summaryrefslogtreecommitdiff
path: root/drivers/regulator
diff options
context:
space:
mode:
authorLinus Walleij <linusw@kernel.org>2026-09-01 22:02:11 +0200
committerMark Brown <broonie@kernel.org>2026-09-10 19:52:53 +0100
commit71ac8878573058e2b85210760ccaeaac90796c35 (patch)
tree2ff6a49d69a47deb37701f3edd807f4052fe92a0 /drivers/regulator
parenta5ee78846015512b4d3d32f8aa463024a23234ce (diff)
downloadlinux-next-71ac8878573058e2b85210760ccaeaac90796c35.tar.gz
linux-next-71ac8878573058e2b85210760ccaeaac90796c35.zip
regulator: ab8500: Propagate mode enable read errors
For regulators whose enable and mode share a state field, set_mode() first reads that field so changing the requested mode does not enable a disabled rail. A register read error is currently treated as true and the driver proceeds to write the new mode, potentially enabling a rail whose state is unknown. Return the read error without changing the register or cached mode. References: AB8500 User Manual, UM0836 Rev 3, p. 227; AB8505 User Manual, DM00046744 Rev 3, p. 237 Fixes: 438e695b87e0 ("regulator: ab8500: Get rid of is_enabled from struct ab8500_regulator_info") Assisted-by: LLM Signed-off-by: Linus Walleij <linusw@kernel.org> Link: https://patch.msgid.link/20260901-ux500-dts-snowball-regulator-v2-6-fe88b01829bf@kernel.org Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/ab8500.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
index 05c6b9c7af0c..e4c3502c8dbc 100644
--- a/drivers/regulator/ab8500.c
+++ b/drivers/regulator/ab8500.c
@@ -433,7 +433,7 @@ static unsigned int ab8500_regulator_get_optimum_mode(
static int ab8500_regulator_set_mode(struct regulator_dev *rdev,
unsigned int mode)
{
- int ret = 0;
+ int enabled, ret = 0;
u8 bank, reg, mask, val;
bool lp_mode_req = false;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
@@ -490,7 +490,17 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev,
goto out_unlock;
}
- if (info->mode_mask || ab8500_regulator_is_enabled(rdev)) {
+ if (info->mode_mask) {
+ enabled = 1;
+ } else {
+ enabled = ab8500_regulator_is_enabled(rdev);
+ if (enabled < 0) {
+ ret = enabled;
+ goto out_unlock;
+ }
+ }
+
+ if (enabled) {
ret = abx500_mask_and_set_register_interruptible(info->dev,
bank, reg, mask, val);
if (ret < 0) {