diff options
-rw-r--r-- | Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt | 3 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/regulator/richtek,rt4831-regulator.yaml | 35 | ||||
-rw-r--r-- | MAINTAINERS | 4 | ||||
-rw-r--r-- | arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 9 | ||||
-rw-r--r-- | drivers/mfd/ab8500-core.c | 1 | ||||
-rw-r--r-- | drivers/regulator/Kconfig | 28 | ||||
-rw-r--r-- | drivers/regulator/Makefile | 3 | ||||
-rw-r--r-- | drivers/regulator/ab8500-ext.c | 422 | ||||
-rw-r--r-- | drivers/regulator/ab8500.c | 116 | ||||
-rw-r--r-- | drivers/regulator/atc260x-regulator.c | 539 | ||||
-rw-r--r-- | drivers/regulator/bd70528-regulator.c | 11 | ||||
-rw-r--r-- | drivers/regulator/bd71828-regulator.c | 13 | ||||
-rw-r--r-- | drivers/regulator/bd718x7-regulator.c | 20 | ||||
-rw-r--r-- | drivers/regulator/core.c | 6 | ||||
-rw-r--r-- | drivers/regulator/mcp16502.c | 2 | ||||
-rw-r--r-- | drivers/regulator/mtk-dvfsrc-regulator.c | 215 | ||||
-rw-r--r-- | drivers/regulator/qcom-rpmh-regulator.c | 26 | ||||
-rw-r--r-- | drivers/regulator/rt4831-regulator.c | 198 | ||||
-rw-r--r-- | include/linux/mfd/abx500/ab8500.h | 3 | ||||
-rw-r--r-- | include/linux/regulator/ab8500.h | 166 | ||||
-rw-r--r-- | lib/linear_ranges.c | 8 |
21 files changed, 1205 insertions, 623 deletions
diff --git a/Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt b/Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt index d86584ed4d93..451cc4e86b01 100644 --- a/Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt @@ -4,7 +4,8 @@ Required properties: - compatible: "microchip,mcp16502" - reg: I2C slave address - lpm-gpios: GPIO for LPM pin. Note that this GPIO *must* remain high during - suspend-to-ram, keeping the PMIC into HIBERNATE mode. + suspend-to-ram, keeping the PMIC into HIBERNATE mode; this + property is optional; - regulators: A node that houses a sub-node for each regulator within the device. Each sub-node is identified using the node's name. The content of each sub-node is defined by the diff --git a/Documentation/devicetree/bindings/regulator/richtek,rt4831-regulator.yaml b/Documentation/devicetree/bindings/regulator/richtek,rt4831-regulator.yaml new file mode 100644 index 000000000000..d9c23333e157 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/richtek,rt4831-regulator.yaml @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/richtek,rt4831-regulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Richtek RT4831 Display Bias Voltage Regulator + +maintainers: + - ChiYuan Huang <cy_huang@richtek.com> + +description: | + RT4831 is a multifunctional device that can provide power to the LCD display + and LCD backlight. + + For Display Bias Voltage DSVP and DSVN, the output range is about 4V to 6.5V. + It is sufficient to meet the current LCD power requirement. + + DSVLCM is a boost regulator in IC internal as DSVP and DSVN input power. + Its voltage should be configured above 0.15V to 0.2V gap larger than the + voltage needed for DSVP and DSVN. Too much voltage gap could improve the + voltage drop from the heavy loading scenario. But it also make the power + efficiency worse. It's a trade-off. + + Datasheet is available at + https://www.richtek.com/assets/product_file/RT4831A/DS4831A-05.pdf + +patternProperties: + "^DSV(LCM|P|N)$": + type: object + $ref: regulator.yaml# + description: + Properties for single Display Bias Voltage regulator. + +additionalProperties: false diff --git a/MAINTAINERS b/MAINTAINERS index cc1e6a5ee6e6..0f8ac3cbe286 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11688,9 +11688,9 @@ F: drivers/video/fbdev/atmel_lcdfb.c F: include/video/atmel_lcdc.h MICROCHIP MCP16502 PMIC DRIVER -M: Andrei Stefanescu <andrei.stefanescu@microchip.com> +M: Claudiu Beznea <claudiu.beznea@microchip.com> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Maintained +S: Supported F: Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt F: drivers/regulator/mcp16502.c diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts index ce22d4fa383e..7917754c99d6 100644 --- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts @@ -122,7 +122,7 @@ &apps_rsc { pm8009-rpmh-regulators { - compatible = "qcom,pm8009-rpmh-regulators"; + compatible = "qcom,pm8009-1-rpmh-regulators"; qcom,pmic-id = "f"; vdd-s1-supply = <&vph_pwr>; @@ -131,6 +131,13 @@ vdd-l5-l6-supply = <&vreg_bob>; vdd-l7-supply = <&vreg_s4a_1p8>; + vreg_s2f_0p95: smps2 { + regulator-name = "vreg_s2f_0p95"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <952000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>; + }; + vreg_l1f_1p1: ldo1 { regulator-name = "vreg_l1f_1p1"; regulator-min-microvolt = <1104000>; diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index a3bac9da8cbb..3b2276f04a98 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -21,7 +21,6 @@ #include <linux/mfd/abx500/ab8500.h> #include <linux/mfd/abx500/ab8500-bm.h> #include <linux/mfd/dbx500-prcmu.h> -#include <linux/regulator/ab8500.h> #include <linux/of.h> #include <linux/of_device.h> diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 5abdd29fb9f3..eafa13be6e3e 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -179,6 +179,14 @@ config REGULATOR_AS3722 AS3722 PMIC. This will enable support for all the software controllable DCDC/LDO regulators. +config REGULATOR_ATC260X + tristate "Actions Semi ATC260x PMIC Regulators" + depends on MFD_ATC260X + help + This driver provides support for the voltage regulators on the + ATC260x PMICs. This will enable support for all the software + controllable DCDC/LDO regulators. + config REGULATOR_AXP20X tristate "X-POWERS AXP20X PMIC Regulators" depends on MFD_AXP20X @@ -777,6 +785,16 @@ config REGULATOR_MT6397 This driver supports the control of different power rails of device through regulator interface. +config REGULATOR_MTK_DVFSRC + tristate "MediaTek DVFSRC regulator driver" + depends on MTK_DVFSRC + help + Say y here to control regulator by DVFSRC (dynamic voltage + and frequency scaling resource collector). + This driver supports to control regulators via the DVFSRC + of Mediatek. It allows for voting on regulator state + between multiple users. + config REGULATOR_PALMAS tristate "TI Palmas PMIC Regulators" depends on MFD_PALMAS @@ -969,6 +987,16 @@ config REGULATOR_RT4801 This adds support for voltage regulators in Richtek RT4801 Display Bias IC. The device supports two regulators (DSVP/DSVN). +config REGULATOR_RT4831 + tristate "Richtek RT4831 DSV Regulators" + depends on MFD_RT4831 + help + This adds support for voltage regulators in Richtek RT4831. + There are three regulators (VLCM/DSVP/DSVN). + VLCM is a virtual voltage input for DSVP/DSVN inside IC. + And DSVP/DSVN is the real Vout range from 4V to 6.5V. + It's common used to provide the power for the display panel. + config REGULATOR_RT5033 tristate "Richtek RT5033 Regulators" depends on MFD_RT5033 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 680e539f6579..bd93fbd1b124 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_REGULATOR_ARIZONA_MICSUPP) += arizona-micsupp.o obj-$(CONFIG_REGULATOR_ARM_SCMI) += scmi-regulator.o obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o +obj-$(CONFIG_REGULATOR_ATC260X) += atc260x-regulator.o obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o obj-$(CONFIG_REGULATOR_BD70528) += bd70528-regulator.o @@ -94,6 +95,7 @@ obj-$(CONFIG_REGULATOR_MT6358) += mt6358-regulator.o obj-$(CONFIG_REGULATOR_MT6360) += mt6360-regulator.o obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o +obj-$(CONFIG_REGULATOR_MTK_DVFSRC) += mtk-dvfsrc-regulator.o obj-$(CONFIG_REGULATOR_QCOM_LABIBB) += qcom-labibb-regulator.o obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o obj-$(CONFIG_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o @@ -118,6 +120,7 @@ obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o obj-$(CONFIG_REGULATOR_RN5T618) += rn5t618-regulator.o obj-$(CONFIG_REGULATOR_ROHM) += rohm-regulator.o obj-$(CONFIG_REGULATOR_RT4801) += rt4801-regulator.o +obj-$(CONFIG_REGULATOR_RT4831) += rt4831-regulator.o obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o obj-$(CONFIG_REGULATOR_RTMV20) += rtmv20-regulator.o obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c index 8bb43a671ded..4f26952caa56 100644 --- a/drivers/regulator/ab8500-ext.c +++ b/drivers/regulator/ab8500-ext.c @@ -22,403 +22,17 @@ #include <linux/regulator/of_regulator.h> #include <linux/mfd/abx500.h> #include <linux/mfd/abx500/ab8500.h> -#include <linux/regulator/ab8500.h> - -static struct regulator_consumer_supply ab8500_vaux1_consumers[] = { - /* Main display, u8500 R3 uib */ - REGULATOR_SUPPLY("vddi", "mcde_disp_sony_acx424akp.0"), - /* Main display, u8500 uib and ST uib */ - REGULATOR_SUPPLY("vdd1", "samsung_s6d16d0.0"), - /* Secondary display, ST uib */ - REGULATOR_SUPPLY("vdd1", "samsung_s6d16d0.1"), - /* SFH7741 proximity sensor */ - REGULATOR_SUPPLY("vcc", "gpio-keys.0"), - /* BH1780GLS ambient light sensor */ - REGULATOR_SUPPLY("vcc", "2-0029"), - /* lsm303dlh accelerometer */ - REGULATOR_SUPPLY("vdd", "2-0018"), - /* lsm303dlhc accelerometer */ - REGULATOR_SUPPLY("vdd", "2-0019"), - /* lsm303dlh magnetometer */ - REGULATOR_SUPPLY("vdd", "2-001e"), - /* Rohm BU21013 Touchscreen devices */ - REGULATOR_SUPPLY("avdd", "3-005c"), - REGULATOR_SUPPLY("avdd", "3-005d"), - /* Synaptics RMI4 Touchscreen device */ - REGULATOR_SUPPLY("vdd", "3-004b"), - /* L3G4200D Gyroscope device */ - REGULATOR_SUPPLY("vdd", "2-0068"), - /* Ambient light sensor device */ - REGULATOR_SUPPLY("vdd", "3-0029"), - /* Pressure sensor device */ - REGULATOR_SUPPLY("vdd", "2-005c"), - /* Cypress TrueTouch Touchscreen device */ - REGULATOR_SUPPLY("vcpin", "spi8.0"), - /* Camera device */ - REGULATOR_SUPPLY("vaux12v5", "mmio_camera"), -}; - -static struct regulator_consumer_supply ab8500_vaux2_consumers[] = { - /* On-board eMMC power */ - REGULATOR_SUPPLY("vmmc", "sdi4"), - /* AB8500 audio codec */ - REGULATOR_SUPPLY("vcc-N2158", "ab8500-codec.0"), - /* AB8500 accessory detect 1 */ - REGULATOR_SUPPLY("vcc-N2158", "ab8500-acc-det.0"), - /* AB8500 Tv-out device */ - REGULATOR_SUPPLY("vcc-N2158", "mcde_tv_ab8500.4"), - /* AV8100 HDMI device */ - REGULATOR_SUPPLY("vcc-N2158", "av8100_hdmi.3"), -}; - -static struct regulator_consumer_supply ab8500_vaux3_consumers[] = { - REGULATOR_SUPPLY("v-SD-STM", "stm"), - /* External MMC slot power */ - REGULATOR_SUPPLY("vmmc", "sdi0"), -}; - -static struct regulator_consumer_supply ab8500_vtvout_consumers[] = { - /* TV-out DENC supply */ - REGULATOR_SUPPLY("vtvout", "ab8500-denc.0"), - /* Internal general-purpose ADC */ - REGULATOR_SUPPLY("vddadc", "ab8500-gpadc.0"), - /* ADC for charger */ - REGULATOR_SUPPLY("vddadc", "ab8500-charger.0"), - /* AB8500 Tv-out device */ - REGULATOR_SUPPLY("vtvout", "mcde_tv_ab8500.4"), -}; - -static struct regulator_consumer_supply ab8500_vaud_consumers[] = { - /* AB8500 audio-codec main supply */ - REGULATOR_SUPPLY("vaud", "ab8500-codec.0"), -}; - -static struct regulator_consumer_supply ab8500_vamic1_consumers[] = { - /* AB8500 audio-codec Mic1 supply */ - REGULATOR_SUPPLY("vamic1", "ab8500-codec.0"), -}; - -static struct regulator_consumer_supply ab8500_vamic2_consumers[] = { - /* AB8500 audio-codec Mic2 supply */ - REGULATOR_SUPPLY("vamic2", "ab8500-codec.0"), -}; - -static struct regulator_consumer_supply ab8500_vdmic_consumers[] = { - /* AB8500 audio-codec DMic supply */ - REGULATOR_SUPPLY("vdmic", "ab8500-codec.0"), -}; -static struct regulator_consumer_supply ab8500_vintcore_consumers[] = { - /* SoC core supply, no device */ - REGULATOR_SUPPLY("v-intcore", NULL), - /* USB Transceiver */ - REGULATOR_SUPPLY("vddulpivio18", "ab8500-usb.0"), - /* Handled by abx500 clk driver */ - REGULATOR_SUPPLY("v-intcore", "abx500-clk.0"), -}; - -static struct regulator_consumer_supply ab8500_vana_consumers[] = { - /* DB8500 DSI */ - REGULATOR_SUPPLY("vdddsi1v2", "mcde"), - REGULATOR_SUPPLY("vdddsi1v2", "b2r2_core"), - REGULATOR_SUPPLY("vdddsi1v2", "b2r2_1_core"), - REGULATOR_SUPPLY("vdddsi1v2", "dsilink.0"), - REGULATOR_SUPPLY("vdddsi1v2", "dsilink.1"), - REGULATOR_SUPPLY("vdddsi1v2", "dsilink.2"), - /* DB8500 CSI */ - REGULATOR_SUPPLY("vddcsi1v2", "mmio_camera"), -}; - -/* ab8500 regulator register initialization */ -static struct ab8500_regulator_reg_init ab8500_reg_init[] = { - /* - * VanaRequestCtrl = HP/LP depending on VxRequest - * VextSupply1RequestCtrl = HP/LP depending on VxRequest - */ - INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2, 0xf0, 0x00), - /* - * VextSupply2RequestCtrl = HP/LP depending on VxRequest - * VextSupply3RequestCtrl = HP/LP depending on VxRequest - * Vaux1RequestCtrl = HP/LP depending on VxRequest - * Vaux2RequestCtrl = HP/LP depending on VxRequest - */ - INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL3, 0xff, 0x00), - /* - * Vaux3RequestCtrl = HP/LP depending on VxRequest - * SwHPReq = Control through SWValid disabled - */ - INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4, 0x07, 0x00), - /* - * VanaSysClkReq1HPValid = disabled - * Vaux1SysClkReq1HPValid = disabled - * Vaux2SysClkReq1HPValid = disabled - * Vaux3SysClkReq1HPValid = disabled - */ - INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0xe8, 0x00), - /* - * VextSupply1SysClkReq1HPValid = disabled - * VextSupply2SysClkReq1HPValid = disabled - * VextSupply3SysClkReq1HPValid = SysClkReq1 controlled - */ - INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID2, 0x70, 0x40), - /* - * VanaHwHPReq1Valid = disabled - * Vaux1HwHPreq1Valid = disabled - * Vaux2HwHPReq1Valid = disabled - * Vaux3HwHPReqValid = disabled - */ - INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID1, 0xe8, 0x00), - /* - * VextSupply1HwHPReq1Valid = disabled - * VextSupply2HwHPReq1Valid = disabled - * VextSupply3HwHPReq1Valid = disabled - */ - INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID2, 0x07, 0x00), - /* - * VanaHwHPReq2Valid = disabled - * Vaux1HwHPReq2Valid = disabled - * Vaux2HwHPReq2Valid = disabled - * Vaux3HwHPReq2Valid = disabled - */ - INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID1, 0xe8, 0x00), - /* - * VextSupply1HwHPReq2Valid = disabled - * VextSupply2HwHPReq2Valid = disabled - * VextSupply3HwHPReq2Valid = HWReq2 controlled - */ - INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID2, 0x07, 0x04), - /* - * VanaSwHPReqValid = disabled - * Vaux1SwHPReqValid = disabled - */ - INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID1, 0xa0, 0x00), - /* - * Vaux2SwHPReqValid = disabled - * Vaux3SwHPReqValid = disabled - * VextSupply1SwHPReqValid = disabled - * VextSupply2SwHPReqValid = disabled - * VextSupply3SwHPReqValid = disabled - */ - INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID2, 0x1f, 0x00), - /* - * SysClkReq2Valid1 = SysClkReq2 controlled - * SysClkReq3Valid1 = disabled - * SysClkReq4Valid1 = SysClkReq4 controlled - * SysClkReq5Valid1 = disabled - * SysClkReq6Valid1 = SysClkReq6 controlled - * SysClkReq7Valid1 = disabled - * SysClkReq8Valid1 = disabled - */ - INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID1, 0xfe, 0x2a), - /* - * SysClkReq2Valid2 = disabled - * SysClkReq3Valid2 = disabled - * SysClkReq4Valid2 = disabled - * SysClkReq5Valid2 = disabled - * SysClkReq6Valid2 = SysClkReq6 controlled - * SysClkReq7Valid2 = disabled - * SysClkReq8Valid2 = disabled - */ - INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID2, 0xfe, 0x20), - /* - * VTVoutEna = disabled - * Vintcore12Ena = disabled - * Vintcore12Sel = 1.25 V - * Vintcore12LP = inactive (HP) - * VTVoutLP = inactive (HP) - */ - INIT_REGULATOR_REGISTER(AB8500_REGUMISC1, 0xfe, 0x10), - /* - * VaudioEna = disabled - * VdmicEna = disabled - * Vamic1Ena = disabled - * Vamic2Ena = disabled - */ - INIT_REGULATOR_REGISTER(AB8500_VAUDIOSUPPLY, 0x1e, 0x00), - /* - * Vamic1_dzout = high-Z when Vamic1 is disabled - * Vamic2_dzout = high-Z when Vamic2 is disabled - */ - INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC, 0x03, 0x00), - /* - * VPll = Hw controlled (NOTE! PRCMU bits) - * VanaRegu = force off - */ - INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU, 0x0f, 0x02), - /* - * VrefDDREna = disabled - * VrefDDRSleepMode = inactive (no pulldown) - */ - INIT_REGULATOR_REGISTER(AB8500_VREFDDR, 0x03, 0x00), - /* - * VextSupply1Regu = force LP - * VextSupply2Regu = force OFF - * VextSupply3Regu = force HP (-> STBB2=LP and TPS=LP) - * ExtSupply2Bypass = ExtSupply12LPn ball is 0 when Ena is 0 - * ExtSupply3Bypass = ExtSupply3LPn ball is 0 when Ena is 0 - */ - INIT_REGULATOR_REGISTER(AB8500_EXTSUPPLYREGU, 0xff, 0x13), - /* - * Vaux1Regu = force HP - * Vaux2Regu = force off - */ - INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU, 0x0f, 0x01), - /* - * Vaux3Regu = force off - */ - INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU, 0x03, 0x00), - /* - * Vaux1Sel = 2.8 V - */ - INIT_REGULATOR_REGISTER(AB8500_VAUX1SEL, 0x0f, 0x0C), - /* - * Vaux2Sel = 2.9 V - */ - INIT_REGULATOR_REGISTER(AB8500_VAUX2SEL, 0x0f, 0x0d), - /* - * Vaux3Sel = 2.91 V - */ - INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3SEL, 0x07, 0x07), - /* - * VextSupply12LP = disabled (no LP) - */ - INIT_REGULATOR_REGISTER(AB8500_REGUCTRL2SPARE, 0x01, 0x00), - /* - * Vaux1Disch = short discharge time - * Vaux2Disch = short discharge time - * Vaux3Disch = short discharge time - * Vintcore12Disch = short discharge time - * VTVoutDisch = short discharge time - * VaudioDisch = short discharge time - */ - INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH, 0xfc, 0x00), - /* - * VanaDisch = short discharge time - * VdmicPullDownEna = pulldown disabled when Vdmic is disabled - * VdmicDisch = short discharge time - */ - INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH2, 0x16, 0x00), +/* AB8500 external regulators */ +enum ab8500_ext_regulator_id { + AB8500_EXT_SUPPLY1, + AB8500_EXT_SUPPLY2, + AB8500_EXT_SUPPLY3, + AB8500_NUM_EXT_REGULATORS, }; -/* AB8500 regulators */ -static struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { - /* supplies to the display/camera */ - [AB8500_LDO_AUX1] = { - .supply_regulator = "ab8500-ext-supply3", - .constraints = { - .name = "V-DISPLAY", - .min_uV = 2800000, - .max_uV = 3300000, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | - REGULATOR_CHANGE_STATUS, - .boot_on = 1, /* display is on at boot */ - }, - .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers), - .consumer_supplies = ab8500_vaux1_consumers, - }, - /* supplies to the on-board eMMC */ - [AB8500_LDO_AUX2] = { - .supply_regulator = "ab8500-ext-supply3", - .constraints = { - .name = "V-eMMC1", - .min_uV = 1100000, - .max_uV = 3300000, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | - REGULATOR_CHANGE_STATUS | - REGULATOR_CHANGE_MODE, - .valid_modes_mask = REGULATOR_MODE_NORMAL | - REGULATOR_MODE_IDLE, - }, - .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers), - .consumer_supplies = ab8500_vaux2_consumers, - }, - /* supply for VAUX3, supplies to SDcard slots */ - [AB8500_LDO_AUX3] = { - .supply_regulator = "ab8500-ext-supply3", - .constraints = { - .name = "V-MMC-SD", - .min_uV = 1100000, - .max_uV = 3300000, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | - REGULATOR_CHANGE_STATUS | - REGULATOR_CHANGE_MODE, - .valid_modes_mask = REGULATOR_MODE_NORMAL | - REGULATOR_MODE_IDLE, - }, - .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers), - .consumer_supplies = ab8500_vaux3_consumers, - }, - /* supply for tvout, gpadc, TVOUT LDO */ - [AB8500_LDO_TVOUT] = { - .constraints = { - .name = "V-TVOUT", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(ab8500_vtvout_consumers), - .consumer_supplies = ab8500_vtvout_consumers, - }, - /* supply for ab8500-vaudio, VAUDIO LDO */ - [AB8500_LDO_AUDIO] = { - .constraints = { - .name = "V-AUD", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(ab8500_vaud_consumers), - .consumer_supplies = ab8500_vaud_consumers, - }, - /* supply for v-anamic1 VAMic1-LDO */ - [AB8500_LDO_ANAMIC1] = { - .constraints = { - .name = "V-AMIC1", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(ab8500_vamic1_consumers), - .consumer_supplies = ab8500_vamic1_consumers, - }, - /* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */ - [AB8500_LDO_ANAMIC2] = { - .constraints = { - .name = "V-AMIC2", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(ab8500_vamic2_consumers), - .consumer_supplies = ab8500_vamic2_consumers, - }, - /* supply for v-dmic, VDMIC LDO */ - [AB8500_LDO_DMIC] = { - .constraints = { - .name = "V-DMIC", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(ab8500_vdmic_consumers), - .consumer_supplies = ab8500_vdmic_consumers, - }, - /* supply for v-intcore12, VINTCORE12 LDO */ - [AB8500_LDO_INTCORE] = { - .constraints = { - .name = "V-INTCORE", - .min_uV = 1250000, - .max_uV = 1350000, - .input_uV = 1800000, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | - REGULATOR_CHANGE_STATUS | - REGULATOR_CHANGE_MODE | - REGULATOR_CHANGE_DRMS, - .valid_modes_mask = REGULATOR_MODE_NORMAL | - REGULATOR_MODE_IDLE, - }, - .num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers), - .consumer_supplies = ab8500_vintcore_consumers, - }, - /* supply for U8500 CSI-DSI, VANA LDO */ - [AB8500_LDO_ANA] = { - .constraints = { - .name = "V-CSI-DSI", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers), - .consumer_supplies = ab8500_vana_consumers, - }, +struct ab8500_ext_regulator_cfg { + bool hwreq; /* requires hw mode or high power mode */ }; /* supply for VextSupply3 */ @@ -465,15 +79,6 @@ static struct regulator_init_data ab8500_ext_regulators[] = { }, }; -static struct ab8500_regulator_platform_data ab8500_regulator_plat_data = { - .reg_init = ab8500_reg_init, - .num_reg_init = ARRAY_SIZE(ab8500_reg_init), - .regulator = ab8500_regulators, - .num_regulator = ARRAY_SIZE(ab8500_regulators), - .ext_regulator = ab8500_ext_regulators, - .num_ext_regulator = ARRAY_SIZE(ab8500_ext_regulators), -}; - /** * struct ab8500_ext_regulator_info - ab8500 regulator information * @dev: device pointer @@ -788,7 +393,6 @@ static struct ab8500_ext_regulator_info static int ab8500_ext_regulator_probe(struct platform_device *pdev) { struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); - struct ab8500_regulator_platform_data *pdata = &ab8500_regulator_plat_data; struct regulator_config config = { }; struct regulator_dev *rdev; int i; @@ -798,12 +402,6 @@ static int ab8500_ext_regulator_probe(struct platform_device *pdev) return -EINVAL; } - /* make sure the platform data has the correct size */ - if (pdata->num_ext_regulator != ARRAY_SIZE(ab8500_ext_regulator_info)) { - dev_err(&pdev->dev, "Configuration error: size mismatch.\n"); - return -EINVAL; - } - /* check for AB8500 2.x */ if (is_ab8500_2p0_or_earlier(ab8500)) { struct ab8500_ext_regulator_info *info; @@ -823,11 +421,11 @@ static int ab8500_ext_regulator_probe(struct platform_device *pdev) info = &ab8500_ext_regulator_info[i]; info->dev = &pdev->dev; info->cfg = (struct ab8500_ext_regulator_cfg *) - pdata->ext_regulator[i].driver_data; + ab8500_ext_regulators[i].driver_data; config.dev = &pdev->dev; config.driver_data = info; - config.init_data = &pdata->ext_regulator[i]; + config.init_data = &ab8500_ext_regulators[i]; /* register regulator with framework */ rdev = devm_regulator_register(&pdev->dev, &info->desc, diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 47b8b6f7b571..23a401734a98 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -25,9 +25,123 @@ #include <linux/regulator/of_regulator.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> -#include <linux/regulator/ab8500.h> #include <linux/slab.h> +/* AB8500 regulators */ +enum ab8500_regulator_id { + AB8500_LDO_AUX1, + AB8500_LDO_AUX2, + AB8500_LDO_AUX3, + AB8500_LDO_INTCORE, + AB8500_LDO_TVOUT, + AB8500_LDO_AUDIO, + AB8500_LDO_ANAMIC1, + AB8500_LDO_ANAMIC2, + AB8500_LDO_DMIC, + AB8500_LDO_ANA, + AB8500_NUM_REGULATORS, +}; + +/* AB8505 regulators */ +enum ab8505_regulator_id { + AB8505_LDO_AUX1, + AB8505_LDO_AUX2, + AB8505_LDO_AUX3, + AB8505_LDO_AUX4, + AB8505_LDO_AUX5, + AB8505_LDO_AUX6, + AB8505_LDO_INTCORE, + AB8505_LDO_ADC, + AB8505_LDO_AUDIO, + AB8505_LDO_ANAMIC1, + AB8505_LDO_ANAMIC2, + AB8505_LDO_AUX8, + AB8505_LDO_ANA, + AB8505_NUM_REGULATORS, +}; + +/* AB8500 registers */ +enum ab8500_regulator_reg { + AB8500_REGUREQUESTCTRL2, + AB8500_REGUREQUESTCTRL3, + AB8500_REGUREQUESTCTRL4, + AB8500_REGUSYSCLKREQ1HPVALID1, + AB8500_REGUSYSCLKREQ1HPVALID2, + AB8500_REGUHWHPREQ1VALID1, + AB8500_REGUHWHPREQ1VALID2, + AB8500_REGUHWHPREQ2VALID1, + AB8500_REGUHWHPREQ2VALID2, + AB8500_REGUSWHPREQVALID1, + AB8500_REGUSWHPREQVALID2, + AB8500_REGUSYSCLKREQVALID1, + AB8500_REGUSYSCLKREQVALID2, + AB8500_REGUMISC1, + AB8500_VAUDIOSUPPLY, + AB8500_REGUCTRL1VAMIC, + AB8500_VPLLVANAREGU, + AB8500_VREFDDR, + AB8500_EXTSUPPLYREGU, + AB8500_VAUX12REGU, + AB8500_VRF1VAUX3REGU, + AB8500_VAUX1SEL, + AB8500_VAUX2SEL, + AB8500_VRF1VAUX3SEL, + AB8500_REGUCTRL2SPARE, + AB8500_REGUCTRLDISCH, + AB8500_REGUCTRLDISCH2, + AB8500_NUM_REGULATOR_REGISTERS, +}; + +/* AB8505 registers */ +enum ab8505_regulator_reg { + AB8505_REGUREQUESTCTRL1, + AB8505_REGUREQUESTCTRL2, + AB8505_REGUREQUESTCTRL3, + AB8505_REGUREQUESTCTRL4, + AB8505_REGUSYSCLKREQ1HPVALID1, + AB8505_REGUSYSCLKREQ1HPVALID2, + AB8505_REGUHWHPREQ1VALID1, + AB8505_REGUHWHPREQ1VALID2, + AB8505_REGUHWHPREQ2VALID1, + AB8505_REGUHWHPREQ2VALID2, + AB8505_REGUSWHPREQVALID1, + AB8505_REGUSWHPREQVALID2, + AB8505_REGUSYSCLKREQVALID1, + AB8505_REGUSYSCLKREQVALID2, + AB8505_REGUVAUX4REQVALID, + AB8505_REGUMISC1, + AB8505_VAUDIOSUPPLY, + AB8505_REGUCTRL1VAMIC, + AB8505_VSMPSAREGU, + AB8505_VSMPSBREGU, + AB8505_VSAFEREGU, /* NOTE! PRCMU register */ + AB8505_VPLLVANAREGU, + AB8505_EXTSUPPLYREGU, + AB8505_VAUX12REGU, + AB8505_VRF1VAUX3REGU, + AB8505_VSMPSASEL1, + AB8505_VSMPSASEL2, + AB8505_VSMPSASEL3, + AB8505_VSMPSBSEL1, + AB8505_VSMPSBSEL2, + AB8505_VSMPSBSEL3, + AB8505_VSAFESEL1, /* NOTE! PRCMU register */ + AB8505_VSAFESEL2, /* NOTE! PRCMU register */ + AB8505_VSAFESEL3, /* NOTE! PRCMU register */ + AB8505_VAUX1SEL, + AB8505_VAUX2SEL, + AB8505_VRF1VAUX3SEL, + AB8505_VAUX4REQCTRL, + AB8505_VAUX4REGU, + AB8505_VAUX4SEL, + AB8505_REGUCTRLDISCH, + AB8505_REGUCTRLDISCH2, + AB8505_REGUCTRLDISCH3, + AB8505_CTRLVAUX5, + AB8505_CTRLVAUX6, + AB8505_NUM_REGULATOR_REGISTERS, +}; + /** * struct ab8500_shared_mode - is used when mode is shared between * two regulators. diff --git a/drivers/regulator/atc260x-regulator.c b/drivers/regulator/atc260x-regulator.c new file mode 100644 index 000000000000..d8b429955d33 --- /dev/null +++ b/drivers/regulator/atc260x-regulator.c @@ -0,0 +1,539 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Regulator driver for ATC260x PMICs +// +// Copyright (C) 2019 Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> +// Copyright (C) 2020 Cristian Ciocaltea <cristian.ciocaltea@gmail.com> + +#include <linux/mfd/atc260x/core.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> + +struct atc260x_regulator_data { + int voltage_time_dcdc; + int voltage_time_ldo; +}; + +static const struct linear_range atc2603c_dcdc_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(1300000, 0, 13, 50000), + REGULATOR_LINEAR_RANGE(1950000, 14, 15, 100000), +}; + +static const struct linear_range atc2609a_dcdc_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 127, 6250), + REGULATOR_LINEAR_RANGE(1400000, 128, 232, 25000), +}; + +static const struct linear_range atc2609a_ldo_voltage_ranges0[] = { + REGULATOR_LINEAR_RANGE(700000, 0, 15, 100000), + REGULATOR_LINEAR_RANGE(2100000, 16, 28, 100000), +}; + +static const struct linear_range atc2609a_ldo_voltage_ranges1[] = { + REGULATOR_LINEAR_RANGE(850000, 0, 15, 100000), + REGULATOR_LINEAR_RANGE(2100000, 16, 27, 100000), +}; + +static const unsigned int atc260x_ldo_voltage_range_sel[] = { + 0x0, 0x1, +}; + +static int atc260x_dcdc_set_voltage_time_sel(struct regulator_dev *rdev, + unsigned int old_selector, + unsigned int new_selector) +{ + struct atc260x_regulator_data *data = rdev_get_drvdata(rdev); + + if (new_selector > old_selector) + return data->voltage_time_dcdc; + + return 0; +} + +static int atc260x_ldo_set_voltage_time_sel(struct regulator_dev *rdev, + unsigned int old_selector, + unsigned int new_selector) +{ + struct atc260x_regulator_data *data = rdev_get_drvdata(rdev); + + if (new_selector > old_selector) + return data->voltage_time_ldo; + + return 0; +} + +static const struct regulator_ops atc260x_dcdc_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, + .set_voltage_time_sel = atc260x_dcdc_set_voltage_time_sel, +}; + +static const struct regulator_ops atc260x_ldo_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, + .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel, +}; + +static const struct regulator_ops atc260x_ldo_bypass_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, + .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel, + .set_bypass = regulator_set_bypass_regmap, + .get_bypass = regulator_get_bypass_regmap, +}; + +static const struct regulator_ops atc260x_ldo_bypass_discharge_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, + .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel, + .set_bypass = regulator_set_bypass_regmap, + .get_bypass = regulator_get_bypass_regmap, + .set_active_discharge = regulator_set_active_discharge_regmap, +}; + +static const struct regulator_ops atc260x_dcdc_range_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 = atc260x_dcdc_set_voltage_time_sel, +}; + +static const struct regulator_ops atc260x_ldo_range_pick_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_pickable_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, + .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel, +}; + +static const struct regulator_ops atc260x_dcdc_fixed_ops = { + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = atc260x_dcdc_set_voltage_time_sel, +}; + +static const struct regulator_ops atc260x_ldo_fixed_ops = { + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel, +}; + +static const struct regulator_ops atc260x_no_ops = { +}; + +/* + * Note LDO8 is not documented in datasheet (v2.4), but supported + * in the vendor's driver implementation (xapp-le-kernel). + */ +enum atc2603c_reg_ids { + ATC2603C_ID_DCDC1, + ATC2603C_ID_DCDC2, + ATC2603C_ID_DCDC3, + ATC2603C_ID_LDO1, + ATC2603C_ID_LDO2, + ATC2603C_ID_LDO3, + ATC2603C_ID_LDO5, + ATC2603C_ID_LDO6, + ATC2603C_ID_LDO7, + ATC2603C_ID_LDO8, + ATC2603C_ID_LDO11, + ATC2603C_ID_LDO12, + ATC2603C_ID_SWITCHLDO1, + ATC2603C_ID_MAX, +}; + +#define atc2603c_reg_desc_dcdc(num, min, step, n_volt, vsel_h, vsel_l) { \ + .name = "DCDC"#num, \ + .supply_name = "dcdc"#num, \ + .of_match = of_match_ptr("dcdc"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = ATC2603C_ID_DCDC##num, \ + .ops = &atc260x_dcdc_ops, \ + .type = REGULATOR_VOLTAGE, \ + .min_uV = min, \ + .uV_step = step, \ + .n_voltages = n_volt, \ + .vsel_reg = ATC2603C_PMU_DC##num##_CTL0, \ + .vsel_mask = GENMASK(vsel_h, vsel_l), \ + .enable_reg = ATC2603C_PMU_DC##num##_CTL0, \ + .enable_mask = BIT(15), \ + .enable_time = 800, \ + .owner = THIS_MODULE, \ +} + +#define atc2603c_reg_desc_dcdc_range(num, vsel_h, vsel_l) { \ + .name = "DCDC"#num, \ + .supply_name = "dcdc"#num, \ + .of_match = of_match_ptr("dcdc"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = ATC2603C_ID_DCDC##num, \ + .ops = &atc260x_dcdc_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .n_voltages = 16, \ + .linear_ranges = atc2603c_dcdc_voltage_ranges, \ + .n_linear_ranges = ARRAY_SIZE(atc2603c_dcdc_voltage_ranges), \ + .vsel_reg = ATC2603C_PMU_DC##num##_CTL0, \ + .vsel_mask = GENMASK(vsel_h, vsel_l), \ + .enable_reg = ATC2603C_PMU_DC##num##_CTL0, \ + .enable_mask = BIT(15), \ + .enable_time = 800, \ + .owner = THIS_MODULE, \ +} + +#define atc2603c_reg_desc_dcdc_fixed(num, min, step, n_volt, vsel_h, vsel_l) { \ + .name = "DCDC"#num, \ + .supply_name = "dcdc"#num, \ + .of_match = of_match_ptr("dcdc"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = ATC2603C_ID_DCDC##num, \ + .ops = &atc260x_dcdc_fixed_ops, \ + .type = REGULATOR_VOLTAGE, \ + .min_uV = min, \ + .uV_step = step, \ + .n_voltages = n_volt, \ + .vsel_reg = ATC2603C_PMU_DC##num##_CTL0, \ + .vsel_mask = GENMASK(vsel_h, vsel_l), \ + .enable_time = 800, \ + .owner = THIS_MODULE, \ +} + +#define atc2603c_reg_desc_ldo(num, min, step, n_volt, vsel_h, vsel_l) { \ + .name = "LDO"#num, \ + .supply_name = "ldo"#num, \ + .of_match = of_match_ptr("ldo"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = ATC2603C_ID_LDO##num, \ + .ops = &atc260x_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .min_uV = min, \ + .uV_step = step, \ + .n_voltages = n_volt, \ + .vsel_reg = ATC2603C_PMU_LDO##num##_CTL, \ + .vsel_mask = GENMASK(vsel_h, vsel_l), \ + .enable_reg = ATC2603C_PMU_LDO##num##_CTL, \ + .enable_mask = BIT(0), \ + .enable_time = 2000, \ + .owner = THIS_MODULE, \ +} + +#define atc2603c_reg_desc_ldo_fixed(num, min, step, n_volt, vsel_h, vsel_l) { \ + .name = "LDO"#num, \ + .supply_name = "ldo"#num, \ + .of_match = of_match_ptr("ldo"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = ATC2603C_ID_LDO##num, \ + .ops = &atc260x_ldo_fixed_ops, \ + .type = REGULATOR_VOLTAGE, \ + .min_uV = min, \ + .uV_step = step, \ + .n_voltages = n_volt, \ + .vsel_reg = ATC2603C_PMU_LDO##num##_CTL, \ + .vsel_mask = GENMASK(vsel_h, vsel_l), \ + .enable_time = 2000, \ + .owner = THIS_MODULE, \ +} + +#define atc2603c_reg_desc_ldo_noops(num, vfixed) { \ + .name = "LDO"#num, \ + .supply_name = "ldo"#num, \ + .of_match = of_match_ptr("ldo"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = ATC2603C_ID_LDO##num, \ + .ops = &atc260x_no_ops, \ + .type = REGULATOR_VOLTAGE, \ + .fixed_uV = vfixed, \ + .n_voltages = 1, \ + .owner = THIS_MODULE, \ +} + +#define atc2603c_reg_desc_ldo_switch(num, min, step, n_volt, vsel_h, vsel_l) { \ + .name = "SWITCHLDO"#num, \ + .supply_name = "switchldo"#num, \ + .of_match = of_match_ptr("switchldo"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = ATC2603C_ID_SWITCHLDO##num, \ + .ops = &atc260x_ldo_bypass_discharge_ops, \ + .type = REGULATOR_VOLTAGE, \ + .min_uV = min, \ + .uV_step = step, \ + .n_voltages = n_volt, \ + .vsel_reg = ATC2603C_PMU_SWITCH_CTL, \ + .vsel_mask = GENMASK(vsel_h, vsel_l), \ + .enable_reg = ATC2603C_PMU_SWITCH_CTL, \ + .enable_mask = BIT(15), \ + .enable_is_inverted = true, \ + .enable_time = 2000, \ + .bypass_reg = ATC2603C_PMU_SWITCH_CTL, \ + .bypass_mask = BIT(5), \ + .active_discharge_reg = ATC2603C_PMU_SWITCH_CTL, \ + .active_discharge_mask = BIT(1), \ + .owner = THIS_MODULE, \ +} + +static const struct regulator_desc atc2603c_reg[] = { + atc2603c_reg_desc_dcdc_fixed(1, 700000, 25000, 29, 11, 7), + atc2603c_reg_desc_dcdc_range(2, 12, 8), + atc2603c_reg_desc_dcdc_fixed(3, 2600000, 100000, 8, 11, 9), + atc2603c_reg_desc_ldo_fixed(1, 2600000, 100000, 8, 15, 13), + atc2603c_reg_desc_ldo_fixed(2, 2600000, 100000, 8, 15, 13), + atc2603c_reg_desc_ldo_fixed(3, 1500000, 100000, 6, 15, 13), + atc2603c_reg_desc_ldo(5, 2600000, 100000, 8, 15, 13), + atc2603c_reg_desc_ldo_fixed(6, 700000, 25000, 29, 15, 11), + atc2603c_reg_desc_ldo(7, 1500000, 100000, 6, 15, 13), + atc2603c_reg_desc_ldo(8, 2300000, 100000, 11, 15, 12), + atc2603c_reg_desc_ldo_fixed(11, 2600000, 100000, 8, 15, 13), + atc2603c_reg_desc_ldo_noops(12, 1800000), + atc2603c_reg_desc_ldo_switch(1, 3000000, 100000, 4, 4, 3), +}; + +static const struct regulator_desc atc2603c_reg_dcdc2_ver_b = + atc2603c_reg_desc_dcdc(2, 1000000, 50000, 18, 12, 8); + +enum atc2609a_reg_ids { + ATC2609A_ID_DCDC0, + ATC2609A_ID_DCDC1, + ATC2609A_ID_DCDC2, + ATC2609A_ID_DCDC3, + ATC2609A_ID_DCDC4, + ATC2609A_ID_LDO0, + ATC2609A_ID_LDO1, + ATC2609A_ID_LDO2, + ATC2609A_ID_LDO3, + ATC2609A_ID_LDO4, + ATC2609A_ID_LDO5, + ATC2609A_ID_LDO6, + ATC2609A_ID_LDO7, + ATC2609A_ID_LDO8, + ATC2609A_ID_LDO9, + ATC2609A_ID_MAX, +}; + +#define atc2609a_reg_desc_dcdc(num, en_bit) { \ + .name = "DCDC"#num, \ + .supply_name = "dcdc"#num, \ + .of_match = of_match_ptr("dcdc"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = ATC2609A_ID_DCDC##num, \ + .ops = &atc260x_dcdc_ops, \ + .type = REGULATOR_VOLTAGE, \ + .min_uV = 600000, \ + .uV_step = 6250, \ + .n_voltages = 256, \ + .vsel_reg = ATC2609A_PMU_DC##num##_CTL0, \ + .vsel_mask = GENMASK(15, 8), \ + .enable_reg = ATC2609A_PMU_DC_OSC, \ + .enable_mask = BIT(en_bit), \ + .enable_time = 800, \ + .owner = THIS_MODULE, \ +} + +#define atc2609a_reg_desc_dcdc_range(num, en_bit) { \ + .name = "DCDC"#num, \ + .supply_name = "dcdc"#num, \ + .of_match = of_match_ptr("dcdc"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = ATC2609A_ID_DCDC##num, \ + .ops = &atc260x_dcdc_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .n_voltages = 233, \ + .linear_ranges = atc2609a_dcdc_voltage_ranges, \ + .n_linear_ranges = ARRAY_SIZE(atc2609a_dcdc_voltage_ranges), \ + .vsel_reg = ATC2609A_PMU_DC##num##_CTL0, \ + .vsel_mask = GENMASK(15, 8), \ + .enable_reg = ATC2609A_PMU_DC_OSC, \ + .enable_mask = BIT(en_bit), \ + .enable_time = 800, \ + .owner = THIS_MODULE, \ +} + +#define atc2609a_reg_desc_ldo(num) { \ + .name = "LDO"#num, \ + .supply_name = "ldo"#num, \ + .of_match = of_match_ptr("ldo"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = ATC2609A_ID_LDO##num, \ + .ops = &atc260x_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .min_uV = 700000, \ + .uV_step = 100000, \ + .n_voltages = 16, \ + .vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \ + .vsel_mask = GENMASK(4, 1), \ + .enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \ + .enable_mask = BIT(0), \ + .enable_time = 2000, \ + .owner = THIS_MODULE, \ +} + +#define atc2609a_reg_desc_ldo_bypass(num) { \ + .name = "LDO"#num, \ + .supply_name = "ldo"#num, \ + .of_match = of_match_ptr("ldo"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = ATC2609A_ID_LDO##num, \ + .ops = &atc260x_ldo_bypass_ops, \ + .type = REGULATOR_VOLTAGE, \ + .min_uV = 2300000, \ + .uV_step = 100000, \ + .n_voltages = 12, \ + .vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \ + .vsel_mask = GENMASK(5, 2), \ + .enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \ + .enable_mask = BIT(0), \ + .enable_time = 2000, \ + .bypass_reg = ATC2609A_PMU_LDO##num##_CTL0, \ + .bypass_mask = BIT(1), \ + .owner = THIS_MODULE, \ +} + +#define atc2609a_reg_desc_ldo_range_pick(num, n_range) { \ + .name = "LDO"#num, \ + .supply_name = "ldo"#num, \ + .of_match = of_match_ptr("ldo"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = ATC2609A_ID_LDO##num, \ + .ops = &atc260x_ldo_range_pick_ops, \ + .type = REGULATOR_VOLTAGE, \ + .linear_ranges = atc2609a_ldo_voltage_ranges##n_range, \ + .n_linear_ranges = ARRAY_SIZE(atc2609a_ldo_voltage_ranges##n_range), \ + .vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \ + .vsel_mask = GENMASK(4, 1), \ + .vsel_range_reg = ATC2609A_PMU_LDO##num##_CTL0, \ + .vsel_range_mask = BIT(5), \ + .linear_range_selectors = atc260x_ldo_voltage_range_sel, \ + .enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \ + .enable_mask = BIT(0), \ + .enable_time = 2000, \ + .owner = THIS_MODULE, \ +} + +#define atc2609a_reg_desc_ldo_fixed(num) { \ + .name = "LDO"#num, \ + .supply_name = "ldo"#num, \ + .of_match = of_match_ptr("ldo"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = ATC2609A_ID_LDO##num, \ + .ops = &atc260x_ldo_fixed_ops, \ + .type = REGULATOR_VOLTAGE, \ + .min_uV = 2600000, \ + .uV_step = 100000, \ + .n_voltages = 8, \ + .vsel_reg = ATC2609A_PMU_LDO##num##_CTL, \ + .vsel_mask = GENMASK(15, 13), \ + .enable_time = 2000, \ + .owner = THIS_MODULE, \ +} + +static const struct regulator_desc atc2609a_reg[] = { + atc2609a_reg_desc_dcdc(0, 4), + atc2609a_reg_desc_dcdc(1, 5), + atc2609a_reg_desc_dcdc(2, 6), + atc2609a_reg_desc_dcdc_range(3, 7), + atc2609a_reg_desc_dcdc(4, 8), + atc2609a_reg_desc_ldo_bypass(0), + atc2609a_reg_desc_ldo_bypass(1), + atc2609a_reg_desc_ldo_bypass(2), + atc2609a_reg_desc_ldo_range_pick(3, 0), + atc2609a_reg_desc_ldo_range_pick(4, 0), + atc2609a_reg_desc_ldo(5), + atc2609a_reg_desc_ldo_range_pick(6, 1), + atc2609a_reg_desc_ldo_range_pick(7, 0), + atc2609a_reg_desc_ldo_range_pick(8, 0), + atc2609a_reg_desc_ldo_fixed(9), +}; + +static int atc260x_regulator_probe(struct platform_device *pdev) +{ + struct atc260x *atc260x = dev_get_drvdata(pdev->dev.parent); + struct device *dev = atc260x->dev; + struct atc260x_regulator_data *atc260x_data; + struct regulator_config config = {}; + struct regulator_dev *atc260x_rdev; + const struct regulator_desc *regulators; + bool atc2603c_ver_b = false; + int i, nregulators; + + atc260x_data = devm_kzalloc(&pdev->dev, sizeof(*atc260x_data), GFP_KERNEL); + if (!atc260x_data) + return -ENOMEM; + + atc260x_data->voltage_time_dcdc = 350; + atc260x_data->voltage_time_ldo = 800; + + switch (atc260x->ic_type) { + case ATC2603C: + regulators = atc2603c_reg; + nregulators = ATC2603C_ID_MAX; + atc2603c_ver_b = atc260x->ic_ver == ATC260X_B; + break; + case ATC2609A: + atc260x_data->voltage_time_dcdc = 250; + regulators = atc2609a_reg; + nregulators = ATC2609A_ID_MAX; + break; + default: + dev_err(dev, "unsupported ATC260X ID %d\n", atc260x->ic_type); + return -EINVAL; + } + + config.dev = dev; + config.regmap = atc260x->regmap; + config.driver_data = atc260x_data; + + /* Instantiate the regulators */ + for (i = 0; i < nregulators; i++) { + if (atc2603c_ver_b && regulators[i].id == ATC2603C_ID_DCDC2) + atc260x_rdev = devm_regulator_register(&pdev->dev, + &atc2603c_reg_dcdc2_ver_b, + &config); + else + atc260x_rdev = devm_regulator_register(&pdev->dev, + ®ulators[i], + &config); + if (IS_ERR(atc260x_rdev)) { + dev_err(dev, "failed to register regulator: %d\n", i); + return PTR_ERR(atc260x_rdev); + } + } + + return 0; +} + +static struct platform_driver atc260x_regulator_driver = { + .probe = atc260x_regulator_probe, + .driver = { + .name = "atc260x-regulator", + }, +}; + +module_platform_driver(atc260x_regulator_driver); + +MODULE_DESCRIPTION("Regulator driver for ATC260x PMICs"); +MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>"); +MODULE_AUTHOR("Cristian Ciocaltea <cristian.ciocaltea@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/bd70528-regulator.c b/drivers/regulator/bd70528-regulator.c index d44adf7e875a..1f5f9482b209 100644 --- a/drivers/regulator/bd70528-regulator.c +++ b/drivers/regulator/bd70528-regulator.c @@ -244,19 +244,14 @@ static const struct regulator_desc bd70528_desc[] = { static int bd70528_probe(struct platform_device *pdev) { - struct rohm_regmap_dev *bd70528; int i; struct regulator_config config = { .dev = pdev->dev.parent, }; - bd70528 = dev_get_drvdata(pdev->dev.parent); - if (!bd70528) { - dev_err(&pdev->dev, "No MFD driver data\n"); - return -EINVAL; - } - - config.regmap = bd70528->regmap; + config.regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!config.regmap) + return -ENODEV; for (i = 0; i < ARRAY_SIZE(bd70528_desc); i++) { struct regulator_dev *rdev; diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c index 85c0b9000963..6b12e963ed8f 100644 --- a/drivers/regulator/bd71828-regulator.c +++ b/drivers/regulator/bd71828-regulator.c @@ -749,19 +749,14 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { static int bd71828_probe(struct platform_device *pdev) { - struct rohm_regmap_dev *bd71828; int i, j, ret; struct regulator_config config = { .dev = pdev->dev.parent, }; - bd71828 = dev_get_drvdata(pdev->dev.parent); - if (!bd71828) { - dev_err(&pdev->dev, "No MFD driver data\n"); - return -EINVAL; - } - - config.regmap = bd71828->regmap; + config.regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!config.regmap) + return -ENODEV; for (i = 0; i < ARRAY_SIZE(bd71828_rdata); i++) { struct regulator_dev *rdev; @@ -777,7 +772,7 @@ static int bd71828_probe(struct platform_device *pdev) return PTR_ERR(rdev); } for (j = 0; j < rd->reg_init_amnt; j++) { - ret = regmap_update_bits(bd71828->regmap, + ret = regmap_update_bits(config.regmap, rd->reg_inits[j].reg, rd->reg_inits[j].mask, rd->reg_inits[j].val); diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c index 9309765d0450..8ff47ea522d6 100644 --- a/drivers/regulator/bd718x7-regulator.c +++ b/drivers/regulator/bd718x7-regulator.c @@ -1554,7 +1554,7 @@ err_out: static int bd718xx_probe(struct platform_device *pdev) { - struct bd718xx *mfd; + struct regmap *regmap; struct regulator_config config = { 0 }; int i, j, err, omit_enable; bool use_snvs; @@ -1563,11 +1563,10 @@ static int bd718xx_probe(struct platform_device *pdev) enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data; const struct regulator_ops **swops, **hwops; - mfd = dev_get_drvdata(pdev->dev.parent); - if (!mfd) { + regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!regmap) { dev_err(&pdev->dev, "No MFD driver data\n"); - err = -EINVAL; - goto err; + return -EINVAL; } switch (chip) { @@ -1590,7 +1589,7 @@ static int bd718xx_probe(struct platform_device *pdev) } /* Register LOCK release */ - err = regmap_update_bits(mfd->chip.regmap, BD718XX_REG_REGLOCK, + err = regmap_update_bits(regmap, BD718XX_REG_REGLOCK, (REGLOCK_PWRSEQ | REGLOCK_VREG), 0); if (err) { dev_err(&pdev->dev, "Failed to unlock PMIC (%d)\n", err); @@ -1609,8 +1608,7 @@ static int bd718xx_probe(struct platform_device *pdev) * bit allowing HW defaults for power rails to be used */ if (!use_snvs) { - err = regmap_update_bits(mfd->chip.regmap, - BD718XX_REG_TRANS_COND1, + err = regmap_update_bits(regmap, BD718XX_REG_TRANS_COND1, BD718XX_ON_REQ_POWEROFF_MASK | BD718XX_SWRESET_POWEROFF_MASK | BD718XX_WDOG_POWEROFF_MASK | @@ -1626,7 +1624,7 @@ static int bd718xx_probe(struct platform_device *pdev) } config.dev = pdev->dev.parent; - config.regmap = mfd->chip.regmap; + config.regmap = regmap; /* * There are cases when we want to leave the enable-control for * the HW state machine and use this driver only for voltage control. @@ -1685,7 +1683,7 @@ static int bd718xx_probe(struct platform_device *pdev) if (!no_enable_control && (!use_snvs || !rdev->constraints->always_on || !rdev->constraints->boot_on)) { - err = regmap_update_bits(mfd->chip.regmap, r->init.reg, + err = regmap_update_bits(regmap, r->init.reg, r->init.mask, r->init.val); if (err) { dev_err(&pdev->dev, @@ -1695,7 +1693,7 @@ static int bd718xx_probe(struct platform_device *pdev) } } for (j = 0; j < r->additional_init_amnt; j++) { - err = regmap_update_bits(mfd->chip.regmap, + err = regmap_update_bits(regmap, r->additional_inits[j].reg, r->additional_inits[j].mask, r->additional_inits[j].val); diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index ca03d8e70bd1..fee924158091 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2020,7 +2020,7 @@ struct regulator *_regulator_get(struct device *dev, const char *id, * Returns a struct regulator corresponding to the regulator producer, * or IS_ERR() condition containing errno. * - * Use of supply names configured via regulator_set_device_supply() is + * Use of supply names configured via set_consumer_device_supply() is * strongly encouraged. It is recommended that the supply name used * should match the name used for the supply and/or the relevant * device pins in the datasheet. @@ -2047,7 +2047,7 @@ EXPORT_SYMBOL_GPL(regulator_get); * regulator off for correct operation of the hardware they are * controlling. * - * Use of supply names configured via regulator_set_device_supply() is + * Use of supply names configured via set_consumer_device_supply() is * strongly encouraged. It is recommended that the supply name used * should match the name used for the supply and/or the relevant * device pins in the datasheet. @@ -2073,7 +2073,7 @@ EXPORT_SYMBOL_GPL(regulator_get_exclusive); * disrupting the operation of drivers that can handle absent * supplies. * - * Use of supply names configured via regulator_set_device_supply() is + * Use of supply names configured via set_consumer_device_supply() is * strongly encouraged. It is recommended that the supply name used * should match the name used for the supply and/or the relevant * device pins in the datasheet. diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c index 74ad92dc664a..88c6bd5b6c78 100644 --- a/drivers/regulator/mcp16502.c +++ b/drivers/regulator/mcp16502.c @@ -550,7 +550,7 @@ static int mcp16502_probe(struct i2c_client *client, config.regmap = rmap; config.driver_data = mcp; - mcp->lpm = devm_gpiod_get(dev, "lpm", GPIOD_OUT_LOW); + mcp->lpm = devm_gpiod_get_optional(dev, "lpm", GPIOD_OUT_LOW); if (IS_ERR(mcp->lpm)) { dev_err(dev, "failed to get lpm pin: %ld\n", PTR_ERR(mcp->lpm)); return PTR_ERR(mcp->lpm); diff --git a/drivers/regulator/mtk-dvfsrc-regulator.c b/drivers/regulator/mtk-dvfsrc-regulator.c new file mode 100644 index 000000000000..d3d876198d6e --- /dev/null +++ b/drivers/regulator/mtk-dvfsrc-regulator.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2020 MediaTek Inc. + +#include <linux/err.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/of_regulator.h> +#include <linux/soc/mediatek/mtk_dvfsrc.h> + +#define DVFSRC_ID_VCORE 0 +#define DVFSRC_ID_VSCP 1 + +#define MT_DVFSRC_REGULAR(match, _name, _volt_table) \ +[DVFSRC_ID_##_name] = { \ + .desc = { \ + .name = match, \ + .of_match = of_match_ptr(match), \ + .ops = &dvfsrc_vcore_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = DVFSRC_ID_##_name, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(_volt_table), \ + .volt_table = _volt_table, \ + }, \ +} + +/* + * DVFSRC regulators' information + * + * @desc: standard fields of regulator description. + * @voltage_selector: Selector used for get_voltage_sel() and + * set_voltage_sel() callbacks + */ + +struct dvfsrc_regulator { + struct regulator_desc desc; +}; + +/* + * MTK DVFSRC regulators' init data + * + * @size: num of regulators + * @regulator_info: regulator info. + */ +struct dvfsrc_regulator_init_data { + u32 size; + struct dvfsrc_regulator *regulator_info; +}; + +static inline struct device *to_dvfsrc_dev(struct regulator_dev *rdev) +{ + return rdev_get_dev(rdev)->parent; +} + +static int dvfsrc_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) +{ + struct device *dvfsrc_dev = to_dvfsrc_dev(rdev); + int id = rdev_get_id(rdev); + + if (id == DVFSRC_ID_VCORE) + mtk_dvfsrc_send_request(dvfsrc_dev, + MTK_DVFSRC_CMD_VCORE_REQUEST, + selector); + else if (id == DVFSRC_ID_VSCP) + mtk_dvfsrc_send_request(dvfsrc_dev, + MTK_DVFSRC_CMD_VSCP_REQUEST, + selector); + else + return -EINVAL; + + return 0; +} + +static int dvfsrc_get_voltage_sel(struct regulator_dev *rdev) +{ + struct device *dvfsrc_dev = to_dvfsrc_dev(rdev); + int id = rdev_get_id(rdev); + int val, ret; + + if (id == DVFSRC_ID_VCORE) + ret = mtk_dvfsrc_query_info(dvfsrc_dev, + MTK_DVFSRC_CMD_VCORE_LEVEL_QUERY, + &val); + else if (id == DVFSRC_ID_VSCP) + ret = mtk_dvfsrc_query_info(dvfsrc_dev, + MTK_DVFSRC_CMD_VSCP_LEVEL_QUERY, + &val); + else + return -EINVAL; + + if (ret != 0) + return ret; + + return val; +} + +static const struct regulator_ops dvfsrc_vcore_ops = { + .list_voltage = regulator_list_voltage_table, + .get_voltage_sel = dvfsrc_get_voltage_sel, + .set_voltage_sel = dvfsrc_set_voltage_sel, +}; + +static const unsigned int mt8183_voltages[] = { + 725000, + 800000, +}; + +static struct dvfsrc_regulator mt8183_regulators[] = { + MT_DVFSRC_REGULAR("dvfsrc-vcore", VCORE, + mt8183_voltages), +}; + +static const struct dvfsrc_regulator_init_data regulator_mt8183_data = { + .size = ARRAY_SIZE(mt8183_regulators), + .regulator_info = &mt8183_regulators[0], +}; + +static const unsigned int mt6873_voltages[] = { + 575000, + 600000, + 650000, + 725000, +}; + +static struct dvfsrc_regulator mt6873_regulators[] = { + MT_DVFSRC_REGULAR("dvfsrc-vcore", VCORE, + mt6873_voltages), + MT_DVFSRC_REGULAR("dvfsrc-vscp", VSCP, + mt6873_voltages), +}; + +static const struct dvfsrc_regulator_init_data regulator_mt6873_data = { + .size = ARRAY_SIZE(mt6873_regulators), + .regulator_info = &mt6873_regulators[0], +}; + +static const struct of_device_id mtk_dvfsrc_regulator_match[] = { + { + .compatible = "mediatek,mt8183-dvfsrc", + .data = ®ulator_mt8183_data, + }, { + .compatible = "mediatek,mt8192-dvfsrc", + .data = ®ulator_mt6873_data, + }, { + .compatible = "mediatek,mt6873-dvfsrc", + .data = ®ulator_mt6873_data, + }, { + /* sentinel */ + }, +}; +MODULE_DEVICE_TABLE(of, mtk_dvfsrc_regulator_match); + +static int dvfsrc_vcore_regulator_probe(struct platform_device *pdev) +{ + const struct of_device_id *match; + struct device *dev = &pdev->dev; + struct regulator_config config = { }; + struct regulator_dev *rdev; + const struct dvfsrc_regulator_init_data *regulator_init_data; + struct dvfsrc_regulator *mt_regulators; + int i; + + match = of_match_node(mtk_dvfsrc_regulator_match, dev->parent->of_node); + + if (!match) { + dev_err(dev, "invalid compatible string\n"); + return -ENODEV; + } + + regulator_init_data = match->data; + + mt_regulators = regulator_init_data->regulator_info; + for (i = 0; i < regulator_init_data->size; i++) { + config.dev = dev->parent; + config.driver_data = (mt_regulators + i); + rdev = devm_regulator_register(dev->parent, + &(mt_regulators + i)->desc, + &config); + if (IS_ERR(rdev)) { + dev_err(dev, "failed to register %s\n", + (mt_regulators + i)->desc.name); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static struct platform_driver mtk_dvfsrc_regulator_driver = { + .driver = { + .name = "mtk-dvfsrc-regulator", + }, + .probe = dvfsrc_vcore_regulator_probe, +}; + +static int __init mtk_dvfsrc_regulator_init(void) +{ + return platform_driver_register(&mtk_dvfsrc_regulator_driver); +} +subsys_initcall(mtk_dvfsrc_regulator_init); + +static void __exit mtk_dvfsrc_regulator_exit(void) +{ + platform_driver_unregister(&mtk_dvfsrc_regulator_driver); +} +module_exit(mtk_dvfsrc_regulator_exit); + +MODULE_AUTHOR("Arvin wang <arvin.wang@mediatek.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index c395a8dda6f7..98320e1d8bf6 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -732,6 +732,15 @@ static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = { .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, }; +static const struct rpmh_vreg_hw_data pmic5_hfsmps515_1 = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(900000, 0, 4, 16000), + .n_voltages = 5, + .pmic_mode_map = pmic_mode_map_pmic5_smps, + .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, +}; + static const struct rpmh_vreg_hw_data pmic5_bob = { .regulator_type = VRM, .ops = &rpmh_regulator_vrm_bypass_ops, @@ -932,6 +941,19 @@ static const struct rpmh_vreg_init_data pm8009_vreg_data[] = { {}, }; +static const struct rpmh_vreg_init_data pm8009_1_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps510, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_hfsmps515_1, "vdd-s2"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l4"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l6"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l5-l6"), + RPMH_VREG("ldo7", "ldo%s6", &pmic5_pldo_lv, "vdd-l7"), + {}, +}; + static const struct rpmh_vreg_init_data pm6150_vreg_data[] = { RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps510, "vdd-s1"), RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps510, "vdd-s2"), @@ -1058,6 +1080,10 @@ static const struct of_device_id __maybe_unused rpmh_regulator_match_table[] = { .data = pm8009_vreg_data, }, { + .compatible = "qcom,pm8009-1-rpmh-regulators", + .data = pm8009_1_vreg_data, + }, + { .compatible = "qcom,pm8150-rpmh-regulators", .data = pm8150_vreg_data, }, diff --git a/drivers/regulator/rt4831-regulator.c b/drivers/regulator/rt4831-regulator.c new file mode 100644 index 000000000000..3d4695ded629 --- /dev/null +++ b/drivers/regulator/rt4831-regulator.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/bitops.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/regulator/driver.h> + +enum { + DSV_OUT_VLCM = 0, + DSV_OUT_VPOS, + DSV_OUT_VNEG, + DSV_OUT_MAX +}; + +#define RT4831_REG_DSVEN 0x09 +#define RT4831_REG_VLCM 0x0c +#define RT4831_REG_VPOS 0x0d +#define RT4831_REG_VNEG 0x0e +#define RT4831_REG_FLAGS 0x0f + +#define RT4831_VOLT_MASK GENMASK(5, 0) +#define RT4831_DSVMODE_SHIFT 5 +#define RT4831_DSVMODE_MASK GENMASK(7, 5) +#define RT4831_POSADEN_MASK BIT(4) +#define RT4831_NEGADEN_MASK BIT(3) +#define RT4831_POSEN_MASK BIT(2) +#define RT4831_NEGEN_MASK BIT(1) + +#define RT4831_OTP_MASK BIT(6) +#define RT4831_LCMOVP_MASK BIT(5) +#define RT4831_VPOSSCP_MASK BIT(3) +#define RT4831_VNEGSCP_MASK BIT(2) + +#define DSV_MODE_NORMAL (0x4 << RT4831_DSVMODE_SHIFT) +#define DSV_MODE_BYPASS (0x6 << RT4831_DSVMODE_SHIFT) +#define STEP_UV 50000 +#define VLCM_MIN_UV 4000000 +#define VLCM_MAX_UV 7150000 +#define VLCM_N_VOLTAGES ((VLCM_MAX_UV - VLCM_MIN_UV) / STEP_UV + 1) +#define VPN_MIN_UV 4000000 +#define VPN_MAX_UV 6500000 +#define VPN_N_VOLTAGES ((VPN_MAX_UV - VPN_MIN_UV) / STEP_UV + 1) + +static int rt4831_get_error_flags(struct regulator_dev *rdev, unsigned int *flags) +{ + struct regmap *regmap = rdev_get_regmap(rdev); + int rid = rdev_get_id(rdev); + unsigned int val, events = 0; + int ret; + + ret = regmap_read(regmap, RT4831_REG_FLAGS, &val); + if (ret) + return ret; + + if (val & RT4831_OTP_MASK) + events |= REGULATOR_ERROR_OVER_TEMP; + + if (rid == DSV_OUT_VLCM && (val & RT4831_LCMOVP_MASK)) + events |= REGULATOR_ERROR_OVER_CURRENT; + + if (rid == DSV_OUT_VPOS && (val & RT4831_VPOSSCP_MASK)) + events |= REGULATOR_ERROR_OVER_CURRENT; + + if (rid == DSV_OUT_VNEG && (val & RT4831_VNEGSCP_MASK)) + events |= REGULATOR_ERROR_OVER_CURRENT; + + *flags = events; + return 0; +} + +static const struct regulator_ops rt4831_dsvlcm_ops = { + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_bypass = regulator_set_bypass_regmap, + .get_bypass = regulator_get_bypass_regmap, + .get_error_flags = rt4831_get_error_flags, +}; + +static const struct regulator_ops rt4831_dsvpn_ops = { + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_active_discharge = regulator_set_active_discharge_regmap, + .get_error_flags = rt4831_get_error_flags, +}; + +static const struct regulator_desc rt4831_regulator_descs[] = { + { + .name = "DSVLCM", + .ops = &rt4831_dsvlcm_ops, + .of_match = of_match_ptr("DSVLCM"), + .regulators_node = of_match_ptr("regulators"), + .type = REGULATOR_VOLTAGE, + .id = DSV_OUT_VLCM, + .n_voltages = VLCM_N_VOLTAGES, + .min_uV = VLCM_MIN_UV, + .uV_step = STEP_UV, + .vsel_reg = RT4831_REG_VLCM, + .vsel_mask = RT4831_VOLT_MASK, + .bypass_reg = RT4831_REG_DSVEN, + .bypass_val_on = DSV_MODE_BYPASS, + .bypass_val_off = DSV_MODE_NORMAL, + }, + { + .name = "DSVP", + .ops = &rt4831_dsvpn_ops, + .of_match = of_match_ptr("DSVP"), + .regulators_node = of_match_ptr("regulators"), + .type = REGULATOR_VOLTAGE, + .id = DSV_OUT_VPOS, + .n_voltages = VPN_N_VOLTAGES, + .min_uV = VPN_MIN_UV, + .uV_step = STEP_UV, + .vsel_reg = RT4831_REG_VPOS, + .vsel_mask = RT4831_VOLT_MASK, + .enable_reg = RT4831_REG_DSVEN, + .enable_mask = RT4831_POSEN_MASK, + .active_discharge_reg = RT4831_REG_DSVEN, + .active_discharge_mask = RT4831_POSADEN_MASK, + }, + { + .name = "DSVN", + .ops = &rt4831_dsvpn_ops, + .of_match = of_match_ptr("DSVN"), + .regulators_node = of_match_ptr("regulators"), + .type = REGULATOR_VOLTAGE, + .id = DSV_OUT_VNEG, + .n_voltages = VPN_N_VOLTAGES, + .min_uV = VPN_MIN_UV, + .uV_step = STEP_UV, + .vsel_reg = RT4831_REG_VNEG, + .vsel_mask = RT4831_VOLT_MASK, + .enable_reg = RT4831_REG_DSVEN, + .enable_mask = RT4831_NEGEN_MASK, + .active_discharge_reg = RT4831_REG_DSVEN, + .active_discharge_mask = RT4831_NEGADEN_MASK, + } +}; + +static int rt4831_regulator_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + struct regulator_dev *rdev; + struct regulator_config config = {}; + int i, ret; + + regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (IS_ERR(regmap)) { + dev_err(&pdev->dev, "Failed to init regmap\n"); + return PTR_ERR(regmap); + } + + /* Configure DSV mode to normal by default */ + ret = regmap_update_bits(regmap, RT4831_REG_DSVEN, RT4831_DSVMODE_MASK, DSV_MODE_NORMAL); + if (ret) { + dev_err(&pdev->dev, "Failed to configure dsv mode to normal\n"); + return ret; + } + + config.dev = pdev->dev.parent; + config.regmap = regmap; + + for (i = 0; i < DSV_OUT_MAX; i++) { + rdev = devm_regulator_register(&pdev->dev, rt4831_regulator_descs + i, &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "Failed to register %d regulator\n", i); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static const struct platform_device_id rt4831_regulator_match[] = { + { "rt4831-regulator", 0 }, + {} +}; +MODULE_DEVICE_TABLE(platform, rt4831_regulator_match); + +static struct platform_driver rt4831_regulator_driver = { + .driver = { + .name = "rt4831-regulator", + }, + .id_table = rt4831_regulator_match, + .probe = rt4831_regulator_probe, +}; +module_platform_driver(rt4831_regulator_driver); + +MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index 524a7e4702c2..302a330c5c84 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -368,7 +368,6 @@ struct ab8500 { int it_latchhier_num; }; -struct ab8500_regulator_platform_data; struct ab8500_codec_platform_data; struct ab8500_sysctrl_platform_data; @@ -376,11 +375,9 @@ struct ab8500_sysctrl_platform_data; * struct ab8500_platform_data - AB8500 platform data * @irq_base: start of AB8500 IRQs, AB8500_NR_IRQS will be used * @init: board-specific initialization after detection of ab8500 - * @regulator: machine-specific constraints for regulators */ struct ab8500_platform_data { void (*init) (struct ab8500 *); - struct ab8500_regulator_platform_data *regulator; struct ab8500_codec_platform_data *codec; struct ab8500_sysctrl_platform_data *sysctrl; }; diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h deleted file mode 100644 index 3ab1ddf151a2..000000000000 --- a/include/linux/regulator/ab8500.h +++ /dev/null @@ -1,166 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson - * Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson - * Daniel Willerud <daniel.willerud@stericsson.com> for ST-Ericsson - */ - -#ifndef __LINUX_MFD_AB8500_REGULATOR_H -#define __LINUX_MFD_AB8500_REGULATOR_H - -#include <linux/platform_device.h> - -/* AB8500 regulators */ -enum ab8500_regulator_id { - AB8500_LDO_AUX1, - AB8500_LDO_AUX2, - AB8500_LDO_AUX3, - AB8500_LDO_INTCORE, - AB8500_LDO_TVOUT, - AB8500_LDO_AUDIO, - AB8500_LDO_ANAMIC1, - AB8500_LDO_ANAMIC2, - AB8500_LDO_DMIC, - AB8500_LDO_ANA, - AB8500_NUM_REGULATORS, -}; - -/* AB8505 regulators */ -enum ab8505_regulator_id { - AB8505_LDO_AUX1, - AB8505_LDO_AUX2, - AB8505_LDO_AUX3, - AB8505_LDO_AUX4, - AB8505_LDO_AUX5, - AB8505_LDO_AUX6, - AB8505_LDO_INTCORE, - AB8505_LDO_ADC, - AB8505_LDO_AUDIO, - AB8505_LDO_ANAMIC1, - AB8505_LDO_ANAMIC2, - AB8505_LDO_AUX8, - AB8505_LDO_ANA, - AB8505_NUM_REGULATORS, -}; - -/* AB8500 and AB8505 register initialization */ -struct ab8500_regulator_reg_init { - int id; - u8 mask; - u8 value; -}; - -#define INIT_REGULATOR_REGISTER(_id, _mask, _value) \ - { \ - .id = _id, \ - .mask = _mask, \ - .value = _value, \ - } - -/* AB8500 registers */ -enum ab8500_regulator_reg { - AB8500_REGUREQUESTCTRL2, - AB8500_REGUREQUESTCTRL3, - AB8500_REGUREQUESTCTRL4, - AB8500_REGUSYSCLKREQ1HPVALID1, - AB8500_REGUSYSCLKREQ1HPVALID2, - AB8500_REGUHWHPREQ1VALID1, - AB8500_REGUHWHPREQ1VALID2, - AB8500_REGUHWHPREQ2VALID1, - AB8500_REGUHWHPREQ2VALID2, - AB8500_REGUSWHPREQVALID1, - AB8500_REGUSWHPREQVALID2, - AB8500_REGUSYSCLKREQVALID1, - AB8500_REGUSYSCLKREQVALID2, - AB8500_REGUMISC1, - AB8500_VAUDIOSUPPLY, - AB8500_REGUCTRL1VAMIC, - AB8500_VPLLVANAREGU, - AB8500_VREFDDR, - AB8500_EXTSUPPLYREGU, - AB8500_VAUX12REGU, - AB8500_VRF1VAUX3REGU, - AB8500_VAUX1SEL, - AB8500_VAUX2SEL, - AB8500_VRF1VAUX3SEL, - AB8500_REGUCTRL2SPARE, - AB8500_REGUCTRLDISCH, - AB8500_REGUCTRLDISCH2, - AB8500_NUM_REGULATOR_REGISTERS, -}; - -/* AB8505 registers */ -enum ab8505_regulator_reg { - AB8505_REGUREQUESTCTRL1, - AB8505_REGUREQUESTCTRL2, - AB8505_REGUREQUESTCTRL3, - AB8505_REGUREQUESTCTRL4, - AB8505_REGUSYSCLKREQ1HPVALID1, - AB8505_REGUSYSCLKREQ1HPVALID2, - AB8505_REGUHWHPREQ1VALID1, - AB8505_REGUHWHPREQ1VALID2, - AB8505_REGUHWHPREQ2VALID1, - AB8505_REGUHWHPREQ2VALID2, - AB8505_REGUSWHPREQVALID1, - AB8505_REGUSWHPREQVALID2, - AB8505_REGUSYSCLKREQVALID1, - AB8505_REGUSYSCLKREQVALID2, - AB8505_REGUVAUX4REQVALID, - AB8505_REGUMISC1, - AB8505_VAUDIOSUPPLY, - AB8505_REGUCTRL1VAMIC, - AB8505_VSMPSAREGU, - AB8505_VSMPSBREGU, - AB8505_VSAFEREGU, /* NOTE! PRCMU register */ - AB8505_VPLLVANAREGU, - AB8505_EXTSUPPLYREGU, - AB8505_VAUX12REGU, - AB8505_VRF1VAUX3REGU, - AB8505_VSMPSASEL1, - AB8505_VSMPSASEL2, - AB8505_VSMPSASEL3, - AB8505_VSMPSBSEL1, - AB8505_VSMPSBSEL2, - AB8505_VSMPSBSEL3, - AB8505_VSAFESEL1, /* NOTE! PRCMU register */ - AB8505_VSAFESEL2, /* NOTE! PRCMU register */ - AB8505_VSAFESEL3, /* NOTE! PRCMU register */ - AB8505_VAUX1SEL, - AB8505_VAUX2SEL, - AB8505_VRF1VAUX3SEL, - AB8505_VAUX4REQCTRL, - AB8505_VAUX4REGU, - AB8505_VAUX4SEL, - AB8505_REGUCTRLDISCH, - AB8505_REGUCTRLDISCH2, - AB8505_REGUCTRLDISCH3, - AB8505_CTRLVAUX5, - AB8505_CTRLVAUX6, - AB8505_NUM_REGULATOR_REGISTERS, -}; - -/* AB8500 external regulators */ -struct ab8500_ext_regulator_cfg { - bool hwreq; /* requires hw mode or high power mode */ -}; - -enum ab8500_ext_regulator_id { - AB8500_EXT_SUPPLY1, - AB8500_EXT_SUPPLY2, - AB8500_EXT_SUPPLY3, - AB8500_NUM_EXT_REGULATORS, -}; - -/* AB8500 regulator platform data */ -struct ab8500_regulator_platform_data { - int num_reg_init; - struct ab8500_regulator_reg_init *reg_init; - int num_regulator; - struct regulator_init_data *regulator; - int num_ext_regulator; - struct regulator_init_data *ext_regulator; -}; - -#endif diff --git a/lib/linear_ranges.c b/lib/linear_ranges.c index 9495ef3572b7..ced5c15d3f04 100644 --- a/lib/linear_ranges.c +++ b/lib/linear_ranges.c @@ -128,7 +128,7 @@ EXPORT_SYMBOL_GPL(linear_range_get_value_array); * @selector: address where found selector value is updated * @found: flag to indicate that given value was in the range * - * Return selector which which range value is closest match for given + * Return selector for which range value is closest match for given * input value. Value is matching if it is equal or smaller than given * value. If given value is in the range, then @found is set true. * @@ -168,11 +168,11 @@ EXPORT_SYMBOL_GPL(linear_range_get_selector_low); * @selector: address where found selector value is updated * @found: flag to indicate that given value was in the range * - * Scan array of ranges for selector which which range value matches given + * Scan array of ranges for selector for which range value matches given * input value. Value is matching if it is equal or smaller than given * value. If given value is found to be in a range scanning is stopped and * @found is set true. If a range with values smaller than given value is found - * but the range max is being smaller than given value, then the ranges + * but the range max is being smaller than given value, then the range's * biggest selector is updated to @selector but scanning ranges is continued * and @found is set to false. * @@ -209,7 +209,7 @@ EXPORT_SYMBOL_GPL(linear_range_get_selector_low_array); * @selector: address where found selector value is updated * @found: flag to indicate that given value was in the range * - * Return selector which which range value is closest match for given + * Return selector for which range value is closest match for given * input value. Value is matching if it is equal or higher than given * value. If given value is in the range, then @found is set true. * |