Update Linux to v5.10.109
Sourced from [1]
[1] https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.109.tar.xz
Change-Id: I19bca9fc6762d4e63bcf3e4cba88bbe560d9c76c
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/drivers/regulator/88pg86x.c b/drivers/regulator/88pg86x.c
index d5ef55c..e91d588 100644
--- a/drivers/regulator/88pg86x.c
+++ b/drivers/regulator/88pg86x.c
@@ -11,13 +11,13 @@
.list_voltage = regulator_list_voltage_linear_range,
};
-static const struct regulator_linear_range pg86x_buck1_ranges[] = {
+static const struct linear_range pg86x_buck1_ranges[] = {
REGULATOR_LINEAR_RANGE( 0, 0, 10, 0),
REGULATOR_LINEAR_RANGE(1000000, 11, 34, 25000),
REGULATOR_LINEAR_RANGE(1600000, 35, 47, 50000),
};
-static const struct regulator_linear_range pg86x_buck2_ranges[] = {
+static const struct linear_range pg86x_buck2_ranges[] = {
REGULATOR_LINEAR_RANGE( 0, 0, 15, 0),
REGULATOR_LINEAR_RANGE(1000000, 16, 39, 25000),
REGULATOR_LINEAR_RANGE(1600000, 40, 52, 50000),
@@ -84,7 +84,7 @@
return 0;
}
-static const struct of_device_id pg86x_dt_ids [] = {
+static const struct of_device_id __maybe_unused pg86x_dt_ids[] = {
{ .compatible = "marvell,88pg867" },
{ .compatible = "marvell,88pg868" },
{ }
diff --git a/drivers/regulator/88pm800-regulator.c b/drivers/regulator/88pm800-regulator.c
index 69ae258..d08ee81 100644
--- a/drivers/regulator/88pm800-regulator.c
+++ b/drivers/regulator/88pm800-regulator.c
@@ -134,13 +134,13 @@
}
/* Ranges are sorted in ascending order. */
-static const struct regulator_linear_range buck1_volt_range[] = {
+static const struct linear_range buck1_volt_range[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500),
REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x54, 50000),
};
/* BUCK 2~5 have same ranges. */
-static const struct regulator_linear_range buck2_5_volt_range[] = {
+static const struct linear_range buck2_5_volt_range[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500),
REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x72, 50000),
};
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 3ee6353..020a00d 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
menuconfig REGULATOR
bool "Voltage and Current Regulator Support"
+ select LINEAR_RANGES
help
Generic Voltage and Current Regulator support.
@@ -107,6 +108,7 @@
config REGULATOR_ANATOP
tristate "Freescale i.MX on-chip ANATOP LDO regulators"
+ depends on ARCH_MXC || COMPILE_TEST
depends on MFD_SYSCON
help
Say y here to support Freescale i.MX on-chip ANATOP LDOs
@@ -194,9 +196,22 @@
This driver can also be built as a module. If so, the module
will be called bd70528-regulator.
+config REGULATOR_BD71828
+ tristate "ROHM BD71828 Power Regulator"
+ depends on MFD_ROHM_BD71828
+ select REGULATOR_ROHM
+ help
+ This driver supports voltage regulators on ROHM BD71828 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 bd71828-regulator.
+
config REGULATOR_BD718XX
tristate "ROHM BD71837 Power Regulator"
depends on MFD_ROHM_BD718XX
+ select REGULATOR_ROHM
help
This driver supports voltage regulators on ROHM BD71837 PMIC.
This will enable support for the software controllable buck
@@ -216,6 +231,16 @@
This driver can also be built as a module. If so, the module
will be called bd9571mwv-regulator.
+config REGULATOR_BD957XMUF
+ tristate "ROHM BD9576MUF and BD9573MUF Regulators"
+ depends on MFD_ROHM_BD957XMUF
+ help
+ This driver supports voltage regulators on ROHM BD9576MUF and
+ BD9573MUF PMICs.
+
+ This driver can also be built as a module. If so, the module
+ will be called bd9576-regulator.
+
config REGULATOR_CPCAP
tristate "Motorola CPCAP regulator"
depends on MFD_CPCAP
@@ -223,6 +248,16 @@
Say y here for CPCAP regulator found on some Motorola phones
and tablets such as Droid 4.
+config REGULATOR_CROS_EC
+ tristate "ChromeOS EC regulators"
+ depends on CROS_EC && OF
+ help
+ This driver supports voltage regulators that is connected to ChromeOS
+ EC and controlled through EC host commands.
+
+ This driver can also be built as a module. If so, the module
+ will be called cros-ec-regulator.
+
config REGULATOR_DA903X
tristate "Dialog Semiconductor DA9030/DA9034 regulators"
depends on PMIC_DA903X
@@ -311,6 +346,16 @@
input voltage supply of 2.5V to 5.5V. The output voltage is
programmed through an I2C interface.
+config REGULATOR_FAN53880
+ tristate "Fairchild FAN53880 Regulator"
+ depends on I2C && (OF || COMPILE_TEST)
+ select REGMAP_I2C
+ help
+ This driver supports Fairchild (ON Semiconductor) FAN53880
+ regulator. The regulator is a programmable power management IC
+ (PMIC), it is controlled by I2C and provides one BUCK, one BOOST
+ and four LDO outputs.
+
config REGULATOR_GPIO
tristate "GPIO regulator support"
depends on GPIOLIB || COMPILE_TEST
@@ -465,7 +510,7 @@
config REGULATOR_MAX77620
tristate "Maxim 77620/MAX20024 voltage regulator"
- depends on MFD_MAX77620
+ depends on MFD_MAX77620 || COMPILE_TEST
help
This driver controls Maxim MAX77620 voltage output regulator
via I2C bus. The provided regulator is suitable for Tegra
@@ -474,7 +519,7 @@
config REGULATOR_MAX77650
tristate "Maxim MAX77650/77651 regulator support"
- depends on MFD_MAX77650
+ depends on MFD_MAX77650 || COMPILE_TEST
help
Regulator driver for MAX77650/77651 PMIC from Maxim
Semiconductor. This device has a SIMO with three independent
@@ -497,7 +542,7 @@
config REGULATOR_MAX8907
tristate "Maxim 8907 voltage regulator"
- depends on MFD_MAX8907
+ depends on MFD_MAX8907 || COMPILE_TEST
help
This driver controls a Maxim 8907 voltage output regulator
via I2C bus. The provided regulator is suitable for Tegra
@@ -547,7 +592,7 @@
config REGULATOR_MAX77686
tristate "Maxim 77686 regulator"
- depends on MFD_MAX77686
+ depends on MFD_MAX77686 || COMPILE_TEST
help
This driver controls a Maxim 77686 regulator
via I2C bus. The provided regulator is suitable for
@@ -555,7 +600,7 @@
config REGULATOR_MAX77693
tristate "Maxim 77693/77843 regulator"
- depends on (MFD_MAX77693 || MFD_MAX77843)
+ depends on MFD_MAX77693 || MFD_MAX77843 || COMPILE_TEST
help
This driver controls a Maxim 77693/77843 regulators via I2C bus.
The regulators include two LDOs, 'SAFEOUT1', 'SAFEOUT2'
@@ -564,13 +609,23 @@
config REGULATOR_MAX77802
tristate "Maxim 77802 regulator"
- depends on MFD_MAX77686
+ depends on MFD_MAX77686 || COMPILE_TEST
help
This driver controls a Maxim 77802 regulator
via I2C bus. The provided regulator is suitable for
Exynos5420/Exynos5800 SoCs to control various voltages.
It includes support for control of voltage and ramp speed.
+config REGULATOR_MAX77826
+ tristate "Maxim 77826 regulator"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ This driver controls a Maxim 77826 regulator via I2C bus.
+ The regulator include 15 LDOs, BUCK and BUCK BOOST regulator.
+ It includes support for control of output voltage. This
+ regulator is found on the Samsung Galaxy S5 (klte) smartphone.
+
config REGULATOR_MC13XXX_CORE
tristate
@@ -600,6 +655,44 @@
through the regulator interface. In addition it enables
suspend-to-ram/standby transition.
+config REGULATOR_MP5416
+ tristate "Monolithic MP5416 PMIC"
+ depends on I2C && OF
+ select REGMAP_I2C
+ help
+ Say y here to support the MP5416 PMIC. This will enable supports
+ the software controllable 4 buck and 4 LDO regulators.
+ Say M here if you want to include support for the regulator as a
+ module.
+
+config REGULATOR_MP8859
+ tristate "MPS MP8859 regulator driver"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Say y here to support the MP8859 voltage regulator. This driver
+ supports basic operations (get/set voltage) through the regulator
+ interface.
+ Say M here if you want to include support for the regulator as a
+ module. The module will be named "mp8859".
+
+config REGULATOR_MP886X
+ tristate "MPS MP8869 regulator driver"
+ depends on I2C && (OF || COMPILE_TEST)
+ select REGMAP_I2C
+ help
+ This driver supports the MP8869 voltage regulator.
+
+config REGULATOR_MPQ7920
+ tristate "Monolithic MPQ7920 PMIC"
+ depends on I2C && OF
+ select REGMAP_I2C
+ help
+ Say y here to support the MPQ7920 PMIC. This will enable supports
+ the software controllable 4 buck and 5 LDO regulators.
+ This driver supports the control of different power rails of device
+ through regulator interface.
+
config REGULATOR_MT6311
tristate "MediaTek MT6311 PMIC"
depends on I2C
@@ -621,13 +714,22 @@
config REGULATOR_MT6358
tristate "MediaTek MT6358 PMIC"
- depends on MFD_MT6397 && BROKEN
+ depends on MFD_MT6397
help
Say y here to select this option to enable the power regulator of
MediaTek MT6358 PMIC.
This driver supports the control of different power rails of device
through regulator interface.
+config REGULATOR_MT6360
+ tristate "MT6360 SubPMIC Regulator"
+ depends on MFD_MT6360
+ help
+ Say Y here to enable MT6360 regulator support.
+ This is support MT6360 PMIC/LDO part include
+ 2-channel buck with Thermal Shutdown and Overload Protection
+ 6-channel High PSRR and Low Dropout LDO.
+
config REGULATOR_MT6380
tristate "MediaTek MT6380 PMIC"
depends on MTK_PMIC_WRAP
@@ -667,6 +769,14 @@
This driver provides support for OMAP pbias modelled
regulators.
+config REGULATOR_PCA9450
+ tristate "NXP PCA9450A/PCA9450B/PCA9450C regulator driver"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Say y here to support the NXP PCA9450A/PCA9450B/PCA9450C PMIC
+ regulator driver.
+
config REGULATOR_PCAP
tristate "Motorola PCAP2 regulator driver"
depends on EZX_PCAP
@@ -763,6 +873,26 @@
Qualcomm SPMI PMICs as a module. The module will be named
"qcom_spmi-regulator".
+config REGULATOR_QCOM_USB_VBUS
+ tristate "Qualcomm USB Vbus regulator driver"
+ depends on SPMI || COMPILE_TEST
+ help
+ If you say yes to this option, support will be included for the
+ regulator used to enable the VBUS output.
+
+ Say M here if you want to include support for enabling the VBUS output
+ as a module. The module will be named "qcom_usb_vbus_regulator".
+
+config REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY
+ tristate "Raspberry Pi 7-inch touchscreen panel ATTINY regulator"
+ depends on BACKLIGHT_CLASS_DEVICE
+ depends on I2C
+ select REGMAP_I2C
+ help
+ This driver supports ATTINY regulator on the Raspberry Pi 7-inch
+ touchscreen unit. The regulator is used to enable power to the
+ TC358762, display and to control backlight.
+
config REGULATOR_RC5T583
tristate "RICOH RC5T583 Power regulators"
depends on MFD_RC5T583
@@ -790,6 +920,17 @@
Say y here to support the regulators found on Ricoh RN5T567,
RN5T618 or RC5T619 PMIC.
+config REGULATOR_ROHM
+ tristate
+
+config REGULATOR_RT4801
+ tristate "Richtek RT4801 Regulators"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ This adds support for voltage regulators in Richtek RT4801 Display Bias IC.
+ The device supports two regulators (DSVP/DSVN).
+
config REGULATOR_RT5033
tristate "Richtek RT5033 Regulators"
depends on MFD_RT5033
@@ -798,16 +939,25 @@
RT5033 PMIC. The device supports multiple regulators like
current source, LDO and Buck.
+config REGULATOR_RTMV20
+ tristate "RTMV20 Laser Diode Regulator"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ This driver adds support for the load switch current regulator on
+ the Richtek RTMV20. It can support the load current up to 6A and
+ integrate strobe/vsync/fsin signal to synchronize the IR camera.
+
config REGULATOR_S2MPA01
tristate "Samsung S2MPA01 voltage regulator"
- depends on MFD_SEC_CORE
+ depends on MFD_SEC_CORE || COMPILE_TEST
help
This driver controls Samsung S2MPA01 voltage output regulator
via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs.
config REGULATOR_S2MPS11
tristate "Samsung S2MPS11/13/14/15/S2MPU02 voltage regulator"
- depends on MFD_SEC_CORE
+ depends on MFD_SEC_CORE || COMPILE_TEST
help
This driver supports a Samsung S2MPS11/13/14/15/S2MPU02 voltage
output regulator via I2C bus. The chip is comprised of high efficient
@@ -816,7 +966,7 @@
config REGULATOR_S5M8767
tristate "Samsung S5M8767A voltage regulator"
- depends on MFD_SEC_CORE
+ depends on MFD_SEC_CORE || COMPILE_TEST
help
This driver supports a Samsung S5M8767A voltage output regulator
via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and
@@ -841,10 +991,10 @@
will be called sky81452-regulator.
config REGULATOR_SLG51000
- tristate "Dialog Semiconductor SLG51000 regulators"
- depends on I2C
- select REGMAP_I2C
- help
+ tristate "Dialog Semiconductor SLG51000 regulators"
+ depends on I2C
+ select REGMAP_I2C
+ help
Say y here to support for the Dialog Semiconductor SLG51000.
The SLG51000 is seven compact and customizable low dropout
regulators.
@@ -923,6 +1073,13 @@
help
This driver supports SY8824C single output regulator.
+config REGULATOR_SY8827N
+ tristate "Silergy SY8827N regulator"
+ depends on I2C && (OF || COMPILE_TEST)
+ select REGMAP_I2C
+ help
+ This driver supports SY8827N single output regulator.
+
config REGULATOR_TPS51632
tristate "TI TPS51632 Power Regulator"
depends on I2C
@@ -1077,6 +1234,13 @@
This driver provides support for voltage regulators available
on the ARM Ltd's Versatile Express platform.
+config REGULATOR_VQMMC_IPQ4019
+ tristate "IPQ4019 VQMMC SD LDO regulator support"
+ depends on ARCH_QCOM
+ help
+ This driver provides support for the VQMMC LDO I/0
+ voltage regulator of the IPQ4019 SD/EMMC controller.
+
config REGULATOR_WM831X
tristate "Wolfson Microelectronics WM831x PMIC regulators"
depends on MFD_WM831X
@@ -1105,5 +1269,15 @@
This driver provides support for the voltage regulators on the
WM8994 CODEC.
+config REGULATOR_QCOM_LABIBB
+ tristate "QCOM LAB/IBB regulator support"
+ depends on SPMI || COMPILE_TEST
+ help
+ This driver supports Qualcomm's LAB/IBB regulators present on the
+ Qualcomm's PMIC chip pmi8998. QCOM LAB and IBB are SPMI
+ based PMIC implementations. LAB can be used as positive
+ boost regulator and IBB can be used as a negative boost regulator
+ for LCD display panel.
+
endif
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 2210ba5..6ebae51 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -13,6 +13,7 @@
obj-$(CONFIG_REGULATOR_88PG86X) += 88pg86x.o
obj-$(CONFIG_REGULATOR_88PM800) += 88pm800-regulator.o
obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
+obj-$(CONFIG_REGULATOR_CROS_EC) += cros-ec-regulator.o
obj-$(CONFIG_REGULATOR_CPCAP) += cpcap-regulator.o
obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
@@ -28,9 +29,11 @@
obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o
obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
obj-$(CONFIG_REGULATOR_BD70528) += bd70528-regulator.o
+obj-$(CONFIG_REGULATOR_BD71828) += bd71828-regulator.o
obj-$(CONFIG_REGULATOR_BD718XX) += bd718x7-regulator.o
obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o
-obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
+obj-$(CONFIG_REGULATOR_BD957XMUF) += bd9576-regulator.o
+obj-$(CONFIG_REGULATOR_DA903X) += da903x-regulator.o
obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
obj-$(CONFIG_REGULATOR_DA9062) += da9062-regulator.o
@@ -40,6 +43,7 @@
obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
+obj-$(CONFIG_REGULATOR_FAN53880) += fan53880.o
obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o
obj-$(CONFIG_REGULATOR_HI6421V530) += hi6421v530-regulator.o
@@ -73,20 +77,29 @@
obj-$(CONFIG_REGULATOR_MAX77686) += max77686-regulator.o
obj-$(CONFIG_REGULATOR_MAX77693) += max77693-regulator.o
obj-$(CONFIG_REGULATOR_MAX77802) += max77802-regulator.o
+obj-$(CONFIG_REGULATOR_MAX77826) += max77826-regulator.o
obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
obj-$(CONFIG_REGULATOR_MCP16502) += mcp16502.o
+obj-$(CONFIG_REGULATOR_MP5416) += mp5416.o
+obj-$(CONFIG_REGULATOR_MP8859) += mp8859.o
+obj-$(CONFIG_REGULATOR_MP886X) += mp886x.o
+obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o
obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
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_QCOM_LABIBB) += qcom-labibb-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o
+obj-$(CONFIG_REGULATOR_QCOM_USB_VBUS) += qcom_usb_vbus-regulator.o
obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
+obj-$(CONFIG_REGULATOR_PCA9450) += pca9450-regulator.o
obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
obj-$(CONFIG_REGULATOR_PV88060) += pv88060-regulator.o
obj-$(CONFIG_REGULATOR_PV88080) += pv88080-regulator.o
@@ -96,10 +109,14 @@
obj-$(CONFIG_REGULATOR_PBIAS) += pbias-regulator.o
obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
+obj-$(CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY) += rpi-panel-attiny-regulator.o
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
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_RT5033) += rt5033-regulator.o
+obj-$(CONFIG_REGULATOR_RTMV20) += rtmv20-regulator.o
obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
@@ -113,6 +130,7 @@
obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
obj-$(CONFIG_REGULATOR_SY8106A) += sy8106a-regulator.o
obj-$(CONFIG_REGULATOR_SY8824X) += sy8824x.o
+obj-$(CONFIG_REGULATOR_SY8827N) += sy8827n.o
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
@@ -132,6 +150,7 @@
obj-$(CONFIG_REGULATOR_UNIPHIER) += uniphier-regulator.o
obj-$(CONFIG_REGULATOR_VCTRL) += vctrl-regulator.o
obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o
+obj-$(CONFIG_REGULATOR_VQMMC_IPQ4019) += vqmmc-ipq4019-regulator.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
index f60e1b2..47b8b6f 100644
--- a/drivers/regulator/ab8500.c
+++ b/drivers/regulator/ab8500.c
@@ -59,6 +59,7 @@
* @voltage_bank: bank to control regulator voltage
* @voltage_reg: register to control regulator voltage
* @voltage_mask: mask to control regulator voltage
+ * @expand_register:
*/
struct ab8500_regulator_info {
struct device *dev;
@@ -79,12 +80,6 @@
u8 voltage_bank;
u8 voltage_reg;
u8 voltage_mask;
- struct {
- u8 voltage_limit;
- u8 voltage_bank;
- u8 voltage_reg;
- u8 voltage_mask;
- } expand_register;
};
/* voltage tables for the vauxn/vintcore supplies */
@@ -139,17 +134,6 @@
1350000,
};
-static const unsigned int ldo_sdio_voltages[] = {
- 1160000,
- 1050000,
- 1100000,
- 1500000,
- 1800000,
- 2200000,
- 2910000,
- 3050000,
-};
-
static const unsigned int fixed_1200000_voltage[] = {
1200000,
};
@@ -166,10 +150,6 @@
2050000,
};
-static const unsigned int fixed_3300000_voltage[] = {
- 3300000,
-};
-
static const unsigned int ldo_vana_voltages[] = {
1050000,
1075000,
@@ -192,13 +172,6 @@
2600000, /* Duplicated in Vaudio and IsoUicc Control register. */
};
-static const unsigned int ldo_vdmic_voltages[] = {
- 1800000,
- 1900000,
- 2000000,
- 2850000,
-};
-
static DEFINE_MUTEX(shared_mode_mutex);
static struct ab8500_shared_mode ldo_anamic1_shared;
static struct ab8500_shared_mode ldo_anamic2_shared;
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c
index 0fa97f9..19b9742 100644
--- a/drivers/regulator/act8865-regulator.c
+++ b/drivers/regulator/act8865-regulator.c
@@ -220,13 +220,13 @@
.val_bits = 8,
};
-static const struct regulator_linear_range act8865_voltage_ranges[] = {
+static const struct linear_range act8865_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000),
REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000),
REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
};
-static const struct regulator_linear_range act8600_sudcdc_voltage_ranges[] = {
+static const struct linear_range act8600_sudcdc_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(3000000, 0, 63, 0),
REGULATOR_LINEAR_RANGE(3000000, 64, 159, 100000),
REGULATOR_LINEAR_RANGE(12600000, 160, 191, 200000),
diff --git a/drivers/regulator/act8945a-regulator.c b/drivers/regulator/act8945a-regulator.c
index d2f804d..6a62f94 100644
--- a/drivers/regulator/act8945a-regulator.c
+++ b/drivers/regulator/act8945a-regulator.c
@@ -73,7 +73,7 @@
u32 op_mode[ACT8945A_ID_MAX];
};
-static const struct regulator_linear_range act8945a_voltage_ranges[] = {
+static const struct linear_range act8945a_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000),
REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000),
REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index 754739d..f9856d4 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -139,7 +139,7 @@
.map_voltage = regulator_map_voltage_linear,
};
-static struct regulator_ops anatop_core_rops = {
+static const struct regulator_ops anatop_core_rops = {
.enable = anatop_regmap_enable,
.disable = anatop_regmap_disable,
.is_enabled = anatop_regmap_is_enabled,
@@ -305,9 +305,13 @@
/* register regulator */
rdev = devm_regulator_register(dev, rdesc, &config);
if (IS_ERR(rdev)) {
- dev_err(dev, "failed to register %s\n",
- rdesc->name);
- return PTR_ERR(rdev);
+ ret = PTR_ERR(rdev);
+ if (ret == -EPROBE_DEFER)
+ dev_dbg(dev, "failed to register %s, deferring...\n",
+ rdesc->name);
+ else
+ dev_err(dev, "failed to register %s\n", rdesc->name);
+ return ret;
}
platform_set_drvdata(pdev, rdev);
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index 1a3d7b7..ade0bef 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -87,7 +87,7 @@
.set_bypass = regulator_set_bypass_regmap,
};
-static const struct regulator_linear_range arizona_ldo1_hc_ranges[] = {
+static const struct linear_range arizona_ldo1_hc_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 0x6, 50000),
REGULATOR_LINEAR_RANGE(1800000, 0x7, 0x7, 0),
};
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c
index ae1a5de..f6cfd3f 100644
--- a/drivers/regulator/arizona-micsupp.c
+++ b/drivers/regulator/arizona-micsupp.c
@@ -125,7 +125,7 @@
.set_bypass = arizona_micsupp_set_bypass,
};
-static const struct regulator_linear_range arizona_micsupp_ranges[] = {
+static const struct linear_range arizona_micsupp_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 0x1e, 50000),
REGULATOR_LINEAR_RANGE(3300000, 0x1f, 0x1f, 0),
};
@@ -152,7 +152,7 @@
.owner = THIS_MODULE,
};
-static const struct regulator_linear_range arizona_micsupp_ext_ranges[] = {
+static const struct linear_range arizona_micsupp_ext_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 0x14, 25000),
REGULATOR_LINEAR_RANGE(1500000, 0x15, 0x27, 100000),
};
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
index ece8810..b6b9206 100644
--- a/drivers/regulator/as3711-regulator.c
+++ b/drivers/regulator/as3711-regulator.c
@@ -103,18 +103,18 @@
.map_voltage = regulator_map_voltage_linear_range,
};
-static const struct regulator_linear_range as3711_sd_ranges[] = {
+static const struct linear_range as3711_sd_ranges[] = {
REGULATOR_LINEAR_RANGE(612500, 0x1, 0x40, 12500),
REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000),
REGULATOR_LINEAR_RANGE(2650000, 0x71, 0x7f, 50000),
};
-static const struct regulator_linear_range as3711_aldo_ranges[] = {
+static const struct linear_range as3711_aldo_ranges[] = {
REGULATOR_LINEAR_RANGE(1200000, 0, 0xf, 50000),
REGULATOR_LINEAR_RANGE(1800000, 0x10, 0x1f, 100000),
};
-static const struct regulator_linear_range as3711_dldo_ranges[] = {
+static const struct linear_range as3711_dldo_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 0x10, 50000),
REGULATOR_LINEAR_RANGE(1750000, 0x20, 0x3f, 50000),
};
diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c
index bd5d0ba..33ca197 100644
--- a/drivers/regulator/as3722-regulator.c
+++ b/drivers/regulator/as3722-regulator.c
@@ -389,7 +389,7 @@
.set_bypass = regulator_set_bypass_regmap,
};
-static const struct regulator_linear_range as3722_ldo_ranges[] = {
+static const struct linear_range as3722_ldo_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x00, 0x00, 0),
REGULATOR_LINEAR_RANGE(825000, 0x01, 0x24, 25000),
REGULATOR_LINEAR_RANGE(1725000, 0x40, 0x7F, 25000),
@@ -487,7 +487,7 @@
return false;
}
-static const struct regulator_linear_range as3722_sd2345_ranges[] = {
+static const struct linear_range as3722_sd2345_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x00, 0x00, 0),
REGULATOR_LINEAR_RANGE(612500, 0x01, 0x40, 12500),
REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000),
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 86a3c2d..d260c44 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -382,8 +382,7 @@
mask = AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_RATE_MASK |
AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN_MASK;
enable = (ramp > 0) ?
- AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN :
- !AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN;
+ AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN : 0;
break;
}
@@ -394,15 +393,14 @@
mask = AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE_MASK |
AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN_MASK;
enable = (ramp > 0) ?
- AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN :
- !AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN;
+ AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN : 0;
break;
}
if (rate_count > 0)
break;
- /* fall through */
+ fallthrough;
default:
/* Not supported for this regulator */
return -ENOTSUPP;
@@ -513,7 +511,7 @@
.is_enabled = regulator_is_enabled_regmap,
};
-static const struct regulator_linear_range axp20x_ldo4_ranges[] = {
+static const struct linear_range axp20x_ldo4_ranges[] = {
REGULATOR_LINEAR_RANGE(1250000,
AXP20X_LDO4_V_OUT_1250mV_START,
AXP20X_LDO4_V_OUT_1250mV_END,
@@ -641,7 +639,7 @@
};
/* DCDC ranges shared with AXP813 */
-static const struct regulator_linear_range axp803_dcdc234_ranges[] = {
+static const struct linear_range axp803_dcdc234_ranges[] = {
REGULATOR_LINEAR_RANGE(500000,
AXP803_DCDC234_500mV_START,
AXP803_DCDC234_500mV_END,
@@ -652,7 +650,7 @@
20000),
};
-static const struct regulator_linear_range axp803_dcdc5_ranges[] = {
+static const struct linear_range axp803_dcdc5_ranges[] = {
REGULATOR_LINEAR_RANGE(800000,
AXP803_DCDC5_800mV_START,
AXP803_DCDC5_800mV_END,
@@ -663,7 +661,7 @@
20000),
};
-static const struct regulator_linear_range axp803_dcdc6_ranges[] = {
+static const struct linear_range axp803_dcdc6_ranges[] = {
REGULATOR_LINEAR_RANGE(600000,
AXP803_DCDC6_600mV_START,
AXP803_DCDC6_600mV_END,
@@ -675,7 +673,7 @@
};
/* AXP806's CLDO2 and AXP809's DLDO1 share the same range */
-static const struct regulator_linear_range axp803_dldo2_ranges[] = {
+static const struct linear_range axp803_dldo2_ranges[] = {
REGULATOR_LINEAR_RANGE(700000,
AXP803_DLDO2_700mV_START,
AXP803_DLDO2_700mV_END,
@@ -761,7 +759,7 @@
AXP_DESC_FIXED(AXP803, RTC_LDO, "rtc-ldo", "ips", 3000),
};
-static const struct regulator_linear_range axp806_dcdca_ranges[] = {
+static const struct linear_range axp806_dcdca_ranges[] = {
REGULATOR_LINEAR_RANGE(600000,
AXP806_DCDCA_600mV_START,
AXP806_DCDCA_600mV_END,
@@ -772,7 +770,7 @@
20000),
};
-static const struct regulator_linear_range axp806_dcdcd_ranges[] = {
+static const struct linear_range axp806_dcdcd_ranges[] = {
REGULATOR_LINEAR_RANGE(600000,
AXP806_DCDCD_600mV_START,
AXP806_DCDCD_600mV_END,
@@ -837,7 +835,7 @@
AXP806_PWR_OUT_CTRL2, AXP806_PWR_OUT_SW_MASK),
};
-static const struct regulator_linear_range axp809_dcdc4_ranges[] = {
+static const struct linear_range axp809_dcdc4_ranges[] = {
REGULATOR_LINEAR_RANGE(600000,
AXP809_DCDC4_600mV_START,
AXP809_DCDC4_600mV_END,
@@ -1025,7 +1023,7 @@
* (See include/linux/mfd/axp20x.h)
*/
reg = AXP803_DCDC_FREQ_CTRL;
- /* Fall through - to the check below.*/
+ fallthrough; /* to the check below */
case AXP806_ID:
/*
* AXP806 also have DCDC work frequency setting register at a
@@ -1033,7 +1031,7 @@
*/
if (axp20x->variant == AXP806_ID)
reg = AXP806_DCDC_FREQ_CTRL;
- /* Fall through */
+ fallthrough;
case AXP221_ID:
case AXP223_ID:
case AXP809_ID:
@@ -1120,7 +1118,7 @@
* (See include/linux/mfd/axp20x.h)
*/
reg = AXP806_DCDC_MODE_CTRL2;
- /* Fall through - to the check below. */
+ fallthrough; /* to the check below */
case AXP221_ID:
case AXP223_ID:
case AXP809_ID:
diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index 8c98c3f..65e23fc 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -116,14 +116,14 @@
};
/* DCDC group CSR: supported voltages in microvolts */
-static const struct regulator_linear_range dcdc_csr_ranges[] = {
+static const struct linear_range dcdc_csr_ranges[] = {
REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
REGULATOR_LINEAR_RANGE(1360000, 51, 55, 20000),
REGULATOR_LINEAR_RANGE(900000, 56, 63, 0),
};
/* DCDC group IOSR1: supported voltages in microvolts */
-static const struct regulator_linear_range dcdc_iosr1_ranges[] = {
+static const struct linear_range dcdc_iosr1_ranges[] = {
REGULATOR_LINEAR_RANGE(860000, 2, 51, 10000),
REGULATOR_LINEAR_RANGE(1500000, 52, 52, 0),
REGULATOR_LINEAR_RANGE(1800000, 53, 53, 0),
@@ -131,7 +131,7 @@
};
/* DCDC group SDSR1: supported voltages in microvolts */
-static const struct regulator_linear_range dcdc_sdsr1_ranges[] = {
+static const struct linear_range dcdc_sdsr1_ranges[] = {
REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
REGULATOR_LINEAR_RANGE(1340000, 51, 51, 0),
REGULATOR_LINEAR_RANGE(900000, 52, 63, 0),
@@ -143,7 +143,7 @@
u8 n_voltages;
const unsigned int *volt_table;
u8 n_linear_ranges;
- const struct regulator_linear_range *linear_ranges;
+ const struct linear_range *linear_ranges;
};
#define BCM590XX_REG_TABLE(_name, _table) \
diff --git a/drivers/regulator/bd70528-regulator.c b/drivers/regulator/bd70528-regulator.c
index 5bf8a2d..d44adf7 100644
--- a/drivers/regulator/bd70528-regulator.c
+++ b/drivers/regulator/bd70528-regulator.c
@@ -20,22 +20,22 @@
#define BUCK_RAMPRATE_125MV 1
#define BUCK_RAMP_MAX 250
-static const struct regulator_linear_range bd70528_buck1_volts[] = {
+static const struct linear_range bd70528_buck1_volts[] = {
REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 600000),
REGULATOR_LINEAR_RANGE(2750000, 0x2, 0xf, 50000),
};
-static const struct regulator_linear_range bd70528_buck2_volts[] = {
+static const struct linear_range bd70528_buck2_volts[] = {
REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 300000),
REGULATOR_LINEAR_RANGE(1550000, 0x2, 0xd, 50000),
REGULATOR_LINEAR_RANGE(3000000, 0xe, 0xf, 300000),
};
-static const struct regulator_linear_range bd70528_buck3_volts[] = {
+static const struct linear_range bd70528_buck3_volts[] = {
REGULATOR_LINEAR_RANGE(800000, 0x00, 0xd, 50000),
REGULATOR_LINEAR_RANGE(1800000, 0xe, 0xf, 0),
};
/* All LDOs have same voltage ranges */
-static const struct regulator_linear_range bd70528_ldo_volts[] = {
+static const struct linear_range bd70528_ldo_volts[] = {
REGULATOR_LINEAR_RANGE(1650000, 0x0, 0x07, 50000),
REGULATOR_LINEAR_RANGE(2100000, 0x8, 0x0f, 100000),
REGULATOR_LINEAR_RANGE(2850000, 0x10, 0x19, 50000),
diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c
new file mode 100644
index 0000000..85c0b90
--- /dev/null
+++ b/drivers/regulator/bd71828-regulator.c
@@ -0,0 +1,807 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2019 ROHM Semiconductors
+// bd71828-regulator.c ROHM BD71828GW-DS1 regulator driver
+//
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/rohm-bd71828.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+struct reg_init {
+ unsigned int reg;
+ unsigned int mask;
+ unsigned int val;
+};
+struct bd71828_regulator_data {
+ struct regulator_desc desc;
+ const struct rohm_dvs_config dvs;
+ const struct reg_init *reg_inits;
+ int reg_init_amnt;
+};
+
+static const struct reg_init buck1_inits[] = {
+ /*
+ * DVS Buck voltages can be changed by register values or via GPIO.
+ * Use register accesses by default.
+ */
+ {
+ .reg = BD71828_REG_PS_CTRL_1,
+ .mask = BD71828_MASK_DVS_BUCK1_CTRL,
+ .val = BD71828_DVS_BUCK1_CTRL_I2C,
+ },
+};
+
+static const struct reg_init buck2_inits[] = {
+ {
+ .reg = BD71828_REG_PS_CTRL_1,
+ .mask = BD71828_MASK_DVS_BUCK2_CTRL,
+ .val = BD71828_DVS_BUCK2_CTRL_I2C,
+ },
+};
+
+static const struct reg_init buck6_inits[] = {
+ {
+ .reg = BD71828_REG_PS_CTRL_1,
+ .mask = BD71828_MASK_DVS_BUCK6_CTRL,
+ .val = BD71828_DVS_BUCK6_CTRL_I2C,
+ },
+};
+
+static const struct reg_init buck7_inits[] = {
+ {
+ .reg = BD71828_REG_PS_CTRL_1,
+ .mask = BD71828_MASK_DVS_BUCK7_CTRL,
+ .val = BD71828_DVS_BUCK7_CTRL_I2C,
+ },
+};
+
+static const struct linear_range bd71828_buck1267_volts[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0x00, 0xef, 6250),
+ REGULATOR_LINEAR_RANGE(2000000, 0xf0, 0xff, 0),
+};
+
+static const struct linear_range bd71828_buck3_volts[] = {
+ REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x0f, 50000),
+ REGULATOR_LINEAR_RANGE(2000000, 0x10, 0x1f, 0),
+};
+
+static const struct linear_range bd71828_buck4_volts[] = {
+ REGULATOR_LINEAR_RANGE(1000000, 0x00, 0x1f, 25000),
+ REGULATOR_LINEAR_RANGE(1800000, 0x20, 0x3f, 0),
+};
+
+static const struct linear_range bd71828_buck5_volts[] = {
+ REGULATOR_LINEAR_RANGE(2500000, 0x00, 0x0f, 50000),
+ REGULATOR_LINEAR_RANGE(3300000, 0x10, 0x1f, 0),
+};
+
+static const struct linear_range bd71828_ldo_volts[] = {
+ REGULATOR_LINEAR_RANGE(800000, 0x00, 0x31, 50000),
+ REGULATOR_LINEAR_RANGE(3300000, 0x32, 0x3f, 0),
+};
+
+static int bd71828_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+ unsigned int val;
+
+ switch (ramp_delay) {
+ case 1 ... 2500:
+ val = 0;
+ break;
+ case 2501 ... 5000:
+ val = 1;
+ break;
+ case 5001 ... 10000:
+ val = 2;
+ break;
+ case 10001 ... 20000:
+ val = 3;
+ break;
+ default:
+ val = 3;
+ dev_err(&rdev->dev,
+ "ramp_delay: %d not supported, setting 20mV/uS",
+ ramp_delay);
+ }
+
+ /*
+ * On BD71828 the ramp delay level control reg is at offset +2 to
+ * enable reg
+ */
+ return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg + 2,
+ BD71828_MASK_RAMP_DELAY,
+ val << (ffs(BD71828_MASK_RAMP_DELAY) - 1));
+}
+
+static int buck_set_hw_dvs_levels(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ struct bd71828_regulator_data *data;
+
+ data = container_of(desc, struct bd71828_regulator_data, desc);
+
+ return rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap);
+}
+
+static int ldo6_parse_dt(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ int ret, i;
+ uint32_t uv = 0;
+ unsigned int en;
+ struct regmap *regmap = cfg->regmap;
+ static const char * const props[] = { "rohm,dvs-run-voltage",
+ "rohm,dvs-idle-voltage",
+ "rohm,dvs-suspend-voltage",
+ "rohm,dvs-lpsr-voltage" };
+ unsigned int mask[] = { BD71828_MASK_RUN_EN, BD71828_MASK_IDLE_EN,
+ BD71828_MASK_SUSP_EN, BD71828_MASK_LPSR_EN };
+
+ for (i = 0; i < ARRAY_SIZE(props); i++) {
+ ret = of_property_read_u32(np, props[i], &uv);
+ if (ret) {
+ if (ret != -EINVAL)
+ return ret;
+ continue;
+ }
+ if (uv)
+ en = 0xffffffff;
+ else
+ en = 0;
+
+ ret = regmap_update_bits(regmap, desc->enable_reg, mask[i], en);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static const struct regulator_ops bd71828_buck_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,
+};
+
+static const struct regulator_ops bd71828_dvs_buck_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 = bd71828_set_ramp_delay,
+};
+
+static const struct regulator_ops bd71828_ldo_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,
+};
+
+static const struct regulator_ops bd71828_ldo6_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+static const struct bd71828_regulator_data bd71828_rdata[] = {
+ {
+ .desc = {
+ .name = "buck1",
+ .of_match = of_match_ptr("BUCK1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD71828_BUCK1,
+ .ops = &bd71828_dvs_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd71828_buck1267_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd71828_buck1267_volts),
+ .n_voltages = BD71828_BUCK1267_VOLTS,
+ .enable_reg = BD71828_REG_BUCK1_EN,
+ .enable_mask = BD71828_MASK_RUN_EN,
+ .vsel_reg = BD71828_REG_BUCK1_VOLT,
+ .vsel_mask = BD71828_MASK_BUCK1267_VOLT,
+ .owner = THIS_MODULE,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND |
+ ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71828_REG_BUCK1_VOLT,
+ .run_mask = BD71828_MASK_BUCK1267_VOLT,
+ .idle_reg = BD71828_REG_BUCK1_IDLE_VOLT,
+ .idle_mask = BD71828_MASK_BUCK1267_VOLT,
+ .idle_on_mask = BD71828_MASK_IDLE_EN,
+ .suspend_reg = BD71828_REG_BUCK1_SUSP_VOLT,
+ .suspend_mask = BD71828_MASK_BUCK1267_VOLT,
+ .suspend_on_mask = BD71828_MASK_SUSP_EN,
+ .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+ /*
+ * LPSR voltage is same as SUSPEND voltage. Allow
+ * setting it so that regulator can be set enabled at
+ * LPSR state
+ */
+ .lpsr_reg = BD71828_REG_BUCK1_SUSP_VOLT,
+ .lpsr_mask = BD71828_MASK_BUCK1267_VOLT,
+ },
+ .reg_inits = buck1_inits,
+ .reg_init_amnt = ARRAY_SIZE(buck1_inits),
+ },
+ {
+ .desc = {
+ .name = "buck2",
+ .of_match = of_match_ptr("BUCK2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD71828_BUCK2,
+ .ops = &bd71828_dvs_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd71828_buck1267_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd71828_buck1267_volts),
+ .n_voltages = BD71828_BUCK1267_VOLTS,
+ .enable_reg = BD71828_REG_BUCK2_EN,
+ .enable_mask = BD71828_MASK_RUN_EN,
+ .vsel_reg = BD71828_REG_BUCK2_VOLT,
+ .vsel_mask = BD71828_MASK_BUCK1267_VOLT,
+ .owner = THIS_MODULE,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND |
+ ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71828_REG_BUCK2_VOLT,
+ .run_mask = BD71828_MASK_BUCK1267_VOLT,
+ .idle_reg = BD71828_REG_BUCK2_IDLE_VOLT,
+ .idle_mask = BD71828_MASK_BUCK1267_VOLT,
+ .idle_on_mask = BD71828_MASK_IDLE_EN,
+ .suspend_reg = BD71828_REG_BUCK2_SUSP_VOLT,
+ .suspend_mask = BD71828_MASK_BUCK1267_VOLT,
+ .suspend_on_mask = BD71828_MASK_SUSP_EN,
+ .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+ .lpsr_reg = BD71828_REG_BUCK2_SUSP_VOLT,
+ .lpsr_mask = BD71828_MASK_BUCK1267_VOLT,
+ },
+ .reg_inits = buck2_inits,
+ .reg_init_amnt = ARRAY_SIZE(buck2_inits),
+ },
+ {
+ .desc = {
+ .name = "buck3",
+ .of_match = of_match_ptr("BUCK3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD71828_BUCK3,
+ .ops = &bd71828_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd71828_buck3_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd71828_buck3_volts),
+ .n_voltages = BD71828_BUCK3_VOLTS,
+ .enable_reg = BD71828_REG_BUCK3_EN,
+ .enable_mask = BD71828_MASK_RUN_EN,
+ .vsel_reg = BD71828_REG_BUCK3_VOLT,
+ .vsel_mask = BD71828_MASK_BUCK3_VOLT,
+ .owner = THIS_MODULE,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ /*
+ * BUCK3 only supports single voltage for all states.
+ * voltage can be individually enabled for each state
+ * though => allow setting all states to support
+ * enabling power rail on different states.
+ */
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND |
+ ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71828_REG_BUCK3_VOLT,
+ .idle_reg = BD71828_REG_BUCK3_VOLT,
+ .suspend_reg = BD71828_REG_BUCK3_VOLT,
+ .lpsr_reg = BD71828_REG_BUCK3_VOLT,
+ .run_mask = BD71828_MASK_BUCK3_VOLT,
+ .idle_mask = BD71828_MASK_BUCK3_VOLT,
+ .suspend_mask = BD71828_MASK_BUCK3_VOLT,
+ .lpsr_mask = BD71828_MASK_BUCK3_VOLT,
+ .idle_on_mask = BD71828_MASK_IDLE_EN,
+ .suspend_on_mask = BD71828_MASK_SUSP_EN,
+ .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+ },
+ },
+ {
+ .desc = {
+ .name = "buck4",
+ .of_match = of_match_ptr("BUCK4"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD71828_BUCK4,
+ .ops = &bd71828_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd71828_buck4_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd71828_buck4_volts),
+ .n_voltages = BD71828_BUCK4_VOLTS,
+ .enable_reg = BD71828_REG_BUCK4_EN,
+ .enable_mask = BD71828_MASK_RUN_EN,
+ .vsel_reg = BD71828_REG_BUCK4_VOLT,
+ .vsel_mask = BD71828_MASK_BUCK4_VOLT,
+ .owner = THIS_MODULE,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ /*
+ * BUCK4 only supports single voltage for all states.
+ * voltage can be individually enabled for each state
+ * though => allow setting all states to support
+ * enabling power rail on different states.
+ */
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND |
+ ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71828_REG_BUCK4_VOLT,
+ .idle_reg = BD71828_REG_BUCK4_VOLT,
+ .suspend_reg = BD71828_REG_BUCK4_VOLT,
+ .lpsr_reg = BD71828_REG_BUCK4_VOLT,
+ .run_mask = BD71828_MASK_BUCK4_VOLT,
+ .idle_mask = BD71828_MASK_BUCK4_VOLT,
+ .suspend_mask = BD71828_MASK_BUCK4_VOLT,
+ .lpsr_mask = BD71828_MASK_BUCK4_VOLT,
+ .idle_on_mask = BD71828_MASK_IDLE_EN,
+ .suspend_on_mask = BD71828_MASK_SUSP_EN,
+ .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+ },
+ },
+ {
+ .desc = {
+ .name = "buck5",
+ .of_match = of_match_ptr("BUCK5"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD71828_BUCK5,
+ .ops = &bd71828_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd71828_buck5_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd71828_buck5_volts),
+ .n_voltages = BD71828_BUCK5_VOLTS,
+ .enable_reg = BD71828_REG_BUCK5_EN,
+ .enable_mask = BD71828_MASK_RUN_EN,
+ .vsel_reg = BD71828_REG_BUCK5_VOLT,
+ .vsel_mask = BD71828_MASK_BUCK5_VOLT,
+ .owner = THIS_MODULE,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ /*
+ * BUCK5 only supports single voltage for all states.
+ * voltage can be individually enabled for each state
+ * though => allow setting all states to support
+ * enabling power rail on different states.
+ */
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND |
+ ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71828_REG_BUCK5_VOLT,
+ .idle_reg = BD71828_REG_BUCK5_VOLT,
+ .suspend_reg = BD71828_REG_BUCK5_VOLT,
+ .lpsr_reg = BD71828_REG_BUCK5_VOLT,
+ .run_mask = BD71828_MASK_BUCK5_VOLT,
+ .idle_mask = BD71828_MASK_BUCK5_VOLT,
+ .suspend_mask = BD71828_MASK_BUCK5_VOLT,
+ .lpsr_mask = BD71828_MASK_BUCK5_VOLT,
+ .idle_on_mask = BD71828_MASK_IDLE_EN,
+ .suspend_on_mask = BD71828_MASK_SUSP_EN,
+ .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+ },
+ },
+ {
+ .desc = {
+ .name = "buck6",
+ .of_match = of_match_ptr("BUCK6"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD71828_BUCK6,
+ .ops = &bd71828_dvs_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd71828_buck1267_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd71828_buck1267_volts),
+ .n_voltages = BD71828_BUCK1267_VOLTS,
+ .enable_reg = BD71828_REG_BUCK6_EN,
+ .enable_mask = BD71828_MASK_RUN_EN,
+ .vsel_reg = BD71828_REG_BUCK6_VOLT,
+ .vsel_mask = BD71828_MASK_BUCK1267_VOLT,
+ .owner = THIS_MODULE,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND |
+ ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71828_REG_BUCK6_VOLT,
+ .run_mask = BD71828_MASK_BUCK1267_VOLT,
+ .idle_reg = BD71828_REG_BUCK6_IDLE_VOLT,
+ .idle_mask = BD71828_MASK_BUCK1267_VOLT,
+ .idle_on_mask = BD71828_MASK_IDLE_EN,
+ .suspend_reg = BD71828_REG_BUCK6_SUSP_VOLT,
+ .suspend_mask = BD71828_MASK_BUCK1267_VOLT,
+ .suspend_on_mask = BD71828_MASK_SUSP_EN,
+ .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+ .lpsr_reg = BD71828_REG_BUCK6_SUSP_VOLT,
+ .lpsr_mask = BD71828_MASK_BUCK1267_VOLT,
+ },
+ .reg_inits = buck6_inits,
+ .reg_init_amnt = ARRAY_SIZE(buck6_inits),
+ },
+ {
+ .desc = {
+ .name = "buck7",
+ .of_match = of_match_ptr("BUCK7"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD71828_BUCK7,
+ .ops = &bd71828_dvs_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd71828_buck1267_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd71828_buck1267_volts),
+ .n_voltages = BD71828_BUCK1267_VOLTS,
+ .enable_reg = BD71828_REG_BUCK7_EN,
+ .enable_mask = BD71828_MASK_RUN_EN,
+ .vsel_reg = BD71828_REG_BUCK7_VOLT,
+ .vsel_mask = BD71828_MASK_BUCK1267_VOLT,
+ .owner = THIS_MODULE,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND |
+ ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71828_REG_BUCK7_VOLT,
+ .run_mask = BD71828_MASK_BUCK1267_VOLT,
+ .idle_reg = BD71828_REG_BUCK7_IDLE_VOLT,
+ .idle_mask = BD71828_MASK_BUCK1267_VOLT,
+ .idle_on_mask = BD71828_MASK_IDLE_EN,
+ .suspend_reg = BD71828_REG_BUCK7_SUSP_VOLT,
+ .suspend_mask = BD71828_MASK_BUCK1267_VOLT,
+ .suspend_on_mask = BD71828_MASK_SUSP_EN,
+ .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+ .lpsr_reg = BD71828_REG_BUCK7_SUSP_VOLT,
+ .lpsr_mask = BD71828_MASK_BUCK1267_VOLT,
+ },
+ .reg_inits = buck7_inits,
+ .reg_init_amnt = ARRAY_SIZE(buck7_inits),
+ },
+ {
+ .desc = {
+ .name = "ldo1",
+ .of_match = of_match_ptr("LDO1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD71828_LDO1,
+ .ops = &bd71828_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd71828_ldo_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts),
+ .n_voltages = BD71828_LDO_VOLTS,
+ .enable_reg = BD71828_REG_LDO1_EN,
+ .enable_mask = BD71828_MASK_RUN_EN,
+ .vsel_reg = BD71828_REG_LDO1_VOLT,
+ .vsel_mask = BD71828_MASK_LDO_VOLT,
+ .owner = THIS_MODULE,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ /*
+ * LDO1 only supports single voltage for all states.
+ * voltage can be individually enabled for each state
+ * though => allow setting all states to support
+ * enabling power rail on different states.
+ */
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND |
+ ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71828_REG_LDO1_VOLT,
+ .idle_reg = BD71828_REG_LDO1_VOLT,
+ .suspend_reg = BD71828_REG_LDO1_VOLT,
+ .lpsr_reg = BD71828_REG_LDO1_VOLT,
+ .run_mask = BD71828_MASK_LDO_VOLT,
+ .idle_mask = BD71828_MASK_LDO_VOLT,
+ .suspend_mask = BD71828_MASK_LDO_VOLT,
+ .lpsr_mask = BD71828_MASK_LDO_VOLT,
+ .idle_on_mask = BD71828_MASK_IDLE_EN,
+ .suspend_on_mask = BD71828_MASK_SUSP_EN,
+ .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+ },
+ }, {
+ .desc = {
+ .name = "ldo2",
+ .of_match = of_match_ptr("LDO2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD71828_LDO2,
+ .ops = &bd71828_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd71828_ldo_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts),
+ .n_voltages = BD71828_LDO_VOLTS,
+ .enable_reg = BD71828_REG_LDO2_EN,
+ .enable_mask = BD71828_MASK_RUN_EN,
+ .vsel_reg = BD71828_REG_LDO2_VOLT,
+ .vsel_mask = BD71828_MASK_LDO_VOLT,
+ .owner = THIS_MODULE,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ /*
+ * LDO2 only supports single voltage for all states.
+ * voltage can be individually enabled for each state
+ * though => allow setting all states to support
+ * enabling power rail on different states.
+ */
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND |
+ ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71828_REG_LDO2_VOLT,
+ .idle_reg = BD71828_REG_LDO2_VOLT,
+ .suspend_reg = BD71828_REG_LDO2_VOLT,
+ .lpsr_reg = BD71828_REG_LDO2_VOLT,
+ .run_mask = BD71828_MASK_LDO_VOLT,
+ .idle_mask = BD71828_MASK_LDO_VOLT,
+ .suspend_mask = BD71828_MASK_LDO_VOLT,
+ .lpsr_mask = BD71828_MASK_LDO_VOLT,
+ .idle_on_mask = BD71828_MASK_IDLE_EN,
+ .suspend_on_mask = BD71828_MASK_SUSP_EN,
+ .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+ },
+ }, {
+ .desc = {
+ .name = "ldo3",
+ .of_match = of_match_ptr("LDO3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD71828_LDO3,
+ .ops = &bd71828_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd71828_ldo_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts),
+ .n_voltages = BD71828_LDO_VOLTS,
+ .enable_reg = BD71828_REG_LDO3_EN,
+ .enable_mask = BD71828_MASK_RUN_EN,
+ .vsel_reg = BD71828_REG_LDO3_VOLT,
+ .vsel_mask = BD71828_MASK_LDO_VOLT,
+ .owner = THIS_MODULE,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ /*
+ * LDO3 only supports single voltage for all states.
+ * voltage can be individually enabled for each state
+ * though => allow setting all states to support
+ * enabling power rail on different states.
+ */
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND |
+ ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71828_REG_LDO3_VOLT,
+ .idle_reg = BD71828_REG_LDO3_VOLT,
+ .suspend_reg = BD71828_REG_LDO3_VOLT,
+ .lpsr_reg = BD71828_REG_LDO3_VOLT,
+ .run_mask = BD71828_MASK_LDO_VOLT,
+ .idle_mask = BD71828_MASK_LDO_VOLT,
+ .suspend_mask = BD71828_MASK_LDO_VOLT,
+ .lpsr_mask = BD71828_MASK_LDO_VOLT,
+ .idle_on_mask = BD71828_MASK_IDLE_EN,
+ .suspend_on_mask = BD71828_MASK_SUSP_EN,
+ .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+ },
+
+ }, {
+ .desc = {
+ .name = "ldo4",
+ .of_match = of_match_ptr("LDO4"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD71828_LDO4,
+ .ops = &bd71828_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd71828_ldo_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts),
+ .n_voltages = BD71828_LDO_VOLTS,
+ .enable_reg = BD71828_REG_LDO4_EN,
+ .enable_mask = BD71828_MASK_RUN_EN,
+ .vsel_reg = BD71828_REG_LDO4_VOLT,
+ .vsel_mask = BD71828_MASK_LDO_VOLT,
+ .owner = THIS_MODULE,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ /*
+ * LDO1 only supports single voltage for all states.
+ * voltage can be individually enabled for each state
+ * though => allow setting all states to support
+ * enabling power rail on different states.
+ */
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND |
+ ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71828_REG_LDO4_VOLT,
+ .idle_reg = BD71828_REG_LDO4_VOLT,
+ .suspend_reg = BD71828_REG_LDO4_VOLT,
+ .lpsr_reg = BD71828_REG_LDO4_VOLT,
+ .run_mask = BD71828_MASK_LDO_VOLT,
+ .idle_mask = BD71828_MASK_LDO_VOLT,
+ .suspend_mask = BD71828_MASK_LDO_VOLT,
+ .lpsr_mask = BD71828_MASK_LDO_VOLT,
+ .idle_on_mask = BD71828_MASK_IDLE_EN,
+ .suspend_on_mask = BD71828_MASK_SUSP_EN,
+ .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+ },
+ }, {
+ .desc = {
+ .name = "ldo5",
+ .of_match = of_match_ptr("LDO5"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD71828_LDO5,
+ .ops = &bd71828_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd71828_ldo_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts),
+ .n_voltages = BD71828_LDO_VOLTS,
+ .enable_reg = BD71828_REG_LDO5_EN,
+ .enable_mask = BD71828_MASK_RUN_EN,
+ .vsel_reg = BD71828_REG_LDO5_VOLT,
+ .vsel_mask = BD71828_MASK_LDO_VOLT,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ .owner = THIS_MODULE,
+ },
+ /*
+ * LDO5 is special. It can choose vsel settings to be configured
+ * from 2 different registers (by GPIO).
+ *
+ * This driver supports only configuration where
+ * BD71828_REG_LDO5_VOLT_L is used.
+ */
+ .dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND |
+ ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71828_REG_LDO5_VOLT,
+ .idle_reg = BD71828_REG_LDO5_VOLT,
+ .suspend_reg = BD71828_REG_LDO5_VOLT,
+ .lpsr_reg = BD71828_REG_LDO5_VOLT,
+ .run_mask = BD71828_MASK_LDO_VOLT,
+ .idle_mask = BD71828_MASK_LDO_VOLT,
+ .suspend_mask = BD71828_MASK_LDO_VOLT,
+ .lpsr_mask = BD71828_MASK_LDO_VOLT,
+ .idle_on_mask = BD71828_MASK_IDLE_EN,
+ .suspend_on_mask = BD71828_MASK_SUSP_EN,
+ .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+ },
+
+ }, {
+ .desc = {
+ .name = "ldo6",
+ .of_match = of_match_ptr("LDO6"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD71828_LDO6,
+ .ops = &bd71828_ldo6_ops,
+ .type = REGULATOR_VOLTAGE,
+ .fixed_uV = BD71828_LDO_6_VOLTAGE,
+ .n_voltages = 1,
+ .enable_reg = BD71828_REG_LDO6_EN,
+ .enable_mask = BD71828_MASK_RUN_EN,
+ .owner = THIS_MODULE,
+ /*
+ * LDO6 only supports enable/disable for all states.
+ * Voltage for LDO6 is fixed.
+ */
+ .of_parse_cb = ldo6_parse_dt,
+ },
+ }, {
+ .desc = {
+ /* SNVS LDO in data-sheet */
+ .name = "ldo7",
+ .of_match = of_match_ptr("LDO7"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD71828_LDO_SNVS,
+ .ops = &bd71828_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd71828_ldo_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts),
+ .n_voltages = BD71828_LDO_VOLTS,
+ .enable_reg = BD71828_REG_LDO7_EN,
+ .enable_mask = BD71828_MASK_RUN_EN,
+ .vsel_reg = BD71828_REG_LDO7_VOLT,
+ .vsel_mask = BD71828_MASK_LDO_VOLT,
+ .owner = THIS_MODULE,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ /*
+ * LDO7 only supports single voltage for all states.
+ * voltage can be individually enabled for each state
+ * though => allow setting all states to support
+ * enabling power rail on different states.
+ */
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND |
+ ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71828_REG_LDO7_VOLT,
+ .idle_reg = BD71828_REG_LDO7_VOLT,
+ .suspend_reg = BD71828_REG_LDO7_VOLT,
+ .lpsr_reg = BD71828_REG_LDO7_VOLT,
+ .run_mask = BD71828_MASK_LDO_VOLT,
+ .idle_mask = BD71828_MASK_LDO_VOLT,
+ .suspend_mask = BD71828_MASK_LDO_VOLT,
+ .lpsr_mask = BD71828_MASK_LDO_VOLT,
+ .idle_on_mask = BD71828_MASK_IDLE_EN,
+ .suspend_on_mask = BD71828_MASK_SUSP_EN,
+ .lpsr_on_mask = BD71828_MASK_LPSR_EN,
+ },
+
+ },
+};
+
+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;
+
+ for (i = 0; i < ARRAY_SIZE(bd71828_rdata); i++) {
+ struct regulator_dev *rdev;
+ const struct bd71828_regulator_data *rd;
+
+ rd = &bd71828_rdata[i];
+ rdev = devm_regulator_register(&pdev->dev,
+ &rd->desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev,
+ "failed to register %s regulator\n",
+ rd->desc.name);
+ return PTR_ERR(rdev);
+ }
+ for (j = 0; j < rd->reg_init_amnt; j++) {
+ ret = regmap_update_bits(bd71828->regmap,
+ rd->reg_inits[j].reg,
+ rd->reg_inits[j].mask,
+ rd->reg_inits[j].val);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "regulator %s init failed\n",
+ rd->desc.name);
+ return ret;
+ }
+ }
+ }
+ return 0;
+}
+
+static struct platform_driver bd71828_regulator = {
+ .driver = {
+ .name = "bd71828-pmic"
+ },
+ .probe = bd71828_probe,
+};
+
+module_platform_driver(bd71828_regulator);
+
+MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
+MODULE_DESCRIPTION("BD71828 voltage regulator driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bd71828-pmic");
diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c
index 6c43145..2c097ee 100644
--- a/drivers/regulator/bd718x7-regulator.c
+++ b/drivers/regulator/bd718x7-regulator.c
@@ -46,6 +46,39 @@
#define BD71837_LDO7_STARTUP_TIME 530
/*
+ * BD718(37/47/50) have two "enable control modes". ON/OFF can either be
+ * controlled by software - or by PMIC internal HW state machine. Whether
+ * regulator should be under SW or HW control can be defined from device-tree.
+ * Let's provide separate ops for regulators to use depending on the "enable
+ * control mode".
+ */
+#define BD718XX_HWOPNAME(swopname) swopname##_hwcontrol
+
+#define BD718XX_OPS(name, _list_voltage, _map_voltage, _set_voltage_sel, \
+ _get_voltage_sel, _set_voltage_time_sel, _set_ramp_delay) \
+static const struct regulator_ops name = { \
+ .enable = regulator_enable_regmap, \
+ .disable = regulator_disable_regmap, \
+ .is_enabled = regulator_is_enabled_regmap, \
+ .list_voltage = (_list_voltage), \
+ .map_voltage = (_map_voltage), \
+ .set_voltage_sel = (_set_voltage_sel), \
+ .get_voltage_sel = (_get_voltage_sel), \
+ .set_voltage_time_sel = (_set_voltage_time_sel), \
+ .set_ramp_delay = (_set_ramp_delay), \
+}; \
+ \
+static const struct regulator_ops BD718XX_HWOPNAME(name) = { \
+ .is_enabled = always_enabled_by_hwstate, \
+ .list_voltage = (_list_voltage), \
+ .map_voltage = (_map_voltage), \
+ .set_voltage_sel = (_set_voltage_sel), \
+ .get_voltage_sel = (_get_voltage_sel), \
+ .set_voltage_time_sel = (_set_voltage_time_sel), \
+ .set_ramp_delay = (_set_ramp_delay), \
+} \
+
+/*
* BUCK1/2/3/4
* BUCK1RAMPRATE[1:0] BUCK1 DVS ramp rate setting
* 00: 10.00mV/usec 10mV 1uS
@@ -85,91 +118,262 @@
BUCK_RAMPRATE_MASK, ramp_value << 6);
}
-/* Bucks 1 to 4 support DVS. PWM mode is used when voltage is changed.
+/* These functions are used when regulators are under HW state machine control.
+ * We assume PMIC is in RUN state because SW running and able to query the
+ * status. Most of the regulators have fixed ON or OFF state at RUN/IDLE so for
+ * them we just return a constant. BD71837 BUCK3 and BUCK4 are exceptions as
+ * they support configuring the ON/OFF state for RUN.
+ *
+ * Note for next hacker - these PMICs have a register where the HW state can be
+ * read. If assuming RUN appears to be false in your use-case - you can
+ * implement state reading (although that is not going to be atomic) before
+ * returning the enable state.
+ */
+static int always_enabled_by_hwstate(struct regulator_dev *rdev)
+{
+ return 1;
+}
+
+static int never_enabled_by_hwstate(struct regulator_dev *rdev)
+{
+ return 0;
+}
+
+static int bd71837_get_buck34_enable_hwctrl(struct regulator_dev *rdev)
+{
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
+ if (ret)
+ return ret;
+
+ return !!(BD718XX_BUCK_RUN_ON & val);
+}
+/*
+ * On BD71837 (not on BD71847, BD71850, ...)
+ * 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.
+ *
+ * On BD71847, BD71850, ... The LDO voltage can be changed when LDO is
+ * enabled. But if voltage is increased the LDO power-good monitoring
+ * must be disabled for the duration of changing + 1mS to ensure voltage
+ * has reached the higher level before HW does next under voltage detection
+ * cycle.
*/
-static int bd718xx_set_voltage_sel_restricted(struct regulator_dev *rdev,
+static int bd71837_set_voltage_sel_restricted(struct regulator_dev *rdev,
unsigned int sel)
{
- if (regulator_is_enabled_regmap(rdev))
+ if (rdev->desc->ops->is_enabled(rdev))
return -EBUSY;
return regulator_set_voltage_sel_regmap(rdev, sel);
}
+static void voltage_change_done(struct regulator_dev *rdev, unsigned int sel,
+ unsigned int *mask)
+{
+ int ret;
+
+ if (*mask) {
+ /*
+ * Let's allow scheduling as we use I2C anyways. We just need to
+ * guarantee minimum of 1ms sleep - it shouldn't matter if we
+ * exceed it due to the scheduling.
+ */
+ msleep(1);
+ /*
+ * Note for next hacker. The PWRGOOD should not be masked on
+ * BD71847 so we will just unconditionally enable detection
+ * when voltage is set.
+ * If someone want's to disable PWRGOOD he must implement
+ * caching and restoring the old value here. I am not
+ * aware of such use-cases so for the sake of the simplicity
+ * we just always enable PWRGOOD here.
+ */
+ ret = regmap_update_bits(rdev->regmap, BD718XX_REG_MVRFLTMASK2,
+ *mask, 0);
+ if (ret)
+ dev_err(&rdev->dev,
+ "Failed to re-enable voltage monitoring (%d)\n",
+ ret);
+ }
+}
+
+static int voltage_change_prepare(struct regulator_dev *rdev, unsigned int sel,
+ unsigned int *mask)
+{
+ int ret;
+
+ *mask = 0;
+ if (rdev->desc->ops->is_enabled(rdev)) {
+ int now, new;
+
+ now = rdev->desc->ops->get_voltage_sel(rdev);
+ if (now < 0)
+ return now;
+
+ now = rdev->desc->ops->list_voltage(rdev, now);
+ if (now < 0)
+ return now;
+
+ new = rdev->desc->ops->list_voltage(rdev, sel);
+ if (new < 0)
+ return new;
+
+ /*
+ * If we increase LDO voltage when LDO is enabled we need to
+ * disable the power-good detection until voltage has reached
+ * the new level. According to HW colleagues the maximum time
+ * it takes is 1000us. I assume that on systems with light load
+ * this might be less - and we could probably use DT to give
+ * system specific delay value if performance matters.
+ *
+ * Well, knowing we use I2C here and can add scheduling delays
+ * I don't think it is worth the hassle and I just add fixed
+ * 1ms sleep here (and allow scheduling). If this turns out to
+ * be a problem we can change it to delay and make the delay
+ * time configurable.
+ */
+ if (new > now) {
+ int ldo_offset = rdev->desc->id - BD718XX_LDO1;
+
+ *mask = BD718XX_LDO1_VRMON80 << ldo_offset;
+ ret = regmap_update_bits(rdev->regmap,
+ BD718XX_REG_MVRFLTMASK2,
+ *mask, *mask);
+ if (ret) {
+ dev_err(&rdev->dev,
+ "Failed to stop voltage monitoring\n");
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int bd718xx_set_voltage_sel_restricted(struct regulator_dev *rdev,
+ unsigned int sel)
+{
+ int ret;
+ int mask;
+
+ ret = voltage_change_prepare(rdev, sel, &mask);
+ if (ret)
+ return ret;
+
+ ret = regulator_set_voltage_sel_regmap(rdev, sel);
+ voltage_change_done(rdev, sel, &mask);
+
+ return ret;
+}
+
static int bd718xx_set_voltage_sel_pickable_restricted(
struct regulator_dev *rdev, unsigned int sel)
{
- if (regulator_is_enabled_regmap(rdev))
+ int ret;
+ int mask;
+
+ ret = voltage_change_prepare(rdev, sel, &mask);
+ if (ret)
+ return ret;
+
+ ret = regulator_set_voltage_sel_pickable_regmap(rdev, sel);
+ voltage_change_done(rdev, sel, &mask);
+
+ return ret;
+}
+
+static int bd71837_set_voltage_sel_pickable_restricted(
+ struct regulator_dev *rdev, unsigned int sel)
+{
+ if (rdev->desc->ops->is_enabled(rdev))
return -EBUSY;
return regulator_set_voltage_sel_pickable_regmap(rdev, sel);
}
-static const struct regulator_ops bd718xx_pickable_range_ldo_ops = {
- .enable = regulator_enable_regmap,
- .disable = regulator_disable_regmap,
- .is_enabled = regulator_is_enabled_regmap,
+/*
+ * OPS common for BD71847 and BD71850
+ */
+BD718XX_OPS(bd718xx_pickable_range_ldo_ops,
+ regulator_list_voltage_pickable_linear_range, NULL,
+ bd718xx_set_voltage_sel_pickable_restricted,
+ regulator_get_voltage_sel_pickable_regmap, NULL, NULL);
+
+/* BD71847 and BD71850 LDO 5 is by default OFF at RUN state */
+static const struct regulator_ops bd718xx_ldo5_ops_hwstate = {
+ .is_enabled = never_enabled_by_hwstate,
.list_voltage = regulator_list_voltage_pickable_linear_range,
.set_voltage_sel = bd718xx_set_voltage_sel_pickable_restricted,
.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
};
-static const struct regulator_ops bd718xx_pickable_range_buck_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 = bd718xx_set_voltage_sel_pickable_restricted,
- .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
- .set_voltage_time_sel = regulator_set_voltage_time_sel,
-};
+BD718XX_OPS(bd718xx_pickable_range_buck_ops,
+ regulator_list_voltage_pickable_linear_range, NULL,
+ regulator_set_voltage_sel_pickable_regmap,
+ regulator_get_voltage_sel_pickable_regmap,
+ regulator_set_voltage_time_sel, NULL);
-static const struct regulator_ops bd718xx_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 = bd718xx_set_voltage_sel_restricted,
- .get_voltage_sel = regulator_get_voltage_sel_regmap,
-};
+BD718XX_OPS(bd718xx_ldo_regulator_ops, regulator_list_voltage_linear_range,
+ NULL, bd718xx_set_voltage_sel_restricted,
+ regulator_get_voltage_sel_regmap, NULL, NULL);
-static const struct regulator_ops bd718xx_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 = bd718xx_set_voltage_sel_restricted,
- .get_voltage_sel = regulator_get_voltage_sel_regmap,
-};
+BD718XX_OPS(bd718xx_ldo_regulator_nolinear_ops, regulator_list_voltage_table,
+ NULL, bd718xx_set_voltage_sel_restricted,
+ regulator_get_voltage_sel_regmap, NULL, NULL);
-static const struct regulator_ops bd718xx_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 = bd718xx_set_voltage_sel_restricted,
- .get_voltage_sel = regulator_get_voltage_sel_regmap,
- .set_voltage_time_sel = regulator_set_voltage_time_sel,
-};
+BD718XX_OPS(bd718xx_buck_regulator_ops, regulator_list_voltage_linear_range,
+ NULL, regulator_set_voltage_sel_regmap,
+ regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
+ NULL);
-static const struct regulator_ops bd718xx_buck_regulator_nolinear_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 = bd718xx_set_voltage_sel_restricted,
- .get_voltage_sel = regulator_get_voltage_sel_regmap,
- .set_voltage_time_sel = regulator_set_voltage_time_sel,
-};
+BD718XX_OPS(bd718xx_buck_regulator_nolinear_ops, regulator_list_voltage_table,
+ regulator_map_voltage_ascend, regulator_set_voltage_sel_regmap,
+ regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
+ NULL);
-static const struct regulator_ops bd718xx_dvs_buck_regulator_ops = {
- .enable = regulator_enable_regmap,
- .disable = regulator_disable_regmap,
- .is_enabled = regulator_is_enabled_regmap,
+/*
+ * OPS for BD71837
+ */
+BD718XX_OPS(bd71837_pickable_range_ldo_ops,
+ regulator_list_voltage_pickable_linear_range, NULL,
+ bd71837_set_voltage_sel_pickable_restricted,
+ regulator_get_voltage_sel_pickable_regmap, NULL, NULL);
+
+BD718XX_OPS(bd71837_pickable_range_buck_ops,
+ regulator_list_voltage_pickable_linear_range, NULL,
+ bd71837_set_voltage_sel_pickable_restricted,
+ regulator_get_voltage_sel_pickable_regmap,
+ regulator_set_voltage_time_sel, NULL);
+
+BD718XX_OPS(bd71837_ldo_regulator_ops, regulator_list_voltage_linear_range,
+ NULL, bd71837_set_voltage_sel_restricted,
+ regulator_get_voltage_sel_regmap, NULL, NULL);
+
+BD718XX_OPS(bd71837_ldo_regulator_nolinear_ops, regulator_list_voltage_table,
+ NULL, bd71837_set_voltage_sel_restricted,
+ regulator_get_voltage_sel_regmap, NULL, NULL);
+
+BD718XX_OPS(bd71837_buck_regulator_ops, regulator_list_voltage_linear_range,
+ NULL, bd71837_set_voltage_sel_restricted,
+ regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
+ NULL);
+
+BD718XX_OPS(bd71837_buck_regulator_nolinear_ops, regulator_list_voltage_table,
+ regulator_map_voltage_ascend, bd71837_set_voltage_sel_restricted,
+ regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
+ NULL);
+/*
+ * BD71837 bucks 3 and 4 support defining their enable/disable state also
+ * when buck enable state is under HW state machine control. In that case the
+ * bit [2] in CTRL register is used to indicate if regulator should be ON.
+ */
+static const struct regulator_ops bd71837_buck34_ops_hwctrl = {
+ .is_enabled = bd71837_get_buck34_enable_hwctrl,
.list_voltage = regulator_list_voltage_linear_range,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -178,11 +382,19 @@
};
/*
+ * OPS for all of the ICs - BD718(37/47/50)
+ */
+BD718XX_OPS(bd718xx_dvs_buck_regulator_ops, regulator_list_voltage_linear_range,
+ NULL, regulator_set_voltage_sel_regmap,
+ regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
+ bd718xx_buck1234_set_ramp_delay);
+
+/*
* BD71837 BUCK1/2/3/4
* BD71847 BUCK1/2
* 0.70 to 1.30V (10mV step)
*/
-static const struct regulator_linear_range bd718xx_dvs_buck_volts[] = {
+static const struct linear_range bd718xx_dvs_buck_volts[] = {
REGULATOR_LINEAR_RANGE(700000, 0x00, 0x3C, 10000),
REGULATOR_LINEAR_RANGE(1300000, 0x3D, 0x3F, 0),
};
@@ -193,7 +405,7 @@
* and
* 0.675 to 1.325 (range 1)
*/
-static const struct regulator_linear_range bd71837_buck5_volts[] = {
+static const struct linear_range bd71837_buck5_volts[] = {
/* Ranges when VOLT_SEL bit is 0 */
REGULATOR_LINEAR_RANGE(700000, 0x00, 0x03, 100000),
REGULATOR_LINEAR_RANGE(1050000, 0x04, 0x05, 50000),
@@ -215,7 +427,7 @@
/*
* BD71847 BUCK3
*/
-static const struct regulator_linear_range bd71847_buck3_volts[] = {
+static const struct linear_range bd71847_buck3_volts[] = {
/* Ranges when VOLT_SEL bits are 00 */
REGULATOR_LINEAR_RANGE(700000, 0x00, 0x03, 100000),
REGULATOR_LINEAR_RANGE(1050000, 0x04, 0x05, 50000),
@@ -232,7 +444,7 @@
0x0, 0x0, 0x0, 0x40, 0x80, 0x80, 0x80
};
-static const struct regulator_linear_range bd71847_buck4_volts[] = {
+static const struct linear_range bd71847_buck4_volts[] = {
REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000),
REGULATOR_LINEAR_RANGE(2600000, 0x00, 0x03, 100000),
};
@@ -243,7 +455,7 @@
* BUCK6
* 3.0V to 3.3V (step 100mV)
*/
-static const struct regulator_linear_range bd71837_buck6_volts[] = {
+static const struct linear_range bd71837_buck6_volts[] = {
REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000),
};
@@ -267,7 +479,7 @@
* BUCK8
* 0.8V to 1.40V (step 10mV)
*/
-static const struct regulator_linear_range bd718xx_4th_nodvs_buck_volts[] = {
+static const struct linear_range bd718xx_4th_nodvs_buck_volts[] = {
REGULATOR_LINEAR_RANGE(800000, 0x00, 0x3C, 10000),
};
@@ -275,7 +487,7 @@
* LDO1
* 3.0 to 3.3V (100mV step)
*/
-static const struct regulator_linear_range bd718xx_ldo1_volts[] = {
+static const struct linear_range bd718xx_ldo1_volts[] = {
REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000),
REGULATOR_LINEAR_RANGE(1600000, 0x00, 0x03, 100000),
};
@@ -294,7 +506,7 @@
* LDO3
* 1.8 to 3.3V (100mV step)
*/
-static const struct regulator_linear_range bd718xx_ldo3_volts[] = {
+static const struct linear_range bd718xx_ldo3_volts[] = {
REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000),
};
@@ -302,7 +514,7 @@
* LDO4
* 0.9 to 1.8V (100mV step)
*/
-static const struct regulator_linear_range bd718xx_ldo4_volts[] = {
+static const struct linear_range bd718xx_ldo4_volts[] = {
REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000),
};
@@ -310,7 +522,7 @@
* LDO5 for BD71837
* 1.8 to 3.3V (100mV step)
*/
-static const struct regulator_linear_range bd71837_ldo5_volts[] = {
+static const struct linear_range bd71837_ldo5_volts[] = {
REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000),
};
@@ -318,7 +530,7 @@
* LDO5 for BD71837
* 1.8 to 3.3V (100mV step)
*/
-static const struct regulator_linear_range bd71847_ldo5_volts[] = {
+static const struct linear_range bd71847_ldo5_volts[] = {
REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000),
REGULATOR_LINEAR_RANGE(800000, 0x00, 0x0F, 100000),
};
@@ -329,7 +541,7 @@
* LDO6
* 0.9 to 1.8V (100mV step)
*/
-static const struct regulator_linear_range bd718xx_ldo6_volts[] = {
+static const struct linear_range bd718xx_ldo6_volts[] = {
REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000),
};
@@ -337,7 +549,7 @@
* LDO7
* 1.8 to 3.3V (100mV step)
*/
-static const struct regulator_linear_range bd71837_ldo7_volts[] = {
+static const struct linear_range bd71837_ldo7_volts[] = {
REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000),
};
@@ -348,6 +560,7 @@
};
struct bd718xx_regulator_data {
struct regulator_desc desc;
+ const struct rohm_dvs_config dvs;
const struct reg_init init;
const struct reg_init *additional_inits;
int additional_init_amnt;
@@ -379,143 +592,48 @@
},
};
-#define NUM_DVS_BUCKS 4
+static int buck_set_hw_dvs_levels(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ struct bd718xx_regulator_data *data;
-struct of_dvs_setting {
- const char *prop;
- unsigned int reg;
+ data = container_of(desc, struct bd718xx_regulator_data, desc);
+
+ return rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap);
+}
+
+static const struct regulator_ops *bd71847_swcontrol_ops[] = {
+ &bd718xx_dvs_buck_regulator_ops, &bd718xx_dvs_buck_regulator_ops,
+ &bd718xx_pickable_range_buck_ops, &bd718xx_pickable_range_buck_ops,
+ &bd718xx_buck_regulator_nolinear_ops, &bd718xx_buck_regulator_ops,
+ &bd718xx_pickable_range_ldo_ops, &bd718xx_ldo_regulator_nolinear_ops,
+ &bd718xx_ldo_regulator_ops, &bd718xx_ldo_regulator_ops,
+ &bd718xx_pickable_range_ldo_ops, &bd718xx_ldo_regulator_ops,
};
-static int set_dvs_levels(const struct of_dvs_setting *dvs,
- struct device_node *np,
- const struct regulator_desc *desc,
- struct regmap *regmap)
-{
- int ret, i;
- unsigned int uv;
+static const struct regulator_ops *bd71847_hwcontrol_ops[] = {
+ &BD718XX_HWOPNAME(bd718xx_dvs_buck_regulator_ops),
+ &BD718XX_HWOPNAME(bd718xx_dvs_buck_regulator_ops),
+ &BD718XX_HWOPNAME(bd718xx_pickable_range_buck_ops),
+ &BD718XX_HWOPNAME(bd718xx_pickable_range_buck_ops),
+ &BD718XX_HWOPNAME(bd718xx_buck_regulator_nolinear_ops),
+ &BD718XX_HWOPNAME(bd718xx_buck_regulator_ops),
+ &BD718XX_HWOPNAME(bd718xx_pickable_range_ldo_ops),
+ &BD718XX_HWOPNAME(bd718xx_ldo_regulator_nolinear_ops),
+ &BD718XX_HWOPNAME(bd718xx_ldo_regulator_ops),
+ &BD718XX_HWOPNAME(bd718xx_ldo_regulator_ops),
+ &bd718xx_ldo5_ops_hwstate,
+ &BD718XX_HWOPNAME(bd718xx_ldo_regulator_ops),
+};
- ret = of_property_read_u32(np, dvs->prop, &uv);
- if (ret) {
- if (ret != -EINVAL)
- return ret;
- return 0;
- }
-
- for (i = 0; i < desc->n_voltages; i++) {
- ret = regulator_desc_list_voltage_linear_range(desc, i);
- if (ret < 0)
- continue;
- if (ret == uv) {
- i <<= ffs(desc->vsel_mask) - 1;
- ret = regmap_update_bits(regmap, dvs->reg,
- DVS_BUCK_RUN_MASK, i);
- break;
- }
- }
- return ret;
-}
-
-static int buck4_set_hw_dvs_levels(struct device_node *np,
- const struct regulator_desc *desc,
- struct regulator_config *cfg)
-{
- int ret, i;
- const struct of_dvs_setting dvs[] = {
- {
- .prop = "rohm,dvs-run-voltage",
- .reg = BD71837_REG_BUCK4_VOLT_RUN,
- },
- };
-
- for (i = 0; i < ARRAY_SIZE(dvs); i++) {
- ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
- if (ret)
- break;
- }
- return ret;
-}
-static int buck3_set_hw_dvs_levels(struct device_node *np,
- const struct regulator_desc *desc,
- struct regulator_config *cfg)
-{
- int ret, i;
- const struct of_dvs_setting dvs[] = {
- {
- .prop = "rohm,dvs-run-voltage",
- .reg = BD71837_REG_BUCK3_VOLT_RUN,
- },
- };
-
- for (i = 0; i < ARRAY_SIZE(dvs); i++) {
- ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
- if (ret)
- break;
- }
- return ret;
-}
-
-static int buck2_set_hw_dvs_levels(struct device_node *np,
- const struct regulator_desc *desc,
- struct regulator_config *cfg)
-{
- int ret, i;
- const struct of_dvs_setting dvs[] = {
- {
- .prop = "rohm,dvs-run-voltage",
- .reg = BD718XX_REG_BUCK2_VOLT_RUN,
- },
- {
- .prop = "rohm,dvs-idle-voltage",
- .reg = BD718XX_REG_BUCK2_VOLT_IDLE,
- },
- };
-
-
-
- for (i = 0; i < ARRAY_SIZE(dvs); i++) {
- ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
- if (ret)
- break;
- }
- return ret;
-}
-
-static int buck1_set_hw_dvs_levels(struct device_node *np,
- const struct regulator_desc *desc,
- struct regulator_config *cfg)
-{
- int ret, i;
- const struct of_dvs_setting dvs[] = {
- {
- .prop = "rohm,dvs-run-voltage",
- .reg = BD718XX_REG_BUCK1_VOLT_RUN,
- },
- {
- .prop = "rohm,dvs-idle-voltage",
- .reg = BD718XX_REG_BUCK1_VOLT_IDLE,
- },
- {
- .prop = "rohm,dvs-suspend-voltage",
- .reg = BD718XX_REG_BUCK1_VOLT_SUSP,
- },
- };
-
- for (i = 0; i < ARRAY_SIZE(dvs); i++) {
- ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
- if (ret)
- break;
- }
- return ret;
-}
-
-static const struct bd718xx_regulator_data bd71847_regulators[] = {
+static struct bd718xx_regulator_data bd71847_regulators[] = {
{
.desc = {
.name = "buck1",
.of_match = of_match_ptr("BUCK1"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_BUCK1,
- .ops = &bd718xx_dvs_buck_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM,
.linear_ranges = bd718xx_dvs_buck_volts,
@@ -527,7 +645,17 @@
.enable_mask = BD718XX_BUCK_EN,
.enable_time = BD71847_BUCK1_STARTUP_TIME,
.owner = THIS_MODULE,
- .of_parse_cb = buck1_set_hw_dvs_levels,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND,
+ .run_reg = BD718XX_REG_BUCK1_VOLT_RUN,
+ .run_mask = DVS_BUCK_RUN_MASK,
+ .idle_reg = BD718XX_REG_BUCK1_VOLT_IDLE,
+ .idle_mask = DVS_BUCK_RUN_MASK,
+ .suspend_reg = BD718XX_REG_BUCK1_VOLT_SUSP,
+ .suspend_mask = DVS_BUCK_RUN_MASK,
},
.init = {
.reg = BD718XX_REG_BUCK1_CTRL,
@@ -541,7 +669,6 @@
.of_match = of_match_ptr("BUCK2"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_BUCK2,
- .ops = &bd718xx_dvs_buck_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM,
.linear_ranges = bd718xx_dvs_buck_volts,
@@ -552,7 +679,14 @@
.enable_mask = BD718XX_BUCK_EN,
.enable_time = BD71847_BUCK2_STARTUP_TIME,
.owner = THIS_MODULE,
- .of_parse_cb = buck2_set_hw_dvs_levels,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE,
+ .run_reg = BD718XX_REG_BUCK2_VOLT_RUN,
+ .run_mask = DVS_BUCK_RUN_MASK,
+ .idle_reg = BD718XX_REG_BUCK2_VOLT_IDLE,
+ .idle_mask = DVS_BUCK_RUN_MASK,
},
.init = {
.reg = BD718XX_REG_BUCK2_CTRL,
@@ -566,7 +700,6 @@
.of_match = of_match_ptr("BUCK3"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_BUCK3,
- .ops = &bd718xx_pickable_range_buck_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD71847_BUCK3_VOLTAGE_NUM,
.linear_ranges = bd71847_buck3_volts,
@@ -594,7 +727,6 @@
.of_match = of_match_ptr("BUCK4"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_BUCK4,
- .ops = &bd718xx_pickable_range_buck_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD71847_BUCK4_VOLTAGE_NUM,
.linear_ranges = bd71847_buck4_volts,
@@ -622,7 +754,6 @@
.of_match = of_match_ptr("BUCK5"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_BUCK5,
- .ops = &bd718xx_buck_regulator_nolinear_ops,
.type = REGULATOR_VOLTAGE,
.volt_table = &bd718xx_3rd_nodvs_buck_volts[0],
.n_voltages = ARRAY_SIZE(bd718xx_3rd_nodvs_buck_volts),
@@ -645,7 +776,6 @@
.of_match = of_match_ptr("BUCK6"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_BUCK6,
- .ops = &bd718xx_buck_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_4TH_NODVS_BUCK_VOLTAGE_NUM,
.linear_ranges = bd718xx_4th_nodvs_buck_volts,
@@ -670,7 +800,6 @@
.of_match = of_match_ptr("LDO1"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_LDO1,
- .ops = &bd718xx_pickable_range_ldo_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_LDO1_VOLTAGE_NUM,
.linear_ranges = bd718xx_ldo1_volts,
@@ -697,7 +826,6 @@
.of_match = of_match_ptr("LDO2"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_LDO2,
- .ops = &bd718xx_ldo_regulator_nolinear_ops,
.type = REGULATOR_VOLTAGE,
.volt_table = &ldo_2_volts[0],
.vsel_reg = BD718XX_REG_LDO2_VOLT,
@@ -720,7 +848,6 @@
.of_match = of_match_ptr("LDO3"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_LDO3,
- .ops = &bd718xx_ldo_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_LDO3_VOLTAGE_NUM,
.linear_ranges = bd718xx_ldo3_volts,
@@ -744,7 +871,6 @@
.of_match = of_match_ptr("LDO4"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_LDO4,
- .ops = &bd718xx_ldo_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_LDO4_VOLTAGE_NUM,
.linear_ranges = bd718xx_ldo4_volts,
@@ -768,7 +894,6 @@
.of_match = of_match_ptr("LDO5"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_LDO5,
- .ops = &bd718xx_pickable_range_ldo_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD71847_LDO5_VOLTAGE_NUM,
.linear_ranges = bd71847_ldo5_volts,
@@ -795,7 +920,6 @@
.of_match = of_match_ptr("LDO6"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_LDO6,
- .ops = &bd718xx_ldo_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_LDO6_VOLTAGE_NUM,
.linear_ranges = bd718xx_ldo6_volts,
@@ -817,14 +941,41 @@
},
};
-static const struct bd718xx_regulator_data bd71837_regulators[] = {
+static const struct regulator_ops *bd71837_swcontrol_ops[] = {
+ &bd718xx_dvs_buck_regulator_ops, &bd718xx_dvs_buck_regulator_ops,
+ &bd718xx_dvs_buck_regulator_ops, &bd718xx_dvs_buck_regulator_ops,
+ &bd71837_pickable_range_buck_ops, &bd71837_buck_regulator_ops,
+ &bd71837_buck_regulator_nolinear_ops, &bd71837_buck_regulator_ops,
+ &bd71837_pickable_range_ldo_ops, &bd71837_ldo_regulator_nolinear_ops,
+ &bd71837_ldo_regulator_ops, &bd71837_ldo_regulator_ops,
+ &bd71837_ldo_regulator_ops, &bd71837_ldo_regulator_ops,
+ &bd71837_ldo_regulator_ops,
+};
+
+static const struct regulator_ops *bd71837_hwcontrol_ops[] = {
+ &BD718XX_HWOPNAME(bd718xx_dvs_buck_regulator_ops),
+ &BD718XX_HWOPNAME(bd718xx_dvs_buck_regulator_ops),
+ &bd71837_buck34_ops_hwctrl, &bd71837_buck34_ops_hwctrl,
+ &BD718XX_HWOPNAME(bd71837_pickable_range_buck_ops),
+ &BD718XX_HWOPNAME(bd71837_buck_regulator_ops),
+ &BD718XX_HWOPNAME(bd71837_buck_regulator_nolinear_ops),
+ &BD718XX_HWOPNAME(bd71837_buck_regulator_ops),
+ &BD718XX_HWOPNAME(bd71837_pickable_range_ldo_ops),
+ &BD718XX_HWOPNAME(bd71837_ldo_regulator_nolinear_ops),
+ &BD718XX_HWOPNAME(bd71837_ldo_regulator_ops),
+ &BD718XX_HWOPNAME(bd71837_ldo_regulator_ops),
+ &BD718XX_HWOPNAME(bd71837_ldo_regulator_ops),
+ &BD718XX_HWOPNAME(bd71837_ldo_regulator_ops),
+ &BD718XX_HWOPNAME(bd71837_ldo_regulator_ops),
+};
+
+static struct bd718xx_regulator_data bd71837_regulators[] = {
{
.desc = {
.name = "buck1",
.of_match = of_match_ptr("BUCK1"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_BUCK1,
- .ops = &bd718xx_dvs_buck_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM,
.linear_ranges = bd718xx_dvs_buck_volts,
@@ -835,7 +986,17 @@
.enable_mask = BD718XX_BUCK_EN,
.enable_time = BD71837_BUCK1_STARTUP_TIME,
.owner = THIS_MODULE,
- .of_parse_cb = buck1_set_hw_dvs_levels,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+ ROHM_DVS_LEVEL_SUSPEND,
+ .run_reg = BD718XX_REG_BUCK1_VOLT_RUN,
+ .run_mask = DVS_BUCK_RUN_MASK,
+ .idle_reg = BD718XX_REG_BUCK1_VOLT_IDLE,
+ .idle_mask = DVS_BUCK_RUN_MASK,
+ .suspend_reg = BD718XX_REG_BUCK1_VOLT_SUSP,
+ .suspend_mask = DVS_BUCK_RUN_MASK,
},
.init = {
.reg = BD718XX_REG_BUCK1_CTRL,
@@ -849,7 +1010,6 @@
.of_match = of_match_ptr("BUCK2"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_BUCK2,
- .ops = &bd718xx_dvs_buck_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM,
.linear_ranges = bd718xx_dvs_buck_volts,
@@ -860,7 +1020,14 @@
.enable_mask = BD718XX_BUCK_EN,
.enable_time = BD71837_BUCK2_STARTUP_TIME,
.owner = THIS_MODULE,
- .of_parse_cb = buck2_set_hw_dvs_levels,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE,
+ .run_reg = BD718XX_REG_BUCK2_VOLT_RUN,
+ .run_mask = DVS_BUCK_RUN_MASK,
+ .idle_reg = BD718XX_REG_BUCK2_VOLT_IDLE,
+ .idle_mask = DVS_BUCK_RUN_MASK,
},
.init = {
.reg = BD718XX_REG_BUCK2_CTRL,
@@ -874,7 +1041,6 @@
.of_match = of_match_ptr("BUCK3"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_BUCK3,
- .ops = &bd718xx_dvs_buck_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM,
.linear_ranges = bd718xx_dvs_buck_volts,
@@ -885,7 +1051,12 @@
.enable_mask = BD718XX_BUCK_EN,
.enable_time = BD71837_BUCK3_STARTUP_TIME,
.owner = THIS_MODULE,
- .of_parse_cb = buck3_set_hw_dvs_levels,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN,
+ .run_reg = BD71837_REG_BUCK3_VOLT_RUN,
+ .run_mask = DVS_BUCK_RUN_MASK,
},
.init = {
.reg = BD71837_REG_BUCK3_CTRL,
@@ -899,7 +1070,6 @@
.of_match = of_match_ptr("BUCK4"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_BUCK4,
- .ops = &bd718xx_dvs_buck_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM,
.linear_ranges = bd718xx_dvs_buck_volts,
@@ -910,7 +1080,12 @@
.enable_mask = BD718XX_BUCK_EN,
.enable_time = BD71837_BUCK4_STARTUP_TIME,
.owner = THIS_MODULE,
- .of_parse_cb = buck4_set_hw_dvs_levels,
+ .of_parse_cb = buck_set_hw_dvs_levels,
+ },
+ .dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN,
+ .run_reg = BD71837_REG_BUCK4_VOLT_RUN,
+ .run_mask = DVS_BUCK_RUN_MASK,
},
.init = {
.reg = BD71837_REG_BUCK4_CTRL,
@@ -924,7 +1099,6 @@
.of_match = of_match_ptr("BUCK5"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_BUCK5,
- .ops = &bd718xx_pickable_range_buck_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD71837_BUCK5_VOLTAGE_NUM,
.linear_ranges = bd71837_buck5_volts,
@@ -952,7 +1126,6 @@
.of_match = of_match_ptr("BUCK6"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_BUCK6,
- .ops = &bd718xx_buck_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD71837_BUCK6_VOLTAGE_NUM,
.linear_ranges = bd71837_buck6_volts,
@@ -977,7 +1150,6 @@
.of_match = of_match_ptr("BUCK7"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_BUCK7,
- .ops = &bd718xx_buck_regulator_nolinear_ops,
.type = REGULATOR_VOLTAGE,
.volt_table = &bd718xx_3rd_nodvs_buck_volts[0],
.n_voltages = ARRAY_SIZE(bd718xx_3rd_nodvs_buck_volts),
@@ -1000,7 +1172,6 @@
.of_match = of_match_ptr("BUCK8"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_BUCK8,
- .ops = &bd718xx_buck_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_4TH_NODVS_BUCK_VOLTAGE_NUM,
.linear_ranges = bd718xx_4th_nodvs_buck_volts,
@@ -1025,7 +1196,6 @@
.of_match = of_match_ptr("LDO1"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_LDO1,
- .ops = &bd718xx_pickable_range_ldo_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_LDO1_VOLTAGE_NUM,
.linear_ranges = bd718xx_ldo1_volts,
@@ -1052,7 +1222,6 @@
.of_match = of_match_ptr("LDO2"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_LDO2,
- .ops = &bd718xx_ldo_regulator_nolinear_ops,
.type = REGULATOR_VOLTAGE,
.volt_table = &ldo_2_volts[0],
.vsel_reg = BD718XX_REG_LDO2_VOLT,
@@ -1075,7 +1244,6 @@
.of_match = of_match_ptr("LDO3"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_LDO3,
- .ops = &bd718xx_ldo_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_LDO3_VOLTAGE_NUM,
.linear_ranges = bd718xx_ldo3_volts,
@@ -1099,7 +1267,6 @@
.of_match = of_match_ptr("LDO4"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_LDO4,
- .ops = &bd718xx_ldo_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_LDO4_VOLTAGE_NUM,
.linear_ranges = bd718xx_ldo4_volts,
@@ -1123,7 +1290,6 @@
.of_match = of_match_ptr("LDO5"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_LDO5,
- .ops = &bd718xx_ldo_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD71837_LDO5_VOLTAGE_NUM,
.linear_ranges = bd71837_ldo5_volts,
@@ -1151,7 +1317,6 @@
.of_match = of_match_ptr("LDO6"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_LDO6,
- .ops = &bd718xx_ldo_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD718XX_LDO6_VOLTAGE_NUM,
.linear_ranges = bd718xx_ldo6_volts,
@@ -1179,7 +1344,6 @@
.of_match = of_match_ptr("LDO7"),
.regulators_node = of_match_ptr("regulators"),
.id = BD718XX_LDO7,
- .ops = &bd718xx_ldo_regulator_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = BD71837_LDO7_VOLTAGE_NUM,
.linear_ranges = bd71837_ldo7_volts,
@@ -1199,28 +1363,57 @@
},
};
-struct bd718xx_pmic_inits {
- const struct bd718xx_regulator_data *r_datas;
- unsigned int r_amount;
-};
+static void mark_hw_controlled(struct device *dev, struct device_node *np,
+ struct bd718xx_regulator_data *reg_data,
+ unsigned int num_reg_data, int *info)
+{
+ int i;
+
+ for (i = 1; i <= num_reg_data; i++) {
+ if (!of_node_name_eq(np, reg_data[i-1].desc.of_match))
+ continue;
+
+ *info |= 1 << (i - 1);
+ dev_dbg(dev, "regulator %d runlevel controlled\n", i);
+ return;
+ }
+ dev_warn(dev, "Bad regulator node\n");
+}
+
+static int get_hw_controlled_regulators(struct device *dev,
+ struct bd718xx_regulator_data *reg_data,
+ unsigned int num_reg_data, int *info)
+{
+ struct device_node *np;
+ struct device_node *nproot = dev->of_node;
+ const char *prop = "rohm,no-regulator-enable-control";
+
+ *info = 0;
+
+ nproot = of_get_child_by_name(nproot, "regulators");
+ if (!nproot) {
+ dev_err(dev, "failed to find regulators node\n");
+ return -ENODEV;
+ }
+ for_each_child_of_node(nproot, np)
+ if (of_property_read_bool(np, prop))
+ mark_hw_controlled(dev, np, reg_data, num_reg_data,
+ info);
+
+ of_node_put(nproot);
+ return 0;
+}
static int bd718xx_probe(struct platform_device *pdev)
{
struct bd718xx *mfd;
struct regulator_config config = { 0 };
- struct bd718xx_pmic_inits pmic_regulators[ROHM_CHIP_TYPE_AMOUNT] = {
- [ROHM_CHIP_TYPE_BD71837] = {
- .r_datas = bd71837_regulators,
- .r_amount = ARRAY_SIZE(bd71837_regulators),
- },
- [ROHM_CHIP_TYPE_BD71847] = {
- .r_datas = bd71847_regulators,
- .r_amount = ARRAY_SIZE(bd71847_regulators),
- },
- };
-
- int i, j, err;
+ int i, j, err, omit_enable;
bool use_snvs;
+ struct bd718xx_regulator_data *reg_data;
+ unsigned int num_reg_data;
+ 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) {
@@ -1229,8 +1422,20 @@
goto err;
}
- if (mfd->chip.chip_type >= ROHM_CHIP_TYPE_AMOUNT ||
- !pmic_regulators[mfd->chip.chip_type].r_datas) {
+ switch (chip) {
+ case ROHM_CHIP_TYPE_BD71837:
+ reg_data = bd71837_regulators;
+ num_reg_data = ARRAY_SIZE(bd71837_regulators);
+ swops = &bd71837_swcontrol_ops[0];
+ hwops = &bd71837_hwcontrol_ops[0];
+ break;
+ case ROHM_CHIP_TYPE_BD71847:
+ reg_data = bd71847_regulators;
+ num_reg_data = ARRAY_SIZE(bd71847_regulators);
+ swops = &bd71847_swcontrol_ops[0];
+ hwops = &bd71847_hwcontrol_ops[0];
+ break;
+ default:
dev_err(&pdev->dev, "Unsupported chip type\n");
err = -EINVAL;
goto err;
@@ -1272,17 +1477,35 @@
}
}
- for (i = 0; i < pmic_regulators[mfd->chip.chip_type].r_amount; i++) {
+ config.dev = pdev->dev.parent;
+ config.regmap = mfd->chip.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.
+ * One special case is when we use PMIC_STBY_REQ line from SoC to PMIC
+ * in order to set the system to SUSPEND state.
+ *
+ * If regulator is taken under SW control the regulator state will not
+ * be affected by PMIC state machine - Eg. regulator is likely to stay
+ * on even in SUSPEND
+ */
+ get_hw_controlled_regulators(pdev->dev.parent, reg_data, num_reg_data,
+ &omit_enable);
- const struct regulator_desc *desc;
+ for (i = 0; i < num_reg_data; i++) {
+
+ struct regulator_desc *desc;
struct regulator_dev *rdev;
- const struct bd718xx_regulator_data *r;
+ struct bd718xx_regulator_data *r;
+ int no_enable_control = omit_enable & (1 << i);
- r = &pmic_regulators[mfd->chip.chip_type].r_datas[i];
+ r = ®_data[i];
desc = &r->desc;
- config.dev = pdev->dev.parent;
- config.regmap = mfd->chip.regmap;
+ if (no_enable_control)
+ desc->ops = hwops[i];
+ else
+ desc->ops = swops[i];
rdev = devm_regulator_register(&pdev->dev, desc, &config);
if (IS_ERR(rdev)) {
@@ -1309,8 +1532,9 @@
* enable SW control for crucial regulators if snvs state is
* used
*/
- if (!use_snvs || !rdev->constraints->always_on ||
- !rdev->constraints->boot_on) {
+ if (!no_enable_control && (!use_snvs ||
+ !rdev->constraints->always_on ||
+ !rdev->constraints->boot_on)) {
err = regmap_update_bits(mfd->chip.regmap, r->init.reg,
r->init.mask, r->init.val);
if (err) {
@@ -1338,11 +1562,19 @@
return err;
}
+static const struct platform_device_id bd718x7_pmic_id[] = {
+ { "bd71837-pmic", ROHM_CHIP_TYPE_BD71837 },
+ { "bd71847-pmic", ROHM_CHIP_TYPE_BD71847 },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, bd718x7_pmic_id);
+
static struct platform_driver bd718xx_regulator = {
.driver = {
.name = "bd718xx-pmic",
},
.probe = bd718xx_probe,
+ .id_table = bd718x7_pmic_id,
};
module_platform_driver(bd718xx_regulator);
@@ -1350,3 +1582,4 @@
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
MODULE_DESCRIPTION("BD71837/BD71847 voltage regulator driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bd718xx-pmic");
diff --git a/drivers/regulator/bd9576-regulator.c b/drivers/regulator/bd9576-regulator.c
new file mode 100644
index 0000000..204a2da
--- /dev/null
+++ b/drivers/regulator/bd9576-regulator.c
@@ -0,0 +1,334 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2020 ROHM Semiconductors
+// ROHM BD9576MUF/BD9573MUF regulator driver
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/rohm-bd957x.h>
+#include <linux/mfd/rohm-generic.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/slab.h>
+
+#define BD957X_VOUTS1_VOLT 3300000
+#define BD957X_VOUTS4_BASE_VOLT 1030000
+#define BD957X_VOUTS34_NUM_VOLT 32
+
+static int vout1_volt_table[] = {5000000, 4900000, 4800000, 4700000, 4600000,
+ 4500000, 4500000, 4500000, 5000000, 5100000,
+ 5200000, 5300000, 5400000, 5500000, 5500000,
+ 5500000};
+
+static int vout2_volt_table[] = {1800000, 1780000, 1760000, 1740000, 1720000,
+ 1700000, 1680000, 1660000, 1800000, 1820000,
+ 1840000, 1860000, 1880000, 1900000, 1920000,
+ 1940000};
+
+static int voutl1_volt_table[] = {2500000, 2540000, 2580000, 2620000, 2660000,
+ 2700000, 2740000, 2780000, 2500000, 2460000,
+ 2420000, 2380000, 2340000, 2300000, 2260000,
+ 2220000};
+
+struct bd957x_regulator_data {
+ struct regulator_desc desc;
+ int base_voltage;
+};
+
+static int bd957x_vout34_list_voltage(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ const struct regulator_desc *desc = rdev->desc;
+ int multiplier = selector & desc->vsel_mask & 0x7f;
+ int tune;
+
+ /* VOUT3 and 4 has 10mV step */
+ tune = multiplier * 10000;
+
+ if (!(selector & 0x80))
+ return desc->fixed_uV - tune;
+
+ return desc->fixed_uV + tune;
+}
+
+static int bd957x_list_voltage(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ const struct regulator_desc *desc = rdev->desc;
+ int index = selector & desc->vsel_mask & 0x7f;
+
+ if (!(selector & 0x80))
+ index += desc->n_voltages/2;
+
+ if (index >= desc->n_voltages)
+ return -EINVAL;
+
+ return desc->volt_table[index];
+}
+
+static const struct regulator_ops bd957x_vout34_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = bd957x_vout34_list_voltage,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static const struct regulator_ops bd957X_vouts1_regulator_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+static const struct regulator_ops bd957x_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = bd957x_list_voltage,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static struct bd957x_regulator_data bd9576_regulators[] = {
+ {
+ .desc = {
+ .name = "VD50",
+ .of_match = of_match_ptr("regulator-vd50"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD957X_VD50,
+ .type = REGULATOR_VOLTAGE,
+ .ops = &bd957x_ops,
+ .volt_table = &vout1_volt_table[0],
+ .n_voltages = ARRAY_SIZE(vout1_volt_table),
+ .vsel_reg = BD957X_REG_VOUT1_TUNE,
+ .vsel_mask = BD957X_MASK_VOUT1_TUNE,
+ .enable_reg = BD957X_REG_POW_TRIGGER1,
+ .enable_mask = BD957X_REGULATOR_EN_MASK,
+ .enable_val = BD957X_REGULATOR_DIS_VAL,
+ .enable_is_inverted = true,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "VD18",
+ .of_match = of_match_ptr("regulator-vd18"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD957X_VD18,
+ .type = REGULATOR_VOLTAGE,
+ .ops = &bd957x_ops,
+ .volt_table = &vout2_volt_table[0],
+ .n_voltages = ARRAY_SIZE(vout2_volt_table),
+ .vsel_reg = BD957X_REG_VOUT2_TUNE,
+ .vsel_mask = BD957X_MASK_VOUT2_TUNE,
+ .enable_reg = BD957X_REG_POW_TRIGGER2,
+ .enable_mask = BD957X_REGULATOR_EN_MASK,
+ .enable_val = BD957X_REGULATOR_DIS_VAL,
+ .enable_is_inverted = true,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "VDDDR",
+ .of_match = of_match_ptr("regulator-vdddr"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD957X_VDDDR,
+ .ops = &bd957x_vout34_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = BD957X_VOUTS34_NUM_VOLT,
+ .vsel_reg = BD957X_REG_VOUT3_TUNE,
+ .vsel_mask = BD957X_MASK_VOUT3_TUNE,
+ .enable_reg = BD957X_REG_POW_TRIGGER3,
+ .enable_mask = BD957X_REGULATOR_EN_MASK,
+ .enable_val = BD957X_REGULATOR_DIS_VAL,
+ .enable_is_inverted = true,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "VD10",
+ .of_match = of_match_ptr("regulator-vd10"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD957X_VD10,
+ .ops = &bd957x_vout34_ops,
+ .type = REGULATOR_VOLTAGE,
+ .fixed_uV = BD957X_VOUTS4_BASE_VOLT,
+ .n_voltages = BD957X_VOUTS34_NUM_VOLT,
+ .vsel_reg = BD957X_REG_VOUT4_TUNE,
+ .vsel_mask = BD957X_MASK_VOUT4_TUNE,
+ .enable_reg = BD957X_REG_POW_TRIGGER4,
+ .enable_mask = BD957X_REGULATOR_EN_MASK,
+ .enable_val = BD957X_REGULATOR_DIS_VAL,
+ .enable_is_inverted = true,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "VOUTL1",
+ .of_match = of_match_ptr("regulator-voutl1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD957X_VOUTL1,
+ .ops = &bd957x_ops,
+ .type = REGULATOR_VOLTAGE,
+ .volt_table = &voutl1_volt_table[0],
+ .n_voltages = ARRAY_SIZE(voutl1_volt_table),
+ .vsel_reg = BD957X_REG_VOUTL1_TUNE,
+ .vsel_mask = BD957X_MASK_VOUTL1_TUNE,
+ .enable_reg = BD957X_REG_POW_TRIGGERL1,
+ .enable_mask = BD957X_REGULATOR_EN_MASK,
+ .enable_val = BD957X_REGULATOR_DIS_VAL,
+ .enable_is_inverted = true,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "VOUTS1",
+ .of_match = of_match_ptr("regulator-vouts1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD957X_VOUTS1,
+ .ops = &bd957X_vouts1_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 1,
+ .fixed_uV = BD957X_VOUTS1_VOLT,
+ .enable_reg = BD957X_REG_POW_TRIGGERS1,
+ .enable_mask = BD957X_REGULATOR_EN_MASK,
+ .enable_val = BD957X_REGULATOR_DIS_VAL,
+ .enable_is_inverted = true,
+ .owner = THIS_MODULE,
+ },
+ },
+};
+
+static int bd957x_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ struct regulator_config config = { 0 };
+ int i;
+ bool vout_mode, ddr_sel;
+ const struct bd957x_regulator_data *reg_data = &bd9576_regulators[0];
+ unsigned int num_reg_data = ARRAY_SIZE(bd9576_regulators);
+ enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data;
+
+ regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!regmap) {
+ dev_err(&pdev->dev, "No regmap\n");
+ return -EINVAL;
+ }
+ vout_mode = of_property_read_bool(pdev->dev.parent->of_node,
+ "rohm,vout1-en-low");
+ if (vout_mode) {
+ struct gpio_desc *en;
+
+ dev_dbg(&pdev->dev, "GPIO controlled mode\n");
+
+ /* VOUT1 enable state judged by VOUT1_EN pin */
+ /* See if we have GPIO defined */
+ en = devm_gpiod_get_from_of_node(&pdev->dev,
+ pdev->dev.parent->of_node,
+ "rohm,vout1-en-gpios", 0,
+ GPIOD_OUT_LOW, "vout1-en");
+ if (!IS_ERR(en)) {
+ /* VOUT1_OPS gpio ctrl */
+ /*
+ * Regulator core prioritizes the ena_gpio over
+ * enable/disable/is_enabled callbacks so no need to
+ * clear them. We can still use same ops
+ */
+ config.ena_gpiod = en;
+ } else {
+ /*
+ * In theory it is possible someone wants to set
+ * vout1-en LOW during OTP loading and set VOUT1 to be
+ * controlled by GPIO - but control the GPIO from some
+ * where else than this driver. For that to work we
+ * should unset the is_enabled callback here.
+ *
+ * I believe such case where rohm,vout1-en-low is set
+ * and vout1-en-gpios is not is likely to be a
+ * misconfiguration. So let's just err out for now.
+ */
+ dev_err(&pdev->dev,
+ "Failed to get VOUT1 control GPIO\n");
+ return PTR_ERR(en);
+ }
+ }
+
+ /*
+ * If more than one PMIC needs to be controlled by same processor then
+ * allocate the regulator data array here and use bd9576_regulators as
+ * template. At the moment I see no such use-case so I spare some
+ * bytes and use bd9576_regulators directly for non-constant configs
+ * like DDR voltage selection.
+ */
+ ddr_sel = of_property_read_bool(pdev->dev.parent->of_node,
+ "rohm,ddr-sel-low");
+ if (ddr_sel)
+ bd9576_regulators[2].desc.fixed_uV = 1350000;
+ else
+ bd9576_regulators[2].desc.fixed_uV = 1500000;
+
+ switch (chip) {
+ case ROHM_CHIP_TYPE_BD9576:
+ dev_dbg(&pdev->dev, "Found BD9576MUF\n");
+ break;
+ case ROHM_CHIP_TYPE_BD9573:
+ dev_dbg(&pdev->dev, "Found BD9573MUF\n");
+ break;
+ default:
+ dev_err(&pdev->dev, "Unsupported chip type\n");
+ return -EINVAL;
+ }
+
+ config.dev = pdev->dev.parent;
+ config.regmap = regmap;
+
+ for (i = 0; i < num_reg_data; i++) {
+
+ const struct regulator_desc *desc;
+ struct regulator_dev *rdev;
+ const struct bd957x_regulator_data *r;
+
+ r = ®_data[i];
+ desc = &r->desc;
+
+ rdev = devm_regulator_register(&pdev->dev, desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev,
+ "failed to register %s regulator\n",
+ desc->name);
+ return PTR_ERR(rdev);
+ }
+ /*
+ * Clear the VOUT1 GPIO setting - rest of the regulators do not
+ * support GPIO control
+ */
+ config.ena_gpiod = NULL;
+ }
+
+ return 0;
+}
+
+static const struct platform_device_id bd957x_pmic_id[] = {
+ { "bd9573-pmic", ROHM_CHIP_TYPE_BD9573 },
+ { "bd9576-pmic", ROHM_CHIP_TYPE_BD9576 },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, bd957x_pmic_id);
+
+static struct platform_driver bd957x_regulator = {
+ .driver = {
+ .name = "bd957x-pmic",
+ },
+ .probe = bd957x_probe,
+ .id_table = bd957x_pmic_id,
+};
+
+module_platform_driver(bd957x_regulator);
+
+MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
+MODULE_DESCRIPTION("ROHM BD9576/BD9573 voltage regulator driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bd957x-pmic");
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 7fd793d..2c48e55 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -105,6 +105,7 @@
static struct regulator *create_regulator(struct regulator_dev *rdev,
struct device *dev,
const char *supply_name);
+static void destroy_regulator(struct regulator *regulator);
static void _regulator_put(struct regulator *regulator);
const char *rdev_get_name(struct regulator_dev *rdev)
@@ -189,11 +190,10 @@
* than the one, which initially locked the mutex, it will
* wait on mutex.
*/
-void regulator_lock(struct regulator_dev *rdev)
+static void regulator_lock(struct regulator_dev *rdev)
{
regulator_lock_nested(rdev, NULL);
}
-EXPORT_SYMBOL_GPL(regulator_lock);
/**
* regulator_unlock - unlock a single regulator
@@ -202,7 +202,7 @@
* This function unlocks the mutex when the
* reference counter reaches 0.
*/
-void regulator_unlock(struct regulator_dev *rdev)
+static void regulator_unlock(struct regulator_dev *rdev)
{
mutex_lock(®ulator_nesting_mutex);
@@ -215,7 +215,6 @@
mutex_unlock(®ulator_nesting_mutex);
}
-EXPORT_SYMBOL_GPL(regulator_unlock);
static bool regulator_supply_is_couple(struct regulator_dev *rdev)
{
@@ -408,11 +407,11 @@
static struct device_node *of_get_regulator(struct device *dev, const char *supply)
{
struct device_node *regnode = NULL;
- char prop_name[32]; /* 32 is max size of property name */
+ char prop_name[64]; /* 64 is max size of property name */
dev_dbg(dev, "Looking up %s-supply from device tree\n", supply);
- snprintf(prop_name, 32, "%s-supply", supply);
+ snprintf(prop_name, 64, "%s-supply", supply);
regnode = of_parse_phandle(dev->of_node, prop_name, 0);
if (!regnode) {
@@ -567,6 +566,30 @@
}
}
+static const struct regulator_state *
+regulator_get_suspend_state_check(struct regulator_dev *rdev, suspend_state_t state)
+{
+ const struct regulator_state *rstate;
+
+ rstate = regulator_get_suspend_state(rdev, state);
+ if (rstate == NULL)
+ return NULL;
+
+ /* If we have no suspend mode configuration don't set anything;
+ * only warn if the driver implements set_suspend_voltage or
+ * set_suspend_mode callback.
+ */
+ if (rstate->enabled != ENABLE_IN_SUSPEND &&
+ rstate->enabled != DISABLE_IN_SUSPEND) {
+ if (rdev->desc->ops->set_suspend_voltage ||
+ rdev->desc->ops->set_suspend_mode)
+ rdev_warn(rdev, "No configuration\n");
+ return NULL;
+ }
+
+ return rstate;
+}
+
static ssize_t regulator_uV_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -944,7 +967,8 @@
/* set the optimum mode for our new total regulator load */
err = rdev->desc->ops->set_load(rdev, current_uA);
if (err < 0)
- rdev_err(rdev, "failed to set load %d\n", current_uA);
+ rdev_err(rdev, "failed to set load %d: %pe\n",
+ current_uA, ERR_PTR(err));
} else {
/* get output voltage */
output_uV = regulator_get_voltage_rdev(rdev);
@@ -971,40 +995,24 @@
/* check the new mode is allowed */
err = regulator_mode_constrain(rdev, &mode);
if (err < 0) {
- rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n",
- current_uA, input_uV, output_uV);
+ rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV: %pe\n",
+ current_uA, input_uV, output_uV, ERR_PTR(err));
return err;
}
err = rdev->desc->ops->set_mode(rdev, mode);
if (err < 0)
- rdev_err(rdev, "failed to set optimum mode %x\n", mode);
+ rdev_err(rdev, "failed to set optimum mode %x: %pe\n",
+ mode, ERR_PTR(err));
}
return err;
}
-static int suspend_set_state(struct regulator_dev *rdev,
- suspend_state_t state)
+static int __suspend_set_state(struct regulator_dev *rdev,
+ const struct regulator_state *rstate)
{
int ret = 0;
- struct regulator_state *rstate;
-
- rstate = regulator_get_suspend_state(rdev, state);
- if (rstate == NULL)
- return 0;
-
- /* If we have no suspend mode configuration don't set anything;
- * only warn if the driver implements set_suspend_voltage or
- * set_suspend_mode callback.
- */
- if (rstate->enabled != ENABLE_IN_SUSPEND &&
- rstate->enabled != DISABLE_IN_SUSPEND) {
- if (rdev->desc->ops->set_suspend_voltage ||
- rdev->desc->ops->set_suspend_mode)
- rdev_warn(rdev, "No configuration\n");
- return 0;
- }
if (rstate->enabled == ENABLE_IN_SUSPEND &&
rdev->desc->ops->set_suspend_enable)
@@ -1016,14 +1024,14 @@
ret = 0;
if (ret < 0) {
- rdev_err(rdev, "failed to enabled/disable\n");
+ rdev_err(rdev, "failed to enabled/disable: %pe\n", ERR_PTR(ret));
return ret;
}
if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) {
ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV);
if (ret < 0) {
- rdev_err(rdev, "failed to set voltage\n");
+ rdev_err(rdev, "failed to set voltage: %pe\n", ERR_PTR(ret));
return ret;
}
}
@@ -1031,7 +1039,7 @@
if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) {
ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode);
if (ret < 0) {
- rdev_err(rdev, "failed to set mode\n");
+ rdev_err(rdev, "failed to set mode: %pe\n", ERR_PTR(ret));
return ret;
}
}
@@ -1039,7 +1047,20 @@
return ret;
}
-static void print_constraints(struct regulator_dev *rdev)
+static int suspend_set_initial_state(struct regulator_dev *rdev)
+{
+ const struct regulator_state *rstate;
+
+ rstate = regulator_get_suspend_state_check(rdev,
+ rdev->constraints->initial_state);
+ if (!rstate)
+ return 0;
+
+ return __suspend_set_state(rdev, rstate);
+}
+
+#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
+static void print_constraints_debug(struct regulator_dev *rdev)
{
struct regulation_constraints *constraints = rdev->constraints;
char buf[160] = "";
@@ -1096,12 +1117,27 @@
if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE)
count += scnprintf(buf + count, len - count, "idle ");
if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY)
- count += scnprintf(buf + count, len - count, "standby");
+ count += scnprintf(buf + count, len - count, "standby ");
if (!count)
- scnprintf(buf, len, "no parameters");
+ count = scnprintf(buf, len, "no parameters");
+ else
+ --count;
+
+ count += scnprintf(buf + count, len - count, ", %s",
+ _regulator_is_enabled(rdev) ? "enabled" : "disabled");
rdev_dbg(rdev, "%s\n", buf);
+}
+#else /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */
+static inline void print_constraints_debug(struct regulator_dev *rdev) {}
+#endif /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */
+
+static void print_constraints(struct regulator_dev *rdev)
+{
+ struct regulation_constraints *constraints = rdev->constraints;
+
+ print_constraints_debug(rdev);
if ((constraints->min_uV != constraints->max_uV) &&
!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE))
@@ -1134,8 +1170,8 @@
if (current_uV < 0) {
rdev_err(rdev,
- "failed to get the current voltage(%d)\n",
- current_uV);
+ "failed to get the current voltage: %pe\n",
+ ERR_PTR(current_uV));
return current_uV;
}
@@ -1164,8 +1200,8 @@
rdev, target_min, target_max);
if (ret < 0) {
rdev_err(rdev,
- "failed to apply %d-%duV constraint(%d)\n",
- target_min, target_max, ret);
+ "failed to apply %d-%duV constraint: %pe\n",
+ target_min, target_max, ERR_PTR(ret));
return ret;
}
}
@@ -1201,6 +1237,10 @@
return -EINVAL;
}
+ /* no need to loop voltages if range is continuous */
+ if (rdev->desc->continuous_voltage_range)
+ return 0;
+
/* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
for (i = 0; i < count; i++) {
int value;
@@ -1299,16 +1339,16 @@
ret = ops->set_input_current_limit(rdev,
rdev->constraints->ilim_uA);
if (ret < 0) {
- rdev_err(rdev, "failed to set input limit\n");
+ rdev_err(rdev, "failed to set input limit: %pe\n", ERR_PTR(ret));
return ret;
}
}
/* do we need to setup our suspend state */
if (rdev->constraints->initial_state) {
- ret = suspend_set_state(rdev, rdev->constraints->initial_state);
+ ret = suspend_set_initial_state(rdev);
if (ret < 0) {
- rdev_err(rdev, "failed to set suspend state\n");
+ rdev_err(rdev, "failed to set suspend state: %pe\n", ERR_PTR(ret));
return ret;
}
}
@@ -1321,7 +1361,7 @@
ret = ops->set_mode(rdev, rdev->constraints->initial_mode);
if (ret < 0) {
- rdev_err(rdev, "failed to set initial mode: %d\n", ret);
+ rdev_err(rdev, "failed to set initial mode: %pe\n", ERR_PTR(ret));
return ret;
}
} else if (rdev->constraints->system_load) {
@@ -1336,7 +1376,7 @@
&& ops->set_ramp_delay) {
ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
if (ret < 0) {
- rdev_err(rdev, "failed to set ramp_delay\n");
+ rdev_err(rdev, "failed to set ramp_delay: %pe\n", ERR_PTR(ret));
return ret;
}
}
@@ -1344,7 +1384,7 @@
if (rdev->constraints->pull_down && ops->set_pull_down) {
ret = ops->set_pull_down(rdev);
if (ret < 0) {
- rdev_err(rdev, "failed to set pull down\n");
+ rdev_err(rdev, "failed to set pull down: %pe\n", ERR_PTR(ret));
return ret;
}
}
@@ -1352,7 +1392,7 @@
if (rdev->constraints->soft_start && ops->set_soft_start) {
ret = ops->set_soft_start(rdev);
if (ret < 0) {
- rdev_err(rdev, "failed to set soft start\n");
+ rdev_err(rdev, "failed to set soft start: %pe\n", ERR_PTR(ret));
return ret;
}
}
@@ -1361,7 +1401,8 @@
&& ops->set_over_current_protection) {
ret = ops->set_over_current_protection(rdev);
if (ret < 0) {
- rdev_err(rdev, "failed to set over current protection\n");
+ rdev_err(rdev, "failed to set over current protection: %pe\n",
+ ERR_PTR(ret));
return ret;
}
}
@@ -1372,7 +1413,7 @@
ret = ops->set_active_discharge(rdev, ad_state);
if (ret < 0) {
- rdev_err(rdev, "failed to set active discharge\n");
+ rdev_err(rdev, "failed to set active discharge: %pe\n", ERR_PTR(ret));
return ret;
}
}
@@ -1398,7 +1439,7 @@
ret = _regulator_do_enable(rdev);
if (ret < 0 && ret != -EINVAL) {
- rdev_err(rdev, "failed to enable\n");
+ rdev_err(rdev, "failed to enable: %pe\n", ERR_PTR(ret));
return ret;
}
@@ -1622,8 +1663,8 @@
err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj,
supply_name);
if (err) {
- rdev_dbg(rdev, "could not add device link %s err %d\n",
- dev->kobj.name, err);
+ rdev_dbg(rdev, "could not add device link %s: %pe\n",
+ dev->kobj.name, ERR_PTR(err));
/* non-fatal */
}
}
@@ -1886,7 +1927,7 @@
{
struct regulator_dev *rdev;
struct regulator *regulator;
- const char *devname = dev ? dev_name(dev) : "deviceless";
+ struct device_link *link;
int ret;
if (get_type >= MAX_GET_TYPE) {
@@ -1923,9 +1964,7 @@
* enabled, even if it isn't hooked up, and just
* provide a dummy.
*/
- dev_warn(dev,
- "%s supply %s not found, using dummy regulator\n",
- devname, id);
+ dev_warn(dev, "supply %s not found, using dummy regulator\n", id);
rdev = dummy_regulator_rdev;
get_device(&rdev->dev);
break;
@@ -1933,7 +1972,7 @@
case EXCLUSIVE_GET:
dev_warn(dev,
"dummy supplies not allowed for exclusive requests\n");
- /* fall through */
+ fallthrough;
default:
return ERR_PTR(-ENODEV);
@@ -1994,7 +2033,9 @@
rdev->use_count = 0;
}
- device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS);
+ link = device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS);
+ if (!IS_ERR_OR_NULL(link))
+ regulator->device_link = true;
return regulator;
}
@@ -2071,6 +2112,31 @@
}
EXPORT_SYMBOL_GPL(regulator_get_optional);
+static void destroy_regulator(struct regulator *regulator)
+{
+ struct regulator_dev *rdev = regulator->rdev;
+
+ debugfs_remove_recursive(regulator->debugfs);
+
+ if (regulator->dev) {
+ if (regulator->device_link)
+ device_link_remove(regulator->dev, &rdev->dev);
+
+ /* remove any sysfs entries */
+ sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
+ }
+
+ regulator_lock(rdev);
+ list_del(®ulator->list);
+
+ rdev->open_count--;
+ rdev->exclusive = 0;
+ regulator_unlock(rdev);
+
+ kfree_const(regulator->supply_name);
+ kfree(regulator);
+}
+
/* regulator_list_mutex lock held by regulator_put() */
static void _regulator_put(struct regulator *regulator)
{
@@ -2086,24 +2152,7 @@
rdev = regulator->rdev;
- debugfs_remove_recursive(regulator->debugfs);
-
- if (regulator->dev) {
- device_link_remove(regulator->dev, &rdev->dev);
-
- /* remove any sysfs entries */
- sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
- }
-
- regulator_lock(rdev);
- list_del(®ulator->list);
-
- rdev->open_count--;
- rdev->exclusive = 0;
- regulator_unlock(rdev);
-
- kfree_const(regulator->supply_name);
- kfree(regulator);
+ destroy_regulator(regulator);
module_put(rdev->owner);
put_device(&rdev->dev);
@@ -2303,19 +2352,19 @@
/* Free the GPIO only in case of no use */
list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) {
- if (pin->gpiod == rdev->ena_pin->gpiod) {
- if (pin->request_count <= 1) {
- pin->request_count = 0;
- gpiod_put(pin->gpiod);
- list_del(&pin->list);
- kfree(pin);
- rdev->ena_pin = NULL;
- return;
- } else {
- pin->request_count--;
- }
- }
+ if (pin != rdev->ena_pin)
+ continue;
+
+ if (--pin->request_count)
+ break;
+
+ gpiod_put(pin->gpiod);
+ list_del(&pin->list);
+ kfree(pin);
+ break;
}
+
+ rdev->ena_pin = NULL;
}
/**
@@ -2394,6 +2443,37 @@
udelay(us);
}
+/**
+ * _regulator_check_status_enabled
+ *
+ * A helper function to check if the regulator status can be interpreted
+ * as 'regulator is enabled'.
+ * @rdev: the regulator device to check
+ *
+ * Return:
+ * * 1 - if status shows regulator is in enabled state
+ * * 0 - if not enabled state
+ * * Error Value - as received from ops->get_status()
+ */
+static inline int _regulator_check_status_enabled(struct regulator_dev *rdev)
+{
+ int ret = rdev->desc->ops->get_status(rdev);
+
+ if (ret < 0) {
+ rdev_info(rdev, "get_status returned error: %d\n", ret);
+ return ret;
+ }
+
+ switch (ret) {
+ case REGULATOR_STATUS_OFF:
+ case REGULATOR_STATUS_ERROR:
+ case REGULATOR_STATUS_UNDEFINED:
+ return 0;
+ default:
+ return 1;
+ }
+}
+
static int _regulator_do_enable(struct regulator_dev *rdev)
{
int ret, delay;
@@ -2403,7 +2483,7 @@
if (ret >= 0) {
delay = ret;
} else {
- rdev_warn(rdev, "enable_time() failed: %d\n", ret);
+ rdev_warn(rdev, "enable_time() failed: %pe\n", ERR_PTR(ret));
delay = 0;
}
@@ -2454,7 +2534,37 @@
* together. */
trace_regulator_enable_delay(rdev_get_name(rdev));
- _regulator_enable_delay(delay);
+ /* If poll_enabled_time is set, poll upto the delay calculated
+ * above, delaying poll_enabled_time uS to check if the regulator
+ * actually got enabled.
+ * If the regulator isn't enabled after enable_delay has
+ * expired, return -ETIMEDOUT.
+ */
+ if (rdev->desc->poll_enabled_time) {
+ unsigned int time_remaining = delay;
+
+ while (time_remaining > 0) {
+ _regulator_enable_delay(rdev->desc->poll_enabled_time);
+
+ if (rdev->desc->ops->get_status) {
+ ret = _regulator_check_status_enabled(rdev);
+ if (ret < 0)
+ return ret;
+ else if (ret)
+ break;
+ } else if (rdev->desc->ops->is_enabled(rdev))
+ break;
+
+ time_remaining -= rdev->desc->poll_enabled_time;
+ }
+
+ if (time_remaining <= 0) {
+ rdev_err(rdev, "Enabled check timed out\n");
+ return -ETIMEDOUT;
+ }
+ } else {
+ _regulator_enable_delay(delay);
+ }
trace_regulator_enable_complete(rdev_get_name(rdev));
@@ -2562,7 +2672,7 @@
_notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE,
NULL);
} else if (ret < 0) {
- rdev_err(rdev, "is_enabled() failed: %d\n", ret);
+ rdev_err(rdev, "is_enabled() failed: %pe\n", ERR_PTR(ret));
goto err_consumer_disable;
}
/* Fallthrough on positive return values - already enabled */
@@ -2664,7 +2774,7 @@
ret = _regulator_do_disable(rdev);
if (ret < 0) {
- rdev_err(rdev, "failed to disable\n");
+ rdev_err(rdev, "failed to disable: %pe\n", ERR_PTR(ret));
_notifier_call_chain(rdev,
REGULATOR_EVENT_ABORT_DISABLE,
NULL);
@@ -2731,7 +2841,7 @@
ret = _regulator_do_disable(rdev);
if (ret < 0) {
- rdev_err(rdev, "failed to force disable\n");
+ rdev_err(rdev, "failed to force disable: %pe\n", ERR_PTR(ret));
_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
REGULATOR_EVENT_ABORT_DISABLE, NULL);
return ret;
@@ -2810,7 +2920,8 @@
for (i = 0; i < count; i++) {
ret = _regulator_disable(regulator);
if (ret != 0)
- rdev_err(rdev, "Deferred disable failed: %d\n", ret);
+ rdev_err(rdev, "Deferred disable failed: %pe\n",
+ ERR_PTR(ret));
}
}
WARN_ON(!total_count);
@@ -3003,7 +3114,7 @@
*vsel_reg = rdev->desc->vsel_reg;
*vsel_mask = rdev->desc->vsel_mask;
- return 0;
+ return 0;
}
EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register);
@@ -3335,7 +3446,7 @@
}
if (delay < 0) {
- rdev_warn(rdev, "failed to get delay: %d\n", delay);
+ rdev_warn(rdev, "failed to get delay: %pe\n", ERR_PTR(delay));
delay = 0;
}
@@ -3487,8 +3598,8 @@
ret = regulator_set_voltage_unlocked(rdev->supply,
best_supply_uV, INT_MAX, state);
if (ret) {
- dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n",
- ret);
+ dev_err(&rdev->dev, "Failed to increase supply voltage: %pe\n",
+ ERR_PTR(ret));
goto out;
}
}
@@ -3505,8 +3616,8 @@
ret = regulator_set_voltage_unlocked(rdev->supply,
best_supply_uV, INT_MAX, state);
if (ret)
- dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n",
- ret);
+ dev_warn(&rdev->dev, "Failed to decrease supply voltage: %pe\n",
+ ERR_PTR(ret));
/* No need to fail here */
ret = 0;
}
@@ -3689,36 +3800,19 @@
return done;
}
-static int regulator_balance_voltage(struct regulator_dev *rdev,
- suspend_state_t state)
+int regulator_do_balance_voltage(struct regulator_dev *rdev,
+ suspend_state_t state, bool skip_coupled)
{
struct regulator_dev **c_rdevs;
struct regulator_dev *best_rdev;
struct coupling_desc *c_desc = &rdev->coupling_desc;
- struct regulator_coupler *coupler = c_desc->coupler;
int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev;
unsigned int delta, best_delta;
unsigned long c_rdev_done = 0;
bool best_c_rdev_done;
c_rdevs = c_desc->coupled_rdevs;
- n_coupled = c_desc->n_coupled;
-
- /*
- * If system is in a state other than PM_SUSPEND_ON, don't check
- * other coupled regulators.
- */
- if (state != PM_SUSPEND_ON)
- n_coupled = 1;
-
- if (c_desc->n_resolved < n_coupled) {
- rdev_err(rdev, "Not all coupled regulators registered\n");
- return -EPERM;
- }
-
- /* Invoke custom balancer for customized couplers */
- if (coupler && coupler->balance_voltage)
- return coupler->balance_voltage(coupler, rdev, state);
+ n_coupled = skip_coupled ? 1 : c_desc->n_coupled;
/*
* Find the best possible voltage change on each loop. Leave the loop
@@ -3789,6 +3883,32 @@
return ret;
}
+static int regulator_balance_voltage(struct regulator_dev *rdev,
+ suspend_state_t state)
+{
+ struct coupling_desc *c_desc = &rdev->coupling_desc;
+ struct regulator_coupler *coupler = c_desc->coupler;
+ bool skip_coupled = false;
+
+ /*
+ * If system is in a state other than PM_SUSPEND_ON, don't check
+ * other coupled regulators.
+ */
+ if (state != PM_SUSPEND_ON)
+ skip_coupled = true;
+
+ if (c_desc->n_resolved < c_desc->n_coupled) {
+ rdev_err(rdev, "Not all coupled regulators registered\n");
+ return -EPERM;
+ }
+
+ /* Invoke custom balancer for customized couplers */
+ if (coupler && coupler->balance_voltage)
+ return coupler->balance_voltage(coupler, rdev, state);
+
+ return regulator_do_balance_voltage(rdev, state, skip_coupled);
+}
+
/**
* regulator_set_voltage - set regulator output voltage
* @regulator: regulator source
@@ -4361,6 +4481,7 @@
int regulator_allow_bypass(struct regulator *regulator, bool enable)
{
struct regulator_dev *rdev = regulator->rdev;
+ const char *name = rdev_get_name(rdev);
int ret = 0;
if (!rdev->desc->ops->set_bypass)
@@ -4375,18 +4496,26 @@
rdev->bypass_count++;
if (rdev->bypass_count == rdev->open_count) {
+ trace_regulator_bypass_enable(name);
+
ret = rdev->desc->ops->set_bypass(rdev, enable);
if (ret != 0)
rdev->bypass_count--;
+ else
+ trace_regulator_bypass_enable_complete(name);
}
} else if (!enable && regulator->bypass) {
rdev->bypass_count--;
if (rdev->bypass_count != rdev->open_count) {
+ trace_regulator_bypass_disable(name);
+
ret = rdev->desc->ops->set_bypass(rdev, enable);
if (ret != 0)
rdev->bypass_count++;
+ else
+ trace_regulator_bypass_disable_complete(name);
}
}
@@ -4476,8 +4605,8 @@
err:
if (ret != -EPROBE_DEFER)
- dev_err(dev, "Failed to get supply '%s': %d\n",
- consumers[i].supply, ret);
+ dev_err(dev, "Failed to get supply '%s': %pe\n",
+ consumers[i].supply, ERR_PTR(ret));
else
dev_dbg(dev, "Failed to get supply '%s', deferring\n",
consumers[i].supply);
@@ -4535,8 +4664,8 @@
err:
for (i = 0; i < num_consumers; i++) {
if (consumers[i].ret < 0)
- pr_err("Failed to enable %s: %d\n", consumers[i].supply,
- consumers[i].ret);
+ pr_err("Failed to enable %s: %pe\n", consumers[i].supply,
+ ERR_PTR(consumers[i].ret));
else
regulator_disable(consumers[i].consumer);
}
@@ -4572,12 +4701,12 @@
return 0;
err:
- pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret);
+ pr_err("Failed to disable %s: %pe\n", consumers[i].supply, ERR_PTR(ret));
for (++i; i < num_consumers; ++i) {
r = regulator_enable(consumers[i].consumer);
if (r != 0)
- pr_err("Failed to re-enable %s: %d\n",
- consumers[i].supply, r);
+ pr_err("Failed to re-enable %s: %pe\n",
+ consumers[i].supply, ERR_PTR(r));
}
return ret;
@@ -4645,14 +4774,11 @@
* @data: callback-specific data.
*
* Called by regulator drivers to notify clients a regulator event has
- * occurred. We also notify regulator clients downstream.
- * Note lock must be held by caller.
+ * occurred.
*/
int regulator_notifier_call_chain(struct regulator_dev *rdev,
unsigned long event, void *data)
{
- lockdep_assert_held_once(&rdev->mutex.base);
-
_notifier_call_chain(rdev, event, data);
return NOTIFY_DONE;
@@ -4959,8 +5085,8 @@
if (coupler && coupler->detach_regulator) {
err = coupler->detach_regulator(coupler, rdev);
if (err)
- rdev_err(rdev, "failed to detach from coupler: %d\n",
- err);
+ rdev_err(rdev, "failed to detach from coupler: %pe\n",
+ ERR_PTR(err));
}
kfree(rdev->coupling_desc.coupled_rdevs);
@@ -4969,20 +5095,20 @@
static int regulator_init_coupling(struct regulator_dev *rdev)
{
+ struct regulator_dev **coupled;
int err, n_phandles;
- size_t alloc_size;
if (!IS_ENABLED(CONFIG_OF))
n_phandles = 0;
else
n_phandles = of_get_n_coupled(rdev);
- alloc_size = sizeof(*rdev) * (n_phandles + 1);
-
- rdev->coupling_desc.coupled_rdevs = kzalloc(alloc_size, GFP_KERNEL);
- if (!rdev->coupling_desc.coupled_rdevs)
+ coupled = kcalloc(n_phandles + 1, sizeof(*coupled), GFP_KERNEL);
+ if (!coupled)
return -ENOMEM;
+ rdev->coupling_desc.coupled_rdevs = coupled;
+
/*
* Every regulator should always have coupling descriptor filled with
* at least pointer to itself.
@@ -5004,7 +5130,7 @@
if (IS_ERR(rdev->coupling_desc.coupler)) {
err = PTR_ERR(rdev->coupling_desc.coupler);
- rdev_err(rdev, "failed to get coupler: %d\n", err);
+ rdev_err(rdev, "failed to get coupler: %pe\n", ERR_PTR(err));
return err;
}
@@ -5020,6 +5146,12 @@
return -EPERM;
}
+ if (!rdev->constraints->always_on) {
+ rdev_err(rdev,
+ "Coupling of a non always-on regulator is unimplemented\n");
+ return -ENOTSUPP;
+ }
+
return 0;
}
@@ -5160,8 +5292,8 @@
if (config->ena_gpiod) {
ret = regulator_ena_gpio_request(rdev, config);
if (ret != 0) {
- rdev_err(rdev, "Failed to request enable GPIO: %d\n",
- ret);
+ rdev_err(rdev, "Failed to request enable GPIO: %pe\n",
+ ERR_PTR(ret));
goto clean;
}
/* The regulator core took over the GPIO descriptor */
@@ -5318,9 +5450,14 @@
struct regulator_dev *rdev = dev_to_rdev(dev);
suspend_state_t state = pm_suspend_target_state;
int ret;
+ const struct regulator_state *rstate;
+
+ rstate = regulator_get_suspend_state_check(rdev, state);
+ if (!rstate)
+ return 0;
regulator_lock(rdev);
- ret = suspend_set_state(rdev, state);
+ ret = __suspend_set_state(rdev, rstate);
regulator_unlock(rdev);
return ret;
@@ -5337,11 +5474,14 @@
if (rstate == NULL)
return 0;
+ /* Avoid grabbing the lock if we don't need to */
+ if (!rdev->desc->ops->resume)
+ return 0;
+
regulator_lock(rdev);
- if (rdev->desc->ops->resume &&
- (rstate->enabled == ENABLE_IN_SUSPEND ||
- rstate->enabled == DISABLE_IN_SUSPEND))
+ if (rstate->enabled == ENABLE_IN_SUSPEND ||
+ rstate->enabled == DISABLE_IN_SUSPEND)
ret = rdev->desc->ops->resume(rdev);
regulator_unlock(rdev);
@@ -5535,6 +5675,7 @@
seq_printf(s, "%*s%-*s ",
(level + 1) * 3 + 1, "",
30 - (level + 1) * 3,
+ consumer->supply_name ? consumer->supply_name :
consumer->dev ? dev_name(consumer->dev) : "deviceless");
switch (rdev->desc->type) {
@@ -5721,9 +5862,8 @@
static int regulator_late_cleanup(struct device *dev, void *data)
{
struct regulator_dev *rdev = dev_to_rdev(dev);
- const struct regulator_ops *ops = rdev->desc->ops;
struct regulation_constraints *c = rdev->constraints;
- int enabled, ret;
+ int ret;
if (c && c->always_on)
return 0;
@@ -5736,13 +5876,8 @@
if (rdev->use_count)
goto unlock;
- /* If we can't read the status assume it's on. */
- if (ops->is_enabled)
- enabled = ops->is_enabled(rdev);
- else
- enabled = 1;
-
- if (!enabled)
+ /* If reading the status failed, assume that it's off. */
+ if (_regulator_is_enabled(rdev) <= 0)
goto unlock;
if (have_full_constraints()) {
@@ -5751,7 +5886,7 @@
rdev_info(rdev, "disabling\n");
ret = _regulator_do_disable(rdev);
if (ret != 0)
- rdev_err(rdev, "couldn't disable: %d\n", ret);
+ rdev_err(rdev, "couldn't disable: %pe\n", ERR_PTR(ret));
} else {
/* The intention is that in future we will
* assume that full constraints are provided
diff --git a/drivers/regulator/cpcap-regulator.c b/drivers/regulator/cpcap-regulator.c
index f80781d..79b3eb3 100644
--- a/drivers/regulator/cpcap-regulator.c
+++ b/drivers/regulator/cpcap-regulator.c
@@ -89,7 +89,7 @@
*/
#define CPCAP_REG_OFF_MODE_SEC BIT(15)
-/**
+/*
* SoC specific configuration for CPCAP regulator. There are at least three
* different SoCs each with their own parameters: omap3, omap4 and tegra2.
*
@@ -169,7 +169,7 @@
static int cpcap_regulator_enable(struct regulator_dev *rdev)
{
struct cpcap_regulator *regulator = rdev_get_drvdata(rdev);
- int error, ignore;
+ int error;
error = regulator_enable_regmap(rdev);
if (error)
@@ -180,7 +180,7 @@
regulator->assign_mask,
regulator->assign_mask);
if (error)
- ignore = regulator_disable_regmap(rdev);
+ regulator_disable_regmap(rdev);
}
return error;
@@ -193,7 +193,7 @@
static int cpcap_regulator_disable(struct regulator_dev *rdev)
{
struct cpcap_regulator *regulator = rdev_get_drvdata(rdev);
- int error, ignore;
+ int error;
if (rdev->desc->enable_val & CPCAP_REG_OFF_MODE_SEC) {
error = regmap_update_bits(rdev->regmap, regulator->assign_reg,
@@ -204,9 +204,9 @@
error = regulator_disable_regmap(rdev);
if (error && (rdev->desc->enable_val & CPCAP_REG_OFF_MODE_SEC)) {
- ignore = regmap_update_bits(rdev->regmap, regulator->assign_reg,
- regulator->assign_mask,
- regulator->assign_mask);
+ regmap_update_bits(rdev->regmap, regulator->assign_reg,
+ regulator->assign_mask,
+ regulator->assign_mask);
}
return error;
@@ -256,7 +256,7 @@
CPCAP_BIT_AUDIO_LOW_PWR, value);
}
-static struct regulator_ops cpcap_regulator_ops = {
+static const struct regulator_ops cpcap_regulator_ops = {
.enable = cpcap_regulator_enable,
.disable = cpcap_regulator_disable,
.is_enabled = regulator_is_enabled_regmap,
@@ -325,7 +325,7 @@
static const unsigned int vusb_val_tbl[] = { 0, 3300000, };
static const unsigned int vaudio_val_tbl[] = { 0, 2775000, };
-/**
+/*
* SoC specific configuration for omap4. The data below is comes from Motorola
* Linux kernel tree. It's basically the values of cpcap_regltr_data,
* cpcap_regulator_mode_values and cpcap_regulator_off_mode_values, see
diff --git a/drivers/regulator/cros-ec-regulator.c b/drivers/regulator/cros-ec-regulator.c
new file mode 100644
index 0000000..c4754f3
--- /dev/null
+++ b/drivers/regulator/cros-ec-regulator.c
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright 2020 Google LLC.
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_data/cros_ec_proto.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/slab.h>
+
+struct cros_ec_regulator_data {
+ struct regulator_desc desc;
+ struct regulator_dev *dev;
+ struct cros_ec_device *ec_dev;
+
+ u32 index;
+
+ u16 *voltages_mV;
+ u16 num_voltages;
+};
+
+static int cros_ec_cmd(struct cros_ec_device *ec, u32 version, u32 command,
+ void *outdata, u32 outsize, void *indata, u32 insize)
+{
+ struct cros_ec_command *msg;
+ int ret;
+
+ msg = kzalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ msg->version = version;
+ msg->command = command;
+ msg->outsize = outsize;
+ msg->insize = insize;
+
+ if (outdata && outsize > 0)
+ memcpy(msg->data, outdata, outsize);
+
+ ret = cros_ec_cmd_xfer_status(ec, msg);
+ if (ret < 0)
+ goto cleanup;
+
+ if (insize)
+ memcpy(indata, msg->data, insize);
+
+cleanup:
+ kfree(msg);
+ return ret;
+}
+
+static int cros_ec_regulator_enable(struct regulator_dev *dev)
+{
+ struct cros_ec_regulator_data *data = rdev_get_drvdata(dev);
+ struct ec_params_regulator_enable cmd = {
+ .index = data->index,
+ .enable = 1,
+ };
+
+ return cros_ec_cmd(data->ec_dev, 0, EC_CMD_REGULATOR_ENABLE, &cmd,
+ sizeof(cmd), NULL, 0);
+}
+
+static int cros_ec_regulator_disable(struct regulator_dev *dev)
+{
+ struct cros_ec_regulator_data *data = rdev_get_drvdata(dev);
+ struct ec_params_regulator_enable cmd = {
+ .index = data->index,
+ .enable = 0,
+ };
+
+ return cros_ec_cmd(data->ec_dev, 0, EC_CMD_REGULATOR_ENABLE, &cmd,
+ sizeof(cmd), NULL, 0);
+}
+
+static int cros_ec_regulator_is_enabled(struct regulator_dev *dev)
+{
+ struct cros_ec_regulator_data *data = rdev_get_drvdata(dev);
+ struct ec_params_regulator_is_enabled cmd = {
+ .index = data->index,
+ };
+ struct ec_response_regulator_is_enabled resp;
+ int ret;
+
+ ret = cros_ec_cmd(data->ec_dev, 0, EC_CMD_REGULATOR_IS_ENABLED, &cmd,
+ sizeof(cmd), &resp, sizeof(resp));
+ if (ret < 0)
+ return ret;
+ return resp.enabled;
+}
+
+static int cros_ec_regulator_list_voltage(struct regulator_dev *dev,
+ unsigned int selector)
+{
+ struct cros_ec_regulator_data *data = rdev_get_drvdata(dev);
+
+ if (selector >= data->num_voltages)
+ return -EINVAL;
+
+ return data->voltages_mV[selector] * 1000;
+}
+
+static int cros_ec_regulator_get_voltage(struct regulator_dev *dev)
+{
+ struct cros_ec_regulator_data *data = rdev_get_drvdata(dev);
+ struct ec_params_regulator_get_voltage cmd = {
+ .index = data->index,
+ };
+ struct ec_response_regulator_get_voltage resp;
+ int ret;
+
+ ret = cros_ec_cmd(data->ec_dev, 0, EC_CMD_REGULATOR_GET_VOLTAGE, &cmd,
+ sizeof(cmd), &resp, sizeof(resp));
+ if (ret < 0)
+ return ret;
+ return resp.voltage_mv * 1000;
+}
+
+static int cros_ec_regulator_set_voltage(struct regulator_dev *dev, int min_uV,
+ int max_uV, unsigned int *selector)
+{
+ struct cros_ec_regulator_data *data = rdev_get_drvdata(dev);
+ int min_mV = DIV_ROUND_UP(min_uV, 1000);
+ int max_mV = max_uV / 1000;
+ struct ec_params_regulator_set_voltage cmd = {
+ .index = data->index,
+ .min_mv = min_mV,
+ .max_mv = max_mV,
+ };
+
+ /*
+ * This can happen when the given range [min_uV, max_uV] doesn't
+ * contain any voltage that can be represented exactly in mV.
+ */
+ if (min_mV > max_mV)
+ return -EINVAL;
+
+ return cros_ec_cmd(data->ec_dev, 0, EC_CMD_REGULATOR_SET_VOLTAGE, &cmd,
+ sizeof(cmd), NULL, 0);
+}
+
+static const struct regulator_ops cros_ec_regulator_voltage_ops = {
+ .enable = cros_ec_regulator_enable,
+ .disable = cros_ec_regulator_disable,
+ .is_enabled = cros_ec_regulator_is_enabled,
+ .list_voltage = cros_ec_regulator_list_voltage,
+ .get_voltage = cros_ec_regulator_get_voltage,
+ .set_voltage = cros_ec_regulator_set_voltage,
+};
+
+static int cros_ec_regulator_init_info(struct device *dev,
+ struct cros_ec_regulator_data *data)
+{
+ struct ec_params_regulator_get_info cmd = {
+ .index = data->index,
+ };
+ struct ec_response_regulator_get_info resp;
+ int ret;
+
+ ret = cros_ec_cmd(data->ec_dev, 0, EC_CMD_REGULATOR_GET_INFO, &cmd,
+ sizeof(cmd), &resp, sizeof(resp));
+ if (ret < 0)
+ return ret;
+
+ data->num_voltages =
+ min_t(u16, ARRAY_SIZE(resp.voltages_mv), resp.num_voltages);
+ data->voltages_mV =
+ devm_kmemdup(dev, resp.voltages_mv,
+ sizeof(u16) * data->num_voltages, GFP_KERNEL);
+ if (!data->voltages_mV)
+ return -ENOMEM;
+
+ data->desc.n_voltages = data->num_voltages;
+
+ /* Make sure the returned name is always a valid string */
+ resp.name[ARRAY_SIZE(resp.name) - 1] = '\0';
+ data->desc.name = devm_kstrdup(dev, resp.name, GFP_KERNEL);
+ if (!data->desc.name)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int cros_ec_regulator_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct cros_ec_regulator_data *drvdata;
+ struct regulator_init_data *init_data;
+ struct regulator_config cfg = {};
+ struct regulator_desc *desc;
+ int ret;
+
+ drvdata = devm_kzalloc(
+ &pdev->dev, sizeof(struct cros_ec_regulator_data), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ drvdata->ec_dev = dev_get_drvdata(dev->parent);
+ desc = &drvdata->desc;
+
+ init_data = of_get_regulator_init_data(dev, np, desc);
+ if (!init_data)
+ return -EINVAL;
+
+ ret = of_property_read_u32(np, "reg", &drvdata->index);
+ if (ret < 0)
+ return ret;
+
+ desc->owner = THIS_MODULE;
+ desc->type = REGULATOR_VOLTAGE;
+ desc->ops = &cros_ec_regulator_voltage_ops;
+
+ ret = cros_ec_regulator_init_info(dev, drvdata);
+ if (ret < 0)
+ return ret;
+
+ cfg.dev = &pdev->dev;
+ cfg.init_data = init_data;
+ cfg.driver_data = drvdata;
+ cfg.of_node = np;
+
+ drvdata->dev = devm_regulator_register(dev, &drvdata->desc, &cfg);
+ if (IS_ERR(drvdata->dev)) {
+ ret = PTR_ERR(drvdata->dev);
+ dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, drvdata);
+
+ return 0;
+}
+
+static const struct of_device_id regulator_cros_ec_of_match[] = {
+ { .compatible = "google,cros-ec-regulator", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, regulator_cros_ec_of_match);
+
+static struct platform_driver cros_ec_regulator_driver = {
+ .probe = cros_ec_regulator_probe,
+ .driver = {
+ .name = "cros-ec-regulator",
+ .of_match_table = regulator_cros_ec_of_match,
+ },
+};
+
+module_platform_driver(cros_ec_regulator_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ChromeOS EC controlled regulator");
+MODULE_AUTHOR("Pi-Hsun Shih <pihsun@chromium.org>");
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x-regulator.c
similarity index 99%
rename from drivers/regulator/da903x.c
rename to drivers/regulator/da903x-regulator.c
index 5493c3a..770e694 100644
--- a/drivers/regulator/da903x.c
+++ b/drivers/regulator/da903x-regulator.c
@@ -248,7 +248,7 @@
return ret;
}
-static const struct regulator_linear_range da9034_ldo12_ranges[] = {
+static const struct linear_range da9034_ldo12_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 50000),
REGULATOR_LINEAR_RANGE(2700000, 8, 15, 50000),
};
diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c
index c025ccb..73ff5fc 100644
--- a/drivers/regulator/da9055-regulator.c
+++ b/drivers/regulator/da9055-regulator.c
@@ -485,10 +485,8 @@
{
struct da9055_regulator *regulator = data;
- regulator_lock(regulator->rdev);
regulator_notifier_call_chain(regulator->rdev,
REGULATOR_EVENT_OVER_CURRENT, NULL);
- regulator_unlock(regulator->rdev);
return IRQ_HANDLED;
}
diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c
index 710e670..1a63240 100644
--- a/drivers/regulator/da9062-regulator.c
+++ b/drivers/regulator/da9062-regulator.c
@@ -16,6 +16,7 @@
#include <linux/regulator/of_regulator.h>
#include <linux/mfd/da9062/core.h>
#include <linux/mfd/da9062/registers.h>
+#include <dt-bindings/regulator/dlg,da9063-regulator.h>
/* Regulator IDs */
enum {
@@ -72,15 +73,7 @@
int irq_ldo_lim;
unsigned n_regulators;
/* Array size to be defined during init. Keep at end. */
- struct da9062_regulator regulator[0];
-};
-
-/* BUCK modes */
-enum {
- BUCK_MODE_MANUAL, /* 0 */
- BUCK_MODE_SLEEP, /* 1 */
- BUCK_MODE_SYNC, /* 2 */
- BUCK_MODE_AUTO /* 3 */
+ struct da9062_regulator regulator[];
};
/* Regulator operations */
@@ -105,6 +98,20 @@
2300000, 2400000, 2500000, 2600000, 2700000, 2800000, 2900000, 3000000
};
+static unsigned int da9062_map_buck_mode(unsigned int mode)
+{
+ switch (mode) {
+ case DA9063_BUCK_MODE_SLEEP:
+ return REGULATOR_MODE_STANDBY;
+ case DA9063_BUCK_MODE_SYNC:
+ return REGULATOR_MODE_FAST;
+ case DA9063_BUCK_MODE_AUTO:
+ return REGULATOR_MODE_NORMAL;
+ default:
+ return REGULATOR_MODE_INVALID;
+ }
+}
+
static int da9062_buck_set_mode(struct regulator_dev *rdev, unsigned mode)
{
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
@@ -112,13 +119,13 @@
switch (mode) {
case REGULATOR_MODE_FAST:
- val = BUCK_MODE_SYNC;
+ val = DA9063_BUCK_MODE_SYNC;
break;
case REGULATOR_MODE_NORMAL:
- val = BUCK_MODE_AUTO;
+ val = DA9063_BUCK_MODE_AUTO;
break;
case REGULATOR_MODE_STANDBY:
- val = BUCK_MODE_SLEEP;
+ val = DA9063_BUCK_MODE_SLEEP;
break;
default:
return -EINVAL;
@@ -136,7 +143,7 @@
static unsigned da9062_buck_get_mode(struct regulator_dev *rdev)
{
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
- unsigned int val, mode = 0;
+ unsigned int val;
int ret;
ret = regmap_field_read(regl->mode, &val);
@@ -145,15 +152,13 @@
switch (val) {
default:
- case BUCK_MODE_MANUAL:
- mode = REGULATOR_MODE_FAST | REGULATOR_MODE_STANDBY;
/* Sleep flag bit decides the mode */
break;
- case BUCK_MODE_SLEEP:
+ case DA9063_BUCK_MODE_SLEEP:
return REGULATOR_MODE_STANDBY;
- case BUCK_MODE_SYNC:
+ case DA9063_BUCK_MODE_SYNC:
return REGULATOR_MODE_FAST;
- case BUCK_MODE_AUTO:
+ case DA9063_BUCK_MODE_AUTO:
return REGULATOR_MODE_NORMAL;
}
@@ -162,11 +167,9 @@
return 0;
if (val)
- mode &= REGULATOR_MODE_STANDBY;
+ return REGULATOR_MODE_STANDBY;
else
- mode &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST;
-
- return mode;
+ return REGULATOR_MODE_FAST;
}
/*
@@ -282,13 +285,13 @@
switch (mode) {
case REGULATOR_MODE_FAST:
- val = BUCK_MODE_SYNC;
+ val = DA9063_BUCK_MODE_SYNC;
break;
case REGULATOR_MODE_NORMAL:
- val = BUCK_MODE_AUTO;
+ val = DA9063_BUCK_MODE_AUTO;
break;
case REGULATOR_MODE_STANDBY:
- val = BUCK_MODE_SLEEP;
+ val = DA9063_BUCK_MODE_SLEEP;
break;
default:
return -EINVAL;
@@ -371,6 +374,7 @@
.desc.vsel_reg = DA9062AA_VBUCK1_A,
.desc.vsel_mask = DA9062AA_VBUCK1_A_MASK,
.desc.linear_min_sel = 0,
+ .desc.of_map_mode = da9062_map_buck_mode,
.sleep = REG_FIELD(DA9062AA_VBUCK1_A,
__builtin_ffs((int)DA9062AA_BUCK1_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
@@ -407,6 +411,7 @@
.desc.vsel_reg = DA9062AA_VBUCK3_A,
.desc.vsel_mask = DA9062AA_VBUCK3_A_MASK,
.desc.linear_min_sel = 0,
+ .desc.of_map_mode = da9062_map_buck_mode,
.sleep = REG_FIELD(DA9062AA_VBUCK3_A,
__builtin_ffs((int)DA9062AA_BUCK3_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
@@ -443,6 +448,7 @@
.desc.vsel_reg = DA9062AA_VBUCK4_A,
.desc.vsel_mask = DA9062AA_VBUCK4_A_MASK,
.desc.linear_min_sel = 0,
+ .desc.of_map_mode = da9062_map_buck_mode,
.sleep = REG_FIELD(DA9062AA_VBUCK4_A,
__builtin_ffs((int)DA9062AA_BUCK4_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
@@ -615,6 +621,7 @@
.desc.vsel_reg = DA9062AA_VBUCK1_A,
.desc.vsel_mask = DA9062AA_VBUCK1_A_MASK,
.desc.linear_min_sel = 0,
+ .desc.of_map_mode = da9062_map_buck_mode,
.sleep = REG_FIELD(DA9062AA_VBUCK1_A,
__builtin_ffs((int)DA9062AA_BUCK1_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
@@ -651,6 +658,7 @@
.desc.vsel_reg = DA9062AA_VBUCK2_A,
.desc.vsel_mask = DA9062AA_VBUCK2_A_MASK,
.desc.linear_min_sel = 0,
+ .desc.of_map_mode = da9062_map_buck_mode,
.sleep = REG_FIELD(DA9062AA_VBUCK2_A,
__builtin_ffs((int)DA9062AA_BUCK2_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
@@ -687,6 +695,7 @@
.desc.vsel_reg = DA9062AA_VBUCK3_A,
.desc.vsel_mask = DA9062AA_VBUCK3_A_MASK,
.desc.linear_min_sel = 0,
+ .desc.of_map_mode = da9062_map_buck_mode,
.sleep = REG_FIELD(DA9062AA_VBUCK3_A,
__builtin_ffs((int)DA9062AA_BUCK3_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
@@ -723,6 +732,7 @@
.desc.vsel_reg = DA9062AA_VBUCK4_A,
.desc.vsel_mask = DA9062AA_VBUCK4_A_MASK,
.desc.linear_min_sel = 0,
+ .desc.of_map_mode = da9062_map_buck_mode,
.sleep = REG_FIELD(DA9062AA_VBUCK4_A,
__builtin_ffs((int)DA9062AA_BUCK4_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
@@ -897,10 +907,8 @@
continue;
if (BIT(regl->info->oc_event.lsb) & bits) {
- regulator_lock(regl->rdev);
regulator_notifier_call_chain(regl->rdev,
REGULATOR_EVENT_OVER_CURRENT, NULL);
- regulator_unlock(regl->rdev);
handled = IRQ_HANDLED;
}
}
@@ -942,8 +950,7 @@
regulators->n_regulators = max_regulators;
platform_set_drvdata(pdev, regulators);
- n = 0;
- while (n < regulators->n_regulators) {
+ for (n = 0; n < regulators->n_regulators; n++) {
/* Initialise regulator structure */
regl = ®ulators->regulator[n];
regl->hw = chip;
@@ -1002,8 +1009,6 @@
regl->desc.name);
return PTR_ERR(regl->rdev);
}
-
- n++;
}
/* LDOs overcurrent event support */
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index 28b1b20..cf7d534 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -66,7 +66,7 @@
};
struct da9063_regulators_pdata {
- unsigned n_regulators;
+ unsigned int n_regulators;
struct da9063_regulator_data *regulator_data;
};
@@ -100,6 +100,7 @@
.desc.vsel_mask = DA9063_V##regl_name##_MASK, \
.desc.linear_min_sel = DA9063_V##regl_name##_BIAS, \
.sleep = BFIELD(DA9063_REG_V##regl_name##_A, DA9063_LDO_SL), \
+ .suspend = BFIELD(DA9063_REG_##regl_name##_CONT, DA9063_LDO_CONF), \
.suspend_sleep = BFIELD(DA9063_REG_V##regl_name##_B, DA9063_LDO_SL), \
.suspend_vsel_reg = DA9063_REG_V##regl_name##_B
@@ -124,6 +125,7 @@
.desc.vsel_mask = DA9063_VBUCK_MASK, \
.desc.linear_min_sel = DA9063_VBUCK_BIAS, \
.sleep = BFIELD(DA9063_REG_V##regl_name##_A, DA9063_BUCK_SL), \
+ .suspend = BFIELD(DA9063_REG_##regl_name##_CONT, DA9063_BUCK_CONF), \
.suspend_sleep = BFIELD(DA9063_REG_V##regl_name##_B, DA9063_BUCK_SL), \
.suspend_vsel_reg = DA9063_REG_V##regl_name##_B, \
.mode = BFIELD(DA9063_REG_##regl_name##_CFG, DA9063_BUCK_MODE_MASK)
@@ -131,7 +133,7 @@
/* Defines asignment of regulators info table to chip model */
struct da9063_dev_model {
const struct da9063_regulator_info *regulator_info;
- unsigned n_regulators;
+ unsigned int n_regulators;
enum da9063_type type;
};
@@ -150,9 +152,9 @@
/* Encapsulates all information for the regulators driver */
struct da9063_regulators {
- unsigned n_regulators;
+ unsigned int n_regulators;
/* Array size to be defined during init. Keep at end. */
- struct da9063_regulator regulator[0];
+ struct da9063_regulator regulator[];
};
/* BUCK modes for DA9063 */
@@ -165,38 +167,46 @@
/* Regulator operations */
-/* Current limits array (in uA) for BCORE1, BCORE2, BPRO.
- Entry indexes corresponds to register values. */
+/*
+ * Current limits array (in uA) for BCORE1, BCORE2, BPRO.
+ * Entry indexes corresponds to register values.
+ */
static const unsigned int da9063_buck_a_limits[] = {
500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000,
1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000, 2000000
};
-/* Current limits array (in uA) for BMEM, BIO, BPERI.
- Entry indexes corresponds to register values. */
+/*
+ * Current limits array (in uA) for BMEM, BIO, BPERI.
+ * Entry indexes corresponds to register values.
+ */
static const unsigned int da9063_buck_b_limits[] = {
1500000, 1600000, 1700000, 1800000, 1900000, 2000000, 2100000, 2200000,
2300000, 2400000, 2500000, 2600000, 2700000, 2800000, 2900000, 3000000
};
-/* Current limits array (in uA) for merged BCORE1 and BCORE2.
- Entry indexes corresponds to register values. */
+/*
+ * Current limits array (in uA) for merged BCORE1 and BCORE2.
+ * Entry indexes corresponds to register values.
+ */
static const unsigned int da9063_bcores_merged_limits[] = {
1000000, 1200000, 1400000, 1600000, 1800000, 2000000, 2200000, 2400000,
2600000, 2800000, 3000000, 3200000, 3400000, 3600000, 3800000, 4000000
};
-/* Current limits array (in uA) for merged BMEM and BIO.
- Entry indexes corresponds to register values. */
+/*
+ * Current limits array (in uA) for merged BMEM and BIO.
+ * Entry indexes corresponds to register values.
+ */
static const unsigned int da9063_bmem_bio_merged_limits[] = {
3000000, 3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000,
4600000, 4800000, 5000000, 5200000, 5400000, 5600000, 5800000, 6000000
};
-static int da9063_buck_set_mode(struct regulator_dev *rdev, unsigned mode)
+static int da9063_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
- unsigned val;
+ unsigned int val;
switch (mode) {
case REGULATOR_MODE_FAST:
@@ -221,11 +231,10 @@
* There are 3 modes to map to: FAST, NORMAL, and STANDBY.
*/
-static unsigned da9063_buck_get_mode(struct regulator_dev *rdev)
+static unsigned int da9063_buck_get_mode(struct regulator_dev *rdev)
{
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
- struct regmap_field *field;
- unsigned int val, mode = 0;
+ unsigned int val;
int ret;
ret = regmap_field_read(regl->mode, &val);
@@ -235,7 +244,6 @@
switch (val) {
default:
case BUCK_MODE_MANUAL:
- mode = REGULATOR_MODE_FAST | REGULATOR_MODE_STANDBY;
/* Sleep flag bit decides the mode */
break;
case BUCK_MODE_SLEEP:
@@ -246,27 +254,14 @@
return REGULATOR_MODE_NORMAL;
}
- /* Detect current regulator state */
- ret = regmap_field_read(regl->suspend, &val);
- if (ret < 0)
- return 0;
-
- /* Read regulator mode from proper register, depending on state */
- if (val)
- field = regl->suspend_sleep;
- else
- field = regl->sleep;
-
- ret = regmap_field_read(field, &val);
+ ret = regmap_field_read(regl->sleep, &val);
if (ret < 0)
return 0;
if (val)
- mode &= REGULATOR_MODE_STANDBY;
+ return REGULATOR_MODE_STANDBY;
else
- mode &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST;
-
- return mode;
+ return REGULATOR_MODE_FAST;
}
/*
@@ -274,10 +269,10 @@
* There are 2 modes to map to: NORMAL and STANDBY (sleep) for each state.
*/
-static int da9063_ldo_set_mode(struct regulator_dev *rdev, unsigned mode)
+static int da9063_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
- unsigned val;
+ unsigned int val;
switch (mode) {
case REGULATOR_MODE_NORMAL:
@@ -293,24 +288,12 @@
return regmap_field_write(regl->sleep, val);
}
-static unsigned da9063_ldo_get_mode(struct regulator_dev *rdev)
+static unsigned int da9063_ldo_get_mode(struct regulator_dev *rdev)
{
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
- struct regmap_field *field;
int ret, val;
- /* Detect current regulator state */
- ret = regmap_field_read(regl->suspend, &val);
- if (ret < 0)
- return 0;
-
- /* Read regulator mode from proper register, depending on state */
- if (val)
- field = regl->suspend_sleep;
- else
- field = regl->sleep;
-
- ret = regmap_field_read(field, &val);
+ ret = regmap_field_read(regl->sleep, &val);
if (ret < 0)
return 0;
@@ -386,7 +369,8 @@
return regmap_field_write(regl->suspend, 0);
}
-static int da9063_buck_set_suspend_mode(struct regulator_dev *rdev, unsigned mode)
+static int da9063_buck_set_suspend_mode(struct regulator_dev *rdev,
+ unsigned int mode)
{
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
int val;
@@ -408,10 +392,11 @@
return regmap_field_write(regl->mode, val);
}
-static int da9063_ldo_set_suspend_mode(struct regulator_dev *rdev, unsigned mode)
+static int da9063_ldo_set_suspend_mode(struct regulator_dev *rdev,
+ unsigned int mode)
{
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
- unsigned val;
+ unsigned int val;
switch (mode) {
case REGULATOR_MODE_NORMAL:
@@ -468,42 +453,36 @@
da9063_buck_a_limits,
DA9063_REG_BUCK_ILIM_C, DA9063_BCORE1_ILIM_MASK),
DA9063_BUCK_COMMON_FIELDS(BCORE1),
- .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBCORE1_SEL),
},
{
DA9063_BUCK(DA9063, BCORE2, 300, 10, 1570,
da9063_buck_a_limits,
DA9063_REG_BUCK_ILIM_C, DA9063_BCORE2_ILIM_MASK),
DA9063_BUCK_COMMON_FIELDS(BCORE2),
- .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBCORE2_SEL),
},
{
DA9063_BUCK(DA9063, BPRO, 530, 10, 1800,
da9063_buck_a_limits,
DA9063_REG_BUCK_ILIM_B, DA9063_BPRO_ILIM_MASK),
DA9063_BUCK_COMMON_FIELDS(BPRO),
- .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBPRO_SEL),
},
{
DA9063_BUCK(DA9063, BMEM, 800, 20, 3340,
da9063_buck_b_limits,
DA9063_REG_BUCK_ILIM_A, DA9063_BMEM_ILIM_MASK),
DA9063_BUCK_COMMON_FIELDS(BMEM),
- .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBMEM_SEL),
},
{
DA9063_BUCK(DA9063, BIO, 800, 20, 3340,
da9063_buck_b_limits,
DA9063_REG_BUCK_ILIM_A, DA9063_BIO_ILIM_MASK),
DA9063_BUCK_COMMON_FIELDS(BIO),
- .suspend = BFIELD(DA9063_REG_DVC_2, DA9063_VBIO_SEL),
},
{
DA9063_BUCK(DA9063, BPERI, 800, 20, 3340,
da9063_buck_b_limits,
DA9063_REG_BUCK_ILIM_B, DA9063_BPERI_ILIM_MASK),
DA9063_BUCK_COMMON_FIELDS(BPERI),
- .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBPERI_SEL),
},
{
DA9063_BUCK(DA9063, BCORES_MERGED, 300, 10, 1570,
@@ -511,7 +490,6 @@
DA9063_REG_BUCK_ILIM_C, DA9063_BCORE1_ILIM_MASK),
/* BCORES_MERGED uses the same register fields as BCORE1 */
DA9063_BUCK_COMMON_FIELDS(BCORE1),
- .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBCORE1_SEL),
},
{
DA9063_BUCK(DA9063, BMEM_BIO_MERGED, 800, 20, 3340,
@@ -519,59 +497,47 @@
DA9063_REG_BUCK_ILIM_A, DA9063_BMEM_ILIM_MASK),
/* BMEM_BIO_MERGED uses the same register fields as BMEM */
DA9063_BUCK_COMMON_FIELDS(BMEM),
- .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBMEM_SEL),
},
{
DA9063_LDO(DA9063, LDO3, 900, 20, 3440),
- .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO3_SEL),
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO3_LIM),
},
{
DA9063_LDO(DA9063, LDO7, 900, 50, 3600),
- .suspend = BFIELD(DA9063_REG_LDO7_CONT, DA9063_VLDO7_SEL),
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO7_LIM),
},
{
DA9063_LDO(DA9063, LDO8, 900, 50, 3600),
- .suspend = BFIELD(DA9063_REG_LDO8_CONT, DA9063_VLDO8_SEL),
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO8_LIM),
},
{
DA9063_LDO(DA9063, LDO9, 950, 50, 3600),
- .suspend = BFIELD(DA9063_REG_LDO9_CONT, DA9063_VLDO9_SEL),
},
{
DA9063_LDO(DA9063, LDO11, 900, 50, 3600),
- .suspend = BFIELD(DA9063_REG_LDO11_CONT, DA9063_VLDO11_SEL),
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO11_LIM),
},
/* The following LDOs are present only on DA9063, not on DA9063L */
{
DA9063_LDO(DA9063, LDO1, 600, 20, 1860),
- .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO1_SEL),
},
{
DA9063_LDO(DA9063, LDO2, 600, 20, 1860),
- .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO2_SEL),
},
{
DA9063_LDO(DA9063, LDO4, 900, 20, 3440),
- .suspend = BFIELD(DA9063_REG_DVC_2, DA9063_VLDO4_SEL),
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO4_LIM),
},
{
DA9063_LDO(DA9063, LDO5, 900, 50, 3600),
- .suspend = BFIELD(DA9063_REG_LDO5_CONT, DA9063_VLDO5_SEL),
},
{
DA9063_LDO(DA9063, LDO6, 900, 50, 3600),
- .suspend = BFIELD(DA9063_REG_LDO6_CONT, DA9063_VLDO6_SEL),
},
{
DA9063_LDO(DA9063, LDO10, 900, 50, 3600),
- .suspend = BFIELD(DA9063_REG_LDO10_CONT, DA9063_VLDO10_SEL),
},
};
@@ -596,7 +562,7 @@
struct da9063_regulators *regulators = data;
struct da9063 *hw = regulators->regulator[0].hw;
struct da9063_regulator *regl;
- int bits, i , ret;
+ int bits, i, ret;
ret = regmap_read(hw->regmap, DA9063_REG_STATUS_D, &bits);
if (ret < 0)
@@ -608,10 +574,8 @@
continue;
if (BIT(regl->info->oc_event.lsb) & bits) {
- regulator_lock(regl->rdev);
regulator_notifier_call_chain(regl->rdev,
REGULATOR_EVENT_OVER_CURRENT, NULL);
- regulator_unlock(regl->rdev);
}
}
@@ -836,7 +800,7 @@
if (regl->info->suspend_sleep.reg) {
regl->suspend_sleep = devm_regmap_field_alloc(&pdev->dev,
- da9063->regmap, regl->info->suspend_sleep);
+ da9063->regmap, regl->info->suspend_sleep);
if (IS_ERR(regl->suspend_sleep))
return PTR_ERR(regl->suspend_sleep);
}
@@ -870,12 +834,10 @@
NULL, da9063_ldo_lim_event,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"LDO_LIM", regulators);
- if (ret) {
+ if (ret)
dev_err(&pdev->dev, "Failed to request LDO_LIM IRQ.\n");
- return ret;
- }
- return 0;
+ return ret;
}
static struct platform_driver da9063_regulator_driver = {
diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c
index f9448ed..7493af0 100644
--- a/drivers/regulator/da9210-regulator.c
+++ b/drivers/regulator/da9210-regulator.c
@@ -77,8 +77,6 @@
if (error < 0)
goto error_i2c;
- regulator_lock(chip->rdev);
-
if (val & DA9210_E_OVCURR) {
regulator_notifier_call_chain(chip->rdev,
REGULATOR_EVENT_OVER_CURRENT,
@@ -103,8 +101,6 @@
handled |= DA9210_E_VMAX;
}
- regulator_unlock(chip->rdev);
-
if (handled) {
/* Clear handled events */
error = regmap_write(chip->regmap, DA9210_REG_EVENT_B, handled);
@@ -125,14 +121,13 @@
* I2C driver interface functions
*/
-static const struct of_device_id da9210_dt_ids[] = {
+static const struct of_device_id __maybe_unused da9210_dt_ids[] = {
{ .compatible = "dlg,da9210", },
{ }
};
MODULE_DEVICE_TABLE(of, da9210_dt_ids);
-static int da9210_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int da9210_i2c_probe(struct i2c_client *i2c)
{
struct da9210 *chip;
struct device *dev = &i2c->dev;
@@ -228,7 +223,7 @@
.name = "da9210",
.of_match_table = of_match_ptr(da9210_dt_ids),
},
- .probe = da9210_i2c_probe,
+ .probe_new = da9210_i2c_probe,
.id_table = da9210_i2c_id,
};
diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c
index bf80748..e01b32d 100644
--- a/drivers/regulator/da9211-regulator.c
+++ b/drivers/regulator/da9211-regulator.c
@@ -17,6 +17,7 @@
#include <linux/gpio/consumer.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/da9211.h>
+#include <dt-bindings/regulator/dlg,da9211-regulator.h>
#include "da9211-regulator.h"
/* DEVICE IDs */
@@ -24,10 +25,6 @@
#define DA9213_DEVICE_ID 0x23
#define DA9215_DEVICE_ID 0x24
-#define DA9211_BUCK_MODE_SLEEP 1
-#define DA9211_BUCK_MODE_SYNC 2
-#define DA9211_BUCK_MODE_AUTO 3
-
/* DA9211 REGULATOR IDs */
#define DA9211_ID_BUCKA 0
#define DA9211_ID_BUCKB 1
@@ -54,10 +51,24 @@
},
};
+static bool da9211_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case DA9211_REG_STATUS_A:
+ case DA9211_REG_STATUS_B:
+ case DA9211_REG_EVENT_A:
+ case DA9211_REG_EVENT_B:
+ return true;
+ }
+ return false;
+}
+
static const struct regmap_config da9211_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 5 * 128,
+ .volatile_reg = da9211_volatile_reg,
+ .cache_type = REGCACHE_RBTREE,
.ranges = da9211_regmap_range,
.num_ranges = ARRAY_SIZE(da9211_regmap_range),
};
@@ -89,6 +100,20 @@
5600000, 5800000, 6000000, 6200000, 6400000, 6600000, 6800000, 7000000
};
+static unsigned int da9211_map_buck_mode(unsigned int mode)
+{
+ switch (mode) {
+ case DA9211_BUCK_MODE_SLEEP:
+ return REGULATOR_MODE_STANDBY;
+ case DA9211_BUCK_MODE_SYNC:
+ return REGULATOR_MODE_FAST;
+ case DA9211_BUCK_MODE_AUTO:
+ return REGULATOR_MODE_NORMAL;
+ default:
+ return REGULATOR_MODE_INVALID;
+ }
+}
+
static unsigned int da9211_buck_get_mode(struct regulator_dev *rdev)
{
int id = rdev_get_id(rdev);
@@ -236,6 +261,7 @@
.vsel_reg = DA9211_REG_VBUCKA_A + DA9211_ID_##_id * 2,\
.vsel_mask = DA9211_VBUCK_MASK,\
.owner = THIS_MODULE,\
+ .of_map_mode = da9211_map_buck_mode,\
}
static struct regulator_desc da9211_regulators[] = {
@@ -245,8 +271,14 @@
#ifdef CONFIG_OF
static struct of_regulator_match da9211_matches[] = {
- [DA9211_ID_BUCKA] = { .name = "BUCKA" },
- [DA9211_ID_BUCKB] = { .name = "BUCKB" },
+ [DA9211_ID_BUCKA] = {
+ .name = "BUCKA",
+ .desc = &da9211_regulators[DA9211_ID_BUCKA],
+ },
+ [DA9211_ID_BUCKB] = {
+ .name = "BUCKB",
+ .desc = &da9211_regulators[DA9211_ID_BUCKB],
+ },
};
static struct da9211_pdata *da9211_parse_regulators_dt(
@@ -283,12 +315,12 @@
pdata->init_data[n] = da9211_matches[i].init_data;
pdata->reg_node[n] = da9211_matches[i].of_node;
- pdata->gpiod_ren[n] = devm_gpiod_get_from_of_node(dev,
- da9211_matches[i].of_node,
- "enable-gpios",
- 0,
- GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
- "da9211-enable");
+ pdata->gpiod_ren[n] = devm_fwnode_gpiod_get(dev,
+ of_fwnode_handle(pdata->reg_node[n]),
+ "enable",
+ GPIOD_OUT_HIGH |
+ GPIOD_FLAGS_BIT_NONEXCLUSIVE,
+ "da9211-enable");
if (IS_ERR(pdata->gpiod_ren[n]))
pdata->gpiod_ren[n] = NULL;
n++;
@@ -314,10 +346,8 @@
goto error_i2c;
if (reg_val & DA9211_E_OV_CURR_A) {
- regulator_lock(chip->rdev[0]);
regulator_notifier_call_chain(chip->rdev[0],
REGULATOR_EVENT_OVER_CURRENT, NULL);
- regulator_unlock(chip->rdev[0]);
err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
DA9211_E_OV_CURR_A);
@@ -328,10 +358,8 @@
}
if (reg_val & DA9211_E_OV_CURR_B) {
- regulator_lock(chip->rdev[1]);
regulator_notifier_call_chain(chip->rdev[1],
REGULATOR_EVENT_OVER_CURRENT, NULL);
- regulator_unlock(chip->rdev[1]);
err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
DA9211_E_OV_CURR_B);
@@ -416,8 +444,7 @@
/*
* I2C driver interface functions
*/
-static int da9211_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int da9211_i2c_probe(struct i2c_client *i2c)
{
struct da9211 *chip;
int error, ret;
@@ -526,7 +553,7 @@
.name = "da9211",
.of_match_table = of_match_ptr(da9211_dt_ids),
},
- .probe = da9211_i2c_probe,
+ .probe_new = da9211_i2c_probe,
.id_table = da9211_i2c_id,
};
diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c
index 88a2dcb..0ce6ec4 100644
--- a/drivers/regulator/db8500-prcmu.c
+++ b/drivers/regulator/db8500-prcmu.c
@@ -181,7 +181,7 @@
goto out;
}
- info->is_enabled = 0;
+ info->is_enabled = false;
out:
return ret;
}
diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c
index f604c8d..8b70bfe 100644
--- a/drivers/regulator/dbx500-prcmu.c
+++ b/drivers/regulator/dbx500-prcmu.c
@@ -67,8 +67,6 @@
static struct ux500_regulator_debug {
struct dentry *dir;
- struct dentry *status_file;
- struct dentry *power_state_cnt_file;
struct dbx500_regulator_info *regulator_array;
int num_regulators;
u8 *state_before_suspend;
@@ -110,13 +108,6 @@
}
DEFINE_SHOW_ATTRIBUTE(ux500_regulator_status);
-int __attribute__((weak)) dbx500_regulator_testcase(
- struct dbx500_regulator_info *regulator_info,
- int num_regulators)
-{
- return 0;
-}
-
int
ux500_regulator_debug_init(struct platform_device *pdev,
struct dbx500_regulator_info *regulator_info,
@@ -124,22 +115,14 @@
{
/* create directory */
rdebug.dir = debugfs_create_dir("ux500-regulator", NULL);
- if (!rdebug.dir)
- goto exit_no_debugfs;
/* create "status" file */
- rdebug.status_file = debugfs_create_file("status",
- S_IRUGO, rdebug.dir, &pdev->dev,
- &ux500_regulator_status_fops);
- if (!rdebug.status_file)
- goto exit_destroy_dir;
+ debugfs_create_file("status", S_IRUGO, rdebug.dir, &pdev->dev,
+ &ux500_regulator_status_fops);
/* create "power-state-count" file */
- rdebug.power_state_cnt_file = debugfs_create_file("power-state-count",
- S_IRUGO, rdebug.dir, &pdev->dev,
- &ux500_regulator_power_state_cnt_fops);
- if (!rdebug.power_state_cnt_file)
- goto exit_destroy_status;
+ debugfs_create_file("power-state-count", S_IRUGO, rdebug.dir,
+ &pdev->dev, &ux500_regulator_power_state_cnt_fops);
rdebug.regulator_array = regulator_info;
rdebug.num_regulators = num_regulators;
@@ -152,19 +135,12 @@
if (!rdebug.state_after_suspend)
goto exit_free;
- dbx500_regulator_testcase(regulator_info, num_regulators);
return 0;
exit_free:
kfree(rdebug.state_before_suspend);
exit_destroy_power_state:
- debugfs_remove(rdebug.power_state_cnt_file);
-exit_destroy_status:
- debugfs_remove(rdebug.status_file);
-exit_destroy_dir:
- debugfs_remove(rdebug.dir);
-exit_no_debugfs:
- dev_err(&pdev->dev, "failed to create debugfs entries.\n");
+ debugfs_remove_recursive(rdebug.dir);
return -ENOMEM;
}
diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
index 3ea1c17..3091210 100644
--- a/drivers/regulator/devres.c
+++ b/drivers/regulator/devres.c
@@ -41,8 +41,8 @@
/**
* devm_regulator_get - Resource managed regulator_get()
- * @dev: device for regulator "consumer"
- * @id: Supply name or regulator ID.
+ * @dev: device to supply
+ * @id: supply name or regulator ID.
*
* Managed regulator_get(). Regulators returned from this function are
* automatically regulator_put() on driver detach. See regulator_get() for more
@@ -56,8 +56,8 @@
/**
* devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
- * @dev: device for regulator "consumer"
- * @id: Supply name or regulator ID.
+ * @dev: device to supply
+ * @id: supply name or regulator ID.
*
* Managed regulator_get_exclusive(). Regulators returned from this function
* are automatically regulator_put() on driver detach. See regulator_get() for
@@ -72,8 +72,8 @@
/**
* devm_regulator_get_optional - Resource managed regulator_get_optional()
- * @dev: device for regulator "consumer"
- * @id: Supply name or regulator ID.
+ * @dev: device to supply
+ * @id: supply name or regulator ID.
*
* Managed regulator_get_optional(). Regulators returned from this
* function are automatically regulator_put() on driver detach. See
@@ -130,9 +130,9 @@
/**
* devm_regulator_bulk_get - managed get multiple regulator consumers
*
- * @dev: Device to supply
- * @num_consumers: Number of consumers to register
- * @consumers: Configuration of consumers; clients are stored here.
+ * @dev: device to supply
+ * @num_consumers: number of consumers to register
+ * @consumers: configuration of consumers; clients are stored here.
*
* @return 0 on success, an errno on failure.
*
@@ -173,8 +173,9 @@
/**
* devm_regulator_register - Resource managed regulator_register()
+ * @dev: device to supply
* @regulator_desc: regulator to register
- * @config: runtime configuration for regulator
+ * @config: runtime configuration for regulator
*
* Called by regulator drivers to register a regulator. Returns a
* valid pointer to struct regulator_dev on success or an ERR_PTR() on
@@ -216,7 +217,8 @@
/**
* devm_regulator_unregister - Resource managed regulator_unregister()
- * @regulator: regulator to free
+ * @dev: device to supply
+ * @rdev: regulator to free
*
* Unregister a regulator registered with devm_regulator_register().
* Normally this function will not need to be called and the resource
@@ -257,10 +259,10 @@
* devm_regulator_register_supply_alias - Resource managed
* regulator_register_supply_alias()
*
- * @dev: device that will be given as the regulator "consumer"
- * @id: Supply name or regulator ID
+ * @dev: device to supply
+ * @id: supply name or regulator ID
* @alias_dev: device that should be used to lookup the supply
- * @alias_id: Supply name or regulator ID that should be used to lookup the
+ * @alias_id: supply name or regulator ID that should be used to lookup the
* supply
*
* The supply alias will automatically be unregistered when the source
@@ -298,8 +300,8 @@
* devm_regulator_unregister_supply_alias - Resource managed
* regulator_unregister_supply_alias()
*
- * @dev: device that will be given as the regulator "consumer"
- * @id: Supply name or regulator ID
+ * @dev: device to supply
+ * @id: supply name or regulator ID
*
* Unregister an alias registered with
* devm_regulator_register_supply_alias(). Normally this function
@@ -325,12 +327,12 @@
* devm_regulator_bulk_register_supply_alias - Managed register
* multiple aliases
*
- * @dev: device that will be given as the regulator "consumer"
- * @id: List of supply names or regulator IDs
+ * @dev: device to supply
+ * @id: list of supply names or regulator IDs
* @alias_dev: device that should be used to lookup the supply
- * @alias_id: List of supply names or regulator IDs that should be used to
- * lookup the supply
- * @num_id: Number of aliases to register
+ * @alias_id: list of supply names or regulator IDs that should be used to
+ * lookup the supply
+ * @num_id: number of aliases to register
*
* @return 0 on success, an errno on failure.
*
@@ -375,9 +377,9 @@
* devm_regulator_bulk_unregister_supply_alias - Managed unregister
* multiple aliases
*
- * @dev: device that will be given as the regulator "consumer"
- * @id: List of supply names or regulator IDs
- * @num_id: Number of aliases to unregister
+ * @dev: device to supply
+ * @id: list of supply names or regulator IDs
+ * @num_id: number of aliases to unregister
*
* Unregister aliases registered with
* devm_regulator_bulk_register_supply_alias(). Normally this function
@@ -421,7 +423,7 @@
* regulator_register_notifier
*
* @regulator: regulator source
- * @nb: notifier block
+ * @nb: notifier block
*
* The notifier will be registers under the consumer device and be
* automatically be unregistered when the source device is unbound.
@@ -458,7 +460,7 @@
* regulator_unregister_notifier()
*
* @regulator: regulator source
- * @nb: notifier block
+ * @nb: notifier block
*
* Unregister a notifier registered with devm_regulator_register_notifier().
* Normally this function will not need to be called and the resource
diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c
index 74de698..d8059f5 100644
--- a/drivers/regulator/dummy.c
+++ b/drivers/regulator/dummy.c
@@ -21,13 +21,13 @@
struct regulator_dev *dummy_regulator_rdev;
-static struct regulator_init_data dummy_initdata = {
+static const struct regulator_init_data dummy_initdata = {
.constraints = {
.always_on = 1,
},
};
-static struct regulator_ops dummy_ops;
+static const struct regulator_ops dummy_ops;
static const struct regulator_desc dummy_desc = {
.name = "regulator-dummy",
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
index dbe477d..aa42618 100644
--- a/drivers/regulator/fan53555.c
+++ b/drivers/regulator/fan53555.c
@@ -83,6 +83,7 @@
enum {
SILERGY_SYR82X = 8,
+ SILERGY_SYR83X = 9,
};
struct fan53555_device_info {
@@ -302,6 +303,7 @@
/* Init voltage range and step */
switch (di->chip_id) {
case SILERGY_SYR82X:
+ case SILERGY_SYR83X:
di->vsel_min = 712500;
di->vsel_step = 12500;
break;
@@ -434,7 +436,7 @@
return pdata;
}
-static const struct of_device_id fan53555_dt_ids[] = {
+static const struct of_device_id __maybe_unused fan53555_dt_ids[] = {
{
.compatible = "fcs,fan53526",
.data = (void *)FAN53526_VENDOR_FAIRCHILD,
diff --git a/drivers/regulator/fan53880.c b/drivers/regulator/fan53880.c
new file mode 100644
index 0000000..94f02f3
--- /dev/null
+++ b/drivers/regulator/fan53880.c
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+
+enum fan53880_regulator_ids {
+ FAN53880_LDO1,
+ FAN53880_LDO2,
+ FAN53880_LDO3,
+ FAN53880_LDO4,
+ FAN53880_BUCK,
+ FAN53880_BOOST,
+};
+
+enum fan53880_registers {
+ FAN53880_PRODUCT_ID = 0x00,
+ FAN53880_SILICON_REV,
+ FAN53880_BUCKVOUT,
+ FAN53880_BOOSTVOUT,
+ FAN53880_LDO1VOUT,
+ FAN53880_LDO2VOUT,
+ FAN53880_LDO3VOUT,
+ FAN53880_LDO4VOUT,
+ FAN53880_IOUT,
+ FAN53880_ENABLE,
+ FAN53880_ENABLE_BOOST,
+};
+
+#define FAN53880_ID 0x01
+
+static const struct regulator_ops fan53880_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .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,
+};
+
+#define FAN53880_LDO(_num, _supply, _default) \
+ [FAN53880_LDO ## _num] = { \
+ .name = "LDO"#_num, \
+ .of_match = of_match_ptr("LDO"#_num), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .linear_ranges = (struct linear_range[]) { \
+ REGULATOR_LINEAR_RANGE(_default, 0x0, 0x0, 0), \
+ REGULATOR_LINEAR_RANGE(800000, 0xf, 0x73, 25000), \
+ }, \
+ .n_linear_ranges = 2, \
+ .n_voltages = 0x74, \
+ .vsel_reg = FAN53880_LDO ## _num ## VOUT, \
+ .vsel_mask = 0x7f, \
+ .enable_reg = FAN53880_ENABLE, \
+ .enable_mask = BIT(_num - 1), \
+ .enable_time = 150, \
+ .supply_name = _supply, \
+ .ops = &fan53880_ops, \
+ }
+
+static const struct regulator_desc fan53880_regulators[] = {
+ FAN53880_LDO(1, "VIN12", 2800000),
+ FAN53880_LDO(2, "VIN12", 2800000),
+ FAN53880_LDO(3, "VIN3", 1800000),
+ FAN53880_LDO(4, "VIN4", 1800000),
+ [FAN53880_BUCK] = {
+ .name = "BUCK",
+ .of_match = of_match_ptr("BUCK"),
+ .regulators_node = of_match_ptr("regulators"),
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(1100000, 0x0, 0x0, 0),
+ REGULATOR_LINEAR_RANGE(600000, 0x1f, 0xf7, 12500),
+ },
+ .n_linear_ranges = 2,
+ .n_voltages = 0xf8,
+ .vsel_reg = FAN53880_BUCKVOUT,
+ .vsel_mask = 0xff,
+ .enable_reg = FAN53880_ENABLE,
+ .enable_mask = 0x10,
+ .enable_time = 480,
+ .supply_name = "PVIN",
+ .ops = &fan53880_ops,
+ },
+ [FAN53880_BOOST] = {
+ .name = "BOOST",
+ .of_match = of_match_ptr("BOOST"),
+ .regulators_node = of_match_ptr("regulators"),
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(5000000, 0x0, 0x0, 0),
+ REGULATOR_LINEAR_RANGE(3000000, 0x4, 0x70, 25000),
+ },
+ .n_linear_ranges = 2,
+ .n_voltages = 0x71,
+ .vsel_reg = FAN53880_BOOSTVOUT,
+ .vsel_mask = 0x7f,
+ .enable_reg = FAN53880_ENABLE_BOOST,
+ .enable_mask = 0xff,
+ .enable_time = 580,
+ .supply_name = "PVIN",
+ .ops = &fan53880_ops,
+ },
+};
+
+static const struct regmap_config fan53880_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = FAN53880_ENABLE_BOOST,
+};
+
+static int fan53880_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct regulator_config config = { };
+ struct regulator_dev *rdev;
+ struct regmap *regmap;
+ int i, ret;
+ unsigned int data;
+
+ regmap = devm_regmap_init_i2c(i2c, &fan53880_regmap);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_read(regmap, FAN53880_PRODUCT_ID, &data);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read PRODUCT_ID: %d\n", ret);
+ return ret;
+ }
+ if (data != FAN53880_ID) {
+ dev_err(&i2c->dev, "Unsupported device id: 0x%x.\n", data);
+ return -ENODEV;
+ }
+
+ config.dev = &i2c->dev;
+ config.init_data = NULL;
+
+ for (i = 0; i < ARRAY_SIZE(fan53880_regulators); i++) {
+ rdev = devm_regulator_register(&i2c->dev,
+ &fan53880_regulators[i],
+ &config);
+ if (IS_ERR(rdev)) {
+ ret = PTR_ERR(rdev);
+ dev_err(&i2c->dev, "Failed to register %s: %d\n",
+ fan53880_regulators[i].name, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id fan53880_dt_ids[] = {
+ { .compatible = "onnn,fan53880", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, fan53880_dt_ids);
+#endif
+
+static const struct i2c_device_id fan53880_i2c_id[] = {
+ { "fan53880", },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, fan53880_i2c_id);
+
+static struct i2c_driver fan53880_regulator_driver = {
+ .driver = {
+ .name = "fan53880",
+ .of_match_table = of_match_ptr(fan53880_dt_ids),
+ },
+ .probe = fan53880_i2c_probe,
+ .id_table = fan53880_i2c_id,
+};
+module_i2c_driver(fan53880_regulator_driver);
+
+MODULE_DESCRIPTION("FAN53880 PMIC voltage regulator driver");
+MODULE_AUTHOR("Christoph Fritz <chf.fritz@googlemail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index f815330..3de7709 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -41,14 +41,6 @@
bool has_enable_clock;
};
-static const struct fixed_dev_type fixed_voltage_data = {
- .has_enable_clock = false,
-};
-
-static const struct fixed_dev_type fixed_clkenable_data = {
- .has_enable_clock = true,
-};
-
static int reg_clock_enable(struct regulator_dev *rdev)
{
struct fixed_voltage_data *priv = rdev_get_drvdata(rdev);
@@ -123,6 +115,7 @@
config->enabled_at_boot = true;
of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
+ of_property_read_u32(np, "off-on-delay-us", &config->off_on_delay);
if (of_find_property(np, "vin-supply", NULL))
config->input_supply = "vin";
@@ -130,10 +123,10 @@
return config;
}
-static struct regulator_ops fixed_voltage_ops = {
+static const struct regulator_ops fixed_voltage_ops = {
};
-static struct regulator_ops fixed_voltage_clkenabled_ops = {
+static const struct regulator_ops fixed_voltage_clkenabled_ops = {
.enable = reg_clock_enable,
.disable = reg_clock_disable,
.is_enabled = reg_clock_is_enabled,
@@ -181,7 +174,7 @@
drvdata->enable_clock = devm_clk_get(dev, NULL);
if (IS_ERR(drvdata->enable_clock)) {
- dev_err(dev, "Cant get enable-clock from devicetree\n");
+ dev_err(dev, "Can't get enable-clock from devicetree\n");
return -ENOENT;
}
} else {
@@ -189,6 +182,7 @@
}
drvdata->desc.enable_time = config->startup_delay;
+ drvdata->desc.off_on_delay = config->off_on_delay;
if (config->input_supply) {
drvdata->desc.supply_name = devm_kstrdup(&pdev->dev,
@@ -208,7 +202,7 @@
/*
* The signal will be inverted by the GPIO core if flagged so in the
- * decriptor.
+ * descriptor.
*/
if (config->enabled_at_boot)
gflags = GPIOD_OUT_HIGH;
@@ -258,6 +252,14 @@
}
#if defined(CONFIG_OF)
+static const struct fixed_dev_type fixed_voltage_data = {
+ .has_enable_clock = false,
+};
+
+static const struct fixed_dev_type fixed_clkenable_data = {
+ .has_enable_clock = true,
+};
+
static const struct of_device_id fixed_of_match[] = {
{
.compatible = "regulator-fixed",
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index 110ee6f..5927d4f 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -148,6 +148,13 @@
config->supply_name = config->init_data->constraints.name;
+ if (config->init_data->constraints.boot_on)
+ config->enabled_at_boot = true;
+
+ /*
+ * Do not use: undocumented device tree property.
+ * This is kept around solely for device tree ABI stability.
+ */
if (of_property_read_bool(np, "enable-at-boot"))
config->enabled_at_boot = true;
@@ -311,7 +318,7 @@
/*
* The signal will be inverted by the GPIO core if flagged so in the
- * decriptor.
+ * descriptor.
*/
if (config->enabled_at_boot)
gflags = GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE;
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index bb16c46..e4bb09b 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -131,10 +131,11 @@
unsigned int r_val;
int range;
unsigned int val;
- int ret, i;
- unsigned int voltages_in_range = 0;
+ int ret;
+ unsigned int voltages = 0;
+ const struct linear_range *r = rdev->desc->linear_ranges;
- if (!rdev->desc->linear_ranges)
+ if (!r)
return -EINVAL;
ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
@@ -152,11 +153,9 @@
if (range < 0)
return -EINVAL;
- for (i = 0; i < range; i++)
- voltages_in_range += (rdev->desc->linear_ranges[i].max_sel -
- rdev->desc->linear_ranges[i].min_sel) + 1;
+ voltages = linear_range_values_in_range_array(r, range);
- return val + voltages_in_range;
+ return val + voltages;
}
EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_pickable_regmap);
@@ -179,8 +178,11 @@
unsigned int voltages_in_range = 0;
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
- voltages_in_range = (rdev->desc->linear_ranges[i].max_sel -
- rdev->desc->linear_ranges[i].min_sel) + 1;
+ const struct linear_range *r;
+
+ r = &rdev->desc->linear_ranges[i];
+ voltages_in_range = linear_range_values_in_range(r);
+
if (sel < voltages_in_range)
break;
sel -= voltages_in_range;
@@ -405,8 +407,10 @@
int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
- const struct regulator_linear_range *range;
+ const struct linear_range *range;
int ret = -EINVAL;
+ unsigned int sel;
+ bool found;
int voltage, i;
if (!rdev->desc->n_linear_ranges) {
@@ -415,35 +419,19 @@
}
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
- int linear_max_uV;
-
range = &rdev->desc->linear_ranges[i];
- linear_max_uV = range->min_uV +
- (range->max_sel - range->min_sel) * range->uV_step;
- if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV))
+ ret = linear_range_get_selector_high(range, min_uV, &sel,
+ &found);
+ if (ret)
continue;
-
- if (min_uV <= range->min_uV)
- min_uV = range->min_uV;
-
- /* range->uV_step == 0 means fixed voltage range */
- if (range->uV_step == 0) {
- ret = 0;
- } else {
- ret = DIV_ROUND_UP(min_uV - range->min_uV,
- range->uV_step);
- if (ret < 0)
- return ret;
- }
-
- ret += range->min_sel;
+ ret = sel;
/*
* Map back into a voltage to verify we're still in bounds.
* If we are not, then continue checking rest of the ranges.
*/
- voltage = rdev->desc->ops->list_voltage(rdev, ret);
+ voltage = rdev->desc->ops->list_voltage(rdev, sel);
if (voltage >= min_uV && voltage <= max_uV)
break;
}
@@ -468,7 +456,7 @@
int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
- const struct regulator_linear_range *range;
+ const struct linear_range *range;
int ret = -EINVAL;
int voltage, i;
unsigned int selector = 0;
@@ -480,30 +468,25 @@
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
int linear_max_uV;
+ bool found;
+ unsigned int sel;
range = &rdev->desc->linear_ranges[i];
- linear_max_uV = range->min_uV +
- (range->max_sel - range->min_sel) * range->uV_step;
+ linear_max_uV = linear_range_get_max_value(range);
- if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV)) {
- selector += (range->max_sel - range->min_sel + 1);
+ if (!(min_uV <= linear_max_uV && max_uV >= range->min)) {
+ selector += linear_range_values_in_range(range);
continue;
}
- if (min_uV <= range->min_uV)
- min_uV = range->min_uV;
-
- /* range->uV_step == 0 means fixed voltage range */
- if (range->uV_step == 0) {
- ret = 0;
- } else {
- ret = DIV_ROUND_UP(min_uV - range->min_uV,
- range->uV_step);
- if (ret < 0)
- return ret;
+ ret = linear_range_get_selector_high(range, min_uV, &sel,
+ &found);
+ if (ret) {
+ selector += linear_range_values_in_range(range);
+ continue;
}
- ret += selector;
+ ret = selector + sel - range->min_sel;
voltage = rdev->desc->ops->list_voltage(rdev, ret);
@@ -513,7 +496,7 @@
* exit but retry until we have checked all ranges.
*/
if (voltage < min_uV || voltage > max_uV)
- selector += (range->max_sel - range->min_sel + 1);
+ selector += linear_range_values_in_range(range);
else
break;
}
@@ -561,7 +544,7 @@
int regulator_list_voltage_pickable_linear_range(struct regulator_dev *rdev,
unsigned int selector)
{
- const struct regulator_linear_range *range;
+ const struct linear_range *range;
int i;
unsigned int all_sels = 0;
@@ -571,18 +554,28 @@
}
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
- unsigned int sels_in_range;
+ unsigned int sel_indexes;
range = &rdev->desc->linear_ranges[i];
- sels_in_range = range->max_sel - range->min_sel;
+ sel_indexes = linear_range_values_in_range(range) - 1;
- if (all_sels + sels_in_range >= selector) {
+ if (all_sels + sel_indexes >= selector) {
selector -= all_sels;
- return range->min_uV + (range->uV_step * selector);
+ /*
+ * As we see here, pickable ranges work only as
+ * long as the first selector for each pickable
+ * range is 0, and the each subsequent range for
+ * this 'pick' follow immediately at next unused
+ * selector (Eg. there is no gaps between ranges).
+ * I think this is fine but it probably should be
+ * documented. OTOH, whole pickable range stuff
+ * might benefit from some documentation
+ */
+ return range->min + (range->step * selector);
}
- all_sels += (sels_in_range + 1);
+ all_sels += (sel_indexes + 1);
}
return -EINVAL;
@@ -604,27 +597,18 @@
int regulator_desc_list_voltage_linear_range(const struct regulator_desc *desc,
unsigned int selector)
{
- const struct regulator_linear_range *range;
- int i;
+ unsigned int val;
+ int ret;
- if (!desc->n_linear_ranges) {
- BUG_ON(!desc->n_linear_ranges);
- return -EINVAL;
- }
+ BUG_ON(!desc->n_linear_ranges);
- for (i = 0; i < desc->n_linear_ranges; i++) {
- range = &desc->linear_ranges[i];
+ ret = linear_range_get_value_array(desc->linear_ranges,
+ desc->n_linear_ranges, selector,
+ &val);
+ if (ret)
+ return ret;
- if (!(selector >= range->min_sel &&
- selector <= range->max_sel))
- continue;
-
- selector -= range->min_sel;
-
- return range->min_uV + (range->uV_step * selector);
- }
-
- return -EINVAL;
+ return val;
}
EXPORT_SYMBOL_GPL(regulator_desc_list_voltage_linear_range);
diff --git a/drivers/regulator/hi6421-regulator.c b/drivers/regulator/hi6421-regulator.c
index efc91b0..d144a4b 100644
--- a/drivers/regulator/hi6421-regulator.c
+++ b/drivers/regulator/hi6421-regulator.c
@@ -5,7 +5,7 @@
// Copyright (c) <2011-2014> HiSilicon Technologies Co., Ltd.
// http://www.hisilicon.com
// Copyright (c) <2013-2014> Linaro Ltd.
-// http://www.linaro.org
+// https://www.linaro.org
//
// Author: Guodong Xu <guodong.xu@linaro.org>
@@ -87,7 +87,7 @@
};
/* Ranges are sorted in ascending order. */
-static const struct regulator_linear_range ldo_audio_volt_range[] = {
+static const struct linear_range ldo_audio_volt_range[] = {
REGULATOR_LINEAR_RANGE(2800000, 0, 3, 50000),
REGULATOR_LINEAR_RANGE(3000000, 4, 7, 100000),
};
@@ -195,7 +195,7 @@
* _id - LDO id name string
* _match - of match name string
* n_volt - number of votages available
- * volt_ranges - array of regulator_linear_range
+ * volt_ranges - array of linear_range
* vstep - voltage increase in each linear step in uV
* vreg - voltage select register
* vmask - voltage select mask
diff --git a/drivers/regulator/hi6421v530-regulator.c b/drivers/regulator/hi6421v530-regulator.c
index 06ae651..988115f 100644
--- a/drivers/regulator/hi6421v530-regulator.c
+++ b/drivers/regulator/hi6421v530-regulator.c
@@ -5,7 +5,7 @@
// Copyright (c) <2017> HiSilicon Technologies Co., Ltd.
// http://www.hisilicon.com
// Copyright (c) <2017> Linaro Ltd.
-// http://www.linaro.org
+// https://www.linaro.org
//
// Author: Wang Xiaoyin <hw.wangxiaoyin@hisilicon.com>
// Guodong Xu <guodong.xu@linaro.org>
diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h
index 83ae442..2391b56 100644
--- a/drivers/regulator/internal.h
+++ b/drivers/regulator/internal.h
@@ -36,6 +36,7 @@
struct list_head list;
unsigned int always_on:1;
unsigned int bypass:1;
+ unsigned int device_link:1;
int uA_load;
unsigned int enable_count;
unsigned int deferred_disables;
diff --git a/drivers/regulator/isl9305.c b/drivers/regulator/isl9305.c
index 978f5e9..cfb7659 100644
--- a/drivers/regulator/isl9305.c
+++ b/drivers/regulator/isl9305.c
@@ -137,8 +137,7 @@
.cache_type = REGCACHE_RBTREE,
};
-static int isl9305_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int isl9305_i2c_probe(struct i2c_client *i2c)
{
struct regulator_config config = { };
struct isl9305_pdata *pdata = i2c->dev.platform_data;
@@ -198,7 +197,7 @@
.name = "isl9305",
.of_match_table = of_match_ptr(isl9305_dt_ids),
},
- .probe = isl9305_i2c_probe,
+ .probe_new = isl9305_i2c_probe,
.id_table = isl9305_i2c_id,
};
diff --git a/drivers/regulator/lochnagar-regulator.c b/drivers/regulator/lochnagar-regulator.c
index 9b05e03..cb71fa5 100644
--- a/drivers/regulator/lochnagar-regulator.c
+++ b/drivers/regulator/lochnagar-regulator.c
@@ -36,7 +36,7 @@
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};
-static const struct regulator_linear_range lochnagar_micvdd_ranges[] = {
+static const struct linear_range lochnagar_micvdd_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 0xC, 50000),
REGULATOR_LINEAR_RANGE(1700000, 0xD, 0x1F, 100000),
};
@@ -97,7 +97,8 @@
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};
-static const struct regulator_linear_range lochnagar_vddcore_ranges[] = {
+static const struct linear_range lochnagar_vddcore_ranges[] = {
+ REGULATOR_LINEAR_RANGE(600000, 0, 0x7, 0),
REGULATOR_LINEAR_RANGE(600000, 0x8, 0x41, 12500),
};
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index bc96e65..8be252f 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -400,8 +400,7 @@
return 0;
}
-static int lp3971_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int lp3971_i2c_probe(struct i2c_client *i2c)
{
struct lp3971 *lp3971;
struct lp3971_platform_data *pdata = dev_get_platdata(&i2c->dev);
@@ -449,7 +448,7 @@
.driver = {
.name = "LP3971",
},
- .probe = lp3971_i2c_probe,
+ .probe_new = lp3971_i2c_probe,
.id_table = lp3971_i2c_id,
};
diff --git a/drivers/regulator/lp873x-regulator.c b/drivers/regulator/lp873x-regulator.c
index b55de29..c38387e 100644
--- a/drivers/regulator/lp873x-regulator.c
+++ b/drivers/regulator/lp873x-regulator.c
@@ -1,7 +1,7 @@
/*
* Regulator driver for LP873X PMIC
*
- * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2016 Texas Instruments Incorporated - https://www.ti.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
@@ -54,14 +54,14 @@
static const struct lp873x_regulator regulators[];
-static const struct regulator_linear_range buck0_buck1_ranges[] = {
+static const struct linear_range buck0_buck1_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x13, 0),
REGULATOR_LINEAR_RANGE(700000, 0x14, 0x17, 10000),
REGULATOR_LINEAR_RANGE(735000, 0x18, 0x9d, 5000),
REGULATOR_LINEAR_RANGE(1420000, 0x9e, 0xff, 20000),
};
-static const struct regulator_linear_range ldo0_ldo1_ranges[] = {
+static const struct linear_range ldo0_ldo1_ranges[] = {
REGULATOR_LINEAR_RANGE(800000, 0x0, 0x19, 100000),
};
diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c
index 4291df0..13c5357 100644
--- a/drivers/regulator/lp8755.c
+++ b/drivers/regulator/lp8755.c
@@ -49,53 +49,15 @@
struct regulator_dev *rdev[LP8755_BUCK_MAX];
};
-/**
- *lp8755_read : read a single register value from lp8755.
- *@pchip : device to read from
- *@reg : register to read from
- *@val : pointer to store read value
- */
-static int lp8755_read(struct lp8755_chip *pchip, unsigned int reg,
- unsigned int *val)
-{
- return regmap_read(pchip->regmap, reg, val);
-}
-
-/**
- *lp8755_write : write a single register value to lp8755.
- *@pchip : device to write to
- *@reg : register to write to
- *@val : value to be written
- */
-static int lp8755_write(struct lp8755_chip *pchip, unsigned int reg,
- unsigned int val)
-{
- return regmap_write(pchip->regmap, reg, val);
-}
-
-/**
- *lp8755_update_bits : set the values of bit fields in lp8755 register.
- *@pchip : device to read from
- *@reg : register to update
- *@mask : bitmask to be changed
- *@val : value for bitmask
- */
-static int lp8755_update_bits(struct lp8755_chip *pchip, unsigned int reg,
- unsigned int mask, unsigned int val)
-{
- return regmap_update_bits(pchip->regmap, reg, mask, val);
-}
-
static int lp8755_buck_enable_time(struct regulator_dev *rdev)
{
int ret;
unsigned int regval;
enum lp8755_bucks id = rdev_get_id(rdev);
- struct lp8755_chip *pchip = rdev_get_drvdata(rdev);
- ret = lp8755_read(pchip, 0x12 + id, ®val);
+ ret = regmap_read(rdev->regmap, 0x12 + id, ®val);
if (ret < 0) {
- dev_err(pchip->dev, "i2c access error %s\n", __func__);
+ dev_err(&rdev->dev, "i2c access error %s\n", __func__);
return ret;
}
return (regval & 0xff) * 100;
@@ -115,17 +77,17 @@
break;
case REGULATOR_MODE_NORMAL:
/* enable automatic pwm/pfm mode */
- ret = lp8755_update_bits(pchip, 0x08 + id, 0x20, 0x00);
+ ret = regmap_update_bits(rdev->regmap, 0x08 + id, 0x20, 0x00);
if (ret < 0)
goto err_i2c;
break;
case REGULATOR_MODE_IDLE:
/* enable automatic pwm/pfm/lppfm mode */
- ret = lp8755_update_bits(pchip, 0x08 + id, 0x20, 0x20);
+ ret = regmap_update_bits(rdev->regmap, 0x08 + id, 0x20, 0x20);
if (ret < 0)
goto err_i2c;
- ret = lp8755_update_bits(pchip, 0x10, 0x01, 0x01);
+ ret = regmap_update_bits(rdev->regmap, 0x10, 0x01, 0x01);
if (ret < 0)
goto err_i2c;
break;
@@ -135,12 +97,12 @@
regbval = (0x01 << id);
}
- ret = lp8755_update_bits(pchip, 0x06, 0x01 << id, regbval);
+ ret = regmap_update_bits(rdev->regmap, 0x06, 0x01 << id, regbval);
if (ret < 0)
goto err_i2c;
return ret;
err_i2c:
- dev_err(pchip->dev, "i2c access error %s\n", __func__);
+ dev_err(&rdev->dev, "i2c access error %s\n", __func__);
return ret;
}
@@ -149,9 +111,8 @@
int ret;
unsigned int regval;
enum lp8755_bucks id = rdev_get_id(rdev);
- struct lp8755_chip *pchip = rdev_get_drvdata(rdev);
- ret = lp8755_read(pchip, 0x06, ®val);
+ ret = regmap_read(rdev->regmap, 0x06, ®val);
if (ret < 0)
goto err_i2c;
@@ -159,7 +120,7 @@
if (regval & (0x01 << id))
return REGULATOR_MODE_FAST;
- ret = lp8755_read(pchip, 0x08 + id, ®val);
+ ret = regmap_read(rdev->regmap, 0x08 + id, ®val);
if (ret < 0)
goto err_i2c;
@@ -171,7 +132,7 @@
return REGULATOR_MODE_NORMAL;
err_i2c:
- dev_err(pchip->dev, "i2c access error %s\n", __func__);
+ dev_err(&rdev->dev, "i2c access error %s\n", __func__);
return 0;
}
@@ -180,7 +141,6 @@
int ret;
unsigned int regval = 0x00;
enum lp8755_bucks id = rdev_get_id(rdev);
- struct lp8755_chip *pchip = rdev_get_drvdata(rdev);
/* uV/us */
switch (ramp) {
@@ -209,17 +169,17 @@
regval = 0x00;
break;
default:
- dev_err(pchip->dev,
+ dev_err(&rdev->dev,
"Not supported ramp value %d %s\n", ramp, __func__);
return -EINVAL;
}
- ret = lp8755_update_bits(pchip, 0x07 + id, 0x07, regval);
+ ret = regmap_update_bits(rdev->regmap, 0x07 + id, 0x07, regval);
if (ret < 0)
goto err_i2c;
return ret;
err_i2c:
- dev_err(pchip->dev, "i2c access error %s\n", __func__);
+ dev_err(&rdev->dev, "i2c access error %s\n", __func__);
return ret;
}
@@ -278,7 +238,7 @@
struct lp8755_platform_data *pdata = pchip->pdata;
/* read back muti-phase configuration */
- ret = lp8755_read(pchip, 0x3D, ®val);
+ ret = regmap_read(pchip->regmap, 0x3D, ®val);
if (ret < 0)
goto out_i2c_error;
pchip->mphase = regval & 0x0F;
@@ -356,11 +316,11 @@
struct lp8755_chip *pchip = data;
/* read flag0 register */
- ret = lp8755_read(pchip, 0x0D, &flag0);
+ ret = regmap_read(pchip->regmap, 0x0D, &flag0);
if (ret < 0)
goto err_i2c;
/* clear flag register to pull up int. pin */
- ret = lp8755_write(pchip, 0x0D, 0x00);
+ ret = regmap_write(pchip->regmap, 0x0D, 0x00);
if (ret < 0)
goto err_i2c;
@@ -369,19 +329,17 @@
if ((flag0 & (0x4 << icnt))
&& (pchip->irqmask & (0x04 << icnt))
&& (pchip->rdev[icnt] != NULL)) {
- regulator_lock(pchip->rdev[icnt]);
regulator_notifier_call_chain(pchip->rdev[icnt],
LP8755_EVENT_PWR_FAULT,
NULL);
- regulator_unlock(pchip->rdev[icnt]);
}
/* read flag1 register */
- ret = lp8755_read(pchip, 0x0E, &flag1);
+ ret = regmap_read(pchip->regmap, 0x0E, &flag1);
if (ret < 0)
goto err_i2c;
/* clear flag register to pull up int. pin */
- ret = lp8755_write(pchip, 0x0E, 0x00);
+ ret = regmap_write(pchip->regmap, 0x0E, 0x00);
if (ret < 0)
goto err_i2c;
@@ -389,22 +347,18 @@
if ((flag1 & 0x01) && (pchip->irqmask & 0x01))
for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
if (pchip->rdev[icnt] != NULL) {
- regulator_lock(pchip->rdev[icnt]);
regulator_notifier_call_chain(pchip->rdev[icnt],
LP8755_EVENT_OCP,
NULL);
- regulator_unlock(pchip->rdev[icnt]);
}
/* send OVP event to all regulator devices */
if ((flag1 & 0x02) && (pchip->irqmask & 0x02))
for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
if (pchip->rdev[icnt] != NULL) {
- regulator_lock(pchip->rdev[icnt]);
regulator_notifier_call_chain(pchip->rdev[icnt],
LP8755_EVENT_OVP,
NULL);
- regulator_unlock(pchip->rdev[icnt]);
}
return IRQ_HANDLED;
@@ -423,7 +377,7 @@
return 0;
}
- ret = lp8755_read(pchip, 0x0F, ®val);
+ ret = regmap_read(pchip->regmap, 0x0F, ®val);
if (ret < 0) {
dev_err(pchip->dev, "i2c access error %s\n", __func__);
return ret;
@@ -502,7 +456,7 @@
err:
/* output disable */
for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
- lp8755_write(pchip, icnt, 0x00);
+ regmap_write(pchip->regmap, icnt, 0x00);
return ret;
}
@@ -513,7 +467,7 @@
struct lp8755_chip *pchip = i2c_get_clientdata(client);
for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
- lp8755_write(pchip, icnt, 0x00);
+ regmap_write(pchip->regmap, icnt, 0x00);
return 0;
}
diff --git a/drivers/regulator/lp87565-regulator.c b/drivers/regulator/lp87565-regulator.c
index 4ae12ac..eeab9d3 100644
--- a/drivers/regulator/lp87565-regulator.c
+++ b/drivers/regulator/lp87565-regulator.c
@@ -2,7 +2,7 @@
/*
* Regulator driver for LP87565 PMIC
*
- * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2017 Texas Instruments Incorporated - https://www.ti.com/
*/
#include <linux/module.h>
@@ -11,8 +11,8 @@
#include <linux/mfd/lp87565.h>
-#define LP87565_REGULATOR(_name, _id, _of, _ops, _n, _vr, _vm, _er, _em, \
- _delay, _lr, _cr) \
+#define LP87565_REGULATOR(_name, _id, _of, _ops, _n, _vr, _vm, \
+ _er, _em, _ev, _delay, _lr, _cr) \
[_id] = { \
.desc = { \
.name = _name, \
@@ -28,6 +28,7 @@
.vsel_mask = _vm, \
.enable_reg = _er, \
.enable_mask = _em, \
+ .enable_val = _ev, \
.ramp_delay = _delay, \
.linear_ranges = _lr, \
.n_linear_ranges = ARRAY_SIZE(_lr), \
@@ -46,7 +47,7 @@
static const struct lp87565_regulator regulators[];
-static const struct regulator_linear_range buck0_1_2_3_ranges[] = {
+static const struct linear_range buck0_1_2_3_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0xA, 0x17, 10000),
REGULATOR_LINEAR_RANGE(735000, 0x18, 0x9d, 5000),
REGULATOR_LINEAR_RANGE(1420000, 0x9e, 0xff, 20000),
@@ -121,38 +122,54 @@
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 |
+ LP87565_BUCK_CTRL_1_EN_PIN_CTRL,
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 |
+ LP87565_BUCK_CTRL_1_EN_PIN_CTRL,
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 |
+ LP87565_BUCK_CTRL_1_EN_PIN_CTRL,
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 |
+ LP87565_BUCK_CTRL_1_EN_PIN_CTRL,
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 |
+ LP87565_BUCK_CTRL_1_EN_PIN_CTRL |
+ LP87565_BUCK_CTRL_1_FPWM_MP_0_2,
+ 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 |
+ LP87565_BUCK_CTRL_1_EN_PIN_CTRL,
LP87565_BUCK_CTRL_1_EN, 3230,
buck0_1_2_3_ranges, LP87565_REG_BUCK2_CTRL_2),
LP87565_REGULATOR("BUCK3210", LP87565_BUCK_3210, "buck3210",
lp87565_buck_ops, 256, LP87565_REG_BUCK0_VOUT,
LP87565_BUCK_VSET, LP87565_REG_BUCK0_CTRL_1,
LP87565_BUCK_CTRL_1_EN |
+ LP87565_BUCK_CTRL_1_EN_PIN_CTRL |
+ LP87565_BUCK_CTRL_1_FPWM_MP_0_2,
+ LP87565_BUCK_CTRL_1_EN |
LP87565_BUCK_CTRL_1_FPWM_MP_0_2, 3230,
buck0_1_2_3_ranges, LP87565_REG_BUCK0_CTRL_2),
};
diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
index 222502a..74b7b49 100644
--- a/drivers/regulator/lp8788-buck.c
+++ b/drivers/regulator/lp8788-buck.c
@@ -92,7 +92,7 @@
};
/* BUCK 1 ~ 4 voltage ranges */
-static const struct regulator_linear_range buck_volt_ranges[] = {
+static const struct linear_range buck_volt_ranges[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0, 0),
REGULATOR_LINEAR_RANGE(800000, 1, 25, 50000),
};
diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c
index 9a037fd..38f7ccb 100644
--- a/drivers/regulator/ltc3589.c
+++ b/drivers/regulator/ltc3589.c
@@ -357,22 +357,16 @@
if (irqstat & LTC3589_IRQSTAT_THERMAL_WARN) {
event = REGULATOR_EVENT_OVER_TEMP;
- for (i = 0; i < LTC3589_NUM_REGULATORS; i++) {
- regulator_lock(ltc3589->regulators[i]);
+ for (i = 0; i < LTC3589_NUM_REGULATORS; i++)
regulator_notifier_call_chain(ltc3589->regulators[i],
event, NULL);
- regulator_unlock(ltc3589->regulators[i]);
- }
}
if (irqstat & LTC3589_IRQSTAT_UNDERVOLT_WARN) {
event = REGULATOR_EVENT_UNDER_VOLTAGE;
- for (i = 0; i < LTC3589_NUM_REGULATORS; i++) {
- regulator_lock(ltc3589->regulators[i]);
+ for (i = 0; i < LTC3589_NUM_REGULATORS; i++)
regulator_notifier_call_chain(ltc3589->regulators[i],
event, NULL);
- regulator_unlock(ltc3589->regulators[i]);
- }
}
/* Clear warning condition */
@@ -457,7 +451,7 @@
};
MODULE_DEVICE_TABLE(i2c, ltc3589_i2c_id);
-static const struct of_device_id ltc3589_of_match[] = {
+static const struct of_device_id __maybe_unused ltc3589_of_match[] = {
{
.compatible = "lltc,ltc3589",
.data = (void *)LTC3589,
diff --git a/drivers/regulator/ltc3676.c b/drivers/regulator/ltc3676.c
index d934540..eb3d6be 100644
--- a/drivers/regulator/ltc3676.c
+++ b/drivers/regulator/ltc3676.c
@@ -221,7 +221,7 @@
#define LTC3676_FIXED_REG(_id, _name, _en_reg, _en_bit) \
LTC3676_REG(_id, _name, fixed, LTC3676_ ## _en_reg, _en_bit, 0, 0)
-static struct regulator_desc ltc3676_regulators[LTC3676_NUM_REGULATORS] = {
+static const struct regulator_desc ltc3676_regulators[LTC3676_NUM_REGULATORS] = {
LTC3676_LINEAR_REG(SW1, sw1, BUCK1, DVB1A),
LTC3676_LINEAR_REG(SW2, sw2, BUCK2, DVB2A),
LTC3676_LINEAR_REG(SW3, sw3, BUCK3, DVB3A),
@@ -276,23 +276,17 @@
if (irqstat & LTC3676_IRQSTAT_THERMAL_WARN) {
dev_warn(dev, "Over-temperature Warning\n");
event = REGULATOR_EVENT_OVER_TEMP;
- for (i = 0; i < LTC3676_NUM_REGULATORS; i++) {
- regulator_lock(ltc3676->regulators[i]);
+ for (i = 0; i < LTC3676_NUM_REGULATORS; i++)
regulator_notifier_call_chain(ltc3676->regulators[i],
event, NULL);
- regulator_unlock(ltc3676->regulators[i]);
- }
}
if (irqstat & LTC3676_IRQSTAT_UNDERVOLT_WARN) {
dev_info(dev, "Undervoltage Warning\n");
event = REGULATOR_EVENT_UNDER_VOLTAGE;
- for (i = 0; i < LTC3676_NUM_REGULATORS; i++) {
- regulator_lock(ltc3676->regulators[i]);
+ for (i = 0; i < LTC3676_NUM_REGULATORS; i++)
regulator_notifier_call_chain(ltc3676->regulators[i],
event, NULL);
- regulator_unlock(ltc3676->regulators[i]);
- }
}
/* Clear warning condition */
@@ -301,8 +295,7 @@
return IRQ_HANDLED;
}
-static int ltc3676_regulator_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int ltc3676_regulator_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct regulator_init_data *init_data = dev_get_platdata(dev);
@@ -369,7 +362,7 @@
};
MODULE_DEVICE_TABLE(i2c, ltc3676_i2c_id);
-static const struct of_device_id ltc3676_of_match[] = {
+static const struct of_device_id __maybe_unused ltc3676_of_match[] = {
{ .compatible = "lltc,ltc3676" },
{ },
};
@@ -380,7 +373,7 @@
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(ltc3676_of_match),
},
- .probe = ltc3676_regulator_probe,
+ .probe_new = ltc3676_regulator_probe,
.id_table = ltc3676_i2c_id,
};
module_i2c_driver(ltc3676_driver);
diff --git a/drivers/regulator/max14577-regulator.c b/drivers/regulator/max14577-regulator.c
index 07a150c..e34face 100644
--- a/drivers/regulator/max14577-regulator.c
+++ b/drivers/regulator/max14577-regulator.c
@@ -155,7 +155,7 @@
[MAX77836_LDO2] = MAX77836_LDO_REG(2),
};
-/**
+/*
* Registers for regulators of max77836 use different I2C slave addresses so
* different regmaps must be used for them.
*
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index f894102..d495839 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -201,7 +201,7 @@
return 0;
}
-static const struct of_device_id max1586_of_match[] = {
+static const struct of_device_id __maybe_unused max1586_of_match[] = {
{ .compatible = "maxim,max1586", },
{},
};
diff --git a/drivers/regulator/max77650-regulator.c b/drivers/regulator/max77650-regulator.c
index e57fc91..ca08f94 100644
--- a/drivers/regulator/max77650-regulator.c
+++ b/drivers/regulator/max77650-regulator.c
@@ -49,7 +49,7 @@
0x0, 0x1, 0x2, 0x3
};
-static const struct regulator_linear_range max77651_sbb1_volt_ranges[] = {
+static const struct linear_range max77651_sbb1_volt_ranges[] = {
/* range index 0 */
REGULATOR_LINEAR_RANGE(2400000, 0x00, 0x0f, 50000),
/* range index 1 */
@@ -386,9 +386,16 @@
return 0;
}
+static const struct of_device_id max77650_regulator_of_match[] = {
+ { .compatible = "maxim,max77650-regulator" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, max77650_regulator_of_match);
+
static struct platform_driver max77650_regulator_driver = {
.driver = {
.name = "max77650-regulator",
+ .of_match_table = max77650_regulator_of_match,
},
.probe = max77650_regulator_probe,
};
diff --git a/drivers/regulator/max77686-regulator.c b/drivers/regulator/max77686-regulator.c
index c8e579e..9089ec6 100644
--- a/drivers/regulator/max77686-regulator.c
+++ b/drivers/regulator/max77686-regulator.c
@@ -256,8 +256,9 @@
case MAX77686_BUCK8:
case MAX77686_BUCK9:
case MAX77686_LDO20 ... MAX77686_LDO22:
- config->ena_gpiod = gpiod_get_from_of_node(np,
- "maxim,ena-gpios",
+ config->ena_gpiod = fwnode_gpiod_get_index(
+ of_fwnode_handle(np),
+ "maxim,ena",
0,
GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"max77686-regulator");
diff --git a/drivers/regulator/max77826-regulator.c b/drivers/regulator/max77826-regulator.c
new file mode 100644
index 0000000..f9e2e88
--- /dev/null
+++ b/drivers/regulator/max77826-regulator.c
@@ -0,0 +1,301 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+//
+// max77826-regulator.c - regulator driver for Maxim MAX77826
+//
+// Author: Iskren Chernev <iskren.chernev@gmail.com>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+enum max77826_registers {
+ MAX77826_REG_INT_SRC = 0x00,
+ MAX77826_REG_SYS_INT,
+ MAX77826_REG_INT1,
+ MAX77826_REG_INT2,
+ MAX77826_REG_BB_INT,
+ MAX77826_REG_INT_SRC_M,
+ MAX77826_REG_TOPSYS_INT_M,
+ MAX77826_REG_INT1_M,
+ MAX77826_REG_INT2_M,
+ MAX77826_REG_BB_INT_M,
+ MAX77826_REG_TOPSYS_STAT,
+ MAX77826_REG_STAT1,
+ MAX77826_REG_STAT2,
+ MAX77826_REG_BB_STAT,
+ /* 0x0E - 0x0F: Reserved */
+ MAX77826_REG_LDO_OPMD1 = 0x10,
+ MAX77826_REG_LDO_OPMD2,
+ MAX77826_REG_LDO_OPMD3,
+ MAX77826_REG_LDO_OPMD4,
+ MAX77826_REG_B_BB_OPMD,
+ /* 0x15 - 0x1F: Reserved */
+ MAX77826_REG_LDO1_CFG = 0x20,
+ MAX77826_REG_LDO2_CFG,
+ MAX77826_REG_LDO3_CFG,
+ MAX77826_REG_LDO4_CFG,
+ MAX77826_REG_LDO5_CFG,
+ MAX77826_REG_LDO6_CFG,
+ MAX77826_REG_LDO7_CFG,
+ MAX77826_REG_LDO8_CFG,
+ MAX77826_REG_LDO9_CFG,
+ MAX77826_REG_LDO10_CFG,
+ MAX77826_REG_LDO11_CFG,
+ MAX77826_REG_LDO12_CFG,
+ MAX77826_REG_LDO13_CFG,
+ MAX77826_REG_LDO14_CFG,
+ MAX77826_REG_LDO15_CFG,
+ /* 0x2F: Reserved */
+ MAX77826_REG_BUCK_CFG = 0x30,
+ MAX77826_REG_BUCK_VOUT,
+ MAX77826_REG_BB_CFG,
+ MAX77826_REG_BB_VOUT,
+ /* 0x34 - 0x3F: Reserved */
+ MAX77826_REG_BUCK_SS_FREQ = 0x40,
+ MAX77826_REG_UVLO_FALL,
+ /* 0x42 - 0xCE: Reserved */
+ MAX77826_REG_DEVICE_ID = 0xCF,
+};
+
+enum max77826_regulators {
+ MAX77826_LDO1 = 0,
+ MAX77826_LDO2,
+ MAX77826_LDO3,
+ MAX77826_LDO4,
+ MAX77826_LDO5,
+ MAX77826_LDO6,
+ MAX77826_LDO7,
+ MAX77826_LDO8,
+ MAX77826_LDO9,
+ MAX77826_LDO10,
+ MAX77826_LDO11,
+ MAX77826_LDO12,
+ MAX77826_LDO13,
+ MAX77826_LDO14,
+ MAX77826_LDO15,
+ MAX77826_BUCK,
+ MAX77826_BUCKBOOST,
+ MAX77826_MAX_REGULATORS,
+};
+
+#define MAX77826_MASK_LDO 0x7f
+#define MAX77826_MASK_BUCK 0xff
+#define MAX77826_MASK_BUCKBOOST 0x7f
+#define MAX77826_BUCK_RAMP_DELAY 12500
+
+/* values in mV */
+/* for LDO1-3 */
+#define MAX77826_NMOS_LDO_VOLT_MIN 600000
+#define MAX77826_NMOS_LDO_VOLT_MAX 2187500
+#define MAX77826_NMOS_LDO_VOLT_STEP 12500
+
+/* for LDO4-15 */
+#define MAX77826_PMOS_LDO_VOLT_MIN 800000
+#define MAX77826_PMOS_LDO_VOLT_MAX 3975000
+#define MAX77826_PMOS_LDO_VOLT_STEP 25000
+
+/* for BUCK */
+#define MAX77826_BUCK_VOLT_MIN 500000
+#define MAX77826_BUCK_VOLT_MAX 1800000
+#define MAX77826_BUCK_VOLT_STEP 6250
+
+/* for BUCKBOOST */
+#define MAX77826_BUCKBOOST_VOLT_MIN 2600000
+#define MAX77826_BUCKBOOST_VOLT_MAX 4187500
+#define MAX77826_BUCKBOOST_VOLT_STEP 12500
+#define MAX77826_VOLT_RANGE(_type) \
+ ((MAX77826_ ## _type ## _VOLT_MAX - \
+ MAX77826_ ## _type ## _VOLT_MIN) / \
+ MAX77826_ ## _type ## _VOLT_STEP + 1)
+
+#define MAX77826_LDO(_id, _type) \
+ [MAX77826_LDO ## _id] = { \
+ .id = MAX77826_LDO ## _id, \
+ .name = "LDO"#_id, \
+ .of_match = of_match_ptr("LDO"#_id), \
+ .regulators_node = "regulators", \
+ .ops = &max77826_most_ops, \
+ .min_uV = MAX77826_ ## _type ## _LDO_VOLT_MIN, \
+ .uV_step = MAX77826_ ## _type ## _LDO_VOLT_STEP, \
+ .n_voltages = MAX77826_VOLT_RANGE(_type ## _LDO), \
+ .enable_reg = MAX77826_REG_LDO_OPMD1 + (_id - 1) / 4, \
+ .enable_mask = BIT(((_id - 1) % 4) * 2 + 1), \
+ .vsel_reg = MAX77826_REG_LDO1_CFG + (_id - 1), \
+ .vsel_mask = MAX77826_MASK_LDO, \
+ .owner = THIS_MODULE, \
+ }
+
+#define MAX77826_BUCK(_idx, _id, _ops) \
+ [MAX77826_ ## _id] = { \
+ .id = MAX77826_ ## _id, \
+ .name = #_id, \
+ .of_match = of_match_ptr(#_id), \
+ .regulators_node = "regulators", \
+ .ops = &_ops, \
+ .min_uV = MAX77826_ ## _id ## _VOLT_MIN, \
+ .uV_step = MAX77826_ ## _id ## _VOLT_STEP, \
+ .n_voltages = MAX77826_VOLT_RANGE(_id), \
+ .enable_reg = MAX77826_REG_B_BB_OPMD, \
+ .enable_mask = BIT(_idx * 2 + 1), \
+ .vsel_reg = MAX77826_REG_BUCK_VOUT + _idx * 2, \
+ .vsel_mask = MAX77826_MASK_ ## _id, \
+ .owner = THIS_MODULE, \
+ }
+
+
+
+struct max77826_regulator_info {
+ struct regmap *regmap;
+ struct regulator_desc *rdesc;
+};
+
+static const struct regmap_config max77826_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MAX77826_REG_DEVICE_ID,
+};
+
+static int max77826_set_voltage_time_sel(struct regulator_dev *,
+ unsigned int old_selector,
+ unsigned int new_selector);
+
+static const struct regulator_ops max77826_most_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static const struct regulator_ops max77826_buck_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = max77826_set_voltage_time_sel,
+};
+
+static struct regulator_desc max77826_regulators_desc[] = {
+ MAX77826_LDO(1, NMOS),
+ MAX77826_LDO(2, NMOS),
+ MAX77826_LDO(3, NMOS),
+ MAX77826_LDO(4, PMOS),
+ MAX77826_LDO(5, PMOS),
+ MAX77826_LDO(6, PMOS),
+ MAX77826_LDO(7, PMOS),
+ MAX77826_LDO(8, PMOS),
+ MAX77826_LDO(9, PMOS),
+ MAX77826_LDO(10, PMOS),
+ MAX77826_LDO(11, PMOS),
+ MAX77826_LDO(12, PMOS),
+ MAX77826_LDO(13, PMOS),
+ MAX77826_LDO(14, PMOS),
+ MAX77826_LDO(15, PMOS),
+ MAX77826_BUCK(0, BUCK, max77826_buck_ops),
+ MAX77826_BUCK(1, BUCKBOOST, max77826_most_ops),
+};
+
+static int max77826_set_voltage_time_sel(struct regulator_dev *rdev,
+ unsigned int old_selector,
+ unsigned int new_selector)
+{
+ if (new_selector > old_selector) {
+ return DIV_ROUND_UP(MAX77826_BUCK_VOLT_STEP *
+ (new_selector - old_selector),
+ MAX77826_BUCK_RAMP_DELAY);
+ }
+
+ return 0;
+}
+
+static int max77826_read_device_id(struct regmap *regmap, struct device *dev)
+{
+ unsigned int device_id;
+ int res;
+
+ res = regmap_read(regmap, MAX77826_REG_DEVICE_ID, &device_id);
+ if (!res)
+ dev_dbg(dev, "DEVICE_ID: 0x%x\n", device_id);
+
+ return res;
+}
+
+static int max77826_i2c_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct max77826_regulator_info *info;
+ struct regulator_config config = {};
+ struct regulator_dev *rdev;
+ struct regmap *regmap;
+ int i;
+
+ info = devm_kzalloc(dev, sizeof(struct max77826_regulator_info),
+ GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->rdesc = max77826_regulators_desc;
+ regmap = devm_regmap_init_i2c(client, &max77826_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "Failed to allocate regmap!\n");
+ return PTR_ERR(regmap);
+ }
+
+ info->regmap = regmap;
+ i2c_set_clientdata(client, info);
+
+ config.dev = dev;
+ config.regmap = regmap;
+ config.driver_data = info;
+
+ for (i = 0; i < MAX77826_MAX_REGULATORS; i++) {
+ rdev = devm_regulator_register(dev,
+ &max77826_regulators_desc[i],
+ &config);
+ if (IS_ERR(rdev)) {
+ dev_err(dev, "Failed to register regulator!\n");
+ return PTR_ERR(rdev);
+ }
+ }
+
+ return max77826_read_device_id(regmap, dev);
+}
+
+static const struct of_device_id __maybe_unused max77826_of_match[] = {
+ { .compatible = "maxim,max77826" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, max77826_of_match);
+
+static const struct i2c_device_id max77826_id[] = {
+ { "max77826-regulator" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, max77826_id);
+
+static struct i2c_driver max77826_regulator_driver = {
+ .driver = {
+ .name = "max77826",
+ .of_match_table = of_match_ptr(max77826_of_match),
+ },
+ .probe_new = max77826_i2c_probe,
+ .id_table = max77826_id,
+};
+module_i2c_driver(max77826_regulator_driver);
+
+MODULE_AUTHOR("Iskren Chernev <iskren.chernev@gmail.com>");
+MODULE_DESCRIPTION("MAX77826 PMIC regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c
index 96dc0ee..1a6fd68 100644
--- a/drivers/regulator/max8907-regulator.c
+++ b/drivers/regulator/max8907-regulator.c
@@ -109,7 +109,7 @@
static const struct regulator_ops max8907_mbatt_ops = {
};
-static struct regulator_ops max8907_ldo_ops = {
+static const struct regulator_ops max8907_ldo_ops = {
.list_voltage = regulator_list_voltage_linear,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -128,7 +128,7 @@
.list_voltage = regulator_list_voltage_linear,
};
-static struct regulator_ops max8907_out5v_ops = {
+static const struct regulator_ops max8907_out5v_ops = {
.list_voltage = regulator_list_voltage_linear,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -145,7 +145,7 @@
.get_voltage_sel = regulator_get_voltage_sel_regmap,
};
-static struct regulator_desc max8907_regulators[] = {
+static const struct regulator_desc max8907_regulators[] = {
REG_MBATT(),
REG_LDO(SD1, "in-v1", MAX8907_REG_SDCTL1, 650000, 2225000, 25000),
REG_LDO(SD2, "in-v2", MAX8907_REG_SDCTL2, 637500, 1425000, 12500),
diff --git a/drivers/regulator/max8997-regulator.c b/drivers/regulator/max8997-regulator.c
index 4d24872..ba47a5e 100644
--- a/drivers/regulator/max8997-regulator.c
+++ b/drivers/regulator/max8997-regulator.c
@@ -732,7 +732,7 @@
return max8997_update_reg(i2c, reg, ~pattern, mask);
}
-static struct regulator_ops max8997_ldo_ops = {
+static const struct regulator_ops max8997_ldo_ops = {
.list_voltage = max8997_list_voltage,
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
@@ -742,7 +742,7 @@
.set_suspend_disable = max8997_reg_disable_suspend,
};
-static struct regulator_ops max8997_buck_ops = {
+static const struct regulator_ops max8997_buck_ops = {
.list_voltage = max8997_list_voltage,
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
@@ -753,7 +753,7 @@
.set_suspend_disable = max8997_reg_disable_suspend,
};
-static struct regulator_ops max8997_fixedvolt_ops = {
+static const struct regulator_ops max8997_fixedvolt_ops = {
.list_voltage = max8997_list_voltage,
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
@@ -761,7 +761,7 @@
.set_suspend_disable = max8997_reg_disable_suspend,
};
-static struct regulator_ops max8997_safeout_ops = {
+static const struct regulator_ops max8997_safeout_ops = {
.list_voltage = regulator_list_voltage_table,
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
@@ -771,7 +771,7 @@
.set_suspend_disable = max8997_reg_disable_suspend,
};
-static struct regulator_ops max8997_fixedstate_ops = {
+static const struct regulator_ops max8997_fixedstate_ops = {
.list_voltage = max8997_list_voltage_charger_cv,
.get_voltage_sel = max8997_get_voltage_sel,
.set_voltage = max8997_set_voltage_charger_cv,
@@ -805,7 +805,7 @@
return max8997_list_voltage(rdev, sel);
}
-static struct regulator_ops max8997_charger_ops = {
+static const struct regulator_ops max8997_charger_ops = {
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
.disable = max8997_reg_disable,
@@ -813,7 +813,7 @@
.set_current_limit = max8997_set_current_limit,
};
-static struct regulator_ops max8997_charger_fixedstate_ops = {
+static const struct regulator_ops max8997_charger_fixedstate_ops = {
.get_current_limit = max8997_get_current_limit,
.set_current_limit = max8997_set_current_limit,
};
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
index 60599c3..ac69bdd 100644
--- a/drivers/regulator/max8998.c
+++ b/drivers/regulator/max8998.c
@@ -33,6 +33,10 @@
unsigned int buck2_idx;
};
+static const unsigned int charger_current_table[] = {
+ 90000, 380000, 475000, 550000, 570000, 600000, 700000, 800000,
+};
+
static int max8998_get_enable_register(struct regulator_dev *rdev,
int *reg, int *shift)
{
@@ -63,6 +67,10 @@
*reg = MAX8998_REG_CHGR2;
*shift = 7 - (ldo - MAX8998_ESAFEOUT1);
break;
+ case MAX8998_CHARGER:
+ *reg = MAX8998_REG_CHGR2;
+ *shift = 0;
+ break;
default:
return -EINVAL;
}
@@ -88,6 +96,11 @@
return val & (1 << shift);
}
+static int max8998_ldo_is_enabled_inverted(struct regulator_dev *rdev)
+{
+ return (!max8998_ldo_is_enabled(rdev));
+}
+
static int max8998_ldo_enable(struct regulator_dev *rdev)
{
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
@@ -358,6 +371,74 @@
return 0;
}
+static int max8998_set_current_limit(struct regulator_dev *rdev,
+ int min_uA, int max_uA)
+{
+ struct max8998_data *max8998 = rdev_get_drvdata(rdev);
+ struct i2c_client *i2c = max8998->iodev->i2c;
+ unsigned int n_currents = rdev->desc->n_current_limits;
+ int i, sel = -1;
+
+ if (n_currents == 0)
+ return -EINVAL;
+
+ if (rdev->desc->curr_table) {
+ const unsigned int *curr_table = rdev->desc->curr_table;
+ bool ascend = curr_table[n_currents - 1] > curr_table[0];
+
+ /* search for closest to maximum */
+ if (ascend) {
+ for (i = n_currents - 1; i >= 0; i--) {
+ if (min_uA <= curr_table[i] &&
+ curr_table[i] <= max_uA) {
+ sel = i;
+ break;
+ }
+ }
+ } else {
+ for (i = 0; i < n_currents; i++) {
+ if (min_uA <= curr_table[i] &&
+ curr_table[i] <= max_uA) {
+ sel = i;
+ break;
+ }
+ }
+ }
+ }
+
+ if (sel < 0)
+ return -EINVAL;
+
+ sel <<= ffs(rdev->desc->csel_mask) - 1;
+
+ return max8998_update_reg(i2c, rdev->desc->csel_reg,
+ sel, rdev->desc->csel_mask);
+}
+
+static int max8998_get_current_limit(struct regulator_dev *rdev)
+{
+ struct max8998_data *max8998 = rdev_get_drvdata(rdev);
+ struct i2c_client *i2c = max8998->iodev->i2c;
+ u8 val;
+ int ret;
+
+ ret = max8998_read_reg(i2c, rdev->desc->csel_reg, &val);
+ if (ret != 0)
+ return ret;
+
+ val &= rdev->desc->csel_mask;
+ val >>= ffs(rdev->desc->csel_mask) - 1;
+
+ if (rdev->desc->curr_table) {
+ if (val >= rdev->desc->n_current_limits)
+ return -EINVAL;
+
+ return rdev->desc->curr_table[val];
+ }
+
+ return -EINVAL;
+}
+
static const struct regulator_ops max8998_ldo_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
@@ -379,6 +460,15 @@
.set_voltage_time_sel = max8998_set_voltage_buck_time_sel,
};
+static const struct regulator_ops max8998_charger_ops = {
+ .set_current_limit = max8998_set_current_limit,
+ .get_current_limit = max8998_get_current_limit,
+ .is_enabled = max8998_ldo_is_enabled_inverted,
+ /* Swapped as register is inverted */
+ .enable = max8998_ldo_disable,
+ .disable = max8998_ldo_enable,
+};
+
static const struct regulator_ops max8998_others_ops = {
.is_enabled = max8998_ldo_is_enabled,
.enable = max8998_ldo_enable,
@@ -397,6 +487,19 @@
.owner = THIS_MODULE, \
}
+#define MAX8998_CURRENT_REG(_name, _ops, _table, _reg, _mask) \
+ { \
+ .name = #_name, \
+ .id = MAX8998_##_name, \
+ .ops = _ops, \
+ .curr_table = _table, \
+ .n_current_limits = ARRAY_SIZE(_table), \
+ .csel_reg = _reg, \
+ .csel_mask = _mask, \
+ .type = REGULATOR_CURRENT, \
+ .owner = THIS_MODULE, \
+ }
+
#define MAX8998_OTHERS_REG(_name, _id) \
{ \
.name = #_name, \
@@ -432,6 +535,8 @@
MAX8998_OTHERS_REG(ENVICHG, MAX8998_ENVICHG),
MAX8998_OTHERS_REG(ESAFEOUT1, MAX8998_ESAFEOUT1),
MAX8998_OTHERS_REG(ESAFEOUT2, MAX8998_ESAFEOUT2),
+ MAX8998_CURRENT_REG(CHARGER, &max8998_charger_ops,
+ charger_current_table, MAX8998_REG_CHGR1, 0x7),
};
static int max8998_pmic_dt_parse_dvs_gpio(struct max8998_dev *iodev,
diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c
index e5a0271..6d0ad74 100644
--- a/drivers/regulator/mcp16502.c
+++ b/drivers/regulator/mcp16502.c
@@ -391,11 +391,11 @@
};
MODULE_DEVICE_TABLE(of, mcp16502_ids);
-static const struct regulator_linear_range b1l12_ranges[] = {
+static const struct linear_range b1l12_ranges[] = {
REGULATOR_LINEAR_RANGE(1200000, VDD_LOW_SEL, VDD_HIGH_SEL, 50000),
};
-static const struct regulator_linear_range b234_ranges[] = {
+static const struct linear_range b234_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, VDD_LOW_SEL, VDD_HIGH_SEL, 25000),
};
diff --git a/drivers/regulator/mp5416.c b/drivers/regulator/mp5416.c
new file mode 100644
index 0000000..67ce1b5
--- /dev/null
+++ b/drivers/regulator/mp5416.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// mp5416.c - regulator driver for mps mp5416
+//
+// Copyright 2020 Monolithic Power Systems, Inc
+//
+// Author: Saravanan Sekar <sravanhome@gmail.com>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/i2c.h>
+
+#define MP5416_REG_CTL0 0x00
+#define MP5416_REG_CTL1 0x01
+#define MP5416_REG_CTL2 0x02
+#define MP5416_REG_ILIM 0x03
+#define MP5416_REG_BUCK1 0x04
+#define MP5416_REG_BUCK2 0x05
+#define MP5416_REG_BUCK3 0x06
+#define MP5416_REG_BUCK4 0x07
+#define MP5416_REG_LDO1 0x08
+#define MP5416_REG_LDO2 0x09
+#define MP5416_REG_LDO3 0x0a
+#define MP5416_REG_LDO4 0x0b
+
+#define MP5416_REGULATOR_EN BIT(7)
+#define MP5416_MASK_VSET 0x7f
+#define MP5416_MASK_BUCK1_ILIM 0xc0
+#define MP5416_MASK_BUCK2_ILIM 0x0c
+#define MP5416_MASK_BUCK3_ILIM 0x30
+#define MP5416_MASK_BUCK4_ILIM 0x03
+#define MP5416_MASK_DVS_SLEWRATE 0xc0
+
+/* values in uV */
+#define MP5416_VOLT1_MIN 600000
+#define MP5416_VOLT1_MAX 2187500
+#define MP5416_VOLT1_STEP 12500
+#define MP5416_VOLT2_MIN 800000
+#define MP5416_VOLT2_MAX 3975000
+#define MP5416_VOLT2_STEP 25000
+
+#define MP5416_VOLT1_RANGE \
+ ((MP5416_VOLT1_MAX - MP5416_VOLT1_MIN)/MP5416_VOLT1_STEP + 1)
+#define MP5416_VOLT2_RANGE \
+ ((MP5416_VOLT2_MAX - MP5416_VOLT2_MIN)/MP5416_VOLT2_STEP + 1)
+
+#define MP5416BUCK(_name, _id, _ilim, _dreg, _dval, _vsel) \
+ [MP5416_BUCK ## _id] = { \
+ .id = MP5416_BUCK ## _id, \
+ .name = _name, \
+ .of_match = _name, \
+ .regulators_node = "regulators", \
+ .ops = &mp5416_buck_ops, \
+ .min_uV = MP5416_VOLT ##_vsel## _MIN, \
+ .uV_step = MP5416_VOLT ##_vsel## _STEP, \
+ .n_voltages = MP5416_VOLT ##_vsel## _RANGE, \
+ .curr_table = _ilim, \
+ .n_current_limits = ARRAY_SIZE(_ilim), \
+ .csel_reg = MP5416_REG_ILIM, \
+ .csel_mask = MP5416_MASK_BUCK ## _id ##_ILIM, \
+ .vsel_reg = MP5416_REG_BUCK ## _id, \
+ .vsel_mask = MP5416_MASK_VSET, \
+ .enable_reg = MP5416_REG_BUCK ## _id, \
+ .enable_mask = MP5416_REGULATOR_EN, \
+ .active_discharge_on = _dval, \
+ .active_discharge_reg = _dreg, \
+ .active_discharge_mask = _dval, \
+ .owner = THIS_MODULE, \
+ }
+
+#define MP5416LDO(_name, _id, _dval) \
+ [MP5416_LDO ## _id] = { \
+ .id = MP5416_LDO ## _id, \
+ .name = _name, \
+ .of_match = _name, \
+ .regulators_node = "regulators", \
+ .ops = &mp5416_ldo_ops, \
+ .min_uV = MP5416_VOLT2_MIN, \
+ .uV_step = MP5416_VOLT2_STEP, \
+ .n_voltages = MP5416_VOLT2_RANGE, \
+ .vsel_reg = MP5416_REG_LDO ##_id, \
+ .vsel_mask = MP5416_MASK_VSET, \
+ .enable_reg = MP5416_REG_LDO ##_id, \
+ .enable_mask = MP5416_REGULATOR_EN, \
+ .active_discharge_on = _dval, \
+ .active_discharge_reg = MP5416_REG_CTL2, \
+ .active_discharge_mask = _dval, \
+ .owner = THIS_MODULE, \
+ }
+
+enum mp5416_regulators {
+ MP5416_BUCK1,
+ MP5416_BUCK2,
+ MP5416_BUCK3,
+ MP5416_BUCK4,
+ MP5416_LDO1,
+ MP5416_LDO2,
+ MP5416_LDO3,
+ MP5416_LDO4,
+ MP5416_MAX_REGULATORS,
+};
+
+static const struct regmap_config mp5416_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x0d,
+};
+
+/* Current limits array (in uA)
+ * ILIM1 & ILIM3
+ */
+static const unsigned int mp5416_I_limits1[] = {
+ 3800000, 4600000, 5600000, 6800000
+};
+
+/* ILIM2 & ILIM4 */
+static const unsigned int mp5416_I_limits2[] = {
+ 2200000, 3200000, 4200000, 5200000
+};
+
+static int mp5416_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay);
+
+static const struct regulator_ops mp5416_ldo_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+};
+
+static const struct regulator_ops mp5416_buck_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .set_ramp_delay = mp5416_set_ramp_delay,
+};
+
+static struct regulator_desc mp5416_regulators_desc[MP5416_MAX_REGULATORS] = {
+ MP5416BUCK("buck1", 1, mp5416_I_limits1, MP5416_REG_CTL1, BIT(0), 1),
+ MP5416BUCK("buck2", 2, mp5416_I_limits2, MP5416_REG_CTL1, BIT(1), 2),
+ MP5416BUCK("buck3", 3, mp5416_I_limits1, MP5416_REG_CTL1, BIT(2), 1),
+ MP5416BUCK("buck4", 4, mp5416_I_limits2, MP5416_REG_CTL2, BIT(5), 2),
+ MP5416LDO("ldo1", 1, BIT(4)),
+ MP5416LDO("ldo2", 2, BIT(3)),
+ MP5416LDO("ldo3", 3, BIT(2)),
+ MP5416LDO("ldo4", 4, BIT(1)),
+};
+
+/*
+ * DVS ramp rate BUCK1 to BUCK4
+ * 00: 32mV/us
+ * 01: 16mV/us
+ * 10: 8mV/us
+ * 11: 4mV/us
+ */
+static int mp5416_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+ unsigned int ramp_val;
+
+ if (ramp_delay > 32000 || ramp_delay < 0)
+ return -EINVAL;
+
+ if (ramp_delay <= 4000)
+ ramp_val = 3;
+ else if (ramp_delay <= 8000)
+ ramp_val = 2;
+ else if (ramp_delay <= 16000)
+ ramp_val = 1;
+ else
+ ramp_val = 0;
+
+ return regmap_update_bits(rdev->regmap, MP5416_REG_CTL2,
+ MP5416_MASK_DVS_SLEWRATE, ramp_val << 6);
+}
+
+static int mp5416_i2c_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct regulator_config config = { NULL, };
+ struct regulator_dev *rdev;
+ struct regmap *regmap;
+ int i;
+
+ regmap = devm_regmap_init_i2c(client, &mp5416_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "Failed to allocate regmap!\n");
+ return PTR_ERR(regmap);
+ }
+
+ config.dev = dev;
+ config.regmap = regmap;
+
+ for (i = 0; i < MP5416_MAX_REGULATORS; i++) {
+ rdev = devm_regulator_register(dev,
+ &mp5416_regulators_desc[i],
+ &config);
+ if (IS_ERR(rdev)) {
+ dev_err(dev, "Failed to register regulator!\n");
+ return PTR_ERR(rdev);
+ }
+ }
+
+ return 0;
+}
+
+static const struct of_device_id mp5416_of_match[] = {
+ { .compatible = "mps,mp5416" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mp5416_of_match);
+
+static const struct i2c_device_id mp5416_id[] = {
+ { "mp5416", },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, mp5416_id);
+
+static struct i2c_driver mp5416_regulator_driver = {
+ .driver = {
+ .name = "mp5416",
+ .of_match_table = of_match_ptr(mp5416_of_match),
+ },
+ .probe_new = mp5416_i2c_probe,
+ .id_table = mp5416_id,
+};
+module_i2c_driver(mp5416_regulator_driver);
+
+MODULE_AUTHOR("Saravanan Sekar <sravanhome@gmail.com>");
+MODULE_DESCRIPTION("MP5416 PMIC regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/mp8859.c b/drivers/regulator/mp8859.c
new file mode 100644
index 0000000..f230071
--- /dev/null
+++ b/drivers/regulator/mp8859.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2019 five technologies GmbH
+// Author: Markus Reichl <m.reichl@fivetechno.de>
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/of.h>
+#include <linux/regulator/driver.h>
+#include <linux/regmap.h>
+
+
+#define VOL_MIN_IDX 0x00
+#define VOL_MAX_IDX 0x7ff
+
+/* Register definitions */
+#define MP8859_VOUT_L_REG 0 //3 lo Bits
+#define MP8859_VOUT_H_REG 1 //8 hi Bits
+#define MP8859_VOUT_GO_REG 2
+#define MP8859_IOUT_LIM_REG 3
+#define MP8859_CTL1_REG 4
+#define MP8859_CTL2_REG 5
+#define MP8859_RESERVED1_REG 6
+#define MP8859_RESERVED2_REG 7
+#define MP8859_RESERVED3_REG 8
+#define MP8859_STATUS_REG 9
+#define MP8859_INTERRUPT_REG 0x0A
+#define MP8859_MASK_REG 0x0B
+#define MP8859_ID1_REG 0x0C
+#define MP8859_MFR_ID_REG 0x27
+#define MP8859_DEV_ID_REG 0x28
+#define MP8859_IC_REV_REG 0x29
+
+#define MP8859_MAX_REG 0x29
+
+#define MP8859_GO_BIT 0x01
+
+
+static int mp8859_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
+{
+ int ret;
+
+ ret = regmap_write(rdev->regmap, MP8859_VOUT_L_REG, sel & 0x7);
+
+ if (ret)
+ return ret;
+ ret = regmap_write(rdev->regmap, MP8859_VOUT_H_REG, sel >> 3);
+
+ if (ret)
+ return ret;
+ ret = regmap_update_bits(rdev->regmap, MP8859_VOUT_GO_REG,
+ MP8859_GO_BIT, 1);
+ return ret;
+}
+
+static int mp8859_get_voltage_sel(struct regulator_dev *rdev)
+{
+ unsigned int val_tmp;
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, MP8859_VOUT_H_REG, &val_tmp);
+
+ if (ret)
+ return ret;
+ val = val_tmp << 3;
+
+ ret = regmap_read(rdev->regmap, MP8859_VOUT_L_REG, &val_tmp);
+
+ if (ret)
+ return ret;
+ val |= val_tmp & 0x07;
+ return val;
+}
+
+static const struct linear_range mp8859_dcdc_ranges[] = {
+ REGULATOR_LINEAR_RANGE(0, VOL_MIN_IDX, VOL_MAX_IDX, 10000),
+};
+
+static const struct regmap_config mp8859_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MP8859_MAX_REG,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static const struct regulator_ops mp8859_ops = {
+ .set_voltage_sel = mp8859_set_voltage_sel,
+ .get_voltage_sel = mp8859_get_voltage_sel,
+ .list_voltage = regulator_list_voltage_linear_range,
+};
+
+static const struct regulator_desc mp8859_regulators[] = {
+ {
+ .id = 0,
+ .type = REGULATOR_VOLTAGE,
+ .name = "mp8859_dcdc",
+ .supply_name = "vin",
+ .of_match = of_match_ptr("mp8859_dcdc"),
+ .n_voltages = VOL_MAX_IDX + 1,
+ .linear_ranges = mp8859_dcdc_ranges,
+ .n_linear_ranges = 1,
+ .ops = &mp8859_ops,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int mp8859_i2c_probe(struct i2c_client *i2c)
+{
+ int ret;
+ struct regulator_config config = {.dev = &i2c->dev};
+ struct regmap *regmap = devm_regmap_init_i2c(i2c, &mp8859_regmap);
+ struct regulator_dev *rdev;
+
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
+ return ret;
+ }
+ rdev = devm_regulator_register(&i2c->dev, &mp8859_regulators[0],
+ &config);
+
+ if (IS_ERR(rdev)) {
+ ret = PTR_ERR(rdev);
+ dev_err(&i2c->dev, "failed to register %s: %d\n",
+ mp8859_regulators[0].name, ret);
+ return ret;
+ }
+ return 0;
+}
+
+static const struct of_device_id mp8859_dt_id[] = {
+ {.compatible = "mps,mp8859"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, mp8859_dt_id);
+
+static const struct i2c_device_id mp8859_i2c_id[] = {
+ { "mp8859", },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, mp8859_i2c_id);
+
+static struct i2c_driver mp8859_regulator_driver = {
+ .driver = {
+ .name = "mp8859",
+ .of_match_table = of_match_ptr(mp8859_dt_id),
+ },
+ .probe_new = mp8859_i2c_probe,
+ .id_table = mp8859_i2c_id,
+};
+
+module_i2c_driver(mp8859_regulator_driver);
+
+MODULE_DESCRIPTION("Monolithic Power Systems MP8859 voltage regulator driver");
+MODULE_AUTHOR("Markus Reichl <m.reichl@fivetechno.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c
new file mode 100644
index 0000000..a84fd74
--- /dev/null
+++ b/drivers/regulator/mp886x.c
@@ -0,0 +1,392 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// MP8867/MP8869 regulator driver
+//
+// Copyright (C) 2020 Synaptics Incorporated
+//
+// Author: Jisheng Zhang <jszhang@kernel.org>
+
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+#define MP886X_VSEL 0x00
+#define MP886X_V_BOOT (1 << 7)
+#define MP886X_SYSCNTLREG1 0x01
+#define MP886X_MODE (1 << 0)
+#define MP886X_SLEW_SHIFT 3
+#define MP886X_SLEW_MASK (0x7 << MP886X_SLEW_SHIFT)
+#define MP886X_GO (1 << 6)
+#define MP886X_EN (1 << 7)
+#define MP8869_SYSCNTLREG2 0x02
+
+struct mp886x_cfg_info {
+ const struct regulator_ops *rops;
+ const int slew_rates[8];
+ const int switch_freq[4];
+ const u8 fs_reg;
+ const u8 fs_shift;
+};
+
+struct mp886x_device_info {
+ struct device *dev;
+ struct regulator_desc desc;
+ struct regulator_init_data *regulator;
+ struct gpio_desc *en_gpio;
+ const struct mp886x_cfg_info *ci;
+ u32 r[2];
+ unsigned int sel;
+};
+
+static int mp886x_set_ramp(struct regulator_dev *rdev, int ramp)
+{
+ struct mp886x_device_info *di = rdev_get_drvdata(rdev);
+ const struct mp886x_cfg_info *ci = di->ci;
+ int reg = -1, i;
+
+ for (i = 0; i < ARRAY_SIZE(ci->slew_rates); i++) {
+ if (ramp <= ci->slew_rates[i])
+ reg = i;
+ else
+ break;
+ }
+
+ if (reg < 0) {
+ dev_err(di->dev, "unsupported ramp value %d\n", ramp);
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
+ MP886X_SLEW_MASK, reg << MP886X_SLEW_SHIFT);
+}
+
+static void mp886x_set_switch_freq(struct mp886x_device_info *di,
+ struct regmap *regmap,
+ u32 freq)
+{
+ const struct mp886x_cfg_info *ci = di->ci;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ci->switch_freq); i++) {
+ if (freq == ci->switch_freq[i]) {
+ regmap_update_bits(regmap, ci->fs_reg,
+ 0x3 << ci->fs_shift, i << ci->fs_shift);
+ return;
+ }
+ }
+
+ dev_err(di->dev, "invalid frequency %d\n", freq);
+}
+
+static int mp886x_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
+ MP886X_MODE, MP886X_MODE);
+ break;
+ case REGULATOR_MODE_NORMAL:
+ regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
+ MP886X_MODE, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static unsigned int mp886x_get_mode(struct regulator_dev *rdev)
+{
+ u32 val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, MP886X_SYSCNTLREG1, &val);
+ if (ret < 0)
+ return ret;
+ if (val & MP886X_MODE)
+ return REGULATOR_MODE_FAST;
+ else
+ return REGULATOR_MODE_NORMAL;
+}
+
+static int mp8869_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
+{
+ int ret;
+
+ ret = regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
+ MP886X_GO, MP886X_GO);
+ if (ret < 0)
+ return ret;
+
+ sel <<= ffs(rdev->desc->vsel_mask) - 1;
+ return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
+ MP886X_V_BOOT | rdev->desc->vsel_mask, sel);
+}
+
+static inline unsigned int mp8869_scale(unsigned int uv, u32 r1, u32 r2)
+{
+ u32 tmp = uv * r1 / r2;
+
+ return uv + tmp;
+}
+
+static int mp8869_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct mp886x_device_info *di = rdev_get_drvdata(rdev);
+ int ret, uv;
+ unsigned int val;
+ bool fbloop;
+
+ ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
+ if (ret)
+ return ret;
+
+ fbloop = val & MP886X_V_BOOT;
+ if (fbloop) {
+ uv = rdev->desc->min_uV;
+ uv = mp8869_scale(uv, di->r[0], di->r[1]);
+ return regulator_map_voltage_linear(rdev, uv, uv);
+ }
+
+ val &= rdev->desc->vsel_mask;
+ val >>= ffs(rdev->desc->vsel_mask) - 1;
+
+ return val;
+}
+
+static const struct regulator_ops mp8869_regulator_ops = {
+ .set_voltage_sel = mp8869_set_voltage_sel,
+ .get_voltage_sel = mp8869_get_voltage_sel,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .map_voltage = regulator_map_voltage_linear,
+ .list_voltage = regulator_list_voltage_linear,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mp886x_set_mode,
+ .get_mode = mp886x_get_mode,
+ .set_ramp_delay = mp886x_set_ramp,
+};
+
+static const struct mp886x_cfg_info mp8869_ci = {
+ .rops = &mp8869_regulator_ops,
+ .slew_rates = {
+ 40000,
+ 30000,
+ 20000,
+ 10000,
+ 5000,
+ 2500,
+ 1250,
+ 625,
+ },
+ .switch_freq = {
+ 500000,
+ 750000,
+ 1000000,
+ 1250000,
+ },
+ .fs_reg = MP8869_SYSCNTLREG2,
+ .fs_shift = 4,
+};
+
+static int mp8867_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
+{
+ struct mp886x_device_info *di = rdev_get_drvdata(rdev);
+ int ret, delta;
+
+ ret = mp8869_set_voltage_sel(rdev, sel);
+ if (ret < 0)
+ return ret;
+
+ delta = di->sel - sel;
+ if (abs(delta) <= 5)
+ ret = regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
+ MP886X_GO, 0);
+ di->sel = sel;
+
+ return ret;
+}
+
+static int mp8867_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct mp886x_device_info *di = rdev_get_drvdata(rdev);
+ int ret, uv;
+ unsigned int val;
+ bool fbloop;
+
+ ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
+ if (ret)
+ return ret;
+
+ fbloop = val & MP886X_V_BOOT;
+
+ val &= rdev->desc->vsel_mask;
+ val >>= ffs(rdev->desc->vsel_mask) - 1;
+
+ if (fbloop) {
+ uv = regulator_list_voltage_linear(rdev, val);
+ uv = mp8869_scale(uv, di->r[0], di->r[1]);
+ return regulator_map_voltage_linear(rdev, uv, uv);
+ }
+
+ return val;
+}
+
+static const struct regulator_ops mp8867_regulator_ops = {
+ .set_voltage_sel = mp8867_set_voltage_sel,
+ .get_voltage_sel = mp8867_get_voltage_sel,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .map_voltage = regulator_map_voltage_linear,
+ .list_voltage = regulator_list_voltage_linear,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = mp886x_set_mode,
+ .get_mode = mp886x_get_mode,
+ .set_ramp_delay = mp886x_set_ramp,
+};
+
+static const struct mp886x_cfg_info mp8867_ci = {
+ .rops = &mp8867_regulator_ops,
+ .slew_rates = {
+ 64000,
+ 32000,
+ 16000,
+ 8000,
+ 4000,
+ 2000,
+ 1000,
+ 500,
+ },
+ .switch_freq = {
+ 500000,
+ 750000,
+ 1000000,
+ 1500000,
+ },
+ .fs_reg = MP886X_SYSCNTLREG1,
+ .fs_shift = 1,
+};
+
+static int mp886x_regulator_register(struct mp886x_device_info *di,
+ struct regulator_config *config)
+{
+ struct regulator_desc *rdesc = &di->desc;
+ struct regulator_dev *rdev;
+
+ rdesc->name = "mp886x-reg";
+ rdesc->supply_name = "vin";
+ rdesc->ops = di->ci->rops;
+ rdesc->type = REGULATOR_VOLTAGE;
+ rdesc->n_voltages = 128;
+ rdesc->enable_reg = MP886X_SYSCNTLREG1;
+ rdesc->enable_mask = MP886X_EN;
+ rdesc->min_uV = 600000;
+ rdesc->uV_step = 10000;
+ rdesc->vsel_reg = MP886X_VSEL;
+ rdesc->vsel_mask = 0x3f;
+ rdesc->owner = THIS_MODULE;
+
+ rdev = devm_regulator_register(di->dev, &di->desc, config);
+ if (IS_ERR(rdev))
+ return PTR_ERR(rdev);
+ di->sel = rdesc->ops->get_voltage_sel(rdev);
+ return 0;
+}
+
+static const struct regmap_config mp886x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int mp886x_i2c_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct device_node *np = dev->of_node;
+ struct mp886x_device_info *di;
+ struct regulator_config config = { };
+ struct regmap *regmap;
+ u32 freq;
+ int ret;
+
+ di = devm_kzalloc(dev, sizeof(struct mp886x_device_info), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+
+ di->regulator = of_get_regulator_init_data(dev, np, &di->desc);
+ if (!di->regulator) {
+ dev_err(dev, "Platform data not found!\n");
+ return -EINVAL;
+ }
+
+ ret = of_property_read_u32_array(np, "mps,fb-voltage-divider",
+ di->r, 2);
+ if (ret)
+ return ret;
+
+ di->en_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
+ if (IS_ERR(di->en_gpio))
+ return PTR_ERR(di->en_gpio);
+
+ di->ci = of_device_get_match_data(dev);
+ di->dev = dev;
+
+ regmap = devm_regmap_init_i2c(client, &mp886x_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "Failed to allocate regmap!\n");
+ return PTR_ERR(regmap);
+ }
+ i2c_set_clientdata(client, di);
+
+ config.dev = di->dev;
+ config.init_data = di->regulator;
+ config.regmap = regmap;
+ config.driver_data = di;
+ config.of_node = np;
+
+ if (!of_property_read_u32(np, "mps,switch-frequency-hz", &freq))
+ mp886x_set_switch_freq(di, regmap, freq);
+
+ ret = mp886x_regulator_register(di, &config);
+ if (ret < 0)
+ dev_err(dev, "Failed to register regulator!\n");
+ return ret;
+}
+
+static const struct of_device_id mp886x_dt_ids[] = {
+ {
+ .compatible = "mps,mp8867",
+ .data = &mp8867_ci
+ },
+ {
+ .compatible = "mps,mp8869",
+ .data = &mp8869_ci
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mp886x_dt_ids);
+
+static const struct i2c_device_id mp886x_id[] = {
+ { "mp886x", },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, mp886x_id);
+
+static struct i2c_driver mp886x_regulator_driver = {
+ .driver = {
+ .name = "mp886x-regulator",
+ .of_match_table = of_match_ptr(mp886x_dt_ids),
+ },
+ .probe_new = mp886x_i2c_probe,
+ .id_table = mp886x_id,
+};
+module_i2c_driver(mp886x_regulator_driver);
+
+MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
+MODULE_DESCRIPTION("MP886x regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/mpq7920.c b/drivers/regulator/mpq7920.c
new file mode 100644
index 0000000..54c862e
--- /dev/null
+++ b/drivers/regulator/mpq7920.c
@@ -0,0 +1,330 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// mpq7920.c - regulator driver for mps mpq7920
+//
+// Copyright 2019 Monolithic Power Systems, Inc
+//
+// Author: Saravanan Sekar <sravanhome@gmail.com>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include "mpq7920.h"
+
+#define MPQ7920_BUCK_VOLT_RANGE \
+ ((MPQ7920_VOLT_MAX - MPQ7920_BUCK_VOLT_MIN)/MPQ7920_VOLT_STEP + 1)
+#define MPQ7920_LDO_VOLT_RANGE \
+ ((MPQ7920_VOLT_MAX - MPQ7920_LDO_VOLT_MIN)/MPQ7920_VOLT_STEP + 1)
+
+#define MPQ7920BUCK(_name, _id, _ilim) \
+ [MPQ7920_BUCK ## _id] = { \
+ .id = MPQ7920_BUCK ## _id, \
+ .name = _name, \
+ .of_match = _name, \
+ .regulators_node = "regulators", \
+ .of_parse_cb = mpq7920_parse_cb, \
+ .ops = &mpq7920_buck_ops, \
+ .min_uV = MPQ7920_BUCK_VOLT_MIN, \
+ .uV_step = MPQ7920_VOLT_STEP, \
+ .n_voltages = MPQ7920_BUCK_VOLT_RANGE, \
+ .curr_table = _ilim, \
+ .n_current_limits = ARRAY_SIZE(_ilim), \
+ .csel_reg = MPQ7920_BUCK ##_id## _REG_C, \
+ .csel_mask = MPQ7920_MASK_BUCK_ILIM, \
+ .enable_reg = MPQ7920_REG_REGULATOR_EN, \
+ .enable_mask = BIT(MPQ7920_REGULATOR_EN_OFFSET - \
+ MPQ7920_BUCK ## _id), \
+ .vsel_reg = MPQ7920_BUCK ##_id## _REG_A, \
+ .vsel_mask = MPQ7920_MASK_VREF, \
+ .active_discharge_on = MPQ7920_DISCHARGE_ON, \
+ .active_discharge_reg = MPQ7920_BUCK ##_id## _REG_B, \
+ .active_discharge_mask = MPQ7920_MASK_DISCHARGE, \
+ .soft_start_reg = MPQ7920_BUCK ##_id## _REG_C, \
+ .soft_start_mask = MPQ7920_MASK_SOFTSTART, \
+ .owner = THIS_MODULE, \
+ }
+
+#define MPQ7920LDO(_name, _id, _ops, _ilim, _ilim_sz, _creg, _cmask) \
+ [MPQ7920_LDO ## _id] = { \
+ .id = MPQ7920_LDO ## _id, \
+ .name = _name, \
+ .of_match = _name, \
+ .regulators_node = "regulators", \
+ .ops = _ops, \
+ .min_uV = MPQ7920_LDO_VOLT_MIN, \
+ .uV_step = MPQ7920_VOLT_STEP, \
+ .n_voltages = MPQ7920_LDO_VOLT_RANGE, \
+ .vsel_reg = MPQ7920_LDO ##_id## _REG_A, \
+ .vsel_mask = MPQ7920_MASK_VREF, \
+ .curr_table = _ilim, \
+ .n_current_limits = _ilim_sz, \
+ .csel_reg = _creg, \
+ .csel_mask = _cmask, \
+ .enable_reg = (_id == 1) ? 0 : MPQ7920_REG_REGULATOR_EN,\
+ .enable_mask = BIT(MPQ7920_REGULATOR_EN_OFFSET - \
+ MPQ7920_LDO ##_id + 1), \
+ .active_discharge_on = MPQ7920_DISCHARGE_ON, \
+ .active_discharge_mask = MPQ7920_MASK_DISCHARGE, \
+ .active_discharge_reg = MPQ7920_LDO ##_id## _REG_B, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ }
+
+enum mpq7920_regulators {
+ MPQ7920_BUCK1,
+ MPQ7920_BUCK2,
+ MPQ7920_BUCK3,
+ MPQ7920_BUCK4,
+ MPQ7920_LDO1, /* LDORTC */
+ MPQ7920_LDO2,
+ MPQ7920_LDO3,
+ MPQ7920_LDO4,
+ MPQ7920_LDO5,
+ MPQ7920_MAX_REGULATORS,
+};
+
+struct mpq7920_regulator_info {
+ struct regmap *regmap;
+ struct regulator_desc *rdesc;
+};
+
+static const struct regmap_config mpq7920_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x25,
+};
+
+/* Current limits array (in uA)
+ * ILIM1 & ILIM3
+ */
+static const unsigned int mpq7920_I_limits1[] = {
+ 4600000, 6600000, 7600000, 9300000
+};
+
+/* ILIM2 & ILIM4 */
+static const unsigned int mpq7920_I_limits2[] = {
+ 2700000, 3900000, 5100000, 6100000
+};
+
+/* LDO4 & LDO5 */
+static const unsigned int mpq7920_I_limits3[] = {
+ 300000, 700000
+};
+
+static int mpq7920_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay);
+static int mpq7920_parse_cb(struct device_node *np,
+ const struct regulator_desc *rdesc,
+ struct regulator_config *config);
+
+/* RTCLDO not controllable, always ON */
+static const struct regulator_ops mpq7920_ldortc_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static const struct regulator_ops mpq7920_ldo_wo_current_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+};
+
+static const struct regulator_ops mpq7920_ldo_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
+ .set_current_limit = regulator_set_current_limit_regmap,
+};
+
+static const struct regulator_ops mpq7920_buck_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+ .set_soft_start = regulator_set_soft_start_regmap,
+ .set_ramp_delay = mpq7920_set_ramp_delay,
+};
+
+static struct regulator_desc mpq7920_regulators_desc[MPQ7920_MAX_REGULATORS] = {
+ MPQ7920BUCK("buck1", 1, mpq7920_I_limits1),
+ MPQ7920BUCK("buck2", 2, mpq7920_I_limits2),
+ MPQ7920BUCK("buck3", 3, mpq7920_I_limits1),
+ MPQ7920BUCK("buck4", 4, mpq7920_I_limits2),
+ MPQ7920LDO("ldortc", 1, &mpq7920_ldortc_ops, NULL, 0, 0, 0),
+ MPQ7920LDO("ldo2", 2, &mpq7920_ldo_wo_current_ops, NULL, 0, 0, 0),
+ MPQ7920LDO("ldo3", 3, &mpq7920_ldo_wo_current_ops, NULL, 0, 0, 0),
+ MPQ7920LDO("ldo4", 4, &mpq7920_ldo_ops, mpq7920_I_limits3,
+ ARRAY_SIZE(mpq7920_I_limits3), MPQ7920_LDO4_REG_B,
+ MPQ7920_MASK_LDO_ILIM),
+ MPQ7920LDO("ldo5", 5, &mpq7920_ldo_ops, mpq7920_I_limits3,
+ ARRAY_SIZE(mpq7920_I_limits3), MPQ7920_LDO5_REG_B,
+ MPQ7920_MASK_LDO_ILIM),
+};
+
+/*
+ * DVS ramp rate BUCK1 to BUCK4
+ * 00-01: Reserved
+ * 10: 8mV/us
+ * 11: 4mV/us
+ */
+static int mpq7920_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+ unsigned int ramp_val;
+
+ if (ramp_delay > 8000 || ramp_delay < 0)
+ return -EINVAL;
+
+ if (ramp_delay <= 4000)
+ ramp_val = 3;
+ else
+ ramp_val = 2;
+
+ return regmap_update_bits(rdev->regmap, MPQ7920_REG_CTL0,
+ MPQ7920_MASK_DVS_SLEWRATE, ramp_val << 6);
+}
+
+static int mpq7920_parse_cb(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *config)
+{
+ uint8_t val;
+ int ret;
+ struct mpq7920_regulator_info *info = config->driver_data;
+ struct regulator_desc *rdesc = &info->rdesc[desc->id];
+
+ if (of_property_read_bool(np, "mps,buck-ovp-disable")) {
+ regmap_update_bits(config->regmap,
+ MPQ7920_BUCK1_REG_B + (rdesc->id * 4),
+ MPQ7920_MASK_OVP, MPQ7920_OVP_DISABLE);
+ }
+
+ ret = of_property_read_u8(np, "mps,buck-phase-delay", &val);
+ if (!ret) {
+ regmap_update_bits(config->regmap,
+ MPQ7920_BUCK1_REG_C + (rdesc->id * 4),
+ MPQ7920_MASK_BUCK_PHASE_DEALY,
+ (val & 3) << 4);
+ }
+
+ ret = of_property_read_u8(np, "mps,buck-softstart", &val);
+ if (!ret)
+ rdesc->soft_start_val_on = (val & 3) << 2;
+
+ return 0;
+}
+
+static void mpq7920_parse_dt(struct device *dev,
+ struct mpq7920_regulator_info *info)
+{
+ int ret;
+ struct device_node *np = dev->of_node;
+ uint8_t freq;
+
+ np = of_get_child_by_name(np, "regulators");
+ if (!np) {
+ dev_err(dev, "missing 'regulators' subnode in DT\n");
+ return;
+ }
+
+ ret = of_property_read_u8(np, "mps,switch-freq", &freq);
+ if (!ret) {
+ regmap_update_bits(info->regmap, MPQ7920_REG_CTL0,
+ MPQ7920_MASK_SWITCH_FREQ,
+ (freq & 3) << 4);
+ }
+
+ of_node_put(np);
+}
+
+static int mpq7920_i2c_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct mpq7920_regulator_info *info;
+ struct regulator_config config = { NULL, };
+ struct regulator_dev *rdev;
+ struct regmap *regmap;
+ int i;
+
+ info = devm_kzalloc(dev, sizeof(struct mpq7920_regulator_info),
+ GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->rdesc = mpq7920_regulators_desc;
+ regmap = devm_regmap_init_i2c(client, &mpq7920_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "Failed to allocate regmap!\n");
+ return PTR_ERR(regmap);
+ }
+
+ i2c_set_clientdata(client, info);
+ info->regmap = regmap;
+ if (client->dev.of_node)
+ mpq7920_parse_dt(&client->dev, info);
+
+ config.dev = dev;
+ config.regmap = regmap;
+ config.driver_data = info;
+
+ for (i = 0; i < MPQ7920_MAX_REGULATORS; i++) {
+ rdev = devm_regulator_register(dev,
+ &mpq7920_regulators_desc[i],
+ &config);
+ if (IS_ERR(rdev)) {
+ dev_err(dev, "Failed to register regulator!\n");
+ return PTR_ERR(rdev);
+ }
+ }
+
+ return 0;
+}
+
+static const struct of_device_id mpq7920_of_match[] = {
+ { .compatible = "mps,mpq7920"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, mpq7920_of_match);
+
+static const struct i2c_device_id mpq7920_id[] = {
+ { "mpq7920", },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, mpq7920_id);
+
+static struct i2c_driver mpq7920_regulator_driver = {
+ .driver = {
+ .name = "mpq7920",
+ .of_match_table = of_match_ptr(mpq7920_of_match),
+ },
+ .probe_new = mpq7920_i2c_probe,
+ .id_table = mpq7920_id,
+};
+module_i2c_driver(mpq7920_regulator_driver);
+
+MODULE_AUTHOR("Saravanan Sekar <sravanhome@gmail.com>");
+MODULE_DESCRIPTION("MPQ7920 PMIC regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/mpq7920.h b/drivers/regulator/mpq7920.h
new file mode 100644
index 0000000..4899246
--- /dev/null
+++ b/drivers/regulator/mpq7920.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * mpq7920.h - Regulator definitions for mpq7920
+ *
+ * Copyright 2019 Monolithic Power Systems, Inc
+ *
+ */
+
+#ifndef __MPQ7920_H__
+#define __MPQ7920_H__
+
+#define MPQ7920_REG_CTL0 0x00
+#define MPQ7920_REG_CTL1 0x01
+#define MPQ7920_REG_CTL2 0x02
+#define MPQ7920_BUCK1_REG_A 0x03
+#define MPQ7920_BUCK1_REG_B 0x04
+#define MPQ7920_BUCK1_REG_C 0x05
+#define MPQ7920_BUCK1_REG_D 0x06
+#define MPQ7920_BUCK2_REG_A 0x07
+#define MPQ7920_BUCK2_REG_B 0x08
+#define MPQ7920_BUCK2_REG_C 0x09
+#define MPQ7920_BUCK2_REG_D 0x0a
+#define MPQ7920_BUCK3_REG_A 0x0b
+#define MPQ7920_BUCK3_REG_B 0x0c
+#define MPQ7920_BUCK3_REG_C 0x0d
+#define MPQ7920_BUCK3_REG_D 0x0e
+#define MPQ7920_BUCK4_REG_A 0x0f
+#define MPQ7920_BUCK4_REG_B 0x10
+#define MPQ7920_BUCK4_REG_C 0x11
+#define MPQ7920_BUCK4_REG_D 0x12
+#define MPQ7920_LDO1_REG_A 0x13
+#define MPQ7920_LDO1_REG_B 0x0
+#define MPQ7920_LDO2_REG_A 0x14
+#define MPQ7920_LDO2_REG_B 0x15
+#define MPQ7920_LDO2_REG_C 0x16
+#define MPQ7920_LDO3_REG_A 0x17
+#define MPQ7920_LDO3_REG_B 0x18
+#define MPQ7920_LDO3_REG_C 0x19
+#define MPQ7920_LDO4_REG_A 0x1a
+#define MPQ7920_LDO4_REG_B 0x1b
+#define MPQ7920_LDO4_REG_C 0x1c
+#define MPQ7920_LDO5_REG_A 0x1d
+#define MPQ7920_LDO5_REG_B 0x1e
+#define MPQ7920_LDO5_REG_C 0x1f
+#define MPQ7920_REG_MODE 0x20
+#define MPQ7920_REG_REGULATOR_EN 0x22
+
+#define MPQ7920_MASK_VREF 0x7f
+#define MPQ7920_MASK_BUCK_ILIM 0xc0
+#define MPQ7920_MASK_LDO_ILIM BIT(6)
+#define MPQ7920_MASK_DISCHARGE BIT(5)
+#define MPQ7920_MASK_MODE 0xc0
+#define MPQ7920_MASK_SOFTSTART 0x0c
+#define MPQ7920_MASK_SWITCH_FREQ 0x30
+#define MPQ7920_MASK_BUCK_PHASE_DEALY 0x30
+#define MPQ7920_MASK_DVS_SLEWRATE 0xc0
+#define MPQ7920_MASK_OVP 0x40
+#define MPQ7920_OVP_DISABLE ~(0x40)
+#define MPQ7920_DISCHARGE_ON BIT(5)
+
+#define MPQ7920_REGULATOR_EN_OFFSET 7
+
+/* values in mV */
+#define MPQ7920_BUCK_VOLT_MIN 400000
+#define MPQ7920_LDO_VOLT_MIN 650000
+#define MPQ7920_VOLT_MAX 3587500
+#define MPQ7920_VOLT_STEP 12500
+
+#endif /* __MPQ7920_H__ */
diff --git a/drivers/regulator/mt6311-regulator.c b/drivers/regulator/mt6311-regulator.c
index af95449..69e6af3 100644
--- a/drivers/regulator/mt6311-regulator.c
+++ b/drivers/regulator/mt6311-regulator.c
@@ -85,8 +85,7 @@
/*
* I2C driver interface functions
*/
-static int mt6311_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int mt6311_i2c_probe(struct i2c_client *i2c)
{
struct regulator_config config = { };
struct regulator_dev *rdev;
@@ -154,7 +153,7 @@
.name = "mt6311",
.of_match_table = of_match_ptr(mt6311_dt_ids),
},
- .probe = mt6311_i2c_probe,
+ .probe_new = mt6311_i2c_probe,
.id_table = mt6311_i2c_id,
};
diff --git a/drivers/regulator/mt6323-regulator.c b/drivers/regulator/mt6323-regulator.c
index 893ea19..ff90161 100644
--- a/drivers/regulator/mt6323-regulator.c
+++ b/drivers/regulator/mt6323-regulator.c
@@ -102,15 +102,15 @@
.modeset_mask = _modeset_mask, \
}
-static const struct regulator_linear_range buck_volt_range1[] = {
+static const struct linear_range buck_volt_range1[] = {
REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
};
-static const struct regulator_linear_range buck_volt_range2[] = {
+static const struct linear_range buck_volt_range2[] = {
REGULATOR_LINEAR_RANGE(1400000, 0, 0x7f, 12500),
};
-static const struct regulator_linear_range buck_volt_range3[] = {
+static const struct linear_range buck_volt_range3[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),
};
diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c
index 40e09b1..1d4eb5d 100644
--- a/drivers/regulator/mt6358-regulator.c
+++ b/drivers/regulator/mt6358-regulator.c
@@ -137,19 +137,19 @@
.qi = BIT(15), \
}
-static const struct regulator_linear_range buck_volt_range1[] = {
+static const struct linear_range buck_volt_range1[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 6250),
};
-static const struct regulator_linear_range buck_volt_range2[] = {
+static const struct linear_range buck_volt_range2[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 12500),
};
-static const struct regulator_linear_range buck_volt_range3[] = {
+static const struct linear_range buck_volt_range3[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),
};
-static const struct regulator_linear_range buck_volt_range4[] = {
+static const struct linear_range buck_volt_range4[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 0x7f, 12500),
};
diff --git a/drivers/regulator/mt6360-regulator.c b/drivers/regulator/mt6360-regulator.c
new file mode 100644
index 0000000..15308ee
--- /dev/null
+++ b/drivers/regulator/mt6360-regulator.c
@@ -0,0 +1,459 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (C) 2020 MediaTek Inc.
+//
+// Author: Gene Chen <gene_chen@richtek.com>
+
+#include <linux/init.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/driver.h>
+#include <linux/regulator/machine.h>
+
+#include <dt-bindings/regulator/mediatek,mt6360-regulator.h>
+
+enum {
+ MT6360_REGULATOR_BUCK1 = 0,
+ MT6360_REGULATOR_BUCK2,
+ MT6360_REGULATOR_LDO6,
+ MT6360_REGULATOR_LDO7,
+ MT6360_REGULATOR_LDO1,
+ MT6360_REGULATOR_LDO2,
+ MT6360_REGULATOR_LDO3,
+ MT6360_REGULATOR_LDO5,
+ MT6360_REGULATOR_MAX,
+};
+
+struct mt6360_irq_mapping {
+ const char *name;
+ irq_handler_t handler;
+};
+
+struct mt6360_regulator_desc {
+ const struct regulator_desc desc;
+ unsigned int mode_reg;
+ unsigned int mode_mask;
+ unsigned int state_reg;
+ unsigned int state_mask;
+ const struct mt6360_irq_mapping *irq_tables;
+ int irq_table_size;
+};
+
+struct mt6360_regulator_data {
+ struct device *dev;
+ struct regmap *regmap;
+};
+
+static irqreturn_t mt6360_pgb_event_handler(int irq, void *data)
+{
+ struct regulator_dev *rdev = data;
+
+ regulator_notifier_call_chain(rdev, REGULATOR_EVENT_FAIL, NULL);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mt6360_oc_event_handler(int irq, void *data)
+{
+ struct regulator_dev *rdev = data;
+
+ regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_CURRENT, NULL);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mt6360_ov_event_handler(int irq, void *data)
+{
+ struct regulator_dev *rdev = data;
+
+ regulator_notifier_call_chain(rdev, REGULATOR_EVENT_REGULATION_OUT, NULL);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mt6360_uv_event_handler(int irq, void *data)
+{
+ struct regulator_dev *rdev = data;
+
+ regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE, NULL);
+ return IRQ_HANDLED;
+}
+
+static const struct mt6360_irq_mapping buck1_irq_tbls[] = {
+ { "buck1_pgb_evt", mt6360_pgb_event_handler },
+ { "buck1_oc_evt", mt6360_oc_event_handler },
+ { "buck1_ov_evt", mt6360_ov_event_handler },
+ { "buck1_uv_evt", mt6360_uv_event_handler },
+};
+
+static const struct mt6360_irq_mapping buck2_irq_tbls[] = {
+ { "buck2_pgb_evt", mt6360_pgb_event_handler },
+ { "buck2_oc_evt", mt6360_oc_event_handler },
+ { "buck2_ov_evt", mt6360_ov_event_handler },
+ { "buck2_uv_evt", mt6360_uv_event_handler },
+};
+
+static const struct mt6360_irq_mapping ldo6_irq_tbls[] = {
+ { "ldo6_pgb_evt", mt6360_pgb_event_handler },
+ { "ldo6_oc_evt", mt6360_oc_event_handler },
+};
+
+static const struct mt6360_irq_mapping ldo7_irq_tbls[] = {
+ { "ldo7_pgb_evt", mt6360_pgb_event_handler },
+ { "ldo7_oc_evt", mt6360_oc_event_handler },
+};
+
+static const struct mt6360_irq_mapping ldo1_irq_tbls[] = {
+ { "ldo1_pgb_evt", mt6360_pgb_event_handler },
+ { "ldo1_oc_evt", mt6360_oc_event_handler },
+};
+
+static const struct mt6360_irq_mapping ldo2_irq_tbls[] = {
+ { "ldo2_pgb_evt", mt6360_pgb_event_handler },
+ { "ldo2_oc_evt", mt6360_oc_event_handler },
+};
+
+static const struct mt6360_irq_mapping ldo3_irq_tbls[] = {
+ { "ldo3_pgb_evt", mt6360_pgb_event_handler },
+ { "ldo3_oc_evt", mt6360_oc_event_handler },
+};
+
+static const struct mt6360_irq_mapping ldo5_irq_tbls[] = {
+ { "ldo5_pgb_evt", mt6360_pgb_event_handler },
+ { "ldo5_oc_evt", mt6360_oc_event_handler },
+};
+
+static const struct linear_range buck_vout_ranges[] = {
+ REGULATOR_LINEAR_RANGE(300000, 0x00, 0xc7, 5000),
+ REGULATOR_LINEAR_RANGE(1300000, 0xc8, 0xff, 0),
+};
+
+static const struct linear_range ldo_vout_ranges1[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0x00, 0x09, 10000),
+ REGULATOR_LINEAR_RANGE(600000, 0x0a, 0x10, 0),
+ REGULATOR_LINEAR_RANGE(610000, 0x11, 0x19, 10000),
+ REGULATOR_LINEAR_RANGE(700000, 0x1a, 0x20, 0),
+ REGULATOR_LINEAR_RANGE(710000, 0x21, 0x29, 10000),
+ REGULATOR_LINEAR_RANGE(800000, 0x2a, 0x30, 0),
+ REGULATOR_LINEAR_RANGE(810000, 0x31, 0x39, 10000),
+ REGULATOR_LINEAR_RANGE(900000, 0x3a, 0x40, 0),
+ REGULATOR_LINEAR_RANGE(910000, 0x41, 0x49, 10000),
+ REGULATOR_LINEAR_RANGE(1000000, 0x4a, 0x50, 0),
+ REGULATOR_LINEAR_RANGE(1010000, 0x51, 0x59, 10000),
+ REGULATOR_LINEAR_RANGE(1100000, 0x5a, 0x60, 0),
+ REGULATOR_LINEAR_RANGE(1110000, 0x61, 0x69, 10000),
+ REGULATOR_LINEAR_RANGE(1200000, 0x6a, 0x70, 0),
+ REGULATOR_LINEAR_RANGE(1210000, 0x71, 0x79, 10000),
+ REGULATOR_LINEAR_RANGE(1300000, 0x7a, 0x80, 0),
+ REGULATOR_LINEAR_RANGE(1310000, 0x81, 0x89, 10000),
+ REGULATOR_LINEAR_RANGE(1400000, 0x8a, 0x90, 0),
+ REGULATOR_LINEAR_RANGE(1410000, 0x91, 0x99, 10000),
+ REGULATOR_LINEAR_RANGE(1500000, 0x9a, 0xa0, 0),
+ REGULATOR_LINEAR_RANGE(1510000, 0xa1, 0xa9, 10000),
+ REGULATOR_LINEAR_RANGE(1600000, 0xaa, 0xb0, 0),
+ REGULATOR_LINEAR_RANGE(1610000, 0xb1, 0xb9, 10000),
+ REGULATOR_LINEAR_RANGE(1700000, 0xba, 0xc0, 0),
+ REGULATOR_LINEAR_RANGE(1710000, 0xc1, 0xc9, 10000),
+ REGULATOR_LINEAR_RANGE(1800000, 0xca, 0xd0, 0),
+ REGULATOR_LINEAR_RANGE(1810000, 0xd1, 0xd9, 10000),
+ REGULATOR_LINEAR_RANGE(1900000, 0xda, 0xe0, 0),
+ REGULATOR_LINEAR_RANGE(1910000, 0xe1, 0xe9, 10000),
+ REGULATOR_LINEAR_RANGE(2000000, 0xea, 0xf0, 0),
+ REGULATOR_LINEAR_RANGE(2010000, 0xf1, 0xf9, 10000),
+ REGULATOR_LINEAR_RANGE(2100000, 0xfa, 0xff, 0),
+};
+
+static const struct linear_range ldo_vout_ranges2[] = {
+ REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x09, 10000),
+ REGULATOR_LINEAR_RANGE(1300000, 0x0a, 0x10, 0),
+ REGULATOR_LINEAR_RANGE(1310000, 0x11, 0x19, 10000),
+ REGULATOR_LINEAR_RANGE(1400000, 0x1a, 0x1f, 0),
+ REGULATOR_LINEAR_RANGE(1500000, 0x20, 0x29, 10000),
+ REGULATOR_LINEAR_RANGE(1600000, 0x2a, 0x2f, 0),
+ REGULATOR_LINEAR_RANGE(1700000, 0x30, 0x39, 10000),
+ REGULATOR_LINEAR_RANGE(1800000, 0x3a, 0x40, 0),
+ REGULATOR_LINEAR_RANGE(1810000, 0x41, 0x49, 10000),
+ REGULATOR_LINEAR_RANGE(1900000, 0x4a, 0x4f, 0),
+ REGULATOR_LINEAR_RANGE(2000000, 0x50, 0x59, 10000),
+ REGULATOR_LINEAR_RANGE(2100000, 0x5a, 0x60, 0),
+ REGULATOR_LINEAR_RANGE(2110000, 0x61, 0x69, 10000),
+ REGULATOR_LINEAR_RANGE(2200000, 0x6a, 0x6f, 0),
+ REGULATOR_LINEAR_RANGE(2500000, 0x70, 0x79, 10000),
+ REGULATOR_LINEAR_RANGE(2600000, 0x7a, 0x7f, 0),
+ REGULATOR_LINEAR_RANGE(2700000, 0x80, 0x89, 10000),
+ REGULATOR_LINEAR_RANGE(2800000, 0x8a, 0x90, 0),
+ REGULATOR_LINEAR_RANGE(2810000, 0x91, 0x99, 10000),
+ REGULATOR_LINEAR_RANGE(2900000, 0x9a, 0xa0, 0),
+ REGULATOR_LINEAR_RANGE(2910000, 0xa1, 0xa9, 10000),
+ REGULATOR_LINEAR_RANGE(3000000, 0xaa, 0xb0, 0),
+ REGULATOR_LINEAR_RANGE(3010000, 0xb1, 0xb9, 10000),
+ REGULATOR_LINEAR_RANGE(3100000, 0xba, 0xc0, 0),
+ REGULATOR_LINEAR_RANGE(3110000, 0xc1, 0xc9, 10000),
+ REGULATOR_LINEAR_RANGE(3200000, 0xca, 0xcf, 0),
+ REGULATOR_LINEAR_RANGE(3300000, 0xd0, 0xd9, 10000),
+ REGULATOR_LINEAR_RANGE(3400000, 0xda, 0xe0, 0),
+ REGULATOR_LINEAR_RANGE(3410000, 0xe1, 0xe9, 10000),
+ REGULATOR_LINEAR_RANGE(3500000, 0xea, 0xf0, 0),
+ REGULATOR_LINEAR_RANGE(3510000, 0xf1, 0xf9, 10000),
+ REGULATOR_LINEAR_RANGE(3600000, 0xfa, 0xff, 0),
+};
+
+static const struct linear_range ldo_vout_ranges3[] = {
+ REGULATOR_LINEAR_RANGE(2700000, 0x00, 0x09, 10000),
+ REGULATOR_LINEAR_RANGE(2800000, 0x0a, 0x10, 0),
+ REGULATOR_LINEAR_RANGE(2810000, 0x11, 0x19, 10000),
+ REGULATOR_LINEAR_RANGE(2900000, 0x1a, 0x20, 0),
+ REGULATOR_LINEAR_RANGE(2910000, 0x21, 0x29, 10000),
+ REGULATOR_LINEAR_RANGE(3000000, 0x2a, 0x30, 0),
+ REGULATOR_LINEAR_RANGE(3010000, 0x31, 0x39, 10000),
+ REGULATOR_LINEAR_RANGE(3100000, 0x3a, 0x40, 0),
+ REGULATOR_LINEAR_RANGE(3110000, 0x41, 0x49, 10000),
+ REGULATOR_LINEAR_RANGE(3200000, 0x4a, 0x4f, 0),
+ REGULATOR_LINEAR_RANGE(3300000, 0x50, 0x59, 10000),
+ REGULATOR_LINEAR_RANGE(3400000, 0x5a, 0x60, 0),
+ REGULATOR_LINEAR_RANGE(3410000, 0x61, 0x69, 10000),
+ REGULATOR_LINEAR_RANGE(3500000, 0x6a, 0x70, 0),
+ REGULATOR_LINEAR_RANGE(3510000, 0x71, 0x79, 10000),
+ REGULATOR_LINEAR_RANGE(3600000, 0x7a, 0x7f, 0),
+};
+
+static int mt6360_regulator_set_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ const struct mt6360_regulator_desc *rdesc = (struct mt6360_regulator_desc *)rdev->desc;
+ struct regmap *regmap = rdev_get_regmap(rdev);
+ int shift = ffs(rdesc->mode_mask) - 1;
+ unsigned int val;
+ int ret;
+
+ switch (mode) {
+ case REGULATOR_MODE_NORMAL:
+ val = MT6360_OPMODE_NORMAL;
+ break;
+ case REGULATOR_MODE_STANDBY:
+ val = MT6360_OPMODE_ULP;
+ break;
+ case REGULATOR_MODE_IDLE:
+ val = MT6360_OPMODE_LP;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_update_bits(regmap, rdesc->mode_reg, rdesc->mode_mask, val << shift);
+ if (ret) {
+ dev_err(&rdev->dev, "%s: fail (%d)\n", __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static unsigned int mt6360_regulator_get_mode(struct regulator_dev *rdev)
+{
+ const struct mt6360_regulator_desc *rdesc = (struct mt6360_regulator_desc *)rdev->desc;
+ struct regmap *regmap = rdev_get_regmap(rdev);
+ int shift = ffs(rdesc->mode_mask) - 1;
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(regmap, rdesc->mode_reg, &val);
+ if (ret)
+ return ret;
+
+ val &= rdesc->mode_mask;
+ val >>= shift;
+
+ switch (val) {
+ case MT6360_OPMODE_LP:
+ return REGULATOR_MODE_IDLE;
+ case MT6360_OPMODE_ULP:
+ return REGULATOR_MODE_STANDBY;
+ case MT6360_OPMODE_NORMAL:
+ return REGULATOR_MODE_NORMAL;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mt6360_regulator_get_status(struct regulator_dev *rdev)
+{
+ const struct mt6360_regulator_desc *rdesc = (struct mt6360_regulator_desc *)rdev->desc;
+ struct regmap *regmap = rdev_get_regmap(rdev);
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(regmap, rdesc->state_reg, &val);
+ if (ret)
+ return ret;
+
+ if (val & rdesc->state_mask)
+ return REGULATOR_STATUS_ON;
+
+ return REGULATOR_STATUS_OFF;
+}
+
+static const struct regulator_ops mt6360_regulator_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_mode = mt6360_regulator_set_mode,
+ .get_mode = mt6360_regulator_get_mode,
+ .get_status = mt6360_regulator_get_status,
+};
+
+static unsigned int mt6360_regulator_of_map_mode(unsigned int hw_mode)
+{
+ switch (hw_mode) {
+ case MT6360_OPMODE_NORMAL:
+ return REGULATOR_MODE_NORMAL;
+ case MT6360_OPMODE_LP:
+ return REGULATOR_MODE_IDLE;
+ case MT6360_OPMODE_ULP:
+ return REGULATOR_MODE_STANDBY;
+ default:
+ return REGULATOR_MODE_INVALID;
+ }
+}
+
+#define MT6360_REGULATOR_DESC(_name, _sname, ereg, emask, vreg, vmask, \
+ mreg, mmask, streg, stmask, vranges, \
+ vcnts, offon_delay, irq_tbls) \
+{ \
+ .desc = { \
+ .name = #_name, \
+ .supply_name = #_sname, \
+ .id = MT6360_REGULATOR_##_name, \
+ .of_match = of_match_ptr(#_name), \
+ .regulators_node = of_match_ptr("regulator"), \
+ .of_map_mode = mt6360_regulator_of_map_mode, \
+ .owner = THIS_MODULE, \
+ .ops = &mt6360_regulator_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .vsel_reg = vreg, \
+ .vsel_mask = vmask, \
+ .enable_reg = ereg, \
+ .enable_mask = emask, \
+ .linear_ranges = vranges, \
+ .n_linear_ranges = ARRAY_SIZE(vranges), \
+ .n_voltages = vcnts, \
+ .off_on_delay = offon_delay, \
+ }, \
+ .mode_reg = mreg, \
+ .mode_mask = mmask, \
+ .state_reg = streg, \
+ .state_mask = stmask, \
+ .irq_tables = irq_tbls, \
+ .irq_table_size = ARRAY_SIZE(irq_tbls), \
+}
+
+static const struct mt6360_regulator_desc mt6360_regulator_descs[] = {
+ MT6360_REGULATOR_DESC(BUCK1, BUCK1_VIN, 0x117, 0x40, 0x110, 0xff, 0x117, 0x30, 0x117, 0x04,
+ buck_vout_ranges, 256, 0, buck1_irq_tbls),
+ MT6360_REGULATOR_DESC(BUCK2, BUCK2_VIN, 0x127, 0x40, 0x120, 0xff, 0x127, 0x30, 0x127, 0x04,
+ buck_vout_ranges, 256, 0, buck2_irq_tbls),
+ MT6360_REGULATOR_DESC(LDO6, LDO_VIN3, 0x137, 0x40, 0x13B, 0xff, 0x137, 0x30, 0x137, 0x04,
+ ldo_vout_ranges1, 256, 0, ldo6_irq_tbls),
+ MT6360_REGULATOR_DESC(LDO7, LDO_VIN3, 0x131, 0x40, 0x135, 0xff, 0x131, 0x30, 0x131, 0x04,
+ ldo_vout_ranges1, 256, 0, ldo7_irq_tbls),
+ MT6360_REGULATOR_DESC(LDO1, LDO_VIN1, 0x217, 0x40, 0x21B, 0xff, 0x217, 0x30, 0x217, 0x04,
+ ldo_vout_ranges2, 256, 0, ldo1_irq_tbls),
+ MT6360_REGULATOR_DESC(LDO2, LDO_VIN1, 0x211, 0x40, 0x215, 0xff, 0x211, 0x30, 0x211, 0x04,
+ ldo_vout_ranges2, 256, 0, ldo2_irq_tbls),
+ MT6360_REGULATOR_DESC(LDO3, LDO_VIN1, 0x205, 0x40, 0x209, 0xff, 0x205, 0x30, 0x205, 0x04,
+ ldo_vout_ranges2, 256, 100, ldo3_irq_tbls),
+ MT6360_REGULATOR_DESC(LDO5, LDO_VIN2, 0x20B, 0x40, 0x20F, 0x7f, 0x20B, 0x30, 0x20B, 0x04,
+ ldo_vout_ranges3, 128, 100, ldo5_irq_tbls),
+};
+
+static int mt6360_regulator_irq_register(struct platform_device *pdev,
+ struct regulator_dev *rdev,
+ const struct mt6360_irq_mapping *tbls,
+ int tbl_size)
+{
+ int i, irq, ret;
+
+ for (i = 0; i < tbl_size; i++) {
+ const struct mt6360_irq_mapping *irq_desc = tbls + i;
+
+ irq = platform_get_irq_byname(pdev, irq_desc->name);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "Fail to get %s irq\n", irq_desc->name);
+ return irq;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, irq_desc->handler, 0,
+ irq_desc->name, rdev);
+ if (ret) {
+ dev_err(&pdev->dev, "Fail to request %s irq\n", irq_desc->name);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int mt6360_regulator_probe(struct platform_device *pdev)
+{
+ struct mt6360_regulator_data *mrd;
+ struct regulator_config config = {};
+ int i, ret;
+
+ mrd = devm_kzalloc(&pdev->dev, sizeof(*mrd), GFP_KERNEL);
+ if (!mrd)
+ return -ENOMEM;
+
+ mrd->dev = &pdev->dev;
+
+ mrd->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!mrd->regmap) {
+ dev_err(&pdev->dev, "Failed to get parent regmap\n");
+ return -ENODEV;
+ }
+
+ config.dev = pdev->dev.parent;
+ config.driver_data = mrd;
+ config.regmap = mrd->regmap;
+
+ for (i = 0; i < ARRAY_SIZE(mt6360_regulator_descs); i++) {
+ const struct mt6360_regulator_desc *rdesc = mt6360_regulator_descs + i;
+ struct regulator_dev *rdev;
+
+ rdev = devm_regulator_register(&pdev->dev, &rdesc->desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "Failed to register %d regulator\n", i);
+ return PTR_ERR(rdev);
+ }
+
+ ret = mt6360_regulator_irq_register(pdev, rdev, rdesc->irq_tables,
+ rdesc->irq_table_size);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register %d regulator irqs\n", i);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static const struct platform_device_id mt6360_regulator_id_table[] = {
+ { "mt6360-regulator", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(platform, mt6360_regulator_id_table);
+
+static struct platform_driver mt6360_regulator_driver = {
+ .driver = {
+ .name = "mt6360-regulator",
+ },
+ .probe = mt6360_regulator_probe,
+ .id_table = mt6360_regulator_id_table,
+};
+module_platform_driver(mt6360_regulator_driver);
+
+MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>");
+MODULE_DESCRIPTION("MT6360 Regulator Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/mt6380-regulator.c b/drivers/regulator/mt6380-regulator.c
index b6aed09..9efd871 100644
--- a/drivers/regulator/mt6380-regulator.c
+++ b/drivers/regulator/mt6380-regulator.c
@@ -152,15 +152,15 @@
.modeset_mask = _modeset_mask, \
}
-static const struct regulator_linear_range buck_volt_range1[] = {
+static const struct linear_range buck_volt_range1[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 0xfe, 6250),
};
-static const struct regulator_linear_range buck_volt_range2[] = {
+static const struct linear_range buck_volt_range2[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 0xfe, 6250),
};
-static const struct regulator_linear_range buck_volt_range3[] = {
+static const struct linear_range buck_volt_range3[] = {
REGULATOR_LINEAR_RANGE(1200000, 0, 0x3c, 25000),
};
diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c
index fd9ed86..0a30df5 100644
--- a/drivers/regulator/mt6397-regulator.c
+++ b/drivers/regulator/mt6397-regulator.c
@@ -13,9 +13,7 @@
#include <linux/regulator/machine.h>
#include <linux/regulator/mt6397-regulator.h>
#include <linux/regulator/of_regulator.h>
-
-#define MT6397_BUCK_MODE_AUTO 0
-#define MT6397_BUCK_MODE_FORCE_PWM 1
+#include <dt-bindings/regulator/mediatek,mt6397-regulator.h>
/*
* MT6397 regulators' information
@@ -55,6 +53,7 @@
.vsel_mask = vosel_mask, \
.enable_reg = enreg, \
.enable_mask = BIT(0), \
+ .of_map_mode = mt6397_map_mode, \
}, \
.qi = BIT(13), \
.vselon_reg = voselon, \
@@ -102,15 +101,15 @@
.qi = BIT(15), \
}
-static const struct regulator_linear_range buck_volt_range1[] = {
+static const struct linear_range buck_volt_range1[] = {
REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
};
-static const struct regulator_linear_range buck_volt_range2[] = {
+static const struct linear_range buck_volt_range2[] = {
REGULATOR_LINEAR_RANGE(800000, 0, 0x7f, 6250),
};
-static const struct regulator_linear_range buck_volt_range3[] = {
+static const struct linear_range buck_volt_range3[] = {
REGULATOR_LINEAR_RANGE(1500000, 0, 0x1f, 20000),
};
@@ -146,6 +145,18 @@
1300000, 1500000, 1800000, 2000000, 2500000, 2800000, 3000000, 3300000,
};
+static unsigned int mt6397_map_mode(unsigned int mode)
+{
+ switch (mode) {
+ case MT6397_BUCK_MODE_AUTO:
+ return REGULATOR_MODE_NORMAL;
+ case MT6397_BUCK_MODE_FORCE_PWM:
+ return REGULATOR_MODE_FAST;
+ default:
+ return REGULATOR_MODE_INVALID;
+ }
+}
+
static int mt6397_regulator_set_mode(struct regulator_dev *rdev,
unsigned int mode)
{
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 87637eb..06c0b15 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -532,7 +532,7 @@
/**
* of_check_coupling_data - Parse rdev's coupling properties and check data
* consistency
- * @rdev - pointer to regulator_dev whose data is checked
+ * @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
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
index 3132591..337dd61 100644
--- a/drivers/regulator/palmas-regulator.c
+++ b/drivers/regulator/palmas-regulator.c
@@ -22,14 +22,14 @@
#include <linux/of_platform.h>
#include <linux/regulator/of_regulator.h>
-static const struct regulator_linear_range smps_low_ranges[] = {
+static const struct linear_range smps_low_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(500000, 0x1, 0x6, 0),
REGULATOR_LINEAR_RANGE(510000, 0x7, 0x79, 10000),
REGULATOR_LINEAR_RANGE(1650000, 0x7A, 0x7f, 0),
};
-static const struct regulator_linear_range smps_high_ranges[] = {
+static const struct linear_range smps_high_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(1000000, 0x1, 0x6, 0),
REGULATOR_LINEAR_RANGE(1020000, 0x7, 0x79, 20000),
diff --git a/drivers/regulator/pbias-regulator.c b/drivers/regulator/pbias-regulator.c
index 92b41a6..4eccf12 100644
--- a/drivers/regulator/pbias-regulator.c
+++ b/drivers/regulator/pbias-regulator.c
@@ -1,7 +1,7 @@
/*
* pbias-regulator.c
*
- * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com/
* Author: Balaji T K <balajitk@ti.com>
*
* This program is free software; you can redistribute it and/or
@@ -38,15 +38,6 @@
int n_voltages;
};
-struct pbias_regulator_data {
- struct regulator_desc desc;
- void __iomem *pbias_addr;
- struct regulator_dev *dev;
- struct regmap *syscon;
- const struct pbias_reg_info *info;
- int voltage;
-};
-
struct pbias_of_data {
unsigned int offset;
};
@@ -157,14 +148,13 @@
static int pbias_regulator_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct pbias_regulator_data *drvdata;
struct resource *res;
struct regulator_config cfg = { };
+ struct regulator_desc *desc;
+ struct regulator_dev *rdev;
struct regmap *syscon;
const struct pbias_reg_info *info;
- int ret = 0;
- int count, idx, data_idx = 0;
- const struct of_device_id *match;
+ int ret, count, idx;
const struct pbias_of_data *data;
unsigned int offset;
@@ -173,19 +163,16 @@
if (count < 0)
return count;
- drvdata = devm_kcalloc(&pdev->dev,
- count, sizeof(struct pbias_regulator_data),
- GFP_KERNEL);
- if (!drvdata)
+ desc = devm_kcalloc(&pdev->dev, count, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
return -ENOMEM;
syscon = syscon_regmap_lookup_by_phandle(np, "syscon");
if (IS_ERR(syscon))
return PTR_ERR(syscon);
- match = of_match_device(of_match_ptr(pbias_of_match), &pdev->dev);
- if (match && match->data) {
- data = match->data;
+ data = of_device_get_match_data(&pdev->dev);
+ if (data) {
offset = data->offset;
} else {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -200,7 +187,7 @@
cfg.regmap = syscon;
cfg.dev = &pdev->dev;
- for (idx = 0; idx < PBIAS_NUM_REGS && data_idx < count; idx++) {
+ for (idx = 0; idx < PBIAS_NUM_REGS && count; idx++) {
if (!pbias_matches[idx].init_data ||
!pbias_matches[idx].of_node)
continue;
@@ -209,41 +196,35 @@
if (!info)
return -ENODEV;
- drvdata[data_idx].syscon = syscon;
- drvdata[data_idx].info = info;
- drvdata[data_idx].desc.name = info->name;
- drvdata[data_idx].desc.owner = THIS_MODULE;
- drvdata[data_idx].desc.type = REGULATOR_VOLTAGE;
- drvdata[data_idx].desc.ops = &pbias_regulator_voltage_ops;
- drvdata[data_idx].desc.volt_table = info->pbias_volt_table;
- drvdata[data_idx].desc.n_voltages = info->n_voltages;
- drvdata[data_idx].desc.enable_time = info->enable_time;
- drvdata[data_idx].desc.vsel_reg = offset;
- drvdata[data_idx].desc.vsel_mask = info->vmode;
- drvdata[data_idx].desc.enable_reg = offset;
- drvdata[data_idx].desc.enable_mask = info->enable_mask;
- drvdata[data_idx].desc.enable_val = info->enable;
- drvdata[data_idx].desc.disable_val = info->disable_val;
+ desc->name = info->name;
+ desc->owner = THIS_MODULE;
+ desc->type = REGULATOR_VOLTAGE;
+ desc->ops = &pbias_regulator_voltage_ops;
+ desc->volt_table = info->pbias_volt_table;
+ desc->n_voltages = info->n_voltages;
+ desc->enable_time = info->enable_time;
+ desc->vsel_reg = offset;
+ desc->vsel_mask = info->vmode;
+ desc->enable_reg = offset;
+ desc->enable_mask = info->enable_mask;
+ desc->enable_val = info->enable;
+ desc->disable_val = info->disable_val;
cfg.init_data = pbias_matches[idx].init_data;
- cfg.driver_data = &drvdata[data_idx];
cfg.of_node = pbias_matches[idx].of_node;
- drvdata[data_idx].dev = devm_regulator_register(&pdev->dev,
- &drvdata[data_idx].desc, &cfg);
- if (IS_ERR(drvdata[data_idx].dev)) {
- ret = PTR_ERR(drvdata[data_idx].dev);
+ rdev = devm_regulator_register(&pdev->dev, desc, &cfg);
+ if (IS_ERR(rdev)) {
+ ret = PTR_ERR(rdev);
dev_err(&pdev->dev,
"Failed to register regulator: %d\n", ret);
- goto err_regulator;
+ return ret;
}
- data_idx++;
+ desc++;
+ count--;
}
- platform_set_drvdata(pdev, drvdata);
-
-err_regulator:
- return ret;
+ return 0;
}
static struct platform_driver pbias_regulator_driver = {
diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c
new file mode 100644
index 0000000..d38109c
--- /dev/null
+++ b/drivers/regulator/pca9450-regulator.c
@@ -0,0 +1,863 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2020 NXP.
+ * NXP PCA9450 pmic driver
+ */
+
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/pca9450.h>
+
+struct pc9450_dvs_config {
+ unsigned int run_reg; /* dvs0 */
+ unsigned int run_mask;
+ unsigned int standby_reg; /* dvs1 */
+ unsigned int standby_mask;
+};
+
+struct pca9450_regulator_desc {
+ struct regulator_desc desc;
+ const struct pc9450_dvs_config dvs;
+};
+
+struct pca9450 {
+ struct device *dev;
+ struct regmap *regmap;
+ struct gpio_desc *sd_vsel_gpio;
+ enum pca9450_chip_type type;
+ unsigned int rcnt;
+ int irq;
+};
+
+static const struct regmap_range pca9450_status_range = {
+ .range_min = PCA9450_REG_INT1,
+ .range_max = PCA9450_REG_PWRON_STAT,
+};
+
+static const struct regmap_access_table pca9450_volatile_regs = {
+ .yes_ranges = &pca9450_status_range,
+ .n_yes_ranges = 1,
+};
+
+static const struct regmap_config pca9450_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_table = &pca9450_volatile_regs,
+ .max_register = PCA9450_MAX_REGISTER - 1,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+/*
+ * BUCK1/2/3
+ * BUCK1RAM[1:0] BUCK1 DVS ramp rate setting
+ * 00: 25mV/1usec
+ * 01: 25mV/2usec
+ * 10: 25mV/4usec
+ * 11: 25mV/8usec
+ */
+static int pca9450_dvs_set_ramp_delay(struct regulator_dev *rdev,
+ int ramp_delay)
+{
+ int id = rdev_get_id(rdev);
+ unsigned int ramp_value;
+
+ switch (ramp_delay) {
+ case 1 ... 3125:
+ ramp_value = BUCK1_RAMP_3P125MV;
+ break;
+ case 3126 ... 6250:
+ ramp_value = BUCK1_RAMP_6P25MV;
+ break;
+ case 6251 ... 12500:
+ ramp_value = BUCK1_RAMP_12P5MV;
+ break;
+ case 12501 ... 25000:
+ ramp_value = BUCK1_RAMP_25MV;
+ break;
+ default:
+ ramp_value = BUCK1_RAMP_25MV;
+ }
+
+ return regmap_update_bits(rdev->regmap, PCA9450_REG_BUCK1CTRL + id * 3,
+ BUCK1_RAMP_MASK, ramp_value << 6);
+}
+
+static const struct regulator_ops pca9450_dvs_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 = 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 = pca9450_dvs_set_ramp_delay,
+};
+
+static const struct regulator_ops pca9450_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 = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+};
+
+static const struct regulator_ops pca9450_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 = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+/*
+ * BUCK1/2/3
+ * 0.60 to 2.1875V (12.5mV step)
+ */
+static const struct linear_range pca9450_dvs_buck_volts[] = {
+ REGULATOR_LINEAR_RANGE(600000, 0x00, 0x7F, 12500),
+};
+
+/*
+ * BUCK4/5/6
+ * 0.6V to 3.4V (25mV step)
+ */
+static const struct linear_range pca9450_buck_volts[] = {
+ REGULATOR_LINEAR_RANGE(600000, 0x00, 0x70, 25000),
+ REGULATOR_LINEAR_RANGE(3400000, 0x71, 0x7F, 0),
+};
+
+/*
+ * LDO1
+ * 1.6 to 3.3V ()
+ */
+static const struct linear_range pca9450_ldo1_volts[] = {
+ REGULATOR_LINEAR_RANGE(1600000, 0x00, 0x03, 100000),
+ REGULATOR_LINEAR_RANGE(3000000, 0x04, 0x07, 100000),
+};
+
+/*
+ * LDO2
+ * 0.8 to 1.15V (50mV step)
+ */
+static const struct linear_range pca9450_ldo2_volts[] = {
+ REGULATOR_LINEAR_RANGE(800000, 0x00, 0x07, 50000),
+};
+
+/*
+ * LDO3/4
+ * 0.8 to 3.3V (100mV step)
+ */
+static const struct linear_range pca9450_ldo34_volts[] = {
+ REGULATOR_LINEAR_RANGE(800000, 0x00, 0x19, 100000),
+ REGULATOR_LINEAR_RANGE(3300000, 0x1A, 0x1F, 0),
+};
+
+/*
+ * LDO5
+ * 1.8 to 3.3V (100mV step)
+ */
+static const struct linear_range pca9450_ldo5_volts[] = {
+ REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000),
+};
+
+static int buck_set_dvs(const struct regulator_desc *desc,
+ struct device_node *np, struct regmap *regmap,
+ char *prop, unsigned int reg, unsigned int mask)
+{
+ int ret, i;
+ uint32_t uv;
+
+ ret = of_property_read_u32(np, prop, &uv);
+ if (ret == -EINVAL)
+ return 0;
+ else if (ret)
+ return ret;
+
+ for (i = 0; i < desc->n_voltages; i++) {
+ ret = regulator_desc_list_voltage_linear_range(desc, i);
+ if (ret < 0)
+ continue;
+ if (ret == uv) {
+ i <<= ffs(desc->vsel_mask) - 1;
+ ret = regmap_update_bits(regmap, reg, mask, i);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int pca9450_set_dvs_levels(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ struct pca9450_regulator_desc *data = container_of(desc,
+ struct pca9450_regulator_desc, desc);
+ const struct pc9450_dvs_config *dvs = &data->dvs;
+ unsigned int reg, mask;
+ char *prop;
+ int i, ret = 0;
+
+ for (i = 0; i < PCA9450_DVS_LEVEL_MAX; i++) {
+ switch (i) {
+ case PCA9450_DVS_LEVEL_RUN:
+ prop = "nxp,dvs-run-voltage";
+ reg = dvs->run_reg;
+ mask = dvs->run_mask;
+ break;
+ case PCA9450_DVS_LEVEL_STANDBY:
+ prop = "nxp,dvs-standby-voltage";
+ reg = dvs->standby_reg;
+ mask = dvs->standby_mask;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = buck_set_dvs(desc, np, cfg->regmap, prop, reg, mask);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+static const struct pca9450_regulator_desc pca9450a_regulators[] = {
+ {
+ .desc = {
+ .name = "buck1",
+ .of_match = of_match_ptr("BUCK1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_BUCK1,
+ .ops = &pca9450_dvs_buck_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_BUCK1_VOLTAGE_NUM,
+ .linear_ranges = pca9450_dvs_buck_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
+ .vsel_reg = PCA9450_REG_BUCK1OUT_DVS0,
+ .vsel_mask = BUCK1OUT_DVS0_MASK,
+ .enable_reg = PCA9450_REG_BUCK1CTRL,
+ .enable_mask = BUCK1_ENMODE_MASK,
+ .owner = THIS_MODULE,
+ .of_parse_cb = pca9450_set_dvs_levels,
+ },
+ .dvs = {
+ .run_reg = PCA9450_REG_BUCK1OUT_DVS0,
+ .run_mask = BUCK1OUT_DVS0_MASK,
+ .standby_reg = PCA9450_REG_BUCK1OUT_DVS1,
+ .standby_mask = BUCK1OUT_DVS1_MASK,
+ },
+ },
+ {
+ .desc = {
+ .name = "buck2",
+ .of_match = of_match_ptr("BUCK2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_BUCK2,
+ .ops = &pca9450_dvs_buck_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_BUCK2_VOLTAGE_NUM,
+ .linear_ranges = pca9450_dvs_buck_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
+ .vsel_reg = PCA9450_REG_BUCK2OUT_DVS0,
+ .vsel_mask = BUCK2OUT_DVS0_MASK,
+ .enable_reg = PCA9450_REG_BUCK2CTRL,
+ .enable_mask = BUCK1_ENMODE_MASK,
+ .owner = THIS_MODULE,
+ .of_parse_cb = pca9450_set_dvs_levels,
+ },
+ .dvs = {
+ .run_reg = PCA9450_REG_BUCK2OUT_DVS0,
+ .run_mask = BUCK2OUT_DVS0_MASK,
+ .standby_reg = PCA9450_REG_BUCK2OUT_DVS1,
+ .standby_mask = BUCK2OUT_DVS1_MASK,
+ },
+ },
+ {
+ .desc = {
+ .name = "buck3",
+ .of_match = of_match_ptr("BUCK3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_BUCK3,
+ .ops = &pca9450_dvs_buck_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_BUCK3_VOLTAGE_NUM,
+ .linear_ranges = pca9450_dvs_buck_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
+ .vsel_reg = PCA9450_REG_BUCK3OUT_DVS0,
+ .vsel_mask = BUCK3OUT_DVS0_MASK,
+ .enable_reg = PCA9450_REG_BUCK3CTRL,
+ .enable_mask = BUCK3_ENMODE_MASK,
+ .owner = THIS_MODULE,
+ .of_parse_cb = pca9450_set_dvs_levels,
+ },
+ .dvs = {
+ .run_reg = PCA9450_REG_BUCK3OUT_DVS0,
+ .run_mask = BUCK3OUT_DVS0_MASK,
+ .standby_reg = PCA9450_REG_BUCK3OUT_DVS1,
+ .standby_mask = BUCK3OUT_DVS1_MASK,
+ },
+ },
+ {
+ .desc = {
+ .name = "buck4",
+ .of_match = of_match_ptr("BUCK4"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_BUCK4,
+ .ops = &pca9450_buck_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_BUCK4_VOLTAGE_NUM,
+ .linear_ranges = pca9450_buck_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+ .vsel_reg = PCA9450_REG_BUCK4OUT,
+ .vsel_mask = BUCK4OUT_MASK,
+ .enable_reg = PCA9450_REG_BUCK4CTRL,
+ .enable_mask = BUCK4_ENMODE_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "buck5",
+ .of_match = of_match_ptr("BUCK5"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_BUCK5,
+ .ops = &pca9450_buck_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_BUCK5_VOLTAGE_NUM,
+ .linear_ranges = pca9450_buck_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+ .vsel_reg = PCA9450_REG_BUCK5OUT,
+ .vsel_mask = BUCK5OUT_MASK,
+ .enable_reg = PCA9450_REG_BUCK5CTRL,
+ .enable_mask = BUCK5_ENMODE_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "buck6",
+ .of_match = of_match_ptr("BUCK6"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_BUCK6,
+ .ops = &pca9450_buck_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_BUCK6_VOLTAGE_NUM,
+ .linear_ranges = pca9450_buck_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+ .vsel_reg = PCA9450_REG_BUCK6OUT,
+ .vsel_mask = BUCK6OUT_MASK,
+ .enable_reg = PCA9450_REG_BUCK6CTRL,
+ .enable_mask = BUCK6_ENMODE_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "ldo1",
+ .of_match = of_match_ptr("LDO1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_LDO1,
+ .ops = &pca9450_ldo_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_LDO1_VOLTAGE_NUM,
+ .linear_ranges = pca9450_ldo1_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_ldo1_volts),
+ .vsel_reg = PCA9450_REG_LDO1CTRL,
+ .vsel_mask = LDO1OUT_MASK,
+ .enable_reg = PCA9450_REG_LDO1CTRL,
+ .enable_mask = LDO1_EN_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "ldo2",
+ .of_match = of_match_ptr("LDO2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_LDO2,
+ .ops = &pca9450_ldo_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_LDO2_VOLTAGE_NUM,
+ .linear_ranges = pca9450_ldo2_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_ldo2_volts),
+ .vsel_reg = PCA9450_REG_LDO2CTRL,
+ .vsel_mask = LDO2OUT_MASK,
+ .enable_reg = PCA9450_REG_LDO2CTRL,
+ .enable_mask = LDO2_EN_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "ldo3",
+ .of_match = of_match_ptr("LDO3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_LDO3,
+ .ops = &pca9450_ldo_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_LDO3_VOLTAGE_NUM,
+ .linear_ranges = pca9450_ldo34_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts),
+ .vsel_reg = PCA9450_REG_LDO3CTRL,
+ .vsel_mask = LDO3OUT_MASK,
+ .enable_reg = PCA9450_REG_LDO3CTRL,
+ .enable_mask = LDO3_EN_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "ldo4",
+ .of_match = of_match_ptr("LDO4"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_LDO4,
+ .ops = &pca9450_ldo_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_LDO4_VOLTAGE_NUM,
+ .linear_ranges = pca9450_ldo34_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts),
+ .vsel_reg = PCA9450_REG_LDO4CTRL,
+ .vsel_mask = LDO4OUT_MASK,
+ .enable_reg = PCA9450_REG_LDO4CTRL,
+ .enable_mask = LDO4_EN_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "ldo5",
+ .of_match = of_match_ptr("LDO5"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_LDO5,
+ .ops = &pca9450_ldo_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_LDO5_VOLTAGE_NUM,
+ .linear_ranges = pca9450_ldo5_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_ldo5_volts),
+ .vsel_reg = PCA9450_REG_LDO5CTRL_H,
+ .vsel_mask = LDO5HOUT_MASK,
+ .enable_reg = PCA9450_REG_LDO5CTRL_H,
+ .enable_mask = LDO5H_EN_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+};
+
+/*
+ * Buck3 removed on PCA9450B and connected with Buck1 internal for dual phase
+ * on PCA9450C as no Buck3.
+ */
+static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
+ {
+ .desc = {
+ .name = "buck1",
+ .of_match = of_match_ptr("BUCK1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_BUCK1,
+ .ops = &pca9450_dvs_buck_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_BUCK1_VOLTAGE_NUM,
+ .linear_ranges = pca9450_dvs_buck_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
+ .vsel_reg = PCA9450_REG_BUCK1OUT_DVS0,
+ .vsel_mask = BUCK1OUT_DVS0_MASK,
+ .enable_reg = PCA9450_REG_BUCK1CTRL,
+ .enable_mask = BUCK1_ENMODE_MASK,
+ .owner = THIS_MODULE,
+ .of_parse_cb = pca9450_set_dvs_levels,
+ },
+ .dvs = {
+ .run_reg = PCA9450_REG_BUCK1OUT_DVS0,
+ .run_mask = BUCK1OUT_DVS0_MASK,
+ .standby_reg = PCA9450_REG_BUCK1OUT_DVS1,
+ .standby_mask = BUCK1OUT_DVS1_MASK,
+ },
+ },
+ {
+ .desc = {
+ .name = "buck2",
+ .of_match = of_match_ptr("BUCK2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_BUCK2,
+ .ops = &pca9450_dvs_buck_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_BUCK2_VOLTAGE_NUM,
+ .linear_ranges = pca9450_dvs_buck_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
+ .vsel_reg = PCA9450_REG_BUCK2OUT_DVS0,
+ .vsel_mask = BUCK2OUT_DVS0_MASK,
+ .enable_reg = PCA9450_REG_BUCK2CTRL,
+ .enable_mask = BUCK1_ENMODE_MASK,
+ .owner = THIS_MODULE,
+ .of_parse_cb = pca9450_set_dvs_levels,
+ },
+ .dvs = {
+ .run_reg = PCA9450_REG_BUCK2OUT_DVS0,
+ .run_mask = BUCK2OUT_DVS0_MASK,
+ .standby_reg = PCA9450_REG_BUCK2OUT_DVS1,
+ .standby_mask = BUCK2OUT_DVS1_MASK,
+ },
+ },
+ {
+ .desc = {
+ .name = "buck4",
+ .of_match = of_match_ptr("BUCK4"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_BUCK4,
+ .ops = &pca9450_buck_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_BUCK4_VOLTAGE_NUM,
+ .linear_ranges = pca9450_buck_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+ .vsel_reg = PCA9450_REG_BUCK4OUT,
+ .vsel_mask = BUCK4OUT_MASK,
+ .enable_reg = PCA9450_REG_BUCK4CTRL,
+ .enable_mask = BUCK4_ENMODE_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "buck5",
+ .of_match = of_match_ptr("BUCK5"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_BUCK5,
+ .ops = &pca9450_buck_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_BUCK5_VOLTAGE_NUM,
+ .linear_ranges = pca9450_buck_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+ .vsel_reg = PCA9450_REG_BUCK5OUT,
+ .vsel_mask = BUCK5OUT_MASK,
+ .enable_reg = PCA9450_REG_BUCK5CTRL,
+ .enable_mask = BUCK5_ENMODE_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "buck6",
+ .of_match = of_match_ptr("BUCK6"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_BUCK6,
+ .ops = &pca9450_buck_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_BUCK6_VOLTAGE_NUM,
+ .linear_ranges = pca9450_buck_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
+ .vsel_reg = PCA9450_REG_BUCK6OUT,
+ .vsel_mask = BUCK6OUT_MASK,
+ .enable_reg = PCA9450_REG_BUCK6CTRL,
+ .enable_mask = BUCK6_ENMODE_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "ldo1",
+ .of_match = of_match_ptr("LDO1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_LDO1,
+ .ops = &pca9450_ldo_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_LDO1_VOLTAGE_NUM,
+ .linear_ranges = pca9450_ldo1_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_ldo1_volts),
+ .vsel_reg = PCA9450_REG_LDO1CTRL,
+ .vsel_mask = LDO1OUT_MASK,
+ .enable_reg = PCA9450_REG_LDO1CTRL,
+ .enable_mask = LDO1_EN_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "ldo2",
+ .of_match = of_match_ptr("LDO2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_LDO2,
+ .ops = &pca9450_ldo_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_LDO2_VOLTAGE_NUM,
+ .linear_ranges = pca9450_ldo2_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_ldo2_volts),
+ .vsel_reg = PCA9450_REG_LDO2CTRL,
+ .vsel_mask = LDO2OUT_MASK,
+ .enable_reg = PCA9450_REG_LDO2CTRL,
+ .enable_mask = LDO2_EN_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "ldo3",
+ .of_match = of_match_ptr("LDO3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_LDO3,
+ .ops = &pca9450_ldo_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_LDO3_VOLTAGE_NUM,
+ .linear_ranges = pca9450_ldo34_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts),
+ .vsel_reg = PCA9450_REG_LDO3CTRL,
+ .vsel_mask = LDO3OUT_MASK,
+ .enable_reg = PCA9450_REG_LDO3CTRL,
+ .enable_mask = LDO3_EN_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "ldo4",
+ .of_match = of_match_ptr("LDO4"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_LDO4,
+ .ops = &pca9450_ldo_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_LDO4_VOLTAGE_NUM,
+ .linear_ranges = pca9450_ldo34_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts),
+ .vsel_reg = PCA9450_REG_LDO4CTRL,
+ .vsel_mask = LDO4OUT_MASK,
+ .enable_reg = PCA9450_REG_LDO4CTRL,
+ .enable_mask = LDO4_EN_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .desc = {
+ .name = "ldo5",
+ .of_match = of_match_ptr("LDO5"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = PCA9450_LDO5,
+ .ops = &pca9450_ldo_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = PCA9450_LDO5_VOLTAGE_NUM,
+ .linear_ranges = pca9450_ldo5_volts,
+ .n_linear_ranges = ARRAY_SIZE(pca9450_ldo5_volts),
+ .vsel_reg = PCA9450_REG_LDO5CTRL_H,
+ .vsel_mask = LDO5HOUT_MASK,
+ .enable_reg = PCA9450_REG_LDO5CTRL_H,
+ .enable_mask = LDO5H_EN_MASK,
+ .owner = THIS_MODULE,
+ },
+ },
+};
+
+static irqreturn_t pca9450_irq_handler(int irq, void *data)
+{
+ struct pca9450 *pca9450 = data;
+ struct regmap *regmap = pca9450->regmap;
+ unsigned int status;
+ int ret;
+
+ ret = regmap_read(regmap, PCA9450_REG_INT1, &status);
+ if (ret < 0) {
+ dev_err(pca9450->dev,
+ "Failed to read INT1(%d)\n", ret);
+ return IRQ_NONE;
+ }
+
+ if (status & IRQ_PWRON)
+ dev_warn(pca9450->dev, "PWRON interrupt.\n");
+
+ if (status & IRQ_WDOGB)
+ dev_warn(pca9450->dev, "WDOGB interrupt.\n");
+
+ if (status & IRQ_VR_FLT1)
+ dev_warn(pca9450->dev, "VRFLT1 interrupt.\n");
+
+ if (status & IRQ_VR_FLT2)
+ dev_warn(pca9450->dev, "VRFLT2 interrupt.\n");
+
+ if (status & IRQ_LOWVSYS)
+ dev_warn(pca9450->dev, "LOWVSYS interrupt.\n");
+
+ if (status & IRQ_THERM_105)
+ dev_warn(pca9450->dev, "IRQ_THERM_105 interrupt.\n");
+
+ if (status & IRQ_THERM_125)
+ dev_warn(pca9450->dev, "IRQ_THERM_125 interrupt.\n");
+
+ return IRQ_HANDLED;
+}
+
+static int pca9450_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ enum pca9450_chip_type type = (unsigned int)(uintptr_t)
+ of_device_get_match_data(&i2c->dev);
+ const struct pca9450_regulator_desc *regulator_desc;
+ struct regulator_config config = { };
+ struct pca9450 *pca9450;
+ unsigned int device_id, i;
+ int ret;
+
+ if (!i2c->irq) {
+ dev_err(&i2c->dev, "No IRQ configured?\n");
+ return -EINVAL;
+ }
+
+ pca9450 = devm_kzalloc(&i2c->dev, sizeof(struct pca9450), GFP_KERNEL);
+ if (!pca9450)
+ return -ENOMEM;
+
+ switch (type) {
+ case PCA9450_TYPE_PCA9450A:
+ regulator_desc = pca9450a_regulators;
+ pca9450->rcnt = ARRAY_SIZE(pca9450a_regulators);
+ break;
+ case PCA9450_TYPE_PCA9450BC:
+ regulator_desc = pca9450bc_regulators;
+ pca9450->rcnt = ARRAY_SIZE(pca9450bc_regulators);
+ break;
+ default:
+ dev_err(&i2c->dev, "Unknown device type");
+ return -EINVAL;
+ }
+
+ pca9450->irq = i2c->irq;
+ pca9450->type = type;
+ pca9450->dev = &i2c->dev;
+
+ dev_set_drvdata(&i2c->dev, pca9450);
+
+ pca9450->regmap = devm_regmap_init_i2c(i2c,
+ &pca9450_regmap_config);
+ if (IS_ERR(pca9450->regmap)) {
+ dev_err(&i2c->dev, "regmap initialization failed\n");
+ return PTR_ERR(pca9450->regmap);
+ }
+
+ ret = regmap_read(pca9450->regmap, PCA9450_REG_DEV_ID, &device_id);
+ if (ret) {
+ dev_err(&i2c->dev, "Read device id error\n");
+ return ret;
+ }
+
+ /* Check your board and dts for match the right pmic */
+ if (((device_id >> 4) != 0x1 && type == PCA9450_TYPE_PCA9450A) ||
+ ((device_id >> 4) != 0x3 && type == PCA9450_TYPE_PCA9450BC)) {
+ dev_err(&i2c->dev, "Device id(%x) mismatched\n",
+ device_id >> 4);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < pca9450->rcnt; i++) {
+ const struct regulator_desc *desc;
+ struct regulator_dev *rdev;
+ const struct pca9450_regulator_desc *r;
+
+ r = ®ulator_desc[i];
+ desc = &r->desc;
+
+ config.regmap = pca9450->regmap;
+ config.dev = pca9450->dev;
+
+ rdev = devm_regulator_register(pca9450->dev, desc, &config);
+ if (IS_ERR(rdev)) {
+ ret = PTR_ERR(rdev);
+ dev_err(pca9450->dev,
+ "Failed to register regulator(%s): %d\n",
+ desc->name, ret);
+ return ret;
+ }
+ }
+
+ ret = devm_request_threaded_irq(pca9450->dev, pca9450->irq, NULL,
+ pca9450_irq_handler,
+ (IRQF_TRIGGER_FALLING | IRQF_ONESHOT),
+ "pca9450-irq", pca9450);
+ if (ret != 0) {
+ dev_err(pca9450->dev, "Failed to request IRQ: %d\n",
+ pca9450->irq);
+ return ret;
+ }
+ /* Unmask all interrupt except PWRON/WDOG/RSVD */
+ ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_INT1_MSK,
+ IRQ_VR_FLT1 | IRQ_VR_FLT2 | IRQ_LOWVSYS |
+ IRQ_THERM_105 | IRQ_THERM_125,
+ IRQ_PWRON | IRQ_WDOGB | IRQ_RSVD);
+ if (ret) {
+ dev_err(&i2c->dev, "Unmask irq error\n");
+ return ret;
+ }
+
+ /* Clear PRESET_EN bit in BUCK123_DVS to use DVS registers */
+ ret = regmap_clear_bits(pca9450->regmap, PCA9450_REG_BUCK123_DVS,
+ BUCK123_PRESET_EN);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to clear PRESET_EN bit: %d\n", ret);
+ return ret;
+ }
+
+ /* Set reset behavior on assertion of WDOG_B signal */
+ ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_RESET_CTRL,
+ WDOG_B_CFG_MASK, WDOG_B_CFG_COLD_LDO12);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to set WDOG_B reset behavior\n");
+ return ret;
+ }
+
+ /*
+ * The driver uses the LDO5CTRL_H register to control the LDO5 regulator.
+ * This is only valid if the SD_VSEL input of the PMIC is high. Let's
+ * check if the pin is available as GPIO and set it to high.
+ */
+ pca9450->sd_vsel_gpio = gpiod_get_optional(pca9450->dev, "sd-vsel", GPIOD_OUT_HIGH);
+
+ if (IS_ERR(pca9450->sd_vsel_gpio)) {
+ dev_err(&i2c->dev, "Failed to get SD_VSEL GPIO\n");
+ return ret;
+ }
+
+ dev_info(&i2c->dev, "%s probed.\n",
+ type == PCA9450_TYPE_PCA9450A ? "pca9450a" : "pca9450bc");
+
+ return 0;
+}
+
+static const struct of_device_id pca9450_of_match[] = {
+ {
+ .compatible = "nxp,pca9450a",
+ .data = (void *)PCA9450_TYPE_PCA9450A,
+ },
+ {
+ .compatible = "nxp,pca9450b",
+ .data = (void *)PCA9450_TYPE_PCA9450BC,
+ },
+ {
+ .compatible = "nxp,pca9450c",
+ .data = (void *)PCA9450_TYPE_PCA9450BC,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pca9450_of_match);
+
+static struct i2c_driver pca9450_i2c_driver = {
+ .driver = {
+ .name = "nxp-pca9450",
+ .of_match_table = pca9450_of_match,
+ },
+ .probe = pca9450_i2c_probe,
+};
+
+module_i2c_driver(pca9450_i2c_driver);
+
+MODULE_AUTHOR("Robin Gong <yibin.gong@nxp.com>");
+MODULE_DESCRIPTION("NXP PCA9450 Power Management IC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c
index c246926..0345f38 100644
--- a/drivers/regulator/pcap-regulator.c
+++ b/drivers/regulator/pcap-regulator.c
@@ -86,10 +86,6 @@
#define SW2_table SW1_table
-static const unsigned int SW3_table[] = {
- 4000000, 4500000, 5000000, 5500000,
-};
-
struct pcap_regulator {
const u8 reg;
const u8 en;
diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c
index 44b1da7..01a12cf 100644
--- a/drivers/regulator/pfuze100-regulator.c
+++ b/drivers/regulator/pfuze100-regulator.c
@@ -128,7 +128,7 @@
struct pfuze_chip *pfuze100 = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev);
bool reg_has_ramp_delay;
- unsigned int ramp_bits;
+ unsigned int ramp_bits = 0;
int ret;
switch (pfuze100->chip_id) {
@@ -149,8 +149,11 @@
}
if (reg_has_ramp_delay) {
- ramp_delay = 12500 / ramp_delay;
- ramp_bits = (ramp_delay >> 1) - (ramp_delay >> 3);
+ if (ramp_delay > 0) {
+ ramp_delay = 12500 / ramp_delay;
+ ramp_bits = (ramp_delay >> 1) - (ramp_delay >> 3);
+ }
+
ret = regmap_update_bits(pfuze100->regmap,
rdev->desc->vsel_reg + 4,
0xc0, ramp_bits << 6);
diff --git a/drivers/regulator/pv88060-regulator.c b/drivers/regulator/pv88060-regulator.c
index 3d34158..4823884 100644
--- a/drivers/regulator/pv88060-regulator.c
+++ b/drivers/regulator/pv88060-regulator.c
@@ -233,13 +233,10 @@
if (reg_val & PV88060_E_VDD_FLT) {
for (i = 0; i < PV88060_MAX_REGULATORS; i++) {
- if (chip->rdev[i] != NULL) {
- regulator_lock(chip->rdev[i]);
+ if (chip->rdev[i] != NULL)
regulator_notifier_call_chain(chip->rdev[i],
REGULATOR_EVENT_UNDER_VOLTAGE,
NULL);
- regulator_unlock(chip->rdev[i]);
- }
}
err = regmap_write(chip->regmap, PV88060_REG_EVENT_A,
@@ -252,13 +249,10 @@
if (reg_val & PV88060_E_OVER_TEMP) {
for (i = 0; i < PV88060_MAX_REGULATORS; i++) {
- if (chip->rdev[i] != NULL) {
- regulator_lock(chip->rdev[i]);
+ if (chip->rdev[i] != NULL)
regulator_notifier_call_chain(chip->rdev[i],
REGULATOR_EVENT_OVER_TEMP,
NULL);
- regulator_unlock(chip->rdev[i]);
- }
}
err = regmap_write(chip->regmap, PV88060_REG_EVENT_A,
@@ -279,8 +273,7 @@
/*
* I2C driver interface functions
*/
-static int pv88060_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int pv88060_i2c_probe(struct i2c_client *i2c)
{
struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
struct pv88060 *chip;
@@ -385,7 +378,7 @@
.name = "pv88060",
.of_match_table = of_match_ptr(pv88060_dt_ids),
},
- .probe = pv88060_i2c_probe,
+ .probe_new = pv88060_i2c_probe,
.id_table = pv88060_i2c_id,
};
diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c
index a444f68..2a74cc0 100644
--- a/drivers/regulator/pv88080-regulator.c
+++ b/drivers/regulator/pv88080-regulator.c
@@ -334,13 +334,10 @@
if (reg_val & PV88080_E_VDD_FLT) {
for (i = 0; i < PV88080_MAX_REGULATORS; i++) {
- if (chip->rdev[i] != NULL) {
- regulator_lock(chip->rdev[i]);
+ if (chip->rdev[i] != NULL)
regulator_notifier_call_chain(chip->rdev[i],
REGULATOR_EVENT_UNDER_VOLTAGE,
NULL);
- regulator_unlock(chip->rdev[i]);
- }
}
err = regmap_write(chip->regmap, PV88080_REG_EVENT_A,
@@ -353,13 +350,10 @@
if (reg_val & PV88080_E_OVER_TEMP) {
for (i = 0; i < PV88080_MAX_REGULATORS; i++) {
- if (chip->rdev[i] != NULL) {
- regulator_lock(chip->rdev[i]);
+ if (chip->rdev[i] != NULL)
regulator_notifier_call_chain(chip->rdev[i],
REGULATOR_EVENT_OVER_TEMP,
NULL);
- regulator_unlock(chip->rdev[i]);
- }
}
err = regmap_write(chip->regmap, PV88080_REG_EVENT_A,
diff --git a/drivers/regulator/pv88090-regulator.c b/drivers/regulator/pv88090-regulator.c
index b1d0d97..a80176b 100644
--- a/drivers/regulator/pv88090-regulator.c
+++ b/drivers/regulator/pv88090-regulator.c
@@ -226,13 +226,10 @@
if (reg_val & PV88090_E_VDD_FLT) {
for (i = 0; i < PV88090_MAX_REGULATORS; i++) {
- if (chip->rdev[i] != NULL) {
- regulator_lock(chip->rdev[i]);
+ if (chip->rdev[i] != NULL)
regulator_notifier_call_chain(chip->rdev[i],
REGULATOR_EVENT_UNDER_VOLTAGE,
NULL);
- regulator_unlock(chip->rdev[i]);
- }
}
err = regmap_write(chip->regmap, PV88090_REG_EVENT_A,
@@ -245,13 +242,10 @@
if (reg_val & PV88090_E_OVER_TEMP) {
for (i = 0; i < PV88090_MAX_REGULATORS; i++) {
- if (chip->rdev[i] != NULL) {
- regulator_lock(chip->rdev[i]);
+ if (chip->rdev[i] != NULL)
regulator_notifier_call_chain(chip->rdev[i],
REGULATOR_EVENT_OVER_TEMP,
NULL);
- regulator_unlock(chip->rdev[i]);
- }
}
err = regmap_write(chip->regmap, PV88090_REG_EVENT_A,
@@ -272,8 +266,7 @@
/*
* I2C driver interface functions
*/
-static int pv88090_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int pv88090_i2c_probe(struct i2c_client *i2c)
{
struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
struct pv88090 *chip;
@@ -406,7 +399,7 @@
.name = "pv88090",
.of_match_table = of_match_ptr(pv88090_dt_ids),
},
- .probe = pv88090_i2c_probe,
+ .probe_new = pv88090_i2c_probe,
.id_table = pv88090_i2c_id,
};
diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c
index 0a9d61a..7629476 100644
--- a/drivers/regulator/pwm-regulator.c
+++ b/drivers/regulator/pwm-regulator.c
@@ -48,7 +48,7 @@
unsigned int dutycycle;
};
-/**
+/*
* Voltage table call-backs
*/
static void pwm_regulator_init_state(struct regulator_dev *rdev)
@@ -354,7 +354,11 @@
drvdata->pwm = devm_pwm_get(&pdev->dev, NULL);
if (IS_ERR(drvdata->pwm)) {
ret = PTR_ERR(drvdata->pwm);
- dev_err(&pdev->dev, "Failed to get PWM: %d\n", ret);
+ if (ret == -EPROBE_DEFER)
+ dev_dbg(&pdev->dev,
+ "Failed to get PWM, deferring probe\n");
+ else
+ dev_err(&pdev->dev, "Failed to get PWM: %d\n", ret);
return ret;
}
@@ -386,7 +390,7 @@
return 0;
}
-static const struct of_device_id pwm_of_match[] = {
+static const struct of_device_id __maybe_unused pwm_of_match[] = {
{ .compatible = "pwm-regulator" },
{ },
};
diff --git a/drivers/regulator/qcom-labibb-regulator.c b/drivers/regulator/qcom-labibb-regulator.c
new file mode 100644
index 0000000..8ccf572
--- /dev/null
+++ b/drivers/regulator/qcom-labibb-regulator.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2020, The Linux Foundation. All rights reserved.
+
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+#define REG_PERPH_TYPE 0x04
+
+#define QCOM_LAB_TYPE 0x24
+#define QCOM_IBB_TYPE 0x20
+
+#define PMI8998_LAB_REG_BASE 0xde00
+#define PMI8998_IBB_REG_BASE 0xdc00
+
+#define REG_LABIBB_STATUS1 0x08
+#define REG_LABIBB_ENABLE_CTL 0x46
+#define LABIBB_STATUS1_VREG_OK_BIT BIT(7)
+#define LABIBB_CONTROL_ENABLE BIT(7)
+
+#define LAB_ENABLE_CTL_MASK BIT(7)
+#define IBB_ENABLE_CTL_MASK (BIT(7) | BIT(6))
+
+#define LABIBB_OFF_ON_DELAY 1000
+#define LAB_ENABLE_TIME (LABIBB_OFF_ON_DELAY * 2)
+#define IBB_ENABLE_TIME (LABIBB_OFF_ON_DELAY * 10)
+#define LABIBB_POLL_ENABLED_TIME 1000
+
+struct labibb_regulator {
+ struct regulator_desc desc;
+ struct device *dev;
+ struct regmap *regmap;
+ struct regulator_dev *rdev;
+ u16 base;
+ u8 type;
+};
+
+struct labibb_regulator_data {
+ const char *name;
+ u8 type;
+ u16 base;
+ const struct regulator_desc *desc;
+};
+
+static const struct regulator_ops qcom_labibb_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+static const struct regulator_desc pmi8998_lab_desc = {
+ .enable_mask = LAB_ENABLE_CTL_MASK,
+ .enable_reg = (PMI8998_LAB_REG_BASE + REG_LABIBB_ENABLE_CTL),
+ .enable_val = LABIBB_CONTROL_ENABLE,
+ .enable_time = LAB_ENABLE_TIME,
+ .poll_enabled_time = LABIBB_POLL_ENABLED_TIME,
+ .off_on_delay = LABIBB_OFF_ON_DELAY,
+ .owner = THIS_MODULE,
+ .type = REGULATOR_VOLTAGE,
+ .ops = &qcom_labibb_ops,
+};
+
+static const struct regulator_desc pmi8998_ibb_desc = {
+ .enable_mask = IBB_ENABLE_CTL_MASK,
+ .enable_reg = (PMI8998_IBB_REG_BASE + REG_LABIBB_ENABLE_CTL),
+ .enable_val = LABIBB_CONTROL_ENABLE,
+ .enable_time = IBB_ENABLE_TIME,
+ .poll_enabled_time = LABIBB_POLL_ENABLED_TIME,
+ .off_on_delay = LABIBB_OFF_ON_DELAY,
+ .owner = THIS_MODULE,
+ .type = REGULATOR_VOLTAGE,
+ .ops = &qcom_labibb_ops,
+};
+
+static const struct labibb_regulator_data pmi8998_labibb_data[] = {
+ {"lab", QCOM_LAB_TYPE, PMI8998_LAB_REG_BASE, &pmi8998_lab_desc},
+ {"ibb", QCOM_IBB_TYPE, PMI8998_IBB_REG_BASE, &pmi8998_ibb_desc},
+ { },
+};
+
+static const struct of_device_id qcom_labibb_match[] = {
+ { .compatible = "qcom,pmi8998-lab-ibb", .data = &pmi8998_labibb_data},
+ { },
+};
+MODULE_DEVICE_TABLE(of, qcom_labibb_match);
+
+static int qcom_labibb_regulator_probe(struct platform_device *pdev)
+{
+ struct labibb_regulator *vreg;
+ struct device *dev = &pdev->dev;
+ struct regulator_config cfg = {};
+
+ const struct of_device_id *match;
+ const struct labibb_regulator_data *reg_data;
+ struct regmap *reg_regmap;
+ unsigned int type;
+ int ret;
+
+ reg_regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!reg_regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -ENODEV;
+ }
+
+ match = of_match_device(qcom_labibb_match, &pdev->dev);
+ if (!match)
+ return -ENODEV;
+
+ for (reg_data = match->data; reg_data->name; reg_data++) {
+
+ /* Validate if the type of regulator is indeed
+ * what's mentioned in DT.
+ */
+ ret = regmap_read(reg_regmap, reg_data->base + REG_PERPH_TYPE,
+ &type);
+ if (ret < 0) {
+ dev_err(dev,
+ "Peripheral type read failed ret=%d\n",
+ ret);
+ return -EINVAL;
+ }
+
+ if (WARN_ON((type != QCOM_LAB_TYPE) && (type != QCOM_IBB_TYPE)) ||
+ WARN_ON(type != reg_data->type))
+ return -EINVAL;
+
+ vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg),
+ GFP_KERNEL);
+ if (!vreg)
+ return -ENOMEM;
+
+ vreg->regmap = reg_regmap;
+ vreg->dev = dev;
+ vreg->base = reg_data->base;
+ vreg->type = reg_data->type;
+
+ memcpy(&vreg->desc, reg_data->desc, sizeof(vreg->desc));
+ vreg->desc.of_match = reg_data->name;
+ vreg->desc.name = reg_data->name;
+
+ cfg.dev = vreg->dev;
+ cfg.driver_data = vreg;
+ cfg.regmap = vreg->regmap;
+
+ vreg->rdev = devm_regulator_register(vreg->dev, &vreg->desc,
+ &cfg);
+
+ if (IS_ERR(vreg->rdev)) {
+ dev_err(dev, "qcom_labibb: error registering %s : %d\n",
+ reg_data->name, ret);
+ return PTR_ERR(vreg->rdev);
+ }
+ }
+
+ return 0;
+}
+
+static struct platform_driver qcom_labibb_regulator_driver = {
+ .driver = {
+ .name = "qcom-lab-ibb-regulator",
+ .of_match_table = qcom_labibb_match,
+ },
+ .probe = qcom_labibb_regulator_probe,
+};
+module_platform_driver(qcom_labibb_regulator_driver);
+
+MODULE_DESCRIPTION("Qualcomm labibb driver");
+MODULE_AUTHOR("Nisha Kumari <nishakumari@codeaurora.org>");
+MODULE_AUTHOR("Sumit Semwal <sumit.semwal@linaro.org>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c
index 2de7af1..c303659 100644
--- a/drivers/regulator/qcom-rpmh-regulator.c
+++ b/drivers/regulator/qcom-rpmh-regulator.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+// Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
#define pr_fmt(fmt) "%s: " fmt, __func__
@@ -22,9 +22,9 @@
/**
* enum rpmh_regulator_type - supported RPMh accelerator types
- * %VRM: RPMh VRM accelerator which supports voting on enable, voltage,
+ * @VRM: RPMh VRM accelerator which supports voting on enable, voltage,
* and mode of LDO, SMPS, and BOB type PMIC regulators.
- * %XOB: RPMh XOB accelerator which supports voting on the enable state
+ * @XOB: RPMh XOB accelerator which supports voting on the enable state
* of PMIC regulators.
*/
enum rpmh_regulator_type {
@@ -86,7 +86,7 @@
struct rpmh_vreg_hw_data {
enum rpmh_regulator_type regulator_type;
const struct regulator_ops *ops;
- const struct regulator_linear_range voltage_range;
+ const struct linear_range voltage_range;
int n_voltages;
int hpm_min_load_uA;
const int *pmic_mode_map;
@@ -399,13 +399,13 @@
/**
* rpmh_regulator_init_vreg() - initialize all attributes of an rpmh-regulator
- * vreg: Pointer to the individual rpmh-regulator resource
- * dev: Pointer to the top level rpmh-regulator PMIC device
- * node: Pointer to the individual rpmh-regulator resource
+ * @vreg: Pointer to the individual rpmh-regulator resource
+ * @dev: Pointer to the top level rpmh-regulator PMIC device
+ * @node: Pointer to the individual rpmh-regulator resource
* device node
- * pmic_id: String used to identify the top level rpmh-regulator
+ * @pmic_id: String used to identify the top level rpmh-regulator
* PMIC device on the board
- * pmic_rpmh_data: Pointer to a null-terminated array of rpmh-regulator
+ * @pmic_rpmh_data: Pointer to a null-terminated array of rpmh-regulator
* resources defined for the top level PMIC device
*
* Return: 0 on success, errno on failure
@@ -732,6 +732,15 @@
.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,
@@ -878,6 +887,71 @@
{},
};
+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"),
+ RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps510, "vdd-s3"),
+ RPMH_VREG("smps4", "smp%s4", &pmic5_hfsmps510, "vdd-s4"),
+ RPMH_VREG("smps5", "smp%s5", &pmic5_hfsmps510, "vdd-s5"),
+ RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1"),
+ RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2-l3"),
+ RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l2-l3"),
+ RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l4-l7-l8"),
+ RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l16-l17-l18-l19"),
+ RPMH_VREG("ldo6", "ldo%s6", &pmic5_nldo, "vdd-l6"),
+ RPMH_VREG("ldo7", "ldo%s7", &pmic5_nldo, "vdd-l4-l7-l8"),
+ RPMH_VREG("ldo8", "ldo%s8", &pmic5_nldo, "vdd-l4-l7-l8"),
+ RPMH_VREG("ldo9", "ldo%s9", &pmic5_nldo, "vdd-l9"),
+ RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo_lv, "vdd-l10-l14-l15"),
+ RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo_lv, "vdd-l11-l12-l13"),
+ RPMH_VREG("ldo12", "ldo%s12", &pmic5_pldo_lv, "vdd-l11-l12-l13"),
+ RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo_lv, "vdd-l11-l12-l13"),
+ RPMH_VREG("ldo14", "ldo%s14", &pmic5_pldo_lv, "vdd-l10-l14-l15"),
+ RPMH_VREG("ldo15", "ldo%s15", &pmic5_pldo_lv, "vdd-l10-l14-l15"),
+ RPMH_VREG("ldo16", "ldo%s16", &pmic5_pldo, "vdd-l5-l16-l17-l18-l19"),
+ RPMH_VREG("ldo17", "ldo%s17", &pmic5_pldo, "vdd-l5-l16-l17-l18-l19"),
+ RPMH_VREG("ldo18", "ldo%s18", &pmic5_pldo, "vdd-l5-l16-l17-l18-l19"),
+ RPMH_VREG("ldo19", "ldo%s19", &pmic5_pldo, "vdd-l5-l16-l17-l18-l19"),
+ {},
+};
+
+static const struct rpmh_vreg_init_data pm6150l_vreg_data[] = {
+ RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps510, "vdd-s1"),
+ RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps510, "vdd-s2"),
+ RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps510, "vdd-s3"),
+ RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps510, "vdd-s4"),
+ RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps510, "vdd-s5"),
+ RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps510, "vdd-s6"),
+ RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps510, "vdd-s7"),
+ RPMH_VREG("smps8", "smp%s8", &pmic5_hfsmps510, "vdd-s8"),
+ RPMH_VREG("ldo1", "ldo%s1", &pmic5_pldo_lv, "vdd-l1-l8"),
+ RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2-l3"),
+ RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l2-l3"),
+ RPMH_VREG("ldo4", "ldo%s4", &pmic5_pldo, "vdd-l4-l5-l6"),
+ RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l4-l5-l6"),
+ RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l4-l5-l6"),
+ RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-l11"),
+ RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo, "vdd-l1-l8"),
+ RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l9-l10"),
+ RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l9-l10"),
+ RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l7-l11"),
+ RPMH_VREG("bob", "bob%s1", &pmic5_bob, "vdd-bob"),
+ {},
+};
+
static int rpmh_regulator_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -915,7 +989,7 @@
return 0;
}
-static const struct of_device_id rpmh_regulator_match_table[] = {
+static const struct of_device_id __maybe_unused rpmh_regulator_match_table[] = {
{
.compatible = "qcom,pm8005-rpmh-regulators",
.data = pm8005_vreg_data,
@@ -925,6 +999,10 @@
.data = pm8009_vreg_data,
},
{
+ .compatible = "qcom,pm8009-1-rpmh-regulators",
+ .data = pm8009_1_vreg_data,
+ },
+ {
.compatible = "qcom,pm8150-rpmh-regulators",
.data = pm8150_vreg_data,
},
@@ -940,6 +1018,14 @@
.compatible = "qcom,pmi8998-rpmh-regulators",
.data = pmi8998_vreg_data,
},
+ {
+ .compatible = "qcom,pm6150-rpmh-regulators",
+ .data = pm6150_vreg_data,
+ },
+ {
+ .compatible = "qcom,pm6150l-rpmh-regulators",
+ .data = pm6150l_vreg_data,
+ },
{}
};
MODULE_DEVICE_TABLE(of, rpmh_regulator_match_table);
diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c
index 7407cd5..7f9d66a 100644
--- a/drivers/regulator/qcom_rpm-regulator.c
+++ b/drivers/regulator/qcom_rpm-regulator.c
@@ -148,41 +148,41 @@
/*
* Physically available PMIC regulator voltage ranges
*/
-static const struct regulator_linear_range pldo_ranges[] = {
+static const struct linear_range pldo_ranges[] = {
REGULATOR_LINEAR_RANGE( 750000, 0, 59, 12500),
REGULATOR_LINEAR_RANGE(1500000, 60, 123, 25000),
REGULATOR_LINEAR_RANGE(3100000, 124, 160, 50000),
};
-static const struct regulator_linear_range nldo_ranges[] = {
+static const struct linear_range nldo_ranges[] = {
REGULATOR_LINEAR_RANGE( 750000, 0, 63, 12500),
};
-static const struct regulator_linear_range nldo1200_ranges[] = {
+static const struct linear_range nldo1200_ranges[] = {
REGULATOR_LINEAR_RANGE( 375000, 0, 59, 6250),
REGULATOR_LINEAR_RANGE( 750000, 60, 123, 12500),
};
-static const struct regulator_linear_range smps_ranges[] = {
+static const struct linear_range smps_ranges[] = {
REGULATOR_LINEAR_RANGE( 375000, 0, 29, 12500),
REGULATOR_LINEAR_RANGE( 750000, 30, 89, 12500),
REGULATOR_LINEAR_RANGE(1500000, 90, 153, 25000),
};
-static const struct regulator_linear_range ftsmps_ranges[] = {
+static const struct linear_range ftsmps_ranges[] = {
REGULATOR_LINEAR_RANGE( 350000, 0, 6, 50000),
REGULATOR_LINEAR_RANGE( 700000, 7, 63, 12500),
REGULATOR_LINEAR_RANGE(1500000, 64, 100, 50000),
};
-static const struct regulator_linear_range smb208_ranges[] = {
+static const struct linear_range smb208_ranges[] = {
REGULATOR_LINEAR_RANGE( 375000, 0, 29, 12500),
REGULATOR_LINEAR_RANGE( 750000, 30, 89, 12500),
REGULATOR_LINEAR_RANGE(1500000, 90, 153, 25000),
REGULATOR_LINEAR_RANGE(3100000, 154, 234, 25000),
};
-static const struct regulator_linear_range ncp_ranges[] = {
+static const struct linear_range ncp_ranges[] = {
REGULATOR_LINEAR_RANGE(1500000, 0, 31, 50000),
};
@@ -407,7 +407,7 @@
return ret;
}
-static struct regulator_ops uV_ops = {
+static const struct regulator_ops uV_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.set_voltage_sel = rpm_reg_set_uV_sel,
@@ -420,7 +420,7 @@
.set_load = rpm_reg_set_load,
};
-static struct regulator_ops mV_ops = {
+static const struct regulator_ops mV_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.set_voltage_sel = rpm_reg_set_mV_sel,
@@ -433,7 +433,7 @@
.set_load = rpm_reg_set_load,
};
-static struct regulator_ops switch_ops = {
+static const struct regulator_ops switch_ops = {
.enable = rpm_reg_switch_enable,
.disable = rpm_reg_switch_disable,
.is_enabled = rpm_reg_is_enabled,
@@ -604,16 +604,6 @@
.supports_force_mode_bypass = false,
};
-static const struct qcom_rpm_reg pm8921_ftsmps = {
- .desc.linear_ranges = ftsmps_ranges,
- .desc.n_linear_ranges = ARRAY_SIZE(ftsmps_ranges),
- .desc.n_voltages = 101,
- .desc.ops = &uV_ops,
- .parts = &rpm8960_smps_parts,
- .supports_force_mode_auto = true,
- .supports_force_mode_bypass = false,
-};
-
static const struct qcom_rpm_reg pm8921_ncp = {
.desc.linear_ranges = ncp_ranges,
.desc.n_linear_ranges = ARRAY_SIZE(ncp_ranges),
@@ -925,12 +915,21 @@
{ }
};
+static const struct rpm_regulator_data rpm_smb208_regulators[] = {
+ { "s1a", QCOM_RPM_SMB208_S1a, &smb208_smps, "vin_s1a" },
+ { "s1b", QCOM_RPM_SMB208_S1b, &smb208_smps, "vin_s1b" },
+ { "s2a", QCOM_RPM_SMB208_S2a, &smb208_smps, "vin_s2a" },
+ { "s2b", QCOM_RPM_SMB208_S2b, &smb208_smps, "vin_s2b" },
+ { }
+};
+
static const struct of_device_id rpm_of_match[] = {
{ .compatible = "qcom,rpm-pm8018-regulators",
.data = &rpm_pm8018_regulators },
{ .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators },
{ .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators },
{ .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_regulators },
+ { .compatible = "qcom,rpm-smb208-regulators", .data = &rpm_smb208_regulators },
{ }
};
MODULE_DEVICE_TABLE(of, rpm_of_match);
diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c
index 3b0828c..03e146e 100644
--- a/drivers/regulator/qcom_smd-regulator.c
+++ b/drivers/regulator/qcom_smd-regulator.c
@@ -9,6 +9,7 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
#include <linux/soc/qcom/smd-rpm.h>
struct qcom_rpm_reg {
@@ -198,8 +199,17 @@
.set_voltage = rpm_reg_set_voltage,
};
+static const struct regulator_ops rpm_mp5496_ops = {
+ .enable = rpm_reg_enable,
+ .disable = rpm_reg_disable,
+ .is_enabled = rpm_reg_is_enabled,
+ .list_voltage = regulator_list_voltage_linear_range,
+
+ .set_voltage = rpm_reg_set_voltage,
+};
+
static const struct regulator_desc pma8084_hfsmps = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(375000, 0, 95, 12500),
REGULATOR_LINEAR_RANGE(1550000, 96, 158, 25000),
},
@@ -209,7 +219,7 @@
};
static const struct regulator_desc pma8084_ftsmps = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(350000, 0, 184, 5000),
REGULATOR_LINEAR_RANGE(1280000, 185, 261, 10000),
},
@@ -219,7 +229,7 @@
};
static const struct regulator_desc pma8084_pldo = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE( 750000, 0, 63, 12500),
REGULATOR_LINEAR_RANGE(1550000, 64, 126, 25000),
REGULATOR_LINEAR_RANGE(3100000, 127, 163, 50000),
@@ -230,7 +240,7 @@
};
static const struct regulator_desc pma8084_nldo = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(750000, 0, 63, 12500),
},
.n_linear_ranges = 1,
@@ -243,7 +253,7 @@
};
static const struct regulator_desc pm8x41_hfsmps = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE( 375000, 0, 95, 12500),
REGULATOR_LINEAR_RANGE(1575000, 96, 158, 25000),
},
@@ -253,7 +263,7 @@
};
static const struct regulator_desc pm8841_ftsmps = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(350000, 0, 184, 5000),
REGULATOR_LINEAR_RANGE(1280000, 185, 261, 10000),
},
@@ -263,7 +273,7 @@
};
static const struct regulator_desc pm8941_boost = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(4000000, 0, 30, 50000),
},
.n_linear_ranges = 1,
@@ -272,7 +282,7 @@
};
static const struct regulator_desc pm8941_pldo = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE( 750000, 0, 63, 12500),
REGULATOR_LINEAR_RANGE(1550000, 64, 126, 25000),
REGULATOR_LINEAR_RANGE(3100000, 127, 163, 50000),
@@ -283,7 +293,7 @@
};
static const struct regulator_desc pm8941_nldo = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(750000, 0, 63, 12500),
},
.n_linear_ranges = 1,
@@ -302,7 +312,7 @@
};
static const struct regulator_desc pm8916_pldo = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(750000, 0, 208, 12500),
},
.n_linear_ranges = 1,
@@ -311,7 +321,7 @@
};
static const struct regulator_desc pm8916_nldo = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(375000, 0, 93, 12500),
},
.n_linear_ranges = 1,
@@ -320,7 +330,7 @@
};
static const struct regulator_desc pm8916_buck_lvo_smps = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(375000, 0, 95, 12500),
REGULATOR_LINEAR_RANGE(750000, 96, 127, 25000),
},
@@ -330,7 +340,7 @@
};
static const struct regulator_desc pm8916_buck_hvo_smps = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(1550000, 0, 31, 25000),
},
.n_linear_ranges = 1,
@@ -338,8 +348,83 @@
.ops = &rpm_smps_ldo_ops,
};
+static const struct regulator_desc pm8950_hfsmps = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(375000, 0, 95, 12500),
+ REGULATOR_LINEAR_RANGE(1550000, 96, 127, 25000),
+ },
+ .n_linear_ranges = 2,
+ .n_voltages = 128,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm8950_ftsmps2p5 = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(80000, 0, 255, 5000),
+ REGULATOR_LINEAR_RANGE(160000, 256, 460, 10000),
+ },
+ .n_linear_ranges = 2,
+ .n_voltages = 461,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm8950_ult_nldo = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(375000, 0, 202, 12500),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 203,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm8950_ult_pldo = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(1750000, 0, 127, 12500),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 128,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm8950_pldo_lv = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(1500000, 0, 16, 25000),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 17,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm8950_pldo = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(975000, 0, 164, 12500),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 165,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm8953_lnldo = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(1380000, 8, 15, 120000),
+ REGULATOR_LINEAR_RANGE(690000, 0, 7, 60000),
+ },
+ .n_linear_ranges = 2,
+ .n_voltages = 16,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm8953_ult_nldo = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(375000, 0, 93, 12500),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 94,
+ .ops = &rpm_smps_ldo_ops,
+};
+
static const struct regulator_desc pm8994_hfsmps = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE( 375000, 0, 95, 12500),
REGULATOR_LINEAR_RANGE(1550000, 96, 158, 25000),
},
@@ -349,7 +434,7 @@
};
static const struct regulator_desc pm8994_ftsmps = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(350000, 0, 199, 5000),
REGULATOR_LINEAR_RANGE(700000, 200, 349, 10000),
},
@@ -359,7 +444,7 @@
};
static const struct regulator_desc pm8994_nldo = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(750000, 0, 63, 12500),
},
.n_linear_ranges = 1,
@@ -368,7 +453,7 @@
};
static const struct regulator_desc pm8994_pldo = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE( 750000, 0, 63, 12500),
REGULATOR_LINEAR_RANGE(1550000, 64, 126, 25000),
REGULATOR_LINEAR_RANGE(3100000, 127, 163, 50000),
@@ -388,8 +473,37 @@
.ops = &rpm_smps_ldo_ops_fixed,
};
+static const struct regulator_desc pmi8994_ftsmps = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(350000, 0, 199, 5000),
+ REGULATOR_LINEAR_RANGE(700000, 200, 349, 10000),
+ },
+ .n_linear_ranges = 2,
+ .n_voltages = 350,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pmi8994_hfsmps = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(350000, 0, 80, 12500),
+ REGULATOR_LINEAR_RANGE(700000, 81, 141, 25000),
+ },
+ .n_linear_ranges = 2,
+ .n_voltages = 142,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pmi8994_bby = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(3000000, 0, 44, 50000),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 45,
+ .ops = &rpm_bob_ops,
+};
+
static const struct regulator_desc pm8998_ftsmps = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(320000, 0, 258, 4000),
},
.n_linear_ranges = 1,
@@ -398,7 +512,7 @@
};
static const struct regulator_desc pm8998_hfsmps = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000),
},
.n_linear_ranges = 1,
@@ -407,7 +521,7 @@
};
static const struct regulator_desc pm8998_nldo = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(312000, 0, 127, 8000),
},
.n_linear_ranges = 1,
@@ -416,7 +530,7 @@
};
static const struct regulator_desc pm8998_pldo = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(1664000, 0, 255, 8000),
},
.n_linear_ranges = 1,
@@ -425,7 +539,7 @@
};
static const struct regulator_desc pm8998_pldo_lv = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(1256000, 0, 127, 8000),
},
.n_linear_ranges = 1,
@@ -438,7 +552,7 @@
};
static const struct regulator_desc pmi8998_bob = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(1824000, 0, 83, 32000),
},
.n_linear_ranges = 1,
@@ -446,8 +560,71 @@
.ops = &rpm_bob_ops,
};
+static const struct regulator_desc pm660_ftsmps = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(355000, 0, 199, 5000),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 200,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm660_hfsmps = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(320000, 0, 216, 8000),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 217,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm660_ht_nldo = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(312000, 0, 124, 8000),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 125,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm660_ht_lvpldo = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(1504000, 0, 62, 8000),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 63,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm660_nldo660 = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(320000, 0, 123, 8000),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 124,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm660_pldo660 = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(1504000, 0, 255, 8000),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 256,
+ .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm660l_bob = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(1800000, 0, 84, 32000),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 85,
+ .ops = &rpm_bob_ops,
+};
+
static const struct regulator_desc pms405_hfsmps3 = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000),
},
.n_linear_ranges = 1,
@@ -456,7 +633,7 @@
};
static const struct regulator_desc pms405_nldo300 = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(312000, 0, 127, 8000),
},
.n_linear_ranges = 1,
@@ -465,7 +642,7 @@
};
static const struct regulator_desc pms405_nldo1200 = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(312000, 0, 127, 8000),
},
.n_linear_ranges = 1,
@@ -474,7 +651,7 @@
};
static const struct regulator_desc pms405_pldo50 = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(1664000, 0, 128, 16000),
},
.n_linear_ranges = 1,
@@ -483,7 +660,7 @@
};
static const struct regulator_desc pms405_pldo150 = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(1664000, 0, 128, 16000),
},
.n_linear_ranges = 1,
@@ -492,7 +669,7 @@
};
static const struct regulator_desc pms405_pldo600 = {
- .linear_ranges = (struct regulator_linear_range[]) {
+ .linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(1256000, 0, 98, 8000),
},
.n_linear_ranges = 1,
@@ -500,6 +677,24 @@
.ops = &rpm_smps_ldo_ops,
};
+static const struct regulator_desc mp5496_smpa2 = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(725000, 0, 27, 12500),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 28,
+ .ops = &rpm_mp5496_ops,
+};
+
+static const struct regulator_desc mp5496_ldoa2 = {
+ .linear_ranges = (struct linear_range[]) {
+ REGULATOR_LINEAR_RANGE(1800000, 0, 60, 25000),
+ },
+ .n_linear_ranges = 1,
+ .n_voltages = 61,
+ .ops = &rpm_mp5496_ops,
+};
+
struct rpm_regulator_data {
const char *name;
u32 type;
@@ -508,6 +703,12 @@
const char *supply;
};
+static const struct rpm_regulator_data rpm_mp5496_regulators[] = {
+ { "s2", QCOM_SMD_RPM_SMPA, 2, &mp5496_smpa2, "s2" },
+ { "l2", QCOM_SMD_RPM_LDOA, 2, &mp5496_ldoa2, "l2" },
+ {}
+};
+
static const struct rpm_regulator_data rpm_pm8841_regulators[] = {
{ "s1", QCOM_SMD_RPM_SMPB, 1, &pm8x41_hfsmps, "vdd_s1" },
{ "s2", QCOM_SMD_RPM_SMPB, 2, &pm8841_ftsmps, "vdd_s2" },
@@ -638,6 +839,75 @@
{}
};
+static const struct rpm_regulator_data rpm_pm8950_regulators[] = {
+ { "s1", QCOM_SMD_RPM_SMPA, 1, &pm8950_hfsmps, "vdd_s1" },
+ { "s2", QCOM_SMD_RPM_SMPA, 2, &pm8950_hfsmps, "vdd_s2" },
+ { "s3", QCOM_SMD_RPM_SMPA, 3, &pm8950_hfsmps, "vdd_s3" },
+ { "s4", QCOM_SMD_RPM_SMPA, 4, &pm8950_hfsmps, "vdd_s4" },
+ { "s5", QCOM_SMD_RPM_SMPA, 5, &pm8950_ftsmps2p5, "vdd_s5" },
+ { "s6", QCOM_SMD_RPM_SMPA, 6, &pm8950_hfsmps, "vdd_s6" },
+
+ { "l1", QCOM_SMD_RPM_LDOA, 1, &pm8950_ult_nldo, "vdd_l1_l19" },
+ { "l2", QCOM_SMD_RPM_LDOA, 2, &pm8950_ult_nldo, "vdd_l2_l23" },
+ { "l3", QCOM_SMD_RPM_LDOA, 3, &pm8950_ult_nldo, "vdd_l3" },
+ { "l4", QCOM_SMD_RPM_LDOA, 4, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16" },
+ { "l5", QCOM_SMD_RPM_LDOA, 5, &pm8950_pldo_lv, "vdd_l4_l5_l6_l7_l16" },
+ { "l6", QCOM_SMD_RPM_LDOA, 6, &pm8950_pldo_lv, "vdd_l4_l5_l6_l7_l16" },
+ { "l7", QCOM_SMD_RPM_LDOA, 7, &pm8950_pldo_lv, "vdd_l4_l5_l6_l7_l16" },
+ { "l8", QCOM_SMD_RPM_LDOA, 8, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22" },
+ { "l9", QCOM_SMD_RPM_LDOA, 9, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18" },
+ { "l10", QCOM_SMD_RPM_LDOA, 10, &pm8950_ult_nldo, "vdd_l9_l10_l13_l14_l15_l18"},
+ { "l11", QCOM_SMD_RPM_LDOA, 11, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22"},
+ { "l12", QCOM_SMD_RPM_LDOA, 12, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22"},
+ { "l13", QCOM_SMD_RPM_LDOA, 13, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18"},
+ { "l14", QCOM_SMD_RPM_LDOA, 14, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18"},
+ { "l15", QCOM_SMD_RPM_LDOA, 15, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18"},
+ { "l16", QCOM_SMD_RPM_LDOA, 16, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16"},
+ { "l17", QCOM_SMD_RPM_LDOA, 17, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22"},
+ { "l18", QCOM_SMD_RPM_LDOA, 18, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18"},
+ { "l19", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l1_l19"},
+ { "l20", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l20"},
+ { "l21", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l21"},
+ { "l22", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l8_l11_l12_l17_l22"},
+ { "l23", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l2_l23"},
+ {}
+};
+
+static const struct rpm_regulator_data rpm_pm8953_regulators[] = {
+ { "s1", QCOM_SMD_RPM_SMPA, 1, &pm8998_hfsmps, "vdd_s1" },
+ { "s2", QCOM_SMD_RPM_SMPA, 2, &pm8998_hfsmps, "vdd_s2" },
+ { "s3", QCOM_SMD_RPM_SMPA, 3, &pm8998_hfsmps, "vdd_s3" },
+ { "s4", QCOM_SMD_RPM_SMPA, 4, &pm8998_hfsmps, "vdd_s4" },
+ { "s5", QCOM_SMD_RPM_SMPA, 5, &pm8950_ftsmps2p5, "vdd_s5" },
+ { "s6", QCOM_SMD_RPM_SMPA, 6, &pm8950_ftsmps2p5, "vdd_s6" },
+ { "s7", QCOM_SMD_RPM_SMPA, 7, &pm8998_hfsmps, "vdd_s7" },
+
+ { "l1", QCOM_SMD_RPM_LDOA, 1, &pm8953_ult_nldo, "vdd_l1" },
+ { "l2", QCOM_SMD_RPM_LDOA, 2, &pm8953_ult_nldo, "vdd_l2_l3" },
+ { "l3", QCOM_SMD_RPM_LDOA, 3, &pm8953_ult_nldo, "vdd_l2_l3" },
+ { "l4", QCOM_SMD_RPM_LDOA, 4, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16_l19" },
+ { "l5", QCOM_SMD_RPM_LDOA, 5, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16_l19" },
+ { "l6", QCOM_SMD_RPM_LDOA, 6, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16_l19" },
+ { "l7", QCOM_SMD_RPM_LDOA, 7, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16_l19" },
+ { "l8", QCOM_SMD_RPM_LDOA, 8, &pm8950_ult_pldo, "vdd_l8_l11_l12_l13_l14_l15" },
+ { "l9", QCOM_SMD_RPM_LDOA, 9, &pm8950_ult_pldo, "vdd_l9_l10_l17_l18_l22" },
+ { "l10", QCOM_SMD_RPM_LDOA, 10, &pm8950_ult_pldo, "vdd_l9_l10_l17_l18_l22" },
+ { "l11", QCOM_SMD_RPM_LDOA, 11, &pm8950_ult_pldo, "vdd_l8_l11_l12_l13_l14_l15" },
+ { "l12", QCOM_SMD_RPM_LDOA, 12, &pm8950_ult_pldo, "vdd_l8_l11_l12_l13_l14_l15" },
+ { "l13", QCOM_SMD_RPM_LDOA, 13, &pm8950_ult_pldo, "vdd_l8_l11_l12_l13_l14_l15" },
+ { "l14", QCOM_SMD_RPM_LDOA, 14, &pm8950_ult_pldo, "vdd_l8_l11_l12_l13_l14_l15" },
+ { "l15", QCOM_SMD_RPM_LDOA, 15, &pm8950_ult_pldo, "vdd_l8_l11_l12_l13_l14_l15" },
+ { "l16", QCOM_SMD_RPM_LDOA, 16, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16_l19" },
+ { "l17", QCOM_SMD_RPM_LDOA, 17, &pm8950_ult_pldo, "vdd_l9_l10_l17_l18_l22" },
+ { "l18", QCOM_SMD_RPM_LDOA, 18, &pm8950_ult_pldo, "vdd_l9_l10_l17_l18_l22" },
+ { "l19", QCOM_SMD_RPM_LDOA, 19, &pm8953_ult_nldo, "vdd_l4_l5_l6_l7_l16_l19" },
+ { "l20", QCOM_SMD_RPM_LDOA, 20, &pm8953_lnldo, "vdd_l20" },
+ { "l21", QCOM_SMD_RPM_LDOA, 21, &pm8953_lnldo, "vdd_l21" },
+ { "l22", QCOM_SMD_RPM_LDOA, 22, &pm8950_ult_pldo, "vdd_l9_l10_l17_l18_l22" },
+ { "l23", QCOM_SMD_RPM_LDOA, 23, &pm8953_ult_nldo, "vdd_l23" },
+ {}
+};
+
static const struct rpm_regulator_data rpm_pm8994_regulators[] = {
{ "s1", QCOM_SMD_RPM_SMPA, 1, &pm8994_ftsmps, "vdd_s1" },
{ "s2", QCOM_SMD_RPM_SMPA, 2, &pm8994_ftsmps, "vdd_s2" },
@@ -689,6 +959,14 @@
{}
};
+static const struct rpm_regulator_data rpm_pmi8994_regulators[] = {
+ { "s1", QCOM_SMD_RPM_SMPB, 1, &pmi8994_ftsmps, "vdd_s1" },
+ { "s2", QCOM_SMD_RPM_SMPB, 2, &pmi8994_hfsmps, "vdd_s2" },
+ { "s3", QCOM_SMD_RPM_SMPB, 3, &pmi8994_hfsmps, "vdd_s3" },
+ { "boost-bypass", QCOM_SMD_RPM_BBYB, 1, &pmi8994_bby, "vdd_bst_byp" },
+ {}
+};
+
static const struct rpm_regulator_data rpm_pm8998_regulators[] = {
{ "s1", QCOM_SMD_RPM_SMPA, 1, &pm8998_ftsmps, "vdd_s1" },
{ "s2", QCOM_SMD_RPM_SMPA, 2, &pm8998_ftsmps, "vdd_s2" },
@@ -741,6 +1019,54 @@
{}
};
+static const struct rpm_regulator_data rpm_pm660_regulators[] = {
+ { "s1", QCOM_SMD_RPM_SMPA, 1, &pm660_ftsmps, "vdd_s1" },
+ { "s2", QCOM_SMD_RPM_SMPA, 2, &pm660_ftsmps, "vdd_s2" },
+ { "s3", QCOM_SMD_RPM_SMPA, 3, &pm660_ftsmps, "vdd_s3" },
+ { "s4", QCOM_SMD_RPM_SMPA, 4, &pm660_hfsmps, "vdd_s4" },
+ { "s5", QCOM_SMD_RPM_SMPA, 5, &pm660_hfsmps, "vdd_s5" },
+ { "s6", QCOM_SMD_RPM_SMPA, 6, &pm660_hfsmps, "vdd_s6" },
+ { "l1", QCOM_SMD_RPM_LDOA, 1, &pm660_nldo660, "vdd_l1_l6_l7" },
+ { "l2", QCOM_SMD_RPM_LDOA, 2, &pm660_ht_nldo, "vdd_l2_l3" },
+ { "l3", QCOM_SMD_RPM_LDOA, 3, &pm660_nldo660, "vdd_l2_l3" },
+ /* l4 is unaccessible on PM660 */
+ { "l5", QCOM_SMD_RPM_LDOA, 5, &pm660_ht_nldo, "vdd_l5" },
+ { "l6", QCOM_SMD_RPM_LDOA, 6, &pm660_ht_nldo, "vdd_l1_l6_l7" },
+ { "l7", QCOM_SMD_RPM_LDOA, 7, &pm660_ht_nldo, "vdd_l1_l6_l7" },
+ { "l8", QCOM_SMD_RPM_LDOA, 8, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" },
+ { "l9", QCOM_SMD_RPM_LDOA, 9, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" },
+ { "l10", QCOM_SMD_RPM_LDOA, 10, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" },
+ { "l11", QCOM_SMD_RPM_LDOA, 11, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" },
+ { "l12", QCOM_SMD_RPM_LDOA, 12, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" },
+ { "l13", QCOM_SMD_RPM_LDOA, 13, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" },
+ { "l14", QCOM_SMD_RPM_LDOA, 14, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" },
+ { "l15", QCOM_SMD_RPM_LDOA, 15, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" },
+ { "l16", QCOM_SMD_RPM_LDOA, 16, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" },
+ { "l17", QCOM_SMD_RPM_LDOA, 17, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" },
+ { "l18", QCOM_SMD_RPM_LDOA, 18, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" },
+ { "l19", QCOM_SMD_RPM_LDOA, 19, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" },
+ { }
+};
+
+static const struct rpm_regulator_data rpm_pm660l_regulators[] = {
+ { "s1", QCOM_SMD_RPM_SMPB, 1, &pm660_ftsmps, "vdd_s1" },
+ { "s2", QCOM_SMD_RPM_SMPB, 2, &pm660_ftsmps, "vdd_s2" },
+ { "s3", QCOM_SMD_RPM_RWCX, 0, &pm660_ftsmps, "vdd_s3_s4" },
+ { "s5", QCOM_SMD_RPM_RWMX, 0, &pm660_ftsmps, "vdd_s5" },
+ { "l1", QCOM_SMD_RPM_LDOB, 1, &pm660_nldo660, "vdd_l1_l9_l10" },
+ { "l2", QCOM_SMD_RPM_LDOB, 2, &pm660_pldo660, "vdd_l2" },
+ { "l3", QCOM_SMD_RPM_LDOB, 3, &pm660_pldo660, "vdd_l3_l5_l7_l8" },
+ { "l4", QCOM_SMD_RPM_LDOB, 4, &pm660_pldo660, "vdd_l4_l6" },
+ { "l5", QCOM_SMD_RPM_LDOB, 5, &pm660_pldo660, "vdd_l3_l5_l7_l8" },
+ { "l6", QCOM_SMD_RPM_LDOB, 6, &pm660_pldo660, "vdd_l4_l6" },
+ { "l7", QCOM_SMD_RPM_LDOB, 7, &pm660_pldo660, "vdd_l3_l5_l7_l8" },
+ { "l8", QCOM_SMD_RPM_LDOB, 8, &pm660_pldo660, "vdd_l3_l5_l7_l8" },
+ { "l9", QCOM_SMD_RPM_RWLC, 0, &pm660_ht_nldo, "vdd_l1_l9_l10" },
+ { "l10", QCOM_SMD_RPM_RWLM, 0, &pm660_ht_nldo, "vdd_l1_l9_l10" },
+ { "bob", QCOM_SMD_RPM_BOBB, 1, &pm660l_bob, "vdd_bob", },
+ { }
+};
+
static const struct rpm_regulator_data rpm_pms405_regulators[] = {
{ "s1", QCOM_SMD_RPM_SMPA, 1, &pms405_hfsmps3, "vdd_s1" },
{ "s2", QCOM_SMD_RPM_SMPA, 2, &pms405_hfsmps3, "vdd_s2" },
@@ -764,64 +1090,109 @@
};
static const struct of_device_id rpm_of_match[] = {
+ { .compatible = "qcom,rpm-mp5496-regulators", .data = &rpm_mp5496_regulators },
{ .compatible = "qcom,rpm-pm8841-regulators", .data = &rpm_pm8841_regulators },
{ .compatible = "qcom,rpm-pm8916-regulators", .data = &rpm_pm8916_regulators },
{ .compatible = "qcom,rpm-pm8941-regulators", .data = &rpm_pm8941_regulators },
+ { .compatible = "qcom,rpm-pm8950-regulators", .data = &rpm_pm8950_regulators },
+ { .compatible = "qcom,rpm-pm8953-regulators", .data = &rpm_pm8953_regulators },
{ .compatible = "qcom,rpm-pm8994-regulators", .data = &rpm_pm8994_regulators },
{ .compatible = "qcom,rpm-pm8998-regulators", .data = &rpm_pm8998_regulators },
+ { .compatible = "qcom,rpm-pm660-regulators", .data = &rpm_pm660_regulators },
+ { .compatible = "qcom,rpm-pm660l-regulators", .data = &rpm_pm660l_regulators },
{ .compatible = "qcom,rpm-pma8084-regulators", .data = &rpm_pma8084_regulators },
+ { .compatible = "qcom,rpm-pmi8994-regulators", .data = &rpm_pmi8994_regulators },
{ .compatible = "qcom,rpm-pmi8998-regulators", .data = &rpm_pmi8998_regulators },
{ .compatible = "qcom,rpm-pms405-regulators", .data = &rpm_pms405_regulators },
{}
};
MODULE_DEVICE_TABLE(of, rpm_of_match);
+/**
+ * rpm_regulator_init_vreg() - initialize all attributes of a qcom_smd-regulator
+ * @vreg: Pointer to the individual qcom_smd-regulator resource
+ * @dev: Pointer to the top level qcom_smd-regulator PMIC device
+ * @node: Pointer to the individual qcom_smd-regulator resource
+ * device node
+ * @rpm: Pointer to the rpm bus node
+ * @pmic_rpm_data: Pointer to a null-terminated array of qcom_smd-regulator
+ * resources defined for the top level PMIC device
+ *
+ * Return: 0 on success, errno on failure
+ */
+static int rpm_regulator_init_vreg(struct qcom_rpm_reg *vreg, struct device *dev,
+ struct device_node *node, struct qcom_smd_rpm *rpm,
+ const struct rpm_regulator_data *pmic_rpm_data)
+{
+ struct regulator_config config = {};
+ const struct rpm_regulator_data *rpm_data;
+ struct regulator_dev *rdev;
+ int ret;
+
+ for (rpm_data = pmic_rpm_data; rpm_data->name; rpm_data++)
+ if (of_node_name_eq(node, rpm_data->name))
+ break;
+
+ if (!rpm_data->name) {
+ dev_err(dev, "Unknown regulator %pOFn\n", node);
+ return -EINVAL;
+ }
+
+ vreg->dev = dev;
+ vreg->rpm = rpm;
+ vreg->type = rpm_data->type;
+ vreg->id = rpm_data->id;
+
+ memcpy(&vreg->desc, rpm_data->desc, sizeof(vreg->desc));
+ vreg->desc.name = rpm_data->name;
+ vreg->desc.supply_name = rpm_data->supply;
+ vreg->desc.owner = THIS_MODULE;
+ vreg->desc.type = REGULATOR_VOLTAGE;
+ vreg->desc.of_match = rpm_data->name;
+
+ config.dev = dev;
+ config.of_node = node;
+ config.driver_data = vreg;
+
+ rdev = devm_regulator_register(dev, &vreg->desc, &config);
+ if (IS_ERR(rdev)) {
+ ret = PTR_ERR(rdev);
+ dev_err(dev, "%pOFn: devm_regulator_register() failed, ret=%d\n", node, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
static int rpm_reg_probe(struct platform_device *pdev)
{
- const struct rpm_regulator_data *reg;
- const struct of_device_id *match;
- struct regulator_config config = { };
- struct regulator_dev *rdev;
+ struct device *dev = &pdev->dev;
+ const struct rpm_regulator_data *vreg_data;
+ struct device_node *node;
struct qcom_rpm_reg *vreg;
struct qcom_smd_rpm *rpm;
+ int ret;
rpm = dev_get_drvdata(pdev->dev.parent);
if (!rpm) {
- dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
+ dev_err(&pdev->dev, "Unable to retrieve handle to rpm\n");
return -ENODEV;
}
- match = of_match_device(rpm_of_match, &pdev->dev);
- if (!match) {
- dev_err(&pdev->dev, "failed to match device\n");
+ vreg_data = of_device_get_match_data(dev);
+ if (!vreg_data)
return -ENODEV;
- }
- for (reg = match->data; reg->name; reg++) {
+ for_each_available_child_of_node(dev->of_node, node) {
vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
if (!vreg)
return -ENOMEM;
- vreg->dev = &pdev->dev;
- vreg->type = reg->type;
- vreg->id = reg->id;
- vreg->rpm = rpm;
+ ret = rpm_regulator_init_vreg(vreg, dev, node, rpm, vreg_data);
- memcpy(&vreg->desc, reg->desc, sizeof(vreg->desc));
-
- vreg->desc.id = -1;
- vreg->desc.owner = THIS_MODULE;
- vreg->desc.type = REGULATOR_VOLTAGE;
- vreg->desc.name = reg->name;
- vreg->desc.supply_name = reg->supply;
- vreg->desc.of_match = reg->name;
-
- config.dev = &pdev->dev;
- config.driver_data = vreg;
- rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);
- if (IS_ERR(rdev)) {
- dev_err(&pdev->dev, "failed to register %s\n", reg->name);
- return PTR_ERR(rdev);
+ if (ret < 0) {
+ of_node_put(node);
+ return ret;
}
}
diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c
index 7f51c5f..e62e1d7 100644
--- a/drivers/regulator/qcom_spmi-regulator.c
+++ b/drivers/regulator/qcom_spmi-regulator.c
@@ -135,6 +135,18 @@
SPMI_REGULATOR_SUBTYPE_LV_P600 = 0x2b,
SPMI_REGULATOR_SUBTYPE_LV_P1200 = 0x2c,
SPMI_REGULATOR_SUBTYPE_LV_P450 = 0x2d,
+ SPMI_REGULATOR_SUBTYPE_HT_N300_ST = 0x30,
+ SPMI_REGULATOR_SUBTYPE_HT_N600_ST = 0x31,
+ SPMI_REGULATOR_SUBTYPE_HT_N1200_ST = 0x32,
+ SPMI_REGULATOR_SUBTYPE_HT_LVP150 = 0x3b,
+ SPMI_REGULATOR_SUBTYPE_HT_LVP300 = 0x3c,
+ SPMI_REGULATOR_SUBTYPE_L660_N300_ST = 0x42,
+ SPMI_REGULATOR_SUBTYPE_L660_N600_ST = 0x43,
+ SPMI_REGULATOR_SUBTYPE_L660_P50 = 0x46,
+ SPMI_REGULATOR_SUBTYPE_L660_P150 = 0x47,
+ SPMI_REGULATOR_SUBTYPE_L660_P600 = 0x49,
+ SPMI_REGULATOR_SUBTYPE_L660_LVP150 = 0x4d,
+ SPMI_REGULATOR_SUBTYPE_L660_LVP600 = 0x4f,
SPMI_REGULATOR_SUBTYPE_LV100 = 0x01,
SPMI_REGULATOR_SUBTYPE_LV300 = 0x02,
SPMI_REGULATOR_SUBTYPE_MV300 = 0x08,
@@ -380,7 +392,7 @@
enum spmi_regulator_logical_type logical_type;
u32 revision_min;
u32 revision_max;
- struct regulator_ops *ops;
+ const struct regulator_ops *ops;
struct spmi_voltage_set_points *set_points;
int hpm_min_load;
};
@@ -511,6 +523,22 @@
SPMI_VOLTAGE_RANGE(0, 1750000, 1750000, 3337500, 3337500, 12500),
};
+static struct spmi_voltage_range pldo660_ranges[] = {
+ SPMI_VOLTAGE_RANGE(0, 1504000, 1504000, 3544000, 3544000, 8000),
+};
+
+static struct spmi_voltage_range nldo660_ranges[] = {
+ SPMI_VOLTAGE_RANGE(0, 320000, 320000, 1304000, 1304000, 8000),
+};
+
+static struct spmi_voltage_range ht_lvpldo_ranges[] = {
+ SPMI_VOLTAGE_RANGE(0, 1504000, 1504000, 2000000, 2000000, 8000),
+};
+
+static struct spmi_voltage_range ht_nldo_ranges[] = {
+ SPMI_VOLTAGE_RANGE(0, 312000, 312000, 1304000, 1304000, 8000),
+};
+
static struct spmi_voltage_range hfs430_ranges[] = {
SPMI_VOLTAGE_RANGE(0, 320000, 320000, 2040000, 2040000, 8000),
};
@@ -530,6 +558,10 @@
static DEFINE_SPMI_SET_POINTS(ult_ho_smps);
static DEFINE_SPMI_SET_POINTS(ult_nldo);
static DEFINE_SPMI_SET_POINTS(ult_pldo);
+static DEFINE_SPMI_SET_POINTS(pldo660);
+static DEFINE_SPMI_SET_POINTS(nldo660);
+static DEFINE_SPMI_SET_POINTS(ht_lvpldo);
+static DEFINE_SPMI_SET_POINTS(ht_nldo);
static DEFINE_SPMI_SET_POINTS(hfs430);
static inline int spmi_vreg_read(struct spmi_regulator *vreg, u16 addr, u8 *buf,
@@ -1261,7 +1293,7 @@
static struct regulator_ops spmi_saw_ops = {};
-static struct regulator_ops spmi_smps_ops = {
+static const struct regulator_ops spmi_smps_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -1276,7 +1308,7 @@
.set_pull_down = spmi_regulator_common_set_pull_down,
};
-static struct regulator_ops spmi_ldo_ops = {
+static const struct regulator_ops spmi_ldo_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -1293,7 +1325,7 @@
.set_soft_start = spmi_regulator_common_set_soft_start,
};
-static struct regulator_ops spmi_ln_ldo_ops = {
+static const struct regulator_ops spmi_ln_ldo_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -1305,7 +1337,7 @@
.get_bypass = spmi_regulator_common_get_bypass,
};
-static struct regulator_ops spmi_vs_ops = {
+static const struct regulator_ops spmi_vs_ops = {
.enable = spmi_regulator_vs_enable,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -1316,7 +1348,7 @@
.get_mode = spmi_regulator_common_get_mode,
};
-static struct regulator_ops spmi_boost_ops = {
+static const struct regulator_ops spmi_boost_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -1327,7 +1359,7 @@
.set_input_current_limit = spmi_regulator_set_ilim,
};
-static struct regulator_ops spmi_ftsmps_ops = {
+static const struct regulator_ops spmi_ftsmps_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -1342,7 +1374,7 @@
.set_pull_down = spmi_regulator_common_set_pull_down,
};
-static struct regulator_ops spmi_ult_lo_smps_ops = {
+static const struct regulator_ops spmi_ult_lo_smps_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -1356,7 +1388,7 @@
.set_pull_down = spmi_regulator_common_set_pull_down,
};
-static struct regulator_ops spmi_ult_ho_smps_ops = {
+static const struct regulator_ops spmi_ult_ho_smps_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -1371,7 +1403,7 @@
.set_pull_down = spmi_regulator_common_set_pull_down,
};
-static struct regulator_ops spmi_ult_ldo_ops = {
+static const struct regulator_ops spmi_ult_ldo_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -1388,7 +1420,7 @@
.set_soft_start = spmi_regulator_common_set_soft_start,
};
-static struct regulator_ops spmi_ftsmps426_ops = {
+static const struct regulator_ops spmi_ftsmps426_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -1403,7 +1435,7 @@
.set_pull_down = spmi_regulator_common_set_pull_down,
};
-static struct regulator_ops spmi_hfs430_ops = {
+static const struct regulator_ops spmi_hfs430_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -1443,6 +1475,30 @@
SPMI_VREG(LDO, LV_P300, 0, INF, LDO, ldo, pldo, 10000),
SPMI_VREG(LDO, LV_P600, 0, INF, LDO, ldo, pldo, 10000),
SPMI_VREG(LDO, LV_P1200, 0, INF, LDO, ldo, pldo, 10000),
+ SPMI_VREG(LDO, HT_N300_ST, 0, INF, FTSMPS426, ftsmps426,
+ ht_nldo, 30000),
+ SPMI_VREG(LDO, HT_N600_ST, 0, INF, FTSMPS426, ftsmps426,
+ ht_nldo, 30000),
+ SPMI_VREG(LDO, HT_N1200_ST, 0, INF, FTSMPS426, ftsmps426,
+ ht_nldo, 30000),
+ SPMI_VREG(LDO, HT_LVP150, 0, INF, FTSMPS426, ftsmps426,
+ ht_lvpldo, 10000),
+ SPMI_VREG(LDO, HT_LVP300, 0, INF, FTSMPS426, ftsmps426,
+ ht_lvpldo, 10000),
+ SPMI_VREG(LDO, L660_N300_ST, 0, INF, FTSMPS426, ftsmps426,
+ nldo660, 10000),
+ SPMI_VREG(LDO, L660_N600_ST, 0, INF, FTSMPS426, ftsmps426,
+ nldo660, 10000),
+ SPMI_VREG(LDO, L660_P50, 0, INF, FTSMPS426, ftsmps426,
+ pldo660, 10000),
+ SPMI_VREG(LDO, L660_P150, 0, INF, FTSMPS426, ftsmps426,
+ pldo660, 10000),
+ SPMI_VREG(LDO, L660_P600, 0, INF, FTSMPS426, ftsmps426,
+ pldo660, 10000),
+ SPMI_VREG(LDO, L660_LVP150, 0, INF, FTSMPS426, ftsmps426,
+ ht_lvpldo, 10000),
+ SPMI_VREG(LDO, L660_LVP600, 0, INF, FTSMPS426, ftsmps426,
+ ht_lvpldo, 10000),
SPMI_VREG_VS(LV100, 0, INF),
SPMI_VREG_VS(LV300, 0, INF),
SPMI_VREG_VS(MV300, 0, INF),
@@ -1633,45 +1689,43 @@
return ret;
/* Set up enable pin control. */
- if ((type == SPMI_REGULATOR_LOGICAL_TYPE_SMPS
- || type == SPMI_REGULATOR_LOGICAL_TYPE_LDO
- || type == SPMI_REGULATOR_LOGICAL_TYPE_VS)
- && !(data->pin_ctrl_enable
- & SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT)) {
- ctrl_reg[SPMI_COMMON_IDX_ENABLE] &=
- ~SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK;
- ctrl_reg[SPMI_COMMON_IDX_ENABLE] |=
- data->pin_ctrl_enable & SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK;
+ if (!(data->pin_ctrl_enable & SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT)) {
+ switch (type) {
+ case SPMI_REGULATOR_LOGICAL_TYPE_SMPS:
+ case SPMI_REGULATOR_LOGICAL_TYPE_LDO:
+ case SPMI_REGULATOR_LOGICAL_TYPE_VS:
+ ctrl_reg[SPMI_COMMON_IDX_ENABLE] &=
+ ~SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK;
+ ctrl_reg[SPMI_COMMON_IDX_ENABLE] |=
+ data->pin_ctrl_enable & SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK;
+ break;
+ default:
+ break;
+ }
}
/* Set up mode pin control. */
- if ((type == SPMI_REGULATOR_LOGICAL_TYPE_SMPS
- || type == SPMI_REGULATOR_LOGICAL_TYPE_LDO)
- && !(data->pin_ctrl_hpm
- & SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) {
- ctrl_reg[SPMI_COMMON_IDX_MODE] &=
- ~SPMI_COMMON_MODE_FOLLOW_ALL_MASK;
- ctrl_reg[SPMI_COMMON_IDX_MODE] |=
- data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_ALL_MASK;
- }
-
- if (type == SPMI_REGULATOR_LOGICAL_TYPE_VS
- && !(data->pin_ctrl_hpm & SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) {
- ctrl_reg[SPMI_COMMON_IDX_MODE] &=
- ~SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK;
- ctrl_reg[SPMI_COMMON_IDX_MODE] |=
- data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK;
- }
-
- if ((type == SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS
- || type == SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS
- || type == SPMI_REGULATOR_LOGICAL_TYPE_ULT_LDO)
- && !(data->pin_ctrl_hpm
- & SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) {
- ctrl_reg[SPMI_COMMON_IDX_MODE] &=
- ~SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK;
- ctrl_reg[SPMI_COMMON_IDX_MODE] |=
- data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK;
+ if (!(data->pin_ctrl_hpm & SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) {
+ switch (type) {
+ case SPMI_REGULATOR_LOGICAL_TYPE_SMPS:
+ case SPMI_REGULATOR_LOGICAL_TYPE_LDO:
+ ctrl_reg[SPMI_COMMON_IDX_MODE] &=
+ ~SPMI_COMMON_MODE_FOLLOW_ALL_MASK;
+ ctrl_reg[SPMI_COMMON_IDX_MODE] |=
+ data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_ALL_MASK;
+ break;
+ case SPMI_REGULATOR_LOGICAL_TYPE_VS:
+ case SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS:
+ case SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS:
+ case SPMI_REGULATOR_LOGICAL_TYPE_ULT_LDO:
+ ctrl_reg[SPMI_COMMON_IDX_MODE] &=
+ ~SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK;
+ ctrl_reg[SPMI_COMMON_IDX_MODE] |=
+ data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK;
+ break;
+ default:
+ break;
+ }
}
/* Write back any control register values that were modified. */
@@ -1869,6 +1923,39 @@
{ }
};
+static const struct spmi_regulator_data pm8950_regulators[] = {
+ { "s1", 0x1400, "vdd_s1", },
+ { "s2", 0x1700, "vdd_s2", },
+ { "s3", 0x1a00, "vdd_s3", },
+ { "s4", 0x1d00, "vdd_s4", },
+ { "s5", 0x2000, "vdd_s5", },
+ { "s6", 0x2300, "vdd_s6", },
+ { "l1", 0x4000, "vdd_l1_l19", },
+ { "l2", 0x4100, "vdd_l2_l23", },
+ { "l3", 0x4200, "vdd_l3", },
+ { "l4", 0x4300, "vdd_l4_l5_l6_l7_l16", },
+ { "l5", 0x4400, "vdd_l4_l5_l6_l7_l16", },
+ { "l6", 0x4500, "vdd_l4_l5_l6_l7_l16", },
+ { "l7", 0x4600, "vdd_l4_l5_l6_l7_l16", },
+ { "l8", 0x4700, "vdd_l8_l11_l12_l17_l22", },
+ { "l9", 0x4800, "vdd_l9_l10_l13_l14_l15_l18", },
+ { "l10", 0x4900, "vdd_l9_l10_l13_l14_l15_l18", },
+ { "l11", 0x4a00, "vdd_l8_l11_l12_l17_l22", },
+ { "l12", 0x4b00, "vdd_l8_l11_l12_l17_l22", },
+ { "l13", 0x4c00, "vdd_l9_l10_l13_l14_l15_l18", },
+ { "l14", 0x4d00, "vdd_l9_l10_l13_l14_l15_l18", },
+ { "l15", 0x4e00, "vdd_l9_l10_l13_l14_l15_l18", },
+ { "l16", 0x4f00, "vdd_l4_l5_l6_l7_l16", },
+ { "l17", 0x5000, "vdd_l8_l11_l12_l17_l22", },
+ { "l18", 0x5100, "vdd_l9_l10_l13_l14_l15_l18", },
+ { "l19", 0x5200, "vdd_l1_l19", },
+ { "l20", 0x5300, "vdd_l20", },
+ { "l21", 0x5400, "vdd_l21", },
+ { "l22", 0x5500, "vdd_l8_l11_l12_l17_l22", },
+ { "l23", 0x5600, "vdd_l2_l23", },
+ { }
+};
+
static const struct spmi_regulator_data pm8994_regulators[] = {
{ "s1", 0x1400, "vdd_s1", },
{ "s2", 0x1700, "vdd_s2", },
@@ -1927,6 +2014,61 @@
{ }
};
+static const struct spmi_regulator_data pm660_regulators[] = {
+ { "s1", 0x1400, "vdd_s1", },
+ { "s2", 0x1700, "vdd_s2", },
+ { "s3", 0x1a00, "vdd_s3", },
+ { "s4", 0x1d00, "vdd_s3", },
+ { "s5", 0x2000, "vdd_s5", },
+ { "s6", 0x2300, "vdd_s6", },
+ { "l1", 0x4000, "vdd_l1_l6_l7", },
+ { "l2", 0x4100, "vdd_l2_l3", },
+ { "l3", 0x4200, "vdd_l2_l3", },
+ /* l4 is unaccessible on PM660 */
+ { "l5", 0x4400, "vdd_l5", },
+ { "l6", 0x4500, "vdd_l1_l6_l7", },
+ { "l7", 0x4600, "vdd_l1_l6_l7", },
+ { "l8", 0x4700, "vdd_l8_l9_l10_l11_l12_l13_l14", },
+ { "l9", 0x4800, "vdd_l8_l9_l10_l11_l12_l13_l14", },
+ { "l10", 0x4900, "vdd_l8_l9_l10_l11_l12_l13_l14", },
+ { "l11", 0x4a00, "vdd_l8_l9_l10_l11_l12_l13_l14", },
+ { "l12", 0x4b00, "vdd_l8_l9_l10_l11_l12_l13_l14", },
+ { "l13", 0x4c00, "vdd_l8_l9_l10_l11_l12_l13_l14", },
+ { "l14", 0x4d00, "vdd_l8_l9_l10_l11_l12_l13_l14", },
+ { "l15", 0x4e00, "vdd_l15_l16_l17_l18_l19", },
+ { "l16", 0x4f00, "vdd_l15_l16_l17_l18_l19", },
+ { "l17", 0x5000, "vdd_l15_l16_l17_l18_l19", },
+ { "l18", 0x5100, "vdd_l15_l16_l17_l18_l19", },
+ { "l19", 0x5200, "vdd_l15_l16_l17_l18_l19", },
+ { }
+};
+
+static const struct spmi_regulator_data pm660l_regulators[] = {
+ { "s1", 0x1400, "vdd_s1", },
+ { "s2", 0x1700, "vdd_s2", },
+ { "s3", 0x1a00, "vdd_s3", },
+ { "s4", 0x1d00, "vdd_s4", },
+ { "s5", 0x2000, "vdd_s5", },
+ { "l1", 0x4000, "vdd_l1_l9_l10", },
+ { "l2", 0x4100, "vdd_l2", },
+ { "l3", 0x4200, "vdd_l3_l5_l7_l8", },
+ { "l4", 0x4300, "vdd_l4_l6", },
+ { "l5", 0x4400, "vdd_l3_l5_l7_l8", },
+ { "l6", 0x4500, "vdd_l4_l6", },
+ { "l7", 0x4600, "vdd_l3_l5_l7_l8", },
+ { "l8", 0x4700, "vdd_l3_l5_l7_l8", },
+ { "l9", 0x4800, "vdd_l1_l9_l10", },
+ { "l10", 0x4900, "vdd_l1_l9_l10", },
+ { }
+};
+
+
+static const struct spmi_regulator_data pm8004_regulators[] = {
+ { "s2", 0x1700, "vdd_s2", },
+ { "s5", 0x2000, "vdd_s5", },
+ { }
+};
+
static const struct spmi_regulator_data pm8005_regulators[] = {
{ "s1", 0x1400, "vdd_s1", },
{ "s2", 0x1700, "vdd_s2", },
@@ -1941,12 +2083,16 @@
};
static const struct of_device_id qcom_spmi_regulator_match[] = {
+ { .compatible = "qcom,pm8004-regulators", .data = &pm8004_regulators },
{ .compatible = "qcom,pm8005-regulators", .data = &pm8005_regulators },
{ .compatible = "qcom,pm8841-regulators", .data = &pm8841_regulators },
{ .compatible = "qcom,pm8916-regulators", .data = &pm8916_regulators },
{ .compatible = "qcom,pm8941-regulators", .data = &pm8941_regulators },
+ { .compatible = "qcom,pm8950-regulators", .data = &pm8950_regulators },
{ .compatible = "qcom,pm8994-regulators", .data = &pm8994_regulators },
{ .compatible = "qcom,pmi8994-regulators", .data = &pmi8994_regulators },
+ { .compatible = "qcom,pm660-regulators", .data = &pm660_regulators },
+ { .compatible = "qcom,pm660l-regulators", .data = &pm660l_regulators },
{ .compatible = "qcom,pms405-regulators", .data = &pms405_regulators },
{ }
};
diff --git a/drivers/regulator/qcom_usb_vbus-regulator.c b/drivers/regulator/qcom_usb_vbus-regulator.c
new file mode 100644
index 0000000..457788b
--- /dev/null
+++ b/drivers/regulator/qcom_usb_vbus-regulator.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Qualcomm PMIC VBUS output regulator driver
+//
+// Copyright (c) 2020, The Linux Foundation. All rights reserved.
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regmap.h>
+
+#define CMD_OTG 0x40
+#define OTG_EN BIT(0)
+#define OTG_CFG 0x53
+#define OTG_EN_SRC_CFG BIT(1)
+
+static const struct regulator_ops qcom_usb_vbus_reg_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+static struct regulator_desc qcom_usb_vbus_rdesc = {
+ .name = "usb_vbus",
+ .ops = &qcom_usb_vbus_reg_ops,
+ .owner = THIS_MODULE,
+ .type = REGULATOR_VOLTAGE,
+};
+
+static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regulator_dev *rdev;
+ struct regmap *regmap;
+ struct regulator_config config = { };
+ struct regulator_init_data *init_data;
+ int ret;
+ u32 base;
+
+ ret = of_property_read_u32(dev->of_node, "reg", &base);
+ if (ret < 0) {
+ dev_err(dev, "no base address found\n");
+ return ret;
+ }
+
+ regmap = dev_get_regmap(dev->parent, NULL);
+ if (!regmap) {
+ dev_err(dev, "Failed to get regmap\n");
+ return -ENOENT;
+ }
+
+ init_data = of_get_regulator_init_data(dev, dev->of_node,
+ &qcom_usb_vbus_rdesc);
+ if (!init_data)
+ return -ENOMEM;
+
+ qcom_usb_vbus_rdesc.enable_reg = base + CMD_OTG;
+ qcom_usb_vbus_rdesc.enable_mask = OTG_EN;
+ config.dev = dev;
+ config.init_data = init_data;
+ config.of_node = dev->of_node;
+ config.regmap = regmap;
+
+ rdev = devm_regulator_register(dev, &qcom_usb_vbus_rdesc, &config);
+ if (IS_ERR(rdev)) {
+ ret = PTR_ERR(rdev);
+ dev_err(dev, "not able to register vbus reg %d\n", ret);
+ return ret;
+ }
+
+ /* Disable HW logic for VBUS enable */
+ regmap_update_bits(regmap, base + OTG_CFG, OTG_EN_SRC_CFG, 0);
+
+ return 0;
+}
+
+static const struct of_device_id qcom_usb_vbus_regulator_match[] = {
+ { .compatible = "qcom,pm8150b-vbus-reg" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, qcom_usb_vbus_regulator_match);
+
+static struct platform_driver qcom_usb_vbus_regulator_driver = {
+ .driver = {
+ .name = "qcom-usb-vbus-regulator",
+ .of_match_table = qcom_usb_vbus_regulator_match,
+ },
+ .probe = qcom_usb_vbus_regulator_probe,
+};
+module_platform_driver(qcom_usb_vbus_regulator_driver);
+
+MODULE_DESCRIPTION("Qualcomm USB vbus regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index 97c846c..e926c1a 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -165,14 +165,14 @@
RK808_BUCK4_CONFIG_REG,
};
-static const struct regulator_linear_range rk808_ldo3_voltage_ranges[] = {
+static const struct linear_range rk808_ldo3_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(800000, 0, 13, 100000),
REGULATOR_LINEAR_RANGE(2500000, 15, 15, 0),
};
#define RK809_BUCK5_SEL_CNT (8)
-static const struct regulator_linear_range rk809_buck5_voltage_ranges[] = {
+static const struct linear_range rk809_buck5_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(1500000, 0, 0, 0),
REGULATOR_LINEAR_RANGE(1800000, 1, 3, 200000),
REGULATOR_LINEAR_RANGE(2800000, 4, 5, 200000),
@@ -201,14 +201,14 @@
#define RK817_BUCK1_SEL_CNT (RK817_BUCK1_SEL0 + RK817_BUCK1_SEL1 + 1)
#define RK817_BUCK3_SEL_CNT (RK817_BUCK1_SEL0 + RK817_BUCK3_SEL1 + 1)
-static const struct regulator_linear_range rk817_buck1_voltage_ranges[] = {
+static const struct linear_range rk817_buck1_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN0, 0,
RK817_BUCK1_SEL0, RK817_BUCK1_STP0),
REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN1, RK817_BUCK1_SEL0 + 1,
RK817_BUCK1_SEL_CNT, RK817_BUCK1_STP1),
};
-static const struct regulator_linear_range rk817_buck3_voltage_ranges[] = {
+static const struct linear_range rk817_buck3_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN0, 0,
RK817_BUCK1_SEL0, RK817_BUCK1_STP0),
REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN1, RK817_BUCK1_SEL0 + 1,
@@ -388,7 +388,7 @@
break;
default:
dev_warn(&rdev->dev,
- "%s ramp_delay: %d not supported, setting 10000\n",
+ "%s ramp_delay: %d not supported, setting 25000\n",
rdev->desc->name, ramp_delay);
}
@@ -411,21 +411,6 @@
sel);
}
-static int rk817_set_suspend_voltage(struct regulator_dev *rdev, int uv)
-{
- unsigned int reg;
- int sel = regulator_map_voltage_linear(rdev, uv, uv);
- /* only ldo1~ldo9 */
- if (sel < 0)
- return -EINVAL;
-
- reg = rdev->desc->vsel_reg + RK808_SLP_REG_OFFSET;
-
- return regmap_update_bits(rdev->regmap, reg,
- rdev->desc->vsel_mask,
- sel);
-}
-
static int rk808_set_suspend_voltage_range(struct regulator_dev *rdev, int uv)
{
unsigned int reg;
@@ -680,13 +665,13 @@
.set_suspend_disable = rk808_set_suspend_disable,
};
-static const struct regulator_linear_range rk805_buck_1_2_voltage_ranges[] = {
+static const struct linear_range rk805_buck_1_2_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(712500, 0, 59, 12500),
REGULATOR_LINEAR_RANGE(1800000, 60, 62, 200000),
REGULATOR_LINEAR_RANGE(2300000, 63, 63, 0),
};
-static struct regulator_ops rk809_buck5_ops_range = {
+static const struct regulator_ops rk809_buck5_ops_range = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -700,7 +685,7 @@
.set_suspend_disable = rk817_set_suspend_disable,
};
-static struct regulator_ops rk817_reg_ops = {
+static const struct regulator_ops rk817_reg_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -708,12 +693,12 @@
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = rk8xx_is_enabled_wmsk_regmap,
- .set_suspend_voltage = rk817_set_suspend_voltage,
+ .set_suspend_voltage = rk808_set_suspend_voltage,
.set_suspend_enable = rk817_set_suspend_enable,
.set_suspend_disable = rk817_set_suspend_disable,
};
-static struct regulator_ops rk817_boost_ops = {
+static const struct regulator_ops rk817_boost_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -725,7 +710,7 @@
.set_suspend_disable = rk817_set_suspend_disable,
};
-static struct regulator_ops rk817_buck_ops_range = {
+static const struct regulator_ops rk817_buck_ops_range = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -743,7 +728,7 @@
.set_suspend_disable = rk817_set_suspend_disable,
};
-static struct regulator_ops rk817_switch_ops = {
+static const struct regulator_ops rk817_switch_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = rk8xx_is_enabled_wmsk_regmap,
diff --git a/drivers/regulator/rn5t618-regulator.c b/drivers/regulator/rn5t618-regulator.c
index aa6e7c5..5c12d57 100644
--- a/drivers/regulator/rn5t618-regulator.c
+++ b/drivers/regulator/rn5t618-regulator.c
@@ -90,7 +90,7 @@
REG(LDO7, LDOEN1, BIT(6), LDO7DAC, 0x7f, 900000, 3500000, 25000),
REG(LDO8, LDOEN1, BIT(7), LDO8DAC, 0x7f, 900000, 3500000, 25000),
REG(LDO9, LDOEN2, BIT(0), LDO9DAC, 0x7f, 900000, 3500000, 25000),
- REG(LDO10, LDOEN2, BIT(0), LDO10DAC, 0x7f, 900000, 3500000, 25000),
+ REG(LDO10, LDOEN2, BIT(1), LDO10DAC, 0x7f, 900000, 3500000, 25000),
/* LDO RTC */
REG(LDORTC1, LDOEN2, BIT(4), LDORTCDAC, 0x7f, 1700000, 3500000, 25000),
REG(LDORTC2, LDOEN2, BIT(5), LDORTC2DAC, 0x7f, 900000, 3500000, 25000),
diff --git a/drivers/regulator/rohm-regulator.c b/drivers/regulator/rohm-regulator.c
new file mode 100644
index 0000000..5c558b1
--- /dev/null
+++ b/drivers/regulator/rohm-regulator.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2020 ROHM Semiconductors
+
+#include <linux/errno.h>
+#include <linux/mfd/rohm-generic.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+
+static int set_dvs_level(const struct regulator_desc *desc,
+ struct device_node *np, struct regmap *regmap,
+ char *prop, unsigned int reg, unsigned int mask,
+ unsigned int omask, unsigned int oreg)
+{
+ int ret, i;
+ uint32_t uv;
+
+ ret = of_property_read_u32(np, prop, &uv);
+ if (ret) {
+ if (ret != -EINVAL)
+ return ret;
+ return 0;
+ }
+
+ if (uv == 0) {
+ if (omask)
+ return regmap_update_bits(regmap, oreg, omask, 0);
+ }
+ for (i = 0; i < desc->n_voltages; i++) {
+ ret = regulator_desc_list_voltage_linear_range(desc, i);
+ if (ret < 0)
+ continue;
+ if (ret == uv) {
+ i <<= ffs(desc->vsel_mask) - 1;
+ ret = regmap_update_bits(regmap, reg, mask, i);
+ if (omask && !ret)
+ ret = regmap_update_bits(regmap, oreg, omask,
+ omask);
+ break;
+ }
+ }
+ return ret;
+}
+
+int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs,
+ struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regmap *regmap)
+{
+ int i, ret = 0;
+ char *prop;
+ unsigned int reg, mask, omask, oreg = desc->enable_reg;
+
+ for (i = 0; i < ROHM_DVS_LEVEL_VALID_AMOUNT && !ret; i++) {
+ int bit;
+
+ bit = BIT(i);
+ if (dvs->level_map & bit) {
+ switch (bit) {
+ case ROHM_DVS_LEVEL_RUN:
+ prop = "rohm,dvs-run-voltage";
+ reg = dvs->run_reg;
+ mask = dvs->run_mask;
+ omask = dvs->run_on_mask;
+ break;
+ case ROHM_DVS_LEVEL_IDLE:
+ prop = "rohm,dvs-idle-voltage";
+ reg = dvs->idle_reg;
+ mask = dvs->idle_mask;
+ omask = dvs->idle_on_mask;
+ break;
+ case ROHM_DVS_LEVEL_SUSPEND:
+ prop = "rohm,dvs-suspend-voltage";
+ reg = dvs->suspend_reg;
+ mask = dvs->suspend_mask;
+ omask = dvs->suspend_on_mask;
+ break;
+ case ROHM_DVS_LEVEL_LPSR:
+ prop = "rohm,dvs-lpsr-voltage";
+ reg = dvs->lpsr_reg;
+ mask = dvs->lpsr_mask;
+ omask = dvs->lpsr_on_mask;
+ break;
+ default:
+ return -EINVAL;
+ }
+ ret = set_dvs_level(desc, np, regmap, prop, reg, mask,
+ omask, oreg);
+ }
+ }
+ return ret;
+}
+EXPORT_SYMBOL(rohm_regulator_set_dvs_levels);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
+MODULE_DESCRIPTION("Generic helpers for ROHM PMIC regulator drivers");
diff --git a/drivers/regulator/rpi-panel-attiny-regulator.c b/drivers/regulator/rpi-panel-attiny-regulator.c
new file mode 100644
index 0000000..ee46bfb
--- /dev/null
+++ b/drivers/regulator/rpi-panel-attiny-regulator.c
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Marek Vasut <marex@denx.de>
+ *
+ * Based on rpi_touchscreen.c by Eric Anholt <eric@anholt.net>
+ */
+
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/slab.h>
+
+/* I2C registers of the Atmel microcontroller. */
+#define REG_ID 0x80
+#define REG_PORTA 0x81
+#define REG_PORTA_HF BIT(2)
+#define REG_PORTA_VF BIT(3)
+#define REG_PORTB 0x82
+#define REG_POWERON 0x85
+#define REG_PWM 0x86
+
+static const struct regmap_config attiny_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = REG_PWM,
+ .cache_type = REGCACHE_NONE,
+};
+
+static int attiny_lcd_power_enable(struct regulator_dev *rdev)
+{
+ unsigned int data;
+
+ regmap_write(rdev->regmap, REG_POWERON, 1);
+ /* Wait for nPWRDWN to go low to indicate poweron is done. */
+ regmap_read_poll_timeout(rdev->regmap, REG_PORTB, data,
+ data & BIT(0), 10, 1000000);
+
+ /* Default to the same orientation as the closed source
+ * firmware used for the panel. Runtime rotation
+ * configuration will be supported using VC4's plane
+ * orientation bits.
+ */
+ regmap_write(rdev->regmap, REG_PORTA, BIT(2));
+
+ return 0;
+}
+
+static int attiny_lcd_power_disable(struct regulator_dev *rdev)
+{
+ regmap_write(rdev->regmap, REG_PWM, 0);
+ regmap_write(rdev->regmap, REG_POWERON, 0);
+ udelay(1);
+ return 0;
+}
+
+static int attiny_lcd_power_is_enabled(struct regulator_dev *rdev)
+{
+ unsigned int data;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, REG_POWERON, &data);
+ if (ret < 0)
+ return ret;
+
+ if (!(data & BIT(0)))
+ return 0;
+
+ ret = regmap_read(rdev->regmap, REG_PORTB, &data);
+ if (ret < 0)
+ return ret;
+
+ return data & BIT(0);
+}
+
+static const struct regulator_init_data attiny_regulator_default = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static const struct regulator_ops attiny_regulator_ops = {
+ .enable = attiny_lcd_power_enable,
+ .disable = attiny_lcd_power_disable,
+ .is_enabled = attiny_lcd_power_is_enabled,
+};
+
+static const struct regulator_desc attiny_regulator = {
+ .name = "tc358762-power",
+ .ops = &attiny_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+};
+
+static int attiny_update_status(struct backlight_device *bl)
+{
+ struct regmap *regmap = bl_get_data(bl);
+ int brightness = bl->props.brightness;
+
+ if (bl->props.power != FB_BLANK_UNBLANK ||
+ bl->props.fb_blank != FB_BLANK_UNBLANK)
+ brightness = 0;
+
+ return regmap_write(regmap, REG_PWM, brightness);
+}
+
+static int attiny_get_brightness(struct backlight_device *bl)
+{
+ struct regmap *regmap = bl_get_data(bl);
+ int ret, brightness;
+
+ ret = regmap_read(regmap, REG_PWM, &brightness);
+ if (ret)
+ return ret;
+
+ return brightness;
+}
+
+static const struct backlight_ops attiny_bl = {
+ .update_status = attiny_update_status,
+ .get_brightness = attiny_get_brightness,
+};
+
+/*
+ * I2C driver interface functions
+ */
+static int attiny_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct backlight_properties props = { };
+ struct regulator_config config = { };
+ struct backlight_device *bl;
+ struct regulator_dev *rdev;
+ struct regmap *regmap;
+ unsigned int data;
+ int ret;
+
+ regmap = devm_regmap_init_i2c(i2c, &attiny_regmap_config);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = regmap_read(regmap, REG_ID, &data);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read REG_ID reg: %d\n", ret);
+ return ret;
+ }
+
+ switch (data) {
+ case 0xde: /* ver 1 */
+ case 0xc3: /* ver 2 */
+ break;
+ default:
+ dev_err(&i2c->dev, "Unknown Atmel firmware revision: 0x%02x\n", data);
+ return -ENODEV;
+ }
+
+ regmap_write(regmap, REG_POWERON, 0);
+ mdelay(1);
+
+ config.dev = &i2c->dev;
+ config.regmap = regmap;
+ config.of_node = i2c->dev.of_node;
+ config.init_data = &attiny_regulator_default;
+
+ rdev = devm_regulator_register(&i2c->dev, &attiny_regulator, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&i2c->dev, "Failed to register ATTINY regulator\n");
+ return PTR_ERR(rdev);
+ }
+
+ props.type = BACKLIGHT_RAW;
+ props.max_brightness = 0xff;
+ bl = devm_backlight_device_register(&i2c->dev,
+ "7inch-touchscreen-panel-bl",
+ &i2c->dev, regmap, &attiny_bl,
+ &props);
+ if (IS_ERR(bl))
+ return PTR_ERR(bl);
+
+ bl->props.brightness = 0xff;
+
+ return 0;
+}
+
+static const struct of_device_id attiny_dt_ids[] = {
+ { .compatible = "raspberrypi,7inch-touchscreen-panel-regulator" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, attiny_dt_ids);
+
+static struct i2c_driver attiny_regulator_driver = {
+ .driver = {
+ .name = "rpi_touchscreen_attiny",
+ .of_match_table = of_match_ptr(attiny_dt_ids),
+ },
+ .probe = attiny_i2c_probe,
+};
+
+module_i2c_driver(attiny_regulator_driver);
+
+MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
+MODULE_DESCRIPTION("Regulator device driver for Raspberry Pi 7-inch touchscreen");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/rt4801-regulator.c b/drivers/regulator/rt4801-regulator.c
new file mode 100644
index 0000000..7a87788
--- /dev/null
+++ b/drivers/regulator/rt4801-regulator.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+
+#define RT4801_REG_VOP 0x00
+#define RT4801_REG_VON 0x01
+#define RT4801_REG_APPS 0x03
+
+#define VOUT_MASK 0x1F
+
+#define MIN_UV 4000000
+#define STEP_UV 100000
+#define MAX_UV 6000000
+#define N_VOLTAGES ((MAX_UV - MIN_UV) / STEP_UV + 1)
+
+#define DSV_OUT_POS 0
+#define DSV_OUT_NEG 1
+#define DSV_OUT_MAX 2
+
+#define DSVP_ENABLE BIT(0)
+#define DSVN_ENABLE BIT(1)
+#define DSVALL_ENABLE (DSVP_ENABLE | DSVN_ENABLE)
+
+struct rt4801_priv {
+ struct device *dev;
+ struct gpio_descs *enable_gpios;
+ unsigned int enable_flag;
+ unsigned int volt_sel[DSV_OUT_MAX];
+};
+
+static int rt4801_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector)
+{
+ struct rt4801_priv *priv = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev), ret;
+
+ if (priv->enable_flag & BIT(id)) {
+ ret = regulator_set_voltage_sel_regmap(rdev, selector);
+ if (ret)
+ return ret;
+ }
+
+ priv->volt_sel[id] = selector;
+ return 0;
+}
+
+static int rt4801_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct rt4801_priv *priv = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+
+ if (priv->enable_flag & BIT(id))
+ return regulator_get_voltage_sel_regmap(rdev);
+
+ return priv->volt_sel[id];
+}
+
+static int rt4801_enable(struct regulator_dev *rdev)
+{
+ struct rt4801_priv *priv = rdev_get_drvdata(rdev);
+ struct gpio_descs *gpios = priv->enable_gpios;
+ int id = rdev_get_id(rdev), ret;
+
+ if (!gpios || gpios->ndescs <= id) {
+ dev_warn(&rdev->dev, "no dedicated gpio can control\n");
+ goto bypass_gpio;
+ }
+
+ gpiod_set_value(gpios->desc[id], 1);
+
+bypass_gpio:
+ ret = regmap_write(rdev->regmap, rdev->desc->vsel_reg, priv->volt_sel[id]);
+ if (ret)
+ return ret;
+
+ priv->enable_flag |= BIT(id);
+ return 0;
+}
+
+static int rt4801_disable(struct regulator_dev *rdev)
+{
+ struct rt4801_priv *priv = rdev_get_drvdata(rdev);
+ struct gpio_descs *gpios = priv->enable_gpios;
+ int id = rdev_get_id(rdev);
+
+ if (!gpios || gpios->ndescs <= id) {
+ dev_warn(&rdev->dev, "no dedicated gpio can control\n");
+ goto bypass_gpio;
+ }
+
+ gpiod_set_value(gpios->desc[id], 0);
+
+bypass_gpio:
+ priv->enable_flag &= ~BIT(id);
+ return 0;
+}
+
+static int rt4801_is_enabled(struct regulator_dev *rdev)
+{
+ struct rt4801_priv *priv = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+
+ return !!(priv->enable_flag & BIT(id));
+}
+
+static const struct regulator_ops rt4801_regulator_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .set_voltage_sel = rt4801_set_voltage_sel,
+ .get_voltage_sel = rt4801_get_voltage_sel,
+ .enable = rt4801_enable,
+ .disable = rt4801_disable,
+ .is_enabled = rt4801_is_enabled,
+};
+
+static const struct regulator_desc rt4801_regulator_descs[] = {
+ {
+ .name = "DSVP",
+ .ops = &rt4801_regulator_ops,
+ .of_match = of_match_ptr("DSVP"),
+ .type = REGULATOR_VOLTAGE,
+ .id = DSV_OUT_POS,
+ .min_uV = MIN_UV,
+ .uV_step = STEP_UV,
+ .n_voltages = N_VOLTAGES,
+ .owner = THIS_MODULE,
+ .vsel_reg = RT4801_REG_VOP,
+ .vsel_mask = VOUT_MASK,
+ },
+ {
+ .name = "DSVN",
+ .ops = &rt4801_regulator_ops,
+ .of_match = of_match_ptr("DSVN"),
+ .type = REGULATOR_VOLTAGE,
+ .id = DSV_OUT_NEG,
+ .min_uV = MIN_UV,
+ .uV_step = STEP_UV,
+ .n_voltages = N_VOLTAGES,
+ .owner = THIS_MODULE,
+ .vsel_reg = RT4801_REG_VON,
+ .vsel_mask = VOUT_MASK,
+ },
+};
+
+static const struct regmap_config rt4801_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = RT4801_REG_APPS,
+};
+
+static int rt4801_probe(struct i2c_client *i2c)
+{
+ struct rt4801_priv *priv;
+ struct regmap *regmap;
+ int i;
+
+ priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = &i2c->dev;
+ /* bootloader will on, driver only reconfigure enable to all output high */
+ priv->enable_flag = DSVALL_ENABLE;
+
+ regmap = devm_regmap_init_i2c(i2c, &rt4801_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(&i2c->dev, "Failed to init regmap\n");
+ return PTR_ERR(regmap);
+ }
+
+ priv->enable_gpios = devm_gpiod_get_array_optional(&i2c->dev, "enable", GPIOD_OUT_HIGH);
+ if (IS_ERR(priv->enable_gpios)) {
+ dev_err(&i2c->dev, "Failed to get gpios\n");
+ return PTR_ERR(priv->enable_gpios);
+ }
+
+ for (i = 0; i < DSV_OUT_MAX; i++) {
+ const struct regulator_desc *desc = rt4801_regulator_descs + i;
+ struct regulator_config config = { .dev = &i2c->dev, .driver_data = priv,
+ .regmap = regmap, };
+ struct regulator_dev *rdev;
+ unsigned int val;
+ int ret;
+
+ /* initialize volt_sel variable */
+ ret = regmap_read(regmap, desc->vsel_reg, &val);
+ if (ret)
+ return ret;
+
+ priv->volt_sel[i] = val & desc->vsel_mask;
+
+ rdev = devm_regulator_register(&i2c->dev, desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&i2c->dev, "Failed to register [%d] regulator\n", i);
+ return PTR_ERR(rdev);
+ }
+ }
+
+ return 0;
+}
+
+static const struct of_device_id __maybe_unused rt4801_of_id[] = {
+ { .compatible = "richtek,rt4801", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, rt4801_of_id);
+
+static struct i2c_driver rt4801_driver = {
+ .driver = {
+ .name = "rt4801",
+ .of_match_table = of_match_ptr(rt4801_of_id),
+ },
+ .probe_new = rt4801_probe,
+};
+module_i2c_driver(rt4801_driver);
+
+MODULE_AUTHOR("ChiYuan Hwang <cy_huang@richtek.com>");
+MODULE_DESCRIPTION("Richtek RT4801 Display Bias Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/rtmv20-regulator.c b/drivers/regulator/rtmv20-regulator.c
new file mode 100644
index 0000000..2ee3341
--- /dev/null
+++ b/drivers/regulator/rtmv20-regulator.c
@@ -0,0 +1,437 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+
+#define RTMV20_REG_DEVINFO 0x00
+#define RTMV20_REG_PULSEDELAY 0x01
+#define RTMV20_REG_PULSEWIDTH 0x03
+#define RTMV20_REG_LDCTRL1 0x05
+#define RTMV20_REG_ESPULSEWIDTH 0x06
+#define RTMV20_REG_ESLDCTRL1 0x08
+#define RTMV20_REG_LBP 0x0A
+#define RTMV20_REG_LDCTRL2 0x0B
+#define RTMV20_REG_FSIN1CTRL1 0x0D
+#define RTMV20_REG_FSIN1CTRL3 0x0F
+#define RTMV20_REG_FSIN2CTRL1 0x10
+#define RTMV20_REG_FSIN2CTRL3 0x12
+#define RTMV20_REG_ENCTRL 0x13
+#define RTMV20_REG_STRBVSYNDLYL 0x29
+#define RTMV20_REG_LDIRQ 0x30
+#define RTMV20_REG_LDSTAT 0x40
+#define RTMV20_REG_LDMASK 0x50
+#define RTMV20_MAX_REGS (RTMV20_REG_LDMASK + 1)
+
+#define RTMV20_VID_MASK GENMASK(7, 4)
+#define RICHTEK_VID 0x80
+#define RTMV20_LDCURR_MASK GENMASK(7, 0)
+#define RTMV20_DELAY_MASK GENMASK(9, 0)
+#define RTMV20_WIDTH_MASK GENMASK(13, 0)
+#define RTMV20_WIDTH2_MASK GENMASK(7, 0)
+#define RTMV20_LBPLVL_MASK GENMASK(3, 0)
+#define RTMV20_LBPEN_MASK BIT(7)
+#define RTMV20_STROBEPOL_MASK BIT(0)
+#define RTMV20_VSYNPOL_MASK BIT(1)
+#define RTMV20_FSINEN_MASK BIT(7)
+#define RTMV20_ESEN_MASK BIT(6)
+#define RTMV20_FSINOUT_MASK BIT(2)
+#define LDENABLE_MASK (BIT(3) | BIT(0))
+
+#define OTPEVT_MASK BIT(4)
+#define SHORTEVT_MASK BIT(3)
+#define OPENEVT_MASK BIT(2)
+#define LBPEVT_MASK BIT(1)
+#define OCPEVT_MASK BIT(0)
+#define FAILEVT_MASK (SHORTEVT_MASK | OPENEVT_MASK | LBPEVT_MASK)
+
+#define RTMV20_LSW_MINUA 0
+#define RTMV20_LSW_MAXUA 6000000
+#define RTMV20_LSW_STEPUA 30000
+
+#define RTMV20_LSW_DEFAULTUA 3000000
+
+#define RTMV20_I2CRDY_TIMEUS 200
+#define RTMV20_CSRDY_TIMEUS 2000
+
+struct rtmv20_priv {
+ struct device *dev;
+ struct regmap *regmap;
+ struct gpio_desc *enable_gpio;
+ struct regulator_dev *rdev;
+};
+
+static int rtmv20_lsw_enable(struct regulator_dev *rdev)
+{
+ struct rtmv20_priv *priv = rdev_get_drvdata(rdev);
+ int ret;
+
+ gpiod_set_value(priv->enable_gpio, 1);
+
+ /* Wait for I2C can be accessed */
+ usleep_range(RTMV20_I2CRDY_TIMEUS, RTMV20_I2CRDY_TIMEUS + 100);
+
+ /* HW re-enable, disable cache only and sync regcache here */
+ regcache_cache_only(priv->regmap, false);
+ ret = regcache_sync(priv->regmap);
+ if (ret)
+ return ret;
+
+ return regulator_enable_regmap(rdev);
+}
+
+static int rtmv20_lsw_disable(struct regulator_dev *rdev)
+{
+ struct rtmv20_priv *priv = rdev_get_drvdata(rdev);
+ int ret;
+
+ ret = regulator_disable_regmap(rdev);
+ if (ret)
+ return ret;
+
+ /* Mark the regcache as dirty and cache only before HW disabled */
+ regcache_cache_only(priv->regmap, true);
+ regcache_mark_dirty(priv->regmap);
+
+ gpiod_set_value(priv->enable_gpio, 0);
+
+ return 0;
+}
+
+static int rtmv20_lsw_set_current_limit(struct regulator_dev *rdev, int min_uA,
+ int max_uA)
+{
+ int sel;
+
+ if (min_uA > RTMV20_LSW_MAXUA || max_uA < RTMV20_LSW_MINUA)
+ return -EINVAL;
+
+ if (max_uA > RTMV20_LSW_MAXUA)
+ max_uA = RTMV20_LSW_MAXUA;
+
+ sel = (max_uA - RTMV20_LSW_MINUA) / RTMV20_LSW_STEPUA;
+
+ /* Ensure the selected setting is still in range */
+ if ((sel * RTMV20_LSW_STEPUA + RTMV20_LSW_MINUA) < min_uA)
+ return -EINVAL;
+
+ sel <<= ffs(rdev->desc->csel_mask) - 1;
+
+ return regmap_update_bits(rdev->regmap, rdev->desc->csel_reg,
+ rdev->desc->csel_mask, sel);
+}
+
+static int rtmv20_lsw_get_current_limit(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, rdev->desc->csel_reg, &val);
+ if (ret)
+ return ret;
+
+ val &= rdev->desc->csel_mask;
+ val >>= ffs(rdev->desc->csel_mask) - 1;
+
+ return val * RTMV20_LSW_STEPUA + RTMV20_LSW_MINUA;
+}
+
+static const struct regulator_ops rtmv20_regulator_ops = {
+ .set_current_limit = rtmv20_lsw_set_current_limit,
+ .get_current_limit = rtmv20_lsw_get_current_limit,
+ .enable = rtmv20_lsw_enable,
+ .disable = rtmv20_lsw_disable,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+static const struct regulator_desc rtmv20_lsw_desc = {
+ .name = "rtmv20,lsw",
+ .of_match = of_match_ptr("lsw"),
+ .type = REGULATOR_CURRENT,
+ .owner = THIS_MODULE,
+ .ops = &rtmv20_regulator_ops,
+ .csel_reg = RTMV20_REG_LDCTRL1,
+ .csel_mask = RTMV20_LDCURR_MASK,
+ .enable_reg = RTMV20_REG_ENCTRL,
+ .enable_mask = LDENABLE_MASK,
+ .enable_time = RTMV20_CSRDY_TIMEUS,
+};
+
+static irqreturn_t rtmv20_irq_handler(int irq, void *data)
+{
+ struct rtmv20_priv *priv = data;
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(priv->regmap, RTMV20_REG_LDIRQ, &val);
+ if (ret) {
+ dev_err(priv->dev, "Failed to get irq flags\n");
+ return IRQ_NONE;
+ }
+
+ if (val & OTPEVT_MASK)
+ regulator_notifier_call_chain(priv->rdev, REGULATOR_EVENT_OVER_TEMP, NULL);
+
+ if (val & OCPEVT_MASK)
+ regulator_notifier_call_chain(priv->rdev, REGULATOR_EVENT_OVER_CURRENT, NULL);
+
+ if (val & FAILEVT_MASK)
+ regulator_notifier_call_chain(priv->rdev, REGULATOR_EVENT_FAIL, NULL);
+
+ return IRQ_HANDLED;
+}
+
+static u32 clamp_to_selector(u32 val, u32 min, u32 max, u32 step)
+{
+ u32 retval = clamp_val(val, min, max);
+
+ return (retval - min) / step;
+}
+
+static int rtmv20_properties_init(struct rtmv20_priv *priv)
+{
+ const struct {
+ const char *name;
+ u32 def;
+ u32 min;
+ u32 max;
+ u32 step;
+ u32 addr;
+ u32 mask;
+ } props[] = {
+ { "richtek,ld-pulse-delay-us", 0, 0, 100000, 100, RTMV20_REG_PULSEDELAY,
+ RTMV20_DELAY_MASK },
+ { "richtek,ld-pulse-width-us", 1200, 0, 10000, 1, RTMV20_REG_PULSEWIDTH,
+ RTMV20_WIDTH_MASK },
+ { "richtek,fsin1-delay-us", 23000, 0, 100000, 100, RTMV20_REG_FSIN1CTRL1,
+ RTMV20_DELAY_MASK },
+ { "richtek,fsin1-width-us", 160, 40, 10000, 40, RTMV20_REG_FSIN1CTRL3,
+ RTMV20_WIDTH2_MASK },
+ { "richtek,fsin2-delay-us", 23000, 0, 100000, 100, RTMV20_REG_FSIN2CTRL1,
+ RTMV20_DELAY_MASK },
+ { "richtek,fsin2-width-us", 160, 40, 10000, 40, RTMV20_REG_FSIN2CTRL3,
+ RTMV20_WIDTH2_MASK },
+ { "richtek,es-pulse-width-us", 1200, 0, 10000, 1, RTMV20_REG_ESPULSEWIDTH,
+ RTMV20_WIDTH_MASK },
+ { "richtek,es-ld-current-microamp", 3000000, 0, 6000000, 30000,
+ RTMV20_REG_ESLDCTRL1, RTMV20_LDCURR_MASK },
+ { "richtek,lbp-level-microvolt", 2700000, 2400000, 3700000, 100000, RTMV20_REG_LBP,
+ RTMV20_LBPLVL_MASK },
+ { "richtek,lbp-enable", 0, 0, 1, 1, RTMV20_REG_LBP, RTMV20_LBPEN_MASK },
+ { "richtek,strobe-polarity-high", 1, 0, 1, 1, RTMV20_REG_LDCTRL2,
+ RTMV20_STROBEPOL_MASK },
+ { "richtek,vsync-polarity-high", 1, 0, 1, 1, RTMV20_REG_LDCTRL2,
+ RTMV20_VSYNPOL_MASK },
+ { "richtek,fsin-enable", 0, 0, 1, 1, RTMV20_REG_ENCTRL, RTMV20_FSINEN_MASK },
+ { "richtek,fsin-output", 0, 0, 1, 1, RTMV20_REG_ENCTRL, RTMV20_FSINOUT_MASK },
+ { "richtek,es-enable", 0, 0, 1, 1, RTMV20_REG_ENCTRL, RTMV20_ESEN_MASK },
+ };
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(props); i++) {
+ __be16 bval16;
+ u16 val16;
+ u32 temp;
+ int significant_bit = fls(props[i].mask);
+ int shift = ffs(props[i].mask) - 1;
+
+ if (props[i].max > 1) {
+ ret = device_property_read_u32(priv->dev, props[i].name, &temp);
+ if (ret)
+ temp = props[i].def;
+ } else
+ temp = device_property_read_bool(priv->dev, props[i].name);
+
+ temp = clamp_to_selector(temp, props[i].min, props[i].max, props[i].step);
+
+ /* If significant bit is over 8, two byte access, others one */
+ if (significant_bit > 8) {
+ ret = regmap_raw_read(priv->regmap, props[i].addr, &bval16, sizeof(bval16));
+ if (ret)
+ return ret;
+
+ val16 = be16_to_cpu(bval16);
+ val16 &= ~props[i].mask;
+ val16 |= (temp << shift);
+ bval16 = cpu_to_be16(val16);
+
+ ret = regmap_raw_write(priv->regmap, props[i].addr, &bval16,
+ sizeof(bval16));
+ } else {
+ ret = regmap_update_bits(priv->regmap, props[i].addr, props[i].mask,
+ temp << shift);
+ }
+
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rtmv20_check_chip_exist(struct rtmv20_priv *priv)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(priv->regmap, RTMV20_REG_DEVINFO, &val);
+ if (ret)
+ return ret;
+
+ if ((val & RTMV20_VID_MASK) != RICHTEK_VID)
+ return -ENODEV;
+
+ return 0;
+}
+
+static bool rtmv20_is_accessible_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case RTMV20_REG_DEVINFO ... RTMV20_REG_STRBVSYNDLYL:
+ case RTMV20_REG_LDIRQ:
+ case RTMV20_REG_LDSTAT:
+ case RTMV20_REG_LDMASK:
+ return true;
+ }
+ return false;
+}
+
+static bool rtmv20_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ if (reg == RTMV20_REG_LDIRQ || reg == RTMV20_REG_LDSTAT)
+ return true;
+ return false;
+}
+
+static const struct regmap_config rtmv20_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .cache_type = REGCACHE_RBTREE,
+ .max_register = RTMV20_REG_LDMASK,
+ .num_reg_defaults_raw = RTMV20_MAX_REGS,
+
+ .writeable_reg = rtmv20_is_accessible_reg,
+ .readable_reg = rtmv20_is_accessible_reg,
+ .volatile_reg = rtmv20_is_volatile_reg,
+};
+
+static int rtmv20_probe(struct i2c_client *i2c)
+{
+ struct rtmv20_priv *priv;
+ struct regulator_config config = {};
+ int ret;
+
+ priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = &i2c->dev;
+
+ /* Before regmap register, configure HW enable to make I2C accessible */
+ priv->enable_gpio = devm_gpiod_get(&i2c->dev, "enable", GPIOD_OUT_HIGH);
+ if (IS_ERR(priv->enable_gpio)) {
+ dev_err(&i2c->dev, "Failed to get enable gpio\n");
+ return PTR_ERR(priv->enable_gpio);
+ }
+
+ /* Wait for I2C can be accessed */
+ usleep_range(RTMV20_I2CRDY_TIMEUS, RTMV20_I2CRDY_TIMEUS + 100);
+
+ priv->regmap = devm_regmap_init_i2c(i2c, &rtmv20_regmap_config);
+ if (IS_ERR(priv->regmap)) {
+ dev_err(&i2c->dev, "Failed to allocate register map\n");
+ return PTR_ERR(priv->regmap);
+ }
+
+ ret = rtmv20_check_chip_exist(priv);
+ if (ret) {
+ dev_err(&i2c->dev, "Chip vendor info is not matched\n");
+ return ret;
+ }
+
+ ret = rtmv20_properties_init(priv);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to init properties\n");
+ return ret;
+ }
+
+ /*
+ * keep in shutdown mode to minimize the current consumption
+ * and also mark regcache as dirty
+ */
+ regcache_cache_only(priv->regmap, true);
+ regcache_mark_dirty(priv->regmap);
+ gpiod_set_value(priv->enable_gpio, 0);
+
+ config.dev = &i2c->dev;
+ config.regmap = priv->regmap;
+ config.driver_data = priv;
+ priv->rdev = devm_regulator_register(&i2c->dev, &rtmv20_lsw_desc, &config);
+ if (IS_ERR(priv->rdev)) {
+ dev_err(&i2c->dev, "Failed to register regulator\n");
+ return PTR_ERR(priv->rdev);
+ }
+
+ /* Unmask all events before IRQ registered */
+ ret = regmap_write(priv->regmap, RTMV20_REG_LDMASK, 0);
+ if (ret)
+ return ret;
+
+ return devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, rtmv20_irq_handler,
+ IRQF_ONESHOT, dev_name(&i2c->dev), priv);
+}
+
+static int __maybe_unused rtmv20_suspend(struct device *dev)
+{
+ struct i2c_client *i2c = to_i2c_client(dev);
+
+ /*
+ * When system suspend, disable irq to prevent interrupt trigger
+ * during I2C bus suspend
+ */
+ disable_irq(i2c->irq);
+ if (device_may_wakeup(dev))
+ enable_irq_wake(i2c->irq);
+
+ return 0;
+}
+
+static int __maybe_unused rtmv20_resume(struct device *dev)
+{
+ struct i2c_client *i2c = to_i2c_client(dev);
+
+ /* Enable irq after I2C bus already resume */
+ enable_irq(i2c->irq);
+ if (device_may_wakeup(dev))
+ disable_irq_wake(i2c->irq);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(rtmv20_pm, rtmv20_suspend, rtmv20_resume);
+
+static const struct of_device_id __maybe_unused rtmv20_of_id[] = {
+ { .compatible = "richtek,rtmv20", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, rtmv20_of_id);
+
+static struct i2c_driver rtmv20_driver = {
+ .driver = {
+ .name = "rtmv20",
+ .of_match_table = of_match_ptr(rtmv20_of_id),
+ .pm = &rtmv20_pm,
+ },
+ .probe_new = rtmv20_probe,
+};
+module_i2c_driver(rtmv20_driver);
+
+MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
+MODULE_DESCRIPTION("Richtek RTMV20 Regulator Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c
index 51f7e8b..115f595 100644
--- a/drivers/regulator/s2mpa01.c
+++ b/drivers/regulator/s2mpa01.c
@@ -390,5 +390,5 @@
/* Module information */
MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
MODULE_AUTHOR("Sachin Kamat <sachin.kamat@samsung.com>");
-MODULE_DESCRIPTION("SAMSUNG S2MPA01 Regulator Driver");
+MODULE_DESCRIPTION("Samsung S2MPA01 Regulator Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 5bc0088..33cf84b 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -749,37 +749,37 @@
}
/* voltage range for s2mps15 LDO 3, 5, 15, 16, 18, 20, 23 and 27 */
-static const struct regulator_linear_range s2mps15_ldo_voltage_ranges1[] = {
+static const struct linear_range s2mps15_ldo_voltage_ranges1[] = {
REGULATOR_LINEAR_RANGE(1000000, 0xc, 0x38, 25000),
};
/* voltage range for s2mps15 LDO 2, 6, 14, 17, 19, 21, 24 and 25 */
-static const struct regulator_linear_range s2mps15_ldo_voltage_ranges2[] = {
+static const struct linear_range s2mps15_ldo_voltage_ranges2[] = {
REGULATOR_LINEAR_RANGE(1800000, 0x0, 0x3f, 25000),
};
/* voltage range for s2mps15 LDO 4, 11, 12, 13, 22 and 26 */
-static const struct regulator_linear_range s2mps15_ldo_voltage_ranges3[] = {
+static const struct linear_range s2mps15_ldo_voltage_ranges3[] = {
REGULATOR_LINEAR_RANGE(700000, 0x0, 0x34, 12500),
};
/* voltage range for s2mps15 LDO 7, 8, 9 and 10 */
-static const struct regulator_linear_range s2mps15_ldo_voltage_ranges4[] = {
+static const struct linear_range s2mps15_ldo_voltage_ranges4[] = {
REGULATOR_LINEAR_RANGE(700000, 0x10, 0x20, 25000),
};
/* voltage range for s2mps15 LDO 1 */
-static const struct regulator_linear_range s2mps15_ldo_voltage_ranges5[] = {
+static const struct linear_range s2mps15_ldo_voltage_ranges5[] = {
REGULATOR_LINEAR_RANGE(500000, 0x0, 0x20, 12500),
};
/* voltage range for s2mps15 BUCK 1, 2, 3, 4, 5, 6 and 7 */
-static const struct regulator_linear_range s2mps15_buck_voltage_ranges1[] = {
+static const struct linear_range s2mps15_buck_voltage_ranges1[] = {
REGULATOR_LINEAR_RANGE(500000, 0x20, 0xc0, 6250),
};
/* voltage range for s2mps15 BUCK 8, 9 and 10 */
-static const struct regulator_linear_range s2mps15_buck_voltage_ranges2[] = {
+static const struct linear_range s2mps15_buck_voltage_ranges2[] = {
REGULATOR_LINEAR_RANGE(1000000, 0x20, 0x78, 12500),
};
@@ -844,10 +844,9 @@
if (!rdata[reg].init_data || !rdata[reg].of_node)
continue;
- gpio[reg] = devm_gpiod_get_from_of_node(&pdev->dev,
- rdata[reg].of_node,
- "samsung,ext-control-gpios",
- 0,
+ gpio[reg] = devm_fwnode_gpiod_get(&pdev->dev,
+ of_fwnode_handle(rdata[reg].of_node),
+ "samsung,ext-control",
GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"s2mps11-regulator");
if (PTR_ERR(gpio[reg]) == -ENOENT)
@@ -1266,5 +1265,5 @@
/* Module information */
MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
-MODULE_DESCRIPTION("SAMSUNG S2MPS11/S2MPS14/S2MPS15/S2MPU02 Regulator Driver");
+MODULE_DESCRIPTION("Samsung S2MPS11/S2MPS14/S2MPS15/S2MPU02 Regulator Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index 5276f84..35269f9 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -571,11 +571,10 @@
continue;
}
- rdata->ext_control_gpiod = devm_gpiod_get_from_of_node(
+ rdata->ext_control_gpiod = devm_fwnode_gpiod_get(
&pdev->dev,
- reg_np,
- "s5m8767,pmic-ext-control-gpios",
- 0,
+ of_fwnode_handle(reg_np),
+ "s5m8767,pmic-ext-control",
GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"s5m8767");
if (PTR_ERR(rdata->ext_control_gpiod) == -ENOENT) {
@@ -596,7 +595,7 @@
if (of_property_read_u32(reg_np, "op_mode",
&rmode->mode)) {
dev_warn(iodev->dev,
- "no op_mode property property at %pOF\n",
+ "no op_mode property at %pOF\n",
reg_np);
rmode->mode = S5M8767_OPMODE_NORMAL_MODE;
@@ -851,18 +850,15 @@
/* DS4 GPIO */
gpio_direction_output(pdata->buck_ds[2], 0x0);
- if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
- pdata->buck4_gpiodvs) {
- regmap_update_bits(s5m8767->iodev->regmap_pmic,
- S5M8767_REG_BUCK2CTRL, 1 << 1,
- (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1));
- regmap_update_bits(s5m8767->iodev->regmap_pmic,
- S5M8767_REG_BUCK3CTRL, 1 << 1,
- (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1));
- regmap_update_bits(s5m8767->iodev->regmap_pmic,
- S5M8767_REG_BUCK4CTRL, 1 << 1,
- (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1));
- }
+ regmap_update_bits(s5m8767->iodev->regmap_pmic,
+ S5M8767_REG_BUCK2CTRL, 1 << 1,
+ (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1));
+ regmap_update_bits(s5m8767->iodev->regmap_pmic,
+ S5M8767_REG_BUCK3CTRL, 1 << 1,
+ (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1));
+ regmap_update_bits(s5m8767->iodev->regmap_pmic,
+ S5M8767_REG_BUCK4CTRL, 1 << 1,
+ (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1));
/* Initialize GPIO DVS registers */
for (i = 0; i < 8; i++) {
@@ -1008,20 +1004,9 @@
.probe = s5m8767_pmic_probe,
.id_table = s5m8767_pmic_id,
};
-
-static int __init s5m8767_pmic_init(void)
-{
- return platform_driver_register(&s5m8767_pmic_driver);
-}
-subsys_initcall(s5m8767_pmic_init);
-
-static void __exit s5m8767_pmic_exit(void)
-{
- platform_driver_unregister(&s5m8767_pmic_driver);
-}
-module_exit(s5m8767_pmic_exit);
+module_platform_driver(s5m8767_pmic_driver);
/* Module information */
MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
-MODULE_DESCRIPTION("SAMSUNG S5M8767 Regulator Driver");
+MODULE_DESCRIPTION("Samsung S5M8767 Regulator Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/sky81452-regulator.c b/drivers/regulator/sky81452-regulator.c
index 177dede..37658af 100644
--- a/drivers/regulator/sky81452-regulator.c
+++ b/drivers/regulator/sky81452-regulator.c
@@ -32,7 +32,7 @@
.is_enabled = regulator_is_enabled_regmap,
};
-static const struct regulator_linear_range sky81452_reg_ranges[] = {
+static const struct linear_range sky81452_reg_ranges[] = {
REGULATOR_LINEAR_RANGE(4500000, 0, 14, 250000),
REGULATOR_LINEAR_RANGE(9000000, 15, 31, 1000000),
};
diff --git a/drivers/regulator/slg51000-regulator.c b/drivers/regulator/slg51000-regulator.c
index a0565da..75a941f 100644
--- a/drivers/regulator/slg51000-regulator.c
+++ b/drivers/regulator/slg51000-regulator.c
@@ -198,17 +198,14 @@
const struct regulator_desc *desc,
struct regulator_config *config)
{
- struct slg51000 *chip = config->driver_data;
struct gpio_desc *ena_gpiod;
- enum gpiod_flags gflags = GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE;
- ena_gpiod = devm_gpiod_get_from_of_node(chip->dev, np,
- "enable-gpios", 0,
- gflags, "gpio-en-ldo");
- if (!IS_ERR(ena_gpiod)) {
+ ena_gpiod = fwnode_gpiod_get_index(of_fwnode_handle(np), "enable", 0,
+ GPIOD_OUT_LOW |
+ GPIOD_FLAGS_BIT_NONEXCLUSIVE,
+ "gpio-en-ldo");
+ if (!IS_ERR(ena_gpiod))
config->ena_gpiod = ena_gpiod;
- devm_gpiod_unhinge(chip->dev, config->ena_gpiod);
- }
return 0;
}
@@ -322,7 +319,7 @@
rdesc->linear_min_sel = 0;
break;
}
- /* Fall through - to the check below.*/
+ fallthrough; /* to the check below */
default:
rdesc->linear_min_sel = vsel_range[0];
@@ -389,10 +386,8 @@
for (i = 0; i < SLG51000_MAX_REGULATORS; i++) {
if (!(evt[i][R2] & SLG51000_IRQ_ILIM_FLAG_MASK) &&
(evt[i][R0] & SLG51000_EVT_ILIM_FLAG_MASK)) {
- regulator_lock(chip->rdev[i]);
regulator_notifier_call_chain(chip->rdev[i],
REGULATOR_EVENT_OVER_CURRENT, NULL);
- regulator_unlock(chip->rdev[i]);
if (evt[i][R1] & SLG51000_STA_ILIM_FLAG_MASK)
dev_warn(chip->dev,
@@ -406,10 +401,8 @@
for (i = 0; i < SLG51000_MAX_REGULATORS; i++) {
if (!(evt[i][R1] & SLG51000_STA_ILIM_FLAG_MASK) &&
(evt[i][R1] & SLG51000_STA_VOUT_OK_FLAG_MASK)) {
- regulator_lock(chip->rdev[i]);
regulator_notifier_call_chain(chip->rdev[i],
REGULATOR_EVENT_OVER_TEMP, NULL);
- regulator_unlock(chip->rdev[i]);
}
}
handled = IRQ_HANDLED;
@@ -442,8 +435,7 @@
dev_dbg(chip->dev, "Fault log: FLT_POR\n");
}
-static int slg51000_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int slg51000_i2c_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct slg51000 *chip;
@@ -512,7 +504,7 @@
.driver = {
.name = "slg51000-regulator",
},
- .probe = slg51000_i2c_probe,
+ .probe_new = slg51000_i2c_probe,
.id_table = slg51000_i2c_id,
};
diff --git a/drivers/regulator/stm32-booster.c b/drivers/regulator/stm32-booster.c
index 03f162f..3136ea8 100644
--- a/drivers/regulator/stm32-booster.c
+++ b/drivers/regulator/stm32-booster.c
@@ -101,7 +101,7 @@
return 0;
}
-static const struct of_device_id stm32_booster_of_match[] = {
+static const struct of_device_id __maybe_unused stm32_booster_of_match[] = {
{
.compatible = "st,stm32h7-booster",
.data = (void *)&stm32h7_booster_desc
diff --git a/drivers/regulator/stm32-pwr.c b/drivers/regulator/stm32-pwr.c
index e0e627b..2a42acb 100644
--- a/drivers/regulator/stm32-pwr.c
+++ b/drivers/regulator/stm32-pwr.c
@@ -166,7 +166,7 @@
return ret;
}
-static const struct of_device_id stm32_pwr_of_match[] = {
+static const struct of_device_id __maybe_unused stm32_pwr_of_match[] = {
{ .compatible = "st,stm32mp1,pwr-reg", },
{},
};
diff --git a/drivers/regulator/stm32-vrefbuf.c b/drivers/regulator/stm32-vrefbuf.c
index 25f24df..161622e 100644
--- a/drivers/regulator/stm32-vrefbuf.c
+++ b/drivers/regulator/stm32-vrefbuf.c
@@ -182,7 +182,6 @@
static int stm32_vrefbuf_probe(struct platform_device *pdev)
{
- struct resource *res;
struct stm32_vrefbuf *priv;
struct regulator_config config = { };
struct regulator_dev *rdev;
@@ -193,8 +192,7 @@
return -ENOMEM;
priv->dev = &pdev->dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->base = devm_ioremap_resource(&pdev->dev, res);
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
@@ -286,7 +284,7 @@
NULL)
};
-static const struct of_device_id stm32_vrefbuf_of_match[] = {
+static const struct of_device_id __maybe_unused stm32_vrefbuf_of_match[] = {
{ .compatible = "st,stm32-vrefbuf", },
{},
};
diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c
index f090614..cf10fdb 100644
--- a/drivers/regulator/stpmic1_regulator.c
+++ b/drivers/regulator/stpmic1_regulator.c
@@ -15,7 +15,7 @@
#include <dt-bindings/mfd/st,stpmic1.h>
/**
- * stpmic1 regulator description: this structure is used as driver data
+ * struct stpmic1 regulator description: this structure is used as driver data
* @desc: regulator framework description
* @mask_reset_reg: mask reset register address
* @mask_reset_mask: mask rank and mask reset register mask
@@ -54,14 +54,16 @@
/* Enable time worst case is 5000mV/(2250uV/uS) */
#define PMIC_ENABLE_TIME_US 2200
+/* Ramp delay worst case is (2250uV/uS) */
+#define PMIC_RAMP_DELAY 2200
-static const struct regulator_linear_range buck1_ranges[] = {
+static const struct linear_range buck1_ranges[] = {
REGULATOR_LINEAR_RANGE(725000, 0, 4, 0),
REGULATOR_LINEAR_RANGE(725000, 5, 36, 25000),
REGULATOR_LINEAR_RANGE(1500000, 37, 63, 0),
};
-static const struct regulator_linear_range buck2_ranges[] = {
+static const struct linear_range buck2_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 17, 0),
REGULATOR_LINEAR_RANGE(1050000, 18, 19, 0),
REGULATOR_LINEAR_RANGE(1100000, 20, 21, 0),
@@ -75,7 +77,7 @@
REGULATOR_LINEAR_RANGE(1500000, 36, 63, 0),
};
-static const struct regulator_linear_range buck3_ranges[] = {
+static const struct linear_range buck3_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 19, 0),
REGULATOR_LINEAR_RANGE(1100000, 20, 23, 0),
REGULATOR_LINEAR_RANGE(1200000, 24, 27, 0),
@@ -85,7 +87,7 @@
REGULATOR_LINEAR_RANGE(3400000, 56, 63, 0),
};
-static const struct regulator_linear_range buck4_ranges[] = {
+static const struct linear_range buck4_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 27, 25000),
REGULATOR_LINEAR_RANGE(1300000, 28, 29, 0),
REGULATOR_LINEAR_RANGE(1350000, 30, 31, 0),
@@ -95,19 +97,19 @@
REGULATOR_LINEAR_RANGE(3900000, 61, 63, 0),
};
-static const struct regulator_linear_range ldo1_ranges[] = {
+static const struct linear_range ldo1_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
};
-static const struct regulator_linear_range ldo2_ranges[] = {
+static const struct linear_range ldo2_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0),
};
-static const struct regulator_linear_range ldo3_ranges[] = {
+static const struct linear_range ldo3_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0),
@@ -115,13 +117,13 @@
REGULATOR_LINEAR_RANGE(500000, 31, 31, 0),
};
-static const struct regulator_linear_range ldo5_ranges[] = {
+static const struct linear_range ldo5_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 30, 100000),
REGULATOR_LINEAR_RANGE(3900000, 31, 31, 0),
};
-static const struct regulator_linear_range ldo6_ranges[] = {
+static const struct linear_range ldo6_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
};
@@ -208,6 +210,7 @@
.enable_val = 1, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
+ .ramp_delay = PMIC_RAMP_DELAY, \
.supply_name = #base, \
}
@@ -227,6 +230,7 @@
.enable_val = 1, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
+ .ramp_delay = PMIC_RAMP_DELAY, \
.bypass_reg = LDO3_ACTIVE_CR, \
.bypass_mask = LDO_BYPASS_MASK, \
.bypass_val_on = LDO_BYPASS_MASK, \
@@ -248,6 +252,7 @@
.enable_val = 1, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
+ .ramp_delay = PMIC_RAMP_DELAY, \
.supply_name = #base, \
}
@@ -267,6 +272,7 @@
.enable_val = 1, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
+ .ramp_delay = PMIC_RAMP_DELAY, \
.of_map_mode = stpmic1_map_mode, \
.pull_down_reg = ids##_PULL_DOWN_REG, \
.pull_down_mask = ids##_PULL_DOWN_MASK, \
@@ -499,15 +505,11 @@
{
struct regulator_dev *rdev = (struct regulator_dev *)data;
- regulator_lock(rdev);
-
/* Send an overcurrent notification */
regulator_notifier_call_chain(rdev,
REGULATOR_EVENT_OVER_CURRENT,
NULL);
- regulator_unlock(rdev);
-
return IRQ_HANDLED;
}
diff --git a/drivers/regulator/stw481x-vmmc.c b/drivers/regulator/stw481x-vmmc.c
index 6dc2316..127ab43 100644
--- a/drivers/regulator/stw481x-vmmc.c
+++ b/drivers/regulator/stw481x-vmmc.c
@@ -27,7 +27,7 @@
3300000,
};
-static struct regulator_ops stw481x_vmmc_ops = {
+static const struct regulator_ops stw481x_vmmc_ops = {
.list_voltage = regulator_list_voltage_table,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -36,7 +36,7 @@
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};
-static struct regulator_desc vmmc_regulator = {
+static const struct regulator_desc vmmc_regulator = {
.name = "VMMC",
.id = 0,
.ops = &stw481x_vmmc_ops,
diff --git a/drivers/regulator/sy8106a-regulator.c b/drivers/regulator/sy8106a-regulator.c
index 42e03b2..c119f85 100644
--- a/drivers/regulator/sy8106a-regulator.c
+++ b/drivers/regulator/sy8106a-regulator.c
@@ -61,8 +61,7 @@
/*
* I2C driver interface functions
*/
-static int sy8106a_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int sy8106a_i2c_probe(struct i2c_client *i2c)
{
struct device *dev = &i2c->dev;
struct regulator_dev *rdev;
@@ -124,7 +123,7 @@
return 0;
}
-static const struct of_device_id sy8106a_i2c_of_match[] = {
+static const struct of_device_id __maybe_unused sy8106a_i2c_of_match[] = {
{ .compatible = "silergy,sy8106a" },
{ },
};
@@ -141,7 +140,7 @@
.name = "sy8106a",
.of_match_table = of_match_ptr(sy8106a_i2c_of_match),
},
- .probe = sy8106a_i2c_probe,
+ .probe_new = sy8106a_i2c_probe,
.id_table = sy8106a_i2c_id,
};
diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c
index 92adb4f..62d243f 100644
--- a/drivers/regulator/sy8824x.c
+++ b/drivers/regulator/sy8824x.c
@@ -112,8 +112,7 @@
.val_bits = 8,
};
-static int sy8824_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int sy8824_i2c_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct device_node *np = dev->of_node;
@@ -222,7 +221,7 @@
.name = "sy8824-regulator",
.of_match_table = of_match_ptr(sy8824_dt_ids),
},
- .probe = sy8824_i2c_probe,
+ .probe_new = sy8824_i2c_probe,
.id_table = sy8824_id,
};
module_i2c_driver(sy8824_regulator_driver);
diff --git a/drivers/regulator/sy8827n.c b/drivers/regulator/sy8827n.c
new file mode 100644
index 0000000..52e8c17
--- /dev/null
+++ b/drivers/regulator/sy8827n.c
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// SY8827N regulator driver
+//
+// Copyright (C) 2020 Synaptics Incorporated
+//
+// Author: Jisheng Zhang <jszhang@kernel.org>
+
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+#define SY8827N_VSEL0 0
+#define SY8827N_BUCK_EN (1 << 7)
+#define SY8827N_MODE (1 << 6)
+#define SY8827N_VSEL1 1
+#define SY8827N_CTRL 2
+
+#define SY8827N_NVOLTAGES 64
+#define SY8827N_VSELMIN 600000
+#define SY8827N_VSELSTEP 12500
+
+struct sy8827n_device_info {
+ struct device *dev;
+ struct regulator_desc desc;
+ struct regulator_init_data *regulator;
+ struct gpio_desc *en_gpio;
+ unsigned int vsel_reg;
+};
+
+static int sy8827n_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ struct sy8827n_device_info *di = rdev_get_drvdata(rdev);
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ regmap_update_bits(rdev->regmap, di->vsel_reg,
+ SY8827N_MODE, SY8827N_MODE);
+ break;
+ case REGULATOR_MODE_NORMAL:
+ regmap_update_bits(rdev->regmap, di->vsel_reg,
+ SY8827N_MODE, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static unsigned int sy8827n_get_mode(struct regulator_dev *rdev)
+{
+ struct sy8827n_device_info *di = rdev_get_drvdata(rdev);
+ u32 val;
+ int ret = 0;
+
+ ret = regmap_read(rdev->regmap, di->vsel_reg, &val);
+ if (ret < 0)
+ return ret;
+ if (val & SY8827N_MODE)
+ return REGULATOR_MODE_FAST;
+ else
+ return REGULATOR_MODE_NORMAL;
+}
+
+static const struct regulator_ops sy8827n_regulator_ops = {
+ .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,
+ .map_voltage = regulator_map_voltage_linear,
+ .list_voltage = regulator_list_voltage_linear,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = sy8827n_set_mode,
+ .get_mode = sy8827n_get_mode,
+};
+
+static int sy8827n_regulator_register(struct sy8827n_device_info *di,
+ struct regulator_config *config)
+{
+ struct regulator_desc *rdesc = &di->desc;
+ struct regulator_dev *rdev;
+
+ rdesc->name = "sy8827n-reg";
+ rdesc->supply_name = "vin";
+ rdesc->ops = &sy8827n_regulator_ops;
+ rdesc->type = REGULATOR_VOLTAGE;
+ rdesc->n_voltages = SY8827N_NVOLTAGES;
+ rdesc->enable_reg = di->vsel_reg;
+ rdesc->enable_mask = SY8827N_BUCK_EN;
+ rdesc->min_uV = SY8827N_VSELMIN;
+ rdesc->uV_step = SY8827N_VSELSTEP;
+ rdesc->vsel_reg = di->vsel_reg;
+ rdesc->vsel_mask = rdesc->n_voltages - 1;
+ rdesc->owner = THIS_MODULE;
+
+ rdev = devm_regulator_register(di->dev, &di->desc, config);
+ return PTR_ERR_OR_ZERO(rdev);
+}
+
+static const struct regmap_config sy8827n_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int sy8827n_i2c_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct device_node *np = dev->of_node;
+ struct sy8827n_device_info *di;
+ struct regulator_config config = { };
+ struct regmap *regmap;
+ int ret;
+
+ di = devm_kzalloc(dev, sizeof(struct sy8827n_device_info), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+
+ di->regulator = of_get_regulator_init_data(dev, np, &di->desc);
+ if (!di->regulator) {
+ dev_err(dev, "Platform data not found!\n");
+ return -EINVAL;
+ }
+
+ di->en_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH);
+ if (IS_ERR(di->en_gpio))
+ return PTR_ERR(di->en_gpio);
+
+ if (of_property_read_bool(np, "silergy,vsel-state-high"))
+ di->vsel_reg = SY8827N_VSEL1;
+ else
+ di->vsel_reg = SY8827N_VSEL0;
+
+ di->dev = dev;
+
+ regmap = devm_regmap_init_i2c(client, &sy8827n_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "Failed to allocate regmap!\n");
+ return PTR_ERR(regmap);
+ }
+ i2c_set_clientdata(client, di);
+
+ config.dev = di->dev;
+ config.init_data = di->regulator;
+ config.regmap = regmap;
+ config.driver_data = di;
+ config.of_node = np;
+
+ ret = sy8827n_regulator_register(di, &config);
+ if (ret < 0)
+ dev_err(dev, "Failed to register regulator!\n");
+ return ret;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id sy8827n_dt_ids[] = {
+ {
+ .compatible = "silergy,sy8827n",
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sy8827n_dt_ids);
+#endif
+
+static const struct i2c_device_id sy8827n_id[] = {
+ { "sy8827n", },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, sy8827n_id);
+
+static struct i2c_driver sy8827n_regulator_driver = {
+ .driver = {
+ .name = "sy8827n-regulator",
+ .of_match_table = of_match_ptr(sy8827n_dt_ids),
+ },
+ .probe_new = sy8827n_i2c_probe,
+ .id_table = sy8827n_id,
+};
+module_i2c_driver(sy8827n_regulator_driver);
+
+MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
+MODULE_DESCRIPTION("SY8827N regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c
index 016330f..9f0a4d5 100644
--- a/drivers/regulator/ti-abb-regulator.c
+++ b/drivers/regulator/ti-abb-regulator.c
@@ -629,7 +629,7 @@
return 0;
}
-static struct regulator_ops ti_abb_reg_ops = {
+static const struct regulator_ops ti_abb_reg_ops = {
.list_voltage = regulator_list_voltage_table,
.set_voltage_sel = ti_abb_set_voltage_sel,
@@ -758,7 +758,7 @@
* We may have shared interrupt register offsets which are
* write-1-to-clear between domains ensuring exclusivity.
*/
- abb->int_base = devm_ioremap_nocache(dev, res->start,
+ abb->int_base = devm_ioremap(dev, res->start,
resource_size(res));
if (!abb->int_base) {
dev_err(dev, "Unable to map '%s'\n", pname);
@@ -778,7 +778,7 @@
* We may have shared efuse register offsets which are read-only
* between domains
*/
- abb->efuse_base = devm_ioremap_nocache(dev, res->start,
+ abb->efuse_base = devm_ioremap(dev, res->start,
resource_size(res));
if (!abb->efuse_base) {
dev_err(dev, "Unable to map '%s'\n", pname);
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
index c139890..a15e415 100644
--- a/drivers/regulator/tps51632-regulator.c
+++ b/drivers/regulator/tps51632-regulator.c
@@ -108,7 +108,7 @@
return ret;
}
-static struct regulator_ops tps51632_dcdc_ops = {
+static const struct regulator_ops tps51632_dcdc_ops = {
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c
index 06059a9..a6469fe 100644
--- a/drivers/regulator/tps6105x-regulator.c
+++ b/drivers/regulator/tps6105x-regulator.c
@@ -26,7 +26,7 @@
5000000, /* There is an additional 5V */
};
-static struct regulator_ops tps6105x_regulator_ops = {
+static const struct regulator_ops tps6105x_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -37,6 +37,7 @@
static const struct regulator_desc tps6105x_regulator_desc = {
.name = "tps6105x-boost",
+ .of_match = of_match_ptr("regulator"),
.ops = &tps6105x_regulator_ops,
.type = REGULATOR_VOLTAGE,
.id = 0,
@@ -71,6 +72,7 @@
config.dev = &tps6105x->client->dev;
config.init_data = pdata->regulator_data;
config.driver_data = tps6105x;
+ config.of_node = pdev->dev.parent->of_node;
config.regmap = tps6105x->regmap;
/* Register regulator with framework */
diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c
index f6a6d36..315cd5d 100644
--- a/drivers/regulator/tps62360-regulator.c
+++ b/drivers/regulator/tps62360-regulator.c
@@ -233,7 +233,7 @@
REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
}
-static struct regulator_ops tps62360_dcdc_ops = {
+static const struct regulator_ops tps62360_dcdc_ops = {
.get_voltage_sel = tps62360_dcdc_get_voltage_sel,
.set_voltage_sel = tps62360_dcdc_set_voltage_sel,
.list_voltage = regulator_list_voltage_linear,
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index 5ca6d21..f258065 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -3,7 +3,7 @@
*
* Supports TPS65023 Regulator
*
- * Copyright (C) 2009 Texas Instrument Incorporated - http://www.ti.com/
+ * Copyright (C) 2009 Texas Instrument Incorporated - https://www.ti.com/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -316,7 +316,7 @@
return 0;
}
-static const struct of_device_id tps65023_of_match[] = {
+static const struct of_device_id __maybe_unused tps65023_of_match[] = {
{ .compatible = "ti,tps65020", .data = &tps65020_drv_data},
{ .compatible = "ti,tps65021", .data = &tps65021_drv_data},
{ .compatible = "ti,tps65023", .data = &tps65023_drv_data},
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
index d2a8f69..eafbc2b 100644
--- a/drivers/regulator/tps6507x-regulator.c
+++ b/drivers/regulator/tps6507x-regulator.c
@@ -3,7 +3,7 @@
*
* Regulator driver for TPS65073 PMIC
*
- * Copyright (C) 2009 Texas Instrument Incorporated - http://www.ti.com/
+ * Copyright (C) 2009 Texas Instrument Incorporated - https://www.ti.com/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
diff --git a/drivers/regulator/tps65086-regulator.c b/drivers/regulator/tps65086-regulator.c
index 5a5e9b5..070c956 100644
--- a/drivers/regulator/tps65086-regulator.c
+++ b/drivers/regulator/tps65086-regulator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
*
* Author: Andrew F. Davis <afd@ti.com>
*
@@ -71,23 +71,23 @@
unsigned int decay_mask;
};
-static const struct regulator_linear_range tps65086_10mv_ranges[] = {
+static const struct linear_range tps65086_10mv_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(410000, 0x1, 0x7F, 10000),
};
-static const struct regulator_linear_range tps65086_buck126_25mv_ranges[] = {
+static const struct linear_range tps65086_buck126_25mv_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(1000000, 0x1, 0x18, 0),
REGULATOR_LINEAR_RANGE(1025000, 0x19, 0x7F, 25000),
};
-static const struct regulator_linear_range tps65086_buck345_25mv_ranges[] = {
+static const struct linear_range tps65086_buck345_25mv_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(425000, 0x1, 0x7F, 25000),
};
-static const struct regulator_linear_range tps65086_ldoa1_ranges[] = {
+static const struct linear_range tps65086_ldoa1_ranges[] = {
REGULATOR_LINEAR_RANGE(1350000, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(1500000, 0x1, 0x7, 100000),
REGULATOR_LINEAR_RANGE(2300000, 0x8, 0xB, 100000),
@@ -95,13 +95,13 @@
REGULATOR_LINEAR_RANGE(3300000, 0xE, 0xE, 0),
};
-static const struct regulator_linear_range tps65086_ldoa23_ranges[] = {
+static const struct linear_range tps65086_ldoa23_ranges[] = {
REGULATOR_LINEAR_RANGE(700000, 0x0, 0xD, 50000),
REGULATOR_LINEAR_RANGE(1400000, 0xE, 0xF, 100000),
};
/* Operations permitted on regulators */
-static struct regulator_ops reg_ops = {
+static const struct regulator_ops reg_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -112,7 +112,7 @@
};
/* Operations permitted on load switches */
-static struct regulator_ops switch_ops = {
+static const struct regulator_ops switch_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
index 10ea4b5..1d2e04f 100644
--- a/drivers/regulator/tps65090-regulator.c
+++ b/drivers/regulator/tps65090-regulator.c
@@ -47,7 +47,7 @@
int overcurrent_wait;
};
-static struct regulator_ops tps65090_ext_control_ops = {
+static const struct regulator_ops tps65090_ext_control_ops = {
};
/**
@@ -167,19 +167,19 @@
return ret;
}
-static struct regulator_ops tps65090_reg_control_ops = {
+static const struct regulator_ops tps65090_reg_control_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
-static struct regulator_ops tps65090_fet_control_ops = {
+static const struct regulator_ops tps65090_fet_control_ops = {
.enable = tps65090_fet_enable,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
-static struct regulator_ops tps65090_ldo_ops = {
+static const struct regulator_ops tps65090_ldo_ops = {
};
#define tps65090_REG_DESC(_id, _sname, _en_reg, _en_bits, _nvolt, _volt, _ops) \
@@ -346,16 +346,20 @@
for (idx = 0; idx < ARRAY_SIZE(tps65090_matches); idx++) {
struct regulator_init_data *ri_data;
struct tps65090_regulator_plat_data *rpdata;
+ struct device_node *np;
rpdata = ®_pdata[idx];
ri_data = tps65090_matches[idx].init_data;
- if (!ri_data || !tps65090_matches[idx].of_node)
+ if (!ri_data)
+ continue;
+
+ np = tps65090_matches[idx].of_node;
+ if (!np)
continue;
rpdata->reg_init_data = ri_data;
- rpdata->enable_ext_control = of_property_read_bool(
- tps65090_matches[idx].of_node,
- "ti,enable-ext-control");
+ rpdata->enable_ext_control = of_property_read_bool(np,
+ "ti,enable-ext-control");
if (rpdata->enable_ext_control) {
enum gpiod_flags gflags;
@@ -366,11 +370,12 @@
gflags = GPIOD_OUT_LOW;
gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE;
- rpdata->gpiod = devm_gpiod_get_from_of_node(&pdev->dev,
- tps65090_matches[idx].of_node,
- "dcdc-ext-control-gpios", 0,
- gflags,
- "tps65090");
+ rpdata->gpiod = devm_fwnode_gpiod_get(
+ &pdev->dev,
+ of_fwnode_handle(np),
+ "dcdc-ext-control",
+ gflags,
+ "tps65090");
if (PTR_ERR(rpdata->gpiod) == -ENOENT) {
dev_err(&pdev->dev,
"could not find DCDC external control GPIO\n");
@@ -379,8 +384,7 @@
return ERR_CAST(rpdata->gpiod);
}
- if (of_property_read_u32(tps65090_matches[idx].of_node,
- "ti,overcurrent-wait",
+ if (of_property_read_u32(np, "ti,overcurrent-wait",
&rpdata->overcurrent_wait) == 0)
rpdata->overcurrent_wait_valid = true;
diff --git a/drivers/regulator/tps65132-regulator.c b/drivers/regulator/tps65132-regulator.c
index e302bd0..0edc830 100644
--- a/drivers/regulator/tps65132-regulator.c
+++ b/drivers/regulator/tps65132-regulator.c
@@ -136,9 +136,10 @@
struct tps65132_reg_pdata *rpdata = &tps->reg_pdata[desc->id];
int ret;
- rpdata->en_gpiod = devm_fwnode_get_index_gpiod_from_child(tps->dev,
- "enable", 0, &np->fwnode, 0, "enable");
- if (IS_ERR_OR_NULL(rpdata->en_gpiod)) {
+ rpdata->en_gpiod = devm_fwnode_gpiod_get(tps->dev, of_fwnode_handle(np),
+ "enable", GPIOD_ASIS,
+ "enable");
+ if (IS_ERR(rpdata->en_gpiod)) {
ret = PTR_ERR(rpdata->en_gpiod);
/* Ignore the error other than probe defer */
@@ -147,10 +148,12 @@
return 0;
}
- rpdata->act_dis_gpiod = devm_fwnode_get_index_gpiod_from_child(
- tps->dev, "active-discharge", 0,
- &np->fwnode, 0, "active-discharge");
- if (IS_ERR_OR_NULL(rpdata->act_dis_gpiod)) {
+ rpdata->act_dis_gpiod = devm_fwnode_gpiod_get(tps->dev,
+ of_fwnode_handle(np),
+ "active-discharge",
+ GPIOD_ASIS,
+ "active-discharge");
+ if (IS_ERR(rpdata->act_dis_gpiod)) {
ret = PTR_ERR(rpdata->act_dis_gpiod);
/* Ignore the error other than probe defer */
@@ -217,8 +220,7 @@
.wr_table = &tps65132_no_reg_table,
};
-static int tps65132_probe(struct i2c_client *client,
- const struct i2c_device_id *client_id)
+static int tps65132_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct tps65132_regulator *tps;
@@ -269,7 +271,7 @@
.driver = {
.name = "tps65132",
},
- .probe = tps65132_probe,
+ .probe_new = tps65132_probe,
.id_table = tps65132_id,
};
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
index 67ba78d..e88ed96 100644
--- a/drivers/regulator/tps65217-regulator.c
+++ b/drivers/regulator/tps65217-regulator.c
@@ -3,7 +3,7 @@
*
* Regulator driver for TPS65217 PMIC
*
- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -56,14 +56,14 @@
2800000, 3000000, 3100000, 3300000,
};
-static const struct regulator_linear_range tps65217_uv1_ranges[] = {
+static const struct linear_range tps65217_uv1_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 24, 25000),
REGULATOR_LINEAR_RANGE(1550000, 25, 52, 50000),
REGULATOR_LINEAR_RANGE(3000000, 53, 55, 100000),
REGULATOR_LINEAR_RANGE(3300000, 56, 63, 0),
};
-static const struct regulator_linear_range tps65217_uv2_ranges[] = {
+static const struct linear_range tps65217_uv2_ranges[] = {
REGULATOR_LINEAR_RANGE(1500000, 0, 8, 50000),
REGULATOR_LINEAR_RANGE(2000000, 9, 13, 100000),
REGULATOR_LINEAR_RANGE(2450000, 14, 31, 50000),
@@ -124,7 +124,7 @@
struct tps65217 *tps = rdev_get_drvdata(dev);
unsigned int rid = rdev_get_id(dev);
- if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
+ if (rid > TPS65217_LDO_4)
return -EINVAL;
return tps65217_clear_bits(tps, dev->desc->bypass_reg,
@@ -137,7 +137,7 @@
struct tps65217 *tps = rdev_get_drvdata(dev);
unsigned int rid = rdev_get_id(dev);
- if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
+ if (rid > TPS65217_LDO_4)
return -EINVAL;
if (!tps->strobes[rid])
@@ -254,6 +254,9 @@
/* Store default strobe info */
ret = tps65217_reg_read(tps, regulators[i].bypass_reg, &val);
+ if (ret)
+ return ret;
+
tps->strobes[i] = val & regulators[i].bypass_mask;
}
diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c
index b720356..fa26354 100644
--- a/drivers/regulator/tps65218-regulator.c
+++ b/drivers/regulator/tps65218-regulator.c
@@ -3,7 +3,7 @@
*
* Regulator driver for TPS65218 PMIC
*
- * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.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
@@ -56,17 +56,17 @@
.bypass_mask = _sm, \
} \
-static const struct regulator_linear_range dcdc1_dcdc2_ranges[] = {
+static const struct linear_range dcdc1_dcdc2_ranges[] = {
REGULATOR_LINEAR_RANGE(850000, 0x0, 0x32, 10000),
REGULATOR_LINEAR_RANGE(1375000, 0x33, 0x3f, 25000),
};
-static const struct regulator_linear_range ldo1_dcdc3_ranges[] = {
+static const struct linear_range ldo1_dcdc3_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0x0, 0x1a, 25000),
REGULATOR_LINEAR_RANGE(1600000, 0x1b, 0x3f, 50000),
};
-static const struct regulator_linear_range dcdc4_ranges[] = {
+static const struct linear_range dcdc4_ranges[] = {
REGULATOR_LINEAR_RANGE(1175000, 0x0, 0xf, 25000),
REGULATOR_LINEAR_RANGE(1600000, 0x10, 0x34, 50000),
};
@@ -128,7 +128,7 @@
struct tps65218 *tps = rdev_get_drvdata(dev);
unsigned int rid = rdev_get_id(dev);
- if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
+ if (rid > TPS65218_LDO_1)
return -EINVAL;
return tps65218_clear_bits(tps, dev->desc->bypass_reg,
@@ -141,7 +141,7 @@
struct tps65218 *tps = rdev_get_drvdata(dev);
unsigned int rid = rdev_get_id(dev);
- if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
+ if (rid > TPS65218_LDO_1)
return -EINVAL;
/*
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index 09e994e..18bf4b8 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -60,7 +60,7 @@
int enable_reg[2];
};
-static struct regulator_ops tps6586x_rw_regulator_ops = {
+static const struct regulator_ops tps6586x_rw_regulator_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -71,7 +71,7 @@
.disable = regulator_disable_regmap,
};
-static struct regulator_ops tps6586x_rw_linear_regulator_ops = {
+static const struct regulator_ops tps6586x_rw_linear_regulator_ops = {
.list_voltage = regulator_list_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -81,7 +81,7 @@
.disable = regulator_disable_regmap,
};
-static struct regulator_ops tps6586x_ro_regulator_ops = {
+static const struct regulator_ops tps6586x_ro_regulator_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -91,7 +91,7 @@
.disable = regulator_disable_regmap,
};
-static struct regulator_ops tps6586x_sys_regulator_ops = {
+static const struct regulator_ops tps6586x_sys_regulator_ops = {
};
static const unsigned int tps6586x_ldo0_voltages[] = {
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
index 4eb5b19..06cbe60 100644
--- a/drivers/regulator/tps65910-regulator.c
+++ b/drivers/regulator/tps65910-regulator.c
@@ -390,8 +390,8 @@
static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
- struct tps65910 *mfd = pmic->mfd;
- int reg, value, id = rdev_get_id(dev);
+ struct regmap *regmap = rdev_get_regmap(dev);
+ int reg, id = rdev_get_id(dev);
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
@@ -399,14 +399,14 @@
switch (mode) {
case REGULATOR_MODE_NORMAL:
- return tps65910_reg_update_bits(pmic->mfd, reg,
- LDO_ST_MODE_BIT | LDO_ST_ON_BIT,
- LDO_ST_ON_BIT);
+ return regmap_update_bits(regmap, reg,
+ LDO_ST_MODE_BIT | LDO_ST_ON_BIT,
+ LDO_ST_ON_BIT);
case REGULATOR_MODE_IDLE:
- value = LDO_ST_ON_BIT | LDO_ST_MODE_BIT;
- return tps65910_reg_set_bits(mfd, reg, value);
+ return regmap_set_bits(regmap, reg,
+ LDO_ST_ON_BIT | LDO_ST_MODE_BIT);
case REGULATOR_MODE_STANDBY:
- return tps65910_reg_clear_bits(mfd, reg, LDO_ST_ON_BIT);
+ return regmap_clear_bits(regmap, reg, LDO_ST_ON_BIT);
}
return -EINVAL;
@@ -415,13 +415,14 @@
static unsigned int tps65910_get_mode(struct regulator_dev *dev)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
+ struct regmap *regmap = rdev_get_regmap(dev);
int ret, reg, value, id = rdev_get_id(dev);
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
return reg;
- ret = tps65910_reg_read(pmic->mfd, reg, &value);
+ ret = regmap_read(regmap, reg, &value);
if (ret < 0)
return ret;
@@ -435,20 +436,20 @@
static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev)
{
- struct tps65910_reg *pmic = rdev_get_drvdata(dev);
+ struct regmap *regmap = rdev_get_regmap(dev);
int ret, id = rdev_get_id(dev);
int opvsel = 0, srvsel = 0, vselmax = 0, mult = 0, sr = 0;
switch (id) {
case TPS65910_REG_VDD1:
- ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1_OP, &opvsel);
+ ret = regmap_read(regmap, TPS65910_VDD1_OP, &opvsel);
if (ret < 0)
return ret;
- ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1, &mult);
+ ret = regmap_read(regmap, TPS65910_VDD1, &mult);
if (ret < 0)
return ret;
mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT;
- ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1_SR, &srvsel);
+ ret = regmap_read(regmap, TPS65910_VDD1_SR, &srvsel);
if (ret < 0)
return ret;
sr = opvsel & VDD1_OP_CMD_MASK;
@@ -457,14 +458,14 @@
vselmax = 75;
break;
case TPS65910_REG_VDD2:
- ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2_OP, &opvsel);
+ ret = regmap_read(regmap, TPS65910_VDD2_OP, &opvsel);
if (ret < 0)
return ret;
- ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2, &mult);
+ ret = regmap_read(regmap, TPS65910_VDD2, &mult);
if (ret < 0)
return ret;
mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT;
- ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2_SR, &srvsel);
+ ret = regmap_read(regmap, TPS65910_VDD2_SR, &srvsel);
if (ret < 0)
return ret;
sr = opvsel & VDD2_OP_CMD_MASK;
@@ -473,12 +474,10 @@
vselmax = 75;
break;
case TPS65911_REG_VDDCTRL:
- ret = tps65910_reg_read(pmic->mfd, TPS65911_VDDCTRL_OP,
- &opvsel);
+ ret = regmap_read(regmap, TPS65911_VDDCTRL_OP, &opvsel);
if (ret < 0)
return ret;
- ret = tps65910_reg_read(pmic->mfd, TPS65911_VDDCTRL_SR,
- &srvsel);
+ ret = regmap_read(regmap, TPS65911_VDDCTRL_SR, &srvsel);
if (ret < 0)
return ret;
sr = opvsel & VDDCTRL_OP_CMD_MASK;
@@ -514,13 +513,14 @@
static int tps65910_get_voltage_sel(struct regulator_dev *dev)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
+ struct regmap *regmap = rdev_get_regmap(dev);
int ret, reg, value, id = rdev_get_id(dev);
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
return reg;
- ret = tps65910_reg_read(pmic->mfd, reg, &value);
+ ret = regmap_read(regmap, reg, &value);
if (ret < 0)
return ret;
@@ -556,12 +556,13 @@
static int tps65911_get_voltage_sel(struct regulator_dev *dev)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
+ struct regmap *regmap = rdev_get_regmap(dev);
int ret, id = rdev_get_id(dev);
unsigned int value, reg;
reg = pmic->get_ctrl_reg(id);
- ret = tps65910_reg_read(pmic->mfd, reg, &value);
+ ret = regmap_read(regmap, reg, &value);
if (ret < 0)
return ret;
@@ -594,7 +595,7 @@
static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev,
unsigned selector)
{
- struct tps65910_reg *pmic = rdev_get_drvdata(dev);
+ struct regmap *regmap = rdev_get_regmap(dev);
int id = rdev_get_id(dev), vsel;
int dcdc_mult = 0;
@@ -605,10 +606,9 @@
dcdc_mult--;
vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;
- tps65910_reg_update_bits(pmic->mfd, TPS65910_VDD1,
- VDD1_VGAIN_SEL_MASK,
- dcdc_mult << VDD1_VGAIN_SEL_SHIFT);
- tps65910_reg_write(pmic->mfd, TPS65910_VDD1_OP, vsel);
+ regmap_update_bits(regmap, TPS65910_VDD1, VDD1_VGAIN_SEL_MASK,
+ dcdc_mult << VDD1_VGAIN_SEL_SHIFT);
+ regmap_write(regmap, TPS65910_VDD1_OP, vsel);
break;
case TPS65910_REG_VDD2:
dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
@@ -616,14 +616,14 @@
dcdc_mult--;
vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;
- tps65910_reg_update_bits(pmic->mfd, TPS65910_VDD2,
- VDD1_VGAIN_SEL_MASK,
- dcdc_mult << VDD2_VGAIN_SEL_SHIFT);
- tps65910_reg_write(pmic->mfd, TPS65910_VDD2_OP, vsel);
+ regmap_update_bits(regmap, TPS65910_VDD2, VDD1_VGAIN_SEL_MASK,
+ dcdc_mult << VDD2_VGAIN_SEL_SHIFT);
+ regmap_write(regmap, TPS65910_VDD2_OP, vsel);
break;
case TPS65911_REG_VDDCTRL:
vsel = selector + 3;
- tps65910_reg_write(pmic->mfd, TPS65911_VDDCTRL_OP, vsel);
+ regmap_write(regmap, TPS65911_VDDCTRL_OP, vsel);
+ break;
}
return 0;
@@ -633,6 +633,7 @@
unsigned selector)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
+ struct regmap *regmap = rdev_get_regmap(dev);
int reg, id = rdev_get_id(dev);
reg = pmic->get_ctrl_reg(id);
@@ -649,11 +650,11 @@
case TPS65910_REG_VAUX2:
case TPS65910_REG_VAUX33:
case TPS65910_REG_VMMC:
- return tps65910_reg_update_bits(pmic->mfd, reg, LDO_SEL_MASK,
- selector << LDO_SEL_SHIFT);
+ return regmap_update_bits(regmap, reg, LDO_SEL_MASK,
+ selector << LDO_SEL_SHIFT);
case TPS65910_REG_VBB:
- return tps65910_reg_update_bits(pmic->mfd, reg, BBCH_BBSEL_MASK,
- selector << BBCH_BBSEL_SHIFT);
+ return regmap_update_bits(regmap, reg, BBCH_BBSEL_MASK,
+ selector << BBCH_BBSEL_SHIFT);
}
return -EINVAL;
@@ -663,6 +664,7 @@
unsigned selector)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
+ struct regmap *regmap = rdev_get_regmap(dev);
int reg, id = rdev_get_id(dev);
reg = pmic->get_ctrl_reg(id);
@@ -673,21 +675,21 @@
case TPS65911_REG_LDO1:
case TPS65911_REG_LDO2:
case TPS65911_REG_LDO4:
- return tps65910_reg_update_bits(pmic->mfd, reg, LDO1_SEL_MASK,
- selector << LDO_SEL_SHIFT);
+ return regmap_update_bits(regmap, reg, LDO1_SEL_MASK,
+ selector << LDO_SEL_SHIFT);
case TPS65911_REG_LDO3:
case TPS65911_REG_LDO5:
case TPS65911_REG_LDO6:
case TPS65911_REG_LDO7:
case TPS65911_REG_LDO8:
- return tps65910_reg_update_bits(pmic->mfd, reg, LDO3_SEL_MASK,
- selector << LDO_SEL_SHIFT);
+ return regmap_update_bits(regmap, reg, LDO3_SEL_MASK,
+ selector << LDO_SEL_SHIFT);
case TPS65910_REG_VIO:
- return tps65910_reg_update_bits(pmic->mfd, reg, LDO_SEL_MASK,
- selector << LDO_SEL_SHIFT);
+ return regmap_update_bits(regmap, reg, LDO_SEL_MASK,
+ selector << LDO_SEL_SHIFT);
case TPS65910_REG_VBB:
- return tps65910_reg_update_bits(pmic->mfd, reg, BBCH_BBSEL_MASK,
- selector << BBCH_BBSEL_SHIFT);
+ return regmap_update_bits(regmap, reg, BBCH_BBSEL_MASK,
+ selector << BBCH_BBSEL_SHIFT);
}
return -EINVAL;
@@ -757,7 +759,7 @@
}
/* Regulator ops (except VRTC) */
-static struct regulator_ops tps65910_ops_dcdc = {
+static const struct regulator_ops tps65910_ops_dcdc = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -770,7 +772,7 @@
.map_voltage = regulator_map_voltage_ascend,
};
-static struct regulator_ops tps65910_ops_vdd3 = {
+static const struct regulator_ops tps65910_ops_vdd3 = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -781,7 +783,7 @@
.map_voltage = regulator_map_voltage_ascend,
};
-static struct regulator_ops tps65910_ops_vbb = {
+static const struct regulator_ops tps65910_ops_vbb = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -793,7 +795,7 @@
.map_voltage = regulator_map_voltage_iterate,
};
-static struct regulator_ops tps65910_ops = {
+static const struct regulator_ops tps65910_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -805,7 +807,7 @@
.map_voltage = regulator_map_voltage_ascend,
};
-static struct regulator_ops tps65911_ops = {
+static const struct regulator_ops tps65911_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -850,10 +852,10 @@
/* External EN1 control */
if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1)
- ret = tps65910_reg_set_bits(mfd,
+ ret = regmap_set_bits(mfd->regmap,
TPS65910_EN1_LDO_ASS + regoffs, bit_pos);
else
- ret = tps65910_reg_clear_bits(mfd,
+ ret = regmap_clear_bits(mfd->regmap,
TPS65910_EN1_LDO_ASS + regoffs, bit_pos);
if (ret < 0) {
dev_err(mfd->dev,
@@ -863,10 +865,10 @@
/* External EN2 control */
if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2)
- ret = tps65910_reg_set_bits(mfd,
+ ret = regmap_set_bits(mfd->regmap,
TPS65910_EN2_LDO_ASS + regoffs, bit_pos);
else
- ret = tps65910_reg_clear_bits(mfd,
+ ret = regmap_clear_bits(mfd->regmap,
TPS65910_EN2_LDO_ASS + regoffs, bit_pos);
if (ret < 0) {
dev_err(mfd->dev,
@@ -878,10 +880,10 @@
if ((tps65910_chip_id(mfd) == TPS65910) &&
(id >= TPS65910_REG_VDIG1)) {
if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3)
- ret = tps65910_reg_set_bits(mfd,
+ ret = regmap_set_bits(mfd->regmap,
TPS65910_EN3_LDO_ASS + regoffs, bit_pos);
else
- ret = tps65910_reg_clear_bits(mfd,
+ ret = regmap_clear_bits(mfd->regmap,
TPS65910_EN3_LDO_ASS + regoffs, bit_pos);
if (ret < 0) {
dev_err(mfd->dev,
@@ -893,10 +895,10 @@
/* Return if no external control is selected */
if (!(ext_sleep_config & EXT_SLEEP_CONTROL)) {
/* Clear all sleep controls */
- ret = tps65910_reg_clear_bits(mfd,
+ ret = regmap_clear_bits(mfd->regmap,
TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos);
if (!ret)
- ret = tps65910_reg_clear_bits(mfd,
+ ret = regmap_clear_bits(mfd->regmap,
TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos);
if (ret < 0)
dev_err(mfd->dev,
@@ -917,39 +919,38 @@
int sr_reg_add = pmic->get_ctrl_reg(id) + 2;
int opvsel, srvsel;
- ret = tps65910_reg_read(pmic->mfd, op_reg_add, &opvsel);
+ ret = regmap_read(mfd->regmap, op_reg_add, &opvsel);
if (ret < 0)
return ret;
- ret = tps65910_reg_read(pmic->mfd, sr_reg_add, &srvsel);
+ ret = regmap_read(mfd->regmap, sr_reg_add, &srvsel);
if (ret < 0)
return ret;
if (opvsel & VDD1_OP_CMD_MASK) {
u8 reg_val = srvsel & VDD1_OP_SEL_MASK;
- ret = tps65910_reg_write(pmic->mfd, op_reg_add,
- reg_val);
+ ret = regmap_write(mfd->regmap, op_reg_add, reg_val);
if (ret < 0) {
dev_err(mfd->dev,
"Error in configuring op register\n");
return ret;
}
}
- ret = tps65910_reg_write(pmic->mfd, sr_reg_add, 0);
+ ret = regmap_write(mfd->regmap, sr_reg_add, 0);
if (ret < 0) {
dev_err(mfd->dev, "Error in setting sr register\n");
return ret;
}
}
- ret = tps65910_reg_clear_bits(mfd,
+ ret = regmap_clear_bits(mfd->regmap,
TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos);
if (!ret) {
if (ext_sleep_config & TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP)
- ret = tps65910_reg_set_bits(mfd,
+ ret = regmap_set_bits(mfd->regmap,
TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos);
else
- ret = tps65910_reg_clear_bits(mfd,
+ ret = regmap_clear_bits(mfd->regmap,
TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos);
}
if (ret < 0)
@@ -1097,7 +1098,7 @@
platform_set_drvdata(pdev, pmic);
/* Give control of all register to control port */
- err = tps65910_reg_set_bits(pmic->mfd, TPS65910_DEVCTRL,
+ err = regmap_set_bits(pmic->mfd->regmap, TPS65910_DEVCTRL,
DEVCTRL_SR_CTL_I2C_SEL_MASK);
if (err < 0)
return err;
@@ -1113,7 +1114,7 @@
* voltage level can go higher than expected or crash
* Workaround: use no synchronization of DCDC clocks
*/
- tps65910_reg_clear_bits(pmic->mfd, TPS65910_DCDCCTRL,
+ regmap_clear_bits(pmic->mfd->regmap, TPS65910_DCDCCTRL,
DCDCCTRL_DCDCCKSYNC_MASK);
break;
case TPS65911:
@@ -1210,12 +1211,10 @@
rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i],
&config);
- if (IS_ERR(rdev)) {
- dev_err(tps65910->dev,
- "failed to register %s regulator\n",
- pdev->name);
- return PTR_ERR(rdev);
- }
+ if (IS_ERR(rdev))
+ return dev_err_probe(tps65910->dev, PTR_ERR(rdev),
+ "failed to register %s regulator\n",
+ pdev->name);
/* Save regulator for cleanup */
pmic->rdev[i] = rdev;
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
index 276faed..b52d4f2 100644
--- a/drivers/regulator/tps65912-regulator.c
+++ b/drivers/regulator/tps65912-regulator.c
@@ -1,7 +1,7 @@
/*
* Regulator driver for TI TPS65912x PMICs
*
- * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
* Andrew F. Davis <afd@ti.com>
*
* This program is free software; you can redistribute it and/or
@@ -46,18 +46,18 @@
.n_linear_ranges = ARRAY_SIZE(_lr), \
}
-static const struct regulator_linear_range tps65912_dcdc_ranges[] = {
+static const struct linear_range tps65912_dcdc_ranges[] = {
REGULATOR_LINEAR_RANGE(500000, 0x0, 0x3f, 50000),
};
-static const struct regulator_linear_range tps65912_ldo_ranges[] = {
+static const struct linear_range tps65912_ldo_ranges[] = {
REGULATOR_LINEAR_RANGE(800000, 0x0, 0x20, 25000),
REGULATOR_LINEAR_RANGE(1650000, 0x21, 0x3c, 50000),
REGULATOR_LINEAR_RANGE(3100000, 0x3d, 0x3f, 100000),
};
/* Operations permitted on DCDCx */
-static struct regulator_ops tps65912_ops_dcdc = {
+static const struct regulator_ops tps65912_ops_dcdc = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -67,7 +67,7 @@
};
/* Operations permitted on LDOx */
-static struct regulator_ops tps65912_ops_ldo = {
+static const struct regulator_ops tps65912_ops_ldo = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
index 85a6a8c..a29e652 100644
--- a/drivers/regulator/tps80031-regulator.c
+++ b/drivers/regulator/tps80031-regulator.c
@@ -271,7 +271,7 @@
{
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_tps80031_dev(rdev);
- int ret = -EIO;
+ int ret;
uint8_t ctrl1 = 0;
uint8_t ctrl3 = 0;
@@ -322,7 +322,7 @@
{
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_tps80031_dev(rdev);
- int ret = 0;
+ int ret;
if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) {
ret = tps80031_write(parent, TPS80031_SLAVE_ID2,
@@ -530,7 +530,8 @@
case TPS80031_REGULATOR_LDOUSB:
if (ri->config_flags & (TPS80031_USBLDO_INPUT_VSYS |
TPS80031_USBLDO_INPUT_PMID)) {
- unsigned val = 0;
+ unsigned val;
+
if (ri->config_flags & TPS80031_USBLDO_INPUT_VSYS)
val = MISC2_LDOUSB_IN_VSYS;
else
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 866b4dd..4a51cfe 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -360,12 +360,12 @@
};
/* 600mV to 1450mV in 12.5 mV steps */
-static const struct regulator_linear_range VDD1_ranges[] = {
+static const struct linear_range VDD1_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 68, 12500)
};
/* 600mV to 1450mV in 12.5 mV steps, everything above = 1500mV */
-static const struct regulator_linear_range VDD2_ranges[] = {
+static const struct linear_range VDD2_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 68, 12500),
REGULATOR_LINEAR_RANGE(1500000, 69, 69, 12500)
};
diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c
index b8100c3..430265c 100644
--- a/drivers/regulator/twl6030-regulator.c
+++ b/drivers/regulator/twl6030-regulator.c
@@ -312,7 +312,7 @@
switch (info->flags) {
case SMPS_OFFSET_EN:
voltage = 100000;
- /* fall through */
+ fallthrough;
case 0:
switch (index) {
case 0:
@@ -495,7 +495,7 @@
};
/*----------------------------------------------------------------------*/
-static const struct regulator_linear_range twl6030ldo_linear_range[] = {
+static const struct linear_range twl6030ldo_linear_range[] = {
REGULATOR_LINEAR_RANGE(0, 0, 0, 0),
REGULATOR_LINEAR_RANGE(1000000, 1, 24, 100000),
REGULATOR_LINEAR_RANGE(2750000, 31, 31, 0),
diff --git a/drivers/regulator/uniphier-regulator.c b/drivers/regulator/uniphier-regulator.c
index 2904c7b..e75b097 100644
--- a/drivers/regulator/uniphier-regulator.c
+++ b/drivers/regulator/uniphier-regulator.c
@@ -45,7 +45,6 @@
struct regulator_config config = { };
struct regulator_dev *rdev;
struct regmap *regmap;
- struct resource *res;
void __iomem *base;
const char *name;
int i, ret, nr;
@@ -58,8 +57,7 @@
if (WARN_ON(!priv->data))
return -EINVAL;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
diff --git a/drivers/regulator/vexpress-regulator.c b/drivers/regulator/vexpress-regulator.c
index 1235f46..5d39663 100644
--- a/drivers/regulator/vexpress-regulator.c
+++ b/drivers/regulator/vexpress-regulator.c
@@ -75,10 +75,7 @@
config.of_node = pdev->dev.of_node;
rdev = devm_regulator_register(&pdev->dev, desc, &config);
- if (IS_ERR(rdev))
- return PTR_ERR(rdev);
-
- return 0;
+ return PTR_ERR_OR_ZERO(rdev);
}
static const struct of_device_id vexpress_regulator_of_match[] = {
diff --git a/drivers/regulator/vqmmc-ipq4019-regulator.c b/drivers/regulator/vqmmc-ipq4019-regulator.c
new file mode 100644
index 0000000..6d5ae25
--- /dev/null
+++ b/drivers/regulator/vqmmc-ipq4019-regulator.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright (c) 2019 Mantas Pucka <mantas@8devices.com>
+// Copyright (c) 2019 Robert Marko <robert.marko@sartura.hr>
+//
+// Driver for IPQ4019 SD/MMC controller's I/O LDO voltage regulator
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+static const unsigned int ipq4019_vmmc_voltages[] = {
+ 1500000, 1800000, 2500000, 3000000,
+};
+
+static const struct regulator_ops ipq4019_regulator_voltage_ops = {
+ .list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static const struct regulator_desc vmmc_regulator = {
+ .name = "vmmcq",
+ .ops = &ipq4019_regulator_voltage_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .volt_table = ipq4019_vmmc_voltages,
+ .n_voltages = ARRAY_SIZE(ipq4019_vmmc_voltages),
+ .vsel_reg = 0,
+ .vsel_mask = 0x3,
+};
+
+static const struct regmap_config ipq4019_vmmcq_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+};
+
+static int ipq4019_regulator_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regulator_init_data *init_data;
+ struct regulator_config cfg = {};
+ struct regulator_dev *rdev;
+ struct resource *res;
+ struct regmap *rmap;
+ void __iomem *base;
+
+ init_data = of_get_regulator_init_data(dev, dev->of_node,
+ &vmmc_regulator);
+ if (!init_data)
+ return -EINVAL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ rmap = devm_regmap_init_mmio(dev, base, &ipq4019_vmmcq_regmap_config);
+ if (IS_ERR(rmap))
+ return PTR_ERR(rmap);
+
+ cfg.dev = dev;
+ cfg.init_data = init_data;
+ cfg.of_node = dev->of_node;
+ cfg.regmap = rmap;
+
+ rdev = devm_regulator_register(dev, &vmmc_regulator, &cfg);
+ if (IS_ERR(rdev)) {
+ dev_err(dev, "Failed to register regulator: %ld\n",
+ PTR_ERR(rdev));
+ return PTR_ERR(rdev);
+ }
+ platform_set_drvdata(pdev, rdev);
+
+ return 0;
+}
+
+static const struct of_device_id regulator_ipq4019_of_match[] = {
+ { .compatible = "qcom,vqmmc-ipq4019-regulator", },
+ {},
+};
+
+static struct platform_driver ipq4019_regulator_driver = {
+ .probe = ipq4019_regulator_probe,
+ .driver = {
+ .name = "vqmmc-ipq4019-regulator",
+ .of_match_table = of_match_ptr(regulator_ipq4019_of_match),
+ },
+};
+module_platform_driver(ipq4019_regulator_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mantas Pucka <mantas@8devices.com>");
+MODULE_DESCRIPTION("IPQ4019 VQMMC voltage regulator");
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 018dbbd..e43ed4d 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -178,11 +178,9 @@
{
struct wm831x_dcdc *dcdc = data;
- regulator_lock(dcdc->regulator);
regulator_notifier_call_chain(dcdc->regulator,
REGULATOR_EVENT_UNDER_VOLTAGE,
NULL);
- regulator_unlock(dcdc->regulator);
return IRQ_HANDLED;
}
@@ -191,11 +189,9 @@
{
struct wm831x_dcdc *dcdc = data;
- regulator_lock(dcdc->regulator);
regulator_notifier_call_chain(dcdc->regulator,
REGULATOR_EVENT_OVER_CURRENT,
NULL);
- regulator_unlock(dcdc->regulator);
return IRQ_HANDLED;
}
@@ -204,7 +200,7 @@
* BUCKV specifics
*/
-static const struct regulator_linear_range wm831x_buckv_ranges[] = {
+static const struct linear_range wm831x_buckv_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 0x7, 0),
REGULATOR_LINEAR_RANGE(600000, 0x8, 0x68, 12500),
};
diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c
index ff3d2bf..eade3ae 100644
--- a/drivers/regulator/wm831x-isink.c
+++ b/drivers/regulator/wm831x-isink.c
@@ -99,11 +99,9 @@
{
struct wm831x_isink *isink = data;
- regulator_lock(isink->regulator);
regulator_notifier_call_chain(isink->regulator,
REGULATOR_EVENT_OVER_CURRENT,
NULL);
- regulator_unlock(isink->regulator);
return IRQ_HANDLED;
}
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
index 5675468..e091b18 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -46,11 +46,9 @@
{
struct wm831x_ldo *ldo = data;
- regulator_lock(ldo->regulator);
regulator_notifier_call_chain(ldo->regulator,
REGULATOR_EVENT_UNDER_VOLTAGE,
NULL);
- regulator_unlock(ldo->regulator);
return IRQ_HANDLED;
}
@@ -59,7 +57,7 @@
* General purpose LDOs
*/
-static const struct regulator_linear_range wm831x_gp_ldo_ranges[] = {
+static const struct linear_range wm831x_gp_ldo_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000),
REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),
};
@@ -312,7 +310,7 @@
* Analogue LDOs
*/
-static const struct regulator_linear_range wm831x_aldo_ranges[] = {
+static const struct linear_range wm831x_aldo_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 12, 50000),
REGULATOR_LINEAR_RANGE(1700000, 13, 31, 100000),
};
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index 56d6168..6579bfd 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -470,7 +470,7 @@
return 0;
}
-static const struct regulator_linear_range wm8350_ldo_ranges[] = {
+static const struct linear_range wm8350_ldo_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 15, 50000),
REGULATOR_LINEAR_RANGE(1800000, 16, 31, 100000),
};
@@ -1089,7 +1089,6 @@
{
struct regulator_dev *rdev = (struct regulator_dev *)data;
- regulator_lock(rdev);
if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2)
regulator_notifier_call_chain(rdev,
REGULATOR_EVENT_REGULATION_OUT,
@@ -1098,7 +1097,6 @@
regulator_notifier_call_chain(rdev,
REGULATOR_EVENT_UNDER_VOLTAGE,
NULL);
- regulator_unlock(rdev);
return IRQ_HANDLED;
}
@@ -1216,11 +1214,11 @@
/**
* wm8350_register_led - Register a WM8350 LED output
*
- * @param wm8350 The WM8350 device to configure.
- * @param lednum LED device index to create.
- * @param dcdc The DCDC to use for the LED.
- * @param isink The ISINK to use for the LED.
- * @param pdata Configuration for the LED.
+ * @wm8350: The WM8350 device to configure.
+ * @lednum: LED device index to create.
+ * @dcdc: The DCDC to use for the LED.
+ * @isink: The ISINK to use for the LED.
+ * @pdata: Configuration for the LED.
*
* The WM8350 supports the use of an ISINK together with a DCDC to
* provide a power-efficient LED driver. This function registers the
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
index 6f331b5..e9fd137 100644
--- a/drivers/regulator/wm8400-regulator.c
+++ b/drivers/regulator/wm8400-regulator.c
@@ -13,7 +13,7 @@
#include <linux/regulator/driver.h>
#include <linux/mfd/wm8400-private.h>
-static const struct regulator_linear_range wm8400_ldo_ranges[] = {
+static const struct linear_range wm8400_ldo_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000),
REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),
};
@@ -234,9 +234,9 @@
* the regulator API. It is intended to be called from the
* platform_init() callback of the WM8400 MFD driver.
*
- * @param dev The WM8400 device to operate on.
- * @param reg The regulator to control.
- * @param initdata Regulator initdata for the regulator.
+ * @dev: The WM8400 device to operate on.
+ * @reg: The regulator to control.
+ * @initdata: Regulator initdata for the regulator.
*/
int wm8400_register_regulator(struct device *dev, int reg,
struct regulator_init_data *initdata)