Loading Documentation/devicetree/bindings/arm/msm/sdx-ext-ipc.txt +7 −0 Original line number Diff line number Diff line Loading @@ -18,10 +18,17 @@ Optional named gpio properties: - qcom,default-policy-nop: Set default policy from PANIC to NOP. - qcom,wakeup-gpio-out: gpio to wakeup remote AP or modem. - qcom,wakeup-gpio-in: input gpio to receive wakeup signal from remote AP or modem. Example: sdx_ext_ipc: qcom,sdx_ext_ipc { compatible = "qcom,sdx-ext-ipc"; qcom,status-in-gpio = <&tlmm 64 0x00>; qcom,status-out-gpio = <&tlmm 63 0x00>; qcom,status-out2-gpio = <&tlmm 66 0x00>; qcom,wakeup-gpio-in = <&tlmm 67 0x00>; qcom,wakeup-gpio-out = <&tlmm 68 0x00>; }; arch/arm64/boot/dts/qcom/sa2150p-ccard.dtsi +22 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,19 @@ output-high; }; }; wakeup_gpio_default: wakeup_gpio_default { mux { pins = "gpio79"; function = "gpio"; }; config { pins = "gpio79"; drive-strength = <2>; bias-pull-down; }; }; }; &pcie0_perst_default { Loading Loading @@ -167,6 +180,15 @@ }; }; }; sdx_ext_ipc: qcom,sdx_ext_ipc { compatible = "qcom,sdx-ext-ipc"; qcom,wakeup-gpio-in = <&tlmm 14 0x00>; qcom,wakeup-gpio-out = <&tlmm 79 0x00>; pinctrl-names = "default"; pinctrl-0 = <&wakeup_gpio_default>; }; }; &thermal_zones { Loading arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi +13 −0 Original line number Diff line number Diff line Loading @@ -1685,5 +1685,18 @@ bias-pull-down; }; }; wakeup_gpio_default: wakeup_gpio_default { mux { pins = "gpio22"; function = "gpio"; }; config { pins = "gpio22"; drive-strength = <2>; bias-pull-down; }; }; }; }; arch/arm64/boot/dts/qcom/sdxprairie.dtsi +4 −0 Original line number Diff line number Diff line Loading @@ -1597,6 +1597,10 @@ qcom,status-in-gpio = <&tlmm 64 0x00>; qcom,status-out-gpio = <&tlmm 63 0x00>; qcom,status-out2-gpio = <&tlmm 66 0x00>; qcom,wakeup-gpio-in = <&tlmm 87 0x00>; qcom,wakeup-gpio-out = <&tlmm 22 0x00>; pinctrl-names = "default"; pinctrl-0 = <&wakeup_gpio_default>; status = "disabled"; }; }; Loading drivers/soc/qcom/sdx_ext_ipc.c +116 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ #include <linux/platform_device.h> #include <linux/module.h> #include <linux/interrupt.h> #include <soc/qcom/sb_notification.h> enum subsys_policies { SUBSYS_PANIC = 0, Loading @@ -33,6 +33,8 @@ enum gpios { STATUS_IN = 0, STATUS_OUT, STATUS_OUT2, WAKEUP_OUT, WAKEUP_IN, NUM_GPIOS, }; Loading @@ -40,16 +42,20 @@ static const char * const gpio_map[] = { [STATUS_IN] = "qcom,status-in-gpio", [STATUS_OUT] = "qcom,status-out-gpio", [STATUS_OUT2] = "qcom,status-out2-gpio", [WAKEUP_OUT] = "qcom,wakeup-gpio-out", [WAKEUP_IN] = "qcom,wakeup-gpio-in", }; struct gpio_cntrl { unsigned int gpios[NUM_GPIOS]; int status_irq; int wakeup_irq; int policy; struct device *dev; struct mutex policy_lock; struct mutex e911_lock; struct notifier_block panic_blk; struct notifier_block sideband_nb; }; static ssize_t policy_show(struct device *dev, struct device_attribute *attr, Loading Loading @@ -128,6 +134,26 @@ static ssize_t e911_store(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RW(e911); static int sideband_notify(struct notifier_block *nb, unsigned long action, void *dev) { struct gpio_cntrl *mdm = container_of(nb, struct gpio_cntrl, sideband_nb); switch (action) { case EVT_WAKE_UP: gpio_set_value(mdm->gpios[WAKEUP_OUT], 1); usleep_range(10000, 20000); gpio_set_value(mdm->gpios[WAKEUP_OUT], 0); break; default: dev_info(mdm->dev, "Invalid action passed %d\n", action); } return NOTIFY_OK; } static irqreturn_t ap_status_change(int irq, void *dev_id) { struct gpio_cntrl *mdm = dev_id; Loading @@ -150,6 +176,12 @@ static irqreturn_t ap_status_change(int irq, void *dev_id) return IRQ_HANDLED; } static irqreturn_t sdx_ext_ipc_wakeup_irq(int irq, void *dev_id) { pr_info("%s: Received\n", __func__); return IRQ_HANDLED; } static void remove_ipc(struct gpio_cntrl *mdm) { int i; Loading Loading @@ -210,6 +242,35 @@ static int setup_ipc(struct gpio_cntrl *mdm) } else dev_info(mdm->dev, "STATUS_OUT2 not used\n"); if (mdm->gpios[WAKEUP_OUT] >= 0) { ret = gpio_request(mdm->gpios[WAKEUP_OUT], "WAKEUP_OUT"); if (ret) { dev_err(mdm->dev, "Failed to configure WAKEUP_OUT gpio\n"); return ret; } gpio_direction_output(mdm->gpios[WAKEUP_OUT], 0); } else dev_info(mdm->dev, "WAKEUP_OUT not used\n"); if (mdm->gpios[WAKEUP_IN] >= 0) { ret = gpio_request(mdm->gpios[WAKEUP_IN], "WAKEUP_IN"); if (ret) { dev_warn(mdm->dev, "Failed to configure WAKEUP_IN gpio\n"); return ret; } gpio_direction_input(mdm->gpios[WAKEUP_IN]); irq = gpio_to_irq(mdm->gpios[WAKEUP_IN]); if (irq < 0) { dev_err(mdm->dev, "bad AP2MDM_STATUS IRQ resource\n"); return irq; } mdm->wakeup_irq = irq; } else dev_info(mdm->dev, "WAKEUP_IN not used\n"); return 0; } Loading Loading @@ -283,6 +344,32 @@ static int sdx_ext_ipc_probe(struct platform_device *pdev) } irq_set_irq_wake(mdm->status_irq, 1); } if (mdm->gpios[WAKEUP_IN] >= 0) { ret = devm_request_threaded_irq(mdm->dev, mdm->wakeup_irq, NULL, sdx_ext_ipc_wakeup_irq, IRQF_TRIGGER_FALLING, "sdx_ext_ipc_wakeup", mdm); if (ret < 0) { dev_err(mdm->dev, "%s: WAKEUP_IN IRQ#%d request failed,\n", __func__, mdm->status_irq); goto irq_fail; } disable_irq(mdm->wakeup_irq); } if (mdm->gpios[WAKEUP_OUT] >= 0) { mdm->sideband_nb.notifier_call = sideband_notify; ret = sb_register_evt_listener(&mdm->sideband_nb); if (ret) { dev_err(mdm->dev, "%s: sb_register_evt_listener failed!\n", __func__); goto irq_fail; } } return 0; irq_fail: Loading Loading @@ -313,6 +400,31 @@ static int sdx_ext_ipc_remove(struct platform_device *pdev) return 0; } #ifdef CONFIG_PM static int sdx_ext_ipc_suspend(struct device *dev) { struct gpio_cntrl *mdm = dev_get_drvdata(dev); if (mdm->gpios[WAKEUP_IN] >= 0) enable_irq_wake(mdm->wakeup_irq); return 0; } static int sdx_ext_ipc_resume(struct device *dev) { struct gpio_cntrl *mdm = dev_get_drvdata(dev); if (mdm->gpios[WAKEUP_IN] >= 0) disable_irq_wake(mdm->wakeup_irq); return 0; } static const struct dev_pm_ops sdx_ext_ipc_pm_ops = { .suspend = sdx_ext_ipc_suspend, .resume = sdx_ext_ipc_resume, }; #endif static const struct of_device_id sdx_ext_ipc_of_match[] = { { .compatible = "qcom,sdx-ext-ipc"}, { .compatible = "qcom,sa515m-ccard"}, Loading @@ -326,6 +438,9 @@ static struct platform_driver sdx_ext_ipc_driver = { .name = "sdx-ext-ipc", .owner = THIS_MODULE, .of_match_table = sdx_ext_ipc_of_match, #ifdef CONFIG_PM .pm = &sdx_ext_ipc_pm_ops, #endif }, }; Loading Loading
Documentation/devicetree/bindings/arm/msm/sdx-ext-ipc.txt +7 −0 Original line number Diff line number Diff line Loading @@ -18,10 +18,17 @@ Optional named gpio properties: - qcom,default-policy-nop: Set default policy from PANIC to NOP. - qcom,wakeup-gpio-out: gpio to wakeup remote AP or modem. - qcom,wakeup-gpio-in: input gpio to receive wakeup signal from remote AP or modem. Example: sdx_ext_ipc: qcom,sdx_ext_ipc { compatible = "qcom,sdx-ext-ipc"; qcom,status-in-gpio = <&tlmm 64 0x00>; qcom,status-out-gpio = <&tlmm 63 0x00>; qcom,status-out2-gpio = <&tlmm 66 0x00>; qcom,wakeup-gpio-in = <&tlmm 67 0x00>; qcom,wakeup-gpio-out = <&tlmm 68 0x00>; };
arch/arm64/boot/dts/qcom/sa2150p-ccard.dtsi +22 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,19 @@ output-high; }; }; wakeup_gpio_default: wakeup_gpio_default { mux { pins = "gpio79"; function = "gpio"; }; config { pins = "gpio79"; drive-strength = <2>; bias-pull-down; }; }; }; &pcie0_perst_default { Loading Loading @@ -167,6 +180,15 @@ }; }; }; sdx_ext_ipc: qcom,sdx_ext_ipc { compatible = "qcom,sdx-ext-ipc"; qcom,wakeup-gpio-in = <&tlmm 14 0x00>; qcom,wakeup-gpio-out = <&tlmm 79 0x00>; pinctrl-names = "default"; pinctrl-0 = <&wakeup_gpio_default>; }; }; &thermal_zones { Loading
arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi +13 −0 Original line number Diff line number Diff line Loading @@ -1685,5 +1685,18 @@ bias-pull-down; }; }; wakeup_gpio_default: wakeup_gpio_default { mux { pins = "gpio22"; function = "gpio"; }; config { pins = "gpio22"; drive-strength = <2>; bias-pull-down; }; }; }; };
arch/arm64/boot/dts/qcom/sdxprairie.dtsi +4 −0 Original line number Diff line number Diff line Loading @@ -1597,6 +1597,10 @@ qcom,status-in-gpio = <&tlmm 64 0x00>; qcom,status-out-gpio = <&tlmm 63 0x00>; qcom,status-out2-gpio = <&tlmm 66 0x00>; qcom,wakeup-gpio-in = <&tlmm 87 0x00>; qcom,wakeup-gpio-out = <&tlmm 22 0x00>; pinctrl-names = "default"; pinctrl-0 = <&wakeup_gpio_default>; status = "disabled"; }; }; Loading
drivers/soc/qcom/sdx_ext_ipc.c +116 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ #include <linux/platform_device.h> #include <linux/module.h> #include <linux/interrupt.h> #include <soc/qcom/sb_notification.h> enum subsys_policies { SUBSYS_PANIC = 0, Loading @@ -33,6 +33,8 @@ enum gpios { STATUS_IN = 0, STATUS_OUT, STATUS_OUT2, WAKEUP_OUT, WAKEUP_IN, NUM_GPIOS, }; Loading @@ -40,16 +42,20 @@ static const char * const gpio_map[] = { [STATUS_IN] = "qcom,status-in-gpio", [STATUS_OUT] = "qcom,status-out-gpio", [STATUS_OUT2] = "qcom,status-out2-gpio", [WAKEUP_OUT] = "qcom,wakeup-gpio-out", [WAKEUP_IN] = "qcom,wakeup-gpio-in", }; struct gpio_cntrl { unsigned int gpios[NUM_GPIOS]; int status_irq; int wakeup_irq; int policy; struct device *dev; struct mutex policy_lock; struct mutex e911_lock; struct notifier_block panic_blk; struct notifier_block sideband_nb; }; static ssize_t policy_show(struct device *dev, struct device_attribute *attr, Loading Loading @@ -128,6 +134,26 @@ static ssize_t e911_store(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RW(e911); static int sideband_notify(struct notifier_block *nb, unsigned long action, void *dev) { struct gpio_cntrl *mdm = container_of(nb, struct gpio_cntrl, sideband_nb); switch (action) { case EVT_WAKE_UP: gpio_set_value(mdm->gpios[WAKEUP_OUT], 1); usleep_range(10000, 20000); gpio_set_value(mdm->gpios[WAKEUP_OUT], 0); break; default: dev_info(mdm->dev, "Invalid action passed %d\n", action); } return NOTIFY_OK; } static irqreturn_t ap_status_change(int irq, void *dev_id) { struct gpio_cntrl *mdm = dev_id; Loading @@ -150,6 +176,12 @@ static irqreturn_t ap_status_change(int irq, void *dev_id) return IRQ_HANDLED; } static irqreturn_t sdx_ext_ipc_wakeup_irq(int irq, void *dev_id) { pr_info("%s: Received\n", __func__); return IRQ_HANDLED; } static void remove_ipc(struct gpio_cntrl *mdm) { int i; Loading Loading @@ -210,6 +242,35 @@ static int setup_ipc(struct gpio_cntrl *mdm) } else dev_info(mdm->dev, "STATUS_OUT2 not used\n"); if (mdm->gpios[WAKEUP_OUT] >= 0) { ret = gpio_request(mdm->gpios[WAKEUP_OUT], "WAKEUP_OUT"); if (ret) { dev_err(mdm->dev, "Failed to configure WAKEUP_OUT gpio\n"); return ret; } gpio_direction_output(mdm->gpios[WAKEUP_OUT], 0); } else dev_info(mdm->dev, "WAKEUP_OUT not used\n"); if (mdm->gpios[WAKEUP_IN] >= 0) { ret = gpio_request(mdm->gpios[WAKEUP_IN], "WAKEUP_IN"); if (ret) { dev_warn(mdm->dev, "Failed to configure WAKEUP_IN gpio\n"); return ret; } gpio_direction_input(mdm->gpios[WAKEUP_IN]); irq = gpio_to_irq(mdm->gpios[WAKEUP_IN]); if (irq < 0) { dev_err(mdm->dev, "bad AP2MDM_STATUS IRQ resource\n"); return irq; } mdm->wakeup_irq = irq; } else dev_info(mdm->dev, "WAKEUP_IN not used\n"); return 0; } Loading Loading @@ -283,6 +344,32 @@ static int sdx_ext_ipc_probe(struct platform_device *pdev) } irq_set_irq_wake(mdm->status_irq, 1); } if (mdm->gpios[WAKEUP_IN] >= 0) { ret = devm_request_threaded_irq(mdm->dev, mdm->wakeup_irq, NULL, sdx_ext_ipc_wakeup_irq, IRQF_TRIGGER_FALLING, "sdx_ext_ipc_wakeup", mdm); if (ret < 0) { dev_err(mdm->dev, "%s: WAKEUP_IN IRQ#%d request failed,\n", __func__, mdm->status_irq); goto irq_fail; } disable_irq(mdm->wakeup_irq); } if (mdm->gpios[WAKEUP_OUT] >= 0) { mdm->sideband_nb.notifier_call = sideband_notify; ret = sb_register_evt_listener(&mdm->sideband_nb); if (ret) { dev_err(mdm->dev, "%s: sb_register_evt_listener failed!\n", __func__); goto irq_fail; } } return 0; irq_fail: Loading Loading @@ -313,6 +400,31 @@ static int sdx_ext_ipc_remove(struct platform_device *pdev) return 0; } #ifdef CONFIG_PM static int sdx_ext_ipc_suspend(struct device *dev) { struct gpio_cntrl *mdm = dev_get_drvdata(dev); if (mdm->gpios[WAKEUP_IN] >= 0) enable_irq_wake(mdm->wakeup_irq); return 0; } static int sdx_ext_ipc_resume(struct device *dev) { struct gpio_cntrl *mdm = dev_get_drvdata(dev); if (mdm->gpios[WAKEUP_IN] >= 0) disable_irq_wake(mdm->wakeup_irq); return 0; } static const struct dev_pm_ops sdx_ext_ipc_pm_ops = { .suspend = sdx_ext_ipc_suspend, .resume = sdx_ext_ipc_resume, }; #endif static const struct of_device_id sdx_ext_ipc_of_match[] = { { .compatible = "qcom,sdx-ext-ipc"}, { .compatible = "qcom,sa515m-ccard"}, Loading @@ -326,6 +438,9 @@ static struct platform_driver sdx_ext_ipc_driver = { .name = "sdx-ext-ipc", .owner = THIS_MODULE, .of_match_table = sdx_ext_ipc_of_match, #ifdef CONFIG_PM .pm = &sdx_ext_ipc_pm_ops, #endif }, }; Loading