aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorAmit Daniel Kachhap <amit.daniel@samsung.com>2013-02-03 18:49:47 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-02-04 05:31:31 -0500
commit26aec009f6b61c077c6de1a96cca7a5132851dbe (patch)
tree4d5ea32c3df9eee4a314403a4a82456866d434c8 /drivers/regulator
parent31a932e1079d771df6c2daf0b8a871b9b34d7e83 (diff)
regulator: add device tree support for s5m8767
This device tree support is added for PMIC block of S5m8767 multi function driver. The usage detail is added in the device tree documentation section. This change is tested on exynos5250 based arndale platform by regulator voltage set/get API's. Reviewed-by: Thomas Abraham <thomas.abraham@linaro.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Tested-by: Sachin Kamat <sachin.kamat@linaro.org> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/s5m8767.c186
1 files changed, 185 insertions, 1 deletions
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index aa0ccef5c31c..1250cef43d7b 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -14,6 +14,7 @@
14#include <linux/bug.h> 14#include <linux/bug.h>
15#include <linux/err.h> 15#include <linux/err.h>
16#include <linux/gpio.h> 16#include <linux/gpio.h>
17#include <linux/of_gpio.h>
17#include <linux/slab.h> 18#include <linux/slab.h>
18#include <linux/module.h> 19#include <linux/module.h>
19#include <linux/platform_device.h> 20#include <linux/platform_device.h>
@@ -21,6 +22,9 @@
21#include <linux/regulator/machine.h> 22#include <linux/regulator/machine.h>
22#include <linux/mfd/samsung/core.h> 23#include <linux/mfd/samsung/core.h>
23#include <linux/mfd/samsung/s5m8767.h> 24#include <linux/mfd/samsung/s5m8767.h>
25#include <linux/regulator/of_regulator.h>
26
27#define S5M8767_OPMODE_NORMAL_MODE 0x1
24 28
25struct s5m8767_info { 29struct s5m8767_info {
26 struct device *dev; 30 struct device *dev;
@@ -474,15 +478,194 @@ static struct regulator_desc regulators[] = {
474 s5m8767_regulator_desc(BUCK9), 478 s5m8767_regulator_desc(BUCK9),
475}; 479};
476 480
481#ifdef CONFIG_OF
482static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev,
483 struct sec_platform_data *pdata,
484 struct device_node *pmic_np)
485{
486 int i, gpio;
487
488 for (i = 0; i < 3; i++) {
489 gpio = of_get_named_gpio(pmic_np,
490 "s5m8767,pmic-buck-dvs-gpios", i);
491 if (!gpio_is_valid(gpio)) {
492 dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio);
493 return -EINVAL;
494 }
495 pdata->buck_gpios[i] = gpio;
496 }
497 return 0;
498}
499
500static int s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev *iodev,
501 struct sec_platform_data *pdata,
502 struct device_node *pmic_np)
503{
504 int i, gpio;
505
506 for (i = 0; i < 3; i++) {
507 gpio = of_get_named_gpio(pmic_np,
508 "s5m8767,pmic-buck-ds-gpios", i);
509 if (!gpio_is_valid(gpio)) {
510 dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio);
511 return -EINVAL;
512 }
513 pdata->buck_ds[i] = gpio;
514 }
515 return 0;
516}
517
518static int s5m8767_pmic_dt_parse_pdata(struct sec_pmic_dev *iodev,
519 struct sec_platform_data *pdata)
520{
521 struct device_node *pmic_np, *regulators_np, *reg_np;
522 struct sec_regulator_data *rdata;
523 struct sec_opmode_data *rmode;
524 unsigned int i, dvs_voltage_nr = 1, ret;
525
526 pmic_np = iodev->dev->of_node;
527 if (!pmic_np) {
528 dev_err(iodev->dev, "could not find pmic sub-node\n");
529 return -ENODEV;
530 }
531
532 regulators_np = of_find_node_by_name(pmic_np, "regulators");
533 if (!regulators_np) {
534 dev_err(iodev->dev, "could not find regulators sub-node\n");
535 return -EINVAL;
536 }
537
538 /* count the number of regulators to be supported in pmic */
539 pdata->num_regulators = 0;
540 for_each_child_of_node(regulators_np, reg_np)
541 pdata->num_regulators++;
542
543 rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
544 pdata->num_regulators, GFP_KERNEL);
545 if (!rdata) {
546 dev_err(iodev->dev,
547 "could not allocate memory for regulator data\n");
548 return -ENOMEM;
549 }
550
551 rmode = devm_kzalloc(iodev->dev, sizeof(*rmode) *
552 pdata->num_regulators, GFP_KERNEL);
553 if (!rdata) {
554 dev_err(iodev->dev,
555 "could not allocate memory for regulator mode\n");
556 return -ENOMEM;
557 }
558
559 pdata->regulators = rdata;
560 pdata->opmode = rmode;
561 for_each_child_of_node(regulators_np, reg_np) {
562 for (i = 0; i < ARRAY_SIZE(regulators); i++)
563 if (!of_node_cmp(reg_np->name, regulators[i].name))
564 break;
565
566 if (i == ARRAY_SIZE(regulators)) {
567 dev_warn(iodev->dev,
568 "don't know how to configure regulator %s\n",
569 reg_np->name);
570 continue;
571 }
572
573 rdata->id = i;
574 rdata->initdata = of_get_regulator_init_data(
575 iodev->dev, reg_np);
576 rdata->reg_node = reg_np;
577 rdata++;
578 rmode->id = i;
579 if (of_property_read_u32(reg_np, "op_mode",
580 &rmode->mode)) {
581 dev_warn(iodev->dev,
582 "no op_mode property property at %s\n",
583 reg_np->full_name);
584
585 rmode->mode = S5M8767_OPMODE_NORMAL_MODE;
586 }
587 rmode++;
588 }
589
590 if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL))
591 pdata->buck2_gpiodvs = true;
592
593 if (of_get_property(pmic_np, "s5m8767,pmic-buck3-uses-gpio-dvs", NULL))
594 pdata->buck3_gpiodvs = true;
595
596 if (of_get_property(pmic_np, "s5m8767,pmic-buck4-uses-gpio-dvs", NULL))
597 pdata->buck4_gpiodvs = true;
598
599 if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
600 pdata->buck4_gpiodvs) {
601 ret = s5m8767_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
602 if (ret)
603 return -EINVAL;
604
605 if (of_property_read_u32(pmic_np,
606 "s5m8767,pmic-buck-default-dvs-idx",
607 &pdata->buck_default_idx)) {
608 pdata->buck_default_idx = 0;
609 } else {
610 if (pdata->buck_default_idx >= 8) {
611 pdata->buck_default_idx = 0;
612 dev_info(iodev->dev,
613 "invalid value for default dvs index, use 0\n");
614 }
615 }
616 dvs_voltage_nr = 8;
617 }
618
619 ret = s5m8767_pmic_dt_parse_ds_gpio(iodev, pdata, pmic_np);
620 if (ret)
621 return -EINVAL;
622
623 if (of_property_read_u32_array(pmic_np,
624 "s5m8767,pmic-buck2-dvs-voltage",
625 pdata->buck2_voltage, dvs_voltage_nr)) {
626 dev_err(iodev->dev, "buck2 voltages not specified\n");
627 return -EINVAL;
628 }
629
630 if (of_property_read_u32_array(pmic_np,
631 "s5m8767,pmic-buck3-dvs-voltage",
632 pdata->buck3_voltage, dvs_voltage_nr)) {
633 dev_err(iodev->dev, "buck3 voltages not specified\n");
634 return -EINVAL;
635 }
636
637 if (of_property_read_u32_array(pmic_np,
638 "s5m8767,pmic-buck4-dvs-voltage",
639 pdata->buck4_voltage, dvs_voltage_nr)) {
640 dev_err(iodev->dev, "buck4 voltages not specified\n");
641 return -EINVAL;
642 }
643
644 return 0;
645}
646#else
647static int s5m8767_pmic_dt_parse_pdata(struct sec_pmic_dev *iodev,
648 struct sec_platform_data *pdata)
649{
650 return 0;
651}
652#endif /* CONFIG_OF */
653
477static int s5m8767_pmic_probe(struct platform_device *pdev) 654static int s5m8767_pmic_probe(struct platform_device *pdev)
478{ 655{
479 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); 656 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
480 struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); 657 struct sec_platform_data *pdata = iodev->pdata;
481 struct regulator_config config = { }; 658 struct regulator_config config = { };
482 struct regulator_dev **rdev; 659 struct regulator_dev **rdev;
483 struct s5m8767_info *s5m8767; 660 struct s5m8767_info *s5m8767;
484 int i, ret, size, buck_init; 661 int i, ret, size, buck_init;
485 662
663 if (iodev->dev->of_node) {
664 ret = s5m8767_pmic_dt_parse_pdata(iodev, pdata);
665 if (ret)
666 return ret;
667 }
668
486 if (!pdata) { 669 if (!pdata) {
487 dev_err(pdev->dev.parent, "Platform data not supplied\n"); 670 dev_err(pdev->dev.parent, "Platform data not supplied\n");
488 return -ENODEV; 671 return -ENODEV;
@@ -726,6 +909,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
726 config.init_data = pdata->regulators[i].initdata; 909 config.init_data = pdata->regulators[i].initdata;
727 config.driver_data = s5m8767; 910 config.driver_data = s5m8767;
728 config.regmap = iodev->regmap; 911 config.regmap = iodev->regmap;
912 config.of_node = pdata->regulators[i].reg_node;
729 913
730 rdev[i] = regulator_register(&regulators[id], &config); 914 rdev[i] = regulator_register(&regulators[id], &config);
731 if (IS_ERR(rdev[i])) { 915 if (IS_ERR(rdev[i])) {