aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2014-09-09 18:13:57 -0400
committerMark Brown <broonie@kernel.org>2014-09-10 07:00:53 -0400
commita0c7b164ad115ec0556dc0904ee2218cbc5cedfa (patch)
treecf4f1e10eb3ec1ca72fc044d213b5be6f6124bb8
parent7d1311b93e58ed55f3a31cc8f94c4b8fe988a2b9 (diff)
regulator: of: Provide simplified DT parsing method
Currently regulator drivers which support DT all repeat very similar code to supply a list of known regulator identifiers to be matched with DT, convert that to platform data which is then matched up with the regulators as they are registered. This is both fiddly to get right and for devices which can use the standard helpers to provide their operations is the main source of code in the driver. Since this code is essentially identical for most drivers we can factor it out into the core, moving the identifiers in the match table into the regulator descriptors and also allowing drivers to pass in the name of the subnode to search. When a driver provides an of_match string for the regulator the core will attempt to use that to obtain init_data, allowing the driver to remove all explicit code for DT parsing and simply provide data instead. The current code leaks the phandles for the child nodes, this will be addressed incrementally and makes no practical difference for FDT anyway as the DT data structures are never freed. Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--drivers/regulator/core.c10
-rw-r--r--drivers/regulator/internal.h4
-rw-r--r--drivers/regulator/of_regulator.c51
-rw-r--r--include/linux/regulator/driver.h4
4 files changed, 66 insertions, 3 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index a3c3785901f5..496002efd961 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -3516,12 +3516,17 @@ regulator_register(const struct regulator_desc *regulator_desc,
3516 return ERR_PTR(-EINVAL); 3516 return ERR_PTR(-EINVAL);
3517 } 3517 }
3518 3518
3519 init_data = config->init_data;
3520
3521 rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3519 rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
3522 if (rdev == NULL) 3520 if (rdev == NULL)
3523 return ERR_PTR(-ENOMEM); 3521 return ERR_PTR(-ENOMEM);
3524 3522
3523 init_data = regulator_of_get_init_data(dev, regulator_desc,
3524 &rdev->dev.of_node);
3525 if (!init_data) {
3526 init_data = config->init_data;
3527 rdev->dev.of_node = of_node_get(config->of_node);
3528 }
3529
3525 mutex_lock(&regulator_list_mutex); 3530 mutex_lock(&regulator_list_mutex);
3526 3531
3527 mutex_init(&rdev->mutex); 3532 mutex_init(&rdev->mutex);
@@ -3548,7 +3553,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
3548 3553
3549 /* register with sysfs */ 3554 /* register with sysfs */
3550 rdev->dev.class = &regulator_class; 3555 rdev->dev.class = &regulator_class;
3551 rdev->dev.of_node = of_node_get(config->of_node);
3552 rdev->dev.parent = dev; 3556 rdev->dev.parent = dev;
3553 dev_set_name(&rdev->dev, "regulator.%d", 3557 dev_set_name(&rdev->dev, "regulator.%d",
3554 atomic_inc_return(&regulator_no) - 1); 3558 atomic_inc_return(&regulator_no) - 1);
diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h
index 84bbda10c396..a6043ad32ead 100644
--- a/drivers/regulator/internal.h
+++ b/drivers/regulator/internal.h
@@ -35,4 +35,8 @@ struct regulator {
35 struct dentry *debugfs; 35 struct dentry *debugfs;
36}; 36};
37 37
38struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
39 const struct regulator_desc *desc,
40 struct device_node **node);
41
38#endif 42#endif
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index ee5e67bc8d5b..7a51814abdc5 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -14,8 +14,11 @@
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/of.h> 15#include <linux/of.h>
16#include <linux/regulator/machine.h> 16#include <linux/regulator/machine.h>
17#include <linux/regulator/driver.h>
17#include <linux/regulator/of_regulator.h> 18#include <linux/regulator/of_regulator.h>
18 19
20#include "internal.h"
21
19static void of_get_regulation_constraints(struct device_node *np, 22static void of_get_regulation_constraints(struct device_node *np,
20 struct regulator_init_data **init_data) 23 struct regulator_init_data **init_data)
21{ 24{
@@ -189,3 +192,51 @@ int of_regulator_match(struct device *dev, struct device_node *node,
189 return count; 192 return count;
190} 193}
191EXPORT_SYMBOL_GPL(of_regulator_match); 194EXPORT_SYMBOL_GPL(of_regulator_match);
195
196struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
197 const struct regulator_desc *desc,
198 struct device_node **node)
199{
200 struct device_node *search, *child;
201 struct regulator_init_data *init_data = NULL;
202 const char *name;
203
204 if (!dev->of_node || !desc->of_match)
205 return NULL;
206
207 if (desc->regulators_node)
208 search = of_get_child_by_name(dev->of_node,
209 desc->regulators_node);
210 else
211 search = dev->of_node;
212
213 if (!search) {
214 dev_err(dev, "Failed to find regulator container node\n");
215 return NULL;
216 }
217
218 for_each_child_of_node(search, child) {
219 name = of_get_property(child, "regulator-compatible", NULL);
220 if (!name)
221 name = child->name;
222
223 if (strcmp(desc->of_match, name))
224 continue;
225
226 init_data = of_get_regulator_init_data(dev, child);
227 if (!init_data) {
228 dev_err(dev,
229 "failed to parse DT for regulator %s\n",
230 child->name);
231 break;
232 }
233
234 of_node_get(child);
235 *node = child;
236 break;
237 }
238
239 of_node_put(search);
240
241 return init_data;
242}
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index bbe03a1924c0..c35f5f97a147 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -203,6 +203,8 @@ enum regulator_type {
203 * 203 *
204 * @name: Identifying name for the regulator. 204 * @name: Identifying name for the regulator.
205 * @supply_name: Identifying the regulator supply 205 * @supply_name: Identifying the regulator supply
206 * @of_match: Name used to identify regulator in DT.
207 * @regulators_node: Name of node containing regulator definitions in DT.
206 * @id: Numerical identifier for the regulator. 208 * @id: Numerical identifier for the regulator.
207 * @ops: Regulator operations table. 209 * @ops: Regulator operations table.
208 * @irq: Interrupt number for the regulator. 210 * @irq: Interrupt number for the regulator.
@@ -242,6 +244,8 @@ enum regulator_type {
242struct regulator_desc { 244struct regulator_desc {
243 const char *name; 245 const char *name;
244 const char *supply_name; 246 const char *supply_name;
247 const char *of_match;
248 const char *regulators_node;
245 int id; 249 int id;
246 bool continuous_voltage_range; 250 bool continuous_voltage_range;
247 unsigned n_voltages; 251 unsigned n_voltages;