181136819SBai Ping /* 288a26465SJacky 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 1188a26465SJacky 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> 1688a26465SJacky Bai #include <lib/smccc.h> 1788a26465SJacky Bai #include <lib/spinlock.h> 1888a26465SJacky Bai #include <plat/common/platform.h> 1909d40e0eSAntonio Nino Diaz #include <services/std_svc.h> 2009d40e0eSAntonio Nino Diaz 2109d40e0eSAntonio Nino Diaz #include <gpc.h> 2288a26465SJacky Bai #include <platform_def.h> 2388a26465SJacky Bai 2488a26465SJacky Bai #define FSL_SIP_CONFIG_GPC_MASK U(0x00) 2588a26465SJacky Bai #define FSL_SIP_CONFIG_GPC_UNMASK U(0x01) 2688a26465SJacky Bai #define FSL_SIP_CONFIG_GPC_SET_WAKE U(0x02) 2788a26465SJacky Bai #define FSL_SIP_CONFIG_GPC_PM_DOMAIN U(0x03) 2888a26465SJacky Bai #define FSL_SIP_CONFIG_GPC_SET_AFF U(0x04) 2988a26465SJacky Bai #define FSL_SIP_CONFIG_GPC_CORE_WAKE U(0x05) 3088a26465SJacky Bai 3188a26465SJacky Bai #define MAX_HW_IRQ_NUM U(128) 3288a26465SJacky Bai #define MAX_IMR_NUM U(4) 3388a26465SJacky Bai 3488a26465SJacky Bai static uint32_t gpc_saved_imrs[16]; 3588a26465SJacky Bai static uint32_t gpc_wake_irqs[4]; 3688a26465SJacky Bai static uint32_t gpc_imr_offset[] = { 3788a26465SJacky Bai IMX_GPC_BASE + IMR1_CORE0_A53, 3888a26465SJacky Bai IMX_GPC_BASE + IMR1_CORE1_A53, 3988a26465SJacky Bai IMX_GPC_BASE + IMR1_CORE2_A53, 4088a26465SJacky Bai IMX_GPC_BASE + IMR1_CORE3_A53, 4188a26465SJacky Bai IMX_GPC_BASE + IMR1_CORE0_M4, 4288a26465SJacky Bai }; 4388a26465SJacky Bai 4488a26465SJacky Bai spinlock_t gpc_imr_lock[4]; 4588a26465SJacky Bai 4688a26465SJacky Bai static void gpc_imr_core_spin_lock(unsigned int core_id) 4788a26465SJacky Bai { 4888a26465SJacky Bai spin_lock(&gpc_imr_lock[core_id]); 4988a26465SJacky Bai } 5088a26465SJacky Bai 5188a26465SJacky Bai static void gpc_imr_core_spin_unlock(unsigned int core_id) 5288a26465SJacky Bai { 5388a26465SJacky Bai spin_unlock(&gpc_imr_lock[core_id]); 5488a26465SJacky Bai } 5588a26465SJacky Bai 5688a26465SJacky Bai static void gpc_save_imr_lpm(unsigned int core_id, unsigned int imr_idx) 5788a26465SJacky Bai { 5888a26465SJacky Bai uint32_t reg = gpc_imr_offset[core_id] + imr_idx * 4; 5988a26465SJacky Bai 6088a26465SJacky Bai gpc_imr_core_spin_lock(core_id); 6188a26465SJacky Bai 6288a26465SJacky Bai gpc_saved_imrs[core_id + imr_idx * 4] = mmio_read_32(reg); 6388a26465SJacky Bai mmio_write_32(reg, ~gpc_wake_irqs[imr_idx]); 6488a26465SJacky Bai 6588a26465SJacky Bai gpc_imr_core_spin_unlock(core_id); 6688a26465SJacky Bai } 6788a26465SJacky Bai 6888a26465SJacky Bai static void gpc_restore_imr_lpm(unsigned int core_id, unsigned int imr_idx) 6988a26465SJacky Bai { 7088a26465SJacky Bai uint32_t reg = gpc_imr_offset[core_id] + imr_idx * 4; 7188a26465SJacky Bai uint32_t val = gpc_saved_imrs[core_id + imr_idx * 4]; 7288a26465SJacky Bai 7388a26465SJacky Bai gpc_imr_core_spin_lock(core_id); 7488a26465SJacky Bai 7588a26465SJacky Bai mmio_write_32(reg, val); 7688a26465SJacky Bai 7788a26465SJacky Bai gpc_imr_core_spin_unlock(core_id); 7888a26465SJacky Bai } 7988a26465SJacky Bai 8088a26465SJacky Bai /* 8188a26465SJacky Bai * On i.MX8MQ, only in system suspend mode, the A53 cluster can 8288a26465SJacky Bai * enter LPM mode and shutdown the A53 PLAT power domain. So LPM 8388a26465SJacky Bai * wakeup only used for system suspend. when system enter suspend, 8488a26465SJacky Bai * any A53 CORE can be the last core to suspend the system, But 8588a26465SJacky Bai * the LPM wakeup can only use the C0's IMR to wakeup A53 cluster 8688a26465SJacky Bai * from LPM, so save C0's IMRs before suspend, restore back after 8788a26465SJacky Bai * resume. 8888a26465SJacky Bai */ 8988a26465SJacky Bai void imx_set_sys_wakeup(unsigned int last_core, bool pdn) 9088a26465SJacky Bai { 9188a26465SJacky Bai unsigned int imr, core; 9288a26465SJacky Bai 9388a26465SJacky Bai if (pdn) { 9488a26465SJacky Bai for (imr = 0U; imr < MAX_IMR_NUM; imr++) { 9588a26465SJacky Bai for (core = 0U; core < PLATFORM_CORE_COUNT; core++) { 9688a26465SJacky Bai gpc_save_imr_lpm(core, imr); 9788a26465SJacky Bai } 9888a26465SJacky Bai } 9988a26465SJacky Bai } else { 10088a26465SJacky Bai for (imr = 0U; imr < MAX_IMR_NUM; imr++) { 10188a26465SJacky Bai for (core = 0U; core < PLATFORM_CORE_COUNT; core++) { 10288a26465SJacky Bai gpc_restore_imr_lpm(core, imr); 10388a26465SJacky Bai } 10488a26465SJacky Bai } 10588a26465SJacky Bai } 10688a26465SJacky Bai } 10788a26465SJacky Bai 10888a26465SJacky Bai static void imx_gpc_hwirq_mask(unsigned int hwirq) 10988a26465SJacky Bai { 11088a26465SJacky Bai uintptr_t reg; 11188a26465SJacky Bai unsigned int val; 11288a26465SJacky Bai 11388a26465SJacky Bai if (hwirq >= MAX_HW_IRQ_NUM) { 11488a26465SJacky Bai return; 11588a26465SJacky Bai } 11688a26465SJacky Bai 11788a26465SJacky Bai gpc_imr_core_spin_lock(0); 11888a26465SJacky Bai reg = gpc_imr_offset[0] + (hwirq / 32) * 4; 11988a26465SJacky Bai val = mmio_read_32(reg); 12088a26465SJacky Bai val |= 1 << hwirq % 32; 12188a26465SJacky Bai mmio_write_32(reg, val); 12288a26465SJacky Bai gpc_imr_core_spin_unlock(0); 12388a26465SJacky Bai } 12488a26465SJacky Bai 12588a26465SJacky Bai static void imx_gpc_hwirq_unmask(unsigned int hwirq) 12688a26465SJacky Bai { 12788a26465SJacky Bai uintptr_t reg; 12888a26465SJacky Bai unsigned int val; 12988a26465SJacky Bai 13088a26465SJacky Bai if (hwirq >= MAX_HW_IRQ_NUM) { 13188a26465SJacky Bai return; 13288a26465SJacky Bai } 13388a26465SJacky Bai 13488a26465SJacky Bai gpc_imr_core_spin_lock(0); 13588a26465SJacky Bai reg = gpc_imr_offset[0] + (hwirq / 32) * 4; 13688a26465SJacky Bai val = mmio_read_32(reg); 13788a26465SJacky Bai val &= ~(1 << hwirq % 32); 13888a26465SJacky Bai mmio_write_32(reg, val); 13988a26465SJacky Bai gpc_imr_core_spin_unlock(0); 14088a26465SJacky Bai } 14188a26465SJacky Bai 14288a26465SJacky Bai static void imx_gpc_set_wake(uint32_t hwirq, bool on) 14388a26465SJacky Bai { 14488a26465SJacky Bai uint32_t mask, idx; 14588a26465SJacky Bai 14688a26465SJacky Bai if (hwirq >= MAX_HW_IRQ_NUM) { 14788a26465SJacky Bai return; 14888a26465SJacky Bai } 14988a26465SJacky Bai 15088a26465SJacky Bai mask = 1 << hwirq % 32; 15188a26465SJacky Bai idx = hwirq / 32; 15288a26465SJacky Bai gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask : 15388a26465SJacky Bai gpc_wake_irqs[idx] & ~mask; 15488a26465SJacky Bai } 15588a26465SJacky Bai 15688a26465SJacky Bai static void imx_gpc_mask_irq0(uint32_t core_id, uint32_t mask) 15788a26465SJacky Bai { 15888a26465SJacky Bai gpc_imr_core_spin_lock(core_id); 15988a26465SJacky Bai if (mask) { 16088a26465SJacky Bai mmio_setbits_32(gpc_imr_offset[core_id], 1); 16188a26465SJacky Bai } else { 16288a26465SJacky Bai mmio_clrbits_32(gpc_imr_offset[core_id], 1); 16388a26465SJacky Bai } 16488a26465SJacky Bai 16588a26465SJacky Bai dsb(); 16688a26465SJacky Bai gpc_imr_core_spin_unlock(core_id); 16788a26465SJacky Bai } 16888a26465SJacky Bai 16988a26465SJacky Bai void imx_gpc_core_wake(uint32_t cpumask) 17088a26465SJacky Bai { 17188a26465SJacky Bai for (int i = 0; i < PLATFORM_CORE_COUNT; i++) { 17288a26465SJacky Bai if (cpumask & (1 << i)) { 17388a26465SJacky Bai imx_gpc_mask_irq0(i, false); 17488a26465SJacky Bai } 17588a26465SJacky Bai } 17688a26465SJacky Bai } 17788a26465SJacky Bai 17888a26465SJacky Bai void imx_gpc_set_a53_core_awake(uint32_t core_id) 17988a26465SJacky Bai { 18088a26465SJacky Bai imx_gpc_mask_irq0(core_id, true); 18188a26465SJacky Bai } 18288a26465SJacky Bai 18388a26465SJacky Bai static void imx_gpc_set_affinity(uint32_t hwirq, unsigned int cpu_idx) 18488a26465SJacky Bai { 18588a26465SJacky Bai uintptr_t reg; 18688a26465SJacky Bai unsigned int val; 18788a26465SJacky Bai 18888a26465SJacky Bai if (hwirq >= MAX_HW_IRQ_NUM || cpu_idx >= 4) { 18988a26465SJacky Bai return; 19088a26465SJacky Bai } 19188a26465SJacky Bai 19288a26465SJacky Bai /* 19388a26465SJacky Bai * using the mask/unmask bit as affinity function.unmask the 19488a26465SJacky Bai * IMR bit to enable IRQ wakeup for this core. 19588a26465SJacky Bai */ 19688a26465SJacky Bai gpc_imr_core_spin_lock(cpu_idx); 19788a26465SJacky Bai reg = gpc_imr_offset[cpu_idx] + (hwirq / 32) * 4; 19888a26465SJacky Bai val = mmio_read_32(reg); 19988a26465SJacky Bai val &= ~(1 << hwirq % 32); 20088a26465SJacky Bai mmio_write_32(reg, val); 20188a26465SJacky Bai gpc_imr_core_spin_unlock(cpu_idx); 20288a26465SJacky Bai 20388a26465SJacky Bai /* clear affinity of other core */ 20488a26465SJacky Bai for (int i = 0; i < PLATFORM_CORE_COUNT; i++) { 20588a26465SJacky Bai if (cpu_idx != i) { 20688a26465SJacky Bai gpc_imr_core_spin_lock(i); 20788a26465SJacky Bai reg = gpc_imr_offset[i] + (hwirq / 32) * 4; 20888a26465SJacky Bai val = mmio_read_32(reg); 20988a26465SJacky Bai val |= (1 << hwirq % 32); 21088a26465SJacky Bai mmio_write_32(reg, val); 21188a26465SJacky Bai gpc_imr_core_spin_unlock(i); 21288a26465SJacky Bai } 21388a26465SJacky Bai } 21488a26465SJacky 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*387a1df1SJacky Bai #define MAX_PLL_NUM U(12) 324*387a1df1SJacky Bai 325*387a1df1SJacky Bai static const struct pll_override imx8mq_pll[MAX_PLL_NUM] = { 326*387a1df1SJacky Bai {.reg = 0x0, .override_mask = 0x140000, }, 327*387a1df1SJacky Bai {.reg = 0x8, .override_mask = 0x140000, }, 328*387a1df1SJacky Bai {.reg = 0x10, .override_mask = 0x140000, }, 329*387a1df1SJacky Bai {.reg = 0x18, .override_mask = 0x140000, }, 330*387a1df1SJacky Bai {.reg = 0x20, .override_mask = 0x140000, }, 331*387a1df1SJacky Bai {.reg = 0x28, .override_mask = 0x140000, }, 332*387a1df1SJacky Bai {.reg = 0x30, .override_mask = 0x1555540, }, 333*387a1df1SJacky Bai {.reg = 0x3c, .override_mask = 0x1555540, }, 334*387a1df1SJacky Bai {.reg = 0x48, .override_mask = 0x140, }, 335*387a1df1SJacky Bai {.reg = 0x54, .override_mask = 0x140, }, 336*387a1df1SJacky Bai {.reg = 0x60, .override_mask = 0x140, }, 337*387a1df1SJacky Bai {.reg = 0x70, .override_mask = 0xa, }, 338*387a1df1SJacky Bai }; 339*387a1df1SJacky Bai 340*387a1df1SJacky Bai void imx_anamix_override(bool enter) 341*387a1df1SJacky Bai { 342*387a1df1SJacky Bai unsigned int i; 343*387a1df1SJacky Bai 344*387a1df1SJacky Bai /* enable the pll override bit before entering DSM mode */ 345*387a1df1SJacky Bai for (i = 0; i < MAX_PLL_NUM; i++) { 346*387a1df1SJacky Bai if (enter) { 347*387a1df1SJacky Bai mmio_setbits_32(IMX_ANAMIX_BASE + imx8mq_pll[i].reg, 348*387a1df1SJacky Bai imx8mq_pll[i].override_mask); 349*387a1df1SJacky Bai } else { 350*387a1df1SJacky Bai mmio_clrbits_32(IMX_ANAMIX_BASE + imx8mq_pll[i].reg, 351*387a1df1SJacky Bai imx8mq_pll[i].override_mask); 352*387a1df1SJacky Bai } 353*387a1df1SJacky Bai } 354*387a1df1SJacky Bai } 355*387a1df1SJacky Bai 35688a26465SJacky Bai int imx_gpc_handler(uint32_t smc_fid, 35788a26465SJacky Bai u_register_t x1, 35888a26465SJacky Bai u_register_t x2, 35988a26465SJacky Bai u_register_t x3) 36088a26465SJacky Bai { 36188a26465SJacky Bai switch (x1) { 36288a26465SJacky Bai case FSL_SIP_CONFIG_GPC_CORE_WAKE: 36388a26465SJacky Bai imx_gpc_core_wake(x2); 36488a26465SJacky Bai break; 36588a26465SJacky Bai case FSL_SIP_CONFIG_GPC_SET_WAKE: 36688a26465SJacky Bai imx_gpc_set_wake(x2, x3); 36788a26465SJacky Bai break; 36888a26465SJacky Bai case FSL_SIP_CONFIG_GPC_MASK: 36988a26465SJacky Bai imx_gpc_hwirq_mask(x2); 37088a26465SJacky Bai break; 37188a26465SJacky Bai case FSL_SIP_CONFIG_GPC_UNMASK: 37288a26465SJacky Bai imx_gpc_hwirq_unmask(x2); 37388a26465SJacky Bai break; 37488a26465SJacky Bai case FSL_SIP_CONFIG_GPC_SET_AFF: 37588a26465SJacky Bai imx_gpc_set_affinity(x2, x3); 37688a26465SJacky Bai break; 37788a26465SJacky Bai default: 37888a26465SJacky Bai return SMC_UNK; 37988a26465SJacky Bai } 38088a26465SJacky Bai 38188a26465SJacky Bai return 0; 38288a26465SJacky Bai } 38388a26465SJacky Bai 38481136819SBai Ping void imx_gpc_init(void) 38581136819SBai Ping { 38681136819SBai Ping uint32_t val; 38788a26465SJacky Bai unsigned int i, j; 38888a26465SJacky Bai 38981136819SBai Ping /* mask all the interrupt by default */ 39088a26465SJacky Bai for (i = 0U; i < PLATFORM_CORE_COUNT; i++) { 39188a26465SJacky Bai for (j = 0U; j < ARRAY_SIZE(gpc_imr_offset); j++) { 39288a26465SJacky Bai mmio_write_32(gpc_imr_offset[j] + i * 4, ~0x0); 3937696880aSLeonard Crestez } 39488a26465SJacky Bai } 39588a26465SJacky Bai 39681136819SBai Ping /* Due to the hardware design requirement, need to make 39781136819SBai Ping * sure GPR interrupt(#32) is unmasked during RUN mode to 39881136819SBai Ping * avoid entering DSM mode by mistake. 39981136819SBai Ping */ 40088a26465SJacky Bai for (i = 0U; i < PLATFORM_CORE_COUNT; i++) { 40188a26465SJacky Bai mmio_write_32(gpc_imr_offset[i], ~0x1); 40288a26465SJacky Bai } 40388a26465SJacky Bai 40488a26465SJacky Bai /* leave the IOMUX_GPC bit 12 on for core wakeup */ 40588a26465SJacky Bai mmio_setbits_32(IMX_IOMUX_GPR_BASE + 0x4, 1 << 12); 40681136819SBai Ping 40781136819SBai Ping /* use external IRQs to wakeup C0~C3 from LPM */ 40881136819SBai Ping val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); 40981136819SBai Ping val |= IRQ_SRC_A53_WUP; 41081136819SBai Ping /* clear the MASTER0 LPM handshake */ 41181136819SBai Ping val &= ~MASTER0_LPM_HSK; 41281136819SBai Ping mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); 41381136819SBai Ping 41481136819SBai Ping /* mask M4 DSM trigger if M4 is NOT enabled */ 41581136819SBai Ping mmio_setbits_32(IMX_GPC_BASE + LPCR_M4, DSM_MODE_MASK); 41681136819SBai Ping 41781136819SBai Ping /* set all mix/PU in A53 domain */ 41881136819SBai Ping mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xfffd); 41981136819SBai Ping 42081136819SBai Ping /* set SCU timming */ 42181136819SBai Ping mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING, 42281136819SBai Ping (0x59 << 10) | 0x5B | (0x2 << 20)); 42381136819SBai Ping 42481136819SBai Ping /* set DUMMY PDN/PUP ACK by default for A53 domain */ 42581136819SBai Ping mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, A53_DUMMY_PUP_ACK | 42681136819SBai Ping A53_DUMMY_PDN_ACK); 42781136819SBai Ping 42881136819SBai Ping /* disable DSM mode by default */ 42981136819SBai Ping mmio_clrbits_32(IMX_GPC_BASE + SLPCR, DSM_MODE_MASK); 43081136819SBai Ping 43181136819SBai Ping /* 43281136819SBai Ping * USB PHY power up needs to make sure RESET bit in SRC is clear, 43381136819SBai Ping * otherwise, the PU power up bit in GPC will NOT self-cleared. 43481136819SBai Ping * only need to do it once. 43581136819SBai Ping */ 43681136819SBai Ping mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1); 43781136819SBai Ping mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1); 438e1958506SLeonard Crestez 43966345b8bSJacky Bai /* 44066345b8bSJacky Bai * for USB OTG, the limitation are: 44166345b8bSJacky Bai * 1. before system clock config, the IPG clock run at 12.5MHz, delay time 44266345b8bSJacky Bai * should be longer than 82us. 44366345b8bSJacky Bai * 2. after system clock config, ipg clock run at 66.5MHz, delay time 44466345b8bSJacky Bai * be longer that 15.3 us. 44566345b8bSJacky Bai * Add 100us to make sure the USB OTG SRC is clear safely. 44666345b8bSJacky Bai */ 44766345b8bSJacky Bai udelay(100); 44881136819SBai Ping } 449