summaryrefslogtreecommitdiff
path: root/plat/imx/imx8m/imx8mn/gpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'plat/imx/imx8m/imx8mn/gpc.c')
-rw-r--r--plat/imx/imx8m/imx8mn/gpc.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/plat/imx/imx8m/imx8mn/gpc.c b/plat/imx/imx8m/imx8mn/gpc.c
new file mode 100644
index 00000000..9f9607d9
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/gpc.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2019 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/smccc.h>
+#include <platform_def.h>
+#include <services/std_svc.h>
+
+#include <gpc.h>
+#include <imx_sip_svc.h>
+
+void imx_gpc_init(void)
+{
+ unsigned int val;
+ int i;
+
+ /* mask all the wakeup irq by default */
+ for (i = 0; i < 4; i++) {
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
+ }
+
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+ /* use GIC wake_request to wakeup C0~C3 from LPM */
+ val |= 0x30c00000;
+ /* clear the MASTER0 LPM handshake */
+ val &= ~(1 << 6);
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+ /* clear MASTER1 & MASTER2 mapping in CPU0(A53) */
+ mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING |
+ MASTER2_MAPPING));
+
+ /* set all mix/PU in A53 domain */
+ mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xffff);
+
+ /*
+ * Set the CORE & SCU power up timing:
+ * SW = 0x1, SW2ISO = 0x1;
+ * the CPU CORE and SCU power up timming counter
+ * is drived by 32K OSC, each domain's power up
+ * latency is (SW + SW2ISO) / 32768
+ */
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING,
+ (0x59 << 10) | 0x5B | (0x2 << 20));
+
+ /* set DUMMY PDN/PUP ACK by default for A53 domain */
+ mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53,
+ A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK);
+
+ /* clear DSM by default */
+ val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+ val &= ~SLPCR_EN_DSM;
+ /* enable the fast wakeup wait mode */
+ val |= SLPCR_A53_FASTWUP_WAIT_MODE;
+ /* clear the RBC */
+ val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT);
+ /* set the STBY_COUNT to 0x5, (128 * 30)us */
+ val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT);
+ val |= (0x5 << SLPCR_STBY_COUNT_SHFT);
+ mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+
+ /*
+ * USB PHY power up needs to make sure RESET bit in SRC is clear,
+ * otherwise, the PU power up bit in GPC will NOT self-cleared.
+ * only need to do it once.
+ */
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
+
+ /* enable all the power domain by default */
+ mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, 0x485);
+}