diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2009-02-26 14:48:36 -0500 |
---|---|---|
committer | Liam Girdwood <lrg@slimlogic.co.uk> | 2009-03-31 04:56:24 -0400 |
commit | 4367cfdc7c657ad8a797f51b9ffd3c64b31910e7 (patch) | |
tree | b5ddefa9b0de91e58666be25e11cc805bf8c88d8 | |
parent | 33f301af0c56971e3c0f4a4eb4b92f7e80230f49 (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>
-rw-r--r-- | drivers/regulator/core.c | 113 | ||||
-rw-r--r-- | include/linux/regulator/consumer.h | 2 | ||||
-rw-r--r-- | include/linux/regulator/driver.h | 9 |
3 files changed, 124 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) | |||
1251 | EXPORT_SYMBOL_GPL(regulator_is_enabled); | 1314 | EXPORT_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 | */ | ||
1324 | int regulator_count_voltages(struct regulator *regulator) | ||
1325 | { | ||
1326 | struct regulator_dev *rdev = regulator->rdev; | ||
1327 | |||
1328 | return rdev->desc->n_voltages ? : -EINVAL; | ||
1329 | } | ||
1330 | EXPORT_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 | */ | ||
1342 | int 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 | } | ||
1364 | EXPORT_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 |
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index df6c4bcf38f8..277f4b964df5 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h | |||
@@ -142,6 +142,8 @@ int regulator_bulk_disable(int num_consumers, | |||
142 | void regulator_bulk_free(int num_consumers, | 142 | void regulator_bulk_free(int num_consumers, |
143 | struct regulator_bulk_data *consumers); | 143 | struct regulator_bulk_data *consumers); |
144 | 144 | ||
145 | int regulator_count_voltages(struct regulator *regulator); | ||
146 | int regulator_list_voltage(struct regulator *regulator, unsigned selector); | ||
145 | int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV); | 147 | int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV); |
146 | int regulator_get_voltage(struct regulator *regulator); | 148 | int regulator_get_voltage(struct regulator *regulator); |
147 | int regulator_set_current_limit(struct regulator *regulator, | 149 | int regulator_set_current_limit(struct regulator *regulator, |
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 0cf37bc85c41..2255468d456f 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h | |||
@@ -45,6 +45,10 @@ enum regulator_status { | |||
45 | * @set_voltage: Set the voltage for the regulator within the range specified. | 45 | * @set_voltage: Set the voltage for the regulator within the range specified. |
46 | * The driver should select the voltage closest to min_uV. | 46 | * The driver should select the voltage closest to min_uV. |
47 | * @get_voltage: Return the currently configured voltage for the regulator. | 47 | * @get_voltage: Return the currently configured voltage for the regulator. |
48 | * @list_voltage: Return one of the supported voltages, in microvolts; zero | ||
49 | * if the selector indicates a voltage that is unusable on this system; | ||
50 | * or negative errno. Selectors range from zero to one less than | ||
51 | * regulator_desc.n_voltages. Voltages may be reported in any order. | ||
48 | * | 52 | * |
49 | * @set_current_limit: Configure a limit for a current-limited regulator. | 53 | * @set_current_limit: Configure a limit for a current-limited regulator. |
50 | * @get_current_limit: Get the limit for a current-limited regulator. | 54 | * @get_current_limit: Get the limit for a current-limited regulator. |
@@ -66,6 +70,9 @@ enum regulator_status { | |||
66 | */ | 70 | */ |
67 | struct regulator_ops { | 71 | struct regulator_ops { |
68 | 72 | ||
73 | /* enumerate supported voltages */ | ||
74 | int (*list_voltage) (struct regulator_dev *, unsigned selector); | ||
75 | |||
69 | /* get/set regulator voltage */ | 76 | /* get/set regulator voltage */ |
70 | int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV); | 77 | int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV); |
71 | int (*get_voltage) (struct regulator_dev *); | 78 | int (*get_voltage) (struct regulator_dev *); |
@@ -124,6 +131,7 @@ enum regulator_type { | |||
124 | * | 131 | * |
125 | * @name: Identifying name for the regulator. | 132 | * @name: Identifying name for the regulator. |
126 | * @id: Numerical identifier for the regulator. | 133 | * @id: Numerical identifier for the regulator. |
134 | * @n_voltages: Number of selectors available for ops.list_voltage(). | ||
127 | * @ops: Regulator operations table. | 135 | * @ops: Regulator operations table. |
128 | * @irq: Interrupt number for the regulator. | 136 | * @irq: Interrupt number for the regulator. |
129 | * @type: Indicates if the regulator is a voltage or current regulator. | 137 | * @type: Indicates if the regulator is a voltage or current regulator. |
@@ -132,6 +140,7 @@ enum regulator_type { | |||
132 | struct regulator_desc { | 140 | struct regulator_desc { |
133 | const char *name; | 141 | const char *name; |
134 | int id; | 142 | int id; |
143 | unsigned n_voltages; | ||
135 | struct regulator_ops *ops; | 144 | struct regulator_ops *ops; |
136 | int irq; | 145 | int irq; |
137 | enum regulator_type type; | 146 | enum regulator_type type; |