diff options
| author | Tom Rini <[email protected]> | 2026-04-06 12:16:57 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-04-06 12:16:57 -0600 |
| commit | 93f84ee022a8401421cdaab84fe7d106d83fdb4a (patch) | |
| tree | fb15a4af876e8faf9893fd86c1c0e127265dbe9a /drivers/power | |
| parent | 88dc2788777babfd6322fa655df549a019aa1e69 (diff) | |
| parent | e2138cf1e6088f12ffa874e87cc8f4b198378635 (diff) | |
Merge branch 'next'
Diffstat (limited to 'drivers/power')
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; } |
