feat(plat/mediatek/mt8186): add CPU hotplug
Implement PSCI platform operations to support CPU hotplug and MCDI. TEST=bringup 8 CPUs successfully on kernel stage. BUG=b:202871018 Change-Id: Ibd5423b70b3ca3f91edaa48d7ca5bc094e751510 Signed-off-by: Garmin.Chang <Garmin.Chang@mediatek.com>
This commit is contained in:
parent
6e5d76bac8
commit
1da57e54b2
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mcucfg.h>
|
||||
#include <mtspmc.h>
|
||||
#include <mtspmc_private.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu)
|
||||
{
|
||||
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
|
||||
}
|
||||
|
||||
void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu)
|
||||
{
|
||||
mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
|
||||
/* Clear cpu's cpc sw hint */
|
||||
mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
|
||||
}
|
||||
|
||||
void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr)
|
||||
{
|
||||
assert(cluster == 0U);
|
||||
|
||||
mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr);
|
||||
}
|
||||
|
||||
uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu)
|
||||
{
|
||||
assert(cluster == 0U);
|
||||
|
||||
return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR));
|
||||
}
|
||||
|
||||
void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
assert(cluster == 0U);
|
||||
|
||||
reg = per_cluster(cluster, MCUCFG_INITARCH);
|
||||
|
||||
if (arm64) {
|
||||
mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
|
||||
} else {
|
||||
mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return subsystem's power state.
|
||||
*
|
||||
* @mask: mask to SPM_CPU_PWR_STATUS to query the power state
|
||||
* of one subsystem.
|
||||
* RETURNS:
|
||||
* 0 (the subsys was powered off)
|
||||
* 1 (the subsys was powered on)
|
||||
*/
|
||||
bool spm_get_powerstate(uint32_t mask)
|
||||
{
|
||||
return (mmio_read_32(SPM_CPU_PWR_STATUS) & mask);
|
||||
}
|
||||
|
||||
bool spm_get_cluster_powerstate(unsigned int cluster)
|
||||
{
|
||||
assert(cluster == 0U);
|
||||
|
||||
return spm_get_powerstate(MP0_CPUTOP);
|
||||
}
|
||||
|
||||
bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu)
|
||||
{
|
||||
uint32_t mask = BIT(cpu);
|
||||
|
||||
assert(cluster == 0U);
|
||||
|
||||
return spm_get_powerstate(mask);
|
||||
}
|
||||
|
||||
int spmc_init(void)
|
||||
{
|
||||
unsigned int cpu = plat_my_core_pos();
|
||||
|
||||
|
||||
INFO("SPM: enable CPC mode\n");
|
||||
|
||||
mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN);
|
||||
|
||||
mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B);
|
||||
mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B);
|
||||
mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B);
|
||||
mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B);
|
||||
mmio_setbits_32(per_cpu(0, 5, 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_clrbits_32(SPM_MCUSYS_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_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
|
||||
|
||||
/* Clear bootup cpu's cpc sw hint */
|
||||
mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Power on a core with specified cluster and core index
|
||||
*
|
||||
* @cluster: the cluster 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(unsigned int cluster, unsigned int cpu)
|
||||
{
|
||||
/* info CPC that CPU hotplug on */
|
||||
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
|
||||
|
||||
/* Set mp0_spmc_pwr_on_cpuX = 1 */
|
||||
mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
|
||||
|
||||
/* wait for power on ack */
|
||||
while (!spm_get_cpu_powerstate(cluster, cpu))
|
||||
;
|
||||
|
||||
/* info CPC that CPU hotplug off */
|
||||
mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Power off a core with specified cluster and core index
|
||||
*
|
||||
* @cluster: the cluster 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(unsigned int cluster, unsigned int cpu)
|
||||
{
|
||||
/* Set mp0_spmc_pwr_on_cpuX = 0 */
|
||||
mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
|
||||
}
|
||||
|
||||
/*
|
||||
* Power off a cluster with specified index
|
||||
*
|
||||
* @cluster: the cluster index which to be powered off
|
||||
*/
|
||||
void spm_poweroff_cluster(unsigned int cluster)
|
||||
{
|
||||
/* No need to power on/off cluster on single cluster platform */
|
||||
assert(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Power on a cluster with specified index
|
||||
*
|
||||
* @cluster: the cluster index which to be powered on
|
||||
*/
|
||||
void spm_poweron_cluster(unsigned int cluster)
|
||||
{
|
||||
/* No need to power on/off cluster on single cluster platform */
|
||||
assert(false);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MTSPMC_H
|
||||
#define MTSPMC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int spmc_init(void);
|
||||
|
||||
void spm_poweron_cpu(unsigned int cluster, unsigned int cpu);
|
||||
void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu);
|
||||
|
||||
void spm_poweroff_cluster(unsigned int cluster);
|
||||
void spm_poweron_cluster(unsigned int cluster);
|
||||
|
||||
bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu);
|
||||
bool spm_get_cluster_powerstate(unsigned int cluster);
|
||||
bool spm_get_powerstate(uint32_t mask);
|
||||
|
||||
void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64);
|
||||
void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr);
|
||||
uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu);
|
||||
|
||||
void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu);
|
||||
void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu);
|
||||
|
||||
#endif /* MTSPMC_H */
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MTSPMC_PRIVATE_H
|
||||
#define MTSPMC_PRIVATE_H
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
unsigned long read_cpuectlr(void);
|
||||
void write_cpuectlr(unsigned long cpuectlr);
|
||||
|
||||
unsigned long read_cpupwrctlr_el1(void);
|
||||
void write_cpupwrctlr_el1(unsigned long cpuectlr);
|
||||
|
||||
/* per_cpu/cluster helper */
|
||||
struct per_cpu_reg {
|
||||
unsigned int cluster_addr;
|
||||
unsigned int cpu_stride;
|
||||
};
|
||||
|
||||
#define per_cpu(cluster, cpu, reg) \
|
||||
(reg[cluster].cluster_addr + (cpu << reg[cluster].cpu_stride))
|
||||
|
||||
#define per_cluster(cluster, reg) (reg[cluster].cluster_addr)
|
||||
|
||||
#define SPM_REG(ofs) (uint32_t)(SPM_BASE + (ofs))
|
||||
#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs))
|
||||
#define INFRACFG_AO_REG(ofs) (uint32_t)(INFRACFG_AO_BASE + (ofs))
|
||||
|
||||
/* SPMC related registers */
|
||||
#define SPM_POWERON_CONFIG_EN SPM_REG(0x000)
|
||||
/* bit-fields of SPM_POWERON_CONFIG_EN */
|
||||
#define PROJECT_CODE (U(0xb16) << 16)
|
||||
#define BCLK_CG_EN BIT(0)
|
||||
|
||||
#define SPM_PWR_STATUS SPM_REG(0x16c)
|
||||
#define SPM_PWR_STATUS_2ND SPM_REG(0x170)
|
||||
#define SPM_CPU_PWR_STATUS SPM_REG(0x174)
|
||||
|
||||
/* bit-fields of SPM_PWR_STATUS */
|
||||
#define MD BIT(0)
|
||||
#define CONN BIT(1)
|
||||
#define DDRPHY BIT(2)
|
||||
#define DISP BIT(3)
|
||||
#define MFG BIT(4)
|
||||
#define ISP BIT(5)
|
||||
#define INFRA BIT(6)
|
||||
#define VDEC BIT(7)
|
||||
#define MP0_CPUTOP BIT(8)
|
||||
#define MP0_CPU0 BIT(9)
|
||||
#define MP0_CPU1 BIT(10)
|
||||
#define MP0_CPU2 BIT(11)
|
||||
#define MP0_CPU3 BIT(12)
|
||||
#define MCUSYS BIT(14)
|
||||
#define MP0_CPU4 BIT(15)
|
||||
#define MP0_CPU5 BIT(16)
|
||||
#define MP0_CPU6 BIT(17)
|
||||
#define MP0_CPU7 BIT(18)
|
||||
#define VEN BIT(21)
|
||||
|
||||
/* SPMC related registers */
|
||||
#define SPM_MCUSYS_PWR_CON SPM_REG(0x200)
|
||||
#define SPM_MP0_CPUTOP_PWR_CON SPM_REG(0x204)
|
||||
#define SPM_MP0_CPU0_PWR_CON SPM_REG(0x208)
|
||||
#define SPM_MP0_CPU1_PWR_CON SPM_REG(0x20c)
|
||||
#define SPM_MP0_CPU2_PWR_CON SPM_REG(0x210)
|
||||
#define SPM_MP0_CPU3_PWR_CON SPM_REG(0x214)
|
||||
#define SPM_MP0_CPU4_PWR_CON SPM_REG(0x218)
|
||||
#define SPM_MP0_CPU5_PWR_CON SPM_REG(0x21c)
|
||||
#define SPM_MP0_CPU6_PWR_CON SPM_REG(0x220)
|
||||
#define SPM_MP0_CPU7_PWR_CON SPM_REG(0x224)
|
||||
|
||||
/* bit-fields of SPM_*_PWR_CON */
|
||||
#define PWR_ON_ACK BIT(31)
|
||||
#define VPROC_EXT_OFF BIT(7)
|
||||
#define DORMANT_EN BIT(6)
|
||||
#define RESETPWRON_CONFIG BIT(5)
|
||||
#define PWR_CLK_DIS BIT(4)
|
||||
#define PWR_ON BIT(2)
|
||||
#define PWR_RST_B BIT(0)
|
||||
|
||||
/* per_cpu registers for SPM_MP0_CPU_PWR_CON */
|
||||
static const struct per_cpu_reg SPM_CPU_PWR[] = {
|
||||
{ .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2U }
|
||||
};
|
||||
|
||||
/* per_cluster registers for SPM_MP0_CPUTOP_PWR_CON */
|
||||
static const struct per_cpu_reg SPM_CLUSTER_PWR[] = {
|
||||
{ .cluster_addr = SPM_MP0_CPUTOP_PWR_CON, .cpu_stride = 0U }
|
||||
};
|
||||
|
||||
/* MCUCFG related registers */
|
||||
#define MCUCFG_MP0_CLUSTER_CFG5 MCUCFG_REG(0xc8e4)
|
||||
/* reset vectors */
|
||||
#define MCUCFG_MP0_CLUSTER_CFG8 MCUCFG_REG(0xc900)
|
||||
#define MCUCFG_MP0_CLUSTER_CFG10 MCUCFG_REG(0xc908)
|
||||
#define MCUCFG_MP0_CLUSTER_CFG12 MCUCFG_REG(0xc910)
|
||||
#define MCUCFG_MP0_CLUSTER_CFG14 MCUCFG_REG(0xc918)
|
||||
#define MCUCFG_MP0_CLUSTER_CFG16 MCUCFG_REG(0xc920)
|
||||
#define MCUCFG_MP0_CLUSTER_CFG18 MCUCFG_REG(0xc928)
|
||||
#define MCUCFG_MP0_CLUSTER_CFG20 MCUCFG_REG(0xc930)
|
||||
#define MCUCFG_MP0_CLUSTER_CFG22 MCUCFG_REG(0xc938)
|
||||
|
||||
/* per_cpu registers for MCUCFG_MP0_CLUSTER_CFG */
|
||||
static const struct per_cpu_reg MCUCFG_BOOTADDR[] = {
|
||||
{ .cluster_addr = MCUCFG_MP0_CLUSTER_CFG8, .cpu_stride = 3U }
|
||||
};
|
||||
|
||||
/* per_cpu registers for MCUCFG_MP0_CLUSTER_CFG5 */
|
||||
static const struct per_cpu_reg MCUCFG_INITARCH[] = {
|
||||
{ .cluster_addr = MCUCFG_MP0_CLUSTER_CFG5, .cpu_stride = 0U }
|
||||
};
|
||||
|
||||
#define MCUCFG_INITARCH_CPU_BIT(cpu) BIT(16U + cpu)
|
||||
/* CPC control */
|
||||
#define MCUCFG_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
|
||||
#define MCUCFG_CPC_SPMC_PWR_STATUS MCUCFG_REG(0xa840)
|
||||
|
||||
/* bit-fields of CPC_FLOW_CTRL_CFG */
|
||||
#define CPC_CTRL_ENABLE BIT(16)
|
||||
#define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */
|
||||
#define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu)
|
||||
|
||||
/* bit-fields of CPC_SPMC_PWR_STATUS */
|
||||
#define CORE_SPMC_PWR_ON_ACK GENMASK(11, 0)
|
||||
|
||||
/* APB module infracfg_ao */
|
||||
#define INFRA_TOPAXI_PROTECTEN INFRACFG_AO_REG(0x0220)
|
||||
#define INFRA_TOPAXI_PROTECTEN_STA0 INFRACFG_AO_REG(0x0224)
|
||||
#define INFRA_TOPAXI_PROTECTEN_STA1 INFRACFG_AO_REG(0x0228)
|
||||
#define INFRA_TOPAXI_PROTECTEN_SET INFRACFG_AO_REG(0x02a0)
|
||||
#define INFRA_TOPAXI_PROTECTEN_CLR INFRACFG_AO_REG(0x02a4)
|
||||
#define INFRA_TOPAXI_PROTECTEN_1 INFRACFG_AO_REG(0x0250)
|
||||
#define INFRA_TOPAXI_PROTECTEN_STA0_1 INFRACFG_AO_REG(0x0254)
|
||||
#define INFRA_TOPAXI_PROTECTEN_STA1_1 INFRACFG_AO_REG(0x0258)
|
||||
#define INFRA_TOPAXI_PROTECTEN_1_SET INFRACFG_AO_REG(0x02a8)
|
||||
#define INFRA_TOPAXI_PROTECTEN_1_CLR INFRACFG_AO_REG(0x02ac)
|
||||
|
||||
/* bit-fields of INFRA_TOPAXI_PROTECTEN */
|
||||
#define MP0_SPMC_PROT_STEP1_0_MASK BIT(12)
|
||||
#define MP0_SPMC_PROT_STEP1_1_MASK (BIT(26) | BIT(12))
|
||||
|
||||
/* SPARK */
|
||||
#define VOLTAGE_04 U(0x40)
|
||||
#define VOLTAGE_05 U(0x60)
|
||||
|
||||
#define PTP3_CPU0_SPMC_SW_CFG MCUCFG_REG(0x200)
|
||||
#define CPU0_ILDO_CONTROL5 MCUCFG_REG(0x334)
|
||||
#define CPU0_ILDO_CONTROL8 MCUCFG_REG(0x340)
|
||||
|
||||
/* bit-fields of CPU0_ILDO_CONTROL5 */
|
||||
#define ILDO_RET_VOSEL GENMASK(7, 0)
|
||||
|
||||
/* bit-fields of PTP3_CPU_SPMC_SW_CFG */
|
||||
#define SW_SPARK_EN BIT(0)
|
||||
|
||||
/* bit-fields of CPU0_ILDO_CONTROL8 */
|
||||
#define ILDO_BYPASS_B BIT(0)
|
||||
|
||||
static const struct per_cpu_reg MCUCFG_SPARK[] = {
|
||||
{ .cluster_addr = PTP3_CPU0_SPMC_SW_CFG, .cpu_stride = 11U }
|
||||
};
|
||||
|
||||
static const struct per_cpu_reg ILDO_CONTROL5[] = {
|
||||
{ .cluster_addr = CPU0_ILDO_CONTROL5, .cpu_stride = 11U }
|
||||
};
|
||||
|
||||
static const struct per_cpu_reg ILDO_CONTROL8[] = {
|
||||
{ .cluster_addr = CPU0_ILDO_CONTROL8, .cpu_stride = 11U }
|
||||
};
|
||||
|
||||
#endif /* MTSPMC_PRIVATE_H */
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MCUCFG_H
|
||||
#define MCUCFG_H
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <stdint.h>
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs))
|
||||
|
||||
#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_REG(0x2290) + ((cpu) * 8))
|
||||
#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_REG(0x2294) + ((cpu) * 8))
|
||||
|
||||
#define MP2_CPUCFG MCUCFG_REG(0x2208)
|
||||
|
||||
#define MP2_CPU0_STANDBYWFE BIT(4)
|
||||
#define MP2_CPU1_STANDBYWFE BIT(5)
|
||||
|
||||
#define MP0_CPUTOP_SPMC_CTL MCUCFG_REG(0x788)
|
||||
#define MP1_CPUTOP_SPMC_CTL MCUCFG_REG(0x78C)
|
||||
#define MP1_CPUTOP_SPMC_SRAM_CTL MCUCFG_REG(0x790)
|
||||
|
||||
#define sw_spark_en BIT(0)
|
||||
#define sw_no_wait_for_q_channel BIT(1)
|
||||
#define sw_fsm_override BIT(2)
|
||||
#define sw_logic_pre1_pdb BIT(3)
|
||||
#define sw_logic_pre2_pdb BIT(4)
|
||||
#define sw_logic_pdb BIT(5)
|
||||
#define sw_iso BIT(6)
|
||||
#define sw_sram_sleepb (U(0x3F) << 7)
|
||||
#define sw_sram_isointb BIT(13)
|
||||
#define sw_clk_dis BIT(14)
|
||||
#define sw_ckiso BIT(15)
|
||||
#define sw_pd (U(0x3F) << 16)
|
||||
#define sw_hot_plug_reset BIT(22)
|
||||
#define sw_pwr_on_override_en BIT(23)
|
||||
#define sw_pwr_on BIT(24)
|
||||
#define sw_coq_dis BIT(25)
|
||||
#define logic_pdbo_all_off_ack BIT(26)
|
||||
#define logic_pdbo_all_on_ack BIT(27)
|
||||
#define logic_pre2_pdbo_all_on_ack BIT(28)
|
||||
#define logic_pre1_pdbo_all_on_ack BIT(29)
|
||||
|
||||
|
||||
#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) \
|
||||
(MCUCFG_REG(0x1c30) + cluster * 0x2000 + cpu * 4)
|
||||
|
||||
#define CPUSYS0_CPU0_SPMC_CTL MCUCFG_REG(0x1c30)
|
||||
#define CPUSYS0_CPU1_SPMC_CTL MCUCFG_REG(0x1c34)
|
||||
#define CPUSYS0_CPU2_SPMC_CTL MCUCFG_REG(0x1c38)
|
||||
#define CPUSYS0_CPU3_SPMC_CTL MCUCFG_REG(0x1c3C)
|
||||
|
||||
#define CPUSYS1_CPU0_SPMC_CTL MCUCFG_REG(0x3c30)
|
||||
#define CPUSYS1_CPU1_SPMC_CTL MCUCFG_REG(0x3c34)
|
||||
#define CPUSYS1_CPU2_SPMC_CTL MCUCFG_REG(0x3c38)
|
||||
#define CPUSYS1_CPU3_SPMC_CTL MCUCFG_REG(0x3c3C)
|
||||
|
||||
#define cpu_sw_spark_en BIT(0)
|
||||
#define cpu_sw_no_wait_for_q_channel BIT(1)
|
||||
#define cpu_sw_fsm_override BIT(2)
|
||||
#define cpu_sw_logic_pre1_pdb BIT(3)
|
||||
#define cpu_sw_logic_pre2_pdb BIT(4)
|
||||
#define cpu_sw_logic_pdb BIT(5)
|
||||
#define cpu_sw_iso BIT(6)
|
||||
#define cpu_sw_sram_sleepb BIT(7)
|
||||
#define cpu_sw_sram_isointb BIT(8)
|
||||
#define cpu_sw_clk_dis BIT(9)
|
||||
#define cpu_sw_ckiso BIT(10)
|
||||
#define cpu_sw_pd (U(0x1F) << 11)
|
||||
#define cpu_sw_hot_plug_reset BIT(16)
|
||||
#define cpu_sw_powr_on_override_en BIT(17)
|
||||
#define cpu_sw_pwr_on BIT(18)
|
||||
#define cpu_spark2ldo_allswoff BIT(19)
|
||||
#define cpu_pdbo_all_on_ack BIT(20)
|
||||
#define cpu_pre2_pdbo_allon_ack BIT(21)
|
||||
#define cpu_pre1_pdbo_allon_ack BIT(22)
|
||||
|
||||
/* CPC related registers */
|
||||
#define CPC_MCUSYS_CPC_OFF_THRES MCUCFG_REG(0xa714)
|
||||
#define CPC_MCUSYS_PWR_CTRL MCUCFG_REG(0xa804)
|
||||
#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
|
||||
#define CPC_MCUSYS_LAST_CORE_REQ MCUCFG_REG(0xa818)
|
||||
#define CPC_MCUSYS_MP_LAST_CORE_RESP MCUCFG_REG(0xa81c)
|
||||
#define CPC_MCUSYS_LAST_CORE_RESP MCUCFG_REG(0xa824)
|
||||
#define CPC_MCUSYS_PWR_ON_MASK MCUCFG_REG(0xa828)
|
||||
#define CPC_MCUSYS_CPU_ON_SW_HINT_SET MCUCFG_REG(0xa8a8)
|
||||
#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR MCUCFG_REG(0xa8ac)
|
||||
#define CPC_MCUSYS_CPC_DBG_SETTING MCUCFG_REG(0xab00)
|
||||
#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE MCUCFG_REG(0xab04)
|
||||
#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE MCUCFG_REG(0xab08)
|
||||
#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE MCUCFG_REG(0xab0c)
|
||||
#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE MCUCFG_REG(0xab10)
|
||||
#define CPC_MCUSYS_TRACE_SEL MCUCFG_REG(0xab14)
|
||||
#define CPC_MCUSYS_TRACE_DATA MCUCFG_REG(0xab20)
|
||||
#define CPC_MCUSYS_CLUSTER_COUNTER MCUCFG_REG(0xab70)
|
||||
#define CPC_MCUSYS_CLUSTER_COUNTER_CLR MCUCFG_REG(0xab74)
|
||||
#define SPARK2LDO MCUCFG_REG(0x2700)
|
||||
/* APB module mcucfg */
|
||||
#define MP0_CA7_CACHE_CONFIG MCUCFG_REG(0x000)
|
||||
#define MP0_AXI_CONFIG MCUCFG_REG(0x02C)
|
||||
#define MP0_MISC_CONFIG0 MCUCFG_REG(0x030)
|
||||
#define MP0_MISC_CONFIG1 MCUCFG_REG(0x034)
|
||||
#define MP0_MISC_CONFIG2 MCUCFG_REG(0x038)
|
||||
#define MP0_MISC_CONFIG_BOOT_ADDR(cpu) (MP0_MISC_CONFIG2 + ((cpu) * 8))
|
||||
#define MP0_MISC_CONFIG3 MCUCFG_REG(0x03C)
|
||||
#define MP0_MISC_CONFIG9 MCUCFG_REG(0x054)
|
||||
#define MP0_CA7_MISC_CONFIG MCUCFG_REG(0x064)
|
||||
|
||||
#define MP0_RW_RSVD0 MCUCFG_REG(0x06C)
|
||||
|
||||
|
||||
#define MP1_CA7_CACHE_CONFIG MCUCFG_REG(0x200)
|
||||
#define MP1_AXI_CONFIG MCUCFG_REG(0x22C)
|
||||
#define MP1_MISC_CONFIG0 MCUCFG_REG(0x230)
|
||||
#define MP1_MISC_CONFIG1 MCUCFG_REG(0x234)
|
||||
#define MP1_MISC_CONFIG2 MCUCFG_REG(0x238)
|
||||
#define MP1_MISC_CONFIG_BOOT_ADDR(cpu) (MP1_MISC_CONFIG2 + ((cpu) * 8))
|
||||
#define MP1_MISC_CONFIG3 MCUCFG_REG(0x23C)
|
||||
#define MP1_MISC_CONFIG9 MCUCFG_REG(0x254)
|
||||
#define MP1_CA7_MISC_CONFIG MCUCFG_REG(0x264)
|
||||
|
||||
#define CCI_ADB400_DCM_CONFIG MCUCFG_REG(0x740)
|
||||
#define SYNC_DCM_CONFIG MCUCFG_REG(0x744)
|
||||
|
||||
#define MP0_CLUSTER_CFG0 MCUCFG_REG(0xC8D0)
|
||||
|
||||
#define MP0_SPMC MCUCFG_REG(0x788)
|
||||
#define MP1_SPMC MCUCFG_REG(0x78C)
|
||||
#define MP2_AXI_CONFIG MCUCFG_REG(0x220C)
|
||||
#define MP2_AXI_CONFIG_ACINACTM BIT(0)
|
||||
#define MP2_AXI_CONFIG_AINACTS BIT(4)
|
||||
|
||||
#define MPx_AXI_CONFIG_ACINACTM BIT(4)
|
||||
#define MPx_AXI_CONFIG_AINACTS BIT(5)
|
||||
#define MPx_CA7_MISC_CONFIG_standbywfil2 BIT(28)
|
||||
|
||||
#define MP0_CPU0_STANDBYWFE BIT(20)
|
||||
#define MP0_CPU1_STANDBYWFE BIT(21)
|
||||
#define MP0_CPU2_STANDBYWFE BIT(22)
|
||||
#define MP0_CPU3_STANDBYWFE BIT(23)
|
||||
|
||||
#define MP1_CPU0_STANDBYWFE BIT(20)
|
||||
#define MP1_CPU1_STANDBYWFE BIT(21)
|
||||
#define MP1_CPU2_STANDBYWFE BIT(22)
|
||||
#define MP1_CPU3_STANDBYWFE BIT(23)
|
||||
|
||||
#define CPUSYS0_SPARKVRETCNTRL MCUCFG_REG(0x1c00)
|
||||
#define CPUSYS0_SPARKEN MCUCFG_REG(0x1c04)
|
||||
#define CPUSYS0_AMUXSEL MCUCFG_REG(0x1c08)
|
||||
#define CPUSYS1_SPARKVRETCNTRL MCUCFG_REG(0x3c00)
|
||||
#define CPUSYS1_SPARKEN MCUCFG_REG(0x3c04)
|
||||
#define CPUSYS1_AMUXSEL MCUCFG_REG(0x3c08)
|
||||
|
||||
#define MP2_PWR_RST_CTL MCUCFG_REG(0x2008)
|
||||
#define MP2_PTP3_CPUTOP_SPMC0 MCUCFG_REG(0x22A0)
|
||||
#define MP2_PTP3_CPUTOP_SPMC1 MCUCFG_REG(0x22A4)
|
||||
|
||||
#define MP2_COQ MCUCFG_REG(0x22BC)
|
||||
#define MP2_COQ_SW_DIS BIT(0)
|
||||
|
||||
#define MP2_CA15M_MON_SEL MCUCFG_REG(0x2400)
|
||||
#define MP2_CA15M_MON_L MCUCFG_REG(0x2404)
|
||||
|
||||
#define CPUSYS2_CPU0_SPMC_CTL MCUCFG_REG(0x2430)
|
||||
#define CPUSYS2_CPU1_SPMC_CTL MCUCFG_REG(0x2438)
|
||||
#define CPUSYS2_CPU0_SPMC_STA MCUCFG_REG(0x2434)
|
||||
#define CPUSYS2_CPU1_SPMC_STA MCUCFG_REG(0x243C)
|
||||
|
||||
#define MP0_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x068)
|
||||
#define MP1_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x268)
|
||||
#define BIG_DBG_PWR_CTRL MCUCFG_REG(0x75C)
|
||||
|
||||
#define MP2_SW_RST_B BIT(0)
|
||||
#define MP2_TOPAON_APB_MASK BIT(1)
|
||||
|
||||
#define B_SW_HOT_PLUG_RESET BIT(30)
|
||||
|
||||
#define B_SW_PD_OFFSET (18U)
|
||||
#define B_SW_PD (U(0x3f) << B_SW_PD_OFFSET)
|
||||
|
||||
#define B_SW_SRAM_SLEEPB_OFFSET (12U)
|
||||
#define B_SW_SRAM_SLEEPB (U(0x3f) << B_SW_SRAM_SLEEPB_OFFSET)
|
||||
|
||||
#define B_SW_SRAM_ISOINTB BIT(9)
|
||||
#define B_SW_ISO BIT(8)
|
||||
#define B_SW_LOGIC_PDB BIT(7)
|
||||
#define B_SW_LOGIC_PRE2_PDB BIT(6)
|
||||
#define B_SW_LOGIC_PRE1_PDB BIT(5)
|
||||
#define B_SW_FSM_OVERRIDE BIT(4)
|
||||
#define B_SW_PWR_ON BIT(3)
|
||||
#define B_SW_PWR_ON_OVERRIDE_EN BIT(2)
|
||||
|
||||
#define B_FSM_STATE_OUT_OFFSET (6U)
|
||||
#define B_FSM_STATE_OUT_MASK (U(0x1f) << B_FSM_STATE_OUT_OFFSET)
|
||||
#define B_SW_LOGIC_PDBO_ALL_OFF_ACK BIT(5)
|
||||
#define B_SW_LOGIC_PDBO_ALL_ON_ACK BIT(4)
|
||||
#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK BIT(3)
|
||||
#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK BIT(2)
|
||||
|
||||
#define B_FSM_OFF (0U << B_FSM_STATE_OUT_OFFSET)
|
||||
#define B_FSM_ON (1U << B_FSM_STATE_OUT_OFFSET)
|
||||
#define B_FSM_RET (2U << B_FSM_STATE_OUT_OFFSET)
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
/* cpu boot mode */
|
||||
enum {
|
||||
MP0_CPUCFG_64BIT_SHIFT = 12U,
|
||||
MP1_CPUCFG_64BIT_SHIFT = 28U,
|
||||
MP0_CPUCFG_64BIT = U(0xf) << MP0_CPUCFG_64BIT_SHIFT,
|
||||
MP1_CPUCFG_64BIT = U(0xf) << MP1_CPUCFG_64BIT_SHIFT
|
||||
};
|
||||
|
||||
enum {
|
||||
MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0U,
|
||||
MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4U,
|
||||
MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8U,
|
||||
MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12U,
|
||||
MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16U,
|
||||
|
||||
MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK =
|
||||
U(0xf) << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT,
|
||||
MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK =
|
||||
U(0xf) << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT,
|
||||
MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK =
|
||||
U(0xf) << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT,
|
||||
MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK =
|
||||
U(0xf) << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT,
|
||||
MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK =
|
||||
U(0xf) << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT
|
||||
};
|
||||
|
||||
enum {
|
||||
MP1_AINACTS_SHIFT = 4U,
|
||||
MP1_AINACTS = 1U << MP1_AINACTS_SHIFT
|
||||
};
|
||||
|
||||
enum {
|
||||
MP1_SW_CG_GEN_SHIFT = 12U,
|
||||
MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT
|
||||
};
|
||||
|
||||
enum {
|
||||
MP1_L2RSTDISABLE_SHIFT = 14U,
|
||||
MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT
|
||||
};
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* MCUCFG_H */
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLAT_MTK_LPM_H
|
||||
#define PLAT_MTK_LPM_H
|
||||
|
||||
#include <lib/psci/psci.h>
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
#define MT_IRQ_REMAIN_MAX U(32)
|
||||
#define MT_IRQ_REMAIN_CAT_LOG BIT(31)
|
||||
|
||||
struct mt_irqremain {
|
||||
unsigned int count;
|
||||
unsigned int irqs[MT_IRQ_REMAIN_MAX];
|
||||
unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX];
|
||||
unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX];
|
||||
};
|
||||
|
||||
#define PLAT_RC_STATUS_READY BIT(0)
|
||||
#define PLAT_RC_STATUS_FEATURE_EN BIT(1)
|
||||
#define PLAT_RC_STATUS_UART_NONSLEEP BIT(31)
|
||||
|
||||
struct mt_lpm_tz {
|
||||
int (*pwr_prompt)(unsigned int cpu, const psci_power_state_t *state);
|
||||
int (*pwr_reflect)(unsigned int cpu, const psci_power_state_t *state);
|
||||
|
||||
int (*pwr_cpu_on)(unsigned int cpu, const psci_power_state_t *state);
|
||||
int (*pwr_cpu_dwn)(unsigned int cpu, const psci_power_state_t *state);
|
||||
|
||||
int (*pwr_cluster_on)(unsigned int cpu,
|
||||
const psci_power_state_t *state);
|
||||
int (*pwr_cluster_dwn)(unsigned int cpu,
|
||||
const psci_power_state_t *state);
|
||||
|
||||
int (*pwr_mcusys_on)(unsigned int cpu, const psci_power_state_t *state);
|
||||
int (*pwr_mcusys_on_finished)(unsigned int cpu,
|
||||
const psci_power_state_t *state);
|
||||
int (*pwr_mcusys_dwn)(unsigned int cpu,
|
||||
const psci_power_state_t *state);
|
||||
};
|
||||
|
||||
const struct mt_lpm_tz *mt_plat_cpu_pm_init(void);
|
||||
|
||||
#endif /* PLAT_MTK_LPM_H */
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLAT_PM_H
|
||||
#define PLAT_PM_H
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
#define MT_PLAT_PWR_STATE_CPU U(1)
|
||||
#define MT_PLAT_PWR_STATE_CLUSTER U(2)
|
||||
#define MT_PLAT_PWR_STATE_MCUSYS U(3)
|
||||
#define MT_PLAT_PWR_STATE_SUSPEND2IDLE U(8)
|
||||
#define MT_PLAT_PWR_STATE_SYSTEM_SUSPEND U(9)
|
||||
|
||||
#define MTK_LOCAL_STATE_RUN U(0)
|
||||
#define MTK_LOCAL_STATE_RET U(1)
|
||||
#define MTK_LOCAL_STATE_OFF U(2)
|
||||
|
||||
#define MTK_AFFLVL_CPU U(0)
|
||||
#define MTK_AFFLVL_CLUSTER U(1)
|
||||
#define MTK_AFFLVL_MCUSYS U(2)
|
||||
#define MTK_AFFLVL_SYSTEM U(3)
|
||||
|
||||
#define IS_CLUSTER_OFF_STATE(s) \
|
||||
is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_CLUSTER])
|
||||
#define IS_MCUSYS_OFF_STATE(s) \
|
||||
is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_MCUSYS])
|
||||
#define IS_SYSTEM_SUSPEND_STATE(s) \
|
||||
is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_SYSTEM])
|
||||
|
||||
#define IS_PLAT_SUSPEND_ID(stateid) \
|
||||
((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE) \
|
||||
|| (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND))
|
||||
|
||||
#endif /* PLAT_PM_H */
|
|
@ -19,6 +19,8 @@
|
|||
#define MTK_DEV_RNG2_BASE MT_GIC_BASE
|
||||
#define MTK_DEV_RNG2_SIZE 0x600000
|
||||
|
||||
#define SPM_BASE (IO_PHYS + 0x00006000)
|
||||
|
||||
/*******************************************************************************
|
||||
* GPIO related constants
|
||||
******************************************************************************/
|
||||
|
|
|
@ -4,16 +4,363 @@
|
|||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/* common headers */
|
||||
#include <assert.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.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_params.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;
|
||||
|
||||
static inline int plat_mt_pm_invoke(int (*func)(unsigned int cpu,
|
||||
const psci_power_state_t *state),
|
||||
int cpu, const psci_power_state_t *state)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if (func != NULL) {
|
||||
ret = func(cpu, state);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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());
|
||||
assert(plat_mt_pm != NULL);
|
||||
|
||||
(void)plat_mt_pm_invoke(plat_mt_pm->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());
|
||||
assert(plat_mt_pm != NULL);
|
||||
|
||||
(void)plat_mt_pm_invoke(plat_mt_pm->pwr_cpu_on, cpu, state);
|
||||
|
||||
coordinate_cluster_pwron();
|
||||
|
||||
/*
|
||||
* If mcusys does power down before then restore
|
||||
* all CPUs' GIC Redistributors
|
||||
*/
|
||||
if (IS_MCUSYS_OFF_STATE(state)) {
|
||||
mt_gic_rdistif_restore_all();
|
||||
} else {
|
||||
gicv3_rdistif_on(cpu);
|
||||
gicv3_cpuif_enable(cpu);
|
||||
mt_gic_rdistif_init();
|
||||
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());
|
||||
assert(plat_mt_pm != NULL);
|
||||
|
||||
if (plat_mt_pm_invoke(plat_mt_pm->pwr_cluster_dwn, cpu, state) != 0) {
|
||||
coordinate_cluster_pwron();
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* Return on fail and 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());
|
||||
assert(plat_mt_pm != NULL);
|
||||
|
||||
if (plat_mt_pm_invoke(plat_mt_pm->pwr_cluster_on, cpu, state) != 0) {
|
||||
/*
|
||||
* TODO:
|
||||
* return on fail and 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());
|
||||
assert(plat_mt_pm != NULL);
|
||||
|
||||
if (plat_mt_pm_invoke(plat_mt_pm->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());
|
||||
assert(plat_mt_pm != NULL);
|
||||
|
||||
if (plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_on, cpu, state) != 0) {
|
||||
/* return on fail */
|
||||
return;
|
||||
}
|
||||
|
||||
mt_gic_init();
|
||||
mt_gic_distif_restore();
|
||||
gic_sgi_restore_all();
|
||||
|
||||
(void)plat_mt_pm_invoke(plat_mt_pm->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);
|
||||
assert(plat_mt_pm != NULL);
|
||||
|
||||
(void)plat_mt_pm_invoke(plat_mt_pm->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);
|
||||
assert(plat_mt_pm != NULL);
|
||||
|
||||
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]);
|
||||
|
||||
(void)plat_mt_pm_invoke(plat_mt_pm->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 = {
|
||||
.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,
|
||||
const plat_psci_ops_t **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();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
|
|||
-I${MTK_PLAT_SOC}/drivers/gpio/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/pmic/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/rtc/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/spmc/ \
|
||||
-I${MTK_PLAT_SOC}/include/
|
||||
|
||||
GICV3_SUPPORT_GIC600 := 1
|
||||
|
@ -55,6 +56,7 @@ BL31_SOURCES += common/desc_image_load.c \
|
|||
${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
|
||||
${MTK_PLAT_SOC}/drivers/pmic/pmic.c \
|
||||
${MTK_PLAT_SOC}/drivers/rtc/rtc.c \
|
||||
${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \
|
||||
${MTK_PLAT_SOC}/plat_pm.c \
|
||||
${MTK_PLAT_SOC}/plat_sip_calls.c \
|
||||
${MTK_PLAT_SOC}/plat_topology.c
|
||||
|
|
Loading…
Reference in New Issue