diff options
44 files changed, 1832 insertions, 418 deletions
diff --git a/Documentation/devicetree/bindings/mfd/bcm590xx.txt b/Documentation/devicetree/bindings/mfd/bcm590xx.txt index 1fe30e2b10da..be51a15e05f9 100644 --- a/Documentation/devicetree/bindings/mfd/bcm590xx.txt +++ b/Documentation/devicetree/bindings/mfd/bcm590xx.txt | |||
| @@ -19,7 +19,9 @@ Optional child nodes: | |||
| 19 | The valid regulator node names for BCM59056 are: | 19 | The valid regulator node names for BCM59056 are: |
| 20 | rfldo, camldo1, camldo2, simldo1, simldo2, sdldo, sdxldo, | 20 | rfldo, camldo1, camldo2, simldo1, simldo2, sdldo, sdxldo, |
| 21 | mmcldo1, mmcldo2, audldo, micldo, usbldo, vibldo, | 21 | mmcldo1, mmcldo2, audldo, micldo, usbldo, vibldo, |
| 22 | csr, iosr1, iosr2, msr, sdsr1, sdsr2, vsr | 22 | csr, iosr1, iosr2, msr, sdsr1, sdsr2, vsr, |
| 23 | gpldo1, gpldo2, gpldo3, gpldo4, gpldo5, gpldo6, | ||
| 24 | vbus | ||
| 23 | 25 | ||
| 24 | Example: | 26 | Example: |
| 25 | pmu: bcm59056@8 { | 27 | pmu: bcm59056@8 { |
diff --git a/Documentation/devicetree/bindings/mfd/s2mps11.txt b/Documentation/devicetree/bindings/mfd/s2mps11.txt index 802e839b0829..d81ba30c0d8b 100644 --- a/Documentation/devicetree/bindings/mfd/s2mps11.txt +++ b/Documentation/devicetree/bindings/mfd/s2mps11.txt | |||
| @@ -56,6 +56,20 @@ for a particular group of BUCKs. So provide same regulator-ramp-delay<value>. | |||
| 56 | Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6], | 56 | Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6], |
| 57 | BUCK[3, 4], and BUCK[7, 8, 10] | 57 | BUCK[3, 4], and BUCK[7, 8, 10] |
| 58 | 58 | ||
| 59 | On S2MPS14 the LDO10, LDO11 and LDO12 can be configured to external control | ||
| 60 | over GPIO. To turn this feature on this property must be added to the regulator | ||
| 61 | sub-node: | ||
| 62 | - samsung,ext-control-gpios: GPIO specifier for one GPIO | ||
| 63 | controlling this regulator (enable/disable); | ||
| 64 | Example: | ||
| 65 | LDO12 { | ||
| 66 | regulator-name = "V_EMMC_2.8V"; | ||
| 67 | regulator-min-microvolt = <2800000>; | ||
| 68 | regulator-max-microvolt = <2800000>; | ||
| 69 | samsung,ext-control-gpios = <&gpk0 2 0>; | ||
| 70 | }; | ||
| 71 | |||
| 72 | |||
| 59 | The regulator constraints inside the regulator nodes use the standard regulator | 73 | The regulator constraints inside the regulator nodes use the standard regulator |
| 60 | bindings which are documented elsewhere. | 74 | bindings which are documented elsewhere. |
| 61 | 75 | ||
diff --git a/Documentation/devicetree/bindings/regulator/ltc3589.txt b/Documentation/devicetree/bindings/regulator/ltc3589.txt new file mode 100644 index 000000000000..801053036146 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/ltc3589.txt | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | Linear Technology LTC3589, LTC3589-1, and LTC3589-2 8-output regulators | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: "lltc,ltc3589", "lltc,ltc3589-1" or "lltc,ltc3589-2" | ||
| 5 | - reg: I2C slave address | ||
| 6 | |||
| 7 | Required child node: | ||
| 8 | - regulators: Contains eight regulator child nodes sw1, sw2, sw3, bb-out, | ||
| 9 | ldo1, ldo2, ldo3, and ldo4, specifying the initialization data as | ||
| 10 | documented in Documentation/devicetree/bindings/regulator/regulator.txt. | ||
| 11 | |||
| 12 | Each regulator is defined using the standard binding for regulators. The | ||
| 13 | nodes for sw1, sw2, sw3, bb-out, ldo1, and ldo2 additionally need to specify | ||
| 14 | the resistor values of their external feedback voltage dividers: | ||
| 15 | |||
| 16 | Required properties (not on ldo3, ldo4): | ||
| 17 | - lltc,fb-voltage-divider: An array of two integers containing the resistor | ||
| 18 | values R1 and R2 of the feedback voltage divider in ohms. | ||
| 19 | |||
| 20 | Regulators sw1, sw2, sw3, and ldo2 can regulate the feedback reference from | ||
| 21 | 0.3625 V to 0.75 V in 12.5 mV steps. The output voltage thus ranges between | ||
| 22 | 0.3625 * (1 + R1/R2) V and 0.75 * (1 + R1/R2) V. Regulators bb-out and ldo1 | ||
| 23 | have a fixed 0.8 V reference and thus output 0.8 * (1 + R1/R2) V. The ldo3 | ||
| 24 | regulator is fixed to 1.8 V on LTC3589 and to 2.8 V on LTC3589-1,2. The ldo4 | ||
| 25 | regulator can output between 1.8 V and 3.3 V on LTC3589 and between 1.2 V | ||
| 26 | and 3.2 V on LTC3589-1,2 in four steps. The ldo1 standby regulator can not | ||
| 27 | be disabled and thus should have the regulator-always-on property set. | ||
| 28 | |||
| 29 | Example: | ||
| 30 | |||
| 31 | ltc3589: pmic@34 { | ||
| 32 | compatible = "lltc,ltc3589-1"; | ||
| 33 | reg = <0x34>; | ||
| 34 | |||
| 35 | regulators { | ||
| 36 | sw1_reg: sw1 { | ||
| 37 | regulator-min-microvolt = <591930>; | ||
| 38 | regulator-max-microvolt = <1224671>; | ||
| 39 | lltc,fb-voltage-divider = <100000 158000>; | ||
| 40 | regulator-ramp-delay = <7000>; | ||
| 41 | regulator-boot-on; | ||
| 42 | regulator-always-on; | ||
| 43 | }; | ||
| 44 | |||
| 45 | sw2_reg: sw2 { | ||
| 46 | regulator-min-microvolt = <704123>; | ||
| 47 | regulator-max-microvolt = <1456803>; | ||
| 48 | lltc,fb-voltage-divider = <180000 191000>; | ||
| 49 | regulator-ramp-delay = <7000>; | ||
| 50 | regulator-boot-on; | ||
| 51 | regulator-always-on; | ||
| 52 | }; | ||
| 53 | |||
| 54 | sw3_reg: sw3 { | ||
| 55 | regulator-min-microvolt = <1341250>; | ||
| 56 | regulator-max-microvolt = <2775000>; | ||
| 57 | lltc,fb-voltage-divider = <270000 100000>; | ||
| 58 | regulator-ramp-delay = <7000>; | ||
| 59 | regulator-boot-on; | ||
| 60 | regulator-always-on; | ||
| 61 | }; | ||
| 62 | |||
| 63 | bb_out_reg: bb-out { | ||
| 64 | regulator-min-microvolt = <3387341>; | ||
| 65 | regulator-max-microvolt = <3387341>; | ||
| 66 | lltc,fb-voltage-divider = <511000 158000>; | ||
| 67 | regulator-boot-on; | ||
| 68 | regulator-always-on; | ||
| 69 | }; | ||
| 70 | |||
| 71 | ldo1_reg: ldo1 { | ||
| 72 | regulator-min-microvolt = <1306329>; | ||
| 73 | regulator-max-microvolt = <1306329>; | ||
| 74 | lltc,fb-voltage-divider = <100000 158000>; | ||
| 75 | regulator-boot-on; | ||
| 76 | regulator-always-on; | ||
| 77 | }; | ||
| 78 | |||
| 79 | ldo2_reg: ldo2 { | ||
| 80 | regulator-min-microvolt = <704123>; | ||
| 81 | regulator-max-microvolt = <1456806>; | ||
| 82 | lltc,fb-voltage-divider = <180000 191000>; | ||
| 83 | regulator-ramp-delay = <7000>; | ||
| 84 | regulator-boot-on; | ||
| 85 | regulator-always-on; | ||
| 86 | }; | ||
| 87 | |||
| 88 | ldo3_reg: ldo3 { | ||
| 89 | regulator-min-microvolt = <2800000>; | ||
| 90 | regulator-max-microvolt = <2800000>; | ||
| 91 | regulator-boot-on; | ||
| 92 | }; | ||
| 93 | |||
| 94 | ldo4_reg: ldo4 { | ||
| 95 | regulator-min-microvolt = <1200000>; | ||
| 96 | regulator-max-microvolt = <3200000>; | ||
| 97 | }; | ||
| 98 | }; | ||
| 99 | }; | ||
diff --git a/Documentation/devicetree/bindings/regulator/tps65090.txt b/Documentation/devicetree/bindings/regulator/tps65090.txt index 313a60ba61d8..340980239ea9 100644 --- a/Documentation/devicetree/bindings/regulator/tps65090.txt +++ b/Documentation/devicetree/bindings/regulator/tps65090.txt | |||
| @@ -21,6 +21,10 @@ Optional properties: | |||
| 21 | number should be provided. If it is externally controlled and no GPIO | 21 | number should be provided. If it is externally controlled and no GPIO |
| 22 | entry then driver will just configure this rails as external control | 22 | entry then driver will just configure this rails as external control |
| 23 | and will not provide any enable/disable APIs. | 23 | and will not provide any enable/disable APIs. |
| 24 | - ti,overcurrent-wait: This is applicable to FET registers, which have a | ||
| 25 | poorly defined "overcurrent wait" field. If this property is present it | ||
| 26 | should be between 0 - 3. If this property isn't present we won't touch the | ||
| 27 | "overcurrent wait" field and we'll leave it to the BIOS/EC to deal with. | ||
| 24 | 28 | ||
| 25 | Each regulator is defined using the standard binding for regulators. | 29 | Each regulator is defined using the standard binding for regulators. |
| 26 | 30 | ||
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 2ee6ead72434..941980474e14 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt | |||
| @@ -74,6 +74,7 @@ lantiq Lantiq Semiconductor | |||
| 74 | lg LG Corporation | 74 | lg LG Corporation |
| 75 | linux Linux-specific binding | 75 | linux Linux-specific binding |
| 76 | lsi LSI Corp. (LSI Logic) | 76 | lsi LSI Corp. (LSI Logic) |
| 77 | lltc Linear Technology Corporation | ||
| 77 | marvell Marvell Technology Group Ltd. | 78 | marvell Marvell Technology Group Ltd. |
| 78 | maxim Maxim Integrated Products | 79 | maxim Maxim Integrated Products |
| 79 | microchip Microchip Technology Inc. | 80 | microchip Microchip Technology Inc. |
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 1c3ae57082ed..07e6e27be23c 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c | |||
| @@ -508,19 +508,31 @@ int arizona_of_get_type(struct device *dev) | |||
| 508 | } | 508 | } |
| 509 | EXPORT_SYMBOL_GPL(arizona_of_get_type); | 509 | EXPORT_SYMBOL_GPL(arizona_of_get_type); |
| 510 | 510 | ||
| 511 | int arizona_of_get_named_gpio(struct arizona *arizona, const char *prop, | ||
| 512 | bool mandatory) | ||
| 513 | { | ||
| 514 | int gpio; | ||
| 515 | |||
| 516 | gpio = of_get_named_gpio(arizona->dev->of_node, prop, 0); | ||
| 517 | if (gpio < 0) { | ||
| 518 | if (mandatory) | ||
| 519 | dev_err(arizona->dev, | ||
| 520 | "Mandatory DT gpio %s missing/malformed: %d\n", | ||
| 521 | prop, gpio); | ||
| 522 | |||
| 523 | gpio = 0; | ||
| 524 | } | ||
| 525 | |||
| 526 | return gpio; | ||
| 527 | } | ||
| 528 | EXPORT_SYMBOL_GPL(arizona_of_get_named_gpio); | ||
| 529 | |||
| 511 | static int arizona_of_get_core_pdata(struct arizona *arizona) | 530 | static int arizona_of_get_core_pdata(struct arizona *arizona) |
| 512 | { | 531 | { |
| 532 | struct arizona_pdata *pdata = &arizona->pdata; | ||
| 513 | int ret, i; | 533 | int ret, i; |
| 514 | 534 | ||
| 515 | arizona->pdata.reset = of_get_named_gpio(arizona->dev->of_node, | 535 | pdata->reset = arizona_of_get_named_gpio(arizona, "wlf,reset", true); |
| 516 | "wlf,reset", 0); | ||
| 517 | if (arizona->pdata.reset < 0) | ||
| 518 | arizona->pdata.reset = 0; | ||
| 519 | |||
| 520 | arizona->pdata.ldoena = of_get_named_gpio(arizona->dev->of_node, | ||
| 521 | "wlf,ldoena", 0); | ||
| 522 | if (arizona->pdata.ldoena < 0) | ||
| 523 | arizona->pdata.ldoena = 0; | ||
| 524 | 536 | ||
| 525 | ret = of_property_read_u32_array(arizona->dev->of_node, | 537 | ret = of_property_read_u32_array(arizona->dev->of_node, |
| 526 | "wlf,gpio-defaults", | 538 | "wlf,gpio-defaults", |
| @@ -652,6 +664,9 @@ int arizona_dev_init(struct arizona *arizona) | |||
| 652 | return -EINVAL; | 664 | return -EINVAL; |
| 653 | } | 665 | } |
| 654 | 666 | ||
| 667 | /* Mark DCVDD as external, LDO1 driver will clear if internal */ | ||
| 668 | arizona->external_dcvdd = true; | ||
| 669 | |||
| 655 | ret = mfd_add_devices(arizona->dev, -1, early_devs, | 670 | ret = mfd_add_devices(arizona->dev, -1, early_devs, |
| 656 | ARRAY_SIZE(early_devs), NULL, 0, NULL); | 671 | ARRAY_SIZE(early_devs), NULL, 0, NULL); |
| 657 | if (ret != 0) { | 672 | if (ret != 0) { |
| @@ -851,14 +866,6 @@ int arizona_dev_init(struct arizona *arizona) | |||
| 851 | arizona->pdata.gpio_defaults[i]); | 866 | arizona->pdata.gpio_defaults[i]); |
| 852 | } | 867 | } |
| 853 | 868 | ||
| 854 | /* | ||
| 855 | * LDO1 can only be used to supply DCVDD so if it has no | ||
| 856 | * consumers then DCVDD is supplied externally. | ||
| 857 | */ | ||
| 858 | if (arizona->pdata.ldo1 && | ||
| 859 | arizona->pdata.ldo1->num_consumer_supplies == 0) | ||
| 860 | arizona->external_dcvdd = true; | ||
| 861 | |||
| 862 | pm_runtime_set_autosuspend_delay(arizona->dev, 100); | 869 | pm_runtime_set_autosuspend_delay(arizona->dev, 100); |
| 863 | pm_runtime_use_autosuspend(arizona->dev); | 870 | pm_runtime_use_autosuspend(arizona->dev); |
| 864 | pm_runtime_enable(arizona->dev); | 871 | pm_runtime_enable(arizona->dev); |
diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c index e9a33c79431b..43cba1a1973c 100644 --- a/drivers/mfd/bcm590xx.c +++ b/drivers/mfd/bcm590xx.c | |||
| @@ -28,39 +28,71 @@ static const struct mfd_cell bcm590xx_devs[] = { | |||
| 28 | }, | 28 | }, |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | static const struct regmap_config bcm590xx_regmap_config = { | 31 | static const struct regmap_config bcm590xx_regmap_config_pri = { |
| 32 | .reg_bits = 8, | 32 | .reg_bits = 8, |
| 33 | .val_bits = 8, | 33 | .val_bits = 8, |
| 34 | .max_register = BCM590XX_MAX_REGISTER, | 34 | .max_register = BCM590XX_MAX_REGISTER_PRI, |
| 35 | .cache_type = REGCACHE_RBTREE, | 35 | .cache_type = REGCACHE_RBTREE, |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | static int bcm590xx_i2c_probe(struct i2c_client *i2c, | 38 | static const struct regmap_config bcm590xx_regmap_config_sec = { |
| 39 | .reg_bits = 8, | ||
| 40 | .val_bits = 8, | ||
| 41 | .max_register = BCM590XX_MAX_REGISTER_SEC, | ||
| 42 | .cache_type = REGCACHE_RBTREE, | ||
| 43 | }; | ||
| 44 | |||
| 45 | static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri, | ||
| 39 | const struct i2c_device_id *id) | 46 | const struct i2c_device_id *id) |
| 40 | { | 47 | { |
| 41 | struct bcm590xx *bcm590xx; | 48 | struct bcm590xx *bcm590xx; |
| 42 | int ret; | 49 | int ret; |
| 43 | 50 | ||
| 44 | bcm590xx = devm_kzalloc(&i2c->dev, sizeof(*bcm590xx), GFP_KERNEL); | 51 | bcm590xx = devm_kzalloc(&i2c_pri->dev, sizeof(*bcm590xx), GFP_KERNEL); |
| 45 | if (!bcm590xx) | 52 | if (!bcm590xx) |
| 46 | return -ENOMEM; | 53 | return -ENOMEM; |
| 47 | 54 | ||
| 48 | i2c_set_clientdata(i2c, bcm590xx); | 55 | i2c_set_clientdata(i2c_pri, bcm590xx); |
| 49 | bcm590xx->dev = &i2c->dev; | 56 | bcm590xx->dev = &i2c_pri->dev; |
| 50 | bcm590xx->i2c_client = i2c; | 57 | bcm590xx->i2c_pri = i2c_pri; |
| 51 | 58 | ||
| 52 | bcm590xx->regmap = devm_regmap_init_i2c(i2c, &bcm590xx_regmap_config); | 59 | bcm590xx->regmap_pri = devm_regmap_init_i2c(i2c_pri, |
| 53 | if (IS_ERR(bcm590xx->regmap)) { | 60 | &bcm590xx_regmap_config_pri); |
| 54 | ret = PTR_ERR(bcm590xx->regmap); | 61 | if (IS_ERR(bcm590xx->regmap_pri)) { |
| 55 | dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret); | 62 | ret = PTR_ERR(bcm590xx->regmap_pri); |
| 63 | dev_err(&i2c_pri->dev, "primary regmap init failed: %d\n", ret); | ||
| 56 | return ret; | 64 | return ret; |
| 57 | } | 65 | } |
| 58 | 66 | ||
| 59 | ret = mfd_add_devices(&i2c->dev, -1, bcm590xx_devs, | 67 | /* Secondary I2C slave address is the base address with A(2) asserted */ |
| 68 | bcm590xx->i2c_sec = i2c_new_dummy(i2c_pri->adapter, | ||
| 69 | i2c_pri->addr | BIT(2)); | ||
| 70 | if (IS_ERR_OR_NULL(bcm590xx->i2c_sec)) { | ||
| 71 | dev_err(&i2c_pri->dev, "failed to add secondary I2C device\n"); | ||
| 72 | return -ENODEV; | ||
| 73 | } | ||
| 74 | i2c_set_clientdata(bcm590xx->i2c_sec, bcm590xx); | ||
| 75 | |||
| 76 | bcm590xx->regmap_sec = devm_regmap_init_i2c(bcm590xx->i2c_sec, | ||
| 77 | &bcm590xx_regmap_config_sec); | ||
| 78 | if (IS_ERR(bcm590xx->regmap_sec)) { | ||
| 79 | ret = PTR_ERR(bcm590xx->regmap_sec); | ||
| 80 | dev_err(&bcm590xx->i2c_sec->dev, | ||
| 81 | "secondary regmap init failed: %d\n", ret); | ||
| 82 | goto err; | ||
| 83 | } | ||
| 84 | |||
| 85 | ret = mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs, | ||
| 60 | ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL); | 86 | ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL); |
| 61 | if (ret < 0) | 87 | if (ret < 0) { |
| 62 | dev_err(&i2c->dev, "failed to add sub-devices: %d\n", ret); | 88 | dev_err(&i2c_pri->dev, "failed to add sub-devices: %d\n", ret); |
| 89 | goto err; | ||
| 90 | } | ||
| 91 | |||
| 92 | return 0; | ||
| 63 | 93 | ||
| 94 | err: | ||
| 95 | i2c_unregister_device(bcm590xx->i2c_sec); | ||
| 64 | return ret; | 96 | return ret; |
| 65 | } | 97 | } |
| 66 | 98 | ||
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c index ba1a25d758c1..1c3e6e2efe41 100644 --- a/drivers/mfd/tps65090.c +++ b/drivers/mfd/tps65090.c | |||
| @@ -32,14 +32,6 @@ | |||
| 32 | #define NUM_INT_REG 2 | 32 | #define NUM_INT_REG 2 |
| 33 | #define TOTAL_NUM_REG 0x18 | 33 | #define TOTAL_NUM_REG 0x18 |
| 34 | 34 | ||
| 35 | /* interrupt status registers */ | ||
| 36 | #define TPS65090_INT_STS 0x0 | ||
| 37 | #define TPS65090_INT_STS2 0x1 | ||
| 38 | |||
| 39 | /* interrupt mask registers */ | ||
| 40 | #define TPS65090_INT_MSK 0x2 | ||
| 41 | #define TPS65090_INT_MSK2 0x3 | ||
| 42 | |||
| 43 | #define TPS65090_INT1_MASK_VAC_STATUS_CHANGE 1 | 35 | #define TPS65090_INT1_MASK_VAC_STATUS_CHANGE 1 |
| 44 | #define TPS65090_INT1_MASK_VSYS_STATUS_CHANGE 2 | 36 | #define TPS65090_INT1_MASK_VSYS_STATUS_CHANGE 2 |
| 45 | #define TPS65090_INT1_MASK_BAT_STATUS_CHANGE 3 | 37 | #define TPS65090_INT1_MASK_BAT_STATUS_CHANGE 3 |
| @@ -64,11 +56,16 @@ static struct resource charger_resources[] = { | |||
| 64 | } | 56 | } |
| 65 | }; | 57 | }; |
| 66 | 58 | ||
| 67 | static const struct mfd_cell tps65090s[] = { | 59 | enum tps65090_cells { |
| 68 | { | 60 | PMIC = 0, |
| 61 | CHARGER = 1, | ||
| 62 | }; | ||
| 63 | |||
| 64 | static struct mfd_cell tps65090s[] = { | ||
| 65 | [PMIC] = { | ||
| 69 | .name = "tps65090-pmic", | 66 | .name = "tps65090-pmic", |
| 70 | }, | 67 | }, |
| 71 | { | 68 | [CHARGER] = { |
| 72 | .name = "tps65090-charger", | 69 | .name = "tps65090-charger", |
| 73 | .num_resources = ARRAY_SIZE(charger_resources), | 70 | .num_resources = ARRAY_SIZE(charger_resources), |
| 74 | .resources = &charger_resources[0], | 71 | .resources = &charger_resources[0], |
| @@ -139,17 +136,26 @@ static struct regmap_irq_chip tps65090_irq_chip = { | |||
| 139 | .irqs = tps65090_irqs, | 136 | .irqs = tps65090_irqs, |
| 140 | .num_irqs = ARRAY_SIZE(tps65090_irqs), | 137 | .num_irqs = ARRAY_SIZE(tps65090_irqs), |
| 141 | .num_regs = NUM_INT_REG, | 138 | .num_regs = NUM_INT_REG, |
| 142 | .status_base = TPS65090_INT_STS, | 139 | .status_base = TPS65090_REG_INTR_STS, |
| 143 | .mask_base = TPS65090_INT_MSK, | 140 | .mask_base = TPS65090_REG_INTR_MASK, |
| 144 | .mask_invert = true, | 141 | .mask_invert = true, |
| 145 | }; | 142 | }; |
| 146 | 143 | ||
| 147 | static bool is_volatile_reg(struct device *dev, unsigned int reg) | 144 | static bool is_volatile_reg(struct device *dev, unsigned int reg) |
| 148 | { | 145 | { |
| 149 | if ((reg == TPS65090_INT_STS) || (reg == TPS65090_INT_STS2)) | 146 | /* Nearly all registers have status bits mixed in, except a few */ |
| 150 | return true; | 147 | switch (reg) { |
| 151 | else | 148 | case TPS65090_REG_INTR_MASK: |
| 149 | case TPS65090_REG_INTR_MASK2: | ||
| 150 | case TPS65090_REG_CG_CTRL0: | ||
| 151 | case TPS65090_REG_CG_CTRL1: | ||
| 152 | case TPS65090_REG_CG_CTRL2: | ||
| 153 | case TPS65090_REG_CG_CTRL3: | ||
| 154 | case TPS65090_REG_CG_CTRL4: | ||
| 155 | case TPS65090_REG_CG_CTRL5: | ||
| 152 | return false; | 156 | return false; |
| 157 | } | ||
| 158 | return true; | ||
| 153 | } | 159 | } |
| 154 | 160 | ||
| 155 | static const struct regmap_config tps65090_regmap_config = { | 161 | static const struct regmap_config tps65090_regmap_config = { |
| @@ -211,6 +217,9 @@ static int tps65090_i2c_probe(struct i2c_client *client, | |||
| 211 | "IRQ init failed with err: %d\n", ret); | 217 | "IRQ init failed with err: %d\n", ret); |
| 212 | return ret; | 218 | return ret; |
| 213 | } | 219 | } |
| 220 | } else { | ||
| 221 | /* Don't tell children they have an IRQ that'll never fire */ | ||
| 222 | tps65090s[CHARGER].num_resources = 0; | ||
| 214 | } | 223 | } |
| 215 | 224 | ||
| 216 | ret = mfd_add_devices(tps65090->dev, -1, tps65090s, | 225 | ret = mfd_add_devices(tps65090->dev, -1, tps65090s, |
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index bbd54414a75d..835e5549ecdd 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c | |||
| @@ -495,6 +495,10 @@ static void tps6586x_print_version(struct i2c_client *client, int version) | |||
| 495 | case TPS658623: | 495 | case TPS658623: |
| 496 | name = "TPS658623"; | 496 | name = "TPS658623"; |
| 497 | break; | 497 | break; |
| 498 | case TPS658640: | ||
| 499 | case TPS658640v2: | ||
| 500 | name = "TPS658640"; | ||
| 501 | break; | ||
| 498 | case TPS658643: | 502 | case TPS658643: |
| 499 | name = "TPS658643"; | 503 | name = "TPS658643"; |
| 500 | break; | 504 | break; |
diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c index 8fc9d6df87f6..1685f63b9e5d 100644 --- a/drivers/power/tps65090-charger.c +++ b/drivers/power/tps65090-charger.c | |||
| @@ -28,17 +28,6 @@ | |||
| 28 | 28 | ||
| 29 | #include <linux/mfd/tps65090.h> | 29 | #include <linux/mfd/tps65090.h> |
| 30 | 30 | ||
| 31 | #define TPS65090_REG_INTR_STS 0x00 | ||
| 32 | #define TPS65090_REG_INTR_MASK 0x02 | ||
| 33 | #define TPS65090_REG_CG_CTRL0 0x04 | ||
| 34 | #define TPS65090_REG_CG_CTRL1 0x05 | ||
| 35 | #define TPS65090_REG_CG_CTRL2 0x06 | ||
| 36 | #define TPS65090_REG_CG_CTRL3 0x07 | ||
| 37 | #define TPS65090_REG_CG_CTRL4 0x08 | ||
| 38 | #define TPS65090_REG_CG_CTRL5 0x09 | ||
| 39 | #define TPS65090_REG_CG_STATUS1 0x0a | ||
| 40 | #define TPS65090_REG_CG_STATUS2 0x0b | ||
| 41 | |||
| 42 | #define TPS65090_CHARGER_ENABLE BIT(0) | 31 | #define TPS65090_CHARGER_ENABLE BIT(0) |
| 43 | #define TPS65090_VACG BIT(1) | 32 | #define TPS65090_VACG BIT(1) |
| 44 | #define TPS65090_NOITERM BIT(5) | 33 | #define TPS65090_NOITERM BIT(5) |
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index f0cc9e6dac3a..789eb46090e3 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
| @@ -139,6 +139,13 @@ config REGULATOR_AS3722 | |||
| 139 | AS3722 PMIC. This will enable support for all the software | 139 | AS3722 PMIC. This will enable support for all the software |
| 140 | controllable DCDC/LDO regulators. | 140 | controllable DCDC/LDO regulators. |
| 141 | 141 | ||
| 142 | config REGULATOR_AXP20X | ||
| 143 | tristate "X-POWERS AXP20X PMIC Regulators" | ||
| 144 | depends on MFD_AXP20X | ||
| 145 | help | ||
| 146 | This driver provides support for the voltage regulators on the | ||
| 147 | AXP20X PMIC. | ||
| 148 | |||
| 142 | config REGULATOR_BCM590XX | 149 | config REGULATOR_BCM590XX |
| 143 | tristate "Broadcom BCM590xx PMU Regulators" | 150 | tristate "Broadcom BCM590xx PMU Regulators" |
| 144 | depends on MFD_BCM590XX | 151 | depends on MFD_BCM590XX |
| @@ -265,6 +272,14 @@ config REGULATOR_LP8788 | |||
| 265 | help | 272 | help |
| 266 | This driver supports LP8788 voltage regulator chip. | 273 | This driver supports LP8788 voltage regulator chip. |
| 267 | 274 | ||
| 275 | config REGULATOR_LTC3589 | ||
| 276 | tristate "LTC3589 8-output voltage regulator" | ||
| 277 | depends on I2C | ||
| 278 | select REGMAP_I2C | ||
| 279 | help | ||
| 280 | This enables support for the LTC3589, LTC3589-1, and LTC3589-2 | ||
| 281 | 8-output regulators controlled via I2C. | ||
| 282 | |||
| 268 | config REGULATOR_MAX14577 | 283 | config REGULATOR_MAX14577 |
| 269 | tristate "Maxim 14577/77836 regulator" | 284 | tristate "Maxim 14577/77836 regulator" |
| 270 | depends on MFD_MAX14577 | 285 | depends on MFD_MAX14577 |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 12ef277a48b4..d461110f4463 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
| @@ -20,6 +20,7 @@ obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o | |||
| 20 | obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o | 20 | obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o |
| 21 | obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o | 21 | obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o |
| 22 | obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o | 22 | obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o |
| 23 | obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o | ||
| 23 | obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o | 24 | obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o |
| 24 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o | 25 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o |
| 25 | obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o | 26 | obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o |
| @@ -37,6 +38,7 @@ obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o | |||
| 37 | obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o | 38 | obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o |
| 38 | obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o | 39 | obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o |
| 39 | obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o | 40 | obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o |
| 41 | obj-$(CONFIG_REGULATOR_LTC3589) += ltc3589.o | ||
| 40 | obj-$(CONFIG_REGULATOR_MAX14577) += max14577.o | 42 | obj-$(CONFIG_REGULATOR_MAX14577) += max14577.o |
| 41 | obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o | 43 | obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o |
| 42 | obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o | 44 | obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o |
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index 7c397bb81e01..4f730af70e7c 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c | |||
| @@ -300,7 +300,7 @@ static int anatop_regulator_probe(struct platform_device *pdev) | |||
| 300 | return 0; | 300 | return 0; |
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | static struct of_device_id of_anatop_regulator_match_tbl[] = { | 303 | static const struct of_device_id of_anatop_regulator_match_tbl[] = { |
| 304 | { .compatible = "fsl,anatop-regulator", }, | 304 | { .compatible = "fsl,anatop-regulator", }, |
| 305 | { /* end */ } | 305 | { /* end */ } |
| 306 | }; | 306 | }; |
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index b1033d30b504..04f262a836b2 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c | |||
| @@ -16,9 +16,11 @@ | |||
| 16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 17 | #include <linux/bitops.h> | 17 | #include <linux/bitops.h> |
| 18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
| 19 | #include <linux/of.h> | ||
| 19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
| 20 | #include <linux/regulator/driver.h> | 21 | #include <linux/regulator/driver.h> |
| 21 | #include <linux/regulator/machine.h> | 22 | #include <linux/regulator/machine.h> |
| 23 | #include <linux/regulator/of_regulator.h> | ||
| 22 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
| 23 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 24 | 26 | ||
| @@ -178,6 +180,42 @@ static const struct regulator_init_data arizona_ldo1_default = { | |||
| 178 | .num_consumer_supplies = 1, | 180 | .num_consumer_supplies = 1, |
| 179 | }; | 181 | }; |
| 180 | 182 | ||
| 183 | static int arizona_ldo1_of_get_pdata(struct arizona *arizona, | ||
| 184 | struct regulator_config *config) | ||
| 185 | { | ||
| 186 | struct arizona_pdata *pdata = &arizona->pdata; | ||
| 187 | struct arizona_ldo1 *ldo1 = config->driver_data; | ||
| 188 | struct device_node *init_node, *dcvdd_node; | ||
| 189 | struct regulator_init_data *init_data; | ||
| 190 | |||
| 191 | pdata->ldoena = arizona_of_get_named_gpio(arizona, "wlf,ldoena", true); | ||
| 192 | |||
| 193 | init_node = of_get_child_by_name(arizona->dev->of_node, "ldo1"); | ||
| 194 | dcvdd_node = of_parse_phandle(arizona->dev->of_node, "DCVDD-supply", 0); | ||
| 195 | |||
| 196 | if (init_node) { | ||
| 197 | config->of_node = init_node; | ||
| 198 | |||
| 199 | init_data = of_get_regulator_init_data(arizona->dev, init_node); | ||
| 200 | |||
| 201 | if (init_data) { | ||
| 202 | init_data->consumer_supplies = &ldo1->supply; | ||
| 203 | init_data->num_consumer_supplies = 1; | ||
| 204 | |||
| 205 | if (dcvdd_node && dcvdd_node != init_node) | ||
| 206 | arizona->external_dcvdd = true; | ||
| 207 | |||
| 208 | pdata->ldo1 = init_data; | ||
| 209 | } | ||
| 210 | } else if (dcvdd_node) { | ||
| 211 | arizona->external_dcvdd = true; | ||
| 212 | } | ||
| 213 | |||
| 214 | of_node_put(dcvdd_node); | ||
| 215 | |||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | |||
| 181 | static int arizona_ldo1_probe(struct platform_device *pdev) | 219 | static int arizona_ldo1_probe(struct platform_device *pdev) |
| 182 | { | 220 | { |
| 183 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | 221 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); |
| @@ -186,6 +224,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev) | |||
| 186 | struct arizona_ldo1 *ldo1; | 224 | struct arizona_ldo1 *ldo1; |
| 187 | int ret; | 225 | int ret; |
| 188 | 226 | ||
| 227 | arizona->external_dcvdd = false; | ||
| 228 | |||
| 189 | ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL); | 229 | ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL); |
| 190 | if (!ldo1) | 230 | if (!ldo1) |
| 191 | return -ENOMEM; | 231 | return -ENOMEM; |
| @@ -216,6 +256,15 @@ static int arizona_ldo1_probe(struct platform_device *pdev) | |||
| 216 | config.dev = arizona->dev; | 256 | config.dev = arizona->dev; |
| 217 | config.driver_data = ldo1; | 257 | config.driver_data = ldo1; |
| 218 | config.regmap = arizona->regmap; | 258 | config.regmap = arizona->regmap; |
| 259 | |||
| 260 | if (IS_ENABLED(CONFIG_OF)) { | ||
| 261 | if (!dev_get_platdata(arizona->dev)) { | ||
| 262 | ret = arizona_ldo1_of_get_pdata(arizona, &config); | ||
| 263 | if (ret < 0) | ||
| 264 | return ret; | ||
| 265 | } | ||
| 266 | } | ||
| 267 | |||
| 219 | config.ena_gpio = arizona->pdata.ldoena; | 268 | config.ena_gpio = arizona->pdata.ldoena; |
| 220 | 269 | ||
| 221 | if (arizona->pdata.ldo1) | 270 | if (arizona->pdata.ldo1) |
| @@ -223,6 +272,13 @@ static int arizona_ldo1_probe(struct platform_device *pdev) | |||
| 223 | else | 272 | else |
| 224 | config.init_data = &ldo1->init_data; | 273 | config.init_data = &ldo1->init_data; |
| 225 | 274 | ||
| 275 | /* | ||
| 276 | * LDO1 can only be used to supply DCVDD so if it has no | ||
| 277 | * consumers then DCVDD is supplied externally. | ||
| 278 | */ | ||
| 279 | if (config.init_data->num_consumer_supplies == 0) | ||
| 280 | arizona->external_dcvdd = true; | ||
| 281 | |||
| 226 | ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config); | 282 | ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config); |
| 227 | if (IS_ERR(ldo1->regulator)) { | 283 | if (IS_ERR(ldo1->regulator)) { |
| 228 | ret = PTR_ERR(ldo1->regulator); | 284 | ret = PTR_ERR(ldo1->regulator); |
| @@ -231,6 +287,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev) | |||
| 231 | return ret; | 287 | return ret; |
| 232 | } | 288 | } |
| 233 | 289 | ||
| 290 | of_node_put(config.of_node); | ||
| 291 | |||
| 234 | platform_set_drvdata(pdev, ldo1); | 292 | platform_set_drvdata(pdev, ldo1); |
| 235 | 293 | ||
| 236 | return 0; | 294 | return 0; |
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index 6fdd9bf6927f..ce9aca5f8ee7 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c | |||
| @@ -16,9 +16,11 @@ | |||
| 16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 17 | #include <linux/bitops.h> | 17 | #include <linux/bitops.h> |
| 18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
| 19 | #include <linux/of.h> | ||
| 19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
| 20 | #include <linux/regulator/driver.h> | 21 | #include <linux/regulator/driver.h> |
| 21 | #include <linux/regulator/machine.h> | 22 | #include <linux/regulator/machine.h> |
| 23 | #include <linux/regulator/of_regulator.h> | ||
| 22 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
| 23 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 24 | #include <linux/workqueue.h> | 26 | #include <linux/workqueue.h> |
| @@ -195,6 +197,32 @@ static const struct regulator_init_data arizona_micsupp_ext_default = { | |||
| 195 | .num_consumer_supplies = 1, | 197 | .num_consumer_supplies = 1, |
| 196 | }; | 198 | }; |
| 197 | 199 | ||
| 200 | static int arizona_micsupp_of_get_pdata(struct arizona *arizona, | ||
| 201 | struct regulator_config *config) | ||
| 202 | { | ||
| 203 | struct arizona_pdata *pdata = &arizona->pdata; | ||
| 204 | struct arizona_micsupp *micsupp = config->driver_data; | ||
| 205 | struct device_node *np; | ||
| 206 | struct regulator_init_data *init_data; | ||
| 207 | |||
| 208 | np = of_get_child_by_name(arizona->dev->of_node, "micvdd"); | ||
| 209 | |||
| 210 | if (np) { | ||
| 211 | config->of_node = np; | ||
| 212 | |||
| 213 | init_data = of_get_regulator_init_data(arizona->dev, np); | ||
| 214 | |||
| 215 | if (init_data) { | ||
| 216 | init_data->consumer_supplies = &micsupp->supply; | ||
| 217 | init_data->num_consumer_supplies = 1; | ||
| 218 | |||
| 219 | pdata->micvdd = init_data; | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | return 0; | ||
| 224 | } | ||
| 225 | |||
| 198 | static int arizona_micsupp_probe(struct platform_device *pdev) | 226 | static int arizona_micsupp_probe(struct platform_device *pdev) |
| 199 | { | 227 | { |
| 200 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | 228 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); |
| @@ -234,6 +262,14 @@ static int arizona_micsupp_probe(struct platform_device *pdev) | |||
| 234 | config.driver_data = micsupp; | 262 | config.driver_data = micsupp; |
| 235 | config.regmap = arizona->regmap; | 263 | config.regmap = arizona->regmap; |
| 236 | 264 | ||
| 265 | if (IS_ENABLED(CONFIG_OF)) { | ||
| 266 | if (!dev_get_platdata(arizona->dev)) { | ||
| 267 | ret = arizona_micsupp_of_get_pdata(arizona, &config); | ||
| 268 | if (ret < 0) | ||
| 269 | return ret; | ||
| 270 | } | ||
| 271 | } | ||
| 272 | |||
| 237 | if (arizona->pdata.micvdd) | 273 | if (arizona->pdata.micvdd) |
| 238 | config.init_data = arizona->pdata.micvdd; | 274 | config.init_data = arizona->pdata.micvdd; |
| 239 | else | 275 | else |
| @@ -253,6 +289,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev) | |||
| 253 | return ret; | 289 | return ret; |
| 254 | } | 290 | } |
| 255 | 291 | ||
| 292 | of_node_put(config.of_node); | ||
| 293 | |||
| 256 | platform_set_drvdata(pdev, micsupp); | 294 | platform_set_drvdata(pdev, micsupp); |
| 257 | 295 | ||
| 258 | return 0; | 296 | return 0; |
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c new file mode 100644 index 000000000000..004aadb7bcc1 --- /dev/null +++ b/drivers/regulator/axp20x-regulator.c | |||
| @@ -0,0 +1,286 @@ | |||
| 1 | /* | ||
| 2 | * AXP20x regulators driver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Carlo Caione <carlo@caione.org> | ||
| 5 | * | ||
| 6 | * This file is subject to the terms and conditions of the GNU General | ||
| 7 | * Public License. See the file "COPYING" in the main directory of this | ||
| 8 | * archive for more details. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/err.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/of.h> | ||
| 20 | #include <linux/of_device.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/regmap.h> | ||
| 23 | #include <linux/mfd/axp20x.h> | ||
| 24 | #include <linux/regulator/driver.h> | ||
| 25 | #include <linux/regulator/of_regulator.h> | ||
| 26 | |||
| 27 | #define AXP20X_IO_ENABLED 0x03 | ||
| 28 | #define AXP20X_IO_DISABLED 0x07 | ||
| 29 | |||
| 30 | #define AXP20X_WORKMODE_DCDC2_MASK BIT(2) | ||
| 31 | #define AXP20X_WORKMODE_DCDC3_MASK BIT(1) | ||
| 32 | |||
| 33 | #define AXP20X_FREQ_DCDC_MASK 0x0f | ||
| 34 | |||
| 35 | #define AXP20X_DESC_IO(_id, _supply, _min, _max, _step, _vreg, _vmask, _ereg, \ | ||
| 36 | _emask, _enable_val, _disable_val) \ | ||
| 37 | [AXP20X_##_id] = { \ | ||
| 38 | .name = #_id, \ | ||
| 39 | .supply_name = (_supply), \ | ||
| 40 | .type = REGULATOR_VOLTAGE, \ | ||
| 41 | .id = AXP20X_##_id, \ | ||
| 42 | .n_voltages = (((_max) - (_min)) / (_step) + 1), \ | ||
| 43 | .owner = THIS_MODULE, \ | ||
| 44 | .min_uV = (_min) * 1000, \ | ||
| 45 | .uV_step = (_step) * 1000, \ | ||
| 46 | .vsel_reg = (_vreg), \ | ||
| 47 | .vsel_mask = (_vmask), \ | ||
| 48 | .enable_reg = (_ereg), \ | ||
| 49 | .enable_mask = (_emask), \ | ||
| 50 | .enable_val = (_enable_val), \ | ||
| 51 | .disable_val = (_disable_val), \ | ||
| 52 | .ops = &axp20x_ops, \ | ||
| 53 | } | ||
| 54 | |||
| 55 | #define AXP20X_DESC(_id, _supply, _min, _max, _step, _vreg, _vmask, _ereg, \ | ||
| 56 | _emask) \ | ||
| 57 | [AXP20X_##_id] = { \ | ||
| 58 | .name = #_id, \ | ||
| 59 | .supply_name = (_supply), \ | ||
| 60 | .type = REGULATOR_VOLTAGE, \ | ||
| 61 | .id = AXP20X_##_id, \ | ||
| 62 | .n_voltages = (((_max) - (_min)) / (_step) + 1), \ | ||
| 63 | .owner = THIS_MODULE, \ | ||
| 64 | .min_uV = (_min) * 1000, \ | ||
| 65 | .uV_step = (_step) * 1000, \ | ||
| 66 | .vsel_reg = (_vreg), \ | ||
| 67 | .vsel_mask = (_vmask), \ | ||
| 68 | .enable_reg = (_ereg), \ | ||
| 69 | .enable_mask = (_emask), \ | ||
| 70 | .ops = &axp20x_ops, \ | ||
| 71 | } | ||
| 72 | |||
| 73 | #define AXP20X_DESC_FIXED(_id, _supply, _volt) \ | ||
| 74 | [AXP20X_##_id] = { \ | ||
| 75 | .name = #_id, \ | ||
| 76 | .supply_name = (_supply), \ | ||
| 77 | .type = REGULATOR_VOLTAGE, \ | ||
| 78 | .id = AXP20X_##_id, \ | ||
| 79 | .n_voltages = 1, \ | ||
| 80 | .owner = THIS_MODULE, \ | ||
| 81 | .min_uV = (_volt) * 1000, \ | ||
| 82 | .ops = &axp20x_ops_fixed \ | ||
| 83 | } | ||
| 84 | |||
| 85 | #define AXP20X_DESC_TABLE(_id, _supply, _table, _vreg, _vmask, _ereg, _emask) \ | ||
| 86 | [AXP20X_##_id] = { \ | ||
| 87 | .name = #_id, \ | ||
| 88 | .supply_name = (_supply), \ | ||
| 89 | .type = REGULATOR_VOLTAGE, \ | ||
| 90 | .id = AXP20X_##_id, \ | ||
| 91 | .n_voltages = ARRAY_SIZE(_table), \ | ||
| 92 | .owner = THIS_MODULE, \ | ||
| 93 | .vsel_reg = (_vreg), \ | ||
| 94 | .vsel_mask = (_vmask), \ | ||
| 95 | .enable_reg = (_ereg), \ | ||
| 96 | .enable_mask = (_emask), \ | ||
| 97 | .volt_table = (_table), \ | ||
| 98 | .ops = &axp20x_ops_table, \ | ||
| 99 | } | ||
| 100 | |||
| 101 | static const int axp20x_ldo4_data[] = { 1250000, 1300000, 1400000, 1500000, 1600000, | ||
| 102 | 1700000, 1800000, 1900000, 2000000, 2500000, | ||
| 103 | 2700000, 2800000, 3000000, 3100000, 3200000, | ||
| 104 | 3300000 }; | ||
| 105 | |||
| 106 | static struct regulator_ops axp20x_ops_fixed = { | ||
| 107 | .list_voltage = regulator_list_voltage_linear, | ||
| 108 | }; | ||
| 109 | |||
| 110 | static struct regulator_ops axp20x_ops_table = { | ||
| 111 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
| 112 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
| 113 | .list_voltage = regulator_list_voltage_table, | ||
| 114 | .map_voltage = regulator_map_voltage_ascend, | ||
| 115 | .enable = regulator_enable_regmap, | ||
| 116 | .disable = regulator_disable_regmap, | ||
| 117 | .is_enabled = regulator_is_enabled_regmap, | ||
| 118 | }; | ||
| 119 | |||
| 120 | static struct regulator_ops axp20x_ops = { | ||
| 121 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
| 122 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
| 123 | .list_voltage = regulator_list_voltage_linear, | ||
| 124 | .enable = regulator_enable_regmap, | ||
| 125 | .disable = regulator_disable_regmap, | ||
| 126 | .is_enabled = regulator_is_enabled_regmap, | ||
| 127 | }; | ||
| 128 | |||
| 129 | static const struct regulator_desc axp20x_regulators[] = { | ||
| 130 | AXP20X_DESC(DCDC2, "vin2", 700, 2275, 25, AXP20X_DCDC2_V_OUT, 0x3f, | ||
| 131 | AXP20X_PWR_OUT_CTRL, 0x10), | ||
| 132 | AXP20X_DESC(DCDC3, "vin3", 700, 3500, 25, AXP20X_DCDC3_V_OUT, 0x7f, | ||
| 133 | AXP20X_PWR_OUT_CTRL, 0x02), | ||
| 134 | AXP20X_DESC_FIXED(LDO1, "acin", 1300), | ||
| 135 | AXP20X_DESC(LDO2, "ldo24in", 1800, 3300, 100, AXP20X_LDO24_V_OUT, 0xf0, | ||
| 136 | AXP20X_PWR_OUT_CTRL, 0x04), | ||
| 137 | AXP20X_DESC(LDO3, "ldo3in", 700, 3500, 25, AXP20X_LDO3_V_OUT, 0x7f, | ||
| 138 | AXP20X_PWR_OUT_CTRL, 0x40), | ||
| 139 | AXP20X_DESC_TABLE(LDO4, "ldo24in", axp20x_ldo4_data, AXP20X_LDO24_V_OUT, 0x0f, | ||
| 140 | AXP20X_PWR_OUT_CTRL, 0x08), | ||
| 141 | AXP20X_DESC_IO(LDO5, "ldo5in", 1800, 3300, 100, AXP20X_LDO5_V_OUT, 0xf0, | ||
| 142 | AXP20X_GPIO0_CTRL, 0x07, AXP20X_IO_ENABLED, | ||
| 143 | AXP20X_IO_DISABLED), | ||
| 144 | }; | ||
| 145 | |||
| 146 | #define AXP_MATCH(_name, _id) \ | ||
| 147 | [AXP20X_##_id] = { \ | ||
| 148 | .name = #_name, \ | ||
| 149 | .driver_data = (void *) &axp20x_regulators[AXP20X_##_id], \ | ||
| 150 | } | ||
| 151 | |||
| 152 | static struct of_regulator_match axp20x_matches[] = { | ||
| 153 | AXP_MATCH(dcdc2, DCDC2), | ||
| 154 | AXP_MATCH(dcdc3, DCDC3), | ||
| 155 | AXP_MATCH(ldo1, LDO1), | ||
| 156 | AXP_MATCH(ldo2, LDO2), | ||
| 157 | AXP_MATCH(ldo3, LDO3), | ||
| 158 | AXP_MATCH(ldo4, LDO4), | ||
| 159 | AXP_MATCH(ldo5, LDO5), | ||
| 160 | }; | ||
| 161 | |||
| 162 | static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) | ||
| 163 | { | ||
| 164 | struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); | ||
| 165 | |||
| 166 | if (dcdcfreq < 750) { | ||
| 167 | dcdcfreq = 750; | ||
| 168 | dev_warn(&pdev->dev, "DCDC frequency too low. Set to 750kHz\n"); | ||
| 169 | } | ||
| 170 | |||
| 171 | if (dcdcfreq > 1875) { | ||
| 172 | dcdcfreq = 1875; | ||
| 173 | dev_warn(&pdev->dev, "DCDC frequency too high. Set to 1875kHz\n"); | ||
| 174 | } | ||
| 175 | |||
| 176 | dcdcfreq = (dcdcfreq - 750) / 75; | ||
| 177 | |||
| 178 | return regmap_update_bits(axp20x->regmap, AXP20X_DCDC_FREQ, | ||
| 179 | AXP20X_FREQ_DCDC_MASK, dcdcfreq); | ||
| 180 | } | ||
| 181 | |||
| 182 | static int axp20x_regulator_parse_dt(struct platform_device *pdev) | ||
| 183 | { | ||
| 184 | struct device_node *np, *regulators; | ||
| 185 | int ret; | ||
| 186 | u32 dcdcfreq; | ||
| 187 | |||
| 188 | np = of_node_get(pdev->dev.parent->of_node); | ||
| 189 | if (!np) | ||
| 190 | return 0; | ||
| 191 | |||
| 192 | regulators = of_get_child_by_name(np, "regulators"); | ||
| 193 | if (!regulators) { | ||
| 194 | dev_warn(&pdev->dev, "regulators node not found\n"); | ||
| 195 | } else { | ||
| 196 | ret = of_regulator_match(&pdev->dev, regulators, axp20x_matches, | ||
| 197 | ARRAY_SIZE(axp20x_matches)); | ||
| 198 | if (ret < 0) { | ||
| 199 | dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret); | ||
| 200 | return ret; | ||
| 201 | } | ||
| 202 | |||
| 203 | dcdcfreq = 1500; | ||
| 204 | of_property_read_u32(regulators, "x-powers,dcdc-freq", &dcdcfreq); | ||
| 205 | ret = axp20x_set_dcdc_freq(pdev, dcdcfreq); | ||
| 206 | if (ret < 0) { | ||
| 207 | dev_err(&pdev->dev, "Error setting dcdc frequency: %d\n", ret); | ||
| 208 | return ret; | ||
| 209 | } | ||
| 210 | |||
| 211 | of_node_put(regulators); | ||
| 212 | } | ||
| 213 | |||
| 214 | return 0; | ||
| 215 | } | ||
| 216 | |||
| 217 | static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode) | ||
| 218 | { | ||
| 219 | unsigned int mask = AXP20X_WORKMODE_DCDC2_MASK; | ||
| 220 | |||
| 221 | if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3)) | ||
| 222 | return -EINVAL; | ||
| 223 | |||
| 224 | if (id == AXP20X_DCDC3) | ||
| 225 | mask = AXP20X_WORKMODE_DCDC3_MASK; | ||
| 226 | |||
| 227 | workmode <<= ffs(mask) - 1; | ||
| 228 | |||
| 229 | return regmap_update_bits(rdev->regmap, AXP20X_DCDC_MODE, mask, workmode); | ||
| 230 | } | ||
| 231 | |||
| 232 | static int axp20x_regulator_probe(struct platform_device *pdev) | ||
| 233 | { | ||
| 234 | struct regulator_dev *rdev; | ||
| 235 | struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); | ||
| 236 | struct regulator_config config = { }; | ||
| 237 | struct regulator_init_data *init_data; | ||
| 238 | int ret, i; | ||
| 239 | u32 workmode; | ||
| 240 | |||
| 241 | ret = axp20x_regulator_parse_dt(pdev); | ||
| 242 | if (ret) | ||
| 243 | return ret; | ||
| 244 | |||
| 245 | for (i = 0; i < AXP20X_REG_ID_MAX; i++) { | ||
| 246 | init_data = axp20x_matches[i].init_data; | ||
| 247 | |||
| 248 | config.dev = &pdev->dev; | ||
| 249 | config.init_data = init_data; | ||
| 250 | config.regmap = axp20x->regmap; | ||
| 251 | config.of_node = axp20x_matches[i].of_node; | ||
| 252 | |||
| 253 | rdev = devm_regulator_register(&pdev->dev, &axp20x_regulators[i], | ||
| 254 | &config); | ||
| 255 | if (IS_ERR(rdev)) { | ||
| 256 | dev_err(&pdev->dev, "Failed to register %s\n", | ||
| 257 | axp20x_regulators[i].name); | ||
| 258 | |||
| 259 | return PTR_ERR(rdev); | ||
| 260 | } | ||
| 261 | |||
| 262 | ret = of_property_read_u32(axp20x_matches[i].of_node, "x-powers,dcdc-workmode", | ||
| 263 | &workmode); | ||
| 264 | if (!ret) { | ||
| 265 | if (axp20x_set_dcdc_workmode(rdev, i, workmode)) | ||
| 266 | dev_err(&pdev->dev, "Failed to set workmode on %s\n", | ||
| 267 | axp20x_regulators[i].name); | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | return 0; | ||
| 272 | } | ||
| 273 | |||
| 274 | static struct platform_driver axp20x_regulator_driver = { | ||
| 275 | .probe = axp20x_regulator_probe, | ||
| 276 | .driver = { | ||
| 277 | .name = "axp20x-regulator", | ||
| 278 | .owner = THIS_MODULE, | ||
| 279 | }, | ||
| 280 | }; | ||
| 281 | |||
| 282 | module_platform_driver(axp20x_regulator_driver); | ||
| 283 | |||
| 284 | MODULE_LICENSE("GPL v2"); | ||
| 285 | MODULE_AUTHOR("Carlo Caione <carlo@caione.org>"); | ||
| 286 | MODULE_DESCRIPTION("Regulator Driver for AXP20X PMIC"); | ||
diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c index c3750c5b382b..57544e254a78 100644 --- a/drivers/regulator/bcm590xx-regulator.c +++ b/drivers/regulator/bcm590xx-regulator.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #include <linux/regulator/of_regulator.h> | 22 | #include <linux/regulator/of_regulator.h> |
| 23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 24 | 24 | ||
| 25 | /* Register defs */ | 25 | /* I2C slave 0 registers */ |
| 26 | #define BCM590XX_RFLDOPMCTRL1 0x60 | 26 | #define BCM590XX_RFLDOPMCTRL1 0x60 |
| 27 | #define BCM590XX_IOSR1PMCTRL1 0x7a | 27 | #define BCM590XX_IOSR1PMCTRL1 0x7a |
| 28 | #define BCM590XX_IOSR2PMCTRL1 0x7c | 28 | #define BCM590XX_IOSR2PMCTRL1 0x7c |
| @@ -31,13 +31,34 @@ | |||
| 31 | #define BCM590XX_SDSR2PMCTRL1 0x86 | 31 | #define BCM590XX_SDSR2PMCTRL1 0x86 |
| 32 | #define BCM590XX_MSRPMCTRL1 0x8a | 32 | #define BCM590XX_MSRPMCTRL1 0x8a |
| 33 | #define BCM590XX_VSRPMCTRL1 0x8e | 33 | #define BCM590XX_VSRPMCTRL1 0x8e |
| 34 | #define BCM590XX_REG_ENABLE BIT(7) | ||
| 35 | |||
| 36 | #define BCM590XX_RFLDOCTRL 0x96 | 34 | #define BCM590XX_RFLDOCTRL 0x96 |
| 37 | #define BCM590XX_CSRVOUT1 0xc0 | 35 | #define BCM590XX_CSRVOUT1 0xc0 |
| 36 | |||
| 37 | /* I2C slave 1 registers */ | ||
| 38 | #define BCM590XX_GPLDO5PMCTRL1 0x16 | ||
| 39 | #define BCM590XX_GPLDO6PMCTRL1 0x18 | ||
| 40 | #define BCM590XX_GPLDO1CTRL 0x1a | ||
| 41 | #define BCM590XX_GPLDO2CTRL 0x1b | ||
| 42 | #define BCM590XX_GPLDO3CTRL 0x1c | ||
| 43 | #define BCM590XX_GPLDO4CTRL 0x1d | ||
| 44 | #define BCM590XX_GPLDO5CTRL 0x1e | ||
| 45 | #define BCM590XX_GPLDO6CTRL 0x1f | ||
| 46 | #define BCM590XX_OTG_CTRL 0x40 | ||
| 47 | #define BCM590XX_GPLDO1PMCTRL1 0x57 | ||
| 48 | #define BCM590XX_GPLDO2PMCTRL1 0x59 | ||
| 49 | #define BCM590XX_GPLDO3PMCTRL1 0x5b | ||
| 50 | #define BCM590XX_GPLDO4PMCTRL1 0x5d | ||
| 51 | |||
| 52 | #define BCM590XX_REG_ENABLE BIT(7) | ||
| 53 | #define BCM590XX_VBUS_ENABLE BIT(2) | ||
| 38 | #define BCM590XX_LDO_VSEL_MASK GENMASK(5, 3) | 54 | #define BCM590XX_LDO_VSEL_MASK GENMASK(5, 3) |
| 39 | #define BCM590XX_SR_VSEL_MASK GENMASK(5, 0) | 55 | #define BCM590XX_SR_VSEL_MASK GENMASK(5, 0) |
| 40 | 56 | ||
| 57 | /* | ||
| 58 | * RFLDO to VSR regulators are | ||
| 59 | * accessed via I2C slave 0 | ||
| 60 | */ | ||
| 61 | |||
| 41 | /* LDO regulator IDs */ | 62 | /* LDO regulator IDs */ |
| 42 | #define BCM590XX_REG_RFLDO 0 | 63 | #define BCM590XX_REG_RFLDO 0 |
| 43 | #define BCM590XX_REG_CAMLDO1 1 | 64 | #define BCM590XX_REG_CAMLDO1 1 |
| @@ -62,9 +83,25 @@ | |||
| 62 | #define BCM590XX_REG_SDSR2 18 | 83 | #define BCM590XX_REG_SDSR2 18 |
| 63 | #define BCM590XX_REG_VSR 19 | 84 | #define BCM590XX_REG_VSR 19 |
| 64 | 85 | ||
| 65 | #define BCM590XX_NUM_REGS 20 | 86 | /* |
| 87 | * GPLDO1 to VBUS regulators are | ||
| 88 | * accessed via I2C slave 1 | ||
| 89 | */ | ||
| 90 | |||
| 91 | #define BCM590XX_REG_GPLDO1 20 | ||
| 92 | #define BCM590XX_REG_GPLDO2 21 | ||
| 93 | #define BCM590XX_REG_GPLDO3 22 | ||
| 94 | #define BCM590XX_REG_GPLDO4 23 | ||
| 95 | #define BCM590XX_REG_GPLDO5 24 | ||
| 96 | #define BCM590XX_REG_GPLDO6 25 | ||
| 97 | #define BCM590XX_REG_VBUS 26 | ||
| 98 | |||
| 99 | #define BCM590XX_NUM_REGS 27 | ||
| 66 | 100 | ||
| 67 | #define BCM590XX_REG_IS_LDO(n) (n < BCM590XX_REG_CSR) | 101 | #define BCM590XX_REG_IS_LDO(n) (n < BCM590XX_REG_CSR) |
| 102 | #define BCM590XX_REG_IS_GPLDO(n) \ | ||
| 103 | ((n > BCM590XX_REG_VSR) && (n < BCM590XX_REG_VBUS)) | ||
| 104 | #define BCM590XX_REG_IS_VBUS(n) (n == BCM590XX_REG_VBUS) | ||
| 68 | 105 | ||
| 69 | struct bcm590xx_board { | 106 | struct bcm590xx_board { |
| 70 | struct regulator_init_data *bcm590xx_pmu_init_data[BCM590XX_NUM_REGS]; | 107 | struct regulator_init_data *bcm590xx_pmu_init_data[BCM590XX_NUM_REGS]; |
| @@ -149,6 +186,12 @@ static struct bcm590xx_info bcm590xx_regs[] = { | |||
| 149 | BCM590XX_REG_RANGES(sdsr1, dcdc_sdsr1_ranges), | 186 | BCM590XX_REG_RANGES(sdsr1, dcdc_sdsr1_ranges), |
| 150 | BCM590XX_REG_RANGES(sdsr2, dcdc_iosr1_ranges), | 187 | BCM590XX_REG_RANGES(sdsr2, dcdc_iosr1_ranges), |
| 151 | BCM590XX_REG_RANGES(vsr, dcdc_iosr1_ranges), | 188 | BCM590XX_REG_RANGES(vsr, dcdc_iosr1_ranges), |
| 189 | BCM590XX_REG_TABLE(gpldo1, ldo_a_table), | ||
| 190 | BCM590XX_REG_TABLE(gpldo2, ldo_a_table), | ||
| 191 | BCM590XX_REG_TABLE(gpldo3, ldo_a_table), | ||
| 192 | BCM590XX_REG_TABLE(gpldo4, ldo_a_table), | ||
| 193 | BCM590XX_REG_TABLE(gpldo5, ldo_a_table), | ||
| 194 | BCM590XX_REG_TABLE(gpldo6, ldo_a_table), | ||
| 152 | }; | 195 | }; |
| 153 | 196 | ||
| 154 | struct bcm590xx_reg { | 197 | struct bcm590xx_reg { |
| @@ -161,6 +204,8 @@ static int bcm590xx_get_vsel_register(int id) | |||
| 161 | { | 204 | { |
| 162 | if (BCM590XX_REG_IS_LDO(id)) | 205 | if (BCM590XX_REG_IS_LDO(id)) |
| 163 | return BCM590XX_RFLDOCTRL + id; | 206 | return BCM590XX_RFLDOCTRL + id; |
| 207 | else if (BCM590XX_REG_IS_GPLDO(id)) | ||
| 208 | return BCM590XX_GPLDO1CTRL + id; | ||
| 164 | else | 209 | else |
| 165 | return BCM590XX_CSRVOUT1 + (id - BCM590XX_REG_CSR) * 3; | 210 | return BCM590XX_CSRVOUT1 + (id - BCM590XX_REG_CSR) * 3; |
| 166 | } | 211 | } |
| @@ -171,6 +216,8 @@ static int bcm590xx_get_enable_register(int id) | |||
| 171 | 216 | ||
| 172 | if (BCM590XX_REG_IS_LDO(id)) | 217 | if (BCM590XX_REG_IS_LDO(id)) |
| 173 | reg = BCM590XX_RFLDOPMCTRL1 + id * 2; | 218 | reg = BCM590XX_RFLDOPMCTRL1 + id * 2; |
| 219 | else if (BCM590XX_REG_IS_GPLDO(id)) | ||
| 220 | reg = BCM590XX_GPLDO1PMCTRL1 + id * 2; | ||
| 174 | else | 221 | else |
| 175 | switch (id) { | 222 | switch (id) { |
| 176 | case BCM590XX_REG_CSR: | 223 | case BCM590XX_REG_CSR: |
| @@ -191,8 +238,11 @@ static int bcm590xx_get_enable_register(int id) | |||
| 191 | case BCM590XX_REG_SDSR2: | 238 | case BCM590XX_REG_SDSR2: |
| 192 | reg = BCM590XX_SDSR2PMCTRL1; | 239 | reg = BCM590XX_SDSR2PMCTRL1; |
| 193 | break; | 240 | break; |
| 241 | case BCM590XX_REG_VBUS: | ||
| 242 | reg = BCM590XX_OTG_CTRL; | ||
| 194 | }; | 243 | }; |
| 195 | 244 | ||
| 245 | |||
| 196 | return reg; | 246 | return reg; |
| 197 | } | 247 | } |
| 198 | 248 | ||
| @@ -216,6 +266,12 @@ static struct regulator_ops bcm590xx_ops_dcdc = { | |||
| 216 | .map_voltage = regulator_map_voltage_linear_range, | 266 | .map_voltage = regulator_map_voltage_linear_range, |
| 217 | }; | 267 | }; |
| 218 | 268 | ||
| 269 | static struct regulator_ops bcm590xx_ops_vbus = { | ||
| 270 | .is_enabled = regulator_is_enabled_regmap, | ||
| 271 | .enable = regulator_enable_regmap, | ||
| 272 | .disable = regulator_disable_regmap, | ||
| 273 | }; | ||
| 274 | |||
| 219 | #define BCM590XX_MATCH(_name, _id) \ | 275 | #define BCM590XX_MATCH(_name, _id) \ |
| 220 | { \ | 276 | { \ |
| 221 | .name = #_name, \ | 277 | .name = #_name, \ |
| @@ -243,6 +299,13 @@ static struct of_regulator_match bcm590xx_matches[] = { | |||
| 243 | BCM590XX_MATCH(sdsr1, SDSR1), | 299 | BCM590XX_MATCH(sdsr1, SDSR1), |
| 244 | BCM590XX_MATCH(sdsr2, SDSR2), | 300 | BCM590XX_MATCH(sdsr2, SDSR2), |
| 245 | BCM590XX_MATCH(vsr, VSR), | 301 | BCM590XX_MATCH(vsr, VSR), |
| 302 | BCM590XX_MATCH(gpldo1, GPLDO1), | ||
| 303 | BCM590XX_MATCH(gpldo2, GPLDO2), | ||
| 304 | BCM590XX_MATCH(gpldo3, GPLDO3), | ||
| 305 | BCM590XX_MATCH(gpldo4, GPLDO4), | ||
| 306 | BCM590XX_MATCH(gpldo5, GPLDO5), | ||
| 307 | BCM590XX_MATCH(gpldo6, GPLDO6), | ||
| 308 | BCM590XX_MATCH(vbus, VBUS), | ||
| 246 | }; | 309 | }; |
| 247 | 310 | ||
| 248 | static struct bcm590xx_board *bcm590xx_parse_dt_reg_data( | 311 | static struct bcm590xx_board *bcm590xx_parse_dt_reg_data( |
| @@ -353,17 +416,23 @@ static int bcm590xx_probe(struct platform_device *pdev) | |||
| 353 | pmu->desc[i].linear_ranges = info->linear_ranges; | 416 | pmu->desc[i].linear_ranges = info->linear_ranges; |
| 354 | pmu->desc[i].n_linear_ranges = info->n_linear_ranges; | 417 | pmu->desc[i].n_linear_ranges = info->n_linear_ranges; |
| 355 | 418 | ||
| 356 | if (BCM590XX_REG_IS_LDO(i)) { | 419 | if ((BCM590XX_REG_IS_LDO(i)) || (BCM590XX_REG_IS_GPLDO(i))) { |
| 357 | pmu->desc[i].ops = &bcm590xx_ops_ldo; | 420 | pmu->desc[i].ops = &bcm590xx_ops_ldo; |
| 358 | pmu->desc[i].vsel_mask = BCM590XX_LDO_VSEL_MASK; | 421 | pmu->desc[i].vsel_mask = BCM590XX_LDO_VSEL_MASK; |
| 359 | } else { | 422 | } else if (BCM590XX_REG_IS_VBUS(i)) |
| 423 | pmu->desc[i].ops = &bcm590xx_ops_vbus; | ||
| 424 | else { | ||
| 360 | pmu->desc[i].ops = &bcm590xx_ops_dcdc; | 425 | pmu->desc[i].ops = &bcm590xx_ops_dcdc; |
| 361 | pmu->desc[i].vsel_mask = BCM590XX_SR_VSEL_MASK; | 426 | pmu->desc[i].vsel_mask = BCM590XX_SR_VSEL_MASK; |
| 362 | } | 427 | } |
| 363 | 428 | ||
| 364 | pmu->desc[i].vsel_reg = bcm590xx_get_vsel_register(i); | 429 | if (BCM590XX_REG_IS_VBUS(i)) |
| 365 | pmu->desc[i].enable_is_inverted = true; | 430 | pmu->desc[i].enable_mask = BCM590XX_VBUS_ENABLE; |
| 366 | pmu->desc[i].enable_mask = BCM590XX_REG_ENABLE; | 431 | else { |
| 432 | pmu->desc[i].vsel_reg = bcm590xx_get_vsel_register(i); | ||
| 433 | pmu->desc[i].enable_is_inverted = true; | ||
| 434 | pmu->desc[i].enable_mask = BCM590XX_REG_ENABLE; | ||
| 435 | } | ||
| 367 | pmu->desc[i].enable_reg = bcm590xx_get_enable_register(i); | 436 | pmu->desc[i].enable_reg = bcm590xx_get_enable_register(i); |
| 368 | pmu->desc[i].type = REGULATOR_VOLTAGE; | 437 | pmu->desc[i].type = REGULATOR_VOLTAGE; |
| 369 | pmu->desc[i].owner = THIS_MODULE; | 438 | pmu->desc[i].owner = THIS_MODULE; |
| @@ -371,7 +440,10 @@ static int bcm590xx_probe(struct platform_device *pdev) | |||
| 371 | config.dev = bcm590xx->dev; | 440 | config.dev = bcm590xx->dev; |
| 372 | config.init_data = reg_data; | 441 | config.init_data = reg_data; |
| 373 | config.driver_data = pmu; | 442 | config.driver_data = pmu; |
| 374 | config.regmap = bcm590xx->regmap; | 443 | if (BCM590XX_REG_IS_GPLDO(i) || BCM590XX_REG_IS_VBUS(i)) |
| 444 | config.regmap = bcm590xx->regmap_sec; | ||
| 445 | else | ||
| 446 | config.regmap = bcm590xx->regmap_pri; | ||
| 375 | 447 | ||
| 376 | if (bcm590xx_reg_matches) | 448 | if (bcm590xx_reg_matches) |
| 377 | config.of_node = bcm590xx_reg_matches[i].of_node; | 449 | config.of_node = bcm590xx_reg_matches[i].of_node; |
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 9a09f3cdbabb..4c1f999041dd 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
| @@ -844,13 +844,22 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, | |||
| 844 | /* do we need to apply the constraint voltage */ | 844 | /* do we need to apply the constraint voltage */ |
| 845 | if (rdev->constraints->apply_uV && | 845 | if (rdev->constraints->apply_uV && |
| 846 | rdev->constraints->min_uV == rdev->constraints->max_uV) { | 846 | rdev->constraints->min_uV == rdev->constraints->max_uV) { |
| 847 | ret = _regulator_do_set_voltage(rdev, | 847 | int current_uV = _regulator_get_voltage(rdev); |
| 848 | rdev->constraints->min_uV, | 848 | if (current_uV < 0) { |
| 849 | rdev->constraints->max_uV); | 849 | rdev_err(rdev, "failed to get the current voltage\n"); |
| 850 | if (ret < 0) { | 850 | return current_uV; |
| 851 | rdev_err(rdev, "failed to apply %duV constraint\n", | 851 | } |
| 852 | rdev->constraints->min_uV); | 852 | if (current_uV < rdev->constraints->min_uV || |
| 853 | return ret; | 853 | current_uV > rdev->constraints->max_uV) { |
| 854 | ret = _regulator_do_set_voltage( | ||
| 855 | rdev, rdev->constraints->min_uV, | ||
| 856 | rdev->constraints->max_uV); | ||
| 857 | if (ret < 0) { | ||
| 858 | rdev_err(rdev, | ||
| 859 | "failed to apply %duV constraint\n", | ||
| 860 | rdev->constraints->min_uV); | ||
| 861 | return ret; | ||
| 862 | } | ||
| 854 | } | 863 | } |
| 855 | } | 864 | } |
| 856 | 865 | ||
| @@ -1430,9 +1439,9 @@ EXPORT_SYMBOL_GPL(regulator_get); | |||
| 1430 | * | 1439 | * |
| 1431 | * Returns a struct regulator corresponding to the regulator producer, | 1440 | * Returns a struct regulator corresponding to the regulator producer, |
| 1432 | * or IS_ERR() condition containing errno. Other consumers will be | 1441 | * or IS_ERR() condition containing errno. Other consumers will be |
| 1433 | * unable to obtain this reference is held and the use count for the | 1442 | * unable to obtain this regulator while this reference is held and the |
| 1434 | * regulator will be initialised to reflect the current state of the | 1443 | * use count for the regulator will be initialised to reflect the current |
| 1435 | * regulator. | 1444 | * state of the regulator. |
| 1436 | * | 1445 | * |
| 1437 | * This is intended for use by consumers which cannot tolerate shared | 1446 | * This is intended for use by consumers which cannot tolerate shared |
| 1438 | * use of the regulator such as those which need to force the | 1447 | * use of the regulator such as those which need to force the |
| @@ -1456,10 +1465,7 @@ EXPORT_SYMBOL_GPL(regulator_get_exclusive); | |||
| 1456 | * @id: Supply name or regulator ID. | 1465 | * @id: Supply name or regulator ID. |
| 1457 | * | 1466 | * |
| 1458 | * Returns a struct regulator corresponding to the regulator producer, | 1467 | * Returns a struct regulator corresponding to the regulator producer, |
| 1459 | * or IS_ERR() condition containing errno. Other consumers will be | 1468 | * or IS_ERR() condition containing errno. |
| 1460 | * unable to obtain this reference is held and the use count for the | ||
| 1461 | * regulator will be initialised to reflect the current state of the | ||
| 1462 | * regulator. | ||
| 1463 | * | 1469 | * |
| 1464 | * This is intended for use by consumers for devices which can have | 1470 | * This is intended for use by consumers for devices which can have |
| 1465 | * some supplies unconnected in normal use, such as some MMC devices. | 1471 | * some supplies unconnected in normal use, such as some MMC devices. |
| @@ -1597,9 +1603,10 @@ EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); | |||
| 1597 | * registered any aliases that were registered will be removed | 1603 | * registered any aliases that were registered will be removed |
| 1598 | * before returning to the caller. | 1604 | * before returning to the caller. |
| 1599 | */ | 1605 | */ |
| 1600 | int regulator_bulk_register_supply_alias(struct device *dev, const char **id, | 1606 | int regulator_bulk_register_supply_alias(struct device *dev, |
| 1607 | const char *const *id, | ||
| 1601 | struct device *alias_dev, | 1608 | struct device *alias_dev, |
| 1602 | const char **alias_id, | 1609 | const char *const *alias_id, |
| 1603 | int num_id) | 1610 | int num_id) |
| 1604 | { | 1611 | { |
| 1605 | int i; | 1612 | int i; |
| @@ -1637,7 +1644,7 @@ EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); | |||
| 1637 | * aliases in one operation. | 1644 | * aliases in one operation. |
| 1638 | */ | 1645 | */ |
| 1639 | void regulator_bulk_unregister_supply_alias(struct device *dev, | 1646 | void regulator_bulk_unregister_supply_alias(struct device *dev, |
| 1640 | const char **id, | 1647 | const char *const *id, |
| 1641 | int num_id) | 1648 | int num_id) |
| 1642 | { | 1649 | { |
| 1643 | int i; | 1650 | int i; |
| @@ -2321,6 +2328,10 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, | |||
| 2321 | regulator_list_voltage_linear) | 2328 | regulator_list_voltage_linear) |
| 2322 | ret = regulator_map_voltage_linear(rdev, | 2329 | ret = regulator_map_voltage_linear(rdev, |
| 2323 | min_uV, max_uV); | 2330 | min_uV, max_uV); |
| 2331 | else if (rdev->desc->ops->list_voltage == | ||
| 2332 | regulator_list_voltage_linear_range) | ||
| 2333 | ret = regulator_map_voltage_linear_range(rdev, | ||
| 2334 | min_uV, max_uV); | ||
| 2324 | else | 2335 | else |
| 2325 | ret = regulator_map_voltage_iterate(rdev, | 2336 | ret = regulator_map_voltage_iterate(rdev, |
| 2326 | min_uV, max_uV); | 2337 | min_uV, max_uV); |
| @@ -3447,7 +3458,7 @@ regulator_register(const struct regulator_desc *regulator_desc, | |||
| 3447 | 3458 | ||
| 3448 | /* register with sysfs */ | 3459 | /* register with sysfs */ |
| 3449 | rdev->dev.class = ®ulator_class; | 3460 | rdev->dev.class = ®ulator_class; |
| 3450 | rdev->dev.of_node = config->of_node; | 3461 | rdev->dev.of_node = of_node_get(config->of_node); |
| 3451 | rdev->dev.parent = dev; | 3462 | rdev->dev.parent = dev; |
| 3452 | dev_set_name(&rdev->dev, "regulator.%d", | 3463 | dev_set_name(&rdev->dev, "regulator.%d", |
| 3453 | atomic_inc_return(®ulator_no) - 1); | 3464 | atomic_inc_return(®ulator_no) - 1); |
| @@ -3589,6 +3600,7 @@ void regulator_unregister(struct regulator_dev *rdev) | |||
| 3589 | list_del(&rdev->list); | 3600 | list_del(&rdev->list); |
| 3590 | kfree(rdev->constraints); | 3601 | kfree(rdev->constraints); |
| 3591 | regulator_ena_gpio_free(rdev); | 3602 | regulator_ena_gpio_free(rdev); |
| 3603 | of_node_put(rdev->dev.of_node); | ||
| 3592 | device_unregister(&rdev->dev); | 3604 | device_unregister(&rdev->dev); |
| 3593 | mutex_unlock(®ulator_list_mutex); | 3605 | mutex_unlock(®ulator_list_mutex); |
| 3594 | } | 3606 | } |
| @@ -3819,8 +3831,9 @@ static int __init regulator_init_complete(void) | |||
| 3819 | mutex_lock(®ulator_list_mutex); | 3831 | mutex_lock(®ulator_list_mutex); |
| 3820 | 3832 | ||
| 3821 | /* If we have a full configuration then disable any regulators | 3833 | /* If we have a full configuration then disable any regulators |
| 3822 | * which are not in use or always_on. This will become the | 3834 | * we have permission to change the status for and which are |
| 3823 | * default behaviour in the future. | 3835 | * not in use or always_on. This is effectively the default |
| 3836 | * for DT and ACPI as they have full constraints. | ||
| 3824 | */ | 3837 | */ |
| 3825 | list_for_each_entry(rdev, ®ulator_list, list) { | 3838 | list_for_each_entry(rdev, ®ulator_list, list) { |
| 3826 | ops = rdev->desc->ops; | 3839 | ops = rdev->desc->ops; |
| @@ -3829,6 +3842,9 @@ static int __init regulator_init_complete(void) | |||
| 3829 | if (c && c->always_on) | 3842 | if (c && c->always_on) |
| 3830 | continue; | 3843 | continue; |
| 3831 | 3844 | ||
| 3845 | if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS)) | ||
| 3846 | continue; | ||
| 3847 | |||
| 3832 | mutex_lock(&rdev->mutex); | 3848 | mutex_lock(&rdev->mutex); |
| 3833 | 3849 | ||
| 3834 | if (rdev->use_count) | 3850 | if (rdev->use_count) |
| @@ -3867,4 +3883,4 @@ unlock: | |||
| 3867 | 3883 | ||
| 3868 | return 0; | 3884 | return 0; |
| 3869 | } | 3885 | } |
| 3870 | late_initcall(regulator_init_complete); | 3886 | late_initcall_sync(regulator_init_complete); |
diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c index f44818b838dc..8f785bc9e510 100644 --- a/drivers/regulator/devres.c +++ b/drivers/regulator/devres.c | |||
| @@ -360,9 +360,9 @@ EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias); | |||
| 360 | * will be removed before returning to the caller. | 360 | * will be removed before returning to the caller. |
| 361 | */ | 361 | */ |
| 362 | int devm_regulator_bulk_register_supply_alias(struct device *dev, | 362 | int devm_regulator_bulk_register_supply_alias(struct device *dev, |
| 363 | const char **id, | 363 | const char *const *id, |
| 364 | struct device *alias_dev, | 364 | struct device *alias_dev, |
| 365 | const char **alias_id, | 365 | const char *const *alias_id, |
| 366 | int num_id) | 366 | int num_id) |
| 367 | { | 367 | { |
| 368 | int i; | 368 | int i; |
| @@ -404,7 +404,7 @@ EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias); | |||
| 404 | * will ensure that the resource is freed. | 404 | * will ensure that the resource is freed. |
| 405 | */ | 405 | */ |
| 406 | void devm_regulator_bulk_unregister_supply_alias(struct device *dev, | 406 | void devm_regulator_bulk_unregister_supply_alias(struct device *dev, |
| 407 | const char **id, | 407 | const char *const *id, |
| 408 | int num_id) | 408 | int num_id) |
| 409 | { | 409 | { |
| 410 | int i; | 410 | int i; |
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index c61f7e97e4f8..354105eff1f8 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c | |||
| @@ -50,7 +50,6 @@ of_get_fixed_voltage_config(struct device *dev) | |||
| 50 | { | 50 | { |
| 51 | struct fixed_voltage_config *config; | 51 | struct fixed_voltage_config *config; |
| 52 | struct device_node *np = dev->of_node; | 52 | struct device_node *np = dev->of_node; |
| 53 | const __be32 *delay; | ||
| 54 | struct regulator_init_data *init_data; | 53 | struct regulator_init_data *init_data; |
| 55 | 54 | ||
| 56 | config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config), | 55 | config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config), |
| @@ -91,15 +90,11 @@ of_get_fixed_voltage_config(struct device *dev) | |||
| 91 | if ((config->gpio == -ENODEV) || (config->gpio == -EPROBE_DEFER)) | 90 | if ((config->gpio == -ENODEV) || (config->gpio == -EPROBE_DEFER)) |
| 92 | return ERR_PTR(-EPROBE_DEFER); | 91 | return ERR_PTR(-EPROBE_DEFER); |
| 93 | 92 | ||
| 94 | delay = of_get_property(np, "startup-delay-us", NULL); | 93 | of_property_read_u32(np, "startup-delay-us", &config->startup_delay); |
| 95 | if (delay) | ||
| 96 | config->startup_delay = be32_to_cpu(*delay); | ||
| 97 | 94 | ||
| 98 | if (of_find_property(np, "enable-active-high", NULL)) | 95 | config->enable_high = of_property_read_bool(np, "enable-active-high"); |
| 99 | config->enable_high = true; | 96 | config->gpio_is_open_drain = of_property_read_bool(np, |
| 100 | 97 | "gpio-open-drain"); | |
| 101 | if (of_find_property(np, "gpio-open-drain", NULL)) | ||
| 102 | config->gpio_is_open_drain = true; | ||
| 103 | 98 | ||
| 104 | if (of_find_property(np, "vin-supply", NULL)) | 99 | if (of_find_property(np, "vin-supply", NULL)) |
| 105 | config->input_supply = "vin"; | 100 | config->input_supply = "vin"; |
diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c new file mode 100644 index 000000000000..110a99ee1162 --- /dev/null +++ b/drivers/regulator/ltc3589.c | |||
| @@ -0,0 +1,554 @@ | |||
| 1 | /* | ||
| 2 | * Linear Technology LTC3589,LTC3589-1 regulator support | ||
| 3 | * | ||
| 4 | * Copyright (c) 2014 Philipp Zabel <p.zabel@pengutronix.de>, Pengutronix | ||
| 5 | * | ||
| 6 | * See file CREDITS for list of people who contributed to this | ||
| 7 | * project. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 | ||
| 11 | * as published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | #include <linux/i2c.h> | ||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/of.h> | ||
| 25 | #include <linux/regmap.h> | ||
| 26 | #include <linux/regulator/driver.h> | ||
| 27 | #include <linux/regulator/of_regulator.h> | ||
| 28 | |||
| 29 | #define DRIVER_NAME "ltc3589" | ||
| 30 | |||
| 31 | #define LTC3589_IRQSTAT 0x02 | ||
| 32 | #define LTC3589_SCR1 0x07 | ||
| 33 | #define LTC3589_OVEN 0x10 | ||
| 34 | #define LTC3589_SCR2 0x12 | ||
| 35 | #define LTC3589_PGSTAT 0x13 | ||
| 36 | #define LTC3589_VCCR 0x20 | ||
| 37 | #define LTC3589_CLIRQ 0x21 | ||
| 38 | #define LTC3589_B1DTV1 0x23 | ||
| 39 | #define LTC3589_B1DTV2 0x24 | ||
| 40 | #define LTC3589_VRRCR 0x25 | ||
| 41 | #define LTC3589_B2DTV1 0x26 | ||
| 42 | #define LTC3589_B2DTV2 0x27 | ||
| 43 | #define LTC3589_B3DTV1 0x29 | ||
| 44 | #define LTC3589_B3DTV2 0x2a | ||
| 45 | #define LTC3589_L2DTV1 0x32 | ||
| 46 | #define LTC3589_L2DTV2 0x33 | ||
| 47 | |||
| 48 | #define LTC3589_IRQSTAT_PGOOD_TIMEOUT BIT(3) | ||
| 49 | #define LTC3589_IRQSTAT_UNDERVOLT_WARN BIT(4) | ||
| 50 | #define LTC3589_IRQSTAT_UNDERVOLT_FAULT BIT(5) | ||
| 51 | #define LTC3589_IRQSTAT_THERMAL_WARN BIT(6) | ||
| 52 | #define LTC3589_IRQSTAT_THERMAL_FAULT BIT(7) | ||
| 53 | |||
| 54 | #define LTC3589_OVEN_SW1 BIT(0) | ||
| 55 | #define LTC3589_OVEN_SW2 BIT(1) | ||
| 56 | #define LTC3589_OVEN_SW3 BIT(2) | ||
| 57 | #define LTC3589_OVEN_BB_OUT BIT(3) | ||
| 58 | #define LTC3589_OVEN_LDO2 BIT(4) | ||
| 59 | #define LTC3589_OVEN_LDO3 BIT(5) | ||
| 60 | #define LTC3589_OVEN_LDO4 BIT(6) | ||
| 61 | #define LTC3589_OVEN_SW_CTRL BIT(7) | ||
| 62 | |||
| 63 | #define LTC3589_VCCR_SW1_GO BIT(0) | ||
| 64 | #define LTC3589_VCCR_SW2_GO BIT(2) | ||
| 65 | #define LTC3589_VCCR_SW3_GO BIT(4) | ||
| 66 | #define LTC3589_VCCR_LDO2_GO BIT(6) | ||
| 67 | |||
| 68 | enum ltc3589_variant { | ||
| 69 | LTC3589, | ||
| 70 | LTC3589_1, | ||
| 71 | LTC3589_2, | ||
| 72 | }; | ||
| 73 | |||
| 74 | enum ltc3589_reg { | ||
| 75 | LTC3589_SW1, | ||
| 76 | LTC3589_SW2, | ||
| 77 | LTC3589_SW3, | ||
| 78 | LTC3589_BB_OUT, | ||
| 79 | LTC3589_LDO1, | ||
| 80 | LTC3589_LDO2, | ||
| 81 | LTC3589_LDO3, | ||
| 82 | LTC3589_LDO4, | ||
| 83 | LTC3589_NUM_REGULATORS, | ||
| 84 | }; | ||
| 85 | |||
| 86 | struct ltc3589_regulator { | ||
| 87 | struct regulator_desc desc; | ||
| 88 | |||
| 89 | /* External feedback voltage divider */ | ||
| 90 | unsigned int r1; | ||
| 91 | unsigned int r2; | ||
| 92 | }; | ||
| 93 | |||
| 94 | struct ltc3589 { | ||
| 95 | struct regmap *regmap; | ||
| 96 | struct device *dev; | ||
| 97 | enum ltc3589_variant variant; | ||
| 98 | struct ltc3589_regulator regulator_descs[LTC3589_NUM_REGULATORS]; | ||
| 99 | struct regulator_dev *regulators[LTC3589_NUM_REGULATORS]; | ||
| 100 | }; | ||
| 101 | |||
| 102 | static const int ltc3589_ldo4[] = { | ||
| 103 | 2800000, 2500000, 1800000, 3300000, | ||
| 104 | }; | ||
| 105 | |||
| 106 | static const int ltc3589_12_ldo4[] = { | ||
| 107 | 1200000, 1800000, 2500000, 3200000, | ||
| 108 | }; | ||
| 109 | |||
| 110 | static int ltc3589_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) | ||
| 111 | { | ||
| 112 | struct ltc3589 *ltc3589 = rdev_get_drvdata(rdev); | ||
| 113 | int sel, shift; | ||
| 114 | |||
| 115 | if (unlikely(ramp_delay <= 0)) | ||
| 116 | return -EINVAL; | ||
| 117 | |||
| 118 | /* VRRCR slew rate offsets are the same as VCCR go bit offsets */ | ||
| 119 | shift = ffs(rdev->desc->apply_bit) - 1; | ||
| 120 | |||
| 121 | /* The slew rate can be set to 0.88, 1.75, 3.5, or 7 mV/uS */ | ||
| 122 | for (sel = 0; sel < 4; sel++) { | ||
| 123 | if ((880 << sel) >= ramp_delay) { | ||
| 124 | return regmap_update_bits(ltc3589->regmap, | ||
| 125 | LTC3589_VRRCR, | ||
| 126 | 0x3 << shift, sel << shift); | ||
| 127 | } | ||
| 128 | } | ||
| 129 | return -EINVAL; | ||
| 130 | } | ||
| 131 | |||
| 132 | static int ltc3589_set_suspend_voltage(struct regulator_dev *rdev, int uV) | ||
| 133 | { | ||
| 134 | struct ltc3589 *ltc3589 = rdev_get_drvdata(rdev); | ||
| 135 | int sel; | ||
| 136 | |||
| 137 | sel = regulator_map_voltage_linear(rdev, uV, uV); | ||
| 138 | if (sel < 0) | ||
| 139 | return sel; | ||
| 140 | |||
| 141 | /* DTV2 register follows right after the corresponding DTV1 register */ | ||
| 142 | return regmap_update_bits(ltc3589->regmap, rdev->desc->vsel_reg + 1, | ||
| 143 | rdev->desc->vsel_mask, sel); | ||
| 144 | } | ||
| 145 | |||
| 146 | static int ltc3589_set_suspend_mode(struct regulator_dev *rdev, | ||
| 147 | unsigned int mode) | ||
| 148 | { | ||
| 149 | struct ltc3589 *ltc3589 = rdev_get_drvdata(rdev); | ||
| 150 | int mask, bit = 0; | ||
| 151 | |||
| 152 | /* VCCR reference selects are right next to the VCCR go bits */ | ||
| 153 | mask = rdev->desc->apply_bit << 1; | ||
| 154 | |||
| 155 | if (mode == REGULATOR_MODE_STANDBY) | ||
| 156 | bit = mask; /* Select DTV2 */ | ||
| 157 | |||
| 158 | mask |= rdev->desc->apply_bit; | ||
| 159 | bit |= rdev->desc->apply_bit; | ||
| 160 | return regmap_update_bits(ltc3589->regmap, LTC3589_VCCR, mask, bit); | ||
| 161 | } | ||
| 162 | |||
| 163 | /* SW1, SW2, SW3, LDO2 */ | ||
| 164 | static struct regulator_ops ltc3589_linear_regulator_ops = { | ||
| 165 | .enable = regulator_enable_regmap, | ||
| 166 | .disable = regulator_disable_regmap, | ||
| 167 | .is_enabled = regulator_is_enabled_regmap, | ||
| 168 | .list_voltage = regulator_list_voltage_linear, | ||
| 169 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
| 170 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
| 171 | .set_ramp_delay = ltc3589_set_ramp_delay, | ||
| 172 | .set_voltage_time_sel = regulator_set_voltage_time_sel, | ||
| 173 | .set_suspend_voltage = ltc3589_set_suspend_voltage, | ||
| 174 | .set_suspend_mode = ltc3589_set_suspend_mode, | ||
| 175 | }; | ||
| 176 | |||
| 177 | /* BB_OUT, LDO3 */ | ||
| 178 | static struct regulator_ops ltc3589_fixed_regulator_ops = { | ||
| 179 | .enable = regulator_enable_regmap, | ||
| 180 | .disable = regulator_disable_regmap, | ||
| 181 | .is_enabled = regulator_is_enabled_regmap, | ||
| 182 | }; | ||
| 183 | |||
| 184 | /* LDO1 */ | ||
| 185 | static struct regulator_ops ltc3589_fixed_standby_regulator_ops = { | ||
| 186 | }; | ||
| 187 | |||
| 188 | /* LDO4 */ | ||
| 189 | static struct regulator_ops ltc3589_table_regulator_ops = { | ||
| 190 | .enable = regulator_enable_regmap, | ||
| 191 | .disable = regulator_disable_regmap, | ||
| 192 | .is_enabled = regulator_is_enabled_regmap, | ||
| 193 | .list_voltage = regulator_list_voltage_table, | ||
| 194 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
| 195 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
| 196 | }; | ||
| 197 | |||
| 198 | |||
| 199 | #define LTC3589_REG(_name, _ops, en_bit, dtv1_reg, dtv_mask, go_bit) \ | ||
| 200 | [LTC3589_ ## _name] = { \ | ||
| 201 | .desc = { \ | ||
| 202 | .name = #_name, \ | ||
| 203 | .n_voltages = (dtv_mask) + 1, \ | ||
| 204 | .min_uV = (go_bit) ? 362500 : 0, \ | ||
| 205 | .uV_step = (go_bit) ? 12500 : 0, \ | ||
| 206 | .ramp_delay = (go_bit) ? 1750 : 0, \ | ||
| 207 | .fixed_uV = (dtv_mask) ? 0 : 800000, \ | ||
| 208 | .ops = <c3589_ ## _ops ## _regulator_ops, \ | ||
| 209 | .type = REGULATOR_VOLTAGE, \ | ||
| 210 | .id = LTC3589_ ## _name, \ | ||
| 211 | .owner = THIS_MODULE, \ | ||
| 212 | .vsel_reg = (dtv1_reg), \ | ||
| 213 | .vsel_mask = (dtv_mask), \ | ||
| 214 | .apply_reg = (go_bit) ? LTC3589_VCCR : 0, \ | ||
| 215 | .apply_bit = (go_bit), \ | ||
| 216 | .enable_reg = (en_bit) ? LTC3589_OVEN : 0, \ | ||
| 217 | .enable_mask = (en_bit), \ | ||
| 218 | }, \ | ||
| 219 | } | ||
| 220 | |||
| 221 | #define LTC3589_LINEAR_REG(_name, _dtv1) \ | ||
| 222 | LTC3589_REG(_name, linear, LTC3589_OVEN_ ## _name, \ | ||
| 223 | LTC3589_ ## _dtv1, 0x1f, \ | ||
| 224 | LTC3589_VCCR_ ## _name ## _GO) | ||
| 225 | |||
| 226 | #define LTC3589_FIXED_REG(_name) \ | ||
| 227 | LTC3589_REG(_name, fixed, LTC3589_OVEN_ ## _name, 0, 0, 0) | ||
| 228 | |||
| 229 | static struct ltc3589_regulator ltc3589_regulators[LTC3589_NUM_REGULATORS] = { | ||
| 230 | LTC3589_LINEAR_REG(SW1, B1DTV1), | ||
| 231 | LTC3589_LINEAR_REG(SW2, B2DTV1), | ||
| 232 | LTC3589_LINEAR_REG(SW3, B3DTV1), | ||
| 233 | LTC3589_FIXED_REG(BB_OUT), | ||
| 234 | LTC3589_REG(LDO1, fixed_standby, 0, 0, 0, 0), | ||
| 235 | LTC3589_LINEAR_REG(LDO2, L2DTV1), | ||
| 236 | LTC3589_FIXED_REG(LDO3), | ||
| 237 | LTC3589_REG(LDO4, table, LTC3589_OVEN_LDO4, LTC3589_L2DTV2, 0x60, 0), | ||
| 238 | }; | ||
| 239 | |||
| 240 | #ifdef CONFIG_OF | ||
| 241 | static struct of_regulator_match ltc3589_matches[LTC3589_NUM_REGULATORS] = { | ||
| 242 | { .name = "sw1", }, | ||
| 243 | { .name = "sw2", }, | ||
| 244 | { .name = "sw3", }, | ||
| 245 | { .name = "bb-out", }, | ||
| 246 | { .name = "ldo1", }, /* standby */ | ||
| 247 | { .name = "ldo2", }, | ||
| 248 | { .name = "ldo3", }, | ||
| 249 | { .name = "ldo4", }, | ||
| 250 | }; | ||
| 251 | |||
| 252 | static int ltc3589_parse_regulators_dt(struct ltc3589 *ltc3589) | ||
| 253 | { | ||
| 254 | struct device *dev = ltc3589->dev; | ||
| 255 | struct device_node *node; | ||
| 256 | int i, ret; | ||
| 257 | |||
| 258 | node = of_find_node_by_name(dev->of_node, "regulators"); | ||
| 259 | if (!node) { | ||
| 260 | dev_err(dev, "regulators node not found\n"); | ||
| 261 | return -EINVAL; | ||
| 262 | } | ||
| 263 | |||
| 264 | ret = of_regulator_match(dev, node, ltc3589_matches, | ||
| 265 | ARRAY_SIZE(ltc3589_matches)); | ||
| 266 | of_node_put(node); | ||
| 267 | if (ret < 0) { | ||
| 268 | dev_err(dev, "Error parsing regulator init data: %d\n", ret); | ||
| 269 | return ret; | ||
| 270 | } | ||
| 271 | if (ret != LTC3589_NUM_REGULATORS) { | ||
| 272 | dev_err(dev, "Only %d regulators described in device tree\n", | ||
| 273 | ret); | ||
| 274 | return -EINVAL; | ||
| 275 | } | ||
| 276 | |||
| 277 | /* Parse feedback voltage dividers. LDO3 and LDO4 don't have them */ | ||
| 278 | for (i = 0; i < LTC3589_LDO3; i++) { | ||
| 279 | struct ltc3589_regulator *desc = <c3589->regulator_descs[i]; | ||
| 280 | struct device_node *np = ltc3589_matches[i].of_node; | ||
| 281 | u32 vdiv[2]; | ||
| 282 | |||
| 283 | ret = of_property_read_u32_array(np, "lltc,fb-voltage-divider", | ||
| 284 | vdiv, 2); | ||
| 285 | if (ret) { | ||
| 286 | dev_err(dev, "Failed to parse voltage divider: %d\n", | ||
| 287 | ret); | ||
| 288 | return ret; | ||
| 289 | } | ||
| 290 | |||
| 291 | desc->r1 = vdiv[0]; | ||
| 292 | desc->r2 = vdiv[1]; | ||
| 293 | } | ||
| 294 | |||
| 295 | return 0; | ||
| 296 | } | ||
| 297 | |||
| 298 | static inline struct regulator_init_data *match_init_data(int index) | ||
| 299 | { | ||
| 300 | return ltc3589_matches[index].init_data; | ||
| 301 | } | ||
| 302 | |||
| 303 | static inline struct device_node *match_of_node(int index) | ||
| 304 | { | ||
| 305 | return ltc3589_matches[index].of_node; | ||
| 306 | } | ||
| 307 | #else | ||
| 308 | static inline int ltc3589_parse_regulators_dt(struct ltc3589 *ltc3589) | ||
| 309 | { | ||
| 310 | return 0; | ||
| 311 | } | ||
| 312 | |||
| 313 | static inline struct regulator_init_data *match_init_data(int index) | ||
| 314 | { | ||
| 315 | return NULL; | ||
| 316 | } | ||
| 317 | |||
| 318 | static inline struct device_node *match_of_node(int index) | ||
| 319 | { | ||
| 320 | return NULL; | ||
| 321 | } | ||
| 322 | #endif | ||
| 323 | |||
| 324 | static bool ltc3589_writeable_reg(struct device *dev, unsigned int reg) | ||
| 325 | { | ||
| 326 | switch (reg) { | ||
| 327 | case LTC3589_IRQSTAT: | ||
| 328 | case LTC3589_SCR1: | ||
| 329 | case LTC3589_OVEN: | ||
| 330 | case LTC3589_SCR2: | ||
| 331 | case LTC3589_VCCR: | ||
| 332 | case LTC3589_CLIRQ: | ||
| 333 | case LTC3589_B1DTV1: | ||
| 334 | case LTC3589_B1DTV2: | ||
| 335 | case LTC3589_VRRCR: | ||
| 336 | case LTC3589_B2DTV1: | ||
| 337 | case LTC3589_B2DTV2: | ||
| 338 | case LTC3589_B3DTV1: | ||
| 339 | case LTC3589_B3DTV2: | ||
| 340 | case LTC3589_L2DTV1: | ||
| 341 | case LTC3589_L2DTV2: | ||
| 342 | return true; | ||
| 343 | } | ||
| 344 | return false; | ||
| 345 | } | ||
| 346 | |||
| 347 | static bool ltc3589_readable_reg(struct device *dev, unsigned int reg) | ||
| 348 | { | ||
| 349 | switch (reg) { | ||
| 350 | case LTC3589_IRQSTAT: | ||
| 351 | case LTC3589_SCR1: | ||
| 352 | case LTC3589_OVEN: | ||
| 353 | case LTC3589_SCR2: | ||
| 354 | case LTC3589_PGSTAT: | ||
| 355 | case LTC3589_VCCR: | ||
| 356 | case LTC3589_B1DTV1: | ||
| 357 | case LTC3589_B1DTV2: | ||
| 358 | case LTC3589_VRRCR: | ||
| 359 | case LTC3589_B2DTV1: | ||
| 360 | case LTC3589_B2DTV2: | ||
| 361 | case LTC3589_B3DTV1: | ||
| 362 | case LTC3589_B3DTV2: | ||
| 363 | case LTC3589_L2DTV1: | ||
| 364 | case LTC3589_L2DTV2: | ||
| 365 | return true; | ||
| 366 | } | ||
| 367 | return false; | ||
| 368 | } | ||
| 369 | |||
| 370 | static bool ltc3589_volatile_reg(struct device *dev, unsigned int reg) | ||
| 371 | { | ||
| 372 | switch (reg) { | ||
| 373 | case LTC3589_IRQSTAT: | ||
| 374 | case LTC3589_PGSTAT: | ||
| 375 | return true; | ||
| 376 | } | ||
| 377 | return false; | ||
| 378 | } | ||
| 379 | |||
| 380 | struct reg_default ltc3589_reg_defaults[] = { | ||
| 381 | { LTC3589_SCR1, 0x00 }, | ||
| 382 | { LTC3589_OVEN, 0x00 }, | ||
| 383 | { LTC3589_SCR2, 0x00 }, | ||
| 384 | { LTC3589_VCCR, 0x00 }, | ||
| 385 | { LTC3589_B1DTV1, 0x19 }, | ||
| 386 | { LTC3589_B1DTV2, 0x19 }, | ||
| 387 | { LTC3589_VRRCR, 0xff }, | ||
| 388 | { LTC3589_B2DTV1, 0x19 }, | ||
| 389 | { LTC3589_B2DTV2, 0x19 }, | ||
| 390 | { LTC3589_B3DTV1, 0x19 }, | ||
| 391 | { LTC3589_B3DTV2, 0x19 }, | ||
| 392 | { LTC3589_L2DTV1, 0x19 }, | ||
| 393 | { LTC3589_L2DTV2, 0x19 }, | ||
| 394 | }; | ||
| 395 | |||
| 396 | static const struct regmap_config ltc3589_regmap_config = { | ||
| 397 | .reg_bits = 8, | ||
| 398 | .val_bits = 8, | ||
| 399 | .writeable_reg = ltc3589_writeable_reg, | ||
| 400 | .readable_reg = ltc3589_readable_reg, | ||
| 401 | .volatile_reg = ltc3589_volatile_reg, | ||
| 402 | .max_register = LTC3589_L2DTV2, | ||
| 403 | .reg_defaults = ltc3589_reg_defaults, | ||
| 404 | .num_reg_defaults = ARRAY_SIZE(ltc3589_reg_defaults), | ||
| 405 | .use_single_rw = true, | ||
| 406 | .cache_type = REGCACHE_RBTREE, | ||
| 407 | }; | ||
| 408 | |||
| 409 | |||
| 410 | static irqreturn_t ltc3589_isr(int irq, void *dev_id) | ||
| 411 | { | ||
| 412 | struct ltc3589 *ltc3589 = dev_id; | ||
| 413 | unsigned int i, irqstat, event; | ||
| 414 | |||
| 415 | regmap_read(ltc3589->regmap, LTC3589_IRQSTAT, &irqstat); | ||
| 416 | |||
| 417 | if (irqstat & LTC3589_IRQSTAT_THERMAL_WARN) { | ||
| 418 | event = REGULATOR_EVENT_OVER_TEMP; | ||
| 419 | for (i = 0; i < LTC3589_NUM_REGULATORS; i++) | ||
| 420 | regulator_notifier_call_chain(ltc3589->regulators[i], | ||
| 421 | event, NULL); | ||
| 422 | } | ||
| 423 | |||
| 424 | if (irqstat & LTC3589_IRQSTAT_UNDERVOLT_WARN) { | ||
| 425 | event = REGULATOR_EVENT_UNDER_VOLTAGE; | ||
| 426 | for (i = 0; i < LTC3589_NUM_REGULATORS; i++) | ||
| 427 | regulator_notifier_call_chain(ltc3589->regulators[i], | ||
| 428 | event, NULL); | ||
| 429 | } | ||
| 430 | |||
| 431 | /* Clear warning condition */ | ||
| 432 | regmap_write(ltc3589->regmap, LTC3589_CLIRQ, 0); | ||
| 433 | |||
| 434 | return IRQ_HANDLED; | ||
| 435 | } | ||
| 436 | |||
| 437 | static inline unsigned int ltc3589_scale(unsigned int uV, u32 r1, u32 r2) | ||
| 438 | { | ||
| 439 | uint64_t tmp; | ||
| 440 | if (uV == 0) | ||
| 441 | return 0; | ||
| 442 | tmp = (uint64_t)uV * r1; | ||
| 443 | do_div(tmp, r2); | ||
| 444 | return uV + (unsigned int)tmp; | ||
| 445 | } | ||
| 446 | |||
| 447 | static void ltc3589_apply_fb_voltage_divider(struct ltc3589_regulator *rdesc) | ||
| 448 | { | ||
| 449 | struct regulator_desc *desc = &rdesc->desc; | ||
| 450 | |||
| 451 | if (!rdesc->r1 || !rdesc->r2) | ||
| 452 | return; | ||
| 453 | |||
| 454 | desc->min_uV = ltc3589_scale(desc->min_uV, rdesc->r1, rdesc->r2); | ||
| 455 | desc->uV_step = ltc3589_scale(desc->uV_step, rdesc->r1, rdesc->r2); | ||
| 456 | desc->fixed_uV = ltc3589_scale(desc->fixed_uV, rdesc->r1, rdesc->r2); | ||
| 457 | } | ||
| 458 | |||
| 459 | static int ltc3589_probe(struct i2c_client *client, | ||
| 460 | const struct i2c_device_id *id) | ||
| 461 | { | ||
| 462 | struct device *dev = &client->dev; | ||
| 463 | struct ltc3589_regulator *descs; | ||
| 464 | struct ltc3589 *ltc3589; | ||
| 465 | int i, ret; | ||
| 466 | |||
| 467 | ltc3589 = devm_kzalloc(dev, sizeof(*ltc3589), GFP_KERNEL); | ||
| 468 | if (!ltc3589) | ||
| 469 | return -ENOMEM; | ||
| 470 | |||
| 471 | i2c_set_clientdata(client, ltc3589); | ||
| 472 | ltc3589->variant = id->driver_data; | ||
| 473 | ltc3589->dev = dev; | ||
| 474 | |||
| 475 | descs = ltc3589->regulator_descs; | ||
| 476 | memcpy(descs, ltc3589_regulators, sizeof(ltc3589_regulators)); | ||
| 477 | if (ltc3589->variant == LTC3589) { | ||
| 478 | descs[LTC3589_LDO3].desc.fixed_uV = 1800000; | ||
| 479 | descs[LTC3589_LDO4].desc.volt_table = ltc3589_ldo4; | ||
| 480 | } else { | ||
| 481 | descs[LTC3589_LDO3].desc.fixed_uV = 2800000; | ||
| 482 | descs[LTC3589_LDO4].desc.volt_table = ltc3589_12_ldo4; | ||
| 483 | } | ||
| 484 | |||
| 485 | ltc3589->regmap = devm_regmap_init_i2c(client, <c3589_regmap_config); | ||
| 486 | if (IS_ERR(ltc3589->regmap)) { | ||
| 487 | ret = PTR_ERR(ltc3589->regmap); | ||
| 488 | dev_err(dev, "failed to initialize regmap: %d\n", ret); | ||
| 489 | return ret; | ||
| 490 | } | ||
| 491 | |||
| 492 | ret = ltc3589_parse_regulators_dt(ltc3589); | ||
| 493 | if (ret) | ||
| 494 | return ret; | ||
| 495 | |||
| 496 | for (i = 0; i < LTC3589_NUM_REGULATORS; i++) { | ||
| 497 | struct ltc3589_regulator *rdesc = <c3589->regulator_descs[i]; | ||
| 498 | struct regulator_desc *desc = &rdesc->desc; | ||
| 499 | struct regulator_init_data *init_data; | ||
| 500 | struct regulator_config config = { }; | ||
| 501 | |||
| 502 | init_data = match_init_data(i); | ||
| 503 | |||
| 504 | if (i < LTC3589_LDO3) | ||
| 505 | ltc3589_apply_fb_voltage_divider(rdesc); | ||
| 506 | |||
| 507 | config.dev = dev; | ||
| 508 | config.init_data = init_data; | ||
| 509 | config.driver_data = ltc3589; | ||
| 510 | config.of_node = match_of_node(i); | ||
| 511 | |||
| 512 | ltc3589->regulators[i] = devm_regulator_register(dev, desc, | ||
| 513 | &config); | ||
| 514 | if (IS_ERR(ltc3589->regulators[i])) { | ||
| 515 | ret = PTR_ERR(ltc3589->regulators[i]); | ||
| 516 | dev_err(dev, "failed to register regulator %s: %d\n", | ||
| 517 | desc->name, ret); | ||
| 518 | return ret; | ||
| 519 | } | ||
| 520 | } | ||
| 521 | |||
| 522 | ret = devm_request_threaded_irq(dev, client->irq, NULL, ltc3589_isr, | ||
| 523 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
| 524 | client->name, ltc3589); | ||
| 525 | if (ret) { | ||
| 526 | dev_err(dev, "Failed to request IRQ: %d\n", ret); | ||
| 527 | return ret; | ||
| 528 | } | ||
| 529 | |||
| 530 | return 0; | ||
| 531 | } | ||
| 532 | |||
| 533 | static struct i2c_device_id ltc3589_i2c_id[] = { | ||
| 534 | { "ltc3589", LTC3589 }, | ||
| 535 | { "ltc3589-1", LTC3589_1 }, | ||
| 536 | { "ltc3589-2", LTC3589_2 }, | ||
| 537 | { } | ||
| 538 | }; | ||
| 539 | MODULE_DEVICE_TABLE(i2c, ltc3589_i2c_id); | ||
| 540 | |||
| 541 | static struct i2c_driver ltc3589_driver = { | ||
| 542 | .driver = { | ||
| 543 | .name = DRIVER_NAME, | ||
| 544 | .owner = THIS_MODULE, | ||
| 545 | }, | ||
| 546 | .probe = ltc3589_probe, | ||
| 547 | .id_table = ltc3589_i2c_id, | ||
| 548 | }; | ||
| 549 | module_i2c_driver(ltc3589_driver); | ||
| 550 | |||
| 551 | MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>"); | ||
| 552 | MODULE_DESCRIPTION("Regulator driver for Linear Technology LTC3589(-1,2)"); | ||
| 553 | MODULE_LICENSE("GPL v2"); | ||
| 554 | MODULE_ALIAS("i2c:ltc3589"); | ||
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 3172da847d24..c8bddcc8f911 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c | |||
| @@ -161,10 +161,8 @@ static int max8649_regulator_probe(struct i2c_client *client, | |||
| 161 | 161 | ||
| 162 | info = devm_kzalloc(&client->dev, sizeof(struct max8649_regulator_info), | 162 | info = devm_kzalloc(&client->dev, sizeof(struct max8649_regulator_info), |
| 163 | GFP_KERNEL); | 163 | GFP_KERNEL); |
| 164 | if (!info) { | 164 | if (!info) |
| 165 | dev_err(&client->dev, "No enough memory\n"); | ||
| 166 | return -ENOMEM; | 165 | return -ENOMEM; |
| 167 | } | ||
| 168 | 166 | ||
| 169 | info->regmap = devm_regmap_init_i2c(client, &max8649_regmap_config); | 167 | info->regmap = devm_regmap_init_i2c(client, &max8649_regmap_config); |
| 170 | if (IS_ERR(info->regmap)) { | 168 | if (IS_ERR(info->regmap)) { |
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index d920f5a32ec8..c2792f0271ab 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c | |||
| @@ -129,7 +129,7 @@ static const struct regulator_desc regulator = { | |||
| 129 | }; | 129 | }; |
| 130 | 130 | ||
| 131 | #ifdef CONFIG_OF | 131 | #ifdef CONFIG_OF |
| 132 | static struct of_device_id max8952_dt_match[] = { | 132 | static const struct of_device_id max8952_dt_match[] = { |
| 133 | { .compatible = "maxim,max8952" }, | 133 | { .compatible = "maxim,max8952" }, |
| 134 | {}, | 134 | {}, |
| 135 | }; | 135 | }; |
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index ea4f36f2cbe2..ee5e67bc8d5b 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c | |||
| @@ -19,9 +19,7 @@ | |||
| 19 | static void of_get_regulation_constraints(struct device_node *np, | 19 | static void of_get_regulation_constraints(struct device_node *np, |
| 20 | struct regulator_init_data **init_data) | 20 | struct regulator_init_data **init_data) |
| 21 | { | 21 | { |
| 22 | const __be32 *min_uV, *max_uV, *uV_offset; | 22 | const __be32 *min_uV, *max_uV; |
| 23 | const __be32 *min_uA, *max_uA, *ramp_delay; | ||
| 24 | struct property *prop; | ||
| 25 | struct regulation_constraints *constraints = &(*init_data)->constraints; | 23 | struct regulation_constraints *constraints = &(*init_data)->constraints; |
| 26 | int ret; | 24 | int ret; |
| 27 | u32 pval; | 25 | u32 pval; |
| @@ -42,36 +40,29 @@ static void of_get_regulation_constraints(struct device_node *np, | |||
| 42 | if (min_uV && max_uV && constraints->min_uV == constraints->max_uV) | 40 | if (min_uV && max_uV && constraints->min_uV == constraints->max_uV) |
| 43 | constraints->apply_uV = true; | 41 | constraints->apply_uV = true; |
| 44 | 42 | ||
| 45 | uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL); | 43 | if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval)) |
| 46 | if (uV_offset) | 44 | constraints->uV_offset = pval; |
| 47 | constraints->uV_offset = be32_to_cpu(*uV_offset); | 45 | if (!of_property_read_u32(np, "regulator-min-microamp", &pval)) |
| 48 | min_uA = of_get_property(np, "regulator-min-microamp", NULL); | 46 | constraints->min_uA = pval; |
| 49 | if (min_uA) | 47 | if (!of_property_read_u32(np, "regulator-max-microamp", &pval)) |
| 50 | constraints->min_uA = be32_to_cpu(*min_uA); | 48 | constraints->max_uA = pval; |
| 51 | max_uA = of_get_property(np, "regulator-max-microamp", NULL); | ||
| 52 | if (max_uA) | ||
| 53 | constraints->max_uA = be32_to_cpu(*max_uA); | ||
| 54 | 49 | ||
| 55 | /* Current change possible? */ | 50 | /* Current change possible? */ |
| 56 | if (constraints->min_uA != constraints->max_uA) | 51 | if (constraints->min_uA != constraints->max_uA) |
| 57 | constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; | 52 | constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; |
| 58 | 53 | ||
| 59 | if (of_find_property(np, "regulator-boot-on", NULL)) | 54 | constraints->boot_on = of_property_read_bool(np, "regulator-boot-on"); |
| 60 | constraints->boot_on = true; | 55 | constraints->always_on = of_property_read_bool(np, "regulator-always-on"); |
| 61 | 56 | if (!constraints->always_on) /* status change should be possible. */ | |
| 62 | if (of_find_property(np, "regulator-always-on", NULL)) | ||
| 63 | constraints->always_on = true; | ||
| 64 | else /* status change should be possible if not always on. */ | ||
| 65 | constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; | 57 | constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; |
| 66 | 58 | ||
| 67 | if (of_property_read_bool(np, "regulator-allow-bypass")) | 59 | if (of_property_read_bool(np, "regulator-allow-bypass")) |
| 68 | constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS; | 60 | constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS; |
| 69 | 61 | ||
| 70 | prop = of_find_property(np, "regulator-ramp-delay", NULL); | 62 | ret = of_property_read_u32(np, "regulator-ramp-delay", &pval); |
| 71 | if (prop && prop->value) { | 63 | if (!ret) { |
| 72 | ramp_delay = prop->value; | 64 | if (pval) |
| 73 | if (*ramp_delay) | 65 | constraints->ramp_delay = pval; |
| 74 | constraints->ramp_delay = be32_to_cpu(*ramp_delay); | ||
| 75 | else | 66 | else |
| 76 | constraints->ramp_disable = true; | 67 | constraints->ramp_disable = true; |
| 77 | } | 68 | } |
| @@ -106,6 +97,20 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev, | |||
| 106 | } | 97 | } |
| 107 | EXPORT_SYMBOL_GPL(of_get_regulator_init_data); | 98 | EXPORT_SYMBOL_GPL(of_get_regulator_init_data); |
| 108 | 99 | ||
| 100 | struct devm_of_regulator_matches { | ||
| 101 | struct of_regulator_match *matches; | ||
| 102 | unsigned int num_matches; | ||
| 103 | }; | ||
| 104 | |||
| 105 | static void devm_of_regulator_put_matches(struct device *dev, void *res) | ||
| 106 | { | ||
| 107 | struct devm_of_regulator_matches *devm_matches = res; | ||
| 108 | int i; | ||
| 109 | |||
| 110 | for (i = 0; i < devm_matches->num_matches; i++) | ||
| 111 | of_node_put(devm_matches->matches[i].of_node); | ||
| 112 | } | ||
| 113 | |||
| 109 | /** | 114 | /** |
| 110 | * of_regulator_match - extract multiple regulator init data from device tree. | 115 | * of_regulator_match - extract multiple regulator init data from device tree. |
| 111 | * @dev: device requesting the data | 116 | * @dev: device requesting the data |
| @@ -119,7 +124,8 @@ EXPORT_SYMBOL_GPL(of_get_regulator_init_data); | |||
| 119 | * regulator. The data parsed from a child node will be matched to a regulator | 124 | * regulator. The data parsed from a child node will be matched to a regulator |
| 120 | * based on either the deprecated property regulator-compatible if present, | 125 | * based on either the deprecated property regulator-compatible if present, |
| 121 | * or otherwise the child node's name. Note that the match table is modified | 126 | * or otherwise the child node's name. Note that the match table is modified |
| 122 | * in place. | 127 | * in place and an additional of_node reference is taken for each matched |
| 128 | * regulator. | ||
| 123 | * | 129 | * |
| 124 | * Returns the number of matches found or a negative error code on failure. | 130 | * Returns the number of matches found or a negative error code on failure. |
| 125 | */ | 131 | */ |
| @@ -131,10 +137,22 @@ int of_regulator_match(struct device *dev, struct device_node *node, | |||
| 131 | unsigned int i; | 137 | unsigned int i; |
| 132 | const char *name; | 138 | const char *name; |
| 133 | struct device_node *child; | 139 | struct device_node *child; |
| 140 | struct devm_of_regulator_matches *devm_matches; | ||
| 134 | 141 | ||
| 135 | if (!dev || !node) | 142 | if (!dev || !node) |
| 136 | return -EINVAL; | 143 | return -EINVAL; |
| 137 | 144 | ||
| 145 | devm_matches = devres_alloc(devm_of_regulator_put_matches, | ||
| 146 | sizeof(struct devm_of_regulator_matches), | ||
| 147 | GFP_KERNEL); | ||
| 148 | if (!devm_matches) | ||
| 149 | return -ENOMEM; | ||
| 150 | |||
| 151 | devm_matches->matches = matches; | ||
| 152 | devm_matches->num_matches = num_matches; | ||
| 153 | |||
| 154 | devres_add(dev, devm_matches); | ||
| 155 | |||
| 138 | for (i = 0; i < num_matches; i++) { | 156 | for (i = 0; i < num_matches; i++) { |
| 139 | struct of_regulator_match *match = &matches[i]; | 157 | struct of_regulator_match *match = &matches[i]; |
| 140 | match->init_data = NULL; | 158 | match->init_data = NULL; |
| @@ -162,7 +180,7 @@ int of_regulator_match(struct device *dev, struct device_node *node, | |||
| 162 | child->name); | 180 | child->name); |
| 163 | return -EINVAL; | 181 | return -EINVAL; |
| 164 | } | 182 | } |
| 165 | match->of_node = child; | 183 | match->of_node = of_node_get(child); |
| 166 | count++; | 184 | count++; |
| 167 | break; | 185 | break; |
| 168 | } | 186 | } |
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 9c62b1d34685..864ed02ce4b7 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c | |||
| @@ -36,6 +36,18 @@ struct regs_info { | |||
| 36 | int sleep_id; | 36 | int sleep_id; |
| 37 | }; | 37 | }; |
| 38 | 38 | ||
| 39 | static const struct regulator_linear_range smps_low_ranges[] = { | ||
| 40 | REGULATOR_LINEAR_RANGE(500000, 0x1, 0x6, 0), | ||
| 41 | REGULATOR_LINEAR_RANGE(510000, 0x7, 0x79, 10000), | ||
| 42 | REGULATOR_LINEAR_RANGE(1650000, 0x7A, 0x7f, 0), | ||
| 43 | }; | ||
| 44 | |||
| 45 | static const struct regulator_linear_range smps_high_ranges[] = { | ||
| 46 | REGULATOR_LINEAR_RANGE(1000000, 0x1, 0x6, 0), | ||
| 47 | REGULATOR_LINEAR_RANGE(1020000, 0x7, 0x79, 20000), | ||
| 48 | REGULATOR_LINEAR_RANGE(3300000, 0x7A, 0x7f, 0), | ||
| 49 | }; | ||
| 50 | |||
| 39 | static const struct regs_info palmas_regs_info[] = { | 51 | static const struct regs_info palmas_regs_info[] = { |
| 40 | { | 52 | { |
| 41 | .name = "SMPS12", | 53 | .name = "SMPS12", |
| @@ -280,54 +292,6 @@ static int palmas_ldo_write(struct palmas *palmas, unsigned int reg, | |||
| 280 | return regmap_write(palmas->regmap[REGULATOR_SLAVE], addr, value); | 292 | return regmap_write(palmas->regmap[REGULATOR_SLAVE], addr, value); |
| 281 | } | 293 | } |
| 282 | 294 | ||
| 283 | static int palmas_is_enabled_smps(struct regulator_dev *dev) | ||
| 284 | { | ||
| 285 | struct palmas_pmic *pmic = rdev_get_drvdata(dev); | ||
| 286 | int id = rdev_get_id(dev); | ||
| 287 | unsigned int reg; | ||
| 288 | |||
| 289 | palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, ®); | ||
| 290 | |||
| 291 | reg &= PALMAS_SMPS12_CTRL_STATUS_MASK; | ||
| 292 | reg >>= PALMAS_SMPS12_CTRL_STATUS_SHIFT; | ||
| 293 | |||
| 294 | return !!(reg); | ||
| 295 | } | ||
| 296 | |||
| 297 | static int palmas_enable_smps(struct regulator_dev *dev) | ||
| 298 | { | ||
| 299 | struct palmas_pmic *pmic = rdev_get_drvdata(dev); | ||
| 300 | int id = rdev_get_id(dev); | ||
| 301 | unsigned int reg; | ||
| 302 | |||
| 303 | palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, ®); | ||
| 304 | |||
| 305 | reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK; | ||
| 306 | if (pmic->current_reg_mode[id]) | ||
| 307 | reg |= pmic->current_reg_mode[id]; | ||
| 308 | else | ||
| 309 | reg |= SMPS_CTRL_MODE_ON; | ||
| 310 | |||
| 311 | palmas_smps_write(pmic->palmas, palmas_regs_info[id].ctrl_addr, reg); | ||
| 312 | |||
| 313 | return 0; | ||
| 314 | } | ||
| 315 | |||
| 316 | static int palmas_disable_smps(struct regulator_dev *dev) | ||
| 317 | { | ||
| 318 | struct palmas_pmic *pmic = rdev_get_drvdata(dev); | ||
| 319 | int id = rdev_get_id(dev); | ||
| 320 | unsigned int reg; | ||
| 321 | |||
| 322 | palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, ®); | ||
| 323 | |||
| 324 | reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK; | ||
| 325 | |||
| 326 | palmas_smps_write(pmic->palmas, palmas_regs_info[id].ctrl_addr, reg); | ||
| 327 | |||
| 328 | return 0; | ||
| 329 | } | ||
| 330 | |||
| 331 | static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode) | 295 | static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode) |
| 332 | { | 296 | { |
| 333 | struct palmas_pmic *pmic = rdev_get_drvdata(dev); | 297 | struct palmas_pmic *pmic = rdev_get_drvdata(dev); |
| @@ -382,81 +346,6 @@ static unsigned int palmas_get_mode_smps(struct regulator_dev *dev) | |||
| 382 | return 0; | 346 | return 0; |
| 383 | } | 347 | } |
| 384 | 348 | ||
| 385 | static int palmas_list_voltage_smps(struct regulator_dev *dev, | ||
| 386 | unsigned selector) | ||
| 387 | { | ||
| 388 | struct palmas_pmic *pmic = rdev_get_drvdata(dev); | ||
| 389 | int id = rdev_get_id(dev); | ||
| 390 | int mult = 1; | ||
| 391 | |||
| 392 | /* Read the multiplier set in VSEL register to return | ||
| 393 | * the correct voltage. | ||
| 394 | */ | ||
| 395 | if (pmic->range[id]) | ||
| 396 | mult = 2; | ||
| 397 | |||
| 398 | if (selector == 0) | ||
| 399 | return 0; | ||
| 400 | else if (selector < 6) | ||
| 401 | return 500000 * mult; | ||
| 402 | else | ||
| 403 | /* Voltage is linear mapping starting from selector 6, | ||
| 404 | * volt = (0.49V + ((selector - 5) * 0.01V)) * RANGE | ||
| 405 | * RANGE is either x1 or x2 | ||
| 406 | */ | ||
| 407 | return (490000 + ((selector - 5) * 10000)) * mult; | ||
| 408 | } | ||
| 409 | |||
| 410 | static int palmas_map_voltage_smps(struct regulator_dev *rdev, | ||
| 411 | int min_uV, int max_uV) | ||
| 412 | { | ||
| 413 | struct palmas_pmic *pmic = rdev_get_drvdata(rdev); | ||
| 414 | int id = rdev_get_id(rdev); | ||
| 415 | int ret, voltage; | ||
| 416 | |||
| 417 | if (min_uV == 0) | ||
| 418 | return 0; | ||
| 419 | |||
| 420 | if (pmic->range[id]) { /* RANGE is x2 */ | ||
| 421 | if (min_uV < 1000000) | ||
| 422 | min_uV = 1000000; | ||
| 423 | ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 6; | ||
| 424 | } else { /* RANGE is x1 */ | ||
| 425 | if (min_uV < 500000) | ||
| 426 | min_uV = 500000; | ||
| 427 | ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 6; | ||
| 428 | } | ||
| 429 | |||
| 430 | /* Map back into a voltage to verify we're still in bounds */ | ||
| 431 | voltage = palmas_list_voltage_smps(rdev, ret); | ||
| 432 | if (voltage < min_uV || voltage > max_uV) | ||
| 433 | return -EINVAL; | ||
| 434 | |||
| 435 | return ret; | ||
| 436 | } | ||
| 437 | |||
| 438 | static int palma_smps_set_voltage_smps_time_sel(struct regulator_dev *rdev, | ||
| 439 | unsigned int old_selector, unsigned int new_selector) | ||
| 440 | { | ||
| 441 | struct palmas_pmic *pmic = rdev_get_drvdata(rdev); | ||
| 442 | int id = rdev_get_id(rdev); | ||
| 443 | int old_uv, new_uv; | ||
| 444 | unsigned int ramp_delay = pmic->ramp_delay[id]; | ||
| 445 | |||
| 446 | if (!ramp_delay) | ||
| 447 | return 0; | ||
| 448 | |||
| 449 | old_uv = palmas_list_voltage_smps(rdev, old_selector); | ||
| 450 | if (old_uv < 0) | ||
| 451 | return old_uv; | ||
| 452 | |||
| 453 | new_uv = palmas_list_voltage_smps(rdev, new_selector); | ||
| 454 | if (new_uv < 0) | ||
| 455 | return new_uv; | ||
| 456 | |||
| 457 | return DIV_ROUND_UP(abs(old_uv - new_uv), ramp_delay); | ||
| 458 | } | ||
| 459 | |||
| 460 | static int palmas_smps_set_ramp_delay(struct regulator_dev *rdev, | 349 | static int palmas_smps_set_ramp_delay(struct regulator_dev *rdev, |
| 461 | int ramp_delay) | 350 | int ramp_delay) |
| 462 | { | 351 | { |
| @@ -493,16 +382,16 @@ static int palmas_smps_set_ramp_delay(struct regulator_dev *rdev, | |||
| 493 | } | 382 | } |
| 494 | 383 | ||
| 495 | static struct regulator_ops palmas_ops_smps = { | 384 | static struct regulator_ops palmas_ops_smps = { |
| 496 | .is_enabled = palmas_is_enabled_smps, | 385 | .is_enabled = regulator_is_enabled_regmap, |
| 497 | .enable = palmas_enable_smps, | 386 | .enable = regulator_enable_regmap, |
| 498 | .disable = palmas_disable_smps, | 387 | .disable = regulator_disable_regmap, |
| 499 | .set_mode = palmas_set_mode_smps, | 388 | .set_mode = palmas_set_mode_smps, |
| 500 | .get_mode = palmas_get_mode_smps, | 389 | .get_mode = palmas_get_mode_smps, |
| 501 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 390 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
| 502 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 391 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
| 503 | .list_voltage = palmas_list_voltage_smps, | 392 | .list_voltage = regulator_list_voltage_linear_range, |
| 504 | .map_voltage = palmas_map_voltage_smps, | 393 | .map_voltage = regulator_map_voltage_linear_range, |
| 505 | .set_voltage_time_sel = palma_smps_set_voltage_smps_time_sel, | 394 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
| 506 | .set_ramp_delay = palmas_smps_set_ramp_delay, | 395 | .set_ramp_delay = palmas_smps_set_ramp_delay, |
| 507 | }; | 396 | }; |
| 508 | 397 | ||
| @@ -511,9 +400,9 @@ static struct regulator_ops palmas_ops_ext_control_smps = { | |||
| 511 | .get_mode = palmas_get_mode_smps, | 400 | .get_mode = palmas_get_mode_smps, |
| 512 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 401 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
| 513 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 402 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
| 514 | .list_voltage = palmas_list_voltage_smps, | 403 | .list_voltage = regulator_list_voltage_linear_range, |
| 515 | .map_voltage = palmas_map_voltage_smps, | 404 | .map_voltage = regulator_map_voltage_linear_range, |
| 516 | .set_voltage_time_sel = palma_smps_set_voltage_smps_time_sel, | 405 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
| 517 | .set_ramp_delay = palmas_smps_set_ramp_delay, | 406 | .set_ramp_delay = palmas_smps_set_ramp_delay, |
| 518 | }; | 407 | }; |
| 519 | 408 | ||
| @@ -1042,12 +931,17 @@ static int palmas_regulators_probe(struct platform_device *pdev) | |||
| 1042 | * ranges. Read the current smps mode for later use. | 931 | * ranges. Read the current smps mode for later use. |
| 1043 | */ | 932 | */ |
| 1044 | addr = palmas_regs_info[id].vsel_addr; | 933 | addr = palmas_regs_info[id].vsel_addr; |
| 934 | pmic->desc[id].n_linear_ranges = 3; | ||
| 1045 | 935 | ||
| 1046 | ret = palmas_smps_read(pmic->palmas, addr, ®); | 936 | ret = palmas_smps_read(pmic->palmas, addr, ®); |
| 1047 | if (ret) | 937 | if (ret) |
| 1048 | return ret; | 938 | return ret; |
| 1049 | if (reg & PALMAS_SMPS12_VOLTAGE_RANGE) | 939 | if (reg & PALMAS_SMPS12_VOLTAGE_RANGE) |
| 1050 | pmic->range[id] = 1; | 940 | pmic->range[id] = 1; |
| 941 | if (pmic->range[id]) | ||
| 942 | pmic->desc[id].linear_ranges = smps_high_ranges; | ||
| 943 | else | ||
| 944 | pmic->desc[id].linear_ranges = smps_low_ranges; | ||
| 1051 | 945 | ||
| 1052 | if (reg_init && reg_init->roof_floor) | 946 | if (reg_init && reg_init->roof_floor) |
| 1053 | pmic->desc[id].ops = | 947 | pmic->desc[id].ops = |
| @@ -1199,7 +1093,7 @@ static int palmas_regulators_probe(struct platform_device *pdev) | |||
| 1199 | return 0; | 1093 | return 0; |
| 1200 | } | 1094 | } |
| 1201 | 1095 | ||
| 1202 | static struct of_device_id of_palmas_match_tbl[] = { | 1096 | static const struct of_device_id of_palmas_match_tbl[] = { |
| 1203 | { .compatible = "ti,palmas-pmic", }, | 1097 | { .compatible = "ti,palmas-pmic", }, |
| 1204 | { .compatible = "ti,twl6035-pmic", }, | 1098 | { .compatible = "ti,twl6035-pmic", }, |
| 1205 | { .compatible = "ti,twl6036-pmic", }, | 1099 | { .compatible = "ti,twl6036-pmic", }, |
diff --git a/drivers/regulator/pbias-regulator.c b/drivers/regulator/pbias-regulator.c index 6d38be3d970c..6d02d68dfb46 100644 --- a/drivers/regulator/pbias-regulator.c +++ b/drivers/regulator/pbias-regulator.c | |||
| @@ -49,33 +49,13 @@ static const unsigned int pbias_volt_table[] = { | |||
| 49 | 3000000 | 49 | 3000000 |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | static int pbias_regulator_enable(struct regulator_dev *rdev) | ||
| 53 | { | ||
| 54 | struct pbias_regulator_data *data = rdev_get_drvdata(rdev); | ||
| 55 | const struct pbias_reg_info *info = data->info; | ||
| 56 | |||
| 57 | return regmap_update_bits(data->syscon, rdev->desc->enable_reg, | ||
| 58 | info->enable_mask, info->enable); | ||
| 59 | } | ||
| 60 | |||
| 61 | static int pbias_regulator_is_enable(struct regulator_dev *rdev) | ||
| 62 | { | ||
| 63 | struct pbias_regulator_data *data = rdev_get_drvdata(rdev); | ||
| 64 | const struct pbias_reg_info *info = data->info; | ||
| 65 | int value; | ||
| 66 | |||
| 67 | regmap_read(data->syscon, rdev->desc->enable_reg, &value); | ||
| 68 | |||
| 69 | return (value & info->enable_mask) == info->enable; | ||
| 70 | } | ||
| 71 | |||
| 72 | static struct regulator_ops pbias_regulator_voltage_ops = { | 52 | static struct regulator_ops pbias_regulator_voltage_ops = { |
| 73 | .list_voltage = regulator_list_voltage_table, | 53 | .list_voltage = regulator_list_voltage_table, |
| 74 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 54 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
| 75 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 55 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
| 76 | .enable = pbias_regulator_enable, | 56 | .enable = regulator_enable_regmap, |
| 77 | .disable = regulator_disable_regmap, | 57 | .disable = regulator_disable_regmap, |
| 78 | .is_enabled = pbias_regulator_is_enable, | 58 | .is_enabled = regulator_is_enabled_regmap, |
| 79 | }; | 59 | }; |
| 80 | 60 | ||
| 81 | static const struct pbias_reg_info pbias_mmc_omap2430 = { | 61 | static const struct pbias_reg_info pbias_mmc_omap2430 = { |
| @@ -142,10 +122,8 @@ static int pbias_regulator_probe(struct platform_device *pdev) | |||
| 142 | 122 | ||
| 143 | drvdata = devm_kzalloc(&pdev->dev, sizeof(struct pbias_regulator_data) | 123 | drvdata = devm_kzalloc(&pdev->dev, sizeof(struct pbias_regulator_data) |
| 144 | * count, GFP_KERNEL); | 124 | * count, GFP_KERNEL); |
| 145 | if (drvdata == NULL) { | 125 | if (!drvdata) |
| 146 | dev_err(&pdev->dev, "Failed to allocate device data\n"); | ||
| 147 | return -ENOMEM; | 126 | return -ENOMEM; |
| 148 | } | ||
| 149 | 127 | ||
| 150 | syscon = syscon_regmap_lookup_by_phandle(np, "syscon"); | 128 | syscon = syscon_regmap_lookup_by_phandle(np, "syscon"); |
| 151 | if (IS_ERR(syscon)) | 129 | if (IS_ERR(syscon)) |
| @@ -180,6 +158,7 @@ static int pbias_regulator_probe(struct platform_device *pdev) | |||
| 180 | drvdata[data_idx].desc.vsel_mask = info->vmode; | 158 | drvdata[data_idx].desc.vsel_mask = info->vmode; |
| 181 | drvdata[data_idx].desc.enable_reg = res->start; | 159 | drvdata[data_idx].desc.enable_reg = res->start; |
| 182 | drvdata[data_idx].desc.enable_mask = info->enable_mask; | 160 | drvdata[data_idx].desc.enable_mask = info->enable_mask; |
| 161 | drvdata[data_idx].desc.enable_val = info->enable; | ||
| 183 | 162 | ||
| 184 | cfg.init_data = pbias_matches[idx].init_data; | 163 | cfg.init_data = pbias_matches[idx].init_data; |
| 185 | cfg.driver_data = &drvdata[data_idx]; | 164 | cfg.driver_data = &drvdata[data_idx]; |
diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 67e678c4301c..c879dff597ee 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c | |||
| @@ -125,6 +125,9 @@ static struct regulator_ops pfuze100_ldo_regulator_ops = { | |||
| 125 | }; | 125 | }; |
| 126 | 126 | ||
| 127 | static struct regulator_ops pfuze100_fixed_regulator_ops = { | 127 | static struct regulator_ops pfuze100_fixed_regulator_ops = { |
| 128 | .enable = regulator_enable_regmap, | ||
| 129 | .disable = regulator_disable_regmap, | ||
| 130 | .is_enabled = regulator_is_enabled_regmap, | ||
| 128 | .list_voltage = regulator_list_voltage_linear, | 131 | .list_voltage = regulator_list_voltage_linear, |
| 129 | }; | 132 | }; |
| 130 | 133 | ||
| @@ -137,6 +140,8 @@ static struct regulator_ops pfuze100_sw_regulator_ops = { | |||
| 137 | }; | 140 | }; |
| 138 | 141 | ||
| 139 | static struct regulator_ops pfuze100_swb_regulator_ops = { | 142 | static struct regulator_ops pfuze100_swb_regulator_ops = { |
| 143 | .enable = regulator_enable_regmap, | ||
| 144 | .disable = regulator_disable_regmap, | ||
| 140 | .list_voltage = regulator_list_voltage_table, | 145 | .list_voltage = regulator_list_voltage_table, |
| 141 | .map_voltage = regulator_map_voltage_ascend, | 146 | .map_voltage = regulator_map_voltage_ascend, |
| 142 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 147 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
| @@ -189,6 +194,8 @@ static struct regulator_ops pfuze100_swb_regulator_ops = { | |||
| 189 | .volt_table = voltages, \ | 194 | .volt_table = voltages, \ |
| 190 | .vsel_reg = (base), \ | 195 | .vsel_reg = (base), \ |
| 191 | .vsel_mask = (mask), \ | 196 | .vsel_mask = (mask), \ |
| 197 | .enable_reg = (base), \ | ||
| 198 | .enable_mask = 0x48, \ | ||
| 192 | }, \ | 199 | }, \ |
| 193 | } | 200 | } |
| 194 | 201 | ||
| @@ -502,6 +509,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client, | |||
| 502 | config.init_data = init_data; | 509 | config.init_data = init_data; |
| 503 | config.driver_data = pfuze_chip; | 510 | config.driver_data = pfuze_chip; |
| 504 | config.of_node = match_of_node(i); | 511 | config.of_node = match_of_node(i); |
| 512 | config.ena_gpio = -EINVAL; | ||
| 505 | 513 | ||
| 506 | pfuze_chip->regulators[i] = | 514 | pfuze_chip->regulators[i] = |
| 507 | devm_regulator_register(&client->dev, desc, &config); | 515 | devm_regulator_register(&client->dev, desc, &config); |
diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c index f19a30f0fb42..ee83b4876420 100644 --- a/drivers/regulator/s2mpa01.c +++ b/drivers/regulator/s2mpa01.c | |||
| @@ -61,7 +61,7 @@ static int s2mpa01_regulator_set_voltage_time_sel(struct regulator_dev *rdev, | |||
| 61 | unsigned int ramp_delay = 0; | 61 | unsigned int ramp_delay = 0; |
| 62 | int old_volt, new_volt; | 62 | int old_volt, new_volt; |
| 63 | 63 | ||
| 64 | switch (rdev->desc->id) { | 64 | switch (rdev_get_id(rdev)) { |
| 65 | case S2MPA01_BUCK2: | 65 | case S2MPA01_BUCK2: |
| 66 | case S2MPA01_BUCK4: | 66 | case S2MPA01_BUCK4: |
| 67 | ramp_delay = s2mpa01->ramp_delay24; | 67 | ramp_delay = s2mpa01->ramp_delay24; |
| @@ -102,7 +102,7 @@ static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) | |||
| 102 | unsigned int ramp_enable = 1, enable_shift = 0; | 102 | unsigned int ramp_enable = 1, enable_shift = 0; |
| 103 | int ret; | 103 | int ret; |
| 104 | 104 | ||
| 105 | switch (rdev->desc->id) { | 105 | switch (rdev_get_id(rdev)) { |
| 106 | case S2MPA01_BUCK1: | 106 | case S2MPA01_BUCK1: |
| 107 | enable_shift = S2MPA01_BUCK1_RAMP_EN_SHIFT; | 107 | enable_shift = S2MPA01_BUCK1_RAMP_EN_SHIFT; |
| 108 | if (!ramp_delay) { | 108 | if (!ramp_delay) { |
| @@ -116,7 +116,6 @@ static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) | |||
| 116 | ramp_delay = s2mpa01->ramp_delay16; | 116 | ramp_delay = s2mpa01->ramp_delay16; |
| 117 | 117 | ||
| 118 | ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT; | 118 | ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT; |
| 119 | ramp_reg = S2MPA01_REG_RAMP1; | ||
| 120 | break; | 119 | break; |
| 121 | case S2MPA01_BUCK2: | 120 | case S2MPA01_BUCK2: |
| 122 | enable_shift = S2MPA01_BUCK2_RAMP_EN_SHIFT; | 121 | enable_shift = S2MPA01_BUCK2_RAMP_EN_SHIFT; |
| @@ -192,11 +191,15 @@ static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) | |||
| 192 | if (!ramp_enable) | 191 | if (!ramp_enable) |
| 193 | goto ramp_disable; | 192 | goto ramp_disable; |
| 194 | 193 | ||
| 195 | ret = regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1, | 194 | /* Ramp delay can be enabled/disabled only for buck[1234] */ |
| 196 | 1 << enable_shift, 1 << enable_shift); | 195 | if (rdev_get_id(rdev) >= S2MPA01_BUCK1 && |
| 197 | if (ret) { | 196 | rdev_get_id(rdev) <= S2MPA01_BUCK4) { |
| 198 | dev_err(&rdev->dev, "failed to enable ramp rate\n"); | 197 | ret = regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1, |
| 199 | return ret; | 198 | 1 << enable_shift, 1 << enable_shift); |
| 199 | if (ret) { | ||
| 200 | dev_err(&rdev->dev, "failed to enable ramp rate\n"); | ||
| 201 | return ret; | ||
| 202 | } | ||
| 200 | } | 203 | } |
| 201 | 204 | ||
| 202 | ramp_val = get_ramp_delay(ramp_delay); | 205 | ramp_val = get_ramp_delay(ramp_delay); |
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: |
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 92f19a005dc3..c79af943a5c0 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c | |||
| @@ -28,7 +28,6 @@ struct s5m8767_info { | |||
| 28 | struct device *dev; | 28 | struct device *dev; |
| 29 | struct sec_pmic_dev *iodev; | 29 | struct sec_pmic_dev *iodev; |
| 30 | int num_regulators; | 30 | int num_regulators; |
| 31 | struct regulator_dev **rdev; | ||
| 32 | struct sec_opmode_data *opmode; | 31 | struct sec_opmode_data *opmode; |
| 33 | 32 | ||
| 34 | int ramp_delay; | 33 | int ramp_delay; |
| @@ -529,16 +528,6 @@ static int s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev *iodev, | |||
| 529 | return 0; | 528 | return 0; |
| 530 | } | 529 | } |
| 531 | 530 | ||
| 532 | static void s5m8767_pmic_dt_parse_ext_control_gpio(struct sec_pmic_dev *iodev, | ||
| 533 | struct sec_regulator_data *rdata, | ||
| 534 | struct device_node *reg_np) | ||
| 535 | { | ||
| 536 | rdata->ext_control_gpio = of_get_named_gpio(reg_np, | ||
| 537 | "s5m8767,pmic-ext-control-gpios", 0); | ||
| 538 | if (!gpio_is_valid(rdata->ext_control_gpio)) | ||
| 539 | rdata->ext_control_gpio = 0; | ||
| 540 | } | ||
| 541 | |||
| 542 | static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, | 531 | static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, |
| 543 | struct sec_platform_data *pdata) | 532 | struct sec_platform_data *pdata) |
| 544 | { | 533 | { |
| @@ -587,7 +576,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, | |||
| 587 | continue; | 576 | continue; |
| 588 | } | 577 | } |
| 589 | 578 | ||
| 590 | s5m8767_pmic_dt_parse_ext_control_gpio(iodev, rdata, reg_np); | 579 | rdata->ext_control_gpio = of_get_named_gpio(reg_np, |
| 580 | "s5m8767,pmic-ext-control-gpios", 0); | ||
| 591 | 581 | ||
| 592 | rdata->id = i; | 582 | rdata->id = i; |
| 593 | rdata->initdata = of_get_regulator_init_data( | 583 | rdata->initdata = of_get_regulator_init_data( |
| @@ -695,7 +685,6 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) | |||
| 695 | struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); | 685 | struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); |
| 696 | struct sec_platform_data *pdata = iodev->pdata; | 686 | struct sec_platform_data *pdata = iodev->pdata; |
| 697 | struct regulator_config config = { }; | 687 | struct regulator_config config = { }; |
| 698 | struct regulator_dev **rdev; | ||
| 699 | struct s5m8767_info *s5m8767; | 688 | struct s5m8767_info *s5m8767; |
| 700 | int i, ret, size, buck_init; | 689 | int i, ret, size, buck_init; |
| 701 | 690 | ||
| @@ -737,11 +726,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) | |||
| 737 | return -ENOMEM; | 726 | return -ENOMEM; |
| 738 | 727 | ||
| 739 | size = sizeof(struct regulator_dev *) * (S5M8767_REG_MAX - 2); | 728 | size = sizeof(struct regulator_dev *) * (S5M8767_REG_MAX - 2); |
| 740 | s5m8767->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); | ||
| 741 | if (!s5m8767->rdev) | ||
| 742 | return -ENOMEM; | ||
| 743 | 729 | ||
| 744 | rdev = s5m8767->rdev; | ||
| 745 | s5m8767->dev = &pdev->dev; | 730 | s5m8767->dev = &pdev->dev; |
| 746 | s5m8767->iodev = iodev; | 731 | s5m8767->iodev = iodev; |
| 747 | s5m8767->num_regulators = pdata->num_regulators; | 732 | s5m8767->num_regulators = pdata->num_regulators; |
| @@ -938,6 +923,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) | |||
| 938 | const struct sec_voltage_desc *desc; | 923 | const struct sec_voltage_desc *desc; |
| 939 | int id = pdata->regulators[i].id; | 924 | int id = pdata->regulators[i].id; |
| 940 | int enable_reg, enable_val; | 925 | int enable_reg, enable_val; |
| 926 | struct regulator_dev *rdev; | ||
| 941 | 927 | ||
| 942 | desc = reg_voltage_map[id]; | 928 | desc = reg_voltage_map[id]; |
| 943 | if (desc) { | 929 | if (desc) { |
| @@ -964,26 +950,27 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) | |||
| 964 | config.driver_data = s5m8767; | 950 | config.driver_data = s5m8767; |
| 965 | config.regmap = iodev->regmap_pmic; | 951 | config.regmap = iodev->regmap_pmic; |
| 966 | config.of_node = pdata->regulators[i].reg_node; | 952 | config.of_node = pdata->regulators[i].reg_node; |
| 967 | config.ena_gpio = config.ena_gpio_flags = 0; | 953 | config.ena_gpio = -EINVAL; |
| 968 | if (pdata->regulators[i].ext_control_gpio) | 954 | config.ena_gpio_flags = 0; |
| 955 | if (gpio_is_valid(pdata->regulators[i].ext_control_gpio)) | ||
| 969 | s5m8767_regulator_config_ext_control(s5m8767, | 956 | s5m8767_regulator_config_ext_control(s5m8767, |
| 970 | &pdata->regulators[i], &config); | 957 | &pdata->regulators[i], &config); |
| 971 | 958 | ||
| 972 | rdev[i] = devm_regulator_register(&pdev->dev, ®ulators[id], | 959 | rdev = devm_regulator_register(&pdev->dev, ®ulators[id], |
| 973 | &config); | 960 | &config); |
| 974 | if (IS_ERR(rdev[i])) { | 961 | if (IS_ERR(rdev)) { |
| 975 | ret = PTR_ERR(rdev[i]); | 962 | ret = PTR_ERR(rdev); |
| 976 | dev_err(s5m8767->dev, "regulator init failed for %d\n", | 963 | dev_err(s5m8767->dev, "regulator init failed for %d\n", |
| 977 | id); | 964 | id); |
| 978 | return ret; | 965 | return ret; |
| 979 | } | 966 | } |
| 980 | 967 | ||
| 981 | if (pdata->regulators[i].ext_control_gpio) { | 968 | if (gpio_is_valid(pdata->regulators[i].ext_control_gpio)) { |
| 982 | ret = s5m8767_enable_ext_control(s5m8767, rdev[i]); | 969 | ret = s5m8767_enable_ext_control(s5m8767, rdev); |
| 983 | if (ret < 0) { | 970 | if (ret < 0) { |
| 984 | dev_err(s5m8767->dev, | 971 | dev_err(s5m8767->dev, |
| 985 | "failed to enable gpio control over %s: %d\n", | 972 | "failed to enable gpio control over %s: %d\n", |
| 986 | rdev[i]->desc->name, ret); | 973 | rdev->desc->name, ret); |
| 987 | return ret; | 974 | return ret; |
| 988 | } | 975 | } |
| 989 | } | 976 | } |
diff --git a/drivers/regulator/st-pwm.c b/drivers/regulator/st-pwm.c index e367af1c5f9d..5ea78df449f8 100644 --- a/drivers/regulator/st-pwm.c +++ b/drivers/regulator/st-pwm.c | |||
| @@ -118,7 +118,7 @@ static const struct st_pwm_regulator_pdata b2105_info = { | |||
| 118 | .duty_cycle_table = b2105_duty_cycle_table, | 118 | .duty_cycle_table = b2105_duty_cycle_table, |
| 119 | }; | 119 | }; |
| 120 | 120 | ||
| 121 | static struct of_device_id st_pwm_of_match[] = { | 121 | static const struct of_device_id st_pwm_of_match[] = { |
| 122 | { .compatible = "st,b2105-pwm-regulator", .data = &b2105_info, }, | 122 | { .compatible = "st,b2105-pwm-regulator", .data = &b2105_info, }, |
| 123 | { }, | 123 | { }, |
| 124 | }; | 124 | }; |
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c index 2e92ef68574d..2064b3fd45f7 100644 --- a/drivers/regulator/tps65090-regulator.c +++ b/drivers/regulator/tps65090-regulator.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 20 | #include <linux/delay.h> | ||
| 20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
| 21 | #include <linux/gpio.h> | 22 | #include <linux/gpio.h> |
| 22 | #include <linux/of_gpio.h> | 23 | #include <linux/of_gpio.h> |
| @@ -28,49 +29,216 @@ | |||
| 28 | #include <linux/regulator/of_regulator.h> | 29 | #include <linux/regulator/of_regulator.h> |
| 29 | #include <linux/mfd/tps65090.h> | 30 | #include <linux/mfd/tps65090.h> |
| 30 | 31 | ||
| 32 | #define MAX_CTRL_READ_TRIES 5 | ||
| 33 | #define MAX_FET_ENABLE_TRIES 1000 | ||
| 34 | |||
| 35 | #define CTRL_EN_BIT 0 /* Regulator enable bit, active high */ | ||
| 36 | #define CTRL_WT_BIT 2 /* Regulator wait time 0 bit */ | ||
| 37 | #define CTRL_PG_BIT 4 /* Regulator power good bit, 1=good */ | ||
| 38 | #define CTRL_TO_BIT 7 /* Regulator timeout bit, 1=wait */ | ||
| 39 | |||
| 40 | #define MAX_OVERCURRENT_WAIT 3 /* Overcurrent wait must be <= this */ | ||
| 41 | |||
| 42 | /** | ||
| 43 | * struct tps65090_regulator - Per-regulator data for a tps65090 regulator | ||
| 44 | * | ||
| 45 | * @dev: Pointer to our device. | ||
| 46 | * @desc: The struct regulator_desc for the regulator. | ||
| 47 | * @rdev: The struct regulator_dev for the regulator. | ||
| 48 | * @overcurrent_wait_valid: True if overcurrent_wait is valid. | ||
| 49 | * @overcurrent_wait: For FETs, the value to put in the WTFET bitfield. | ||
| 50 | */ | ||
| 51 | |||
| 31 | struct tps65090_regulator { | 52 | struct tps65090_regulator { |
| 32 | struct device *dev; | 53 | struct device *dev; |
| 33 | struct regulator_desc *desc; | 54 | struct regulator_desc *desc; |
| 34 | struct regulator_dev *rdev; | 55 | struct regulator_dev *rdev; |
| 56 | bool overcurrent_wait_valid; | ||
| 57 | int overcurrent_wait; | ||
| 35 | }; | 58 | }; |
| 36 | 59 | ||
| 37 | static struct regulator_ops tps65090_ext_control_ops = { | 60 | static struct regulator_ops tps65090_ext_control_ops = { |
| 38 | }; | 61 | }; |
| 39 | 62 | ||
| 40 | static struct regulator_ops tps65090_reg_contol_ops = { | 63 | /** |
| 64 | * tps65090_reg_set_overcurrent_wait - Setup overcurrent wait | ||
| 65 | * | ||
| 66 | * This will set the overcurrent wait time based on what's in the regulator | ||
| 67 | * info. | ||
| 68 | * | ||
| 69 | * @ri: Overall regulator data | ||
| 70 | * @rdev: Regulator device | ||
| 71 | * | ||
| 72 | * Return: 0 if no error, non-zero if there was an error writing the register. | ||
| 73 | */ | ||
| 74 | static int tps65090_reg_set_overcurrent_wait(struct tps65090_regulator *ri, | ||
| 75 | struct regulator_dev *rdev) | ||
| 76 | { | ||
| 77 | int ret; | ||
| 78 | |||
| 79 | ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | ||
| 80 | MAX_OVERCURRENT_WAIT << CTRL_WT_BIT, | ||
| 81 | ri->overcurrent_wait << CTRL_WT_BIT); | ||
| 82 | if (ret) { | ||
| 83 | dev_err(&rdev->dev, "Error updating overcurrent wait %#x\n", | ||
| 84 | rdev->desc->enable_reg); | ||
| 85 | } | ||
| 86 | |||
| 87 | return ret; | ||
| 88 | } | ||
| 89 | |||
| 90 | /** | ||
| 91 | * tps65090_try_enable_fet - Try to enable a FET | ||
| 92 | * | ||
| 93 | * @rdev: Regulator device | ||
| 94 | * | ||
| 95 | * Return: 0 if ok, -ENOTRECOVERABLE if the FET power good bit did not get | ||
| 96 | * set, or some other -ve value if another error occurred (e.g. i2c error) | ||
| 97 | */ | ||
| 98 | static int tps65090_try_enable_fet(struct regulator_dev *rdev) | ||
| 99 | { | ||
| 100 | unsigned int control; | ||
| 101 | int ret, i; | ||
| 102 | |||
| 103 | ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | ||
| 104 | rdev->desc->enable_mask, | ||
| 105 | rdev->desc->enable_mask); | ||
| 106 | if (ret < 0) { | ||
| 107 | dev_err(&rdev->dev, "Error in updating reg %#x\n", | ||
| 108 | rdev->desc->enable_reg); | ||
| 109 | return ret; | ||
| 110 | } | ||
| 111 | |||
| 112 | for (i = 0; i < MAX_CTRL_READ_TRIES; i++) { | ||
| 113 | ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, | ||
| 114 | &control); | ||
| 115 | if (ret < 0) | ||
| 116 | return ret; | ||
| 117 | |||
| 118 | if (!(control & BIT(CTRL_TO_BIT))) | ||
| 119 | break; | ||
| 120 | |||
| 121 | usleep_range(1000, 1500); | ||
| 122 | } | ||
| 123 | if (!(control & BIT(CTRL_PG_BIT))) | ||
| 124 | return -ENOTRECOVERABLE; | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | /** | ||
| 130 | * tps65090_fet_enable - Enable a FET, trying a few times if it fails | ||
| 131 | * | ||
| 132 | * Some versions of the tps65090 have issues when turning on the FETs. | ||
| 133 | * This function goes through several steps to ensure the best chance of the | ||
| 134 | * FET going on. Specifically: | ||
| 135 | * - We'll make sure that we bump the "overcurrent wait" to the maximum, which | ||
| 136 | * increases the chances that we'll turn on properly. | ||
| 137 | * - We'll retry turning the FET on multiple times (turning off in between). | ||
| 138 | * | ||
| 139 | * @rdev: Regulator device | ||
| 140 | * | ||
| 141 | * Return: 0 if ok, non-zero if it fails. | ||
| 142 | */ | ||
| 143 | static int tps65090_fet_enable(struct regulator_dev *rdev) | ||
| 144 | { | ||
| 145 | int ret, tries; | ||
| 146 | |||
| 147 | /* | ||
| 148 | * Try enabling multiple times until we succeed since sometimes the | ||
| 149 | * first try times out. | ||
| 150 | */ | ||
| 151 | tries = 0; | ||
| 152 | while (true) { | ||
| 153 | ret = tps65090_try_enable_fet(rdev); | ||
| 154 | if (!ret) | ||
| 155 | break; | ||
| 156 | if (ret != -ENOTRECOVERABLE || tries == MAX_FET_ENABLE_TRIES) | ||
| 157 | goto err; | ||
| 158 | |||
| 159 | /* Try turning the FET off (and then on again) */ | ||
| 160 | ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | ||
| 161 | rdev->desc->enable_mask, 0); | ||
| 162 | if (ret) | ||
| 163 | goto err; | ||
| 164 | |||
| 165 | tries++; | ||
| 166 | } | ||
| 167 | |||
| 168 | if (tries) | ||
| 169 | dev_warn(&rdev->dev, "reg %#x enable ok after %d tries\n", | ||
| 170 | rdev->desc->enable_reg, tries); | ||
| 171 | |||
| 172 | return 0; | ||
| 173 | err: | ||
| 174 | dev_warn(&rdev->dev, "reg %#x enable failed\n", rdev->desc->enable_reg); | ||
| 175 | WARN_ON(1); | ||
| 176 | |||
| 177 | return ret; | ||
| 178 | } | ||
| 179 | |||
| 180 | static struct regulator_ops tps65090_reg_control_ops = { | ||
| 41 | .enable = regulator_enable_regmap, | 181 | .enable = regulator_enable_regmap, |
| 42 | .disable = regulator_disable_regmap, | 182 | .disable = regulator_disable_regmap, |
| 43 | .is_enabled = regulator_is_enabled_regmap, | 183 | .is_enabled = regulator_is_enabled_regmap, |
| 44 | }; | 184 | }; |
| 45 | 185 | ||
| 186 | static struct regulator_ops tps65090_fet_control_ops = { | ||
| 187 | .enable = tps65090_fet_enable, | ||
| 188 | .disable = regulator_disable_regmap, | ||
| 189 | .is_enabled = regulator_is_enabled_regmap, | ||
| 190 | }; | ||
| 191 | |||
| 46 | static struct regulator_ops tps65090_ldo_ops = { | 192 | static struct regulator_ops tps65090_ldo_ops = { |
| 47 | }; | 193 | }; |
| 48 | 194 | ||
| 49 | #define tps65090_REG_DESC(_id, _sname, _en_reg, _ops) \ | 195 | #define tps65090_REG_DESC(_id, _sname, _en_reg, _en_bits, _ops) \ |
| 50 | { \ | 196 | { \ |
| 51 | .name = "TPS65090_RAILS"#_id, \ | 197 | .name = "TPS65090_RAILS"#_id, \ |
| 52 | .supply_name = _sname, \ | 198 | .supply_name = _sname, \ |
| 53 | .id = TPS65090_REGULATOR_##_id, \ | 199 | .id = TPS65090_REGULATOR_##_id, \ |
| 54 | .ops = &_ops, \ | 200 | .ops = &_ops, \ |
| 55 | .enable_reg = _en_reg, \ | 201 | .enable_reg = _en_reg, \ |
| 56 | .enable_mask = BIT(0), \ | 202 | .enable_val = _en_bits, \ |
| 203 | .enable_mask = _en_bits, \ | ||
| 57 | .type = REGULATOR_VOLTAGE, \ | 204 | .type = REGULATOR_VOLTAGE, \ |
| 58 | .owner = THIS_MODULE, \ | 205 | .owner = THIS_MODULE, \ |
| 59 | } | 206 | } |
| 60 | 207 | ||
| 61 | static struct regulator_desc tps65090_regulator_desc[] = { | 208 | static struct regulator_desc tps65090_regulator_desc[] = { |
| 62 | tps65090_REG_DESC(DCDC1, "vsys1", 0x0C, tps65090_reg_contol_ops), | 209 | tps65090_REG_DESC(DCDC1, "vsys1", 0x0C, BIT(CTRL_EN_BIT), |
| 63 | tps65090_REG_DESC(DCDC2, "vsys2", 0x0D, tps65090_reg_contol_ops), | 210 | tps65090_reg_control_ops), |
| 64 | tps65090_REG_DESC(DCDC3, "vsys3", 0x0E, tps65090_reg_contol_ops), | 211 | tps65090_REG_DESC(DCDC2, "vsys2", 0x0D, BIT(CTRL_EN_BIT), |
| 65 | tps65090_REG_DESC(FET1, "infet1", 0x0F, tps65090_reg_contol_ops), | 212 | tps65090_reg_control_ops), |
| 66 | tps65090_REG_DESC(FET2, "infet2", 0x10, tps65090_reg_contol_ops), | 213 | tps65090_REG_DESC(DCDC3, "vsys3", 0x0E, BIT(CTRL_EN_BIT), |
| 67 | tps65090_REG_DESC(FET3, "infet3", 0x11, tps65090_reg_contol_ops), | 214 | tps65090_reg_control_ops), |
| 68 | tps65090_REG_DESC(FET4, "infet4", 0x12, tps65090_reg_contol_ops), | 215 | |
| 69 | tps65090_REG_DESC(FET5, "infet5", 0x13, tps65090_reg_contol_ops), | 216 | tps65090_REG_DESC(FET1, "infet1", 0x0F, |
| 70 | tps65090_REG_DESC(FET6, "infet6", 0x14, tps65090_reg_contol_ops), | 217 | BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), |
| 71 | tps65090_REG_DESC(FET7, "infet7", 0x15, tps65090_reg_contol_ops), | 218 | tps65090_fet_control_ops), |
| 72 | tps65090_REG_DESC(LDO1, "vsys-l1", 0, tps65090_ldo_ops), | 219 | tps65090_REG_DESC(FET2, "infet2", 0x10, |
| 73 | tps65090_REG_DESC(LDO2, "vsys-l2", 0, tps65090_ldo_ops), | 220 | BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), |
| 221 | tps65090_fet_control_ops), | ||
| 222 | tps65090_REG_DESC(FET3, "infet3", 0x11, | ||
| 223 | BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), | ||
| 224 | tps65090_fet_control_ops), | ||
| 225 | tps65090_REG_DESC(FET4, "infet4", 0x12, | ||
| 226 | BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), | ||
| 227 | tps65090_fet_control_ops), | ||
| 228 | tps65090_REG_DESC(FET5, "infet5", 0x13, | ||
| 229 | BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), | ||
| 230 | tps65090_fet_control_ops), | ||
| 231 | tps65090_REG_DESC(FET6, "infet6", 0x14, | ||
| 232 | BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), | ||
| 233 | tps65090_fet_control_ops), | ||
| 234 | tps65090_REG_DESC(FET7, "infet7", 0x15, | ||
| 235 | BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), | ||
| 236 | tps65090_fet_control_ops), | ||
| 237 | |||
| 238 | tps65090_REG_DESC(LDO1, "vsys-l1", 0, 0, | ||
| 239 | tps65090_ldo_ops), | ||
| 240 | tps65090_REG_DESC(LDO2, "vsys-l2", 0, 0, | ||
| 241 | tps65090_ldo_ops), | ||
| 74 | }; | 242 | }; |
| 75 | 243 | ||
| 76 | static inline bool is_dcdc(int id) | 244 | static inline bool is_dcdc(int id) |
| @@ -209,6 +377,11 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data( | |||
| 209 | rpdata->gpio = of_get_named_gpio(np, | 377 | rpdata->gpio = of_get_named_gpio(np, |
| 210 | "dcdc-ext-control-gpios", 0); | 378 | "dcdc-ext-control-gpios", 0); |
| 211 | 379 | ||
| 380 | if (of_property_read_u32(tps65090_matches[idx].of_node, | ||
| 381 | "ti,overcurrent-wait", | ||
| 382 | &rpdata->overcurrent_wait) == 0) | ||
| 383 | rpdata->overcurrent_wait_valid = true; | ||
| 384 | |||
| 212 | tps65090_pdata->reg_pdata[idx] = rpdata; | 385 | tps65090_pdata->reg_pdata[idx] = rpdata; |
| 213 | } | 386 | } |
| 214 | return tps65090_pdata; | 387 | return tps65090_pdata; |
| @@ -258,6 +431,11 @@ static int tps65090_regulator_probe(struct platform_device *pdev) | |||
| 258 | ri = &pmic[num]; | 431 | ri = &pmic[num]; |
| 259 | ri->dev = &pdev->dev; | 432 | ri->dev = &pdev->dev; |
| 260 | ri->desc = &tps65090_regulator_desc[num]; | 433 | ri->desc = &tps65090_regulator_desc[num]; |
| 434 | if (tps_pdata) { | ||
| 435 | ri->overcurrent_wait_valid = | ||
| 436 | tps_pdata->overcurrent_wait_valid; | ||
| 437 | ri->overcurrent_wait = tps_pdata->overcurrent_wait; | ||
| 438 | } | ||
| 261 | 439 | ||
| 262 | /* | 440 | /* |
| 263 | * TPS5090 DCDC support the control from external digital input. | 441 | * TPS5090 DCDC support the control from external digital input. |
| @@ -299,6 +477,12 @@ static int tps65090_regulator_probe(struct platform_device *pdev) | |||
| 299 | } | 477 | } |
| 300 | ri->rdev = rdev; | 478 | ri->rdev = rdev; |
| 301 | 479 | ||
| 480 | if (ri->overcurrent_wait_valid) { | ||
| 481 | ret = tps65090_reg_set_overcurrent_wait(ri, rdev); | ||
| 482 | if (ret < 0) | ||
| 483 | return ret; | ||
| 484 | } | ||
| 485 | |||
| 302 | /* Enable external control if it is require */ | 486 | /* Enable external control if it is require */ |
| 303 | if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data && | 487 | if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data && |
| 304 | tps_pdata->enable_ext_control) { | 488 | tps_pdata->enable_ext_control) { |
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 10b78d2b766a..f7ed20a5a8b9 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c | |||
| @@ -134,6 +134,7 @@ static struct regulator_ops tps65217_pmic_ldo1_ops = { | |||
| 134 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 134 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
| 135 | .set_voltage_sel = tps65217_pmic_set_voltage_sel, | 135 | .set_voltage_sel = tps65217_pmic_set_voltage_sel, |
| 136 | .list_voltage = regulator_list_voltage_table, | 136 | .list_voltage = regulator_list_voltage_table, |
| 137 | .map_voltage = regulator_map_voltage_ascend, | ||
| 137 | }; | 138 | }; |
| 138 | 139 | ||
| 139 | static const struct regulator_desc regulators[] = { | 140 | static const struct regulator_desc regulators[] = { |
| @@ -257,9 +258,6 @@ static int tps65217_regulator_probe(struct platform_device *pdev) | |||
| 257 | pdev->name); | 258 | pdev->name); |
| 258 | return PTR_ERR(rdev); | 259 | return PTR_ERR(rdev); |
| 259 | } | 260 | } |
| 260 | |||
| 261 | /* Save regulator for cleanup */ | ||
| 262 | tps->rdev[i] = rdev; | ||
| 263 | } | 261 | } |
| 264 | return 0; | 262 | return 0; |
| 265 | } | 263 | } |
diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c index cec72fa71d1d..69b4b7750410 100644 --- a/drivers/regulator/tps65218-regulator.c +++ b/drivers/regulator/tps65218-regulator.c | |||
| @@ -27,12 +27,10 @@ | |||
| 27 | #include <linux/regulator/machine.h> | 27 | #include <linux/regulator/machine.h> |
| 28 | #include <linux/mfd/tps65218.h> | 28 | #include <linux/mfd/tps65218.h> |
| 29 | 29 | ||
| 30 | static unsigned int tps65218_ramp_delay = 4000; | ||
| 31 | |||
| 32 | enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, DCDC5, DCDC6, LDO1 }; | 30 | enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, DCDC5, DCDC6, LDO1 }; |
| 33 | 31 | ||
| 34 | #define TPS65218_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _er, _em, _t, \ | 32 | #define TPS65218_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _er, _em, _t, \ |
| 35 | _lr, _nlr) \ | 33 | _lr, _nlr, _delay) \ |
| 36 | { \ | 34 | { \ |
| 37 | .name = _name, \ | 35 | .name = _name, \ |
| 38 | .id = _id, \ | 36 | .id = _id, \ |
| @@ -47,6 +45,7 @@ enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, DCDC5, DCDC6, LDO1 }; | |||
| 47 | .volt_table = _t, \ | 45 | .volt_table = _t, \ |
| 48 | .linear_ranges = _lr, \ | 46 | .linear_ranges = _lr, \ |
| 49 | .n_linear_ranges = _nlr, \ | 47 | .n_linear_ranges = _nlr, \ |
| 48 | .ramp_delay = _delay, \ | ||
| 50 | } \ | 49 | } \ |
| 51 | 50 | ||
| 52 | #define TPS65218_INFO(_id, _nm, _min, _max) \ | 51 | #define TPS65218_INFO(_id, _nm, _min, _max) \ |
| @@ -152,22 +151,6 @@ static int tps65218_pmic_disable(struct regulator_dev *dev) | |||
| 152 | dev->desc->enable_mask, TPS65218_PROTECT_L1); | 151 | dev->desc->enable_mask, TPS65218_PROTECT_L1); |
| 153 | } | 152 | } |
| 154 | 153 | ||
| 155 | static int tps65218_set_voltage_time_sel(struct regulator_dev *rdev, | ||
| 156 | unsigned int old_selector, unsigned int new_selector) | ||
| 157 | { | ||
| 158 | int old_uv, new_uv; | ||
| 159 | |||
| 160 | old_uv = regulator_list_voltage_linear_range(rdev, old_selector); | ||
| 161 | if (old_uv < 0) | ||
| 162 | return old_uv; | ||
| 163 | |||
| 164 | new_uv = regulator_list_voltage_linear_range(rdev, new_selector); | ||
| 165 | if (new_uv < 0) | ||
| 166 | return new_uv; | ||
| 167 | |||
| 168 | return DIV_ROUND_UP(abs(old_uv - new_uv), tps65218_ramp_delay); | ||
| 169 | } | ||
| 170 | |||
| 171 | /* Operations permitted on DCDC1, DCDC2 */ | 154 | /* Operations permitted on DCDC1, DCDC2 */ |
| 172 | static struct regulator_ops tps65218_dcdc12_ops = { | 155 | static struct regulator_ops tps65218_dcdc12_ops = { |
| 173 | .is_enabled = regulator_is_enabled_regmap, | 156 | .is_enabled = regulator_is_enabled_regmap, |
| @@ -177,7 +160,7 @@ static struct regulator_ops tps65218_dcdc12_ops = { | |||
| 177 | .set_voltage_sel = tps65218_pmic_set_voltage_sel, | 160 | .set_voltage_sel = tps65218_pmic_set_voltage_sel, |
| 178 | .list_voltage = regulator_list_voltage_linear_range, | 161 | .list_voltage = regulator_list_voltage_linear_range, |
| 179 | .map_voltage = regulator_map_voltage_linear_range, | 162 | .map_voltage = regulator_map_voltage_linear_range, |
| 180 | .set_voltage_time_sel = tps65218_set_voltage_time_sel, | 163 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
| 181 | }; | 164 | }; |
| 182 | 165 | ||
| 183 | /* Operations permitted on DCDC3, DCDC4 and LDO1 */ | 166 | /* Operations permitted on DCDC3, DCDC4 and LDO1 */ |
| @@ -203,33 +186,33 @@ static const struct regulator_desc regulators[] = { | |||
| 203 | TPS65218_REG_CONTROL_DCDC1, | 186 | TPS65218_REG_CONTROL_DCDC1, |
| 204 | TPS65218_CONTROL_DCDC1_MASK, | 187 | TPS65218_CONTROL_DCDC1_MASK, |
| 205 | TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC1_EN, NULL, | 188 | TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC1_EN, NULL, |
| 206 | dcdc1_dcdc2_ranges, 2), | 189 | dcdc1_dcdc2_ranges, 2, 4000), |
| 207 | TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, tps65218_dcdc12_ops, 64, | 190 | TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, tps65218_dcdc12_ops, 64, |
| 208 | TPS65218_REG_CONTROL_DCDC2, | 191 | TPS65218_REG_CONTROL_DCDC2, |
| 209 | TPS65218_CONTROL_DCDC2_MASK, | 192 | TPS65218_CONTROL_DCDC2_MASK, |
| 210 | TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC2_EN, NULL, | 193 | TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC2_EN, NULL, |
| 211 | dcdc1_dcdc2_ranges, 2), | 194 | dcdc1_dcdc2_ranges, 2, 4000), |
| 212 | TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, tps65218_ldo1_dcdc34_ops, | 195 | TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, tps65218_ldo1_dcdc34_ops, |
| 213 | 64, TPS65218_REG_CONTROL_DCDC3, | 196 | 64, TPS65218_REG_CONTROL_DCDC3, |
| 214 | TPS65218_CONTROL_DCDC3_MASK, TPS65218_REG_ENABLE1, | 197 | TPS65218_CONTROL_DCDC3_MASK, TPS65218_REG_ENABLE1, |
| 215 | TPS65218_ENABLE1_DC3_EN, NULL, | 198 | TPS65218_ENABLE1_DC3_EN, NULL, |
| 216 | ldo1_dcdc3_ranges, 2), | 199 | ldo1_dcdc3_ranges, 2, 0), |
| 217 | TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, tps65218_ldo1_dcdc34_ops, | 200 | TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, tps65218_ldo1_dcdc34_ops, |
| 218 | 53, TPS65218_REG_CONTROL_DCDC4, | 201 | 53, TPS65218_REG_CONTROL_DCDC4, |
| 219 | TPS65218_CONTROL_DCDC4_MASK, | 202 | TPS65218_CONTROL_DCDC4_MASK, |
| 220 | TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC4_EN, NULL, | 203 | TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC4_EN, NULL, |
| 221 | dcdc4_ranges, 2), | 204 | dcdc4_ranges, 2, 0), |
| 222 | TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, tps65218_dcdc56_pmic_ops, | 205 | TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, tps65218_dcdc56_pmic_ops, |
| 223 | 1, -1, -1, TPS65218_REG_ENABLE1, | 206 | 1, -1, -1, TPS65218_REG_ENABLE1, |
| 224 | TPS65218_ENABLE1_DC5_EN, NULL, NULL, 0), | 207 | TPS65218_ENABLE1_DC5_EN, NULL, NULL, 0, 0), |
| 225 | TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, tps65218_dcdc56_pmic_ops, | 208 | TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, tps65218_dcdc56_pmic_ops, |
| 226 | 1, -1, -1, TPS65218_REG_ENABLE1, | 209 | 1, -1, -1, TPS65218_REG_ENABLE1, |
| 227 | TPS65218_ENABLE1_DC6_EN, NULL, NULL, 0), | 210 | TPS65218_ENABLE1_DC6_EN, NULL, NULL, 0, 0), |
| 228 | TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, tps65218_ldo1_dcdc34_ops, 64, | 211 | TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, tps65218_ldo1_dcdc34_ops, 64, |
| 229 | TPS65218_REG_CONTROL_DCDC4, | 212 | TPS65218_REG_CONTROL_DCDC4, |
| 230 | TPS65218_CONTROL_LDO1_MASK, TPS65218_REG_ENABLE2, | 213 | TPS65218_CONTROL_LDO1_MASK, TPS65218_REG_ENABLE2, |
| 231 | TPS65218_ENABLE2_LDO1_EN, NULL, ldo1_dcdc3_ranges, | 214 | TPS65218_ENABLE2_LDO1_EN, NULL, ldo1_dcdc3_ranges, |
| 232 | 2), | 215 | 2, 0), |
| 233 | }; | 216 | }; |
| 234 | 217 | ||
| 235 | static int tps65218_regulator_probe(struct platform_device *pdev) | 218 | static int tps65218_regulator_probe(struct platform_device *pdev) |
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 32f38a63d944..0a3bb3aecd97 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c | |||
| @@ -63,12 +63,7 @@ struct tps6586x_regulator { | |||
| 63 | int enable_reg[2]; | 63 | int enable_reg[2]; |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
| 66 | static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev) | 66 | static struct regulator_ops tps6586x_rw_regulator_ops = { |
| 67 | { | ||
| 68 | return rdev_get_dev(rdev)->parent; | ||
| 69 | } | ||
| 70 | |||
| 71 | static struct regulator_ops tps6586x_regulator_ops = { | ||
| 72 | .list_voltage = regulator_list_voltage_table, | 67 | .list_voltage = regulator_list_voltage_table, |
| 73 | .map_voltage = regulator_map_voltage_ascend, | 68 | .map_voltage = regulator_map_voltage_ascend, |
| 74 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 69 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
| @@ -79,6 +74,16 @@ static struct regulator_ops tps6586x_regulator_ops = { | |||
| 79 | .disable = regulator_disable_regmap, | 74 | .disable = regulator_disable_regmap, |
| 80 | }; | 75 | }; |
| 81 | 76 | ||
| 77 | static struct regulator_ops tps6586x_ro_regulator_ops = { | ||
| 78 | .list_voltage = regulator_list_voltage_table, | ||
| 79 | .map_voltage = regulator_map_voltage_ascend, | ||
| 80 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
| 81 | |||
| 82 | .is_enabled = regulator_is_enabled_regmap, | ||
| 83 | .enable = regulator_enable_regmap, | ||
| 84 | .disable = regulator_disable_regmap, | ||
| 85 | }; | ||
| 86 | |||
| 82 | static struct regulator_ops tps6586x_sys_regulator_ops = { | 87 | static struct regulator_ops tps6586x_sys_regulator_ops = { |
| 83 | }; | 88 | }; |
| 84 | 89 | ||
| @@ -106,6 +111,13 @@ static const unsigned int tps6586x_sm2_voltages[] = { | |||
| 106 | 4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000, | 111 | 4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000, |
| 107 | }; | 112 | }; |
| 108 | 113 | ||
| 114 | static int tps658640_sm2_voltages[] = { | ||
| 115 | 2150000, 2200000, 2250000, 2300000, 2350000, 2400000, 2450000, 2500000, | ||
| 116 | 2550000, 2600000, 2650000, 2700000, 2750000, 2800000, 2850000, 2900000, | ||
| 117 | 2950000, 3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000, | ||
| 118 | 3350000, 3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000, | ||
| 119 | }; | ||
| 120 | |||
| 109 | static const unsigned int tps658643_sm2_voltages[] = { | 121 | static const unsigned int tps658643_sm2_voltages[] = { |
| 110 | 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, | 122 | 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, |
| 111 | 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000, | 123 | 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000, |
| @@ -120,12 +132,16 @@ static const unsigned int tps6586x_dvm_voltages[] = { | |||
| 120 | 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000, | 132 | 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000, |
| 121 | }; | 133 | }; |
| 122 | 134 | ||
| 123 | #define TPS6586X_REGULATOR(_id, _pin_name, vdata, vreg, shift, nbits, \ | 135 | static int tps658640_rtc_voltages[] = { |
| 136 | 2500000, 2850000, 3100000, 3300000, | ||
| 137 | }; | ||
| 138 | |||
| 139 | #define TPS6586X_REGULATOR(_id, _ops, _pin_name, vdata, vreg, shift, nbits, \ | ||
| 124 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ | 140 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ |
| 125 | .desc = { \ | 141 | .desc = { \ |
| 126 | .supply_name = _pin_name, \ | 142 | .supply_name = _pin_name, \ |
| 127 | .name = "REG-" #_id, \ | 143 | .name = "REG-" #_id, \ |
| 128 | .ops = &tps6586x_regulator_ops, \ | 144 | .ops = &tps6586x_## _ops ## _regulator_ops, \ |
| 129 | .type = REGULATOR_VOLTAGE, \ | 145 | .type = REGULATOR_VOLTAGE, \ |
| 130 | .id = TPS6586X_ID_##_id, \ | 146 | .id = TPS6586X_ID_##_id, \ |
| 131 | .n_voltages = ARRAY_SIZE(vdata##_voltages), \ | 147 | .n_voltages = ARRAY_SIZE(vdata##_voltages), \ |
| @@ -146,14 +162,21 @@ static const unsigned int tps6586x_dvm_voltages[] = { | |||
| 146 | #define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits, \ | 162 | #define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits, \ |
| 147 | ereg0, ebit0, ereg1, ebit1) \ | 163 | ereg0, ebit0, ereg1, ebit1) \ |
| 148 | { \ | 164 | { \ |
| 149 | TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \ | 165 | TPS6586X_REGULATOR(_id, rw, _pname, vdata, vreg, shift, nbits, \ |
| 166 | ereg0, ebit0, ereg1, ebit1, 0, 0) \ | ||
| 167 | } | ||
| 168 | |||
| 169 | #define TPS6586X_FIXED_LDO(_id, _pname, vdata, vreg, shift, nbits, \ | ||
| 170 | ereg0, ebit0, ereg1, ebit1) \ | ||
| 171 | { \ | ||
| 172 | TPS6586X_REGULATOR(_id, ro, _pname, vdata, vreg, shift, nbits, \ | ||
| 150 | ereg0, ebit0, ereg1, ebit1, 0, 0) \ | 173 | ereg0, ebit0, ereg1, ebit1, 0, 0) \ |
| 151 | } | 174 | } |
| 152 | 175 | ||
| 153 | #define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits, \ | 176 | #define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits, \ |
| 154 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ | 177 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ |
| 155 | { \ | 178 | { \ |
| 156 | TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \ | 179 | TPS6586X_REGULATOR(_id, rw, _pname, vdata, vreg, shift, nbits, \ |
| 157 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ | 180 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ |
| 158 | } | 181 | } |
| 159 | 182 | ||
| @@ -207,6 +230,26 @@ static struct tps6586x_regulator tps658623_regulator[] = { | |||
| 207 | END, 7), | 230 | END, 7), |
| 208 | }; | 231 | }; |
| 209 | 232 | ||
| 233 | static struct tps6586x_regulator tps658640_regulator[] = { | ||
| 234 | TPS6586X_LDO(LDO_3, "vinldo23", tps6586x_ldo0, SUPPLYV4, 0, 3, | ||
| 235 | ENC, 2, END, 2), | ||
| 236 | TPS6586X_LDO(LDO_5, "REG-SYS", tps6586x_ldo0, SUPPLYV6, 0, 3, | ||
| 237 | ENE, 6, ENE, 6), | ||
| 238 | TPS6586X_LDO(LDO_6, "vinldo678", tps6586x_ldo0, SUPPLYV3, 0, 3, | ||
| 239 | ENC, 4, END, 4), | ||
| 240 | TPS6586X_LDO(LDO_7, "vinldo678", tps6586x_ldo0, SUPPLYV3, 3, 3, | ||
| 241 | ENC, 5, END, 5), | ||
| 242 | TPS6586X_LDO(LDO_8, "vinldo678", tps6586x_ldo0, SUPPLYV2, 5, 3, | ||
| 243 | ENC, 6, END, 6), | ||
| 244 | TPS6586X_LDO(LDO_9, "vinldo9", tps6586x_ldo0, SUPPLYV6, 3, 3, | ||
| 245 | ENE, 7, ENE, 7), | ||
| 246 | TPS6586X_LDO(SM_2, "vin-sm2", tps658640_sm2, SUPPLYV2, 0, 5, | ||
| 247 | ENC, 7, END, 7), | ||
| 248 | |||
| 249 | TPS6586X_FIXED_LDO(LDO_RTC, "REG-SYS", tps658640_rtc, SUPPLYV4, 3, 2, | ||
| 250 | V4, 7, V4, 7), | ||
| 251 | }; | ||
| 252 | |||
| 210 | static struct tps6586x_regulator tps658643_regulator[] = { | 253 | static struct tps6586x_regulator tps658643_regulator[] = { |
| 211 | TPS6586X_LDO(SM_2, "vin-sm2", tps658643_sm2, SUPPLYV2, 0, 5, ENC, 7, | 254 | TPS6586X_LDO(SM_2, "vin-sm2", tps658643_sm2, SUPPLYV2, 0, 5, ENC, 7, |
| 212 | END, 7), | 255 | END, 7), |
| @@ -295,6 +338,11 @@ static struct tps6586x_regulator *find_regulator_info(int id, int version) | |||
| 295 | table = tps658623_regulator; | 338 | table = tps658623_regulator; |
| 296 | num = ARRAY_SIZE(tps658623_regulator); | 339 | num = ARRAY_SIZE(tps658623_regulator); |
| 297 | break; | 340 | break; |
| 341 | case TPS658640: | ||
| 342 | case TPS658640v2: | ||
| 343 | table = tps658640_regulator; | ||
| 344 | num = ARRAY_SIZE(tps658640_regulator); | ||
| 345 | break; | ||
| 298 | case TPS658643: | 346 | case TPS658643: |
| 299 | table = tps658643_regulator; | 347 | table = tps658643_regulator; |
| 300 | num = ARRAY_SIZE(tps658643_regulator); | 348 | num = ARRAY_SIZE(tps658643_regulator); |
diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c index 2863428813e4..02e7267ccf92 100644 --- a/drivers/regulator/vexpress.c +++ b/drivers/regulator/vexpress.c | |||
| @@ -98,7 +98,7 @@ static int vexpress_regulator_probe(struct platform_device *pdev) | |||
| 98 | return 0; | 98 | return 0; |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | static struct of_device_id vexpress_regulator_of_match[] = { | 101 | static const struct of_device_id vexpress_regulator_of_match[] = { |
| 102 | { .compatible = "arm,vexpress-volt", }, | 102 | { .compatible = "arm,vexpress-volt", }, |
| 103 | { } | 103 | { } |
| 104 | }; | 104 | }; |
diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h index 5cf8b91ce996..6d9371f88875 100644 --- a/include/linux/mfd/arizona/core.h +++ b/include/linux/mfd/arizona/core.h | |||
| @@ -124,4 +124,7 @@ int wm5102_patch(struct arizona *arizona); | |||
| 124 | int wm5110_patch(struct arizona *arizona); | 124 | int wm5110_patch(struct arizona *arizona); |
| 125 | int wm8997_patch(struct arizona *arizona); | 125 | int wm8997_patch(struct arizona *arizona); |
| 126 | 126 | ||
| 127 | extern int arizona_of_get_named_gpio(struct arizona *arizona, const char *prop, | ||
| 128 | bool mandatory); | ||
| 129 | |||
| 127 | #endif | 130 | #endif |
diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h index 434df2d4e587..267aedee1c7a 100644 --- a/include/linux/mfd/bcm590xx.h +++ b/include/linux/mfd/bcm590xx.h | |||
| @@ -19,12 +19,15 @@ | |||
| 19 | #include <linux/regmap.h> | 19 | #include <linux/regmap.h> |
| 20 | 20 | ||
| 21 | /* max register address */ | 21 | /* max register address */ |
| 22 | #define BCM590XX_MAX_REGISTER 0xe7 | 22 | #define BCM590XX_MAX_REGISTER_PRI 0xe7 |
| 23 | #define BCM590XX_MAX_REGISTER_SEC 0xf0 | ||
| 23 | 24 | ||
| 24 | struct bcm590xx { | 25 | struct bcm590xx { |
| 25 | struct device *dev; | 26 | struct device *dev; |
| 26 | struct i2c_client *i2c_client; | 27 | struct i2c_client *i2c_pri; |
| 27 | struct regmap *regmap; | 28 | struct i2c_client *i2c_sec; |
| 29 | struct regmap *regmap_pri; | ||
| 30 | struct regmap *regmap_sec; | ||
| 28 | unsigned int id; | 31 | unsigned int id; |
| 29 | }; | 32 | }; |
| 30 | 33 | ||
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index bdba8c61207b..f543de91ce19 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h | |||
| @@ -63,7 +63,7 @@ struct mfd_cell { | |||
| 63 | /* A list of regulator supplies that should be mapped to the MFD | 63 | /* A list of regulator supplies that should be mapped to the MFD |
| 64 | * device rather than the child device when requested | 64 | * device rather than the child device when requested |
| 65 | */ | 65 | */ |
| 66 | const char **parent_supplies; | 66 | const char * const *parent_supplies; |
| 67 | int num_parent_supplies; | 67 | int num_parent_supplies; |
| 68 | }; | 68 | }; |
| 69 | 69 | ||
diff --git a/include/linux/mfd/samsung/s2mps14.h b/include/linux/mfd/samsung/s2mps14.h index 4b449b8ac548..900cd7a04314 100644 --- a/include/linux/mfd/samsung/s2mps14.h +++ b/include/linux/mfd/samsung/s2mps14.h | |||
| @@ -148,6 +148,8 @@ enum s2mps14_regulators { | |||
| 148 | #define S2MPS14_ENABLE_SHIFT 6 | 148 | #define S2MPS14_ENABLE_SHIFT 6 |
| 149 | /* On/Off controlled by PWREN */ | 149 | /* On/Off controlled by PWREN */ |
| 150 | #define S2MPS14_ENABLE_SUSPEND (0x01 << S2MPS14_ENABLE_SHIFT) | 150 | #define S2MPS14_ENABLE_SUSPEND (0x01 << S2MPS14_ENABLE_SHIFT) |
| 151 | /* On/Off controlled by LDO10EN or EMMCEN */ | ||
| 152 | #define S2MPS14_ENABLE_EXT_CONTROL (0x00 << S2MPS14_ENABLE_SHIFT) | ||
| 151 | #define S2MPS14_LDO_N_VOLTAGES (S2MPS14_LDO_VSEL_MASK + 1) | 153 | #define S2MPS14_LDO_N_VOLTAGES (S2MPS14_LDO_VSEL_MASK + 1) |
| 152 | #define S2MPS14_BUCK_N_VOLTAGES (S2MPS14_BUCK_VSEL_MASK + 1) | 154 | #define S2MPS14_BUCK_N_VOLTAGES (S2MPS14_BUCK_VSEL_MASK + 1) |
| 153 | 155 | ||
diff --git a/include/linux/mfd/tps65090.h b/include/linux/mfd/tps65090.h index 3f43069413e7..0bf2708df150 100644 --- a/include/linux/mfd/tps65090.h +++ b/include/linux/mfd/tps65090.h | |||
| @@ -64,6 +64,20 @@ enum { | |||
| 64 | TPS65090_REGULATOR_MAX, | 64 | TPS65090_REGULATOR_MAX, |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | /* Register addresses */ | ||
| 68 | #define TPS65090_REG_INTR_STS 0x00 | ||
| 69 | #define TPS65090_REG_INTR_STS2 0x01 | ||
| 70 | #define TPS65090_REG_INTR_MASK 0x02 | ||
| 71 | #define TPS65090_REG_INTR_MASK2 0x03 | ||
| 72 | #define TPS65090_REG_CG_CTRL0 0x04 | ||
| 73 | #define TPS65090_REG_CG_CTRL1 0x05 | ||
| 74 | #define TPS65090_REG_CG_CTRL2 0x06 | ||
| 75 | #define TPS65090_REG_CG_CTRL3 0x07 | ||
| 76 | #define TPS65090_REG_CG_CTRL4 0x08 | ||
| 77 | #define TPS65090_REG_CG_CTRL5 0x09 | ||
| 78 | #define TPS65090_REG_CG_STATUS1 0x0a | ||
| 79 | #define TPS65090_REG_CG_STATUS2 0x0b | ||
| 80 | |||
| 67 | struct tps65090 { | 81 | struct tps65090 { |
| 68 | struct device *dev; | 82 | struct device *dev; |
| 69 | struct regmap *rmap; | 83 | struct regmap *rmap; |
| @@ -78,11 +92,16 @@ struct tps65090 { | |||
| 78 | * DCDC1, DCDC2 and DCDC3. | 92 | * DCDC1, DCDC2 and DCDC3. |
| 79 | * @gpio: Gpio number if external control is enabled and controlled through | 93 | * @gpio: Gpio number if external control is enabled and controlled through |
| 80 | * gpio. | 94 | * gpio. |
| 95 | * @overcurrent_wait_valid: True if the overcurrent_wait should be applied. | ||
| 96 | * @overcurrent_wait: Value to set as the overcurrent wait time. This is the | ||
| 97 | * actual bitfield value, not a time in ms (valid value are 0 - 3). | ||
| 81 | */ | 98 | */ |
| 82 | struct tps65090_regulator_plat_data { | 99 | struct tps65090_regulator_plat_data { |
| 83 | struct regulator_init_data *reg_init_data; | 100 | struct regulator_init_data *reg_init_data; |
| 84 | bool enable_ext_control; | 101 | bool enable_ext_control; |
| 85 | int gpio; | 102 | int gpio; |
| 103 | bool overcurrent_wait_valid; | ||
| 104 | int overcurrent_wait; | ||
| 86 | }; | 105 | }; |
| 87 | 106 | ||
| 88 | struct tps65090_platform_data { | 107 | struct tps65090_platform_data { |
diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h index 54b5458ec084..95d6938737fd 100644 --- a/include/linux/mfd/tps65217.h +++ b/include/linux/mfd/tps65217.h | |||
| @@ -254,7 +254,6 @@ struct tps65217 { | |||
| 254 | struct tps65217_board *pdata; | 254 | struct tps65217_board *pdata; |
| 255 | unsigned long id; | 255 | unsigned long id; |
| 256 | struct regulator_desc desc[TPS65217_NUM_REGULATOR]; | 256 | struct regulator_desc desc[TPS65217_NUM_REGULATOR]; |
| 257 | struct regulator_dev *rdev[TPS65217_NUM_REGULATOR]; | ||
| 258 | struct regmap *regmap; | 257 | struct regmap *regmap; |
| 259 | }; | 258 | }; |
| 260 | 259 | ||
diff --git a/include/linux/mfd/tps6586x.h b/include/linux/mfd/tps6586x.h index cbecec2e353a..96187ed9f9bb 100644 --- a/include/linux/mfd/tps6586x.h +++ b/include/linux/mfd/tps6586x.h | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | #define TPS658621A 0x15 | 17 | #define TPS658621A 0x15 |
| 18 | #define TPS658621CD 0x2c | 18 | #define TPS658621CD 0x2c |
| 19 | #define TPS658623 0x1b | 19 | #define TPS658623 0x1b |
| 20 | #define TPS658640 0x01 | ||
| 21 | #define TPS658640v2 0x02 | ||
| 20 | #define TPS658643 0x03 | 22 | #define TPS658643 0x03 |
| 21 | 23 | ||
| 22 | enum { | 24 | enum { |
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 1a4a8c157b31..a2d9d81038d1 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h | |||
| @@ -151,11 +151,13 @@ int regulator_register_supply_alias(struct device *dev, const char *id, | |||
| 151 | const char *alias_id); | 151 | const char *alias_id); |
| 152 | void regulator_unregister_supply_alias(struct device *dev, const char *id); | 152 | void regulator_unregister_supply_alias(struct device *dev, const char *id); |
| 153 | 153 | ||
| 154 | int regulator_bulk_register_supply_alias(struct device *dev, const char **id, | 154 | int regulator_bulk_register_supply_alias(struct device *dev, |
| 155 | const char *const *id, | ||
| 155 | struct device *alias_dev, | 156 | struct device *alias_dev, |
| 156 | const char **alias_id, int num_id); | 157 | const char *const *alias_id, |
| 158 | int num_id); | ||
| 157 | void regulator_bulk_unregister_supply_alias(struct device *dev, | 159 | void regulator_bulk_unregister_supply_alias(struct device *dev, |
| 158 | const char **id, int num_id); | 160 | const char * const *id, int num_id); |
| 159 | 161 | ||
| 160 | int devm_regulator_register_supply_alias(struct device *dev, const char *id, | 162 | int devm_regulator_register_supply_alias(struct device *dev, const char *id, |
| 161 | struct device *alias_dev, | 163 | struct device *alias_dev, |
| @@ -164,12 +166,12 @@ void devm_regulator_unregister_supply_alias(struct device *dev, | |||
| 164 | const char *id); | 166 | const char *id); |
| 165 | 167 | ||
| 166 | int devm_regulator_bulk_register_supply_alias(struct device *dev, | 168 | int devm_regulator_bulk_register_supply_alias(struct device *dev, |
| 167 | const char **id, | 169 | const char *const *id, |
| 168 | struct device *alias_dev, | 170 | struct device *alias_dev, |
| 169 | const char **alias_id, | 171 | const char *const *alias_id, |
| 170 | int num_id); | 172 | int num_id); |
| 171 | void devm_regulator_bulk_unregister_supply_alias(struct device *dev, | 173 | void devm_regulator_bulk_unregister_supply_alias(struct device *dev, |
| 172 | const char **id, | 174 | const char *const *id, |
| 173 | int num_id); | 175 | int num_id); |
| 174 | 176 | ||
| 175 | /* regulator output control and status */ | 177 | /* regulator output control and status */ |
| @@ -290,17 +292,17 @@ static inline void regulator_unregister_supply_alias(struct device *dev, | |||
| 290 | } | 292 | } |
| 291 | 293 | ||
| 292 | static inline int regulator_bulk_register_supply_alias(struct device *dev, | 294 | static inline int regulator_bulk_register_supply_alias(struct device *dev, |
| 293 | const char **id, | 295 | const char *const *id, |
| 294 | struct device *alias_dev, | 296 | struct device *alias_dev, |
| 295 | const char **alias_id, | 297 | const char * const *alias_id, |
| 296 | int num_id) | 298 | int num_id) |
| 297 | { | 299 | { |
| 298 | return 0; | 300 | return 0; |
| 299 | } | 301 | } |
| 300 | 302 | ||
| 301 | static inline void regulator_bulk_unregister_supply_alias(struct device *dev, | 303 | static inline void regulator_bulk_unregister_supply_alias(struct device *dev, |
| 302 | const char **id, | 304 | const char * const *id, |
| 303 | int num_id) | 305 | int num_id) |
| 304 | { | 306 | { |
| 305 | } | 307 | } |
| 306 | 308 | ||
| @@ -317,15 +319,17 @@ static inline void devm_regulator_unregister_supply_alias(struct device *dev, | |||
| 317 | { | 319 | { |
| 318 | } | 320 | } |
| 319 | 321 | ||
| 320 | static inline int devm_regulator_bulk_register_supply_alias( | 322 | static inline int devm_regulator_bulk_register_supply_alias(struct device *dev, |
| 321 | struct device *dev, const char **id, struct device *alias_dev, | 323 | const char *const *id, |
| 322 | const char **alias_id, int num_id) | 324 | struct device *alias_dev, |
| 325 | const char *const *alias_id, | ||
| 326 | int num_id) | ||
| 323 | { | 327 | { |
| 324 | return 0; | 328 | return 0; |
| 325 | } | 329 | } |
| 326 | 330 | ||
| 327 | static inline void devm_regulator_bulk_unregister_supply_alias( | 331 | static inline void devm_regulator_bulk_unregister_supply_alias( |
| 328 | struct device *dev, const char **id, int num_id) | 332 | struct device *dev, const char *const *id, int num_id) |
| 329 | { | 333 | { |
| 330 | } | 334 | } |
| 331 | 335 | ||
| @@ -397,6 +401,12 @@ static inline int regulator_set_voltage(struct regulator *regulator, | |||
| 397 | return 0; | 401 | return 0; |
| 398 | } | 402 | } |
| 399 | 403 | ||
| 404 | static inline int regulator_set_voltage_time(struct regulator *regulator, | ||
| 405 | int old_uV, int new_uV) | ||
| 406 | { | ||
| 407 | return 0; | ||
| 408 | } | ||
| 409 | |||
| 400 | static inline int regulator_get_voltage(struct regulator *regulator) | 410 | static inline int regulator_get_voltage(struct regulator *regulator) |
| 401 | { | 411 | { |
| 402 | return -EINVAL; | 412 | return -EINVAL; |
