mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 11:19:37 +00:00
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 <ivo.g.dimitrov.75@gmail.com> Tested-by: Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
895fe2321e
commit
fa93fd4ecc
2 changed files with 26 additions and 8 deletions
|
@ -906,7 +906,8 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
|
||||||
|
|
||||||
/* do we need to apply the constraint voltage */
|
/* do we need to apply the constraint voltage */
|
||||||
if (rdev->constraints->apply_uV &&
|
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);
|
int current_uV = _regulator_get_voltage(rdev);
|
||||||
if (current_uV < 0) {
|
if (current_uV < 0) {
|
||||||
rdev_err(rdev,
|
rdev_err(rdev,
|
||||||
|
@ -914,15 +915,32 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
|
||||||
current_uV);
|
current_uV);
|
||||||
return 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(
|
ret = _regulator_do_set_voltage(
|
||||||
rdev, rdev->constraints->min_uV,
|
rdev, target_min, target_max);
|
||||||
rdev->constraints->max_uV);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
rdev_err(rdev,
|
rdev_err(rdev,
|
||||||
"failed to apply %duV constraint(%d)\n",
|
"failed to apply %d-%duV constraint(%d)\n",
|
||||||
rdev->constraints->min_uV, ret);
|
target_min, target_max, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ static void of_get_regulation_constraints(struct device_node *np,
|
||||||
constraints->max_uV = pval;
|
constraints->max_uV = pval;
|
||||||
|
|
||||||
/* Voltage change possible? */
|
/* 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->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
|
||||||
constraints->apply_uV = true;
|
constraints->apply_uV = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue