diff options
| author | Linus Walleij <linusw@kernel.org> | 2026-09-01 22:02:11 +0200 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-09-10 19:52:53 +0100 |
| commit | 71ac8878573058e2b85210760ccaeaac90796c35 (patch) | |
| tree | 2ff6a49d69a47deb37701f3edd807f4052fe92a0 /drivers/regulator | |
| parent | a5ee78846015512b4d3d32f8aa463024a23234ce (diff) | |
| download | linux-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.c | 14 |
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) { |
