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"); | ||
