Merge pull request #1207 from hzhuang1/isp_clk

hikey960: set isp clks as unsecure mode
diff --git a/Makefile b/Makefile
index fe75798..1058b39 100644
--- a/Makefile
+++ b/Makefile
@@ -125,6 +125,7 @@
 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
@@ -159,10 +160,19 @@
 				-ffreestanding -fno-builtin -Wall -std=gnu99	\
 				-Os -ffunction-sections -fdata-sections
 
+GCC_V_OUTPUT		:=	$(shell $(CC) -v 2>&1)
+PIE_FOUND		:=	$(findstring --enable-default-pie,${GCC_V_OUTPUT})
+
+ifeq ($(PIE_FOUND),1)
+TF_CFLAGS		+=	-fno-PIE
+endif
+
 TF_LDFLAGS		+=	--fatal-warnings -O1
 TF_LDFLAGS		+=	--gc-sections
 TF_LDFLAGS		+=	$(TF_LDFLAGS_$(ARCH))
 
+DTC_FLAGS		+=	-I dts -O dtb
+
 ################################################################################
 # Common sources and include directories
 ################################################################################
@@ -451,6 +461,10 @@
 endif
 endif
 
+ifdef FDT_SOURCES
+NEED_FDT := yes
+endif
+
 ################################################################################
 # Build options checks
 ################################################################################
@@ -468,6 +482,7 @@
 $(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))
@@ -508,6 +523,7 @@
 $(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))
@@ -549,7 +565,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
@@ -602,6 +618,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")
@@ -729,6 +752,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 ebd0e71..fdcc931 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -54,6 +54,10 @@
 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/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S
index 9325973..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
@@ -190,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
@@ -205,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/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/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/common/tf_printf.c b/common/tf_printf.c
index f73842a..d403983 100644
--- a/common/tf_printf.c
+++ b/common/tf_printf.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -31,7 +31,8 @@
 		putchar(*str++);
 }
 
-static void unsigned_num_print(unsigned long long int unum, unsigned int radix)
+static void unsigned_num_print(unsigned long long int unum, unsigned int radix,
+			       char padc, int padn)
 {
 	/* Just need enough space to store 64 bit decimal integer */
 	unsigned char num_buf[20];
@@ -45,6 +46,12 @@
 			num_buf[i++] = 'a' + (rem - 0xa);
 	} while (unum /= radix);
 
+	if (padn > 0) {
+		while (i < padn--) {
+			putchar(padc);
+		}
+	}
+
 	while (--i >= 0)
 		putchar(num_buf[i]);
 }
@@ -63,6 +70,9 @@
  * %ll - long long int (64-bit on AArch64)
  * %z - size_t sized integer formats (64 bit on AArch64)
  *
+ * The following padding specifiers are supported by this print
+ * %0NN - Left-pad the number with 0s (NN is a decimal number)
+ *
  * The print exits on all other formats specifiers other than valid
  * combinations of the above specifiers.
  *******************************************************************/
@@ -72,9 +82,12 @@
 	long long int num;
 	unsigned long long int unum;
 	char *str;
+	char padc = 0; /* Padding character */
+	int padn; /* Number of characters to pad */
 
 	while (*fmt) {
 		l_count = 0;
+		padn = 0;
 
 		if (*fmt == '%') {
 			fmt++;
@@ -87,10 +100,11 @@
 				if (num < 0) {
 					putchar('-');
 					unum = (unsigned long long int)-num;
+					padn--;
 				} else
 					unum = (unsigned long long int)num;
 
-				unsigned_num_print(unum, 10);
+				unsigned_num_print(unum, 10, padc, padn);
 				break;
 			case 's':
 				str = va_arg(args, char *);
@@ -98,14 +112,16 @@
 				break;
 			case 'p':
 				unum = (uintptr_t)va_arg(args, void *);
-				if (unum)
+				if (unum) {
 					tf_string_print("0x");
+					padn -= 2;
+				}
 
-				unsigned_num_print(unum, 16);
+				unsigned_num_print(unum, 16, padc, padn);
 				break;
 			case 'x':
 				unum = get_unum_va_args(args, l_count);
-				unsigned_num_print(unum, 16);
+				unsigned_num_print(unum, 16, padc, padn);
 				break;
 			case 'z':
 				if (sizeof(size_t) == 8)
@@ -119,8 +135,21 @@
 				goto loop;
 			case 'u':
 				unum = get_unum_va_args(args, l_count);
-				unsigned_num_print(unum, 10);
+				unsigned_num_print(unum, 10, padc, padn);
 				break;
+			case '0':
+				padc = '0';
+				padn = 0;
+				fmt++;
+
+				while (1) {
+					char ch = *fmt;
+					if (ch < '0' || ch > '9') {
+						goto loop;
+					}
+					padn = (padn * 10) + (ch - '0');
+					fmt++;
+				}
 			default:
 				/* Exit on any other format specifier */
 				return;
diff --git a/docs/diagrams/secure_sw_stack_sp.png b/docs/diagrams/secure_sw_stack_sp.png
new file mode 100644
index 0000000..5cb2ca7
--- /dev/null
+++ b/docs/diagrams/secure_sw_stack_sp.png
Binary files differ
diff --git a/docs/diagrams/secure_sw_stack_tos.png b/docs/diagrams/secure_sw_stack_tos.png
new file mode 100644
index 0000000..1f2d555
--- /dev/null
+++ b/docs/diagrams/secure_sw_stack_tos.png
Binary files differ
diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst
index 405964d..3cb004a 100644
--- a/docs/firmware-design.rst
+++ b/docs/firmware-design.rst
@@ -1868,9 +1868,11 @@
 
 The FIP layout consists of a table of contents (ToC) followed by payload data.
 The ToC itself has a header followed by one or more table entries. The ToC is
-terminated by an end marker entry. All ToC entries describe some payload data
-that has been appended to the end of the binary package. With the information
-provided in the ToC entry the corresponding payload data can be retrieved.
+terminated by an end marker entry, and since the size of the ToC is 0 bytes,
+the offset equals the total size of the FIP file. All ToC entries describe some
+payload data that has been appended to the end of the binary package. With the
+information provided in the ToC entry the corresponding payload data can be
+retrieved.
 
 ::
 
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/plat/socionext-uniphier.rst b/docs/plat/socionext-uniphier.rst
index fb6ebe5..2c652ac 100644
--- a/docs/plat/socionext-uniphier.rst
+++ b/docs/plat/socionext-uniphier.rst
@@ -1,11 +1,12 @@
 ARM Trusted Firmware for Socionext UniPhier SoCs
 ================================================
 
+
 Socionext UniPhier ARMv8-A SoCs use ARM Trusted Firmware as the secure world
 firmware, supporting BL1, BL2, and BL31.
 
 UniPhier SoC family implements its internal boot ROM, so BL1 is used as pseudo
-ROM (i.e. runs in RAM). The internal boot ROM loads 64KB `1`_ image from a
+ROM (i.e. runs in RAM). The internal boot ROM loads 64KB [1]_ image from a
 non-volatile storage to the on-chip SRAM. Unfortunately, BL1 does not fit in
 the 64KB limit if `Trusted Board Boot`_ (TBB) is enabled. To solve this problem,
 Socionext provides a first stage loader called `UniPhier BL`_. This loader runs
@@ -23,35 +24,33 @@
 fits in the 64KB limit. The concatenated image is loaded by the boot ROM
 (and verified if the chip fuses are blown).
 
-::
-
-     to the lowest common denominator.
 
 Boot Flow
 ---------
 
-#. The Boot ROM
+1. The Boot ROM
 
-This is hard-wired ROM, so never corrupted. It loads the UniPhier BL (with
-compressed-BL1 appended) into the on-chip SRAM. If the SoC fuses are blown,
-the image is verified by the SoC's own method.
+   This is hard-wired ROM, so never corrupted. It loads the UniPhier BL (with
+   compressed-BL1 appended) into the on-chip SRAM. If the SoC fuses are blown,
+   the image is verified by the SoC's own method.
 
-#. UniPhier BL
+2. UniPhier BL
 
-This runs in the on-chip SRAM. After the minimum SoC initialization and DRAM
-setup, it decompresses the appended BL1 image into the DRAM, then jumps to
-the BL1 entry.
+   This runs in the on-chip SRAM. After the minimum SoC initialization and DRAM
+   setup, it decompresses the appended BL1 image into the DRAM, then jumps to
+   the BL1 entry.
 
-#. BL1
+3. BL1
 
-This runs in the DRAM. It extracts BL2 from FIP (Firmware Image Package).
-If TBB is enabled, the BL2 is authenticated by the standard mechanism of ARM
-Trusted Firmware.
+   This runs in the DRAM. It extracts BL2 from FIP (Firmware Image Package).
+   If TBB is enabled, the BL2 is authenticated by the standard mechanism of ARM
+   Trusted Firmware.
 
-#. BL2, BL31, and more
+4. BL2, BL31, and more
 
-They all run in the DRAM, and are authenticated by the standard mechanism if
-TBB is enabled. See `Firmware Design`_ for details.
+   They all run in the DRAM, and are authenticated by the standard mechanism if
+   TBB is enabled. See `Firmware Design`_ for details.
+
 
 Basic Build
 -----------
@@ -63,59 +62,52 @@
 SoCs. The U-Boot image (``u-boot.bin``) must be built in advance. For the build
 procedure of U-Boot, refer to the document in the `U-Boot`_ project.
 
-To build minimum functionality for UniPhier (without TBB):
-
-::
+To build minimum functionality for UniPhier (without TBB)::
 
     make CROSS_COMPILE=<gcc-prefix> PLAT=uniphier BL33=<path-to-BL33> bl1_gzip fip
 
 Output images:
 
+- ``bl1.bin.gzip``
+- ``fip.bin``
+
--  ``bl1.bin.gzip``
--  ``fip.bin``
 
 Optional features
 -----------------
 
--  Trusted Board Boot
+- Trusted Board Boot
 
-`mbed TLS`_ is needed as the cryptographic and image parser modules.
-Refer to the `User Guide`_ for the appropriate version of mbed TLS.
+  `mbed TLS`_ is needed as the cryptographic and image parser modules.
+  Refer to the `User Guide`_ for the appropriate version of mbed TLS.
 
-To enable TBB, add the following options to the build command:
-
-::
+  To enable TBB, add the following options to the build command::
 
       TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR=<path-to-mbedtls>
 
--  System Control Processor (SCP)
+- System Control Processor (SCP)
 
-If desired, FIP can include an SCP BL2 image. If BL2 finds an SCP BL2 image
-in FIP, BL2 loads it into DRAM and kicks the SCP. Most of UniPhier boards
-still work without SCP, but SCP provides better power management support.
+  If desired, FIP can include an SCP BL2 image. If BL2 finds an SCP BL2 image
+  in FIP, BL2 loads it into DRAM and kicks the SCP. Most of UniPhier boards
+  still work without SCP, but SCP provides better power management support.
 
-To include SCP\_BL2, add the following option to the build command:
-
-::
+  To include SCP BL2, add the following option to the build command::
 
       SCP_BL2=<path-to-SCP>
 
--  BL32 (Secure Payload)
+- BL32 (Secure Payload)
 
-To enable BL32, add the following option to the build command:
-
-::
+  To enable BL32, add the following options to the build command::
 
       SPD=<spd> BL32=<path-to-BL32>
 
-If you use TSP for BL32, ``BL32=<path-to-BL32>`` is not required. Just add the
-following:
-
-::
+  If you use TSP for BL32, ``BL32=<path-to-BL32>`` is not required. Just add the
+  following::
 
       SPD=tspd
 
-.. _1: Some%20SoCs%20can%20load%2080KB,%20but%20the%20software%20implementation%20must%20be%20aligned
+
+.. [1] Some SoCs can load 80KB, but the software implementation must be aligned
+   to the lowest common denominator.
 .. _Trusted Board Boot: ../trusted-board-boot.rst
 .. _UniPhier BL: https://github.com/uniphier/uniphier-bl
 .. _Firmware Design: ../firmware-design.rst
diff --git a/docs/secure-partition-manager-design.rst b/docs/secure-partition-manager-design.rst
new file mode 100644
index 0000000..05d4e8b
--- /dev/null
+++ b/docs/secure-partition-manager-design.rst
@@ -0,0 +1,825 @@
+*******************************
+Secure Partition Manager Design
+*******************************
+
+.. section-numbering::
+    :suffix: .
+
+.. contents::
+
+Background
+==========
+
+In some market segments that primarily deal with client-side devices like mobile
+phones, tablets, STBs and embedded devices, a Trusted OS instantiates trusted
+applications to provide security services like DRM, secure payment and
+authentication. The Global Platform TEE Client API specification defines the API
+used by Non-secure world applications to access these services. A Trusted OS
+fulfils the requirements of a security service as described above.
+
+Management services are typically implemented at the highest level of privilege
+in the system (i.e. EL3 in Arm Trusted Firmware). The service requirements are
+fulfilled by the execution environment provided by Arm Trusted Firmware.
+
+The following diagram illustrates the corresponding software stack:
+
+|Image 1|
+
+In other market segments that primarily deal with server-side devices (e.g. data
+centres and enterprise servers) the secure software stack typically does not
+include a Global Platform Trusted OS. Security functions are accessed through
+other interfaces (e.g. ACPI TCG TPM interface, UEFI runtime variable service).
+
+Placement of management and security functions with diverse requirements in a
+privileged Exception Level (i.e. EL3 or S-EL1) makes security auditing of
+firmware more difficult and does not allow isolation of unrelated services from
+each other either.
+
+Introduction
+============
+
+A **Secure Partition** is a software execution environment instantiated in
+S-EL0 that can be used to implement simple management and security services.
+Since S-EL0 is an unprivileged Exception Level, a Secure Partition relies on
+privileged firmware (i.e. Arm Trusted Firmware) to be granted access to system
+and processor resources. Essentially, it is a software sandbox in the Secure
+world that runs under the control of privileged software, provides one or more
+services and accesses the following system resources:
+
+- Memory and device regions in the system address map.
+
+- PE system registers.
+
+- A range of synchronous exceptions (e.g. SMC function identifiers).
+
+Note that currently the Arm Trusted Firmware only supports handling one Secure
+Partition.
+
+A Secure Partition enables Arm Trusted Firmware to implement only the essential
+secure services in EL3 and instantiate the rest in a partition in S-EL0.
+Furthermore, multiple Secure Partitions can be used to isolate unrelated
+services from each other.
+
+The following diagram illustrates the place of a Secure Partition in a typical
+ARMv8-A software stack. A single or multiple Secure Partitions provide secure
+services to software components in the Non-secure world and other Secure
+Partitions.
+
+|Image 2|
+
+The Arm Trusted Firmware build system is responsible for including the Secure
+Partition image in the FIP. During boot, BL2 includes support to authenticate
+and load the Secure Partition image. A BL31 component called **Secure Partition
+Manager (SPM)** is responsible for managing the partition. This is semantically
+similar to a hypervisor managing a virtual machine.
+
+The SPM is responsible for the following actions during boot:
+
+- Allocate resources requested by the Secure Partition.
+
+- Perform architectural and system setup required by the Secure Partition to
+  fulfil a service request.
+
+- Implement a standard interface that is used for initialising a Secure
+  Partition.
+
+The SPM is responsible for the following actions during runtime:
+
+- Implement a standard interface that is used by a Secure Partition to fulfil
+  service requests.
+
+- Implement a standard interface that is used by the Non-secure world for
+  accessing the services exported by a Secure Partition. A service can be
+  invoked through a SMC.
+
+Alternatively, a partition can be viewed as a thread of execution running under
+the control of the SPM. Hence common programming concepts described below are
+applicable to a partition.
+
+Description
+===========
+
+The previous section introduced some general aspects of the software
+architecture of a Secure Partition. This section describes the specific choices
+made in the current implementation of this software architecture. Subsequent
+revisions of the implementation will include a richer set of features that
+enable a more flexible architecture.
+
+Building Arm Trusted Firmware with Secure Partition support
+-----------------------------------------------------------
+
+SPM is supported on the Arm FVP exclusively at the moment. The current
+implementation supports inclusion of only a single Secure Partition in which a
+service always runs to completion (e.g. the requested services cannot be
+preempted to give control back to the Normal world).
+
+It is not currently possible for BL31 to integrate SPM support and a Secure
+Payload Dispatcher (SPD) at the same time; they are mutually exclusive. In the
+SPM bootflow, a Secure Partition image executing at S-EL0 replaces the Secure
+Payload image executing at S-EL1 (e.g. a Trusted OS). Both are referred to as
+BL32.
+
+A working prototype of a SP has been implemented by re-purposing the EDK2 code
+and tools, leveraging the concept of the *Standalone Management Mode (MM)* in
+the UEFI specification (see the PI v1.6 Volume 4: Management Mode Core
+Interface). This will be referred to as the *Standalone MM Secure Partition* in
+the rest of this document.
+
+To enable SPM support in the TF, the source code must be compiled with the build
+flag ``ENABLE_SPM=1``. On Arm platforms the build option ``ARM_BL31_IN_DRAM``
+can be used to select the location of BL31, both SRAM and DRAM are supported.
+Also, the location of the binary that contains the BL32 image
+(``BL32=path/to/image.bin``) must be specified.
+
+First, build the Standalone MM Secure Partition. To build it, refer to the
+`instructions in the EDK2 repository`_.
+
+Then build TF with SPM support and include the Standalone MM Secure Partition
+image in the FIP:
+
+::
+
+    BL32=path/to/standalone/mm/sp BL33=path/to/bl33.bin \
+    make PLAT=fvp ENABLE_SPM=1 fip all
+
+Describing Secure Partition resources
+-------------------------------------
+
+Arm Trusted Firmware exports a porting interface that enables a platform to
+specify the system resources required by the Secure Partition. Some instructions
+are given below. However, this interface is under development and it may change
+as new features are implemented.
+
+- A Secure Partition is considered a BL32 image, so the same defines that apply
+  to BL32 images apply to a Secure Partition: ``BL32_BASE`` and ``BL32_LIMIT``.
+
+- The following defines are needed to allocate space for the translation tables
+  used by the Secure Partition: ``PLAT_SP_IMAGE_MMAP_REGIONS`` and
+  ``PLAT_SP_IMAGE_MAX_XLAT_TABLES``.
+
+- The functions ``plat_get_secure_partition_mmap()`` and
+  ``plat_get_secure_partition_boot_info()`` have to be implemented. The file
+  ``plat/arm/board/fvp/fvp_common.c`` can be used as an example. It uses the
+  defines in ``include/plat/arm/common/arm_spm_def.h``.
+
+  - ``plat_get_secure_partition_mmap()`` returns an array of mmap regions that
+    describe the memory regions that the SPM needs to allocate for a Secure
+    Partition.
+
+  - ``plat_get_secure_partition_boot_info()`` returns a
+    ``secure_partition_boot_info_t`` struct that is populated by the platform
+    with information about the memory map of the Secure Partition.
+
+For an example of all the changes in context, you may refer to commit
+``e29efeb1b4``, in which the port for FVP was introduced.
+
+Accessing Secure Partition services
+-----------------------------------
+
+The `SMC Calling Convention`_ (*ARM DEN 0028B*) describes SMCs as a conduit for
+accessing services implemented in the Secure world. The ``MM_COMMUNICATE``
+interface defined in the `Management Mode Interface Specification`_ (*ARM DEN
+0060A*) is used to invoke a Secure Partition service as a Fast Call.
+
+The mechanism used to identify a service within the partition depends on the
+service implementation. It is assumed that the caller of the service will be
+able to discover this mechanism through standard platform discovery mechanisms
+like ACPI and Device Trees. For example, *Volume 4: Platform Initialisation
+Specification v1.6. Management Mode Core Interface* specifies that a GUID is
+used to identify a management mode service. A client populates the GUID in the
+``EFI_MM_COMMUNICATE_HEADER``. The header is populated in the communication
+buffer shared with the Secure Partition.
+
+A Fast Call appears to be atomic from the perspective of the caller and returns
+when the requested operation has completed. A service invoked through the
+``MM_COMMUNICATE`` SMC will run to completion in the partition on a given CPU.
+The SPM is responsible for guaranteeing this behaviour. This means that there
+can only be a single outstanding Fast Call in a partition on a given CPU.
+
+Exchanging data with the Secure Partition
+-----------------------------------------
+
+The exchange of data between the Non-secure world and the partition takes place
+through a shared memory region. The location of data in the shared memory area
+is passed as a parameter to the ``MM_COMMUNICATE`` SMC. The shared memory area
+is statically allocated by the SPM and is expected to be either implicitly known
+to the Non-secure world or discovered through a platform discovery mechanism
+e.g. ACPI table or device tree. It is possible for the Non-secure world to
+exchange data with a partition only if it has been populated in this shared
+memory area. The shared memory area is implemented as per the guidelines
+specified in Section 3.2.3 of the `Management Mode Interface Specification`_
+(*ARM DEN 0060A*).
+
+The format of data structures used to encapsulate data in the shared memory is
+agreed between the Non-secure world and the Secure Partition. For example, in
+the `Management Mode Interface specification`_ (*ARM DEN 0060A*), Section 4
+describes that the communication buffer shared between the Non-secure world and
+the Management Mode (MM) in the Secure world must be of the type
+``EFI_MM_COMMUNICATE_HEADER``. This data structure is defined in *Volume 4:
+Platform Initialisation Specification v1.6. Management Mode Core Interface*.
+Any caller of a MM service will have to use the ``EFI_MM_COMMUNICATE_HEADER``
+data structure.
+
+Runtime model of the Secure Partition
+=====================================
+
+This section describes how the Secure Partition interfaces with the SPM.
+
+Interface with SPM
+------------------
+
+In order to instantiate one or more secure services in the Secure Partition in
+S-EL0, the SPM should define the following types of interfaces:
+
+- Interfaces that enable access to privileged operations from S-EL0. These
+  operations typically require access to system resources that are either shared
+  amongst multiple software components in the Secure world or cannot be directly
+  accessed from an unprivileged Exception Level.
+
+- Interfaces that establish the control path between the SPM and the Secure
+  Partition.
+
+This section describes the APIs currently exported by the SPM that enable a
+Secure Partition to initialise itself and export its services in S-EL0. These
+interfaces are not accessible from the Non-secure world.
+
+Conduit
+^^^^^^^
+
+The `SMC Calling Convention`_ (*ARM DEN 0028B*) specification describes the SMC
+and HVC conduits for accessing firmware services and their availability
+depending on the implemented Exception levels. In S-EL0, the Supervisor Call
+exception (SVC) is the only architectural mechanism available for unprivileged
+software to make a request for an operation implemented in privileged software.
+Hence, the SVC conduit must be used by the Secure Partition to access interfaces
+implemented by the SPM.
+
+A SVC causes an exception to be taken to S-EL1. Arm Trusted Firmware assumes
+ownership of S-EL1 and installs a simple exception vector table in S-EL1 that
+relays a SVC request from a Secure Partition as a SMC request to the SPM in EL3.
+Upon servicing the SMC request, Arm Trusted Firmware returns control directly to
+S-EL0 through an ERET instruction.
+
+Calling conventions
+^^^^^^^^^^^^^^^^^^^
+
+The `SMC Calling Convention`_ (*ARM DEN 0028B*) specification describes the
+32-bit and 64-bit calling conventions for the SMC and HVC conduits. The SVC
+conduit introduces the concept of SVC32 and SVC64 calling conventions. The SVC32
+and SVC64 calling conventions are equivalent to the 32-bit (SMC32) and the
+64-bit (SMC64) calling conventions respectively.
+
+Communication initiated by SPM
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A service request is initiated from the SPM through an exception return
+instruction (ERET) to S-EL0. Later, the Secure Partition issues an SVC
+instruction to signal completion of the request. Some example use cases are
+given below:
+
+- A request to initialise the Secure Partition during system boot.
+
+- A request to handle a runtime service request.
+
+Communication initiated by Secure Partition
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A request is initiated from the Secure Partition by executing a SVC instruction.
+An ERET instruction is used by Arm Trusted Firmware to return to S-EL0 with the
+result of the request.
+
+For instance, a request to perform privileged operations on behalf of a
+partition (e.g.  management of memory attributes in the translation tables for
+the Secure EL1&0 translation regime).
+
+Interfaces
+^^^^^^^^^^
+
+The current implementation reserves function IDs for Fast Calls in the Standard
+Secure Service calls range (see `SMC Calling Convention`_ (*ARM DEN 0028B*)
+specification) for each API exported by the SPM. This section defines the
+function prototypes for each function ID. The function IDs specify whether one
+or both of the SVC32 and SVC64 calling conventions can be used to invoke the
+corresponding interface.
+
+Secure Partition Event Management
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The Secure Partition provides an Event Management interface that is used by the
+SPM to delegate service requests to the Secure Partition. The interface also
+allows the Secure Partition to:
+
+- Register with the SPM a service that it provides.
+- Indicate completion of a service request delagated by the SPM
+
+Miscellaneous interfaces
+------------------------
+
+``SPM_VERSION_AARCH32``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+- Description
+
+  Returns the version of the interface exported by SPM.
+
+- Parameters
+
+  - **uint32** - Function ID
+
+    - SVC32 Version: **0x84000060**
+
+- Return parameters
+
+  - **int32** - Status
+
+    On success, the format of the value is as follows:
+
+    - Bit [31]: Must be 0
+    - Bits [30:16]: Major Version. Must be 0 for this revision of the SPM
+      interface.
+    - Bits [15:0]: Minor Version. Must be 1 for this revision of the SPM
+      interface.
+
+    On error, the format of the value is as follows:
+
+    - ``NOT_SUPPORTED``: SPM interface is not supported or not available for the
+      client.
+
+- Usage
+
+  This function returns the version of the Secure Partition Manager
+  implementation. The major version is 0 and the minor version is 1. The version
+  number is a 31-bit unsigned integer, with the upper 15 bits denoting the major
+  revision, and the lower 16 bits denoting the minor revision. The following
+  rules apply to the version numbering:
+
+  - Different major revision values indicate possibly incompatible functions.
+
+  - For two revisions, A and B, for which the major revision values are
+    identical, if the minor revision value of revision B is greater than the
+    minor revision value of revision A, then every function in revision A must
+    work in a compatible way with revision B. However, it is possible for
+    revision B to have a higher function count than revision A.
+
+- Implementation responsibilities
+
+  If this function returns a valid version number, all the functions that are
+  described subsequently must be implemented, unless it is explicitly stated
+  that a function is optional.
+
+See `Error Codes`_ for integer values that are associated with each return
+code.
+
+Secure Partition Initialisation
+-------------------------------
+
+The SPM is responsible for initialising the architectural execution context to
+enable initialisation of a service in S-EL0. The responsibilities of the SPM are
+listed below. At the end of initialisation, the partition issues a
+``SP_EVENT_COMPLETE_AARCH64`` call (described later) to signal readiness for
+handling requests for services implemented by the Secure Partition. The
+initialisation event is executed as a Fast Call.
+
+Entry point invocation
+^^^^^^^^^^^^^^^^^^^^^^
+
+The entry point for service requests that should be handled as Fast Calls is
+used as the target of the ERET instruction to start initialisation of the Secure
+Partition.
+
+Architectural Setup
+^^^^^^^^^^^^^^^^^^^
+
+At cold boot, system registers accessible from S-EL0 will be in their reset
+state unless otherwise specified. The SPM will perform the following
+architectural setup to enable execution in S-EL0
+
+MMU setup
+^^^^^^^^^
+
+The platform port of a Secure Partition specifies to the SPM a list of regions
+that it needs access to and their attributes. The SPM validates this resource
+description and initialises the Secure EL1&0 translation regime as follows.
+
+1. Device regions are mapped with nGnRE attributes and Execute Never
+   instruction access permissions.
+
+2. Code memory regions are mapped with RO data and Executable instruction access
+   permissions.
+
+3. Read Only data memory regions are mapped with RO data and Execute Never
+   instruction access permissions.
+
+4. Read Write data memory regions are mapped with RW data and Execute Never
+   instruction access permissions.
+
+5. If the resource description does not explicitly describe the type of memory
+   regions then all memory regions will be marked with Code memory region
+   attributes.
+
+6. The ``UXN`` and ``PXN`` bits are set for regions that are not executable by
+   S-EL0 or S-EL1.
+
+System Register Setup
+^^^^^^^^^^^^^^^^^^^^^
+
+System registers that influence software execution in S-EL0 are setup by the SPM
+as follows:
+
+1. ``SCTLR_EL1``
+
+   - ``UCI=1``
+   - ``EOE=0``
+   - ``WXN=1``
+   - ``nTWE=1``
+   - ``nTWI=1``
+   - ``UCT=1``
+   - ``DZE=1``
+   - ``I=1``
+   - ``UMA=0``
+   - ``SA0=1``
+   - ``C=1``
+   - ``A=1``
+   - ``M=1``
+
+2. ``CPACR_EL1``
+
+   - ``FPEN=b'11``
+
+3. ``PSTATE``
+
+   - ``D,A,I,F=1``
+   - ``CurrentEL=0`` (EL0)
+   - ``SpSel=0`` (Thread mode)
+   - ``NRW=0`` (AArch64)
+
+General Purpose Register Setup
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+SPM will invoke the entry point of a service by executing an ERET instruction.
+This transition into S-EL0 is special since it is not in response to a previous
+request through a SVC instruction. This is the first entry into S-EL0. The
+general purpose register usage at the time of entry will be as specified in the
+"Return State" column of Table 3-1 in Section 3.1 "Register use in AArch64 SMC
+calls" of the `SMC Calling Convention`_ (*ARM DEN 0028B*) specification. In
+addition, certain other restrictions will be applied as described below.
+
+1. ``SP_EL0``
+
+   A non-zero value will indicate that the SPM has initialised the stack pointer
+   for the current CPU.
+
+   The value will be 0 otherwise.
+
+2. ``X4-X30``
+
+   The values of these registers will be 0.
+
+3. ``X0-X3``
+
+   Parameters passed by the SPM.
+
+   - ``X0``: Virtual address of a buffer shared between EL3 and S-EL0. The
+     buffer will be mapped in the Secure EL1&0 translation regime with read-only
+     memory attributes described earlier.
+
+   - ``X1``: Size of the buffer in bytes.
+
+   - ``X2``: Cookie value (*IMPLEMENTATION DEFINED*).
+
+   - ``X3``: Cookie value (*IMPLEMENTATION DEFINED*).
+
+Runtime Event Delegation
+------------------------
+
+The SPM receives requests for Secure Partition services through a synchronous
+invocation (i.e. a SMC from the Non-secure world). These requests are delegated
+to the partition by programming a return from the last
+``SP_EVENT_COMPLETE_AARCH64`` call received from the partition. The last call
+was made to signal either completion of Secure Partition initialisation or
+completion of a partition service request.
+
+``SP_EVENT_COMPLETE_AARCH64``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Description
+
+  Signal completion of the last SP service request.
+
+- Parameters
+
+  - **uint32** - Function ID
+
+    - SVC64 Version: **0xC4000061**
+
+  - **int32** - Event Status Code
+
+    Zero or a positive value indicates that the event was handled successfully.
+    The values depend upon the original event that was delegated to the Secure
+    partition. They are described as follows.
+
+    - ``SUCCESS`` : Used to indicate that the Secure Partition was initialised
+      or a runtime request was handled successfully.
+
+    - Any other value greater than 0 is used to pass a specific Event Status
+      code in response to a runtime event.
+
+    A negative value indicates an error. The values of Event Status code depend
+    on the original event.
+
+- Return parameters
+
+  - **int32** - Event ID/Return Code
+
+    Zero or a positive value specifies the unique ID of the event being
+    delegated to the partition by the SPM.
+
+    In the current implementation, this parameter contains the function ID of
+    the ``MM_COMMUNICATE`` SMC. This value indicates to the partition that an
+    event has been delegated to it in response to an ``MM_COMMUNICATE`` request
+    from the Non-secure world.
+
+    A negative value indicates an error. The format of the value is as follows:
+
+    - ``NOT_SUPPORTED``: Function was called from the Non-secure world.
+
+    See `Error Codes`_ for integer values that are associated with each return
+    code.
+
+  - **uint32** - Event Context Address
+
+    Address of a buffer shared between the SPM and Secure Partition to pass
+    event specific information. The format of the data populated in the buffer
+    is implementation defined.
+
+    The buffer is mapped in the Secure EL1&0 translation regime with read-only
+    memory attributes described earlier.
+
+    For the SVC64 version, this parameter is a 64-bit Virtual Address (VA).
+
+    For the SVC32 version, this parameter is a 32-bit Virtual Address (VA).
+
+  - **uint32** - Event context size
+
+    Size of the memory starting at Event Address.
+
+  - **uint32/uint64** - Event Cookie
+
+    This is an optional parameter. If unused its value is SBZ.
+
+- Usage
+
+  This function signals to the SPM that the handling of the last event delegated
+  to a partition has completed. The partition is ready to handle its next event.
+  A return from this function is in response to the next event that will be
+  delegated to the partition. The return parameters describe the next event.
+
+- Caller responsibilities
+
+  A Secure Partition must only call ``SP_EVENT_COMPLETE_AARCH64`` to signal
+  completion of a request that was delegated to it by the SPM.
+
+- Callee responsibilities
+
+  When the SPM receives this call from a Secure Partition, the corresponding
+  syndrome information can be used to return control through an ERET
+  instruction, to the instruction immediately after the call in the Secure
+  Partition context. This syndrome information comprises of general purpose and
+  system register values when the call was made.
+
+  The SPM must save this syndrome information and use it to delegate the next
+  event to the Secure Partition. The return parameters of this interface must
+  specify the properties of the event and be populated in ``X0-X3/W0-W3``
+  registers.
+
+Secure Partition Memory Management
+----------------------------------
+
+A Secure Partition executes at S-EL0, which is an unprivileged Exception Level.
+The SPM is responsible for enabling access to regions of memory in the system
+address map from a Secure Partition. This is done by mapping these regions in
+the Secure EL1&0 Translation regime with appropriate memory attributes.
+Attributes refer to memory type, permission, cacheability and shareability
+attributes used in the Translation tables. The definitions of these attributes
+and their usage can be found in the `ARMv8 ARM`_ (*ARM DDI 0487*).
+
+All memory required by the Secure Partition is allocated upfront in the SPM,
+even before handing over to the Secure Partition for the first time. The initial
+access permissions of the memory regions are statically provided by the platform
+port and should allow the Secure Partition to run its initialisation code.
+
+However, they might not suit the final needs of the Secure Partition because its
+final memory layout might not be known until the Secure Partition initialises
+itself. As the Secure Partition initialises its runtime environment it might,
+for example, load dynamically some modules. For instance, a Secure Partition
+could implement a loader for a standard executable file format (e.g. an PE-COFF
+loader for loading executable files at runtime). These executable files will be
+a part of the Secure Partition image. The location of various sections in an
+executable file and their permission attributes (e.g. read-write data, read-only
+data and code) will be known only when the file is loaded into memory.
+
+In this case, the Secure Partition needs a way to change the access permissions
+of its memory regions. The SPM provides this feature through the
+``SP_MEMORY_ATTRIBUTES_SET_AARCH64`` SVC interface. This interface is available
+to the Secure Partition during a specific time window: from the first entry into
+the Secure Partition up to the first ``SP_EVENT_COMPLETE`` call that signals the
+Secure Partition has finished its initialisation. Once the initialisation is
+complete, the SPM does not allow changes to the memory attributes.
+
+This section describes the standard SVC interface that is implemented by the SPM
+to determine and change permission attributes of memory regions that belong to a
+Secure Partition.
+
+``SP_MEMORY_ATTRIBUTES_GET_AARCH64``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Description
+
+  Request the permission attributes of a memory region from S-EL0.
+
+- Parameters
+
+  - **uint32** Function ID
+
+    - SVC64 Version: **0xC4000064**
+
+  - **uint64** Base Address
+
+    This parameter is a 64-bit Virtual Address (VA).
+
+    There are no alignment restrictions on the Base Address. The permission
+    attributes of the translation granule it lies in are returned.
+
+- Return parameters
+
+  - **int32** - Memory Attributes/Return Code
+
+    On success the format of the Return Code is as follows:
+
+    - Bits[1:0] : Data access permission
+
+      - b'00 : No access
+      - b'01 : Read-Write access
+      - b'10 : Reserved
+      - b'11 : Read-only access
+
+    - Bit[2]: Instruction access permission
+
+      - b'0 : Executable
+      - b'1 : Non-executable
+
+    - Bit[30:3] : Reserved. SBZ.
+
+    - Bit[31]   : Must be 0
+
+    On failure the following error codes are returned:
+
+    - ``INVALID_PARAMETERS``: The Secure Partition is not allowed to access the
+      memory region the Base Address lies in.
+
+    - ``NOT_SUPPORTED`` : The SPM does not support retrieval of attributes of
+      any memory page that is accessible by the Secure Partition, or the
+      function was called from the Non-secure world. Also returned if it is
+      used after ``SP_EVENT_COMPLETE_AARCH64``.
+
+    See `Error Codes`_ for integer values that are associated with each return
+    code.
+
+- Usage
+
+  This function is used to request the permission attributes for S-EL0 on a
+  memory region accessible from a Secure Partition. The size of the memory
+  region is equal to the Translation Granule size used in the Secure EL1&0
+  translation regime. Requests to retrieve other memory region attributes are
+  not currently supported.
+
+- Caller responsibilities
+
+  The caller must obtain the Translation Granule Size of the Secure EL1&0
+  translation regime from the SPM through an implementation defined method.
+
+- Callee responsibilities
+
+  The SPM must not return the memory access controls for a page of memory that
+  is not accessible from a Secure Partition.
+
+``SP_MEMORY_ATTRIBUTES_SET_AARCH64``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Description
+
+  Set the permission attributes of a memory region from S-EL0.
+
+- Parameters
+
+  - **uint32** - Function ID
+
+    - SVC64 Version: **0xC4000065**
+
+  - **uint64** - Base Address
+
+    This parameter is a 64-bit Virtual Address (VA).
+
+    The alignment of the Base Address must be greater than or equal to the size
+    of the Translation Granule Size used in the Secure EL1&0 translation
+    regime.
+
+  - **uint32** - Page count
+
+    Number of pages starting from the Base Address whose memory attributes
+    should be changed. The page size is equal to the Translation Granule Size.
+
+  - **uint32** - Memory Access Controls
+
+    - Bits[1:0] : Data access permission
+
+      - b'00 : No access
+      - b'01 : Read-Write access
+      - b'10 : Reserved
+      - b'11 : Read-only access
+
+    - Bit[2] : Instruction access permission
+
+      - b'0 : Executable
+      - b'1 : Non-executable
+
+    - Bits[31:3] : Reserved. SBZ.
+
+    A combination of attributes that mark the region with RW and Executable
+    permissions is prohibited. A request to mark a device memory region with
+    Executable permissions is prohibited.
+
+- Return parameters
+
+  - **int32** - Return Code
+
+    - ``SUCCESS``: The Memory Access Controls were changed successfully.
+
+    - ``DENIED``: The SPM is servicing a request to change the attributes of a
+      memory region that overlaps with the region specified in this request.
+
+    - ``INVALID_PARAMETER``: An invalid combination of Memory Access Controls
+      has been specified. The Base Address is not correctly aligned. The Secure
+      Partition is not allowed to access part or all of the memory region
+      specified in the call.
+
+    - ``NO_MEMORY``: The SPM does not have memory resources to change the
+      attributes of the memory region in the translation tables.
+
+    - ``NOT_SUPPORTED``: The SPM does not permit change of attributes of any
+      memory region that is accessible by the Secure Partition. Function was
+      called from the Non-secure world. Also returned if it is used after
+      ``SP_EVENT_COMPLETE_AARCH64``.
+
+    See `Error Codes`_ for integer values that are associated with each return
+    code.
+
+- Usage
+
+  This function is used to change the permission attributes for S-EL0 on a
+  memory region accessible from a Secure Partition. The size of the memory
+  region is equal to the Translation Granule size used in the Secure EL1&0
+  translation regime. Requests to change other memory region attributes are not
+  currently supported.
+
+  This function is only available at boot time. This interface is revoked after
+  the Secure Partition sends the first ``SP_EVENT_COMPLETE_AARCH64`` to signal
+  that it is initialised and ready to receive run-time requests.
+
+- Caller responsibilities
+
+  The caller must obtain the Translation Granule Size of the Secure EL1&0
+  translation regime from the SPM through an implementation defined method.
+
+- Callee responsibilities
+
+  The SPM must preserve the original memory access controls of the region of
+  memory in case of an unsuccessful call.  The SPM must preserve the consistency
+  of the S-EL1 translation regime if this function is called on different PEs
+  concurrently and the memory regions specified overlap.
+
+Error Codes
+-----------
+
+.. csv-table::
+   :header: "Name", "Value"
+
+   ``SUCCESS``,0
+   ``NOT_SUPPORTED``,-1
+   ``INVALID_PARAMETER``,-2
+   ``DENIED``,-3
+   ``NO_MEMORY``,-5
+   ``NOT_PRESENT``,-7
+
+--------------
+
+*Copyright (c) 2017, Arm Limited and Contributors. All rights reserved.*
+
+.. _ARMv8 ARM: https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile
+.. _instructions in the EDK2 repository: https://github.com/tianocore/edk2-staging/blob/AArch64StandaloneMm/HowtoBuild.MD
+.. _Management Mode Interface Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0060a/DEN0060A_ARM_MM_Interface_Specification.pdf
+.. _SDEI Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf
+.. _SMC Calling Convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf
+
+.. |Image 1| image:: diagrams/secure_sw_stack_tos.png
+.. |Image 2| image:: diagrams/secure_sw_stack_sp.png
diff --git a/docs/spm-user-guide.rst b/docs/spm-user-guide.rst
deleted file mode 100644
index a3b64d9..0000000
--- a/docs/spm-user-guide.rst
+++ /dev/null
@@ -1,59 +0,0 @@
-ARM Trusted Firmware - SPM User Guide
-=====================================
-
-.. section-numbering::
-    :suffix: .
-
-.. contents::
-
-
-This document briefly presents the Secure Partition Management (SPM) support in
-the Arm Trusted Firmware (TF), specifically focusing on how to build Arm TF with
-SPM support.
-
-Overview of the SPM software stack
-----------------------------------
-
-SPM is supported on the Arm FVP exclusively at the moment.
-
-It is not currently possible for BL31 to integrate SPM support and a Secure
-Payload Dispatcher (SPD) at the same time; they are mutually exclusive. In the
-SPM bootflow, a Secure Partition (SP) image executing at Secure-EL0 replaces the
-Secure Payload image executing at Secure-EL1 (e.g. a Trusted OS). Both are
-referred to as BL32.
-
-A working prototype of a SP has been implemented by repurposing the EDK2 code
-and tools, leveraging the concept of the *Standalone Management Mode (MM)* in
-the UEFI specification (see the PI v1.6 Volume 4: Management Mode Core
-Interface). This will be referred to as the *Standalone MM Secure Partition* in
-the rest of this document.
-
-
-Building TF with SPM support
-----------------------------
-
-To enable SPM support in the TF, the source code must be compiled with the build
-flag ``ENABLE_SPM=1``. On Arm platforms the build option ``ARM_BL31_IN_DRAM``
-can be used to select the location of BL31, both SRAM and DRAM are supported.
-
-
-Using the Standalone MM SP
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-First, build the Standalone MM Secure Partition. To build it, refer to the
-`instructions in the EDK2 repository`_.
-
-Then build TF with SPM support and include the Standalone MM Secure Partition
-image in the FIP:
-
-::
-
-    BL32=path/to/standalone/mm/sp BL33=path/to/bl33.bin \
-    make PLAT=fvp ENABLE_SPM=1 fip all
-
-
---------------
-
-*Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.*
-
-.. _instructions in the EDK2 repository: https://github.com/tianocore/edk2-staging/blob/AArch64StandaloneMm/HowtoBuild.MD
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index 138ed8b..0647e70 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -55,7 +55,7 @@
 
     sudo apt-get install build-essential gcc make git libssl-dev
 
-ARM TF has been tested with `Linaro Release 17.04`_.
+ARM TF has been tested with `Linaro Release 17.10`_.
 
 Download and install the AArch32 or AArch64 little-endian GCC cross compiler.
 The `Linaro Release Notes`_ documents which version of the compiler to use for a
@@ -354,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
@@ -995,7 +1006,7 @@
    modules by checking out a recent version of the `mbed TLS Repository`_. It
    is important to use a version that is compatible with TF and fixes any
    known security vulnerabilities. See `mbed TLS Security Center`_ for more
-   information. The latest version of TF is tested with tag ``mbedtls-2.4.2``.
+   information. The latest version of TF is tested with tag ``mbedtls-2.6.0``.
 
    The ``drivers/auth/mbedtls/mbedtls_*.mk`` files contain the list of mbed TLS
    source files the modules depend upon.
@@ -1464,10 +1475,10 @@
 The latest version of the AArch64 build of ARM Trusted Firmware has been tested
 on the following ARM FVPs (64-bit host machine only).
 
-NOTE: Unless otherwise stated, the model version is Version 11.1 Build 11.1.22.
+NOTE: Unless otherwise stated, the model version is Version 11.2 Build 11.2.33.
 
 -  ``Foundation_Platform``
--  ``FVP_Base_AEMv8A-AEMv8A`` (Version 8.7, Build 0.8.8702)
+-  ``FVP_Base_AEMv8A-AEMv8A`` (Version 9.0, Build 0.8.9005)
 -  ``FVP_Base_Cortex-A35x4``
 -  ``FVP_Base_Cortex-A53x4``
 -  ``FVP_Base_Cortex-A57x4-A53x4``
@@ -1480,7 +1491,7 @@
 The latest version of the AArch32 build of ARM Trusted Firmware has been tested
 on the following ARM FVPs (64-bit host machine only).
 
--  ``FVP_Base_AEMv8A-AEMv8A`` (Version 8.7, Build 0.8.8702)
+-  ``FVP_Base_AEMv8A-AEMv8A`` (Version 9.0, Build 0.8.9005)
 -  ``FVP_Base_Cortex-A32x4``
 
 NOTE: The build numbers quoted above are those reported by launching the FVP
@@ -1857,10 +1868,10 @@
 
 .. _Linaro: `Linaro Release Notes`_
 .. _Linaro Release: `Linaro Release Notes`_
-.. _Linaro Release Notes: https://community.arm.com/tools/dev-platforms/b/documents/posts/linaro-release-notes-deprecated
-.. _Linaro Release 17.04: https://community.arm.com/tools/dev-platforms/b/documents/posts/linaro-release-notes-deprecated#LinaroRelease17.04
-.. _Linaro instructions: https://community.arm.com/dev-platforms/b/documents/posts/instructions-for-using-the-linaro-software-deliverables
-.. _Instructions for using Linaro's deliverables on Juno: https://community.arm.com/dev-platforms/b/documents/posts/using-linaros-deliverables-on-juno
+.. _Linaro Release Notes: https://community.arm.com/dev-platforms/w/docs/226/old-linaro-release-notes
+.. _Linaro Release 17.10: https://community.arm.com/dev-platforms/w/docs/226/old-linaro-release-notes#1710
+.. _Linaro instructions: https://community.arm.com/dev-platforms/w/docs/304/linaro-software-deliverables
+.. _Instructions for using Linaro's deliverables on Juno: https://community.arm.com/dev-platforms/w/docs/303/juno
 .. _ARM Platforms Portal: https://community.arm.com/dev-platforms/
 .. _Development Studio 5 (DS-5): http://www.arm.com/products/tools/software-tools/ds-5/index.php
 .. _Dia: https://wiki.gnome.org/Apps/Dia/Download
diff --git a/drivers/io/io_block.c b/drivers/io/io_block.c
index 128246f..8226554 100644
--- a/drivers/io/io_block.c
+++ b/drivers/io/io_block.c
@@ -167,15 +167,98 @@
 	return 0;
 }
 
+/*
+ * This function allows the caller to read any number of bytes
+ * from any position. It hides from the caller that the low level
+ * driver only can read aligned blocks of data. For this reason
+ * we need to handle the use case where the first byte to be read is not
+ * aligned to start of the block, the last byte to be read is also not
+ * aligned to the end of a block, and there are zero or more blocks-worth
+ * of data in between.
+ *
+ * In such a case we need to read more bytes than requested (i.e. full
+ * blocks) and strip-out the leading bytes (aka skip) and the trailing
+ * bytes (aka padding). See diagram below
+ *
+ * cur->file_pos ------------
+ *                          |
+ * cur->base                |
+ *  |                       |
+ *  v                       v<----  length   ---->
+ *  --------------------------------------------------------------
+ * |           |         block#1    |        |   block#n          |
+ * |  block#0  |            +       |   ...  |     +              |
+ * |           | <- skip -> +       |        |     + <- padding ->|
+ *  ------------------------+----------------------+--------------
+ *             ^                                                  ^
+ *             |                                                  |
+ *             v    iteration#1                iteration#n        v
+ *              --------------------------------------------------
+ *             |                    |        |                    |
+ *             |<----  request ---->|  ...   |<----- request ---->|
+ *             |                    |        |                    |
+ *              --------------------------------------------------
+ *            /                   /          |                    |
+ *           /                   /           |                    |
+ *          /                   /            |                    |
+ *         /                   /             |                    |
+ *        /                   /              |                    |
+ *       /                   /               |                    |
+ *      /                   /                |                    |
+ *     /                   /                 |                    |
+ *    /                   /                  |                    |
+ *   /                   /                   |                    |
+ *  <---- request ------>                    <------ request  ----->
+ *  ---------------------                    -----------------------
+ *  |        |          |                    |          |           |
+ *  |<-skip->|<-nbytes->|           -------->|<-nbytes->|<-padding->|
+ *  |        |          |           |        |          |           |
+ *  ---------------------           |        -----------------------
+ *  ^        \           \          |        |          |
+ *  |         \           \         |        |          |
+ *  |          \           \        |        |          |
+ *  buf->offset \           \   buf->offset  |          |
+ *               \           \               |          |
+ *                \           \              |          |
+ *                 \           \             |          |
+ *                  \           \            |          |
+ *                   \           \           |          |
+ *                    \           \          |          |
+ *                     \           \         |          |
+ *                      --------------------------------
+ *                      |           |        |         |
+ * buffer-------------->|           | ...    |         |
+ *                      |           |        |         |
+ *                      --------------------------------
+ *                      <-count#1->|                   |
+ *                      <----------  count#n   -------->
+ *                      <----------  length  ---------->
+ *
+ * Additionally, the IO driver has an underlying buffer that is at least
+ * one block-size and may be big enough to allow.
+ */
 static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length,
 		      size_t *length_read)
 {
 	block_dev_state_t *cur;
 	io_block_spec_t *buf;
 	io_block_ops_t *ops;
-	size_t aligned_length, skip, count, left, padding, block_size;
 	int lba;
-	int buffer_not_aligned;
+	size_t block_size, left;
+	size_t nbytes;  /* number of bytes read in one iteration */
+	size_t request; /* number of requested bytes in one iteration */
+	size_t count;   /* number of bytes already read */
+	/*
+	 * number of leading bytes from start of the block
+	 * to the first byte to be read
+	 */
+	size_t skip;
+
+	/*
+	 * number of trailing bytes between the last byte
+	 * to be read and the end of the block
+	 */
+	size_t padding;
 
 	assert(entity->info != (uintptr_t)NULL);
 	cur = (block_dev_state_t *)entity->info;
@@ -186,102 +269,107 @@
 	       (length > 0) &&
 	       (ops->read != 0));
 
-	if ((buffer & (block_size - 1)) != 0) {
+	/*
+	 * We don't know the number of bytes that we are going
+	 * to read in every iteration, because it will depend
+	 * on the low level driver.
+	 */
+	count = 0;
+	for (left = length; left > 0; left -= nbytes) {
 		/*
-		 * buffer isn't aligned with block size.
-		 * Block device always relies on DMA operation.
-		 * It's better to make the buffer as block size aligned.
+		 * We must only request operations aligned to the block
+		 * size. Therefore if file_pos is not block-aligned,
+		 * we have to request the operation to start at the
+		 * previous block boundary and skip the leading bytes. And
+		 * similarly, the number of bytes requested must be a
+		 * block size multiple
 		 */
-		buffer_not_aligned = 1;
-	} else {
-		buffer_not_aligned = 0;
-	}
+		skip = cur->file_pos & (block_size - 1);
 
-	skip = cur->file_pos % block_size;
-	aligned_length = ((skip + length) + (block_size - 1)) &
-			 ~(block_size - 1);
-	padding = aligned_length - (skip + length);
-	left = aligned_length;
-	do {
+		/*
+		 * Calculate the block number containing file_pos
+		 * - e.g. block 3.
+		 */
 		lba = (cur->file_pos + cur->base) / block_size;
-		if (left >= buf->length) {
+
+		if (skip + left > buf->length) {
 			/*
-			 * Since left is larger, it's impossible to padding.
-			 *
-			 * If buffer isn't aligned, we need to use aligned
-			 * buffer instead.
+			 * The underlying read buffer is too small to
+			 * read all the required data - limit to just
+			 * fill the buffer, and then read again.
 			 */
-			if (skip || buffer_not_aligned) {
-				/*
-				 * The beginning address (file_pos) isn't
-				 * aligned with block size, we need to use
-				 * block buffer to read block. Since block
-				 * device is always relied on DMA operation.
-				 */
-				count = ops->read(lba, buf->offset,
-						  buf->length);
-			} else {
-				count = ops->read(lba, buffer, buf->length);
-			}
-			assert(count == buf->length);
-			cur->file_pos += count - skip;
-			if (skip || buffer_not_aligned) {
-				/*
-				 * Since there's not aligned block size caused
-				 * by skip or not aligned buffer, block buffer
-				 * is used to store data.
-				 */
-				memcpy((void *)buffer,
-				       (void *)(buf->offset + skip),
-				       count - skip);
-			}
-			left = left - (count - skip);
+			request = buf->length;
 		} else {
-			if (skip || padding || buffer_not_aligned) {
-				/*
-				 * The beginning address (file_pos) isn't
-				 * aligned with block size, we have to read
-				 * full block by block buffer instead.
-				 * The size isn't aligned with block size.
-				 * Use block buffer to avoid overflow.
-				 *
-				 * If buffer isn't aligned, use block buffer
-				 * to avoid DMA error.
-				 */
-				count = ops->read(lba, buf->offset, left);
-			} else
-				count = ops->read(lba, buffer, left);
-			assert(count == left);
-			left = left - (skip + padding);
-			cur->file_pos += left;
-			if (skip || padding || buffer_not_aligned) {
-				/*
-				 * Since there's not aligned block size or
-				 * buffer, block buffer is used to store data.
-				 */
-				memcpy((void *)buffer,
-				       (void *)(buf->offset + skip),
-				       left);
-			}
-			/* It's already the last block operation */
-			left = 0;
+			/*
+			 * The underlying read buffer is big enough to
+			 * read all the required data. Calculate the
+			 * number of bytes to read to align with the
+			 * block size.
+			 */
+			request = skip + left;
+			request = (request + (block_size - 1)) & ~(block_size - 1);
+		}
+		request = ops->read(lba, buf->offset, request);
+
+		if (request <= skip) {
+			/*
+			 * We couldn't read enough bytes to jump over
+			 * the skip bytes, so we should have to read
+			 * again the same block, thus generating
+			 * the same error.
+			 */
+			return -EIO;
 		}
-		skip = cur->file_pos % block_size;
-	} while (left > 0);
-	*length_read = length;
+
+		/*
+		 * Need to remove skip and padding bytes,if any, from
+		 * the read data when copying to the user buffer.
+		 */
+		nbytes = request - skip;
+		padding = (nbytes > left) ? nbytes - left : 0;
+		nbytes -= padding;
+
+		memcpy((void *)(buffer + count),
+		       (void *)(buf->offset + skip),
+		       nbytes);
+
+		cur->file_pos += nbytes;
+		count += nbytes;
+	}
+	assert(count == length);
+	*length_read = count;
 
 	return 0;
 }
 
+/*
+ * This function allows the caller to write any number of bytes
+ * from any position. It hides from the caller that the low level
+ * driver only can write aligned blocks of data.
+ * See comments for block_read for more details.
+ */
 static int block_write(io_entity_t *entity, const uintptr_t buffer,
 		       size_t length, size_t *length_written)
 {
 	block_dev_state_t *cur;
 	io_block_spec_t *buf;
 	io_block_ops_t *ops;
-	size_t aligned_length, skip, count, left, padding, block_size;
 	int lba;
-	int buffer_not_aligned;
+	size_t block_size, left;
+	size_t nbytes;  /* number of bytes read in one iteration */
+	size_t request; /* number of requested bytes in one iteration */
+	size_t count;   /* number of bytes already read */
+	/*
+	 * number of leading bytes from start of the block
+	 * to the first byte to be read
+	 */
+	size_t skip;
+
+	/*
+	 * number of trailing bytes between the last byte
+	 * to be read and the end of the block
+	 */
+	size_t padding;
 
 	assert(entity->info != (uintptr_t)NULL);
 	cur = (block_dev_state_t *)entity->info;
@@ -293,75 +381,107 @@
 	       (ops->read != 0) &&
 	       (ops->write != 0));
 
-	if ((buffer & (block_size - 1)) != 0) {
+	/*
+	 * We don't know the number of bytes that we are going
+	 * to write in every iteration, because it will depend
+	 * on the low level driver.
+	 */
+	count = 0;
+	for (left = length; left > 0; left -= nbytes) {
 		/*
-		 * buffer isn't aligned with block size.
-		 * Block device always relies on DMA operation.
-		 * It's better to make the buffer as block size aligned.
+		 * We must only request operations aligned to the block
+		 * size. Therefore if file_pos is not block-aligned,
+		 * we have to request the operation to start at the
+		 * previous block boundary and skip the leading bytes. And
+		 * similarly, the number of bytes requested must be a
+		 * block size multiple
 		 */
-		buffer_not_aligned = 1;
-	} else {
-		buffer_not_aligned = 0;
-	}
+		skip = cur->file_pos & (block_size - 1);
 
-	skip = cur->file_pos % block_size;
-	aligned_length = ((skip + length) + (block_size - 1)) &
-			 ~(block_size - 1);
-	padding = aligned_length - (skip + length);
-	left = aligned_length;
-	do {
+		/*
+		 * Calculate the block number containing file_pos
+		 * - e.g. block 3.
+		 */
 		lba = (cur->file_pos + cur->base) / block_size;
-		if (left >= buf->length) {
-			/* Since left is larger, it's impossible to padding. */
-			if (skip || buffer_not_aligned) {
-				/*
-				 * The beginning address (file_pos) isn't
-				 * aligned with block size or buffer isn't
-				 * aligned, we need to use block buffer to
-				 * write block.
-				 */
-				count = ops->read(lba, buf->offset,
-						  buf->length);
-				assert(count == buf->length);
-				memcpy((void *)(buf->offset + skip),
-				       (void *)buffer,
-				       count - skip);
-				count = ops->write(lba, buf->offset,
-						   buf->length);
-			} else
-				count = ops->write(lba, buffer, buf->length);
-			assert(count == buf->length);
-			cur->file_pos += count - skip;
-			left = left - (count - skip);
+
+		if (skip + left > buf->length) {
+			/*
+			 * The underlying read buffer is too small to
+			 * read all the required data - limit to just
+			 * fill the buffer, and then read again.
+			 */
+			request = buf->length;
 		} else {
-			if (skip || padding || buffer_not_aligned) {
+			/*
+			 * The underlying read buffer is big enough to
+			 * read all the required data. Calculate the
+			 * number of bytes to read to align with the
+			 * block size.
+			 */
+			request = skip + left;
+			request = (request + (block_size - 1)) & ~(block_size - 1);
+		}
+
+		/*
+		 * The number of bytes that we are going to write
+		 * from the user buffer will depend of the size
+		 * of the current request.
+		 */
+		nbytes = request - skip;
+		padding = (nbytes > left) ? nbytes - left : 0;
+		nbytes -= padding;
+
+		/*
+		 * If we have skip or padding bytes then we have to preserve
+		 * some content and it means that we have to read before
+		 * writing
+		 */
+		if (skip > 0 || padding > 0) {
+			request = ops->read(lba, buf->offset, request);
+			/*
+			 * The read may return size less than
+			 * requested. Round down to the nearest block
+			 * boundary
+			 */
+			request &= ~(block_size-1);
+			if (request <= skip) {
 				/*
-				 * The beginning address (file_pos) isn't
-				 * aligned with block size, we need to avoid
-				 * poluate data in the beginning. Reading and
-				 * skipping the beginning is the only way.
-				 * The size isn't aligned with block size.
-				 * Use block buffer to avoid overflow.
-				 *
-				 * If buffer isn't aligned, use block buffer
-				 * to avoid DMA error.
+				 * We couldn't read enough bytes to jump over
+				 * the skip bytes, so we should have to read
+				 * again the same block, thus generating
+				 * the same error.
 				 */
-				count = ops->read(lba, buf->offset, left);
-				assert(count == left);
-				memcpy((void *)(buf->offset + skip),
-				       (void *)buffer,
-				       left - skip - padding);
-				count = ops->write(lba, buf->offset, left);
-			} else
-				count = ops->write(lba, buffer, left);
-			assert(count == left);
-			cur->file_pos += left - (skip + padding);
-			/* It's already the last block operation */
-			left = 0;
+				return -EIO;
+			}
+			nbytes = request - skip;
+			padding = (nbytes > left) ? nbytes - left : 0;
+			nbytes -= padding;
 		}
-		skip = cur->file_pos % block_size;
-	} while (left > 0);
-	*length_written = length;
+
+		memcpy((void *)(buf->offset + skip),
+		       (void *)(buffer + count),
+		       nbytes);
+
+		request = ops->write(lba, buf->offset, request);
+		if (request <= skip)
+			return -EIO;
+
+		/*
+		 * And the previous write operation may modify the size
+		 * of the request, so again, we have to calculate the
+		 * number of bytes that we consumed from the user
+		 * buffer
+		 */
+		nbytes = request - skip;
+		padding = (nbytes > left) ? nbytes - left : 0;
+		nbytes -= padding;
+
+		cur->file_pos += nbytes;
+		count += nbytes;
+	}
+	assert(count == length);
+	*length_written = count;
+
 	return 0;
 }
 
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/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 65e9fc1..96e2d5f 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -114,6 +114,9 @@
 #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)
@@ -301,6 +304,7 @@
 #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 */
@@ -309,6 +313,7 @@
 #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 */
@@ -556,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
  ******************************************************************************/
 /*
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index b6be167..831dfb0 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -329,6 +329,9 @@
 
 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/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 68f4a0e..e0c3c86 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -90,11 +90,7 @@
  * 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
-#endif
+#define PLAT_ARM_MAX_BL31_SIZE		0x1E000
 
 #ifdef AARCH32
 /*
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 7887525..f38c357 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -491,4 +491,15 @@
 #define ARM_SDEI_DS_EVENT_1		2001
 #define ARM_SDEI_DS_EVENT_2		2002
 
+#define ARM_SDEI_PRIVATE_EVENTS \
+	SDEI_DEFINE_EVENT_0(ARM_SDEI_SGI), \
+	SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \
+	SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \
+	SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)
+
+#define ARM_SDEI_SHARED_EVENTS \
+	SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \
+	SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \
+	SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)
+
 #endif /* __ARM_DEF_H__ */
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/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_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/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index b892729..c6c2249 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -18,6 +18,7 @@
 #include <smcc_helpers.h>
 #include <spe.h>
 #include <string.h>
+#include <sve.h>
 #include <utils.h>
 
 
@@ -225,6 +226,10 @@
 #if ENABLE_AMU
 	amu_enable(el2_unused);
 #endif
+
+#if ENABLE_SVE_FOR_NS
+	sve_enable(el2_unused);
+#endif
 #endif
 }
 
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/maintainers.rst b/maintainers.rst
index 701ea17..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,24 +73,44 @@
 
 -  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
@@ -96,13 +118,15 @@
 
 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/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 9f7abed..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
 
@@ -158,3 +155,12 @@
 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/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..4ac0850 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>
@@ -145,4 +146,7 @@
 
 #define PLAT_ARM_G0_IRQ_PROPS(grp)	ARM_G0_IRQ_PROPS(grp)
 
+#define PLAT_ARM_PRIVATE_SDEI_EVENTS	ARM_SDEI_PRIVATE_EVENTS
+#define PLAT_ARM_SHARED_SDEI_EVENTS	ARM_SDEI_SHARED_EVENTS
+
 #endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index e475ece..cac47f7 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -238,4 +238,7 @@
 /* CSS SoC NIC-400 Global Programmers View (GPV) */
 #define PLAT_SOC_CSS_NIC400_BASE	0x2a000000
 
+#define PLAT_ARM_PRIVATE_SDEI_EVENTS	ARM_SDEI_PRIVATE_EVENTS
+#define PLAT_ARM_SHARED_SDEI_EVENTS	ARM_SDEI_SHARED_EVENTS
+
 #endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index bfb7847..fee4391 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -99,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/aarch64/arm_sdei.c b/plat/arm/common/aarch64/arm_sdei.c
index 514800c..687b21d 100644
--- a/plat/arm/common/aarch64/arm_sdei.c
+++ b/plat/arm/common/aarch64/arm_sdei.c
@@ -11,23 +11,14 @@
 #include <sdei.h>
 
 /* Private event mappings */
-static sdei_ev_map_t arm_private_sdei[] = {
-	/* Event 0 */
-	SDEI_DEFINE_EVENT_0(ARM_SDEI_SGI),
-
-	/* Dynamic private events */
-	SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
-	SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
-	SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
+static sdei_ev_map_t arm_sdei_private[] = {
+	PLAT_ARM_PRIVATE_SDEI_EVENTS
 };
 
 /* Shared event mappings */
-static sdei_ev_map_t arm_shared_sdei[] = {
-	/* Dynamic shared events */
-	SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
-	SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
-	SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
+static sdei_ev_map_t arm_sdei_shared[] = {
+	PLAT_ARM_SHARED_SDEI_EVENTS
 };
 
 /* Export ARM SDEI events */
-REGISTER_SDEI_MAP(arm_private_sdei, arm_shared_sdei);
+REGISTER_SDEI_MAP(arm_sdei_private, arm_sdei_shared);
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 17acae5..fab57f1 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -7,13 +7,9 @@
 ifeq (${ARCH}, aarch64)
   # On ARM standard platorms, the TSP can execute from Trusted SRAM, Trusted
   # DRAM (if available) or the TZC secured area of DRAM.
-  # Trusted SRAM is the default.
+  # TZC secured DRAM is the default.
 
-  ifneq (${TRUSTED_BOARD_BOOT},0)
-    ARM_TSP_RAM_LOCATION	?=	dram
-  else
-    ARM_TSP_RAM_LOCATION	?=	tsram
-  endif
+  ARM_TSP_RAM_LOCATION	?=	dram
 
   ifeq (${ARM_TSP_RAM_LOCATION}, tsram)
     ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_SRAM_ID
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/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..524fa6a 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))
@@ -119,3 +120,5 @@
 ERRATA_A53_836870		:=	1
 ERRATA_A53_843419		:=	1
 ERRATA_A53_855873		:=	1
+
+FIP_ALIGN			:=	512
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..cb97deb 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))
@@ -100,3 +101,5 @@
 ERRATA_A53_836870		:=	1
 ERRATA_A53_843419		:=	1
 ERRATA_A53_855873		:=	1
+
+FIP_ALIGN			:=	512
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/include/platform_def.h b/plat/socionext/uniphier/include/platform_def.h
index b5dc16a..cc046eb 100644
--- a/plat/socionext/uniphier/include/platform_def.h
+++ b/plat/socionext/uniphier/include/platform_def.h
@@ -47,7 +47,7 @@
 #define BL32_LIMIT			(UNIPHIER_SEC_DRAM_LIMIT)
 
 #define UNIPHIER_BLOCK_BUF_SIZE		0x00400000
-#define UNIPHIER_BLOCK_BUF_BASE		((BL2_LIMIT) - \
+#define UNIPHIER_BLOCK_BUF_BASE		((BL2_BASE) - \
 					 (UNIPHIER_BLOCK_BUF_SIZE))
 
 #define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
diff --git a/plat/socionext/uniphier/platform.mk b/plat/socionext/uniphier/platform.mk
index c91abb6..41d0444 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)
@@ -115,5 +116,5 @@
 .PHONY: bl1_gzip
 bl1_gzip: $(BUILD_PLAT)/bl1.bin.gzip
 %.gzip: %
-	@echo " GZIP     $@"
+	@echo "  GZIP    $@"
 	$(Q)(cat $< | gzip -n -f -9 > $@) || (rm -f $@ || false)
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 6f4b057..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;
diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c
index de657a2..979b9a8 100644
--- a/services/std_svc/spm/spm_main.c
+++ b/services/std_svc/spm/spm_main.c
@@ -29,7 +29,6 @@
  * Secure Partition context information.
  ******************************************************************************/
 static secure_partition_context_t sp_ctx;
-unsigned int sp_init_in_progress;
 
 /*******************************************************************************
  * Replace the S-EL1 re-entry information with S-EL0 re-entry
@@ -48,7 +47,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 +74,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 +100,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 +125,28 @@
 	secure_partition_setup();
 
 	/*
-	 * Arrange for an entry into the secure payload.
+	 * Make all CPUs use the same secure context.
 	 */
-	sp_init_in_progress = 1;
+	for (unsigned int i = 0; i < PLATFORM_CORE_COUNT; i++) {
+		cm_set_context_by_index(i, &sp_ctx.cpu_ctx, SECURE);
+	}
+
+	/*
+	 * Arrange for an entry into the secure partition.
+	 */
+	sp_ctx.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");
+	sp_ctx.sp_init_in_progress = 0;
+	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 +167,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 +234,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 +269,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 +356,7 @@
 
 		switch (smc_fid) {
 
-		case  SPM_VERSION_AARCH32:
+		case SPM_VERSION_AARCH32:
 			SMC_RET1(handle, SPM_VERSION_COMPILED);
 
 		case SP_EVENT_COMPLETE_AARCH64:
@@ -357,7 +364,7 @@
 			cm_el1_sysregs_context_save(SECURE);
 			spm_setup_next_eret_into_sel0(handle);
 
-			if (sp_init_in_progress) {
+			if (sp_ctx.sp_init_in_progress) {
 				/*
 				 * SPM reports completion. The SPM must have
 				 * initiated the original request through a
@@ -369,6 +376,9 @@
 				assert(0);
 			}
 
+			/* Release the Secure Partition context */
+			spin_unlock(&sp_ctx.lock);
+
 			/*
 			 * This is the result from the Secure partition of an
 			 * earlier request. Copy the result into the non-secure
@@ -387,20 +397,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");
+			if (!sp_ctx.sp_init_in_progress) {
+				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");
+			if (!sp_ctx.sp_init_in_progress) {
+				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,16 +423,38 @@
 
 		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 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);
+			}
+
-		case SP_COMMUNICATE_AARCH32:
-		case SP_COMMUNICATE_AARCH64:
+			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);
 
+			/* Lock the Secure Partition context. */
+			spin_lock(&sp_ctx.lock);
+
 			/*
 			 * Restore the secure world context and prepare for
 			 * entry in S-EL0
@@ -431,17 +463,12 @@
 			cm_el1_sysregs_context_restore(SECURE);
 			cm_set_next_eret_context(SECURE);
 
-			/* Cookie. Reserved for future use. It must be zero. */
-			assert(x1 == 0);
-
-			if (x3 != 0) {
-				VERBOSE("SP_COMMUNICATE_AARCH32/64: X3 is not 0 as recommended.\n");
-			}
-
-			SMC_RET4(&sp_ctx.cpu_ctx, smc_fid, x1, x2, x3);
+			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);
 
diff --git a/services/std_svc/spm/spm_private.h b/services/std_svc/spm/spm_private.h
index 16993e8..1d16b45 100644
--- a/services/std_svc/spm/spm_private.h
+++ b/services/std_svc/spm/spm_private.h
@@ -32,6 +32,7 @@
 
 #ifndef __ASSEMBLY__
 
+#include <spinlock.h>
 #include <stdint.h>
 #include <xlat_tables_v2.h>
 
@@ -43,6 +44,8 @@
 typedef struct secure_partition_context {
 	uint64_t c_rt_ctx;
 	cpu_context_t cpu_ctx;
+	unsigned int sp_init_in_progress;
+	spinlock_t lock;
 } secure_partition_context_t;
 
 uint64_t spm_secure_partition_enter(uint64_t *c_rt_ctx);
diff --git a/tools/fiptool/fiptool.c b/tools/fiptool/fiptool.c
index 1dcb7e8..33c451e 100644
--- a/tools/fiptool/fiptool.c
+++ b/tools/fiptool/fiptool.c
@@ -492,7 +492,7 @@
 	fip_toc_header_t *toc_header;
 	fip_toc_entry_t *toc_entry;
 	char *buf;
-	uint64_t entry_offset, buf_size, payload_size = 0;
+	uint64_t entry_offset, buf_size, payload_size = 0, pad_size;
 	size_t nr_images = 0;
 
 	for (desc = image_desc_head; desc != NULL; desc = desc->next)
@@ -526,9 +526,13 @@
 		entry_offset += image->toc_e.size;
 	}
 
-	/* Append a null uuid entry to mark the end of ToC entries. */
+	/*
+	 * Append a null uuid entry to mark the end of ToC entries.
+	 * NOTE the offset address for the last toc_entry must match the fip
+	 * size.
+	 */
 	memset(toc_entry, 0, sizeof(*toc_entry));
-	toc_entry->offset_address = entry_offset;
+	toc_entry->offset_address = (entry_offset + align - 1) & ~(align - 1);
 
 	/* Generate the FIP file. */
 	fp = fopen(filename, "wb");
@@ -555,6 +559,13 @@
 		xfwrite(image->buffer, image->toc_e.size, fp, filename);
 	}
 
+	if (fseek(fp, entry_offset, SEEK_SET))
+		log_errx("Failed to set file position");
+
+	pad_size = toc_entry->offset_address - entry_offset;
+	while (pad_size--)
+		fputc(0x0, fp);
+
 	fclose(fp);
 	return 0;
 }