From 609fbaaee4e5fb6b5d2e0142b8a03a8eced0f92c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 21 Mar 2016 18:12:52 +0000 Subject: [PATCH] UPSTREAM: regulator: core: Ensure we are at least in bounds for our constraints Currently we only attempt to set the voltage during constraints application if an exact voltage is specified. Extend this so that if the currently set voltage for the regulator is outside the bounds set in constraints we will move the voltage to the nearest constraint, raising to the minimum or lowering to the maximum as needed. This ensures that drivers can probe without the hardware being driven out of spec. Reported-by: Ivaylo Dimitrov Tested-by: Ivaylo Dimitrov Signed-off-by: Mark Brown (cherry picked from commit fa93fd4ecc9c58475abac6db93a797bff893bc16) Change-Id: I3e3e60f2f93e971364a74f9735c362acaa59f512 Signed-off-by: David Wu --- drivers/regulator/core.c | 32 +++++++++++++++++++++++++------- drivers/regulator/of_regulator.c | 2 +- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 55cf0f12b2a9..a6f7abefef62 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -904,7 +904,8 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, /* do we need to apply the constraint voltage */ if (rdev->constraints->apply_uV && - rdev->constraints->min_uV == rdev->constraints->max_uV) { + rdev->constraints->min_uV && rdev->constraints->max_uV) { + int target_min, target_max; int current_uV = _regulator_get_voltage(rdev); if (current_uV < 0) { rdev_err(rdev, @@ -912,15 +913,32 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, current_uV); return current_uV; } - if (current_uV < rdev->constraints->min_uV || - current_uV > rdev->constraints->max_uV) { + + /* + * If we're below the minimum voltage move up to the + * minimum voltage, if we're above the maximum voltage + * then move down to the maximum. + */ + target_min = current_uV; + target_max = current_uV; + + if (current_uV < rdev->constraints->min_uV) { + target_min = rdev->constraints->min_uV; + target_max = rdev->constraints->min_uV; + } + + if (current_uV > rdev->constraints->max_uV) { + target_min = rdev->constraints->max_uV; + target_max = rdev->constraints->max_uV; + } + + if (target_min != current_uV || target_max != current_uV) { ret = _regulator_do_set_voltage( - rdev, rdev->constraints->min_uV, - rdev->constraints->max_uV); + rdev, target_min, target_max); if (ret < 0) { rdev_err(rdev, - "failed to apply %duV constraint(%d)\n", - rdev->constraints->min_uV, ret); + "failed to apply %d-%duV constraint(%d)\n", + target_min, target_max, ret); return ret; } } diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index d2ddefaaddaf..f45106a44635 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -43,7 +43,7 @@ static void of_get_regulation_constraints(struct device_node *np, constraints->max_uV = pval; /* Voltage change possible? */ - if (constraints->min_uV != constraints->max_uV) { + if (constraints->min_uV && constraints->max_uV) { constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; constraints->apply_uV = true; } -- 2.34.1