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 <wenzhen.yu@mediatek.com>
Change-Id: Ie51cffeb1d683d65d88701fc63c426b20b22492f
This commit is contained in:
Wenzhen Yu 2024-12-20 14:37:26 +08:00
parent 01ce1d5d2f
commit fb57af70ae
9 changed files with 1575 additions and 0 deletions

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <lib/mmio.h>
#include <platform_def.h>
#include <lpm_v2/mt_lpm_dispatch.h>
#include <lpm_v2/mt_lpm_smc.h>
#include <mt_spm_conservation.h>
#include <mt_spm_dispatcher.h>
#include <mt_spm_internal.h>
#include <mt_spm_reg.h>
#include <mt_spm_smc.h>
#include <mt_spm_suspend.h>
#include <pcm_def.h>
#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;
}

View file

@ -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 */

View file

@ -0,0 +1,707 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <lib/mmio.h>
#include <platform_def.h>
#include <mt_spm_hwreq.h>
#include <mt_spm_reg.h>
/* 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();
}

View file

@ -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 <drivers/spm/mt_spm_resource_req.h>
/* 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 */

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <lib/mmio.h>
#include <mt_spm.h>
#include <mt_spm_reg.h>
#include <mt_spm_stats.h>
#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;
}

View file

@ -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 <stdint.h>
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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */