Merge pull request #1428 from jeenu-arm/mbedtls

Move to mbedtls-2.10.0 tag
diff --git a/Makefile b/Makefile
index 17630fb..f230f4a 100644
--- a/Makefile
+++ b/Makefile
@@ -198,7 +198,8 @@
 				${COMPILER_RT_SRCS}			\
 				${STDLIB_SRCS}
 
-INCLUDES		+=	-Iinclude/bl1				\
+INCLUDES		+=	-Iinclude				\
+				-Iinclude/bl1				\
 				-Iinclude/bl2				\
 				-Iinclude/bl2u				\
 				-Iinclude/bl31				\
diff --git a/docs/plat/allwinner.rst b/docs/plat/allwinner.rst
new file mode 100644
index 0000000..a7e84a3
--- /dev/null
+++ b/docs/plat/allwinner.rst
@@ -0,0 +1,29 @@
+Trusted Firmware-A for Allwinner ARMv8 SoCs
+===========================================
+
+Trusted Firmware-A (TF-A) implements the EL3 firmware layer for Allwinner
+SoCs with ARMv8 cores. Only BL31 is used to provide proper EL3 setup and
+PSCI runtime services.
+U-Boot's SPL acts as a loader, loading both BL31 and BL33 (typically U-Boot).
+Loading is done from SD card, eMMC or SPI flash, also via an USB debug
+interface (FEL).
+BL31 lives in SRAM A2, which is documented to be accessible from secure
+world only.
+
+Current limitations:
+
+-  Missing PMIC support
+
+After building bl31.bin, the binary must be fed to the U-Boot build system
+to include it in the FIT image that the SPL loader will process.
+bl31.bin can be either copied (or sym-linked) into U-Boot's root directory,
+or the environment variable BL31 must contain the binary's path.
+See the respective `U-Boot documentation`_ for more details.
+
+To build:
+
+::
+
+    make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_a64 DEBUG=1 bl31
+
+.. _U-Boot documentation: http://git.denx.de/?p=u-boot.git;f=board/sunxi/README.sunxi64;hb=HEAD
diff --git a/docs/plat/imx8.rst b/docs/plat/imx8.rst
new file mode 100644
index 0000000..4240962
--- /dev/null
+++ b/docs/plat/imx8.rst
@@ -0,0 +1,58 @@
+Description
+===========
+
+The i.MX 8 series of applications processors is a feature- and
+performance-scalable multi-core platform that includes single-,
+dual-, and quad-core families based on the Arm® Cortex®
+architecture—including combined Cortex-A72 + Cortex-A53,
+Cortex-A35, and Cortex-M4 based solutions for advanced graphics,
+imaging, machine vision, audio, voice, video, and safety-critical
+applications.
+
+The i.MX8QM is with 2 Cortex-A72 ARM core, 4 Cortex-A53 ARM core
+and 1 Cortex-M4 system controller.
+
+The i.MX8QX is with 4 Cortex-A35 ARM core and 1 Cortex-M4 system
+controller.
+
+The System Controller (SC) represents the evolution of centralized
+control for system-level resources on i.MX8. The heart of the system
+controller is a Cortex-M4 that executes system controller firmware.
+
+Boot Sequence
+=============
+
+Bootrom --> BL31 --> BL33(u-boot) --> Linux kernel
+
+How to build
+============
+
+Build Procedure
+---------------
+
+-  Prepare AARCH64 toolchain.
+
+-  Build System Controller Firmware and u-boot firstly, and get binary images: scfw_tcm.bin and u-boot.bin
+
+-  Build TF-A
+
+   Build bl31:
+
+   .. code:: shell
+
+       CROSS_COMPILE=aarch64-linux-gnu- make PLAT=<Target_SoC> bl31
+
+   Target_SoC should be "imx8qm" for i.MX8QM SoC.
+   Target_SoC should be "imx8qx" for i.MX8QX SoC.
+
+Deploy TF-A Images
+-----------------
+
+TF-A binary(bl31.bin), scfw_tcm.bin and u-boot.bin 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 system controller firmware,
+u-boot and imx-mkimage will be upstreamed soon, this doc will be updated
+once they are ready, and the link will be posted.
+
+.. _i.MX8: https://www.nxp.com/products/processors-and-microcontrollers/applications-processors/i.mx-applications-processors/i.mx-8-processors/i.mx-8-family-arm-cortex-a53-cortex-a72-virtualization-vision-3d-graphics-4k-video:i.MX8
diff --git a/docs/plat/rpi3.rst b/docs/plat/rpi3.rst
index b7879a8..554c9a1 100644
--- a/docs/plat/rpi3.rst
+++ b/docs/plat/rpi3.rst
@@ -122,7 +122,7 @@
     0x10000000 +-----------------+
                |   Secure SRAM   | BL2, BL31
     0x10100000 +-----------------+
-               |   Secure DRAM   |
+               |   Secure DRAM   | BL32 (Secure payload)
     0x10300000 +-----------------+
                | Non-secure DRAM | BL33
     0x11000000 +-----------------+
@@ -134,7 +134,7 @@
     0x40000000 +-----------------+
 
 The area between **0x10000000** and **0x11000000** has to be protected so that
-the kernel doesn't use it. That is done by adding ``memmap=256M$16M`` to the
+the kernel doesn't use it. That is done by adding ``memmap=16M$256M`` to the
 command line passed to the kernel. See the `Setup SD card`_ instructions to see
 how to do it.
 
@@ -237,6 +237,12 @@
   in AArch64 mode. If set to 1, it will jump to BL33 in Hypervisor in AArch32
   mode.
 
+- ``BL32``: This port can load and run OP-TEE. The OP-TEE image is optional.
+  Please use the code from `here <https://github.com/OP-TEE/optee_os>`__.
+  Build the Trusted Firmware with option ``BL32=tee-header_v2.bin
+  BL32_EXTRA1=tee-pager_v2.bin  BL32_EXTRA2=tee-pageable_v2.bin``
+  to put the binaries into the FIP.
+
 The following is not currently supported:
 
 - AArch32 for TF-A itself.
@@ -317,7 +323,7 @@
    bootloader will look for a file called ``armstub8.bin`` and load it at
    address **0x0** instead of a predefined one.
 
-4. Open ``cmdline.txt`` and add ``memmap=256M$16M`` to prevent the kernel from
+4. Open ``cmdline.txt`` and add ``memmap=16M$256M`` to prevent the kernel from
    using the memory needed by TF-A. If you want to enable the serial port
    "Mini UART", make sure that this file also contains
    ``console=serial0,115200 console=tty1``.
diff --git a/docs/plat/ti-k3.rst b/docs/plat/ti-k3.rst
new file mode 100644
index 0000000..6515c64
--- /dev/null
+++ b/docs/plat/ti-k3.rst
@@ -0,0 +1,55 @@
+Trusted Firmware-A for Texas Instruments K3 SoCs
+================================================
+
+Trusted Firmware-A (TF-A) implements the EL3 firmware layer for Texas Instruments K3 SoCs.
+
+Boot Flow
+---------
+
+R5(U-Boot) --> TF-A BL31 --> BL32(OP-TEE) --> TF-A BL31 --> BL33(U-Boot) --> Linux
+                                                       \
+                                                Optional direct to Linux boot
+                                                         \
+                                                           --> BL33(Linux)
+
+Texas Instruments K3 SoCs contain an R5 processor used as the boot master, it
+loads the needed images for A53 startup, because of this we do not need BL1 or
+BL2 TF-A stages.
+
+Build Instructions
+------------------
+
+https://github.com/ARM-software/arm-trusted-firmware.git
+
+TF-A:
+
+.. code:: shell
+
+    make CROSS_COMPILE=aarch64-linux-gnu- PLAT=k3 SPD=opteed all
+
+OP-TEE:
+
+.. code:: shell
+
+    make ARCH=arm CROSS_COMPILE64=aarch64-linux-gnu- PLATFORM=k3 CFG_ARM64_core=y all
+
+R5 U-Boot:
+
+.. code:: shell
+
+    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- am65x_evm_r5_defconfig
+    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- SYSFW=<path to SYSFW>
+
+A53 U-Boot:
+
+.. code:: shell
+
+    make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- am65x_evm_a53_defconfig
+    make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- ATF=<path> TEE=<path>
+
+Deploy Images
+-------------
+
+.. code:: shell
+
+    cp tiboot3.bin tispl.bin u-boot.img /sdcard/boot/
diff --git a/include/drivers/console.h b/include/drivers/console.h
index a4d89fe..6e7ebbf 100644
--- a/include/drivers/console.h
+++ b/include/drivers/console.h
@@ -16,9 +16,9 @@
 #define CONSOLE_T_FLUSH			(U(4) * REGSZ)
 #define CONSOLE_T_DRVDATA		(U(5) * REGSZ)
 
-#define CONSOLE_FLAG_BOOT		BIT(0)
-#define CONSOLE_FLAG_RUNTIME		BIT(1)
-#define CONSOLE_FLAG_CRASH		BIT(2)
+#define CONSOLE_FLAG_BOOT		(U(1) << 0)
+#define CONSOLE_FLAG_RUNTIME		(U(1) << 1)
+#define CONSOLE_FLAG_CRASH		(U(1) << 2)
 /* Bits 3 to 7 reserved for additional scopes in future expansion. */
 #define CONSOLE_FLAG_SCOPE_MASK		((U(1) << 8) - 1)
 /* Bits 8 to 31 reserved for non-scope use in future expansion. */
diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h
index 3624cc6..910341a 100644
--- a/include/lib/aarch32/arch.h
+++ b/include/lib/aarch32/arch.h
@@ -379,6 +379,7 @@
  * Definitions of register offsets and fields in the CNTCTLBase Frame of the
  * system level implementation of the Generic Timer.
  ******************************************************************************/
+#define CNTCTLBASE_CNTFRQ	U(0x0)
 #define CNTNSAR			0x4
 #define CNTNSAR_NS_SHIFT(x)	(x)
 
@@ -390,6 +391,12 @@
 #define CNTACR_RWVT_SHIFT	0x4
 #define CNTACR_RWPT_SHIFT	0x5
 
+/*******************************************************************************
+ * Definitions of register offsets in the CNTBaseN Frame of the
+ * system level implementation of the Generic Timer.
+ ******************************************************************************/
+#define CNTBASE_CNTFRQ		U(0x10)
+
 /* MAIR macros */
 #define MAIR0_ATTR_SET(attr, index)	((attr) << ((index) << 3))
 #define MAIR1_ATTR_SET(attr, index)	((attr) << (((index) - 3) << 3))
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 92bb97d..7cc4b23 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -554,6 +554,7 @@
  * Definitions of register offsets and fields in the CNTCTLBase Frame of the
  * system level implementation of the Generic Timer.
  ******************************************************************************/
+#define CNTCTLBASE_CNTFRQ	U(0x0)
 #define CNTNSAR			U(0x4)
 #define CNTNSAR_NS_SHIFT(x)	(x)
 
@@ -565,6 +566,12 @@
 #define CNTACR_RWVT_SHIFT	U(0x4)
 #define CNTACR_RWPT_SHIFT	U(0x5)
 
+/*******************************************************************************
+ * Definitions of register offsets in the CNTBaseN Frame of the
+ * system level implementation of the Generic Timer.
+ ******************************************************************************/
+#define CNTBASE_CNTFRQ		U(0x10)
+
 /* PMCR_EL0 definitions */
 #define PMCR_EL0_RESET_VAL	U(0x0)
 #define PMCR_EL0_N_SHIFT	U(11)
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index 31b1294..7335103 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -16,7 +16,31 @@
 
 #define SIZE_FROM_LOG2_WORDS(n)		(4 << (n))
 
-#define BIT(nr)				(ULL(1) << (nr))
+#define BIT_32(nr)			(U(1) << (nr))
+#define BIT_64(nr)			(ULL(1) << (nr))
+
+#ifdef AARCH32
+#define BIT				BIT_32
+#else
+#define BIT				BIT_64
+#endif
+
+/*
+ * Create a contiguous bitmask starting at bit position @l and ending at
+ * position @h. For example
+ * GENMASK_64(39, 21) gives us the 64bit vector 0x000000ffffe00000.
+ */
+#define GENMASK_32(h, l) \
+	(((~UINT32_C(0)) << (l)) & (~UINT32_C(0) >> (32 - 1 - (h))))
+
+#define GENMASK_64(h, l) \
+	(((~UINT64_C(0)) << (l)) & (~UINT64_C(0) >> (64 - 1 - (h))))
+
+#ifdef AARCH32
+#define GENMASK				GENMASK_32
+#else
+#define GENMASK				GENMASK_64
+#endif
 
 /*
  * This variant of div_round_up can be used in macro definition but should not
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index 2d8e4c1..030e067 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -89,7 +89,7 @@
 #if TRUSTED_BOARD_BOOT
 # define PLAT_ARM_MAX_BL2_SIZE		0x1E000
 #else
-# define PLAT_ARM_MAX_BL2_SIZE		0x10000
+# define PLAT_ARM_MAX_BL2_SIZE		0x11000
 #endif
 
 /*
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index e07156c..e3d0edb 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -258,6 +258,8 @@
 #define ARM_SYS_CNTCTL_BASE		0x2a430000
 #define ARM_SYS_CNTREAD_BASE		0x2a800000
 #define ARM_SYS_TIMCTL_BASE		0x2a810000
+#define ARM_SYS_CNT_BASE_S		0x2a820000
+#define ARM_SYS_CNT_BASE_NS		0x2a830000
 
 #define ARM_CONSOLE_BAUDRATE		115200
 
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index fc3f4ec..33f2c7d 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -155,6 +155,12 @@
 void arm_tzc_dmc500_setup(struct tzc_dmc500_driver_data *plat_driver_data,
 			const arm_tzc_regions_info_t *tzc_regions);
 
+/* Console utility functions */
+void arm_console_boot_init(void);
+void arm_console_boot_end(void);
+void arm_console_runtime_init(void);
+void arm_console_runtime_end(void);
+
 /* Systimer utility function */
 void arm_configure_sys_timer(void);
 
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index 07fadd1..8e60445 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -404,6 +404,7 @@
 #if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
 	adr	x0, wa_cve_2017_5715_mmu_vbar
 	msr	vbar_el3, x0
+	/* isb will be performed before returning from this function */
 #endif
 
 #if WORKAROUND_CVE_2018_3639
diff --git a/lib/cpus/aarch64/cortex_a72.S b/lib/cpus/aarch64/cortex_a72.S
index bb9381d..38b76b9 100644
--- a/lib/cpus/aarch64/cortex_a72.S
+++ b/lib/cpus/aarch64/cortex_a72.S
@@ -137,6 +137,7 @@
 	cpu_check_csv2	x0, 1f
 	adr	x0, wa_cve_2017_5715_mmu_vbar
 	msr	vbar_el3, x0
+	/* isb will be performed before returning from this function */
 1:
 #endif
 
diff --git a/lib/cpus/aarch64/cortex_a73.S b/lib/cpus/aarch64/cortex_a73.S
index d595f12..b796561 100644
--- a/lib/cpus/aarch64/cortex_a73.S
+++ b/lib/cpus/aarch64/cortex_a73.S
@@ -40,6 +40,7 @@
 	cpu_check_csv2	x0, 1f
 	adr	x0, wa_cve_2017_5715_bpiall_vbar
 	msr	vbar_el3, x0
+	/* isb will be performed before returning from this function */
 1:
 #endif
 
diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S
index 20ec32c..73f566f 100644
--- a/lib/cpus/aarch64/cortex_a75.S
+++ b/lib/cpus/aarch64/cortex_a75.S
@@ -15,6 +15,7 @@
 	cpu_check_csv2	x0, 1f
 	adr	x0, wa_cve_2017_5715_bpiall_vbar
 	msr	vbar_el3, x0
+	isb
 1:
 #endif
 
diff --git a/lib/xlat_tables_v2/xlat_tables_internal.c b/lib/xlat_tables_v2/xlat_tables_internal.c
index 31d3365..3b586b2 100644
--- a/lib/xlat_tables_v2/xlat_tables_internal.c
+++ b/lib/xlat_tables_v2/xlat_tables_internal.c
@@ -784,8 +784,8 @@
 	       && mm_cursor->size)
 		++mm_cursor;
 
-	while ((mm_cursor->base_va + mm_cursor->size - 1 == end_va)
-	       && (mm_cursor->size < mm->size))
+	while ((mm_cursor->base_va + mm_cursor->size - 1 == end_va) &&
+	       (mm_cursor->size != 0U) && (mm_cursor->size < mm->size))
 		++mm_cursor;
 
 	/*
@@ -1087,13 +1087,13 @@
 
 	if (xlat_regime == EL3_REGIME) {
 		/* For EL3, the XN bit is all what matters */
-		tf_printf("%s", LOWER_ATTRS(XN) & desc ? xn_str : exec_str);
+		tf_printf("%s", (UPPER_ATTRS(XN) & desc) ? xn_str : exec_str);
 	} else {
 		/* For EL0 and EL1, we need to know who has which rights */
-		tf_printf("%s", LOWER_ATTRS(PXN) & desc ? xn_str : exec_str);
+		tf_printf("%s", (UPPER_ATTRS(PXN) & desc) ? xn_str : exec_str);
 		tf_printf("%s", priv_str);
 
-		tf_printf("%s", LOWER_ATTRS(UXN) & desc ? xn_str : exec_str);
+		tf_printf("%s", (UPPER_ATTRS(UXN) & desc) ? xn_str : exec_str);
 		tf_printf("%s", user_str);
 	}
 
diff --git a/maintainers.rst b/maintainers.rst
index 2217cbe..96ff0e0 100644
--- a/maintainers.rst
+++ b/maintainers.rst
@@ -64,6 +64,16 @@
 -  plat/hisilicon/hikey/\*
 -  plat/hisilicon/hikey960/\*
 
+Allwinner ARMv8 platform sub-maintainer
+---------------------------------------
+
+Andre Przywara (andre.przywara@arm.com, `Andre-ARM`_)
+
+Files:
+
+-  docs/plat/allwinner.rst
+-  plat/allwinner/\*
+
 HiSilicon Poplar platform sub-maintainer
 ----------------------------------------
 
@@ -92,6 +102,16 @@
 -  docs/plat/ls1043a.rst
 -  plat/layerscape/\*
 
+NXP i.MX 8 platform sub-maintainer
+--------------------------------------
+
+Anson Huang (Anson.Huang@nxp.com, `Anson-Huang`_)
+
+Files:
+
+-  docs/plat/imx8.rst
+-  plat/imx/\*
+
 Raspberry Pi 3 platform sub-maintainer
 --------------------------------------
 
@@ -112,6 +132,16 @@
 
 -  plat/rockchip/\*
 
+Texas Instruments platform sub-maintainer
+-----------------------------------------
+
+Andrew F. Davis (afd@ti.com, `glneo`_)
+
+Files:
+
+- docs/plat/ti-k3.rst
+- plat/ti/\*
+
 UniPhier platform sub-maintainer
 --------------------------------
 
@@ -147,7 +177,9 @@
 .. _masahir0y: https://github.com/masahir0y
 .. _mtk09422: https://github.com/mtk09422
 .. _TonyXie06: https://github.com/TonyXie06
+.. _glneo: https://github.com/glneo
 .. _sivadur: https://github.com/sivadur
 .. _rockchip-linux: https://github.com/rockchip-linux
 .. _etienne-lms: https://github.com/etienne-lms
 .. _qoriq-open-source: https://github.com/qoriq-open-source
+.. _Andre-ARM: https://github.com/Andre-ARM
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index cac9dfc..2a6ded4 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -372,11 +372,14 @@
 define MAKE_DTB
 
 $(eval DOBJ := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2))))
+$(eval DPRE := $(addprefix $(1)/,$(patsubst %.dts,%.pre.dts,$(notdir $(2)))))
 $(eval DEP := $(patsubst %.dtb,%.d,$(DOBJ)))
 
 $(DOBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | fdt_dirs
+	@echo "  CPP     $$<"
+	$$(Q)$$(CPP) $$(CPPFLAGS) -x assembler-with-cpp -o $(DPRE) $$<
 	@echo "  DTC     $$<"
-	$$(Q)$$(DTC) $$(DTC_FLAGS) -d $(DEP) -o $$@ $$<
+	$$(Q)$$(DTC) $$(DTC_FLAGS) -i fdts -d $(DEP) -o $$@ $(DPRE)
 
 -include $(DEP)
 
diff --git a/plat/allwinner/common/include/plat_macros.S b/plat/allwinner/common/include/plat_macros.S
new file mode 100644
index 0000000..6ee4597
--- /dev/null
+++ b/plat/allwinner/common/include/plat_macros.S
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_MACROS_S__
+#define __PLAT_MACROS_S__
+
+#include <arm_macros.S>
+#include <sunxi_mmap.h>
+
+	/* ---------------------------------------------
+	 * The below required platform porting macro
+	 * prints out relevant GIC and CCI registers
+	 * whenever an unhandled exception is taken in
+	 * BL31.
+	 * Clobbers: x0 - x10, x16, x17, sp
+	 * ---------------------------------------------
+	 */
+	.macro plat_crash_print_regs
+	mov_imm	x17, SUNXI_GICC_BASE
+	mov_imm	x16, SUNXI_GICD_BASE
+	arm_print_gic_regs
+	.endm
+
+#endif /* __PLAT_MACROS_S__ */
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
new file mode 100644
index 0000000..ca7db2f
--- /dev/null
+++ b/plat/allwinner/common/include/platform_def.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <common_def.h>
+#include <sunxi_mmap.h>
+#include <tbbr/tbbr_img_def.h>
+
+#define BL31_BASE			SUNXI_SRAM_A2_BASE
+#define BL31_LIMIT			(SUNXI_SRAM_A2_BASE + SUNXI_SRAM_A2_SIZE)
+
+/* The traditional U-Boot load address is 160MB into DRAM, so at 0x4a000000 */
+#define PLAT_SUNXI_NS_IMAGE_OFFSET	(SUNXI_DRAM_BASE + (160U << 20))
+
+#define CACHE_WRITEBACK_SHIFT		6
+#define CACHE_WRITEBACK_GRANULE		(1 << CACHE_WRITEBACK_SHIFT)
+
+#define MAX_MMAP_REGIONS		(4 + PLATFORM_MMAP_REGIONS)
+#define MAX_XLAT_TABLES			2
+
+#define PLAT_MAX_PWR_LVL_STATES		2
+#define PLAT_MAX_RET_STATE		1
+#define PLAT_MAX_OFF_STATE		2
+
+#define PLAT_MAX_PWR_LVL		2
+#define PLAT_NUM_PWR_DOMAINS		(1 + \
+					 PLATFORM_CLUSTER_COUNT + \
+					 PLATFORM_CORE_COUNT)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
+
+#define PLATFORM_CLUSTER_COUNT		1
+#define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER_COUNT * \
+					 PLATFORM_MAX_CPUS_PER_CLUSTER)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER	4
+#define PLATFORM_MMAP_REGIONS		4
+#define PLATFORM_STACK_SIZE		(0x1000 / PLATFORM_CORE_COUNT)
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/allwinner/common/include/sunxi_def.h b/plat/allwinner/common/include/sunxi_def.h
new file mode 100644
index 0000000..e68fbe4
--- /dev/null
+++ b/plat/allwinner/common/include/sunxi_def.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SUNXI_DEF_H__
+#define __SUNXI_DEF_H__
+
+/* Clock configuration */
+#define SUNXI_OSC24M_CLK_IN_HZ		24000000
+
+/* UART configuration */
+#define SUNXI_UART0_BAUDRATE		115200
+#define SUNXI_UART0_CLK_IN_HZ		SUNXI_OSC24M_CLK_IN_HZ
+
+#endif /* __SUNXI_DEF_H__ */
diff --git a/plat/allwinner/common/plat_helpers.S b/plat/allwinner/common/plat_helpers.S
new file mode 100644
index 0000000..b00c7ae
--- /dev/null
+++ b/plat/allwinner/common/plat_helpers.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <sunxi_def.h>
+#include <sunxi_mmap.h>
+
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_putc
+	.globl	plat_crash_console_flush
+	.globl	plat_my_core_pos
+	.globl	platform_mem_init
+	.globl	plat_report_exception
+
+func plat_crash_console_init
+	mov_imm x0, SUNXI_UART0_BASE
+	mov_imm x1, SUNXI_UART0_CLK_IN_HZ
+	mov_imm x2, SUNXI_UART0_BAUDRATE
+	b	console_16550_core_init
+endfunc plat_crash_console_init
+
+func plat_crash_console_putc
+	mov_imm x1, SUNXI_UART0_BASE
+	b	console_16550_core_putc
+endfunc plat_crash_console_putc
+
+func plat_crash_console_flush
+	ret
+endfunc plat_crash_console_flush
+
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	and	x1, x0, #MPIDR_CLUSTER_MASK
+	and	x0, x0, #MPIDR_CPU_MASK
+	add	x0, x0, x1, LSR #6
+	ret
+endfunc plat_my_core_pos
+
+func platform_mem_init
+	ret
+endfunc platform_mem_init
+
+func plat_report_exception
+	ret
+endfunc plat_report_exception
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
new file mode 100644
index 0000000..d1f1aa1
--- /dev/null
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <assert.h>
+#include <console.h>
+#include <debug.h>
+#include <generic_delay_timer.h>
+#include <gicv2.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <sunxi_def.h>
+#include <sunxi_mmap.h>
+#include <uart_16550.h>
+
+#include "sunxi_private.h"
+
+static entry_point_info_t bl33_image_ep_info;
+
+static console_16550_t console;
+
+static const gicv2_driver_data_t sunxi_gic_data = {
+	.gicd_base = SUNXI_GICD_BASE,
+	.gicc_base = SUNXI_GICC_BASE,
+};
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	/* Initialize the debug console as soon as possible */
+	console_16550_register(SUNXI_UART0_BASE, SUNXI_UART0_CLK_IN_HZ,
+			       SUNXI_UART0_BAUDRATE, &console);
+
+	/* Populate entry point information for BL33 */
+	SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+	/*
+	 * Tell BL31 where the non-trusted software image
+	 * is located and the entry state information
+	 */
+	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+	bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
+					  DISABLE_ALL_EXCEPTIONS);
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+	/* Turn off all secondary CPUs */
+	sunxi_disable_secondary_cpus(plat_my_core_pos());
+}
+
+void bl31_plat_arch_setup(void)
+{
+	sunxi_configure_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+	generic_delay_timer_init();
+
+	/* Configure the interrupt controller */
+	gicv2_driver_init(&sunxi_gic_data);
+	gicv2_distif_init();
+	gicv2_pcpu_distif_init();
+	gicv2_cpuif_enable();
+
+	sunxi_security_setup();
+
+	INFO("BL31: Platform setup done\n");
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	assert(sec_state_is_valid(type) != 0);
+	assert(type == NON_SECURE);
+
+	return &bl33_image_ep_info;
+}
diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c
new file mode 100644
index 0000000..e36c8b0
--- /dev/null
+++ b/plat/allwinner/common/sunxi_common.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform.h>
+#include <platform_def.h>
+#include <sunxi_def.h>
+#include <xlat_tables_v2.h>
+
+static mmap_region_t sunxi_mmap[PLATFORM_MMAP_REGIONS + 1] = {
+	MAP_REGION_FLAT(SUNXI_ROM_BASE, SUNXI_ROM_SIZE,
+			MT_MEMORY | MT_RO | MT_SECURE),
+	MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE,
+			MT_MEMORY | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(SUNXI_DRAM_BASE, SUNXI_DRAM_SIZE,
+			MT_MEMORY | MT_RW | MT_NS),
+	{},
+};
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return SUNXI_OSC24M_CLK_IN_HZ;
+}
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+	return PRELOADED_BL33_BASE;
+#else
+	return PLAT_SUNXI_NS_IMAGE_OFFSET;
+#endif
+}
+
+void sunxi_configure_mmu_el3(int flags)
+{
+	mmap_add_region(BL31_BASE, BL31_BASE,
+			BL31_LIMIT - BL31_BASE,
+			MT_MEMORY | MT_RW | MT_SECURE);
+	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+			BL_CODE_END - BL_CODE_BASE,
+			MT_CODE | MT_SECURE);
+	mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
+			BL_RO_DATA_END - BL_RO_DATA_BASE,
+			MT_RO_DATA | MT_SECURE);
+	mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
+			BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+			MT_DEVICE | MT_RW | MT_SECURE);
+	mmap_add(sunxi_mmap);
+	init_xlat_tables();
+
+	enable_mmu_el3(0);
+}
diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c
new file mode 100644
index 0000000..be72dee
--- /dev/null
+++ b/plat/allwinner/common/sunxi_cpu_ops.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <sunxi_mmap.h>
+#include <sunxi_cpucfg.h>
+#include <utils_def.h>
+
+#include "sunxi_private.h"
+
+static void sunxi_cpu_disable_power(unsigned int cluster, unsigned int core)
+{
+	if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff)
+		return;
+
+	INFO("PSCI: Disabling power to cluster %d core %d\n", cluster, core);
+
+	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xff);
+}
+
+static void sunxi_cpu_enable_power(unsigned int cluster, unsigned int core)
+{
+	if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0)
+		return;
+
+	INFO("PSCI: Enabling power to cluster %d core %d\n", cluster, core);
+
+	/* Power enable sequence from original Allwinner sources */
+	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xfe);
+	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xf8);
+	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0);
+	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80);
+	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00);
+}
+
+void sunxi_cpu_off(unsigned int cluster, unsigned int core)
+{
+	INFO("PSCI: Powering off cluster %d core %d\n", cluster, core);
+
+	/* Deassert DBGPWRDUP */
+	mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
+	/* Activate the core output clamps */
+	mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core));
+	/* Assert CPU power-on reset */
+	mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
+	/* Remove power from the CPU */
+	sunxi_cpu_disable_power(cluster, core);
+}
+
+void sunxi_cpu_on(unsigned int cluster, unsigned int core)
+{
+	INFO("PSCI: Powering on cluster %d core %d\n", cluster, core);
+
+	/* Assert CPU core reset */
+	mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
+	/* Assert CPU power-on reset */
+	mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
+	/* Set CPU to start in AArch64 mode */
+	mmio_setbits_32(SUNXI_CPUCFG_CLS_CTRL_REG0(cluster), BIT(24 + core));
+	/* Apply power to the CPU */
+	sunxi_cpu_enable_power(cluster, core);
+	/* Release the core output clamps */
+	mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core));
+	/* Deassert CPU power-on reset */
+	mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
+	/* Deassert CPU core reset */
+	mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
+	/* Assert DBGPWRDUP */
+	mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
+}
+
+void sunxi_disable_secondary_cpus(unsigned int primary_cpu)
+{
+	for (unsigned int cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu += 1) {
+		if (cpu == primary_cpu)
+			continue;
+		sunxi_cpu_off(cpu / PLATFORM_MAX_CPUS_PER_CLUSTER,
+			       cpu % PLATFORM_MAX_CPUS_PER_CLUSTER);
+	}
+}
diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c
new file mode 100644
index 0000000..fcab130
--- /dev/null
+++ b/plat/allwinner/common/sunxi_pm.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <gicv2.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <sunxi_mmap.h>
+#include <sunxi_cpucfg.h>
+
+#define SUNXI_WDOG0_CTRL_REG		(SUNXI_WDOG_BASE + 0x0010)
+#define SUNXI_WDOG0_CFG_REG		(SUNXI_WDOG_BASE + 0x0014)
+#define SUNXI_WDOG0_MODE_REG		(SUNXI_WDOG_BASE + 0x0018)
+
+#include "sunxi_private.h"
+
+#define mpidr_is_valid(mpidr) ( \
+	MPIDR_AFFLVL3_VAL(mpidr) == 0 && \
+	MPIDR_AFFLVL2_VAL(mpidr) == 0 && \
+	MPIDR_AFFLVL1_VAL(mpidr) < PLATFORM_CLUSTER_COUNT && \
+	MPIDR_AFFLVL0_VAL(mpidr) < PLATFORM_MAX_CPUS_PER_CLUSTER)
+
+static int sunxi_pwr_domain_on(u_register_t mpidr)
+{
+	if (mpidr_is_valid(mpidr) == 0)
+		return PSCI_E_INTERN_FAIL;
+
+	sunxi_cpu_on(MPIDR_AFFLVL1_VAL(mpidr), MPIDR_AFFLVL0_VAL(mpidr));
+
+	return PSCI_E_SUCCESS;
+}
+
+static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	gicv2_cpuif_disable();
+}
+
+static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	gicv2_pcpu_distif_init();
+	gicv2_cpuif_enable();
+}
+
+static void __dead2 sunxi_system_off(void)
+{
+	/* Turn off all secondary CPUs */
+	sunxi_disable_secondary_cpus(plat_my_core_pos());
+
+	ERROR("PSCI: Full shutdown not implemented, halting\n");
+	wfi();
+	panic();
+}
+
+static void __dead2 sunxi_system_reset(void)
+{
+	/* Reset the whole system when the watchdog times out */
+	mmio_write_32(SUNXI_WDOG0_CFG_REG, 1);
+	/* Enable the watchdog with the shortest timeout (0.5 seconds) */
+	mmio_write_32(SUNXI_WDOG0_MODE_REG, (0 << 4) | 1);
+	/* Wait for twice the watchdog timeout before panicking */
+	mdelay(1000);
+
+	ERROR("PSCI: System reset failed\n");
+	wfi();
+	panic();
+}
+
+static int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint)
+{
+	/* The non-secure entry point must be in DRAM */
+	if (ns_entrypoint >= SUNXI_DRAM_BASE &&
+	    ns_entrypoint < SUNXI_DRAM_BASE + SUNXI_DRAM_SIZE)
+		return PSCI_E_SUCCESS;
+
+	return PSCI_E_INVALID_ADDRESS;
+}
+
+static plat_psci_ops_t sunxi_psci_ops = {
+	.pwr_domain_on			= sunxi_pwr_domain_on,
+	.pwr_domain_off			= sunxi_pwr_domain_off,
+	.pwr_domain_on_finish		= sunxi_pwr_domain_on_finish,
+	.system_off			= sunxi_system_off,
+	.system_reset			= sunxi_system_reset,
+	.validate_ns_entrypoint		= sunxi_validate_ns_entrypoint,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	assert(psci_ops);
+
+	for (int cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu += 1) {
+		mmio_write_32(SUNXI_CPUCFG_RVBAR_LO_REG(cpu),
+			      sec_entrypoint & 0xffffffff);
+		mmio_write_32(SUNXI_CPUCFG_RVBAR_HI_REG(cpu),
+			      sec_entrypoint >> 32);
+	}
+
+	*psci_ops = &sunxi_psci_ops;
+
+	return 0;
+}
diff --git a/plat/allwinner/common/sunxi_private.h b/plat/allwinner/common/sunxi_private.h
new file mode 100644
index 0000000..b9f0fb4
--- /dev/null
+++ b/plat/allwinner/common/sunxi_private.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SUNXI_PRIVATE_H__
+#define __SUNXI_PRIVATE_H__
+
+void sunxi_configure_mmu_el3(int flags);
+void sunxi_cpu_off(unsigned int cluster, unsigned int core);
+void sunxi_cpu_on(unsigned int cluster, unsigned int core);
+void sunxi_disable_secondary_cpus(unsigned int primary_cpu);
+
+void sunxi_security_setup(void);
+
+#endif /* __SUNXI_PRIVATE_H__ */
diff --git a/plat/allwinner/common/sunxi_security.c b/plat/allwinner/common/sunxi_security.c
new file mode 100644
index 0000000..e760072
--- /dev/null
+++ b/plat/allwinner/common/sunxi_security.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <mmio.h>
+#include <sunxi_mmap.h>
+
+#ifdef SUNXI_SPC_BASE
+#define SPC_DECPORT_STA_REG(p)	(SUNXI_SPC_BASE + ((p) * 0x0c) + 0x4)
+#define SPC_DECPORT_SET_REG(p)	(SUNXI_SPC_BASE + ((p) * 0x0c) + 0x8)
+#define SPC_DECPORT_CLR_REG(p)	(SUNXI_SPC_BASE + ((p) * 0x0c) + 0xc)
+#endif
+
+#define R_PRCM_SEC_SWITCH_REG	0x1d0
+#define DMA_SEC_REG		0x20
+
+/*
+ * Setup the peripherals to be accessible by non-secure world.
+ * This will not work for the Secure Peripherals Controller (SPC) unless
+ * a fuse it burnt (seems to be an erratum), but we do it nevertheless,
+ * to allow booting on boards using secure boot.
+ */
+void sunxi_security_setup(void)
+{
+	int i;
+
+#ifdef SUNXI_SPC_BASE
+	INFO("Configuring SPC Controller\n");
+	/* SPC setup: set all devices to non-secure */
+	for (i = 0; i < 6; i++)
+		mmio_write_32(SPC_DECPORT_SET_REG(i), 0xff);
+#endif
+
+	/* set MBUS clocks, bus clocks (AXI/AHB/APB) and PLLs to non-secure */
+	mmio_write_32(SUNXI_CCU_SEC_SWITCH_REG, 0x7);
+
+	/* set R_PRCM clocks to non-secure */
+	mmio_write_32(SUNXI_R_PRCM_BASE + R_PRCM_SEC_SWITCH_REG, 0x7);
+
+	/* Set all DMA channels (16 max.) to non-secure */
+	mmio_write_32(SUNXI_DMA_BASE + DMA_SEC_REG, 0xffff);
+}
diff --git a/plat/allwinner/common/sunxi_topology.c b/plat/allwinner/common/sunxi_topology.c
new file mode 100644
index 0000000..98cf63c
--- /dev/null
+++ b/plat/allwinner/common/sunxi_topology.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <platform.h>
+#include <platform_def.h>
+
+static unsigned char plat_power_domain_tree_desc[PLAT_MAX_PWR_LVL + 1] = {
+	/* One root node for the SoC */
+	1,
+	/* One node for each cluster */
+	PLATFORM_CLUSTER_COUNT,
+	/* One set of CPUs per cluster */
+	PLATFORM_MAX_CPUS_PER_CLUSTER,
+};
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
+	unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
+
+	if (MPIDR_AFFLVL3_VAL(mpidr) > 0 ||
+	    MPIDR_AFFLVL2_VAL(mpidr) > 0 ||
+	    cluster >= PLATFORM_CLUSTER_COUNT ||
+	    core >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+		return -1;
+	}
+
+	return cluster * PLATFORM_MAX_CPUS_PER_CLUSTER + core;
+}
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return plat_power_domain_tree_desc;
+}
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
new file mode 100644
index 0000000..049c2ad
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SUNXI_CPUCFG_H__
+#define __SUNXI_CPUCFG_H__
+
+#include <sunxi_mmap.h>
+
+/* c = cluster, n = core */
+#define SUNXI_CPUCFG_CLS_CTRL_REG0(c)	(SUNXI_CPUCFG_BASE + 0x0000 + (c) * 16)
+#define SUNXI_CPUCFG_CLS_CTRL_REG1(c)	(SUNXI_CPUCFG_BASE + 0x0004 + (c) * 16)
+#define SUNXI_CPUCFG_CACHE_CFG_REG0	(SUNXI_CPUCFG_BASE + 0x0008)
+#define SUNXI_CPUCFG_CACHE_CFG_REG1	(SUNXI_CPUCFG_BASE + 0x000c)
+#define SUNXI_CPUCFG_DBG_REG0		(SUNXI_CPUCFG_BASE + 0x0020)
+#define SUNXI_CPUCFG_GLB_CTRL_REG	(SUNXI_CPUCFG_BASE + 0x0028)
+#define SUNXI_CPUCFG_CPU_STS_REG(c)	(SUNXI_CPUCFG_BASE + 0x0030 + (c) * 4)
+#define SUNXI_CPUCFG_L2_STS_REG		(SUNXI_CPUCFG_BASE + 0x003c)
+#define SUNXI_CPUCFG_RST_CTRL_REG(c)	(SUNXI_CPUCFG_BASE + 0x0080 + (c) * 4)
+#define SUNXI_CPUCFG_RVBAR_LO_REG(n)	(SUNXI_CPUCFG_BASE + 0x00a0 + (n) * 8)
+#define SUNXI_CPUCFG_RVBAR_HI_REG(n)	(SUNXI_CPUCFG_BASE + 0x00a4 + (n) * 8)
+
+#define SUNXI_CPU_POWER_CLAMP_REG(c, n)	(SUNXI_R_PRCM_BASE + 0x0140 + \
+					 (c) * 16 + (n) * 4)
+#define SUNXI_POWEROFF_GATING_REG(c)	(SUNXI_R_PRCM_BASE + 0x0100 + (c) * 4)
+#define SUNXI_R_CPUCFG_CPUS_RST_REG	(SUNXI_R_CPUCFG_BASE + 0x0000)
+#define SUNXI_POWERON_RST_REG(c)	(SUNXI_R_CPUCFG_BASE + 0x0030 + (c) * 4)
+#define SUNXI_R_CPUCFG_SYS_RST_REG	(SUNXI_R_CPUCFG_BASE + 0x0140)
+#define SUNXI_R_CPUCFG_SS_FLAG_REG	(SUNXI_R_CPUCFG_BASE + 0x01a0)
+#define SUNXI_R_CPUCFG_CPU_ENTRY_REG	(SUNXI_R_CPUCFG_BASE + 0x01a4)
+#define SUNXI_R_CPUCFG_SS_ENTRY_REG	(SUNXI_R_CPUCFG_BASE + 0x01a8)
+#define SUNXI_R_CPUCFG_HP_FLAG_REG	(SUNXI_R_CPUCFG_BASE + 0x01ac)
+
+#endif /* __SUNXI_CPUCFG_H__ */
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
new file mode 100644
index 0000000..cb202a8
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SUNXI_MMAP_H__
+#define __SUNXI_MMAP_H__
+
+/* Memory regions */
+#define SUNXI_ROM_BASE			0x00000000
+#define SUNXI_ROM_SIZE			0x00010000
+#define SUNXI_SRAM_BASE			0x00010000
+#define SUNXI_SRAM_SIZE			0x00044000
+#define SUNXI_SRAM_A1_BASE		0x00010000
+#define SUNXI_SRAM_A1_SIZE		0x00008000
+#define SUNXI_SRAM_A2_BASE		0x00044000
+#define SUNXI_SRAM_A2_SIZE		0x00010000
+#define SUNXI_SRAM_C_BASE		0x00018000
+#define SUNXI_SRAM_C_SIZE		0x0001c000
+#define SUNXI_DEV_BASE			0x01000000
+#define SUNXI_DEV_SIZE			0x01000000
+#define SUNXI_DRAM_BASE			0x40000000
+#define SUNXI_DRAM_SIZE			0x80000000
+
+/* Memory-mapped devices */
+#define SUNXI_CPU_MBIST_BASE		0x01502000
+#define SUNXI_CPUCFG_BASE		0x01700000
+#define SUNXI_SYSCON_BASE		0x01c00000
+#define SUNXI_SRAM_VER_REG		(SUNXI_SYSCON_BASE + 0x24)
+#define SUNXI_DMA_BASE			0x01c02000
+#define SUNXI_KEYMEM_BASE		0x01c0b000
+#define SUNXI_SMHC0_BASE		0x01c0f000
+#define SUNXI_SMHC1_BASE		0x01c10000
+#define SUNXI_SMHC2_BASE		0x01c11000
+#define SUNXI_SID_BASE			0x01c14000
+#define SUNXI_MSGBOX_BASE		0x01c17000
+#define SUNXI_SPINLOCK_BASE		0x01c18000
+#define SUNXI_CCU_BASE			0x01c20000
+#define SUNXI_CCU_SEC_SWITCH_REG	(SUNXI_CCU_BASE + 0x2f0)
+#define SUNXI_PIO_BASE			0x01c20800
+#define SUNXI_TIMER_BASE		0x01c20c00
+#define SUNXI_WDOG_BASE			0x01c20ca0
+#define SUNXI_SPC_BASE			0x01c23400
+#define SUNXI_THS_BASE			0x01c25000
+#define SUNXI_UART0_BASE		0x01c28000
+#define SUNXI_UART1_BASE		0x01c28400
+#define SUNXI_UART2_BASE		0x01c28800
+#define SUNXI_UART3_BASE		0x01c28c00
+#define SUNXI_I2C0_BASE			0x01c2ac00
+#define SUNXI_I2C1_BASE			0x01c2b000
+#define SUNXI_I2C2_BASE			0x01c2b400
+#define SUNXI_DRAMCOM_BASE		0x01c62000
+#define SUNXI_DRAMCTL_BASE		0x01c63000
+#define SUNXI_DRAMPHY_BASE		0x01c65000
+#define SUNXI_SPI0_BASE			0x01c68000
+#define SUNXI_SPI1_BASE			0x01c69000
+#define SUNXI_SCU_BASE			0x01c80000
+#define SUNXI_GICD_BASE			0x01c81000
+#define SUNXI_GICC_BASE			0x01c82000
+#define SUNXI_RTC_BASE			0x01f00000
+#define SUNXI_R_TIMER_BASE		0x01f00800
+#define SUNXI_R_INTC_BASE		0x01f00c00
+#define SUNXI_R_WDOG_BASE		0x01f01000
+#define SUNXI_R_PRCM_BASE		0x01f01400
+#define SUNXI_R_TWD_BASE		0x01f01800
+#define SUNXI_R_CPUCFG_BASE		0x01f01c00
+#define SUNXI_R_CIR_BASE		0x01f02000
+#define SUNXI_R_I2C_BASE		0x01f02400
+#define SUNXI_R_UART_BASE		0x01f02800
+#define SUNXI_R_PIO_BASE		0x01f02c00
+#define SUNXI_R_RSB_BASE		0x01f03400
+#define SUNXI_R_PWM_BASE		0x01f03800
+
+#endif /* __SUNXI_MMAP_H__ */
diff --git a/plat/allwinner/sun50i_a64/platform.mk b/plat/allwinner/sun50i_a64/platform.mk
new file mode 100644
index 0000000..236464f
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/platform.mk
@@ -0,0 +1,59 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+AW_PLAT			:=	plat/allwinner
+
+PLAT_INCLUDES		:=	-Iinclude/plat/arm/common/		\
+				-Iinclude/plat/arm/common/aarch64	\
+				-I${AW_PLAT}/common/include		\
+				-I${AW_PLAT}/${PLAT}/include
+
+PLAT_BL_COMMON_SOURCES	:=	drivers/console/${ARCH}/console.S	\
+				drivers/ti/uart/${ARCH}/16550_console.S	\
+				${XLAT_TABLES_LIB_SRCS}			\
+				${AW_PLAT}/common/plat_helpers.S	\
+				${AW_PLAT}/common/sunxi_common.c
+
+BL31_SOURCES		+=	drivers/arm/gic/common/gic_common.c	\
+				drivers/arm/gic/v2/gicv2_helpers.c	\
+				drivers/arm/gic/v2/gicv2_main.c		\
+				drivers/delay_timer/delay_timer.c	\
+				drivers/delay_timer/generic_delay_timer.c \
+				lib/cpus/${ARCH}/cortex_a53.S		\
+				plat/common/plat_gicv2.c		\
+				plat/common/plat_psci_common.c		\
+				${AW_PLAT}/common/sunxi_bl31_setup.c	\
+				${AW_PLAT}/common/sunxi_cpu_ops.c	\
+				${AW_PLAT}/common/sunxi_pm.c		\
+				${AW_PLAT}/common/sunxi_security.c	\
+				${AW_PLAT}/common/sunxi_topology.c
+
+# The bootloader is guaranteed to only run on CPU 0 by the boot ROM.
+COLD_BOOT_SINGLE_CPU		:=	1
+
+# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4.
+ERRATA_A53_835769		:=	1
+ERRATA_A53_843419		:=	1
+ERRATA_A53_855873		:=	1
+
+# Disable the PSCI platform compatibility layer.
+ENABLE_PLAT_COMPAT		:= 	0
+
+MULTI_CONSOLE_API		:=	1
+
+# Prohibit using deprecated interfaces. We rely on this for this platform.
+ERROR_DEPRECATED		:=	1
+
+# The reset vector can be changed for each CPU.
+PROGRAMMABLE_RESET_ADDRESS	:=	1
+
+# Allow mapping read-only data as execute-never.
+SEPARATE_CODE_AND_RODATA	:=	1
+
+# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL
+RESET_TO_BL31			:=	1
diff --git a/plat/arm/common/aarch64/arm_helpers.S b/plat/arm/common/aarch64/arm_helpers.S
index 760a53a..752929d 100644
--- a/plat/arm/common/aarch64/arm_helpers.S
+++ b/plat/arm/common/aarch64/arm_helpers.S
@@ -8,9 +8,9 @@
 
 	.weak	plat_arm_calc_core_pos
 	.weak	plat_my_core_pos
-	.globl	plat_crash_console_init
-	.globl	plat_crash_console_putc
-	.globl	plat_crash_console_flush
+	.weak	plat_crash_console_init
+	.weak	plat_crash_console_putc
+	.weak	plat_crash_console_flush
 	.globl	platform_mem_init
 
 
@@ -50,7 +50,7 @@
 	mov_imm	x0, PLAT_ARM_CRASH_UART_BASE
 	mov_imm	x1, PLAT_ARM_CRASH_UART_CLK_IN_HZ
 	mov_imm	x2, ARM_CONSOLE_BAUDRATE
-	b	console_core_init
+	b	console_pl011_core_init
 endfunc plat_crash_console_init
 
 	/* ---------------------------------------------
@@ -62,7 +62,7 @@
 	 */
 func plat_crash_console_putc
 	mov_imm	x1, PLAT_ARM_CRASH_UART_BASE
-	b	console_core_putc
+	b	console_pl011_core_putc
 endfunc plat_crash_console_putc
 
 	/* ---------------------------------------------
@@ -75,7 +75,7 @@
 	 */
 func plat_crash_console_flush
 	mov_imm	x0, PLAT_ARM_CRASH_UART_BASE
-	b	console_core_flush
+	b	console_pl011_core_flush
 endfunc plat_crash_console_flush
 
 	/* ---------------------------------------------------------------------
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 379e87d..e5e7304 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -9,7 +9,6 @@
 #include <arm_xlat_tables.h>
 #include <bl1.h>
 #include <bl_common.h>
-#include <console.h>
 #include <plat_arm.h>
 #include <platform.h>
 #include <platform_def.h>
@@ -45,8 +44,7 @@
 #endif
 
 	/* Initialize the console to provide early debug support */
-	console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
-			ARM_CONSOLE_BAUDRATE);
+	arm_console_boot_init();
 
 	/* Allow BL1 to see the whole Trusted RAM */
 	bl1_tzram_layout.total_base = ARM_BL_RAM_BASE;
diff --git a/plat/arm/common/arm_bl2_el3_setup.c b/plat/arm/common/arm_bl2_el3_setup.c
index e70d115..e7247c6 100644
--- a/plat/arm/common/arm_bl2_el3_setup.c
+++ b/plat/arm/common/arm_bl2_el3_setup.c
@@ -1,9 +1,8 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
-#include <console.h>
 #include <generic_delay_timer.h>
 #include <plat_arm.h>
 #include <platform.h>
@@ -21,8 +20,7 @@
 void arm_bl2_el3_early_platform_setup(void)
 {
 	/* Initialize the console to provide early debug support */
-	console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
-			ARM_CONSOLE_BAUDRATE);
+	arm_console_boot_init();
 
 	/*
 	 * Allow BL2 to see the whole Trusted RAM. This is determined
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 4ef3a9b..3aa99f8 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -8,7 +8,6 @@
 #include <arm_def.h>
 #include <assert.h>
 #include <bl_common.h>
-#include <console.h>
 #include <debug.h>
 #include <desc_image_load.h>
 #include <generic_delay_timer.h>
@@ -176,8 +175,7 @@
 void arm_bl2_early_platform_setup(uintptr_t tb_fw_config, meminfo_t *mem_layout)
 {
 	/* Initialize the console to provide early debug support */
-	console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
-			ARM_CONSOLE_BAUDRATE);
+	arm_console_boot_init();
 
 	/* Setup the BL2 memory layout */
 	bl2_tzram_layout = *mem_layout;
diff --git a/plat/arm/common/arm_bl2u_setup.c b/plat/arm/common/arm_bl2u_setup.c
index 3b8e4aa..cd691e5 100644
--- a/plat/arm/common/arm_bl2u_setup.c
+++ b/plat/arm/common/arm_bl2u_setup.c
@@ -7,7 +7,6 @@
 #include <arch_helpers.h>
 #include <arm_def.h>
 #include <bl_common.h>
-#include <console.h>
 #include <generic_delay_timer.h>
 #include <plat_arm.h>
 #include <platform_def.h>
@@ -36,8 +35,8 @@
 void arm_bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info)
 {
 	/* Initialize the console to provide early debug support */
-	console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
-			ARM_CONSOLE_BAUDRATE);
+	arm_console_boot_init();
+
 	generic_delay_timer_init();
 }
 
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index 46f7ae0..6346f0f 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -78,8 +78,7 @@
 #endif
 {
 	/* Initialize the console to provide early debug support */
-	console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ,
-			ARM_CONSOLE_BAUDRATE);
+	arm_console_boot_init();
 
 #if RESET_TO_BL31
 	/* There are no parameters from BL2 if BL31 is a reset vector */
@@ -249,12 +248,18 @@
 /*******************************************************************************
  * Perform any BL31 platform runtime setup prior to BL31 exit common to ARM
  * standard platforms
+ * Perform BL31 platform setup
  ******************************************************************************/
 void arm_bl31_plat_runtime_setup(void)
 {
+#if MULTI_CONSOLE_API
+	console_switch_state(CONSOLE_FLAG_RUNTIME);
+#else
+	console_uninit();
+#endif
+
 	/* Initialize the runtime console */
-	console_init(PLAT_ARM_BL31_RUN_UART_BASE, PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ,
-			ARM_CONSOLE_BAUDRATE);
+	arm_console_runtime_init();
 }
 
 void bl31_platform_setup(void)
diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c
index 11bdeac..32fd9ee 100644
--- a/plat/arm/common/arm_common.c
+++ b/plat/arm/common/arm_common.c
@@ -160,6 +160,9 @@
 {
 	unsigned int reg_val;
 
+	/* Read the frequency of the system counter */
+	unsigned int freq_val = plat_get_syscnt_freq2();
+
 #if ARM_CONFIG_CNTACR
 	reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT);
 	reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT);
@@ -169,6 +172,23 @@
 
 	reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_ARM_NSTIMER_FRAME_ID));
 	mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTNSAR, reg_val);
+
+	/*
+	 * Initialize CNTFRQ register in CNTCTLBase frame. The CNTFRQ
+	 * system register initialized during psci_arch_setup() is different
+	 * from this and has to be updated independently.
+	 */
+	mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTCTLBASE_CNTFRQ, freq_val);
+
+#ifdef PLAT_juno
+	/*
+	 * Initialize CNTFRQ register in Non-secure CNTBase frame.
+	 * This is only required for Juno, because it doesn't follow ARM ARM
+	 * in that the value updated in CNTFRQ is not reflected in CNTBASE_CNTFRQ.
+	 * Hence update the value manually.
+	 */
+	mmio_write_32(ARM_SYS_CNT_BASE_NS + CNTBASE_CNTFRQ, freq_val);
+#endif
 }
 #endif /* ARM_SYS_TIMCTL_BASE */
 
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 4b23ac6..76a75d3 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -125,6 +125,11 @@
 # Enable new version of image loading on ARM platforms
 LOAD_IMAGE_V2			:=	1
 
+# Use the multi console API, which is only available for AArch64 for now
+ifeq (${ARCH}, aarch64)
+  MULTI_CONSOLE_API		:=	1
+endif
+
 # Use generic OID definition (tbbr_oid.h)
 USE_TBBR_DEFS			:=	1
 
@@ -141,7 +146,8 @@
 endif
 
 PLAT_BL_COMMON_SOURCES	+=	plat/arm/common/${ARCH}/arm_helpers.S		\
-				plat/arm/common/arm_common.c
+				plat/arm/common/arm_common.c			\
+				plat/arm/common/arm_console.c
 
 ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
 PLAT_BL_COMMON_SOURCES	+=	lib/xlat_tables/xlat_tables_common.c		\
diff --git a/plat/arm/common/arm_console.c b/plat/arm/common/arm_console.c
new file mode 100644
index 0000000..6c8587f
--- /dev/null
+++ b/plat/arm/common/arm_console.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+#include <console.h>
+#include <debug.h>
+#include <pl011.h>
+#include <plat_arm.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Functions that set up the console
+ ******************************************************************************/
+#if MULTI_CONSOLE_API
+static console_pl011_t arm_boot_console;
+static console_pl011_t arm_runtime_console;
+#endif
+
+/* Initialize the console to provide early debug support */
+void arm_console_boot_init(void)
+{
+#if MULTI_CONSOLE_API
+	int rc = console_pl011_register(PLAT_ARM_BOOT_UART_BASE,
+					PLAT_ARM_BOOT_UART_CLK_IN_HZ,
+					ARM_CONSOLE_BAUDRATE,
+					&arm_boot_console);
+	if (rc == 0) {
+		/*
+		 * The crash console doesn't use the multi console API, it uses
+		 * the core console functions directly. It is safe to call panic
+		 * and let it print debug information.
+		 */
+		panic();
+	}
+
+	console_set_scope(&arm_boot_console.console, CONSOLE_FLAG_BOOT);
+#else
+	(void)console_init(PLAT_ARM_BOOT_UART_BASE,
+			   PLAT_ARM_BOOT_UART_CLK_IN_HZ,
+			   ARM_CONSOLE_BAUDRATE);
+#endif /* MULTI_CONSOLE_API */
+}
+
+void arm_console_boot_end(void)
+{
+	(void)console_flush();
+
+#if MULTI_CONSOLE_API
+	(void)console_unregister(&arm_boot_console.console);
+#else
+	console_uninit();
+#endif /* MULTI_CONSOLE_API */
+}
+
+/* Initialize the runtime console */
+void arm_console_runtime_init(void)
+{
+#if MULTI_CONSOLE_API
+	int rc = console_pl011_register(PLAT_ARM_BL31_RUN_UART_BASE,
+					PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ,
+					ARM_CONSOLE_BAUDRATE,
+					&arm_runtime_console);
+	if (rc == 0)
+		panic();
+
+	console_set_scope(&arm_runtime_console.console, CONSOLE_FLAG_RUNTIME);
+#else
+	(void)console_init(PLAT_ARM_BL31_RUN_UART_BASE,
+			   PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ,
+			   ARM_CONSOLE_BAUDRATE);
+#endif /* MULTI_CONSOLE_API */
+}
+
+void arm_console_runtime_end(void)
+{
+	(void)console_flush();
+
+#if MULTI_CONSOLE_API
+	(void)console_unregister(&arm_runtime_console.console);
+#else
+	console_uninit();
+#endif /* MULTI_CONSOLE_API */
+}
diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c
index 32a515b..118bd26 100644
--- a/plat/arm/common/arm_dyn_cfg.c
+++ b/plat/arm/common/arm_dyn_cfg.c
@@ -61,8 +61,8 @@
 
 	err = arm_dyn_tb_fw_cfg_init((void *)config_base, &tb_fw_node);
 	if (err < 0) {
-		WARN("Invalid TB_FW_CONFIG loaded\n");
-		return;
+		ERROR("Invalid TB_FW_CONFIG loaded\n");
+		panic();
 	}
 
 	err = arm_dyn_get_disable_auth((void *)config_base, tb_fw_node, &disable_auth);
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index 44ac5b5..4632099 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,7 +8,6 @@
 #include <arm_def.h>
 #include <arm_gic.h>
 #include <assert.h>
-#include <console.h>
 #include <errno.h>
 #include <plat_arm.h>
 #include <platform.h>
@@ -160,6 +159,12 @@
 	plat_arm_gic_save();
 
 	/*
+	 * Unregister console now so that it is not registered for a second
+	 * time during resume.
+	 */
+	arm_console_runtime_end();
+
+	/*
 	 * All the other peripheral which are configured by ARM TF are
 	 * re-initialized on resume from system suspend. Hence we
 	 * don't save their state here.
@@ -174,8 +179,8 @@
  *****************************************************************************/
 void arm_system_pwr_domain_resume(void)
 {
-	console_init(PLAT_ARM_BL31_RUN_UART_BASE, PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ,
-						ARM_CONSOLE_BAUDRATE);
+	/* Initialize the console */
+	arm_console_runtime_init();
 
 	/* Assert system power domain is available on the platform */
 	assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2);
diff --git a/plat/arm/common/tsp/arm_tsp_setup.c b/plat/arm/common/tsp/arm_tsp_setup.c
index abeaea0..16125ad 100644
--- a/plat/arm/common/tsp/arm_tsp_setup.c
+++ b/plat/arm/common/tsp/arm_tsp_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,6 +7,8 @@
 #include <arm_def.h>
 #include <bl_common.h>
 #include <console.h>
+#include <debug.h>
+#include <pl011.h>
 #include <plat_arm.h>
 #include <platform_def.h>
 #include <platform_tsp.h>
@@ -22,14 +24,30 @@
 /*******************************************************************************
  * Initialize the UART
  ******************************************************************************/
+#if MULTI_CONSOLE_API
+static console_pl011_t arm_tsp_runtime_console;
+#endif
+
 void arm_tsp_early_platform_setup(void)
 {
+#if MULTI_CONSOLE_API
 	/*
 	 * Initialize a different console than already in use to display
 	 * messages from TSP
 	 */
+	int rc = console_pl011_register(PLAT_ARM_TSP_UART_BASE,
+					PLAT_ARM_TSP_UART_CLK_IN_HZ,
+					ARM_CONSOLE_BAUDRATE,
+					&arm_tsp_runtime_console);
+	if (rc == 0)
+		panic();
+
+	console_set_scope(&arm_tsp_runtime_console.console,
+			  CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
+#else
 	console_init(PLAT_ARM_TSP_UART_BASE, PLAT_ARM_TSP_UART_CLK_IN_HZ,
 			ARM_CONSOLE_BAUDRATE);
+#endif /* MULTI_CONSOLE_API */
 }
 
 void tsp_early_platform_setup(void)
diff --git a/plat/arm/css/sgi/fdts/sgi575.dts b/plat/arm/css/sgi/fdts/sgi575.dts
new file mode 100644
index 0000000..be9920c
--- /dev/null
+++ b/plat/arm/css/sgi/fdts/sgi575.dts
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+	/* compatible string */
+	compatible = "arm,sgi575";
+};
diff --git a/plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts b/plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts
new file mode 100644
index 0000000..0bb0a94
--- /dev/null
+++ b/plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+	/* Platform Config */
+	compatible = "arm,tb_fw";
+	hw_config_addr = <0x0 0xFEF00000>;
+	hw_config_max_size = <0x0100000>;
+};
diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk
index f6ef95a..f4092f3 100644
--- a/plat/arm/css/sgi/sgi-common.mk
+++ b/plat/arm/css/sgi/sgi-common.mk
@@ -30,7 +30,8 @@
 				${CSS_ENT_BASE}/sgi_bl1_setup.c	\
 				${CSS_ENT_BASE}/sgi_plat_config.c
 
-BL2_SOURCES		+=	${CSS_ENT_BASE}/sgi_security.c
+BL2_SOURCES		+=	${CSS_ENT_BASE}/sgi_security.c		\
+				${CSS_ENT_BASE}/sgi_image_load.c
 
 BL31_SOURCES		+=	${ENT_CPU_SOURCES}			\
 				${INTERCONNECT_SOURCES}			\
@@ -39,6 +40,19 @@
 				${CSS_ENT_BASE}/sgi_topology.c	\
 				${CSS_ENT_BASE}/sgi_plat_config.c
 
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES		+=	${CSS_ENT_BASE}/fdts/${PLAT}_tb_fw_config.dts
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
+
+FDT_SOURCES		+=	${CSS_ENT_BASE}/fdts/${PLAT}.dts
+HW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}.dtb
+
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config))
+
 $(eval $(call add_define,SGI_PLAT))
 
 override CSS_LOAD_SCP_IMAGES	:=	0
diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c
index 0928b83..2090846 100644
--- a/plat/arm/css/sgi/sgi_bl31_setup.c
+++ b/plat/arm/css/sgi/sgi_bl31_setup.c
@@ -12,23 +12,8 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
-	uint32_t plat_version;
-	bl_params_node_t *bl_params;
-
-	bl_params = ((bl_params_t *)arg0)->head;
-
 	/* Initialize the platform configuration structure */
 	plat_config_init();
 
-	while (bl_params) {
-		if (bl_params->image_id == BL33_IMAGE_ID) {
-			plat_version = mmio_read_32(SSC_VERSION);
-			bl_params->ep_info->args.arg2 = plat_version;
-			break;
-		}
-
-		bl_params = bl_params->next_params_info;
-	}
-
 	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
 }
diff --git a/plat/arm/css/sgi/sgi_image_load.c b/plat/arm/css/sgi/sgi_image_load.c
new file mode 100644
index 0000000..dda5e96
--- /dev/null
+++ b/plat/arm/css/sgi/sgi_image_load.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <desc_image_load.h>
+#include <libfdt.h>
+#include <platform.h>
+
+/*******************************************************************************
+ * This function inserts Platform information via device tree nodes as,
+ * system-id {
+ *    platform-id = <0>;
+ * }
+ ******************************************************************************/
+static int plat_sgi_append_config_node(void)
+{
+	bl_mem_params_node_t *mem_params;
+	void *fdt;
+	int nodeoffset, err;
+	unsigned int platid = 0;
+	char *platform_name;
+
+	mem_params = get_bl_mem_params_node(HW_CONFIG_ID);
+	if (mem_params == NULL) {
+		ERROR("HW CONFIG base address is NULL");
+		return -1;
+	}
+
+	fdt = (void *)(mem_params->image_info.image_base);
+
+	/* Check the validity of the fdt */
+	if (fdt_check_header(fdt) != 0) {
+		ERROR("Invalid HW_CONFIG DTB passed\n");
+		return -1;
+	}
+
+	platform_name = (char *)fdt_getprop(fdt, 0, "compatible", NULL);
+
+	if (strcmp(platform_name, "arm,sgi575") == 0) {
+		platid = mmio_read_32(SSC_VERSION);
+	} else {
+		WARN("Invalid platform \n");
+		return -1;
+	}
+
+	/* Increase DTB blob by 512 byte */
+	err = fdt_open_into(fdt, fdt, mem_params->image_info.image_size + 512);
+	if (err < 0) {
+		ERROR("Failed to open HW_CONFIG DTB\n");
+		return -1;
+	}
+
+	/* Create "/system-id" node */
+	nodeoffset = fdt_add_subnode(fdt, 0, "system-id");
+	if (nodeoffset < 0) {
+		ERROR("Failed to add node system-id\n");
+		return -1;
+	}
+
+	err = fdt_setprop_u32(fdt, nodeoffset, "platform-id", platid);
+	if (err < 0) {
+		ERROR("Failed to add node platform-id\n");
+		return -1;
+	}
+	return 0;
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+	int ret;
+	bl_params_t *next_bl_params;
+
+	ret = plat_sgi_append_config_node();
+	if (ret != 0)
+		panic();
+
+	next_bl_params = get_next_bl_params_from_mem_params_desc();
+	populate_next_bl_params_config(next_bl_params);
+
+	return next_bl_params;
+}
diff --git a/plat/arm/css/sgi/sgi_plat.c b/plat/arm/css/sgi/sgi_plat.c
index 94d713d..7e1d4e2 100644
--- a/plat/arm/css/sgi/sgi_plat.c
+++ b/plat/arm/css/sgi/sgi_plat.c
@@ -72,50 +72,3 @@
 #endif
 
 ARM_CASSERT_MMAP
-
-/*
- * Set up the page tables for the generic and platform-specific memory regions.
- * The extents of the generic memory regions are specified by the function
- * arguments and consist of:
- * - Trusted SRAM seen by the BL image;
- * - Code section;
- * - Read-only data section;
- * - Coherent memory region, if applicable.
- */
-
-#if IMAGE_BL1
-void bl1_plat_arch_setup(void)
-{
-	arm_setup_page_tables(ARM_BL_RAM_BASE,
-			      ARM_BL_RAM_SIZE,
-			      BL_CODE_BASE,
-			      BL1_CODE_END,
-			      BL1_RO_DATA_BASE,
-			      BL1_RO_DATA_END
-#if USE_COHERENT_MEM
-			      , BL1_COHERENT_RAM_BASE,
-			      BL1_COHERENT_RAM_LIMIT
-#endif /* USE_COHERENT_MEM */
-			     );
-
-	enable_mmu_el3(0);
-}
-#endif /* IMAGE_BL1 */
-
-#if IMAGE_BL2
-void bl2_plat_arch_setup(void)
-{
-	arm_setup_page_tables(BL2_BASE,
-			      BL2_LIMIT-BL2_BASE,
-			      BL_CODE_BASE,
-			      BL_CODE_END,
-			      BL_RO_DATA_BASE,
-			      BL_RO_DATA_END
-#if USE_COHERENT_MEM
-			      , BL2_COHERENT_RAM_BASE,
-			      BL2_COHERENT_RAM_LIMIT
-#endif /* USE_COHERENT_MEM */
-			      );
-	enable_mmu_el1(0);
-}
-#endif /* IMAGE_BL2 */
diff --git a/plat/common/plat_bl1_common.c b/plat/common/plat_bl1_common.c
index 4b1f233..c5bbe74 100644
--- a/plat/common/plat_bl1_common.c
+++ b/plat/common/plat_bl1_common.c
@@ -107,7 +107,8 @@
 #if LOAD_IMAGE_V2
 	bl2_tzram_layout = (meminfo_t *) bl1_tzram_layout->total_base;
 #else
-	bl2_tzram_layout = (meminfo_t *) bl1_tzram_layout->free_base;
+	bl2_tzram_layout = (meminfo_t *) round_up(bl1_tzram_layout->free_base,
+						  sizeof(uint64_t));
 #endif /* LOAD_IMAGE_V2 */
 
 #if !ERROR_DEPRECATED
diff --git a/plat/imx/common/imx8_helpers.S b/plat/imx/common/imx8_helpers.S
new file mode 100644
index 0000000..b89d346
--- /dev/null
+++ b/plat/imx/common/imx8_helpers.S
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <platform_def.h>
+#include <cortex_a35.h>
+
+	.globl	plat_is_my_cpu_primary
+	.globl	plat_my_core_pos
+	.globl	plat_calc_core_pos
+	.globl	plat_reset_handler
+	.globl	plat_get_my_entrypoint
+	.globl	plat_secondary_cold_boot_setup
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_putc
+	.globl	platform_mem_init
+	.globl  imx_mailbox_init
+
+	/* --------------------------------------------------------------------
+	 * Helper macro that reads the part number of the current CPU and jumps
+	 * to the given label if it matches the CPU MIDR provided.
+	 *
+	 * Clobbers x0.
+	 * --------------------------------------------------------------------
+	 */
+	.macro  jump_if_cpu_midr _cpu_midr, _label
+
+	mrs	x0, midr_el1
+	ubfx	x0, x0, MIDR_PN_SHIFT, #12
+	cmp     w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+	b.eq	\_label
+
+	.endm
+
+	/* ----------------------------------------------
+	 * The mailbox_base is used to distinguish warm/cold
+	 * reset. The mailbox_base is in the data section, not
+	 * in .bss, this allows function to start using this
+	 * variable before the runtime memory is initialized.
+	 * ----------------------------------------------
+	 */
+	.section .data.mailbox_base
+	.align 3
+	mailbox_base: .quad 0x0
+
+	/* ----------------------------------------------
+	 * unsigned int plat_is_my_cpu_primary(void);
+	 * This function checks if this is the primary CPU
+	 * ----------------------------------------------
+	 */
+func plat_is_my_cpu_primary
+	mrs	x0, mpidr_el1
+	and	x0, x0, #(MPIDR_CPU_MASK)
+	cmp	x0, #PLAT_PRIMARY_CPU
+	cset	x0, eq
+	ret
+endfunc plat_is_my_cpu_primary
+
+	/* ----------------------------------------------
+	 * unsigned int plat_my_core_pos(void)
+	 * This Function uses the plat_calc_core_pos()
+	 * to get the index of the calling CPU.
+	 * ----------------------------------------------
+	 */
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	and	x1, x0, #MPIDR_CPU_MASK
+	and 	x0, x0, #MPIDR_CLUSTER_MASK
+	add	x0, x1, x0, LSR #6
+	ret
+endfunc plat_my_core_pos
+
+	/*
+	 * unsigned int plat_calc_core_pos(uint64_t mpidr)
+	 * helper function to calculate the core position.
+	 * With this function.
+	 */
+func plat_calc_core_pos
+	and	x1, x0, #MPIDR_CPU_MASK
+	and 	x0, x0, #MPIDR_CLUSTER_MASK
+	add	x0, x1, x0, LSR #6
+	ret
+endfunc plat_calc_core_pos
+
+	/* ---------------------------------------------
+	 * function to get the entrypoint.
+	 * ---------------------------------------------
+	 */
+func plat_get_my_entrypoint
+	adrp	x1, mailbox_base
+	ldr	x0, [x1, :lo12:mailbox_base]
+	ret
+endfunc	plat_get_my_entrypoint
+
+func imx_mailbox_init
+	adrp	x1, mailbox_base
+	str	x0, [x1, :lo12:mailbox_base]
+	ret
+endfunc imx_mailbox_init
+
+func plat_secondary_cold_boot_setup
+	b	.
+endfunc plat_secondary_cold_boot_setup
+
+func plat_crash_console_init
+	ret
+endfunc plat_crash_console_init
+
+func plat_crash_console_putc
+	ret
+endfunc plat_crash_console_putc
+
+func platform_mem_init
+	ret
+endfunc platform_mem_init
diff --git a/plat/imx/common/imx8_topology.c b/plat/imx/common/imx8_topology.c
new file mode 100644
index 0000000..bcb7d59
--- /dev/null
+++ b/plat/imx/common/imx8_topology.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <platform.h>
+
+const unsigned char imx_power_domain_tree_desc[] = {
+	PWR_DOMAIN_AT_MAX_LVL,
+	PLATFORM_CLUSTER_COUNT,
+	PLATFORM_CORE_COUNT,
+};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return imx_power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	unsigned int cluster_id, cpu_id;
+
+	mpidr &= MPIDR_AFFINITY_MASK;
+
+	if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+		return -1;
+
+	cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+	cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+	if (cluster_id > PLATFORM_CLUSTER_COUNT ||
+		cpu_id > PLATFORM_MAX_CPU_PER_CLUSTER)
+		return -1;
+
+	return (cpu_id + (cluster_id * 4));
+}
diff --git a/plat/imx/common/include/imx8_iomux.h b/plat/imx/common/include/imx8_iomux.h
new file mode 100644
index 0000000..7a7f549
--- /dev/null
+++ b/plat/imx/common/include/imx8_iomux.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __IMX8_IOMUX_H__
+#define __IMX8_IOMUX_H__
+
+#define PADRING_IFMUX_EN_SHIFT		31
+#define PADRING_IFMUX_EN_MASK		(1 << PADRING_IFMUX_EN_SHIFT)
+#define PADRING_GP_EN_SHIFT		30
+#define PADRING_GP_EN_MASK		(1 << PADRING_GP_EN_SHIFT)
+#define PADRING_IFMUX_SHIFT		27
+#define PADRING_IFMUX_MASK		(0x7 << PADRING_IFMUX_SHIFT)
+#define PADRING_CONFIG_SHIFT		25
+#define PADRING_CONFIG_MASK		(0x3 << PADRING_CONFIG_SHIFT)
+#define PADRING_LPCONFIG_SHIFT		23
+#define PADRING_LPCONFIG_MASK		(0x3 << PADRING_LPCONFIG_SHIFT)
+#define PADRING_PULL_SHIFT		5
+#define PADRING_PULL_MASK		(0x3 << PADRING_PULL_SHIFT)
+#define PADRING_DSE_SHIFT		0
+#define PADRING_DSE_MASK		(0x7 << PADRING_DSE_SHIFT)
+
+#endif	/* __IMX8_IOMUX_H__ */
diff --git a/plat/imx/common/include/imx8_lpuart.h b/plat/imx/common/include/imx8_lpuart.h
new file mode 100644
index 0000000..4ff91bd
--- /dev/null
+++ b/plat/imx/common/include/imx8_lpuart.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __IMX_LPUART_H__
+#define __IMX_LPUART_H__
+
+#include <console.h>
+
+#define VERID	0x0
+#define PARAM	0x4
+#define GLOBAL	0x8
+#define PINCFG	0xC
+#define BAUD	0x10
+#define STAT	0x14
+#define CTRL	0x18
+#define DATA	0x1C
+#define MATCH	0x20
+#define MODIR	0x24
+#define FIFO	0x28
+#define WATER	0x2c
+
+#define US1_TDRE	(1 << 23)
+#define US1_RDRF	(1 << 21)
+
+#define CTRL_TE		(1 << 19)
+#define CTRL_RE		(1 << 18)
+
+#define FIFO_TXFE	0x80
+#define FIFO_RXFE	0x40
+
+#define WATER_TXWATER_OFF	1
+#define WATER_RXWATER_OFF	16
+
+#define LPUART_CTRL_PT_MASK	0x1
+#define LPUART_CTRL_PE_MASK	0x2
+#define LPUART_CTRL_M_MASK	0x10
+
+#define LPUART_BAUD_OSR_MASK                     (0x1F000000U)
+#define LPUART_BAUD_OSR_SHIFT                    (24U)
+#define LPUART_BAUD_OSR(x)                       (((uint32_t)(((uint32_t)(x)) << LPUART_BAUD_OSR_SHIFT)) & LPUART_BAUD_OSR_MASK)
+
+#define LPUART_BAUD_SBR_MASK                     (0x1FFFU)
+#define LPUART_BAUD_SBR_SHIFT                    (0U)
+#define LPUART_BAUD_SBR(x)                       (((uint32_t)(((uint32_t)(x)) << LPUART_BAUD_SBR_SHIFT)) & LPUART_BAUD_SBR_MASK)
+
+#define LPUART_BAUD_SBNS_MASK                    (0x2000U)
+#define LPUART_BAUD_BOTHEDGE_MASK                (0x20000U)
+#define LPUART_BAUD_M10_MASK                     (0x20000000U)
+
+#ifndef __ASSEMBLY__
+
+#include <types.h>
+
+typedef struct {
+	console_t console;
+	uintptr_t base;
+} console_lpuart_t;
+
+int console_lpuart_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
+			   console_lpuart_t *console);
+#endif /*__ASSEMBLY__*/
+
+#endif  /* __IMX_LPUART_H__*/
diff --git a/plat/imx/common/include/imx8qm_pads.h b/plat/imx/common/include/imx8qm_pads.h
new file mode 100644
index 0000000..6107bd9
--- /dev/null
+++ b/plat/imx/common/include/imx8qm_pads.h
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file used to configure SoC pad list.
+ */
+
+#ifndef SC_PADS_H
+#define SC_PADS_H
+
+/* Includes */
+
+/* Defines */
+
+/*!
+ * @name Pad Definitions
+ */
+/*@{*/
+#define SC_P_SIM0_CLK                            0	/* DMA.SIM0.CLK, LSIO.GPIO0.IO00 */
+#define SC_P_SIM0_RST                            1	/* DMA.SIM0.RST, LSIO.GPIO0.IO01 */
+#define SC_P_SIM0_IO                             2	/* DMA.SIM0.IO, LSIO.GPIO0.IO02 */
+#define SC_P_SIM0_PD                             3	/* DMA.SIM0.PD, DMA.I2C3.SCL, LSIO.GPIO0.IO03 */
+#define SC_P_SIM0_POWER_EN                       4	/* DMA.SIM0.POWER_EN, DMA.I2C3.SDA, LSIO.GPIO0.IO04 */
+#define SC_P_SIM0_GPIO0_00                       5	/* DMA.SIM0.POWER_EN, LSIO.GPIO0.IO05 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_SIM           6	/*  */
+#define SC_P_M40_I2C0_SCL                        7	/* M40.I2C0.SCL, M40.UART0.RX, M40.GPIO0.IO02, LSIO.GPIO0.IO06 */
+#define SC_P_M40_I2C0_SDA                        8	/* M40.I2C0.SDA, M40.UART0.TX, M40.GPIO0.IO03, LSIO.GPIO0.IO07 */
+#define SC_P_M40_GPIO0_00                        9	/* M40.GPIO0.IO00, M40.TPM0.CH0, DMA.UART4.RX, LSIO.GPIO0.IO08 */
+#define SC_P_M40_GPIO0_01                        10	/* M40.GPIO0.IO01, M40.TPM0.CH1, DMA.UART4.TX, LSIO.GPIO0.IO09 */
+#define SC_P_M41_I2C0_SCL                        11	/* M41.I2C0.SCL, M41.UART0.RX, M41.GPIO0.IO02, LSIO.GPIO0.IO10 */
+#define SC_P_M41_I2C0_SDA                        12	/* M41.I2C0.SDA, M41.UART0.TX, M41.GPIO0.IO03, LSIO.GPIO0.IO11 */
+#define SC_P_M41_GPIO0_00                        13	/* M41.GPIO0.IO00, M41.TPM0.CH0, DMA.UART3.RX, LSIO.GPIO0.IO12 */
+#define SC_P_M41_GPIO0_01                        14	/* M41.GPIO0.IO01, M41.TPM0.CH1, DMA.UART3.TX, LSIO.GPIO0.IO13 */
+#define SC_P_GPT0_CLK                            15	/* LSIO.GPT0.CLK, DMA.I2C1.SCL, LSIO.KPP0.COL4, LSIO.GPIO0.IO14 */
+#define SC_P_GPT0_CAPTURE                        16	/* LSIO.GPT0.CAPTURE, DMA.I2C1.SDA, LSIO.KPP0.COL5, LSIO.GPIO0.IO15 */
+#define SC_P_GPT0_COMPARE                        17	/* LSIO.GPT0.COMPARE, LSIO.PWM3.OUT, LSIO.KPP0.COL6, LSIO.GPIO0.IO16 */
+#define SC_P_GPT1_CLK                            18	/* LSIO.GPT1.CLK, DMA.I2C2.SCL, LSIO.KPP0.COL7, LSIO.GPIO0.IO17 */
+#define SC_P_GPT1_CAPTURE                        19	/* LSIO.GPT1.CAPTURE, DMA.I2C2.SDA, LSIO.KPP0.ROW4, LSIO.GPIO0.IO18 */
+#define SC_P_GPT1_COMPARE                        20	/* LSIO.GPT1.COMPARE, LSIO.PWM2.OUT, LSIO.KPP0.ROW5, LSIO.GPIO0.IO19 */
+#define SC_P_UART0_RX                            21	/* DMA.UART0.RX, SCU.UART0.RX, LSIO.GPIO0.IO20 */
+#define SC_P_UART0_TX                            22	/* DMA.UART0.TX, SCU.UART0.TX, LSIO.GPIO0.IO21 */
+#define SC_P_UART0_RTS_B                         23	/* DMA.UART0.RTS_B, LSIO.PWM0.OUT, DMA.UART2.RX, LSIO.GPIO0.IO22 */
+#define SC_P_UART0_CTS_B                         24	/* DMA.UART0.CTS_B, LSIO.PWM1.OUT, DMA.UART2.TX, LSIO.GPIO0.IO23 */
+#define SC_P_UART1_TX                            25	/* DMA.UART1.TX, DMA.SPI3.SCK, LSIO.GPIO0.IO24 */
+#define SC_P_UART1_RX                            26	/* DMA.UART1.RX, DMA.SPI3.SDO, LSIO.GPIO0.IO25 */
+#define SC_P_UART1_RTS_B                         27	/* DMA.UART1.RTS_B, DMA.SPI3.SDI, DMA.UART1.CTS_B, LSIO.GPIO0.IO26 */
+#define SC_P_UART1_CTS_B                         28	/* DMA.UART1.CTS_B, DMA.SPI3.CS0, DMA.UART1.RTS_B, LSIO.GPIO0.IO27 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOLH        29	/*  */
+#define SC_P_SCU_PMIC_MEMC_ON                    30	/* SCU.GPIO0.IOXX_PMIC_MEMC_ON */
+#define SC_P_SCU_WDOG_OUT                        31	/* SCU.WDOG0.WDOG_OUT */
+#define SC_P_PMIC_I2C_SDA                        32	/* SCU.PMIC_I2C.SDA */
+#define SC_P_PMIC_I2C_SCL                        33	/* SCU.PMIC_I2C.SCL */
+#define SC_P_PMIC_EARLY_WARNING                  34	/* SCU.PMIC_EARLY_WARNING */
+#define SC_P_PMIC_INT_B                          35	/* SCU.DSC.PMIC_INT_B */
+#define SC_P_SCU_GPIO0_00                        36	/* SCU.GPIO0.IO00, SCU.UART0.RX, LSIO.GPIO0.IO28 */
+#define SC_P_SCU_GPIO0_01                        37	/* SCU.GPIO0.IO01, SCU.UART0.TX, LSIO.GPIO0.IO29 */
+#define SC_P_SCU_GPIO0_02                        38	/* SCU.GPIO0.IO02, SCU.GPIO0.IOXX_PMIC_GPU0_ON, LSIO.GPIO0.IO30 */
+#define SC_P_SCU_GPIO0_03                        39	/* SCU.GPIO0.IO03, SCU.GPIO0.IOXX_PMIC_GPU1_ON, LSIO.GPIO0.IO31 */
+#define SC_P_SCU_GPIO0_04                        40	/* SCU.GPIO0.IO04, SCU.GPIO0.IOXX_PMIC_A72_ON, LSIO.GPIO1.IO00 */
+#define SC_P_SCU_GPIO0_05                        41	/* SCU.GPIO0.IO05, SCU.GPIO0.IOXX_PMIC_A53_ON, LSIO.GPIO1.IO01 */
+#define SC_P_SCU_GPIO0_06                        42	/* SCU.GPIO0.IO06, SCU.TPM0.CH0, LSIO.GPIO1.IO02 */
+#define SC_P_SCU_GPIO0_07                        43	/* SCU.GPIO0.IO07, SCU.TPM0.CH1, SCU.DSC.RTC_CLOCK_OUTPUT_32K, LSIO.GPIO1.IO03 */
+#define SC_P_SCU_BOOT_MODE0                      44	/* SCU.DSC.BOOT_MODE0 */
+#define SC_P_SCU_BOOT_MODE1                      45	/* SCU.DSC.BOOT_MODE1 */
+#define SC_P_SCU_BOOT_MODE2                      46	/* SCU.DSC.BOOT_MODE2 */
+#define SC_P_SCU_BOOT_MODE3                      47	/* SCU.DSC.BOOT_MODE3 */
+#define SC_P_SCU_BOOT_MODE4                      48	/* SCU.DSC.BOOT_MODE4, SCU.PMIC_I2C.SCL */
+#define SC_P_SCU_BOOT_MODE5                      49	/* SCU.DSC.BOOT_MODE5, SCU.PMIC_I2C.SDA */
+#define SC_P_LVDS0_GPIO00                        50	/* LVDS0.GPIO0.IO00, LVDS0.PWM0.OUT, LSIO.GPIO1.IO04 */
+#define SC_P_LVDS0_GPIO01                        51	/* LVDS0.GPIO0.IO01, LSIO.GPIO1.IO05 */
+#define SC_P_LVDS0_I2C0_SCL                      52	/* LVDS0.I2C0.SCL, LVDS0.GPIO0.IO02, LSIO.GPIO1.IO06 */
+#define SC_P_LVDS0_I2C0_SDA                      53	/* LVDS0.I2C0.SDA, LVDS0.GPIO0.IO03, LSIO.GPIO1.IO07 */
+#define SC_P_LVDS0_I2C1_SCL                      54	/* LVDS0.I2C1.SCL, DMA.UART2.TX, LSIO.GPIO1.IO08 */
+#define SC_P_LVDS0_I2C1_SDA                      55	/* LVDS0.I2C1.SDA, DMA.UART2.RX, LSIO.GPIO1.IO09 */
+#define SC_P_LVDS1_GPIO00                        56	/* LVDS1.GPIO0.IO00, LVDS1.PWM0.OUT, LSIO.GPIO1.IO10 */
+#define SC_P_LVDS1_GPIO01                        57	/* LVDS1.GPIO0.IO01, LSIO.GPIO1.IO11 */
+#define SC_P_LVDS1_I2C0_SCL                      58	/* LVDS1.I2C0.SCL, LVDS1.GPIO0.IO02, LSIO.GPIO1.IO12 */
+#define SC_P_LVDS1_I2C0_SDA                      59	/* LVDS1.I2C0.SDA, LVDS1.GPIO0.IO03, LSIO.GPIO1.IO13 */
+#define SC_P_LVDS1_I2C1_SCL                      60	/* LVDS1.I2C1.SCL, DMA.UART3.TX, LSIO.GPIO1.IO14 */
+#define SC_P_LVDS1_I2C1_SDA                      61	/* LVDS1.I2C1.SDA, DMA.UART3.RX, LSIO.GPIO1.IO15 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_LVDSGPIO      62	/*  */
+#define SC_P_MIPI_DSI0_I2C0_SCL                  63	/* MIPI_DSI0.I2C0.SCL, LSIO.GPIO1.IO16 */
+#define SC_P_MIPI_DSI0_I2C0_SDA                  64	/* MIPI_DSI0.I2C0.SDA, LSIO.GPIO1.IO17 */
+#define SC_P_MIPI_DSI0_GPIO0_00                  65	/* MIPI_DSI0.GPIO0.IO00, MIPI_DSI0.PWM0.OUT, LSIO.GPIO1.IO18 */
+#define SC_P_MIPI_DSI0_GPIO0_01                  66	/* MIPI_DSI0.GPIO0.IO01, LSIO.GPIO1.IO19 */
+#define SC_P_MIPI_DSI1_I2C0_SCL                  67	/* MIPI_DSI1.I2C0.SCL, LSIO.GPIO1.IO20 */
+#define SC_P_MIPI_DSI1_I2C0_SDA                  68	/* MIPI_DSI1.I2C0.SDA, LSIO.GPIO1.IO21 */
+#define SC_P_MIPI_DSI1_GPIO0_00                  69	/* MIPI_DSI1.GPIO0.IO00, MIPI_DSI1.PWM0.OUT, LSIO.GPIO1.IO22 */
+#define SC_P_MIPI_DSI1_GPIO0_01                  70	/* MIPI_DSI1.GPIO0.IO01, LSIO.GPIO1.IO23 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_MIPIDSIGPIO   71	/*  */
+#define SC_P_MIPI_CSI0_MCLK_OUT                  72	/* MIPI_CSI0.ACM.MCLK_OUT, LSIO.GPIO1.IO24 */
+#define SC_P_MIPI_CSI0_I2C0_SCL                  73	/* MIPI_CSI0.I2C0.SCL, LSIO.GPIO1.IO25 */
+#define SC_P_MIPI_CSI0_I2C0_SDA                  74	/* MIPI_CSI0.I2C0.SDA, LSIO.GPIO1.IO26 */
+#define SC_P_MIPI_CSI0_GPIO0_00                  75	/* MIPI_CSI0.GPIO0.IO00, DMA.I2C0.SCL, MIPI_CSI1.I2C0.SCL, LSIO.GPIO1.IO27 */
+#define SC_P_MIPI_CSI0_GPIO0_01                  76	/* MIPI_CSI0.GPIO0.IO01, DMA.I2C0.SDA, MIPI_CSI1.I2C0.SDA, LSIO.GPIO1.IO28 */
+#define SC_P_MIPI_CSI1_MCLK_OUT                  77	/* MIPI_CSI1.ACM.MCLK_OUT, LSIO.GPIO1.IO29 */
+#define SC_P_MIPI_CSI1_GPIO0_00                  78	/* MIPI_CSI1.GPIO0.IO00, DMA.UART4.RX, LSIO.GPIO1.IO30 */
+#define SC_P_MIPI_CSI1_GPIO0_01                  79	/* MIPI_CSI1.GPIO0.IO01, DMA.UART4.TX, LSIO.GPIO1.IO31 */
+#define SC_P_MIPI_CSI1_I2C0_SCL                  80	/* MIPI_CSI1.I2C0.SCL, LSIO.GPIO2.IO00 */
+#define SC_P_MIPI_CSI1_I2C0_SDA                  81	/* MIPI_CSI1.I2C0.SDA, LSIO.GPIO2.IO01 */
+#define SC_P_HDMI_TX0_TS_SCL                     82	/* HDMI_TX0.I2C0.SCL, DMA.I2C0.SCL, LSIO.GPIO2.IO02 */
+#define SC_P_HDMI_TX0_TS_SDA                     83	/* HDMI_TX0.I2C0.SDA, DMA.I2C0.SDA, LSIO.GPIO2.IO03 */
+#define SC_P_COMP_CTL_GPIO_3V3_HDMIGPIO          84	/*  */
+#define SC_P_ESAI1_FSR                           85	/* AUD.ESAI1.FSR, LSIO.GPIO2.IO04 */
+#define SC_P_ESAI1_FST                           86	/* AUD.ESAI1.FST, AUD.SPDIF0.EXT_CLK, LSIO.GPIO2.IO05 */
+#define SC_P_ESAI1_SCKR                          87	/* AUD.ESAI1.SCKR, LSIO.GPIO2.IO06 */
+#define SC_P_ESAI1_SCKT                          88	/* AUD.ESAI1.SCKT, AUD.SAI2.RXC, AUD.SPDIF0.EXT_CLK, LSIO.GPIO2.IO07 */
+#define SC_P_ESAI1_TX0                           89	/* AUD.ESAI1.TX0, AUD.SAI2.RXD, AUD.SPDIF0.RX, LSIO.GPIO2.IO08 */
+#define SC_P_ESAI1_TX1                           90	/* AUD.ESAI1.TX1, AUD.SAI2.RXFS, AUD.SPDIF0.TX, LSIO.GPIO2.IO09 */
+#define SC_P_ESAI1_TX2_RX3                       91	/* AUD.ESAI1.TX2_RX3, AUD.SPDIF0.RX, LSIO.GPIO2.IO10 */
+#define SC_P_ESAI1_TX3_RX2                       92	/* AUD.ESAI1.TX3_RX2, AUD.SPDIF0.TX, LSIO.GPIO2.IO11 */
+#define SC_P_ESAI1_TX4_RX1                       93	/* AUD.ESAI1.TX4_RX1, LSIO.GPIO2.IO12 */
+#define SC_P_ESAI1_TX5_RX0                       94	/* AUD.ESAI1.TX5_RX0, LSIO.GPIO2.IO13 */
+#define SC_P_SPDIF0_RX                           95	/* AUD.SPDIF0.RX, AUD.MQS.R, AUD.ACM.MCLK_IN1, LSIO.GPIO2.IO14 */
+#define SC_P_SPDIF0_TX                           96	/* AUD.SPDIF0.TX, AUD.MQS.L, AUD.ACM.MCLK_OUT1, LSIO.GPIO2.IO15 */
+#define SC_P_SPDIF0_EXT_CLK                      97	/* AUD.SPDIF0.EXT_CLK, DMA.DMA0.REQ_IN0, LSIO.GPIO2.IO16 */
+#define SC_P_SPI3_SCK                            98	/* DMA.SPI3.SCK, LSIO.GPIO2.IO17 */
+#define SC_P_SPI3_SDO                            99	/* DMA.SPI3.SDO, DMA.FTM.CH0, LSIO.GPIO2.IO18 */
+#define SC_P_SPI3_SDI                            100	/* DMA.SPI3.SDI, DMA.FTM.CH1, LSIO.GPIO2.IO19 */
+#define SC_P_SPI3_CS0                            101	/* DMA.SPI3.CS0, DMA.FTM.CH2, LSIO.GPIO2.IO20 */
+#define SC_P_SPI3_CS1                            102	/* DMA.SPI3.CS1, LSIO.GPIO2.IO21 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHB       103	/*  */
+#define SC_P_ESAI0_FSR                           104	/* AUD.ESAI0.FSR, LSIO.GPIO2.IO22 */
+#define SC_P_ESAI0_FST                           105	/* AUD.ESAI0.FST, LSIO.GPIO2.IO23 */
+#define SC_P_ESAI0_SCKR                          106	/* AUD.ESAI0.SCKR, LSIO.GPIO2.IO24 */
+#define SC_P_ESAI0_SCKT                          107	/* AUD.ESAI0.SCKT, LSIO.GPIO2.IO25 */
+#define SC_P_ESAI0_TX0                           108	/* AUD.ESAI0.TX0, LSIO.GPIO2.IO26 */
+#define SC_P_ESAI0_TX1                           109	/* AUD.ESAI0.TX1, LSIO.GPIO2.IO27 */
+#define SC_P_ESAI0_TX2_RX3                       110	/* AUD.ESAI0.TX2_RX3, LSIO.GPIO2.IO28 */
+#define SC_P_ESAI0_TX3_RX2                       111	/* AUD.ESAI0.TX3_RX2, LSIO.GPIO2.IO29 */
+#define SC_P_ESAI0_TX4_RX1                       112	/* AUD.ESAI0.TX4_RX1, LSIO.GPIO2.IO30 */
+#define SC_P_ESAI0_TX5_RX0                       113	/* AUD.ESAI0.TX5_RX0, LSIO.GPIO2.IO31 */
+#define SC_P_MCLK_IN0                            114	/* AUD.ACM.MCLK_IN0, AUD.ESAI0.RX_HF_CLK, AUD.ESAI1.RX_HF_CLK, LSIO.GPIO3.IO00 */
+#define SC_P_MCLK_OUT0                           115	/* AUD.ACM.MCLK_OUT0, AUD.ESAI0.TX_HF_CLK, AUD.ESAI1.TX_HF_CLK, LSIO.GPIO3.IO01 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHC       116	/*  */
+#define SC_P_SPI0_SCK                            117	/* DMA.SPI0.SCK, AUD.SAI0.RXC, LSIO.GPIO3.IO02 */
+#define SC_P_SPI0_SDO                            118	/* DMA.SPI0.SDO, AUD.SAI0.TXD, LSIO.GPIO3.IO03 */
+#define SC_P_SPI0_SDI                            119	/* DMA.SPI0.SDI, AUD.SAI0.RXD, LSIO.GPIO3.IO04 */
+#define SC_P_SPI0_CS0                            120	/* DMA.SPI0.CS0, AUD.SAI0.RXFS, LSIO.GPIO3.IO05 */
+#define SC_P_SPI0_CS1                            121	/* DMA.SPI0.CS1, AUD.SAI0.TXC, LSIO.GPIO3.IO06 */
+#define SC_P_SPI2_SCK                            122	/* DMA.SPI2.SCK, LSIO.GPIO3.IO07 */
+#define SC_P_SPI2_SDO                            123	/* DMA.SPI2.SDO, LSIO.GPIO3.IO08 */
+#define SC_P_SPI2_SDI                            124	/* DMA.SPI2.SDI, LSIO.GPIO3.IO09 */
+#define SC_P_SPI2_CS0                            125	/* DMA.SPI2.CS0, LSIO.GPIO3.IO10 */
+#define SC_P_SPI2_CS1                            126	/* DMA.SPI2.CS1, AUD.SAI0.TXFS, LSIO.GPIO3.IO11 */
+#define SC_P_SAI1_RXC                            127	/* AUD.SAI1.RXC, AUD.SAI0.TXD, LSIO.GPIO3.IO12 */
+#define SC_P_SAI1_RXD                            128	/* AUD.SAI1.RXD, AUD.SAI0.TXFS, LSIO.GPIO3.IO13 */
+#define SC_P_SAI1_RXFS                           129	/* AUD.SAI1.RXFS, AUD.SAI0.RXD, LSIO.GPIO3.IO14 */
+#define SC_P_SAI1_TXC                            130	/* AUD.SAI1.TXC, AUD.SAI0.TXC, LSIO.GPIO3.IO15 */
+#define SC_P_SAI1_TXD                            131	/* AUD.SAI1.TXD, AUD.SAI1.RXC, LSIO.GPIO3.IO16 */
+#define SC_P_SAI1_TXFS                           132	/* AUD.SAI1.TXFS, AUD.SAI1.RXFS, LSIO.GPIO3.IO17 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHT       133	/*  */
+#define SC_P_ADC_IN7                             134	/* DMA.ADC1.IN3, DMA.SPI1.CS1, LSIO.KPP0.ROW3, LSIO.GPIO3.IO25 */
+#define SC_P_ADC_IN6                             135	/* DMA.ADC1.IN2, DMA.SPI1.CS0, LSIO.KPP0.ROW2, LSIO.GPIO3.IO24 */
+#define SC_P_ADC_IN5                             136	/* DMA.ADC1.IN1, DMA.SPI1.SDI, LSIO.KPP0.ROW1, LSIO.GPIO3.IO23 */
+#define SC_P_ADC_IN4                             137	/* DMA.ADC1.IN0, DMA.SPI1.SDO, LSIO.KPP0.ROW0, LSIO.GPIO3.IO22 */
+#define SC_P_ADC_IN3                             138	/* DMA.ADC0.IN3, DMA.SPI1.SCK, LSIO.KPP0.COL3, LSIO.GPIO3.IO21 */
+#define SC_P_ADC_IN2                             139	/* DMA.ADC0.IN2, LSIO.KPP0.COL2, LSIO.GPIO3.IO20 */
+#define SC_P_ADC_IN1                             140	/* DMA.ADC0.IN1, LSIO.KPP0.COL1, LSIO.GPIO3.IO19 */
+#define SC_P_ADC_IN0                             141	/* DMA.ADC0.IN0, LSIO.KPP0.COL0, LSIO.GPIO3.IO18 */
+#define SC_P_MLB_SIG                             142	/* CONN.MLB.SIG, AUD.SAI3.RXC, LSIO.GPIO3.IO26 */
+#define SC_P_MLB_CLK                             143	/* CONN.MLB.CLK, AUD.SAI3.RXFS, LSIO.GPIO3.IO27 */
+#define SC_P_MLB_DATA                            144	/* CONN.MLB.DATA, AUD.SAI3.RXD, LSIO.GPIO3.IO28 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOLHT       145	/*  */
+#define SC_P_FLEXCAN0_RX                         146	/* DMA.FLEXCAN0.RX, LSIO.GPIO3.IO29 */
+#define SC_P_FLEXCAN0_TX                         147	/* DMA.FLEXCAN0.TX, LSIO.GPIO3.IO30 */
+#define SC_P_FLEXCAN1_RX                         148	/* DMA.FLEXCAN1.RX, LSIO.GPIO3.IO31 */
+#define SC_P_FLEXCAN1_TX                         149	/* DMA.FLEXCAN1.TX, LSIO.GPIO4.IO00 */
+#define SC_P_FLEXCAN2_RX                         150	/* DMA.FLEXCAN2.RX, LSIO.GPIO4.IO01 */
+#define SC_P_FLEXCAN2_TX                         151	/* DMA.FLEXCAN2.TX, LSIO.GPIO4.IO02 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOTHR       152	/*  */
+#define SC_P_USB_SS3_TC0                         153	/* DMA.I2C1.SCL, CONN.USB_OTG1.PWR, LSIO.GPIO4.IO03 */
+#define SC_P_USB_SS3_TC1                         154	/* DMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO04 */
+#define SC_P_USB_SS3_TC2                         155	/* DMA.I2C1.SDA, CONN.USB_OTG1.OC, LSIO.GPIO4.IO05 */
+#define SC_P_USB_SS3_TC3                         156	/* DMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO06 */
+#define SC_P_COMP_CTL_GPIO_3V3_USB3IO            157	/*  */
+#define SC_P_USDHC1_RESET_B                      158	/* CONN.USDHC1.RESET_B, LSIO.GPIO4.IO07 */
+#define SC_P_USDHC1_VSELECT                      159	/* CONN.USDHC1.VSELECT, LSIO.GPIO4.IO08 */
+#define SC_P_USDHC2_RESET_B                      160	/* CONN.USDHC2.RESET_B, LSIO.GPIO4.IO09 */
+#define SC_P_USDHC2_VSELECT                      161	/* CONN.USDHC2.VSELECT, LSIO.GPIO4.IO10 */
+#define SC_P_USDHC2_WP                           162	/* CONN.USDHC2.WP, LSIO.GPIO4.IO11 */
+#define SC_P_USDHC2_CD_B                         163	/* CONN.USDHC2.CD_B, LSIO.GPIO4.IO12 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSELSEP       164	/*  */
+#define SC_P_ENET0_MDIO                          165	/* CONN.ENET0.MDIO, DMA.I2C4.SDA, LSIO.GPIO4.IO13 */
+#define SC_P_ENET0_MDC                           166	/* CONN.ENET0.MDC, DMA.I2C4.SCL, LSIO.GPIO4.IO14 */
+#define SC_P_ENET0_REFCLK_125M_25M               167	/* CONN.ENET0.REFCLK_125M_25M, CONN.ENET0.PPS, LSIO.GPIO4.IO15 */
+#define SC_P_ENET1_REFCLK_125M_25M               168	/* CONN.ENET1.REFCLK_125M_25M, CONN.ENET1.PPS, LSIO.GPIO4.IO16 */
+#define SC_P_ENET1_MDIO                          169	/* CONN.ENET1.MDIO, DMA.I2C4.SDA, LSIO.GPIO4.IO17 */
+#define SC_P_ENET1_MDC                           170	/* CONN.ENET1.MDC, DMA.I2C4.SCL, LSIO.GPIO4.IO18 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOCT        171	/*  */
+#define SC_P_QSPI1A_SS0_B                        172	/* LSIO.QSPI1A.SS0_B, LSIO.GPIO4.IO19 */
+#define SC_P_QSPI1A_SS1_B                        173	/* LSIO.QSPI1A.SS1_B, LSIO.QSPI1A.SCLK2, LSIO.GPIO4.IO20 */
+#define SC_P_QSPI1A_SCLK                         174	/* LSIO.QSPI1A.SCLK, LSIO.GPIO4.IO21 */
+#define SC_P_QSPI1A_DQS                          175	/* LSIO.QSPI1A.DQS, LSIO.GPIO4.IO22 */
+#define SC_P_QSPI1A_DATA3                        176	/* LSIO.QSPI1A.DATA3, DMA.I2C1.SDA, CONN.USB_OTG1.OC, LSIO.GPIO4.IO23 */
+#define SC_P_QSPI1A_DATA2                        177	/* LSIO.QSPI1A.DATA2, DMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO24 */
+#define SC_P_QSPI1A_DATA1                        178	/* LSIO.QSPI1A.DATA1, DMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO25 */
+#define SC_P_QSPI1A_DATA0                        179	/* LSIO.QSPI1A.DATA0, LSIO.GPIO4.IO26 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI1         180	/*  */
+#define SC_P_QSPI0A_DATA0                        181	/* LSIO.QSPI0A.DATA0 */
+#define SC_P_QSPI0A_DATA1                        182	/* LSIO.QSPI0A.DATA1 */
+#define SC_P_QSPI0A_DATA2                        183	/* LSIO.QSPI0A.DATA2 */
+#define SC_P_QSPI0A_DATA3                        184	/* LSIO.QSPI0A.DATA3 */
+#define SC_P_QSPI0A_DQS                          185	/* LSIO.QSPI0A.DQS */
+#define SC_P_QSPI0A_SS0_B                        186	/* LSIO.QSPI0A.SS0_B */
+#define SC_P_QSPI0A_SS1_B                        187	/* LSIO.QSPI0A.SS1_B, LSIO.QSPI0A.SCLK2 */
+#define SC_P_QSPI0A_SCLK                         188	/* LSIO.QSPI0A.SCLK */
+#define SC_P_QSPI0B_SCLK                         189	/* LSIO.QSPI0B.SCLK */
+#define SC_P_QSPI0B_DATA0                        190	/* LSIO.QSPI0B.DATA0 */
+#define SC_P_QSPI0B_DATA1                        191	/* LSIO.QSPI0B.DATA1 */
+#define SC_P_QSPI0B_DATA2                        192	/* LSIO.QSPI0B.DATA2 */
+#define SC_P_QSPI0B_DATA3                        193	/* LSIO.QSPI0B.DATA3 */
+#define SC_P_QSPI0B_DQS                          194	/* LSIO.QSPI0B.DQS */
+#define SC_P_QSPI0B_SS0_B                        195	/* LSIO.QSPI0B.SS0_B */
+#define SC_P_QSPI0B_SS1_B                        196	/* LSIO.QSPI0B.SS1_B, LSIO.QSPI0B.SCLK2 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI0         197	/*  */
+#define SC_P_PCIE_CTRL0_CLKREQ_B                 198	/* HSIO.PCIE0.CLKREQ_B, LSIO.GPIO4.IO27 */
+#define SC_P_PCIE_CTRL0_WAKE_B                   199	/* HSIO.PCIE0.WAKE_B, LSIO.GPIO4.IO28 */
+#define SC_P_PCIE_CTRL0_PERST_B                  200	/* HSIO.PCIE0.PERST_B, LSIO.GPIO4.IO29 */
+#define SC_P_PCIE_CTRL1_CLKREQ_B                 201	/* HSIO.PCIE1.CLKREQ_B, DMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO30 */
+#define SC_P_PCIE_CTRL1_WAKE_B                   202	/* HSIO.PCIE1.WAKE_B, DMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO31 */
+#define SC_P_PCIE_CTRL1_PERST_B                  203	/* HSIO.PCIE1.PERST_B, DMA.I2C1.SCL, CONN.USB_OTG1.PWR, LSIO.GPIO5.IO00 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_PCIESEP       204	/*  */
+#define SC_P_USB_HSIC0_DATA                      205	/* CONN.USB_HSIC0.DATA, DMA.I2C1.SDA, LSIO.GPIO5.IO01 */
+#define SC_P_USB_HSIC0_STROBE                    206	/* CONN.USB_HSIC0.STROBE, DMA.I2C1.SCL, LSIO.GPIO5.IO02 */
+#define SC_P_CALIBRATION_0_HSIC                  207	/*  */
+#define SC_P_CALIBRATION_1_HSIC                  208	/*  */
+#define SC_P_EMMC0_CLK                           209	/* CONN.EMMC0.CLK, CONN.NAND.READY_B */
+#define SC_P_EMMC0_CMD                           210	/* CONN.EMMC0.CMD, CONN.NAND.DQS, AUD.MQS.R, LSIO.GPIO5.IO03 */
+#define SC_P_EMMC0_DATA0                         211	/* CONN.EMMC0.DATA0, CONN.NAND.DATA00, LSIO.GPIO5.IO04 */
+#define SC_P_EMMC0_DATA1                         212	/* CONN.EMMC0.DATA1, CONN.NAND.DATA01, LSIO.GPIO5.IO05 */
+#define SC_P_EMMC0_DATA2                         213	/* CONN.EMMC0.DATA2, CONN.NAND.DATA02, LSIO.GPIO5.IO06 */
+#define SC_P_EMMC0_DATA3                         214	/* CONN.EMMC0.DATA3, CONN.NAND.DATA03, LSIO.GPIO5.IO07 */
+#define SC_P_EMMC0_DATA4                         215	/* CONN.EMMC0.DATA4, CONN.NAND.DATA04, LSIO.GPIO5.IO08 */
+#define SC_P_EMMC0_DATA5                         216	/* CONN.EMMC0.DATA5, CONN.NAND.DATA05, LSIO.GPIO5.IO09 */
+#define SC_P_EMMC0_DATA6                         217	/* CONN.EMMC0.DATA6, CONN.NAND.DATA06, LSIO.GPIO5.IO10 */
+#define SC_P_EMMC0_DATA7                         218	/* CONN.EMMC0.DATA7, CONN.NAND.DATA07, LSIO.GPIO5.IO11 */
+#define SC_P_EMMC0_STROBE                        219	/* CONN.EMMC0.STROBE, CONN.NAND.CLE, LSIO.GPIO5.IO12 */
+#define SC_P_EMMC0_RESET_B                       220	/* CONN.EMMC0.RESET_B, CONN.NAND.WP_B, CONN.USDHC1.VSELECT, LSIO.GPIO5.IO13 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_SD1FIX        221	/*  */
+#define SC_P_USDHC1_CLK                          222	/* CONN.USDHC1.CLK, AUD.MQS.R */
+#define SC_P_USDHC1_CMD                          223	/* CONN.USDHC1.CMD, AUD.MQS.L, LSIO.GPIO5.IO14 */
+#define SC_P_USDHC1_DATA0                        224	/* CONN.USDHC1.DATA0, CONN.NAND.RE_N, LSIO.GPIO5.IO15 */
+#define SC_P_USDHC1_DATA1                        225	/* CONN.USDHC1.DATA1, CONN.NAND.RE_P, LSIO.GPIO5.IO16 */
+#define SC_P_CTL_NAND_RE_P_N                     226	/*  */
+#define SC_P_USDHC1_DATA2                        227	/* CONN.USDHC1.DATA2, CONN.NAND.DQS_N, LSIO.GPIO5.IO17 */
+#define SC_P_USDHC1_DATA3                        228	/* CONN.USDHC1.DATA3, CONN.NAND.DQS_P, LSIO.GPIO5.IO18 */
+#define SC_P_CTL_NAND_DQS_P_N                    229	/*  */
+#define SC_P_USDHC1_DATA4                        230	/* CONN.USDHC1.DATA4, CONN.NAND.CE0_B, AUD.MQS.R, LSIO.GPIO5.IO19 */
+#define SC_P_USDHC1_DATA5                        231	/* CONN.USDHC1.DATA5, CONN.NAND.RE_B, AUD.MQS.L, LSIO.GPIO5.IO20 */
+#define SC_P_USDHC1_DATA6                        232	/* CONN.USDHC1.DATA6, CONN.NAND.WE_B, CONN.USDHC1.WP, LSIO.GPIO5.IO21 */
+#define SC_P_USDHC1_DATA7                        233	/* CONN.USDHC1.DATA7, CONN.NAND.ALE, CONN.USDHC1.CD_B, LSIO.GPIO5.IO22 */
+#define SC_P_USDHC1_STROBE                       234	/* CONN.USDHC1.STROBE, CONN.NAND.CE1_B, CONN.USDHC1.RESET_B, LSIO.GPIO5.IO23 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSEL2         235	/*  */
+#define SC_P_USDHC2_CLK                          236	/* CONN.USDHC2.CLK, AUD.MQS.R, LSIO.GPIO5.IO24 */
+#define SC_P_USDHC2_CMD                          237	/* CONN.USDHC2.CMD, AUD.MQS.L, LSIO.GPIO5.IO25 */
+#define SC_P_USDHC2_DATA0                        238	/* CONN.USDHC2.DATA0, DMA.UART4.RX, LSIO.GPIO5.IO26 */
+#define SC_P_USDHC2_DATA1                        239	/* CONN.USDHC2.DATA1, DMA.UART4.TX, LSIO.GPIO5.IO27 */
+#define SC_P_USDHC2_DATA2                        240	/* CONN.USDHC2.DATA2, DMA.UART4.CTS_B, LSIO.GPIO5.IO28 */
+#define SC_P_USDHC2_DATA3                        241	/* CONN.USDHC2.DATA3, DMA.UART4.RTS_B, LSIO.GPIO5.IO29 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSEL3         242	/*  */
+#define SC_P_ENET0_RGMII_TXC                     243	/* CONN.ENET0.RGMII_TXC, CONN.ENET0.RCLK50M_OUT, CONN.ENET0.RCLK50M_IN, LSIO.GPIO5.IO30 */
+#define SC_P_ENET0_RGMII_TX_CTL                  244	/* CONN.ENET0.RGMII_TX_CTL, LSIO.GPIO5.IO31 */
+#define SC_P_ENET0_RGMII_TXD0                    245	/* CONN.ENET0.RGMII_TXD0, LSIO.GPIO6.IO00 */
+#define SC_P_ENET0_RGMII_TXD1                    246	/* CONN.ENET0.RGMII_TXD1, LSIO.GPIO6.IO01 */
+#define SC_P_ENET0_RGMII_TXD2                    247	/* CONN.ENET0.RGMII_TXD2, DMA.UART3.TX, VPU.TSI_S1.VID, LSIO.GPIO6.IO02 */
+#define SC_P_ENET0_RGMII_TXD3                    248	/* CONN.ENET0.RGMII_TXD3, DMA.UART3.RTS_B, VPU.TSI_S1.SYNC, LSIO.GPIO6.IO03 */
+#define SC_P_ENET0_RGMII_RXC                     249	/* CONN.ENET0.RGMII_RXC, DMA.UART3.CTS_B, VPU.TSI_S1.DATA, LSIO.GPIO6.IO04 */
+#define SC_P_ENET0_RGMII_RX_CTL                  250	/* CONN.ENET0.RGMII_RX_CTL, VPU.TSI_S0.VID, LSIO.GPIO6.IO05 */
+#define SC_P_ENET0_RGMII_RXD0                    251	/* CONN.ENET0.RGMII_RXD0, VPU.TSI_S0.SYNC, LSIO.GPIO6.IO06 */
+#define SC_P_ENET0_RGMII_RXD1                    252	/* CONN.ENET0.RGMII_RXD1, VPU.TSI_S0.DATA, LSIO.GPIO6.IO07 */
+#define SC_P_ENET0_RGMII_RXD2                    253	/* CONN.ENET0.RGMII_RXD2, CONN.ENET0.RMII_RX_ER, VPU.TSI_S0.CLK, LSIO.GPIO6.IO08 */
+#define SC_P_ENET0_RGMII_RXD3                    254	/* CONN.ENET0.RGMII_RXD3, DMA.UART3.RX, VPU.TSI_S1.CLK, LSIO.GPIO6.IO09 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB    255	/*  */
+#define SC_P_ENET1_RGMII_TXC                     256	/* CONN.ENET1.RGMII_TXC, CONN.ENET1.RCLK50M_OUT, CONN.ENET1.RCLK50M_IN, LSIO.GPIO6.IO10 */
+#define SC_P_ENET1_RGMII_TX_CTL                  257	/* CONN.ENET1.RGMII_TX_CTL, LSIO.GPIO6.IO11 */
+#define SC_P_ENET1_RGMII_TXD0                    258	/* CONN.ENET1.RGMII_TXD0, LSIO.GPIO6.IO12 */
+#define SC_P_ENET1_RGMII_TXD1                    259	/* CONN.ENET1.RGMII_TXD1, LSIO.GPIO6.IO13 */
+#define SC_P_ENET1_RGMII_TXD2                    260	/* CONN.ENET1.RGMII_TXD2, DMA.UART3.TX, VPU.TSI_S1.VID, LSIO.GPIO6.IO14 */
+#define SC_P_ENET1_RGMII_TXD3                    261	/* CONN.ENET1.RGMII_TXD3, DMA.UART3.RTS_B, VPU.TSI_S1.SYNC, LSIO.GPIO6.IO15 */
+#define SC_P_ENET1_RGMII_RXC                     262	/* CONN.ENET1.RGMII_RXC, DMA.UART3.CTS_B, VPU.TSI_S1.DATA, LSIO.GPIO6.IO16 */
+#define SC_P_ENET1_RGMII_RX_CTL                  263	/* CONN.ENET1.RGMII_RX_CTL, VPU.TSI_S0.VID, LSIO.GPIO6.IO17 */
+#define SC_P_ENET1_RGMII_RXD0                    264	/* CONN.ENET1.RGMII_RXD0, VPU.TSI_S0.SYNC, LSIO.GPIO6.IO18 */
+#define SC_P_ENET1_RGMII_RXD1                    265	/* CONN.ENET1.RGMII_RXD1, VPU.TSI_S0.DATA, LSIO.GPIO6.IO19 */
+#define SC_P_ENET1_RGMII_RXD2                    266	/* CONN.ENET1.RGMII_RXD2, CONN.ENET1.RMII_RX_ER, VPU.TSI_S0.CLK, LSIO.GPIO6.IO20 */
+#define SC_P_ENET1_RGMII_RXD3                    267	/* CONN.ENET1.RGMII_RXD3, DMA.UART3.RX, VPU.TSI_S1.CLK, LSIO.GPIO6.IO21 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETA    268	/*  */
+/*@}*/
+
+#endif				/* SC_PADS_H */
diff --git a/plat/imx/common/include/imx8qx_pads.h b/plat/imx/common/include/imx8qx_pads.h
new file mode 100644
index 0000000..0e153bb
--- /dev/null
+++ b/plat/imx/common/include/imx8qx_pads.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file used to configure SoC pad list.
+ */
+
+#ifndef SC_PADS_H
+#define SC_PADS_H
+
+/* Includes */
+
+/* Defines */
+
+/*!
+ * @name Pad Definitions
+ */
+/*@{*/
+#define SC_P_PCIE_CTRL0_PERST_B                  0	/* HSIO.PCIE0.PERST_B, LSIO.GPIO4.IO00 */
+#define SC_P_PCIE_CTRL0_CLKREQ_B                 1	/* HSIO.PCIE0.CLKREQ_B, LSIO.GPIO4.IO01 */
+#define SC_P_PCIE_CTRL0_WAKE_B                   2	/* HSIO.PCIE0.WAKE_B, LSIO.GPIO4.IO02 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_PCIESEP       3	/*  */
+#define SC_P_USB_SS3_TC0                         4	/* ADMA.I2C1.SCL, CONN.USB_OTG1.PWR, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO03 */
+#define SC_P_USB_SS3_TC1                         5	/* ADMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO04 */
+#define SC_P_USB_SS3_TC2                         6	/* ADMA.I2C1.SDA, CONN.USB_OTG1.OC, CONN.USB_OTG2.OC, LSIO.GPIO4.IO05 */
+#define SC_P_USB_SS3_TC3                         7	/* ADMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO06 */
+#define SC_P_COMP_CTL_GPIO_3V3_USB3IO            8	/*  */
+#define SC_P_EMMC0_CLK                           9	/* CONN.EMMC0.CLK, CONN.NAND.READY_B, LSIO.GPIO4.IO07 */
+#define SC_P_EMMC0_CMD                           10	/* CONN.EMMC0.CMD, CONN.NAND.DQS, LSIO.GPIO4.IO08 */
+#define SC_P_EMMC0_DATA0                         11	/* CONN.EMMC0.DATA0, CONN.NAND.DATA00, LSIO.GPIO4.IO09 */
+#define SC_P_EMMC0_DATA1                         12	/* CONN.EMMC0.DATA1, CONN.NAND.DATA01, LSIO.GPIO4.IO10 */
+#define SC_P_EMMC0_DATA2                         13	/* CONN.EMMC0.DATA2, CONN.NAND.DATA02, LSIO.GPIO4.IO11 */
+#define SC_P_EMMC0_DATA3                         14	/* CONN.EMMC0.DATA3, CONN.NAND.DATA03, LSIO.GPIO4.IO12 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_SD1FIX0       15	/*  */
+#define SC_P_EMMC0_DATA4                         16	/* CONN.EMMC0.DATA4, CONN.NAND.DATA04, CONN.EMMC0.WP, LSIO.GPIO4.IO13 */
+#define SC_P_EMMC0_DATA5                         17	/* CONN.EMMC0.DATA5, CONN.NAND.DATA05, CONN.EMMC0.VSELECT, LSIO.GPIO4.IO14 */
+#define SC_P_EMMC0_DATA6                         18	/* CONN.EMMC0.DATA6, CONN.NAND.DATA06, CONN.MLB.CLK, LSIO.GPIO4.IO15 */
+#define SC_P_EMMC0_DATA7                         19	/* CONN.EMMC0.DATA7, CONN.NAND.DATA07, CONN.MLB.SIG, LSIO.GPIO4.IO16 */
+#define SC_P_EMMC0_STROBE                        20	/* CONN.EMMC0.STROBE, CONN.NAND.CLE, CONN.MLB.DATA, LSIO.GPIO4.IO17 */
+#define SC_P_EMMC0_RESET_B                       21	/* CONN.EMMC0.RESET_B, CONN.NAND.WP_B, LSIO.GPIO4.IO18 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_SD1FIX1       22	/*  */
+#define SC_P_USDHC1_RESET_B                      23	/* CONN.USDHC1.RESET_B, CONN.NAND.RE_N, ADMA.SPI2.SCK, LSIO.GPIO4.IO19 */
+#define SC_P_USDHC1_VSELECT                      24	/* CONN.USDHC1.VSELECT, CONN.NAND.RE_P, ADMA.SPI2.SDO, CONN.NAND.RE_B, LSIO.GPIO4.IO20 */
+#define SC_P_CTL_NAND_RE_P_N                     25	/*  */
+#define SC_P_USDHC1_WP                           26	/* CONN.USDHC1.WP, CONN.NAND.DQS_N, ADMA.SPI2.SDI, LSIO.GPIO4.IO21 */
+#define SC_P_USDHC1_CD_B                         27	/* CONN.USDHC1.CD_B, CONN.NAND.DQS_P, ADMA.SPI2.CS0, CONN.NAND.DQS, LSIO.GPIO4.IO22 */
+#define SC_P_CTL_NAND_DQS_P_N                    28	/*  */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSELSEP       29	/*  */
+#define SC_P_USDHC1_CLK                          30	/* CONN.USDHC1.CLK, ADMA.UART3.RX, LSIO.GPIO4.IO23 */
+#define SC_P_USDHC1_CMD                          31	/* CONN.USDHC1.CMD, CONN.NAND.CE0_B, ADMA.MQS.R, LSIO.GPIO4.IO24 */
+#define SC_P_USDHC1_DATA0                        32	/* CONN.USDHC1.DATA0, CONN.NAND.CE1_B, ADMA.MQS.L, LSIO.GPIO4.IO25 */
+#define SC_P_USDHC1_DATA1                        33	/* CONN.USDHC1.DATA1, CONN.NAND.RE_B, ADMA.UART3.TX, LSIO.GPIO4.IO26 */
+#define SC_P_USDHC1_DATA2                        34	/* CONN.USDHC1.DATA2, CONN.NAND.WE_B, ADMA.UART3.CTS_B, LSIO.GPIO4.IO27 */
+#define SC_P_USDHC1_DATA3                        35	/* CONN.USDHC1.DATA3, CONN.NAND.ALE, ADMA.UART3.RTS_B, LSIO.GPIO4.IO28 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSEL3         36	/*  */
+#define SC_P_ENET0_RGMII_TXC                     37	/* CONN.ENET0.RGMII_TXC, CONN.ENET0.RCLK50M_OUT, CONN.ENET0.RCLK50M_IN, CONN.NAND.CE1_B, LSIO.GPIO4.IO29 */
+#define SC_P_ENET0_RGMII_TX_CTL                  38	/* CONN.ENET0.RGMII_TX_CTL, CONN.USDHC1.RESET_B, LSIO.GPIO4.IO30 */
+#define SC_P_ENET0_RGMII_TXD0                    39	/* CONN.ENET0.RGMII_TXD0, CONN.USDHC1.VSELECT, LSIO.GPIO4.IO31 */
+#define SC_P_ENET0_RGMII_TXD1                    40	/* CONN.ENET0.RGMII_TXD1, CONN.USDHC1.WP, LSIO.GPIO5.IO00 */
+#define SC_P_ENET0_RGMII_TXD2                    41	/* CONN.ENET0.RGMII_TXD2, CONN.MLB.CLK, CONN.NAND.CE0_B, CONN.USDHC1.CD_B, LSIO.GPIO5.IO01 */
+#define SC_P_ENET0_RGMII_TXD3                    42	/* CONN.ENET0.RGMII_TXD3, CONN.MLB.SIG, CONN.NAND.RE_B, LSIO.GPIO5.IO02 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB0   43	/*  */
+#define SC_P_ENET0_RGMII_RXC                     44	/* CONN.ENET0.RGMII_RXC, CONN.MLB.DATA, CONN.NAND.WE_B, CONN.USDHC1.CLK, LSIO.GPIO5.IO03 */
+#define SC_P_ENET0_RGMII_RX_CTL                  45	/* CONN.ENET0.RGMII_RX_CTL, CONN.USDHC1.CMD, LSIO.GPIO5.IO04 */
+#define SC_P_ENET0_RGMII_RXD0                    46	/* CONN.ENET0.RGMII_RXD0, CONN.USDHC1.DATA0, LSIO.GPIO5.IO05 */
+#define SC_P_ENET0_RGMII_RXD1                    47	/* CONN.ENET0.RGMII_RXD1, CONN.USDHC1.DATA1, LSIO.GPIO5.IO06 */
+#define SC_P_ENET0_RGMII_RXD2                    48	/* CONN.ENET0.RGMII_RXD2, CONN.ENET0.RMII_RX_ER, CONN.USDHC1.DATA2, LSIO.GPIO5.IO07 */
+#define SC_P_ENET0_RGMII_RXD3                    49	/* CONN.ENET0.RGMII_RXD3, CONN.NAND.ALE, CONN.USDHC1.DATA3, LSIO.GPIO5.IO08 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB1   50	/*  */
+#define SC_P_ENET0_REFCLK_125M_25M               51	/* CONN.ENET0.REFCLK_125M_25M, CONN.ENET0.PPS, CONN.ENET1.PPS, LSIO.GPIO5.IO09 */
+#define SC_P_ENET0_MDIO                          52	/* CONN.ENET0.MDIO, ADMA.I2C3.SDA, CONN.ENET1.MDIO, LSIO.GPIO5.IO10 */
+#define SC_P_ENET0_MDC                           53	/* CONN.ENET0.MDC, ADMA.I2C3.SCL, CONN.ENET1.MDC, LSIO.GPIO5.IO11 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOCT        54	/*  */
+#define SC_P_ESAI0_FSR                           55	/* ADMA.ESAI0.FSR, CONN.ENET1.RCLK50M_OUT, ADMA.LCDIF.D00, CONN.ENET1.RGMII_TXC, CONN.ENET1.RCLK50M_IN */
+#define SC_P_ESAI0_FST                           56	/* ADMA.ESAI0.FST, CONN.MLB.CLK, ADMA.LCDIF.D01, CONN.ENET1.RGMII_TXD2, LSIO.GPIO0.IO01 */
+#define SC_P_ESAI0_SCKR                          57	/* ADMA.ESAI0.SCKR, ADMA.LCDIF.D02, CONN.ENET1.RGMII_TX_CTL, LSIO.GPIO0.IO02 */
+#define SC_P_ESAI0_SCKT                          58	/* ADMA.ESAI0.SCKT, CONN.MLB.SIG, ADMA.LCDIF.D03, CONN.ENET1.RGMII_TXD3, LSIO.GPIO0.IO03 */
+#define SC_P_ESAI0_TX0                           59	/* ADMA.ESAI0.TX0, CONN.MLB.DATA, ADMA.LCDIF.D04, CONN.ENET1.RGMII_RXC, LSIO.GPIO0.IO04 */
+#define SC_P_ESAI0_TX1                           60	/* ADMA.ESAI0.TX1, ADMA.LCDIF.D05, CONN.ENET1.RGMII_RXD3, LSIO.GPIO0.IO05 */
+#define SC_P_ESAI0_TX2_RX3                       61	/* ADMA.ESAI0.TX2_RX3, CONN.ENET1.RMII_RX_ER, ADMA.LCDIF.D06, CONN.ENET1.RGMII_RXD2, LSIO.GPIO0.IO06 */
+#define SC_P_ESAI0_TX3_RX2                       62	/* ADMA.ESAI0.TX3_RX2, ADMA.LCDIF.D07, CONN.ENET1.RGMII_RXD1, LSIO.GPIO0.IO07 */
+#define SC_P_ESAI0_TX4_RX1                       63	/* ADMA.ESAI0.TX4_RX1, ADMA.LCDIF.D08, CONN.ENET1.RGMII_TXD0, LSIO.GPIO0.IO08 */
+#define SC_P_ESAI0_TX5_RX0                       64	/* ADMA.ESAI0.TX5_RX0, ADMA.LCDIF.D09, CONN.ENET1.RGMII_TXD1, LSIO.GPIO0.IO09 */
+#define SC_P_SPDIF0_RX                           65	/* ADMA.SPDIF0.RX, ADMA.MQS.R, ADMA.LCDIF.D10, CONN.ENET1.RGMII_RXD0, LSIO.GPIO0.IO10 */
+#define SC_P_SPDIF0_TX                           66	/* ADMA.SPDIF0.TX, ADMA.MQS.L, ADMA.LCDIF.D11, CONN.ENET1.RGMII_RX_CTL, LSIO.GPIO0.IO11 */
+#define SC_P_SPDIF0_EXT_CLK                      67	/* ADMA.SPDIF0.EXT_CLK, ADMA.LCDIF.D12, CONN.ENET1.REFCLK_125M_25M, LSIO.GPIO0.IO12 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHB       68	/*  */
+#define SC_P_SPI3_SCK                            69	/* ADMA.SPI3.SCK, ADMA.LCDIF.D13, LSIO.GPIO0.IO13 */
+#define SC_P_SPI3_SDO                            70	/* ADMA.SPI3.SDO, ADMA.LCDIF.D14, LSIO.GPIO0.IO14 */
+#define SC_P_SPI3_SDI                            71	/* ADMA.SPI3.SDI, ADMA.LCDIF.D15, LSIO.GPIO0.IO15 */
+#define SC_P_SPI3_CS0                            72	/* ADMA.SPI3.CS0, ADMA.ACM.MCLK_OUT1, ADMA.LCDIF.HSYNC, LSIO.GPIO0.IO16 */
+#define SC_P_SPI3_CS1                            73	/* ADMA.SPI3.CS1, ADMA.I2C3.SCL, ADMA.LCDIF.RESET, ADMA.SPI2.CS0, ADMA.LCDIF.D16 */
+#define SC_P_MCLK_IN1                            74	/* ADMA.ACM.MCLK_IN1, ADMA.I2C3.SDA, ADMA.LCDIF.EN, ADMA.SPI2.SCK, ADMA.LCDIF.D17 */
+#define SC_P_MCLK_IN0                            75	/* ADMA.ACM.MCLK_IN0, ADMA.ESAI0.RX_HF_CLK, ADMA.LCDIF.VSYNC, ADMA.SPI2.SDI, LSIO.GPIO0.IO19 */
+#define SC_P_MCLK_OUT0                           76	/* ADMA.ACM.MCLK_OUT0, ADMA.ESAI0.TX_HF_CLK, ADMA.LCDIF.CLK, ADMA.SPI2.SDO, LSIO.GPIO0.IO20 */
+#define SC_P_UART1_TX                            77	/* ADMA.UART1.TX, LSIO.PWM0.OUT, LSIO.GPT0.CAPTURE, LSIO.GPIO0.IO21 */
+#define SC_P_UART1_RX                            78	/* ADMA.UART1.RX, LSIO.PWM1.OUT, LSIO.GPT0.COMPARE, LSIO.GPT1.CLK, LSIO.GPIO0.IO22 */
+#define SC_P_UART1_RTS_B                         79	/* ADMA.UART1.RTS_B, LSIO.PWM2.OUT, ADMA.LCDIF.D16, LSIO.GPT1.CAPTURE, LSIO.GPT0.CLK */
+#define SC_P_UART1_CTS_B                         80	/* ADMA.UART1.CTS_B, LSIO.PWM3.OUT, ADMA.LCDIF.D17, LSIO.GPT1.COMPARE, LSIO.GPIO0.IO24 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHK       81	/*  */
+#define SC_P_SAI0_TXD                            82	/* ADMA.SAI0.TXD, ADMA.SAI1.RXC, ADMA.SPI1.SDO, ADMA.LCDIF.D18, LSIO.GPIO0.IO25 */
+#define SC_P_SAI0_TXC                            83	/* ADMA.SAI0.TXC, ADMA.SAI1.TXD, ADMA.SPI1.SDI, ADMA.LCDIF.D19, LSIO.GPIO0.IO26 */
+#define SC_P_SAI0_RXD                            84	/* ADMA.SAI0.RXD, ADMA.SAI1.RXFS, ADMA.SPI1.CS0, ADMA.LCDIF.D20, LSIO.GPIO0.IO27 */
+#define SC_P_SAI0_TXFS                           85	/* ADMA.SAI0.TXFS, ADMA.SPI2.CS1, ADMA.SPI1.SCK, LSIO.GPIO0.IO28 */
+#define SC_P_SAI1_RXD                            86	/* ADMA.SAI1.RXD, ADMA.SAI0.RXFS, ADMA.SPI1.CS1, ADMA.LCDIF.D21, LSIO.GPIO0.IO29 */
+#define SC_P_SAI1_RXC                            87	/* ADMA.SAI1.RXC, ADMA.SAI1.TXC, ADMA.LCDIF.D22, LSIO.GPIO0.IO30 */
+#define SC_P_SAI1_RXFS                           88	/* ADMA.SAI1.RXFS, ADMA.SAI1.TXFS, ADMA.LCDIF.D23, LSIO.GPIO0.IO31 */
+#define SC_P_SPI2_CS0                            89	/* ADMA.SPI2.CS0, LSIO.GPIO1.IO00 */
+#define SC_P_SPI2_SDO                            90	/* ADMA.SPI2.SDO, LSIO.GPIO1.IO01 */
+#define SC_P_SPI2_SDI                            91	/* ADMA.SPI2.SDI, LSIO.GPIO1.IO02 */
+#define SC_P_SPI2_SCK                            92	/* ADMA.SPI2.SCK, LSIO.GPIO1.IO03 */
+#define SC_P_SPI0_SCK                            93	/* ADMA.SPI0.SCK, ADMA.SAI0.TXC, M40.I2C0.SCL, M40.GPIO0.IO00, LSIO.GPIO1.IO04 */
+#define SC_P_SPI0_SDI                            94	/* ADMA.SPI0.SDI, ADMA.SAI0.TXD, M40.TPM0.CH0, M40.GPIO0.IO02, LSIO.GPIO1.IO05 */
+#define SC_P_SPI0_SDO                            95	/* ADMA.SPI0.SDO, ADMA.SAI0.TXFS, M40.I2C0.SDA, M40.GPIO0.IO01, LSIO.GPIO1.IO06 */
+#define SC_P_SPI0_CS1                            96	/* ADMA.SPI0.CS1, ADMA.SAI0.RXC, ADMA.SAI1.TXD, ADMA.LCD_PWM0.OUT, LSIO.GPIO1.IO07 */
+#define SC_P_SPI0_CS0                            97	/* ADMA.SPI0.CS0, ADMA.SAI0.RXD, M40.TPM0.CH1, M40.GPIO0.IO03, LSIO.GPIO1.IO08 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHT       98	/*  */
+#define SC_P_ADC_IN1                             99	/* ADMA.ADC.IN1, M40.I2C0.SDA, M40.GPIO0.IO01, LSIO.GPIO1.IO09 */
+#define SC_P_ADC_IN0                             100	/* ADMA.ADC.IN0, M40.I2C0.SCL, M40.GPIO0.IO00, LSIO.GPIO1.IO10 */
+#define SC_P_ADC_IN3                             101	/* ADMA.ADC.IN3, M40.UART0.TX, M40.GPIO0.IO03, ADMA.ACM.MCLK_OUT0, LSIO.GPIO1.IO11 */
+#define SC_P_ADC_IN2                             102	/* ADMA.ADC.IN2, M40.UART0.RX, M40.GPIO0.IO02, ADMA.ACM.MCLK_IN0, LSIO.GPIO1.IO12 */
+#define SC_P_ADC_IN5                             103	/* ADMA.ADC.IN5, M40.TPM0.CH1, M40.GPIO0.IO05, LSIO.GPIO1.IO13 */
+#define SC_P_ADC_IN4                             104	/* ADMA.ADC.IN4, M40.TPM0.CH0, M40.GPIO0.IO04, LSIO.GPIO1.IO14 */
+#define SC_P_FLEXCAN0_RX                         105	/* ADMA.FLEXCAN0.RX, ADMA.SAI2.RXC, ADMA.UART0.RTS_B, ADMA.SAI1.TXC, LSIO.GPIO1.IO15 */
+#define SC_P_FLEXCAN0_TX                         106	/* ADMA.FLEXCAN0.TX, ADMA.SAI2.RXD, ADMA.UART0.CTS_B, ADMA.SAI1.TXFS, LSIO.GPIO1.IO16 */
+#define SC_P_FLEXCAN1_RX                         107	/* ADMA.FLEXCAN1.RX, ADMA.SAI2.RXFS, ADMA.FTM.CH2, ADMA.SAI1.TXD, LSIO.GPIO1.IO17 */
+#define SC_P_FLEXCAN1_TX                         108	/* ADMA.FLEXCAN1.TX, ADMA.SAI3.RXC, ADMA.DMA0.REQ_IN0, ADMA.SAI1.RXD, LSIO.GPIO1.IO18 */
+#define SC_P_FLEXCAN2_RX                         109	/* ADMA.FLEXCAN2.RX, ADMA.SAI3.RXD, ADMA.UART3.RX, ADMA.SAI1.RXFS, LSIO.GPIO1.IO19 */
+#define SC_P_FLEXCAN2_TX                         110	/* ADMA.FLEXCAN2.TX, ADMA.SAI3.RXFS, ADMA.UART3.TX, ADMA.SAI1.RXC, LSIO.GPIO1.IO20 */
+#define SC_P_UART0_RX                            111	/* ADMA.UART0.RX, ADMA.MQS.R, ADMA.FLEXCAN0.RX, SCU.UART0.RX, LSIO.GPIO1.IO21 */
+#define SC_P_UART0_TX                            112	/* ADMA.UART0.TX, ADMA.MQS.L, ADMA.FLEXCAN0.TX, SCU.UART0.TX, LSIO.GPIO1.IO22 */
+#define SC_P_UART2_TX                            113	/* ADMA.UART2.TX, ADMA.FTM.CH1, ADMA.FLEXCAN1.TX, LSIO.GPIO1.IO23 */
+#define SC_P_UART2_RX                            114	/* ADMA.UART2.RX, ADMA.FTM.CH0, ADMA.FLEXCAN1.RX, LSIO.GPIO1.IO24 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOLH        115	/*  */
+#define SC_P_MIPI_DSI0_I2C0_SCL                  116	/* MIPI_DSI0.I2C0.SCL, MIPI_DSI1.GPIO0.IO02, LSIO.GPIO1.IO25 */
+#define SC_P_MIPI_DSI0_I2C0_SDA                  117	/* MIPI_DSI0.I2C0.SDA, MIPI_DSI1.GPIO0.IO03, LSIO.GPIO1.IO26 */
+#define SC_P_MIPI_DSI0_GPIO0_00                  118	/* MIPI_DSI0.GPIO0.IO00, ADMA.I2C1.SCL, MIPI_DSI0.PWM0.OUT, LSIO.GPIO1.IO27 */
+#define SC_P_MIPI_DSI0_GPIO0_01                  119	/* MIPI_DSI0.GPIO0.IO01, ADMA.I2C1.SDA, LSIO.GPIO1.IO28 */
+#define SC_P_MIPI_DSI1_I2C0_SCL                  120	/* MIPI_DSI1.I2C0.SCL, MIPI_DSI0.GPIO0.IO02, LSIO.GPIO1.IO29 */
+#define SC_P_MIPI_DSI1_I2C0_SDA                  121	/* MIPI_DSI1.I2C0.SDA, MIPI_DSI0.GPIO0.IO03, LSIO.GPIO1.IO30 */
+#define SC_P_MIPI_DSI1_GPIO0_00                  122	/* MIPI_DSI1.GPIO0.IO00, ADMA.I2C2.SCL, MIPI_DSI1.PWM0.OUT, LSIO.GPIO1.IO31 */
+#define SC_P_MIPI_DSI1_GPIO0_01                  123	/* MIPI_DSI1.GPIO0.IO01, ADMA.I2C2.SDA, LSIO.GPIO2.IO00 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_MIPIDSIGPIO   124	/*  */
+#define SC_P_JTAG_TRST_B                         125	/* SCU.JTAG.TRST_B, SCU.WDOG0.WDOG_OUT */
+#define SC_P_PMIC_I2C_SCL                        126	/* SCU.PMIC_I2C.SCL, SCU.GPIO0.IOXX_PMIC_A35_ON, LSIO.GPIO2.IO01 */
+#define SC_P_PMIC_I2C_SDA                        127	/* SCU.PMIC_I2C.SDA, SCU.GPIO0.IOXX_PMIC_GPU_ON, LSIO.GPIO2.IO02 */
+#define SC_P_PMIC_INT_B                          128	/* SCU.DSC.PMIC_INT_B */
+#define SC_P_SCU_GPIO0_00                        129	/* SCU.GPIO0.IO00, SCU.UART0.RX, M40.UART0.RX, ADMA.UART3.RX, LSIO.GPIO2.IO03 */
+#define SC_P_SCU_GPIO0_01                        130	/* SCU.GPIO0.IO01, SCU.UART0.TX, M40.UART0.TX, ADMA.UART3.TX, SCU.WDOG0.WDOG_OUT */
+#define SC_P_SCU_PMIC_STANDBY                    131	/* SCU.DSC.PMIC_STANDBY */
+#define SC_P_SCU_BOOT_MODE0                      132	/* SCU.DSC.BOOT_MODE0 */
+#define SC_P_SCU_BOOT_MODE1                      133	/* SCU.DSC.BOOT_MODE1 */
+#define SC_P_SCU_BOOT_MODE2                      134	/* SCU.DSC.BOOT_MODE2, SCU.PMIC_I2C.SDA */
+#define SC_P_SCU_BOOT_MODE3                      135	/* SCU.DSC.BOOT_MODE3, SCU.PMIC_I2C.SCL, SCU.DSC.RTC_CLOCK_OUTPUT_32K */
+#define SC_P_CSI_D00                             136	/* CI_PI.D02, ADMA.SAI0.RXC */
+#define SC_P_CSI_D01                             137	/* CI_PI.D03, ADMA.SAI0.RXD */
+#define SC_P_CSI_D02                             138	/* CI_PI.D04, ADMA.SAI0.RXFS */
+#define SC_P_CSI_D03                             139	/* CI_PI.D05, ADMA.SAI2.RXC */
+#define SC_P_CSI_D04                             140	/* CI_PI.D06, ADMA.SAI2.RXD */
+#define SC_P_CSI_D05                             141	/* CI_PI.D07, ADMA.SAI2.RXFS */
+#define SC_P_CSI_D06                             142	/* CI_PI.D08, ADMA.SAI3.RXC */
+#define SC_P_CSI_D07                             143	/* CI_PI.D09, ADMA.SAI3.RXD */
+#define SC_P_CSI_HSYNC                           144	/* CI_PI.HSYNC, CI_PI.D00, ADMA.SAI3.RXFS */
+#define SC_P_CSI_VSYNC                           145	/* CI_PI.VSYNC, CI_PI.D01 */
+#define SC_P_CSI_PCLK                            146	/* CI_PI.PCLK, MIPI_CSI0.I2C0.SCL, ADMA.SPI1.SCK, LSIO.GPIO3.IO00 */
+#define SC_P_CSI_MCLK                            147	/* CI_PI.MCLK, MIPI_CSI0.I2C0.SDA, ADMA.SPI1.SDO, LSIO.GPIO3.IO01 */
+#define SC_P_CSI_EN                              148	/* CI_PI.EN, CI_PI.I2C.SCL, ADMA.I2C3.SCL, ADMA.SPI1.SDI, LSIO.GPIO3.IO02 */
+#define SC_P_CSI_RESET                           149	/* CI_PI.RESET, CI_PI.I2C.SDA, ADMA.I2C3.SDA, ADMA.SPI1.CS0, LSIO.GPIO3.IO03 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHD       150	/*  */
+#define SC_P_MIPI_CSI0_MCLK_OUT                  151	/* MIPI_CSI0.ACM.MCLK_OUT, LSIO.GPIO3.IO04 */
+#define SC_P_MIPI_CSI0_I2C0_SCL                  152	/* MIPI_CSI0.I2C0.SCL, MIPI_CSI0.GPIO0.IO02, LSIO.GPIO3.IO05 */
+#define SC_P_MIPI_CSI0_I2C0_SDA                  153	/* MIPI_CSI0.I2C0.SDA, MIPI_CSI0.GPIO0.IO03, LSIO.GPIO3.IO06 */
+#define SC_P_MIPI_CSI0_GPIO0_01                  154	/* MIPI_CSI0.GPIO0.IO01, ADMA.I2C0.SDA, LSIO.GPIO3.IO07 */
+#define SC_P_MIPI_CSI0_GPIO0_00                  155	/* MIPI_CSI0.GPIO0.IO00, ADMA.I2C0.SCL, LSIO.GPIO3.IO08 */
+#define SC_P_QSPI0A_DATA0                        156	/* LSIO.QSPI0A.DATA0, LSIO.GPIO3.IO09 */
+#define SC_P_QSPI0A_DATA1                        157	/* LSIO.QSPI0A.DATA1, LSIO.GPIO3.IO10 */
+#define SC_P_QSPI0A_DATA2                        158	/* LSIO.QSPI0A.DATA2, LSIO.GPIO3.IO11 */
+#define SC_P_QSPI0A_DATA3                        159	/* LSIO.QSPI0A.DATA3, LSIO.GPIO3.IO12 */
+#define SC_P_QSPI0A_DQS                          160	/* LSIO.QSPI0A.DQS, LSIO.GPIO3.IO13 */
+#define SC_P_QSPI0A_SS0_B                        161	/* LSIO.QSPI0A.SS0_B, LSIO.GPIO3.IO14 */
+#define SC_P_QSPI0A_SS1_B                        162	/* LSIO.QSPI0A.SS1_B, LSIO.GPIO3.IO15 */
+#define SC_P_QSPI0A_SCLK                         163	/* LSIO.QSPI0A.SCLK, LSIO.GPIO3.IO16 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI0A        164	/*  */
+#define SC_P_QSPI0B_SCLK                         165	/* LSIO.QSPI0B.SCLK, LSIO.QSPI1A.SCLK, LSIO.KPP0.COL0, LSIO.GPIO3.IO17 */
+#define SC_P_QSPI0B_DATA0                        166	/* LSIO.QSPI0B.DATA0, LSIO.QSPI1A.DATA0, LSIO.KPP0.COL1, LSIO.GPIO3.IO18 */
+#define SC_P_QSPI0B_DATA1                        167	/* LSIO.QSPI0B.DATA1, LSIO.QSPI1A.DATA1, LSIO.KPP0.COL2, LSIO.GPIO3.IO19 */
+#define SC_P_QSPI0B_DATA2                        168	/* LSIO.QSPI0B.DATA2, LSIO.QSPI1A.DATA2, LSIO.KPP0.COL3, LSIO.GPIO3.IO20 */
+#define SC_P_QSPI0B_DATA3                        169	/* LSIO.QSPI0B.DATA3, LSIO.QSPI1A.DATA3, LSIO.KPP0.ROW0, LSIO.GPIO3.IO21 */
+#define SC_P_QSPI0B_DQS                          170	/* LSIO.QSPI0B.DQS, LSIO.QSPI1A.DQS, LSIO.KPP0.ROW1, LSIO.GPIO3.IO22 */
+#define SC_P_QSPI0B_SS0_B                        171	/* LSIO.QSPI0B.SS0_B, LSIO.QSPI1A.SS0_B, LSIO.KPP0.ROW2, LSIO.GPIO3.IO23 */
+#define SC_P_QSPI0B_SS1_B                        172	/* LSIO.QSPI0B.SS1_B, LSIO.QSPI1A.SS1_B, LSIO.KPP0.ROW3, LSIO.GPIO3.IO24 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI0B        173	/*  */
+/*@}*/
+
+#endif				/* SC_PADS_H */
diff --git a/plat/imx/common/include/plat_imx8.h b/plat/imx/common/include/plat_imx8.h
new file mode 100644
index 0000000..27d4c37
--- /dev/null
+++ b/plat/imx/common/include/plat_imx8.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_IMX8_H__
+#define __PLAT_IMX8_H__
+
+#include <gicv3.h>
+
+unsigned int plat_calc_core_pos(uint64_t mpidr);
+void imx_mailbox_init(uintptr_t base_addr);
+void plat_gic_driver_init(void);
+void plat_gic_init(void);
+void plat_gic_cpuif_enable(void);
+void plat_gic_cpuif_disable(void);
+void plat_gic_pcpu_init(void);
+
+#endif /*__PLAT_IMX8_H__ */
diff --git a/plat/imx/common/include/plat_macros.S b/plat/imx/common/include/plat_macros.S
new file mode 100644
index 0000000..30cce0a
--- /dev/null
+++ b/plat/imx/common/include/plat_macros.S
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * the below macros print out relevant GIC
+ * registers whenever an unhandled exception is
+ * taken in BL3-1
+ */
+.macro plat_print_gic_regs
+	/* TODO */
+.endm
+
+/*
+ * the below macros print out relevant interconnect
+ * registers whenever an unhandled exception is
+ * taken in BL3-1
+ */
+.macro plat_print_interconnect_regs
+	/* TODO */
+.endm
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * ---------------------------------------------
+ */
+.macro plat_crash_print_regs
+      /* TODO */
+.endm
diff --git a/plat/imx/common/include/sci/sci.h b/plat/imx/common/include/sci/sci.h
new file mode 100644
index 0000000..3dd17ce
--- /dev/null
+++ b/plat/imx/common/include/sci/sci.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _SC_SCI_H
+#define _SC_SCI_H
+
+/* Defines */
+
+/* Includes */
+
+#include <sci/sci_ipc.h>
+#include <sci/svc/pad/sci_pad_api.h>
+#include <sci/svc/pm/sci_pm_api.h>
+#include <sci/svc/rm/sci_rm_api.h>
+
+#endif /* _SC_SCI_H */
diff --git a/plat/imx/common/include/sci/sci_ipc.h b/plat/imx/common/include/sci/sci_ipc.h
new file mode 100644
index 0000000..c169a79
--- /dev/null
+++ b/plat/imx/common/include/sci/sci_ipc.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file for the IPC implementation.
+ */
+
+#ifndef SC_IPC_H
+#define SC_IPC_H
+
+/* Includes */
+
+#include <sci/sci_types.h>
+
+/* Defines */
+
+/* Types */
+
+/* Functions */
+
+/*!
+ * This function opens an IPC channel.
+ *
+ * @param[out]    ipc         return pointer for ipc handle
+ * @param[in]     id          id of channel to open
+ *
+ * @return Returns an error code (SC_ERR_NONE = success, SC_ERR_IPC
+ *         otherwise).
+ *
+ * The \a id parameter is implementation specific. Could be an MU
+ * address, pointer to a driver path, channel index, etc.
+ */
+sc_err_t sc_ipc_open(sc_ipc_t *ipc, sc_ipc_id_t id);
+
+/*!
+ * This function closes an IPC channel.
+ *
+ * @param[in]     ipc         id of channel to close
+ */
+void sc_ipc_close(sc_ipc_t ipc);
+
+/*!
+ * This function reads a message from an IPC channel.
+ *
+ * @param[in]     ipc         id of channel read from
+ * @param[out]    data        pointer to message buffer to read
+ *
+ * This function will block if no message is available to be read.
+ */
+void sc_ipc_read(sc_ipc_t ipc, void *data);
+
+/*!
+ * This function writes a message to an IPC channel.
+ *
+ * @param[in]     ipc         id of channel to write to
+ * @param[in]     data        pointer to message buffer to write
+ *
+ * This function will block if the outgoing buffer is full.
+ */
+void sc_ipc_write(sc_ipc_t ipc, void *data);
+
+sc_ipc_t ipc_handle;
+
+#endif				/* SC_IPC_H */
diff --git a/plat/imx/common/include/sci/sci_rpc.h b/plat/imx/common/include/sci/sci_rpc.h
new file mode 100644
index 0000000..052f361
--- /dev/null
+++ b/plat/imx/common/include/sci/sci_rpc.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file for the RPC implementation.
+ */
+
+#ifndef SC_RPC_H
+#define SC_RPC_H
+
+/* Includes */
+
+#include <sci/sci_types.h>
+#include <sci/sci_ipc.h>
+#include <stdbool.h>
+
+/* Defines */
+
+#define SC_RPC_VERSION          1U
+
+#define SC_RPC_MAX_MSG          8U
+
+#define RPC_VER(MSG)            ((MSG)->version)
+#define RPC_SIZE(MSG)           ((MSG)->size)
+#define RPC_SVC(MSG)            ((MSG)->svc)
+#define RPC_FUNC(MSG)           ((MSG)->func)
+#define RPC_R8(MSG)             ((MSG)->func)
+#define RPC_I32(MSG, IDX)       ((MSG)->DATA.i32[(IDX) / 4U])
+#define RPC_I16(MSG, IDX)       ((MSG)->DATA.i16[(IDX) / 2U])
+#define RPC_I8(MSG, IDX)        ((MSG)->DATA.i8[(IDX)])
+#define RPC_U32(MSG, IDX)       ((MSG)->DATA.u32[(IDX) / 4U])
+#define RPC_U16(MSG, IDX)       ((MSG)->DATA.u16[(IDX) / 2U])
+#define RPC_U8(MSG, IDX)        ((MSG)->DATA.u8[(IDX)])
+
+#define SC_RPC_SVC_UNKNOWN      0U
+#define SC_RPC_SVC_RETURN       1U
+#define SC_RPC_SVC_PM           2U
+#define SC_RPC_SVC_RM           3U
+#define SC_RPC_SVC_TIMER        5U
+#define SC_RPC_SVC_PAD          6U
+#define SC_RPC_SVC_MISC         7U
+#define SC_RPC_SVC_IRQ          8U
+#define SC_RPC_SVC_ABORT        9U
+
+#define SC_RPC_ASYNC_STATE_RD_START      0U
+#define SC_RPC_ASYNC_STATE_RD_ACTIVE     1U
+#define SC_RPC_ASYNC_STATE_RD_DONE       2U
+#define SC_RPC_ASYNC_STATE_WR_START      3U
+#define SC_RPC_ASYNC_STATE_WR_ACTIVE     4U
+#define SC_RPC_ASYNC_STATE_WR_DONE       5U
+
+#define SC_RPC_MU_GIR_SVC       0x1U
+#define SC_RPC_MU_GIR_DBG       0x8U
+
+/* Types */
+
+typedef uint8_t sc_rpc_svc_t;
+
+typedef struct sc_rpc_msg_s {
+	uint8_t version;
+	uint8_t size;
+	uint8_t svc;
+	uint8_t func;
+	union {
+		int32_t i32[(SC_RPC_MAX_MSG - 1U)];
+		int16_t i16[(SC_RPC_MAX_MSG - 1U) * 2U];
+		int8_t i8[(SC_RPC_MAX_MSG - 1U) * 4U];
+		uint32_t u32[(SC_RPC_MAX_MSG - 1U)];
+		uint16_t u16[(SC_RPC_MAX_MSG - 1U) * 2U];
+		uint8_t u8[(SC_RPC_MAX_MSG - 1U) * 4U];
+	} DATA;
+} sc_rpc_msg_t;
+
+typedef uint8_t sc_rpc_async_state_t;
+
+typedef struct sc_rpc_async_msg_s {
+	sc_rpc_async_state_t state;
+	uint8_t wordIdx;
+	sc_rpc_msg_t msg;
+	uint32_t timeStamp;
+} sc_rpc_async_msg_t;
+
+/* Functions */
+
+/*!
+ * This is an internal function to send an RPC message over an IPC
+ * channel. It is called by client-side SCFW API function shims.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in,out] msg         handle to a message
+ * @param[in]     no_resp     response flag
+ *
+ * If \a no_resp is SC_FALSE then this function waits for a response
+ * and returns the result in \a msg.
+ */
+void sc_call_rpc(sc_ipc_t ipc, sc_rpc_msg_t *msg, bool no_resp);
+
+/*!
+ * This is an internal function to dispath an RPC call that has
+ * arrived via IPC over an MU. It is called by server-side SCFW.
+ *
+ * @param[in]     mu          MU message arrived on
+ * @param[in,out] msg         handle to a message
+ *
+ * The function result is returned in \a msg.
+ */
+void sc_rpc_dispatch(sc_rsrc_t mu, sc_rpc_msg_t *msg);
+
+/*!
+ * This function translates an RPC message and forwards on to the
+ * normal RPC API.  It is used only by hypervisors.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in,out] msg         handle to a message
+ *
+ * This function decodes a message, calls macros to translate the
+ * resources, pads, addresses, partitions, memory regions, etc. and
+ * then forwards on to the hypervisors SCFW API.Return results are
+ * translated back abd placed back into the message to be returned
+ * to the original API.
+ */
+void sc_rpc_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg);
+
+#endif				/* SC_RPC_H */
diff --git a/plat/imx/common/include/sci/sci_scfw.h b/plat/imx/common/include/sci/sci_scfw.h
new file mode 100644
index 0000000..9d08dad
--- /dev/null
+++ b/plat/imx/common/include/sci/sci_scfw.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _SC_SCFW_H
+#define _SC_SCFW_H
+
+/* Includes */
+
+#include <types.h>
+
+#ifdef __cplusplus
+  #define   __I     volatile             /*!< Defines 'read only' permissions                 */
+#else
+  #define   __I     volatile const       /*!< Defines 'read only' permissions                 */
+#endif
+#define     __O     volatile             /*!< Defines 'write only' permissions                */
+#define     __IO    volatile             /*!< Defines 'read / write' permissions              */
+
+/*!
+ * This type is used to declare a handle for an IPC communication
+ * channel. Its meaning is specific to the IPC implementation.
+ */
+typedef uint64_t sc_ipc_t;
+
+/*!
+ * This type is used to declare an ID for an IPC communication
+ * channel. For the reference IPC implementation, this ID
+ * selects the base address of the MU used for IPC.
+ */
+typedef uint64_t sc_ipc_id_t;
+
+
+#endif /* _SC_SCFW_H */
+
diff --git a/plat/imx/common/include/sci/sci_types.h b/plat/imx/common/include/sci/sci_types.h
new file mode 100644
index 0000000..3ee5276
--- /dev/null
+++ b/plat/imx/common/include/sci/sci_types.h
@@ -0,0 +1,849 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file containing types used across multiple service APIs.
+ */
+
+#ifndef SC_TYPES_H
+#define SC_TYPES_H
+
+/* Includes */
+
+#include <sci/sci_scfw.h>
+
+/* Defines */
+
+/*!
+ * @name Defines for common frequencies
+ */
+/*@{*/
+#define SC_32KHZ            32768U	/* 32KHz */
+#define SC_10MHZ         10000000U	/* 10MHz */
+#define SC_20MHZ         20000000U	/* 20MHz */
+#define SC_25MHZ         25000000U	/* 25MHz */
+#define SC_27MHZ         27000000U	/* 27MHz */
+#define SC_40MHZ         40000000U	/* 40MHz */
+#define SC_45MHZ         45000000U	/* 45MHz */
+#define SC_50MHZ         50000000U	/* 50MHz */
+#define SC_60MHZ         60000000U	/* 60MHz */
+#define SC_66MHZ         66666666U	/* 66MHz */
+#define SC_74MHZ         74250000U	/* 74.25MHz */
+#define SC_80MHZ         80000000U	/* 80MHz */
+#define SC_83MHZ         83333333U	/* 83MHz */
+#define SC_84MHZ         84375000U	/* 84.37MHz */
+#define SC_100MHZ       100000000U	/* 100MHz */
+#define SC_125MHZ       125000000U	/* 125MHz */
+#define SC_133MHZ       133333333U	/* 133MHz */
+#define SC_135MHZ       135000000U	/* 135MHz */
+#define SC_150MHZ       150000000U	/* 150MHz */
+#define SC_160MHZ       160000000U	/* 160MHz */
+#define SC_166MHZ       166666666U	/* 166MHz */
+#define SC_175MHZ       175000000U	/* 175MHz */
+#define SC_180MHZ       180000000U	/* 180MHz */
+#define SC_200MHZ       200000000U	/* 200MHz */
+#define SC_250MHZ       250000000U	/* 250MHz */
+#define SC_266MHZ       266666666U	/* 266MHz */
+#define SC_300MHZ       300000000U	/* 300MHz */
+#define SC_312MHZ       312500000U	/* 312.5MHZ */
+#define SC_320MHZ       320000000U	/* 320MHz */
+#define SC_325MHZ       325000000U	/* 325MHz */
+#define SC_333MHZ       333333333U	/* 333MHz */
+#define SC_350MHZ       350000000U	/* 350MHz */
+#define SC_372MHZ       372000000U	/* 372MHz */
+#define SC_375MHZ       375000000U	/* 375MHz */
+#define SC_400MHZ       400000000U	/* 400MHz */
+#define SC_500MHZ       500000000U	/* 500MHz */
+#define SC_594MHZ       594000000U	/* 594MHz */
+#define SC_625MHZ       625000000U	/* 625MHz */
+#define SC_640MHZ       640000000U	/* 640MHz */
+#define SC_650MHZ       650000000U	/* 650MHz */
+#define SC_667MHZ       666666667U	/* 667MHz */
+#define SC_675MHZ       675000000U	/* 675MHz */
+#define SC_700MHZ       700000000U	/* 700MHz */
+#define SC_720MHZ       720000000U	/* 720MHz */
+#define SC_750MHZ       750000000U	/* 750MHz */
+#define SC_800MHZ       800000000U	/* 800MHz */
+#define SC_850MHZ       850000000U	/* 850MHz */
+#define SC_900MHZ       900000000U	/* 900MHz */
+#define SC_1000MHZ     1000000000U	/* 1GHz */
+#define SC_1056MHZ     1056000000U	/* 1.056GHz */
+#define SC_1188MHZ     1188000000U	/* 1.188GHz */
+#define SC_1260MHZ     1260000000U	/* 1.26GHz */
+#define SC_1280MHZ     1280000000U	/* 1.28GHz */
+#define SC_1300MHZ     1300000000U	/* 1.3GHz */
+#define SC_1400MHZ     1400000000U	/* 1.4GHz */
+#define SC_1500MHZ     1500000000U	/* 1.5GHz */
+#define SC_1600MHZ     1600000000U	/* 1.6GHz */
+#define SC_1800MHZ     1800000000U	/* 1.8GHz */
+#define SC_2000MHZ     2000000000U	/* 2.0GHz */
+#define SC_2112MHZ     2112000000U	/* 2.12GHz */
+/*@}*/
+
+/*!
+ * @name Defines for 24M related frequencies
+ */
+/*@{*/
+#define SC_8MHZ           8000000U	/* 8MHz */
+#define SC_12MHZ         12000000U	/* 12MHz */
+#define SC_19MHZ         19800000U	/* 19.8MHz */
+#define SC_24MHZ         24000000U	/* 24MHz */
+#define SC_48MHZ         48000000U	/* 48MHz */
+#define SC_120MHZ       120000000U	/* 120MHz */
+#define SC_132MHZ       132000000U	/* 132MHz */
+#define SC_144MHZ       144000000U	/* 144MHz */
+#define SC_192MHZ       192000000U	/* 192MHz */
+#define SC_211MHZ       211200000U	/* 211.2MHz */
+#define SC_240MHZ       240000000U	/* 240MHz */
+#define SC_264MHZ       264000000U	/* 264MHz */
+#define SC_352MHZ       352000000U	/* 352MHz */
+#define SC_360MHZ       360000000U	/* 360MHz */
+#define SC_384MHZ       384000000U	/* 384MHz */
+#define SC_396MHZ       396000000U	/* 396MHz */
+#define SC_432MHZ       432000000U	/* 432MHz */
+#define SC_480MHZ       480000000U	/* 480MHz */
+#define SC_600MHZ       600000000U	/* 600MHz */
+#define SC_744MHZ       744000000U	/* 744MHz */
+#define SC_792MHZ       792000000U	/* 792MHz */
+#define SC_864MHZ       864000000U	/* 864MHz */
+#define SC_960MHZ       960000000U	/* 960MHz */
+#define SC_1056MHZ     1056000000U	/* 1056MHz */
+#define SC_1200MHZ     1200000000U	/* 1.2GHz */
+#define SC_1464MHZ     1464000000U	/* 1.464GHz */
+#define SC_2400MHZ     2400000000U	/* 2.4GHz */
+/*@}*/
+
+/*!
+ * @name Defines for A/V related frequencies
+ */
+/*@{*/
+#define SC_62MHZ         62937500U	/* 62.9375MHz */
+#define SC_755MHZ       755250000U	/* 755.25MHz */
+/*@}*/
+
+/*!
+ * @name Defines for type widths
+ */
+/*@{*/
+#define SC_FADDR_W      36U	/* Width of sc_faddr_t */
+#define SC_BOOL_W       1U	/* Width of sc_bool_t */
+#define SC_ERR_W        4U	/* Width of sc_err_t */
+#define SC_RSRC_W       10U	/* Width of sc_rsrc_t */
+#define SC_CTRL_W       6U	/* Width of sc_ctrl_t */
+/*@}*/
+
+/*!
+ * @name Defines for sc_bool_t
+ */
+/*@{*/
+#define SC_FALSE        ((sc_bool_t) 0U)	/* True */
+#define SC_TRUE         ((sc_bool_t) 1U)	/* False */
+/*@}*/
+
+/*!
+ * @name Defines for sc_err_t.
+ */
+/*@{*/
+#define SC_ERR_NONE         0U	/* Success */
+#define SC_ERR_VERSION      1U	/* Incompatible API version */
+#define SC_ERR_CONFIG       2U	/* Configuration error */
+#define SC_ERR_PARM         3U	/* Bad parameter */
+#define SC_ERR_NOACCESS     4U	/* Permission error (no access) */
+#define SC_ERR_LOCKED       5U	/* Permission error (locked) */
+#define SC_ERR_UNAVAILABLE  6U	/* Unavailable (out of resources) */
+#define SC_ERR_NOTFOUND     7U	/* Not found */
+#define SC_ERR_NOPOWER      8U	/* No power */
+#define SC_ERR_IPC          9U	/* Generic IPC error */
+#define SC_ERR_BUSY         10U	/* Resource is currently busy/active */
+#define SC_ERR_FAIL         11U	/* General I/O failure */
+#define SC_ERR_LAST         12U
+/*@}*/
+
+/*!
+ * @name Defines for sc_rsrc_t.
+ */
+/*@{*/
+#define SC_R_A53                  0U
+#define SC_R_A53_0                1U
+#define SC_R_A53_1                2U
+#define SC_R_A53_2                3U
+#define SC_R_A53_3                4U
+#define SC_R_A72                  5U
+#define SC_R_A72_0                6U
+#define SC_R_A72_1                7U
+#define SC_R_A72_2                8U
+#define SC_R_A72_3                9U
+#define SC_R_CCI                  10U
+#define SC_R_DB                   11U
+#define SC_R_DRC_0                12U
+#define SC_R_DRC_1                13U
+#define SC_R_GIC_SMMU             14U
+#define SC_R_IRQSTR_M4_0          15U
+#define SC_R_IRQSTR_M4_1          16U
+#define SC_R_SMMU                 17U
+#define SC_R_GIC                  18U
+#define SC_R_DC_0_BLIT0           19U
+#define SC_R_DC_0_BLIT1           20U
+#define SC_R_DC_0_BLIT2           21U
+#define SC_R_DC_0_BLIT_OUT        22U
+#define SC_R_DC_0_CAPTURE0        23U
+#define SC_R_DC_0_CAPTURE1        24U
+#define SC_R_DC_0_WARP            25U
+#define SC_R_DC_0_INTEGRAL0       26U
+#define SC_R_DC_0_INTEGRAL1       27U
+#define SC_R_DC_0_VIDEO0          28U
+#define SC_R_DC_0_VIDEO1          29U
+#define SC_R_DC_0_FRAC0           30U
+#define SC_R_DC_0_FRAC1           31U
+#define SC_R_DC_0                 32U
+#define SC_R_GPU_2_PID0           33U
+#define SC_R_DC_0_PLL_0           34U
+#define SC_R_DC_0_PLL_1           35U
+#define SC_R_DC_1_BLIT0           36U
+#define SC_R_DC_1_BLIT1           37U
+#define SC_R_DC_1_BLIT2           38U
+#define SC_R_DC_1_BLIT_OUT        39U
+#define SC_R_DC_1_CAPTURE0        40U
+#define SC_R_DC_1_CAPTURE1        41U
+#define SC_R_DC_1_WARP            42U
+#define SC_R_DC_1_INTEGRAL0       43U
+#define SC_R_DC_1_INTEGRAL1       44U
+#define SC_R_DC_1_VIDEO0          45U
+#define SC_R_DC_1_VIDEO1          46U
+#define SC_R_DC_1_FRAC0           47U
+#define SC_R_DC_1_FRAC1           48U
+#define SC_R_DC_1                 49U
+#define SC_R_GPU_3_PID0           50U
+#define SC_R_DC_1_PLL_0           51U
+#define SC_R_DC_1_PLL_1           52U
+#define SC_R_SPI_0                53U
+#define SC_R_SPI_1                54U
+#define SC_R_SPI_2                55U
+#define SC_R_SPI_3                56U
+#define SC_R_UART_0               57U
+#define SC_R_UART_1               58U
+#define SC_R_UART_2               59U
+#define SC_R_UART_3               60U
+#define SC_R_UART_4               61U
+#define SC_R_EMVSIM_0             62U
+#define SC_R_EMVSIM_1             63U
+#define SC_R_DMA_0_CH0            64U
+#define SC_R_DMA_0_CH1            65U
+#define SC_R_DMA_0_CH2            66U
+#define SC_R_DMA_0_CH3            67U
+#define SC_R_DMA_0_CH4            68U
+#define SC_R_DMA_0_CH5            69U
+#define SC_R_DMA_0_CH6            70U
+#define SC_R_DMA_0_CH7            71U
+#define SC_R_DMA_0_CH8            72U
+#define SC_R_DMA_0_CH9            73U
+#define SC_R_DMA_0_CH10           74U
+#define SC_R_DMA_0_CH11           75U
+#define SC_R_DMA_0_CH12           76U
+#define SC_R_DMA_0_CH13           77U
+#define SC_R_DMA_0_CH14           78U
+#define SC_R_DMA_0_CH15           79U
+#define SC_R_DMA_0_CH16           80U
+#define SC_R_DMA_0_CH17           81U
+#define SC_R_DMA_0_CH18           82U
+#define SC_R_DMA_0_CH19           83U
+#define SC_R_DMA_0_CH20           84U
+#define SC_R_DMA_0_CH21           85U
+#define SC_R_DMA_0_CH22           86U
+#define SC_R_DMA_0_CH23           87U
+#define SC_R_DMA_0_CH24           88U
+#define SC_R_DMA_0_CH25           89U
+#define SC_R_DMA_0_CH26           90U
+#define SC_R_DMA_0_CH27           91U
+#define SC_R_DMA_0_CH28           92U
+#define SC_R_DMA_0_CH29           93U
+#define SC_R_DMA_0_CH30           94U
+#define SC_R_DMA_0_CH31           95U
+#define SC_R_I2C_0                96U
+#define SC_R_I2C_1                97U
+#define SC_R_I2C_2                98U
+#define SC_R_I2C_3                99U
+#define SC_R_I2C_4                100U
+#define SC_R_ADC_0                101U
+#define SC_R_ADC_1                102U
+#define SC_R_FTM_0                103U
+#define SC_R_FTM_1                104U
+#define SC_R_CAN_0                105U
+#define SC_R_CAN_1                106U
+#define SC_R_CAN_2                107U
+#define SC_R_DMA_1_CH0            108U
+#define SC_R_DMA_1_CH1            109U
+#define SC_R_DMA_1_CH2            110U
+#define SC_R_DMA_1_CH3            111U
+#define SC_R_DMA_1_CH4            112U
+#define SC_R_DMA_1_CH5            113U
+#define SC_R_DMA_1_CH6            114U
+#define SC_R_DMA_1_CH7            115U
+#define SC_R_DMA_1_CH8            116U
+#define SC_R_DMA_1_CH9            117U
+#define SC_R_DMA_1_CH10           118U
+#define SC_R_DMA_1_CH11           119U
+#define SC_R_DMA_1_CH12           120U
+#define SC_R_DMA_1_CH13           121U
+#define SC_R_DMA_1_CH14           122U
+#define SC_R_DMA_1_CH15           123U
+#define SC_R_DMA_1_CH16           124U
+#define SC_R_DMA_1_CH17           125U
+#define SC_R_DMA_1_CH18           126U
+#define SC_R_DMA_1_CH19           127U
+#define SC_R_DMA_1_CH20           128U
+#define SC_R_DMA_1_CH21           129U
+#define SC_R_DMA_1_CH22           130U
+#define SC_R_DMA_1_CH23           131U
+#define SC_R_DMA_1_CH24           132U
+#define SC_R_DMA_1_CH25           133U
+#define SC_R_DMA_1_CH26           134U
+#define SC_R_DMA_1_CH27           135U
+#define SC_R_DMA_1_CH28           136U
+#define SC_R_DMA_1_CH29           137U
+#define SC_R_DMA_1_CH30           138U
+#define SC_R_DMA_1_CH31           139U
+#define SC_R_UNUSED1              140U
+#define SC_R_UNUSED2              141U
+#define SC_R_UNUSED3              142U
+#define SC_R_UNUSED4              143U
+#define SC_R_GPU_0_PID0           144U
+#define SC_R_GPU_0_PID1           145U
+#define SC_R_GPU_0_PID2           146U
+#define SC_R_GPU_0_PID3           147U
+#define SC_R_GPU_1_PID0           148U
+#define SC_R_GPU_1_PID1           149U
+#define SC_R_GPU_1_PID2           150U
+#define SC_R_GPU_1_PID3           151U
+#define SC_R_PCIE_A               152U
+#define SC_R_SERDES_0             153U
+#define SC_R_MATCH_0              154U
+#define SC_R_MATCH_1              155U
+#define SC_R_MATCH_2              156U
+#define SC_R_MATCH_3              157U
+#define SC_R_MATCH_4              158U
+#define SC_R_MATCH_5              159U
+#define SC_R_MATCH_6              160U
+#define SC_R_MATCH_7              161U
+#define SC_R_MATCH_8              162U
+#define SC_R_MATCH_9              163U
+#define SC_R_MATCH_10             164U
+#define SC_R_MATCH_11             165U
+#define SC_R_MATCH_12             166U
+#define SC_R_MATCH_13             167U
+#define SC_R_MATCH_14             168U
+#define SC_R_PCIE_B               169U
+#define SC_R_SATA_0               170U
+#define SC_R_SERDES_1             171U
+#define SC_R_HSIO_GPIO            172U
+#define SC_R_MATCH_15             173U
+#define SC_R_MATCH_16             174U
+#define SC_R_MATCH_17             175U
+#define SC_R_MATCH_18             176U
+#define SC_R_MATCH_19             177U
+#define SC_R_MATCH_20             178U
+#define SC_R_MATCH_21             179U
+#define SC_R_MATCH_22             180U
+#define SC_R_MATCH_23             181U
+#define SC_R_MATCH_24             182U
+#define SC_R_MATCH_25             183U
+#define SC_R_MATCH_26             184U
+#define SC_R_MATCH_27             185U
+#define SC_R_MATCH_28             186U
+#define SC_R_LCD_0                187U
+#define SC_R_LCD_0_PWM_0          188U
+#define SC_R_LCD_0_I2C_0          189U
+#define SC_R_LCD_0_I2C_1          190U
+#define SC_R_PWM_0                191U
+#define SC_R_PWM_1                192U
+#define SC_R_PWM_2                193U
+#define SC_R_PWM_3                194U
+#define SC_R_PWM_4                195U
+#define SC_R_PWM_5                196U
+#define SC_R_PWM_6                197U
+#define SC_R_PWM_7                198U
+#define SC_R_GPIO_0               199U
+#define SC_R_GPIO_1               200U
+#define SC_R_GPIO_2               201U
+#define SC_R_GPIO_3               202U
+#define SC_R_GPIO_4               203U
+#define SC_R_GPIO_5               204U
+#define SC_R_GPIO_6               205U
+#define SC_R_GPIO_7               206U
+#define SC_R_GPT_0                207U
+#define SC_R_GPT_1                208U
+#define SC_R_GPT_2                209U
+#define SC_R_GPT_3                210U
+#define SC_R_GPT_4                211U
+#define SC_R_KPP                  212U
+#define SC_R_MU_0A                213U
+#define SC_R_MU_1A                214U
+#define SC_R_MU_2A                215U
+#define SC_R_MU_3A                216U
+#define SC_R_MU_4A                217U
+#define SC_R_MU_5A                218U
+#define SC_R_MU_6A                219U
+#define SC_R_MU_7A                220U
+#define SC_R_MU_8A                221U
+#define SC_R_MU_9A                222U
+#define SC_R_MU_10A               223U
+#define SC_R_MU_11A               224U
+#define SC_R_MU_12A               225U
+#define SC_R_MU_13A               226U
+#define SC_R_MU_5B                227U
+#define SC_R_MU_6B                228U
+#define SC_R_MU_7B                229U
+#define SC_R_MU_8B                230U
+#define SC_R_MU_9B                231U
+#define SC_R_MU_10B               232U
+#define SC_R_MU_11B               233U
+#define SC_R_MU_12B               234U
+#define SC_R_MU_13B               235U
+#define SC_R_ROM_0                236U
+#define SC_R_FSPI_0               237U
+#define SC_R_FSPI_1               238U
+#define SC_R_IEE                  239U
+#define SC_R_IEE_R0               240U
+#define SC_R_IEE_R1               241U
+#define SC_R_IEE_R2               242U
+#define SC_R_IEE_R3               243U
+#define SC_R_IEE_R4               244U
+#define SC_R_IEE_R5               245U
+#define SC_R_IEE_R6               246U
+#define SC_R_IEE_R7               247U
+#define SC_R_SDHC_0               248U
+#define SC_R_SDHC_1               249U
+#define SC_R_SDHC_2               250U
+#define SC_R_ENET_0               251U
+#define SC_R_ENET_1               252U
+#define SC_R_MLB_0                253U
+#define SC_R_DMA_2_CH0            254U
+#define SC_R_DMA_2_CH1            255U
+#define SC_R_DMA_2_CH2            256U
+#define SC_R_DMA_2_CH3            257U
+#define SC_R_DMA_2_CH4            258U
+#define SC_R_USB_0                259U
+#define SC_R_USB_1                260U
+#define SC_R_USB_0_PHY            261U
+#define SC_R_USB_2                262U
+#define SC_R_USB_2_PHY            263U
+#define SC_R_DTCP                 264U
+#define SC_R_NAND                 265U
+#define SC_R_LVDS_0               266U
+#define SC_R_LVDS_0_PWM_0         267U
+#define SC_R_LVDS_0_I2C_0         268U
+#define SC_R_LVDS_0_I2C_1         269U
+#define SC_R_LVDS_1               270U
+#define SC_R_LVDS_1_PWM_0         271U
+#define SC_R_LVDS_1_I2C_0         272U
+#define SC_R_LVDS_1_I2C_1         273U
+#define SC_R_LVDS_2               274U
+#define SC_R_LVDS_2_PWM_0         275U
+#define SC_R_LVDS_2_I2C_0         276U
+#define SC_R_LVDS_2_I2C_1         277U
+#define SC_R_M4_0_PID0            278U
+#define SC_R_M4_0_PID1            279U
+#define SC_R_M4_0_PID2            280U
+#define SC_R_M4_0_PID3            281U
+#define SC_R_M4_0_PID4            282U
+#define SC_R_M4_0_RGPIO           283U
+#define SC_R_M4_0_SEMA42          284U
+#define SC_R_M4_0_TPM             285U
+#define SC_R_M4_0_PIT             286U
+#define SC_R_M4_0_UART            287U
+#define SC_R_M4_0_I2C             288U
+#define SC_R_M4_0_INTMUX          289U
+#define SC_R_M4_0_SIM             290U
+#define SC_R_M4_0_WDOG            291U
+#define SC_R_M4_0_MU_0B           292U
+#define SC_R_M4_0_MU_0A0          293U
+#define SC_R_M4_0_MU_0A1          294U
+#define SC_R_M4_0_MU_0A2          295U
+#define SC_R_M4_0_MU_0A3          296U
+#define SC_R_M4_0_MU_1A           297U
+#define SC_R_M4_1_PID0            298U
+#define SC_R_M4_1_PID1            299U
+#define SC_R_M4_1_PID2            300U
+#define SC_R_M4_1_PID3            301U
+#define SC_R_M4_1_PID4            302U
+#define SC_R_M4_1_RGPIO           303U
+#define SC_R_M4_1_SEMA42          304U
+#define SC_R_M4_1_TPM             305U
+#define SC_R_M4_1_PIT             306U
+#define SC_R_M4_1_UART            307U
+#define SC_R_M4_1_I2C             308U
+#define SC_R_M4_1_INTMUX          309U
+#define SC_R_M4_1_SIM             310U
+#define SC_R_M4_1_WDOG            311U
+#define SC_R_M4_1_MU_0B           312U
+#define SC_R_M4_1_MU_0A0          313U
+#define SC_R_M4_1_MU_0A1          314U
+#define SC_R_M4_1_MU_0A2          315U
+#define SC_R_M4_1_MU_0A3          316U
+#define SC_R_M4_1_MU_1A           317U
+#define SC_R_SAI_0                318U
+#define SC_R_SAI_1                319U
+#define SC_R_SAI_2                320U
+#define SC_R_IRQSTR_SCU2          321U
+#define SC_R_IRQSTR_DSP           322U
+#define SC_R_UNUSED5              323U
+#define SC_R_OCRAM                324U
+#define SC_R_AUDIO_PLL_0          325U
+#define SC_R_PI_0                 326U
+#define SC_R_PI_0_PWM_0           327U
+#define SC_R_PI_0_PWM_1           328U
+#define SC_R_PI_0_I2C_0           329U
+#define SC_R_PI_0_PLL             330U
+#define SC_R_PI_1                 331U
+#define SC_R_PI_1_PWM_0           332U
+#define SC_R_PI_1_PWM_1           333U
+#define SC_R_PI_1_I2C_0           334U
+#define SC_R_PI_1_PLL             335U
+#define SC_R_SC_PID0              336U
+#define SC_R_SC_PID1              337U
+#define SC_R_SC_PID2              338U
+#define SC_R_SC_PID3              339U
+#define SC_R_SC_PID4              340U
+#define SC_R_SC_SEMA42            341U
+#define SC_R_SC_TPM               342U
+#define SC_R_SC_PIT               343U
+#define SC_R_SC_UART              344U
+#define SC_R_SC_I2C               345U
+#define SC_R_SC_MU_0B             346U
+#define SC_R_SC_MU_0A0            347U
+#define SC_R_SC_MU_0A1            348U
+#define SC_R_SC_MU_0A2            349U
+#define SC_R_SC_MU_0A3            350U
+#define SC_R_SC_MU_1A             351U
+#define SC_R_SYSCNT_RD            352U
+#define SC_R_SYSCNT_CMP           353U
+#define SC_R_DEBUG                354U
+#define SC_R_SYSTEM               355U
+#define SC_R_SNVS                 356U
+#define SC_R_OTP                  357U
+#define SC_R_VPU_PID0             358U
+#define SC_R_VPU_PID1             359U
+#define SC_R_VPU_PID2             360U
+#define SC_R_VPU_PID3             361U
+#define SC_R_VPU_PID4             362U
+#define SC_R_VPU_PID5             363U
+#define SC_R_VPU_PID6             364U
+#define SC_R_VPU_PID7             365U
+#define SC_R_VPU_UART             366U
+#define SC_R_VPUCORE              367U
+#define SC_R_VPUCORE_0            368U
+#define SC_R_VPUCORE_1            369U
+#define SC_R_VPUCORE_2            370U
+#define SC_R_VPUCORE_3            371U
+#define SC_R_DMA_4_CH0            372U
+#define SC_R_DMA_4_CH1            373U
+#define SC_R_DMA_4_CH2            374U
+#define SC_R_DMA_4_CH3            375U
+#define SC_R_DMA_4_CH4            376U
+#define SC_R_ISI_CH0              377U
+#define SC_R_ISI_CH1              378U
+#define SC_R_ISI_CH2              379U
+#define SC_R_ISI_CH3              380U
+#define SC_R_ISI_CH4              381U
+#define SC_R_ISI_CH5              382U
+#define SC_R_ISI_CH6              383U
+#define SC_R_ISI_CH7              384U
+#define SC_R_MJPEG_DEC_S0         385U
+#define SC_R_MJPEG_DEC_S1         386U
+#define SC_R_MJPEG_DEC_S2         387U
+#define SC_R_MJPEG_DEC_S3         388U
+#define SC_R_MJPEG_ENC_S0         389U
+#define SC_R_MJPEG_ENC_S1         390U
+#define SC_R_MJPEG_ENC_S2         391U
+#define SC_R_MJPEG_ENC_S3         392U
+#define SC_R_MIPI_0               393U
+#define SC_R_MIPI_0_PWM_0         394U
+#define SC_R_MIPI_0_I2C_0         395U
+#define SC_R_MIPI_0_I2C_1         396U
+#define SC_R_MIPI_1               397U
+#define SC_R_MIPI_1_PWM_0         398U
+#define SC_R_MIPI_1_I2C_0         399U
+#define SC_R_MIPI_1_I2C_1         400U
+#define SC_R_CSI_0                401U
+#define SC_R_CSI_0_PWM_0          402U
+#define SC_R_CSI_0_I2C_0          403U
+#define SC_R_CSI_1                404U
+#define SC_R_CSI_1_PWM_0          405U
+#define SC_R_CSI_1_I2C_0          406U
+#define SC_R_HDMI                 407U
+#define SC_R_HDMI_I2S             408U
+#define SC_R_HDMI_I2C_0           409U
+#define SC_R_HDMI_PLL_0           410U
+#define SC_R_HDMI_RX              411U
+#define SC_R_HDMI_RX_BYPASS       412U
+#define SC_R_HDMI_RX_I2C_0        413U
+#define SC_R_ASRC_0               414U
+#define SC_R_ESAI_0               415U
+#define SC_R_SPDIF_0              416U
+#define SC_R_SPDIF_1              417U
+#define SC_R_SAI_3                418U
+#define SC_R_SAI_4                419U
+#define SC_R_SAI_5                420U
+#define SC_R_GPT_5                421U
+#define SC_R_GPT_6                422U
+#define SC_R_GPT_7                423U
+#define SC_R_GPT_8                424U
+#define SC_R_GPT_9                425U
+#define SC_R_GPT_10               426U
+#define SC_R_DMA_2_CH5            427U
+#define SC_R_DMA_2_CH6            428U
+#define SC_R_DMA_2_CH7            429U
+#define SC_R_DMA_2_CH8            430U
+#define SC_R_DMA_2_CH9            431U
+#define SC_R_DMA_2_CH10           432U
+#define SC_R_DMA_2_CH11           433U
+#define SC_R_DMA_2_CH12           434U
+#define SC_R_DMA_2_CH13           435U
+#define SC_R_DMA_2_CH14           436U
+#define SC_R_DMA_2_CH15           437U
+#define SC_R_DMA_2_CH16           438U
+#define SC_R_DMA_2_CH17           439U
+#define SC_R_DMA_2_CH18           440U
+#define SC_R_DMA_2_CH19           441U
+#define SC_R_DMA_2_CH20           442U
+#define SC_R_DMA_2_CH21           443U
+#define SC_R_DMA_2_CH22           444U
+#define SC_R_DMA_2_CH23           445U
+#define SC_R_DMA_2_CH24           446U
+#define SC_R_DMA_2_CH25           447U
+#define SC_R_DMA_2_CH26           448U
+#define SC_R_DMA_2_CH27           449U
+#define SC_R_DMA_2_CH28           450U
+#define SC_R_DMA_2_CH29           451U
+#define SC_R_DMA_2_CH30           452U
+#define SC_R_DMA_2_CH31           453U
+#define SC_R_ASRC_1               454U
+#define SC_R_ESAI_1               455U
+#define SC_R_SAI_6                456U
+#define SC_R_SAI_7                457U
+#define SC_R_AMIX                 458U
+#define SC_R_MQS_0                459U
+#define SC_R_DMA_3_CH0            460U
+#define SC_R_DMA_3_CH1            461U
+#define SC_R_DMA_3_CH2            462U
+#define SC_R_DMA_3_CH3            463U
+#define SC_R_DMA_3_CH4            464U
+#define SC_R_DMA_3_CH5            465U
+#define SC_R_DMA_3_CH6            466U
+#define SC_R_DMA_3_CH7            467U
+#define SC_R_DMA_3_CH8            468U
+#define SC_R_DMA_3_CH9            469U
+#define SC_R_DMA_3_CH10           470U
+#define SC_R_DMA_3_CH11           471U
+#define SC_R_DMA_3_CH12           472U
+#define SC_R_DMA_3_CH13           473U
+#define SC_R_DMA_3_CH14           474U
+#define SC_R_DMA_3_CH15           475U
+#define SC_R_DMA_3_CH16           476U
+#define SC_R_DMA_3_CH17           477U
+#define SC_R_DMA_3_CH18           478U
+#define SC_R_DMA_3_CH19           479U
+#define SC_R_DMA_3_CH20           480U
+#define SC_R_DMA_3_CH21           481U
+#define SC_R_DMA_3_CH22           482U
+#define SC_R_DMA_3_CH23           483U
+#define SC_R_DMA_3_CH24           484U
+#define SC_R_DMA_3_CH25           485U
+#define SC_R_DMA_3_CH26           486U
+#define SC_R_DMA_3_CH27           487U
+#define SC_R_DMA_3_CH28           488U
+#define SC_R_DMA_3_CH29           489U
+#define SC_R_DMA_3_CH30           490U
+#define SC_R_DMA_3_CH31           491U
+#define SC_R_AUDIO_PLL_1          492U
+#define SC_R_AUDIO_CLK_0          493U
+#define SC_R_AUDIO_CLK_1          494U
+#define SC_R_MCLK_OUT_0           495U
+#define SC_R_MCLK_OUT_1           496U
+#define SC_R_PMIC_0               497U
+#define SC_R_PMIC_1               498U
+#define SC_R_SECO                 499U
+#define SC_R_CAAM_JR1             500U
+#define SC_R_CAAM_JR2             501U
+#define SC_R_CAAM_JR3             502U
+#define SC_R_SECO_MU_2            503U
+#define SC_R_SECO_MU_3            504U
+#define SC_R_SECO_MU_4            505U
+#define SC_R_HDMI_RX_PWM_0        506U
+#define SC_R_A35                  507U
+#define SC_R_A35_0                508U
+#define SC_R_A35_1                509U
+#define SC_R_A35_2                510U
+#define SC_R_A35_3                511U
+#define SC_R_DSP                  512U
+#define SC_R_DSP_RAM              513U
+#define SC_R_CAAM_JR1_OUT         514U
+#define SC_R_CAAM_JR2_OUT         515U
+#define SC_R_CAAM_JR3_OUT         516U
+#define SC_R_VPU_DEC_0            517U
+#define SC_R_VPU_ENC_0            518U
+#define SC_R_CAAM_JR0             519U
+#define SC_R_CAAM_JR0_OUT         520U
+#define SC_R_PMIC_2               521U
+#define SC_R_DBLOGIC              522U
+#define SC_R_HDMI_PLL_1           523U
+#define SC_R_BOARD_R0             524U
+#define SC_R_BOARD_R1             525U
+#define SC_R_BOARD_R2             526U
+#define SC_R_BOARD_R3             527U
+#define SC_R_BOARD_R4             528U
+#define SC_R_BOARD_R5             529U
+#define SC_R_BOARD_R6             530U
+#define SC_R_BOARD_R7             531U
+#define SC_R_MJPEG_DEC_MP         532U
+#define SC_R_MJPEG_ENC_MP         533U
+#define SC_R_VPU_TS_0             534U
+#define SC_R_VPU_MU_0             535U
+#define SC_R_VPU_MU_1             536U
+#define SC_R_VPU_MU_2             537U
+#define SC_R_VPU_MU_3             538U
+#define SC_R_VPU_ENC_1            539U
+#define SC_R_VPU                  540U
+#define SC_R_LAST                 541U
+#define SC_R_ALL                  ((sc_rsrc_t) UINT16_MAX)	/* All resources */
+/*@}*/
+
+/* NOTE - please add by replacing some of the UNUSED from above! */
+
+/*!
+ * Defnes for sc_ctrl_t.
+ */
+#define SC_C_TEMP                       0U
+#define SC_C_TEMP_HI                    1U
+#define SC_C_TEMP_LOW                   2U
+#define SC_C_PXL_LINK_MST1_ADDR         3U
+#define SC_C_PXL_LINK_MST2_ADDR         4U
+#define SC_C_PXL_LINK_MST_ENB           5U
+#define SC_C_PXL_LINK_MST1_ENB          6U
+#define SC_C_PXL_LINK_MST2_ENB          7U
+#define SC_C_PXL_LINK_SLV1_ADDR         8U
+#define SC_C_PXL_LINK_SLV2_ADDR         9U
+#define SC_C_PXL_LINK_MST_VLD           10U
+#define SC_C_PXL_LINK_MST1_VLD          11U
+#define SC_C_PXL_LINK_MST2_VLD          12U
+#define SC_C_SINGLE_MODE                13U
+#define SC_C_ID                         14U
+#define SC_C_PXL_CLK_POLARITY           15U
+#define SC_C_LINESTATE                  16U
+#define SC_C_PCIE_G_RST                 17U
+#define SC_C_PCIE_BUTTON_RST            18U
+#define SC_C_PCIE_PERST                 19U
+#define SC_C_PHY_RESET                  20U
+#define SC_C_PXL_LINK_RATE_CORRECTION   21U
+#define SC_C_PANIC                      22U
+#define SC_C_PRIORITY_GROUP             23U
+#define SC_C_TXCLK                      24U
+#define SC_C_CLKDIV                     25U
+#define SC_C_DISABLE_50                 26U
+#define SC_C_DISABLE_125                27U
+#define SC_C_SEL_125                    28U
+#define SC_C_MODE                       29U
+#define SC_C_SYNC_CTRL0                 30U
+#define SC_C_KACHUNK_CNT                31U
+#define SC_C_KACHUNK_SEL                32U
+#define SC_C_SYNC_CTRL1                 33U
+#define SC_C_DPI_RESET                  34U
+#define SC_C_MIPI_RESET                 35U
+#define SC_C_DUAL_MODE                  36U
+#define SC_C_VOLTAGE                    37U
+#define SC_C_PXL_LINK_SEL               38U
+#define SC_C_OFS_SEL                    39U
+#define SC_C_OFS_AUDIO                  40U
+#define SC_C_OFS_PERIPH                 41U
+#define SC_C_OFS_IRQ                    42U
+#define SC_C_RST0                       43U
+#define SC_C_RST1                       44U
+#define SC_C_SEL0                       45U
+#define SC_C_LAST                       46U
+
+#define SC_P_ALL        ((sc_pad_t) UINT16_MAX)	/* All pads */
+
+/* Types */
+
+/*!
+ * This type is used to store a boolean
+ */
+typedef uint8_t sc_bool_t;
+
+/*!
+ * This type is used to store a system (full-size) address.
+ */
+typedef uint64_t sc_faddr_t;
+
+/*!
+ * This type is used to indicate error response for most functions.
+ */
+typedef uint8_t sc_err_t;
+
+/*!
+ * This type is used to indicate a resource. Resources include peripherals
+ * and bus masters (but not memory regions). Note items from list should
+ * never be changed or removed (only added to at the end of the list).
+ */
+typedef uint16_t sc_rsrc_t;
+
+/*!
+ * This type is used to indicate a control.
+ */
+typedef uint8_t sc_ctrl_t;
+
+/*!
+ * This type is used to indicate a pad. Valid values are SoC specific.
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+typedef uint16_t sc_pad_t;
+
+/* Extra documentation of standard types */
+
+#ifdef DOXYGEN
+    /*!
+     * Type used to declare an 8-bit integer.
+     */
+typedef __INT8_TYPE__ int8_t;
+
+    /*!
+     * Type used to declare a 16-bit integer.
+     */
+typedef __INT16_TYPE__ int16_t;
+
+    /*!
+     * Type used to declare a 32-bit integer.
+     */
+typedef __INT32_TYPE__ int32_t;
+
+    /*!
+     * Type used to declare a 64-bit integer.
+     */
+typedef __INT64_TYPE__ int64_t;
+
+    /*!
+     * Type used to declare an 8-bit unsigned integer.
+     */
+typedef __UINT8_TYPE__ uint8_t;
+
+    /*!
+     * Type used to declare a 16-bit unsigned integer.
+     */
+typedef __UINT16_TYPE__ uint16_t;
+
+    /*!
+     * Type used to declare a 32-bit unsigned integer.
+     */
+typedef __UINT32_TYPE__ uint32_t;
+
+    /*!
+     * Type used to declare a 64-bit unsigned integer.
+     */
+typedef __UINT64_TYPE__ uint64_t;
+#endif
+
+#endif				/* SC_TYPES_H */
diff --git a/plat/imx/common/include/sci/svc/pad/sci_pad_api.h b/plat/imx/common/include/sci/svc/pad/sci_pad_api.h
new file mode 100644
index 0000000..0955678
--- /dev/null
+++ b/plat/imx/common/include/sci/svc/pad/sci_pad_api.h
@@ -0,0 +1,572 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file containing the public API for the System Controller (SC)
+ * Pad Control (PAD) function.
+ *
+ * @addtogroup PAD_SVC (SVC) Pad Service
+ *
+ * Module for the Pad Control (PAD) service.
+ *
+ * @details
+ *
+ * Pad configuration is managed by SC firmware. The pad configuration
+ * features supported by the SC firmware include:
+ *
+ * - Configuring the mux, input/output connection, and low-power isolation
+     mode.
+ * - Configuring the technology-specific pad setting such as drive strength,
+ *   pullup/pulldown, etc.
+ * - Configuring compensation for pad groups with dual voltage capability.
+ *
+ * Pad functions fall into one of three categories. Generic functions are
+ * common to all SoCs and all process technologies. SoC functions are raw
+ * low-level functions. Technology-specific functions are specific to the
+ * process technology.
+ *
+ * The list of pads is SoC specific.  Refer to the SoC [Pad List](@ref PADS)
+ * for valid pad values. Note that all pads exist on a die but may or
+ * may not be brought out by the specific package.  Mapping of pads to
+ * package pins/balls is documented in the associated Data Sheet. Some pads
+ * may not be brought out because the part (die+package) is defeatured and
+ * some pads may connect to the substrate in the package.
+ *
+ * Some pads (SC_P_COMP_*) that can be specified are not individual pads
+ * but are in fact pad groups. These groups have additional configuration
+ * that can be done using the sc_pad_set_gp_28fdsoi_comp() function. More
+ * info on these can be found in the associated Reference Manual.
+ *
+ * Pads are managed as a resource by the Resource Manager (RM).  They have
+ * assigned owners and only the owners can configure the pads. Some of the
+ * pads are reserved for use by the SCFW itself and this can be overriden
+ * with the implementation of board_config_sc(). Additionally, pads may
+ * be assigned to various other partitions via the implementation of
+ * board_system_config().
+ *
+ * Note muxing two input pads to the same IP functional signal will
+ * result in undefined behavior.
+ * @{
+ */
+
+#ifndef SC_PAD_API_H
+#define SC_PAD_API_H
+
+/* Includes */
+
+#include <sci/sci_types.h>
+#include <sci/svc/rm/sci_rm_api.h>
+
+/* Defines */
+
+/*!
+ * @name Defines for type widths
+ */
+/*@{*/
+#define SC_PAD_MUX_W            3	/* Width of mux parameter */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pad_config_t
+ */
+/*@{*/
+#define SC_PAD_CONFIG_NORMAL    0U	/* Normal */
+#define SC_PAD_CONFIG_OD        1U	/* Open Drain */
+#define SC_PAD_CONFIG_OD_IN     2U	/* Open Drain and input */
+#define SC_PAD_CONFIG_OUT_IN    3U	/* Output and input */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pad_iso_t
+ */
+/*@{*/
+#define SC_PAD_ISO_OFF          0U	/* ISO latch is transparent */
+#define SC_PAD_ISO_EARLY        1U	/* Follow EARLY_ISO */
+#define SC_PAD_ISO_LATE         2U	/* Follow LATE_ISO */
+#define SC_PAD_ISO_ON           3U	/* ISO latched data is held */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pad_28fdsoi_dse_t
+ */
+/*@{*/
+#define SC_PAD_28FDSOI_DSE_18V_1MA   0U	/* Drive strength of 1mA for 1.8v */
+#define SC_PAD_28FDSOI_DSE_18V_2MA   1U	/* Drive strength of 2mA for 1.8v */
+#define SC_PAD_28FDSOI_DSE_18V_4MA   2U	/* Drive strength of 4mA for 1.8v */
+#define SC_PAD_28FDSOI_DSE_18V_6MA   3U	/* Drive strength of 6mA for 1.8v */
+#define SC_PAD_28FDSOI_DSE_18V_8MA   4U	/* Drive strength of 8mA for 1.8v */
+#define SC_PAD_28FDSOI_DSE_18V_10MA  5U	/* Drive strength of 10mA for 1.8v */
+#define SC_PAD_28FDSOI_DSE_18V_12MA  6U	/* Drive strength of 12mA for 1.8v */
+#define SC_PAD_28FDSOI_DSE_18V_HS    7U	/* High-speed drive strength for 1.8v */
+#define SC_PAD_28FDSOI_DSE_33V_2MA   0U	/* Drive strength of 2mA for 3.3v */
+#define SC_PAD_28FDSOI_DSE_33V_4MA   1U	/* Drive strength of 4mA for 3.3v */
+#define SC_PAD_28FDSOI_DSE_33V_8MA   2U	/* Drive strength of 8mA for 3.3v */
+#define SC_PAD_28FDSOI_DSE_33V_12MA  3U	/* Drive strength of 12mA for 3.3v */
+#define SC_PAD_28FDSOI_DSE_DV_HIGH   0U	/* High drive strength for dual volt */
+#define SC_PAD_28FDSOI_DSE_DV_LOW    1U	/* Low drive strength for dual volt */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pad_28fdsoi_ps_t
+ */
+/*@{*/
+#define SC_PAD_28FDSOI_PS_KEEPER 0U	/* Bus-keeper (only valid for 1.8v) */
+#define SC_PAD_28FDSOI_PS_PU     1U	/* Pull-up */
+#define SC_PAD_28FDSOI_PS_PD     2U	/* Pull-down */
+#define SC_PAD_28FDSOI_PS_NONE   3U	/* No pull (disabled) */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pad_28fdsoi_pus_t
+ */
+/*@{*/
+#define SC_PAD_28FDSOI_PUS_30K_PD  0U	/* 30K pull-down */
+#define SC_PAD_28FDSOI_PUS_100K_PU 1U	/* 100K pull-up */
+#define SC_PAD_28FDSOI_PUS_3K_PU   2U	/* 3K pull-up */
+#define SC_PAD_28FDSOI_PUS_30K_PU  3U	/* 30K pull-up */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pad_wakeup_t
+ */
+/*@{*/
+#define SC_PAD_WAKEUP_OFF       0U	/* Off */
+#define SC_PAD_WAKEUP_CLEAR     1U	/* Clears pending flag */
+#define SC_PAD_WAKEUP_LOW_LVL   4U	/* Low level */
+#define SC_PAD_WAKEUP_FALL_EDGE 5U	/* Falling edge */
+#define SC_PAD_WAKEUP_RISE_EDGE 6U	/* Rising edge */
+#define SC_PAD_WAKEUP_HIGH_LVL  7U	/* High-level */
+/*@}*/
+
+/* Types */
+
+/*!
+ * This type is used to declare a pad config. It determines how the
+ * output data is driven, pull-up is controlled, and input signal is
+ * connected. Normal and OD are typical and only connect the input
+ * when the output is not driven.  The IN options are less common and
+ * force an input connection even when driving the output.
+ */
+typedef uint8_t sc_pad_config_t;
+
+/*!
+ * This type is used to declare a pad low-power isolation config.
+ * ISO_LATE is the most common setting. ISO_EARLY is only used when
+ * an output pad is directly determined by another input pad. The
+ * other two are only used when SW wants to directly contol isolation.
+ */
+typedef uint8_t sc_pad_iso_t;
+
+/*!
+ * This type is used to declare a drive strength. Note it is specific
+ * to 28FDSOI. Also note that valid values depend on the pad type.
+ */
+typedef uint8_t sc_pad_28fdsoi_dse_t;
+
+/*!
+ * This type is used to declare a pull select. Note it is specific
+ * to 28FDSOI.
+ */
+typedef uint8_t sc_pad_28fdsoi_ps_t;
+
+/*!
+ * This type is used to declare a pull-up select. Note it is specific
+ * to 28FDSOI HSIC pads.
+ */
+typedef uint8_t sc_pad_28fdsoi_pus_t;
+
+/*!
+ * This type is used to declare a wakeup mode of a pad.
+ */
+typedef uint8_t sc_pad_wakeup_t;
+
+/* Functions */
+
+/*!
+ * @name Generic Functions
+ * @{
+ */
+
+/*!
+ * This function configures the mux settings for a pad. This includes
+ * the signal mux, pad config, and low-power isolation mode.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to configure
+ * @param[in]     mux         mux setting
+ * @param[in]     config      pad config
+ * @param[in]     iso         low-power isolation mode
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Note muxing two input pads to the same IP functional signal will
+ * result in undefined behavior.
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_set_mux(sc_ipc_t ipc, sc_pad_t pad,
+			uint8_t mux, sc_pad_config_t config, sc_pad_iso_t iso);
+
+/*!
+ * This function gets the mux settings for a pad. This includes
+ * the signal mux, pad config, and low-power isolation mode.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to query
+ * @param[out]    mux         pointer to return mux setting
+ * @param[out]    config      pointer to return pad config
+ * @param[out]    iso         pointer to return low-power isolation mode
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get_mux(sc_ipc_t ipc, sc_pad_t pad,
+			uint8_t *mux, sc_pad_config_t *config,
+			sc_pad_iso_t *iso);
+
+/*!
+ * This function configures the general purpose pad control. This
+ * is technology dependent and includes things like drive strength,
+ * slew rate, pull up/down, etc. Refer to the SoC Reference Manual
+ * for bit field details.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to configure
+ * @param[in]     ctrl        control value to set
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_set_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t ctrl);
+
+/*!
+ * This function gets the general purpose pad control. This
+ * is technology dependent and includes things like drive strength,
+ * slew rate, pull up/down, etc. Refer to the SoC Reference Manual
+ * for bit field details.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to query
+ * @param[out]    ctrl        pointer to return control value
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t *ctrl);
+
+/*!
+ * This function configures the wakeup mode of the pad.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to configure
+ * @param[in]     wakeup      wakeup to set
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_set_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t wakeup);
+
+/*!
+ * This function gets the wakeup mode of a pad.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to query
+ * @param[out]    wakeup      pointer to return wakeup
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t *wakeup);
+
+/*!
+ * This function configures a pad.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to configure
+ * @param[in]     mux         mux setting
+ * @param[in]     config      pad config
+ * @param[in]     iso         low-power isolation mode
+ * @param[in]     ctrl        control value
+ * @param[in]     wakeup      wakeup to set
+ *
+ * @see sc_pad_set_mux().
+ * @see sc_pad_set_gp().
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Note muxing two input pads to the same IP functional signal will
+ * result in undefined behavior.
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_set_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t mux,
+			sc_pad_config_t config, sc_pad_iso_t iso, uint32_t ctrl,
+			sc_pad_wakeup_t wakeup);
+
+/*!
+ * This function gets a pad's config.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to query
+ * @param[out]    mux         pointer to return mux setting
+ * @param[out]    config      pointer to return pad config
+ * @param[out]    iso         pointer to return low-power isolation mode
+ * @param[out]    ctrl        pointer to return control value
+ * @param[out]    wakeup      pointer to return wakeup to set
+ *
+ * @see sc_pad_set_mux().
+ * @see sc_pad_set_gp().
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t *mux,
+			sc_pad_config_t *config, sc_pad_iso_t *iso,
+			uint32_t *ctrl, sc_pad_wakeup_t *wakeup);
+
+/* @} */
+
+/*!
+ * @name SoC Specific Functions
+ * @{
+ */
+
+/*!
+ * This function configures the settings for a pad. This setting is SoC
+ * specific.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to configure
+ * @param[in]     val         value to set
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_set(sc_ipc_t ipc, sc_pad_t pad, uint32_t val);
+
+/*!
+ * This function gets the settings for a pad. This setting is SoC
+ * specific.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to query
+ * @param[out]    val         pointer to return setting
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get(sc_ipc_t ipc, sc_pad_t pad, uint32_t *val);
+
+/* @} */
+
+/*!
+ * @name Technology Specific Functions
+ * @{
+ */
+
+/*!
+ * This function configures the pad control specific to 28FDSOI.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to configure
+ * @param[in]     dse         drive strength
+ * @param[in]     ps          pull select
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner,
+ * - SC_ERR_UNAVAILABLE if process not applicable
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_set_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad,
+			       sc_pad_28fdsoi_dse_t dse,
+			       sc_pad_28fdsoi_ps_t ps);
+
+/*!
+ * This function gets the pad control specific to 28FDSOI.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to query
+ * @param[out]    dse         pointer to return drive strength
+ * @param[out]    ps          pointer to return pull select
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner,
+ * - SC_ERR_UNAVAILABLE if process not applicable
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad,
+			       sc_pad_28fdsoi_dse_t *dse,
+			       sc_pad_28fdsoi_ps_t *ps);
+
+/*!
+ * This function configures the pad control specific to 28FDSOI.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to configure
+ * @param[in]     dse         drive strength
+ * @param[in]     hys         hysteresis
+ * @param[in]     pus         pull-up select
+ * @param[in]     pke         pull keeper enable
+ * @param[in]     pue         pull-up enable
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner,
+ * - SC_ERR_UNAVAILABLE if process not applicable
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_set_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad,
+				    sc_pad_28fdsoi_dse_t dse, sc_bool_t hys,
+				    sc_pad_28fdsoi_pus_t pus, sc_bool_t pke,
+				    sc_bool_t pue);
+
+/*!
+ * This function gets the pad control specific to 28FDSOI.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to query
+ * @param[out]    dse         pointer to return drive strength
+ * @param[out]    hys         pointer to return hysteresis
+ * @param[out]    pus         pointer to return pull-up select
+ * @param[out]    pke         pointer to return pull keeper enable
+ * @param[out]    pue         pointer to return pull-up enable
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner,
+ * - SC_ERR_UNAVAILABLE if process not applicable
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad,
+				    sc_pad_28fdsoi_dse_t *dse, sc_bool_t *hys,
+				    sc_pad_28fdsoi_pus_t *pus, sc_bool_t *pke,
+				    sc_bool_t *pue);
+
+/*!
+ * This function configures the compensation control specific to 28FDSOI.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to configure
+ * @param[in]     compen      compensation/freeze mode
+ * @param[in]     fastfrz     fast freeze
+ * @param[in]     rasrcp      compensation code for PMOS
+ * @param[in]     rasrcn      compensation code for NMOS
+ * @param[in]     nasrc_sel   NASRC read select
+ * @param[in]     psw_ovr     2.5v override
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner,
+ * - SC_ERR_UNAVAILABLE if process not applicable
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ *
+ * Note \a psw_ovr is only applicable to pads supporting 2.5 volt
+ * operation (e.g. some Ethernet pads).
+ */
+sc_err_t sc_pad_set_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad,
+				    uint8_t compen, sc_bool_t fastfrz,
+				    uint8_t rasrcp, uint8_t rasrcn,
+				    sc_bool_t nasrc_sel, sc_bool_t psw_ovr);
+
+/*!
+ * This function gets the compensation control specific to 28FDSOI.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to query
+ * @param[out]    compen      pointer to return compensation/freeze mode
+ * @param[out]    fastfrz     pointer to return fast freeze
+ * @param[out]    rasrcp      pointer to return compensation code for PMOS
+ * @param[out]    rasrcn      pointer to return compensation code for NMOS
+ * @param[out]    nasrc_sel   pointer to return NASRC read select
+ * @param[out]    compok      pointer to return compensation status
+ * @param[out]    nasrc       pointer to return NASRCP/NASRCN
+ * @param[out]    psw_ovr     pointer to return the 2.5v override
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner,
+ * - SC_ERR_UNAVAILABLE if process not applicable
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad,
+				    uint8_t *compen, sc_bool_t *fastfrz,
+				    uint8_t *rasrcp, uint8_t *rasrcn,
+				    sc_bool_t *nasrc_sel, sc_bool_t *compok,
+				    uint8_t *nasrc, sc_bool_t *psw_ovr);
+
+/* @} */
+
+#endif				/* SC_PAD_API_H */
+
+/**@}*/
diff --git a/plat/imx/common/include/sci/svc/pm/sci_pm_api.h b/plat/imx/common/include/sci/svc/pm/sci_pm_api.h
new file mode 100644
index 0000000..5c3c382
--- /dev/null
+++ b/plat/imx/common/include/sci/svc/pm/sci_pm_api.h
@@ -0,0 +1,684 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file containing the public API for the System Controller (SC)
+ * Power Management (PM) function. This includes functions for power state
+ * control, clock control, reset control, and wake-up event control.
+ *
+ * @addtogroup PM_SVC (SVC) Power Management Service
+ *
+ * Module for the Power Management (PM) service.
+ *
+ * @{
+ */
+
+#ifndef SC_PM_API_H
+#define SC_PM_API_H
+
+/* Includes */
+
+#include <sci/sci_types.h>
+#include <sci/svc/rm/sci_rm_api.h>
+
+/* Defines */
+
+/*!
+ * @name Defines for type widths
+ */
+/*@{*/
+#define SC_PM_POWER_MODE_W      2	/* Width of sc_pm_power_mode_t */
+#define SC_PM_CLOCK_MODE_W      3	/* Width of sc_pm_clock_mode_t */
+#define SC_PM_RESET_TYPE_W      2	/* Width of sc_pm_reset_type_t */
+#define SC_PM_RESET_REASON_W    3	/* Width of sc_pm_reset_reason_t */
+/*@}*/
+
+/*!
+ * @name Defines for clock indexes (sc_pm_clk_t)
+ */
+/*@{*/
+/*@}*/
+
+/*!
+ * @name Defines for ALL parameters
+ */
+/*@{*/
+#define SC_PM_CLK_ALL   UINT8_MAX	/* All clocks */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_power_mode_t
+ */
+/*@{*/
+#define SC_PM_PW_MODE_OFF       0U	/* Power off */
+#define SC_PM_PW_MODE_STBY      1U	/* Power in standby */
+#define SC_PM_PW_MODE_LP        2U	/* Power in low-power */
+#define SC_PM_PW_MODE_ON        3U	/* Power on */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_clk_t
+ */
+/*@{*/
+#define SC_PM_CLK_SLV_BUS       0U	/* Slave bus clock */
+#define SC_PM_CLK_MST_BUS       1U	/* Master bus clock */
+#define SC_PM_CLK_PER           2U	/* Peripheral clock */
+#define SC_PM_CLK_PHY           3U	/* Phy clock */
+#define SC_PM_CLK_MISC          4U	/* Misc clock */
+#define SC_PM_CLK_MISC0         0U	/* Misc 0 clock */
+#define SC_PM_CLK_MISC1         1U	/* Misc 1 clock */
+#define SC_PM_CLK_MISC2         2U	/* Misc 2 clock */
+#define SC_PM_CLK_MISC3         3U	/* Misc 3 clock */
+#define SC_PM_CLK_MISC4         4U	/* Misc 4 clock */
+#define SC_PM_CLK_CPU           2U	/* CPU clock */
+#define SC_PM_CLK_PLL           4U	/* PLL */
+#define SC_PM_CLK_BYPASS        4U	/* Bypass clock */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_clk_mode_t
+ */
+/*@{*/
+#define SC_PM_CLK_MODE_ROM_INIT        0U	/* Clock is initialized by ROM. */
+#define SC_PM_CLK_MODE_OFF             1U	/* Clock is disabled */
+#define SC_PM_CLK_MODE_ON              2U	/* Clock is enabled. */
+#define SC_PM_CLK_MODE_AUTOGATE_SW     3U	/* Clock is in SW autogate mode */
+#define SC_PM_CLK_MODE_AUTOGATE_HW     4U	/* Clock is in HW autogate mode */
+#define SC_PM_CLK_MODE_AUTOGATE_SW_HW  5U	/* Clock is in SW-HW autogate mode */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_clk_parent_t
+ */
+/*@{*/
+#define SC_PM_PARENT_XTAL              0U	/* Parent is XTAL. */
+#define SC_PM_PARENT_PLL0              1U	/* Parent is PLL0 */
+#define SC_PM_PARENT_PLL1              2U	/* Parent is PLL1 or PLL0/2 */
+#define SC_PM_PARENT_PLL2              3U	/* Parent in PLL2 or PLL0/4 */
+#define SC_PM_PARENT_BYPS              4U	/* Parent is a bypass clock. */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_reset_type_t
+ */
+/*@{*/
+#define SC_PM_RESET_TYPE_COLD          0U	/* Cold reset */
+#define SC_PM_RESET_TYPE_WARM          1U	/* Warm reset */
+#define SC_PM_RESET_TYPE_BOARD         2U	/* Board reset */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_reset_cause_t
+ */
+/*@{*/
+#define SC_PM_RESET_CAUSE_TEMP         0U	/* Reset due to temp panic alarm */
+#define SC_PM_RESET_CAUSE_FAULT        1U	/* Reset due to fault exception */
+#define SC_PM_RESET_CAUSE_IRQ          2U	/* Reset due to SCU reset IRQ */
+#define SC_PM_RESET_CAUSE_WDOG         3U	/* Reset due to SW WDOG */
+#define SC_PM_RESET_CAUSE_API          4U	/* Reset due to pm_reset() or monitor */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_reset_reason_t
+ */
+/*@{*/
+#define SC_PM_RESET_REASON_POR         0U	/* Power on reset */
+#define SC_PM_RESET_REASON_WARM        1U	/* Warm reset */
+#define SC_PM_RESET_REASON_SW          2U	/* Software reset */
+#define SC_PM_RESET_REASON_WDOG        3U	/* Watchdog reset */
+#define SC_PM_RESET_REASON_LOCKUP      4U	/* Lockup reset */
+#define SC_PM_RESET_REASON_TAMPER      5U	/* Tamper reset */
+#define SC_PM_RESET_REASON_TEMP        6U	/* Temp reset */
+#define SC_PM_RESET_REASON_LOW_VOLT    7U	/* Low voltage reset */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_sys_if_t
+ */
+/*@{*/
+#define SC_PM_SYS_IF_INTERCONNECT       0U	/* System interconnect */
+#define SC_PM_SYS_IF_MU                 1U	/* AP -> SCU message units */
+#define SC_PM_SYS_IF_OCMEM              2U	/* On-chip memory (ROM/OCRAM) */
+#define SC_PM_SYS_IF_DDR                3U	/* DDR memory */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_wake_src_t
+ */
+/*@{*/
+#define SC_PM_WAKE_SRC_NONE             0U	/* No wake source, used for self-kill */
+#define SC_PM_WAKE_SRC_SCU              1U	/* Wakeup from SCU to resume CPU (IRQSTEER & GIC powered down) */
+#define SC_PM_WAKE_SRC_IRQSTEER         2U	/* Wakeup from IRQSTEER to resume CPU (GIC powered down) */
+#define SC_PM_WAKE_SRC_IRQSTEER_GIC     3U	/* Wakeup from IRQSTEER+GIC to wake CPU  (GIC clock gated) */
+#define SC_PM_WAKE_SRC_GIC              4U	/* Wakeup from GIC to wake CPU */
+/*@}*/
+
+/* Types */
+
+/*!
+ * This type is used to declare a power mode. Note resources only use
+ * SC_PM_PW_MODE_OFF and SC_PM_PW_MODE_ON. The other modes are used only
+ * as system power modes.
+ */
+typedef uint8_t sc_pm_power_mode_t;
+
+/*!
+ * This type is used to declare a clock.
+ */
+typedef uint8_t sc_pm_clk_t;
+
+/*!
+ * This type is used to declare a clock mode.
+ */
+typedef uint8_t sc_pm_clk_mode_t;
+
+/*!
+ * This type is used to declare the clock parent.
+ */
+typedef uint8_t sc_pm_clk_parent_t;
+
+/*!
+ * This type is used to declare clock rates.
+ */
+typedef uint32_t sc_pm_clock_rate_t;
+
+/*!
+ * This type is used to declare a desired reset type.
+ */
+typedef uint8_t sc_pm_reset_type_t;
+
+/*!
+ * This type is used to declare a desired reset type.
+ */
+typedef uint8_t sc_pm_reset_cause;
+
+/*!
+ * This type is used to declare a reason for a reset.
+ */
+typedef uint8_t sc_pm_reset_reason_t;
+
+/*!
+ * This type is used to specify a system-level interface to be power managed.
+ */
+typedef uint8_t sc_pm_sys_if_t;
+
+/*!
+ * This type is used to specify a wake source for CPU resources.
+ */
+typedef uint8_t sc_pm_wake_src_t;
+
+/* Functions */
+
+/*!
+ * @name Power Functions
+ * @{
+ */
+
+/*!
+ * This function sets the system power mode. Only the owner of the
+ * SC_R_SYSTEM resource can do this.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     mode        power mode to apply
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid mode,
+ * - SC_ERR_NOACCESS if caller not the owner of SC_R_SYSTEM
+ *
+ * @see sc_pm_set_sys_power_mode().
+ */
+sc_err_t sc_pm_set_sys_power_mode(sc_ipc_t ipc, sc_pm_power_mode_t mode);
+
+/*!
+ * This function sets the power mode of a partition.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pt          handle of partition
+ * @param[in]     mode        power mode to apply
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid partition or mode,
+ * - SC_ERR_NOACCESS if caller's partition is not the owner or
+ *   parent of \a pt
+ *
+ * The power mode of the partitions is a max power any resource will
+ * be set to. Calling this will result in all resources owned
+ * by \a pt to have their power changed to the lower of \a mode or the
+ * individual resource mode set using sc_pm_set_resource_power_mode().
+ */
+sc_err_t sc_pm_set_partition_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt,
+					sc_pm_power_mode_t mode);
+
+/*!
+ * This function gets the power mode of a partition.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pt          handle of partition
+ * @param[out]    mode        pointer to return power mode
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid partition
+ */
+sc_err_t sc_pm_get_sys_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt,
+				  sc_pm_power_mode_t *mode);
+
+/*!
+ * This function sets the power mode of a resource.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    ID of the resource
+ * @param[in]     mode        power mode to apply
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or mode,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner
+ *   or parent of the owner
+ *
+ * This function will record the individual resource power mode
+ * and change it if the requested mode is lower than or equal to the
+ * partition power mode set with sc_pm_set_partition_power_mode().
+ * In other words, the power mode of the resource will be the minimum
+ * of the resource power mode and the partition power mode.
+ *
+ * Note some resources are still not accessible even when powered up if bus
+ * transactions go through a fabric not powered up. Examples of this are
+ * resources in display and capture subsystems which require the display
+ * controller or the imaging subsytem to be powered up first.
+ *
+ * Not that resources are grouped into power domains by the underlying
+ * hardware. If any resource in the domain is on, the entire power domain
+ * will be on. Other power domains required to access the resource will
+ * also be turned on. Clocks required to access the peripheral will be
+ * turned on. Refer to the SoC RM for more info on power domains and access
+ * infrastructure (bus fabrics, clock domains, etc.).
+ */
+sc_err_t sc_pm_set_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+				       sc_pm_power_mode_t mode);
+
+/*!
+ * This function gets the power mode of a resource.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    ID of the resource
+ * @param[out]    mode        pointer to return power mode
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Note only SC_PM_PW_MODE_OFF and SC_PM_PW_MODE_ON are valid. The value
+ * returned does not reflect the power mode of the partition..
+ */
+sc_err_t sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+				       sc_pm_power_mode_t *mode);
+
+/*!
+ * This function requests the low power mode some of the resources
+ * can enter based on their state. This API is only valid for the
+ * following resources : SC_R_A53, SC_R_A53_0, SC_R_A53_1, SC_A53_2,
+ * SC_A53_3, SC_R_A72, SC_R_A72_0, SC_R_A72_1, SC_R_CC1, SC_R_A35,
+ * SC_R_A35_0, SC_R_A35_1, SC_R_A35_2, SC_R_A35_3.
+ * For all other resources it will return SC_ERR_PARAM.
+ * This function will set the low power mode the cores, cluster
+ * and cluster associated resources will enter when all the cores
+ * in a given cluster execute WFI
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    ID of the resource
+ * @param[in]     mode        power mode to apply
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ */
+sc_err_t sc_pm_req_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+				  sc_pm_power_mode_t mode);
+
+/*!
+ * This function requests low-power mode entry for CPU/cluster
+ * resources. This API is only valid for the following resources:
+ * SC_R_A53, SC_R_A53_x, SC_R_A72, SC_R_A72_x, SC_R_A35, SC_R_A35_x,
+ * SC_R_CCI. For all other resources it will return SC_ERR_PARAM.
+ * For individual core resources, the specified power mode
+ * and wake source will be applied after the core has entered
+ * WFI.  For cluster resources, the specified power mode is
+ * applied after all cores in the cluster have entered low-power mode.
+ * For multicluster resources, the specified power mode is applied
+ * after all clusters have reached low-power mode.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    ID of the resource
+ * @param[in]     mode        power mode to apply
+ * @param[in]     wake_src    wake source for low-power exit
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ */
+sc_err_t sc_pm_req_cpu_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+				      sc_pm_power_mode_t mode,
+				      sc_pm_wake_src_t wake_src);
+
+/*!
+ * This function is used to set the resume address of a CPU.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    ID of the CPU resource
+ * @param[in]     address     64-bit resume address
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or address,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of the
+ *   resource (CPU) owner
+ */
+sc_err_t sc_pm_set_cpu_resume_addr(sc_ipc_t ipc, sc_rsrc_t resource,
+				   sc_faddr_t address);
+
+/*!
+ * This function is used to set parameters for CPU resume from
+ * low-power mode.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    ID of the CPU resource
+ * @param[in]     isPrimary   set SC_TRUE if primary wake CPU
+ * @param[in]     address     64-bit resume address
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or address,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of the
+ *   resource (CPU) owner
+ */
+sc_err_t sc_pm_set_cpu_resume(sc_ipc_t ipc, sc_rsrc_t resource,
+			      sc_bool_t isPrimary, sc_faddr_t address);
+
+/*!
+ * This function requests the power mode configuration for system-level
+ * interfaces including messaging units, interconnect, and memories.  This API
+ * is only valid for the following resources : SC_R_A53, SC_R_A72, and
+ * SC_R_M4_x_PID_y.  For all other resources, it will return SC_ERR_PARAM.
+ * The requested power mode will be captured and applied to system-level
+ * resources as system conditions allow.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    ID of the resource
+ * @param[in]     sys_if      system-level interface to be configured
+ * @param[in]     hpm         high-power mode for the system interface
+ * @param[in]     lpm         low-power mode for the system interface
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ */
+sc_err_t sc_pm_req_sys_if_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+				     sc_pm_sys_if_t sys_if,
+				     sc_pm_power_mode_t hpm,
+				     sc_pm_power_mode_t lpm);
+
+/* @} */
+
+/*!
+ * @name Clock/PLL Functions
+ * @{
+ */
+
+/*!
+ * This function sets the rate of a resource's clock/PLL.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    ID of the resource
+ * @param[in]     clk         clock/PLL to affect
+ * @param[in,out] rate        pointer to rate to set,
+ *                            return actual rate
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or clock/PLL,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner
+ *   or parent of the owner,
+ * - SC_ERR_UNAVAILABLE if clock/PLL not applicable to this resource,
+ * - SC_ERR_LOCKED if rate locked (usually because shared clock/PLL)
+ *
+ * Refer to the [Clock List](@ref CLOCKS) for valid clock/PLL values.
+ */
+sc_err_t sc_pm_set_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource,
+			      sc_pm_clk_t clk, sc_pm_clock_rate_t *rate);
+
+/*!
+ * This function gets the rate of a resource's clock/PLL.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    ID of the resource
+ * @param[in]     clk         clock/PLL to affect
+ * @param[out]    rate        pointer to return rate
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or clock/PLL,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner
+ *   or parent of the owner,
+ * - SC_ERR_UNAVAILABLE if clock/PLL not applicable to this resource
+ *
+ * Refer to the [Clock List](@ref CLOCKS) for valid clock/PLL values.
+ */
+sc_err_t sc_pm_get_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource,
+			      sc_pm_clk_t clk, sc_pm_clock_rate_t *rate);
+
+/*!
+ * This function enables/disables a resource's clock.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    ID of the resource
+ * @param[in]     clk         clock to affect
+ * @param[in]     enable      enable if SC_TRUE; otherwise disabled
+ * @param[in]     autog       HW auto clock gating
+ *
+ * If \a resource is SC_R_ALL then all resources owned will be affected.
+ * No error will be returned.
+ *
+ * If \a clk is SC_PM_CLK_ALL, then an error will be returned if any
+ * of the available clocks returns an error.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or clock,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner
+ *   or parent of the owner,
+ * - SC_ERR_UNAVAILABLE if clock not applicable to this resource
+ *
+ * Refer to the [Clock List](@ref CLOCKS) for valid clock values.
+ */
+sc_err_t sc_pm_clock_enable(sc_ipc_t ipc, sc_rsrc_t resource,
+			    sc_pm_clk_t clk, sc_bool_t enable, sc_bool_t autog);
+
+/*!
+ * This function sets the parent of a resource's clock.
+ * This function should only be called when the clock is disabled.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    ID of the resource
+ * @param[in]     clk         clock to affect
+ * @param[in]     parent      New parent of the clock.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or clock,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner
+ *   or parent of the owner,
+ * - SC_ERR_UNAVAILABLE if clock not applicable to this resource
+ * - SC_ERR_BUSY if clock is currently enabled.
+ * - SC_ERR_NOPOWER if resource not powered
+ *
+ * Refer to the [Clock List](@ref CLOCKS) for valid clock values.
+ */
+sc_err_t sc_pm_set_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource,
+				sc_pm_clk_t clk, sc_pm_clk_parent_t parent);
+
+/*!
+ * This function gets the parent of a resource's clock.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    ID of the resource
+ * @param[in]     clk         clock to affect
+ * @param[out]     parent     pointer to return parent of clock.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or clock,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner
+ *   or parent of the owner,
+ * - SC_ERR_UNAVAILABLE if clock not applicable to this resource
+ *
+ * Refer to the [Clock List](@ref CLOCKS) for valid clock values.
+ */
+sc_err_t sc_pm_get_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource,
+				sc_pm_clk_t clk, sc_pm_clk_parent_t *parent);
+
+/* @} */
+
+/*!
+ * @name Reset Functions
+ * @{
+ */
+
+/*!
+ * This function is used to reset the system. Only the owner of the
+ * SC_R_SYSTEM resource can do this.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     type        reset type
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid type,
+ * - SC_ERR_NOACCESS if caller not the owner of SC_R_SYSTEM
+ *
+ * If this function returns, then the reset did not occur due to an
+ * invalid parameter.
+ */
+sc_err_t sc_pm_reset(sc_ipc_t ipc, sc_pm_reset_type_t type);
+
+/*!
+ * This function gets a caller's reset reason.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[out]    reason      pointer to return reset reason
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ */
+sc_err_t sc_pm_reset_reason(sc_ipc_t ipc, sc_pm_reset_reason_t *reason);
+
+/*!
+ * This function is used to boot a partition.
+ *
+ * @param[in]     ipc          IPC handle
+ * @param[in]     pt           handle of partition to boot
+ * @param[in]     resource_cpu ID of the CPU resource to start
+ * @param[in]     boot_addr    64-bit boot address
+ * @param[in]     resource_mu  ID of the MU that must be powered
+ * @param[in]     resource_dev ID of the boot device that must be powered
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid partition, resource, or addr,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of the
+ *   partition to boot
+ */
+sc_err_t sc_pm_boot(sc_ipc_t ipc, sc_rm_pt_t pt,
+		    sc_rsrc_t resource_cpu, sc_faddr_t boot_addr,
+		    sc_rsrc_t resource_mu, sc_rsrc_t resource_dev);
+
+/*!
+ * This function is used to reboot the caller's partition.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     type        reset type
+ *
+ * If \a type is SC_PM_RESET_TYPE_COLD, then most peripherals owned by
+ * the calling partition will be reset if possible. SC state (partitions,
+ * power, clocks, etc.) is reset. The boot SW of the booting CPU must be
+ * able to handle peripherals that that are not reset.
+ *
+ * If \a type is SC_PM_RESET_TYPE_WARM, then only the boot CPU is reset.
+ * SC state (partitions, power, clocks, etc.) are NOT reset. The boot SW
+ * of the booting CPU must be able to handle peripherals and SC state that
+ * that are not reset.
+ *
+ * If \a type is SC_PM_RESET_TYPE_BOARD, then return with no action.
+ *
+ * If this function returns, then the reset did not occur due to an
+ * invalid parameter.
+ */
+void sc_pm_reboot(sc_ipc_t ipc, sc_pm_reset_type_t type);
+
+/*!
+ * This function is used to reboot a partition.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pt          handle of partition to reboot
+ * @param[in]     type        reset type
+ *
+ * If \a type is SC_PM_RESET_TYPE_COLD, then most peripherals owned by
+ * the calling partition will be reset if possible. SC state (partitions,
+ * power, clocks, etc.) is reset. The boot SW of the booting CPU must be
+ * able to handle peripherals that that are not reset.
+ *
+ * If \a type is SC_PM_RESET_TYPE_WARM, then only the boot CPU is reset.
+ * SC state (partitions, power, clocks, etc.) are NOT reset. The boot SW
+ * of the booting CPU must be able to handle peripherals and SC state that
+ * that are not reset.
+ *
+ * If \a type is SC_PM_RESET_TYPE_BOARD, then return with no action.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid partition or type
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt,
+ *
+ * Most peripherals owned by the partition will be reset if
+ * possible. SC state (partitions, power, clocks, etc.) is reset. The
+ * boot SW of the booting CPU must be able to handle peripherals that
+ * that are not reset.
+ */
+sc_err_t sc_pm_reboot_partition(sc_ipc_t ipc, sc_rm_pt_t pt,
+				sc_pm_reset_type_t type);
+
+/*!
+ * This function is used to start/stop a CPU.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    ID of the CPU resource
+ * @param[in]     enable      start if SC_TRUE; otherwise stop
+ * @param[in]     address     64-bit boot address
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or address,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of the
+ *   resource (CPU) owner
+ */
+sc_err_t sc_pm_cpu_start(sc_ipc_t ipc, sc_rsrc_t resource, sc_bool_t enable,
+			 sc_faddr_t address);
+
+/* @} */
+
+#endif				/* SC_PM_API_H */
+
+/**@}*/
diff --git a/plat/imx/common/include/sci/svc/rm/sci_rm_api.h b/plat/imx/common/include/sci/svc/rm/sci_rm_api.h
new file mode 100644
index 0000000..012d919
--- /dev/null
+++ b/plat/imx/common/include/sci/svc/rm/sci_rm_api.h
@@ -0,0 +1,757 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file containing the public API for the System Controller (SC)
+ * Resource Management (RM) function. This includes functions for
+ * partitioning resources, pads, and memory regions.
+ *
+ * @addtogroup RM_SVC (SVC) Resource Management Service
+ *
+ * Module for the Resource Management (RM) service.
+ *
+ * @includedoc rm/details.dox
+ *
+ * @{
+ */
+
+#ifndef SC_RM_API_H
+#define SC_RM_API_H
+
+/* Includes */
+
+#include <sci/sci_types.h>
+
+/* Defines */
+
+/*!
+ * @name Defines for type widths
+ */
+/*@{*/
+#define SC_RM_PARTITION_W   5	/* Width of sc_rm_pt_t */
+#define SC_RM_MEMREG_W      6	/* Width of sc_rm_mr_t */
+#define SC_RM_DID_W         4	/* Width of sc_rm_did_t */
+#define SC_RM_SID_W         6	/* Width of sc_rm_sid_t */
+#define SC_RM_SPA_W         2	/* Width of sc_rm_spa_t */
+#define SC_RM_PERM_W        3	/* Width of sc_rm_perm_t */
+/*@}*/
+
+/*!
+ * @name Defines for ALL parameters
+ */
+/*@{*/
+#define SC_RM_PT_ALL        ((sc_rm_pt_t) UINT8_MAX)	/* All partitions */
+#define SC_RM_MR_ALL        ((sc_rm_mr_t) UINT8_MAX)	/* All memory regions */
+/*@}*/
+
+/*!
+ * @name Defines for sc_rm_spa_t
+ */
+/*@{*/
+#define SC_RM_SPA_PASSTHRU  0U	/* Pass through (attribute driven by master) */
+#define SC_RM_SPA_PASSSID   1U	/* Pass through and output on SID */
+#define SC_RM_SPA_ASSERT    2U	/* Assert (force to be secure/privileged) */
+#define SC_RM_SPA_NEGATE    3U	/* Negate (force to be non-secure/user) */
+/*@}*/
+
+/*!
+ * @name Defines for sc_rm_perm_t
+ */
+/*@{*/
+#define SC_RM_PERM_NONE         0U	/* No access */
+#define SC_RM_PERM_SEC_R        1U	/* Secure RO */
+#define SC_RM_PERM_SECPRIV_RW   2U	/* Secure privilege R/W */
+#define SC_RM_PERM_SEC_RW       3U	/* Secure R/W */
+#define SC_RM_PERM_NSPRIV_R     4U	/* Secure R/W, non-secure privilege RO */
+#define SC_RM_PERM_NS_R         5U	/* Secure R/W, non-secure RO */
+#define SC_RM_PERM_NSPRIV_RW    6U	/* Secure R/W, non-secure privilege R/W */
+#define SC_RM_PERM_FULL         7U	/* Full access */
+/*@}*/
+
+/* Types */
+
+/*!
+ * This type is used to declare a resource partition.
+ */
+typedef uint8_t sc_rm_pt_t;
+
+/*!
+ * This type is used to declare a memory region.
+ */
+typedef uint8_t sc_rm_mr_t;
+
+/*!
+ * This type is used to declare a resource domain ID used by the
+ * isolation HW.
+ */
+typedef uint8_t sc_rm_did_t;
+
+/*!
+ * This type is used to declare an SMMU StreamID.
+ */
+typedef uint16_t sc_rm_sid_t;
+
+/*!
+ * This type is a used to declare master transaction attributes.
+ */
+typedef uint8_t sc_rm_spa_t;
+
+/*!
+ * This type is used to declare a resource/memory region access permission.
+ * Refer to the XRDC2 Block Guide for more information.
+ */
+typedef uint8_t sc_rm_perm_t;
+
+/* Functions */
+
+/*!
+ * @name Partition Functions
+ * @{
+ */
+
+/*!
+ * This function requests that the SC create a new resource partition.
+ *
+ * @param[in]     ipc          IPC handle
+ * @param[out]    pt           return handle for partition; used for subsequent function
+ *                             calls associated with this partition
+ * @param[in]     secure       boolean indicating if this partition should be secure; only
+ *                             valid if caller is secure
+ * @param[in]     isolated     boolean indicating if this partition should be HW isolated
+ *                             via XRDC; set SC_TRUE if new DID is desired
+ * @param[in]     restricted   boolean indicating if this partition should be restricted; set
+ *                             SC_TRUE if masters in this partition cannot create new partitions
+ * @param[in]     grant        boolean indicating if this partition should always grant
+ *                             access and control to the parent
+ * @param[in]     coherent     boolean indicating if this partition is coherent;
+ *                             set SC_TRUE if only this partition will contain both AP clusters
+ *                             and they will be coherent via the CCI
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_ERR_PARM if caller's partition is not secure but a new secure partition is requested,
+ * - SC_ERR_LOCKED if caller's partition is locked,
+ * - SC_ERR_UNAVAILABLE if partition table is full (no more allocation space)
+ *
+ * Marking as non-secure prevents subsequent functions from configuring masters in this
+ * partition to assert the secure signal. If restricted then the new partition is limited
+ * in what functions it can call, especially those associated with managing partitions.
+ *
+ * The grant option is usually used to isolate a bus master's traffic to specific
+ * memory without isolating the peripheral interface of the master or the API
+ * controls of that master.
+ */
+sc_err_t sc_rm_partition_alloc(sc_ipc_t ipc, sc_rm_pt_t *pt, sc_bool_t secure,
+			       sc_bool_t isolated, sc_bool_t restricted,
+			       sc_bool_t grant, sc_bool_t coherent);
+
+/*!
+ * This function makes a partition confidential.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pt          handle of partition that is granting
+ * @param[in]     retro       retroactive
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if \a pt out of range,
+ * - SC_ERR_NOACCESS if caller's not allowed to change \a pt
+ * - SC_ERR_LOCKED if partition \a pt is locked
+ *
+ * Call to make a partition confidential. Confidential means only this
+ * partition should be able to grant access permissions to this partition.
+ *
+ * If retroactive, then all resources owned by other partitions will have
+ * access rights for this partition removed, even if locked.
+ */
+sc_err_t sc_rm_set_confidential(sc_ipc_t ipc, sc_rm_pt_t pt, sc_bool_t retro);
+
+/*!
+ * This function frees a partition and assigns all resources to the caller.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pt          handle of partition to free
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if \a pt out of range or invalid,
+ * - SC_ERR_NOACCESS if \a pt is the SC partition,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt,
+ * - SC_ERR_LOCKED if \a pt or caller's partition is locked
+ *
+ * All resources, memory regions, and pads are assigned to the caller/parent.
+ * The partition watchdog is disabled (even if locked). DID is freed.
+ */
+sc_err_t sc_rm_partition_free(sc_ipc_t ipc, sc_rm_pt_t pt);
+
+/*!
+ * This function returns the DID of a partition.
+ *
+ * @param[in]     ipc         IPC handle
+ *
+ * @return Returns the domain ID (DID) of the caller's partition.
+ *
+ * The DID is a SoC-specific internal ID used by the HW resource
+ * protection mechanism. It is only required by clients when using the
+ * SEMA42 module as the DID is sometimes connected to the master ID.
+ */
+sc_rm_did_t sc_rm_get_did(sc_ipc_t ipc);
+
+/*!
+ * This function forces a partition to use a specific static DID.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pt          handle of partition to assign \a did
+ * @param[in]     did         static DID to assign
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if \a pt or \a did out of range,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt,
+ * - SC_ERR_LOCKED if \a pt is locked
+ *
+ * Assumes no assigned resources or memory regions yet! The number of static
+ * DID is fixed by the SC at boot.
+ */
+sc_err_t sc_rm_partition_static(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_did_t did);
+
+/*!
+ * This function locks a partition.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pt          handle of partition to lock
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if \a pt out of range,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt
+ *
+ * If a partition is locked it cannot be freed, have resources/pads assigned
+ * to/from it, memory regions created/assigned, DID changed, or parent changed.
+ */
+sc_err_t sc_rm_partition_lock(sc_ipc_t ipc, sc_rm_pt_t pt);
+
+/*!
+ * This function gets the partition handle of the caller.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[out]    pt          return handle for caller's partition
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ */
+sc_err_t sc_rm_get_partition(sc_ipc_t ipc, sc_rm_pt_t *pt);
+
+/*!
+ * This function sets a new parent for a partition.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pt          handle of partition for which parent is to be
+ *                            changed
+ * @param[in]     pt_parent   handle of partition to set as parent
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt,
+ * - SC_ERR_LOCKED if either partition is locked
+ */
+sc_err_t sc_rm_set_parent(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_pt_t pt_parent);
+
+/*!
+ * This function moves all movable resources/pads owned by a source partition
+ * to a destination partition. It can be used to more quickly set up a new
+ * partition if a majority of the caller's resources are to be moved to a
+ * new partition.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pt_src      handle of partition from which resources should
+ *                            be moved from
+ * @param[in]     pt_dst      handle of partition to which resources should be
+ *                            moved to
+ * @param[in]     move_rsrc   boolean to indicate if resources should be moved
+ * @param[in]     move_pads   boolean to indicate if pads should be moved
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * By default, all resources are movable. This can be changed using the
+ * sc_rm_set_resource_movable() function. Note all masters defaulted to SMMU
+ * bypass.
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not \a pt_src or the
+ *   parent of \a pt_src,
+ * - SC_ERR_LOCKED if either partition is locked
+ */
+sc_err_t sc_rm_move_all(sc_ipc_t ipc, sc_rm_pt_t pt_src, sc_rm_pt_t pt_dst,
+			sc_bool_t move_rsrc, sc_bool_t move_pads);
+
+/* @} */
+
+/*!
+ * @name Resource Functions
+ * @{
+ */
+
+/*!
+ * This function assigns ownership of a resource to a partition.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pt          handle of partition to which resource should be
+ *                            assigned
+ * @param[in]     resource    resource to assign
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * This action resets the resource's master and peripheral attributes.
+ * Privilege attribute will be PASSTHRU, security attribute will be
+ * ASSERT if the partition si secure and NEGATE if it is not, and
+ * masters will defaulted to SMMU bypass. Access permissions will reset
+ * to SEC_RW for the owning partition only for secure partitions, FULL for
+ * non-secure. DEfault is no access by other partitions.
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent
+ *   of the owner,
+ * - SC_ERR_LOCKED if the owning partition or \a pt is locked
+ */
+sc_err_t sc_rm_assign_resource(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rsrc_t resource);
+
+/*!
+ * This function flags resources as movable or not.
+ *
+ * @param[in]     ipc          IPC handle
+ * @param[in]     resource_fst first resource for which flag should be set
+ * @param[in]     resource_lst last resource for which flag should be set
+ * @param[in]     movable      movable flag (SC_TRUE is movable)
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if resources are out of range,
+ * - SC_ERR_NOACCESS if caller's partition is not a parent of a resource owner,
+ * - SC_ERR_LOCKED if the owning partition is locked
+ *
+ * This function is used to determine the set of resources that will be
+ * moved using the sc_rm_move_all() function. All resources are movable
+ * by default so this function is normally used to prevent a set of
+ * resources from moving.
+ */
+sc_err_t sc_rm_set_resource_movable(sc_ipc_t ipc, sc_rsrc_t resource_fst,
+				    sc_rsrc_t resource_lst, sc_bool_t movable);
+
+/*!
+ * This function flags all of a subsystem's resources as movable
+ * or not.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    resource to use to identify subsystem
+ * @param[in]     movable     movable flag (SC_TRUE is movable)
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if a function argument is out of range
+ *
+ * Note \a resource is used to find the associated subsystem. Only
+ * resources owned by the caller are set.
+ */
+sc_err_t sc_rm_set_subsys_rsrc_movable(sc_ipc_t ipc, sc_rsrc_t resource,
+				       sc_bool_t movable);
+
+/*!
+ * This function sets attributes for a resource which is a bus master (i.e.
+ * capable of DMA).
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    master resource for which attributes should apply
+ * @param[in]     sa          security attribute
+ * @param[in]     pa          privilege attribute
+ * @param[in]     smmu_bypass SMMU bypass mode
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not a parent of the resource owner,
+ * - SC_ERR_LOCKED if the owning partition is locked
+ *
+ * This function configures how the HW isolation will see bus transactions
+ * from the specified master. Note the security attribute will only be
+ * changed if the caller's partition is secure.
+ */
+sc_err_t sc_rm_set_master_attributes(sc_ipc_t ipc, sc_rsrc_t resource,
+				     sc_rm_spa_t sa, sc_rm_spa_t pa,
+				     sc_bool_t smmu_bypass);
+
+/*!
+ * This function sets the StreamID for a resource which is a bus master (i.e.
+ * capable of DMA).
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    master resource for which attributes should apply
+ * @param[in]     sid         StreamID
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent
+ *   of the owner,
+ * - SC_ERR_LOCKED if the owning partition is locked
+ *
+ * This function configures the SID attribute associated with all bus transactions
+ * from this master. Note 0 is not a valid SID as it is reserved to indicate
+ * bypass.
+ */
+sc_err_t sc_rm_set_master_sid(sc_ipc_t ipc, sc_rsrc_t resource,
+			      sc_rm_sid_t sid);
+
+/*!
+ * This function sets access permissions for a peripheral resource.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    peripheral resource for which permissions should apply
+ * @param[in]     pt          handle of partition \a perm should by applied for
+ * @param[in]     perm        permissions to apply to \a resource for \a pt
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent
+ *   of the owner,
+ * - SC_ERR_LOCKED if the owning partition is locked
+ * - SC_ERR_LOCKED if the \a pt is confidential and the caller isn't \a pt
+ *
+ * This function configures how the HW isolation will restrict access to a
+ * peripheral based on the attributes of a transaction from bus master.
+ */
+sc_err_t sc_rm_set_peripheral_permissions(sc_ipc_t ipc, sc_rsrc_t resource,
+					  sc_rm_pt_t pt, sc_rm_perm_t perm);
+
+/*!
+ * This function gets ownership status of a resource.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    resource to check
+ *
+ * @return Returns a boolean (SC_TRUE if caller's partition owns the resource).
+ *
+ * If \a resource is out of range then SC_FALSE is returned.
+ */
+sc_bool_t sc_rm_is_resource_owned(sc_ipc_t ipc, sc_rsrc_t resource);
+
+/*!
+ * This function is used to test if a resource is a bus master.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    resource to check
+ *
+ * @return Returns a boolean (SC_TRUE if the resource is a bus master).
+ *
+ * If \a resource is out of range then SC_FALSE is returned.
+ */
+sc_bool_t sc_rm_is_resource_master(sc_ipc_t ipc, sc_rsrc_t resource);
+
+/*!
+ * This function is used to test if a resource is a peripheral.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    resource to check
+ *
+ * @return Returns a boolean (SC_TRUE if the resource is a peripheral).
+ *
+ * If \a resource is out of range then SC_FALSE is returned.
+ */
+sc_bool_t sc_rm_is_resource_peripheral(sc_ipc_t ipc, sc_rsrc_t resource);
+
+/*!
+ * This function is used to obtain info about a resource.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     resource    resource to inquire about
+ * @param[out]    sid         pointer to return StreamID
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if \a resource is out of range
+ */
+sc_err_t sc_rm_get_resource_info(sc_ipc_t ipc, sc_rsrc_t resource,
+				 sc_rm_sid_t *sid);
+
+/* @} */
+
+/*!
+ * @name Memory Region Functions
+ * @{
+ */
+
+/*!
+ * This function requests that the SC create a new memory region.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[out]    mr          return handle for region; used for
+ *                            subsequent function calls
+ *                            associated with this region
+ * @param[in]     addr_start  start address of region (physical)
+ * @param[in]     addr_end    end address of region (physical)
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if the new memory region is misaligned,
+ * - SC_ERR_LOCKED if caller's partition is locked,
+ * - SC_ERR_PARM if the new memory region spans multiple existing regions,
+ * - SC_ERR_NOACCESS if caller's partition does not own the memory containing
+ *   the new region,
+ * - SC_ERR_UNAVAILABLE if memory region table is full (no more allocation
+ *   space)
+ *
+ * The area covered by the memory region must currently be owned by the caller.
+ * By default, the new region will have access permission set to allow the
+ * caller to access.
+ */
+sc_err_t sc_rm_memreg_alloc(sc_ipc_t ipc, sc_rm_mr_t *mr,
+			    sc_faddr_t addr_start, sc_faddr_t addr_end);
+
+/*!
+ * This function requests that the SC split a memory region.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     mr          handle of memory region to split
+ * @param[out]    mr_ret      return handle for new region; used for
+ *                            subsequent function calls
+ *                            associated with this region
+ * @param[in]     addr_start  start address of region (physical)
+ * @param[in]     addr_end    end address of region (physical)
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if the new memory region is not start/end part of mr,
+ * - SC_ERR_LOCKED if caller's partition is locked,
+ * - SC_ERR_PARM if the new memory region spans multiple existing regions,
+ * - SC_ERR_NOACCESS if caller's partition does not own the memory containing
+ *   the new region,
+ * - SC_ERR_UNAVAILABLE if memory region table is full (no more allocation
+ *   space)
+ *
+ * Note the new region must start or end on the split region.
+ */
+sc_err_t sc_rm_memreg_split(sc_ipc_t ipc, sc_rm_mr_t mr,
+			    sc_rm_mr_t *mr_ret, sc_faddr_t addr_start,
+			    sc_faddr_t addr_end);
+
+/*!
+ * This function frees a memory region.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     mr          handle of memory region to free
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if \a mr out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not a parent of \a mr,
+ * - SC_ERR_LOCKED if the owning partition of \a mr is locked
+ */
+sc_err_t sc_rm_memreg_free(sc_ipc_t ipc, sc_rm_mr_t mr);
+
+/*!
+ * Internal SC function to find a memory region.
+ *
+ * @see sc_rm_find_memreg().
+ */
+/*!
+ * This function finds a memory region.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[out]    mr          return handle for region; used for
+ *                            subsequent function calls
+ *                            associated with this region
+ * @param[in]     addr_start  start address of region to search for
+ * @param[in]     addr_end    end address of region to search for
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOTFOUND if region not found,
+ *
+ * Searches only for regions owned by the caller. Finds first
+ * region containing the range specified.
+ */
+sc_err_t sc_rm_find_memreg(sc_ipc_t ipc, sc_rm_mr_t *mr,
+			   sc_faddr_t addr_start, sc_faddr_t addr_end);
+
+/*!
+ * This function assigns ownership of a memory region.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pt          handle of partition to which memory region
+ *                            should be assigned
+ * @param[in]     mr          handle of memory region to assign
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the \a mr owner or parent
+ *   of the owner,
+ * - SC_ERR_LOCKED if the owning partition or \a pt is locked
+ */
+sc_err_t sc_rm_assign_memreg(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_mr_t mr);
+
+/*!
+ * This function sets access permissions for a memory region.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     mr          handle of memory region for which permissions
+ *                            should apply
+ * @param[in]     pt          handle of partition \a perm should by
+ *                            applied for
+ * @param[in]     perm        permissions to apply to \a mr for \a pt
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the region owner or parent
+ *   of the owner,
+ * - SC_ERR_LOCKED if the owning partition is locked
+ * - SC_ERR_LOCKED if the \a pt is confidential and the caller isn't \a pt
+ *
+ * This function configures how the HW isolation will restrict access to a
+ * memory region based on the attributes of a transaction from bus master.
+ */
+sc_err_t sc_rm_set_memreg_permissions(sc_ipc_t ipc, sc_rm_mr_t mr,
+				      sc_rm_pt_t pt, sc_rm_perm_t perm);
+
+/*!
+ * This function gets ownership status of a memory region.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     mr          handle of memory region to check
+ *
+ * @return Returns a boolean (SC_TRUE if caller's partition owns the
+ * memory region).
+ *
+ * If \a mr is out of range then SC_FALSE is returned.
+ */
+sc_bool_t sc_rm_is_memreg_owned(sc_ipc_t ipc, sc_rm_mr_t mr);
+
+/*!
+ * This function is used to obtain info about a memory region.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     mr          handle of memory region to inquire about
+ * @param[out]    addr_start  pointer to return start address
+ * @param[out]    addr_end    pointer to return end address
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if \a mr is out of range
+ */
+sc_err_t sc_rm_get_memreg_info(sc_ipc_t ipc, sc_rm_mr_t mr,
+			       sc_faddr_t *addr_start, sc_faddr_t *addr_end);
+
+/* @} */
+
+/*!
+ * @name Pad Functions
+ * @{
+ */
+
+/*!
+ * This function assigns ownership of a pad to a partition.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pt          handle of partition to which pad should
+ *                            be assigned
+ * @param[in]     pad         pad to assign
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner or parent
+ *   of the owner,
+ * - SC_ERR_LOCKED if the owning partition or \a pt is locked
+ */
+sc_err_t sc_rm_assign_pad(sc_ipc_t ipc, sc_rm_pt_t pt, sc_pad_t pad);
+
+/*!
+ * This function flags pads as movable or not.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad_fst     first pad for which flag should be set
+ * @param[in]     pad_lst     last pad for which flag should be set
+ * @param[in]     movable     movable flag (SC_TRUE is movable)
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if pads are out of range,
+ * - SC_ERR_NOACCESS if caller's partition is not a parent of a pad owner,
+ * - SC_ERR_LOCKED if the owning partition is locked
+ *
+ * This function is used to determine the set of pads that will be
+ * moved using the sc_rm_move_all() function. All pads are movable
+ * by default so this function is normally used to prevent a set of
+ * pads from moving.
+ */
+sc_err_t sc_rm_set_pad_movable(sc_ipc_t ipc, sc_pad_t pad_fst,
+			       sc_pad_t pad_lst, sc_bool_t movable);
+
+/*!
+ * This function gets ownership status of a pad.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     pad         pad to check
+ *
+ * @return Returns a boolean (SC_TRUE if caller's partition owns the pad).
+ *
+ * If \a pad is out of range then SC_FALSE is returned.
+ */
+sc_bool_t sc_rm_is_pad_owned(sc_ipc_t ipc, sc_pad_t pad);
+
+/* @} */
+
+/*!
+ * @name Debug Functions
+ * @{
+ */
+
+/*!
+ * This function dumps the RM state for debug.
+ *
+ * @param[in]     ipc         IPC handle
+ */
+void sc_rm_dump(sc_ipc_t ipc);
+
+/* @} */
+
+#endif				/* SC_RM_API_H */
+
+/**@}*/
diff --git a/plat/imx/common/lpuart_console.S b/plat/imx/common/lpuart_console.S
new file mode 100644
index 0000000..ad71b89
--- /dev/null
+++ b/plat/imx/common/lpuart_console.S
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <console_macros.S>
+#include <assert_macros.S>
+#include "imx8_lpuart.h"
+
+	.globl	console_lpuart_register
+	.globl	console_lpuart_init
+	.globl	console_lpuart_putc
+	.globl	console_lpuart_getc
+
+func console_lpuart_register
+	mov	x7, x30
+	mov	x6, x3
+	cbz	x6, register_fail
+	str	x0, [x6, #CONSOLE_T_DRVDATA]
+
+	bl	console_lpuart_init
+	cbz	x0, register_fail
+
+	mov	x0, x6
+	mov	x30, x7
+	finish_console_register lpuart
+
+register_fail:
+	ret	x7
+endfunc console_lpuart_register
+
+func console_lpuart_init
+	mov	w0, #1
+	ret
+endfunc console_lpuart_init
+
+func console_lpuart_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, #STAT]
+	tbz	w2, #23, 1b
+	mov	w2, #0xD
+	str	w2, [x1, #DATA]
+2:
+	/* Check if the transmit FIFO is full */
+	ldr	w2, [x1, #STAT]
+	tbz	w2, #23, 2b
+	str	w0, [x1, #DATA]
+	ret
+putc_error:
+	mov	w0, #-1
+	ret
+endfunc console_lpuart_putc
+
+func console_lpuart_getc
+	ldr	x0, [x0, #CONSOLE_T_DRVDATA]
+	cbz	x0, getc_error
+	/* Check if the receive FIFO state */
+	ret
+getc_error:
+	mov	w0, #-1
+	ret
+endfunc console_lpuart_getc
diff --git a/plat/imx/common/plat_imx8_gic.c b/plat/imx/common/plat_imx8_gic.c
new file mode 100644
index 0000000..242e31b
--- /dev/null
+++ b/plat/imx/common/plat_imx8_gic.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <gicv3.h>
+#include <plat_imx8.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <utils.h>
+
+/* the GICv3 driver only needs to be initialized in EL3 */
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+/* array of Group1 secure interrupts to be configured by the gic driver */
+const unsigned int g1s_interrupt_array[] = { 6 };
+
+/* array of Group0 interrupts to be configured by the gic driver */
+const unsigned int g0_interrupt_array[] = { 7 };
+
+static unsigned int plat_imx_mpidr_to_core_pos(unsigned long mpidr)
+{
+	return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+const gicv3_driver_data_t arm_gic_data = {
+	.gicd_base = PLAT_GICD_BASE,
+	.gicr_base = PLAT_GICR_BASE,
+	.g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array),
+	.g1s_interrupt_num = ARRAY_SIZE(g1s_interrupt_array),
+	.g0_interrupt_array = g0_interrupt_array,
+	.g1s_interrupt_array = g1s_interrupt_array,
+	.rdistif_num = PLATFORM_CORE_COUNT,
+	.rdistif_base_addrs = rdistif_base_addrs,
+	.mpidr_to_core_pos = plat_imx_mpidr_to_core_pos,
+};
+
+void plat_gic_driver_init(void)
+{
+	/*
+	 * the GICv3 driver is initialized in EL3 and does not need
+	 * to be initialized again in S-EL1. This is because the S-EL1
+	 * can use GIC system registers to manage interrupts and does
+	 * not need GIC interface base addresses to be configured.
+	 */
+#if IMAGE_BL31
+	gicv3_driver_init(&arm_gic_data);
+#endif
+}
+
+void plat_gic_init(void)
+{
+	gicv3_distif_init();
+	gicv3_rdistif_init(plat_my_core_pos());
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void plat_gic_cpuif_enable(void)
+{
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void plat_gic_cpuif_disable(void)
+{
+	gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+void plat_gic_pcpu_init(void)
+{
+	gicv3_rdistif_init(plat_my_core_pos());
+}
diff --git a/plat/imx/common/sci/imx8_mu.c b/plat/imx/common/sci/imx8_mu.c
new file mode 100644
index 0000000..8028c76
--- /dev/null
+++ b/plat/imx/common/sci/imx8_mu.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mmio.h>
+#include "imx8_mu.h"
+
+void MU_EnableRxFullInt(uint32_t base, uint32_t index)
+{
+	uint32_t reg = mmio_read_32(base + MU_ACR_OFFSET1);
+
+	reg &= ~(MU_CR_GIRn_MASK1 | MU_CR_NMI_MASK1);
+	reg |= MU_CR_RIE0_MASK1 >> index;
+	mmio_write_32(base + MU_ACR_OFFSET1, reg);
+}
+
+void MU_EnableGeneralInt(uint32_t base, uint32_t index)
+{
+	uint32_t reg = mmio_read_32(base + MU_ACR_OFFSET1);
+
+	reg &= ~(MU_CR_GIRn_MASK1 | MU_CR_NMI_MASK1);
+	reg |= MU_CR_GIE0_MASK1 >> index;
+	mmio_write_32(base + MU_ACR_OFFSET1, reg);
+}
+
+void MU_SendMessage(uint32_t base, uint32_t regIndex, uint32_t msg)
+{
+	uint32_t mask = MU_SR_TE0_MASK1 >> regIndex;
+
+	/* Wait TX register to be empty. */
+	while (!(mmio_read_32(base + MU_ASR_OFFSET1) & mask))
+		;
+	mmio_write_32(base + MU_ATR0_OFFSET1 + (regIndex * 4), msg);
+}
+
+void MU_ReceiveMsg(uint32_t base, uint32_t regIndex, uint32_t *msg)
+{
+	uint32_t mask = MU_SR_RF0_MASK1 >> regIndex;
+
+	/* Wait RX register to be full. */
+	while (!(mmio_read_32(base + MU_ASR_OFFSET1) & mask))
+		;
+	*msg = mmio_read_32(base + MU_ARR0_OFFSET1 + (regIndex * 4));
+}
+
+void MU_Init(uint32_t base)
+{
+	uint32_t reg;
+
+	reg = mmio_read_32(base + MU_ACR_OFFSET1);
+	/* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */
+	reg &= ~(MU_CR_GIEn_MASK1 | MU_CR_RIEn_MASK1 | MU_CR_TIEn_MASK1
+			| MU_CR_GIRn_MASK1 | MU_CR_Fn_MASK1);
+	mmio_write_32(base + MU_ACR_OFFSET1, reg);
+}
diff --git a/plat/imx/common/sci/imx8_mu.h b/plat/imx/common/sci/imx8_mu.h
new file mode 100644
index 0000000..8834a97
--- /dev/null
+++ b/plat/imx/common/sci/imx8_mu.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <types.h>
+
+#define MU_ATR0_OFFSET1		0x0
+#define MU_ARR0_OFFSET1		0x10
+#define MU_ASR_OFFSET1		0x20
+#define MU_ACR_OFFSET1		0x24
+#define MU_TR_COUNT1		4
+#define MU_RR_COUNT1		4
+
+#define MU_CR_GIEn_MASK1	(0xF << 28)
+#define MU_CR_RIEn_MASK1	(0xF << 24)
+#define MU_CR_TIEn_MASK1	(0xF << 20)
+#define MU_CR_GIRn_MASK1	(0xF << 16)
+#define MU_CR_NMI_MASK1		(1 << 3)
+#define MU_CR_Fn_MASK1		0x7
+
+#define MU_SR_TE0_MASK1		(1 << 23)
+#define MU_SR_RF0_MASK1		(1 << 27)
+#define MU_CR_RIE0_MASK1	(1 << 27)
+#define MU_CR_GIE0_MASK1	(1 << 31)
+
+#define MU_TR_COUNT			4
+#define MU_RR_COUNT			4
+
+void MU_Init(uint32_t base);
+void MU_SendMessage(uint32_t base, uint32_t regIndex, uint32_t msg);
+void MU_ReceiveMsg(uint32_t base, uint32_t regIndex, uint32_t *msg);
+void MU_EnableGeneralInt(uint32_t base, uint32_t index);
+void MU_EnableRxFullInt(uint32_t base, uint32_t index);
diff --git a/plat/imx/common/sci/ipc.c b/plat/imx/common/sci/ipc.c
new file mode 100644
index 0000000..2af2567
--- /dev/null
+++ b/plat/imx/common/sci/ipc.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bakery_lock.h>
+#include <sci/sci_scfw.h>
+#include <sci/sci_ipc.h>
+#include <sci/sci_rpc.h>
+#include <stdlib.h>
+#include "imx8_mu.h"
+
+DEFINE_BAKERY_LOCK(sc_ipc_bakery_lock);
+#define sc_ipc_lock_init()	bakery_lock_init(&sc_ipc_bakery_lock)
+#define sc_ipc_lock()		bakery_lock_get(&sc_ipc_bakery_lock)
+#define sc_ipc_unlock()		bakery_lock_release(&sc_ipc_bakery_lock)
+
+void sc_call_rpc(sc_ipc_t ipc, sc_rpc_msg_t *msg, bool no_resp)
+{
+	sc_ipc_lock();
+
+	sc_ipc_write(ipc, msg);
+	if (!no_resp)
+		sc_ipc_read(ipc, msg);
+
+	sc_ipc_unlock();
+}
+
+sc_err_t sc_ipc_open(sc_ipc_t *ipc, sc_ipc_id_t id)
+{
+	uint32_t base = id;
+	uint32_t i;
+
+	/* Get MU base associated with IPC channel */
+	if ((ipc == NULL) || (base == 0))
+		return SC_ERR_IPC;
+
+	sc_ipc_lock_init();
+
+	/* Init MU */
+	MU_Init(base);
+
+	/* Enable all RX interrupts */
+	for (i = 0; i < MU_RR_COUNT; i++) {
+		MU_EnableRxFullInt(base, i);
+	}
+
+	/* Return MU address as handle */
+	*ipc = (sc_ipc_t) id;
+
+	return SC_ERR_NONE;
+}
+
+void sc_ipc_close(sc_ipc_t ipc)
+{
+	uint32_t base = ipc;
+
+	if (base != 0)
+		MU_Init(base);
+}
+
+void sc_ipc_read(sc_ipc_t ipc, void *data)
+{
+	uint32_t base = ipc;
+	sc_rpc_msg_t *msg = (sc_rpc_msg_t *) data;
+	uint8_t count = 0;
+
+	/* Check parms */
+	if ((base == 0) || (msg == NULL))
+		return;
+
+	/* Read first word */
+	MU_ReceiveMsg(base, 0, (uint32_t *) msg);
+	count++;
+
+	/* Check size */
+	if (msg->size > SC_RPC_MAX_MSG) {
+		*((uint32_t *) msg) = 0;
+		return;
+	}
+
+	/* Read remaining words */
+	while (count < msg->size) {
+		MU_ReceiveMsg(base, count % MU_RR_COUNT,
+			&(msg->DATA.u32[count - 1]));
+		count++;
+	}
+}
+
+void sc_ipc_write(sc_ipc_t ipc, void *data)
+{
+	sc_rpc_msg_t *msg = (sc_rpc_msg_t *) data;
+	uint32_t base = ipc;
+	uint8_t count = 0;
+
+	/* Check parms */
+	if ((base == 0) || (msg == NULL))
+		return;
+
+	/* Check size */
+	if (msg->size > SC_RPC_MAX_MSG)
+		return;
+
+	/* Write first word */
+	MU_SendMessage(base, 0, *((uint32_t *) msg));
+	count++;
+
+	/* Write remaining words */
+	while (count < msg->size) {
+		MU_SendMessage(base, count % MU_TR_COUNT,
+			msg->DATA.u32[count - 1]);
+		count++;
+	}
+}
+
diff --git a/plat/imx/common/sci/sci_api.mk b/plat/imx/common/sci/sci_api.mk
new file mode 100644
index 0000000..b277877
--- /dev/null
+++ b/plat/imx/common/sci/sci_api.mk
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL31_SOURCES	+=	plat/imx/common/sci/ipc.c			\
+			plat/imx/common/sci/imx8_mu.c			\
+			plat/imx/common/sci/svc/pad/pad_rpc_clnt.c	\
+			plat/imx/common/sci/svc/pm/pm_rpc_clnt.c	\
+			plat/imx/common/sci/svc/rm/rm_rpc_clnt.c
diff --git a/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c b/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c
new file mode 100644
index 0000000..555e704
--- /dev/null
+++ b/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * File containing client-side RPC functions for the PAD service. These
+ * functions are ported to clients that communicate to the SC.
+ *
+ * @addtogroup PAD_SVC
+ * @{
+ */
+
+/* Includes */
+
+#include <sci/sci_types.h>
+#include <sci/svc/rm/sci_rm_api.h>
+#include <sci/svc/pad/sci_pad_api.h>
+#include <sci/sci_rpc.h>
+#include <stdlib.h>
+#include "sci_pad_rpc.h"
+
+/* Local Defines */
+
+/* Local Types */
+
+/* Local Functions */
+
+sc_err_t sc_pad_set_mux(sc_ipc_t ipc, sc_pad_t pad,
+			uint8_t mux, sc_pad_config_t config, sc_pad_iso_t iso)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_MUX;
+	RPC_U16(&msg, 0U) = (uint16_t)pad;
+	RPC_U8(&msg, 2U) = (uint8_t)mux;
+	RPC_U8(&msg, 3U) = (uint8_t)config;
+	RPC_U8(&msg, 4U) = (uint8_t)iso;
+	RPC_SIZE(&msg) = 3U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get_mux(sc_ipc_t ipc, sc_pad_t pad,
+			uint8_t *mux, sc_pad_config_t *config,
+			sc_pad_iso_t *iso)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_MUX;
+	RPC_U16(&msg, 0U) = (uint16_t)pad;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	if (mux != NULL) {
+		*mux = RPC_U8(&msg, 0U);
+	}
+
+	if (config != NULL) {
+		*config = RPC_U8(&msg, 1U);
+	}
+
+	if (iso != NULL) {
+		*iso = RPC_U8(&msg, 2U);
+	}
+
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_set_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t ctrl)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP;
+	RPC_U32(&msg, 0U) = (uint32_t)ctrl;
+	RPC_U16(&msg, 4U) = (uint16_t)pad;
+	RPC_SIZE(&msg) = 3U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t *ctrl)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP;
+	RPC_U16(&msg, 0U) = (uint16_t)pad;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	if (ctrl != NULL) {
+		*ctrl = RPC_U32(&msg, 0U);
+	}
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_set_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t wakeup)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_WAKEUP;
+	RPC_U16(&msg, 0U) = (uint16_t)pad;
+	RPC_U8(&msg, 2U) = (uint8_t)wakeup;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t *wakeup)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_WAKEUP;
+	RPC_U16(&msg, 0U) = (uint16_t)pad;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	if (wakeup != NULL) {
+		*wakeup = RPC_U8(&msg, 0U);
+	}
+
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_set_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t mux,
+			sc_pad_config_t config, sc_pad_iso_t iso, uint32_t ctrl,
+			sc_pad_wakeup_t wakeup)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_ALL;
+	RPC_U32(&msg, 0U) = (uint32_t)ctrl;
+	RPC_U16(&msg, 4U) = (uint16_t)pad;
+	RPC_U8(&msg, 6U) = (uint8_t)mux;
+	RPC_U8(&msg, 7U) = (uint8_t)config;
+	RPC_U8(&msg, 8U) = (uint8_t)iso;
+	RPC_U8(&msg, 9U) = (uint8_t)wakeup;
+	RPC_SIZE(&msg) = 4U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t *mux,
+			sc_pad_config_t *config, sc_pad_iso_t *iso,
+			uint32_t *ctrl, sc_pad_wakeup_t *wakeup)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_ALL;
+	RPC_U16(&msg, 0U) = (uint16_t)pad;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	if (ctrl != NULL) {
+		*ctrl = RPC_U32(&msg, 0U);
+	}
+
+	result = RPC_R8(&msg);
+	if (mux != NULL) {
+		*mux = RPC_U8(&msg, 4U);
+	}
+
+	if (config != NULL) {
+		*config = RPC_U8(&msg, 5U);
+	}
+
+	if (iso != NULL) {
+		*iso = RPC_U8(&msg, 6U);
+	}
+
+	if (wakeup != NULL) {
+		*wakeup = RPC_U8(&msg, 7U);
+	}
+
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_set(sc_ipc_t ipc, sc_pad_t pad, uint32_t val)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET;
+	RPC_U32(&msg, 0U) = (uint32_t)val;
+	RPC_U16(&msg, 4U) = (uint16_t)pad;
+	RPC_SIZE(&msg) = 3U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get(sc_ipc_t ipc, sc_pad_t pad, uint32_t *val)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET;
+	RPC_U16(&msg, 0U) = (uint16_t)pad;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	if (val != NULL) {
+		*val = RPC_U32(&msg, 0U);
+	}
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_set_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad,
+			       sc_pad_28fdsoi_dse_t dse, sc_pad_28fdsoi_ps_t ps)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP_28FDSOI;
+	RPC_U16(&msg, 0U) = (uint16_t)pad;
+	RPC_U8(&msg, 2U) = (uint8_t)dse;
+	RPC_U8(&msg, 3U) = (uint8_t)ps;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad,
+			       sc_pad_28fdsoi_dse_t *dse,
+			       sc_pad_28fdsoi_ps_t *ps)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP_28FDSOI;
+	RPC_U16(&msg, 0U) = (uint16_t)pad;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	if (dse != NULL) {
+		*dse = RPC_U8(&msg, 0U);
+	}
+
+	if (ps != NULL) {
+		*ps = RPC_U8(&msg, 1U);
+	}
+
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_set_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad,
+				    sc_pad_28fdsoi_dse_t dse, sc_bool_t hys,
+				    sc_pad_28fdsoi_pus_t pus, sc_bool_t pke,
+				    sc_bool_t pue)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP_28FDSOI_HSIC;
+	RPC_U16(&msg, 0U) = (uint16_t)pad;
+	RPC_U8(&msg, 2U) = (uint8_t)dse;
+	RPC_U8(&msg, 3U) = (uint8_t)pus;
+	RPC_U8(&msg, 4U) = (uint8_t)hys;
+	RPC_U8(&msg, 5U) = (uint8_t)pke;
+	RPC_U8(&msg, 6U) = (uint8_t)pue;
+	RPC_SIZE(&msg) = 3U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad,
+				    sc_pad_28fdsoi_dse_t *dse, sc_bool_t *hys,
+				    sc_pad_28fdsoi_pus_t *pus, sc_bool_t *pke,
+				    sc_bool_t *pue)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP_28FDSOI_HSIC;
+	RPC_U16(&msg, 0U) = (uint16_t)pad;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	if (dse != NULL) {
+		*dse = RPC_U8(&msg, 0U);
+	}
+
+	if (pus != NULL) {
+		*pus = RPC_U8(&msg, 1U);
+	}
+
+	if (hys != NULL) {
+		*hys = RPC_U8(&msg, 2U);
+	}
+
+	if (pke != NULL) {
+		*pke = RPC_U8(&msg, 3U);
+	}
+
+	if (pue != NULL) {
+		*pue = RPC_U8(&msg, 4U);
+	}
+
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_set_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad,
+				    uint8_t compen, sc_bool_t fastfrz,
+				    uint8_t rasrcp, uint8_t rasrcn,
+				    sc_bool_t nasrc_sel, sc_bool_t psw_ovr)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP_28FDSOI_COMP;
+	RPC_U16(&msg, 0U) = (uint16_t)pad;
+	RPC_U8(&msg, 2U) = (uint8_t)compen;
+	RPC_U8(&msg, 3U) = (uint8_t)rasrcp;
+	RPC_U8(&msg, 4U) = (uint8_t)rasrcn;
+	RPC_U8(&msg, 5U) = (uint8_t)fastfrz;
+	RPC_U8(&msg, 6U) = (uint8_t)nasrc_sel;
+	RPC_U8(&msg, 7U) = (uint8_t)psw_ovr;
+	RPC_SIZE(&msg) = 3U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad,
+				    uint8_t *compen, sc_bool_t *fastfrz,
+				    uint8_t *rasrcp, uint8_t *rasrcn,
+				    sc_bool_t *nasrc_sel, sc_bool_t *compok,
+				    uint8_t *nasrc, sc_bool_t *psw_ovr)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+	RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP_28FDSOI_COMP;
+	RPC_U16(&msg, 0U) = (uint16_t)pad;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	if (compen != NULL) {
+		*compen = RPC_U8(&msg, 0U);
+	}
+
+	if (rasrcp != NULL) {
+		*rasrcp = RPC_U8(&msg, 1U);
+	}
+
+	if (rasrcn != NULL) {
+		*rasrcn = RPC_U8(&msg, 2U);
+	}
+
+	if (nasrc != NULL) {
+		*nasrc = RPC_U8(&msg, 3U);
+	}
+
+	if (fastfrz != NULL) {
+		*fastfrz = RPC_U8(&msg, 4U);
+	}
+
+	if (nasrc_sel != NULL) {
+		*nasrc_sel = RPC_U8(&msg, 5U);
+	}
+
+	if (compok != NULL) {
+		*compok = RPC_U8(&msg, 6U);
+	}
+
+	if (psw_ovr != NULL) {
+		*psw_ovr = RPC_U8(&msg, 7U);
+	}
+
+	return (sc_err_t)result;
+}
+
+/**@}*/
diff --git a/plat/imx/common/sci/svc/pad/sci_pad_rpc.h b/plat/imx/common/sci/svc/pad/sci_pad_rpc.h
new file mode 100644
index 0000000..686e6e9
--- /dev/null
+++ b/plat/imx/common/sci/svc/pad/sci_pad_rpc.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file for the PAD RPC implementation.
+ *
+ * @addtogroup PAD_SVC
+ * @{
+ */
+
+#ifndef SC_PAD_RPC_H
+#define SC_PAD_RPC_H
+
+/* Includes */
+
+/* Defines */
+
+/*!
+ * @name Defines for RPC PAD function calls
+ */
+/*@{*/
+#define PAD_FUNC_UNKNOWN 0	/* Unknown function */
+#define PAD_FUNC_SET_MUX 1U	/* Index for pad_set_mux() RPC call */
+#define PAD_FUNC_GET_MUX 6U	/* Index for pad_get_mux() RPC call */
+#define PAD_FUNC_SET_GP 2U	/* Index for pad_set_gp() RPC call */
+#define PAD_FUNC_GET_GP 7U	/* Index for pad_get_gp() RPC call */
+#define PAD_FUNC_SET_WAKEUP 4U	/* Index for pad_set_wakeup() RPC call */
+#define PAD_FUNC_GET_WAKEUP 9U	/* Index for pad_get_wakeup() RPC call */
+#define PAD_FUNC_SET_ALL 5U	/* Index for pad_set_all() RPC call */
+#define PAD_FUNC_GET_ALL 10U	/* Index for pad_get_all() RPC call */
+#define PAD_FUNC_SET 15U	/* Index for pad_set() RPC call */
+#define PAD_FUNC_GET 16U	/* Index for pad_get() RPC call */
+#define PAD_FUNC_SET_GP_28FDSOI 11U	/* Index for pad_set_gp_28fdsoi() RPC call */
+#define PAD_FUNC_GET_GP_28FDSOI 12U	/* Index for pad_get_gp_28fdsoi() RPC call */
+#define PAD_FUNC_SET_GP_28FDSOI_HSIC 3U	/* Index for pad_set_gp_28fdsoi_hsic() RPC call */
+#define PAD_FUNC_GET_GP_28FDSOI_HSIC 8U	/* Index for pad_get_gp_28fdsoi_hsic() RPC call */
+#define PAD_FUNC_SET_GP_28FDSOI_COMP 13U	/* Index for pad_set_gp_28fdsoi_comp() RPC call */
+#define PAD_FUNC_GET_GP_28FDSOI_COMP 14U	/* Index for pad_get_gp_28fdsoi_comp() RPC call */
+/*@}*/
+
+/* Types */
+
+/* Functions */
+
+/*!
+ * This function dispatches an incoming PAD RPC request.
+ *
+ * @param[in]     caller_pt   caller partition
+ * @param[in]     msg         pointer to RPC message
+ */
+void pad_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg);
+
+/*!
+ * This function translates and dispatches an PAD RPC request.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     msg         pointer to RPC message
+ */
+void pad_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg);
+
+#endif				/* SC_PAD_RPC_H */
+
+/**@}*/
diff --git a/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c b/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c
new file mode 100644
index 0000000..b108c49
--- /dev/null
+++ b/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * File containing client-side RPC functions for the PM service. These
+ * functions are ported to clients that communicate to the SC.
+ *
+ * @addtogroup PM_SVC
+ * @{
+ */
+
+/* Includes */
+
+#include <sci/sci_types.h>
+#include <sci/svc/rm/sci_rm_api.h>
+#include <sci/svc/pm/sci_pm_api.h>
+#include <sci/sci_rpc.h>
+#include <stdlib.h>
+#include "sci_pm_rpc.h"
+
+/* Local Defines */
+
+/* Local Types */
+
+/* Local Functions */
+
+sc_err_t sc_pm_set_sys_power_mode(sc_ipc_t ipc, sc_pm_power_mode_t mode)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_SYS_POWER_MODE;
+	RPC_U8(&msg, 0U) = (uint8_t)mode;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_set_partition_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt,
+					sc_pm_power_mode_t mode)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_PARTITION_POWER_MODE;
+	RPC_U8(&msg, 0U) = (uint8_t)pt;
+	RPC_U8(&msg, 1U) = (uint8_t)mode;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_get_sys_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt,
+				  sc_pm_power_mode_t *mode)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_SYS_POWER_MODE;
+	RPC_U8(&msg, 0U) = (uint8_t)pt;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	if (mode != NULL) {
+		*mode = RPC_U8(&msg, 0U);
+	}
+
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_set_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+				       sc_pm_power_mode_t mode)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_RESOURCE_POWER_MODE;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_U8(&msg, 2U) = (uint8_t)mode;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+				       sc_pm_power_mode_t *mode)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_RESOURCE_POWER_MODE;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	if (mode != NULL) {
+		*mode = RPC_U8(&msg, 0U);
+	}
+
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_req_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+				  sc_pm_power_mode_t mode)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_LOW_POWER_MODE;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_U8(&msg, 2U) = (uint8_t)mode;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_req_cpu_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+				      sc_pm_power_mode_t mode,
+				      sc_pm_wake_src_t wake_src)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_CPU_LOW_POWER_MODE;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_U8(&msg, 2U) = (uint8_t)mode;
+	RPC_U8(&msg, 3U) = (uint8_t)wake_src;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_set_cpu_resume_addr(sc_ipc_t ipc, sc_rsrc_t resource,
+				   sc_faddr_t address)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CPU_RESUME_ADDR;
+	RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U);
+	RPC_U32(&msg, 4U) = (uint32_t)address;
+	RPC_U16(&msg, 8U) = (uint16_t)resource;
+	RPC_SIZE(&msg) = 4U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_set_cpu_resume(sc_ipc_t ipc, sc_rsrc_t resource,
+			      sc_bool_t isPrimary, sc_faddr_t address)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CPU_RESUME;
+	RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U);
+	RPC_U32(&msg, 4U) = (uint32_t)address;
+	RPC_U16(&msg, 8U) = (uint16_t)resource;
+	RPC_U8(&msg, 10U) = (uint8_t)isPrimary;
+	RPC_SIZE(&msg) = 4U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_req_sys_if_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+				     sc_pm_sys_if_t sys_if,
+				     sc_pm_power_mode_t hpm,
+				     sc_pm_power_mode_t lpm)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_SYS_IF_POWER_MODE;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_U8(&msg, 2U) = (uint8_t)sys_if;
+	RPC_U8(&msg, 3U) = (uint8_t)hpm;
+	RPC_U8(&msg, 4U) = (uint8_t)lpm;
+	RPC_SIZE(&msg) = 3U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_set_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource,
+			      sc_pm_clk_t clk, sc_pm_clock_rate_t *rate)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CLOCK_RATE;
+	RPC_U32(&msg, 0U) = *(uint32_t *)rate;
+	RPC_U16(&msg, 4U) = (uint16_t)resource;
+	RPC_U8(&msg, 6U) = (uint8_t)clk;
+	RPC_SIZE(&msg) = 3U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	*rate = RPC_U32(&msg, 0U);
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_get_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource,
+			      sc_pm_clk_t clk, sc_pm_clock_rate_t *rate)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_CLOCK_RATE;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_U8(&msg, 2U) = (uint8_t)clk;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	if (rate != NULL) {
+		*rate = RPC_U32(&msg, 0U);
+	}
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_clock_enable(sc_ipc_t ipc, sc_rsrc_t resource,
+			    sc_pm_clk_t clk, sc_bool_t enable, sc_bool_t autog)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_CLOCK_ENABLE;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_U8(&msg, 2U) = (uint8_t)clk;
+	RPC_U8(&msg, 3U) = (uint8_t)enable;
+	RPC_U8(&msg, 4U) = (uint8_t)autog;
+	RPC_SIZE(&msg) = 3U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_set_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource,
+				sc_pm_clk_t clk, sc_pm_clk_parent_t parent)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CLOCK_PARENT;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_U8(&msg, 2U) = (uint8_t)clk;
+	RPC_U8(&msg, 3U) = (uint8_t)parent;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_get_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource,
+				sc_pm_clk_t clk, sc_pm_clk_parent_t *parent)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_CLOCK_PARENT;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_U8(&msg, 2U) = (uint8_t)clk;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	if (parent != NULL) {
+		*parent = RPC_U8(&msg, 0U);
+	}
+
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_reset(sc_ipc_t ipc, sc_pm_reset_type_t type)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_RESET;
+	RPC_U8(&msg, 0U) = (uint8_t)type;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_reset_reason(sc_ipc_t ipc, sc_pm_reset_reason_t *reason)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_RESET_REASON;
+	RPC_SIZE(&msg) = 1U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	if (reason != NULL) {
+		*reason = RPC_U8(&msg, 0U);
+	}
+
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_boot(sc_ipc_t ipc, sc_rm_pt_t pt,
+		    sc_rsrc_t resource_cpu, sc_faddr_t boot_addr,
+		    sc_rsrc_t resource_mu, sc_rsrc_t resource_dev)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_BOOT;
+	RPC_U32(&msg, 0U) = (uint32_t)(boot_addr >> 32U);
+	RPC_U32(&msg, 4U) = (uint32_t)boot_addr;
+	RPC_U16(&msg, 8U) = (uint16_t)resource_cpu;
+	RPC_U16(&msg, 10U) = (uint16_t)resource_mu;
+	RPC_U16(&msg, 12U) = (uint16_t)resource_dev;
+	RPC_U8(&msg, 14U) = (uint8_t)pt;
+	RPC_SIZE(&msg) = 5U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+void sc_pm_reboot(sc_ipc_t ipc, sc_pm_reset_type_t type)
+{
+	sc_rpc_msg_t msg;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REBOOT;
+	RPC_U8(&msg, 0U) = (uint8_t)type;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_TRUE);
+
+	return;
+}
+
+sc_err_t sc_pm_reboot_partition(sc_ipc_t ipc, sc_rm_pt_t pt,
+				sc_pm_reset_type_t type)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REBOOT_PARTITION;
+	RPC_U8(&msg, 0U) = (uint8_t)pt;
+	RPC_U8(&msg, 1U) = (uint8_t)type;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_cpu_start(sc_ipc_t ipc, sc_rsrc_t resource, sc_bool_t enable,
+			 sc_faddr_t address)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+	RPC_FUNC(&msg) = (uint8_t)PM_FUNC_CPU_START;
+	RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U);
+	RPC_U32(&msg, 4U) = (uint32_t)address;
+	RPC_U16(&msg, 8U) = (uint16_t)resource;
+	RPC_U8(&msg, 10U) = (uint8_t)enable;
+	RPC_SIZE(&msg) = 4U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+/**@}*/
diff --git a/plat/imx/common/sci/svc/pm/sci_pm_rpc.h b/plat/imx/common/sci/svc/pm/sci_pm_rpc.h
new file mode 100644
index 0000000..19ab6e4
--- /dev/null
+++ b/plat/imx/common/sci/svc/pm/sci_pm_rpc.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file for the PM RPC implementation.
+ *
+ * @addtogroup PM_SVC
+ * @{
+ */
+
+#ifndef SC_PM_RPC_H
+#define SC_PM_RPC_H
+
+/* Includes */
+
+/* Defines */
+
+/*!
+ * @name Defines for RPC PM function calls
+ */
+/*@{*/
+#define PM_FUNC_UNKNOWN 0	/* Unknown function */
+#define PM_FUNC_SET_SYS_POWER_MODE 19U	/* Index for pm_set_sys_power_mode() RPC call */
+#define PM_FUNC_SET_PARTITION_POWER_MODE 1U	/* Index for pm_set_partition_power_mode() RPC call */
+#define PM_FUNC_GET_SYS_POWER_MODE 2U	/* Index for pm_get_sys_power_mode() RPC call */
+#define PM_FUNC_SET_RESOURCE_POWER_MODE 3U	/* Index for pm_set_resource_power_mode() RPC call */
+#define PM_FUNC_GET_RESOURCE_POWER_MODE 4U	/* Index for pm_get_resource_power_mode() RPC call */
+#define PM_FUNC_REQ_LOW_POWER_MODE 16U	/* Index for pm_req_low_power_mode() RPC call */
+#define PM_FUNC_REQ_CPU_LOW_POWER_MODE 20U	/* Index for pm_req_cpu_low_power_mode() RPC call */
+#define PM_FUNC_SET_CPU_RESUME_ADDR 17U	/* Index for pm_set_cpu_resume_addr() RPC call */
+#define PM_FUNC_SET_CPU_RESUME 21U	/* Index for pm_set_cpu_resume() RPC call */
+#define PM_FUNC_REQ_SYS_IF_POWER_MODE 18U	/* Index for pm_req_sys_if_power_mode() RPC call */
+#define PM_FUNC_SET_CLOCK_RATE 5U	/* Index for pm_set_clock_rate() RPC call */
+#define PM_FUNC_GET_CLOCK_RATE 6U	/* Index for pm_get_clock_rate() RPC call */
+#define PM_FUNC_CLOCK_ENABLE 7U	/* Index for pm_clock_enable() RPC call */
+#define PM_FUNC_SET_CLOCK_PARENT 14U	/* Index for pm_set_clock_parent() RPC call */
+#define PM_FUNC_GET_CLOCK_PARENT 15U	/* Index for pm_get_clock_parent() RPC call */
+#define PM_FUNC_RESET 13U	/* Index for pm_reset() RPC call */
+#define PM_FUNC_RESET_REASON 10U	/* Index for pm_reset_reason() RPC call */
+#define PM_FUNC_BOOT 8U		/* Index for pm_boot() RPC call */
+#define PM_FUNC_REBOOT 9U	/* Index for pm_reboot() RPC call */
+#define PM_FUNC_REBOOT_PARTITION 12U	/* Index for pm_reboot_partition() RPC call */
+#define PM_FUNC_CPU_START 11U	/* Index for pm_cpu_start() RPC call */
+/*@}*/
+
+/* Types */
+
+/* Functions */
+
+/*!
+ * This function dispatches an incoming PM RPC request.
+ *
+ * @param[in]     caller_pt   caller partition
+ * @param[in]     msg         pointer to RPC message
+ */
+void pm_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg);
+
+/*!
+ * This function translates and dispatches an PM RPC request.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     msg         pointer to RPC message
+ */
+void pm_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg);
+
+#endif				/* SC_PM_RPC_H */
+
+/**@}*/
diff --git a/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c b/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c
new file mode 100644
index 0000000..230956c
--- /dev/null
+++ b/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c
@@ -0,0 +1,637 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * File containing client-side RPC functions for the RM service. These
+ * functions are ported to clients that communicate to the SC.
+ *
+ * @addtogroup RM_SVC
+ * @{
+ */
+
+/* Includes */
+
+#include <sci/sci_types.h>
+#include <sci/svc/rm/sci_rm_api.h>
+#include <sci/sci_rpc.h>
+#include <stdlib.h>
+#include "sci_rm_rpc.h"
+
+/* Local Defines */
+
+/* Local Types */
+
+/* Local Functions */
+
+sc_err_t sc_rm_partition_alloc(sc_ipc_t ipc, sc_rm_pt_t *pt, sc_bool_t secure,
+			       sc_bool_t isolated, sc_bool_t restricted,
+			       sc_bool_t grant, sc_bool_t coherent)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_ALLOC;
+	RPC_U8(&msg, 0U) = (uint8_t)secure;
+	RPC_U8(&msg, 1U) = (uint8_t)isolated;
+	RPC_U8(&msg, 2U) = (uint8_t)restricted;
+	RPC_U8(&msg, 3U) = (uint8_t)grant;
+	RPC_U8(&msg, 4U) = (uint8_t)coherent;
+	RPC_SIZE(&msg) = 3U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	if (pt != NULL) {
+		*pt = RPC_U8(&msg, 0U);
+	}
+
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_confidential(sc_ipc_t ipc, sc_rm_pt_t pt, sc_bool_t retro)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_CONFIDENTIAL;
+	RPC_U8(&msg, 0U) = (uint8_t)pt;
+	RPC_U8(&msg, 1U) = (uint8_t)retro;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_partition_free(sc_ipc_t ipc, sc_rm_pt_t pt)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_FREE;
+	RPC_U8(&msg, 0U) = (uint8_t)pt;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_rm_did_t sc_rm_get_did(sc_ipc_t ipc)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_DID;
+	RPC_SIZE(&msg) = 1U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_rm_did_t) result;
+}
+
+sc_err_t sc_rm_partition_static(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_did_t did)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_STATIC;
+	RPC_U8(&msg, 0U) = (uint8_t)pt;
+	RPC_U8(&msg, 1U) = (uint8_t)did;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_partition_lock(sc_ipc_t ipc, sc_rm_pt_t pt)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_LOCK;
+	RPC_U8(&msg, 0U) = (uint8_t)pt;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_get_partition(sc_ipc_t ipc, sc_rm_pt_t *pt)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_PARTITION;
+	RPC_SIZE(&msg) = 1U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	if (pt != NULL) {
+		*pt = RPC_U8(&msg, 0U);
+	}
+
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_parent(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_pt_t pt_parent)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_PARENT;
+	RPC_U8(&msg, 0U) = (uint8_t)pt;
+	RPC_U8(&msg, 1U) = (uint8_t)pt_parent;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_move_all(sc_ipc_t ipc, sc_rm_pt_t pt_src, sc_rm_pt_t pt_dst,
+			sc_bool_t move_rsrc, sc_bool_t move_pads)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MOVE_ALL;
+	RPC_U8(&msg, 0U) = (uint8_t)pt_src;
+	RPC_U8(&msg, 1U) = (uint8_t)pt_dst;
+	RPC_U8(&msg, 2U) = (uint8_t)move_rsrc;
+	RPC_U8(&msg, 3U) = (uint8_t)move_pads;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_assign_resource(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rsrc_t resource)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_ASSIGN_RESOURCE;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_U8(&msg, 2U) = (uint8_t)pt;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_resource_movable(sc_ipc_t ipc, sc_rsrc_t resource_fst,
+				    sc_rsrc_t resource_lst, sc_bool_t movable)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_RESOURCE_MOVABLE;
+	RPC_U16(&msg, 0U) = (uint16_t)resource_fst;
+	RPC_U16(&msg, 2U) = (uint16_t)resource_lst;
+	RPC_U8(&msg, 4U) = (uint8_t)movable;
+	RPC_SIZE(&msg) = 3U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_subsys_rsrc_movable(sc_ipc_t ipc, sc_rsrc_t resource,
+				       sc_bool_t movable)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_SUBSYS_RSRC_MOVABLE;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_U8(&msg, 2U) = (uint8_t)movable;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_master_attributes(sc_ipc_t ipc, sc_rsrc_t resource,
+				     sc_rm_spa_t sa, sc_rm_spa_t pa,
+				     sc_bool_t smmu_bypass)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_MASTER_ATTRIBUTES;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_U8(&msg, 2U) = (uint8_t)sa;
+	RPC_U8(&msg, 3U) = (uint8_t)pa;
+	RPC_U8(&msg, 4U) = (uint8_t)smmu_bypass;
+	RPC_SIZE(&msg) = 3U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_master_sid(sc_ipc_t ipc, sc_rsrc_t resource, sc_rm_sid_t sid)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_MASTER_SID;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_U16(&msg, 2U) = (uint16_t)sid;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_peripheral_permissions(sc_ipc_t ipc, sc_rsrc_t resource,
+					  sc_rm_pt_t pt, sc_rm_perm_t perm)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_PERIPHERAL_PERMISSIONS;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_U8(&msg, 2U) = (uint8_t)pt;
+	RPC_U8(&msg, 3U) = (uint8_t)perm;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_bool_t sc_rm_is_resource_owned(sc_ipc_t ipc, sc_rsrc_t resource)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_RESOURCE_OWNED;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_bool_t)result;
+}
+
+sc_bool_t sc_rm_is_resource_master(sc_ipc_t ipc, sc_rsrc_t resource)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_RESOURCE_MASTER;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_bool_t)result;
+}
+
+sc_bool_t sc_rm_is_resource_peripheral(sc_ipc_t ipc, sc_rsrc_t resource)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_RESOURCE_PERIPHERAL;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_bool_t)result;
+}
+
+sc_err_t sc_rm_get_resource_info(sc_ipc_t ipc, sc_rsrc_t resource,
+				 sc_rm_sid_t *sid)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_RESOURCE_INFO;
+	RPC_U16(&msg, 0U) = (uint16_t)resource;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	if (sid != NULL) {
+		*sid = RPC_U16(&msg, 0U);
+	}
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_memreg_alloc(sc_ipc_t ipc, sc_rm_mr_t *mr,
+			    sc_faddr_t addr_start, sc_faddr_t addr_end)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MEMREG_ALLOC;
+	RPC_U32(&msg, 0U) = (uint32_t)(addr_start >> 32U);
+	RPC_U32(&msg, 4U) = (uint32_t)addr_start;
+	RPC_U32(&msg, 8U) = (uint32_t)(addr_end >> 32U);
+	RPC_U32(&msg, 12U) = (uint32_t)addr_end;
+	RPC_SIZE(&msg) = 5U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	if (mr != NULL) {
+		*mr = RPC_U8(&msg, 0U);
+	}
+
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_memreg_split(sc_ipc_t ipc, sc_rm_mr_t mr,
+			    sc_rm_mr_t *mr_ret, sc_faddr_t addr_start,
+			    sc_faddr_t addr_end)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MEMREG_SPLIT;
+	RPC_U32(&msg, 0U) = (uint32_t)(addr_start >> 32U);
+	RPC_U32(&msg, 4U) = (uint32_t)addr_start;
+	RPC_U32(&msg, 8U) = (uint32_t)(addr_end >> 32U);
+	RPC_U32(&msg, 12U) = (uint32_t)addr_end;
+	RPC_U8(&msg, 16U) = (uint8_t)mr;
+	RPC_SIZE(&msg) = 6U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	if (mr_ret != NULL) {
+		*mr_ret = RPC_U8(&msg, 0U);
+	}
+
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_memreg_free(sc_ipc_t ipc, sc_rm_mr_t mr)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MEMREG_FREE;
+	RPC_U8(&msg, 0U) = (uint8_t)mr;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_find_memreg(sc_ipc_t ipc, sc_rm_mr_t *mr,
+			   sc_faddr_t addr_start, sc_faddr_t addr_end)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_FIND_MEMREG;
+	RPC_U32(&msg, 0U) = (uint32_t)(addr_start >> 32U);
+	RPC_U32(&msg, 4U) = (uint32_t)addr_start;
+	RPC_U32(&msg, 8U) = (uint32_t)(addr_end >> 32U);
+	RPC_U32(&msg, 12U) = (uint32_t)addr_end;
+	RPC_SIZE(&msg) = 5U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	if (mr != NULL) {
+		*mr = RPC_U8(&msg, 0U);
+	}
+
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_assign_memreg(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_mr_t mr)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_ASSIGN_MEMREG;
+	RPC_U8(&msg, 0U) = (uint8_t)pt;
+	RPC_U8(&msg, 1U) = (uint8_t)mr;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_memreg_permissions(sc_ipc_t ipc, sc_rm_mr_t mr,
+				      sc_rm_pt_t pt, sc_rm_perm_t perm)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_MEMREG_PERMISSIONS;
+	RPC_U8(&msg, 0U) = (uint8_t)mr;
+	RPC_U8(&msg, 1U) = (uint8_t)pt;
+	RPC_U8(&msg, 2U) = (uint8_t)perm;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_bool_t sc_rm_is_memreg_owned(sc_ipc_t ipc, sc_rm_mr_t mr)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_MEMREG_OWNED;
+	RPC_U8(&msg, 0U) = (uint8_t)mr;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_bool_t)result;
+}
+
+sc_err_t sc_rm_get_memreg_info(sc_ipc_t ipc, sc_rm_mr_t mr,
+			       sc_faddr_t *addr_start, sc_faddr_t *addr_end)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_MEMREG_INFO;
+	RPC_U8(&msg, 0U) = (uint8_t)mr;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	if (addr_start != NULL) {
+		*addr_start =
+		    ((uint64_t) RPC_U32(&msg, 0U) << 32U) | RPC_U32(&msg, 4U);
+	}
+
+	if (addr_end != NULL) {
+		*addr_end =
+		    ((uint64_t) RPC_U32(&msg, 8U) << 32U) | RPC_U32(&msg, 12U);
+	}
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_assign_pad(sc_ipc_t ipc, sc_rm_pt_t pt, sc_pad_t pad)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_ASSIGN_PAD;
+	RPC_U16(&msg, 0U) = (uint16_t)pad;
+	RPC_U8(&msg, 2U) = (uint8_t)pt;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_pad_movable(sc_ipc_t ipc, sc_pad_t pad_fst,
+			       sc_pad_t pad_lst, sc_bool_t movable)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_PAD_MOVABLE;
+	RPC_U16(&msg, 0U) = (uint16_t)pad_fst;
+	RPC_U16(&msg, 2U) = (uint16_t)pad_lst;
+	RPC_U8(&msg, 4U) = (uint8_t)movable;
+	RPC_SIZE(&msg) = 3U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_err_t)result;
+}
+
+sc_bool_t sc_rm_is_pad_owned(sc_ipc_t ipc, sc_pad_t pad)
+{
+	sc_rpc_msg_t msg;
+	uint8_t result;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_PAD_OWNED;
+	RPC_U8(&msg, 0U) = (uint8_t)pad;
+	RPC_SIZE(&msg) = 2U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	result = RPC_R8(&msg);
+	return (sc_bool_t)result;
+}
+
+void sc_rm_dump(sc_ipc_t ipc)
+{
+	sc_rpc_msg_t msg;
+
+	RPC_VER(&msg) = SC_RPC_VERSION;
+	RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+	RPC_FUNC(&msg) = (uint8_t)RM_FUNC_DUMP;
+	RPC_SIZE(&msg) = 1U;
+
+	sc_call_rpc(ipc, &msg, SC_FALSE);
+
+	return;
+}
+
+/**@}*/
diff --git a/plat/imx/common/sci/svc/rm/sci_rm_rpc.h b/plat/imx/common/sci/svc/rm/sci_rm_rpc.h
new file mode 100644
index 0000000..e3de450
--- /dev/null
+++ b/plat/imx/common/sci/svc/rm/sci_rm_rpc.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file for the RM RPC implementation.
+ *
+ * @addtogroup RM_SVC
+ * @{
+ */
+
+#ifndef SC_RM_RPC_H
+#define SC_RM_RPC_H
+
+/* Includes */
+
+/* Defines */
+
+/*!
+ * @name Defines for RPC RM function calls
+ */
+/*@{*/
+#define RM_FUNC_UNKNOWN 0	/* Unknown function */
+#define RM_FUNC_PARTITION_ALLOC 1U	/* Index for rm_partition_alloc() RPC call */
+#define RM_FUNC_SET_CONFIDENTIAL 31U	/* Index for rm_set_confidential() RPC call */
+#define RM_FUNC_PARTITION_FREE 2U	/* Index for rm_partition_free() RPC call */
+#define RM_FUNC_GET_DID 26U	/* Index for rm_get_did() RPC call */
+#define RM_FUNC_PARTITION_STATIC 3U	/* Index for rm_partition_static() RPC call */
+#define RM_FUNC_PARTITION_LOCK 4U	/* Index for rm_partition_lock() RPC call */
+#define RM_FUNC_GET_PARTITION 5U	/* Index for rm_get_partition() RPC call */
+#define RM_FUNC_SET_PARENT 6U	/* Index for rm_set_parent() RPC call */
+#define RM_FUNC_MOVE_ALL 7U	/* Index for rm_move_all() RPC call */
+#define RM_FUNC_ASSIGN_RESOURCE 8U	/* Index for rm_assign_resource() RPC call */
+#define RM_FUNC_SET_RESOURCE_MOVABLE 9U	/* Index for rm_set_resource_movable() RPC call */
+#define RM_FUNC_SET_SUBSYS_RSRC_MOVABLE 28U	/* Index for rm_set_subsys_rsrc_movable() RPC call */
+#define RM_FUNC_SET_MASTER_ATTRIBUTES 10U	/* Index for rm_set_master_attributes() RPC call */
+#define RM_FUNC_SET_MASTER_SID 11U	/* Index for rm_set_master_sid() RPC call */
+#define RM_FUNC_SET_PERIPHERAL_PERMISSIONS 12U	/* Index for rm_set_peripheral_permissions() RPC call */
+#define RM_FUNC_IS_RESOURCE_OWNED 13U	/* Index for rm_is_resource_owned() RPC call */
+#define RM_FUNC_IS_RESOURCE_MASTER 14U	/* Index for rm_is_resource_master() RPC call */
+#define RM_FUNC_IS_RESOURCE_PERIPHERAL 15U	/* Index for rm_is_resource_peripheral() RPC call */
+#define RM_FUNC_GET_RESOURCE_INFO 16U	/* Index for rm_get_resource_info() RPC call */
+#define RM_FUNC_MEMREG_ALLOC 17U	/* Index for rm_memreg_alloc() RPC call */
+#define RM_FUNC_MEMREG_SPLIT 29U	/* Index for rm_memreg_split() RPC call */
+#define RM_FUNC_MEMREG_FREE 18U	/* Index for rm_memreg_free() RPC call */
+#define RM_FUNC_FIND_MEMREG 30U	/* Index for rm_find_memreg() RPC call */
+#define RM_FUNC_ASSIGN_MEMREG 19U	/* Index for rm_assign_memreg() RPC call */
+#define RM_FUNC_SET_MEMREG_PERMISSIONS 20U	/* Index for rm_set_memreg_permissions() RPC call */
+#define RM_FUNC_IS_MEMREG_OWNED 21U	/* Index for rm_is_memreg_owned() RPC call */
+#define RM_FUNC_GET_MEMREG_INFO 22U	/* Index for rm_get_memreg_info() RPC call */
+#define RM_FUNC_ASSIGN_PAD 23U	/* Index for rm_assign_pad() RPC call */
+#define RM_FUNC_SET_PAD_MOVABLE 24U	/* Index for rm_set_pad_movable() RPC call */
+#define RM_FUNC_IS_PAD_OWNED 25U	/* Index for rm_is_pad_owned() RPC call */
+#define RM_FUNC_DUMP 27U	/* Index for rm_dump() RPC call */
+/*@}*/
+
+/* Types */
+
+/* Functions */
+
+/*!
+ * This function dispatches an incoming RM RPC request.
+ *
+ * @param[in]     caller_pt   caller partition
+ * @param[in]     msg         pointer to RPC message
+ */
+void rm_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg);
+
+/*!
+ * This function translates and dispatches an RM RPC request.
+ *
+ * @param[in]     ipc         IPC handle
+ * @param[in]     msg         pointer to RPC message
+ */
+void rm_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg);
+
+#endif				/* SC_RM_RPC_H */
+
+/**@}*/
diff --git a/plat/imx/imx8qm/imx8qm_bl31_setup.c b/plat/imx/imx8qm/imx8qm_bl31_setup.c
new file mode 100644
index 0000000..6cfdaf8
--- /dev/null
+++ b/plat/imx/imx8qm/imx8qm_bl31_setup.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 2015-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 <cci.h>
+#include <console.h>
+#include <context.h>
+#include <context_mgmt.h>
+#include <debug.h>
+#include <imx8qm_pads.h>
+#include <imx8_iomux.h>
+#include <imx8_lpuart.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <plat_imx8.h>
+#include <sci/sci.h>
+#include <sec_rsrc.h>
+#include <stdbool.h>
+#include <xlat_tables.h>
+
+IMPORT_SYM(unsigned long, __COHERENT_RAM_START__, BL31_COHERENT_RAM_START);
+IMPORT_SYM(unsigned long, __COHERENT_RAM_END__, BL31_COHERENT_RAM_END);
+IMPORT_SYM(unsigned long, __RO_START__, BL31_RO_START);
+IMPORT_SYM(unsigned long, __RO_END__, BL31_RO_END);
+IMPORT_SYM(unsigned long, __RW_START__, BL31_RW_START);
+IMPORT_SYM(unsigned long, __RW_END__, BL31_RW_END);
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+#define UART_PAD_CTRL	(PADRING_IFMUX_EN_MASK | PADRING_GP_EN_MASK | \
+			(SC_PAD_CONFIG_OUT_IN << PADRING_CONFIG_SHIFT) | \
+			(SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \
+			(SC_PAD_28FDSOI_DSE_DV_LOW << PADRING_DSE_SHIFT) | \
+			(SC_PAD_28FDSOI_PS_PD << PADRING_PULL_SHIFT))
+
+const static int imx8qm_cci_map[] = {
+	CLUSTER0_CCI_SLVAE_IFACE,
+	CLUSTER1_CCI_SLVAE_IFACE
+};
+
+static const mmap_region_t imx_mmap[] = {
+	MAP_REGION_FLAT(IMX_BOOT_UART_BASE, IMX_BOOT_UART_SIZE, MT_DEVICE | MT_RW),
+	MAP_REGION_FLAT(SC_IPC_BASE, SC_IPC_SIZE, MT_DEVICE | MT_RW),
+	MAP_REGION_FLAT(PLAT_GICD_BASE, PLAT_GICD_SIZE, MT_DEVICE | MT_RW),
+	MAP_REGION_FLAT(PLAT_GICR_BASE, PLAT_GICR_SIZE, MT_DEVICE | MT_RW),
+	MAP_REGION_FLAT(PLAT_CCI_BASE, PLAT_CCI_SIZE, MT_DEVICE | MT_RW),
+	{0}
+};
+
+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;
+}
+
+#if DEBUG_CONSOLE_A53
+static void lpuart32_serial_setbrg(unsigned int base, int baudrate)
+{
+	unsigned int sbr, osr, baud_diff, tmp_osr, tmp_sbr;
+	unsigned int diff1, diff2, tmp, rate;
+
+	if (baudrate == 0)
+		panic();
+
+	sc_pm_get_clock_rate(ipc_handle, SC_R_UART_0, 2, &rate);
+
+	baud_diff = baudrate;
+	osr = 0;
+	sbr = 0;
+	for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) {
+		tmp_sbr = (rate / (baudrate * tmp_osr));
+		if (tmp_sbr == 0)
+			tmp_sbr = 1;
+
+		/* calculate difference in actual baud w/ current values */
+		diff1 = rate / (tmp_osr * tmp_sbr) - baudrate;
+		diff2 = rate / (tmp_osr * (tmp_sbr + 1));
+
+		/* select best values between sbr and sbr+1 */
+		if (diff1 > (baudrate - diff2)) {
+			diff1 = baudrate - diff2;
+			tmp_sbr++;
+		}
+
+		if (diff1 <= baud_diff) {
+			baud_diff = diff1;
+			osr = tmp_osr;
+			sbr = tmp_sbr;
+		}
+	}
+
+	tmp = mmio_read_32(IMX_BOOT_UART_BASE + BAUD);
+
+	if ((osr > 3) && (osr < 8))
+		tmp |= LPUART_BAUD_BOTHEDGE_MASK;
+
+	tmp &= ~LPUART_BAUD_OSR_MASK;
+	tmp |= LPUART_BAUD_OSR(osr - 1);
+	tmp &= ~LPUART_BAUD_SBR_MASK;
+	tmp |= LPUART_BAUD_SBR(sbr);
+
+	/* explicitly disable 10 bit mode & set 1 stop bit */
+	tmp &= ~(LPUART_BAUD_M10_MASK | LPUART_BAUD_SBNS_MASK);
+
+	mmio_write_32(IMX_BOOT_UART_BASE + BAUD, tmp);
+}
+
+static int lpuart32_serial_init(unsigned int base)
+{
+	unsigned int tmp;
+
+	/* disable TX & RX before enabling clocks */
+	tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL);
+	tmp &= ~(CTRL_TE | CTRL_RE);
+	mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp);
+
+	mmio_write_32(IMX_BOOT_UART_BASE + MODIR, 0);
+	mmio_write_32(IMX_BOOT_UART_BASE + FIFO, ~(FIFO_TXFE | FIFO_RXFE));
+
+	mmio_write_32(IMX_BOOT_UART_BASE + MATCH, 0);
+
+	/* provide data bits, parity, stop bit, etc */
+	lpuart32_serial_setbrg(base, IMX_BOOT_UART_BAUDRATE);
+
+	/* eight data bits no parity bit */
+	tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL);
+	tmp &= ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK);
+	mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp);
+
+	mmio_write_32(IMX_BOOT_UART_BASE + CTRL, CTRL_RE | CTRL_TE);
+
+	mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55);
+	mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55);
+	mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x0A);
+
+	return 0;
+}
+#endif
+
+void mx8_partition_resources(void)
+{
+	sc_rm_pt_t secure_part, os_part;
+	sc_rm_mr_t mr, mr_record = 64;
+	sc_faddr_t start, end;
+	bool owned, owned2;
+	sc_err_t err;
+	int i;
+
+	err = sc_rm_get_partition(ipc_handle, &secure_part);
+
+	err = sc_rm_partition_alloc(ipc_handle, &os_part, false, false,
+		false, false, false);
+
+	err = sc_rm_set_parent(ipc_handle, os_part, secure_part);
+
+	/* set secure resources to NOT-movable */
+	for (i = 0; i < ARRAY_SIZE(secure_rsrcs); i++) {
+		err = sc_rm_set_resource_movable(ipc_handle, secure_rsrcs[i],
+			secure_rsrcs[i], false);
+		if (err)
+			ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n",
+				secure_rsrcs[i], err);
+	}
+
+	owned = sc_rm_is_resource_owned(ipc_handle, SC_R_M4_0_PID0);
+	if (owned) {
+		err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_0_PID0,
+				SC_R_M4_0_PID0, false);
+		if (err)
+			ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n",
+				SC_R_M4_0_PID0, err);
+	}
+
+	owned2 = sc_rm_is_resource_owned(ipc_handle, SC_R_M4_1_PID0);
+	if (owned2) {
+		err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_1_PID0,
+				SC_R_M4_1_PID0, false);
+		if (err)
+			ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n",
+				SC_R_M4_1_PID0, err);
+	}
+	/* move all movable resources and pins to non-secure partition */
+	err = sc_rm_move_all(ipc_handle, secure_part, os_part, true, true);
+	if (err)
+		ERROR("sc_rm_move_all: %u\n", err);
+
+	/* iterate through peripherals to give NS OS part access */
+	for (i = 0; i < ARRAY_SIZE(ns_access_allowed); i++) {
+		err = sc_rm_set_peripheral_permissions(ipc_handle, ns_access_allowed[i],
+			os_part, SC_RM_PERM_FULL);
+		if (err)
+			ERROR("sc_rm_set_peripheral_permissions: rsrc %u, \
+				ret %u\n", ns_access_allowed[i], err);
+	}
+
+	if (owned) {
+		err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_0_PID0,
+				SC_R_M4_0_PID0, true);
+		if (err)
+			ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n",
+				SC_R_M4_0_PID0, err);
+		err = sc_rm_assign_resource(ipc_handle, os_part, SC_R_M4_0_PID0);
+		if (err)
+			ERROR("sc_rm_assign_resource: rsrc %u, ret %u\n",
+				SC_R_M4_0_PID0, err);
+	}
+	if (owned2) {
+		err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_1_PID0,
+				SC_R_M4_1_PID0, true);
+		if (err)
+			ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n",
+				SC_R_M4_1_PID0, err);
+		err = sc_rm_assign_resource(ipc_handle, os_part, SC_R_M4_1_PID0);
+		if (err)
+			ERROR("sc_rm_assign_resource: rsrc %u, ret %u\n",
+				SC_R_M4_1_PID0, err);
+	}
+
+	/*
+	 * sc_rm_set_peripheral_permissions
+	 * sc_rm_set_memreg_permissions
+	 * sc_rm_set_pin_movable
+	 */
+
+	for (mr = 0; mr < 64; mr++) {
+		owned = sc_rm_is_memreg_owned(ipc_handle, mr);
+		if (owned) {
+			err = sc_rm_get_memreg_info(ipc_handle, mr, &start, &end);
+			if (err)
+				ERROR("Memreg get info failed, %u\n", mr);
+			NOTICE("Memreg %u 0x%llx -- 0x%llx\n", mr, start, end);
+			if (BL31_BASE >= start && (BL31_LIMIT - 1) <= end) {
+				mr_record = mr; /* Record the mr for ATF running */
+			} else {
+				err = sc_rm_assign_memreg(ipc_handle, os_part, mr);
+				if (err)
+					ERROR("Memreg assign failed, 0x%llx -- 0x%llx, \
+						err %d\n", start, end, err);
+			}
+		}
+	}
+
+	if (mr_record != 64) {
+		err = sc_rm_get_memreg_info(ipc_handle, mr_record, &start, &end);
+		if (err)
+			ERROR("Memreg get info failed, %u\n", mr_record);
+		if ((BL31_LIMIT - 1) < end) {
+			err = sc_rm_memreg_alloc(ipc_handle, &mr, BL31_LIMIT, end);
+			if (err)
+				ERROR("sc_rm_memreg_alloc failed, 0x%llx -- 0x%llx\n",
+					(sc_faddr_t)BL31_LIMIT, end);
+			err = sc_rm_assign_memreg(ipc_handle, os_part, mr);
+			if (err)
+				ERROR("Memreg assign failed, 0x%llx -- 0x%llx\n",
+					(sc_faddr_t)BL31_LIMIT, end);
+		}
+
+		if (start < (BL31_BASE - 1)) {
+			err = sc_rm_memreg_alloc(ipc_handle, &mr, start, BL31_BASE - 1);
+			if (err)
+				ERROR("sc_rm_memreg_alloc failed, 0x%llx -- 0x%llx\n",
+					start, (sc_faddr_t)BL31_BASE - 1);
+			err = sc_rm_assign_memreg(ipc_handle, os_part, mr);
+				if (err)
+					ERROR("Memreg assign failed, 0x%llx -- 0x%llx\n",
+						start, (sc_faddr_t)BL31_BASE - 1);
+		}
+	}
+
+	if (err)
+		NOTICE("Partitioning Failed\n");
+	else
+		NOTICE("Non-secure Partitioning Succeeded\n");
+
+}
+
+void bl31_early_platform_setup(bl31_params_t *from_bl2,
+				void *plat_params_from_bl2)
+{
+#if DEBUG_CONSOLE
+	static console_lpuart_t console;
+#endif
+	if (sc_ipc_open(&ipc_handle, SC_IPC_BASE) != SC_ERR_NONE)
+		panic();
+
+#if DEBUG_CONSOLE_A53
+	sc_pm_set_resource_power_mode(ipc_handle, SC_R_UART_0, SC_PM_PW_MODE_ON);
+	sc_pm_clock_rate_t rate = 80000000;
+	sc_pm_set_clock_rate(ipc_handle, SC_R_UART_0, 2, &rate);
+	sc_pm_clock_enable(ipc_handle, SC_R_UART_0, 2, true, false);
+
+	/* configure UART pads */
+	sc_pad_set(ipc_handle, SC_P_UART0_RX, UART_PAD_CTRL);
+	sc_pad_set(ipc_handle, SC_P_UART0_TX, UART_PAD_CTRL);
+	sc_pad_set(ipc_handle, SC_P_UART0_RTS_B, UART_PAD_CTRL);
+	sc_pad_set(ipc_handle, SC_P_UART0_CTS_B, UART_PAD_CTRL);
+	lpuart32_serial_init(IMX_BOOT_UART_BASE);
+#endif
+
+#if DEBUG_CONSOLE
+	console_lpuart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+		     IMX_CONSOLE_BAUDRATE, &console);
+#endif
+
+	/* turn on MU1 for non-secure OS/Hypervisor */
+	sc_pm_set_resource_power_mode(ipc_handle, SC_R_MU_1A, SC_PM_PW_MODE_ON);
+
+	/*
+	 * create new partition for non-secure OS/Hypervisor
+	 * uses global structs defined in sec_rsrc.h
+	 */
+	mx8_partition_resources();
+
+	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);
+
+	/* init the first cluster's cci slave interface */
+	cci_init(PLAT_CCI_BASE, imx8qm_cci_map, PLATFORM_CLUSTER_COUNT);
+	cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+void bl31_plat_arch_setup(void)
+{
+	unsigned long ro_start = BL31_RO_START;
+	unsigned long ro_size = BL31_RO_END - BL31_RO_START;
+	unsigned long rw_start = BL31_RW_START;
+	unsigned long rw_size = BL31_RW_END - BL31_RW_START;
+#if USE_COHERENT_MEM
+	unsigned long coh_start = BL31_COHERENT_RAM_START;
+	unsigned long coh_size = BL31_COHERENT_RAM_END - BL31_COHERENT_RAM_START;
+#endif
+
+	mmap_add_region(ro_start, ro_start, ro_size,
+		MT_RO | MT_MEMORY | MT_SECURE);
+	mmap_add_region(rw_start, rw_start, rw_size,
+		MT_RW | MT_MEMORY | MT_SECURE);
+	mmap_add(imx_mmap);
+
+#if USE_COHERENT_MEM
+	mmap_add_region(coh_start, coh_start, coh_size,
+			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)
+{
+	plat_gic_driver_init();
+	plat_gic_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/imx8qm/imx8qm_psci.c b/plat/imx/imx8qm/imx8qm_psci.c
new file mode 100644
index 0000000..b9b794b
--- /dev/null
+++ b/plat/imx/imx8qm/imx8qm_psci.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <cci.h>
+#include <debug.h>
+#include <gicv3.h>
+#include <mmio.h>
+#include <plat_imx8.h>
+#include <psci.h>
+#include <sci/sci.h>
+#include <stdbool.h>
+
+const static int ap_core_index[PLATFORM_CORE_COUNT] = {
+	SC_R_A53_0, SC_R_A53_1, SC_R_A53_2,
+	SC_R_A53_3, SC_R_A72_0, SC_R_A72_1,
+};
+
+/* need to enable USE_COHERENT_MEM to avoid coherence issue */
+#if USE_COHERENT_MEM
+static unsigned int a53_cpu_on_number __section("tzfw_coherent_mem");
+static unsigned int a72_cpu_on_number __section("tzfw_coherent_mem");
+#endif
+
+int imx_pwr_domain_on(u_register_t mpidr)
+{
+	int ret = PSCI_E_SUCCESS;
+	unsigned int cluster_id, cpu_id;
+
+	cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+	cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+	tf_printf("imx_pwr_domain_on cluster_id %d, cpu_id %d\n", cluster_id, cpu_id);
+
+	if (cluster_id == 0) {
+		if (a53_cpu_on_number == 0)
+			sc_pm_set_resource_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_ON);
+
+		if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id],
+			SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
+			ERROR("cluster0 core %d power on failed!\n", cpu_id);
+			ret = PSCI_E_INTERN_FAIL;
+		}
+
+		if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id],
+			true, BL31_BASE) != SC_ERR_NONE) {
+			ERROR("boot cluster0 core %d failed!\n", cpu_id);
+			ret = PSCI_E_INTERN_FAIL;
+		}
+	} else {
+		if (a72_cpu_on_number == 0)
+			sc_pm_set_resource_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
+
+		if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id + 4],
+			SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
+			ERROR(" cluster1 core %d power on failed!\n", cpu_id);
+			ret = PSCI_E_INTERN_FAIL;
+		}
+
+		if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id + 4],
+			true, BL31_BASE) != SC_ERR_NONE) {
+			ERROR("boot cluster1 core %d failed!\n", cpu_id);
+			ret = PSCI_E_INTERN_FAIL;
+		}
+	}
+
+	return ret;
+}
+
+void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	uint64_t mpidr = read_mpidr_el1();
+	unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+
+	if (cluster_id == 0 && a53_cpu_on_number++ == 0)
+		cci_enable_snoop_dvm_reqs(0);
+	if (cluster_id == 1 && a72_cpu_on_number++ == 0)
+		cci_enable_snoop_dvm_reqs(1);
+
+	plat_gic_pcpu_init();
+	plat_gic_cpuif_enable();
+}
+
+int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
+{
+	return PSCI_E_SUCCESS;
+}
+
+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,
+	.validate_ns_entrypoint = imx_validate_ns_entrypoint,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	uint64_t mpidr = read_mpidr_el1();
+	unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+
+	imx_mailbox_init(sec_entrypoint);
+	*psci_ops = &imx_plat_psci_ops;
+
+	if (cluster_id == 0)
+		a53_cpu_on_number++;
+	else
+		a72_cpu_on_number++;
+
+	return 0;
+}
diff --git a/plat/imx/imx8qm/include/platform_def.h b/plat/imx/imx8qm/include/platform_def.h
new file mode 100644
index 0000000..51c2e1e
--- /dev/null
+++ b/plat/imx/imx8qm/include/platform_def.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015-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		0X400
+#define CACHE_WRITEBACK_GRANULE		64
+
+#define PLAT_PRIMARY_CPU		0x0
+#define PLATFORM_MAX_CPU_PER_CLUSTER	4
+#define PLATFORM_CLUSTER_COUNT		2
+#define PLATFORM_CLUSTER0_CORE_COUNT	4
+#define PLATFORM_CLUSTER1_CORE_COUNT	2
+#define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER0_CORE_COUNT + \
+					 PLATFORM_CLUSTER1_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			0x80000000
+#define BL31_LIMIT			0x80020000
+
+#define PLAT_GICD_BASE			0x51a00000
+#define PLAT_GICD_SIZE			0x10000
+#define PLAT_GICR_BASE			0x51b00000
+#define PLAT_GICR_SIZE			0xc0000
+#define PLAT_CCI_BASE			0x52090000
+#define PLAT_CCI_SIZE			0x10000
+#define CLUSTER0_CCI_SLVAE_IFACE	3
+#define CLUSTER1_CCI_SLVAE_IFACE	4
+#define IMX_BOOT_UART_BASE		0x5a060000
+#define IMX_BOOT_UART_SIZE		0x1000
+#define IMX_BOOT_UART_BAUDRATE		115200
+#define IMX_BOOT_UART_CLK_IN_HZ		24000000
+#define PLAT_CRASH_UART_BASE		IMX_BOOT_UART_BASE
+#define PLAT__CRASH_UART_CLK_IN_HZ	24000000
+#define IMX_CONSOLE_BAUDRATE		115200
+#define SC_IPC_BASE			0x5d1b0000
+#define SC_IPC_SIZE			0x10000
+
+#define COUNTER_FREQUENCY		8000000 /* 8MHz */
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET		0x80020000
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ull << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ull << 32)
+
+#define MAX_XLAT_TABLES			8
+#define MAX_MMAP_REGIONS		12
+
+#define DEBUG_CONSOLE			0
+#define DEBUG_CONSOLE_A53		0
+#define PLAT_IMX8QM			1
diff --git a/plat/imx/imx8qm/include/sec_rsrc.h b/plat/imx/imx8qm/include/sec_rsrc.h
new file mode 100644
index 0000000..a623cd3
--- /dev/null
+++ b/plat/imx/imx8qm/include/sec_rsrc.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* resources that are going to stay in secure partition */
+sc_rsrc_t secure_rsrcs[] = {
+	SC_R_MU_0A,
+	SC_R_A53,
+	SC_R_A53_0,
+	SC_R_A53_1,
+	SC_R_A53_2,
+	SC_R_A53_3,
+	SC_R_A72,
+	SC_R_A72_0,
+	SC_R_A72_1,
+	SC_R_GIC,
+	SC_R_GIC_SMMU,
+	SC_R_CCI,
+	SC_R_SYSTEM,
+	SC_R_IRQSTR_SCU2
+};
+
+/* resources that have register access for non-secure domain */
+sc_rsrc_t ns_access_allowed[] = {
+	SC_R_GIC,
+	SC_R_GIC_SMMU,
+	SC_R_CCI
+};
diff --git a/plat/imx/imx8qm/platform.mk b/plat/imx/imx8qm/platform.mk
new file mode 100644
index 0000000..c295e14
--- /dev/null
+++ b/plat/imx/imx8qm/platform.mk
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES		:=	-Iplat/imx/imx8qm/include		\
+				-Iplat/imx/common/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/lpuart_console.S	\
+				plat/imx/common/imx8_helpers.S		\
+				plat/imx/imx8qm/imx8qm_bl31_setup.c	\
+				plat/imx/imx8qm/imx8qm_psci.c		\
+				plat/imx/common/imx8_topology.c		\
+				lib/xlat_tables/aarch64/xlat_tables.c		\
+				lib/xlat_tables/xlat_tables_common.c		\
+				lib/cpus/aarch64/cortex_a53.S			\
+				lib/cpus/aarch64/cortex_a72.S			\
+				drivers/console/aarch64/console.S		\
+				drivers/arm/cci/cci.c				\
+				${IMX_GIC_SOURCES}				\
+
+include plat/imx/common/sci/sci_api.mk
+
+ENABLE_PLAT_COMPAT	:=	0
+USE_COHERENT_MEM	:=	1
+RESET_TO_BL31		:=	1
+ARM_GIC_ARCH		:=	3
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+MULTI_CONSOLE_API	:=	1
+ERRATA_A72_859971	:=	1
diff --git a/plat/imx/imx8qx/imx8qx_bl31_setup.c b/plat/imx/imx8qx/imx8qx_bl31_setup.c
new file mode 100644
index 0000000..8dac943
--- /dev/null
+++ b/plat/imx/imx8qx/imx8qx_bl31_setup.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2015-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 <cci.h>
+#include <console.h>
+#include <context.h>
+#include <context_mgmt.h>
+#include <debug.h>
+#include <imx8qx_pads.h>
+#include <imx8_iomux.h>
+#include <imx8_lpuart.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <plat_imx8.h>
+#include <sci/sci.h>
+#include <sec_rsrc.h>
+#include <stdbool.h>
+#include <xlat_tables.h>
+
+IMPORT_SYM(unsigned long, __COHERENT_RAM_START__, BL31_COHERENT_RAM_START);
+IMPORT_SYM(unsigned long, __COHERENT_RAM_END__, BL31_COHERENT_RAM_END);
+IMPORT_SYM(unsigned long, __RO_START__, BL31_RO_START);
+IMPORT_SYM(unsigned long, __RO_END__, BL31_RO_END);
+IMPORT_SYM(unsigned long, __RW_START__, BL31_RW_START);
+IMPORT_SYM(unsigned long, __RW_END__, BL31_RW_END);
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+#define UART_PAD_CTRL	(PADRING_IFMUX_EN_MASK | PADRING_GP_EN_MASK | \
+			(SC_PAD_CONFIG_OUT_IN << PADRING_CONFIG_SHIFT) | \
+			(SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \
+			(SC_PAD_28FDSOI_DSE_DV_LOW << PADRING_DSE_SHIFT) | \
+			(SC_PAD_28FDSOI_PS_PD << PADRING_PULL_SHIFT))
+
+static const mmap_region_t imx_mmap[] = {
+	MAP_REGION_FLAT(IMX_BOOT_UART_BASE, IMX_BOOT_UART_SIZE, MT_DEVICE | MT_RW),
+	MAP_REGION_FLAT(SC_IPC_BASE, SC_IPC_SIZE, MT_DEVICE | MT_RW),
+	MAP_REGION_FLAT(PLAT_GICD_BASE, PLAT_GICD_SIZE, MT_DEVICE | MT_RW),
+	MAP_REGION_FLAT(PLAT_GICR_BASE, PLAT_GICR_SIZE, MT_DEVICE | MT_RW),
+	{0}
+};
+
+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;
+}
+
+#if DEBUG_CONSOLE_A35
+static void lpuart32_serial_setbrg(unsigned int base, int baudrate)
+{
+	unsigned int sbr, osr, baud_diff, tmp_osr, tmp_sbr;
+	unsigned int diff1, diff2, tmp, rate;
+
+	if (baudrate == 0)
+		panic();
+
+	sc_pm_get_clock_rate(ipc_handle, SC_R_UART_0, 2, &rate);
+
+	baud_diff = baudrate;
+	osr = 0;
+	sbr = 0;
+	for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) {
+		tmp_sbr = (rate / (baudrate * tmp_osr));
+		if (tmp_sbr == 0)
+			tmp_sbr = 1;
+
+		/* calculate difference in actual baud w/ current values */
+		diff1 = rate / (tmp_osr * tmp_sbr) - baudrate;
+		diff2 = rate / (tmp_osr * (tmp_sbr + 1));
+
+		/* select best values between sbr and sbr+1 */
+		if (diff1 > (baudrate - diff2)) {
+			diff1 = baudrate - diff2;
+			tmp_sbr++;
+		}
+
+		if (diff1 <= baud_diff) {
+			baud_diff = diff1;
+			osr = tmp_osr;
+			sbr = tmp_sbr;
+		}
+	}
+
+	tmp = mmio_read_32(IMX_BOOT_UART_BASE + BAUD);
+
+	if ((osr > 3) && (osr < 8))
+		tmp |= LPUART_BAUD_BOTHEDGE_MASK;
+
+	tmp &= ~LPUART_BAUD_OSR_MASK;
+	tmp |= LPUART_BAUD_OSR(osr - 1);
+	tmp &= ~LPUART_BAUD_SBR_MASK;
+	tmp |= LPUART_BAUD_SBR(sbr);
+
+	/* explicitly disable 10 bit mode & set 1 stop bit */
+	tmp &= ~(LPUART_BAUD_M10_MASK | LPUART_BAUD_SBNS_MASK);
+
+	mmio_write_32(IMX_BOOT_UART_BASE + BAUD, tmp);
+}
+
+static int lpuart32_serial_init(unsigned int base)
+{
+	unsigned int tmp;
+
+	/* disable TX & RX before enabling clocks */
+	tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL);
+	tmp &= ~(CTRL_TE | CTRL_RE);
+	mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp);
+
+	mmio_write_32(IMX_BOOT_UART_BASE + MODIR, 0);
+	mmio_write_32(IMX_BOOT_UART_BASE + FIFO, ~(FIFO_TXFE | FIFO_RXFE));
+
+	mmio_write_32(IMX_BOOT_UART_BASE + MATCH, 0);
+
+	/* provide data bits, parity, stop bit, etc */
+	lpuart32_serial_setbrg(base, IMX_BOOT_UART_BAUDRATE);
+
+	/* eight data bits no parity bit */
+	tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL);
+	tmp &= ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK);
+	mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp);
+
+	mmio_write_32(IMX_BOOT_UART_BASE + CTRL, CTRL_RE | CTRL_TE);
+
+	mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55);
+	mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55);
+	mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x0A);
+
+	return 0;
+}
+#endif
+
+void imx8_partition_resources(void)
+{
+	sc_rm_pt_t secure_part, os_part;
+	sc_rm_mr_t mr, mr_record = 64;
+	sc_faddr_t start, end;
+	sc_err_t err;
+	bool owned;
+	int i;
+
+	err = sc_rm_get_partition(ipc_handle, &secure_part);
+	if (err)
+		ERROR("sc_rm_get_partition failed: %u\n", err);
+
+	err = sc_rm_partition_alloc(ipc_handle, &os_part, false, false,
+		false, false, false);
+	if (err)
+		ERROR("sc_rm_partition_alloc failed: %u\n", err);
+
+	err = sc_rm_set_parent(ipc_handle, os_part, secure_part);
+	if (err)
+		ERROR("sc_rm_set_parent: %u\n", err);
+
+	/* set secure resources to NOT-movable */
+	for (i = 0; i < (ARRAY_SIZE(secure_rsrcs)); i++) {
+		err = sc_rm_set_resource_movable(ipc_handle,
+			 secure_rsrcs[i], secure_rsrcs[i], false);
+		if (err)
+			ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n",
+				secure_rsrcs[i], err);
+	}
+
+	/* move all movable resources and pins to non-secure partition */
+	err = sc_rm_move_all(ipc_handle, secure_part, os_part, true, true);
+	if (err)
+		ERROR("sc_rm_move_all: %u\n", err);
+
+	/* iterate through peripherals to give NS OS part access */
+	for (i = 0; i < ARRAY_SIZE(ns_access_allowed); i++) {
+		err = sc_rm_set_peripheral_permissions(ipc_handle,
+			ns_access_allowed[i], os_part, SC_RM_PERM_FULL);
+		if (err)
+			ERROR("sc_rm_set_peripheral_permissions: rsrc %u, \
+				ret %u\n", ns_access_allowed[i], err);
+	}
+
+	/*
+	 * sc_rm_set_peripheral_permissions
+	 * sc_rm_set_memreg_permissions
+	 * sc_rm_set_pin_movable
+	 */
+	for (mr = 0; mr < 64; mr++) {
+		owned = sc_rm_is_memreg_owned(ipc_handle, mr);
+		if (owned) {
+			err = sc_rm_get_memreg_info(ipc_handle, mr, &start, &end);
+			if (err)
+				ERROR("Memreg get info failed, %u\n", mr);
+
+			NOTICE("Memreg %u 0x%llx -- 0x%llx\n", mr, start, end);
+			if (BL31_BASE >= start && (BL31_LIMIT - 1) <= end) {
+				mr_record = mr; /* Record the mr for ATF running */
+			} else {
+				err = sc_rm_assign_memreg(ipc_handle, os_part, mr);
+				if (err)
+					ERROR("Memreg assign failed, 0x%llx -- 0x%llx, \
+						err %d\n", start, end, err);
+			}
+		}
+	}
+
+	if (mr_record != 64) {
+		err = sc_rm_get_memreg_info(ipc_handle, mr_record, &start, &end);
+		if (err)
+			ERROR("Memreg get info failed, %u\n", mr_record);
+		if ((BL31_LIMIT - 1) < end) {
+			err = sc_rm_memreg_alloc(ipc_handle, &mr, BL31_LIMIT, end);
+			if (err)
+				ERROR("sc_rm_memreg_alloc failed, 0x%llx -- 0x%llx\n",
+					(sc_faddr_t)BL31_LIMIT, end);
+			err = sc_rm_assign_memreg(ipc_handle, os_part, mr);
+			if (err)
+				ERROR("Memreg assign failed, 0x%llx -- 0x%llx\n",
+					(sc_faddr_t)BL31_LIMIT, end);
+		}
+
+		if (start < (BL31_BASE - 1)) {
+			err = sc_rm_memreg_alloc(ipc_handle, &mr, start, BL31_BASE - 1);
+			if (err)
+				ERROR("sc_rm_memreg_alloc failed, 0x%llx -- 0x%llx\n",
+					start, (sc_faddr_t)BL31_BASE - 1);
+			err = sc_rm_assign_memreg(ipc_handle, os_part, mr);
+			if (err)
+				ERROR("Memreg assign failed, 0x%llx -- 0x%llx\n",
+					start, (sc_faddr_t)BL31_BASE - 1);
+		}
+	}
+
+	if (err)
+		NOTICE("Partitioning Failed\n");
+	else
+		NOTICE("Non-secure Partitioning Succeeded\n");
+}
+
+void bl31_early_platform_setup(bl31_params_t *from_bl2,
+				void *plat_params_from_bl2)
+{
+#if DEBUG_CONSOLE
+	static console_lpuart_t console;
+#endif
+	if (sc_ipc_open(&ipc_handle, SC_IPC_BASE) != SC_ERR_NONE)
+		panic();
+
+#if DEBUG_CONSOLE_A35
+	sc_pm_set_resource_power_mode(ipc_handle, SC_R_UART_0, SC_PM_PW_MODE_ON);
+	sc_pm_clock_rate_t rate = 80000000;
+	sc_pm_set_clock_rate(ipc_handle, SC_R_UART_0, 2, &rate);
+	sc_pm_clock_enable(ipc_handle, SC_R_UART_0, 2, true, false);
+
+	/* Configure UART pads */
+	sc_pad_set(ipc_handle, SC_P_UART0_RX, UART_PAD_CTRL);
+	sc_pad_set(ipc_handle, SC_P_UART0_TX, UART_PAD_CTRL);
+	lpuart32_serial_init(IMX_BOOT_UART_BASE);
+#endif
+
+#if DEBUG_CONSOLE
+	console_lpuart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+		     IMX_CONSOLE_BAUDRATE, &console);
+#endif
+	/* Turn on MU1 for non-secure OS/Hypervisor */
+	sc_pm_set_resource_power_mode(ipc_handle, SC_R_MU_1A, SC_PM_PW_MODE_ON);
+
+	/*
+	 * create new partition for non-secure OS/Hypervisor
+	 * uses global structs defined in sec_rsrc.h
+	 */
+	imx8_partition_resources();
+
+	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)
+{
+	unsigned long ro_start = BL31_RO_START;
+	unsigned long ro_size = BL31_RO_END - BL31_RO_START;
+	unsigned long rw_start = BL31_RW_START;
+	unsigned long rw_size = BL31_RW_END - BL31_RW_START;
+#if USE_COHERENT_MEM
+	unsigned long coh_start = BL31_COHERENT_RAM_START;
+	unsigned long coh_size = BL31_COHERENT_RAM_END - BL31_COHERENT_RAM_START;
+#endif
+
+	mmap_add_region(ro_start, ro_start, ro_size,
+		MT_RO | MT_MEMORY | MT_SECURE);
+	mmap_add_region(rw_start, rw_start, rw_size,
+		MT_RW | MT_MEMORY | MT_SECURE);
+	mmap_add(imx_mmap);
+
+#if USE_COHERENT_MEM
+	mmap_add_region(coh_start, coh_start, coh_size,
+			MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+
+	init_xlat_tables();
+	enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+	plat_gic_driver_init();
+	plat_gic_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/imx8qx/imx8qx_psci.c b/plat/imx/imx8qx/imx8qx_psci.c
new file mode 100644
index 0000000..47233dc
--- /dev/null
+++ b/plat/imx/imx8qx/imx8qx_psci.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015-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 <gicv3.h>
+#include <mmio.h>
+#include <plat_imx8.h>
+#include <psci.h>
+#include <sci/sci.h>
+#include <stdbool.h>
+
+const static int ap_core_index[PLATFORM_CORE_COUNT] = {
+	SC_R_A35_0, SC_R_A35_1, SC_R_A35_2, SC_R_A35_3
+};
+
+plat_local_state_t plat_get_target_pwr_state(unsigned int lvl,
+					     const plat_local_state_t *target_state,
+					     unsigned int ncpu)
+{
+	return 0;
+}
+
+int imx_pwr_domain_on(u_register_t mpidr)
+{
+	int ret = PSCI_E_SUCCESS;
+	unsigned int cpu_id;
+
+	cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+	tf_printf("imx_pwr_domain_on cpu_id %d\n", cpu_id);
+
+	if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id],
+	    SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
+		ERROR("core %d power on failed!\n", cpu_id);
+		ret = PSCI_E_INTERN_FAIL;
+	}
+
+	if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id],
+	    true, BL31_BASE) != SC_ERR_NONE) {
+		ERROR("boot core %d failed!\n", cpu_id);
+		ret = PSCI_E_INTERN_FAIL;
+	}
+
+	return ret;
+}
+
+void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	plat_gic_pcpu_init();
+	plat_gic_cpuif_enable();
+}
+
+int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
+{
+	return PSCI_E_SUCCESS;
+}
+
+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,
+	.validate_ns_entrypoint = imx_validate_ns_entrypoint,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	imx_mailbox_init(sec_entrypoint);
+	*psci_ops = &imx_plat_psci_ops;
+
+	return 0;
+}
diff --git a/plat/imx/imx8qx/include/platform_def.h b/plat/imx/imx8qx/include/platform_def.h
new file mode 100644
index 0000000..2cd1400
--- /dev/null
+++ b/plat/imx/imx8qx/include/platform_def.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#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_CORE_COUNT		4
+
+#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			0x80000000
+#define BL31_LIMIT			0x80020000
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ull << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ull << 32)
+
+#define MAX_XLAT_TABLES			8
+#define MAX_MMAP_REGIONS		8
+
+#define PLAT_GICD_BASE			0x51a00000
+#define PLAT_GICD_SIZE			0x10000
+#define PLAT_GICR_BASE			0x51b00000
+#define PLAT_GICR_SIZE			0xc0000
+#define IMX_BOOT_UART_BASE		0x5a060000
+#define IMX_BOOT_UART_SIZE		0x1000
+#define IMX_BOOT_UART_BAUDRATE		115200
+#define IMX_BOOT_UART_CLK_IN_HZ		24000000
+#define PLAT_CRASH_UART_BASE		IMX_BOOT_UART_BASE
+#define PLAT__CRASH_UART_CLK_IN_HZ	24000000
+#define IMX_CONSOLE_BAUDRATE		115200
+#define SC_IPC_BASE			0x5d1b0000
+#define SC_IPC_SIZE			0x10000
+
+#define COUNTER_FREQUENCY		8000000
+
+/* non-secure u-boot base */
+#define PLAT_NS_IMAGE_OFFSET		0x80020000
+
+#define DEBUG_CONSOLE			0
+#define DEBUG_CONSOLE_A35		0
+#define PLAT_IMX8QX			1
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/imx/imx8qx/include/sec_rsrc.h b/plat/imx/imx8qx/include/sec_rsrc.h
new file mode 100644
index 0000000..37c9f66
--- /dev/null
+++ b/plat/imx/imx8qx/include/sec_rsrc.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* resources that are going to stay in secure partition */
+sc_rsrc_t secure_rsrcs[] = {
+	SC_R_MU_0A,
+	SC_R_A35,
+	SC_R_A35_0,
+	SC_R_A35_1,
+	SC_R_A35_2,
+	SC_R_A35_3,
+	SC_R_GIC,
+	SC_R_SYSTEM,
+	SC_R_IRQSTR_SCU2
+};
+
+/* resources that have register access for non-secure domain */
+sc_rsrc_t ns_access_allowed[] = {
+	SC_R_GIC,
+};
diff --git a/plat/imx/imx8qx/platform.mk b/plat/imx/imx8qx/platform.mk
new file mode 100644
index 0000000..c16ce6e
--- /dev/null
+++ b/plat/imx/imx8qx/platform.mk
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES		:=	-Iplat/imx/imx8qx/include		\
+				-Iplat/imx/common/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/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES		+=	plat/imx/common/lpuart_console.S	\
+				plat/imx/common/imx8_helpers.S		\
+				plat/imx/imx8qx/imx8qx_bl31_setup.c	\
+				plat/imx/imx8qx/imx8qx_psci.c		\
+				plat/imx/common/imx8_topology.c		\
+				lib/xlat_tables/xlat_tables_common.c	\
+				lib/xlat_tables/aarch64/xlat_tables.c	\
+				lib/cpus/aarch64/cortex_a35.S		\
+				drivers/console/aarch64/console.S	\
+				${IMX_GIC_SOURCES}			\
+
+include plat/imx/common/sci/sci_api.mk
+
+ENABLE_PLAT_COMPAT	:=	0
+USE_COHERENT_MEM	:=	1
+RESET_TO_BL31		:=	1
+ARM_GIC_ARCH		:=	3
+MULTI_CONSOLE_API	:=	1
diff --git a/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c b/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c
index e3acfe9..6a3c1d6 100644
--- a/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c
+++ b/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c
@@ -99,6 +99,10 @@
 		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
 				      VERSION_2, image_info_t,
 				      IMAGE_ATTRIB_SKIP_LOADING),
+#ifdef SPD_opteed
+		.image_info.image_base = RPI3_OPTEE_PAGEABLE_LOAD_BASE,
+		.image_info.image_max_size = RPI3_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
 		.next_handoff_image_id = INVALID_IMAGE_ID,
 	},
 # endif /* BL32_BASE */
diff --git a/plat/rpi3/include/platform_def.h b/plat/rpi3/include/platform_def.h
index 5e2f1da..ebd77cd 100644
--- a/plat/rpi3/include/platform_def.h
+++ b/plat/rpi3/include/platform_def.h
@@ -181,6 +181,13 @@
 #define BL32_DRAM_BASE			SEC_DRAM0_BASE
 #define BL32_DRAM_LIMIT			(SEC_DRAM0_BASE + SEC_DRAM0_SIZE)
 
+#ifdef SPD_opteed
+/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */
+#define RPI3_OPTEE_PAGEABLE_LOAD_SIZE	0x080000 /* 512KB */
+#define RPI3_OPTEE_PAGEABLE_LOAD_BASE	(BL32_DRAM_LIMIT - \
+					 RPI3_OPTEE_PAGEABLE_LOAD_SIZE)
+#endif
+
 #define SEC_SRAM_ID			0
 #define SEC_DRAM_ID			1
 
diff --git a/plat/rpi3/platform.mk b/plat/rpi3/platform.mk
index 2cb7a15..2aaf406 100644
--- a/plat/rpi3/platform.mk
+++ b/plat/rpi3/platform.mk
@@ -120,3 +120,17 @@
 ifeq (${ARCH},aarch32)
   $(error Error: AArch32 not supported on rpi3)
 endif
+
+ifeq (${SPD},opteed)
+BL2_SOURCES	+=							\
+		lib/optee/optee_utils.c
+endif
+
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
+endif
diff --git a/plat/rpi3/rpi3_bl2_setup.c b/plat/rpi3/rpi3_bl2_setup.c
index f286caf..13e8c01 100644
--- a/plat/rpi3/rpi3_bl2_setup.c
+++ b/plat/rpi3/rpi3_bl2_setup.c
@@ -9,6 +9,7 @@
 #include <bl_common.h>
 #include <debug.h>
 #include <desc_image_load.h>
+#include <optee_utils.h>
 #include <platform_def.h>
 #include <xlat_mmu_helpers.h>
 #include <xlat_tables_defs.h>
@@ -67,11 +68,28 @@
 {
 	int err = 0;
 	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+#ifdef SPD_opteed
+	bl_mem_params_node_t *pager_mem_params = NULL;
+	bl_mem_params_node_t *paged_mem_params = NULL;
+#endif
 
 	assert(bl_mem_params != NULL);
 
 	switch (image_id) {
 	case BL32_IMAGE_ID:
+#ifdef SPD_opteed
+		pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+		assert(pager_mem_params);
+
+		paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+		assert(paged_mem_params);
+
+		err = parse_optee_header(&bl_mem_params->ep_info,
+				&pager_mem_params->image_info,
+				&paged_mem_params->image_info);
+		if (err != 0)
+			WARN("OPTEE header parse error.\n");
+#endif
 		bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl32_entry();
 		break;
 
diff --git a/plat/rpi3/rpi3_common.c b/plat/rpi3/rpi3_common.c
index 03914a6..65f5e7a 100644
--- a/plat/rpi3/rpi3_common.c
+++ b/plat/rpi3/rpi3_common.c
@@ -34,6 +34,13 @@
 #define MAP_BL32_MEM	MAP_REGION_FLAT(BL32_MEM_BASE, BL32_MEM_SIZE,	\
 					MT_MEMORY | MT_RW | MT_SECURE)
 
+#ifdef SPD_opteed
+#define MAP_OPTEE_PAGEABLE	MAP_REGION_FLAT(		\
+				RPI3_OPTEE_PAGEABLE_LOAD_BASE,	\
+				RPI3_OPTEE_PAGEABLE_LOAD_SIZE,	\
+				MT_MEMORY | MT_RW | MT_SECURE)
+#endif
+
 /*
  * Table of regions for various BL stages to map using the MMU.
  */
@@ -42,6 +49,9 @@
 	MAP_SHARED_RAM,
 	MAP_DEVICE0,
 	MAP_FIP,
+#ifdef SPD_opteed
+	MAP_OPTEE_PAGEABLE,
+#endif
 	{0}
 };
 #endif
@@ -190,3 +200,13 @@
 {
 	return INTR_TYPE_INVAL;
 }
+
+uint32_t plat_interrupt_type_to_line(uint32_t type,
+				     uint32_t security_state)
+{
+	/* It is not expected to receive an interrupt route to EL3.
+	 * Hence panic() to flag error.
+	 */
+	ERROR("Interrupt not expected to be routed to EL3");
+	panic();
+}
diff --git a/plat/rpi3/rpi3_io_storage.c b/plat/rpi3/rpi3_io_storage.c
index 7ac45ef..e090b2b 100644
--- a/plat/rpi3/rpi3_io_storage.c
+++ b/plat/rpi3/rpi3_io_storage.c
@@ -54,6 +54,14 @@
 	.uuid = UUID_SECURE_PAYLOAD_BL32,
 };
 
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
 static const io_uuid_spec_t bl33_uuid_spec = {
 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
 };
@@ -123,6 +131,21 @@
 		(uintptr_t)&bl32_uuid_spec,
 		open_fip
 	},
+	[BL32_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_uuid_spec,
+		open_fip
+	},
+	[BL32_EXTRA1_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra1_uuid_spec,
+		open_fip
+	},
+	[BL32_EXTRA2_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra2_uuid_spec,
+		open_fip
+	},
 	[BL33_IMAGE_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&bl33_uuid_spec,
diff --git a/plat/ti/k3/board/generic/board.mk b/plat/ti/k3/board/generic/board.mk
new file mode 100644
index 0000000..a342214
--- /dev/null
+++ b/plat/ti/k3/board/generic/board.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL32_BASE ?= 0x9e800000
+$(eval $(call add_define,BL32_BASE))
+
+PRELOADED_BL33_BASE ?= 0x80080000
+$(eval $(call add_define,PRELOADED_BL33_BASE))
+
+K3_HW_CONFIG_BASE ?= 0x82000000
+$(eval $(call add_define,K3_HW_CONFIG_BASE))
+
+PLAT_INCLUDES		+=	\
+				-Iplat/ti/k3/board/generic/include	\
diff --git a/plat/ti/k3/board/generic/include/board_def.h b/plat/ti/k3/board/generic/include/board_def.h
new file mode 100644
index 0000000..4c59c75
--- /dev/null
+++ b/plat/ti/k3/board/generic/include/board_def.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __BOARD_DEF_H__
+#define __BOARD_DEF_H__
+
+/* The ports must be in order and contiguous */
+#define K3_CLUSTER0_CORE_COUNT		2
+#define K3_CLUSTER0_MSMC_PORT		0
+
+#define K3_CLUSTER1_CORE_COUNT		2
+#define K3_CLUSTER1_MSMC_PORT		1
+
+#define K3_CLUSTER2_CORE_COUNT		2
+#define K3_CLUSTER2_MSMC_PORT		2
+
+#define K3_CLUSTER3_CORE_COUNT		2
+#define K3_CLUSTER3_MSMC_PORT		3
+
+/*
+ * This RAM will be used for the bootloader including code, bss, and stacks.
+ * It may need to be increased if BL31 grows in size.
+ */
+#define SEC_SRAM_BASE			0x70000000 /* Base of MSMC SRAM */
+#define SEC_SRAM_SIZE			0x00020000 /* 128k */
+
+#define PLAT_MAX_OFF_STATE		2
+#define PLAT_MAX_RET_STATE		1
+
+#endif /* __BOARD_DEF_H__ */
diff --git a/plat/ti/k3/common/k3_bl31_setup.c b/plat/ti/k3/common/k3_bl31_setup.c
new file mode 100644
index 0000000..ca7d214
--- /dev/null
+++ b/plat/ti/k3/common/k3_bl31_setup.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <k3_console.h>
+#include <plat_arm.h>
+#include <platform_def.h>
+#include <k3_gicv3.h>
+#include <string.h>
+
+/* Table of regions to map using the MMU */
+const mmap_region_t plat_arm_mmap[] = {
+	MAP_REGION_FLAT(SHARED_RAM_BASE, SHARED_RAM_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(K3_USART_BASE_ADDRESS, K3_USART_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(K3_GICD_BASE, K3_GICD_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(K3_GICR_BASE, K3_GICR_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+	{ /* sentinel */ }
+};
+
+/*
+ * Placeholder variables for maintaining information about the next image(s)
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+static uint32_t k3_get_spsr_for_bl33_entry(void)
+{
+	unsigned long el_status;
+	unsigned int mode;
+	uint32_t spsr;
+
+	/* Figure out what mode we enter the non-secure world in */
+	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;
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 early platform setup, such as console init and deciding on
+ * memory layout.
+ ******************************************************************************/
+void bl31_early_platform_setup(bl31_params_t *from_bl2,
+			       void *plat_params_from_bl2)
+{
+	/* There are no parameters from BL2 if BL31 is a reset vector */
+	assert(from_bl2 == NULL);
+	assert(plat_params_from_bl2 == NULL);
+
+	bl31_console_setup();
+
+#ifdef BL32_BASE
+	/* Populate entry point information for BL32 */
+	SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+	bl32_image_ep_info.pc = BL32_BASE;
+	bl32_image_ep_info.spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
+					  DISABLE_ALL_EXCEPTIONS);
+	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+#endif
+
+	/* Populate entry point information for BL33 */
+	SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+	bl33_image_ep_info.pc = PRELOADED_BL33_BASE;
+	bl33_image_ep_info.spsr = k3_get_spsr_for_bl33_entry();
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#ifdef K3_HW_CONFIG_BASE
+	/*
+	 * According to the file ``Documentation/arm64/booting.txt`` of the
+	 * Linux kernel tree, Linux expects the physical address of the device
+	 * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
+	 * must be 0.
+	 */
+	bl33_image_ep_info.args.arg0 = (u_register_t)K3_HW_CONFIG_BASE;
+	bl33_image_ep_info.args.arg1 = 0U;
+	bl33_image_ep_info.args.arg2 = 0U;
+	bl33_image_ep_info.args.arg3 = 0U;
+#endif
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	bl31_early_platform_setup((void *)arg0, (void *)arg1);
+}
+
+void bl31_plat_arch_setup(void)
+{
+	arm_setup_page_tables(BL31_BASE,
+			      BL31_END - BL31_BASE,
+			      BL_CODE_BASE,
+			      BL_CODE_END,
+			      BL_RO_DATA_BASE,
+			      BL_RO_DATA_END);
+	enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+	k3_gic_driver_init(K3_GICD_BASE, K3_GICR_BASE);
+	k3_gic_init();
+}
+
+void platform_mem_init(void)
+{
+	/* Do nothing for now... */
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+/*
+ * Empty function to prevent the console from being uninitialized after BL33 is
+ * started and allow us to see messages from BL31.
+ */
+void bl31_plat_runtime_setup(void)
+{
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image
+ * for the security state specified. BL3-3 corresponds to the non-secure
+ * image type while BL3-2 corresponds to the secure image type. A NULL
+ * pointer is returned if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	entry_point_info_t *next_image_info;
+
+	assert(sec_state_is_valid(type));
+	next_image_info = (type == NON_SECURE) ? &bl33_image_ep_info :
+						 &bl32_image_ep_info;
+	/*
+	 * None of the images on the ARM development platforms can have 0x0
+	 * as the entrypoint
+	 */
+	if (next_image_info->pc)
+		return next_image_info;
+
+	NOTICE("Requested nonexistent image\n");
+	return NULL;
+}
diff --git a/plat/ti/k3/common/k3_console.c b/plat/ti/k3/common/k3_console.c
new file mode 100644
index 0000000..ff3ca61
--- /dev/null
+++ b/plat/ti/k3/common/k3_console.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <console.h>
+#include <k3_console.h>
+#include <platform_def.h>
+#include <uart_16550.h>
+
+void bl31_console_setup(void)
+{
+	static console_16550_t console;
+
+	/* Initialize the console to provide early debug support */
+	console_16550_register(K3_USART_BASE_ADDRESS, K3_USART_CLK_SPEED,
+			       K3_USART_BAUD, &console);
+}
diff --git a/plat/ti/k3/common/k3_gicv3.c b/plat/ti/k3/common/k3_gicv3.c
new file mode 100644
index 0000000..3253130
--- /dev/null
+++ b/plat/ti/k3/common/k3_gicv3.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <gicv3.h>
+#include <interrupt_props.h>
+#include <k3_gicv3.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <utils.h>
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static const interrupt_prop_t k3_interrupt_props[] = {
+	PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
+	PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0)
+};
+
+static unsigned int k3_mpidr_to_core_pos(unsigned long mpidr)
+{
+	return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+gicv3_driver_data_t k3_gic_data = {
+	.rdistif_num = PLATFORM_CORE_COUNT,
+	.rdistif_base_addrs = rdistif_base_addrs,
+	.interrupt_props = k3_interrupt_props,
+	.interrupt_props_num = ARRAY_SIZE(k3_interrupt_props),
+	.mpidr_to_core_pos = k3_mpidr_to_core_pos,
+};
+
+void k3_gic_driver_init(uintptr_t gicd_base, uintptr_t gicr_base)
+{
+	/*
+	 * The GICv3 driver is initialized in EL3 and does not need
+	 * to be initialized again in SEL1. This is because the S-EL1
+	 * can use GIC system registers to manage interrupts and does
+	 * not need GIC interface base addresses to be configured.
+	 */
+	k3_gic_data.gicd_base = gicd_base;
+	k3_gic_data.gicr_base = gicr_base;
+	gicv3_driver_init(&k3_gic_data);
+}
+
+void k3_gic_init(void)
+{
+	gicv3_distif_init();
+	gicv3_rdistif_init(plat_my_core_pos());
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void k3_gic_cpuif_enable(void)
+{
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void k3_gic_cpuif_disable(void)
+{
+	gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+void k3_gic_pcpu_init(void)
+{
+	gicv3_rdistif_init(plat_my_core_pos());
+}
diff --git a/plat/ti/k3/common/k3_helpers.S b/plat/ti/k3/common/k3_helpers.S
new file mode 100644
index 0000000..c95e9c3
--- /dev/null
+++ b/plat/ti/k3/common/k3_helpers.S
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+#define K3_BOOT_REASON_COLD_RESET 0x1
+
+	/* ------------------------------------------------------------------
+	 *  uintptr_t plat_get_my_entrypoint(void)
+	 * ------------------------------------------------------------------
+	 *
+	 * This function is called with the called with the MMU and caches
+	 * disabled (SCTLR_EL3.M = 0 and SCTLR_EL3.C = 0). The function is
+	 * responsible for distinguishing between a warm and cold reset for the
+	 * current CPU using platform-specific means. If it's a warm reset,
+	 * then it returns the warm reset entrypoint point provided to
+	 * plat_setup_psci_ops() during BL31 initialization. If it's a cold
+	 * reset then this function must return zero.
+	 *
+	 * This function does not follow the Procedure Call Standard used by
+	 * the Application Binary Interface for the ARM 64-bit architecture.
+	 * The caller should not assume that callee saved registers are
+	 * preserved across a call to this function.
+	 */
+	.globl	plat_get_my_entrypoint
+func plat_get_my_entrypoint
+	ldr x0, k3_boot_reason_data_store
+	cmp  x0, #K3_BOOT_REASON_COLD_RESET
+
+	/* We ONLY support cold boot at this point */
+	bne plat_unsupported_boot
+	mov	x0, #0
+	ret
+
+	/*
+	 * We self manage our boot reason.
+	 * At load time, we have just a default reason - which is cold reset
+	 */
+k3_boot_reason_data_store:
+	.word	K3_BOOT_REASON_COLD_RESET
+
+plat_unsupported_boot:
+	b plat_unsupported_boot
+
+endfunc plat_get_my_entrypoint
+
+	/* ------------------------------------------------------------------
+	 * unsigned int plat_my_core_pos(void)
+	 * ------------------------------------------------------------------
+	 *
+	 * This function returns the index of the calling CPU which is used as a
+	 * CPU-specific linear index into blocks of memory (for example while
+	 * allocating per-CPU stacks). This function will be invoked very early
+	 * in the initialization sequence which mandates that this function
+	 * should be implemented in assembly and should not rely on the
+	 * avalability of a C runtime environment. This function can clobber x0
+	 * - x8 and must preserve x9 - x29.
+	 *
+	 * This function plays a crucial role in the power domain topology
+	 * framework in PSCI and details of this can be found in Power Domain
+	 * Topology Design.
+	 */
+	.globl plat_my_core_pos
+func plat_my_core_pos
+	mrs	x0, MPIDR_EL1
+
+	and	x1, x0, #MPIDR_CLUSTER_MASK
+	lsr	x1, x1, #MPIDR_AFF1_SHIFT
+	and	x0, x0, #MPIDR_CPU_MASK
+
+#if K3_CLUSTER1_MSMC_PORT != UNUSED
+	cmp	x1, #K3_CLUSTER0_MSMC_PORT
+	b.eq out
+	add	x0, x0, #K3_CLUSTER0_CORE_COUNT
+#if K3_CLUSTER2_MSMC_PORT != UNUSED
+	cmp	x1, #K3_CLUSTER1_MSMC_PORT
+	b.eq out
+	add	x0, x0, #K3_CLUSTER1_CORE_COUNT
+#if K3_CLUSTER3_MSMC_PORT != UNUSED
+	cmp	x1, #K3_CLUSTER2_MSMC_PORT
+	b.eq out
+	add	x0, x0, #K3_CLUSTER2_CORE_COUNT
+#endif /* K3_CLUSTER3_MSMC_PORT != UNUSED */
+#endif /* K3_CLUSTER2_MSMC_PORT != UNUSED */
+#endif /* K3_CLUSTER1_MSMC_PORT != UNUSED */
+
+out:
+	ret
+endfunc plat_my_core_pos
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_init(void)
+	 * Function to initialize the crash console
+	 * without a C Runtime to print crash report.
+	 * Clobber list : x0 - x4
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_init
+	mov_imm	x0, CRASH_CONSOLE_BASE
+	mov_imm	x1, CRASH_CONSOLE_CLK
+	mov_imm	x2, CRASH_CONSOLE_BAUD_RATE
+	mov w3, #0x0
+	b	console_core_init
+
+endfunc plat_crash_console_init
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_putc(void)
+	 * Function to print a character on the crash
+	 * console without a C Runtime.
+	 * Clobber list : x1, x2
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_putc
+	mov_imm	x1, CRASH_CONSOLE_BASE
+	b	console_core_putc
+endfunc plat_crash_console_putc
diff --git a/plat/ti/k3/common/k3_psci.c b/plat/ti/k3/common/k3_psci.c
new file mode 100644
index 0000000..91602c8
--- /dev/null
+++ b/plat/ti/k3/common/k3_psci.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <k3_gicv3.h>
+#include <psci.h>
+#include <stdbool.h>
+
+#define STUB() ERROR("stub %s called\n", __func__)
+
+uintptr_t k3_sec_entrypoint;
+
+static void k3_cpu_standby(plat_local_state_t cpu_state)
+{
+	/*
+	 * Enter standby state
+	 * dsb is good practice before using wfi to enter low power states
+	 */
+	dsb();
+	wfi();
+}
+
+static int k3_pwr_domain_on(u_register_t mpidr)
+{
+	sev();
+
+	/* TODO: Indicate to System firmware about powering up */
+
+	return PSCI_E_SUCCESS;
+}
+
+void k3_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	/* Prevent interrupts from spuriously waking up this cpu */
+	k3_gic_cpuif_disable();
+
+	/* TODO: Indicate to System firmware about powering down */
+}
+
+void k3_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	/* TODO: Indicate to System firmware about completion */
+
+	k3_gic_pcpu_init();
+	k3_gic_cpuif_enable();
+}
+
+static void __dead2 k3_system_reset(void)
+{
+	/* TODO: Indicate to System firmware about system reset */
+	STUB();
+
+	while (true)
+		wfi();
+}
+
+static int k3_validate_power_state(unsigned int power_state,
+				   psci_power_state_t *req_state)
+{
+	/* TODO: perform the proper validation */
+
+	return PSCI_E_SUCCESS;
+}
+
+static int k3_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+	/* TODO: perform the proper validation */
+
+	return PSCI_E_SUCCESS;
+}
+
+static const plat_psci_ops_t k3_plat_psci_ops = {
+	.cpu_standby = k3_cpu_standby,
+	.pwr_domain_on = k3_pwr_domain_on,
+	.pwr_domain_off = k3_pwr_domain_off,
+	.pwr_domain_on_finish = k3_pwr_domain_on_finish,
+	.system_reset = k3_system_reset,
+	.validate_power_state = k3_validate_power_state,
+	.validate_ns_entrypoint = k3_validate_ns_entrypoint
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	k3_sec_entrypoint = sec_entrypoint;
+
+	*psci_ops = &k3_plat_psci_ops;
+
+	return 0;
+}
diff --git a/plat/ti/k3/common/k3_topology.c b/plat/ti/k3/common/k3_topology.c
new file mode 100644
index 0000000..a77c8f3
--- /dev/null
+++ b/plat/ti/k3/common/k3_topology.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+#include <psci.h>
+
+/* The power domain tree descriptor */
+static unsigned char power_domain_tree_desc[] = {
+	PLATFORM_CLUSTER_COUNT,
+	K3_CLUSTER0_CORE_COUNT,
+#if K3_CLUSTER1_MSMC_PORT != UNUSED
+	K3_CLUSTER1_CORE_COUNT,
+#endif /* K3_CLUSTER1_MSMC_PORT != UNUSED */
+#if K3_CLUSTER2_MSMC_PORT != UNUSED
+	K3_CLUSTER2_CORE_COUNT,
+#endif /* K3_CLUSTER2_MSMC_PORT != UNUSED */
+#if K3_CLUSTER3_MSMC_PORT != UNUSED
+	K3_CLUSTER3_CORE_COUNT,
+#endif /* K3_CLUSTER3_MSMC_PORT != UNUSED */
+};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	unsigned int cpu_id;
+
+	mpidr &= MPIDR_AFFINITY_MASK;
+
+	if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+		return -1;
+
+	cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+	switch (MPIDR_AFFLVL1_VAL(mpidr)) {
+	case K3_CLUSTER0_MSMC_PORT:
+		if (cpu_id < K3_CLUSTER0_CORE_COUNT)
+			return cpu_id;
+		return -1;
+#if K3_CLUSTER1_MSMC_PORT != UNUSED
+	case K3_CLUSTER1_MSMC_PORT:
+		if (cpu_id < K3_CLUSTER1_CORE_COUNT)
+			return K3_CLUSTER0_CORE_COUNT + cpu_id;
+		return -1;
+#endif /* K3_CLUSTER1_MSMC_PORT != UNUSED */
+#if K3_CLUSTER2_MSMC_PORT != UNUSED
+	case K3_CLUSTER2_MSMC_PORT:
+		if (cpu_id < K3_CLUSTER2_CORE_COUNT)
+			return K3_CLUSTER0_CORE_COUNT +
+			       K3_CLUSTER1_CORE_COUNT + cpu_id;
+		return -1;
+#endif /* K3_CLUSTER2_MSMC_PORT != UNUSED */
+#if K3_CLUSTER3_MSMC_PORT != UNUSED
+	case K3_CLUSTER3_MSMC_PORT:
+		if (cpu_id < K3_CLUSTER3_CORE_COUNT)
+			return K3_CLUSTER0_CORE_COUNT +
+			       K3_CLUSTER1_CORE_COUNT +
+			       K3_CLUSTER2_CORE_COUNT + cpu_id;
+		return -1;
+#endif /* K3_CLUSTER3_MSMC_PORT != UNUSED */
+	default:
+		return -1;
+	}
+}
diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/k3/common/plat_common.mk
new file mode 100644
index 0000000..bf2a73f
--- /dev/null
+++ b/plat/ti/k3/common/plat_common.mk
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# We don't use BL1 or BL2, so BL31 is the first image to execute
+RESET_TO_BL31		:=	1
+# Only one core starts up at first
+COLD_BOOT_SINGLE_CPU	:=	1
+# We can choose where a core starts executing
+PROGRAMMABLE_RESET_ADDRESS:=	1
+
+# System coherency is managed in hardware
+HW_ASSISTED_COHERENCY	:=	1
+USE_COHERENT_MEM	:=	0
+
+ERROR_DEPRECATED	:=	1
+ENABLE_PLAT_COMPAT	:=	0
+
+# A53 erratum for SoC. (enable them all)
+ERRATA_A53_826319	:=	1
+ERRATA_A53_835769	:=	1
+ERRATA_A53_836870	:=	1
+ERRATA_A53_843419	:=	1
+ERRATA_A53_855873	:=	1
+
+MULTI_CONSOLE_API	:=	1
+TI_16550_MDR_QUIRK	:=	1
+$(eval $(call add_define,TI_16550_MDR_QUIRK))
+
+# Libraries
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_INCLUDES		+=	\
+				-I${PLAT_PATH}/include			\
+				-Iinclude/plat/arm/common/		\
+				-Iinclude/plat/arm/common/aarch64/	\
+
+K3_CONSOLE_SOURCES	+=	\
+				drivers/console/aarch64/console.S	\
+				drivers/ti/uart/aarch64/16550_console.S	\
+				${PLAT_PATH}/common/k3_console.c	\
+
+K3_GIC_SOURCES		+=	\
+				drivers/arm/gic/common/gic_common.c	\
+				drivers/arm/gic/v3/gicv3_main.c		\
+				drivers/arm/gic/v3/gicv3_helpers.c	\
+				plat/common/plat_gicv3.c		\
+				${PLAT_PATH}/common/k3_gicv3.c		\
+
+K3_PSCI_SOURCES		+=	\
+				plat/common/plat_psci_common.c		\
+				${PLAT_PATH}/common/k3_psci.c		\
+
+PLAT_BL_COMMON_SOURCES	+=	\
+				plat/arm/common/arm_common.c		\
+				lib/cpus/aarch64/cortex_a53.S		\
+				${XLAT_TABLES_LIB_SRCS}			\
+				${K3_CONSOLE_SOURCES}			\
+
+BL31_SOURCES		+=	\
+				${PLAT_PATH}/common/k3_bl31_setup.c	\
+				${PLAT_PATH}/common/k3_helpers.S	\
+				${PLAT_PATH}/common/k3_topology.c	\
+				${K3_GIC_SOURCES}			\
+				${K3_PSCI_SOURCES}			\
diff --git a/plat/ti/k3/include/k3_console.h b/plat/ti/k3/include/k3_console.h
new file mode 100644
index 0000000..5b01a31
--- /dev/null
+++ b/plat/ti/k3/include/k3_console.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __K3_CONSOLE_H__
+#define __K3_CONSOLE_H__
+
+void bl31_console_setup(void);
+
+#endif /* __K3_CONSOLE_H__ */
diff --git a/plat/ti/k3/include/k3_gicv3.h b/plat/ti/k3/include/k3_gicv3.h
new file mode 100644
index 0000000..bbf5bf9
--- /dev/null
+++ b/plat/ti/k3/include/k3_gicv3.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __K3_GICV3_H__
+#define __K3_GICV3_H__
+
+void k3_gic_driver_init(uintptr_t gicd_base, uintptr_t gicr_base);
+void k3_gic_init(void);
+void k3_gic_cpuif_enable(void);
+void k3_gic_cpuif_disable(void);
+void k3_gic_pcpu_init(void);
+
+#endif /* __K3_GICV3_H__ */
diff --git a/plat/ti/k3/include/plat_macros.S b/plat/ti/k3/include/plat_macros.S
new file mode 100644
index 0000000..96d1cd2
--- /dev/null
+++ b/plat/ti/k3/include/plat_macros.S
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_MACROS_S__
+#define __PLAT_MACROS_S__
+
+	/* ---------------------------------------------
+	 * The below required platform porting macro
+	 * prints out relevant platform registers
+	 * whenever an unhandled exception is taken in
+	 * BL31.
+	 * ---------------------------------------------
+	 */
+	.macro plat_crash_print_regs
+	/* STUB */
+	.endm
+
+#endif /* __PLAT_MACROS_S__ */
diff --git a/plat/ti/k3/include/platform_def.h b/plat/ti/k3/include/platform_def.h
new file mode 100644
index 0000000..8856af2
--- /dev/null
+++ b/plat/ti/k3/include/platform_def.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arch.h>
+#include <board_def.h>
+#include <common_def.h>
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stack */
+#if IMAGE_BL31
+#define PLATFORM_STACK_SIZE		0x800
+#else
+#define PLATFORM_STACK_SIZE		0x1000
+#endif
+
+#define PLATFORM_SYSTEM_COUNT		1
+#define PLATFORM_CORE_COUNT		(K3_CLUSTER0_CORE_COUNT + \
+					K3_CLUSTER1_CORE_COUNT + \
+					K3_CLUSTER2_CORE_COUNT + \
+					K3_CLUSTER3_CORE_COUNT)
+
+#define PLATFORM_CLUSTER_COUNT		((K3_CLUSTER0_MSMC_PORT != UNUSED) + \
+					(K3_CLUSTER1_MSMC_PORT != UNUSED) + \
+					(K3_CLUSTER2_MSMC_PORT != UNUSED) + \
+					(K3_CLUSTER3_MSMC_PORT != UNUSED))
+
+#define UNUSED				-1
+
+#if !defined(K3_CLUSTER1_CORE_COUNT) || !defined(K3_CLUSTER1_MSMC_PORT)
+#define K3_CLUSTER1_CORE_COUNT		0
+#define K3_CLUSTER1_MSMC_PORT		UNUSED
+#endif
+
+#if !defined(K3_CLUSTER2_CORE_COUNT) || !defined(K3_CLUSTER2_MSMC_PORT)
+#define K3_CLUSTER2_CORE_COUNT		0
+#define K3_CLUSTER2_MSMC_PORT		UNUSED
+#endif
+
+#if !defined(K3_CLUSTER3_CORE_COUNT) || !defined(K3_CLUSTER3_MSMC_PORT)
+#define K3_CLUSTER3_CORE_COUNT		0
+#define K3_CLUSTER3_MSMC_PORT		UNUSED
+#endif
+
+#if K3_CLUSTER0_MSMC_PORT == UNUSED
+#error "ARM cluster 0 must be used"
+#endif
+
+#if ((K3_CLUSTER1_MSMC_PORT == UNUSED) && (K3_CLUSTER1_CORE_COUNT != 0)) || \
+    ((K3_CLUSTER2_MSMC_PORT == UNUSED) && (K3_CLUSTER2_CORE_COUNT != 0)) || \
+    ((K3_CLUSTER3_MSMC_PORT == UNUSED) && (K3_CLUSTER3_CORE_COUNT != 0))
+#error "Unused ports must have 0 ARM cores"
+#endif
+
+#define PLATFORM_CLUSTER_OFFSET		K3_CLUSTER0_MSMC_PORT
+
+#define PLAT_NUM_PWR_DOMAINS		(PLATFORM_CLUSTER_COUNT + \
+					PLATFORM_CORE_COUNT)
+#define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL1
+
+/*******************************************************************************
+ * Memory layout constants
+ ******************************************************************************/
+
+/*
+ * ARM-TF lives in SRAM, partition it here
+ */
+
+#define SHARED_RAM_BASE			BL31_LIMIT
+#define SHARED_RAM_SIZE			0x00001000
+
+/*
+ * BL3-1 specific defines.
+ *
+ * Put BL3-1 at the base of the Trusted SRAM, before SHARED_RAM.
+ */
+#define BL31_BASE			SEC_SRAM_BASE
+#define BL31_SIZE			(SEC_SRAM_SIZE - SHARED_RAM_SIZE)
+#define BL31_LIMIT			(BL31_BASE + BL31_SIZE)
+#define BL31_PROGBITS_LIMIT		BL31_LIMIT
+
+/*
+ * Defines the maximum number of translation tables that are allocated by the
+ * translation table library code. To minimize the amount of runtime memory
+ * used, choose the smallest value needed to map the required virtual addresses
+ * for each BL stage.
+ */
+#define MAX_XLAT_TABLES		8
+
+/*
+ * Defines the maximum number of regions that are allocated by the translation
+ * table library code. A region consists of physical base address, virtual base
+ * address, size and attributes (Device/Memory, RO/RW, Secure/Non-Secure), as
+ * defined in the `mmap_region_t` structure. The platform defines the regions
+ * that should be mapped. Then, the translation table library will create the
+ * corresponding tables and descriptors at runtime. To minimize the amount of
+ * runtime memory used, choose the smallest value needed to register the
+ * required regions for each BL stage.
+ */
+#define MAX_MMAP_REGIONS	8
+
+/*
+ * Defines the total size of the address space in bytes. For example, for a 32
+ * bit address space, this value should be `(1ull << 32)`.
+ */
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ull << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ull << 32)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_SHIFT		6
+#define CACHE_WRITEBACK_GRANULE		(1 << CACHE_WRITEBACK_SHIFT)
+
+/* Platform default console definitions */
+#ifndef K3_USART_BASE_ADDRESS
+#define K3_USART_BASE_ADDRESS 0x02800000
+#endif
+
+/* USART has a default size for address space */
+#define K3_USART_SIZE 0x1000
+
+#ifndef K3_USART_CLK_SPEED
+#define K3_USART_CLK_SPEED 48000000
+#endif
+
+#ifndef K3_USART_BAUD
+#define K3_USART_BAUD 115200
+#endif
+
+/* Crash console defaults */
+#define CRASH_CONSOLE_BASE K3_USART_BASE_ADDRESS
+#define CRASH_CONSOLE_CLK K3_USART_CLK_SPEED
+#define CRASH_CONSOLE_BAUD_RATE K3_USART_BAUD
+
+/* Timer frequency */
+#ifndef SYS_COUNTER_FREQ_IN_TICKS
+#define SYS_COUNTER_FREQ_IN_TICKS 200000000
+#endif
+
+/* Interrupt numbers */
+#define ARM_IRQ_SEC_PHY_TIMER		29
+
+#define ARM_IRQ_SEC_SGI_0		8
+#define ARM_IRQ_SEC_SGI_1		9
+#define ARM_IRQ_SEC_SGI_2		10
+#define ARM_IRQ_SEC_SGI_3		11
+#define ARM_IRQ_SEC_SGI_4		12
+#define ARM_IRQ_SEC_SGI_5		13
+#define ARM_IRQ_SEC_SGI_6		14
+#define ARM_IRQ_SEC_SGI_7		15
+
+/*
+ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
+	INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_LEVEL), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE)
+
+#define PLAT_ARM_G0_IRQ_PROPS(grp) \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE)
+
+#define K3_GICD_BASE  0x01800000
+#define K3_GICD_SIZE  0x10000
+#define K3_GICR_BASE  0x01880000
+#define K3_GICR_SIZE  0x100000
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/ti/k3/platform.mk b/plat/ti/k3/platform.mk
new file mode 100644
index 0000000..65d5cc2
--- /dev/null
+++ b/plat/ti/k3/platform.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_PATH	:=	plat/ti/k3
+TARGET_BOARD	?=	generic
+
+include ${PLAT_PATH}/common/plat_common.mk
+include ${PLAT_PATH}/board/${TARGET_BOARD}/board.mk
+
+# modify BUILD_PLAT to point to board specific build directory
+BUILD_PLAT := ${BUILD_BASE}/${PLAT}/${TARGET_BOARD}/${BUILD_TYPE}
diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
index b144c84..c361270 100644
--- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
+++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
@@ -205,12 +205,21 @@
 {
 	uint32_t id, ver, chipid[2];
 	size_t i, j, len;
-	enum pm_ret_status ret;
 	const char *name = "EG/EV";
 
-	ret = pm_get_chipid(chipid);
-	if (ret)
+#ifdef IMAGE_BL32
+	/*
+	 * For BL32, get the chip id info directly by reading corresponding
+	 * registers instead of making pm call. This has limitation
+	 * that these registers should be configured to have access
+	 * from APU which is default case.
+	 */
+	chipid[0] = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
+	chipid[1] = mmio_read_32(EFUSE_BASEADDR + EFUSE_IPDISABLE_OFFSET);
+#else
+	if (pm_get_chipid(chipid) != PM_RET_SUCCESS)
 		return "UNKN";
+#endif
 
 	id = chipid[0] & (ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
 			  ZYNQMP_CSU_IDCODE_SVD_MASK);
diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h
index ebbc8c2..49766cc 100644
--- a/plat/xilinx/zynqmp/include/platform_def.h
+++ b/plat/xilinx/zynqmp/include/platform_def.h
@@ -34,7 +34,7 @@
  * little space for growth.
  */
 #ifndef ZYNQMP_ATF_MEM_BASE
-#if !DEBUG
+#if !DEBUG && defined(SPD_none)
 # define BL31_BASE			0xfffea000
 # define BL31_LIMIT			0xffffffff
 #else
diff --git a/readme.rst b/readme.rst
index 94b1e63..3738c97 100644
--- a/readme.rst
+++ b/readme.rst
@@ -183,6 +183,7 @@
 -  Raspberry Pi 3 board
 -  RockChip RK3328, RK3368 and RK3399 SoCs
 -  Socionext UniPhier SoC family
+-  Texas Instruments K3 SoCs
 -  Xilinx Zynq UltraScale + MPSoC
 
 Still to come
diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c
index be76dc2..f63f9c4 100644
--- a/services/std_svc/spm/spm_main.c
+++ b/services/std_svc/spm/spm_main.c
@@ -81,10 +81,13 @@
 }
 
 /*******************************************************************************
- * This function takes an SP context pointer and prepares the CPU to enter.
+ * This function takes an SP context pointer and performs a synchronous entry
+ * into it.
  ******************************************************************************/
-static void spm_sp_prepare_enter(sp_context_t *sp_ctx)
+static uint64_t spm_sp_synchronous_entry(sp_context_t *sp_ctx)
 {
+	uint64_t rc;
+
 	assert(sp_ctx != NULL);
 
 	/* Assign the context of the SP to this CPU */
@@ -97,15 +100,32 @@
 	/* Invalidate TLBs at EL1. */
 	tlbivmalle1();
 	dsbish();
+
+	/* Enter Secure Partition */
+	rc = spm_secure_partition_enter(&sp_ctx->c_rt_ctx);
+
+	/* Save secure state */
+	cm_el1_sysregs_context_save(SECURE);
+
+	return rc;
 }
 
 /*******************************************************************************
- * Enter SP after preparing it with spm_sp_prepare_enter().
+ * This function returns to the place where spm_sp_synchronous_entry() was
+ * called originally.
  ******************************************************************************/
-static uint64_t spm_sp_enter(sp_context_t *sp_ctx)
+__dead2 static void spm_sp_synchronous_exit(uint64_t rc)
 {
-	/* Enter Secure Partition */
-	return spm_secure_partition_enter(&sp_ctx->c_rt_ctx);
+	sp_context_t *ctx = &sp_ctx;
+
+	/*
+	 * The SPM must have initiated the original request through a
+	 * synchronous entry into the secure partition. Jump back to the
+	 * original C runtime context with the value of rc in x0;
+	 */
+	spm_secure_partition_exit(ctx->c_rt_ctx, rc);
+
+	panic();
 }
 
 /*******************************************************************************
@@ -113,7 +133,7 @@
  ******************************************************************************/
 static int32_t spm_init(void)
 {
-	uint64_t rc = 0;
+	uint64_t rc;
 	sp_context_t *ctx;
 
 	INFO("Secure Partition init...\n");
@@ -122,8 +142,7 @@
 
 	ctx->state = SP_STATE_RESET;
 
-	spm_sp_prepare_enter(ctx);
-	rc |= spm_sp_enter(ctx);
+	rc = spm_sp_synchronous_entry(ctx);
 	assert(rc == 0);
 
 	ctx->state = SP_STATE_IDLE;
@@ -168,6 +187,7 @@
 			       uint64_t comm_buffer_address,
 			       uint64_t comm_size_address, void *handle)
 {
+	uint64_t rc;
 	sp_context_t *ctx = &sp_ctx;
 
 	/* Cookie. Reserved for future use. It must be zero. */
@@ -188,59 +208,29 @@
 	/* Save the Normal world context */
 	cm_el1_sysregs_context_save(NON_SECURE);
 
-	/* Wait until the Secure Partition is IDLE and set it to BUSY. */
+	/* Wait until the Secure Partition is idle and set it to busy. */
 	sp_state_wait_switch(ctx, SP_STATE_IDLE, SP_STATE_BUSY);
 
-	/* Jump to the Secure Partition. */
-	spm_sp_prepare_enter(ctx);
-
-	SMC_RET4(&(ctx->cpu_ctx), smc_fid, comm_buffer_address,
-		 comm_size_address, plat_my_core_pos());
-}
-
-/*******************************************************************************
- * SP_EVENT_COMPLETE_AARCH64 handler
- ******************************************************************************/
-static uint64_t sp_event_complete(uint64_t x1)
-{
-	sp_context_t *ctx = &sp_ctx;
+	/* Set values for registers on SP entry */
+	cpu_context_t *cpu_ctx = &(ctx->cpu_ctx);
 
-	/* Save secure state */
-	cm_el1_sysregs_context_save(SECURE);
+	write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X0, smc_fid);
+	write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X1, comm_buffer_address);
+	write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X2, comm_size_address);
+	write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X3, plat_my_core_pos());
 
-	if (ctx->state == SP_STATE_RESET) {
-		/*
-		 * SPM reports completion. The SPM must have initiated the
-		 * original request through a synchronous entry into the secure
-		 * partition. Jump back to the original C runtime context.
-		 */
-		spm_secure_partition_exit(ctx->c_rt_ctx, x1);
-
-		/* spm_secure_partition_exit doesn't return */
-	}
-
-	/*
-	 * This is the result from the Secure partition of an earlier request.
-	 * Copy the result into the non-secure context and return to the
-	 * non-secure state.
-	 */
+	/* Jump to the Secure Partition. */
+	rc = spm_sp_synchronous_entry(ctx);
 
-	/* Mark Secure Partition as idle */
+	/* Flag Secure Partition as idle. */
 	assert(ctx->state == SP_STATE_BUSY);
-
 	sp_state_set(ctx, SP_STATE_IDLE);
 
-	/* Get a reference to the non-secure context */
-	cpu_context_t *ns_cpu_context = cm_get_context(NON_SECURE);
-
-	assert(ns_cpu_context != NULL);
-
 	/* Restore non-secure state */
 	cm_el1_sysregs_context_restore(NON_SECURE);
 	cm_set_next_eret_context(NON_SECURE);
 
-	/* Return to non-secure world */
-	SMC_RET1(ns_cpu_context, x1);
+	SMC_RET1(handle, rc);
 }
 
 /*******************************************************************************
@@ -275,7 +265,7 @@
 			SMC_RET1(handle, SPM_VERSION_COMPILED);
 
 		case SP_EVENT_COMPLETE_AARCH64:
-			return sp_event_complete(x1);
+			spm_sp_synchronous_exit(x1);
 
 		case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
 			INFO("Received SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n");
@@ -305,6 +295,8 @@
 
 		/* Handle SMCs from Non-secure world. */
 
+		assert(handle == cm_get_context(NON_SECURE));
+
 		switch (smc_fid) {
 
 		case MM_VERSION_AARCH32:
diff --git a/services/std_svc/spm/spm_private.h b/services/std_svc/spm/spm_private.h
index 64d8cf8..f094739 100644
--- a/services/std_svc/spm/spm_private.h
+++ b/services/std_svc/spm/spm_private.h
@@ -35,7 +35,7 @@
 #include <stdint.h>
 #include <xlat_tables_v2.h>
 
-typedef enum secure_partition_state {
+typedef enum sp_state {
 	SP_STATE_RESET = 0,
 	SP_STATE_IDLE,
 	SP_STATE_BUSY