[PATCH 01/12] power: sequencing: Introduce an API to check whether the pwrseq is fixed or controllable

Manivannan Sadhasivam via B4 Relay
2026-04-22T11:25:12Z

Introduce an API pwrseq_is_fixed() so that the consumers can check whether
the given power sequencer is fixed or controllable. This will come handy
in situations where the consumers need to know whether the specific power
sequencer like 'Bluetooth' can be controllable using properties like BT_EN.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
drivers/power/sequencing/core.c | 33 +++++++++++++++++++++++++++++++++
include/linux/pwrseq/consumer.h | 6 ++++++
include/linux/pwrseq/provider.h | 2 ++
3 files changed, 41 insertions(+)

diff --git a/drivers/power/sequencing/core.c b/drivers/power/sequencing/core.c
index 4dff71be11b6..20af9643f1ac 100644
--- a/drivers/power/sequencing/core.c
+++ b/drivers/power/sequencing/core.c
@@ -182,12 +182,14 @@ static void pwrseq_unit_release(struct kref *ref)
* the state lock has been released. It's useful for implementing
* boot-up delays without blocking other users from powering up
* using the same power sequencer.
+ * @is_fixed: Check whether this target is fixed or not.
*/
struct pwrseq_target {
struct list_head list;
const char *name;
struct pwrseq_unit *unit;
pwrseq_power_state_func post_enable;
+ bool (*is_fixed)(struct pwrseq_device *pwrseq);
};

static struct pwrseq_target *
@@ -206,6 +208,7 @@ pwrseq_target_new(const struct pwrseq_target_data *data)
}

target->post_enable = data->post_enable;
+ target->is_fixed = data->is_fixed;

return target;
}
@@ -965,6 +968,36 @@ int pwrseq_power_off(struct pwrseq_desc *desc)
}
EXPORT_SYMBOL_GPL(pwrseq_power_off);

+/**
+ * pwrseq_is_fixed() - Check whether the power sequencer is fixed or
+ * controllable.
+ * @desc: Descriptor referencing the power sequencer.
+ *
+ * This API can be used to check whether a specific power sequencer like
+ * 'Bluetooth' is fixed or controllable through properties like 'BT_EN' GPIO.
+ *
+ * Returns: true if fixed, false if controllable.
+ */
+bool pwrseq_is_fixed(struct pwrseq_desc *desc)
+{
+ /*
+ * If there is no power sequencer, then the consumer cannot control
+ * the power, so it is effectively fixed.
+ */
+ if (!desc)
+ return true;
+
+ /*
+ * If the provider hasn't implemented the callback, assume it acts
+ * like a controllable power sequencer (for backward compatibility).
+ */
+ if (!desc->target->is_fixed)
+ return false;
+
+ return desc->target->is_fixed(desc->pwrseq);
+}
+EXPORT_SYMBOL_GPL(pwrseq_is_fixed);
+
#if IS_ENABLED(CONFIG_DEBUG_FS)

struct pwrseq_debugfs_count_ctx {
diff --git a/include/linux/pwrseq/consumer.h b/include/linux/pwrseq/consumer.h
index 7d583b4f266e..7c24958880d7 100644
--- a/include/linux/pwrseq/consumer.h
+++ b/include/linux/pwrseq/consumer.h
@@ -22,6 +22,7 @@ devm_pwrseq_get(struct device *dev, const char *target);

int pwrseq_power_on(struct pwrseq_desc *desc);
int pwrseq_power_off(struct pwrseq_desc *desc);
+bool pwrseq_is_fixed(struct pwrseq_desc *desc);

#else /* CONFIG_POWER_SEQUENCING */

@@ -51,6 +52,11 @@ static inline int pwrseq_power_off(struct pwrseq_desc *desc)
return -ENOSYS;
}

+static inline bool pwrseq_is_fixed(struct pwrseq_desc *desc)
+{
+ return true;
+}
+
#endif /* CONFIG_POWER_SEQUENCING */

#endif /* __POWER_SEQUENCING_CONSUMER_H__ */
diff --git a/include/linux/pwrseq/provider.h b/include/linux/pwrseq/provider.h
index 33b3d2c2e39d..11165e98cde0 100644
--- a/include/linux/pwrseq/provider.h
+++ b/include/linux/pwrseq/provider.h
@@ -43,11 +43,13 @@ struct pwrseq_unit_data {
* the state lock has been released. It's useful for implementing
* boot-up delays without blocking other users from powering up
* using the same power sequencer.
+ * @is_fixed: Callback to check whether this power sequencer is fixed or not.
*/
struct pwrseq_target_data {
const char *name;
const struct pwrseq_unit_data *unit;
pwrseq_power_state_func post_enable;
+ bool (*is_fixed)(struct pwrseq_device *pwrseq);
};

/**

--
2.51.0