1*81136819SBai Ping /* 2*81136819SBai Ping * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 3*81136819SBai Ping * 4*81136819SBai Ping * SPDX-License-Identifier: BSD-3-Clause 5*81136819SBai Ping */ 6*81136819SBai Ping 7*81136819SBai Ping #include <debug.h> 8*81136819SBai Ping #include <gpc.h> 9*81136819SBai Ping #include <mmio.h> 10*81136819SBai Ping #include <platform_def.h> 11*81136819SBai Ping #include <psci.h> 12*81136819SBai Ping #include <stdlib.h> 13*81136819SBai Ping #include <stdint.h> 14*81136819SBai Ping #include <stdbool.h> 15*81136819SBai Ping #include <std_svc.h> 16*81136819SBai Ping 17*81136819SBai Ping void imx_set_cpu_secure_entry(unsigned int core_id, uintptr_t sec_entrypoint) 18*81136819SBai Ping { 19*81136819SBai Ping uint64_t temp_base; 20*81136819SBai Ping 21*81136819SBai Ping temp_base = (uint64_t) sec_entrypoint; 22*81136819SBai Ping temp_base >>= 2; 23*81136819SBai Ping 24*81136819SBai Ping mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3), 25*81136819SBai Ping ((uint32_t)(temp_base >> 22) & 0xffff)); 26*81136819SBai Ping mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3) + 4, 27*81136819SBai Ping ((uint32_t)temp_base & 0x003fffff)); 28*81136819SBai Ping } 29*81136819SBai Ping 30*81136819SBai Ping /* use wfi power down the core */ 31*81136819SBai Ping void imx_set_cpu_pwr_off(unsigned int core_id) 32*81136819SBai Ping { 33*81136819SBai Ping /* enable the wfi power down of the core */ 34*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) | 35*81136819SBai Ping (1 << (core_id + 20))); 36*81136819SBai Ping /* assert the pcg pcr bit of the core */ 37*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); 38*81136819SBai Ping }; 39*81136819SBai Ping 40*81136819SBai Ping /* use the sw method to power up the core */ 41*81136819SBai Ping void imx_set_cpu_pwr_on(unsigned int core_id) 42*81136819SBai Ping { 43*81136819SBai Ping /* clear the wfi power down bit of the core */ 44*81136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id)); 45*81136819SBai Ping /* assert the ncpuporeset */ 46*81136819SBai Ping mmio_clrbits_32(IMX_SRC_BASE + SRC_A53RCR1, (1 << core_id)); 47*81136819SBai Ping /* assert the pcg pcr bit of the core */ 48*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); 49*81136819SBai Ping /* sw power up the core */ 50*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + CPU_PGC_UP_TRG, (1 << core_id)); 51*81136819SBai Ping 52*81136819SBai Ping /* wait for the power up finished */ 53*81136819SBai Ping while ((mmio_read_32(IMX_GPC_BASE + CPU_PGC_UP_TRG) & (1 << core_id)) != 0) 54*81136819SBai Ping ; 55*81136819SBai Ping 56*81136819SBai Ping /* deassert the pcg pcr bit of the core */ 57*81136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); 58*81136819SBai Ping /* deassert the ncpuporeset */ 59*81136819SBai Ping mmio_setbits_32(IMX_SRC_BASE + SRC_A53RCR1, (1 << core_id)); 60*81136819SBai Ping } 61*81136819SBai Ping 62*81136819SBai Ping /* if out of lpm, we need to do reverse steps */ 63*81136819SBai Ping void imx_set_cpu_lpm(unsigned int core_id, bool pdn) 64*81136819SBai Ping { 65*81136819SBai Ping if (pdn) { 66*81136819SBai Ping /* enable the core WFI PDN & IRQ PUP */ 67*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) | 68*81136819SBai Ping (1 << (core_id + 20)) | COREx_IRQ_WUP(core_id)); 69*81136819SBai Ping /* assert the pcg pcr bit of the core */ 70*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); 71*81136819SBai Ping } else { 72*81136819SBai Ping /* disable CORE WFI PDN & IRQ PUP */ 73*81136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) | 74*81136819SBai Ping COREx_IRQ_WUP(core_id)); 75*81136819SBai Ping /* deassert the pcg pcr bit of the core */ 76*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); 77*81136819SBai Ping } 78*81136819SBai Ping } 79*81136819SBai Ping 80*81136819SBai Ping void imx_set_sys_wakeup(unsigned int last_core, bool pdn) 81*81136819SBai Ping { 82*81136819SBai Ping /* TODO */ 83*81136819SBai Ping } 84*81136819SBai Ping 85*81136819SBai Ping void imx_pup_pdn_slot_config(int last_core, bool pdn) 86*81136819SBai Ping { 87*81136819SBai Ping if (pdn) { 88*81136819SBai Ping /* SLOT0 for A53 PLAT power down */ 89*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(0), SLT_PLAT_PDN); 90*81136819SBai Ping /* SLOT1 for A53 PLAT power up */ 91*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(1), SLT_PLAT_PUP); 92*81136819SBai Ping /* SLOT2 for A53 primary core power up */ 93*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(2), SLT_COREx_PUP(last_core)); 94*81136819SBai Ping /* ACK setting: PLAT ACK for PDN, CORE ACK for PUP */ 95*81136819SBai Ping mmio_clrsetbits_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, 0xFFFFFFFF, 96*81136819SBai Ping A53_PLAT_PDN_ACK | A53_PLAT_PUP_ACK); 97*81136819SBai Ping } else { 98*81136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(0), 0xFFFFFFFF); 99*81136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(1), 0xFFFFFFFF); 100*81136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(2), 0xFFFFFFFF); 101*81136819SBai Ping mmio_clrsetbits_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, 0xFFFFFFFF, 102*81136819SBai Ping A53_DUMMY_PDN_ACK | A53_DUMMY_PUP_ACK); 103*81136819SBai Ping } 104*81136819SBai Ping } 105*81136819SBai Ping 106*81136819SBai Ping void imx_set_cluster_standby(bool retention) 107*81136819SBai Ping { 108*81136819SBai Ping /* 109*81136819SBai Ping * Enable BIT 6 of A53 AD register to make sure system 110*81136819SBai Ping * don't enter LPM mode. 111*81136819SBai Ping */ 112*81136819SBai Ping if (retention) 113*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, (1 << 6)); 114*81136819SBai Ping else 115*81136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, (1 << 6)); 116*81136819SBai Ping } 117*81136819SBai Ping 118*81136819SBai Ping void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state) 119*81136819SBai Ping { 120*81136819SBai Ping uint32_t val; 121*81136819SBai Ping 122*81136819SBai Ping if (is_local_state_off(power_state)) { 123*81136819SBai Ping val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); 124*81136819SBai Ping val |= A53_LPM_STOP; /* enable C0-C1's STOP mode */ 125*81136819SBai Ping val &= ~CPU_CLOCK_ON_LPM; /* disable CPU clock in LPM mode */ 126*81136819SBai Ping mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); 127*81136819SBai Ping 128*81136819SBai Ping /* enable C2-3's STOP mode */ 129*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, A53_LPM_STOP); 130*81136819SBai Ping 131*81136819SBai Ping /* enable PLAT/SCU power down */ 132*81136819SBai Ping val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD); 133*81136819SBai Ping val &= ~EN_L2_WFI_PDN; 134*81136819SBai Ping val |= L2PGE | EN_PLAT_PDN; 135*81136819SBai Ping val &= ~COREx_IRQ_WUP(last_core); /* disable IRQ PUP for last core */ 136*81136819SBai Ping val |= COREx_LPM_PUP(last_core); /* enable LPM PUP for last core */ 137*81136819SBai Ping mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val); 138*81136819SBai Ping 139*81136819SBai Ping imx_pup_pdn_slot_config(last_core, true); 140*81136819SBai Ping 141*81136819SBai Ping /* enable PLAT PGC */ 142*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + A53_PLAT_PGC, 0x1); 143*81136819SBai Ping } else { 144*81136819SBai Ping /* clear PLAT PGC */ 145*81136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + A53_PLAT_PGC, 0x1); 146*81136819SBai Ping 147*81136819SBai Ping /* clear the slot and ack for cluster power down */ 148*81136819SBai Ping imx_pup_pdn_slot_config(last_core, false); 149*81136819SBai Ping 150*81136819SBai Ping val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); 151*81136819SBai Ping val &= ~A53_LPM_MASK; /* clear the C0~1 LPM */ 152*81136819SBai Ping val |= CPU_CLOCK_ON_LPM; /* disable cpu clock in LPM */ 153*81136819SBai Ping mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); 154*81136819SBai Ping 155*81136819SBai Ping /* set A53 LPM to RUN mode */ 156*81136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, A53_LPM_MASK); 157*81136819SBai Ping 158*81136819SBai Ping /* clear PLAT/SCU power down */ 159*81136819SBai Ping val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD); 160*81136819SBai Ping val |= EN_L2_WFI_PDN; 161*81136819SBai Ping val &= ~(L2PGE | EN_PLAT_PDN); 162*81136819SBai Ping val &= ~COREx_LPM_PUP(last_core); /* disable C0's LPM PUP */ 163*81136819SBai Ping mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val); 164*81136819SBai Ping } 165*81136819SBai Ping } 166*81136819SBai Ping 167*81136819SBai Ping /* config the system level power mode */ 168*81136819SBai Ping void imx_set_sys_lpm(bool retention) 169*81136819SBai Ping { 170*81136819SBai Ping uint32_t val; 171*81136819SBai Ping 172*81136819SBai Ping /* set system DSM mode SLPCR(0x14) */ 173*81136819SBai Ping val = mmio_read_32(IMX_GPC_BASE + SLPCR); 174*81136819SBai Ping val &= ~(SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS | 175*81136819SBai Ping SLPCR_BYPASS_PMIC_READY | SLPCR_RBC_EN); 176*81136819SBai Ping 177*81136819SBai Ping if (retention) 178*81136819SBai Ping val |= (SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS | 179*81136819SBai Ping SLPCR_BYPASS_PMIC_READY | SLPCR_RBC_EN | 180*81136819SBai Ping SLPCR_A53_FASTWUP_STOP_MODE); 181*81136819SBai Ping 182*81136819SBai Ping mmio_write_32(IMX_GPC_BASE + SLPCR, val); 183*81136819SBai Ping } 184*81136819SBai Ping 185*81136819SBai Ping void imx_set_rbc_count(void) 186*81136819SBai Ping { 187*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + SLPCR, 0x3f << SLPCR_RBC_COUNT_SHIFT); 188*81136819SBai Ping } 189*81136819SBai Ping 190*81136819SBai Ping void imx_clear_rbc_count(void) 191*81136819SBai Ping { 192*81136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + SLPCR, 0x3f << SLPCR_RBC_COUNT_SHIFT); 193*81136819SBai Ping } 194*81136819SBai Ping 195*81136819SBai Ping void imx_gpc_init(void) 196*81136819SBai Ping { 197*81136819SBai Ping uint32_t val; 198*81136819SBai Ping int i; 199*81136819SBai Ping /* mask all the interrupt by default */ 200*81136819SBai Ping /* Due to the hardware design requirement, need to make 201*81136819SBai Ping * sure GPR interrupt(#32) is unmasked during RUN mode to 202*81136819SBai Ping * avoid entering DSM mode by mistake. 203*81136819SBai Ping */ 204*81136819SBai Ping for (i = 0; i < 4; i++) { 205*81136819SBai Ping mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, 0xFFFFFFFE); 206*81136819SBai Ping mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, 0xFFFFFFFE); 207*81136819SBai Ping mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, 0xFFFFFFFE); 208*81136819SBai Ping mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, 0xFFFFFFFE); 209*81136819SBai Ping mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0); 210*81136819SBai Ping } 211*81136819SBai Ping 212*81136819SBai Ping /* use external IRQs to wakeup C0~C3 from LPM */ 213*81136819SBai Ping val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); 214*81136819SBai Ping val |= IRQ_SRC_A53_WUP; 215*81136819SBai Ping /* clear the MASTER0 LPM handshake */ 216*81136819SBai Ping val &= ~MASTER0_LPM_HSK; 217*81136819SBai Ping mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); 218*81136819SBai Ping 219*81136819SBai Ping /* mask M4 DSM trigger if M4 is NOT enabled */ 220*81136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + LPCR_M4, DSM_MODE_MASK); 221*81136819SBai Ping 222*81136819SBai Ping /* set all mix/PU in A53 domain */ 223*81136819SBai Ping mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xfffd); 224*81136819SBai Ping 225*81136819SBai Ping /* set SCU timming */ 226*81136819SBai Ping mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING, 227*81136819SBai Ping (0x59 << 10) | 0x5B | (0x2 << 20)); 228*81136819SBai Ping 229*81136819SBai Ping /* set DUMMY PDN/PUP ACK by default for A53 domain */ 230*81136819SBai Ping mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, A53_DUMMY_PUP_ACK | 231*81136819SBai Ping A53_DUMMY_PDN_ACK); 232*81136819SBai Ping 233*81136819SBai Ping /* disable DSM mode by default */ 234*81136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + SLPCR, DSM_MODE_MASK); 235*81136819SBai Ping 236*81136819SBai Ping /* 237*81136819SBai Ping * USB PHY power up needs to make sure RESET bit in SRC is clear, 238*81136819SBai Ping * otherwise, the PU power up bit in GPC will NOT self-cleared. 239*81136819SBai Ping * only need to do it once. 240*81136819SBai Ping */ 241*81136819SBai Ping mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1); 242*81136819SBai Ping mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1); 243*81136819SBai Ping } 244