aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2009-02-26 14:48:36 -0500
committerLiam Girdwood <lrg@slimlogic.co.uk>2009-03-31 04:56:24 -0400
commit4367cfdc7c657ad8a797f51b9ffd3c64b31910e7 (patch)
treeb5ddefa9b0de91e58666be25e11cc805bf8c88d8 /drivers
parent33f301af0c56971e3c0f4a4eb4b92f7e80230f49 (diff)
regulator: enumerate voltages (v2)
Add a basic mechanism for regulators to report the discrete voltages they support: list_voltage() enumerates them using selectors numbered from 0 to an upper bound. Use those methods to force machine-level constraints into bounds. (Example: regulator supports 1.8V, 2.4V, 2.6V, 3.3V, and board constraints for that rail are 2.0V to 3.6V ... so the range of voltages is then 2.4V to 3.3V on this board.) Export those voltages to the regulator consumer interface, so for example regulator hooked up to an MMC/SD/SDIO slot can report the actual voltage options available to cards connected there. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/regulator/core.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 75abcd85e51b..da357a07c98e 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -692,6 +692,69 @@ static int set_machine_constraints(struct regulator_dev *rdev,
692 else 692 else
693 name = "regulator"; 693 name = "regulator";
694 694
695 /* constrain machine-level voltage specs to fit
696 * the actual range supported by this regulator.
697 */
698 if (ops->list_voltage && rdev->desc->n_voltages) {
699 int count = rdev->desc->n_voltages;
700 int i;
701 int min_uV = INT_MAX;
702 int max_uV = INT_MIN;
703 int cmin = constraints->min_uV;
704 int cmax = constraints->max_uV;
705
706 /* it's safe to autoconfigure fixed-voltage supplies */
707 if (count == 1 && !cmin) {
708 cmin = INT_MIN;
709 cmax = INT_MAX;
710 }
711
712 /* else require explicit machine-level constraints */
713 else if (cmin <= 0 || cmax <= 0 || cmax < cmin) {
714 pr_err("%s: %s '%s' voltage constraints\n",
715 __func__, "invalid", name);
716 ret = -EINVAL;
717 goto out;
718 }
719
720 /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
721 for (i = 0; i < count; i++) {
722 int value;
723
724 value = ops->list_voltage(rdev, i);
725 if (value <= 0)
726 continue;
727
728 /* maybe adjust [min_uV..max_uV] */
729 if (value >= cmin && value < min_uV)
730 min_uV = value;
731 if (value <= cmax && value > max_uV)
732 max_uV = value;
733 }
734
735 /* final: [min_uV..max_uV] valid iff constraints valid */
736 if (max_uV < min_uV) {
737 pr_err("%s: %s '%s' voltage constraints\n",
738 __func__, "unsupportable", name);
739 ret = -EINVAL;
740 goto out;
741 }
742
743 /* use regulator's subset of machine constraints */
744 if (constraints->min_uV < min_uV) {
745 pr_debug("%s: override '%s' %s, %d -> %d\n",
746 __func__, name, "min_uV",
747 constraints->min_uV, min_uV);
748 constraints->min_uV = min_uV;
749 }
750 if (constraints->max_uV > max_uV) {
751 pr_debug("%s: override '%s' %s, %d -> %d\n",
752 __func__, name, "max_uV",
753 constraints->max_uV, max_uV);
754 constraints->max_uV = max_uV;
755 }
756 }
757
695 rdev->constraints = constraints; 758 rdev->constraints = constraints;
696 759
697 /* do we need to apply the constraint voltage */ 760 /* do we need to apply the constraint voltage */
@@ -1251,6 +1314,56 @@ int regulator_is_enabled(struct regulator *regulator)
1251EXPORT_SYMBOL_GPL(regulator_is_enabled); 1314EXPORT_SYMBOL_GPL(regulator_is_enabled);
1252 1315
1253/** 1316/**
1317 * regulator_count_voltages - count regulator_list_voltage() selectors
1318 * @regulator: regulator source
1319 *
1320 * Returns number of selectors, or negative errno. Selectors are
1321 * numbered starting at zero, and typically correspond to bitfields
1322 * in hardware registers.
1323 */
1324int regulator_count_voltages(struct regulator *regulator)
1325{
1326 struct regulator_dev *rdev = regulator->rdev;
1327
1328 return rdev->desc->n_voltages ? : -EINVAL;
1329}
1330EXPORT_SYMBOL_GPL(regulator_count_voltages);
1331
1332/**
1333 * regulator_list_voltage - enumerate supported voltages
1334 * @regulator: regulator source
1335 * @selector: identify voltage to list
1336 * Context: can sleep
1337 *
1338 * Returns a voltage that can be passed to @regulator_set_voltage(),
1339 * zero if this selector code can't be used on this sytem, or a
1340 * negative errno.
1341 */
1342int regulator_list_voltage(struct regulator *regulator, unsigned selector)
1343{
1344 struct regulator_dev *rdev = regulator->rdev;
1345 struct regulator_ops *ops = rdev->desc->ops;
1346 int ret;
1347
1348 if (!ops->list_voltage || selector >= rdev->desc->n_voltages)
1349 return -EINVAL;
1350
1351 mutex_lock(&rdev->mutex);
1352 ret = ops->list_voltage(rdev, selector);
1353 mutex_unlock(&rdev->mutex);
1354
1355 if (ret > 0) {
1356 if (ret < rdev->constraints->min_uV)
1357 ret = 0;
1358 else if (ret > rdev->constraints->max_uV)
1359 ret = 0;
1360 }
1361
1362 return ret;
1363}
1364EXPORT_SYMBOL_GPL(regulator_list_voltage);
1365
1366/**
1254 * regulator_set_voltage - set regulator output voltage 1367 * regulator_set_voltage - set regulator output voltage
1255 * @regulator: regulator source 1368 * @regulator: regulator source
1256 * @min_uV: Minimum required voltage in uV 1369 * @min_uV: Minimum required voltage in uV