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
gpc_imr_core_spin_lock(unsigned int core_id)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
gpc_imr_core_spin_unlock(unsigned int core_id)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
gpc_save_imr_lpm(unsigned int core_id,unsigned int imr_idx)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
gpc_restore_imr_lpm(unsigned int core_id,unsigned int imr_idx)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 */
imx_set_sys_wakeup(unsigned int last_core,bool pdn)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
imx_gpc_hwirq_mask(unsigned int hwirq)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
imx_gpc_hwirq_unmask(unsigned int hwirq)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
imx_gpc_set_wake(uint32_t hwirq,bool on)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
imx_gpc_mask_irq0(uint32_t core_id,uint32_t mask)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
imx_gpc_core_wake(uint32_t cpumask)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
imx_gpc_set_a53_core_awake(uint32_t core_id)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
imx_gpc_set_affinity(uint32_t hwirq,unsigned int cpu_idx)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 */
imx_set_cpu_pwr_off(unsigned int core_id)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 */
imx_set_cpu_lpm(unsigned int core_id,bool pdn)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
imx_pup_pdn_slot_config(int last_core,bool pdn)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,
264724ac3e2SJacky Bai A53_PLAT_PDN_ACK | SLT_COREx_PUP_ACK(last_core));
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
imx_set_cluster_powerdown(unsigned int last_core,uint8_t power_state)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
323387a1df1SJacky Bai #define MAX_PLL_NUM U(12)
324387a1df1SJacky Bai
325387a1df1SJacky Bai static const struct pll_override imx8mq_pll[MAX_PLL_NUM] = {
326387a1df1SJacky Bai {.reg = 0x0, .override_mask = 0x140000, },
327387a1df1SJacky Bai {.reg = 0x8, .override_mask = 0x140000, },
328387a1df1SJacky Bai {.reg = 0x10, .override_mask = 0x140000, },
329387a1df1SJacky Bai {.reg = 0x18, .override_mask = 0x140000, },
330387a1df1SJacky Bai {.reg = 0x20, .override_mask = 0x140000, },
331387a1df1SJacky Bai {.reg = 0x28, .override_mask = 0x140000, },
332387a1df1SJacky Bai {.reg = 0x30, .override_mask = 0x1555540, },
333387a1df1SJacky Bai {.reg = 0x3c, .override_mask = 0x1555540, },
334387a1df1SJacky Bai {.reg = 0x48, .override_mask = 0x140, },
335387a1df1SJacky Bai {.reg = 0x54, .override_mask = 0x140, },
336387a1df1SJacky Bai {.reg = 0x60, .override_mask = 0x140, },
337387a1df1SJacky Bai {.reg = 0x70, .override_mask = 0xa, },
338387a1df1SJacky Bai };
339387a1df1SJacky Bai
imx_anamix_override(bool enter)340387a1df1SJacky Bai void imx_anamix_override(bool enter)
341387a1df1SJacky Bai {
342387a1df1SJacky Bai unsigned int i;
343387a1df1SJacky Bai
344387a1df1SJacky Bai /* enable the pll override bit before entering DSM mode */
345387a1df1SJacky Bai for (i = 0; i < MAX_PLL_NUM; i++) {
346387a1df1SJacky Bai if (enter) {
347387a1df1SJacky Bai mmio_setbits_32(IMX_ANAMIX_BASE + imx8mq_pll[i].reg,
348387a1df1SJacky Bai imx8mq_pll[i].override_mask);
349387a1df1SJacky Bai } else {
350387a1df1SJacky Bai mmio_clrbits_32(IMX_ANAMIX_BASE + imx8mq_pll[i].reg,
351387a1df1SJacky Bai imx8mq_pll[i].override_mask);
352387a1df1SJacky Bai }
353387a1df1SJacky Bai }
354387a1df1SJacky Bai }
355387a1df1SJacky Bai
imx_gpc_handler(uint32_t smc_fid,u_register_t x1,u_register_t x2,u_register_t x3)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
imx_gpc_init(void)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
420*1b491eeaSElyes Haouas /* set SCU timing */
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