]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
regulator: core: move supply check earlier in set_machine_constraints()
authorAndré Draszik <andre.draszik@linaro.org>
Fri, 9 Jan 2026 08:38:39 +0000 (08:38 +0000)
committerMark Brown <broonie@kernel.org>
Fri, 9 Jan 2026 13:37:56 +0000 (13:37 +0000)
Since commit 98e48cd9283d ("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 8a866d527ac0 ("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: 98e48cd9283d ("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>
drivers/regulator/core.c

index 48c091de68d81e3e89eacecd8526255ab9a446b2..9ce0eef1dcfcb39a072675e44a5577ae85d51982 100644 (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.
                 */