[PATCH v4 05/11] power: sequencing: qcom-wcn: Report power controllability
From: Loic Poulain
Date: Thu Jul 16 2026 - 12:55:05 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
consumer cannot gate or reset that function on its own.
Implement the .is_controllable() callback on the "bluetooth" and "wlan"
targets 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..19b51c94653b7f8e7e1f5a2fe906c0cc1cd46aa8 100644
--- a/drivers/power/sequencing/pwrseq-qcom-wcn.c
+++ b/drivers/power/sequencing/pwrseq-qcom-wcn.c
@@ -184,6 +184,19 @@ 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,
@@ -218,6 +231,19 @@ 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,
@@ -258,12 +284,14 @@ static const struct pwrseq_target_data pwrseq_qcom_wcn_bt_target_data = {
.name = "bluetooth",
.unit = &pwrseq_qcom_wcn_bt_unit_data,
.post_enable = pwrseq_qcom_wcn_pwup_delay,
+ .is_controllable = pwrseq_qcom_wcn_bt_is_controllable,
};
static const struct pwrseq_target_data pwrseq_qcom_wcn_wlan_target_data = {
.name = "wlan",
.unit = &pwrseq_qcom_wcn_wlan_unit_data,
.post_enable = pwrseq_qcom_wcn_pwup_delay,
+ .is_controllable = pwrseq_qcom_wcn_wlan_is_controllable,
};
/* There are no separate BT and WLAN enablement pins */
@@ -281,12 +309,14 @@ static const struct pwrseq_target_data pwrseq_qcom_wcn6855_bt_target_data = {
.name = "bluetooth",
.unit = &pwrseq_qcom_wcn6855_bt_unit_data,
.post_enable = pwrseq_qcom_wcn6855_xo_clk_deassert,
+ .is_controllable = pwrseq_qcom_wcn_bt_is_controllable,
};
static const struct pwrseq_target_data pwrseq_qcom_wcn6855_wlan_target_data = {
.name = "wlan",
.unit = &pwrseq_qcom_wcn6855_wlan_unit_data,
.post_enable = pwrseq_qcom_wcn6855_xo_clk_deassert,
+ .is_controllable = pwrseq_qcom_wcn_wlan_is_controllable,
};
static const struct pwrseq_target_data *pwrseq_qcom_wcn_targets[] = {
--
2.34.1