Merge pull request #1194 from robertovargas-arm/io-fix

io: block: fix block_read/write may read/write overlap buffer
diff --git a/Makefile b/Makefile
index 9894c5c..51e622e 100644
--- a/Makefile
+++ b/Makefile
@@ -125,21 +125,30 @@
 OD			:=	${CROSS_COMPILE}objdump
 NM			:=	${CROSS_COMPILE}nm
 PP			:=	${CROSS_COMPILE}gcc -E
+DTC			?=	dtc
+
+ifeq (${ARM_ARCH_MAJOR},7)
+target32-directive	= 	-target arm-none-eabi
+# Will set march32-directive from platform configuration
+else
+target32-directive	= 	-target armv8a-none-eabi
+march32-directive	= 	-march=armv8-a
+endif
 
 ifeq ($(notdir $(CC)),armclang)
-TF_CFLAGS_aarch32	=	-target arm-arm-none-eabi -march=armv8-a
+TF_CFLAGS_aarch32	=	-target arm-arm-none-eabi $(march32-directive)
 TF_CFLAGS_aarch64	=	-target aarch64-arm-none-eabi -march=armv8-a
 else ifneq ($(findstring clang,$(notdir $(CC))),)
-TF_CFLAGS_aarch32	=	-target armv8a-none-eabi
+TF_CFLAGS_aarch32	=	$(target32-directive)
 TF_CFLAGS_aarch64	=	-target aarch64-elf
 else
-TF_CFLAGS_aarch32	=	-march=armv8-a
+TF_CFLAGS_aarch32	=	$(march32-directive)
 TF_CFLAGS_aarch64	=	-march=armv8-a
 endif
 
 TF_CFLAGS_aarch64	+=	-mgeneral-regs-only -mstrict-align
 
-ASFLAGS_aarch32		=	-march=armv8-a
+ASFLAGS_aarch32		=	$(march32-directive)
 ASFLAGS_aarch64		=	-march=armv8-a
 
 CPPFLAGS		=	${DEFINES} ${INCLUDES} -nostdinc		\
@@ -155,6 +164,8 @@
 TF_LDFLAGS		+=	--gc-sections
 TF_LDFLAGS		+=	$(TF_LDFLAGS_$(ARCH))
 
+DTC_FLAGS		+=	-I dts -O dtb
+
 ################################################################################
 # Common sources and include directories
 ################################################################################
@@ -263,6 +274,10 @@
 
 $(eval $(call MAKE_PREREQ_DIR,${BUILD_PLAT}))
 
+ifeq (${ARM_ARCH_MAJOR},7)
+include make_helpers/armv7-a-cpus.mk
+endif
+
 # Platform compatibility is not supported in AArch32
 ifneq (${ARCH},aarch32)
 # If the platform has not defined ENABLE_PLAT_COMPAT, then enable it by default
@@ -371,6 +386,17 @@
         NEED_SCP_BL2		:=	yes
 endif
 
+# For AArch32, BL31 is not currently supported.
+ifneq (${ARCH},aarch32)
+    ifdef BL31_SOURCES
+        # When booting an EL3 payload, there is no need to compile the BL31 image nor
+        # put it in the FIP.
+        ifndef EL3_PAYLOAD_BASE
+            NEED_BL31 := yes
+        endif
+    endif
+endif
+
 # Process TBB related flags
 ifneq (${GENERATE_COT},0)
         # Common cert_create options
@@ -422,16 +448,14 @@
 include bl2u/bl2u.mk
 endif
 
-# For AArch32, BL31 is not currently supported.
-ifneq (${ARCH},aarch32)
+ifeq (${NEED_BL31},yes)
 ifdef BL31_SOURCES
-# When booting an EL3 payload, there is no need to compile the BL31 image nor
-# put it in the FIP.
-ifndef EL3_PAYLOAD_BASE
-NEED_BL31 := yes
 include bl31/bl31.mk
 endif
 endif
+
+ifdef FDT_SOURCES
+NEED_FDT := yes
 endif
 
 ################################################################################
@@ -444,12 +468,14 @@
 $(eval $(call assert_boolean,CTX_INCLUDE_FPREGS))
 $(eval $(call assert_boolean,DEBUG))
 $(eval $(call assert_boolean,DISABLE_PEDANTIC))
+$(eval $(call assert_boolean,ENABLE_AMU))
 $(eval $(call assert_boolean,ENABLE_ASSERTIONS))
 $(eval $(call assert_boolean,ENABLE_PLAT_COMPAT))
 $(eval $(call assert_boolean,ENABLE_PMF))
 $(eval $(call assert_boolean,ENABLE_PSCI_STAT))
 $(eval $(call assert_boolean,ENABLE_RUNTIME_INSTRUMENTATION))
 $(eval $(call assert_boolean,ENABLE_SPE_FOR_LOWER_ELS))
+$(eval $(call assert_boolean,ENABLE_SVE_FOR_NS))
 $(eval $(call assert_boolean,ERROR_DEPRECATED))
 $(eval $(call assert_boolean,GENERATE_COT))
 $(eval $(call assert_boolean,GICV2_G0_FOR_EL3))
@@ -483,12 +509,14 @@
 $(eval $(call add_define,COLD_BOOT_SINGLE_CPU))
 $(eval $(call add_define,CTX_INCLUDE_AARCH32_REGS))
 $(eval $(call add_define,CTX_INCLUDE_FPREGS))
+$(eval $(call add_define,ENABLE_AMU))
 $(eval $(call add_define,ENABLE_ASSERTIONS))
 $(eval $(call add_define,ENABLE_PLAT_COMPAT))
 $(eval $(call add_define,ENABLE_PMF))
 $(eval $(call add_define,ENABLE_PSCI_STAT))
 $(eval $(call add_define,ENABLE_RUNTIME_INSTRUMENTATION))
 $(eval $(call add_define,ENABLE_SPE_FOR_LOWER_ELS))
+$(eval $(call add_define,ENABLE_SVE_FOR_NS))
 $(eval $(call add_define,ERROR_DEPRECATED))
 $(eval $(call add_define,GICV2_G0_FOR_EL3))
 $(eval $(call add_define,HW_ASSISTED_COHERENCY))
@@ -530,7 +558,7 @@
 # Build targets
 ################################################################################
 
-.PHONY:	all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip fwu_fip certtool
+.PHONY:	all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip fwu_fip certtool dtbs
 .SUFFIXES:
 
 all: msg_start
@@ -583,6 +611,13 @@
 $(eval $(call FWU_FIP_ADD_PAYLOAD,${BL2U_PATH},--ap-fwu-cfg))
 endif
 
+# Expand build macros for the different images
+ifeq (${NEED_FDT},yes)
+$(eval $(call MAKE_DTBS,$(BUILD_PLAT)/fdts,$(FDT_SOURCES)))
+$(eval $(call MAKE_FDT))
+dtbs: $(DTBS)
+endif
+
 locate-checkpatch:
 ifndef CHECKPATCH
 	$(error "Please set CHECKPATCH to point to the Linux checkpatch.pl file, eg: CHECKPATCH=../linux/scripts/checkpatch.pl")
@@ -710,6 +745,7 @@
 	@echo "  distclean      Remove all build artifacts for all platforms"
 	@echo "  certtool       Build the Certificate generation tool"
 	@echo "  fiptool        Build the Firmware Image Package (FIP) creation tool"
+	@echo "  dtbs           Build the Flattened device tree (if required for the platform)"
 	@echo ""
 	@echo "Note: most build targets require PLAT to be set to a specific platform."
 	@echo ""
diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S
index 2c453bd..e4c454b 100644
--- a/bl1/bl1.ld.S
+++ b/bl1/bl1.ld.S
@@ -5,6 +5,7 @@
  */
 
 #include <platform_def.h>
+#include <xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
 OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
@@ -18,7 +19,7 @@
 SECTIONS
 {
     . = BL1_RO_BASE;
-    ASSERT(. == ALIGN(4096),
+    ASSERT(. == ALIGN(PAGE_SIZE),
            "BL1_RO_BASE address is not aligned on a page boundary.")
 
 #if SEPARATE_CODE_AND_RODATA
@@ -27,7 +28,7 @@
         *bl1_entrypoint.o(.text*)
         *(.text*)
         *(.vectors)
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __TEXT_END__ = .;
      } >ROM
 
@@ -88,7 +89,7 @@
            "cpu_ops not defined for this platform.")
 
     . = BL1_RW_BASE;
-    ASSERT(BL1_RW_BASE == ALIGN(4096),
+    ASSERT(BL1_RW_BASE == ALIGN(PAGE_SIZE),
            "BL1_RW_BASE address is not aligned on a page boundary.")
 
     /*
@@ -141,7 +142,7 @@
      * are not mixed with normal data.  This is required to set up the correct
      * memory attributes for the coherent data page tables.
      */
-    coherent_ram (NOLOAD) : ALIGN(4096) {
+    coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
         __COHERENT_RAM_START__ = .;
         *(tzfw_coherent_mem)
         __COHERENT_RAM_END_UNALIGNED__ = .;
@@ -150,7 +151,7 @@
          * as device memory.  No other unexpected data must creep in.
          * Ensure the rest of the current memory page is unused.
          */
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __COHERENT_RAM_END__ = .;
     } >RAM
 #endif
diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S
index f3ab706..4fe78f9 100644
--- a/bl2/bl2.ld.S
+++ b/bl2/bl2.ld.S
@@ -5,6 +5,7 @@
  */
 
 #include <platform_def.h>
+#include <xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
 OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
@@ -18,7 +19,7 @@
 SECTIONS
 {
     . = BL2_BASE;
-    ASSERT(. == ALIGN(4096),
+    ASSERT(. == ALIGN(PAGE_SIZE),
            "BL2_BASE address is not aligned on a page boundary.")
 
 #if SEPARATE_CODE_AND_RODATA
@@ -27,7 +28,7 @@
         *bl2_entrypoint.o(.text*)
         *(.text*)
         *(.vectors)
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __TEXT_END__ = .;
      } >RAM
 
@@ -41,7 +42,7 @@
         KEEP(*(.img_parser_lib_descs))
         __PARSER_LIB_DESCS_END__ = .;
 
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __RODATA_END__ = .;
     } >RAM
 #else
@@ -64,7 +65,7 @@
          * read-only, executable.  No RW data from the next section must
          * creep in.  Ensure the rest of the current memory page is unused.
          */
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __RO_END__ = .;
     } >RAM
 #endif
@@ -120,7 +121,7 @@
      * are not mixed with normal data.  This is required to set up the correct
      * memory attributes for the coherent data page tables.
      */
-    coherent_ram (NOLOAD) : ALIGN(4096) {
+    coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
         __COHERENT_RAM_START__ = .;
         *(tzfw_coherent_mem)
         __COHERENT_RAM_END_UNALIGNED__ = .;
@@ -129,7 +130,7 @@
          * as device memory.  No other unexpected data must creep in.
          * Ensure the rest of the current memory page is unused.
          */
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __COHERENT_RAM_END__ = .;
     } >RAM
 #endif
diff --git a/bl2u/bl2u.ld.S b/bl2u/bl2u.ld.S
index efae293..da58717 100644
--- a/bl2u/bl2u.ld.S
+++ b/bl2u/bl2u.ld.S
@@ -5,6 +5,7 @@
  */
 
 #include <platform_def.h>
+#include <xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
 OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
@@ -18,7 +19,7 @@
 SECTIONS
 {
     . = BL2U_BASE;
-    ASSERT(. == ALIGN(4096),
+    ASSERT(. == ALIGN(PAGE_SIZE),
            "BL2U_BASE address is not aligned on a page boundary.")
 
 #if SEPARATE_CODE_AND_RODATA
@@ -27,14 +28,14 @@
         *bl2u_entrypoint.o(.text*)
         *(.text*)
         *(.vectors)
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __TEXT_END__ = .;
      } >RAM
 
     .rodata . : {
         __RODATA_START__ = .;
         *(.rodata*)
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __RODATA_END__ = .;
     } >RAM
 #else
@@ -51,7 +52,7 @@
          * read-only, executable.  No RW data from the next section must
          * creep in.  Ensure the rest of the current memory page is unused.
          */
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __RO_END__ = .;
     } >RAM
 #endif
@@ -107,7 +108,7 @@
      * are not mixed with normal data.  This is required to set up the correct
      * memory attributes for the coherent data page tables.
      */
-    coherent_ram (NOLOAD) : ALIGN(4096) {
+    coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
         __COHERENT_RAM_START__ = .;
         *(tzfw_coherent_mem)
         __COHERENT_RAM_END_UNALIGNED__ = .;
@@ -116,7 +117,7 @@
          * as device memory.  No other unexpected data must creep in.
          * Ensure the rest of the current memory page is unused.
          */
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __COHERENT_RAM_END__ = .;
     } >RAM
 #endif
diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
index 7f442d0..dd046c4 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -5,6 +5,7 @@
  */
 
 #include <platform_def.h>
+#include <xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
 OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
@@ -22,7 +23,7 @@
 SECTIONS
 {
     . = BL31_BASE;
-    ASSERT(. == ALIGN(4096),
+    ASSERT(. == ALIGN(PAGE_SIZE),
            "BL31_BASE address is not aligned on a page boundary.")
 
 #if SEPARATE_CODE_AND_RODATA
@@ -31,7 +32,7 @@
         *bl31_entrypoint.o(.text*)
         *(.text*)
         *(.vectors)
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __TEXT_END__ = .;
     } >RAM
 
@@ -66,7 +67,7 @@
         . = ALIGN(8);
 #include <pubsub_events.h>
 
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __RODATA_END__ = .;
     } >RAM
 #else
@@ -110,7 +111,7 @@
          * executable.  No RW data from the next section must creep in.
          * Ensure the rest of the current memory page is unused.
          */
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __RO_END__ = .;
     } >RAM
 #endif
@@ -127,10 +128,10 @@
      * There's no need to include this into the RO section of BL31 because it
      * doesn't need to be accessed by BL31.
      */
-    spm_shim_exceptions : ALIGN(4096) {
+    spm_shim_exceptions : ALIGN(PAGE_SIZE) {
         __SPM_SHIM_EXCEPTIONS_START__ = .;
         *(.spm_shim_exceptions)
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __SPM_SHIM_EXCEPTIONS_END__ = .;
     } >RAM
 #endif
@@ -223,7 +224,7 @@
         __SP_IMAGE_XLAT_TABLES_START__ = .;
         *secure_partition*.o(xlat_table)
         /* Make sure that the rest of the page is empty. */
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __SP_IMAGE_XLAT_TABLES_END__ = .;
 #endif
         *(xlat_table)
@@ -236,7 +237,7 @@
      * are not mixed with normal data.  This is required to set up the correct
      * memory attributes for the coherent data page tables.
      */
-    coherent_ram (NOLOAD) : ALIGN(4096) {
+    coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
         __COHERENT_RAM_START__ = .;
         /*
          * Bakery locks are stored in coherent memory
@@ -251,7 +252,7 @@
          * as device memory.  No other unexpected data must creep in.
          * Ensure the rest of the current memory page is unused.
          */
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __COHERENT_RAM_END__ = .;
     } >RAM
 #endif
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index fccdc8a..fdcc931 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -50,6 +50,14 @@
 BL31_SOURCES		+=	lib/extensions/spe/spe.c
 endif
 
+ifeq (${ENABLE_AMU},1)
+BL31_SOURCES		+=	lib/extensions/amu/aarch64/amu.c
+endif
+
+ifeq (${ENABLE_SVE_FOR_NS},1)
+BL31_SOURCES		+=	lib/extensions/sve/sve.c
+endif
+
 BL31_LINKERFILE		:=	bl31/bl31.ld.S
 
 # Flag used to indicate if Crash reporting via console should be included
diff --git a/bl32/sp_min/aarch32/entrypoint.S b/bl32/sp_min/aarch32/entrypoint.S
index cd9fe5c..b2b7953 100644
--- a/bl32/sp_min/aarch32/entrypoint.S
+++ b/bl32/sp_min/aarch32/entrypoint.S
@@ -30,6 +30,16 @@
 		stcopr	\reg, SCR
 	.endm
 
+	.macro clrex_on_monitor_entry
+#if (ARM_ARCH_MAJOR == 7)
+	/*
+	 * ARMv7 architectures need to clear the exclusive access when
+	 * entering Monitor mode.
+	 */
+	clrex
+#endif
+	.endm
+
 vector_base sp_min_vector_table
 	b	sp_min_entrypoint
 	b	plat_panic_handler	/* Undef */
@@ -147,6 +157,8 @@
 
 	smcc_save_gp_mode_regs
 
+	clrex_on_monitor_entry
+
 	/*
 	 * `sp` still points to `smc_ctx_t`. Save it to a register
 	 * and restore the C runtime stack pointer to `sp`.
@@ -203,11 +215,7 @@
 
 	smcc_save_gp_mode_regs
 
-	/*
-	 * AArch32 architectures need to clear the exclusive access when
-	 * entering Monitor mode.
-	 */
-	clrex
+	clrex_on_monitor_entry
 
 	/* load run-time stack */
 	mov	r2, sp
diff --git a/bl32/sp_min/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S
index fc44d52..e798a0d 100644
--- a/bl32/sp_min/sp_min.ld.S
+++ b/bl32/sp_min/sp_min.ld.S
@@ -5,6 +5,7 @@
  */
 
 #include <platform_def.h>
+#include <xlat_tables_defs.h>
 
 OUTPUT_FORMAT(elf32-littlearm)
 OUTPUT_ARCH(arm)
@@ -18,7 +19,7 @@
 SECTIONS
 {
     . = BL32_BASE;
-   ASSERT(. == ALIGN(4096),
+   ASSERT(. == ALIGN(PAGE_SIZE),
           "BL32_BASE address is not aligned on a page boundary.")
 
 #if SEPARATE_CODE_AND_RODATA
@@ -27,7 +28,7 @@
         *entrypoint.o(.text*)
         *(.text*)
         *(.vectors)
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __TEXT_END__ = .;
     } >RAM
 
@@ -54,7 +55,7 @@
         . = ALIGN(8);
 #include <pubsub_events.h>
 
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __RODATA_END__ = .;
     } >RAM
 #else
@@ -91,7 +92,7 @@
          * read-only, executable.  No RW data from the next section must
          * creep in.  Ensure the rest of the current memory block is unused.
          */
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __RO_END__ = .;
     } >RAM
 #endif
@@ -110,6 +111,10 @@
         __DATA_END__ = .;
     } >RAM
 
+#ifdef BL32_PROGBITS_LIMIT
+    ASSERT(. <= BL32_PROGBITS_LIMIT, "BL32 progbits has exceeded its limit.")
+#endif
+
     stacks (NOLOAD) : {
         __STACKS_START__ = .;
         *(tzfw_normal_stacks)
@@ -186,7 +191,7 @@
      * are not mixed with normal data.  This is required to set up the correct
      * memory attributes for the coherent data page tables.
      */
-    coherent_ram (NOLOAD) : ALIGN(4096) {
+    coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
         __COHERENT_RAM_START__ = .;
         /*
          * Bakery locks are stored in coherent memory
@@ -201,7 +206,7 @@
          * as device memory.  No other unexpected data must creep in.
          * Ensure the rest of the current memory page is unused.
          */
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __COHERENT_RAM_END__ = .;
     } >RAM
 
diff --git a/bl32/sp_min/sp_min.mk b/bl32/sp_min/sp_min.mk
index 39588ce..56489a3 100644
--- a/bl32/sp_min/sp_min.mk
+++ b/bl32/sp_min/sp_min.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -22,6 +22,10 @@
 BL32_SOURCES		+=	lib/pmf/pmf_main.c
 endif
 
+ifeq (${ENABLE_AMU}, 1)
+BL32_SOURCES		+=	lib/extensions/amu/aarch32/amu.c
+endif
+
 BL32_LINKERFILE	:=	bl32/sp_min/sp_min.ld.S
 
 # Include the platform-specific SP_MIN Makefile
diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S
index 2b672ef..d256b46 100644
--- a/bl32/tsp/tsp.ld.S
+++ b/bl32/tsp/tsp.ld.S
@@ -5,6 +5,7 @@
  */
 
 #include <platform_def.h>
+#include <xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
 OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
@@ -19,7 +20,7 @@
 SECTIONS
 {
     . = BL32_BASE;
-    ASSERT(. == ALIGN(4096),
+    ASSERT(. == ALIGN(PAGE_SIZE),
            "BL32_BASE address is not aligned on a page boundary.")
 
 #if SEPARATE_CODE_AND_RODATA
@@ -28,14 +29,14 @@
         *tsp_entrypoint.o(.text*)
         *(.text*)
         *(.vectors)
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __TEXT_END__ = .;
     } >RAM
 
     .rodata . : {
         __RODATA_START__ = .;
         *(.rodata*)
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __RODATA_END__ = .;
     } >RAM
 #else
@@ -51,7 +52,7 @@
          * read-only, executable.  No RW data from the next section must
          * creep in.  Ensure the rest of the current memory page is unused.
          */
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __RO_END__ = .;
     } >RAM
 #endif
@@ -106,7 +107,7 @@
      * are not mixed with normal data.  This is required to set up the correct
      * memory attributes for the coherent data page tables.
      */
-    coherent_ram (NOLOAD) : ALIGN(4096) {
+    coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
         __COHERENT_RAM_START__ = .;
         *(tzfw_coherent_mem)
         __COHERENT_RAM_END_UNALIGNED__ = .;
@@ -115,7 +116,7 @@
          * as device memory.  No other unexpected data must creep in.
          * Ensure the rest of the current memory page is unused.
          */
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __COHERENT_RAM_END__ = .;
     } >RAM
 #endif
diff --git a/common/aarch32/debug.S b/common/aarch32/debug.S
index 583ee4a..f506356 100644
--- a/common/aarch32/debug.S
+++ b/common/aarch32/debug.S
@@ -71,7 +71,15 @@
 assert_msg1:
 	.asciz "ASSERT: File "
 assert_msg2:
+#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
+	/******************************************************************
+	 * Virtualization comes with the UDIV/SDIV instructions. If missing
+	 * write file line number in hexadecimal format.
+	 ******************************************************************/
+	.asciz " Line 0x"
+#else
 	.asciz " Line "
+#endif
 
 /* ---------------------------------------------------------------------------
  * Assertion support in assembly.
@@ -113,6 +121,13 @@
 	bne	1f
 	mov	r4, r6
 
+#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
+	/******************************************************************
+	 * Virtualization comes with the UDIV/SDIV instructions. If missing
+	 * write file line number in hexadecimal format.
+	 ******************************************************************/
+	bl	asm_print_hex
+#else
 	/* Print line number in decimal */
 	mov	r6, #10			/* Divide by 10 after every loop iteration */
 	ldr	r5, =MAX_DEC_DIVISOR
@@ -124,6 +139,7 @@
 	udiv	r5, r5, r6			/* Reduce divisor */
 	cmp	r5, #0
 	bne	dec_print_loop
+#endif
 
 	bl	plat_crash_console_flush
 
diff --git a/common/bl_common.c b/common/bl_common.c
index e4473ed..b0d1bfa 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -200,14 +200,14 @@
 #if LOAD_IMAGE_V2
 
 /*******************************************************************************
- * Generic function to load an image at a specific address given
+ * Internal function to load an image at a specific address given
  * an image ID and extents of free memory.
  *
  * If the load is successful then the image information is updated.
  *
  * Returns 0 on success, a negative error code otherwise.
  ******************************************************************************/
-int load_image(unsigned int image_id, image_info_t *image_data)
+static int load_image(unsigned int image_id, image_info_t *image_data)
 {
 	uintptr_t dev_handle;
 	uintptr_t image_handle;
@@ -266,17 +266,6 @@
 		goto exit;
 	}
 
-#if !TRUSTED_BOARD_BOOT
-	/*
-	 * File has been successfully loaded.
-	 * Flush the image to main memory so that it can be executed later by
-	 * any CPU, regardless of cache and MMU state.
-	 * When TBB is enabled the image is flushed later, after image
-	 * authentication.
-	 */
-	flush_dcache_range(image_base, image_size);
-#endif /* TRUSTED_BOARD_BOOT */
-
 	INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base,
 	     (void *) (image_base + image_size));
 
@@ -329,18 +318,19 @@
 				   image_data->image_size);
 		return -EAUTH;
 	}
+#endif /* TRUSTED_BOARD_BOOT */
 
 	/*
-	 * File has been successfully loaded and authenticated.
 	 * Flush the image to main memory so that it can be executed later by
-	 * any CPU, regardless of cache and MMU state.
-	 * Do it only for child images, not for the parents (certificates).
+	 * any CPU, regardless of cache and MMU state. If TBB is enabled, then
+	 * the file has been successfully loaded and authenticated and flush
+	 * only for child images, not for the parents (certificates).
 	 */
 	if (!is_parent_image) {
 		flush_dcache_range(image_data->image_base,
 				   image_data->image_size);
 	}
-#endif /* TRUSTED_BOARD_BOOT */
+
 
 	return 0;
 }
diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst
index c0ece0b..405964d 100644
--- a/docs/firmware-design.rst
+++ b/docs/firmware-design.rst
@@ -2519,6 +2519,35 @@
    table entries for a given stage of translation for a particular translation
    regime.
 
+ARMv7
+~~~~~
+
+This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` == 7.
+
+There are several ARMv7 extensions available. Obviously the TrustZone
+extension is mandatory to support the ARM Trusted Firmware bootloader
+and runtime services.
+
+Platform implementing an ARMv7 system can to define from its target
+Cortex-A architecture through ``ARM_CORTEX_A<X> = yes`` in their
+``plaform.mk`` script. For example ``ARM_CORTEX_A15=yes`` for a
+Cortex-A15 target.
+
+Platform can also set ``ARM_WITH_NEON=yes`` to enable neon support.
+Note that using neon at runtime has constraints on non secure wolrd context.
+The trusted firmware does not yet provide VFP context management.
+
+Directive ``ARM_CORTEX_A<x>`` and ``ARM_WITH_NEON`` are used to set
+the toolchain  target architecture directive.
+
+Platform may choose to not define straight the toolchain target architecture
+directive by defining ``MARCH32_DIRECTIVE``.
+I.e:
+
+::
+
+   MARCH32_DIRECTIVE := -mach=armv7-a
+
 Code Structure
 --------------
 
diff --git a/docs/plat/poplar.rst b/docs/plat/poplar.rst
index d7f1fe0..0129478 100644
--- a/docs/plat/poplar.rst
+++ b/docs/plat/poplar.rst
@@ -11,6 +11,8 @@
 It supports a premium user experience with up to H.265 HEVC decoding of 4K
 video at 60 frames per second.
 
+::
+
     SOC Hisilicon Hi3798CV200
     CPU Quad-core ARM Cortex-A53 64 bit
     DRAM DDR3/3L/4 SDRAM interface, maximum 32-bit data width 2 GB
@@ -28,6 +30,8 @@
 binary whose main role is to change the processor state to 64bit mode. This
 must  happen prior invoking the arm trusted  firmware:
 
+::
+
     l-loader --> arm_trusted_firmware --> u-boot
 
 How to build
@@ -54,10 +58,16 @@
 -  Prepare the AARCH64 toolchain.
 
 -  Build u-boot using poplar_defconfig
+
+.. code:: bash
+
        make CROSS_COMPILE=aarch64-linux-gnu- poplar_defconfig
        make CROSS_COMPILE=aarch64-linux-gnu-
 
 -  Build atf providing the previously generated u-boot.bin as the BL33 image
+
+.. code:: bash
+
        make CROSS_COMPILE=aarch64-linux-gnu-  all fip SPD=none PLAT=poplar
        BL33=u-boot.bin
 
@@ -81,85 +91,86 @@
 Boot trace
 ==========
 
-Bootrom start
-Boot Media: eMMC
-Decrypt auxiliary code ...OK
+::
 
-lsadc voltage min: 000000FE, max: 000000FF, aver: 000000FE, index: 00000000
+    Bootrom start
+    Boot Media: eMMC
+    Decrypt auxiliary code ...OK
 
-Entry boot auxiliary code
+    lsadc voltage min: 000000FE, max: 000000FF, aver: 000000FE, index: 00000000
 
-Auxiliary code - v1.00
-DDR code - V1.1.2 20160205
-Build: Mar 24 2016 - 17:09:44
-Reg Version:  v134
-Reg Time:     2016/03/18 09:44:55
-Reg Name:     hi3798cv2dmb_hi3798cv200_ddr3_2gbyte_8bitx4_4layers.reg
+    Entry boot auxiliary code
 
-Boot auxiliary code success
-Bootrom success
+    Auxiliary code - v1.00
+    DDR code - V1.1.2 20160205
+    Build: Mar 24 2016 - 17:09:44
+    Reg Version:  v134
+    Reg Time:     2016/03/18 09:44:55
+    Reg Name:     hi3798cv2dmb_hi3798cv200_ddr3_2gbyte_8bitx4_4layers.reg
 
-LOADER:  Switched to aarch64 mode
-LOADER:  Entering ARM TRUSTED FIRMWARE
-LOADER:  CPU0 executes at 0x000ce000
+    Boot auxiliary code success
+    Bootrom success
 
-INFO:    BL1: 0xe1000 - 0xe7000 [size = 24576]
-NOTICE:  Booting Trusted Firmware
-NOTICE:  BL1: v1.3(debug):v1.3-372-g1ba9c60
-NOTICE:  BL1: Built : 17:51:33, Apr 30 2017
-INFO:    BL1: RAM 0xe1000 - 0xe7000
-INFO:    BL1: Loading BL2
-INFO:    Loading image id=1 at address 0xe9000
-INFO:    Image id=1 loaded at address 0xe9000, size = 0x5008
-NOTICE:  BL1: Booting BL2
-INFO:    Entry point address = 0xe9000
-INFO:    SPSR = 0x3c5
-NOTICE:  BL2: v1.3(debug):v1.3-372-g1ba9c60
-NOTICE:  BL2: Built : 17:51:33, Apr 30 2017
-INFO:    BL2: Loading BL31
-INFO:    Loading image id=3 at address 0x129000
-INFO:    Image id=3 loaded at address 0x129000, size = 0x8038
-INFO:    BL2: Loading BL33
-INFO:    Loading image id=5 at address 0x37000000
-INFO:    Image id=5 loaded at address 0x37000000, size = 0x58f17
-NOTICE:  BL1: Booting BL31
-INFO:    Entry point address = 0x129000
-INFO:    SPSR = 0x3cd
-INFO:    Boot bl33 from 0x37000000 for 364311 Bytes
-NOTICE:  BL31: v1.3(debug):v1.3-372-g1ba9c60
-NOTICE:  BL31: Built : 17:51:33, Apr 30 2017
-INFO:    BL31: Initializing runtime services
-INFO:    BL31: Preparing for EL3 exit to normal world
-INFO:    Entry point address = 0x37000000
-INFO:    SPSR = 0x3c9
+    LOADER:  Switched to aarch64 mode
+    LOADER:  Entering ARM TRUSTED FIRMWARE
+    LOADER:  CPU0 executes at 0x000ce000
 
+    INFO:    BL1: 0xe1000 - 0xe7000 [size = 24576]
+    NOTICE:  Booting Trusted Firmware
+    NOTICE:  BL1: v1.3(debug):v1.3-372-g1ba9c60
+    NOTICE:  BL1: Built : 17:51:33, Apr 30 2017
+    INFO:    BL1: RAM 0xe1000 - 0xe7000
+    INFO:    BL1: Loading BL2
+    INFO:    Loading image id=1 at address 0xe9000
+    INFO:    Image id=1 loaded at address 0xe9000, size = 0x5008
+    NOTICE:  BL1: Booting BL2
+    INFO:    Entry point address = 0xe9000
+    INFO:    SPSR = 0x3c5
+    NOTICE:  BL2: v1.3(debug):v1.3-372-g1ba9c60
+    NOTICE:  BL2: Built : 17:51:33, Apr 30 2017
+    INFO:    BL2: Loading BL31
+    INFO:    Loading image id=3 at address 0x129000
+    INFO:    Image id=3 loaded at address 0x129000, size = 0x8038
+    INFO:    BL2: Loading BL33
+    INFO:    Loading image id=5 at address 0x37000000
+    INFO:    Image id=5 loaded at address 0x37000000, size = 0x58f17
+    NOTICE:  BL1: Booting BL31
+    INFO:    Entry point address = 0x129000
+    INFO:    SPSR = 0x3cd
+    INFO:    Boot bl33 from 0x37000000 for 364311 Bytes
+    NOTICE:  BL31: v1.3(debug):v1.3-372-g1ba9c60
+    NOTICE:  BL31: Built : 17:51:33, Apr 30 2017
+    INFO:    BL31: Initializing runtime services
+    INFO:    BL31: Preparing for EL3 exit to normal world
+    INFO:    Entry point address = 0x37000000
+    INFO:    SPSR = 0x3c9
 
-U-Boot 2017.05-rc2-00130-gd2255b0 (Apr 30 2017 - 17:51:28 +0200)poplar
 
-Model: HiSilicon Poplar Development Board
-BOARD: Hisilicon HI3798cv200 Poplar
-DRAM:  1 GiB
-MMC:   Hisilicon DWMMC: 0
-In:    serial@f8b00000
-Out:   serial@f8b00000
-Err:   serial@f8b00000
-Net:   Net Initialization Skipped
-No ethernet found.
+    U-Boot 2017.05-rc2-00130-gd2255b0 (Apr 30 2017 - 17:51:28 +0200)poplar
 
-Hit any key to stop autoboot:  0
-starting USB...
-USB0:   USB EHCI 1.00
-scanning bus 0 for devices... 1 USB Device(s) found
-USB1:   USB EHCI 1.00
-scanning bus 1 for devices... 4 USB Device(s) found
-       scanning usb for storage devices... 1 Storage Device(s) found
-       scanning usb for ethernet devices... 1 Ethernet Device(s) found
+    Model: HiSilicon Poplar Development Board
+    BOARD: Hisilicon HI3798cv200 Poplar
+    DRAM:  1 GiB
+    MMC:   Hisilicon DWMMC: 0
+    In:    serial@f8b00000
+    Out:   serial@f8b00000
+    Err:   serial@f8b00000
+    Net:   Net Initialization Skipped
+    No ethernet found.
 
-USB device 0:
-    Device 0: Vendor: SanDisk Rev: 1.00 Prod: Cruzer Blade
-            Type: Removable Hard Disk
-            Capacity: 7632.0 MB = 7.4 GB (15630336 x 512)
-... is now current device
-Scanning usb 0:1...
-=>
+    Hit any key to stop autoboot:  0
+    starting USB...
+    USB0:   USB EHCI 1.00
+    scanning bus 0 for devices... 1 USB Device(s) found
+    USB1:   USB EHCI 1.00
+    scanning bus 1 for devices... 4 USB Device(s) found
+           scanning usb for storage devices... 1 Storage Device(s) found
+           scanning usb for ethernet devices... 1 Ethernet Device(s) found
 
+    USB device 0:
+        Device 0: Vendor: SanDisk Rev: 1.00 Prod: Cruzer Blade
+                Type: Removable Hard Disk
+                Capacity: 7632.0 MB = 7.4 GB (15630336 x 512)
+    ... is now current device
+    Scanning usb 0:1...
+    =>
diff --git a/docs/plat/rpi3.rst b/docs/plat/rpi3.rst
new file mode 100644
index 0000000..219faaf
--- /dev/null
+++ b/docs/plat/rpi3.rst
@@ -0,0 +1,364 @@
+Arm Trusted Firmware for Raspberry Pi 3
+=======================================
+
+.. section-numbering::
+    :suffix: .
+
+.. contents::
+
+The `Raspberry Pi 3`_ is an inexpensive single-board computer that contains four
+Cortex-A53 cores, which makes it possible to have a port of the Arm Trusted
+Firmware.
+
+The following instructions explain how to use this port of the Trusted Firmware
+with the default distribution of `Raspbian`_ because that's the distribution
+officially supported by the Raspberry Pi Foundation. At the moment of writing
+this, the officially supported kernel is a AArch32 kernel. This doesn't mean
+that this port of the Trusted Firmware can't boot a AArch64 kernel. The `Linux
+tree fork`_ maintained by the Foundation can be compiled for AArch64 by
+following the steps in `AArch64 kernel build instructions`_.
+
+**IMPORTANT NOTE**: This port isn't secure. All of the memory used is DRAM,
+which is available from both the Non-secure and Secure worlds. This port
+shouldn't be considered more than a prototype to play with and implement
+elements like PSCI to support the Linux kernel.
+
+Design
+------
+
+The SoC used by the Raspberry Pi 3 is the Broadcom BCM2837. It is a SoC with a
+VideoCore IV that acts as primary processor (and loads everything from the SD
+card) and is located between all Arm cores and the DRAM. Check the `Raspberry Pi
+3 documentation`_ for more information.
+
+This explains why it is possible to change the execution state (AArch64/AArch32)
+depending on a few files on the SD card. We only care about the cases in which
+the cores boot in AArch64 mode.
+
+The rules are simple:
+
+- If a file called ``kernel8.img`` is located on the ``boot`` partition of the
+  SD card, it will load it and execute in EL2 in AArch64. Basically, it executes
+  a `default AArch64 stub`_ at address **0x0** that jumps to the kernel.
+
+- If there is also a file called ``armstub8.bin``, it will load it at address
+  **0x0** (instead of the default stub) and execute it in EL3 in AArch64. All
+  the cores are powered on at the same time and start at address **0x0**.
+
+This means that we can use the default AArch32 kernel provided in the official
+`Raspbian`_ distribution by renaming it to ``kernel8.img``, while the Trusted
+Firmware and anything else we need is in ``armstub8.bin``. This way we can
+forget about the default bootstrap code. When using a AArch64 kernel, it is only
+needed to make sure that the name on the SD card is ``kernel8.img``.
+
+Ideally, we want to load the kernel and have all cores available, which means
+that we need to make the secondary cores work in the way the kernel expects, as
+explained in `Secondary cores`_. In practice, a small bootstrap is needed
+between the Trusted Firmware and the kernel.
+
+To get the most out of a AArch32 kernel, we want to boot it in Hypervisor mode
+in AArch32. This means that BL33 can't be in EL2 in AArch64 mode. The
+architecture specifies that AArch32 Hypervisor mode isn't present when AArch64
+is used for EL2. When using a AArch64 kernel, it should simply start in EL2.
+
+Placement of images
+~~~~~~~~~~~~~~~~~~~
+
+The file ``armstub8.bin`` contains BL1 and the FIP. It is needed to add padding
+between them so that the addresses they are loaded to match the ones specified
+when compiling the Trusted Firmware.
+
+The device tree block is loaded by the VideoCore loader from an appropriate
+file, but we can specify the address it is loaded to in ``config.txt``.
+
+The file ``kernel8.img`` contains a kernel image that is loaded to the address
+specified in ``config.txt``. The `Linux kernel tree`_ has information about how
+a AArch32 Linux kernel image is loaded in ``Documentation/arm/Booting``:
+
+::
+
+    The zImage may also be placed in system RAM and called there.  The
+    kernel should be placed in the first 128MiB of RAM.  It is recommended
+    that it is loaded above 32MiB in order to avoid the need to relocate
+    prior to decompression, which will make the boot process slightly
+    faster.
+
+There are no similar restrictions for AArch64 kernels, as specified in the file
+``Documentation/arm64/booting.txt``.
+
+This means that we need to avoid the first 128 MiB of RAM when placing the
+Trusted Firmware images (and specially the first 32 MiB, as they are directly
+used to place the uncompressed AArch32 kernel image. This way, both AArch32 and
+AArch64 kernels can be placed at the same address.
+
+In the end, the images look like the following diagram when placed in memory.
+All addresses are Physical Addresses from the point of view of the Arm cores.
+Again, note that this is all just part of the same DRAM that goes from
+**0x00000000** to **0x3F000000**, it just has different names to simulate a real
+secure platform!
+
+::
+
+    0x00000000 +-----------------+
+               |       ROM       | BL1
+    0x00010000 +-----------------+
+               |       FIP       |
+    0x00200000 +-----------------+
+               |                 |
+               |       ...       |
+               |                 |
+    0x01000000 +-----------------+
+               |     Kernel      |
+               +-----------------+
+               |                 |
+               |       ...       |
+               |                 |
+    0x02000000 +-----------------+
+               |       DTB       |
+               +-----------------+
+               |                 |
+               |       ...       |
+               |                 |
+    0x10000000 +-----------------+
+               |   Secure SRAM   | BL2, BL31
+    0x10100000 +-----------------+
+               |   Secure DRAM   |
+    0x10300000 +-----------------+
+               | Non-secure DRAM | BL33
+    0x11000000 +-----------------+
+               |                 |
+               |       ...       |
+               |                 |
+    0x3F000000 +-----------------+
+               |       I/O       |
+    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
+command line passed to the kernel. See the `Setup SD card`_ instructions to see
+how to do it.
+
+The last 16 MiB of DRAM can only be accessed by the VideoCore, that has
+different mappings than the Arm cores in which the I/O addresses don't overlap
+the DRAM. The memory reserved to be used by the VideoCore is always placed at
+the end of the DRAM, so this space isn't wasted.
+
+Considering the 128 MiB allocated to the GPU and the 16 MiB allocated for the
+Trusted Firmware, there are 880 MiB available for Linux.
+
+Boot sequence
+~~~~~~~~~~~~~
+
+The boot sequence of the Trusted Firmware is the usual one except when booting
+a AArch32 kernel. In that case, BL33 is booted in AArch32 Hypervisor mode so
+that it can jump to the kernel in the same mode and let it take over that
+privilege level. If BL33 was running in EL2 in AArch64 (as in the default
+bootflow of the Trusted Firmware) it could only jump to the kernel in AArch32 in
+Supervisor mode.
+
+The `Linux kernel tree`_ has instructions on how to jump to the Linux kernel
+in ``Documentation/arm/Booting`` and ``Documentation/arm64/booting.txt``. The
+bootstrap should take care of this.
+
+Secondary cores
+~~~~~~~~~~~~~~~
+
+The kernel used by `Raspbian`_ doesn't have support for PSCI, so it is needed to
+use mailboxes to trap the secondary cores until they are ready to jump to the
+kernel. This mailbox is located at a different address in the AArch32 default
+kernel than in the AArch64 kernel.
+
+Also, this port of the Trusted Firmware has another Trusted Mailbox in Shared BL
+RAM. During cold boot, all secondary cores wait in a loop until they are given
+given an address to jump to in this Mailbox (``bl31_warm_entrypoint``).
+
+Once BL31 has finished and the primary core has jumped to the BL33 payload, it
+has to call ``PSCI_CPU_ON`` to release the secondary CPUs from the wait loop.
+The payload then makes them wait in another waitloop listening from messages
+from the kernel. When the primary CPU jumps into the kernel, it will send an
+address to the mailbox so that the secondary CPUs jump to it and are recognised
+by the kernel.
+
+Build Instructions
+------------------
+
+To boot a AArch64 kernel, only the AArch64 toolchain is required.
+
+To boot a AArch32 kernel, both AArch64 and AArch32 toolchains are required. The
+AArch32 toolchain is needed for the AArch32 bootstrap needed to load a 32-bit
+kernel.
+
+First, clone and compile `Raspberry Pi 3 Arm Trusted Firmware bootstrap`_.
+Choose the one needed for the architecture of your kernel.
+
+Then compile the Arm Trusted Firmware. For a AArch32 kernel, use the following
+command line:
+
+.. code:: shell
+
+    CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3             \
+    RPI3_BL33_IN_AARCH32=1                                      \
+    BL33=../rpi3-arm-tf-bootstrap/aarch32/el2-bootstrap.bin     \
+    all fip
+
+For a AArch64 kernel, use this other command line:
+
+.. code:: shell
+
+    CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3             \
+    BL33=../rpi3-arm-tf-bootstrap/aarch64/el2-bootstrap.bin     \
+    all fip
+
+Then, join BL1 and the FIP with the following instructions (replace ``release``
+by ``debug`` if you set the build option ``DEBUG=1``):
+
+.. code:: shell
+
+    cp build/rpi3/release/bl1.bin bl1.pad.bin
+    truncate --size=65536 bl1.pad.bin
+    cat bl1.pad.bin build/rpi3/release/fip.bin > armstub8.bin
+
+The resulting file, ``armstub8.bin``, contains BL1 and the FIP in the place they
+need to be for the Trusted Firmware to boot correctly. Now, follow the
+instructions in `Setup SD card`_.
+
+The following build options are supported:
+
+- ``PRELOADED_BL33_BASE``: Specially useful because the file ``kernel8.img`` can
+  be loaded anywhere by modifying the file ``config.txt``. It doesn't have to
+  contain a kernel, it could have any arbitrary payload.
+
+- ``RESET_TO_BL31``: Set to 1 by default. If using a 32-bit kernel like
+  `Raspbian`_, the space used by BL1 can overwritten by the kernel when it is
+  being loaded. Even when using a AArch64 kernel the region used by
+  BL1 isn't protected and the kernel could overwrite it. The space used by BL31
+  is reserved by the command line passed to the kernel.
+
+- ``RPI3_BL33_IN_AARCH32``: This port can load a AArch64 or AArch32 BL33 image.
+  By default this option is 0, which means that the Trusted Firmware will jump
+  to BL33 in EL2 in AArch64 mode. If set to 1, it will jump to BL33 in
+  Hypervisor in AArch32 mode.
+
+The following is not currently supported:
+
+- AArch32 for the Trusted Firmware itself.
+
+- ``EL3_PAYLOAD_BASE``: The reason is that you can already load anything to any
+  address by changing the file ``armstub8.bin``, so there's no point in using
+  the Trusted Firmware in this case.
+
+- ``LOAD_IMAGE_V2=0``: Only version 2 is supported.
+
+AArch64 kernel build instructions
+---------------------------------
+
+The following instructions show how to install and run a AArch64 kernel by
+using a SD card with the default `Raspbian`_ install as base. Skip them if you
+want to use the default 32-bit kernel.
+
+Note that this system won't be fully 64-bit because all the tools in the
+filesystem are 32-bit binaries, but it's a quick way to get it working, and it
+allows the user to run 64-bit binaries in addition to 32-bit binaries.
+
+1. Clone the `Linux tree fork`_ maintained by the Raspberry Pi Foundation. To
+   speed things up, do a shallow clone of the desired branch.
+
+.. code:: shell
+
+    git clone --depth=1 -b rpi-4.14.y https://github.com/raspberrypi/linux
+    cd linux
+
+2. Configure and compile the kernel. Adapt the number after ``-j`` so that it is
+   1.5 times the number of CPUs in your computer. This may take some time to
+   finish.
+
+.. code:: shell
+
+    make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcmrpi3_defconfig
+    make -j 6 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
+
+3. Copy the kernel image and the device tree to the SD card. Replace the path
+   by the corresponding path in your computers to the ``boot`` partition of the
+   SD card.
+
+.. code:: shell
+
+    cp arch/arm64/boot/Image /path/to/boot/kernel8.img
+    cp arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dtb /path/to/boot/
+
+4. Install the kernel modules. Replace the path by the corresponding path to the
+   filesystem partition of the SD card on your computer.
+
+.. code:: shell
+
+    make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \
+    INSTALL_MOD_PATH=/path/to/filesystem modules_install
+
+5. Follow the instructions in `Setup SD card`_ except for the step of renaming
+   the existing ``kernel7.img`` (we have already copied a AArch64 kernel).
+
+Setup SD card
+-------------
+
+The instructions assume that you have an SD card with a fresh install of
+`Raspbian`_ (or that, at least, the ``boot`` partition is untouched, or nearly
+untouched). They have been tested with the image available in 2017-09-07.
+
+1. Insert the SD card and open the ``boot`` partition.
+
+2. Rename ``kernel7.img`` to ``kernel8.img``. This tricks the VideoCore
+   bootloader into booting the Arm cores in AArch64 mode, like the Trusted
+   Firmware needs, even though the kernel is not compiled for AArch64.
+
+3. Copy ``armstub8.bin`` here. When ``kernel8.img`` is available, The VideoCore
+   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
+   using the memory needed by the Trusted Firmware. If you want to enable the
+   serial port "Mini UART", make sure that this file also contains
+   ``console=serial0,115200 console=tty1``.
+
+   Note that the 16 MiB reserved this way won't be available for Linux, the same
+   way as the memory reserved in DRAM for the GPU isn't available.
+
+5. Open ``config.txt`` and add the following lines at the end (``enable_uart=1``
+   is only needed to enable debugging through the Mini UART):
+
+::
+
+    enable_uart=1
+    kernel_address=0x01000000
+    device_tree_address=0x02000000
+
+If you connect a serial cable to the Mini UART and your computer, and connect
+to it (for example, with ``screen /dev/ttyUSB0 115200``) you should see some
+text. In the case of an AArch32 kernel, you should see something like this:
+
+::
+
+    NOTICE:  Booting Trusted Firmware
+    NOTICE:  BL1: v1.4(release):v1.4-329-g61e94684-dirty
+    NOTICE:  BL1: Built : 00:09:25, Nov  6 2017
+    NOTICE:  BL1: Booting BL2
+    NOTICE:  BL2: v1.4(release):v1.4-329-g61e94684-dirty
+    NOTICE:  BL2: Built : 00:09:25, Nov  6 2017
+    NOTICE:  BL1: Booting BL31
+    NOTICE:  BL31: v1.4(release):v1.4-329-g61e94684-dirty
+    NOTICE:  BL31: Built : 00:09:25, Nov  6 2017
+    [    0.266484] bcm2835-aux-uart 3f215040.serial: could not get clk: -517
+
+    Raspbian GNU/Linux 9 raspberrypi ttyS0
+    raspberrypi login:
+
+Just enter your credentials, everything should work as expected. Note that the
+HDMI output won't show any text during boot.
+
+.. _default Arm stub: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub7.S
+.. _default AArch64 stub: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub8.S
+.. _Linux kernel tree: https://github.com/torvalds/linux
+.. _Linux tree fork: https://github.com/raspberrypi/linux
+.. _Raspberry Pi 3: https://www.raspberrypi.org/products/raspberry-pi-3-model-b/
+.. _Raspberry Pi 3 Arm Trusted Firmware bootstrap: https://github.com/AntonioND/rpi3-arm-tf-bootstrap
+.. _Raspberry Pi 3 documentation: https://www.raspberrypi.org/documentation/
+.. _Raspbian: https://www.raspberrypi.org/downloads/raspbian/
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index 542fd80..13f0964 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -219,7 +219,8 @@
 
 -  ``ARM_ARCH_MAJOR``: The major version of ARM Architecture to target when
    compiling ARM Trusted Firmware. Its value must be numeric, and defaults to
-   8 . See also, *ARMv8 Architecture Extensions* in `Firmware Design`_.
+   8 . See also, *ARMv8 Architecture Extensions* and
+   *ARMv7 Architecture Extensions* in `Firmware Design`_.
 
 -  ``ARM_ARCH_MINOR``: The minor version of ARM Architecture to target when
    compiling ARM Trusted Firmware. Its value must be a numeric, and defaults
@@ -320,6 +321,11 @@
    payload. Please refer to the "Booting an EL3 payload" section for more
    details.
 
+-  ``ENABLE_AMU``: Boolean option to enable Activity Monitor Unit extensions.
+   This is an optional architectural feature available on v8.4 onwards. Some
+   v8.2 implementations also implement an AMU and this option can be used to
+   enable this feature on those systems as well. Default is 0.
+
 -  ``ENABLE_ASSERTIONS``: This option controls whether or not calls to ``assert()``
    are compiled out. For debug builds, this option defaults to 1, and calls to
    ``assert()`` are left in place. For release builds, this option defaults to 0
@@ -348,6 +354,17 @@
    The default is 1 but is automatically disabled when the target architecture
    is AArch32.
 
+-  ``ENABLE_SVE_FOR_NS``: Boolean option to enable Scalable Vector Extension
+   (SVE) for the Non-secure world only. SVE is an optional architectural feature
+   for AArch64. Note that when SVE is enabled for the Non-secure world, access
+   to SIMD and floating-point functionality from the Secure world is disabled.
+   This is to avoid corruption of the Non-secure world data in the Z-registers
+   which are aliased by the SIMD and FP registers. The build option is not
+   compatible with the ``CTX_INCLUDE_FPREGS`` build option, and will raise an
+   assert on platforms where SVE is implemented and ``ENABLE_SVE_FOR_NS`` set to
+   1. The default is 1 but is automatically disabled when the target
+   architecture is AArch32.
+
 -  ``ENABLE_STACK_PROTECTOR``: String option to enable the stack protection
    checks in GCC. Allowed values are "all", "strong" and "0" (default).
    "strong" is the recommended stack protection level if this feature is
@@ -1206,7 +1223,7 @@
 
           make ARCH=aarch64 PLAT=juno LOAD_IMAGE_V2=1 JUNO_AARCH32_EL3_RUNTIME=1 \
           BL33=<path-to-juno32-oe-uboot>/SOFTWARE/bl33-uboot.bin \
-          SCP_BL2=<path-to-juno32-oe-uboot>/SOFTWARE/scp_bl2.bin SPD=tspd \
+          SCP_BL2=<path-to-juno32-oe-uboot>/SOFTWARE/scp_bl2.bin \
           BL32=<path-to-bl32>/bl32.bin all fip
 
 The resulting BL1 and FIP images may be found in:
diff --git a/drivers/arm/gic/v2/gicv2_main.c b/drivers/arm/gic/v2/gicv2_main.c
index 72f15cd..8798659 100644
--- a/drivers/arm/gic/v2/gicv2_main.c
+++ b/drivers/arm/gic/v2/gicv2_main.c
@@ -176,7 +176,19 @@
 	gic_version = gicd_read_pidr2(plat_driver_data->gicd_base);
 	gic_version = (gic_version >> PIDR2_ARCH_REV_SHIFT)
 					& PIDR2_ARCH_REV_MASK;
-	assert(gic_version == ARCH_REV_GICV2);
+
+	/*
+	 * GICv1 with security extension complies with trusted firmware
+	 * GICv2 driver as far as virtualization and few tricky power
+	 * features are not used. GICv2 features that are not supported
+	 * by GICv1 with Security Extensions are:
+	 * - virtual interrupt support.
+	 * - wake up events.
+	 * - writeable GIC state register (for power sequences)
+	 * - interrupt priority drop.
+	 * - interrupt signal bypass.
+	 */
+	assert(gic_version == ARCH_REV_GICV2 || gic_version == ARCH_REV_GICV1);
 
 	driver_data = plat_driver_data;
 
diff --git a/include/common/aarch32/asm_macros.S b/include/common/aarch32/asm_macros.S
index f573744..7432222 100644
--- a/include/common/aarch32/asm_macros.S
+++ b/include/common/aarch32/asm_macros.S
@@ -79,6 +79,25 @@
 	ldr r0, =(\_name + \_size)
 	.endm
 
+#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
+	/*
+	 * ARMv7 cores without Virtualization extension do not support the
+	 * eret instruction.
+	 */
+	.macro eret
+	movs	pc, lr
+	.endm
+#endif
+
+#if (ARM_ARCH_MAJOR == 7)
+	/* ARMv7 does not support stl instruction */
+	.macro stl _reg, _write_lock
+	dmb
+	str	\_reg, \_write_lock
+	dsb
+	.endm
+#endif
+
 	/*
 	 * Helper macro to generate the best mov/movw/movt combinations
 	 * according to the value to be moved.
diff --git a/include/common/aarch32/el3_common_macros.S b/include/common/aarch32/el3_common_macros.S
index 6fc00dd..59e99f8 100644
--- a/include/common/aarch32/el3_common_macros.S
+++ b/include/common/aarch32/el3_common_macros.S
@@ -107,6 +107,7 @@
 	vmsr	FPEXC, r0
 	isb
 
+#if (ARM_ARCH_MAJOR > 7)
 	/* ---------------------------------------------------------------------
 	 * Initialise SDCR, setting all the fields rather than relying on hw.
 	 *
@@ -116,6 +117,7 @@
 	 */
 	ldr	r0, =(SDCR_RESET_VAL | SDCR_SPD(SDCR_SPD_DISABLE))
 	stcopr	r0, SDCR
+#endif
 
 	.endm
 
diff --git a/include/common/aarch64/el3_common_macros.S b/include/common/aarch64/el3_common_macros.S
index ed35df8..63a0fa7 100644
--- a/include/common/aarch64/el3_common_macros.S
+++ b/include/common/aarch64/el3_common_macros.S
@@ -127,9 +127,9 @@
 	 * CPTR_EL3.TTA: Set to zero so that System register accesses to the
 	 *  trace registers do not trap to EL3.
 	 *
-	 * CPTR_EL3.TFP: Set to zero so that accesses to Advanced SIMD and
-	 *  floating-point functionality do not trap to EL3.
-	 * ---------------------------------------------------------------------
+	 * CPTR_EL3.TFP: Set to zero so that accesses to the V- or Z- registers
+	 *  by Advanced SIMD, floating-point or SVE instructions (if implemented)
+	 *  do not trap to EL3.
 	 */
 	mov_imm x0, (CPTR_EL3_RESET_VAL & ~(TCPAC_BIT | TTA_BIT | TFP_BIT))
 	msr	cptr_el3, x0
diff --git a/include/common/bl_common.h b/include/common/bl_common.h
index 15ffc57..8915ba0 100644
--- a/include/common/bl_common.h
+++ b/include/common/bl_common.h
@@ -205,7 +205,6 @@
 
 #if LOAD_IMAGE_V2
 
-int load_image(unsigned int image_id, image_info_t *image_data);
 int load_auth_image(unsigned int image_id, image_info_t *image_data);
 
 #else
diff --git a/include/drivers/arm/gic_common.h b/include/drivers/arm/gic_common.h
index efa9703..001f573 100644
--- a/include/drivers/arm/gic_common.h
+++ b/include/drivers/arm/gic_common.h
@@ -72,6 +72,8 @@
 #define ARCH_REV_GICV3		0x3
 /* GICv2 revision as reported by the PIDR2 register */
 #define ARCH_REV_GICV2		0x2
+/* GICv1 revision as reported by the PIDR2 register */
+#define ARCH_REV_GICV1		0x1
 
 #define IGROUPR_SHIFT		5
 #define ISENABLER_SHIFT		5
diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h
index 3846bec..4d2a5fc 100644
--- a/include/lib/aarch32/arch.h
+++ b/include/lib/aarch32/arch.h
@@ -78,6 +78,11 @@
 /* CSSELR definitions */
 #define LEVEL_SHIFT		1
 
+/* ID_PFR0 definitions */
+#define ID_PFR0_AMU_SHIFT	U(20)
+#define ID_PFR0_AMU_LENGTH	U(4)
+#define ID_PFR0_AMU_MASK	U(0xf)
+
 /* ID_PFR1 definitions */
 #define ID_PFR1_VIRTEXT_SHIFT	12
 #define ID_PFR1_VIRTEXT_MASK	0xf
@@ -87,15 +92,21 @@
 #define ID_PFR1_GIC_MASK	0xf
 
 /* SCTLR definitions */
-#define SCTLR_RES1	((1 << 23) | (1 << 22) | (1 << 11) | (1 << 4) | \
-			(1 << 3))
+#define SCTLR_RES1_DEF		((1 << 23) | (1 << 22) | (1 << 4) | (1 << 3))
+#if ARM_ARCH_MAJOR == 7
+#define SCTLR_RES1		SCTLR_RES1_DEF
+#else
+#define SCTLR_RES1		(SCTLR_RES1_DEF | (1 << 11))
+#endif
 #define SCTLR_M_BIT		(1 << 0)
 #define SCTLR_A_BIT		(1 << 1)
 #define SCTLR_C_BIT		(1 << 2)
 #define SCTLR_CP15BEN_BIT	(1 << 5)
 #define SCTLR_ITD_BIT		(1 << 7)
+#define SCTLR_Z_BIT		(1 << 11)
 #define SCTLR_I_BIT		(1 << 12)
 #define SCTLR_V_BIT		(1 << 13)
+#define SCTLR_RR_BIT		(1 << 14)
 #define SCTLR_NTWI_BIT		(1 << 16)
 #define SCTLR_NTWE_BIT		(1 << 18)
 #define SCTLR_WXN_BIT		(1 << 19)
@@ -181,6 +192,7 @@
 /* HCPTR definitions */
 #define HCPTR_RES1		((1 << 13) | (1<<12) | 0x3ff)
 #define TCPAC_BIT		(1 << 31)
+#define TAM_BIT			(1 << 30)
 #define TTA_BIT			(1 << 20)
 #define TCP11_BIT		(1 << 10)
 #define TCP10_BIT		(1 << 10)
@@ -385,6 +397,7 @@
 /* System register defines The format is: coproc, opt1, CRn, CRm, opt2 */
 #define SCR		p15, 0, c1, c1, 0
 #define SCTLR		p15, 0, c1, c0, 0
+#define ACTLR		p15, 0, c1, c0, 1
 #define SDCR		p15, 0, c1, c3, 1
 #define MPIDR		p15, 0, c0, c0, 5
 #define MIDR		p15, 0, c0, c0, 0
@@ -400,6 +413,7 @@
 #define DCISW		p15, 0, c7, c6, 2
 #define CTR		p15, 0, c0, c0, 1
 #define CNTFRQ		p15, 0, c14, c0, 0
+#define ID_PFR0		p15, 0, c0, c1, 0
 #define ID_PFR1		p15, 0, c0, c1, 1
 #define MAIR0		p15, 0, c10, c2, 0
 #define MAIR1		p15, 0, c10, c2, 1
@@ -431,6 +445,11 @@
 #define PMCR		p15, 0, c9, c12, 0
 #define CNTHP_CTL	p15, 4, c14, c2, 1
 
+/* AArch32 coproc registers for 32bit MMU descriptor support */
+#define PRRR		p15, 0, c10, c2, 0
+#define NMRR		p15, 0, c10, c2, 1
+#define DACR		p15, 0, c3, c0, 0
+
 /* GICv3 CPU Interface system register defines. The format is: coproc, opt1, CRn, CRm, opt2 */
 #define ICC_IAR1	p15, 0, c12, c12, 0
 #define ICC_IAR0	p15, 0, c12, c8, 0
@@ -513,4 +532,28 @@
 
 #define MAKE_MAIR_NORMAL_MEMORY(inner, outer)	((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT))
 
+/*******************************************************************************
+ * Definitions for system register interface to AMU for ARMv8.4 onwards
+ ******************************************************************************/
+#define AMCR		p15, 0, c13, c2, 0
+#define AMCFGR		p15, 0, c13, c2, 1
+#define AMCGCR		p15, 0, c13, c2, 2
+#define AMUSERENR	p15, 0, c13, c2, 3
+#define AMCNTENCLR0	p15, 0, c13, c2, 4
+#define AMCNTENSET0	p15, 0, c13, c2, 5
+#define AMCNTENCLR1	p15, 0, c13, c3, 0
+#define AMCNTENSET1	p15, 0, c13, c1, 1
+
+/* Activity Monitor Group 0 Event Counter Registers */
+#define AMEVCNTR00	p15, 0, c0
+#define AMEVCNTR01	p15, 1, c0
+#define AMEVCNTR02	p15, 2, c0
+#define AMEVCNTR03	p15, 3, c0
+
+/* Activity Monitor Group 0 Event Type Registers */
+#define AMEVTYPER00	p15, 0, c13, c6, 0
+#define AMEVTYPER01	p15, 0, c13, c6, 1
+#define AMEVTYPER02	p15, 0, c13, c6, 2
+#define AMEVTYPER03	p15, 0, c13, c6, 3
+
 #endif /* __ARCH_H__ */
diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h
index 469e9b0..0230195 100644
--- a/include/lib/aarch32/arch_helpers.h
+++ b/include/lib/aarch32/arch_helpers.h
@@ -227,6 +227,7 @@
  ******************************************************************************/
 DEFINE_COPROCR_READ_FUNC(mpidr, MPIDR)
 DEFINE_COPROCR_READ_FUNC(midr, MIDR)
+DEFINE_COPROCR_READ_FUNC(id_pfr0, ID_PFR0)
 DEFINE_COPROCR_READ_FUNC(id_pfr1, ID_PFR1)
 DEFINE_COPROCR_READ_FUNC(isr, ISR)
 DEFINE_COPROCR_READ_FUNC(clidr, CLIDR)
@@ -235,6 +236,7 @@
 DEFINE_COPROCR_RW_FUNCS(scr, SCR)
 DEFINE_COPROCR_RW_FUNCS(ctr, CTR)
 DEFINE_COPROCR_RW_FUNCS(sctlr, SCTLR)
+DEFINE_COPROCR_RW_FUNCS(actlr, ACTLR)
 DEFINE_COPROCR_RW_FUNCS(hsctlr, HSCTLR)
 DEFINE_COPROCR_RW_FUNCS(hcr, HCR)
 DEFINE_COPROCR_RW_FUNCS(hcptr, HCPTR)
@@ -273,6 +275,18 @@
 DEFINE_COPROCR_RW_FUNCS(cnthp_ctl, CNTHP_CTL)
 DEFINE_COPROCR_READ_FUNC(pmcr, PMCR)
 
+DEFINE_COPROCR_RW_FUNCS(nsacr, NSACR)
+
+/* AArch32 coproc registers for 32bit MMU descriptor support */
+DEFINE_COPROCR_RW_FUNCS(prrr, PRRR)
+DEFINE_COPROCR_RW_FUNCS(nmrr, NMRR)
+DEFINE_COPROCR_RW_FUNCS(dacr, DACR)
+
+DEFINE_COPROCR_RW_FUNCS(amcntenset0, AMCNTENSET0)
+DEFINE_COPROCR_RW_FUNCS(amcntenset1, AMCNTENSET1)
+DEFINE_COPROCR_RW_FUNCS(amcntenclr0, AMCNTENCLR0)
+DEFINE_COPROCR_RW_FUNCS(amcntenclr1, AMCNTENCLR1)
+
 /*
  * TLBI operation prototypes
  */
@@ -296,6 +310,7 @@
 
 /* Previously defined accessor functions with incomplete register names  */
 #define dsb()			dsbsy()
+#define dmb()			dmbsy()
 
 #define IS_IN_SECURE() \
 	(GET_NS_BIT(read_scr()) == 0)
diff --git a/include/lib/aarch32/smcc_macros.S b/include/lib/aarch32/smcc_macros.S
index cf26175..93f211f 100644
--- a/include/lib/aarch32/smcc_macros.S
+++ b/include/lib/aarch32/smcc_macros.S
@@ -22,6 +22,44 @@
 	mov	r0, sp
 	add	r0, r0, #SMC_CTX_SP_USR
 
+#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
+	/* Must be in secure state to restore Monitor mode */
+	ldcopr	r4, SCR
+	bic	r2, r4, #SCR_NS_BIT
+	stcopr	r2, SCR
+	isb
+
+	cps	#MODE32_sys
+	stm	r0!, {sp, lr}
+
+	cps	#MODE32_irq
+	mrs	r2, spsr
+	stm	r0!, {r2, sp, lr}
+
+	cps	#MODE32_fiq
+	mrs	r2, spsr
+	stm	r0!, {r2, sp, lr}
+
+	cps	#MODE32_svc
+	mrs	r2, spsr
+	stm	r0!, {r2, sp, lr}
+
+	cps	#MODE32_abt
+	mrs	r2, spsr
+	stm	r0!, {r2, sp, lr}
+
+	cps	#MODE32_und
+	mrs	r2, spsr
+	stm	r0!, {r2, sp, lr}
+
+	/* lr_mon is already saved by caller */
+	cps	#MODE32_mon
+	mrs	r2, spsr
+	stm	r0!, {r2}
+
+	stcopr	r4, SCR
+	isb
+#else
 	/* Save the banked registers including the current SPSR and LR */
 	mrs	r4, sp_usr
 	mrs	r5, lr_usr
@@ -44,9 +82,10 @@
 	mrs	r11, lr_und
 	mrs	r12, spsr
 	stm	r0!, {r4-r12}
-
 	/* lr_mon is already saved by caller */
+
 	ldcopr	r4, SCR
+#endif
 	str	r4, [sp, #SMC_CTX_SCR]
 	ldcopr	r4, PMCR
 	str	r4, [sp, #SMC_CTX_PMCR]
@@ -82,6 +121,44 @@
 
 	/* Restore the banked registers including the current SPSR */
 	add	r1, r0, #SMC_CTX_SP_USR
+
+#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
+	/* Must be in secure state to restore Monitor mode */
+	ldcopr	r4, SCR
+	bic	r2, r4, #SCR_NS_BIT
+	stcopr	r2, SCR
+	isb
+
+	cps	#MODE32_sys
+	ldm	r1!, {sp, lr}
+
+	cps	#MODE32_irq
+	ldm	r1!, {r2, sp, lr}
+	msr	spsr_fsxc, r2
+
+	cps	#MODE32_fiq
+	ldm	r1!, {r2, sp, lr}
+	msr	spsr_fsxc, r2
+
+	cps	#MODE32_svc
+	ldm	r1!, {r2, sp, lr}
+	msr	spsr_fsxc, r2
+
+	cps	#MODE32_abt
+	ldm	r1!, {r2, sp, lr}
+	msr	spsr_fsxc, r2
+
+	cps	#MODE32_und
+	ldm	r1!, {r2, sp, lr}
+	msr	spsr_fsxc, r2
+
+	cps	#MODE32_mon
+	ldm	r1!, {r2}
+	msr	spsr_fsxc, r2
+
+	stcopr	r4, SCR
+	isb
+#else
 	ldm	r1!, {r4-r12}
 	msr	sp_usr, r4
 	msr	lr_usr, r5
@@ -109,6 +186,7 @@
 	 * f->[31:24] and c->[7:0] bits of SPSR.
 	 */
 	msr	spsr_fsxc, r12
+#endif
 
 	/* Restore the LR */
 	ldr	lr, [r0, #SMC_CTX_LR_MON]
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 777a01a..96e2d5f 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -110,7 +110,13 @@
 #define ID_AA64PFR0_EL1_SHIFT	U(4)
 #define ID_AA64PFR0_EL2_SHIFT	U(8)
 #define ID_AA64PFR0_EL3_SHIFT	U(12)
+#define ID_AA64PFR0_AMU_SHIFT	U(44)
+#define ID_AA64PFR0_AMU_LENGTH	U(4)
+#define ID_AA64PFR0_AMU_MASK	U(0xf)
 #define ID_AA64PFR0_ELX_MASK	U(0xf)
+#define ID_AA64PFR0_SVE_SHIFT	U(32)
+#define ID_AA64PFR0_SVE_MASK	U(0xf)
+#define ID_AA64PFR0_SVE_LENGTH	U(4)
 
 /* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */
 #define ID_AA64DFR0_PMS_SHIFT	U(32)
@@ -135,6 +141,7 @@
 #define PARANGE_0011	U(42)
 #define PARANGE_0100	U(44)
 #define PARANGE_0101	U(48)
+#define PARANGE_0110	U(52)
 
 #define ID_AA64MMFR0_EL1_TGRAN4_SHIFT		U(28)
 #define ID_AA64MMFR0_EL1_TGRAN4_MASK		U(0xf)
@@ -294,15 +301,19 @@
 
 /* CPTR_EL3 definitions */
 #define TCPAC_BIT		(U(1) << 31)
+#define TAM_BIT			(U(1) << 30)
 #define TTA_BIT			(U(1) << 20)
 #define TFP_BIT			(U(1) << 10)
+#define CPTR_EZ_BIT		(U(1) << 8)
 #define CPTR_EL3_RESET_VAL	U(0x0)
 
 /* CPTR_EL2 definitions */
 #define CPTR_EL2_RES1		((U(1) << 13) | (U(1) << 12) | (U(0x3ff)))
 #define CPTR_EL2_TCPAC_BIT	(U(1) << 31)
+#define CPTR_EL2_TAM_BIT	(U(1) << 30)
 #define CPTR_EL2_TTA_BIT	(U(1) << 20)
 #define CPTR_EL2_TFP_BIT	(U(1) << 10)
+#define CPTR_EL2_TZ_BIT		(U(1) << 8)
 #define CPTR_EL2_RESET_VAL	CPTR_EL2_RES1
 
 /* CPSR/SPSR definitions */
@@ -550,6 +561,18 @@
 #define PMCR_EL0_D_BIT		(U(1) << 3)
 
 /*******************************************************************************
+ * Definitions for system register interface to SVE
+ ******************************************************************************/
+#define ZCR_EL3			S3_6_C1_C2_0
+#define ZCR_EL2			S3_4_C1_C2_0
+
+/* ZCR_EL3 definitions */
+#define ZCR_EL3_LEN_MASK	U(0xf)
+
+/* ZCR_EL2 definitions */
+#define ZCR_EL2_LEN_MASK	U(0xf)
+
+/*******************************************************************************
  * Definitions of MAIR encodings for device and normal memory
  ******************************************************************************/
 /*
@@ -609,4 +632,28 @@
  ******************************************************************************/
 #define PMBLIMITR_EL1		S3_0_C9_C10_0
 
+/*******************************************************************************
+ * Definitions for system register interface to AMU for ARMv8.4 onwards
+ ******************************************************************************/
+#define AMCR_EL0		S3_3_C13_C2_0
+#define AMCFGR_EL0		S3_3_C13_C2_1
+#define AMCGCR_EL0		S3_3_C13_C2_2
+#define AMUSERENR_EL0		S3_3_C13_C2_3
+#define AMCNTENCLR0_EL0		S3_3_C13_C2_4
+#define AMCNTENSET0_EL0		S3_3_C13_C2_5
+#define AMCNTENCLR1_EL0		S3_3_C13_C3_0
+#define AMCNTENSET1_EL0		S3_3_C13_C3_1
+
+/* Activity Monitor Group 0 Event Counter Registers */
+#define AMEVCNTR00_EL0		S3_3_C13_C4_0
+#define AMEVCNTR01_EL0		S3_3_C13_C4_1
+#define AMEVCNTR02_EL0		S3_3_C13_C4_2
+#define AMEVCNTR03_EL0		S3_3_C13_C4_3
+
+/* Activity Monitor Group 0 Event Type Registers */
+#define AMEVTYPER00_EL0		S3_3_C13_C6_0
+#define AMEVTYPER01_EL0		S3_3_C13_C6_1
+#define AMEVTYPER02_EL0		S3_3_C13_C6_2
+#define AMEVTYPER03_EL0		S3_3_C13_C6_3
+
 #endif /* __ARCH_H__ */
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 46d9a1c..831dfb0 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -322,8 +322,16 @@
 DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir1_el1, ICC_EOIR1_EL1)
 DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_sgi0r_el1, ICC_SGI0R_EL1)
 
+DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr0_el0, AMCNTENCLR0_EL0)
+DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset0_el0, AMCNTENSET0_EL0)
+DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr1_el0, AMCNTENCLR1_EL0)
+DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset1_el0, AMCNTENSET1_EL0)
+
 DEFINE_RENAME_SYSREG_RW_FUNCS(pmblimitr_el1, PMBLIMITR_EL1)
 
+DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el3, ZCR_EL3)
+DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el2, ZCR_EL2)
+
 #define IS_IN_EL(x) \
 	(GET_EL(read_CurrentEl()) == MODE_EL##x)
 
diff --git a/include/lib/cpus/aarch32/cortex_a12.h b/include/lib/cpus/aarch32/cortex_a12.h
new file mode 100644
index 0000000..3068a41
--- /dev/null
+++ b/include/lib/cpus/aarch32/cortex_a12.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CORTEX_A12_H__
+#define __CORTEX_A12_H__
+
+/*******************************************************************************
+ * Cortex-A12 midr with version/revision set to 0
+ ******************************************************************************/
+#define CORTEX_A12_MIDR			0x410FC0C0
+
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A12_ACTLR_SMP_BIT	(1 << 6)
+
+#endif /* __CORTEX_A12_H__ */
diff --git a/include/lib/cpus/aarch32/cortex_a15.h b/include/lib/cpus/aarch32/cortex_a15.h
new file mode 100644
index 0000000..905c139
--- /dev/null
+++ b/include/lib/cpus/aarch32/cortex_a15.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CORTEX_A15_H__
+#define __CORTEX_A15_H__
+
+/*******************************************************************************
+ * Cortex-A15 midr with version/revision set to 0
+ ******************************************************************************/
+#define CORTEX_A15_MIDR			0x410FC0F0
+
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A15_ACTLR_SMP_BIT	(1 << 6)
+
+#endif /* __CORTEX_A15_H__ */
diff --git a/include/lib/cpus/aarch32/cortex_a17.h b/include/lib/cpus/aarch32/cortex_a17.h
new file mode 100644
index 0000000..d2ca91c
--- /dev/null
+++ b/include/lib/cpus/aarch32/cortex_a17.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CORTEX_A17_H__
+#define __CORTEX_A17_H__
+
+/*******************************************************************************
+ * Cortex-A17 midr with version/revision set to 0
+ ******************************************************************************/
+#define CORTEX_A17_MIDR			0x410FC0E0
+
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A17_ACTLR_SMP_BIT	(1 << 6)
+
+#endif /* __CORTEX_A17_H__ */
diff --git a/include/lib/cpus/aarch32/cortex_a5.h b/include/lib/cpus/aarch32/cortex_a5.h
new file mode 100644
index 0000000..0a0b7ff
--- /dev/null
+++ b/include/lib/cpus/aarch32/cortex_a5.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CORTEX_A5_H__
+#define __CORTEX_A5_H__
+
+/*******************************************************************************
+ * Cortex-A8 midr with version/revision set to 0
+ ******************************************************************************/
+#define CORTEX_A5_MIDR			0x410FC050
+
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A5_ACTLR_SMP_BIT		(1 << 6)
+
+#endif /* __CORTEX_A5_H__ */
diff --git a/include/lib/cpus/aarch32/cortex_a7.h b/include/lib/cpus/aarch32/cortex_a7.h
new file mode 100644
index 0000000..61b0d00
--- /dev/null
+++ b/include/lib/cpus/aarch32/cortex_a7.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CORTEX_A7_H__
+#define __CORTEX_A7_H__
+
+/*******************************************************************************
+ * Cortex-A7 midr with version/revision set to 0
+ ******************************************************************************/
+#define CORTEX_A7_MIDR			0x410FC070
+
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A7_ACTLR_SMP_BIT		(1 << 6)
+
+#endif /* __CORTEX_A7_H__ */
diff --git a/include/lib/cpus/aarch32/cortex_a9.h b/include/lib/cpus/aarch32/cortex_a9.h
new file mode 100644
index 0000000..be85f9b
--- /dev/null
+++ b/include/lib/cpus/aarch32/cortex_a9.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CORTEX_A9_H__
+#define __CORTEX_A9_H__
+
+/*******************************************************************************
+ * Cortex-A9 midr with version/revision set to 0
+ ******************************************************************************/
+#define CORTEX_A9_MIDR			0x410FC090
+
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A9_ACTLR_SMP_BIT		(1 << 6)
+#define CORTEX_A9_ACTLR_FLZW_BIT	(1 << 3)
+
+/*******************************************************************************
+ * CPU Power Control Register
+ ******************************************************************************/
+#define PCR		p15, 0, c15, c0, 0
+
+#ifndef __ASSEMBLY__
+#include <arch_helpers.h>
+DEFINE_COPROCR_RW_FUNCS(pcr, PCR)
+#endif
+
+#endif /* __CORTEX_A9_H__ */
diff --git a/include/lib/cpus/aarch64/cortex_a75.h b/include/lib/cpus/aarch64/cortex_a75.h
index 1ffe20b..d68c957 100644
--- a/include/lib/cpus/aarch64/cortex_a75.h
+++ b/include/lib/cpus/aarch64/cortex_a75.h
@@ -19,4 +19,38 @@
 /* Definitions of register field mask in CORTEX_A75_CPUPWRCTLR_EL1 */
 #define CORTEX_A75_CORE_PWRDN_EN_MASK	0x1
 
+/*******************************************************************************
+ * CPU Activity Monitor Unit register specific definitions.
+ ******************************************************************************/
+#define CPUAMCNTENCLR_EL0	S3_3_C15_C9_7
+#define CPUAMCNTENSET_EL0	S3_3_C15_C9_6
+#define CPUAMCFGR_EL0		S3_3_C15_C10_6
+#define CPUAMUSERENR_EL0	S3_3_C15_C10_7
+
+/* Activity Monitor Event Counter Registers */
+#define CPUAMEVCNTR0_EL0	S3_3_C15_C9_0
+#define CPUAMEVCNTR1_EL0	S3_3_C15_C9_1
+#define CPUAMEVCNTR2_EL0	S3_3_C15_C9_2
+#define CPUAMEVCNTR3_EL0	S3_3_C15_C9_3
+#define CPUAMEVCNTR4_EL0	S3_3_C15_C9_4
+
+/* Activity Monitor Event Type Registers */
+#define CPUAMEVTYPER0_EL0	S3_3_C15_C10_0
+#define CPUAMEVTYPER1_EL0	S3_3_C15_C10_1
+#define CPUAMEVTYPER2_EL0	S3_3_C15_C10_2
+#define CPUAMEVTYPER3_EL0	S3_3_C15_C10_3
+#define CPUAMEVTYPER4_EL0	S3_3_C15_C10_4
+
+#define CORTEX_A75_ACTLR_AMEN_BIT	(U(1) << 4)
+
+/*
+ * The Cortex-A75 core implements five counters, 0-4. Events 0, 1, 2, are
+ * fixed and are enabled (Group 0). Events 3 and 4 (Group 1) are
+ * programmable by programming the appropriate Event count bits in
+ * CPUAMEVTYPER<n> register and are disabled by default. Platforms may
+ * enable this with suitable programming.
+ */
+#define CORTEX_A75_AMU_GROUP0_MASK	0x7
+#define CORTEX_A75_AMU_GROUP1_MASK	(0 << 3)
+
 #endif /* __CORTEX_A75_H__ */
diff --git a/include/lib/extensions/amu.h b/include/lib/extensions/amu.h
new file mode 100644
index 0000000..bbefe8f
--- /dev/null
+++ b/include/lib/extensions/amu.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __AMU_H__
+#define __AMU_H__
+
+/* Enable all group 0 counters */
+#define AMU_GROUP0_COUNTERS_MASK	0xf
+
+void amu_enable(int el2_unused);
+
+#endif /* __AMU_H__ */
diff --git a/include/lib/extensions/sve.h b/include/lib/extensions/sve.h
new file mode 100644
index 0000000..28923e3
--- /dev/null
+++ b/include/lib/extensions/sve.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SVE_H__
+#define __SVE_H__
+
+void sve_enable(int el2_unused);
+
+#endif /* __SVE_H__ */
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index 73a9c53..ba3e360 100644
--- a/include/lib/xlat_tables/xlat_tables_v2.h
+++ b/include/lib/xlat_tables/xlat_tables_v2.h
@@ -168,21 +168,28 @@
 					 _xlat_tables_count,		\
 					 _virt_addr_space_size,		\
 					 _phy_addr_space_size,		\
-					 IMAGE_XLAT_DEFAULT_REGIME)
+					 IMAGE_XLAT_DEFAULT_REGIME,	\
+					"xlat_table")
 
 /*
- * Same as REGISTER_XLAT_CONTEXT plus the additional parameter _xlat_regime to
- * specify the translation regime managed by this xlat_ctx_t instance. The
- * values are the one from xlat_regime_t enumeration.
+ * Same as REGISTER_XLAT_CONTEXT plus the additional parameters:
+ *
+ * _xlat_regime:
+ *   Specify the translation regime managed by this xlat_ctx_t instance. The
+ *   values are the one from xlat_regime_t enumeration.
+ *
+ * _section_name:
+ *   Specify the name of the section where the translation tables have to be
+ *   placed by the linker.
  */
 #define REGISTER_XLAT_CONTEXT2(_ctx_name, _mmap_count, _xlat_tables_count,	\
 			_virt_addr_space_size, _phy_addr_space_size,		\
-			_xlat_regime)					\
+			_xlat_regime, _section_name)				\
 	_REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count,	\
 					 _xlat_tables_count,		\
 					 _virt_addr_space_size,		\
 					 _phy_addr_space_size,		\
-					 _xlat_regime)
+					 _xlat_regime, _section_name)
 
 /******************************************************************************
  * Generic translation table APIs.
diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
index 96dee1a..1be99b7 100644
--- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h
+++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
@@ -123,7 +123,7 @@
 
 #define _REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, _xlat_tables_count,	\
 			_virt_addr_space_size, _phy_addr_space_size,		\
-			_xlat_regime)					\
+			_xlat_regime, _section_name)				\
 	CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(_virt_addr_space_size),		\
 		assert_invalid_virtual_addr_space_size_for_##_ctx_name);	\
 										\
@@ -134,7 +134,7 @@
 										\
 	static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count]		\
 		[XLAT_TABLE_ENTRIES]						\
-		__aligned(XLAT_TABLE_SIZE) __section("xlat_table");		\
+		__aligned(XLAT_TABLE_SIZE) __section(_section_name);		\
 										\
 	static uint64_t _ctx_name##_base_xlat_table				\
 		[GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)]		\
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index 97a1af4..69eb727 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -90,10 +90,14 @@
  * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a
  * little space for growth.
  */
-#if ENABLE_SPM
-#define PLAT_ARM_MAX_BL31_SIZE		0x28000
-#else
 #define PLAT_ARM_MAX_BL31_SIZE		0x1D000
+
+#ifdef AARCH32
+/*
+ * PLAT_ARM_MAX_BL32_SIZE is calculated for SP_MIN as the AArch32 Secure
+ * Payload.
+ */
+# define PLAT_ARM_MAX_BL32_SIZE		0x1D000
 #endif
 
 #endif /* ARM_BOARD_OPTIMISE_MEM */
diff --git a/include/plat/arm/common/arm_common.ld.S b/include/plat/arm/common/arm_common.ld.S
index 478b08c..6edfa09 100644
--- a/include/plat/arm/common/arm_common.ld.S
+++ b/include/plat/arm/common/arm_common.ld.S
@@ -6,6 +6,8 @@
 #ifndef __ARM_COMMON_LD_S__
 #define __ARM_COMMON_LD_S__
 
+#include <xlat_tables_defs.h>
+
 MEMORY {
     EL3_SEC_DRAM (rw): ORIGIN = ARM_EL3_TZC_DRAM1_BASE, LENGTH = ARM_EL3_TZC_DRAM1_SIZE
 }
@@ -13,14 +15,14 @@
 SECTIONS
 {
 	. = ARM_EL3_TZC_DRAM1_BASE;
-	ASSERT(. == ALIGN(4096),
+	ASSERT(. == ALIGN(PAGE_SIZE),
 	"ARM_EL3_TZC_DRAM_BASE address is not aligned on a page boundary.")
-	el3_tzc_dram (NOLOAD) : ALIGN(4096) {
+	el3_tzc_dram (NOLOAD) : ALIGN(PAGE_SIZE) {
 	__EL3_SEC_DRAM_START__ = .;
 	*(arm_el3_tzc_dram)
 	__EL3_SEC_DRAM_UNALIGNED_END__ = .;
 
-	. = NEXT(4096);
+	. = NEXT(PAGE_SIZE);
 	__EL3_SEC_DRAM_END__ = .;
 	} >EL3_SEC_DRAM
 }
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index b8955af..7887525 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -326,14 +326,21 @@
 /*******************************************************************************
  * BL2 specific defines.
  ******************************************************************************/
-#if ARM_BL31_IN_DRAM || (defined(AARCH32) && !defined(JUNO_AARCH32_EL3_RUNTIME))
+#if ARM_BL31_IN_DRAM
 /*
- * For AArch32 BL31 is not applicable.
  * For AArch64 BL31 is loaded in the DRAM.
  * Put BL2 just below BL1.
  */
 #define BL2_BASE			(BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE)
 #define BL2_LIMIT			BL1_RW_BASE
+
+#elif defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME
+/*
+ * Put BL2 just below BL32.
+ */
+#define BL2_BASE			(BL32_BASE - PLAT_ARM_MAX_BL2_SIZE)
+#define BL2_LIMIT			BL32_BASE
+
 #else
 /*
  * Put BL2 just below BL31.
@@ -370,76 +377,86 @@
 #define BL31_LIMIT			(ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
 #endif
 
+#if defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME
 /*******************************************************************************
- * BL32 specific defines.
+ * BL32 specific defines for EL3 runtime in AArch32 mode
+ ******************************************************************************/
+# if RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME
+/* SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM to BL32 */
+#  define BL32_BASE			ARM_BL_RAM_BASE
+#  define BL32_LIMIT			(ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
+# else
+/* Put BL32 at the top of the Trusted SRAM.*/
+#  define BL32_BASE			(ARM_BL_RAM_BASE +		\
+						ARM_BL_RAM_SIZE -	\
+						PLAT_ARM_MAX_BL32_SIZE)
+#  define BL32_PROGBITS_LIMIT		BL1_RW_BASE
+#  define BL32_LIMIT			(ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
+# endif /* RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME */
+
+#else
+/*******************************************************************************
+ * BL32 specific defines for EL3 runtime in AArch64 mode
  ******************************************************************************/
 /*
  * On ARM standard platforms, the TSP can execute from Trusted SRAM,
  * Trusted DRAM (if available) or the DRAM region secured by the TrustZone
  * controller.
  */
-#if ENABLE_SPM
-# define TSP_SEC_MEM_BASE		(ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
-# define TSP_SEC_MEM_SIZE		(ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000))
-# define BL32_BASE			(ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
-# define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
+# if ENABLE_SPM
+#  define TSP_SEC_MEM_BASE		(ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
+#  define TSP_SEC_MEM_SIZE		(ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000))
+#  define BL32_BASE			(ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
+#  define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
 						ARM_AP_TZC_DRAM1_SIZE)
-#elif ARM_BL31_IN_DRAM
-# define TSP_SEC_MEM_BASE		(ARM_AP_TZC_DRAM1_BASE +	\
+# elif ARM_BL31_IN_DRAM
+#  define TSP_SEC_MEM_BASE		(ARM_AP_TZC_DRAM1_BASE +	\
 						PLAT_ARM_MAX_BL31_SIZE)
-# define TSP_SEC_MEM_SIZE		(ARM_AP_TZC_DRAM1_SIZE -	\
+#  define TSP_SEC_MEM_SIZE		(ARM_AP_TZC_DRAM1_SIZE -	\
 						PLAT_ARM_MAX_BL31_SIZE)
-# define BL32_BASE			(ARM_AP_TZC_DRAM1_BASE +	\
+#  define BL32_BASE			(ARM_AP_TZC_DRAM1_BASE +	\
 						PLAT_ARM_MAX_BL31_SIZE)
-# define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
+#  define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
 						ARM_AP_TZC_DRAM1_SIZE)
-#elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID
-# define TSP_SEC_MEM_BASE		ARM_BL_RAM_BASE
-# define TSP_SEC_MEM_SIZE		ARM_BL_RAM_SIZE
-# define TSP_PROGBITS_LIMIT		BL2_BASE
-# define BL32_BASE			ARM_BL_RAM_BASE
-# define BL32_LIMIT			BL31_BASE
-#elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID
-# define TSP_SEC_MEM_BASE		PLAT_ARM_TRUSTED_DRAM_BASE
-# define TSP_SEC_MEM_SIZE		PLAT_ARM_TRUSTED_DRAM_SIZE
-# define BL32_BASE			PLAT_ARM_TRUSTED_DRAM_BASE
-# define BL32_LIMIT			(PLAT_ARM_TRUSTED_DRAM_BASE	\
+# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID
+#  define TSP_SEC_MEM_BASE		ARM_BL_RAM_BASE
+#  define TSP_SEC_MEM_SIZE		ARM_BL_RAM_SIZE
+#  define TSP_PROGBITS_LIMIT		BL2_BASE
+#  define BL32_BASE			ARM_BL_RAM_BASE
+#  define BL32_LIMIT			BL31_BASE
+# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID
+#  define TSP_SEC_MEM_BASE		PLAT_ARM_TRUSTED_DRAM_BASE
+#  define TSP_SEC_MEM_SIZE		PLAT_ARM_TRUSTED_DRAM_SIZE
+#  define BL32_BASE			PLAT_ARM_TRUSTED_DRAM_BASE
+#  define BL32_LIMIT			(PLAT_ARM_TRUSTED_DRAM_BASE	\
 						+ (1 << 21))
-#elif ARM_TSP_RAM_LOCATION_ID == ARM_DRAM_ID
-# define TSP_SEC_MEM_BASE		ARM_AP_TZC_DRAM1_BASE
-# define TSP_SEC_MEM_SIZE		ARM_AP_TZC_DRAM1_SIZE
-# define BL32_BASE			ARM_AP_TZC_DRAM1_BASE
-# define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
+# elif ARM_TSP_RAM_LOCATION_ID == ARM_DRAM_ID
+#  define TSP_SEC_MEM_BASE		ARM_AP_TZC_DRAM1_BASE
+#  define TSP_SEC_MEM_SIZE		ARM_AP_TZC_DRAM1_SIZE
+#  define BL32_BASE			ARM_AP_TZC_DRAM1_BASE
+#  define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
 						ARM_AP_TZC_DRAM1_SIZE)
-#else
-# error "Unsupported ARM_TSP_RAM_LOCATION_ID value"
-#endif
+# else
+#  error "Unsupported ARM_TSP_RAM_LOCATION_ID value"
+# endif
+#endif /* AARCH32 || JUNO_AARCH32_EL3_RUNTIME */
 
 /*
  * BL32 is mandatory in AArch32. In AArch64, undefine BL32_BASE if there is no
  * SPD and no SPM, as they are the only ones that can be used as BL32.
  */
-#ifndef AARCH32
+#if !(defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME)
 # if defined(SPD_none) && !ENABLE_SPM
 #  undef BL32_BASE
-# endif
-#endif
+# endif /* defined(SPD_none) && !ENABLE_SPM */
+#endif /* !(defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME) */
 
 /*******************************************************************************
  * FWU Images: NS_BL1U, BL2U & NS_BL2U defines.
  ******************************************************************************/
 #define BL2U_BASE			BL2_BASE
-#if ARM_BL31_IN_DRAM || (defined(AARCH32) && !defined(JUNO_AARCH32_EL3_RUNTIME))
-/*
- * For AArch32 BL31 is not applicable.
- * For AArch64 BL31 is loaded in the DRAM.
- * BL2U extends up to BL1.
- */
-#define BL2U_LIMIT			BL1_RW_BASE
-#else
-/* BL2U extends up to BL31. */
-#define BL2U_LIMIT			BL31_BASE
-#endif
+#define BL2U_LIMIT			BL2_LIMIT
+
 #define NS_BL2U_BASE			ARM_NS_DRAM1_BASE
 #define NS_BL1U_BASE			(PLAT_ARM_NVM_BASE + 0x03EB8000)
 
diff --git a/include/plat/arm/common/arm_spm_def.h b/include/plat/arm/common/arm_spm_def.h
index 83277a6..3f5c958 100644
--- a/include/plat/arm/common/arm_spm_def.h
+++ b/include/plat/arm/common/arm_spm_def.h
@@ -98,6 +98,12 @@
 /* Total number of memory regions with distinct properties */
 #define ARM_SP_IMAGE_NUM_MEM_REGIONS	6
 
+/*
+ * Name of the section to put the translation tables used by the S-EL1/S-EL0
+ * context of a Secure Partition.
+ */
+#define PLAT_SP_IMAGE_XLAT_SECTION_NAME	"arm_el3_tzc_dram"
+
 /* Cookies passed to the Secure Partition at boot. Not used by ARM platforms. */
 #define PLAT_SPM_COOKIE_0		ULL(0)
 #define PLAT_SPM_COOKIE_1		ULL(0)
diff --git a/include/services/spm_svc.h b/include/services/spm_svc.h
index 2c8c7cd..738979e 100644
--- a/include/services/spm_svc.h
+++ b/include/services/spm_svc.h
@@ -32,24 +32,24 @@
  * Manager from the Secure Partition(s). These services enable a partition to
  * handle delegated events and request privileged operations from the manager.
  */
-#define SPM_VERSION_AARCH32		U(0x84000060)
-#define SP_EVENT_COMPLETE_AARCH64	U(0xC4000061)
-#define SP_MEM_ATTRIBUTES_GET_AARCH64	U(0xC4000064)
-#define SP_MEM_ATTRIBUTES_SET_AARCH64	U(0xC4000065)
+#define SPM_VERSION_AARCH32			U(0x84000060)
+#define SP_EVENT_COMPLETE_AARCH64		U(0xC4000061)
+#define SP_MEMORY_ATTRIBUTES_GET_AARCH64	U(0xC4000064)
+#define SP_MEMORY_ATTRIBUTES_SET_AARCH64	U(0xC4000065)
 
 /*
- * Macros used by SP_MEM_ATTRIBUTES_SET_AARCH64.
+ * Macros used by SP_MEMORY_ATTRIBUTES_SET_AARCH64.
  */
 
-#define SP_MEM_ATTR_ACCESS_NOACCESS	U(0)
-#define SP_MEM_ATTR_ACCESS_RW		U(1)
+#define SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS	U(0)
+#define SP_MEMORY_ATTRIBUTES_ACCESS_RW		U(1)
 /* Value U(2) is reserved. */
-#define SP_MEM_ATTR_ACCESS_RO		U(3)
-#define SP_MEM_ATTR_ACCESS_MASK		U(3)
-#define SP_MEM_ATTR_ACCESS_SHIFT	0
+#define SP_MEMORY_ATTRIBUTES_ACCESS_RO		U(3)
+#define SP_MEMORY_ATTRIBUTES_ACCESS_MASK	U(3)
+#define SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT	0
 
-#define SP_MEM_ATTR_EXEC		(U(0) << 2)
-#define SP_MEM_ATTR_NON_EXEC		(U(1) << 2)
+#define SP_MEMORY_ATTRIBUTES_EXEC		(U(0) << 2)
+#define SP_MEMORY_ATTRIBUTES_NON_EXEC		(U(1) << 2)
 
 /*
  * SMC IDs defined in [1] for accessing secure partition services from the
@@ -59,8 +59,8 @@
 #define SP_VERSION_AARCH64		U(0xC4000040)
 #define SP_VERSION_AARCH32		U(0x84000040)
 
-#define SP_COMMUNICATE_AARCH64		U(0xC4000041)
-#define SP_COMMUNICATE_AARCH32		U(0x84000041)
+#define MM_COMMUNICATE_AARCH64		U(0xC4000041)
+#define MM_COMMUNICATE_AARCH32		U(0x84000041)
 
 /* SPM error codes. */
 #define SPM_SUCCESS		0
diff --git a/lib/aarch32/arm32_aeabi_divmod.c b/lib/aarch32/arm32_aeabi_divmod.c
new file mode 100644
index 0000000..a8f2e74
--- /dev/null
+++ b/lib/aarch32/arm32_aeabi_divmod.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Form ABI specifications:
+ *      int __aeabi_idiv(int numerator, int denominator);
+ *     unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator);
+ *
+ *     typedef struct { int quot; int rem; } idiv_return;
+ *     typedef struct { unsigned quot; unsigned rem; } uidiv_return;
+ *
+ *     __value_in_regs idiv_return __aeabi_idivmod(int numerator,
+ *     int *denominator);
+ *     __value_in_regs uidiv_return __aeabi_uidivmod(unsigned *numerator,
+ *     unsigned denominator);
+ */
+
+/* struct qr - stores qutient/remainder to handle divmod EABI interfaces. */
+struct qr {
+	unsigned int q;		/* computed quotient */
+	unsigned int r;		/* computed remainder */
+	unsigned int q_n;	/* specficies if quotient shall be negative */
+	unsigned int r_n;	/* specficies if remainder shall be negative */
+};
+
+static void uint_div_qr(unsigned int numerator, unsigned int denominator,
+			struct qr *qr);
+
+/* returns in R0 and R1 by tail calling an asm function */
+unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator);
+
+unsigned int __aeabi_uidiv(unsigned int numerator, unsigned int denominator);
+unsigned int __aeabi_uimod(unsigned int numerator, unsigned int denominator);
+
+/* returns in R0 and R1 by tail calling an asm function */
+signed int __aeabi_idivmod(signed int numerator, signed int denominator);
+
+signed int __aeabi_idiv(signed int numerator, signed int denominator);
+signed int __aeabi_imod(signed int numerator, signed int denominator);
+
+/*
+ * __ste_idivmod_ret_t __aeabi_idivmod(signed numerator, signed denominator)
+ * Numerator and Denominator are received in R0 and R1.
+ * Where __ste_idivmod_ret_t is returned in R0 and R1.
+ *
+ * __ste_uidivmod_ret_t __aeabi_uidivmod(unsigned numerator,
+ *                                       unsigned denominator)
+ * Numerator and Denominator are received in R0 and R1.
+ * Where __ste_uidivmod_ret_t is returned in R0 and R1.
+ */
+#ifdef __GNUC__
+signed int ret_idivmod_values(signed int quotient, signed int remainder);
+unsigned int ret_uidivmod_values(unsigned int quotient, unsigned int remainder);
+#else
+#error "Compiler not supported"
+#endif
+
+static void division_qr(unsigned int n, unsigned int p, struct qr *qr)
+{
+	unsigned int i = 1, q = 0;
+
+	if (p == 0) {
+		qr->r = 0xFFFFFFFF;	/* division by 0 */
+		return;
+	}
+
+	while ((p >> 31) == 0) {
+		i = i << 1;	/* count the max division steps */
+		p = p << 1;     /* increase p until it has maximum size*/
+	}
+
+	while (i > 0) {
+		q = q << 1;	/* write bit in q at index (size-1) */
+		if (n >= p) {
+			n -= p;
+			q++;
+		}
+		p = p >> 1;	/* decrease p */
+		i = i >> 1;	/* decrease remaining size in q */
+	}
+	qr->r = n;
+	qr->q = q;
+}
+
+static void uint_div_qr(unsigned int numerator, unsigned int denominator,
+			struct qr *qr)
+{
+	division_qr(numerator, denominator, qr);
+
+	/* negate quotient and/or remainder according to requester */
+	if (qr->q_n)
+		qr->q = -qr->q;
+	if (qr->r_n)
+		qr->r = -qr->r;
+}
+
+unsigned int __aeabi_uidiv(unsigned int numerator, unsigned int denominator)
+{
+	struct qr qr = { .q_n = 0, .r_n = 0 };
+
+	uint_div_qr(numerator, denominator, &qr);
+
+	return qr.q;
+}
+
+unsigned int __aeabi_uimod(unsigned int numerator, unsigned int denominator)
+{
+	struct qr qr = { .q_n = 0, .r_n = 0 };
+
+	uint_div_qr(numerator, denominator, &qr);
+
+	return qr.r;
+}
+
+unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator)
+{
+	struct qr qr = { .q_n = 0, .r_n = 0 };
+
+	uint_div_qr(numerator, denominator, &qr);
+
+	return ret_uidivmod_values(qr.q, qr.r);
+}
+
+signed int __aeabi_idiv(signed int numerator, signed int denominator)
+{
+	struct qr qr = { .q_n = 0, .r_n = 0 };
+
+	if (((numerator < 0) && (denominator > 0)) ||
+	    ((numerator > 0) && (denominator < 0)))
+		qr.q_n = 1;	/* quotient shall be negate */
+
+	if (numerator < 0) {
+		numerator = -numerator;
+		qr.r_n = 1;	/* remainder shall be negate */
+	}
+
+	if (denominator < 0)
+		denominator = -denominator;
+
+	uint_div_qr(numerator, denominator, &qr);
+
+	return qr.q;
+}
+
+signed int __aeabi_imod(signed int numerator, signed int denominator)
+{
+	signed int s;
+	signed int i;
+	signed int j;
+	signed int h;
+	struct qr qr = { .q_n = 0, .r_n = 0 };
+
+	/* in case modulo of a power of 2 */
+	for (i = 0, j = 0, h = 0, s = denominator; (s != 0) || (h > 1); i++) {
+		if (s & 1) {
+			j = i;
+			h++;
+		}
+		s = s >> 1;
+	}
+	if (h == 1)
+		return numerator >> j;
+
+	if (((numerator < 0) && (denominator > 0)) ||
+	    ((numerator > 0) && (denominator < 0)))
+		qr.q_n = 1;	/* quotient shall be negate */
+
+	if (numerator < 0) {
+		numerator = -numerator;
+		qr.r_n = 1;	/* remainder shall be negate */
+	}
+
+	if (denominator < 0)
+		denominator = -denominator;
+
+	uint_div_qr(numerator, denominator, &qr);
+
+	return qr.r;
+}
+
+signed int __aeabi_idivmod(signed int numerator, signed int denominator)
+{
+	struct qr qr = { .q_n = 0, .r_n = 0 };
+
+	if (((numerator < 0) && (denominator > 0)) ||
+	    ((numerator > 0) && (denominator < 0)))
+		qr.q_n = 1;	/* quotient shall be negate */
+
+	if (numerator < 0) {
+		numerator = -numerator;
+		qr.r_n = 1;	/* remainder shall be negate */
+	}
+
+	if (denominator < 0)
+		denominator = -denominator;
+
+	uint_div_qr(numerator, denominator, &qr);
+
+	return ret_idivmod_values(qr.q, qr.r);
+}
diff --git a/lib/aarch32/arm32_aeabi_divmod_a32.S b/lib/aarch32/arm32_aeabi_divmod_a32.S
new file mode 100644
index 0000000..6915dcd
--- /dev/null
+++ b/lib/aarch32/arm32_aeabi_divmod_a32.S
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+/*
+ * EABI wrappers from the udivmod and idivmod functions
+ */
+
+	.globl ret_uidivmod_values
+	.globl ret_idivmod_values
+
+/*
+ * signed ret_idivmod_values(signed quot, signed rem);
+ * return quotient and remaining the EABI way (regs r0,r1)
+ */
+func ret_idivmod_values
+        bx lr
+endfunc ret_idivmod_values
+
+/*
+ * unsigned ret_uidivmod_values(unsigned quot, unsigned rem);
+ * return quotient and remaining the EABI way (regs r0,r1)
+ */
+func ret_uidivmod_values
+        bx      lr
+endfunc ret_uidivmod_values
diff --git a/lib/cpus/aarch32/cortex_a12.S b/lib/cpus/aarch32/cortex_a12.S
new file mode 100644
index 0000000..73c9750
--- /dev/null
+++ b/lib/cpus/aarch32/cortex_a12.S
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017, 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 <cortex_a12.h>
+#include <cpu_macros.S>
+
+	.macro assert_cache_enabled
+#if ENABLE_ASSERTIONS
+		ldcopr	r0, SCTLR
+		tst	r0, #SCTLR_C_BIT
+		ASM_ASSERT(eq)
+#endif
+	.endm
+
+func cortex_a12_disable_smp
+	ldcopr	r0, ACTLR
+	bic	r0, #CORTEX_A12_ACTLR_SMP_BIT
+	stcopr	r0, ACTLR
+	isb
+	dsb	sy
+	bx	lr
+endfunc cortex_a12_disable_smp
+
+func cortex_a12_enable_smp
+	ldcopr	r0, ACTLR
+	orr	r0, #CORTEX_A12_ACTLR_SMP_BIT
+	stcopr	r0, ACTLR
+	isb
+	bx	lr
+endfunc cortex_a12_enable_smp
+
+func cortex_a12_reset_func
+	b	cortex_a12_enable_smp
+endfunc cortex_a12_reset_func
+
+func cortex_a12_core_pwr_dwn
+	push	{r12, lr}
+
+	assert_cache_enabled
+
+	/* Flush L1 cache */
+	mov	r0, #DC_OP_CISW
+	bl	dcsw_op_level1
+
+	/* Exit cluster coherency */
+	pop	{r12, lr}
+	b	cortex_a12_disable_smp
+endfunc cortex_a12_core_pwr_dwn
+
+func cortex_a12_cluster_pwr_dwn
+	push	{r12, lr}
+
+	assert_cache_enabled
+
+	/* Flush L1 caches */
+	mov	r0, #DC_OP_CISW
+	bl	dcsw_op_level1
+
+	bl	plat_disable_acp
+
+	/* Exit cluster coherency */
+	pop	{r12, lr}
+	b	cortex_a12_disable_smp
+endfunc cortex_a12_cluster_pwr_dwn
+
+declare_cpu_ops cortex_a12, CORTEX_A12_MIDR, \
+	cortex_a12_reset_func, \
+	cortex_a12_core_pwr_dwn, \
+	cortex_a12_cluster_pwr_dwn
diff --git a/lib/cpus/aarch32/cortex_a15.S b/lib/cpus/aarch32/cortex_a15.S
new file mode 100644
index 0000000..0d5a116
--- /dev/null
+++ b/lib/cpus/aarch32/cortex_a15.S
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016, 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 <cortex_a15.h>
+#include <cpu_macros.S>
+
+/*
+ * Cortex-A15 support LPAE and Virtualization Extensions.
+ * Don't care if confiugration uses or not LPAE and VE.
+ * Therefore, where we don't check ARCH_IS_ARMV7_WITH_LPAE/VE
+ */
+
+	.macro assert_cache_enabled
+#if ENABLE_ASSERTIONS
+		ldcopr	r0, SCTLR
+		tst	r0, #SCTLR_C_BIT
+		ASM_ASSERT(eq)
+#endif
+	.endm
+
+func cortex_a15_disable_smp
+	ldcopr	r0, ACTLR
+	bic	r0, #CORTEX_A15_ACTLR_SMP_BIT
+	stcopr	r0, ACTLR
+	isb
+	dsb	sy
+	bx	lr
+endfunc cortex_a15_disable_smp
+
+func cortex_a15_enable_smp
+	ldcopr	r0, ACTLR
+	orr	r0, #CORTEX_A15_ACTLR_SMP_BIT
+	stcopr	r0, ACTLR
+	isb
+	bx	lr
+endfunc cortex_a15_enable_smp
+
+func cortex_a15_reset_func
+	b	cortex_a15_enable_smp
+endfunc cortex_a15_reset_func
+
+func cortex_a15_core_pwr_dwn
+	push	{r12, lr}
+
+	assert_cache_enabled
+
+	/* Flush L1 cache */
+	mov	r0, #DC_OP_CISW
+	bl	dcsw_op_level1
+
+	/* Exit cluster coherency */
+	pop	{r12, lr}
+	b	cortex_a15_disable_smp
+endfunc cortex_a15_core_pwr_dwn
+
+func cortex_a15_cluster_pwr_dwn
+	push	{r12, lr}
+
+	assert_cache_enabled
+
+	/* Flush L1 caches */
+	mov	r0, #DC_OP_CISW
+	bl	dcsw_op_level1
+
+	bl	plat_disable_acp
+
+	/* Exit cluster coherency */
+	pop	{r12, lr}
+	b	cortex_a15_disable_smp
+endfunc cortex_a15_cluster_pwr_dwn
+
+declare_cpu_ops cortex_a15, CORTEX_A15_MIDR, \
+	cortex_a15_reset_func, \
+	cortex_a15_core_pwr_dwn, \
+	cortex_a15_cluster_pwr_dwn
diff --git a/lib/cpus/aarch32/cortex_a17.S b/lib/cpus/aarch32/cortex_a17.S
new file mode 100644
index 0000000..316d4f0
--- /dev/null
+++ b/lib/cpus/aarch32/cortex_a17.S
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017, 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 <cortex_a17.h>
+#include <cpu_macros.S>
+
+	.macro assert_cache_enabled
+#if ENABLE_ASSERTIONS
+		ldcopr	r0, SCTLR
+		tst	r0, #SCTLR_C_BIT
+		ASM_ASSERT(eq)
+#endif
+	.endm
+
+func cortex_a17_disable_smp
+	ldcopr	r0, ACTLR
+	bic	r0, #CORTEX_A17_ACTLR_SMP_BIT
+	stcopr	r0, ACTLR
+	isb
+	dsb	sy
+	bx	lr
+endfunc cortex_a17_disable_smp
+
+func cortex_a17_enable_smp
+	ldcopr	r0, ACTLR
+	orr	r0, #CORTEX_A17_ACTLR_SMP_BIT
+	stcopr	r0, ACTLR
+	isb
+	bx	lr
+endfunc cortex_a17_enable_smp
+
+func cortex_a17_reset_func
+	b	cortex_a17_enable_smp
+endfunc cortex_a17_reset_func
+
+func cortex_a17_core_pwr_dwn
+	push	{r12, lr}
+
+	assert_cache_enabled
+
+	/* Flush L1 cache */
+	mov	r0, #DC_OP_CISW
+	bl	dcsw_op_level1
+
+	/* Exit cluster coherency */
+	pop	{r12, lr}
+	b	cortex_a17_disable_smp
+endfunc cortex_a17_core_pwr_dwn
+
+func cortex_a17_cluster_pwr_dwn
+	push	{r12, lr}
+
+	assert_cache_enabled
+
+	/* Flush L1 caches */
+	mov	r0, #DC_OP_CISW
+	bl	dcsw_op_level1
+
+	bl	plat_disable_acp
+
+	/* Exit cluster coherency */
+	pop	{r12, lr}
+	b	cortex_a17_disable_smp
+endfunc cortex_a17_cluster_pwr_dwn
+
+declare_cpu_ops cortex_a17, CORTEX_A17_MIDR, \
+	cortex_a17_reset_func, \
+	cortex_a17_core_pwr_dwn, \
+	cortex_a17_cluster_pwr_dwn
diff --git a/lib/cpus/aarch32/cortex_a5.S b/lib/cpus/aarch32/cortex_a5.S
new file mode 100644
index 0000000..c07c13e
--- /dev/null
+++ b/lib/cpus/aarch32/cortex_a5.S
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016, 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 <cortex_a5.h>
+#include <cpu_macros.S>
+
+	.macro assert_cache_enabled
+#if ENABLE_ASSERTIONS
+		ldcopr	r0, SCTLR
+		tst	r0, #SCTLR_C_BIT
+		ASM_ASSERT(eq)
+#endif
+	.endm
+
+func cortex_a5_disable_smp
+	ldcopr	r0, ACTLR
+	bic	r0, #CORTEX_A5_ACTLR_SMP_BIT
+	stcopr	r0, ACTLR
+	isb
+	dsb	sy
+	bx	lr
+endfunc cortex_a5_disable_smp
+
+func cortex_a5_enable_smp
+	ldcopr	r0, ACTLR
+	orr	r0, #CORTEX_A5_ACTLR_SMP_BIT
+	stcopr	r0, ACTLR
+	isb
+	bx	lr
+endfunc cortex_a5_enable_smp
+
+func cortex_a5_reset_func
+	b	cortex_a5_enable_smp
+endfunc cortex_a5_reset_func
+
+func cortex_a5_core_pwr_dwn
+	push	{r12, lr}
+
+	assert_cache_enabled
+
+	/* Flush L1 cache */
+	mov	r0, #DC_OP_CISW
+	bl	dcsw_op_level1
+
+	/* Exit cluster coherency */
+	pop	{r12, lr}
+	b	cortex_a5_disable_smp
+endfunc cortex_a5_core_pwr_dwn
+
+func cortex_a5_cluster_pwr_dwn
+	push	{r12, lr}
+
+	assert_cache_enabled
+
+	/* Flush L1 caches */
+	mov	r0, #DC_OP_CISW
+	bl	dcsw_op_level1
+
+	bl	plat_disable_acp
+
+	/* Exit cluster coherency */
+	pop	{r12, lr}
+	b	cortex_a5_disable_smp
+endfunc cortex_a5_cluster_pwr_dwn
+
+declare_cpu_ops cortex_a5, CORTEX_A5_MIDR, \
+	cortex_a5_reset_func, \
+	cortex_a5_core_pwr_dwn, \
+	cortex_a5_cluster_pwr_dwn
diff --git a/lib/cpus/aarch32/cortex_a53.S b/lib/cpus/aarch32/cortex_a53.S
index 74cedc3..1647e16 100644
--- a/lib/cpus/aarch32/cortex_a53.S
+++ b/lib/cpus/aarch32/cortex_a53.S
@@ -174,7 +174,7 @@
 	push	{r12, lr}
 
 	/* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
 	ldcopr	r0, SCTLR
 	tst	r0, #SCTLR_C_BIT
 	ASM_ASSERT(eq)
@@ -204,7 +204,7 @@
 	push	{r12, lr}
 
 	/* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
 	ldcopr	r0, SCTLR
 	tst	r0, #SCTLR_C_BIT
 	ASM_ASSERT(eq)
diff --git a/lib/cpus/aarch32/cortex_a57.S b/lib/cpus/aarch32/cortex_a57.S
index b5189e7..64a6d67 100644
--- a/lib/cpus/aarch32/cortex_a57.S
+++ b/lib/cpus/aarch32/cortex_a57.S
@@ -406,7 +406,7 @@
 	push	{r12, lr}
 
 	/* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
 	ldcopr	r0, SCTLR
 	tst	r0, #SCTLR_C_BIT
 	ASM_ASSERT(eq)
@@ -448,7 +448,7 @@
 	push	{r12, lr}
 
 	/* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
 	ldcopr	r0, SCTLR
 	tst	r0, #SCTLR_C_BIT
 	ASM_ASSERT(eq)
diff --git a/lib/cpus/aarch32/cortex_a7.S b/lib/cpus/aarch32/cortex_a7.S
new file mode 100644
index 0000000..0278d1f
--- /dev/null
+++ b/lib/cpus/aarch32/cortex_a7.S
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017, 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 <cortex_a7.h>
+#include <cpu_macros.S>
+
+	.macro assert_cache_enabled
+#if ENABLE_ASSERTIONS
+		ldcopr	r0, SCTLR
+		tst	r0, #SCTLR_C_BIT
+		ASM_ASSERT(eq)
+#endif
+	.endm
+
+func cortex_a7_disable_smp
+	ldcopr	r0, ACTLR
+	bic	r0, #CORTEX_A7_ACTLR_SMP_BIT
+	stcopr	r0, ACTLR
+	isb
+	dsb	sy
+	bx	lr
+endfunc cortex_a7_disable_smp
+
+func cortex_a7_enable_smp
+	ldcopr	r0, ACTLR
+	orr	r0, #CORTEX_A7_ACTLR_SMP_BIT
+	stcopr	r0, ACTLR
+	isb
+	bx	lr
+endfunc cortex_a7_enable_smp
+
+func cortex_a7_reset_func
+	b	cortex_a7_enable_smp
+endfunc cortex_a7_reset_func
+
+func cortex_a7_core_pwr_dwn
+	push	{r12, lr}
+
+	assert_cache_enabled
+
+	/* Flush L1 cache */
+	mov	r0, #DC_OP_CISW
+	bl	dcsw_op_level1
+
+	/* Exit cluster coherency */
+	pop	{r12, lr}
+	b	cortex_a7_disable_smp
+endfunc cortex_a7_core_pwr_dwn
+
+func cortex_a7_cluster_pwr_dwn
+	push	{r12, lr}
+
+	assert_cache_enabled
+
+	/* Flush L1 caches */
+	mov	r0, #DC_OP_CISW
+	bl	dcsw_op_level1
+
+	bl	plat_disable_acp
+
+	/* Exit cluster coherency */
+	pop	{r12, lr}
+	b	cortex_a7_disable_smp
+endfunc cortex_a7_cluster_pwr_dwn
+
+declare_cpu_ops cortex_a7, CORTEX_A7_MIDR, \
+	cortex_a7_reset_func, \
+	cortex_a7_core_pwr_dwn, \
+	cortex_a7_cluster_pwr_dwn
diff --git a/lib/cpus/aarch32/cortex_a72.S b/lib/cpus/aarch32/cortex_a72.S
index 69cc2ea..7550520 100644
--- a/lib/cpus/aarch32/cortex_a72.S
+++ b/lib/cpus/aarch32/cortex_a72.S
@@ -120,7 +120,7 @@
 	push	{r12, lr}
 
 	/* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
 	ldcopr	r0, SCTLR
 	tst	r0, #SCTLR_C_BIT
 	ASM_ASSERT(eq)
@@ -167,7 +167,7 @@
 	push	{r12, lr}
 
 	/* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
 	ldcopr	r0, SCTLR
 	tst	r0, #SCTLR_C_BIT
 	ASM_ASSERT(eq)
diff --git a/lib/cpus/aarch32/cortex_a9.S b/lib/cpus/aarch32/cortex_a9.S
new file mode 100644
index 0000000..4f30f84
--- /dev/null
+++ b/lib/cpus/aarch32/cortex_a9.S
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016, 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 <cortex_a9.h>
+#include <cpu_macros.S>
+
+	.macro assert_cache_enabled
+#if ENABLE_ASSERTIONS
+		ldcopr	r0, SCTLR
+		tst	r0, #SCTLR_C_BIT
+		ASM_ASSERT(eq)
+#endif
+	.endm
+
+func cortex_a9_disable_smp
+	ldcopr	r0, ACTLR
+	bic	r0, #CORTEX_A9_ACTLR_SMP_BIT
+	stcopr	r0, ACTLR
+	isb
+	dsb	sy
+	bx	lr
+endfunc cortex_a9_disable_smp
+
+func cortex_a9_enable_smp
+	ldcopr	r0, ACTLR
+	orr	r0, #CORTEX_A9_ACTLR_SMP_BIT
+	stcopr	r0, ACTLR
+	isb
+	bx	lr
+endfunc cortex_a9_enable_smp
+
+func cortex_a9_reset_func
+	b	cortex_a9_enable_smp
+endfunc cortex_a9_reset_func
+
+func cortex_a9_core_pwr_dwn
+	push	{r12, lr}
+
+	assert_cache_enabled
+
+	/* Flush L1 cache */
+	mov	r0, #DC_OP_CISW
+	bl	dcsw_op_level1
+
+	/* Exit cluster coherency */
+	pop	{r12, lr}
+	b	cortex_a9_disable_smp
+endfunc cortex_a9_core_pwr_dwn
+
+func cortex_a9_cluster_pwr_dwn
+	push	{r12, lr}
+
+	assert_cache_enabled
+
+	/* Flush L1 caches */
+	mov	r0, #DC_OP_CISW
+	bl	dcsw_op_level1
+
+	bl	plat_disable_acp
+
+	/* Exit cluster coherency */
+	pop	{r12, lr}
+	b	cortex_a9_disable_smp
+endfunc cortex_a9_cluster_pwr_dwn
+
+declare_cpu_ops cortex_a9, CORTEX_A9_MIDR, \
+	cortex_a9_reset_func, \
+	cortex_a9_core_pwr_dwn, \
+	cortex_a9_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S
index 1f4500c..4cab9e4 100644
--- a/lib/cpus/aarch64/cortex_a75.S
+++ b/lib/cpus/aarch64/cortex_a75.S
@@ -11,6 +11,33 @@
 #include <plat_macros.S>
 #include <cortex_a75.h>
 
+func cortex_a75_reset_func
+#if ENABLE_AMU
+	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
+	mrs	x0, actlr_el3
+	orr	x0, x0, #CORTEX_A75_ACTLR_AMEN_BIT
+	msr	actlr_el3, x0
+	isb
+
+	/* Make sure accesses from EL0/EL1 are not trapped to EL2 */
+	mrs	x0, actlr_el2
+	orr	x0, x0, #CORTEX_A75_ACTLR_AMEN_BIT
+	msr	actlr_el2, x0
+	isb
+
+	/* Enable group0 counters */
+	mov	x0, #CORTEX_A75_AMU_GROUP0_MASK
+	msr	CPUAMCNTENSET_EL0, x0
+	isb
+
+	/* Enable group1 counters */
+	mov	x0, #CORTEX_A75_AMU_GROUP1_MASK
+	msr	CPUAMCNTENSET_EL0, x0
+	isb
+#endif
+	ret
+endfunc cortex_a75_reset_func
+
 	/* ---------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ---------------------------------------------
@@ -47,5 +74,5 @@
 endfunc cortex_a75_cpu_reg_dump
 
 declare_cpu_ops cortex_a75, CORTEX_A75_MIDR, \
-	CPU_NO_RESET_FUNC, \
+	cortex_a75_reset_func, \
 	cortex_a75_core_pwr_dwn
diff --git a/lib/el3_runtime/aarch32/context_mgmt.c b/lib/el3_runtime/aarch32/context_mgmt.c
index a8672d6..76e440e 100644
--- a/lib/el3_runtime/aarch32/context_mgmt.c
+++ b/lib/el3_runtime/aarch32/context_mgmt.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <amu.h>
 #include <arch.h>
 #include <arch_helpers.h>
 #include <assert.h>
@@ -132,6 +133,9 @@
 static void enable_extensions_nonsecure(int el2_unused)
 {
 #if IMAGE_BL32
+#if ENABLE_AMU
+	amu_enable(el2_unused);
+#endif
 #endif
 }
 
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 8f1523f..c6c2249 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <amu.h>
 #include <arch.h>
 #include <arch_helpers.h>
 #include <assert.h>
@@ -17,6 +18,7 @@
 #include <smcc_helpers.h>
 #include <spe.h>
 #include <string.h>
+#include <sve.h>
 #include <utils.h>
 
 
@@ -220,6 +222,14 @@
 #if ENABLE_SPE_FOR_LOWER_ELS
 	spe_enable(el2_unused);
 #endif
+
+#if ENABLE_AMU
+	amu_enable(el2_unused);
+#endif
+
+#if ENABLE_SVE_FOR_NS
+	sve_enable(el2_unused);
+#endif
 #endif
 }
 
diff --git a/lib/extensions/amu/aarch32/amu.c b/lib/extensions/amu/aarch32/amu.c
new file mode 100644
index 0000000..d450bd6
--- /dev/null
+++ b/lib/extensions/amu/aarch32/amu.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <amu.h>
+#include <arch.h>
+#include <arch_helpers.h>
+
+void amu_enable(int el2_unused)
+{
+	uint64_t features;
+
+	features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
+	if ((features & ID_PFR0_AMU_MASK) == 1) {
+		if (el2_unused) {
+			uint64_t v;
+
+			/*
+			 * Non-secure access from EL0 or EL1 to the Activity Monitor
+			 * registers do not trap to EL2.
+			 */
+			v = read_hcptr();
+			v &= ~TAM_BIT;
+			write_hcptr(v);
+		}
+
+		/* Enable group 0 counters */
+		write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
+	}
+}
diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c
new file mode 100644
index 0000000..007b349
--- /dev/null
+++ b/lib/extensions/amu/aarch64/amu.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <amu.h>
+#include <arch.h>
+#include <arch_helpers.h>
+
+void amu_enable(int el2_unused)
+{
+	uint64_t features;
+
+	features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT;
+	if ((features & ID_AA64PFR0_AMU_MASK) == 1) {
+		uint64_t v;
+
+		if (el2_unused) {
+			/*
+			 * CPTR_EL2.TAM: Set to zero so any accesses to
+			 * the Activity Monitor registers do not trap to EL2.
+			 */
+			v = read_cptr_el2();
+			v &= ~CPTR_EL2_TAM_BIT;
+			write_cptr_el2(v);
+		}
+
+		/*
+		 * CPTR_EL3.TAM: Set to zero so that any accesses to
+		 * the Activity Monitor registers do not trap to EL3.
+		 */
+		v = read_cptr_el3();
+		v &= ~TAM_BIT;
+		write_cptr_el3(v);
+
+		/* Enable group 0 counters */
+		write_amcntenset0_el0(AMU_GROUP0_COUNTERS_MASK);
+	}
+}
diff --git a/lib/extensions/sve/sve.c b/lib/extensions/sve/sve.c
new file mode 100644
index 0000000..14e51bd
--- /dev/null
+++ b/lib/extensions/sve/sve.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <pubsub.h>
+#include <sve.h>
+
+static void *disable_sve_hook(const void *arg)
+{
+	uint64_t features;
+
+	features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
+	if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
+		uint64_t cptr;
+
+		/*
+		 * Disable SVE, SIMD and FP access for the Secure world.
+		 * As the SIMD/FP registers are part of the SVE Z-registers, any
+		 * use of SIMD/FP functionality will corrupt the SVE registers.
+		 * Therefore it is necessary to prevent use of SIMD/FP support
+		 * in the Secure world as well as SVE functionality.
+		 */
+		cptr = read_cptr_el3();
+		cptr = (cptr | TFP_BIT) & ~(CPTR_EZ_BIT);
+		write_cptr_el3(cptr);
+
+		/*
+		 * No explicit ISB required here as ERET to switch to Secure
+		 * world covers it
+		 */
+	}
+	return 0;
+}
+
+static void *enable_sve_hook(const void *arg)
+{
+	uint64_t features;
+
+	features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
+	if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
+		uint64_t cptr;
+
+		/*
+		 * Enable SVE, SIMD and FP access for the Non-secure world.
+		 */
+		cptr = read_cptr_el3();
+		cptr = (cptr | CPTR_EZ_BIT) & ~(TFP_BIT);
+		write_cptr_el3(cptr);
+
+		/*
+		 * No explicit ISB required here as ERET to switch to Non-secure
+		 * world covers it
+		 */
+	}
+	return 0;
+}
+
+void sve_enable(int el2_unused)
+{
+	uint64_t features;
+
+	features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
+	if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
+		uint64_t cptr;
+#if CTX_INCLUDE_FPREGS
+		/*
+		 * CTX_INCLUDE_FPREGS is not supported on SVE enabled systems.
+		 */
+		assert(0);
+#endif
+		/*
+		 * Update CPTR_EL3 to enable access to SVE functionality for the
+		 * Non-secure world.
+		 * NOTE - assumed that CPTR_EL3.TFP is set to allow access to
+		 * the SIMD, floating-point and SVE support.
+		 *
+		 * CPTR_EL3.EZ: Set to 1 to enable access to SVE  functionality
+		 *  in the Non-secure world.
+		 */
+		cptr = read_cptr_el3();
+		cptr |= CPTR_EZ_BIT;
+		write_cptr_el3(cptr);
+
+		/*
+		 * Need explicit ISB here to guarantee that update to ZCR_ELx
+		 * and CPTR_EL2.TZ do not result in trap to EL3.
+		 */
+		isb();
+
+		/*
+		 * Ensure lower ELs have access to full vector length.
+		 */
+		write_zcr_el3(ZCR_EL3_LEN_MASK);
+
+		if (el2_unused) {
+			/*
+			 * Update CPTR_EL2 to enable access to SVE functionality
+			 * for Non-secure world, EL2 and Non-secure EL1 and EL0.
+			 * NOTE - assumed that CPTR_EL2.TFP is set to allow
+			 * access to the SIMD, floating-point and SVE support.
+			 *
+			 * CPTR_EL2.TZ: Set to 0 to enable access to SVE support
+			 *  for EL2 and Non-secure EL1 and EL0.
+			 */
+			cptr = read_cptr_el2();
+			cptr &= ~(CPTR_EL2_TZ_BIT);
+			write_cptr_el2(cptr);
+
+			/*
+			 * Ensure lower ELs have access to full vector length.
+			 */
+			write_zcr_el2(ZCR_EL2_LEN_MASK);
+		}
+		/*
+		 * No explicit ISB required here as ERET to switch to
+		 * Non-secure world covers it.
+		 */
+	}
+}
+
+SUBSCRIBE_TO_EVENT(cm_exited_normal_world, disable_sve_hook);
+SUBSCRIBE_TO_EVENT(cm_entering_normal_world, enable_sve_hook);
diff --git a/lib/locks/exclusive/aarch32/spinlock.S b/lib/locks/exclusive/aarch32/spinlock.S
index bc77bc9..9492cc0 100644
--- a/lib/locks/exclusive/aarch32/spinlock.S
+++ b/lib/locks/exclusive/aarch32/spinlock.S
@@ -9,6 +9,17 @@
 	.globl	spin_lock
 	.globl	spin_unlock
 
+#if ARM_ARCH_AT_LEAST(8, 0)
+/*
+ * According to the ARMv8-A Architecture Reference Manual, "when the global
+ * monitor for a PE changes from Exclusive Access state to Open Access state,
+ * an event is generated.". This applies to both AArch32 and AArch64 modes of
+ * ARMv8-A. As a result, no explicit SEV with unlock is required.
+ */
+#define COND_SEV()
+#else
+#define COND_SEV()	sev
+#endif
 
 func spin_lock
 	mov	r2, #1
@@ -27,5 +38,6 @@
 func spin_unlock
 	mov	r1, #0
 	stl	r1, [r0]
+	COND_SEV()
 	bx	lr
 endfunc spin_unlock
diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c
index 4105e63..8e41cf0 100644
--- a/lib/psci/psci_main.c
+++ b/lib/psci/psci_main.c
@@ -220,6 +220,23 @@
 	if (target_idx == -1)
 		return PSCI_E_INVALID_PARAMS;
 
+	/*
+	 * Generic management:
+	 * Perform cache maintanence ahead of reading the target CPU state to
+	 * ensure that the data is not stale.
+	 * There is a theoretical edge case where the cache may contain stale
+	 * data for the target CPU data - this can occur under the following
+	 * conditions:
+	 * - the target CPU is in another cluster from the current
+	 * - the target CPU was the last CPU to shutdown on its cluster
+	 * - the cluster was removed from coherency as part of the CPU shutdown
+	 *
+	 * In this case the cache maintenace that was performed as part of the
+	 * target CPUs shutdown was not seen by the current CPU's cluster. And
+	 * so the cache may contain stale data for the target CPU.
+	 */
+	flush_cpu_data_by_index(target_idx, psci_svc_cpu_data.aff_info_state);
+
 	return psci_get_aff_info_state_by_idx(target_idx);
 }
 
diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c
index a841dda..c00bd94 100644
--- a/lib/psci/psci_setup.c
+++ b/lib/psci/psci_setup.c
@@ -266,8 +266,10 @@
  ******************************************************************************/
 void psci_arch_setup(void)
 {
+#if ARM_ARCH_MAJOR > 7 || defined(ARMV7_SUPPORTS_GENERIC_TIMER)
 	/* Program the counter frequency */
 	write_cntfrq_el0(plat_get_syscnt_freq2());
+#endif
 
 	/* Initialize the cpu_ops pointer. */
 	init_cpu_ops();
diff --git a/lib/xlat_tables/aarch32/xlat_tables.c b/lib/xlat_tables/aarch32/xlat_tables.c
index c7e34f2..720d446 100644
--- a/lib/xlat_tables/aarch32/xlat_tables.c
+++ b/lib/xlat_tables/aarch32/xlat_tables.c
@@ -13,6 +13,10 @@
 #include <xlat_tables.h>
 #include "../xlat_tables_private.h"
 
+#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING)
+#error ARMv7 target does not support LPAE MMU descriptors
+#endif
+
 #define XLAT_TABLE_LEVEL_BASE	\
        GET_XLAT_TABLE_LEVEL_BASE(PLAT_VIRT_ADDR_SPACE_SIZE)
 
diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c
index 28ae1f7..eabc3df 100644
--- a/lib/xlat_tables/aarch64/xlat_tables.c
+++ b/lib/xlat_tables/aarch64/xlat_tables.c
@@ -60,7 +60,10 @@
 /* Physical Address ranges supported in the AArch64 Memory Model */
 static const unsigned int pa_range_bits_arr[] = {
 	PARANGE_0000, PARANGE_0001, PARANGE_0010, PARANGE_0011, PARANGE_0100,
-	PARANGE_0101
+	PARANGE_0101,
+#if ARM_ARCH_AT_LEAST(8, 2)
+	PARANGE_0110,
+#endif
 };
 
 static unsigned long long get_max_supported_pa(void)
diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
index 642f799..fc7ca46 100644
--- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
@@ -14,6 +14,10 @@
 #include <xlat_tables_v2.h>
 #include "../xlat_tables_private.h"
 
+#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING)
+#error ARMv7 target does not support LPAE MMU descriptors
+#endif
+
 #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 4331107..aa5b9e5 100644
--- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
@@ -48,7 +48,10 @@
 /* Physical Address ranges supported in the AArch64 Memory Model */
 static const unsigned int pa_range_bits_arr[] = {
 	PARANGE_0000, PARANGE_0001, PARANGE_0010, PARANGE_0011, PARANGE_0100,
-	PARANGE_0101
+	PARANGE_0101,
+#if ARM_ARCH_AT_LEAST(8, 2)
+	PARANGE_0110,
+#endif
 };
 
 unsigned long long xlat_arch_get_max_supported_pa(void)
diff --git a/maintainers.rst b/maintainers.rst
index 388073e..04ab695 100644
--- a/maintainers.rst
+++ b/maintainers.rst
@@ -21,8 +21,8 @@
 
 Files:
 
--  docs/spd/optee-dispatcher.md
--  docs/plat/qemu.md
+-  docs/plat/qemu.rst
+-  docs/spd/optee-dispatcher.rst
 -  services/spd/opteed/\*
 -  plat/qemu/\*
 
@@ -33,8 +33,9 @@
 
 Files:
 
--  docs/spd/tlk-dispatcher.md
--  docs/spd/trusty-dispatcher.md
+-  docs/plat/nvidia-tegra.rst
+-  docs/spd/tlk-dispatcher.rst
+-  docs/spd/trusty-dispatcher.rst
 -  include/bl32/payloads/tlk.h
 -  include/lib/cpus/aarch64/denver.h
 -  lib/cpus/aarch64/denver.S
@@ -49,8 +50,9 @@
 
 Files:
 
--  docs/plat/hikey.md
--  docs/plat/hikey960.md
+-  docs/plat/hikey.rst
+-  docs/plat/hikey960.rst
+-  docs/plat/poplar.rst
 -  drivers/emmc/\*
 -  drivers/partition/\*
 -  drivers/synopsys/emmc/\*
@@ -71,32 +73,60 @@
 
 -  plat/mediatek/\*
 
+Raspberry Pi 3 platform sub-maintainer
+--------------------------------------
+
+Antonio Niño Díaz (antonio.ninodiaz@arm.com, `antonio-nino-diaz-arm`_)
+
+Files:
+
+-  docs/plat/rpi3.rst
+-  plat/rpi3/\*
+
 RockChip platform sub-maintainer
 --------------------------------
 
 Tony Xie (tony.xie@rock-chips.com, `TonyXie06`_
-or `rkchrome`_)
+or `rockchip-linux`_)
 
 Files:
 
 -  plat/rockchip/\*
 
+UniPhier platform sub-maintainer
+--------------------------------
+
+Masahiro Yamada (yamada.masahiro@socionext.com, `masahir0y`_)
+
+Files:
+
+- docs/plat/socionext-uniphier.rst
+- plat/socionext/\*
+
 Xilinx platform sub-maintainer
 ------------------------------
 
-Sören Brinkmann (soren.brinkmann@xilinx.com, `sorenb-xlnx`_)
+Siva Durga Prasad Paladugu (siva.durga.paladugu@xilinx.com, `sivadur`_)
 
 Files:
 
--  docs/plat/xilinx-zynqmp.md
+-  docs/plat/xilinx-zynqmp.rst
 -  plat/xilinx/\*
 
+ARMv7 architecture sub-maintainer
+---------------------------------
+
+Etienne Carriere (etienne.carriere@linaro.org, `etienne-lms`_)
+
+.. _antonio-nino-diaz-arm: https://github.com/antonio-nino-diaz-arm
 .. _danh-arm: https://github.com/danh-arm
 .. _davidcunado-arm: https://github.com/davidcunado-arm
 .. _jenswi-linaro: https://github.com/jenswi-linaro
 .. _vwadekar: https://github.com/vwadekar
 .. _hzhuang1: https://github.com/hzhuang1
+.. _masahir0y: https://github.com/masahir0y
 .. _mtk09422: https://github.com/mtk09422
 .. _TonyXie06: https://github.com/TonyXie06
-.. _rkchrome: https://github.com/rkchrome
-.. _sorenb-xlnx: https://github.com/sorenb-xlnx
+.. _sivadur: https://github.com/sivadur
+.. _rockchip-linux: https://github.com/rockchip-linux
+.. _etienne-lms: https://github.com/etienne-lms
diff --git a/make_helpers/armv7-a-cpus.mk b/make_helpers/armv7-a-cpus.mk
new file mode 100644
index 0000000..20e7ec5
--- /dev/null
+++ b/make_helpers/armv7-a-cpus.mk
@@ -0,0 +1,50 @@
+#
+# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifneq (${ARCH},aarch32)
+$(error ARM_ARCH_MAJOR=7 mandates ARCH=aarch32)
+endif
+
+# For ARMv7, set march32 from platform directive ARMV7_CORTEX_Ax=yes
+# and ARM_WITH_NEON=yes/no.
+#
+# GCC and Clang require -march=armv7-a for C-A9 and -march=armv7ve for C-A15.
+# armClang requires -march=armv7-a for all ARMv7 Cortex-A. To comply with
+# all, just drop -march and supply only -mcpu.
+
+# Platform can override march32-directive through MARCH32_DIRECTIVE
+ifdef MARCH32_DIRECTIVE
+march32-directive		:= $(MARCH32_DIRECTIVE)
+else
+march32-set-${ARM_CORTEX_A5}	:= -mcpu=cortex-a5
+march32-set-${ARM_CORTEX_A7}	:= -mcpu=cortex-a7
+march32-set-${ARM_CORTEX_A9}	:= -mcpu=cortex-a9
+march32-set-${ARM_CORTEX_A12}	:= -mcpu=cortex-a12
+march32-set-${ARM_CORTEX_A15}	:= -mcpu=cortex-a15
+march32-set-${ARM_CORTEX_A17}	:= -mcpu=cortex-a17
+march32-neon-$(ARM_WITH_NEON)	:= -mfpu=neon
+
+# default to -march=armv7-a as target directive
+march32-set-yes			?= -march=armv7-a
+march32-directive		:= ${march32-set-yes} ${march32-neon-yes}
+endif
+
+# Platform may override these extension support directives:
+#
+# ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING
+# Defined if core supports the Large Page Addressing extension.
+#
+# ARMV7_SUPPORTS_VIRTUALIZATION
+# Defined if ARMv7 core supports the Virtualization extension.
+#
+# ARMV7_SUPPORTS_GENERIC_TIMER
+# Defined if ARMv7 core supports the Generic Timer extension.
+
+ifeq ($(filter yes,$(ARM_CORTEX_A7) $(ARM_CORTEX_A12) $(ARM_CORTEX_A15) $(ARM_CORTEX_A17)),yes)
+$(eval $(call add_define,ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING))
+$(eval $(call add_define,ARMV7_SUPPORTS_VIRTUALIZATION))
+$(eval $(call add_define,ARMV7_SUPPORTS_GENERIC_TIMER))
+endif
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 7531f6d..e1bfbbe 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -336,3 +336,49 @@
 
 endef
 
+define SOURCES_TO_DTBS
+        $(notdir $(patsubst %.dts,%.dtb,$(filter %.dts,$(1))))
+endef
+
+# MAKE_FDT macro defines the targets and options to build each FDT binary
+# Arguments: (none)
+define MAKE_FDT
+        $(eval DTB_BUILD_DIR  := ${BUILD_PLAT}/fdts)
+        $(eval DTBS       := $(addprefix $(DTB_BUILD_DIR)/,$(call SOURCES_TO_DTBS,$(FDT_SOURCES))))
+        $(eval TEMP_DTB_DIRS := $(sort $(dir ${DTBS})))
+        # The $(dir ) function leaves a trailing / on the directory names
+        # Rip off the / to match directory names with make rule targets.
+        $(eval DTB_DIRS   := $(patsubst %/,%,$(TEMP_DTB_DIRS)))
+
+$(eval $(foreach objd,${DTB_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR})))
+
+fdt_dirs: ${DTB_DIRS}
+
+endef
+
+# MAKE_DTB generate the Flattened device tree binary (device tree binary)
+#   $(1) = output directory
+#   $(2) = input dts
+define MAKE_DTB
+
+$(eval DOBJ := $(1)/$(patsubst %.dts,%.dtb,$(notdir $(2))))
+$(eval DEP := $(patsubst %.dtb,%.d,$(DOBJ)))
+
+$(DOBJ): $(2) | fdt_dirs
+	@echo "  DTC      $$<"
+	$$(Q)$$(DTC) $$(DTC_FLAGS) -d $(DEP) -o $$@ $$<
+
+-include $(DEP)
+
+endef
+
+# MAKE_DTBS builds flattened device tree sources
+#   $(1) = output directory
+#   $(2) = list of flattened device tree source files
+define MAKE_DTBS
+        $(eval DOBJS := $(filter %.dts,$(2)))
+        $(eval REMAIN := $(filter-out %.dts,$(2)))
+        $(eval $(foreach obj,$(DOBJS),$(call MAKE_DTB,$(1),$(obj))))
+
+        $(and $(REMAIN),$(error Unexpected s present: $(REMAIN)))
+endef
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index b7ce051..fa0d17d 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -24,9 +24,6 @@
 # in EL3. The platform port can change this value if needed.
 ARM_GIC_ARCH			:= 2
 
-# Flag used to indicate if ASM_ASSERTION should be enabled for the build.
-ASM_ASSERTION			:= 0
-
 # Base commit to perform code check on
 BASE_COMMIT			:= origin/master
 
@@ -156,3 +153,14 @@
 ifeq (${ARCH},aarch32)
     override ENABLE_SPE_FOR_LOWER_ELS := 0
 endif
+
+ENABLE_AMU			:= 0
+
+# By default, enable Scalable Vector Extension if implemented for Non-secure
+# lower ELs
+# Note SVE is only supported on AArch64 - therefore do not enable in AArch32
+ifneq (${ARCH},aarch32)
+    ENABLE_SVE_FOR_NS		:= 1
+else
+    override ENABLE_SVE_FOR_NS	:= 0
+endif
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index b13afe4..6e6e273 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -77,6 +77,7 @@
 endif
 
 ifeq (${ARCH},aarch64)
+ifeq (${NEED_BL31},yes)
 # Add the BL31 CoT (key cert + img cert + image)
 $(if ${BL31},$(eval $(call CERT_ADD_CMD_OPT,${BL31},--soc-fw,true)),\
              $(eval $(call CERT_ADD_CMD_OPT,$(call IMG_BIN,31),--soc-fw,true)))
@@ -86,6 +87,7 @@
 $(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_content.crt,--soc-fw-cert))
 $(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert))
 endif
+endif
 
 # Add the BL32 CoT (key cert + img cert + image)
 ifeq (${NEED_BL32},yes)
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 13bd8f2..7284584 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -402,12 +402,20 @@
 	.validate_ns_entrypoint = arm_validate_psci_entrypoint,
 	.translate_power_state_by_mpidr = fvp_translate_power_state_by_mpidr,
 	.get_node_hw_state = fvp_node_hw_state,
+#if !ARM_BL31_IN_DRAM
+	/*
+	 * The TrustZone Controller is set up during the warmboot sequence after
+	 * resuming the CPU from a SYSTEM_SUSPEND. If BL31 is located in SRAM
+	 * this is  not a problem but, if it is in TZC-secured DRAM, it tries to
+	 * reconfigure the same memory it is running on, causing an exception.
+	 */
 	.get_sys_suspend_power_state = fvp_get_sys_suspend_power_state,
-/*
- * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN,
- * as that would require mapping in all of NS DRAM into BL31 or BL32.
- */
+#endif
 #if !RESET_TO_BL31 && !RESET_TO_SP_MIN
+	/*
+	 * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN,
+	 * as that would require mapping in all of NS DRAM into BL31 or BL32.
+	 */
 	.mem_protect_chk	= arm_psci_mem_protect_chk,
 	.read_mem_protect	= arm_psci_read_mem_protect,
 	.write_mem_protect	= arm_nor_psci_write_mem_protect,
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 310db7b..7080fc3 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -8,6 +8,7 @@
 #define __PLATFORM_DEF_H__
 
 #include <arm_def.h>
+#include <arm_spm_def.h>
 #include <board_arm_def.h>
 #include <common_def.h>
 #include <tzc400.h>
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 1b50296..7edbd3d 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -147,6 +147,9 @@
 # Disable the PSCI platform compatibility layer
 ENABLE_PLAT_COMPAT	:= 	0
 
+# Enable Activity Monitor Unit extensions by default
+ENABLE_AMU			:=	1
+
 ifneq (${ENABLE_STACK_PROTECTOR},0)
 PLAT_BL_COMMON_SOURCES	+=	plat/arm/board/fvp/fvp_stack_protector.c
 endif
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index ccc7771..e475ece 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -128,6 +128,15 @@
  */
 #define PLAT_ARM_MAX_BL31_SIZE		0x1E000
 
+#if JUNO_AARCH32_EL3_RUNTIME
+/*
+ * PLAT_ARM_MAX_BL32_SIZE is calculated for SP_MIN as the AArch32 Secure
+ * Payload. We also need to take care of SCP_BL2 size as well, as the SCP_BL2
+ * is loaded into the space BL32 -> BL1_RW_BASE
+ */
+# define PLAT_ARM_MAX_BL32_SIZE		0x1E000
+#endif
+
 /*
  * Since free SRAM space is scant, enable the ASSERTION message size
  * optimization by fixing the PLAT_LOG_LEVEL_ASSERT to LOG_LEVEL_INFO (40).
diff --git a/plat/arm/board/juno/juno_bl2_setup.c b/plat/arm/board/juno/juno_bl2_setup.c
index 2771e0f..cedef66 100644
--- a/plat/arm/board/juno/juno_bl2_setup.c
+++ b/plat/arm/board/juno/juno_bl2_setup.c
@@ -29,33 +29,4 @@
 
 	return err;
 }
-
-#if !CSS_USE_SCMI_SDS_DRIVER
-/*
- * We need to override some of the platform functions when booting SP_MIN
- * on Juno AArch32. These needs to be done only for SCPI/BOM SCP systems as
- * in case of SDS, the structures remain in memory and doesn't need to be
- * overwritten.
- */
-
-static unsigned int scp_boot_config;
-
-void bl2_early_platform_setup(meminfo_t *mem_layout)
-{
-	arm_bl2_early_platform_setup(mem_layout);
-
-	/* Save SCP Boot config before it gets overwritten by SCP_BL2 loading */
-	VERBOSE("BL2: Saving SCP Boot config = 0x%x\n", scp_boot_config);
-	scp_boot_config = mmio_read_32(SCP_BOOT_CFG_ADDR);
-}
-
-void bl2_platform_setup(void)
-{
-	arm_bl2_platform_setup();
-
-	mmio_write_32(SCP_BOOT_CFG_ADDR, scp_boot_config);
-	VERBOSE("BL2: Restored SCP Boot config = 0x%x\n", scp_boot_config);
-}
-#endif
-
 #endif /* JUNO_AARCH32_EL3_RUNTIME */
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 5cd125b..fee4391 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -31,6 +31,19 @@
 $(eval $(call assert_boolean,JUNO_AARCH32_EL3_RUNTIME))
 $(eval $(call add_define,JUNO_AARCH32_EL3_RUNTIME))
 
+ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1)
+# Include BL32 in FIP
+NEED_BL32		:= yes
+# BL31 is not required
+override BL31_SOURCES =
+
+# The BL32 needs to be built separately invoking the AARCH32 compiler and
+# be specifed via `BL32` build option.
+  ifneq (${ARCH}, aarch32)
+    override BL32_SOURCES =
+  endif
+endif
+
 ifeq (${ARCH},aarch64)
 BL1_SOURCES		+=	lib/cpus/aarch64/cortex_a53.S		\
 				lib/cpus/aarch64/cortex_a57.S		\
@@ -86,6 +99,9 @@
 # Enable memory map related constants optimisation
 ARM_BOARD_OPTIMISE_MEM		:=	1
 
+# Do not enable SVE
+ENABLE_SVE_FOR_NS		:=	0
+
 include plat/arm/board/common/board_css.mk
 include plat/arm/common/arm_common.mk
 include plat/arm/soc/common/soc_css.mk
diff --git a/plat/arm/common/arm_tzc400.c b/plat/arm/common/arm_tzc400.c
index 23c0317..cf13326 100644
--- a/plat/arm/common/arm_tzc400.c
+++ b/plat/arm/common/arm_tzc400.c
@@ -74,8 +74,8 @@
 
 #else /* if defined(EL3_PAYLOAD_BASE) */
 
-	/* Allow secure access only to DRAM for EL3 payloads. */
-	tzc400_configure_region0(TZC_REGION_S_RDWR, 0);
+	/* Allow Secure and Non-secure access to DRAM for EL3 payloads */
+	tzc400_configure_region0(TZC_REGION_S_RDWR, PLAT_ARM_TZC_NS_DEV_ACCESS);
 
 #endif /* EL3_PAYLOAD_BASE */
 
diff --git a/plat/arm/css/common/css_bl2_setup.c b/plat/arm/css/common/css_bl2_setup.c
index 9b4800e..b4aafd4 100644
--- a/plat/arm/css/common/css_bl2_setup.c
+++ b/plat/arm/css/common/css_bl2_setup.c
@@ -49,13 +49,13 @@
 }
 
 #if !CSS_USE_SCMI_SDS_DRIVER
-# ifdef EL3_PAYLOAD_BASE
+# if defined(EL3_PAYLOAD_BASE) || JUNO_AARCH32_EL3_RUNTIME
 
 /*
  * We need to override some of the platform functions when booting an EL3
- * payload. These needs to be done only for SCPI/BOM SCP systems as
- * in case of SDS, the structures remain in memory and doesn't need to be
- * overwritten.
+ * payload or SP_MIN on Juno AArch32. This needs to be done only for
+ * SCPI/BOM SCP systems as in case of SDS, the structures remain in memory and
+ * don't need to be overwritten.
  */
 
 static unsigned int scp_boot_config;
diff --git a/plat/common/aarch32/platform_helpers.S b/plat/common/aarch32/platform_helpers.S
index 61d21ab..0a0e927 100644
--- a/plat/common/aarch32/platform_helpers.S
+++ b/plat/common/aarch32/platform_helpers.S
@@ -7,12 +7,15 @@
 #include <arch.h>
 #include <asm_macros.S>
 
+	.weak	plat_report_exception
 	.weak	plat_crash_console_init
 	.weak	plat_crash_console_putc
 	.weak	plat_crash_console_flush
 	.weak	plat_reset_handler
 	.weak	plat_disable_acp
+	.weak	bl1_plat_prepare_exit
 	.weak	platform_mem_init
+	.weak	plat_error_handler
 	.weak	plat_panic_handler
 	.weak	bl2_plat_preload_setup
 	.weak	plat_try_next_boot_source
@@ -22,6 +25,15 @@
 	 * each platform.
 	 * -----------------------------------------------------
 	 */
+func plat_report_exception
+	bx	lr
+endfunc plat_report_exception
+
+	/* -----------------------------------------------------
+	 * Placeholder function which should be redefined by
+	 * each platform.
+	 * -----------------------------------------------------
+	 */
 func plat_crash_console_init
 	mov	r0, #0
 	bx	lr
@@ -74,6 +86,25 @@
 endfunc platform_mem_init
 
 	/* -----------------------------------------------------
+	 * void bl1_plat_prepare_exit(entry_point_info_t *ep_info);
+	 * Called before exiting BL1. Default: do nothing
+	 * -----------------------------------------------------
+	 */
+func bl1_plat_prepare_exit
+	bx	lr
+endfunc bl1_plat_prepare_exit
+
+	/* -----------------------------------------------------
+	 * void plat_error_handler(int err) __dead2;
+	 * Endless loop by default.
+	 * -----------------------------------------------------
+	 */
+func plat_error_handler
+	wfi
+	b	plat_error_handler
+endfunc plat_error_handler
+
+	/* -----------------------------------------------------
 	 * void plat_panic_handler(void) __dead2;
 	 * Endless loop by default.
 	 * -----------------------------------------------------
diff --git a/plat/compat/plat_compat.mk b/plat/compat/plat_compat.mk
index af88542..f1867da 100644
--- a/plat/compat/plat_compat.mk
+++ b/plat/compat/plat_compat.mk
@@ -18,3 +18,6 @@
 BL31_SOURCES		+=	plat/common/plat_psci_common.c		\
 				plat/compat/plat_pm_compat.c		\
 				plat/compat/plat_topology_compat.c
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS	:=	0
diff --git a/plat/hisilicon/hikey/platform.mk b/plat/hisilicon/hikey/platform.mk
index 26218a4..18b5e15 100644
--- a/plat/hisilicon/hikey/platform.mk
+++ b/plat/hisilicon/hikey/platform.mk
@@ -24,6 +24,7 @@
 PLAT_PL061_MAX_GPIOS		:=	160
 COLD_BOOT_SINGLE_CPU		:=	1
 PROGRAMMABLE_RESET_ADDRESS	:=	1
+ENABLE_SVE_FOR_NS		:=	0
 
 # Process flags
 $(eval $(call add_define,HIKEY_TSP_RAM_LOCATION_ID))
diff --git a/plat/hisilicon/hikey960/hikey960_pm.c b/plat/hisilicon/hikey960/hikey960_pm.c
index 348cdba..078f0d8 100644
--- a/plat/hisilicon/hikey960/hikey960_pm.c
+++ b/plat/hisilicon/hikey960/hikey960_pm.c
@@ -26,6 +26,38 @@
 #define SYSTEM_PWR_STATE(state) \
 	((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
 
+#define PSTATE_WIDTH		4
+#define PSTATE_MASK		((1 << PSTATE_WIDTH) - 1)
+
+#define MAKE_PWRSTATE(lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \
+		(((lvl2_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH * 2)) | \
+		 ((lvl1_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH)) | \
+		 ((lvl0_state) << (PSTATE_ID_SHIFT)) | \
+		 ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
+		 ((type) << PSTATE_TYPE_SHIFT))
+
+/*
+ * The table storing the valid idle power states. Ensure that the
+ * array entries are populated in ascending order of state-id to
+ * enable us to use binary search during power state validation.
+ * The table must be terminated by a NULL entry.
+ */
+const unsigned int hikey960_pwr_idle_states[] = {
+	/* State-id - 0x001 */
+	MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
+		      PLAT_MAX_STB_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
+	/* State-id - 0x002 */
+	MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
+		      PLAT_MAX_RET_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
+	/* State-id - 0x003 */
+	MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
+		      PLAT_MAX_OFF_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN),
+	/* State-id - 0x033 */
+	MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_OFF_STATE,
+		      PLAT_MAX_OFF_STATE, MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN),
+	0,
+};
+
 #define DMAC_GLB_REG_SEC	0x694
 #define AXI_CONF_BASE		0x820
 
@@ -36,16 +68,21 @@
 	unsigned long scr;
 	unsigned int val = 0;
 
-	assert(cpu_state == PLAT_MAX_RET_STATE);
+	assert(cpu_state == PLAT_MAX_STB_STATE ||
+	       cpu_state == PLAT_MAX_RET_STATE);
 
 	scr = read_scr_el3();
 
 	/* Enable Physical IRQ and FIQ to wake the CPU*/
 	write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
 
-	set_retention_ticks(val);
+	if (cpu_state == PLAT_MAX_RET_STATE)
+		set_retention_ticks(val);
+
 	wfi();
-	clr_retention_ticks(val);
+
+	if (cpu_state == PLAT_MAX_RET_STATE)
+		clr_retention_ticks(val);
 
 	/*
 	 * Restore SCR to the original value, synchronisazion of
@@ -124,38 +161,34 @@
 int hikey960_validate_power_state(unsigned int power_state,
 			       psci_power_state_t *req_state)
 {
-	int pstate = psci_get_pstate_type(power_state);
-	int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+	unsigned int state_id;
 	int i;
 
 	assert(req_state);
 
-	if (pwr_lvl > PLAT_MAX_PWR_LVL)
+	/*
+	 *  Currently we are using a linear search for finding the matching
+	 *  entry in the idle power state array. This can be made a binary
+	 *  search if the number of entries justify the additional complexity.
+	 */
+	for (i = 0; !!hikey960_pwr_idle_states[i]; i++) {
+		if (power_state == hikey960_pwr_idle_states[i])
+			break;
+	}
+
+	/* Return error if entry not found in the idle state array */
+	if (!hikey960_pwr_idle_states[i])
 		return PSCI_E_INVALID_PARAMS;
 
-	/* Sanity check the requested state */
-	if (pstate == PSTATE_TYPE_STANDBY) {
-		/*
-		 * It's possible to enter standby only on power level 0
-		 * Ignore any other power level.
-		 */
-		if (pwr_lvl != MPIDR_AFFLVL0)
-			return PSCI_E_INVALID_PARAMS;
+	i = 0;
+	state_id = psci_get_pstate_id(power_state);
 
-		req_state->pwr_domain_state[MPIDR_AFFLVL0] =
-					PLAT_MAX_RET_STATE;
-	} else {
-		for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
-			req_state->pwr_domain_state[i] =
-					PLAT_MAX_OFF_STATE;
+	/* Parse the State ID and populate the state info parameter */
+	while (state_id) {
+		req_state->pwr_domain_state[i++] = state_id & PSTATE_MASK;
+		state_id >>= PSTATE_WIDTH;
 	}
 
-	/*
-	 * We expect the 'state id' to be zero.
-	 */
-	if (psci_get_pstate_id(power_state))
-		return PSCI_E_INVALID_PARAMS;
-
 	return PSCI_E_SUCCESS;
 }
 
diff --git a/plat/hisilicon/hikey960/include/platform_def.h b/plat/hisilicon/hikey960/include/platform_def.h
index cb76090..2ac7f2a 100644
--- a/plat/hisilicon/hikey960/include/platform_def.h
+++ b/plat/hisilicon/hikey960/include/platform_def.h
@@ -31,8 +31,10 @@
 #define PLAT_NUM_PWR_DOMAINS		(PLATFORM_CORE_COUNT + \
 					 PLATFORM_CLUSTER_COUNT + 1)
 
-#define PLAT_MAX_RET_STATE		1
-#define PLAT_MAX_OFF_STATE		2
+#define PLAT_MAX_RUN_STATE		0
+#define PLAT_MAX_STB_STATE		1
+#define PLAT_MAX_RET_STATE		2
+#define PLAT_MAX_OFF_STATE		3
 
 #define MAX_IO_DEVICES			3
 #define MAX_IO_HANDLES			4
diff --git a/plat/hisilicon/hikey960/platform.mk b/plat/hisilicon/hikey960/platform.mk
index da7bb82..695f092 100644
--- a/plat/hisilicon/hikey960/platform.mk
+++ b/plat/hisilicon/hikey960/platform.mk
@@ -20,6 +20,7 @@
 CRASH_CONSOLE_BASE		:=	PL011_UART6_BASE
 COLD_BOOT_SINGLE_CPU		:=	1
 PROGRAMMABLE_RESET_ADDRESS	:=	1
+ENABLE_SVE_FOR_NS		:=	0
 
 # Process flags
 $(eval $(call add_define,HIKEY960_TSP_RAM_LOCATION_ID))
diff --git a/plat/hisilicon/poplar/aarch64/platform_common.c b/plat/hisilicon/poplar/aarch64/platform_common.c
index a7dac4f..762bd84 100644
--- a/plat/hisilicon/poplar/aarch64/platform_common.c
+++ b/plat/hisilicon/poplar/aarch64/platform_common.c
@@ -25,9 +25,14 @@
 					DEVICE_SIZE,			\
 					MT_DEVICE | MT_RW | MT_SECURE)
 
+#define MAP_TSP_MEM	MAP_REGION_FLAT(TSP_SEC_MEM_BASE,		\
+					TSP_SEC_MEM_SIZE,		\
+					MT_MEMORY | MT_RW | MT_SECURE)
+
 static const mmap_region_t poplar_mmap[] = {
 	MAP_DDR,
 	MAP_DEVICE,
+	MAP_TSP_MEM,
 	{0}
 };
 
diff --git a/plat/hisilicon/poplar/bl2_plat_setup.c b/plat/hisilicon/poplar/bl2_plat_setup.c
index 1741475..db507c3 100644
--- a/plat/hisilicon/poplar/bl2_plat_setup.c
+++ b/plat/hisilicon/poplar/bl2_plat_setup.c
@@ -29,8 +29,10 @@
 typedef struct bl2_to_bl31_params_mem {
 	bl31_params_t		bl31_params;
 	image_info_t		bl31_image_info;
+	image_info_t		bl32_image_info;
 	image_info_t		bl33_image_info;
 	entry_point_info_t	bl33_ep_info;
+	entry_point_info_t	bl32_ep_info;
 	entry_point_info_t	bl31_ep_info;
 } bl2_to_bl31_params_mem_t;
 
@@ -61,6 +63,16 @@
 	SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info,
 		       PARAM_IMAGE_BINARY, VERSION_1, 0);
 
+	/* Fill BL3-2 related information if it exists */
+#ifdef BL32_BASE
+	bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info;
+	SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP,
+		VERSION_1, 0);
+	bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info;
+	SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY,
+		VERSION_1, 0);
+#endif
+
 	/* Fill BL3-3 related information */
 	bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info;
 	SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info,
@@ -89,6 +101,41 @@
 				     DISABLE_ALL_EXCEPTIONS);
 }
 
+/*******************************************************************************
+ * Before calling this function BL32 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL32 and set SPSR and security state.
+ * On Poplar we only set the security state of the entrypoint
+ ******************************************************************************/
+#ifdef BL32_BASE
+void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info,
+					entry_point_info_t *bl32_ep_info)
+{
+	SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE);
+	/*
+	 * The Secure Payload Dispatcher service is responsible for
+	 * setting the SPSR prior to entry into the BL32 image.
+	 */
+	bl32_ep_info->spsr = 0;
+}
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL32
+ ******************************************************************************/
+void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)
+{
+	/*
+	 * Populate the extents of memory available for loading BL32.
+	 */
+	bl32_meminfo->total_base = BL32_BASE;
+	bl32_meminfo->free_base = BL32_BASE;
+	bl32_meminfo->total_size =
+			(TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+	bl32_meminfo->free_size =
+			(TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+}
+#endif /* BL32_BASE */
+
 static uint32_t hisi_get_spsr_for_bl33_entry(void)
 {
 	unsigned long el_status;
@@ -159,5 +206,5 @@
 
 unsigned long plat_get_ns_image_entrypoint(void)
 {
-	return PLAT_ARM_NS_IMAGE_OFFSET;
+	return PLAT_POPLAR_NS_IMAGE_OFFSET;
 }
diff --git a/plat/hisilicon/poplar/bl31_plat_setup.c b/plat/hisilicon/poplar/bl31_plat_setup.c
index b9a0e18..e3a5c50 100644
--- a/plat/hisilicon/poplar/bl31_plat_setup.c
+++ b/plat/hisilicon/poplar/bl31_plat_setup.c
@@ -32,11 +32,31 @@
 #define BL31_COHERENT_RAM_BASE	(unsigned long)(&__COHERENT_RAM_START__)
 #define BL31_COHERENT_RAM_LIMIT	(unsigned long)(&__COHERENT_RAM_END__)
 
+#define TZPC_SEC_ATTR_CTRL_VALUE (0x9DB98D45)
+
+static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
 
+static void hisi_tzpc_sec_init(void)
+{
+	mmio_write_32(HISI_TZPC_SEC_ATTR_CTRL, TZPC_SEC_ATTR_CTRL_VALUE);
+}
+
 entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
 {
-	return &bl33_image_ep_info;
+	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;
+	else
+		return NULL;
 }
 
 void bl31_early_platform_setup(bl31_params_t *from_bl2,
@@ -47,6 +67,13 @@
 	/* Init console for crash report */
 	plat_crash_console_init();
 
+
+	/*
+	 * Copy BL32 (if populated by BL2) and BL33 entry point information.
+	 * They are stored in Secure RAM, in BL2's address space.
+	 */
+	if (from_bl2->bl32_ep_info)
+		bl32_image_ep_info = *from_bl2->bl32_ep_info;
 	bl33_image_ep_info = *from_bl2->bl33_ep_info;
 }
 
@@ -58,6 +85,9 @@
 	/* Init GIC distributor and CPU interface */
 	plat_arm_gic_driver_init();
 	plat_arm_gic_init();
+
+	/* Init security properties of IP blocks */
+	hisi_tzpc_sec_init();
 }
 
 void bl31_plat_runtime_setup(void)
diff --git a/plat/hisilicon/poplar/include/hi3798cv200.h b/plat/hisilicon/poplar/include/hi3798cv200.h
index 6318b9c..540d0aa 100644
--- a/plat/hisilicon/poplar/include/hi3798cv200.h
+++ b/plat/hisilicon/poplar/include/hi3798cv200.h
@@ -30,7 +30,7 @@
 #define TIMER20_BGLOAD			(SEC_TIMER2_BASE + 0x018)
 
 /* GPIO */
-#define	GPIO_MAX			(12)
+#define	GPIO_MAX			(13)
 #define	GPIO_BASE(x)			(x != 5 ?			\
 					0xf820000 + x * 0x1000 : 0xf8004000)
 
@@ -97,4 +97,7 @@
 /* Watchdog */
 #define HISI_WDG0_BASE			(0xF8A2C000)
 
+#define HISI_TZPC_BASE			(0xF8A80000)
+#define HISI_TZPC_SEC_ATTR_CTRL		(HISI_TZPC_BASE + 0x10)
+
 #endif	/* __HI3798cv200_H__ */
diff --git a/plat/hisilicon/poplar/include/platform_def.h b/plat/hisilicon/poplar/include/platform_def.h
index b7afe82..3d1ad9b 100644
--- a/plat/hisilicon/poplar/include/platform_def.h
+++ b/plat/hisilicon/poplar/include/platform_def.h
@@ -48,11 +48,55 @@
 #define TEE_SEC_MEM_BASE		(0x70000000)
 #define TEE_SEC_MEM_SIZE		(0x10000000)
 
+/* Memory location options for TSP */
+#define POPLAR_SRAM_ID	0
+#define POPLAR_DRAM_ID	1
+
+/*
+ * DDR for OP-TEE (28MB from 0x02200000 -0x04000000) is divided in several
+ * regions:
+ *   - Secure DDR (default is the top 16MB) used by OP-TEE
+ *   - Non-secure DDR (4MB) reserved for OP-TEE's future use
+ *   - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature
+ *   - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB)
+ *   - Non-secure DDR (2MB) reserved for OP-TEE's future use
+ */
+#define DDR_SEC_SIZE			0x01000000
+#define DDR_SEC_BASE			0x03000000
+
 #define BL_MEM_BASE			(BL1_RO_BASE)
 #define BL_MEM_LIMIT			(BL31_LIMIT)
 #define BL_MEM_SIZE			(BL_MEM_LIMIT - BL_MEM_BASE)
 
+/*
+ * BL3-2 specific defines.
+ */
+
+/*
+ * The TSP currently executes from TZC secured area of DRAM.
+ */
+#define BL32_DRAM_BASE			0x03000000
+#define BL32_DRAM_LIMIT			0x04000000
+
+#if (POPLAR_TSP_RAM_LOCATION_ID == POPLAR_DRAM_ID)
+#define TSP_SEC_MEM_BASE		BL32_DRAM_BASE
+#define TSP_SEC_MEM_SIZE		(BL32_DRAM_LIMIT - BL32_DRAM_BASE)
+#define BL32_BASE			BL32_DRAM_BASE
+#define BL32_LIMIT			BL32_DRAM_LIMIT
+#elif (POPLAR_TSP_RAM_LOCATION_ID == POPLAR_SRAM_ID)
+#error "SRAM storage of TSP payload is currently unsupported"
+#else
+#error "Currently unsupported POPLAR_TSP_LOCATION_ID value"
+#endif
+
+/* BL32 is mandatory in AArch32 */
+#ifndef AARCH32
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
+#endif
+
-#define PLAT_ARM_NS_IMAGE_OFFSET	0x37000000
+#define PLAT_POPLAR_NS_IMAGE_OFFSET	0x37000000
 
 /* Page table and MMU setup constants */
 #define ADDR_SPACE_SIZE			(1ull << 32)
diff --git a/plat/hisilicon/poplar/include/poplar_layout.h b/plat/hisilicon/poplar/include/poplar_layout.h
index 192bcb9..e0b5618 100644
--- a/plat/hisilicon/poplar/include/poplar_layout.h
+++ b/plat/hisilicon/poplar/include/poplar_layout.h
@@ -74,16 +74,16 @@
  * "OFFSET" is an offset to the start of a region relative to the
  * base of the "l-loader" TEXT section (also a multiple of page size).
  */
-#define LLOADER_TEXT_BASE		0x00001000	/* page aligned */
+#define LLOADER_TEXT_BASE		0x02001000	/* page aligned */
 #define BL1_OFFSET			0x0000D000	/* page multiple */
-#define FIP_BASE			0x00040000
+#define FIP_BASE			0x02040000
 
 #define BL1_RO_SIZE			0x00008000	/* page multiple */
 #define BL1_RW_SIZE			0x00008000	/* page multiple */
 #define BL1_SIZE			(BL1_RO_SIZE + BL1_RW_SIZE)
 #define BL2_SIZE			0x0000c000	/* page multiple */
 #define BL31_SIZE			0x00014000
-#define FIP_SIZE			0x00068000
+#define FIP_SIZE			0x000c0000  /* absolute max */
 
      /* BL1_OFFSET */			/* (Defined above) */
 #define BL1_BASE			(LLOADER_TEXT_BASE + BL1_OFFSET)
diff --git a/plat/hisilicon/poplar/plat_storage.c b/plat/hisilicon/poplar/plat_storage.c
index 623a61b..ab94cba 100644
--- a/plat/hisilicon/poplar/plat_storage.c
+++ b/plat/hisilicon/poplar/plat_storage.c
@@ -43,6 +43,10 @@
 	.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
 };
 
+static const io_uuid_spec_t bl32_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
 static const io_uuid_spec_t bl33_uuid_spec = {
 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
 };
@@ -69,6 +73,11 @@
 		(uintptr_t)&bl31_uuid_spec,
 		open_fip
 	},
+	[BL32_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_uuid_spec,
+		open_fip
+	},
 	[BL33_IMAGE_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&bl33_uuid_spec,
diff --git a/plat/hisilicon/poplar/platform.mk b/plat/hisilicon/poplar/platform.mk
index fc75ff3..818e311 100644
--- a/plat/hisilicon/poplar/platform.mk
+++ b/plat/hisilicon/poplar/platform.mk
@@ -4,6 +4,17 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# On Poplar, the TSP can execute from TZC secure area in DRAM.
+POPLAR_TSP_RAM_LOCATION	:=	dram
+ifeq (${POPLAR_TSP_RAM_LOCATION}, dram)
+  POPLAR_TSP_RAM_LOCATION_ID = POPLAR_DRAM_ID
+else ifeq (${HIKEY960_TSP_RAM_LOCATION}, sram)
+  POPLAR_TSP_RAM_LOCATION_ID := POPLAR_SRAM_ID
+else
+  $(error "Currently unsupported POPLAR_TSP_RAM_LOCATION value")
+endif
+$(eval $(call add_define,POPLAR_TSP_RAM_LOCATION_ID))
+
 NEED_BL33			:= yes
 
 COLD_BOOT_SINGLE_CPU		:= 1
@@ -13,6 +24,7 @@
 ERRATA_A53_855873		:= 1
 ERRATA_A53_835769		:= 1
 ERRATA_A53_843419		:= 1
+ENABLE_SVE_FOR_NS		:= 0
 
 ARM_GIC_ARCH			:= 2
 $(eval $(call add_define,ARM_GIC_ARCH))
@@ -69,4 +81,3 @@
 		plat/hisilicon/poplar/bl31_plat_setup.c			\
 		plat/hisilicon/poplar/plat_topology.c			\
 		plat/hisilicon/poplar/plat_pm.c
-
diff --git a/plat/mediatek/mt6795/bl31.ld.S b/plat/mediatek/mt6795/bl31.ld.S
index 0f60a0c..eacb1b2 100644
--- a/plat/mediatek/mt6795/bl31.ld.S
+++ b/plat/mediatek/mt6795/bl31.ld.S
@@ -5,6 +5,7 @@
  */
 
 #include <platform_def.h>
+#include <xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
 OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
@@ -29,7 +30,7 @@
         *(.vectors)
     } >RAM
 
-    ASSERT(. == ALIGN(4096),
+    ASSERT(. == ALIGN(PAGE_SIZE),
            "BL31_BASE address is not aligned on a page boundary.")
 
     ro . : {
@@ -58,7 +59,7 @@
          * executable.  No RW data from the next section must creep in.
          * Ensure the rest of the current memory page is unused.
          */
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __RO_END__ = .;
     } >RAM
 
@@ -144,7 +145,7 @@
      * are not mixed with normal data.  This is required to set up the correct
      * memory attributes for the coherent data page tables.
      */
-    coherent_ram (NOLOAD) : ALIGN(4096) {
+    coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) {
         __COHERENT_RAM_START__ = .;
         /*
          * Bakery locks are stored in coherent memory
@@ -159,7 +160,7 @@
          * as device memory.  No other unexpected data must creep in.
          * Ensure the rest of the current memory page is unused.
          */
-        . = NEXT(4096);
+        . = NEXT(PAGE_SIZE);
         __COHERENT_RAM_END__ = .;
     } >RAM2
 #endif
diff --git a/plat/mediatek/mt6795/platform.mk b/plat/mediatek/mt6795/platform.mk
index 4ebc78e..8230067 100644
--- a/plat/mediatek/mt6795/platform.mk
+++ b/plat/mediatek/mt6795/platform.mk
@@ -66,3 +66,5 @@
 
 $(eval $(call add_define,MTK_SIP_KERNEL_BOOT_ENABLE))
 
+# Do not enable SVE
+ENABLE_SVE_FOR_NS	:=	0
diff --git a/plat/mediatek/mt8173/platform.mk b/plat/mediatek/mt8173/platform.mk
index cd01645..2eef81b 100644
--- a/plat/mediatek/mt8173/platform.mk
+++ b/plat/mediatek/mt8173/platform.mk
@@ -70,3 +70,6 @@
 PROGRAMMABLE_RESET_ADDRESS	:=	1
 
 $(eval $(call add_define,MTK_SIP_SET_AUTHORIZED_SECURE_REG_ENABLE))
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS		:=	0
diff --git a/plat/nvidia/tegra/platform.mk b/plat/nvidia/tegra/platform.mk
index 9a9e79e..ad60620 100644
--- a/plat/nvidia/tegra/platform.mk
+++ b/plat/nvidia/tegra/platform.mk
@@ -29,6 +29,9 @@
 # do not use coherent memory
 USE_COHERENT_MEM	:=	0
 
+# do not enable SVE
+ENABLE_SVE_FOR_NS	:=	0
+
 include plat/nvidia/tegra/common/tegra_common.mk
 include ${SOC_DIR}/platform_${TARGET_SOC}.mk
 
diff --git a/plat/qemu/platform.mk b/plat/qemu/platform.mk
index 2a7415f..43ab846 100644
--- a/plat/qemu/platform.mk
+++ b/plat/qemu/platform.mk
@@ -153,3 +153,6 @@
 
 # Process flags
 $(eval $(call add_define,BL32_RAM_LOCATION_ID))
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS	:=	0
diff --git a/plat/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk
index 8863fb4..5de4680 100644
--- a/plat/rockchip/rk3328/platform.mk
+++ b/plat/rockchip/rk3328/platform.mk
@@ -48,7 +48,10 @@
 				${RK_PLAT_SOC}/drivers/pmu/pmu.c		\
 				${RK_PLAT_SOC}/drivers/soc/soc.c
 
-ENABLE_PLAT_COMPAT 	:=      0
+ENABLE_PLAT_COMPAT 	:=	0
 
 $(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
 $(eval $(call add_define,PLAT_SKIP_OPTEE_S_EL1_INT_REGISTER))
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS	:=	0
diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk
index f6960cf..d3c6eef 100644
--- a/plat/rockchip/rk3368/platform.mk
+++ b/plat/rockchip/rk3368/platform.mk
@@ -48,6 +48,9 @@
 				${RK_PLAT_SOC}/drivers/soc/soc.c		\
 				${RK_PLAT_SOC}/drivers/ddr/ddr_rk3368.c		\
 
-ENABLE_PLAT_COMPAT	:=      0
+ENABLE_PLAT_COMPAT	:=	0
 
 $(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS	:=	0
diff --git a/plat/rockchip/rk3399/include/plat.ld.S b/plat/rockchip/rk3399/include/plat.ld.S
index c42d9a9..85f4dc3 100644
--- a/plat/rockchip/rk3399/include/plat.ld.S
+++ b/plat/rockchip/rk3399/include/plat.ld.S
@@ -6,6 +6,8 @@
 #ifndef __ROCKCHIP_PLAT_LD_S__
 #define __ROCKCHIP_PLAT_LD_S__
 
+#include <xlat_tables_defs.h>
+
 MEMORY {
     SRAM (rwx): ORIGIN = SRAM_BASE, LENGTH = SRAM_SIZE
     PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE
@@ -14,7 +16,7 @@
 SECTIONS
 {
 	. = SRAM_BASE;
-	ASSERT(. == ALIGN(4096),
+	ASSERT(. == ALIGN(PAGE_SIZE),
 		"SRAM_BASE address is not aligned on a page boundary.")
 
 	/*
@@ -27,40 +29,40 @@
 	 * | sram data
 	 * ----------------
 	 */
-	.incbin_sram : ALIGN(4096) {
+	.incbin_sram : ALIGN(PAGE_SIZE) {
 		__sram_incbin_start = .;
 		*(.sram.incbin)
 		 __sram_incbin_real_end = .;
-		. = ALIGN(4096);
+		. = ALIGN(PAGE_SIZE);
 		__sram_incbin_end = .;
 	} >SRAM
 	ASSERT((__sram_incbin_real_end - __sram_incbin_start) <=
 		SRAM_BIN_LIMIT, ".incbin_sram has exceeded its limit")
 
-	.text_sram : ALIGN(4096) {
+	.text_sram : ALIGN(PAGE_SIZE) {
 		__bl31_sram_text_start = .;
 		*(.sram.text)
 		*(.sram.rodata)
 		__bl31_sram_text_real_end = .;
-		. = ALIGN(4096);
+		. = ALIGN(PAGE_SIZE);
 		__bl31_sram_text_end = .;
 	} >SRAM
 	ASSERT((__bl31_sram_text_real_end - __bl31_sram_text_start) <=
 		SRAM_TEXT_LIMIT, ".text_sram has exceeded its limit")
 
-	.data_sram : ALIGN(4096) {
+	.data_sram : ALIGN(PAGE_SIZE) {
 		__bl31_sram_data_start = .;
 		*(.sram.data)
 		__bl31_sram_data_real_end = .;
-		. = ALIGN(4096);
+		. = ALIGN(PAGE_SIZE);
 		__bl31_sram_data_end = .;
 	} >SRAM
 	ASSERT((__bl31_sram_data_real_end - __bl31_sram_data_start) <=
 		SRAM_DATA_LIMIT, ".data_sram has exceeded its limit")
 
-	.stack_sram : ALIGN(4096) {
+	.stack_sram : ALIGN(PAGE_SIZE) {
 		__bl31_sram_stack_start = .;
-		. += 4096;
+		. += PAGE_SIZE;
 		__bl31_sram_stack_end = .;
 	} >SRAM
 
diff --git a/plat/rockchip/rk3399/plat_sip_calls.c b/plat/rockchip/rk3399/plat_sip_calls.c
index 074dc19..2fbda67 100644
--- a/plat/rockchip/rk3399/plat_sip_calls.c
+++ b/plat/rockchip/rk3399/plat_sip_calls.c
@@ -11,6 +11,7 @@
 #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/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk
index 6cd5b24..33b9723 100644
--- a/plat/rockchip/rk3399/platform.mk
+++ b/plat/rockchip/rk3399/platform.mk
@@ -92,3 +92,6 @@
 .PHONY: $(RK3399M0FW)
 $(RK3399M0FW): | ${BUILD_M0}
 	$(MAKE) -C ${RK_PLAT_SOC}/drivers/m0 BUILD=$(abspath ${BUILD_PLAT}/m0)
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS	:=	0
diff --git a/plat/rpi3/aarch64/plat_helpers.S b/plat/rpi3/aarch64/plat_helpers.S
new file mode 100644
index 0000000..76a542f
--- /dev/null
+++ b/plat/rpi3/aarch64/plat_helpers.S
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2015-2017, 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>
+
+#include "../rpi3_hw.h"
+
+	.globl	plat_crash_console_flush
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_putc
+	.globl	platform_mem_init
+	.globl	plat_get_my_entrypoint
+	.globl	plat_is_my_cpu_primary
+	.globl	plat_my_core_pos
+	.globl	plat_reset_handler
+	.globl	plat_rpi3_calc_core_pos
+	.globl	plat_secondary_cold_boot_setup
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_my_core_pos(void)
+	 *
+	 *  This function uses the plat_rpi3_calc_core_pos()
+	 *  definition to get the index of the calling CPU.
+	 * -----------------------------------------------------
+	 */
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	b	plat_rpi3_calc_core_pos
+endfunc plat_my_core_pos
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
+	 *
+	 *  CorePos = (ClusterId * 4) + CoreId
+	 * -----------------------------------------------------
+	 */
+func plat_rpi3_calc_core_pos
+	and	x1, x0, #MPIDR_CPU_MASK
+	and	x0, x0, #MPIDR_CLUSTER_MASK
+	add	x0, x1, x0, LSR #6
+	ret
+endfunc plat_rpi3_calc_core_pos
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_is_my_cpu_primary (void);
+	 *
+	 * Find out whether the current cpu is the primary
+	 * cpu.
+	 * -----------------------------------------------------
+	 */
+func plat_is_my_cpu_primary
+	mrs	x0, mpidr_el1
+	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+	cmp	x0, #RPI3_PRIMARY_CPU
+	cset	w0, eq
+	ret
+endfunc plat_is_my_cpu_primary
+
+	/* -----------------------------------------------------
+	 * void plat_secondary_cold_boot_setup (void);
+	 *
+	 * This function performs any platform specific actions
+	 * needed for a secondary cpu after a cold reset e.g
+	 * mark the cpu's presence, mechanism to place it in a
+	 * holding pen etc.
+	 * -----------------------------------------------------
+	 */
+func plat_secondary_cold_boot_setup
+	/* Calculate address of our hold entry */
+	bl	plat_my_core_pos
+	lsl	x0, x0, #3
+	mov_imm	x2, PLAT_RPI3_TM_HOLD_BASE
+	add	x0, x0, x2
+
+	/*
+	 * This code runs way before requesting the warmboot of this core,
+	 * so it is possible to clear the mailbox before getting a request
+	 * to boot.
+	 */
+	mov	x1, PLAT_RPI3_TM_HOLD_STATE_WAIT
+	str	x1,[x0]
+
+	/* Wait until we have a go */
+poll_mailbox:
+	wfe
+	ldr	x1, [x0]
+	cmp	x1, PLAT_RPI3_TM_HOLD_STATE_GO
+	bne	poll_mailbox
+
+	/* Jump to the provided entrypoint */
+	mov_imm	x0, PLAT_RPI3_TM_ENTRYPOINT
+	ldr	x1, [x0]
+	br	x1
+endfunc plat_secondary_cold_boot_setup
+
+	/* ---------------------------------------------------------------------
+	 * uintptr_t plat_get_my_entrypoint (void);
+	 *
+	 * Main job of this routine is to distinguish between a cold and a warm
+	 * boot.
+	 *
+	 * This functions returns:
+	 *  - 0 for a cold boot.
+	 *  - Any other value for a warm boot.
+	 * ---------------------------------------------------------------------
+	 */
+func plat_get_my_entrypoint
+	/* TODO: support warm boot */
+	mov	x0, #0
+	ret
+endfunc plat_get_my_entrypoint
+
+	/* ---------------------------------------------
+	 * void platform_mem_init (void);
+	 *
+	 * No need to carry out any memory initialization.
+	 * ---------------------------------------------
+	 */
+func platform_mem_init
+	ret
+endfunc platform_mem_init
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_init(void)
+	 * Function to initialize the crash console
+	 * without a C Runtime to print crash report.
+	 * Clobber list : x0 - x3
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_init
+	mov_imm	x0, PLAT_RPI3_UART_BASE
+	mov_imm	x1, PLAT_RPI3_UART_CLK_IN_HZ
+	mov_imm	x2, PLAT_RPI3_UART_BAUDRATE
+	b	console_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_RPI3_UART_BASE
+	b	console_core_putc
+endfunc plat_crash_console_putc
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_flush()
+	 * 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	x1, PLAT_RPI3_UART_BASE
+	b	console_core_flush
+endfunc plat_crash_console_flush
+
+	/* ---------------------------------------------
+	 * void plat_reset_handler(void);
+	 * ---------------------------------------------
+	 */
+func plat_reset_handler
+	/* use the 19.2 MHz clock for the architected timer */
+	mov	x0, #RPI3_INTC_BASE_ADDRESS
+	mov	w1, #0x80000000
+	str	wzr, [x0, #RPI3_INTC_CONTROL_OFFSET]
+	str	w1, [x0, #RPI3_INTC_PRESCALER_OFFSET]
+
+	/* wire mailbox 3 to the FIQ line */
+	mov	w1, RPI3_INTC_MBOX_CONTROL_SLOT3_FIQ
+	str	w1, [x0, #RPI3_INTC_MBOX_CONTROL_OFFSET]
+	ret
+endfunc plat_reset_handler
diff --git a/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c b/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c
new file mode 100644
index 0000000..e3acfe9
--- /dev/null
+++ b/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <desc_image_load.h>
+#include <platform.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+
+	/* Fill BL31 related information */
+	{
+		.image_id = BL31_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | EXECUTABLE | EP_FIRST_EXE),
+		.ep_info.pc = BL31_BASE,
+		.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+					DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+		.ep_info.args.arg1 = RPI3_BL31_PLAT_PARAM_VAL,
+#endif
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_PLAT_SETUP),
+		.image_info.image_base = BL31_BASE,
+		.image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+# ifdef BL32_BASE
+		.next_handoff_image_id = BL32_IMAGE_ID,
+# else
+		.next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+	},
+
+# ifdef BL32_BASE
+	/* Fill BL32 related information */
+	{
+		.image_id = BL32_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | EXECUTABLE),
+		.ep_info.pc = BL32_BASE,
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t, 0),
+		.image_info.image_base = BL32_BASE,
+		.image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+		.next_handoff_image_id = BL33_IMAGE_ID,
+	},
+
+	/*
+	 * Fill BL32 external 1 related information.
+	 * A typical use for extra1 image is with OP-TEE where it is the pager
+	 * image.
+	 */
+	{
+		.image_id = BL32_EXTRA1_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+		.image_info.image_base = BL32_BASE,
+		.image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+
+	/*
+	 * Fill BL32 external 2 related information.
+	 * A typical use for extra2 image is with OP-TEE where it is the paged
+	 * image.
+	 */
+	{
+		.image_id = BL32_EXTRA2_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+# endif /* BL32_BASE */
+
+	/* Fill BL33 related information */
+	{
+		.image_id = BL33_IMAGE_ID,
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      NON_SECURE | EXECUTABLE),
+# ifdef PRELOADED_BL33_BASE
+		.ep_info.pc = PRELOADED_BL33_BASE,
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+# else
+		.ep_info.pc = PLAT_RPI3_NS_IMAGE_OFFSET,
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t, 0),
+		.image_info.image_base = PLAT_RPI3_NS_IMAGE_OFFSET,
+		.image_info.image_max_size = PLAT_RPI3_NS_IMAGE_MAX_SIZE,
+# endif /* PRELOADED_BL33_BASE */
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	}
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/rpi3/include/plat_macros.S b/plat/rpi3/include/plat_macros.S
new file mode 100644
index 0000000..f5e057e
--- /dev/null
+++ b/plat/rpi3/include/plat_macros.S
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016-2017, 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 <platform_def.h>
+
+	/* ---------------------------------------------
+	 * The below required platform porting macro
+	 * prints out relevant platform registers
+	 * whenever an unhandled exception is taken in
+	 * BL31.
+	 * Clobbers: x0 - x10, x16, x17, sp
+	 * ---------------------------------------------
+	 */
+	.macro plat_crash_print_regs
+	.endm
+
+#endif /* __PLAT_MACROS_S__ */
diff --git a/plat/rpi3/include/platform_def.h b/plat/rpi3/include/platform_def.h
new file mode 100644
index 0000000..5e2f1da
--- /dev/null
+++ b/plat/rpi3/include/platform_def.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2015-2017, 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 <common_def.h>
+#include <tbbr_img_def.h>
+#include <utils_def.h>
+
+#include "../rpi3_hw.h"
+
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define RPI3_BL31_PLAT_PARAM_VAL	ULL(0x0F1E2D3C4B5A6978)
+
+#define PLATFORM_STACK_SIZE		ULL(0x1000)
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER	U(4)
+#define PLATFORM_CLUSTER_COUNT		U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT	PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CORE_COUNT		PLATFORM_CLUSTER0_CORE_COUNT
+
+#define RPI3_PRIMARY_CPU		U(0)
+
+#define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL1
+#define PLAT_NUM_PWR_DOMAINS		(PLATFORM_CLUSTER_COUNT + \
+					 PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_RET_STATE		U(1)
+#define PLAT_MAX_OFF_STATE		U(2)
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN		U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET		U(1)
+/*
+ * Local power state for OFF/power-down. Valid for CPU and cluster power
+ * domains.
+ */
+#define PLAT_LOCAL_STATE_OFF		U(2)
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH		U(4)
+#define PLAT_LOCAL_PSTATE_MASK		((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * 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		U(6)
+#define CACHE_WRITEBACK_GRANULE		(U(1) << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Partition memory into secure ROM, non-secure DRAM, secure "SRAM", and
+ * secure DRAM. Note that this is all actually DRAM with different names,
+ * there is no Secure RAM in the Raspberry Pi 3.
+ */
+#define SEC_ROM_BASE			ULL(0x00000000)
+#define SEC_ROM_SIZE			ULL(0x00010000)
+
+/* FIP placed after ROM to append it to BL1 with very little padding. */
+#define PLAT_RPI3_FIP_BASE		ULL(0x00010000)
+#define PLAT_RPI3_FIP_MAX_SIZE		ULL(0x001F0000)
+
+/* We have 16M of memory reserved at at 256M */
+#define SEC_SRAM_BASE			ULL(0x10000000)
+#define SEC_SRAM_SIZE			ULL(0x00100000)
+
+#define SEC_DRAM0_BASE			ULL(0x10100000)
+#define SEC_DRAM0_SIZE			ULL(0x00200000)
+
+#define NS_DRAM0_BASE			ULL(0x10300000)
+#define NS_DRAM0_SIZE			ULL(0x00D00000)
+/* End of reserved memory */
+
+/*
+ * BL33 entrypoint.
+ */
+#define PLAT_RPI3_NS_IMAGE_OFFSET	NS_DRAM0_BASE
+#define PLAT_RPI3_NS_IMAGE_MAX_SIZE	NS_DRAM0_SIZE
+
+/*
+ * I/O registers.
+ */
+#define DEVICE0_BASE			RPI3_IO_BASE
+#define DEVICE0_SIZE			RPI3_IO_SIZE
+
+/*
+ * Arm TF lives in SRAM, partition it here
+ */
+#define SHARED_RAM_BASE			SEC_SRAM_BASE
+#define SHARED_RAM_SIZE			ULL(0x00001000)
+
+#define BL_RAM_BASE			(SHARED_RAM_BASE + SHARED_RAM_SIZE)
+#define BL_RAM_SIZE			(SEC_SRAM_SIZE - SHARED_RAM_SIZE)
+
+/*
+ * Mailbox to control the secondary cores.All secondary cores are held in a wait
+ * loop in cold boot. To release them perform the following steps (plus any
+ * additional barriers that may be needed):
+ *
+ *     uint64_t *entrypoint = (uint64_t *)PLAT_RPI3_TM_ENTRYPOINT;
+ *     *entrypoint = ADDRESS_TO_JUMP_TO;
+ *
+ *     uint64_t *mbox_entry = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE;
+ *     mbox_entry[cpu_id] = PLAT_RPI3_TM_HOLD_STATE_GO;
+ *
+ *     sev();
+ */
+#define PLAT_RPI3_TRUSTED_MAILBOX_BASE	SHARED_RAM_BASE
+
+#define PLAT_RPI3_TM_ENTRYPOINT		PLAT_RPI3_TRUSTED_MAILBOX_BASE
+#define PLAT_RPI3_TM_ENTRYPOINT_SIZE	ULL(8)
+
+#define PLAT_RPI3_TM_HOLD_BASE		(PLAT_RPI3_TM_ENTRYPOINT + \
+					 PLAT_RPI3_TM_ENTRYPOINT_SIZE)
+#define PLAT_RPI3_TM_HOLD_ENTRY_SIZE	ULL(8)
+#define PLAT_RPI3_TM_HOLD_SIZE		(PLAT_RPI3_TM_HOLD_ENTRY_SIZE * \
+					 PLATFORM_CORE_COUNT)
+
+#define PLAT_RPI3_TRUSTED_MAILBOX_SIZE	(PLAT_RPI3_TM_ENTRYPOINT_SIZE + \
+					 PLAT_RPI3_TM_HOLD_SIZE)
+
+#define PLAT_RPI3_TM_HOLD_STATE_WAIT	ULL(0)
+#define PLAT_RPI3_TM_HOLD_STATE_GO	ULL(1)
+
+/*
+ * BL1 specific defines.
+ *
+ * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
+ * addresses.
+ *
+ * Put BL1 RW at the top of the Secure SRAM. BL1_RW_BASE is calculated using
+ * the current BL1 RW debug size plus a little space for growth.
+ */
+#define PLAT_MAX_BL1_RW_SIZE		ULL(0x12000)
+
+#define BL1_RO_BASE			SEC_ROM_BASE
+#define BL1_RO_LIMIT			(SEC_ROM_BASE + SEC_ROM_SIZE)
+#define BL1_RW_BASE			(BL1_RW_LIMIT - PLAT_MAX_BL1_RW_SIZE)
+#define BL1_RW_LIMIT			(BL_RAM_BASE + BL_RAM_SIZE)
+
+/*
+ * BL2 specific defines.
+ *
+ * Put BL2 just below BL31. BL2_BASE is calculated using the current BL2 debug
+ * size plus a little space for growth.
+ */
+#define PLAT_MAX_BL2_SIZE		ULL(0x2C000)
+
+#define BL2_BASE			(BL2_LIMIT - PLAT_MAX_BL2_SIZE)
+#define BL2_LIMIT			BL31_BASE
+
+/*
+ * BL31 specific defines.
+ *
+ * Put BL31 at the top of the Trusted SRAM. BL31_BASE is calculated using the
+ * current BL31 debug size plus a little space for growth.
+ */
+#define PLAT_MAX_BL31_SIZE		ULL(0x20000)
+
+#define BL31_BASE			(BL31_LIMIT - PLAT_MAX_BL31_SIZE)
+#define BL31_LIMIT			(BL_RAM_BASE + BL_RAM_SIZE)
+#define BL31_PROGBITS_LIMIT		BL1_RW_BASE
+
+/*
+ * BL32 specific defines.
+ *
+ * BL32 can execute from Secure SRAM or Secure DRAM.
+ */
+#define BL32_SRAM_BASE			BL_RAM_BASE
+#define BL32_SRAM_LIMIT			BL31_BASE
+#define BL32_DRAM_BASE			SEC_DRAM0_BASE
+#define BL32_DRAM_LIMIT			(SEC_DRAM0_BASE + SEC_DRAM0_SIZE)
+
+#define SEC_SRAM_ID			0
+#define SEC_DRAM_ID			1
+
+#if RPI3_BL32_RAM_LOCATION_ID == SEC_SRAM_ID
+# define BL32_MEM_BASE			BL_RAM_BASE
+# define BL32_MEM_SIZE			BL_RAM_SIZE
+# define BL32_BASE			BL32_SRAM_BASE
+# define BL32_LIMIT			BL32_SRAM_LIMIT
+#elif RPI3_BL32_RAM_LOCATION_ID == SEC_DRAM_ID
+# define BL32_MEM_BASE			SEC_DRAM0_BASE
+# define BL32_MEM_SIZE			SEC_DRAM0_SIZE
+# define BL32_BASE			BL32_DRAM_BASE
+# define BL32_LIMIT			BL32_DRAM_LIMIT
+#else
+# error "Unsupported RPI3_BL32_RAM_LOCATION_ID value"
+#endif
+#define BL32_SIZE			(BL32_LIMIT - BL32_BASE)
+
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
+
+/*
+ * Other memory-related defines.
+ */
+#define ADDR_SPACE_SIZE			(ULL(1) << 32)
+
+#define MAX_MMAP_REGIONS		U(8)
+#define MAX_XLAT_TABLES			U(4)
+
+#define MAX_IO_DEVICES			U(3)
+#define MAX_IO_HANDLES			U(4)
+
+/*
+ * Serial-related constants.
+ */
+#define PLAT_RPI3_UART_BASE		RPI3_MINI_UART_BASE
+#define PLAT_RPI3_UART_CLK_IN_HZ	RPI3_MINI_UART_CLK_IN_HZ
+#define PLAT_RPI3_UART_BAUDRATE		ULL(115200)
+
+/*
+ * System counter
+ */
+#define SYS_COUNTER_FREQ_IN_TICKS	ULL(19200000)
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/rpi3/platform.mk b/plat/rpi3/platform.mk
new file mode 100644
index 0000000..821f801
--- /dev/null
+++ b/plat/rpi3/platform.mk
@@ -0,0 +1,113 @@
+#
+# Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES		:=	-Iinclude/common/tbbr			\
+				-Iinclude/plat/arm/common/		\
+				-Iinclude/plat/arm/common/aarch64/	\
+				-Iplat/rpi3/include
+
+PLAT_BL_COMMON_SOURCES	:=	drivers/console/aarch64/console.S	\
+				drivers/ti/uart/aarch64/16550_console.S	\
+				plat/rpi3/rpi3_common.c
+
+BL1_SOURCES		+=	drivers/io/io_fip.c			\
+				drivers/io/io_memmap.c			\
+				drivers/io/io_storage.c			\
+				lib/cpus/aarch64/cortex_a53.S		\
+				plat/common/aarch64/platform_mp_stack.S	\
+				plat/rpi3/aarch64/plat_helpers.S	\
+				plat/rpi3/rpi3_bl1_setup.c		\
+				plat/rpi3/rpi3_io_storage.c
+
+BL2_SOURCES		+=	common/desc_image_load.c		\
+				drivers/io/io_fip.c			\
+				drivers/io/io_memmap.c			\
+				drivers/io/io_storage.c			\
+				plat/common/aarch64/platform_mp_stack.S	\
+				plat/rpi3/aarch64/plat_helpers.S	\
+				plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c \
+				plat/rpi3/rpi3_bl2_setup.c		\
+				plat/rpi3/rpi3_image_load.c		\
+				plat/rpi3/rpi3_io_storage.c
+
+BL31_SOURCES		+=	lib/cpus/aarch64/cortex_a53.S		\
+				plat/common/aarch64/plat_psci_common.c	\
+				plat/rpi3/aarch64/plat_helpers.S	\
+				plat/rpi3/rpi3_bl31_setup.c		\
+				plat/rpi3/rpi3_pm.c			\
+				plat/rpi3/rpi3_topology.c
+
+# Translation tables library
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_BL_COMMON_SOURCES	+=	${XLAT_TABLES_LIB_SRCS}
+
+# Tune compiler for Cortex-A53
+ifeq ($(notdir $(CC)),armclang)
+    TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
+else ifneq ($(findstring clang,$(notdir $(CC))),)
+    TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
+else
+    TF_CFLAGS_aarch64	+=	-mtune=cortex-a53
+endif
+
+# Build config flags
+# ------------------
+
+# Enable all errata workarounds for Cortex-A53
+ERRATA_A53_826319		:= 1
+ERRATA_A53_835769		:= 1
+ERRATA_A53_836870		:= 1
+ERRATA_A53_843419		:= 1
+ERRATA_A53_855873		:= 1
+
+# Disable the PSCI platform compatibility layer by default
+ENABLE_PLAT_COMPAT		:= 0
+
+# Enable reset to BL31 by default
+RESET_TO_BL31			:= 1
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA	:= 1
+
+# Use Coherent memory
+USE_COHERENT_MEM		:= 1
+
+# Enable new version of image loading
+LOAD_IMAGE_V2			:= 1
+
+# Platform build flags
+# --------------------
+
+# BL33 images are in AArch64 by default
+RPI3_BL33_IN_AARCH32		:= 0
+
+# BL32 location
+RPI3_BL32_RAM_LOCATION	:= tdram
+ifeq (${RPI3_BL32_RAM_LOCATION}, tsram)
+  RPI3_BL32_RAM_LOCATION_ID = SEC_SRAM_ID
+else ifeq (${RPI3_BL32_RAM_LOCATION}, tdram)
+  RPI3_BL32_RAM_LOCATION_ID = SEC_DRAM_ID
+else
+  $(error "Unsupported RPI3_BL32_RAM_LOCATION value")
+endif
+
+# Process platform flags
+# ----------------------
+
+$(eval $(call add_define,RPI3_BL32_RAM_LOCATION_ID))
+$(eval $(call add_define,RPI3_BL33_IN_AARCH32))
+
+# Verify build config
+# -------------------
+
+ifneq (${LOAD_IMAGE_V2}, 1)
+  $(error Error: rpi3 needs LOAD_IMAGE_V2=1)
+endif
+
+ifeq (${ARCH},aarch32)
+  $(error Error: AArch32 not supported on rpi3)
+endif
diff --git a/plat/rpi3/rpi3_bl1_setup.c b/plat/rpi3/rpi3_bl1_setup.c
new file mode 100644
index 0000000..11c0f4a
--- /dev/null
+++ b/plat/rpi3/rpi3_bl1_setup.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <bl_common.h>
+#include <console.h>
+#include <platform_def.h>
+#include <xlat_mmu_helpers.h>
+#include <xlat_tables_defs.h>
+
+#include "../../bl1/bl1_private.h"
+#include "rpi3_private.h"
+
+/* Data structure which holds the extents of the trusted SRAM for BL1 */
+static meminfo_t bl1_tzram_layout;
+
+meminfo_t *bl1_plat_sec_mem_layout(void)
+{
+	return &bl1_tzram_layout;
+}
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+	/* Initialize the console to provide early debug support */
+	console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ,
+		     PLAT_RPI3_UART_BAUDRATE);
+
+	/* Allow BL1 to see the whole Trusted RAM */
+	bl1_tzram_layout.total_base = BL_RAM_BASE;
+	bl1_tzram_layout.total_size = BL_RAM_SIZE;
+}
+
+/******************************************************************************
+ * Perform the very early platform specific architecture setup.  This only
+ * does basic initialization. Later architectural setup (bl1_arch_setup())
+ * does not do anything platform specific.
+ *****************************************************************************/
+void bl1_plat_arch_setup(void)
+{
+	rpi3_setup_page_tables(bl1_tzram_layout.total_base,
+			       bl1_tzram_layout.total_size,
+			       BL_CODE_BASE, BL1_CODE_END,
+			       BL1_RO_DATA_BASE, BL1_RO_DATA_END
+#if USE_COHERENT_MEM
+			       , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
+#endif
+			      );
+
+	enable_mmu_el3(0);
+}
+
+void bl1_platform_setup(void)
+{
+	/* Initialise the IO layer and register platform IO devices */
+	plat_rpi3_io_setup();
+}
diff --git a/plat/rpi3/rpi3_bl2_setup.c b/plat/rpi3/rpi3_bl2_setup.c
new file mode 100644
index 0000000..1fd822e
--- /dev/null
+++ b/plat/rpi3/rpi3_bl2_setup.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <debug.h>
+#include <desc_image_load.h>
+#include <platform_def.h>
+#include <xlat_mmu_helpers.h>
+#include <xlat_tables_defs.h>
+
+#include "rpi3_private.h"
+
+/* Data structure which holds the extents of the trusted SRAM for BL2 */
+static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+
+/*******************************************************************************
+ * BL1 has passed the extents of the trusted SRAM that should be visible to BL2
+ * in x0. This memory layout is sitting at the base of the free trusted SRAM.
+ * Copy it to a safe location before its reclaimed by later BL2 functionality.
+ ******************************************************************************/
+void bl2_early_platform_setup(meminfo_t *mem_layout)
+{
+	/* Initialize the console to provide early debug support */
+	console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ,
+		     PLAT_RPI3_UART_BAUDRATE);
+
+	/* Setup the BL2 memory layout */
+	bl2_tzram_layout = *mem_layout;
+
+	plat_rpi3_io_setup();
+}
+
+void bl2_platform_setup(void)
+{
+	/*
+	 * This is where a TrustZone address space controller and other
+	 * security related peripherals, would be configured.
+	 */
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here.
+ ******************************************************************************/
+void bl2_plat_arch_setup(void)
+{
+	rpi3_setup_page_tables(bl2_tzram_layout.total_base,
+			       bl2_tzram_layout.total_size,
+			       BL_CODE_BASE, BL_CODE_END,
+			       BL_RO_DATA_BASE, BL_RO_DATA_END
+#if USE_COHERENT_MEM
+			       , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
+#endif
+			      );
+
+	enable_mmu_el1(0);
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	int err = 0;
+	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
+	assert(bl_mem_params != NULL);
+
+	switch (image_id) {
+	case BL32_IMAGE_ID:
+		bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl32_entry();
+		break;
+
+	case BL33_IMAGE_ID:
+		/* BL33 expects to receive the primary CPU MPID (through r0) */
+		bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+		bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl33_entry();
+		break;
+
+	}
+
+	return err;
+}
diff --git a/plat/rpi3/rpi3_bl31_setup.c b/plat/rpi3/rpi3_bl31_setup.c
new file mode 100644
index 0000000..3913356
--- /dev/null
+++ b/plat/rpi3/rpi3_bl31_setup.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <xlat_mmu_helpers.h>
+#include <xlat_tables_defs.h>
+
+#include "rpi3_private.h"
+
+#define BL31_END	(uintptr_t)(&__BL31_END__)
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 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) != 0);
+
+	next_image_info = (type == NON_SECURE)
+			? &bl33_image_ep_info : &bl32_image_ep_info;
+
+	/* None of the images can have 0x0 as the entrypoint. */
+	if (next_image_info->pc) {
+		return next_image_info;
+	} else {
+		return NULL;
+	}
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before
+ * they are lost (potentially). This needs to be done before the MMU is
+ * initialized so that the memory layout can be used while creating page
+ * tables. BL2 has flushed this information to memory, so we are guaranteed
+ * to pick up good data.
+ ******************************************************************************/
+void bl31_early_platform_setup(void *from_bl2,
+			       void *plat_params_from_bl2)
+{
+	/* Initialize the console to provide early debug support */
+	console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ,
+		     PLAT_RPI3_UART_BAUDRATE);
+
+#if RESET_TO_BL31
+
+	/* 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 = rpi3_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 = plat_get_ns_image_entrypoint();
+
+	bl33_image_ep_info.spsr = rpi3_get_spsr_for_bl33_entry();
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#else /* RESET_TO_BL31 */
+
+	/*
+	 * In debug builds, we pass a special value in 'plat_params_from_bl2'
+	 * to verify platform parameters from BL2 to BL31.
+	 * In release builds, it's not used.
+	 */
+	assert(((uintptr_t)plat_params_from_bl2) == RPI3_BL31_PLAT_PARAM_VAL);
+
+	/*
+	 * Check params passed from BL2 should not be NULL,
+	 */
+	bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+
+	assert(params_from_bl2 != NULL);
+	assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+	assert(params_from_bl2->h.version >= VERSION_2);
+
+	bl_params_node_t *bl_params = params_from_bl2->head;
+
+	/*
+	 * Copy BL33 and BL32 (if present), entry point information.
+	 * They are stored in Secure RAM, in BL2's address space.
+	 */
+	while (bl_params) {
+		if (bl_params->image_id == BL32_IMAGE_ID) {
+			bl32_image_ep_info = *bl_params->ep_info;
+		}
+
+		if (bl_params->image_id == BL33_IMAGE_ID) {
+			bl33_image_ep_info = *bl_params->ep_info;
+		}
+
+		bl_params = bl_params->next_params_info;
+	}
+
+	if (bl33_image_ep_info.pc == 0) {
+		panic();
+	}
+
+#endif /* RESET_TO_BL31 */
+}
+
+void bl31_plat_arch_setup(void)
+{
+	rpi3_setup_page_tables(BL31_BASE, BL31_END - BL31_BASE,
+			       BL_CODE_BASE, BL_CODE_END,
+			       BL_RO_DATA_BASE, BL_RO_DATA_END
+#if USE_COHERENT_MEM
+			       , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
+#endif
+			      );
+
+	enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+#if RESET_TO_BL31
+	/*
+	 * Do initial security configuration to allow DRAM/device access
+	 * (if earlier BL has not already done so).
+	 */
+#endif /* RESET_TO_BL31 */
+
+	return;
+}
+
+void bl31_plat_runtime_setup(void)
+{
+	/* Initialize the runtime console */
+	console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ,
+		     PLAT_RPI3_UART_BAUDRATE);
+}
diff --git a/plat/rpi3/rpi3_common.c b/plat/rpi3/rpi3_common.c
new file mode 100644
index 0000000..97dce09
--- /dev/null
+++ b/plat/rpi3/rpi3_common.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <interrupt_mgmt.h>
+#include <platform_def.h>
+#include <xlat_tables_v2.h>
+
+#include "rpi3_hw.h"
+#include "rpi3_private.h"
+
+#define MAP_DEVICE0	MAP_REGION_FLAT(DEVICE0_BASE,			\
+					DEVICE0_SIZE,			\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SHARED_RAM	MAP_REGION_FLAT(SHARED_RAM_BASE,		\
+					SHARED_RAM_SIZE,		\
+					MT_DEVICE  | MT_RW | MT_SECURE)
+
+#define MAP_NS_DRAM0	MAP_REGION_FLAT(NS_DRAM0_BASE, NS_DRAM0_SIZE,	\
+					MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_FIP		MAP_REGION_FLAT(PLAT_RPI3_FIP_BASE,		\
+					PLAT_RPI3_FIP_MAX_SIZE,		\
+					MT_MEMORY | MT_RO | MT_NS)
+
+#define MAP_BL32_MEM	MAP_REGION_FLAT(BL32_MEM_BASE, BL32_MEM_SIZE,	\
+					MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
+ * Table of regions for various BL stages to map using the MMU.
+ */
+#ifdef IMAGE_BL1
+static const mmap_region_t plat_rpi3_mmap[] = {
+	MAP_SHARED_RAM,
+	MAP_DEVICE0,
+	MAP_FIP,
+	{0}
+};
+#endif
+
+#ifdef IMAGE_BL2
+static const mmap_region_t plat_rpi3_mmap[] = {
+	MAP_SHARED_RAM,
+	MAP_DEVICE0,
+	MAP_FIP,
+	MAP_NS_DRAM0,
+#ifdef BL32_BASE
+	MAP_BL32_MEM,
+#endif
+	{0}
+};
+#endif
+
+#ifdef IMAGE_BL31
+static const mmap_region_t plat_rpi3_mmap[] = {
+	MAP_SHARED_RAM,
+	MAP_DEVICE0,
+#ifdef BL32_BASE
+	MAP_BL32_MEM,
+#endif
+	{0}
+};
+#endif
+
+/*******************************************************************************
+ * Function that sets up the translation tables.
+ ******************************************************************************/
+void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size,
+			    uintptr_t code_start, uintptr_t code_limit,
+			    uintptr_t rodata_start, uintptr_t rodata_limit
+#if USE_COHERENT_MEM
+			    , uintptr_t coh_start, uintptr_t coh_limit
+#endif
+			    )
+{
+	/*
+	 * Map the Trusted SRAM with appropriate memory attributes.
+	 * Subsequent mappings will adjust the attributes for specific regions.
+	 */
+	VERBOSE("Trusted SRAM 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_MEMORY | MT_RW | MT_SECURE);
+
+	/* Re-map the code section */
+	VERBOSE("Code region: %p - %p\n",
+		(void *) code_start, (void *) code_limit);
+	mmap_add_region(code_start, code_start,
+			code_limit - code_start,
+			MT_CODE | MT_SECURE);
+
+	/* Re-map the read-only data section */
+	VERBOSE("Read-only data region: %p - %p\n",
+		(void *) rodata_start, (void *) rodata_limit);
+	mmap_add_region(rodata_start, rodata_start,
+			rodata_limit - rodata_start,
+			MT_RO_DATA | MT_SECURE);
+
+#if USE_COHERENT_MEM
+	/* Re-map the coherent memory region */
+	VERBOSE("Coherent region: %p - %p\n",
+		(void *) coh_start, (void *) coh_limit);
+	mmap_add_region(coh_start, coh_start,
+			coh_limit - coh_start,
+			MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+
+	mmap_add(plat_rpi3_mmap);
+
+	init_xlat_tables();
+}
+
+/*******************************************************************************
+ * Return entrypoint of BL33.
+ ******************************************************************************/
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+	return PRELOADED_BL33_BASE;
+#else
+	return PLAT_RPI3_NS_IMAGE_OFFSET;
+#endif
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t rpi3_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 rpi3_get_spsr_for_bl33_entry(void)
+{
+#if RPI3_BL33_IN_AARCH32
+	INFO("BL33 will boot in Non-secure AArch32 Hypervisor mode\n");
+	return SPSR_MODE32(MODE32_hyp, SPSR_T_ARM, SPSR_E_LITTLE,
+			   DISABLE_ALL_EXCEPTIONS);
+#else
+	return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+#endif
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+uint32_t plat_ic_get_pending_interrupt_type(void)
+{
+	return INTR_TYPE_INVAL;
+}
diff --git a/plat/rpi3/rpi3_hw.h b/plat/rpi3/rpi3_hw.h
new file mode 100644
index 0000000..70272e0
--- /dev/null
+++ b/plat/rpi3/rpi3_hw.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __RPI3_HW__
+#define __RPI3_HW__
+
+#include <utils_def.h>
+
+/*
+ * Peripherals
+ */
+
+#define RPI3_IO_BASE			ULL(0x3F000000)
+#define RPI3_IO_SIZE			ULL(0x01000000)
+
+/*
+ * Serial port (called 'Mini UART' in the BCM docucmentation).
+ */
+#define RPI3_IO_MINI_UART_OFFSET	ULL(0x00215040)
+#define RPI3_MINI_UART_BASE		(RPI3_IO_BASE + RPI3_IO_MINI_UART_OFFSET)
+#define RPI3_MINI_UART_CLK_IN_HZ	ULL(500000000)
+
+/*
+ * Power management, reset controller, watchdog.
+ */
+#define RPI3_IO_PM_OFFSET		ULL(0x00100000)
+#define RPI3_PM_BASE			(RPI3_IO_BASE + RPI3_IO_PM_OFFSET)
+/* Registers on top of RPI3_PM_BASE. */
+#define RPI3_PM_RSTC_OFFSET		ULL(0x0000001C)
+#define RPI3_PM_WDOG_OFFSET		ULL(0x00000024)
+/* Watchdog constants */
+#define RPI3_PM_PASSWORD		ULL(0x5A000000)
+#define RPI3_PM_RSTC_WRCFG_MASK		ULL(0x00000030)
+#define RPI3_PM_RSTC_WRCFG_FULL_RESET	ULL(0x00000020)
+
+/*
+ * Local interrupt controller
+ */
+#define RPI3_INTC_BASE_ADDRESS			ULL(0x40000000)
+/* Registers on top of RPI3_INTC_BASE_ADDRESS */
+#define RPI3_INTC_CONTROL_OFFSET		ULL(0x00000000)
+#define RPI3_INTC_PRESCALER_OFFSET		ULL(0x00000008)
+#define RPI3_INTC_MBOX_CONTROL_OFFSET		ULL(0x00000050)
+#define RPI3_INTC_MBOX_CONTROL_SLOT3_FIQ	ULL(0x00000080)
+#define RPI3_INTC_PENDING_FIQ_OFFSET		ULL(0x00000070)
+#define RPI3_INTC_PENDING_FIQ_MBOX3		ULL(0x00000080)
+
+#endif /* __RPI3_HW__ */
diff --git a/plat/rpi3/rpi3_image_load.c b/plat/rpi3/rpi3_image_load.c
new file mode 100644
index 0000000..fad9e4f
--- /dev/null
+++ b/plat/rpi3/rpi3_image_load.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <desc_image_load.h>
+#include <platform.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+	flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+	return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+	return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/rpi3/rpi3_io_storage.c b/plat/rpi3/rpi3_io_storage.c
new file mode 100644
index 0000000..7ac45ef
--- /dev/null
+++ b/plat/rpi3/rpi3_io_storage.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <firmware_image_package.h>
+#include <io_driver.h>
+#include <io_fip.h>
+#include <io_memmap.h>
+#include <platform_def.h>
+#include <string.h>
+
+/* Semihosting filenames */
+#define BL2_IMAGE_NAME			"bl2.bin"
+#define BL31_IMAGE_NAME			"bl31.bin"
+#define BL32_IMAGE_NAME			"bl32.bin"
+#define BL33_IMAGE_NAME			"bl33.bin"
+
+#if TRUSTED_BOARD_BOOT
+#define BL2_CERT_NAME			"bl2.crt"
+#define TRUSTED_KEY_CERT_NAME		"trusted_key.crt"
+#define BL31_KEY_CERT_NAME		"bl31_key.crt"
+#define BL32_KEY_CERT_NAME		"bl32_key.crt"
+#define BL33_KEY_CERT_NAME		"bl33_key.crt"
+#define BL31_CERT_NAME			"bl31.crt"
+#define BL32_CERT_NAME			"bl32.crt"
+#define BL33_CERT_NAME			"bl33.crt"
+#endif /* TRUSTED_BOARD_BOOT */
+
+/* IO devices */
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+static uintptr_t memmap_dev_handle;
+
+static const io_block_spec_t fip_block_spec = {
+	.offset = PLAT_RPI3_FIP_BASE,
+	.length = PLAT_RPI3_FIP_MAX_SIZE
+};
+
+static const io_uuid_spec_t bl2_uuid_spec = {
+	.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+	.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl32_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t bl2_cert_uuid_spec = {
+	.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT,
+};
+
+static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
+	.uuid = UUID_TRUSTED_KEY_CERT,
+};
+
+static const io_uuid_spec_t bl31_key_cert_uuid_spec = {
+	.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT,
+};
+
+static const io_uuid_spec_t bl32_key_cert_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_KEY_CERT,
+};
+
+static const io_uuid_spec_t bl33_key_cert_uuid_spec = {
+	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT,
+};
+
+static const io_uuid_spec_t bl31_cert_uuid_spec = {
+	.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT,
+};
+
+static const io_uuid_spec_t bl32_cert_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_CERT,
+};
+
+static const io_uuid_spec_t bl33_cert_uuid_spec = {
+	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_CERT,
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+static int open_fip(const uintptr_t spec);
+static int open_memmap(const uintptr_t spec);
+
+struct plat_io_policy {
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	int (*check)(const uintptr_t spec);
+};
+
+/* By default, load images from the FIP */
+static const struct plat_io_policy policies[] = {
+	[FIP_IMAGE_ID] = {
+		&memmap_dev_handle,
+		(uintptr_t)&fip_block_spec,
+		open_memmap
+	},
+	[BL2_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl2_uuid_spec,
+		open_fip
+	},
+	[BL31_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl31_uuid_spec,
+		open_fip
+	},
+	[BL32_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_uuid_spec,
+		open_fip
+	},
+	[BL33_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl33_uuid_spec,
+		open_fip
+	},
+#if TRUSTED_BOARD_BOOT
+	[BL2_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl2_cert_uuid_spec,
+		open_fip
+	},
+	[TRUSTED_KEY_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&trusted_key_cert_uuid_spec,
+		open_fip
+	},
+	[BL31_KEY_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl31_key_cert_uuid_spec,
+		open_fip
+	},
+	[BL32_KEY_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_key_cert_uuid_spec,
+		open_fip
+	},
+	[BL33_KEY_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl33_key_cert_uuid_spec,
+		open_fip
+	},
+	[BL31_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl31_cert_uuid_spec,
+		open_fip
+	},
+	[BL32_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_cert_uuid_spec,
+		open_fip
+	},
+	[BL33_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl33_cert_uuid_spec,
+		open_fip
+	},
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+static int open_fip(const uintptr_t spec)
+{
+	int result;
+	uintptr_t local_image_handle;
+
+	/* See if a Firmware Image Package is available */
+	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+	if (result == 0) {
+		result = io_open(fip_dev_handle, spec, &local_image_handle);
+		if (result == 0) {
+			VERBOSE("Using FIP\n");
+			io_close(local_image_handle);
+		}
+	}
+	return result;
+}
+
+static int open_memmap(const uintptr_t spec)
+{
+	int result;
+	uintptr_t local_image_handle;
+
+	result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
+	if (result == 0) {
+		result = io_open(memmap_dev_handle, spec, &local_image_handle);
+		if (result == 0) {
+			VERBOSE("Using Memmap\n");
+			io_close(local_image_handle);
+		}
+	}
+	return result;
+}
+
+void plat_rpi3_io_setup(void)
+{
+	int io_result;
+
+	io_result = register_io_dev_fip(&fip_dev_con);
+	assert(io_result == 0);
+
+	io_result = register_io_dev_memmap(&memmap_dev_con);
+	assert(io_result == 0);
+
+	/* Open connections to devices and cache the handles */
+	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+				&fip_dev_handle);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+				&memmap_dev_handle);
+	assert(io_result == 0);
+
+	/* Ignore improbable errors in release builds */
+	(void)io_result;
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	int result;
+	const struct plat_io_policy *policy;
+
+	assert(image_id < ARRAY_SIZE(policies));
+
+	policy = &policies[image_id];
+	result = policy->check(policy->image_spec);
+	if (result == 0) {
+		*image_spec = policy->image_spec;
+		*dev_handle = *(policy->dev_handle);
+	}
+
+	return result;
+}
diff --git a/plat/rpi3/rpi3_pm.c b/plat/rpi3/rpi3_pm.c
new file mode 100644
index 0000000..1d067fb
--- /dev/null
+++ b/plat/rpi3/rpi3_pm.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <console.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <platform.h>
+#include <psci.h>
+
+#include "rpi3_hw.h"
+
+/*
+ * The secure entry point to be used on warm reset.
+ */
+static uintptr_t secure_entrypoint;
+
+/* Make composite power state parameter till power level 0 */
+#if PSCI_EXTENDED_STATE_ID
+
+#define rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
+		(((lvl0_state) << PSTATE_ID_SHIFT) | \
+		 ((type) << PSTATE_TYPE_SHIFT))
+
+#else
+
+#define rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
+		(((lvl0_state) << PSTATE_ID_SHIFT) | \
+		 ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
+		 ((type) << PSTATE_TYPE_SHIFT))
+
+#endif /* PSCI_EXTENDED_STATE_ID */
+
+#define rpi3_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \
+		(((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \
+		 rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
+
+/*
+ *  The table storing the valid idle power states. Ensure that the
+ *  array entries are populated in ascending order of state-id to
+ *  enable us to use binary search during power state validation.
+ *  The table must be terminated by a NULL entry.
+ */
+static const unsigned int rpi3_pm_idle_states[] = {
+	/* State-id - 0x01 */
+	rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET,
+				MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
+	/* State-id - 0x02 */
+	rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF,
+				MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN),
+	/* State-id - 0x22 */
+	rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF,
+				MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN),
+	0,
+};
+
+/*******************************************************************************
+ * Platform handler called to check the validity of the power state
+ * parameter. The power state parameter has to be a composite power state.
+ ******************************************************************************/
+static int rpi3_validate_power_state(unsigned int power_state,
+				     psci_power_state_t *req_state)
+{
+	unsigned int state_id;
+	int i;
+
+	assert(req_state != 0);
+
+	/*
+	 *  Currently we are using a linear search for finding the matching
+	 *  entry in the idle power state array. This can be made a binary
+	 *  search if the number of entries justify the additional complexity.
+	 */
+	for (i = 0; rpi3_pm_idle_states[i] != 0; i++) {
+		if (power_state == rpi3_pm_idle_states[i]) {
+			break;
+		}
+	}
+
+	/* Return error if entry not found in the idle state array */
+	if (!rpi3_pm_idle_states[i]) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	i = 0;
+	state_id = psci_get_pstate_id(power_state);
+
+	/* Parse the State ID and populate the state info parameter */
+	while (state_id) {
+		req_state->pwr_domain_state[i++] = state_id &
+						PLAT_LOCAL_PSTATE_MASK;
+		state_id >>= PLAT_LOCAL_PSTATE_WIDTH;
+	}
+
+	return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Platform handler called when a CPU is about to enter standby.
+ ******************************************************************************/
+static void rpi3_cpu_standby(plat_local_state_t cpu_state)
+{
+	assert(cpu_state == PLAT_LOCAL_STATE_RET);
+
+	/*
+	 * Enter standby state.
+	 * dsb is good practice before using wfi to enter low power states
+	 */
+	dsb();
+	wfi();
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+static int rpi3_pwr_domain_on(u_register_t mpidr)
+{
+	int rc = PSCI_E_SUCCESS;
+	unsigned int pos = plat_core_pos_by_mpidr(mpidr);
+	uint64_t *hold_base = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE;
+
+	assert(pos < PLATFORM_CORE_COUNT);
+
+	hold_base[pos] = PLAT_RPI3_TM_HOLD_STATE_GO;
+
+	/* Make sure that the write has completed */
+	dsb();
+	isb();
+
+	sev();
+
+	return rc;
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+void rpi3_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+					PLAT_LOCAL_STATE_OFF);
+}
+
+/*******************************************************************************
+ * Platform handler to reboot the system
+ ******************************************************************************/
+#define RESET_TIMEOUT	10
+
+static void __dead2 rpi3_system_reset(void)
+{
+	/* Setup watchdog for reset */
+
+	static const uintptr_t base = RPI3_PM_BASE;
+	uint32_t rstc;
+
+	INFO("rpi3: PSCI System Reset: invoking watchdog reset\n");
+
+	console_flush();
+
+	rstc = mmio_read_32(base + RPI3_PM_RSTC_OFFSET);
+	rstc &= ~RPI3_PM_RSTC_WRCFG_MASK;
+	rstc |= RPI3_PM_RSTC_WRCFG_FULL_RESET;
+
+	dmbst();
+
+	/*
+	 * Watchdog timer = Timer clock / 16
+	 * Password (31:16) | Value (11:0)
+	 */
+	mmio_write_32(base + RPI3_PM_WDOG_OFFSET,
+		      RPI3_PM_PASSWORD | RESET_TIMEOUT);
+	mmio_write_32(base + RPI3_PM_RSTC_OFFSET,
+		      RPI3_PM_PASSWORD | rstc);
+
+	for (;;) {
+		wfi();
+	}
+}
+
+/*******************************************************************************
+ * Platform handlers and setup function.
+ ******************************************************************************/
+static const plat_psci_ops_t plat_rpi3_psci_pm_ops = {
+	.cpu_standby = rpi3_cpu_standby,
+	.pwr_domain_on = rpi3_pwr_domain_on,
+	.pwr_domain_on_finish = rpi3_pwr_domain_on_finish,
+	.system_reset = rpi3_system_reset,
+	.validate_power_state = rpi3_validate_power_state,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	uintptr_t *mailbox = (void *)PLAT_RPI3_TRUSTED_MAILBOX_BASE;
+
+	*mailbox = sec_entrypoint;
+	secure_entrypoint = (uintptr_t)sec_entrypoint;
+	*psci_ops = &plat_rpi3_psci_pm_ops;
+
+	return 0;
+}
diff --git a/plat/rpi3/rpi3_private.h b/plat/rpi3/rpi3_private.h
new file mode 100644
index 0000000..01c4055
--- /dev/null
+++ b/plat/rpi3/rpi3_private.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __RPI3_PRIVATE_H__
+#define __RPI3_PRIVATE_H__
+
+#include <sys/types.h>
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+
+/* Utility functions */
+void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size,
+			    uintptr_t code_start, uintptr_t code_limit,
+			    uintptr_t rodata_start, uintptr_t rodata_limit
+#if USE_COHERENT_MEM
+			    , uintptr_t coh_start, uintptr_t coh_limit
+#endif
+			    );
+
+/* Optional functions required in the Raspberry Pi 3 port */
+unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
+
+/* BL2 utility functions */
+uint32_t rpi3_get_spsr_for_bl32_entry(void);
+uint32_t rpi3_get_spsr_for_bl33_entry(void);
+
+/* IO storage utility functions */
+void plat_rpi3_io_setup(void);
+
+#endif /*__RPI3_PRIVATE_H__ */
diff --git a/plat/rpi3/rpi3_topology.c b/plat/rpi3/rpi3_topology.c
new file mode 100644
index 0000000..0e03ec3
--- /dev/null
+++ b/plat/rpi3/rpi3_topology.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <platform_def.h>
+#include <sys/types.h>
+
+#include "rpi3_private.h"
+
+/* The power domain tree descriptor */
+static unsigned char power_domain_tree_desc[] = {
+	/* Number of root nodes */
+	PLATFORM_CLUSTER_COUNT,
+	/* Number of children for the first node */
+	PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+/*******************************************************************************
+ * This function returns the ARM default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+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 >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+	cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+	if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+		return -1;
+	}
+
+	if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+		return -1;
+	}
+
+	return plat_rpi3_calc_core_pos(mpidr);
+}
diff --git a/plat/socionext/uniphier/platform.mk b/plat/socionext/uniphier/platform.mk
index c91abb6..3c78054 100644
--- a/plat/socionext/uniphier/platform.mk
+++ b/plat/socionext/uniphier/platform.mk
@@ -10,6 +10,7 @@
 override LOAD_IMAGE_V2		:= 1
 override USE_COHERENT_MEM	:= 1
 override USE_TBBR_DEFS		:= 1
+override ENABLE_SVE_FOR_NS	:= 0
 
 # Cortex-A53 revision r0p4-51rel0
 # needed for LD20, unneeded for LD11, PXs3 (no ACE)
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index ca87cc8..cb3b442 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -11,6 +11,9 @@
 SEPARATE_CODE_AND_RODATA := 1
 override RESET_TO_BL31 := 1
 
+# Do not enable SVE
+ENABLE_SVE_FOR_NS	:= 0
+
 ifdef ZYNQMP_ATF_MEM_BASE
     $(eval $(call add_define,ZYNQMP_ATF_MEM_BASE))
 
diff --git a/services/std_svc/sdei/sdei_main.c b/services/std_svc/sdei/sdei_main.c
index 2f08c8b..1969307 100644
--- a/services/std_svc/sdei/sdei_main.c
+++ b/services/std_svc/sdei/sdei_main.c
@@ -795,7 +795,7 @@
 		 */
 		ret = sdei_event_unregister(map->ev_num);
 		if ((ret == SDEI_EPEND) && (final_ret == 0))
-			final_ret = ret;
+			final_ret = SDEI_EDENY;
 	}
 
 	return final_ret;
@@ -817,7 +817,7 @@
 		 */
 		ret = sdei_event_unregister(map->ev_num);
 		if ((ret == SDEI_EPEND) && (final_ret == 0))
-			final_ret = ret;
+			final_ret = SDEI_EDENY;
 	}
 
 	if (final_ret != 0)
diff --git a/services/std_svc/spm/secure_partition_setup.c b/services/std_svc/spm/secure_partition_setup.c
index 6730160..c1f0edf 100644
--- a/services/std_svc/spm/secure_partition_setup.c
+++ b/services/std_svc/spm/secure_partition_setup.c
@@ -6,7 +6,6 @@
 
 #include <arch.h>
 #include <arch_helpers.h>
-#include <arm_spm_def.h>
 #include <assert.h>
 #include <common_def.h>
 #include <context.h>
@@ -22,12 +21,17 @@
 #include "spm_private.h"
 #include "spm_shim_private.h"
 
+/* Place translation tables by default along with the ones used by BL31. */
+#ifndef PLAT_SP_IMAGE_XLAT_SECTION_NAME
+#define PLAT_SP_IMAGE_XLAT_SECTION_NAME	"xlat_table"
+#endif
+
 /* Allocate and initialise the translation context for the secure partition. */
 REGISTER_XLAT_CONTEXT2(secure_partition,
 			PLAT_SP_IMAGE_MMAP_REGIONS,
 			PLAT_SP_IMAGE_MAX_XLAT_TABLES,
 			PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE,
-			EL1_EL0_REGIME);
+			EL1_EL0_REGIME, PLAT_SP_IMAGE_XLAT_SECTION_NAME);
 
 /* Export a handle on the secure partition translation context */
 xlat_ctx_t *secure_partition_xlat_ctx_handle = &secure_partition_xlat_ctx;
@@ -92,20 +96,20 @@
 
 	/* Get max granularity supported by the platform. */
 
-	u_register_t id_aa64prf0_el1 = read_id_aa64pfr0_el1();
+	u_register_t id_aa64mmfr0_el1 = read_id_aa64mmfr0_el1();
 
 	int tgran64_supported =
-		((id_aa64prf0_el1 >> ID_AA64MMFR0_EL1_TGRAN64_SHIFT) &
+		((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN64_SHIFT) &
 		 ID_AA64MMFR0_EL1_TGRAN64_MASK) ==
 		 ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED;
 
 	int tgran16_supported =
-		((id_aa64prf0_el1 >> ID_AA64MMFR0_EL1_TGRAN16_SHIFT) &
+		((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN16_SHIFT) &
 		 ID_AA64MMFR0_EL1_TGRAN16_MASK) ==
 		 ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED;
 
 	int tgran4_supported =
-		((id_aa64prf0_el1 >> ID_AA64MMFR0_EL1_TGRAN4_SHIFT) &
+		((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN4_SHIFT) &
 		 ID_AA64MMFR0_EL1_TGRAN4_MASK) ==
 		 ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED;
 
@@ -121,7 +125,7 @@
 	}
 
 	VERBOSE("Max translation granule supported: %lu KiB\n",
-		max_granule_size);
+		max_granule_size / 1024);
 
 	uintptr_t max_granule_size_mask = max_granule_size - 1;
 
diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c
index 1b40d81..ae71c1d 100644
--- a/services/std_svc/spm/spm_main.c
+++ b/services/std_svc/spm/spm_main.c
@@ -48,7 +48,7 @@
  * 2. Saves the current C runtime state (callee-saved registers) on the stack
  *    frame and saves a reference to this state.
  * 3. Calls el3_exit() so that the EL3 system and general purpose registers
- *    from the sp_ctx->cpu_ctx are used to enter the secure payload image.
+ *    from the sp_ctx->cpu_ctx are used to enter the secure partition image.
  ******************************************************************************/
 static uint64_t spm_synchronous_sp_entry(secure_partition_context_t *sp_ctx_ptr)
 {
@@ -75,7 +75,7 @@
 
 /*******************************************************************************
  * This function takes a Secure partition context pointer and:
- * 1. Saves the S-EL1 system register context tp sp_ctx->cpu_ctx.
+ * 1. Saves the S-EL1 system register context to sp_ctx->cpu_ctx.
  * 2. Restores the current C runtime state (callee saved registers) from the
  *    stack frame using the reference to this state saved in
  *    spm_secure_partition_enter().
@@ -101,7 +101,7 @@
  * This function passes control to the Secure Partition image (BL32) for the
  * first time on the primary cpu after a cold boot. It assumes that a valid
  * secure context has already been created by spm_setup() which can be directly
- * used. This function performs a synchronous entry into the Secure payload.
+ * used. This function performs a synchronous entry into the Secure partition.
  * The SP passes control back to this routine through a SMC.
  ******************************************************************************/
 int32_t spm_init(void)
@@ -126,21 +126,21 @@
 	secure_partition_setup();
 
 	/*
-	 * Arrange for an entry into the secure payload.
+	 * Arrange for an entry into the secure partition.
 	 */
 	sp_init_in_progress = 1;
 	rc = spm_synchronous_sp_entry(&sp_ctx);
 	assert(rc == 0);
 	sp_init_in_progress = 0;
-	VERBOSE("SP_MEM_ATTRIBUTES_SET_AARCH64 availability has been revoked\n");
+	VERBOSE("SP_MEMORY_ATTRIBUTES_SET_AARCH64 availability has been revoked\n");
 
 	return rc;
 }
 
 /*******************************************************************************
- * Given a secure payload entrypoint info pointer, entry point PC & pointer to
+ * Given a secure partition entrypoint info pointer, entry point PC & pointer to
  * a context data structure, this function will initialize the SPM context and
- * entry point info for the secure payload
+ * entry point info for the secure partition.
  ******************************************************************************/
 void spm_init_sp_ep_state(struct entry_point_info *sp_ep_info,
 			  uint64_t pc,
@@ -161,7 +161,7 @@
 	SET_PARAM_HEAD(sp_ep_info, PARAM_EP, VERSION_1, ep_attr);
 
 	sp_ep_info->pc = pc;
-	/* The SPM payload runs in S-EL0 */
+	/* The secure partition runs in S-EL0. */
 	sp_ep_info->spsr = SPSR_64(MODE_EL0,
 				   MODE_SP_EL0,
 				   DISABLE_ALL_EXCEPTIONS);
@@ -228,21 +228,21 @@
 {
 	mmap_attr_t tf_attr = 0;
 
-	unsigned int access = (attributes & SP_MEM_ATTR_ACCESS_MASK)
-			      >> SP_MEM_ATTR_ACCESS_SHIFT;
+	unsigned int access = (attributes & SP_MEMORY_ATTRIBUTES_ACCESS_MASK)
+			      >> SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT;
 
-	if (access == SP_MEM_ATTR_ACCESS_RW) {
+	if (access == SP_MEMORY_ATTRIBUTES_ACCESS_RW) {
 		tf_attr |= MT_RW | MT_USER;
-	} else if (access ==  SP_MEM_ATTR_ACCESS_RO) {
+	} else if (access ==  SP_MEMORY_ATTRIBUTES_ACCESS_RO) {
 		tf_attr |= MT_RO | MT_USER;
 	} else {
 		/* Other values are reserved. */
-		assert(access ==  SP_MEM_ATTR_ACCESS_NOACCESS);
+		assert(access ==  SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS);
 		/* The only requirement is that there's no access from EL0 */
 		tf_attr |= MT_RO | MT_PRIVILEGED;
 	}
 
-	if ((attributes & SP_MEM_ATTR_NON_EXEC) == 0) {
+	if ((attributes & SP_MEMORY_ATTRIBUTES_NON_EXEC) == 0) {
 		tf_attr |= MT_EXECUTE;
 	} else {
 		tf_attr |= MT_EXECUTE_NEVER;
@@ -263,20 +263,21 @@
 
 	if ((attr & MT_USER) == 0) {
 		/* No access from EL0. */
-		data_access = SP_MEM_ATTR_ACCESS_NOACCESS;
+		data_access = SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS;
 	} else {
 		if ((attr & MT_RW) != 0) {
 			assert(MT_TYPE(attr) != MT_DEVICE);
-			data_access = SP_MEM_ATTR_ACCESS_RW;
+			data_access = SP_MEMORY_ATTRIBUTES_ACCESS_RW;
 		} else {
-			data_access = SP_MEM_ATTR_ACCESS_RO;
+			data_access = SP_MEMORY_ATTRIBUTES_ACCESS_RO;
 		}
 	}
 
-	smc_attr |= (data_access & SP_MEM_ATTR_ACCESS_MASK) << SP_MEM_ATTR_ACCESS_SHIFT;
+	smc_attr |= (data_access & SP_MEMORY_ATTRIBUTES_ACCESS_MASK)
+		    << SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT;
 
 	if (attr & MT_EXECUTE_NEVER) {
-		smc_attr |= SP_MEM_ATTR_NON_EXEC;
+		smc_attr |= SP_MEMORY_ATTRIBUTES_NON_EXEC;
 	}
 
 	return smc_attr;
@@ -349,7 +350,7 @@
 
 		switch (smc_fid) {
 
-		case  SPM_VERSION_AARCH32:
+		case SPM_VERSION_AARCH32:
 			SMC_RET1(handle, SPM_VERSION_COMPILED);
 
 		case SP_EVENT_COMPLETE_AARCH64:
@@ -387,20 +388,20 @@
 			/* Return to normal world */
 			SMC_RET1(ns_cpu_context, x1);
 
-		case SP_MEM_ATTRIBUTES_GET_AARCH64:
-			INFO("Received SP_MEM_ATTRIBUTES_GET_AARCH64 SMC\n");
+		case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
+			INFO("Received SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n");
 
 			if (!sp_init_in_progress) {
-				WARN("SP_MEM_ATTRIBUTES_GET_AARCH64 is available at boot time only\n");
+				WARN("SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n");
 				SMC_RET1(handle, SPM_NOT_SUPPORTED);
 			}
 			SMC_RET1(handle, spm_memory_attributes_get_smc_handler(x1));
 
-		case SP_MEM_ATTRIBUTES_SET_AARCH64:
-			INFO("Received SP_MEM_ATTRIBUTES_SET_AARCH64 SMC\n");
+		case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
+			INFO("Received SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n");
 
 			if (!sp_init_in_progress) {
-				WARN("SP_MEM_ATTRIBUTES_SET_AARCH64 is available at boot time only\n");
+				WARN("SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n");
 				SMC_RET1(handle, SPM_NOT_SUPPORTED);
 			}
 			SMC_RET1(handle, spm_memory_attributes_set_smc_handler(x1, x2, x3));
@@ -413,12 +414,31 @@
 
 		switch (smc_fid) {
 
-		case  SP_VERSION_AARCH64:
-		case  SP_VERSION_AARCH32:
+		case SP_VERSION_AARCH64:
+		case SP_VERSION_AARCH32:
 			SMC_RET1(handle, SP_VERSION_COMPILED);
 
-		case SP_COMMUNICATE_AARCH32:
-		case SP_COMMUNICATE_AARCH64:
+		case MM_COMMUNICATE_AARCH32:
+		case MM_COMMUNICATE_AARCH64:
+		{
+			uint64_t mm_cookie = x1;
+			uint64_t comm_buffer_address = x2;
+			uint64_t comm_size_address = x3;
+
+			/* Cookie. Reserved for future use. It must be zero. */
+			if (mm_cookie != 0) {
+				ERROR("MM_COMMUNICATE: cookie is not zero\n");
+				SMC_RET1(handle, SPM_INVALID_PARAMETER);
+			}
+
+			if (comm_buffer_address == 0) {
+				ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n");
+				SMC_RET1(handle, SPM_INVALID_PARAMETER);
+			}
+
+			if (comm_size_address != 0) {
+				VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n");
+			}
 
 			/* Save the Normal world context */
 			cm_el1_sysregs_context_save(NON_SECURE);
@@ -431,15 +451,12 @@
 			cm_el1_sysregs_context_restore(SECURE);
 			cm_set_next_eret_context(SECURE);
 
-			if (x2 != 0) {
-				VERBOSE("SP_COMMUNICATE_AARCH32/64: X2 is not 0 as recommended.");
-			}
-
-			SMC_RET4(&sp_ctx.cpu_ctx,
-				 smc_fid, x2, x3, plat_my_core_pos());
+			SMC_RET4(&sp_ctx.cpu_ctx, smc_fid, comm_buffer_address,
+				 comm_size_address, plat_my_core_pos());
+		}
 
-		case SP_MEM_ATTRIBUTES_GET_AARCH64:
-		case SP_MEM_ATTRIBUTES_SET_AARCH64:
+		case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
+		case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
 			/* SMC interfaces reserved for secure callers. */
 			SMC_RET1(handle, SPM_NOT_SUPPORTED);