diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-08 13:08:57 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-08 13:08:57 -0700 |
commit | 68cc38ff33f38424d0456f9a1ecfec4683226a7e (patch) | |
tree | fa96b657dca1893ee8da5e858a0b6692f038fad1 | |
parent | 410feb75de245664d66bc05ab2e2412751d10acf (diff) | |
parent | 13ed4964057e5ad183da9f7f8160841d261e9517 (diff) | |
download | linux-68cc38ff33f38424d0456f9a1ecfec4683226a7e.tar.bz2 |
Merge tag 'regulator-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator
Pull regulator updates from Mark Brown:
"Quite a lot of core work this time around, though not 100% successful.
We gained support for runtime mode changes thanks to David Collins and
improved support for write only regulators (ones where we can't read
back the configuration) from Douglas Anderson.
There's been quite a bit of work from Linus Walleij on converting from
specfying GPIOs by numbers to descriptors. Sadly the testing turned
out to be less good than we had hoped and so a lot of this had to be
reverted.
We also have the start of updates to use coupled regulators from
Maciej Purski, unfortunately there are further problems there so the
last couple of patches have been reverted.
We also have new drivers for BD71837 and SY8106A devices, SAW
regulators on Qualcomm SPMI and dropped support for some preproduction
chips that never made it to market from the AB8500 driver"
* tag 'regulator-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (57 commits)
regulator: gpio: Revert
ARM: pxa, regulator: fix building ezx e680
regulator: Revert coupled regulator support again
regulator: wm8994: Fix shared GPIOs
regulator: max77686: Fix shared GPIOs
regulator: bd71837: BD71837 PMIC regulator driver
regulator: bd71837: Devicetree bindings for BD71837 regulators
regulator: gpio: Get enable GPIO using GPIO descriptor
regulator: fixed: Convert to use GPIO descriptor only
regulator: s2mps11: Fix boot on Odroid XU3
dt-bindings: qcom_spmi: Document SAW support
regulator: qcom_spmi: Add support for SAW
regulator: tps65090: Pass descriptor instead of GPIO number
regulator: s5m8767: Pass descriptor instead of GPIO number
regulator: pfuze100: Delete reference to ena_gpio
regulator: max8952: Pass descriptor instead of GPIO number
regulator: lp8788-ldo: Pass descriptor instead of GPIO number
regulator: lm363x: Pass descriptor instead of GPIO number
regulator: max8973: Pass descriptor instead of GPIO number
regulator: mc13xxx-core: Switch to SPDX identifier
...
51 files changed, 2010 insertions, 1849 deletions
diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt index 9455503b0299..d1762f3b30af 100644 --- a/Documentation/devicetree/bindings/mfd/axp20x.txt +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt @@ -43,7 +43,7 @@ Optional properties: regulator to drive the OTG VBus, rather then as an input pin which signals whether the board is driving OTG VBus or not. - (axp221 / axp223 / axp813 only) + (axp221 / axp223 / axp803/ axp813 only) - x-powers,master-mode: Boolean (axp806 only). Set this when the PMIC is wired for master mode. The default is slave mode. @@ -132,6 +132,7 @@ FLDO2 : LDO : fldoin-supply : shared supply LDO_IO0 : LDO : ips-supply : GPIO 0 LDO_IO1 : LDO : ips-supply : GPIO 1 RTC_LDO : LDO : ips-supply : always on +DRIVEVBUS : Enable output : drivevbus-supply : external regulator AXP806 regulators, type, and corresponding input supply names: diff --git a/Documentation/devicetree/bindings/mfd/bd9571mwv.txt b/Documentation/devicetree/bindings/mfd/bd9571mwv.txt index 9ab216a851d5..25d1f697eb25 100644 --- a/Documentation/devicetree/bindings/mfd/bd9571mwv.txt +++ b/Documentation/devicetree/bindings/mfd/bd9571mwv.txt @@ -25,6 +25,25 @@ Required properties: Each child node is defined using the standard binding for regulators. +Optional properties: + - rohm,ddr-backup-power : Value to use for DDR-Backup Power (default 0). + This is a bitmask that specifies which DDR power + rails need to be kept powered when backup mode is + entered, for system suspend: + - bit 0: DDR0 + - bit 1: DDR1 + - bit 2: DDR0C + - bit 3: DDR1C + These bits match the KEEPON_DDR* bits in the + documentation for the "BKUP Mode Cnt" register. + - rohm,rstbmode-level: The RSTB signal is configured for level mode, to + accommodate a toggle power switch (the RSTBMODE pin is + strapped low). + - rohm,rstbmode-pulse: The RSTB signal is configured for pulse mode, to + accommodate a momentary power switch (the RSTBMODE pin + is strapped high). + The two properties above are mutually exclusive. + Example: pmic: pmic@30 { @@ -36,6 +55,8 @@ Example: #interrupt-cells = <2>; gpio-controller; #gpio-cells = <2>; + rohm,ddr-backup-power = <0xf>; + rohm,rstbmode-pulse; regulators { dvfs: dvfs { diff --git a/Documentation/devicetree/bindings/regulator/pfuze100.txt b/Documentation/devicetree/bindings/regulator/pfuze100.txt index c6dd3f5e485b..f0ada3b14d70 100644 --- a/Documentation/devicetree/bindings/regulator/pfuze100.txt +++ b/Documentation/devicetree/bindings/regulator/pfuze100.txt @@ -21,7 +21,7 @@ Each regulator is defined using the standard binding for regulators. Example 1: PFUZE100 - pmic: pfuze100@8 { + pfuze100: pmic@8 { compatible = "fsl,pfuze100"; reg = <0x08>; @@ -122,7 +122,7 @@ Example 1: PFUZE100 Example 2: PFUZE200 - pmic: pfuze200@8 { + pfuze200: pmic@8 { compatible = "fsl,pfuze200"; reg = <0x08>; @@ -216,7 +216,7 @@ Example 2: PFUZE200 Example 3: PFUZE3000 - pmic: pfuze3000@8 { + pfuze3000: pmic@8 { compatible = "fsl,pfuze3000"; reg = <0x08>; diff --git a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt index 57d2c65899df..406f2e570c50 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt @@ -110,6 +110,11 @@ Qualcomm SPMI Regulators Definition: Reference to regulator supplying the input pin, as described in the data sheet. +- qcom,saw-reg: + Usage: optional + Value type: <phandle> + Description: Reference to syscon node defining the SAW registers. + The regulator node houses sub-nodes for each regulator within the device. Each sub-node is identified using the node's name, with valid values listed for each @@ -201,6 +206,17 @@ see regulator.txt - with additional custom properties described below: 2 = 0.55 uA 3 = 0.75 uA +- qcom,saw-slave: + Usage: optional + Value type: <boo> + Description: SAW controlled gang slave. Will not be configured. + +- qcom,saw-leader: + Usage: optional + Value type: <boo> + Description: SAW controlled gang leader. Will be configured as + SAW regulator. + Example: regulators { @@ -221,3 +237,32 @@ Example: .... }; + +Example 2: + + saw3: syscon@9A10000 { + compatible = "syscon"; + reg = <0x9A10000 0x1000>; + }; + + ... + + spm-regulators { + compatible = "qcom,pm8994-regulators"; + qcom,saw-reg = <&saw3>; + s8 { + qcom,saw-slave; + }; + s9 { + qcom,saw-slave; + }; + s10 { + qcom,saw-slave; + }; + pm8994_s11_saw: s11 { + qcom,saw-leader; + regulator-always-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1140000>; + }; + }; diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt index 2babe15b618d..a7cd36877bfe 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.txt +++ b/Documentation/devicetree/bindings/regulator/regulator.txt @@ -59,6 +59,11 @@ Optional properties: - regulator-initial-mode: initial operating mode. The set of possible operating modes depends on the capabilities of every hardware so each device binding documentation explains which values the regulator supports. +- regulator-allowed-modes: list of operating modes that software is allowed to + configure for the regulator at run-time. Elements may be specified in any + order. The set of possible operating modes depends on the capabilities of + every hardware so each device binding document explains which values the + regulator supports. - regulator-system-load: Load in uA present on regulator that is not captured by any consumer request. - regulator-pull-down: Enable pull down resistor when the regulator is disabled. @@ -68,6 +73,11 @@ Optional properties: 0: Disable active discharge. 1: Enable active discharge. Absence of this property will leave configuration to default. +- regulator-coupled-with: Regulators with which the regulator + is coupled. The linkage is 2-way - all coupled regulators should be linked + with each other. A regulator should not be coupled with its supplier. +- regulator-coupled-max-spread: Max spread between voltages of coupled regulators + in microvolts. Deprecated properties: - regulator-compatible: If a regulator chip contains multiple diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.txt b/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.txt new file mode 100644 index 000000000000..4edf3137d9f7 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.txt @@ -0,0 +1,126 @@ +ROHM BD71837 Power Management Integrated Circuit (PMIC) regulator bindings + +BD71837MWV is a programmable Power Management +IC (PMIC) for powering single-core, dual-core, and +quad-core SoC’s such as NXP-i.MX 8M. It is optimized +for low BOM cost and compact solution footprint. It +integrates 8 Buck regulators and 7 LDO’s to provide all +the power rails required by the SoC and the commonly +used peripherals. + +Required properties: + - regulator-name: should be "buck1", ..., "buck8" and "ldo1", ..., "ldo7" + +List of regulators provided by this controller. BD71837 regulators node +should be sub node of the BD71837 MFD node. See BD71837 MFD bindings at +Documentation/devicetree/bindings/mfd/rohm,bd71837-pmic.txt +Regulator nodes should be named to BUCK_<number> and LDO_<number>. The +definition for each of these nodes is defined using the standard +binding for regulators at +Documentation/devicetree/bindings/regulator/regulator.txt. +Note that if BD71837 starts at RUN state you probably want to use +regulator-boot-on at least for BUCK6 and BUCK7 so that those are not +disabled by driver at startup. LDO5 and LDO6 are supplied by those and +if they are disabled at startup the voltage monitoring for LDO5/LDO6 will +cause PMIC to reset. + +The valid names for regulator nodes are: +BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6, BUCK7, BUCK8 +LDO1, LDO2, LDO3, LDO4, LDO5, LDO6, LDO7 + +Optional properties: +- Any optional property defined in bindings/regulator/regulator.txt + +Example: +regulators { + buck1: BUCK1 { + regulator-name = "buck1"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1300000>; + regulator-boot-on; + regulator-ramp-delay = <1250>; + }; + buck2: BUCK2 { + regulator-name = "buck2"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1300000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <1250>; + }; + buck3: BUCK3 { + regulator-name = "buck3"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1300000>; + regulator-boot-on; + }; + buck4: BUCK4 { + regulator-name = "buck4"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1300000>; + regulator-boot-on; + }; + buck5: BUCK5 { + regulator-name = "buck5"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1350000>; + regulator-boot-on; + }; + buck6: BUCK6 { + regulator-name = "buck6"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + buck7: BUCK7 { + regulator-name = "buck7"; + regulator-min-microvolt = <1605000>; + regulator-max-microvolt = <1995000>; + regulator-boot-on; + }; + buck8: BUCK8 { + regulator-name = "buck8"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1400000>; + }; + + ldo1: LDO1 { + regulator-name = "ldo1"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + ldo2: LDO2 { + regulator-name = "ldo2"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-boot-on; + }; + ldo3: LDO3 { + regulator-name = "ldo3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + ldo4: LDO4 { + regulator-name = "ldo4"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1800000>; + }; + ldo5: LDO5 { + regulator-name = "ldo5"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + ldo6: LDO6 { + regulator-name = "ldo6"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1800000>; + }; + ldo7_reg: LDO7 { + regulator-name = "ldo7"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; +}; + + diff --git a/Documentation/devicetree/bindings/regulator/sy8106a-regulator.txt b/Documentation/devicetree/bindings/regulator/sy8106a-regulator.txt new file mode 100644 index 000000000000..39a8ca73f572 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/sy8106a-regulator.txt @@ -0,0 +1,23 @@ +SY8106A Voltage regulator + +Required properties: +- compatible: Must be "silergy,sy8106a" +- reg: I2C slave address - must be <0x65> +- silergy,fixed-microvolt - the voltage when I2C regulating is disabled (set + by external resistor like a fixed voltage) + +Any property defined as part of the core regulator binding, defined in +./regulator.txt, can also be used. + +Example: + + sy8106a { + compatible = "silergy,sy8106a"; + reg = <0x65>; + regulator-name = "sy8106a-vdd"; + silergy,fixed-microvolt = <1200000>; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + regulator-always-on; + }; diff --git a/MAINTAINERS b/MAINTAINERS index abec3381cf45..d51226a23345 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13609,6 +13609,12 @@ S: Supported F: net/switchdev/ F: include/net/switchdev.h +SY8106A REGULATOR DRIVER +M: Icenowy Zheng <icenowy@aosc.io> +S: Maintained +F: drivers/regulator/sy8106a-regulator.c +F: Documentation/devicetree/bindings/regulator/sy8106a-regulator.txt + SYNC FILE FRAMEWORK M: Sumit Semwal <sumit.semwal@linaro.org> R: Gustavo Padovan <gustavo@padovan.org> diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c index f00988705408..5aa472892465 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c @@ -9,6 +9,7 @@ #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/spi/spi.h> +#include <linux/gpio/machine.h> #include <linux/mfd/wm831x/irq.h> #include <linux/mfd/wm831x/gpio.h> @@ -206,9 +207,6 @@ static const struct i2c_board_info wm1277_devs[] = { }; static struct arizona_pdata wm5102_reva_pdata = { - .ldo1 = { - .ldoena = S3C64XX_GPN(7), - }, .gpio_base = CODEC_GPIO_BASE, .irq_flags = IRQF_TRIGGER_HIGH, .micd_pol_gpio = CODEC_GPIO_BASE + 4, @@ -237,10 +235,16 @@ static struct spi_board_info wm5102_reva_spi_devs[] = { }, }; -static struct arizona_pdata wm5102_pdata = { - .ldo1 = { - .ldoena = S3C64XX_GPN(7), +static struct gpiod_lookup_table wm5102_reva_gpiod_table = { + .dev_id = "spi0.1", /* SPI device name */ + .table = { + GPIO_LOOKUP("GPION", 7, + "wlf,ldoena", GPIO_ACTIVE_HIGH), + { }, }, +}; + +static struct arizona_pdata wm5102_pdata = { .gpio_base = CODEC_GPIO_BASE, .irq_flags = IRQF_TRIGGER_HIGH, .micd_pol_gpio = CODEC_GPIO_BASE + 2, @@ -264,6 +268,15 @@ static struct spi_board_info wm5102_spi_devs[] = { }, }; +static struct gpiod_lookup_table wm5102_gpiod_table = { + .dev_id = "spi0.1", /* SPI device name */ + .table = { + GPIO_LOOKUP("GPION", 7, + "wlf,ldo1ena", GPIO_ACTIVE_HIGH), + { }, + }, +}; + static struct spi_board_info wm5110_spi_devs[] = { [0] = { .modalias = "wm5110", @@ -366,6 +379,9 @@ static int wlf_gf_module_probe(struct i2c_client *i2c, rev == gf_mods[i].rev)) break; + gpiod_add_lookup_table(&wm5102_reva_gpiod_table); + gpiod_add_lookup_table(&wm5102_gpiod_table); + if (i < ARRAY_SIZE(gf_mods)) { dev_info(&i2c->dev, "%s revision %d\n", gf_mods[i].name, rev + 1); diff --git a/drivers/mfd/bd9571mwv.c b/drivers/mfd/bd9571mwv.c index 64e088dfe7b0..503979c81dae 100644 --- a/drivers/mfd/bd9571mwv.c +++ b/drivers/mfd/bd9571mwv.c @@ -29,6 +29,7 @@ static const struct mfd_cell bd9571mwv_cells[] = { static const struct regmap_range bd9571mwv_readable_yes_ranges[] = { regmap_reg_range(BD9571MWV_VENDOR_CODE, BD9571MWV_PRODUCT_REVISION), + regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT), regmap_reg_range(BD9571MWV_AVS_SET_MONI, BD9571MWV_AVS_DVFS_VID(3)), regmap_reg_range(BD9571MWV_VD18_VID, BD9571MWV_VD33_VID), regmap_reg_range(BD9571MWV_DVFS_VINIT, BD9571MWV_DVFS_VINIT), @@ -44,6 +45,7 @@ static const struct regmap_access_table bd9571mwv_readable_table = { }; static const struct regmap_range bd9571mwv_writable_yes_ranges[] = { + regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT), regmap_reg_range(BD9571MWV_AVS_VD09_VID(0), BD9571MWV_AVS_VD09_VID(3)), regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_SETVID), regmap_reg_range(BD9571MWV_GPIO_DIR, BD9571MWV_GPIO_OUT), diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 097f61784a7d..5dbccf5f3037 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -180,6 +180,17 @@ config REGULATOR_BCM590XX BCM590xx PMUs. This will enable support for the software controllable LDO/Switching regulators. +config REGULATOR_BD71837 + tristate "ROHM BD71837 Power Regulator" + depends on MFD_BD71837 + help + This driver supports voltage regulators on ROHM BD71837 PMIC. + This will enable support for the software controllable buck + and LDO regulators. + + This driver can also be built as a module. If so, the module + will be called bd71837-regulator. + config REGULATOR_BD9571MWV tristate "ROHM BD9571MWV Regulators" depends on MFD_BD9571MWV @@ -801,6 +812,13 @@ config REGULATOR_STW481X_VMMC This driver supports the internal VMMC regulator in the STw481x PMIC chips. +config REGULATOR_SY8106A + tristate "Silergy SY8106A regulator" + depends on I2C && (OF || COMPILE_TEST) + select REGMAP_I2C + help + This driver supports SY8106A single output regulator. + config REGULATOR_TPS51632 tristate "TI TPS51632 Power Regulator" depends on I2C diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 590674fbecd7..bd818ceb7c72 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o +obj-$(CONFIG_REGULATOR_BD71837) += bd71837-regulator.o obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o obj-$(CONFIG_REGULATOR_DA903X) += da903x.o obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o @@ -100,6 +101,7 @@ obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o +obj-$(CONFIG_REGULATOR_SY8106A) += sy8106a-regulator.o obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o @@ -125,5 +127,4 @@ obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o - ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 0f97514e3474..83dba3fbfe0c 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -132,33 +132,6 @@ static const unsigned int ldo_vaux56_voltages[] = { 2790000, }; -static const unsigned int ldo_vaux3_ab8540_voltages[] = { - 1200000, - 1500000, - 1800000, - 2100000, - 2500000, - 2750000, - 2790000, - 2910000, - 3050000, -}; - -static const unsigned int ldo_vaux56_ab8540_voltages[] = { - 750000, 760000, 770000, 780000, 790000, 800000, - 810000, 820000, 830000, 840000, 850000, 860000, - 870000, 880000, 890000, 900000, 910000, 920000, - 930000, 940000, 950000, 960000, 970000, 980000, - 990000, 1000000, 1010000, 1020000, 1030000, - 1040000, 1050000, 1060000, 1070000, 1080000, - 1090000, 1100000, 1110000, 1120000, 1130000, - 1140000, 1150000, 1160000, 1170000, 1180000, - 1190000, 1200000, 1210000, 1220000, 1230000, - 1240000, 1250000, 1260000, 1270000, 1280000, - 1290000, 1300000, 1310000, 1320000, 1330000, - 1340000, 1350000, 1360000, 1800000, 2790000, -}; - static const unsigned int ldo_vintcore_voltages[] = { 1200000, 1225000, @@ -232,8 +205,6 @@ static const unsigned int ldo_vdmic_voltages[] = { static DEFINE_MUTEX(shared_mode_mutex); static struct ab8500_shared_mode ldo_anamic1_shared; static struct ab8500_shared_mode ldo_anamic2_shared; -static struct ab8500_shared_mode ab8540_ldo_anamic1_shared; -static struct ab8500_shared_mode ab8540_ldo_anamic2_shared; static int ab8500_regulator_enable(struct regulator_dev *rdev) { @@ -507,53 +478,6 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) return (regval & info->voltage_mask) >> voltage_shift; } -static int ab8540_aux3_regulator_get_voltage_sel(struct regulator_dev *rdev) -{ - int ret, voltage_shift; - struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - u8 regval, regval_expand; - - if (info == NULL) { - dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); - return -EINVAL; - } - - ret = abx500_get_register_interruptible(info->dev, - info->expand_register.voltage_bank, - info->expand_register.voltage_reg, ®val_expand); - if (ret < 0) { - dev_err(rdev_get_dev(rdev), - "couldn't read voltage expand reg for regulator\n"); - return ret; - } - - dev_vdbg(rdev_get_dev(rdev), - "%s-get_voltage expand (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", - info->desc.name, info->expand_register.voltage_bank, - info->expand_register.voltage_reg, - info->expand_register.voltage_mask, regval_expand); - - if (regval_expand & info->expand_register.voltage_mask) - return info->expand_register.voltage_limit; - - ret = abx500_get_register_interruptible(info->dev, - info->voltage_bank, info->voltage_reg, ®val); - if (ret < 0) { - dev_err(rdev_get_dev(rdev), - "couldn't read voltage reg for regulator\n"); - return ret; - } - - dev_vdbg(rdev_get_dev(rdev), - "%s-get_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", - info->desc.name, info->voltage_bank, info->voltage_reg, - info->voltage_mask, regval); - - voltage_shift = ffs(info->voltage_mask) - 1; - - return (regval & info->voltage_mask) >> voltage_shift; -} - static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { @@ -586,61 +510,6 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, return ret; } -static int ab8540_aux3_regulator_set_voltage_sel(struct regulator_dev *rdev, - unsigned selector) -{ - int ret; - struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - u8 regval, regval_expand; - - if (info == NULL) { - dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); - return -EINVAL; - } - - if (selector < info->expand_register.voltage_limit) { - int voltage_shift = ffs(info->voltage_mask) - 1; - - regval = (u8)selector << voltage_shift; - ret = abx500_mask_and_set_register_interruptible(info->dev, - info->voltage_bank, info->voltage_reg, - info->voltage_mask, regval); - if (ret < 0) { - dev_err(rdev_get_dev(rdev), - "couldn't set voltage reg for regulator\n"); - return ret; - } - - dev_vdbg(rdev_get_dev(rdev), - "%s-set_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", - info->desc.name, info->voltage_bank, info->voltage_reg, - info->voltage_mask, regval); - - regval_expand = 0; - } else { - regval_expand = info->expand_register.voltage_mask; - } - - ret = abx500_mask_and_set_register_interruptible(info->dev, - info->expand_register.voltage_bank, - info->expand_register.voltage_reg, - info->expand_register.voltage_mask, - regval_expand); - if (ret < 0) { - dev_err(rdev_get_dev(rdev), - "couldn't set expand voltage reg for regulator\n"); - return ret; - } - - dev_vdbg(rdev_get_dev(rdev), - "%s-set_voltage expand (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", - info->desc.name, info->expand_register.voltage_bank, - info->expand_register.voltage_reg, - info->expand_register.voltage_mask, regval_expand); - - return 0; -} - static struct regulator_ops ab8500_regulator_volt_mode_ops = { .enable = ab8500_regulator_enable, .disable = ab8500_regulator_disable, @@ -653,18 +522,6 @@ static struct regulator_ops ab8500_regulator_volt_mode_ops = { .list_voltage = regulator_list_voltage_table, }; -static struct regulator_ops ab8540_aux3_regulator_volt_mode_ops = { - .enable = ab8500_regulator_enable, - .disable = ab8500_regulator_disable, - .get_optimum_mode = ab8500_regulator_get_optimum_mode, - .set_mode = ab8500_regulator_set_mode, - .get_mode = ab8500_regulator_get_mode, - .is_enabled = ab8500_regulator_is_enabled, - .get_voltage_sel = ab8540_aux3_regulator_get_voltage_sel, - .set_voltage_sel = ab8540_aux3_regulator_set_voltage_sel, - .list_voltage = regulator_list_voltage_table, -}; - static struct regulator_ops ab8500_regulator_volt_ops = { .enable = ab8500_regulator_enable, .disable = ab8500_regulator_disable, @@ -1217,562 +1074,6 @@ static struct ab8500_regulator_info }, }; -/* AB9540 regulator information */ -static struct ab8500_regulator_info - ab9540_regulator_info[AB9540_NUM_REGULATORS] = { - /* - * Variable Voltage Regulators - * name, min mV, max mV, - * update bank, reg, mask, enable val - * volt bank, reg, mask - */ - [AB9540_LDO_AUX1] = { - .desc = { - .name = "LDO-AUX1", - .ops = &ab8500_regulator_volt_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_AUX1, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), - .volt_table = ldo_vauxn_voltages, - }, - .load_lp_uA = 5000, - .update_bank = 0x04, - .update_reg = 0x09, - .update_mask = 0x03, - .update_val = 0x01, - .update_val_idle = 0x03, - .update_val_normal = 0x01, - .voltage_bank = 0x04, - .voltage_reg = 0x1f, - .voltage_mask = 0x0f, - }, - [AB9540_LDO_AUX2] = { - .desc = { - .name = "LDO-AUX2", - .ops = &ab8500_regulator_volt_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_AUX2, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), - .volt_table = ldo_vauxn_voltages, - }, - .load_lp_uA = 5000, - .update_bank = 0x04, - .update_reg = 0x09, - .update_mask = 0x0c, - .update_val = 0x04, - .update_val_idle = 0x0c, - .update_val_normal = 0x04, - .voltage_bank = 0x04, - .voltage_reg = 0x20, - .voltage_mask = 0x0f, - }, - [AB9540_LDO_AUX3] = { - .desc = { - .name = "LDO-AUX3", - .ops = &ab8500_regulator_volt_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_AUX3, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), - .volt_table = ldo_vaux3_voltages, - }, - .load_lp_uA = 5000, - .update_bank = 0x04, - .update_reg = 0x0a, - .update_mask = 0x03, - .update_val = 0x01, - .update_val_idle = 0x03, - .update_val_normal = 0x01, - .voltage_bank = 0x04, - .voltage_reg = 0x21, - .voltage_mask = 0x07, - }, - [AB9540_LDO_AUX4] = { - .desc = { - .name = "LDO-AUX4", - .ops = &ab8500_regulator_volt_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_AUX4, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), - .volt_table = ldo_vauxn_voltages, - }, - .load_lp_uA = 5000, - /* values for Vaux4Regu register */ - .update_bank = 0x04, - .update_reg = 0x2e, - .update_mask = 0x03, - .update_val = 0x01, - .update_val_idle = 0x03, - .update_val_normal = 0x01, - /* values for Vaux4SEL register */ - .voltage_bank = 0x04, - .voltage_reg = 0x2f, - .voltage_mask = 0x0f, - }, - [AB9540_LDO_INTCORE] = { - .desc = { - .name = "LDO-INTCORE", - .ops = &ab8500_regulator_volt_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_INTCORE, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), - .volt_table = ldo_vintcore_voltages, - }, - .load_lp_uA = 5000, - .update_bank = 0x03, - .update_reg = 0x80, - .update_mask = 0x44, - .update_val = 0x44, - .update_val_idle = 0x44, - .update_val_normal = 0x04, - .voltage_bank = 0x03, - .voltage_reg = 0x80, - .voltage_mask = 0x38, - }, - - /* - * Fixed Voltage Regulators - * name, fixed mV, - * update bank, reg, mask, enable val - */ - [AB9540_LDO_TVOUT] = { - .desc = { - .name = "LDO-TVOUT", - .ops = &ab8500_regulator_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_TVOUT, - .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_2000000_voltage, - .enable_time = 10000, - }, - .load_lp_uA = 1000, - .update_bank = 0x03, - .update_reg = 0x80, - .update_mask = 0x82, - .update_val = 0x02, - .update_val_idle = 0x82, - .update_val_normal = 0x02, - }, - [AB9540_LDO_USB] = { - .desc = { - .name = "LDO-USB", - .ops = &ab8500_regulator_ops, - .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_USB, - .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_3300000_voltage, - }, - .update_bank = 0x03, - .update_reg = 0x82, - .update_mask = 0x03, - .update_val = 0x01, - .update_val_idle = 0x03, - .update_val_normal = 0x01, - }, - [AB9540_LDO_AUDIO] = { - .desc = { - .name = "LDO-AUDIO", - .ops = &ab8500_regulator_ops, - .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_AUDIO, - .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_2000000_voltage, - }, - .update_bank = 0x03, - .update_reg = 0x83, - .update_mask = 0x02, - .update_val = 0x02, - }, - [AB9540_LDO_ANAMIC1] = { - .desc = { - .name = "LDO-ANAMIC1", - .ops = &ab8500_regulator_ops, - .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_ANAMIC1, - .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_2050000_voltage, - }, - .update_bank = 0x03, - .update_reg = 0x83, - .update_mask = 0x08, - .update_val = 0x08, - }, - [AB9540_LDO_ANAMIC2] = { - .desc = { - .name = "LDO-ANAMIC2", - .ops = &ab8500_regulator_ops, - .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_ANAMIC2, - .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_2050000_voltage, - }, - .update_bank = 0x03, - .update_reg = 0x83, - .update_mask = 0x10, - .update_val = 0x10, - }, - [AB9540_LDO_DMIC] = { - .desc = { - .name = "LDO-DMIC", - .ops = &ab8500_regulator_ops, - .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_DMIC, - .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_1800000_voltage, - }, - .update_bank = 0x03, - .update_reg = 0x83, - .update_mask = 0x04, - .update_val = 0x04, - }, - - /* - * Regulators with fixed voltage and normal/idle modes - */ - [AB9540_LDO_ANA] = { - .desc = { - .name = "LDO-ANA", - .ops = &ab8500_regulator_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_ANA, - .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_1200000_voltage, - }, - .load_lp_uA = 1000, - .update_bank = 0x04, - .update_reg = 0x06, - .update_mask = 0x0c, - .update_val = 0x08, - .update_val_idle = 0x0c, - .update_val_normal = 0x08, - }, -}; - -/* AB8540 regulator information */ -static struct ab8500_regulator_info - ab8540_regulator_info[AB8540_NUM_REGULATORS] = { - /* - * Variable Voltage Regulators - * name, min mV, max mV, - * update bank, reg, mask, enable val - * volt bank, reg, mask - */ - [AB8540_LDO_AUX1] = { - .desc = { - .name = "LDO-AUX1", - .ops = &ab8500_regulator_volt_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8540_LDO_AUX1, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), - .volt_table = ldo_vauxn_voltages, - }, - .load_lp_uA = 5000, - .update_bank = 0x04, - .update_reg = 0x09, - .update_mask = 0x03, - .update_val = 0x01, - .update_val_idle = 0x03, - .update_val_normal = 0x01, - .voltage_bank = 0x04, - .voltage_reg = 0x1f, - .voltage_mask = 0x0f, - }, - [AB8540_LDO_AUX2] = { - .desc = { - .name = "LDO-AUX2", - .ops = &ab8500_regulator_volt_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8540_LDO_AUX2, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), - .volt_table = ldo_vauxn_voltages, - }, - .load_lp_uA = 5000, - .update_bank = 0x04, - .update_reg = 0x09, - .update_mask = 0x0c, - .update_val = 0x04, - .update_val_idle = 0x0c, - .update_val_normal = 0x04, - .voltage_bank = 0x04, - .voltage_reg = 0x20, - .voltage_mask = 0x0f, - }, - [AB8540_LDO_AUX3] = { - .desc = { - .name = "LDO-AUX3", - .ops = &ab8540_aux3_regulator_volt_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8540_LDO_AUX3, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vaux3_ab8540_voltages), - .volt_table = ldo_vaux3_ab8540_voltages, - }, - .load_lp_uA = 5000, - .update_bank = 0x04, - .update_reg = 0x0a, - .update_mask = 0x03, - .update_val = 0x01, - .update_val_idle = 0x03, - .update_val_normal = 0x01, - .voltage_bank = 0x04, - .voltage_reg = 0x21, - .voltage_mask = 0x07, - .expand_register = { - .voltage_limit = 8, - .voltage_bank = 0x04, - .voltage_reg = 0x01, - .voltage_mask = 0x10, - } - }, - [AB8540_LDO_AUX4] = { - .desc = { - .name = "LDO-AUX4", - .ops = &ab8500_regulator_volt_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8540_LDO_AUX4, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), - .volt_table = ldo_vauxn_voltages, - }, - .load_lp_uA = 5000, - /* values for Vaux4Regu register */ - .update_bank = 0x04, - .update_reg = 0x2e, - .update_mask = 0x03, - .update_val = 0x01, - .update_val_idle = 0x03, - .update_val_normal = 0x01, - /* values for Vaux4SEL register */ - .voltage_bank = 0x04, - .voltage_reg = 0x2f, - .voltage_mask = 0x0f, - }, - [AB8540_LDO_AUX5] = { - .desc = { - .name = "LDO-AUX5", - .ops = &ab8500_regulator_volt_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8540_LDO_AUX5, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vaux56_ab8540_voltages), - .volt_table = ldo_vaux56_ab8540_voltages, - }, - .load_lp_uA = 20000, - /* values for Vaux5Regu register */ - .update_bank = 0x04, - .update_reg = 0x32, - .update_mask = 0x03, - .update_val = 0x01, - .update_val_idle = 0x03, - .update_val_normal = 0x01, - /* values for Vaux5SEL register */ - .voltage_bank = 0x04, - .voltage_reg = 0x33, - .voltage_mask = 0x3f, - }, - [AB8540_LDO_AUX6] = { - .desc = { - .name = "LDO-AUX6", - .ops = &ab8500_regulator_volt_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8540_LDO_AUX6, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vaux56_ab8540_voltages), - .volt_table = ldo_vaux56_ab8540_voltages, - }, - .load_lp_uA = 20000, - /* values for Vaux6Regu register */ - .update_bank = 0x04, - .update_reg = 0x35, - .update_mask = 0x03, - .update_val = 0x01, - .update_val_idle = 0x03, - .update_val_normal = 0x01, - /* values for Vaux6SEL register */ - .voltage_bank = 0x04, - .voltage_reg = 0x36, - .voltage_mask = 0x3f, - }, - [AB8540_LDO_INTCORE] = { - .desc = { - .name = "LDO-INTCORE", - .ops = &ab8500_regulator_volt_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8540_LDO_INTCORE, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), - .volt_table = ldo_vintcore_voltages, - }, - .load_lp_uA = 5000, - .update_bank = 0x03, - .update_reg = 0x80, - .update_mask = 0x44, - .update_val = 0x44, - .update_val_idle = 0x44, - .update_val_normal = 0x04, - .voltage_bank = 0x03, - .voltage_reg = 0x80, - .voltage_mask = 0x38, - }, - - /* - * Fixed Voltage Regulators - * name, fixed mV, - * update bank, reg, mask, enable val - */ - [AB8540_LDO_TVOUT] = { - .desc = { - .name = "LDO-TVOUT", - .ops = &ab8500_regulator_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8540_LDO_TVOUT, - .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_2000000_voltage, - .enable_time = 10000, - }, - .load_lp_uA = 1000, - .update_bank = 0x03, - .update_reg = 0x80, - .update_mask = 0x82, - .update_val = 0x02, - .update_val_idle = 0x82, - .update_val_normal = 0x02, - }, - [AB8540_LDO_AUDIO] = { - .desc = { - .name = "LDO-AUDIO", - .ops = &ab8500_regulator_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8540_LDO_AUDIO, - .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_2000000_voltage, - }, - .update_bank = 0x03, - .update_reg = 0x83, - .update_mask = 0x02, - .update_val = 0x02, - }, - [AB8540_LDO_ANAMIC1] = { - .desc = { - .name = "LDO-ANAMIC1", - .ops = &ab8500_regulator_anamic_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8540_LDO_ANAMIC1, - .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_2050000_voltage, - }, - .shared_mode = &ab8540_ldo_anamic1_shared, - .update_bank = 0x03, - .update_reg = 0x83, - .update_mask = 0x08, - .update_val = 0x08, - .mode_bank = 0x03, - .mode_reg = 0x83, - .mode_mask = 0x20, - .mode_val_idle = 0x20, - .mode_val_normal = 0x00, - }, - [AB8540_LDO_ANAMIC2] = { - .desc = { - .name = "LDO-ANAMIC2", - .ops = &ab8500_regulator_anamic_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8540_LDO_ANAMIC2, - .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_2050000_voltage, - }, - .shared_mode = &ab8540_ldo_anamic2_shared, - .update_bank = 0x03, - .update_reg = 0x83, - .update_mask = 0x10, - .update_val = 0x10, - .mode_bank = 0x03, - .mode_reg = 0x83, - .mode_mask = 0x20, - .mode_val_idle = 0x20, - .mode_val_normal = 0x00, - }, - [AB8540_LDO_DMIC] = { - .desc = { - .name = "LDO-DMIC", - .ops = &ab8500_regulator_volt_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8540_LDO_DMIC, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vdmic_voltages), - .volt_table = ldo_vdmic_voltages, - }, - .load_lp_uA = 1000, - .update_bank = 0x03, - .update_reg = 0x83, - .update_mask = 0x04, - .update_val = 0x04, - .voltage_bank = 0x03, - .voltage_reg = 0x83, - .voltage_mask = 0xc0, - }, - - /* - * Regulators with fixed voltage and normal/idle modes - */ - [AB8540_LDO_ANA] = { - .desc = { - .name = "LDO-ANA", - .ops = &ab8500_regulator_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8540_LDO_ANA, - .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_1200000_voltage, - }, - .load_lp_uA = 1000, - .update_bank = 0x04, - .update_reg = 0x06, - .update_mask = 0x0c, - .update_val = 0x04, - .update_val_idle = 0x0c, - .update_val_normal = 0x04, - }, - [AB8540_LDO_SDIO] = { - .desc = { - .name = "LDO-SDIO", - .ops = &ab8500_regulator_volt_mode_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8540_LDO_SDIO, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_sdio_voltages), - .volt_table = ldo_sdio_voltages, - }, - .load_lp_uA = 5000, - .update_bank = 0x03, - .update_reg = 0x88, - .update_mask = 0x30, - .update_val = 0x10, - .update_val_idle = 0x30, - .update_val_normal = 0x10, - .voltage_bank = 0x03, - .voltage_reg = 0x88, - .voltage_mask = 0x07, - }, -}; - static struct ab8500_shared_mode ldo_anamic1_shared = { .shared_regulator = &ab8505_regulator_info[AB8505_LDO_ANAMIC2], }; @@ -1781,14 +1082,6 @@ static struct ab8500_shared_mode ldo_anamic2_shared = { .shared_regulator = &ab8505_regulator_info[AB8505_LDO_ANAMIC1], }; -static struct ab8500_shared_mode ab8540_ldo_anamic1_shared = { - .shared_regulator = &ab8540_regulator_info[AB8540_LDO_ANAMIC2], -}; - -static struct ab8500_shared_mode ab8540_ldo_anamic2_shared = { - .shared_regulator = &ab8540_regulator_info[AB8540_LDO_ANAMIC1], -}; - struct ab8500_reg_init { u8 bank; u8 addr; @@ -2243,659 +1536,6 @@ static struct ab8500_reg_init ab8505_reg_init[] = { REG_INIT(AB8505_CTRLVAUX6, 0x01, 0x56, 0x9f), }; -/* AB9540 register init */ -static struct ab8500_reg_init ab9540_reg_init[] = { - /* - * 0x03, VarmRequestCtrl - * 0x0c, VapeRequestCtrl - * 0x30, Vsmps1RequestCtrl - * 0xc0, Vsmps2RequestCtrl - */ - REG_INIT(AB9540_REGUREQUESTCTRL1, 0x03, 0x03, 0xff), - /* - * 0x03, Vsmps3RequestCtrl - * 0x0c, VpllRequestCtrl - * 0x30, VanaRequestCtrl - * 0xc0, VextSupply1RequestCtrl - */ - REG_INIT(AB9540_REGUREQUESTCTRL2, 0x03, 0x04, 0xff), - /* - * 0x03, VextSupply2RequestCtrl - * 0x0c, VextSupply3RequestCtrl - * 0x30, Vaux1RequestCtrl - * 0xc0, Vaux2RequestCtrl - */ - REG_INIT(AB9540_REGUREQUESTCTRL3, 0x03, 0x05, 0xff), - /* - * 0x03, Vaux3RequestCtrl - * 0x04, SwHPReq - */ - REG_INIT(AB9540_REGUREQUESTCTRL4, 0x03, 0x06, 0x07), - /* - * 0x01, Vsmps1SysClkReq1HPValid - * 0x02, Vsmps2SysClkReq1HPValid - * 0x04, Vsmps3SysClkReq1HPValid - * 0x08, VanaSysClkReq1HPValid - * 0x10, VpllSysClkReq1HPValid - * 0x20, Vaux1SysClkReq1HPValid - * 0x40, Vaux2SysClkReq1HPValid - * 0x80, Vaux3SysClkReq1HPValid - */ - REG_INIT(AB9540_REGUSYSCLKREQ1HPVALID1, 0x03, 0x07, 0xff), - /* - * 0x01, VapeSysClkReq1HPValid - * 0x02, VarmSysClkReq1HPValid - * 0x04, VbbSysClkReq1HPValid - * 0x08, VmodSysClkReq1HPValid - * 0x10, VextSupply1SysClkReq1HPValid - * 0x20, VextSupply2SysClkReq1HPValid - * 0x40, VextSupply3SysClkReq1HPValid - */ - REG_INIT(AB9540_REGUSYSCLKREQ1HPVALID2, 0x03, 0x08, 0x7f), - /* - * 0x01, Vsmps1HwHPReq1Valid - * 0x02, Vsmps2HwHPReq1Valid - * 0x04, Vsmps3HwHPReq1Valid - * 0x08, VanaHwHPReq1Valid - * 0x10, VpllHwHPReq1Valid - * 0x20, Vaux1HwHPReq1Valid - * 0x40, Vaux2HwHPReq1Valid - * 0x80, Vaux3HwHPReq1Valid - */ - REG_INIT(AB9540_REGUHWHPREQ1VALID1, 0x03, 0x09, 0xff), - /* - * 0x01, VextSupply1HwHPReq1Valid - * 0x02, VextSupply2HwHPReq1Valid - * 0x04, VextSupply3HwHPReq1Valid - * 0x08, VmodHwHPReq1Valid - */ - REG_INIT(AB9540_REGUHWHPREQ1VALID2, 0x03, 0x0a, 0x0f), - /* - * 0x01, Vsmps1HwHPReq2Valid - * 0x02, Vsmps2HwHPReq2Valid - * 0x03, Vsmps3HwHPReq2Valid - * 0x08, VanaHwHPReq2Valid - * 0x10, VpllHwHPReq2Valid - * 0x20, Vaux1HwHPReq2Valid - * 0x40, Vaux2HwHPReq2Valid - * 0x80, Vaux3HwHPReq2Valid - */ - REG_INIT(AB9540_REGUHWHPREQ2VALID1, 0x03, 0x0b, 0xff), - /* - * 0x01, VextSupply1HwHPReq2Valid - * 0x02, VextSupply2HwHPReq2Valid - * 0x04, VextSupply3HwHPReq2Valid - * 0x08, VmodHwHPReq2Valid - */ - REG_INIT(AB9540_REGUHWHPREQ2VALID2, 0x03, 0x0c, 0x0f), - /* - * 0x01, VapeSwHPReqValid - * 0x02, VarmSwHPReqValid - * 0x04, Vsmps1SwHPReqValid - * 0x08, Vsmps2SwHPReqValid - * 0x10, Vsmps3SwHPReqValid - * 0x20, VanaSwHPReqValid - * 0x40, VpllSwHPReqValid - * 0x80, Vaux1SwHPReqValid - */ - REG_INIT(AB9540_REGUSWHPREQVALID1, 0x03, 0x0d, 0xff), - /* - * 0x01, Vaux2SwHPReqValid - * 0x02, Vaux3SwHPReqValid - * 0x04, VextSupply1SwHPReqValid - * 0x08, VextSupply2SwHPReqValid - * 0x10, VextSupply3SwHPReqValid - * 0x20, VmodSwHPReqValid - */ - REG_INIT(AB9540_REGUSWHPREQVALID2, 0x03, 0x0e, 0x3f), - /* - * 0x02, SysClkReq2Valid1 - * ... - * 0x80, SysClkReq8Valid1 - */ - REG_INIT(AB9540_REGUSYSCLKREQVALID1, 0x03, 0x0f, 0xfe), - /* - * 0x02, SysClkReq2Valid2 - * ... - * 0x80, SysClkReq8Valid2 - */ - REG_INIT(AB9540_REGUSYSCLKREQVALID2, 0x03, 0x10, 0xfe), - /* - * 0x01, Vaux4SwHPReqValid - * 0x02, Vaux4HwHPReq2Valid - * 0x04, Vaux4HwHPReq1Valid - * 0x08, Vaux4SysClkReq1HPValid - */ - REG_INIT(AB9540_REGUVAUX4REQVALID, 0x03, 0x11, 0x0f), - /* - * 0x02, VTVoutEna - * 0x04, Vintcore12Ena - * 0x38, Vintcore12Sel - * 0x40, Vintcore12LP - * 0x80, VTVoutLP - */ - REG_INIT(AB9540_REGUMISC1, 0x03, 0x80, 0xfe), - /* - * 0x02, VaudioEna - * 0x04, VdmicEna - * 0x08, Vamic1Ena - * 0x10, Vamic2Ena - */ - REG_INIT(AB9540_VAUDIOSUPPLY, 0x03, 0x83, 0x1e), - /* - * 0x01, Vamic1_dzout - * 0x02, Vamic2_dzout - */ - REG_INIT(AB9540_REGUCTRL1VAMIC, 0x03, 0x84, 0x03), - /* - * 0x03, Vsmps1Regu - * 0x0c, Vsmps1SelCtrl - * 0x10, Vsmps1AutoMode - * 0x20, Vsmps1PWMMode - */ - REG_INIT(AB9540_VSMPS1REGU, 0x04, 0x03, 0x3f), - /* - * 0x03, Vsmps2Regu - * 0x0c, Vsmps2SelCtrl - * 0x10, Vsmps2AutoMode - * 0x20, Vsmps2PWMMode - */ - REG_INIT(AB9540_VSMPS2REGU, 0x04, 0x04, 0x3f), - /* - * 0x03, Vsmps3Regu - * 0x0c, Vsmps3SelCtrl - * NOTE! PRCMU register - */ - REG_INIT(AB9540_VSMPS3REGU, 0x04, 0x05, 0x0f), - /* - * 0x03, VpllRegu - * 0x0c, VanaRegu - */ - REG_INIT(AB9540_VPLLVANAREGU, 0x04, 0x06, 0x0f), - /* - * 0x03, VextSupply1Regu - * 0x0c, VextSupply2Regu - * 0x30, VextSupply3Regu - * 0x40, ExtSupply2Bypass - * 0x80, ExtSupply3Bypass - */ - REG_INIT(AB9540_EXTSUPPLYREGU, 0x04, 0x08, 0xff), - /* - * 0x03, Vaux1Regu - * 0x0c, Vaux2Regu - */ - REG_INIT(AB9540_VAUX12REGU, 0x04, 0x09, 0x0f), - /* - * 0x0c, Vrf1Regu - * 0x03, Vaux3Regu - */ - REG_INIT(AB9540_VRF1VAUX3REGU, 0x04, 0x0a, 0x0f), - /* - * 0x3f, Vsmps1Sel1 - */ - REG_INIT(AB9540_VSMPS1SEL1, 0x04, 0x13, 0x3f), - /* - * 0x3f, Vsmps1Sel2 - */ - REG_INIT(AB9540_VSMPS1SEL2, 0x04, 0x14, 0x3f), - /* - * 0x3f, Vsmps1Sel3 - */ - REG_INIT(AB9540_VSMPS1SEL3, 0x04, 0x15, 0x3f), - /* - * 0x3f, Vsmps2Sel1 - */ - REG_INIT(AB9540_VSMPS2SEL1, 0x04, 0x17, 0x3f), - /* - * 0x3f, Vsmps2Sel2 - */ - REG_INIT(AB9540_VSMPS2SEL2, 0x04, 0x18, 0x3f), - /* - * 0x3f, Vsmps2Sel3 - */ - REG_INIT(AB9540_VSMPS2SEL3, 0x04, 0x19, 0x3f), - /* - * 0x7f, Vsmps3Sel1 - * NOTE! PRCMU register - */ - REG_INIT(AB9540_VSMPS3SEL1, 0x04, 0x1b, 0x7f), - /* - * 0x7f, Vsmps3Sel2 - * NOTE! PRCMU register - */ - REG_INIT(AB9540_VSMPS3SEL2, 0x04, 0x1c, 0x7f), - /* - * 0x0f, Vaux1Sel - */ - REG_INIT(AB9540_VAUX1SEL, 0x04, 0x1f, 0x0f), - /* - * 0x0f, Vaux2Sel - */ - REG_INIT(AB9540_VAUX2SEL, 0x04, 0x20, 0x0f), - /* - * 0x07, Vaux3Sel - * 0x30, Vrf1Sel - */ - REG_INIT(AB9540_VRF1VAUX3SEL, 0x04, 0x21, 0x37), - /* - * 0x01, VextSupply12LP - */ - REG_INIT(AB9540_REGUCTRL2SPARE, 0x04, 0x22, 0x01), - /* - * 0x03, Vaux4RequestCtrl - */ - REG_INIT(AB9540_VAUX4REQCTRL, 0x04, 0x2d, 0x03), - /* - * 0x03, Vaux4Regu - */ - REG_INIT(AB9540_VAUX4REGU, 0x04, 0x2e, 0x03), - /* - * 0x08, Vaux4Sel - */ - REG_INIT(AB9540_VAUX4SEL, 0x04, 0x2f, 0x0f), - /* - * 0x01, VpllDisch - * 0x02, Vrf1Disch - * 0x04, Vaux1Disch - * 0x08, Vaux2Disch - * 0x10, Vaux3Disch - * 0x20, Vintcore12Disch - * 0x40, VTVoutDisch - * 0x80, VaudioDisch - */ - REG_INIT(AB9540_REGUCTRLDISCH, 0x04, 0x43, 0xff), - /* - * 0x01, VsimDisch - * 0x02, VanaDisch - * 0x04, VdmicPullDownEna - * 0x08, VpllPullDownEna - * 0x10, VdmicDisch - */ - REG_INIT(AB9540_REGUCTRLDISCH2, 0x04, 0x44, 0x1f), - /* - * 0x01, Vaux4Disch - */ - REG_INIT(AB9540_REGUCTRLDISCH3, 0x04, 0x48, 0x01), -}; - -/* AB8540 register init */ -static struct ab8500_reg_init ab8540_reg_init[] = { - /* - * 0x01, VSimSycClkReq1Valid - * 0x02, VSimSycClkReq2Valid - * 0x04, VSimSycClkReq3Valid - * 0x08, VSimSycClkReq4Valid - * 0x10, VSimSycClkReq5Valid - * 0x20, VSimSycClkReq6Valid - * 0x40, VSimSycClkReq7Valid - * 0x80, VSimSycClkReq8Valid - */ - REG_INIT(AB8540_VSIMSYSCLKCTRL, 0x02, 0x33, 0xff), - /* - * 0x03, VarmRequestCtrl - * 0x0c, VapeRequestCtrl - * 0x30, Vsmps1RequestCtrl - * 0xc0, Vsmps2RequestCtrl - */ - REG_INIT(AB8540_REGUREQUESTCTRL1, 0x03, 0x03, 0xff), - /* - * 0x03, Vsmps3RequestCtrl - * 0x0c, VpllRequestCtrl - * 0x30, VanaRequestCtrl - * 0xc0, VextSupply1RequestCtrl - */ - REG_INIT(AB8540_REGUREQUESTCTRL2, 0x03, 0x04, 0xff), - /* - * 0x03, VextSupply2RequestCtrl - * 0x0c, VextSupply3RequestCtrl - * 0x30, Vaux1RequestCtrl - * 0xc0, Vaux2RequestCtrl - */ - REG_INIT(AB8540_REGUREQUESTCTRL3, 0x03, 0x05, 0xff), - /* - * 0x03, Vaux3RequestCtrl - * 0x04, SwHPReq - */ - REG_INIT(AB8540_REGUREQUESTCTRL4, 0x03, 0x06, 0x07), - /* - * 0x01, Vsmps1SysClkReq1HPValid - * 0x02, Vsmps2SysClkReq1HPValid - * 0x04, Vsmps3SysClkReq1HPValid - * 0x08, VanaSysClkReq1HPValid - * 0x10, VpllSysClkReq1HPValid - * 0x20, Vaux1SysClkReq1HPValid - * 0x40, Vaux2SysClkReq1HPValid - * 0x80, Vaux3SysClkReq1HPValid - */ - REG_INIT(AB8540_REGUSYSCLKREQ1HPVALID1, 0x03, 0x07, 0xff), - /* - * 0x01, VapeSysClkReq1HPValid - * 0x02, VarmSysClkReq1HPValid - * 0x04, VbbSysClkReq1HPValid - * 0x10, VextSupply1SysClkReq1HPValid - * 0x20, VextSupply2SysClkReq1HPValid - * 0x40, VextSupply3SysClkReq1HPValid - */ - REG_INIT(AB8540_REGUSYSCLKREQ1HPVALID2, 0x03, 0x08, 0x77), - /* - * 0x01, Vsmps1HwHPReq1Valid - * 0x02, Vsmps2HwHPReq1Valid - * 0x04, Vsmps3HwHPReq1Valid - * 0x08, VanaHwHPReq1Valid - * 0x10, VpllHwHPReq1Valid - * 0x20, Vaux1HwHPReq1Valid - * 0x40, Vaux2HwHPReq1Valid - * 0x80, Vaux3HwHPReq1Valid - */ - REG_INIT(AB8540_REGUHWHPREQ1VALID1, 0x03, 0x09, 0xff), - /* - * 0x01, VextSupply1HwHPReq1Valid - * 0x02, VextSupply2HwHPReq1Valid - * 0x04, VextSupply3HwHPReq1Valid - */ - REG_INIT(AB8540_REGUHWHPREQ1VALID2, 0x03, 0x0a, 0x07), - /* - * 0x01, Vsmps1HwHPReq2Valid - * 0x02, Vsmps2HwHPReq2Valid - * 0x03, Vsmps3HwHPReq2Valid - * 0x08, VanaHwHPReq2Valid - * 0x10, VpllHwHPReq2Valid - * 0x20, Vaux1HwHPReq2Valid - * 0x40, Vaux2HwHPReq2Valid - * 0x80, Vaux3HwHPReq2Valid - */ - REG_INIT(AB8540_REGUHWHPREQ2VALID1, 0x03, 0x0b, 0xff), - /* - * 0x01, VextSupply1HwHPReq2Valid - * 0x02, VextSupply2HwHPReq2Valid - * 0x04, VextSupply3HwHPReq2Valid - */ - REG_INIT(AB8540_REGUHWHPREQ2VALID2, 0x03, 0x0c, 0x07), - /* - * 0x01, VapeSwHPReqValid - * 0x02, VarmSwHPReqValid - * 0x04, Vsmps1SwHPReqValid - * 0x08, Vsmps2SwHPReqValid - * 0x10, Vsmps3SwHPReqValid - * 0x20, VanaSwHPReqValid - * 0x40, VpllSwHPReqValid - * 0x80, Vaux1SwHPReqValid - */ - REG_INIT(AB8540_REGUSWHPREQVALID1, 0x03, 0x0d, 0xff), - /* - * 0x01, Vaux2SwHPReqValid - * 0x02, Vaux3SwHPReqValid - * 0x04, VextSupply1SwHPReqValid - * 0x08, VextSupply2SwHPReqValid - * 0x10, VextSupply3SwHPReqValid - */ - REG_INIT(AB8540_REGUSWHPREQVALID2, 0x03, 0x0e, 0x1f), - /* - * 0x02, SysClkReq2Valid1 - * ... - * 0x80, SysClkReq8Valid1 - */ - REG_INIT(AB8540_REGUSYSCLKREQVALID1, 0x03, 0x0f, 0xff), - /* - * 0x02, SysClkReq2Valid2 - * ... - * 0x80, SysClkReq8Valid2 - */ - REG_INIT(AB8540_REGUSYSCLKREQVALID2, 0x03, 0x10, 0xff), - /* - * 0x01, Vaux4SwHPReqValid - * 0x02, Vaux4HwHPReq2Valid - * 0x04, Vaux4HwHPReq1Valid - * 0x08, Vaux4SysClkReq1HPValid - */ - REG_INIT(AB8540_REGUVAUX4REQVALID, 0x03, 0x11, 0x0f), - /* - * 0x01, Vaux5SwHPReqValid - * 0x02, Vaux5HwHPReq2Valid - * 0x04, Vaux5HwHPReq1Valid - * 0x08, Vaux5SysClkReq1HPValid - */ - REG_INIT(AB8540_REGUVAUX5REQVALID, 0x03, 0x12, 0x0f), - /* - * 0x01, Vaux6SwHPReqValid - * 0x02, Vaux6HwHPReq2Valid - * 0x04, Vaux6HwHPReq1Valid - * 0x08, Vaux6SysClkReq1HPValid - */ - REG_INIT(AB8540_REGUVAUX6REQVALID, 0x03, 0x13, 0x0f), - /* - * 0x01, VclkbSwHPReqValid - * 0x02, VclkbHwHPReq2Valid - * 0x04, VclkbHwHPReq1Valid - * 0x08, VclkbSysClkReq1HPValid - */ - REG_INIT(AB8540_REGUVCLKBREQVALID, 0x03, 0x14, 0x0f), - /* - * 0x01, Vrf1SwHPReqValid - * 0x02, Vrf1HwHPReq2Valid - * 0x04, Vrf1HwHPReq1Valid - * 0x08, Vrf1SysClkReq1HPValid - */ - REG_INIT(AB8540_REGUVRF1REQVALID, 0x03, 0x15, 0x0f), - /* - * 0x02, VTVoutEna - * 0x04, Vintcore12Ena - * 0x38, Vintcore12Sel - * 0x40, Vintcore12LP - * 0x80, VTVoutLP - */ - REG_INIT(AB8540_REGUMISC1, 0x03, 0x80, 0xfe), - /* - * 0x02, VaudioEna - * 0x04, VdmicEna - * 0x08, Vamic1Ena - * 0x10, Vamic2Ena - * 0x20, Vamic12LP - * 0xC0, VdmicSel - */ - REG_INIT(AB8540_VAUDIOSUPPLY, 0x03, 0x83, 0xfe), - /* - * 0x01, Vamic1_dzout - * 0x02, Vamic2_dzout - */ - REG_INIT(AB8540_REGUCTRL1VAMIC, 0x03, 0x84, 0x03), - /* - * 0x07, VHSICSel - * 0x08, VHSICOffState - * 0x10, VHSIEna - * 0x20, VHSICLP - */ - REG_INIT(AB8540_VHSIC, 0x03, 0x87, 0x3f), - /* - * 0x07, VSDIOSel - * 0x08, VSDIOOffState - * 0x10, VSDIOEna - * 0x20, VSDIOLP - */ - REG_INIT(AB8540_VSDIO, 0x03, 0x88, 0x3f), - /* - * 0x03, Vsmps1Regu - * 0x0c, Vsmps1SelCtrl - * 0x10, Vsmps1AutoMode - * 0x20, Vsmps1PWMMode - */ - REG_INIT(AB8540_VSMPS1REGU, 0x04, 0x03, 0x3f), - /* - * 0x03, Vsmps2Regu - * 0x0c, Vsmps2SelCtrl - * 0x10, Vsmps2AutoMode - * 0x20, Vsmps2PWMMode - */ - REG_INIT(AB8540_VSMPS2REGU, 0x04, 0x04, 0x3f), - /* - * 0x03, Vsmps3Regu - * 0x0c, Vsmps3SelCtrl - * 0x10, Vsmps3AutoMode - * 0x20, Vsmps3PWMMode - * NOTE! PRCMU register - */ - REG_INIT(AB8540_VSMPS3REGU, 0x04, 0x05, 0x0f), - /* - * 0x03, VpllRegu - * 0x0c, VanaRegu - */ - REG_INIT(AB8540_VPLLVANAREGU, 0x04, 0x06, 0x0f), - /* - * 0x03, VextSupply1Regu - * 0x0c, VextSupply2Regu - * 0x30, VextSupply3Regu - * 0x40, ExtSupply2Bypass - * 0x80, ExtSupply3Bypass - */ - REG_INIT(AB8540_EXTSUPPLYREGU, 0x04, 0x08, 0xff), - /* - * 0x03, Vaux1Regu - * 0x0c, Vaux2Regu - */ - REG_INIT(AB8540_VAUX12REGU, 0x04, 0x09, 0x0f), - /* - * 0x0c, VRF1Regu - * 0x03, Vaux3Regu - */ - REG_INIT(AB8540_VRF1VAUX3REGU, 0x04, 0x0a, 0x0f), - /* - * 0x3f, Vsmps1Sel1 - */ - REG_INIT(AB8540_VSMPS1SEL1, 0x04, 0x13, 0x3f), - /* - * 0x3f, Vsmps1Sel2 - */ - REG_INIT(AB8540_VSMPS1SEL2, 0x04, 0x14, 0x3f), - /* - * 0x3f, Vsmps1Sel3 - */ - REG_INIT(AB8540_VSMPS1SEL3, 0x04, 0x15, 0x3f), - /* - * 0x3f, Vsmps2Sel1 - */ - REG_INIT(AB8540_VSMPS2SEL1, 0x04, 0x17, 0x3f), - /* - * 0x3f, Vsmps2Sel2 - */ - REG_INIT(AB8540_VSMPS2SEL2, 0x04, 0x18, 0x3f), - /* - * 0x3f, Vsmps2Sel3 - */ - REG_INIT(AB8540_VSMPS2SEL3, 0x04, 0x19, 0x3f), - /* - * 0x7f, Vsmps3Sel1 - * NOTE! PRCMU register - */ - REG_INIT(AB8540_VSMPS3SEL1, 0x04, 0x1b, 0x7f), - /* - * 0x7f, Vsmps3Sel2 - * NOTE! PRCMU register - */ - REG_INIT(AB8540_VSMPS3SEL2, 0x04, 0x1c, 0x7f), - /* - * 0x0f, Vaux1Sel - */ - REG_INIT(AB8540_VAUX1SEL, 0x04, 0x1f, 0x0f), - /* - * 0x0f, Vaux2Sel - */ - REG_INIT(AB8540_VAUX2SEL, 0x04, 0x20, 0x0f), - /* - * 0x07, Vaux3Sel - * 0x70, Vrf1Sel - */ - REG_INIT(AB8540_VRF1VAUX3SEL, 0x04, 0x21, 0x77), - /* - * 0x01, VextSupply12LP - */ - REG_INIT(AB8540_REGUCTRL2SPARE, 0x04, 0x22, 0x01), - /* - * 0x07, Vanasel - * 0x30, Vpllsel - */ - REG_INIT(AB8540_VANAVPLLSEL, 0x04, 0x29, 0x37), - /* - * 0x03, Vaux4RequestCtrl - */ - REG_INIT(AB8540_VAUX4REQCTRL, 0x04, 0x2d, 0x03), - /* - * 0x03, Vaux4Regu - */ - REG_INIT(AB8540_VAUX4REGU, 0x04, 0x2e, 0x03), - /* - * 0x0f, Vaux4Sel - */ - REG_INIT(AB8540_VAUX4SEL, 0x04, 0x2f, 0x0f), - /* - * 0x03, Vaux5RequestCtrl - */ - REG_INIT(AB8540_VAUX5REQCTRL, 0x04, 0x31, 0x03), - /* - * 0x03, Vaux5Regu - */ - REG_INIT(AB8540_VAUX5REGU, 0x04, 0x32, 0x03), - /* - * 0x3f, Vaux5Sel - */ - REG_INIT(AB8540_VAUX5SEL, 0x04, 0x33, 0x3f), - /* - * 0x03, Vaux6RequestCtrl - */ - REG_INIT(AB8540_VAUX6REQCTRL, 0x04, 0x34, 0x03), - /* - * 0x03, Vaux6Regu - */ - REG_INIT(AB8540_VAUX6REGU, 0x04, 0x35, 0x03), - /* - * 0x3f, Vaux6Sel - */ - REG_INIT(AB8540_VAUX6SEL, 0x04, 0x36, 0x3f), - /* - * 0x03, VCLKBRequestCtrl - */ - REG_INIT(AB8540_VCLKBREQCTRL, 0x04, 0x37, 0x03), - /* - * 0x03, VCLKBRegu - */ - REG_INIT(AB8540_VCLKBREGU, 0x04, 0x38, 0x03), - /* - * 0x07, VCLKBSel - */ - REG_INIT(AB8540_VCLKBSEL, 0x04, 0x39, 0x07), - /* - * 0x03, Vrf1RequestCtrl - */ - REG_INIT(AB8540_VRF1REQCTRL, 0x04, 0x3a, 0x03), - /* - * 0x01, VpllDisch - * 0x02, Vrf1Disch - * 0x04, Vaux1Disch - * 0x08, Vaux2Disch - * 0x10, Vaux3Disch - * 0x20, Vintcore12Disch - * 0x40, VTVoutDisch - * 0x80, VaudioDisch - */ - REG_INIT(AB8540_REGUCTRLDISCH, 0x04, 0x43, 0xff), - /* - * 0x02, VanaDisch - * 0x04, VdmicPullDownEna - * 0x08, VpllPullDownEna - * 0x10, VdmicDisch - */ - REG_INIT(AB8540_REGUCTRLDISCH2, 0x04, 0x44, 0x1e), - /* - * 0x01, Vaux4Disch - */ - REG_INIT(AB8540_REGUCTRLDISCH3, 0x04, 0x48, 0x01), - /* - * 0x01, Vaux5Disch - * 0x02, Vaux6Disch - * 0x04, VCLKBDisch - */ - REG_INIT(AB8540_REGUCTRLDISCH4, 0x04, 0x49, 0x07), -}; - static struct of_regulator_match ab8500_regulator_match[] = { { .name = "ab8500_ldo_aux1", .driver_data = (void *) AB8500_LDO_AUX1, }, { .name = "ab8500_ldo_aux2", .driver_data = (void *) AB8500_LDO_AUX2, }, @@ -2925,37 +1565,6 @@ static struct of_regulator_match ab8505_regulator_match[] = { { .name = "ab8500_ldo_ana", .driver_data = (void *) AB8505_LDO_ANA, }, }; -static struct of_regulator_match ab8540_regulator_match[] = { - { .name = "ab8500_ldo_aux1", .driver_data = (void *) AB8540_LDO_AUX1, }, - { .name = "ab8500_ldo_aux2", .driver_data = (void *) AB8540_LDO_AUX2, }, - { .name = "ab8500_ldo_aux3", .driver_data = (void *) AB8540_LDO_AUX3, }, - { .name = "ab8500_ldo_aux4", .driver_data = (void *) AB8540_LDO_AUX4, }, - { .name = "ab8500_ldo_aux5", .driver_data = (void *) AB8540_LDO_AUX5, }, - { .name = "ab8500_ldo_aux6", .driver_data = (void *) AB8540_LDO_AUX6, }, - { .name = "ab8500_ldo_intcore", .driver_data = (void *) AB8540_LDO_INTCORE, }, - { .name = "ab8500_ldo_tvout", .driver_data = (void *) AB8540_LDO_TVOUT, }, - { .name = "ab8500_ldo_audio", .driver_data = (void *) AB8540_LDO_AUDIO, }, - { .name = "ab8500_ldo_anamic1", .driver_data = (void *) AB8540_LDO_ANAMIC1, }, - { .name = "ab8500_ldo_anamic2", .driver_data = (void *) AB8540_LDO_ANAMIC2, }, - { .name = "ab8500_ldo_dmic", .driver_data = (void *) AB8540_LDO_DMIC, }, - { .name = "ab8500_ldo_ana", .driver_data = (void *) AB8540_LDO_ANA, }, - { .name = "ab8500_ldo_sdio", .driver_data = (void *) AB8540_LDO_SDIO, }, -}; - -static struct of_regulator_match ab9540_regulator_match[] = { - { .name = "ab8500_ldo_aux1", .driver_data = (void *) AB9540_LDO_AUX1, }, - { .name = "ab8500_ldo_aux2", .driver_data = (void *) AB9540_LDO_AUX2, }, - { .name = "ab8500_ldo_aux3", .driver_data = (void *) AB9540_LDO_AUX3, }, - { .name = "ab8500_ldo_aux4", .driver_data = (void *) AB9540_LDO_AUX4, }, - { .name = "ab8500_ldo_intcore", .driver_data = (void *) AB9540_LDO_INTCORE, }, - { .name = "ab8500_ldo_tvout", .driver_data = (void *) AB9540_LDO_TVOUT, }, - { .name = "ab8500_ldo_audio", .driver_data = (void *) AB9540_LDO_AUDIO, }, - { .name = "ab8500_ldo_anamic1", .driver_data = (void *) AB9540_LDO_ANAMIC1, }, - { .name = "ab8500_ldo_anamic2", .driver_data = (void *) AB9540_LDO_ANAMIC2, }, - { .name = "ab8500_ldo_dmic", .driver_data = (void *) AB9540_LDO_DMIC, }, - { .name = "ab8500_ldo_ana", .driver_data = (void *) AB9540_LDO_ANA, }, -}; - static struct { struct ab8500_regulator_info *info; int info_size; @@ -2967,27 +1576,13 @@ static struct { static void abx500_get_regulator_info(struct ab8500 *ab8500) { - if (is_ab9540(ab8500)) { - abx500_regulator.info = ab9540_regulator_info; - abx500_regulator.info_size = ARRAY_SIZE(ab9540_regulator_info); - abx500_regulator.init = ab9540_reg_init; - abx500_regulator.init_size = AB9540_NUM_REGULATOR_REGISTERS; - abx500_regulator.match = ab9540_regulator_match; - abx500_regulator.match_size = ARRAY_SIZE(ab9540_regulator_match); - } else if (is_ab8505(ab8500)) { + if (is_ab8505(ab8500)) { abx500_regulator.info = ab8505_regulator_info; abx500_regulator.info_size = ARRAY_SIZE(ab8505_regulator_info); abx500_regulator.init = ab8505_reg_init; abx500_regulator.init_size = AB8505_NUM_REGULATOR_REGISTERS; abx500_regulator.match = ab8505_regulator_match; abx500_regulator.match_size = ARRAY_SIZE(ab8505_regulator_match); - } else if (is_ab8540(ab8500)) { - abx500_regulator.info = ab8540_regulator_info; - abx500_regulator.info_size = ARRAY_SIZE(ab8540_regulator_info); - abx500_regulator.init = ab8540_reg_init; - abx500_regulator.init_size = AB8540_NUM_REGULATOR_REGISTERS; - abx500_regulator.match = ab8540_regulator_match; - abx500_regulator.match_size = ARRAY_SIZE(ab8540_regulator_match); } else { abx500_regulator.info = ab8500_regulator_info; abx500_regulator.info_size = ARRAY_SIZE(ab8500_regulator_info); diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index 7d6478e6a503..d9d8155ed8cb 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -1,22 +1,6 @@ -/* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. #include <linux/slab.h> #include <linux/device.h> diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index 96fddfff5dc4..f6d6a4ad9e8a 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c @@ -17,12 +17,11 @@ #include <linux/bitops.h> #include <linux/err.h> #include <linux/of.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> -#include <linux/gpio.h> #include <linux/slab.h> #include <linux/regulator/arizona-ldo1.h> @@ -198,16 +197,6 @@ static int arizona_ldo1_of_get_pdata(struct arizona_ldo1_pdata *pdata, struct device_node *init_node, *dcvdd_node; struct regulator_init_data *init_data; - pdata->ldoena = of_get_named_gpio(np, "wlf,ldoena", 0); - if (pdata->ldoena < 0) { - dev_warn(config->dev, - "LDOENA GPIO property missing/malformed: %d\n", - pdata->ldoena); - pdata->ldoena = 0; - } else { - config->ena_gpio_initialized = true; - } - init_node = of_get_child_by_name(np, "ldo1"); dcvdd_node = of_parse_phandle(np, "DCVDD-supply", 0); @@ -264,7 +253,11 @@ static int arizona_ldo1_common_init(struct platform_device *pdev, } } - config.ena_gpio = pdata->ldoena; + /* We assume that high output = regulator off */ + config.ena_gpiod = devm_gpiod_get_optional(&pdev->dev, "wlf,ldoena", + GPIOD_OUT_HIGH); + if (IS_ERR(config.ena_gpiod)) + return PTR_ERR(config.ena_gpiod); if (pdata->init_data) config.init_data = pdata->init_data; diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 181622b2813d..91b8ff8bac15 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -721,6 +721,8 @@ static int axp20x_regulator_probe(struct platform_device *pdev) case AXP803_ID: regulators = axp803_regulators; nregulators = AXP803_REG_ID_MAX; + drivevbus = of_property_read_bool(pdev->dev.parent->of_node, + "x-powers,drive-vbus-en"); break; case AXP806_ID: regulators = axp806_regulators; diff --git a/drivers/regulator/bd71837-regulator.c b/drivers/regulator/bd71837-regulator.c new file mode 100644 index 000000000000..6eae4d0432a2 --- /dev/null +++ b/drivers/regulator/bd71837-regulator.c @@ -0,0 +1,640 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 ROHM Semiconductors +// bd71837-regulator.c ROHM BD71837MWV regulator driver + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/gpio.h> +#include <linux/mfd/bd71837.h> +#include <linux/regulator/of_regulator.h> + +struct bd71837_pmic { + struct regulator_desc descs[BD71837_REGULATOR_CNT]; + struct bd71837 *mfd; + struct platform_device *pdev; + struct regulator_dev *rdev[BD71837_REGULATOR_CNT]; +}; + +/* + * BUCK1/2/3/4 + * BUCK1RAMPRATE[1:0] BUCK1 DVS ramp rate setting + * 00: 10.00mV/usec 10mV 1uS + * 01: 5.00mV/usec 10mV 2uS + * 10: 2.50mV/usec 10mV 4uS + * 11: 1.25mV/usec 10mV 8uS + */ +static int bd71837_buck1234_set_ramp_delay(struct regulator_dev *rdev, + int ramp_delay) +{ + struct bd71837_pmic *pmic = rdev_get_drvdata(rdev); + struct bd71837 *mfd = pmic->mfd; + int id = rdev->desc->id; + unsigned int ramp_value = BUCK_RAMPRATE_10P00MV; + + dev_dbg(&(pmic->pdev->dev), "Buck[%d] Set Ramp = %d\n", id + 1, + ramp_delay); + switch (ramp_delay) { + case 1 ... 1250: + ramp_value = BUCK_RAMPRATE_1P25MV; + break; + case 1251 ... 2500: + ramp_value = BUCK_RAMPRATE_2P50MV; + break; + case 2501 ... 5000: + ramp_value = BUCK_RAMPRATE_5P00MV; + break; + case 5001 ... 10000: + ramp_value = BUCK_RAMPRATE_10P00MV; + break; + default: + ramp_value = BUCK_RAMPRATE_10P00MV; + dev_err(&pmic->pdev->dev, + "%s: ramp_delay: %d not supported, setting 10000mV//us\n", + rdev->desc->name, ramp_delay); + } + + return regmap_update_bits(mfd->regmap, BD71837_REG_BUCK1_CTRL + id, + BUCK_RAMPRATE_MASK, ramp_value << 6); +} + +/* Bucks 1 to 4 support DVS. PWM mode is used when voltage is changed. + * Bucks 5 to 8 and LDOs can use PFM and must be disabled when voltage + * is changed. Hence we return -EBUSY for these if voltage is changed + * when BUCK/LDO is enabled. + */ +static int bd71837_set_voltage_sel_restricted(struct regulator_dev *rdev, + unsigned int sel) +{ + int ret; + + ret = regulator_is_enabled_regmap(rdev); + if (!ret) + ret = regulator_set_voltage_sel_regmap(rdev, sel); + else if (ret == 1) + ret = -EBUSY; + return ret; +} + +static struct regulator_ops bd71837_ldo_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = bd71837_set_voltage_sel_restricted, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static struct regulator_ops bd71837_ldo_regulator_nolinear_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_table, + .set_voltage_sel = bd71837_set_voltage_sel_restricted, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static struct regulator_ops bd71837_buck_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = bd71837_set_voltage_sel_restricted, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, +}; + +static struct regulator_ops bd71837_buck_regulator_nolinear_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_table, + .set_voltage_sel = bd71837_set_voltage_sel_restricted, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, +}; + +static struct regulator_ops bd71837_buck1234_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = bd71837_buck1234_set_ramp_delay, +}; + +/* + * BUCK1/2/3/4 + * 0.70 to 1.30V (10mV step) + */ +static const struct regulator_linear_range bd71837_buck1234_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(700000, 0x00, 0x3C, 10000), + REGULATOR_LINEAR_RANGE(1300000, 0x3D, 0x3F, 0), +}; + +/* + * BUCK5 + * 0.9V to 1.35V () + */ +static const struct regulator_linear_range bd71837_buck5_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(700000, 0x00, 0x03, 100000), + REGULATOR_LINEAR_RANGE(1050000, 0x04, 0x05, 50000), + REGULATOR_LINEAR_RANGE(1200000, 0x06, 0x07, 150000), +}; + +/* + * BUCK6 + * 3.0V to 3.3V (step 100mV) + */ +static const struct regulator_linear_range bd71837_buck6_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000), +}; + +/* + * BUCK7 + * 000 = 1.605V + * 001 = 1.695V + * 010 = 1.755V + * 011 = 1.8V (Initial) + * 100 = 1.845V + * 101 = 1.905V + * 110 = 1.95V + * 111 = 1.995V + */ +static const unsigned int buck_7_volts[] = { + 1605000, 1695000, 1755000, 1800000, 1845000, 1905000, 1950000, 1995000 +}; + +/* + * BUCK8 + * 0.8V to 1.40V (step 10mV) + */ +static const struct regulator_linear_range bd71837_buck8_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(800000, 0x00, 0x3C, 10000), + REGULATOR_LINEAR_RANGE(1400000, 0x3D, 0x3F, 0), +}; + +/* + * LDO1 + * 3.0 to 3.3V (100mV step) + */ +static const struct regulator_linear_range bd71837_ldo1_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000), +}; + +/* + * LDO2 + * 0.8 or 0.9V + */ +const unsigned int ldo_2_volts[] = { + 900000, 800000 +}; + +/* + * LDO3 + * 1.8 to 3.3V (100mV step) + */ +static const struct regulator_linear_range bd71837_ldo3_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), +}; + +/* + * LDO4 + * 0.9 to 1.8V (100mV step) + */ +static const struct regulator_linear_range bd71837_ldo4_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000), + REGULATOR_LINEAR_RANGE(1800000, 0x0A, 0x0F, 0), +}; + +/* + * LDO5 + * 1.8 to 3.3V (100mV step) + */ +static const struct regulator_linear_range bd71837_ldo5_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), +}; + +/* + * LDO6 + * 0.9 to 1.8V (100mV step) + */ +static const struct regulator_linear_range bd71837_ldo6_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000), + REGULATOR_LINEAR_RANGE(1800000, 0x0A, 0x0F, 0), +}; + +/* + * LDO7 + * 1.8 to 3.3V (100mV step) + */ +static const struct regulator_linear_range bd71837_ldo7_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), +}; + +static const struct regulator_desc bd71837_regulators[] = { + { + .name = "buck1", + .of_match = of_match_ptr("BUCK1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_BUCK1, + .ops = &bd71837_buck1234_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_BUCK1_VOLTAGE_NUM, + .linear_ranges = bd71837_buck1234_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(bd71837_buck1234_voltage_ranges), + .vsel_reg = BD71837_REG_BUCK1_VOLT_RUN, + .vsel_mask = BUCK1_RUN_MASK, + .enable_reg = BD71837_REG_BUCK1_CTRL, + .enable_mask = BD71837_BUCK_EN, + .owner = THIS_MODULE, + }, + { + .name = "buck2", + .of_match = of_match_ptr("BUCK2"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_BUCK2, + .ops = &bd71837_buck1234_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_BUCK2_VOLTAGE_NUM, + .linear_ranges = bd71837_buck1234_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(bd71837_buck1234_voltage_ranges), + .vsel_reg = BD71837_REG_BUCK2_VOLT_RUN, + .vsel_mask = BUCK2_RUN_MASK, + .enable_reg = BD71837_REG_BUCK2_CTRL, + .enable_mask = BD71837_BUCK_EN, + .owner = THIS_MODULE, + }, + { + .name = "buck3", + .of_match = of_match_ptr("BUCK3"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_BUCK3, + .ops = &bd71837_buck1234_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_BUCK3_VOLTAGE_NUM, + .linear_ranges = bd71837_buck1234_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(bd71837_buck1234_voltage_ranges), + .vsel_reg = BD71837_REG_BUCK3_VOLT_RUN, + .vsel_mask = BUCK3_RUN_MASK, + .enable_reg = BD71837_REG_BUCK3_CTRL, + .enable_mask = BD71837_BUCK_EN, + .owner = THIS_MODULE, + }, + { + .name = "buck4", + .of_match = of_match_ptr("BUCK4"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_BUCK4, + .ops = &bd71837_buck1234_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_BUCK4_VOLTAGE_NUM, + .linear_ranges = bd71837_buck1234_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(bd71837_buck1234_voltage_ranges), + .vsel_reg = BD71837_REG_BUCK4_VOLT_RUN, + .vsel_mask = BUCK4_RUN_MASK, + .enable_reg = BD71837_REG_BUCK4_CTRL, + .enable_mask = BD71837_BUCK_EN, + .owner = THIS_MODULE, + }, + { + .name = "buck5", + .of_match = of_match_ptr("BUCK5"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_BUCK5, + .ops = &bd71837_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_BUCK5_VOLTAGE_NUM, + .linear_ranges = bd71837_buck5_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(bd71837_buck5_voltage_ranges), + .vsel_reg = BD71837_REG_BUCK5_VOLT, + .vsel_mask = BUCK5_MASK, + .enable_reg = BD71837_REG_BUCK5_CTRL, + .enable_mask = BD71837_BUCK_EN, + .owner = THIS_MODULE, + }, + { + .name = "buck6", + .of_match = of_match_ptr("BUCK6"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_BUCK6, + .ops = &bd71837_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_BUCK6_VOLTAGE_NUM, + .linear_ranges = bd71837_buck6_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(bd71837_buck6_voltage_ranges), + .vsel_reg = BD71837_REG_BUCK6_VOLT, + .vsel_mask = BUCK6_MASK, + .enable_reg = BD71837_REG_BUCK6_CTRL, + .enable_mask = BD71837_BUCK_EN, + .owner = THIS_MODULE, + }, + { + .name = "buck7", + .of_match = of_match_ptr("BUCK7"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_BUCK7, + .ops = &bd71837_buck_regulator_nolinear_ops, + .type = REGULATOR_VOLTAGE, + .volt_table = &buck_7_volts[0], + .n_voltages = ARRAY_SIZE(buck_7_volts), + .vsel_reg = BD71837_REG_BUCK7_VOLT, + .vsel_mask = BUCK7_MASK, + .enable_reg = BD71837_REG_BUCK7_CTRL, + .enable_mask = BD71837_BUCK_EN, + .owner = THIS_MODULE, + }, + { + .name = "buck8", + .of_match = of_match_ptr("BUCK8"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_BUCK8, + .ops = &bd71837_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_BUCK8_VOLTAGE_NUM, + .linear_ranges = bd71837_buck8_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(bd71837_buck8_voltage_ranges), + .vsel_reg = BD71837_REG_BUCK8_VOLT, + .vsel_mask = BUCK8_MASK, + .enable_reg = BD71837_REG_BUCK8_CTRL, + .enable_mask = BD71837_BUCK_EN, + .owner = THIS_MODULE, + }, + { + .name = "ldo1", + .of_match = of_match_ptr("LDO1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_LDO1, + .ops = &bd71837_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_LDO1_VOLTAGE_NUM, + .linear_ranges = bd71837_ldo1_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(bd71837_ldo1_voltage_ranges), + .vsel_reg = BD71837_REG_LDO1_VOLT, + .vsel_mask = LDO1_MASK, + .enable_reg = BD71837_REG_LDO1_VOLT, + .enable_mask = BD71837_LDO_EN, + .owner = THIS_MODULE, + }, + { + .name = "ldo2", + .of_match = of_match_ptr("LDO2"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_LDO2, + .ops = &bd71837_ldo_regulator_nolinear_ops, + .type = REGULATOR_VOLTAGE, + .volt_table = &ldo_2_volts[0], + .vsel_reg = BD71837_REG_LDO2_VOLT, + .vsel_mask = LDO2_MASK, + .n_voltages = ARRAY_SIZE(ldo_2_volts), + .n_voltages = BD71837_LDO2_VOLTAGE_NUM, + .enable_reg = BD71837_REG_LDO2_VOLT, + .enable_mask = BD71837_LDO_EN, + .owner = THIS_MODULE, + }, + { + .name = "ldo3", + .of_match = of_match_ptr("LDO3"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_LDO3, + .ops = &bd71837_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_LDO3_VOLTAGE_NUM, + .linear_ranges = bd71837_ldo3_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(bd71837_ldo3_voltage_ranges), + .vsel_reg = BD71837_REG_LDO3_VOLT, + .vsel_mask = LDO3_MASK, + .enable_reg = BD71837_REG_LDO3_VOLT, + .enable_mask = BD71837_LDO_EN, + .owner = THIS_MODULE, + }, + { + .name = "ldo4", + .of_match = of_match_ptr("LDO4"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_LDO4, + .ops = &bd71837_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_LDO4_VOLTAGE_NUM, + .linear_ranges = bd71837_ldo4_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(bd71837_ldo4_voltage_ranges), + .vsel_reg = BD71837_REG_LDO4_VOLT, + .vsel_mask = LDO4_MASK, + .enable_reg = BD71837_REG_LDO4_VOLT, + .enable_mask = BD71837_LDO_EN, + .owner = THIS_MODULE, + }, + { + .name = "ldo5", + .of_match = of_match_ptr("LDO5"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_LDO5, + .ops = &bd71837_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_LDO5_VOLTAGE_NUM, + .linear_ranges = bd71837_ldo5_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(bd71837_ldo5_voltage_ranges), + /* LDO5 is supplied by buck6 */ + .supply_name = "buck6", + .vsel_reg = BD71837_REG_LDO5_VOLT, + .vsel_mask = LDO5_MASK, + .enable_reg = BD71837_REG_LDO5_VOLT, + .enable_mask = BD71837_LDO_EN, + .owner = THIS_MODULE, + }, + { + .name = "ldo6", + .of_match = of_match_ptr("LDO6"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_LDO6, + .ops = &bd71837_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_LDO6_VOLTAGE_NUM, + .linear_ranges = bd71837_ldo6_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(bd71837_ldo6_voltage_ranges), + /* LDO6 is supplied by buck7 */ + .supply_name = "buck7", + .vsel_reg = BD71837_REG_LDO6_VOLT, + .vsel_mask = LDO6_MASK, + .enable_reg = BD71837_REG_LDO6_VOLT, + .enable_mask = BD71837_LDO_EN, + .owner = THIS_MODULE, + }, + { + .name = "ldo7", + .of_match = of_match_ptr("LDO7"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71837_LDO7, + .ops = &bd71837_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_LDO7_VOLTAGE_NUM, + .linear_ranges = bd71837_ldo7_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(bd71837_ldo7_voltage_ranges), + .vsel_reg = BD71837_REG_LDO7_VOLT, + .vsel_mask = LDO7_MASK, + .enable_reg = BD71837_REG_LDO7_VOLT, + .enable_mask = BD71837_LDO_EN, + .owner = THIS_MODULE, + }, +}; + +struct reg_init { + unsigned int reg; + unsigned int mask; +}; + +static int bd71837_probe(struct platform_device *pdev) +{ + struct bd71837_pmic *pmic; + struct bd71837_board *pdata; + struct regulator_config config = { 0 }; + struct reg_init pmic_regulator_inits[] = { + { + .reg = BD71837_REG_BUCK1_CTRL, + .mask = BD71837_BUCK_SEL, + }, { + .reg = BD71837_REG_BUCK2_CTRL, + .mask = BD71837_BUCK_SEL, + }, { + .reg = BD71837_REG_BUCK3_CTRL, + .mask = BD71837_BUCK_SEL, + }, { + .reg = BD71837_REG_BUCK4_CTRL, + .mask = BD71837_BUCK_SEL, + }, { + .reg = BD71837_REG_BUCK5_CTRL, + .mask = BD71837_BUCK_SEL, + }, { + .reg = BD71837_REG_BUCK6_CTRL, + .mask = BD71837_BUCK_SEL, + }, { + .reg = BD71837_REG_BUCK7_CTRL, + .mask = BD71837_BUCK_SEL, + }, { + .reg = BD71837_REG_BUCK8_CTRL, + .mask = BD71837_BUCK_SEL, + }, { + .reg = BD71837_REG_LDO1_VOLT, + .mask = BD71837_LDO_SEL, + }, { + .reg = BD71837_REG_LDO2_VOLT, + .mask = BD71837_LDO_SEL, + }, { + .reg = BD71837_REG_LDO3_VOLT, + .mask = BD71837_LDO_SEL, + }, { + .reg = BD71837_REG_LDO4_VOLT, + .mask = BD71837_LDO_SEL, + }, { + .reg = BD71837_REG_LDO5_VOLT, + .mask = BD71837_LDO_SEL, + }, { + .reg = BD71837_REG_LDO6_VOLT, + .mask = BD71837_LDO_SEL, + }, { + .reg = BD71837_REG_LDO7_VOLT, + .mask = BD71837_LDO_SEL, + } + }; + + int i, err; + + pmic = devm_kzalloc(&pdev->dev, sizeof(struct bd71837_pmic), + GFP_KERNEL); + if (!pmic) + return -ENOMEM; + + memcpy(pmic->descs, bd71837_regulators, sizeof(pmic->descs)); + + pmic->pdev = pdev; + pmic->mfd = dev_get_drvdata(pdev->dev.parent); + + if (!pmic->mfd) { + dev_err(&pdev->dev, "No MFD driver data\n"); + err = -EINVAL; + goto err; + } + platform_set_drvdata(pdev, pmic); + pdata = dev_get_platdata(pmic->mfd->dev); + + /* Register LOCK release */ + err = regmap_update_bits(pmic->mfd->regmap, BD71837_REG_REGLOCK, + (REGLOCK_PWRSEQ | REGLOCK_VREG), 0); + if (err) { + dev_err(&pmic->pdev->dev, "Failed to unlock PMIC (%d)\n", err); + goto err; + } else { + dev_dbg(&pmic->pdev->dev, "%s: Unlocked lock register 0x%x\n", + __func__, BD71837_REG_REGLOCK); + } + + for (i = 0; i < ARRAY_SIZE(pmic_regulator_inits); i++) { + + struct regulator_desc *desc; + struct regulator_dev *rdev; + + desc = &pmic->descs[i]; + + if (pdata) + config.init_data = pdata->init_data[i]; + + config.dev = pdev->dev.parent; + config.driver_data = pmic; + config.regmap = pmic->mfd->regmap; + + rdev = devm_regulator_register(&pdev->dev, desc, &config); + if (IS_ERR(rdev)) { + dev_err(pmic->mfd->dev, + "failed to register %s regulator\n", + desc->name); + err = PTR_ERR(rdev); + goto err; + } + /* Regulator register gets the regulator constraints and + * applies them (set_machine_constraints). This should have + * turned the control register(s) to correct values and we + * can now switch the control from PMIC state machine to the + * register interface + */ + err = regmap_update_bits(pmic->mfd->regmap, + pmic_regulator_inits[i].reg, + pmic_regulator_inits[i].mask, + 0xFFFFFFFF); + if (err) { + dev_err(&pmic->pdev->dev, + "Failed to write BUCK/LDO SEL bit for (%s)\n", + desc->name); + goto err; + } + + pmic->rdev[i] = rdev; + } + + return 0; + +err: + return err; +} + +static struct platform_driver bd71837_regulator = { + .driver = { + .name = "bd71837-pmic", + .owner = THIS_MODULE, + }, + .probe = bd71837_probe, +}; + +module_platform_driver(bd71837_regulator); + +MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); +MODULE_DESCRIPTION("BD71837 voltage regulator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c index c67a83d53c4c..be574eb444eb 100644 --- a/drivers/regulator/bd9571mwv-regulator.c +++ b/drivers/regulator/bd9571mwv-regulator.c @@ -24,6 +24,18 @@ #include <linux/mfd/bd9571mwv.h> +struct bd9571mwv_reg { + struct bd9571mwv *bd; + + /* DDR Backup Power */ + u8 bkup_mode_cnt_keepon; /* from "rohm,ddr-backup-power" */ + u8 bkup_mode_cnt_saved; + + /* Power switch type */ + bool rstbmode_level; + bool rstbmode_pulse; +}; + enum bd9571mwv_regulators { VD09, VD18, VD25, VD33, DVFS }; #define BD9571MWV_REG(_name, _of, _id, _ops, _vr, _vm, _nv, _min, _step, _lmin)\ @@ -131,14 +143,99 @@ static struct regulator_desc regulators[] = { 0x80, 600000, 10000, 0x3c), }; +#ifdef CONFIG_PM_SLEEP +static int bd9571mwv_bkup_mode_read(struct bd9571mwv *bd, unsigned int *mode) +{ + int ret; + + ret = regmap_read(bd->regmap, BD9571MWV_BKUP_MODE_CNT, mode); + if (ret) { + dev_err(bd->dev, "failed to read backup mode (%d)\n", ret); + return ret; + } + + return 0; +} + +static int bd9571mwv_bkup_mode_write(struct bd9571mwv *bd, unsigned int mode) +{ + int ret; + + ret = regmap_write(bd->regmap, BD9571MWV_BKUP_MODE_CNT, mode); + if (ret) { + dev_err(bd->dev, "failed to configure backup mode 0x%x (%d)\n", + mode, ret); + return ret; + } + + return 0; +} + +static int bd9571mwv_suspend(struct device *dev) +{ + struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev); + unsigned int mode; + int ret; + + if (!device_may_wakeup(dev)) + return 0; + + /* Save DDR Backup Mode */ + ret = bd9571mwv_bkup_mode_read(bdreg->bd, &mode); + if (ret) + return ret; + + bdreg->bkup_mode_cnt_saved = mode; + + if (!bdreg->rstbmode_pulse) + return 0; + + /* Enable DDR Backup Mode */ + mode &= ~BD9571MWV_BKUP_MODE_CNT_KEEPON_MASK; + mode |= bdreg->bkup_mode_cnt_keepon; + + if (mode != bdreg->bkup_mode_cnt_saved) + return bd9571mwv_bkup_mode_write(bdreg->bd, mode); + + return 0; +} + +static int bd9571mwv_resume(struct device *dev) +{ + struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev); + + if (!device_may_wakeup(dev)) + return 0; + + /* Restore DDR Backup Mode */ + return bd9571mwv_bkup_mode_write(bdreg->bd, bdreg->bkup_mode_cnt_saved); +} + +static const struct dev_pm_ops bd9571mwv_pm = { + SET_SYSTEM_SLEEP_PM_OPS(bd9571mwv_suspend, bd9571mwv_resume) +}; + +#define DEV_PM_OPS &bd9571mwv_pm +#else +#define DEV_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ + static int bd9571mwv_regulator_probe(struct platform_device *pdev) { struct bd9571mwv *bd = dev_get_drvdata(pdev->dev.parent); struct regulator_config config = { }; + struct bd9571mwv_reg *bdreg; struct regulator_dev *rdev; + unsigned int val; int i; - platform_set_drvdata(pdev, bd); + bdreg = devm_kzalloc(&pdev->dev, sizeof(*bdreg), GFP_KERNEL); + if (!bdreg) + return -ENOMEM; + + bdreg->bd = bd; + + platform_set_drvdata(pdev, bdreg); config.dev = &pdev->dev; config.dev->of_node = bd->dev->of_node; @@ -155,6 +252,33 @@ static int bd9571mwv_regulator_probe(struct platform_device *pdev) } } + val = 0; + of_property_read_u32(bd->dev->of_node, "rohm,ddr-backup-power", &val); + if (val & ~BD9571MWV_BKUP_MODE_CNT_KEEPON_MASK) { + dev_err(bd->dev, "invalid %s mode %u\n", + "rohm,ddr-backup-power", val); + return -EINVAL; + } + bdreg->bkup_mode_cnt_keepon = val; + + bdreg->rstbmode_level = of_property_read_bool(bd->dev->of_node, + "rohm,rstbmode-level"); + bdreg->rstbmode_pulse = of_property_read_bool(bd->dev->of_node, + "rohm,rstbmode-pulse"); + if (bdreg->rstbmode_level && bdreg->rstbmode_pulse) { + dev_err(bd->dev, "only one rohm,rstbmode-* may be specified"); + return -EINVAL; + } + + if (bdreg->bkup_mode_cnt_keepon) { + device_set_wakeup_capable(&pdev->dev, true); + /* + * Wakeup is enabled by default in pulse mode, but needs + * explicit user setup in level mode. + */ + device_set_wakeup_enable(&pdev->dev, bdreg->rstbmode_pulse); + } + return 0; } @@ -167,6 +291,7 @@ MODULE_DEVICE_TABLE(platform, bd9571mwv_regulator_id_table); static struct platform_driver bd9571mwv_regulator_driver = { .driver = { .name = "bd9571mwv-regulator", + .pm = DEV_PM_OPS, }, .probe = bd9571mwv_regulator_probe, .id_table = bd9571mwv_regulator_id_table, diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index d4803460a557..6ed568b96c0e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -147,6 +147,56 @@ static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev) } /** + * regulator_lock_nested - lock a single regulator + * @rdev: regulator source + * @subclass: mutex subclass used for lockdep + * + * This function can be called many times by one task on + * a single regulator and its mutex will be locked only + * once. If a task, which is calling this function is other + * than the one, which initially locked the mutex, it will + * wait on mutex. + */ +static void regulator_lock_nested(struct regulator_dev *rdev, + unsigned int subclass) +{ + if (!mutex_trylock(&rdev->mutex)) { + if (rdev->mutex_owner == current) { + rdev->ref_cnt++; + return; + } + mutex_lock_nested(&rdev->mutex, subclass); + } + + rdev->ref_cnt = 1; + rdev->mutex_owner = current; +} + +static inline void regulator_lock(struct regulator_dev *rdev) +{ + regulator_lock_nested(rdev, 0); +} + +/** + * regulator_unlock - unlock a single regulator + * @rdev: regulator_source + * + * This function unlocks the mutex when the + * reference counter reaches 0. + */ +static void regulator_unlock(struct regulator_dev *rdev) +{ + if (rdev->ref_cnt != 0) { + rdev->ref_cnt--; + + if (!rdev->ref_cnt) { + rdev->mutex_owner = NULL; + mutex_unlock(&rdev->mutex); + } + } +} + +/** * regulator_lock_supply - lock a regulator and its supplies * @rdev: regulator source */ @@ -155,7 +205,7 @@ static void regulator_lock_supply(struct regulator_dev *rdev) int i; for (i = 0; rdev; rdev = rdev_get_supply(rdev), i++) - mutex_lock_nested(&rdev->mutex, i); + regulator_lock_nested(rdev, i); } /** @@ -167,7 +217,7 @@ static void regulator_unlock_supply(struct regulator_dev *rdev) struct regulator *supply; while (1) { - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); supply = rdev->supply; if (!rdev->supply) @@ -350,9 +400,9 @@ static ssize_t regulator_uV_show(struct device *dev, struct regulator_dev *rdev = dev_get_drvdata(dev); ssize_t ret; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev)); - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return ret; } @@ -416,9 +466,9 @@ static ssize_t regulator_state_show(struct device *dev, struct regulator_dev *rdev = dev_get_drvdata(dev); ssize_t ret; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return ret; } @@ -526,10 +576,10 @@ static ssize_t regulator_total_uA_show(struct device *dev, struct regulator *regulator; int uA = 0; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); list_for_each_entry(regulator, &rdev->consumer_list, list) uA += regulator->uA_load; - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return sprintf(buf, "%d\n", uA); } static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); @@ -886,6 +936,18 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, rdev->constraints->min_uV && rdev->constraints->max_uV) { int target_min, target_max; int current_uV = _regulator_get_voltage(rdev); + + if (current_uV == -ENOTRECOVERABLE) { + /* This regulator can't be read and must be initted */ + rdev_info(rdev, "Setting %d-%duV\n", + rdev->constraints->min_uV, + rdev->constraints->max_uV); + _regulator_do_set_voltage(rdev, + rdev->constraints->min_uV, + rdev->constraints->max_uV); + current_uV = _regulator_get_voltage(rdev); + } + if (current_uV < 0) { rdev_err(rdev, "failed to get the current voltage(%d)\n", @@ -1321,7 +1383,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, if (regulator == NULL) return NULL; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); regulator->rdev = rdev; list_add(®ulator->list, &rdev->consumer_list); @@ -1376,12 +1438,12 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, _regulator_is_enabled(rdev)) regulator->always_on = true; - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return regulator; overflow_err: list_del(®ulator->list); kfree(regulator); - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return NULL; } @@ -1770,13 +1832,13 @@ static void _regulator_put(struct regulator *regulator) /* remove any sysfs entries */ if (regulator->dev) sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); - mutex_lock(&rdev->mutex); + regulator_lock(rdev); list_del(®ulator->list); rdev->open_count--; rdev->exclusive = 0; put_device(&rdev->dev); - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); kfree_const(regulator->supply_name); kfree(regulator); @@ -2384,7 +2446,7 @@ static void regulator_disable_work(struct work_struct *work) disable_work.work); int count, i, ret; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); BUG_ON(!rdev->deferred_disables); @@ -2405,7 +2467,7 @@ static void regulator_disable_work(struct work_struct *work) rdev_err(rdev, "Deferred disable failed: %d\n", ret); } - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); if (rdev->supply) { for (i = 0; i < count; i++) { @@ -2440,11 +2502,11 @@ int regulator_disable_deferred(struct regulator *regulator, int ms) if (!ms) return regulator_disable(regulator); - mutex_lock(&rdev->mutex); + regulator_lock(rdev); rdev->deferred_disables++; mod_delayed_work(system_power_efficient_wq, &rdev->disable_work, msecs_to_jiffies(ms)); - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return 0; } @@ -2476,10 +2538,10 @@ static int _regulator_list_voltage(struct regulator_dev *rdev, if (selector >= rdev->desc->n_voltages) return -EINVAL; if (lock) - mutex_lock(&rdev->mutex); + regulator_lock(rdev); ret = ops->list_voltage(rdev, selector); if (lock) - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); } else if (rdev->is_switch && rdev->supply) { ret = _regulator_list_voltage(rdev->supply->rdev, selector, lock); @@ -3252,7 +3314,7 @@ int regulator_sync_voltage(struct regulator *regulator) struct regulator_voltage *voltage = ®ulator->voltage[PM_SUSPEND_ON]; int ret, min_uV, max_uV; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); if (!rdev->desc->ops->set_voltage && !rdev->desc->ops->set_voltage_sel) { @@ -3281,7 +3343,7 @@ int regulator_sync_voltage(struct regulator *regulator) ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); out: - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return ret; } EXPORT_SYMBOL_GPL(regulator_sync_voltage); @@ -3374,7 +3436,7 @@ int regulator_set_current_limit(struct regulator *regulator, struct regulator_dev *rdev = regulator->rdev; int ret; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); /* sanity check */ if (!rdev->desc->ops->set_current_limit) { @@ -3389,7 +3451,7 @@ int regulator_set_current_limit(struct regulator *regulator, ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); out: - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return ret; } EXPORT_SYMBOL_GPL(regulator_set_current_limit); @@ -3398,7 +3460,7 @@ static int _regulator_get_current_limit(struct regulator_dev *rdev) { int ret; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); /* sanity check */ if (!rdev->desc->ops->get_current_limit) { @@ -3408,7 +3470,7 @@ static int _regulator_get_current_limit(struct regulator_dev *rdev) ret = rdev->desc->ops->get_current_limit(rdev); out: - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return ret; } @@ -3444,7 +3506,7 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode) int ret; int regulator_curr_mode; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); /* sanity check */ if (!rdev->desc->ops->set_mode) { @@ -3468,7 +3530,7 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode) ret = rdev->desc->ops->set_mode(rdev, mode); out: - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return ret; } EXPORT_SYMBOL_GPL(regulator_set_mode); @@ -3477,7 +3539,7 @@ static unsigned int _regulator_get_mode(struct regulator_dev *rdev) { int ret; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); /* sanity check */ if (!rdev->desc->ops->get_mode) { @@ -3487,7 +3549,7 @@ static unsigned int _regulator_get_mode(struct regulator_dev *rdev) ret = rdev->desc->ops->get_mode(rdev); out: - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return ret; } @@ -3508,7 +3570,7 @@ static int _regulator_get_error_flags(struct regulator_dev *rdev, { int ret; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); /* sanity check */ if (!rdev->desc->ops->get_error_flags) { @@ -3518,7 +3580,7 @@ static int _regulator_get_error_flags(struct regulator_dev *rdev, ret = rdev->desc->ops->get_error_flags(rdev, flags); out: - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return ret; } @@ -3567,10 +3629,10 @@ int regulator_set_load(struct regulator *regulator, int uA_load) struct regulator_dev *rdev = regulator->rdev; int ret; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); regulator->uA_load = uA_load; ret = drms_uA_update(rdev); - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return ret; } @@ -3598,7 +3660,7 @@ int regulator_allow_bypass(struct regulator *regulator, bool enable) if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS)) return 0; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); if (enable && !regulator->bypass) { rdev->bypass_count++; @@ -3622,7 +3684,7 @@ int regulator_allow_bypass(struct regulator *regulator, bool enable) if (ret == 0) regulator->bypass = enable; - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return ret; } @@ -4067,6 +4129,96 @@ static int regulator_register_resolve_supply(struct device *dev, void *data) return 0; } +static int regulator_fill_coupling_array(struct regulator_dev *rdev) +{ + struct coupling_desc *c_desc = &rdev->coupling_desc; + int n_coupled = c_desc->n_coupled; + struct regulator_dev *c_rdev; + int i; + + for (i = 1; i < n_coupled; i++) { + /* already resolved */ + if (c_desc->coupled_rdevs[i]) + continue; + + c_rdev = of_parse_coupled_regulator(rdev, i - 1); + + if (c_rdev) { + c_desc->coupled_rdevs[i] = c_rdev; + c_desc->n_resolved++; + } + } + + if (rdev->coupling_desc.n_resolved < n_coupled) + return -1; + else + return 0; +} + +static int regulator_register_fill_coupling_array(struct device *dev, + void *data) +{ + struct regulator_dev *rdev = dev_to_rdev(dev); + + if (!IS_ENABLED(CONFIG_OF)) + return 0; + + if (regulator_fill_coupling_array(rdev)) + rdev_dbg(rdev, "unable to resolve coupling\n"); + + return 0; +} + +static int regulator_resolve_coupling(struct regulator_dev *rdev) +{ + int n_phandles; + + if (!IS_ENABLED(CONFIG_OF)) + n_phandles = 0; + else + n_phandles = of_get_n_coupled(rdev); + + if (n_phandles + 1 > MAX_COUPLED) { + rdev_err(rdev, "too many regulators coupled\n"); + return -EPERM; + } + + /* + * Every regulator should always have coupling descriptor filled with + * at least pointer to itself. + */ + rdev->coupling_desc.coupled_rdevs[0] = rdev; + rdev->coupling_desc.n_coupled = n_phandles + 1; + rdev->coupling_desc.n_resolved++; + + /* regulator isn't coupled */ + if (n_phandles == 0) + return 0; + + /* regulator, which can't change its voltage, can't be coupled */ + if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { + rdev_err(rdev, "voltage operation not allowed\n"); + return -EPERM; + } + + if (rdev->constraints->max_spread <= 0) { + rdev_err(rdev, "wrong max_spread value\n"); + return -EPERM; + } + + if (!of_check_coupling_data(rdev)) + return -EPERM; + + /* + * After everything has been checked, try to fill rdevs array + * with pointers to regulators parsed from device tree. If some + * regulators are not registered yet, retry in late init call + */ + regulator_fill_coupling_array(rdev); + + return 0; +} + /** * regulator_register - register regulator * @regulator_desc: regulator to register @@ -4200,6 +4352,13 @@ regulator_register(const struct regulator_desc *regulator_desc, if (ret < 0) goto wash; + mutex_lock(®ulator_list_mutex); + ret = regulator_resolve_coupling(rdev); + mutex_unlock(®ulator_list_mutex); + + if (ret != 0) + goto wash; + /* add consumers devices */ if (init_data) { mutex_lock(®ulator_list_mutex); @@ -4288,9 +4447,9 @@ static int _regulator_suspend_late(struct device *dev, void *data) suspend_state_t *state = data; int ret; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); ret = suspend_set_state(rdev, *state); - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return ret; } @@ -4320,14 +4479,14 @@ static int _regulator_resume_early(struct device *dev, void *data) if (rstate == NULL) return 0; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); if (rdev->desc->ops->resume_early && (rstate->enabled == ENABLE_IN_SUSPEND || rstate->enabled == DISABLE_IN_SUSPEND)) ret = rdev->desc->ops->resume_early(rdev); - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return ret; } @@ -4629,7 +4788,7 @@ static int __init regulator_late_cleanup(struct device *dev, void *data) if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) return 0; - mutex_lock(&rdev->mutex); + regulator_lock(rdev); if (rdev->use_count) goto unlock; @@ -4660,7 +4819,7 @@ static int __init regulator_late_cleanup(struct device *dev, void *data) } unlock: - mutex_unlock(&rdev->mutex); + regulator_unlock(rdev); return 0; } @@ -4694,6 +4853,9 @@ static int __init regulator_init_complete(void) class_for_each_device(®ulator_class, NULL, NULL, regulator_late_cleanup); + class_for_each_device(®ulator_class, NULL, NULL, + regulator_register_fill_coupling_array); + return 0; } late_initcall_sync(regulator_init_complete); diff --git a/drivers/regulator/cpcap-regulator.c b/drivers/regulator/cpcap-regulator.c index f541b80f1b54..bd910fe123d9 100644 --- a/drivers/regulator/cpcap-regulator.c +++ b/drivers/regulator/cpcap-regulator.c @@ -222,7 +222,7 @@ static unsigned int cpcap_map_mode(unsigned int mode) case CPCAP_BIT_AUDIO_LOW_PWR: return REGULATOR_MODE_STANDBY; default: - return -EINVAL; + return REGULATOR_MODE_INVALID; } } diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h index abfd56e8c78a..943926a156f2 100644 --- a/drivers/regulator/internal.h +++ b/drivers/regulator/internal.h @@ -56,14 +56,27 @@ static inline struct regulator_dev *dev_to_rdev(struct device *dev) return container_of(dev, struct regulator_dev, dev); } -struct regulator_dev *of_find_regulator_by_node(struct device_node *np); - #ifdef CONFIG_OF +struct regulator_dev *of_find_regulator_by_node(struct device_node *np); struct regulator_init_data *regulator_of_get_init_data(struct device *dev, const struct regulator_desc *desc, struct regulator_config *config, struct device_node **node); + +struct regulator_dev *of_parse_coupled_regulator(struct regulator_dev *rdev, + int index); + +int of_get_n_coupled(struct regulator_dev *rdev); + +bool of_check_coupling_data(struct regulator_dev *rdev); + #else +static inline struct regulator_dev * +of_find_regulator_by_node(struct device_node *np) +{ + return NULL; +} + static inline struct regulator_init_data * regulator_of_get_init_data(struct device *dev, const struct regulator_desc *desc, @@ -72,8 +85,25 @@ regulator_of_get_init_data(struct device *dev, { return NULL; } -#endif +static inline struct regulator_dev * +of_parse_coupled_regulator(struct regulator_dev *rdev, + int index) +{ + return NULL; +} + +static inline int of_get_n_coupled(struct regulator_dev *rdev) +{ + return 0; +} + +static inline bool of_check_coupling_data(struct regulator_dev *rdev) +{ + return false; +} + +#endif enum regulator_get_type { NORMAL_GET, EXCLUSIVE_GET, @@ -83,5 +113,4 @@ enum regulator_get_type { struct regulator *_regulator_get(struct device *dev, const char *id, enum regulator_get_type get_type); - #endif diff --git a/drivers/regulator/lm363x-regulator.c b/drivers/regulator/lm363x-regulator.c index ce5f7d9ad475..b615a413ca9f 100644 --- a/drivers/regulator/lm363x-regulator.c +++ b/drivers/regulator/lm363x-regulator.c @@ -16,7 +16,7 @@ #include <linux/mfd/ti-lmu-register.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> @@ -219,7 +219,7 @@ static const struct regulator_desc lm363x_regulator_desc[] = { }, }; -static int lm363x_regulator_of_get_enable_gpio(struct device_node *np, int id) +static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev, int id) { /* * Check LCM_EN1/2_GPIO is configured. @@ -227,11 +227,11 @@ static int lm363x_regulator_of_get_enable_gpio(struct device_node *np, int id) */ switch (id) { case LM3632_LDO_POS: - return of_get_named_gpio(np, "enable-gpios", 0); + return devm_gpiod_get_index_optional(dev, "enable", 0, GPIOD_OUT_LOW); case LM3632_LDO_NEG: - return of_get_named_gpio(np, "enable-gpios", 1); + return devm_gpiod_get_index_optional(dev, "enable", 1, GPIOD_OUT_LOW); default: - return -EINVAL; + return NULL; } } @@ -243,7 +243,8 @@ static int lm363x_regulator_probe(struct platform_device *pdev) struct regulator_dev *rdev; struct device *dev = &pdev->dev; int id = pdev->id; - int ret, ena_gpio; + struct gpio_desc *gpiod; + int ret; cfg.dev = dev; cfg.regmap = regmap; @@ -252,10 +253,9 @@ static int lm363x_regulator_probe(struct platform_device *pdev) * LM3632 LDOs can be controlled by external pin. * Register update is required if the pin is used. */ - ena_gpio = lm363x_regulator_of_get_enable_gpio(dev->of_node, id); - if (gpio_is_valid(ena_gpio)) { - cfg.ena_gpio = ena_gpio; - cfg.ena_gpio_flags = GPIOF_OUT_INIT_LOW; + gpiod = lm363x_regulator_of_get_enable_gpio(dev, id); + if (gpiod) { + cfg.ena_gpiod = gpiod; ret = regmap_update_bits(regmap, LM3632_REG_BIAS_CONFIG, LM3632_EXT_EN_MASK, diff --git a/drivers/regulator/lp87565-regulator.c b/drivers/regulator/lp87565-regulator.c index cfdbe294fb6a..c192357d1dea 100644 --- a/drivers/regulator/lp87565-regulator.c +++ b/drivers/regulator/lp87565-regulator.c @@ -95,6 +95,10 @@ static int lp87565_buck_set_ramp_delay(struct regulator_dev *rdev, rdev->constraints->ramp_delay = lp87565_buck_ramp_delay[reg]; + /* Conservatively give a 15% margin */ + rdev->constraints->ramp_delay = + rdev->constraints->ramp_delay * 85 / 100; + return 0; } @@ -154,32 +158,33 @@ static const struct lp87565_regulator regulators[] = { LP87565_REGULATOR("BUCK0", LP87565_BUCK_0, "buck0", lp87565_buck_ops, 256, LP87565_REG_BUCK0_VOUT, LP87565_BUCK_VSET, LP87565_REG_BUCK0_CTRL_1, - LP87565_BUCK_CTRL_1_EN, 3800, + LP87565_BUCK_CTRL_1_EN, 3230, buck0_1_2_3_ranges, LP87565_REG_BUCK0_CTRL_2), LP87565_REGULATOR("BUCK1", LP87565_BUCK_1, "buck1", lp87565_buck_ops, 256, LP87565_REG_BUCK1_VOUT, LP87565_BUCK_VSET, LP87565_REG_BUCK1_CTRL_1, - LP87565_BUCK_CTRL_1_EN, 3800, + LP87565_BUCK_CTRL_1_EN, 3230, buck0_1_2_3_ranges, LP87565_REG_BUCK1_CTRL_2), LP87565_REGULATOR("BUCK2", LP87565_BUCK_2, "buck2", lp87565_buck_ops, 256, LP87565_REG_BUCK2_VOUT, LP87565_BUCK_VSET, LP87565_REG_BUCK2_CTRL_1, - LP87565_BUCK_CTRL_1_EN, 3800, + LP87565_BUCK_CTRL_1_EN, 3230, buck0_1_2_3_ranges, LP87565_REG_BUCK2_CTRL_2), LP87565_REGULATOR("BUCK3", LP87565_BUCK_3, "buck3", lp87565_buck_ops, 256, LP87565_REG_BUCK3_VOUT, LP87565_BUCK_VSET, LP87565_REG_BUCK3_CTRL_1, - LP87565_BUCK_CTRL_1_EN, 3800, + LP87565_BUCK_CTRL_1_EN, 3230, buck0_1_2_3_ranges, LP87565_REG_BUCK3_CTRL_2), LP87565_REGULATOR("BUCK10", LP87565_BUCK_10, "buck10", lp87565_buck_ops, 256, LP87565_REG_BUCK0_VOUT, LP87565_BUCK_VSET, LP87565_REG_BUCK0_CTRL_1, - LP87565_BUCK_CTRL_1_EN, 3800, + LP87565_BUCK_CTRL_1_EN | + LP87565_BUCK_CTRL_1_FPWM_MP_0_2, 3230, buck0_1_2_3_ranges, LP87565_REG_BUCK0_CTRL_2), LP87565_REGULATOR("BUCK23", LP87565_BUCK_23, "buck23", lp87565_buck_ops, 256, LP87565_REG_BUCK2_VOUT, LP87565_BUCK_VSET, LP87565_REG_BUCK2_CTRL_1, - LP87565_BUCK_CTRL_1_EN, 3800, + LP87565_BUCK_CTRL_1_EN, 3230, buck0_1_2_3_ranges, LP87565_REG_BUCK2_CTRL_2), }; diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c index cbfd35873575..f2347474a106 100644 --- a/drivers/regulator/lp8788-ldo.c +++ b/drivers/regulator/lp8788-ldo.c @@ -16,7 +16,7 @@ #include <linux/err.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/mfd/lp8788.h> /* register address */ @@ -85,8 +85,6 @@ #define LP8788_STARTUP_TIME_S 3 #define ENABLE_TIME_USEC 32 -#define ENABLE GPIOF_OUT_INIT_HIGH -#define DISABLE GPIOF_OUT_INIT_LOW enum lp8788_ldo_id { DLDO1, @@ -117,7 +115,7 @@ struct lp8788_ldo { struct lp8788 *lp; struct regulator_desc *desc; struct regulator_dev *regulator; - struct lp8788_ldo_enable_pin *en_pin; + struct gpio_desc *ena_gpiod; }; /* DLDO 1, 2, 3, 9 voltage table */ @@ -469,7 +467,6 @@ static int lp8788_config_ldo_enable_mode(struct platform_device *pdev, enum lp8788_ldo_id id) { struct lp8788 *lp = ldo->lp; - struct lp8788_platform_data *pdata = lp->pdata; enum lp8788_ext_ldo_en_id enable_id; u8 en_mask[] = { [EN_ALDO1] = LP8788_EN_SEL_ALDO1_M, @@ -504,11 +501,18 @@ static int lp8788_config_ldo_enable_mode(struct platform_device *pdev, return 0; } - /* if no platform data for ldo pin, then set default enable mode */ - if (!pdata || !pdata->ldo_pin || !pdata->ldo_pin[enable_id]) + /* FIXME: check default mode for GPIO here: high or low? */ + ldo->ena_gpiod = devm_gpiod_get_index_optional(&pdev->dev, + "enable", + enable_id, + GPIOD_OUT_HIGH); + if (IS_ERR(ldo->ena_gpiod)) + return PTR_ERR(ldo->ena_gpiod); + + /* if no GPIO for ldo pin, then set default enable mode */ + if (!ldo->ena_gpiod) goto set_default_ldo_enable_mode; - ldo->en_pin = pdata->ldo_pin[enable_id]; return 0; set_default_ldo_enable_mode: @@ -533,10 +537,8 @@ static int lp8788_dldo_probe(struct platform_device *pdev) if (ret) return ret; - if (ldo->en_pin) { - cfg.ena_gpio = ldo->en_pin->gpio; - cfg.ena_gpio_flags = ldo->en_pin->init_state; - } + if (ldo->ena_gpiod) + cfg.ena_gpiod = ldo->ena_gpiod; cfg.dev = pdev->dev.parent; cfg.init_data = lp->pdata ? lp->pdata->dldo_data[id] : NULL; @@ -582,10 +584,8 @@ static int lp8788_aldo_probe(struct platform_device *pdev) if (ret) return ret; - if (ldo->en_pin) { - cfg.ena_gpio = ldo->en_pin->gpio; - cfg.ena_gpio_flags = ldo->en_pin->init_state; - } + if (ldo->ena_gpiod) + cfg.ena_gpiod = ldo->ena_gpiod; cfg.dev = pdev->dev.parent; cfg.init_data = lp->pdata ? lp->pdata->aldo_data[id] : NULL; diff --git a/drivers/regulator/ltc3676.c b/drivers/regulator/ltc3676.c index 662ee05ea44d..9dec1609ff66 100644 --- a/drivers/regulator/ltc3676.c +++ b/drivers/regulator/ltc3676.c @@ -52,6 +52,7 @@ #define LTC3676_CLIRQ 0x1F #define LTC3676_DVBxA_REF_SELECT BIT(5) +#define LTC3676_DVBxB_PGOOD_MASK BIT(5) #define LTC3676_IRQSTAT_PGOOD_TIMEOUT BIT(3) #define LTC3676_IRQSTAT_UNDERVOLT_WARN BIT(4) @@ -123,6 +124,23 @@ static int ltc3676_set_suspend_mode(struct regulator_dev *rdev, mask, val); } +static int ltc3676_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) +{ + struct ltc3676 *ltc3676 = rdev_get_drvdata(rdev); + struct device *dev = ltc3676->dev; + int ret, dcdc = rdev_get_id(rdev); + + dev_dbg(dev, "%s id=%d selector=%d\n", __func__, dcdc, selector); + + ret = regmap_update_bits(ltc3676->regmap, rdev->desc->vsel_reg + 1, + LTC3676_DVBxB_PGOOD_MASK, + LTC3676_DVBxB_PGOOD_MASK); + if (ret) + return ret; + + return regulator_set_voltage_sel_regmap(rdev, selector); +} + static inline unsigned int ltc3676_scale(unsigned int uV, u32 r1, u32 r2) { uint64_t tmp; @@ -166,7 +184,7 @@ static const struct regulator_ops ltc3676_linear_regulator_ops = { .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, .list_voltage = regulator_list_voltage_linear, - .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_sel = ltc3676_set_voltage_sel, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_suspend_voltage = ltc3676_set_suspend_voltage, .set_suspend_mode = ltc3676_set_suspend_mode, diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 1096546c05e9..f1e77ed5dfec 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -27,6 +27,7 @@ #include <linux/regulator/driver.h> #include <linux/regulator/max8952.h> #include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/io.h> #include <linux/of.h> #include <linux/of_gpio.h> @@ -148,7 +149,6 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev) pd->gpio_vid0 = of_get_named_gpio(np, "max8952,vid-gpios", 0); pd->gpio_vid1 = of_get_named_gpio(np, "max8952,vid-gpios", 1); - pd->gpio_en = of_get_named_gpio(np, "max8952,en-gpio", 0); if (of_property_read_u32(np, "max8952,default-mode", &pd->default_mode)) dev_warn(dev, "Default mode not specified, assuming 0\n"); @@ -197,6 +197,8 @@ static int max8952_pmic_probe(struct i2c_client *client, struct regulator_config config = { }; struct max8952_data *max8952; struct regulator_dev *rdev; + struct gpio_desc *gpiod; + enum gpiod_flags gflags; int ret = 0, err = 0; @@ -224,11 +226,17 @@ static int max8952_pmic_probe(struct i2c_client *client, config.driver_data = max8952; config.of_node = client->dev.of_node; - config.ena_gpio = pdata->gpio_en; - if (client->dev.of_node) - config.ena_gpio_initialized = true; if (pdata->reg_data->constraints.boot_on) - config.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; + gflags = GPIOD_OUT_HIGH; + else + gflags = GPIOD_OUT_LOW; + gpiod = devm_gpiod_get_optional(&client->dev, + "max8952,en", + gflags); + if (IS_ERR(gpiod)) + return PTR_ERR(gpiod); + if (gpiod) + config.ena_gpiod = gpiod; rdev = devm_regulator_register(&client->dev, ®ulator, &config); if (IS_ERR(rdev)) { diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index e0c747aa9f85..7cd493ec6315 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -34,6 +34,7 @@ #include <linux/regulator/max8973-regulator.h> #include <linux/regulator/of_regulator.h> #include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/of_gpio.h> #include <linux/i2c.h> #include <linux/slab.h> @@ -114,7 +115,6 @@ struct max8973_chip { struct regulator_desc desc; struct regmap *regmap; bool enable_external_control; - int enable_gpio; int dvs_gpio; int lru_index[MAX8973_MAX_VOUT_REG]; int curr_vout_val[MAX8973_MAX_VOUT_REG]; @@ -567,7 +567,6 @@ static struct max8973_regulator_platform_data *max8973_parse_dt( pdata->enable_ext_control = of_property_read_bool(np, "maxim,externally-enable"); - pdata->enable_gpio = of_get_named_gpio(np, "maxim,enable-gpio", 0); pdata->dvs_gpio = of_get_named_gpio(np, "maxim,dvs-gpio", 0); ret = of_property_read_u32(np, "maxim,dvs-default-state", &pval); @@ -633,6 +632,8 @@ static int max8973_probe(struct i2c_client *client, struct max8973_chip *max; bool pdata_from_dt = false; unsigned int chip_id; + struct gpio_desc *gpiod; + enum gpiod_flags gflags; int ret; pdata = dev_get_platdata(&client->dev); @@ -647,8 +648,7 @@ static int max8973_probe(struct i2c_client *client, return -EIO; } - if ((pdata->dvs_gpio == -EPROBE_DEFER) || - (pdata->enable_gpio == -EPROBE_DEFER)) + if (pdata->dvs_gpio == -EPROBE_DEFER) return -EPROBE_DEFER; max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL); @@ -696,15 +696,11 @@ static int max8973_probe(struct i2c_client *client, max->desc.n_voltages = MAX8973_BUCK_N_VOLTAGE; max->dvs_gpio = (pdata->dvs_gpio) ? pdata->dvs_gpio : -EINVAL; - max->enable_gpio = (pdata->enable_gpio) ? pdata->enable_gpio : -EINVAL; max->enable_external_control = pdata->enable_ext_control; max->curr_gpio_val = pdata->dvs_def_state; max->curr_vout_reg = MAX8973_VOUT + pdata->dvs_def_state; max->junction_temp_warning = pdata->junction_temp_warning; - if (gpio_is_valid(max->enable_gpio)) - max->enable_external_control = true; - max->lru_index[0] = max->curr_vout_reg; if (gpio_is_valid(max->dvs_gpio)) { @@ -757,27 +753,35 @@ static int max8973_probe(struct i2c_client *client, break; } - if (gpio_is_valid(max->enable_gpio)) { - config.ena_gpio_flags = GPIOF_OUT_INIT_LOW; - if (ridata && (ridata->constraints.always_on || - ridata->constraints.boot_on)) - config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH; - config.ena_gpio = max->enable_gpio; + if (ridata && (ridata->constraints.always_on || + ridata->constraints.boot_on)) + gflags = GPIOD_OUT_HIGH; + else + gflags = GPIOD_OUT_LOW; + gpiod = devm_gpiod_get_optional(&client->dev, + "maxim,enable", + gflags); + if (IS_ERR(gpiod)) + return PTR_ERR(gpiod); + if (gpiod) { + config.ena_gpiod = gpiod; + max->enable_external_control = true; } + break; case MAX77621: - if (gpio_is_valid(max->enable_gpio)) { - ret = devm_gpio_request_one(&client->dev, - max->enable_gpio, GPIOF_OUT_INIT_HIGH, - "max8973-en-gpio"); - if (ret) { - dev_err(&client->dev, - "gpio_request for gpio %d failed: %d\n", - max->enable_gpio, ret); - return ret; - } - } + /* + * We do not let the core switch this regulator on/off, + * we just leave it on. + */ + gpiod = devm_gpiod_get_optional(&client->dev, + "maxim,enable", + GPIOD_OUT_HIGH); + if (IS_ERR(gpiod)) + return PTR_ERR(gpiod); + if (gpiod) + max->enable_external_control = true; max->desc.enable_reg = MAX8973_VOUT; max->desc.enable_mask = MAX8973_VOUT_ENABLE; diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 3027e7ce100b..6a2b61c012b5 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -309,8 +309,7 @@ static int max8998_set_voltage_buck_sel(struct regulator_dev *rdev, unsigned selector) { struct max8998_data *max8998 = rdev_get_drvdata(rdev); - struct max8998_platform_data *pdata = - dev_get_platdata(max8998->iodev->dev); + struct max8998_platform_data *pdata = max8998->iodev->pdata; struct i2c_client *i2c = max8998->iodev->i2c; int buck = rdev_get_id(rdev); int reg, shift = 0, mask, ret, j; diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 0e0277bd91a8..8fd1adc9c9a9 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -1,14 +1,10 @@ -/* - * Regulator Driver for Freescale MC13783 PMIC - * - * Copyright 2010 Yong Shen <yong.shen@linaro.org> - * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> - * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ +// SPDX-License-Identifier: GPL-2.0 +// +// Regulator Driver for Freescale MC13783 PMIC +// +// Copyright 2010 Yong Shen <yong.shen@linaro.org> +// Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> +// Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> #include <linux/mfd/mc13783.h> #include <linux/regulator/machine.h> diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 15dd7bc7b529..f3fba1cc1379 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -1,14 +1,10 @@ -/* - * Regulator Driver for Freescale MC13892 PMIC - * - * Copyright 2010 Yong Shen <yong.shen@linaro.org> - * - * Based on draft driver from Arnaud Patard <arnaud.patard@rtp-net.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ +// SPDX-License-Identifier: GPL-2.0 +// +// Regulator Driver for Freescale MC13892 PMIC +// +// Copyright 2010 Yong Shen <yong.shen@linaro.org> +// +// Based on draft driver from Arnaud Patard <arnaud.patard@rtp-net.org> #include <linux/mfd/mc13892.h> #include <linux/regulator/machine.h> diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index 0281c31ae2ed..41271aeea63e 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c @@ -1,19 +1,15 @@ -/* - * Regulator Driver for Freescale MC13xxx PMIC - * - * Copyright 2010 Yong Shen <yong.shen@linaro.org> - * - * Based on mc13783 regulator driver : - * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> - * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Regs infos taken from mc13xxx drivers from freescale and mc13xxx.pdf file - * from freescale - */ +// SPDX-License-Identifier: GPL-2.0 +// +// Regulator Driver for Freescale MC13xxx PMIC +// +// Copyright 2010 Yong Shen <yong.shen@linaro.org> +// +// Based on mc13783 regulator driver : +// Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> +// Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> +// +// Regs infos taken from mc13xxx drivers from freescale and mc13xxx.pdf file +// from freescale #include <linux/mfd/mc13xxx.h> #include <linux/regulator/machine.h> diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index f47264fa1940..638f17d4c848 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -31,7 +31,8 @@ static void of_get_regulation_constraints(struct device_node *np, struct regulation_constraints *constraints = &(*init_data)->constraints; struct regulator_state *suspend_state; struct device_node *suspend_np; - int ret, i; + unsigned int mode; + int ret, i, len; u32 pval; constraints->name = of_get_property(np, "regulator-name", NULL); @@ -124,20 +125,51 @@ static void of_get_regulation_constraints(struct device_node *np, if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) { if (desc && desc->of_map_mode) { - ret = desc->of_map_mode(pval); - if (ret == -EINVAL) + mode = desc->of_map_mode(pval); + if (mode == REGULATOR_MODE_INVALID) pr_err("%s: invalid mode %u\n", np->name, pval); else - constraints->initial_mode = ret; + constraints->initial_mode = mode; } else { pr_warn("%s: mapping for mode %d not defined\n", np->name, pval); } } + len = of_property_count_elems_of_size(np, "regulator-allowed-modes", + sizeof(u32)); + if (len > 0) { + if (desc && desc->of_map_mode) { + for (i = 0; i < len; i++) { + ret = of_property_read_u32_index(np, + "regulator-allowed-modes", i, &pval); + if (ret) { + pr_err("%s: couldn't read allowed modes index %d, ret=%d\n", + np->name, i, ret); + break; + } + mode = desc->of_map_mode(pval); + if (mode == REGULATOR_MODE_INVALID) + pr_err("%s: invalid regulator-allowed-modes element %u\n", + np->name, pval); + else + constraints->valid_modes_mask |= mode; + } + if (constraints->valid_modes_mask) + constraints->valid_ops_mask + |= REGULATOR_CHANGE_MODE; + } else { + pr_warn("%s: mode mapping not defined\n", np->name); + } + } + if (!of_property_read_u32(np, "regulator-system-load", &pval)) constraints->system_load = pval; + if (!of_property_read_u32(np, "regulator-coupled-max-spread", + &pval)) + constraints->max_spread = pval; + constraints->over_current_protection = of_property_read_bool(np, "regulator-over-current-protection"); @@ -163,12 +195,12 @@ static void of_get_regulation_constraints(struct device_node *np, if (!of_property_read_u32(suspend_np, "regulator-mode", &pval)) { if (desc && desc->of_map_mode) { - ret = desc->of_map_mode(pval); - if (ret == -EINVAL) + mode = desc->of_map_mode(pval); + if (mode == REGULATOR_MODE_INVALID) pr_err("%s: invalid mode %u\n", np->name, pval); else - suspend_state->mode = ret; + suspend_state->mode = mode; } else { pr_warn("%s: mapping for mode %d not defined\n", np->name, pval); @@ -407,3 +439,150 @@ struct regulator_dev *of_find_regulator_by_node(struct device_node *np) return dev ? dev_to_rdev(dev) : NULL; } + +/* + * Returns number of regulators coupled with rdev. + */ +int of_get_n_coupled(struct regulator_dev *rdev) +{ + struct device_node *node = rdev->dev.of_node; + int n_phandles; + + n_phandles = of_count_phandle_with_args(node, + "regulator-coupled-with", + NULL); + + return (n_phandles > 0) ? n_phandles : 0; +} + +/* Looks for "to_find" device_node in src's "regulator-coupled-with" property */ +static bool of_coupling_find_node(struct device_node *src, + struct device_node *to_find) +{ + int n_phandles, i; + bool found = false; + + n_phandles = of_count_phandle_with_args(src, + "regulator-coupled-with", + NULL); + + for (i = 0; i < n_phandles; i++) { + struct device_node *tmp = of_parse_phandle(src, + "regulator-coupled-with", i); + + if (!tmp) + break; + + /* found */ + if (tmp == to_find) + found = true; + + of_node_put(tmp); + + if (found) + break; + } + + return found; +} + +/** + * of_check_coupling_data - Parse rdev's coupling properties and check data + * consistency + * @rdev - pointer to regulator_dev whose data is checked + * + * Function checks if all the following conditions are met: + * - rdev's max_spread is greater than 0 + * - all coupled regulators have the same max_spread + * - all coupled regulators have the same number of regulator_dev phandles + * - all regulators are linked to each other + * + * Returns true if all conditions are met. + */ +bool of_check_coupling_data(struct regulator_dev *rdev) +{ + int max_spread = rdev->constraints->max_spread; + struct device_node *node = rdev->dev.of_node; + int n_phandles = of_get_n_coupled(rdev); + struct device_node *c_node; + int i; + bool ret = true; + + if (max_spread <= 0) { + dev_err(&rdev->dev, "max_spread value invalid\n"); + return false; + } + + /* iterate over rdev's phandles */ + for (i = 0; i < n_phandles; i++) { + int c_max_spread, c_n_phandles; + + c_node = of_parse_phandle(node, + "regulator-coupled-with", i); + + if (!c_node) + ret = false; + + c_n_phandles = of_count_phandle_with_args(c_node, + "regulator-coupled-with", + NULL); + + if (c_n_phandles != n_phandles) { + dev_err(&rdev->dev, "number of couped reg phandles mismatch\n"); + ret = false; + goto clean; + } + + if (of_property_read_u32(c_node, "regulator-coupled-max-spread", + &c_max_spread)) { + ret = false; + goto clean; + } + + if (c_max_spread != max_spread) { + dev_err(&rdev->dev, + "coupled regulators max_spread mismatch\n"); + ret = false; + goto clean; + } + + if (!of_coupling_find_node(c_node, node)) { + dev_err(&rdev->dev, "missing 2-way linking for coupled regulators\n"); + ret = false; + } + +clean: + of_node_put(c_node); + if (!ret) + break; + } + + return ret; +} + +/** + * of_parse_coupled regulator - Get regulator_dev pointer from rdev's property + * @rdev: Pointer to regulator_dev, whose DTS is used as a source to parse + * "regulator-coupled-with" property + * @index: Index in phandles array + * + * Returns the regulator_dev pointer parsed from DTS. If it has not been yet + * registered, returns NULL + */ +struct regulator_dev *of_parse_coupled_regulator(struct regulator_dev *rdev, + int index) +{ + struct device_node *node = rdev->dev.of_node; + struct device_node *c_node; + struct regulator_dev *c_rdev; + + c_node = of_parse_phandle(node, "regulator-coupled-with", index); + if (!c_node) + return NULL; + + c_rdev = of_find_regulator_by_node(c_node); + + of_node_put(c_node); + + return c_rdev; +} diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 63922a2167e5..8d9dbcc775ea 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -1,20 +1,7 @@ -/* - * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. + #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> @@ -86,6 +73,13 @@ static const int pfuze100_coin[] = { 2500000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000, }; +static const int pfuze3000_sw1a[] = { + 700000, 725000, 750000, 775000, 800000, 825000, 850000, 875000, + 900000, 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, + 1100000, 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, + 1300000, 1325000, 1350000, 1375000, 1400000, 1425000, 1800000, 3300000, +}; + static const int pfuze3000_sw2lo[] = { 1500000, 1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, }; @@ -148,6 +142,9 @@ static const struct regulator_ops pfuze100_fixed_regulator_ops = { }; static const struct regulator_ops pfuze100_sw_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, .list_voltage = regulator_list_voltage_linear, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -158,6 +155,7 @@ static const struct regulator_ops pfuze100_sw_regulator_ops = { static const struct regulator_ops pfuze100_swb_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .set_voltage_sel = regulator_set_voltage_sel_regmap, @@ -193,6 +191,11 @@ static const struct regulator_ops pfuze100_swb_regulator_ops = { .uV_step = (step), \ .vsel_reg = (base) + PFUZE100_VOL_OFFSET, \ .vsel_mask = 0x3f, \ + .enable_reg = (base) + PFUZE100_MODE_OFFSET, \ + .enable_val = 0xc, \ + .disable_val = 0x0, \ + .enable_mask = 0xf, \ + .enable_time = 500, \ }, \ .stby_reg = (base) + PFUZE100_STANDBY_OFFSET, \ .stby_mask = 0x3f, \ @@ -343,7 +346,7 @@ static struct pfuze_regulator pfuze200_regulators[] = { }; static struct pfuze_regulator pfuze3000_regulators[] = { - PFUZE100_SW_REG(PFUZE3000, SW1A, PFUZE100_SW1ABVOL, 700000, 1475000, 25000), + PFUZE100_SWB_REG(PFUZE3000, SW1A, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a), PFUZE100_SW_REG(PFUZE3000, SW1B, PFUZE100_SW1CVOL, 700000, 1475000, 25000), PFUZE100_SWB_REG(PFUZE3000, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo), PFUZE3000_SW3_REG(PFUZE3000, SW3, PFUZE100_SW3AVOL, 900000, 1650000, 50000), @@ -648,7 +651,6 @@ static int pfuze100_regulator_probe(struct i2c_client *client, config.init_data = init_data; config.driver_data = pfuze_chip; config.of_node = match_of_node(i); - config.ena_gpio = -EINVAL; pfuze_chip->regulators[i] = devm_regulator_register(&client->dev, desc, &config); diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index 63c7a0c17777..9817f1a75342 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -25,6 +25,8 @@ #include <linux/regulator/driver.h> #include <linux/regmap.h> #include <linux/list.h> +#include <linux/mfd/syscon.h> +#include <linux/io.h> /* Pin control enable input pins. */ #define SPMI_REGULATOR_PIN_CTRL_ENABLE_NONE 0x00 @@ -181,6 +183,23 @@ enum spmi_boost_byp_registers { SPMI_BOOST_BYP_REG_CURRENT_LIMIT = 0x4b, }; +enum spmi_saw3_registers { + SAW3_SECURE = 0x00, + SAW3_ID = 0x04, + SAW3_SPM_STS = 0x0C, + SAW3_AVS_STS = 0x10, + SAW3_PMIC_STS = 0x14, + SAW3_RST = 0x18, + SAW3_VCTL = 0x1C, + SAW3_AVS_CTL = 0x20, + SAW3_AVS_LIMIT = 0x24, + SAW3_AVS_DLY = 0x28, + SAW3_AVS_HYSTERESIS = 0x2C, + SAW3_SPM_STS2 = 0x38, + SAW3_SPM_PMIC_DATA_3 = 0x4C, + SAW3_VERSION = 0xFD0, +}; + /* Used for indexing into ctrl_reg. These are offets from 0x40 */ enum spmi_common_control_register_index { SPMI_COMMON_IDX_VOLTAGE_RANGE = 0, @@ -1035,6 +1054,89 @@ static irqreturn_t spmi_regulator_vs_ocp_isr(int irq, void *data) return IRQ_HANDLED; } +#define SAW3_VCTL_DATA_MASK 0xFF +#define SAW3_VCTL_CLEAR_MASK 0x700FF +#define SAW3_AVS_CTL_EN_MASK 0x1 +#define SAW3_AVS_CTL_TGGL_MASK 0x8000000 +#define SAW3_AVS_CTL_CLEAR_MASK 0x7efc00 + +static struct regmap *saw_regmap = NULL; + +static void spmi_saw_set_vdd(void *data) +{ + u32 vctl, data3, avs_ctl, pmic_sts; + bool avs_enabled = false; + unsigned long timeout; + u8 voltage_sel = *(u8 *)data; + + regmap_read(saw_regmap, SAW3_AVS_CTL, &avs_ctl); + regmap_read(saw_regmap, SAW3_VCTL, &vctl); + regmap_read(saw_regmap, SAW3_SPM_PMIC_DATA_3, &data3); + + /* select the band */ + vctl &= ~SAW3_VCTL_CLEAR_MASK; + vctl |= (u32)voltage_sel; + + data3 &= ~SAW3_VCTL_CLEAR_MASK; + data3 |= (u32)voltage_sel; + + /* If AVS is enabled, switch it off during the voltage change */ + avs_enabled = SAW3_AVS_CTL_EN_MASK & avs_ctl; + if (avs_enabled) { + avs_ctl &= ~SAW3_AVS_CTL_TGGL_MASK; + regmap_write(saw_regmap, SAW3_AVS_CTL, avs_ctl); + } + + regmap_write(saw_regmap, SAW3_RST, 1); + regmap_write(saw_regmap, SAW3_VCTL, vctl); + regmap_write(saw_regmap, SAW3_SPM_PMIC_DATA_3, data3); + + timeout = jiffies + usecs_to_jiffies(100); + do { + regmap_read(saw_regmap, SAW3_PMIC_STS, &pmic_sts); + pmic_sts &= SAW3_VCTL_DATA_MASK; + if (pmic_sts == (u32)voltage_sel) + break; + + cpu_relax(); + + } while (time_before(jiffies, timeout)); + + /* After successful voltage change, switch the AVS back on */ + if (avs_enabled) { + pmic_sts &= 0x3f; + avs_ctl &= ~SAW3_AVS_CTL_CLEAR_MASK; + avs_ctl |= ((pmic_sts - 4) << 10); + avs_ctl |= (pmic_sts << 17); + avs_ctl |= SAW3_AVS_CTL_TGGL_MASK; + regmap_write(saw_regmap, SAW3_AVS_CTL, avs_ctl); + } +} + +static int +spmi_regulator_saw_set_voltage(struct regulator_dev *rdev, unsigned selector) +{ + struct spmi_regulator *vreg = rdev_get_drvdata(rdev); + int ret; + u8 range_sel, voltage_sel; + + ret = spmi_sw_selector_to_hw(vreg, selector, &range_sel, &voltage_sel); + if (ret) + return ret; + + if (0 != range_sel) { + dev_dbg(&rdev->dev, "range_sel = %02X voltage_sel = %02X", \ + range_sel, voltage_sel); + return -EINVAL; + } + + /* Always do the SAW register writes on the first CPU */ + return smp_call_function_single(0, spmi_saw_set_vdd, \ + &voltage_sel, true); +} + +static struct regulator_ops spmi_saw_ops = {}; + static struct regulator_ops spmi_smps_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -1250,6 +1352,7 @@ static int spmi_regulator_match(struct spmi_regulator *vreg, u16 force_type) } dig_major_rev = version[SPMI_COMMON_REG_DIG_MAJOR_REV - SPMI_COMMON_REG_DIG_MAJOR_REV]; + if (!force_type) { type = version[SPMI_COMMON_REG_TYPE - SPMI_COMMON_REG_DIG_MAJOR_REV]; @@ -1648,7 +1751,9 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev) struct regmap *regmap; const char *name; struct device *dev = &pdev->dev; - int ret; + struct device_node *node = pdev->dev.of_node; + struct device_node *syscon; + int ret, lenp; struct list_head *vreg_list; vreg_list = devm_kzalloc(dev, sizeof(*vreg_list), GFP_KERNEL); @@ -1665,7 +1770,22 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev) if (!match) return -ENODEV; + if (of_find_property(node, "qcom,saw-reg", &lenp)) { + syscon = of_parse_phandle(node, "qcom,saw-reg", 0); + saw_regmap = syscon_node_to_regmap(syscon); + of_node_put(syscon); + if (IS_ERR(regmap)) + dev_err(dev, "ERROR reading SAW regmap\n"); + } + for (reg = match->data; reg->name; reg++) { + + if (saw_regmap && \ + of_find_property(of_find_node_by_name(node, reg->name), \ + "qcom,saw-slave", &lenp)) { + continue; + } + vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL); if (!vreg) return -ENOMEM; @@ -1673,7 +1793,6 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev) vreg->dev = dev; vreg->base = reg->base; vreg->regmap = regmap; - if (reg->ocp) { vreg->ocp_irq = platform_get_irq_byname(pdev, reg->ocp); if (vreg->ocp_irq < 0) { @@ -1681,7 +1800,6 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev) goto err; } } - vreg->desc.id = -1; vreg->desc.owner = THIS_MODULE; vreg->desc.type = REGULATOR_VOLTAGE; @@ -1698,6 +1816,15 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev) if (ret) continue; + if (saw_regmap && \ + of_find_property(of_find_node_by_name(node, reg->name), \ + "qcom,saw-leader", &lenp)) { + spmi_saw_ops = *(vreg->desc.ops); + spmi_saw_ops.set_voltage_sel = \ + spmi_regulator_saw_set_voltage; + vreg->desc.ops = &spmi_saw_ops; + } + config.dev = dev; config.driver_data = vreg; config.regmap = regmap; diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 4836947e1521..b8443a360646 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -13,6 +13,7 @@ #include <linux/err.h> #include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> @@ -459,15 +460,14 @@ static void s5m8767_regulator_config_ext_control(struct s5m8767_info *s5m8767, return; } - if (!gpio_is_valid(rdata->ext_control_gpio)) { + if (!rdata->ext_control_gpiod) { dev_warn(s5m8767->dev, "ext-control for %s: GPIO not valid, ignoring\n", - rdata->reg_node->name); + rdata->reg_node->name); return; } - config->ena_gpio = rdata->ext_control_gpio; - config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH; + config->ena_gpiod = rdata->ext_control_gpiod; } /* @@ -577,8 +577,14 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, continue; } - rdata->ext_control_gpio = of_get_named_gpio(reg_np, - "s5m8767,pmic-ext-control-gpios", 0); + rdata->ext_control_gpiod = devm_gpiod_get_from_of_node(&pdev->dev, + reg_np, + "s5m8767,pmic-ext-control-gpios", + 0, + GPIOD_OUT_HIGH, + "s5m8767"); + if (IS_ERR(rdata->ext_control_gpiod)) + return PTR_ERR(rdata->ext_control_gpiod); rdata->id = i; rdata->initdata = of_get_regulator_init_data( @@ -954,10 +960,8 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) config.driver_data = s5m8767; config.regmap = iodev->regmap_pmic; config.of_node = pdata->regulators[i].reg_node; - config.ena_gpio = -EINVAL; - config.ena_gpio_flags = 0; - config.ena_gpio_initialized = true; - if (gpio_is_valid(pdata->regulators[i].ext_control_gpio)) + config.ena_gpiod = NULL; + if (pdata->regulators[i].ext_control_gpiod) s5m8767_regulator_config_ext_control(s5m8767, &pdata->regulators[i], &config); @@ -970,7 +974,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) return ret; } - if (gpio_is_valid(pdata->regulators[i].ext_control_gpio)) { + if (pdata->regulators[i].ext_control_gpiod) { ret = s5m8767_enable_ext_control(s5m8767, rdev); if (ret < 0) { dev_err(s5m8767->dev, diff --git a/drivers/regulator/sy8106a-regulator.c b/drivers/regulator/sy8106a-regulator.c new file mode 100644 index 000000000000..65fbd1f0b612 --- /dev/null +++ b/drivers/regulator/sy8106a-regulator.c @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// sy8106a-regulator.c - Regulator device driver for SY8106A +// +// Copyright (C) 2016 Ondřej Jirman <megous@megous.com> +// Copyright (c) 2017-2018 Icenowy Zheng <icenowy@aosc.io> + +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/of_regulator.h> + +#define SY8106A_REG_VOUT1_SEL 0x01 +#define SY8106A_REG_VOUT_COM 0x02 +#define SY8106A_REG_VOUT1_SEL_MASK 0x7f +#define SY8106A_DISABLE_REG BIT(0) +/* + * The I2C controlled voltage will only work when this bit is set; otherwise + * it will behave like a fixed regulator. + */ +#define SY8106A_GO_BIT BIT(7) + +struct sy8106a { + struct regulator_dev *rdev; + struct regmap *regmap; + u32 fixed_voltage; +}; + +static const struct regmap_config sy8106a_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static const struct regulator_ops sy8106a_ops = { + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear, + /* Enabling/disabling the regulator is not yet implemented */ +}; + +/* Default limits measured in millivolts */ +#define SY8106A_MIN_MV 680 +#define SY8106A_MAX_MV 1950 +#define SY8106A_STEP_MV 10 + +static const struct regulator_desc sy8106a_reg = { + .name = "SY8106A", + .id = 0, + .ops = &sy8106a_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = ((SY8106A_MAX_MV - SY8106A_MIN_MV) / SY8106A_STEP_MV) + 1, + .min_uV = (SY8106A_MIN_MV * 1000), + .uV_step = (SY8106A_STEP_MV * 1000), + .vsel_reg = SY8106A_REG_VOUT1_SEL, + .vsel_mask = SY8106A_REG_VOUT1_SEL_MASK, + /* + * This ramp_delay is a conservative default value which works on + * H3/H5 boards VDD-CPUX situations. + */ + .ramp_delay = 200, + .owner = THIS_MODULE, +}; + +/* + * I2C driver interface functions + */ +static int sy8106a_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct sy8106a *chip; + struct device *dev = &i2c->dev; + struct regulator_dev *rdev = NULL; + struct regulator_config config = { }; + unsigned int reg, vsel; + int error; + + chip = devm_kzalloc(&i2c->dev, sizeof(struct sy8106a), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + error = of_property_read_u32(dev->of_node, "silergy,fixed-microvolt", + &chip->fixed_voltage); + if (error) + return error; + + if (chip->fixed_voltage < SY8106A_MIN_MV * 1000 || + chip->fixed_voltage > SY8106A_MAX_MV * 1000) + return -EINVAL; + + chip->regmap = devm_regmap_init_i2c(i2c, &sy8106a_regmap_config); + if (IS_ERR(chip->regmap)) { + error = PTR_ERR(chip->regmap); + dev_err(dev, "Failed to allocate register map: %d\n", error); + return error; + } + + config.dev = &i2c->dev; + config.regmap = chip->regmap; + config.driver_data = chip; + + config.of_node = dev->of_node; + config.init_data = of_get_regulator_init_data(dev, dev->of_node, + &sy8106a_reg); + + if (!config.init_data) + return -ENOMEM; + + /* Ensure GO_BIT is enabled when probing */ + error = regmap_read(chip->regmap, SY8106A_REG_VOUT1_SEL, ®); + if (error) + return error; + + if (!(reg & SY8106A_GO_BIT)) { + vsel = (chip->fixed_voltage / 1000 - SY8106A_MIN_MV) / + SY8106A_STEP_MV; + + error = regmap_write(chip->regmap, SY8106A_REG_VOUT1_SEL, + vsel | SY8106A_GO_BIT); + if (error) + return error; + } + + /* Probe regulator */ + rdev = devm_regulator_register(&i2c->dev, &sy8106a_reg, &config); + if (IS_ERR(rdev)) { + error = PTR_ERR(rdev); + dev_err(&i2c->dev, "Failed to register SY8106A regulator: %d\n", error); + return error; + } + + chip->rdev = rdev; + + i2c_set_clientdata(i2c, chip); + + return 0; +} + +static const struct of_device_id sy8106a_i2c_of_match[] = { + { .compatible = "silergy,sy8106a" }, + { }, +}; +MODULE_DEVICE_TABLE(of, sy8106a_i2c_of_match); + +static const struct i2c_device_id sy8106a_i2c_id[] = { + { "sy8106a", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, sy8106a_i2c_id); + +static struct i2c_driver sy8106a_regulator_driver = { + .driver = { + .name = "sy8106a", + .of_match_table = of_match_ptr(sy8106a_i2c_of_match), + }, + .probe = sy8106a_i2c_probe, + .id_table = sy8106a_i2c_id, +}; + +module_i2c_driver(sy8106a_regulator_driver); + +MODULE_AUTHOR("Ondřej Jirman <megous@megous.com>"); +MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.io>"); +MODULE_DESCRIPTION("Regulator device driver for Silergy SY8106A"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c index 395f35dc8cdb..2d398fa3b720 100644 --- a/drivers/regulator/tps65090-regulator.c +++ b/drivers/regulator/tps65090-regulator.c @@ -19,8 +19,8 @@ #include <linux/module.h> #include <linux/delay.h> #include <linux/init.h> -#include <linux/gpio.h> -#include <linux/of_gpio.h> +#include <linux/of.h> +#include <linux/gpio/consumer.h> #include <linux/slab.h> #include <linux/err.h> #include <linux/platform_device.h> @@ -300,26 +300,6 @@ static int tps65090_regulator_disable_ext_control( return tps65090_config_ext_control(ri, false); } -static void tps65090_configure_regulator_config( - struct tps65090_regulator_plat_data *tps_pdata, - struct regulator_config *config) -{ - if (gpio_is_valid(tps_pdata->gpio)) { - int gpio_flag = GPIOF_OUT_INIT_LOW; - - if (tps_pdata->reg_init_data->constraints.always_on || - tps_pdata->reg_init_data->constraints.boot_on) - gpio_flag = GPIOF_OUT_INIT_HIGH; - - config->ena_gpio = tps_pdata->gpio; - config->ena_gpio_initialized = true; - config->ena_gpio_flags = gpio_flag; - } else { - config->ena_gpio = -EINVAL; - config->ena_gpio_initialized = false; - } -} - #ifdef CONFIG_OF static struct of_regulator_match tps65090_matches[] = { { .name = "dcdc1", }, @@ -385,9 +365,26 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data( rpdata->enable_ext_control = of_property_read_bool( tps65090_matches[idx].of_node, "ti,enable-ext-control"); - if (rpdata->enable_ext_control) - rpdata->gpio = of_get_named_gpio(np, - "dcdc-ext-control-gpios", 0); + if (rpdata->enable_ext_control) { + enum gpiod_flags gflags; + + if (ri_data->constraints.always_on || + ri_data->constraints.boot_on) + gflags = GPIOD_OUT_HIGH; + else + gflags = GPIOD_OUT_LOW; + + rpdata->gpiod = devm_gpiod_get_from_of_node(&pdev->dev, + tps65090_matches[idx].of_node, + "dcdc-ext-control-gpios", 0, + gflags, + "tps65090"); + if (IS_ERR(rpdata->gpiod)) + return ERR_CAST(rpdata->gpiod); + if (!rpdata->gpiod) + dev_err(&pdev->dev, + "could not find DCDC external control GPIO\n"); + } if (of_property_read_u32(tps65090_matches[idx].of_node, "ti,overcurrent-wait", @@ -455,8 +452,7 @@ static int tps65090_regulator_probe(struct platform_device *pdev) */ if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data) { if (tps_pdata->enable_ext_control) { - tps65090_configure_regulator_config( - tps_pdata, &config); + config.ena_gpiod = tps_pdata->gpiod; ri->desc->ops = &tps65090_ext_control_ops; } else { ret = tps65090_regulator_disable_ext_control( diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 9e9d22038017..ba3dae7b2d2d 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -342,6 +342,7 @@ static struct tps6586x_regulator *find_regulator_info(int id, int version) switch (version) { case TPS658623: + case TPS658624: table = tps658623_regulator; num = ARRAY_SIZE(tps658623_regulator); break; diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index a4456db5849d..884c7505ed91 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -274,7 +274,7 @@ static inline unsigned int twl4030reg_map_mode(unsigned int mode) case RES_STATE_SLEEP: return REGULATOR_MODE_STANDBY; default: - return -EINVAL; + return REGULATOR_MODE_INVALID; } } diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index da9106bd2109..8ad11b074b49 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -911,6 +911,7 @@ static unsigned int get_mode(int uA, const struct wm8350_dcdc_efficiency *eff) while (eff[i].uA_load_min != -1) { if (uA >= eff[i].uA_load_min && uA <= eff[i].uA_load_max) return eff[i].mode; + i++; } return REGULATOR_MODE_NORMAL; } diff --git a/include/linux/mfd/bd9571mwv.h b/include/linux/mfd/bd9571mwv.h index f0708ba4cbba..eb05569f752b 100644 --- a/include/linux/mfd/bd9571mwv.h +++ b/include/linux/mfd/bd9571mwv.h @@ -33,6 +33,11 @@ #define BD9571MWV_I2C_MD2_E1_BIT_2 0x12 #define BD9571MWV_BKUP_MODE_CNT 0x20 +#define BD9571MWV_BKUP_MODE_CNT_KEEPON_MASK GENMASK(3, 0) +#define BD9571MWV_BKUP_MODE_CNT_KEEPON_DDR0 BIT(0) +#define BD9571MWV_BKUP_MODE_CNT_KEEPON_DDR1 BIT(1) +#define BD9571MWV_BKUP_MODE_CNT_KEEPON_DDR0C BIT(2) +#define BD9571MWV_BKUP_MODE_CNT_KEEPON_DDR1C BIT(3) #define BD9571MWV_BKUP_MODE_STATUS 0x21 #define BD9571MWV_BKUP_RECOVERY_CNT 0x22 #define BD9571MWV_BKUP_CTRL_TIM_CNT 0x23 diff --git a/include/linux/mfd/lp8788.h b/include/linux/mfd/lp8788.h index 786bf6679a28..2010e0de3e34 100644 --- a/include/linux/mfd/lp8788.h +++ b/include/linux/mfd/lp8788.h @@ -182,20 +182,6 @@ struct lp8788_buck2_dvs { }; /* - * struct lp8788_ldo_enable_pin - * - * Basically, all LDOs are enabled through the I2C commands. - * But ALDO 1 ~ 5, 7, DLDO 7, 9, 11 can be enabled by external gpio pins. - * - * @gpio : gpio number which is used for enabling ldos - * @init_state : initial gpio state (ex. GPIOF_OUT_INIT_LOW) - */ -struct lp8788_ldo_enable_pin { - int gpio; - int init_state; -}; - -/* * struct lp8788_chg_param * @addr : charging control register address (range : 0x11 ~ 0x1C) * @val : charging parameter value @@ -288,7 +274,6 @@ struct lp8788_vib_platform_data { * @aldo_data : regulator initial data for analog ldo * @buck1_dvs : gpio configurations for buck1 dvs * @buck2_dvs : gpio configurations for buck2 dvs - * @ldo_pin : gpio configurations for enabling LDOs * @chg_pdata : platform data for charger driver * @alarm_sel : rtc alarm selection (1 or 2) * @bl_pdata : configurable data for backlight driver @@ -306,7 +291,6 @@ struct lp8788_platform_data { struct regulator_init_data *aldo_data[LP8788_NUM_ALDOS]; struct lp8788_buck1_dvs *buck1_dvs; struct lp8788_buck2_dvs *buck2_dvs; - struct lp8788_ldo_enable_pin *ldo_pin[EN_LDOS_MAX]; /* charger */ struct lp8788_charger_platform_data *chg_pdata; diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index 5a23dd4df432..28f4ae76271d 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -39,6 +39,8 @@ #define STEP_12_5_MV 12500 #define STEP_6_25_MV 6250 +struct gpio_desc; + enum sec_device_type { S5M8751X, S5M8763X, @@ -151,7 +153,7 @@ struct sec_regulator_data { int id; struct regulator_init_data *initdata; struct device_node *reg_node; - int ext_control_gpio; + struct gpio_desc *ext_control_gpiod; }; /* diff --git a/include/linux/mfd/tps65090.h b/include/linux/mfd/tps65090.h index 67d144b3b8f9..f05bf4a146e2 100644 --- a/include/linux/mfd/tps65090.h +++ b/include/linux/mfd/tps65090.h @@ -83,6 +83,8 @@ enum { #define TPS65090_MAX_REG TPS65090_REG_AD_OUT2 #define TPS65090_NUM_REGS (TPS65090_MAX_REG + 1) +struct gpio_desc; + struct tps65090 { struct device *dev; struct regmap *rmap; @@ -95,8 +97,8 @@ struct tps65090 { * @reg_init_data: The regulator init data. * @enable_ext_control: Enable extrenal control or not. Only available for * DCDC1, DCDC2 and DCDC3. - * @gpio: Gpio number if external control is enabled and controlled through - * gpio. + * @gpiod: Gpio descriptor if external control is enabled and controlled through + * gpio * @overcurrent_wait_valid: True if the overcurrent_wait should be applied. * @overcurrent_wait: Value to set as the overcurrent wait time. This is the * actual bitfield value, not a time in ms (valid value are 0 - 3). @@ -104,7 +106,7 @@ struct tps65090 { struct tps65090_regulator_plat_data { struct regulator_init_data *reg_init_data; bool enable_ext_control; - int gpio; + struct gpio_desc *gpiod; bool overcurrent_wait_valid; int overcurrent_wait; }; diff --git a/include/linux/mfd/tps6586x.h b/include/linux/mfd/tps6586x.h index 2fe68e481230..b19c2801a30e 100644 --- a/include/linux/mfd/tps6586x.h +++ b/include/linux/mfd/tps6586x.h @@ -18,6 +18,7 @@ #define TPS658621A 0x15 #define TPS658621CD 0x2c #define TPS658623 0x1b +#define TPS658624 0x0a #define TPS658640 0x01 #define TPS658640v2 0x02 #define TPS658643 0x03 diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index d8ecefaf63ca..6d46f962685d 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h @@ -49,47 +49,7 @@ enum ab8505_regulator_id { AB8505_NUM_REGULATORS, }; -/* AB9540 regulators */ -enum ab9540_regulator_id { - AB9540_LDO_AUX1, - AB9540_LDO_AUX2, - AB9540_LDO_AUX3, - AB9540_LDO_AUX4, - AB9540_LDO_INTCORE, - AB9540_LDO_TVOUT, - AB9540_LDO_USB, - AB9540_LDO_AUDIO, - AB9540_LDO_ANAMIC1, - AB9540_LDO_ANAMIC2, - AB9540_LDO_DMIC, - AB9540_LDO_ANA, - AB9540_SYSCLKREQ_2, - AB9540_SYSCLKREQ_4, - AB9540_NUM_REGULATORS, -}; - -/* AB8540 regulators */ -enum ab8540_regulator_id { - AB8540_LDO_AUX1, - AB8540_LDO_AUX2, - AB8540_LDO_AUX3, - AB8540_LDO_AUX4, - AB8540_LDO_AUX5, - AB8540_LDO_AUX6, - AB8540_LDO_INTCORE, - AB8540_LDO_TVOUT, - AB8540_LDO_AUDIO, - AB8540_LDO_ANAMIC1, - AB8540_LDO_ANAMIC2, - AB8540_LDO_DMIC, - AB8540_LDO_ANA, - AB8540_LDO_SDIO, - AB8540_SYSCLKREQ_2, - AB8540_SYSCLKREQ_4, - AB8540_NUM_REGULATORS, -}; - -/* AB8500, AB8505, and AB9540 register initialization */ +/* AB8500 and AB8505 register initialization */ struct ab8500_regulator_reg_init { int id; u8 mask; @@ -185,121 +145,6 @@ enum ab8505_regulator_reg { AB8505_NUM_REGULATOR_REGISTERS, }; -/* AB9540 registers */ -enum ab9540_regulator_reg { - AB9540_REGUREQUESTCTRL1, - AB9540_REGUREQUESTCTRL2, - AB9540_REGUREQUESTCTRL3, - AB9540_REGUREQUESTCTRL4, - AB9540_REGUSYSCLKREQ1HPVALID1, - AB9540_REGUSYSCLKREQ1HPVALID2, - AB9540_REGUHWHPREQ1VALID1, - AB9540_REGUHWHPREQ1VALID2, - AB9540_REGUHWHPREQ2VALID1, - AB9540_REGUHWHPREQ2VALID2, - AB9540_REGUSWHPREQVALID1, - AB9540_REGUSWHPREQVALID2, - AB9540_REGUSYSCLKREQVALID1, - AB9540_REGUSYSCLKREQVALID2, - AB9540_REGUVAUX4REQVALID, - AB9540_REGUMISC1, - AB9540_VAUDIOSUPPLY, - AB9540_REGUCTRL1VAMIC, - AB9540_VSMPS1REGU, - AB9540_VSMPS2REGU, - AB9540_VSMPS3REGU, /* NOTE! PRCMU register */ - AB9540_VPLLVANAREGU, - AB9540_EXTSUPPLYREGU, - AB9540_VAUX12REGU, - AB9540_VRF1VAUX3REGU, - AB9540_VSMPS1SEL1, - AB9540_VSMPS1SEL2, - AB9540_VSMPS1SEL3, - AB9540_VSMPS2SEL1, - AB9540_VSMPS2SEL2, - AB9540_VSMPS2SEL3, - AB9540_VSMPS3SEL1, /* NOTE! PRCMU register */ - AB9540_VSMPS3SEL2, /* NOTE! PRCMU register */ - AB9540_VAUX1SEL, - AB9540_VAUX2SEL, - AB9540_VRF1VAUX3SEL, - AB9540_REGUCTRL2SPARE, - AB9540_VAUX4REQCTRL, - AB9540_VAUX4REGU, - AB9540_VAUX4SEL, - AB9540_REGUCTRLDISCH, - AB9540_REGUCTRLDISCH2, - AB9540_REGUCTRLDISCH3, - AB9540_NUM_REGULATOR_REGISTERS, -}; - -/* AB8540 registers */ -enum ab8540_regulator_reg { - AB8540_REGUREQUESTCTRL1, - AB8540_REGUREQUESTCTRL2, - AB8540_REGUREQUESTCTRL3, - AB8540_REGUREQUESTCTRL4, - AB8540_REGUSYSCLKREQ1HPVALID1, - AB8540_REGUSYSCLKREQ1HPVALID2, - AB8540_REGUHWHPREQ1VALID1, - AB8540_REGUHWHPREQ1VALID2, - AB8540_REGUHWHPREQ2VALID1, - AB8540_REGUHWHPREQ2VALID2, - AB8540_REGUSWHPREQVALID1, - AB8540_REGUSWHPREQVALID2, - AB8540_REGUSYSCLKREQVALID1, - AB8540_REGUSYSCLKREQVALID2, - AB8540_REGUVAUX4REQVALID, - AB8540_REGUVAUX5REQVALID, - AB8540_REGUVAUX6REQVALID, - AB8540_REGUVCLKBREQVALID, - AB8540_REGUVRF1REQVALID, - AB8540_REGUMISC1, - AB8540_VAUDIOSUPPLY, - AB8540_REGUCTRL1VAMIC, - AB8540_VHSIC, - AB8540_VSDIO, - AB8540_VSMPS1REGU, - AB8540_VSMPS2REGU, - AB8540_VSMPS3REGU, - AB8540_VPLLVANAREGU, - AB8540_EXTSUPPLYREGU, - AB8540_VAUX12REGU, - AB8540_VRF1VAUX3REGU, - AB8540_VSMPS1SEL1, - AB8540_VSMPS1SEL2, - AB8540_VSMPS1SEL3, - AB8540_VSMPS2SEL1, - AB8540_VSMPS2SEL2, - AB8540_VSMPS2SEL3, - AB8540_VSMPS3SEL1, - AB8540_VSMPS3SEL2, - AB8540_VAUX1SEL, - AB8540_VAUX2SEL, - AB8540_VRF1VAUX3SEL, - AB8540_REGUCTRL2SPARE, - AB8540_VAUX4REQCTRL, - AB8540_VAUX4REGU, - AB8540_VAUX4SEL, - AB8540_VAUX5REQCTRL, - AB8540_VAUX5REGU, - AB8540_VAUX5SEL, - AB8540_VAUX6REQCTRL, - AB8540_VAUX6REGU, - AB8540_VAUX6SEL, - AB8540_VCLKBREQCTRL, - AB8540_VCLKBREGU, - AB8540_VCLKBSEL, - AB8540_VRF1REQCTRL, - AB8540_REGUCTRLDISCH, - AB8540_REGUCTRLDISCH2, - AB8540_REGUCTRLDISCH3, - AB8540_REGUCTRLDISCH4, - AB8540_VSIMSYSCLKCTRL, - AB8540_VANAVPLLSEL, - AB8540_NUM_REGULATOR_REGISTERS, -}; - /* AB8500 external regulators */ struct ab8500_ext_regulator_cfg { bool hwreq; /* requires hw mode or high power mode */ diff --git a/include/linux/regulator/arizona-ldo1.h b/include/linux/regulator/arizona-ldo1.h index c685f1277c63..fe74ab9990e6 100644 --- a/include/linux/regulator/arizona-ldo1.h +++ b/include/linux/regulator/arizona-ldo1.h @@ -14,9 +14,6 @@ struct regulator_init_data; struct arizona_ldo1_pdata { - /** GPIO controlling LDOENA, if any */ - int ldoena; - /** Regulator configuration for LDO1 */ const struct regulator_init_data *init_data; }; diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index df176d7c2b87..25602afd4844 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -80,6 +80,7 @@ struct regmap; * These modes can be OR'ed together to make up a mask of valid register modes. */ +#define REGULATOR_MODE_INVALID 0x0 #define REGULATOR_MODE_FAST 0x1 #define REGULATOR_MODE_NORMAL 0x2 #define REGULATOR_MODE_IDLE 0x4 diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 4fc96cb8e5d7..fc2dc8df476f 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -15,6 +15,8 @@ #ifndef __LINUX_REGULATOR_DRIVER_H_ #define __LINUX_REGULATOR_DRIVER_H_ +#define MAX_COUPLED 4 + #include <linux/device.h> #include <linux/notifier.h> #include <linux/regulator/consumer.h> @@ -81,9 +83,12 @@ struct regulator_linear_range { * @set_voltage_sel: Set the voltage for the regulator using the specified * selector. * @map_voltage: Convert a voltage into a selector - * @get_voltage: Return the currently configured voltage for the regulator. + * @get_voltage: Return the currently configured voltage for the regulator; + * return -ENOTRECOVERABLE if regulator can't be read at + * bootup and hasn't been set yet. * @get_voltage_sel: Return the currently configured voltage selector for the - * regulator. + * regulator; return -ENOTRECOVERABLE if regulator can't + * be read at bootup and hasn't been set yet. * @list_voltage: Return one of the supported voltages, in microvolts; zero * if the selector indicates a voltage that is unusable on this system; * or negative errno. Selectors range from zero to one less than @@ -407,6 +412,20 @@ struct regulator_config { }; /* + * struct coupling_desc + * + * Describes coupling of regulators. Each regulator should have + * at least a pointer to itself in coupled_rdevs array. + * When a new coupled regulator is resolved, n_resolved is + * incremented. + */ +struct coupling_desc { + struct regulator_dev *coupled_rdevs[MAX_COUPLED]; + int n_resolved; + int n_coupled; +}; + +/* * struct regulator_dev * * Voltage / Current regulator class device. One for each @@ -429,8 +448,12 @@ struct regulator_dev { /* lists we own */ struct list_head consumer_list; /* consumers we supply */ + struct coupling_desc coupling_desc; + struct blocking_notifier_head notifier; struct mutex mutex; /* consumer lock */ + struct task_struct *mutex_owner; + int ref_cnt; struct module *owner; struct device dev; struct regulation_constraints *constraints; diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 93a04893c739..3468703d663a 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -103,6 +103,7 @@ struct regulator_state { * @ilim_uA: Maximum input current. * @system_load: Load that isn't captured by any consumer requests. * + * @max_spread: Max possible spread between coupled regulators * @valid_modes_mask: Mask of modes which may be configured by consumers. * @valid_ops_mask: Operations which may be performed by consumers. * @@ -154,6 +155,9 @@ struct regulation_constraints { int system_load; + /* used for coupled regulators */ + int max_spread; + /* valid regulator operating modes for this machine */ unsigned int valid_modes_mask; diff --git a/include/linux/regulator/max8952.h b/include/linux/regulator/max8952.h index 4dbb63a1d4ab..686c42c041b5 100644 --- a/include/linux/regulator/max8952.h +++ b/include/linux/regulator/max8952.h @@ -120,7 +120,6 @@ enum { struct max8952_platform_data { int gpio_vid0; int gpio_vid1; - int gpio_en; u32 default_mode; u32 dvs_mode[MAX8952_NUM_DVS_MODE]; /* MAX8952_DVS_MODEx_XXXXmV */ |