Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Amit Daniel Kachhap and committed by
Mark Brown
26aec009 31a932e1

+416 -6
+152
Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt
··· 1 + * Samsung S5M8767 Voltage and Current Regulator 2 + 3 + The Samsung S5M8767 is a multi-function device which includes volatage and 4 + current regulators, rtc, charger controller and other sub-blocks. It is 5 + interfaced to the host controller using a i2c interface. Each sub-block is 6 + addressed by the host system using different i2c slave address. This document 7 + describes the bindings for 'pmic' sub-block of s5m8767. 8 + 9 + Required properties: 10 + - compatible: Should be "samsung,s5m8767-pmic". 11 + - reg: Specifies the i2c slave address of the pmic block. It should be 0x66. 12 + 13 + - s5m8767,pmic-buck2-dvs-voltage: A set of 8 voltage values in micro-volt (uV) 14 + units for buck2 when changing voltage using gpio dvs. Refer to [1] below 15 + for additional information. 16 + 17 + - s5m8767,pmic-buck3-dvs-voltage: A set of 8 voltage values in micro-volt (uV) 18 + units for buck3 when changing voltage using gpio dvs. Refer to [1] below 19 + for additional information. 20 + 21 + - s5m8767,pmic-buck4-dvs-voltage: A set of 8 voltage values in micro-volt (uV) 22 + units for buck4 when changing voltage using gpio dvs. Refer to [1] below 23 + for additional information. 24 + 25 + - s5m8767,pmic-buck-ds-gpios: GPIO specifiers for three host gpio's used 26 + for selecting GPIO DVS lines. It is one-to-one mapped to dvs gpio lines. 27 + 28 + [1] If none of the 's5m8767,pmic-buck[2/3/4]-uses-gpio-dvs' optional 29 + property is specified, the 's5m8767,pmic-buck[2/3/4]-dvs-voltage' 30 + property should specify atleast one voltage level (which would be a 31 + safe operating voltage). 32 + 33 + If either of the 's5m8767,pmic-buck[2/3/4]-uses-gpio-dvs' optional 34 + property is specified, then all the eight voltage values for the 35 + 's5m8767,pmic-buck[2/3/4]-dvs-voltage' should be specified. 36 + 37 + Optional properties: 38 + - interrupt-parent: Specifies the phandle of the interrupt controller to which 39 + the interrupts from s5m8767 are delivered to. 40 + - interrupts: Interrupt specifiers for two interrupt sources. 41 + - First interrupt specifier is for 'irq1' interrupt. 42 + - Second interrupt specifier is for 'alert' interrupt. 43 + - s5m8767,pmic-buck2-uses-gpio-dvs: 'buck2' can be controlled by gpio dvs. 44 + - s5m8767,pmic-buck3-uses-gpio-dvs: 'buck3' can be controlled by gpio dvs. 45 + - s5m8767,pmic-buck4-uses-gpio-dvs: 'buck4' can be controlled by gpio dvs. 46 + 47 + Additional properties required if either of the optional properties are used: 48 + 49 + - s5m8767,pmic-buck234-default-dvs-idx: Default voltage setting selected from 50 + the possible 8 options selectable by the dvs gpios. The value of this 51 + property should be between 0 and 7. If not specified or if out of range, the 52 + default value of this property is set to 0. 53 + 54 + - s5m8767,pmic-buck-dvs-gpios: GPIO specifiers for three host gpio's used 55 + for dvs. The format of the gpio specifier depends in the gpio controller. 56 + 57 + Regulators: The regulators of s5m8767 that have to be instantiated should be 58 + included in a sub-node named 'regulators'. Regulator nodes included in this 59 + sub-node should be of the format as listed below. 60 + 61 + regulator_name { 62 + ldo1_reg: LDO1 { 63 + regulator-name = "VDD_ALIVE_1.0V"; 64 + regulator-min-microvolt = <1100000>; 65 + regulator-max-microvolt = <1100000>; 66 + regulator-always-on; 67 + regulator-boot-on; 68 + op_mode = <1>; /* Normal Mode */ 69 + }; 70 + }; 71 + The above regulator entries are defined in regulator bindings documentation 72 + except op_mode description. 73 + - op_mode: describes the different operating modes of the LDO's with 74 + power mode change in SOC. The different possible values are, 75 + 0 - always off mode 76 + 1 - on in normal mode 77 + 2 - low power mode 78 + 3 - suspend mode 79 + 80 + The following are the names of the regulators that the s5m8767 pmic block 81 + supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number 82 + as per the datasheet of s5m8767. 83 + 84 + - LDOn 85 + - valid values for n are 1 to 28 86 + - Example: LDO0, LD01, LDO28 87 + - BUCKn 88 + - valid values for n are 1 to 9. 89 + - Example: BUCK1, BUCK2, BUCK9 90 + 91 + The bindings inside the regulator nodes use the standard regulator bindings 92 + which are documented elsewhere. 93 + 94 + Example: 95 + 96 + s5m8767_pmic@66 { 97 + compatible = "samsung,s5m8767-pmic"; 98 + reg = <0x66>; 99 + 100 + s5m8767,pmic-buck2-uses-gpio-dvs; 101 + s5m8767,pmic-buck3-uses-gpio-dvs; 102 + s5m8767,pmic-buck4-uses-gpio-dvs; 103 + 104 + s5m8767,pmic-buck-default-dvs-idx = <0>; 105 + 106 + s5m8767,pmic-buck-dvs-gpios = <&gpx0 0 1 0 0>, /* DVS1 */ 107 + <&gpx0 1 1 0 0>, /* DVS2 */ 108 + <&gpx0 2 1 0 0>; /* DVS3 */ 109 + 110 + s5m8767,pmic-buck-ds-gpios = <&gpx2 3 1 0 0>, /* SET1 */ 111 + <&gpx2 4 1 0 0>, /* SET2 */ 112 + <&gpx2 5 1 0 0>; /* SET3 */ 113 + 114 + s5m8767,pmic-buck2-dvs-voltage = <1350000>, <1300000>, 115 + <1250000>, <1200000>, 116 + <1150000>, <1100000>, 117 + <1000000>, <950000>; 118 + 119 + s5m8767,pmic-buck3-dvs-voltage = <1100000>, <1100000>, 120 + <1100000>, <1100000>, 121 + <1000000>, <1000000>, 122 + <1000000>, <1000000>; 123 + 124 + s5m8767,pmic-buck4-dvs-voltage = <1200000>, <1200000>, 125 + <1200000>, <1200000>, 126 + <1200000>, <1200000>, 127 + <1200000>, <1200000>; 128 + 129 + regulators { 130 + ldo1_reg: LDO1 { 131 + regulator-name = "VDD_ABB_3.3V"; 132 + regulator-min-microvolt = <3300000>; 133 + regulator-max-microvolt = <3300000>; 134 + op_mode = <1>; /* Normal Mode */ 135 + }; 136 + 137 + ldo2_reg: LDO2 { 138 + regulator-name = "VDD_ALIVE_1.1V"; 139 + regulator-min-microvolt = <1100000>; 140 + regulator-max-microvolt = <1100000>; 141 + regulator-always-on; 142 + }; 143 + 144 + buck1_reg: BUCK1 { 145 + regulator-name = "VDD_MIF_1.2V"; 146 + regulator-min-microvolt = <950000>; 147 + regulator-max-microvolt = <1350000>; 148 + regulator-always-on; 149 + regulator-boot-on; 150 + }; 151 + }; 152 + };
+72 -1
drivers/mfd/sec-core.c
··· 17 17 #include <linux/err.h> 18 18 #include <linux/slab.h> 19 19 #include <linux/i2c.h> 20 + #include <linux/of_irq.h> 20 21 #include <linux/interrupt.h> 21 22 #include <linux/pm_runtime.h> 22 23 #include <linux/mutex.h> ··· 61 60 }, 62 61 }; 63 62 63 + #ifdef CONFIG_OF 64 + static struct of_device_id sec_dt_match[] = { 65 + { .compatible = "samsung,s5m8767-pmic", 66 + .data = (void *)S5M8767X, 67 + }, 68 + {}, 69 + }; 70 + #endif 71 + 64 72 int sec_reg_read(struct sec_pmic_dev *sec_pmic, u8 reg, void *dest) 65 73 { 66 74 return regmap_read(sec_pmic->regmap, reg, dest); ··· 105 95 .val_bits = 8, 106 96 }; 107 97 98 + 99 + #ifdef CONFIG_OF 100 + /* 101 + * Only the common platform data elements for s5m8767 are parsed here from the 102 + * device tree. Other sub-modules of s5m8767 such as pmic, rtc , charger and 103 + * others have to parse their own platform data elements from device tree. 104 + * 105 + * The s5m8767 platform data structure is instantiated here and the drivers for 106 + * the sub-modules need not instantiate another instance while parsing their 107 + * platform data. 108 + */ 109 + static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( 110 + struct device *dev) 111 + { 112 + struct sec_platform_data *pd; 113 + 114 + pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); 115 + if (!pd) { 116 + dev_err(dev, "could not allocate memory for pdata\n"); 117 + return ERR_PTR(-ENOMEM); 118 + } 119 + 120 + /* 121 + * ToDo: the 'wakeup' member in the platform data is more of a linux 122 + * specfic information. Hence, there is no binding for that yet and 123 + * not parsed here. 124 + */ 125 + 126 + return pd; 127 + } 128 + #else 129 + static struct sec_platform_data *sec_i2c_parse_dt_pdata( 130 + struct device *dev) 131 + { 132 + return 0; 133 + } 134 + #endif 135 + 136 + static inline int sec_i2c_get_driver_data(struct i2c_client *i2c, 137 + const struct i2c_device_id *id) 138 + { 139 + #ifdef CONFIG_OF 140 + if (i2c->dev.of_node) { 141 + const struct of_device_id *match; 142 + match = of_match_node(sec_dt_match, i2c->dev.of_node); 143 + return (int)match->data; 144 + } 145 + #endif 146 + return (int)id->driver_data; 147 + } 148 + 108 149 static int sec_pmic_probe(struct i2c_client *i2c, 109 150 const struct i2c_device_id *id) 110 151 { ··· 172 111 sec_pmic->dev = &i2c->dev; 173 112 sec_pmic->i2c = i2c; 174 113 sec_pmic->irq = i2c->irq; 175 - sec_pmic->type = id->driver_data; 114 + sec_pmic->type = sec_i2c_get_driver_data(i2c, id); 176 115 116 + if (sec_pmic->dev->of_node) { 117 + pdata = sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev); 118 + if (IS_ERR(pdata)) { 119 + ret = PTR_ERR(pdata); 120 + return ret; 121 + } 122 + pdata->device_type = sec_pmic->type; 123 + } 177 124 if (pdata) { 178 125 sec_pmic->device_type = pdata->device_type; 179 126 sec_pmic->ono = pdata->ono; 180 127 sec_pmic->irq_base = pdata->irq_base; 181 128 sec_pmic->wakeup = pdata->wakeup; 129 + sec_pmic->pdata = pdata; 182 130 } 183 131 184 132 sec_pmic->regmap = devm_regmap_init_i2c(i2c, &sec_regmap_config); ··· 262 192 .driver = { 263 193 .name = "sec_pmic", 264 194 .owner = THIS_MODULE, 195 + .of_match_table = of_match_ptr(sec_dt_match), 265 196 }, 266 197 .probe = sec_pmic_probe, 267 198 .remove = sec_pmic_remove,
+185 -1
drivers/regulator/s5m8767.c
··· 14 14 #include <linux/bug.h> 15 15 #include <linux/err.h> 16 16 #include <linux/gpio.h> 17 + #include <linux/of_gpio.h> 17 18 #include <linux/slab.h> 18 19 #include <linux/module.h> 19 20 #include <linux/platform_device.h> ··· 22 21 #include <linux/regulator/machine.h> 23 22 #include <linux/mfd/samsung/core.h> 24 23 #include <linux/mfd/samsung/s5m8767.h> 24 + #include <linux/regulator/of_regulator.h> 25 + 26 + #define S5M8767_OPMODE_NORMAL_MODE 0x1 25 27 26 28 struct s5m8767_info { 27 29 struct device *dev; ··· 478 474 s5m8767_regulator_desc(BUCK9), 479 475 }; 480 476 477 + #ifdef CONFIG_OF 478 + static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev, 479 + struct sec_platform_data *pdata, 480 + struct device_node *pmic_np) 481 + { 482 + int i, gpio; 483 + 484 + for (i = 0; i < 3; i++) { 485 + gpio = of_get_named_gpio(pmic_np, 486 + "s5m8767,pmic-buck-dvs-gpios", i); 487 + if (!gpio_is_valid(gpio)) { 488 + dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio); 489 + return -EINVAL; 490 + } 491 + pdata->buck_gpios[i] = gpio; 492 + } 493 + return 0; 494 + } 495 + 496 + static int s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev *iodev, 497 + struct sec_platform_data *pdata, 498 + struct device_node *pmic_np) 499 + { 500 + int i, gpio; 501 + 502 + for (i = 0; i < 3; i++) { 503 + gpio = of_get_named_gpio(pmic_np, 504 + "s5m8767,pmic-buck-ds-gpios", i); 505 + if (!gpio_is_valid(gpio)) { 506 + dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio); 507 + return -EINVAL; 508 + } 509 + pdata->buck_ds[i] = gpio; 510 + } 511 + return 0; 512 + } 513 + 514 + static int s5m8767_pmic_dt_parse_pdata(struct sec_pmic_dev *iodev, 515 + struct sec_platform_data *pdata) 516 + { 517 + struct device_node *pmic_np, *regulators_np, *reg_np; 518 + struct sec_regulator_data *rdata; 519 + struct sec_opmode_data *rmode; 520 + unsigned int i, dvs_voltage_nr = 1, ret; 521 + 522 + pmic_np = iodev->dev->of_node; 523 + if (!pmic_np) { 524 + dev_err(iodev->dev, "could not find pmic sub-node\n"); 525 + return -ENODEV; 526 + } 527 + 528 + regulators_np = of_find_node_by_name(pmic_np, "regulators"); 529 + if (!regulators_np) { 530 + dev_err(iodev->dev, "could not find regulators sub-node\n"); 531 + return -EINVAL; 532 + } 533 + 534 + /* count the number of regulators to be supported in pmic */ 535 + pdata->num_regulators = 0; 536 + for_each_child_of_node(regulators_np, reg_np) 537 + pdata->num_regulators++; 538 + 539 + rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * 540 + pdata->num_regulators, GFP_KERNEL); 541 + if (!rdata) { 542 + dev_err(iodev->dev, 543 + "could not allocate memory for regulator data\n"); 544 + return -ENOMEM; 545 + } 546 + 547 + rmode = devm_kzalloc(iodev->dev, sizeof(*rmode) * 548 + pdata->num_regulators, GFP_KERNEL); 549 + if (!rdata) { 550 + dev_err(iodev->dev, 551 + "could not allocate memory for regulator mode\n"); 552 + return -ENOMEM; 553 + } 554 + 555 + pdata->regulators = rdata; 556 + pdata->opmode = rmode; 557 + for_each_child_of_node(regulators_np, reg_np) { 558 + for (i = 0; i < ARRAY_SIZE(regulators); i++) 559 + if (!of_node_cmp(reg_np->name, regulators[i].name)) 560 + break; 561 + 562 + if (i == ARRAY_SIZE(regulators)) { 563 + dev_warn(iodev->dev, 564 + "don't know how to configure regulator %s\n", 565 + reg_np->name); 566 + continue; 567 + } 568 + 569 + rdata->id = i; 570 + rdata->initdata = of_get_regulator_init_data( 571 + iodev->dev, reg_np); 572 + rdata->reg_node = reg_np; 573 + rdata++; 574 + rmode->id = i; 575 + if (of_property_read_u32(reg_np, "op_mode", 576 + &rmode->mode)) { 577 + dev_warn(iodev->dev, 578 + "no op_mode property property at %s\n", 579 + reg_np->full_name); 580 + 581 + rmode->mode = S5M8767_OPMODE_NORMAL_MODE; 582 + } 583 + rmode++; 584 + } 585 + 586 + if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL)) 587 + pdata->buck2_gpiodvs = true; 588 + 589 + if (of_get_property(pmic_np, "s5m8767,pmic-buck3-uses-gpio-dvs", NULL)) 590 + pdata->buck3_gpiodvs = true; 591 + 592 + if (of_get_property(pmic_np, "s5m8767,pmic-buck4-uses-gpio-dvs", NULL)) 593 + pdata->buck4_gpiodvs = true; 594 + 595 + if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs || 596 + pdata->buck4_gpiodvs) { 597 + ret = s5m8767_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np); 598 + if (ret) 599 + return -EINVAL; 600 + 601 + if (of_property_read_u32(pmic_np, 602 + "s5m8767,pmic-buck-default-dvs-idx", 603 + &pdata->buck_default_idx)) { 604 + pdata->buck_default_idx = 0; 605 + } else { 606 + if (pdata->buck_default_idx >= 8) { 607 + pdata->buck_default_idx = 0; 608 + dev_info(iodev->dev, 609 + "invalid value for default dvs index, use 0\n"); 610 + } 611 + } 612 + dvs_voltage_nr = 8; 613 + } 614 + 615 + ret = s5m8767_pmic_dt_parse_ds_gpio(iodev, pdata, pmic_np); 616 + if (ret) 617 + return -EINVAL; 618 + 619 + if (of_property_read_u32_array(pmic_np, 620 + "s5m8767,pmic-buck2-dvs-voltage", 621 + pdata->buck2_voltage, dvs_voltage_nr)) { 622 + dev_err(iodev->dev, "buck2 voltages not specified\n"); 623 + return -EINVAL; 624 + } 625 + 626 + if (of_property_read_u32_array(pmic_np, 627 + "s5m8767,pmic-buck3-dvs-voltage", 628 + pdata->buck3_voltage, dvs_voltage_nr)) { 629 + dev_err(iodev->dev, "buck3 voltages not specified\n"); 630 + return -EINVAL; 631 + } 632 + 633 + if (of_property_read_u32_array(pmic_np, 634 + "s5m8767,pmic-buck4-dvs-voltage", 635 + pdata->buck4_voltage, dvs_voltage_nr)) { 636 + dev_err(iodev->dev, "buck4 voltages not specified\n"); 637 + return -EINVAL; 638 + } 639 + 640 + return 0; 641 + } 642 + #else 643 + static int s5m8767_pmic_dt_parse_pdata(struct sec_pmic_dev *iodev, 644 + struct sec_platform_data *pdata) 645 + { 646 + return 0; 647 + } 648 + #endif /* CONFIG_OF */ 649 + 481 650 static int s5m8767_pmic_probe(struct platform_device *pdev) 482 651 { 483 652 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); 484 - struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); 653 + struct sec_platform_data *pdata = iodev->pdata; 485 654 struct regulator_config config = { }; 486 655 struct regulator_dev **rdev; 487 656 struct s5m8767_info *s5m8767; 488 657 int i, ret, size, buck_init; 658 + 659 + if (iodev->dev->of_node) { 660 + ret = s5m8767_pmic_dt_parse_pdata(iodev, pdata); 661 + if (ret) 662 + return ret; 663 + } 489 664 490 665 if (!pdata) { 491 666 dev_err(pdev->dev.parent, "Platform data not supplied\n"); ··· 909 726 config.init_data = pdata->regulators[i].initdata; 910 727 config.driver_data = s5m8767; 911 728 config.regmap = iodev->regmap; 729 + config.of_node = pdata->regulators[i].reg_node; 912 730 913 731 rdev[i] = regulator_register(&regulators[id], &config); 914 732 if (IS_ERR(rdev[i])) {
+7 -4
include/linux/mfd/samsung/core.h
··· 26 26 /** 27 27 * struct sec_pmic_dev - s5m87xx master device for sub-drivers 28 28 * @dev: master device of the chip (can be used to access platform data) 29 + * @pdata: pointer to private data used to pass platform data to child 29 30 * @i2c: i2c client private data for regulator 30 31 * @rtc: i2c client private data for rtc 31 32 * @iolock: mutex for serializing io access ··· 40 39 */ 41 40 struct sec_pmic_dev { 42 41 struct device *dev; 42 + struct sec_platform_data *pdata; 43 43 struct regmap *regmap; 44 44 struct i2c_client *i2c; 45 45 struct i2c_client *rtc; ··· 84 82 85 83 int buck_gpios[3]; 86 84 int buck_ds[3]; 87 - int buck2_voltage[8]; 85 + unsigned int buck2_voltage[8]; 88 86 bool buck2_gpiodvs; 89 - int buck3_voltage[8]; 87 + unsigned int buck3_voltage[8]; 90 88 bool buck3_gpiodvs; 91 - int buck4_voltage[8]; 89 + unsigned int buck4_voltage[8]; 92 90 bool buck4_gpiodvs; 93 91 94 92 int buck_set1; ··· 129 127 struct sec_regulator_data { 130 128 int id; 131 129 struct regulator_init_data *initdata; 130 + struct device_node *reg_node; 132 131 }; 133 132 134 133 /* ··· 139 136 */ 140 137 struct sec_opmode_data { 141 138 int id; 142 - int mode; 139 + unsigned int mode; 143 140 }; 144 141 145 142 /*