181136819SBai Ping /* 2*88a26465SJacky Bai * Copyright (c) 2018-2023, ARM Limited and Contributors. All rights reserved. 381136819SBai Ping * 481136819SBai Ping * SPDX-License-Identifier: BSD-3-Clause 581136819SBai Ping */ 681136819SBai Ping 781136819SBai Ping #include <stdlib.h> 881136819SBai Ping #include <stdint.h> 981136819SBai Ping #include <stdbool.h> 1009d40e0eSAntonio Nino Diaz 11*88a26465SJacky Bai #include <arch_helpers.h> 1209d40e0eSAntonio Nino Diaz #include <common/debug.h> 1366345b8bSJacky Bai #include <drivers/delay_timer.h> 1409d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 1509d40e0eSAntonio Nino Diaz #include <lib/psci/psci.h> 16*88a26465SJacky Bai #include <lib/smccc.h> 17*88a26465SJacky Bai #include <lib/spinlock.h> 18*88a26465SJacky Bai #include <plat/common/platform.h> 1909d40e0eSAntonio Nino Diaz #include <services/std_svc.h> 2009d40e0eSAntonio Nino Diaz 2109d40e0eSAntonio Nino Diaz #include <gpc.h> 22*88a26465SJacky Bai #include <platform_def.h> 23*88a26465SJacky Bai 24*88a26465SJacky Bai #define FSL_SIP_CONFIG_GPC_MASK U(0x00) 25*88a26465SJacky Bai #define FSL_SIP_CONFIG_GPC_UNMASK U(0x01) 26*88a26465SJacky Bai #define FSL_SIP_CONFIG_GPC_SET_WAKE U(0x02) 27*88a26465SJacky Bai #define FSL_SIP_CONFIG_GPC_PM_DOMAIN U(0x03) 28*88a26465SJacky Bai #define FSL_SIP_CONFIG_GPC_SET_AFF U(0x04) 29*88a26465SJacky Bai #define FSL_SIP_CONFIG_GPC_CORE_WAKE U(0x05) 30*88a26465SJacky Bai 31*88a26465SJacky Bai #define MAX_HW_IRQ_NUM U(128) 32*88a26465SJacky Bai #define MAX_IMR_NUM U(4) 33*88a26465SJacky Bai 34*88a26465SJacky Bai static uint32_t gpc_saved_imrs[16]; 35*88a26465SJacky Bai static uint32_t gpc_wake_irqs[4]; 36*88a26465SJacky Bai static uint32_t gpc_imr_offset[] = { 37*88a26465SJacky Bai IMX_GPC_BASE + IMR1_CORE0_A53, 38*88a26465SJacky Bai IMX_GPC_BASE + IMR1_CORE1_A53, 39*88a26465SJacky Bai IMX_GPC_BASE + IMR1_CORE2_A53, 40*88a26465SJacky Bai IMX_GPC_BASE + IMR1_CORE3_A53, 41*88a26465SJacky Bai IMX_GPC_BASE + IMR1_CORE0_M4, 42*88a26465SJacky Bai }; 43*88a26465SJacky Bai 44*88a26465SJacky Bai spinlock_t gpc_imr_lock[4]; 45*88a26465SJacky Bai 46*88a26465SJacky Bai static void gpc_imr_core_spin_lock(unsigned int core_id) 47*88a26465SJacky Bai { 48*88a26465SJacky Bai spin_lock(&gpc_imr_lock[core_id]); 49*88a26465SJacky Bai } 50*88a26465SJacky Bai 51*88a26465SJacky Bai static void gpc_imr_core_spin_unlock(unsigned int core_id) 52*88a26465SJacky Bai { 53*88a26465SJacky Bai spin_unlock(&gpc_imr_lock[core_id]); 54*88a26465SJacky Bai } 55*88a26465SJacky Bai 56*88a26465SJacky Bai static void gpc_save_imr_lpm(unsigned int core_id, unsigned int imr_idx) 57*88a26465SJacky Bai { 58*88a26465SJacky Bai uint32_t reg = gpc_imr_offset[core_id] + imr_idx * 4; 59*88a26465SJacky Bai 60*88a26465SJacky Bai gpc_imr_core_spin_lock(core_id); 61*88a26465SJacky Bai 62*88a26465SJacky Bai gpc_saved_imrs[core_id + imr_idx * 4] = mmio_read_32(reg); 63*88a26465SJacky Bai mmio_write_32(reg, ~gpc_wake_irqs[imr_idx]); 64*88a26465SJacky Bai 65*88a26465SJacky Bai gpc_imr_core_spin_unlock(core_id); 66*88a26465SJacky Bai } 67*88a26465SJacky Bai 68*88a26465SJacky Bai static void gpc_restore_imr_lpm(unsigned int core_id, unsigned int imr_idx) 69*88a26465SJacky Bai { 70*88a26465SJacky Bai uint32_t reg = gpc_imr_offset[core_id] + imr_idx * 4; 71*88a26465SJacky Bai uint32_t val = gpc_saved_imrs[core_id + imr_idx * 4]; 72*88a26465SJacky Bai 73*88a26465SJacky Bai gpc_imr_core_spin_lock(core_id); 74*88a26465SJacky Bai 75*88a26465SJacky Bai mmio_write_32(reg, val); 76*88a26465SJacky Bai 77*88a26465SJacky Bai gpc_imr_core_spin_unlock(core_id); 78*88a26465SJacky Bai } 79*88a26465SJacky Bai 80*88a26465SJacky Bai /* 81*88a26465SJacky Bai * On i.MX8MQ, only in system suspend mode, the A53 cluster can 82*88a26465SJacky Bai * enter LPM mode and shutdown the A53 PLAT power domain. So LPM 83*88a26465SJacky Bai * wakeup only used for system suspend. when system enter suspend, 84*88a26465SJacky Bai * any A53 CORE can be the last core to suspend the system, But 85*88a26465SJacky Bai * the LPM wakeup can only use the C0's IMR to wakeup A53 cluster 86*88a26465SJacky Bai * from LPM, so save C0's IMRs before suspend, restore back after 87*88a26465SJacky Bai * resume. 88*88a26465SJacky Bai */ 89*88a26465SJacky Bai void imx_set_sys_wakeup(unsigned int last_core, bool pdn) 90*88a26465SJacky Bai { 91*88a26465SJacky Bai unsigned int imr, core; 92*88a26465SJacky Bai 93*88a26465SJacky Bai if (pdn) { 94*88a26465SJacky Bai for (imr = 0U; imr < MAX_IMR_NUM; imr++) { 95*88a26465SJacky Bai for (core = 0U; core < PLATFORM_CORE_COUNT; core++) { 96*88a26465SJacky Bai gpc_save_imr_lpm(core, imr); 97*88a26465SJacky Bai } 98*88a26465SJacky Bai } 99*88a26465SJacky Bai } else { 100*88a26465SJacky Bai for (imr = 0U; imr < MAX_IMR_NUM; imr++) { 101*88a26465SJacky Bai for (core = 0U; core < PLATFORM_CORE_COUNT; core++) { 102*88a26465SJacky Bai gpc_restore_imr_lpm(core, imr); 103*88a26465SJacky Bai } 104*88a26465SJacky Bai } 105*88a26465SJacky Bai } 106*88a26465SJacky Bai } 107*88a26465SJacky Bai 108*88a26465SJacky Bai static void imx_gpc_hwirq_mask(unsigned int hwirq) 109*88a26465SJacky Bai { 110*88a26465SJacky Bai uintptr_t reg; 111*88a26465SJacky Bai unsigned int val; 112*88a26465SJacky Bai 113*88a26465SJacky Bai if (hwirq >= MAX_HW_IRQ_NUM) { 114*88a26465SJacky Bai return; 115*88a26465SJacky Bai } 116*88a26465SJacky Bai 117*88a26465SJacky Bai gpc_imr_core_spin_lock(0); 118*88a26465SJacky Bai reg = gpc_imr_offset[0] + (hwirq / 32) * 4; 119*88a26465SJacky Bai val = mmio_read_32(reg); 120*88a26465SJacky Bai val |= 1 << hwirq % 32; 121*88a26465SJacky Bai mmio_write_32(reg, val); 122*88a26465SJacky Bai gpc_imr_core_spin_unlock(0); 123*88a26465SJacky Bai } 124*88a26465SJacky Bai 125*88a26465SJacky Bai static void imx_gpc_hwirq_unmask(unsigned int hwirq) 126*88a26465SJacky Bai { 127*88a26465SJacky Bai uintptr_t reg; 128*88a26465SJacky Bai unsigned int val; 129*88a26465SJacky Bai 130*88a26465SJacky Bai if (hwirq >= MAX_HW_IRQ_NUM) { 131*88a26465SJacky Bai return; 132*88a26465SJacky Bai } 133*88a26465SJacky Bai 134*88a26465SJacky Bai gpc_imr_core_spin_lock(0); 135*88a26465SJacky Bai reg = gpc_imr_offset[0] + (hwirq / 32) * 4; 136*88a26465SJacky Bai val = mmio_read_32(reg); 137*88a26465SJacky Bai val &= ~(1 << hwirq % 32); 138*88a26465SJacky Bai mmio_write_32(reg, val); 139*88a26465SJacky Bai gpc_imr_core_spin_unlock(0); 140*88a26465SJacky Bai } 141*88a26465SJacky Bai 142*88a26465SJacky Bai static void imx_gpc_set_wake(uint32_t hwirq, bool on) 143*88a26465SJacky Bai { 144*88a26465SJacky Bai uint32_t mask, idx; 145*88a26465SJacky Bai 146*88a26465SJacky Bai if (hwirq >= MAX_HW_IRQ_NUM) { 147*88a26465SJacky Bai return; 148*88a26465SJacky Bai } 149*88a26465SJacky Bai 150*88a26465SJacky Bai mask = 1 << hwirq % 32; 151*88a26465SJacky Bai idx = hwirq / 32; 152*88a26465SJacky Bai gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask : 153*88a26465SJacky Bai gpc_wake_irqs[idx] & ~mask; 154*88a26465SJacky Bai } 155*88a26465SJacky Bai 156*88a26465SJacky Bai static void imx_gpc_mask_irq0(uint32_t core_id, uint32_t mask) 157*88a26465SJacky Bai { 158*88a26465SJacky Bai gpc_imr_core_spin_lock(core_id); 159*88a26465SJacky Bai if (mask) { 160*88a26465SJacky Bai mmio_setbits_32(gpc_imr_offset[core_id], 1); 161*88a26465SJacky Bai } else { 162*88a26465SJacky Bai mmio_clrbits_32(gpc_imr_offset[core_id], 1); 163*88a26465SJacky Bai } 164*88a26465SJacky Bai 165*88a26465SJacky Bai dsb(); 166*88a26465SJacky Bai gpc_imr_core_spin_unlock(core_id); 167*88a26465SJacky Bai } 168*88a26465SJacky Bai 169*88a26465SJacky Bai void imx_gpc_core_wake(uint32_t cpumask) 170*88a26465SJacky Bai { 171*88a26465SJacky Bai for (int i = 0; i < PLATFORM_CORE_COUNT; i++) { 172*88a26465SJacky Bai if (cpumask & (1 << i)) { 173*88a26465SJacky Bai imx_gpc_mask_irq0(i, false); 174*88a26465SJacky Bai } 175*88a26465SJacky Bai } 176*88a26465SJacky Bai } 177*88a26465SJacky Bai 178*88a26465SJacky Bai void imx_gpc_set_a53_core_awake(uint32_t core_id) 179*88a26465SJacky Bai { 180*88a26465SJacky Bai imx_gpc_mask_irq0(core_id, true); 181*88a26465SJacky Bai } 182*88a26465SJacky Bai 183*88a26465SJacky Bai static void imx_gpc_set_affinity(uint32_t hwirq, unsigned int cpu_idx) 184*88a26465SJacky Bai { 185*88a26465SJacky Bai uintptr_t reg; 186*88a26465SJacky Bai unsigned int val; 187*88a26465SJacky Bai 188*88a26465SJacky Bai if (hwirq >= MAX_HW_IRQ_NUM || cpu_idx >= 4) { 189*88a26465SJacky Bai return; 190*88a26465SJacky Bai } 191*88a26465SJacky Bai 192*88a26465SJacky Bai /* 193*88a26465SJacky Bai * using the mask/unmask bit as affinity function.unmask the 194*88a26465SJacky Bai * IMR bit to enable IRQ wakeup for this core. 195*88a26465SJacky Bai */ 196*88a26465SJacky Bai gpc_imr_core_spin_lock(cpu_idx); 197*88a26465SJacky Bai reg = gpc_imr_offset[cpu_idx] + (hwirq / 32) * 4; 198*88a26465SJacky Bai val = mmio_read_32(reg); 199*88a26465SJacky Bai val &= ~(1 << hwirq % 32); 200*88a26465SJacky Bai mmio_write_32(reg, val); 201*88a26465SJacky Bai gpc_imr_core_spin_unlock(cpu_idx); 202*88a26465SJacky Bai 203*88a26465SJacky Bai /* clear affinity of other core */ 204*88a26465SJacky Bai for (int i = 0; i < PLATFORM_CORE_COUNT; i++) { 205*88a26465SJacky Bai if (cpu_idx != i) { 206*88a26465SJacky Bai gpc_imr_core_spin_lock(i); 207*88a26465SJacky Bai reg = gpc_imr_offset[i] + (hwirq / 32) * 4; 208*88a26465SJacky Bai val = mmio_read_32(reg); 209*88a26465SJacky Bai val |= (1 << hwirq % 32); 210*88a26465SJacky Bai mmio_write_32(reg, val); 211*88a26465SJacky Bai gpc_imr_core_spin_unlock(i); 212*88a26465SJacky Bai } 213*88a26465SJacky Bai } 214*88a26465SJacky Bai } 21581136819SBai Ping 21681136819SBai Ping /* use wfi power down the core */ 21781136819SBai Ping void imx_set_cpu_pwr_off(unsigned int core_id) 21881136819SBai Ping { 219fe5e1c14SJacky Bai bakery_lock_get(&gpc_lock); 220fe5e1c14SJacky Bai 22181136819SBai Ping /* enable the wfi power down of the core */ 22281136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) | 22381136819SBai Ping (1 << (core_id + 20))); 224fe5e1c14SJacky Bai 225fe5e1c14SJacky Bai bakery_lock_release(&gpc_lock); 226fe5e1c14SJacky Bai 22781136819SBai Ping /* assert the pcg pcr bit of the core */ 22881136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); 22981136819SBai Ping }; 23081136819SBai Ping 23181136819SBai Ping /* if out of lpm, we need to do reverse steps */ 23281136819SBai Ping void imx_set_cpu_lpm(unsigned int core_id, bool pdn) 23381136819SBai Ping { 234fe5e1c14SJacky Bai bakery_lock_get(&gpc_lock); 235fe5e1c14SJacky Bai 23681136819SBai Ping if (pdn) { 23781136819SBai Ping /* enable the core WFI PDN & IRQ PUP */ 23881136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) | 23981136819SBai Ping (1 << (core_id + 20)) | COREx_IRQ_WUP(core_id)); 24081136819SBai Ping /* assert the pcg pcr bit of the core */ 24181136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); 24281136819SBai Ping } else { 24381136819SBai Ping /* disable CORE WFI PDN & IRQ PUP */ 24481136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) | 24581136819SBai Ping COREx_IRQ_WUP(core_id)); 24681136819SBai Ping /* deassert the pcg pcr bit of the core */ 24781136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1); 24881136819SBai Ping } 249fe5e1c14SJacky Bai 250fe5e1c14SJacky Bai bakery_lock_release(&gpc_lock); 25181136819SBai Ping } 25281136819SBai Ping 25381136819SBai Ping void imx_pup_pdn_slot_config(int last_core, bool pdn) 25481136819SBai Ping { 25581136819SBai Ping if (pdn) { 25681136819SBai Ping /* SLOT0 for A53 PLAT power down */ 25781136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(0), SLT_PLAT_PDN); 25881136819SBai Ping /* SLOT1 for A53 PLAT power up */ 25981136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(1), SLT_PLAT_PUP); 26081136819SBai Ping /* SLOT2 for A53 primary core power up */ 26181136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(2), SLT_COREx_PUP(last_core)); 26281136819SBai Ping /* ACK setting: PLAT ACK for PDN, CORE ACK for PUP */ 26381136819SBai Ping mmio_clrsetbits_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, 0xFFFFFFFF, 26481136819SBai Ping A53_PLAT_PDN_ACK | A53_PLAT_PUP_ACK); 26581136819SBai Ping } else { 26681136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(0), 0xFFFFFFFF); 26781136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(1), 0xFFFFFFFF); 26881136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(2), 0xFFFFFFFF); 26981136819SBai Ping mmio_clrsetbits_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, 0xFFFFFFFF, 27081136819SBai Ping A53_DUMMY_PDN_ACK | A53_DUMMY_PUP_ACK); 27181136819SBai Ping } 27281136819SBai Ping } 27381136819SBai Ping 27481136819SBai Ping void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state) 27581136819SBai Ping { 27681136819SBai Ping uint32_t val; 27781136819SBai Ping 27881136819SBai Ping if (is_local_state_off(power_state)) { 27981136819SBai Ping val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); 28081136819SBai Ping val |= A53_LPM_STOP; /* enable C0-C1's STOP mode */ 28181136819SBai Ping val &= ~CPU_CLOCK_ON_LPM; /* disable CPU clock in LPM mode */ 28281136819SBai Ping mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); 28381136819SBai Ping 28481136819SBai Ping /* enable C2-3's STOP mode */ 28581136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, A53_LPM_STOP); 28681136819SBai Ping 28781136819SBai Ping /* enable PLAT/SCU power down */ 28881136819SBai Ping val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD); 28981136819SBai Ping val &= ~EN_L2_WFI_PDN; 29081136819SBai Ping val |= L2PGE | EN_PLAT_PDN; 29181136819SBai Ping val &= ~COREx_IRQ_WUP(last_core); /* disable IRQ PUP for last core */ 29281136819SBai Ping val |= COREx_LPM_PUP(last_core); /* enable LPM PUP for last core */ 29381136819SBai Ping mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val); 29481136819SBai Ping 29581136819SBai Ping imx_pup_pdn_slot_config(last_core, true); 29681136819SBai Ping 29781136819SBai Ping /* enable PLAT PGC */ 29881136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + A53_PLAT_PGC, 0x1); 29981136819SBai Ping } else { 30081136819SBai Ping /* clear PLAT PGC */ 30181136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + A53_PLAT_PGC, 0x1); 30281136819SBai Ping 30381136819SBai Ping /* clear the slot and ack for cluster power down */ 30481136819SBai Ping imx_pup_pdn_slot_config(last_core, false); 30581136819SBai Ping 30681136819SBai Ping val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); 30781136819SBai Ping val &= ~A53_LPM_MASK; /* clear the C0~1 LPM */ 30881136819SBai Ping val |= CPU_CLOCK_ON_LPM; /* disable cpu clock in LPM */ 30981136819SBai Ping mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); 31081136819SBai Ping 31181136819SBai Ping /* set A53 LPM to RUN mode */ 31281136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, A53_LPM_MASK); 31381136819SBai Ping 31481136819SBai Ping /* clear PLAT/SCU power down */ 31581136819SBai Ping val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD); 31681136819SBai Ping val |= EN_L2_WFI_PDN; 31781136819SBai Ping val &= ~(L2PGE | EN_PLAT_PDN); 31881136819SBai Ping val &= ~COREx_LPM_PUP(last_core); /* disable C0's LPM PUP */ 31981136819SBai Ping mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val); 32081136819SBai Ping } 32181136819SBai Ping } 32281136819SBai Ping 323*88a26465SJacky Bai int imx_gpc_handler(uint32_t smc_fid, 324*88a26465SJacky Bai u_register_t x1, 325*88a26465SJacky Bai u_register_t x2, 326*88a26465SJacky Bai u_register_t x3) 327*88a26465SJacky Bai { 328*88a26465SJacky Bai switch (x1) { 329*88a26465SJacky Bai case FSL_SIP_CONFIG_GPC_CORE_WAKE: 330*88a26465SJacky Bai imx_gpc_core_wake(x2); 331*88a26465SJacky Bai break; 332*88a26465SJacky Bai case FSL_SIP_CONFIG_GPC_SET_WAKE: 333*88a26465SJacky Bai imx_gpc_set_wake(x2, x3); 334*88a26465SJacky Bai break; 335*88a26465SJacky Bai case FSL_SIP_CONFIG_GPC_MASK: 336*88a26465SJacky Bai imx_gpc_hwirq_mask(x2); 337*88a26465SJacky Bai break; 338*88a26465SJacky Bai case FSL_SIP_CONFIG_GPC_UNMASK: 339*88a26465SJacky Bai imx_gpc_hwirq_unmask(x2); 340*88a26465SJacky Bai break; 341*88a26465SJacky Bai case FSL_SIP_CONFIG_GPC_SET_AFF: 342*88a26465SJacky Bai imx_gpc_set_affinity(x2, x3); 343*88a26465SJacky Bai break; 344*88a26465SJacky Bai default: 345*88a26465SJacky Bai return SMC_UNK; 346*88a26465SJacky Bai } 347*88a26465SJacky Bai 348*88a26465SJacky Bai return 0; 349*88a26465SJacky Bai } 350*88a26465SJacky Bai 35181136819SBai Ping void imx_gpc_init(void) 35281136819SBai Ping { 35381136819SBai Ping uint32_t val; 354*88a26465SJacky Bai unsigned int i, j; 355*88a26465SJacky Bai 35681136819SBai Ping /* mask all the interrupt by default */ 357*88a26465SJacky Bai for (i = 0U; i < PLATFORM_CORE_COUNT; i++) { 358*88a26465SJacky Bai for (j = 0U; j < ARRAY_SIZE(gpc_imr_offset); j++) { 359*88a26465SJacky Bai mmio_write_32(gpc_imr_offset[j] + i * 4, ~0x0); 3607696880aSLeonard Crestez } 361*88a26465SJacky Bai } 362*88a26465SJacky Bai 36381136819SBai Ping /* Due to the hardware design requirement, need to make 36481136819SBai Ping * sure GPR interrupt(#32) is unmasked during RUN mode to 36581136819SBai Ping * avoid entering DSM mode by mistake. 36681136819SBai Ping */ 367*88a26465SJacky Bai for (i = 0U; i < PLATFORM_CORE_COUNT; i++) { 368*88a26465SJacky Bai mmio_write_32(gpc_imr_offset[i], ~0x1); 369*88a26465SJacky Bai } 370*88a26465SJacky Bai 371*88a26465SJacky Bai /* leave the IOMUX_GPC bit 12 on for core wakeup */ 372*88a26465SJacky Bai mmio_setbits_32(IMX_IOMUX_GPR_BASE + 0x4, 1 << 12); 37381136819SBai Ping 37481136819SBai Ping /* use external IRQs to wakeup C0~C3 from LPM */ 37581136819SBai Ping val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); 37681136819SBai Ping val |= IRQ_SRC_A53_WUP; 37781136819SBai Ping /* clear the MASTER0 LPM handshake */ 37881136819SBai Ping val &= ~MASTER0_LPM_HSK; 37981136819SBai Ping mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); 38081136819SBai Ping 38181136819SBai Ping /* mask M4 DSM trigger if M4 is NOT enabled */ 38281136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + LPCR_M4, DSM_MODE_MASK); 38381136819SBai Ping 38481136819SBai Ping /* set all mix/PU in A53 domain */ 38581136819SBai Ping mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xfffd); 38681136819SBai Ping 38781136819SBai Ping /* set SCU timming */ 38881136819SBai Ping mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING, 38981136819SBai Ping (0x59 << 10) | 0x5B | (0x2 << 20)); 39081136819SBai Ping 39181136819SBai Ping /* set DUMMY PDN/PUP ACK by default for A53 domain */ 39281136819SBai Ping mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, A53_DUMMY_PUP_ACK | 39381136819SBai Ping A53_DUMMY_PDN_ACK); 39481136819SBai Ping 39581136819SBai Ping /* disable DSM mode by default */ 39681136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + SLPCR, DSM_MODE_MASK); 39781136819SBai Ping 39881136819SBai Ping /* 39981136819SBai Ping * USB PHY power up needs to make sure RESET bit in SRC is clear, 40081136819SBai Ping * otherwise, the PU power up bit in GPC will NOT self-cleared. 40181136819SBai Ping * only need to do it once. 40281136819SBai Ping */ 40381136819SBai Ping mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1); 40481136819SBai Ping mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1); 405e1958506SLeonard Crestez 40666345b8bSJacky Bai /* 40766345b8bSJacky Bai * for USB OTG, the limitation are: 40866345b8bSJacky Bai * 1. before system clock config, the IPG clock run at 12.5MHz, delay time 40966345b8bSJacky Bai * should be longer than 82us. 41066345b8bSJacky Bai * 2. after system clock config, ipg clock run at 66.5MHz, delay time 41166345b8bSJacky Bai * be longer that 15.3 us. 41266345b8bSJacky Bai * Add 100us to make sure the USB OTG SRC is clear safely. 41366345b8bSJacky Bai */ 41466345b8bSJacky Bai udelay(100); 41581136819SBai Ping } 416