Merge pull request #1653 from JackyBai/master

Add NXP i.MX8MQ basic support 
diff --git a/docs/plat/imx8m.rst b/docs/plat/imx8m.rst
new file mode 100644
index 0000000..ab33a8a
--- /dev/null
+++ b/docs/plat/imx8m.rst
@@ -0,0 +1,42 @@
+Description
+===========
+
+The i.MX 8M family of applications processors based on Arm Corte-A53 and Cortex-M4
+cores provide high-performance computing, power efficiency, enhanced system
+reliability and embedded security needed to drive the growth of fast-growing
+edge node computing, streaming multimedia, and machine learning applications.
+
+Boot Sequence
+=============
+
+Bootrom --> SPL --> BL31 --> BL33(u-boot) --> Linux kernel
+
+How to build
+============
+
+Build Procedure
+---------------
+
+-  Prepare AARCH64 toolchain.
+
+-  Build spl and u-boot firstly, and get binary images: u-boot-spl.bin,
+   u-boot-nodtb.bin and dtb for the target board.
+
+-  Build TF-A
+
+   Build bl31:
+
+   .. code:: shell
+
+       CROSS_COMPILE=aarch64-linux-gnu- make PLAT=<Target_SoC> bl31
+
+   Target_SoC should be "imx8mq" for i.MX8MQ SoC.
+
+Deploy TF-A Images
+-----------------
+
+TF-A binary(bl31.bin), u-boot-spl.bin u-boot-nodtb.bin and dtb are combined
+together to generate a binary file called flash.bin, the imx-mkimage tool is
+used to generate flash.bin, and flash.bin needs to be flashed into SD card
+with certain offset for BOOT ROM. the u-boot and imx-mkimage will be upstreamed
+soon, this doc will be updated once they are ready, and the link will be posted.
diff --git a/drivers/arm/tzc/tzc380.c b/drivers/arm/tzc/tzc380.c
new file mode 100644
index 0000000..b30a5e6
--- /dev/null
+++ b/drivers/arm/tzc/tzc380.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <mmio.h>
+#include <stddef.h>
+#include <tzc380.h>
+
+struct tzc380_instance {
+	uintptr_t base;
+	uint8_t addr_width;
+	uint8_t num_regions;
+};
+
+struct tzc380_instance tzc380;
+
+static unsigned int tzc380_read_build_config(uintptr_t base)
+{
+	return mmio_read_32(base + TZC380_CONFIGURATION_OFF);
+}
+
+static void tzc380_write_action(uintptr_t base, tzc_action_t action)
+{
+	mmio_write_32(base + ACTION_OFF, action);
+}
+
+static void tzc380_write_region_base_low(uintptr_t base, unsigned int region,
+				      unsigned int val)
+{
+	mmio_write_32(base + REGION_SETUP_LOW_OFF(region), val);
+}
+
+static void tzc380_write_region_base_high(uintptr_t base, unsigned int region,
+				       unsigned int val)
+{
+	mmio_write_32(base + REGION_SETUP_HIGH_OFF(region), val);
+}
+
+static void tzc380_write_region_attributes(uintptr_t base, unsigned int region,
+					unsigned int val)
+{
+	mmio_write_32(base + REGION_ATTRIBUTES_OFF(region), val);
+}
+
+void tzc380_init(uintptr_t base)
+{
+	unsigned int tzc_build;
+
+	assert(base != NULL);
+	tzc380.base = base;
+
+	/* Save values we will use later. */
+	tzc_build = tzc380_read_build_config(tzc380.base);
+	tzc380.addr_width  = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
+			      BUILD_CONFIG_AW_MASK) + 1;
+	tzc380.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
+			       BUILD_CONFIG_NR_MASK) + 1;
+}
+
+static uint32_t addr_low(uintptr_t addr)
+{
+	return (uint32_t)addr;
+}
+
+static uint32_t addr_high(uintptr_t addr __unused)
+{
+#if (UINTPTR_MAX == UINT64_MAX)
+	return addr >> 32;
+#else
+	return 0;
+#endif
+}
+
+/*
+ * `tzc380_configure_region` is used to program regions into the TrustZone
+ * controller.
+ */
+void tzc380_configure_region(uint8_t region, uintptr_t region_base, unsigned int attr)
+{
+	assert(tzc380.base != NULL);
+
+	assert(region < tzc380.num_regions);
+
+	tzc380_write_region_base_low(tzc380.base, region, addr_low(region_base));
+	tzc380_write_region_base_high(tzc380.base, region, addr_high(region_base));
+	tzc380_write_region_attributes(tzc380.base, region, attr);
+}
+
+void tzc380_set_action(tzc_action_t action)
+{
+	assert(tzc380.base != NULL);
+
+	/*
+	 * - Currently no handler is provided to trap an error via interrupt
+	 *   or exception.
+	 * - The interrupt action has not been tested.
+	 */
+	tzc380_write_action(tzc380.base, action);
+}
diff --git a/include/drivers/arm/tzc380.h b/include/drivers/arm/tzc380.h
new file mode 100644
index 0000000..19cf988
--- /dev/null
+++ b/include/drivers/arm/tzc380.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TZC380_H
+#define TZC380_H
+
+#include <tzc_common.h>
+#include <utils_def.h>
+
+#define TZC380_CONFIGURATION_OFF	U(0x000)
+#define ACTION_OFF			U(0x004)
+#define LOCKDOWN_RANGE_OFF		U(0x008)
+#define LOCKDOWN_SELECT_OFF		U(0x00C)
+#define INT_STATUS			U(0x010)
+#define INT_CLEAR			U(0x014)
+
+#define FAIL_ADDRESS_LOW_OFF		U(0x020)
+#define FAIL_ADDRESS_HIGH_OFF		U(0x024)
+#define FAIL_CONTROL_OFF		U(0x028)
+#define FAIL_ID				U(0x02c)
+
+#define SPECULATION_CTRL_OFF		U(0x030)
+#define SECURITY_INV_EN_OFF		U(0x034)
+
+#define REGION_SETUP_LOW_OFF(n)		U(0x100 + (n) * 0x10)
+#define REGION_SETUP_HIGH_OFF(n)	U(0x104 + (n) * 0x10)
+#define REGION_ATTRIBUTES_OFF(n)	U(0x108 + (n) * 0x10)
+
+#define BUILD_CONFIG_AW_SHIFT		8
+#define BUILD_CONFIG_AW_MASK		U(0x3f)
+#define BUILD_CONFIG_NR_SHIFT		0
+#define BUILD_CONFIG_NR_MASK		U(0xf)
+
+#define ACTION_RV_SHIFT			0
+#define ACTION_RV_MASK			U(0x3)
+#define ACTION_RV_LOWOK			U(0x0)
+#define ACTION_RV_LOWERR		U(0x1)
+#define ACTION_RV_HIGHOK		U(0x2)
+#define ACTION_RV_HIGHERR		U(0x3)
+
+/* Speculation is enabled by default. */
+#define SPECULATION_CTRL_WRITE_DISABLE	BIT_32(1)
+#define SPECULATION_CTRL_READ_DISABLE	BIT_32(0)
+
+#define INT_STATUS_OVERRUN_SHIFT	1
+#define INT_STATUS_OVERRUN_MASK		U(0x1)
+#define INT_STATUS_STATUS_SHIFT		0
+#define INT_STATUS_STATUS_MASK		U(0x1)
+
+#define INT_CLEAR_CLEAR_SHIFT		0
+#define INT_CLEAR_CLEAR_MASK		U(0x1)
+
+#define TZC380_COMPONENT_ID		U(0xb105f00d)
+#define TZC380_PERIPH_ID_LOW		U(0x001bb380)
+#define TZC380_PERIPH_ID_HIGH		U(0x00000004)
+
+#define TZC_SP_NS_W			BIT_32(0)
+#define TZC_SP_NS_R			BIT_32(1)
+#define TZC_SP_S_W			BIT_32(2)
+#define TZC_SP_S_R			BIT_32(3)
+
+#define TZC_ATTR_SP_SHIFT		28
+#define TZC_ATTR_SP_ALL			((TZC_SP_S_W | TZC_SP_S_R | TZC_SP_NS_W | \
+					TZC_SP_NS_R) << TZC_ATTR_SP_SHIFT)
+#define TZC_ATTR_SP_S_RW		((TZC_SP_S_W | TZC_SP_S_R) << \
+					 TZC_ATTR_SP_SHIFT)
+#define TZC_ATTR_SP_NS_RW		((TZC_SP_NS_W | TZC_SP_NS_R) << \
+					TZC_ATTR_SP_SHIFT)
+
+#define TZC_REGION_SIZE_32K		U(0xe)
+#define TZC_REGION_SIZE_64K		U(0xf)
+#define TZC_REGION_SIZE_128K		U(0x10)
+#define TZC_REGION_SIZE_256K		U(0x11)
+#define TZC_REGION_SIZE_512K		U(0x12)
+#define TZC_REGION_SIZE_1M		U(0x13)
+#define TZC_REGION_SIZE_2M		U(0x14)
+#define TZC_REGION_SIZE_4M		U(0x15)
+#define TZC_REGION_SIZE_8M		U(0x16)
+#define TZC_REGION_SIZE_16M		U(0x17)
+#define TZC_REGION_SIZE_32M		U(0x18)
+#define TZC_REGION_SIZE_64M		U(0x19)
+#define TZC_REGION_SIZE_128M		U(0x1a)
+#define TZC_REGION_SIZE_256M		U(0x1b)
+#define TZC_REGION_SIZE_512M		U(0x1c)
+#define TZC_REGION_SIZE_1G		U(0x1d)
+#define TZC_REGION_SIZE_2G		U(0x1e)
+#define TZC_REGION_SIZE_4G		U(0x1f)
+#define TZC_REGION_SIZE_8G		U(0x20)
+#define TZC_REGION_SIZE_16G		U(0x21)
+#define TZC_REGION_SIZE_32G		U(0x22)
+#define TZC_REGION_SIZE_64G		U(0x23)
+#define TZC_REGION_SIZE_128G		U(0x24)
+#define TZC_REGION_SIZE_256G		U(0x25)
+#define TZC_REGION_SIZE_512G		U(0x26)
+#define TZC_REGION_SIZE_1T		U(0x27)
+#define TZC_REGION_SIZE_2T		U(0x28)
+#define TZC_REGION_SIZE_4T		U(0x29)
+#define TZC_REGION_SIZE_8T		U(0x2a)
+#define TZC_REGION_SIZE_16T		U(0x2b)
+#define TZC_REGION_SIZE_32T		U(0x2c)
+#define TZC_REGION_SIZE_64T		U(0x2d)
+#define TZC_REGION_SIZE_128T		U(0x2e)
+#define TZC_REGION_SIZE_256T		U(0x2f)
+#define TZC_REGION_SIZE_512T		U(0x30)
+#define TZC_REGION_SIZE_1P		U(0x31)
+#define TZC_REGION_SIZE_2P		U(0x32)
+#define TZC_REGION_SIZE_4P		U(0x33)
+#define TZC_REGION_SIZE_8P		U(0x34)
+#define TZC_REGION_SIZE_16P		U(0x35)
+#define TZC_REGION_SIZE_32P		U(0x36)
+#define TZC_REGION_SIZE_64P		U(0x37)
+#define TZC_REGION_SIZE_128P		U(0x38)
+#define TZC_REGION_SIZE_256P		U(0x39)
+#define TZC_REGION_SIZE_512P		U(0x3a)
+#define TZC_REGION_SIZE_1E		U(0x3b)
+#define TZC_REGION_SIZE_2E		U(0x3c)
+#define TZC_REGION_SIZE_4E		U(0x3d)
+#define TZC_REGION_SIZE_8E		U(0x3e)
+#define TZC_REGION_SIZE_16E		U(0x3f)
+
+#define TZC_REGION_SIZE_SHIFT		0x1
+#define TZC_REGION_SIZE_MASK		U(0x7e)
+#define TZC_ATTR_REGION_SIZE(s)		((s) << TZC_REGION_SIZE_SHIFT)
+
+#define TZC_ATTR_REGION_EN_SHIFT	0x0
+#define TZC_ATTR_REGION_EN_MASK		U(0x1)
+
+#define TZC_ATTR_REGION_EN
+#define TZC_ATTR_REGION_ENABLE		U(0x1)
+#define TZC_ATTR_REGION_DISABLE		U(0x0)
+
+#define	REGION_MAX	16
+
+void tzc380_init(uintptr_t base);
+void tzc380_configure_region(uint8_t region,
+			     uintptr_t region_base,
+			     unsigned int attr);
+void tzc380_set_action(tzc_action_t action);
+static inline void tzc_init(uintptr_t base)
+{
+	tzc380_init(base);
+}
+
+static inline void tzc_configure_region(uint8_t region,
+					uintptr_t region_base,
+					unsigned int attr)
+{
+	tzc380_configure_region(region, region_base, attr);
+}
+
+static inline void tzc_set_action(tzc_action_t action)
+{
+	tzc380_set_action(action);
+}
+
+#endif /* TZC380_H */
diff --git a/plat/imx/common/imx_uart_console.S b/plat/imx/common/imx_uart_console.S
new file mode 100644
index 0000000..7dbde79
--- /dev/null
+++ b/plat/imx/common/imx_uart_console.S
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#define USE_FINISH_CONSOLE_REG_2
+#include <console_macros.S>
+#include <assert_macros.S>
+#include "imx_uart.h"
+
+#define URXD  0x0  /* Receiver Register */
+#define UTXD  0x40 /* Transmitter Register */
+#define UTS   0xb4 /* UART Test Register (mx31) */
+#define  URXD_RX_DATA    (0xFF)
+
+	.globl	console_uart_register
+	.globl	console_uart_init
+	.globl	console_uart_putc
+	.globl	console_uart_getc
+
+func console_imx_uart_register
+	mov	x7, x30
+	mov	x6, x3
+	cbz	x6, register_fail
+	str	x0, [x6, #CONSOLE_T_DRVDATA]
+
+	bl	console_imx_uart_init
+	cbz	x0, register_fail
+
+	mov	x0, x6
+	mov	x30, x7
+	finish_console_register imx_uart putc=1, getc=1
+
+register_fail:
+	ret	x7
+endfunc console_imx_uart_register
+
+func console_imx_uart_init
+	mov	w0, #1
+	ret
+endfunc console_imx_uart_init
+
+func console_imx_uart_putc
+	ldr	x1, [x1, #CONSOLE_T_DRVDATA]
+	cbz	x1, putc_error
+
+	/* Prepare '\r' to '\n' */
+	cmp	w0, #0xA
+	b.ne	2f
+1:
+	/* Check if the transmit FIFO is full */
+	ldr	w2, [x1, #UTS]
+	tbz	w2, #6, 1b
+	mov	w2, #0xD
+	str	w2, [x1, #UTXD]
+2:
+	/* Check if the transmit FIFO is full */
+	ldr	w2, [x1, #UTS]
+	tbz	w2, #6, 2b
+	str	w0, [x1, #UTXD]
+	ret
+putc_error:
+	mov	w0, #-1
+	ret
+endfunc console_imx_uart_putc
+
+func console_imx_uart_getc
+	ldr	x0, [x0, #CONSOLE_T_DRVDATA]
+	cbz	x0, getc_error
+1:
+	ldr	w1, [x0, #UTS]
+	tbnz	w1, #5, 1b
+
+	ldr	w1, [x0, #URXD]
+	and	w0, w1, #URXD_RX_DATA
+
+	ret
+getc_error:
+	mov	w0, #-1
+	ret
+endfunc console_imx_uart_getc
diff --git a/plat/imx/common/include/imx_uart.h b/plat/imx/common/include/imx_uart.h
new file mode 100644
index 0000000..d2c3968
--- /dev/null
+++ b/plat/imx/common/include/imx_uart.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_UART_H
+#define IMX_UART_H
+
+#include <console.h>
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+	console_t console;
+	uintptr_t base;
+} console_uart_t;
+
+int console_uart_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
+			   console_uart_t *console);
+#endif /*__ASSEMBLY__*/
+
+#endif  /* IMX_UART_H */
diff --git a/plat/imx/imx8m/imx8mq/gpc.c b/plat/imx/imx8m/imx8mq/gpc.c
new file mode 100644
index 0000000..187a4ad
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/gpc.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <gpc.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <std_svc.h>
+
+void imx_set_cpu_secure_entry(unsigned int core_id, uintptr_t sec_entrypoint)
+{
+	uint64_t temp_base;
+
+	temp_base = (uint64_t) sec_entrypoint;
+	temp_base >>= 2;
+
+	mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3),
+		((uint32_t)(temp_base >> 22) & 0xffff));
+	mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3) + 4,
+		((uint32_t)temp_base & 0x003fffff));
+}
+
+/* use wfi power down the core */
+void imx_set_cpu_pwr_off(unsigned int core_id)
+{
+	/* enable the wfi power down of the core */
+	mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) |
+			(1 << (core_id + 20)));
+	/* assert the pcg pcr bit of the core */
+	mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+};
+
+/* use the sw method to power up the core */
+void imx_set_cpu_pwr_on(unsigned int core_id)
+{
+	/* clear the wfi power down bit of the core */
+	mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id));
+	/* assert the ncpuporeset */
+	mmio_clrbits_32(IMX_SRC_BASE + SRC_A53RCR1, (1 << core_id));
+	/* assert the pcg pcr bit of the core */
+	mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+	/* sw power up the core */
+	mmio_setbits_32(IMX_GPC_BASE + CPU_PGC_UP_TRG, (1 << core_id));
+
+	/* wait for the power up finished */
+	while ((mmio_read_32(IMX_GPC_BASE + CPU_PGC_UP_TRG) & (1 << core_id)) != 0)
+		;
+
+	/* deassert the pcg pcr bit of the core */
+	mmio_clrbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+	/* deassert the ncpuporeset */
+	mmio_setbits_32(IMX_SRC_BASE + SRC_A53RCR1, (1 << core_id));
+}
+
+/* if out of lpm, we need to do reverse steps */
+void imx_set_cpu_lpm(unsigned int core_id, bool pdn)
+{
+	if (pdn) {
+		/* enable the core WFI PDN & IRQ PUP */
+		mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) |
+				(1 << (core_id + 20)) | COREx_IRQ_WUP(core_id));
+		/* assert the pcg pcr bit of the core */
+		mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+	} else {
+		/* disable CORE WFI PDN & IRQ PUP */
+		mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) |
+				COREx_IRQ_WUP(core_id));
+		/* deassert the pcg pcr bit of the core */
+		mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+	}
+}
+
+void imx_set_sys_wakeup(unsigned int last_core, bool pdn)
+{
+	/* TODO */
+}
+
+void imx_pup_pdn_slot_config(int last_core, bool pdn)
+{
+	if (pdn) {
+		/* SLOT0 for A53 PLAT power down */
+		mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(0), SLT_PLAT_PDN);
+		/* SLOT1 for A53 PLAT power up */
+		mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(1), SLT_PLAT_PUP);
+		/* SLOT2 for A53 primary core power up */
+		mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(2), SLT_COREx_PUP(last_core));
+		/* ACK setting: PLAT ACK for PDN, CORE ACK for PUP */
+		mmio_clrsetbits_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, 0xFFFFFFFF,
+			A53_PLAT_PDN_ACK | A53_PLAT_PUP_ACK);
+	} else {
+		mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(0), 0xFFFFFFFF);
+		mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(1), 0xFFFFFFFF);
+		mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(2), 0xFFFFFFFF);
+		mmio_clrsetbits_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, 0xFFFFFFFF,
+			A53_DUMMY_PDN_ACK | A53_DUMMY_PUP_ACK);
+	}
+}
+
+void imx_set_cluster_standby(bool retention)
+{
+	/*
+	 * Enable BIT 6 of A53 AD register to make sure system
+	 * don't enter LPM mode.
+	 */
+	if (retention)
+		mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, (1 << 6));
+	else
+		mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, (1 << 6));
+}
+
+void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state)
+{
+	uint32_t val;
+
+	if (is_local_state_off(power_state)) {
+		val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+		val |= A53_LPM_STOP; /* enable C0-C1's STOP mode */
+		val &= ~CPU_CLOCK_ON_LPM; /* disable CPU clock in LPM mode */
+		mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+		/* enable C2-3's STOP mode */
+		mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, A53_LPM_STOP);
+
+		/* enable PLAT/SCU power down */
+		val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD);
+		val &= ~EN_L2_WFI_PDN;
+		val |= L2PGE | EN_PLAT_PDN;
+		val &= ~COREx_IRQ_WUP(last_core); /* disable IRQ PUP for last core */
+		val |= COREx_LPM_PUP(last_core); /* enable LPM PUP for last core */
+		mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val);
+
+		imx_pup_pdn_slot_config(last_core, true);
+
+		/* enable PLAT PGC */
+		mmio_setbits_32(IMX_GPC_BASE + A53_PLAT_PGC, 0x1);
+	} else {
+		/* clear PLAT PGC */
+		mmio_clrbits_32(IMX_GPC_BASE + A53_PLAT_PGC, 0x1);
+
+		/* clear the slot and ack for cluster power down */
+		imx_pup_pdn_slot_config(last_core, false);
+
+		val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+		val &= ~A53_LPM_MASK; /* clear the C0~1 LPM */
+		val |= CPU_CLOCK_ON_LPM; /* disable cpu clock in LPM */
+		mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+		/* set A53 LPM to RUN mode */
+		mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, A53_LPM_MASK);
+
+		/* clear PLAT/SCU power down */
+		val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD);
+		val |= EN_L2_WFI_PDN;
+		val &= ~(L2PGE | EN_PLAT_PDN);
+		val &= ~COREx_LPM_PUP(last_core);  /* disable C0's LPM PUP */
+		mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val);
+	}
+}
+
+/* config the system level power mode */
+void imx_set_sys_lpm(bool retention)
+{
+	uint32_t val;
+
+	/* set system DSM mode SLPCR(0x14) */
+	val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+	val &= ~(SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS |
+		 SLPCR_BYPASS_PMIC_READY | SLPCR_RBC_EN);
+
+	if (retention)
+		val |= (SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS |
+			 SLPCR_BYPASS_PMIC_READY | SLPCR_RBC_EN |
+			 SLPCR_A53_FASTWUP_STOP_MODE);
+
+	mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+}
+
+void imx_set_rbc_count(void)
+{
+	mmio_setbits_32(IMX_GPC_BASE + SLPCR, 0x3f << SLPCR_RBC_COUNT_SHIFT);
+}
+
+void imx_clear_rbc_count(void)
+{
+	mmio_clrbits_32(IMX_GPC_BASE + SLPCR, 0x3f << SLPCR_RBC_COUNT_SHIFT);
+}
+
+void imx_gpc_init(void)
+{
+	uint32_t val;
+	int i;
+	/* mask all the interrupt by default */
+	/* 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.
+	 */
+	for (i = 0; i < 4; i++) {
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, 0xFFFFFFFE);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, 0xFFFFFFFE);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, 0xFFFFFFFE);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, 0xFFFFFFFE);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
+	}
+
+	/* use external IRQs to wakeup C0~C3 from LPM */
+	val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+	val |= IRQ_SRC_A53_WUP;
+	/* clear the MASTER0 LPM handshake */
+	val &= ~MASTER0_LPM_HSK;
+	mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+	/* mask M4 DSM trigger if M4 is NOT enabled */
+	mmio_setbits_32(IMX_GPC_BASE + LPCR_M4, DSM_MODE_MASK);
+
+	/* set all mix/PU in A53 domain */
+	mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xfffd);
+
+	/* set SCU timming */
+	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);
+
+	/* disable DSM mode by default */
+	mmio_clrbits_32(IMX_GPC_BASE + SLPCR, DSM_MODE_MASK);
+
+	/*
+	 * 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);
+	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1);
+}
diff --git a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
new file mode 100644
index 0000000..45d2a40
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#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 <gpc.h>
+#include <imx_uart.h>
+#include <stdbool.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <plat_imx8.h>
+#include <xlat_tables.h>
+#include <tzc380.h>
+
+IMPORT_SYM(uintptr_t, __COHERENT_RAM_START__, BL31_COHERENT_RAM_START);
+IMPORT_SYM(uintptr_t, __COHERENT_RAM_END__, BL31_COHERENT_RAM_END);
+IMPORT_SYM(uintptr_t, __RO_START__, BL31_RO_START);
+IMPORT_SYM(uintptr_t, __RO_END__, BL31_RO_END);
+IMPORT_SYM(uintptr_t, __RW_START__, BL31_RW_START);
+IMPORT_SYM(uintptr_t, __RW_END__, BL31_RW_END);
+
+static const mmap_region_t imx_mmap[] = {
+	MAP_REGION_FLAT(GPV_BASE, GPV_SIZE, MT_DEVICE | MT_RW), /* GPV map */
+	MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW), /* AIPS map */
+	MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW), /* GIC map */
+	{0},
+};
+
+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;
+}
+
+static void bl31_tz380_setup(void)
+{
+	unsigned int val;
+
+	val = mmio_read_32(IMX_IOMUX_GPR_BASE + IOMUXC_GPR10);
+	if ((val & GPR_TZASC_EN) != GPR_TZASC_EN)
+		return;
+
+	tzc380_init(IMX_TZASC_BASE);
+	/*
+	 * Need to substact offset 0x40000000 from CPU address when
+	 * programming tzasc region for i.mx8mq. Enable 1G-5G S/NS RW
+	 */
+	tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) |
+				TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL);
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+			u_register_t arg2, u_register_t arg3)
+{
+	int i;
+	/* enable CSU NS access permission */
+	for (i = 0; i < 64; i++) {
+		mmio_write_32(IMX_CSU_BASE + i * 4, 0xffffffff);
+	}
+
+#if DEBUG_CONSOLE
+	static console_uart_t console;
+
+	console_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+		IMX_CONSOLE_BAUDRATE, &console);
+#endif
+	/*
+	 * 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);
+
+	bl31_tz380_setup();
+}
+
+void bl31_plat_arch_setup(void)
+{
+	mmap_add_region(BL31_RO_START, BL31_RO_START, (BL31_RO_END - BL31_RO_START),
+		MT_MEMORY | MT_RO | MT_SECURE);
+	mmap_add_region(BL31_RW_START, BL31_RW_START, (BL31_RW_END - BL31_RW_START),
+		MT_MEMORY | MT_RW | MT_SECURE);
+
+	mmap_add(imx_mmap);
+
+#if USE_COHERENT_MEM
+	mmap_add_region(BL31_COHERENT_RAM_START, BL31_COHERENT_RAM_START,
+		BL31_COHERENT_RAM_END - BL31_COHERENT_RAM_START,
+		MT_DEVICE | MT_RW | MT_SECURE);
+#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 COUNTER_FREQUENCY;
+}
+
+void bl31_plat_runtime_setup(void)
+{
+	return;
+}
diff --git a/plat/imx/imx8m/imx8mq/imx8mq_psci.c b/plat/imx/imx8m/imx8mq/imx8mq_psci.c
new file mode 100644
index 0000000..7afe52d
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/imx8mq_psci.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <debug.h>
+#include <gpc.h>
+#include <stdbool.h>
+#include <plat_imx8.h>
+#include <psci.h>
+#include <mmio.h>
+
+#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0])
+#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
+
+int imx_pwr_domain_on(u_register_t mpidr)
+{
+	unsigned int core_id;
+	uint64_t base_addr = BL31_BASE;
+
+	core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+	/* set the secure entrypoint */
+	imx_set_cpu_secure_entry(core_id, base_addr);
+	/* power up the core */
+	imx_set_cpu_pwr_on(core_id);
+
+	return PSCI_E_SUCCESS;
+}
+
+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)
+{
+	uint64_t mpidr = read_mpidr_el1();
+	unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+	/* disable the GIC cpu interface first */
+	plat_gic_cpuif_disable();
+	/* config the core for power down */
+	imx_set_cpu_pwr_off(core_id);
+}
+
+int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
+{
+	/* The non-secure entrypoint should be in RAM space */
+	if (ns_entrypoint < PLAT_NS_IMAGE_OFFSET)
+		return PSCI_E_INVALID_PARAMS;
+
+	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);
+	int pwr_type = psci_get_pstate_type(power_state);
+	int state_id = psci_get_pstate_id(power_state);
+
+	if (pwr_lvl > PLAT_MAX_PWR_LVL)
+		return PSCI_E_INVALID_PARAMS;
+
+	if (pwr_type == PSTATE_TYPE_STANDBY) {
+		CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
+		CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
+	}
+
+	if (pwr_type == PSTATE_TYPE_POWERDOWN && state_id == 0x33) {
+		CORE_PWR_STATE(req_state) = PLAT_MAX_OFF_STATE;
+		CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
+	}
+
+	return PSCI_E_SUCCESS;
+}
+
+void imx_cpu_standby(plat_local_state_t cpu_state)
+{
+	dsb();
+	write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+	isb();
+
+	wfi();
+
+	write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
+	isb();
+}
+
+void imx_domain_suspend(const psci_power_state_t *target_state)
+{
+	uint64_t base_addr = BL31_BASE;
+	uint64_t mpidr = read_mpidr_el1();
+	unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+	if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+		/* disable the cpu interface */
+		plat_gic_cpuif_disable();
+		imx_set_cpu_secure_entry(core_id, base_addr);
+		imx_set_cpu_lpm(core_id, true);
+	} else {
+		dsb();
+		write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+		isb();
+	}
+
+	if (is_local_state_off(CLUSTER_PWR_STATE(target_state)))
+		imx_set_cluster_powerdown(core_id, true);
+	else
+		imx_set_cluster_standby(true);
+
+	if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
+		imx_set_sys_lpm(true);
+	}
+}
+
+void imx_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+	uint64_t mpidr = read_mpidr_el1();
+	unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+	/* check the system level status */
+	if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
+		imx_set_sys_lpm(false);
+		imx_clear_rbc_count();
+	}
+
+	/* check the cluster level power status */
+	if (is_local_state_off(CLUSTER_PWR_STATE(target_state)))
+		imx_set_cluster_powerdown(core_id, false);
+	else
+		imx_set_cluster_standby(false);
+
+	/* check the core level power status */
+	if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+		/* clear the core lpm setting */
+		imx_set_cpu_lpm(core_id, false);
+		/* enable the gic cpu interface */
+		plat_gic_cpuif_enable();
+	} else {
+		write_scr_el3(read_scr_el3() & (~0x4));
+		isb();
+	}
+}
+
+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_STOP_OFF_STATE;
+
+	req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PLAT_MAX_RET_STATE;
+}
+
+void __dead2 imx_system_reset(void)
+{
+	uintptr_t wdog_base = IMX_WDOG_BASE;
+	unsigned int val;
+
+	/* WDOG_B reset */
+	val = mmio_read_16(wdog_base);
+#ifdef IMX_WDOG_B_RESET
+	val = (val & 0x00FF) | WDOG_WCR_WDZST | WDOG_WCR_WDE |
+		WDOG_WCR_WDT | WDOG_WCR_SRS;
+#else
+	val = (val & 0x00FF) | WDOG_WCR_WDZST | WDOG_WCR_SRS;
+#endif
+	mmio_write_16(wdog_base, val);
+
+	mmio_write_16(wdog_base + WDOG_WSR, 0x5555);
+	mmio_write_16(wdog_base + WDOG_WSR, 0xaaaa);
+	while (1)
+		;
+}
+
+
+
+void __dead2 imx_system_off(void)
+{
+	mmio_write_32(IMX_SNVS_BASE + SNVS_LPCR, SNVS_LPCR_SRTC_ENV |
+			SNVS_LPCR_DP_EN | SNVS_LPCR_TOP);
+
+	while (1)
+		;
+}
+
+void __dead2 imx_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
+{
+	if (is_local_state_off(CLUSTER_PWR_STATE(target_state)))
+		imx_set_rbc_count();
+
+	while (1)
+		wfi();
+}
+
+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,
+	.pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+	.get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+	.system_reset = imx_system_reset,
+	.system_off = imx_system_off,
+};
+
+/* 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/imx/imx8m/imx8mq/include/platform_def.h b/plat/imx/imx8m/imx8mq/include/platform_def.h
new file mode 100644
index 0000000..4957582
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/include/platform_def.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+#define PLATFORM_STACK_SIZE		0x800
+#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_CLUSTER1_CORE_COUNT	0
+#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		U(1)
+#define PLAT_MAX_PWR_LVL		U(2)
+#define PLAT_MAX_OFF_STATE		U(4)
+#define PLAT_MAX_RET_STATE		U(1)
+
+#define PLAT_WAIT_OFF_STATE		U(2)
+#define PLAT_STOP_OFF_STATE		U(3)
+
+#define BL31_BASE			U(0x910000)
+#define BL31_LIMIT			U(0x920000)
+#define BL32_BASE			U(0xfe000000)
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET		U(0x40200000)
+
+/* GICv3 base address */
+#define PLAT_GICD_BASE			U(0x38800000)
+#define PLAT_GICR_BASE			U(0x38880000)
+
+#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		14
+
+#define HAB_RVT_BASE			U(0x00000880) /* HAB_RVT for i.MX8MQ */
+
+#define IMX_BOOT_UART_BASE		U(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_AIPS_BASE			U(0x30200000)
+#define IMX_AIPS_SIZE			U(0xC00000)
+#define IMX_AIPS1_BASE			U(0x30200000)
+#define IMX_AIPS3_ARB_BASE		U(0x30800000)
+#define IMX_ANAMIX_BASE			U(0x30360000)
+#define IMX_CCM_BASE			U(0x30380000)
+#define IMX_SRC_BASE			U(0x30390000)
+#define IMX_GPC_BASE			U(0x303a0000)
+#define IMX_RDC_BASE			U(0x303d0000)
+#define IMX_CSU_BASE			U(0x303e0000)
+#define IMX_WDOG_BASE			U(0x30280000)
+#define IMX_SNVS_BASE			U(0x30370000)
+#define IMX_NOC_BASE			U(0x32700000)
+#define IMX_TZASC_BASE			U(0x32F80000)
+#define IMX_IOMUX_GPR_BASE		U(0x30340000)
+#define IMX_DDRC_BASE			U(0x3d400000)
+#define IMX_DDRPHY_BASE			U(0x3c000000)
+#define IMX_DDR_IPS_BASE		U(0x3d000000)
+#define IMX_ROM_BASE			U(0x00000000)
+
+#define AIPSTZ1_BASE			U(0x301f0000)
+#define AIPSTZ2_BASE			U(0x305f0000)
+#define AIPSTZ3_BASE			U(0x309f0000)
+#define AIPSTZ4_BASE			U(0x32df0000)
+
+#define GPV_BASE			U(0x32000000)
+#define GPV_SIZE			U(0x800000)
+#define IMX_GIC_BASE			PLAT_GICD_BASE
+#define IMX_GIC_SIZE			U(0x200000)
+
+#define WDOG_WSR			U(0x2)
+#define WDOG_WCR_WDZST			BIT(0)
+#define WDOG_WCR_WDBG			BIT(1)
+#define WDOG_WCR_WDE			BIT(2)
+#define WDOG_WCR_WDT			BIT(3)
+#define WDOG_WCR_SRS			BIT(4)
+#define WDOG_WCR_WDA			BIT(5)
+#define WDOG_WCR_SRE			BIT(6)
+#define WDOG_WCR_WDW			BIT(7)
+
+#define SRC_A53RCR0			U(0x4)
+#define SRC_A53RCR1			U(0x8)
+#define SRC_OTG1PHY_SCR			U(0x20)
+#define SRC_OTG2PHY_SCR			U(0x24)
+#define SRC_GPR1_OFFSET			U(0x74)
+
+#define SNVS_LPCR			U(0x38)
+#define SNVS_LPCR_SRTC_ENV		BIT(0)
+#define SNVS_LPCR_DP_EN			BIT(5)
+#define SNVS_LPCR_TOP			BIT(6)
+
+
+#define IOMUXC_GPR10			U(0x28)
+#define GPR_TZASC_EN			BIT(0)
+#define GPR_TZASC_EN_LOCK		BIT(16)
+
+#define OCRAM_S_BASE			U(0x00180000)
+#define OCRAM_S_SIZE			U(0x8000)
+#define OCRAM_S_LIMIT			(OCRAM_S_BASE + OCRAM_S_SIZE)
+
+#define COUNTER_FREQUENCY		8000000 /* 8MHz */
+
+#define DEBUG_CONSOLE			0
+#define IMX_WDOG_B_RESET
+#define PLAT_IMX8M			1
diff --git a/plat/imx/imx8m/imx8mq/platform.mk b/plat/imx/imx8m/imx8mq/platform.mk
new file mode 100644
index 0000000..0255268
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/platform.mk
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES		:=	-Iplat/imx/common/include		\
+				-Iplat/imx/imx8m/include		\
+				-Iplat/imx/imx8m/imx8mq/include
+
+IMX_GIC_SOURCES		:=	drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/arm_gicv3_common.c   \
+				drivers/arm/gic/v3/gic500.c             \
+				drivers/arm/gic/v3/gicv3_main.c		\
+				drivers/arm/gic/common/gic_common.c	\
+				plat/common/plat_gicv3.c		\
+				plat/common/plat_psci_common.c		\
+				plat/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES		+=	plat/imx/common/imx8_helpers.S			\
+				plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c	\
+				plat/imx/imx8m/imx8mq/imx8mq_psci.c		\
+				plat/imx/imx8m/imx8mq/gpc.c			\
+				plat/imx/common/imx8_topology.c			\
+				plat/imx/common/imx_uart_console.S		\
+				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		\
+				drivers/arm/tzc/tzc380.c			\
+				${IMX_GIC_SOURCES}
+
+USE_COHERENT_MEM	:=	1
+RESET_TO_BL31		:=	1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+MULTI_CONSOLE_API	:=	1
diff --git a/plat/imx/imx8m/include/gpc.h b/plat/imx/imx8m/include/gpc.h
new file mode 100644
index 0000000..6fdf6ad
--- /dev/null
+++ b/plat/imx/imx8m/include/gpc.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX8M_GPC_H
+#define IMX8M_GPC_H
+
+#define LPCR_A53_BSC			0x0
+#define LPCR_A53_BSC2			0x108
+#define LPCR_A53_AD			0x4
+#define LPCR_M4				0x8
+#define SLPCR				0x14
+#define MST_CPU_MAPPING			0x18
+#define MLPCR				0x20
+#define PGC_ACK_SEL_A53			0x24
+#define IMR1_CORE0_A53			0x30
+#define IMR1_CORE1_A53			0x40
+#define IMR1_CORE2_A53			0x1C0
+#define IMR1_CORE3_A53			0x1D0
+#define IMR1_CORE0_M4			0x50
+#define SLT0_CFG			0xB0
+#define GPC_PU_PWRHSK			0x1FC
+#define PGC_CPU_0_1_MAPPING		0xEC
+#define CPU_PGC_UP_TRG			0xF0
+#define PU_PGC_UP_TRG			0xF8
+#define CPU_PGC_DN_TRG			0xFC
+#define PU_PGC_DN_TRG			0x104
+#define A53_CORE0_PGC			0x800
+#define A53_PLAT_PGC			0x900
+#define PGC_SCU_TIMING			0x910
+
+#define MASK_DSM_TRIGGER_A53		BIT(31)
+#define IRQ_SRC_A53_WUP			BIT(30)
+#define IRQ_SRC_C1			BIT(29)
+#define IRQ_SRC_C0			BIT(28)
+#define IRQ_SRC_C3			BIT(23)
+#define IRQ_SRC_C2			BIT(22)
+#define CPU_CLOCK_ON_LPM		BIT(14)
+#define MASTER0_LPM_HSK			BIT(6)
+
+#define L2PGE				BIT(31)
+#define EN_L2_WFI_PDN			BIT(5)
+#define EN_PLAT_PDN			BIT(4)
+
+#define SLPCR_EN_DSM			BIT(31)
+#define SLPCR_RBC_EN			BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
+#define SLPCR_VSTBY			BIT(2)
+#define SLPCR_SBYOS			BIT(1)
+#define SLPCR_BYPASS_PMIC_READY		BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT		24
+
+#define A53_DUMMY_PDN_ACK		BIT(15)
+#define A53_DUMMY_PUP_ACK		BIT(31)
+#define A53_PLAT_PDN_ACK		BIT(2)
+#define A53_PLAT_PUP_ACK		BIT(18)
+
+#define SLT_PLAT_PDN			BIT(8)
+#define SLT_PLAT_PUP			BIT(9)
+
+/* helper macro */
+#define A53_LPM_MASK	U(0xF)
+#define A53_LPM_WAIT	U(0x5)
+#define A53_LPM_STOP	U(0xA)
+
+#define DSM_MODE_MASK	BIT(31)
+
+#define A53_CORE_WUP_SRC(core_id)	(1 << ((core_id) < 2 ? 28 + (core_id) : 22 + (core_id) - 2))
+#define COREx_PGC_PCR(core_id)		(0x800 + (core_id) * 0x40)
+#define COREx_WFI_PDN(core_id)		(1 << ((core_id) < 2 ? (core_id) * 2 : ((core_id) - 2) * 2 + 16))
+#define COREx_IRQ_WUP(core_id)		((core_id) < 2 ? (1 << ((core_id) * 2 + 8)) : (1 << ((core_id) * 2 + 20)))
+#define COREx_LPM_PUP(core_id)		((core_id) < 2 ? (1 << ((core_id) * 2 + 9)) : (1 << ((core_id) * 2 + 21)))
+#define SLTx_CFG(n)			((SLT0_CFG + ((n) * 4)))
+#define SLT_COREx_PUP(core_id)		(0x2 << ((core_id) * 2))
+
+/* function declare */
+void imx_gpc_init(void);
+void imx_set_cpu_secure_entry(unsigned int core_index, uintptr_t sec_entrypoint);
+void imx_set_cpu_pwr_off(unsigned int core_index);
+void imx_set_cpu_pwr_on(unsigned int core_index);
+void imx_set_cpu_lpm(unsigned int core_index, bool pdn);
+void imx_set_cluster_standby(bool retention);
+void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state);
+void imx_set_sys_lpm(bool retention);
+void imx_set_rbc_count(void);
+void imx_clear_rbc_count(void);
+
+#endif /*IMX8M_GPC_H */
diff --git a/plat/layerscape/board/ls1043/include/soc_tzasc.h b/plat/layerscape/board/ls1043/include/soc_tzasc.h
index b2483d9..46dfba0 100644
--- a/plat/layerscape/board/ls1043/include/soc_tzasc.h
+++ b/plat/layerscape/board/ls1043/include/soc_tzasc.h
@@ -7,8 +7,6 @@
 #ifndef SOC_TZASC_H
 #define SOC_TZASC_H
 
-#include "tzc380.h"
-
 #define MAX_NUM_TZC_REGION	3
 
 /* TZASC related constants */
@@ -58,6 +56,15 @@
 #define CCI_TERMINATE_BARRIER_TX	0x8
 #define CONFIG_SYS_FSL_TZASC_ADDR	0x1500000
 
+struct tzc380_reg {
+	unsigned int secure;
+	unsigned int enabled;
+	unsigned int low_addr;
+	unsigned int high_addr;
+	unsigned int size;
+	unsigned int sub_mask;
+};
+
 /* List of MAX_NUM_TZC_REGION TZC regions' boundaries and configurations. */
 
 static const struct tzc380_reg tzc380_reg_list[] = {
diff --git a/plat/layerscape/common/include/tzc380.h b/plat/layerscape/common/include/tzc380.h
deleted file mode 100644
index 88063a9..0000000
--- a/plat/layerscape/common/include/tzc380.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef TZC380_H
-#define TZC380_H
-
-struct tzc380_reg {
-	unsigned int secure;
-	unsigned int enabled;
-	unsigned int low_addr;
-	unsigned int high_addr;
-	unsigned int size;
-	unsigned int sub_mask;
-};
-
-#endif /* TZC380_H */