diff options
Diffstat (limited to 'drivers/regulator/s2mps11.c')
-rw-r--r-- | drivers/regulator/s2mps11.c | 113 |
1 files changed, 96 insertions, 17 deletions
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index e713c162fbd4..02e2fb2fca66 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/regulator/driver.h> | 27 | #include <linux/regulator/driver.h> |
28 | #include <linux/regulator/machine.h> | 28 | #include <linux/regulator/machine.h> |
29 | #include <linux/regulator/of_regulator.h> | 29 | #include <linux/regulator/of_regulator.h> |
30 | #include <linux/of_gpio.h> | ||
30 | #include <linux/mfd/samsung/core.h> | 31 | #include <linux/mfd/samsung/core.h> |
31 | #include <linux/mfd/samsung/s2mps11.h> | 32 | #include <linux/mfd/samsung/s2mps11.h> |
32 | #include <linux/mfd/samsung/s2mps14.h> | 33 | #include <linux/mfd/samsung/s2mps14.h> |
@@ -44,6 +45,8 @@ struct s2mps11_info { | |||
44 | * was enabled. | 45 | * was enabled. |
45 | */ | 46 | */ |
46 | unsigned int s2mps14_suspend_state:30; | 47 | unsigned int s2mps14_suspend_state:30; |
48 | /* Array of size rdev_num with GPIO-s for external sleep control */ | ||
49 | int *ext_control_gpio; | ||
47 | }; | 50 | }; |
48 | 51 | ||
49 | static int get_ramp_delay(int ramp_delay) | 52 | static int get_ramp_delay(int ramp_delay) |
@@ -202,11 +205,16 @@ static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) | |||
202 | if (!ramp_enable) | 205 | if (!ramp_enable) |
203 | goto ramp_disable; | 206 | goto ramp_disable; |
204 | 207 | ||
205 | ret = regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP, | 208 | /* Ramp delay can be enabled/disabled only for buck[2346] */ |
206 | 1 << enable_shift, 1 << enable_shift); | 209 | if ((rdev_get_id(rdev) >= S2MPS11_BUCK2 && |
207 | if (ret) { | 210 | rdev_get_id(rdev) <= S2MPS11_BUCK4) || |
208 | dev_err(&rdev->dev, "failed to enable ramp rate\n"); | 211 | rdev_get_id(rdev) == S2MPS11_BUCK6) { |
209 | return ret; | 212 | ret = regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP, |
213 | 1 << enable_shift, 1 << enable_shift); | ||
214 | if (ret) { | ||
215 | dev_err(&rdev->dev, "failed to enable ramp rate\n"); | ||
216 | return ret; | ||
217 | } | ||
210 | } | 218 | } |
211 | 219 | ||
212 | ramp_val = get_ramp_delay(ramp_delay); | 220 | ramp_val = get_ramp_delay(ramp_delay); |
@@ -409,6 +417,8 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev) | |||
409 | 417 | ||
410 | if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev))) | 418 | if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev))) |
411 | val = S2MPS14_ENABLE_SUSPEND; | 419 | val = S2MPS14_ENABLE_SUSPEND; |
420 | else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)])) | ||
421 | val = S2MPS14_ENABLE_EXT_CONTROL; | ||
412 | else | 422 | else |
413 | val = rdev->desc->enable_mask; | 423 | val = rdev->desc->enable_mask; |
414 | 424 | ||
@@ -565,12 +575,61 @@ static const struct regulator_desc s2mps14_regulators[] = { | |||
565 | regulator_desc_s2mps14_buck1235(5), | 575 | regulator_desc_s2mps14_buck1235(5), |
566 | }; | 576 | }; |
567 | 577 | ||
578 | static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11, | ||
579 | struct regulator_dev *rdev) | ||
580 | { | ||
581 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | ||
582 | rdev->desc->enable_mask, S2MPS14_ENABLE_EXT_CONTROL); | ||
583 | } | ||
584 | |||
585 | static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev, | ||
586 | struct of_regulator_match *rdata, struct s2mps11_info *s2mps11) | ||
587 | { | ||
588 | int *gpio = s2mps11->ext_control_gpio; | ||
589 | unsigned int i; | ||
590 | unsigned int valid_regulators[3] = { S2MPS14_LDO10, S2MPS14_LDO11, | ||
591 | S2MPS14_LDO12 }; | ||
592 | |||
593 | for (i = 0; i < ARRAY_SIZE(valid_regulators); i++) { | ||
594 | unsigned int reg = valid_regulators[i]; | ||
595 | |||
596 | if (!rdata[reg].init_data || !rdata[reg].of_node) | ||
597 | continue; | ||
598 | |||
599 | gpio[reg] = of_get_named_gpio(rdata[reg].of_node, | ||
600 | "samsung,ext-control-gpios", 0); | ||
601 | if (gpio_is_valid(gpio[reg])) | ||
602 | dev_dbg(&pdev->dev, "Using GPIO %d for ext-control over %d/%s\n", | ||
603 | gpio[reg], reg, rdata[reg].name); | ||
604 | } | ||
605 | } | ||
606 | |||
607 | static int s2mps11_pmic_dt_parse(struct platform_device *pdev, | ||
608 | struct of_regulator_match *rdata, struct s2mps11_info *s2mps11, | ||
609 | enum sec_device_type dev_type) | ||
610 | { | ||
611 | struct device_node *reg_np; | ||
612 | |||
613 | reg_np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators"); | ||
614 | if (!reg_np) { | ||
615 | dev_err(&pdev->dev, "could not find regulators sub-node\n"); | ||
616 | return -EINVAL; | ||
617 | } | ||
618 | |||
619 | of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num); | ||
620 | if (dev_type == S2MPS14X) | ||
621 | s2mps14_pmic_dt_parse_ext_control_gpio(pdev, rdata, s2mps11); | ||
622 | |||
623 | of_node_put(reg_np); | ||
624 | |||
625 | return 0; | ||
626 | } | ||
627 | |||
568 | static int s2mps11_pmic_probe(struct platform_device *pdev) | 628 | static int s2mps11_pmic_probe(struct platform_device *pdev) |
569 | { | 629 | { |
570 | struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); | 630 | struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); |
571 | struct sec_platform_data *pdata = iodev->pdata; | 631 | struct sec_platform_data *pdata = NULL; |
572 | struct of_regulator_match *rdata = NULL; | 632 | struct of_regulator_match *rdata = NULL; |
573 | struct device_node *reg_np = NULL; | ||
574 | struct regulator_config config = { }; | 633 | struct regulator_config config = { }; |
575 | struct s2mps11_info *s2mps11; | 634 | struct s2mps11_info *s2mps11; |
576 | int i, ret = 0; | 635 | int i, ret = 0; |
@@ -597,8 +656,21 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) | |||
597 | return -EINVAL; | 656 | return -EINVAL; |
598 | }; | 657 | }; |
599 | 658 | ||
659 | s2mps11->ext_control_gpio = devm_kzalloc(&pdev->dev, | ||
660 | sizeof(*s2mps11->ext_control_gpio) * s2mps11->rdev_num, | ||
661 | GFP_KERNEL); | ||
662 | if (!s2mps11->ext_control_gpio) | ||
663 | return -ENOMEM; | ||
664 | /* | ||
665 | * 0 is a valid GPIO so initialize all GPIO-s to negative value | ||
666 | * to indicate that external control won't be used for this regulator. | ||
667 | */ | ||
668 | for (i = 0; i < s2mps11->rdev_num; i++) | ||
669 | s2mps11->ext_control_gpio[i] = -EINVAL; | ||
670 | |||
600 | if (!iodev->dev->of_node) { | 671 | if (!iodev->dev->of_node) { |
601 | if (pdata) { | 672 | if (iodev->pdata) { |
673 | pdata = iodev->pdata; | ||
602 | goto common_reg; | 674 | goto common_reg; |
603 | } else { | 675 | } else { |
604 | dev_err(pdev->dev.parent, | 676 | dev_err(pdev->dev.parent, |
@@ -614,15 +686,9 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) | |||
614 | for (i = 0; i < s2mps11->rdev_num; i++) | 686 | for (i = 0; i < s2mps11->rdev_num; i++) |
615 | rdata[i].name = regulators[i].name; | 687 | rdata[i].name = regulators[i].name; |
616 | 688 | ||
617 | reg_np = of_get_child_by_name(iodev->dev->of_node, "regulators"); | 689 | ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11, dev_type); |
618 | if (!reg_np) { | 690 | if (ret) |
619 | dev_err(&pdev->dev, "could not find regulators sub-node\n"); | ||
620 | ret = -EINVAL; | ||
621 | goto out; | 691 | goto out; |
622 | } | ||
623 | |||
624 | of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num); | ||
625 | of_node_put(reg_np); | ||
626 | 692 | ||
627 | common_reg: | 693 | common_reg: |
628 | platform_set_drvdata(pdev, s2mps11); | 694 | platform_set_drvdata(pdev, s2mps11); |
@@ -630,16 +696,18 @@ common_reg: | |||
630 | config.dev = &pdev->dev; | 696 | config.dev = &pdev->dev; |
631 | config.regmap = iodev->regmap_pmic; | 697 | config.regmap = iodev->regmap_pmic; |
632 | config.driver_data = s2mps11; | 698 | config.driver_data = s2mps11; |
699 | config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH; | ||
633 | for (i = 0; i < s2mps11->rdev_num; i++) { | 700 | for (i = 0; i < s2mps11->rdev_num; i++) { |
634 | struct regulator_dev *regulator; | 701 | struct regulator_dev *regulator; |
635 | 702 | ||
636 | if (!reg_np) { | 703 | if (pdata) { |
637 | config.init_data = pdata->regulators[i].initdata; | 704 | config.init_data = pdata->regulators[i].initdata; |
638 | config.of_node = pdata->regulators[i].reg_node; | 705 | config.of_node = pdata->regulators[i].reg_node; |
639 | } else { | 706 | } else { |
640 | config.init_data = rdata[i].init_data; | 707 | config.init_data = rdata[i].init_data; |
641 | config.of_node = rdata[i].of_node; | 708 | config.of_node = rdata[i].of_node; |
642 | } | 709 | } |
710 | config.ena_gpio = s2mps11->ext_control_gpio[i]; | ||
643 | 711 | ||
644 | regulator = devm_regulator_register(&pdev->dev, | 712 | regulator = devm_regulator_register(&pdev->dev, |
645 | ®ulators[i], &config); | 713 | ®ulators[i], &config); |
@@ -649,6 +717,17 @@ common_reg: | |||
649 | i); | 717 | i); |
650 | goto out; | 718 | goto out; |
651 | } | 719 | } |
720 | |||
721 | if (gpio_is_valid(s2mps11->ext_control_gpio[i])) { | ||
722 | ret = s2mps14_pmic_enable_ext_control(s2mps11, | ||
723 | regulator); | ||
724 | if (ret < 0) { | ||
725 | dev_err(&pdev->dev, | ||
726 | "failed to enable GPIO control over %s: %d\n", | ||
727 | regulator->desc->name, ret); | ||
728 | goto out; | ||
729 | } | ||
730 | } | ||
652 | } | 731 | } |
653 | 732 | ||
654 | out: | 733 | out: |