summaryrefslogtreecommitdiff
path: root/plat/freescale/imx8mq
diff options
context:
space:
mode:
Diffstat (limited to 'plat/freescale/imx8mq')
-rw-r--r--plat/freescale/imx8mq/gpc.c456
-rw-r--r--plat/freescale/imx8mq/imx8m_bl31_setup.c203
-rw-r--r--plat/freescale/imx8mq/imx8m_psci.c215
-rw-r--r--plat/freescale/imx8mq/include/fsl_sip.h24
-rw-r--r--plat/freescale/imx8mq/include/platform_def.h52
-rw-r--r--plat/freescale/imx8mq/include/soc.h67
-rw-r--r--plat/freescale/imx8mq/platform.mk27
-rw-r--r--plat/freescale/imx8mq/sip_svc.c80
8 files changed, 1124 insertions, 0 deletions
diff --git a/plat/freescale/imx8mq/gpc.c b/plat/freescale/imx8mq/gpc.c
new file mode 100644
index 00000000..58744c24
--- /dev/null
+++ b/plat/freescale/imx8mq/gpc.c
@@ -0,0 +1,456 @@
+/*
+ * Copyright 2017 NXP
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <debug.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <smcc_helpers.h>
+#include <std_svc.h>
+#include <types.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <fsl_sip.h>
+#include <soc.h>
+
+#define GPC_LPCR_A53_BSC 0x0
+#define GPC_LPCR_A53_BSC2 0x108
+#define GPC_LPCR_A53_AD 0x4
+#define GPC_LPCR_M4 0x8
+#define GPC_SLPCR 0x14
+#define GPC_MST_CPU_MAPPING 0x18
+#define GPC_PGC_ACK_SEL_A53 0x24
+#define GPC_IMR1_CORE0_A53 0x30
+#define GPC_IMR2_CORE0_A53 0x34
+#define GPC_IMR3_CORE0_A53 0x38
+#define GPC_IMR4_CORE0_A53 0x3c
+#define GPC_IMR1_CORE1_A53 0x40
+#define GPC_IMR2_CORE1_A53 0x44
+#define GPC_IMR3_CORE1_A53 0x48
+#define GPC_IMR4_CORE1_A53 0x4c
+#define GPC_IMR1_CORE2_A53 0x1c0
+#define GPC_IMR2_CORE2_A53 0x1c4
+#define GPC_IMR3_CORE2_A53 0x1c8
+#define GPC_IMR4_CORE2_A53 0x1cc
+#define GPC_IMR1_CORE3_A53 0x1d0
+#define GPC_IMR2_CORE3_A53 0x1d4
+#define GPC_IMR3_CORE3_A53 0x1d8
+#define GPC_IMR4_CORE3_A53 0x1dc
+#define GPC_PGC_CPU_0_1_MAPPING 0xec
+#define GPC_PGC_CORE0_TIMMING 0x804
+#define GPC_PGC_CORE1_TIMMING 0x844
+#define GPC_PGC_CORE2_TIMMING 0x884
+#define GPC_PGC_CORE3_TIMMING 0x8c4
+#define GPC_PGC_SCU_TIMMING 0x910
+#define GPC_SLOT0_CFG 0xb0
+
+#define LPCR_A53_BSC_CPU_CLK_ON_LPM 0x4000
+#define LPCR_A53_BSC_LPM0 0x3
+#define LPCR_A53_BSC_LPM1 0xc
+#define LPCR_A53_BSC2_LPM2 0x3
+#define LPCR_A53_BSC2_LPM3 0xc
+
+#define LPCR_A53_AD_L2PGE 0x80000000
+#define LPCR_A53_AD_EN_C3_PUP 0x8000000
+#define LPCR_A53_AD_EN_C3_IRQ_PUP 0x4000000
+#define LPCR_A53_AD_EN_C2_PUP 0x2000000
+#define LPCR_A53_AD_EN_C2_IRQ_PUP 0x1000000
+#define LPCR_A53_AD_EN_C3_PDN 0x80000
+#define LPCR_A53_AD_EN_C3_WFI_PDN 0x40000
+#define LPCR_A53_AD_EN_C2_PDN 0x20000
+#define LPCR_A53_AD_EN_C2_WFI_PDN 0x10000
+#define LPCR_A53_AD_EN_C1_PUP 0x800
+#define LPCR_A53_AD_EN_C1_IRQ_PUP 0x400
+#define LPCR_A53_AD_EN_C0_PUP 0x200
+#define LPCR_A53_AD_EN_C0_IRQ_PUP 0x100
+#define LPCR_A53_AD_EN_L2_WFI_PDN 0x20
+#define LPCR_A53_AD_EN_PLAT_PDN 0x10
+#define LPCR_A53_AD_EN_C1_PDN 0x8
+#define LPCR_A53_AD_EN_C1_WFI_PDN 0x4
+#define LPCR_A53_AD_EN_C0_PDN 0x2
+#define LPCR_A53_AD_EN_C0_WFI_PDN 0x1
+
+#define A53_LPM_WAIT 0x5
+#define A53_LPM_STOP 0xa
+
+#define SLPCR_EN_DSM 0x80000000
+#define SLPCR_RBC_EN 0x40000000
+#define SLPCR_VSTBY 0x4
+#define SLPCR_SBYOS 0x2
+#define SLPCR_BYPASS_PMIC_READY 0x1
+#define SLPCR_A53_FASTWUP_STOP (1 << 17)
+#define SLPCR_A53_FASTWUP_WAIT (1 << 16)
+
+#define GPC_CPU_PGC_SW_PUP_REQ 0xf0
+#define GPC_CPU_PGC_SW_PDN_REQ 0xf4
+#define BM_CPU_PGC_SW_PDN_PUP_REQ 0x1
+
+#define GPC_ARM_PGC 0x800
+#define PGC_PCR 0
+
+static uint32_t gpc_saved_imrs[128];
+static uint32_t gpc_wake_irqs[128];
+//static uint32_t gpc_mf_irqs[128];
+
+void imx_gpc_set_m_core_pgc(unsigned int cpu, bool pdn)
+{
+ uintptr_t val;
+
+ val = mmio_read_32(IMX_GPC_BASE + GPC_ARM_PGC + cpu * 64);
+ val &= ~(0x1 << PGC_PCR);
+
+ if(pdn)
+ val |= 0x1 << PGC_PCR;
+ mmio_write_32(IMX_GPC_BASE + GPC_ARM_PGC + cpu * 64, val);
+}
+
+void imx_gpc_set_lpm_mode(enum imx_cpu_pwr_mode mode)
+{
+ uint32_t val1, val2, val3, val4;
+
+ val1 = mmio_read_32(IMX_GPC_BASE + GPC_LPCR_A53_BSC);
+ val2 = mmio_read_32(IMX_GPC_BASE + GPC_LPCR_A53_BSC2);
+ val3 = mmio_read_32(IMX_GPC_BASE + GPC_SLPCR);
+ val4 = mmio_read_32(IMX_GPC_BASE + GPC_LPCR_A53_AD);
+
+ /* all core's LPM setting must be same */
+ val1 &= ~(LPCR_A53_BSC_LPM0 | LPCR_A53_BSC_LPM1);
+ val2 &= ~(LPCR_A53_BSC2_LPM2 | LPCR_A53_BSC2_LPM3);
+ val3 &= ~(SLPCR_EN_DSM | SLPCR_RBC_EN | SLPCR_VSTBY |
+ SLPCR_SBYOS | SLPCR_BYPASS_PMIC_READY);
+ val4 |= (1 << 5);
+
+ switch(mode) {
+ case WAIT_CLOCKED:
+ break;
+ case WAIT_UNCLOCKED:
+ val1 |= A53_LPM_WAIT;
+ val2 |= A53_LPM_WAIT;
+ val1 &= ~LPCR_A53_BSC_CPU_CLK_ON_LPM;
+ break;
+ case STOP_POWER_ON:
+ val1 |= A53_LPM_STOP;
+ val2 |= A53_LPM_STOP;
+ val1 &= ~LPCR_A53_BSC_CPU_CLK_ON_LPM;
+ val3 |= SLPCR_EN_DSM;
+ val3 |= SLPCR_RBC_EN;
+ val3 |= SLPCR_BYPASS_PMIC_READY;
+ break;
+ case STOP_POWER_OFF:
+ val1 |= A53_LPM_STOP;
+ val2 |= A53_LPM_STOP;
+ val1 &= ~LPCR_A53_BSC_CPU_CLK_ON_LPM;
+ val3 |= SLPCR_EN_DSM;
+ val3 |= SLPCR_A53_FASTWUP_STOP;
+ val3 |= SLPCR_RBC_EN;
+ val3 |= SLPCR_VSTBY;
+ val3 |= SLPCR_SBYOS;
+ val3 |= SLPCR_BYPASS_PMIC_READY;
+ val4 &= ~(1 << 5);
+ break;
+ default:
+ break;
+ }
+
+ mmio_write_32(IMX_GPC_BASE + GPC_LPCR_A53_BSC, val1);
+ mmio_write_32(IMX_GPC_BASE + GPC_LPCR_A53_BSC2, val2);
+ mmio_write_32(IMX_GPC_BASE + GPC_LPCR_A53_AD, val4);
+ mmio_write_32(IMX_GPC_BASE + GPC_SLPCR, val3);
+}
+
+/* enable CORE LPM PDN/WUP in AD register */
+void imx_gpc_set_cpu_power_gate_by_lpm(unsigned int cpu, bool pdn)
+{
+ uint32_t mask, val;
+
+ val = mmio_read_32(IMX_GPC_BASE + GPC_LPCR_A53_AD);
+
+ switch(cpu) {
+ case 0:
+ mask = LPCR_A53_AD_EN_C0_PDN | LPCR_A53_AD_EN_C0_PUP;
+ break;
+ case 1:
+ mask = LPCR_A53_AD_EN_C1_PDN | LPCR_A53_AD_EN_C1_PUP;
+ break;
+ case 2:
+ mask = LPCR_A53_AD_EN_C2_PDN | LPCR_A53_AD_EN_C3_PUP;
+ break;
+ case 3:
+ mask = LPCR_A53_AD_EN_C3_PDN | LPCR_A53_AD_EN_C3_PUP;
+ break;
+ default:
+ return;
+ }
+
+ if (pdn)
+ val |= mask;
+ else
+ val &= ~mask;
+
+ mmio_write_32(IMX_GPC_BASE + GPC_LPCR_A53_AD, val);
+}
+
+/* enable PLAT/SCU power down in AD register */
+void imx_gpc_set_plat_power_gate_by_lpm(bool pdn)
+{
+ uint32_t val;
+
+ val = mmio_read_32(IMX_GPC_BASE + GPC_LPCR_A53_AD);
+ val &= ~(LPCR_A53_AD_EN_PLAT_PDN | LPCR_A53_AD_L2PGE);
+
+ if (pdn)
+ val |= LPCR_A53_AD_EN_PLAT_PDN | LPCR_A53_AD_L2PGE;
+
+ mmio_write_32(IMX_GPC_BASE + GPC_LPCR_A53_AD, val);
+}
+
+void imx_gpc_set_slot_ack(uint32_t index, enum imx_gpc_slot m_core,
+ bool mode, bool ack)
+{
+ uint32_t val, shift;
+
+ if (index > 10) {
+ tf_printf("Invalid slot index\n");
+ return;
+ }
+ /* set slot */
+ val = mmio_read_32(IMX_GPC_BASE + GPC_SLOT0_CFG + index * 4);
+ val |= (mode + 1) << m_core * 2;
+ mmio_write_32(IMX_GPC_BASE + GPC_SLOT0_CFG + index * 4, val);
+ /* set ack */
+ if (ack) {
+ shift = m_core >= A53_SCU ? 2 : 0;
+ val = mmio_read_32(IMX_GPC_BASE + GPC_PGC_ACK_SEL_A53);
+ /* clear dummy ack */
+ val &= ~(1 << (15 + (mode ? 16: 0)));
+ val |= 1 << (shift + (mode ? 16 : 0));
+ mmio_write_32(IMX_GPC_BASE + GPC_PGC_ACK_SEL_A53, val);
+ }
+}
+
+/* cpu: cpu index */
+void imx_gpc_set_core_pdn_pup_by_software(unsigned int cpu, bool pdn)
+{
+ uint32_t val, index;
+
+ val = mmio_read_32(IMX_GPC_BASE + (pdn ?
+ GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ));
+
+ /*Set the core PCR bit before sw PUP/PDN trigger */
+ imx_gpc_set_m_core_pgc(cpu, true);
+
+ index = cpu < 2 ? cpu : cpu + 1;
+ val |= (BM_CPU_PGC_SW_PDN_PUP_REQ << index);
+ mmio_write_32(IMX_GPC_BASE + (pdn ?
+ GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ), val);
+
+ while((mmio_read_32(IMX_GPC_BASE + (pdn ?
+ GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ)) &
+ BM_CPU_PGC_SW_PDN_PUP_REQ) != 0)
+ ;
+
+ /*Clear the core PCR bit after sw PUP/PDN trigger */
+ imx_gpc_set_m_core_pgc(cpu, false);
+}
+
+void imx_gpc_pre_suspend(bool arm_power_off)
+{
+ unsigned int i;
+
+ /* set the LPM mode */
+ if (arm_power_off) {
+ /* enable core 0/1/2/3 power down/up with low power mode */
+ /* enable plat power down/up with low power mode */
+
+ /*
+ * to avoid confuse, we use slot 0~4 for power down.
+ * slot 5~9 for power up.
+ * power down slot sequence:
+ * slot 0 -> CORE0,
+ * SLOT 1 -> Mega/Fast mix,
+ * SLOT 2 -> SCU
+ *
+ * SLOT 5 -> Mega/Fast mix,
+ * SLOT 6 -> SCU
+ * SLOT 7 -> CORE0
+ */
+ /* SCU slot ack as the power down ack */
+ /* CORE0 slot ack as the power up ack */
+ imx_gpc_set_lpm_mode(STOP_POWER_OFF);
+ imx_gpc_set_slot_ack(0, A53_CORE0, false, false);
+ imx_gpc_set_slot_ack(2, A53_SCU, false, true);
+
+ imx_gpc_set_slot_ack(6, A53_SCU, true, false);
+ imx_gpc_set_slot_ack(7, A53_CORE0, true, true);
+ imx_gpc_set_m_core_pgc(0, true);
+ imx_gpc_set_m_core_pgc(4, true);
+
+ imx_gpc_set_cpu_power_gate_by_lpm(0, true);
+ imx_gpc_set_plat_power_gate_by_lpm(true);
+ } else {
+ imx_gpc_set_lpm_mode(STOP_POWER_ON);
+ }
+
+ for (i = 0; i < 4; i++) {
+ gpc_saved_imrs[i] = mmio_read_32(IMX_GPC_BASE + GPC_IMR1_CORE0_A53 + i * 4);
+ mmio_write_32(IMX_GPC_BASE + GPC_IMR1_CORE0_A53 + i * 4, ~gpc_wake_irqs[i]);
+ }
+
+}
+
+void imx_gpc_post_resume(void)
+{
+ int i;
+ /* set LPM mode WAIT CLOCKED */
+ imx_gpc_set_lpm_mode(WAIT_CLOCKED);
+ /* clear lpm power gate of core and plat */
+ imx_gpc_set_cpu_power_gate_by_lpm(0, false);
+ imx_gpc_set_plat_power_gate_by_lpm(false);
+ /* clear PGC PDN bit */
+ imx_gpc_set_m_core_pgc(0, false);
+ imx_gpc_set_m_core_pgc(4, false);
+
+ for (i = 0; i < 4; i++) {
+ mmio_write_32(IMX_GPC_BASE + GPC_IMR1_CORE0_A53 + i * 4, gpc_saved_imrs[i]);
+ }
+
+ /* skip slot m4 use , clear slots */
+ for(i = 0; i < 10; i ++) {
+ if (i == 1 || i == 5)
+ continue;
+ mmio_write_32(IMX_GPC_BASE +GPC_SLOT0_CFG + i * 0x4, 0x0);
+ }
+ /* set DUMMY PDN/PUP ACK by default for A53 domain */
+ mmio_write_32(IMX_GPC_BASE + GPC_PGC_ACK_SEL_A53, 1 << 31 | 1 << 15);
+}
+
+static void imx_gpc_hwirq_mask(unsigned int hwirq)
+{
+ uintptr_t reg;
+ unsigned int val;
+
+ reg = IMX_GPC_BASE + GPC_IMR1_CORE0_A53 + (hwirq / 32) * 4;
+ val = mmio_read_32(reg);
+ val |= 1 << hwirq % 32;
+ mmio_write_32(reg, val);
+}
+
+static void imx_gpc_hwirq_unmask(unsigned int hwirq)
+{
+ uintptr_t reg;
+ unsigned int val;
+
+ reg = IMX_GPC_BASE + GPC_IMR1_CORE0_A53 + (hwirq / 32) * 4;
+ val = mmio_read_32(reg);
+ val &= ~(1 << hwirq % 32);
+ mmio_write_32(reg, val);
+}
+
+static void imx_gpc_set_wake(uint32_t hwirq, unsigned int on)
+{
+ uint32_t mask, idx;
+
+ mask = 1 << hwirq % 32;
+ idx = hwirq / 32;
+ gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
+ gpc_wake_irqs[idx] & ~mask;
+}
+
+static void imx_gpc_pm_domain_enable(uint32_t domain_id, uint32_t on)
+{
+ uint32_t val;
+ uintptr_t reg;
+
+ reg = IMX_GPC_BASE + (on ? 0xf8 : 0x104);
+ val = 1 << domain_id;
+ mmio_write_32(reg, val);
+ while(mmio_read_32(reg) & val)
+ ;
+}
+
+void imx_gpc_init(void)
+{
+ unsigned int val;
+ int i;
+ /* mask all the interrupt by default */
+ for (i = 0; i < 4; i ++) {
+ mmio_write_32(IMX_GPC_BASE + GPC_IMR1_CORE0_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + GPC_IMR1_CORE1_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + GPC_IMR1_CORE2_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + GPC_IMR1_CORE3_A53 + i * 4, ~0x0);
+ }
+
+ /* Due to the hardware design requirement, need to make
+ * sure GPR interrupt(#32) is unmasked during RUN mode to
+ * avoid entering DSM mode by mistake.
+ */
+ mmio_write_32(IMX_GPC_BASE + GPC_IMR1_CORE0_A53, ~0x1);
+
+ /* use external IRQs to wakeup C0~C3 from LPM */
+ val = mmio_read_32(IMX_GPC_BASE + GPC_LPCR_A53_BSC);
+ val |= 0x70c00000;
+ /* clear the MASTER0 LPM handshake */
+ val &= ~(1 << 6);
+ mmio_write_32(IMX_GPC_BASE + GPC_LPCR_A53_BSC, val);
+
+ /* mask M4 DSM trigger if M4 is NOT enabled */
+ val = mmio_read_32(IMX_GPC_BASE + GPC_LPCR_M4);
+ val |= 1 << 31;
+ mmio_write_32(IMX_GPC_BASE + GPC_LPCR_M4, val);
+
+ /* set mega/fast mix in A53 domain */
+ mmio_write_32(IMX_GPC_BASE + GPC_PGC_CPU_0_1_MAPPING, 0x1);
+
+ /* set SCU timming */
+ mmio_write_32(IMX_GPC_BASE + GPC_PGC_SCU_TIMMING,
+ (0x59 << 10) | 0x5B | (0x2 << 20));
+
+ /* set A53 core power up timming */
+ mmio_write_32(IMX_GPC_BASE + GPC_PGC_CORE0_TIMMING, 0x1a << 7);
+ mmio_write_32(IMX_GPC_BASE + GPC_PGC_CORE1_TIMMING, 0x1a << 7);
+ mmio_write_32(IMX_GPC_BASE + GPC_PGC_CORE2_TIMMING, 0x1a << 7);
+ mmio_write_32(IMX_GPC_BASE + GPC_PGC_CORE3_TIMMING, 0x1a << 7);
+
+ /* set DUMMY PDN/PUP ACK by default for A53 domain */
+ mmio_write_32(IMX_GPC_BASE + GPC_PGC_ACK_SEL_A53, 1 << 31 | 1 << 15);
+ /* clear DSM by default */
+ val = mmio_read_32(IMX_GPC_BASE + GPC_SLPCR);
+ val &= ~(1 << 31);
+ /* TODO if M4 is not enabled, clear more SLPCR bits */
+ mmio_write_32(IMX_GPC_BASE + GPC_SLPCR, val);
+}
+
+int imx_gpc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3)
+{
+ switch(x1) {
+ case FSL_SIP_CONFIG_GPC_SET_WAKE:
+ imx_gpc_set_wake(x2, x3);
+ break;
+ case FSL_SIP_CONFIG_GPC_MASK:
+ imx_gpc_hwirq_mask(x2);
+ break;
+ case FSL_SIP_CONFIG_GPC_UNMASK:
+ imx_gpc_hwirq_unmask(x2);
+ break;
+ case FSL_SIP_CONFIG_GPC_PM_DOMAIN:
+ imx_gpc_pm_domain_enable(x2, x3);
+ break;
+ default:
+ return SMC_UNK;
+ }
+
+ return 0;
+}
diff --git a/plat/freescale/imx8mq/imx8m_bl31_setup.c b/plat/freescale/imx8mq/imx8m_bl31_setup.c
new file mode 100644
index 00000000..9bc2fbbc
--- /dev/null
+++ b/plat/freescale/imx8mq/imx8m_bl31_setup.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright 2017 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <context.h>
+#include <context_mgmt.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <plat_imx8.h>
+#include <xlat_tables.h>
+#include <soc.h>
+
+/* linker defined symbols */
+extern unsigned long __RO_START__;
+extern unsigned long __RO_END__;
+extern unsigned long __BL31_END__;
+
+#if USE_COHERENT_MEM
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+
+#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+#endif
+
+#define BL31_RO_BASE (unsigned long)(&__RO_START__)
+#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
+#define BL31_END (unsigned long)(&__BL31_END__)
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* get SPSR for BL33 entry */
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned long mode;
+ uint32_t spsr;
+
+ /* figure out what mode we enter the non-secure world */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
+#define SCTR_BASE_ADDR 0x306c0000
+#define CNTFID0_OFF 0x20
+#define CNTFID1_OFF 0x24
+
+#define SC_CNTCR_ENABLE (1 << 0)
+#define SC_CNTCR_HDBG (1 << 1)
+#define SC_CNTCR_FREQ0 (1 << 8)
+#define SC_CNTCR_FREQ1 (1 << 9)
+
+unsigned int freq;
+
+void system_counter_init(void)
+{
+ int val;
+
+ /* Update with accurate clock frequency */
+ freq = mmio_read_32(SCTR_BASE_ADDR + CNTFID0_OFF);
+
+ val = mmio_read_32(SCTR_BASE_ADDR + CNTCR_OFF);
+ val &= ~(SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1);
+ val |= SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG;
+ mmio_write_32(SCTR_BASE_ADDR + CNTCR_OFF, val);
+}
+
+void bl31_early_platform_setup(bl31_params_t *from_bl2,
+ void *plat_params_from_bl2)
+{
+ int i;
+ /* enable CSU NS access permission */
+ for (i = 0; i < 64; i++) {
+ mmio_write_32(0x303e0000 + i * 4, 0xffffffff);
+ }
+
+ mmio_write_32(0x303a00ec, 0x0000ffff);
+ /* Power up VPU, DISP, GPU etc */
+ mmio_write_32(0x303a00f8, 0x3fef);
+
+ /* config the AIPSTZ1 */
+ mmio_write_32(0x301f0000, 0x77777777);
+ mmio_write_32(0x301f0004, 0x77777777);
+ mmio_write_32(0x301f0040, 0x0);
+ mmio_write_32(0x301f0044, 0x0);
+ mmio_write_32(0x301f0048, 0x0);
+ mmio_write_32(0x301f004c, 0x0);
+ mmio_write_32(0x301f0050, 0x0);
+
+ /* config the AIPSTZ3 */
+ mmio_write_32(0x309f0000, 0x77777777);
+ mmio_write_32(0x309f0004, 0x77777777);
+ mmio_write_32(0x309f0040, 0x0);
+ mmio_write_32(0x309f0044, 0x0);
+ mmio_write_32(0x309f0048, 0x0);
+ mmio_write_32(0x309f004c, 0x0);
+ mmio_write_32(0x309f0050, 0x0);
+
+ /* enable the system counter */
+ system_counter_init();
+
+ /*
+ * tell BL3-1 where the non-secure software image is located
+ * and the entry state information.
+ */
+ bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
+ bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+}
+
+void bl31_plat_arch_setup(void)
+{
+ /* add the mmap */
+ mmap_add_region(BL31_BASE, BL31_BASE, 0x10000,
+ MT_MEMORY | MT_RW);
+ mmap_add_region(BL31_BASE, BL31_BASE, BL31_RO_LIMIT - BL31_RO_BASE,
+ MT_MEMORY | MT_RO);
+ mmap_add_region(IMX_BOOT_UART_BASE, IMX_BOOT_UART_BASE,
+ 0x1000, MT_DEVICE | MT_RW);
+ mmap_add_region(IMX_SRC_BASE, IMX_SRC_BASE,
+ 0x1000, MT_DEVICE | MT_RW);
+ mmap_add_region(IMX_GPC_BASE, IMX_GPC_BASE, 0x1000, MT_DEVICE | MT_RW);
+ mmap_add_region(IMX_ANAMIX_BASE, IMX_ANAMIX_BASE, 0x1000, MT_DEVICE | MT_RW);
+ mmap_add_region(PLAT_GICD_BASE, PLAT_GICD_BASE, 0x80000,
+ MT_DEVICE | MT_RW);
+ mmap_add_region(PLAT_GICR_BASE, PLAT_GICR_BASE, 0x80000,
+ MT_DEVICE | MT_RW);
+#if USE_COHERENT_MEM
+ mmap_add_region(BL31_COHERENT_RAM_BASE, BL31_COHERENT_RAM_BASE,
+ BL31_COHERENT_RAM_LIMIT - BL31_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW);
+#endif
+
+ /* setup xlat table */
+ init_xlat_tables();
+
+ /* enable the MMU */
+ enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+ /* init the GICv3 cpu and distributor interface */
+ plat_gic_driver_init();
+ plat_gic_init();
+
+ /* gpc init */
+ imx_gpc_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+{
+ if (type == NON_SECURE)
+ return &bl33_image_ep_info;
+ if (type == SECURE)
+ return &bl32_image_ep_info;
+
+ return NULL;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return freq;
+}
diff --git a/plat/freescale/imx8mq/imx8m_psci.c b/plat/freescale/imx8mq/imx8m_psci.c
new file mode 100644
index 00000000..f53c81eb
--- /dev/null
+++ b/plat/freescale/imx8mq/imx8m_psci.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright 2017 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <debug.h>
+#include <plat_imx8.h>
+#include <psci.h>
+#include <mmio.h>
+#include <soc.h>
+
+#define SCR_A53RCR1_OFFSET 0x08
+#define SRC_GPR1_OFFSET 0x74
+#define ARM_PGC 0x800
+#define PGC_PCR 1
+#define GPC_CPU_PGC_SW_PUP_REQ 0xf0
+#define GPC_CPU_PGC_SW_PDN_REQ 0xfc
+
+extern void imx_gpc_set_core_pdn_pup_by_software(unsigned int cpu, bool pdn);
+extern void imx_gpc_set_cpu_power_gate_by_wfi(unsigned int cpu, bool pdn);
+
+const unsigned char imx_power_domain_tree_desc[] = {
+ /* number of root nodes */
+ PWR_DOMAIN_AT_MAX_LVL,
+ /* number of child at the first node */
+ PLATFORM_CLUSTER_COUNT,
+ PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+void imx8m_kill_cpu(unsigned int target_idx)
+{
+ unsigned int val1;
+
+ /* Disable the secondary core */
+ val1 = mmio_read_32(IMX_SRC_BASE + SCR_A53RCR1_OFFSET);
+ val1 &= ~(1 << target_idx);
+ mmio_write_32(IMX_SRC_BASE + SCR_A53RCR1_OFFSET, val1);
+
+ imx_gpc_set_core_pdn_pup_by_software(target_idx, true);
+}
+
+int imx_pwr_domain_on(u_register_t mpidr)
+{
+ int ret = PSCI_E_SUCCESS;
+ unsigned int cpu_id, reg;
+
+ uint64_t base_addr = BL31_BASE;
+
+ tf_printf("cpu on\n");
+ cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ /* core power up sequence
+ * 1. Assert nCPUPORESET
+ * 2. power the core.
+ * 3. Deassert reset.
+ */
+ reg = mmio_read_32(IMX_SRC_BASE + SCR_A53RCR1_OFFSET);
+ reg &= ~(1 << cpu_id);
+ mmio_write_32(IMX_SRC_BASE + SCR_A53RCR1_OFFSET, reg);
+
+ /* Set CPU jump address */
+ if (cpu_id > 0) {
+ base_addr >>= 2;
+ mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (cpu_id << 3),
+ ((uint32_t)(base_addr >> 22) & 0xFFFF));
+ mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (cpu_id << 3) + 4,
+ ((uint32_t)base_addr & 0x003FFFFF));
+ }
+
+ imx_gpc_set_core_pdn_pup_by_software(cpu_id, false);
+
+ /* Kick CPU here */
+ reg = mmio_read_32(IMX_SRC_BASE + SCR_A53RCR1_OFFSET);
+ reg |= (1 << cpu_id);
+ mmio_write_32(IMX_SRC_BASE + SCR_A53RCR1_OFFSET, reg);
+
+ return ret;
+}
+
+void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ /* program the GIC per cpu dist and rdist interface */
+ plat_gic_pcpu_init();
+ /* enable the GICv3 cpu interface */
+ plat_gic_cpuif_enable();
+}
+
+void imx_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ plat_gic_cpuif_disable();
+}
+
+int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
+{
+ /* TODO */
+ return PSCI_E_SUCCESS;
+}
+
+int imx_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ /* Sanity check the requested afflvl */
+ if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) {
+ if (pwr_lvl != MPIDR_AFFLVL0)
+ return PSCI_E_INVALID_PARAMS;
+ /* power domain in standby state */
+ req_state->pwr_domain_state[pwr_lvl] = PLAT_MAX_RET_STATE;
+
+ return PSCI_E_SUCCESS;
+ }
+
+ return 0;
+}
+
+void imx_cpu_standby(plat_local_state_t cpu_state)
+{
+ dsb();
+ write_icc_igrpen1_el1(1);
+ write_scr_el3(read_scr_el3() | 0x4);
+ isb();
+
+ wfi();
+
+ write_icc_igrpen1_el1(0);
+ write_scr_el3(read_scr_el3() & (~0x4));
+ isb();
+}
+
+void imx_domain_suspend(const psci_power_state_t *target_state)
+{
+ uint64_t base_addr = BL31_BASE;
+ plat_gic_cpuif_disable();
+
+ /* imx gpc pre suspend */
+ imx_gpc_pre_suspend(true);
+
+ base_addr >>= 2;
+ mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET ,
+ ((uint32_t)(base_addr >> 22) & 0xFFFF));
+ mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + 4,
+ ((uint32_t)base_addr & 0x003FFFFF));
+
+}
+
+void imx_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ /* imx gpc post resume */
+ imx_gpc_post_resume();
+ /* enable the GICv3 cpu interface */
+ plat_gic_cpuif_enable();
+}
+
+void imx_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int i;
+
+ for (i = IMX_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE;
+}
+
+static const plat_psci_ops_t imx_plat_psci_ops = {
+ .pwr_domain_on = imx_pwr_domain_on,
+ .pwr_domain_on_finish = imx_pwr_domain_on_finish,
+ .pwr_domain_off = imx_pwr_domain_off,
+ .validate_ns_entrypoint = imx_validate_ns_entrypoint,
+ .validate_power_state = imx_validate_power_state,
+ .cpu_standby = imx_cpu_standby,
+ .pwr_domain_suspend = imx_domain_suspend,
+ .pwr_domain_suspend_finish = imx_domain_suspend_finish,
+ .get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+};
+
+/* export the platform specific psci ops */
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ imx_mailbox_init(sec_entrypoint);
+ /* sec_entrypoint is used for warm reset */
+ *psci_ops = &imx_plat_psci_ops;
+
+ return 0;
+}
diff --git a/plat/freescale/imx8mq/include/fsl_sip.h b/plat/freescale/imx8mq/include/fsl_sip.h
new file mode 100644
index 00000000..73fa08d4
--- /dev/null
+++ b/plat/freescale/imx8mq/include/fsl_sip.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2017 NXP
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SOC_FSL_SIP_H
+#define __SOC_FSL_SIP_H
+
+#define FSL_SIP_GPC 0xC2000000
+#define FSL_SIP_CONFIG_GPC_MASK 0x00
+#define FSL_SIP_CONFIG_GPC_UNMASK 0x01
+#define FSL_SIP_CONFIG_GPC_SET_WAKE 0x02
+#define FSL_SIP_CONFIG_GPC_PM_DOMAIN 0x03
+
+#endif
diff --git a/plat/freescale/imx8mq/include/platform_def.h b/plat/freescale/imx8mq/include/platform_def.h
new file mode 100644
index 00000000..8d5dffb7
--- /dev/null
+++ b/plat/freescale/imx8mq/include/platform_def.h
@@ -0,0 +1,52 @@
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define PLATFORM_STACK_SIZE 0X400
+#define CACHE_WRITEBACK_GRANULE 64
+
+#define PLAT_PRIMARY_CPU 0x0
+#define PLATFORM_MAX_CPU_PER_CLUSTER 4
+#define PLATFORM_CLUSTER_COUNT 1
+#define PLATFORM_CLUSTER0_CORE_COUNT 4
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define IMX_PWR_LVL0 MPIDR_AFFLVL0
+#define IMX_PWR_LVL1 MPIDR_AFFLVL1
+#define IMX_PWR_LVL2 MPIDR_AFFLVL2
+
+#define PWR_DOMAIN_AT_MAX_LVL 1
+#define PLAT_MAX_PWR_LVL 2
+#define PLAT_MAX_OFF_STATE 2
+#define PLAT_MAX_RET_STATE 1
+
+#define BL31_BASE 0x40001000
+#define BL31_LIMIT 0x40021000
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET 0x40021000
+
+/* GICv3 base address */
+#define PLAT_GICD_BASE 0x38800000
+#define PLAT_GICR_BASE 0x38880000
+
+#define PLAT_FSL_ADDR_SPACE_SIZE (1ull << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
+
+#define MAX_XLAT_TABLES 4
+#define MAX_MMAP_REGIONS 16
+
+#define IMX_BOOT_UART_BASE 0x30860000
+#define IMX_BOOT_UART_CLK_IN_HZ 25000000 /* Select 25Mhz oscillator */
+#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE
+#define PLAT__CRASH_UART_CLK_IN_HZ 25000000
+#define IMX_CONSOLE_BAUDRATE 115200
+
+#define IMX_ANAMIX_BASE 0x30360000
+#define IMX_SRC_BASE 0x30390000
+#define IMX_GPC_BASE 0x303a0000
+
+#define COUNTER_FREQUENCY 8000000 /* 8MHz */
+
+#define DEBUG_CONSOLE 0
+#define PLAT_IMX8M 1
diff --git a/plat/freescale/imx8mq/include/soc.h b/plat/freescale/imx8mq/include/soc.h
new file mode 100644
index 00000000..ebce7ea8
--- /dev/null
+++ b/plat/freescale/imx8mq/include/soc.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2017 NXP
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __IMX_SOC_H
+#define __IMX_SOC_H
+
+enum imx_cpu_pwr_mode {
+ WAIT_CLOCKED, /* wfi only */
+ WAIT_UNCLOCKED, /* WAIT */
+ WAIT_UNCLOCKED_POWER_OFF, /* WAIT + SRPG */
+ STOP_POWER_ON, /* just STOP */
+ STOP_POWER_OFF, /* STOP + SRPG */
+};
+
+enum imx_gpc_slot {
+ A53_CORE0,
+ A53_CORE1,
+ A53_CORE2,
+ A53_CORE3,
+ A53_SCU,
+};
+
+enum imx_gpc_pu_slot {
+ FAST_MEGA_MIX,
+ MIPI_PHY,
+ PCIE1_PHY,
+ OTG1_PHY,
+ OTG2_PHY,
+ RESERVED,
+ CORE1_M4,
+ DDR1_PHY,
+ DDR2_PHY,
+ GPU,
+ VPU,
+ HDMI_PHY,
+ DSIP,
+ MIPI_CSI1,
+ MIPI_CSI2,
+ PCIE2_PHY,
+};
+
+void imx_gpc_set_m_core_pgc(unsigned int cpu, bool pdn);
+void imx_gpc_set_lpm_mode(enum imx_cpu_pwr_mode mode);
+void imx_gpc_set_cpu_power_gate_by_lpm(unsigned int cpu, bool pdn);
+void imx_gpc_set_plat_power_gate_by_lpm(bool pdn);
+void imx_gpc_set_core_pdn_pup_by_software(unsigned int cpu, bool pdn);
+void imx_gpc_set_cpu_ppower_gate_by_wfi(unsigned int cpu, bool pdn);
+void imx_gpc_pre_suspend(bool arm_power_off);
+void imx_gpc_post_resume(void);
+void imx_gpc_init(void);
+
+
+void imx_enable_cpu(unsigned int cpu, bool enable);
+int imx_is_m4_enabled(void);
+void imx_set_cpu_jump_addr(unsigned int cpu, void *jump_addr);
+#endif /* __IMX_SOC_H */
diff --git a/plat/freescale/imx8mq/platform.mk b/plat/freescale/imx8mq/platform.mk
new file mode 100644
index 00000000..ec51a899
--- /dev/null
+++ b/plat/freescale/imx8mq/platform.mk
@@ -0,0 +1,27 @@
+PLAT_INCLUDES := -Iplat/freescale/imx8mq/include \
+ -Iplat/freescale/common/include \
+
+PLAT_GIC_SOURCES := drivers/arm/gic/v3/gicv3_helpers.c \
+ drivers/arm/gic/v3/gicv3_main.c \
+ drivers/arm/gic/common/gic_common.c \
+ plat/common/plat_gicv3.c \
+ plat/freescale/common/plat_imx8_gic.c
+
+BL31_SOURCES += plat/freescale/common/imx8_helpers.S \
+ plat/freescale/common/mxcuart_console.S \
+ plat/freescale/imx8mq/imx8m_bl31_setup.c \
+ plat/freescale/imx8mq/gpc.c \
+ plat/freescale/imx8mq/imx8m_psci.c \
+ plat/freescale/imx8mq/sip_svc.c \
+ plat/freescale/common/imx8_topology.c \
+ plat/common/plat_psci_common.c \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ drivers/console/aarch64/console.S \
+ ${PLAT_GIC_SOURCES} \
+
+ENABLE_PLAT_COMPAT := 0
+USE_COHERENT_MEM := 0
+RESET_TO_BL31 := 1
+ERROR_DEPRECATED := 1
diff --git a/plat/freescale/imx8mq/sip_svc.c b/plat/freescale/imx8mq/sip_svc.c
new file mode 100644
index 00000000..0bf9cd3e
--- /dev/null
+++ b/plat/freescale/imx8mq/sip_svc.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright 2017 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <debug.h>
+#include <fsl_sip.h>
+#include <runtime_svc.h>
+#include <smcc_helpers.h>
+#include <std_svc.h>
+#include <stdint.h>
+#include <uuid.h>
+
+extern int imx_gpc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, u_register_t x3);
+
+/* Setup i.MX platform specific services Services */
+static int32_t plat_svc_setup(void)
+{
+ /* gpc init ?*/
+ NOTICE("sip svc init\n");
+ return 0;
+}
+
+/* i.MX platform specific service SMC handler */
+uintptr_t imx_svc_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ uint64_t flags)
+{
+ NOTICE("smc_fid is %x\n", smc_fid);
+ switch (smc_fid) {
+ case FSL_SIP_GPC:
+ SMC_RET1(handle, imx_gpc_handler(smc_fid, x1, x2, x3));
+ break;
+ default:
+ WARN("Uimplemented SIP Service Call: 0x%x \n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ break;
+ }
+}
+
+/* Rigister SIP Service Calls as runtime service */
+DECLARE_RT_SVC(
+ imx_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ plat_svc_setup,
+ imx_svc_smc_handler
+);