aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/regulator/core.c37
-rw-r--r--include/linux/regulator/driver.h3
2 files changed, 38 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,
1637 selector); 1637 selector);
1638 else 1638 else
1639 selector = -1; 1639 selector = -1;
1640 } else if (rdev->desc->ops->set_voltage_sel) {
1641 int best_val = INT_MAX;
1642 int i;
1643
1644 selector = 0;
1645
1646 /* Find the smallest voltage that falls within the specified
1647 * range.
1648 */
1649 for (i = 0; i < rdev->desc->n_voltages; i++) {
1650 ret = rdev->desc->ops->list_voltage(rdev, i);
1651 if (ret < 0)
1652 continue;
1653
1654 if (ret < best_val && ret >= min_uV && ret <= max_uV) {
1655 best_val = ret;
1656 selector = i;
1657 }
1658 }
1659
1660 if (best_val != INT_MAX) {
1661 ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
1662 selector = best_val;
1663 } else {
1664 ret = -EINVAL;
1665 }
1640 } else { 1666 } else {
1641 ret = -EINVAL; 1667 ret = -EINVAL;
1642 } 1668 }
@@ -1672,7 +1698,8 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
1672 mutex_lock(&rdev->mutex); 1698 mutex_lock(&rdev->mutex);
1673 1699
1674 /* sanity check */ 1700 /* sanity check */
1675 if (!rdev->desc->ops->set_voltage) { 1701 if (!rdev->desc->ops->set_voltage &&
1702 !rdev->desc->ops->set_voltage_sel) {
1676 ret = -EINVAL; 1703 ret = -EINVAL;
1677 goto out; 1704 goto out;
1678 } 1705 }
@@ -2256,7 +2283,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
2256 return status; 2283 return status;
2257 2284
2258 /* constraints need specific supporting methods */ 2285 /* constraints need specific supporting methods */
2259 if (ops->set_voltage) { 2286 if (ops->set_voltage || ops->set_voltage_sel) {
2260 status = device_create_file(dev, &dev_attr_min_microvolts); 2287 status = device_create_file(dev, &dev_attr_min_microvolts);
2261 if (status < 0) 2288 if (status < 0)
2262 return status; 2289 return status;
@@ -2354,12 +2381,18 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
2354 /* Only one of each should be implemented */ 2381 /* Only one of each should be implemented */
2355 WARN_ON(regulator_desc->ops->get_voltage && 2382 WARN_ON(regulator_desc->ops->get_voltage &&
2356 regulator_desc->ops->get_voltage_sel); 2383 regulator_desc->ops->get_voltage_sel);
2384 WARN_ON(regulator_desc->ops->set_voltage &&
2385 regulator_desc->ops->set_voltage_sel);
2357 2386
2358 /* If we're using selectors we must implement list_voltage. */ 2387 /* If we're using selectors we must implement list_voltage. */
2359 if (regulator_desc->ops->get_voltage_sel && 2388 if (regulator_desc->ops->get_voltage_sel &&
2360 !regulator_desc->ops->list_voltage) { 2389 !regulator_desc->ops->list_voltage) {
2361 return ERR_PTR(-EINVAL); 2390 return ERR_PTR(-EINVAL);
2362 } 2391 }
2392 if (regulator_desc->ops->set_voltage_sel &&
2393 !regulator_desc->ops->list_voltage) {
2394 return ERR_PTR(-EINVAL);
2395 }
2363 2396
2364 rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 2397 rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
2365 if (rdev == NULL) 2398 if (rdev == NULL)
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index bf3e653591b9..975ae06cb634 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -42,6 +42,8 @@ enum regulator_status {
42 * 42 *
43 * @set_voltage: Set the voltage for the regulator within the range specified. 43 * @set_voltage: Set the voltage for the regulator within the range specified.
44 * The driver should select the voltage closest to min_uV. 44 * The driver should select the voltage closest to min_uV.
45 * @set_voltage_sel: Set the voltage for the regulator using the specified
46 * selector.
45 * @get_voltage: Return the currently configured voltage for the regulator. 47 * @get_voltage: Return the currently configured voltage for the regulator.
46 * @get_voltage_sel: Return the currently configured voltage selector for the 48 * @get_voltage_sel: Return the currently configured voltage selector for the
47 * regulator. 49 * regulator.
@@ -83,6 +85,7 @@ struct regulator_ops {
83 /* get/set regulator voltage */ 85 /* get/set regulator voltage */
84 int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV, 86 int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV,
85 unsigned *selector); 87 unsigned *selector);
88 int (*set_voltage_sel) (struct regulator_dev *, unsigned selector);
86 int (*get_voltage) (struct regulator_dev *); 89 int (*get_voltage) (struct regulator_dev *);
87 int (*get_voltage_sel) (struct regulator_dev *); 90 int (*get_voltage_sel) (struct regulator_dev *);
88 91