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.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 23c5f7c80bff..a0579f069002 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1637,6 +1637,32 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
selector);
else
selector = -1;
+ } else if (rdev->desc->ops->set_voltage_sel) {
+ int best_val = INT_MAX;
+ 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 (ret < best_val && ret >= min_uV && ret <= max_uV) {
+ best_val = ret;
+ selector = i;
+ }
+ }
+
+ if (best_val != INT_MAX) {
+ ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
+ selector = best_val;
+ } else {
+ ret = -EINVAL;
+ }
} else {
ret = -EINVAL;
}
@@ -1672,7 +1698,8 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
mutex_lock(&rdev->mutex);
/* sanity check */
- if (!rdev->desc->ops->set_voltage) {
+ if (!rdev->desc->ops->set_voltage &&
+ !rdev->desc->ops->set_voltage_sel) {
ret = -EINVAL;
goto out;
}
@@ -2256,7 +2283,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
return status;
/* constraints need specific supporting methods */
- if (ops->set_voltage) {
+ if (ops->set_voltage || ops->set_voltage_sel) {
status = device_create_file(dev, &dev_attr_min_microvolts);
if (status < 0)
return status;
@@ -2354,12 +2381,18 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
/* Only one of each should be implemented */
WARN_ON(regulator_desc->ops->get_voltage &&
regulator_desc->ops->get_voltage_sel);
+ WARN_ON(regulator_desc->ops->set_voltage &&
+ regulator_desc->ops->set_voltage_sel);
/* If we're using selectors we must implement list_voltage. */
if (regulator_desc->ops->get_voltage_sel &&
!regulator_desc->ops->list_voltage) {
return ERR_PTR(-EINVAL);
}
+ if (regulator_desc->ops->set_voltage_sel &&
+ !regulator_desc->ops->list_voltage) {
+ return ERR_PTR(-EINVAL);
+ }
rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
if (rdev == NULL)