summaryrefslogtreecommitdiff
path: root/drivers/regulator/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator/core.c')
-rw-r--r--drivers/regulator/core.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 7a248dc8d2e2..8ed9b96518cf 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -3797,6 +3797,16 @@ static int _regulator_do_set_suspend_voltage(struct regulator_dev *rdev,
return 0;
}
+static int regulator_get_voltage_delta(struct regulator_dev *rdev, int uV)
+{
+ int current_uV = regulator_get_voltage_rdev(rdev);
+
+ if (current_uV < 0)
+ return current_uV;
+
+ return abs(current_uV - uV);
+}
+
static int regulator_set_voltage_unlocked(struct regulator *regulator,
int min_uV, int max_uV,
suspend_state_t state)
@@ -3804,8 +3814,8 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
struct regulator_dev *rdev = regulator->rdev;
struct regulator_voltage *voltage = &regulator->voltage[state];
int ret = 0;
+ int current_uV, delta, new_delta;
int old_min_uV, old_max_uV;
- int current_uV;
/* If we're setting the same range as last time the change
* should be a noop (some cpufreq implementations use the same
@@ -3852,6 +3862,37 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
voltage->max_uV = old_max_uV;
}
+ if (rdev->constraints->max_uV_step > 0) {
+ /* For regulators with a maximum voltage step, reaching the desired
+ * voltage might take a few retries.
+ */
+ ret = regulator_get_voltage_delta(rdev, min_uV);
+ if (ret < 0)
+ goto out;
+
+ delta = ret;
+
+ while (delta > 0) {
+ ret = regulator_balance_voltage(rdev, state);
+ if (ret < 0)
+ goto out;
+
+ ret = regulator_get_voltage_delta(rdev, min_uV);
+ if (ret < 0)
+ goto out;
+
+ new_delta = ret;
+
+ /* check that voltage is converging quickly enough */
+ if (new_delta - delta > rdev->constraints->max_uV_step) {
+ ret = -EWOULDBLOCK;
+ goto out;
+ }
+
+ delta = new_delta;
+ }
+ }
+
out:
return ret;
}
@@ -5639,6 +5680,7 @@ static void regulator_remove_coupling(struct regulator_dev *rdev)
ERR_PTR(err));
}
+ rdev->coupling_desc.n_coupled = 0;
kfree(rdev->coupling_desc.coupled_rdevs);
rdev->coupling_desc.coupled_rdevs = NULL;
}