Skip to content

Commit

Permalink
regulator: core: Allow regulators to provide a voltage to selector ma…
Browse files Browse the repository at this point in the history
…pping

In order to allow more drivers to factor things out into data allow
drivers to provide a mapping function to convert voltages into selectors.
This allows any driver to use set_voltage_sel(). The existing mapping
based on iterating over list_voltage() is provided as an operation which
can be assigned to the new map_voltage() function though for ease of
transition it is treated as the default.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@ti.com>
  • Loading branch information
Mark Brown committed May 12, 2012
1 parent 5949a7e commit e843fc4
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 27 deletions.
82 changes: 55 additions & 27 deletions drivers/regulator/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1967,14 +1967,54 @@ int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel)
}
EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap);

/**
* regulator_map_voltage_iterate - map_voltage() based on list_voltage()
*
* @rdev: Regulator to operate on
* @min_uV: Lower bound for voltage
* @max_uV: Upper bound for voltage
*
* Drivers implementing set_voltage_sel() and list_voltage() can use
* this as their map_voltage() operation. It will find a suitable
* voltage by calling list_voltage() until it gets something in bounds
* for the requested voltages.
*/
int regulator_map_voltage_iterate(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
int best_val = INT_MAX;
int selector = 0;
int i, ret;

/* Find the smallest voltage that falls within the specified
* range.
*/
for (i = 0; i < rdev->desc->n_voltages; i++) {
ret = rdev->desc->ops->list_voltage(rdev, i);
if (ret < 0)
continue;

if (ret < best_val && ret >= min_uV && ret <= max_uV) {
best_val = ret;
selector = i;
}
}

if (best_val != INT_MAX)
return selector;
else
return -EINVAL;
}
EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);

static int _regulator_do_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
int ret;
int delay = 0;
int best_val;
unsigned int selector;
int old_selector = -1;
int best_val = INT_MAX;

trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);

Expand All @@ -1995,39 +2035,27 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
if (rdev->desc->ops->set_voltage) {
ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
&selector);

if (rdev->desc->ops->list_voltage)
best_val = rdev->desc->ops->list_voltage(rdev,
selector);
else
best_val = -1;
} else if (rdev->desc->ops->set_voltage_sel) {
int i;

selector = 0;

/* Find the smallest voltage that falls within the specified
* range.
*/
for (i = 0; i < rdev->desc->n_voltages; i++) {
ret = rdev->desc->ops->list_voltage(rdev, i);
if (ret < 0)
continue;
if (rdev->desc->ops->map_voltage)
ret = rdev->desc->ops->map_voltage(rdev, min_uV,
max_uV);
else
ret = regulator_map_voltage_iterate(rdev, min_uV,
max_uV);

if (ret < best_val && ret >= min_uV && ret <= max_uV) {
best_val = ret;
selector = i;
}
if (ret >= 0) {
selector = ret;
ret = rdev->desc->ops->set_voltage_sel(rdev, ret);
}

if (best_val != INT_MAX)
ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
else
ret = -EINVAL;
} else {
ret = -EINVAL;
}

if (rdev->desc->ops->list_voltage)
best_val = rdev->desc->ops->list_voltage(rdev, selector);
else
best_val = -1;

/* Call set_voltage_time_sel if successfully obtained old_selector */
if (ret == 0 && old_selector >= 0 &&
rdev->desc->ops->set_voltage_time_sel) {
Expand Down
4 changes: 4 additions & 0 deletions include/linux/regulator/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ enum regulator_status {
* The driver should select the voltage closest to min_uV.
* @set_voltage_sel: Set the voltage for the regulator using the specified
* selector.
* @map_voltage: Convert a voltage into a selector
* @get_voltage: Return the currently configured voltage for the regulator.
* @get_voltage_sel: Return the currently configured voltage selector for the
* regulator.
Expand Down Expand Up @@ -91,6 +92,7 @@ struct regulator_ops {
/* get/set regulator voltage */
int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV,
unsigned *selector);
int (*map_voltage)(struct regulator_dev *, int min_uV, int max_uV);
int (*set_voltage_sel) (struct regulator_dev *, unsigned selector);
int (*get_voltage) (struct regulator_dev *);
int (*get_voltage_sel) (struct regulator_dev *);
Expand Down Expand Up @@ -260,6 +262,8 @@ int rdev_get_id(struct regulator_dev *rdev);

int regulator_mode_to_status(unsigned int);

int regulator_map_voltage_iterate(struct regulator_dev *rdev,
int min_uV, int max_uV);
int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev);
int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel);
int regulator_is_enabled_regmap(struct regulator_dev *rdev);
Expand Down

0 comments on commit e843fc4

Please sign in to comment.