Balancing coupled regulators must wait until the clients for all of the coupled regualtors set their constraints, otherwise the balancing code might change the voltage of the not-yet-constrained regulator to the value below the bootloader-configured operation point, what might cause a system crash. Signed-off-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> --- This is probably a generalization of the issue aleady observed and reported here: https://lore.kernel.org/linux-samsung-soc/20191008101709.qVNy8eijBi0LynOteWFMnTg4GUwKG599n6OyYoX1Abs@z/ https://lore.kernel.org/lkml/20191017102758.8104-1-m.szyprowski@xxxxxxxxxxx/ https://lore.kernel.org/linux-pm/cover.1589528491.git.viresh.kumar@xxxxxxxxxx/ The problem is with "vdd_int" regulator coupled with "vdd_arm" on Odroid XU3/XU4 boards family. "vdd_arm" is handled by CPUfreq. "vdd_int" is handled by devfreq. CPUfreq initialized quite early during boot and it starts changing OPPs and "vdd_arm" value. Sometimes CPU activity during boot goes down and some low-frequency OPPs are selected, what in turn causes lowering "vdd_arm". This happens before devfreq applies its requirements on "vdd_int". Regulator balancing code reduces "vdd_arm" voltage value, what in turn causes lowering "vdd_int" value to the lowest possible value. This is much below the operation point of the wcore bus, which still runs at the highest frequency. The issue was hard to notice because in the most cases the board managed to boot properly, even when the regulator was set to lowest value allowed by the regulator constraints. However, it caused some random issues, which can be observed as "Unhandled prefetch abort" or low USB stability. I know that adding more and more special cases to the generic code is not the best idea, but so far I see no other way to fix this issue. The only other solution that comes to my mind is admiting that it is not possible to have generic regulator coupler and this needs board-specific code in all cases. Such code might take care of those corner cases if they are critical. Best regards, Marek Szyprowski --- drivers/regulator/core.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 941783a14b45..c1d77d44186b 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3697,10 +3697,21 @@ static int regulator_balance_voltage(struct regulator_dev *rdev, * the coupled voltages. */ int optimal_uV = 0, optimal_max_uV = 0, current_uV = 0; + int cons_uV = 0, cons_max_uV = INT_MAX; if (test_bit(i, &c_rdev_done)) continue; + ret = regulator_check_consumers(c_rdevs[i], + &cons_uV, + &cons_max_uV, state); + if (ret < 0) + goto out; + + /* no constraints set - ignore */ + if (cons_uV == 0) + continue; + ret = regulator_get_optimal_voltage(c_rdevs[i], ¤t_uV, &optimal_uV, -- 2.17.1