diff options
| author | Tom Rini <trini@konsulko.com> | 2026-02-26 10:23:12 -0600 |
|---|---|---|
| committer | Tom Rini <trini@konsulko.com> | 2026-02-26 10:23:12 -0600 |
| commit | f6963fc232603007c661411fb31c57f1a9678a87 (patch) | |
| tree | 562bd5abaf1ccfc4204080e84f421165ea30b72b | |
| parent | 8fd76675efbe7af785ccc1ba1ac8b9f7e10f6715 (diff) | |
| parent | b3d16267b5095746888927478a0973fa810a0826 (diff) | |
Merge tag 'mmc-next-2026-02-26' of https://source.denx.de/u-boot/custodians/u-boot-mmc into next
- Add MediaTek MT6359P regulator driver
- Add MediaTek MT6357 regulator driver
- Add MediaTek PMIC Wrapper driver
- Enable pmic and regulator for mt8365 evk
- Minor cleanup
| -rw-r--r-- | MAINTAINERS | 3 | ||||
| -rw-r--r-- | cmd/mmc.c | 4 | ||||
| -rw-r--r-- | configs/mt8365_evk_defconfig | 6 | ||||
| -rw-r--r-- | drivers/mmc/mtk-sd.c | 11 | ||||
| -rw-r--r-- | drivers/power/pmic/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/power/pmic/Makefile | 1 | ||||
| -rw-r--r-- | drivers/power/pmic/mtk-pwrap.c | 896 | ||||
| -rw-r--r-- | drivers/power/regulator/Kconfig | 26 | ||||
| -rw-r--r-- | drivers/power/regulator/Makefile | 2 | ||||
| -rw-r--r-- | drivers/power/regulator/mt6357_regulator.c | 512 | ||||
| -rw-r--r-- | drivers/power/regulator/mt6359_regulator.c | 711 | ||||
| -rw-r--r-- | include/power/mt6357.h | 159 | ||||
| -rw-r--r-- | include/power/mt6359.h | 225 | ||||
| -rw-r--r-- | include/power/mt6359p.h | 230 |
14 files changed, 2792 insertions, 2 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index f8d4f6ee8b2..00cb03fe592 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -432,6 +432,8 @@ F: drivers/net/phy/mediatek/ F: drivers/phy/phy-mtk-* F: drivers/pinctrl/mediatek/ F: drivers/power/domain/mtk-power-domain.c +F: drivers/power/pmic/mtk-pwrap.c +F: drivers/power/regulator/mt*.c F: drivers/pci/pcie_mediatek_gen3.c F: drivers/pci/pcie_mediatek.c F: drivers/pwm/pwm-mtk.c @@ -448,6 +450,7 @@ F: drivers/reset/reset-mediatek.c F: drivers/serial/serial_mtk.c F: include/dt-bindings/clock/mediatek,* F: include/dt-bindings/power/mediatek,* +F: include/power/mt*.h F: tools/mtk_image.c F: tools/mtk_image.h F: tools/mtk_nand_headers.c diff --git a/cmd/mmc.c b/cmd/mmc.c index 6cb1ef5dc23..81b1ca4ad84 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -29,12 +29,12 @@ static void print_mmcinfo(struct mmc *mmc) printf("Manufacturer ID: %x\n", mmc->cid[0] >> 24); if (IS_SD(mmc)) { printf("OEM: %x\n", (mmc->cid[0] >> 8) & 0xffff); - printf("Name: %c%c%c%c%c \n", mmc->cid[0] & 0xff, + printf("Name: %c%c%c%c%c\n", mmc->cid[0] & 0xff, (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff, (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff); } else { printf("OEM: %x\n", (mmc->cid[0] >> 8) & 0xff); - printf("Name: %c%c%c%c%c%c \n", mmc->cid[0] & 0xff, + printf("Name: %c%c%c%c%c%c\n", mmc->cid[0] & 0xff, (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff, (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff, (mmc->cid[2] >> 24)); diff --git a/configs/mt8365_evk_defconfig b/configs/mt8365_evk_defconfig index f1e7d7fc58a..9b403cd7aab 100644 --- a/configs/mt8365_evk_defconfig +++ b/configs/mt8365_evk_defconfig @@ -15,12 +15,18 @@ CONFIG_CMD_CLK=y CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_PART=y +CONFIG_CMD_PMIC=y +CONFIG_CMD_REGULATOR=y CONFIG_OF_UPSTREAM=y CONFIG_CLK=y CONFIG_MMC_MTK=y CONFIG_PINCTRL=y CONFIG_PINCONF=y CONFIG_PINCTRL_MT8365=y +CONFIG_DM_PMIC=y +CONFIG_DM_PMIC_MTK_PWRAP=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_MT6357=y CONFIG_BAUDRATE=921600 CONFIG_DM_SERIAL=y CONFIG_MTK_SERIAL=y diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c index 4928a880038..7a4bdee7496 100644 --- a/drivers/mmc/mtk-sd.c +++ b/drivers/mmc/mtk-sd.c @@ -1979,6 +1979,16 @@ static const struct msdc_compatible mt8183_compat = { .use_dma_mode = true, }; +static const struct msdc_compatible mt8189_compat = { + .clk_div_bits = 12, + .pad_tune0 = true, + .async_fifo = true, + .data_tune = true, + .busy_check = true, + .stop_clk_fix = true, + .enhance_rx = true, +}; + static const struct udevice_id msdc_ids[] = { { .compatible = "mediatek,mt7620-mmc", .data = (ulong)&mt7620_compat }, { .compatible = "mediatek,mt7621-mmc", .data = (ulong)&mt7621_compat }, @@ -1990,6 +2000,7 @@ static const struct udevice_id msdc_ids[] = { { .compatible = "mediatek,mt8512-mmc", .data = (ulong)&mt8512_compat }, { .compatible = "mediatek,mt8516-mmc", .data = (ulong)&mt8516_compat }, { .compatible = "mediatek,mt8183-mmc", .data = (ulong)&mt8183_compat }, + { .compatible = "mediatek,mt8189-mmc", .data = (ulong)&mt8189_compat }, {} }; diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index b1a5b1c2a1f..345b7c92263 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -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/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 <jmasson@baylibre.com> + */ + +#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/regulator/Kconfig b/drivers/power/regulator/Kconfig index bd9ccd26981..4f39e46cebd 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/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 <jmasson@baylibre.com> + */ + +#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 <rex-bc.chen@mediatek.com> + */ + +#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/include/power/mt6357.h b/include/power/mt6357.h new file mode 100644 index 00000000000..b7ee9d64386 --- /dev/null +++ b/include/power/mt6357.h @@ -0,0 +1,159 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2026 BayLibre, SAS. + * Author: Julien Masson <jmasson@baylibre.com> + */ + +#ifndef _REGULATOR_MT6357_H_ +#define _REGULATOR_MT6357_H_ + +#define MT6357_REGULATOR_DRIVER "mt6357_regulator" + +enum { + /* Bucks */ + MT6357_ID_VCORE, + MT6357_ID_VMODEM, + MT6357_ID_VPA, + MT6357_ID_VPROC, + MT6357_ID_VS1, + + /* LDOs */ + MT6357_ID_VAUX18, + MT6357_ID_VAUD28, + MT6357_ID_VCAMA, + MT6357_ID_VCAMD, + MT6357_ID_VCAMIO, + MT6357_ID_VCN18, + MT6357_ID_VCN28, + MT6357_ID_VCN33_BT, + MT6357_ID_VCN33_WIFI, + MT6357_ID_VDRAM, + MT6357_ID_VEFUSE, + MT6357_ID_VEMC, + MT6357_ID_VFE28, + MT6357_ID_VIBR, + MT6357_ID_VIO18, + MT6357_ID_VIO28, + MT6357_ID_VLDO28, + MT6357_ID_VMC, + MT6357_ID_VMCH, + MT6357_ID_VRF12, + MT6357_ID_VRF18, + MT6357_ID_VSIM1, + MT6357_ID_VSIM2, + MT6357_ID_VSRAM_OTHERS, + MT6357_ID_VSRAM_PROC, + MT6357_ID_VUSB33, + MT6357_ID_VXO22, +}; + +/* PMIC Registers */ +#define MT6357_BUCK_TOP_CLK_CON0 0x140c +#define MT6357_BUCK_TOP_CLK_HWEN_CON0 0x1412 +#define MT6357_BUCK_TOP_CLK_MISC_CON0 0x1418 +#define MT6357_BUCK_TOP_INT_CON0 0x141a +#define MT6357_BUCK_TOP_INT_MASK_CON0 0x1420 +#define MT6357_BUCK_TOP_SLP_CON0 0x142c +#define MT6357_BUCK_TOP_OC_CON0 0x1434 +#define MT6357_BUCK_TOP_K_CON0 0x1436 +#define MT6357_BUCK_VPROC_CON0 0x1488 +#define MT6357_BUCK_VPROC_DBG0 0x14a2 +#define MT6357_BUCK_VPROC_ELR0 0x14aa +#define MT6357_BUCK_VCORE_CON0 0x1508 +#define MT6357_BUCK_VCORE_DBG0 0x1522 +#define MT6357_BUCK_VCORE_ELR0 0x152a +#define MT6357_BUCK_VMODEM_CON0 0x1588 +#define MT6357_BUCK_VMODEM_DBG0 0x15a2 +#define MT6357_BUCK_VMODEM_ELR0 0x15aa +#define MT6357_BUCK_VS1_CON0 0x1608 +#define MT6357_BUCK_VS1_DBG0 0x1622 +#define MT6357_BUCK_VS1_ELR0 0x1632 +#define MT6357_BUCK_VPA_CON0 0x1688 +#define MT6357_BUCK_VPA_CON1 0x168a +#define MT6357_BUCK_VPA_DBG0 0x1692 +#define MT6357_BUCK_VPA_DLC_CON0 0x1698 +#define MT6357_BUCK_VPA_MSFG_CON0 0x169e +#define MT6357_LDO_TOP_CLK_DCM_CON0 0x188c +#define MT6357_LDO_TOP_CLK_VIO28_CON0 0x188e +#define MT6357_LDO_TOP_CLK_VIO18_CON0 0x1890 +#define MT6357_LDO_TOP_CLK_VAUD28_CON0 0x1892 +#define MT6357_LDO_TOP_CLK_VDRAM_CON0 0x1894 +#define MT6357_LDO_TOP_CLK_VSRAM_PROC_CON0 0x1896 +#define MT6357_LDO_TOP_CLK_VSRAM_OTHERS_CON0 0x1898 +#define MT6357_LDO_TOP_CLK_VAUX18_CON0 0x189a +#define MT6357_LDO_TOP_CLK_VUSB33_CON0 0x189c +#define MT6357_LDO_TOP_CLK_VEMC_CON0 0x189e +#define MT6357_LDO_TOP_CLK_VXO22_CON0 0x18a0 +#define MT6357_LDO_TOP_CLK_VSIM1_CON0 0x18a2 +#define MT6357_LDO_TOP_CLK_VSIM2_CON0 0x18a4 +#define MT6357_LDO_TOP_CLK_VCAMD_CON0 0x18a6 +#define MT6357_LDO_TOP_CLK_VCAMIO_CON0 0x18a8 +#define MT6357_LDO_TOP_CLK_VEFUSE_CON0 0x18aa +#define MT6357_LDO_TOP_CLK_VCN33_CON0 0x18ac +#define MT6357_LDO_TOP_CLK_VCN18_CON0 0x18ae +#define MT6357_LDO_TOP_CLK_VCN28_CON0 0x18b0 +#define MT6357_LDO_TOP_CLK_VIBR_CON0 0x18b2 +#define MT6357_LDO_TOP_CLK_VFE28_CON0 0x18b4 +#define MT6357_LDO_TOP_CLK_VMCH_CON0 0x18b6 +#define MT6357_LDO_TOP_CLK_VMC_CON0 0x18b8 +#define MT6357_LDO_TOP_CLK_VRF18_CON0 0x18ba +#define MT6357_LDO_TOP_CLK_VLDO28_CON0 0x18bc +#define MT6357_LDO_TOP_CLK_VRF12_CON0 0x18be +#define MT6357_LDO_TOP_CLK_VCAMA_CON0 0x18c0 +#define MT6357_LDO_TOP_CLK_TREF_CON0 0x18c2 +#define MT6357_LDO_TOP_INT_CON0 0x18c4 +#define MT6357_LDO_TOP_INT_MASK_CON0 0x18d0 +#define MT6357_LDO_TEST_CON0 0x18e4 +#define MT6357_LDO_TOP_WDT_CON0 0x18e6 +#define MT6357_LDO_TOP_RSV_CON0 0x18e8 +#define MT6357_LDO_VXO22_CON0 0x1908 +#define MT6357_LDO_VAUX18_CON0 0x191c +#define MT6357_LDO_VAUD28_CON0 0x1930 +#define MT6357_LDO_VIO28_CON0 0x1944 +#define MT6357_LDO_VIO18_CON0 0x1958 +#define MT6357_LDO_VDRAM_CON0 0x196c +#define MT6357_LDO_VEMC_CON0 0x1988 +#define MT6357_LDO_VUSB33_CON0_0 0x199c +#define MT6357_LDO_VSRAM_PROC_CON0 0x19b2 +#define MT6357_LDO_VSRAM_PROC_DBG0 0x19cc +#define MT6357_LDO_VSRAM_OTHERS_CON0 0x19d0 +#define MT6357_LDO_VSRAM_OTHERS_DBG0 0x19ea +#define MT6357_LDO_VSRAM_WDT_DBG0 0x19f6 +#define MT6357_LDO_VSRAM_CON0 0x19fa +#define MT6357_LDO_VSRAM_CON1 0x19fc +#define MT6357_LDO_VFE28_CON0 0x1a08 +#define MT6357_LDO_VRF18_CON0 0x1a1c +#define MT6357_LDO_VRF12_CON0 0x1a30 +#define MT6357_LDO_VEFUSE_CON0 0x1a44 +#define MT6357_LDO_VCN18_CON0 0x1a58 +#define MT6357_LDO_VCAMA_CON0 0x1a6c +#define MT6357_LDO_VCAMD_CON0 0x1a88 +#define MT6357_LDO_VCAMIO_CON0 0x1a9c +#define MT6357_LDO_VMC_CON0 0x1ab0 +#define MT6357_LDO_VMCH_CON0 0x1ac4 +#define MT6357_LDO_VSIM1_CON0 0x1ad8 +#define MT6357_LDO_VSIM2_CON0 0x1aec +#define MT6357_LDO_VIBR_CON0 0x1b08 +#define MT6357_LDO_VCN33_CON0_0 0x1b1c +#define MT6357_LDO_VCN33_CON0_1 0x1b2a +#define MT6357_LDO_VLDO28_CON0_0 0x1b32 +#define MT6357_LDO_GOFF2_RSV_CON0 0x1b48 +#define MT6357_LDO_VCN28_CON0 0x1b88 +#define MT6357_LDO_TREF_CON0 0x1b9e +#define MT6357_LDO_GOFF3_RSV_CON0 0x1bae +#define MT6357_VXO22_ANA_CON0 0x1c18 +#define MT6357_VCN33_ANA_CON0 0x1c1c +#define MT6357_VEMC_ANA_CON0 0x1c20 +#define MT6357_VLDO28_ANA_CON0 0x1c24 +#define MT6357_VIBR_ANA_CON0 0x1c2c +#define MT6357_VSIM1_ANA_CON0 0x1c30 +#define MT6357_VSIM2_ANA_CON0 0x1c34 +#define MT6357_VMCH_ANA_CON0 0x1c38 +#define MT6357_VMC_ANA_CON0 0x1c3c +#define MT6357_VUSB33_ANA_CON0 0x1c88 +#define MT6357_VCAMA_ANA_CON0 0x1c8c +#define MT6357_VEFUSE_ANA_CON0 0x1c90 +#define MT6357_VCAMD_ANA_CON0 0x1c94 +#define MT6357_VDRAM_ELR_2 0x1cac + +#endif diff --git a/include/power/mt6359.h b/include/power/mt6359.h new file mode 100644 index 00000000000..1e0380e87b0 --- /dev/null +++ b/include/power/mt6359.h @@ -0,0 +1,225 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2026 MediaTek Inc. All Rights Reserved. + * Author: Bo-Chen Chen <rex-bc.chen@mediatek.com> + */ + +#ifndef __MT6359_H_ +#define __MT6359_H_ + +#define MT6359_REGULATOR_DRIVER "mt6359_regulator" + +enum { + MT6359_ID_VS1 = 0, + MT6359_ID_VGPU11, + MT6359_ID_VMODEM, + MT6359_ID_VPU, + MT6359_ID_VCORE, + MT6359_ID_VS2, + MT6359_ID_VPA, + MT6359_ID_VPROC2, + MT6359_ID_VPROC1, + MT6359_ID_VCORE_SSHUB, + MT6359_ID_VGPU11_SSHUB = MT6359_ID_VCORE_SSHUB, + MT6359_ID_VAUD18 = 10, + MT6359_ID_VSIM1, + MT6359_ID_VIBR, + MT6359_ID_VRF12, + MT6359_ID_VUSB, + MT6359_ID_VSRAM_PROC2, + MT6359_ID_VIO18, + MT6359_ID_VCAMIO, + MT6359_ID_VCN18, + MT6359_ID_VFE28, + MT6359_ID_VCN13, + MT6359_ID_VCN33_1_BT, + MT6359_ID_VCN33_1_WIFI, + MT6359_ID_VAUX18, + MT6359_ID_VSRAM_OTHERS, + MT6359_ID_VEFUSE, + MT6359_ID_VXO22, + MT6359_ID_VRFCK, + MT6359_ID_VBIF28, + MT6359_ID_VIO28, + MT6359_ID_VEMC, + MT6359_ID_VCN33_2_BT, + MT6359_ID_VCN33_2_WIFI, + MT6359_ID_VA12, + MT6359_ID_VA09, + MT6359_ID_VRF18, + MT6359_ID_VSRAM_MD, + MT6359_ID_VUFS, + MT6359_ID_VM18, + MT6359_ID_VBBCK, + MT6359_ID_VSRAM_PROC1, + MT6359_ID_VSIM2, + MT6359_ID_VSRAM_OTHERS_SSHUB, + MT6359_ID_RG_MAX, +}; + + +/* PMIC Registers */ +#define MT6359_BUCK_VPU_CON0 0x1488 +#define MT6359_BUCK_VPU_DBG1 0x14a8 +#define MT6359_BUCK_VPU_ELR0 0x14ac +#define MT6359_BUCK_VCORE_CON0 0x1508 +#define MT6359_BUCK_VCORE_DBG1 0x1528 +#define MT6359_BUCK_VGPU11_CON0 0x1588 +#define MT6359_BUCK_VGPU11_DBG1 0x15a8 +#define MT6359_BUCK_VMODEM_CON0 0x1688 +#define MT6359_BUCK_VMODEM_DBG1 0x16a8 +#define MT6359_BUCK_VMODEM_ELR0 0x16ae +#define MT6359_BUCK_VPROC1_CON0 0x1708 +#define MT6359_BUCK_VPROC1_DBG1 0x1728 +#define MT6359_BUCK_VPROC1_ELR0 0x172e +#define MT6359_BUCK_VPROC2_CON0 0x1788 +#define MT6359_BUCK_VPROC2_DBG1 0x17a8 +#define MT6359_BUCK_VPROC2_ELR0 0x17b2 +#define MT6359_BUCK_VS1_CON0 0x1808 +#define MT6359_BUCK_VS1_DBG1 0x1828 +#define MT6359_BUCK_VS1_ELR0 0x1834 +#define MT6359_BUCK_VS2_CON0 0x1888 +#define MT6359_BUCK_VS2_DBG1 0x18a8 +#define MT6359_BUCK_VS2_ELR0 0x18b4 +#define MT6359_BUCK_VPA_CON0 0x1908 +#define MT6359_BUCK_VPA_CON1 0x190e +#define MT6359_BUCK_VPA_DBG1 0x1916 +#define MT6359_VGPUVCORE_ANA_CON2 0x198e +#define MT6359_VGPUVCORE_ANA_CON13 0x19a4 +#define MT6359_VPROC1_ANA_CON3 0x19b2 +#define MT6359_VPROC2_ANA_CON3 0x1a0e +#define MT6359_VMODEM_ANA_CON3 0x1a1a +#define MT6359_VPU_ANA_CON3 0x1a26 +#define MT6359_VS1_ANA_CON0 0x1a2c +#define MT6359_VS2_ANA_CON0 0x1a34 +#define MT6359_VPA_ANA_CON0 0x1a3c + +#define MT6359_RG_BUCK_VPU_EN_ADDR MT6359_BUCK_VPU_CON0 +#define MT6359_RG_BUCK_VPU_LP_ADDR MT6359_BUCK_VPU_CON0 +#define MT6359_RG_BUCK_VPU_LP_SHIFT 1 +#define MT6359_DA_VPU_EN_ADDR MT6359_BUCK_VPU_DBG1 +#define MT6359_RG_BUCK_VPU_VOSEL_ADDR MT6359_BUCK_VPU_ELR0 +#define MT6359_RG_BUCK_VPU_VOSEL_MASK 0x7F +#define MT6359_RG_BUCK_VPU_VOSEL_SHIFT 0 +#define MT6359_RG_BUCK_VCORE_EN_ADDR MT6359_BUCK_VCORE_CON0 +#define MT6359_RG_BUCK_VCORE_LP_ADDR MT6359_BUCK_VCORE_CON0 +#define MT6359_RG_BUCK_VCORE_LP_SHIFT 1 +#define MT6359_DA_VCORE_EN_ADDR MT6359_BUCK_VCORE_DBG1 +#define MT6359_RG_BUCK_VCORE_VOSEL_MASK 0x7F +#define MT6359_RG_BUCK_VCORE_VOSEL_SHIFT 0 +#define MT6359_RG_BUCK_VGPU11_EN_ADDR MT6359_BUCK_VGPU11_CON0 +#define MT6359_RG_BUCK_VGPU11_LP_ADDR MT6359_BUCK_VGPU11_CON0 +#define MT6359_RG_BUCK_VGPU11_LP_SHIFT 1 +#define MT6359_DA_VGPU11_EN_ADDR MT6359_BUCK_VGPU11_DBG1 +#define MT6359_RG_BUCK_VGPU11_VOSEL_MASK 0x7F +#define MT6359_RG_BUCK_VGPU11_VOSEL_SHIFT 0 +#define MT6359_RG_BUCK_VMODEM_EN_ADDR MT6359_BUCK_VMODEM_CON0 +#define MT6359_RG_BUCK_VMODEM_LP_ADDR MT6359_BUCK_VMODEM_CON0 +#define MT6359_RG_BUCK_VMODEM_LP_SHIFT 1 +#define MT6359_DA_VMODEM_EN_ADDR MT6359_BUCK_VMODEM_DBG1 +#define MT6359_RG_BUCK_VMODEM_VOSEL_ADDR MT6359_BUCK_VMODEM_ELR0 +#define MT6359_RG_BUCK_VMODEM_VOSEL_MASK 0x7F +#define MT6359_RG_BUCK_VMODEM_VOSEL_SHIFT 0 +#define MT6359_RG_BUCK_VPROC1_EN_ADDR MT6359_BUCK_VPROC1_CON0 +#define MT6359_RG_BUCK_VPROC1_LP_ADDR MT6359_BUCK_VPROC1_CON0 +#define MT6359_RG_BUCK_VPROC1_LP_SHIFT 1 +#define MT6359_DA_VPROC1_EN_ADDR MT6359_BUCK_VPROC1_DBG1 +#define MT6359_RG_BUCK_VPROC1_VOSEL_ADDR MT6359_BUCK_VPROC1_ELR0 +#define MT6359_RG_BUCK_VPROC1_VOSEL_MASK 0x7F +#define MT6359_RG_BUCK_VPROC1_VOSEL_SHIFT 0 +#define MT6359_RG_BUCK_VPROC2_EN_ADDR MT6359_BUCK_VPROC2_CON0 +#define MT6359_RG_BUCK_VPROC2_LP_ADDR MT6359_BUCK_VPROC2_CON0 +#define MT6359_RG_BUCK_VPROC2_LP_SHIFT 1 +#define MT6359_DA_VPROC2_EN_ADDR MT6359_BUCK_VPROC2_DBG1 +#define MT6359_RG_BUCK_VPROC2_VOSEL_ADDR MT6359_BUCK_VPROC2_ELR0 +#define MT6359_RG_BUCK_VPROC2_VOSEL_MASK 0x7F +#define MT6359_RG_BUCK_VPROC2_VOSEL_SHIFT 0 +#define MT6359_RG_BUCK_VS1_EN_ADDR MT6359_BUCK_VS1_CON0 +#define MT6359_RG_BUCK_VS1_LP_ADDR MT6359_BUCK_VS1_CON0 +#define MT6359_RG_BUCK_VS1_LP_SHIFT 1 +#define MT6359_DA_VS1_EN_ADDR MT6359_BUCK_VS1_DBG1 +#define MT6359_RG_BUCK_VS1_VOSEL_ADDR MT6359_BUCK_VS1_ELR0 +#define MT6359_RG_BUCK_VS1_VOSEL_MASK 0x7F +#define MT6359_RG_BUCK_VS1_VOSEL_SHIFT 0 +#define MT6359_RG_BUCK_VS2_EN_ADDR MT6359_BUCK_VS2_CON0 +#define MT6359_RG_BUCK_VS2_LP_ADDR MT6359_BUCK_VS2_CON0 +#define MT6359_RG_BUCK_VS2_LP_SHIFT 1 +#define MT6359_DA_VS2_EN_ADDR MT6359_BUCK_VS2_DBG1 +#define MT6359_RG_BUCK_VS2_VOSEL_ADDR MT6359_BUCK_VS2_ELR0 +#define MT6359_RG_BUCK_VS2_VOSEL_MASK 0x7F +#define MT6359_RG_BUCK_VS2_VOSEL_SHIFT 0 +#define MT6359_RG_BUCK_VPA_EN_ADDR MT6359_BUCK_VPA_CON0 +#define MT6359_RG_BUCK_VPA_LP_ADDR MT6359_BUCK_VPA_CON0 +#define MT6359_RG_BUCK_VPA_LP_SHIFT 1 +#define MT6359_RG_BUCK_VPA_VOSEL_ADDR MT6359_BUCK_VPA_CON1 +#define MT6359_RG_BUCK_VPA_VOSEL_MASK 0x3F +#define MT6359_RG_BUCK_VPA_VOSEL_SHIFT 0 +#define MT6359_DA_VPA_EN_ADDR MT6359_BUCK_VPA_DBG1 +#define MT6359_RG_VGPU11_FCCM_ADDR MT6359_VGPUVCORE_ANA_CON2 +#define MT6359_RG_VGPU11_FCCM_SHIFT 9 +#define MT6359_RG_VCORE_FCCM_ADDR MT6359_VGPUVCORE_ANA_CON13 +#define MT6359_RG_VCORE_FCCM_SHIFT 5 +#define MT6359_RG_VPROC1_FCCM_ADDR MT6359_VPROC1_ANA_CON3 +#define MT6359_RG_VPROC1_FCCM_SHIFT 1 +#define MT6359_RG_VPROC2_FCCM_ADDR MT6359_VPROC2_ANA_CON3 +#define MT6359_RG_VPROC2_FCCM_SHIFT 1 +#define MT6359_RG_VMODEM_FCCM_ADDR MT6359_VMODEM_ANA_CON3 +#define MT6359_RG_VMODEM_FCCM_SHIFT 1 +#define MT6359_RG_VPU_FCCM_ADDR MT6359_VPU_ANA_CON3 +#define MT6359_RG_VPU_FCCM_SHIFT 1 +#define MT6359_RG_VS1_FPWM_ADDR MT6359_VS1_ANA_CON0 +#define MT6359_RG_VS1_FPWM_SHIFT 3 +#define MT6359_RG_VS2_FPWM_ADDR MT6359_VS2_ANA_CON0 +#define MT6359_RG_VS2_FPWM_SHIFT 3 +#define MT6359_RG_VPA_MODESET_ADDR MT6359_VPA_ANA_CON0 +#define MT6359_RG_VPA_MODESET_SHIFT 1 +#define MT6359_RG_LDO_VSRAM_PROC1_VOSEL_MASK 0x7F +#define MT6359_RG_LDO_VSRAM_PROC1_VOSEL_SHIFT 0 +#define MT6359_RG_LDO_VSRAM_PROC2_VOSEL_MASK 0x7F +#define MT6359_RG_LDO_VSRAM_PROC2_VOSEL_SHIFT 0 +#define MT6359_RG_LDO_VSRAM_OTHERS_VOSEL_MASK 0x7F +#define MT6359_RG_LDO_VSRAM_OTHERS_VOSEL_SHIFT 0 +#define MT6359_RG_LDO_VSRAM_MD_VOSEL_MASK 0x7F +#define MT6359_RG_LDO_VSRAM_MD_VOSEL_SHIFT 0 +#define MT6359_RG_LDO_VCN33_1_EN_0_SHIFT 0 +#define MT6359_RG_LDO_VCN33_2_EN_1_SHIFT 15 +#define MT6359_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL_MASK 0x7F +#define MT6359_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL_SHIFT 1 +#define MT6359_RG_VCN33_1_VOSEL_MASK 0xF +#define MT6359_RG_VCN33_1_VOSEL_SHIFT 8 +#define MT6359_RG_VCN33_2_VOSEL_MASK 0xF +#define MT6359_RG_VCN33_2_VOSEL_SHIFT 8 +#define MT6359_RG_VSIM1_VOSEL_MASK 0xF +#define MT6359_RG_VSIM1_VOSEL_SHIFT 8 +#define MT6359_RG_VSIM2_VOSEL_MASK 0xF +#define MT6359_RG_VSIM2_VOSEL_SHIFT 8 +#define MT6359_RG_VIO28_VOSEL_MASK 0xF +#define MT6359_RG_VIO28_VOSEL_SHIFT 8 +#define MT6359_RG_VIBR_VOSEL_MASK 0xF +#define MT6359_RG_VIBR_VOSEL_SHIFT 8 +#define MT6359_RG_VRF18_VOSEL_MASK 0xF +#define MT6359_RG_VRF18_VOSEL_SHIFT 8 +#define MT6359_RG_VEFUSE_VOSEL_MASK 0xF +#define MT6359_RG_VEFUSE_VOSEL_SHIFT 8 +#define MT6359_RG_VCAMIO_VOSEL_MASK 0xF +#define MT6359_RG_VCAMIO_VOSEL_SHIFT 8 +#define MT6359_RG_VIO18_VOSEL_MASK 0xF +#define MT6359_RG_VIO18_VOSEL_SHIFT 8 +#define MT6359_RG_VM18_VOSEL_MASK 0xF +#define MT6359_RG_VM18_VOSEL_SHIFT 8 +#define MT6359_RG_VUFS_VOSEL_MASK 0xF +#define MT6359_RG_VUFS_VOSEL_SHIFT 8 +#define MT6359_RG_VRF12_VOSEL_MASK 0xF +#define MT6359_RG_VRF12_VOSEL_SHIFT 8 +#define MT6359_RG_VCN13_VOSEL_MASK 0xF +#define MT6359_RG_VCN13_VOSEL_SHIFT 8 +#define MT6359_RG_VA09_VOSEL_MASK 0xF +#define MT6359_RG_VA09_VOSEL_SHIFT 8 +#define MT6359_RG_VA12_VOSEL_MASK 0xF +#define MT6359_RG_VA12_VOSEL_SHIFT 8 +#define MT6359_RG_VXO22_VOSEL_MASK 0xF +#define MT6359_RG_VXO22_VOSEL_SHIFT 8 +#define MT6359_RG_VRFCK_VOSEL_MASK 0xF +#define MT6359_RG_VRFCK_VOSEL_SHIFT 8 + +#endif diff --git a/include/power/mt6359p.h b/include/power/mt6359p.h new file mode 100644 index 00000000000..506b5d38c68 --- /dev/null +++ b/include/power/mt6359p.h @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2026 MediaTek Inc. All Rights Reserved. + * Author: Bo-Chen Chen <rex-bc.chen@mediatek.com> + */ + +#ifndef __MT6359P_H_ +#define __MT6359P_H_ + +#define MT6359P_CHIP_VER 0x5930 + +/* PMIC Registers */ +#define MT6359P_HWCID 0x8 +#define MT6359P_TOP_TRAP 0x50 +#define MT6359P_TOP_TMA_KEY 0x3a8 +#define MT6359P_BUCK_VCORE_ELR0 0x152c +#define MT6359P_BUCK_VGPU11_SSHUB_CON0 0x15aa +#define MT6359P_BUCK_VGPU11_ELR0 0x15b4 +#define MT6359P_LDO_VSRAM_PROC1_ELR 0x1b44 +#define MT6359P_LDO_VSRAM_PROC2_ELR 0x1b46 +#define MT6359P_LDO_VSRAM_OTHERS_ELR 0x1b48 +#define MT6359P_LDO_VSRAM_MD_ELR 0x1b4a +#define MT6359P_LDO_VEMC_ELR_0 0x1b4c +#define MT6359P_LDO_VFE28_CON0 0x1b88 +#define MT6359P_LDO_VFE28_MON 0x1b8c +#define MT6359P_LDO_VXO22_CON0 0x1b9a +#define MT6359P_LDO_VXO22_MON 0x1b9e +#define MT6359P_LDO_VRF18_CON0 0x1bac +#define MT6359P_LDO_VRF18_MON 0x1bb0 +#define MT6359P_LDO_VRF12_CON0 0x1bbe +#define MT6359P_LDO_VRF12_MON 0x1bc2 +#define MT6359P_LDO_VEFUSE_CON0 0x1bd0 +#define MT6359P_LDO_VEFUSE_MON 0x1bd4 +#define MT6359P_LDO_VCN33_1_CON0 0x1be2 +#define MT6359P_LDO_VCN33_1_MON 0x1be6 +#define MT6359P_LDO_VCN33_1_MULTI_SW 0x1bf4 +#define MT6359P_LDO_VCN33_2_CON0 0x1c08 +#define MT6359P_LDO_VCN33_2_MON 0x1c0c +#define MT6359P_LDO_VCN33_2_MULTI_SW 0x1c1a +#define MT6359P_LDO_VCN13_CON0 0x1c1c +#define MT6359P_LDO_VCN13_MON 0x1c20 +#define MT6359P_LDO_VCN18_CON0 0x1c2e +#define MT6359P_LDO_VCN18_MON 0x1c32 +#define MT6359P_LDO_VA09_CON0 0x1c40 +#define MT6359P_LDO_VA09_MON 0x1c44 +#define MT6359P_LDO_VCAMIO_CON0 0x1c52 +#define MT6359P_LDO_VCAMIO_MON 0x1c56 +#define MT6359P_LDO_VA12_CON0 0x1c64 +#define MT6359P_LDO_VA12_MON 0x1c68 +#define MT6359P_LDO_VAUX18_CON0 0x1c88 +#define MT6359P_LDO_VAUX18_MON 0x1c8c +#define MT6359P_LDO_VAUD18_CON0 0x1c9a +#define MT6359P_LDO_VAUD18_MON 0x1c9e +#define MT6359P_LDO_VIO18_CON0 0x1cac +#define MT6359P_LDO_VIO18_MON 0x1cb0 +#define MT6359P_LDO_VEMC_CON0 0x1cbe +#define MT6359P_LDO_VEMC_MON 0x1cc2 +#define MT6359P_LDO_VSIM1_CON0 0x1cd0 +#define MT6359P_LDO_VSIM1_MON 0x1cd4 +#define MT6359P_LDO_VSIM2_CON0 0x1ce2 +#define MT6359P_LDO_VSIM2_MON 0x1ce6 +#define MT6359P_LDO_VUSB_CON0 0x1d08 +#define MT6359P_LDO_VUSB_MON 0x1d0c +#define MT6359P_LDO_VRFCK_CON0 0x1d1c +#define MT6359P_LDO_VRFCK_MON 0x1d20 +#define MT6359P_LDO_VBBCK_CON0 0x1d2e +#define MT6359P_LDO_VBBCK_MON 0x1d32 +#define MT6359P_LDO_VBIF28_CON0 0x1d40 +#define MT6359P_LDO_VBIF28_MON 0x1d44 +#define MT6359P_LDO_VIBR_CON0 0x1d52 +#define MT6359P_LDO_VIBR_MON 0x1d56 +#define MT6359P_LDO_VIO28_CON0 0x1d64 +#define MT6359P_LDO_VIO28_MON 0x1d68 +#define MT6359P_LDO_VM18_CON0 0x1d88 +#define MT6359P_LDO_VM18_MON 0x1d8c +#define MT6359P_LDO_VUFS_CON0 0x1d9a +#define MT6359P_LDO_VUFS_MON 0x1d9e +#define MT6359P_LDO_VSRAM_PROC1_CON0 0x1e88 +#define MT6359P_LDO_VSRAM_PROC1_MON 0x1e8c +#define MT6359P_LDO_VSRAM_PROC2_CON0 0x1ea8 +#define MT6359P_LDO_VSRAM_PROC2_MON 0x1eac +#define MT6359P_LDO_VSRAM_OTHERS_CON0 0x1f08 +#define MT6359P_LDO_VSRAM_OTHERS_MON 0x1f0c +#define MT6359P_LDO_VSRAM_OTHERS_SSHUB 0x1f28 +#define MT6359P_LDO_VSRAM_MD_CON0 0x1f2e +#define MT6359P_LDO_VSRAM_MD_MON 0x1f32 +#define MT6359P_VCN33_1_ANA_CON0 0x1f98 +#define MT6359P_VCN33_2_ANA_CON0 0x1f9c +#define MT6359P_VSIM1_ANA_CON0 0x1fa2 +#define MT6359P_VSIM2_ANA_CON0 0x1fa6 +#define MT6359P_VIO28_ANA_CON0 0x1faa +#define MT6359P_VIBR_ANA_CON0 0x1fae +#define MT6359P_VFE28_ELR_4 0x1fc0 +#define MT6359P_VRF18_ANA_CON0 0x2008 +#define MT6359P_VEFUSE_ANA_CON0 0x200c +#define MT6359P_VCAMIO_ANA_CON0 0x2014 +#define MT6359P_VIO18_ANA_CON0 0x201c +#define MT6359P_VM18_ANA_CON0 0x2020 +#define MT6359P_VUFS_ANA_CON0 0x2024 +#define MT6359P_VRF12_ANA_CON0 0x202a +#define MT6359P_VCN13_ANA_CON0 0x202e +#define MT6359P_VRF18_ELR_3 0x204e +#define MT6359P_VXO22_ANA_CON0 0x2088 +#define MT6359P_VRFCK_ANA_CON0 0x208c +#define MT6359P_VBBCK_ANA_CON0 0x2096 + +#define MT6359P_RG_BUCK_VCORE_VOSEL_ADDR MT6359P_BUCK_VCORE_ELR0 +#define MT6359P_RG_BUCK_VGPU11_SSHUB_EN_ADDR MT6359P_BUCK_VGPU11_SSHUB_CON0 +#define MT6359P_RG_BUCK_VGPU11_VOSEL_ADDR MT6359P_BUCK_VGPU11_ELR0 +#define MT6359P_RG_BUCK_VGPU11_SSHUB_VOSEL_ADDR MT6359P_BUCK_VGPU11_SSHUB_CON0 +#define MT6359P_RG_BUCK_VGPU11_SSHUB_VOSEL_MASK 0x7F +#define MT6359P_RG_BUCK_VGPU11_SSHUB_VOSEL_SHIFT 4 +#define MT6359P_RG_LDO_VSRAM_PROC1_VOSEL_ADDR MT6359P_LDO_VSRAM_PROC1_ELR +#define MT6359P_RG_LDO_VSRAM_PROC2_VOSEL_ADDR MT6359P_LDO_VSRAM_PROC2_ELR +#define MT6359P_RG_LDO_VSRAM_OTHERS_VOSEL_ADDR MT6359P_LDO_VSRAM_OTHERS_ELR +#define MT6359P_RG_LDO_VSRAM_MD_VOSEL_ADDR MT6359P_LDO_VSRAM_MD_ELR +#define MT6359P_RG_LDO_VEMC_VOSEL_0_ADDR MT6359P_LDO_VEMC_ELR_0 +#define MT6359P_RG_LDO_VEMC_VOSEL_0_MASK 0xF +#define MT6359P_RG_LDO_VEMC_VOSEL_0_SHIFT 0 +#define MT6359P_RG_LDO_VFE28_EN_ADDR MT6359P_LDO_VFE28_CON0 +#define MT6359P_DA_VFE28_B_EN_ADDR MT6359P_LDO_VFE28_MON +#define MT6359P_RG_LDO_VXO22_EN_ADDR MT6359P_LDO_VXO22_CON0 +#define MT6359P_RG_LDO_VXO22_EN_SHIFT 0 +#define MT6359P_DA_VXO22_B_EN_ADDR MT6359P_LDO_VXO22_MON +#define MT6359P_RG_LDO_VRF18_EN_ADDR MT6359P_LDO_VRF18_CON0 +#define MT6359P_RG_LDO_VRF18_EN_SHIFT 0 +#define MT6359P_DA_VRF18_B_EN_ADDR MT6359P_LDO_VRF18_MON +#define MT6359P_RG_LDO_VRF12_EN_ADDR MT6359P_LDO_VRF12_CON0 +#define MT6359P_RG_LDO_VRF12_EN_SHIFT 0 +#define MT6359P_DA_VRF12_B_EN_ADDR MT6359P_LDO_VRF12_MON +#define MT6359P_RG_LDO_VEFUSE_EN_ADDR MT6359P_LDO_VEFUSE_CON0 +#define MT6359P_RG_LDO_VEFUSE_EN_SHIFT 0 +#define MT6359P_DA_VEFUSE_B_EN_ADDR MT6359P_LDO_VEFUSE_MON +#define MT6359P_RG_LDO_VCN33_1_EN_0_ADDR MT6359P_LDO_VCN33_1_CON0 +#define MT6359P_DA_VCN33_1_B_EN_ADDR MT6359P_LDO_VCN33_1_MON +#define MT6359P_RG_LDO_VCN33_1_EN_1_ADDR MT6359P_LDO_VCN33_1_MULTI_SW +#define MT6359P_RG_LDO_VCN33_1_EN_1_SHIFT 15 +#define MT6359P_RG_LDO_VCN33_2_EN_0_ADDR MT6359P_LDO_VCN33_2_CON0 +#define MT6359P_RG_LDO_VCN33_2_EN_0_SHIFT 0 +#define MT6359P_DA_VCN33_2_B_EN_ADDR MT6359P_LDO_VCN33_2_MON +#define MT6359P_RG_LDO_VCN33_2_EN_1_ADDR MT6359P_LDO_VCN33_2_MULTI_SW +#define MT6359P_RG_LDO_VCN13_EN_ADDR MT6359P_LDO_VCN13_CON0 +#define MT6359P_RG_LDO_VCN13_EN_SHIFT 0 +#define MT6359P_DA_VCN13_B_EN_ADDR MT6359P_LDO_VCN13_MON +#define MT6359P_RG_LDO_VCN18_EN_ADDR MT6359P_LDO_VCN18_CON0 +#define MT6359P_DA_VCN18_B_EN_ADDR MT6359P_LDO_VCN18_MON +#define MT6359P_RG_LDO_VA09_EN_ADDR MT6359P_LDO_VA09_CON0 +#define MT6359P_RG_LDO_VA09_EN_SHIFT 0 +#define MT6359P_DA_VA09_B_EN_ADDR MT6359P_LDO_VA09_MON +#define MT6359P_RG_LDO_VCAMIO_EN_ADDR MT6359P_LDO_VCAMIO_CON0 +#define MT6359P_RG_LDO_VCAMIO_EN_SHIFT 0 +#define MT6359P_DA_VCAMIO_B_EN_ADDR MT6359P_LDO_VCAMIO_MON +#define MT6359P_RG_LDO_VA12_EN_ADDR MT6359P_LDO_VA12_CON0 +#define MT6359P_RG_LDO_VA12_EN_SHIFT 0 +#define MT6359P_DA_VA12_B_EN_ADDR MT6359P_LDO_VA12_MON +#define MT6359P_RG_LDO_VAUX18_EN_ADDR MT6359P_LDO_VAUX18_CON0 +#define MT6359P_DA_VAUX18_B_EN_ADDR MT6359P_LDO_VAUX18_MON +#define MT6359P_RG_LDO_VAUD18_EN_ADDR MT6359P_LDO_VAUD18_CON0 +#define MT6359P_DA_VAUD18_B_EN_ADDR MT6359P_LDO_VAUD18_MON +#define MT6359P_RG_LDO_VIO18_EN_ADDR MT6359P_LDO_VIO18_CON0 +#define MT6359P_RG_LDO_VIO18_EN_SHIFT 0 +#define MT6359P_DA_VIO18_B_EN_ADDR MT6359P_LDO_VIO18_MON +#define MT6359P_RG_LDO_VEMC_EN_ADDR MT6359P_LDO_VEMC_CON0 +#define MT6359P_RG_LDO_VEMC_EN_SHIFT 0 +#define MT6359P_DA_VEMC_B_EN_ADDR MT6359P_LDO_VEMC_MON +#define MT6359P_RG_LDO_VSIM1_EN_ADDR MT6359P_LDO_VSIM1_CON0 +#define MT6359P_RG_LDO_VSIM1_EN_SHIFT 0 +#define MT6359P_DA_VSIM1_B_EN_ADDR MT6359P_LDO_VSIM1_MON +#define MT6359P_RG_LDO_VSIM2_EN_ADDR MT6359P_LDO_VSIM2_CON0 +#define MT6359P_RG_LDO_VSIM2_EN_SHIFT 0 +#define MT6359P_DA_VSIM2_B_EN_ADDR MT6359P_LDO_VSIM2_MON +#define MT6359P_RG_LDO_VUSB_EN_0_ADDR MT6359P_LDO_VUSB_CON0 +#define MT6359P_DA_VUSB_B_EN_ADDR MT6359P_LDO_VUSB_MON +#define MT6359P_RG_LDO_VRFCK_EN_ADDR MT6359P_LDO_VRFCK_CON0 +#define MT6359P_RG_LDO_VRFCK_EN_SHIFT 0 +#define MT6359P_DA_VRFCK_B_EN_ADDR MT6359P_LDO_VRFCK_MON +#define MT6359P_RG_LDO_VBBCK_EN_ADDR MT6359P_LDO_VBBCK_CON0 +#define MT6359P_RG_LDO_VBBCK_EN_SHIFT 0 +#define MT6359P_DA_VBBCK_B_EN_ADDR MT6359P_LDO_VBBCK_MON +#define MT6359P_RG_LDO_VBIF28_EN_ADDR MT6359P_LDO_VBIF28_CON0 +#define MT6359P_DA_VBIF28_B_EN_ADDR MT6359P_LDO_VBIF28_MON +#define MT6359P_RG_LDO_VIBR_EN_ADDR MT6359P_LDO_VIBR_CON0 +#define MT6359P_RG_LDO_VIBR_EN_SHIFT 0 +#define MT6359P_DA_VIBR_B_EN_ADDR MT6359P_LDO_VIBR_MON +#define MT6359P_RG_LDO_VIO28_EN_ADDR MT6359P_LDO_VIO28_CON0 +#define MT6359P_RG_LDO_VIO28_EN_SHIFT 0 +#define MT6359P_DA_VIO28_B_EN_ADDR MT6359P_LDO_VIO28_MON +#define MT6359P_RG_LDO_VM18_EN_ADDR MT6359P_LDO_VM18_CON0 +#define MT6359P_RG_LDO_VM18_EN_SHIFT 0 +#define MT6359P_DA_VM18_B_EN_ADDR MT6359P_LDO_VM18_MON +#define MT6359P_RG_LDO_VUFS_EN_ADDR MT6359P_LDO_VUFS_CON0 +#define MT6359P_RG_LDO_VUFS_EN_SHIFT 0 +#define MT6359P_DA_VUFS_B_EN_ADDR MT6359P_LDO_VUFS_MON +#define MT6359P_RG_LDO_VSRAM_PROC1_EN_ADDR MT6359P_LDO_VSRAM_PROC1_CON0 +#define MT6359P_DA_VSRAM_PROC1_B_EN_ADDR MT6359P_LDO_VSRAM_PROC1_MON +#define MT6359P_RG_LDO_VSRAM_PROC2_EN_ADDR MT6359P_LDO_VSRAM_PROC2_CON0 +#define MT6359P_DA_VSRAM_PROC2_B_EN_ADDR MT6359P_LDO_VSRAM_PROC2_MON +#define MT6359P_RG_LDO_VSRAM_OTHERS_EN_ADDR MT6359P_LDO_VSRAM_OTHERS_CON0 +#define MT6359P_DA_VSRAM_OTHERS_B_EN_ADDR MT6359P_LDO_VSRAM_OTHERS_MON +#define MT6359P_RG_LDO_VSRAM_OTHERS_SSHUB_EN_ADDR MT6359P_LDO_VSRAM_OTHERS_SSHUB +#define MT6359P_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL_ADDR MT6359P_LDO_VSRAM_OTHERS_SSHUB +#define MT6359P_RG_LDO_VSRAM_MD_EN_ADDR MT6359P_LDO_VSRAM_MD_CON0 +#define MT6359P_DA_VSRAM_MD_B_EN_ADDR MT6359P_LDO_VSRAM_MD_MON +#define MT6359P_RG_VCN33_1_VOSEL_ADDR MT6359P_VCN33_1_ANA_CON0 +#define MT6359P_RG_VCN33_2_VOSEL_ADDR MT6359P_VCN33_2_ANA_CON0 +#define MT6359P_RG_VSIM1_VOSEL_ADDR MT6359P_VSIM1_ANA_CON0 +#define MT6359P_RG_VSIM2_VOSEL_ADDR MT6359P_VSIM2_ANA_CON0 +#define MT6359P_RG_VIO28_VOSEL_ADDR MT6359P_VIO28_ANA_CON0 +#define MT6359P_RG_VIBR_VOSEL_ADDR MT6359P_VIBR_ANA_CON0 +#define MT6359P_RG_VRF18_VOSEL_ADDR MT6359P_VRF18_ANA_CON0 +#define MT6359P_RG_VEFUSE_VOSEL_ADDR MT6359P_VEFUSE_ANA_CON0 +#define MT6359P_RG_VCAMIO_VOSEL_ADDR MT6359P_VCAMIO_ANA_CON0 +#define MT6359P_RG_VIO18_VOSEL_ADDR MT6359P_VIO18_ANA_CON0 +#define MT6359P_RG_VM18_VOSEL_ADDR MT6359P_VM18_ANA_CON0 +#define MT6359P_RG_VUFS_VOSEL_ADDR MT6359P_VUFS_ANA_CON0 +#define MT6359P_RG_VRF12_VOSEL_ADDR MT6359P_VRF12_ANA_CON0 +#define MT6359P_RG_VCN13_VOSEL_ADDR MT6359P_VCN13_ANA_CON0 +#define MT6359P_RG_VA09_VOSEL_ADDR MT6359P_VRF18_ELR_3 +#define MT6359P_RG_VA12_VOSEL_ADDR MT6359P_VFE28_ELR_4 +#define MT6359P_RG_VXO22_VOSEL_ADDR MT6359P_VXO22_ANA_CON0 +#define MT6359P_RG_VRFCK_VOSEL_ADDR MT6359P_VRFCK_ANA_CON0 +#define MT6359P_RG_VBBCK_VOSEL_ADDR MT6359P_VBBCK_ANA_CON0 +#define MT6359P_RG_VBBCK_VOSEL_MASK 0xF +#define MT6359P_RG_VBBCK_VOSEL_SHIFT 4 +#define MT6359P_VM_MODE_ADDR MT6359P_TOP_TRAP +#define MT6359P_TMA_KEY_ADDR MT6359P_TOP_TMA_KEY + +#define MT6359P_TMA_KEY 0x9CA6 + +#endif |
