diff options
author | Bai Ping <ping.bai@nxp.com> | 2017-11-10 12:45:30 +0800 |
---|---|---|
committer | Abel Vesa <abel.vesa@nxp.com> | 2018-06-11 10:08:40 +0300 |
commit | 34fbf7a35c83c879a0ca385b0200858641ca37b4 (patch) | |
tree | 58618b546ef33bbf9dba4dd97e8f68ee7f64bea2 /plat/imx/imx8mq | |
parent | bf35eec4a53aa16bc6b03caa909930bbbd96c539 (diff) |
plat: imx8mq: enable cpuidle support on iMX8MQ
Refact the PSCI related code. Enable cpuidle support
on i.MX8MQ for CPU idle support.
Signed-off-by: Bai Ping <ping.bai@nxp.com>
Diffstat (limited to 'plat/imx/imx8mq')
-rw-r--r-- | plat/imx/imx8mq/ddrc.c | 14 | ||||
-rw-r--r-- | plat/imx/imx8mq/gpc.c | 566 | ||||
-rw-r--r-- | plat/imx/imx8mq/imx8m_psci.c | 174 | ||||
-rw-r--r-- | plat/imx/imx8mq/include/platform_def.h | 5 | ||||
-rw-r--r-- | plat/imx/imx8mq/include/soc.h | 57 |
5 files changed, 450 insertions, 366 deletions
diff --git a/plat/imx/imx8mq/ddrc.c b/plat/imx/imx8mq/ddrc.c index f649dd98..2557d2b2 100644 --- a/plat/imx/imx8mq/ddrc.c +++ b/plat/imx/imx8mq/ddrc.c @@ -2599,7 +2599,7 @@ void lpddr4_cfg_phy(void) void ddrc_enter_retention(void) { - NOTICE("enter LPDDR4 retention\n"); + INFO("enter LPDDR4 retention\n"); /* save the ddr phy trained csr in ocram */ if (!trained_csr_saved) { @@ -2784,7 +2784,7 @@ void lpddr4_dvfs_hwffc(int init_vrcg, int init_fsp, int target_freq, { uint32_t tmp, tmp_t; - NOTICE("hwffc enter\n"); + INFO("hwffc enter\n"); /* step 1: hwffc flow enter, set the HWFCCCTL */ tmp = ((init_fsp << 4) & 0x10) | ((init_vrcg << 5) & 0x20) | 0x40; @@ -2914,7 +2914,7 @@ void lpddr4_dvfs_hwffc(int init_vrcg, int init_fsp, int target_freq, while ((mmio_read_32(IMX_DDRC_BASE + DDRC_STAT) & 0x3) != 0x1) ; - NOTICE("hwffc exit\n"); + INFO("hwffc exit\n"); } spinlock_t dfs_lock; @@ -2958,10 +2958,14 @@ int lpddr4_dvfs_handler(uint32_t smc_fid, /* trigger the IRQ */ for (int i = 0; i < 4; i++) { int irq = irqs_used[i] % 32; - if (cpu_id != i && (online_cores & (0x1 << (i * 8)))) + if (cpu_id != i && (online_cores & (0x1 << (i * 8)))) { mmio_write_32(0x38800204 + (irqs_used[i] / 32) * 4, (1 << irq)); + mmio_write_32(0x303a0040, mmio_read_32(0x303a0040) & ~(0x1)); + } } + mmio_write_32(0x30340004, mmio_read_32(0x30340004) | (1 << 12)); + /* make sure all the core in WFE */ online_cores &= ~(0x1 << (cpu_id * 8)); while (1) { @@ -2969,6 +2973,8 @@ int lpddr4_dvfs_handler(uint32_t smc_fid, break; } + mmio_write_32(0x30340004, mmio_read_32(0x30340004) & ~(1 << 12)); + lpddr4_dvfs_hwffc(init_vrcg, init_fsp, target_freq, discamdrain); init_fsp = (~init_fsp) & 0x1; wait_ddrc_hwffc_done = false; diff --git a/plat/imx/imx8mq/gpc.c b/plat/imx/imx8mq/gpc.c index fb3ae7bb..3da8aadf 100644 --- a/plat/imx/imx8mq/gpc.c +++ b/plat/imx/imx8mq/gpc.c @@ -16,11 +16,6 @@ #include <fsl_sip.h> #include <soc.h> -#define GPC_LPCR_A53_BSC 0x0 -#define GPC_LPCR_A53_BSC2 0x108 -#define GPC_LPCR_A53_AD 0x4 -#define GPC_LPCR_M4 0x8 -#define GPC_SLPCR 0x14 #define GPC_MST_CPU_MAPPING 0x18 #define GPC_PGC_ACK_SEL_A53 0x24 #define GPC_IMR1_CORE0_A53 0x30 @@ -48,43 +43,6 @@ #define GPC_PGC_SCU_TIMMING 0x910 #define GPC_SLOT0_CFG 0xb0 -#define LPCR_A53_BSC_CPU_CLK_ON_LPM 0x4000 -#define LPCR_A53_BSC_LPM0 0x3 -#define LPCR_A53_BSC_LPM1 0xc -#define LPCR_A53_BSC2_LPM2 0x3 -#define LPCR_A53_BSC2_LPM3 0xc - -#define LPCR_A53_AD_L2PGE 0x80000000 -#define LPCR_A53_AD_EN_C3_PUP 0x8000000 -#define LPCR_A53_AD_EN_C3_IRQ_PUP 0x4000000 -#define LPCR_A53_AD_EN_C2_PUP 0x2000000 -#define LPCR_A53_AD_EN_C2_IRQ_PUP 0x1000000 -#define LPCR_A53_AD_EN_C3_PDN 0x80000 -#define LPCR_A53_AD_EN_C3_WFI_PDN 0x40000 -#define LPCR_A53_AD_EN_C2_PDN 0x20000 -#define LPCR_A53_AD_EN_C2_WFI_PDN 0x10000 -#define LPCR_A53_AD_EN_C1_PUP 0x800 -#define LPCR_A53_AD_EN_C1_IRQ_PUP 0x400 -#define LPCR_A53_AD_EN_C0_PUP 0x200 -#define LPCR_A53_AD_EN_C0_IRQ_PUP 0x100 -#define LPCR_A53_AD_EN_L2_WFI_PDN 0x20 -#define LPCR_A53_AD_EN_PLAT_PDN 0x10 -#define LPCR_A53_AD_EN_C1_PDN 0x8 -#define LPCR_A53_AD_EN_C1_WFI_PDN 0x4 -#define LPCR_A53_AD_EN_C0_PDN 0x2 -#define LPCR_A53_AD_EN_C0_WFI_PDN 0x1 - -#define A53_LPM_WAIT 0x5 -#define A53_LPM_STOP 0xa - -#define SLPCR_EN_DSM 0x80000000 -#define SLPCR_RBC_EN 0x40000000 -#define SLPCR_VSTBY 0x4 -#define SLPCR_SBYOS 0x2 -#define SLPCR_BYPASS_PMIC_READY 0x1 -#define SLPCR_A53_FASTWUP_STOP (1 << 17) -#define SLPCR_A53_FASTWUP_WAIT (1 << 16) - #define GPC_CPU_PGC_SW_PUP_REQ 0xf0 #define GPC_CPU_PGC_SW_PDN_REQ 0xfc #define BM_CPU_PGC_SW_PDN_PUP_REQ 0x1 @@ -106,8 +64,26 @@ #define ANAMIX_HW_DRAM_PLL_CFG0 0x60 #define ANAMIX_HW_ANAMIX_MISC_CFG 0x70 -static uint32_t gpc_saved_imrs[128]; -static uint32_t gpc_wake_irqs[128]; +#define LPCR_A53_BSC 0x0 +#define LPCR_A53_BSC2 0x108 +#define LPCR_A53_AD 0x4 +#define LPCR_M4 0x8 +#define SLPCR 0x14 +#define SLPCR_EN_DSM (1 << 31) +#define SLPCR_RBC_EN (1 << 30) +#define SLPCR_A53_FASTWUP_STOP (1 << 17) +#define SLPCR_A53_FASTWUP_WAIT (1 << 16) +#define SLPCR_VSTBY (1 << 2) +#define SLPCR_SBYOS (1 << 1) +#define SLPCR_BYPASS_PMIC_READY 0x1 +#define A53_LPM_WAIT 0x5 +#define A53_LPM_STOP 0xa + +#define GPC_SLOT0_CFG 0xb0 +#define SRC_GPR1_OFFSET 0x74 + +static uint32_t gpc_saved_imrs[4]; +static uint32_t gpc_wake_irqs[4]; static bool is_pcie1_power_down = true; static uint32_t gpc_pu_m_core_offset[11] = { @@ -128,198 +104,286 @@ void imx_gpc_set_m_core_pgc(unsigned int offset, bool pdn) mmio_write_32(IMX_GPC_BASE + offset, val); } -void imx_gpc_set_lpm_mode(enum imx_cpu_pwr_mode mode) +void imx_set_cpu_secure_entry(int core_id, uintptr_t sec_entrypoint) { - uint32_t val1, val2, val3, val4; - - val1 = mmio_read_32(IMX_GPC_BASE + GPC_LPCR_A53_BSC); - val2 = mmio_read_32(IMX_GPC_BASE + GPC_LPCR_A53_BSC2); - val3 = mmio_read_32(IMX_GPC_BASE + GPC_SLPCR); - val4 = mmio_read_32(IMX_GPC_BASE + GPC_LPCR_A53_AD); - - /* all core's LPM setting must be same */ - val1 &= ~(LPCR_A53_BSC_LPM0 | LPCR_A53_BSC_LPM1); - val2 &= ~(LPCR_A53_BSC2_LPM2 | LPCR_A53_BSC2_LPM3); - val3 &= ~(SLPCR_EN_DSM | SLPCR_RBC_EN | SLPCR_VSTBY | - SLPCR_SBYOS | SLPCR_BYPASS_PMIC_READY); - val4 |= (1 << 5); - - switch(mode) { - case WAIT_CLOCKED: - break; - case WAIT_UNCLOCKED: - val1 |= A53_LPM_WAIT; - val2 |= A53_LPM_WAIT; - val1 &= ~LPCR_A53_BSC_CPU_CLK_ON_LPM; - break; - case STOP_POWER_ON: - val1 |= A53_LPM_STOP; - val2 |= A53_LPM_STOP; - val1 &= ~LPCR_A53_BSC_CPU_CLK_ON_LPM; - val3 |= SLPCR_EN_DSM; - val3 |= SLPCR_RBC_EN; - val3 |= SLPCR_BYPASS_PMIC_READY; - break; - case STOP_POWER_OFF: - val1 |= A53_LPM_STOP; - val2 |= A53_LPM_STOP; - val1 &= ~LPCR_A53_BSC_CPU_CLK_ON_LPM; - val3 |= SLPCR_EN_DSM; - val3 &= ~SLPCR_A53_FASTWUP_STOP; - val3 |= SLPCR_RBC_EN; - val3 |= SLPCR_VSTBY; - val3 |= SLPCR_SBYOS; - val3 |= SLPCR_BYPASS_PMIC_READY; - val4 &= ~(1 << 5); - break; - default: - break; - } + uint64_t temp_base; - mmio_write_32(IMX_GPC_BASE + GPC_LPCR_A53_BSC, val1); - mmio_write_32(IMX_GPC_BASE + GPC_LPCR_A53_BSC2, val2); - mmio_write_32(IMX_GPC_BASE + GPC_LPCR_A53_AD, val4); - mmio_write_32(IMX_GPC_BASE + GPC_SLPCR, val3); + temp_base = (uint64_t) sec_entrypoint; + temp_base >>= 2; + + mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3), + ((uint32_t)(temp_base >> 22) & 0xffff)); + mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3) + 4, + ((uint32_t)temp_base & 0x003fffff)); } -/* enable CORE LPM PDN/WUP in AD register */ -void imx_gpc_set_cpu_power_gate_by_lpm(unsigned int cpu, bool pdn) +/* use wfi power down the core */ +void imx_set_cpu_pwr_off(int core_id) { - uint32_t mask, val; - - val = mmio_read_32(IMX_GPC_BASE + GPC_LPCR_A53_AD); - - switch(cpu) { - case 0: - mask = LPCR_A53_AD_EN_C0_PDN | LPCR_A53_AD_EN_C0_PUP; - break; - case 1: - mask = LPCR_A53_AD_EN_C1_PDN | LPCR_A53_AD_EN_C1_PUP; - break; - case 2: - mask = LPCR_A53_AD_EN_C2_PDN | LPCR_A53_AD_EN_C3_PUP; - break; - case 3: - mask = LPCR_A53_AD_EN_C3_PDN | LPCR_A53_AD_EN_C3_PUP; - break; - default: - return; - } + uint32_t val; - if (pdn) - val |= mask; - else - val &= ~mask; + /* enable the wfi power down of the core */ + val = mmio_read_32(IMX_GPC_BASE + 0x4); + val |= (1 << (core_id < 2 ? core_id * 2 : (core_id - 2) * 2 + 16)); + val |= 1 << (core_id + 20); + mmio_write_32(IMX_GPC_BASE + 0x4, val); - mmio_write_32(IMX_GPC_BASE + GPC_LPCR_A53_AD, val); -} + /* assert the pcg pcr bit of the core */ + val = mmio_read_32(IMX_GPC_BASE + 0x800 + 0x40 * core_id); + val |= (1 << 0); + mmio_write_32(IMX_GPC_BASE + 0x800 + 0x40 * core_id, val); +}; -/* enable PLAT/SCU power down in AD register */ -void imx_gpc_set_plat_power_gate_by_lpm(bool pdn) +/* use the sw method to power up the core */ +void imx_set_cpu_pwr_on(int core_id) { uint32_t val; - val = mmio_read_32(IMX_GPC_BASE + GPC_LPCR_A53_AD); - val &= ~(LPCR_A53_AD_EN_PLAT_PDN | LPCR_A53_AD_L2PGE); + /* clear the wfi power down bit of the core */ + val = mmio_read_32(IMX_GPC_BASE + 0x4); + val &= ~(1 << (core_id < 2 ? core_id * 2 : (core_id - 2) * 2 + 16)); + mmio_write_32(IMX_GPC_BASE + 0x4, val); - if (pdn) - val |= LPCR_A53_AD_EN_PLAT_PDN | LPCR_A53_AD_L2PGE; + /* assert the ncpuporeset */ + val = mmio_read_32(IMX_SRC_BASE + 0x8); + val &= ~(1 << core_id); + mmio_write_32(IMX_SRC_BASE + 0x8, val); - mmio_write_32(IMX_GPC_BASE + GPC_LPCR_A53_AD, val); + /* assert the pcg pcr bit of the core */ + val = mmio_read_32(IMX_GPC_BASE + 0x800 + 0x40 * core_id); + val |= (1 << 0); + mmio_write_32(IMX_GPC_BASE + 0x800 + 0x40 * core_id, val); + + /* sw power up the core */ + val = mmio_read_32(IMX_GPC_BASE + 0xf0); + val |= (1 << core_id); + mmio_write_32(IMX_GPC_BASE + 0xf0, val); + + /* wait for the power up finished */ + while ((mmio_read_32(IMX_GPC_BASE + 0xf0) & (1 << core_id)) != 0) + ; + + /* deassert the pcg pcr bit of the core */ + val = mmio_read_32(IMX_GPC_BASE + 0x800 + 0x40 * core_id); + val &= ~(1 << 0); + mmio_write_32(IMX_GPC_BASE + 0x800 + 0x40 * core_id, val); + + /* deassert the ncpuporeset */ + val = mmio_read_32(IMX_SRC_BASE + 0x8); + val |= (1 << core_id); + mmio_write_32(IMX_SRC_BASE + 0x8, val); } -void imx_gpc_set_slot_ack(uint32_t index, enum imx_gpc_slot m_core, - bool mode, bool ack) +/* if out of lpm, we need to do reverse steps */ +void imx_set_cpu_lpm(int core_id, bool pdn) { - uint32_t val, shift; + uint32_t val; - if (index > 10) { - tf_printf("Invalid slot index\n"); - return; - } - /* set slot */ - val = mmio_read_32(IMX_GPC_BASE + GPC_SLOT0_CFG + index * 4); - val |= (mode + 1) << m_core * 2; - mmio_write_32(IMX_GPC_BASE + GPC_SLOT0_CFG + index * 4, val); - /* set ack */ - if (ack) { - shift = m_core >= A53_SCU ? 2 : 0; - val = mmio_read_32(IMX_GPC_BASE + GPC_PGC_ACK_SEL_A53); - /* clear dummy ack */ - val &= ~(1 << (15 + (mode ? 16: 0))); - val |= 1 << (shift + (mode ? 16 : 0)); - mmio_write_32(IMX_GPC_BASE + GPC_PGC_ACK_SEL_A53, val); + if (pdn) { + val = mmio_read_32(IMX_GPC_BASE + 0x4); + /* enable the core WFI power down */ + val |= (1 << (core_id < 2 ? core_id * 2 : (core_id - 2) * 2 + 16)); + val |= 1 << (core_id + 20); + /* enable the core IRQ wakeup */ + val |= (core_id < 2 ? (1 << (core_id * 2 + 8)) : (1 << (core_id * 2 + 20))); + mmio_write_32(IMX_GPC_BASE + 0x4, val); + + /* assert the pcg pcr bit of the core */ + val = mmio_read_32(IMX_GPC_BASE + 0x800 + 0x40 * core_id); + val |= (1 << 0); + mmio_write_32(IMX_GPC_BASE + 0x800 + 0x40 * core_id, val); + } else { + val = mmio_read_32(IMX_GPC_BASE + 0x4); + /* disable the core WFI power down */ + val &= ~(1 << (core_id < 2 ? core_id * 2 : (core_id - 2) * 2 + 16)); + /* disable the core IRQ wakeup */ + val &= ~(core_id < 2 ? (1 << (core_id * 2 + 8)) : (1 << (core_id * 2 + 20))); + mmio_write_32(IMX_GPC_BASE + 0x4, val); + /* deassert the pcg pcr bit of the core */ + val = mmio_read_32(IMX_GPC_BASE + 0x800 + 0x40 * core_id); + val &= ~(1 << 0); + mmio_write_32(IMX_GPC_BASE + 0x800 + 0x40 * core_id, val); } } -/* cpu: cpu index */ -void imx_gpc_set_core_pdn_pup_by_software(unsigned int cpu, bool pdn) +/* SLOT 0 is used for A53 PLAT poewr down */ +/* SLOT 1 is used for A53 PLAT power up */ +/* SLOT 2 is used for A53 last core power up */ +/* when enter LPM power down, SCU's ACK is used */ +/* when out of LPM, last_core's ACK is used */ +void imx_pup_pdn_slot_config(int last_core, bool pdn) { - uint32_t val, index; + uint32_t slot_ack; + uint32_t slot0_cfg, slot1_cfg, slot2_cfg; - val = mmio_read_32(IMX_GPC_BASE + (pdn ? - GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ)); + slot0_cfg = mmio_read_32(IMX_GPC_BASE + GPC_SLOT0_CFG); + slot1_cfg = mmio_read_32(IMX_GPC_BASE + GPC_SLOT0_CFG + 0x4); + slot2_cfg = mmio_read_32(IMX_GPC_BASE + GPC_SLOT0_CFG + 0x8); + slot_ack = mmio_read_32(IMX_GPC_BASE + 0x24); - /*Set the core PCR bit before sw PUP/PDN trigger */ - imx_gpc_set_m_core_pgc(GPC_ARM_PGC + cpu * 0x40, true); + if (pdn) { + /* PUP and PDN SLOT config */ + slot0_cfg |= (1 << 8); + slot1_cfg |= (1 << 9); + slot2_cfg |= (0x2 << last_core * 2); - index = cpu; - val |= (BM_CPU_PGC_SW_PDN_PUP_REQ << index); - mmio_write_32(IMX_GPC_BASE + (pdn ? - GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ), val); + /*PDN ACK config */ + slot_ack &= ~(1 << 15); + slot_ack |= (1 << 2); - while((mmio_read_32(IMX_GPC_BASE + (pdn ? - GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ)) & - BM_CPU_PGC_SW_PDN_PUP_REQ) != 0) - ; + /*PUP ACK setting */ + slot_ack &= ~(1 << 31); + slot_ack |= (last_core < 2 ? (1 << (last_core + 16)) : + (1 << (last_core + 27))); + + } else { + slot0_cfg &= ~(1 << 8); + slot1_cfg &= ~(1 << 9); + slot2_cfg &= ~(0x2 << last_core * 2); + + slot_ack |= (1 << 15); + slot_ack &= ~(1 << 2); + + slot_ack |= (1 << 31); + slot_ack &= ~(last_core < 2 ? (1 << (last_core + 16)) : + (1 << (last_core + 27))); + } - /*Clear the core PCR bit after sw PUP/PDN trigger */ - imx_gpc_set_m_core_pgc(GPC_ARM_PGC + cpu * 0x40, false); + mmio_write_32(IMX_GPC_BASE + GPC_SLOT0_CFG, slot0_cfg); + mmio_write_32(IMX_GPC_BASE + GPC_SLOT0_CFG + 0x4, slot1_cfg); + mmio_write_32(IMX_GPC_BASE + GPC_SLOT0_CFG + 0x8, slot2_cfg); + mmio_write_32(IMX_GPC_BASE + 0x24, slot_ack); } -void imx_gpc_pre_suspend(bool arm_power_off) +/* used for cpuidle support on imx8mq */ +void imx_set_cluster_standby(bool enter) { - unsigned int i; + uint32_t val; + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD); + /* + * Enable BIT 6 of A53 AD register to make sure + * system don't enter LPM mode. + */ + if (enter) + val |= (1 << 6); + else + val &= ~(1 << 6); - /* set the LPM mode */ - if (arm_power_off) { - /* enable core 0/1/2/3 power down/up with low power mode */ - /* enable plat power down/up with low power mode */ - - /* - * to avoid confuse, we use slot 0~4 for power down. - * slot 5~9 for power up. - * power down slot sequence: - * slot 0 -> CORE0, - * SLOT 1 -> Mega/Fast mix, - * SLOT 2 -> SCU - * - * SLOT 5 -> Mega/Fast mix, - * SLOT 6 -> SCU - * SLOT 7 -> CORE0 + mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val); +} + +/* only support the GPC STOP mode power off */ +/* set the BSC and BSC2 LPM bit, and other bit in AD */ +void imx_set_cluster_powerdown(int last_core, bool pdn) +{ + uint32_t val; + + if (pdn) { + /* + * config the LPM STOP mode, enable CPU clock + * disable in LPM mode. */ - /* SCU slot ack as the power down ack */ - /* CORE0 slot ack as the power up ack */ - imx_gpc_set_lpm_mode(STOP_POWER_OFF); - imx_gpc_set_slot_ack(0, A53_CORE0, false, false); - imx_gpc_set_slot_ack(2, A53_SCU, false, true); - - imx_gpc_set_slot_ack(6, A53_SCU, true, false); - imx_gpc_set_slot_ack(7, A53_CORE0, true, true); - imx_gpc_set_m_core_pgc(GPC_ARM_PGC, true); - imx_gpc_set_m_core_pgc(GPC_SCU_PGC, true); - - imx_gpc_set_cpu_power_gate_by_lpm(0, true); - imx_gpc_set_plat_power_gate_by_lpm(true); + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); + val |= 0xa; /* enable the C0~1 LPM */ + val &= ~(1 << 14); /* disable cpu clock in LPM */ + mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); + + /* enable C2-3's LPM */ + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC2); + val |= 0xa; + mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC2, val); + + /* enable PLAT/SCU power down */ + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD); + val &= ~(1 << 5); + val |= ((1 << 31) | (1 << 4)); + /* enable C0's LPM power down */ + /*If cluster enter LPM, the last core's IRQ wakeup must be clear */ + val &= ~(last_core < 2 ? (1 << (last_core * 2 + 8)) : (1 << (last_core * 2 + 20))); + /* enable the C0's LPM PUP */ + val |= (last_core < 2 ? (1 << (last_core * 2 + 9)) : (1 << (last_core * 2 + 21))); + mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val); + + imx_pup_pdn_slot_config(last_core, true); + + /* enable PLAT PGC */ + val = mmio_read_32(IMX_GPC_BASE + 0x900); + val |= 0x1; + mmio_write_32(IMX_GPC_BASE + 0x900, val); } else { - imx_gpc_set_lpm_mode(STOP_POWER_ON); + /* clear PLAT PGC */ + val = mmio_read_32(IMX_GPC_BASE + 0x900); + val &= ~0x1; + mmio_write_32(IMX_GPC_BASE + 0x900, val); + + /* clear the slot and ack for cluster power down */ + imx_pup_pdn_slot_config(last_core, false); + + /* reverse the cluster level setting */ + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); + val &= ~0xa; /* clear the C0~1 LPM */ + val |= (1 << 14); /* disable cpu clock in LPM */ + mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); + + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC2); + val &= ~0xa; + mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC2, val); + + /* clear PLAT/SCU power down */ + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD); + val |= (1 << 5); + val &= ~((1 << 31) | (1 << 4)); + /* disable C0's LPM PUP */ + val &= ~(last_core < 2 ? (1 << (last_core * 2 + 9)) : (1 << (last_core * 2 + 21))); + mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val); } +} + +/* only handle the SLPCR and DDR retention */ +/* config the PLLs override setting */ +void imx_set_sys_lpm(bool retention) +{ + uint32_t val; + + /* set system DSM mode SLPCR(0x14) */ + val = mmio_read_32(IMX_GPC_BASE + SLPCR); + val &= ~(SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS | + SLPCR_BYPASS_PMIC_READY | SLPCR_RBC_EN); - for (i = 0; i < 4; i++) { - gpc_saved_imrs[i] = mmio_read_32(IMX_GPC_BASE + GPC_IMR1_CORE0_A53 + i * 4); - mmio_write_32(IMX_GPC_BASE + GPC_IMR1_CORE0_A53 + i * 4, ~gpc_wake_irqs[i]); + if (retention) { + val |= (SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS | + SLPCR_BYPASS_PMIC_READY | SLPCR_RBC_EN); + + /* DDR enter retention */ + ddrc_enter_retention(); + } else { + /* DDR exit retention */ + ddrc_exit_retention(); } + mmio_write_32(IMX_GPC_BASE + 0x14, val); +} + +void imx_set_rbc_count(void) +{ + uint32_t val; + + val = mmio_read_32(IMX_GPC_BASE + SLPCR); + val |= (0x3f << 24); + mmio_write_32(IMX_GPC_BASE + SLPCR, val); +} + +void imx_clear_rbc_count(void) +{ + uint32_t val; + + val = mmio_read_32(IMX_GPC_BASE + SLPCR); + val &= ~(0x3f << 24); + mmio_write_32(IMX_GPC_BASE + SLPCR, val); + +} +void imx_anamix_pre_suspend() +{ /* override PLL/OSC to let ccm control them */ mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_HW_AUDIO_PLL1_CFG0, mmio_read_32(IMX_ANAMIX_BASE + ANAMIX_HW_AUDIO_PLL1_CFG0) | 0x140000); @@ -347,31 +411,8 @@ void imx_gpc_pre_suspend(bool arm_power_off) mmio_read_32(IMX_ANAMIX_BASE + ANAMIX_HW_ANAMIX_MISC_CFG) | 0xa); } -void imx_gpc_post_resume(void) +void imx_anamix_post_resume(void) { - int i; - /* set LPM mode WAIT CLOCKED */ - imx_gpc_set_lpm_mode(WAIT_CLOCKED); - /* clear lpm power gate of core and plat */ - imx_gpc_set_cpu_power_gate_by_lpm(0, false); - imx_gpc_set_plat_power_gate_by_lpm(false); - /* clear PGC PDN bit */ - imx_gpc_set_m_core_pgc(GPC_ARM_PGC, false); - imx_gpc_set_m_core_pgc(GPC_SCU_PGC, false); - - for (i = 0; i < 4; i++) { - mmio_write_32(IMX_GPC_BASE + GPC_IMR1_CORE0_A53 + i * 4, gpc_saved_imrs[i]); - } - - /* skip slot m4 use , clear slots */ - for(i = 0; i < 10; i ++) { - if (i == 1 || i == 5) - continue; - mmio_write_32(IMX_GPC_BASE +GPC_SLOT0_CFG + i * 0x4, 0x0); - } - /* set DUMMY PDN/PUP ACK by default for A53 domain */ - mmio_write_32(IMX_GPC_BASE + GPC_PGC_ACK_SEL_A53, 1 << 31 | 1 << 15); - /* clear override of PLL/OSC */ mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_HW_AUDIO_PLL1_CFG0, mmio_read_32(IMX_ANAMIX_BASE + ANAMIX_HW_AUDIO_PLL1_CFG0) & ~0x140000); @@ -399,6 +440,30 @@ void imx_gpc_post_resume(void) mmio_read_32(IMX_ANAMIX_BASE + ANAMIX_HW_ANAMIX_MISC_CFG) & ~0xa); } +/* + * On i.MX8MQ, only in system suspend mode, the A53 cluster can + * enter LPM mode and shutdown the A53 PLAT power domain. So LPM + * wakeup only used for system suspend. when system enter suspend, + * any A53 CORE can be the last core to suspend the system, But + * the LPM wakeup can only use the C0's IMR to wakeup A53 cluster + * from LPM, so save C0's IMRs before suspend, restore back after + * resume. + */ +void imx_set_lpm_wakeup(bool pdn) +{ + unsigned int i; + + if (pdn) { + for (i = 0; i < 4; i++) { + gpc_saved_imrs[i] = mmio_read_32(IMX_GPC_BASE + GPC_IMR1_CORE0_A53 + i * 4); + mmio_write_32(IMX_GPC_BASE + GPC_IMR1_CORE0_A53 + i * 4, ~gpc_wake_irqs[i]); + } + } else { + for (i = 0; i < 4; i++) + mmio_write_32(IMX_GPC_BASE + GPC_IMR1_CORE0_A53 + i * 4, gpc_saved_imrs[i]); + } +} + static void imx_gpc_hwirq_mask(unsigned int hwirq) { uintptr_t reg; @@ -431,6 +496,33 @@ static void imx_gpc_set_wake(uint32_t hwirq, unsigned int on) gpc_wake_irqs[idx] & ~mask; } +static uint32_t mask_offset[] = {0x30, 0x40, 0x1c0, 0x1d0,}; +static void imx_gpc_set_affinity(uint32_t hwirq, unsigned cpu_idx) +{ + uint32_t offset = mask_offset[cpu_idx]; + + uintptr_t reg; + unsigned int val; + + /* + * using the mask/unmask bit as affinity function.unmask the + * IMR bit to enable IRQ wakeup for this core. + */ + reg = IMX_GPC_BASE + offset + (hwirq / 32) * 4; + val = mmio_read_32(reg); + val &= ~(1 << hwirq % 32); + mmio_write_32(reg, val); + + /* clear affinity of other core */ + for (int i = 0; i < 4; i++) { + if (cpu_idx != i) { + val = mmio_read_32(IMX_GPC_BASE + mask_offset[i] + (hwirq / 32) * 4); + val |= (1 << hwirq % 32); + mmio_write_32(IMX_GPC_BASE + mask_offset[i] + (hwirq / 32) * 4, val); + } + } +} + static void imx_gpc_pm_domain_enable(uint32_t domain_id, uint32_t on) { uint32_t val; @@ -499,18 +591,21 @@ void imx_gpc_init(void) * avoid entering DSM mode by mistake. */ mmio_write_32(IMX_GPC_BASE + GPC_IMR1_CORE0_A53, ~0x1); + mmio_write_32(IMX_GPC_BASE + 0x40, ~0x1); + mmio_write_32(IMX_GPC_BASE + 0x1c0, ~0x1); + mmio_write_32(IMX_GPC_BASE + 0x1d0, ~0x1); /* use external IRQs to wakeup C0~C3 from LPM */ - val = mmio_read_32(IMX_GPC_BASE + GPC_LPCR_A53_BSC); - val |= 0x70c00000; + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); + val |= 0x40000000; /* clear the MASTER0 LPM handshake */ val &= ~(1 << 6); - mmio_write_32(IMX_GPC_BASE + GPC_LPCR_A53_BSC, val); + mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); /* mask M4 DSM trigger if M4 is NOT enabled */ - val = mmio_read_32(IMX_GPC_BASE + GPC_LPCR_M4); + val = mmio_read_32(IMX_GPC_BASE + LPCR_M4); val |= 1 << 31; - mmio_write_32(IMX_GPC_BASE + GPC_LPCR_M4, val); + mmio_write_32(IMX_GPC_BASE + LPCR_M4, val); /* set all mix/PU in A53 domain */ mmio_write_32(IMX_GPC_BASE + GPC_PGC_CPU_0_1_MAPPING, 0xfffd); @@ -519,19 +614,13 @@ void imx_gpc_init(void) mmio_write_32(IMX_GPC_BASE + GPC_PGC_SCU_TIMMING, (0x59 << 10) | 0x5B | (0x2 << 20)); - /* set A53 core power up timming */ - mmio_write_32(IMX_GPC_BASE + GPC_PGC_CORE0_TIMMING, 0x1a << 7); - mmio_write_32(IMX_GPC_BASE + GPC_PGC_CORE1_TIMMING, 0x1a << 7); - mmio_write_32(IMX_GPC_BASE + GPC_PGC_CORE2_TIMMING, 0x1a << 7); - mmio_write_32(IMX_GPC_BASE + GPC_PGC_CORE3_TIMMING, 0x1a << 7); - /* set DUMMY PDN/PUP ACK by default for A53 domain */ mmio_write_32(IMX_GPC_BASE + GPC_PGC_ACK_SEL_A53, 1 << 31 | 1 << 15); /* clear DSM by default */ - val = mmio_read_32(IMX_GPC_BASE + GPC_SLPCR); + val = mmio_read_32(IMX_GPC_BASE + SLPCR); val &= ~(1 << 31); /* TODO if M4 is not enabled, clear more SLPCR bits */ - mmio_write_32(IMX_GPC_BASE + GPC_SLPCR, val); + mmio_write_32(IMX_GPC_BASE + SLPCR, val); /* * USB PHY power up needs to make sure RESET bit in SRC is clear, @@ -564,6 +653,9 @@ int imx_gpc_handler(uint32_t smc_fid, case FSL_SIP_CONFIG_GPC_PM_DOMAIN: imx_gpc_pm_domain_enable(x2, x3); break; + case FSL_SIP_CONFIG_GPC_SET_AFF: + imx_gpc_set_affinity(x2, x3); + break; default: return SMC_UNK; } diff --git a/plat/imx/imx8mq/imx8m_psci.c b/plat/imx/imx8mq/imx8m_psci.c index 6045e722..b43af4cc 100644 --- a/plat/imx/imx8mq/imx8m_psci.c +++ b/plat/imx/imx8mq/imx8m_psci.c @@ -38,17 +38,11 @@ #include <mmio.h> #include <soc.h> -#define SCR_A53RCR1_OFFSET 0x08 -#define SRC_GPR1_OFFSET 0x74 -#define ARM_PGC 0x800 -#define PGC_PCR 1 -#define GPC_CPU_PGC_SW_PUP_REQ 0xf0 -#define GPC_CPU_PGC_SW_PDN_REQ 0xfc - #define SNVS_LPCR 0x38 -extern void imx_gpc_set_core_pdn_pup_by_software(unsigned int cpu, bool pdn); -extern void imx_gpc_set_cpu_power_gate_by_wfi(unsigned int cpu, bool pdn); +#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0]) +#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1]) +#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) const unsigned char imx_power_domain_tree_desc[] = { /* number of root nodes */ @@ -58,54 +52,19 @@ const unsigned char imx_power_domain_tree_desc[] = { PLATFORM_CLUSTER0_CORE_COUNT, }; -void imx8m_kill_cpu(unsigned int target_idx) -{ - unsigned int val1; - - /* Disable the secondary core */ - val1 = mmio_read_32(IMX_SRC_BASE + SCR_A53RCR1_OFFSET); - val1 &= ~(1 << target_idx); - mmio_write_32(IMX_SRC_BASE + SCR_A53RCR1_OFFSET, val1); - - imx_gpc_set_core_pdn_pup_by_software(target_idx, true); -} - int imx_pwr_domain_on(u_register_t mpidr) { - int ret = PSCI_E_SUCCESS; - unsigned int cpu_id, reg; - + unsigned int core_id; uint64_t base_addr = BL31_BASE; - tf_printf("cpu on\n"); - cpu_id = MPIDR_AFFLVL0_VAL(mpidr); - - /* core power up sequence - * 1. Assert nCPUPORESET - * 2. power the core. - * 3. Deassert reset. - */ - reg = mmio_read_32(IMX_SRC_BASE + SCR_A53RCR1_OFFSET); - reg &= ~(1 << cpu_id); - mmio_write_32(IMX_SRC_BASE + SCR_A53RCR1_OFFSET, reg); - - /* Set CPU jump address */ - if (cpu_id > 0) { - base_addr >>= 2; - mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (cpu_id << 3), - ((uint32_t)(base_addr >> 22) & 0xFFFF)); - mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (cpu_id << 3) + 4, - ((uint32_t)base_addr & 0x003FFFFF)); - } - - imx_gpc_set_core_pdn_pup_by_software(cpu_id, false); + core_id = MPIDR_AFFLVL0_VAL(mpidr); - /* Kick CPU here */ - reg = mmio_read_32(IMX_SRC_BASE + SCR_A53RCR1_OFFSET); - reg |= (1 << cpu_id); - mmio_write_32(IMX_SRC_BASE + SCR_A53RCR1_OFFSET, reg); + /* set the secure entrypoint */ + imx_set_cpu_secure_entry(core_id, base_addr); + /* power up the core */ + imx_set_cpu_pwr_on(core_id); - return ret; + return PSCI_E_SUCCESS; } void imx_pwr_domain_on_finish(const psci_power_state_t *target_state) @@ -118,12 +77,21 @@ void imx_pwr_domain_on_finish(const psci_power_state_t *target_state) void imx_pwr_domain_off(const psci_power_state_t *target_state) { + uint64_t mpidr = read_mpidr_el1(); + unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr); + + /* disable the GIC cpu interface first */ plat_gic_cpuif_disable(); + /* config the core for power down */ + imx_set_cpu_pwr_off(core_id); } int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint) { - /* TODO */ + /* The non-secure entrypoint should be in RAM space */ + if (ns_entrypoint < 0x40000000) + return PSCI_E_INVALID_PARAMS; + return PSCI_E_SUCCESS; } @@ -131,21 +99,23 @@ int imx_validate_power_state(unsigned int power_state, psci_power_state_t *req_state) { int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int pwr_type = psci_get_pstate_type(power_state); + int state_id = psci_get_pstate_id(power_state); if (pwr_lvl > PLAT_MAX_PWR_LVL) return PSCI_E_INVALID_PARAMS; - /* Sanity check the requested afflvl */ - if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) { - if (pwr_lvl != MPIDR_AFFLVL0) - return PSCI_E_INVALID_PARAMS; - /* power domain in standby state */ - req_state->pwr_domain_state[pwr_lvl] = PLAT_MAX_RET_STATE; + if (pwr_type == PSTATE_TYPE_STANDBY) { + CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; + CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; + } - return PSCI_E_SUCCESS; + if (pwr_type == PSTATE_TYPE_POWERDOWN && state_id == 0x33) { + CORE_PWR_STATE(req_state) = PLAT_MAX_OFF_STATE; + CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; } - return 0; + return PSCI_E_SUCCESS; } void imx_cpu_standby(plat_local_state_t cpu_state) @@ -163,38 +133,74 @@ void imx_cpu_standby(plat_local_state_t cpu_state) void imx_domain_suspend(const psci_power_state_t *target_state) { uint64_t base_addr = BL31_BASE; - plat_gic_cpuif_disable(); - - ddrc_enter_retention(); - /* imx gpc pre suspend */ - imx_gpc_pre_suspend(true); + uint64_t mpidr = read_mpidr_el1(); + unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr); + + if (is_local_state_off(CORE_PWR_STATE(target_state))) { + /* disable the cpu interface */ + plat_gic_cpuif_disable(); + imx_set_cpu_secure_entry(core_id, base_addr); + imx_set_cpu_lpm(core_id, true); + } else { + /* TODO cluster level clock gate off ? */ + dsb(); + write_scr_el3(read_scr_el3() | 0x4); + isb(); + } - base_addr >>= 2; - mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET , - ((uint32_t)(base_addr >> 22) & 0xFFFF)); - mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + 4, - ((uint32_t)base_addr & 0x003FFFFF)); + if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) + imx_set_cluster_powerdown(core_id, true); + else + imx_set_cluster_standby(true); + if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) { + /* put DDR into retention mode */ + imx_set_sys_lpm(true); + imx_anamix_pre_suspend(); + } } void imx_domain_suspend_finish(const psci_power_state_t *target_state) { - ddrc_exit_retention(); - /* imx gpc post resume */ - imx_gpc_post_resume(); - /* enable the GICv3 cpu interface */ - plat_gic_cpuif_enable(); + uint64_t mpidr = read_mpidr_el1(); + unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr); + + /* check the system level status */ + if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) { + imx_set_sys_lpm(false); + imx_anamix_post_resume(); + imx_clear_rbc_count(); + } + + /* check the cluster level power status */ + if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) + imx_set_cluster_powerdown(core_id, false); + else + imx_set_cluster_standby(false); + + /* check the core level power status */ + if (is_local_state_off(CORE_PWR_STATE(target_state))) { + /* clear the core lpm setting */ + imx_set_cpu_lpm(core_id, false); + /* enable the gic cpu interface */ + plat_gic_cpuif_enable(); + } else { + write_scr_el3(read_scr_el3() & (~0x4)); + isb(); + } } void imx_get_sys_suspend_power_state(psci_power_state_t *req_state) { unsigned int i; - for (i = IMX_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) - req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE; + for (i = IMX_PWR_LVL0; i < PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_STOP_OFF_STATE; + + req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PLAT_MAX_RET_STATE; } -void __attribute__((noreturn)) imx_system_reset(void) +void __dead2 imx_system_reset(void) { uintptr_t wdog_base = IMX_WDOG_BASE; unsigned int val; @@ -214,7 +220,7 @@ void __attribute__((noreturn)) imx_system_reset(void) ; } -void __attribute__((noreturn)) imx_system_off(void) +void __dead2 imx_system_off(void) { mmio_write_32(IMX_SNVS_BASE + SNVS_LPCR, 0x61); @@ -224,6 +230,15 @@ void __attribute__((noreturn)) imx_system_off(void) ; } +void __dead2 imx_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) +{ + if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) + imx_set_rbc_count(); + + while (1) + wfi(); +} + static const plat_psci_ops_t imx_plat_psci_ops = { .pwr_domain_on = imx_pwr_domain_on, .pwr_domain_on_finish = imx_pwr_domain_on_finish, @@ -233,6 +248,7 @@ static const plat_psci_ops_t imx_plat_psci_ops = { .cpu_standby = imx_cpu_standby, .pwr_domain_suspend = imx_domain_suspend, .pwr_domain_suspend_finish = imx_domain_suspend_finish, + .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi, .get_sys_suspend_power_state = imx_get_sys_suspend_power_state, .system_reset = imx_system_reset, .system_off = imx_system_off, diff --git a/plat/imx/imx8mq/include/platform_def.h b/plat/imx/imx8mq/include/platform_def.h index faff2021..1021fd25 100644 --- a/plat/imx/imx8mq/include/platform_def.h +++ b/plat/imx/imx8mq/include/platform_def.h @@ -16,9 +16,12 @@ #define PWR_DOMAIN_AT_MAX_LVL 1 #define PLAT_MAX_PWR_LVL 2 -#define PLAT_MAX_OFF_STATE 2 +#define PLAT_MAX_OFF_STATE 4 #define PLAT_MAX_RET_STATE 1 +#define PLAT_WAIT_OFF_STATE 2 +#define PLAT_STOP_OFF_STATE 3 + #define BL31_BASE 0x910000 #define BL31_LIMIT 0x920000 #define BL32_BASE 0xfe000000 diff --git a/plat/imx/imx8mq/include/soc.h b/plat/imx/imx8mq/include/soc.h index 65a49d00..af6fc09e 100644 --- a/plat/imx/imx8mq/include/soc.h +++ b/plat/imx/imx8mq/include/soc.h @@ -7,55 +7,22 @@ #ifndef __IMX_SOC_H #define __IMX_SOC_H -enum imx_cpu_pwr_mode { - WAIT_CLOCKED, /* wfi only */ - WAIT_UNCLOCKED, /* WAIT */ - WAIT_UNCLOCKED_POWER_OFF, /* WAIT + SRPG */ - STOP_POWER_ON, /* just STOP */ - STOP_POWER_OFF, /* STOP + SRPG */ -}; - -enum imx_gpc_slot { - A53_CORE0, - A53_CORE1, - A53_CORE2, - A53_CORE3, - A53_SCU, -}; - -enum imx_gpc_pu_slot { - FAST_MEGA_MIX, - MIPI_PHY, - PCIE1_PHY, - OTG1_PHY, - OTG2_PHY, - RESERVED, - CORE1_M4, - DDR1_PHY, - DDR2_PHY, - GPU, - VPU, - HDMI_PHY, - DSIP, - MIPI_CSI1, - MIPI_CSI2, - PCIE2_PHY, -}; - void imx_gpc_set_m_core_pgc(unsigned int cpu, bool pdn); -void imx_gpc_set_lpm_mode(enum imx_cpu_pwr_mode mode); -void imx_gpc_set_cpu_power_gate_by_lpm(unsigned int cpu, bool pdn); -void imx_gpc_set_plat_power_gate_by_lpm(bool pdn); -void imx_gpc_set_core_pdn_pup_by_software(unsigned int cpu, bool pdn); -void imx_gpc_set_cpu_ppower_gate_by_wfi(unsigned int cpu, bool pdn); -void imx_gpc_pre_suspend(bool arm_power_off); -void imx_gpc_post_resume(void); +void imx_anamix_pre_suspend(void); +void imx_anamix_post_resume(void); void imx_gpc_init(void); +void imx_set_cpu_secure_entry(int cpu_id, uintptr_t sec_entrypoint); +void imx_set_cpu_pwr_off(int cpu_id); +void imx_set_cpu_pwr_on(int cpu_id); +void imx_set_cpu_lpm(int cpu_id, bool pdn); +void imx_set_cluster_standby(bool pdn); +void imx_set_cluster_powerdown(int last_core, bool pdn); +void imx_set_sys_lpm(bool retention); +void imx_set_rbc_count(void); +void imx_clear_rbc_count(void); + void ddrc_enter_retention(void); void ddrc_exit_retention(void); -void imx_enable_cpu(unsigned int cpu, bool enable); -int imx_is_m4_enabled(void); -void imx_set_cpu_jump_addr(unsigned int cpu, void *jump_addr); #endif /* __IMX_SOC_H */ |