feat(mt8196): add SPM features support

When the system is in idle or suspend state, SPM will turn off some
unused system resources. This patch enables this feature to achieve
power saving.

Signed-off-by: Wenzhen Yu <wenzhen.yu@mediatek.com>
Change-Id: Ia9764b91073c4765d41fe7fcd8e4a21372c290f1
This commit is contained in:
Wenzhen Yu 2024-12-24 20:53:54 +08:00
parent e8e87683f2
commit 01ce1d5d2f
18 changed files with 4964 additions and 1 deletions

View file

@ -0,0 +1,158 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <constraints/mt_spm_rc_api.h>
#include <constraints/mt_spm_rc_internal.h>
#include <lpm_v2/mt_lpm_smc.h>
#include <mt_plat_spm_setting.h>
#include <mt_spm.h>
#include <mt_spm_common.h>
#define SPM_RC_VALID_SET(dest, src) ({ (dest) |= (src); })
#define SPM_RC_VALID_CLR(dest, src) ({ (dest) &= ~(src); })
int spm_rc_constraint_status_get(uint32_t id, uint32_t type,
uint32_t act,
enum mt_spm_rm_rc_type dest_rc_id,
struct constraint_status * const src,
struct constraint_status * const dest)
{
if (((id != MT_RM_CONSTRAINT_ID_ALL) &&
(id != dest_rc_id)) || !dest || !src)
return -1;
spm_lock_get();
switch (type) {
case CONSTRAINT_GET_ENTER_CNT:
if (id == MT_RM_CONSTRAINT_ID_ALL)
dest->enter_cnt += src->enter_cnt;
else
dest->enter_cnt = src->enter_cnt;
break;
case CONSTRAINT_GET_VALID:
dest->is_valid = src->is_valid;
break;
case CONSTRAINT_COND_BLOCK:
dest->is_cond_block = src->is_cond_block;
dest->all_pll_dump = src->all_pll_dump;
break;
case CONSTRAINT_GET_COND_BLOCK_DETAIL:
dest->cond_res = src->cond_res;
break;
case CONSTRAINT_GET_RESIDNECY:
dest->residency = src->residency;
if (act & MT_LPM_SMC_ACT_CLR)
src->residency = 0;
break;
default:
break;
}
spm_lock_release();
return 0;
}
int spm_rc_constraint_status_set(uint32_t id, uint32_t type,
uint32_t act,
enum mt_spm_rm_rc_type dest_rc_id,
struct constraint_status * const src,
struct constraint_status * const dest)
{
if (((id != MT_RM_CONSTRAINT_ID_ALL) &&
(id != dest_rc_id)) || !dest)
return -1;
spm_lock_get();
switch (type) {
case CONSTRAINT_UPDATE_VALID:
if (src) {
if (act & MT_LPM_SMC_ACT_SET)
SPM_RC_VALID_SET(dest->is_valid, src->is_valid);
else if (act & MT_LPM_SMC_ACT_CLR)
SPM_RC_VALID_CLR(dest->is_valid, src->is_valid);
}
break;
case CONSTRAINT_RESIDNECY:
if (act & MT_LPM_SMC_ACT_CLR)
dest->residency = 0;
break;
default:
break;
}
spm_lock_release();
return 0;
}
int spm_rc_constraint_valid_set(enum mt_spm_rm_rc_type id,
enum mt_spm_rm_rc_type dest_rc_id,
uint32_t valid,
struct constraint_status * const dest)
{
if (((id != MT_RM_CONSTRAINT_ID_ALL) &&
(id != dest_rc_id)) || !dest)
return -1;
spm_lock_get();
SPM_RC_VALID_SET(dest->is_valid, valid);
spm_lock_release();
return 0;
}
int spm_rc_constraint_valid_clr(enum mt_spm_rm_rc_type id,
enum mt_spm_rm_rc_type dest_rc_id,
uint32_t valid,
struct constraint_status * const dest)
{
if (((id != MT_RM_CONSTRAINT_ID_ALL) &&
(id != dest_rc_id)) || !dest)
return -1;
spm_lock_get();
SPM_RC_VALID_CLR(dest->is_valid, valid);
spm_lock_release();
return 0;
}
/*
* CIRQ will respresent interrupt which type is edge
* when gic mask. But if the 26 clk have turned off before
* then cirq won't work normally.
* So we need to set irq pending for specific wakeup source.
*/
#ifndef MTK_PLAT_CIRQ_UNSUPPORT
static void mt_spm_irq_remain_dump(struct mt_irqremain *irqs,
uint32_t irq_index,
struct wake_status *wakeup)
{
INFO("[SPM] r12=0x%08x(0x%08x), irq:%u(0x%08x) set pending\n",
wakeup->tr.comm.r12,
wakeup->md32pcm_wakeup_sta,
irqs->wakeupsrc[irq_index],
irqs->irqs[irq_index]);
}
void do_irqs_delivery(struct mt_irqremain *irqs,
struct wake_status *wakeup)
{
uint32_t idx;
if (!irqs || !wakeup)
return;
for (idx = 0; idx < irqs->count; idx++) {
if ((wakeup->tr.comm.raw_sta & irqs->wakeupsrc[idx]) ||
(wakeup->tr.comm.r12 & irqs->wakeupsrc[idx])) {
if ((irqs->wakeupsrc_cat[idx] & MT_IRQ_REMAIN_CAT_LOG))
mt_spm_irq_remain_dump(irqs, idx, wakeup);
}
}
}
#endif

View file

@ -0,0 +1,84 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_SPM_RC_API_H
#define MT_SPM_RC_API_H
#include <constraints/mt_spm_trace.h>
#include <mt_spm.h>
#include <mt_spm_constraint.h>
#include <mt_spm_internal.h>
enum mt_spm_rm_rc_type {
MT_RM_CONSTRAINT_ID_VCORE,
MT_RM_CONSTRAINT_ID_BUS26,
MT_RM_CONSTRAINT_ID_SYSPL,
MT_RM_CONSTRAINT_ID_ALL = 0xff,
};
enum mt_spm_rc_fp_type {
MT_SPM_RC_FP_INIT = 0,
MT_SPM_RC_FP_ENTER_START,
MT_SPM_RC_FP_ENTER_NOTIFY,
MT_SPM_RC_FP_ENTER_WAKE_SPM_BEFORE,
MT_SPM_RC_FP_ENTER_WAKE_SPM_AFTER,
MT_SPM_RC_FP_RESUME_START,
MT_SPM_RC_FP_RESUME_NOTIFY,
MT_SPM_RC_FP_RESUME_RESET_SPM_BEFORE,
MT_SPM_RC_FP_RESUME_BACKUP_EDGE_INT,
};
#define MT_SPM_RC_INFO(_cpu, _stateid, _rc_id) ({ \
MT_SPM_TRACE_COMMON_U32_WR(MT_SPM_TRACE_COMM_RC_INFO, \
((_cpu) << 28) | \
(((_stateid) & 0xffff) << 12) | \
((_rc_id) & 0xfff)); })
#define MT_SPM_RC_LAST_TIME(_time) ({ \
MT_SPM_TRACE_COMMON_U32_WR(MT_SPM_TRACE_COMM_RC_LAST_TIME_H, \
(uint32_t)((_time) >> 32)); \
MT_SPM_TRACE_COMMON_U32_WR(MT_SPM_TRACE_COMM_RC_LAST_TIME_L, \
(uint32_t)((_time) & 0xffffffff)); })
#define MT_SPM_RC_TAG(_cpu, _stateid, _rc_id) \
MT_SPM_RC_INFO(_cpu, _stateid, _rc_id)
#define MT_SPM_RC_FP(fp) ({ \
MT_SPM_TRACE_COMMON_U32_WR(MT_SPM_TRACE_COMM_RC_FP, fp); })
#define MT_SPM_RC_TAG_VALID(_valid) ({ \
MT_SPM_TRACE_COMMON_U32_WR(MT_SPM_TRACE_COMM_RC_VALID, _valid); })
int spm_rc_constraint_status_get(uint32_t id, uint32_t type,
uint32_t act,
enum mt_spm_rm_rc_type dest_rc_id,
struct constraint_status * const src,
struct constraint_status * const dest);
int spm_rc_constraint_status_set(uint32_t id, uint32_t type,
uint32_t act,
enum mt_spm_rm_rc_type dest_rc_id,
struct constraint_status * const src,
struct constraint_status * const dest);
int spm_rc_constraint_valid_set(enum mt_spm_rm_rc_type id,
enum mt_spm_rm_rc_type dest_rc_id,
uint32_t valid,
struct constraint_status * const dest);
int spm_rc_constraint_valid_clr(enum mt_spm_rm_rc_type id,
enum mt_spm_rm_rc_type dest_rc_id,
uint32_t valid,
struct constraint_status * const dest);
#ifdef MTK_PLAT_CIRQ_UNSUPPORT
#define do_irqs_delivery(_x, _w)
#else
void do_irqs_delivery(struct mt_irqremain *irqs,
struct wake_status *wakeup);
#endif /* MTK_PLAT_CIRQ_UNSUPPORT */
#endif /* MT_SPM_RC_API_H */

View file

@ -0,0 +1,255 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <common/debug.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/pm/mtk_pm.h>
#include <lpm_v2/mt_lp_rm.h>
#include <mt_plat_spm_setting.h>
#include <mt_spm.h>
#include <mt_spm_conservation.h>
#include <mt_spm_constraint.h>
#include <mt_spm_idle.h>
#include <mt_spm_internal.h>
#include <mt_spm_pmic_lp.h>
#include <mt_spm_reg.h>
#include <mt_spm_suspend.h>
#include <notifier/inc/mt_spm_notifier.h>
#define CONSTRAINT_BUS26M_ALLOW (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \
MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
MT_RM_CONSTRAINT_ALLOW_VCORE_LP | \
MT_RM_CONSTRAINT_ALLOW_LVTS_STATE | \
MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF)
#define CONSTRAINT_BUS26M_PCM_FLAG (SPM_FLAG_DISABLE_VCORE_DVS | \
SPM_FLAG_DISABLE_DDR_DFS | \
SPM_FLAG_DISABLE_EMI_DFS | \
SPM_FLAG_DISABLE_BUS_DFS | \
SPM_FLAG_ENABLE_AOV | \
SPM_FLAG_DISABLE_VLP_PDN | \
SPM_FLAG_SRAM_SLEEP_CTRL | \
SPM_FLAG_KEEP_CSYSPWRACK_HIGH)
#define CONSTRAINT_BUS26M_PCM_FLAG1 (SPM_FLAG1_ENABLE_ALCO_TRACE)
/*
* If sspm sram won't enter sleep voltage
* then vcore couldn't enter low power mode
*/
#if defined(MTK_PLAT_SPM_SRAM_SLP_UNSUPPORT) && SPM_SRAM_SLEEP_RC_RES_RESTRICT
#define CONSTRAINT_BUS26M_RESOURCE_REQ (MT_SPM_26M | MT_SPM_VCORE)
#else
#define CONSTRAINT_BUS26M_RESOURCE_REQ (MT_SPM_VCORE)
#endif
static uint32_t bus26m_ext_opand;
static struct mt_irqremain *refer2remain_irq;
static uint32_t cmd;
static struct constraint_status status = {
.id = MT_RM_CONSTRAINT_ID_BUS26,
.is_valid = (MT_SPM_RC_VALID_SW |
MT_SPM_RC_VALID_FW |
MT_SPM_RC_VALID_TRACE_TIME |
MT_SPM_RC_VALID_NOTIFY),
.enter_cnt = 0,
.all_pll_dump = 0,
.residency = 0,
};
int spm_bus26m_conduct(int state_id, struct spm_lp_scen *spm_lp,
uint32_t *resource_req)
{
if ((spm_lp == NULL) || (resource_req == NULL))
return -1;
struct pwr_ctrl *pwrctrl = spm_lp->pwrctrl;
pwrctrl->pcm_flags = CONSTRAINT_BUS26M_PCM_FLAG;
pwrctrl->pcm_flags1 = CONSTRAINT_BUS26M_PCM_FLAG1;
*resource_req |= CONSTRAINT_BUS26M_RESOURCE_REQ;
return 0;
}
bool spm_is_valid_rc_bus26m(uint32_t cpu, int state_id)
{
return (IS_MT_RM_RC_READY(status.is_valid) &&
!(bus26m_ext_opand & (MT_BUS26M_EXT_LP_26M_ON_MODE)));
}
int spm_update_rc_bus26m(int state_id, int type, const void *val)
{
int res = MT_RM_STATUS_OK;
uint32_t flag = *(uint32_t *)val;
if (type == PLAT_RC_UPDATE_REMAIN_IRQS) {
refer2remain_irq = (struct mt_irqremain *)val;
} else if (type == PLAT_RC_IS_FMAUDIO) {
if (flag)
bus26m_ext_opand |= MT_SPM_EX_OP_SET_IS_FM_AUDIO;
else
bus26m_ext_opand &= ~MT_SPM_EX_OP_SET_IS_FM_AUDIO;
} else if (type == PLAT_RC_IS_ADSP) {
if (flag)
bus26m_ext_opand |= MT_SPM_EX_OP_SET_IS_ADSP;
else
bus26m_ext_opand &= ~MT_SPM_EX_OP_SET_IS_ADSP;
} else if (type == PLAT_RC_IS_USB_HEADSET) {
if (flag)
bus26m_ext_opand |= MT_SPM_EX_OP_SET_IS_USB_HEADSET;
else
bus26m_ext_opand &= ~MT_SPM_EX_OP_SET_IS_USB_HEADSET;
} else if (type == PLAT_RC_STATUS) {
const struct rc_common_state *st;
st = (const struct rc_common_state *)val;
if (!st)
return 0;
if ((st->type == CONSTRAINT_UPDATE_VALID) ||
(st->type == CONSTRAINT_RESIDNECY))
spm_rc_constraint_status_set(st->id,
st->type, st->act,
MT_RM_CONSTRAINT_ID_BUS26,
st->value,
&status);
else
INFO("[%s:%d] - Unknown type: 0x%x\n",
__func__, __LINE__, st->type);
}
return res;
}
uint32_t spm_allow_rc_bus26m(int state_id)
{
return CONSTRAINT_BUS26M_ALLOW;
}
int spm_run_rc_bus26m(uint32_t cpu, int state_id)
{
uint32_t ext_op = MT_SPM_EX_OP_HW_S1_DETECT |
MT_SPM_EX_OP_NOTIFY_INFRA_OFF;
uint32_t nb_type = MT_SPM_NOTIFY_IDLE_ENTER;
MT_SPM_RC_TAG(cpu, state_id, MT_RM_CONSTRAINT_ID_BUS26);
MT_SPM_RC_TAG_VALID(status.is_valid);
MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_START);
cmd = CONSTRAINT_BUS26M_ALLOW;
if (IS_PLAT_SUSPEND_ID(state_id)) {
cmd |= (MT_RM_CONSTRAINT_ALLOW_AP_PLAT_SUSPEND |
MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND);
ext_op |= (MT_SPM_EX_OP_CLR_26M_RECORD |
MT_SPM_EX_OP_SET_WDT);
if (IS_MT_SPM_RC_NOTIFY_ENABLE(status.is_valid))
mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_SUSPEND_VCORE, 0);
} else {
if (status.is_valid & MT_SPM_RC_VALID_TRACE_TIME)
ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN;
}
#ifdef MTK_SPM_PMIC_LP_SUPPORT
do_spm_low_power(SPM_LP_ENTER, cmd);
#endif
MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_NOTIFY);
if (IS_MT_SPM_RC_NOTIFY_ENABLE(status.is_valid))
mt_spm_sspm_notify_u32(nb_type, cmd);
MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_WAKE_SPM_BEFORE);
if (IS_PLAT_SUSPEND_ID(state_id))
mt_spm_suspend_enter(state_id, ext_op,
CONSTRAINT_BUS26M_RESOURCE_REQ);
else
mt_spm_idle_generic_enter(state_id, ext_op,
spm_bus26m_conduct);
MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_WAKE_SPM_AFTER);
return 0;
}
int spm_reset_rc_bus26m(uint32_t cpu, int state_id)
{
struct wake_status *waken = NULL;
uint32_t ext_op = MT_SPM_EX_OP_HW_S1_DETECT |
MT_SPM_EX_OP_NOTIFY_INFRA_OFF;
uint32_t nb_type = MT_SPM_NOTIFY_IDLE_LEAVE;
MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_START);
if (IS_PLAT_SUSPEND_ID(state_id)) {
ext_op |= MT_SPM_EX_OP_SET_WDT;
} else {
if (status.is_valid & MT_SPM_RC_VALID_TRACE_TIME)
ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN;
if (spm_unlikely(status.is_valid &
MT_SPM_RC_VALID_TRACE_EVENT))
ext_op |= MT_SPM_EX_OP_TRACE_LP;
}
#ifdef MTK_SPM_PMIC_LP_SUPPORT
do_spm_low_power(SPM_LP_RESUME, cmd);
#endif
MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_NOTIFY);
if (IS_MT_SPM_RC_NOTIFY_ENABLE(status.is_valid))
mt_spm_sspm_notify_u32(nb_type, 0);
MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_RESET_SPM_BEFORE);
if (IS_PLAT_SUSPEND_ID(state_id)) {
mt_spm_suspend_resume(state_id, ext_op, &waken);
bus26m_ext_opand = 0;
} else {
mt_spm_idle_generic_resume(state_id, ext_op, &waken, NULL);
status.enter_cnt++;
if (spm_unlikely(status.is_valid & MT_SPM_RC_VALID_RESIDNECY))
status.residency += waken ?
waken->tr.comm.timer_out : 0;
}
MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_BACKUP_EDGE_INT);
do_irqs_delivery(refer2remain_irq, waken);
MT_SPM_RC_FP(MT_SPM_RC_FP_INIT);
return 0;
}
int spm_get_status_rc_bus26m(uint32_t type, void *priv)
{
int ret = MT_RM_STATUS_OK;
if (type == PLAT_RC_STATUS) {
struct rc_common_state *st = (struct rc_common_state *)priv;
if (!st)
return MT_RM_STATUS_BAD;
ret = spm_rc_constraint_status_get(st->id, st->type,
st->act,
MT_RM_CONSTRAINT_ID_BUS26,
&status,
st->value);
if (!ret && (st->id != MT_RM_CONSTRAINT_ID_ALL))
ret = MT_RM_STATUS_STOP;
}
return ret;
}

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_SPM_RC_INTERNAL_H
#define MT_SPM_RC_INTERNAL_H
#include <sleep_def.h>
#define SPM_SRAM_SLEEP_DEFAULT_FLAG (SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP)
#ifdef MTK_PLAT_SPM_SRAM_SLP_UNSUPPORT
#define SPM_FLAG_SRAM_SLEEP_CTRL (SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP)
#else
#define SPM_FLAG_SRAM_SLEEP_CTRL (SPM_SRAM_SLEEP_DEFAULT_FLAG)
#endif
#define SPM_SRAM_SLEEP_RC_RES_RESTRICT 0
#define SPM_RC_UPDATE_COND_ID_MASK 0xffff
#define SPM_RC_UPDATE_COND_RC_ID_MASK 0xffff
#define SPM_RC_UPDATE_COND_RC_ID_SHIFT 16
#define SPM_RC_UPDATE_COND_RC_ID_GET(val) \
(((val) >> SPM_RC_UPDATE_COND_RC_ID_SHIFT) & \
SPM_RC_UPDATE_COND_RC_ID_MASK)
#define SPM_RC_UPDATE_COND_ID_GET(val) \
((val) & SPM_RC_UPDATE_COND_ID_MASK)
/* CPU buck/ldo constraint function */
int spm_is_valid_rc_cpu_buck_ldo(int cpu, int state_id);
int spm_update_rc_cpu_buck_ldo(int state_id, int type,
const void *val);
uint32_t spm_allow_rc_cpu_buck_ldo(int state_id);
int spm_run_rc_cpu_buck_ldo(int cpu, int state_id);
int spm_reset_rc_cpu_buck_ldo(int cpu, int state_id);
int spm_get_status_rc_cpu_buck_ldo(uint32_t type, void *priv);
/* SPM resource syspll constraint function */
bool spm_is_valid_rc_syspll(uint32_t cpu, int state_id);
int spm_update_rc_syspll(int state_id, int type, const void *val);
uint32_t spm_allow_rc_syspll(int state_id);
int spm_run_rc_syspll(uint32_t cpu, int state_id);
int spm_reset_rc_syspll(uint32_t cpu, int state_id);
int spm_get_status_rc_syspll(uint32_t type, void *priv);
/* SPM resource bus26m constraint function */
bool spm_is_valid_rc_bus26m(uint32_t cpu, int state_id);
int spm_update_rc_bus26m(int state_id, int type, const void *val);
uint32_t spm_allow_rc_bus26m(int state_id);
int spm_run_rc_bus26m(uint32_t cpu, int state_id);
int spm_reset_rc_bus26m(uint32_t cpu, int state_id);
int spm_get_status_rc_bus26m(uint32_t type, void *priv);
/* SPM resource vcore constraint function */
bool spm_is_valid_rc_vcore(uint32_t cpu, int state_id);
int spm_update_rc_vcore(int state_id, int type, const void *val);
uint32_t spm_allow_rc_vcore(int state_id);
int spm_run_rc_vcore(uint32_t cpu, int state_id);
int spm_reset_rc_vcore(uint32_t cpu, int state_id);
int spm_get_status_rc_vcore(uint32_t type, void *priv);
#endif /* MT_SPM_RC_INTERNAL_H */

View file

@ -0,0 +1,260 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <common/debug.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/pm/mtk_pm.h>
#include <lpm_v2/mt_lp_api.h>
#include <lpm_v2/mt_lp_rm.h>
#include <mt_plat_spm_setting.h>
#include <mt_spm.h>
#include <mt_spm_conservation.h>
#include <mt_spm_constraint.h>
#include <mt_spm_idle.h>
#include <mt_spm_internal.h>
#include <mt_spm_pmic_lp.h>
#include <mt_spm_reg.h>
#include <mt_spm_suspend.h>
#include <notifier/inc/mt_spm_notifier.h>
#define CONSTRAINT_SYSPLL_ALLOW (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \
MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
MT_RM_CONSTRAINT_ALLOW_VCORE_LP | \
MT_RM_CONSTRAINT_ALLOW_LVTS_STATE)
#define CONSTRAINT_SYSPLL_PCM_FLAG (SPM_FLAG_DISABLE_VCORE_DVS | \
SPM_FLAG_DISABLE_DDR_DFS | \
SPM_FLAG_DISABLE_EMI_DFS | \
SPM_FLAG_DISABLE_BUS_DFS | \
SPM_FLAG_ENABLE_AOV | \
SPM_FLAG_DISABLE_VLP_PDN | \
SPM_FLAG_SRAM_SLEEP_CTRL | \
SPM_FLAG_KEEP_CSYSPWRACK_HIGH)
#define CONSTRAINT_SYSPLL_PCM_FLAG1 (SPM_FLAG1_ENABLE_ALCO_TRACE)
#define CONSTRAINT_SYSPLL_RESOURCE_REQ (MT_SPM_26M | \
MT_SPM_VCORE | MT_SPM_INFRA)
#define CHECK_VAL(val, sys_state) \
((val) ? !!(*((uint32_t *)(val)) == (sys_state)) : 0)
static uint32_t cmd;
static struct constraint_status status = {
.id = MT_RM_CONSTRAINT_ID_SYSPL,
.is_valid = (MT_SPM_RC_VALID_SW |
MT_SPM_RC_VALID_FW |
MT_SPM_RC_VALID_NOTIFY),
.enter_cnt = 0,
.residency = 0,
};
int spm_syspll_conduct(int state_id, struct spm_lp_scen *spm_lp,
uint32_t *resource_req)
{
if ((spm_lp == NULL) || (resource_req == NULL))
return -1;
struct pwr_ctrl *pwrctrl = spm_lp->pwrctrl;
pwrctrl->pcm_flags = CONSTRAINT_SYSPLL_PCM_FLAG;
pwrctrl->pcm_flags1 = CONSTRAINT_SYSPLL_PCM_FLAG1;
*resource_req |= CONSTRAINT_SYSPLL_RESOURCE_REQ;
return 0;
}
bool spm_is_valid_rc_syspll(uint32_t cpu, int state_id)
{
return IS_MT_RM_RC_READY(status.is_valid);
}
int spm_update_rc_syspll(int state_id, int type, const void *val)
{
int res = MT_RM_STATUS_OK;
if (type == PLAT_RC_CLKBUF_STATUS) {
bool is_flight = CHECK_VAL(val, FLIGHT_MODE_ON);
if (is_flight)
spm_rc_constraint_valid_set(MT_RM_CONSTRAINT_ID_SYSPL,
MT_RM_CONSTRAINT_ID_SYSPL,
MT_SPM_RC_VALID_FLIGHTMODE,
&status);
else
spm_rc_constraint_valid_clr(MT_RM_CONSTRAINT_ID_SYSPL,
MT_RM_CONSTRAINT_ID_SYSPL,
MT_SPM_RC_VALID_FLIGHTMODE,
&status);
} else if (type == PLAT_RC_UFS_STATUS) {
uint32_t is_ufs_h8 = CHECK_VAL(val, UFS_REF_CLK_OFF);
if (is_ufs_h8)
spm_rc_constraint_valid_set(MT_RM_CONSTRAINT_ID_SYSPL,
MT_RM_CONSTRAINT_ID_SYSPL,
MT_SPM_RC_VALID_UFS_H8,
&status);
else
spm_rc_constraint_valid_clr(MT_RM_CONSTRAINT_ID_SYSPL,
MT_RM_CONSTRAINT_ID_SYSPL,
MT_SPM_RC_VALID_UFS_H8,
&status);
} else if (type == PLAT_RC_STATUS) {
const struct rc_common_state *st;
st = (const struct rc_common_state *)val;
if (!st)
return 0;
if ((st->type == CONSTRAINT_UPDATE_VALID) ||
(st->type == CONSTRAINT_RESIDNECY))
spm_rc_constraint_status_set(st->id, st->type,
st->act,
MT_RM_CONSTRAINT_ID_SYSPL,
st->value,
&status);
else
INFO("[%s:%d] - Unknown type: 0x%x\n",
__func__, __LINE__, st->type);
}
return res;
}
uint32_t spm_allow_rc_syspll(int state_id)
{
return CONSTRAINT_SYSPLL_ALLOW;
}
int spm_run_rc_syspll(uint32_t cpu, int state_id)
{
uint32_t ext_op = MT_SPM_EX_OP_HW_S1_DETECT |
MT_SPM_EX_OP_NOTIFY_INFRA_OFF;
uint32_t nb_type = MT_SPM_NOTIFY_IDLE_ENTER;
MT_SPM_RC_TAG(cpu, state_id, MT_RM_CONSTRAINT_ID_SYSPL);
MT_SPM_RC_TAG_VALID(status.is_valid);
MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_START);
cmd = CONSTRAINT_SYSPLL_ALLOW;
if (IS_PLAT_SUSPEND_ID(state_id)) {
cmd |= MT_RM_CONSTRAINT_ALLOW_AP_PLAT_SUSPEND;
ext_op |= (MT_SPM_EX_OP_CLR_26M_RECORD |
MT_SPM_EX_OP_SET_WDT);
} else {
if (status.is_valid & MT_SPM_RC_VALID_TRACE_TIME)
ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN;
if (!IS_MT_PLAT_PWR_STATE(state_id,
MT_PLAT_PWR_STATE_SYSTEM_PLL)) {
nb_type = MT_SPM_NOTIFY_IDLE_ENTER;
ext_op &= ~MT_SPM_EX_OP_NOTIFY_INFRA_OFF;
}
}
#ifdef MTK_SPM_PMIC_LP_SUPPORT
do_spm_low_power(SPM_LP_ENTER, cmd);
#endif
MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_NOTIFY);
if (IS_MT_SPM_RC_NOTIFY_ENABLE(status.is_valid))
mt_spm_sspm_notify_u32(nb_type, cmd);
MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_WAKE_SPM_BEFORE);
if (IS_PLAT_SUSPEND_ID(state_id))
mt_spm_suspend_enter(state_id, ext_op,
CONSTRAINT_SYSPLL_RESOURCE_REQ);
else
mt_spm_idle_generic_enter(state_id, ext_op, spm_syspll_conduct);
MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_WAKE_SPM_AFTER);
return 0;
}
int spm_reset_rc_syspll(uint32_t cpu, int state_id)
{
uint32_t ext_op = MT_SPM_EX_OP_HW_S1_DETECT |
MT_SPM_EX_OP_NOTIFY_INFRA_OFF;
uint32_t nb_type = MT_SPM_NOTIFY_IDLE_LEAVE;
MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_START);
if (IS_PLAT_SUSPEND_ID(state_id)) {
ext_op |= (MT_SPM_EX_OP_SET_WDT);
} else {
if (status.is_valid & MT_SPM_RC_VALID_TRACE_TIME)
ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN;
if (spm_unlikely(status.is_valid &
MT_SPM_RC_VALID_TRACE_EVENT))
ext_op |= MT_SPM_EX_OP_TRACE_LP;
if (!IS_MT_PLAT_PWR_STATE(state_id,
MT_PLAT_PWR_STATE_SYSTEM_PLL)) {
nb_type = MT_SPM_NOTIFY_IDLE_LEAVE;
ext_op &= ~MT_SPM_EX_OP_NOTIFY_INFRA_OFF;
}
}
#ifdef MTK_SPM_PMIC_LP_SUPPORT
do_spm_low_power(SPM_LP_RESUME, cmd);
#endif
MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_NOTIFY);
if (IS_MT_SPM_RC_NOTIFY_ENABLE(status.is_valid))
mt_spm_sspm_notify_u32(nb_type, cmd);
MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_RESET_SPM_BEFORE);
if (IS_PLAT_SUSPEND_ID(state_id))
mt_spm_suspend_resume(state_id, ext_op, NULL);
else {
struct wake_status *waken = NULL;
mt_spm_idle_generic_resume(state_id, ext_op, &waken, NULL);
status.enter_cnt++;
if (spm_unlikely(status.is_valid & MT_SPM_RC_VALID_RESIDNECY))
status.residency += waken ?
waken->tr.comm.timer_out : 0;
}
MT_SPM_RC_FP(MT_SPM_RC_FP_INIT);
return 0;
}
int spm_get_status_rc_syspll(uint32_t type, void *priv)
{
int ret = MT_RM_STATUS_OK;
if (type == PLAT_RC_STATUS) {
int res = 0;
struct rc_common_state *st = (struct rc_common_state *)priv;
if (!st)
return MT_RM_STATUS_BAD;
res = spm_rc_constraint_status_get(st->id, st->type,
st->act,
MT_RM_CONSTRAINT_ID_SYSPL,
&status,
st->value);
if (!res && (st->id != MT_RM_CONSTRAINT_ID_ALL))
ret = MT_RM_STATUS_STOP;
}
return ret;
}

View file

@ -0,0 +1,266 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <common/debug.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/pm/mtk_pm.h>
#include <lpm_v2/mt_lp_rm.h>
#include <lpm_v2/mt_lp_rqm.h>
#include <mt_plat_spm_setting.h>
#include <mt_spm.h>
#include <mt_spm_conservation.h>
#include <mt_spm_constraint.h>
#include <mt_spm_idle.h>
#include <mt_spm_internal.h>
#include <mt_spm_pmic_lp.h>
#include <mt_spm_reg.h>
#include <mt_spm_suspend.h>
#include <notifier/inc/mt_spm_notifier.h>
#define ERROW_TEST
#define CONSTRAINT_VCORE_ALLOW (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \
MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
MT_RM_CONSTRAINT_ALLOW_VCORE_LP | \
MT_RM_CONSTRAINT_ALLOW_LVTS_STATE | \
MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF | \
MT_RM_CONSTRAINT_ALLOW_VCORE_OFF)
#define CONSTRAINT_VCORE_PCM_FLAG (SPM_FLAG_DISABLE_VCORE_DVS | \
SPM_FLAG_DISABLE_DDR_DFS | \
SPM_FLAG_DISABLE_EMI_DFS | \
SPM_FLAG_DISABLE_BUS_DFS | \
SPM_FLAG_DISABLE_VLP_PDN | \
SPM_FLAG_DISABLE_BUS_DFS | \
SPM_FLAG_ENABLE_AOV | \
SPM_FLAG_SRAM_SLEEP_CTRL)
#define CONSTRAINT_VCORE_PCM_FLAG1 (SPM_FLAG1_ENABLE_ALCO_TRACE)
#if defined(MTK_PLAT_SPM_SRAM_SLP_UNSUPPORT) && SPM_SRAM_SLEEP_RC_RES_RESTRICT
#define CONSTRAINT_VCORE_RESOURCE_REQ (MT_SPM_26M | MT_SPM_VCORE)
#else
#define CONSTRAINT_VCORE_RESOURCE_REQ 0
#endif
static uint32_t vcore_ext_opand;
static struct mt_irqremain *refer2remain_irq;
static uint32_t cmd;
static struct constraint_status status = {
.id = MT_RM_CONSTRAINT_ID_VCORE,
.is_valid = (MT_SPM_RC_VALID_SW |
MT_SPM_RC_VALID_FW |
MT_SPM_RC_VALID_TRACE_TIME |
MT_SPM_RC_VALID_NOTIFY),
.enter_cnt = 0,
.all_pll_dump = 0,
.residency = 0,
};
int spm_vcore_conduct(int state_id, struct spm_lp_scen *spm_lp,
uint32_t *resource_req)
{
if ((spm_lp == NULL) || (resource_req == NULL))
return -1;
struct pwr_ctrl *pwrctrl = spm_lp->pwrctrl;
pwrctrl->pcm_flags = CONSTRAINT_VCORE_PCM_FLAG;
pwrctrl->pcm_flags1 = CONSTRAINT_VCORE_PCM_FLAG1;
*resource_req |= CONSTRAINT_VCORE_RESOURCE_REQ;
return 0;
}
bool spm_is_valid_rc_vcore(uint32_t cpu, int state_id)
{
uint32_t vcore_ext = vcore_ext_opand &
(MT_VCORE_EXT_LP_VCORE_ON_MODE);
return (IS_MT_RM_RC_READY(status.is_valid) &&
IS_MT_PLAT_PWR_STATE(state_id,
MT_PLAT_PWR_STATE_SYSTEM_VCORE) &&
!vcore_ext);
}
int spm_update_rc_vcore(int state_id, int type, const void *val)
{
int res = MT_RM_STATUS_OK;
uint32_t flag = *(uint32_t *)val;
if (type == PLAT_RC_UPDATE_REMAIN_IRQS) {
refer2remain_irq = (struct mt_irqremain *)val;
} else if (type == PLAT_RC_IS_FMAUDIO) {
if (flag)
vcore_ext_opand |= MT_SPM_EX_OP_SET_IS_FM_AUDIO;
else
vcore_ext_opand &= ~MT_SPM_EX_OP_SET_IS_FM_AUDIO;
} else if (type == PLAT_RC_IS_ADSP) {
if (flag)
vcore_ext_opand |= MT_SPM_EX_OP_SET_IS_ADSP;
else
vcore_ext_opand &= ~MT_SPM_EX_OP_SET_IS_ADSP;
} else if (type == PLAT_RC_IS_USB_HEADSET) {
if (flag)
vcore_ext_opand |= MT_SPM_EX_OP_SET_IS_USB_HEADSET;
else
vcore_ext_opand &= ~MT_SPM_EX_OP_SET_IS_USB_HEADSET;
} else if (type == PLAT_RC_STATUS) {
const struct rc_common_state *st;
st = (const struct rc_common_state *)val;
if (!st)
return -1;
if ((st->type == CONSTRAINT_UPDATE_VALID) ||
(st->type == CONSTRAINT_RESIDNECY))
spm_rc_constraint_status_set(st->id,
st->type, st->act,
MT_RM_CONSTRAINT_ID_VCORE,
st->value,
&status);
else
INFO("[%s:%d] - Unknown type: 0x%x\n",
__func__, __LINE__, st->type);
}
return res;
}
uint32_t spm_allow_rc_vcore(int state_id)
{
return CONSTRAINT_VCORE_ALLOW;
}
int spm_run_rc_vcore(uint32_t cpu, int state_id)
{
uint32_t ext_op = (MT_SPM_EX_OP_HW_S1_DETECT |
MT_SPM_EX_OP_DEVICES_SAVE |
MT_SPM_EX_OP_TRACE_TIMESTAMP_EN |
MT_SPM_EX_OP_NOTIFY_INFRA_OFF);
uint32_t spm_lp_notify_mode;
MT_SPM_RC_TAG(cpu, state_id, MT_RM_CONSTRAINT_ID_VCORE);
MT_SPM_RC_TAG_VALID(status.is_valid);
MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_START);
cmd = CONSTRAINT_VCORE_ALLOW | MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND;
spm_lp_notify_mode = MT_SPM_NOTIFY_LP_ENTER;
if (IS_PLAT_SUSPEND_ID(state_id)) {
cmd |= (MT_RM_CONSTRAINT_ALLOW_AP_PLAT_SUSPEND);
ext_op |= (MT_SPM_EX_OP_CLR_26M_RECORD |
MT_SPM_EX_OP_SET_WDT);
if (IS_MT_SPM_RC_NOTIFY_ENABLE(status.is_valid))
mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_SUSPEND_VCORE, 0);
} else {
if (!(status.is_valid & MT_SPM_RC_VALID_TRACE_TIME))
ext_op &= ~MT_SPM_EX_OP_TRACE_TIMESTAMP_EN;
}
#ifdef MTK_SPM_PMIC_LP_SUPPORT
do_spm_low_power(SPM_LP_ENTER, cmd);
#endif
MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_NOTIFY);
if (IS_MT_SPM_RC_NOTIFY_ENABLE(status.is_valid))
mt_spm_sspm_notify_u32(spm_lp_notify_mode, cmd);
MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_WAKE_SPM_BEFORE);
if (IS_PLAT_SUSPEND_ID(state_id))
mt_spm_suspend_enter(state_id, ext_op, 0);
else
mt_spm_idle_generic_enter(state_id, ext_op,
spm_vcore_conduct);
MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_WAKE_SPM_AFTER);
return 0;
}
int spm_reset_rc_vcore(uint32_t cpu, int state_id)
{
struct wake_status *waken = NULL;
uint32_t ext_op = (MT_SPM_EX_OP_HW_S1_DETECT |
MT_SPM_EX_OP_DEVICES_SAVE |
MT_SPM_EX_OP_TRACE_LP |
MT_SPM_EX_OP_NOTIFY_INFRA_OFF);
uint32_t spm_lp_notify_mode;
MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_START);
spm_lp_notify_mode = MT_SPM_NOTIFY_LP_LEAVE;
if (IS_PLAT_SUSPEND_ID(state_id)) {
ext_op |= MT_SPM_EX_OP_SET_WDT;
} else {
if (status.is_valid & MT_SPM_RC_VALID_TRACE_TIME)
ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN;
if (spm_unlikely(!(status.is_valid &
MT_SPM_RC_VALID_TRACE_EVENT)))
ext_op &= ~MT_SPM_EX_OP_TRACE_LP;
}
#ifdef MTK_SPM_PMIC_LP_SUPPORT
do_spm_low_power(SPM_LP_RESUME, cmd);
#endif
MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_NOTIFY);
if (IS_MT_SPM_RC_NOTIFY_ENABLE(status.is_valid))
mt_spm_sspm_notify_u32(spm_lp_notify_mode, 0);
MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_RESET_SPM_BEFORE);
if (IS_PLAT_SUSPEND_ID(state_id)) {
mt_spm_suspend_resume(state_id, ext_op, &waken);
vcore_ext_opand = 0;
} else {
mt_spm_idle_generic_resume(state_id, ext_op, &waken, NULL);
status.enter_cnt++;
if (spm_unlikely(status.is_valid & MT_SPM_RC_VALID_RESIDNECY))
status.residency += waken ?
waken->tr.comm.timer_out : 0;
}
MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_BACKUP_EDGE_INT);
do_irqs_delivery(refer2remain_irq, waken);
MT_SPM_RC_FP(MT_SPM_RC_FP_INIT);
return 0;
}
int spm_get_status_rc_vcore(uint32_t type, void *priv)
{
int ret = MT_RM_STATUS_OK;
if (type == PLAT_RC_STATUS) {
struct rc_common_state *st = (struct rc_common_state *)priv;
if (!st)
return MT_RM_STATUS_BAD;
ret = spm_rc_constraint_status_get(st->id, st->type,
st->act,
MT_RM_CONSTRAINT_ID_VCORE,
&status,
st->value);
if (!ret && (st->id != MT_RM_CONSTRAINT_ID_ALL))
ret = MT_RM_STATUS_STOP;
}
return ret;
}

View file

@ -0,0 +1,157 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_SPM_TRACE_H
#define MT_SPM_TRACE_H
#include <lib/mmio.h>
#include <platform_def.h>
enum mt_spm_sysram_type {
MT_SPM_SYSRAM_COMMON,
MT_SPM_SYSRAM_SUSPEND,
MT_SPM_SYSRAM_LP,
};
/* SPM trace common type */
enum mt_spm_trace_common_type {
MT_SPM_TRACE_COMM_HAED,
MT_SPM_TRACE_COMM_FP,
MT_SPM_TRACE_COMM_RC_LAST_TIME_H,
MT_SPM_TRACE_COMM_RC_LAST_TIME_L,
MT_SPM_TRACE_COMM_RC_INFO,
MT_SPM_TRACE_COMM_RC_FP,
MT_SPM_TRACE_COMM_RC_VALID,
};
/* SPM trace suspend type */
enum mt_spm_trace_suspend_type {
MT_SPM_TRACE_SUSPEND_WAKE_SRC,
};
/*
* SPM sram usage with mcdi sram
* start offset : 0x500
*/
#define MT_SPM_SYSRAM_BASE (MTK_LPM_SRAM_BASE + 0x500)
#define MT_SPM_SYSRAM_COMM_BASE MT_SPM_SYSRAM_BASE
#define MT_SPM_SYSRAM_COMM_SZ 0x20
#define MT_SPM_SYSRAM_SUSPEND_BASE \
(MT_SPM_SYSRAM_BASE + MT_SPM_SYSRAM_COMM_SZ)
#define MT_SPM_SYSRAM_SUSPEND_SZ 0xe0
#define MT_SPM_SYSRAM_LP_BASE \
(MT_SPM_SYSRAM_SUSPEND_BASE + MT_SPM_SYSRAM_SUSPEND_SZ)
#define MT_SPM_SYSRAM_SLOT(slot) ((slot) << 2u)
#ifndef MTK_PLAT_SPM_TRACE_UNSUPPORT
#define MT_SPM_SYSRAM_W(_s, type, val, _sz) \
mt_spm_sysram_write(_s, type, val, _sz)
#define MT_SPM_SYSRAM_R_U32(addr, val) ({ \
unsigned int *r_val = (unsigned int *)val; \
if (r_val) \
*r_val = mmio_read_32(addr); })
#define MT_SPM_SYSRAM_R(_s, type, val) \
mt_spm_sysram_read(_s, type, val)
/* SPM trace common */
#define MT_SPM_TRACE_INIT(_magic) ({ \
mt_spm_sysram_init(_magic); })
#define MT_SPM_TRACE_COMMON_U32_WR(_type, _val) ({ \
mmio_write_32((MT_SPM_SYSRAM_COMM_BASE + \
MT_SPM_SYSRAM_SLOT(_type)), _val); })
#define MT_SPM_TRACE_COMMON_WR(_type, val, _sz) ({ \
int ret = MT_SPM_SYSRAM_W(MT_SPM_SYSRAM_COMMON, \
_type, val, _sz); ret; })
#define MT_SPM_TRACE_COMMON_U32_RD(_type, _val) ({ \
MT_SPM_SYSRAM_R_U32((MT_SPM_SYSRAM_COMM_BASE + \
MT_SPM_SYSRAM_SLOT(_type)), _val); })
#define MT_SPM_TRACE_COMMON_RD(_type, _val) ({ \
int ret = MT_SPM_SYSRAM_R(MT_SPM_SYSRAM_COMMON, \
_type, _val); ret; })
/* SPM trace suspend */
#define MT_SPM_TRACE_SUSPEND_U32_WR(_type, _val) ({ \
mmio_write_32((MT_SPM_SYSRAM_SUSPEND_BASE + \
MT_SPM_SYSRAM_SLOT(_type)), _val); })
#define MT_SPM_TRACE_SUSPEND_WR(_type, _val, _sz) ({ \
int ret = MT_SPM_SYSRAM_W(MT_SPM_SYSRAM_SUSPEND, \
_type, _val, _sz); ret; })
#define MT_SPM_TRACE_SUSPEND_U32_RD(_type, _val) ({\
MT_SPM_SYSRAM_R_U32((MT_SPM_SYSRAM_SUSPEND_BASE + \
MT_SPM_SYSRAM_SLOT(_type)), _val); })
#define MT_SPM_TRACE_SUSPEND_RD(_type, _val) ({ \
int ret = MT_SPM_SYSRAM_R(MT_SPM_SYSRAM_SUSPEND, \
_type, _val); ret; })
/* SPM trace low power */
#define MT_SPM_TRACE_LP_U32_WR(_type, _val) ({ \
mmio_write_32((MT_SPM_SYSRAM_LP_BASE + \
MT_SPM_SYSRAM_SLOT(_type)), _val); })
#define MT_SPM_TRACE_LP_WR(_type, _val, _sz) ({ \
int ret = MT_SPM_SYSRAM_W(MT_SPM_SYSRAM_LP, \
_type, _val, _sz); ret; })
#define MT_SPM_TRACE_LP_U32_RD(_type, _val) ({ \
MT_SPM_SYSRAM_R_U32((MT_SPM_SYSRAM_LP_BASE + \
MT_SPM_SYSRAM_SLOT(_type)), _val); })
#define MT_SPM_TRACE_LP_RD(_type, _val) ({ \
int ret = MT_SPM_SYSRAM_R(MT_SPM_SYSRAM_LP, \
_type, _val); ret; })
#define MT_SPM_TRACE_LP_RINGBUF(_pval, _sz) ({ \
int ret = mt_spm_sysram_lp_ringbuf_add(_pval, _sz); ret; })
int mt_spm_sysram_lp_ringbuf_add(const void *val, unsigned int sz);
int mt_spm_sysram_write(int section, int type, const void *val,
unsigned int sz);
int mt_spm_sysram_read(int section, int type, void *val);
int mt_spm_sysram_init(unsigned int magic);
#else
/* SPM trace common */
#define MT_SPM_TRACE_INIT(_magic)
#define MT_SPM_TRACE_COMMON_U32_WR(type, val)
#define MT_SPM_TRACE_COMMON_WR(val)
#define MT_SPM_TRACE_COMMON_U32_RD(type, val)
#define MT_SPM_TRACE_COMMON_RD(val)
/* SPM trace suspend */
#define MT_SPM_TRACE_SUSPEND_U32_WR(type, val)
#define MT_SPM_TRACE_SUSPEND_WR(val)
#define MT_SPM_TRACE_SUSPEND_U32_RD(type, val)
#define MT_SPM_TRACE_SUSPEND_RD(val)
/* SPM trace low power */
#define MT_SPM_TRACE_LP_U32_WR(type, val)
#define MT_SPM_TRACE_LP_WR(val)
#define MT_SPM_TRACE_LP_U32_RD(type, val)
#define MT_SPM_TRACE_LP_RD(val)
#define MT_SPM_TRACE_LP_RINGBUF(pval, sz)
#define mt_spm_sysram_lp_ringbuf_add(_val, _sz)
#define mt_spm_sysram_write(_s, _type, _val, _sz)
#define mt_spm_sysram_read(_s, _type, _val)
#define mt_spm_sysram_init(_magic)
#endif
#endif /* MT_SPM_TRACE_H */

View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdbool.h>
#include <lib/mmio.h>
#include <platform_def.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>
/*
* BIT Operation
*/
#define CMD_DATA(h, l, v) ((GENMASK(h, l) & ((v) << (l))))
#define VOLT_DATA(v) CMD_DATA(7, 0, VOLT_TO_PMIC_VAL(v))
/*
* PMIC_WRAP
*/
#define VCORE_BASE_UV 0 /* PMIC MT6316 */
#define VOLT_TO_PMIC_VAL(volt) (((volt) - VCORE_BASE_UV + 500 - 1) / 500)
#define PMIC_VAL_TO_VOLT(pmic) (((pmic) * 500) + VCORE_BASE_UV)
#define NR_PMIC_WRAP_CMD NR_IDX_ALL
#define MAX_RETRY_COUNT 100
#define SPM_DATA_SHIFT 16
/* MT6316 */
#define MT6316_TOP_VRCTL_VOSEL_VBUCK1 0x1448
#define MT6316_VCORE_VBUCK1_ON 0x1441
#define MT6316_VCORE_VBUCK1_OFF 0x1442
static struct pmic_wrap_cmd_setting cmd_table[NR_PMIC_WRAP_CMD] = {
{SPM_PWRAP_CMD0, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(57500)},
{SPM_PWRAP_CMD1, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(57500)},
{SPM_PWRAP_CMD2, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(60000)},
{SPM_PWRAP_CMD3, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(65000)},
{SPM_PWRAP_CMD4, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(72500)},
{SPM_PWRAP_CMD5, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(72500)},
{SPM_PWRAP_CMD6, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(82500)},
{SPM_PWRAP_CMD7, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(87500)},
{SPM_PWRAP_CMD8, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(87500)},
{SPM_PWRAP_CMD9, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(57500)},
{SPM_PWRAP_CMD10, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(60000)},
{SPM_PWRAP_CMD11, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(65000)},
{SPM_PWRAP_CMD12, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(72500)},
{SPM_PWRAP_CMD13, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(82500)},
{SPM_PWRAP_CMD14, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(87500)},
{SPM_PWRAP_CMD15, MT6316_VCORE_VBUCK1_ON, 1},
{SPM_PWRAP_CMD16, MT6316_VCORE_VBUCK1_OFF, 1},
{SPM_PWRAP_CMD17, MT6316_TOP_VRCTL_VOSEL_VBUCK1, VOLT_DATA(75000)},
{SPM_PWRAP_CMD18, 0, 0},
{SPM_PWRAP_CMD19, 0, 0},
{SPM_PWRAP_CMD20, 0, 0},
{SPM_PWRAP_CMD21, 0, 0},
{SPM_PWRAP_CMD22, 0, 0},
{SPM_PWRAP_CMD23, 0, 0},
{SPM_PWRAP_CMD24, 0, 0},
{SPM_PWRAP_CMD25, 0, 0},
{SPM_PWRAP_CMD26, 0, 0},
{SPM_PWRAP_CMD27, 0, 0},
{SPM_PWRAP_CMD28, 0, 0},
{SPM_PWRAP_CMD29, 0, 0},
{SPM_PWRAP_CMD30, 0, 0},
{SPM_PWRAP_CMD31, 0, 0},
};
static struct pmic_wrap_phase_setting phase_table[NR_PMIC_WRAP_PHASE] = {
{
.cmd = cmd_table,
.nr_idx = NR_IDX_ALL,
},
};
static struct pmic_wrap_setting pmic_wrap_table = {
.phase = phase_table,
.phase_nr_idx = NR_PMIC_WRAP_PHASE,
};
void plat_spm_pmic_wrap_init(void)
{
mt_spm_pmic_wrap_set_table(&pmic_wrap_table);
mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_ALLINONE);
}
#define PMIC_WRAP_REG_1 0x3E8
#define PMIC_WRAP_REG_STEP 0x4
#define PMIC_WRAP_REG_2 0xC28
#define PMIC_WRAP_REG_3 0xF54
#ifndef MTK_PLAT_SPM_PMIC_WRAP_DUMP_UNSUPPORT
void mt_spm_dump_pmic_warp_reg(void)
{
uint32_t temp;
uint32_t i;
for (i = 0; i <= PMIC_WRAP_REG_1; i += PMIC_WRAP_REG_STEP) {
temp = mmio_read_32(PMIC_WRAP_BASE + i);
}
for (i = 0xC00; i <= PMIC_WRAP_REG_2; i += PMIC_WRAP_REG_STEP) {
temp = mmio_read_32(PMIC_WRAP_BASE + i);
}
for (i = 0xF00; i <= PMIC_WRAP_REG_3; i += PMIC_WRAP_REG_STEP) {
temp = mmio_read_32(PMIC_WRAP_BASE + i);
}
}
#endif

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_PLAT_SPM_SETTING_H
#define MT_PLAT_SPM_SETTING_H
#include <sleep_def.h>
enum plat_spm_cond {
PLAT_SPM_COND_MAX = 0,
};
enum pmic_wrap_phase_id {
PMIC_WRAP_PHASE_ALLINONE,
NR_PMIC_WRAP_PHASE,
};
/* IDX mapping */
enum {
CMD_0,
CMD_1,
CMD_2,
CMD_3,
CMD_4,
CMD_5,
CMD_6,
CMD_7,
CMD_8,
CMD_9,
CMD_10,
CMD_11,
CMD_12,
CMD_13,
CMD_14,
CMD_15,
CMD_16,
CMD_17,
CMD_18,
CMD_19,
CMD_20,
CMD_21,
CMD_22,
CMD_23,
CMD_24,
CMD_25,
CMD_26,
CMD_27,
CMD_28,
CMD_29,
CMD_30,
CMD_31,
NR_IDX_ALL,
};
/* APIs */
void mt_spm_dump_pmic_warp_reg(void);
void plat_spm_pmic_wrap_init(void);
#endif /* MT_PLAT_SPM_SETTING_H */

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_SPM_DOE_RESOURCE_CTRL_H
#define MT_SPM_DOE_RESOURCE_CTRL_H
#include <mt_spm_internal.h>
enum resource_ctrl_enum {
MT_SPM_RESOURCE_CTRL_BUS26M,
MT_SPM_RESOURCE_CTRL_INFRA,
MT_SPM_RESOURCE_CTRL_SYSPLL,
MT_SPM_RESOURCE_CTRL_DRAM_S0,
MT_SPM_RESOURCE_CTRL_DRAM_S1,
MT_SPM_RESORUCE_CTRL_VCORE,
MT_SPM_RESOURCE_CTRL_EMI,
MT_SPM_RESOURCE_CTRL_PMIC,
MT_SPM_RESOURCE_CTRL_MAX_NUM,
};
#endif /* MT_SPM_DOE_RESOURCE_CTRL_H */

View file

@ -0,0 +1,607 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <common/debug.h>
#include <lib/mmio.h>
#include <drivers/spm/mt_spm_resource_req.h>
#include <lib/pm/mtk_pm.h>
#include <lpm_v2/mt_lp_api.h>
#include <mt_spm.h>
#include <mt_spm_conservation.h>
#include <mt_spm_idle.h>
#include <mt_spm_internal.h>
#include <mt_spm_reg.h>
#include <mt_spm_stats.h>
#define SPM_BYPASS_SYSPWREQ_GENERIC 1
/* Default will be the bus26m or deeper spm's low power mode*/
#define __WAKE_SRC_FOR_IDLE_COMMON__ ( \
(R12_PCM_TIMER_B) | \
(R12_KP_IRQ_B) | \
(R12_APWDT_EVENT_B) | \
(R12_APXGPT_EVENT_B) | \
(R12_CONN2AP_WAKEUP_B) | \
(R12_EINT_EVENT_B) | \
(R12_CONN_WDT_IRQ_B) | \
(R12_CCIF0_EVENT_B) | \
(R12_CCIF1_EVENT_B) | \
(R12_SSPM2SPM_WAKEUP_B) | \
(R12_SCP2SPM_WAKEUP_B) | \
(R12_ADSP2SPM_WAKEUP_B) | \
(R12_USB0_CDSC_B) | \
(R12_USB0_POWERDWN_B) | \
(R12_UART_EVENT_B) | \
(R12_SYS_TIMER_EVENT_B) | \
(R12_EINT_EVENT_SECURE_B) | \
(R12_AFE_IRQ_MCU_B) | \
(R12_SYS_CIRQ_IRQ_B) | \
(R12_MD_WDT_B) | \
(R12_AP2AP_PEER_WAKEUP_B) | \
(R12_CPU_WAKEUP) | \
(R12_APUSYS_WAKE_HOST_B) |\
(R12_PCIE_WAKE_B))
#if defined(CFG_MICROTRUST_TEE_SUPPORT)
#define WAKE_SRC_FOR_IDLE (__WAKE_SRC_FOR_IDLE_COMMON__)
#else
#define WAKE_SRC_FOR_IDLE \
(__WAKE_SRC_FOR_IDLE_COMMON__ | R12_SEJ_B)
#endif
static struct pwr_ctrl idle_spm_pwr = {
.wake_src = WAKE_SRC_FOR_IDLE,
/* SPM_SRC_REQ */
.reg_spm_adsp_mailbox_req = 0,
.reg_spm_apsrc_req = 1,
.reg_spm_ddren_req = 0,
.reg_spm_dvfs_req = 0,
.reg_spm_emi_req = 1,
.reg_spm_f26m_req = 0,
.reg_spm_infra_req = 0,
.reg_spm_pmic_req = 0,
.reg_spm_scp_mailbox_req = 0,
.reg_spm_sspm_mailbox_req = 0,
.reg_spm_sw_mailbox_req = 0,
.reg_spm_vcore_req = 0,
.reg_spm_vrf18_req = 0,
.adsp_mailbox_state = 0,
.apsrc_state = 0,
.ddren_state = 0,
.dvfs_state = 0,
.emi_state = 0,
.f26m_state = 0,
.infra_state = 0,
.pmic_state = 0,
.scp_mailbox_state = 0,
.sspm_mailbox_state = 0,
.sw_mailbox_state = 0,
.vcore_state = 0,
.vrf18_state = 0,
/* SPM_SRC_MASK_0 */
.reg_apifr_apsrc_rmb = 0,
.reg_apifr_ddren_rmb = 0,
.reg_apifr_emi_rmb = 0,
.reg_apifr_infra_rmb = 0,
.reg_apifr_pmic_rmb = 0,
.reg_apifr_srcclkena_mb = 0,
.reg_apifr_vcore_rmb = 0,
.reg_apifr_vrf18_rmb = 0,
.reg_apu_apsrc_rmb = 1,
.reg_apu_ddren_rmb = 0,
.reg_apu_emi_rmb = 1,
.reg_apu_infra_rmb = 1,
.reg_apu_pmic_rmb = 1,
.reg_apu_srcclkena_mb = 1,
.reg_apu_vcore_rmb = 1,
.reg_apu_vrf18_rmb = 1,
.reg_audio_apsrc_rmb = 1,
.reg_audio_ddren_rmb = 0,
.reg_audio_emi_rmb = 1,
.reg_audio_infra_rmb = 1,
.reg_audio_pmic_rmb = 0,
.reg_audio_srcclkena_mb = 1,
.reg_audio_vcore_rmb = 1,
.reg_audio_vrf18_rmb = 1,
/* SPM_SRC_MASK_1 */
.reg_audio_dsp_apsrc_rmb = 1,
.reg_audio_dsp_ddren_rmb = 0,
.reg_audio_dsp_emi_rmb = 1,
.reg_audio_dsp_infra_rmb = 1,
.reg_audio_dsp_pmic_rmb = 1,
.reg_audio_dsp_srcclkena_mb = 1,
.reg_audio_dsp_vcore_rmb = 1,
.reg_audio_dsp_vrf18_rmb = 1,
.reg_cam_apsrc_rmb = 0,
.reg_cam_ddren_rmb = 0,
.reg_cam_emi_rmb = 0,
.reg_cam_infra_rmb = 0,
.reg_cam_pmic_rmb = 0,
.reg_cam_srcclkena_mb = 0,
.reg_cam_vrf18_rmb = 0,
.reg_ccif_apsrc_rmb = 0xfff,
/* SPM_SRC_MASK_2 */
.reg_ccif_emi_rmb = 0xfff,
.reg_ccif_infra_rmb = 0xfff,
/* SPM_SRC_MASK_3 */
.reg_ccif_pmic_rmb = 0xfff,
.reg_ccif_srcclkena_mb = 0xfff,
/* SPM_SRC_MASK_4 */
.reg_ccif_vcore_rmb = 0xfff,
.reg_ccif_vrf18_rmb = 0xfff,
.reg_ccu_apsrc_rmb = 0,
.reg_ccu_ddren_rmb = 0,
.reg_ccu_emi_rmb = 0,
.reg_ccu_infra_rmb = 0,
.reg_ccu_pmic_rmb = 0,
.reg_ccu_srcclkena_mb = 0,
.reg_ccu_vrf18_rmb = 0,
.reg_cg_check_apsrc_rmb = 0,
/* SPM_SRC_MASK_5 */
.reg_cg_check_ddren_rmb = 0,
.reg_cg_check_emi_rmb = 0,
.reg_cg_check_infra_rmb = 0,
.reg_cg_check_pmic_rmb = 0,
.reg_cg_check_srcclkena_mb = 0,
/* for UFS HWCG vcore req */
.reg_cg_check_vcore_rmb = 1,
.reg_cg_check_vrf18_rmb = 0,
.reg_cksys_apsrc_rmb = 1,
.reg_cksys_ddren_rmb = 0,
.reg_cksys_emi_rmb = 1,
.reg_cksys_infra_rmb = 1,
.reg_cksys_pmic_rmb = 1,
.reg_cksys_srcclkena_mb = 1,
.reg_cksys_vcore_rmb = 1,
.reg_cksys_vrf18_rmb = 1,
.reg_cksys_1_apsrc_rmb = 1,
.reg_cksys_1_ddren_rmb = 0,
.reg_cksys_1_emi_rmb = 1,
.reg_cksys_1_infra_rmb = 1,
.reg_cksys_1_pmic_rmb = 1,
.reg_cksys_1_srcclkena_mb = 1,
.reg_cksys_1_vcore_rmb = 1,
.reg_cksys_1_vrf18_rmb = 1,
/* SPM_SRC_MASK_6 */
.reg_cksys_2_apsrc_rmb = 1,
.reg_cksys_2_ddren_rmb = 0,
.reg_cksys_2_emi_rmb = 1,
.reg_cksys_2_infra_rmb = 1,
.reg_cksys_2_pmic_rmb = 1,
.reg_cksys_2_srcclkena_mb = 1,
.reg_cksys_2_vcore_rmb = 1,
.reg_cksys_2_vrf18_rmb = 1,
.reg_conn_apsrc_rmb = 1,
.reg_conn_ddren_rmb = 0,
.reg_conn_emi_rmb = 1,
.reg_conn_infra_rmb = 1,
.reg_conn_pmic_rmb = 1,
.reg_conn_srcclkena_mb = 1,
.reg_conn_srcclkenb_mb = 1,
.reg_conn_vcore_rmb = 1,
.reg_conn_vrf18_rmb = 1,
.reg_corecfg_apsrc_rmb = 0,
.reg_corecfg_ddren_rmb = 0,
.reg_corecfg_emi_rmb = 0,
.reg_corecfg_infra_rmb = 0,
.reg_corecfg_pmic_rmb = 0,
.reg_corecfg_srcclkena_mb = 0,
.reg_corecfg_vcore_rmb = 0,
.reg_corecfg_vrf18_rmb = 0,
/* SPM_SRC_MASK_7 */
.reg_cpueb_apsrc_rmb = 1,
.reg_cpueb_ddren_rmb = 0,
.reg_cpueb_emi_rmb = 1,
.reg_cpueb_infra_rmb = 1,
.reg_cpueb_pmic_rmb = 1,
.reg_cpueb_srcclkena_mb = 1,
.reg_cpueb_vcore_rmb = 0,
.reg_cpueb_vrf18_rmb = 1,
.reg_disp0_apsrc_rmb = 0,
.reg_disp0_ddren_rmb = 0,
.reg_disp0_emi_rmb = 0,
.reg_disp0_infra_rmb = 0,
.reg_disp0_pmic_rmb = 0,
.reg_disp0_srcclkena_mb = 0,
.reg_disp0_vrf18_rmb = 0,
.reg_disp1_apsrc_rmb = 0,
.reg_disp1_ddren_rmb = 0,
.reg_disp1_emi_rmb = 0,
.reg_disp1_infra_rmb = 0,
.reg_disp1_pmic_rmb = 0,
.reg_disp1_srcclkena_mb = 0,
.reg_disp1_vrf18_rmb = 0,
.reg_dpm_apsrc_rmb = 0xf,
.reg_dpm_ddren_rmb = 0xf,
/* SPM_SRC_MASK_8 */
.reg_dpm_emi_rmb = 0xf,
.reg_dpm_infra_rmb = 0xf,
.reg_dpm_pmic_rmb = 0xf,
.reg_dpm_srcclkena_mb = 0xf,
.reg_dpm_vcore_rmb = 0xf,
.reg_dpm_vrf18_rmb = 0xf,
.reg_dpmaif_apsrc_rmb = 1,
.reg_dpmaif_ddren_rmb = 0,
.reg_dpmaif_emi_rmb = 1,
.reg_dpmaif_infra_rmb = 1,
.reg_dpmaif_pmic_rmb = 1,
.reg_dpmaif_srcclkena_mb = 1,
.reg_dpmaif_vcore_rmb = 1,
.reg_dpmaif_vrf18_rmb = 1,
/* SPM_SRC_MASK_9 */
.reg_dvfsrc_level_rmb = 1,
.reg_emisys_apsrc_rmb = 0,
.reg_emisys_ddren_rmb = 0,
.reg_emisys_emi_rmb = 0,
.reg_emisys_infra_rmb = 0,
.reg_emisys_pmic_rmb = 0,
.reg_emisys_srcclkena_mb = 0,
.reg_emisys_vcore_rmb = 0,
.reg_emisys_vrf18_rmb = 0,
.reg_gce_apsrc_rmb = 0,
.reg_gce_ddren_rmb = 0,
.reg_gce_emi_rmb = 0,
.reg_gce_infra_rmb = 0,
.reg_gce_pmic_rmb = 0,
.reg_gce_srcclkena_mb = 0,
.reg_gce_vcore_rmb = 0,
.reg_gce_vrf18_rmb = 0,
.reg_gpueb_apsrc_rmb = 1,
.reg_gpueb_ddren_rmb = 0,
.reg_gpueb_emi_rmb = 1,
.reg_gpueb_infra_rmb = 1,
.reg_gpueb_pmic_rmb = 1,
.reg_gpueb_srcclkena_mb = 1,
.reg_gpueb_vcore_rmb = 1,
.reg_gpueb_vrf18_rmb = 1,
.reg_hwccf_apsrc_rmb = 1,
.reg_hwccf_ddren_rmb = 0,
.reg_hwccf_emi_rmb = 1,
.reg_hwccf_infra_rmb = 1,
.reg_hwccf_pmic_rmb = 1,
.reg_hwccf_srcclkena_mb = 1,
.reg_hwccf_vcore_rmb = 1,
/* SPM_SRC_MASK_10 */
.reg_hwccf_vrf18_rmb = 1,
.reg_img_apsrc_rmb = 0,
.reg_img_ddren_rmb = 0,
.reg_img_emi_rmb = 0,
.reg_img_infra_rmb = 0,
.reg_img_pmic_rmb = 0,
.reg_img_srcclkena_mb = 0,
.reg_img_vrf18_rmb = 0,
.reg_infrasys_apsrc_rmb = 0,
.reg_infrasys_ddren_rmb = 0,
.reg_infrasys_emi_rmb = 0,
.reg_infrasys_infra_rmb = 0,
.reg_infrasys_pmic_rmb = 0,
.reg_infrasys_srcclkena_mb = 0,
.reg_infrasys_vcore_rmb = 0,
.reg_infrasys_vrf18_rmb = 0,
.reg_ipic_infra_rmb = 1,
.reg_ipic_vrf18_rmb = 1,
.reg_mcu_apsrc_rmb = 1,
.reg_mcu_ddren_rmb = 0,
.reg_mcu_emi_rmb = 1,
.reg_mcu_infra_rmb = 1,
.reg_mcu_pmic_rmb = 1,
.reg_mcu_srcclkena_mb = 1,
.reg_mcu_vcore_rmb = 0,
.reg_mcu_vrf18_rmb = 1,
.reg_md_apsrc_rmb = 1,
.reg_md_ddren_rmb = 0,
.reg_md_emi_rmb = 1,
.reg_md_infra_rmb = 1,
.reg_md_pmic_rmb = 1,
.reg_md_srcclkena_mb = 1,
/* SPM_SRC_MASK_11 */
.reg_md_srcclkena1_mb = 1,
.reg_md_vcore_rmb = 1,
.reg_md_vrf18_rmb = 1,
.reg_mm_proc_apsrc_rmb = 1,
.reg_mm_proc_ddren_rmb = 0,
.reg_mm_proc_emi_rmb = 1,
.reg_mm_proc_infra_rmb = 1,
.reg_mm_proc_pmic_rmb = 1,
.reg_mm_proc_srcclkena_mb = 1,
.reg_mm_proc_vcore_rmb = 1,
.reg_mm_proc_vrf18_rmb = 1,
.reg_mml0_apsrc_rmb = 0,
.reg_mml0_ddren_rmb = 0,
.reg_mml0_emi_rmb = 0,
.reg_mml0_infra_rmb = 0,
.reg_mml0_pmic_rmb = 0,
.reg_mml0_srcclkena_mb = 0,
.reg_mml0_vrf18_rmb = 0,
.reg_mml1_apsrc_rmb = 0,
.reg_mml1_ddren_rmb = 0,
.reg_mml1_emi_rmb = 0,
.reg_mml1_infra_rmb = 0,
.reg_mml1_pmic_rmb = 0,
.reg_mml1_srcclkena_mb = 0,
.reg_mml1_vrf18_rmb = 0,
.reg_ovl0_apsrc_rmb = 0,
.reg_ovl0_ddren_rmb = 0,
.reg_ovl0_emi_rmb = 0,
.reg_ovl0_infra_rmb = 0,
.reg_ovl0_pmic_rmb = 0,
.reg_ovl0_srcclkena_mb = 0,
.reg_ovl0_vrf18_rmb = 0,
/* SPM_SRC_MASK_12 */
.reg_ovl1_apsrc_rmb = 0,
.reg_ovl1_ddren_rmb = 0,
.reg_ovl1_emi_rmb = 0,
.reg_ovl1_infra_rmb = 0,
.reg_ovl1_pmic_rmb = 0,
.reg_ovl1_srcclkena_mb = 0,
.reg_ovl1_vrf18_rmb = 0,
.reg_pcie0_apsrc_rmb = 1,
.reg_pcie0_ddren_rmb = 0,
.reg_pcie0_emi_rmb = 1,
.reg_pcie0_infra_rmb = 1,
.reg_pcie0_pmic_rmb = 1,
.reg_pcie0_srcclkena_mb = 1,
.reg_pcie0_vcore_rmb = 1,
.reg_pcie0_vrf18_rmb = 1,
.reg_pcie1_apsrc_rmb = 1,
.reg_pcie1_ddren_rmb = 0,
.reg_pcie1_emi_rmb = 1,
.reg_pcie1_infra_rmb = 1,
.reg_pcie1_pmic_rmb = 1,
.reg_pcie1_srcclkena_mb = 1,
.reg_pcie1_vcore_rmb = 1,
.reg_pcie1_vrf18_rmb = 1,
.reg_perisys_apsrc_rmb = 1,
.reg_perisys_ddren_rmb = 0,
.reg_perisys_emi_rmb = 1,
.reg_perisys_infra_rmb = 1,
.reg_perisys_pmic_rmb = 1,
.reg_perisys_srcclkena_mb = 1,
.reg_perisys_vcore_rmb = 1,
.reg_perisys_vrf18_rmb = 1,
.reg_pmsr_apsrc_rmb = 1,
/* SPM_SRC_MASK_13 */
.reg_pmsr_ddren_rmb = 0,
.reg_pmsr_emi_rmb = 1,
.reg_pmsr_infra_rmb = 1,
.reg_pmsr_pmic_rmb = 1,
.reg_pmsr_srcclkena_mb = 1,
.reg_pmsr_vcore_rmb = 1,
.reg_pmsr_vrf18_rmb = 1,
.reg_scp_apsrc_rmb = 1,
.reg_scp_ddren_rmb = 0,
.reg_scp_emi_rmb = 1,
.reg_scp_infra_rmb = 1,
.reg_scp_pmic_rmb = 1,
.reg_scp_srcclkena_mb = 1,
.reg_scp_vcore_rmb = 1,
.reg_scp_vrf18_rmb = 1,
.reg_spu_hwr_apsrc_rmb = 1,
.reg_spu_hwr_ddren_rmb = 0,
.reg_spu_hwr_emi_rmb = 1,
.reg_spu_hwr_infra_rmb = 1,
.reg_spu_hwr_pmic_rmb = 1,
.reg_spu_hwr_srcclkena_mb = 1,
.reg_spu_hwr_vcore_rmb = 1,
.reg_spu_hwr_vrf18_rmb = 1,
.reg_spu_ise_apsrc_rmb = 1,
.reg_spu_ise_ddren_rmb = 0,
.reg_spu_ise_emi_rmb = 1,
.reg_spu_ise_infra_rmb = 1,
.reg_spu_ise_pmic_rmb = 1,
.reg_spu_ise_srcclkena_mb = 1,
.reg_spu_ise_vcore_rmb = 1,
.reg_spu_ise_vrf18_rmb = 1,
/* SPM_SRC_MASK_14 */
.reg_srcclkeni_infra_rmb = 0x3,
.reg_srcclkeni_pmic_rmb = 0x3,
.reg_srcclkeni_srcclkena_mb = 0x3,
.reg_srcclkeni_vcore_rmb = 0x3,
.reg_sspm_apsrc_rmb = 1,
.reg_sspm_ddren_rmb = 0,
.reg_sspm_emi_rmb = 1,
.reg_sspm_infra_rmb = 1,
.reg_sspm_pmic_rmb = 1,
.reg_sspm_srcclkena_mb = 1,
.reg_sspm_vrf18_rmb = 1,
.reg_ssrsys_apsrc_rmb = 1,
.reg_ssrsys_ddren_rmb = 0,
.reg_ssrsys_emi_rmb = 1,
.reg_ssrsys_infra_rmb = 1,
.reg_ssrsys_pmic_rmb = 1,
.reg_ssrsys_srcclkena_mb = 1,
.reg_ssrsys_vcore_rmb = 1,
.reg_ssrsys_vrf18_rmb = 1,
.reg_ssusb_apsrc_rmb = 1,
.reg_ssusb_ddren_rmb = 0,
.reg_ssusb_emi_rmb = 1,
.reg_ssusb_infra_rmb = 1,
.reg_ssusb_pmic_rmb = 1,
.reg_ssusb_srcclkena_mb = 1,
.reg_ssusb_vcore_rmb = 1,
.reg_ssusb_vrf18_rmb = 1,
.reg_uart_hub_infra_rmb = 1,
/* SPM_SRC_MASK_15 */
.reg_uart_hub_pmic_rmb = 1,
.reg_uart_hub_srcclkena_mb = 1,
.reg_uart_hub_vcore_rmb = 1,
.reg_uart_hub_vrf18_rmb = 1,
.reg_ufs_apsrc_rmb = 1,
.reg_ufs_ddren_rmb = 0,
.reg_ufs_emi_rmb = 1,
.reg_ufs_infra_rmb = 1,
.reg_ufs_pmic_rmb = 1,
.reg_ufs_srcclkena_mb = 1,
.reg_ufs_vcore_rmb = 1,
.reg_ufs_vrf18_rmb = 1,
.reg_vdec_apsrc_rmb = 0,
.reg_vdec_ddren_rmb = 0,
.reg_vdec_emi_rmb = 0,
.reg_vdec_infra_rmb = 0,
.reg_vdec_pmic_rmb = 0,
.reg_vdec_srcclkena_mb = 0,
.reg_vdec_vrf18_rmb = 0,
.reg_venc_apsrc_rmb = 0,
.reg_venc_ddren_rmb = 0,
.reg_venc_emi_rmb = 0,
.reg_venc_infra_rmb = 0,
.reg_venc_pmic_rmb = 0,
.reg_venc_srcclkena_mb = 0,
.reg_venc_vrf18_rmb = 0,
.reg_vlpcfg_apsrc_rmb = 1,
.reg_vlpcfg_ddren_rmb = 0,
.reg_vlpcfg_emi_rmb = 1,
.reg_vlpcfg_infra_rmb = 1,
.reg_vlpcfg_pmic_rmb = 1,
.reg_vlpcfg_srcclkena_mb = 1,
/* SPM_SRC_MASK_16 */
.reg_vlpcfg_vcore_rmb = 1,
.reg_vlpcfg_vrf18_rmb = 1,
.reg_vlpcfg1_apsrc_rmb = 1,
.reg_vlpcfg1_ddren_rmb = 0,
.reg_vlpcfg1_emi_rmb = 1,
.reg_vlpcfg1_infra_rmb = 1,
.reg_vlpcfg1_pmic_rmb = 0,
.reg_vlpcfg1_srcclkena_mb = 1,
.reg_vlpcfg1_vcore_rmb = 1,
.reg_vlpcfg1_vrf18_rmb = 1,
/* SPM_EVENT_CON_MISC */
.reg_srcclken_fast_resp = 0,
.reg_csyspwrup_ack_mask = 1,
/* SPM_SRC_MASK_17 */
.reg_spm_sw_vcore_rmb = 0x3,
.reg_spm_sw_pmic_rmb = 0,
/* SPM_SRC_MASK_18 */
.reg_spm_sw_srcclkena_mb = 0,
/* SPM_WAKE_MASK*/
.reg_wake_mask = 0x81322012,
/* SPM_WAKEUP_EVENT_EXT_MASK */
.reg_ext_wake_mask = 0xFFFFFFFF,
};
static struct dbg_ctrl idle_spm_dbg = {
.count = 0,
.duration = 0,
.ext = NULL,
};
static struct spm_lp_stat idle_lp_stat;
static struct spm_lp_scen idle_spm_lp = {
.pwrctrl = &idle_spm_pwr,
.dbgctrl = &idle_spm_dbg,
.lpstat = &idle_lp_stat,
};
static int determine_event_level(int state_id)
{
if (IS_MT_PLAT_PWR_STATE(state_id, MT_PLAT_PWR_STATE_SYSTEM_VCORE))
return MT_LP_SYSPOWER_LEVEL_VCORE0V;
else if (IS_MT_PLAT_PWR_STATE(state_id, MT_PLAT_PWR_STATE_SYSTEM_BUS))
return MT_LP_SYSPOWER_LEVEL_BUS26M;
else if (IS_MT_PLAT_PWR_STATE(state_id, MT_PLAT_PWR_STATE_SYSTEM_PLL))
return MT_LP_SYSPOWER_LEVEL_SYSPLL;
else if (IS_MT_PLAT_PWR_STATE(state_id, MT_PLAT_PWR_STATE_SYSTEM_MEM))
return MT_LP_SYSPOWER_LEVEL_DRAM;
else
return MT_LP_SYSPOWER_LEVEL_APMCU;
}
int mt_spm_idle_generic_enter(int state_id, uint32_t ext_opand,
spm_idle_conduct fn)
{
int ret = 0;
uint32_t src_req = 0;
struct mt_lp_publish_event event = {
.id = MT_LPM_PUBEVENTS_SYS_POWER_OFF,
.val.u32 = 0,
.level = 0,
};
event.level = determine_event_level(state_id);
if (fn)
fn(state_id, &idle_spm_lp, &src_req);
ret = spm_conservation(state_id, ext_opand, &idle_spm_lp, src_req);
if (ret) {
NOTICE("[%s:%d] - unknown issue !!\n", __func__, __LINE__);
panic();
}
mmio_write_32(SPM2SW_MAILBOX_0, 0x1);
if (ext_opand & MT_SPM_EX_OP_DEVICES_SAVE)
MT_LP_SUSPEND_PUBLISH_EVENT(&event);
else
MT_LP_PUBLISH_EVENT(&event);
return ret;
}
void mt_spm_idle_generic_resume(int state_id, uint32_t ext_opand,
struct wake_status **status,
spm_idle_conduct_restore fn)
{
struct mt_lp_publish_event event = {
.id = MT_LPM_PUBEVENTS_SYS_POWER_ON,
.val.u32 = 0,
};
event.level = determine_event_level(state_id);
ext_opand |= (MT_SPM_EX_OP_TIME_CHECK | MT_SPM_EX_OP_TIME_OBS);
spm_conservation_finish(state_id, ext_opand, &idle_spm_lp, status);
mt_spm_update_lp_stat(&idle_lp_stat);
if (spm_unlikely(fn))
fn(state_id, &idle_spm_lp, *status);
if (ext_opand & MT_SPM_EX_OP_DEVICES_SAVE) {
mmio_write_32(SPM2SW_MAILBOX_0, 0x0);
MT_LP_SUSPEND_PUBLISH_EVENT(&event);
} else
MT_LP_PUBLISH_EVENT(&event);
}
int mt_spm_idle_generic_get_spm_lp(struct spm_lp_scen **lp)
{
if (!lp)
return -1;
*lp = &idle_spm_lp;
return 0;
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_SPM_IDLE_H
#define MT_SPM_IDLE_H
#include <mt_spm_internal.h>
typedef int (*spm_idle_conduct)(int state_id, struct spm_lp_scen *spm_lp,
uint32_t *resource_req);
typedef int (*spm_idle_conduct_restore)(int state_id,
struct spm_lp_scen *spm_lp,
struct wake_status *status);
int mt_spm_idle_generic_enter(int state_id, uint32_t ext_opand,
spm_idle_conduct fn);
void mt_spm_idle_generic_resume(int state_id, uint32_t ext_opand,
struct wake_status **status,
spm_idle_conduct_restore fn);
int mt_spm_idle_generic_get_spm_lp(struct spm_lp_scen **lp);
#endif /* MT_SPM_IDLE_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,711 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <stdio.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <drivers/gpio.h>
#include <lib/mmio.h>
#include <constraints/mt_spm_rc_internal.h>
#include <drivers/spm/mt_spm_resource_req.h>
#include <lib/pm/mtk_pm.h>
#include <lpm_v2/mt_lp_api.h>
#include <lpm_v2/mt_lp_rqm.h>
#include <mt_spm.h>
#include <mt_spm_conservation.h>
#include <mt_spm_internal.h>
#include <mt_spm_reg.h>
#include <mt_spm_stats.h>
#include <mt_spm_suspend.h>
#if defined(CONFIG_MTK_VCOREDVFS_SUPPORT)
#include <mt_spm_vcorefs_exp.h>
#endif
#define SPM_SUSPEND_SLEEP_PCM_FLAG (SPM_FLAG_DISABLE_DDR_DFS | \
SPM_FLAG_DISABLE_EMI_DFS | \
SPM_FLAG_DISABLE_VLP_PDN | \
SPM_FLAG_DISABLE_BUS_DFS | \
SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \
SPM_FLAG_ENABLE_AOV | \
SPM_FLAG_ENABLE_MD_MUMTAS | \
SPM_FLAG_SRAM_SLEEP_CTRL)
#define SPM_SUSPEND_SLEEP_PCM_FLAG1 (SPM_FLAG1_ENABLE_ALCO_TRACE | \
SPM_FLAG1_ENABLE_SUSPEND_AVS)
#define SPM_SUSPEND_PCM_FLAG (SPM_FLAG_DISABLE_VCORE_DVS | \
SPM_FLAG_DISABLE_MCUPM_PDN | \
SPM_FLAG_DISABLE_VLP_PDN | \
SPM_FLAG_DISABLE_DDR_DFS | \
SPM_FLAG_DISABLE_EMI_DFS | \
SPM_FLAG_DISABLE_BUS_DFS | \
SPM_FLAG_ENABLE_MD_MUMTAS | \
SPM_FLAG_SRAM_SLEEP_CTRL)
#define SPM_SUSPEND_PCM_FLAG1 (SPM_FLAG1_ENABLE_ALCO_TRACE | \
SPM_FLAG1_ENABLE_SUSPEND_AVS | \
SPM_FLAG1_ENABLE_CSOPLU_OFF)
/* Suspend spm power control */
#define __WAKE_SRC_FOR_SUSPEND_COMMON__ ( \
(R12_KP_IRQ_B) | \
(R12_APWDT_EVENT_B) | \
(R12_CONN2AP_WAKEUP_B) | \
(R12_EINT_EVENT_B) | \
(R12_CONN_WDT_IRQ_B) | \
(R12_CCIF0_EVENT_B) | \
(R12_CCIF1_EVENT_B) | \
(R12_SCP2SPM_WAKEUP_B) | \
(R12_ADSP2SPM_WAKEUP_B) | \
(R12_USB0_CDSC_B) | \
(R12_USB0_POWERDWN_B) | \
(R12_UART_EVENT_B) |\
(R12_SYS_TIMER_EVENT_B) | \
(R12_EINT_EVENT_SECURE_B) | \
(R12_SYS_CIRQ_IRQ_B) | \
(R12_MD_WDT_B) | \
(R12_AP2AP_PEER_WAKEUP_B) | \
(R12_CPU_WAKEUP) | \
(R12_APUSYS_WAKE_HOST_B)|\
(R12_PCIE_WAKE_B))
#if defined(CFG_MICROTRUST_TEE_SUPPORT)
#define WAKE_SRC_FOR_SUSPEND \
(__WAKE_SRC_FOR_SUSPEND_COMMON__)
#else
#define WAKE_SRC_FOR_SUSPEND \
(__WAKE_SRC_FOR_SUSPEND_COMMON__ | \
R12_SEJ_B)
#endif
static uint32_t gpio_bk1;
static uint32_t gpio_bk2;
static uint32_t gpio_bk3;
static struct pwr_ctrl suspend_ctrl = {
.wake_src = WAKE_SRC_FOR_SUSPEND,
/* SPM_SRC_REQ */
.reg_spm_adsp_mailbox_req = 0,
.reg_spm_apsrc_req = 0,
.reg_spm_ddren_req = 0,
.reg_spm_dvfs_req = 0,
.reg_spm_emi_req = 0,
.reg_spm_f26m_req = 0,
.reg_spm_infra_req = 0,
.reg_spm_pmic_req = 0,
.reg_spm_scp_mailbox_req = 0,
.reg_spm_sspm_mailbox_req = 0,
.reg_spm_sw_mailbox_req = 0,
.reg_spm_vcore_req = 1,
.reg_spm_vrf18_req = 0,
.adsp_mailbox_state = 0,
.apsrc_state = 0,
.ddren_state = 0,
.dvfs_state = 0,
.emi_state = 0,
.f26m_state = 0,
.infra_state = 0,
.pmic_state = 0,
.scp_mailbox_state = 0,
.sspm_mailbox_state = 0,
.sw_mailbox_state = 0,
.vcore_state = 0,
.vrf18_state = 0,
/* SPM_SRC_MASK_0 */
.reg_apifr_apsrc_rmb = 0,
.reg_apifr_ddren_rmb = 0,
.reg_apifr_emi_rmb = 0,
.reg_apifr_infra_rmb = 0,
.reg_apifr_pmic_rmb = 0,
.reg_apifr_srcclkena_mb = 0,
.reg_apifr_vcore_rmb = 0,
.reg_apifr_vrf18_rmb = 0,
.reg_apu_apsrc_rmb = 1,
.reg_apu_ddren_rmb = 0,
.reg_apu_emi_rmb = 1,
.reg_apu_infra_rmb = 1,
.reg_apu_pmic_rmb = 1,
.reg_apu_srcclkena_mb = 1,
.reg_apu_vcore_rmb = 1,
.reg_apu_vrf18_rmb = 1,
.reg_audio_apsrc_rmb = 1,
.reg_audio_ddren_rmb = 0,
.reg_audio_emi_rmb = 1,
.reg_audio_infra_rmb = 1,
.reg_audio_pmic_rmb = 0,
.reg_audio_srcclkena_mb = 1,
.reg_audio_vcore_rmb = 1,
.reg_audio_vrf18_rmb = 1,
/* SPM_SRC_MASK_1 */
.reg_audio_dsp_apsrc_rmb = 1,
.reg_audio_dsp_ddren_rmb = 0,
.reg_audio_dsp_emi_rmb = 1,
.reg_audio_dsp_infra_rmb = 1,
.reg_audio_dsp_pmic_rmb = 1,
.reg_audio_dsp_srcclkena_mb = 1,
.reg_audio_dsp_vcore_rmb = 1,
.reg_audio_dsp_vrf18_rmb = 1,
.reg_cam_apsrc_rmb = 0,
.reg_cam_ddren_rmb = 0,
.reg_cam_emi_rmb = 0,
.reg_cam_infra_rmb = 0,
.reg_cam_pmic_rmb = 0,
.reg_cam_srcclkena_mb = 0,
.reg_cam_vrf18_rmb = 0,
.reg_ccif_apsrc_rmb = 0xfff,
/* SPM_SRC_MASK_2 */
.reg_ccif_emi_rmb = 0xfff,
.reg_ccif_infra_rmb = 0xfff,
/* SPM_SRC_MASK_3 */
.reg_ccif_pmic_rmb = 0xfff,
.reg_ccif_srcclkena_mb = 0xfff,
/* SPM_SRC_MASK_4 */
.reg_ccif_vcore_rmb = 0xfff,
.reg_ccif_vrf18_rmb = 0xfff,
.reg_ccu_apsrc_rmb = 0,
.reg_ccu_ddren_rmb = 0,
.reg_ccu_emi_rmb = 0,
.reg_ccu_infra_rmb = 0,
.reg_ccu_pmic_rmb = 0,
.reg_ccu_srcclkena_mb = 0,
.reg_ccu_vrf18_rmb = 0,
.reg_cg_check_apsrc_rmb = 0,
/* SPM_SRC_MASK_5 */
.reg_cg_check_ddren_rmb = 0,
.reg_cg_check_emi_rmb = 0,
.reg_cg_check_infra_rmb = 0,
.reg_cg_check_pmic_rmb = 0,
.reg_cg_check_srcclkena_mb = 0,
.reg_cg_check_vcore_rmb = 1,
.reg_cg_check_vrf18_rmb = 0,
.reg_cksys_apsrc_rmb = 1,
.reg_cksys_ddren_rmb = 0,
.reg_cksys_emi_rmb = 1,
.reg_cksys_infra_rmb = 1,
.reg_cksys_pmic_rmb = 1,
.reg_cksys_srcclkena_mb = 1,
.reg_cksys_vcore_rmb = 1,
.reg_cksys_vrf18_rmb = 1,
.reg_cksys_1_apsrc_rmb = 1,
.reg_cksys_1_ddren_rmb = 0,
.reg_cksys_1_emi_rmb = 1,
.reg_cksys_1_infra_rmb = 1,
.reg_cksys_1_pmic_rmb = 1,
.reg_cksys_1_srcclkena_mb = 1,
.reg_cksys_1_vcore_rmb = 1,
.reg_cksys_1_vrf18_rmb = 1,
/* SPM_SRC_MASK_6 */
.reg_cksys_2_apsrc_rmb = 1,
.reg_cksys_2_ddren_rmb = 0,
.reg_cksys_2_emi_rmb = 1,
.reg_cksys_2_infra_rmb = 1,
.reg_cksys_2_pmic_rmb = 1,
.reg_cksys_2_srcclkena_mb = 1,
.reg_cksys_2_vcore_rmb = 1,
.reg_cksys_2_vrf18_rmb = 1,
.reg_conn_apsrc_rmb = 1,
.reg_conn_ddren_rmb = 0,
.reg_conn_emi_rmb = 1,
.reg_conn_infra_rmb = 1,
.reg_conn_pmic_rmb = 1,
.reg_conn_srcclkena_mb = 1,
.reg_conn_srcclkenb_mb = 1,
.reg_conn_vcore_rmb = 1,
.reg_conn_vrf18_rmb = 1,
.reg_corecfg_apsrc_rmb = 0,
.reg_corecfg_ddren_rmb = 0,
.reg_corecfg_emi_rmb = 0,
.reg_corecfg_infra_rmb = 0,
.reg_corecfg_pmic_rmb = 0,
.reg_corecfg_srcclkena_mb = 0,
.reg_corecfg_vcore_rmb = 0,
.reg_corecfg_vrf18_rmb = 0,
/* SPM_SRC_MASK_7 */
.reg_cpueb_apsrc_rmb = 1,
.reg_cpueb_ddren_rmb = 0,
.reg_cpueb_emi_rmb = 1,
.reg_cpueb_infra_rmb = 1,
.reg_cpueb_pmic_rmb = 1,
.reg_cpueb_srcclkena_mb = 1,
.reg_cpueb_vcore_rmb = 0,
.reg_cpueb_vrf18_rmb = 1,
.reg_disp0_apsrc_rmb = 0,
.reg_disp0_ddren_rmb = 0,
.reg_disp0_emi_rmb = 0,
.reg_disp0_infra_rmb = 0,
.reg_disp0_pmic_rmb = 0,
.reg_disp0_srcclkena_mb = 0,
.reg_disp0_vrf18_rmb = 0,
.reg_disp1_apsrc_rmb = 0,
.reg_disp1_ddren_rmb = 0,
.reg_disp1_emi_rmb = 0,
.reg_disp1_infra_rmb = 0,
.reg_disp1_pmic_rmb = 0,
.reg_disp1_srcclkena_mb = 0,
.reg_disp1_vrf18_rmb = 0,
.reg_dpm_apsrc_rmb = 0xf,
.reg_dpm_ddren_rmb = 0xf,
/* SPM_SRC_MASK_8 */
.reg_dpm_emi_rmb = 0xf,
.reg_dpm_infra_rmb = 0xf,
.reg_dpm_pmic_rmb = 0xf,
.reg_dpm_srcclkena_mb = 0xf,
.reg_dpm_vcore_rmb = 0xf,
.reg_dpm_vrf18_rmb = 0xf,
.reg_dpmaif_apsrc_rmb = 1,
.reg_dpmaif_ddren_rmb = 0,
.reg_dpmaif_emi_rmb = 1,
.reg_dpmaif_infra_rmb = 1,
.reg_dpmaif_pmic_rmb = 1,
.reg_dpmaif_srcclkena_mb = 1,
.reg_dpmaif_vcore_rmb = 1,
.reg_dpmaif_vrf18_rmb = 1,
/* SPM_SRC_MASK_9 */
.reg_dvfsrc_level_rmb = 1,
.reg_emisys_apsrc_rmb = 0,
.reg_emisys_ddren_rmb = 0,
.reg_emisys_emi_rmb = 0,
.reg_emisys_infra_rmb = 0,
.reg_emisys_pmic_rmb = 0,
.reg_emisys_srcclkena_mb = 0,
.reg_emisys_vcore_rmb = 0,
.reg_emisys_vrf18_rmb = 0,
.reg_gce_apsrc_rmb = 0,
.reg_gce_ddren_rmb = 0,
.reg_gce_emi_rmb = 0,
.reg_gce_infra_rmb = 0,
.reg_gce_pmic_rmb = 0,
.reg_gce_srcclkena_mb = 0,
.reg_gce_vcore_rmb = 0,
.reg_gce_vrf18_rmb = 0,
.reg_gpueb_apsrc_rmb = 1,
.reg_gpueb_ddren_rmb = 0,
.reg_gpueb_emi_rmb = 1,
.reg_gpueb_infra_rmb = 1,
.reg_gpueb_pmic_rmb = 1,
.reg_gpueb_srcclkena_mb = 1,
.reg_gpueb_vcore_rmb = 1,
.reg_gpueb_vrf18_rmb = 1,
.reg_hwccf_apsrc_rmb = 1,
.reg_hwccf_ddren_rmb = 0,
.reg_hwccf_emi_rmb = 1,
.reg_hwccf_infra_rmb = 1,
.reg_hwccf_pmic_rmb = 1,
.reg_hwccf_srcclkena_mb = 1,
.reg_hwccf_vcore_rmb = 1,
/* SPM_SRC_MASK_10 */
.reg_hwccf_vrf18_rmb = 1,
.reg_img_apsrc_rmb = 0,
.reg_img_ddren_rmb = 0,
.reg_img_emi_rmb = 0,
.reg_img_infra_rmb = 0,
.reg_img_pmic_rmb = 0,
.reg_img_srcclkena_mb = 0,
.reg_img_vrf18_rmb = 0,
.reg_infrasys_apsrc_rmb = 0,
.reg_infrasys_ddren_rmb = 0,
.reg_infrasys_emi_rmb = 0,
.reg_infrasys_infra_rmb = 0,
.reg_infrasys_pmic_rmb = 0,
.reg_infrasys_srcclkena_mb = 0,
.reg_infrasys_vcore_rmb = 0,
.reg_infrasys_vrf18_rmb = 0,
.reg_ipic_infra_rmb = 1,
.reg_ipic_vrf18_rmb = 1,
.reg_mcu_apsrc_rmb = 1,
.reg_mcu_ddren_rmb = 0,
.reg_mcu_emi_rmb = 1,
.reg_mcu_infra_rmb = 1,
.reg_mcu_pmic_rmb = 1,
.reg_mcu_srcclkena_mb = 1,
.reg_mcu_vcore_rmb = 0,
.reg_mcu_vrf18_rmb = 1,
.reg_md_apsrc_rmb = 1,
.reg_md_ddren_rmb = 0,
.reg_md_emi_rmb = 1,
.reg_md_infra_rmb = 1,
.reg_md_pmic_rmb = 1,
.reg_md_srcclkena_mb = 1,
/* SPM_SRC_MASK_11 */
.reg_md_srcclkena1_mb = 1,
.reg_md_vcore_rmb = 1,
.reg_md_vrf18_rmb = 1,
.reg_mm_proc_apsrc_rmb = 1,
.reg_mm_proc_ddren_rmb = 0,
.reg_mm_proc_emi_rmb = 1,
.reg_mm_proc_infra_rmb = 1,
.reg_mm_proc_pmic_rmb = 1,
.reg_mm_proc_srcclkena_mb = 1,
.reg_mm_proc_vcore_rmb = 1,
.reg_mm_proc_vrf18_rmb = 1,
.reg_mml0_apsrc_rmb = 0,
.reg_mml0_ddren_rmb = 0,
.reg_mml0_emi_rmb = 0,
.reg_mml0_infra_rmb = 0,
.reg_mml0_pmic_rmb = 0,
.reg_mml0_srcclkena_mb = 0,
.reg_mml0_vrf18_rmb = 0,
.reg_mml1_apsrc_rmb = 0,
.reg_mml1_ddren_rmb = 0,
.reg_mml1_emi_rmb = 0,
.reg_mml1_infra_rmb = 0,
.reg_mml1_pmic_rmb = 0,
.reg_mml1_srcclkena_mb = 0,
.reg_mml1_vrf18_rmb = 0,
.reg_ovl0_apsrc_rmb = 0,
.reg_ovl0_ddren_rmb = 0,
.reg_ovl0_emi_rmb = 0,
.reg_ovl0_infra_rmb = 0,
.reg_ovl0_pmic_rmb = 0,
.reg_ovl0_srcclkena_mb = 0,
.reg_ovl0_vrf18_rmb = 0,
/* SPM_SRC_MASK_12 */
.reg_ovl1_apsrc_rmb = 0,
.reg_ovl1_ddren_rmb = 0,
.reg_ovl1_emi_rmb = 0,
.reg_ovl1_infra_rmb = 0,
.reg_ovl1_pmic_rmb = 0,
.reg_ovl1_srcclkena_mb = 0,
.reg_ovl1_vrf18_rmb = 0,
.reg_pcie0_apsrc_rmb = 1,
.reg_pcie0_ddren_rmb = 0,
.reg_pcie0_emi_rmb = 1,
.reg_pcie0_infra_rmb = 1,
.reg_pcie0_pmic_rmb = 1,
.reg_pcie0_srcclkena_mb = 1,
.reg_pcie0_vcore_rmb = 1,
.reg_pcie0_vrf18_rmb = 1,
.reg_pcie1_apsrc_rmb = 1,
.reg_pcie1_ddren_rmb = 0,
.reg_pcie1_emi_rmb = 1,
.reg_pcie1_infra_rmb = 1,
.reg_pcie1_pmic_rmb = 1,
.reg_pcie1_srcclkena_mb = 1,
.reg_pcie1_vcore_rmb = 1,
.reg_pcie1_vrf18_rmb = 1,
.reg_perisys_apsrc_rmb = 1,
.reg_perisys_ddren_rmb = 0,
.reg_perisys_emi_rmb = 1,
.reg_perisys_infra_rmb = 1,
.reg_perisys_pmic_rmb = 1,
.reg_perisys_srcclkena_mb = 1,
.reg_perisys_vcore_rmb = 1,
.reg_perisys_vrf18_rmb = 1,
.reg_pmsr_apsrc_rmb = 1,
/* SPM_SRC_MASK_13 */
.reg_pmsr_ddren_rmb = 0,
.reg_pmsr_emi_rmb = 1,
.reg_pmsr_infra_rmb = 1,
.reg_pmsr_pmic_rmb = 1,
.reg_pmsr_srcclkena_mb = 1,
.reg_pmsr_vcore_rmb = 1,
.reg_pmsr_vrf18_rmb = 1,
.reg_scp_apsrc_rmb = 1,
.reg_scp_ddren_rmb = 0,
.reg_scp_emi_rmb = 1,
.reg_scp_infra_rmb = 1,
.reg_scp_pmic_rmb = 1,
.reg_scp_srcclkena_mb = 1,
.reg_scp_vcore_rmb = 1,
.reg_scp_vrf18_rmb = 1,
.reg_spu_hwr_apsrc_rmb = 1,
.reg_spu_hwr_ddren_rmb = 0,
.reg_spu_hwr_emi_rmb = 1,
.reg_spu_hwr_infra_rmb = 1,
.reg_spu_hwr_pmic_rmb = 1,
.reg_spu_hwr_srcclkena_mb = 1,
.reg_spu_hwr_vcore_rmb = 1,
.reg_spu_hwr_vrf18_rmb = 1,
.reg_spu_ise_apsrc_rmb = 1,
.reg_spu_ise_ddren_rmb = 0,
.reg_spu_ise_emi_rmb = 1,
.reg_spu_ise_infra_rmb = 1,
.reg_spu_ise_pmic_rmb = 1,
.reg_spu_ise_srcclkena_mb = 1,
.reg_spu_ise_vcore_rmb = 1,
.reg_spu_ise_vrf18_rmb = 1,
/* SPM_SRC_MASK_14 */
.reg_srcclkeni_infra_rmb = 0x3,
.reg_srcclkeni_pmic_rmb = 0x3,
.reg_srcclkeni_srcclkena_mb = 0x3,
.reg_srcclkeni_vcore_rmb = 0x3,
.reg_sspm_apsrc_rmb = 1,
.reg_sspm_ddren_rmb = 0,
.reg_sspm_emi_rmb = 1,
.reg_sspm_infra_rmb = 1,
.reg_sspm_pmic_rmb = 1,
.reg_sspm_srcclkena_mb = 1,
.reg_sspm_vrf18_rmb = 1,
.reg_ssrsys_apsrc_rmb = 1,
.reg_ssrsys_ddren_rmb = 0,
.reg_ssrsys_emi_rmb = 1,
.reg_ssrsys_infra_rmb = 1,
.reg_ssrsys_pmic_rmb = 1,
.reg_ssrsys_srcclkena_mb = 1,
.reg_ssrsys_vcore_rmb = 1,
.reg_ssrsys_vrf18_rmb = 1,
.reg_ssusb_apsrc_rmb = 1,
.reg_ssusb_ddren_rmb = 0,
.reg_ssusb_emi_rmb = 1,
.reg_ssusb_infra_rmb = 1,
.reg_ssusb_pmic_rmb = 1,
.reg_ssusb_srcclkena_mb = 1,
.reg_ssusb_vcore_rmb = 1,
.reg_ssusb_vrf18_rmb = 1,
.reg_uart_hub_infra_rmb = 1,
/* SPM_SRC_MASK_15 */
.reg_uart_hub_pmic_rmb = 1,
.reg_uart_hub_srcclkena_mb = 1,
.reg_uart_hub_vcore_rmb = 1,
.reg_uart_hub_vrf18_rmb = 1,
.reg_ufs_apsrc_rmb = 1,
.reg_ufs_ddren_rmb = 0,
.reg_ufs_emi_rmb = 1,
.reg_ufs_infra_rmb = 1,
.reg_ufs_pmic_rmb = 1,
.reg_ufs_srcclkena_mb = 1,
.reg_ufs_vcore_rmb = 1,
.reg_ufs_vrf18_rmb = 1,
.reg_vdec_apsrc_rmb = 0,
.reg_vdec_ddren_rmb = 0,
.reg_vdec_emi_rmb = 0,
.reg_vdec_infra_rmb = 0,
.reg_vdec_pmic_rmb = 0,
.reg_vdec_srcclkena_mb = 0,
.reg_vdec_vrf18_rmb = 0,
.reg_venc_apsrc_rmb = 0,
.reg_venc_ddren_rmb = 0,
.reg_venc_emi_rmb = 0,
.reg_venc_infra_rmb = 0,
.reg_venc_pmic_rmb = 0,
.reg_venc_srcclkena_mb = 0,
.reg_venc_vrf18_rmb = 0,
.reg_vlpcfg_apsrc_rmb = 1,
.reg_vlpcfg_ddren_rmb = 0,
.reg_vlpcfg_emi_rmb = 1,
.reg_vlpcfg_infra_rmb = 1,
.reg_vlpcfg_pmic_rmb = 1,
.reg_vlpcfg_srcclkena_mb = 1,
/* SPM_SRC_MASK_16 */
.reg_vlpcfg_vcore_rmb = 1,
.reg_vlpcfg_vrf18_rmb = 1,
.reg_vlpcfg1_apsrc_rmb = 1,
.reg_vlpcfg1_ddren_rmb = 0,
.reg_vlpcfg1_emi_rmb = 1,
.reg_vlpcfg1_infra_rmb = 1,
.reg_vlpcfg1_pmic_rmb = 0,
.reg_vlpcfg1_srcclkena_mb = 1,
.reg_vlpcfg1_vcore_rmb = 1,
.reg_vlpcfg1_vrf18_rmb = 1,
/* SPM_EVENT_CON_MISC */
.reg_srcclken_fast_resp = 0,
.reg_csyspwrup_ack_mask = 1,
/* SPM_SRC_MASK_17 */
.reg_spm_sw_vcore_rmb = 0x3,
.reg_spm_sw_pmic_rmb = 0,
/* SPM_SRC_MASK_18 */
.reg_spm_sw_srcclkena_mb = 0,
/* SPM_WAKE_MASK*/
.reg_wake_mask = 0x81322012,
/* SPM_WAKEUP_EVENT_EXT_MASK */
.reg_ext_wake_mask = 0xFFFFFFFF,
/*SW flag setting */
.pcm_flags = SPM_SUSPEND_PCM_FLAG,
.pcm_flags1 = SPM_SUSPEND_PCM_FLAG1,
};
static struct suspend_dbg_ctrl suspend_spm_dbg_ext = {
.sleep_suspend_cnt = 0,
};
static struct dbg_ctrl suspend_spm_dbg = {
.count = 0,
.duration = 0,
.ext = &suspend_spm_dbg_ext,
};
static struct spm_lp_stat suspend_lp_stat;
struct spm_lp_scen __spm_suspend = {
.pwrctrl = &suspend_ctrl,
.dbgctrl = &suspend_spm_dbg,
.lpstat = &suspend_lp_stat,
};
static uint8_t bak_spm_vcore_req;
int mt_spm_suspend_mode_set(enum mt_spm_suspend_mode mode, void *prv)
{
if (mode == MT_SPM_SUSPEND_SLEEP) {
suspend_ctrl.pcm_flags = SPM_SUSPEND_SLEEP_PCM_FLAG;
suspend_ctrl.pcm_flags1 = SPM_SUSPEND_SLEEP_PCM_FLAG1;
suspend_ctrl.reg_spm_vcore_req = 1;
} else {
suspend_ctrl.pcm_flags = SPM_SUSPEND_PCM_FLAG;
suspend_ctrl.pcm_flags1 = SPM_SUSPEND_PCM_FLAG1;
}
return 0;
}
static void spm_CSOPLU_ctrl_leave_suspend(void)
{
mmio_setbits_32(SPM_RSV_CSOPLU_REQ, (0x1));
}
static void mt_spm_suspend_ec_pin(void)
{
gpio_bk1 = mmio_read_32(MODE_BACKUP_REG);
gpio_bk2 = mmio_read_32(DIR_BACKUP_REG);
gpio_bk3 = mmio_read_32(DOUT_BACKUP_REG);
mmio_write_32(MODE_SET, SET_GPIO_MODE);
gpio_set_direction(EC_SUSPEND_BK_PIN, GPIO_DIR_OUT);
/* GPIO111 LOW */
gpio_set_value(EC_SUSPEND_BK_PIN, GPIO_LEVEL_LOW);
/* GPIO38 LOW */
gpio_set_value(EC_SUSPEND_PIN, GPIO_LEVEL_LOW);
}
static void mt_spm_resume_ec_pin(void)
{
/* GPIO38 HIGH */
gpio_set_value(EC_SUSPEND_PIN, GPIO_LEVEL_HIGH);
/* GPIO111 HIGH */
gpio_set_value(EC_SUSPEND_BK_PIN, GPIO_LEVEL_HIGH);
udelay(10);
mmio_write_32(MODE_BACKUP_REG, gpio_bk1);
mmio_write_32(DIR_BACKUP_REG, gpio_bk2);
mmio_write_32(DOUT_BACKUP_REG, gpio_bk3);
}
int mt_spm_suspend_enter(int state_id,
uint32_t ext_opand, uint32_t resource_req)
{
int ret = 0;
bak_spm_vcore_req = suspend_ctrl.reg_spm_vcore_req;
/* if FMAudio, ADSP, USB headset is active, change to sleep mode */
if (ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE)
mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SLEEP,
&resource_req);
else
mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN,
&resource_req);
mmio_write_32(SPM2SW_MAILBOX_0, 0x1);
ext_opand |= MT_SPM_EX_OP_DEVICES_SAVE;
#if defined(CONFIG_MTK_VCOREDVFS_SUPPORT)
/* Notify vcoredvfs suspend enter */
spm_vcorefs_plat_suspend();
#endif
ret = spm_conservation(state_id, ext_opand,
&__spm_suspend, resource_req);
if (ret == 0) {
struct mt_lp_publish_event event = {
.id = MT_LPM_PUBEVENTS_SYS_POWER_OFF,
.val.u32 = 0,
.level = MT_LP_SYSPOWER_LEVEL_SUSPEND,
};
MT_LP_SUSPEND_PUBLISH_EVENT(&event);
}
mt_spm_suspend_ec_pin();
return ret;
}
void mt_spm_suspend_resume(int state_id, uint32_t ext_opand,
struct wake_status **status)
{
struct mt_lp_publish_event event;
struct wake_status *st = NULL;
ext_opand |= MT_SPM_EX_OP_DEVICES_SAVE;
mt_spm_resume_ec_pin();
spm_conservation_finish(state_id, ext_opand, &__spm_suspend, &st);
spm_CSOPLU_ctrl_leave_suspend();
mt_spm_update_lp_stat(&suspend_lp_stat);
#if defined(CONFIG_MTK_VCOREDVFS_SUPPORT)
/* Notify vcoredvfs suspend enter */
spm_vcorefs_plat_resume();
mmio_write_32(SPM2SW_MAILBOX_0, 0x0);
#endif
/*****************************************
* If FMAudio, ADSP, USB headset is active,
* change back to suspend mode and counting in resume
*****************************************/
if (ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) {
mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN, NULL);
suspend_spm_dbg_ext.sleep_suspend_cnt += 1;
}
suspend_ctrl.reg_spm_vcore_req = bak_spm_vcore_req;
suspend_spm_dbg.count += 1;
event.id = MT_LPM_PUBEVENTS_SYS_POWER_ON;
event.val.u32 = 0;
event.level = MT_LP_SYSPOWER_LEVEL_SUSPEND;
if (st) {
if (st->tr.comm.r12 & R12_AP2AP_PEER_WAKEUP_B)
event.val.u32 = MT_LPM_WAKE_MD_WAKEUP_DPMAIF;
if (st->tr.comm.r12 & R12_CCIF0_EVENT_B)
event.val.u32 = MT_LPM_WAKE_MD_WAKEUP_CCIF0;
if (st->tr.comm.r12 & R12_CCIF1_EVENT_B)
event.val.u32 = MT_LPM_WAKE_MD_WAKEUP_CCIF1;
}
if (status)
*status = st;
MT_LP_SUSPEND_PUBLISH_EVENT(&event);
}
int mt_spm_suspend_get_spm_lp(struct spm_lp_scen **lp)
{
if (!lp)
return -1;
*lp = &__spm_suspend;
return 0;
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_SPM_SUSPEND_H
#define MT_SPM_SUSPEND_H
#include <mt_spm_internal.h>
struct suspend_dbg_ctrl {
uint32_t sleep_suspend_cnt;
};
enum mt_spm_suspend_mode {
MT_SPM_SUSPEND_SYSTEM_PDN,
MT_SPM_SUSPEND_SLEEP,
};
int mt_spm_suspend_mode_set(enum mt_spm_suspend_mode mode, void *prv);
int mt_spm_suspend_enter(int state_id, uint32_t ext_opand,
uint32_t reosuce_req);
void mt_spm_suspend_resume(int state_id, uint32_t ext_opand,
struct wake_status **status);
int mt_spm_suspend_get_spm_lp(struct spm_lp_scen **lp);
#endif /* MT_SPM_SUSPEND_H */

View file

@ -0,0 +1,37 @@
#
# 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_${MTK_SOC}
#Add your source code here
LOCAL_SRCS-${CONFIG_MTK_SPM_SUPPORT} := ${LOCAL_DIR}/mt_spm.c
LOCAL_SRCS-${CONFIG_MTK_SPM_SUPPORT} += ${LOCAL_DIR}/mt_spm_conservation.c
LOCAL_SRCS-${CONFIG_MTK_SPM_SUPPORT} += ${LOCAL_DIR}/mt_spm_internal.c
LOCAL_SRCS-${MT_SPM_FEATURE_SUPPORT} += ${LOCAL_DIR}/mt_plat_spm_setting.c
LOCAL_SRCS-${MT_SPM_FEATURE_SUPPORT} += ${LOCAL_DIR}/mt_spm_dispatcher.c
LOCAL_SRCS-${MT_SPM_FEATURE_SUPPORT} += ${LOCAL_DIR}/mt_spm_idle.c
LOCAL_SRCS-${MT_SPM_FEATURE_SUPPORT} += ${LOCAL_DIR}/mt_spm_suspend.c
LOCAL_SRCS-${MT_SPM_FEATURE_SUPPORT} += ${LOCAL_DIR}/mt_spm_stats.c
LOCAL_SRCS-${MT_SPM_FEATURE_SUPPORT} += ${LOCAL_DIR}/constraints/mt_spm_rc_api.c
LOCAL_SRCS-${MT_SPM_FEATURE_SUPPORT} += ${LOCAL_DIR}/constraints/mt_spm_rc_bus26m.c
LOCAL_SRCS-${MT_SPM_FEATURE_SUPPORT} += ${LOCAL_DIR}/constraints/mt_spm_rc_vcore.c
LOCAL_SRCS-${MT_SPM_FEATURE_SUPPORT} += ${LOCAL_DIR}/constraints/mt_spm_rc_syspll.c
LOCAL_SRCS-${MTK_SPM_PMIC_LP_SUPPORT} += ${LOCAL_DIR}/mt_spm_pmic_lp.c
LOCAL_SRCS-${MT_SPM_FEATURE_SUPPORT} += ${LOCAL_DIR}/mt_spm_hwreq.c
LOCAL_SRCS-${CONFIG_MTK_VCOREDVFS_SUPPORT} += ${LOCAL_DIR}/mt_spm_vcorefs.c
LOCAL_SRCS-${CONFIG_MTK_VCOREDVFS_SUPPORT} += ${LOCAL_DIR}/mt_vcore_dvfsrc_plat.c
#Epilogue, build as module
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
$(eval $(call add_defined_option,CONFIG_MTK_VCOREDVFS_SUPPORT))
$(eval $(call add_defined_option,CONFIG_MTK_VCOREDVFS_LK_SUPPORT))
$(eval $(call add_defined_option,CONFIG_MTK_VCOREDVFS_PLAT_CMD))
$(eval $(call add_defined_option,MTK_VCORE_DVFS_PAUSE))

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, MediaTek Inc. All rights reserved.
* Copyright (c) 2023-2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -14,6 +14,9 @@
#define MT_SPM_BIT_SYSPLL (3U)
#define MT_SPM_BIT_DRAM_S0 (4U)
#define MT_SPM_BIT_DRAM_S1 (5U)
#define MT_SPM_BIT_VCORE (6U)
#define MT_SPM_BIT_EMI (7U)
#define MT_SPM_BIT_PMIC (8U)
/* SPM resource request internal bit_mask */
#define MT_SPM_XO_FPM BIT(MT_SPM_BIT_XO_FPM)
@ -22,5 +25,8 @@
#define MT_SPM_SYSPLL BIT(MT_SPM_BIT_SYSPLL)
#define MT_SPM_DRAM_S0 BIT(MT_SPM_BIT_DRAM_S0)
#define MT_SPM_DRAM_S1 BIT(MT_SPM_BIT_DRAM_S1)
#define MT_SPM_VCORE BIT(MT_SPM_BIT_VCORE)
#define MT_SPM_EMI BIT(MT_SPM_BIT_EMI)
#define MT_SPM_PMIC BIT(MT_SPM_BIT_PMIC)
#endif /* MT_SPM_RESOURCE_REQ_H */

View file

@ -31,6 +31,7 @@ MODULES-y += $(MTK_PLAT)/drivers/apusys
MODULES-y += $(MTK_PLAT)/drivers/dp
MODULES-y += $(MTK_PLAT)/drivers/emi
MODULES-y += $(MTK_PLAT)/drivers/mcusys
MODULES-y += $(MTK_PLAT)/drivers/spm
MODULES-y += $(MTK_PLAT)/drivers/timer
MODULES-y += $(MTK_PLAT)/drivers/vcp
MODULES-y += $(MTK_PLAT)/helpers