diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/regulator/core.c | 37 |
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, | |||
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) |