mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 17:44:19 +00:00
feat(mt8196): add mcdi driver
Add MCDI driver to manage CPU idle states and optimize power consumption. Signed-off-by: Kai Liang <kai.liang@mediatek.com> Change-Id: I3a2e163730dd997dd72f2ebc1375dea38d728cb7
This commit is contained in:
parent
4ba679da8b
commit
5cb0bc07e3
10 changed files with 218 additions and 4 deletions
94
plat/mediatek/common/lpm/mt_lpm_dispatch.c
Normal file
94
plat/mediatek/common/lpm/mt_lpm_dispatch.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2025, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <cdefs.h>
|
||||
|
||||
#include <lpm/mt_lpm_dispatch.h>
|
||||
|
||||
struct mt_dispatch_ctrl mt_dispatcher __section("mt_lpm_s") = {
|
||||
.enable = 0,
|
||||
};
|
||||
|
||||
struct mt_dispatch_ctrl mt_secure_dispatcher __section("mt_secure_lpm_s") = {
|
||||
.enable = 0,
|
||||
};
|
||||
|
||||
u_register_t invoke_mt_lpm_dispatch(u_register_t x1,
|
||||
u_register_t x2,
|
||||
u_register_t x3,
|
||||
u_register_t x4,
|
||||
void *handle,
|
||||
struct smccc_res *smccc_ret)
|
||||
{
|
||||
uint64_t res = 0;
|
||||
uint32_t user;
|
||||
|
||||
if (!IS_MT_LPM_SMC(x1))
|
||||
return 0;
|
||||
|
||||
user = MT_LPM_SMC_USER(x1);
|
||||
if ((user < MT_LPM_SMC_USER_MAX) &&
|
||||
(mt_dispatcher.enable & (BIT(user)))) {
|
||||
res = mt_dispatcher.fn[user](MT_LPM_SMC_USER_ID(x1),
|
||||
x2,
|
||||
x3,
|
||||
x4,
|
||||
handle,
|
||||
smccc_ret);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
DECLARE_SMC_HANDLER(MTK_SIP_MTK_LPM_CONTROL, invoke_mt_lpm_dispatch);
|
||||
|
||||
u_register_t invoke_mt_secure_lpm_dispatch(u_register_t x1,
|
||||
u_register_t x2,
|
||||
u_register_t x3,
|
||||
u_register_t x4,
|
||||
void *handle,
|
||||
struct smccc_res *smccc_ret)
|
||||
{
|
||||
uint64_t res = 0;
|
||||
uint32_t user;
|
||||
|
||||
if (!IS_MT_LPM_SMC(x1))
|
||||
return 0;
|
||||
|
||||
user = MT_LPM_SMC_USER(x1);
|
||||
if (mt_secure_dispatcher.enable & (BIT(user))) {
|
||||
res = mt_secure_dispatcher.fn[user](MT_LPM_SMC_USER_ID(x1),
|
||||
x2,
|
||||
x3,
|
||||
x4,
|
||||
handle,
|
||||
smccc_ret);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
DECLARE_SMC_HANDLER(MTK_SIP_BL_LPM_CONTROL, invoke_mt_secure_lpm_dispatch);
|
||||
|
||||
/* Check lpm smc user number at compile time */
|
||||
CASSERT(MT_LPM_SMC_USER_MAX <= MTK_DISPATCH_ID_MAX,
|
||||
lpm_smc_user_declare_too_large);
|
||||
|
||||
void mt_lpm_dispatcher_registry(unsigned int id, mt_lpm_dispatch_fn fn)
|
||||
{
|
||||
if (id >= MT_LPM_SMC_USER_MAX)
|
||||
return;
|
||||
|
||||
mt_dispatcher.enable |= BIT(id);
|
||||
mt_dispatcher.fn[id] = fn;
|
||||
}
|
||||
|
||||
void mt_secure_lpm_dispatcher_registry(unsigned int id, mt_lpm_dispatch_fn fn)
|
||||
{
|
||||
if (id >= MT_LPM_SMC_USER_MAX)
|
||||
return;
|
||||
|
||||
mt_secure_dispatcher.enable |= BIT(id);
|
||||
mt_secure_dispatcher.fn[id] = fn;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2023, MediaTek Inc. All rights reserved.
|
||||
# Copyright (c) 2023-2025, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
@ -11,6 +11,7 @@ MODULE := lpm
|
|||
LOCAL_SRCS-y := $(LOCAL_DIR)/mt_lp_api.c
|
||||
LOCAL_SRCS-y += $(LOCAL_DIR)/mt_lp_rm.c
|
||||
LOCAL_SRCS-y += $(LOCAL_DIR)/mt_lp_rq.c
|
||||
LOCAL_SRCS-y += ${LOCAL_DIR}/mt_lpm_dispatch.c
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}
|
||||
|
||||
|
|
|
@ -394,6 +394,17 @@ mt_pwr_mcusysoff_reflect:
|
|||
mt_pwr_mcusysoff_break:
|
||||
plat_mt_lp_cpu_rc = -1;
|
||||
|
||||
if (IS_PLAT_ALL_ONLINE_CORES_S2IDLE(state)) {
|
||||
/* set SPM pending if s2idle fail to turn mcusys off */
|
||||
if (suspend_abort_reason == MTK_PM_SUSPEND_ABORT_PWR_REQ)
|
||||
NOTICE("[LPM] PWR_REQ is held\n");
|
||||
else if (suspend_abort_reason == MTK_PM_SUSPEND_ABORT_LAST_CORE)
|
||||
NOTICE("[LPM] suspend last core prot fail\n");
|
||||
else if (suspend_abort_reason ==
|
||||
MTK_PM_SUSPEND_ABORT_RC_INVALID)
|
||||
NOTICE("[LPM] no available RC\n");
|
||||
}
|
||||
|
||||
return MTK_CPUPM_E_FAIL;
|
||||
}
|
||||
|
||||
|
|
33
plat/mediatek/include/lpm/mt_lpm_dispatch.h
Normal file
33
plat/mediatek/include/lpm/mt_lpm_dispatch.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_LPM_DISPATCH_H
|
||||
#define MT_LPM_DISPATCH_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mt_lpm_smc.h"
|
||||
#include <mtk_sip_svc.h>
|
||||
|
||||
#define MTK_DISPATCH_ID_MAX 32
|
||||
|
||||
typedef uint64_t (*mt_lpm_dispatch_fn)(u_register_t x1, u_register_t x2,
|
||||
u_register_t x3, u_register_t x4,
|
||||
void *handle,
|
||||
struct smccc_res *smccc_ret);
|
||||
|
||||
struct mt_dispatch_ctrl {
|
||||
unsigned int enable;
|
||||
mt_lpm_dispatch_fn fn[MT_LPM_SMC_USER_MAX];
|
||||
};
|
||||
|
||||
void mt_lpm_dispatcher_registry(unsigned int id, mt_lpm_dispatch_fn fn);
|
||||
|
||||
void mt_secure_lpm_dispatcher_registry(unsigned int id, mt_lpm_dispatch_fn fn);
|
||||
|
||||
extern struct mt_dispatch_ctrl mt_dispatcher;
|
||||
extern struct mt_dispatch_ctrl mt_secure_dispatcher;
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023, MediaTek Inc. All rights reserved.
|
||||
* Copyright (c) 2024, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -13,6 +13,7 @@
|
|||
_func(MTK_SIP_KERNEL_DFD, 0x205) \
|
||||
_func(MTK_SIP_KERNEL_MSDC, 0x273) \
|
||||
_func(MTK_SIP_VCORE_CONTROL, 0x506) \
|
||||
_func(MTK_SIP_MTK_LPM_CONTROL, 0x507) \
|
||||
_func(MTK_SIP_EMIDBG_CONTROL, 0x50B) \
|
||||
_func(MTK_SIP_IOMMU_CONTROL, 0x514) \
|
||||
_func(MTK_SIP_AUDIO_CONTROL, 0x517) \
|
||||
|
@ -27,6 +28,7 @@
|
|||
|
||||
#define MTK_SIP_SMC_FROM_BL33_TABLE(_func) \
|
||||
_func(MTK_SIP_KERNEL_BOOT, 0x115) \
|
||||
_func(MTK_SIP_BL_LPM_CONTROL, 0x410) \
|
||||
_func(MTK_SIP_BL_EMIMPU_CONTROL, 0x415)
|
||||
|
||||
#endif /* MTK_SIP_DEF_H */
|
||||
|
|
|
@ -371,6 +371,19 @@ static void get_sys_suspend_power_state(psci_power_state_t *req_state)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void __dead2 pwr_domain_pwr_down_wfi(const psci_power_state_t *req_state)
|
||||
{
|
||||
unsigned int cpu = plat_my_core_pos();
|
||||
int ret = MTK_CPUPM_E_NOT_SUPPORT;
|
||||
|
||||
if (IS_CPUIDLE_FN_ENABLE(MTK_CPUPM_FN_PWR_DOMAIN_POWER_DOWN_WFI))
|
||||
ret = imtk_cpu_pwr.ops->pwr_domain_pwr_down_wfi(cpu);
|
||||
if (ret == MTK_CPUPM_E_OK)
|
||||
plat_panic_handler();
|
||||
else
|
||||
psci_power_down_wfi();
|
||||
}
|
||||
|
||||
static void pm_smp_init(unsigned int cpu_id, uintptr_t entry_point)
|
||||
{
|
||||
if (entry_point == 0) {
|
||||
|
@ -382,6 +395,16 @@ static void pm_smp_init(unsigned int cpu_id, uintptr_t entry_point)
|
|||
INFO("[%s:%d] - Initialize finished\n", __func__, __LINE__);
|
||||
}
|
||||
|
||||
static struct plat_pm_pwr_ctrl armv9_0_pwr_ops = {
|
||||
.pwr_domain_suspend = power_domain_suspend,
|
||||
.pwr_domain_suspend_finish = power_domain_suspend_finish,
|
||||
.validate_power_state = validate_power_state,
|
||||
#if CONFIG_MTK_SUPPORT_SYSTEM_SUSPEND
|
||||
.get_sys_suspend_power_state = get_sys_suspend_power_state,
|
||||
#endif
|
||||
.pwr_domain_pwr_down_wfi = pwr_domain_pwr_down_wfi,
|
||||
};
|
||||
|
||||
struct plat_pm_smp_ctrl armv9_0_smp_ops = {
|
||||
.init = pm_smp_init,
|
||||
.pwr_domain_on = power_domain_on,
|
||||
|
@ -416,6 +439,50 @@ int plat_pm_invoke_func(enum mtk_cpu_pm_mode mode, unsigned int id, void *priv)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int register_cpu_pm_ops(unsigned int fn_flags, struct mtk_cpu_pm_ops *ops)
|
||||
{
|
||||
int success = 1;
|
||||
unsigned int fns = 0;
|
||||
|
||||
if (!ops || imtk_cpu_pwr.ops) {
|
||||
ERROR("[%s:%d] register cpu_pm fail !!\n", __FILE__, __LINE__);
|
||||
return MTK_CPUPM_E_ERR;
|
||||
}
|
||||
CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_RESUME_CORE,
|
||||
cpu_resume, 1, success, fns);
|
||||
CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_SUSPEND_CORE,
|
||||
cpu_suspend, 1, success, fns);
|
||||
CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_RESUME_CLUSTER,
|
||||
cluster_resume, 1, success, fns);
|
||||
CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_SUSPEND_CLUSTER,
|
||||
cluster_suspend, 1, success, fns);
|
||||
CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_RESUME_MCUSYS,
|
||||
mcusys_resume, 1,
|
||||
success, fns);
|
||||
CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_SUSPEND_MCUSYS,
|
||||
mcusys_suspend, 1, success, fns);
|
||||
CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_CPUPM_GET_PWR_STATE,
|
||||
get_pstate, 1, success, fns);
|
||||
CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_PWR_STATE_VALID,
|
||||
pwr_state_valid, 1, success, fns);
|
||||
CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_INIT,
|
||||
init, 1, success, fns);
|
||||
CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_PWR_DOMAIN_POWER_DOWN_WFI,
|
||||
pwr_domain_pwr_down_wfi, 1, success, fns);
|
||||
if (success) {
|
||||
imtk_cpu_pwr.ops = ops;
|
||||
imtk_cpu_pwr.fn_mask |= fns;
|
||||
plat_pm_ops_setup_pwr(&armv9_0_pwr_ops);
|
||||
INFO("[%s:%d] CPU pwr ops register success, support:0x%x\n",
|
||||
__func__, __LINE__, fns);
|
||||
} else {
|
||||
ERROR("[%s:%d] register cpu_pm ops fail !, fn:0x%x\n",
|
||||
__func__, __LINE__, fn_flags);
|
||||
assert(0);
|
||||
}
|
||||
return MTK_CPUPM_E_OK;
|
||||
}
|
||||
|
||||
int register_cpu_smp_ops(unsigned int fn_flags, struct mtk_cpu_smp_ops *ops)
|
||||
{
|
||||
int success = 1;
|
||||
|
|
|
@ -45,6 +45,9 @@ int plat_pm_ops_setup_pwr(struct plat_pm_pwr_ctrl *ops)
|
|||
mtk_pm_ops.get_sys_suspend_power_state = ops->get_sys_suspend_power_state;
|
||||
}
|
||||
|
||||
if (!mtk_pm_ops.pwr_domain_pwr_down_wfi)
|
||||
mtk_pm_ops.pwr_domain_pwr_down_wfi = ops->pwr_domain_pwr_down_wfi;
|
||||
|
||||
mtk_pm_status |= MTK_PM_ST_PWR_READY;
|
||||
#endif
|
||||
return MTK_CPUPM_E_OK;
|
||||
|
|
|
@ -258,7 +258,6 @@
|
|||
******************************************************************************/
|
||||
#define CPU_EB_TCM_BASE 0x0C2CF000
|
||||
#define CPU_EB_TCM_SIZE 0x1000
|
||||
#define CPU_EB_MBOX3_OFFSET 0xFCE0
|
||||
#define CPU_EB_TCM_CNT_BASE 0x0C2CC000
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
@ -36,17 +36,20 @@ CONFIG_MTK_APUSYS_SEC_CTRL := y
|
|||
CONFIG_MTK_APUSYS_SETUP_CE := y
|
||||
CONFIG_MTK_MCUSYS := y
|
||||
MCUSYS_VERSION := v4
|
||||
MCUPM_VERSION := v3
|
||||
CONFIG_MTK_PM_SUPPORT := y
|
||||
CONFIG_MTK_PM_ARCH := 9_0
|
||||
CONFIG_MTK_CPU_PM_SUPPORT := y
|
||||
CONFIG_MTK_CPU_PM_ARCH := 5_4
|
||||
CONFIG_MTK_SMP_EN := y
|
||||
CONFIG_MTK_CPU_SUSPEND_EN := n
|
||||
CONFIG_MTK_CPU_SUSPEND_EN := y
|
||||
CONFIG_MTK_SPM_VERSION := mt8196
|
||||
CONFIG_MTK_SUPPORT_SYSTEM_SUSPEND := n
|
||||
CONFIG_MTK_TINYSYS_VCP := y
|
||||
CPU_PWR_TOPOLOGY := group_4_3_1
|
||||
CPU_PM_CORE_ARCH64_ONLY := y
|
||||
CPU_PM_DOMAIN_CORE_ONLY := n
|
||||
CPU_PM_SUSPEND_NOTIFY := y
|
||||
CPU_PM_TINYSYS_SUPPORT := y
|
||||
MTK_PUBEVENT_ENABLE := y
|
||||
CONFIG_MTK_PMIC := y
|
||||
|
|
|
@ -24,6 +24,7 @@ PLAT_INCLUDES := -I${MTK_PLAT}/common \
|
|||
-Idrivers/arm/gic \
|
||||
|
||||
MODULES-y += $(MTK_PLAT)/common
|
||||
MODULES-y += $(MTK_PLAT)/common/lpm
|
||||
MODULES-y += $(MTK_PLAT)/lib/mtk_init
|
||||
MODULES-y += $(MTK_PLAT)/lib/pm
|
||||
MODULES-y += $(MTK_PLAT)/drivers/apusys
|
||||
|
|
Loading…
Add table
Reference in a new issue