From fb57af70ae8c93ebe806eb6281036a15113dc4f5 Mon Sep 17 00:00:00 2001 From: Wenzhen Yu Date: Fri, 20 Dec 2024 14:37:26 +0800 Subject: [PATCH] feat(mt8196): add SPM basic features support This patch mainly collects and organizes SPM state information to facilitate debugging when issues arise. Signed-off-by: Wenzhen Yu Change-Id: Ie51cffeb1d683d65d88701fc63c426b20b22492f --- .../drivers/spm/mt8196/mt_spm_dispatcher.c | 93 +++ .../drivers/spm/mt8196/mt_spm_dispatcher.h | 11 + .../drivers/spm/mt8196/mt_spm_hwreq.c | 707 ++++++++++++++++++ .../drivers/spm/mt8196/mt_spm_hwreq.h | 245 ++++++ .../drivers/spm/mt8196/mt_spm_stats.c | 65 ++ .../drivers/spm/mt8196/mt_spm_stats.h | 43 ++ plat/mediatek/drivers/spm/mt8196/pcm_def.h | 209 ++++++ plat/mediatek/drivers/spm/mt8196/sleep_def.h | 147 ++++ plat/mediatek/mt8196/include/platform_def.h | 55 ++ 9 files changed, 1575 insertions(+) create mode 100644 plat/mediatek/drivers/spm/mt8196/mt_spm_dispatcher.c create mode 100644 plat/mediatek/drivers/spm/mt8196/mt_spm_dispatcher.h create mode 100644 plat/mediatek/drivers/spm/mt8196/mt_spm_hwreq.c create mode 100644 plat/mediatek/drivers/spm/mt8196/mt_spm_hwreq.h create mode 100644 plat/mediatek/drivers/spm/mt8196/mt_spm_stats.c create mode 100644 plat/mediatek/drivers/spm/mt8196/mt_spm_stats.h create mode 100644 plat/mediatek/drivers/spm/mt8196/pcm_def.h create mode 100644 plat/mediatek/drivers/spm/mt8196/sleep_def.h diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm_dispatcher.c b/plat/mediatek/drivers/spm/mt8196/mt_spm_dispatcher.c new file mode 100644 index 000000000..879b20d3e --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/mt_spm_dispatcher.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPM_FW_BASE_SIZE 0x100000 + +static void mt_spm_pcm_wdt(int enable, uint64_t time) +{ + mmio_write_32(PCM_TIMER_VAL, time); + __spm_set_pcm_wdt(enable); +} + +static uint32_t mt_spm_phypll_mode_check(void) +{ + uint32_t val = mmio_read_32(SPM_POWER_ON_VAL0); + + return val; +} + +static uint64_t mt_spm_compatible_smc_id(uint64_t lp_id) +{ + switch (lp_id) { + case MT_LPM_SPMC_COMPAT_LK_FW_INIT: + lp_id = MT_SPM_SMC_UID_FW_INIT; + break; + default: + break; + } + return lp_id; +} + +uint64_t mt_spm_dispatcher(u_register_t lp_id, u_register_t act, + u_register_t arg1, u_register_t arg2, + void *handle, struct smccc_res *smccc_ret) +{ + uint64_t ret = 0; + + if (act & MT_LPM_SMC_ACT_COMPAT) { + lp_id = mt_spm_compatible_smc_id(lp_id); + act &= ~(MT_LPM_SMC_ACT_COMPAT); + } + + switch (lp_id) { + case MT_SPM_SMC_UID_STATUS: + if (!(arg2 & MT_SPM_STATUS_SUSPEND_SLEEP)) + break; + if (act & MT_LPM_SMC_ACT_SET) + /* Legacy audio check from kernel */ + mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SLEEP, NULL); + else if (act & MT_LPM_SMC_ACT_CLR) + mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN, + NULL); + break; + case MT_SPM_SMC_UID_PCM_WDT: + if (act & MT_LPM_SMC_ACT_SET) + mt_spm_pcm_wdt(1, arg2); + else if (act & MT_LPM_SMC_ACT_CLR) + mt_spm_pcm_wdt(0, arg2); + break; + case MT_SPM_SMC_UID_PHYPLL_MODE: + if (act & MT_LPM_SMC_ACT_GET) + ret = mt_spm_phypll_mode_check(); + break; + case MT_SPM_SMC_UID_SET_PENDING_IRQ_INIT: + spm_set_irq_num((uint32_t)arg1); + break; + default: + break; + } + return ret; +} + +int mt_spm_dispatcher_init(void) +{ + mt_lpm_dispatcher_registry(MT_LPM_SMC_USER_SPM, + mt_spm_dispatcher); + return 0; +} diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm_dispatcher.h b/plat/mediatek/drivers/spm/mt8196/mt_spm_dispatcher.h new file mode 100644 index 000000000..cf6d11cf5 --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/mt_spm_dispatcher.h @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_DISPATCHER_H +#define MT_SPM_DISPATCHER_H + +int mt_spm_dispatcher_init(void); +#endif /* MT_SPM_DISPATCHER_H */ diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm_hwreq.c b/plat/mediatek/drivers/spm/mt8196/mt_spm_hwreq.c new file mode 100644 index 000000000..1d6c9d8bb --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/mt_spm_hwreq.c @@ -0,0 +1,707 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +/* Ddren, apsrc and emi resource have become hw resource_req. + * So we don't need to use HW CG for request resource. + */ +#define SPM_HWCG_DDREN_PWR_MB 0 +#define SPM_HWCG_DDREN_PWR_MSB_MB 0 +#define SPM_HWCG_DDREN_MODULE_BUSY_MB 0 + +/* VRF18 */ +#define SPM_HWCG_VRF18_PWR_MB 0 +#define SPM_HWCG_VRF18_PWR_MSB_MB 0 +#define SPM_HWCG_VRF18_MODULE_BUSY_MB 0 + +/* INFRA */ +#define SPM_HWCG_INFRA_PWR_MB SPM_HWCG_VRF18_PWR_MB +#define SPM_HWCG_INFRA_PWR_MSB_MB SPM_HWCG_VRF18_PWR_MSB_MB +#define SPM_HWCG_INFRA_MODULE_BUSY_MB 0 + +/* PMIC */ +#define SPM_HWCG_PMIC_PWR_MB SPM_HWCG_VRF18_PWR_MB +#define SPM_HWCG_PMIC_PWR_MSB_MB SPM_HWCG_VRF18_PWR_MSB_MB +#define SPM_HWCG_PMIC_MODULE_BUSY_MB 0 + +/* F26M */ +#define SPM_HWCG_F26M_PWR_MB SPM_HWCG_PMIC_PWR_MB +#define SPM_HWCG_F26M_PWR_MSB_MB SPM_HWCG_PMIC_PWR_MSB_MB +#define SPM_HWCG_F26M_MODULE_BUSY_MB 0 + +/* VCORE */ +#define SPM_HWCG_VCORE_PWR_MB SPM_HWCG_F26M_PWR_MB +#define SPM_HWCG_VCORE_PWR_MSB_MB SPM_HWCG_F26M_PWR_MSB_MB +#define SPM_HWCG_VCORE_MODULE_BUSY_MB SPM_HWCG_F26M_MODULE_BUSY_MB + +#define INFRA_SW_CG_MB 0 + +struct spm_hwcg_info { + uint32_t pwr; + uint32_t pwr_msb; + uint32_t module_busy; +}; + +#define HWCG_INFO_INIT(_info) ({ \ + _info.pwr = _info.pwr_msb = _info.module_busy = 0; }) + +#define DECLARE_HWCG_REG(_name_, _info) ({ \ + _info.pwr = REG_PWR_STATUS_##_name_##_REQ_MASK; \ + _info.pwr_msb = REG_PWR_STATUS_MSB_##_name_##_REQ_MASK; \ + _info.module_busy = REG_MODULE_BUSY_##_name_##_REQ_MASK; }) + +#define DECLARE_HWCG_DEFAULT(_name_, _info) ({ \ + _info.pwr = SPM_HWCG_##_name_##_PWR_MB; \ + _info.pwr_msb = SPM_HWCG_##_name_##_PWR_MSB_MB; \ + _info.module_busy = SPM_HWCG_##_name_##_MODULE_BUSY_MB; }) + +#define PERI_REQ_EN_INFO_INIT(_info) ({_info.req_en = 0; }) + +#define PERI_REQ_STA_INFO_INIT(_info) ({_info.req_sta = 0; }) + +#define DECLARE_PERI_REQ_EN_REG(_offset, _info) ({ \ + _info.req_en = REG_PERI_REQ_EN(_offset); }) + +#define DECLARE_PERI_REQ_STA_REG(_offset, _info) ({ \ + _info.req_sta = REG_PERI_REQ_STA(_offset); }) + +#define DECLARE_PERI_REQ_DEFAULT(_name_, _info) ({ \ + _info.req_en = PERI_REQ_##_name_##_MB; }) + +#define PERI_REQ_EN_MASK 0x3FFFFF + +static uint32_t spm_hwcg_index2res(uint32_t idx) +{ + uint32_t res; + + if (idx >= HWCG_MAX) + return 0; + + switch (idx) { + case HWCG_DDREN: + res = (MT_SPM_DRAM_S0 | MT_SPM_DRAM_S1 | MT_SPM_EMI); + break; + case HWCG_VRF18: + res = MT_SPM_SYSPLL; + break; + case HWCG_INFRA: + res = MT_SPM_INFRA; + break; + case HWCG_PMIC: + res = MT_SPM_PMIC; + break; + case HWCG_F26M: + res = MT_SPM_26M; + break; + case HWCG_VCORE: + res = MT_SPM_VCORE; + break; + default: + res = 0; + } + return res; +} + +static uint32_t spm_hwcg_ctrl_get(struct spm_hwcg_info *info, + enum spm_hwcg_setting type) +{ + uint32_t reg = 0; + + if (!info) + return 0; + + switch (type) { + case HWCG_PWR: + reg = info->pwr; + break; + case HWCG_PWR_MSB: + reg = info->pwr_msb; + break; + default: + reg = info->module_busy; + break; + } + return reg; +} + +static void __spm_hwcg_ctrl(struct spm_hwcg_info *info, + enum spm_hwcg_setting type, + uint32_t is_set, uint32_t val) +{ + uint32_t reg; + + reg = spm_hwcg_ctrl_get(info, type); + + if (!reg) + return; + + if (is_set) + mmio_setbits_32(reg, val); + else + mmio_clrbits_32(reg, val); +} + +void spm_hwcg_ctrl(uint32_t res, enum spm_hwcg_setting type, + uint32_t is_set, uint32_t val) +{ + struct spm_hwcg_info info; + + if (res & (MT_SPM_DRAM_S0 | MT_SPM_DRAM_S1 | MT_SPM_EMI)) + DECLARE_HWCG_REG(DDREN, info); + else if (res & MT_SPM_SYSPLL) + DECLARE_HWCG_REG(VRF18, info); + else if (res & MT_SPM_INFRA) + DECLARE_HWCG_REG(INFRA, info); + else if (res & MT_SPM_PMIC) + DECLARE_HWCG_REG(PMIC, info); + else if (res & MT_SPM_26M) + DECLARE_HWCG_REG(F26M, info); + else if (res & MT_SPM_VCORE) + DECLARE_HWCG_REG(VCORE, info); + else + HWCG_INFO_INIT(info); + + if (info.pwr) + __spm_hwcg_ctrl(&info, type, is_set, val); +} + +void spm_hwcg_ctrl_by_index(uint32_t idx, enum spm_hwcg_setting type, + uint32_t is_set, uint32_t val) +{ + uint32_t res = spm_hwcg_index2res(idx); + + if (res) + spm_hwcg_ctrl(res, type, is_set, val); +} + +static uint32_t spm_hwcg_mask_get(uint32_t res, enum spm_hwcg_setting type) +{ + struct spm_hwcg_info info; + uint32_t raw_val = 0, reg = 0; + + if (res & (MT_SPM_DRAM_S0 | MT_SPM_DRAM_S1 | MT_SPM_EMI)) + DECLARE_HWCG_REG(DDREN, info); + else if (res & MT_SPM_SYSPLL) + DECLARE_HWCG_REG(VRF18, info); + else if (res & MT_SPM_INFRA) + DECLARE_HWCG_REG(INFRA, info); + else if (res & MT_SPM_PMIC) + DECLARE_HWCG_REG(PMIC, info); + else if (res & MT_SPM_26M) + DECLARE_HWCG_REG(F26M, info); + else if (res & MT_SPM_VCORE) + DECLARE_HWCG_REG(VCORE, info); + else + HWCG_INFO_INIT(info); + + if (!info.pwr) + return 0; + + reg = spm_hwcg_ctrl_get(&info, type); + + if (!reg) + return 0; + + raw_val = ~mmio_read_32(reg); + + return raw_val; +} + +static uint32_t spm_hwcg_get_default(uint32_t res, enum spm_hwcg_setting type) +{ + struct spm_hwcg_info info; + + if (res & (MT_SPM_DRAM_S0 | MT_SPM_DRAM_S1 | MT_SPM_EMI)) + DECLARE_HWCG_DEFAULT(DDREN, info); + else if (res & MT_SPM_SYSPLL) + DECLARE_HWCG_DEFAULT(VRF18, info); + else if (res & MT_SPM_INFRA) + DECLARE_HWCG_DEFAULT(INFRA, info); + else if (res & MT_SPM_PMIC) + DECLARE_HWCG_DEFAULT(PMIC, info); + else if (res & MT_SPM_26M) + DECLARE_HWCG_DEFAULT(F26M, info); + else if (res & MT_SPM_VCORE) + DECLARE_HWCG_DEFAULT(VCORE, info); + else + HWCG_INFO_INIT(info); + + if (!info.pwr) + return 0; + + return spm_hwcg_ctrl_get(&info, type); +} + +uint32_t spm_hwcg_get_status(uint32_t idx, enum spm_hwcg_setting type) +{ + uint32_t val = 0; + + switch (type) { + case HWCG_PWR: + val = mmio_read_32(PWR_STATUS); + break; + case HWCG_PWR_MSB: + val = mmio_read_32(PWR_STATUS_MSB); + break; + default: + break; + } + return val; +} + +int spm_hwcg_get_setting(uint32_t res, enum spm_hwcg_sta_type sta_type, + enum spm_hwcg_setting type, + struct spm_hwcg_sta *sta) +{ + int ret = 0; + + if (!sta) + return -1; + + switch (sta_type) { + case HWCG_STA_DEFAULT_MASK: + sta->sta = spm_hwcg_get_default(res, type); + break; + case HWCG_STA_MASK: + sta->sta = spm_hwcg_mask_get(res, type); + break; + default: + ret = -1; + MT_SPM_HW_CG_STA_INIT(sta); + break; + } + return ret; +} + +int spm_hwcg_get_setting_by_index(uint32_t idx, + enum spm_hwcg_sta_type sta_type, + enum spm_hwcg_setting type, + struct spm_hwcg_sta *sta) +{ + uint32_t res = spm_hwcg_index2res(idx); + + return spm_hwcg_get_setting(res, sta_type, type, sta); +} + +int spm_hwcg_name(uint32_t idex, char *name, size_t sz) +{ + int ret = 0; + + if (!name) + return -1; + + switch (idex) { + case HWCG_DDREN: + ret = snprintf(name, sz - 1, "dram"); + break; + case HWCG_VRF18: + ret = snprintf(name, sz - 1, "vrf18"); + break; + case HWCG_INFRA: + ret = snprintf(name, sz - 1, "infra"); + break; + case HWCG_PMIC: + ret = snprintf(name, sz - 1, "pmic"); + break; + case HWCG_F26M: + ret = snprintf(name, sz - 1, "26m"); + break; + case HWCG_VCORE: + ret = snprintf(name, sz - 1, "vcore"); + break; + default: + ret = -1; + break; + } + + if (ret < 0) + ret = -1; + + name[sz-1] = '\0'; + + return ret; +} + +static void spm_infra_swcg_init(void) +{ + mmio_write_32(INFRA_SW_CG_MASK, ~INFRA_SW_CG_MB); +} + +static void spm_hwcg_init(void) +{ + /* HW CG for ddren, apsrc, emi resource req */ + mmio_write_32(REG_PWR_STATUS_DDREN_REQ_MASK, + ~SPM_HWCG_DDREN_PWR_MB); + mmio_write_32(REG_PWR_STATUS_MSB_DDREN_REQ_MASK, + ~SPM_HWCG_DDREN_PWR_MSB_MB); + mmio_write_32(REG_MODULE_BUSY_DDREN_REQ_MASK, + ~SPM_HWCG_DDREN_MODULE_BUSY_MB); + + /* HW CG for vrf18 resource req */ + mmio_write_32(REG_PWR_STATUS_VRF18_REQ_MASK, + ~SPM_HWCG_VRF18_PWR_MB); + mmio_write_32(REG_PWR_STATUS_MSB_VRF18_REQ_MASK, + ~SPM_HWCG_VRF18_PWR_MSB_MB); + mmio_write_32(REG_MODULE_BUSY_VRF18_REQ_MASK, + ~SPM_HWCG_VRF18_MODULE_BUSY_MB); + + /* HW CG for infra resource req */ + mmio_write_32(REG_PWR_STATUS_INFRA_REQ_MASK, + ~SPM_HWCG_INFRA_PWR_MB); + mmio_write_32(REG_PWR_STATUS_MSB_INFRA_REQ_MASK, + ~SPM_HWCG_INFRA_PWR_MSB_MB); + mmio_write_32(REG_MODULE_BUSY_INFRA_REQ_MASK, + ~SPM_HWCG_INFRA_MODULE_BUSY_MB); + + /* HW CG for pmic resource req */ + mmio_write_32(REG_PWR_STATUS_PMIC_REQ_MASK, + ~SPM_HWCG_PMIC_PWR_MB); + mmio_write_32(REG_PWR_STATUS_MSB_PMIC_REQ_MASK, + ~SPM_HWCG_PMIC_PWR_MSB_MB); + mmio_write_32(REG_MODULE_BUSY_PMIC_REQ_MASK, + ~SPM_HWCG_PMIC_MODULE_BUSY_MB); + + /* HW CG for f26m resource req */ + mmio_write_32(REG_PWR_STATUS_F26M_REQ_MASK, + ~SPM_HWCG_F26M_PWR_MB); + mmio_write_32(REG_PWR_STATUS_MSB_F26M_REQ_MASK, + ~SPM_HWCG_F26M_PWR_MSB_MB); + mmio_write_32(REG_MODULE_BUSY_F26M_REQ_MASK, + ~SPM_HWCG_F26M_MODULE_BUSY_MB); + + /* HW CG for vcore resource req */ + mmio_write_32(REG_PWR_STATUS_VCORE_REQ_MASK, + ~SPM_HWCG_VCORE_PWR_MB); + mmio_write_32(REG_PWR_STATUS_MSB_VCORE_REQ_MASK, + ~SPM_HWCG_VCORE_PWR_MSB_MB); + mmio_write_32(REG_MODULE_BUSY_VCORE_REQ_MASK, + ~SPM_HWCG_VCORE_MODULE_BUSY_MB); +} + +#define PERI_CG(ofs) (PERICFG_AO_BASE + 0x10 + (0x4 * (ofs))) +#define PERI_REQ_DEFAULT_MB (BIT(PERI_REQ_EN_FLASHIF) | \ + BIT(PERI_REQ_EN_AP_DMA) | \ + BIT(PERI_REQ_EN_UART1) | \ + BIT(PERI_REQ_EN_UART2) | \ + BIT(PERI_REQ_EN_UART4) | \ + BIT(PERI_REQ_EN_UART5) | \ + BIT(PERI_REQ_EN_PWM) | \ + BIT(PERI_REQ_EN_SPI0) | \ + BIT(PERI_REQ_EN_SPI0_INCR16) | \ + BIT(PERI_REQ_EN_SPI1) | \ + BIT(PERI_REQ_EN_SPI2) | \ + BIT(PERI_REQ_EN_SPI3) | \ + BIT(PERI_REQ_EN_SPI4) | \ + BIT(PERI_REQ_EN_SPI5) | \ + BIT(PERI_REQ_EN_SPI6) | \ + BIT(PERI_REQ_EN_SPI7) | \ + BIT(PERI_REQ_EN_IMP_IIC)) + +/* For MSDC reqesut WA: PERI_REQ_EN_RSV_FOR_MSDC */ +#define PERI_REQ_APSRC_MB (PERI_REQ_DEFAULT_MB | \ + BIT(PERI_REQ_EN_RSV_FOR_MSDC)) + +#define PERI_REQ_DDREN_MB (PERI_REQ_DEFAULT_MB | \ + BIT(PERI_REQ_EN_USB) | \ + BIT(PERI_REQ_EN_UFS0) | \ + BIT(PERI_REQ_EN_PEXTP1) | \ + BIT(PERI_REQ_EN_PEXTP0) | \ + BIT(PERI_REQ_EN_PERI_BUS_TRAFFIC)) +#define PERI_REQ_EMI_MB (PERI_REQ_DEFAULT_MB) +#define PERI_REQ_INFRA_MB (PERI_REQ_DEFAULT_MB) +#define PERI_REQ_SYSPLL_MB (PERI_REQ_DEFAULT_MB) +#define PERI_REQ_F26M_MB (PERI_REQ_DEFAULT_MB) + +uint32_t spm_peri_req_get_status(uint32_t idx, enum spm_peri_req_status type) +{ + uint32_t val = 0, reg = 0; + struct spm_peri_req_info info; + + switch (type) { + case PERI_RES_REQ_EN: + + switch (idx) { + case PERI_REQ_DDREN: + DECLARE_PERI_REQ_STA_REG(PERI_REQ_DDREN, info); + + break; + case PERI_REQ_EMI: + DECLARE_PERI_REQ_STA_REG(PERI_REQ_EMI, info); + + break; + case PERI_REQ_APSRC: + DECLARE_PERI_REQ_STA_REG(PERI_REQ_APSRC, info); + + break; + case PERI_REQ_SYSPLL: + DECLARE_PERI_REQ_STA_REG(PERI_REQ_SYSPLL, info); + + break; + case PERI_REQ_INFRA: + DECLARE_PERI_REQ_STA_REG(PERI_REQ_INFRA, info); + + break; + case PERI_REQ_F26M: + DECLARE_PERI_REQ_STA_REG(PERI_REQ_F26M, info); + + break; + default: + PERI_REQ_STA_INFO_INIT(info); + break; + } + + if (!info.req_sta) + return 0; + + reg = info.req_sta; + val = (mmio_read_32(reg) & PERI_REQ_EN_MASK); + + break; + default: + break; + } + return val; +} + +int spm_peri_req_name(uint32_t idex, char *name, size_t sz) +{ + int ret = 0; + + if (!name) + return -1; + + switch (idex) { + case PERI_REQ_DDREN: + ret = snprintf(name, sz - 1, "ddren"); + break; + case PERI_REQ_EMI: + ret = snprintf(name, sz - 1, "emi"); + break; + case PERI_REQ_APSRC: + ret = snprintf(name, sz - 1, "apsrc"); + break; + case PERI_REQ_SYSPLL: + ret = snprintf(name, sz - 1, "syspll"); + break; + case PERI_REQ_INFRA: + ret = snprintf(name, sz - 1, "infra"); + break; + case PERI_REQ_F26M: + ret = snprintf(name, sz - 1, "26m_pmic_vcore"); + break; + default: + ret = -1; + break; + } + + if (ret < 0) + ret = -1; + + name[sz-1] = '\0'; + + return ret; +} + +uint32_t spm_peri_req_get_status_raw(enum spm_peri_req_status_raw type, + uint32_t idx, + char *name, size_t sz) +{ + return 0; +} + +static uint32_t spm_peri_req_get_default(uint32_t res) +{ + struct spm_peri_req_info info; + + if (res & MT_SPM_DRAM_S1) + DECLARE_PERI_REQ_DEFAULT(DDREN, info); + else if (res & MT_SPM_EMI) + DECLARE_PERI_REQ_DEFAULT(EMI, info); + else if (res & MT_SPM_DRAM_S0) + DECLARE_PERI_REQ_DEFAULT(APSRC, info); + else if (res & MT_SPM_SYSPLL) + DECLARE_PERI_REQ_DEFAULT(SYSPLL, info); + else if (res & MT_SPM_INFRA) + DECLARE_PERI_REQ_DEFAULT(INFRA, info); + else if (res & (MT_SPM_PMIC | MT_SPM_26M | MT_SPM_VCORE)) + DECLARE_PERI_REQ_DEFAULT(F26M, info); + else + PERI_REQ_EN_INFO_INIT(info); + + return info.req_en; +} + +static uint32_t spm_peri_req_mask_get(uint32_t res) +{ + struct spm_peri_req_info info; + uint32_t raw_val = 0, reg = 0; + + if (res & MT_SPM_DRAM_S1) + DECLARE_PERI_REQ_EN_REG(PERI_REQ_DDREN, info); + else if (res & MT_SPM_EMI) + DECLARE_PERI_REQ_EN_REG(PERI_REQ_EMI, info); + else if (res & MT_SPM_DRAM_S0) + DECLARE_PERI_REQ_EN_REG(PERI_REQ_APSRC, info); + else if (res & MT_SPM_SYSPLL) + DECLARE_PERI_REQ_EN_REG(PERI_REQ_SYSPLL, info); + else if (res & MT_SPM_INFRA) + DECLARE_PERI_REQ_EN_REG(PERI_REQ_INFRA, info); + else if (res & (MT_SPM_PMIC | MT_SPM_26M | MT_SPM_VCORE)) + DECLARE_PERI_REQ_EN_REG(PERI_REQ_F26M, info); + else + PERI_REQ_EN_INFO_INIT(info); + + if (!info.req_en) + return 0; + + reg = info.req_en; + + raw_val = (mmio_read_32(reg) & PERI_REQ_EN_MASK); + + return raw_val; +} + +int spm_peri_req_get_setting(uint32_t res, + enum spm_peri_req_sta_type sta_type, + struct spm_peri_req_sta *sta) +{ + int ret = 0; + + if (!sta) + return -1; + + switch (sta_type) { + case PERI_REQ_STA_DEFAULT_MASK: + sta->sta = spm_peri_req_get_default(res); + break; + case PERI_REQ_STA_MASK: + sta->sta = spm_peri_req_mask_get(res); + break; + default: + ret = -1; + MT_SPM_HW_CG_STA_INIT(sta); + break; + } + return ret; +} + +static uint32_t spm_peri_req_index2res(uint32_t idx) +{ + uint32_t res; + + if (idx >= PERI_REQ_MAX) + return 0; + + switch (idx) { + case PERI_REQ_DDREN: + res = MT_SPM_DRAM_S1; + break; + case PERI_REQ_EMI: + res = MT_SPM_EMI; + break; + case PERI_REQ_APSRC: + res = MT_SPM_DRAM_S0; + break; + case PERI_REQ_SYSPLL: + res = MT_SPM_SYSPLL; + break; + case PERI_REQ_INFRA: + res = MT_SPM_INFRA; + break; + case PERI_REQ_F26M: + res = (MT_SPM_PMIC | MT_SPM_26M | MT_SPM_VCORE); + break; + default: + res = 0; + } + return res; + +} + +int spm_peri_req_get_setting_by_index(uint32_t idx, + enum spm_peri_req_sta_type sta_type, + struct spm_peri_req_sta *sta) +{ + uint32_t res = spm_peri_req_index2res(idx); + + return spm_peri_req_get_setting(res, sta_type, sta); +} + +static void __spm_peri_req_ctrl(struct spm_peri_req_info *info, + uint32_t is_set, uint32_t val) +{ + uint32_t raw_val, reg; + + reg = info->req_en; + + if (!reg) + return; + + raw_val = (mmio_read_32(reg) & PERI_REQ_EN_MASK); + + if (is_set) + raw_val |= val; + else + raw_val &= ~val; + + mmio_write_32(reg, raw_val); +} + +void spm_peri_req_ctrl(uint32_t res, + uint32_t is_set, uint32_t val) +{ + struct spm_peri_req_info info; + + if (res & MT_SPM_DRAM_S1) + DECLARE_PERI_REQ_EN_REG(PERI_REQ_DDREN, info); + else if (res & MT_SPM_EMI) + DECLARE_PERI_REQ_EN_REG(PERI_REQ_EMI, info); + else if (res & MT_SPM_DRAM_S0) + DECLARE_PERI_REQ_EN_REG(PERI_REQ_APSRC, info); + else if (res & MT_SPM_SYSPLL) + DECLARE_PERI_REQ_EN_REG(PERI_REQ_SYSPLL, info); + else if (res & MT_SPM_INFRA) + DECLARE_PERI_REQ_EN_REG(PERI_REQ_INFRA, info); + else if (res & (MT_SPM_PMIC | MT_SPM_26M | MT_SPM_VCORE)) + DECLARE_PERI_REQ_EN_REG(PERI_REQ_F26M, info); + else + PERI_REQ_EN_INFO_INIT(info); + + if (info.req_en) + __spm_peri_req_ctrl(&info, is_set, val); +} + +void spm_peri_req_ctrl_by_index(uint32_t idx, + uint32_t is_set, uint32_t val) +{ + uint32_t res = spm_peri_req_index2res(idx); + + if (res) + spm_peri_req_ctrl(res, is_set, val); +} + +static void spm_peri_req_init(void) +{ + mmio_write_32(REG_PERI_REQ_EN(PERI_REQ_DDREN), PERI_REQ_DDREN_MB); + mmio_write_32(REG_PERI_REQ_EN(PERI_REQ_EMI), PERI_REQ_EMI_MB); + mmio_write_32(REG_PERI_REQ_EN(PERI_REQ_APSRC), PERI_REQ_APSRC_MB); + mmio_write_32(REG_PERI_REQ_EN(PERI_REQ_INFRA), PERI_REQ_INFRA_MB); + mmio_write_32(REG_PERI_REQ_EN(PERI_REQ_SYSPLL), PERI_REQ_SYSPLL_MB); + mmio_write_32(REG_PERI_REQ_EN(PERI_REQ_F26M), PERI_REQ_F26M_MB); +} + +void spm_hwreq_init(void) +{ + spm_infra_swcg_init(); + spm_hwcg_init(); + spm_peri_req_init(); +} diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm_hwreq.h b/plat/mediatek/drivers/spm/mt8196/mt_spm_hwreq.h new file mode 100644 index 000000000..e40372634 --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/mt_spm_hwreq.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_HWREQ_H +#define MT_SPM_HWREQ_H + +#include + +/* Resource requirement which HW CG support */ +enum { + HWCG_DDREN = 0, + HWCG_VRF18, + HWCG_INFRA, + HWCG_PMIC, + HWCG_F26M, + HWCG_VCORE, + HWCG_MAX +}; + +/* Signal that monitor by HW CG */ +enum spm_hwcg_setting { + HWCG_PWR, + HWCG_PWR_MSB, + HWCG_MODULE_BUSY, + HWCG_SETTING_MAX +}; + +enum spm_pwr_status { + HWCG_PWR_MD1 = 0, + HWCG_PWR_CONN, + HWCG_PWR_APIFR_IO, + HWCG_PWR_APIFR_MEM, + HWCG_PWR_PERI, + HWCG_PWR_PERI_ETHER, + HWCG_PWR_SSUSB_PD_PHY_P0, + HWCG_PWR_SSUSB_P0, + HWCG_PWR_SSUSB_P1, + HWCG_PWR_SSUSB_P23, + HWCG_PWR_SSUSB_PHY_P2, + HWCG_PWR_UFS0, + HWCG_PWR_UFS0_PHY, + HWCG_PWR_PEXTP_MAC0, + HWCG_PWR_PEXTP_MAC1, + HWCG_PWR_PEXTP_MAC2, + HWCG_PWR_PEXTP_PHY0, + HWCG_PWR_PEXTP_PHY1, + HWCG_PWR_PEXTP_PHY3, + HWCG_PWR_AUDIO, + HWCG_PWR_ADSP_CORE1, + HWCG_PWR_ADSP_TOP, + HWCG_PWR_ADSP_INFRA, + HWCG_PWR_ADSP_AO, + HWCG_PWR_MM_PROC, + HWCG_PWR_SCP, + HWCG_PWR_SCP2, + HWCG_PWR_DPYD0, + HWCG_PWR_DPYD1, + HWCG_PWR_DPYD2, + HWCG_PWR_DPYD3, + HWCG_PWR_DPYA0 +}; + +CASSERT(HWCG_PWR_SSUSB_P1 == 8, spm_pwr_status_err); +CASSERT(HWCG_PWR_PEXTP_PHY0 == 16, spm_pwr_status_err); +CASSERT(HWCG_PWR_MM_PROC == 24, spm_pwr_status_err); + +enum spm_hwcg_module_busy { + HWCG_MODULE_ADSP = 0, + HWCG_MODULE_MMPLL, + HWCG_MODULE_TVDPLL, + HWCG_MODULE_MSDCPLL, + HWCG_MODULE_UNIVPLL +}; + +enum spm_hwcg_sta_type { + HWCG_STA_DEFAULT_MASK, + HWCG_STA_MASK +}; + +/* Signal that monitor by HW CG */ +enum spm_peri_req_setting { + PERI_REQ_EN = 0, + PERI_REQ_SETTING_MAX +}; + +/* Resource requirement which PERI REQ support */ +enum spm_peri_req { + PERI_REQ_F26M = 0, + PERI_REQ_INFRA, + PERI_REQ_SYSPLL, + PERI_REQ_APSRC, + PERI_REQ_EMI, + PERI_REQ_DDREN, + PERI_REQ_MAX +}; + +enum spm_peri_req_sta_type { + PERI_REQ_STA_DEFAULT_MASK, + PERI_REQ_STA_MASK, + PERI_REQ_STA_MAX +}; + +enum spm_peri_req_status { + PERI_RES_REQ_EN, + PERI_REQ_STATUS_MAX +}; + +enum spm_peri_req_status_raw { + PERI_REQ_STATUS_RAW_NUM, + PERI_REQ_STATUS_RAW_NAME, + PERI_REQ_STATUS_RAW_STA, + PERI_REQ_STATUS_RAW_MAX +}; + +enum spm_peri_req_en { + PERI_REQ_EN_FLASHIF = 0, + PERI_REQ_EN_AP_DMA, + PERI_REQ_EN_UART0, + PERI_REQ_EN_UART1, + PERI_REQ_EN_UART2, + PERI_REQ_EN_UART3, + PERI_REQ_EN_UART4, + PERI_REQ_EN_UART5, + PERI_REQ_EN_PWM, + PERI_REQ_EN_SPI0, + PERI_REQ_EN_SPI0_INCR16, + PERI_REQ_EN_SPI1, + PERI_REQ_EN_SPI2, + PERI_REQ_EN_SPI3, + PERI_REQ_EN_SPI4, + PERI_REQ_EN_SPI5, + PERI_REQ_EN_SPI6, + PERI_REQ_EN_SPI7, + PERI_REQ_EN_IMP_IIC, + PERI_REQ_EN_MSDC1, + PERI_REQ_EN_MSDC2, + PERI_REQ_EN_USB, + PERI_REQ_EN_UFS0, + PERI_REQ_EN_PEXTP1, + PERI_REQ_EN_PEXTP0, + PERI_REQ_EN_RSV_DUMMY0, + PERI_REQ_EN_PERI_BUS_TRAFFIC, + PERI_REQ_EN_RSV_DUMMY1, + PERI_REQ_EN_RSV_FOR_MSDC, + PERI_REQ_EN_MAX +}; + +CASSERT(PERI_REQ_EN_PWM == 8, spm_peri_req_en_err); +CASSERT(PERI_REQ_EN_SPI6 == 16, spm_peri_req_en_err); +CASSERT(PERI_REQ_EN_PEXTP0 == 24, spm_peri_req_en_err); + +struct spm_peri_req_sta { + uint32_t sta; +}; + +struct spm_peri_req_info { + uint32_t req_en; + uint32_t req_sta; +}; + +struct spm_hwcg_sta { + uint32_t sta; +}; + +#define MT_SPM_HW_CG_STA_INIT(_x) ({ if (_x) _x->sta = 0; }) + +#define INFRA_AO_OFFSET(offset) (INFRACFG_AO_BASE + offset) +#define INFRA_SW_CG_MASK INFRA_AO_OFFSET(0x060) + +#define REG_PERI_REQ_EN(N) (PERICFG_AO_BASE + 0x070 + 0x4 * (N)) +#define REG_PERI_REQ_STA(N) (PERICFG_AO_BASE + 0x0A0 + 0x4 * (N)) + +void spm_hwreq_init(void); + +/* Res: + * Please refer the mt_spm_resource_req.h. + * Section of SPM resource request internal bit_mask. + */ +void spm_hwcg_ctrl(uint32_t res, enum spm_hwcg_setting type, + uint32_t is_set, uint32_t val); + +/* Idx: + * index of HWCG setting. + */ +void spm_hwcg_ctrl_by_index(uint32_t idx, enum spm_hwcg_setting type, + uint32_t is_set, uint32_t val); + +/* Res: + * Please refer the mt_spm_resource_req.h. + * Section of SPM resource request internal bit_mask. + */ +int spm_hwcg_get_setting(uint32_t res, enum spm_hwcg_sta_type sta_type, + enum spm_hwcg_setting type, + struct spm_hwcg_sta *sta); + +/* Idx: + * index of HWCG setting. + */ +int spm_hwcg_get_setting_by_index(uint32_t idx, + enum spm_hwcg_sta_type sta_type, + enum spm_hwcg_setting type, + struct spm_hwcg_sta *sta); + +uint32_t spm_hwcg_get_status(uint32_t idx, enum spm_hwcg_setting type); + +int spm_hwcg_name(uint32_t idex, char *name, size_t sz); + +static inline uint32_t spm_hwcg_num(void) +{ + return HWCG_MAX; +} + +static inline uint32_t spm_hwcg_setting_num(void) +{ + return HWCG_SETTING_MAX; +} + +uint32_t spm_peri_req_get_status(uint32_t idx, enum spm_peri_req_status type); +uint32_t spm_peri_req_get_status_raw(enum spm_peri_req_status_raw type, + uint32_t idx, + char *name, size_t sz); + +static inline uint32_t spm_peri_req_num(void) +{ + return PERI_REQ_MAX; +} + +static inline uint32_t spm_peri_req_setting_num(void) +{ + return PERI_REQ_SETTING_MAX; +} + +int spm_peri_req_get_setting_by_index(uint32_t idx, + enum spm_peri_req_sta_type sta_type, + struct spm_peri_req_sta *sta); + +void spm_peri_req_ctrl_by_index(uint32_t idx, + uint32_t is_set, uint32_t val); + +int spm_peri_req_name(uint32_t idex, char *name, size_t sz); + +#endif /* MT_SPM_HWREQ_H */ diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm_stats.c b/plat/mediatek/drivers/spm/mt8196/mt_spm_stats.c new file mode 100644 index 000000000..adf784d6e --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/mt_spm_stats.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#define READ_AND_MASK_16BIT(addr) (mmio_read_32(addr) & 0xFFFF) + +void mt_spm_update_lp_stat(struct spm_lp_stat *stat) +{ + if (!stat) + return; + + stat->record[SPM_STAT_MCUSYS].count += 1; + stat->record[SPM_STAT_MCUSYS].duration += + mmio_read_32(SPM_BK_PCM_TIMER); + stat->record[SPM_STAT_D1_2].count += + READ_AND_MASK_16BIT(SPM_APSRC_EVENT_COUNT_STA); + stat->record[SPM_STAT_D2].count += + READ_AND_MASK_16BIT(SPM_EMI_EVENT_COUNT_STA); + stat->record[SPM_STAT_D3].count += + READ_AND_MASK_16BIT(SPM_VRF18_EVENT_COUNT_STA); + stat->record[SPM_STAT_D4].count += + READ_AND_MASK_16BIT(SPM_INFRA_EVENT_COUNT_STA); + stat->record[SPM_STAT_D6X].count += + READ_AND_MASK_16BIT(SPM_PMIC_EVENT_COUNT_STA); + stat->record[SPM_STAT_F26M].count += + READ_AND_MASK_16BIT(SPM_SRCCLKENA_EVENT_COUNT_STA); + stat->record[SPM_STAT_F26M].duration += + READ_AND_MASK_16BIT(SPM_BK_VTCXO_DUR); + stat->record[SPM_STAT_VCORE].count += + READ_AND_MASK_16BIT(SPM_VCORE_EVENT_COUNT_STA); + stat->record[SPM_STAT_VCORE].duration += + mmio_read_32(SPM_SW_RSV_4); +} + +uint64_t mt_spm_get_lp_stat(struct spm_lp_stat *stat, + uint32_t index, uint32_t type) +{ + + uint64_t ret; + + if (!stat || index >= NUM_SPM_STAT) + return 0; + + switch (type) { + case SPM_SLP_COUNT: + ret = stat->record[index].count; + break; + case SPM_SLP_DURATION: + ret = stat->record[index].duration; + break; + default: + ret = 0; + break; + } + + return ret; +} diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm_stats.h b/plat/mediatek/drivers/spm/mt8196/mt_spm_stats.h new file mode 100644 index 000000000..6ec715693 --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/mt_spm_stats.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_STATS_H +#define MT_SPM_STATS_H + +#include + +enum spm_stat_type { + SPM_SLP_COUNT, + SPM_SLP_DURATION, +}; + +enum spm_stat_state { + SPM_STAT_MCUSYS, + SPM_STAT_F26M, + SPM_STAT_VCORE, + SPM_STAT_D1_2, + SPM_STAT_D2, + SPM_STAT_D3, + SPM_STAT_D4, + SPM_STAT_D6X, + NUM_SPM_STAT, +}; + +struct spm_lp_stat_record { + uint64_t count; + uint64_t duration; +}; + +struct spm_lp_stat { + struct spm_lp_stat_record record[NUM_SPM_STAT]; +}; + +void mt_spm_update_lp_stat(struct spm_lp_stat *stat); + +uint64_t mt_spm_get_lp_stat(struct spm_lp_stat *stat, + uint32_t index, uint32_t type); + +#endif /* MT_SPM_STATS_H */ diff --git a/plat/mediatek/drivers/spm/mt8196/pcm_def.h b/plat/mediatek/drivers/spm/mt8196/pcm_def.h new file mode 100644 index 000000000..1e29bc630 --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/pcm_def.h @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PCM_DEF_H +#define PCM_DEF_H + +#define CTRL0_SC_26M_CK_OFF BIT(0) +#define CTRL0_SC_VLP_BUS_CK_OFF BIT(1) +#define CTRL0_SC_PMIF_CK_OFF BIT(2) +#define CTRL0_SC_AXI_CK_OFF BIT(3) +#define CTRL0_SC_AXI_MEM_CK_OFF BIT(4) +#define CTRL0_SC_MD26M_CK_OFF BIT(5) +#define CTRL0_SC_MD32K_CK_OFF BIT(6) +#define CTRL0_SC_VLP_26M_CLK_SEL BIT(7) +#define CTRL0_SC_26M_CK_SEL BIT(8) +#define CTRL0_SC_TOP_26M_CLK_SEL BIT(9) +#define CTRL0_SC_SYS_TIMER_CLK_32K_SEL BIT(10) +#define CTRL0_SC_CIRQ_CLK_32K_SEL BIT(11) +#define CTRL0_SC_AXI_DCM_DIS BIT(12) +#define CTRL0_SC_CKSQ0_OFF BIT(13) +#define CTRL0_SC_CKSQ1_OFF BIT(14) +#define CTRL0_VCORE_PWR_ISO BIT(15) +#define CTRL0_VCORE_PWR_ISO_PRE BIT(16) +#define CTRL0_VCORE_PWR_RST_B BIT(17) +#define CTRL0_VCORE_RESTORE_ENABLE BIT(18) +#define CTRL0_SC_TOP_RESTORE_26M_CLK_SEL BIT(19) +#define CTRL0_AOC_VCORE_SRAM_ISO_DIN BIT(20) +#define CTRL0_AOC_VCORE_SRAM_LATCH_ENB BIT(21) +#define CTRL0_AOC_VCORE_ANA_ISO BIT(22) +#define CTRL0_AOC_VCORE_ANA_ISO_PRE BIT(23) +#define CTRL0_AOC_VLPTOP_SRAM_ISO_DIN BIT(24) +#define CTRL0_AOC_VLPTOP_SRAM_LATCH_ENB BIT(25) +#define CTRL0_AOC_VCORE_IO_ISO BIT(26) +#define CTRL0_AOC_VCORE_IO_LATCH_ENB BIT(27) +#define CTRL0_RTFF_VCORE_SAVE BIT(28) +#define CTRL0_RTFF_VCORE_NRESTORE BIT(29) +#define CTRL0_RTFF_VCORE_CLK_DIS BIT(30) + +#define CTRL1_PWRAP_SLEEP_REQ BIT(0) +#define CTRL1_IM_SLP_EN BIT(1) +#define CTRL1_SPM_LEAVE_VCORE_OFF_REQ BIT(2) +#define CTRL1_SPM_CK_SEL0 BIT(4) +#define CTRL1_SPM_CK_SEL1 BIT(5) +#define CTRL1_TIMER_SET BIT(6) +#define CTRL1_TIMER_CLR BIT(7) +#define CTRL1_SPM_LEAVE_DEEPIDLE_REQ BIT(8) +#define CTRL1_SPM_LEAVE_SUSPEND_REQ BIT(9) +#define CTRL1_CSYSPWRUPACK BIT(10) +#define CTRL1_SRCCLKENO0 BIT(11) +#define CTRL1_SRCCLKENO1 BIT(12) +#define CTRL1_SRCCLKENO2 BIT(13) +#define CTRL1_SPM_APSRC_INTERNAL_ACK BIT(14) +#define CTRL1_SPM_EMI_INTERNAL_ACK BIT(15) +#define CTRL1_SPM_DDREN_INTERNAL_ACK BIT(16) +#define CTRL1_SPM_INFRA_INTERNAL_ACK BIT(17) +#define CTRL1_SPM_VRF18_INTERNAL_ACK BIT(18) +#define CTRL1_SPM_VCORE_INTERNAL_ACK BIT(19) +#define CTRL1_SPM_VCORE_RESTORE_ACK BIT(20) +#define CTRL1_SPM_PMIC_INTERNAL_ACK BIT(21) +#define CTRL1_PMIC_IRQ_REQ_EN BIT(22) +#define CTRL1_WDT_KICK_P BIT(23) +#define CTRL1_FORCE_DDREN_WAKE BIT(24) +#define CTRL1_FORCE_F26M_WAKE BIT(25) +#define CTRL1_FORCE_APSRC_WAKE BIT(26) +#define CTRL1_FORCE_INFRA_WAKE BIT(27) +#define CTRL1_FORCE_VRF18_WAKE BIT(28) +#define CTRL1_FORCE_VCORE_WAKE BIT(29) +#define CTRL1_FORCE_EMI_WAKE BIT(30) +#define CTRL1_FORCE_PMIC_WAKE BIT(31) + + +#define CTRL2_MD32PCM_IRQ_TRIG_BIT BIT(31) + +#define STA0_SRCCLKENI0 BIT(0) +#define STA0_SRCCLKENI1 BIT(1) +#define STA0_MD_SRCCLKENA BIT(2) +#define STA0_MD_SRCCLKENA1 BIT(3) +#define STA0_MD_DDREN_REQ BIT(4) +#define STA0_CONN_DDREN_REQ BIT(5) +#define STA0_SSPM_SRCCLKENA BIT(6) +#define STA0_SSPM_APSRC_REQ BIT(7) +#define STA0_MD_STATE BIT(8) +#define STA0_RC2SPM_SRCCLKENO_0_ACK BIT(9) +#define STA0_MM_STATE BIT(10) +#define STA0_SSPM_STATE BIT(11) +#define STA0_CPUEB_STATE BIT(12) +#define STA0_CONN_STATE BIT(13) +#define STA0_CONN_VCORE_REQ BIT(14) +#define STA0_CONN_SRCCLKENA BIT(15) +#define STA0_CONN_SRCCLKENB BIT(16) +#define STA0_CONN_APSRC_REQ BIT(17) +#define STA0_SCP_STATE BIT(18) +#define STA0_CSYSPWRUPREQ BIT(19) +#define STA0_PWRAP_SLEEP_ACK BIT(20) +#define STA0_DPM_STATE BIT(21) +#define STA0_AUDIO_DSP_STATE BIT(22) +#define STA0_PMIC_IRQ_ACK BIT(23) +#define STA0_RESERVED_BIT_24 BIT(24) +#define STA0_RESERVED_BIT_25 BIT(25) +#define STA0_RESERVED_BIT_26 BIT(26) +#define STA0_DVFS_STATE BIT(27) +#define STA0_RESERVED_BIT_28 BIT(28) +#define STA0_RESERVED_BIT_29 BIT(29) +#define STA0_SC_HW_S1_ACK_ALL BIT(30) +#define STA0_DDREN_STATE BIT(31) + +#define R12_PCM_TIMER_B BIT(0) +#define R12_TWAM_PMSR_DVFSRC_ALCO BIT(1) +#define R12_KP_IRQ_B BIT(2) +#define R12_APWDT_EVENT_B BIT(3) +#define R12_APXGPT_EVENT_B BIT(4) +#define R12_CONN2AP_WAKEUP_B BIT(5) +#define R12_EINT_EVENT_B BIT(6) +#define R12_CONN_WDT_IRQ_B BIT(7) +#define R12_CCIF0_EVENT_B BIT(8) +#define R12_CCIF1_EVENT_B BIT(9) +#define R12_SSPM2SPM_WAKEUP_B BIT(10) +#define R12_SCP2SPM_WAKEUP_B BIT(11) +#define R12_ADSP2SPM_WAKEUP_B BIT(12) +#define R12_PCM_WDT_WAKEUP_B BIT(13) +#define R12_USB0_CDSC_B BIT(14) +#define R12_USB0_POWERDWN_B BIT(15) +#define R12_UART_EVENT_B BIT(16) +#define R12_DEBUGTOP_FLAG_IRQ_B BIT(17) +#define R12_SYS_TIMER_EVENT_B BIT(18) +#define R12_EINT_EVENT_SECURE_B BIT(19) +#define R12_AFE_IRQ_MCU_B BIT(20) +#define R12_THERM_CTRL_EVENT_B BIT(21) +#define R12_SYS_CIRQ_IRQ_B BIT(22) +#define R12_PBUS_EVENT_B BIT(23) +#define R12_CSYSPWREQ_B BIT(24) +#define R12_MD_WDT_B BIT(25) +#define R12_AP2AP_PEER_WAKEUP_B BIT(26) +#define R12_SEJ_B BIT(27) +#define R12_CPU_WAKEUP BIT(28) +#define R12_APUSYS_WAKE_HOST_B BIT(29) +#define R12_PCIE_WAKE_B BIT(30) +#define R12_MSDC_WAKE_B BIT(31) + +#define EVENT_F26M_WAKE BIT(0) +#define EVENT_F26M_SLEEP BIT(1) +#define EVENT_INFRA_WAKE BIT(2) +#define EVENT_INFRA_SLEEP BIT(3) +#define EVENT_EMI_WAKE BIT(4) +#define EVENT_EMI_SLEEP BIT(5) +#define EVENT_APSRC_WAKE BIT(6) +#define EVENT_APSRC_SLEEP BIT(7) +#define EVENT_VRF18_WAKE BIT(8) +#define EVENT_VRF18_SLEEP BIT(9) +#define EVENT_DVFS_WAKE BIT(10) +#define EVENT_DDREN_WAKE BIT(11) +#define EVENT_DDREN_SLEEP BIT(12) +#define EVENT_VCORE_WAKE BIT(13) +#define EVENT_VCORE_SLEEP BIT(14) +#define EVENT_PMIC_WAKE BIT(15) +#define EVENT_PMIC_SLEEP BIT(16) +#define EVENT_CPUEB_STATE BIT(17) +#define EVENT_SSPM_STATE BIT(18) +#define EVENT_DPM_STATE BIT(19) +#define EVENT_SPM_LEAVE_VCORE_OFF_ACK BIT(20) +#define EVENT_SW_SSPM_ADSP_SCP_MAILBOX_WAKE BIT(21) +#define EVENT_SPM_LEAVE_SUSPEND_ACK BIT(22) +#define EVENT_SPM_LEAVE_DEEPIDLE_ACK BIT(23) +#define EVENT_CROSS_REQ_APU_l3 BIT(24) +#define EVENT_DFD_SOC_MTCMOS_REQ_IPIC_WAKE BIT(25) +#define EVENT_AOVBUS_WAKE BIT(26) +#define EVENT_AOVBUS_SLEEP BIT(27) + +enum SPM_WAKE_SRC_LIST { + WAKE_SRC_STA1_PCM_TIMER = BIT(0), + WAKE_SRC_STA1_TWAM_PMSR_DVFSRC = BIT(1), + WAKE_SRC_STA1_KP_IRQ_B = BIT(2), + WAKE_SRC_STA1_APWDT_EVENT_B = BIT(3), + WAKE_SRC_STA1_APXGPT1_EVENT_B = BIT(4), + WAKE_SRC_STA1_CONN2AP_SPM_WAKEUP_B = BIT(5), + WAKE_SRC_STA1_EINT_EVENT_B = BIT(6), + WAKE_SRC_STA1_CONN_WDT_IRQ_B = BIT(7), + WAKE_SRC_STA1_CCIF0_EVENT_B = BIT(8), + WAKE_SRC_STA1_CCIF1_EVENT_B = BIT(9), + WAKE_SRC_STA1_SC_SSPM2SPM_WAKEUP_B = BIT(10), + WAKE_SRC_STA1_SC_SCP2SPM_WAKEUP_B = BIT(11), + WAKE_SRC_STA1_SC_ADSP2SPM_WAKEUP_B = BIT(12), + WAKE_SRC_STA1_PCM_WDT_WAKEUP_B = BIT(13), + WAKE_SRC_STA1_USB_CDSC_B = BIT(14), + WAKE_SRC_STA1_USB_POWERDWN_B = BIT(15), + WAKE_SRC_STA1_AP_UART_B = BIT(16), + WAKE_SRC_STA1_DEBUGTOP_FLAG_IRQ_B = BIT(17), + WAKE_SRC_STA1_SYS_TIMER_EVENT_B = BIT(18), + WAKE_SRC_STA1_EINT_EVENT_SECURE_B = BIT(19), + WAKE_SRC_STA1_AFE_IRQ_MCU_B = BIT(20), + WAKE_SRC_STA1_THERM_CTRL_EVENT_B = BIT(21), + WAKE_SRC_STA1_SYS_CIRQ_IRQ_B = BIT(22), + WAKE_SRC_STA1_PBUS_EVENT_B = BIT(23), + WAKE_SRC_STA1_CSYSPWREQ_B = BIT(24), + WAKE_SRC_STA1_MD1_WDT_B = BIT(25), + WAKE_SRC_STA1_AP2AP_PEER_WAKEUPEVENT_B = BIT(26), + WAKE_SRC_STA1_SEJ_EVENT_B = BIT(27), + WAKE_SRC_STA1_SPM_CPU_WAKEUPEVENT_B = BIT(28), + WAKE_SRC_STA1_APUSYS_WAKE_HOST_B = BIT(29), + WAKE_SRC_STA1_PCIE_B = BIT(30), + WAKE_SRC_STA1_MSDC_B = BIT(31), +}; + +extern const char *wakesrc_str[32]; + +#endif /* PCM_DEF_H */ diff --git a/plat/mediatek/drivers/spm/mt8196/sleep_def.h b/plat/mediatek/drivers/spm/mt8196/sleep_def.h new file mode 100644 index 000000000..1860416e0 --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/sleep_def.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SLEEP_DEF_H +#define SLEEP_DEF_H + +/* --- SPM Flag Define --- */ +#define SPM_FLAG_DISABLE_INFRA_PDN BIT(0) +#define SPM_FLAG_DISABLE_DPM_PDN BIT(1) +#define SPM_FLAG_DISABLE_MCUPM_PDN BIT(2) +#define SPM_FLAG_RESERVED_BIT_3 BIT(3) +#define SPM_FLAG_DISABLE_VLP_PDN BIT(4) +#define SPM_FLAG_DISABLE_VLPCLK_SWITCH BIT(5) +#define SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP BIT(6) +#define SPM_FLAG_RESERVED_BIT_7 BIT(7) +#define SPM_FLAG_DISABLE_VCORE_DVS BIT(8) +#define SPM_FLAG_DISABLE_DDR_DFS BIT(9) +#define SPM_FLAG_DISABLE_EMI_DFS BIT(10) +#define SPM_FLAG_DISABLE_BUS_DFS BIT(11) +#define SPM_FLAG_DISABLE_COMMON_SCENARIO BIT(12) +#define SPM_FLAG_RESERVED_BIT_13 BIT(13) +#define SPM_FLAG_RESERVED_BIT_14 BIT(14) +#define SPM_FLAG_RESERVED_BIT_15 BIT(15) +#define SPM_FLAG_KEEP_CSYSPWRACK_HIGH BIT(16) +#define SPM_FLAG_ENABLE_MT8196_IVI BIT(17) +#define SPM_FLAG_ENABLE_SPM_DBG_WDT_DUMP BIT(18) +#define SPM_FLAG_RUN_COMMON_SCENARIO BIT(19) +#define SPM_FLAG_USE_SRCCLKENO2 BIT(20) +#define SPM_FLAG_ENABLE_AOV BIT(21) +#define SPM_FLAG_ENABLE_MD_MUMTAS BIT(22) +#define SPM_FLAG_ENABLE_COMMON_SODI5 BIT(23) +#define SPM_FLAG_ENABLE_MT8196_E1_WA BIT(24) +#define SPM_FLAG_ENABLE_MT8196_EMI_E1_WA BIT(25) +#define SPM_FLAG_VCORE_STATE BIT(26) +#define SPM_FLAG_VTCXO_STATE BIT(27) +#define SPM_FLAG_INFRA_STATE BIT(28) +#define SPM_FLAG_APSRC_STATE BIT(29) +#define SPM_FLAG_VRF18_STATE BIT(30) +#define SPM_FLAG_DDREN_STATE BIT(31) + +/* --- SPM Flag1 Define --- */ +#define SPM_FLAG1_DISABLE_AXI_BUS_TO_26M BIT(0) +#define SPM_FLAG1_DISABLE_SYSPLL_OFF BIT(1) +#define SPM_FLAG1_DISABLE_PWRAP_CLK_SWITCH BIT(2) +#define SPM_FLAG1_DISABLE_CSOPLU_OFF BIT(3) +#define SPM_FLAG1_FW_SET_CSOPLU_ON BIT(4) +#define SPM_FLAG1_DISABLE_EMI_CLK_TO_CSOPLU BIT(5) +#define SPM_FLAG1_DISABLE_NO_RESUME BIT(6) +#define SPM_FLAG1_RESERVED_BIT_7 BIT(7) +#define SPM_FLAG1_RESERVED_BIT_8 BIT(8) +#define SPM_FLAG1_RESERVED_BIT_9 BIT(9) +#define SPM_FLAG1_DISABLE_SRCLKEN_LOW BIT(10) +#define SPM_FLAG1_DISABLE_SCP_CLK_SWITCH BIT(11) +#define SPM_FLAG1_DISABLE_TOP_26M_CK_OFF BIT(12) +#define SPM_FLAG1_DISABLE_PCM_26M_SWITCH BIT(13) +#define SPM_FLAG1_DISABLE_CKSQ_OFF BIT(14) +#define SPM_FLAG1_DO_DPSW_0P725V BIT(15) +#define SPM_FLAG1_ENABLE_ALCO_TRACE BIT(16) +#define SPM_FLAG1_ENABLE_SUSPEND_AVS BIT(17) +#define SPM_FLAG1_DISABLE_TVCORE_OFF BIT(18) +#define SPM_FLAG1_ENABLE_CSOPLU_OFF BIT(19) +#define SPM_FLAG1_DISABLE_INFRA_SRAM_SLEEP BIT(20) +#define SPM_FLAG1_DISABLE_AXI_MEM_CLK_OFF BIT(21) +#define SPM_FLAG1_RESERVED_BIT_22 BIT(22) +#define SPM_FLAG1_RESERVED_BIT_23 BIT(23) +#define SPM_FLAG1_DISABLE_SCP_VREQ_MASK_CONTROL BIT(24) +#define SPM_FLAG1_RESERVED_BIT_25 BIT(25) +#define SPM_FLAG1_RESERVED_BIT_26 BIT(26) +#define SPM_FLAG1_RESERVED_BIT_27 BIT(27) +#define SPM_FLAG1_RESERVED_BIT_28 BIT(28) +#define SPM_FLAG1_RESERVED_BIT_29 BIT(29) +#define SPM_FLAG1_ENABLE_WAKE_PROF BIT(30) +#define SPM_FLAG1_ENABLE_SLEEP_PROF BIT(31) + +/* --- SPM DEBUG Define --- */ +#define SPM_DBG_DEBUG_IDX_26M_WAKE BIT(0) +#define SPM_DBG_DEBUG_IDX_26M_SLEEP BIT(1) +#define SPM_DBG_DEBUG_IDX_INFRA_WAKE BIT(2) +#define SPM_DBG_DEBUG_IDX_INFRA_SLEEP BIT(3) +#define SPM_DBG_DEBUG_IDX_APSRC_WAKE BIT(4) +#define SPM_DBG_DEBUG_IDX_APSRC_SLEEP BIT(5) +#define SPM_DBG_DEBUG_IDX_VRF18_WAKE BIT(6) +#define SPM_DBG_DEBUG_IDX_VRF18_SLEEP BIT(7) +#define SPM_DBG_DEBUG_IDX_VCORE_WAKE BIT(8) +#define SPM_DBG_DEBUG_IDX_VCORE_SLEEP BIT(9) +#define SPM_DBG_DEBUG_IDX_DDREN_WAKE BIT(10) +#define SPM_DBG_DEBUG_IDX_DDREN_SLEEP BIT(11) +#define SPM_DBG_DEBUG_IDX_PMIC_WAKE BIT(12) +#define SPM_DBG_DEBUG_IDX_PMIC_SLEEP BIT(13) +#define SPM_DBG_DEBUG_IDX_EMI_WAKE BIT(14) +#define SPM_DBG_DEBUG_IDX_EMI_SLEEP BIT(15) +#define SPM_DBG_DEBUG_IDX_AOVBUS_WAKE BIT(16) +#define SPM_DBG_DEBUG_IDX_AOVBUS_SLEEP BIT(17) +#define SPM_DBG_DEBUG_IDX_CURRENT_IS_CM BIT(18) +#define SPM_DBG_DEBUG_IDX_SYSRAM_ON BIT(19) +#define SPM_DBG_DEBUG_IDX_WAIT_SSPM BIT(20) +#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_SLP BIT(21) +#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_ON BIT(22) +#define SPM_DBG_DEBUG_IDX_SPM_DVFS_NO_REQ BIT(23) +#define SPM_DBG_DEBUG_IDX_VCORE_LP_MODE BIT(24) +#define SPM_DBG_DEBUG_IDX_SPM_NORMAL_WAKEUP BIT(28) +#define SPM_DBG_DEBUG_IDX_SPM_WAKEUP_BY_NONE BIT(29) +/* --- SPM DEBUG1 Define --- */ +#define SPM_DBG1_DEBUG_IDX_CURRENT_IS_LP BIT(0) +#define SPM_DBG1_DEBUG_IDX_VCORE_DVFS_START BIT(1) +#define SPM_DBG1_DEBUG_IDX_SYSPLL_OFF BIT(2) +#define SPM_DBG1_DEBUG_IDX_SYSPLL_ON BIT(3) +#define SPM_DBG1_DEBUG_IDX_VMDDRVDDQ_ON BIT(4) +#define SPM_DBG1_DEBUG_IDX_INFRA_MTCMOS_OFF BIT(5) +#define SPM_DBG1_DEBUG_IDX_INFRA_MTCMOS_ON BIT(6) +#define SPM_DBG1_DEBUG_IDX_VTCXO_SLEEP_ABORT_0 BIT(7) +#define SPM_DBG1_DEBUG_IDX_VTCXO_SLEEP_ABORT_1 BIT(8) +#define SPM_DBG1_DEBUG_IDX_VCORE_SLEEP_ABORT_0 BIT(9) +#define SPM_DBG1_DEBUG_IDX_VCORE_SLEEP_ABORT_1 BIT(10) +#define SPM_DBG1_DEBUG_IDX_PWRAP_CLK_TO_CSOPLU BIT(11) +#define SPM_DBG1_DEBUG_IDX_PWRAP_CLK_TO_26M BIT(12) +#define SPM_DBG1_DEBUG_IDX_SCP_CLK_TO_32K BIT(13) +#define SPM_DBG1_DEBUG_IDX_SCP_CLK_TO_26M BIT(14) +#define SPM_DBG1_DEBUG_IDX_BUS_CLK_OFF BIT(15) +#define SPM_DBG1_DEBUG_IDX_BUS_CLK_ON BIT(16) +#define SPM_DBG1_DEBUG_IDX_SRCLKEN2_LOW BIT(17) +#define SPM_DBG1_DEBUG_IDX_SRCLKEN2_HIGH BIT(18) +#define SPM_DBG1_RESERVED_BIT_19 BIT(19) +#define SPM_DBG1_DEBUG_IDX_CSOPLU_IS_OFF_BUT_SHOULD_ON BIT(20) +#define SPM_DBG1_DEBUG_IDX_PMIC_IRQ_ACK_LOW_ABORT BIT(21) +#define SPM_DBG1_DEBUG_IDX_PMIC_IRQ_ACK_HIGH_ABORT BIT(22) +#define SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_LOW_ABORT BIT(23) +#define SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_HIGH_ABORT BIT(24) +#define SPM_DBG1_DEBUG_IDX_VMDDRVDDQ_OFF BIT(25) +#define SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_LOW_ABORT BIT(26) +#define SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_HIGH_ABORT BIT(27) +#define SPM_DBG1_DEBUG_IDX_SPM_PMIF_CMD_RDY_ABORT BIT(28) +#define SPM_DBG1_DEBUG_IDX_EMI_PDN_RDY_ABORT BIT(29) +#define SPM_DBG1_DEBUG_IDX_LVTS_WRONG_DEVICE_ID BIT(30) +#define SPM_DBG1_DEBUG_IDX_DISABLE_DVFSRC BIT(31) + +/* --- SPM PCM_WDT_LATCH3 Define --- */ +#define SPM_WDT_LATCH3_RESOURCE_STATE_AOV_INFRA_ON BIT(0) +#define SPM_WDT_LATCH3_RESOURCE_STATE_26M_INFRA_ON BIT(1) +#define SPM_WDT_LATCH3_RESOURCE_STATE_AOV_CLK_ON BIT(2) +#define SPM_WDT_LATCH3_RESOURCE_STATE_26M_CLK_ON BIT(3) +#define SPM_WDT_LATCH3_RESOURCE_STATE_AOV_EMI_ON BIT(4) +#define SPM_WDT_LATCH3_RESOURCE_STATE_26M_EMI_ON BIT(5) +#endif /* SLEEP_DEF_H */ diff --git a/plat/mediatek/mt8196/include/platform_def.h b/plat/mediatek/mt8196/include/platform_def.h index 1c01483da..330b82514 100644 --- a/plat/mediatek/mt8196/include/platform_def.h +++ b/plat/mediatek/mt8196/include/platform_def.h @@ -273,4 +273,59 @@ ******************************************************************************/ #define SYSTIMER_BASE (0x1C400000) +/******************************************************************************* + * CKSYS related constants + ******************************************************************************/ +#define CKSYS_BASE (IO_PHYS) + +/******************************************************************************* + * VLP AO related constants + ******************************************************************************/ +#define VLPCFG_BUS_BASE (IO_PHYS + 0x0C001000) +#define VLPCFG_BUS_SIZE (0x1000) +#define VLP_AO_DEVAPC_APB_BASE (IO_PHYS + 0x0C550000) +#define VLP_AO_DEVAPC_APB_SIZE (0x1000) + +/******************************************************************************* + * SCP registers + ******************************************************************************/ +#define SCP_CLK_CTRL_BASE (IO_PHYS + 0x0CF21000) +#define SCP_CLK_CTRL_SIZE (0x1000) + +#define SCP_CFGREG_BASE (IO_PHYS + 0x0CF24000) +#define SCP_CFGREG_SIZE (0x1000) + +/******************************************************************************* + * VLP CKSYS related constants + ******************************************************************************/ +#define VLP_CKSYS_BASE (IO_PHYS + 0x0C016000) +#define VLP_CKSYS_SIZE 0x1000 + +/******************************************************************************* + * PERI related constants use PERI secure address to garuantee access + ******************************************************************************/ +#define PERICFG_AO_SIZE 0x1000 +#define PERI_CG0_STA (PERICFG_AO_BASE + 0x10) +#define PERI_CLK_CON (PERICFG_AO_BASE + 0x20) +#define PERI_CG1_CLR (PERICFG_AO_BASE + 0x30) + +/****************************************************************************** + * LPM syssram related constants + *****************************************************************************/ +#define MTK_LPM_SRAM_BASE 0x11B000 +#define MTK_LPM_SRAM_MAP_SIZE 0x1000 + +/******************************************************************************* + * SSPM_MBOX_3 related constants + ******************************************************************************/ +#define SSPM_MBOX_3_BASE (IO_PHYS + 0x0C380000) +#define SSPM_MBOX_3_SIZE 0x1000 + +/******************************************************************************* + * SSPM related constants + ******************************************************************************/ +#define SSPM_REG_OFFSET (0x40000) +#define SSPM_CFGREG_BASE (IO_PHYS + 0x0C300000 + SSPM_REG_OFFSET) +#define SSPM_CFGREG_SIZE (0x1000) + #endif /* PLATFORM_DEF_H */