diff --git a/Documentation/devicetree/bindings/regulator/qcom,wcn3990-pmu.yaml b/Documentation/devicetree/bindings/regulator/qcom,wcn3990-pmu.yaml index 9a7abc878b831..00cd8b6c27d97 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,wcn3990-pmu.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,wcn3990-pmu.yaml @@ -42,6 +42,20 @@ properties: maxItems: 1 description: GPIO line indicating the state of the clock supply to the BT module + interrupts: + maxItems: 1 + description: SW_CTRL wake interrupt, asserted when the WCN chip is active + + interrupt-names: + const: wakeup + + wakeup-source: + type: boolean + description: + Mark the PMU as a wakeup source. Requires the "wakeup" interrupt to be + present. When set, the SW_CTRL IRQ is used to wake the application + processor from system suspend. + clocks: maxItems: 1 description: Reference clock handle @@ -67,6 +81,14 @@ required: - vddrf-supply - vddch0-supply +dependencies: + wakeup-source: + required: + - interrupt-names + anyOf: + - required: [interrupts] + - required: [interrupts-extended] + additionalProperties: false examples: diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 142c712dfebd5..dc205537c7989 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -9,6 +9,7 @@ #include "shikra-cqm-som.dtsi" #include "shikra-evk.dtsi" #include +#include #include / { @@ -140,6 +141,9 @@ vddch0-supply = <&pm4125_l22>; swctrl-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + interrupts-extended = <&tlmm 88 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "wakeup"; + wakeup-source; regulators { vreg_pmu_io: ldo0 { diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index e74e8ef0dfb6f..29817c3b314db 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -8,6 +8,7 @@ #include "shikra-cqm-som.dtsi" #include "shikra-evk.dtsi" #include +#include #include / { @@ -122,6 +123,9 @@ vddch0-supply = <&pm4125_l22>; swctrl-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + interrupts-extended = <&tlmm 88 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "wakeup"; + wakeup-source; regulators { vreg_pmu_io: ldo0 { diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index ed43a2c055e29..2f17f3535fe95 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -176,6 +176,9 @@ vddch0-supply = <&vreg_wcn_3p3>; swctrl-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + interrupts-extended = <&tlmm 88 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "wakeup"; + wakeup-source; regulators { vreg_pmu_io: ldo0 { diff --git a/drivers/power/sequencing/pwrseq-qcom-wcn.c b/drivers/power/sequencing/pwrseq-qcom-wcn.c index c5071708e85ea..c1090448c024c 100644 --- a/drivers/power/sequencing/pwrseq-qcom-wcn.c +++ b/drivers/power/sequencing/pwrseq-qcom-wcn.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -454,11 +456,17 @@ static int pwrseq_qcom_wcn3990_match(struct pwrseq_device *pwrseq, return pwrseq_qcom_wcn_match_regulator(pwrseq, dev, "vdd-1.8-xo-supply"); } +static void pwrseq_qcom_wcn_clear_wake_irq(void *data) +{ + dev_pm_clear_wake_irq(data); +} + static int pwrseq_qcom_wcn_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct pwrseq_qcom_wcn_ctx *ctx; struct pwrseq_config config; + int wake_irq; int i, ret; ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); @@ -496,6 +504,28 @@ static int pwrseq_qcom_wcn_probe(struct platform_device *pdev) return dev_err_probe(dev, PTR_ERR(ctx->bt_gpio), "Failed to get the Bluetooth enable GPIO\n"); + if (of_property_read_bool(dev->of_node, "wakeup-source")) { + wake_irq = platform_get_irq_byname(pdev, "wakeup"); + if (wake_irq < 0) + return dev_err_probe(dev, wake_irq, + "Failed to get the SW_CTRL wake IRQ\n"); + + ret = devm_device_init_wakeup(dev); + if (ret) + return dev_err_probe(dev, ret, + "Failed to enable wakeup\n"); + + ret = dev_pm_set_dedicated_wake_irq(dev, wake_irq); + if (ret) + return dev_err_probe(dev, ret, + "Failed to set the SW_CTRL wake IRQ\n"); + + ret = devm_add_action_or_reset(dev, + pwrseq_qcom_wcn_clear_wake_irq, dev); + if (ret) + return ret; + } + /* * FIXME: This should actually be GPIOD_OUT_LOW, but doing so would * cause the WLAN power to be toggled, resulting in PCIe link down.