aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorRajendra Nayak <rnayak@ti.com>2011-11-18 06:17:20 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-11-23 13:47:31 -0500
commit69511a452e6dc6b74fe4f3671a51b1b44b9c57e3 (patch)
tree486fe8a536a367c0e83f55a97103a1a527a7e2bf /drivers/regulator
parent2c043bcbf287dc69848054d5c02c55c20f7a7bc5 (diff)
regulator: map consumer regulator based on device tree
Device nodes in DT can associate themselves with one or more regulators/supply by providing a list of phandles (to regulator nodes) and corresponding supply names. For Example: devicenode: node@0x0 { ... ... vmmc-supply = <&regulator1>; vpll-supply = <&regulator2>; }; The driver would then do a regulator_get(dev, "vmmc"); to get regulator1 and do a regulator_get(dev, "vpll"); to get regulator2. of_get_regulator() extracts the regulator node for a given device, based on the supply name. Use it to look up the regulator for a given consumer from device tree, during a regulator_get(). If not found fallback and lookup through the regulator_map_list instead. Also, since the regulator dt nodes can use the same binding to associate with a parent regulator/supply, allow the drivers to specify a supply_name, which can then be used to lookup dt to find the parent phandle. Signed-off-by: Rajendra Nayak <rnayak@ti.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/core.c79
1 files changed, 67 insertions, 12 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 8b01eb06ba64..9867ebc00bed 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -25,6 +25,8 @@
25#include <linux/mutex.h> 25#include <linux/mutex.h>
26#include <linux/suspend.h> 26#include <linux/suspend.h>
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include <linux/of.h>
29#include <linux/regulator/of_regulator.h>
28#include <linux/regulator/consumer.h> 30#include <linux/regulator/consumer.h>
29#include <linux/regulator/driver.h> 31#include <linux/regulator/driver.h>
30#include <linux/regulator/machine.h> 32#include <linux/regulator/machine.h>
@@ -132,6 +134,33 @@ static struct regulator *get_device_regulator(struct device *dev)
132 return NULL; 134 return NULL;
133} 135}
134 136
137/**
138 * of_get_regulator - get a regulator device node based on supply name
139 * @dev: Device pointer for the consumer (of regulator) device
140 * @supply: regulator supply name
141 *
142 * Extract the regulator device node corresponding to the supply name.
143 * retruns the device node corresponding to the regulator if found, else
144 * returns NULL.
145 */
146static struct device_node *of_get_regulator(struct device *dev, const char *supply)
147{
148 struct device_node *regnode = NULL;
149 char prop_name[32]; /* 32 is max size of property name */
150
151 dev_dbg(dev, "Looking up %s-supply from device tree\n", supply);
152
153 snprintf(prop_name, 32, "%s-supply", supply);
154 regnode = of_parse_phandle(dev->of_node, prop_name, 0);
155
156 if (!regnode) {
157 dev_warn(dev, "%s property in node %s references invalid phandle",
158 prop_name, dev->of_node->full_name);
159 return NULL;
160 }
161 return regnode;
162}
163
135/* Platform voltage constraint check */ 164/* Platform voltage constraint check */
136static int regulator_check_voltage(struct regulator_dev *rdev, 165static int regulator_check_voltage(struct regulator_dev *rdev,
137 int *min_uV, int *max_uV) 166 int *min_uV, int *max_uV)
@@ -1148,6 +1177,30 @@ static int _regulator_get_enable_time(struct regulator_dev *rdev)
1148 return rdev->desc->ops->enable_time(rdev); 1177 return rdev->desc->ops->enable_time(rdev);
1149} 1178}
1150 1179
1180static struct regulator_dev *regulator_dev_lookup(struct device *dev,
1181 const char *supply)
1182{
1183 struct regulator_dev *r;
1184 struct device_node *node;
1185
1186 /* first do a dt based lookup */
1187 if (dev && dev->of_node) {
1188 node = of_get_regulator(dev, supply);
1189 if (node)
1190 list_for_each_entry(r, &regulator_list, list)
1191 if (r->dev.parent &&
1192 node == r->dev.of_node)
1193 return r;
1194 }
1195
1196 /* if not found, try doing it non-dt way */
1197 list_for_each_entry(r, &regulator_list, list)
1198 if (strcmp(rdev_get_name(r), supply) == 0)
1199 return r;
1200
1201 return NULL;
1202}
1203
1151/* Internal regulator request function */ 1204/* Internal regulator request function */
1152static struct regulator *_regulator_get(struct device *dev, const char *id, 1205static struct regulator *_regulator_get(struct device *dev, const char *id,
1153 int exclusive) 1206 int exclusive)
@@ -1168,6 +1221,10 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
1168 1221
1169 mutex_lock(&regulator_list_mutex); 1222 mutex_lock(&regulator_list_mutex);
1170 1223
1224 rdev = regulator_dev_lookup(dev, id);
1225 if (rdev)
1226 goto found;
1227
1171 list_for_each_entry(map, &regulator_map_list, list) { 1228 list_for_each_entry(map, &regulator_map_list, list) {
1172 /* If the mapping has a device set up it must match */ 1229 /* If the mapping has a device set up it must match */
1173 if (map->dev_name && 1230 if (map->dev_name &&
@@ -2642,6 +2699,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
2642 static atomic_t regulator_no = ATOMIC_INIT(0); 2699 static atomic_t regulator_no = ATOMIC_INIT(0);
2643 struct regulator_dev *rdev; 2700 struct regulator_dev *rdev;
2644 int ret, i; 2701 int ret, i;
2702 const char *supply = NULL;
2645 2703
2646 if (regulator_desc == NULL) 2704 if (regulator_desc == NULL)
2647 return ERR_PTR(-EINVAL); 2705 return ERR_PTR(-EINVAL);
@@ -2718,21 +2776,18 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
2718 if (ret < 0) 2776 if (ret < 0)
2719 goto scrub; 2777 goto scrub;
2720 2778
2721 if (init_data->supply_regulator) { 2779 if (init_data->supply_regulator)
2780 supply = init_data->supply_regulator;
2781 else if (regulator_desc->supply_name)
2782 supply = regulator_desc->supply_name;
2783
2784 if (supply) {
2722 struct regulator_dev *r; 2785 struct regulator_dev *r;
2723 int found = 0;
2724 2786
2725 list_for_each_entry(r, &regulator_list, list) { 2787 r = regulator_dev_lookup(dev, supply);
2726 if (strcmp(rdev_get_name(r),
2727 init_data->supply_regulator) == 0) {
2728 found = 1;
2729 break;
2730 }
2731 }
2732 2788
2733 if (!found) { 2789 if (!r) {
2734 dev_err(dev, "Failed to find supply %s\n", 2790 dev_err(dev, "Failed to find supply %s\n", supply);
2735 init_data->supply_regulator);
2736 ret = -ENODEV; 2791 ret = -ENODEV;
2737 goto scrub; 2792 goto scrub;
2738 } 2793 }