diff mbox series

[2/2] regulator: core: Ensure we are at least in bounds for our constraints

Message ID 1458587912-32665-2-git-send-email-broonie@kernel.org
State New
Headers show
Series [1/2] regulator: core: Always flag voltage constraints as appliable | expand

Commit Message

Mark Brown March 21, 2016, 7:18 p.m. UTC
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 regualtor 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 <ivo.g.dimitrov.75@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

---

Untested so far, will give it a spin later/tomorrow.

 drivers/regulator/core.c | 32 +++++++++++++++++++++++++-------
 1 file changed, 25 insertions(+), 7 deletions(-)

-- 
2.7.0
diff mbox series

Patch

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index fab065304fe2..f2acb6744c48 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -907,7 +907,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,
@@ -915,15 +916,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;
 			}
 		}