diff options
| author | Mark Brown <broonie@kernel.org> | 2018-08-10 12:31:24 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2018-08-10 12:31:24 -0400 |
| commit | d22d59362b7b2c749245f1269d447011c76ca41d (patch) | |
| tree | b3fc0673f62394dc5ed417eac6bad485a28baf25 /drivers/regulator | |
| parent | a8afa92ec0d9312b23fd291aa8db95da266f2d5f (diff) | |
| parent | 46fc033eba42f5a4fb583b2ab53f0a9918468452 (diff) | |
Merge branch 'regulator-4.19' into regulator-next
Diffstat (limited to 'drivers/regulator')
| -rw-r--r-- | drivers/regulator/Kconfig | 25 | ||||
| -rw-r--r-- | drivers/regulator/Makefile | 4 | ||||
| -rw-r--r-- | drivers/regulator/bd71837-regulator.c | 44 | ||||
| -rw-r--r-- | drivers/regulator/bd9571mwv-regulator.c | 72 | ||||
| -rw-r--r-- | drivers/regulator/core.c | 44 | ||||
| -rw-r--r-- | drivers/regulator/cpcap-regulator.c | 103 | ||||
| -rw-r--r-- | drivers/regulator/max14577-regulator.c | 22 | ||||
| -rw-r--r-- | drivers/regulator/max77686-regulator.c | 32 | ||||
| -rw-r--r-- | drivers/regulator/max77693-regulator.c | 32 | ||||
| -rw-r--r-- | drivers/regulator/max77802-regulator.c | 34 | ||||
| -rw-r--r-- | drivers/regulator/max8997-regulator.c | 33 | ||||
| -rw-r--r-- | drivers/regulator/max8998.c | 28 | ||||
| -rw-r--r-- | drivers/regulator/pfuze100-regulator.c | 112 | ||||
| -rw-r--r-- | drivers/regulator/qcom-rpmh-regulator.c | 769 | ||||
| -rw-r--r-- | drivers/regulator/qcom_spmi-regulator.c | 38 | ||||
| -rw-r--r-- | drivers/regulator/s2mpa01.c | 14 | ||||
| -rw-r--r-- | drivers/regulator/s2mps11.c | 21 | ||||
| -rw-r--r-- | drivers/regulator/s5m8767.c | 16 | ||||
| -rw-r--r-- | drivers/regulator/tps65217-regulator.c | 2 | ||||
| -rw-r--r-- | drivers/regulator/uniphier-regulator.c | 213 |
20 files changed, 1411 insertions, 247 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 5dbccf5f3037..329cdd33ed62 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
| @@ -180,9 +180,9 @@ config REGULATOR_BCM590XX | |||
| 180 | BCM590xx PMUs. This will enable support for the software | 180 | BCM590xx PMUs. This will enable support for the software |
| 181 | controllable LDO/Switching regulators. | 181 | controllable LDO/Switching regulators. |
| 182 | 182 | ||
| 183 | config REGULATOR_BD71837 | 183 | config REGULATOR_BD718XX |
| 184 | tristate "ROHM BD71837 Power Regulator" | 184 | tristate "ROHM BD71837 Power Regulator" |
| 185 | depends on MFD_BD71837 | 185 | depends on MFD_ROHM_BD718XX |
| 186 | help | 186 | help |
| 187 | This driver supports voltage regulators on ROHM BD71837 PMIC. | 187 | This driver supports voltage regulators on ROHM BD71837 PMIC. |
| 188 | This will enable support for the software controllable buck | 188 | This will enable support for the software controllable buck |
| @@ -633,12 +633,12 @@ config REGULATOR_PCF50633 | |||
| 633 | on PCF50633 | 633 | on PCF50633 |
| 634 | 634 | ||
| 635 | config REGULATOR_PFUZE100 | 635 | config REGULATOR_PFUZE100 |
| 636 | tristate "Freescale PFUZE100/200/3000 regulator driver" | 636 | tristate "Freescale PFUZE100/200/3000/3001 regulator driver" |
| 637 | depends on I2C | 637 | depends on I2C |
| 638 | select REGMAP_I2C | 638 | select REGMAP_I2C |
| 639 | help | 639 | help |
| 640 | Say y here to support the regulators found on the Freescale | 640 | Say y here to support the regulators found on the Freescale |
| 641 | PFUZE100/200/3000 PMIC. | 641 | PFUZE100/200/3000/3001 PMIC. |
| 642 | 642 | ||
| 643 | config REGULATOR_PV88060 | 643 | config REGULATOR_PV88060 |
| 644 | tristate "Powerventure Semiconductor PV88060 regulator" | 644 | tristate "Powerventure Semiconductor PV88060 regulator" |
| @@ -682,6 +682,15 @@ config REGULATOR_QCOM_RPM | |||
| 682 | Qualcomm RPM as a module. The module will be named | 682 | Qualcomm RPM as a module. The module will be named |
| 683 | "qcom_rpm-regulator". | 683 | "qcom_rpm-regulator". |
| 684 | 684 | ||
| 685 | config REGULATOR_QCOM_RPMH | ||
| 686 | tristate "Qualcomm Technologies, Inc. RPMh regulator driver" | ||
| 687 | depends on QCOM_RPMH || COMPILE_TEST | ||
| 688 | help | ||
| 689 | This driver supports control of PMIC regulators via the RPMh hardware | ||
| 690 | block found on Qualcomm Technologies Inc. SoCs. RPMh regulator | ||
| 691 | control allows for voting on regulator state between multiple | ||
| 692 | processors within the SoC. | ||
| 693 | |||
| 685 | config REGULATOR_QCOM_SMD_RPM | 694 | config REGULATOR_QCOM_SMD_RPM |
| 686 | tristate "Qualcomm SMD based RPM regulator driver" | 695 | tristate "Qualcomm SMD based RPM regulator driver" |
| 687 | depends on QCOM_SMD_RPM | 696 | depends on QCOM_SMD_RPM |
| @@ -950,6 +959,14 @@ config REGULATOR_TWL4030 | |||
| 950 | This driver supports the voltage regulators provided by | 959 | This driver supports the voltage regulators provided by |
| 951 | this family of companion chips. | 960 | this family of companion chips. |
| 952 | 961 | ||
| 962 | config REGULATOR_UNIPHIER | ||
| 963 | tristate "UniPhier regulator driver" | ||
| 964 | depends on ARCH_UNIPHIER || COMPILE_TEST | ||
| 965 | depends on OF && MFD_SYSCON | ||
| 966 | default ARCH_UNIPHIER | ||
| 967 | help | ||
| 968 | Support for regulators implemented on Socionext UniPhier SoCs. | ||
| 969 | |||
| 953 | config REGULATOR_VCTRL | 970 | config REGULATOR_VCTRL |
| 954 | tristate "Voltage controlled regulators" | 971 | tristate "Voltage controlled regulators" |
| 955 | depends on OF | 972 | depends on OF |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index bd818ceb7c72..801d9a34a203 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
| @@ -27,7 +27,7 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o | |||
| 27 | obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o | 27 | obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o |
| 28 | obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o | 28 | obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o |
| 29 | obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o | 29 | obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o |
| 30 | obj-$(CONFIG_REGULATOR_BD71837) += bd71837-regulator.o | 30 | obj-$(CONFIG_REGULATOR_BD718XX) += bd71837-regulator.o |
| 31 | obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o | 31 | obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o |
| 32 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o | 32 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o |
| 33 | obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o | 33 | obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o |
| @@ -78,6 +78,7 @@ obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o | |||
| 78 | obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o | 78 | obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o |
| 79 | obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o | 79 | obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o |
| 80 | obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o | 80 | obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o |
| 81 | obj-$(CONFIG_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o | ||
| 81 | obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o | 82 | obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o |
| 82 | obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o | 83 | obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o |
| 83 | obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o | 84 | obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o |
| @@ -118,6 +119,7 @@ obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o | |||
| 118 | obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o | 119 | obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o |
| 119 | obj-$(CONFIG_REGULATOR_TPS65132) += tps65132-regulator.o | 120 | obj-$(CONFIG_REGULATOR_TPS65132) += tps65132-regulator.o |
| 120 | obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o twl6030-regulator.o | 121 | obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o twl6030-regulator.o |
| 122 | obj-$(CONFIG_REGULATOR_UNIPHIER) += uniphier-regulator.o | ||
| 121 | obj-$(CONFIG_REGULATOR_VCTRL) += vctrl-regulator.o | 123 | obj-$(CONFIG_REGULATOR_VCTRL) += vctrl-regulator.o |
| 122 | obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o | 124 | obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o |
| 123 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o | 125 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o |
diff --git a/drivers/regulator/bd71837-regulator.c b/drivers/regulator/bd71837-regulator.c index 6eae4d0432a2..0f8ac8dec3e1 100644 --- a/drivers/regulator/bd71837-regulator.c +++ b/drivers/regulator/bd71837-regulator.c | |||
| @@ -2,19 +2,18 @@ | |||
| 2 | // Copyright (C) 2018 ROHM Semiconductors | 2 | // Copyright (C) 2018 ROHM Semiconductors |
| 3 | // bd71837-regulator.c ROHM BD71837MWV regulator driver | 3 | // bd71837-regulator.c ROHM BD71837MWV regulator driver |
| 4 | 4 | ||
| 5 | #include <linux/kernel.h> | 5 | #include <linux/delay.h> |
| 6 | #include <linux/module.h> | ||
| 7 | #include <linux/init.h> | ||
| 8 | #include <linux/err.h> | 6 | #include <linux/err.h> |
| 7 | #include <linux/gpio.h> | ||
| 9 | #include <linux/interrupt.h> | 8 | #include <linux/interrupt.h> |
| 9 | #include <linux/kernel.h> | ||
| 10 | #include <linux/mfd/rohm-bd718x7.h> | ||
| 11 | #include <linux/module.h> | ||
| 10 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
| 11 | #include <linux/regulator/driver.h> | 13 | #include <linux/regulator/driver.h> |
| 12 | #include <linux/regulator/machine.h> | 14 | #include <linux/regulator/machine.h> |
| 13 | #include <linux/delay.h> | ||
| 14 | #include <linux/slab.h> | ||
| 15 | #include <linux/gpio.h> | ||
| 16 | #include <linux/mfd/bd71837.h> | ||
| 17 | #include <linux/regulator/of_regulator.h> | 15 | #include <linux/regulator/of_regulator.h> |
| 16 | #include <linux/slab.h> | ||
| 18 | 17 | ||
| 19 | struct bd71837_pmic { | 18 | struct bd71837_pmic { |
| 20 | struct regulator_desc descs[BD71837_REGULATOR_CNT]; | 19 | struct regulator_desc descs[BD71837_REGULATOR_CNT]; |
| @@ -39,7 +38,7 @@ static int bd71837_buck1234_set_ramp_delay(struct regulator_dev *rdev, | |||
| 39 | int id = rdev->desc->id; | 38 | int id = rdev->desc->id; |
| 40 | unsigned int ramp_value = BUCK_RAMPRATE_10P00MV; | 39 | unsigned int ramp_value = BUCK_RAMPRATE_10P00MV; |
| 41 | 40 | ||
| 42 | dev_dbg(&(pmic->pdev->dev), "Buck[%d] Set Ramp = %d\n", id + 1, | 41 | dev_dbg(&pmic->pdev->dev, "Buck[%d] Set Ramp = %d\n", id + 1, |
| 43 | ramp_delay); | 42 | ramp_delay); |
| 44 | switch (ramp_delay) { | 43 | switch (ramp_delay) { |
| 45 | case 1 ... 1250: | 44 | case 1 ... 1250: |
| @@ -73,14 +72,10 @@ static int bd71837_buck1234_set_ramp_delay(struct regulator_dev *rdev, | |||
| 73 | static int bd71837_set_voltage_sel_restricted(struct regulator_dev *rdev, | 72 | static int bd71837_set_voltage_sel_restricted(struct regulator_dev *rdev, |
| 74 | unsigned int sel) | 73 | unsigned int sel) |
| 75 | { | 74 | { |
| 76 | int ret; | 75 | if (regulator_is_enabled_regmap(rdev)) |
| 77 | 76 | return -EBUSY; | |
| 78 | ret = regulator_is_enabled_regmap(rdev); | 77 | |
| 79 | if (!ret) | 78 | return regulator_set_voltage_sel_regmap(rdev, sel); |
| 80 | ret = regulator_set_voltage_sel_regmap(rdev, sel); | ||
| 81 | else if (ret == 1) | ||
| 82 | ret = -EBUSY; | ||
| 83 | return ret; | ||
| 84 | } | 79 | } |
| 85 | 80 | ||
| 86 | static struct regulator_ops bd71837_ldo_regulator_ops = { | 81 | static struct regulator_ops bd71837_ldo_regulator_ops = { |
| @@ -195,7 +190,7 @@ static const struct regulator_linear_range bd71837_ldo1_voltage_ranges[] = { | |||
| 195 | * LDO2 | 190 | * LDO2 |
| 196 | * 0.8 or 0.9V | 191 | * 0.8 or 0.9V |
| 197 | */ | 192 | */ |
| 198 | const unsigned int ldo_2_volts[] = { | 193 | static const unsigned int ldo_2_volts[] = { |
| 199 | 900000, 800000 | 194 | 900000, 800000 |
| 200 | }; | 195 | }; |
| 201 | 196 | ||
| @@ -495,7 +490,6 @@ struct reg_init { | |||
| 495 | static int bd71837_probe(struct platform_device *pdev) | 490 | static int bd71837_probe(struct platform_device *pdev) |
| 496 | { | 491 | { |
| 497 | struct bd71837_pmic *pmic; | 492 | struct bd71837_pmic *pmic; |
| 498 | struct bd71837_board *pdata; | ||
| 499 | struct regulator_config config = { 0 }; | 493 | struct regulator_config config = { 0 }; |
| 500 | struct reg_init pmic_regulator_inits[] = { | 494 | struct reg_init pmic_regulator_inits[] = { |
| 501 | { | 495 | { |
| @@ -548,8 +542,7 @@ static int bd71837_probe(struct platform_device *pdev) | |||
| 548 | 542 | ||
| 549 | int i, err; | 543 | int i, err; |
| 550 | 544 | ||
| 551 | pmic = devm_kzalloc(&pdev->dev, sizeof(struct bd71837_pmic), | 545 | pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); |
| 552 | GFP_KERNEL); | ||
| 553 | if (!pmic) | 546 | if (!pmic) |
| 554 | return -ENOMEM; | 547 | return -ENOMEM; |
| 555 | 548 | ||
| @@ -564,7 +557,6 @@ static int bd71837_probe(struct platform_device *pdev) | |||
| 564 | goto err; | 557 | goto err; |
| 565 | } | 558 | } |
| 566 | platform_set_drvdata(pdev, pmic); | 559 | platform_set_drvdata(pdev, pmic); |
| 567 | pdata = dev_get_platdata(pmic->mfd->dev); | ||
| 568 | 560 | ||
| 569 | /* Register LOCK release */ | 561 | /* Register LOCK release */ |
| 570 | err = regmap_update_bits(pmic->mfd->regmap, BD71837_REG_REGLOCK, | 562 | err = regmap_update_bits(pmic->mfd->regmap, BD71837_REG_REGLOCK, |
| @@ -573,8 +565,8 @@ static int bd71837_probe(struct platform_device *pdev) | |||
| 573 | dev_err(&pmic->pdev->dev, "Failed to unlock PMIC (%d)\n", err); | 565 | dev_err(&pmic->pdev->dev, "Failed to unlock PMIC (%d)\n", err); |
| 574 | goto err; | 566 | goto err; |
| 575 | } else { | 567 | } else { |
| 576 | dev_dbg(&pmic->pdev->dev, "%s: Unlocked lock register 0x%x\n", | 568 | dev_dbg(&pmic->pdev->dev, "Unlocked lock register 0x%x\n", |
| 577 | __func__, BD71837_REG_REGLOCK); | 569 | BD71837_REG_REGLOCK); |
| 578 | } | 570 | } |
| 579 | 571 | ||
| 580 | for (i = 0; i < ARRAY_SIZE(pmic_regulator_inits); i++) { | 572 | for (i = 0; i < ARRAY_SIZE(pmic_regulator_inits); i++) { |
| @@ -584,9 +576,6 @@ static int bd71837_probe(struct platform_device *pdev) | |||
| 584 | 576 | ||
| 585 | desc = &pmic->descs[i]; | 577 | desc = &pmic->descs[i]; |
| 586 | 578 | ||
| 587 | if (pdata) | ||
| 588 | config.init_data = pdata->init_data[i]; | ||
| 589 | |||
| 590 | config.dev = pdev->dev.parent; | 579 | config.dev = pdev->dev.parent; |
| 591 | config.driver_data = pmic; | 580 | config.driver_data = pmic; |
| 592 | config.regmap = pmic->mfd->regmap; | 581 | config.regmap = pmic->mfd->regmap; |
| @@ -619,8 +608,6 @@ static int bd71837_probe(struct platform_device *pdev) | |||
| 619 | pmic->rdev[i] = rdev; | 608 | pmic->rdev[i] = rdev; |
| 620 | } | 609 | } |
| 621 | 610 | ||
| 622 | return 0; | ||
| 623 | |||
| 624 | err: | 611 | err: |
| 625 | return err; | 612 | return err; |
| 626 | } | 613 | } |
| @@ -628,7 +615,6 @@ err: | |||
| 628 | static struct platform_driver bd71837_regulator = { | 615 | static struct platform_driver bd71837_regulator = { |
| 629 | .driver = { | 616 | .driver = { |
| 630 | .name = "bd71837-pmic", | 617 | .name = "bd71837-pmic", |
| 631 | .owner = THIS_MODULE, | ||
| 632 | }, | 618 | }, |
| 633 | .probe = bd71837_probe, | 619 | .probe = bd71837_probe, |
| 634 | }; | 620 | }; |
diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c index be574eb444eb..274c5ed7cd73 100644 --- a/drivers/regulator/bd9571mwv-regulator.c +++ b/drivers/regulator/bd9571mwv-regulator.c | |||
| @@ -30,6 +30,7 @@ struct bd9571mwv_reg { | |||
| 30 | /* DDR Backup Power */ | 30 | /* DDR Backup Power */ |
| 31 | u8 bkup_mode_cnt_keepon; /* from "rohm,ddr-backup-power" */ | 31 | u8 bkup_mode_cnt_keepon; /* from "rohm,ddr-backup-power" */ |
| 32 | u8 bkup_mode_cnt_saved; | 32 | u8 bkup_mode_cnt_saved; |
| 33 | bool bkup_mode_enabled; | ||
| 33 | 34 | ||
| 34 | /* Power switch type */ | 35 | /* Power switch type */ |
| 35 | bool rstbmode_level; | 36 | bool rstbmode_level; |
| @@ -171,13 +172,60 @@ static int bd9571mwv_bkup_mode_write(struct bd9571mwv *bd, unsigned int mode) | |||
| 171 | return 0; | 172 | return 0; |
| 172 | } | 173 | } |
| 173 | 174 | ||
| 175 | static ssize_t backup_mode_show(struct device *dev, | ||
| 176 | struct device_attribute *attr, char *buf) | ||
| 177 | { | ||
| 178 | struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev); | ||
| 179 | |||
| 180 | return sprintf(buf, "%s\n", bdreg->bkup_mode_enabled ? "on" : "off"); | ||
| 181 | } | ||
| 182 | |||
| 183 | static ssize_t backup_mode_store(struct device *dev, | ||
| 184 | struct device_attribute *attr, | ||
| 185 | const char *buf, size_t count) | ||
| 186 | { | ||
| 187 | struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev); | ||
| 188 | unsigned int mode; | ||
| 189 | int ret; | ||
| 190 | |||
| 191 | if (!count) | ||
| 192 | return 0; | ||
| 193 | |||
| 194 | ret = kstrtobool(buf, &bdreg->bkup_mode_enabled); | ||
| 195 | if (ret) | ||
| 196 | return ret; | ||
| 197 | |||
| 198 | if (!bdreg->rstbmode_level) | ||
| 199 | return count; | ||
| 200 | |||
| 201 | /* | ||
| 202 | * Configure DDR Backup Mode, to change the role of the accessory power | ||
| 203 | * switch from a power switch to a wake-up switch, or vice versa | ||
| 204 | */ | ||
| 205 | ret = bd9571mwv_bkup_mode_read(bdreg->bd, &mode); | ||
| 206 | if (ret) | ||
| 207 | return ret; | ||
| 208 | |||
| 209 | mode &= ~BD9571MWV_BKUP_MODE_CNT_KEEPON_MASK; | ||
| 210 | if (bdreg->bkup_mode_enabled) | ||
| 211 | mode |= bdreg->bkup_mode_cnt_keepon; | ||
| 212 | |||
| 213 | ret = bd9571mwv_bkup_mode_write(bdreg->bd, mode); | ||
| 214 | if (ret) | ||
| 215 | return ret; | ||
| 216 | |||
| 217 | return count; | ||
| 218 | } | ||
| 219 | |||
| 220 | static DEVICE_ATTR_RW(backup_mode); | ||
| 221 | |||
| 174 | static int bd9571mwv_suspend(struct device *dev) | 222 | static int bd9571mwv_suspend(struct device *dev) |
| 175 | { | 223 | { |
| 176 | struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev); | 224 | struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev); |
| 177 | unsigned int mode; | 225 | unsigned int mode; |
| 178 | int ret; | 226 | int ret; |
| 179 | 227 | ||
| 180 | if (!device_may_wakeup(dev)) | 228 | if (!bdreg->bkup_mode_enabled) |
| 181 | return 0; | 229 | return 0; |
| 182 | 230 | ||
| 183 | /* Save DDR Backup Mode */ | 231 | /* Save DDR Backup Mode */ |
| @@ -204,7 +252,7 @@ static int bd9571mwv_resume(struct device *dev) | |||
| 204 | { | 252 | { |
| 205 | struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev); | 253 | struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev); |
| 206 | 254 | ||
| 207 | if (!device_may_wakeup(dev)) | 255 | if (!bdreg->bkup_mode_enabled) |
| 208 | return 0; | 256 | return 0; |
| 209 | 257 | ||
| 210 | /* Restore DDR Backup Mode */ | 258 | /* Restore DDR Backup Mode */ |
| @@ -215,9 +263,15 @@ static const struct dev_pm_ops bd9571mwv_pm = { | |||
| 215 | SET_SYSTEM_SLEEP_PM_OPS(bd9571mwv_suspend, bd9571mwv_resume) | 263 | SET_SYSTEM_SLEEP_PM_OPS(bd9571mwv_suspend, bd9571mwv_resume) |
| 216 | }; | 264 | }; |
| 217 | 265 | ||
| 266 | static int bd9571mwv_regulator_remove(struct platform_device *pdev) | ||
| 267 | { | ||
| 268 | device_remove_file(&pdev->dev, &dev_attr_backup_mode); | ||
| 269 | return 0; | ||
| 270 | } | ||
| 218 | #define DEV_PM_OPS &bd9571mwv_pm | 271 | #define DEV_PM_OPS &bd9571mwv_pm |
| 219 | #else | 272 | #else |
| 220 | #define DEV_PM_OPS NULL | 273 | #define DEV_PM_OPS NULL |
| 274 | #define bd9571mwv_regulator_remove NULL | ||
| 221 | #endif /* CONFIG_PM_SLEEP */ | 275 | #endif /* CONFIG_PM_SLEEP */ |
| 222 | 276 | ||
| 223 | static int bd9571mwv_regulator_probe(struct platform_device *pdev) | 277 | static int bd9571mwv_regulator_probe(struct platform_device *pdev) |
| @@ -270,14 +324,21 @@ static int bd9571mwv_regulator_probe(struct platform_device *pdev) | |||
| 270 | return -EINVAL; | 324 | return -EINVAL; |
| 271 | } | 325 | } |
| 272 | 326 | ||
| 327 | #ifdef CONFIG_PM_SLEEP | ||
| 273 | if (bdreg->bkup_mode_cnt_keepon) { | 328 | if (bdreg->bkup_mode_cnt_keepon) { |
| 274 | device_set_wakeup_capable(&pdev->dev, true); | 329 | int ret; |
| 330 | |||
| 275 | /* | 331 | /* |
| 276 | * Wakeup is enabled by default in pulse mode, but needs | 332 | * Backup mode is enabled by default in pulse mode, but needs |
| 277 | * explicit user setup in level mode. | 333 | * explicit user setup in level mode. |
| 278 | */ | 334 | */ |
| 279 | device_set_wakeup_enable(&pdev->dev, bdreg->rstbmode_pulse); | 335 | bdreg->bkup_mode_enabled = bdreg->rstbmode_pulse; |
| 336 | |||
| 337 | ret = device_create_file(&pdev->dev, &dev_attr_backup_mode); | ||
| 338 | if (ret) | ||
| 339 | return ret; | ||
| 280 | } | 340 | } |
| 341 | #endif /* CONFIG_PM_SLEEP */ | ||
| 281 | 342 | ||
| 282 | return 0; | 343 | return 0; |
| 283 | } | 344 | } |
| @@ -294,6 +355,7 @@ static struct platform_driver bd9571mwv_regulator_driver = { | |||
| 294 | .pm = DEV_PM_OPS, | 355 | .pm = DEV_PM_OPS, |
| 295 | }, | 356 | }, |
| 296 | .probe = bd9571mwv_regulator_probe, | 357 | .probe = bd9571mwv_regulator_probe, |
| 358 | .remove = bd9571mwv_regulator_remove, | ||
| 297 | .id_table = bd9571mwv_regulator_id_table, | 359 | .id_table = bd9571mwv_regulator_id_table, |
| 298 | }; | 360 | }; |
| 299 | module_platform_driver(bd9571mwv_regulator_driver); | 361 | module_platform_driver(bd9571mwv_regulator_driver); |
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 6ed568b96c0e..bb1324f93143 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
| @@ -1740,6 +1740,8 @@ struct regulator *_regulator_get(struct device *dev, const char *id, | |||
| 1740 | rdev->use_count = 0; | 1740 | rdev->use_count = 0; |
| 1741 | } | 1741 | } |
| 1742 | 1742 | ||
| 1743 | device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS); | ||
| 1744 | |||
| 1743 | return regulator; | 1745 | return regulator; |
| 1744 | } | 1746 | } |
| 1745 | 1747 | ||
| @@ -1829,9 +1831,21 @@ static void _regulator_put(struct regulator *regulator) | |||
| 1829 | 1831 | ||
| 1830 | debugfs_remove_recursive(regulator->debugfs); | 1832 | debugfs_remove_recursive(regulator->debugfs); |
| 1831 | 1833 | ||
| 1832 | /* remove any sysfs entries */ | 1834 | if (regulator->dev) { |
| 1833 | if (regulator->dev) | 1835 | int count = 0; |
| 1836 | struct regulator *r; | ||
| 1837 | |||
| 1838 | list_for_each_entry(r, &rdev->consumer_list, list) | ||
| 1839 | if (r->dev == regulator->dev) | ||
| 1840 | count++; | ||
| 1841 | |||
| 1842 | if (count == 1) | ||
| 1843 | device_link_remove(regulator->dev, &rdev->dev); | ||
| 1844 | |||
| 1845 | /* remove any sysfs entries */ | ||
| 1834 | sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); | 1846 | sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); |
| 1847 | } | ||
| 1848 | |||
| 1835 | regulator_lock(rdev); | 1849 | regulator_lock(rdev); |
| 1836 | list_del(®ulator->list); | 1850 | list_del(®ulator->list); |
| 1837 | 1851 | ||
| @@ -4441,7 +4455,7 @@ void regulator_unregister(struct regulator_dev *rdev) | |||
| 4441 | EXPORT_SYMBOL_GPL(regulator_unregister); | 4455 | EXPORT_SYMBOL_GPL(regulator_unregister); |
| 4442 | 4456 | ||
| 4443 | #ifdef CONFIG_SUSPEND | 4457 | #ifdef CONFIG_SUSPEND |
| 4444 | static int _regulator_suspend_late(struct device *dev, void *data) | 4458 | static int _regulator_suspend(struct device *dev, void *data) |
| 4445 | { | 4459 | { |
| 4446 | struct regulator_dev *rdev = dev_to_rdev(dev); | 4460 | struct regulator_dev *rdev = dev_to_rdev(dev); |
| 4447 | suspend_state_t *state = data; | 4461 | suspend_state_t *state = data; |
| @@ -4455,20 +4469,20 @@ static int _regulator_suspend_late(struct device *dev, void *data) | |||
| 4455 | } | 4469 | } |
| 4456 | 4470 | ||
| 4457 | /** | 4471 | /** |
| 4458 | * regulator_suspend_late - prepare regulators for system wide suspend | 4472 | * regulator_suspend - prepare regulators for system wide suspend |
| 4459 | * @state: system suspend state | 4473 | * @state: system suspend state |
| 4460 | * | 4474 | * |
| 4461 | * Configure each regulator with it's suspend operating parameters for state. | 4475 | * Configure each regulator with it's suspend operating parameters for state. |
| 4462 | */ | 4476 | */ |
| 4463 | static int regulator_suspend_late(struct device *dev) | 4477 | static int regulator_suspend(struct device *dev) |
| 4464 | { | 4478 | { |
| 4465 | suspend_state_t state = pm_suspend_target_state; | 4479 | suspend_state_t state = pm_suspend_target_state; |
| 4466 | 4480 | ||
| 4467 | return class_for_each_device(®ulator_class, NULL, &state, | 4481 | return class_for_each_device(®ulator_class, NULL, &state, |
| 4468 | _regulator_suspend_late); | 4482 | _regulator_suspend); |
| 4469 | } | 4483 | } |
| 4470 | 4484 | ||
| 4471 | static int _regulator_resume_early(struct device *dev, void *data) | 4485 | static int _regulator_resume(struct device *dev, void *data) |
| 4472 | { | 4486 | { |
| 4473 | int ret = 0; | 4487 | int ret = 0; |
| 4474 | struct regulator_dev *rdev = dev_to_rdev(dev); | 4488 | struct regulator_dev *rdev = dev_to_rdev(dev); |
| @@ -4481,35 +4495,35 @@ static int _regulator_resume_early(struct device *dev, void *data) | |||
| 4481 | 4495 | ||
| 4482 | regulator_lock(rdev); | 4496 | regulator_lock(rdev); |
| 4483 | 4497 | ||
| 4484 | if (rdev->desc->ops->resume_early && | 4498 | if (rdev->desc->ops->resume && |
| 4485 | (rstate->enabled == ENABLE_IN_SUSPEND || | 4499 | (rstate->enabled == ENABLE_IN_SUSPEND || |
| 4486 | rstate->enabled == DISABLE_IN_SUSPEND)) | 4500 | rstate->enabled == DISABLE_IN_SUSPEND)) |
| 4487 | ret = rdev->desc->ops->resume_early(rdev); | 4501 | ret = rdev->desc->ops->resume(rdev); |
| 4488 | 4502 | ||
| 4489 | regulator_unlock(rdev); | 4503 | regulator_unlock(rdev); |
| 4490 | 4504 | ||
| 4491 | return ret; | 4505 | return ret; |
| 4492 | } | 4506 | } |
| 4493 | 4507 | ||
| 4494 | static int regulator_resume_early(struct device *dev) | 4508 | static int regulator_resume(struct device *dev) |
| 4495 | { | 4509 | { |
| 4496 | suspend_state_t state = pm_suspend_target_state; | 4510 | suspend_state_t state = pm_suspend_target_state; |
| 4497 | 4511 | ||
| 4498 | return class_for_each_device(®ulator_class, NULL, &state, | 4512 | return class_for_each_device(®ulator_class, NULL, &state, |
| 4499 | _regulator_resume_early); | 4513 | _regulator_resume); |
| 4500 | } | 4514 | } |
| 4501 | 4515 | ||
| 4502 | #else /* !CONFIG_SUSPEND */ | 4516 | #else /* !CONFIG_SUSPEND */ |
| 4503 | 4517 | ||
| 4504 | #define regulator_suspend_late NULL | 4518 | #define regulator_suspend NULL |
| 4505 | #define regulator_resume_early NULL | 4519 | #define regulator_resume NULL |
| 4506 | 4520 | ||
| 4507 | #endif /* !CONFIG_SUSPEND */ | 4521 | #endif /* !CONFIG_SUSPEND */ |
| 4508 | 4522 | ||
| 4509 | #ifdef CONFIG_PM | 4523 | #ifdef CONFIG_PM |
| 4510 | static const struct dev_pm_ops __maybe_unused regulator_pm_ops = { | 4524 | static const struct dev_pm_ops __maybe_unused regulator_pm_ops = { |
| 4511 | .suspend_late = regulator_suspend_late, | 4525 | .suspend = regulator_suspend, |
| 4512 | .resume_early = regulator_resume_early, | 4526 | .resume = regulator_resume, |
| 4513 | }; | 4527 | }; |
| 4514 | #endif | 4528 | #endif |
| 4515 | 4529 | ||
diff --git a/drivers/regulator/cpcap-regulator.c b/drivers/regulator/cpcap-regulator.c index bd910fe123d9..2131457937b7 100644 --- a/drivers/regulator/cpcap-regulator.c +++ b/drivers/regulator/cpcap-regulator.c | |||
| @@ -271,6 +271,29 @@ static struct regulator_ops cpcap_regulator_ops = { | |||
| 271 | }; | 271 | }; |
| 272 | 272 | ||
| 273 | static const unsigned int unknown_val_tbl[] = { 0, }; | 273 | static const unsigned int unknown_val_tbl[] = { 0, }; |
| 274 | static const unsigned int sw2_sw4_val_tbl[] = { 612500, 625000, 637500, | ||
| 275 | 650000, 662500, 675000, | ||
| 276 | 687500, 700000, 712500, | ||
| 277 | 725000, 737500, 750000, | ||
| 278 | 762500, 775000, 787500, | ||
| 279 | 800000, 812500, 825000, | ||
| 280 | 837500, 850000, 862500, | ||
| 281 | 875000, 887500, 900000, | ||
| 282 | 912500, 925000, 937500, | ||
| 283 | 950000, 962500, 975000, | ||
| 284 | 987500, 1000000, 1012500, | ||
| 285 | 1025000, 1037500, 1050000, | ||
| 286 | 1062500, 1075000, 1087500, | ||
| 287 | 1100000, 1112500, 1125000, | ||
| 288 | 1137500, 1150000, 1162500, | ||
| 289 | 1175000, 1187500, 1200000, | ||
| 290 | 1212500, 1225000, 1237500, | ||
| 291 | 1250000, 1262500, 1275000, | ||
| 292 | 1287500, 1300000, 1312500, | ||
| 293 | 1325000, 1337500, 1350000, | ||
| 294 | 1362500, 1375000, 1387500, | ||
| 295 | 1400000, 1412500, 1425000, | ||
| 296 | 1437500, 1450000, 1462500, }; | ||
| 274 | static const unsigned int sw5_val_tbl[] = { 0, 5050000, }; | 297 | static const unsigned int sw5_val_tbl[] = { 0, 5050000, }; |
| 275 | static const unsigned int vcam_val_tbl[] = { 2600000, 2700000, 2800000, | 298 | static const unsigned int vcam_val_tbl[] = { 2600000, 2700000, 2800000, |
| 276 | 2900000, }; | 299 | 2900000, }; |
| @@ -389,6 +412,82 @@ static struct cpcap_regulator omap4_regulators[] = { | |||
| 389 | { /* sentinel */ }, | 412 | { /* sentinel */ }, |
| 390 | }; | 413 | }; |
| 391 | 414 | ||
| 415 | static struct cpcap_regulator xoom_regulators[] = { | ||
| 416 | CPCAP_REG(SW1, CPCAP_REG_S1C1, CPCAP_REG_ASSIGN2, | ||
| 417 | CPCAP_BIT_SW1_SEL, unknown_val_tbl, | ||
| 418 | 0, 0, 0, 0, 0, 0), | ||
| 419 | CPCAP_REG(SW2, CPCAP_REG_S2C1, CPCAP_REG_ASSIGN2, | ||
| 420 | CPCAP_BIT_SW2_SEL, sw2_sw4_val_tbl, | ||
| 421 | 0xf00, 0x7f, 0, 0x800, 0, 120), | ||
| 422 | CPCAP_REG(SW3, CPCAP_REG_S3C, CPCAP_REG_ASSIGN2, | ||
| 423 | CPCAP_BIT_SW3_SEL, unknown_val_tbl, | ||
| 424 | 0, 0, 0, 0, 0, 0), | ||
| 425 | CPCAP_REG(SW4, CPCAP_REG_S4C1, CPCAP_REG_ASSIGN2, | ||
| 426 | CPCAP_BIT_SW4_SEL, sw2_sw4_val_tbl, | ||
| 427 | 0xf00, 0x7f, 0, 0x900, 0, 100), | ||
| 428 | CPCAP_REG(SW5, CPCAP_REG_S5C, CPCAP_REG_ASSIGN2, | ||
| 429 | CPCAP_BIT_SW5_SEL, sw5_val_tbl, | ||
| 430 | 0x2a, 0, 0, 0x22, 0, 0), | ||
| 431 | CPCAP_REG(SW6, CPCAP_REG_S6C, CPCAP_REG_ASSIGN2, | ||
| 432 | CPCAP_BIT_SW6_SEL, unknown_val_tbl, | ||
| 433 | 0, 0, 0, 0, 0, 0), | ||
| 434 | CPCAP_REG(VCAM, CPCAP_REG_VCAMC, CPCAP_REG_ASSIGN2, | ||
| 435 | CPCAP_BIT_VCAM_SEL, vcam_val_tbl, | ||
| 436 | 0x87, 0x30, 4, 0x7, 0, 420), | ||
| 437 | CPCAP_REG(VCSI, CPCAP_REG_VCSIC, CPCAP_REG_ASSIGN3, | ||
| 438 | CPCAP_BIT_VCSI_SEL, vcsi_val_tbl, | ||
| 439 | 0x47, 0x10, 4, 0x7, 0, 350), | ||
| 440 | CPCAP_REG(VDAC, CPCAP_REG_VDACC, CPCAP_REG_ASSIGN3, | ||
| 441 | CPCAP_BIT_VDAC_SEL, vdac_val_tbl, | ||
| 442 | 0x87, 0x30, 4, 0x3, 0, 420), | ||
| 443 | CPCAP_REG(VDIG, CPCAP_REG_VDIGC, CPCAP_REG_ASSIGN2, | ||
| 444 | CPCAP_BIT_VDIG_SEL, vdig_val_tbl, | ||
| 445 | 0x87, 0x30, 4, 0x5, 0, 420), | ||
| 446 | CPCAP_REG(VFUSE, CPCAP_REG_VFUSEC, CPCAP_REG_ASSIGN3, | ||
| 447 | CPCAP_BIT_VFUSE_SEL, vfuse_val_tbl, | ||
| 448 | 0x80, 0xf, 0, 0x80, 0, 420), | ||
| 449 | CPCAP_REG(VHVIO, CPCAP_REG_VHVIOC, CPCAP_REG_ASSIGN3, | ||
| 450 | CPCAP_BIT_VHVIO_SEL, vhvio_val_tbl, | ||
| 451 | 0x17, 0, 0, 0x2, 0, 0), | ||
| 452 | CPCAP_REG(VSDIO, CPCAP_REG_VSDIOC, CPCAP_REG_ASSIGN2, | ||
| 453 | CPCAP_BIT_VSDIO_SEL, vsdio_val_tbl, | ||
| 454 | 0x87, 0x38, 3, 0x2, 0, 420), | ||
| 455 | CPCAP_REG(VPLL, CPCAP_REG_VPLLC, CPCAP_REG_ASSIGN3, | ||
| 456 | CPCAP_BIT_VPLL_SEL, vpll_val_tbl, | ||
| 457 | 0x43, 0x18, 3, 0x1, 0, 420), | ||
| 458 | CPCAP_REG(VRF1, CPCAP_REG_VRF1C, CPCAP_REG_ASSIGN3, | ||
| 459 | CPCAP_BIT_VRF1_SEL, vrf1_val_tbl, | ||
| 460 | 0xac, 0x2, 1, 0xc, 0, 10), | ||
| 461 | CPCAP_REG(VRF2, CPCAP_REG_VRF2C, CPCAP_REG_ASSIGN3, | ||
| 462 | CPCAP_BIT_VRF2_SEL, vrf2_val_tbl, | ||
| 463 | 0x23, 0x8, 3, 0x3, 0, 10), | ||
| 464 | CPCAP_REG(VRFREF, CPCAP_REG_VRFREFC, CPCAP_REG_ASSIGN3, | ||
| 465 | CPCAP_BIT_VRFREF_SEL, vrfref_val_tbl, | ||
| 466 | 0x23, 0x8, 3, 0x3, 0, 420), | ||
| 467 | CPCAP_REG(VWLAN1, CPCAP_REG_VWLAN1C, CPCAP_REG_ASSIGN3, | ||
| 468 | CPCAP_BIT_VWLAN1_SEL, vwlan1_val_tbl, | ||
| 469 | 0x47, 0x10, 4, 0x5, 0, 420), | ||
| 470 | CPCAP_REG(VWLAN2, CPCAP_REG_VWLAN2C, CPCAP_REG_ASSIGN3, | ||
| 471 | CPCAP_BIT_VWLAN2_SEL, vwlan2_val_tbl, | ||
| 472 | 0x20c, 0xc0, 6, 0x8, 0, 420), | ||
| 473 | CPCAP_REG(VSIM, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3, | ||
| 474 | 0xffff, vsim_val_tbl, | ||
| 475 | 0x23, 0x8, 3, 0x3, 0, 420), | ||
| 476 | CPCAP_REG(VSIMCARD, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3, | ||
| 477 | 0xffff, vsimcard_val_tbl, | ||
| 478 | 0x1e80, 0x8, 3, 0x1e00, 0, 420), | ||
| 479 | CPCAP_REG(VVIB, CPCAP_REG_VVIBC, CPCAP_REG_ASSIGN3, | ||
| 480 | CPCAP_BIT_VVIB_SEL, vvib_val_tbl, | ||
| 481 | 0x1, 0xc, 2, 0, 0x1, 500), | ||
| 482 | CPCAP_REG(VUSB, CPCAP_REG_VUSBC, CPCAP_REG_ASSIGN3, | ||
| 483 | CPCAP_BIT_VUSB_SEL, vusb_val_tbl, | ||
| 484 | 0x11c, 0x40, 6, 0xc, 0, 0), | ||
| 485 | CPCAP_REG(VAUDIO, CPCAP_REG_VAUDIOC, CPCAP_REG_ASSIGN4, | ||
| 486 | CPCAP_BIT_VAUDIO_SEL, vaudio_val_tbl, | ||
| 487 | 0x16, 0x1, 0, 0x4, 0, 0), | ||
| 488 | { /* sentinel */ }, | ||
| 489 | }; | ||
| 490 | |||
| 392 | static const struct of_device_id cpcap_regulator_id_table[] = { | 491 | static const struct of_device_id cpcap_regulator_id_table[] = { |
| 393 | { | 492 | { |
| 394 | .compatible = "motorola,cpcap-regulator", | 493 | .compatible = "motorola,cpcap-regulator", |
| @@ -397,6 +496,10 @@ static const struct of_device_id cpcap_regulator_id_table[] = { | |||
| 397 | .compatible = "motorola,mapphone-cpcap-regulator", | 496 | .compatible = "motorola,mapphone-cpcap-regulator", |
| 398 | .data = omap4_regulators, | 497 | .data = omap4_regulators, |
| 399 | }, | 498 | }, |
| 499 | { | ||
| 500 | .compatible = "motorola,xoom-cpcap-regulator", | ||
| 501 | .data = xoom_regulators, | ||
| 502 | }, | ||
| 400 | {}, | 503 | {}, |
| 401 | }; | 504 | }; |
| 402 | MODULE_DEVICE_TABLE(of, cpcap_regulator_id_table); | 505 | MODULE_DEVICE_TABLE(of, cpcap_regulator_id_table); |
diff --git a/drivers/regulator/max14577-regulator.c b/drivers/regulator/max14577-regulator.c index 0db288ce319c..bc7f4751bf9c 100644 --- a/drivers/regulator/max14577-regulator.c +++ b/drivers/regulator/max14577-regulator.c | |||
| @@ -1,19 +1,9 @@ | |||
| 1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | * max14577.c - Regulator driver for the Maxim 14577/77836 | 2 | // |
| 3 | * | 3 | // max14577.c - Regulator driver for the Maxim 14577/77836 |
| 4 | * Copyright (C) 2013,2014 Samsung Electronics | 4 | // |
| 5 | * Krzysztof Kozlowski <krzk@kernel.org> | 5 | // Copyright (C) 2013,2014 Samsung Electronics |
| 6 | * | 6 | // Krzysztof Kozlowski <krzk@kernel.org> |
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | */ | ||
| 17 | 7 | ||
| 18 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 19 | #include <linux/platform_device.h> | 9 | #include <linux/platform_device.h> |
diff --git a/drivers/regulator/max77686-regulator.c b/drivers/regulator/max77686-regulator.c index c301f3733475..bee060937f56 100644 --- a/drivers/regulator/max77686-regulator.c +++ b/drivers/regulator/max77686-regulator.c | |||
| @@ -1,26 +1,12 @@ | |||
| 1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | * max77686.c - Regulator driver for the Maxim 77686 | 2 | // |
| 3 | * | 3 | // max77686.c - Regulator driver for the Maxim 77686 |
| 4 | * Copyright (C) 2012 Samsung Electronics | 4 | // |
| 5 | * Chiwoong Byun <woong.byun@samsung.com> | 5 | // Copyright (C) 2012 Samsung Electronics |
| 6 | * Jonghwa Lee <jonghwa3.lee@samsung.com> | 6 | // Chiwoong Byun <woong.byun@samsung.com> |
| 7 | * | 7 | // Jonghwa Lee <jonghwa3.lee@samsung.com> |
| 8 | * This program is free software; you can redistribute it and/or modify | 8 | // |
| 9 | * it under the terms of the GNU General Public License as published by | 9 | // This driver is based on max8997.c |
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 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 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | * | ||
| 22 | * This driver is based on max8997.c | ||
| 23 | */ | ||
| 24 | 10 | ||
| 25 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| 26 | #include <linux/bug.h> | 12 | #include <linux/bug.h> |
diff --git a/drivers/regulator/max77693-regulator.c b/drivers/regulator/max77693-regulator.c index e7000e777292..077ecbbfdf76 100644 --- a/drivers/regulator/max77693-regulator.c +++ b/drivers/regulator/max77693-regulator.c | |||
| @@ -1,26 +1,12 @@ | |||
| 1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | * max77693.c - Regulator driver for the Maxim 77693 and 77843 | 2 | // |
| 3 | * | 3 | // max77693.c - Regulator driver for the Maxim 77693 and 77843 |
| 4 | * Copyright (C) 2013-2015 Samsung Electronics | 4 | // |
| 5 | * Jonghwa Lee <jonghwa3.lee@samsung.com> | 5 | // Copyright (C) 2013-2015 Samsung Electronics |
| 6 | * Krzysztof Kozlowski <krzk@kernel.org> | 6 | // Jonghwa Lee <jonghwa3.lee@samsung.com> |
| 7 | * | 7 | // Krzysztof Kozlowski <krzk@kernel.org> |
| 8 | * This program is free software; you can redistribute it and/or modify | 8 | // |
| 9 | * it under the terms of the GNU General Public License as published by | 9 | // This driver is based on max77686.c |
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 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 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | * | ||
| 22 | * This driver is based on max77686.c | ||
| 23 | */ | ||
| 24 | 10 | ||
| 25 | #include <linux/err.h> | 11 | #include <linux/err.h> |
| 26 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
diff --git a/drivers/regulator/max77802-regulator.c b/drivers/regulator/max77802-regulator.c index b6261903818c..c30cf5c9f2de 100644 --- a/drivers/regulator/max77802-regulator.c +++ b/drivers/regulator/max77802-regulator.c | |||
| @@ -1,25 +1,15 @@ | |||
| 1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | * max77802.c - Regulator driver for the Maxim 77802 | 2 | // |
| 3 | * | 3 | // max77802.c - Regulator driver for the Maxim 77802 |
| 4 | * Copyright (C) 2013-2014 Google, Inc | 4 | // |
| 5 | * Simon Glass <sjg@chromium.org> | 5 | // Copyright (C) 2013-2014 Google, Inc |
| 6 | * | 6 | // Simon Glass <sjg@chromium.org> |
| 7 | * Copyright (C) 2012 Samsung Electronics | 7 | // |
| 8 | * Chiwoong Byun <woong.byun@samsung.com> | 8 | // Copyright (C) 2012 Samsung Electronics |
| 9 | * Jonghwa Lee <jonghwa3.lee@samsung.com> | 9 | // Chiwoong Byun <woong.byun@samsung.com> |
| 10 | * | 10 | // Jonghwa Lee <jonghwa3.lee@samsung.com> |
| 11 | * This program is free software; you can redistribute it and/or modify | 11 | // |
| 12 | * it under the terms of the GNU General Public License as published by | 12 | // This driver is based on max8997.c |
| 13 | * the Free Software Foundation; either version 2 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * This driver is based on max8997.c | ||
| 22 | */ | ||
| 23 | 13 | ||
| 24 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 25 | #include <linux/bug.h> | 15 | #include <linux/bug.h> |
diff --git a/drivers/regulator/max8997-regulator.c b/drivers/regulator/max8997-regulator.c index a8ea30ee18a6..ad0c806b0737 100644 --- a/drivers/regulator/max8997-regulator.c +++ b/drivers/regulator/max8997-regulator.c | |||
| @@ -1,25 +1,11 @@ | |||
| 1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | * max8997.c - Regulator driver for the Maxim 8997/8966 | 2 | // |
| 3 | * | 3 | // max8997.c - Regulator driver for the Maxim 8997/8966 |
| 4 | * Copyright (C) 2011 Samsung Electronics | 4 | // |
| 5 | * MyungJoo Ham <myungjoo.ham@samsung.com> | 5 | // Copyright (C) 2011 Samsung Electronics |
| 6 | * | 6 | // MyungJoo Ham <myungjoo.ham@samsung.com> |
| 7 | * This program is free software; you can redistribute it and/or modify | 7 | // |
| 8 | * it under the terms of the GNU General Public License as published by | 8 | // This driver is based on max8998.c |
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | * | ||
| 21 | * This driver is based on max8998.c | ||
| 22 | */ | ||
| 23 | 9 | ||
| 24 | #include <linux/bug.h> | 10 | #include <linux/bug.h> |
| 25 | #include <linux/err.h> | 11 | #include <linux/err.h> |
| @@ -165,8 +151,7 @@ static int max8997_list_voltage(struct regulator_dev *rdev, | |||
| 165 | int rid = rdev_get_id(rdev); | 151 | int rid = rdev_get_id(rdev); |
| 166 | int val; | 152 | int val; |
| 167 | 153 | ||
| 168 | if (rid >= ARRAY_SIZE(reg_voltage_map) || | 154 | if (rid < 0 || rid >= ARRAY_SIZE(reg_voltage_map)) |
| 169 | rid < 0) | ||
| 170 | return -EINVAL; | 155 | return -EINVAL; |
| 171 | 156 | ||
| 172 | desc = reg_voltage_map[rid]; | 157 | desc = reg_voltage_map[rid]; |
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 6b9f262ebbb0..271bb736f3f5 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c | |||
| @@ -1,24 +1,10 @@ | |||
| 1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | * max8998.c - Voltage regulator driver for the Maxim 8998 | 2 | // |
| 3 | * | 3 | // max8998.c - Voltage regulator driver for the Maxim 8998 |
| 4 | * Copyright (C) 2009-2010 Samsung Electronics | 4 | // |
| 5 | * Kyungmin Park <kyungmin.park@samsung.com> | 5 | // Copyright (C) 2009-2010 Samsung Electronics |
| 6 | * Marek Szyprowski <m.szyprowski@samsung.com> | 6 | // Kyungmin Park <kyungmin.park@samsung.com> |
| 7 | * | 7 | // Marek Szyprowski <m.szyprowski@samsung.com> |
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 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 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | */ | ||
| 22 | 8 | ||
| 23 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 24 | #include <linux/init.h> | 10 | #include <linux/init.h> |
diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 8d9dbcc775ea..31c3a236120a 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/regmap.h> | 18 | #include <linux/regmap.h> |
| 19 | 19 | ||
| 20 | #define PFUZE_FLAG_DISABLE_SW BIT(1) | ||
| 21 | |||
| 20 | #define PFUZE_NUMREGS 128 | 22 | #define PFUZE_NUMREGS 128 |
| 21 | #define PFUZE100_VOL_OFFSET 0 | 23 | #define PFUZE100_VOL_OFFSET 0 |
| 22 | #define PFUZE100_STANDBY_OFFSET 1 | 24 | #define PFUZE100_STANDBY_OFFSET 1 |
| @@ -44,16 +46,18 @@ | |||
| 44 | #define PFUZE100_VGEN5VOL 0x70 | 46 | #define PFUZE100_VGEN5VOL 0x70 |
| 45 | #define PFUZE100_VGEN6VOL 0x71 | 47 | #define PFUZE100_VGEN6VOL 0x71 |
| 46 | 48 | ||
| 47 | enum chips { PFUZE100, PFUZE200, PFUZE3000 = 3 }; | 49 | enum chips { PFUZE100, PFUZE200, PFUZE3000 = 3, PFUZE3001 = 0x31, }; |
| 48 | 50 | ||
| 49 | struct pfuze_regulator { | 51 | struct pfuze_regulator { |
| 50 | struct regulator_desc desc; | 52 | struct regulator_desc desc; |
| 51 | unsigned char stby_reg; | 53 | unsigned char stby_reg; |
| 52 | unsigned char stby_mask; | 54 | unsigned char stby_mask; |
| 55 | bool sw_reg; | ||
| 53 | }; | 56 | }; |
| 54 | 57 | ||
| 55 | struct pfuze_chip { | 58 | struct pfuze_chip { |
| 56 | int chip_id; | 59 | int chip_id; |
| 60 | int flags; | ||
| 57 | struct regmap *regmap; | 61 | struct regmap *regmap; |
| 58 | struct device *dev; | 62 | struct device *dev; |
| 59 | struct pfuze_regulator regulator_descs[PFUZE100_MAX_REGULATOR]; | 63 | struct pfuze_regulator regulator_descs[PFUZE100_MAX_REGULATOR]; |
| @@ -92,6 +96,7 @@ static const struct i2c_device_id pfuze_device_id[] = { | |||
| 92 | {.name = "pfuze100", .driver_data = PFUZE100}, | 96 | {.name = "pfuze100", .driver_data = PFUZE100}, |
| 93 | {.name = "pfuze200", .driver_data = PFUZE200}, | 97 | {.name = "pfuze200", .driver_data = PFUZE200}, |
| 94 | {.name = "pfuze3000", .driver_data = PFUZE3000}, | 98 | {.name = "pfuze3000", .driver_data = PFUZE3000}, |
| 99 | {.name = "pfuze3001", .driver_data = PFUZE3001}, | ||
| 95 | { } | 100 | { } |
| 96 | }; | 101 | }; |
| 97 | MODULE_DEVICE_TABLE(i2c, pfuze_device_id); | 102 | MODULE_DEVICE_TABLE(i2c, pfuze_device_id); |
| @@ -100,6 +105,7 @@ static const struct of_device_id pfuze_dt_ids[] = { | |||
| 100 | { .compatible = "fsl,pfuze100", .data = (void *)PFUZE100}, | 105 | { .compatible = "fsl,pfuze100", .data = (void *)PFUZE100}, |
| 101 | { .compatible = "fsl,pfuze200", .data = (void *)PFUZE200}, | 106 | { .compatible = "fsl,pfuze200", .data = (void *)PFUZE200}, |
| 102 | { .compatible = "fsl,pfuze3000", .data = (void *)PFUZE3000}, | 107 | { .compatible = "fsl,pfuze3000", .data = (void *)PFUZE3000}, |
| 108 | { .compatible = "fsl,pfuze3001", .data = (void *)PFUZE3001}, | ||
| 103 | { } | 109 | { } |
| 104 | }; | 110 | }; |
| 105 | MODULE_DEVICE_TABLE(of, pfuze_dt_ids); | 111 | MODULE_DEVICE_TABLE(of, pfuze_dt_ids); |
| @@ -108,10 +114,28 @@ static int pfuze100_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) | |||
| 108 | { | 114 | { |
| 109 | struct pfuze_chip *pfuze100 = rdev_get_drvdata(rdev); | 115 | struct pfuze_chip *pfuze100 = rdev_get_drvdata(rdev); |
| 110 | int id = rdev_get_id(rdev); | 116 | int id = rdev_get_id(rdev); |
| 117 | bool reg_has_ramp_delay; | ||
| 111 | unsigned int ramp_bits; | 118 | unsigned int ramp_bits; |
| 112 | int ret; | 119 | int ret; |
| 113 | 120 | ||
| 114 | if (id < PFUZE100_SWBST) { | 121 | switch (pfuze100->chip_id) { |
| 122 | case PFUZE3001: | ||
| 123 | /* no dynamic voltage scaling for PF3001 */ | ||
| 124 | reg_has_ramp_delay = false; | ||
| 125 | break; | ||
| 126 | case PFUZE3000: | ||
| 127 | reg_has_ramp_delay = (id < PFUZE3000_SWBST); | ||
| 128 | break; | ||
| 129 | case PFUZE200: | ||
| 130 | reg_has_ramp_delay = (id < PFUZE200_SWBST); | ||
| 131 | break; | ||
| 132 | case PFUZE100: | ||
| 133 | default: | ||
| 134 | reg_has_ramp_delay = (id < PFUZE100_SWBST); | ||
| 135 | break; | ||
| 136 | } | ||
| 137 | |||
| 138 | if (reg_has_ramp_delay) { | ||
| 115 | ramp_delay = 12500 / ramp_delay; | 139 | ramp_delay = 12500 / ramp_delay; |
| 116 | ramp_bits = (ramp_delay >> 1) - (ramp_delay >> 3); | 140 | ramp_bits = (ramp_delay >> 1) - (ramp_delay >> 3); |
| 117 | ret = regmap_update_bits(pfuze100->regmap, | 141 | ret = regmap_update_bits(pfuze100->regmap, |
| @@ -119,8 +143,9 @@ static int pfuze100_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) | |||
| 119 | 0xc0, ramp_bits << 6); | 143 | 0xc0, ramp_bits << 6); |
| 120 | if (ret < 0) | 144 | if (ret < 0) |
| 121 | dev_err(pfuze100->dev, "ramp failed, err %d\n", ret); | 145 | dev_err(pfuze100->dev, "ramp failed, err %d\n", ret); |
| 122 | } else | 146 | } else { |
| 123 | ret = -EACCES; | 147 | ret = -EACCES; |
| 148 | } | ||
| 124 | 149 | ||
| 125 | return ret; | 150 | return ret; |
| 126 | } | 151 | } |
| @@ -142,6 +167,14 @@ static const struct regulator_ops pfuze100_fixed_regulator_ops = { | |||
| 142 | }; | 167 | }; |
| 143 | 168 | ||
| 144 | static const struct regulator_ops pfuze100_sw_regulator_ops = { | 169 | static const struct regulator_ops pfuze100_sw_regulator_ops = { |
| 170 | .list_voltage = regulator_list_voltage_linear, | ||
| 171 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
| 172 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
| 173 | .set_voltage_time_sel = regulator_set_voltage_time_sel, | ||
| 174 | .set_ramp_delay = pfuze100_set_ramp_delay, | ||
| 175 | }; | ||
| 176 | |||
| 177 | static const struct regulator_ops pfuze100_sw_disable_regulator_ops = { | ||
| 145 | .enable = regulator_enable_regmap, | 178 | .enable = regulator_enable_regmap, |
| 146 | .disable = regulator_disable_regmap, | 179 | .disable = regulator_disable_regmap, |
| 147 | .is_enabled = regulator_is_enabled_regmap, | 180 | .is_enabled = regulator_is_enabled_regmap, |
| @@ -192,13 +225,11 @@ static const struct regulator_ops pfuze100_swb_regulator_ops = { | |||
| 192 | .vsel_reg = (base) + PFUZE100_VOL_OFFSET, \ | 225 | .vsel_reg = (base) + PFUZE100_VOL_OFFSET, \ |
| 193 | .vsel_mask = 0x3f, \ | 226 | .vsel_mask = 0x3f, \ |
| 194 | .enable_reg = (base) + PFUZE100_MODE_OFFSET, \ | 227 | .enable_reg = (base) + PFUZE100_MODE_OFFSET, \ |
| 195 | .enable_val = 0xc, \ | ||
| 196 | .disable_val = 0x0, \ | ||
| 197 | .enable_mask = 0xf, \ | 228 | .enable_mask = 0xf, \ |
| 198 | .enable_time = 500, \ | ||
| 199 | }, \ | 229 | }, \ |
| 200 | .stby_reg = (base) + PFUZE100_STANDBY_OFFSET, \ | 230 | .stby_reg = (base) + PFUZE100_STANDBY_OFFSET, \ |
| 201 | .stby_mask = 0x3f, \ | 231 | .stby_mask = 0x3f, \ |
| 232 | .sw_reg = true, \ | ||
| 202 | } | 233 | } |
| 203 | 234 | ||
| 204 | #define PFUZE100_SWB_REG(_chip, _name, base, mask, voltages) \ | 235 | #define PFUZE100_SWB_REG(_chip, _name, base, mask, voltages) \ |
| @@ -361,6 +392,19 @@ static struct pfuze_regulator pfuze3000_regulators[] = { | |||
| 361 | PFUZE100_VGEN_REG(PFUZE3000, VLDO4, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000), | 392 | PFUZE100_VGEN_REG(PFUZE3000, VLDO4, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000), |
| 362 | }; | 393 | }; |
| 363 | 394 | ||
| 395 | static struct pfuze_regulator pfuze3001_regulators[] = { | ||
| 396 | PFUZE100_SWB_REG(PFUZE3001, SW1, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a), | ||
| 397 | PFUZE100_SWB_REG(PFUZE3001, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo), | ||
| 398 | PFUZE3000_SW3_REG(PFUZE3001, SW3, PFUZE100_SW3AVOL, 900000, 1650000, 50000), | ||
| 399 | PFUZE100_SWB_REG(PFUZE3001, VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs), | ||
| 400 | PFUZE100_VGEN_REG(PFUZE3001, VLDO1, PFUZE100_VGEN1VOL, 1800000, 3300000, 100000), | ||
| 401 | PFUZE100_VGEN_REG(PFUZE3001, VLDO2, PFUZE100_VGEN2VOL, 800000, 1550000, 50000), | ||
| 402 | PFUZE3000_VCC_REG(PFUZE3001, VCCSD, PFUZE100_VGEN3VOL, 2850000, 3300000, 150000), | ||
| 403 | PFUZE3000_VCC_REG(PFUZE3001, V33, PFUZE100_VGEN4VOL, 2850000, 3300000, 150000), | ||
| 404 | PFUZE100_VGEN_REG(PFUZE3001, VLDO3, PFUZE100_VGEN5VOL, 1800000, 3300000, 100000), | ||
| 405 | PFUZE100_VGEN_REG(PFUZE3001, VLDO4, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000), | ||
| 406 | }; | ||
| 407 | |||
| 364 | #ifdef CONFIG_OF | 408 | #ifdef CONFIG_OF |
| 365 | /* PFUZE100 */ | 409 | /* PFUZE100 */ |
| 366 | static struct of_regulator_match pfuze100_matches[] = { | 410 | static struct of_regulator_match pfuze100_matches[] = { |
| @@ -418,6 +462,21 @@ static struct of_regulator_match pfuze3000_matches[] = { | |||
| 418 | { .name = "vldo4", }, | 462 | { .name = "vldo4", }, |
| 419 | }; | 463 | }; |
| 420 | 464 | ||
| 465 | /* PFUZE3001 */ | ||
| 466 | static struct of_regulator_match pfuze3001_matches[] = { | ||
| 467 | |||
| 468 | { .name = "sw1", }, | ||
| 469 | { .name = "sw2", }, | ||
| 470 | { .name = "sw3", }, | ||
| 471 | { .name = "vsnvs", }, | ||
| 472 | { .name = "vldo1", }, | ||
| 473 | { .name = "vldo2", }, | ||
| 474 | { .name = "vccsd", }, | ||
| 475 | { .name = "v33", }, | ||
| 476 | { .name = "vldo3", }, | ||
| 477 | { .name = "vldo4", }, | ||
| 478 | }; | ||
| 479 | |||
| 421 | static struct of_regulator_match *pfuze_matches; | 480 | static struct of_regulator_match *pfuze_matches; |
| 422 | 481 | ||
| 423 | static int pfuze_parse_regulators_dt(struct pfuze_chip *chip) | 482 | static int pfuze_parse_regulators_dt(struct pfuze_chip *chip) |
| @@ -430,6 +489,9 @@ static int pfuze_parse_regulators_dt(struct pfuze_chip *chip) | |||
| 430 | if (!np) | 489 | if (!np) |
| 431 | return -EINVAL; | 490 | return -EINVAL; |
| 432 | 491 | ||
| 492 | if (of_property_read_bool(np, "fsl,pfuze-support-disable-sw")) | ||
| 493 | chip->flags |= PFUZE_FLAG_DISABLE_SW; | ||
| 494 | |||
| 433 | parent = of_get_child_by_name(np, "regulators"); | 495 | parent = of_get_child_by_name(np, "regulators"); |
| 434 | if (!parent) { | 496 | if (!parent) { |
| 435 | dev_err(dev, "regulators node not found\n"); | 497 | dev_err(dev, "regulators node not found\n"); |
| @@ -437,6 +499,11 @@ static int pfuze_parse_regulators_dt(struct pfuze_chip *chip) | |||
| 437 | } | 499 | } |
| 438 | 500 | ||
| 439 | switch (chip->chip_id) { | 501 | switch (chip->chip_id) { |
| 502 | case PFUZE3001: | ||
| 503 | pfuze_matches = pfuze3001_matches; | ||
| 504 | ret = of_regulator_match(dev, parent, pfuze3001_matches, | ||
| 505 | ARRAY_SIZE(pfuze3001_matches)); | ||
| 506 | break; | ||
| 440 | case PFUZE3000: | 507 | case PFUZE3000: |
| 441 | pfuze_matches = pfuze3000_matches; | 508 | pfuze_matches = pfuze3000_matches; |
| 442 | ret = of_regulator_match(dev, parent, pfuze3000_matches, | 509 | ret = of_regulator_match(dev, parent, pfuze3000_matches, |
| @@ -508,7 +575,8 @@ static int pfuze_identify(struct pfuze_chip *pfuze_chip) | |||
| 508 | */ | 575 | */ |
| 509 | dev_info(pfuze_chip->dev, "Assuming misprogrammed ID=0x8"); | 576 | dev_info(pfuze_chip->dev, "Assuming misprogrammed ID=0x8"); |
| 510 | } else if ((value & 0x0f) != pfuze_chip->chip_id && | 577 | } else if ((value & 0x0f) != pfuze_chip->chip_id && |
| 511 | (value & 0xf0) >> 4 != pfuze_chip->chip_id) { | 578 | (value & 0xf0) >> 4 != pfuze_chip->chip_id && |
| 579 | (value != pfuze_chip->chip_id)) { | ||
| 512 | /* device id NOT match with your setting */ | 580 | /* device id NOT match with your setting */ |
| 513 | dev_warn(pfuze_chip->dev, "Illegal ID: %x\n", value); | 581 | dev_warn(pfuze_chip->dev, "Illegal ID: %x\n", value); |
| 514 | return -ENODEV; | 582 | return -ENODEV; |
| @@ -588,6 +656,13 @@ static int pfuze100_regulator_probe(struct i2c_client *client, | |||
| 588 | 656 | ||
| 589 | /* use the right regulators after identify the right device */ | 657 | /* use the right regulators after identify the right device */ |
| 590 | switch (pfuze_chip->chip_id) { | 658 | switch (pfuze_chip->chip_id) { |
| 659 | case PFUZE3001: | ||
| 660 | pfuze_chip->pfuze_regulators = pfuze3001_regulators; | ||
| 661 | regulator_num = ARRAY_SIZE(pfuze3001_regulators); | ||
| 662 | sw_check_start = PFUZE3001_SW2; | ||
| 663 | sw_check_end = PFUZE3001_SW2; | ||
| 664 | sw_hi = 1 << 3; | ||
| 665 | break; | ||
| 591 | case PFUZE3000: | 666 | case PFUZE3000: |
| 592 | pfuze_chip->pfuze_regulators = pfuze3000_regulators; | 667 | pfuze_chip->pfuze_regulators = pfuze3000_regulators; |
| 593 | regulator_num = ARRAY_SIZE(pfuze3000_regulators); | 668 | regulator_num = ARRAY_SIZE(pfuze3000_regulators); |
| @@ -611,7 +686,8 @@ static int pfuze100_regulator_probe(struct i2c_client *client, | |||
| 611 | } | 686 | } |
| 612 | dev_info(&client->dev, "pfuze%s found.\n", | 687 | dev_info(&client->dev, "pfuze%s found.\n", |
| 613 | (pfuze_chip->chip_id == PFUZE100) ? "100" : | 688 | (pfuze_chip->chip_id == PFUZE100) ? "100" : |
| 614 | ((pfuze_chip->chip_id == PFUZE200) ? "200" : "3000")); | 689 | (((pfuze_chip->chip_id == PFUZE200) ? "200" : |
| 690 | ((pfuze_chip->chip_id == PFUZE3000) ? "3000" : "3001")))); | ||
| 615 | 691 | ||
| 616 | memcpy(pfuze_chip->regulator_descs, pfuze_chip->pfuze_regulators, | 692 | memcpy(pfuze_chip->regulator_descs, pfuze_chip->pfuze_regulators, |
| 617 | sizeof(pfuze_chip->regulator_descs)); | 693 | sizeof(pfuze_chip->regulator_descs)); |
| @@ -636,7 +712,8 @@ static int pfuze100_regulator_probe(struct i2c_client *client, | |||
| 636 | if (i >= sw_check_start && i <= sw_check_end) { | 712 | if (i >= sw_check_start && i <= sw_check_end) { |
| 637 | regmap_read(pfuze_chip->regmap, desc->vsel_reg, &val); | 713 | regmap_read(pfuze_chip->regmap, desc->vsel_reg, &val); |
| 638 | if (val & sw_hi) { | 714 | if (val & sw_hi) { |
| 639 | if (pfuze_chip->chip_id == PFUZE3000) { | 715 | if (pfuze_chip->chip_id == PFUZE3000 || |
| 716 | pfuze_chip->chip_id == PFUZE3001) { | ||
| 640 | desc->volt_table = pfuze3000_sw2hi; | 717 | desc->volt_table = pfuze3000_sw2hi; |
| 641 | desc->n_voltages = ARRAY_SIZE(pfuze3000_sw2hi); | 718 | desc->n_voltages = ARRAY_SIZE(pfuze3000_sw2hi); |
| 642 | } else { | 719 | } else { |
| @@ -647,6 +724,21 @@ static int pfuze100_regulator_probe(struct i2c_client *client, | |||
| 647 | } | 724 | } |
| 648 | } | 725 | } |
| 649 | 726 | ||
| 727 | /* | ||
| 728 | * Allow SW regulators to turn off. Checking it trough a flag is | ||
| 729 | * a workaround to keep the backward compatibility with existing | ||
| 730 | * old dtb's which may relay on the fact that we didn't disable | ||
| 731 | * the switched regulator till yet. | ||
| 732 | */ | ||
| 733 | if (pfuze_chip->flags & PFUZE_FLAG_DISABLE_SW) { | ||
| 734 | if (pfuze_chip->regulator_descs[i].sw_reg) { | ||
| 735 | desc->ops = &pfuze100_sw_disable_regulator_ops; | ||
| 736 | desc->enable_val = 0x8; | ||
| 737 | desc->disable_val = 0x0; | ||
| 738 | desc->enable_time = 500; | ||
| 739 | } | ||
| 740 | } | ||
| 741 | |||
| 650 | config.dev = &client->dev; | 742 | config.dev = &client->dev; |
| 651 | config.init_data = init_data; | 743 | config.init_data = init_data; |
| 652 | config.driver_data = pfuze_chip; | 744 | config.driver_data = pfuze_chip; |
| @@ -675,5 +767,5 @@ static struct i2c_driver pfuze_driver = { | |||
| 675 | module_i2c_driver(pfuze_driver); | 767 | module_i2c_driver(pfuze_driver); |
| 676 | 768 | ||
| 677 | MODULE_AUTHOR("Robin Gong <b38343@freescale.com>"); | 769 | MODULE_AUTHOR("Robin Gong <b38343@freescale.com>"); |
| 678 | MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100/200/3000 PMIC"); | 770 | MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100/200/3000/3001 PMIC"); |
| 679 | MODULE_LICENSE("GPL v2"); | 771 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c new file mode 100644 index 000000000000..9f27daebd8c8 --- /dev/null +++ b/drivers/regulator/qcom-rpmh-regulator.c | |||
| @@ -0,0 +1,769 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | // Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
| 3 | |||
| 4 | #define pr_fmt(fmt) "%s: " fmt, __func__ | ||
| 5 | |||
| 6 | #include <linux/err.h> | ||
| 7 | #include <linux/kernel.h> | ||
| 8 | #include <linux/module.h> | ||
| 9 | #include <linux/of.h> | ||
| 10 | #include <linux/of_device.h> | ||
| 11 | #include <linux/platform_device.h> | ||
| 12 | #include <linux/slab.h> | ||
| 13 | #include <linux/string.h> | ||
| 14 | #include <linux/regulator/driver.h> | ||
| 15 | #include <linux/regulator/machine.h> | ||
| 16 | #include <linux/regulator/of_regulator.h> | ||
| 17 | |||
| 18 | #include <soc/qcom/cmd-db.h> | ||
| 19 | #include <soc/qcom/rpmh.h> | ||
| 20 | |||
| 21 | #include <dt-bindings/regulator/qcom,rpmh-regulator.h> | ||
| 22 | |||
| 23 | /** | ||
| 24 | * enum rpmh_regulator_type - supported RPMh accelerator types | ||
| 25 | * %VRM: RPMh VRM accelerator which supports voting on enable, voltage, | ||
| 26 | * and mode of LDO, SMPS, and BOB type PMIC regulators. | ||
| 27 | * %XOB: RPMh XOB accelerator which supports voting on the enable state | ||
| 28 | * of PMIC regulators. | ||
| 29 | */ | ||
| 30 | enum rpmh_regulator_type { | ||
| 31 | VRM, | ||
| 32 | XOB, | ||
| 33 | }; | ||
| 34 | |||
| 35 | #define RPMH_REGULATOR_REG_VRM_VOLTAGE 0x0 | ||
| 36 | #define RPMH_REGULATOR_REG_ENABLE 0x4 | ||
| 37 | #define RPMH_REGULATOR_REG_VRM_MODE 0x8 | ||
| 38 | |||
| 39 | #define PMIC4_LDO_MODE_RETENTION 4 | ||
| 40 | #define PMIC4_LDO_MODE_LPM 5 | ||
| 41 | #define PMIC4_LDO_MODE_HPM 7 | ||
| 42 | |||
| 43 | #define PMIC4_SMPS_MODE_RETENTION 4 | ||
| 44 | #define PMIC4_SMPS_MODE_PFM 5 | ||
| 45 | #define PMIC4_SMPS_MODE_AUTO 6 | ||
| 46 | #define PMIC4_SMPS_MODE_PWM 7 | ||
| 47 | |||
| 48 | #define PMIC4_BOB_MODE_PASS 0 | ||
| 49 | #define PMIC4_BOB_MODE_PFM 1 | ||
| 50 | #define PMIC4_BOB_MODE_AUTO 2 | ||
| 51 | #define PMIC4_BOB_MODE_PWM 3 | ||
| 52 | |||
| 53 | /** | ||
| 54 | * struct rpmh_vreg_hw_data - RPMh regulator hardware configurations | ||
| 55 | * @regulator_type: RPMh accelerator type used to manage this | ||
| 56 | * regulator | ||
| 57 | * @ops: Pointer to regulator ops callback structure | ||
| 58 | * @voltage_range: The single range of voltages supported by this | ||
| 59 | * PMIC regulator type | ||
| 60 | * @n_voltages: The number of unique voltage set points defined | ||
| 61 | * by voltage_range | ||
| 62 | * @hpm_min_load_uA: Minimum load current in microamps that requires | ||
| 63 | * high power mode (HPM) operation. This is used | ||
| 64 | * for LDO hardware type regulators only. | ||
| 65 | * @pmic_mode_map: Array indexed by regulator framework mode | ||
| 66 | * containing PMIC hardware modes. Must be large | ||
| 67 | * enough to index all framework modes supported | ||
| 68 | * by this regulator hardware type. | ||
| 69 | * @of_map_mode: Maps an RPMH_REGULATOR_MODE_* mode value defined | ||
| 70 | * in device tree to a regulator framework mode | ||
| 71 | */ | ||
| 72 | struct rpmh_vreg_hw_data { | ||
| 73 | enum rpmh_regulator_type regulator_type; | ||
| 74 | const struct regulator_ops *ops; | ||
| 75 | const struct regulator_linear_range voltage_range; | ||
| 76 | int n_voltages; | ||
| 77 | int hpm_min_load_uA; | ||
| 78 | const int *pmic_mode_map; | ||
| 79 | unsigned int (*of_map_mode)(unsigned int mode); | ||
| 80 | }; | ||
| 81 | |||
| 82 | /** | ||
| 83 | * struct rpmh_vreg - individual RPMh regulator data structure encapsulating a | ||
| 84 | * single regulator device | ||
| 85 | * @dev: Device pointer for the top-level PMIC RPMh | ||
| 86 | * regulator parent device. This is used as a | ||
| 87 | * handle in RPMh write requests. | ||
| 88 | * @addr: Base address of the regulator resource within | ||
| 89 | * an RPMh accelerator | ||
| 90 | * @rdesc: Regulator descriptor | ||
| 91 | * @hw_data: PMIC regulator configuration data for this RPMh | ||
| 92 | * regulator | ||
| 93 | * @always_wait_for_ack: Boolean flag indicating if a request must always | ||
| 94 | * wait for an ACK from RPMh before continuing even | ||
| 95 | * if it corresponds to a strictly lower power | ||
| 96 | * state (e.g. enabled --> disabled). | ||
| 97 | * @enabled: Flag indicating if the regulator is enabled or | ||
| 98 | * not | ||
| 99 | * @bypassed: Boolean indicating if the regulator is in | ||
| 100 | * bypass (pass-through) mode or not. This is | ||
| 101 | * only used by BOB rpmh-regulator resources. | ||
| 102 | * @voltage_selector: Selector used for get_voltage_sel() and | ||
| 103 | * set_voltage_sel() callbacks | ||
| 104 | * @mode: RPMh VRM regulator current framework mode | ||
| 105 | */ | ||
| 106 | struct rpmh_vreg { | ||
| 107 | struct device *dev; | ||
| 108 | u32 addr; | ||
| 109 | struct regulator_desc rdesc; | ||
| 110 | const struct rpmh_vreg_hw_data *hw_data; | ||
| 111 | bool always_wait_for_ack; | ||
| 112 | |||
| 113 | int enabled; | ||
| 114 | bool bypassed; | ||
| 115 | int voltage_selector; | ||
| 116 | unsigned int mode; | ||
| 117 | }; | ||
| 118 | |||
| 119 | /** | ||
| 120 | * struct rpmh_vreg_init_data - initialization data for an RPMh regulator | ||
| 121 | * @name: Name for the regulator which also corresponds | ||
| 122 | * to the device tree subnode name of the regulator | ||
| 123 | * @resource_name: RPMh regulator resource name format string. | ||
| 124 | * This must include exactly one field: '%s' which | ||
| 125 | * is filled at run-time with the PMIC ID provided | ||
| 126 | * by device tree property qcom,pmic-id. Example: | ||
| 127 | * "ldo%s1" for RPMh resource "ldoa1". | ||
| 128 | * @supply_name: Parent supply regulator name | ||
| 129 | * @hw_data: Configuration data for this PMIC regulator type | ||
| 130 | */ | ||
| 131 | struct rpmh_vreg_init_data { | ||
| 132 | const char *name; | ||
| 133 | const char *resource_name; | ||
| 134 | const char *supply_name; | ||
| 135 | const struct rpmh_vreg_hw_data *hw_data; | ||
| 136 | }; | ||
| 137 | |||
| 138 | /** | ||
| 139 | * rpmh_regulator_send_request() - send the request to RPMh | ||
| 140 | * @vreg: Pointer to the RPMh regulator | ||
| 141 | * @cmd: Pointer to the RPMh command to send | ||
| 142 | * @wait_for_ack: Boolean indicating if execution must wait until the | ||
| 143 | * request has been acknowledged as complete | ||
| 144 | * | ||
| 145 | * Return: 0 on success, errno on failure | ||
| 146 | */ | ||
| 147 | static int rpmh_regulator_send_request(struct rpmh_vreg *vreg, | ||
| 148 | struct tcs_cmd *cmd, bool wait_for_ack) | ||
| 149 | { | ||
| 150 | int ret; | ||
| 151 | |||
| 152 | if (wait_for_ack || vreg->always_wait_for_ack) | ||
| 153 | ret = rpmh_write(vreg->dev, RPMH_ACTIVE_ONLY_STATE, cmd, 1); | ||
| 154 | else | ||
| 155 | ret = rpmh_write_async(vreg->dev, RPMH_ACTIVE_ONLY_STATE, cmd, | ||
| 156 | 1); | ||
| 157 | |||
| 158 | return ret; | ||
| 159 | } | ||
| 160 | |||
| 161 | static int _rpmh_regulator_vrm_set_voltage_sel(struct regulator_dev *rdev, | ||
| 162 | unsigned int selector, bool wait_for_ack) | ||
| 163 | { | ||
| 164 | struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); | ||
| 165 | struct tcs_cmd cmd = { | ||
| 166 | .addr = vreg->addr + RPMH_REGULATOR_REG_VRM_VOLTAGE, | ||
| 167 | }; | ||
| 168 | int ret; | ||
| 169 | |||
| 170 | /* VRM voltage control register is set with voltage in millivolts. */ | ||
| 171 | cmd.data = DIV_ROUND_UP(regulator_list_voltage_linear_range(rdev, | ||
| 172 | selector), 1000); | ||
| 173 | |||
| 174 | ret = rpmh_regulator_send_request(vreg, &cmd, wait_for_ack); | ||
| 175 | if (!ret) | ||
| 176 | vreg->voltage_selector = selector; | ||
| 177 | |||
| 178 | return ret; | ||
| 179 | } | ||
| 180 | |||
| 181 | static int rpmh_regulator_vrm_set_voltage_sel(struct regulator_dev *rdev, | ||
| 182 | unsigned int selector) | ||
| 183 | { | ||
| 184 | struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); | ||
| 185 | |||
| 186 | if (vreg->enabled == -EINVAL) { | ||
| 187 | /* | ||
| 188 | * Cache the voltage and send it later when the regulator is | ||
| 189 | * enabled or disabled. | ||
| 190 | */ | ||
| 191 | vreg->voltage_selector = selector; | ||
| 192 | return 0; | ||
| 193 | } | ||
| 194 | |||
| 195 | return _rpmh_regulator_vrm_set_voltage_sel(rdev, selector, | ||
| 196 | selector > vreg->voltage_selector); | ||
| 197 | } | ||
| 198 | |||
| 199 | static int rpmh_regulator_vrm_get_voltage_sel(struct regulator_dev *rdev) | ||
| 200 | { | ||
| 201 | struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); | ||
| 202 | |||
| 203 | return vreg->voltage_selector; | ||
| 204 | } | ||
| 205 | |||
| 206 | static int rpmh_regulator_is_enabled(struct regulator_dev *rdev) | ||
| 207 | { | ||
| 208 | struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); | ||
| 209 | |||
| 210 | return vreg->enabled; | ||
| 211 | } | ||
| 212 | |||
| 213 | static int rpmh_regulator_set_enable_state(struct regulator_dev *rdev, | ||
| 214 | bool enable) | ||
| 215 | { | ||
| 216 | struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); | ||
| 217 | struct tcs_cmd cmd = { | ||
| 218 | .addr = vreg->addr + RPMH_REGULATOR_REG_ENABLE, | ||
| 219 | .data = enable, | ||
| 220 | }; | ||
| 221 | int ret; | ||
| 222 | |||
| 223 | if (vreg->enabled == -EINVAL && | ||
| 224 | vreg->voltage_selector != -ENOTRECOVERABLE) { | ||
| 225 | ret = _rpmh_regulator_vrm_set_voltage_sel(rdev, | ||
| 226 | vreg->voltage_selector, true); | ||
| 227 | if (ret < 0) | ||
| 228 | return ret; | ||
| 229 | } | ||
| 230 | |||
| 231 | ret = rpmh_regulator_send_request(vreg, &cmd, enable); | ||
| 232 | if (!ret) | ||
| 233 | vreg->enabled = enable; | ||
| 234 | |||
| 235 | return ret; | ||
| 236 | } | ||
| 237 | |||
| 238 | static int rpmh_regulator_enable(struct regulator_dev *rdev) | ||
| 239 | { | ||
| 240 | return rpmh_regulator_set_enable_state(rdev, true); | ||
| 241 | } | ||
| 242 | |||
| 243 | static int rpmh_regulator_disable(struct regulator_dev *rdev) | ||
| 244 | { | ||
| 245 | return rpmh_regulator_set_enable_state(rdev, false); | ||
| 246 | } | ||
| 247 | |||
| 248 | static int rpmh_regulator_vrm_set_mode_bypass(struct rpmh_vreg *vreg, | ||
| 249 | unsigned int mode, bool bypassed) | ||
| 250 | { | ||
| 251 | struct tcs_cmd cmd = { | ||
| 252 | .addr = vreg->addr + RPMH_REGULATOR_REG_VRM_MODE, | ||
| 253 | }; | ||
| 254 | int pmic_mode; | ||
| 255 | |||
| 256 | if (mode > REGULATOR_MODE_STANDBY) | ||
| 257 | return -EINVAL; | ||
| 258 | |||
| 259 | pmic_mode = vreg->hw_data->pmic_mode_map[mode]; | ||
| 260 | if (pmic_mode < 0) | ||
| 261 | return pmic_mode; | ||
| 262 | |||
| 263 | if (bypassed) | ||
| 264 | cmd.data = PMIC4_BOB_MODE_PASS; | ||
| 265 | else | ||
| 266 | cmd.data = pmic_mode; | ||
| 267 | |||
| 268 | return rpmh_regulator_send_request(vreg, &cmd, true); | ||
| 269 | } | ||
| 270 | |||
| 271 | static int rpmh_regulator_vrm_set_mode(struct regulator_dev *rdev, | ||
| 272 | unsigned int mode) | ||
| 273 | { | ||
| 274 | struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); | ||
| 275 | int ret; | ||
| 276 | |||
| 277 | if (mode == vreg->mode) | ||
| 278 | return 0; | ||
| 279 | |||
| 280 | ret = rpmh_regulator_vrm_set_mode_bypass(vreg, mode, vreg->bypassed); | ||
| 281 | if (!ret) | ||
| 282 | vreg->mode = mode; | ||
| 283 | |||
| 284 | return ret; | ||
| 285 | } | ||
| 286 | |||
| 287 | static unsigned int rpmh_regulator_vrm_get_mode(struct regulator_dev *rdev) | ||
| 288 | { | ||
| 289 | struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); | ||
| 290 | |||
| 291 | return vreg->mode; | ||
| 292 | } | ||
| 293 | |||
| 294 | /** | ||
| 295 | * rpmh_regulator_vrm_set_load() - set the regulator mode based upon the load | ||
| 296 | * current requested | ||
| 297 | * @rdev: Regulator device pointer for the rpmh-regulator | ||
| 298 | * @load_uA: Aggregated load current in microamps | ||
| 299 | * | ||
| 300 | * This function is used in the regulator_ops for VRM type RPMh regulator | ||
| 301 | * devices. | ||
| 302 | * | ||
| 303 | * Return: 0 on success, errno on failure | ||
| 304 | */ | ||
| 305 | static int rpmh_regulator_vrm_set_load(struct regulator_dev *rdev, int load_uA) | ||
| 306 | { | ||
| 307 | struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); | ||
| 308 | unsigned int mode; | ||
| 309 | |||
| 310 | if (load_uA >= vreg->hw_data->hpm_min_load_uA) | ||
| 311 | mode = REGULATOR_MODE_NORMAL; | ||
| 312 | else | ||
| 313 | mode = REGULATOR_MODE_IDLE; | ||
| 314 | |||
| 315 | return rpmh_regulator_vrm_set_mode(rdev, mode); | ||
| 316 | } | ||
| 317 | |||
| 318 | static int rpmh_regulator_vrm_set_bypass(struct regulator_dev *rdev, | ||
| 319 | bool enable) | ||
| 320 | { | ||
| 321 | struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); | ||
| 322 | int ret; | ||
| 323 | |||
| 324 | if (vreg->bypassed == enable) | ||
| 325 | return 0; | ||
| 326 | |||
| 327 | ret = rpmh_regulator_vrm_set_mode_bypass(vreg, vreg->mode, enable); | ||
| 328 | if (!ret) | ||
| 329 | vreg->bypassed = enable; | ||
| 330 | |||
| 331 | return ret; | ||
| 332 | } | ||
| 333 | |||
| 334 | static int rpmh_regulator_vrm_get_bypass(struct regulator_dev *rdev, | ||
| 335 | bool *enable) | ||
| 336 | { | ||
| 337 | struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); | ||
| 338 | |||
| 339 | *enable = vreg->bypassed; | ||
| 340 | |||
| 341 | return 0; | ||
| 342 | } | ||
| 343 | |||
| 344 | static const struct regulator_ops rpmh_regulator_vrm_ops = { | ||
| 345 | .enable = rpmh_regulator_enable, | ||
| 346 | .disable = rpmh_regulator_disable, | ||
| 347 | .is_enabled = rpmh_regulator_is_enabled, | ||
| 348 | .set_voltage_sel = rpmh_regulator_vrm_set_voltage_sel, | ||
| 349 | .get_voltage_sel = rpmh_regulator_vrm_get_voltage_sel, | ||
| 350 | .list_voltage = regulator_list_voltage_linear_range, | ||
| 351 | .set_mode = rpmh_regulator_vrm_set_mode, | ||
| 352 | .get_mode = rpmh_regulator_vrm_get_mode, | ||
| 353 | }; | ||
| 354 | |||
| 355 | static const struct regulator_ops rpmh_regulator_vrm_drms_ops = { | ||
| 356 | .enable = rpmh_regulator_enable, | ||
| 357 | .disable = rpmh_regulator_disable, | ||
| 358 | .is_enabled = rpmh_regulator_is_enabled, | ||
| 359 | .set_voltage_sel = rpmh_regulator_vrm_set_voltage_sel, | ||
| 360 | .get_voltage_sel = rpmh_regulator_vrm_get_voltage_sel, | ||
| 361 | .list_voltage = regulator_list_voltage_linear_range, | ||
| 362 | .set_mode = rpmh_regulator_vrm_set_mode, | ||
| 363 | .get_mode = rpmh_regulator_vrm_get_mode, | ||
| 364 | .set_load = rpmh_regulator_vrm_set_load, | ||
| 365 | }; | ||
| 366 | |||
| 367 | static const struct regulator_ops rpmh_regulator_vrm_bypass_ops = { | ||
| 368 | .enable = rpmh_regulator_enable, | ||
| 369 | .disable = rpmh_regulator_disable, | ||
| 370 | .is_enabled = rpmh_regulator_is_enabled, | ||
| 371 | .set_voltage_sel = rpmh_regulator_vrm_set_voltage_sel, | ||
| 372 | .get_voltage_sel = rpmh_regulator_vrm_get_voltage_sel, | ||
| 373 | .list_voltage = regulator_list_voltage_linear_range, | ||
| 374 | .set_mode = rpmh_regulator_vrm_set_mode, | ||
| 375 | .get_mode = rpmh_regulator_vrm_get_mode, | ||
| 376 | .set_bypass = rpmh_regulator_vrm_set_bypass, | ||
| 377 | .get_bypass = rpmh_regulator_vrm_get_bypass, | ||
| 378 | }; | ||
| 379 | |||
| 380 | static const struct regulator_ops rpmh_regulator_xob_ops = { | ||
| 381 | .enable = rpmh_regulator_enable, | ||
| 382 | .disable = rpmh_regulator_disable, | ||
| 383 | .is_enabled = rpmh_regulator_is_enabled, | ||
| 384 | }; | ||
| 385 | |||
| 386 | /** | ||
| 387 | * rpmh_regulator_init_vreg() - initialize all attributes of an rpmh-regulator | ||
| 388 | * vreg: Pointer to the individual rpmh-regulator resource | ||
| 389 | * dev: Pointer to the top level rpmh-regulator PMIC device | ||
| 390 | * node: Pointer to the individual rpmh-regulator resource | ||
| 391 | * device node | ||
| 392 | * pmic_id: String used to identify the top level rpmh-regulator | ||
| 393 | * PMIC device on the board | ||
| 394 | * pmic_rpmh_data: Pointer to a null-terminated array of rpmh-regulator | ||
| 395 | * resources defined for the top level PMIC device | ||
| 396 | * | ||
| 397 | * Return: 0 on success, errno on failure | ||
| 398 | */ | ||
| 399 | static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev, | ||
| 400 | struct device_node *node, const char *pmic_id, | ||
| 401 | const struct rpmh_vreg_init_data *pmic_rpmh_data) | ||
| 402 | { | ||
| 403 | struct regulator_config reg_config = {}; | ||
| 404 | char rpmh_resource_name[20] = ""; | ||
| 405 | const struct rpmh_vreg_init_data *rpmh_data; | ||
| 406 | struct regulator_init_data *init_data; | ||
| 407 | struct regulator_dev *rdev; | ||
| 408 | int ret; | ||
| 409 | |||
| 410 | vreg->dev = dev; | ||
| 411 | |||
| 412 | for (rpmh_data = pmic_rpmh_data; rpmh_data->name; rpmh_data++) | ||
| 413 | if (!strcmp(rpmh_data->name, node->name)) | ||
| 414 | break; | ||
| 415 | |||
| 416 | if (!rpmh_data->name) { | ||
| 417 | dev_err(dev, "Unknown regulator %s\n", node->name); | ||
| 418 | return -EINVAL; | ||
| 419 | } | ||
| 420 | |||
| 421 | scnprintf(rpmh_resource_name, sizeof(rpmh_resource_name), | ||
| 422 | rpmh_data->resource_name, pmic_id); | ||
| 423 | |||
| 424 | vreg->addr = cmd_db_read_addr(rpmh_resource_name); | ||
| 425 | if (!vreg->addr) { | ||
| 426 | dev_err(dev, "%s: could not find RPMh address for resource %s\n", | ||
| 427 | node->name, rpmh_resource_name); | ||
| 428 | return -ENODEV; | ||
| 429 | } | ||
| 430 | |||
| 431 | vreg->rdesc.name = rpmh_data->name; | ||
| 432 | vreg->rdesc.supply_name = rpmh_data->supply_name; | ||
| 433 | vreg->hw_data = rpmh_data->hw_data; | ||
| 434 | |||
| 435 | vreg->enabled = -EINVAL; | ||
| 436 | vreg->voltage_selector = -ENOTRECOVERABLE; | ||
| 437 | vreg->mode = REGULATOR_MODE_INVALID; | ||
| 438 | |||
| 439 | if (rpmh_data->hw_data->n_voltages) { | ||
| 440 | vreg->rdesc.linear_ranges = &rpmh_data->hw_data->voltage_range; | ||
| 441 | vreg->rdesc.n_linear_ranges = 1; | ||
| 442 | vreg->rdesc.n_voltages = rpmh_data->hw_data->n_voltages; | ||
| 443 | } | ||
| 444 | |||
| 445 | vreg->always_wait_for_ack = of_property_read_bool(node, | ||
| 446 | "qcom,always-wait-for-ack"); | ||
| 447 | |||
| 448 | vreg->rdesc.owner = THIS_MODULE; | ||
| 449 | vreg->rdesc.type = REGULATOR_VOLTAGE; | ||
| 450 | vreg->rdesc.ops = vreg->hw_data->ops; | ||
| 451 | vreg->rdesc.of_map_mode = vreg->hw_data->of_map_mode; | ||
| 452 | |||
| 453 | init_data = of_get_regulator_init_data(dev, node, &vreg->rdesc); | ||
| 454 | if (!init_data) | ||
| 455 | return -ENOMEM; | ||
| 456 | |||
| 457 | if (rpmh_data->hw_data->regulator_type == XOB && | ||
| 458 | init_data->constraints.min_uV && | ||
| 459 | init_data->constraints.min_uV == init_data->constraints.max_uV) { | ||
| 460 | vreg->rdesc.fixed_uV = init_data->constraints.min_uV; | ||
| 461 | vreg->rdesc.n_voltages = 1; | ||
| 462 | } | ||
| 463 | |||
| 464 | reg_config.dev = dev; | ||
| 465 | reg_config.init_data = init_data; | ||
| 466 | reg_config.of_node = node; | ||
| 467 | reg_config.driver_data = vreg; | ||
| 468 | |||
| 469 | rdev = devm_regulator_register(dev, &vreg->rdesc, ®_config); | ||
| 470 | if (IS_ERR(rdev)) { | ||
| 471 | ret = PTR_ERR(rdev); | ||
| 472 | dev_err(dev, "%s: devm_regulator_register() failed, ret=%d\n", | ||
| 473 | node->name, ret); | ||
| 474 | return ret; | ||
| 475 | } | ||
| 476 | |||
| 477 | dev_dbg(dev, "%s regulator registered for RPMh resource %s @ 0x%05X\n", | ||
| 478 | node->name, rpmh_resource_name, vreg->addr); | ||
| 479 | |||
| 480 | return 0; | ||
| 481 | } | ||
| 482 | |||
| 483 | static const int pmic_mode_map_pmic4_ldo[REGULATOR_MODE_STANDBY + 1] = { | ||
| 484 | [REGULATOR_MODE_INVALID] = -EINVAL, | ||
| 485 | [REGULATOR_MODE_STANDBY] = PMIC4_LDO_MODE_RETENTION, | ||
| 486 | [REGULATOR_MODE_IDLE] = PMIC4_LDO_MODE_LPM, | ||
| 487 | [REGULATOR_MODE_NORMAL] = PMIC4_LDO_MODE_HPM, | ||
| 488 | [REGULATOR_MODE_FAST] = -EINVAL, | ||
| 489 | }; | ||
| 490 | |||
| 491 | static unsigned int rpmh_regulator_pmic4_ldo_of_map_mode(unsigned int rpmh_mode) | ||
| 492 | { | ||
| 493 | unsigned int mode; | ||
| 494 | |||
| 495 | switch (rpmh_mode) { | ||
| 496 | case RPMH_REGULATOR_MODE_HPM: | ||
| 497 | mode = REGULATOR_MODE_NORMAL; | ||
| 498 | break; | ||
| 499 | case RPMH_REGULATOR_MODE_LPM: | ||
| 500 | mode = REGULATOR_MODE_IDLE; | ||
| 501 | break; | ||
| 502 | case RPMH_REGULATOR_MODE_RET: | ||
| 503 | mode = REGULATOR_MODE_STANDBY; | ||
| 504 | break; | ||
| 505 | default: | ||
| 506 | mode = REGULATOR_MODE_INVALID; | ||
| 507 | } | ||
| 508 | |||
| 509 | return mode; | ||
| 510 | } | ||
| 511 | |||
| 512 | static const int pmic_mode_map_pmic4_smps[REGULATOR_MODE_STANDBY + 1] = { | ||
| 513 | [REGULATOR_MODE_INVALID] = -EINVAL, | ||
| 514 | [REGULATOR_MODE_STANDBY] = PMIC4_SMPS_MODE_RETENTION, | ||
| 515 | [REGULATOR_MODE_IDLE] = PMIC4_SMPS_MODE_PFM, | ||
| 516 | [REGULATOR_MODE_NORMAL] = PMIC4_SMPS_MODE_AUTO, | ||
| 517 | [REGULATOR_MODE_FAST] = PMIC4_SMPS_MODE_PWM, | ||
| 518 | }; | ||
| 519 | |||
| 520 | static unsigned int | ||
| 521 | rpmh_regulator_pmic4_smps_of_map_mode(unsigned int rpmh_mode) | ||
| 522 | { | ||
| 523 | unsigned int mode; | ||
| 524 | |||
| 525 | switch (rpmh_mode) { | ||
| 526 | case RPMH_REGULATOR_MODE_HPM: | ||
| 527 | mode = REGULATOR_MODE_FAST; | ||
| 528 | break; | ||
| 529 | case RPMH_REGULATOR_MODE_AUTO: | ||
| 530 | mode = REGULATOR_MODE_NORMAL; | ||
| 531 | break; | ||
| 532 | case RPMH_REGULATOR_MODE_LPM: | ||
| 533 | mode = REGULATOR_MODE_IDLE; | ||
| 534 | break; | ||
| 535 | case RPMH_REGULATOR_MODE_RET: | ||
| 536 | mode = REGULATOR_MODE_STANDBY; | ||
| 537 | break; | ||
| 538 | default: | ||
| 539 | mode = REGULATOR_MODE_INVALID; | ||
| 540 | } | ||
| 541 | |||
| 542 | return mode; | ||
| 543 | } | ||
| 544 | |||
| 545 | static const int pmic_mode_map_pmic4_bob[REGULATOR_MODE_STANDBY + 1] = { | ||
| 546 | [REGULATOR_MODE_INVALID] = -EINVAL, | ||
| 547 | [REGULATOR_MODE_STANDBY] = -EINVAL, | ||
| 548 | [REGULATOR_MODE_IDLE] = PMIC4_BOB_MODE_PFM, | ||
| 549 | [REGULATOR_MODE_NORMAL] = PMIC4_BOB_MODE_AUTO, | ||
| 550 | [REGULATOR_MODE_FAST] = PMIC4_BOB_MODE_PWM, | ||
| 551 | }; | ||
| 552 | |||
| 553 | static unsigned int rpmh_regulator_pmic4_bob_of_map_mode(unsigned int rpmh_mode) | ||
| 554 | { | ||
| 555 | unsigned int mode; | ||
| 556 | |||
| 557 | switch (rpmh_mode) { | ||
| 558 | case RPMH_REGULATOR_MODE_HPM: | ||
| 559 | mode = REGULATOR_MODE_FAST; | ||
| 560 | break; | ||
| 561 | case RPMH_REGULATOR_MODE_AUTO: | ||
| 562 | mode = REGULATOR_MODE_NORMAL; | ||
| 563 | break; | ||
| 564 | case RPMH_REGULATOR_MODE_LPM: | ||
| 565 | mode = REGULATOR_MODE_IDLE; | ||
| 566 | break; | ||
| 567 | default: | ||
| 568 | mode = REGULATOR_MODE_INVALID; | ||
| 569 | } | ||
| 570 | |||
| 571 | return mode; | ||
| 572 | } | ||
| 573 | |||
| 574 | static const struct rpmh_vreg_hw_data pmic4_pldo = { | ||
| 575 | .regulator_type = VRM, | ||
| 576 | .ops = &rpmh_regulator_vrm_drms_ops, | ||
| 577 | .voltage_range = REGULATOR_LINEAR_RANGE(1664000, 0, 255, 8000), | ||
| 578 | .n_voltages = 256, | ||
| 579 | .hpm_min_load_uA = 10000, | ||
| 580 | .pmic_mode_map = pmic_mode_map_pmic4_ldo, | ||
| 581 | .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, | ||
| 582 | }; | ||
| 583 | |||
| 584 | static const struct rpmh_vreg_hw_data pmic4_pldo_lv = { | ||
| 585 | .regulator_type = VRM, | ||
| 586 | .ops = &rpmh_regulator_vrm_drms_ops, | ||
| 587 | .voltage_range = REGULATOR_LINEAR_RANGE(1256000, 0, 127, 8000), | ||
| 588 | .n_voltages = 128, | ||
| 589 | .hpm_min_load_uA = 10000, | ||
| 590 | .pmic_mode_map = pmic_mode_map_pmic4_ldo, | ||
| 591 | .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, | ||
| 592 | }; | ||
| 593 | |||
| 594 | static const struct rpmh_vreg_hw_data pmic4_nldo = { | ||
| 595 | .regulator_type = VRM, | ||
| 596 | .ops = &rpmh_regulator_vrm_drms_ops, | ||
| 597 | .voltage_range = REGULATOR_LINEAR_RANGE(312000, 0, 127, 8000), | ||
| 598 | .n_voltages = 128, | ||
| 599 | .hpm_min_load_uA = 30000, | ||
| 600 | .pmic_mode_map = pmic_mode_map_pmic4_ldo, | ||
| 601 | .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, | ||
| 602 | }; | ||
| 603 | |||
| 604 | static const struct rpmh_vreg_hw_data pmic4_hfsmps3 = { | ||
| 605 | .regulator_type = VRM, | ||
| 606 | .ops = &rpmh_regulator_vrm_ops, | ||
| 607 | .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000), | ||
| 608 | .n_voltages = 216, | ||
| 609 | .pmic_mode_map = pmic_mode_map_pmic4_smps, | ||
| 610 | .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, | ||
| 611 | }; | ||
| 612 | |||
| 613 | static const struct rpmh_vreg_hw_data pmic4_ftsmps426 = { | ||
| 614 | .regulator_type = VRM, | ||
| 615 | .ops = &rpmh_regulator_vrm_ops, | ||
| 616 | .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 258, 4000), | ||
| 617 | .n_voltages = 259, | ||
| 618 | .pmic_mode_map = pmic_mode_map_pmic4_smps, | ||
| 619 | .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, | ||
| 620 | }; | ||
| 621 | |||
| 622 | static const struct rpmh_vreg_hw_data pmic4_bob = { | ||
| 623 | .regulator_type = VRM, | ||
| 624 | .ops = &rpmh_regulator_vrm_bypass_ops, | ||
| 625 | .voltage_range = REGULATOR_LINEAR_RANGE(1824000, 0, 83, 32000), | ||
| 626 | .n_voltages = 84, | ||
| 627 | .pmic_mode_map = pmic_mode_map_pmic4_bob, | ||
| 628 | .of_map_mode = rpmh_regulator_pmic4_bob_of_map_mode, | ||
| 629 | }; | ||
| 630 | |||
| 631 | static const struct rpmh_vreg_hw_data pmic4_lvs = { | ||
| 632 | .regulator_type = XOB, | ||
| 633 | .ops = &rpmh_regulator_xob_ops, | ||
| 634 | /* LVS hardware does not support voltage or mode configuration. */ | ||
| 635 | }; | ||
| 636 | |||
| 637 | #define RPMH_VREG(_name, _resource_name, _hw_data, _supply_name) \ | ||
| 638 | { \ | ||
| 639 | .name = _name, \ | ||
| 640 | .resource_name = _resource_name, \ | ||
| 641 | .hw_data = _hw_data, \ | ||
| 642 | .supply_name = _supply_name, \ | ||
| 643 | } | ||
| 644 | |||
| 645 | static const struct rpmh_vreg_init_data pm8998_vreg_data[] = { | ||
| 646 | RPMH_VREG("smps1", "smp%s1", &pmic4_ftsmps426, "vdd-s1"), | ||
| 647 | RPMH_VREG("smps2", "smp%s2", &pmic4_ftsmps426, "vdd-s2"), | ||
| 648 | RPMH_VREG("smps3", "smp%s3", &pmic4_hfsmps3, "vdd-s3"), | ||
| 649 | RPMH_VREG("smps4", "smp%s4", &pmic4_hfsmps3, "vdd-s4"), | ||
| 650 | RPMH_VREG("smps5", "smp%s5", &pmic4_hfsmps3, "vdd-s5"), | ||
| 651 | RPMH_VREG("smps6", "smp%s6", &pmic4_ftsmps426, "vdd-s6"), | ||
| 652 | RPMH_VREG("smps7", "smp%s7", &pmic4_ftsmps426, "vdd-s7"), | ||
| 653 | RPMH_VREG("smps8", "smp%s8", &pmic4_ftsmps426, "vdd-s8"), | ||
| 654 | RPMH_VREG("smps9", "smp%s9", &pmic4_ftsmps426, "vdd-s9"), | ||
| 655 | RPMH_VREG("smps10", "smp%s10", &pmic4_ftsmps426, "vdd-s10"), | ||
| 656 | RPMH_VREG("smps11", "smp%s11", &pmic4_ftsmps426, "vdd-s11"), | ||
| 657 | RPMH_VREG("smps12", "smp%s12", &pmic4_ftsmps426, "vdd-s12"), | ||
| 658 | RPMH_VREG("smps13", "smp%s13", &pmic4_ftsmps426, "vdd-s13"), | ||
| 659 | RPMH_VREG("ldo1", "ldo%s1", &pmic4_nldo, "vdd-l1-l27"), | ||
| 660 | RPMH_VREG("ldo2", "ldo%s2", &pmic4_nldo, "vdd-l2-l8-l17"), | ||
| 661 | RPMH_VREG("ldo3", "ldo%s3", &pmic4_nldo, "vdd-l3-l11"), | ||
| 662 | RPMH_VREG("ldo4", "ldo%s4", &pmic4_nldo, "vdd-l4-l5"), | ||
| 663 | RPMH_VREG("ldo5", "ldo%s5", &pmic4_nldo, "vdd-l4-l5"), | ||
| 664 | RPMH_VREG("ldo6", "ldo%s6", &pmic4_pldo, "vdd-l6"), | ||
| 665 | RPMH_VREG("ldo7", "ldo%s7", &pmic4_pldo_lv, "vdd-l7-l12-l14-l15"), | ||
| 666 | RPMH_VREG("ldo8", "ldo%s8", &pmic4_nldo, "vdd-l2-l8-l17"), | ||
| 667 | RPMH_VREG("ldo9", "ldo%s9", &pmic4_pldo, "vdd-l9"), | ||
| 668 | RPMH_VREG("ldo10", "ldo%s10", &pmic4_pldo, "vdd-l10-l23-l25"), | ||
| 669 | RPMH_VREG("ldo11", "ldo%s11", &pmic4_nldo, "vdd-l3-l11"), | ||
| 670 | RPMH_VREG("ldo12", "ldo%s12", &pmic4_pldo_lv, "vdd-l7-l12-l14-l15"), | ||
| 671 | RPMH_VREG("ldo13", "ldo%s13", &pmic4_pldo, "vdd-l13-l19-l21"), | ||
| 672 | RPMH_VREG("ldo14", "ldo%s14", &pmic4_pldo_lv, "vdd-l7-l12-l14-l15"), | ||
| 673 | RPMH_VREG("ldo15", "ldo%s15", &pmic4_pldo_lv, "vdd-l7-l12-l14-l15"), | ||
| 674 | RPMH_VREG("ldo16", "ldo%s16", &pmic4_pldo, "vdd-l16-l28"), | ||
| 675 | RPMH_VREG("ldo17", "ldo%s17", &pmic4_nldo, "vdd-l2-l8-l17"), | ||
| 676 | RPMH_VREG("ldo18", "ldo%s18", &pmic4_pldo, "vdd-l18-l22"), | ||
| 677 | RPMH_VREG("ldo19", "ldo%s19", &pmic4_pldo, "vdd-l13-l19-l21"), | ||
| 678 | RPMH_VREG("ldo20", "ldo%s20", &pmic4_pldo, "vdd-l20-l24"), | ||
| 679 | RPMH_VREG("ldo21", "ldo%s21", &pmic4_pldo, "vdd-l13-l19-l21"), | ||
| 680 | RPMH_VREG("ldo22", "ldo%s22", &pmic4_pldo, "vdd-l18-l22"), | ||
| 681 | RPMH_VREG("ldo23", "ldo%s23", &pmic4_pldo, "vdd-l10-l23-l25"), | ||
| 682 | RPMH_VREG("ldo24", "ldo%s24", &pmic4_pldo, "vdd-l20-l24"), | ||
| 683 | RPMH_VREG("ldo25", "ldo%s25", &pmic4_pldo, "vdd-l10-l23-l25"), | ||
| 684 | RPMH_VREG("ldo26", "ldo%s26", &pmic4_nldo, "vdd-l26"), | ||
| 685 | RPMH_VREG("ldo27", "ldo%s27", &pmic4_nldo, "vdd-l1-l27"), | ||
| 686 | RPMH_VREG("ldo28", "ldo%s28", &pmic4_pldo, "vdd-l16-l28"), | ||
| 687 | RPMH_VREG("lvs1", "vs%s1", &pmic4_lvs, "vin-lvs-1-2"), | ||
| 688 | RPMH_VREG("lvs2", "vs%s2", &pmic4_lvs, "vin-lvs-1-2"), | ||
| 689 | {}, | ||
| 690 | }; | ||
| 691 | |||
| 692 | static const struct rpmh_vreg_init_data pmi8998_vreg_data[] = { | ||
| 693 | RPMH_VREG("bob", "bob%s1", &pmic4_bob, "vdd-bob"), | ||
| 694 | {}, | ||
| 695 | }; | ||
| 696 | |||
| 697 | static const struct rpmh_vreg_init_data pm8005_vreg_data[] = { | ||
| 698 | RPMH_VREG("smps1", "smp%s1", &pmic4_ftsmps426, "vdd-s1"), | ||
| 699 | RPMH_VREG("smps2", "smp%s2", &pmic4_ftsmps426, "vdd-s2"), | ||
| 700 | RPMH_VREG("smps3", "smp%s3", &pmic4_ftsmps426, "vdd-s3"), | ||
| 701 | RPMH_VREG("smps4", "smp%s4", &pmic4_ftsmps426, "vdd-s4"), | ||
| 702 | {}, | ||
| 703 | }; | ||
| 704 | |||
| 705 | static int rpmh_regulator_probe(struct platform_device *pdev) | ||
| 706 | { | ||
| 707 | struct device *dev = &pdev->dev; | ||
| 708 | const struct rpmh_vreg_init_data *vreg_data; | ||
| 709 | struct device_node *node; | ||
| 710 | struct rpmh_vreg *vreg; | ||
| 711 | const char *pmic_id; | ||
| 712 | int ret; | ||
| 713 | |||
| 714 | vreg_data = of_device_get_match_data(dev); | ||
| 715 | if (!vreg_data) | ||
| 716 | return -ENODEV; | ||
| 717 | |||
| 718 | ret = of_property_read_string(dev->of_node, "qcom,pmic-id", &pmic_id); | ||
| 719 | if (ret < 0) { | ||
| 720 | dev_err(dev, "qcom,pmic-id missing in DT node\n"); | ||
| 721 | return ret; | ||
| 722 | } | ||
| 723 | |||
| 724 | for_each_available_child_of_node(dev->of_node, node) { | ||
| 725 | vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL); | ||
| 726 | if (!vreg) { | ||
| 727 | of_node_put(node); | ||
| 728 | return -ENOMEM; | ||
| 729 | } | ||
| 730 | |||
| 731 | ret = rpmh_regulator_init_vreg(vreg, dev, node, pmic_id, | ||
| 732 | vreg_data); | ||
| 733 | if (ret < 0) { | ||
| 734 | of_node_put(node); | ||
| 735 | return ret; | ||
| 736 | } | ||
| 737 | } | ||
| 738 | |||
| 739 | return 0; | ||
| 740 | } | ||
| 741 | |||
| 742 | static const struct of_device_id rpmh_regulator_match_table[] = { | ||
| 743 | { | ||
| 744 | .compatible = "qcom,pm8998-rpmh-regulators", | ||
| 745 | .data = pm8998_vreg_data, | ||
| 746 | }, | ||
| 747 | { | ||
| 748 | .compatible = "qcom,pmi8998-rpmh-regulators", | ||
| 749 | .data = pmi8998_vreg_data, | ||
| 750 | }, | ||
| 751 | { | ||
| 752 | .compatible = "qcom,pm8005-rpmh-regulators", | ||
| 753 | .data = pm8005_vreg_data, | ||
| 754 | }, | ||
| 755 | {} | ||
| 756 | }; | ||
| 757 | MODULE_DEVICE_TABLE(of, rpmh_regulator_match_table); | ||
| 758 | |||
| 759 | static struct platform_driver rpmh_regulator_driver = { | ||
| 760 | .driver = { | ||
| 761 | .name = "qcom-rpmh-regulator", | ||
| 762 | .of_match_table = of_match_ptr(rpmh_regulator_match_table), | ||
| 763 | }, | ||
| 764 | .probe = rpmh_regulator_probe, | ||
| 765 | }; | ||
| 766 | module_platform_driver(rpmh_regulator_driver); | ||
| 767 | |||
| 768 | MODULE_DESCRIPTION("Qualcomm RPMh regulator driver"); | ||
| 769 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index 9817f1a75342..53a61fb65642 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c | |||
| @@ -1060,7 +1060,7 @@ static irqreturn_t spmi_regulator_vs_ocp_isr(int irq, void *data) | |||
| 1060 | #define SAW3_AVS_CTL_TGGL_MASK 0x8000000 | 1060 | #define SAW3_AVS_CTL_TGGL_MASK 0x8000000 |
| 1061 | #define SAW3_AVS_CTL_CLEAR_MASK 0x7efc00 | 1061 | #define SAW3_AVS_CTL_CLEAR_MASK 0x7efc00 |
| 1062 | 1062 | ||
| 1063 | static struct regmap *saw_regmap = NULL; | 1063 | static struct regmap *saw_regmap; |
| 1064 | 1064 | ||
| 1065 | static void spmi_saw_set_vdd(void *data) | 1065 | static void spmi_saw_set_vdd(void *data) |
| 1066 | { | 1066 | { |
| @@ -1728,7 +1728,7 @@ static const struct spmi_regulator_data pmi8994_regulators[] = { | |||
| 1728 | { "s2", 0x1700, "vdd_s2", }, | 1728 | { "s2", 0x1700, "vdd_s2", }, |
| 1729 | { "s3", 0x1a00, "vdd_s3", }, | 1729 | { "s3", 0x1a00, "vdd_s3", }, |
| 1730 | { "l1", 0x4000, "vdd_l1", }, | 1730 | { "l1", 0x4000, "vdd_l1", }, |
| 1731 | { } | 1731 | { } |
| 1732 | }; | 1732 | }; |
| 1733 | 1733 | ||
| 1734 | static const struct of_device_id qcom_spmi_regulator_match[] = { | 1734 | static const struct of_device_id qcom_spmi_regulator_match[] = { |
| @@ -1752,7 +1752,8 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev) | |||
| 1752 | const char *name; | 1752 | const char *name; |
| 1753 | struct device *dev = &pdev->dev; | 1753 | struct device *dev = &pdev->dev; |
| 1754 | struct device_node *node = pdev->dev.of_node; | 1754 | struct device_node *node = pdev->dev.of_node; |
| 1755 | struct device_node *syscon; | 1755 | struct device_node *syscon, *reg_node; |
| 1756 | struct property *reg_prop; | ||
| 1756 | int ret, lenp; | 1757 | int ret, lenp; |
| 1757 | struct list_head *vreg_list; | 1758 | struct list_head *vreg_list; |
| 1758 | 1759 | ||
| @@ -1774,16 +1775,19 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev) | |||
| 1774 | syscon = of_parse_phandle(node, "qcom,saw-reg", 0); | 1775 | syscon = of_parse_phandle(node, "qcom,saw-reg", 0); |
| 1775 | saw_regmap = syscon_node_to_regmap(syscon); | 1776 | saw_regmap = syscon_node_to_regmap(syscon); |
| 1776 | of_node_put(syscon); | 1777 | of_node_put(syscon); |
| 1777 | if (IS_ERR(regmap)) | 1778 | if (IS_ERR(saw_regmap)) |
| 1778 | dev_err(dev, "ERROR reading SAW regmap\n"); | 1779 | dev_err(dev, "ERROR reading SAW regmap\n"); |
| 1779 | } | 1780 | } |
| 1780 | 1781 | ||
| 1781 | for (reg = match->data; reg->name; reg++) { | 1782 | for (reg = match->data; reg->name; reg++) { |
| 1782 | 1783 | ||
| 1783 | if (saw_regmap && \ | 1784 | if (saw_regmap) { |
| 1784 | of_find_property(of_find_node_by_name(node, reg->name), \ | 1785 | reg_node = of_get_child_by_name(node, reg->name); |
| 1785 | "qcom,saw-slave", &lenp)) { | 1786 | reg_prop = of_find_property(reg_node, "qcom,saw-slave", |
| 1786 | continue; | 1787 | &lenp); |
| 1788 | of_node_put(reg_node); | ||
| 1789 | if (reg_prop) | ||
| 1790 | continue; | ||
| 1787 | } | 1791 | } |
| 1788 | 1792 | ||
| 1789 | vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL); | 1793 | vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL); |
| @@ -1816,13 +1820,17 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev) | |||
| 1816 | if (ret) | 1820 | if (ret) |
| 1817 | continue; | 1821 | continue; |
| 1818 | 1822 | ||
| 1819 | if (saw_regmap && \ | 1823 | if (saw_regmap) { |
| 1820 | of_find_property(of_find_node_by_name(node, reg->name), \ | 1824 | reg_node = of_get_child_by_name(node, reg->name); |
| 1821 | "qcom,saw-leader", &lenp)) { | 1825 | reg_prop = of_find_property(reg_node, "qcom,saw-leader", |
| 1822 | spmi_saw_ops = *(vreg->desc.ops); | 1826 | &lenp); |
| 1823 | spmi_saw_ops.set_voltage_sel = \ | 1827 | of_node_put(reg_node); |
| 1824 | spmi_regulator_saw_set_voltage; | 1828 | if (reg_prop) { |
| 1825 | vreg->desc.ops = &spmi_saw_ops; | 1829 | spmi_saw_ops = *(vreg->desc.ops); |
| 1830 | spmi_saw_ops.set_voltage_sel = | ||
| 1831 | spmi_regulator_saw_set_voltage; | ||
| 1832 | vreg->desc.ops = &spmi_saw_ops; | ||
| 1833 | } | ||
| 1826 | } | 1834 | } |
| 1827 | 1835 | ||
| 1828 | config.dev = dev; | 1836 | config.dev = dev; |
diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c index 48f0ca90743c..095d25f3d2ea 100644 --- a/drivers/regulator/s2mpa01.c +++ b/drivers/regulator/s2mpa01.c | |||
| @@ -1,13 +1,7 @@ | |||
| 1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | * Copyright (c) 2013 Samsung Electronics Co., Ltd | 2 | // |
| 3 | * http://www.samsung.com | 3 | // Copyright (c) 2013 Samsung Electronics Co., Ltd |
| 4 | * | 4 | // http://www.samsung.com |
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License as published by the | ||
| 7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 8 | * option) any later version. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | 5 | ||
| 12 | #include <linux/bug.h> | 6 | #include <linux/bug.h> |
| 13 | #include <linux/err.h> | 7 | #include <linux/err.h> |
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index d1207ec683db..5bb6f4ca48db 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c | |||
| @@ -1,20 +1,7 @@ | |||
| 1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | * s2mps11.c | 2 | // |
| 3 | * | 3 | // Copyright (c) 2012-2014 Samsung Electronics Co., Ltd |
| 4 | * Copyright (c) 2012-2014 Samsung Electronics Co., Ltd | 4 | // http://www.samsung.com |
| 5 | * http://www.samsung.com | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the | ||
| 9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 10 | * option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | 5 | ||
| 19 | #include <linux/bug.h> | 6 | #include <linux/bug.h> |
| 20 | #include <linux/err.h> | 7 | #include <linux/err.h> |
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 0cbc980753c2..667d16dc83ce 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c | |||
| @@ -1,15 +1,7 @@ | |||
| 1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | * s5m8767.c | 2 | // |
| 3 | * | 3 | // Copyright (c) 2011 Samsung Electronics Co., Ltd |
| 4 | * Copyright (c) 2011 Samsung Electronics Co., Ltd | 4 | // http://www.samsung.com |
| 5 | * http://www.samsung.com | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the | ||
| 9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 10 | * option) any later version. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | 5 | ||
| 14 | #include <linux/err.h> | 6 | #include <linux/err.h> |
| 15 | #include <linux/of_gpio.h> | 7 | #include <linux/of_gpio.h> |
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index fc12badf3805..d84fab616abf 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c | |||
| @@ -232,6 +232,8 @@ static int tps65217_regulator_probe(struct platform_device *pdev) | |||
| 232 | tps->strobes = devm_kcalloc(&pdev->dev, | 232 | tps->strobes = devm_kcalloc(&pdev->dev, |
| 233 | TPS65217_NUM_REGULATOR, sizeof(u8), | 233 | TPS65217_NUM_REGULATOR, sizeof(u8), |
| 234 | GFP_KERNEL); | 234 | GFP_KERNEL); |
| 235 | if (!tps->strobes) | ||
| 236 | return -ENOMEM; | ||
| 235 | 237 | ||
| 236 | platform_set_drvdata(pdev, tps); | 238 | platform_set_drvdata(pdev, tps); |
| 237 | 239 | ||
diff --git a/drivers/regulator/uniphier-regulator.c b/drivers/regulator/uniphier-regulator.c new file mode 100644 index 000000000000..abf22acbd13e --- /dev/null +++ b/drivers/regulator/uniphier-regulator.c | |||
| @@ -0,0 +1,213 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | // | ||
| 3 | // Regulator controller driver for UniPhier SoC | ||
| 4 | // Copyright 2018 Socionext Inc. | ||
| 5 | // Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com> | ||
| 6 | |||
| 7 | #include <linux/clk.h> | ||
| 8 | #include <linux/io.h> | ||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/of_device.h> | ||
| 11 | #include <linux/platform_device.h> | ||
| 12 | #include <linux/regmap.h> | ||
| 13 | #include <linux/regulator/driver.h> | ||
| 14 | #include <linux/regulator/of_regulator.h> | ||
| 15 | #include <linux/reset.h> | ||
| 16 | |||
| 17 | #define MAX_CLKS 2 | ||
| 18 | #define MAX_RSTS 2 | ||
| 19 | |||
| 20 | struct uniphier_regulator_soc_data { | ||
| 21 | int nclks; | ||
| 22 | const char * const *clock_names; | ||
| 23 | int nrsts; | ||
| 24 | const char * const *reset_names; | ||
| 25 | const struct regulator_desc *desc; | ||
| 26 | const struct regmap_config *regconf; | ||
| 27 | }; | ||
| 28 | |||
| 29 | struct uniphier_regulator_priv { | ||
| 30 | struct clk_bulk_data clk[MAX_CLKS]; | ||
| 31 | struct reset_control *rst[MAX_RSTS]; | ||
| 32 | const struct uniphier_regulator_soc_data *data; | ||
| 33 | }; | ||
| 34 | |||
| 35 | static struct regulator_ops uniphier_regulator_ops = { | ||
| 36 | .enable = regulator_enable_regmap, | ||
| 37 | .disable = regulator_disable_regmap, | ||
| 38 | .is_enabled = regulator_is_enabled_regmap, | ||
| 39 | }; | ||
| 40 | |||
| 41 | static int uniphier_regulator_probe(struct platform_device *pdev) | ||
| 42 | { | ||
| 43 | struct device *dev = &pdev->dev; | ||
| 44 | struct uniphier_regulator_priv *priv; | ||
| 45 | struct regulator_config config = { }; | ||
| 46 | struct regulator_dev *rdev; | ||
| 47 | struct regmap *regmap; | ||
| 48 | struct resource *res; | ||
| 49 | void __iomem *base; | ||
| 50 | const char *name; | ||
| 51 | int i, ret, nr; | ||
| 52 | |||
| 53 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
| 54 | if (!priv) | ||
| 55 | return -ENOMEM; | ||
| 56 | |||
| 57 | priv->data = of_device_get_match_data(dev); | ||
| 58 | if (WARN_ON(!priv->data)) | ||
| 59 | return -EINVAL; | ||
| 60 | |||
| 61 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 62 | base = devm_ioremap_resource(dev, res); | ||
| 63 | if (IS_ERR(base)) | ||
| 64 | return PTR_ERR(base); | ||
| 65 | |||
| 66 | for (i = 0; i < priv->data->nclks; i++) | ||
| 67 | priv->clk[i].id = priv->data->clock_names[i]; | ||
| 68 | ret = devm_clk_bulk_get(dev, priv->data->nclks, priv->clk); | ||
| 69 | if (ret) | ||
| 70 | return ret; | ||
| 71 | |||
| 72 | for (i = 0; i < priv->data->nrsts; i++) { | ||
| 73 | name = priv->data->reset_names[i]; | ||
| 74 | priv->rst[i] = devm_reset_control_get_shared(dev, name); | ||
| 75 | if (IS_ERR(priv->rst[i])) | ||
| 76 | return PTR_ERR(priv->rst[i]); | ||
| 77 | } | ||
| 78 | |||
| 79 | ret = clk_bulk_prepare_enable(priv->data->nclks, priv->clk); | ||
| 80 | if (ret) | ||
| 81 | return ret; | ||
| 82 | |||
| 83 | for (nr = 0; nr < priv->data->nrsts; nr++) { | ||
| 84 | ret = reset_control_deassert(priv->rst[nr]); | ||
| 85 | if (ret) | ||
| 86 | goto out_rst_assert; | ||
| 87 | } | ||
| 88 | |||
| 89 | regmap = devm_regmap_init_mmio(dev, base, priv->data->regconf); | ||
| 90 | if (IS_ERR(regmap)) | ||
| 91 | return PTR_ERR(regmap); | ||
| 92 | |||
| 93 | config.dev = dev; | ||
| 94 | config.driver_data = priv; | ||
| 95 | config.of_node = dev->of_node; | ||
| 96 | config.regmap = regmap; | ||
| 97 | config.init_data = of_get_regulator_init_data(dev, dev->of_node, | ||
| 98 | priv->data->desc); | ||
| 99 | rdev = devm_regulator_register(dev, priv->data->desc, &config); | ||
| 100 | if (IS_ERR(rdev)) { | ||
| 101 | ret = PTR_ERR(rdev); | ||
| 102 | goto out_rst_assert; | ||
| 103 | } | ||
| 104 | |||
| 105 | platform_set_drvdata(pdev, priv); | ||
| 106 | |||
| 107 | return 0; | ||
| 108 | |||
| 109 | out_rst_assert: | ||
| 110 | while (nr--) | ||
| 111 | reset_control_assert(priv->rst[nr]); | ||
| 112 | |||
| 113 | clk_bulk_disable_unprepare(priv->data->nclks, priv->clk); | ||
| 114 | |||
| 115 | return ret; | ||
| 116 | } | ||
| 117 | |||
| 118 | static int uniphier_regulator_remove(struct platform_device *pdev) | ||
| 119 | { | ||
| 120 | struct uniphier_regulator_priv *priv = platform_get_drvdata(pdev); | ||
| 121 | int i; | ||
| 122 | |||
| 123 | for (i = 0; i < priv->data->nrsts; i++) | ||
| 124 | reset_control_assert(priv->rst[i]); | ||
| 125 | |||
| 126 | clk_bulk_disable_unprepare(priv->data->nclks, priv->clk); | ||
| 127 | |||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | /* USB3 controller data */ | ||
| 132 | #define USB3VBUS_OFFSET 0x0 | ||
| 133 | #define USB3VBUS_REG BIT(4) | ||
| 134 | #define USB3VBUS_REG_EN BIT(3) | ||
| 135 | static const struct regulator_desc uniphier_usb3_regulator_desc = { | ||
| 136 | .name = "vbus", | ||
| 137 | .of_match = of_match_ptr("vbus"), | ||
| 138 | .ops = &uniphier_regulator_ops, | ||
| 139 | .type = REGULATOR_VOLTAGE, | ||
| 140 | .owner = THIS_MODULE, | ||
| 141 | .enable_reg = USB3VBUS_OFFSET, | ||
| 142 | .enable_mask = USB3VBUS_REG_EN | USB3VBUS_REG, | ||
| 143 | .enable_val = USB3VBUS_REG_EN | USB3VBUS_REG, | ||
| 144 | .disable_val = USB3VBUS_REG_EN, | ||
| 145 | }; | ||
| 146 | |||
| 147 | static const struct regmap_config uniphier_usb3_regulator_regconf = { | ||
| 148 | .reg_bits = 32, | ||
| 149 | .val_bits = 32, | ||
| 150 | .reg_stride = 4, | ||
| 151 | .max_register = 1, | ||
| 152 | }; | ||
| 153 | |||
| 154 | static const char * const uniphier_pro4_clock_reset_names[] = { | ||
| 155 | "gio", "link", | ||
| 156 | }; | ||
| 157 | |||
| 158 | static const struct uniphier_regulator_soc_data uniphier_pro4_usb3_data = { | ||
| 159 | .nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names), | ||
| 160 | .clock_names = uniphier_pro4_clock_reset_names, | ||
| 161 | .nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names), | ||
| 162 | .reset_names = uniphier_pro4_clock_reset_names, | ||
| 163 | .desc = &uniphier_usb3_regulator_desc, | ||
| 164 | .regconf = &uniphier_usb3_regulator_regconf, | ||
| 165 | }; | ||
| 166 | |||
| 167 | static const char * const uniphier_pxs2_clock_reset_names[] = { | ||
| 168 | "link", | ||
| 169 | }; | ||
| 170 | |||
| 171 | static const struct uniphier_regulator_soc_data uniphier_pxs2_usb3_data = { | ||
| 172 | .nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names), | ||
| 173 | .clock_names = uniphier_pxs2_clock_reset_names, | ||
| 174 | .nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names), | ||
| 175 | .reset_names = uniphier_pxs2_clock_reset_names, | ||
| 176 | .desc = &uniphier_usb3_regulator_desc, | ||
| 177 | .regconf = &uniphier_usb3_regulator_regconf, | ||
| 178 | }; | ||
| 179 | |||
| 180 | static const struct of_device_id uniphier_regulator_match[] = { | ||
| 181 | /* USB VBUS */ | ||
| 182 | { | ||
| 183 | .compatible = "socionext,uniphier-pro4-usb3-regulator", | ||
| 184 | .data = &uniphier_pro4_usb3_data, | ||
| 185 | }, | ||
| 186 | { | ||
| 187 | .compatible = "socionext,uniphier-pxs2-usb3-regulator", | ||
| 188 | .data = &uniphier_pxs2_usb3_data, | ||
| 189 | }, | ||
| 190 | { | ||
| 191 | .compatible = "socionext,uniphier-ld20-usb3-regulator", | ||
| 192 | .data = &uniphier_pxs2_usb3_data, | ||
| 193 | }, | ||
| 194 | { | ||
| 195 | .compatible = "socionext,uniphier-pxs3-usb3-regulator", | ||
| 196 | .data = &uniphier_pxs2_usb3_data, | ||
| 197 | }, | ||
| 198 | { /* Sentinel */ }, | ||
| 199 | }; | ||
| 200 | |||
| 201 | static struct platform_driver uniphier_regulator_driver = { | ||
| 202 | .probe = uniphier_regulator_probe, | ||
| 203 | .remove = uniphier_regulator_remove, | ||
| 204 | .driver = { | ||
| 205 | .name = "uniphier-regulator", | ||
| 206 | .of_match_table = uniphier_regulator_match, | ||
| 207 | }, | ||
| 208 | }; | ||
| 209 | module_platform_driver(uniphier_regulator_driver); | ||
| 210 | |||
| 211 | MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>"); | ||
| 212 | MODULE_DESCRIPTION("UniPhier Regulator Controller Driver"); | ||
| 213 | MODULE_LICENSE("GPL"); | ||
