From: Fabio Estevam <festevam@gmail.com>
To: broonie@kernel.org
Cc: linux-kernel@vger.kernel.org, imx@lists.linux.dev,
Fabio Estevam <festevam@nabladev.com>
Subject: [PATCH] regulator: pca9450: Support regulator-off-in-suspend
Date: Fri, 24 Jul 2026 17:13:22 -0300 [thread overview]
Message-ID: <20260724201322.73937-1-festevam@gmail.com> (raw)
From: Fabio Estevam <festevam@nabladev.com>
The PCA9450 uses each regulator's ENMODE field to control whether the
regulator remains enabled when the PMIC transitions from RUN to STANDBY
mode.
The driver does not currently implement set_suspend_disable(), so a
regulator configured with regulator-off-in-suspend remains enabled
during system suspend.
Implement set_suspend_disable() for the buck regulators and LDO3-LDO5
by programming ENMODE to 10b. This keeps the regulator enabled in RUN
mode, turns it off when PMIC_STBY_REQ is asserted, and enables it again
when the PMIC returns to RUN mode.
Keep LDO1 and LDO2 on regulator operations without
set_suspend_disable(), because these regulators supply the SNVS domain
and must remain enabled in STANDBY mode.
Measured on a custom i.MX8MP board, turning off NVCC_SD2 (LDO5) during
system suspend reduced power consumption by approximately 64 mW.
Signed-off-by: Fabio Estevam <festevam@nabladev.com>
---
drivers/regulator/pca9450-regulator.c | 43 +++++++++++++++++++++++----
include/linux/regulator/pca9450.h | 3 ++
2 files changed, 40 insertions(+), 6 deletions(-)
diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c
index c41db70fa052..13082585140f 100644
--- a/drivers/regulator/pca9450-regulator.c
+++ b/drivers/regulator/pca9450-regulator.c
@@ -77,6 +77,24 @@ static const unsigned int pca9450_dvs_buck_ramp_table[] = {
25000, 12500, 6250, 3125
};
+/*
+ * ENMODE = 10b keeps the regulator enabled in RUN mode and disables it
+ * while PMIC_STBY_REQ is asserted.
+ */
+static int pca9450_buck_set_suspend_disable(struct regulator_dev *rdev)
+{
+ return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+ rdev->desc->enable_mask,
+ BUCK_ENMODE_ONREQ_STBYREQ);
+}
+
+static int pca9450_ldo_set_suspend_disable(struct regulator_dev *rdev)
+{
+ return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+ rdev->desc->enable_mask,
+ LDO_ENMODE_ONREQ_STBYREQ);
+}
+
static const struct regulator_ops pca9450_dvs_buck_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -88,6 +106,7 @@ static const struct regulator_ops pca9450_dvs_buck_regulator_ops = {
.set_ramp_delay = regulator_set_ramp_delay_regmap,
.set_mode = pca9450_buck_set_mode,
.get_mode = pca9450_buck_get_mode,
+ .set_suspend_disable = pca9450_buck_set_suspend_disable,
};
static const struct regulator_ops pca9450_buck_regulator_ops = {
@@ -100,6 +119,7 @@ static const struct regulator_ops pca9450_buck_regulator_ops = {
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_mode = pca9450_buck_set_mode,
.get_mode = pca9450_buck_get_mode,
+ .set_suspend_disable = pca9450_buck_set_suspend_disable,
};
static const struct regulator_ops pca9450_ldo_regulator_ops = {
@@ -111,6 +131,16 @@ static const struct regulator_ops pca9450_ldo_regulator_ops = {
.get_voltage_sel = regulator_get_voltage_sel_regmap,
};
+static const struct regulator_ops pca9450_ldo_suspend_regulator_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_suspend_disable = pca9450_ldo_set_suspend_disable,
+};
+
static unsigned int pca9450_ldo5_get_reg_voltage_sel(struct regulator_dev *rdev)
{
struct pca9450 *pca9450 = rdev_get_drvdata(rdev);
@@ -164,6 +194,7 @@ static const struct regulator_ops pca9450_ldo5_regulator_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.set_voltage_sel = pca9450_ldo5_set_voltage_sel_regmap,
.get_voltage_sel = pca9450_ldo5_get_voltage_sel_regmap,
+ .set_suspend_disable = pca9450_ldo_set_suspend_disable,
};
/*
@@ -575,7 +606,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = {
.of_match = of_match_ptr("LDO3"),
.regulators_node = of_match_ptr("regulators"),
.id = PCA9450_LDO3,
- .ops = &pca9450_ldo_regulator_ops,
+ .ops = &pca9450_ldo_suspend_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = PCA9450_LDO3_VOLTAGE_NUM,
.linear_ranges = pca9450_ldo34_volts,
@@ -594,7 +625,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = {
.of_match = of_match_ptr("LDO4"),
.regulators_node = of_match_ptr("regulators"),
.id = PCA9450_LDO4,
- .ops = &pca9450_ldo_regulator_ops,
+ .ops = &pca9450_ldo_suspend_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = PCA9450_LDO4_VOLTAGE_NUM,
.linear_ranges = pca9450_ldo34_volts,
@@ -820,7 +851,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = {
.of_match = of_match_ptr("LDO3"),
.regulators_node = of_match_ptr("regulators"),
.id = PCA9450_LDO3,
- .ops = &pca9450_ldo_regulator_ops,
+ .ops = &pca9450_ldo_suspend_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = PCA9450_LDO3_VOLTAGE_NUM,
.linear_ranges = pca9450_ldo34_volts,
@@ -839,7 +870,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = {
.of_match = of_match_ptr("LDO4"),
.regulators_node = of_match_ptr("regulators"),
.id = PCA9450_LDO4,
- .ops = &pca9450_ldo_regulator_ops,
+ .ops = &pca9450_ldo_suspend_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = PCA9450_LDO4_VOLTAGE_NUM,
.linear_ranges = pca9450_ldo34_volts,
@@ -1040,7 +1071,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = {
.of_match = of_match_ptr("LDO3"),
.regulators_node = of_match_ptr("regulators"),
.id = PCA9450_LDO3,
- .ops = &pca9450_ldo_regulator_ops,
+ .ops = &pca9450_ldo_suspend_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = PCA9450_LDO3_VOLTAGE_NUM,
.linear_ranges = pca9450_ldo34_volts,
@@ -1059,7 +1090,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = {
.of_match = of_match_ptr("LDO4"),
.regulators_node = of_match_ptr("regulators"),
.id = PCA9450_LDO4,
- .ops = &pca9450_ldo_regulator_ops,
+ .ops = &pca9450_ldo_suspend_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = PCA9450_LDO4_VOLTAGE_NUM,
.linear_ranges = pca9450_ldo34_volts,
diff --git a/include/linux/regulator/pca9450.h b/include/linux/regulator/pca9450.h
index 0df8b3c48082..8925e9c9376b 100644
--- a/include/linux/regulator/pca9450.h
+++ b/include/linux/regulator/pca9450.h
@@ -213,6 +213,9 @@ enum {
#define LDO5H_EN_MASK 0xC0
#define LDO5HOUT_MASK 0x0F
+/* LDO ENMODE value: ON in RUN, OFF while PMIC_STBY_REQ is asserted */
+#define LDO_ENMODE_ONREQ_STBYREQ 0x80
+
/* PCA9450_REG_IRQ bits */
#define IRQ_PWRON 0x80
#define IRQ_WDOGB 0x40
--
2.43.0
next reply other threads:[~2026-07-24 20:13 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-24 20:13 Fabio Estevam [this message]
2026-07-24 20:27 ` [PATCH] regulator: pca9450: Support regulator-off-in-suspend sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260724201322.73937-1-festevam@gmail.com \
--to=festevam@gmail.com \
--cc=broonie@kernel.org \
--cc=festevam@nabladev.com \
--cc=imx@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.