diff options
| -rw-r--r-- | Documentation/devicetree/bindings/mfd/bcm590xx.txt | 4 | ||||
| -rw-r--r-- | drivers/mfd/arizona-core.c | 41 | ||||
| -rw-r--r-- | drivers/mfd/bcm590xx.c | 60 | ||||
| -rw-r--r-- | drivers/mfd/tps65090.c | 41 | ||||
| -rw-r--r-- | drivers/power/tps65090-charger.c | 11 | ||||
| -rw-r--r-- | drivers/regulator/Kconfig | 7 | ||||
| -rw-r--r-- | drivers/regulator/Makefile | 1 | ||||
| -rw-r--r-- | drivers/regulator/arizona-ldo1.c | 58 | ||||
| -rw-r--r-- | drivers/regulator/arizona-micsupp.c | 38 | ||||
| -rw-r--r-- | drivers/regulator/axp20x-regulator.c | 286 | ||||
| -rw-r--r-- | drivers/regulator/bcm590xx-regulator.c | 92 | ||||
| -rw-r--r-- | include/linux/mfd/arizona/core.h | 3 | ||||
| -rw-r--r-- | include/linux/mfd/bcm590xx.h | 9 | ||||
| -rw-r--r-- | include/linux/mfd/tps65090.h | 14 |
14 files changed, 593 insertions, 72 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/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/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 903eb37f047a..65e5d7d1b35a 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 |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 12ef277a48b4..c14696b290c0 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 |
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/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/tps65090.h b/include/linux/mfd/tps65090.h index 3f43069413e7..45f0f9d2ed25 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; |
