diff --git a/Documentation/devicetree/bindings/regulator/qcom,wcn3990-pmu.yaml b/Documentation/devicetree/bindings/regulator/qcom,wcn3990-pmu.yaml new file mode 100644 index 0000000000000..9a7abc878b831 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/qcom,wcn3990-pmu.yaml @@ -0,0 +1,100 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/qcom,wcn3990-pmu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies, Inc. WCN3990 PMU Regulators + +maintainers: + - Bartosz Golaszewski + +description: + The WCN3990 package contains discrete modules for WLAN and Bluetooth. They + are powered by the Power Management Unit (PMU) that takes inputs from the + host and provides LDO outputs. This document describes this module. + +properties: + compatible: + enum: + - qcom,wcn3950-pmu + - qcom,wcn3988-pmu + - qcom,wcn3990-pmu + - qcom,wcn3991-pmu + - qcom,wcn3998-pmu + + vddio-supply: + description: VDD_IO supply regulator handle + + vddxo-supply: + description: VDD_XTAL supply regulator handle + + vddrf-supply: + description: VDD_RF supply regulator handle + + vddch0-supply: + description: chain 0 supply regulator handle + + vddch1-supply: + description: chain 1 supply regulator handle + + swctrl-gpios: + maxItems: 1 + description: GPIO line indicating the state of the clock supply to the BT module + + clocks: + maxItems: 1 + description: Reference clock handle + + regulators: + type: object + description: + LDO outputs of the PMU + + patternProperties: + "^ldo[0-9]$": + $ref: regulator.yaml# + type: object + unevaluatedProperties: false + + additionalProperties: false + +required: + - compatible + - regulators + - vddio-supply + - vddxo-supply + - vddrf-supply + - vddch0-supply + +additionalProperties: false + +examples: + - | + #include + pmu { + compatible = "qcom,wcn3990-pmu"; + + vddio-supply = <&vreg_io>; + vddxo-supply = <&vreg_xo>; + vddrf-supply = <&vreg_rf>; + vddch0-supply = <&vreg_ch0>; + + regulators { + vreg_pmu_io: ldo0 { + regulator-name = "vreg_pmu_io"; + }; + + vreg_pmu_xo: ldo1 { + regulator-name = "vreg_pmu_xo"; + }; + + vreg_pmu_rf: ldo2 { + regulator-name = "vreg_pmu_rf"; + }; + + vreg_pmu_ch0: ldo3 { + regulator-name = "vreg_pmu_ch0"; + }; + }; + }; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 5a8ec61e1c7cc..19861ef5daf51 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -21,7 +21,6 @@ mmc0 = &sdhc_1; mmc1 = &sdhc_2; /* SDC2 SD card slot */ serial0 = &uart0; - serial1 = &uart8; }; chosen { @@ -127,6 +126,7 @@ regulator-always-on; regulator-boot-on; }; + }; &audiocorecc { @@ -673,17 +673,6 @@ }; }; -&uart8 { - status = "okay"; - - bluetooth { - vddio-supply = <&pm4125_l7>; - vddxo-supply = <&pm4125_l13>; - vddrf-supply = <&pm4125_l10>; - vddch0-supply = <&pm4125_l22>; - }; -}; - &usb_1 { dr_mode = "otg"; @@ -720,14 +709,3 @@ qcom,dmic-sample-rate = <4800000>; status = "okay"; }; - -&wifi { - vdd-0.8-cx-mx-supply = <&pm4125_l7>; - vdd-1.8-xo-supply = <&pm4125_l13>; - vdd-1.3-rfa-supply = <&pm4125_l10>; - vdd-3.3-ch0-supply = <&pm4125_l22>; - qcom,calibration-variant = "Shikra_EVK"; - firmware-name = "cq2390"; - - status = "okay"; -}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi index 9c87316444c80..e2bc4d4a2be8d 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi @@ -12,6 +12,10 @@ #include "pm8005.dtsi" / { + aliases { + serial1 = &uart8; + }; + gpio-key { compatible = "gpio-keys"; label = "gpio-keys"; @@ -29,6 +33,42 @@ }; }; + wcn3988-pmu { + compatible = "qcom,wcn3988-pmu"; + + pinctrl-0 = <&sw_ctrl_default>; + pinctrl-names = "default"; + + swctrl-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + + vddio-supply = <&pm4125_l7>; + vddxo-supply = <&pm4125_l13>; + vddrf-supply = <&pm4125_l10>; + vddch0-supply = <&pm4125_l22>; + + regulators { + vreg_pmu_io: ldo0 { + regulator-name = "vreg_pmu_io"; + }; + + vreg_pmu_xo: ldo1 { + regulator-name = "vreg_pmu_xo"; + }; + + vreg_pmu_rf: ldo2 { + regulator-name = "vreg_pmu_rf"; + }; + + vreg_pmu_ch0: ldo3 { + regulator-name = "vreg_pmu_ch0"; + }; + + vreg_pmu_ch1: ldo4 { + regulator-name = "vreg_pmu_ch1"; + }; + }; + }; + pm4125_msm_therm_bridge: pm4125-msm-therm-bridge { compatible = "generic-adc-thermal"; io-channels = <&pm4125_adc ADC5_AMUX_THM3_100K_PU>; @@ -382,3 +422,37 @@ }; }; }; + +&tlmm { + sw_ctrl_default: sw-ctrl-default-state { + pins = "gpio88"; + function = "gpio"; + bias-pull-down; + }; +}; + +&uart8 { + status = "okay"; + + bluetooth { + compatible = "qcom,wcn3988-bt"; + max-speed = <3200000>; + + vddio-supply = <&vreg_pmu_io>; + vddxo-supply = <&vreg_pmu_xo>; + vddrf-supply = <&vreg_pmu_rf>; + vddch0-supply = <&vreg_pmu_ch0>; + }; +}; + +&wifi { + vdd-0.8-cx-mx-supply = <&pm4125_l7>; + vdd-1.8-xo-supply = <&vreg_pmu_xo>; + vdd-1.3-rfa-supply = <&vreg_pmu_rf>; + vdd-3.3-ch0-supply = <&vreg_pmu_ch0>; + + qcom,calibration-variant = "Shikra_EVK"; + firmware-name = "shikra"; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 8c3cd39cbd238..09a1838e7566a 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -20,7 +20,6 @@ mmc0 = &sdhc_1; mmc1 = &sdhc_2; /* SDC2 SD card slot */ serial0 = &uart0; - serial1 = &uart8; }; chosen { @@ -109,6 +108,7 @@ regulator-always-on; regulator-boot-on; }; + }; &audiocorecc { @@ -595,17 +595,6 @@ }; }; -&uart8 { - status = "okay"; - - bluetooth { - vddio-supply = <&pm4125_l7>; - vddxo-supply = <&pm4125_l13>; - vddrf-supply = <&pm4125_l10>; - vddch0-supply = <&pm4125_l22>; - }; -}; - &usb_1 { dr_mode = "otg"; @@ -647,14 +636,3 @@ qcom,dmic-sample-rate = <4800000>; status = "okay"; }; - -&wifi { - vdd-0.8-cx-mx-supply = <&pm4125_l7>; - vdd-1.8-xo-supply = <&pm4125_l13>; - vdd-1.3-rfa-supply = <&pm4125_l10>; - vdd-3.3-ch0-supply = <&pm4125_l22>; - qcom,calibration-variant = "Shikra_EVK"; - firmware-name = "cq2390"; - - status = "okay"; -}; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 98ab8380a3178..eba4fdf7b71f1 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -19,7 +19,6 @@ mmc0 = &sdhc_1; mmc1 = &sdhc_2; /* SDC2 SD card slot */ serial0 = &uart0; - serial1 = &uart8; i2c3 = &i2c3; }; @@ -96,22 +95,6 @@ }; }; - vreg_bt_3p3_dummy: regulator-bt-3p3-dummy { - compatible = "regulator-fixed"; - regulator-name = "bt_3p3_dummy"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vreg_wlan_3p3_dummy: regulator-wlan-3p3-dummy { - compatible = "regulator-fixed"; - regulator-name = "wlan_3p3_dummy"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - vreg_0p9: regulator-0v9 { compatible = "regulator-fixed"; regulator-name = "VREG_0P9"; @@ -131,7 +114,6 @@ regulator-always-on; regulator-boot-on; }; - }; ðernet0 { @@ -595,17 +577,6 @@ }; }; -&uart8 { - status = "okay"; - - bluetooth { - vddio-supply = <&pm8150_s4>; - vddxo-supply = <&pm8150_l12>; - vddrf-supply = <&pm8150_l8>; - vddch0-supply = <&vreg_bt_3p3_dummy>; - }; -}; - &usb_1 { dr_mode = "otg"; @@ -641,17 +612,6 @@ status = "okay"; }; -&wifi { - vdd-0.8-cx-mx-supply = <&pm8150_s4>; - vdd-1.8-xo-supply = <&pm8150_l12>; - vdd-1.3-rfa-supply = <&pm8150_l8>; - vdd-3.3-ch0-supply = <&vreg_wlan_3p3_dummy>; - qcom,calibration-variant = "Shikra_EVK"; - firmware-name = "cq2390"; - - status = "okay"; -}; - &tlmm { pcie_default_state: pcie-default-state { clkreq-pins { diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi index 9ab0b44b00bed..52a3152ae9445 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi @@ -11,6 +11,10 @@ #include "pm8150.dtsi" / { + aliases { + serial1 = &uart8; + }; + gpio-key { compatible = "gpio-keys"; label = "gpio-keys"; @@ -28,6 +32,50 @@ }; }; + vreg_wcn_3p3: regulator-wcn-3p3 { + compatible = "regulator-fixed"; + regulator-name = "wcn_3p3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + wcn3988-pmu { + compatible = "qcom,wcn3988-pmu"; + + pinctrl-0 = <&sw_ctrl_default>; + pinctrl-names = "default"; + + swctrl-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + + vddio-supply = <&pm8150_s4>; + vddxo-supply = <&pm8150_l12>; + vddrf-supply = <&pm8150_l8>; + vddch0-supply = <&vreg_wcn_3p3>; + + regulators { + vreg_pmu_io: ldo0 { + regulator-name = "vreg_pmu_io"; + }; + + vreg_pmu_xo: ldo1 { + regulator-name = "vreg_pmu_xo"; + }; + + vreg_pmu_rf: ldo2 { + regulator-name = "vreg_pmu_rf"; + }; + + vreg_pmu_ch0: ldo3 { + regulator-name = "vreg_pmu_ch0"; + }; + + vreg_pmu_ch1: ldo4 { + regulator-name = "vreg_pmu_ch1"; + }; + }; + }; + thermal-zones { sys-1-thermal { thermal-sensors = <&pm8150_adc_tm 0>; @@ -281,3 +329,37 @@ }; }; }; + +&tlmm { + sw_ctrl_default: sw-ctrl-default-state { + pins = "gpio88"; + function = "gpio"; + bias-pull-down; + }; +}; + +&uart8 { + status = "okay"; + + bluetooth { + compatible = "qcom,wcn3988-bt"; + max-speed = <3200000>; + + vddio-supply = <&vreg_pmu_io>; + vddxo-supply = <&vreg_pmu_xo>; + vddrf-supply = <&vreg_pmu_rf>; + vddch0-supply = <&vreg_pmu_ch0>; + }; +}; + +&wifi { + vdd-0.8-cx-mx-supply = <&pm8150_s4>; + vdd-1.8-xo-supply = <&vreg_pmu_xo>; + vdd-1.3-rfa-supply = <&vreg_pmu_rf>; + vdd-3.3-ch0-supply = <&vreg_pmu_ch0>; + + qcom,calibration-variant = "Shikra_EVK"; + firmware-name = "shikra"; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index fd675f7ec47f3..d4f1831203dc5 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -2433,13 +2433,6 @@ pinctrl-names = "default"; status = "disabled"; - - bluetooth { - compatible = "qcom,wcn3988-bt"; - enable-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; - max-speed = <3200000>; - }; - }; i2c9: i2c@4aa4000 { diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 5d1730e58e47b..67bf0df8bed71 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -2254,6 +2254,18 @@ static void qca_power_shutdown(struct hci_uart *hu) qcadev = serdev_device_get_drvdata(hu->serdev); power = qcadev->bt_power; + switch (soc_type) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + host_set_baudrate(hu, 2400); + qca_send_power_pulse(hu, false); + break; + default: + break; + } + if (power && power->pwrseq) { pwrseq_power_off(power->pwrseq); set_bit(QCA_BT_OFF, &qca->flags); @@ -2265,8 +2277,6 @@ static void qca_power_shutdown(struct hci_uart *hu) case QCA_WCN3990: case QCA_WCN3991: case QCA_WCN3998: - host_set_baudrate(hu, 2400); - qca_send_power_pulse(hu, false); qca_regulator_disable(qcadev); break; @@ -2441,6 +2451,11 @@ static int qca_serdev_probe(struct serdev_device *serdev) switch (qcadev->btsoc_type) { case QCA_QCC2072: + case QCA_WCN3950: + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: case QCA_WCN6855: case QCA_WCN7850: case QCA_WCN6750: @@ -2465,12 +2480,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) else break; } - fallthrough; - case QCA_WCN3950: - case QCA_WCN3988: - case QCA_WCN3990: - case QCA_WCN3991: - case QCA_WCN3998: + qcadev->bt_power->dev = &serdev->dev; err = qca_init_regulators(qcadev->bt_power, data->vregs, data->num_vregs); diff --git a/drivers/power/sequencing/pwrseq-qcom-wcn.c b/drivers/power/sequencing/pwrseq-qcom-wcn.c index 916fa056025f5..7e749ca0c2313 100644 --- a/drivers/power/sequencing/pwrseq-qcom-wcn.c +++ b/drivers/power/sequencing/pwrseq-qcom-wcn.c @@ -23,6 +23,9 @@ struct pwrseq_qcom_wcn_pdata { unsigned int pwup_delay_ms; unsigned int gpio_enable_delay_ms; const struct pwrseq_target_data **targets; + bool bt_gpio_required; /* BT enable path requires a dedicated GPIO */ + bool has_vddio; /* separate VDD IO regulator */ + int (*match)(struct pwrseq_device *pwrseq, struct device *dev); }; struct pwrseq_qcom_wcn_ctx { @@ -30,6 +33,7 @@ struct pwrseq_qcom_wcn_ctx { struct device_node *of_node; const struct pwrseq_qcom_wcn_pdata *pdata; struct regulator_bulk_data *regs; + struct regulator *vddio; struct gpio_desc *bt_gpio; struct gpio_desc *wlan_gpio; struct gpio_desc *xo_clk_gpio; @@ -52,6 +56,26 @@ static void pwrseq_qcom_wcn_ensure_gpio_delay(struct pwrseq_qcom_wcn_ctx *ctx) msleep(ctx->pdata->gpio_enable_delay_ms - diff_msecs); } +static int pwrseq_qcom_wcn_vddio_enable(struct pwrseq_device *pwrseq) +{ + struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); + + return regulator_enable(ctx->vddio); +} + +static int pwrseq_qcom_wcn_vddio_disable(struct pwrseq_device *pwrseq) +{ + struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); + + return regulator_disable(ctx->vddio); +} + +static const struct pwrseq_unit_data pwrseq_qcom_wcn_vddio_unit_data = { + .name = "vddio-enable", + .enable = pwrseq_qcom_wcn_vddio_enable, + .disable = pwrseq_qcom_wcn_vddio_disable, +}; + static int pwrseq_qcom_wcn_vregs_enable(struct pwrseq_device *pwrseq) { struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); @@ -94,6 +118,19 @@ static const struct pwrseq_unit_data pwrseq_qcom_wcn_clk_unit_data = { .disable = pwrseq_qcom_wcn_clk_disable, }; +static const struct pwrseq_unit_data *pwrseq_qcom_wcn3990_unit_deps[] = { + &pwrseq_qcom_wcn_vddio_unit_data, + &pwrseq_qcom_wcn_vregs_unit_data, + NULL, +}; + +static const struct pwrseq_unit_data pwrseq_qcom_wcn3990_unit_data = { + .name = "clock-enable", + .deps = pwrseq_qcom_wcn3990_unit_deps, + .enable = pwrseq_qcom_wcn_clk_enable, + .disable = pwrseq_qcom_wcn_clk_disable, +}; + static const struct pwrseq_unit_data *pwrseq_qcom_wcn_unit_deps[] = { &pwrseq_qcom_wcn_vregs_unit_data, &pwrseq_qcom_wcn_clk_unit_data, @@ -229,6 +266,17 @@ static const struct pwrseq_target_data pwrseq_qcom_wcn_wlan_target_data = { .post_enable = pwrseq_qcom_wcn_pwup_delay, }; +/* There are no separate BT and WLAN enablement pins */ +static const struct pwrseq_target_data pwrseq_qcom_wcn3990_bt_target_data = { + .name = "bluetooth", + .unit = &pwrseq_qcom_wcn3990_unit_data, +}; + +static const struct pwrseq_target_data pwrseq_qcom_wcn3990_wlan_target_data = { + .name = "wlan", + .unit = &pwrseq_qcom_wcn3990_unit_data, +}; + static const struct pwrseq_target_data pwrseq_qcom_wcn6855_bt_target_data = { .name = "bluetooth", .unit = &pwrseq_qcom_wcn6855_bt_unit_data, @@ -247,6 +295,12 @@ static const struct pwrseq_target_data *pwrseq_qcom_wcn_targets[] = { NULL }; +static const struct pwrseq_target_data *pwrseq_qcom_wcn3990_targets[] = { + &pwrseq_qcom_wcn3990_bt_target_data, + &pwrseq_qcom_wcn3990_wlan_target_data, + NULL +}; + static const struct pwrseq_target_data *pwrseq_qcom_wcn6855_targets[] = { &pwrseq_qcom_wcn6855_bt_target_data, &pwrseq_qcom_wcn6855_wlan_target_data, @@ -272,6 +326,26 @@ static const struct pwrseq_qcom_wcn_pdata pwrseq_qca6390_of_data = { .targets = pwrseq_qcom_wcn_targets, }; +static const char *const pwrseq_wcn3990_vregs[] = { + /* vddio is handled separately */ + "vddxo", + "vddrf", + "vddch0", + "vddch1", +}; + +static int pwrseq_qcom_wcn3990_match(struct pwrseq_device *pwrseq, + struct device *dev); + +static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn3990_of_data = { + .vregs = pwrseq_wcn3990_vregs, + .num_vregs = ARRAY_SIZE(pwrseq_wcn3990_vregs), + .pwup_delay_ms = 50, + .targets = pwrseq_qcom_wcn3990_targets, + .has_vddio = true, + .match = pwrseq_qcom_wcn3990_match, +}; + static const char *const pwrseq_wcn6750_vregs[] = { "vddaon", "vddasd", @@ -309,6 +383,7 @@ static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn6855_of_data = { .pwup_delay_ms = 50, .gpio_enable_delay_ms = 5, .targets = pwrseq_qcom_wcn6855_targets, + .bt_gpio_required = true, }; static const char *const pwrseq_wcn7850_vregs[] = { @@ -326,10 +401,12 @@ static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn7850_of_data = { .num_vregs = ARRAY_SIZE(pwrseq_wcn7850_vregs), .pwup_delay_ms = 50, .targets = pwrseq_qcom_wcn_targets, + .bt_gpio_required = true, }; -static int pwrseq_qcom_wcn_match(struct pwrseq_device *pwrseq, - struct device *dev) +static int pwrseq_qcom_wcn_match_regulator(struct pwrseq_device *pwrseq, + struct device *dev, + const char *name) { struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); struct device_node *dev_node = dev->of_node; @@ -340,11 +417,11 @@ static int pwrseq_qcom_wcn_match(struct pwrseq_device *pwrseq, * 'vddaon-supply' property and whether it leads us to the right * device. */ - if (!of_property_present(dev_node, "vddaon-supply")) + if (!of_property_present(dev_node, name)) return PWRSEQ_NO_MATCH; struct device_node *reg_node __free(device_node) = - of_parse_phandle(dev_node, "vddaon-supply", 0); + of_parse_phandle(dev_node, name, 0); if (!reg_node) return PWRSEQ_NO_MATCH; @@ -358,22 +435,45 @@ static int pwrseq_qcom_wcn_match(struct pwrseq_device *pwrseq, return PWRSEQ_NO_MATCH; /* - * If this is a Bluetooth consumer device but the bt-enable GPIO is not - * configured in the power sequencer (e.g. BT_EN is tied high via a - * hardware pull-up and therefore absent from the DT), don't match. - * The consumer driver will fall back to its legacy power control path - * and correctly set power_ctrl_enabled to false. + * If this chip requires a dedicated BT enable GPIO (bt_gpio_required) + * but the bt-enable GPIO is not configured in the power sequencer + * (e.g. BT_EN is tied high via a hardware pull-up and therefore absent + * from the DT), don't match. The consumer driver will fall back to its + * legacy power control path and correctly set power_ctrl_enabled to + * false. Chips like WCN3990 have no separate BT/WLAN enable pins by + * design, so the flag is left unset for them and matching proceeds. * * BT device nodes are conventionally named "bluetooth" in the DT, * so use of_node_name_eq() as a generic check rather than enumerating * specific compatible strings. */ - if (!ctx->bt_gpio && of_node_name_eq(dev_node, "bluetooth")) + if (ctx->pdata->bt_gpio_required && !ctx->bt_gpio && + of_node_name_eq(dev_node, "bluetooth")) return PWRSEQ_NO_MATCH; return PWRSEQ_MATCH_OK; } +static int pwrseq_qcom_wcn_match(struct pwrseq_device *pwrseq, + struct device *dev) +{ + return pwrseq_qcom_wcn_match_regulator(pwrseq, dev, "vddaon-supply"); +} + +static int pwrseq_qcom_wcn3990_match(struct pwrseq_device *pwrseq, + struct device *dev) +{ + int ret; + + /* BT device */ + ret = pwrseq_qcom_wcn_match_regulator(pwrseq, dev, "vddio-supply"); + if (ret == PWRSEQ_MATCH_OK) + return ret; + + /* WiFi device match */ + return pwrseq_qcom_wcn_match_regulator(pwrseq, dev, "vdd-1.8-xo-supply"); +} + static int pwrseq_qcom_wcn_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -405,6 +505,12 @@ static int pwrseq_qcom_wcn_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "Failed to get all regulators\n"); + if (ctx->pdata->has_vddio) { + ctx->vddio = devm_regulator_get(dev, "vddio"); + if (IS_ERR(ctx->vddio)) + return dev_err_probe(dev, ret, "Failed to get VDDIO\n"); + } + ctx->bt_gpio = devm_gpiod_get_optional(dev, "bt-enable", GPIOD_OUT_LOW); if (IS_ERR(ctx->bt_gpio)) return dev_err_probe(dev, PTR_ERR(ctx->bt_gpio), @@ -446,7 +552,7 @@ static int pwrseq_qcom_wcn_probe(struct platform_device *pdev) config.parent = dev; config.owner = THIS_MODULE; config.drvdata = ctx; - config.match = pwrseq_qcom_wcn_match; + config.match = ctx->pdata->match ? : pwrseq_qcom_wcn_match; config.targets = ctx->pdata->targets; ctx->pwrseq = devm_pwrseq_device_register(dev, &config); @@ -458,6 +564,26 @@ static int pwrseq_qcom_wcn_probe(struct platform_device *pdev) } static const struct of_device_id pwrseq_qcom_wcn_of_match[] = { + { + .compatible = "qcom,wcn3950-pmu", + .data = &pwrseq_wcn3990_of_data, + }, + { + .compatible = "qcom,wcn3988-pmu", + .data = &pwrseq_wcn3990_of_data, + }, + { + .compatible = "qcom,wcn3990-pmu", + .data = &pwrseq_wcn3990_of_data, + }, + { + .compatible = "qcom,wcn3991-pmu", + .data = &pwrseq_wcn3990_of_data, + }, + { + .compatible = "qcom,wcn3998-pmu", + .data = &pwrseq_wcn3990_of_data, + }, { .compatible = "qcom,qca6390-pmu", .data = &pwrseq_qca6390_of_data,