Merge pull request #1406 from robertovargas-arm/uuid

Make TF UUID RFC 4122 compliant
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/bl31/bl31.ld.S b/bl31/bl31.ld.S
index c6a4fe4..59df9b8 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -221,13 +221,6 @@
      * tables library.
      */
     xlat_table (NOLOAD) : {
-#if ENABLE_SPM
-        __SP_IMAGE_XLAT_TABLES_START__ = .;
-        *secure_partition*.o(xlat_table)
-        /* Make sure that the rest of the page is empty. */
-        . = NEXT(PAGE_SIZE);
-        __SP_IMAGE_XLAT_TABLES_END__ = .;
-#endif
         *(xlat_table)
     } >RAM
 
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index a6c0a9a..307ddab 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -18,15 +18,16 @@
 BL31_SOURCES		+=	bl31/bl31_main.c				\
 				bl31/interrupt_mgmt.c				\
 				bl31/aarch64/bl31_entrypoint.S			\
-				bl31/aarch64/runtime_exceptions.S		\
 				bl31/aarch64/crash_reporting.S			\
+				bl31/aarch64/runtime_exceptions.S		\
 				bl31/bl31_context_mgmt.c			\
 				common/runtime_svc.c				\
+				lib/aarch64/setjmp.S				\
 				plat/common/aarch64/platform_mp_stack.S		\
 				services/arm_arch_svc/arm_arch_svc_setup.c	\
 				services/std_svc/std_svc_setup.c		\
 				${PSCI_LIB_SOURCES}				\
-				${SPM_SOURCES}					\
+				${SPM_SOURCES}
 
 
 ifeq (${ENABLE_PMF}, 1)
@@ -41,7 +42,8 @@
 ifeq (${EL3_EXCEPTION_HANDLING},0)
   $(error EL3_EXCEPTION_HANDLING must be 1 for SDEI support)
 endif
-BL31_SOURCES		+=	services/std_svc/sdei/sdei_event.c	\
+BL31_SOURCES		+=	services/std_svc/sdei/sdei_dispatch.S	\
+				services/std_svc/sdei/sdei_event.c	\
 				services/std_svc/sdei/sdei_intr_mgmt.c	\
 				services/std_svc/sdei/sdei_main.c	\
 				services/std_svc/sdei/sdei_state.c
diff --git a/docs/plantuml/sdei_explicit_dispatch.puml b/docs/plantuml/sdei_explicit_dispatch.puml
index c80fcd1..90ff23c 100644
--- a/docs/plantuml/sdei_explicit_dispatch.puml
+++ b/docs/plantuml/sdei_explicit_dispatch.puml
@@ -1,5 +1,5 @@
 /'
- ' 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
  '/
@@ -9,7 +9,8 @@
 autonumber "<b>[#]</b>"
 participant "SDEI client" as EL2
 participant EL3
-participant "Secure Partition" as SP
+participant SDEI
+participant "RAS Driver" as RAS
 
 activate EL2
 EL2->EL3: **SDEI_EVENT_REGISTER**(ev, handler, ...)
@@ -24,21 +25,26 @@
 EL3<--]: **CRITICAL EVENT**
 activate EL3 #red
 note over EL3: Critical event triage
-EL3->SP: dispatch
-activate SP #salmon
-note over SP: Critical event handling
-SP->EL3: done
-deactivate SP
-EL3-->EL3: sdei_dispatch_event(ev)
-note over EL3: Prepare SDEI dispatch
-EL3->EL2: dispatch
+EL3->RAS: dispatch to handle
+deactivate EL3
+activate RAS #salmon
+note over RAS: Critical event handling
+RAS-->SDEI: sdei_dispatch_event(ev)
+deactivate RAS
+activate SDEI #salmon
+note over SDEI: Prepare SDEI dispatch
+SDEI->EL2: dispatch
 activate EL2 #salmon
 note over EL2: SDEI handler
-EL2->EL3: **SDEI_EVENT_COMPLETE()**
+EL2->SDEI: **SDEI_EVENT_COMPLETE()**
 deactivate EL2
-note over EL3: Complete SDEI dispatch
+note over SDEI: Complete SDEI dispatch
+SDEI-->RAS: return
+deactivate SDEI
+activate RAS #salmon
+RAS->EL3: error handling done
+deactivate RAS
 EL3->EL2: resumes preempted execution
-deactivate EL3
 
 ... <<Normal execution resumes>> ...
 
diff --git a/docs/plantuml/sdei_explicit_dispatch.svg b/docs/plantuml/sdei_explicit_dispatch.svg
index 182df0a..e12cae2 100644
--- a/docs/plantuml/sdei_explicit_dispatch.svg
+++ b/docs/plantuml/sdei_explicit_dispatch.svg
@@ -1 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="767px" preserveAspectRatio="none" style="width:692px;height:767px;" version="1.1" viewBox="0 0 692 767" width="692px" zoomAndPan="magnify"><defs><filter height="300%" id="fueepysa066oi" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><rect fill="#FFFFFF" filter="url(#fueepysa066oi)" height="174.7969" style="stroke: #FFFFFF; stroke-width: 1.0;" width="10" x="56.5" y="48.2969"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="56.5" y1="48.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="66.5" y1="48.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="66.5" y1="48.2969" y2="48.2969"/><rect fill="#FFFFFF" filter="url(#fueepysa066oi)" height="412.5938" style="stroke: #FFFFFF; stroke-width: 1.0;" width="10" x="56.5" y="263.8984"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="56.5" y1="263.8984" y2="676.4922"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="66.5" y1="263.8984" y2="676.4922"/><rect fill="#FFFFFF" filter="url(#fueepysa066oi)" height="1" style="stroke: #FFFFFF; stroke-width: 1.0;" width="10" x="56.5" y="717.2969"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="56.5" y1="717.2969" y2="718.2969"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="66.5" y1="717.2969" y2="718.2969"/><rect fill="#FA8072" filter="url(#fueepysa066oi)" height="68.2656" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="61.5" y="531.8281"/><rect fill="#FF0000" filter="url(#fueepysa066oi)" height="383.4609" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="375.5" y="284.8984"/><rect fill="#FA8072" filter="url(#fueepysa066oi)" height="68.2656" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="588.5" y="353.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="61" x2="61" y1="38.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="61" x2="61" y1="223.0938" y2="263.8984"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="61" x2="61" y1="263.8984" y2="676.4922"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="61" x2="61" y1="676.4922" y2="717.2969"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="61" x2="61" y1="717.2969" y2="727.2969"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="380" x2="380" y1="38.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="380" x2="380" y1="223.0938" y2="263.8984"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="380" x2="380" y1="263.8984" y2="676.4922"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="380" x2="380" y1="676.4922" y2="717.2969"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="380" x2="380" y1="717.2969" y2="727.2969"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="593" x2="593" y1="38.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="593" x2="593" y1="223.0938" y2="263.8984"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="593" x2="593" y1="263.8984" y2="676.4922"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="593" x2="593" y1="676.4922" y2="717.2969"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="593" x2="593" y1="717.2969" y2="727.2969"/><rect fill="#FEFECE" filter="url(#fueepysa066oi)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="87" x="16" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="73" x="23" y="22.9951">SDEI client</text><rect fill="#FEFECE" filter="url(#fueepysa066oi)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="87" x="16" y="726.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="73" x="23" y="746.292">SDEI client</text><rect fill="#FEFECE" filter="url(#fueepysa066oi)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="39" x="359" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="25" x="366" y="22.9951">EL3</text><rect fill="#FEFECE" filter="url(#fueepysa066oi)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="39" x="359" y="726.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="25" x="366" y="746.292">EL3</text><rect fill="#FEFECE" filter="url(#fueepysa066oi)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="123" x="530" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="109" x="537" y="22.9951">Secure Partition</text><rect fill="#FEFECE" filter="url(#fueepysa066oi)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="123" x="530" y="726.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="109" x="537" y="746.292">Secure Partition</text><rect fill="#FFFFFF" filter="url(#fueepysa066oi)" height="174.7969" style="stroke: #FFFFFF; stroke-width: 1.0;" width="10" x="56.5" y="48.2969"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="56.5" y1="48.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="66.5" y1="48.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="66.5" y1="48.2969" y2="48.2969"/><rect fill="#FFFFFF" filter="url(#fueepysa066oi)" height="412.5938" style="stroke: #FFFFFF; stroke-width: 1.0;" width="10" x="56.5" y="263.8984"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="56.5" y1="263.8984" y2="676.4922"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="66.5" y1="263.8984" y2="676.4922"/><rect fill="#FFFFFF" filter="url(#fueepysa066oi)" height="1" style="stroke: #FFFFFF; stroke-width: 1.0;" width="10" x="56.5" y="717.2969"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="56.5" y1="717.2969" y2="718.2969"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="66.5" y1="717.2969" y2="718.2969"/><rect fill="#FA8072" filter="url(#fueepysa066oi)" height="68.2656" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="61.5" y="531.8281"/><rect fill="#FF0000" filter="url(#fueepysa066oi)" height="383.4609" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="375.5" y="284.8984"/><rect fill="#FA8072" filter="url(#fueepysa066oi)" height="68.2656" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="588.5" y="353.1641"/><polygon fill="#A80036" points="368.5,65.2969,378.5,69.2969,368.5,73.2969,372.5,69.2969" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="374.5" y1="69.2969" y2="69.2969"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="73.5" y="64.3638">[1]</text><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="164" x="98.5" y="64.3638">SDEI_EVENT_REGISTER</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="101" x="262.5" y="64.3638">(ev, handler, ...)</text><polygon fill="#A80036" points="77.5,94.4297,67.5,98.4297,77.5,102.4297,73.5,98.4297" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="71.5" x2="379.5" y1="98.4297" y2="98.4297"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="83.5" y="93.4966">[2]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="51" x="108.5" y="93.4966">success</text><polygon fill="#A80036" points="368.5,123.5625,378.5,127.5625,368.5,131.5625,372.5,127.5625" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="374.5" y1="127.5625" y2="127.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="73.5" y="122.6294">[3]</text><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="151" x="98.5" y="122.6294">SDEI_EVENT_ENABLE</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="25" x="249.5" y="122.6294">(ev)</text><polygon fill="#A80036" points="77.5,152.6953,67.5,156.6953,77.5,160.6953,73.5,156.6953" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="71.5" x2="379.5" y1="156.6953" y2="156.6953"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="83.5" y="151.7622">[4]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="51" x="108.5" y="151.7622">success</text><polygon fill="#A80036" points="368.5,181.8281,378.5,185.8281,368.5,189.8281,372.5,185.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="374.5" y1="185.8281" y2="185.8281"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="73.5" y="180.895">[5]</text><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="129" x="98.5" y="180.895">SDEI_PE_UNMASK</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="10" x="227.5" y="180.895">()</text><polygon fill="#A80036" points="77.5,210.9609,67.5,214.9609,77.5,218.9609,73.5,214.9609" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="71.5" x2="379.5" y1="214.9609" y2="214.9609"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="83.5" y="210.0278">[6]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="8" x="108.5" y="210.0278">1</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="142" x="256.5" y="247.3042">&lt;&lt;Business as usual&gt;&gt;</text><polygon fill="#A80036" points="396.5,280.8984,386.5,284.8984,396.5,288.8984,392.5,284.8984" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 2.0,2.0;" x1="390.5" x2="680" y1="284.8984" y2="284.8984"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="402.5" y="279.9653">[7]</text><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="116" x="427.5" y="279.9653">CRITICAL EVENT</text><polygon fill="#FBFB77" filter="url(#fueepysa066oi)" points="306,298.0313,306,323.0313,451,323.0313,451,308.0313,441,298.0313,306,298.0313" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="441" x2="441" y1="298.0313" y2="308.0313"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="451" x2="441" y1="308.0313" y2="308.0313"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="124" x="312" y="315.0981">Critical event triage</text><polygon fill="#A80036" points="576.5,349.1641,586.5,353.1641,576.5,357.1641,580.5,353.1641" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="385.5" x2="582.5" y1="353.1641" y2="353.1641"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="392.5" y="348.231">[8]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="54" x="417.5" y="348.231">dispatch</text><polygon fill="#FBFB77" filter="url(#fueepysa066oi)" points="510,366.2969,510,391.2969,672,391.2969,672,376.2969,662,366.2969,510,366.2969" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="662" x2="662" y1="366.2969" y2="376.2969"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="672" x2="662" y1="376.2969" y2="376.2969"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="141" x="516" y="383.3638">Critical event handling</text><polygon fill="#A80036" points="396.5,417.4297,386.5,421.4297,396.5,425.4297,392.5,421.4297" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="390.5" x2="592.5" y1="421.4297" y2="421.4297"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="402.5" y="416.4966">[9]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="32" x="427.5" y="416.4966">done</text><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 2.0,2.0;" x1="385.5" x2="427.5" y1="450.6953" y2="450.6953"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 2.0,2.0;" x1="427.5" x2="427.5" y1="450.6953" y2="463.6953"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 2.0,2.0;" x1="386.5" x2="427.5" y1="463.6953" y2="463.6953"/><polygon fill="#A80036" points="396.5,459.6953,386.5,463.6953,396.5,467.6953,392.5,463.6953" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="30" x="392.5" y="445.6294">[10]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="155" x="426.5" y="445.6294">sdei_dispatch_event(ev)</text><polygon fill="#FBFB77" filter="url(#fueepysa066oi)" points="297,476.6953,297,501.6953,460,501.6953,460,486.6953,450,476.6953,297,476.6953" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="450" x2="450" y1="476.6953" y2="486.6953"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="460" x2="450" y1="486.6953" y2="486.6953"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="142" x="303" y="493.7622">Prepare SDEI dispatch</text><polygon fill="#A80036" points="82.5,527.8281,72.5,531.8281,82.5,535.8281,78.5,531.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="76.5" x2="374.5" y1="531.8281" y2="531.8281"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="30" x="88.5" y="526.895">[11]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="54" x="122.5" y="526.895">dispatch</text><polygon fill="#FBFB77" filter="url(#fueepysa066oi)" points="8,544.9609,8,569.9609,111,569.9609,111,554.9609,101,544.9609,8,544.9609" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="101" x2="101" y1="544.9609" y2="554.9609"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="111" x2="101" y1="554.9609" y2="554.9609"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="82" x="14" y="562.0278">SDEI handler</text><polygon fill="#A80036" points="363.5,596.0938,373.5,600.0938,363.5,604.0938,367.5,600.0938" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="369.5" y1="600.0938" y2="600.0938"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="30" x="73.5" y="595.1606">[12]</text><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="184" x="107.5" y="595.1606">SDEI_EVENT_COMPLETE()</text><polygon fill="#FBFB77" filter="url(#fueepysa066oi)" points="291,613.2266,291,638.2266,466,638.2266,466,623.2266,456,613.2266,291,613.2266" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="456" x2="456" y1="613.2266" y2="623.2266"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="466" x2="456" y1="623.2266" y2="623.2266"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="154" x="297" y="630.2935">Complete SDEI dispatch</text><polygon fill="#A80036" points="77.5,664.3594,67.5,668.3594,77.5,672.3594,73.5,668.3594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="71.5" x2="379.5" y1="668.3594" y2="668.3594"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="30" x="83.5" y="663.4263">[13]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="197" x="117.5" y="663.4263">resumes preempted execution</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="190" x="232.5" y="700.7026">&lt;&lt;Normal execution resumes&gt;&gt;</text></g></svg>
\ No newline at end of file
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="783px" preserveAspectRatio="none" style="width:745px;height:783px;" version="1.1" viewBox="0 0 745 783" width="745px" zoomAndPan="magnify"><defs><filter height="300%" id="f18zq03ani7xpz" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><rect fill="#FFFFFF" filter="url(#f18zq03ani7xpz)" height="174.7969" style="stroke: #FFFFFF; stroke-width: 1.0;" width="10" x="56.5" y="48.2969"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="56.5" y1="48.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="66.5" y1="48.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="66.5" y1="48.2969" y2="48.2969"/><rect fill="#FFFFFF" filter="url(#f18zq03ani7xpz)" height="428.7266" style="stroke: #FFFFFF; stroke-width: 1.0;" width="10" x="56.5" y="263.8984"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="56.5" y1="263.8984" y2="692.625"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="66.5" y1="263.8984" y2="692.625"/><rect fill="#FFFFFF" filter="url(#f18zq03ani7xpz)" height="1" style="stroke: #FFFFFF; stroke-width: 1.0;" width="10" x="56.5" y="733.4297"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="56.5" y1="733.4297" y2="734.4297"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="66.5" y1="733.4297" y2="734.4297"/><rect fill="#FA8072" filter="url(#f18zq03ani7xpz)" height="68.2656" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="61.5" y="489.8281"/><rect fill="#FF0000" filter="url(#f18zq03ani7xpz)" height="68.2656" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="375.5" y="285.0313"/><rect fill="#FA8072" filter="url(#f18zq03ani7xpz)" height="204.7969" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="432" y="421.5625"/><rect fill="#FA8072" filter="url(#f18zq03ani7xpz)" height="68.2656" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="641" y="353.2969"/><rect fill="#FA8072" filter="url(#f18zq03ani7xpz)" height="29.1328" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="641" y="626.3594"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="61" x2="61" y1="38.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="61" x2="61" y1="223.0938" y2="263.8984"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="61" x2="61" y1="263.8984" y2="692.625"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="61" x2="61" y1="692.625" y2="733.4297"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="61" x2="61" y1="733.4297" y2="743.4297"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="380" x2="380" y1="38.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="380" x2="380" y1="223.0938" y2="263.8984"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="380" x2="380" y1="263.8984" y2="692.625"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="380" x2="380" y1="692.625" y2="733.4297"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="380" x2="380" y1="733.4297" y2="743.4297"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="437" x2="437" y1="38.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="437" x2="437" y1="223.0938" y2="263.8984"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="437" x2="437" y1="263.8984" y2="692.625"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="437" x2="437" y1="692.625" y2="733.4297"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="437" x2="437" y1="733.4297" y2="743.4297"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="646" x2="646" y1="38.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="646" x2="646" y1="223.0938" y2="263.8984"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="646" x2="646" y1="263.8984" y2="692.625"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="646" x2="646" y1="692.625" y2="733.4297"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="646" x2="646" y1="733.4297" y2="743.4297"/><rect fill="#FEFECE" filter="url(#f18zq03ani7xpz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="87" x="16" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="73" x="23" y="22.9951">SDEI client</text><rect fill="#FEFECE" filter="url(#f18zq03ani7xpz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="87" x="16" y="742.4297"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="73" x="23" y="762.4248">SDEI client</text><rect fill="#FEFECE" filter="url(#f18zq03ani7xpz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="39" x="359" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="25" x="366" y="22.9951">EL3</text><rect fill="#FEFECE" filter="url(#f18zq03ani7xpz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="39" x="359" y="742.4297"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="25" x="366" y="762.4248">EL3</text><rect fill="#FEFECE" filter="url(#f18zq03ani7xpz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="46" x="412" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="32" x="419" y="22.9951">SDEI</text><rect fill="#FEFECE" filter="url(#f18zq03ani7xpz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="46" x="412" y="742.4297"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="32" x="419" y="762.4248">SDEI</text><rect fill="#FEFECE" filter="url(#f18zq03ani7xpz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="86" x="601" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="72" x="608" y="22.9951">RAS Driver</text><rect fill="#FEFECE" filter="url(#f18zq03ani7xpz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="86" x="601" y="742.4297"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="72" x="608" y="762.4248">RAS Driver</text><rect fill="#FFFFFF" filter="url(#f18zq03ani7xpz)" height="174.7969" style="stroke: #FFFFFF; stroke-width: 1.0;" width="10" x="56.5" y="48.2969"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="56.5" y1="48.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="66.5" y1="48.2969" y2="223.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="66.5" y1="48.2969" y2="48.2969"/><rect fill="#FFFFFF" filter="url(#f18zq03ani7xpz)" height="428.7266" style="stroke: #FFFFFF; stroke-width: 1.0;" width="10" x="56.5" y="263.8984"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="56.5" y1="263.8984" y2="692.625"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="66.5" y1="263.8984" y2="692.625"/><rect fill="#FFFFFF" filter="url(#f18zq03ani7xpz)" height="1" style="stroke: #FFFFFF; stroke-width: 1.0;" width="10" x="56.5" y="733.4297"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="56.5" x2="56.5" y1="733.4297" y2="734.4297"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="66.5" y1="733.4297" y2="734.4297"/><rect fill="#FA8072" filter="url(#f18zq03ani7xpz)" height="68.2656" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="61.5" y="489.8281"/><rect fill="#FF0000" filter="url(#f18zq03ani7xpz)" height="68.2656" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="375.5" y="285.0313"/><rect fill="#FA8072" filter="url(#f18zq03ani7xpz)" height="204.7969" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="432" y="421.5625"/><rect fill="#FA8072" filter="url(#f18zq03ani7xpz)" height="68.2656" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="641" y="353.2969"/><rect fill="#FA8072" filter="url(#f18zq03ani7xpz)" height="29.1328" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="641" y="626.3594"/><polygon fill="#A80036" points="368.5,65.4297,378.5,69.4297,368.5,73.4297,372.5,69.4297" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="374.5" y1="69.4297" y2="69.4297"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="73.5" y="64.3638">[1]</text><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="164" x="98.5" y="64.3638">SDEI_EVENT_REGISTER</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="101" x="262.5" y="64.3638">(ev, handler, ...)</text><polygon fill="#A80036" points="77.5,94.5625,67.5,98.5625,77.5,102.5625,73.5,98.5625" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="71.5" x2="379.5" y1="98.5625" y2="98.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="83.5" y="93.4966">[2]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="51" x="108.5" y="93.4966">success</text><polygon fill="#A80036" points="368.5,123.6953,378.5,127.6953,368.5,131.6953,372.5,127.6953" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="374.5" y1="127.6953" y2="127.6953"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="73.5" y="122.6294">[3]</text><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="151" x="98.5" y="122.6294">SDEI_EVENT_ENABLE</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="25" x="249.5" y="122.6294">(ev)</text><polygon fill="#A80036" points="77.5,152.8281,67.5,156.8281,77.5,160.8281,73.5,156.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="71.5" x2="379.5" y1="156.8281" y2="156.8281"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="83.5" y="151.7622">[4]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="51" x="108.5" y="151.7622">success</text><polygon fill="#A80036" points="368.5,181.9609,378.5,185.9609,368.5,189.9609,372.5,185.9609" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="374.5" y1="185.9609" y2="185.9609"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="73.5" y="180.895">[5]</text><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="129" x="98.5" y="180.895">SDEI_PE_UNMASK</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="10" x="227.5" y="180.895">()</text><polygon fill="#A80036" points="77.5,211.0938,67.5,215.0938,77.5,219.0938,73.5,215.0938" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="71.5" x2="379.5" y1="215.0938" y2="215.0938"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="83.5" y="210.0278">[6]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="8" x="108.5" y="210.0278">1</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="142" x="282.75" y="247.3042">&lt;&lt;Business as usual&gt;&gt;</text><polygon fill="#A80036" points="396.5,281.0313,386.5,285.0313,396.5,289.0313,392.5,285.0313" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 2.0,2.0;" x1="390.5" x2="733" y1="285.0313" y2="285.0313"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="402.5" y="279.9653">[7]</text><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="116" x="427.5" y="279.9653">CRITICAL EVENT</text><path d="M306,298.0313 L306,323.0313 L451,323.0313 L451,308.0313 L441,298.0313 L306,298.0313 " fill="#FBFB77" filter="url(#f18zq03ani7xpz)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M441,298.0313 L441,308.0313 L451,308.0313 L441,298.0313 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="124" x="312" y="315.0981">Critical event triage</text><polygon fill="#A80036" points="629,349.2969,639,353.2969,629,357.2969,633,353.2969" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="380.5" x2="635" y1="353.2969" y2="353.2969"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="387.5" y="348.231">[8]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="118" x="412.5" y="348.231">dispatch to handle</text><path d="M563,366.2969 L563,391.2969 L725,391.2969 L725,376.2969 L715,366.2969 L563,366.2969 " fill="#FBFB77" filter="url(#f18zq03ani7xpz)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M715,366.2969 L715,376.2969 L725,376.2969 L715,366.2969 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="141" x="569" y="383.3638">Critical event handling</text><polygon fill="#A80036" points="453,417.5625,443,421.5625,453,425.5625,449,421.5625" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 2.0,2.0;" x1="447" x2="645" y1="421.5625" y2="421.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="21" x="459" y="416.4966">[9]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="155" x="484" y="416.4966">sdei_dispatch_event(ev)</text><path d="M353,434.5625 L353,459.5625 L516,459.5625 L516,444.5625 L506,434.5625 L353,434.5625 " fill="#FBFB77" filter="url(#f18zq03ani7xpz)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M506,434.5625 L506,444.5625 L516,444.5625 L506,434.5625 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="142" x="359" y="451.6294">Prepare SDEI dispatch</text><polygon fill="#A80036" points="82.5,485.8281,72.5,489.8281,82.5,493.8281,78.5,489.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="76.5" x2="431" y1="489.8281" y2="489.8281"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="30" x="88.5" y="484.7622">[10]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="54" x="122.5" y="484.7622">dispatch</text><path d="M8,502.8281 L8,527.8281 L111,527.8281 L111,512.8281 L101,502.8281 L8,502.8281 " fill="#FBFB77" filter="url(#f18zq03ani7xpz)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M101,502.8281 L101,512.8281 L111,512.8281 L101,502.8281 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="82" x="14" y="519.895">SDEI handler</text><polygon fill="#A80036" points="420,554.0938,430,558.0938,420,562.0938,424,558.0938" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="66.5" x2="426" y1="558.0938" y2="558.0938"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="30" x="73.5" y="553.0278">[11]</text><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="184" x="107.5" y="553.0278">SDEI_EVENT_COMPLETE()</text><path d="M347,571.0938 L347,596.0938 L522,596.0938 L522,581.0938 L512,571.0938 L347,571.0938 " fill="#FBFB77" filter="url(#f18zq03ani7xpz)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M512,571.0938 L512,581.0938 L522,581.0938 L512,571.0938 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="154" x="353" y="588.1606">Complete SDEI dispatch</text><polygon fill="#A80036" points="629,622.3594,639,626.3594,629,630.3594,633,626.3594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 2.0,2.0;" x1="437" x2="635" y1="626.3594" y2="626.3594"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="30" x="444" y="621.2935">[12]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="39" x="478" y="621.2935">return</text><polygon fill="#A80036" points="391.5,651.4922,381.5,655.4922,391.5,659.4922,387.5,655.4922" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="385.5" x2="645" y1="655.4922" y2="655.4922"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="30" x="397.5" y="650.4263">[13]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="125" x="431.5" y="650.4263">error handling done</text><polygon fill="#A80036" points="77.5,680.625,67.5,684.625,77.5,688.625,73.5,684.625" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="71.5" x2="379.5" y1="684.625" y2="684.625"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="30" x="83.5" y="679.5591">[14]</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="197" x="117.5" y="679.5591">resumes preempted execution</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="190" x="258.75" y="716.8354">&lt;&lt;Normal execution resumes&gt;&gt;</text></g></svg>
\ No newline at end of file
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/synquacer.rst b/docs/plat/synquacer.rst
new file mode 100644
index 0000000..ca53deb
--- /dev/null
+++ b/docs/plat/synquacer.rst
@@ -0,0 +1,117 @@
+Trusted Firmware-A for Socionext Synquacer SoCs
+===============================================
+
+Socionext's Synquacer SC2A11 is a multi-core processor with 24 cores of Arm
+Cortex-A53. The Developerbox, of 96boards, is a platform that contains this
+processor. This port of the Trusted Firmware only supports this platform at
+the moment.
+
+More information are listed in `link`_.
+
+How to build
+============
+
+Code Locations
+--------------
+
+-  Trusted Firmware-A:
+   `link <https://github.com/ARM-software/arm-trusted-firmware>`__
+
+-  edk2:
+   `link <https://github.com/tianocore/edk2>`__
+
+-  edk2-platforms:
+   `link <https://github.com/tianocore/edk2-platforms>`__
+
+-  edk2-non-osi:
+   `link <https://github.com/tianocore/edk2-non-osi>`__
+
+Boot Flow
+---------
+
+SCP firmware --> TF-A BL31 --> UEFI(edk2)
+
+Build Procedure
+---------------
+
+-  Firstly, in addition to the “normal” build tools you will also need a
+   few specialist tools. On a Debian or Ubuntu operating system try:
+
+   .. code:: shell
+
+       sudo apt install acpica-tools device-tree-compiler uuid-dev
+
+-  Secondly, create a new working directory and store the absolute path to this
+   directory in an environment variable, WORKSPACE. It does not matter where
+   this directory is created but as an example:
+
+   .. code:: shell
+
+       export WORKSPACE=$HOME/build/developerbox-firmware
+       mkdir -p $WORKSPACE
+
+-  Run the following commands to clone the source code:
+
+   .. code:: shell
+
+       cd $WORKSPACE
+       git clone https://github.com/ARM-software/arm-trusted-firmware -b master
+       git clone https://github.com/tianocore/edk2.git -b master
+       git clone https://github.com/tianocore/edk2-platforms.git -b master
+       git clone https://github.com/tianocore/edk2-non-osi.git -b master
+
+-  Build ATF:
+
+   .. code:: shell
+
+       cd $WORKSPACE/arm-trusted-firmware
+       make -j`nproc` PLAT=synquacer PRELOADED_BL33_BASE=0x8200000 bl31 fiptool
+       tools/fiptool/fiptool create \
+             --tb-fw ./build/synquacer/release/bl31.bin \
+             --soc-fw ./build/synquacer/release/bl31.bin \
+             --scp-fw ./build/synquacer/release/bl31.bin \
+             ../edk2-non-osi/Platform/Socionext/DeveloperBox/fip_all_arm_tf.bin
+
+-  Build EDK2:
+
+   .. code:: shell
+
+       cd $WORKSPACE
+       export PACKAGES_PATH=$WORKSPACE/edk2:$WORKSPACE/edk2-platforms:$WORKSPACE/edk2-non-osi
+       export ACTIVE_PLATFORM="Platform/Socionext/DeveloperBox/DeveloperBox.dsc"
+       export GCC5_AARCH64_PREFIX=aarch64-linux-gnu-
+       unset ARCH
+
+       . edk2/edksetup.sh
+       make -C edk2/BaseTools
+
+       build -p $ACTIVE_PLATFORM -b RELEASE -a AARCH64 -t GCC5 -n `nproc` -D DO_X86EMU=TRUE
+
+-  The firmware image, which comprises the option ROM, ARM trusted firmware and
+   EDK2 itself, can be found $WORKSPACE/../Build/DeveloperBox/RELEASE_GCC5/FV/.
+   Use SYNQUACERFIRMWAREUPDATECAPSULEFMPPKCS7.Cap for UEFI capsule update and
+   SPI_NOR_IMAGE.fd for the serial flasher.
+
+   Note #1: -t GCC5 can be loosely translated as “enable link-time-optimization”;
+   any version of gcc >= 5 will support this feature and may be used to build EDK2.
+
+   Note #2: Replace -b RELEASE with -b DEBUG to build a debug.
+
+Install the System Firmware
+---------------------------
+
+-  Providing your Developerbox is fully working and has on operating system
+   installed then you can adopt your the newly compiled system firmware using
+   the capsule update method:.
+
+   .. code:: shell
+
+       sudo apt install fwupdate
+       sudo fwupdate --apply {50b94ce5-8b63-4849-8af4-ea479356f0e3} \
+                     SYNQUACERFIRMWAREUPDATECAPSULEFMPPKCS7.Cap
+       sudo reboot
+
+-  Alternatively you can install SPI_NOR_IMAGE.fd using the `board recovery method`_.
+
+.. _link: https://www.96boards.org/product/developerbox/
+.. _board recovery method: https://www.96boards.org/documentation/enterprise/developerbox/installation/board-recovery.md.html
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/docs/sdei.rst b/docs/sdei.rst
index b81e21a..531145f 100644
--- a/docs/sdei.rst
+++ b/docs/sdei.rst
@@ -48,8 +48,10 @@
 original EL2 execution [13]. Note that the SDEI interrupt remains active until
 the client handler completes, at which point EL3 does EOI [12].
 
-SDEI events can be explicitly dispatched in response to other asynchronous
-exceptions. See `Explicit dispatch of events`_.
+Other than events bound to interrupts (as depicted in the sequence above, SDEI
+events can be explicitly dispatched in response to other exceptions, for
+example, upon receiving an *SError* or *Synchronous External Abort*. See
+`Explicit dispatch of events`_.
 
 The remainder of this document only discusses the design and implementation of
 SDEI dispatcher in TF-A, and assumes that the reader is familiar with the SDEI
@@ -71,7 +73,8 @@
 
 -  The event number: this must be a positive 32-bit integer.
 
--  The interrupt number the event is bound to:
+-  For an event that has a backing interrupt, the interrupt number the event is
+   bound to:
 
    - If it's not applicable to an event, this shall be left as ``0``.
 
@@ -82,6 +85,17 @@
 To define event 0, the macro ``SDEI_DEFINE_EVENT_0()`` should be used. This
 macro takes only one parameter: an SGI number to signal other PEs.
 
+To define an event that's meant to be `explicitly dispatched`__ (i.e., not as a
+result of receiving an SDEI interrupt), the macro ``SDEI_EXPLICIT_EVENT()``
+should be used. It accepts two parameters:
+
+.. __: `Explicit dispatch of events`_
+
+-  The event number (as above);
+
+-  Event priority: ``SDEI_MAPF_CRITICAL`` or ``SDEI_MAPF_NORMAL``, as described
+   below.
+
 Once the event descriptor arrays are defined, they should be exported to the
 SDEI dispatcher using the ``REGISTER_SDEI_MAP()`` macro, passing it the pointers
 to the private and shared event descriptor arrays, respectively. Note that the
@@ -99,6 +113,8 @@
 
    - Must be bound to a Secure SGI on the platform.
 
+-  Explicit events should only be used in the private array.
+
 -  Statically bound shared and private interrupts must be bound to shared and
    private interrupts on the platform, respectively. See the section on
    `interrupt configuration`__.
@@ -132,8 +148,10 @@
 -  ``SDEI_MAPF_BOUND``: Marks the event as statically bound to an interrupt.
    These events cannot be re-bound at runtime.
 
+-  ``SDEI_MAPF_NORMAL``: Marks the event as having *Normal* priority. This is
+   the default priority.
+
 -  ``SDEI_MAPF_CRITICAL``: Marks the event as having *Critical* priority.
-   Without this flag, the event is assumed to have *Normal* priority.
 
 Event definition example
 ------------------------
@@ -150,6 +168,10 @@
         /* Dynamic private events */
         SDEI_PRIVATE_EVENT(100, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
         SDEI_PRIVATE_EVENT(101, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)
+
+        /* Events for explicit dispatch */
+        SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_NORMAL);
+        SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_CRITICAL);
    };
 
    /* Shared event mappings */
@@ -211,14 +233,10 @@
 
 ::
 
-        int sdei_dispatch_event(int ev_num, unsigned int preempted_sec_state);
+        int sdei_dispatch_event(int ev_num);
 
--  The parameter ``ev_num`` is the event number to dispatch;
-
--  The parameter ``preempted_sec_state`` indicates the context that was
-   preempted. This must be either ``SECURE`` or ``NON_SECURE``.
-
-The API returns ``0`` on success, or ``-1`` on failure.
+The parameter ``ev_num`` is the event number to dispatch. The API returns ``0``
+on success, or ``-1`` on failure.
 
 The following figure depicts a scenario involving explicit dispatch of SDEI
 event. A commentary is provided below:
@@ -231,22 +249,18 @@
 bound or dynamic events can't be explicitly dispatched (see the section below).
 
 At a later point in time, a critical event [#critical-event]_ is trapped into
-EL3 [7]. EL3 performs a first-level triage of the event, and decides to dispatch
-to a Secure Partition [#secpart]_ for further handling [8]. The dispatch
-completes, but intends to involve Non-secure world in further handling, and
-therefore decides to explicitly dispatch an event [10] (which the client had
-already registered for [1]). The rest of the sequence is similar to that in the
-`general SDEI dispatch`_: the requested event is dispatched to the client
-(assuming all the conditions are met), and when the handler completes, the
-preempted execution resumes.
+EL3 [7]. EL3 performs a first-level triage of the event, and a RAS component
+assumes further handling [8]. The dispatch completes, but intends to involve
+Non-secure world in further handling, and therefore decides to explicitly
+dispatch an event [10] (which the client had already registered for [1]). The
+rest of the sequence is similar to that in the `general SDEI dispatch`_: the
+requested event is dispatched to the client (assuming all the conditions are
+met), and when the handler completes, the preempted execution resumes.
 
 .. [#critical-event] Examples of critical event are *SError*, *Synchronous
                      External Abort*, *Fault Handling interrupt*, or *Error
                      Recovery interrupt* from one of RAS nodes in the system.
 
-.. [#secpart] Dispatching to Secure Partition involves *Secure Partition
-              Manager*, which isn't depicted in the sequence.
-
 Conditions for event dispatch
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -258,7 +272,8 @@
 
 -  Event 0 can't be dispatched.
 
--  The event must neither be a dynamic event nor be bound to an interrupt.
+-  The event must be declared using the ``SDEI_EXPLICIT_EVENT()`` macro
+   described above.
 
 -  The event must be private to the PE.
 
@@ -279,28 +294,22 @@
 Further, the caller should be aware of the following assumptions made by the
 dispatcher:
 
--  The caller of the API is a component running in EL3; for example, the *Secure
-   Partition Manager*.
+-  The caller of the API is a component running in EL3; for example, a RAS
+   driver.
 
 -  The requested dispatch will be permitted by the Exception Handling Framework.
    I.e. the caller must make sure that the requested dispatch has sufficient
    priority so as not to cause priority level inversion within Exception
    Handling Framework.
 
--  At the time of the call, the active context is Secure, and it has been saved.
+-  The caller must be prepared for the SDEI dispatcher to restore the Non-secure
+   context, and mark that the active context.
 
--  Upon returning success, the Non-secure context will be restored and setup for
-   the event dispatch, and it will be the active context. The Non-secure context
-   should not be modified further by the caller.
+-  The call will block until the SDEI client completes the event (i.e. when the
+   client calls either ``SDEI_EVENT_COMPLETE`` or ``SDEI_COMPLETE_AND_RESUME``).
 
--  The API returning success only means that the dispatch is scheduled at the
-   next ``ERET``, and not immediately performed. Also, the caller must be
-   prepared for this API to return failure and handle accordingly.
-
--  Upon completing the event (i.e. when the client calls either
-   ``SDEI_EVENT_COMPLETE`` or ``SDEI_COMPLETE_AND_RESUME``), the preempted
-   context is resumed (as indicated by the ``preempted_sec_state`` parameter of
-   the API).
+-  The caller must be prepared for this API to return failure and handle
+   accordingly.
 
 Porting requirements
 --------------------
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index f6d0c76..c7f7ef8 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -486,8 +486,8 @@
    ::
 
        0  (LOG_LEVEL_NONE)
-       10 (LOG_LEVEL_NOTICE)
-       20 (LOG_LEVEL_ERROR)
+       10 (LOG_LEVEL_ERROR)
+       20 (LOG_LEVEL_NOTICE)
        30 (LOG_LEVEL_WARNING)
        40 (LOG_LEVEL_INFO)
        50 (LOG_LEVEL_VERBOSE)
@@ -1074,7 +1074,7 @@
    is important to use a version that is compatible with TF-A and fixes any
    known security vulnerabilities. See `mbed TLS Security Center`_ for more
    information. The latest version of TF-A is tested with tag
-   ``mbedtls-2.6.0``.
+   ``mbedtls-2.10.0``.
 
    The ``drivers/auth/mbedtls/mbedtls_*.mk`` files contain the list of mbed TLS
    source files the modules depend upon.
diff --git a/docs/xlat-tables-lib-v2-design.rst b/docs/xlat-tables-lib-v2-design.rst
index d256b6b..d207f30 100644
--- a/docs/xlat-tables-lib-v2-design.rst
+++ b/docs/xlat-tables-lib-v2-design.rst
@@ -79,9 +79,9 @@
 normal memory) as well as the memory access permissions (read-only or
 read-write, executable or not, secure or non-secure, and so on). In the case of
 the EL1&0 translation regime, the attributes also specify whether the region is
-a User region (EL0) or Privileged region (EL1). See the ``mmap_attr_t``
-enumeration type in `xlat\_tables\_v2.h`_. Note that for the EL1&0 translation
-regime the Execute Never attribute is set simultaneously for both EL1 and EL0.
+a User region (EL0) or Privileged region (EL1). See the ``MT_xxx`` definitions
+in `xlat\_tables\_v2.h`_. Note that for the EL1&0 translation regime the Execute
+Never attribute is set simultaneously for both EL1 and EL0.
 
 The granularity controls the translation table level to go down to when mapping
 the region. For example, assuming the MMU has been configured to use a 4KB
diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk
index 8c4123d..a5d19e6 100644
--- a/drivers/auth/mbedtls/mbedtls_common.mk
+++ b/drivers/auth/mbedtls/mbedtls_common.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -27,6 +27,8 @@
 				memory_buffer_alloc.c			\
 				oid.c 					\
 				platform.c 				\
+				platform_util.c				\
+				rsa_internal.c				\
 				)
 
 endif
diff --git a/drivers/ti/uart/aarch64/16550_console.S b/drivers/ti/uart/aarch64/16550_console.S
index 56e7e5c..d46fa61 100644
--- a/drivers/ti/uart/aarch64/16550_console.S
+++ b/drivers/ti/uart/aarch64/16550_console.S
@@ -66,6 +66,10 @@
 	/* no interrupt */
 	mov	w3, #0
 	str	w3, [x0, #UARTIER]
+#ifdef TI_16550_MDR_QUIRK
+	/* UART must be enabled on some platforms via the MDR register */
+	str	w3, [x0, #UARTMDR1]
+#endif /* TI_16550_MDR_QUIRK */
 	/* enable fifo, DMA */
 	mov	w3, #(UARTFCR_FIFOEN | UARTFCR_DMAEN)
 	str	w3, [x0, #UARTFCR]
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/drivers/ti/uart/uart_16550.h b/include/drivers/ti/uart/uart_16550.h
index 9eba41a..b00f664 100644
--- a/include/drivers/ti/uart/uart_16550.h
+++ b/include/drivers/ti/uart/uart_16550.h
@@ -23,6 +23,8 @@
 #define UARTMSR			0x18
 #define UARTSPR			0x1c
 #define UARTCSR			0x20
+/* Some instances have MDR1 defined as well */
+#define UARTMDR1		0x20
 #define UARTRXFIFOCFG		0x24
 #define UARTMIE			0x28
 #define UARTVNDR		0x2c
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/aarch64/setjmp.h b/include/lib/aarch64/setjmp.h
new file mode 100644
index 0000000..c65810d
--- /dev/null
+++ b/include/lib/aarch64/setjmp.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __JMP_H__
+#define __JMP_H__
+
+#define JMP_CTX_X19	0x0
+#define JMP_CTX_X21	0x10
+#define JMP_CTX_X23	0x20
+#define JMP_CTX_X25	0x30
+#define JMP_CTX_X27	0x40
+#define JMP_CTX_X29	0x50
+#define JMP_CTX_SP	0x60
+#define JMP_CTX_END	0x70
+
+#define JMP_SIZE	(JMP_CTX_END >> 3)
+
+#ifndef __ASSEMBLY__
+
+#include <stdint.h>
+
+/* Jump buffer hosting x18 - x30 and sp_el0 registers */
+struct jmpbuf {
+	uint64_t buf[JMP_SIZE];
+} __aligned(16);
+
+
+/*
+ * Set a jump point, and populate the jump buffer with context information so
+ * that longjmp() can jump later. The caller must adhere to the following
+ * conditions:
+ *
+ *  - After calling this function, the stack must not be shrunk. The contents of
+ *    the stack must not be changed either.
+ *
+ *  - If the caller were to 'return', the buffer must be considered invalid, and
+ *    must not be used with longjmp().
+ *
+ * The caller will observe this function returning at two distinct
+ * circumstances, each with different return values:
+ *
+ *  - Zero, when the buffer is setup;
+ *
+ *  - Non-zero, when a call to longjmp() is made (presumably by one of the
+ *    callee functions) with the same jump buffer.
+ */
+int setjmp(struct jmpbuf *buf);
+
+/*
+ * Reset execution to a jump point, and restore context information according to
+ * the jump buffer populated by setjmp().
+ */
+void longjmp(struct jmpbuf *buf);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __JMP_H__ */
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/lib/xlat_tables/xlat_mmu_helpers.h b/include/lib/xlat_tables/xlat_mmu_helpers.h
index d83d764..7795317 100644
--- a/include/lib/xlat_tables/xlat_mmu_helpers.h
+++ b/include/lib/xlat_tables/xlat_mmu_helpers.h
@@ -43,6 +43,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <sys/types.h>
+
 #ifdef AARCH32
 /* AArch32 specific translation table API */
 void enable_mmu_secure(unsigned int flags);
@@ -52,6 +54,9 @@
 void enable_mmu_el3(unsigned int flags);
 #endif /* AARCH32 */
 
+int xlat_arch_is_granule_size_supported(size_t size);
+size_t xlat_arch_get_max_supported_granule_size(void);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __XLAT_MMU_HELPERS_H__ */
diff --git a/include/lib/xlat_tables/xlat_tables.h b/include/lib/xlat_tables/xlat_tables.h
index 91f2f05..c017e19 100644
--- a/include/lib/xlat_tables/xlat_tables.h
+++ b/include/lib/xlat_tables/xlat_tables.h
@@ -25,7 +25,7 @@
 #define MAP_REGION(pa, va, sz, attr) {(pa), (va), (sz), (attr)}
 
 /*
- * Shifts and masks to access fields of an mmap_attr_t
+ * Shifts and masks to access fields of an mmap attribute
  */
 #define MT_TYPE_MASK	U(0x7)
 #define MT_TYPE(_attr)	((_attr) & MT_TYPE_MASK)
@@ -39,37 +39,41 @@
 /*
  * Memory mapping attributes
  */
-typedef enum  {
-	/*
-	 * Memory types supported.
-	 * These are organised so that, going down the list, the memory types
-	 * are getting weaker; conversely going up the list the memory types are
-	 * getting stronger.
-	 */
-	MT_DEVICE,
-	MT_NON_CACHEABLE,
-	MT_MEMORY,
-	/* Values up to 7 are reserved to add new memory types in the future */
 
-	MT_RO		= U(0) << MT_PERM_SHIFT,
-	MT_RW		= U(1) << MT_PERM_SHIFT,
+/*
+ * Memory types supported.
+ * These are organised so that, going down the list, the memory types are
+ * getting weaker; conversely going up the list the memory types are getting
+ * stronger.
+ */
+#define MT_DEVICE		U(0)
+#define MT_NON_CACHEABLE	U(1)
+#define MT_MEMORY		U(2)
+/* Values up to 7 are reserved to add new memory types in the future */
 
-	MT_SECURE	= U(0) << MT_SEC_SHIFT,
-	MT_NS		= U(1) << MT_SEC_SHIFT,
+#define MT_RO			(U(0) << MT_PERM_SHIFT)
+#define MT_RW			(U(1) << MT_PERM_SHIFT)
 
-	/*
-	 * Access permissions for instruction execution are only relevant for
-	 * normal read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored
-	 * (and potentially overridden) otherwise:
-	 *  - Device memory is always marked as execute-never.
-	 *  - Read-write normal memory is always marked as execute-never.
-	 */
-	MT_EXECUTE		= U(0) << MT_EXECUTE_SHIFT,
-	MT_EXECUTE_NEVER	= U(1) << MT_EXECUTE_SHIFT,
-} mmap_attr_t;
+#define MT_SECURE		(U(0) << MT_SEC_SHIFT)
+#define MT_NS			(U(1) << MT_SEC_SHIFT)
 
-#define MT_CODE		(MT_MEMORY | MT_RO | MT_EXECUTE)
-#define MT_RO_DATA	(MT_MEMORY | MT_RO | MT_EXECUTE_NEVER)
+/*
+ * Access permissions for instruction execution are only relevant for normal
+ * read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored (and potentially
+ * overridden) otherwise:
+ *  - Device memory is always marked as execute-never.
+ *  - Read-write normal memory is always marked as execute-never.
+ */
+#define MT_EXECUTE		(U(0) << MT_EXECUTE_SHIFT)
+#define MT_EXECUTE_NEVER	(U(1) << MT_EXECUTE_SHIFT)
+
+/* Compound attributes for most common usages */
+#define MT_CODE			(MT_MEMORY | MT_RO | MT_EXECUTE)
+#define MT_RO_DATA		(MT_MEMORY | MT_RO | MT_EXECUTE_NEVER)
+
+#if !ERROR_DEPRECATED
+typedef unsigned int mmap_attr_t;
+#endif
 
 /*
  * Structure for specifying a single region of memory.
@@ -78,13 +82,13 @@
 	unsigned long long	base_pa;
 	uintptr_t		base_va;
 	size_t			size;
-	mmap_attr_t		attr;
+	unsigned int		attr;
 } mmap_region_t;
 
 /* Generic translation table APIs */
 void init_xlat_tables(void);
 void mmap_add_region(unsigned long long base_pa, uintptr_t base_va,
-				size_t size, mmap_attr_t attr);
+		     size_t size, unsigned int attr);
 void mmap_add(const mmap_region_t *mm);
 
 #endif /*__ASSEMBLY__*/
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index b237945..98f00d7 100644
--- a/include/lib/xlat_tables/xlat_tables_v2.h
+++ b/include/lib/xlat_tables/xlat_tables_v2.h
@@ -47,7 +47,7 @@
 	_MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, _gr)
 
 /*
- * Shifts and masks to access fields of an mmap_attr_t
+ * Shifts and masks to access fields of an mmap attribute
  */
 #define MT_TYPE_MASK		U(0x7)
 #define MT_TYPE(_attr)		((_attr) & MT_TYPE_MASK)
@@ -57,57 +57,56 @@
 #define MT_SEC_SHIFT		U(4)
 /* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */
 #define MT_EXECUTE_SHIFT	U(5)
-/*
- * In the EL1&0 translation regime, mark the region as User (EL0) or
- * Privileged (EL1). In the EL3 translation regime this has no effect.
- */
+/* In the EL1&0 translation regime, User (EL0) or Privileged (EL1). */
 #define MT_USER_SHIFT		U(6)
 /* All other bits are reserved */
 
 /*
  * Memory mapping attributes
  */
-typedef enum  {
-	/*
-	 * Memory types supported.
-	 * These are organised so that, going down the list, the memory types
-	 * are getting weaker; conversely going up the list the memory types are
-	 * getting stronger.
-	 */
-	MT_DEVICE,
-	MT_NON_CACHEABLE,
-	MT_MEMORY,
-	/* Values up to 7 are reserved to add new memory types in the future */
 
-	MT_RO		= U(0) << MT_PERM_SHIFT,
-	MT_RW		= U(1) << MT_PERM_SHIFT,
+/*
+ * Memory types supported.
+ * These are organised so that, going down the list, the memory types are
+ * getting weaker; conversely going up the list the memory types are getting
+ * stronger.
+ */
+#define MT_DEVICE		U(0)
+#define MT_NON_CACHEABLE	U(1)
+#define MT_MEMORY		U(2)
+/* Values up to 7 are reserved to add new memory types in the future */
 
-	MT_SECURE	= U(0) << MT_SEC_SHIFT,
-	MT_NS		= U(1) << MT_SEC_SHIFT,
+#define MT_RO			(U(0) << MT_PERM_SHIFT)
+#define MT_RW			(U(1) << MT_PERM_SHIFT)
 
-	/*
-	 * Access permissions for instruction execution are only relevant for
-	 * normal read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored
-	 * (and potentially overridden) otherwise:
-	 *  - Device memory is always marked as execute-never.
-	 *  - Read-write normal memory is always marked as execute-never.
-	 */
-	MT_EXECUTE		= U(0) << MT_EXECUTE_SHIFT,
-	MT_EXECUTE_NEVER	= U(1) << MT_EXECUTE_SHIFT,
+#define MT_SECURE		(U(0) << MT_SEC_SHIFT)
+#define MT_NS			(U(1) << MT_SEC_SHIFT)
 
-	/*
-	 * When mapping a region at EL0 or EL1, this attribute will be used to
-	 * determine if a User mapping (EL0) will be created or a Privileged
-	 * mapping (EL1).
-	 */
-	MT_USER				= U(1) << MT_USER_SHIFT,
-	MT_PRIVILEGED			= U(0) << MT_USER_SHIFT,
-} mmap_attr_t;
+/*
+ * Access permissions for instruction execution are only relevant for normal
+ * read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored (and potentially
+ * overridden) otherwise:
+ *  - Device memory is always marked as execute-never.
+ *  - Read-write normal memory is always marked as execute-never.
+ */
+#define MT_EXECUTE		(U(0) << MT_EXECUTE_SHIFT)
+#define MT_EXECUTE_NEVER	(U(1) << MT_EXECUTE_SHIFT)
+
+/*
+ * When mapping a region at EL0 or EL1, this attribute will be used to determine
+ * if a User mapping (EL0) will be created or a Privileged mapping (EL1).
+ */
+#define MT_USER			(U(1) << MT_USER_SHIFT)
+#define MT_PRIVILEGED		(U(0) << MT_USER_SHIFT)
 
 /* Compound attributes for most common usages */
-#define MT_CODE		(MT_MEMORY | MT_RO | MT_EXECUTE)
-#define MT_RO_DATA	(MT_MEMORY | MT_RO | MT_EXECUTE_NEVER)
-#define MT_RW_DATA	(MT_MEMORY | MT_RW | MT_EXECUTE_NEVER)
+#define MT_CODE			(MT_MEMORY | MT_RO | MT_EXECUTE)
+#define MT_RO_DATA		(MT_MEMORY | MT_RO | MT_EXECUTE_NEVER)
+#define MT_RW_DATA		(MT_MEMORY | MT_RW | MT_EXECUTE_NEVER)
+
+#if !ERROR_DEPRECATED
+typedef unsigned int mmap_attr_t;
+#endif
 
 /*
  * Structure for specifying a single region of memory.
@@ -116,7 +115,7 @@
 	unsigned long long	base_pa;
 	uintptr_t		base_va;
 	size_t			size;
-	mmap_attr_t		attr;
+	unsigned int		attr;
 	/* Desired granularity. See the MAP_REGION2() macro for more details. */
 	size_t			granularity;
 } mmap_region_t;
@@ -213,7 +212,7 @@
  * removed afterwards.
  */
 void mmap_add_region(unsigned long long base_pa, uintptr_t base_va,
-				size_t size, mmap_attr_t attr);
+		     size_t size, unsigned int attr);
 void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm);
 
 /*
@@ -238,7 +237,7 @@
  *    EPERM: It overlaps another region in an invalid way.
  */
 int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va,
-				size_t size, mmap_attr_t attr);
+			    size_t size, unsigned int attr);
 int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm);
 
 /*
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index 2d8e4c1..96eefbb 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -87,9 +87,9 @@
  * little space for growth.
  */
 #if TRUSTED_BOARD_BOOT
-# define PLAT_ARM_MAX_BL2_SIZE		0x1E000
+# define PLAT_ARM_MAX_BL2_SIZE		0x1F000
 #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 d87fc16..e3d0edb 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -245,13 +245,7 @@
  * The number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
  */
-#if ENABLE_SPM && defined(IMAGE_BL31)
-# if USE_COHERENT_MEM
-#  define ARM_BL_REGIONS		5
-# else
-#  define ARM_BL_REGIONS		4
-# endif
-#elif USE_COHERENT_MEM
+#if USE_COHERENT_MEM
 # define ARM_BL_REGIONS			4
 #else
 # define ARM_BL_REGIONS			3
@@ -264,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/include/services/sdei.h b/include/services/sdei.h
index ce9a008..79d1d06 100644
--- a/include/services/sdei.h
+++ b/include/services/sdei.h
@@ -1,5 +1,5 @@
 /*
- * 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
  */
@@ -52,6 +52,7 @@
 #define _SDEI_MAPF_SIGNALABLE_SHIFT	3
 #define _SDEI_MAPF_PRIVATE_SHIFT	4
 #define _SDEI_MAPF_CRITICAL_SHIFT	5
+#define _SDEI_MAPF_EXPLICIT_SHIFT	6
 
 /* SDEI event 0 */
 #define SDEI_EVENT_0	0
@@ -81,9 +82,12 @@
  */
 #define SDEI_MAPF_DYNAMIC	BIT(_SDEI_MAPF_DYNAMIC_SHIFT)
 #define SDEI_MAPF_BOUND		BIT(_SDEI_MAPF_BOUND_SHIFT)
+#define SDEI_MAPF_EXPLICIT	BIT(_SDEI_MAPF_EXPLICIT_SHIFT)
 
 #define SDEI_MAPF_SIGNALABLE	BIT(_SDEI_MAPF_SIGNALABLE_SHIFT)
 #define SDEI_MAPF_PRIVATE	BIT(_SDEI_MAPF_PRIVATE_SHIFT)
+
+#define SDEI_MAPF_NORMAL	0
 #define SDEI_MAPF_CRITICAL	BIT(_SDEI_MAPF_CRITICAL_SHIFT)
 
 /* Indices of private and shared mappings */
@@ -114,6 +118,9 @@
 #define SDEI_DEFINE_EVENT_0(_intr) \
 	SDEI_PRIVATE_EVENT(SDEI_EVENT_0, _intr, SDEI_MAPF_SIGNALABLE)
 
+#define SDEI_EXPLICIT_EVENT(_event, _pri) \
+	SDEI_EVENT_MAP(_event, 0, _pri | SDEI_MAPF_EXPLICIT | SDEI_MAPF_PRIVATE)
+
 /*
  * Declare shared and private entries for each core. Also declare a global
  * structure containing private and share entries.
@@ -176,6 +183,6 @@
 void sdei_init(void);
 
 /* Public API to dispatch an event to Normal world */
-int sdei_dispatch_event(int ev_num, unsigned int preempted_sec_state);
+int sdei_dispatch_event(int ev_num);
 
 #endif /* __SDEI_H__ */
diff --git a/include/services/secure_partition.h b/include/services/secure_partition.h
index f1fdb73..d4aff1c 100644
--- a/include/services/secure_partition.h
+++ b/include/services/secure_partition.h
@@ -7,18 +7,9 @@
 #ifndef __SECURE_PARTITION_H__
 #define __SECURE_PARTITION_H__
 
-#include <bl_common.h>
 #include <types.h>
 #include <utils_def.h>
 
-/* Import linker symbols */
-IMPORT_SYM(uintptr_t, __SP_IMAGE_XLAT_TABLES_START__,	SP_IMAGE_XLAT_TABLES_START);
-IMPORT_SYM(uintptr_t, __SP_IMAGE_XLAT_TABLES_END__,	SP_IMAGE_XLAT_TABLES_END);
-
-/* Definitions */
-#define SP_IMAGE_XLAT_TABLES_SIZE	\
-	(SP_IMAGE_XLAT_TABLES_END - SP_IMAGE_XLAT_TABLES_START)
-
 /*
  * Flags used by the secure_partition_mp_info structure to describe the
  * characteristics of a cpu. Only a single flag is defined at the moment to
diff --git a/include/services/spm_svc.h b/include/services/spm_svc.h
index 8f872c3..0200992 100644
--- a/include/services/spm_svc.h
+++ b/include/services/spm_svc.h
@@ -74,6 +74,9 @@
 			 void *handle,
 			 uint64_t flags);
 
+/* Helper to enter a Secure Partition */
+uint64_t spm_sp_call(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __SPM_SVC_H__ */
diff --git a/lib/aarch64/setjmp.S b/lib/aarch64/setjmp.S
new file mode 100644
index 0000000..9060cb7
--- /dev/null
+++ b/lib/aarch64/setjmp.S
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <setjmp.h>
+
+	.globl	setjmp
+	.globl	longjmp
+
+/*
+ * int setjmp(struct jmpbuf *buf);
+ *
+ * Sets a jump point in the buffer specified in x0. Returns 0 to the caller when
+ * when setting up the jump, and 1 when returning from the jump.
+ */
+func setjmp
+	mov	x7, sp
+
+	stp	x19, x20, [x0, #JMP_CTX_X19]
+	stp	x21, x22, [x0, #JMP_CTX_X21]
+	stp	x23, x24, [x0, #JMP_CTX_X23]
+	stp	x25, x26, [x0, #JMP_CTX_X25]
+	stp	x27, x28, [x0, #JMP_CTX_X27]
+	stp	x29, x30, [x0, #JMP_CTX_X29]
+	stp	x7, xzr, [x0, #JMP_CTX_SP]
+
+	mov	x0, #0
+	ret
+endfunc setjmp
+
+
+/*
+ * void longjmp(struct jmpbuf *buf);
+ *
+ * Return to a jump point setup by setjmp()
+ */
+func longjmp
+	ldp	x7, xzr, [x0, #JMP_CTX_SP]
+
+#if ENABLE_ASSERTIONS
+	/*
+	 * Since we're unwinding the stack, assert that the stack being reset to
+	 * is shallower.
+	 */
+	mov	x19, sp
+	cmp	x7, x19
+	ASM_ASSERT(ge)
+#endif
+
+	ldp	x19, x20, [x0, #JMP_CTX_X19]
+	ldp	x21, x22, [x0, #JMP_CTX_X21]
+	ldp	x23, x24, [x0, #JMP_CTX_X23]
+	ldp	x25, x26, [x0, #JMP_CTX_X25]
+	ldp	x27, x28, [x0, #JMP_CTX_X27]
+	ldp	x29, x30, [x0, #JMP_CTX_X29]
+
+	mov	sp, x7
+
+	mov	x0, #1
+	ret
+endfunc longjmp
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/utils/mem_region.c b/lib/utils/mem_region.c
index 24c2c1d..e9541ba 100644
--- a/lib/utils/mem_region.c
+++ b/lib/utils/mem_region.c
@@ -58,7 +58,7 @@
 	uintptr_t begin;
 	int r;
 	size_t size;
-	const mmap_attr_t attr = MT_MEMORY|MT_RW|MT_NS;
+	const unsigned int attr = MT_MEMORY | MT_RW | MT_NS;
 
 	assert(regions != NULL);
 	assert(nregions > 0 && chunk > 0);
diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c
index 21bf489..b42cd68 100644
--- a/lib/xlat_tables/xlat_tables_common.c
+++ b/lib/xlat_tables/xlat_tables_common.c
@@ -66,7 +66,7 @@
 }
 
 void mmap_add_region(unsigned long long base_pa, uintptr_t base_va,
-			size_t size, mmap_attr_t attr)
+		     size_t size, unsigned int attr)
 {
 	mmap_region_t *mm = mmap;
 	mmap_region_t *mm_last = mm + ARRAY_SIZE(mmap) - 1;
@@ -178,8 +178,8 @@
 	}
 }
 
-static uint64_t mmap_desc(mmap_attr_t attr, unsigned long long addr_pa,
-							unsigned int level)
+static uint64_t mmap_desc(unsigned int attr, unsigned long long addr_pa,
+			  unsigned int level)
 {
 	uint64_t desc;
 	int mem_type;
@@ -264,7 +264,7 @@
  * value pointed by attr should be ignored by the caller.
  */
 static int mmap_region_attr(mmap_region_t *mm, uintptr_t base_va,
-					size_t size, mmap_attr_t *attr)
+			    size_t size, unsigned int *attr)
 {
 	/* Don't assume that the area is contained in the first region */
 	int ret = -1;
@@ -348,7 +348,7 @@
 			 * there are partially overlapping regions. On success,
 			 * it will return the innermost region's attributes.
 			 */
-			mmap_attr_t attr;
+			unsigned int attr;
 			int r = mmap_region_attr(mm, base_va, level_size, &attr);
 
 			if (!r) {
diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
index 7d67a4a..f66f802 100644
--- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
@@ -18,6 +18,23 @@
 #error ARMv7 target does not support LPAE MMU descriptors
 #endif
 
+/*
+ * Returns 1 if the provided granule size is supported, 0 otherwise.
+ */
+int xlat_arch_is_granule_size_supported(size_t size)
+{
+	/*
+	 * The Trusted Firmware uses long descriptor translation table format,
+	 * which supports 4 KiB pages only.
+	 */
+	return (size == (4U * 1024U));
+}
+
+size_t xlat_arch_get_max_supported_granule_size(void)
+{
+	return 4U * 1024U;
+}
+
 #if ENABLE_ASSERTIONS
 unsigned long long xlat_arch_get_max_supported_pa(void)
 {
diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
index b3504e1..c501e70 100644
--- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
@@ -16,6 +16,42 @@
 #include <xlat_tables_v2.h>
 #include "../xlat_tables_private.h"
 
+/*
+ * Returns 1 if the provided granule size is supported, 0 otherwise.
+ */
+int xlat_arch_is_granule_size_supported(size_t size)
+{
+	u_register_t id_aa64mmfr0_el1 = read_id_aa64mmfr0_el1();
+
+	if (size == (4U * 1024U)) {
+		return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN4_SHIFT) &
+			 ID_AA64MMFR0_EL1_TGRAN4_MASK) ==
+			 ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED;
+	} else if (size == (16U * 1024U)) {
+		return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN16_SHIFT) &
+			 ID_AA64MMFR0_EL1_TGRAN16_MASK) ==
+			 ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED;
+	} else if (size == (64U * 1024U)) {
+		return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN64_SHIFT) &
+			 ID_AA64MMFR0_EL1_TGRAN64_MASK) ==
+			 ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED;
+	}
+
+	return 0;
+}
+
+size_t xlat_arch_get_max_supported_granule_size(void)
+{
+	if (xlat_arch_is_granule_size_supported(64U * 1024U)) {
+		return 64U * 1024U;
+	} else if (xlat_arch_is_granule_size_supported(16U * 1024U)) {
+		return 16U * 1024U;
+	} else {
+		assert(xlat_arch_is_granule_size_supported(4U * 1024U));
+		return 4U * 1024U;
+	}
+}
+
 unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr)
 {
 	/* Physical address can't exceed 48 bits */
diff --git a/lib/xlat_tables_v2/xlat_tables_internal.c b/lib/xlat_tables_v2/xlat_tables_internal.c
index 31d3365..5beb51e 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;
 
 	/*
@@ -823,10 +823,8 @@
 		ctx->max_va = end_va;
 }
 
-void mmap_add_region(unsigned long long base_pa,
-				uintptr_t base_va,
-				size_t size,
-				mmap_attr_t attr)
+void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, size_t size,
+		     unsigned int attr)
 {
 	mmap_region_t mm = MAP_REGION(base_pa, base_va, size, attr);
 	mmap_add_region_ctx(&tf_xlat_ctx, &mm);
@@ -947,8 +945,8 @@
 	return 0;
 }
 
-int mmap_add_dynamic_region(unsigned long long base_pa,
-			    uintptr_t base_va, size_t size, mmap_attr_t attr)
+int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va,
+			    size_t size, unsigned int attr)
 {
 	mmap_region_t mm = MAP_REGION(base_pa, base_va, size, attr);
 	return mmap_add_dynamic_region_ctx(&tf_xlat_ctx, &mm);
@@ -1087,13 +1085,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/lib/xlat_tables_v2/xlat_tables_private.h b/lib/xlat_tables_v2/xlat_tables_private.h
index 07963b1..157dd03 100644
--- a/lib/xlat_tables_v2/xlat_tables_private.h
+++ b/lib/xlat_tables_v2/xlat_tables_private.h
@@ -12,27 +12,26 @@
 
 #if PLAT_XLAT_TABLES_DYNAMIC
 /*
- * Shifts and masks to access fields of an mmap_attr_t
+ * Private shifts and masks to access fields of an mmap attribute
  */
 /* Dynamic or static */
-#define MT_DYN_SHIFT		30 /* 31 would cause undefined behaviours */
+#define MT_DYN_SHIFT		U(31)
 
 /*
  * Memory mapping private attributes
  *
- * Private attributes not exposed in the mmap_attr_t enum.
+ * Private attributes not exposed in the public header.
  */
-typedef enum  {
-	/*
-	 * Regions mapped before the MMU can't be unmapped dynamically (they are
-	 * static) and regions mapped with MMU enabled can be unmapped. This
-	 * behaviour can't be overridden.
-	 *
-	 * Static regions can overlap each other, dynamic regions can't.
-	 */
-	MT_STATIC	= 0 << MT_DYN_SHIFT,
-	MT_DYNAMIC	= 1 << MT_DYN_SHIFT
-} mmap_priv_attr_t;
+
+/*
+ * Regions mapped before the MMU can't be unmapped dynamically (they are
+ * static) and regions mapped with MMU enabled can be unmapped. This
+ * behaviour can't be overridden.
+ *
+ * Static regions can overlap each other, dynamic regions can't.
+ */
+#define MT_STATIC	(U(0) << MT_DYN_SHIFT)
+#define MT_DYNAMIC	(U(1) << MT_DYN_SHIFT)
 
 #endif /* PLAT_XLAT_TABLES_DYNAMIC */
 
diff --git a/maintainers.rst b/maintainers.rst
index 2217cbe..4466a56 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,26 @@
 
 -  plat/rockchip/\*
 
+Synquacer platform sub-maintainer
+---------------------------------
+
+Sumit Garg (sumit.garg@linaro.org, `b49020`_)
+
+Files:
+
+- docs/plat/synquacer.rst
+- plat/socionext/synquacer/\*
+
+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 +187,10 @@
 .. _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
+.. _b49020: https://github.com/b49020
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/board/fvp/aarch64/fvp_ras.c b/plat/arm/board/fvp/aarch64/fvp_ras.c
new file mode 100644
index 0000000..fb80a8a
--- /dev/null
+++ b/plat/arm/board/fvp/aarch64/fvp_ras.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <ras.h>
+
+struct ras_interrupt fvp_ras_interrupts[] = {
+};
+
+struct err_record_info fvp_err_records[] = {
+};
+
+REGISTER_ERR_RECORD_INFO(fvp_err_records);
+REGISTER_RAS_INTERRUPTS(fvp_ras_interrupts);
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 3a28733..ed41d4c 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -216,6 +216,10 @@
 				lib/cpus/aarch64/cpuamu_helpers.S
 endif
 
+ifeq (${RAS_EXTENSION},1)
+BL31_SOURCES		+=	plat/arm/board/fvp/aarch64/fvp_ras.c
+endif
+
 ifneq (${ENABLE_STACK_PROTECTOR},0)
 PLAT_BL_COMMON_SOURCES	+=	plat/arm/board/fvp/fvp_stack_protector.c
 endif
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/aarch64/arm_ras.c b/plat/arm/common/aarch64/arm_ras.c
deleted file mode 100644
index 80dfaf1..0000000
--- a/plat/arm/common/aarch64/arm_ras.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <ras.h>
-
-struct ras_interrupt arm_ras_interrupts[] = {
-};
-
-struct err_record_info arm_err_records[] = {
-};
-
-REGISTER_ERR_RECORD_INFO(arm_err_records);
-REGISTER_RAS_INTERRUPTS(arm_ras_interrupts);
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 3f0ea01..32fd9ee 100644
--- a/plat/arm/common/arm_common.c
+++ b/plat/arm/common/arm_common.c
@@ -81,14 +81,6 @@
 			MT_DEVICE | MT_RW | MT_SECURE);
 #endif
 
-#if ENABLE_SPM && defined(IMAGE_BL31)
-	/* The address of the following region is calculated by the linker. */
-	mmap_add_region(SP_IMAGE_XLAT_TABLES_START,
-			SP_IMAGE_XLAT_TABLES_START,
-			SP_IMAGE_XLAT_TABLES_SIZE,
-			MT_MEMORY | MT_RW | MT_SECURE);
-#endif
-
 	/* Now (re-)map the platform-specific memory regions */
 	mmap_add(plat_arm_get_mmap());
 
@@ -168,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);
@@ -177,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..5330847 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		\
@@ -230,8 +236,7 @@
 # RAS sources
 ifeq (${RAS_EXTENSION},1)
 BL31_SOURCES		+=	lib/extensions/ras/std_err_record.c		\
-				lib/extensions/ras/ras_common.c \
-				plat/arm/common/aarch64/arm_ras.c
+				lib/extensions/ras/ras_common.c
 endif
 
 ifneq (${TRUSTED_BOARD_BOOT},0)
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/rockchip/rk3399/drivers/dram/dfs.h b/plat/rockchip/rk3399/drivers/dram/dfs.h
index 679216c..e847b2e 100644
--- a/plat/rockchip/rk3399/drivers/dram/dfs.h
+++ b/plat/rockchip/rk3399/drivers/dram/dfs.h
@@ -7,6 +7,8 @@
 #ifndef __SOC_ROCKCHIP_RK3399_DFS_H__
 #define __SOC_ROCKCHIP_RK3399_DFS_H__
 
+#include <stdint.h>
+
 struct rk3399_sdram_default_config {
 	unsigned char bl;
 	/* 1:auto precharge, 0:never auto precharge */
diff --git a/plat/rockchip/rk3399/plat_sip_calls.c b/plat/rockchip/rk3399/plat_sip_calls.c
index ae74c9c..3f0f619 100644
--- a/plat/rockchip/rk3399/plat_sip_calls.c
+++ b/plat/rockchip/rk3399/plat_sip_calls.c
@@ -11,7 +11,6 @@
 #include <plat_sip_calls.h>
 #include <rockchip_sip_svc.h>
 #include <runtime_svc.h>
-#include <stdint.h>
 
 #define RK_SIP_DDR_CFG		0x82000008
 #define DRAM_INIT		0x00
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/socionext/synquacer/drivers/mhu/sq_mhu.c b/plat/socionext/synquacer/drivers/mhu/sq_mhu.c
new file mode 100644
index 0000000..5c2a635
--- /dev/null
+++ b/plat/socionext/synquacer/drivers/mhu/sq_mhu.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bakery_lock.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <sq_common.h>
+#include "sq_mhu.h"
+
+/* SCP MHU secure channel registers */
+#define SCP_INTR_S_STAT		0x200
+#define SCP_INTR_S_SET		0x208
+#define SCP_INTR_S_CLEAR	0x210
+
+/* CPU MHU secure channel registers */
+#define CPU_INTR_S_STAT		0x300
+#define CPU_INTR_S_SET		0x308
+#define CPU_INTR_S_CLEAR	0x310
+
+DEFINE_BAKERY_LOCK(sq_lock);
+
+/*
+ * Slot 31 is reserved because the MHU hardware uses this register bit to
+ * indicate a non-secure access attempt. The total number of available slots is
+ * therefore 31 [30:0].
+ */
+#define MHU_MAX_SLOT_ID		30
+
+void mhu_secure_message_start(unsigned int slot_id)
+{
+	assert(slot_id <= MHU_MAX_SLOT_ID);
+
+	bakery_lock_get(&sq_lock);
+
+	/* Make sure any previous command has finished */
+	while (mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) &
+							(1 << slot_id))
+		;
+}
+
+void mhu_secure_message_send(unsigned int slot_id)
+{
+	assert(slot_id <= MHU_MAX_SLOT_ID);
+	assert(!(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) &
+							(1 << slot_id)));
+
+	/* Send command to SCP */
+	mmio_write_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id);
+}
+
+uint32_t mhu_secure_message_wait(void)
+{
+	uint32_t response;
+
+	/* Wait for response from SCP */
+	while (!(response = mmio_read_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_STAT)))
+		;
+
+	return response;
+}
+
+void mhu_secure_message_end(unsigned int slot_id)
+{
+	assert(slot_id <= MHU_MAX_SLOT_ID);
+
+	/*
+	 * Clear any response we got by writing one in the relevant slot bit to
+	 * the CLEAR register
+	 */
+	mmio_write_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id);
+
+	bakery_lock_release(&sq_lock);
+}
+
+void mhu_secure_init(void)
+{
+	bakery_lock_init(&sq_lock);
+
+	/*
+	 * The STAT register resets to zero. Ensure it is in the expected state,
+	 * as a stale or garbage value would make us think it's a message we've
+	 * already sent.
+	 */
+	assert(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) == 0);
+}
+
+void plat_sq_pwrc_setup(void)
+{
+	mhu_secure_init();
+}
diff --git a/plat/socionext/synquacer/drivers/mhu/sq_mhu.h b/plat/socionext/synquacer/drivers/mhu/sq_mhu.h
new file mode 100644
index 0000000..bef117d
--- /dev/null
+++ b/plat/socionext/synquacer/drivers/mhu/sq_mhu.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SQ_MHU_H__
+#define __SQ_MHU_H__
+
+#include <stdint.h>
+
+void mhu_secure_message_start(unsigned int slot_id);
+void mhu_secure_message_send(unsigned int slot_id);
+uint32_t mhu_secure_message_wait(void);
+void mhu_secure_message_end(unsigned int slot_id);
+
+void mhu_secure_init(void);
+
+#endif	/* __SQ_MHU_H__ */
diff --git a/plat/socionext/synquacer/drivers/scpi/sq_scpi.c b/plat/socionext/synquacer/drivers/scpi/sq_scpi.c
new file mode 100644
index 0000000..170b7e1
--- /dev/null
+++ b/plat/socionext/synquacer/drivers/scpi/sq_scpi.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <platform_def.h>
+#include <sq_common.h>
+#include <debug.h>
+#include <string.h>
+#include "sq_mhu.h"
+#include "sq_scpi.h"
+
+#define SCPI_SHARED_MEM_SCP_TO_AP	PLAT_SQ_SCP_COM_SHARED_MEM_BASE
+#define SCPI_SHARED_MEM_AP_TO_SCP	(PLAT_SQ_SCP_COM_SHARED_MEM_BASE \
+								 + 0x100)
+
+#define SCPI_CMD_HEADER_AP_TO_SCP		\
+	((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP)
+#define SCPI_CMD_PAYLOAD_AP_TO_SCP		\
+	((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t)))
+
+/* ID of the MHU slot used for the SCPI protocol */
+#define SCPI_MHU_SLOT_ID		0
+
+static void scpi_secure_message_start(void)
+{
+	mhu_secure_message_start(SCPI_MHU_SLOT_ID);
+}
+
+static void scpi_secure_message_send(size_t payload_size)
+{
+	/*
+	 * Ensure that any write to the SCPI payload area is seen by SCP before
+	 * we write to the MHU register. If these 2 writes were reordered by
+	 * the CPU then SCP would read stale payload data
+	 */
+	dmbst();
+
+	mhu_secure_message_send(SCPI_MHU_SLOT_ID);
+}
+
+static void scpi_secure_message_receive(scpi_cmd_t *cmd)
+{
+	uint32_t mhu_status;
+
+	assert(cmd != NULL);
+
+	mhu_status = mhu_secure_message_wait();
+
+	/* Expect an SCPI message, reject any other protocol */
+	if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) {
+		ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n",
+			mhu_status);
+		panic();
+	}
+
+	/*
+	 * Ensure that any read to the SCPI payload area is done after reading
+	 * the MHU register. If these 2 reads were reordered then the CPU would
+	 * read invalid payload data
+	 */
+	dmbld();
+
+	memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd));
+}
+
+static void scpi_secure_message_end(void)
+{
+	mhu_secure_message_end(SCPI_MHU_SLOT_ID);
+}
+
+int scpi_wait_ready(void)
+{
+	scpi_cmd_t scpi_cmd;
+	scpi_status_t status = SCP_OK;
+
+	VERBOSE("Waiting for SCP_READY command...\n");
+
+	/* Get a message from the SCP */
+	scpi_secure_message_start();
+	scpi_secure_message_receive(&scpi_cmd);
+	scpi_secure_message_end();
+
+	/* We are expecting 'SCP Ready', produce correct error if it's not */
+	if (scpi_cmd.id != SCPI_CMD_SCP_READY) {
+		ERROR("Unexpected SCP command: expected command #%u,"
+		      "got command #%u\n", SCPI_CMD_SCP_READY, scpi_cmd.id);
+		status = SCP_E_SUPPORT;
+	} else if (scpi_cmd.size != 0) {
+		ERROR("SCP_READY command has incorrect size: expected 0,"
+		      "got %u\n", scpi_cmd.size);
+		status = SCP_E_SIZE;
+	}
+
+	VERBOSE("Sending response for SCP_READY command\n");
+
+	/*
+	 * Send our response back to SCP.
+	 * We are using the same SCPI header, just update the status field.
+	 */
+	scpi_cmd.status = status;
+	scpi_secure_message_start();
+	memcpy((void *) SCPI_SHARED_MEM_AP_TO_SCP, &scpi_cmd, sizeof(scpi_cmd));
+	scpi_secure_message_send(0);
+	scpi_secure_message_end();
+
+	return status == SCP_OK ? 0 : -1;
+}
+
+void scpi_set_sq_power_state(unsigned int mpidr, scpi_power_state_t cpu_state,
+		scpi_power_state_t cluster_state, scpi_power_state_t sq_state)
+{
+	scpi_cmd_t *cmd;
+	uint32_t state = 0;
+	uint32_t *payload_addr;
+
+	state |= mpidr & 0x0f;	/* CPU ID */
+	state |= (mpidr & 0xf00) >> 4;	/* Cluster ID */
+	state |= cpu_state << 8;
+	state |= cluster_state << 12;
+	state |= sq_state << 16;
+
+	scpi_secure_message_start();
+
+	/* Populate the command header */
+	cmd = SCPI_CMD_HEADER_AP_TO_SCP;
+	cmd->id = SCPI_CMD_SET_POWER_STATE;
+	cmd->set = SCPI_SET_NORMAL;
+	cmd->sender = 0;
+	cmd->size = sizeof(state);
+	/* Populate the command payload */
+	payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP;
+	*payload_addr = state;
+	scpi_secure_message_send(sizeof(state));
+
+	/*
+	 * SCP does not reply to this command in order to avoid MHU interrupts
+	 * from the sender, which could interfere with its power state request.
+	 */
+	scpi_secure_message_end();
+}
+
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state)
+{
+	scpi_cmd_t *cmd;
+	uint8_t *payload_addr;
+	scpi_cmd_t response;
+
+	scpi_secure_message_start();
+
+	/* Populate the command header */
+	cmd = SCPI_CMD_HEADER_AP_TO_SCP;
+	cmd->id = SCPI_CMD_SYS_POWER_STATE;
+	cmd->set = 0;
+	cmd->sender = 0;
+	cmd->size = sizeof(*payload_addr);
+	/* Populate the command payload */
+	payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP;
+	*payload_addr = system_state & 0xff;
+	scpi_secure_message_send(sizeof(*payload_addr));
+
+	scpi_secure_message_receive(&response);
+
+	scpi_secure_message_end();
+
+	return response.status;
+}
+
+uint32_t scpi_get_draminfo(struct draminfo *info)
+{
+	scpi_cmd_t *cmd;
+	struct {
+		scpi_cmd_t	cmd;
+		struct draminfo	info;
+	} response;
+	uint32_t mhu_status;
+
+	scpi_secure_message_start();
+
+	/* Populate the command header */
+	cmd		= SCPI_CMD_HEADER_AP_TO_SCP;
+	cmd->id		= SCPI_CMD_GET_DRAMINFO;
+	cmd->set	= SCPI_SET_EXTENDED;
+	cmd->sender	= 0;
+	cmd->size	= 0;
+
+	scpi_secure_message_send(0);
+
+	mhu_status = mhu_secure_message_wait();
+
+	/* Expect an SCPI message, reject any other protocol */
+	if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) {
+		ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n",
+			mhu_status);
+		panic();
+	}
+
+	/*
+	 * Ensure that any read to the SCPI payload area is done after reading
+	 * the MHU register. If these 2 reads were reordered then the CPU would
+	 * read invalid payload data
+	 */
+	dmbld();
+
+	memcpy(&response, (void *)SCPI_SHARED_MEM_SCP_TO_AP, sizeof(response));
+
+	scpi_secure_message_end();
+
+	if (response.cmd.status == SCP_OK)
+		*info = response.info;
+
+	return response.cmd.status;
+}
diff --git a/plat/socionext/synquacer/drivers/scpi/sq_scpi.h b/plat/socionext/synquacer/drivers/scpi/sq_scpi.h
new file mode 100644
index 0000000..30fa5c7
--- /dev/null
+++ b/plat/socionext/synquacer/drivers/scpi/sq_scpi.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SQ_SCPI_H__
+#define __SQ_SCPI_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * An SCPI command consists of a header and a payload.
+ * The following structure describes the header. It is 64-bit long.
+ */
+typedef struct {
+	/* Command ID */
+	uint32_t id		: 7;
+	/* Set ID. Identifies whether this is a standard or extended command. */
+	uint32_t set		: 1;
+	/* Sender ID to match a reply. The value is sender specific. */
+	uint32_t sender		: 8;
+	/* Size of the payload in bytes (0 - 511) */
+	uint32_t size		: 9;
+	uint32_t reserved	: 7;
+	/*
+	 * Status indicating the success of a command.
+	 * See the enum below.
+	 */
+	uint32_t status;
+} scpi_cmd_t;
+
+typedef enum {
+	SCPI_SET_NORMAL = 0,	/* Normal SCPI commands */
+	SCPI_SET_EXTENDED	/* Extended SCPI commands */
+} scpi_set_t;
+
+enum {
+	SCP_OK = 0,	/* Success */
+	SCP_E_PARAM,	/* Invalid parameter(s) */
+	SCP_E_ALIGN,	/* Invalid alignment */
+	SCP_E_SIZE,	/* Invalid size */
+	SCP_E_HANDLER,	/* Invalid handler or callback */
+	SCP_E_ACCESS,	/* Invalid access or permission denied */
+	SCP_E_RANGE,	/* Value out of range */
+	SCP_E_TIMEOUT,	/* Time out has ocurred */
+	SCP_E_NOMEM,	/* Invalid memory area or pointer */
+	SCP_E_PWRSTATE,	/* Invalid power state */
+	SCP_E_SUPPORT,	/* Feature not supported or disabled */
+	SCPI_E_DEVICE,	/* Device error */
+	SCPI_E_BUSY,	/* Device is busy */
+};
+
+typedef uint32_t scpi_status_t;
+
+typedef enum {
+	SCPI_CMD_SCP_READY = 0x01,
+	SCPI_CMD_SET_POWER_STATE = 0x03,
+	SCPI_CMD_SYS_POWER_STATE = 0x05
+} scpi_command_t;
+
+typedef enum {
+	scpi_power_on = 0,
+	scpi_power_retention = 1,
+	scpi_power_off = 3,
+} scpi_power_state_t;
+
+typedef enum {
+	scpi_system_shutdown = 0,
+	scpi_system_reboot = 1,
+	scpi_system_reset = 2
+} scpi_system_state_t;
+
+extern int scpi_wait_ready(void);
+extern void scpi_set_sq_power_state(unsigned int mpidr,
+					scpi_power_state_t cpu_state,
+					scpi_power_state_t cluster_state,
+					scpi_power_state_t css_state);
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state);
+
+#endif	/* __SQ_SCPI_H__ */
diff --git a/plat/socionext/synquacer/include/plat_macros.S b/plat/socionext/synquacer/include/plat_macros.S
new file mode 100644
index 0000000..3dc06aa
--- /dev/null
+++ b/plat/socionext/synquacer/include/plat_macros.S
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_MACROS_S__
+#define __PLAT_MACROS_S__
+
+/*
+ * Print CCN registers
+ */
+	.macro plat_crash_print_regs
+	.endm
+#endif /* __PLAT_MACROS_S__ */
diff --git a/plat/socionext/synquacer/include/platform_def.h b/plat/socionext/synquacer/include/platform_def.h
new file mode 100644
index 0000000..3e16642
--- /dev/null
+++ b/plat/socionext/synquacer/include/platform_def.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 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>
+
+/* CPU topology */
+#define PLAT_MAX_CORES_PER_CLUSTER	2
+#define PLAT_CLUSTER_COUNT		12
+#define PLATFORM_CORE_COUNT		(PLAT_CLUSTER_COUNT *	\
+					 PLAT_MAX_CORES_PER_CLUSTER)
+
+#define PLAT_MAX_PWR_LVL		1
+#define PLAT_MAX_RET_STATE		1
+#define PLAT_MAX_OFF_STATE		2
+
+#define SQ_LOCAL_STATE_RUN		0
+#define SQ_LOCAL_STATE_RET		1
+#define SQ_LOCAL_STATE_OFF		2
+
+#define CACHE_WRITEBACK_SHIFT		6
+#define CACHE_WRITEBACK_GRANULE		(1 << CACHE_WRITEBACK_SHIFT)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
+#define MAX_XLAT_TABLES			4
+#define MAX_MMAP_REGIONS		6
+
+#define PLATFORM_STACK_SIZE		0x400
+
+#define BL31_BASE			0x04000000
+#define BL31_SIZE			0x00080000
+#define BL31_LIMIT			(BL31_BASE + BL31_SIZE)
+
+#define PLAT_SQ_CCN_BASE		0x32000000
+#define PLAT_SQ_CLUSTER_TO_CCN_ID_MAP					\
+					0,	/* Cluster 0 */		\
+					18,	/* Cluster 1 */		\
+					11,	/* Cluster 2 */		\
+					29,	/* Cluster 3 */		\
+					35,	/* Cluster 4 */		\
+					17,	/* Cluster 5 */		\
+					12,	/* Cluster 6 */		\
+					30,	/* Cluster 7 */		\
+					14,	/* Cluster 8 */		\
+					32,	/* Cluster 9 */		\
+					15,	/* Cluster 10 */	\
+					33	/* Cluster 11 */
+
+/* UART related constants */
+#define PLAT_SQ_BOOT_UART_BASE		0x2A400000
+#define PLAT_SQ_BOOT_UART_CLK_IN_HZ	62500000
+#define SQ_CONSOLE_BAUDRATE		115200
+
+#define SQ_SYS_CNTCTL_BASE		0x2a430000
+
+#define SQ_SYS_TIMCTL_BASE		0x2a810000
+#define PLAT_SQ_NSTIMER_FRAME_ID	0
+
+#define DRAMINFO_BASE			0x2E00FFC0
+
+#define PLAT_SQ_MHU_BASE		0x45000000
+
+#define PLAT_SQ_SCP_COM_SHARED_MEM_BASE		0x45400000
+#define SCPI_CMD_GET_DRAMINFO			0x1
+
+#define SQ_BOOT_CFG_ADDR			0x45410000
+#define PLAT_SQ_PRIMARY_CPU_SHIFT		8
+#define PLAT_SQ_PRIMARY_CPU_BIT_WIDTH		6
+
+#define PLAT_SQ_GICD_BASE		0x30000000
+#define PLAT_SQ_GICR_BASE		0x30400000
+
+#define PLAT_SQ_GPIO_BASE		0x51000000
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/socionext/synquacer/include/sq_common.h b/plat/socionext/synquacer/include/sq_common.h
new file mode 100644
index 0000000..58b1e24
--- /dev/null
+++ b/plat/socionext/synquacer/include/sq_common.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SQ_COMMON_H__
+#define __SQ_COMMON_H__
+
+#include <sys/types.h>
+#include <xlat_tables_v2.h>
+
+struct draminfo {
+	uint32_t	num_regions;
+	uint32_t	reserved;
+	uint64_t	base1;
+	uint64_t	size1;
+	uint64_t	base2;
+	uint64_t	size2;
+	uint64_t	base3;
+	uint64_t	size3;
+};
+
+uint32_t scpi_get_draminfo(struct draminfo *info);
+
+void plat_sq_pwrc_setup(void);
+
+void plat_sq_interconnect_init(void);
+void plat_sq_interconnect_enter_coherency(void);
+void plat_sq_interconnect_exit_coherency(void);
+
+unsigned int sq_calc_core_pos(u_register_t mpidr);
+
+void sq_gic_driver_init(void);
+void sq_gic_init(void);
+void sq_gic_cpuif_enable(void);
+void sq_gic_cpuif_disable(void);
+void sq_gic_pcpu_init(void);
+
+void sq_mmap_setup(uintptr_t total_base, size_t total_size,
+		   const struct mmap_region *mmap);
+
+#endif /* __SQ_COMMON_H__ */
diff --git a/plat/socionext/synquacer/platform.mk b/plat/socionext/synquacer/platform.mk
new file mode 100644
index 0000000..546f84a
--- /dev/null
+++ b/plat/socionext/synquacer/platform.mk
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+override RESET_TO_BL31			:= 1
+override ENABLE_PLAT_COMPAT		:= 0
+override MULTI_CONSOLE_API		:= 1
+override PROGRAMMABLE_RESET_ADDRESS	:= 1
+override USE_COHERENT_MEM		:= 1
+override SEPARATE_CODE_AND_RODATA	:= 1
+override ENABLE_SVE_FOR_NS		:= 0
+
+# Enable workarounds for selected Cortex-A53 erratas.
+ERRATA_A53_855873		:= 1
+
+# Libraries
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_PATH		:=	plat/socionext/synquacer
+PLAT_INCLUDES		:=	-I$(PLAT_PATH)/include		\
+				-I$(PLAT_PATH)/drivers/scpi	\
+				-I$(PLAT_PATH)/drivers/mhu
+
+PLAT_BL_COMMON_SOURCES	+=	$(PLAT_PATH)/sq_helpers.S		\
+				drivers/arm/pl011/pl011_console.S	\
+				drivers/delay_timer/delay_timer.c	\
+				drivers/delay_timer/generic_delay_timer.c \
+				${XLAT_TABLES_LIB_SRCS}
+
+BL31_SOURCES		+=	drivers/arm/ccn/ccn.c			\
+				drivers/arm/gic/common/gic_common.c	\
+				drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicv3_main.c		\
+				lib/cpus/aarch64/cortex_a53.S		\
+				plat/common/plat_gicv3.c		\
+				plat/common/plat_psci_common.c		\
+				$(PLAT_PATH)/sq_bl31_setup.c		\
+				$(PLAT_PATH)/sq_ccn.c			\
+				$(PLAT_PATH)/sq_topology.c		\
+				$(PLAT_PATH)/sq_psci.c			\
+				$(PLAT_PATH)/sq_gicv3.c			\
+				$(PLAT_PATH)/sq_xlat_setup.c		\
+				$(PLAT_PATH)/drivers/scpi/sq_scpi.c	\
+				$(PLAT_PATH)/drivers/mhu/sq_mhu.c
diff --git a/plat/socionext/synquacer/sq_bl31_setup.c b/plat/socionext/synquacer/sq_bl31_setup.c
new file mode 100644
index 0000000..461c8de
--- /dev/null
+++ b/plat/socionext/synquacer/sq_bl31_setup.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <platform_def.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <pl011.h>
+#include <debug.h>
+#include <mmio.h>
+#include <sq_common.h>
+
+static console_pl011_t console;
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	assert(sec_state_is_valid(type));
+	return type == NON_SECURE ? &bl33_image_ep_info : &bl32_image_ep_info;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t sq_get_spsr_for_bl32_entry(void)
+{
+	/*
+	 * The Secure Payload Dispatcher service is responsible for
+	 * setting the SPSR prior to entry into the BL32 image.
+	 */
+	return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+uint32_t sq_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;
+}
+
+void bl31_early_platform_setup(bl31_params_t *from_bl2,
+				void *plat_params_from_bl2)
+{
+	/* Initialize the console to provide early debug support */
+	(void)console_pl011_register(PLAT_SQ_BOOT_UART_BASE,
+			       PLAT_SQ_BOOT_UART_CLK_IN_HZ,
+			       SQ_CONSOLE_BAUDRATE, &console);
+
+	console_set_scope(&console.console, CONSOLE_FLAG_BOOT |
+			  CONSOLE_FLAG_RUNTIME);
+
+	/* There are no parameters from BL2 if BL31 is a reset vector */
+	assert(from_bl2 == NULL);
+	assert(plat_params_from_bl2 == NULL);
+
+#ifdef BL32_BASE
+	/* Populate entry point information for BL32 */
+	SET_PARAM_HEAD(&bl32_image_ep_info,
+				PARAM_EP,
+				VERSION_1,
+				0);
+	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+	bl32_image_ep_info.pc = BL32_BASE;
+	bl32_image_ep_info.spsr = sq_get_spsr_for_bl32_entry();
+#endif /* BL32_BASE */
+
+	/* 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 = PRELOADED_BL33_BASE;
+	bl33_image_ep_info.spsr = sq_get_spsr_for_bl33_entry();
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+}
+
+static void sq_configure_sys_timer(void)
+{
+	unsigned int reg_val;
+
+	reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT);
+	reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT);
+	reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT);
+	mmio_write_32(SQ_SYS_TIMCTL_BASE +
+		      CNTACR_BASE(PLAT_SQ_NSTIMER_FRAME_ID), reg_val);
+
+	reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_SQ_NSTIMER_FRAME_ID));
+	mmio_write_32(SQ_SYS_TIMCTL_BASE + CNTNSAR, reg_val);
+}
+
+void bl31_platform_setup(void)
+{
+	/* Initialize the CCN interconnect */
+	plat_sq_interconnect_init();
+	plat_sq_interconnect_enter_coherency();
+
+	/* Initialize the GIC driver, cpu and distributor interfaces */
+	sq_gic_driver_init();
+	sq_gic_init();
+
+	/* Enable and initialize the System level generic timer */
+	mmio_write_32(SQ_SYS_CNTCTL_BASE + CNTCR_OFF,
+			CNTCR_FCREQ(0) | CNTCR_EN);
+
+	/* Allow access to the System counter timer module */
+	sq_configure_sys_timer();
+
+	/* Initialize power controller before setting up topology */
+	plat_sq_pwrc_setup();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+	struct draminfo *di = (struct draminfo *)(unsigned long)DRAMINFO_BASE;
+
+	scpi_get_draminfo(di);
+}
+
+void bl31_plat_arch_setup(void)
+{
+	sq_mmap_setup(BL31_BASE, BL31_SIZE, NULL);
+	enable_mmu_el3(XLAT_TABLE_NC);
+}
+
+void bl31_plat_enable_mmu(uint32_t flags)
+{
+	enable_mmu_el3(flags | XLAT_TABLE_NC);
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	unsigned int counter_base_frequency;
+
+	/* Read the frequency from Frequency modes table */
+	counter_base_frequency = mmio_read_32(SQ_SYS_CNTCTL_BASE + CNTFID_OFF);
+
+	/* The first entry of the frequency modes table must not be 0 */
+	if (counter_base_frequency == 0)
+		panic();
+
+	return counter_base_frequency;
+}
diff --git a/plat/socionext/synquacer/sq_ccn.c b/plat/socionext/synquacer/sq_ccn.c
new file mode 100644
index 0000000..bb70d5d
--- /dev/null
+++ b/plat/socionext/synquacer/sq_ccn.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <ccn.h>
+#include <platform_def.h>
+
+static const unsigned char master_to_rn_id_map[] = {
+	PLAT_SQ_CLUSTER_TO_CCN_ID_MAP
+};
+
+static const ccn_desc_t sq_ccn_desc = {
+	.periphbase = PLAT_SQ_CCN_BASE,
+	.num_masters = ARRAY_SIZE(master_to_rn_id_map),
+	.master_to_rn_id_map = master_to_rn_id_map
+};
+
+/******************************************************************************
+ * Helper function to initialize SQ CCN driver.
+ *****************************************************************************/
+void plat_sq_interconnect_init(void)
+{
+	ccn_init(&sq_ccn_desc);
+}
+
+/******************************************************************************
+ * Helper function to place current master into coherency
+ *****************************************************************************/
+void plat_sq_interconnect_enter_coherency(void)
+{
+	ccn_enter_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+/******************************************************************************
+ * Helper function to remove current master from coherency
+ *****************************************************************************/
+void plat_sq_interconnect_exit_coherency(void)
+{
+	ccn_exit_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
diff --git a/plat/socionext/synquacer/sq_gicv3.c b/plat/socionext/synquacer/sq_gicv3.c
new file mode 100644
index 0000000..94e5a66
--- /dev/null
+++ b/plat/socionext/synquacer/sq_gicv3.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <gicv3.h>
+#include <interrupt_props.h>
+#include <platform.h>
+#include <platform_def.h>
+
+#include "sq_common.h"
+
+static uintptr_t sq_rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static const interrupt_prop_t sq_interrupt_props[] = {
+	/* G0 interrupts */
+
+	/* SGI0 */
+	INTR_PROP_DESC(8, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+			GIC_INTR_CFG_EDGE),
+	/* SGI6 */
+	INTR_PROP_DESC(14, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+			GIC_INTR_CFG_EDGE),
+
+	/* G1S interrupts */
+
+	/* Timer */
+	INTR_PROP_DESC(29, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+			GIC_INTR_CFG_LEVEL),
+	/* SGI1 */
+	INTR_PROP_DESC(9, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+			GIC_INTR_CFG_EDGE),
+	/* SGI2 */
+	INTR_PROP_DESC(10, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+			GIC_INTR_CFG_EDGE),
+	/* SGI3 */
+	INTR_PROP_DESC(11, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+			GIC_INTR_CFG_EDGE),
+	/* SGI4 */
+	INTR_PROP_DESC(12, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+			GIC_INTR_CFG_EDGE),
+	/* SGI5 */
+	INTR_PROP_DESC(13, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+			GIC_INTR_CFG_EDGE),
+	/* SGI7 */
+	INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+			GIC_INTR_CFG_EDGE)
+};
+
+static unsigned int sq_mpidr_to_core_pos(u_register_t mpidr)
+{
+	return plat_core_pos_by_mpidr(mpidr);
+}
+
+static const struct gicv3_driver_data sq_gic_driver_data = {
+		.gicd_base = PLAT_SQ_GICD_BASE,
+		.gicr_base = PLAT_SQ_GICR_BASE,
+		.interrupt_props = sq_interrupt_props,
+		.interrupt_props_num = ARRAY_SIZE(sq_interrupt_props),
+		.rdistif_num = PLATFORM_CORE_COUNT,
+		.rdistif_base_addrs = sq_rdistif_base_addrs,
+		.mpidr_to_core_pos = sq_mpidr_to_core_pos,
+};
+
+void sq_gic_driver_init(void)
+{
+	gicv3_driver_init(&sq_gic_driver_data);
+}
+
+void sq_gic_init(void)
+{
+	gicv3_distif_init();
+	gicv3_rdistif_init(plat_my_core_pos());
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void sq_gic_cpuif_enable(void)
+{
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void sq_gic_cpuif_disable(void)
+{
+	gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+void sq_gic_pcpu_init(void)
+{
+	gicv3_rdistif_init(plat_my_core_pos());
+}
diff --git a/plat/socionext/synquacer/sq_helpers.S b/plat/socionext/synquacer/sq_helpers.S
new file mode 100644
index 0000000..558aa15
--- /dev/null
+++ b/plat/socionext/synquacer/sq_helpers.S
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <platform_def.h>
+
+	.global	sq_calc_core_pos
+	.global	plat_my_core_pos
+	.global	platform_mem_init
+	.global	plat_is_my_cpu_primary
+	.global plat_secondary_cold_boot_setup
+	.global	plat_crash_console_init
+	.global	plat_crash_console_putc
+	.global	plat_crash_console_flush
+
+/*
+ * unsigned int sq_calc_core_pos(u_register_t mpidr)
+ * core_pos = (cluster_id * max_cpus_per_cluster) + core_id
+ */
+func sq_calc_core_pos
+	and	x1, x0, #MPIDR_CPU_MASK
+	and	x0, x0, #MPIDR_CLUSTER_MASK
+	add	x0, x1, x0, lsr #7
+	ret
+endfunc sq_calc_core_pos
+
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	b	sq_calc_core_pos
+endfunc plat_my_core_pos
+
+func platform_mem_init
+	ret
+endfunc platform_mem_init
+
+/*
+ * Secondary CPUs are placed in a holding pen, waiting for their mailbox
+ * to be populated. Note that all CPUs share the same mailbox ; therefore,
+ * populating it will release all CPUs from their holding pen. If
+ * finer-grained control is needed then this should be handled in the
+ * code that secondary CPUs jump to.
+ */
+func plat_secondary_cold_boot_setup
+	ldr	x0, sq_sec_entrypoint
+
+	/* Wait until the mailbox gets populated */
+poll_mailbox:
+	cbz	x0, 1f
+	br	x0
+1:
+	wfe
+	b	poll_mailbox
+endfunc plat_secondary_cold_boot_setup
+
+/*
+ * Find out whether the current cpu is the primary
+ * cpu (applicable only after a cold boot)
+ */
+func plat_is_my_cpu_primary
+	mov	x9, x30
+	bl	plat_my_core_pos
+	ldr	x1, =SQ_BOOT_CFG_ADDR
+	ldr	x1, [x1]
+	ubfx	x1, x1, #PLAT_SQ_PRIMARY_CPU_SHIFT, \
+			#PLAT_SQ_PRIMARY_CPU_BIT_WIDTH
+	cmp	x0, x1
+	cset	w0, eq
+	ret	x9
+endfunc plat_is_my_cpu_primary
+
+/*
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0, x1, x2
+ */
+func plat_crash_console_init
+	mov_imm x0, PLAT_SQ_BOOT_UART_BASE
+	mov_imm x1, PLAT_SQ_BOOT_UART_CLK_IN_HZ
+	mov_imm x2, SQ_CONSOLE_BAUDRATE
+	b	console_pl011_core_init
+endfunc plat_crash_console_init
+
+/*
+ * int plat_crash_console_putc(int c)
+ * 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, PLAT_SQ_BOOT_UART_BASE
+	b	console_pl011_core_putc
+endfunc plat_crash_console_putc
+
+/*
+ * int plat_crash_console_flush(int c)
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : return -1 on error else return 0.
+ * Clobber list : x0, x1
+ */
+func plat_crash_console_flush
+	mov_imm	x0, PLAT_SQ_BOOT_UART_BASE
+	b	console_pl011_core_flush
+endfunc plat_crash_console_flush
diff --git a/plat/socionext/synquacer/sq_psci.c b/plat/socionext/synquacer/sq_psci.c
new file mode 100644
index 0000000..c327f1d
--- /dev/null
+++ b/plat/socionext/synquacer/sq_psci.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <cassert.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <generic_delay_timer.h>
+#include <platform_def.h>
+#include <sq_common.h>
+#include "sq_scpi.h"
+#include <psci.h>
+
+/* Macros to read the SQ power domain state */
+#define SQ_PWR_LVL0	MPIDR_AFFLVL0
+#define SQ_PWR_LVL1	MPIDR_AFFLVL1
+#define SQ_PWR_LVL2	MPIDR_AFFLVL2
+
+#define SQ_CORE_PWR_STATE(state)	(state)->pwr_domain_state[SQ_PWR_LVL0]
+#define SQ_CLUSTER_PWR_STATE(state)	(state)->pwr_domain_state[SQ_PWR_LVL1]
+#define SQ_SYSTEM_PWR_STATE(state)	((PLAT_MAX_PWR_LVL > SQ_PWR_LVL1) ?\
+				(state)->pwr_domain_state[SQ_PWR_LVL2] : 0)
+
+uintptr_t sq_sec_entrypoint;
+
+int sq_pwr_domain_on(u_register_t mpidr)
+{
+	/*
+	 * SCP takes care of powering up parent power domains so we
+	 * only need to care about level 0
+	 */
+	scpi_set_sq_power_state(mpidr, scpi_power_on, scpi_power_on,
+				 scpi_power_on);
+
+	return PSCI_E_SUCCESS;
+}
+
+static void sq_pwr_domain_on_finisher_common(
+		const psci_power_state_t *target_state)
+{
+	assert(SQ_CORE_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF);
+
+	/*
+	 * Perform the common cluster specific operations i.e enable coherency
+	 * if this cluster was off.
+	 */
+	if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF)
+		plat_sq_interconnect_enter_coherency();
+}
+
+void sq_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	/* Assert that the system power domain need not be initialized */
+	assert(SQ_SYSTEM_PWR_STATE(target_state) == SQ_LOCAL_STATE_RUN);
+
+	sq_pwr_domain_on_finisher_common(target_state);
+
+	/* Program the gic per-cpu distributor or re-distributor interface */
+	sq_gic_pcpu_init();
+
+	/* Enable the gic cpu interface */
+	sq_gic_cpuif_enable();
+}
+
+static void sq_power_down_common(const psci_power_state_t *target_state)
+{
+	uint32_t cluster_state = scpi_power_on;
+	uint32_t system_state = scpi_power_on;
+
+	/* Prevent interrupts from spuriously waking up this cpu */
+	sq_gic_cpuif_disable();
+
+	/* Check if power down at system power domain level is requested */
+	if (SQ_SYSTEM_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF)
+		system_state = scpi_power_retention;
+
+	/* Cluster is to be turned off, so disable coherency */
+	if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) {
+		plat_sq_interconnect_exit_coherency();
+		cluster_state = scpi_power_off;
+	}
+
+	/*
+	 * Ask the SCP to power down the appropriate components depending upon
+	 * their state.
+	 */
+	scpi_set_sq_power_state(read_mpidr_el1(),
+				 scpi_power_off,
+				 cluster_state,
+				 system_state);
+}
+
+void sq_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	sq_power_down_common(target_state);
+}
+
+void __dead2 sq_system_off(void)
+{
+	volatile uint32_t *gpio = (uint32_t *)PLAT_SQ_GPIO_BASE;
+
+	/* set PD[9] high to power off the system */
+	gpio[5] |= 0x2;		/* set output */
+	gpio[1] |= 0x2;		/* set high */
+	dmbst();
+
+	generic_delay_timer_init();
+
+	mdelay(1);
+
+	while (1) {
+		gpio[1] &= ~0x2;	/* set low */
+		dmbst();
+
+		mdelay(1);
+
+		gpio[1] |= 0x2;		/* set high */
+		dmbst();
+
+		mdelay(100);
+	}
+
+	wfi();
+	ERROR("SQ System Off: operation not handled.\n");
+	panic();
+}
+
+void __dead2 sq_system_reset(void)
+{
+	uint32_t response;
+
+	/* Send the system reset request to the SCP */
+	response = scpi_sys_power_state(scpi_system_reboot);
+
+	if (response != SCP_OK) {
+		ERROR("SQ System Reset: SCP error %u.\n", response);
+		panic();
+	}
+	wfi();
+	ERROR("SQ System Reset: operation not handled.\n");
+	panic();
+}
+
+void sq_cpu_standby(plat_local_state_t cpu_state)
+{
+	unsigned int scr;
+
+	assert(cpu_state == SQ_LOCAL_STATE_RET);
+
+	scr = read_scr_el3();
+	/* Enable PhysicalIRQ bit for NS world to wake the CPU */
+	write_scr_el3(scr | SCR_IRQ_BIT);
+	isb();
+	dsb();
+	wfi();
+
+	/*
+	 * Restore SCR to the original value, synchronisation of scr_el3 is
+	 * done by eret while el3_exit to save some execution cycles.
+	 */
+	write_scr_el3(scr);
+}
+
+const plat_psci_ops_t sq_psci_ops = {
+	.pwr_domain_on		= sq_pwr_domain_on,
+	.pwr_domain_off		= sq_pwr_domain_off,
+	.pwr_domain_on_finish	= sq_pwr_domain_on_finish,
+	.cpu_standby		= sq_cpu_standby,
+	.system_off		= sq_system_off,
+	.system_reset		= sq_system_reset,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const struct plat_psci_ops **psci_ops)
+{
+	sq_sec_entrypoint = sec_entrypoint;
+	flush_dcache_range((uint64_t)&sq_sec_entrypoint,
+			   sizeof(sq_sec_entrypoint));
+
+	*psci_ops = &sq_psci_ops;
+
+	return 0;
+}
diff --git a/plat/socionext/synquacer/sq_topology.c b/plat/socionext/synquacer/sq_topology.c
new file mode 100644
index 0000000..aa20355
--- /dev/null
+++ b/plat/socionext/synquacer/sq_topology.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <sq_common.h>
+#include <platform_def.h>
+
+unsigned char sq_pd_tree_desc[PLAT_CLUSTER_COUNT + 1];
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	unsigned int cluster_id, cpu_id;
+
+	cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+	if (cluster_id >= PLAT_CLUSTER_COUNT)
+		return -1;
+
+	cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+	if (cpu_id >= PLAT_MAX_CORES_PER_CLUSTER)
+		return -1;
+
+	return sq_calc_core_pos(mpidr);
+}
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	int i;
+
+	sq_pd_tree_desc[0] = PLAT_CLUSTER_COUNT;
+
+	for (i = 0; i < PLAT_CLUSTER_COUNT; i++)
+		sq_pd_tree_desc[i + 1] = PLAT_MAX_CORES_PER_CLUSTER;
+
+	return sq_pd_tree_desc;
+}
diff --git a/plat/socionext/synquacer/sq_xlat_setup.c b/plat/socionext/synquacer/sq_xlat_setup.c
new file mode 100644
index 0000000..ae14700
--- /dev/null
+++ b/plat/socionext/synquacer/sq_xlat_setup.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <platform_def.h>
+#include <xlat_tables_v2.h>
+
+#define SQ_REG_REGION_BASE	0x20000000ULL
+#define SQ_REG_REGION_SIZE	0x60000000ULL
+
+void sq_mmap_setup(uintptr_t total_base, size_t total_size,
+			 const struct mmap_region *mmap)
+{
+	VERBOSE("Trusted RAM seen by this BL image: %p - %p\n",
+		(void *)total_base, (void *)(total_base + total_size));
+	mmap_add_region(total_base, total_base,
+			total_size,
+			MT_NON_CACHEABLE | MT_RW | MT_SECURE);
+
+	/* remap the code section */
+	VERBOSE("Code region: %p - %p\n",
+		(void *)BL_CODE_BASE, (void *)BL_CODE_END);
+	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+			round_up(BL_CODE_END, PAGE_SIZE) - BL_CODE_BASE,
+			MT_NON_CACHEABLE | MT_RO | MT_SECURE);
+
+	/* Re-map the read-only data section */
+	VERBOSE("Read-only data region: %p - %p\n",
+		(void *)BL_RO_DATA_BASE, (void *)BL_RO_DATA_END);
+	mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
+			round_up(BL_RO_DATA_END, PAGE_SIZE) - BL_RO_DATA_BASE,
+			(MT_NON_CACHEABLE | MT_RO | MT_EXECUTE_NEVER |
+			 MT_SECURE));
+
+	/* remap the coherent memory region */
+	VERBOSE("Coherent region: %p - %p\n",
+		(void *)BL_COHERENT_RAM_BASE, (void *)BL_COHERENT_RAM_END);
+	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);
+
+	/* register region */
+	mmap_add_region(SQ_REG_REGION_BASE, SQ_REG_REGION_BASE,
+			SQ_REG_REGION_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE);
+
+	/* additional regions if needed */
+	if (mmap)
+		mmap_add(mmap);
+
+	init_xlat_tables();
+}
diff --git a/plat/socionext/uniphier/uniphier_cci.c b/plat/socionext/uniphier/uniphier_cci.c
index 30f4b47..9e00c56 100644
--- a/plat/socionext/uniphier/uniphier_cci.c
+++ b/plat/socionext/uniphier/uniphier_cci.c
@@ -13,7 +13,7 @@
 
 #define UNIPHIER_CCI500_BASE	0x5FD00000
 
-static const int uniphier_cci_map[] = {0, 1};
+static const int uniphier_cci_map[] = {1, 0};
 
 static void __uniphier_cci_init(void)
 {
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..c87936c 100644
--- a/readme.rst
+++ b/readme.rst
@@ -182,7 +182,8 @@
 -  QEMU emulator
 -  Raspberry Pi 3 board
 -  RockChip RK3328, RK3368 and RK3399 SoCs
--  Socionext UniPhier SoC family
+-  Socionext UniPhier SoC family and SynQuacer SC2A11 SoCs
+-  Texas Instruments K3 SoCs
 -  Xilinx Zynq UltraScale + MPSoC
 
 Still to come
diff --git a/services/std_svc/sdei/sdei_dispatch.S b/services/std_svc/sdei/sdei_dispatch.S
new file mode 100644
index 0000000..a7a4a40
--- /dev/null
+++ b/services/std_svc/sdei/sdei_dispatch.S
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+	.globl	begin_sdei_synchronous_dispatch
+
+/*
+ * void begin_sdei_synchronous_dispatch(struct jmpbuf *buffer);
+ *
+ * Begin SDEI dispatch synchronously by setting up a jump point, and exiting
+ * EL3. This jump point is jumped to by the dispatcher after the event is
+ * completed by the client.
+ */
+func begin_sdei_synchronous_dispatch
+	stp	x30, xzr, [sp, #-16]!
+	bl	setjmp
+	cbz	x0, 1f
+	ldp	x30, xzr, [sp], #16
+	ret
+1:
+	b	el3_exit
+endfunc begin_sdei_synchronous_dispatch
diff --git a/services/std_svc/sdei/sdei_intr_mgmt.c b/services/std_svc/sdei/sdei_intr_mgmt.c
index c0bd9de..a37188a 100644
--- a/services/std_svc/sdei/sdei_intr_mgmt.c
+++ b/services/std_svc/sdei/sdei_intr_mgmt.c
@@ -8,7 +8,6 @@
 #include <assert.h>
 #include <bl_common.h>
 #include <cassert.h>
-#include <context_mgmt.h>
 #include <debug.h>
 #include <ehf.h>
 #include <interrupt_mgmt.h>
@@ -32,9 +31,8 @@
 /* Structure to store information about an outstanding dispatch */
 typedef struct sdei_dispatch_context {
 	sdei_ev_map_t *map;
-	unsigned int sec_state;
-	unsigned int intr_raw;
 	uint64_t x[SDEI_SAVED_GPREGS];
+	struct jmpbuf *dispatch_jmp;
 
 	/* Exception state registers */
 	uint64_t elr_el3;
@@ -154,8 +152,8 @@
 	return &state->dispatch_stack[state->stack_top - 1];
 }
 
-static void save_event_ctx(sdei_ev_map_t *map, void *tgt_ctx, int sec_state,
-		unsigned int intr_raw)
+static sdei_dispatch_context_t *save_event_ctx(sdei_ev_map_t *map,
+		void *tgt_ctx)
 {
 	sdei_dispatch_context_t *disp_ctx;
 	gp_regs_t *tgt_gpregs;
@@ -167,26 +165,14 @@
 
 	disp_ctx = push_dispatch();
 	assert(disp_ctx);
-	disp_ctx->sec_state = sec_state;
 	disp_ctx->map = map;
-	disp_ctx->intr_raw = intr_raw;
 
 	/* Save general purpose and exception registers */
 	memcpy(disp_ctx->x, tgt_gpregs, sizeof(disp_ctx->x));
 	disp_ctx->spsr_el3 = read_ctx_reg(tgt_el3, CTX_SPSR_EL3);
 	disp_ctx->elr_el3 = read_ctx_reg(tgt_el3, CTX_ELR_EL3);
 
-#if DYNAMIC_WORKAROUND_CVE_2018_3639
-	cve_2018_3639_t *tgt_cve_2018_3639;
-	tgt_cve_2018_3639 = get_cve_2018_3639_ctx(tgt_ctx);
-
-	/* Save CVE-2018-3639 mitigation state */
-	disp_ctx->disable_cve_2018_3639 = read_ctx_reg(tgt_cve_2018_3639,
-		CTX_CVE_2018_3639_DISABLE);
-
-	/* Force SDEI handler to execute with mitigation enabled by default */
-	write_ctx_reg(tgt_cve_2018_3639, CTX_CVE_2018_3639_DISABLE, 0);
-#endif
+	return disp_ctx;
 }
 
 static void restore_event_ctx(sdei_dispatch_context_t *disp_ctx, void *tgt_ctx)
@@ -250,13 +236,12 @@
  * SDEI client.
  */
 static void setup_ns_dispatch(sdei_ev_map_t *map, sdei_entry_t *se,
-		cpu_context_t *ctx, int sec_state_to_resume,
-		unsigned int intr_raw)
+		cpu_context_t *ctx, struct jmpbuf *dispatch_jmp)
 {
-	el3_state_t *el3_ctx = get_el3state_ctx(ctx);
+	sdei_dispatch_context_t *disp_ctx;
 
 	/* Push the event and context */
-	save_event_ctx(map, ctx, sec_state_to_resume, intr_raw);
+	disp_ctx = save_event_ctx(map, ctx);
 
 	/*
 	 * Setup handler arguments:
@@ -268,8 +253,8 @@
 	 */
 	SMC_SET_GP(ctx, CTX_GPREG_X0, map->ev_num);
 	SMC_SET_GP(ctx, CTX_GPREG_X1, se->arg);
-	SMC_SET_GP(ctx, CTX_GPREG_X2, read_ctx_reg(el3_ctx, CTX_ELR_EL3));
-	SMC_SET_GP(ctx, CTX_GPREG_X3, read_ctx_reg(el3_ctx, CTX_SPSR_EL3));
+	SMC_SET_GP(ctx, CTX_GPREG_X2, disp_ctx->elr_el3);
+	SMC_SET_GP(ctx, CTX_GPREG_X3, disp_ctx->spsr_el3);
 
 	/*
 	 * Prepare for ERET:
@@ -280,6 +265,20 @@
 	cm_set_elr_spsr_el3(NON_SECURE, (uintptr_t) se->ep,
 			SPSR_64(sdei_client_el(), MODE_SP_ELX,
 				DISABLE_ALL_EXCEPTIONS));
+
+#if DYNAMIC_WORKAROUND_CVE_2018_3639
+	cve_2018_3639_t *tgt_cve_2018_3639;
+	tgt_cve_2018_3639 = get_cve_2018_3639_ctx(ctx);
+
+	/* Save CVE-2018-3639 mitigation state */
+	disp_ctx->disable_cve_2018_3639 = read_ctx_reg(tgt_cve_2018_3639,
+		CTX_CVE_2018_3639_DISABLE);
+
+	/* Force SDEI handler to execute with mitigation enabled by default */
+	write_ctx_reg(tgt_cve_2018_3639, CTX_CVE_2018_3639_DISABLE, 0);
+#endif
+
+	disp_ctx->dispatch_jmp = dispatch_jmp;
 }
 
 /* Handle a triggered SDEI interrupt while events were masked on this PE */
@@ -349,6 +348,7 @@
 	unsigned int sec_state;
 	sdei_cpu_state_t *state;
 	uint32_t intr;
+	struct jmpbuf dispatch_jmp;
 
 	/*
 	 * To handle an event, the following conditions must be true:
@@ -482,29 +482,60 @@
 		ctx = restore_and_resume_ns_context();
 	}
 
-	setup_ns_dispatch(map, se, ctx, sec_state, intr_raw);
+	/* Synchronously dispatch event */
+	setup_ns_dispatch(map, se, ctx, &dispatch_jmp);
+	begin_sdei_synchronous_dispatch(&dispatch_jmp);
 
 	/*
-	 * End of interrupt is done in sdei_event_complete, when the client
-	 * signals completion.
+	 * We reach here when client completes the event.
+	 *
+	 * If the cause of dispatch originally interrupted the Secure world, and
+	 * if Non-secure world wasn't allowed to preempt Secure execution,
+	 * resume Secure.
+	 *
+	 * No need to save the Non-secure context ahead of a world switch: the
+	 * Non-secure context was fully saved before dispatch, and has been
+	 * returned to its pre-dispatch state.
 	 */
+	if ((sec_state == SECURE) && (ehf_is_ns_preemption_allowed() == 0))
+		restore_and_resume_secure_context();
+
+	/*
+	 * The event was dispatched after receiving SDEI interrupt. With
+	 * the event handling completed, EOI the corresponding
+	 * interrupt.
+	 */
+	if ((map->ev_num != SDEI_EVENT_0) && !is_map_bound(map)) {
+		ERROR("Invalid SDEI mapping: ev=%u\n", map->ev_num);
+		panic();
+	}
+	plat_ic_end_of_interrupt(intr_raw);
+
+	if (is_event_shared(map))
+		sdei_map_unlock(map);
+
 	return 0;
 }
 
-/* Explicitly dispatch the given SDEI event */
-int sdei_dispatch_event(int ev_num, unsigned int preempted_sec_state)
+/*
+ * Explicitly dispatch the given SDEI event.
+ *
+ * When calling this API, the caller must be prepared for the SDEI dispatcher to
+ * restore and make Non-secure context as active. This call returns only after
+ * the client has completed the dispatch. Then, the Non-secure context will be
+ * active, and the following ERET will return to Non-secure.
+ *
+ * Should the caller require re-entry to Secure, it must restore the Secure
+ * context and program registers for ERET.
+ */
+int sdei_dispatch_event(int ev_num)
 {
 	sdei_entry_t *se;
 	sdei_ev_map_t *map;
-	cpu_context_t *ctx;
+	cpu_context_t *ns_ctx;
 	sdei_dispatch_context_t *disp_ctx;
 	sdei_cpu_state_t *state;
-
-	/* Validate preempted security state */
-	if ((preempted_sec_state != SECURE) &&
-			(preempted_sec_state != NON_SECURE)) {
-		return -1;
-	}
+	struct jmpbuf dispatch_jmp;
 
 	/* Can't dispatch if events are masked on this PE */
 	state = sdei_get_this_pe_state();
@@ -520,15 +551,8 @@
 	if (!map)
 		return -1;
 
-	/*
-	 * Statically-bound or dynamic maps are dispatched only as a result of
-	 * interrupt, and not upon explicit request.
-	 */
-	if (is_map_dynamic(map) || is_map_bound(map))
-		return -1;
-
-	/* The event must be private */
-	if (is_event_shared(map))
+	/* Only explicit events can be dispatched */
+	if (!is_map_explicit(map))
 		return -1;
 
 	/* Examine state of dispatch stack */
@@ -557,21 +581,31 @@
 	ehf_activate_priority(sdei_event_priority(map));
 
 	/*
-	 * We assume the current context is SECURE, and that it's already been
-	 * saved.
+	 * Prepare for NS dispatch by restoring the Non-secure context and
+	 * marking that as active.
 	 */
-	ctx = restore_and_resume_ns_context();
+	ns_ctx = restore_and_resume_ns_context();
+
+	/* Dispatch event synchronously */
+	setup_ns_dispatch(map, se, ns_ctx, &dispatch_jmp);
+	begin_sdei_synchronous_dispatch(&dispatch_jmp);
 
 	/*
-	 * The caller has effectively terminated execution. Record to resume the
-	 * preempted context later when the event completes or
-	 * complete-and-resumes.
+	 * We reach here when client completes the event.
+	 *
+	 * Deactivate the priority level that was activated at the time of
+	 * explicit dispatch.
 	 */
-	setup_ns_dispatch(map, se, ctx, preempted_sec_state, 0);
+	ehf_deactivate_priority(sdei_event_priority(map));
 
 	return 0;
 }
 
+static void end_sdei_synchronous_dispatch(struct jmpbuf *buffer)
+{
+	longjmp(buffer);
+}
+
 int sdei_event_complete(int resume, uint64_t pc)
 {
 	sdei_dispatch_context_t *disp_ctx;
@@ -644,38 +678,8 @@
 		}
 	}
 
-	/*
-	 * If the cause of dispatch originally interrupted the Secure world, and
-	 * if Non-secure world wasn't allowed to preempt Secure execution,
-	 * resume Secure.
-	 *
-	 * No need to save the Non-secure context ahead of a world switch: the
-	 * Non-secure context was fully saved before dispatch, and has been
-	 * returned to its pre-dispatch state.
-	 */
-	if ((disp_ctx->sec_state == SECURE) &&
-			(ehf_is_ns_preemption_allowed() == 0)) {
-		restore_and_resume_secure_context();
-	}
-
-	if ((map->ev_num == SDEI_EVENT_0) || is_map_bound(map)) {
-		/*
-		 * The event was dispatched after receiving SDEI interrupt. With
-		 * the event handling completed, EOI the corresponding
-		 * interrupt.
-		 */
-		plat_ic_end_of_interrupt(disp_ctx->intr_raw);
-	} else {
-		/*
-		 * An unbound event must have been dispatched explicitly.
-		 * Deactivate the priority level that was activated at the time
-		 * of explicit dispatch.
-		 */
-		ehf_deactivate_priority(sdei_event_priority(map));
-	}
-
-	if (is_event_shared(map))
-		sdei_map_unlock(map);
+	/* End the outstanding dispatch */
+	end_sdei_synchronous_dispatch(disp_ctx->dispatch_jmp);
 
 	return 0;
 }
diff --git a/services/std_svc/sdei/sdei_main.c b/services/std_svc/sdei/sdei_main.c
index 9589a25..d6d092d 100644
--- a/services/std_svc/sdei/sdei_main.c
+++ b/services/std_svc/sdei/sdei_main.c
@@ -1,5 +1,5 @@
 /*
- * 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
  */
@@ -10,7 +10,6 @@
 #include <bl_common.h>
 #include <cassert.h>
 #include <context.h>
-#include <context_mgmt.h>
 #include <debug.h>
 #include <ehf.h>
 #include <interrupt_mgmt.h>
@@ -111,6 +110,9 @@
 
 		/* No shared mapping should have signalable property */
 		assert(!is_event_signalable(map));
+
+		/* Shared mappings can't be explicit */
+		assert(!is_map_explicit(map));
 #endif
 
 		/* Skip initializing the wrong priority */
@@ -162,6 +164,16 @@
 
 		/* Make sure it's a private event */
 		assert(is_event_private(map));
+
+		/*
+		 * Other than priority, explicit events can only have explicit
+		 * and private flags set.
+		 */
+		if (is_map_explicit(map)) {
+			assert((map->map_flags | SDEI_MAPF_CRITICAL) ==
+					(SDEI_MAPF_EXPLICIT | SDEI_MAPF_PRIVATE
+					| SDEI_MAPF_CRITICAL));
+		}
 #endif
 
 		/* Skip initializing the wrong priority */
@@ -174,6 +186,12 @@
 				assert(map->intr == SDEI_DYN_IRQ);
 				assert(is_event_normal(map));
 				num_dyn_priv_slots++;
+			} else if (is_map_explicit(map)) {
+				/*
+				 * Explicit mappings don't have a backing
+				 * SDEI interrupt, but verify that anyway.
+				 */
+				assert(map->intr == SDEI_DYN_IRQ);
 			} else {
 				/*
 				 * Private mappings must be bound to private
diff --git a/services/std_svc/sdei/sdei_private.h b/services/std_svc/sdei/sdei_private.h
index 44db419..874fc22 100644
--- a/services/std_svc/sdei/sdei_private.h
+++ b/services/std_svc/sdei/sdei_private.h
@@ -1,5 +1,5 @@
 /*
- * 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
  */
@@ -8,11 +8,13 @@
 #define __SDEI_PRIVATE_H__
 
 #include <arch_helpers.h>
+#include <context_mgmt.h>
 #include <debug.h>
 #include <errno.h>
 #include <interrupt_mgmt.h>
 #include <platform.h>
 #include <sdei.h>
+#include <setjmp.h>
 #include <spinlock.h>
 #include <stdbool.h>
 #include <types.h>
@@ -137,6 +139,11 @@
 	map->map_flags |= BIT(_SDEI_MAPF_BOUND_SHIFT);
 }
 
+static inline int is_map_explicit(sdei_ev_map_t *map)
+{
+	return ((map->map_flags & BIT(_SDEI_MAPF_EXPLICIT_SHIFT)) != 0);
+}
+
 static inline void clr_map_bound(sdei_ev_map_t *map)
 {
 	map->map_flags &= ~(BIT(_SDEI_MAPF_BOUND_SHIFT));
@@ -154,7 +161,11 @@
  */
 static inline unsigned int sdei_client_el(void)
 {
-	return read_scr_el3() & SCR_HCE_BIT ? MODE_EL2 : MODE_EL1;
+	cpu_context_t *ns_ctx = cm_get_context(NON_SECURE);
+	el3_state_t *el3_ctx = get_el3state_ctx(ns_ctx);
+
+	return read_ctx_reg(el3_ctx, CTX_SCR_EL3) & SCR_HCE_BIT ? MODE_EL2 :
+		MODE_EL1;
 }
 
 static inline unsigned int sdei_event_priority(sdei_ev_map_t *map)
@@ -230,5 +241,6 @@
 int sdei_intr_handler(uint32_t intr, uint32_t flags, void *handle,
 		void *cookie);
 bool can_sdei_state_trans(sdei_entry_t *se, sdei_action_t act);
+void begin_sdei_synchronous_dispatch(struct jmpbuf *buffer);
 
 #endif /* __SDEI_PRIVATE_H__ */
diff --git a/services/std_svc/spm/sp_setup.c b/services/std_svc/spm/sp_setup.c
index de27e3e..b9b67f7 100644
--- a/services/std_svc/spm/sp_setup.c
+++ b/services/std_svc/spm/sp_setup.c
@@ -33,16 +33,11 @@
 	entry_point_info_t ep_info = {0};
 
 	SET_PARAM_HEAD(&ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE);
+
+	/* Setup entrypoint and SPSR */
 	ep_info.pc = BL32_BASE;
 	ep_info.spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS);
 
-	cm_setup_context(ctx, &ep_info);
-
-	/*
-	 * General-Purpose registers
-	 * -------------------------
-	 */
-
 	/*
 	 * X0: Virtual address of a buffer shared between EL3 and Secure EL0.
 	 *     The buffer will be mapped in the Secure EL1 translation regime
@@ -55,12 +50,14 @@
 	 *
 	 * X3: cookie value (Implementation Defined)
 	 *
-	 * X4 to X30 = 0 (already done by cm_init_my_context())
+	 * X4 to X7 = 0
 	 */
-	write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X0, PLAT_SPM_BUF_BASE);
-	write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X1, PLAT_SPM_BUF_SIZE);
-	write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X2, PLAT_SPM_COOKIE_0);
-	write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X3, PLAT_SPM_COOKIE_1);
+	ep_info.args.arg0 = PLAT_SPM_BUF_BASE;
+	ep_info.args.arg1 = PLAT_SPM_BUF_SIZE;
+	ep_info.args.arg2 = PLAT_SPM_COOKIE_0;
+	ep_info.args.arg3 = PLAT_SPM_COOKIE_1;
+
+	cm_setup_context(ctx, &ep_info);
 
 	/*
 	 * SP_EL0: A non-zero value will indicate to the SP that the SPM has
@@ -78,45 +75,18 @@
 #if ENABLE_ASSERTIONS
 
 	/* Get max granularity supported by the platform. */
+	unsigned int max_granule = xlat_arch_get_max_supported_granule_size();
 
-	u_register_t id_aa64mmfr0_el1 = read_id_aa64mmfr0_el1();
+	VERBOSE("Max translation granule size supported: %u KiB\n",
+		max_granule / 1024U);
 
-	int tgran64_supported =
-		((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN64_SHIFT) &
-		 ID_AA64MMFR0_EL1_TGRAN64_MASK) ==
-		 ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED;
-
-	int tgran16_supported =
-		((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN16_SHIFT) &
-		 ID_AA64MMFR0_EL1_TGRAN16_MASK) ==
-		 ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED;
-
-	int tgran4_supported =
-		((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN4_SHIFT) &
-		 ID_AA64MMFR0_EL1_TGRAN4_MASK) ==
-		 ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED;
-
-	uintptr_t max_granule_size;
-
-	if (tgran64_supported) {
-		max_granule_size = 64 * 1024;
-	} else if (tgran16_supported) {
-		max_granule_size = 16 * 1024;
-	} else {
-		assert(tgran4_supported);
-		max_granule_size = 4 * 1024;
-	}
-
-	VERBOSE("Max translation granule supported: %lu KiB\n",
-		max_granule_size / 1024);
-
-	uintptr_t max_granule_size_mask = max_granule_size - 1;
+	unsigned int max_granule_mask = max_granule - 1U;
 
 	/* Base must be aligned to the max granularity */
-	assert((ARM_SP_IMAGE_NS_BUF_BASE & max_granule_size_mask) == 0);
+	assert((ARM_SP_IMAGE_NS_BUF_BASE & max_granule_mask) == 0);
 
 	/* Size must be a multiple of the max granularity */
-	assert((ARM_SP_IMAGE_NS_BUF_SIZE & max_granule_size_mask) == 0);
+	assert((ARM_SP_IMAGE_NS_BUF_SIZE & max_granule_mask) == 0);
 
 #endif /* ENABLE_ASSERTIONS */
 
diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c
index be76dc2..585707d 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;
@@ -162,13 +181,42 @@
 }
 
 /*******************************************************************************
+ * Function to perform a call to a Secure Partition.
+ ******************************************************************************/
+uint64_t spm_sp_call(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3)
+{
+	uint64_t rc;
+	sp_context_t *sp_ptr = &sp_ctx;
+
+	/* Wait until the Secure Partition is idle and set it to busy. */
+	sp_state_wait_switch(sp_ptr, SP_STATE_IDLE, SP_STATE_BUSY);
+
+	/* Set values for registers on SP entry */
+	cpu_context_t *cpu_ctx = &(sp_ptr->cpu_ctx);
+
+	write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X0, smc_fid);
+	write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X1, x1);
+	write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X2, x2);
+	write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X3, x3);
+
+	/* Jump to the Secure Partition. */
+	rc = spm_sp_synchronous_entry(sp_ptr);
+
+	/* Flag Secure Partition as idle. */
+	assert(sp_ptr->state == SP_STATE_BUSY);
+	sp_state_set(sp_ptr, SP_STATE_IDLE);
+
+	return rc;
+}
+
+/*******************************************************************************
  * MM_COMMUNICATE handler
  ******************************************************************************/
 static uint64_t mm_communicate(uint32_t smc_fid, uint64_t mm_cookie,
 			       uint64_t comm_buffer_address,
 			       uint64_t comm_size_address, void *handle)
 {
-	sp_context_t *ctx = &sp_ctx;
+	uint64_t rc;
 
 	/* Cookie. Reserved for future use. It must be zero. */
 	if (mm_cookie != 0U) {
@@ -188,59 +236,14 @@
 	/* Save the Normal world context */
 	cm_el1_sysregs_context_save(NON_SECURE);
 
-	/* 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;
-
-	/* Save secure state */
-	cm_el1_sysregs_context_save(SECURE);
-
-	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.
-	 */
-
-	/* Mark 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);
+	rc = spm_sp_call(smc_fid, comm_buffer_address, comm_size_address,
+			 plat_my_core_pos());
 
 	/* 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 +278,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 +308,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