regulator: use linear_ranges helper

Change the regulator helpers to use common linear_ranges code.

Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Acked-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
Link: https://lore.kernel.org/r/64f01d5e381b8631a271616b7790f9d5640974fb.1588944082.git.matti.vaittinen@fi.rohmeurope.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Matti Vaittinen
2020-05-08 18:43:36 +03:00
committed by Mark Brown
parent de824cc965
commit 60ab7f4153
47 changed files with 229 additions and 261 deletions

View File

@@ -131,10 +131,11 @@ int regulator_get_voltage_sel_pickable_regmap(struct regulator_dev *rdev)
unsigned int r_val;
int range;
unsigned int val;
int ret, i;
unsigned int voltages_in_range = 0;
int ret;
unsigned int voltages = 0;
const struct linear_range *r = rdev->desc->linear_ranges;
if (!rdev->desc->linear_ranges)
if (!r)
return -EINVAL;
ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
@@ -152,11 +153,9 @@ int regulator_get_voltage_sel_pickable_regmap(struct regulator_dev *rdev)
if (range < 0)
return -EINVAL;
for (i = 0; i < range; i++)
voltages_in_range += (rdev->desc->linear_ranges[i].max_sel -
rdev->desc->linear_ranges[i].min_sel) + 1;
voltages = linear_range_values_in_range_array(r, range);
return val + voltages_in_range;
return val + voltages;
}
EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_pickable_regmap);
@@ -179,8 +178,11 @@ int regulator_set_voltage_sel_pickable_regmap(struct regulator_dev *rdev,
unsigned int voltages_in_range = 0;
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
voltages_in_range = (rdev->desc->linear_ranges[i].max_sel -
rdev->desc->linear_ranges[i].min_sel) + 1;
const struct linear_range *r;
r = &rdev->desc->linear_ranges[i];
voltages_in_range = linear_range_values_in_range(r);
if (sel < voltages_in_range)
break;
sel -= voltages_in_range;
@@ -405,8 +407,10 @@ EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);
int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
const struct regulator_linear_range *range;
const struct linear_range *range;
int ret = -EINVAL;
unsigned int sel;
bool found;
int voltage, i;
if (!rdev->desc->n_linear_ranges) {
@@ -415,35 +419,19 @@ int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
}
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
int linear_max_uV;
range = &rdev->desc->linear_ranges[i];
linear_max_uV = range->min_uV +
(range->max_sel - range->min_sel) * range->uV_step;
if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV))
ret = linear_range_get_selector_high(range, min_uV, &sel,
&found);
if (ret)
continue;
if (min_uV <= range->min_uV)
min_uV = range->min_uV;
/* range->uV_step == 0 means fixed voltage range */
if (range->uV_step == 0) {
ret = 0;
} else {
ret = DIV_ROUND_UP(min_uV - range->min_uV,
range->uV_step);
if (ret < 0)
return ret;
}
ret += range->min_sel;
ret = sel;
/*
* Map back into a voltage to verify we're still in bounds.
* If we are not, then continue checking rest of the ranges.
*/
voltage = rdev->desc->ops->list_voltage(rdev, ret);
voltage = rdev->desc->ops->list_voltage(rdev, sel);
if (voltage >= min_uV && voltage <= max_uV)
break;
}
@@ -468,7 +456,7 @@ EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range);
int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
const struct regulator_linear_range *range;
const struct linear_range *range;
int ret = -EINVAL;
int voltage, i;
unsigned int selector = 0;
@@ -480,30 +468,25 @@ int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev,
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
int linear_max_uV;
bool found;
unsigned int sel;
range = &rdev->desc->linear_ranges[i];
linear_max_uV = range->min_uV +
(range->max_sel - range->min_sel) * range->uV_step;
linear_max_uV = linear_range_get_max_value(range);
if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV)) {
selector += (range->max_sel - range->min_sel + 1);
if (!(min_uV <= linear_max_uV && max_uV >= range->min)) {
selector += linear_range_values_in_range(range);
continue;
}
if (min_uV <= range->min_uV)
min_uV = range->min_uV;
/* range->uV_step == 0 means fixed voltage range */
if (range->uV_step == 0) {
ret = 0;
} else {
ret = DIV_ROUND_UP(min_uV - range->min_uV,
range->uV_step);
if (ret < 0)
return ret;
ret = linear_range_get_selector_high(range, min_uV, &sel,
&found);
if (ret) {
selector += linear_range_values_in_range(range);
continue;
}
ret += selector;
ret = selector + sel;
voltage = rdev->desc->ops->list_voltage(rdev, ret);
@@ -513,7 +496,7 @@ int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev,
* exit but retry until we have checked all ranges.
*/
if (voltage < min_uV || voltage > max_uV)
selector += (range->max_sel - range->min_sel + 1);
selector += linear_range_values_in_range(range);
else
break;
}
@@ -561,7 +544,7 @@ EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
int regulator_list_voltage_pickable_linear_range(struct regulator_dev *rdev,
unsigned int selector)
{
const struct regulator_linear_range *range;
const struct linear_range *range;
int i;
unsigned int all_sels = 0;
@@ -571,18 +554,28 @@ int regulator_list_voltage_pickable_linear_range(struct regulator_dev *rdev,
}
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
unsigned int sels_in_range;
unsigned int sel_indexes;
range = &rdev->desc->linear_ranges[i];
sels_in_range = range->max_sel - range->min_sel;
sel_indexes = linear_range_values_in_range(range) - 1;
if (all_sels + sels_in_range >= selector) {
if (all_sels + sel_indexes >= selector) {
selector -= all_sels;
return range->min_uV + (range->uV_step * selector);
/*
* As we see here, pickable ranges work only as
* long as the first selector for each pickable
* range is 0, and the each subsequent range for
* this 'pick' follow immediately at next unused
* selector (Eg. there is no gaps between ranges).
* I think this is fine but it probably should be
* documented. OTOH, whole pickable range stuff
* might benefit from some documentation
*/
return range->min + (range->step * selector);
}
all_sels += (sels_in_range + 1);
all_sels += (sel_indexes + 1);
}
return -EINVAL;
@@ -604,27 +597,18 @@ EXPORT_SYMBOL_GPL(regulator_list_voltage_pickable_linear_range);
int regulator_desc_list_voltage_linear_range(const struct regulator_desc *desc,
unsigned int selector)
{
const struct regulator_linear_range *range;
int i;
unsigned int val;
int ret;
if (!desc->n_linear_ranges) {
BUG_ON(!desc->n_linear_ranges);
return -EINVAL;
}
BUG_ON(!desc->n_linear_ranges);
for (i = 0; i < desc->n_linear_ranges; i++) {
range = &desc->linear_ranges[i];
ret = linear_range_get_value_array(desc->linear_ranges,
desc->n_linear_ranges, selector,
&val);
if (ret)
return ret;
if (!(selector >= range->min_sel &&
selector <= range->max_sel))
continue;
selector -= range->min_sel;
return range->min_uV + (range->uV_step * selector);
}
return -EINVAL;
return val;
}
EXPORT_SYMBOL_GPL(regulator_desc_list_voltage_linear_range);