diff options
author | Shawn Guo <shawn.guo@linaro.org> | 2011-12-21 10:00:46 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-12-22 06:10:45 -0500 |
commit | 93bcb23b38f634e8fb4ddda0d3f4862fda5cedae (patch) | |
tree | 9f087497a7511022c8e740c3e16bb3703efc4fda /drivers/regulator | |
parent | 3a5d03158d0174ae700e15b63eab2023f27aeb88 (diff) |
regulator: mc13892: add device tree probe support
It adds device tree probe support for mc13892-regulator driver.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/mc13892-regulator.c | 43 | ||||
-rw-r--r-- | drivers/regulator/mc13xxx-regulator-core.c | 57 | ||||
-rw-r--r-- | drivers/regulator/mc13xxx.h | 20 |
3 files changed, 109 insertions, 11 deletions
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 2824804a2892..46bfa4ae2afd 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c | |||
@@ -527,18 +527,27 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) | |||
527 | struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent); | 527 | struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent); |
528 | struct mc13xxx_regulator_platform_data *pdata = | 528 | struct mc13xxx_regulator_platform_data *pdata = |
529 | dev_get_platdata(&pdev->dev); | 529 | dev_get_platdata(&pdev->dev); |
530 | struct mc13xxx_regulator_init_data *init_data; | 530 | struct mc13xxx_regulator_init_data *mc13xxx_data; |
531 | int i, ret; | 531 | int i, ret; |
532 | int num_regulators = 0; | ||
532 | u32 val; | 533 | u32 val; |
533 | 534 | ||
535 | num_regulators = mc13xxx_get_num_regulators_dt(pdev); | ||
536 | if (num_regulators <= 0 && pdata) | ||
537 | num_regulators = pdata->num_regulators; | ||
538 | if (num_regulators <= 0) | ||
539 | return -EINVAL; | ||
540 | |||
534 | priv = kzalloc(sizeof(*priv) + | 541 | priv = kzalloc(sizeof(*priv) + |
535 | pdata->num_regulators * sizeof(priv->regulators[0]), | 542 | num_regulators * sizeof(priv->regulators[0]), |
536 | GFP_KERNEL); | 543 | GFP_KERNEL); |
537 | if (!priv) | 544 | if (!priv) |
538 | return -ENOMEM; | 545 | return -ENOMEM; |
539 | 546 | ||
547 | priv->num_regulators = num_regulators; | ||
540 | priv->mc13xxx_regulators = mc13892_regulators; | 548 | priv->mc13xxx_regulators = mc13892_regulators; |
541 | priv->mc13xxx = mc13892; | 549 | priv->mc13xxx = mc13892; |
550 | platform_set_drvdata(pdev, priv); | ||
542 | 551 | ||
543 | mc13xxx_lock(mc13892); | 552 | mc13xxx_lock(mc13892); |
544 | ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val); | 553 | ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val); |
@@ -569,11 +578,27 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) | |||
569 | = mc13892_vcam_set_mode; | 578 | = mc13892_vcam_set_mode; |
570 | mc13892_regulators[MC13892_VCAM].desc.ops->get_mode | 579 | mc13892_regulators[MC13892_VCAM].desc.ops->get_mode |
571 | = mc13892_vcam_get_mode; | 580 | = mc13892_vcam_get_mode; |
572 | for (i = 0; i < pdata->num_regulators; i++) { | 581 | |
573 | init_data = &pdata->regulators[i]; | 582 | mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators, |
583 | ARRAY_SIZE(mc13892_regulators)); | ||
584 | for (i = 0; i < num_regulators; i++) { | ||
585 | struct regulator_init_data *init_data; | ||
586 | struct regulator_desc *desc; | ||
587 | struct device_node *node = NULL; | ||
588 | int id; | ||
589 | |||
590 | if (mc13xxx_data) { | ||
591 | id = mc13xxx_data[i].id; | ||
592 | init_data = mc13xxx_data[i].init_data; | ||
593 | node = mc13xxx_data[i].node; | ||
594 | } else { | ||
595 | id = pdata->regulators[i].id; | ||
596 | init_data = pdata->regulators[i].init_data; | ||
597 | } | ||
598 | desc = &mc13892_regulators[id].desc; | ||
599 | |||
574 | priv->regulators[i] = regulator_register( | 600 | priv->regulators[i] = regulator_register( |
575 | &mc13892_regulators[init_data->id].desc, | 601 | desc, &pdev->dev, init_data, priv, node); |
576 | &pdev->dev, init_data->init_data, priv, NULL); | ||
577 | 602 | ||
578 | if (IS_ERR(priv->regulators[i])) { | 603 | if (IS_ERR(priv->regulators[i])) { |
579 | dev_err(&pdev->dev, "failed to register regulator %s\n", | 604 | dev_err(&pdev->dev, "failed to register regulator %s\n", |
@@ -583,8 +608,6 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) | |||
583 | } | 608 | } |
584 | } | 609 | } |
585 | 610 | ||
586 | platform_set_drvdata(pdev, priv); | ||
587 | |||
588 | return 0; | 611 | return 0; |
589 | err: | 612 | err: |
590 | while (--i >= 0) | 613 | while (--i >= 0) |
@@ -600,13 +623,11 @@ err_free: | |||
600 | static int __devexit mc13892_regulator_remove(struct platform_device *pdev) | 623 | static int __devexit mc13892_regulator_remove(struct platform_device *pdev) |
601 | { | 624 | { |
602 | struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); | 625 | struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); |
603 | struct mc13xxx_regulator_platform_data *pdata = | ||
604 | dev_get_platdata(&pdev->dev); | ||
605 | int i; | 626 | int i; |
606 | 627 | ||
607 | platform_set_drvdata(pdev, NULL); | 628 | platform_set_drvdata(pdev, NULL); |
608 | 629 | ||
609 | for (i = 0; i < pdata->num_regulators; i++) | 630 | for (i = 0; i < priv->num_regulators; i++) |
610 | regulator_unregister(priv->regulators[i]); | 631 | regulator_unregister(priv->regulators[i]); |
611 | 632 | ||
612 | kfree(priv); | 633 | kfree(priv); |
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index 6532853a6ef5..80ecafef1bc3 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c | |||
@@ -18,12 +18,14 @@ | |||
18 | #include <linux/mfd/mc13xxx.h> | 18 | #include <linux/mfd/mc13xxx.h> |
19 | #include <linux/regulator/machine.h> | 19 | #include <linux/regulator/machine.h> |
20 | #include <linux/regulator/driver.h> | 20 | #include <linux/regulator/driver.h> |
21 | #include <linux/regulator/of_regulator.h> | ||
21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
22 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
23 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
24 | #include <linux/init.h> | 25 | #include <linux/init.h> |
25 | #include <linux/err.h> | 26 | #include <linux/err.h> |
26 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/of.h> | ||
27 | #include "mc13xxx.h" | 29 | #include "mc13xxx.h" |
28 | 30 | ||
29 | static int mc13xxx_regulator_enable(struct regulator_dev *rdev) | 31 | static int mc13xxx_regulator_enable(struct regulator_dev *rdev) |
@@ -236,6 +238,61 @@ int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev) | |||
236 | } | 238 | } |
237 | EXPORT_SYMBOL_GPL(mc13xxx_sw_regulator_is_enabled); | 239 | EXPORT_SYMBOL_GPL(mc13xxx_sw_regulator_is_enabled); |
238 | 240 | ||
241 | #ifdef CONFIG_OF | ||
242 | int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev) | ||
243 | { | ||
244 | struct device_node *parent, *child; | ||
245 | int num = 0; | ||
246 | |||
247 | of_node_get(pdev->dev.parent->of_node); | ||
248 | parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); | ||
249 | if (!parent) | ||
250 | return -ENODEV; | ||
251 | |||
252 | for_each_child_of_node(parent, child) | ||
253 | num++; | ||
254 | |||
255 | return num; | ||
256 | } | ||
257 | |||
258 | struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt( | ||
259 | struct platform_device *pdev, struct mc13xxx_regulator *regulators, | ||
260 | int num_regulators) | ||
261 | { | ||
262 | struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); | ||
263 | struct mc13xxx_regulator_init_data *data, *p; | ||
264 | struct device_node *parent, *child; | ||
265 | int i; | ||
266 | |||
267 | of_node_get(pdev->dev.parent->of_node); | ||
268 | parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); | ||
269 | if (!parent) | ||
270 | return NULL; | ||
271 | |||
272 | data = devm_kzalloc(&pdev->dev, sizeof(*data) * priv->num_regulators, | ||
273 | GFP_KERNEL); | ||
274 | if (!data) | ||
275 | return NULL; | ||
276 | p = data; | ||
277 | |||
278 | for_each_child_of_node(parent, child) { | ||
279 | for (i = 0; i < num_regulators; i++) { | ||
280 | if (!of_node_cmp(child->name, | ||
281 | regulators[i].desc.name)) { | ||
282 | p->id = i; | ||
283 | p->init_data = of_get_regulator_init_data( | ||
284 | &pdev->dev, child); | ||
285 | p->node = child; | ||
286 | p++; | ||
287 | break; | ||
288 | } | ||
289 | } | ||
290 | } | ||
291 | |||
292 | return data; | ||
293 | } | ||
294 | #endif | ||
295 | |||
239 | MODULE_LICENSE("GPL v2"); | 296 | MODULE_LICENSE("GPL v2"); |
240 | MODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>"); | 297 | MODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>"); |
241 | MODULE_DESCRIPTION("Regulator Driver for Freescale MC13xxx PMIC"); | 298 | MODULE_DESCRIPTION("Regulator Driver for Freescale MC13xxx PMIC"); |
diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h index 75e383226a87..b3961c658b05 100644 --- a/drivers/regulator/mc13xxx.h +++ b/drivers/regulator/mc13xxx.h | |||
@@ -29,6 +29,7 @@ struct mc13xxx_regulator_priv { | |||
29 | struct mc13xxx *mc13xxx; | 29 | struct mc13xxx *mc13xxx; |
30 | u32 powermisc_pwgt_state; | 30 | u32 powermisc_pwgt_state; |
31 | struct mc13xxx_regulator *mc13xxx_regulators; | 31 | struct mc13xxx_regulator *mc13xxx_regulators; |
32 | int num_regulators; | ||
32 | struct regulator_dev *regulators[]; | 33 | struct regulator_dev *regulators[]; |
33 | }; | 34 | }; |
34 | 35 | ||
@@ -42,6 +43,25 @@ extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, | |||
42 | int min_uV, int max_uV, unsigned *selector); | 43 | int min_uV, int max_uV, unsigned *selector); |
43 | extern int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev); | 44 | extern int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev); |
44 | 45 | ||
46 | #ifdef CONFIG_OF | ||
47 | extern int mc13xxx_get_num_regulators_dt(struct platform_device *pdev); | ||
48 | extern struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( | ||
49 | struct platform_device *pdev, struct mc13xxx_regulator *regulators, | ||
50 | int num_regulators); | ||
51 | #else | ||
52 | static inline int mc13xxx_get_num_regulators_dt(struct platform_device *pdev) | ||
53 | { | ||
54 | return -ENODEV; | ||
55 | } | ||
56 | |||
57 | static inline struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( | ||
58 | struct platform_device *pdev, struct mc13xxx_regulator *regulators, | ||
59 | int num_regulators) | ||
60 | { | ||
61 | return NULL; | ||
62 | } | ||
63 | #endif | ||
64 | |||
45 | extern struct regulator_ops mc13xxx_regulator_ops; | 65 | extern struct regulator_ops mc13xxx_regulator_ops; |
46 | extern struct regulator_ops mc13xxx_fixed_regulator_ops; | 66 | extern struct regulator_ops mc13xxx_fixed_regulator_ops; |
47 | 67 | ||