Skip to content

Commit

Permalink
regulator: implement selector stepping
Browse files Browse the repository at this point in the history
Some regulators require that the requested voltage be reached gradually
by setting all or some of the intermediate values. Implement a new field
in the regulator description struct that allows users to specify the
number of selectors by which the regulator API should step when ramping
the voltage up/down.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Link: https://lore.kernel.org/r/20190703161035.31808-2-brgl@bgdev.pl
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Bartosz Golaszewski authored and Mark Brown committed Jul 4, 2019
1 parent ba2bf34 commit 2da8d94
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 0 deletions.
63 changes: 63 additions & 0 deletions drivers/regulator/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -3106,6 +3106,66 @@ static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev,
return ret;
}

static int _regulator_set_voltage_sel_step(struct regulator_dev *rdev,
int uV, int new_selector)
{
const struct regulator_ops *ops = rdev->desc->ops;
int diff, old_sel, curr_sel, ret;

/* Stepping is only needed if the regulator is enabled. */
if (!_regulator_is_enabled(rdev))
goto final_set;

if (!ops->get_voltage_sel)
return -EINVAL;

old_sel = ops->get_voltage_sel(rdev);
if (old_sel < 0)
return old_sel;

diff = new_selector - old_sel;
if (diff == 0)
return 0; /* No change needed. */

if (diff > 0) {
/* Stepping up. */
for (curr_sel = old_sel + rdev->desc->vsel_step;
curr_sel < new_selector;
curr_sel += rdev->desc->vsel_step) {
/*
* Call the callback directly instead of using
* _regulator_call_set_voltage_sel() as we don't
* want to notify anyone yet. Same in the branch
* below.
*/
ret = ops->set_voltage_sel(rdev, curr_sel);
if (ret)
goto try_revert;
}
} else {
/* Stepping down. */
for (curr_sel = old_sel - rdev->desc->vsel_step;
curr_sel > new_selector;
curr_sel -= rdev->desc->vsel_step) {
ret = ops->set_voltage_sel(rdev, curr_sel);
if (ret)
goto try_revert;
}
}

final_set:
/* The final selector will trigger the notifiers. */
return _regulator_call_set_voltage_sel(rdev, uV, new_selector);

try_revert:
/*
* At least try to return to the previous voltage if setting a new
* one failed.
*/
(void)ops->set_voltage_sel(rdev, old_sel);
return ret;
}

static int _regulator_set_voltage_time(struct regulator_dev *rdev,
int old_uV, int new_uV)
{
Expand Down Expand Up @@ -3179,6 +3239,9 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
selector = ret;
if (old_selector == selector)
ret = 0;
else if (rdev->desc->vsel_step)
ret = _regulator_set_voltage_sel_step(
rdev, best_val, selector);
else
ret = _regulator_call_set_voltage_sel(
rdev, best_val, selector);
Expand Down
6 changes: 6 additions & 0 deletions include/linux/regulator/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,11 @@ enum regulator_type {
* @vsel_range_mask: Mask for register bitfield used for range selector
* @vsel_reg: Register for selector when using regulator_regmap_X_voltage_
* @vsel_mask: Mask for register bitfield used for selector
* @vsel_step: Specify the resolution of selector stepping when setting
* voltage. If 0, then no stepping is done (requested selector is
* set directly), if >0 then the regulator API will ramp the
* voltage up/down gradually each time increasing/decreasing the
* selector by the specified step value.
* @csel_reg: Register for current limit selector using regmap set_current_limit
* @csel_mask: Mask for register bitfield used for current limit selector
* @apply_reg: Register for initiate voltage change on the output when
Expand Down Expand Up @@ -360,6 +365,7 @@ struct regulator_desc {
unsigned int vsel_range_mask;
unsigned int vsel_reg;
unsigned int vsel_mask;
unsigned int vsel_step;
unsigned int csel_reg;
unsigned int csel_mask;
unsigned int apply_reg;
Expand Down

0 comments on commit 2da8d94

Please sign in to comment.