diff --git a/plat/mediatek/drivers/spm/common/dbg_ctrl.h b/plat/mediatek/drivers/spm/common/dbg_ctrl.h new file mode 100644 index 000000000..aea2fb8b1 --- /dev/null +++ b/plat/mediatek/drivers/spm/common/dbg_ctrl.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DBG_CTRL_H +#define DBG_CTRL_H + +/* SPM_WAKEUP_MISC */ +#define WAKE_MISC_TWAM BIT(18) +#define WAKE_MISC_PCM_TIMER BIT(19) +#define WAKE_MISC_CPU_WAKE BIT(20) + +struct dbg_ctrl { + uint32_t count; + uint32_t duration; + void *ext; +}; + +enum dbg_ctrl_enum { + DBG_CTRL_COUNT, + DBG_CTRL_DURATION, + DBG_CTRL_MAX, +}; + +#endif /* DBG_CTRL_H */ diff --git a/plat/mediatek/drivers/spm/common/mt_spm_common.h b/plat/mediatek/drivers/spm/common/mt_spm_common.h new file mode 100644 index 000000000..b44361ed4 --- /dev/null +++ b/plat/mediatek/drivers/spm/common/mt_spm_common.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights resrved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_COMMON_H +#define MT_SPM_COMMON_H + +#include <lib/bakery_lock.h> +#include <lib/spinlock.h> +/* + * ARM v8.2, the cache will turn off automatically when cpu + * power down. So, there is no doubt to use the spin_lock here + */ +#if !HW_ASSISTED_COHERENCY +#define MT_SPM_USING_BAKERY_LOCK +#endif + +#ifdef MT_SPM_USING_BAKERY_LOCK +DECLARE_BAKERY_LOCK(spm_lock); +#define plat_spm_lock() \ + bakery_lock_get(&spm_lock) + +#define plat_spm_unlock() \ + bakery_lock_release(&spm_lock) +#else +extern spinlock_t spm_lock; +#define plat_spm_lock() \ + spin_lock(&spm_lock) + +#define plat_spm_unlock() \ + spin_unlock(&spm_lock) +#endif + +#define MT_SPM_ERR_NO_FW_LOAD -1 +#define MT_SPM_ERR_KICKED -2 +#define MT_SPM_ERR_RUNNING -3 +#define MT_SPM_ERR_FW_NOT_FOUND -4 +#define MT_SPM_ERR_INVALID -5 +#define MT_SPM_ERR_OVERFLOW -6 + +static inline void spm_lock_get(void) +{ + plat_spm_lock(); +} + +static inline void spm_lock_release(void) +{ + plat_spm_unlock(); +} + +#endif /* MT_SPM_COMMON_H */ diff --git a/plat/mediatek/drivers/spm/common/mt_spm_constraint.h b/plat/mediatek/drivers/spm/common/mt_spm_constraint.h new file mode 100644 index 000000000..0dbbfb344 --- /dev/null +++ b/plat/mediatek/drivers/spm/common/mt_spm_constraint.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_CONSTRAINT_H +#define MT_SPM_CONSTRAINT_H + +#include <lpm_v2/mt_lp_rm.h> + +#define MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF BIT(0) +#define MT_RM_CONSTRAINT_ALLOW_DRAM_S0 BIT(1) +#define MT_RM_CONSTRAINT_ALLOW_DRAM_S1 BIT(2) +#define MT_RM_CONSTRAINT_ALLOW_VCORE_LP BIT(3) +#define MT_RM_CONSTRAINT_ALLOW_INFRA_PDN BIT(4) +#define MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF BIT(5) +#define MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND BIT(6) /* System suspend */ +#define MT_RM_CONSTRAINT_ALLOW_BBLPM BIT(7) +#define MT_RM_CONSTRAINT_ALLOW_XO_UFS BIT(8) +#define MT_RM_CONSTRAINT_ALLOW_GPS_STATE BIT(9) +#define MT_RM_CONSTRAINT_ALLOW_LVTS_STATE BIT(10) +#define MT_RM_CONSTRAINT_ALLOW_AP_PLAT_SUSPEND BIT(11) /* Kernel suspend */ +#define MT_RM_CONSTRAINT_ALLOW_VCORE_OFF BIT(12) + +#define MT_SPM_RC_INVALID 0x0 +#define MT_SPM_RC_VALID_SW BIT(0) +#define MT_SPM_RC_VALID_FW BIT(1) +#define MT_SPM_RC_VALID_RESIDNECY BIT(2) +#define MT_SPM_RC_VALID_COND_CHECK BIT(3) +#define MT_SPM_RC_VALID_COND_LATCH BIT(4) +#define MT_SPM_RC_VALID_UFS_H8 BIT(5) +#define MT_SPM_RC_VALID_FLIGHTMODE BIT(6) +#define MT_SPM_RC_VALID_XSOC_BBLPM BIT(7) +#define MT_SPM_RC_VALID_TRACE_EVENT BIT(8) +#define MT_SPM_RC_VALID_TRACE_TIME BIT(9) +#define MT_SPM_RC_VALID_NOTIFY BIT(10) + +#define MT_SPM_RC_VALID (MT_SPM_RC_VALID_SW | MT_SPM_RC_VALID_FW) + +#define IS_MT_RM_RC_READY(status) \ + ((status & MT_SPM_RC_VALID) == MT_SPM_RC_VALID) + +struct constraint_status { + uint16_t id; + uint16_t is_valid; + uint64_t is_cond_block; + uint32_t enter_cnt; + uint64_t all_pll_dump; + unsigned long long residency; + struct mt_spm_cond_tables *cond_res; +}; + +enum constraint_status_update_type { + CONSTRAINT_UPDATE_VALID, + CONSTRAINT_UPDATE_COND_CHECK, + CONSTRAINT_RESIDNECY, +}; + +enum constraint_status_get_type { + CONSTRAINT_GET_VALID = 0xD0000000, + CONSTRAINT_GET_ENTER_CNT, + CONSTRAINT_GET_RESIDENCY, + CONSTRAINT_GET_COND_EN, + CONSTRAINT_COND_BLOCK, + CONSTRAINT_GET_COND_BLOCK_LATCH, + CONSTRAINT_GET_COND_BLOCK_DETAIL, + CONSTRAINT_GET_RESIDNECY, +}; + +struct rc_common_state { + unsigned int id; + unsigned int act; + unsigned int type; + void *value; +}; + +#define MT_SPM_RC_BBLPM_MODE (MT_SPM_RC_VALID_UFS_H8 | \ + MT_SPM_RC_VALID_FLIGHTMODE | \ + MT_SPM_RC_VALID_XSOC_BBLPM) + +#define IS_MT_SPM_RC_BBLPM_MODE(st) \ + ((st & (MT_SPM_RC_BBLPM_MODE)) == MT_SPM_RC_BBLPM_MODE) + +#define IS_MT_SPM_RC_NOTIFY_ENABLE(st) \ + ((st & (MT_SPM_RC_VALID_NOTIFY))) + +#define MT_SPM_RC_EXTERN_STATUS_SET(v, st) ({v |= (st & 0xffff); }) +#define MT_SPM_RC_EXTERN_STATUS_CLR(v, st) ({v &= ~(st & 0xffff); }) + +#endif /* MT_SPM_CONSTRAINT_H */ diff --git a/plat/mediatek/drivers/spm/common/mt_spm_smc.h b/plat/mediatek/drivers/spm/common/mt_spm_smc.h new file mode 100644 index 000000000..62f090f65 --- /dev/null +++ b/plat/mediatek/drivers/spm/common/mt_spm_smc.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_SMC_H +#define MT_SPM_SMC_H + +/* + * SPM dispatcher's smc id definition + * Please adding custom smc id here for spm dispatcher + */ +#define MT_SPM_STATUS_SUSPEND_SLEEP BIT(27) + +enum mt_spm_smc_uid { + MT_SPM_SMC_UID_STATUS, + MT_SPM_SMC_UID_PCM_WDT, + MT_SPM_SMC_UID_PCM_TIMER, + MT_SPM_SMC_UID_FW_TYPE, + MT_SPM_SMC_UID_PHYPLL_MODE, + MT_SPM_SMC_UID_SET_PENDING_IRQ_INIT, + MT_SPM_SMC_UID_FW_INIT = 0x5731, +}; + +/* + * SPM dbg dispatcher's smc id definition + * Please adding custom smc id here for spm dbg dispatcher + */ +enum mt_spm_dbg_smc_uid { + MT_SPM_DBG_SMC_UID_IDLE_PWR_CTRL, + MT_SPM_DBG_SMC_UID_IDLE_CNT, + MT_SPM_DBG_SMC_UID_SUSPEND_PWR_CTRL, + MT_SPM_DBG_SMC_UID_SUSPEND_DBG_CTRL, + MT_SPM_DBG_SMC_UID_FS, + MT_SPM_DBG_SMC_UID_RC_SWITCH, + MT_SPM_DBG_SMC_UID_RC_CNT, + MT_SPM_DBG_SMC_UID_COND_CHECK, + MT_SPM_DBG_SMC_UID_COND_BLOCK, + MT_SPM_DBG_SMC_UID_BLOCK_LATCH, + MT_SPM_DBG_SMC_UID_BLOCK_DETAIL, + MT_SPM_DBG_SMC_UID_RES_NUM, + MT_SPM_DBG_SMC_UID_RES_REQ, + MT_SPM_DBG_SMC_UID_RES_USAGE, + MT_SPM_DBG_SMC_UID_RES_USER_NUM, + MT_SPM_DBG_SMC_UID_RES_USER_VALID, + MT_SPM_DBG_SMC_UID_RES_USER_NAME, + MT_SPM_DBG_SMC_UID_DOE_RESOURCE_CTRL, + MT_SPM_DBG_SMC_UID_DOE_RC, + MT_SPM_DBG_SMC_UID_RC_COND_CTRL, + MT_SPM_DBG_SMC_UID_RC_RES_CTRL, + MT_SPM_DBG_SMC_UID_RC_RES_INFO, + MT_SPM_DBG_SMC_UID_RC_BBLPM, + MT_SPM_DBG_SMC_UID_RC_TRACE, + MT_SPM_DBG_SMC_UID_RC_TRACE_TIME, + MT_SPM_DBG_SMC_UID_DUMP_PLL, + MT_SPM_DBG_SMC_HWCG_NUM, + MT_SPM_DBG_SMC_HWCG_STATUS, + MT_SPM_DBG_SMC_HWCG_SETTING, + MT_SPM_DBG_SMC_HWCG_DEF_SETTING, + MT_SPM_DBG_SMC_HWCG_RES_NAME, + MT_SPM_DBG_SMC_UID_RC_NOTIFY_CTRL, + MT_SPM_DBG_SMC_VCORE_LP_ENABLE, + MT_SPM_DBG_SMC_VCORE_LP_VOLT, + MT_SPM_DBG_SMC_VSRAM_LP_ENABLE, + MT_SPM_DBG_SMC_VSRAM_LP_VOLT, + MT_SPM_DBG_SMC_PERI_REQ_NUM, + MT_SPM_DBG_SMC_PERI_REQ_STATUS, + MT_SPM_DBG_SMC_PERI_REQ_SETTING, + MT_SPM_DBG_SMC_PERI_REQ_DEF_SETTING, + MT_SPM_DBG_SMC_PERI_REQ_RES_NAME, + MT_SPM_DBG_SMC_PERI_REQ_STATUS_RAW, + MT_SPM_DBG_SMC_IDLE_PWR_STAT, + MT_SPM_DBG_SMC_SUSPEND_PWR_STAT, + MT_SPM_DBG_SMC_LP_REQ_STAT, + MT_SPM_DBG_SMC_COMMON_SODI_CTRL, + MT_SPM_DBG_SMC_SPM_TIMESTAMP, + MT_SPM_DBG_SMC_SPM_TIMESTAMP_SIZE, + MT_SPM_DBG_SMC_UID_COMMON_SODI_PWR_CTRL, +}; + +enum wake_status_enum { + WAKE_STA_ASSERT_PC, + WAKE_STA_R12, + WAKE_STA_R12_EXT, + WAKE_STA_RAW_STA, + WAKE_STA_RAW_EXT_STA, + WAKE_STA_WAKE_MISC, + WAKE_STA_TIMER_OUT, + WAKE_STA_R13, + WAKE_STA_IDLE_STA, + WAKE_STA_REQ_STA, + WAKE_STA_DEBUG_FLAG, + WAKE_STA_DEBUG_FLAG1, + WAKE_STA_EVENT_REG, + WAKE_STA_ISR, + WAKE_STA_MAX_COUNT, +}; + +#endif /* MT_SPM_SMC_H */ diff --git a/plat/mediatek/drivers/spm/common/rules.mk b/plat/mediatek/drivers/spm/common/rules.mk new file mode 100644 index 000000000..50273de46 --- /dev/null +++ b/plat/mediatek/drivers/spm/common/rules.mk @@ -0,0 +1,18 @@ +# +# Copyright (c) 2025, MediaTek Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +#Prologue, init variable +LOCAL_DIR := $(call GET_LOCAL_DIR) + +#Define your module name +MODULE := spm_common + +#Add your source code here +LOCAL_SRCS-y := + +#Epilogue, build as module +$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL))) +$(eval $(call add_defined_option,CONFIG_MTK_VCOREDVFS_SUPPORT)) diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm.c b/plat/mediatek/drivers/spm/mt8196/mt_spm.c new file mode 100644 index 000000000..fee5b4c74 --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/mt_spm.c @@ -0,0 +1,464 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> + +#include <arch.h> +#include <common/debug.h> +#include <drivers/console.h> +#include <drivers/delay_timer.h> +#include <drivers/gpio.h> +#include <lib/bakery_lock.h> +#include <lib/mmio.h> +#include <lib/utils_def.h> +#include <platform_def.h> + +#include <constraints/mt_spm_rc_api.h> +#include <constraints/mt_spm_rc_internal.h> +#include <drivers/spm/mt_spm_resource_req.h> +#include <lib/mtk_init/mtk_init.h> +#include <lib/pm/mtk_pm.h> +#include <lpm_v2/mt_lp_rm.h> +#include <lpm_v2/mt_lp_rqm.h> +#include <lpm_v2/mt_lpm_smc.h> +#include <mt_plat_spm_setting.h> +#include <mt_spm.h> +#include <mt_spm_common.h> +#include <mt_spm_conservation.h> +#include <mt_spm_constraint.h> +#include <mt_spm_dispatcher.h> +#include <mt_spm_hwreq.h> +#include <mt_spm_idle.h> +#include <mt_spm_internal.h> +#include <mt_spm_reg.h> +#include <mt_spm_suspend.h> +#include <mtk_mmap_pool.h> +#include <sleep_def.h> + +#ifdef MT_SPM_USING_BAKERY_LOCK +DEFINE_BAKERY_LOCK(spm_lock); +#define plat_spm_lock_init() \ + bakery_lock_init(&spm_lock) +#else +spinlock_t spm_lock; +#define plat_spm_lock_init() +#endif + +uint32_t mt_spm_version; + +static uint32_t spm_irq_num; + +void spm_set_sysclk_settle(void) +{ + uint32_t settle; + + mmio_write_32(SPM_CLK_SETTLE, SPM_SYSCLK_SETTLE); + settle = mmio_read_32(SPM_CLK_SETTLE); + + INFO("md_settle = %u, settle = %u\n", SPM_SYSCLK_SETTLE, settle); +} + +void spm_set_irq_num(uint32_t num) +{ + spm_irq_num = num; +} + +void spm_irq0_handler(uint64_t x1, uint64_t x2) +{ + if (x2 == 0) { + mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM); + mmio_write_32(SPM_IRQ_STA, x1); + mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT0); + } +} + +static int spm_ap_mdsrc_ack(void) +{ + int ack, md_state = 0; + + /* Check ap_mdsrc_ack = 1'b1, for md internal resource on ack */ + ack = !!(mmio_read_32(AP_MDSRC_REQ) & AP_MDSMSRC_ACK_LSB); + + if (!ack) { + /* Check md_apsrc_req = 1'b0, for md state 0:sleep, 1:wakeup */ + md_state = !!(mmio_read_32(SPM_REQ_STA_10) + & MD_APSRC_REQ_LSB); + + ERROR("[SPM] error: md_sleep = %d\n", md_state); + ERROR("%s can not get AP_MDSRC_ACK\n", __func__); + return -1; + } + return 0; +} + +static void spm_ap_mdsrc_req(int set) +{ + spm_lock_get(); + + if (set) + mmio_setbits_32(AP_MDSRC_REQ, AP_MDSMSRC_REQ_LSB); + else + mmio_clrbits_32(AP_MDSRC_REQ, AP_MDSMSRC_REQ_LSB); + + spm_lock_release(); +} + +static int spm_is_md_sleep(void *priv) +{ + int md_state = 0; + int *sleep = (int *)priv; + + if (!priv) + return -1; + + /* Check md_apsrc_req = 1'b0, for md state 0:sleep, 1:wakeup */ + md_state = !!(mmio_read_32(SPM_REQ_STA_10) + & MD_APSRC_REQ_LSB); + + if (md_state == 0) + *sleep = 1; + else + *sleep = 0; + + return 0; +} + +static void spm_ap_gpueb_pll_control(int set) +{ + spm_lock_get(); + + if (set) + mmio_setbits_32(SPM2GPUPM_CON, SC_MFG_PLL_EN_LSB); + else + mmio_clrbits_32(SPM2GPUPM_CON, SC_MFG_PLL_EN_LSB); + + spm_lock_release(); +} + +static uint32_t spm_ap_gpueb_get_pwr_status(void) +{ + uint32_t ret; + + ret = mmio_read_32(XPU_PWR_STATUS); + + return ret; +} + +static uint32_t spm_ap_gpueb_get_mfg0_pwr_con(void) +{ + uint32_t ret; + + ret = mmio_read_32(MFG0_PWR_CON); + + return ret; +} + +#ifndef MTK_PLAT_SPM_UNSUPPORT +struct mt_lp_res_req rq_xo_fpm = { + .res_id = MT_LP_RQ_XO_FPM, + .res_rq = MT_SPM_XO_FPM, + .res_usage = 0, +}; + +struct mt_lp_res_req rq_26m = { + .res_id = MT_LP_RQ_26M, + .res_rq = MT_SPM_26M, + .res_usage = 0, +}; + +struct mt_lp_res_req rq_infra = { + .res_id = MT_LP_RQ_INFRA, + .res_rq = MT_SPM_INFRA, + .res_usage = 0, +}; + +struct mt_lp_res_req rq_syspll = { + .res_id = MT_LP_RQ_SYSPLL, + .res_rq = MT_SPM_SYSPLL, + .res_usage = 0, +}; + +struct mt_lp_res_req rq_dram_s0 = { + .res_id = MT_LP_RQ_DRAM, + .res_rq = MT_SPM_DRAM_S0, + .res_usage = 0, +}; + +struct mt_lp_res_req rq_dram_s1 = { + .res_id = MT_LP_RQ_DRAM, + .res_rq = MT_SPM_DRAM_S1, + .res_usage = 0, +}; + +struct mt_lp_res_req rq_vcore = { + .res_id = MT_LP_RQ_VCORE, + .res_rq = MT_SPM_VCORE, + .res_usage = 0, +}; + +struct mt_lp_res_req rq_emi = { + .res_id = MT_LP_RQ_EMI, + .res_rq = MT_SPM_EMI, + .res_usage = 0, +}; + +struct mt_lp_res_req rq_pmic = { + .res_id = MT_LP_RQ_PMIC, + .res_rq = MT_SPM_PMIC, + .res_usage = 0, +}; + +struct mt_lp_res_req *spm_resources[] = { + &rq_xo_fpm, + &rq_26m, + &rq_infra, + &rq_syspll, + &rq_dram_s0, + &rq_dram_s1, + &rq_vcore, + &rq_emi, + &rq_pmic, + NULL, +}; + +struct mt_resource_req_manager plat_mt8196_rq = { + .res = spm_resources, +}; + +struct mt_resource_constraint plat_constraint_vcore = { + .is_valid = spm_is_valid_rc_vcore, + .update = spm_update_rc_vcore, + .allow = spm_allow_rc_vcore, + .run = spm_run_rc_vcore, + .reset = spm_reset_rc_vcore, + .get_status = spm_get_status_rc_vcore, +}; + +struct mt_resource_constraint plat_constraint_bus26m = { + .is_valid = spm_is_valid_rc_bus26m, + .update = spm_update_rc_bus26m, + .allow = spm_allow_rc_bus26m, + .run = spm_run_rc_bus26m, + .reset = spm_reset_rc_bus26m, + .get_status = spm_get_status_rc_bus26m, +}; + +struct mt_resource_constraint plat_constraint_syspll = { + .is_valid = spm_is_valid_rc_syspll, + .update = spm_update_rc_syspll, + .allow = spm_allow_rc_syspll, + .run = spm_run_rc_syspll, + .reset = spm_reset_rc_syspll, + .get_status = spm_get_status_rc_syspll, +}; + +struct mt_resource_constraint *plat_constraints[] = { + &plat_constraint_vcore, + &plat_constraint_bus26m, + &plat_constraint_syspll, + NULL, +}; +#endif + +int mt_spm_hwctrl(uint32_t type, int set, void *priv) +{ + int ret = 0; + + if (type == PLAT_AP_MDSRC_REQ) { + spm_ap_mdsrc_req(set); + } else if (type == PLAT_AP_MDSRC_ACK) { + ret = spm_ap_mdsrc_ack(); + } else if (type == PLAT_AP_IS_MD_SLEEP) { + ret = spm_is_md_sleep(priv); + } else if (type == PLAT_AP_MDSRC_SETTLE) { + if (!priv) + return -1; + *(int *)priv = AP_MDSRC_REQ_MD_26M_SETTLE; + } else if (type == PLAT_AP_GPUEB_PLL_CONTROL) { + spm_ap_gpueb_pll_control(set); + } else if (type == PLAT_AP_GPUEB_PWR_STATUS) { + if (!priv) + return -1; + *(uint32_t *)priv = spm_ap_gpueb_get_pwr_status(); + } else if (type == PLAT_AP_GPUEB_MFG0_PWR_CON) { + if (!priv) + return -1; + *(uint32_t *)priv = spm_ap_gpueb_get_mfg0_pwr_con(); + } else if (type == PLAT_AP_SPM_RESOURCE_REQUEST_UPDATE) { + struct spm_lp_scen *spmlp = NULL; + +#ifdef MT_SPM_COMMON_SODI_SUPPORT + mt_spm_common_sodi_get_spm_lp(&spmlp); +#else +#if defined(MT_SPM_FEATURE_SUPPORT) + mt_spm_idle_generic_get_spm_lp(&spmlp); +#endif +#endif + if (!spmlp) + return -1; + __spm_set_power_control(spmlp->pwrctrl, *(uint32_t *)priv); + ret = __spm_wait_spm_request_ack(*(uint32_t *)priv, + SPM_ACK_TIMEOUT_US); + } else if (type == PLAT_AP_SPM_WDT_TRIGGER) { + mmio_write_32(PCM_WDT_VAL, 0x1); + mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | + REG_PCM_WDT_EN_LSB | REG_PCM_WDT_WAKE_LSB); + } else { + /* Not supported type */ + return -1; + } + + return ret; +} + +#ifndef MTK_PLAT_SPM_UNSUPPORT +struct mt_resource_manager plat_mt8196_rm = { + .update = NULL, + .hwctrl = mt_spm_hwctrl, + .consts = plat_constraints, +}; +#else +struct mt_resource_manager plat_mt8196_rm = { + .hwctrl = mt_spm_hwctrl, +}; +#endif + +/* Determine for spm sw resource user */ +static struct mt_lp_resource_user spm_res_user; + +struct mt_lp_resource_user *get_spm_res_user(void) +{ + return &spm_res_user; +} + +#ifdef MT_SPM_COMMON_SODI_SUPPORT +int mt_spm_common_sodi_get_spm_pcm_flag(uint32_t *lp, uint32_t idx) +{ + struct spm_lp_scen *spmlp; + struct pwr_ctrl *pwrctrl; + + mt_spm_common_sodi_get_spm_lp(&spmlp); + + pwrctrl = spmlp->pwrctrl; + + if (!lp || idx > 1) + return -1; + + switch (idx) { + case 0: + *lp = pwrctrl->pcm_flags; + break; + case 1: + *lp = pwrctrl->pcm_flags; + break; + default: + return -1; + } + return 0; +} + +void mt_spm_common_sodi_en(bool en) +{ + struct spm_lp_scen *spmlp; + struct pwr_ctrl *pwrctrl; + + mt_spm_common_sodi_get_spm_lp(&spmlp); + pwrctrl = spmlp->pwrctrl; +#if defined(CONFIG_MTK_VCOREDVFS_SUPPORT) + __spm_sync_vcore_dvfs_pcm_flags(&pwrctrl->pcm_flags, + &__spm_vcorefs.pwrctrl->pcm_flags); +#endif + if (en) + pwrctrl->pcm_flags |= SPM_FLAG_ENABLE_COMMON_SODI5; + else + pwrctrl->pcm_flags &= (~SPM_FLAG_ENABLE_COMMON_SODI5); + + /* Set PCM flags */ + __spm_set_pcm_flags(pwrctrl); + + __spm_send_cpu_wakeup_event(); +} + +int mt_spm_common_sodi_get_spm_lp(struct spm_lp_scen **lp) +{ + if (!lp) + return -1; + + *lp = &__spm_common_sodi; + return 0; +} + +void mt_spm_set_common_sodi_pwrctr(void) +{ + struct resource_req_status common_sodi_spm_resource_req = { + .id = MT_LP_RQ_ID_ALL_USAGE, + .val = 0, + }; + struct spm_lp_scen *spmlp; + + mt_lp_rq_get_status(PLAT_RQ_REQ_USAGE, + &common_sodi_spm_resource_req); + mt_spm_common_sodi_get_spm_lp(&spmlp); + + __spm_set_power_control(spmlp->pwrctrl, + common_sodi_spm_resource_req.val); +} + +void mt_spm_set_common_sodi_pcm_flags(void) +{ + struct spm_lp_scen *spmlp; + struct pwr_ctrl *pwrctrl; + + mt_spm_common_sodi_get_spm_lp(&spmlp); + pwrctrl = spmlp->pwrctrl; +#if defined(CONFIG_MTK_VCOREDVFS_SUPPORT) + /* Set PCM flags */ + __spm_sync_vcore_dvfs_pcm_flags(&pwrctrl->pcm_flags, + &__spm_vcorefs.pwrctrl->pcm_flags); +#endif + __spm_set_pcm_flags(pwrctrl); + + __spm_send_cpu_wakeup_event(); + +} +#endif + +static void spm_gpio_init(void) +{ + gpio_set_direction(EC_SUSPEND_PIN, GPIO_DIR_OUT); + gpio_set_value(EC_SUSPEND_PIN, GPIO_LEVEL_HIGH); +} + +int spm_boot_init(void) +{ + plat_spm_lock_init(); + +#if defined(MT_SPM_FEATURE_SUPPORT) + plat_spm_pmic_wrap_init(); +#endif + mt_lp_rm_register(&plat_mt8196_rm); + +#ifndef MTK_PLAT_SPM_UNSUPPORT + mt_lp_resource_request_manager_register(&plat_mt8196_rq); + mt_lp_resource_user_register("SPM", &spm_res_user); + mt_spm_dispatcher_init(); +#endif +#if defined(MT_SPM_FEATURE_SUPPORT) + spm_hwreq_init(); +#endif + spm_gpio_init(); + + spm_irq_num = 0xFFFFFFFF; + + INFO("[%s:%d] - spm finished, version = %u, PC = 0x%x\n", + __func__, __LINE__, + mt_spm_version, mmio_read_32(MD32PCM_PC)); + return 0; +} +MTK_PLAT_SETUP_1_INIT(spm_boot_init); diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm.h b/plat/mediatek/drivers/spm/mt8196/mt_spm.h new file mode 100644 index 000000000..bc6fa44e5 --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/mt_spm.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_H +#define MT_SPM_H + +#include <stdint.h> +#include <stdio.h> + +#include <lib/pm/mtk_pm.h> +#include <lpm_v2/mt_lp_rq.h> + +#ifdef __GNUC__ +#define spm_likely(x) __builtin_expect(!!(x), 1) +#define spm_unlikely(x) __builtin_expect(!!(x), 0) +#else +#define spm_likely(x) (x) +#define spm_unlikely(x) (x) +#endif + +#define CLK_SCP_CFG_0 (CKSYS_BASE + 0x1A0) +#define INFRA_BUS_DCM_CTRL (INFRACFG_AO_BASE + 0x070) +#define RG_AXI_DCM_DIS_EN BIT(21) +#define RG_PLLCK_SEL_NO_SPM BIT(22) + +#define MT_SPM_TIME_GET(tm) ({ (tm) = el3_uptime(); }) + +#define MT_SPM_VERSION_ES 0x0 +#define MT_SPM_VERSION_CS 0x1 + +#define SPM_FW_NO_RESUME 1 +#define MCUSYS_MTCMOS_ON 0 +#define WAKEUP_LOG_ON 0 + +#define MT_SPM_USING_SRCLKEN_RC +/* SPM extern operand definition */ +#define MT_SPM_EX_OP_CLR_26M_RECORD BIT(0) +#define MT_SPM_EX_OP_SET_WDT BIT(1) +#define MT_SPM_EX_OP_NON_GENERIC_RESOURCE_REQ BIT(2) +#define MT_SPM_EX_OP_SET_SUSPEND_MODE BIT(3) +#define MT_SPM_EX_OP_SET_IS_ADSP BIT(4) +#define MT_SPM_EX_OP_SRCLKEN_RC_BBLPM BIT(5) +#define MT_SPM_EX_OP_HW_S1_DETECT BIT(6) +#define MT_SPM_EX_OP_TRACE_LP BIT(7) +#define MT_SPM_EX_OP_TRACE_SUSPEND BIT(8) +#define MT_SPM_EX_OP_TRACE_TIMESTAMP_EN BIT(9) +#define MT_SPM_EX_OP_TIME_CHECK BIT(10) +#define MT_SPM_EX_OP_TIME_OBS BIT(11) +#define MT_SPM_EX_OP_SET_IS_USB_HEADSET BIT(12) +#define MT_SPM_EX_OP_SET_IS_FM_AUDIO BIT(13) +#define MT_SPM_EX_OP_DEVICES_SAVE BIT(14) +#define MT_SPM_EX_OP_NOTIFY_INFRA_OFF BIT(15) + +#define MT_BUS26M_EXT_LP_26M_ON_MODE (MT_SPM_EX_OP_SET_IS_ADSP | \ + MT_SPM_EX_OP_SET_IS_FM_AUDIO) + +#define MT_VCORE_EXT_LP_VCORE_ON_MODE (MT_SPM_EX_OP_SET_IS_ADSP | \ + MT_SPM_EX_OP_SET_IS_FM_AUDIO) + +/* EN SPM INFRA DEBUG OUT */ +#define DEBUGSYS_DEBUG_EN_REG (DBGSYS_DEM_BASE + 0x94) + +/* INFRA_AO_DEBUG_CON */ +#define INFRA_AO_DBG_CON0 (INFRACFG_AO_BASE + 0x500) +#define INFRA_AO_DBG_CON1 (INFRACFG_AO_BASE + 0x504) +#define INFRA_AO_DBG_CON2 (INFRACFG_AO_BASE + 0x508) +#define INFRA_AO_DBG_CON3 (INFRACFG_AO_BASE + 0x50C) + +/* SPM init. related registers */ +#define VLP_AO_APC_CON (VLP_AO_DEVAPC_APB_BASE + 0xF00) +#define VLP_AO_MAS_SEC_0 (VLP_AO_DEVAPC_APB_BASE + 0xA00) +#define SCP_CFGREG_PERI_BUS_CTRL0 (SCP_CFGREG_BASE + 0x24) +#define MODULE_SW_CG_0_MASK (INFRACFG_AO_BASE + 0x060) +#define VLP_DBG_MON_SEL0_ADDR (VLPCFG_BUS_BASE + 0x108) +#define VLP_DBG_MON_SEL1_ADDR (VLPCFG_BUS_BASE + 0x10C) +#define VLP_CLKSQ_CON1 (VLP_CKSYS_BASE + 0x224) +#define VLP_AP_PLL_CON3 (VLP_CKSYS_BASE + 0x264) + +/* SPM SRAM Data */ +#define SPM_SRAM_TIMESTAMP_START (SPM_SRAM_BASE + 0xF80) +#define SPM_SRAM_TIMESTAMP_END (SPM_SRAM_BASE + 0xFFC) +#define SPM_SRAM_TIMESTAMP_SIZE \ + (((SPM_SRAM_TIMESTAMP_END - SPM_SRAM_TIMESTAMP_START) >> 2) + 1) + +/* AP_MDSRC_REQ MD 26M ON settle time (3ms) */ +#define AP_MDSRC_REQ_MD_26M_SETTLE 3 + +/* Setting the SPM settle time*/ +#define SPM_SYSCLK_SETTLE 0x60FE /* 1685us */ + +/* Setting the SPM req/ack time*/ +#define SPM_ACK_TIMEOUT_US 1000 + +/* Settine the firmware status check for SPM PC */ +#define SPM_PC_CHECKABLE + +enum { + SPM_ARGS_SPMFW_IDX_KICK = 0, + SPM_ARGS_SPMFW_INIT, + SPM_ARGS_SUSPEND, + SPM_ARGS_SUSPEND_FINISH, + SPM_ARGS_SODI, + SPM_ARGS_SODI_FINISH, + SPM_ARGS_DPIDLE, + SPM_ARGS_DPIDLE_FINISH, + SPM_ARGS_PCM_WDT, + SPM_ARGS_SUSPEND_CALLBACK, + SPM_ARGS_HARDWARE_CG_CHECK, + SPM_ARGS_NUM, +}; + +typedef enum { + WR_NONE = 0, + WR_UART_BUSY, + WR_ABORT, + WR_PCM_TIMER, + WR_WAKE_SRC, + WR_DVFSRC, + WR_TWAM, + WR_PMSR, + WR_SPM_ACK_CHK, + WR_UNKNOWN, +} wake_reason_t; + +struct pwr_ctrl; +struct spm_lp_scen; + +void spm_set_irq_num(uint32_t num); +void spm_irq0_handler(uint64_t x1, uint64_t x2); +struct mt_lp_resource_user *get_spm_res_user(void); +int mt_spm_common_sodi_get_spm_pcm_flag(uint32_t *lp, uint32_t idx); +void mt_spm_common_sodi_en(bool en); +int mt_spm_common_sodi_get_spm_lp(struct spm_lp_scen **lp); +void mt_spm_set_common_sodi_pwrctr(void); +void mt_spm_set_common_sodi_pcm_flags(void); +int spm_boot_init(void); +void spm_dvfsfw_init(uint64_t boot_up_opp, uint64_t dram_issue); +extern uint32_t mt_spm_version; +extern struct pwr_ctrl spm_init_ctrl; +/* Support by bl31_plat_setup.c */ +uint32_t is_abnormal_boot(void); + +#endif /* MT_SPM_H */ diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm_conservation.c b/plat/mediatek/drivers/spm/mt8196/mt_spm_conservation.c new file mode 100644 index 000000000..16d9f29d6 --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/mt_spm_conservation.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <inttypes.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +#include <common/debug.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> +#include <platform_def.h> + +#include <lib/pm/mtk_pm.h> +#include <lpm_v2/mt_lp_rqm.h> +#include <mt_spm.h> +#include <mt_spm_common.h> +#include <mt_spm_conservation.h> +#include <mt_spm_reg.h> +#include <mt_spm_vcorefs.h> + +#define MT_RESUMETIME_THRESHOLD_MAX 5 +#define IS_RESUME_OVERTIME(delta) \ + (delta > MT_RESUMETIME_THRESHOLD_MAX) + +static struct wake_status spm_wakesta; /* Record last wakesta */ +static wake_reason_t spm_wake_reason = WR_NONE; +static struct resource_req_status generic_spm_resource_req = { + .id = MT_LP_RQ_ID_ALL_USAGE, + .val = 0, +}; + +#define do_spm_init(pwrctrl) ({ int local_ret = 0; local_ret; }) +#define do_spm_run(pwrctrl) __spm_send_cpu_wakeup_event() + +static int go_to_spm_before_wfi(int state_id, uint32_t ext_opand, + struct spm_lp_scen *spm_lp, + uint32_t resource_req) +{ + int ret = 0; + struct pwr_ctrl *pwrctrl; + + pwrctrl = spm_lp->pwrctrl; + +#if SPM_FW_NO_RESUME == 0 + ret = do_spm_init(pwrctrl); + + if (ret) + return ret; +#endif + __spm_set_power_control(pwrctrl, resource_req); + __spm_set_wakeup_event(pwrctrl); +#if defined(CONFIG_MTK_VCOREDVFS_SUPPORT) + __spm_sync_vcore_dvfs_power_control(pwrctrl, __spm_vcorefs.pwrctrl); +#endif + if (mt_spm_version == MT_SPM_VERSION_ES) + pwrctrl->pcm_flags |= (SPM_FLAG_ENABLE_MT8196_E1_WA | + SPM_FLAG_ENABLE_MT8196_EMI_E1_WA); + +#ifdef MTK_SPM_IVI_SUPPORT + pwrctrl->pcm_flags |= SPM_FLAG_ENABLE_MT8196_IVI; +#endif + + __spm_set_pcm_flags(pwrctrl); + +#ifdef HW_S1_DETECT + if (ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) + spm_hw_s1_state_monitor_resume(); +#endif + do_spm_run(pwrctrl); + return ret; +} + +static void go_to_spm_after_wfi(int state_id, uint32_t ext_opand, + struct spm_lp_scen *spm_lp, + struct wake_status **status) +{ + uint32_t ext_status = 0; + + spm_wakesta.tr.comm.resumetime = 0; + spm_wakesta.tr.comm.times_h = spm_wakesta.tr.comm.times_l = 0; + + if (ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) + spm_hw_s1_state_monitor_pause(&ext_status); + + __spm_ext_int_wakeup_req_clr(); + + __spm_get_wakeup_status(&spm_wakesta, ext_status); + + if (status) + *status = &spm_wakesta; + +#ifndef MT_SPM_COMMON_SODI_SUPPORT + __spm_clean_after_wakeup(); +#endif + spm_wake_reason = __spm_output_wake_reason(&spm_wakesta); +} + +int spm_conservation(int state_id, uint32_t ext_opand, + struct spm_lp_scen *spm_lp, uint32_t resource_req) +{ + uint32_t rc_state = resource_req; + + if (!spm_lp) + return -1; + + spm_lock_get(); + + /* Uart bk/rs is needed if infra off for legacy project + * leave code here for reference. + */ + if (ext_opand & MT_SPM_EX_OP_NOTIFY_INFRA_OFF) { +#ifndef MTK_PLAT_SPM_UART_UNSUPPORT + /* Notify UART to sleep */ + mt_uart_save(); +#endif + } + + if (!(ext_opand & MT_SPM_EX_OP_NON_GENERIC_RESOURCE_REQ)) { + /* Resource request */ + mt_lp_rq_get_status(PLAT_RQ_REQ_USAGE, + &generic_spm_resource_req); + rc_state |= generic_spm_resource_req.val; + } + go_to_spm_before_wfi(state_id, ext_opand, spm_lp, rc_state); + + spm_lock_release(); + + return 0; +} + +void spm_conservation_finish(int state_id, uint32_t ext_opand, + struct spm_lp_scen *spm_lp, + struct wake_status **status) +{ + /* Uart bk/rs is needed if infra off for legacy project + * leave code here for reference. + */ + if (ext_opand & MT_SPM_EX_OP_NOTIFY_INFRA_OFF) { +#ifndef MTK_PLAT_SPM_UART_UNSUPPORT + /* Notify UART to wakeup */ + mt_uart_restore(); +#endif + } + + spm_lock_get(); + go_to_spm_after_wfi(state_id, ext_opand, spm_lp, status); +#ifdef MT_SPM_COMMON_SODI_SUPPORT + /* Restore common sodi mask and resource req setting */ + mt_spm_set_common_sodi_pwrctr(); + mt_spm_set_common_sodi_pcm_flags(); +#endif + spm_lock_release(); +} + +int spm_conservation_get_result(struct wake_status **res) +{ + if (!res) + return -1; + *res = &spm_wakesta; + return 0; +} diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm_conservation.h b/plat/mediatek/drivers/spm/mt8196/mt_spm_conservation.h new file mode 100644 index 000000000..692180a58 --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/mt_spm_conservation.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_CONSERVATION_H +#define MT_SPM_CONSERVATION_H + +#include <mt_spm.h> +#include <mt_spm_internal.h> + +int spm_conservation(int state_id, uint32_t ext_opand, + struct spm_lp_scen *spm_lp, + uint32_t resource_req); + +void spm_conservation_finish(int state_id, uint32_t ext_opand, + struct spm_lp_scen *spm_lp, + struct wake_status **status); + +int spm_conservation_get_result(struct wake_status **res); + +int spm_conservation_fw_run(uint32_t first, void *pwrctrl); + +int spm_conservation_wakeup_obs(int IsSet, int cat, + uint32_t wake_src_bits); + +void mt_uart_save(void); +void mt_uart_restore(void); +#endif /* MT_SPM_CONSERVATION_H */ diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm_internal.c b/plat/mediatek/drivers/spm/mt8196/mt_spm_internal.c new file mode 100644 index 000000000..355c49262 --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/mt_spm_internal.c @@ -0,0 +1,825 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> + +#include <common/debug.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> +#include <platform_def.h> + +#include <drivers/spm/mt_spm_resource_req.h> +#include <mt_plat_spm_setting.h> +#include <mt_spm.h> +#include <mt_spm_internal.h> +#include <mt_spm_reg.h> +#include <pmic_wrap/inc/mt_spm_pmic_wrap.h> + +/************************************** + * Define and Declare + **************************************/ +#define SPM_INIT_DONE_US 20 /* Simulation result */ + +wake_reason_t __spm_output_wake_reason(const struct wake_status *wakesta) +{ + uint32_t i; + wake_reason_t wr = WR_UNKNOWN; + + if (!wakesta) + return WR_UNKNOWN; + + if (wakesta->is_abort) { + INFO("SPM EARLY WAKE r13 = 0x%x, ", wakesta->tr.comm.r13); +#ifndef MTK_PLAT_SPM_PMIC_WRAP_DUMP_UNSUPPORT + mt_spm_dump_pmic_warp_reg(); +#endif + } + + if (wakesta->tr.comm.r12 & R12_PCM_TIMER_B) { + + if (wakesta->wake_misc & WAKE_MISC_PCM_TIMER_EVENT) + wr = WR_PCM_TIMER; + } + + for (i = 2; i < 32; i++) { + if (wakesta->tr.comm.r12 & (1U << i)) + wr = WR_WAKE_SRC; + } + + return wr; +} + +void __spm_init_pcm_register(void) +{ + /* Disable r0 and r7 to control power */ + mmio_write_32(PCM_PWR_IO_EN, 0); +} + +void __spm_set_power_control(const struct pwr_ctrl *pwrctrl, + uint32_t resource_usage) +{ + /* SPM_SRC_REQ */ + mmio_write_32(SPM_SRC_REQ, + ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 0) | + (((pwrctrl->reg_spm_apsrc_req | + !!(resource_usage & MT_SPM_DRAM_S0)) & 0x1) << 1) | + (((pwrctrl->reg_spm_ddren_req | + !!(resource_usage & MT_SPM_DRAM_S1)) & 0x1) << 2) | + ((pwrctrl->reg_spm_dvfs_req & 0x1) << 3) | + (((pwrctrl->reg_spm_emi_req | + !!(resource_usage & MT_SPM_EMI)) & 0x1) << 4) | + (((pwrctrl->reg_spm_f26m_req | + !!(resource_usage & (MT_SPM_26M | + MT_SPM_XO_FPM))) & 0x1) << 5) | + (((pwrctrl->reg_spm_infra_req | + !!(resource_usage & MT_SPM_INFRA)) & 0x1) << 6) | + (((pwrctrl->reg_spm_pmic_req | + !!(resource_usage & MT_SPM_PMIC)) & 0x1) << 7) | + (((u32)pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 8) | + (((u32)pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 9) | + (((u32)pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 10) | + ((((u32)pwrctrl->reg_spm_vcore_req | + !!(resource_usage & MT_SPM_VCORE)) & 0x1) << 11) | + ((((u32)pwrctrl->reg_spm_vrf18_req | + !!(resource_usage & MT_SPM_SYSPLL)) & 0x1) << 12) | + (((u32)pwrctrl->adsp_mailbox_state & 0x1) << 16) | + (((u32)pwrctrl->apsrc_state & 0x1) << 17) | + (((u32)pwrctrl->ddren_state & 0x1) << 18) | + (((u32)pwrctrl->dvfs_state & 0x1) << 19) | + (((u32)pwrctrl->emi_state & 0x1) << 20) | + (((u32)pwrctrl->f26m_state & 0x1) << 21) | + (((u32)pwrctrl->infra_state & 0x1) << 22) | + (((u32)pwrctrl->pmic_state & 0x1) << 23) | + (((u32)pwrctrl->scp_mailbox_state & 0x1) << 24) | + (((u32)pwrctrl->sspm_mailbox_state & 0x1) << 25) | + (((u32)pwrctrl->sw_mailbox_state & 0x1) << 26) | + (((u32)pwrctrl->vcore_state & 0x1) << 27) | + (((u32)pwrctrl->vrf18_state & 0x1) << 28)); + + /* SPM_SRC_MASK_0 */ + mmio_write_32(SPM_SRC_MASK_0, + (((u32)pwrctrl->reg_apifr_apsrc_rmb & 0x1) << 0) | + (((u32)pwrctrl->reg_apifr_ddren_rmb & 0x1) << 1) | + (((u32)pwrctrl->reg_apifr_emi_rmb & 0x1) << 2) | + (((u32)pwrctrl->reg_apifr_infra_rmb & 0x1) << 3) | + (((u32)pwrctrl->reg_apifr_pmic_rmb & 0x1) << 4) | + (((u32)pwrctrl->reg_apifr_srcclkena_mb & 0x1) << 5) | + (((u32)pwrctrl->reg_apifr_vcore_rmb & 0x1) << 6) | + (((u32)pwrctrl->reg_apifr_vrf18_rmb & 0x1) << 7) | + (((u32)pwrctrl->reg_apu_apsrc_rmb & 0x1) << 8) | + (((u32)pwrctrl->reg_apu_ddren_rmb & 0x1) << 9) | + (((u32)pwrctrl->reg_apu_emi_rmb & 0x1) << 10) | + (((u32)pwrctrl->reg_apu_infra_rmb & 0x1) << 11) | + (((u32)pwrctrl->reg_apu_pmic_rmb & 0x1) << 12) | + (((u32)pwrctrl->reg_apu_srcclkena_mb & 0x1) << 13) | + (((u32)pwrctrl->reg_apu_vcore_rmb & 0x1) << 14) | + (((u32)pwrctrl->reg_apu_vrf18_rmb & 0x1) << 15) | + (((u32)pwrctrl->reg_audio_apsrc_rmb & 0x1) << 16) | + (((u32)pwrctrl->reg_audio_ddren_rmb & 0x1) << 17) | + (((u32)pwrctrl->reg_audio_emi_rmb & 0x1) << 18) | + (((u32)pwrctrl->reg_audio_infra_rmb & 0x1) << 19) | + (((u32)pwrctrl->reg_audio_pmic_rmb & 0x1) << 20) | + (((u32)pwrctrl->reg_audio_srcclkena_mb & 0x1) << 21) | + (((u32)pwrctrl->reg_audio_vcore_rmb & 0x1) << 22) | + (((u32)pwrctrl->reg_audio_vrf18_rmb & 0x1) << 23)); + + /* SPM_SRC_MASK_1 */ + mmio_write_32(SPM_SRC_MASK_1, + (((u32)pwrctrl->reg_audio_dsp_apsrc_rmb & 0x1) << 0) | + (((u32)pwrctrl->reg_audio_dsp_ddren_rmb & 0x1) << 1) | + (((u32)pwrctrl->reg_audio_dsp_emi_rmb & 0x1) << 2) | + (((u32)pwrctrl->reg_audio_dsp_infra_rmb & 0x1) << 3) | + (((u32)pwrctrl->reg_audio_dsp_pmic_rmb & 0x1) << 4) | + (((u32)pwrctrl->reg_audio_dsp_srcclkena_mb & 0x1) << 5) | + (((u32)pwrctrl->reg_audio_dsp_vcore_rmb & 0x1) << 6) | + (((u32)pwrctrl->reg_audio_dsp_vrf18_rmb & 0x1) << 7) | + (((u32)pwrctrl->reg_cam_apsrc_rmb & 0x1) << 8) | + (((u32)pwrctrl->reg_cam_ddren_rmb & 0x1) << 9) | + (((u32)pwrctrl->reg_cam_emi_rmb & 0x1) << 10) | + (((u32)pwrctrl->reg_cam_infra_rmb & 0x1) << 11) | + (((u32)pwrctrl->reg_cam_pmic_rmb & 0x1) << 12) | + (((u32)pwrctrl->reg_cam_srcclkena_mb & 0x1) << 13) | + (((u32)pwrctrl->reg_cam_vrf18_rmb & 0x1) << 14) | + (((u32)pwrctrl->reg_ccif_apsrc_rmb & 0xfff) << 15)); + + /* SPM_SRC_MASK_2 */ + mmio_write_32(SPM_SRC_MASK_2, + (((u32)pwrctrl->reg_ccif_emi_rmb & 0xfff) << 0) | + (((u32)pwrctrl->reg_ccif_infra_rmb & 0xfff) << 12)); + + /* SPM_SRC_MASK_3 */ + mmio_write_32(SPM_SRC_MASK_3, + (((u32)pwrctrl->reg_ccif_pmic_rmb & 0xfff) << 0) | + (((u32)pwrctrl->reg_ccif_srcclkena_mb & 0xfff) << 12)); + + /* SPM_SRC_MASK_4 */ + mmio_write_32(SPM_SRC_MASK_4, + (((u32)pwrctrl->reg_ccif_vcore_rmb & 0xfff) << 0) | + (((u32)pwrctrl->reg_ccif_vrf18_rmb & 0xfff) << 12) | + (((u32)pwrctrl->reg_ccu_apsrc_rmb & 0x1) << 24) | + (((u32)pwrctrl->reg_ccu_ddren_rmb & 0x1) << 25) | + (((u32)pwrctrl->reg_ccu_emi_rmb & 0x1) << 26) | + (((u32)pwrctrl->reg_ccu_infra_rmb & 0x1) << 27) | + (((u32)pwrctrl->reg_ccu_pmic_rmb & 0x1) << 28) | + (((u32)pwrctrl->reg_ccu_srcclkena_mb & 0x1) << 29) | + (((u32)pwrctrl->reg_ccu_vrf18_rmb & 0x1) << 30) | + (((u32)pwrctrl->reg_cg_check_apsrc_rmb & 0x1) << 31)); + + /* SPM_SRC_MASK_5 */ + mmio_write_32(SPM_SRC_MASK_5, + (((u32)pwrctrl->reg_cg_check_ddren_rmb & 0x1) << 0) | + (((u32)pwrctrl->reg_cg_check_emi_rmb & 0x1) << 1) | + (((u32)pwrctrl->reg_cg_check_infra_rmb & 0x1) << 2) | + (((u32)pwrctrl->reg_cg_check_pmic_rmb & 0x1) << 3) | + (((u32)pwrctrl->reg_cg_check_srcclkena_mb & 0x1) << 4) | + (((u32)pwrctrl->reg_cg_check_vcore_rmb & 0x1) << 5) | + (((u32)pwrctrl->reg_cg_check_vrf18_rmb & 0x1) << 6) | + (((u32)pwrctrl->reg_cksys_apsrc_rmb & 0x1) << 7) | + (((u32)pwrctrl->reg_cksys_ddren_rmb & 0x1) << 8) | + (((u32)pwrctrl->reg_cksys_emi_rmb & 0x1) << 9) | + (((u32)pwrctrl->reg_cksys_infra_rmb & 0x1) << 10) | + (((u32)pwrctrl->reg_cksys_pmic_rmb & 0x1) << 11) | + (((u32)pwrctrl->reg_cksys_srcclkena_mb & 0x1) << 12) | + (((u32)pwrctrl->reg_cksys_vcore_rmb & 0x1) << 13) | + (((u32)pwrctrl->reg_cksys_vrf18_rmb & 0x1) << 14) | + (((u32)pwrctrl->reg_cksys_1_apsrc_rmb & 0x1) << 15) | + (((u32)pwrctrl->reg_cksys_1_ddren_rmb & 0x1) << 16) | + (((u32)pwrctrl->reg_cksys_1_emi_rmb & 0x1) << 17) | + (((u32)pwrctrl->reg_cksys_1_infra_rmb & 0x1) << 18) | + (((u32)pwrctrl->reg_cksys_1_pmic_rmb & 0x1) << 19) | + (((u32)pwrctrl->reg_cksys_1_srcclkena_mb & 0x1) << 20) | + (((u32)pwrctrl->reg_cksys_1_vcore_rmb & 0x1) << 21) | + (((u32)pwrctrl->reg_cksys_1_vrf18_rmb & 0x1) << 22)); + + /* SPM_SRC_MASK_6 */ + mmio_write_32(SPM_SRC_MASK_6, + (((u32)pwrctrl->reg_cksys_2_apsrc_rmb & 0x1) << 0) | + (((u32)pwrctrl->reg_cksys_2_ddren_rmb & 0x1) << 1) | + (((u32)pwrctrl->reg_cksys_2_emi_rmb & 0x1) << 2) | + (((u32)pwrctrl->reg_cksys_2_infra_rmb & 0x1) << 3) | + (((u32)pwrctrl->reg_cksys_2_pmic_rmb & 0x1) << 4) | + (((u32)pwrctrl->reg_cksys_2_srcclkena_mb & 0x1) << 5) | + (((u32)pwrctrl->reg_cksys_2_vcore_rmb & 0x1) << 6) | + (((u32)pwrctrl->reg_cksys_2_vrf18_rmb & 0x1) << 7) | + (((u32)pwrctrl->reg_conn_apsrc_rmb & 0x1) << 8) | + (((u32)pwrctrl->reg_conn_ddren_rmb & 0x1) << 9) | + (((u32)pwrctrl->reg_conn_emi_rmb & 0x1) << 10) | + (((u32)pwrctrl->reg_conn_infra_rmb & 0x1) << 11) | + (((u32)pwrctrl->reg_conn_pmic_rmb & 0x1) << 12) | + (((u32)pwrctrl->reg_conn_srcclkena_mb & 0x1) << 13) | + (((u32)pwrctrl->reg_conn_srcclkenb_mb & 0x1) << 14) | + (((u32)pwrctrl->reg_conn_vcore_rmb & 0x1) << 15) | + (((u32)pwrctrl->reg_conn_vrf18_rmb & 0x1) << 16) | + (((u32)pwrctrl->reg_corecfg_apsrc_rmb & 0x1) << 17) | + (((u32)pwrctrl->reg_corecfg_ddren_rmb & 0x1) << 18) | + (((u32)pwrctrl->reg_corecfg_emi_rmb & 0x1) << 19) | + (((u32)pwrctrl->reg_corecfg_infra_rmb & 0x1) << 20) | + (((u32)pwrctrl->reg_corecfg_pmic_rmb & 0x1) << 21) | + (((u32)pwrctrl->reg_corecfg_srcclkena_mb & 0x1) << 22) | + (((u32)pwrctrl->reg_corecfg_vcore_rmb & 0x1) << 23) | + (((u32)pwrctrl->reg_corecfg_vrf18_rmb & 0x1) << 24)); + + /* SPM_SRC_MASK_7 */ + mmio_write_32(SPM_SRC_MASK_7, + (((u32)pwrctrl->reg_cpueb_apsrc_rmb & 0x1) << 0) | + (((u32)pwrctrl->reg_cpueb_ddren_rmb & 0x1) << 1) | + (((u32)pwrctrl->reg_cpueb_emi_rmb & 0x1) << 2) | + (((u32)pwrctrl->reg_cpueb_infra_rmb & 0x1) << 3) | + (((u32)pwrctrl->reg_cpueb_pmic_rmb & 0x1) << 4) | + (((u32)pwrctrl->reg_cpueb_srcclkena_mb & 0x1) << 5) | + (((u32)pwrctrl->reg_cpueb_vcore_rmb & 0x1) << 6) | + (((u32)pwrctrl->reg_cpueb_vrf18_rmb & 0x1) << 7) | + (((u32)pwrctrl->reg_disp0_apsrc_rmb & 0x1) << 8) | + (((u32)pwrctrl->reg_disp0_ddren_rmb & 0x1) << 9) | + (((u32)pwrctrl->reg_disp0_emi_rmb & 0x1) << 10) | + (((u32)pwrctrl->reg_disp0_infra_rmb & 0x1) << 11) | + (((u32)pwrctrl->reg_disp0_pmic_rmb & 0x1) << 12) | + (((u32)pwrctrl->reg_disp0_srcclkena_mb & 0x1) << 13) | + (((u32)pwrctrl->reg_disp0_vrf18_rmb & 0x1) << 14) | + (((u32)pwrctrl->reg_disp1_apsrc_rmb & 0x1) << 15) | + (((u32)pwrctrl->reg_disp1_ddren_rmb & 0x1) << 16) | + (((u32)pwrctrl->reg_disp1_emi_rmb & 0x1) << 17) | + (((u32)pwrctrl->reg_disp1_infra_rmb & 0x1) << 18) | + (((u32)pwrctrl->reg_disp1_pmic_rmb & 0x1) << 19) | + (((u32)pwrctrl->reg_disp1_srcclkena_mb & 0x1) << 20) | + (((u32)pwrctrl->reg_disp1_vrf18_rmb & 0x1) << 21) | + (((u32)pwrctrl->reg_dpm_apsrc_rmb & 0xf) << 22) | + (((u32)pwrctrl->reg_dpm_ddren_rmb & 0xf) << 26)); + + /* SPM_SRC_MASK_8 */ + mmio_write_32(SPM_SRC_MASK_8, + (((u32)pwrctrl->reg_dpm_emi_rmb & 0xf) << 0) | + (((u32)pwrctrl->reg_dpm_infra_rmb & 0xf) << 4) | + (((u32)pwrctrl->reg_dpm_pmic_rmb & 0xf) << 8) | + (((u32)pwrctrl->reg_dpm_srcclkena_mb & 0xf) << 12) | + (((u32)pwrctrl->reg_dpm_vcore_rmb & 0xf) << 16) | + (((u32)pwrctrl->reg_dpm_vrf18_rmb & 0xf) << 20) | + (((u32)pwrctrl->reg_dpmaif_apsrc_rmb & 0x1) << 24) | + (((u32)pwrctrl->reg_dpmaif_ddren_rmb & 0x1) << 25) | + (((u32)pwrctrl->reg_dpmaif_emi_rmb & 0x1) << 26) | + (((u32)pwrctrl->reg_dpmaif_infra_rmb & 0x1) << 27) | + (((u32)pwrctrl->reg_dpmaif_pmic_rmb & 0x1) << 28) | + (((u32)pwrctrl->reg_dpmaif_srcclkena_mb & 0x1) << 29) | + (((u32)pwrctrl->reg_dpmaif_vcore_rmb & 0x1) << 30) | + (((u32)pwrctrl->reg_dpmaif_vrf18_rmb & 0x1) << 31)); + + /* SPM_SRC_MASK_9 */ + mmio_write_32(SPM_SRC_MASK_9, + (((u32)pwrctrl->reg_dvfsrc_level_rmb & 0x1) << 0) | + (((u32)pwrctrl->reg_emisys_apsrc_rmb & 0x1) << 1) | + (((u32)pwrctrl->reg_emisys_ddren_rmb & 0x1) << 2) | + (((u32)pwrctrl->reg_emisys_emi_rmb & 0x1) << 3) | + (((u32)pwrctrl->reg_emisys_infra_rmb & 0x1) << 4) | + (((u32)pwrctrl->reg_emisys_pmic_rmb & 0x1) << 5) | + (((u32)pwrctrl->reg_emisys_srcclkena_mb & 0x1) << 6) | + (((u32)pwrctrl->reg_emisys_vcore_rmb & 0x1) << 7) | + (((u32)pwrctrl->reg_emisys_vrf18_rmb & 0x1) << 8) | + (((u32)pwrctrl->reg_gce_apsrc_rmb & 0x1) << 9) | + (((u32)pwrctrl->reg_gce_ddren_rmb & 0x1) << 10) | + (((u32)pwrctrl->reg_gce_emi_rmb & 0x1) << 11) | + (((u32)pwrctrl->reg_gce_infra_rmb & 0x1) << 12) | + (((u32)pwrctrl->reg_gce_pmic_rmb & 0x1) << 13) | + (((u32)pwrctrl->reg_gce_srcclkena_mb & 0x1) << 14) | + (((u32)pwrctrl->reg_gce_vcore_rmb & 0x1) << 15) | + (((u32)pwrctrl->reg_gce_vrf18_rmb & 0x1) << 16) | + (((u32)pwrctrl->reg_gpueb_apsrc_rmb & 0x1) << 17) | + (((u32)pwrctrl->reg_gpueb_ddren_rmb & 0x1) << 18) | + (((u32)pwrctrl->reg_gpueb_emi_rmb & 0x1) << 19) | + (((u32)pwrctrl->reg_gpueb_infra_rmb & 0x1) << 20) | + (((u32)pwrctrl->reg_gpueb_pmic_rmb & 0x1) << 21) | + (((u32)pwrctrl->reg_gpueb_srcclkena_mb & 0x1) << 22) | + (((u32)pwrctrl->reg_gpueb_vcore_rmb & 0x1) << 23) | + (((u32)pwrctrl->reg_gpueb_vrf18_rmb & 0x1) << 24) | + (((u32)pwrctrl->reg_hwccf_apsrc_rmb & 0x1) << 25) | + (((u32)pwrctrl->reg_hwccf_ddren_rmb & 0x1) << 26) | + (((u32)pwrctrl->reg_hwccf_emi_rmb & 0x1) << 27) | + (((u32)pwrctrl->reg_hwccf_infra_rmb & 0x1) << 28) | + (((u32)pwrctrl->reg_hwccf_pmic_rmb & 0x1) << 29) | + (((u32)pwrctrl->reg_hwccf_srcclkena_mb & 0x1) << 30) | + (((u32)pwrctrl->reg_hwccf_vcore_rmb & 0x1) << 31)); + + /* SPM_SRC_MASK_10 */ + mmio_write_32(SPM_SRC_MASK_10, + (((u32)pwrctrl->reg_hwccf_vrf18_rmb & 0x1) << 0) | + (((u32)pwrctrl->reg_img_apsrc_rmb & 0x1) << 1) | + (((u32)pwrctrl->reg_img_ddren_rmb & 0x1) << 2) | + (((u32)pwrctrl->reg_img_emi_rmb & 0x1) << 3) | + (((u32)pwrctrl->reg_img_infra_rmb & 0x1) << 4) | + (((u32)pwrctrl->reg_img_pmic_rmb & 0x1) << 5) | + (((u32)pwrctrl->reg_img_srcclkena_mb & 0x1) << 6) | + (((u32)pwrctrl->reg_img_vrf18_rmb & 0x1) << 7) | + (((u32)pwrctrl->reg_infrasys_apsrc_rmb & 0x1) << 8) | + (((u32)pwrctrl->reg_infrasys_ddren_rmb & 0x1) << 9) | + (((u32)pwrctrl->reg_infrasys_emi_rmb & 0x1) << 10) | + (((u32)pwrctrl->reg_infrasys_infra_rmb & 0x1) << 11) | + (((u32)pwrctrl->reg_infrasys_pmic_rmb & 0x1) << 12) | + (((u32)pwrctrl->reg_infrasys_srcclkena_mb & 0x1) << 13) | + (((u32)pwrctrl->reg_infrasys_vcore_rmb & 0x1) << 14) | + (((u32)pwrctrl->reg_infrasys_vrf18_rmb & 0x1) << 15) | + (((u32)pwrctrl->reg_ipic_infra_rmb & 0x1) << 16) | + (((u32)pwrctrl->reg_ipic_vrf18_rmb & 0x1) << 17) | + (((u32)pwrctrl->reg_mcu_apsrc_rmb & 0x1) << 18) | + (((u32)pwrctrl->reg_mcu_ddren_rmb & 0x1) << 19) | + (((u32)pwrctrl->reg_mcu_emi_rmb & 0x1) << 20) | + (((u32)pwrctrl->reg_mcu_infra_rmb & 0x1) << 21) | + (((u32)pwrctrl->reg_mcu_pmic_rmb & 0x1) << 22) | + (((u32)pwrctrl->reg_mcu_srcclkena_mb & 0x1) << 23) | + (((u32)pwrctrl->reg_mcu_vcore_rmb & 0x1) << 24) | + (((u32)pwrctrl->reg_mcu_vrf18_rmb & 0x1) << 25) | + (((u32)pwrctrl->reg_md_apsrc_rmb & 0x1) << 26) | + (((u32)pwrctrl->reg_md_ddren_rmb & 0x1) << 27) | + (((u32)pwrctrl->reg_md_emi_rmb & 0x1) << 28) | + (((u32)pwrctrl->reg_md_infra_rmb & 0x1) << 29) | + (((u32)pwrctrl->reg_md_pmic_rmb & 0x1) << 30) | + (((u32)pwrctrl->reg_md_srcclkena_mb & 0x1) << 31)); + + /* SPM_SRC_MASK_11 */ + mmio_write_32(SPM_SRC_MASK_11, + (((u32)pwrctrl->reg_md_srcclkena1_mb & 0x1) << 0) | + (((u32)pwrctrl->reg_md_vcore_rmb & 0x1) << 1) | + (((u32)pwrctrl->reg_md_vrf18_rmb & 0x1) << 2) | + (((u32)pwrctrl->reg_mm_proc_apsrc_rmb & 0x1) << 3) | + (((u32)pwrctrl->reg_mm_proc_ddren_rmb & 0x1) << 4) | + (((u32)pwrctrl->reg_mm_proc_emi_rmb & 0x1) << 5) | + (((u32)pwrctrl->reg_mm_proc_infra_rmb & 0x1) << 6) | + (((u32)pwrctrl->reg_mm_proc_pmic_rmb & 0x1) << 7) | + (((u32)pwrctrl->reg_mm_proc_srcclkena_mb & 0x1) << 8) | + (((u32)pwrctrl->reg_mm_proc_vcore_rmb & 0x1) << 9) | + (((u32)pwrctrl->reg_mm_proc_vrf18_rmb & 0x1) << 10) | + (((u32)pwrctrl->reg_mml0_apsrc_rmb & 0x1) << 11) | + (((u32)pwrctrl->reg_mml0_ddren_rmb & 0x1) << 12) | + (((u32)pwrctrl->reg_mml0_emi_rmb & 0x1) << 13) | + (((u32)pwrctrl->reg_mml0_infra_rmb & 0x1) << 14) | + (((u32)pwrctrl->reg_mml0_pmic_rmb & 0x1) << 15) | + (((u32)pwrctrl->reg_mml0_srcclkena_mb & 0x1) << 16) | + (((u32)pwrctrl->reg_mml0_vrf18_rmb & 0x1) << 17) | + (((u32)pwrctrl->reg_mml1_apsrc_rmb & 0x1) << 18) | + (((u32)pwrctrl->reg_mml1_ddren_rmb & 0x1) << 19) | + (((u32)pwrctrl->reg_mml1_emi_rmb & 0x1) << 20) | + (((u32)pwrctrl->reg_mml1_infra_rmb & 0x1) << 21) | + (((u32)pwrctrl->reg_mml1_pmic_rmb & 0x1) << 22) | + (((u32)pwrctrl->reg_mml1_srcclkena_mb & 0x1) << 23) | + (((u32)pwrctrl->reg_mml1_vrf18_rmb & 0x1) << 24) | + (((u32)pwrctrl->reg_ovl0_apsrc_rmb & 0x1) << 25) | + (((u32)pwrctrl->reg_ovl0_ddren_rmb & 0x1) << 26) | + (((u32)pwrctrl->reg_ovl0_emi_rmb & 0x1) << 27) | + (((u32)pwrctrl->reg_ovl0_infra_rmb & 0x1) << 28) | + (((u32)pwrctrl->reg_ovl0_pmic_rmb & 0x1) << 29) | + (((u32)pwrctrl->reg_ovl0_srcclkena_mb & 0x1) << 30) | + (((u32)pwrctrl->reg_ovl0_vrf18_rmb & 0x1) << 31)); + + mmio_write_32(SPM_SRC_MASK_12, + (((u32)pwrctrl->reg_ovl1_apsrc_rmb & 0x1) << 0) | + (((u32)pwrctrl->reg_ovl1_ddren_rmb & 0x1) << 1) | + (((u32)pwrctrl->reg_ovl1_emi_rmb & 0x1) << 2) | + (((u32)pwrctrl->reg_ovl1_infra_rmb & 0x1) << 3) | + (((u32)pwrctrl->reg_ovl1_pmic_rmb & 0x1) << 4) | + (((u32)pwrctrl->reg_ovl1_srcclkena_mb & 0x1) << 5) | + (((u32)pwrctrl->reg_ovl1_vrf18_rmb & 0x1) << 6) | + (((u32)pwrctrl->reg_pcie0_apsrc_rmb & 0x1) << 7) | + (((u32)pwrctrl->reg_pcie0_ddren_rmb & 0x1) << 8) | + (((u32)pwrctrl->reg_pcie0_emi_rmb & 0x1) << 9) | + (((u32)pwrctrl->reg_pcie0_infra_rmb & 0x1) << 10) | + (((u32)pwrctrl->reg_pcie0_pmic_rmb & 0x1) << 11) | + (((u32)pwrctrl->reg_pcie0_srcclkena_mb & 0x1) << 12) | + (((u32)pwrctrl->reg_pcie0_vcore_rmb & 0x1) << 13) | + (((u32)pwrctrl->reg_pcie0_vrf18_rmb & 0x1) << 14) | + (((u32)pwrctrl->reg_pcie1_apsrc_rmb & 0x1) << 15) | + (((u32)pwrctrl->reg_pcie1_ddren_rmb & 0x1) << 16) | + (((u32)pwrctrl->reg_pcie1_emi_rmb & 0x1) << 17) | + (((u32)pwrctrl->reg_pcie1_infra_rmb & 0x1) << 18) | + (((u32)pwrctrl->reg_pcie1_pmic_rmb & 0x1) << 19) | + (((u32)pwrctrl->reg_pcie1_srcclkena_mb & 0x1) << 20) | + (((u32)pwrctrl->reg_pcie1_vcore_rmb & 0x1) << 21) | + (((u32)pwrctrl->reg_pcie1_vrf18_rmb & 0x1) << 22) | + (((u32)pwrctrl->reg_perisys_apsrc_rmb & 0x1) << 23) | + (((u32)pwrctrl->reg_perisys_ddren_rmb & 0x1) << 24) | + (((u32)pwrctrl->reg_perisys_emi_rmb & 0x1) << 25) | + (((u32)pwrctrl->reg_perisys_infra_rmb & 0x1) << 26) | + (((u32)pwrctrl->reg_perisys_pmic_rmb & 0x1) << 27) | + (((u32)pwrctrl->reg_perisys_srcclkena_mb & 0x1) << 28) | + (((u32)pwrctrl->reg_perisys_vcore_rmb & 0x1) << 29) | + (((u32)pwrctrl->reg_perisys_vrf18_rmb & 0x1) << 30) | + (((u32)pwrctrl->reg_pmsr_apsrc_rmb & 0x1) << 31)); + + /* SPM_SRC_MASK_13 */ + mmio_write_32(SPM_SRC_MASK_13, + (((u32)pwrctrl->reg_pmsr_ddren_rmb & 0x1) << 0) | + (((u32)pwrctrl->reg_pmsr_emi_rmb & 0x1) << 1) | + (((u32)pwrctrl->reg_pmsr_infra_rmb & 0x1) << 2) | + (((u32)pwrctrl->reg_pmsr_pmic_rmb & 0x1) << 3) | + (((u32)pwrctrl->reg_pmsr_srcclkena_mb & 0x1) << 4) | + (((u32)pwrctrl->reg_pmsr_vcore_rmb & 0x1) << 5) | + (((u32)pwrctrl->reg_pmsr_vrf18_rmb & 0x1) << 6) | + (((u32)pwrctrl->reg_scp_apsrc_rmb & 0x1) << 7) | + (((u32)pwrctrl->reg_scp_ddren_rmb & 0x1) << 8) | + (((u32)pwrctrl->reg_scp_emi_rmb & 0x1) << 9) | + (((u32)pwrctrl->reg_scp_infra_rmb & 0x1) << 10) | + (((u32)pwrctrl->reg_scp_pmic_rmb & 0x1) << 11) | + (((u32)pwrctrl->reg_scp_srcclkena_mb & 0x1) << 12) | + (((u32)pwrctrl->reg_scp_vcore_rmb & 0x1) << 13) | + (((u32)pwrctrl->reg_scp_vrf18_rmb & 0x1) << 14) | + (((u32)pwrctrl->reg_spu_hwr_apsrc_rmb & 0x1) << 15) | + (((u32)pwrctrl->reg_spu_hwr_ddren_rmb & 0x1) << 16) | + (((u32)pwrctrl->reg_spu_hwr_emi_rmb & 0x1) << 17) | + (((u32)pwrctrl->reg_spu_hwr_infra_rmb & 0x1) << 18) | + (((u32)pwrctrl->reg_spu_hwr_pmic_rmb & 0x1) << 19) | + (((u32)pwrctrl->reg_spu_hwr_srcclkena_mb & 0x1) << 20) | + (((u32)pwrctrl->reg_spu_hwr_vcore_rmb & 0x1) << 21) | + (((u32)pwrctrl->reg_spu_hwr_vrf18_rmb & 0x1) << 22) | + (((u32)pwrctrl->reg_spu_ise_apsrc_rmb & 0x1) << 23) | + (((u32)pwrctrl->reg_spu_ise_ddren_rmb & 0x1) << 24) | + (((u32)pwrctrl->reg_spu_ise_emi_rmb & 0x1) << 25) | + (((u32)pwrctrl->reg_spu_ise_infra_rmb & 0x1) << 26) | + (((u32)pwrctrl->reg_spu_ise_pmic_rmb & 0x1) << 27) | + (((u32)pwrctrl->reg_spu_ise_srcclkena_mb & 0x1) << 28) | + (((u32)pwrctrl->reg_spu_ise_vcore_rmb & 0x1) << 29) | + (((u32)pwrctrl->reg_spu_ise_vrf18_rmb & 0x1) << 30)); + + /* SPM_SRC_MASK_14 */ + mmio_write_32(SPM_SRC_MASK_14, + (((u32)pwrctrl->reg_srcclkeni_infra_rmb & 0x3) << 0) | + (((u32)pwrctrl->reg_srcclkeni_pmic_rmb & 0x3) << 2) | + (((u32)pwrctrl->reg_srcclkeni_srcclkena_mb & 0x3) << 4) | + (((u32)pwrctrl->reg_srcclkeni_vcore_rmb & 0x3) << 6) | + (((u32)pwrctrl->reg_sspm_apsrc_rmb & 0x1) << 8) | + (((u32)pwrctrl->reg_sspm_ddren_rmb & 0x1) << 9) | + (((u32)pwrctrl->reg_sspm_emi_rmb & 0x1) << 10) | + (((u32)pwrctrl->reg_sspm_infra_rmb & 0x1) << 11) | + (((u32)pwrctrl->reg_sspm_pmic_rmb & 0x1) << 12) | + (((u32)pwrctrl->reg_sspm_srcclkena_mb & 0x1) << 13) | + (((u32)pwrctrl->reg_sspm_vrf18_rmb & 0x1) << 14) | + (((u32)pwrctrl->reg_ssrsys_apsrc_rmb & 0x1) << 15) | + (((u32)pwrctrl->reg_ssrsys_ddren_rmb & 0x1) << 16) | + (((u32)pwrctrl->reg_ssrsys_emi_rmb & 0x1) << 17) | + (((u32)pwrctrl->reg_ssrsys_infra_rmb & 0x1) << 18) | + (((u32)pwrctrl->reg_ssrsys_pmic_rmb & 0x1) << 19) | + (((u32)pwrctrl->reg_ssrsys_srcclkena_mb & 0x1) << 20) | + (((u32)pwrctrl->reg_ssrsys_vcore_rmb & 0x1) << 21) | + (((u32)pwrctrl->reg_ssrsys_vrf18_rmb & 0x1) << 22) | + (((u32)pwrctrl->reg_ssusb_apsrc_rmb & 0x1) << 23) | + (((u32)pwrctrl->reg_ssusb_ddren_rmb & 0x1) << 24) | + (((u32)pwrctrl->reg_ssusb_emi_rmb & 0x1) << 25) | + (((u32)pwrctrl->reg_ssusb_infra_rmb & 0x1) << 26) | + (((u32)pwrctrl->reg_ssusb_pmic_rmb & 0x1) << 27) | + (((u32)pwrctrl->reg_ssusb_srcclkena_mb & 0x1) << 28) | + (((u32)pwrctrl->reg_ssusb_vcore_rmb & 0x1) << 29) | + (((u32)pwrctrl->reg_ssusb_vrf18_rmb & 0x1) << 30) | + (((u32)pwrctrl->reg_uart_hub_infra_rmb & 0x1) << 31)); + + /* SPM_SRC_MASK_15 */ + mmio_write_32(SPM_SRC_MASK_15, + (((u32)pwrctrl->reg_uart_hub_pmic_rmb & 0x1) << 0) | + (((u32)pwrctrl->reg_uart_hub_srcclkena_mb & 0x1) << 1) | + (((u32)pwrctrl->reg_uart_hub_vcore_rmb & 0x1) << 2) | + (((u32)pwrctrl->reg_uart_hub_vrf18_rmb & 0x1) << 3) | + (((u32)pwrctrl->reg_ufs_apsrc_rmb & 0x1) << 4) | + (((u32)pwrctrl->reg_ufs_ddren_rmb & 0x1) << 5) | + (((u32)pwrctrl->reg_ufs_emi_rmb & 0x1) << 6) | + (((u32)pwrctrl->reg_ufs_infra_rmb & 0x1) << 7) | + (((u32)pwrctrl->reg_ufs_pmic_rmb & 0x1) << 8) | + (((u32)pwrctrl->reg_ufs_srcclkena_mb & 0x1) << 9) | + (((u32)pwrctrl->reg_ufs_vcore_rmb & 0x1) << 10) | + (((u32)pwrctrl->reg_ufs_vrf18_rmb & 0x1) << 11) | + (((u32)pwrctrl->reg_vdec_apsrc_rmb & 0x1) << 12) | + (((u32)pwrctrl->reg_vdec_ddren_rmb & 0x1) << 13) | + (((u32)pwrctrl->reg_vdec_emi_rmb & 0x1) << 14) | + (((u32)pwrctrl->reg_vdec_infra_rmb & 0x1) << 15) | + (((u32)pwrctrl->reg_vdec_pmic_rmb & 0x1) << 16) | + (((u32)pwrctrl->reg_vdec_srcclkena_mb & 0x1) << 17) | + (((u32)pwrctrl->reg_vdec_vrf18_rmb & 0x1) << 18) | + (((u32)pwrctrl->reg_venc_apsrc_rmb & 0x1) << 19) | + (((u32)pwrctrl->reg_venc_ddren_rmb & 0x1) << 20) | + (((u32)pwrctrl->reg_venc_emi_rmb & 0x1) << 21) | + (((u32)pwrctrl->reg_venc_infra_rmb & 0x1) << 22) | + (((u32)pwrctrl->reg_venc_pmic_rmb & 0x1) << 23) | + (((u32)pwrctrl->reg_venc_srcclkena_mb & 0x1) << 24) | + (((u32)pwrctrl->reg_venc_vrf18_rmb & 0x1) << 25) | + (((u32)pwrctrl->reg_vlpcfg_apsrc_rmb & 0x1) << 26) | + (((u32)pwrctrl->reg_vlpcfg_ddren_rmb & 0x1) << 27) | + (((u32)pwrctrl->reg_vlpcfg_emi_rmb & 0x1) << 28) | + (((u32)pwrctrl->reg_vlpcfg_infra_rmb & 0x1) << 29) | + (((u32)pwrctrl->reg_vlpcfg_pmic_rmb & 0x1) << 30) | + (((u32)pwrctrl->reg_vlpcfg_srcclkena_mb & 0x1) << 31)); + + /* SPM_SRC_MASK_16 */ + mmio_write_32(SPM_SRC_MASK_16, + (((u32)pwrctrl->reg_vlpcfg_vcore_rmb & 0x1) << 0) | + (((u32)pwrctrl->reg_vlpcfg_vrf18_rmb & 0x1) << 1) | + (((u32)pwrctrl->reg_vlpcfg1_apsrc_rmb & 0x1) << 2) | + (((u32)pwrctrl->reg_vlpcfg1_ddren_rmb & 0x1) << 3) | + (((u32)pwrctrl->reg_vlpcfg1_emi_rmb & 0x1) << 4) | + (((u32)pwrctrl->reg_vlpcfg1_infra_rmb & 0x1) << 5) | + (((u32)pwrctrl->reg_vlpcfg1_pmic_rmb & 0x1) << 6) | + (((u32)pwrctrl->reg_vlpcfg1_srcclkena_mb & 0x1) << 7) | + (((u32)pwrctrl->reg_vlpcfg1_vcore_rmb & 0x1) << 8) | + (((u32)pwrctrl->reg_vlpcfg1_vrf18_rmb & 0x1) << 9)); + + /* SPM_SRC_MASK_17 */ + mmio_write_32(SPM_SRC_MASK_17, + (((u32)pwrctrl->reg_spm_sw_vcore_rmb & 0xffff) << 0) | + (((u32)pwrctrl->reg_spm_sw_pmic_rmb & 0xffff) << 16)); + + /* SPM_SRC_MASK_18 */ + mmio_write_32(SPM_SRC_MASK_18, + (((u32)pwrctrl->reg_spm_sw_srcclkena_mb & 0xffff) << 0)); + + /* SPM_EVENT_CON_MISC */ + mmio_write_32(SPM_EVENT_CON_MISC, + (((u32)pwrctrl->reg_srcclken_fast_resp & 0x1) << 0) | + (((u32)pwrctrl->reg_csyspwrup_ack_mask & 0x1) << 1)); + + /* SPM_WAKE_MASK*/ + mmio_write_32(SPM_WAKEUP_EVENT_MASK, + (((u32)pwrctrl->reg_wake_mask & 0xffffffff) << 0)); + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + mmio_write_32(SPM_WAKEUP_EVENT_EXT_MASK, + (((u32)pwrctrl->reg_ext_wake_mask & 0xffffffff) << 0)); +} + +#define CHECK_ONE 0xffffffff +#define CHECK_ZERO 0x0 +static int32_t __spm_check_ack(u32 reg, u32 mask, u32 check_en) +{ + u32 val; + + val = mmio_read_32(reg); + if ((val & mask) == (mask & check_en)) + return 0; + return -1; +} + +int32_t __spm_wait_spm_request_ack(u32 spm_resource_req, u32 timeout_us) +{ + u32 spm_ctrl0_mask, spm_ctrl1_mask; + int32_t ret, retry; + + if (spm_resource_req == 0) + return 0; + + spm_ctrl0_mask = 0; + spm_ctrl1_mask = 0; + + if (spm_resource_req & (MT_SPM_XO_FPM | MT_SPM_26M)) + spm_ctrl0_mask |= CTRL0_SC_MD26M_CK_OFF; + + if (spm_resource_req & MT_SPM_VCORE) + spm_ctrl1_mask |= CTRL1_SPM_VCORE_INTERNAL_ACK; + if (spm_resource_req & MT_SPM_PMIC) + spm_ctrl1_mask |= CTRL1_SPM_PMIC_INTERNAL_ACK; + if (spm_resource_req & MT_SPM_INFRA) + spm_ctrl1_mask |= CTRL1_SPM_INFRA_INTERNAL_ACK; + if (spm_resource_req & MT_SPM_SYSPLL) + spm_ctrl1_mask |= CTRL1_SPM_VRF18_INTERNAL_ACK; + if (spm_resource_req & MT_SPM_EMI) + spm_ctrl1_mask |= CTRL1_SPM_EMI_INTERNAL_ACK; + if (spm_resource_req & MT_SPM_DRAM_S0) + spm_ctrl1_mask |= CTRL1_SPM_APSRC_INTERNAL_ACK; + if (spm_resource_req & MT_SPM_DRAM_S1) + spm_ctrl1_mask |= CTRL1_SPM_DDREN_INTERNAL_ACK; + + retry = -1; + ret = 0; + + while (retry++ < timeout_us) { + udelay(1); + if (spm_ctrl0_mask != 0) { + ret = __spm_check_ack(MD32PCM_SCU_CTRL0, + spm_ctrl0_mask, + CHECK_ZERO); + if (ret) + continue; + } + if (spm_ctrl1_mask != 0) { + ret = __spm_check_ack(MD32PCM_SCU_CTRL1, + spm_ctrl1_mask, + CHECK_ONE); + if (ret) + continue; + } + break; + } + + return ret; +} + +void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl) +{ + u32 val, mask; + + /* Toggle event counter clear */ + mmio_write_32(SPM_EVENT_COUNTER_CLEAR, REG_SPM_EVENT_COUNTER_CLR_LSB); + /* Toggle for reset SYS TIMER start point */ + mmio_setbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB); + + if (pwrctrl->timer_val_cust == 0) + val = pwrctrl->timer_val ? pwrctrl->timer_val : PCM_TIMER_MAX; + else + val = pwrctrl->timer_val_cust; + + mmio_write_32(PCM_TIMER_VAL, val); + mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | REG_PCM_TIMER_EN_LSB); + + /* Unmask AP wakeup source */ + if (pwrctrl->wake_src_cust == 0) + mask = pwrctrl->wake_src; + else + mask = pwrctrl->wake_src_cust; + + if (pwrctrl->reg_csyspwrup_ack_mask) + mask &= ~R12_CSYSPWREQ_B; + mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~mask); + + /* Unmask SPM ISR (keep TWAM setting) */ + mmio_setbits_32(SPM_IRQ_MASK, ISRM_RET_IRQ_AUX); + + /* Toggle event counter clear */ + mmio_write_32(SPM_EVENT_COUNTER_CLEAR, 0); + /* Toggle for reset SYS TIMER start point */ + mmio_clrbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB); +} + +void __spm_set_fw_resume_option(struct pwr_ctrl *pwrctrl) +{ +#if SPM_FW_NO_RESUME + /* Do Nothing */ +#else + pwrctrl->pcm_flags1 |= SPM_FLAG1_DISABLE_NO_RESUME; +#endif +} + +void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl) +{ + /* Set PCM flags and data */ + if (pwrctrl->pcm_flags_cust_clr != 0) + pwrctrl->pcm_flags &= ~pwrctrl->pcm_flags_cust_clr; + if (pwrctrl->pcm_flags_cust_set != 0) + pwrctrl->pcm_flags |= pwrctrl->pcm_flags_cust_set; + if (pwrctrl->pcm_flags1_cust_clr != 0) + pwrctrl->pcm_flags1 &= ~pwrctrl->pcm_flags1_cust_clr; + if (pwrctrl->pcm_flags1_cust_set != 0) + pwrctrl->pcm_flags1 |= pwrctrl->pcm_flags1_cust_set; + + mmio_write_32(SPM_SW_FLAG_0, pwrctrl->pcm_flags); + + mmio_write_32(SPM_SW_FLAG_1, pwrctrl->pcm_flags1); + + mmio_write_32(SPM_SW_RSV_7, pwrctrl->pcm_flags); + + mmio_write_32(SPM_SW_RSV_8, pwrctrl->pcm_flags1); +} + +void __spm_kick_pcm_to_run(struct pwr_ctrl *pwrctrl) +{ + /* Waiting for loading SPMFW done*/ + while (mmio_read_32(MD32PCM_DMA0_RLCT) != 0x0) + ; + + __spm_set_pcm_flags(pwrctrl); + + udelay(SPM_INIT_DONE_US); +} + +void __spm_get_wakeup_status(struct wake_status *wakesta, + uint32_t ext_status) +{ + /* Get wakeup event */ + wakesta->tr.comm.r12 = mmio_read_32(SPM_BK_WAKE_EVENT); + wakesta->r12_ext = mmio_read_32(SPM_WAKEUP_EXT_STA); + wakesta->tr.comm.raw_sta = mmio_read_32(SPM_WAKEUP_STA); + wakesta->raw_ext_sta = mmio_read_32(SPM_WAKEUP_EXT_STA); + wakesta->md32pcm_wakeup_sta = mmio_read_32(MD32PCM_WAKEUP_STA); + wakesta->md32pcm_event_sta = mmio_read_32(MD32PCM_EVENT_STA); + wakesta->wake_misc = mmio_read_32(SPM_BK_WAKE_MISC); + + /* Get sleep time */ + wakesta->tr.comm.timer_out = mmio_read_32(SPM_BK_PCM_TIMER); + wakesta->tr.comm.r13 = mmio_read_32(MD32PCM_SCU_STA0); + wakesta->tr.comm.req_sta0 = mmio_read_32(SPM_REQ_STA_0); + wakesta->tr.comm.req_sta1 = mmio_read_32(SPM_REQ_STA_1); + wakesta->tr.comm.req_sta2 = mmio_read_32(SPM_REQ_STA_2); + wakesta->tr.comm.req_sta3 = mmio_read_32(SPM_REQ_STA_3); + wakesta->tr.comm.req_sta4 = mmio_read_32(SPM_REQ_STA_4); + wakesta->tr.comm.req_sta5 = mmio_read_32(SPM_REQ_STA_5); + wakesta->tr.comm.req_sta6 = mmio_read_32(SPM_REQ_STA_6); + wakesta->tr.comm.req_sta7 = mmio_read_32(SPM_REQ_STA_7); + wakesta->tr.comm.req_sta8 = mmio_read_32(SPM_REQ_STA_8); + wakesta->tr.comm.req_sta9 = mmio_read_32(SPM_REQ_STA_9); + wakesta->tr.comm.req_sta10 = mmio_read_32(SPM_REQ_STA_10); + wakesta->tr.comm.req_sta11 = mmio_read_32(SPM_REQ_STA_11); + wakesta->tr.comm.req_sta12 = mmio_read_32(SPM_REQ_STA_12); + wakesta->tr.comm.req_sta13 = mmio_read_32(SPM_REQ_STA_13); + wakesta->tr.comm.req_sta14 = mmio_read_32(SPM_REQ_STA_14); + wakesta->tr.comm.req_sta15 = mmio_read_32(SPM_REQ_STA_15); + wakesta->tr.comm.req_sta16 = mmio_read_32(SPM_REQ_STA_16); + + /* Get debug flag for PCM execution check */ + wakesta->tr.comm.debug_flag = mmio_read_32(PCM_WDT_LATCH_SPARE_0); + wakesta->tr.comm.debug_flag1 = mmio_read_32(PCM_WDT_LATCH_SPARE_1); + + /* Get backup SW flag status */ + wakesta->tr.comm.b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7); + wakesta->tr.comm.b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8); + + /* Get ISR status */ + wakesta->isr = mmio_read_32(SPM_IRQ_STA); + + /* Get SW flag status */ + wakesta->sw_flag0 = mmio_read_32(SPM_SW_FLAG_0); + wakesta->sw_flag1 = mmio_read_32(SPM_SW_FLAG_1); + + /* Check abort */ + wakesta->is_abort = wakesta->tr.comm.debug_flag1 & DEBUG_ABORT_MASK_1; +} + +void __spm_clean_after_wakeup(void) +{ + /* + * Copy SPM_WAKEUP_STA to SPM_BK_WAKE_EVENT + * before clear SPM_WAKEUP_STA + * + * CPU dormant driver @kernel will copy edge-trig IRQ pending + * (recorded @SPM_BK_WAKE_EVENT) to GIC + */ + mmio_write_32(SPM_BK_WAKE_EVENT, mmio_read_32(SPM_WAKEUP_STA) | + mmio_read_32(SPM_BK_WAKE_EVENT)); + + mmio_write_32(SPM_CPU_WAKEUP_EVENT, 0); + + /* Clean wakeup event raw status (for edge trigger event) */ + mmio_write_32(SPM_WAKEUP_EVENT_MASK, 0xefffffff); + + /* Clean ISR status (except TWAM) */ + mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM); + mmio_write_32(SPM_IRQ_STA, ISRC_ALL_EXC_TWAM); + mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT_ALL); +} + +void __spm_set_pcm_wdt(int en) +{ + /* Enable PCM WDT (normal mode) to start count if needed */ + if (en) { + mmio_clrsetbits_32(PCM_CON1, REG_PCM_WDT_WAKE_LSB, + SPM_REGWR_CFG_KEY); + + if (mmio_read_32(PCM_TIMER_VAL) > PCM_TIMER_MAX) + mmio_write_32(PCM_TIMER_VAL, PCM_TIMER_MAX); + mmio_write_32(PCM_WDT_VAL, mmio_read_32(PCM_TIMER_VAL) + + PCM_WDT_TIMEOUT); + mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | + REG_PCM_WDT_EN_LSB); + } else { + mmio_clrsetbits_32(PCM_CON1, REG_PCM_WDT_EN_LSB, + SPM_REGWR_CFG_KEY); + } +} + +u32 __spm_get_pcm_timer_val(void) +{ + return mmio_read_32(PCM_TIMER_VAL) >> 15; +} + +void __spm_send_cpu_wakeup_event(void) +{ + mmio_write_32(SPM_CPU_WAKEUP_EVENT, 1); +} + +void __spm_ext_int_wakeup_req_clr(void) +{ + u32 cpu = plat_my_core_pos(); + + mmio_write_32(EXT_INT_WAKEUP_REQ_CLR, (1U << cpu)); + + /* Clear spm2mcupm wakeup interrupt status */ + mmio_clrbits_32(SPM2MCUPM_CON, SPM2MCUPM_SW_INT_LSB); +} + +void __spm_hw_s1_state_monitor(int en, uint32_t *status) +{ + uint32_t reg; + + if (en) { + mmio_clrsetbits_32(SPM_ACK_CHK_CON_3, + SPM_ACK_CHK_3_CON_CLR_ALL, + SPM_ACK_CHK_3_CON_EN); + } else { + + reg = mmio_read_32(SPM_ACK_CHK_CON_3); + + if (reg & SPM_ACK_CHK_3_CON_RESULT) { + if (status) + *status |= SPM_INTERNAL_STATUS_HW_S1; + } + mmio_clrsetbits_32(SPM_ACK_CHK_CON_3, SPM_ACK_CHK_3_CON_EN, + (SPM_ACK_CHK_3_CON_HW_MODE_TRIG | + SPM_ACK_CHK_3_CON_CLR_ALL)); + } +} diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm_internal.h b/plat/mediatek/drivers/spm/mt8196/mt_spm_internal.h new file mode 100644 index 000000000..5e08f3da4 --- /dev/null +++ b/plat/mediatek/drivers/spm/mt8196/mt_spm_internal.h @@ -0,0 +1,1206 @@ +/* + * Copyright (c) 2025, Mediatek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_SPM_INTERNAL_H +#define MT_SPM_INTERNAL_H + +#include <dbg_ctrl.h> +#include <mt_spm.h> +#include <mt_spm_stats.h> + +/************************************** + * Config and Parameter + **************************************/ +#define POWER_ON_VAL0_DEF 0x0000F100 +/* SPM_POWER_ON_VAL1 */ +#define POWER_ON_VAL1_DEF 0x003FFE20 +/* SPM_WAKE_MASK*/ +#define SPM_WAKEUP_EVENT_MASK_DEF 0xEFFFFFFF + +#define PCM_WDT_TIMEOUT (30 * 32768) /* 30s */ +#define PCM_TIMER_MAX (0xFFFFFFFF) +/************************************** + * Define and Declare + **************************************/ +/* PCM_PWR_IO_EN */ +#define PCM_PWRIO_EN_R0 BIT(0) +#define PCM_PWRIO_EN_R7 BIT(7) +#define PCM_RF_SYNC_R0 BIT(16) +#define PCM_RF_SYNC_R6 BIT(22) +#define PCM_RF_SYNC_R7 BIT(23) + +/* SPM_SWINT */ +#define PCM_SW_INT0 BIT(0) +#define PCM_SW_INT1 BIT(1) +#define PCM_SW_INT2 BIT(2) +#define PCM_SW_INT3 BIT(3) +#define PCM_SW_INT4 BIT(4) +#define PCM_SW_INT5 BIT(5) +#define PCM_SW_INT6 BIT(6) +#define PCM_SW_INT7 BIT(7) +#define PCM_SW_INT8 BIT(8) +#define PCM_SW_INT9 BIT(9) +#define PCM_SW_INT_ALL (PCM_SW_INT9 | PCM_SW_INT8 | PCM_SW_INT7 | \ + PCM_SW_INT6 | PCM_SW_INT5 | PCM_SW_INT4 | \ + PCM_SW_INT3 | PCM_SW_INT2 | PCM_SW_INT1 | \ + PCM_SW_INT0) + +/* SPM_AP_STANDBY_CON */ +#define WFI_OP_AND 1 +#define WFI_OP_OR 0 + +/* SPM_IRQ_MASK */ +#define ISRM_TWAM BIT(2) +#define ISRM_PCM_RETURN BIT(3) +#define ISRM_RET_IRQ0 BIT(8) +#define ISRM_RET_IRQ1 BIT(9) +#define ISRM_RET_IRQ2 BIT(10) +#define ISRM_RET_IRQ3 BIT(11) +#define ISRM_RET_IRQ4 BIT(12) +#define ISRM_RET_IRQ5 BIT(13) +#define ISRM_RET_IRQ6 BIT(14) +#define ISRM_RET_IRQ7 BIT(15) +#define ISRM_RET_IRQ8 BIT(16) +#define ISRM_RET_IRQ9 BIT(17) +#define ISRM_RET_IRQ_AUX ((ISRM_RET_IRQ9) | (ISRM_RET_IRQ8) | \ + (ISRM_RET_IRQ7) | (ISRM_RET_IRQ6) | \ + (ISRM_RET_IRQ5) | (ISRM_RET_IRQ4) | \ + (ISRM_RET_IRQ3) | (ISRM_RET_IRQ2) | \ + (ISRM_RET_IRQ1)) +#define ISRM_ALL_EXC_TWAM (ISRM_RET_IRQ_AUX) +#define ISRM_ALL (ISRM_ALL_EXC_TWAM | ISRM_TWAM) + +/* SPM_IRQ_STA */ +#define ISRS_TWAM BIT(2) +#define ISRS_PCM_RETURN BIT(3) +#define ISRC_TWAM ISRS_TWAM +#define ISRC_ALL_EXC_TWAM ISRS_PCM_RETURN +#define ISRC_ALL (ISRC_ALL_EXC_TWAM | ISRC_TWAM) + +/* SPM_WAKEUP_MISC */ +#define WAKE_MISC_GIC_WAKEUP 0x3FF /* bit0 ~ bit9 */ +#define WAKE_MISC_DVFSRC_IRQ DVFSRC_IRQ_LSB +#define WAKE_MISC_REG_CPU_WAKEUP SPM_WAKEUP_MISC_REG_CPU_WAKEUP_LSB +#define WAKE_MISC_PCM_TIMER_EVENT PCM_TIMER_EVENT_LSB +#define WAKE_MISC_PMIC_OUT_B (BIT(19) | BIT(20)) +#define WAKE_MISC_TWAM_IRQ_B TWAM_IRQ_B_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_0 SPM_ACK_CHK_WAKEUP_0_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_1 SPM_ACK_CHK_WAKEUP_1_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_2 SPM_ACK_CHK_WAKEUP_2_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_3 SPM_ACK_CHK_WAKEUP_3_LSB +#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_ALL SPM_ACK_CHK_WAKEUP_ALL_LSB +#define WAKE_MISC_PMIC_IRQ_ACK PMIC_IRQ_ACK_LSB +#define WAKE_MISC_PMIC_SCP_IRQ PMIC_SCP_IRQ_LSB + +/* MD32PCM ADDR for SPM code fetch */ +#define MD32PCM_BASE (SPM_BASE + 0x0A00) +#define MD32PCM_CFGREG_SW_RSTN (MD32PCM_BASE + 0x0000) +#define MD32PCM_DMA0_SRC (MD32PCM_BASE + 0x0200) +#define MD32PCM_DMA0_DST (MD32PCM_BASE + 0x0204) +#define MD32PCM_DMA0_WPPT (MD32PCM_BASE + 0x0208) +#define MD32PCM_DMA0_WPTO (MD32PCM_BASE + 0x020C) +#define MD32PCM_DMA0_COUNT (MD32PCM_BASE + 0x0210) +#define MD32PCM_DMA0_CON (MD32PCM_BASE + 0x0214) +#define MD32PCM_DMA0_START (MD32PCM_BASE + 0x0218) +#define MD32PCM_DMA0_RLCT (MD32PCM_BASE + 0x0224) +#define MD32PCM_INTC_IRQ_RAW_STA (MD32PCM_BASE + 0x033C) + +/* ABORT MASK for DEBUG FOORTPRINT */ +#define DEBUG_ABORT_MASK (SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_APSRC | \ + SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_DDREN) + +#define DEBUG_ABORT_MASK_1 (SPM_DBG1_DEBUG_IDX_VTCXO_SLEEP_ABORT_0 | \ + SPM_DBG1_DEBUG_IDX_VTCXO_SLEEP_ABORT_1 | \ + SPM_DBG1_DEBUG_IDX_VCORE_SLEEP_ABORT_0 | \ + SPM_DBG1_DEBUG_IDX_VCORE_SLEEP_ABORT_1 | \ + SPM_DBG1_DEBUG_IDX_PMIC_IRQ_ACK_LOW_ABORT | \ + SPM_DBG1_DEBUG_IDX_PMIC_IRQ_ACK_HIGH_ABORT | \ + SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_LOW_ABORT | \ + SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_HIGH_ABORT | \ + SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_LOW_ABORT | \ + SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_HIGH_ABORT | \ + SPM_DBG1_DEBUG_IDX_SPM_PMIF_CMD_RDY_ABORT) + +struct pwr_ctrl { + + /* For SPM */ + uint32_t pcm_flags; + uint32_t pcm_flags_cust; + uint32_t pcm_flags_cust_set; + uint32_t pcm_flags_cust_clr; + uint32_t pcm_flags1; + uint32_t pcm_flags1_cust; + uint32_t pcm_flags1_cust_set; + uint32_t pcm_flags1_cust_clr; + uint32_t timer_val; + uint32_t timer_val_cust; + uint32_t timer_val_ramp_en; + uint32_t timer_val_ramp_en_sec; + uint32_t wake_src; + uint32_t wake_src_cust; + uint32_t wakelock_timer_val; + uint8_t wdt_disable; + /* Auto-gen Start */ + + /* SPM_CLK_CON */ + uint8_t reg_spm_lock_infra_dcm_lsb; + uint8_t reg_cxo32k_remove_en_lsb; + uint8_t reg_spm_leave_suspend_merge_mask_lsb; + uint8_t reg_sysclk0_src_mb_lsb; + uint8_t reg_sysclk1_src_mb_lsb; + uint8_t reg_sysclk2_src_mb_lsb; + + /* SPM_AP_STANDBY_CON */ + uint8_t reg_wfi_op; + uint8_t reg_wfi_type; + uint8_t reg_mp0_cputop_idle_mask; + uint8_t reg_mp1_cputop_idle_mask; + uint8_t reg_mcusys_idle_mask; + uint8_t reg_csyspwrup_req_mask_lsb; + uint8_t reg_wfi_af_sel; + uint8_t reg_cpu_sleep_wfi; + + /* SPM_SRC_REQ */ + uint8_t reg_spm_adsp_mailbox_req; + uint8_t reg_spm_apsrc_req; + uint8_t reg_spm_ddren_req; + uint8_t reg_spm_dvfs_req; + uint8_t reg_spm_emi_req; + uint8_t reg_spm_f26m_req; + uint8_t reg_spm_infra_req; + uint8_t reg_spm_pmic_req; + uint8_t reg_spm_scp_mailbox_req; + uint8_t reg_spm_sspm_mailbox_req; + uint8_t reg_spm_sw_mailbox_req; + uint8_t reg_spm_vcore_req; + uint8_t reg_spm_vrf18_req; + uint8_t adsp_mailbox_state; + uint8_t apsrc_state; + uint8_t ddren_state; + uint8_t dvfs_state; + uint8_t emi_state; + uint8_t f26m_state; + uint8_t infra_state; + uint8_t pmic_state; + uint8_t scp_mailbox_state; + uint8_t sspm_mailbox_state; + uint8_t sw_mailbox_state; + uint8_t vcore_state; + uint8_t vrf18_state; + + /* SPM_SRC_MASK_0 */ + uint8_t reg_apifr_apsrc_rmb; + uint8_t reg_apifr_ddren_rmb; + uint8_t reg_apifr_emi_rmb; + uint8_t reg_apifr_infra_rmb; + uint8_t reg_apifr_pmic_rmb; + uint8_t reg_apifr_srcclkena_mb; + uint8_t reg_apifr_vcore_rmb; + uint8_t reg_apifr_vrf18_rmb; + uint8_t reg_apu_apsrc_rmb; + uint8_t reg_apu_ddren_rmb; + uint8_t reg_apu_emi_rmb; + uint8_t reg_apu_infra_rmb; + uint8_t reg_apu_pmic_rmb; + uint8_t reg_apu_srcclkena_mb; + uint8_t reg_apu_vcore_rmb; + uint8_t reg_apu_vrf18_rmb; + uint8_t reg_audio_apsrc_rmb; + uint8_t reg_audio_ddren_rmb; + uint8_t reg_audio_emi_rmb; + uint8_t reg_audio_infra_rmb; + uint8_t reg_audio_pmic_rmb; + uint8_t reg_audio_srcclkena_mb; + uint8_t reg_audio_vcore_rmb; + uint8_t reg_audio_vrf18_rmb; + + /* SPM_SRC_MASK_1 */ + uint8_t reg_audio_dsp_apsrc_rmb; + uint8_t reg_audio_dsp_ddren_rmb; + uint8_t reg_audio_dsp_emi_rmb; + uint8_t reg_audio_dsp_infra_rmb; + uint8_t reg_audio_dsp_pmic_rmb; + uint8_t reg_audio_dsp_srcclkena_mb; + uint8_t reg_audio_dsp_vcore_rmb; + uint8_t reg_audio_dsp_vrf18_rmb; + uint8_t reg_cam_apsrc_rmb; + uint8_t reg_cam_ddren_rmb; + uint8_t reg_cam_emi_rmb; + uint8_t reg_cam_infra_rmb; + uint8_t reg_cam_pmic_rmb; + uint8_t reg_cam_srcclkena_mb; + uint8_t reg_cam_vrf18_rmb; + uint32_t reg_ccif_apsrc_rmb; + + /* SPM_SRC_MASK_2 */ + uint32_t reg_ccif_emi_rmb; + uint32_t reg_ccif_infra_rmb; + + /* SPM_SRC_MASK_3 */ + uint32_t reg_ccif_pmic_rmb; + uint32_t reg_ccif_srcclkena_mb; + + /* SPM_SRC_MASK_4 */ + uint32_t reg_ccif_vcore_rmb; + uint32_t reg_ccif_vrf18_rmb; + uint8_t reg_ccu_apsrc_rmb; + uint8_t reg_ccu_ddren_rmb; + uint8_t reg_ccu_emi_rmb; + uint8_t reg_ccu_infra_rmb; + uint8_t reg_ccu_pmic_rmb; + uint8_t reg_ccu_srcclkena_mb; + uint8_t reg_ccu_vrf18_rmb; + uint8_t reg_cg_check_apsrc_rmb; + + /* SPM_SRC_MASK_5 */ + uint8_t reg_cg_check_ddren_rmb; + uint8_t reg_cg_check_emi_rmb; + uint8_t reg_cg_check_infra_rmb; + uint8_t reg_cg_check_pmic_rmb; + uint8_t reg_cg_check_srcclkena_mb; + uint8_t reg_cg_check_vcore_rmb; + uint8_t reg_cg_check_vrf18_rmb; + uint8_t reg_cksys_apsrc_rmb; + uint8_t reg_cksys_ddren_rmb; + uint8_t reg_cksys_emi_rmb; + uint8_t reg_cksys_infra_rmb; + uint8_t reg_cksys_pmic_rmb; + uint8_t reg_cksys_srcclkena_mb; + uint8_t reg_cksys_vcore_rmb; + uint8_t reg_cksys_vrf18_rmb; + uint8_t reg_cksys_1_apsrc_rmb; + uint8_t reg_cksys_1_ddren_rmb; + uint8_t reg_cksys_1_emi_rmb; + uint8_t reg_cksys_1_infra_rmb; + uint8_t reg_cksys_1_pmic_rmb; + uint8_t reg_cksys_1_srcclkena_mb; + uint8_t reg_cksys_1_vcore_rmb; + uint8_t reg_cksys_1_vrf18_rmb; + + /* SPM_SRC_MASK_6 */ + uint8_t reg_cksys_2_apsrc_rmb; + uint8_t reg_cksys_2_ddren_rmb; + uint8_t reg_cksys_2_emi_rmb; + uint8_t reg_cksys_2_infra_rmb; + uint8_t reg_cksys_2_pmic_rmb; + uint8_t reg_cksys_2_srcclkena_mb; + uint8_t reg_cksys_2_vcore_rmb; + uint8_t reg_cksys_2_vrf18_rmb; + uint8_t reg_conn_apsrc_rmb; + uint8_t reg_conn_ddren_rmb; + uint8_t reg_conn_emi_rmb; + uint8_t reg_conn_infra_rmb; + uint8_t reg_conn_pmic_rmb; + uint8_t reg_conn_srcclkena_mb; + uint8_t reg_conn_srcclkenb_mb; + uint8_t reg_conn_vcore_rmb; + uint8_t reg_conn_vrf18_rmb; + uint8_t reg_corecfg_apsrc_rmb; + uint8_t reg_corecfg_ddren_rmb; + uint8_t reg_corecfg_emi_rmb; + uint8_t reg_corecfg_infra_rmb; + uint8_t reg_corecfg_pmic_rmb; + uint8_t reg_corecfg_srcclkena_mb; + uint8_t reg_corecfg_vcore_rmb; + uint8_t reg_corecfg_vrf18_rmb; + + /* SPM_SRC_MASK_7 */ + uint8_t reg_cpueb_apsrc_rmb; + uint8_t reg_cpueb_ddren_rmb; + uint8_t reg_cpueb_emi_rmb; + uint8_t reg_cpueb_infra_rmb; + uint8_t reg_cpueb_pmic_rmb; + uint8_t reg_cpueb_srcclkena_mb; + uint8_t reg_cpueb_vcore_rmb; + uint8_t reg_cpueb_vrf18_rmb; + uint8_t reg_disp0_apsrc_rmb; + uint8_t reg_disp0_ddren_rmb; + uint8_t reg_disp0_emi_rmb; + uint8_t reg_disp0_infra_rmb; + uint8_t reg_disp0_pmic_rmb; + uint8_t reg_disp0_srcclkena_mb; + uint8_t reg_disp0_vrf18_rmb; + uint8_t reg_disp1_apsrc_rmb; + uint8_t reg_disp1_ddren_rmb; + uint8_t reg_disp1_emi_rmb; + uint8_t reg_disp1_infra_rmb; + uint8_t reg_disp1_pmic_rmb; + uint8_t reg_disp1_srcclkena_mb; + uint8_t reg_disp1_vrf18_rmb; + uint8_t reg_dpm_apsrc_rmb; + uint8_t reg_dpm_ddren_rmb; + + /* SPM_SRC_MASK_8 */ + uint8_t reg_dpm_emi_rmb; + uint8_t reg_dpm_infra_rmb; + uint8_t reg_dpm_pmic_rmb; + uint8_t reg_dpm_srcclkena_mb; + uint8_t reg_dpm_vcore_rmb; + uint8_t reg_dpm_vrf18_rmb; + uint8_t reg_dpmaif_apsrc_rmb; + uint8_t reg_dpmaif_ddren_rmb; + uint8_t reg_dpmaif_emi_rmb; + uint8_t reg_dpmaif_infra_rmb; + uint8_t reg_dpmaif_pmic_rmb; + uint8_t reg_dpmaif_srcclkena_mb; + uint8_t reg_dpmaif_vcore_rmb; + uint8_t reg_dpmaif_vrf18_rmb; + + /* SPM_SRC_MASK_9 */ + uint8_t reg_dvfsrc_level_rmb; + uint8_t reg_emisys_apsrc_rmb; + uint8_t reg_emisys_ddren_rmb; + uint8_t reg_emisys_emi_rmb; + uint8_t reg_emisys_infra_rmb; + uint8_t reg_emisys_pmic_rmb; + uint8_t reg_emisys_srcclkena_mb; + uint8_t reg_emisys_vcore_rmb; + uint8_t reg_emisys_vrf18_rmb; + uint8_t reg_gce_apsrc_rmb; + uint8_t reg_gce_ddren_rmb; + uint8_t reg_gce_emi_rmb; + uint8_t reg_gce_infra_rmb; + uint8_t reg_gce_pmic_rmb; + uint8_t reg_gce_srcclkena_mb; + uint8_t reg_gce_vcore_rmb; + uint8_t reg_gce_vrf18_rmb; + uint8_t reg_gpueb_apsrc_rmb; + uint8_t reg_gpueb_ddren_rmb; + uint8_t reg_gpueb_emi_rmb; + uint8_t reg_gpueb_infra_rmb; + uint8_t reg_gpueb_pmic_rmb; + uint8_t reg_gpueb_srcclkena_mb; + uint8_t reg_gpueb_vcore_rmb; + uint8_t reg_gpueb_vrf18_rmb; + uint8_t reg_hwccf_apsrc_rmb; + uint8_t reg_hwccf_ddren_rmb; + uint8_t reg_hwccf_emi_rmb; + uint8_t reg_hwccf_infra_rmb; + uint8_t reg_hwccf_pmic_rmb; + uint8_t reg_hwccf_srcclkena_mb; + uint8_t reg_hwccf_vcore_rmb; + + /* SPM_SRC_MASK_10 */ + uint8_t reg_hwccf_vrf18_rmb; + uint8_t reg_img_apsrc_rmb; + uint8_t reg_img_ddren_rmb; + uint8_t reg_img_emi_rmb; + uint8_t reg_img_infra_rmb; + uint8_t reg_img_pmic_rmb; + uint8_t reg_img_srcclkena_mb; + uint8_t reg_img_vrf18_rmb; + uint8_t reg_infrasys_apsrc_rmb; + uint8_t reg_infrasys_ddren_rmb; + uint8_t reg_infrasys_emi_rmb; + uint8_t reg_infrasys_infra_rmb; + uint8_t reg_infrasys_pmic_rmb; + uint8_t reg_infrasys_srcclkena_mb; + uint8_t reg_infrasys_vcore_rmb; + uint8_t reg_infrasys_vrf18_rmb; + uint8_t reg_ipic_infra_rmb; + uint8_t reg_ipic_vrf18_rmb; + uint8_t reg_mcu_apsrc_rmb; + uint8_t reg_mcu_ddren_rmb; + uint8_t reg_mcu_emi_rmb; + uint8_t reg_mcu_infra_rmb; + uint8_t reg_mcu_pmic_rmb; + uint8_t reg_mcu_srcclkena_mb; + uint8_t reg_mcu_vcore_rmb; + uint8_t reg_mcu_vrf18_rmb; + uint8_t reg_md_apsrc_rmb; + uint8_t reg_md_ddren_rmb; + uint8_t reg_md_emi_rmb; + uint8_t reg_md_infra_rmb; + uint8_t reg_md_pmic_rmb; + uint8_t reg_md_srcclkena_mb; + + /* SPM_SRC_MASK_11 */ + uint8_t reg_md_srcclkena1_mb; + uint8_t reg_md_vcore_rmb; + uint8_t reg_md_vrf18_rmb; + uint8_t reg_mm_proc_apsrc_rmb; + uint8_t reg_mm_proc_ddren_rmb; + uint8_t reg_mm_proc_emi_rmb; + uint8_t reg_mm_proc_infra_rmb; + uint8_t reg_mm_proc_pmic_rmb; + uint8_t reg_mm_proc_srcclkena_mb; + uint8_t reg_mm_proc_vcore_rmb; + uint8_t reg_mm_proc_vrf18_rmb; + uint8_t reg_mml0_apsrc_rmb; + uint8_t reg_mml0_ddren_rmb; + uint8_t reg_mml0_emi_rmb; + uint8_t reg_mml0_infra_rmb; + uint8_t reg_mml0_pmic_rmb; + uint8_t reg_mml0_srcclkena_mb; + uint8_t reg_mml0_vrf18_rmb; + uint8_t reg_mml1_apsrc_rmb; + uint8_t reg_mml1_ddren_rmb; + uint8_t reg_mml1_emi_rmb; + uint8_t reg_mml1_infra_rmb; + uint8_t reg_mml1_pmic_rmb; + uint8_t reg_mml1_srcclkena_mb; + uint8_t reg_mml1_vrf18_rmb; + uint8_t reg_ovl0_apsrc_rmb; + uint8_t reg_ovl0_ddren_rmb; + uint8_t reg_ovl0_emi_rmb; + uint8_t reg_ovl0_infra_rmb; + uint8_t reg_ovl0_pmic_rmb; + uint8_t reg_ovl0_srcclkena_mb; + uint8_t reg_ovl0_vrf18_rmb; + + /* SPM_SRC_MASK_12 */ + uint8_t reg_ovl1_apsrc_rmb; + uint8_t reg_ovl1_ddren_rmb; + uint8_t reg_ovl1_emi_rmb; + uint8_t reg_ovl1_infra_rmb; + uint8_t reg_ovl1_pmic_rmb; + uint8_t reg_ovl1_srcclkena_mb; + uint8_t reg_ovl1_vrf18_rmb; + uint8_t reg_pcie0_apsrc_rmb; + uint8_t reg_pcie0_ddren_rmb; + uint8_t reg_pcie0_emi_rmb; + uint8_t reg_pcie0_infra_rmb; + uint8_t reg_pcie0_pmic_rmb; + uint8_t reg_pcie0_srcclkena_mb; + uint8_t reg_pcie0_vcore_rmb; + uint8_t reg_pcie0_vrf18_rmb; + uint8_t reg_pcie1_apsrc_rmb; + uint8_t reg_pcie1_ddren_rmb; + uint8_t reg_pcie1_emi_rmb; + uint8_t reg_pcie1_infra_rmb; + uint8_t reg_pcie1_pmic_rmb; + uint8_t reg_pcie1_srcclkena_mb; + uint8_t reg_pcie1_vcore_rmb; + uint8_t reg_pcie1_vrf18_rmb; + uint8_t reg_perisys_apsrc_rmb; + uint8_t reg_perisys_ddren_rmb; + uint8_t reg_perisys_emi_rmb; + uint8_t reg_perisys_infra_rmb; + uint8_t reg_perisys_pmic_rmb; + uint8_t reg_perisys_srcclkena_mb; + uint8_t reg_perisys_vcore_rmb; + uint8_t reg_perisys_vrf18_rmb; + uint8_t reg_pmsr_apsrc_rmb; + + /* SPM_SRC_MASK_13 */ + uint8_t reg_pmsr_ddren_rmb; + uint8_t reg_pmsr_emi_rmb; + uint8_t reg_pmsr_infra_rmb; + uint8_t reg_pmsr_pmic_rmb; + uint8_t reg_pmsr_srcclkena_mb; + uint8_t reg_pmsr_vcore_rmb; + uint8_t reg_pmsr_vrf18_rmb; + uint8_t reg_scp_apsrc_rmb; + uint8_t reg_scp_ddren_rmb; + uint8_t reg_scp_emi_rmb; + uint8_t reg_scp_infra_rmb; + uint8_t reg_scp_pmic_rmb; + uint8_t reg_scp_srcclkena_mb; + uint8_t reg_scp_vcore_rmb; + uint8_t reg_scp_vrf18_rmb; + uint8_t reg_spu_hwr_apsrc_rmb; + uint8_t reg_spu_hwr_ddren_rmb; + uint8_t reg_spu_hwr_emi_rmb; + uint8_t reg_spu_hwr_infra_rmb; + uint8_t reg_spu_hwr_pmic_rmb; + uint8_t reg_spu_hwr_srcclkena_mb; + uint8_t reg_spu_hwr_vcore_rmb; + uint8_t reg_spu_hwr_vrf18_rmb; + uint8_t reg_spu_ise_apsrc_rmb; + uint8_t reg_spu_ise_ddren_rmb; + uint8_t reg_spu_ise_emi_rmb; + uint8_t reg_spu_ise_infra_rmb; + uint8_t reg_spu_ise_pmic_rmb; + uint8_t reg_spu_ise_srcclkena_mb; + uint8_t reg_spu_ise_vcore_rmb; + uint8_t reg_spu_ise_vrf18_rmb; + + /* SPM_SRC_MASK_14 */ + uint8_t reg_srcclkeni_infra_rmb; + uint8_t reg_srcclkeni_pmic_rmb; + uint8_t reg_srcclkeni_srcclkena_mb; + uint8_t reg_srcclkeni_vcore_rmb; + uint8_t reg_sspm_apsrc_rmb; + uint8_t reg_sspm_ddren_rmb; + uint8_t reg_sspm_emi_rmb; + uint8_t reg_sspm_infra_rmb; + uint8_t reg_sspm_pmic_rmb; + uint8_t reg_sspm_srcclkena_mb; + uint8_t reg_sspm_vrf18_rmb; + uint8_t reg_ssrsys_apsrc_rmb; + uint8_t reg_ssrsys_ddren_rmb; + uint8_t reg_ssrsys_emi_rmb; + uint8_t reg_ssrsys_infra_rmb; + uint8_t reg_ssrsys_pmic_rmb; + uint8_t reg_ssrsys_srcclkena_mb; + uint8_t reg_ssrsys_vcore_rmb; + uint8_t reg_ssrsys_vrf18_rmb; + uint8_t reg_ssusb_apsrc_rmb; + uint8_t reg_ssusb_ddren_rmb; + uint8_t reg_ssusb_emi_rmb; + uint8_t reg_ssusb_infra_rmb; + uint8_t reg_ssusb_pmic_rmb; + uint8_t reg_ssusb_srcclkena_mb; + uint8_t reg_ssusb_vcore_rmb; + uint8_t reg_ssusb_vrf18_rmb; + uint8_t reg_uart_hub_infra_rmb; + + /* SPM_SRC_MASK_15 */ + uint8_t reg_uart_hub_pmic_rmb; + uint8_t reg_uart_hub_srcclkena_mb; + uint8_t reg_uart_hub_vcore_rmb; + uint8_t reg_uart_hub_vrf18_rmb; + uint8_t reg_ufs_apsrc_rmb; + uint8_t reg_ufs_ddren_rmb; + uint8_t reg_ufs_emi_rmb; + uint8_t reg_ufs_infra_rmb; + uint8_t reg_ufs_pmic_rmb; + uint8_t reg_ufs_srcclkena_mb; + uint8_t reg_ufs_vcore_rmb; + uint8_t reg_ufs_vrf18_rmb; + uint8_t reg_vdec_apsrc_rmb; + uint8_t reg_vdec_ddren_rmb; + uint8_t reg_vdec_emi_rmb; + uint8_t reg_vdec_infra_rmb; + uint8_t reg_vdec_pmic_rmb; + uint8_t reg_vdec_srcclkena_mb; + uint8_t reg_vdec_vrf18_rmb; + uint8_t reg_venc_apsrc_rmb; + uint8_t reg_venc_ddren_rmb; + uint8_t reg_venc_emi_rmb; + uint8_t reg_venc_infra_rmb; + uint8_t reg_venc_pmic_rmb; + uint8_t reg_venc_srcclkena_mb; + uint8_t reg_venc_vrf18_rmb; + uint8_t reg_vlpcfg_apsrc_rmb; + uint8_t reg_vlpcfg_ddren_rmb; + uint8_t reg_vlpcfg_emi_rmb; + uint8_t reg_vlpcfg_infra_rmb; + uint8_t reg_vlpcfg_pmic_rmb; + uint8_t reg_vlpcfg_srcclkena_mb; + + /* SPM_SRC_MASK_16 */ + uint8_t reg_vlpcfg_vcore_rmb; + uint8_t reg_vlpcfg_vrf18_rmb; + uint8_t reg_vlpcfg1_apsrc_rmb; + uint8_t reg_vlpcfg1_ddren_rmb; + uint8_t reg_vlpcfg1_emi_rmb; + uint8_t reg_vlpcfg1_infra_rmb; + uint8_t reg_vlpcfg1_pmic_rmb; + uint8_t reg_vlpcfg1_srcclkena_mb; + uint8_t reg_vlpcfg1_vcore_rmb; + uint8_t reg_vlpcfg1_vrf18_rmb; + + /* SPM_EVENT_CON_MISC */ + uint8_t reg_srcclken_fast_resp; + uint8_t reg_csyspwrup_ack_mask; + + /* SPM_SRC_MASK_17 */ + uint32_t reg_spm_sw_vcore_rmb; + uint32_t reg_spm_sw_pmic_rmb; + + /* SPM_SRC_MASK_18 */ + uint32_t reg_spm_sw_srcclkena_mb; + + /* SPM_WAKE_MASK*/ + uint32_t reg_wake_mask; + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + uint32_t reg_ext_wake_mask; +}; + +enum pwr_ctrl_enum { + PW_PCM_FLAGS, + PW_PCM_FLAGS_CUST, + PW_PCM_FLAGS_CUST_SET, + PW_PCM_FLAGS_CUST_CLR, + PW_PCM_FLAGS1, + PW_PCM_FLAGS1_CUST, + PW_PCM_FLAGS1_CUST_SET, + PW_PCM_FLAGS1_CUST_CLR, + PW_TIMER_VAL, + PW_TIMER_VAL_CUST, + PW_TIMER_VAL_RAMP_EN, + PW_TIMER_VAL_RAMP_EN_SEC, + PW_WAKE_SRC, + PW_WAKE_SRC_CUST, + PW_WAKELOCK_TIMER_VAL, + PW_WDT_DISABLE, + + /* SPM_SRC_REQ */ + PW_REG_SPM_ADSP_MAILBOX_REQ, + PW_REG_SPM_APSRC_REQ, + PW_REG_SPM_DDREN_REQ, + PW_REG_SPM_DVFS_REQ, + PW_REG_SPM_EMI_REQ, + PW_REG_SPM_F26M_REQ, + PW_REG_SPM_INFRA_REQ, + PW_REG_SPM_PMIC_REQ, + PW_REG_SPM_SCP_MAILBOX_REQ, + PW_REG_SPM_SSPM_MAILBOX_REQ, + PW_REG_SPM_SW_MAILBOX_REQ, + PW_REG_SPM_VCORE_REQ, + PW_REG_SPM_VRF18_REQ, + + /* SPM_SRC_MASK_0 */ + PW_REG_APIFR_APSRC_RMB, + PW_REG_APIFR_DDREN_RMB, + PW_REG_APIFR_EMI_RMB, + PW_REG_APIFR_INFRA_RMB, + PW_REG_APIFR_PMIC_RMB, + PW_REG_APIFR_SRCCLKENA_MB, + PW_REG_APIFR_VCORE_RMB, + PW_REG_APIFR_VRF18_RMB, + PW_REG_APU_APSRC_RMB, + PW_REG_APU_DDREN_RMB, + PW_REG_APU_EMI_RMB, + PW_REG_APU_INFRA_RMB, + PW_REG_APU_PMIC_RMB, + PW_REG_APU_SRCCLKENA_MB, + PW_REG_APU_VCORE_RMB, + PW_REG_APU_VRF18_RMB, + PW_REG_AUDIO_APSRC_RMB, + PW_REG_AUDIO_DDREN_RMB, + PW_REG_AUDIO_EMI_RMB, + PW_REG_AUDIO_INFRA_RMB, + PW_REG_AUDIO_PMIC_RMB, + PW_REG_AUDIO_SRCCLKENA_MB, + PW_REG_AUDIO_VCORE_RMB, + PW_REG_AUDIO_VRF18_RMB, + + /* SPM_SRC_MASK_1 */ + PW_REG_AUDIO_DSP_APSRC_RMB, + PW_REG_AUDIO_DSP_DDREN_RMB, + PW_REG_AUDIO_DSP_EMI_RMB, + PW_REG_AUDIO_DSP_INFRA_RMB, + PW_REG_AUDIO_DSP_PMIC_RMB, + PW_REG_AUDIO_DSP_SRCCLKENA_MB, + PW_REG_AUDIO_DSP_VCORE_RMB, + PW_REG_AUDIO_DSP_VRF18_RMB, + PW_REG_CAM_APSRC_RMB, + PW_REG_CAM_DDREN_RMB, + PW_REG_CAM_EMI_RMB, + PW_REG_CAM_INFRA_RMB, + PW_REG_CAM_PMIC_RMB, + PW_REG_CAM_SRCCLKENA_MB, + PW_REG_CAM_VRF18_RMB, + PW_REG_CCIF_APSRC_RMB, + + /* SPM_SRC_MASK_2 */ + PW_REG_CCIF_EMI_RMB, + PW_REG_CCIF_INFRA_RMB, + + /* SPM_SRC_MASK_3 */ + PW_REG_CCIF_PMIC_RMB, + PW_REG_CCIF_SRCCLKENA_MB, + + /* SPM_SRC_MASK_4 */ + PW_REG_CCIF_VCORE_RMB, + PW_REG_CCIF_VRF18_RMB, + PW_REG_CCU_APSRC_RMB, + PW_REG_CCU_DDREN_RMB, + PW_REG_CCU_EMI_RMB, + PW_REG_CCU_INFRA_RMB, + PW_REG_CCU_PMIC_RMB, + PW_REG_CCU_SRCCLKENA_MB, + PW_REG_CCU_VRF18_RMB, + PW_REG_CG_CHECK_APSRC_RMB, + + /* SPM_SRC_MASK_5 */ + PW_REG_CG_CHECK_DDREN_RMB, + PW_REG_CG_CHECK_EMI_RMB, + PW_REG_CG_CHECK_INFRA_RMB, + PW_REG_CG_CHECK_PMIC_RMB, + PW_REG_CG_CHECK_SRCCLKENA_MB, + PW_REG_CG_CHECK_VCORE_RMB, + PW_REG_CG_CHECK_VRF18_RMB, + PW_REG_CKSYS_APSRC_RMB, + PW_REG_CKSYS_DDREN_RMB, + PW_REG_CKSYS_EMI_RMB, + PW_REG_CKSYS_INFRA_RMB, + PW_REG_CKSYS_PMIC_RMB, + PW_REG_CKSYS_SRCCLKENA_MB, + PW_REG_CKSYS_VCORE_RMB, + PW_REG_CKSYS_VRF18_RMB, + PW_REG_CKSYS_1_APSRC_RMB, + PW_REG_CKSYS_1_DDREN_RMB, + PW_REG_CKSYS_1_EMI_RMB, + PW_REG_CKSYS_1_INFRA_RMB, + PW_REG_CKSYS_1_PMIC_RMB, + PW_REG_CKSYS_1_SRCCLKENA_MB, + PW_REG_CKSYS_1_VCORE_RMB, + PW_REG_CKSYS_1_VRF18_RMB, + + /* SPM_SRC_MASK_6 */ + PW_REG_CKSYS_2_APSRC_RMB, + PW_REG_CKSYS_2_DDREN_RMB, + PW_REG_CKSYS_2_EMI_RMB, + PW_REG_CKSYS_2_INFRA_RMB, + PW_REG_CKSYS_2_PMIC_RMB, + PW_REG_CKSYS_2_SRCCLKENA_MB, + PW_REG_CKSYS_2_VCORE_RMB, + PW_REG_CKSYS_2_VRF18_RMB, + PW_REG_CONN_APSRC_RMB, + PW_REG_CONN_DDREN_RMB, + PW_REG_CONN_EMI_RMB, + PW_REG_CONN_INFRA_RMB, + PW_REG_CONN_PMIC_RMB, + PW_REG_CONN_SRCCLKENA_MB, + PW_REG_CONN_SRCCLKENB_MB, + PW_REG_CONN_VCORE_RMB, + PW_REG_CONN_VRF18_RMB, + PW_REG_CORECFG_APSRC_RMB, + PW_REG_CORECFG_DDREN_RMB, + PW_REG_CORECFG_EMI_RMB, + PW_REG_CORECFG_INFRA_RMB, + PW_REG_CORECFG_PMIC_RMB, + PW_REG_CORECFG_SRCCLKENA_MB, + PW_REG_CORECFG_VCORE_RMB, + PW_REG_CORECFG_VRF18_RMB, + + /* SPM_SRC_MASK_7 */ + PW_REG_CPUEB_APSRC_RMB, + PW_REG_CPUEB_DDREN_RMB, + PW_REG_CPUEB_EMI_RMB, + PW_REG_CPUEB_INFRA_RMB, + PW_REG_CPUEB_PMIC_RMB, + PW_REG_CPUEB_SRCCLKENA_MB, + PW_REG_CPUEB_VCORE_RMB, + PW_REG_CPUEB_VRF18_RMB, + PW_REG_DISP0_APSRC_RMB, + PW_REG_DISP0_DDREN_RMB, + PW_REG_DISP0_EMI_RMB, + PW_REG_DISP0_INFRA_RMB, + PW_REG_DISP0_PMIC_RMB, + PW_REG_DISP0_SRCCLKENA_MB, + PW_REG_DISP0_VRF18_RMB, + PW_REG_DISP1_APSRC_RMB, + PW_REG_DISP1_DDREN_RMB, + PW_REG_DISP1_EMI_RMB, + PW_REG_DISP1_INFRA_RMB, + PW_REG_DISP1_PMIC_RMB, + PW_REG_DISP1_SRCCLKENA_MB, + PW_REG_DISP1_VRF18_RMB, + PW_REG_DPM_APSRC_RMB, + PW_REG_DPM_DDREN_RMB, + + /* SPM_SRC_MASK_8 */ + PW_REG_DPM_EMI_RMB, + PW_REG_DPM_INFRA_RMB, + PW_REG_DPM_PMIC_RMB, + PW_REG_DPM_SRCCLKENA_MB, + PW_REG_DPM_VCORE_RMB, + PW_REG_DPM_VRF18_RMB, + PW_REG_DPMAIF_APSRC_RMB, + PW_REG_DPMAIF_DDREN_RMB, + PW_REG_DPMAIF_EMI_RMB, + PW_REG_DPMAIF_INFRA_RMB, + PW_REG_DPMAIF_PMIC_RMB, + PW_REG_DPMAIF_SRCCLKENA_MB, + PW_REG_DPMAIF_VCORE_RMB, + PW_REG_DPMAIF_VRF18_RMB, + + /* SPM_SRC_MASK_9 */ + PW_REG_DVFSRC_LEVEL_RMB, + PW_REG_EMISYS_APSRC_RMB, + PW_REG_EMISYS_DDREN_RMB, + PW_REG_EMISYS_EMI_RMB, + PW_REG_EMISYS_INFRA_RMB, + PW_REG_EMISYS_PMIC_RMB, + PW_REG_EMISYS_SRCCLKENA_MB, + PW_REG_EMISYS_VCORE_RMB, + PW_REG_EMISYS_VRF18_RMB, + PW_REG_GCE_APSRC_RMB, + PW_REG_GCE_DDREN_RMB, + PW_REG_GCE_EMI_RMB, + PW_REG_GCE_INFRA_RMB, + PW_REG_GCE_PMIC_RMB, + PW_REG_GCE_SRCCLKENA_MB, + PW_REG_GCE_VCORE_RMB, + PW_REG_GCE_VRF18_RMB, + PW_REG_GPUEB_APSRC_RMB, + PW_REG_GPUEB_DDREN_RMB, + PW_REG_GPUEB_EMI_RMB, + PW_REG_GPUEB_INFRA_RMB, + PW_REG_GPUEB_PMIC_RMB, + PW_REG_GPUEB_SRCCLKENA_MB, + PW_REG_GPUEB_VCORE_RMB, + PW_REG_GPUEB_VRF18_RMB, + PW_REG_HWCCF_APSRC_RMB, + PW_REG_HWCCF_DDREN_RMB, + PW_REG_HWCCF_EMI_RMB, + PW_REG_HWCCF_INFRA_RMB, + PW_REG_HWCCF_PMIC_RMB, + PW_REG_HWCCF_SRCCLKENA_MB, + PW_REG_HWCCF_VCORE_RMB, + + /* SPM_SRC_MASK_10 */ + PW_REG_HWCCF_VRF18_RMB, + PW_REG_IMG_APSRC_RMB, + PW_REG_IMG_DDREN_RMB, + PW_REG_IMG_EMI_RMB, + PW_REG_IMG_INFRA_RMB, + PW_REG_IMG_PMIC_RMB, + PW_REG_IMG_SRCCLKENA_MB, + PW_REG_IMG_VRF18_RMB, + PW_REG_INFRASYS_APSRC_RMB, + PW_REG_INFRASYS_DDREN_RMB, + PW_REG_INFRASYS_EMI_RMB, + PW_REG_INFRASYS_INFRA_RMB, + PW_REG_INFRASYS_PMIC_RMB, + PW_REG_INFRASYS_SRCCLKENA_MB, + PW_REG_INFRASYS_VCORE_RMB, + PW_REG_INFRASYS_VRF18_RMB, + PW_REG_IPIC_INFRA_RMB, + PW_REG_IPIC_VRF18_RMB, + PW_REG_MCU_APSRC_RMB, + PW_REG_MCU_DDREN_RMB, + PW_REG_MCU_EMI_RMB, + PW_REG_MCU_INFRA_RMB, + PW_REG_MCU_PMIC_RMB, + PW_REG_MCU_SRCCLKENA_MB, + PW_REG_MCU_VCORE_RMB, + PW_REG_MCU_VRF18_RMB, + PW_REG_MD_APSRC_RMB, + PW_REG_MD_DDREN_RMB, + PW_REG_MD_EMI_RMB, + PW_REG_MD_INFRA_RMB, + PW_REG_MD_PMIC_RMB, + PW_REG_MD_SRCCLKENA_MB, + + /* SPM_SRC_MASK_11 */ + PW_REG_MD_SRCCLKENA1_MB, + PW_REG_MD_VCORE_RMB, + PW_REG_MD_VRF18_RMB, + PW_REG_MM_PROC_APSRC_RMB, + PW_REG_MM_PROC_DDREN_RMB, + PW_REG_MM_PROC_EMI_RMB, + PW_REG_MM_PROC_INFRA_RMB, + PW_REG_MM_PROC_PMIC_RMB, + PW_REG_MM_PROC_SRCCLKENA_MB, + PW_REG_MM_PROC_VCORE_RMB, + PW_REG_MM_PROC_VRF18_RMB, + PW_REG_MML0_APSRC_RMB, + PW_REG_MML0_DDREN_RMB, + PW_REG_MML0_EMI_RMB, + PW_REG_MML0_INFRA_RMB, + PW_REG_MML0_PMIC_RMB, + PW_REG_MML0_SRCCLKENA_MB, + PW_REG_MML0_VRF18_RMB, + PW_REG_MML1_APSRC_RMB, + PW_REG_MML1_DDREN_RMB, + PW_REG_MML1_EMI_RMB, + PW_REG_MML1_INFRA_RMB, + PW_REG_MML1_PMIC_RMB, + PW_REG_MML1_SRCCLKENA_MB, + PW_REG_MML1_VRF18_RMB, + PW_REG_OVL0_APSRC_RMB, + PW_REG_OVL0_DDREN_RMB, + PW_REG_OVL0_EMI_RMB, + PW_REG_OVL0_INFRA_RMB, + PW_REG_OVL0_PMIC_RMB, + PW_REG_OVL0_SRCCLKENA_MB, + PW_REG_OVL0_VRF18_RMB, + + /* SPM_SRC_MASK_12 */ + PW_REG_OVL1_APSRC_RMB, + PW_REG_OVL1_DDREN_RMB, + PW_REG_OVL1_EMI_RMB, + PW_REG_OVL1_INFRA_RMB, + PW_REG_OVL1_PMIC_RMB, + PW_REG_OVL1_SRCCLKENA_MB, + PW_REG_OVL1_VRF18_RMB, + PW_REG_PCIE0_APSRC_RMB, + PW_REG_PCIE0_DDREN_RMB, + PW_REG_PCIE0_EMI_RMB, + PW_REG_PCIE0_INFRA_RMB, + PW_REG_PCIE0_PMIC_RMB, + PW_REG_PCIE0_SRCCLKENA_MB, + PW_REG_PCIE0_VCORE_RMB, + PW_REG_PCIE0_VRF18_RMB, + PW_REG_PCIE1_APSRC_RMB, + PW_REG_PCIE1_DDREN_RMB, + PW_REG_PCIE1_EMI_RMB, + PW_REG_PCIE1_INFRA_RMB, + PW_REG_PCIE1_PMIC_RMB, + PW_REG_PCIE1_SRCCLKENA_MB, + PW_REG_PCIE1_VCORE_RMB, + PW_REG_PCIE1_VRF18_RMB, + PW_REG_PERISYS_APSRC_RMB, + PW_REG_PERISYS_DDREN_RMB, + PW_REG_PERISYS_EMI_RMB, + PW_REG_PERISYS_INFRA_RMB, + PW_REG_PERISYS_PMIC_RMB, + PW_REG_PERISYS_SRCCLKENA_MB, + PW_REG_PERISYS_VCORE_RMB, + PW_REG_PERISYS_VRF18_RMB, + PW_REG_PMSR_APSRC_RMB, + + /* SPM_SRC_MASK_13 */ + PW_REG_PMSR_DDREN_RMB, + PW_REG_PMSR_EMI_RMB, + PW_REG_PMSR_INFRA_RMB, + PW_REG_PMSR_PMIC_RMB, + PW_REG_PMSR_SRCCLKENA_MB, + PW_REG_PMSR_VCORE_RMB, + PW_REG_PMSR_VRF18_RMB, + PW_REG_SCP_APSRC_RMB, + PW_REG_SCP_DDREN_RMB, + PW_REG_SCP_EMI_RMB, + PW_REG_SCP_INFRA_RMB, + PW_REG_SCP_PMIC_RMB, + PW_REG_SCP_SRCCLKENA_MB, + PW_REG_SCP_VCORE_RMB, + PW_REG_SCP_VRF18_RMB, + PW_REG_SPU_HWR_APSRC_RMB, + PW_REG_SPU_HWR_DDREN_RMB, + PW_REG_SPU_HWR_EMI_RMB, + PW_REG_SPU_HWR_INFRA_RMB, + PW_REG_SPU_HWR_PMIC_RMB, + PW_REG_SPU_HWR_SRCCLKENA_MB, + PW_REG_SPU_HWR_VCORE_RMB, + PW_REG_SPU_HWR_VRF18_RMB, + PW_REG_SPU_ISE_APSRC_RMB, + PW_REG_SPU_ISE_DDREN_RMB, + PW_REG_SPU_ISE_EMI_RMB, + PW_REG_SPU_ISE_INFRA_RMB, + PW_REG_SPU_ISE_PMIC_RMB, + PW_REG_SPU_ISE_SRCCLKENA_MB, + PW_REG_SPU_ISE_VCORE_RMB, + PW_REG_SPU_ISE_VRF18_RMB, + + /* SPM_SRC_MASK_14 */ + PW_REG_SRCCLKENI_INFRA_RMB, + PW_REG_SRCCLKENI_PMIC_RMB, + PW_REG_SRCCLKENI_SRCCLKENA_MB, + PW_REG_SRCCLKENI_VCORE_RMB, + PW_REG_SSPM_APSRC_RMB, + PW_REG_SSPM_DDREN_RMB, + PW_REG_SSPM_EMI_RMB, + PW_REG_SSPM_INFRA_RMB, + PW_REG_SSPM_PMIC_RMB, + PW_REG_SSPM_SRCCLKENA_MB, + PW_REG_SSPM_VRF18_RMB, + PW_REG_SSRSYS_APSRC_RMB, + PW_REG_SSRSYS_DDREN_RMB, + PW_REG_SSRSYS_EMI_RMB, + PW_REG_SSRSYS_INFRA_RMB, + PW_REG_SSRSYS_PMIC_RMB, + PW_REG_SSRSYS_SRCCLKENA_MB, + PW_REG_SSRSYS_VCORE_RMB, + PW_REG_SSRSYS_VRF18_RMB, + PW_REG_SSUSB_APSRC_RMB, + PW_REG_SSUSB_DDREN_RMB, + PW_REG_SSUSB_EMI_RMB, + PW_REG_SSUSB_INFRA_RMB, + PW_REG_SSUSB_PMIC_RMB, + PW_REG_SSUSB_SRCCLKENA_MB, + PW_REG_SSUSB_VCORE_RMB, + PW_REG_SSUSB_VRF18_RMB, + PW_REG_UART_HUB_INFRA_RMB, + + /* SPM_SRC_MASK_15 */ + PW_REG_UART_HUB_PMIC_RMB, + PW_REG_UART_HUB_SRCCLKENA_MB, + PW_REG_UART_HUB_VCORE_RMB, + PW_REG_UART_HUB_VRF18_RMB, + PW_REG_UFS_APSRC_RMB, + PW_REG_UFS_DDREN_RMB, + PW_REG_UFS_EMI_RMB, + PW_REG_UFS_INFRA_RMB, + PW_REG_UFS_PMIC_RMB, + PW_REG_UFS_SRCCLKENA_MB, + PW_REG_UFS_VCORE_RMB, + PW_REG_UFS_VRF18_RMB, + PW_REG_VDEC_APSRC_RMB, + PW_REG_VDEC_DDREN_RMB, + PW_REG_VDEC_EMI_RMB, + PW_REG_VDEC_INFRA_RMB, + PW_REG_VDEC_PMIC_RMB, + PW_REG_VDEC_SRCCLKENA_MB, + PW_REG_VDEC_VRF18_RMB, + PW_REG_VENC_APSRC_RMB, + PW_REG_VENC_DDREN_RMB, + PW_REG_VENC_EMI_RMB, + PW_REG_VENC_INFRA_RMB, + PW_REG_VENC_PMIC_RMB, + PW_REG_VENC_SRCCLKENA_MB, + PW_REG_VENC_VRF18_RMB, + PW_REG_VLPCFG_APSRC_RMB, + PW_REG_VLPCFG_DDREN_RMB, + PW_REG_VLPCFG_EMI_RMB, + PW_REG_VLPCFG_INFRA_RMB, + PW_REG_VLPCFG_PMIC_RMB, + PW_REG_VLPCFG_SRCCLKENA_MB, + + /* SPM_SRC_MASK_16 */ + PW_REG_VLPCFG_VCORE_RMB, + PW_REG_VLPCFG_VRF18_RMB, + PW_REG_VLPCFG1_APSRC_RMB, + PW_REG_VLPCFG1_DDREN_RMB, + PW_REG_VLPCFG1_EMI_RMB, + PW_REG_VLPCFG1_INFRA_RMB, + PW_REG_VLPCFG1_PMIC_RMB, + PW_REG_VLPCFG1_SRCCLKENA_MB, + PW_REG_VLPCFG1_VCORE_RMB, + PW_REG_VLPCFG1_VRF18_RMB, + + /* SPM_EVENT_CON_MISC */ + PW_REG_SRCCLKEN_FAST_RESP, + PW_REG_CSYSPWRUP_ACK_MASK, + + /* SPM_SRC_MASK_17 */ + PW_REG_SPM_SW_VCORE_RMB, + PW_REG_SPM_SW_PMIC_RMB, + + /* SPM_SRC_MASK_18 */ + PW_REG_SPM_SW_SRCCLKENA_MB, + + /* SPM_WAKE_MASK*/ + PW_REG_WAKEUP_EVENT_MASK, + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + PW_REG_EXT_WAKEUP_EVENT_MASK, + + PW_MAX_COUNT, +}; + +/* spm_internal.c internal status */ +#define SPM_INTERNAL_STATUS_HW_S1 BIT(0) + +/* + * HW_TARG_GROUP_SEL_3 : 3b'1 (pcm_reg_13) + * HW_TARG_SIGNAL_SEL_3 : 5b'10101 + * HW_TRIG_GROUP_SEL_3 : 3'b100 (trig_reserve) + * HW_TRIG_SIGNAL_SEL_3 : 5'b1100 (trig_reserve[24]=sc_hw_s1_req) + */ +#define SPM_ACK_CHK_3_SEL_HW_S1 (0x00350098) +#define SPM_ACK_CHK_3_HW_S1_CNT (1) + +#define SPM_ACK_CHK_3_CON_HW_MODE_TRIG (0x800) +/* BIT[0]: SW_EN, BIT[4]: STA_EN, BIT[8]: HW_EN */ +#define SPM_ACK_CHK_3_CON_EN (0x110) +#define SPM_ACK_CHK_3_CON_CLR_ALL (0x2) +/* BIT[15]: RESULT */ +#define SPM_ACK_CHK_3_CON_RESULT (0x8000) + +struct wake_status_trace_comm { + uint32_t debug_flag; /* PCM_WDT_LATCH_SPARE_0 */ + uint32_t debug_flag1; /* PCM_WDT_LATCH_SPARE_1 */ + uint32_t timer_out; /* SPM_SW_RSV_6*/ + uint32_t b_sw_flag0; /* SPM_SW_RSV_7 */ + uint32_t b_sw_flag1; /* SPM_SW_RSV_7 */ + uint32_t r12; /* SPM_SW_RSV_0 */ + uint32_t r13; /* PCM_REG13_DATA */ + uint32_t req_sta0; /* SRC_REQ_STA_0 */ + uint32_t req_sta1; /* SRC_REQ_STA_1 */ + uint32_t req_sta2; /* SRC_REQ_STA_2 */ + uint32_t req_sta3; /* SRC_REQ_STA_3 */ + uint32_t req_sta4; /* SRC_REQ_STA_4 */ + uint32_t req_sta5; /* SRC_REQ_STA_5 */ + uint32_t req_sta6; /* SRC_REQ_STA_6 */ + uint32_t req_sta7; /* SRC_REQ_STA_7 */ + uint32_t req_sta8; /* SRC_REQ_STA_8 */ + uint32_t req_sta9; /* SRC_REQ_STA_9 */ + uint32_t req_sta10; /* SRC_REQ_STA_10 */ + uint32_t req_sta11; /* SRC_REQ_STA_11 */ + uint32_t req_sta12; /* SRC_REQ_STA_12 */ + uint32_t req_sta13; /* SRC_REQ_STA_13 */ + uint32_t req_sta14; /* SRC_REQ_STA_14 */ + uint32_t req_sta15; /* SRC_REQ_STA_15 */ + uint32_t req_sta16; /* SRC_REQ_STA_16 */ + uint32_t raw_sta; /* SPM_WAKEUP_STA */ + uint32_t times_h; /* Timestamp high bits */ + uint32_t times_l; /* Timestamp low bits */ + uint32_t resumetime; /* Timestamp low bits */ +}; + +struct wake_status_trace { + struct wake_status_trace_comm comm; + /* Add suspend or idle part bellow */ +}; + +struct wake_status { + struct wake_status_trace tr; + uint32_t r12_ext; /* SPM_WAKEUP_EXT_STA */ + uint32_t raw_ext_sta; /* SPM_WAKEUP_EXT_STA */ + uint32_t md32pcm_wakeup_sta; /* MD32PCM_WAKEUP_STA */ + uint32_t md32pcm_event_sta; /* MD32PCM_EVENT_STA */ + uint32_t wake_misc; /* SPM_SW_RSV_5 */ + uint32_t sw_flag0; /* SPM_SW_FLAG_0 */ + uint32_t sw_flag1; /* SPM_SW_FLAG_1 */ + uint32_t isr; /* SPM_IRQ_STA */ + uint32_t log_index; + uint32_t is_abort; +}; + +struct spm_lp_scen { + struct pcm_desc *pcmdesc; + struct pwr_ctrl *pwrctrl; + struct dbg_ctrl *dbgctrl; + struct spm_lp_stat *lpstat; +}; + +extern struct spm_lp_scen __spm_vcorefs; +typedef uint32_t u32; + +void __spm_init_pcm_register(void); /* init r0 and r7 */ +void __spm_set_power_control(const struct pwr_ctrl *pwrctrl, + uint32_t resource_usage); +void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl); +void __spm_kick_pcm_to_run(struct pwr_ctrl *pwrctrl); +void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl); +void __spm_send_cpu_wakeup_event(void); + +void __spm_get_wakeup_status(struct wake_status *wakesta, + uint32_t ext_status); +void __spm_clean_after_wakeup(void); +wake_reason_t __spm_output_wake_reason(const struct wake_status *wakesta); + +void __spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl, + const struct pwr_ctrl *src_pwr_ctrl); +void __spm_sync_vcore_dvfs_pcm_flags(uint32_t *dest_pcm_flags, + const uint32_t *src_pcm_flags); + +void __spm_set_pcm_wdt(int en); +uint32_t __spm_get_pcm_timer_val(void); +uint32_t _spm_get_wake_period(int pwake_time, wake_reason_t last_wr); +void __spm_set_fw_resume_option(struct pwr_ctrl *pwrctrl); +void __spm_ext_int_wakeup_req_clr(void); + +static inline void set_pwrctrl_pcm_flags(struct pwr_ctrl *pwrctrl, + uint32_t flags) +{ + if (pwrctrl->pcm_flags_cust == 0) + pwrctrl->pcm_flags = flags; + else + pwrctrl->pcm_flags = pwrctrl->pcm_flags_cust; +} + +static inline void set_pwrctrl_pcm_flags1(struct pwr_ctrl *pwrctrl, + uint32_t flags) +{ + if (pwrctrl->pcm_flags1_cust == 0) + pwrctrl->pcm_flags1 = flags; + else + pwrctrl->pcm_flags1 = pwrctrl->pcm_flags1_cust; +} + +void __spm_hw_s1_state_monitor(int en, uint32_t *status); + +static inline void spm_hw_s1_state_monitor_resume(void) +{ + __spm_hw_s1_state_monitor(1, NULL); +} +static inline void spm_hw_s1_state_monitor_pause(uint32_t *status) +{ + __spm_hw_s1_state_monitor(0, status); +} + +int32_t __spm_wait_spm_request_ack(uint32_t spm_resource_req, + uint32_t timeout_us); + +#endif /* MT_SPM_INTERNAL */ diff --git a/plat/mediatek/drivers/spm/rules.mk b/plat/mediatek/drivers/spm/rules.mk index b7128dba1..174d1b154 100644 --- a/plat/mediatek/drivers/spm/rules.mk +++ b/plat/mediatek/drivers/spm/rules.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2023, MediaTek Inc. All rights reserved. +# Copyright (c) 2025, MediaTek Inc. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -7,8 +7,6 @@ LOCAL_DIR := $(call GET_LOCAL_DIR) MODULE := spm -$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL))) - ifneq ($(CONFIG_MTK_SPM_VERSION),) PLAT_INCLUDES += -I${LOCAL_DIR}/$(MTK_SOC) PLAT_INCLUDES += -I${LOCAL_DIR}/version/notifier/inc @@ -17,4 +15,34 @@ SUB_RULES-y += ${LOCAL_DIR}/$(CONFIG_MTK_SPM_VERSION) $(eval $(call add_define,SPM_PLAT_IMPL)) endif +ifeq ($(CONFIG_MTK_SPM_VERSION), mt8196) +ifeq ($(CONFIG_MTK_SPM_SUPPORT), y) +ifeq ($(CONFIG_MTK_SPM_COMMON_SUPPORT), y) +include ${LOCAL_DIR}/$(CONFIG_MTK_SPM_VERSION)/plat_conf.mk +PLAT_INCLUDES += -I${LOCAL_DIR} +PLAT_INCLUDES += -I${LOCAL_DIR}/version +PLAT_INCLUDES += -I${LOCAL_DIR}/common +endif +endif + +$(eval $(call add_defined_option,CONFIG_MTK_VCOREDVFS_SUPPORT)) + +ifneq ($(CONFIG_MTK_SPM_COMMON_SUPPORT), y) +LOCAL_SRCS-${CONFIG_MTK_SPM_SUPPORT} += ${LOCAL_DIR}/mt_spm_early_init.c +endif + +ifneq ($(CONFIG_MTK_SPM_COMMON_SUPPORT), y) +LOCAL_SRCS-${CONFIG_MTK_SPM_SUPPORT} += ${LOCAL_DIR}/mt_spm_early_init.c +endif + +$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL))) + +SUB_RULES-${MTK_SPM_COMMON_DRV} += ${LOCAL_DIR}/common +SUB_RULES-${MTK_SPM_COMMON_DRV} += ${LOCAL_DIR}/version + +$(eval $(call add_defined_option,CONFIG_MTK_SPM_COMMON_SUPPORT)) +else +$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL))) +endif + $(eval $(call INCLUDE_MAKEFILE,$(SUB_RULES-y))) diff --git a/plat/mediatek/mt8196/plat_config.mk b/plat/mediatek/mt8196/plat_config.mk index 7d4309757..f45ec6478 100644 --- a/plat/mediatek/mt8196/plat_config.mk +++ b/plat/mediatek/mt8196/plat_config.mk @@ -50,6 +50,8 @@ CPU_PWR_TOPOLOGY := group_4_3_1 CPU_PM_CORE_ARCH64_ONLY := y CPU_PM_DOMAIN_CORE_ONLY := n CPU_PM_SUSPEND_NOTIFY := y +CONFIG_MTK_SPM_SUPPORT := y +CONFIG_MTK_SPM_COMMON_SUPPORT := y CPU_PM_TINYSYS_SUPPORT := y MTK_PUBEVENT_ENABLE := y CONFIG_MTK_PMIC := y