[PATCH v3 05/11] power: sequencing: qcom-wcn: Report power controllability
From: Loic Poulain
Date: Fri Jul 10 2026 - 05:59:30 EST
The "bluetooth" and "wlan" targets drive the BT_EN and WLAN_EN GPIOs to
gate the respective functions. These GPIOs are optional, on some boards
they are hardwired to an always-on pull-up and not routed to a host GPIO.
In that case the corresponding enable/disable callbacks are no-ops, so the
host cannot gate that function's power on its own.
Implement the per-unit .is_controllable() callback on the bluetooth-enable
and wlan-enable units so that consumers can query this via the pwrseq API.
Signed-off-by: Loic Poulain <loic.poulain@xxxxxxxxxxxxxxxx>
---
drivers/power/sequencing/pwrseq-qcom-wcn.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/power/sequencing/pwrseq-qcom-wcn.c b/drivers/power/sequencing/pwrseq-qcom-wcn.c
index b55b4317e21b626e050e022648147770ca7f386e..d5c9b734b0538e209734e15980ff2877ef5a614d 100644
--- a/drivers/power/sequencing/pwrseq-qcom-wcn.c
+++ b/drivers/power/sequencing/pwrseq-qcom-wcn.c
@@ -184,11 +184,25 @@ static int pwrseq_qcom_wcn_bt_disable(struct pwrseq_device *pwrseq)
return 0;
}
+static bool pwrseq_qcom_wcn_bt_is_controllable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ /*
+ * The Bluetooth enable is driven through the BT_EN GPIO. When it is not
+ * wired up (e.g. hardwired to an always-on pull-up), the enable/disable
+ * callbacks are no-ops, so the host cannot gate the Bluetooth function
+ * on its own.
+ */
+ return !!ctx->bt_gpio;
+}
+
static const struct pwrseq_unit_data pwrseq_qcom_wcn_bt_unit_data = {
.name = "bluetooth-enable",
.deps = pwrseq_qcom_wcn_unit_deps,
.enable = pwrseq_qcom_wcn_bt_enable,
.disable = pwrseq_qcom_wcn_bt_disable,
+ .is_controllable = pwrseq_qcom_wcn_bt_is_controllable,
};
static const struct pwrseq_unit_data pwrseq_qcom_wcn6855_bt_unit_data = {
@@ -196,6 +210,7 @@ static const struct pwrseq_unit_data pwrseq_qcom_wcn6855_bt_unit_data = {
.deps = pwrseq_qcom_wcn6855_unit_deps,
.enable = pwrseq_qcom_wcn_bt_enable,
.disable = pwrseq_qcom_wcn_bt_disable,
+ .is_controllable = pwrseq_qcom_wcn_bt_is_controllable,
};
static int pwrseq_qcom_wcn_wlan_enable(struct pwrseq_device *pwrseq)
@@ -218,11 +233,25 @@ static int pwrseq_qcom_wcn_wlan_disable(struct pwrseq_device *pwrseq)
return 0;
}
+static bool pwrseq_qcom_wcn_wlan_is_controllable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ /*
+ * The WLAN enable is driven through the WLAN_EN GPIO. When it is not
+ * wired up (e.g. hardwired to an always-on pull-up), the enable/disable
+ * callbacks are no-ops, so the host cannot gate the WLAN function on
+ * its own.
+ */
+ return !!ctx->wlan_gpio;
+}
+
static const struct pwrseq_unit_data pwrseq_qcom_wcn_wlan_unit_data = {
.name = "wlan-enable",
.deps = pwrseq_qcom_wcn_unit_deps,
.enable = pwrseq_qcom_wcn_wlan_enable,
.disable = pwrseq_qcom_wcn_wlan_disable,
+ .is_controllable = pwrseq_qcom_wcn_wlan_is_controllable,
};
static const struct pwrseq_unit_data pwrseq_qcom_wcn6855_wlan_unit_data = {
@@ -230,6 +259,7 @@ static const struct pwrseq_unit_data pwrseq_qcom_wcn6855_wlan_unit_data = {
.deps = pwrseq_qcom_wcn6855_unit_deps,
.enable = pwrseq_qcom_wcn_wlan_enable,
.disable = pwrseq_qcom_wcn_wlan_disable,
+ .is_controllable = pwrseq_qcom_wcn_wlan_is_controllable,
};
static int pwrseq_qcom_wcn_pwup_delay(struct pwrseq_device *pwrseq)
--
2.34.1