regulator: core: move supply check earlier in set_machine_constraints()

Since commit 98e48cd928 ("regulator: core: resolve supply for
boot-on/always-on regulators"), set_machine_constraints() can return
-EPROBE_DEFER very late, after it has done a lot of work and
configuration of the regulator.

This means that configuration will happen multiple times for no
benefit in that case. Furthermore, this can lead to timing-dependent
voltage glitches as mentioned e.g. in commit 8a866d527a ("regulator:
core: Resolve supply name earlier to prevent double-init").

We can know that it's going to fail very early, in particular before
going through the complete regulator configuration by moving some code
around a little.

Do so to avoid re-configuring the regulator multiple times, also
avoiding the voltage glitches if we can.

Fixes: 98e48cd928 ("regulator: core: resolve supply for boot-on/always-on regulators")
Signed-off-by: André Draszik <andre.draszik@linaro.org>
Link: https://patch.msgid.link/20260109-regulators-defer-v2-3-1a25dc968e60@linaro.org
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
André Draszik
2026-01-09 08:38:39 +00:00
committed by Mark Brown
parent 497330b203
commit 86a8eeb0e9
+30 -25
View File
@@ -1444,6 +1444,33 @@ static int set_machine_constraints(struct regulator_dev *rdev)
int ret = 0;
const struct regulator_ops *ops = rdev->desc->ops;
/*
* If there is no mechanism for controlling the regulator then
* flag it as always_on so we don't end up duplicating checks
* for this so much. Note that we could control the state of
* a supply to control the output on a regulator that has no
* direct control.
*/
if (!rdev->ena_pin && !ops->enable) {
if (rdev->supply_name && !rdev->supply)
return -EPROBE_DEFER;
if (rdev->supply)
rdev->constraints->always_on =
rdev->supply->rdev->constraints->always_on;
else
rdev->constraints->always_on = true;
}
/*
* If we want to enable this regulator, make sure that we know the
* supplying regulator.
*/
if (rdev->constraints->always_on || rdev->constraints->boot_on) {
if (rdev->supply_name && !rdev->supply)
return -EPROBE_DEFER;
}
ret = machine_constraints_voltage(rdev, rdev->constraints);
if (ret != 0)
return ret;
@@ -1609,37 +1636,15 @@ static int set_machine_constraints(struct regulator_dev *rdev)
}
}
/*
* If there is no mechanism for controlling the regulator then
* flag it as always_on so we don't end up duplicating checks
* for this so much. Note that we could control the state of
* a supply to control the output on a regulator that has no
* direct control.
*/
if (!rdev->ena_pin && !ops->enable) {
if (rdev->supply_name && !rdev->supply)
return -EPROBE_DEFER;
if (rdev->supply)
rdev->constraints->always_on =
rdev->supply->rdev->constraints->always_on;
else
rdev->constraints->always_on = true;
}
/* If the constraints say the regulator should be on at this point
* and we have control then make sure it is enabled.
*/
if (rdev->constraints->always_on || rdev->constraints->boot_on) {
bool supply_enabled = false;
/* If we want to enable this regulator, make sure that we know
* the supplying regulator.
*/
if (rdev->supply_name && !rdev->supply)
return -EPROBE_DEFER;
/* If supplying regulator has already been enabled,
/* We have ensured a potential supply has been resolved above.
*
* If supplying regulator has already been enabled,
* it's not intended to have use_count increment
* when rdev is only boot-on.
*/