mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-18 02:24:18 +00:00

Add topology module to support CPU power state control. Signed-off-by: Kai Liang <kai.liang@mediatek.com> Change-Id: I0cc1e5a426762b1b29bff1e940e077643da02e5e
125 lines
2.9 KiB
C
125 lines
2.9 KiB
C
/*
|
|
* Copyright (c) 2025, MediaTek Inc. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <stdint.h>
|
|
|
|
#include <lib/spinlock.h>
|
|
#include <platform_def.h>
|
|
|
|
#include "../inc/pwr_topology.h"
|
|
#include <lib/pm/mtk_pm.h>
|
|
#include <lpm/mt_lp_rm.h>
|
|
|
|
#ifdef MT_CPU_PM_USING_BAKERY_LOCK
|
|
DEFINE_BAKERY_LOCK(mt_pwr_lock);
|
|
|
|
#define plat_pwr_lock_init() bakery_lock_init(&mt_pwr_lock)
|
|
|
|
#define plat_pwr_lock() bakery_lock_get(&mt_pwr_lock)
|
|
|
|
#define plat_pwr_unlock() bakery_lock_release(&mt_pwr_lock)
|
|
#else
|
|
spinlock_t mt_pwr_lock;
|
|
|
|
#define plat_pwr_lock_init()
|
|
#define plat_pwr_lock() spin_lock(&mt_pwr_lock)
|
|
|
|
#define plat_pwr_unlock() spin_unlock(&mt_pwr_lock)
|
|
#endif
|
|
|
|
enum mt_pwr_domain_node {
|
|
MT_PWR_NONMCUSYS = 0,
|
|
MT_PWR_MCUSYS_PDN,
|
|
MT_PWR_MAX
|
|
};
|
|
|
|
#if CONFIG_MTK_PM_SUPPORT && CONFIG_MTK_CPU_SUSPEND_EN && \
|
|
!CPU_PM_DOMAIN_CORE_ONLY
|
|
static int mt_pwr_domain_st[MT_PWR_MAX];
|
|
#endif
|
|
|
|
#define ALL_IN_ONE_GROUP 0xFF
|
|
unsigned int pwr_domain_coordination(enum pwr_domain_status pwr,
|
|
const mtk_pstate_type psci_state,
|
|
const struct mtk_cpupm_pwrstate *state,
|
|
afflv_prepare fn)
|
|
{
|
|
unsigned int pstate = 0;
|
|
|
|
#if CONFIG_MTK_PM_SUPPORT && CONFIG_MTK_CPU_SUSPEND_EN && \
|
|
!CPU_PM_DOMAIN_CORE_ONLY
|
|
unsigned int is_flush = 0;
|
|
struct pwr_toplogy tp = {
|
|
.cur_group_bit = ALL_IN_ONE_GROUP,
|
|
.group = ALL_IN_ONE_GROUP,
|
|
};
|
|
|
|
/* Skip to process smp */
|
|
if (pwr > PWR_DOMAIN_OFF)
|
|
return pstate;
|
|
|
|
if (!IS_MT_PLAT_PWR_STATE_MCUSYS(state->pwr.state_id)) {
|
|
plat_pwr_lock();
|
|
if (pwr == PWR_DOMAIN_OFF)
|
|
mt_pwr_domain_st[MT_PWR_NONMCUSYS] += 1;
|
|
else
|
|
mt_pwr_domain_st[MT_PWR_NONMCUSYS] -= 1;
|
|
flush_dcache_range(
|
|
(uintptr_t)&mt_pwr_domain_st[MT_PWR_NONMCUSYS],
|
|
sizeof(mt_pwr_domain_st[MT_PWR_NONMCUSYS]));
|
|
plat_pwr_unlock();
|
|
}
|
|
|
|
plat_pwr_lock();
|
|
if (state->pwr.afflv >= PLAT_MT_CPU_SUSPEND_CLUSTER)
|
|
pstate |= MT_CPUPM_PWR_DOMAIN_CLUSTER;
|
|
|
|
if (psci_get_pstate_pwrlvl(psci_state) >= PLAT_MT_CPU_SUSPEND_CLUSTER)
|
|
pstate |= MT_CPUPM_PWR_DOMAIN_PERCORE_DSU;
|
|
|
|
if (pwr == PWR_DOMAIN_OFF) {
|
|
if (IS_PLAT_MCUSYSOFF_AFFLV(state->pwr.afflv) &&
|
|
(mt_pwr_domain_st[MT_PWR_NONMCUSYS] == 0)) {
|
|
int ret = MTK_CPUPM_E_OK;
|
|
|
|
tp.group = ALL_IN_ONE_GROUP;
|
|
if (fn)
|
|
ret = fn(1, state, &tp);
|
|
|
|
if (ret == MTK_CPUPM_E_OK) {
|
|
pstate |= MT_CPUPM_PWR_DOMAIN_MCUSYS;
|
|
mt_pwr_domain_st[MT_PWR_MCUSYS_PDN] += 1;
|
|
is_flush = 1;
|
|
}
|
|
}
|
|
} else {
|
|
if (mt_pwr_domain_st[MT_PWR_MCUSYS_PDN]) {
|
|
tp.group = 0x0;
|
|
if (fn)
|
|
fn(1, state, &tp);
|
|
pstate |= MT_CPUPM_PWR_DOMAIN_MCUSYS;
|
|
mt_pwr_domain_st[MT_PWR_MCUSYS_PDN] -= 1;
|
|
is_flush = 1;
|
|
}
|
|
if (mt_pwr_domain_st[MT_PWR_NONMCUSYS] < 0)
|
|
assert(0);
|
|
}
|
|
|
|
if (is_flush)
|
|
flush_dcache_range(
|
|
(uintptr_t)&mt_pwr_domain_st[MT_PWR_MCUSYS_PDN],
|
|
sizeof(mt_pwr_domain_st[MT_PWR_MCUSYS_PDN]));
|
|
|
|
plat_pwr_unlock();
|
|
#endif
|
|
return pstate;
|
|
}
|
|
|
|
void pwr_topology_init(void)
|
|
{
|
|
plat_pwr_lock_init();
|
|
}
|