summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-04-06 12:16:57 -0600
committerTom Rini <[email protected]>2026-04-06 12:16:57 -0600
commit93f84ee022a8401421cdaab84fe7d106d83fdb4a (patch)
treefb15a4af876e8faf9893fd86c1c0e127265dbe9a /drivers/power
parent88dc2788777babfd6322fa655df549a019aa1e69 (diff)
parente2138cf1e6088f12ffa874e87cc8f4b198378635 (diff)
Merge branch 'next'
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/domain/Kconfig2
-rw-r--r--drivers/power/domain/imx8m-power-domain.c3
-rw-r--r--drivers/power/pmic/Kconfig10
-rw-r--r--drivers/power/pmic/Makefile1
-rw-r--r--drivers/power/pmic/bd71837.c3
-rw-r--r--drivers/power/pmic/cpcap.c4
-rw-r--r--drivers/power/pmic/max77663.c4
-rw-r--r--drivers/power/pmic/max8907.c3
-rw-r--r--drivers/power/pmic/mc34708.c3
-rw-r--r--drivers/power/pmic/mp5416.c3
-rw-r--r--drivers/power/pmic/mtk-pwrap.c896
-rw-r--r--drivers/power/pmic/palmas.c4
-rw-r--r--drivers/power/pmic/pca9450.c3
-rw-r--r--drivers/power/pmic/pmic_tps65910_dm.c4
-rw-r--r--drivers/power/pmic/rk8xx.c4
-rw-r--r--drivers/power/pmic/tps80031.c4
-rw-r--r--drivers/power/regulator/Kconfig26
-rw-r--r--drivers/power/regulator/Makefile2
-rw-r--r--drivers/power/regulator/cpcap_regulator.c55
-rw-r--r--drivers/power/regulator/mt6357_regulator.c512
-rw-r--r--drivers/power/regulator/mt6359_regulator.c711
-rw-r--r--drivers/power/regulator/pwm_regulator.c3
-rw-r--r--drivers/power/regulator/regulator-uclass.c2
23 files changed, 2206 insertions, 56 deletions
diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
index 935f282d6c5..2f63a8e54e5 100644
--- a/drivers/power/domain/Kconfig
+++ b/drivers/power/domain/Kconfig
@@ -20,7 +20,7 @@ config APPLE_PMGR_POWER_DOMAIN
config AGILEX5_PMGR_POWER_DOMAIN
bool "Enable the Agilex5 PMGR power domain driver"
- depends on SPL_POWER_DOMAIN && TARGET_SOCFPGA_SOC64
+ depends on SPL_POWER_DOMAIN && ARCH_SOCFPGA_SOC64
help
Enable support for power gating peripherals' SRAM specified in
the handoff data values obtained from the bitstream to reduce
diff --git a/drivers/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c
index a7e64971a2a..1c731b897cc 100644
--- a/drivers/power/domain/imx8m-power-domain.c
+++ b/drivers/power/domain/imx8m-power-domain.c
@@ -7,7 +7,6 @@
#include <dm.h>
#include <malloc.h>
#include <power-domain-uclass.h>
-#include <asm/global_data.h>
#include <asm/io.h>
#include <asm/mach-imx/sys_proto.h>
#include <dm/device-internal.h>
@@ -22,8 +21,6 @@
#include <dt-bindings/power/imx8mp-power.h>
#include <dt-bindings/power/imx8mq-power.h>
-DECLARE_GLOBAL_DATA_PTR;
-
#define GPC_PGC_CPU_MAPPING 0x0ec
#define IMX8MP_GPC_PGC_CPU_MAPPING 0x1cc
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index b1a5b1c2a1f..5bc14842e66 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -384,7 +384,7 @@ config DM_PMIC_TPS80031
config PMIC_STPMIC1
bool "Enable support for STMicroelectronics STPMIC1 PMIC"
depends on DM_I2C
- select SYSRESET_CMD_POWEROFF if CMD_POWEROFF && !ARM_PSCI_FW
+ select SYSRESET_CMD_POWEROFF if SYSRESET && CMD_POWEROFF && !ARM_PSCI_FW
---help---
The STPMIC1 PMIC provides 4 BUCKs, 6 LDOs, 1 VREF and 2 power switches.
It is accessed via an I2C interface. The device is used with STM32MP1
@@ -433,6 +433,14 @@ config PMIC_RAA215300
support and several voltage regulators. For now, this driver simply
allows register access and will bind the sysreset driver
(CONFIG_SYSRESET_RAA215300) if it is enabled.
+
+config DM_PMIC_MTK_PWRAP
+ bool "Enable driver for MediaTek PMIC Wrapper Support"
+ help
+ Say yes here to add support for MediaTek PMIC Wrapper found
+ on different MediaTek SoCs. The PMIC wrapper is a proprietary
+ hardware to connect the PMIC.
+
endif
config PMIC_TPS65217
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 6bebffb05a6..2cda5a892fd 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_PMIC_TPS65941) += tps65941.o
obj-$(CONFIG_PMIC_RAA215300) += raa215300.o
obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o
obj-$(CONFIG_$(PHASE_)DM_PMIC_CPCAP) += cpcap.o
+obj-$(CONFIG_DM_PMIC_MTK_PWRAP) += mtk-pwrap.o
ifeq ($(CONFIG_$(PHASE_)POWER_LEGACY),y)
obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o
diff --git a/drivers/power/pmic/bd71837.c b/drivers/power/pmic/bd71837.c
index a5df2570fc3..13642794765 100644
--- a/drivers/power/pmic/bd71837.c
+++ b/drivers/power/pmic/bd71837.c
@@ -7,14 +7,11 @@
#include <dm.h>
#include <i2c.h>
#include <log.h>
-#include <asm/global_data.h>
#include <linux/printk.h>
#include <power/pmic.h>
#include <power/regulator.h>
#include <power/bd71837.h>
-DECLARE_GLOBAL_DATA_PTR;
-
static const struct pmic_child_info pmic_children_info[] = {
/* buck */
{ .prefix = "b", .driver = BD718XX_REGULATOR_DRIVER},
diff --git a/drivers/power/pmic/cpcap.c b/drivers/power/pmic/cpcap.c
index f2076afff43..b9d783773ed 100644
--- a/drivers/power/pmic/cpcap.c
+++ b/drivers/power/pmic/cpcap.c
@@ -14,7 +14,9 @@
static const struct pmic_child_info pmic_children_info[] = {
{ .prefix = "sw", .driver = CPCAP_SW_DRIVER },
+ { .prefix = "SW", .driver = CPCAP_SW_DRIVER },
{ .prefix = "v", .driver = CPCAP_LDO_DRIVER },
+ { .prefix = "V", .driver = CPCAP_LDO_DRIVER },
{ },
};
@@ -112,6 +114,8 @@ static struct dm_pmic_ops cpcap_ops = {
static const struct udevice_id cpcap_ids[] = {
{ .compatible = "motorola,cpcap" },
{ .compatible = "st,6556002" },
+ { .compatible = "motorola,mapphone-cpcap" },
+ { .compatible = "motorola,mot-cpcap" },
{ }
};
diff --git a/drivers/power/pmic/max77663.c b/drivers/power/pmic/max77663.c
index c2a7cbf7e40..a06042e2918 100644
--- a/drivers/power/pmic/max77663.c
+++ b/drivers/power/pmic/max77663.c
@@ -46,7 +46,9 @@ static int max77663_bind(struct udevice *dev)
ofnode regulators_node;
int children, ret;
- if (IS_ENABLED(CONFIG_SYSRESET_MAX77663)) {
+ if (IS_ENABLED(CONFIG_SYSRESET_MAX77663) &&
+ (dev_read_bool(dev, "maxim,system-power-controller") ||
+ dev_read_bool(dev, "system-power-controller"))) {
ret = device_bind_driver_to_node(dev, MAX77663_RST_DRIVER,
"sysreset", dev_ofnode(dev),
NULL);
diff --git a/drivers/power/pmic/max8907.c b/drivers/power/pmic/max8907.c
index a7ef70177de..34bef0c8cd6 100644
--- a/drivers/power/pmic/max8907.c
+++ b/drivers/power/pmic/max8907.c
@@ -48,7 +48,8 @@ static int max8907_bind(struct udevice *dev)
int children, ret;
if (IS_ENABLED(CONFIG_SYSRESET_MAX8907) &&
- dev_read_bool(dev, "maxim,system-power-controller")) {
+ (dev_read_bool(dev, "maxim,system-power-controller") ||
+ dev_read_bool(dev, "system-power-controller"))) {
ret = device_bind_driver_to_node(dev, MAX8907_RST_DRIVER,
"sysreset", dev_ofnode(dev),
NULL);
diff --git a/drivers/power/pmic/mc34708.c b/drivers/power/pmic/mc34708.c
index 43badb5767a..0ec52e25a9e 100644
--- a/drivers/power/pmic/mc34708.c
+++ b/drivers/power/pmic/mc34708.c
@@ -9,11 +9,8 @@
#include <errno.h>
#include <fsl_pmic.h>
#include <i2c.h>
-#include <asm/global_data.h>
#include <power/pmic.h>
-DECLARE_GLOBAL_DATA_PTR;
-
static int mc34708_reg_count(struct udevice *dev)
{
return PMIC_NUM_OF_REGS;
diff --git a/drivers/power/pmic/mp5416.c b/drivers/power/pmic/mp5416.c
index 9d44f0ae655..899c2beeb37 100644
--- a/drivers/power/pmic/mp5416.c
+++ b/drivers/power/pmic/mp5416.c
@@ -9,9 +9,6 @@
#include <power/pmic.h>
#include <power/regulator.h>
#include <power/mp5416.h>
-#include <asm/global_data.h>
-
-DECLARE_GLOBAL_DATA_PTR;
static const struct pmic_child_info pmic_children_info[] = {
/* buck */
diff --git a/drivers/power/pmic/mtk-pwrap.c b/drivers/power/pmic/mtk-pwrap.c
new file mode 100644
index 00000000000..3e3a691d9e8
--- /dev/null
+++ b/drivers/power/pmic/mtk-pwrap.c
@@ -0,0 +1,896 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * MT6357 regulator driver
+ *
+ * Copyright (c) 2026 BayLibre, SAS.
+ * Author: Julien Masson <[email protected]>
+ */
+
+#include <asm/io.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <linux/bitfield.h>
+#include <linux/err.h>
+#include <power/pmic.h>
+#include <power/mt6357.h>
+#include <power/mt6359.h>
+#include <time.h>
+
+static const struct pmic_child_info mt6357_pmic_children_info[] = {
+ { .prefix = "buck", .driver = MT6357_REGULATOR_DRIVER },
+ { .prefix = "ldo", .driver = MT6357_REGULATOR_DRIVER },
+ { }
+};
+
+static const struct pmic_child_info mt6359_pmic_children_info[] = {
+ { .prefix = "buck", .driver = MT6359_REGULATOR_DRIVER },
+ { .prefix = "ldo", .driver = MT6359_REGULATOR_DRIVER },
+ { }
+};
+
+/* macro for wrapper status */
+#define PWRAP_GET_WACS_RDATA GENMASK(15, 0)
+#define PWRAP_GET_WACS_FSM GENMASK(18, 16)
+#define PWRAP_GET_WACS_ARB_FSM GENMASK(3, 1)
+#define PWRAP_STATE_SYNC_IDLE0 BIT(20)
+#define PWRAP_STATE_INIT_DONE0 BIT(21)
+#define PWRAP_STATE_INIT_DONE1 BIT(15)
+
+/* macro for WACS FSM */
+#define PWRAP_WACS_FSM_IDLE 0x00
+#define PWRAP_WACS_FSM_WFVLDCLR 0x06
+
+/* macro for device wrapper default value */
+#define PWRAP_DEW_READ_TEST_VAL 0x5aa5
+
+/* macro for manual command */
+#define PWRAP_MAN_CMD_SPI_WRITE BIT(13)
+#define PWRAP_MAN_CMD_OP_CSH (0x0 << 8)
+#define PWRAP_MAN_CMD_OP_CSL (0x1 << 8)
+#define PWRAP_MAN_CMD_OP_OUTS (0x8 << 8)
+
+/* macro for Watch Dog Timer Source */
+#define PWRAP_WDT_SRC_MASK_ALL GENMASK(31, 0)
+
+/* Group of bits used for shown slave capability */
+#define PWRAP_SLV_CAP_SPI BIT(0)
+#define PWRAP_SLV_CAP_DUALIO BIT(1)
+#define HAS_CAP(_c, _x_val) (((_c) & (_x_val)) == (_x_val))
+
+/* Group of bits used for shown pwrap capability */
+#define PWRAP_CAP_INT1_EN BIT(3)
+#define PWRAP_CAP_WDT_SRC1 BIT(4)
+#define PWRAP_CAP_ARB BIT(5)
+
+/* defines for slave device wrapper registers */
+enum dew_regs {
+ PWRAP_DEW_BASE,
+ PWRAP_DEW_DIO_EN,
+ PWRAP_DEW_READ_TEST,
+ PWRAP_DEW_WRITE_TEST,
+ PWRAP_DEW_CRC_EN,
+ PWRAP_DEW_CRC_VAL,
+ PWRAP_DEW_MON_GRP_SEL,
+ PWRAP_DEW_CIPHER_KEY_SEL,
+ PWRAP_DEW_CIPHER_IV_SEL,
+ PWRAP_DEW_CIPHER_RDY,
+ PWRAP_DEW_CIPHER_MODE,
+ PWRAP_DEW_CIPHER_SWRST,
+
+ /* MT6323 only regs */
+ PWRAP_DEW_CIPHER_EN,
+ PWRAP_DEW_RDDMY_NO,
+
+ /* MT6358 only regs */
+ PWRAP_SMT_CON1,
+ PWRAP_DRV_CON1,
+ PWRAP_FILTER_CON0,
+ PWRAP_GPIO_PULLEN0_CLR,
+ PWRAP_RG_SPI_CON0,
+ PWRAP_RG_SPI_RECORD0,
+ PWRAP_RG_SPI_CON2,
+ PWRAP_RG_SPI_CON3,
+ PWRAP_RG_SPI_CON4,
+ PWRAP_RG_SPI_CON5,
+ PWRAP_RG_SPI_CON6,
+ PWRAP_RG_SPI_CON7,
+ PWRAP_RG_SPI_CON8,
+ PWRAP_RG_SPI_CON13,
+ PWRAP_SPISLV_KEY,
+
+ /* MT6359 only regs */
+ PWRAP_DEW_CRC_SWRST,
+ PWRAP_DEW_RG_EN_RECORD,
+ PWRAP_DEW_RECORD_CMD0,
+ PWRAP_DEW_RECORD_CMD1,
+ PWRAP_DEW_RECORD_CMD2,
+ PWRAP_DEW_RECORD_CMD3,
+ PWRAP_DEW_RECORD_CMD4,
+ PWRAP_DEW_RECORD_CMD5,
+ PWRAP_DEW_RECORD_WDATA0,
+ PWRAP_DEW_RECORD_WDATA1,
+ PWRAP_DEW_RECORD_WDATA2,
+ PWRAP_DEW_RECORD_WDATA3,
+ PWRAP_DEW_RECORD_WDATA4,
+ PWRAP_DEW_RECORD_WDATA5,
+ PWRAP_DEW_RG_ADDR_TARGET,
+ PWRAP_DEW_RG_ADDR_MASK,
+ PWRAP_DEW_RG_WDATA_TARGET,
+ PWRAP_DEW_RG_WDATA_MASK,
+ PWRAP_DEW_RG_SPI_RECORD_CLR,
+ PWRAP_DEW_RG_CMD_ALERT_CLR,
+};
+
+static const u32 mt6357_regs[] = {
+ [PWRAP_DEW_DIO_EN] = 0x040A,
+ [PWRAP_DEW_READ_TEST] = 0x040C,
+ [PWRAP_DEW_WRITE_TEST] = 0x040E,
+ [PWRAP_DEW_CRC_EN] = 0x0412,
+ [PWRAP_DEW_CRC_VAL] = 0x0414,
+ [PWRAP_DEW_CIPHER_KEY_SEL] = 0x0418,
+ [PWRAP_DEW_CIPHER_IV_SEL] = 0x041A,
+ [PWRAP_DEW_CIPHER_RDY] = 0x041E,
+ [PWRAP_DEW_CIPHER_MODE] = 0x0420,
+ [PWRAP_DEW_CIPHER_SWRST] = 0x0422,
+ [PWRAP_DEW_CIPHER_EN] = 0x041C,
+ [PWRAP_DEW_RDDMY_NO] = 0x0424,
+};
+
+static const u32 mt6359_regs[] = {
+ [PWRAP_DEW_RG_EN_RECORD] = 0x040a,
+ [PWRAP_DEW_DIO_EN] = 0x040c,
+ [PWRAP_DEW_READ_TEST] = 0x040e,
+ [PWRAP_DEW_WRITE_TEST] = 0x0410,
+ [PWRAP_DEW_CRC_SWRST] = 0x0412,
+ [PWRAP_DEW_CRC_EN] = 0x0414,
+ [PWRAP_DEW_CRC_VAL] = 0x0416,
+ [PWRAP_DEW_CIPHER_KEY_SEL] = 0x0418,
+ [PWRAP_DEW_CIPHER_IV_SEL] = 0x041a,
+ [PWRAP_DEW_CIPHER_EN] = 0x041c,
+ [PWRAP_DEW_CIPHER_RDY] = 0x041e,
+ [PWRAP_DEW_CIPHER_MODE] = 0x0420,
+ [PWRAP_DEW_CIPHER_SWRST] = 0x0422,
+ [PWRAP_DEW_RDDMY_NO] = 0x0424,
+ [PWRAP_DEW_RECORD_CMD0] = 0x0428,
+ [PWRAP_DEW_RECORD_CMD1] = 0x042a,
+ [PWRAP_DEW_RECORD_CMD2] = 0x042c,
+ [PWRAP_DEW_RECORD_CMD3] = 0x042e,
+ [PWRAP_DEW_RECORD_CMD4] = 0x0430,
+ [PWRAP_DEW_RECORD_CMD5] = 0x0432,
+ [PWRAP_DEW_RECORD_WDATA0] = 0x0434,
+ [PWRAP_DEW_RECORD_WDATA1] = 0x0436,
+ [PWRAP_DEW_RECORD_WDATA2] = 0x0438,
+ [PWRAP_DEW_RECORD_WDATA3] = 0x043a,
+ [PWRAP_DEW_RECORD_WDATA4] = 0x043c,
+ [PWRAP_DEW_RECORD_WDATA5] = 0x043e,
+ [PWRAP_DEW_RG_ADDR_TARGET] = 0x0440,
+ [PWRAP_DEW_RG_ADDR_MASK] = 0x0442,
+ [PWRAP_DEW_RG_WDATA_TARGET] = 0x0444,
+ [PWRAP_DEW_RG_WDATA_MASK] = 0x0446,
+ [PWRAP_DEW_RG_SPI_RECORD_CLR] = 0x0448,
+ [PWRAP_DEW_RG_CMD_ALERT_CLR] = 0x0448,
+ [PWRAP_SPISLV_KEY] = 0x044a,
+};
+
+enum pwrap_regs {
+ PWRAP_MUX_SEL,
+ PWRAP_WRAP_EN,
+ PWRAP_DIO_EN,
+ PWRAP_SIDLY,
+ PWRAP_CSHEXT_WRITE,
+ PWRAP_CSHEXT_READ,
+ PWRAP_CSLEXT_START,
+ PWRAP_CSLEXT_END,
+ PWRAP_STAUPD_PRD,
+ PWRAP_STAUPD_GRPEN,
+ PWRAP_STAUPD_MAN_TRIG,
+ PWRAP_STAUPD_STA,
+ PWRAP_WRAP_STA,
+ PWRAP_HARB_INIT,
+ PWRAP_HARB_HPRIO,
+ PWRAP_HIPRIO_ARB_EN,
+ PWRAP_HARB_STA0,
+ PWRAP_HARB_STA1,
+ PWRAP_MAN_EN,
+ PWRAP_MAN_CMD,
+ PWRAP_MAN_RDATA,
+ PWRAP_MAN_VLDCLR,
+ PWRAP_WACS0_EN,
+ PWRAP_INIT_DONE0,
+ PWRAP_WACS0_CMD,
+ PWRAP_WACS0_RDATA,
+ PWRAP_WACS0_VLDCLR,
+ PWRAP_WACS1_EN,
+ PWRAP_INIT_DONE1,
+ PWRAP_WACS1_CMD,
+ PWRAP_WACS1_RDATA,
+ PWRAP_WACS1_VLDCLR,
+ PWRAP_WACS2_EN,
+ PWRAP_INIT_DONE2,
+ PWRAP_WACS2_CMD,
+ PWRAP_WACS2_RDATA,
+ PWRAP_WACS2_VLDCLR,
+ PWRAP_INT_EN,
+ PWRAP_INT_FLG_RAW,
+ PWRAP_INT_FLG,
+ PWRAP_INT_CLR,
+ PWRAP_SIG_ADR,
+ PWRAP_SIG_MODE,
+ PWRAP_SIG_VALUE,
+ PWRAP_SIG_ERRVAL,
+ PWRAP_CRC_EN,
+ PWRAP_TIMER_EN,
+ PWRAP_TIMER_STA,
+ PWRAP_WDT_UNIT,
+ PWRAP_WDT_SRC_EN,
+ PWRAP_WDT_FLG,
+ PWRAP_DEBUG_INT_SEL,
+ PWRAP_CIPHER_KEY_SEL,
+ PWRAP_CIPHER_IV_SEL,
+ PWRAP_CIPHER_RDY,
+ PWRAP_CIPHER_MODE,
+ PWRAP_CIPHER_SWRST,
+ PWRAP_DCM_EN,
+ PWRAP_DCM_DBC_PRD,
+ PWRAP_EINT_STA0_ADR,
+ PWRAP_EINT_STA1_ADR,
+ PWRAP_SWINF_2_WDATA_31_0,
+ PWRAP_SWINF_2_RDATA_31_0,
+
+ /* MT8390 only regs */
+ PWRAP_STAUPD_CTRL,
+
+ /* MT8365 only regs */
+ PWRAP_INT1_EN,
+ PWRAP_INT1_FLG,
+ PWRAP_INT1_CLR,
+ PWRAP_WDT_SRC_EN_1,
+};
+
+static int mt8188_regs[] = {
+ [PWRAP_INIT_DONE2] = 0x0,
+ [PWRAP_STAUPD_CTRL] = 0x4C,
+ [PWRAP_TIMER_EN] = 0x3E4,
+ [PWRAP_INT_EN] = 0x420,
+ [PWRAP_INT_FLG] = 0x428,
+ [PWRAP_INT_CLR] = 0x42C,
+ [PWRAP_INT1_EN] = 0x450,
+ [PWRAP_INT1_FLG] = 0x458,
+ [PWRAP_INT1_CLR] = 0x45C,
+ [PWRAP_WACS2_CMD] = 0x880,
+ [PWRAP_SWINF_2_WDATA_31_0] = 0x884,
+ [PWRAP_SWINF_2_RDATA_31_0] = 0x894,
+ [PWRAP_WACS2_VLDCLR] = 0x8A4,
+ [PWRAP_WACS2_RDATA] = 0x8A8,
+};
+
+static int mt8189_regs[] = {
+ [PWRAP_INIT_DONE2] = 0x0,
+ [PWRAP_TIMER_EN] = 0x3E4,
+ [PWRAP_INT_EN] = 0x450,
+ [PWRAP_WACS2_CMD] = 0x880,
+ [PWRAP_SWINF_2_WDATA_31_0] = 0x884,
+ [PWRAP_SWINF_2_RDATA_31_0] = 0x894,
+ [PWRAP_WACS2_VLDCLR] = 0x8A4,
+ [PWRAP_WACS2_RDATA] = 0x8A8,
+};
+
+static int mt8365_regs[] = {
+ [PWRAP_MUX_SEL] = 0x0,
+ [PWRAP_WRAP_EN] = 0x4,
+ [PWRAP_DIO_EN] = 0x8,
+ [PWRAP_CSHEXT_WRITE] = 0x24,
+ [PWRAP_CSHEXT_READ] = 0x28,
+ [PWRAP_STAUPD_PRD] = 0x3c,
+ [PWRAP_STAUPD_GRPEN] = 0x40,
+ [PWRAP_STAUPD_MAN_TRIG] = 0x58,
+ [PWRAP_STAUPD_STA] = 0x5c,
+ [PWRAP_WRAP_STA] = 0x60,
+ [PWRAP_HARB_INIT] = 0x64,
+ [PWRAP_HARB_HPRIO] = 0x68,
+ [PWRAP_HIPRIO_ARB_EN] = 0x6c,
+ [PWRAP_HARB_STA0] = 0x70,
+ [PWRAP_HARB_STA1] = 0x74,
+ [PWRAP_MAN_EN] = 0x7c,
+ [PWRAP_MAN_CMD] = 0x80,
+ [PWRAP_MAN_RDATA] = 0x84,
+ [PWRAP_MAN_VLDCLR] = 0x88,
+ [PWRAP_WACS0_EN] = 0x8c,
+ [PWRAP_INIT_DONE0] = 0x90,
+ [PWRAP_WACS0_CMD] = 0xc00,
+ [PWRAP_WACS0_RDATA] = 0xc04,
+ [PWRAP_WACS0_VLDCLR] = 0xc08,
+ [PWRAP_WACS1_EN] = 0x94,
+ [PWRAP_INIT_DONE1] = 0x98,
+ [PWRAP_WACS2_EN] = 0x9c,
+ [PWRAP_INIT_DONE2] = 0xa0,
+ [PWRAP_WACS2_CMD] = 0xc20,
+ [PWRAP_WACS2_RDATA] = 0xc24,
+ [PWRAP_WACS2_VLDCLR] = 0xc28,
+ [PWRAP_INT_EN] = 0xb4,
+ [PWRAP_INT_FLG_RAW] = 0xb8,
+ [PWRAP_INT_FLG] = 0xbc,
+ [PWRAP_INT_CLR] = 0xc0,
+ [PWRAP_SIG_ADR] = 0xd4,
+ [PWRAP_SIG_MODE] = 0xd8,
+ [PWRAP_SIG_VALUE] = 0xdc,
+ [PWRAP_SIG_ERRVAL] = 0xe0,
+ [PWRAP_CRC_EN] = 0xe4,
+ [PWRAP_TIMER_EN] = 0xe8,
+ [PWRAP_TIMER_STA] = 0xec,
+ [PWRAP_WDT_UNIT] = 0xf0,
+ [PWRAP_WDT_SRC_EN] = 0xf4,
+ [PWRAP_WDT_FLG] = 0xfc,
+ [PWRAP_DEBUG_INT_SEL] = 0x104,
+ [PWRAP_CIPHER_KEY_SEL] = 0x1c4,
+ [PWRAP_CIPHER_IV_SEL] = 0x1c8,
+ [PWRAP_CIPHER_RDY] = 0x1d0,
+ [PWRAP_CIPHER_MODE] = 0x1d4,
+ [PWRAP_CIPHER_SWRST] = 0x1d8,
+ [PWRAP_DCM_EN] = 0x1dc,
+ [PWRAP_DCM_DBC_PRD] = 0x1e0,
+ [PWRAP_EINT_STA0_ADR] = 0x44,
+ [PWRAP_EINT_STA1_ADR] = 0x48,
+ [PWRAP_INT1_EN] = 0xc4,
+ [PWRAP_INT1_FLG] = 0xcc,
+ [PWRAP_INT1_CLR] = 0xd0,
+ [PWRAP_WDT_SRC_EN_1] = 0xf8,
+};
+
+enum pwrap_type {
+ PWRAP_MT8188,
+ PWRAP_MT8189,
+ PWRAP_MT8365,
+};
+
+struct pwrap_slv_type {
+ const u32 *dew_regs;
+ u32 caps;
+};
+
+struct pmic_wrapper {
+ struct udevice *dev;
+ void __iomem *base;
+ const struct pmic_wrapper_type *master;
+ const struct pwrap_slv_type *slave;
+ struct clk *clk_spi;
+ struct clk *clk_wrap;
+ struct clk *clk_wrap_sys;
+ struct clk *clk_wrap_tmr;
+};
+
+struct pmic_wrapper_type {
+ int *regs;
+ enum pwrap_type type;
+ u32 arb_en_all;
+ u32 int_en_all;
+ u32 int1_en_all;
+ u32 spi_w;
+ u32 wdt_src;
+ /* Flags indicating the capability for the target pwrap */
+ u32 caps;
+};
+
+static u32 pwrap_readl(struct pmic_wrapper *wrp, enum pwrap_regs reg)
+{
+ return readl(wrp->base + wrp->master->regs[reg]);
+}
+
+static void pwrap_writel(struct pmic_wrapper *wrp, u32 val, enum pwrap_regs reg)
+{
+ writel(val, wrp->base + wrp->master->regs[reg]);
+}
+
+static u32 pwrap_get_fsm_state(struct pmic_wrapper *wrp)
+{
+ u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+
+ if (HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB))
+ return FIELD_GET(PWRAP_GET_WACS_ARB_FSM, val);
+
+ return FIELD_GET(PWRAP_GET_WACS_FSM, val);
+}
+
+static bool pwrap_is_fsm_idle(struct pmic_wrapper *wrp)
+{
+ return pwrap_get_fsm_state(wrp) == PWRAP_WACS_FSM_IDLE;
+}
+
+static bool pwrap_is_fsm_vldclr(struct pmic_wrapper *wrp)
+{
+ return pwrap_get_fsm_state(wrp) == PWRAP_WACS_FSM_WFVLDCLR;
+}
+
+/*
+ * Timeout issue sometimes caused by the last read command
+ * failed because pmic wrap could not got the FSM_VLDCLR
+ * in time after finishing WACS2_CMD. It made state machine
+ * still on FSM_VLDCLR and timeout next time.
+ * Check the status of FSM and clear the vldclr to recovery the
+ * error.
+ */
+static inline void pwrap_leave_fsm_vldclr(struct pmic_wrapper *wrp)
+{
+ if (pwrap_is_fsm_vldclr(wrp))
+ pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR);
+}
+
+static bool pwrap_is_sync_idle(struct pmic_wrapper *wrp)
+{
+ return FIELD_GET(PWRAP_STATE_SYNC_IDLE0, pwrap_readl(wrp, PWRAP_WACS2_RDATA));
+}
+
+static bool pwrap_is_fsm_idle_and_sync_idle(struct pmic_wrapper *wrp)
+{
+ u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+
+ return FIELD_GET(PWRAP_GET_WACS_FSM, val) == PWRAP_WACS_FSM_IDLE &&
+ FIELD_GET(PWRAP_STATE_SYNC_IDLE0, val);
+}
+
+static int pwrap_wait_for_state(struct pmic_wrapper *wrp, bool (*fp)(struct pmic_wrapper *))
+{
+ unsigned long timeout;
+
+ timeout = timer_get_us() + 10000;
+
+ do {
+ if (time_after(timer_get_us(), timeout))
+ return fp(wrp) ? 0 : -ETIMEDOUT;
+
+ if (fp(wrp))
+ return 0;
+ } while (1);
+}
+
+/* pwrap_read16 in linux kernel */
+static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata)
+{
+ int ret;
+ u32 val;
+
+ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle);
+ if (ret) {
+ pwrap_leave_fsm_vldclr(wrp);
+ return ret;
+ }
+
+ if (HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB))
+ val = adr;
+ else
+ val = (adr >> 1) << 16;
+
+ pwrap_writel(wrp, val, PWRAP_WACS2_CMD);
+
+ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_vldclr);
+ if (ret)
+ return ret;
+
+ if (HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB))
+ val = pwrap_readl(wrp, PWRAP_SWINF_2_RDATA_31_0);
+ else
+ val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+
+ *rdata = FIELD_GET(PWRAP_GET_WACS_RDATA, val);
+
+ pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR);
+
+ return 0;
+}
+
+/* pwrap_write16 in linux kernel */
+static int pwrap_write(struct pmic_wrapper *wrp, u32 adr, u32 wdata)
+{
+ int ret;
+
+ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle);
+ if (ret) {
+ pwrap_leave_fsm_vldclr(wrp);
+ return ret;
+ }
+
+ if (HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB)) {
+ pwrap_writel(wrp, wdata, PWRAP_SWINF_2_WDATA_31_0);
+ pwrap_writel(wrp, BIT(29) | adr, PWRAP_WACS2_CMD);
+ } else {
+ pwrap_writel(wrp, BIT(31) | ((adr >> 1) << 16) | wdata, PWRAP_WACS2_CMD);
+ }
+
+ return 0;
+}
+
+static int pwrap_reset_spislave(struct pmic_wrapper *wrp)
+{
+ int ret, i;
+
+ pwrap_writel(wrp, 0, PWRAP_HIPRIO_ARB_EN);
+ pwrap_writel(wrp, 0, PWRAP_WRAP_EN);
+ pwrap_writel(wrp, 1, PWRAP_MUX_SEL);
+ pwrap_writel(wrp, 1, PWRAP_MAN_EN);
+ pwrap_writel(wrp, 0, PWRAP_DIO_EN);
+
+ pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_CSL, PWRAP_MAN_CMD);
+ pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_OUTS, PWRAP_MAN_CMD);
+ pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_CSH, PWRAP_MAN_CMD);
+
+ for (i = 0; i < 4; i++)
+ pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_OUTS,
+ PWRAP_MAN_CMD);
+
+ ret = pwrap_wait_for_state(wrp, pwrap_is_sync_idle);
+ if (ret) {
+ dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret);
+ return ret;
+ }
+
+ pwrap_writel(wrp, 0, PWRAP_MAN_EN);
+ pwrap_writel(wrp, 0, PWRAP_MUX_SEL);
+
+ return 0;
+}
+
+/*
+ * pwrap_init_sidly - configure serial input delay
+ *
+ * This configures the serial input delay. We can configure 0, 2, 4 or 6ns
+ * delay. Do a read test with all possible values and chose the best delay.
+ */
+static int pwrap_init_sidly(struct pmic_wrapper *wrp)
+{
+ u32 rdata;
+ u32 i;
+ u32 pass = 0;
+ signed char dly[16] = {
+ -1, 0, 1, 0, 2, -1, 1, 1, 3, -1, -1, -1, 3, -1, 2, 1
+ };
+
+ for (i = 0; i < 4; i++) {
+ pwrap_writel(wrp, i, PWRAP_SIDLY);
+ pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], &rdata);
+ if (rdata == PWRAP_DEW_READ_TEST_VAL) {
+ dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i);
+ pass |= 1 << i;
+ }
+ }
+
+ if (dly[pass] < 0) {
+ dev_err(wrp->dev, "sidly pass range 0x%x not continuous\n", pass);
+ return -EIO;
+ }
+
+ pwrap_writel(wrp, dly[pass], PWRAP_SIDLY);
+
+ return 0;
+}
+
+static int pwrap_init_dual_io(struct pmic_wrapper *wrp)
+{
+ int ret;
+ u32 rdata;
+
+ /* Enable dual IO mode */
+ pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1);
+
+ /* Check IDLE & INIT_DONE in advance */
+ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle);
+ if (ret) {
+ dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret);
+ return ret;
+ }
+
+ pwrap_writel(wrp, 1, PWRAP_DIO_EN);
+
+ /* Read Test */
+ pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], &rdata);
+ if (rdata != PWRAP_DEW_READ_TEST_VAL) {
+ dev_err(wrp->dev, "Read failed on DIO mode: 0x%04x!=0x%04x\n",
+ PWRAP_DEW_READ_TEST_VAL, rdata);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int pwrap_init(struct pmic_wrapper *wrp)
+{
+ int ret;
+
+ /* Reset SPI slave */
+ if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_SPI)) {
+ ret = pwrap_reset_spislave(wrp);
+ if (ret)
+ return ret;
+ }
+
+ pwrap_writel(wrp, 1, PWRAP_WRAP_EN);
+
+ pwrap_writel(wrp, wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN);
+
+ pwrap_writel(wrp, 1, PWRAP_WACS2_EN);
+
+ /* Setup serial input delay */
+ if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_SPI)) {
+ ret = pwrap_init_sidly(wrp);
+ if (ret)
+ return ret;
+ }
+
+ /* Enable dual I/O mode */
+ if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_DUALIO)) {
+ ret = pwrap_init_dual_io(wrp);
+ if (ret)
+ return ret;
+ }
+
+ pwrap_writel(wrp, 0x1, PWRAP_WACS0_EN);
+ pwrap_writel(wrp, 0x1, PWRAP_WACS1_EN);
+ pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN);
+ pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD);
+ pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN);
+
+ /* Setup the init done registers */
+ pwrap_writel(wrp, 1, PWRAP_INIT_DONE2);
+ pwrap_writel(wrp, 1, PWRAP_INIT_DONE0);
+ pwrap_writel(wrp, 1, PWRAP_INIT_DONE1);
+
+ return 0;
+}
+
+static const struct pwrap_slv_type pmic_mt6357 = {
+ .dew_regs = mt6357_regs,
+ .caps = 0,
+};
+
+static const struct pwrap_slv_type pmic_mt6359 = {
+ .dew_regs = mt6359_regs,
+ .caps = PWRAP_SLV_CAP_DUALIO,
+};
+
+static const struct udevice_id mtk_pmic_ids[] = {
+ { .compatible = "mediatek,mt6357", .data = (ulong)&pmic_mt6357 },
+ { .compatible = "mediatek,mt6359", .data = (ulong)&pmic_mt6359 },
+ { }
+};
+
+static int mtk_pwrap_find_slave(const struct pwrap_slv_type **slave, ofnode pmic_node)
+{
+ const struct udevice_id *of_match = mtk_pmic_ids;
+ const char *pmic_name;
+
+ pmic_name = ofnode_get_property(pmic_node, "compatible", NULL);
+ if (!pmic_name) {
+ log_err("%s: missing compatible property\n", __func__);
+ return -EINVAL;
+ }
+
+ while (of_match->compatible) {
+ if (!strcmp(of_match->compatible, pmic_name)) {
+ *slave = (struct pwrap_slv_type *)of_match->data;
+ return 0;
+ }
+ of_match++;
+ }
+
+ return -ENOENT;
+}
+
+static int mtk_pwrap_probe(struct udevice *dev)
+{
+ struct pmic_wrapper *wrp = dev_get_priv(dev);
+ ofnode pmic_node;
+ u32 mask_done;
+ int ret;
+
+ wrp->dev = dev;
+
+ wrp->base = dev_remap_addr(dev);
+ if (IS_ERR(wrp->base))
+ return PTR_ERR(wrp->base);
+
+ wrp->master = (void *)dev_get_driver_data(dev);
+
+ pmic_node = dev_read_first_subnode(dev);
+ if (!ofnode_valid(pmic_node)) {
+ dev_err(dev, "pmic subnode not found\n");
+ return -ENXIO;
+ }
+
+ ret = mtk_pwrap_find_slave(&wrp->slave, pmic_node);
+ if (ret) {
+ dev_err(dev, "pmic slave not found\n");
+ return -EINVAL;
+ }
+
+ wrp->clk_spi = devm_clk_get(dev, "spi");
+ if (IS_ERR(wrp->clk_spi))
+ return PTR_ERR(wrp->clk_spi);
+
+ wrp->clk_wrap = devm_clk_get(dev, "wrap");
+ if (IS_ERR(wrp->clk_wrap))
+ return PTR_ERR(wrp->clk_wrap);
+
+ wrp->clk_wrap_sys = devm_clk_get_optional(dev, "wrap_sys");
+ wrp->clk_wrap_tmr = devm_clk_get_optional(dev, "wrap_tmr");
+
+ ret = clk_enable(wrp->clk_spi);
+ if (ret)
+ return ret;
+
+ ret = clk_enable(wrp->clk_wrap);
+ if (ret)
+ return ret;
+
+ ret = clk_enable(wrp->clk_wrap_sys);
+ if (ret)
+ return ret;
+
+ ret = clk_enable(wrp->clk_wrap_tmr);
+ if (ret)
+ return ret;
+
+ /*
+ * The PMIC could already be initialized by the bootloader.
+ * Skip initialization here in this case.
+ */
+ if (!pwrap_readl(wrp, PWRAP_INIT_DONE2)) {
+ ret = pwrap_init(wrp);
+ if (ret) {
+ dev_err(dev, "init failed with %d\n", ret);
+ return ret;
+ }
+ }
+
+ if (HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB))
+ mask_done = PWRAP_STATE_INIT_DONE1;
+ else
+ mask_done = PWRAP_STATE_INIT_DONE0;
+
+ if (!(pwrap_readl(wrp, PWRAP_WACS2_RDATA) & mask_done)) {
+ dev_dbg(dev, "initialization isn't finished\n");
+ return -ENODEV;
+ }
+
+ /*
+ * Since STAUPD was not used on mt8173 platform,
+ * so STAUPD of WDT_SRC which should be turned off
+ */
+ pwrap_writel(wrp, wrp->master->wdt_src, PWRAP_WDT_SRC_EN);
+
+ if (HAS_CAP(wrp->master->caps, PWRAP_CAP_WDT_SRC1))
+ pwrap_writel(wrp, wrp->master->wdt_src, PWRAP_WDT_SRC_EN_1);
+
+ if (HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB))
+ pwrap_writel(wrp, 0x3, PWRAP_TIMER_EN);
+ else
+ pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
+
+ pwrap_writel(wrp, wrp->master->int_en_all, PWRAP_INT_EN);
+
+ /*
+ * We add INT1 interrupt to handle starvation and request exception
+ * If we support it, we should enable it here.
+ */
+ if (HAS_CAP(wrp->master->caps, PWRAP_CAP_INT1_EN))
+ pwrap_writel(wrp, wrp->master->int1_en_all, PWRAP_INT1_EN);
+
+ return 0;
+}
+
+static int mtk_pwrap_bind(struct udevice *dev)
+{
+ ofnode pmic_node, regulators_node;
+ int children;
+ const struct pmic_child_info *pmic_children_info;
+ struct pmic_wrapper_type *pw_type = (void *)dev_get_driver_data(dev);
+
+ pmic_node = dev_read_first_subnode(dev);
+ if (!ofnode_valid(pmic_node)) {
+ dev_err(dev, "pmic subnode not found\n");
+ return -ENXIO;
+ }
+
+ switch (pw_type->type) {
+ case PWRAP_MT8365:
+ pmic_children_info = mt6357_pmic_children_info;
+ break;
+ case PWRAP_MT8188:
+ case PWRAP_MT8189:
+ pmic_children_info = mt6359_pmic_children_info;
+ break;
+ default:
+ dev_err(dev, "pwrap type %d not supported\n", pw_type->type);
+ return -ENXIO;
+ }
+
+ regulators_node = ofnode_find_subnode(pmic_node, "regulators");
+ if (ofnode_valid(regulators_node)) {
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ dev_dbg(dev, "no children found\n");
+ } else {
+ dev_dbg(dev, "regulators subnode not found\n");
+ }
+
+ return 0;
+}
+
+static int mtk_pwrap_reg_count(struct udevice *dev)
+{
+ return 0x8000;
+}
+
+static int mtk_pwrap_read(struct udevice *dev, uint reg, uint8_t *buf, int len)
+{
+ struct pmic_wrapper *wrp = dev_get_priv(dev);
+
+ if ((len * sizeof(uint8_t)) > sizeof(u32))
+ return -EINVAL;
+
+ return pwrap_read(wrp, reg, (u32 *)buf);
+}
+
+static int mtk_pwrap_write(struct udevice *dev, uint reg, const uint8_t *buf, int len)
+{
+ struct pmic_wrapper *wrp = dev_get_priv(dev);
+
+ if ((len * sizeof(uint8_t)) > sizeof(u32))
+ return -EINVAL;
+
+ return pwrap_write(wrp, reg, *(u32 *)buf);
+}
+
+static struct dm_pmic_ops mtk_pwrap_ops = {
+ .reg_count = mtk_pwrap_reg_count,
+ .read = mtk_pwrap_read,
+ .write = mtk_pwrap_write,
+};
+
+static struct pmic_wrapper_type pwrap_mt8188 = {
+ .regs = mt8188_regs,
+ .type = PWRAP_MT8188,
+ .arb_en_all = 0x777f,
+ .int_en_all = 0x180000,
+ .int1_en_all = 0x0,
+ .spi_w = PWRAP_MAN_CMD_SPI_WRITE,
+ .wdt_src = PWRAP_WDT_SRC_MASK_ALL,
+ .caps = PWRAP_CAP_INT1_EN | PWRAP_CAP_ARB,
+};
+
+static struct pmic_wrapper_type pwrap_mt8189 = {
+ .regs = mt8189_regs,
+ .type = PWRAP_MT8189,
+ .arb_en_all = 0x777f,
+ .int_en_all = 0x180000,
+ .spi_w = PWRAP_MAN_CMD_SPI_WRITE,
+ .wdt_src = PWRAP_WDT_SRC_MASK_ALL,
+ .caps = PWRAP_CAP_ARB,
+};
+
+static const struct pmic_wrapper_type pwrap_mt8365 = {
+ .regs = mt8365_regs,
+ .type = PWRAP_MT8365,
+ .arb_en_all = 0x3ffff,
+ .int_en_all = 0x7f1fffff,
+ .int1_en_all = 0x0,
+ .spi_w = PWRAP_MAN_CMD_SPI_WRITE,
+ .wdt_src = PWRAP_WDT_SRC_MASK_ALL,
+ .caps = PWRAP_CAP_INT1_EN | PWRAP_CAP_WDT_SRC1,
+};
+
+static const struct udevice_id mtk_pwrap_ids[] = {
+ { .compatible = "mediatek,mt8188-pwrap", .data = (ulong)&pwrap_mt8188 },
+ { .compatible = "mediatek,mt8189-pwrap", .data = (ulong)&pwrap_mt8189 },
+ { .compatible = "mediatek,mt8365-pwrap", .data = (ulong)&pwrap_mt8365 },
+ { }
+};
+
+U_BOOT_DRIVER(mtk_pwrap) = {
+ .name = "mtk_pwrap",
+ .id = UCLASS_PMIC,
+ .of_match = mtk_pwrap_ids,
+ .bind = mtk_pwrap_bind,
+ .probe = mtk_pwrap_probe,
+ .ops = &mtk_pwrap_ops,
+ .priv_auto = sizeof(struct pmic_wrapper),
+};
diff --git a/drivers/power/pmic/palmas.c b/drivers/power/pmic/palmas.c
index 37d4190fabe..e5b497dfc39 100644
--- a/drivers/power/pmic/palmas.c
+++ b/drivers/power/pmic/palmas.c
@@ -48,7 +48,9 @@ static int palmas_bind(struct udevice *dev)
ofnode subnode, gpio_node;
int children, ret;
- if (IS_ENABLED(CONFIG_SYSRESET_PALMAS)) {
+ if (IS_ENABLED(CONFIG_SYSRESET_PALMAS) &&
+ (dev_read_bool(dev, "ti,system-power-controller") ||
+ dev_read_bool(dev, "system-power-controller"))) {
ret = device_bind_driver_to_node(dev, PALMAS_RST_DRIVER,
"sysreset", dev_ofnode(dev),
NULL);
diff --git a/drivers/power/pmic/pca9450.c b/drivers/power/pmic/pca9450.c
index e5c1f037b61..c95e6357ee8 100644
--- a/drivers/power/pmic/pca9450.c
+++ b/drivers/power/pmic/pca9450.c
@@ -10,7 +10,6 @@
#include <dm/lists.h>
#include <i2c.h>
#include <log.h>
-#include <asm/global_data.h>
#include <linux/delay.h>
#include <linux/printk.h>
#include <power/pmic.h>
@@ -18,8 +17,6 @@
#include <power/pca9450.h>
#include <sysreset.h>
-DECLARE_GLOBAL_DATA_PTR;
-
static const struct pmic_child_info pmic_children_info[] = {
/* buck */
{ .prefix = "b", .driver = PCA9450_REGULATOR_DRIVER},
diff --git a/drivers/power/pmic/pmic_tps65910_dm.c b/drivers/power/pmic/pmic_tps65910_dm.c
index de8d805566a..bce35603275 100644
--- a/drivers/power/pmic/pmic_tps65910_dm.c
+++ b/drivers/power/pmic/pmic_tps65910_dm.c
@@ -61,7 +61,9 @@ static int pmic_tps65910_bind(struct udevice *dev)
ofnode regulators_node;
int children, ret;
- if (IS_ENABLED(CONFIG_SYSRESET_TPS65910)) {
+ if (IS_ENABLED(CONFIG_SYSRESET_TPS65910) &&
+ (dev_read_bool(dev, "ti,system-power-controller") ||
+ dev_read_bool(dev, "system-power-controller"))) {
ret = device_bind_driver(dev, TPS65910_RST_DRIVER,
"sysreset", NULL);
if (ret) {
diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
index d11f7a7886e..95b71d2fe49 100644
--- a/drivers/power/pmic/rk8xx.c
+++ b/drivers/power/pmic/rk8xx.c
@@ -220,7 +220,9 @@ static int rk8xx_bind(struct udevice *dev)
debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
- if (CONFIG_IS_ENABLED(SYSRESET)) {
+ if (CONFIG_IS_ENABLED(SYSRESET) &&
+ (dev_read_bool(dev, "rockchip,system-power-controller") ||
+ dev_read_bool(dev, "system-power-controller"))) {
ret = device_bind_driver_to_node(dev, "rk8xx_sysreset",
"rk8xx_sysreset",
dev_ofnode(dev), NULL);
diff --git a/drivers/power/pmic/tps80031.c b/drivers/power/pmic/tps80031.c
index a2f935b0c6d..6004a14cd6c 100644
--- a/drivers/power/pmic/tps80031.c
+++ b/drivers/power/pmic/tps80031.c
@@ -46,7 +46,9 @@ static int tps80031_bind(struct udevice *dev)
ofnode regulators_node;
int children, ret;
- if (IS_ENABLED(CONFIG_SYSRESET_TPS80031)) {
+ if (IS_ENABLED(CONFIG_SYSRESET_TPS80031) &&
+ (dev_read_bool(dev, "ti,system-power-controller") ||
+ dev_read_bool(dev, "system-power-controller"))) {
ret = device_bind_driver(dev, TPS80031_RST_DRIVER,
"sysreset", NULL);
if (ret) {
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index d8b3e0f62e6..a4ee5f1335a 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -191,6 +191,14 @@ config DM_REGULATOR_FAN53555
or switching the mode is not supported by this driver (at
this time).
+config SPL_DM_REGULATOR_FAN53555
+ bool "Enable Driver Model for REGULATOR FAN53555 in SPL"
+ depends on SPL_DM_PMIC_FAN53555
+ help
+ This configuration setting enables the implementation of the
+ driver-model regulator uclass features for the FAN53555
+ regulator in SPL.
+
config DM_REGULATOR_COMMON
bool
depends on DM_REGULATOR
@@ -521,3 +529,21 @@ config DM_REGULATOR_CPCAP
REGULATOR CPCAP. The driver supports both DC-to-DC Step-Down Switching
(SW) Regulators and Low-Dropout Linear (LDO) Regulators found in CPCAP
PMIC and implements get/set api for voltage and state.
+
+config DM_REGULATOR_MT6357
+ bool "Enable driver for MediaTek MT6357 PMIC regulators"
+ depends on DM_REGULATOR && DM_PMIC_MTK_PWRAP
+ help
+ Say y here to select this option to enable the power regulator of
+ MediaTek MT6357 PMIC.
+ This driver supports the control of different power rails of device
+ through regulator interface.
+
+config DM_REGULATOR_MT6359
+ bool "Enable driver for MediaTek MT6359 PMIC regulators"
+ depends on DM_REGULATOR && DM_PMIC_MTK_PWRAP
+ help
+ Say y here to select this option to enable the power regulator of
+ MediaTek MT6359 PMIC.
+ This driver supports the control of different power rails of device
+ through regulator interface.
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index ee8f56ea3b9..9e303d4f7f8 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -47,3 +47,5 @@ obj-$(CONFIG_$(PHASE_)DM_REGULATOR_ANATOP) += anatop_regulator.o
obj-$(CONFIG_DM_REGULATOR_TPS65219) += tps65219_regulator.o
obj-$(CONFIG_REGULATOR_RZG2L_USBPHY) += rzg2l-usbphy-regulator.o
obj-$(CONFIG_$(PHASE_)DM_REGULATOR_CPCAP) += cpcap_regulator.o
+obj-$(CONFIG_DM_REGULATOR_MT6357) += mt6357_regulator.o
+obj-$(CONFIG_DM_REGULATOR_MT6359) += mt6359_regulator.o
diff --git a/drivers/power/regulator/cpcap_regulator.c b/drivers/power/regulator/cpcap_regulator.c
index 04cd6651374..0fbce57048c 100644
--- a/drivers/power/regulator/cpcap_regulator.c
+++ b/drivers/power/regulator/cpcap_regulator.c
@@ -55,7 +55,7 @@
#define CPCAP_REG(_reg, _assignment_reg, _assignment_mask, _mode_mask, \
_volt_mask, _volt_shft, _mode_val, _off_mode_val, _val_tbl, \
- _mode_cntr, _volt_trans_time, _turn_on_time, _bit_offset) { \
+ _mode_cntr, _volt_trans_time, _turn_on_time) { \
.reg = CPCAP_REG_##_reg, \
.assignment_reg = CPCAP_REG_##_assignment_reg, \
.assignment_mask = CPCAP_BIT_##_assignment_mask, \
@@ -69,60 +69,59 @@
.mode_cntr = _mode_cntr, \
.volt_trans_time = _volt_trans_time, \
.turn_on_time = _turn_on_time, \
- .bit_offset_from_cpcap_lowest_voltage = _bit_offset, \
}
static const struct cpcap_regulator_data tegra20_regulators[CPCAP_REGULATORS_COUNT] = {
/* BUCK */
[CPCAP_SW1] = CPCAP_REG(S1C1, ASSIGN2, SW1_SEL, 0x6f00, 0x007f,
- 0, 0x6800, 0, sw1_val_tbl, 0, 0, 1500, 0x0c),
+ 0, 0x6800, 0, sw_val_tbl, 0, 0, 1500),
[CPCAP_SW2] = CPCAP_REG(S2C1, ASSIGN2, SW2_SEL, 0x6f00, 0x007f,
- 0, 0x4804, 0, sw2_sw4_val_tbl, 0, 0, 1500, 0x18),
+ 0, 0x4804, 0, sw_val_tbl, 0, 0, 1500),
[CPCAP_SW3] = CPCAP_REG(S3C, ASSIGN2, SW3_SEL, 0x0578, 0x0003,
- 0, 0x043c, 0, sw3_val_tbl, 0, 0, 0, 0),
+ 0, 0x043c, 0, sw3_val_tbl, 0, 0, 0),
[CPCAP_SW4] = CPCAP_REG(S4C1, ASSIGN2, SW4_SEL, 0x6f00, 0x007f,
- 0, 0x4909, 0, sw2_sw4_val_tbl, 0, 0, 1500, 0x18),
+ 0, 0x4909, 0, sw_val_tbl, 0, 0, 1500),
[CPCAP_SW5] = CPCAP_REG(S5C, ASSIGN2, SW5_SEL, 0x0028, 0x0000,
- 0, 0x0020, 0, sw5_val_tbl, 0, 0, 1500, 0),
+ 0, 0x0020, 0, sw5_val_tbl, 0, 0, 1500),
[CPCAP_SW6] = CPCAP_REG(S6C, ASSIGN2, SW6_SEL, 0x0000, 0x0000,
- 0, 0, 0, unknown_val_tbl, 0, 0, 0, 0),
+ 0, 0, 0, unknown_val_tbl, 0, 0, 0),
/* LDO */
[CPCAP_VCAM] = CPCAP_REG(VCAMC, ASSIGN2, VCAM_SEL, 0x0087, 0x0030,
- 4, 0x7, 0, vcam_val_tbl, 0, 420, 1000, 0),
+ 4, 0x7, 0, vcam_val_tbl, 0, 420, 1000),
[CPCAP_VCSI] = CPCAP_REG(VCSIC, ASSIGN3, VCSI_SEL, 0x0047, 0x0010,
- 4, 0x7, 0, vcsi_val_tbl, 0, 350, 1000, 0),
+ 4, 0x7, 0, vcsi_val_tbl, 0, 350, 1000),
[CPCAP_VDAC] = CPCAP_REG(VDACC, ASSIGN3, VDAC_SEL, 0x0087, 0x0030,
- 4, 0x0, 0, vdac_val_tbl, 0, 420, 1000, 0),
+ 4, 0x0, 0, vdac_val_tbl, 0, 420, 1000),
[CPCAP_VDIG] = CPCAP_REG(VDIGC, ASSIGN2, VDIG_SEL, 0x0087, 0x0030,
- 4, 0x0, 0, vdig_val_tbl, 0, 420, 1000, 0),
+ 4, 0x0, 0, vdig_val_tbl, 0, 420, 1000),
[CPCAP_VFUSE] = CPCAP_REG(VFUSEC, ASSIGN3, VFUSE_SEL, 0x00a0, 0x000f,
- 0, 0x0, 0, vfuse_val_tbl, 0, 420, 1000, 0),
+ 0, 0x0, 0, vfuse_val_tbl, 0, 420, 1000),
[CPCAP_VHVIO] = CPCAP_REG(VHVIOC, ASSIGN3, VHVIO_SEL, 0x0017, 0x0000,
- 0, 0x2, 0, vhvio_val_tbl, 0, 0, 1000, 0),
+ 0, 0x2, 0, vhvio_val_tbl, 0, 0, 1000),
[CPCAP_VSDIO] = CPCAP_REG(VSDIOC, ASSIGN2, VSDIO_SEL, 0x0087, 0x0038,
- 3, 0x2, 0, vsdio_val_tbl, 0, 420, 1000, 0),
+ 3, 0x2, 0, vsdio_val_tbl, 0, 420, 1000),
[CPCAP_VPLL] = CPCAP_REG(VPLLC, ASSIGN3, VPLL_SEL, 0x0047, 0x0018,
- 3, 0x1, 0, vpll_val_tbl, 0, 420, 100, 0),
+ 3, 0x1, 0, vpll_val_tbl, 0, 420, 100),
[CPCAP_VRF1] = CPCAP_REG(VRF1C, ASSIGN3, VRF1_SEL, 0x00ac, 0x0002,
- 1, 0x0, 0, vrf1_val_tbl, 0, 10, 1000, 0),
+ 1, 0x0, 0, vrf1_val_tbl, 0, 10, 1000),
[CPCAP_VRF2] = CPCAP_REG(VRF2C, ASSIGN3, VRF2_SEL, 0x0023, 0x0008,
- 3, 0x0, 0, vrf2_val_tbl, 0, 10, 1000, 0),
+ 3, 0x0, 0, vrf2_val_tbl, 0, 10, 1000),
[CPCAP_VRFREF] = CPCAP_REG(VRFREFC, ASSIGN3, VRFREF_SEL, 0x0023, 0x0008,
- 3, 0x0, 0, vrfref_val_tbl, 0, 420, 100, 0),
+ 3, 0x0, 0, vrfref_val_tbl, 0, 420, 100),
[CPCAP_VWLAN1] = CPCAP_REG(VWLAN1C, ASSIGN3, VWLAN1_SEL, 0x0047, 0x0010,
- 4, 0x0, 0, vwlan1_val_tbl, 0, 420, 1000, 0),
+ 4, 0x0, 0, vwlan1_val_tbl, 0, 420, 1000),
[CPCAP_VWLAN2] = CPCAP_REG(VWLAN2C, ASSIGN3, VWLAN2_SEL, 0x020c, 0x00c0,
- 6, 0xd, 0, vwlan2_val_tbl, 0, 420, 1000, 0),
+ 6, 0xd, 0, vwlan2_val_tbl, 0, 420, 1000),
[CPCAP_VSIM] = CPCAP_REG(VSIMC, ASSIGN3, NONE, 0x0023, 0x0008,
- 3, 0x0, 0, vsim_val_tbl, 0, 420, 1000, 0),
+ 3, 0x0, 0, vsim_val_tbl, 0, 420, 1000),
[CPCAP_VSIMCARD] = CPCAP_REG(VSIMC, ASSIGN3, NONE, 0x1e80, 0x0008,
- 3, 0x1E00, 0, vsimcard_val_tbl, 0, 420, 1000, 0),
+ 3, 0x1E00, 0, vsimcard_val_tbl, 0, 420, 1000),
[CPCAP_VVIB] = CPCAP_REG(VVIBC, ASSIGN3, VVIB_SEL, 0x0001, 0x000c,
- 2, 0x1, 0, vvib_val_tbl, 0, 500, 500, 0),
+ 2, 0x1, 0, vvib_val_tbl, 0, 500, 500),
[CPCAP_VUSB] = CPCAP_REG(VUSBC, ASSIGN3, VUSB_SEL, 0x011c, 0x0040,
- 6, 0xc, 0, vusb_val_tbl, 0, 0, 1000, 0),
+ 6, 0xc, 0, vusb_val_tbl, 0, 0, 1000),
[CPCAP_VAUDIO] = CPCAP_REG(VAUDIOC, ASSIGN4, VAUDIO_SEL, 0x0016, 0x0001,
- 0, 0x5, 0, vaudio_val_tbl, 0, 0, 1000, 0),
+ 0, 0x5, 0, vaudio_val_tbl, 0, 0, 1000),
};
static int cpcap_regulator_get_value(struct udevice *dev)
@@ -139,7 +138,6 @@ static int cpcap_regulator_get_value(struct udevice *dev)
return 0;
value &= regulator->volt_mask;
- value -= regulator->bit_offset_from_cpcap_lowest_voltage;
return regulator->val_tbl[value >> volt_shift];
}
@@ -164,7 +162,6 @@ static int cpcap_regulator_set_value(struct udevice *dev, int uV)
value = regulator->val_tbl_sz;
value <<= volt_shift;
- value += regulator->bit_offset_from_cpcap_lowest_voltage;
}
ret = pmic_clrsetbits(dev->parent, regulator->reg, regulator->volt_mask,
@@ -232,7 +229,7 @@ static int cpcap_regulator_probe(struct udevice *dev)
for (id = 0; id < CPCAP_REGULATORS_COUNT; id++)
if (cpcap_regulator_to_name[id])
- if (!strcmp(dev->name, cpcap_regulator_to_name[id]))
+ if (!strcasecmp(dev->name, cpcap_regulator_to_name[id]))
break;
switch (id) {
diff --git a/drivers/power/regulator/mt6357_regulator.c b/drivers/power/regulator/mt6357_regulator.c
new file mode 100644
index 00000000000..533cc22b93a
--- /dev/null
+++ b/drivers/power/regulator/mt6357_regulator.c
@@ -0,0 +1,512 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * MT6357 regulator driver
+ *
+ * Copyright (c) 2026 BayLibre, SAS.
+ * Author: Julien Masson <[email protected]>
+ */
+
+#include <dm.h>
+#include <power/regulator.h>
+#include <power/mt6357.h>
+#include <power/pmic.h>
+
+enum mt6357_regulator_type {
+ MT6357_REG_TYPE_RANGE,
+ MT6357_REG_TYPE_TABLE,
+ MT6357_REG_TYPE_FIXED,
+};
+
+struct mt6357_linear_range {
+ unsigned int min;
+ unsigned int min_sel;
+ unsigned int max_sel;
+ unsigned int step;
+};
+
+struct mt6357_regulator_desc {
+ const char *name;
+ const char *of_match;
+ enum mt6357_regulator_type type;
+ int id;
+ unsigned int n_voltages;
+ const unsigned int *volt_table;
+ const struct mt6357_linear_range *linear_ranges;
+ int n_linear_ranges;
+ unsigned int min_uV;
+ unsigned int vsel_reg;
+ unsigned int vsel_mask;
+ unsigned int enable_reg;
+ unsigned int enable_mask;
+};
+
+struct mt6357_regulator_info {
+ struct mt6357_regulator_desc desc;
+ const u32 *index_table;
+ unsigned int n_table;
+ u32 vsel_shift;
+ u32 da_vsel_reg;
+ u32 da_vsel_mask;
+ u32 da_vsel_shift;
+};
+
+/* Initialize struct mt6357_linear_range for regulators */
+#define REGULATOR_LINEAR_RANGE(_min_uV, _min_sel, _max_sel, _step_uV) \
+{ \
+ .min = _min_uV, \
+ .min_sel = _min_sel, \
+ .max_sel = _max_sel, \
+ .step = _step_uV, \
+}
+
+#define MT6357_BUCK(match, vreg, min, max, step, \
+ volt_ranges, vosel_reg, vosel_mask, _da_vsel_mask) \
+ [MT6357_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .type = MT6357_REG_TYPE_RANGE, \
+ .id = MT6357_ID_##vreg, \
+ .n_voltages = ((max) - (min)) / (step) + 1, \
+ .linear_ranges = volt_ranges, \
+ .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
+ .vsel_reg = vosel_reg, \
+ .vsel_mask = vosel_mask, \
+ .enable_reg = MT6357_BUCK_##vreg##_CON0, \
+ .enable_mask = BIT(0), \
+ }, \
+ .da_vsel_reg = MT6357_BUCK_##vreg##_DBG0, \
+ .da_vsel_mask = _da_vsel_mask, \
+ .da_vsel_shift = 0, \
+ }
+
+#define MT6357_LDO(match, vreg, ldo_volt_table, \
+ ldo_index_table, enreg, vosel, \
+ vosel_mask) \
+ [MT6357_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .type = MT6357_REG_TYPE_TABLE, \
+ .id = MT6357_ID_##vreg, \
+ .n_voltages = ARRAY_SIZE(ldo_volt_table), \
+ .volt_table = ldo_volt_table, \
+ .vsel_reg = vosel, \
+ .vsel_mask = vosel_mask << 8, \
+ .enable_reg = enreg, \
+ .enable_mask = BIT(0), \
+ }, \
+ .index_table = ldo_index_table, \
+ .n_table = ARRAY_SIZE(ldo_index_table), \
+ }
+
+#define MT6357_LDO1(match, vreg, min, max, step, volt_ranges, \
+ enreg, vosel, vosel_mask) \
+ [MT6357_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .type = MT6357_REG_TYPE_RANGE, \
+ .id = MT6357_ID_##vreg, \
+ .n_voltages = ((max) - (min)) / (step) + 1, \
+ .linear_ranges = volt_ranges, \
+ .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
+ .vsel_reg = vosel, \
+ .vsel_mask = vosel_mask, \
+ .enable_reg = enreg, \
+ .enable_mask = BIT(0), \
+ }, \
+ .da_vsel_reg = MT6357_LDO_##vreg##_DBG0, \
+ .da_vsel_mask = 0x7f, \
+ .da_vsel_shift = 8, \
+ }
+
+#define MT6357_REG_FIXED(match, vreg, volt) \
+ [MT6357_ID_##vreg] = { \
+ .desc = { \
+ .name = #vreg, \
+ .of_match = of_match_ptr(match), \
+ .type = MT6357_REG_TYPE_FIXED, \
+ .id = MT6357_ID_##vreg, \
+ .n_voltages = 1, \
+ .enable_reg = MT6357_LDO_##vreg##_CON0, \
+ .enable_mask = BIT(0), \
+ .min_uV = volt, \
+ }, \
+ }
+
+static int mt6357_range_find_value(const struct mt6357_linear_range *r,
+ unsigned int sel,
+ unsigned int *val)
+{
+ if (!val || sel < r->min_sel || sel > r->max_sel)
+ return -EINVAL;
+
+ *val = r->min + r->step * (sel - r->min_sel);
+
+ return 0;
+}
+
+static int mt6357_range_find_selector(const struct mt6357_linear_range *r,
+ int val, unsigned int *sel)
+{
+ int num_vals = r->max_sel - r->min_sel + 1;
+ int ret = -EINVAL;
+
+ if (val >= r->min && val <= r->min + r->step * (num_vals - 1)) {
+ if (r->step) {
+ *sel = r->min_sel + ((val - r->min) / r->step);
+ ret = 0;
+ } else {
+ *sel = r->min_sel;
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+static int mt6357_get_enable(struct udevice *dev)
+{
+ struct mt6357_regulator_info *info = dev_get_priv(dev);
+ int ret;
+
+ ret = pmic_reg_read(dev->parent, info->desc.enable_reg);
+ if (ret < 0)
+ return ret;
+
+ return ret & info->desc.enable_mask ? true : false;
+}
+
+static int mt6357_set_enable(struct udevice *dev, bool enable)
+{
+ struct mt6357_regulator_info *info = dev_get_priv(dev);
+
+ return pmic_clrsetbits(dev->parent, info->desc.enable_reg,
+ info->desc.enable_mask,
+ enable ? info->desc.enable_mask : 0);
+}
+
+static int mt6357_get_value(struct udevice *dev)
+{
+ struct mt6357_regulator_info *info = dev_get_priv(dev);
+ unsigned int val_uV;
+ int selector, idx, ret;
+ const u32 *pvol;
+
+ switch (info->desc.type) {
+ case MT6357_REG_TYPE_RANGE:
+ selector = pmic_reg_read(dev->parent, info->da_vsel_reg);
+ if (selector < 0)
+ return selector;
+
+ selector = (selector & info->da_vsel_mask) >> info->da_vsel_shift;
+ ret = mt6357_range_find_value(info->desc.linear_ranges, selector, &val_uV);
+ if (ret < 0)
+ return ret;
+
+ return val_uV;
+ case MT6357_REG_TYPE_TABLE:
+ selector = pmic_reg_read(dev->parent, info->desc.vsel_reg);
+ if (selector < 0)
+ return selector;
+
+ selector = (selector & info->desc.vsel_mask) >> 8;
+ pvol = info->index_table;
+
+ for (idx = 0; idx < info->desc.n_voltages; idx++) {
+ if (pvol[idx] == selector)
+ return info->desc.volt_table[idx];
+ }
+
+ return -EINVAL;
+ case MT6357_REG_TYPE_FIXED:
+ return info->desc.min_uV;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mt6357_set_value(struct udevice *dev, int uvolt)
+{
+ struct mt6357_regulator_info *info = dev_get_priv(dev);
+ int selector, idx, ret;
+ const u32 *pvol;
+
+ switch (info->desc.type) {
+ case MT6357_REG_TYPE_RANGE:
+ ret = mt6357_range_find_selector(info->desc.linear_ranges, uvolt,
+ &selector);
+ if (ret < 0)
+ return ret;
+
+ return pmic_clrsetbits(dev->parent, info->desc.vsel_reg,
+ info->desc.vsel_mask, selector);
+ case MT6357_REG_TYPE_TABLE:
+ pvol = info->desc.volt_table;
+
+ for (idx = 0; idx < info->desc.n_voltages; idx++) {
+ if (pvol[idx] == uvolt) {
+ selector = info->index_table[idx];
+
+ return pmic_clrsetbits(dev->parent, info->desc.vsel_reg,
+ info->desc.vsel_mask, selector << 8);
+ }
+ }
+
+ return -EINVAL;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const int vxo22_voltages[] = {
+ 2200000,
+ 2400000,
+};
+
+static const int vefuse_voltages[] = {
+ 1200000,
+ 1300000,
+ 1500000,
+ 1800000,
+ 2800000,
+ 2900000,
+ 3000000,
+ 3300000,
+};
+
+static const int vcn33_voltages[] = {
+ 3300000,
+ 3400000,
+ 3500000,
+};
+
+static const int vcama_voltages[] = {
+ 2500000,
+ 2800000,
+};
+
+static const int vcamd_voltages[] = {
+ 1000000,
+ 1100000,
+ 1200000,
+ 1300000,
+ 1500000,
+ 1800000,
+};
+
+static const int vldo28_voltages[] = {
+ 2800000,
+ 3000000,
+};
+
+static const int vdram_voltages[] = {
+ 1100000,
+ 1200000,
+};
+
+static const int vsim_voltages[] = {
+ 1700000,
+ 1800000,
+ 2700000,
+ 3000000,
+ 3100000,
+};
+
+static const int vibr_voltages[] = {
+ 1200000,
+ 1300000,
+ 1500000,
+ 1800000,
+ 2000000,
+ 2800000,
+ 3000000,
+ 3300000,
+};
+
+static const int vmc_voltages[] = {
+ 1800000,
+ 2900000,
+ 3000000,
+ 3300000,
+};
+
+static const int vmch_voltages[] = {
+ 2900000,
+ 3000000,
+ 3300000,
+};
+
+static const int vemc_voltages[] = {
+ 2900000,
+ 3000000,
+ 3300000,
+};
+
+static const int vusb_voltages[] = {
+ 3000000,
+ 3100000,
+};
+
+static const int vmc_idx[] = {
+ 4, 10, 11, 13,
+};
+
+static const int vmch_idx[] = {
+ 2, 3, 5,
+};
+
+static const int vemc_idx[] = {
+ 2, 3, 5,
+};
+
+static const int vusb_idx[] = {
+ 3, 4,
+};
+
+static const int vxo22_idx[] = {
+ 0, 2,
+};
+
+static const int vefuse_idx[] = {
+ 0, 1, 2, 4, 9, 10, 11, 13,
+};
+
+static const int vcn33_idx[] = {
+ 1, 2, 3,
+};
+
+static const int vcama_idx[] = {
+ 7, 10,
+};
+
+static const int vcamd_idx[] = {
+ 4, 5, 6, 7, 9, 12,
+};
+
+static const int vldo28_idx[] = {
+ 1, 3,
+};
+
+static const int vdram_idx[] = {
+ 1, 2,
+};
+
+static const int vsim_idx[] = {
+ 3, 4, 8, 11, 12,
+};
+
+static const int vibr_idx[] = {
+ 0, 1, 2, 4, 5, 9, 11, 13,
+};
+
+static const struct mt6357_linear_range buck_volt_range1[] = {
+ REGULATOR_LINEAR_RANGE(518750, 0, 0x7f, 6250),
+};
+
+static const struct mt6357_linear_range buck_volt_range2[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 6250),
+};
+
+static const struct mt6357_linear_range buck_volt_range3[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),
+};
+
+static const struct mt6357_linear_range buck_volt_range4[] = {
+ REGULATOR_LINEAR_RANGE(1200000, 0, 0x7f, 12500),
+};
+
+/* The array is indexed by id(MT6357_ID_XXX) */
+static struct mt6357_regulator_info mt6357_regulators[] = {
+ /* Bucks */
+ MT6357_BUCK("buck-vcore", VCORE, 518750, 1312500, 6250,
+ buck_volt_range1, MT6357_BUCK_VCORE_ELR0, 0x7f, 0x7f),
+ MT6357_BUCK("buck-vproc", VPROC, 518750, 1312500, 6250,
+ buck_volt_range1, MT6357_BUCK_VPROC_ELR0, 0x7f, 0x7f),
+ MT6357_BUCK("buck-vmodem", VMODEM, 500000, 1293750, 6250,
+ buck_volt_range2, MT6357_BUCK_VMODEM_ELR0, 0x7f, 0x7f),
+ MT6357_BUCK("buck-vpa", VPA, 500000, 3650000, 50000,
+ buck_volt_range3, MT6357_BUCK_VPA_CON1, 0x3f, 0x3f),
+ MT6357_BUCK("buck-vs1", VS1, 1200000, 2787500, 12500,
+ buck_volt_range4, MT6357_BUCK_VS1_ELR0, 0x7f, 0x7f),
+
+ /* LDOs */
+ MT6357_LDO("ldo-vcama", VCAMA, vcama_voltages, vcama_idx,
+ MT6357_LDO_VCAMA_CON0, MT6357_VCAMA_ANA_CON0, 0xf),
+ MT6357_LDO("ldo-vcamd", VCAMD, vcamd_voltages, vcamd_idx,
+ MT6357_LDO_VCAMD_CON0, MT6357_VCAMD_ANA_CON0, 0xf),
+ MT6357_LDO("ldo-vcn33-bt", VCN33_BT, vcn33_voltages, vcn33_idx,
+ MT6357_LDO_VCN33_CON0_0, MT6357_VCN33_ANA_CON0, 0x3),
+ MT6357_LDO("ldo-vcn33-wifi", VCN33_WIFI, vcn33_voltages, vcn33_idx,
+ MT6357_LDO_VCN33_CON0_1, MT6357_VCN33_ANA_CON0, 0x3),
+ MT6357_LDO("ldo-vdram", VDRAM, vdram_voltages, vdram_idx,
+ MT6357_LDO_VDRAM_CON0, MT6357_VDRAM_ELR_2, 0x3),
+ MT6357_LDO("ldo-vefuse", VEFUSE, vefuse_voltages, vefuse_idx,
+ MT6357_LDO_VEFUSE_CON0, MT6357_VEFUSE_ANA_CON0, 0xf),
+ MT6357_LDO("ldo-vemc", VEMC, vemc_voltages, vemc_idx,
+ MT6357_LDO_VEMC_CON0, MT6357_VEMC_ANA_CON0, 0x7),
+ MT6357_LDO("ldo-vibr", VIBR, vibr_voltages, vibr_idx,
+ MT6357_LDO_VIBR_CON0, MT6357_VIBR_ANA_CON0, 0xf),
+ MT6357_LDO("ldo-vldo28", VLDO28, vldo28_voltages, vldo28_idx,
+ MT6357_LDO_VLDO28_CON0_0, MT6357_VLDO28_ANA_CON0, 0x3),
+ MT6357_LDO("ldo-vmc", VMC, vmc_voltages, vmc_idx,
+ MT6357_LDO_VMC_CON0, MT6357_VMC_ANA_CON0, 0xf),
+ MT6357_LDO("ldo-vmch", VMCH, vmch_voltages, vmch_idx,
+ MT6357_LDO_VMCH_CON0, MT6357_VMCH_ANA_CON0, 0x7),
+ MT6357_LDO("ldo-vsim1", VSIM1, vsim_voltages, vsim_idx,
+ MT6357_LDO_VSIM1_CON0, MT6357_VSIM1_ANA_CON0, 0xf),
+ MT6357_LDO("ldo-vsim2", VSIM2, vsim_voltages, vsim_idx,
+ MT6357_LDO_VSIM2_CON0, MT6357_VSIM2_ANA_CON0, 0xf),
+ MT6357_LDO("ldo-vusb33", VUSB33, vusb_voltages, vusb_idx,
+ MT6357_LDO_VUSB33_CON0_0, MT6357_VUSB33_ANA_CON0, 0x7),
+ MT6357_LDO("ldo-vxo22", VXO22, vxo22_voltages, vxo22_idx,
+ MT6357_LDO_VXO22_CON0, MT6357_VXO22_ANA_CON0, 0x3),
+
+ MT6357_LDO1("ldo-vsram-proc", VSRAM_PROC, 518750, 1312500, 6250,
+ buck_volt_range1, MT6357_LDO_VSRAM_PROC_CON0,
+ MT6357_LDO_VSRAM_CON0, 0x7f),
+ MT6357_LDO1("ldo-vsram-others", VSRAM_OTHERS, 518750, 1312500, 6250,
+ buck_volt_range1, MT6357_LDO_VSRAM_OTHERS_CON0,
+ MT6357_LDO_VSRAM_CON1, 0x7f),
+
+ MT6357_REG_FIXED("ldo-vaud28", VAUD28, 2800000),
+ MT6357_REG_FIXED("ldo-vaux18", VAUX18, 1800000),
+ MT6357_REG_FIXED("ldo-vcamio18", VCAMIO, 1800000),
+ MT6357_REG_FIXED("ldo-vcn18", VCN18, 1800000),
+ MT6357_REG_FIXED("ldo-vcn28", VCN28, 2800000),
+ MT6357_REG_FIXED("ldo-vfe28", VFE28, 2800000),
+ MT6357_REG_FIXED("ldo-vio18", VIO18, 1800000),
+ MT6357_REG_FIXED("ldo-vio28", VIO28, 2800000),
+ MT6357_REG_FIXED("ldo-vrf12", VRF12, 1200000),
+ MT6357_REG_FIXED("ldo-vrf18", VRF18, 1800000),
+};
+
+static int mt6357_regulator_probe(struct udevice *dev)
+{
+ struct mt6357_regulator_info *priv = dev_get_priv(dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mt6357_regulators); i++) {
+ if (!strcmp(dev->name, mt6357_regulators[i].desc.of_match)) {
+ *priv = mt6357_regulators[i];
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
+static const struct dm_regulator_ops mt6357_regulator_ops = {
+ .get_value = mt6357_get_value,
+ .set_value = mt6357_set_value,
+ .get_enable = mt6357_get_enable,
+ .set_enable = mt6357_set_enable,
+};
+
+U_BOOT_DRIVER(mt6357_regulator) = {
+ .name = MT6357_REGULATOR_DRIVER,
+ .id = UCLASS_REGULATOR,
+ .ops = &mt6357_regulator_ops,
+ .probe = mt6357_regulator_probe,
+ .priv_auto = sizeof(struct mt6357_regulator_info),
+};
diff --git a/drivers/power/regulator/mt6359_regulator.c b/drivers/power/regulator/mt6359_regulator.c
new file mode 100644
index 00000000000..cdafcfcb25e
--- /dev/null
+++ b/drivers/power/regulator/mt6359_regulator.c
@@ -0,0 +1,711 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026 MediaTek Inc. All Rights Reserved.
+ * Author: Bo-Chen Chen <[email protected]>
+ */
+
+#include <dm.h>
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <power/mt6359.h>
+#include <power/mt6359p.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+
+#include <dm/device.h>
+#include <dm/device_compat.h>
+
+enum mt6359_regulator_type {
+ MT6359_REG_TYPE_LINEAR,
+ MT6359_REG_TYPE_TABLE,
+ MT6359_REG_TYPE_FIXED,
+ MT6359_REG_TYPE_VEMC,
+};
+
+struct regulator_desc {
+ const char *name;
+ const char *of_match;
+ enum mt6359_regulator_type type;
+ int id;
+ unsigned int uV_step;
+ unsigned int n_voltages;
+ const unsigned int *volt_table;
+ unsigned int min_uV;
+ unsigned int vsel_reg;
+ unsigned int vsel_mask;
+ unsigned int enable_reg;
+ unsigned int enable_mask;
+ unsigned int fixed_uV;
+};
+
+/*
+ * MT6359 regulators' information
+ *
+ * @desc: standard fields of regulator description.
+ * @status_reg: for query status of regulators.
+ * @qi: Mask for query enable signal status of regulators.
+ * @modeset_reg: for operating AUTO/PWM mode register.
+ * @modeset_mask: MASK for operating modeset register.
+ */
+struct mt6359_regulator_info {
+ struct regulator_desc desc;
+ u32 status_reg;
+ u32 qi;
+ u32 modeset_reg;
+ u32 modeset_mask;
+ u32 lp_mode_reg;
+ u32 lp_mode_mask;
+};
+
+#define MT6359_BUCK(match, _name, _min, _max, _step, \
+ _enable_reg, _status_reg, \
+ _vsel_reg, _vsel_mask, \
+ _lp_mode_reg, _lp_mode_shift, \
+ _modeset_reg, _modeset_shift) \
+[MT6359_ID_##_name] = { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(match), \
+ .type = MT6359_REG_TYPE_LINEAR, \
+ .id = MT6359_ID_##_name, \
+ .uV_step = (_step), \
+ .n_voltages = ((_max) - (_min)) / (_step) + 1, \
+ .min_uV = (_min), \
+ .vsel_reg = _vsel_reg, \
+ .vsel_mask = _vsel_mask, \
+ .enable_reg = _enable_reg, \
+ .enable_mask = BIT(0), \
+ }, \
+ .status_reg = _status_reg, \
+ .qi = BIT(0), \
+ .lp_mode_reg = _lp_mode_reg, \
+ .lp_mode_mask = BIT(_lp_mode_shift), \
+ .modeset_reg = _modeset_reg, \
+ .modeset_mask = BIT(_modeset_shift), \
+}
+
+#define MT6359_LDO_LINEAR(match, _name, _min, _max, _step, \
+ _enable_reg, _status_reg, _vsel_reg, _vsel_mask) \
+[MT6359_ID_##_name] = { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(match), \
+ .type = MT6359_REG_TYPE_LINEAR, \
+ .id = MT6359_ID_##_name, \
+ .uV_step = (_step), \
+ .n_voltages = ((_max) - (_min)) / (_step) + 1, \
+ .min_uV = (_min), \
+ .vsel_reg = _vsel_reg, \
+ .vsel_mask = _vsel_mask, \
+ .enable_reg = _enable_reg, \
+ .enable_mask = BIT(0), \
+ }, \
+ .status_reg = _status_reg, \
+ .qi = BIT(0), \
+}
+
+#define MT6359_LDO(match, _name, _tmp_volt_table, \
+ _enable_reg, _enable_mask, _status_reg, \
+ _vsel_reg, _vsel_mask, _en_delay) \
+[MT6359_ID_##_name] = { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(match), \
+ .type = MT6359_REG_TYPE_TABLE, \
+ .id = MT6359_ID_##_name, \
+ .n_voltages = ARRAY_SIZE(_tmp_volt_table), \
+ .volt_table = _tmp_volt_table, \
+ .vsel_reg = _vsel_reg, \
+ .vsel_mask = _vsel_mask, \
+ .enable_reg = _enable_reg, \
+ .enable_mask = BIT(_enable_mask), \
+ }, \
+ .status_reg = _status_reg, \
+ .qi = BIT(0), \
+}
+
+#define MT6359_REG_FIXED(match, _name, _enable_reg, \
+ _status_reg, _fixed_volt) \
+[MT6359_ID_##_name] = { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(match), \
+ .type = MT6359_REG_TYPE_FIXED, \
+ .id = MT6359_ID_##_name, \
+ .n_voltages = 1, \
+ .enable_reg = _enable_reg, \
+ .enable_mask = BIT(0), \
+ .fixed_uV = (_fixed_volt), \
+ }, \
+ .status_reg = _status_reg, \
+ .qi = BIT(0), \
+}
+
+#define MT6359P_LDO1(match, _name, _type, _tmp_volt_table, \
+ _enable_reg, _enable_mask, _status_reg, \
+ _vsel_reg, _vsel_mask) \
+[MT6359_ID_##_name] = { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(match), \
+ .type = _type, \
+ .id = MT6359_ID_##_name, \
+ .n_voltages = ARRAY_SIZE(_tmp_volt_table), \
+ .volt_table = _tmp_volt_table, \
+ .vsel_reg = _vsel_reg, \
+ .vsel_mask = _vsel_mask, \
+ .enable_reg = _enable_reg, \
+ .enable_mask = BIT(_enable_mask), \
+ }, \
+ .status_reg = _status_reg, \
+ .qi = BIT(0), \
+}
+
+static const unsigned int vsim1_voltages[] = {
+ 0, 0, 0, 1700000, 1800000, 0, 0, 0, 2700000, 0, 0, 3000000, 3100000,
+};
+
+static const unsigned int vibr_voltages[] = {
+ 1200000, 1300000, 1500000, 0, 1800000, 2000000, 0, 0, 2700000, 2800000,
+ 0, 3000000, 0, 3300000,
+};
+
+static const unsigned int vrf12_voltages[] = {
+ 0, 0, 1100000, 1200000, 1300000,
+};
+
+static const unsigned int volt18_voltages[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1700000, 1800000, 1900000,
+};
+
+static const unsigned int vcn13_voltages[] = {
+ 900000, 1000000, 0, 1200000, 1300000,
+};
+
+static const unsigned int vcn33_voltages[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2800000, 0, 0, 0, 3300000, 3400000, 3500000,
+};
+
+static const unsigned int vefuse_voltages[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1700000, 1800000, 1900000, 2000000,
+};
+
+static const unsigned int vxo22_voltages[] = {
+ 1800000, 0, 0, 0, 2200000,
+};
+
+static const unsigned int vrfck_voltages_1[] = {
+ 1240000, 1600000,
+};
+
+static const unsigned int vio28_voltages[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2800000, 2900000, 3000000, 3100000, 3300000,
+};
+
+static const unsigned int vemc_voltages_1[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 2500000, 2800000, 2900000, 3000000, 3100000,
+ 3300000,
+};
+
+static const unsigned int va12_voltages[] = {
+ 0, 0, 0, 0, 0, 0, 1200000, 1300000,
+};
+
+static const unsigned int va09_voltages[] = {
+ 0, 0, 800000, 900000, 0, 0, 1200000,
+};
+
+static const unsigned int vrf18_voltages[] = {
+ 0, 0, 0, 0, 0, 1700000, 1800000, 1810000,
+};
+
+static const unsigned int vbbck_voltages[] = {
+ 0, 0, 0, 0, 1100000, 0, 0, 0, 1150000, 0, 0, 0, 1200000,
+};
+
+static const unsigned int vsim2_voltages[] = {
+ 0, 0, 0, 1700000, 1800000, 0, 0, 0, 2700000, 0, 0, 3000000, 3100000,
+};
+
+static int mt6359_set_voltage_sel_regmap(struct udevice *dev,
+ struct mt6359_regulator_info *info,
+ unsigned int sel)
+{
+ sel <<= ffs(info->desc.vsel_mask) - 1;
+
+ return pmic_clrsetbits(dev->parent, info->desc.vsel_reg,
+ info->desc.vsel_mask, sel);
+}
+
+static int mt6359p_vemc_set_voltage_sel(struct udevice *dev,
+ struct mt6359_regulator_info *info, unsigned int sel)
+{
+ int ret;
+
+ sel <<= ffs(info->desc.vsel_mask) - 1;
+ ret = pmic_reg_write(dev->parent, MT6359P_TMA_KEY_ADDR, MT6359P_TMA_KEY);
+ if (ret)
+ return ret;
+
+ ret = pmic_reg_read(dev->parent, MT6359P_VM_MODE_ADDR);
+ if (ret < 0)
+ return ret;
+
+ switch (ret) {
+ case 0:
+ /* If HW trapping is 0, use VEMC_VOSEL_0 */
+ ret = pmic_clrsetbits(dev->parent, info->desc.vsel_reg,
+ info->desc.vsel_mask, sel);
+ if (ret)
+ return ret;
+
+ break;
+ case 1:
+ /* If HW trapping is 1, use VEMC_VOSEL_1 */
+ ret = pmic_clrsetbits(dev->parent, info->desc.vsel_reg + 0x2,
+ info->desc.vsel_mask, sel);
+ if (ret)
+ return ret;
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return pmic_reg_write(dev->parent, MT6359P_TMA_KEY_ADDR, 0);
+}
+
+static int mt6359_get_voltage_sel(struct udevice *dev, struct mt6359_regulator_info *info)
+{
+ int selector;
+
+ selector = pmic_reg_read(dev->parent, info->desc.vsel_reg);
+ if (selector < 0)
+ return selector;
+
+ selector &= info->desc.vsel_mask;
+ selector >>= ffs(info->desc.vsel_mask) - 1;
+
+ return selector;
+}
+
+static int mt6359p_vemc_get_voltage_sel(struct udevice *dev, struct mt6359_regulator_info *info)
+{
+ int selector;
+
+ switch (pmic_reg_read(dev->parent, MT6359P_VM_MODE_ADDR)) {
+ case 0:
+ /* If HW trapping is 0, use VEMC_VOSEL_0 */
+ selector = pmic_reg_read(dev->parent, info->desc.vsel_reg);
+ break;
+ case 1:
+ /* If HW trapping is 1, use VEMC_VOSEL_1 */
+ selector = pmic_reg_read(dev->parent, info->desc.vsel_reg + 0x2);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (selector < 0)
+ return selector;
+
+ selector &= info->desc.vsel_mask;
+ selector >>= ffs(info->desc.vsel_mask) - 1;
+
+ return selector;
+}
+
+static int mt6359_get_enable(struct udevice *dev)
+{
+ struct mt6359_regulator_info *info = dev_get_priv(dev);
+ int ret;
+
+ ret = pmic_reg_read(dev->parent, info->desc.enable_reg);
+ if (ret < 0)
+ return ret;
+
+ return ret & info->desc.enable_mask ? true : false;
+}
+
+static int mt6359_set_enable(struct udevice *dev, bool enable)
+{
+ struct mt6359_regulator_info *info = dev_get_priv(dev);
+
+ return pmic_clrsetbits(dev->parent, info->desc.enable_reg,
+ info->desc.enable_mask,
+ enable ? info->desc.enable_mask : 0);
+}
+
+static int mt6359_get_value(struct udevice *dev)
+{
+ struct mt6359_regulator_info *info = dev_get_priv(dev);
+ int selector;
+
+ switch (info->desc.type) {
+ case MT6359_REG_TYPE_LINEAR:
+ /* Get selection */
+ selector = mt6359_get_voltage_sel(dev, info);
+ if (selector < 0)
+ return -EINVAL;
+
+ /* Get voltage value */
+ if (selector >= info->desc.n_voltages)
+ return -EINVAL;
+
+ return info->desc.min_uV + (info->desc.uV_step * selector);
+ case MT6359_REG_TYPE_TABLE:
+ /* Get selection */
+ selector = mt6359_get_voltage_sel(dev, info);
+ if (selector < 0)
+ return -EINVAL;
+
+ /* Get voltage value */
+ if (!info->desc.volt_table) {
+ dev_err(dev, "invalid voltage table for %s\n", info->desc.name);
+ return -EINVAL;
+ }
+
+ if (selector >= info->desc.n_voltages)
+ return -EINVAL;
+
+ return info->desc.volt_table[selector];
+ case MT6359_REG_TYPE_FIXED:
+ return info->desc.fixed_uV;
+ case MT6359_REG_TYPE_VEMC:
+ /* Get selection */
+ selector = mt6359p_vemc_get_voltage_sel(dev, info);
+ if (selector < 0)
+ return -EINVAL;
+
+ /* Get voltage value */
+ if (!info->desc.volt_table) {
+ dev_err(dev, "invalid voltage table for %s\n", info->desc.name);
+ return -EINVAL;
+ }
+
+ if (selector >= info->desc.n_voltages)
+ return -EINVAL;
+
+ return info->desc.volt_table[selector];
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mt6359_set_value(struct udevice *dev, int uvolt)
+{
+ struct mt6359_regulator_info *info = dev_get_priv(dev);
+ int selector;
+ int i;
+
+ switch (info->desc.type) {
+ case MT6359_REG_TYPE_LINEAR:
+ /* Find selection */
+ if (uvolt < info->desc.min_uV)
+ return -EINVAL;
+ selector = DIV_ROUND_UP(uvolt - info->desc.min_uV, info->desc.uV_step);
+ if (selector < 0)
+ return -EINVAL;
+
+ /* Set selection */
+ return mt6359_set_voltage_sel_regmap(dev, info, selector);
+ case MT6359_REG_TYPE_TABLE:
+ /* Find selection */
+ for (i = 0; i < info->desc.n_voltages; i++) {
+ if (info->desc.volt_table[i] == uvolt)
+ return mt6359_set_voltage_sel_regmap(dev, info, i);
+ }
+
+ return -EINVAL;
+ case MT6359_REG_TYPE_VEMC:
+ /* Find selection */
+ for (i = 0; i < info->desc.n_voltages; i++) {
+ if (info->desc.volt_table[i] == uvolt)
+ return mt6359p_vemc_set_voltage_sel(dev, info, i);
+ }
+
+ return -EINVAL;
+ default:
+ return -EINVAL;
+ }
+}
+
+static struct mt6359_regulator_info mt6359p_regulators[] = {
+ MT6359_BUCK("buck_vs1", VS1, 800000, 2200000, 12500,
+ MT6359_RG_BUCK_VS1_EN_ADDR,
+ MT6359_DA_VS1_EN_ADDR, MT6359_RG_BUCK_VS1_VOSEL_ADDR,
+ MT6359_RG_BUCK_VS1_VOSEL_MASK <<
+ MT6359_RG_BUCK_VS1_VOSEL_SHIFT,
+ MT6359_RG_BUCK_VS1_LP_ADDR, MT6359_RG_BUCK_VS1_LP_SHIFT,
+ MT6359_RG_VS1_FPWM_ADDR, MT6359_RG_VS1_FPWM_SHIFT),
+ MT6359_BUCK("buck_vgpu11", VGPU11, 400000, 1193750, 6250,
+ MT6359_RG_BUCK_VGPU11_EN_ADDR,
+ MT6359_DA_VGPU11_EN_ADDR, MT6359P_RG_BUCK_VGPU11_VOSEL_ADDR,
+ MT6359_RG_BUCK_VGPU11_VOSEL_MASK <<
+ MT6359_RG_BUCK_VGPU11_VOSEL_SHIFT,
+ MT6359_RG_BUCK_VGPU11_LP_ADDR,
+ MT6359_RG_BUCK_VGPU11_LP_SHIFT,
+ MT6359_RG_VGPU11_FCCM_ADDR, MT6359_RG_VGPU11_FCCM_SHIFT),
+ MT6359_BUCK("buck_vmodem", VMODEM, 400000, 1100000, 6250,
+ MT6359_RG_BUCK_VMODEM_EN_ADDR,
+ MT6359_DA_VMODEM_EN_ADDR, MT6359_RG_BUCK_VMODEM_VOSEL_ADDR,
+ MT6359_RG_BUCK_VMODEM_VOSEL_MASK <<
+ MT6359_RG_BUCK_VMODEM_VOSEL_SHIFT,
+ MT6359_RG_BUCK_VMODEM_LP_ADDR,
+ MT6359_RG_BUCK_VMODEM_LP_SHIFT,
+ MT6359_RG_VMODEM_FCCM_ADDR, MT6359_RG_VMODEM_FCCM_SHIFT),
+ MT6359_BUCK("buck_vpu", VPU, 400000, 1193750, 6250,
+ MT6359_RG_BUCK_VPU_EN_ADDR,
+ MT6359_DA_VPU_EN_ADDR, MT6359_RG_BUCK_VPU_VOSEL_ADDR,
+ MT6359_RG_BUCK_VPU_VOSEL_MASK <<
+ MT6359_RG_BUCK_VPU_VOSEL_SHIFT,
+ MT6359_RG_BUCK_VPU_LP_ADDR, MT6359_RG_BUCK_VPU_LP_SHIFT,
+ MT6359_RG_VPU_FCCM_ADDR, MT6359_RG_VPU_FCCM_SHIFT),
+ MT6359_BUCK("buck_vcore", VCORE, 506250, 1300000, 6250,
+ MT6359_RG_BUCK_VCORE_EN_ADDR,
+ MT6359_DA_VCORE_EN_ADDR, MT6359P_RG_BUCK_VCORE_VOSEL_ADDR,
+ MT6359_RG_BUCK_VCORE_VOSEL_MASK <<
+ MT6359_RG_BUCK_VCORE_VOSEL_SHIFT,
+ MT6359_RG_BUCK_VCORE_LP_ADDR, MT6359_RG_BUCK_VCORE_LP_SHIFT,
+ MT6359_RG_VCORE_FCCM_ADDR, MT6359_RG_VCORE_FCCM_SHIFT),
+ MT6359_BUCK("buck_vs2", VS2, 800000, 1600000, 12500,
+ MT6359_RG_BUCK_VS2_EN_ADDR,
+ MT6359_DA_VS2_EN_ADDR, MT6359_RG_BUCK_VS2_VOSEL_ADDR,
+ MT6359_RG_BUCK_VS2_VOSEL_MASK <<
+ MT6359_RG_BUCK_VS2_VOSEL_SHIFT,
+ MT6359_RG_BUCK_VS2_LP_ADDR, MT6359_RG_BUCK_VS2_LP_SHIFT,
+ MT6359_RG_VS2_FPWM_ADDR, MT6359_RG_VS2_FPWM_SHIFT),
+ MT6359_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,
+ MT6359_RG_BUCK_VPA_EN_ADDR,
+ MT6359_DA_VPA_EN_ADDR, MT6359_RG_BUCK_VPA_VOSEL_ADDR,
+ MT6359_RG_BUCK_VPA_VOSEL_MASK <<
+ MT6359_RG_BUCK_VPA_VOSEL_SHIFT,
+ MT6359_RG_BUCK_VPA_LP_ADDR, MT6359_RG_BUCK_VPA_LP_SHIFT,
+ MT6359_RG_VPA_MODESET_ADDR, MT6359_RG_VPA_MODESET_SHIFT),
+ MT6359_BUCK("buck_vproc2", VPROC2, 400000, 1193750, 6250,
+ MT6359_RG_BUCK_VPROC2_EN_ADDR,
+ MT6359_DA_VPROC2_EN_ADDR, MT6359_RG_BUCK_VPROC2_VOSEL_ADDR,
+ MT6359_RG_BUCK_VPROC2_VOSEL_MASK <<
+ MT6359_RG_BUCK_VPROC2_VOSEL_SHIFT,
+ MT6359_RG_BUCK_VPROC2_LP_ADDR,
+ MT6359_RG_BUCK_VPROC2_LP_SHIFT,
+ MT6359_RG_VPROC2_FCCM_ADDR, MT6359_RG_VPROC2_FCCM_SHIFT),
+ MT6359_BUCK("buck_vproc1", VPROC1, 400000, 1193750, 6250,
+ MT6359_RG_BUCK_VPROC1_EN_ADDR,
+ MT6359_DA_VPROC1_EN_ADDR, MT6359_RG_BUCK_VPROC1_VOSEL_ADDR,
+ MT6359_RG_BUCK_VPROC1_VOSEL_MASK <<
+ MT6359_RG_BUCK_VPROC1_VOSEL_SHIFT,
+ MT6359_RG_BUCK_VPROC1_LP_ADDR,
+ MT6359_RG_BUCK_VPROC1_LP_SHIFT,
+ MT6359_RG_VPROC1_FCCM_ADDR, MT6359_RG_VPROC1_FCCM_SHIFT),
+ MT6359_BUCK("buck_vgpu11_sshub", VGPU11_SSHUB, 400000, 1193750, 6250,
+ MT6359P_RG_BUCK_VGPU11_SSHUB_EN_ADDR,
+ MT6359_DA_VGPU11_EN_ADDR,
+ MT6359P_RG_BUCK_VGPU11_SSHUB_VOSEL_ADDR,
+ MT6359P_RG_BUCK_VGPU11_SSHUB_VOSEL_MASK <<
+ MT6359P_RG_BUCK_VGPU11_SSHUB_VOSEL_SHIFT,
+ MT6359_RG_BUCK_VGPU11_LP_ADDR,
+ MT6359_RG_BUCK_VGPU11_LP_SHIFT,
+ MT6359_RG_VGPU11_FCCM_ADDR, MT6359_RG_VGPU11_FCCM_SHIFT),
+ MT6359_REG_FIXED("ldo_vaud18", VAUD18, MT6359P_RG_LDO_VAUD18_EN_ADDR,
+ MT6359P_DA_VAUD18_B_EN_ADDR, 1800000),
+ MT6359_LDO("ldo_vsim1", VSIM1, vsim1_voltages,
+ MT6359P_RG_LDO_VSIM1_EN_ADDR, MT6359P_RG_LDO_VSIM1_EN_SHIFT,
+ MT6359P_DA_VSIM1_B_EN_ADDR, MT6359P_RG_VSIM1_VOSEL_ADDR,
+ MT6359_RG_VSIM1_VOSEL_MASK << MT6359_RG_VSIM1_VOSEL_SHIFT,
+ 480),
+ MT6359_LDO("ldo_vibr", VIBR, vibr_voltages,
+ MT6359P_RG_LDO_VIBR_EN_ADDR, MT6359P_RG_LDO_VIBR_EN_SHIFT,
+ MT6359P_DA_VIBR_B_EN_ADDR, MT6359P_RG_VIBR_VOSEL_ADDR,
+ MT6359_RG_VIBR_VOSEL_MASK << MT6359_RG_VIBR_VOSEL_SHIFT,
+ 240),
+ MT6359_LDO("ldo_vrf12", VRF12, vrf12_voltages,
+ MT6359P_RG_LDO_VRF12_EN_ADDR, MT6359P_RG_LDO_VRF12_EN_SHIFT,
+ MT6359P_DA_VRF12_B_EN_ADDR, MT6359P_RG_VRF12_VOSEL_ADDR,
+ MT6359_RG_VRF12_VOSEL_MASK << MT6359_RG_VRF12_VOSEL_SHIFT,
+ 480),
+ MT6359_REG_FIXED("ldo_vusb", VUSB, MT6359P_RG_LDO_VUSB_EN_0_ADDR,
+ MT6359P_DA_VUSB_B_EN_ADDR, 3000000),
+ MT6359_LDO_LINEAR("ldo_vsram_proc2", VSRAM_PROC2, 500000, 1293750, 6250,
+ MT6359P_RG_LDO_VSRAM_PROC2_EN_ADDR,
+ MT6359P_DA_VSRAM_PROC2_B_EN_ADDR,
+ MT6359P_RG_LDO_VSRAM_PROC2_VOSEL_ADDR,
+ MT6359_RG_LDO_VSRAM_PROC2_VOSEL_MASK <<
+ MT6359_RG_LDO_VSRAM_PROC2_VOSEL_SHIFT),
+ MT6359_LDO("ldo_vio18", VIO18, volt18_voltages,
+ MT6359P_RG_LDO_VIO18_EN_ADDR, MT6359P_RG_LDO_VIO18_EN_SHIFT,
+ MT6359P_DA_VIO18_B_EN_ADDR, MT6359P_RG_VIO18_VOSEL_ADDR,
+ MT6359_RG_VIO18_VOSEL_MASK << MT6359_RG_VIO18_VOSEL_SHIFT,
+ 960),
+ MT6359_LDO("ldo_vcamio", VCAMIO, volt18_voltages,
+ MT6359P_RG_LDO_VCAMIO_EN_ADDR,
+ MT6359P_RG_LDO_VCAMIO_EN_SHIFT,
+ MT6359P_DA_VCAMIO_B_EN_ADDR, MT6359P_RG_VCAMIO_VOSEL_ADDR,
+ MT6359_RG_VCAMIO_VOSEL_MASK << MT6359_RG_VCAMIO_VOSEL_SHIFT,
+ 1290),
+ MT6359_REG_FIXED("ldo_vcn18", VCN18, MT6359P_RG_LDO_VCN18_EN_ADDR,
+ MT6359P_DA_VCN18_B_EN_ADDR, 1800000),
+ MT6359_REG_FIXED("ldo_vfe28", VFE28, MT6359P_RG_LDO_VFE28_EN_ADDR,
+ MT6359P_DA_VFE28_B_EN_ADDR, 2800000),
+ MT6359_LDO("ldo_vcn13", VCN13, vcn13_voltages,
+ MT6359P_RG_LDO_VCN13_EN_ADDR, MT6359P_RG_LDO_VCN13_EN_SHIFT,
+ MT6359P_DA_VCN13_B_EN_ADDR, MT6359P_RG_VCN13_VOSEL_ADDR,
+ MT6359_RG_VCN13_VOSEL_MASK << MT6359_RG_VCN13_VOSEL_SHIFT,
+ 240),
+ MT6359_LDO("ldo_vcn33_1_bt", VCN33_1_BT, vcn33_voltages,
+ MT6359P_RG_LDO_VCN33_1_EN_0_ADDR,
+ MT6359_RG_LDO_VCN33_1_EN_0_SHIFT,
+ MT6359P_DA_VCN33_1_B_EN_ADDR, MT6359P_RG_VCN33_1_VOSEL_ADDR,
+ MT6359_RG_VCN33_1_VOSEL_MASK <<
+ MT6359_RG_VCN33_1_VOSEL_SHIFT, 240),
+ MT6359_LDO("ldo_vcn33_1_wifi", VCN33_1_WIFI, vcn33_voltages,
+ MT6359P_RG_LDO_VCN33_1_EN_1_ADDR,
+ MT6359P_RG_LDO_VCN33_1_EN_1_SHIFT,
+ MT6359P_DA_VCN33_1_B_EN_ADDR, MT6359P_RG_VCN33_1_VOSEL_ADDR,
+ MT6359_RG_VCN33_1_VOSEL_MASK <<
+ MT6359_RG_VCN33_1_VOSEL_SHIFT, 240),
+ MT6359_REG_FIXED("ldo_vaux18", VAUX18, MT6359P_RG_LDO_VAUX18_EN_ADDR,
+ MT6359P_DA_VAUX18_B_EN_ADDR, 1800000),
+ MT6359_LDO_LINEAR("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250,
+ MT6359P_RG_LDO_VSRAM_OTHERS_EN_ADDR,
+ MT6359P_DA_VSRAM_OTHERS_B_EN_ADDR,
+ MT6359P_RG_LDO_VSRAM_OTHERS_VOSEL_ADDR,
+ MT6359_RG_LDO_VSRAM_OTHERS_VOSEL_MASK <<
+ MT6359_RG_LDO_VSRAM_OTHERS_VOSEL_SHIFT),
+ MT6359_LDO("ldo_vefuse", VEFUSE, vefuse_voltages,
+ MT6359P_RG_LDO_VEFUSE_EN_ADDR,
+ MT6359P_RG_LDO_VEFUSE_EN_SHIFT,
+ MT6359P_DA_VEFUSE_B_EN_ADDR, MT6359P_RG_VEFUSE_VOSEL_ADDR,
+ MT6359_RG_VEFUSE_VOSEL_MASK << MT6359_RG_VEFUSE_VOSEL_SHIFT,
+ 240),
+ MT6359_LDO("ldo_vxo22", VXO22, vxo22_voltages,
+ MT6359P_RG_LDO_VXO22_EN_ADDR, MT6359P_RG_LDO_VXO22_EN_SHIFT,
+ MT6359P_DA_VXO22_B_EN_ADDR, MT6359P_RG_VXO22_VOSEL_ADDR,
+ MT6359_RG_VXO22_VOSEL_MASK << MT6359_RG_VXO22_VOSEL_SHIFT,
+ 480),
+ MT6359_LDO("ldo_vrfck", VRFCK, vrfck_voltages_1,
+ MT6359P_RG_LDO_VRFCK_EN_ADDR, MT6359P_RG_LDO_VRFCK_EN_SHIFT,
+ MT6359P_DA_VRFCK_B_EN_ADDR, MT6359P_RG_VRFCK_VOSEL_ADDR,
+ MT6359_RG_VRFCK_VOSEL_MASK << MT6359_RG_VRFCK_VOSEL_SHIFT,
+ 480),
+ MT6359_LDO("ldo_vrfck_1", VRFCK, vrfck_voltages_1,
+ MT6359P_RG_LDO_VRFCK_EN_ADDR, MT6359P_RG_LDO_VRFCK_EN_SHIFT,
+ MT6359P_DA_VRFCK_B_EN_ADDR, MT6359P_RG_VRFCK_VOSEL_ADDR,
+ MT6359_RG_VRFCK_VOSEL_MASK << MT6359_RG_VRFCK_VOSEL_SHIFT,
+ 480),
+ MT6359_REG_FIXED("ldo_vbif28", VBIF28, MT6359P_RG_LDO_VBIF28_EN_ADDR,
+ MT6359P_DA_VBIF28_B_EN_ADDR, 2800000),
+ MT6359_LDO("ldo_vio28", VIO28, vio28_voltages,
+ MT6359P_RG_LDO_VIO28_EN_ADDR, MT6359P_RG_LDO_VIO28_EN_SHIFT,
+ MT6359P_DA_VIO28_B_EN_ADDR, MT6359P_RG_VIO28_VOSEL_ADDR,
+ MT6359_RG_VIO28_VOSEL_MASK << MT6359_RG_VIO28_VOSEL_SHIFT,
+ 1920),
+ MT6359P_LDO1("ldo_vemc_1", VEMC, MT6359_REG_TYPE_VEMC, vemc_voltages_1,
+ MT6359P_RG_LDO_VEMC_EN_ADDR, MT6359P_RG_LDO_VEMC_EN_SHIFT,
+ MT6359P_DA_VEMC_B_EN_ADDR,
+ MT6359P_RG_LDO_VEMC_VOSEL_0_ADDR,
+ MT6359P_RG_LDO_VEMC_VOSEL_0_MASK <<
+ MT6359P_RG_LDO_VEMC_VOSEL_0_SHIFT),
+ MT6359_LDO("ldo_vcn33_2_bt", VCN33_2_BT, vcn33_voltages,
+ MT6359P_RG_LDO_VCN33_2_EN_0_ADDR,
+ MT6359P_RG_LDO_VCN33_2_EN_0_SHIFT,
+ MT6359P_DA_VCN33_2_B_EN_ADDR, MT6359P_RG_VCN33_2_VOSEL_ADDR,
+ MT6359_RG_VCN33_2_VOSEL_MASK <<
+ MT6359_RG_VCN33_2_VOSEL_SHIFT, 240),
+ MT6359_LDO("ldo_vcn33_2_wifi", VCN33_2_WIFI, vcn33_voltages,
+ MT6359P_RG_LDO_VCN33_2_EN_1_ADDR,
+ MT6359_RG_LDO_VCN33_2_EN_1_SHIFT,
+ MT6359P_DA_VCN33_2_B_EN_ADDR, MT6359P_RG_VCN33_2_VOSEL_ADDR,
+ MT6359_RG_VCN33_2_VOSEL_MASK <<
+ MT6359_RG_VCN33_2_VOSEL_SHIFT, 240),
+ MT6359_LDO("ldo_va12", VA12, va12_voltages,
+ MT6359P_RG_LDO_VA12_EN_ADDR, MT6359P_RG_LDO_VA12_EN_SHIFT,
+ MT6359P_DA_VA12_B_EN_ADDR, MT6359P_RG_VA12_VOSEL_ADDR,
+ MT6359_RG_VA12_VOSEL_MASK << MT6359_RG_VA12_VOSEL_SHIFT,
+ 960),
+ MT6359_LDO("ldo_va09", VA09, va09_voltages,
+ MT6359P_RG_LDO_VA09_EN_ADDR, MT6359P_RG_LDO_VA09_EN_SHIFT,
+ MT6359P_DA_VA09_B_EN_ADDR, MT6359P_RG_VA09_VOSEL_ADDR,
+ MT6359_RG_VA09_VOSEL_MASK << MT6359_RG_VA09_VOSEL_SHIFT,
+ 960),
+ MT6359_LDO("ldo_vrf18", VRF18, vrf18_voltages,
+ MT6359P_RG_LDO_VRF18_EN_ADDR, MT6359P_RG_LDO_VRF18_EN_SHIFT,
+ MT6359P_DA_VRF18_B_EN_ADDR, MT6359P_RG_VRF18_VOSEL_ADDR,
+ MT6359_RG_VRF18_VOSEL_MASK << MT6359_RG_VRF18_VOSEL_SHIFT,
+ 240),
+ MT6359_LDO_LINEAR("ldo_vsram_md", VSRAM_MD, 500000, 1293750, 6250,
+ MT6359P_RG_LDO_VSRAM_MD_EN_ADDR,
+ MT6359P_DA_VSRAM_MD_B_EN_ADDR,
+ MT6359P_RG_LDO_VSRAM_MD_VOSEL_ADDR,
+ MT6359_RG_LDO_VSRAM_MD_VOSEL_MASK <<
+ MT6359_RG_LDO_VSRAM_MD_VOSEL_SHIFT),
+ MT6359_LDO("ldo_vufs", VUFS, volt18_voltages,
+ MT6359P_RG_LDO_VUFS_EN_ADDR, MT6359P_RG_LDO_VUFS_EN_SHIFT,
+ MT6359P_DA_VUFS_B_EN_ADDR, MT6359P_RG_VUFS_VOSEL_ADDR,
+ MT6359_RG_VUFS_VOSEL_MASK << MT6359_RG_VUFS_VOSEL_SHIFT,
+ 1920),
+ MT6359_LDO("ldo_vm18", VM18, volt18_voltages,
+ MT6359P_RG_LDO_VM18_EN_ADDR, MT6359P_RG_LDO_VM18_EN_SHIFT,
+ MT6359P_DA_VM18_B_EN_ADDR, MT6359P_RG_VM18_VOSEL_ADDR,
+ MT6359_RG_VM18_VOSEL_MASK << MT6359_RG_VM18_VOSEL_SHIFT,
+ 1920),
+ MT6359_LDO("ldo_vbbck", VBBCK, vbbck_voltages,
+ MT6359P_RG_LDO_VBBCK_EN_ADDR, MT6359P_RG_LDO_VBBCK_EN_SHIFT,
+ MT6359P_DA_VBBCK_B_EN_ADDR, MT6359P_RG_VBBCK_VOSEL_ADDR,
+ MT6359P_RG_VBBCK_VOSEL_MASK << MT6359P_RG_VBBCK_VOSEL_SHIFT,
+ 480),
+ MT6359_LDO_LINEAR("ldo_vsram_proc1", VSRAM_PROC1, 500000, 1293750, 6250,
+ MT6359P_RG_LDO_VSRAM_PROC1_EN_ADDR,
+ MT6359P_DA_VSRAM_PROC1_B_EN_ADDR,
+ MT6359P_RG_LDO_VSRAM_PROC1_VOSEL_ADDR,
+ MT6359_RG_LDO_VSRAM_PROC1_VOSEL_MASK <<
+ MT6359_RG_LDO_VSRAM_PROC1_VOSEL_SHIFT),
+ MT6359_LDO("ldo_vsim2", VSIM2, vsim2_voltages,
+ MT6359P_RG_LDO_VSIM2_EN_ADDR, MT6359P_RG_LDO_VSIM2_EN_SHIFT,
+ MT6359P_DA_VSIM2_B_EN_ADDR, MT6359P_RG_VSIM2_VOSEL_ADDR,
+ MT6359_RG_VSIM2_VOSEL_MASK << MT6359_RG_VSIM2_VOSEL_SHIFT,
+ 480),
+ MT6359_LDO_LINEAR("ldo_vsram_others_sshub", VSRAM_OTHERS_SSHUB,
+ 500000, 1293750, 6250,
+ MT6359P_RG_LDO_VSRAM_OTHERS_SSHUB_EN_ADDR,
+ MT6359P_DA_VSRAM_OTHERS_B_EN_ADDR,
+ MT6359P_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL_ADDR,
+ MT6359_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL_MASK <<
+ MT6359_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL_SHIFT),
+};
+
+static int mt6359_regulator_probe(struct udevice *dev)
+{
+ struct mt6359_regulator_info *priv = dev_get_priv(dev);
+ int i, hw_ver;
+
+ hw_ver = pmic_reg_read(dev->parent, MT6359P_HWCID);
+ if (hw_ver < MT6359P_CHIP_VER) {
+ dev_err(dev, "mt6359 is not supported. Only support mt6359p, hw_ver(%d)\n",
+ hw_ver);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(mt6359p_regulators); i++) {
+ if (!strcmp(dev->name, mt6359p_regulators[i].desc.of_match)) {
+ *priv = mt6359p_regulators[i];
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
+static const struct dm_regulator_ops mt6359_regulator_ops = {
+ .get_value = mt6359_get_value,
+ .set_value = mt6359_set_value,
+ .get_enable = mt6359_get_enable,
+ .set_enable = mt6359_set_enable,
+};
+
+U_BOOT_DRIVER(mt6359_regulator) = {
+ .name = MT6359_REGULATOR_DRIVER,
+ .id = UCLASS_REGULATOR,
+ .ops = &mt6359_regulator_ops,
+ .probe = mt6359_regulator_probe,
+ .priv_auto = sizeof(struct mt6359_regulator_info),
+};
diff --git a/drivers/power/regulator/pwm_regulator.c b/drivers/power/regulator/pwm_regulator.c
index ff738faadc5..adde5156c76 100644
--- a/drivers/power/regulator/pwm_regulator.c
+++ b/drivers/power/regulator/pwm_regulator.c
@@ -11,12 +11,9 @@
#include <errno.h>
#include <log.h>
#include <pwm.h>
-#include <asm/global_data.h>
#include <dm/device_compat.h>
#include <power/regulator.h>
-DECLARE_GLOBAL_DATA_PTR;
-
struct pwm_regulator_info {
/* pwm id corresponding to the PWM driver */
int pwm_id;
diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c
index 94c52cf555b..1c7f75a9338 100644
--- a/drivers/power/regulator/regulator-uclass.c
+++ b/drivers/power/regulator/regulator-uclass.c
@@ -449,7 +449,7 @@ static int regulator_post_bind(struct udevice *dev)
}
if (!regulator_name_is_unique(dev, uc_pdata->name)) {
- dev_err(dev, "'%s' has nonunique value: '%s\n",
+ dev_err(dev, "'%s' has nonunique value: '%s'\n",
property, uc_pdata->name);
return -EINVAL;
}