diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm_pmic_lp.c b/plat/mediatek/drivers/spm/mt8196/mt_spm_pmic_lp.c new file mode 100644 index 000000000..e15e1ff5f --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/mt_spm_pmic_lp.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +/* SPMI_M: 6363, SPMI_P: 6373/6316 */ +/* SPMI_M: 6363, SPMI_P: 6373/6316 */ +static struct lp_pmic_cfg { + uint8_t slave; + uint8_t master; + char *name; +} pmics[] = { + [LP_MT6363] = {MT6363_SLAVE, SPMI_MASTER_1, "MT6363"}, + [LP_MT6373] = {MT6373_SLAVE, SPMI_MASTER_P_1, "MT6373"}, + [LP_MT6316_1] = {MT6316_S8_SLAVE, SPMI_MASTER_P_1, "MT6316_S8"}, + [LP_MT6316_2] = {MT6316_S6_SLAVE, SPMI_MASTER_P_1, "MT6316_S6"}, + [LP_MT6316_3] = {MT6316_S7_SLAVE, SPMI_MASTER_P_1, "MT6316_S7"}, + [LP_MT6316_4] = {MT6316_S15_SLAVE, SPMI_MASTER_P_1, "MT6316_S15"}, +}; + +#ifdef MTK_SPM_PMIC_GS_DUMP +static struct pmic_gs_info pmic_gs_dump_info; +static char *pmic_str[] = { + [LP_MT6363] = "MT6363", + [LP_MT6373] = "MT6373", + [LP_MT6316_1] = "MT6316_1", + [LP_MT6316_2] = "MT6316_2", + [LP_MT6316_3] = "MT6316_3", + [LP_MT6316_4] = "MT6316_4", +}; +#endif +struct spmi_device *lp_sdev[LP_PMIC_SLAVE_NUM]; + +#define VSRAM_CORE_0_35V 56 +#define VSRAM_CORE_0_55V 88 +#define VSRAM_CORE_0_75V 120 + +/* VSRAM_CORE Low bound */ +#ifdef MTK_AGING_FLAVOR_LOAD +#define SUSPEND_AGING_VAL_SHIFT 3 +#define SUSPEND_AGING_VAL_DEFAULT 85 +#define VSRAM_CORE_LOWBOUND (74 - SUSPEND_AGING_VAL_SHIFT) +#else +#define VSRAM_CORE_LOWBOUND 74 +#endif +#define MT6363_LP_REG 0x1687 +#define MT6363_VIO18_SWITCH 0x53 +#define MT6373_VIO18_SWITCH 0x58 + +static uint32_t vcore_sram_suspend_vol = VSRAM_CORE_0_55V; +static bool vcore_sram_lp_enable = true; +static bool vcore_lp_enable = true; + +static uint32_t get_vcore_sram_suspend_vol(void) +{ + uint8_t value; + /* Set vcore_sram to 0.55V by default */ + value = VSRAM_CORE_0_55V; + +#ifdef MTK_AGING_FLAVOR_LOAD + value -= SUSPEND_AGING_VAL_SHIFT; + if (value > SUSPEND_AGING_VAL_DEFAULT) + value = SUSPEND_AGING_VAL_DEFAULT; + INFO("%s(%d) enable aging with value: %u\n", + __func__, __LINE__, value); +#endif + return value; +} + +#ifdef MTK_SPM_PMIC_GS_DUMP +static void mt_spm_dump_pmic_gs(uint32_t cmd) +{ +#ifdef MTK_SPM_PMIC_GS_DUMP_SUSPEND + if (cmd & MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND) { /* Suspend enter */ + mt_spm_pmic_gs_dump(SUSPEND, LP_MT6363); + mt_spm_pmic_gs_dump(SUSPEND, LP_MT6373); + } +#endif + if (cmd & MT_RM_CONSTRAINT_ALLOW_VCORE_LP) { + if (cmd & MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF) { /* SODI3 */ +#ifdef MTK_SPM_PMIC_GS_DUMP_SODI3 + mt_spm_pmic_gs_dump(SODI3, LP_MT6363); + mt_spm_pmic_gs_dump(SODI3, LP_MT6373); +#endif + } else { /* DPIDLE enter */ +#ifdef MTK_SPM_PMIC_GS_DUMP_DPIDLE + mt_spm_pmic_gs_dump(DPIDLE, LP_MT6363); + mt_spm_pmic_gs_dump(DPIDLE, LP_MT6373); +#endif + } + } +} +#endif + +int spm_lp_setting_init(void) +{ + uint8_t i, slvid, spmi_master; + + for (i = 0; i < ARRAY_SIZE(pmics); i++) { + slvid = pmics[i].slave; + spmi_master = pmics[i].master; + lp_sdev[i] = get_spmi_device(spmi_master, slvid); + if (!lp_sdev[i]) + return -ENODEV; + } + + PMIC_SLVID_BUCK_SET_LP(MT6316, S8, VBUCK1, RC8, + false, OP_MODE_LP, HW_OFF); + + /* Get suspend case vcore_sram sleep voltage */ + vcore_sram_suspend_vol = get_vcore_sram_suspend_vol(); + +#ifdef MTK_SPM_PMIC_GS_DUMP + pmic_gs_dump_info.lp_sdev = lp_sdev; + pmic_gs_dump_info.pmic_str = pmic_str; + pmic_gs_dump_info.pmic_num = LP_PMIC_SLAVE_NUM; +#ifdef MTK_SPM_PMIC_GS_DUMP_SUSPEND + pmic_gs_dump_info.scen_gs[SUSPEND].data = pmic_gs_suspend; +#endif +#ifdef MTK_SPM_PMIC_GS_DUMP_SODI3 + pmic_gs_dump_info.scen_gs[SODI3].data = pmic_gs_sodi3; +#endif +#ifdef MTK_SPM_PMIC_GS_DUMP_DPIDLE + pmic_gs_dump_info.scen_gs[DPIDLE].data = pmic_gs_dpidle; +#endif + return register_pmic_gs_info(&pmic_gs_dump_info); +#else + return 0; +#endif +} + +#ifdef MTK_SPM_PMIC_LP_SUPPORT +MTK_PLAT_SETUP_0_INIT(spm_lp_setting_init); +#endif + +void set_vcore_lp_enable(bool enable) +{ + vcore_lp_enable = enable; +} + +bool get_vcore_lp_enable(void) +{ + return vcore_lp_enable; +} + +void set_vsram_lp_enable(bool enable) +{ + vcore_sram_lp_enable = enable; +} + +bool get_vsram_lp_enable(void) +{ + return vcore_sram_lp_enable; +} + +void set_vsram_lp_volt(uint32_t volt) +{ + /* Allow 0.35V ~ 0.75V */ + if (volt < VSRAM_CORE_0_35V || volt > VSRAM_CORE_0_75V) + return; + vcore_sram_suspend_vol = volt; +} + +uint32_t get_vsram_lp_volt(void) +{ + return vcore_sram_suspend_vol; +} + +static int pmic_lp_setting(uint8_t data) +{ + int ret; + + if (data != 0x0 && data != 0x1) + return -ENODEV; + /* SUSPEND:VS1 HW2&RC9 normal mode */ + PMIC_BUCK_SET_LP(MT6363, VS1, HW2, + false, OP_MODE_LP, HW_LP); + PMIC_BUCK_SET_LP(MT6363, VS1, RC9, + false, OP_MODE_MU, HW_ON); + PMIC_LDO_SET_LP(MT6363, VIO18, HW2, + false, OP_MODE_LP, HW_LP); + PMIC_LDO_SET_LP(MT6363, VIO18, RC9, + false, OP_MODE_MU, HW_ON); + + /* Switch DIG18 to VIO18 for power saving */ + ret = spmi_ext_register_writel(lp_sdev[LP_MT6363], MT6363_VIO18_SWITCH, &data, 1); + if (ret) + INFO("MT6363 RG_VIO18 spmi failed\n"); + + ret = spmi_ext_register_writel(lp_sdev[LP_MT6373], MT6373_VIO18_SWITCH, &data, 1); + if (ret) + INFO("MT6373 RG_VIO18 spmi failed\n"); + return ret; +} + +int do_spm_low_power(enum SPM_PWR_TYPE type, uint32_t cmd) +{ + int ret; + uint8_t value; + bool enter_suspend, vcore_sram_lp = false; + + if (type == SPM_LP_ENTER) { + enter_suspend = true; + vcore_sram_lp = vcore_sram_lp_enable; + + if (cmd & MT_RM_CONSTRAINT_ALLOW_AP_PLAT_SUSPEND) { + value = vcore_sram_suspend_vol; + if (value < VSRAM_CORE_LOWBOUND || + value > VSRAM_CORE_0_75V) { + INFO("Vsram_core voltage wrong\n"); + panic(); + } + } else { + value = VSRAM_CORE_0_55V; + } + } else { + enter_suspend = false; + vcore_sram_lp = false; + value = VSRAM_CORE_0_75V; + } + /* Enable VA12_2/VSRAM_CPUL HW_LP for suspend/idle */ + PMIC_LDO_SET_LP(MT6363, VA12_2, HW2, enter_suspend, OP_MODE_LP, HW_LP); + PMIC_LDO_SET_LP(MT6363, VSRAM_CPUL, HW2, + enter_suspend, OP_MODE_LP, HW_LP); + + if (!(cmd & MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND)) + return 0; + PMIC_SLVID_BUCK_SET_LP(MT6316, S8, VBUCK1, HW2, vcore_lp_enable, + OP_MODE_LP, HW_LP); + PMIC_BUCK_SET_LP(MT6363, VBUCK4, HW0, vcore_sram_lp, + OP_MODE_LP, HW_LP); + PMIC_BUCK_SET_LP(MT6363, VBUCK4, HW2, !enter_suspend, + OP_MODE_LP, HW_LP); + ret = spmi_ext_register_writel(lp_sdev[LP_MT6363], MT6363_LP_REG, &value, 1); + if (ret) + INFO("BUCK(VSRAM_CORE) spmi write failed\n"); + + if (cmd & MT_RM_CONSTRAINT_ALLOW_AP_PLAT_SUSPEND) + pmic_lp_setting(enter_suspend ? 1 : 0); + + return 0; +} diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm_pmic_lp.h b/plat/mediatek/drivers/spm/mt8196/mt_spm_pmic_lp.h new file mode 100644 index 000000000..0ba305e68 --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/mt_spm_pmic_lp.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_PMIC_LP_H +#define MT_SPM_PMIC_LP_H + +enum SPM_PWR_TYPE { + SPM_LP_ENTER, + SPM_LP_RESUME +}; + +enum { + LP_MT6363 = 0, + LP_MT6373, + LP_MT6316_1, + LP_MT6316_2, + LP_MT6316_3, + LP_MT6316_4, + LP_PMIC_SLAVE_NUM, +}; + +#ifdef MTK_SPM_PMIC_LP_SUPPORT +void set_vcore_lp_enable(bool enable); +bool get_vcore_lp_enable(void); + +void set_vsram_lp_enable(bool enable); +bool get_vsram_lp_enable(void); +void set_vsram_lp_volt(uint32_t volt); +uint32_t get_vsram_lp_volt(void); + +int do_spm_low_power(enum SPM_PWR_TYPE type, uint32_t cmd); +#else +static inline void set_vcore_lp_enable(bool enable) +{ + (void)enable; +} + +static inline bool get_vcore_lp_enable(void) +{ + return false; +} + +static inline void set_vsram_lp_enable(bool enable) +{ + (void)enable; +} + +static inline bool get_vsram_lp_enable(void) +{ + return false; +} + +static inline void set_vsram_lp_volt(uint32_t volt) +{ + (void)volt; +} + +static inline uint32_t get_vsram_lp_volt(void) +{ + return 0; +} + +static inline int do_spm_low_power(enum SPM_PWR_TYPE type, uint32_t cmd) +{ + (void)type; + (void)cmd; + return 0; +} +#endif /* MTK_SPM_PMIC_LP_SUPPORT */ + +#endif /* MT_SPM_PMIC_LP_H */ diff --git a/plat/mediatek/drivers/spm/mt8196/plat_conf.mk b/plat/mediatek/drivers/spm/mt8196/plat_conf.mk new file mode 100644 index 000000000..7bf958eaa --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/plat_conf.mk @@ -0,0 +1,117 @@ +# +# Copyright (c) 2025, MediaTek Inc. All rights reserved. + +# SPDX-License-Identifier: BSD-3-Clause +# + +NOTIFIER_VER := v4 + +PMIC_WRAP_VER := v1 + +MTK_SPM_COMMON_DRV := y + +# Enable or disable spm feature +MT_SPM_FEATURE_SUPPORT := y + +# Enable or disable cirq restore +MT_SPM_CIRQ_FEATURE_SUPPORT := y + +# Enable or disable get dram type from dramc +MT_SPMFW_LOAD_BY_DRAM_TYPE := n + +# Enable or disable sspm sram +MT_SPMFW_SPM_SRAM_SLEEP_SUPPORT := n + +# Enable or disable uart save/restore at tf-a spm driver +# mt8196 uart is restore by RTFF +MT_SPM_UART_SUSPEND_SUPPORT := n + +# Enable or disable pmic wrap reg dump +MT_SPM_PMIC_WRAP_DUMP_SUPPORT := n + +# spm timestamp support +MT_SPM_TIMESTAMP_SUPPORT := n + +MTK_SPM_PMIC_LP_SUPPORT := y + +MTK_SPM_LVTS_SUPPORT := FIXME + +MT_SPM_COMMON_SODI_SUPPORT := n + +#spm emi thermal threshold control +MT_SPM_EMI_THERMAL_CONTROL_SUPPORT := FIXME + +# spm rgu workaround +MT_SPM_RGU_WA := y + +CONSTRAINT_ID_ALL := 0xff +$(eval $(call add_defined_option,CONSTRAINT_ID_ALL)) + +ifneq (${PMIC_GS_DUMP_VER},) +$(eval $(call add_define,MTK_SPM_PMIC_GS_DUMP)) +$(eval $(call add_define,MTK_SPM_PMIC_GS_DUMP_SUSPEND)) +$(eval $(call add_define,MTK_SPM_PMIC_GS_DUMP_SODI3)) +$(eval $(call add_define,MTK_SPM_PMIC_GS_DUMP_DPIDLE)) +endif + +ifeq (${MT_SPM_FEATURE_SUPPORT},n) +$(eval $(call add_define,MTK_PLAT_SPM_UNSUPPORT)) +else +$(eval $(call add_define,MT_SPM_FEATURE_SUPPORT)) +endif + +ifeq (${MT_SPMFW_LOAD_BY_DRAM_TYPE},n) +$(eval $(call add_define,MTK_PLAT_DRAMC_UNSUPPORT)) +endif + +ifeq (${MT_SPM_CIRQ_FEATURE_SUPPORT},n) +$(eval $(call add_define,MTK_PLAT_CIRQ_UNSUPPORT)) +endif + +ifeq (${MT_SPMFW_SPM_SRAM_SLEEP_SUPPORT},n) +$(eval $(call add_define,MTK_PLAT_SPM_SRAM_SLP_UNSUPPORT)) +endif + +ifeq (${NOTIFIER_VER},) +$(eval $(call add_define,MTK_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT)) +endif + +ifeq (${MT_SPM_UART_SUSPEND_SUPPORT},n) +$(eval $(call add_define,MTK_PLAT_SPM_UART_UNSUPPORT)) +endif + +ifeq (${MT_SPM_PMIC_WRAP_DUMP_SUPPORT},n) +$(eval $(call add_define,MTK_PLAT_SPM_PMIC_WRAP_DUMP_UNSUPPORT)) +endif + +ifeq (${TRACER_VER},) +$(eval $(call add_define,MTK_PLAT_SPM_TRACE_UNSUPPORT)) +endif + +ifeq (${MT_SPM_TIMESTAMP_SUPPORT},y) +$(eval $(call add_define,MT_SPM_TIMESTAMP_SUPPORT)) +endif + +ifeq ($(MTK_VOLTAGE_BIN_VCORE),y) +$(eval $(call add_define,MTK_VOLTAGE_BIN_VCORE_SUPPORT)) +endif + +ifeq (${MTK_SPM_PMIC_LP_SUPPORT},y) +$(eval $(call add_define,MTK_SPM_PMIC_LP_SUPPORT)) +endif + +ifeq (${MTK_SPM_LVTS_SUPPORT},y) +$(eval $(call add_define,MTK_SPM_LVTS_SUPPORT)) +endif + +ifeq (${MT_SPM_COMMON_SODI_SUPPORT},y) +$(eval $(call add_define,MT_SPM_COMMON_SODI_SUPPORT)) +endif + +ifeq (${MT_SPM_EMI_THERMAL_CONTROL_SUPPORT},y) +$(eval $(call add_define,MT_SPM_EMI_THERMAL_CONTROL_SUPPORT)) +endif + +ifeq (${MT_SPM_RGU_WA},y) +$(eval $(call add_define,MT_SPM_RGU_WA)) +endif