Commit fe985428 authored by James Liao's avatar James Liao Committed by Yidi Lin
Browse files

mediatek: mt8195: Add CPU hotplug and MCDI support



Implement PSCI platform OPs to support CPU hotplug and MCDI.
Signed-off-by: default avatarJames Liao <jamesjj.liao@mediatek.com>
Change-Id: I1321f7989c8a3d116d698768a7146e8f180ee9c0
parent acc85548
...@@ -15,31 +15,31 @@ ...@@ -15,31 +15,31 @@
#include <mtspmc_private.h> #include <mtspmc_private.h>
void mcucfg_disable_gic_wakeup(uint32_t cluster, uint32_t cpu) void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu)
{ {
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu)); mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
} }
void mcucfg_enable_gic_wakeup(uint32_t cluster, uint32_t cpu) void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu)
{ {
mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu)); mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
} }
void mcucfg_set_bootaddr(uint32_t cluster, uint32_t cpu, uintptr_t bootaddr) void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr)
{ {
assert(cluster == 0U); assert(cluster == 0U);
mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr); mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr);
} }
uintptr_t mcucfg_get_bootaddr(uint32_t cluster, uint32_t cpu) uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu)
{ {
assert(cluster == 0U); assert(cluster == 0U);
return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR)); return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR));
} }
void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64) void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64)
{ {
uint32_t reg; uint32_t reg;
...@@ -57,7 +57,7 @@ void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64) ...@@ -57,7 +57,7 @@ void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64)
/** /**
* Return subsystem's power state. * Return subsystem's power state.
* *
* @mask: mask to SPM_CPU_PWR_STATUS to query the power state * @mask: mask to MCUCFG_CPC_SPMC_PWR_STATUS to query the power state
* of one subsystem. * of one subsystem.
* RETURNS: * RETURNS:
* 0 (the subsys was powered off) * 0 (the subsys was powered off)
...@@ -65,17 +65,17 @@ void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64) ...@@ -65,17 +65,17 @@ void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64)
*/ */
bool spm_get_powerstate(uint32_t mask) bool spm_get_powerstate(uint32_t mask)
{ {
return (mmio_read_32(SPM_CPU_PWR_STATUS) & mask) != 0U; return (mmio_read_32(MCUCFG_CPC_SPMC_PWR_STATUS) & mask) != 0U;
} }
bool spm_get_cluster_powerstate(uint32_t cluster) bool spm_get_cluster_powerstate(unsigned int cluster)
{ {
assert(cluster == 0U); assert(cluster == 0U);
return spm_get_powerstate(MP0_CPUTOP); return spm_get_powerstate(BIT(14));
} }
bool spm_get_cpu_powerstate(uint32_t cluster, uint32_t cpu) bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu)
{ {
uint32_t mask = BIT(cpu); uint32_t mask = BIT(cpu);
...@@ -98,19 +98,12 @@ int spmc_init(void) ...@@ -98,19 +98,12 @@ int spmc_init(void)
mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B); mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B);
mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B); mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B);
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(1));
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(2));
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(3));
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(4));
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(5));
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(6));
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(7));
mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG); mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG); mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG); mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG);
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE); mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_CORE_PWR_ON_EN);
return 0; return 0;
} }
...@@ -121,24 +114,20 @@ int spmc_init(void) ...@@ -121,24 +114,20 @@ int spmc_init(void)
* @cluster: the cluster ID of the CPU which to be powered on * @cluster: the cluster ID of the CPU which to be powered on
* @cpu: the CPU ID of the CPU which to be powered on * @cpu: the CPU ID of the CPU which to be powered on
*/ */
void spm_poweron_cpu(uint32_t cluster, uint32_t cpu) void spm_poweron_cpu(unsigned int cluster, unsigned int cpu)
{ {
uintptr_t cpu_pwr_con = per_cpu(cluster, cpu, SPM_CPU_PWR);
/* set to 0 after BIG VPROC bulk on & before B-core power on seq. */ /* set to 0 after BIG VPROC bulk on & before B-core power on seq. */
if (cpu >= 4U) { if (cpu >= 4U) {
mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U); mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U);
} }
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN); mmio_setbits_32(cpu_pwr_con, PWR_ON);
mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
while (!spm_get_cpu_powerstate(cluster, cpu)) { while (!spm_get_cpu_powerstate(cluster, cpu)) {
} mmio_clrbits_32(cpu_pwr_con, PWR_ON);
mmio_setbits_32(cpu_pwr_con, PWR_ON);
mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
/* Enable Big CPU Last PC */
if (cpu >= 4U) {
mmio_clrbits_32(LAST_PC_REG(cpu), BIT(3));
} }
} }
...@@ -148,7 +137,7 @@ void spm_poweron_cpu(uint32_t cluster, uint32_t cpu) ...@@ -148,7 +137,7 @@ void spm_poweron_cpu(uint32_t cluster, uint32_t cpu)
* @cluster: the cluster ID of the CPU which to be powered off * @cluster: the cluster ID of the CPU which to be powered off
* @cpu: the CPU ID of the CPU which to be powered off * @cpu: the CPU ID of the CPU which to be powered off
*/ */
void spm_poweroff_cpu(uint32_t cluster, uint32_t cpu) void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu)
{ {
/* Set mp0_spmc_pwr_on_cpuX = 0 */ /* Set mp0_spmc_pwr_on_cpuX = 0 */
mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON); mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
...@@ -159,7 +148,7 @@ void spm_poweroff_cpu(uint32_t cluster, uint32_t cpu) ...@@ -159,7 +148,7 @@ void spm_poweroff_cpu(uint32_t cluster, uint32_t cpu)
* *
* @cluster: the cluster index which to be powered off * @cluster: the cluster index which to be powered off
*/ */
void spm_poweroff_cluster(uint32_t cluster) void spm_poweroff_cluster(unsigned int cluster)
{ {
/* No need to power on/off cluster on single cluster platform */ /* No need to power on/off cluster on single cluster platform */
assert(false); assert(false);
...@@ -170,7 +159,7 @@ void spm_poweroff_cluster(uint32_t cluster) ...@@ -170,7 +159,7 @@ void spm_poweroff_cluster(uint32_t cluster)
* *
* @cluster: the cluster index which to be powered on * @cluster: the cluster index which to be powered on
*/ */
void spm_poweron_cluster(uint32_t cluster) void spm_poweron_cluster(unsigned int cluster)
{ {
/* No need to power on/off cluster on single cluster platform */ /* No need to power on/off cluster on single cluster platform */
assert(false); assert(false);
......
...@@ -11,21 +11,21 @@ ...@@ -11,21 +11,21 @@
int spmc_init(void); int spmc_init(void);
void spm_poweron_cpu(uint32_t cluster, uint32_t cpu); void spm_poweron_cpu(unsigned int cluster, unsigned int cpu);
void spm_poweroff_cpu(uint32_t cluster, uint32_t cpu); void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu);
void spm_poweroff_cluster(uint32_t cluster); void spm_poweroff_cluster(unsigned int cluster);
void spm_poweron_cluster(uint32_t cluster); void spm_poweron_cluster(unsigned int cluster);
bool spm_get_cpu_powerstate(uint32_t cluster, uint32_t cpu); bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu);
bool spm_get_cluster_powerstate(uint32_t cluster); bool spm_get_cluster_powerstate(unsigned int cluster);
bool spm_get_powerstate(uint32_t mask); bool spm_get_powerstate(uint32_t mask);
void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64); void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64);
void mcucfg_set_bootaddr(uint32_t cluster, uint32_t cpu, uintptr_t bootaddr); void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr);
uintptr_t mcucfg_get_bootaddr(uint32_t cluster, uint32_t cpu); uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu);
void mcucfg_disable_gic_wakeup(uint32_t cluster, uint32_t cpu); void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu);
void mcucfg_enable_gic_wakeup(uint32_t cluster, uint32_t cpu); void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu);
#endif /* MTSPMC_H */ #endif /* MTSPMC_H */
...@@ -122,19 +122,18 @@ static const struct per_cpu_reg MCUCFG_INITARCH[] = { ...@@ -122,19 +122,18 @@ static const struct per_cpu_reg MCUCFG_INITARCH[] = {
}; };
#define MCUCFG_INITARCH_CPU_BIT(cpu) BIT(16U + cpu) #define MCUCFG_INITARCH_CPU_BIT(cpu) BIT(16U + cpu)
#define LAST_PC_REG(cpu) (MCUCFG_REG(0x308) + (cpu * 0x800))
/* === CPC control */ /* === CPC control */
#define MCUCFG_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814) #define MCUCFG_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
#define MCUCFG_CPC_SPMC_PWR_STATUS MCUCFG_REG(0xa840) #define MCUCFG_CPC_SPMC_PWR_STATUS MCUCFG_REG(0xa840)
/* bit fields of CPC_FLOW_CTRL_CFG */ /* bit fields of CPC_FLOW_CTRL_CFG */
#define CPC_CTRL_ENABLE BIT(16) #define CPC_CTRL_ENABLE BIT(16)
#define SSPM_CORE_PWR_ON_EN BIT(7) /* for cpu-hotplug */
#define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */ #define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */
#define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu) #define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu)
/* bit fields of CPC_SPMC_PWR_STATUS */ /* bit fields of CPC_SPMC_PWR_STATUS */
#define CORE_SPMC_PWR_ON_ACK GENMASK(15, 0) #define CORE_SPMC_PWR_ON_ACK GENMASK(11, 0)
/* === APB Module infracfg_ao */ /* === APB Module infracfg_ao */
#define INFRA_TOPAXI_PROTECTEN INFRACFG_AO_REG(0x0220) #define INFRA_TOPAXI_PROTECTEN INFRACFG_AO_REG(0x0220)
......
...@@ -4,15 +4,361 @@ ...@@ -4,15 +4,361 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
/* common headers */
#include <assert.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <lib/psci/psci.h> #include <lib/psci/psci.h>
/* platform specific headers */
#include <mt_gic_v3.h>
#include <mtspmc.h>
#include <plat/common/platform.h>
#include <plat_mtk_lpm.h>
#include <plat_pm.h>
/*
* Cluster state request:
* [0] : The CPU requires cluster power down
* [1] : The CPU requires cluster power on
*/
#define coordinate_cluster(onoff) write_clusterpwrdn_el1(onoff)
#define coordinate_cluster_pwron() coordinate_cluster(1)
#define coordinate_cluster_pwroff() coordinate_cluster(0)
/* platform secure entry point */
static uintptr_t secure_entrypoint;
/* per-CPU power state */
static unsigned int plat_power_state[PLATFORM_CORE_COUNT];
/* platform CPU power domain - ops */
static const struct mt_lpm_tz *plat_mt_pm;
#define plat_mt_pm_invoke(_name, _cpu, _state) ({ \
int ret = -1; \
if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \
ret = plat_mt_pm->_name(_cpu, _state); \
} \
ret; })
#define plat_mt_pm_invoke_no_check(_name, _cpu, _state) ({ \
if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \
(void) plat_mt_pm->_name(_cpu, _state); \
} \
})
/*
* Common MTK_platform operations to power on/off a
* CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
*/
static void plat_cpu_pwrdwn_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
plat_mt_pm_invoke_no_check(pwr_cpu_dwn, cpu, state);
if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) ||
(req_pstate == 0U)) { /* hotplug off */
coordinate_cluster_pwroff();
}
/* Prevent interrupts from spuriously waking up this CPU */
mt_gic_rdistif_save();
gicv3_cpuif_disable(cpu);
gicv3_rdistif_off(cpu);
}
static void plat_cpu_pwron_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
plat_mt_pm_invoke_no_check(pwr_cpu_on, cpu, state);
coordinate_cluster_pwron();
/* Enable the GIC CPU interface */
gicv3_rdistif_on(cpu);
gicv3_cpuif_enable(cpu);
mt_gic_rdistif_init();
/*
* If mcusys does power down before then restore
* all CPUs' GIC Redistributors
*/
if (IS_MCUSYS_OFF_STATE(state)) {
mt_gic_rdistif_restore_all();
} else {
mt_gic_rdistif_restore();
}
}
/*
* Common MTK_platform operations to power on/off a
* cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
*/
static void plat_cluster_pwrdwn_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
if (plat_mt_pm_invoke(pwr_cluster_dwn, cpu, state) != 0) {
coordinate_cluster_pwron();
/* TODO: return on fail.
* Add a 'return' here before adding any code following
* the if-block.
*/
}
}
static void plat_cluster_pwron_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
if (plat_mt_pm_invoke(pwr_cluster_on, cpu, state) != 0) {
/* TODO: return on fail.
* Add a 'return' here before adding any code following
* the if-block.
*/
}
}
/*
* Common MTK_platform operations to power on/off a
* mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
*/
static void plat_mcusys_pwrdwn_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
if (plat_mt_pm_invoke(pwr_mcusys_dwn, cpu, state) != 0) {
return; /* return on fail */
}
mt_gic_distif_save();
gic_sgi_save_all();
}
static void plat_mcusys_pwron_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
if (plat_mt_pm_invoke(pwr_mcusys_on, cpu, state) != 0) {
return; /* return on fail */
}
mt_gic_init();
mt_gic_distif_restore();
gic_sgi_restore_all();
plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state);
}
/*
* plat_psci_ops implementation
*/
static void plat_cpu_standby(plat_local_state_t cpu_state)
{
uint64_t scr;
scr = read_scr_el3();
write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
isb();
dsb();
wfi();
write_scr_el3(scr);
}
static int plat_power_domain_on(u_register_t mpidr)
{
unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
unsigned int cluster = 0U;
if (cpu >= PLATFORM_CORE_COUNT) {
return PSCI_E_INVALID_PARAMS;
}
if (!spm_get_cluster_powerstate(cluster)) {
spm_poweron_cluster(cluster);
}
/* init CPU reset arch as AARCH64 */
mcucfg_init_archstate(cluster, cpu, true);
mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
spm_poweron_cpu(cluster, cpu);
return PSCI_E_SUCCESS;
}
static void plat_power_domain_on_finish(const psci_power_state_t *state)
{
unsigned long mpidr = read_mpidr_el1();
unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
assert(cpu < PLATFORM_CORE_COUNT);
/* Allow IRQs to wakeup this core in IDLE flow */
mcucfg_enable_gic_wakeup(0U, cpu);
if (IS_CLUSTER_OFF_STATE(state)) {
plat_cluster_pwron_common(cpu, state, 0U);
}
plat_cpu_pwron_common(cpu, state, 0U);
}
static void plat_power_domain_off(const psci_power_state_t *state)
{
unsigned long mpidr = read_mpidr_el1();
unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
assert(cpu < PLATFORM_CORE_COUNT);
plat_cpu_pwrdwn_common(cpu, state, 0U);
spm_poweroff_cpu(0U, cpu);
/* prevent unintended IRQs from waking up the hot-unplugged core */
mcucfg_disable_gic_wakeup(0U, cpu);
if (IS_CLUSTER_OFF_STATE(state)) {
plat_cluster_pwrdwn_common(cpu, state, 0U);
}
}
static void plat_power_domain_suspend(const psci_power_state_t *state)
{
unsigned int cpu = plat_my_core_pos();
assert(cpu < PLATFORM_CORE_COUNT);
plat_mt_pm_invoke_no_check(pwr_prompt, cpu, state);
/* Perform the common CPU specific operations */
plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]);
if (IS_CLUSTER_OFF_STATE(state)) {
/* Perform the common cluster specific operations */
plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]);
}
if (IS_MCUSYS_OFF_STATE(state)) {
/* Perform the common mcusys specific operations */
plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]);
}
}
static void plat_power_domain_suspend_finish(const psci_power_state_t *state)
{
unsigned int cpu = plat_my_core_pos();
assert(cpu < PLATFORM_CORE_COUNT);
if (IS_MCUSYS_OFF_STATE(state)) {
/* Perform the common mcusys specific operations */
plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]);
}
if (IS_CLUSTER_OFF_STATE(state)) {
/* Perform the common cluster specific operations */
plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]);
}
/* Perform the common CPU specific operations */
plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]);
plat_mt_pm_invoke_no_check(pwr_reflect, cpu, state);
}
static int plat_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state)
{
unsigned int pstate = psci_get_pstate_type(power_state);
unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state);
unsigned int cpu = plat_my_core_pos();
if (aff_lvl > PLAT_MAX_PWR_LVL) {
return PSCI_E_INVALID_PARAMS;
}
if (pstate == PSTATE_TYPE_STANDBY) {
req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE;
} else {
unsigned int i;
unsigned int pstate_id = psci_get_pstate_id(power_state);
plat_local_state_t s = MTK_LOCAL_STATE_OFF;
/* Use pstate_id to be power domain state */
if (pstate_id > s) {
s = (plat_local_state_t)pstate_id;
}
for (i = 0U; i <= aff_lvl; i++) {
req_state->pwr_domain_state[i] = s;
}
}
plat_power_state[cpu] = power_state;
return PSCI_E_SUCCESS;
}
static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state)
{
unsigned int lv;
unsigned int cpu = plat_my_core_pos();
for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) {
req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE;
}
plat_power_state[cpu] =
psci_make_powerstate(
MT_PLAT_PWR_STATE_SYSTEM_SUSPEND,
PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL);
flush_dcache_range((uintptr_t)
&plat_power_state[cpu],
sizeof(plat_power_state[cpu]));
}
static const plat_psci_ops_t plat_psci_ops = { static const plat_psci_ops_t plat_psci_ops = {
.cpu_standby = plat_cpu_standby,
.pwr_domain_on = plat_power_domain_on,
.pwr_domain_on_finish = plat_power_domain_on_finish,
.pwr_domain_off = plat_power_domain_off,
.pwr_domain_suspend = plat_power_domain_suspend,
.pwr_domain_suspend_finish = plat_power_domain_suspend_finish,
.validate_power_state = plat_validate_power_state,
.get_sys_suspend_power_state = plat_get_sys_suspend_power_state
}; };
int plat_setup_psci_ops(uintptr_t sec_entrypoint, int plat_setup_psci_ops(uintptr_t sec_entrypoint,
const plat_psci_ops_t **psci_ops) const plat_psci_ops_t **psci_ops)
{ {
*psci_ops = &plat_psci_ops; *psci_ops = &plat_psci_ops;
secure_entrypoint = sec_entrypoint;
/*
* init the warm reset config for boot CPU
* reset arch as AARCH64
* reset addr as function bl31_warm_entrypoint()
*/
mcucfg_init_archstate(0U, 0U, true);
mcucfg_set_bootaddr(0U, 0U, secure_entrypoint);
spmc_init();
plat_mt_pm = mt_plat_cpu_pm_init();
return 0; return 0;
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment