Merge pull request #1866 from mmind/rockchip-fdt-param

rockchip: add an fdt parsing stub for platform param
diff --git a/.checkpatch.conf b/.checkpatch.conf
index 50ab716..2a53961 100644
--- a/.checkpatch.conf
+++ b/.checkpatch.conf
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -69,3 +69,23 @@
 # "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt"
 # We allow the usage of the volatile keyword in TF.
 --ignore VOLATILE
+
+# BRACES reports this kind of messages:
+# braces {} are not necessary for any arm of this statement
+--ignore BRACES
+
+# PREFER_KERNEL_TYPES reports this kind of messages (when using --strict):
+# "Prefer kernel type 'u32' over 'uint32_t'"
+--ignore PREFER_KERNEL_TYPES
+
+# USLEEP_RANGE reports this kind of messages (when using --strict):
+# "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt"
+--ignore USLEEP_RANGE
+
+# COMPARISON_TO_NULL reports this kind of messages (when using --strict):
+# Comparison to NULL could be written ""
+--ignore COMPARISON_TO_NULL
+
+# UNNECESSARY_PARENTHESES reports this kind of messages (when using --strict):
+# Unnecessary parentheses around ""
+--ignore UNNECESSARY_PARENTHESES
diff --git a/Makefile b/Makefile
index 7b0ef5b..8656da5 100644
--- a/Makefile
+++ b/Makefile
@@ -147,26 +147,34 @@
 # Will set march32-directive from platform configuration
 else
 target32-directive	= 	-target armv8a-none-eabi
+
+# Set the compiler's target architecture profile based on ARM_ARCH_MINOR option
+ifeq (${ARM_ARCH_MINOR},0)
 march32-directive	= 	-march=armv8-a
+march64-directive	= 	-march=armv8-a
+else
+march32-directive	= 	-march=armv8.${ARM_ARCH_MINOR}-a
+march64-directive	= 	-march=armv8.${ARM_ARCH_MINOR}-a
+endif
 endif
 
 ifneq ($(findstring armclang,$(notdir $(CC))),)
 TF_CFLAGS_aarch32	=	-target arm-arm-none-eabi $(march32-directive)
-TF_CFLAGS_aarch64	=	-target aarch64-arm-none-eabi -march=armv8-a
+TF_CFLAGS_aarch64	=	-target aarch64-arm-none-eabi $(march64-directive)
 LD			=	$(LINKER)
 AS			=	$(CC) -c -x assembler-with-cpp $(TF_CFLAGS_$(ARCH))
 CPP			=	$(CC) -E $(TF_CFLAGS_$(ARCH))
 PP			=	$(CC) -E $(TF_CFLAGS_$(ARCH))
 else ifneq ($(findstring clang,$(notdir $(CC))),)
 TF_CFLAGS_aarch32	=	$(target32-directive) $(march32-directive)
-TF_CFLAGS_aarch64	=	-target aarch64-elf
+TF_CFLAGS_aarch64	=	-target aarch64-elf $(march64-directive)
 LD			=	$(LINKER)
 AS			=	$(CC) -c -x assembler-with-cpp $(TF_CFLAGS_$(ARCH))
 CPP			=	$(CC) -E
 PP			=	$(CC) -E
 else
 TF_CFLAGS_aarch32	=	$(march32-directive)
-TF_CFLAGS_aarch64	=	-march=armv8-a
+TF_CFLAGS_aarch64	=	$(march64-directive)
 LD			=	$(LINKER)
 endif
 
@@ -182,15 +190,7 @@
 TF_CFLAGS_aarch64	+=	-mgeneral-regs-only -mstrict-align
 
 ASFLAGS_aarch32		=	$(march32-directive)
-ASFLAGS_aarch64		=	-march=armv8-a
-
-# Set the compiler to ARMv8.3 mode so that it uses all the ARMv8.3-PAuth
-# instructions. Keeping it in 8.0 would make the compiler emit
-# backwards-compatible hint instructions, which needs more space.
-ifeq (${ENABLE_PAUTH},1)
-TF_CFLAGS_aarch64	+=	-march=armv8.3-a
-ASFLAGS_aarch64		+=	-march=armv8.3-a
-endif
+ASFLAGS_aarch64		=	$(march64-directive)
 
 WARNING1 := -Wextra
 WARNING1 += -Wunused -Wno-unused-parameter
@@ -245,8 +245,13 @@
 
 GCC_V_OUTPUT		:=	$(shell $(CC) -v 2>&1)
 
+ifneq ($(findstring armlink,$(notdir $(LD))),)
+TF_LDFLAGS		+=	--diag_error=warning --lto_level=O1
+TF_LDFLAGS		+=	--remove --info=unused,unusedsymbols
+else
 TF_LDFLAGS		+=	--fatal-warnings -O1
 TF_LDFLAGS		+=	--gc-sections
+endif
 TF_LDFLAGS		+=	$(TF_LDFLAGS_$(ARCH))
 
 DTC_FLAGS		+=	-I dts -O dtb
@@ -366,7 +371,7 @@
 
 ifeq ($(ENABLE_PIE),1)
     TF_CFLAGS		+=	-fpie
-    TF_LDFLAGS		+=	-pie
+    TF_LDFLAGS		+=	-pie --no-dynamic-linker
 else
     PIE_FOUND		:=	$(findstring --enable-default-pie,${GCC_V_OUTPUT})
     ifneq ($(PIE_FOUND),)
@@ -714,6 +719,10 @@
 $(eval $(call add_define,DYN_DISABLE_AUTH))
 endif
 
+ifneq ($(findstring armlink,$(notdir $(LD))),)
+$(eval $(call add_define,USE_ARM_LINK))
+endif
+
 ################################################################################
 # Build targets
 ################################################################################
@@ -728,8 +737,12 @@
 
 # Check if deprecated declarations and cpp warnings should be treated as error or not.
 ifeq (${ERROR_DEPRECATED},0)
+ifneq ($(findstring clang,$(notdir $(CC))),)
+    CPPFLAGS		+= 	-Wno-error=deprecated-declarations
+else
     CPPFLAGS		+= 	-Wno-error=deprecated-declarations -Wno-error=cpp
 endif
+endif
 
 $(eval $(call MAKE_LIB_DIRS))
 $(eval $(call MAKE_LIB,c))
@@ -828,13 +841,18 @@
 
 checkpatch:		locate-checkpatch
 	@echo "  CHECKING STYLE"
+	@if test -n "${CHECKPATCH_OPTS}"; then				\
+		echo "    with ${CHECKPATCH_OPTS} option(s)";		\
+	fi
 	${Q}COMMON_COMMIT=$$(git merge-base HEAD ${BASE_COMMIT});	\
 	for commit in `git rev-list $$COMMON_COMMIT..HEAD`; do		\
 		printf "\n[*] Checking style of '$$commit'\n\n";	\
 		git log --format=email "$$commit~..$$commit"		\
-			-- ${CHECK_PATHS} | ${CHECKPATCH} - || true;	\
+			-- ${CHECK_PATHS} |				\
+			${CHECKPATCH} ${CHECKPATCH_OPTS} - || true;	\
 		git diff --format=email "$$commit~..$$commit"		\
-			-- ${CHECK_PATHS} | ${CHECKPATCH} - || true;	\
+			-- ${CHECK_PATHS} |				\
+			${CHECKPATCH}  ${CHECKPATCH_OPTS} - || true;	\
 	done
 
 certtool: ${CRTTOOL}
diff --git a/bl1/aarch32/bl1_exceptions.S b/bl1/aarch32/bl1_exceptions.S
index 6728278..f2af9ab 100644
--- a/bl1/aarch32/bl1_exceptions.S
+++ b/bl1/aarch32/bl1_exceptions.S
@@ -71,7 +71,7 @@
 	 */
 	ldr	lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET]
 	ldr	r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)]
-	msr	spsr, r1
+	msr	spsr_xc, r1
 
 	/* Some BL32 stages expect lr_svc to provide the BL33 entry address */
 	cps	#MODE32_svc
diff --git a/bl2/aarch32/bl2_el3_entrypoint.S b/bl2/aarch32/bl2_el3_entrypoint.S
index 35da133..9b4da6b 100644
--- a/bl2/aarch32/bl2_el3_entrypoint.S
+++ b/bl2/aarch32/bl2_el3_entrypoint.S
@@ -78,7 +78,7 @@
 	 */
 	ldr	lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET]
 	ldr	r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)]
-	msr	spsr, r1
+	msr	spsr_xc, r1
 
 	/* Some BL32 stages expect lr_svc to provide the BL33 entry address */
 	cps	#MODE32_svc
diff --git a/bl2/aarch32/bl2_entrypoint.S b/bl2/aarch32/bl2_entrypoint.S
index 23d1513..102fd2f 100644
--- a/bl2/aarch32/bl2_entrypoint.S
+++ b/bl2/aarch32/bl2_entrypoint.S
@@ -42,12 +42,13 @@
 	stcopr	r0, VBAR
 	isb
 
-	/* -----------------------------------------------------
-	 * Enable the instruction cache
-	 * -----------------------------------------------------
+	/* --------------------------------------------------------
+	 * Enable the instruction cache - disable speculative loads
+	 * --------------------------------------------------------
 	 */
 	ldcopr	r0, SCTLR
 	orr	r0, r0, #SCTLR_I_BIT
+	bic	r0, r0, #SCTLR_DSSBS_BIT
 	stcopr	r0, SCTLR
 	isb
 
diff --git a/bl2/aarch64/bl2_entrypoint.S b/bl2/aarch64/bl2_entrypoint.S
index 611b807..c820cd1 100644
--- a/bl2/aarch64/bl2_entrypoint.S
+++ b/bl2/aarch64/bl2_entrypoint.S
@@ -41,12 +41,14 @@
 
 	/* ---------------------------------------------
 	 * Enable the instruction cache, stack pointer
-	 * and data access alignment checks
+	 * and data access alignment checks and disable
+	 * speculative loads.
 	 * ---------------------------------------------
 	 */
 	mov	x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
 	mrs	x0, sctlr_el1
 	orr	x0, x0, x1
+	bic	x0, x0, #SCTLR_DSSBS_BIT
 	msr	sctlr_el1, x0
 	isb
 
diff --git a/bl2u/aarch32/bl2u_entrypoint.S b/bl2u/aarch32/bl2u_entrypoint.S
index 67566df..6391f53 100644
--- a/bl2u/aarch32/bl2u_entrypoint.S
+++ b/bl2u/aarch32/bl2u_entrypoint.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -41,12 +41,13 @@
 	stcopr	r0, VBAR
 	isb
 
-	/* -----------------------------------------------------
-	 * Enable the instruction cache
-	 * -----------------------------------------------------
+	/* --------------------------------------------------------
+	 * Enable the instruction cache - disable speculative loads
+	 * --------------------------------------------------------
 	 */
 	ldcopr	r0, SCTLR
 	orr	r0, r0, #SCTLR_I_BIT
+	bic	r0, r0, #SCTLR_DSSBS_BIT
 	stcopr	r0, SCTLR
 	isb
 
diff --git a/bl2u/aarch64/bl2u_entrypoint.S b/bl2u/aarch64/bl2u_entrypoint.S
index 591f5f6..452869e 100644
--- a/bl2u/aarch64/bl2u_entrypoint.S
+++ b/bl2u/aarch64/bl2u_entrypoint.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -38,12 +38,14 @@
 
 	/* ---------------------------------------------
 	 * Enable the instruction cache, stack pointer
-	 * and data access alignment checks
+	 * and data access alignment checks and disable
+	 * speculative loads.
 	 * ---------------------------------------------
 	 */
 	mov	x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
 	mrs	x0, sctlr_el1
 	orr	x0, x0, x1
+	bic	x0, x0, #SCTLR_DSSBS_BIT
 	msr	sctlr_el1, x0
 	isb
 
diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S
index 8e9528b..065edff 100644
--- a/bl31/aarch64/bl31_entrypoint.S
+++ b/bl31/aarch64/bl31_entrypoint.S
@@ -201,6 +201,19 @@
 #endif
 	bl	bl31_plat_enable_mmu
 
+	/* --------------------------------------------------------------------
+	 * Enable pointer authentication
+	 * --------------------------------------------------------------------
+	 */
+#if ENABLE_PAUTH
+	bl	pauth_load_bl_apiakey
+
+	mrs	x0, sctlr_el3
+	orr	x0, x0, #SCTLR_EnIA_BIT
+	msr	sctlr_el3, x0
+	isb
+#endif /* ENABLE_PAUTH */
+
 	bl	psci_warmboot_entrypoint
 
 #if ENABLE_RUNTIME_INSTRUMENTATION
diff --git a/bl32/tsp/aarch64/tsp_entrypoint.S b/bl32/tsp/aarch64/tsp_entrypoint.S
index 710b458..cd08ce7 100644
--- a/bl32/tsp/aarch64/tsp_entrypoint.S
+++ b/bl32/tsp/aarch64/tsp_entrypoint.S
@@ -63,12 +63,14 @@
 
 	/* ---------------------------------------------
 	 * Enable the instruction cache, stack pointer
-	 * and data access alignment checks
+	 * and data access alignment checks and disable
+	 * speculative loads.
 	 * ---------------------------------------------
 	 */
 	mov	x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
 	mrs	x0, sctlr_el1
 	orr	x0, x0, x1
+	bic	x0, x0, #SCTLR_DSSBS_BIT
 	msr	sctlr_el1, x0
 	isb
 
diff --git a/common/bl_common.c b/common/bl_common.c
index 4e76dd3..61f031b 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -265,7 +265,7 @@
 	 * system registers. Pointer authentication can't be enabled here or the
 	 * authentication will fail when returning from this function.
 	 */
-	assert(is_armv8_3_pauth_api_present());
+	assert(is_armv8_3_pauth_apa_api_present());
 
 	uint64_t *apiakey = plat_init_apiakey();
 
diff --git a/docs/cpu-specific-build-macros.rst b/docs/cpu-specific-build-macros.rst
index 81738d8..ca3366d 100644
--- a/docs/cpu-specific-build-macros.rst
+++ b/docs/cpu-specific-build-macros.rst
@@ -71,6 +71,22 @@
 The value of the build flags is 0 by default, that is, disabled. A value of 1
 will enable it.
 
+For Cortex-A15, the following errata build flags are defined :
+
+-  ``ERRATA_A15_816470``: This applies errata 816470 workaround to Cortex-A15
+   CPU. This needs to be enabled only for revision >= r3p0 of the CPU.
+
+-  ``ERRATA_A15_827671``: This applies errata 827671 workaround to Cortex-A15
+   CPU. This needs to be enabled only for revision >= r3p0 of the CPU.
+
+For Cortex-A17, the following errata build flags are defined :
+
+-  ``ERRATA_A17_852421``: This applies errata 852421 workaround to Cortex-A17
+   CPU. This needs to be enabled only for revision <= r1p2 of the CPU.
+
+-  ``ERRATA_A17_852423``: This applies errata 852423 workaround to Cortex-A17
+   CPU. This needs to be enabled only for revision <= r1p2 of the CPU.
+
 For Cortex-A53, the following errata build flags are defined :
 
 -  ``ERRATA_A53_819472``: This applies errata 819472 workaround to all
@@ -166,6 +182,9 @@
 
 For Cortex-A73, the following errata build flags are defined :
 
+-  ``ERRATA_A73_852427``: This applies errata 852427 workaround to Cortex-A73
+   CPU. This needs to be enabled only for revision r0p0 of the CPU.
+
 -  ``ERRATA_A73_855423``: This applies errata 855423 workaround to Cortex-A73
    CPU. This needs to be enabled only for revision <= r0p1 of the CPU.
 
diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst
index 266de27..52520ea 100644
--- a/docs/firmware-design.rst
+++ b/docs/firmware-design.rst
@@ -2031,7 +2031,6 @@
 
         /*
          * Index of the parent power domain node.
-         * TODO: Figure out whether to whether using pointer is more efficient.
          */
         unsigned int parent_node;
 
@@ -2522,7 +2521,7 @@
 controlling them.
 
 In general, and unless individually mentioned, the build options
-``ARM_ARCH_MAJOR`` and ``ARM_ARCH_MINOR`` selects the Architecture Extension to
+``ARM_ARCH_MAJOR`` and ``ARM_ARCH_MINOR`` select the Architecture Extension to
 target when building TF-A. Subsequent Arm Architecture Extensions are backward
 compatible with previous versions.
 
@@ -2571,6 +2570,10 @@
    ``CTX_INCLUDE_PAUTH_REGS`` to 1. This enables pointer authentication in BL1,
    BL2, BL31, and the TSP if it is used.
 
+   If ``ARM_ARCH_MAJOR == 8`` and ``ARM_ARCH_MINOR >= 3`` the code footprint of
+   enabling PAuth is lower because the compiler will use the optimized
+   PAuth instructions rather than the backwards-compatible ones.
+
 Armv7-A
 ~~~~~~~
 
diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst
new file mode 100644
index 0000000..7a4ff0e
--- /dev/null
+++ b/docs/frequently-asked-questions.rst
@@ -0,0 +1,91 @@
+Frequently-Asked Questions (FAQ)
+================================
+
+How do I update a Pull Request?
+-------------------------------
+
+Often it is necessary to update a Pull Request (PR) before it is merged.  When
+you push to the source topic branch of an open PR, the PR is automatically
+updated with the new commits.
+
+If you need to modify existing commits in the PR (for example following review
+comments), then use the ``--force`` option when pushing. Any comments that apply
+to previous versions of the PR are retained in the PR. Sometimes it may be
+confusing whether comments apply to the current or a previous version of the PR,
+especially if there are several rounds of rework. In this case, you may be asked
+to close the PR and create a new one with the latest commits. The new PR should
+have a version appended to the name (e.g. "My topic v2") and you should create a
+link to the old PR so that reviewers can easily find previous versions.
+
+When the PR is finally merged, you will be given the option of deleting your
+topic branch. It is recommended you delete this (and any previous topic branch
+versions) to avoid polluting your fork with obsolete branches.
+
+How long will my Pull Request take to merge?
+--------------------------------------------
+
+This can vary a lot, depending on:
+
+* How important the Pull Request (PR) is considered by the TF maintainers. Where
+  possible, you should indicate the required timescales for merging the PR and
+  the impact of any delay.
+
+* The quality of the PR. PRs are likely to be merged quicker if they follow the
+  coding guidelines, have already had some code review, and have been
+  appropriately tested. Note that PRs from Arm engineers go through an internal
+  review process before appearing on GitHub, therefore may appear to be merged
+  more quickly.
+
+* The impact of the PR. For example, a PR that changes a key generic API is
+  likely to receive much greater scrutiny than a local change to a specific
+  platform port.
+
+* How much opportunity for external review is required. For example, the TF
+  maintainers may not wait for external review comments to merge trivial
+  bug-fixes but may wait up to a week to merge major changes, or ones requiring
+  feedback from specific parties.
+
+* How many other topics need to be integrated and the risk of conflict between
+  the topics.
+
+* Is there a code freeze in place in preparation for the release. Please refer
+  the `release information`_ for more details.
+
+* The workload of the TF maintainers.
+
+Feel free to add a comment to your PR to get an estimate of when it will
+be merged.
+
+How long will it take for my merged Pull Request to go from ``integration`` to ``master``?
+------------------------------------------------------------------------------------------
+
+This depends on how many concurrent Pull Requests (PRs) are being processed at
+the same time. In simple cases where all potential regressions have already been
+tested, the delay will be less than 1 day.  If the TF maintainers are trying to
+merge several things over the course of a few days, it might take up to a week.
+Typically, it will be 1-2 days.
+
+The worst case is if the TF maintainers are trying to make a release while also
+receiving PRs that will not be merged into the release. In this case, the PRs
+will be merged onto ``integration``, which will temporarily diverge from the
+release branch. The ``integration`` branch will be rebased onto ``master`` after
+the release, and then ``master`` will be fast-forwarded to ``integration`` 1-2
+days later. This whole process could take up 4 weeks. Please refer the `release
+information`_ for code freeze dates. The TF maintainers will inform the PR owner
+if this is going to happen.
+
+It is OK to create a PR based on commits that are only available in
+``integration`` or another PR, rather than ``master``. There is a risk that the
+dependency commits will change (for example due to PR rework or integration
+problems). If this happens, the dependent PR will need reworking.
+
+What are these strange comments in my Pull Request?
+---------------------------------------------------
+
+For example, comments like "Can one of the admins verify this patch?" or "test
+this please". These are associated with Arm's Continuous Integration
+infrastructure and can be safely ignored. Those who are curious can see the
+documentation for `this Jenkins plugin`_ for more details.
+
+.. _release information: release-information.rst
+.. _this Jenkins plugin: https://wiki.jenkins-ci.org/display/JENKINS/GitHub+pull+request+builder+plugin
diff --git a/docs/image-terminology.rst b/docs/image-terminology.rst
new file mode 100644
index 0000000..4dc1d73
--- /dev/null
+++ b/docs/image-terminology.rst
@@ -0,0 +1,180 @@
+Image Terminology
+=================
+
+.. section-numbering::
+    :suffix: .
+
+.. contents::
+
+This page contains the current name, abbreviated name and purpose of the various
+images referred to in the Trusted Firmware project.
+
+General Notes
+-------------
+
+- Some of the names and abbreviated names have changed to accomodate new
+  requirements. The changed names are as backward compatible as possible to
+  minimize confusion. Where applicable, the previous names are indicated. Some
+  code, documentation and build artefacts may still refer to the previous names;
+  these will inevitably take time to catch up.
+
+- The main name change is to prefix each image with the processor it corresponds
+  to (for example ``AP_``, ``SCP_``, ...). In situations where there is no
+  ambiguity (for example, within AP specific code/documentation), it is
+  permitted to omit the processor prefix (for example, just BL1 instead of
+  ``AP_BL1``).
+
+- Previously, the format for 3rd level images had 2 forms; ``BL3`` was either
+  suffixed with a dash ("-") followed by a number (for example, ``BL3-1``) or a
+  subscript number, depending on whether rich text formatting was available.
+  This was confusing and often the dash gets omitted in practice. Therefore the
+  new form is to just omit the dash and not use subscript formatting.
+
+- The names no longer contain dash ("-") characters at all. In some places (for
+  example, function names) it's not possible to use this character. All dashes
+  are either removed or replaced by underscores ("_").
+
+- The abbreviation BL stands for BootLoader. This is a historical anomaly.
+  Clearly, many of these images are not BootLoaders, they are simply firmware
+  images. However, the BL abbreviation is now widely used and is retained for
+  backwards compatibility.
+
+- The image names are not case sensitive. For example, ``bl1`` is
+  interchangeable with ``BL1``, although mixed case should be avoided.
+
+Trusted Firmware Images
+-----------------------
+
+AP Boot ROM: ``AP_BL1``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Typically, this is the first code to execute on the AP and cannot be modified.
+Its primary purpose is to perform the minimum intialization necessary to load
+and authenticate an updateable AP firmware image into an executable RAM
+location, then hand-off control to that image.
+
+AP RAM Firmware: ``AP_BL2``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is the 2nd stage AP firmware. It is currently also known as the "Trusted
+Boot Firmware". Its primary purpose is to perform any additional initialization
+required to load and authenticate all 3rd level firmware images into their
+executable RAM locations, then hand-off control to the EL3 Runtime Firmware.
+
+EL3 Runtime Firmware: ``AP_BL31``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Also known as "SoC AP firmware" or "EL3 monitor firmware". Its primary purpose
+is to handle transitions between the normal and secure world.
+
+Secure-EL1 Payload (SP): ``AP_BL32``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Typically this is a TEE or Trusted OS, providing runtime secure services to the
+normal world. However, it may refer to a more abstract Secure-EL1 Payload (SP).
+Note that this abbreviation should only be used in systems where there is a
+single or primary image executing at Secure-EL1. In systems where there are
+potentially multiple SPs and there is no concept of a primary SP, this
+abbreviation should be avoided; use the recommended **Other AP 3rd level
+images** abbreviation instead.
+
+AP Normal World Firmware: ``AP_BL33``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For example, UEFI or uboot. Its primary purpose is to boot a normal world OS.
+
+Other AP 3rd level images: ``AP_BL3_XXX``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The abbreviated names of the existing 3rd level images imply a load/execution
+ordering (for example, ``AP_BL31 -> AP_BL32 -> AP_BL33``).  Some systems may
+have additional images and/or a different load/execution ordering. The
+abbreviated names of the existing images are retained for backward compatibility
+but new 3rd level images should be suffixed with an underscore followed by text
+identifier, not a number.
+
+In systems where 3rd level images are provided by different vendors, the
+abbreviated name should identify the vendor as well as the image
+function. For example, ``AP_BL3_ARM_RAS``.
+
+SCP Boot ROM: ``SCP_BL1`` (previously ``BL0``)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Typically, this is the first code to execute on the SCP and cannot be modified.
+Its primary purpose is to perform the minimum intialization necessary to load
+and authenticate an updateable SCP firmware image into an executable RAM
+location, then hand-off control to that image. This may be performed in
+conjunction with other processor firmware (for example, ``AP_BL1`` and
+``AP_BL2``).
+
+This image was previously abbreviated as ``BL0`` but in some systems, the SCP
+may directly load/authenticate its own firmware. In these systems, it doesn't
+make sense to interleave the image terminology for AP and SCP; both AP and SCP
+Boot ROMs are ``BL1`` from their own point of view.
+
+SCP RAM Firmware: ``SCP_BL2`` (previously ``BL3-0``)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is the 2nd stage SCP firmware. It is currently also known as the "SCP
+runtime firmware" but it could potentially be an intermediate firmware if the
+SCP needs to load/authenticate multiple 3rd level images in future.
+
+This image was previously abbreviated as BL3-0 but from the SCP's point of view,
+this has always been the 2nd stage firmware. The previous name is too
+AP-centric.
+
+Firmware Update (FWU) Images
+----------------------------
+
+The terminology for these images has not been widely adopted yet but they have
+to be considered in a production Trusted Board Boot solution.
+
+AP Firmware Update Boot ROM: ``AP_NS_BL1U``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Typically, this is the first normal world code to execute on the AP during a
+firmware update operation, and cannot be modified. Its primary purpose is to
+load subequent firmware update images from an external interface and communicate
+with ``AP_BL1`` to authenticate those images.
+
+During firmware update, there are (potentially) multiple transitions between the
+secure and normal world. The "level" of the BL image is relative to the world
+it's in so it makes sense to encode "NS" in the normal world images. The absence
+of "NS" implies a secure world image.
+
+AP Firmware Update Config: ``AP_BL2U``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This image does the minimum necessary AP secure world configuration required to
+complete the firmware update operation. It is potentially a subset of ``AP_BL2``
+functionality.
+
+SCP Firmware Update Config: ``SCP_BL2U`` (previously ``BL2-U0``)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This image does the minimum necessary SCP secure world configuration required to
+complete the firmware update operation. It is potentially a subset of
+``SCP_BL2`` functionality.
+
+AP Firmware Updater: ``AP_NS_BL2U`` (previously ``BL3-U``)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is the 2nd stage AP normal world firmware updater. Its primary purpose is
+to load a new set of firmware images from an external interface and write them
+into non-volatile storage.
+
+Other Processor Firmware Images
+-------------------------------
+
+Some systems may have additional processors to the AP and SCP. For example, a
+Management Control Processor (MCP). Images for these processors should follow
+the same terminology, with the processor abbreviation prefix, followed by
+underscore and the level of the firmware image.
+
+For example,
+
+MCP Boot ROM: ``MCP_BL1``
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+MCP RAM Firmware: ``MCP_BL2``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/interrupt-framework-design.rst b/docs/interrupt-framework-design.rst
index 52d1ed4..58130cd 100644
--- a/docs/interrupt-framework-design.rst
+++ b/docs/interrupt-framework-design.rst
@@ -89,8 +89,9 @@
 following sub-sections describe all the possible routing models and specify
 which ones are valid or invalid. EL3 interrupts are currently supported only
 for GIC version 3.0 (Arm GICv3) and only the Secure-EL1 and Non-secure interrupt
-types are supported for GIC version 2.0 (Arm GICv2) (See 1.2). The terminology
-used in the following sub-sections is explained below.
+types are supported for GIC version 2.0 (Arm GICv2) (see `Assumptions in
+Interrupt Management Framework`_). The terminology used in the following
+sub-sections is explained below.
 
 #. **CSS**. Current Security State. ``0`` when secure and ``1`` when non-secure
 
@@ -230,8 +231,8 @@
 
 Both aspects of interrupt management involve various components in the secure
 software stack spanning from EL3 to Secure-EL1. These components are described
-in the section 2.1. The framework stores information associated with each type
-of interrupt in the following data structure.
+in the section `Software components`_. The framework stores information
+associated with each type of interrupt in the following data structure.
 
 .. code:: c
 
@@ -244,11 +245,11 @@
 The ``flags`` field stores the routing model for the interrupt type in
 bits[1:0]. Bit[0] stores the routing model when execution is in the secure
 state. Bit[1] stores the routing model when execution is in the non-secure
-state. As mentioned in Section 1.2.2, a value of ``0`` implies that the interrupt
-should be targeted to the FEL. A value of ``1`` implies that it should be targeted
-to EL3. The remaining bits are reserved and SBZ. The helper macro
-``set_interrupt_rm_flag()`` should be used to set the bits in the ``flags``
-parameter.
+state. As mentioned in Section `Routing model`_, a value of ``0`` implies that
+the interrupt should be targeted to the FEL. A value of ``1`` implies that it
+should be targeted to EL3. The remaining bits are reserved and SBZ. The helper
+macro ``set_interrupt_rm_flag()`` should be used to set the bits in the
+``flags`` parameter.
 
 The ``scr_el3[2]`` field also stores the routing model but as a mapping of the
 model in the ``flags`` field to the corresponding bit in the ``SCR_EL3`` for each
@@ -302,8 +303,9 @@
 Interrupt registration
 ----------------------
 
-This section describes in detail the role of each software component (see 2.1)
-during the registration of a handler for an interrupt type.
+This section describes in detail the role of each software component (see
+`Software components`_) during the registration of a handler for an interrupt
+type.
 
 EL3 runtime firmware
 ~~~~~~~~~~~~~~~~~~~~
@@ -395,6 +397,8 @@
 responsible for ensuring that the routing model has been adhered to upon
 receiving an interrupt.
 
+.. _spd-int-registration:
+
 Secure payload dispatcher
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -487,6 +491,8 @@
        if (rc)
            panic();
 
+.. _sp-int-registration:
+
 Secure payload
 ~~~~~~~~~~~~~~
 
@@ -512,10 +518,10 @@
 both these interrupt handling models depending upon the chosen routing model.
 
 The following list briefly describes how the choice of a valid routing model
-(See 1.2.3) effects the implementation of the Secure-EL1 IHF. If the choice of
-the interrupt routing model is not known to the SPD service at compile time,
-then the SP should pass this information to the SPD service at runtime during
-its initialisation phase.
+(see `Valid routing models`_) effects the implementation of the Secure-EL1
+IHF. If the choice of the interrupt routing model is not known to the SPD
+service at compile time, then the SP should pass this information to the SPD
+service at runtime during its initialisation phase.
 
 As mentioned earlier, an Arm GICv2 system is considered and it is assumed that
 the FIQ signal is used to generate Secure-EL1 interrupts and the IRQ signal
@@ -584,7 +590,10 @@
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The routing model for Secure-EL1 and non-secure interrupts chosen by the TSP is
-described in Section 2.2.2. It is known to the TSPD service at build time.
+described in Section `Secure Payload Dispatcher`__. It is known to the TSPD
+service at build time.
+
+.. __: #spd-int-registration
 
 The TSP implements an entrypoint (``tsp_sel1_intr_entry()``) for handling Secure-EL1
 interrupts taken in non-secure state and routed through the TSPD service
@@ -599,13 +608,14 @@
 
 The TSP also programs the Secure Physical Timer in the Arm Generic Timer block
 to raise a periodic interrupt (every half a second) for the purpose of testing
-interrupt management across all the software components listed in 2.1
+interrupt management across all the software components listed in `Software
+components`_.
 
 Interrupt handling
 ------------------
 
 This section describes in detail the role of each software component (see
-Section 2.1) in handling an interrupt of a particular type.
+Section `Software components`_) in handling an interrupt of a particular type.
 
 EL3 runtime firmware
 ~~~~~~~~~~~~~~~~~~~~
@@ -769,7 +779,7 @@
    will be trashed, which is the ``ELR_EL3`` and ``SPSR_EL3``, in order to be able
    to re-enter TSP for Secure-EL1 interrupt processing. It does not need to
    save any other secure context since the TSP is expected to preserve it
-   (see Section 2.2.2.1).
+   (see section `Test secure payload dispatcher behavior`_).
 
 #. It restores the system register context for the secure state by calling
    ``cm_el1_sysregs_context_restore(SECURE);``.
@@ -823,21 +833,21 @@
 It should be noted that while TSP is preempted, the TSPD only allows entry into
 the TSP either for Secure-EL1 interrupt handling or for resuming the preempted
 ``yielding`` SMC in response to the ``TSP_FID_RESUME`` SMC from the normal world.
-(See Section 3).
+(See Section `Implication of preempted SMC on Non-Secure Software`_).
 
-The non-secure interrupt triggered in Secure-EL1 during ``yielding`` SMC processing
-can be routed to either EL3 or Secure-EL1 and is controlled by build option
-``TSP_NS_INTR_ASYNC_PREEMPT`` (see Section 2.2.2.1). If the build option is set,
-the TSPD will set the routing model for the non-secure interrupt to be routed to
-EL3 from secure state i.e. **TEL3=1, CSS=0** and registers
-``tspd_ns_interrupt_handler()`` as the non-secure interrupt handler. The
-``tspd_ns_interrupt_handler()`` on being invoked ensures that the interrupt
-originated from the secure state and disables routing of non-secure interrupts
-from secure state to EL3. This is to prevent further preemption (by a non-secure
-interrupt) when TSP is reentered for handling Secure-EL1 interrupts that
-triggered while execution was in the normal world. The
-``tspd_ns_interrupt_handler()`` then invokes ``tspd_handle_sp_preemption()`` for
-further handling.
+The non-secure interrupt triggered in Secure-EL1 during ``yielding`` SMC
+processing can be routed to either EL3 or Secure-EL1 and is controlled by build
+option ``TSP_NS_INTR_ASYNC_PREEMPT`` (see Section `Test secure payload
+dispatcher behavior`_). If the build option is set, the TSPD will set the
+routing model for the non-secure interrupt to be routed to EL3 from secure state
+i.e. **TEL3=1, CSS=0** and registers ``tspd_ns_interrupt_handler()`` as the
+non-secure interrupt handler. The ``tspd_ns_interrupt_handler()`` on being
+invoked ensures that the interrupt originated from the secure state and disables
+routing of non-secure interrupts from secure state to EL3. This is to prevent
+further preemption (by a non-secure interrupt) when TSP is reentered for
+handling Secure-EL1 interrupts that triggered while execution was in the normal
+world. The ``tspd_ns_interrupt_handler()`` then invokes
+``tspd_handle_sp_preemption()`` for further handling.
 
 If the ``TSP_NS_INTR_ASYNC_PREEMPT`` build option is zero (default), the default
 routing model for non-secure interrupt in secure state is in effect
@@ -866,10 +876,11 @@
 #. ``SMC_PREEMPTED`` is set in x0 and return to non secure state after
    restoring non secure context.
 
-The Normal World is expected to resume the TSP after the ``yielding`` SMC preemption
-by issuing an SMC with ``TSP_FID_RESUME`` as the function identifier (see section 3).
-The TSPD service takes the following actions in ``tspd_smc_handler()`` function
-upon receiving this SMC:
+The Normal World is expected to resume the TSP after the ``yielding`` SMC
+preemption by issuing an SMC with ``TSP_FID_RESUME`` as the function identifier
+(see section `Implication of preempted SMC on Non-Secure Software`_).  The TSPD
+service takes the following actions in ``tspd_smc_handler()`` function upon
+receiving this SMC:
 
 #. It ensures that the call originated from the non secure state. An
    assertion is raised otherwise.
@@ -898,16 +909,18 @@
 
 The SP should implement one or both of the synchronous and asynchronous
 interrupt handling models depending upon the interrupt routing model it has
-chosen (as described in 2.2.3).
+chosen (as described in section `Secure Payload`__).
+
+.. __: #sp-int-registration
 
 In the synchronous model, it should begin handling a Secure-EL1 interrupt after
 receiving control from the SPD service at an entrypoint agreed upon during build
 time or during the registration phase. Before handling the interrupt, the SP
 should save any Secure-EL1 system register context which is needed for resuming
-normal execution in the SP later e.g. ``SPSR_EL1,``\ ELR_EL1\`. After handling the
-interrupt, the SP could return control back to the exception level and security
-state where the interrupt was originally taken from. The SP should use an SMC32
-or SMC64 to ask the SPD service to do this.
+normal execution in the SP later e.g. ``SPSR_EL1``, ``ELR_EL1``. After handling
+the interrupt, the SP could return control back to the exception level and
+security state where the interrupt was originally taken from. The SP should use
+an SMC32 or SMC64 to ask the SPD service to do this.
 
 In the asynchronous model, the Secure Payload is responsible for handling
 non-secure and Secure-EL1 interrupts at the IRQ and FIQ vectors in its exception
@@ -922,8 +935,9 @@
 
 The TSPD hands control of a Secure-EL1 interrupt to the TSP at the
 ``tsp_sel1_intr_entry()``. The TSP handles the interrupt while ensuring that the
-handover agreement described in Section 2.2.2.1 is maintained. It updates some
-statistics by calling ``tsp_update_sync_sel1_intr_stats()``. It then calls
+handover agreement described in Section `Test secure payload dispatcher
+behavior`_ is maintained. It updates some statistics by calling
+``tsp_update_sync_sel1_intr_stats()``. It then calls
 ``tsp_common_int_handler()`` which.
 
 #. Checks whether the interrupt is the secure physical timer interrupt. It
@@ -947,18 +961,19 @@
 #. Secure-EL1 interrupts are handled by calling the ``tsp_common_int_handler()``
    function. The function has been described above.
 
-#. Non-secure interrupts are handled by by calling the ``tsp_common_int_handler()``
+#. Non-secure interrupts are handled by calling the ``tsp_common_int_handler()``
    function which ends up invoking ``tsp_handle_preemption()`` and issuing an
    SMC64 with ``TSP_PREEMPTED`` as the function identifier. Execution resumes at
-   the instruction that follows this SMC instruction when the TSPD hands
-   control to the TSP in response to an SMC with ``TSP_FID_RESUME`` as the
-   function identifier from the non-secure state (see section 2.3.2.4).
+   the instruction that follows this SMC instruction when the TSPD hands control
+   to the TSP in response to an SMC with ``TSP_FID_RESUME`` as the function
+   identifier from the non-secure state (see section `Test secure payload
+   dispatcher non-secure interrupt handling`_).
 
-#. .. rubric:: Other considerations
-      :name: other-considerations
+Other considerations
+--------------------
 
 Implication of preempted SMC on Non-Secure Software
----------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 A ``yielding`` SMC call to Secure payload can be preempted by a non-secure
 interrupt and the execution can return to the non-secure world for handling
@@ -1001,7 +1016,7 @@
 
 --------------
 
-*Copyright (c) 2014-2018, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2014-2019, Arm Limited and Contributors. All rights reserved.*
 
 .. _Porting Guide: ./porting-guide.rst
 .. _SMC calling convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
diff --git a/docs/plat/imx8m.rst b/docs/plat/imx8m.rst
index ab33a8a..a69f022 100644
--- a/docs/plat/imx8m.rst
+++ b/docs/plat/imx8m.rst
@@ -31,6 +31,7 @@
        CROSS_COMPILE=aarch64-linux-gnu- make PLAT=<Target_SoC> bl31
 
    Target_SoC should be "imx8mq" for i.MX8MQ SoC.
+   Target_SoC should be "imx8mm" for i.MX8MM SoC.
 
 Deploy TF-A Images
 -----------------
diff --git a/docs/plat/nvidia-tegra.rst b/docs/plat/nvidia-tegra.rst
index 7ed0f2c..6a03b12 100644
--- a/docs/plat/nvidia-tegra.rst
+++ b/docs/plat/nvidia-tegra.rst
@@ -82,6 +82,16 @@
 Tegra210: TLK and Trusty
 Tegra186: Trusty
 
+Scatter files
+=============
+
+Tegra platforms currently support scatter files and ld.S scripts. The scatter
+files help support ARMLINK linker to generate BL31 binaries. For now, there
+exists a common scatter file, plat/nvidia/tegra/scat/bl31.scat, for all Tegra
+SoCs. The `LINKER` build variable needs to point to the ARMLINK binary for
+the scatter file to be used. Tegra platforms have verified BL31 image generation
+with ARMCLANG (compilation) and ARMLINK (linking) for the Tegra186 platforms.
+
 Preparing the BL31 image to run on Tegra SoCs
 =============================================
 
diff --git a/docs/psci-performance-juno.rst b/docs/psci-performance-juno.rst
new file mode 100644
index 0000000..caed8bf
--- /dev/null
+++ b/docs/psci-performance-juno.rst
@@ -0,0 +1,288 @@
+PSCI Performance Measurements on Arm Juno Development Platform
+==============================================================
+
+This document summarises the findings of performance measurements of key
+operations in the ARM Trusted Firmware (TF) Power State Coordination Interface
+(PSCI) implementation, using the in-built Performance Measurement Framework
+(PMF) and runtime instrumentation timestamps.
+
+Method
+------
+
+We used the `Juno R1 platform`_ for these tests, which has 4 x Cortex-A53 and 2
+x Cortex-A57 clusters running at the following frequencies:
+
++-----------------+--------------------+
+| Domain          | Frequency (MHz)    |
++=================+====================+
+| Cortex-A57      | 900 (nominal)      |
++-----------------+--------------------+
+| Cortex-A53      | 650 (underdrive)   |
++-----------------+--------------------+
+| AXI subsystem   | 533                |
++-----------------+--------------------+
+
+Juno supports CPU, cluster and system power down states, corresponding to power
+levels 0, 1 and 2 respectively. It does not support any retention states.
+
+We used the upstream `TF master as of 31/01/2017`_, building the platform using
+the ``ENABLE_RUNTIME_INSTRUMENTATION`` option:
+
+::
+
+    make PLAT=juno ENABLE_RUNTIME_INSTRUMENTATION=1 \
+        SCP_BL2=<path/to/scp-fw.bin>                \
+        BL33=<path/to/test-fw.bin>                  \
+        all fip
+
+When using the debug build of TF, there was no noticeable difference in the
+results.
+
+The tests are based on an ARM-internal test framework. The release build of this
+framework was used because the results in the debug build became skewed; the
+console output prevented some of the tests from executing in parallel.
+
+The tests consist of both parallel and sequential tests, which are broadly
+described as follows:
+
+- **Parallel Tests** This type of test powers on all the non-lead CPUs and
+  brings them and the lead CPU to a common synchronization point.  The lead CPU
+  then initiates the test on all CPUs in parallel.
+
+- **Sequential Tests** This type of test powers on each non-lead CPU in
+  sequence. The lead CPU initiates the test on a non-lead CPU then waits for the
+  test to complete before proceeding to the next non-lead CPU. The lead CPU then
+  executes the test on itself.
+
+In the results below, CPUs 0-3 refer to CPUs in the little cluster (A53) and
+CPUs 4-5 refer to CPUs in the big cluster (A57). In all cases CPU 4 is the lead
+CPU.
+
+``PSCI_ENTRY`` refers to the time taken from entering the TF PSCI implementation
+to the point the hardware enters the low power state (WFI). Referring to the TF
+runtime instrumentation points, this corresponds to:
+``(RT_INSTR_ENTER_HW_LOW_PWR - RT_INSTR_ENTER_PSCI)``.
+
+``PSCI_EXIT`` refers to the time taken from the point the hardware exits the low
+power state to exiting the TF PSCI implementation. This corresponds to:
+``(RT_INSTR_EXIT_PSCI - RT_INSTR_EXIT_HW_LOW_PWR)``.
+
+``CFLUSH_OVERHEAD`` refers to the part of ``PSCI_ENTRY`` taken to flush the
+caches. This corresponds to: ``(RT_INSTR_EXIT_CFLUSH - RT_INSTR_ENTER_CFLUSH)``.
+
+Note there is very little variance observed in the values given (~1us), although
+the values for each CPU are sometimes interchanged, depending on the order in
+which locks are acquired. Also, there is very little variance observed between
+executing the tests sequentially in a single boot or rebooting between tests.
+
+Given that runtime instrumentation using PMF is invasive, there is a small
+(unquantified) overhead on the results. PMF uses the generic counter for
+timestamps, which runs at 50MHz on Juno.
+
+Results and Commentary
+----------------------
+
+``CPU_SUSPEND`` to deepest power level on all CPUs in parallel
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
++-------+---------------------+--------------------+--------------------------+
+| CPU   | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) |
++=======+=====================+====================+==========================+
+| 0     | 27                  | 20                 | 5                        |
++-------+---------------------+--------------------+--------------------------+
+| 1     | 114                 | 86                 | 5                        |
++-------+---------------------+--------------------+--------------------------+
+| 2     | 202                 | 58                 | 5                        |
++-------+---------------------+--------------------+--------------------------+
+| 3     | 375                 | 29                 | 94                       |
++-------+---------------------+--------------------+--------------------------+
+| 4     | 20                  | 22                 | 6                        |
++-------+---------------------+--------------------+--------------------------+
+| 5     | 290                 | 18                 | 206                      |
++-------+---------------------+--------------------+--------------------------+
+
+A large variance in ``PSCI_ENTRY`` and ``PSCI_EXIT`` times across CPUs is
+observed due to TF PSCI lock contention. In the worst case, CPU 3 has to wait
+for the 3 other CPUs in the cluster (0-2) to complete ``PSCI_ENTRY`` and release
+the lock before proceeding.
+
+The ``CFLUSH_OVERHEAD`` times for CPUs 3 and 5 are higher because they are the
+last CPUs in their respective clusters to power down, therefore both the L1 and
+L2 caches are flushed.
+
+The ``CFLUSH_OVERHEAD`` time for CPU 5 is a lot larger than that for CPU 3
+because the L2 cache size for the big cluster is lot larger (2MB) compared to
+the little cluster (1MB).
+
+``CPU_SUSPEND`` to power level 0 on all CPUs in parallel
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
++-------+---------------------+--------------------+--------------------------+
+| CPU   | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) |
++=======+=====================+====================+==========================+
+| 0     | 116                 | 14                 | 8                        |
++-------+---------------------+--------------------+--------------------------+
+| 1     | 204                 | 14                 | 8                        |
++-------+---------------------+--------------------+--------------------------+
+| 2     | 287                 | 13                 | 8                        |
++-------+---------------------+--------------------+--------------------------+
+| 3     | 376                 | 13                 | 9                        |
++-------+---------------------+--------------------+--------------------------+
+| 4     | 29                  | 15                 | 7                        |
++-------+---------------------+--------------------+--------------------------+
+| 5     | 21                  | 15                 | 8                        |
++-------+---------------------+--------------------+--------------------------+
+
+There is no lock contention in TF generic code at power level 0 but the large
+variance in ``PSCI_ENTRY`` times across CPUs is due to lock contention in Juno
+platform code. The platform lock is used to mediate access to a single SCP
+communication channel. This is compounded by the SCP firmware waiting for each
+AP CPU to enter WFI before making the channel available to other CPUs, which
+effectively serializes the SCP power down commands from all CPUs.
+
+On platforms with a more efficient CPU power down mechanism, it should be
+possible to make the ``PSCI_ENTRY`` times smaller and consistent.
+
+The ``PSCI_EXIT`` times are consistent across all CPUs because TF does not
+require locks at power level 0.
+
+The ``CFLUSH_OVERHEAD`` times for all CPUs are small and consistent since only
+the cache associated with power level 0 is flushed (L1).
+
+``CPU_SUSPEND`` to deepest power level on all CPUs in sequence
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
++-------+---------------------+--------------------+--------------------------+
+| CPU   | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) |
++=======+=====================+====================+==========================+
+| 0     | 114                 | 20                 | 94                       |
++-------+---------------------+--------------------+--------------------------+
+| 1     | 114                 | 20                 | 94                       |
++-------+---------------------+--------------------+--------------------------+
+| 2     | 114                 | 20                 | 94                       |
++-------+---------------------+--------------------+--------------------------+
+| 3     | 114                 | 20                 | 94                       |
++-------+---------------------+--------------------+--------------------------+
+| 4     | 195                 | 22                 | 180                      |
++-------+---------------------+--------------------+--------------------------+
+| 5     | 21                  | 17                 | 6                        |
++-------+---------------------+--------------------+--------------------------+
+
+The ``CLUSH_OVERHEAD`` times for lead CPU 4 and all CPUs in the non-lead cluster
+are large because all other CPUs in the cluster are powered down during the
+test. The ``CPU_SUSPEND`` call powers down to the cluster level, requiring a
+flush of both L1 and L2 caches.
+
+The ``CFLUSH_OVERHEAD`` time for CPU 4 is a lot larger than those for the little
+CPUs because the L2 cache size for the big cluster is lot larger (2MB) compared
+to the little cluster (1MB).
+
+The ``PSCI_ENTRY`` and ``CFLUSH_OVERHEAD`` times for CPU 5 are low because lead
+CPU 4 continues to run while CPU 5 is suspended. Hence CPU 5 only powers down to
+level 0, which only requires L1 cache flush.
+
+``CPU_SUSPEND`` to power level 0 on all CPUs in sequence
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
++-------+---------------------+--------------------+--------------------------+
+| CPU   | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) |
++=======+=====================+====================+==========================+
+| 0     | 22                  | 14                 | 5                        |
++-------+---------------------+--------------------+--------------------------+
+| 1     | 22                  | 14                 | 5                        |
++-------+---------------------+--------------------+--------------------------+
+| 2     | 21                  | 14                 | 5                        |
++-------+---------------------+--------------------+--------------------------+
+| 3     | 22                  | 14                 | 5                        |
++-------+---------------------+--------------------+--------------------------+
+| 4     | 17                  | 14                 | 6                        |
++-------+---------------------+--------------------+--------------------------+
+| 5     | 18                  | 15                 | 6                        |
++-------+---------------------+--------------------+--------------------------+
+
+Here the times are small and consistent since there is no contention and it is
+only necessary to flush the cache to power level 0 (L1). This is the best case
+scenario.
+
+The ``PSCI_ENTRY`` times for CPUs in the big cluster are slightly smaller than
+for the CPUs in little cluster due to greater CPU performance.
+
+The ``PSCI_EXIT`` times are generally lower than in the last test because the
+cluster remains powered on throughout the test and there is less code to execute
+on power on (for example, no need to enter CCI coherency)
+
+``CPU_OFF`` on all non-lead CPUs in sequence then ``CPU_SUSPEND`` on lead CPU to deepest power level
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The test sequence here is as follows:
+
+1. Call ``CPU_ON`` and ``CPU_OFF`` on each non-lead CPU in sequence.
+
+2. Program wake up timer and suspend the lead CPU to the deepest power level.
+
+3. Call ``CPU_ON`` on non-lead CPU to get the timestamps from each CPU.
+
++-------+---------------------+--------------------+--------------------------+
+| CPU   | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) |
++=======+=====================+====================+==========================+
+| 0     | 110                 | 28                 | 93                       |
++-------+---------------------+--------------------+--------------------------+
+| 1     | 110                 | 28                 | 93                       |
++-------+---------------------+--------------------+--------------------------+
+| 2     | 110                 | 28                 | 93                       |
++-------+---------------------+--------------------+--------------------------+
+| 3     | 111                 | 28                 | 93                       |
++-------+---------------------+--------------------+--------------------------+
+| 4     | 195                 | 22                 | 181                      |
++-------+---------------------+--------------------+--------------------------+
+| 5     | 20                  | 23                 | 6                        |
++-------+---------------------+--------------------+--------------------------+
+
+The ``CFLUSH_OVERHEAD`` times for all little CPUs are large because all other
+CPUs in that cluster are powerered down during the test. The ``CPU_OFF`` call
+powers down to the cluster level, requiring a flush of both L1 and L2 caches.
+
+The ``PSCI_ENTRY`` and ``CFLUSH_OVERHEAD`` times for CPU 5 are small because
+lead CPU 4 is running and CPU 5 only powers down to level 0, which only requires
+an L1 cache flush.
+
+The ``CFLUSH_OVERHEAD`` time for CPU 4 is a lot larger than those for the little
+CPUs because the L2 cache size for the big cluster is lot larger (2MB) compared
+to the little cluster (1MB).
+
+The ``PSCI_EXIT`` times for CPUs in the big cluster are slightly smaller than
+for CPUs in the little cluster due to greater CPU performance.  These times
+generally are greater than the ``PSCI_EXIT`` times in the ``CPU_SUSPEND`` tests
+because there is more code to execute in the "on finisher" compared to the
+"suspend finisher" (for example, GIC redistributor register programming).
+
+``PSCI_VERSION`` on all CPUs in parallel
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Since very little code is associated with ``PSCI_VERSION``, this test
+approximates the round trip latency for handling a fast SMC at EL3 in TF.
+
++-------+-------------------+
+| CPU   | TOTAL TIME (ns)   |
++=======+===================+
+| 0     | 3020              |
++-------+-------------------+
+| 1     | 2940              |
++-------+-------------------+
+| 2     | 2980              |
++-------+-------------------+
+| 3     | 3060              |
++-------+-------------------+
+| 4     | 520               |
++-------+-------------------+
+| 5     | 720               |
++-------+-------------------+
+
+The times for the big CPUs are less than the little CPUs due to greater CPU
+performance.
+
+We suspect the time for lead CPU 4 is shorter than CPU 5 due to subtle cache
+effects, given that these measurements are at the nano-second level.
+
+.. _Juno R1 platform: https://www.arm.com/files/pdf/Juno_r1_ARM_Dev_datasheet.pdf
+.. _TF master as of 31/01/2017: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/?id=c38b36d
diff --git a/docs/release-information.rst b/docs/release-information.rst
new file mode 100644
index 0000000..5531150
--- /dev/null
+++ b/docs/release-information.rst
@@ -0,0 +1,89 @@
+TF-A Release Information
+========================
+
+.. section-numbering::
+    :suffix: .
+
+.. contents::
+
+--------------
+
+Project Release Cadence
+-----------------------
+
+The project currently aims to do a release once every 6 months which will be
+tagged on the master branch. There will be a code freeze (stop merging
+non-essential PRs) up to 4 weeks prior to the target release date. The release
+candidates will start appearing after this and only bug fixes or updates
+required for the release will be merged. The maintainers are free to use their
+judgement on what PRs are essential for the release. A release branch may be
+created after code freeze if there are significant PRs that need merging onto
+the integration branch during the merge window.
+
+The release testing will be performed on release candidates and depending on
+issues found, additional release candidates may be created to fix the issues.
+
+::
+
+                            |<----------6 months---------->|
+            |<---4 weeks--->|              |<---4 weeks--->|
+       +-----------------------------------------------------------> time
+            |               |              |               |
+         code freeze       ver w.x       code freeze     ver y.z
+
+
+Upcoming Releases
+~~~~~~~~~~~~~~~~~
+
+These are the estimated dates for the upcoming release. These may change
+depending on project requirement and partner feedback.
+
++-----------------+---------------------------+------------------------------+
+| Release Version |  Target Date              | Expected Code Freeze         |
++=================+===========================+==============================+
+| v2.0            | 1st week of Oct '18       | 1st week of Sep '18          |
++-----------------+---------------------------+------------------------------+
+| v2.1            | 5th week of Mar '19       | 1st week of Mar '19          |
++-----------------+---------------------------+------------------------------+
+
+Removal of Deprecated Interfaces
+--------------------------------
+
+As mentioned in the `Platform compatibility policy`_, this is a live document
+cataloging all the deprecated interfaces in TF-A project and the Release version
+after which it will be removed.
+
++--------------------------------+-------------+---------+---------------------------------------------------------+
+| Interface                      | Deprecation | Removed | Comments                                                |
+|                                | Date        | after   |                                                         |
+|                                |             | Release |                                                         |
++================================+=============+=========+=========================================================+
+| Legacy Console API             | Jan '18     | v2.1    | Deprecated in favour of ``MULTI_CONSOLE_API``           |
++--------------------------------+-------------+---------+---------------------------------------------------------+
+| Weak default                   | Oct '18     | v2.1    | The default implementations are defined in              |
+| ``plat_crash_console_*``       |             |         | `crash_console_helpers.S`_. The platforms have to       |
+| APIs                           |             |         | define ``plat_crash_console_*``.                        |
++--------------------------------+-------------+---------+---------------------------------------------------------+
+| ``finish_console_register``    | Oct '18     | v2.1    | The old version of the macro is deprecated. See commit  |
+| macro in                       |             |         | cc5859c_ for more details.                              |
+| ``MULTI_CONSOLE_API``          |             |         |                                                         |
++--------------------------------+-------------+---------+---------------------------------------------------------+
+| Types ``tzc_action_t`` and     | Oct '18     | v2.1    | Using logical operations such as OR in enumerations     |
+| ``tzc_region_attributes_t``    |             |         | goes against the MISRA guidelines.                      |
++--------------------------------+-------------+---------+---------------------------------------------------------+
+| Macro ``EL_IMPLEMENTED()``     | Oct '18     | v2.1    | Deprecated in favour of ``el_implemented()``.           |
++--------------------------------+-------------+---------+---------------------------------------------------------+
+| ``get_afflvl_shift()``,        | Dec '18     | v2.1    | Removed.                                                |
+| ``mpidr_mask_lower_afflvls()``,|             |         |                                                         |
+| and ``eret()``.                |             |         |                                                         |
++--------------------------------+-------------+---------+---------------------------------------------------------+
+| Extra include paths in the     | Jan '18     | v2.1    | Now it is needed to use the full path of the common     |
+| Makefile in ``INCLUDES``.      |             |         | header files. More information in commit 09d40e0e0828_. |
++--------------------------------+-------------+---------+---------------------------------------------------------+
+
+*Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.*
+
+.. _Platform compatibility policy: platform-compatibility-policy.rst
+.. _crash_console_helpers.S: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/common/aarch64/crash_console_helpers.S
+.. _cc5859c: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=cc5859ca19ff546c35eb0331000dae090b6eabcf
+.. _09d40e0e0828: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=09d40e0e08283a249e7dce0e106c07c5141f9b7e
diff --git a/docs/security-center.rst b/docs/security-center.rst
new file mode 100644
index 0000000..672c563
--- /dev/null
+++ b/docs/security-center.rst
@@ -0,0 +1,103 @@
+Security Center
+===============
+
+Security Disclosures
+--------------------
+
+We disclose all security vulnerabilities we find or are advised about that are
+relevant for ARM Trusted Firmware (TF). We encourage responsible disclosure of
+vulnerabilities and inform users as best we can about all possible issues.
+
+We disclose TF vulnerabilities as Security Advisories. These are listed at the
+bottom of this page and announced as issues in the `GitHub issue tracker`_ with
+the "security-advisory" tag. You can receive notification emails for these by
+watching that project.
+
+Found a Security Issue?
+-----------------------
+
+Although we try to keep TF secure, we can only do so with the help of the
+community of developers and security researchers.
+
+If you think you have found a security vulnerability, please *do not* report it
+in the `GitHub issue tracker`_. Instead send an email to
+trusted-firmware-security@arm.com
+
+Please include:
+
+* Trusted Firmware version (or commit) affected
+
+* A description of the concern or vulnerability
+
+* Details on how to replicate the vulnerability, including:
+
+  - Configuration details
+
+  - Proof of concept exploit code
+
+  - Any additional software or tools required
+
+We recommend using `this PGP/GPG key`_ for encrypting the information. This key
+is also available at http://keyserver.pgp.com and LDAP port 389 of the same
+server. The fingerprint for this key is:
+
+::
+
+    1309 2C19 22B4 8E87 F17B FE5C 3AB7 EFCB 45A0 DFD0
+
+If you would like replies to be encrypted, please provide your public key.
+
+Please give us the time to respond to you and fix the vulnerability before going
+public. We do our best to respond and fix any issues quickly. We also need to
+ensure providers of products that use TF have a chance to consider the
+implications of the vulnerability and its remedy.
+
+Afterwards, we encourage you to write-up your findings about the TF source code.
+
+Attribution
+-----------
+
+We will name and thank you in the ``change-log.rst`` distributed with the source
+code and in any published security advisory.
+
+Security Advisories
+-------------------
+
++-----------+------------------------------------------------------------------+
+| ID        | Title                                                            |
++===========+==================================================================+
+| `TFV-1`_  | Malformed Firmware Update SMC can result in copy of unexpectedly |
+|           | large data into secure memory                                    |
++-----------+------------------------------------------------------------------+
+| `TFV-2`_  | Enabled secure self-hosted invasive debug interface can allow    |
+|           | normal world to panic secure world                               |
++-----------+------------------------------------------------------------------+
+| `TFV-3`_  | RO memory is always executable at AArch64 Secure EL1             |
++-----------+------------------------------------------------------------------+
+| `TFV-4`_  | Malformed Firmware Update SMC can result in copy or              |
+|           | authentication of unexpected data in secure memory in AArch32    |
+|           | state                                                            |
++-----------+------------------------------------------------------------------+
+| `TFV-5`_  | Not initializing or saving/restoring PMCR_EL0 can leak secure    |
+|           | world timing information                                         |
++-----------+------------------------------------------------------------------+
+| `TFV-6`_  | Arm Trusted Firmware exposure to speculative processor           |
+|           | vulnerabilities using cache timing side-channels                 |
++-----------+------------------------------------------------------------------+
+| `TFV-7`_  | Trusted Firmware-A exposure to cache speculation vulnerability   |
+|           | Variant 4                                                        |
++-----------+------------------------------------------------------------------+
+| `TFV-8`_  | Not saving x0 to x3 registers can leak information from one      |
+|           | Normal World SMC client to another                               |
++-----------+------------------------------------------------------------------+
+
+.. _GitHub issue tracker: https://github.com/ARM-software/tf-issues/issues
+.. _this PGP/GPG key: security-reporting.asc
+.. _TFV-1: ./security_advisories/security-advisory-tfv-1.rst
+.. _TFV-2: ./security_advisories/security-advisory-tfv-2.rst
+.. _TFV-3: ./security_advisories/security-advisory-tfv-3.rst
+.. _TFV-4: ./security_advisories/security-advisory-tfv-4.rst
+.. _TFV-5: ./security_advisories/security-advisory-tfv-5.rst
+.. _TFV-6: ./security_advisories/security-advisory-tfv-6.rst
+.. _TFV-7: ./security_advisories/security-advisory-tfv-7.rst
+.. _TFV-8: ./security_advisories/security-advisory-tfv-8.rst
diff --git a/docs/security-reporting.asc b/docs/security-reporting.asc
new file mode 100644
index 0000000..8c41f7b
--- /dev/null
+++ b/docs/security-reporting.asc
@@ -0,0 +1,45 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: PGP Desktop 10.2.0 (Build 2317)
+
+mQENBFey/QMBCACyxJaLsMYU794ZfzLdY172tHXRJfP0X3b34HU35G7kYl1zNiYc
+/NoygtQdtDv/aW1B2A/YTNhGge+gX4BWAREd5CYDbdPEoMWC395/qbnmMmez7YNY
+PEJ9Iq9e5AayAWwZTL1zgKwdvE+WTwWok/nMbsifJSEdhdrOIHNqRcZgplUUyZ2R
+sDqFtSbACO3xj4Psk8KJ23Ax7UZgULouZOJaHOnyq8F9V/U7zWvX4Odf96XaC1Em
+cUTsG0kQfa7Y4Hqqjzowq366I4k2o2LAtuLPWNCvq5jjEceLs2+qV4cNLgyL2dzO
+wtUL6EdkrGfkxsPHpsVKXig4wjeX9ehCSqRlABEBAAG0PVRydXN0ZWQgRmlybXdh
+cmUgU2VjdXJpdHkgPHRydXN0ZWQtZmlybXdhcmUtc2VjdXJpdHlAYXJtLmNvbT6J
+AYwEEAECAHYFAley/SEwFIAAAAAAIAAHcHJlZmVycmVkLWVtYWlsLWVuY29kaW5n
+QHBncC5jb21wZ3BtaW1lCAsJCAcDAgEKAhkBGRhsZGFwOi8va2V5c2VydmVyLnBn
+cC5jb20FGwMAAAAFFgADAgEFHgEAAAAGFQgJCgMCAAoJEDq378tFoN/QFJsH/0ly
+H91LYYzKIQrbolQw7Rp47lgzH88uN1rInYpW2GaTbjwPffAhYJ4VsN8RaiFskD9m
+DjMg4vY8p0jPTCUX1Acq20Wq0Ybv3HcrtjUp4ie0+rLUi3043yJyKFMWkJC2Kr+p
+SobnxSrAie4HDFUgSaPoh9Qf1zXEzOavdgcziMiyS5iVUf6NXYZ9z82OTZ6TdPKS
+u+L5zOHTdrV3+hD54w00Xa+EIE7u4v0to6Uwm977508hyGuvpOVq+u7+S3qJQvnY
++JheStbgLsm6CyoRjyrlTE01ujAD6hI6Ef9yMgEljOBEy4phKAJ67SCRLEOiCp5U
+YHFCULwhzIyg2y3WmZSJASIEEAECAAwFAlezAnwFAwASdQAACgkQlxC4m8pXrXzd
+GAf/T8YEICI9qQt2vnCtCbBvVaTc2sAphVZ51kZVDqCDPB7znDtJYRBpi/9IPELt
+mYwIElMx2mqmahVaeUghmbzmcLZe8QHUi8GanO1mh+ook6uyjRojSIq6VUVV5uUf
+tuscfhpilOvUclqMqYEIgXfl08YwS40Kmmj0qokwad0co0zGQ8GEhlgMi2yvJfiG
+fPS0Xcn1J0980E/VgJQCAKwZvukrbb32WVwuhgepqs/4/62PZNxglcErioFt6P0A
+ik4t9Hr0uErqCeEKiYtmEw5e9ioRdX7CV+tJgIk907Tpv6E0iDFRJHmJBvmsz82O
+stOazS3wZ5Xck7asTqkvoyo9Z7kBDQRXsv0DAQgAsmL1UUIWyoNmYJWixSPDmclP
+0ul3T1FCOsIlWTeVeshnHByYdgZOfce78ETCUoq8G7qvYm4GRrEDpqVbxqTxJioP
+4Li05WDdNCKzSoqWd8ADA48gYnnJEu2NhA7ZkEC6u3+Mdbmd3M0J6nsAWeE0BV1p
+F5zI600sJuoH2QNWB7Kv5N3GCFE4IgCIH8MwDo4Y4FTZtygx4GjEtSExiOIz+bpX
+2+GkFCQGpIyLHLP4FmQmrsNzsIdEyFuG0IdoVuQ2PtNLiw+Wkm7CXWgRmFx/dtPN
+eVnOFWdbTtjBWVv/Z6zbANos2knfc75KR4FCQ6pWRvVeJuMuMopUDkfFDMtR8QAR
+AQABiQJBBBgBAgErBQJXsv0EBRsMAAAAwF0gBBkBCAAGBQJXsv0DAAoJENaB8ph8
+s9hu/nsH/Rx696ZR+1vZi5qCTUwo6s0Qa15x4OuyJEM85VgMLVY7/MZpp1Y8If6u
+A5BynQpy4QIPxIRsRx6twduW9/gb8UVhpMRPyuJ+5sSv0/KeUqkPbKSUGro2zGlR
+sjqPrchi6uafWZqOR/y/DNkEvkgZZaP+f9xs2qWKuoF08yTioo76QoroA4DVuVAT
+MkDFe9d3natAmfmjO4kvxuthg3y7R+sdXrCHpYYJZdbiR6gyj7e8whlSLwHQT3lz
+7QBL/CvVvL/dmhu5pk8fsksbehepMQTkCJ6GGEamOPEhwh7IvlzhEt97U4uzjuMd
+BPjqOCes+4QTmn/+lMTySG0kXxnHOEUACgkQOrfvy0Wg39D8Jgf/Uf3epkMOJ9xm
+N1l5vW8tQQ6RR055YQxQ9P6JMyCQGEJmGOcvrasCho69wMQDy4AYVtJaZd25LH/3
+LX/lcyDOP4C9VYXM+IxlcaRmjBKqWx9UzQeeioIkfmjMpJFU846ZP1dacge0lPx8
+p6ocPbM0rkv0xuF/dwkDQd4BPSmv4/3/UM8FRoYo8Q7SHkDR98wJ8FCm6k9wRtWC
+K/jzmBswY2TewAHom3jLzTM0FZ/n5Sini3EGAI2EvnQrxWRpeE7ZOkHKqLHEOaHl
+zeST4U/cUgxhwgnhbGJ7zmrFsHpYnnZYM3mIKfQ3/EhksZ68TF9IB1tfUiQTij4r
+9jWa0ybRdQ==
+=nZZb
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/docs/security_advisories/security-advisory-tfv-1.rst b/docs/security_advisories/security-advisory-tfv-1.rst
new file mode 100644
index 0000000..e3d1984
--- /dev/null
+++ b/docs/security_advisories/security-advisory-tfv-1.rst
@@ -0,0 +1,159 @@
++----------------+-------------------------------------------------------------+
+| Title          | Malformed Firmware Update SMC can result in copy of         |
+|                | unexpectedly large data into secure memory                  |
++================+=============================================================+
+| CVE ID         | `CVE-2016-10319`_                                           |
++----------------+-------------------------------------------------------------+
+| Date           | 18 Oct 2016                                                 |
++----------------+-------------------------------------------------------------+
+| Versions       | v1.2 and v1.3 (since commit `48bfb88`_)                     |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Configurations | Platforms that use AArch64 BL1 plus untrusted normal world  |
+| Affected       | firmware update code executing before BL31                  |
++----------------+-------------------------------------------------------------+
+| Impact         | Copy of unexpectedly large data into the free secure memory |
+|                | reported by BL1 platform code                               |
++----------------+-------------------------------------------------------------+
+| Fix Version    | `Pull Request #783`_                                        |
++----------------+-------------------------------------------------------------+
+| Credit         | IOActive                                                    |
++----------------+-------------------------------------------------------------+
+
+Generic Trusted Firmware (TF) BL1 code contains an SMC interface that is briefly
+available after cold reset to support the Firmware Update (FWU) feature (also
+known as recovery mode). This allows most FWU functionality to be implemented in
+the normal world, while retaining the essential image authentication
+functionality in BL1. When cold boot reaches the EL3 Runtime Software (for
+example, BL31 on AArch64 systems), the FWU SMC interface is replaced by the EL3
+Runtime SMC interface. Platforms may choose how much of this FWU functionality
+to use, if any.
+
+The BL1 FWU SMC handling code, currently only supported on AArch64, contains
+several vulnerabilities that may be exploited when *all* the following
+conditions apply:
+
+1. Platform code uses TF BL1 with the ``TRUSTED_BOARD_BOOT`` build option
+   enabled.
+
+2. Platform code arranges for untrusted normal world FWU code to be executed in
+   the cold boot path, before BL31 starts. Untrusted in this sense means code
+   that is not in ROM or has not been authenticated or has otherwise been
+   executed by an attacker.
+
+3. Platform code copies the insecure pattern described below from the ARM
+   platform version of ``bl1_plat_mem_check()``.
+
+The vulnerabilities consist of potential integer overflows in the input
+validation checks while handling the ``FWU_SMC_IMAGE_COPY`` SMC. The SMC
+implementation is designed to copy an image into secure memory for subsequent
+authentication, but the vulnerabilities may allow an attacker to copy
+unexpectedly large data into secure memory. Note that a separate vulnerability
+is required to leverage these vulnerabilities; for example a way to get the
+system to change its behaviour based on the unexpected secure memory contents.
+
+Two of the vulnerabilities are in the function ``bl1_fwu_image_copy()`` in
+``bl1/bl1_fwu.c``. These are listed below, referring to the v1.3 tagged version
+of the code:
+
+- Line 155:
+
+  .. code:: c
+
+    /*
+     * If last block is more than expected then
+     * clip the block to the required image size.
+     */
+    if (image_desc->copied_size + block_size >
+         image_desc->image_info.image_size) {
+        block_size = image_desc->image_info.image_size -
+            image_desc->copied_size;
+        WARN("BL1-FWU: Copy argument block_size > remaining image size."
+            " Clipping block_size\n");
+    }
+
+    /* Make sure the image src/size is mapped. */
+    if (bl1_plat_mem_check(image_src, block_size, flags)) {
+        WARN("BL1-FWU: Copy arguments source/size not mapped\n");
+        return -ENOMEM;
+    }
+
+    INFO("BL1-FWU: Continuing image copy in blocks\n");
+
+    /* Copy image for given block size. */
+    base_addr += image_desc->copied_size;
+    image_desc->copied_size += block_size;
+    memcpy((void *)base_addr, (const void *)image_src, block_size);
+    ...
+
+  This code fragment is executed when the image copy operation is performed in
+  blocks over multiple SMCs. ``block_size`` is an SMC argument and therefore
+  potentially controllable by an attacker. A very large value may result in an
+  integer overflow in the 1st ``if`` statement, which would bypass the check,
+  allowing an unclipped ``block_size`` to be passed into
+  ``bl1_plat_mem_check()``. If ``bl1_plat_mem_check()`` also passes, this may
+  result in an unexpectedly large copy of data into secure memory.
+
+- Line 206:
+
+  .. code:: c
+
+    /* Make sure the image src/size is mapped. */
+    if (bl1_plat_mem_check(image_src, block_size, flags)) {
+        WARN("BL1-FWU: Copy arguments source/size not mapped\n");
+        return -ENOMEM;
+    }
+
+    /* Find out how much free trusted ram remains after BL1 load */
+    mem_layout = bl1_plat_sec_mem_layout();
+    if ((image_desc->image_info.image_base < mem_layout->free_base) ||
+         (image_desc->image_info.image_base + image_size >
+          mem_layout->free_base + mem_layout->free_size)) {
+        WARN("BL1-FWU: Memory not available to copy\n");
+        return -ENOMEM;
+    }
+
+    /* Update the image size. */
+    image_desc->image_info.image_size = image_size;
+
+    /* Copy image for given size. */
+    memcpy((void *)base_addr, (const void *)image_src, block_size);
+    ...
+
+  This code fragment is executed during the 1st invocation of the image copy
+  operation. Both ``block_size`` and ``image_size`` are SMC arguments. A very
+  large value of ``image_size`` may result in an integer overflow in the 2nd
+  ``if`` statement, which would bypass the check, allowing execution to proceed.
+  If ``bl1_plat_mem_check()`` also passes, this may result in an unexpectedly
+  large copy of data into secure memory.
+
+If the platform's implementation of ``bl1_plat_mem_check()`` is correct then it
+may help prevent the above 2 vulnerabilities from being exploited. However, the
+ARM platform version of this function contains a similar vulnerability:
+
+- Line 88 of ``plat/arm/common/arm_bl1_fwu.c`` in function of
+  ``bl1_plat_mem_check()``:
+
+  .. code:: c
+
+    while (mmap[index].mem_size) {
+        if ((mem_base >= mmap[index].mem_base) &&
+            ((mem_base + mem_size)
+            <= (mmap[index].mem_base +
+            mmap[index].mem_size)))
+            return 0;
+
+        index++;
+    }
+    ...
+
+  This function checks that the passed memory region is within one of the
+  regions mapped in by ARM platforms. Here, ``mem_size`` may be the
+  ``block_size`` passed from ``bl1_fwu_image_copy()``. A very large value of
+  ``mem_size`` may result in an integer overflow and the function to incorrectly
+  return success. Platforms that copy this insecure pattern will have the same
+  vulnerability.
+
+.. _CVE-2016-10319: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-10319
+.. _48bfb88: https://github.com/ARM-software/arm-trusted-firmware/commit/48bfb88
+.. _Pull Request #783: https://github.com/ARM-software/arm-trusted-firmware/pull/783
diff --git a/docs/security_advisories/security-advisory-tfv-2.rst b/docs/security_advisories/security-advisory-tfv-2.rst
new file mode 100644
index 0000000..db47458
--- /dev/null
+++ b/docs/security_advisories/security-advisory-tfv-2.rst
@@ -0,0 +1,58 @@
++----------------+-------------------------------------------------------------+
+| Title          | Enabled secure self-hosted invasive debug interface can     |
+|                | allow normal world to panic secure world                    |
++================+=============================================================+
+| CVE ID         | `CVE-2017-7564`_                                            |
++----------------+-------------------------------------------------------------+
+| Date           | 02 Feb 2017                                                 |
++----------------+-------------------------------------------------------------+
+| Versions       | All versions up to v1.3                                     |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Configurations | All                                                         |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Impact         | Denial of Service (secure world panic)                      |
++----------------+-------------------------------------------------------------+
+| Fix Version    | 15 Feb 2017 `Pull Request #841`_                            |
++----------------+-------------------------------------------------------------+
+| Credit         | ARM                                                         |
++----------------+-------------------------------------------------------------+
+
+The ``MDCR_EL3.SDD`` bit controls AArch64 secure self-hosted invasive debug
+enablement. By default, the BL1 and BL31 images of the current version of ARM
+Trusted Firmware (TF) unconditionally assign this bit to ``0`` in the early
+entrypoint code, which enables debug exceptions from the secure world. This can
+be seen in the implementation of the ``el3_arch_init_common`` `AArch64 macro`_ .
+Given that TF does not currently contain support for this feature (for example,
+by saving and restoring the appropriate debug registers), this may allow a
+normal world attacker to induce a panic in the secure world.
+
+The ``MDCR_EL3.SDD`` bit should be assigned to ``1`` to disable debug exceptions
+from the secure world.
+
+Earlier versions of TF (prior to `commit 495f3d3`_) did not assign this bit.
+Since the bit has an architecturally ``UNKNOWN`` reset value, earlier versions
+may or may not have the same problem, depending on the platform.
+
+A similar issue applies to the ``MDCR_EL3.SPD32`` bits, which control AArch32
+secure self-hosted invasive debug enablement. TF assigns these bits to ``00``
+meaning that debug exceptions from Secure EL1 are enabled by the authentication
+interface. Therefore this issue only exists for AArch32 Secure EL1 code when
+secure privileged invasive debug is enabled by the authentication interface, at
+which point the device is vulnerable to other, more serious attacks anyway.
+
+However, given that TF contains no support for handling debug exceptions, the
+``MDCR_EL3.SPD32`` bits should be assigned to ``10`` to disable debug exceptions
+from AArch32 Secure EL1.
+
+Finally, this also issue applies to AArch32 platforms that use the TF SP_MIN
+image or integrate the `AArch32 equivalent`_ of the ``el3_arch_init_common``
+macro. Here the affected bits are ``SDCR.SPD``, which should also be assigned to
+``10`` instead of ``00``
+
+.. _CVE-2017-7564: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7564
+.. _commit 495f3d3: https://github.com/ARM-software/arm-trusted-firmware/commit/495f3d3
+.. _AArch64 macro: https://github.com/ARM-software/arm-trusted-firmware/blob/bcc2bf0/include/common/aarch64/el3_common_macros.S#L85
+.. _AArch32 equivalent: https://github.com/ARM-software/arm-trusted-firmware/blob/bcc2bf0/include/common/aarch32/el3_common_macros.S#L41
+.. _Pull Request #841: https://github.com/ARM-software/arm-trusted-firmware/pull/841
diff --git a/docs/security_advisories/security-advisory-tfv-3.rst b/docs/security_advisories/security-advisory-tfv-3.rst
new file mode 100644
index 0000000..28e10bf
--- /dev/null
+++ b/docs/security_advisories/security-advisory-tfv-3.rst
@@ -0,0 +1,83 @@
++----------------+-------------------------------------------------------------+
+| Title          | RO memory is always executable at AArch64 Secure EL1        |
++================+=============================================================+
+| CVE ID         | `CVE-2017-7563`_                                            |
++----------------+-------------------------------------------------------------+
+| Date           | 06 Apr 2017                                                 |
++----------------+-------------------------------------------------------------+
+| Versions       | v1.3 (since `Pull Request #662`_)                           |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Configurations | AArch64 BL2, TSP or other users of xlat_tables library      |
+| Affected       | executing at AArch64 Secure EL1                             |
++----------------+-------------------------------------------------------------+
+| Impact         | Unexpected Privilege Escalation                             |
++----------------+-------------------------------------------------------------+
+| Fix Version    | `Pull Request #924`_                                        |
++----------------+-------------------------------------------------------------+
+| Credit         | ARM                                                         |
++----------------+-------------------------------------------------------------+
+
+The translation table library in ARM Trusted Firmware (TF) (under
+``lib/xlat_tables`` and ``lib/xlat_tables_v2``) provides APIs to help program
+translation tables in the MMU. The xlat\_tables client specifies its required
+memory mappings in the form of ``mmap_region`` structures.  Each ``mmap_region``
+has memory attributes represented by the ``mmap_attr_t`` enumeration type. This
+contains flags to control data access permissions (``MT_RO``/``MT_RW``) and
+instruction execution permissions (``MT_EXECUTE``/``MT_EXECUTE_NEVER``). Thus a
+mapping specifying both ``MT_RO`` and ``MT_EXECUTE_NEVER`` should result in a
+Read-Only (RO), non-executable memory region.
+
+This feature does not work correctly for AArch64 images executing at Secure EL1.
+Any memory region mapped as RO will always be executable, regardless of whether
+the client specified ``MT_EXECUTE`` or ``MT_EXECUTE_NEVER``.
+
+The vulnerability is known to affect the BL2 and Test Secure Payload (TSP)
+images on platforms that enable the ``SEPARATE_CODE_AND_RODATA`` build option,
+which includes all ARM standard platforms, and the upstream Xilinx and NVidia
+platforms. The RO data section for these images on these platforms is
+unexpectedly executable instead of non-executable. Other platforms or
+``xlat_tables`` clients may also be affected.
+
+The vulnerability primarily manifests itself after `Pull Request #662`_.  Before
+that, ``xlat_tables`` clients could not specify instruction execution
+permissions separately to data access permissions. All RO normal memory regions
+were implicitly executable. Before `Pull Request #662`_.  the vulnerability
+would only manifest itself for device memory mapped as RO; use of this mapping
+is considered rare, although the upstream QEMU platform uses this mapping when
+the ``DEVICE2_BASE`` build option is used.
+
+Note that one or more separate vulnerabilities are also required to exploit this
+vulnerability.
+
+The vulnerability is due to incorrect handling of the execute-never bits in the
+translation tables. The EL3 translation regime uses a single ``XN`` bit to
+determine whether a region is executable. The Secure EL1&0 translation regime
+handles 2 Virtual Address (VA) ranges and so uses 2 bits, ``UXN`` and ``PXN``.
+The ``xlat_tables`` library only handles the ``XN`` bit, which maps to ``UXN``
+in the Secure EL1&0 regime. As a result, this programs the Secure EL0 execution
+permissions but always leaves the memory as executable at Secure EL1.
+
+The vulnerability is mitigated by the following factors:
+
+- The xlat\_tables library ensures that all Read-Write (RW) memory regions are
+  non-executable by setting the ``SCTLR_ELx.WXN`` bit. This overrides any value
+  of the ``XN``, ``UXN`` or ``PXN`` bits in the translation tables. See the
+  ``enable_mmu()`` function:
+
+  .. code:: c
+
+      sctlr = read_sctlr_el##_el();               \
+      sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT;       \
+
+- AArch32 configurations are unaffected. Here the ``XN`` bit controls execution
+  privileges of the currently executing translation regime, which is the desired
+  behaviour.
+
+- ARM TF EL3 code (for example BL1 and BL31) ensures that all non-secure memory
+  mapped into the secure world is non-executable by setting the ``SCR_EL3.SIF``
+  bit. See the ``el3_arch_init_common`` macro in ``el3_common_macros.S``.
+
+.. _CVE-2017-7563: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7563
+.. _Pull Request #662: https://github.com/ARM-software/arm-trusted-firmware/pull/662
+.. _Pull Request #924: https://github.com/ARM-software/arm-trusted-firmware/pull/924
diff --git a/docs/security_advisories/security-advisory-tfv-4.rst b/docs/security_advisories/security-advisory-tfv-4.rst
new file mode 100644
index 0000000..386d0da
--- /dev/null
+++ b/docs/security_advisories/security-advisory-tfv-4.rst
@@ -0,0 +1,121 @@
++----------------+-------------------------------------------------------------+
+| Title          | Malformed Firmware Update SMC can result in copy or         |
+|                | authentication of unexpected data in secure memory in       |
+|                | AArch32 state                                               |
++================+=============================================================+
+| CVE ID         | `CVE-2017-9607`_                                            |
++----------------+-------------------------------------------------------------+
+| Date           | 20 Jun 2017                                                 |
++----------------+-------------------------------------------------------------+
+| Versions       | None (only between 22 May 2017 and 14 June 2017)            |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Configurations | Platforms that use AArch32 BL1 plus untrusted normal world  |
+| Affected       | firmware update code executing before BL31                  |
++----------------+-------------------------------------------------------------+
+| Impact         | Copy or authentication of unexpected data in the secure     |
+|                | memory                                                      |
++----------------+-------------------------------------------------------------+
+| Fix Version    | `Pull Request #979`_ (merged on 14 June 2017)               |
++----------------+-------------------------------------------------------------+
+| Credit         | ARM                                                         |
++----------------+-------------------------------------------------------------+
+
+The ``include/lib/utils_def.h`` header file provides the
+``check_uptr_overflow()`` macro, which aims at detecting arithmetic overflows
+that may occur when computing the sum of a base pointer and an offset. This
+macro evaluates to 1 if the sum of the given base pointer and offset would
+result in a value large enough to wrap around, which may lead to unpredictable
+behaviour.
+
+The macro code is at line 52, referring to the version of the code as of `commit
+c396b73`_:
+
+.. code:: c
+
+    /*
+     * Evaluates to 1 if (ptr + inc) overflows, 0 otherwise.
+     * Both arguments must be unsigned pointer values (i.e. uintptr_t).
+     */
+    #define check_uptr_overflow(ptr, inc)       \
+        (((ptr) > UINTPTR_MAX - (inc)) ? 1 : 0)
+
+This macro does not work correctly for AArch32 images. It fails to detect
+overflows when the sum of its two parameters fall into the ``[2^32, 2^64 - 1]``
+range. Therefore, any AArch32 code relying on this macro to detect such integer
+overflows is actually not protected.
+
+The buggy code has been present in ARM Trusted Firmware (TF) since `Pull Request
+#678`_ was merged (on 18 August 2016). However, the upstream code was not
+vulnerable until `Pull Request #939`_ was merged (on 22 May 2017), which
+introduced AArch32 support for the Trusted Board Boot (TBB) feature. Before
+then, the ``check_uptr_overflow()`` macro was not used in AArch32 code.
+
+The vulnerability resides in the BL1 FWU SMC handling code and it may be
+exploited when *all* the following conditions apply:
+
+- Platform code uses TF BL1 with the ``TRUSTED_BOARD_BOOT`` build option.
+
+- Platform code uses the Firmware Update (FWU) code provided in
+  ``bl1/bl1_fwu.c``, which is part of the TBB support.
+
+- TF BL1 is compiled with the ``ARCH=aarch32`` build option.
+
+In this context, the AArch32 BL1 image might fail to detect potential integer
+overflows in the input validation checks while handling the
+``FWU_SMC_IMAGE_COPY`` and ``FWU_SMC_IMAGE_AUTH`` SMCs.
+
+The ``FWU_SMC_IMAGE_COPY`` SMC handler is designed to copy an image into secure
+memory for subsequent authentication. This is implemented by the
+``bl1_fwu_image_copy()`` function, which has the following function prototype:
+
+.. code:: c
+
+     static int bl1_fwu_image_copy(unsigned int image_id,
+                        uintptr_t image_src,
+                        unsigned int block_size,
+                        unsigned int image_size,
+                        unsigned int flags)
+
+``image_src`` is an SMC argument and therefore potentially controllable by an
+attacker. A very large 32-bit value, for example ``2^32 -1``, may result in the
+sum of ``image_src`` and ``block_size`` overflowing a 32-bit type, which
+``check_uptr_overflow()`` will fail to detect.  Depending on its implementation,
+the platform-specific function ``bl1_plat_mem_check()`` might get defeated by
+these unsanitized values and allow the following memory copy operation, that
+would wrap around.  This may allow an attacker to copy unexpected data into
+secure memory if the memory is mapped in BL1's address space, or cause a fatal
+exception if it's not.
+
+The ``FWU_SMC_IMAGE_AUTH`` SMC handler is designed to authenticate an image
+resident in secure memory. This is implemented by the ``bl1_fwu_image_auth()``
+function, which has the following function prototype:
+
+.. code:: c
+
+    static int bl1_fwu_image_auth(unsigned int image_id,
+                        uintptr_t image_src,
+                        unsigned int image_size,
+                        unsigned int flags)
+
+Similarly, if an attacker has control over the ``image_src`` or ``image_size``
+arguments through the SMC interface and injects high values whose sum overflows,
+they might defeat the ``bl1_plat_mem_check()`` function and make the
+authentication module read data outside of what's normally allowed by the
+platform code or crash the platform.
+
+Note that in both cases, a separate vulnerability is required to leverage this
+vulnerability; for example a way to get the system to change its behaviour based
+on the unexpected secure memory accesses.  Moreover, the normal world FWU code
+would need to be compromised in order to send a malformed FWU SMC that triggers
+an integer overflow.
+
+The vulnerability is known to affect all ARM standard platforms when enabling
+the ``TRUSTED_BOARD_BOOT`` and ``ARCH=aarch32`` build options.  Other platforms
+may also be affected if they fulfil the above conditions.
+
+.. _CVE-2017-9607: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9607
+.. _commit c396b73: https://github.com/ARM-software/arm-trusted-firmware/commit/c396b73
+.. _Pull Request #678: https://github.com/ARM-software/arm-trusted-firmware/pull/678
+.. _Pull Request #939: https://github.com/ARM-software/arm-trusted-firmware/pull/939
+.. _Pull Request #979: https://github.com/ARM-software/arm-trusted-firmware/pull/979
diff --git a/docs/security_advisories/security-advisory-tfv-5.rst b/docs/security_advisories/security-advisory-tfv-5.rst
new file mode 100644
index 0000000..4479bf0
--- /dev/null
+++ b/docs/security_advisories/security-advisory-tfv-5.rst
@@ -0,0 +1,43 @@
++----------------+-------------------------------------------------------------+
+| Title          | Not initializing or saving/restoring ``PMCR_EL0`` can leak  |
+|                | secure world timing information                             |
++================+=============================================================+
+| CVE ID         | `CVE-2017-15031`_                                           |
++----------------+-------------------------------------------------------------+
+| Date           | 02 Oct 2017                                                 |
++----------------+-------------------------------------------------------------+
+| Versions       | All, up to and including v1.4                               |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Configurations | All                                                         |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Impact         | Leakage of sensitive secure world timing information        |
++----------------+-------------------------------------------------------------+
+| Fix Version    | `Pull Request #1127`_ (merged on 18 October 2017)           |
++----------------+-------------------------------------------------------------+
+| Credit         | Arm                                                         |
++----------------+-------------------------------------------------------------+
+
+The ``PMCR_EL0`` (Performance Monitors Control Register) provides details of the
+Performance Monitors implementation, including the number of counters
+implemented, and configures and controls the counters. If the ``PMCR_EL0.DP``
+bit is set to zero, the cycle counter (when enabled) counts during secure world
+execution, even when prohibited by the debug signals.
+
+Since Arm TF does not save and restore ``PMCR_EL0`` when switching between the
+normal and secure worlds, normal world code can set ``PMCR_EL0.DP`` to zero to
+cause leakage of secure world timing information. This register should be added
+to the list of saved/restored registers.
+
+Furthermore, ``PMCR_EL0.DP`` has an architecturally ``UNKNOWN`` reset value.
+Since Arm TF does not initialize this register, it's possible that on at least
+some implementations, ``PMCR_EL0.DP`` is set to zero by default. This and other
+bits with an architecturally UNKNOWN reset value should be initialized to
+sensible default values in the secure context.
+
+The same issue exists for the equivalent AArch32 register, ``PMCR``, except that
+here ``PMCR_EL0.DP`` architecturally resets to zero.
+
+.. _CVE-2017-15031: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15031
+.. _Pull Request #1127: https://github.com/ARM-software/arm-trusted-firmware/pull/1127
diff --git a/docs/security_advisories/security-advisory-tfv-6.rst b/docs/security_advisories/security-advisory-tfv-6.rst
new file mode 100644
index 0000000..7b556d8
--- /dev/null
+++ b/docs/security_advisories/security-advisory-tfv-6.rst
@@ -0,0 +1,145 @@
++----------------+-------------------------------------------------------------+
+| Title          | Arm Trusted Firmware exposure to speculative processor      |
+|                | vulnerabilities using cache timing side-channels            |
++================+=============================================================+
+| CVE ID         | `CVE-2017-5753`_ / `CVE-2017-5715`_ / `CVE-2017-5754`_      |
++----------------+-------------------------------------------------------------+
+| Date           | 03 Jan 2018 (Updated 11 Jan, 18 Jan, 26 Jan, 30 Jan and 07  |
+|                | June 2018)                                                  |
++----------------+-------------------------------------------------------------+
+| Versions       | All, up to and including v1.4                               |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Configurations | All                                                         |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Impact         | Leakage of secure world data to normal world                |
++----------------+-------------------------------------------------------------+
+| Fix Version    | `Pull Request #1214`_, `Pull Request #1228`_,               |
+|                | `Pull Request #1240`_ and `Pull Request #1405`_             |
++----------------+-------------------------------------------------------------+
+| Credit         | Google / Arm                                                |
++----------------+-------------------------------------------------------------+
+
+This security advisory describes the current understanding of the Arm Trusted
+Firmware (TF) exposure to the speculative processor vulnerabilities identified
+by `Google Project Zero`_.  To understand the background and wider impact of
+these vulnerabilities on Arm systems, please refer to the `Arm Processor
+Security Update`_.
+
+Variant 1 (`CVE-2017-5753`_)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+At the time of writing, no vulnerable patterns have been observed in upstream TF
+code, therefore no workarounds have been applied or are planned.
+
+Variant 2 (`CVE-2017-5715`_)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Where possible on vulnerable CPUs, Arm recommends invalidating the branch
+predictor as early as possible on entry into the secure world, before any branch
+instruction is executed. There are a number of implementation defined ways to
+achieve this.
+
+For Cortex-A57 and Cortex-A72 CPUs, the Pull Requests (PRs) in this advisory
+invalidate the branch predictor when entering EL3 by disabling and re-enabling
+the MMU.
+
+For Cortex-A73 and Cortex-A75 CPUs, the PRs in this advisory invalidate the
+branch predictor when entering EL3 by temporarily dropping into AArch32
+Secure-EL1 and executing the ``BPIALL`` instruction. This workaround is
+signifiantly more complex than the "MMU disable/enable" workaround. The latter
+is not effective at invalidating the branch predictor on Cortex-A73/Cortex-A75.
+
+Note that if other privileged software, for example a Rich OS kernel, implements
+its own branch predictor invalidation during context switch by issuing an SMC
+(to execute firmware branch predictor invalidation), then there is a dependency
+on the PRs in this advisory being deployed in order for those workarounds to
+work. If that other privileged software is able to workaround the vulnerability
+locally (for example by implementing "MMU disable/enable" itself), there is no
+such dependency.
+
+`Pull Request #1240`_ and `Pull Request #1405`_ optimise the earlier fixes by
+implementing a specified `CVE-2017-5715`_ workaround SMC
+(``SMCCC_ARCH_WORKAROUND_1``) for use by normal world privileged software. This
+is more efficient than calling an arbitrary SMC (for example ``PSCI_VERSION``).
+Details of ``SMCCC_ARCH_WORKAROUND_1`` can be found in the `CVE-2017-5715
+mitigation specification`_.  The specification and implementation also enable
+the normal world to discover the presence of this firmware service.
+
+On Juno R1 we measured the round trip latency for both the ``PSCI_VERSION`` and
+``SMCCC_ARCH_WORKAROUND_1`` SMCs on Cortex-A57, using both the "MMU
+disable/enable" and "BPIALL at AArch32 Secure-EL1" workarounds described above.
+This includes the time spent in test code conforming to the SMC Calling
+Convention (SMCCC) from AArch64. For the ``SMCCC_ARCH_WORKAROUND_1`` cases, the
+test code uses SMCCC v1.1, which reduces the number of general purpose registers
+it needs to save/restore. Although the ``BPIALL`` instruction is not effective
+at invalidating the branch predictor on Cortex-A57, the drop into Secure-EL1
+with MMU disabled that this workaround entails effectively does invalidate the
+branch predictor. Hence this is a reasonable comparison.
+
+The results were as follows:
+
++------------------------------------------------------------------+-----------+
+| Test                                                             | Time (ns) |
++==================================================================+===========+
+| ``PSCI_VERSION`` baseline (without PRs in this advisory)         | 515       |
++------------------------------------------------------------------+-----------+
+| ``PSCI_VERSION`` baseline (with PRs in this advisory)            | 527       |
++------------------------------------------------------------------+-----------+
+| ``PSCI_VERSION`` with "MMU disable/enable"                       | 930       |
++------------------------------------------------------------------+-----------+
+| ``SMCCC_ARCH_WORKAROUND_1`` with "MMU disable/enable"            | 386       |
++------------------------------------------------------------------+-----------+
+| ``PSCI_VERSION`` with "BPIALL at AArch32 Secure-EL1"             | 1276      |
++------------------------------------------------------------------+-----------+
+| ``SMCCC_ARCH_WORKAROUND_1`` with "BPIALL at AArch32 Secure-EL1"  | 770       |
++------------------------------------------------------------------+-----------+
+
+Due to the high severity and wide applicability of this issue, the above
+workarounds are enabled by default (on vulnerable CPUs only), despite some
+performance and code size overhead. Platforms can choose to disable them at
+compile time if they do not require them. `Pull Request #1240`_ disables the
+workarounds for unaffected upstream platforms.
+
+For vulnerable AArch32-only CPUs (for example Cortex-A8, Cortex-A9 and
+Cortex-A17), the ``BPIALL`` instruction should be used as early as possible on
+entry into the secure world. For Cortex-A8, also set ``ACTLR[6]`` to 1 during
+early processor initialization. Note that the ``BPIALL`` instruction is not
+effective at invalidating the branch predictor on Cortex-A15. For that CPU, set
+``ACTLR[0]`` to 1 during early processor initialization, and invalidate the
+branch predictor by performing an ``ICIALLU`` instruction.
+
+On AArch32 EL3 systems, the monitor and secure-SVC code is typically tightly
+integrated, for example as part of a Trusted OS. Therefore any Variant 2
+workaround should be provided by vendors of that software and is outside the
+scope of TF. However, an example implementation in the minimal AArch32 Secure
+Payload, ``SP_MIN`` is provided in `Pull Request #1228`_.
+
+Other Arm CPUs are not vulnerable to this or other variants. This includes
+Cortex-A76, Cortex-A53, Cortex-A55, Cortex-A32, Cortex-A7 and Cortex-A5.
+
+For more information about non-Arm CPUs, please contact the CPU vendor.
+
+Variant 3 (`CVE-2017-5754`_)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This variant is only exploitable between Exception Levels within the same
+translation regime, for example between EL0 and EL1, therefore this variant
+cannot be used to access secure memory from the non-secure world, and is not
+applicable for TF. However, Secure Payloads (for example, Trusted OS) should
+provide mitigations on vulnerable CPUs to protect themselves from exploited
+Secure-EL0 applications.
+
+The only Arm CPU vulnerable to this variant is Cortex-A75.
+
+.. _Google Project Zero: https://googleprojectzero.blogspot.co.uk/2018/01/reading-privileged-memory-with-side.html
+.. _Arm Processor Security Update: http://www.arm.com/security-update
+.. _CVE-2017-5753: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5753
+.. _CVE-2017-5715: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+.. _CVE-2017-5754: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5754
+.. _Pull Request #1214: https://github.com/ARM-software/arm-trusted-firmware/pull/1214
+.. _Pull Request #1228: https://github.com/ARM-software/arm-trusted-firmware/pull/1228
+.. _Pull Request #1240: https://github.com/ARM-software/arm-trusted-firmware/pull/1240
+.. _Pull Request #1405: https://github.com/ARM-software/arm-trusted-firmware/pull/1405
+.. _CVE-2017-5715 mitigation specification: https://developer.arm.com/cache-speculation-vulnerability-firmware-specification
diff --git a/docs/security_advisories/security-advisory-tfv-7.rst b/docs/security_advisories/security-advisory-tfv-7.rst
new file mode 100644
index 0000000..572268a
--- /dev/null
+++ b/docs/security_advisories/security-advisory-tfv-7.rst
@@ -0,0 +1,104 @@
++----------------+-------------------------------------------------------------+
+| Title          | Trusted Firmware-A exposure to cache speculation            |
+|                | vulnerability Variant 4                                     |
++================+=============================================================+
+| CVE ID         | `CVE-2018-3639`_                                            |
++----------------+-------------------------------------------------------------+
+| Date           | 21 May 2018 (Updated 7 June 2018)                           |
++----------------+-------------------------------------------------------------+
+| Versions       | All, up to and including v1.5                               |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Configurations | All                                                         |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Impact         | Leakage of secure world data to normal world                |
++----------------+-------------------------------------------------------------+
+| Fix Version    | `Pull Request #1392`_, `Pull Request #1397`_                |
++----------------+-------------------------------------------------------------+
+| Credit         | Google                                                      |
++----------------+-------------------------------------------------------------+
+
+This security advisory describes the current understanding of the Trusted
+Firmware-A (TF-A) exposure to Variant 4 of the cache speculation vulnerabilities
+identified by `Google Project Zero`_.  To understand the background and wider
+impact of these vulnerabilities on Arm systems, please refer to the `Arm
+Processor Security Update`_.
+
+At the time of writing, the TF-A project is not aware of a Variant 4 exploit
+that could be used against TF-A. It is likely to be very difficult to achieve an
+exploit against current standard configurations of TF-A, due to the limited
+interfaces into the secure world with attacker-controlled inputs. However, this
+is becoming increasingly difficult to guarantee with the introduction of complex
+new firmware interfaces, for example the `Software Delegated Exception Interface
+(SDEI)`_.  Also, the TF-A project does not have visibility of all
+vendor-supplied interfaces. Therefore, the TF-A project takes a conservative
+approach by mitigating Variant 4 in hardware wherever possible during secure
+world execution. The mitigation is enabled by setting an implementation defined
+control bit to prevent the re-ordering of stores and loads.
+
+For each affected CPU type, TF-A implements one of the two following mitigation
+approaches in `Pull Request #1392`_ and `Pull Request #1397`_.  Both approaches
+have a system performance impact, which varies for each CPU type and use-case.
+The mitigation code is enabled by default, but can be disabled at compile time
+for platforms that are unaffected or where the risk is deemed low enough.
+
+Arm CPUs not mentioned below are unaffected.
+
+Static mitigation
+~~~~~~~~~~~~~~~~~
+
+For affected CPUs, this approach enables the mitigation during EL3
+initialization, following every PE reset. No mechanism is provided to disable
+the mitigation at runtime.
+
+This approach permanently mitigates the entire software stack and no additional
+mitigation code is required in other software components.
+
+TF-A implements this approach for the following affected CPUs:
+
+- Cortex-A57 and Cortex-A72, by setting bit 55 (Disable load pass store) of
+  ``CPUACTLR_EL1`` (``S3_1_C15_C2_0``).
+
+- Cortex-A73, by setting bit 3 of ``S3_0_C15_C0_0`` (not documented in the
+  Technical Reference Manual (TRM)).
+
+- Cortex-A75, by setting bit 35 (reserved in TRM) of ``CPUACTLR_EL1``
+  (``S3_0_C15_C1_0``).
+
+Dynamic mitigation
+~~~~~~~~~~~~~~~~~~
+
+For affected CPUs, this approach also enables the mitigation during EL3
+initialization, following every PE reset. In addition, this approach implements
+``SMCCC_ARCH_WORKAROUND_2`` in the Arm architectural range to allow callers at
+lower exception levels to temporarily disable the mitigation in their execution
+context, where the risk is deemed low enough. This approach enables mitigation
+on entry to EL3, and restores the mitigation state of the lower exception level
+on exit from EL3. For more information on this approach, see `Firmware
+interfaces for mitigating cache speculation vulnerabilities`_.
+
+This approach may be complemented by additional mitigation code in other
+software components, for example code that calls ``SMCCC_ARCH_WORKAROUND_2``.
+However, even without any mitigation code in other software components, this
+approach will effectively permanently mitigate the entire software stack, since
+the default mitigation state for firmware-managed execution contexts is enabled.
+
+Since the expectation in this approach is that more software executes with the
+mitigation disabled, this may result in better system performance than the
+static approach for some systems or use-cases.  However, for other systems or
+use-cases, this performance saving may be outweighed by the additional overhead
+of ``SMCCC_ARCH_WORKAROUND_2`` calls and TF-A exception handling.
+
+TF-A implements this approach for the following affected CPU:
+
+- Cortex-A76, by setting and clearing bit 16 (reserved in TRM) of
+  ``CPUACTLR2_EL1`` (``S3_0_C15_C1_1``).
+
+.. _Google Project Zero: https://bugs.chromium.org/p/project-zero/issues/detail?id=1528
+.. _Arm Processor Security Update: http://www.arm.com/security-update
+.. _CVE-2018-3639: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3639
+.. _Software Delegated Exception Interface (SDEI): http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf
+.. _Firmware interfaces for mitigating cache speculation vulnerabilities: https://developer.arm.com/cache-speculation-vulnerability-firmware-specification
+.. _Pull Request #1392: https://github.com/ARM-software/arm-trusted-firmware/pull/1392
+.. _Pull Request #1397: https://github.com/ARM-software/arm-trusted-firmware/pull/1397
diff --git a/docs/security_advisories/security-advisory-tfv-8.rst b/docs/security_advisories/security-advisory-tfv-8.rst
new file mode 100644
index 0000000..eacdc7b
--- /dev/null
+++ b/docs/security_advisories/security-advisory-tfv-8.rst
@@ -0,0 +1,100 @@
++----------------+-------------------------------------------------------------+
+| Title          | Not saving x0 to x3 registers can leak information from one |
+|                | Normal World SMC client to another                          |
++================+=============================================================+
+| CVE ID         | `CVE-2018-19440`_                                           |
++----------------+-------------------------------------------------------------+
+| Date           | 27 Nov 2018                                                 |
++----------------+-------------------------------------------------------------+
+| Versions       | All                                                         |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Configurations | Multiple normal world SMC clients calling into AArch64 BL31 |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Impact         | Leakage of SMC return values from one normal world SMC      |
+|                | client to another                                           |
++----------------+-------------------------------------------------------------+
+| Fix Version    | `Pull Request #1710`_                                       |
++----------------+-------------------------------------------------------------+
+| Credit         | Secmation                                                   |
++----------------+-------------------------------------------------------------+
+
+When taking an exception to EL3, BL31 saves the CPU context. The aim is to
+restore it before returning into the lower exception level software that called
+into the firmware. However, for an SMC exception, the general purpose registers
+``x0`` to ``x3`` are not part of the CPU context saved on the stack.
+
+As per the `SMC Calling Convention`_, up to 4 values may be returned to the
+caller in registers ``x0`` to ``x3``. In TF-A, these return values are written
+into the CPU context, typically using one of the ``SMC_RETx()`` macros provided
+in the ``include/lib/aarch64/smccc_helpers.h`` header file.
+
+Before returning to the caller, the ``restore_gp_registers()`` function is
+called. It restores the values of all general purpose registers taken from the
+CPU context stored on the stack. This includes registers ``x0`` to ``x3``, as
+can be seen in the ``lib/el3_runtime/aarch64/context.S`` file at line 339
+(referring to the version of the code as of `commit c385955`_):
+
+.. code:: c
+
+    /*
+     * This function restores all general purpose registers except x30 from the
+     * CPU context. x30 register must be explicitly restored by the caller.
+     */
+    func restore_gp_registers
+        ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+        ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
+
+In the case of an SMC handler that does not use all 4 return values, the
+remaining ones are left unchanged in the CPU context. As a result,
+``restore_gp_registers()`` restores the stale values saved by a previous SMC
+request (or asynchronous exception to EL3) that used these return values.
+
+In the presence of multiple normal world SMC clients, this behaviour might leak
+some of the return values from one client to another. For example, if a victim
+client first sends an SMC that returns 4 values, a malicious client may then
+send a second SMC expecting no return values (for example, a
+``SDEI_EVENT_COMPLETE`` SMC) to get the 4 return values of the victim client.
+
+In general, the responsibility for mitigating threats due to the presence of
+multiple normal world SMC clients lies with EL2 software.  When present, EL2
+software must trap SMC calls from EL1 software to ensure secure behaviour.
+
+For this reason, TF-A does not save ``x0`` to ``x3`` in the CPU context on an
+SMC synchronous exception. It has behaved this way since the first version.
+
+We can confirm that at least upstream KVM-based systems mitigate this threat,
+and are therefore unaffected by this issue. Other EL2 software should be audited
+to assess the impact of this threat.
+
+EL2 software might find mitigating this threat somewhat onerous, because for all
+SMCs it would need to be aware of which return registers contain valid data, so
+it can sanitise any unused return registers. On the other hand, mitigating this
+in EL3 is relatively easy and cheap. Therefore, TF-A will now ensure that no
+information is leaked through registers ``x0`` to ``x3``, by preserving the
+register state over the call.
+
+Note that AArch32 TF-A is not affected by this issue. The SMC handling code in
+``SP_MIN`` already saves all general purpose registers - including ``r0`` to
+``r3``, as can be seen in the ``include/lib/aarch32/smccc_macros.S`` file at
+line 19 (referring to the version of the code as of `commit c385955`_):
+
+.. code:: c
+
+    /*
+     * Macro to save the General purpose registers (r0 - r12), the banked
+     * spsr, lr, sp registers and the `scr` register to the SMC context on entry
+     * due a SMC call. The `lr` of the current mode (monitor) is expected to be
+     * already saved. The `sp` must point to the `smc_ctx_t` to save to.
+     * Additionally, also save the 'pmcr' register as this is updated whilst
+     * executing in the secure world.
+     */
+        .macro smccc_save_gp_mode_regs
+        /* Save r0 - r12 in the SMC context */
+        stm sp, {r0-r12}
+
+.. _CVE-2018-19440: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19440
+.. _commit c385955: https://github.com/ARM-software/arm-trusted-firmware/commit/c385955
+.. _SMC Calling Convention: http://arminfo.emea.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf
+.. _Pull Request #1710: https://github.com/ARM-software/arm-trusted-firmware/pull/1710
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index b602956..de4611c 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -729,6 +729,12 @@
    Note: when ``EL3_EXCEPTION_HANDLING`` is ``1``, ``TSP_NS_INTR_ASYNC_PREEMPT``
    must also be set to ``1``.
 
+-  ``USE_ARM_LINK``: This flag determines whether to enable support for ARM
+   linker. When the ``LINKER`` build variable points to the armlink linker,
+   this flag is enabled automatically. To enable support for armlink, platforms
+   will have to provide a scatter file for the BL image. Currently, Tegra
+   platforms use the armlink support to compile BL3-1 images.
+
 -  ``USE_COHERENT_MEM``: This flag determines whether to include the coherent
    memory region in the BL memory map or not (see "Use of Coherent memory in
    TF-A" section in `Firmware Design`_). It can take the value 1
@@ -1108,7 +1114,7 @@
    is important to use a version that is compatible with TF-A and fixes any
    known security vulnerabilities. See `mbed TLS Security Center`_ for more
    information. The latest version of TF-A is tested with tag
-   ``mbedtls-2.12.0``.
+   ``mbedtls-2.16.0``.
 
    The ``drivers/auth/mbedtls/mbedtls_*.mk`` files contain the list of mbed TLS
    source files the modules depend upon.
diff --git a/drivers/arm/css/scmi/scmi_private.h b/drivers/arm/css/scmi/scmi_private.h
index 6530573..61437f6 100644
--- a/drivers/arm/css/scmi/scmi_private.h
+++ b/drivers/arm/css/scmi/scmi_private.h
@@ -152,4 +152,9 @@
 	assert(ch->info && ch->info->scmi_mbx_mem);
 }
 
+/*
+ * SCMI vendor specific protocol
+ */
+#define SCMI_SYS_VENDOR_EXT_PROTO_ID		0x80
+
 #endif /* SCMI_PRIVATE_H */
diff --git a/drivers/arm/css/scmi/vendor/scmi_sq.c b/drivers/arm/css/scmi/vendor/scmi_sq.c
new file mode 100644
index 0000000..2ae7ca1
--- /dev/null
+++ b/drivers/arm/css/scmi/vendor/scmi_sq.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/css/scmi.h>
+
+#include "scmi_private.h"
+#include "scmi_sq.h"
+
+#include <sq_common.h>
+
+/* SCMI messge ID to get the available DRAM region */
+#define SCMI_VENDOR_EXT_MEMINFO_GET_MSG		0x3
+
+/*
+ * API to get the available DRAM region
+ */
+int scmi_get_draminfo(void *p, struct draminfo *info)
+{
+	mailbox_mem_t *mbx_mem;
+	int token = 0, ret;
+	scmi_channel_t *ch = (scmi_channel_t *)p;
+	struct dram_info_resp response;
+
+	validate_scmi_channel(ch);
+
+	scmi_get_channel(ch);
+
+	mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem);
+	mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_SYS_VENDOR_EXT_PROTO_ID,
+			SCMI_VENDOR_EXT_MEMINFO_GET_MSG, token);
+	mbx_mem->len = 8;
+	mbx_mem->flags = SCMI_FLAG_RESP_POLL;
+
+	scmi_send_sync_command(ch);
+
+	/*
+	 * Ensure that any read to the SCPI payload area is done after reading
+	 * the MHU register. If these 2 reads were reordered then the CPU would
+	 * read invalid payload data
+	 */
+	dmbld();
+
+	/* Get the return values */
+	SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret);
+
+	memcpy(&response, (void *)mbx_mem->payload, sizeof(response));
+
+	scmi_put_channel(ch);
+
+	*info = response.info;
+
+	return ret;
+}
diff --git a/drivers/arm/css/scmi/vendor/scmi_sq.h b/drivers/arm/css/scmi/vendor/scmi_sq.h
new file mode 100644
index 0000000..aee1a3a
--- /dev/null
+++ b/drivers/arm/css/scmi/vendor/scmi_sq.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SCMI_SQ_H
+#define SCMI_SQ_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <sq_common.h>
+
+/* Structure to represent available DRAM region */
+struct dram_info_resp {
+	int status;
+	int reserved;
+	struct draminfo info;
+};
+
+/* API to get the available DRAM region */
+int scmi_get_draminfo(void *p, struct draminfo *info);
+
+#endif /* SCMI_SQ_H */
diff --git a/drivers/auth/mbedtls/mbedtls_common.c b/drivers/auth/mbedtls/mbedtls_common.c
index b6d02fd..cdb5042 100644
--- a/drivers/auth/mbedtls/mbedtls_common.c
+++ b/drivers/auth/mbedtls/mbedtls_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,6 +16,8 @@
 #include <drivers/auth/mbedtls/mbedtls_config.h>
 #include <plat/common/platform.h>
 
+#pragma weak plat_get_mbedtls_heap
+
 static void cleanup(void)
 {
 	ERROR("EXIT from BL2\n");
@@ -54,3 +56,19 @@
 		ready = 1;
 	}
 }
+
+/*
+ * The following default implementation of the function simply returns the
+ * by default allocated heap.
+ */
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+	static unsigned char heap[TF_MBEDTLS_HEAP_SIZE];
+
+	assert(heap_addr != NULL);
+	assert(heap_size != NULL);
+
+	*heap_addr = heap;
+	*heap_size = sizeof(heap);
+	return 0;
+}
diff --git a/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c b/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c
new file mode 100644
index 0000000..7d7d55f
--- /dev/null
+++ b/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_storage.h>
+#include <lib/utils.h>
+
+#include "drivers/qspi/cadence_qspi.h"
+
+/* As we need to be able to keep state for seek, only one file can be open
+ * at a time. Make this a structure and point to the entity->info. When we
+ * can malloc memory we can change this to support more open files.
+ */
+typedef struct {
+	/* Use the 'in_use' flag as any value for base and file_pos could be
+	 * valid.
+	 */
+	int		in_use;
+	uintptr_t	base;
+	size_t		file_pos;
+	size_t		size;
+} file_state_t;
+
+static file_state_t current_file = {0};
+
+/* Identify the device type as memmap */
+static io_type_t device_type_memmap(void)
+{
+	return IO_TYPE_MEMMAP;
+}
+
+/* Memmap device functions */
+static int memmap_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
+static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+			     io_entity_t *entity);
+static int memmap_block_seek(io_entity_t *entity, int mode,
+			     ssize_t offset);
+static int memmap_block_len(io_entity_t *entity, size_t *length);
+static int memmap_block_read(io_entity_t *entity, uintptr_t buffer,
+			     size_t length, size_t *length_read);
+static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer,
+			      size_t length, size_t *length_written);
+static int memmap_block_close(io_entity_t *entity);
+static int memmap_dev_close(io_dev_info_t *dev_info);
+
+
+static const io_dev_connector_t memmap_dev_connector = {
+	.dev_open = memmap_dev_open
+};
+
+
+static const io_dev_funcs_t memmap_dev_funcs = {
+	.type = device_type_memmap,
+	.open = memmap_block_open,
+	.seek = memmap_block_seek,
+	.size = memmap_block_len,
+	.read = memmap_block_read,
+	.write = memmap_block_write,
+	.close = memmap_block_close,
+	.dev_init = NULL,
+	.dev_close = memmap_dev_close,
+};
+
+
+/* No state associated with this device so structure can be const */
+static const io_dev_info_t memmap_dev_info = {
+	.funcs = &memmap_dev_funcs,
+	.info = (uintptr_t)NULL
+};
+
+
+/* Open a connection to the memmap device */
+static int memmap_dev_open(const uintptr_t dev_spec __unused,
+			   io_dev_info_t **dev_info)
+{
+	assert(dev_info != NULL);
+	*dev_info = (io_dev_info_t *)&memmap_dev_info; /* cast away const */
+
+	return 0;
+}
+
+
+
+/* Close a connection to the memmap device */
+static int memmap_dev_close(io_dev_info_t *dev_info)
+{
+	/* NOP */
+	/* TODO: Consider tracking open files and cleaning them up here */
+	return 0;
+}
+
+
+/* Open a file on the memmap device */
+static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
+			     io_entity_t *entity)
+{
+	int result = -ENOMEM;
+	const io_block_spec_t *block_spec = (io_block_spec_t *)spec;
+
+	/* Since we need to track open state for seek() we only allow one open
+	 * spec at a time. When we have dynamic memory we can malloc and set
+	 * entity->info.
+	 */
+	if (current_file.in_use == 0) {
+		assert(block_spec != NULL);
+		assert(entity != NULL);
+
+		current_file.in_use = 1;
+		current_file.base = block_spec->offset;
+		/* File cursor offset for seek and incremental reads etc. */
+		current_file.file_pos = 0;
+		current_file.size = block_spec->length;
+		entity->info = (uintptr_t)&current_file;
+		result = 0;
+	} else {
+		WARN("A Memmap device is already active. Close first.\n");
+	}
+
+	return result;
+}
+
+
+/* Seek to a particular file offset on the memmap device */
+static int memmap_block_seek(io_entity_t *entity, int mode, ssize_t offset)
+{
+	int result = -ENOENT;
+	file_state_t *fp;
+
+	/* We only support IO_SEEK_SET for the moment. */
+	if (mode == IO_SEEK_SET) {
+		assert(entity != NULL);
+
+		fp = (file_state_t *) entity->info;
+
+		/* Assert that new file position is valid */
+		assert((offset >= 0) && (offset < fp->size));
+
+		/* Reset file position */
+		fp->file_pos = offset;
+		result = 0;
+	}
+
+	return result;
+}
+
+
+/* Return the size of a file on the memmap device */
+static int memmap_block_len(io_entity_t *entity, size_t *length)
+{
+	assert(entity != NULL);
+	assert(length != NULL);
+
+	*length = ((file_state_t *)entity->info)->size;
+
+	return 0;
+}
+
+
+/* Read data from a file on the memmap device */
+static int memmap_block_read(io_entity_t *entity, uintptr_t buffer,
+			     size_t length, size_t *length_read)
+{
+	file_state_t *fp;
+	size_t pos_after;
+
+	assert(entity != NULL);
+	assert(length_read != NULL);
+
+	fp = (file_state_t *) entity->info;
+
+	/* Assert that file position is valid for this read operation */
+	pos_after = fp->file_pos + length;
+	assert((pos_after >= fp->file_pos) && (pos_after <= fp->size));
+
+	//memcpy((void *)buffer, (void *)(fp->base + fp->file_pos), length);
+	cad_qspi_read((void *)buffer, fp->base + fp->file_pos, length);
+	*length_read = length;
+
+	/* Set file position after read */
+	fp->file_pos = pos_after;
+
+	return 0;
+}
+
+
+/* Write data to a file on the memmap device */
+static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer,
+			      size_t length, size_t *length_written)
+{
+	file_state_t *fp;
+	size_t pos_after;
+
+	assert(entity != NULL);
+	assert(length_written != NULL);
+
+	fp = (file_state_t *) entity->info;
+
+	/* Assert that file position is valid for this write operation */
+	pos_after = fp->file_pos + length;
+	assert((pos_after >= fp->file_pos) && (pos_after <= fp->size));
+
+	memcpy((void *)(fp->base + fp->file_pos), (void *)buffer, length);
+
+	*length_written = length;
+
+	/* Set file position after write */
+	fp->file_pos = pos_after;
+
+	return 0;
+}
+
+
+/* Close a file on the memmap device */
+static int memmap_block_close(io_entity_t *entity)
+{
+	assert(entity != NULL);
+
+	entity->info = 0;
+
+	/* This would be a mem free() if we had malloc.*/
+	zeromem((void *)&current_file, sizeof(current_file));
+
+	return 0;
+}
+
+
+/* Exported functions */
+
+/* Register the memmap driver with the IO abstraction */
+int register_io_dev_memmap(const io_dev_connector_t **dev_con)
+{
+	int result;
+
+	assert(dev_con != NULL);
+
+	result = io_register_device(&memmap_dev_info);
+	if (result == 0)
+		*dev_con = &memmap_dev_connector;
+
+	return result;
+}
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
index d4771b5..eaaf090 100644
--- a/drivers/io/io_fip.c
+++ b/drivers/io/io_fip.c
@@ -85,7 +85,6 @@
 }
 
 
-/* TODO: We could check version numbers or do a package checksum? */
 static inline int is_valid_header(fip_toc_header_t *header)
 {
 	if ((header->name == TOC_HEADER_NAME) && (header->serial_number != 0)) {
diff --git a/drivers/io/io_storage.c b/drivers/io/io_storage.c
index c9ff31b..e444f87 100644
--- a/drivers/io/io_storage.c
+++ b/drivers/io/io_storage.c
@@ -189,9 +189,6 @@
 	return result;
 }
 
-
-/* TODO: Consider whether an explicit "shutdown" API should be included */
-
 /* Close a connection to a device */
 int io_dev_close(uintptr_t dev_handle)
 {
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 77d683c..db6f3f9 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -29,6 +29,7 @@
 static unsigned int mmc_flags;
 static struct mmc_device_info *mmc_dev_info;
 static unsigned int rca;
+static unsigned int scr[2]__aligned(16) = { 0 };
 
 static const unsigned char tran_speed_base[16] = {
 	0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80
@@ -90,7 +91,8 @@
 		ret = mmc_send_cmd(MMC_CMD(13), rca << RCA_SHIFT_OFFSET,
 				   MMC_RESPONSE_R1, &resp_data[0]);
 		if (ret != 0) {
-			return ret;
+			retries--;
+			continue;
 		}
 
 		if ((resp_data[0] & STATUS_SWITCH_ERROR) != 0U) {
@@ -129,7 +131,6 @@
 {
 	int ret;
 	int retries = MMC_DEFAULT_MAX_RETRIES;
-	unsigned int scr[2] = { 0 };
 	unsigned int bus_width_arg = 0;
 
 	ret = ops->prepare(0, (uintptr_t)&scr, sizeof(scr));
@@ -341,8 +342,9 @@
 		}
 
 		/* ACMD41: SD_SEND_OP_COND */
-		ret = mmc_send_cmd(MMC_ACMD(41), OCR_HCS, MMC_RESPONSE_R3,
-				   &resp_data[0]);
+		ret = mmc_send_cmd(MMC_ACMD(41), OCR_HCS |
+			mmc_dev_info->ocr_voltage, MMC_RESPONSE_R3,
+			&resp_data[0]);
 		if (ret != 0) {
 			return ret;
 		}
diff --git a/drivers/renesas/rcar/pwrc/pwrc.c b/drivers/renesas/rcar/pwrc/pwrc.c
index d7f0880..d85e4a5 100644
--- a/drivers/renesas/rcar/pwrc/pwrc.c
+++ b/drivers/renesas/rcar/pwrc/pwrc.c
@@ -309,7 +309,7 @@
 	c = rcar_pwrc_get_mpidr_cluster(mpidr);
 	dst = IS_CA53(c) ? RCAR_CA53CPUCMCR : RCAR_CA57CPUCMCR;
 
-	if (RCAR_PRODUCT_M3 == product && cut <= RCAR_M3_CUT_VER11)
+	if (RCAR_PRODUCT_M3 == product && cut < RCAR_CUT_VER30)
 		goto done;
 
 	if (RCAR_PRODUCT_H3 == product && cut <= RCAR_CUT_VER20)
@@ -383,7 +383,7 @@
 	product = reg & RCAR_PRODUCT_MASK;
 	cut = reg & RCAR_CUT_MASK;
 
-	if (product == RCAR_PRODUCT_M3)
+	if (product == RCAR_PRODUCT_M3 && cut < RCAR_CUT_VER30)
 		goto self_refresh;
 
 	if (product == RCAR_PRODUCT_H3 && cut < RCAR_CUT_VER20)
@@ -450,7 +450,7 @@
 	mmio_write_32(DBSC4_REG_DBRFEN, 0U);
 	rcar_micro_delay(1U);
 
-	if (product == RCAR_PRODUCT_M3)
+	if (product == RCAR_PRODUCT_M3 && cut < RCAR_CUT_VER30)
 		return;
 
 	if (product == RCAR_PRODUCT_H3 && cut < RCAR_CUT_VER20)
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
index 06de112..f453ce9 100644
--- a/drivers/st/mmc/stm32_sdmmc2.c
+++ b/drivers/st/mmc/stm32_sdmmc2.c
@@ -723,6 +723,7 @@
 	mdelay(1);
 
 	sdmmc2_params.clk_rate = stm32mp_clk_get_rate(sdmmc2_params.clock_id);
+	sdmmc2_params.device_info->ocr_voltage = OCR_3_2_3_3 | OCR_3_3_3_4;
 
 	return mmc_init(&stm32_sdmmc2_ops, sdmmc2_params.clk_rate,
 			sdmmc2_params.bus_width, sdmmc2_params.flags,
diff --git a/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram.c b/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram.c
index f4bfdde..f88de83 100644
--- a/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram.c
+++ b/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram.c
@@ -2094,7 +2094,9 @@
 	/* DBTR16 */
 	/* WDQL : tphy_wrlat + tphy_wrdata */
 	tmp[0] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_F1);
-	/* DQENLTNCY : tphy_wrlat = WL-2 */
+	/* DQENLTNCY : tphy_wrlat = WL-2 : PHY_WRITE_PATH_LAT_ADD == 0
+	 *             tphy_wrlat = WL-3 : PHY_WRITE_PATH_LAT_ADD != 0
+	 */
 	tmp[1] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_ADJ_F1);
 	/* DQL : tphy_rdlat + trdata_en */
 	/* it is not important for dbsc */
@@ -2417,7 +2419,7 @@
 	/* periodic dram zqcal and phy ctrl update enable */
 	mmio_write_32(DBSC_DBCALCNF, 0x01000010);
 	if (((Prr_Product == PRR_PRODUCT_H3) && (Prr_Cut <= PRR_PRODUCT_11))
-	    || ((Prr_Product == PRR_PRODUCT_M3) && (Prr_Cut <= PRR_PRODUCT_20))) {
+	    || ((Prr_Product == PRR_PRODUCT_M3) && (Prr_Cut < PRR_PRODUCT_30))) {
 		/* non : H3 Ver.1.x/M3-W Ver.1.x not support */
 	} else {
 #if RCAR_DRAM_SPLIT == 2
@@ -4216,7 +4218,7 @@
 	}
 
 	if (((Prr_Product == PRR_PRODUCT_H3) && (Prr_Cut <= PRR_PRODUCT_11))
-	    || ((Prr_Product == PRR_PRODUCT_M3) && (Prr_Cut <= PRR_PRODUCT_20))) {
+	    || ((Prr_Product == PRR_PRODUCT_M3) && (Prr_Cut < PRR_PRODUCT_30))) {
 		/* non : H3 Ver.1.x/M3-W Ver.1.x not support */
 	} else {
 		mmio_write_32(DBSC_DBSYSCNT0, 0x00001234);
@@ -4351,7 +4353,7 @@
 	foreach_vch(ch)
 	    mmio_write_32(DBSC_DBPDLK(ch), 0x00000000);
 	if (((Prr_Product == PRR_PRODUCT_H3) && (Prr_Cut <= PRR_PRODUCT_11))
-	    || ((Prr_Product == PRR_PRODUCT_M3) && (Prr_Cut <= PRR_PRODUCT_20))) {
+	    || ((Prr_Product == PRR_PRODUCT_M3) && (Prr_Cut < PRR_PRODUCT_30))) {
 		/* non : H3 Ver.1.x/M3-W Ver.1.x not support */
 	} else {
 		mmio_write_32(DBSC_DBSYSCNT0, 0x00000000);
diff --git a/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram_config.c b/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram_config.c
index 8040d93..43978c2 100644
--- a/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram_config.c
+++ b/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram_config.c
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#define BOARDNUM 18
+#define BOARDNUM 19
 #define BOARD_JUDGE_AUTO
 
 #ifdef BOARD_JUDGE_AUTO
@@ -1322,7 +1322,58 @@
 	    0, 0, 0, 0, 0, 0, 0, 0}
 	  }
 	 }
-	}
+	},
+/* boardcnf[18] RENESAS SALVATOR-X board with M3-W/SIP(16Gbit 2rank) */
+	{
+	 0x03,
+	 0x01,
+	 0x02c0,
+	 0,
+	 0x0300,
+	 0x00a0,
+	 {
+	  {
+	   {0x04, 0x04},
+	    0x00543210,
+	    0x3201,
+	   {0x70612543, 0x43251670, 0x45326170, 0x10672534},
+	   {0x08, 0x08, 0x08, 0x08},
+	   WDQLVL_PAT,
+	   {0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0},
+	   {0, 0, 0, 0},
+	   {0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0},
+	   {0, 0, 0, 0},
+	   {0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0}
+	   },
+	  {
+	   {0x04, 0x04},
+	    0x00543210,
+	    0x2310,
+	   {0x01327654, 0x34526107, 0x35421670, 0x70615324},
+	   {0x08, 0x08, 0x08, 0x08},
+	   WDQLVL_PAT,
+	   {0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0},
+	   {0, 0, 0, 0},
+	   {0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0},
+	   {0, 0, 0, 0},
+	   {0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0}
+	  }
+	 }
+	},
 };
 
 void boardcnf_get_brd_clk(uint32_t brd, uint32_t * clk, uint32_t * div)
@@ -1567,9 +1618,12 @@
 		} else if (Prr_Product == PRR_PRODUCT_M3N) {
 			/* RENESAS SALVATOR-X (M3-N/SIP) */
 			brd = 11;
-		} else if (Prr_Product == PRR_PRODUCT_M3) {
+		} else if ((Prr_Product == PRR_PRODUCT_M3) && (Prr_Cut < PRR_PRODUCT_30)) {
 			/* RENESAS SALVATOR-X (M3-W/SIP) */
 			brd = 0;
+		} else if ((Prr_Product == PRR_PRODUCT_M3) && (Prr_Cut >= PRR_PRODUCT_30)) {
+			/* RENESAS SALVATOR-X (M3-W ver.3.0/SIP) */
+			brd = 18;
 		}
 	}
 #endif
diff --git a/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram_regdef.h b/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram_regdef.h
index d72959b..6a3d1c0 100644
--- a/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram_regdef.h
+++ b/drivers/staging/renesas/rcar/ddr/ddr_b/boot_init_dram_regdef.h
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#define RCAR_DDR_VERSION        "rev.0.34"
+#define RCAR_DDR_VERSION        "rev.0.35rc01"
 #define DRAM_CH_CNT		(0x04)
 #define SLICE_CNT		(0x04)
 #define CS_CNT			(0x02)
diff --git a/drivers/staging/renesas/rcar/pfc/H3/pfc_init_h3_v1.c b/drivers/staging/renesas/rcar/pfc/H3/pfc_init_h3_v1.c
index 2f62bb2..e33005f 100644
--- a/drivers/staging/renesas/rcar/pfc/H3/pfc_init_h3_v1.c
+++ b/drivers/staging/renesas/rcar/pfc/H3/pfc_init_h3_v1.c
@@ -1396,6 +1396,10 @@
 	mmio_write_32(GPIO_INOUTSEL2, 0x00000400U);
 	mmio_write_32(GPIO_INOUTSEL3, 0x0000C000U);
 	mmio_write_32(GPIO_INOUTSEL4, 0x00000000U);
+#if (RCAR_GEN3_ULCB == 1)
+	mmio_write_32(GPIO_INOUTSEL5, 0x0000000EU);
+#else
 	mmio_write_32(GPIO_INOUTSEL5, 0x0000020EU);
+#endif
 	mmio_write_32(GPIO_INOUTSEL6, 0x00013880U);
 }
diff --git a/drivers/staging/renesas/rcar/pfc/H3/pfc_init_h3_v2.c b/drivers/staging/renesas/rcar/pfc/H3/pfc_init_h3_v2.c
index 116fd82..fd9be59 100644
--- a/drivers/staging/renesas/rcar/pfc/H3/pfc_init_h3_v2.c
+++ b/drivers/staging/renesas/rcar/pfc/H3/pfc_init_h3_v2.c
@@ -1444,6 +1444,10 @@
 	mmio_write_32(GPIO_INOUTSEL2, 0x00000400U);
 	mmio_write_32(GPIO_INOUTSEL3, 0x0000C000U);
 	mmio_write_32(GPIO_INOUTSEL4, 0x00000000U);
+#if (RCAR_GEN3_ULCB == 1)
+	mmio_write_32(GPIO_INOUTSEL5, 0x0000000EU);
+#else
 	mmio_write_32(GPIO_INOUTSEL5, 0x0000020EU);
+#endif
 	mmio_write_32(GPIO_INOUTSEL6, 0x00013880U);
 }
diff --git a/drivers/staging/renesas/rcar/pfc/M3/pfc_init_m3.c b/drivers/staging/renesas/rcar/pfc/M3/pfc_init_m3.c
index fc12cd6..3bb560f 100644
--- a/drivers/staging/renesas/rcar/pfc/M3/pfc_init_m3.c
+++ b/drivers/staging/renesas/rcar/pfc/M3/pfc_init_m3.c
@@ -1526,6 +1526,10 @@
 	mmio_write_32(GPIO_INOUTSEL2, 0x00000400U);
 	mmio_write_32(GPIO_INOUTSEL3, 0x0000C000U);
 	mmio_write_32(GPIO_INOUTSEL4, 0x00000000U);
+#if (RCAR_GEN3_ULCB == 1)
+	mmio_write_32(GPIO_INOUTSEL5, 0x0000000EU);
+#else
 	mmio_write_32(GPIO_INOUTSEL5, 0x0000020EU);
+#endif
 	mmio_write_32(GPIO_INOUTSEL6, 0x00013880U);
 }
diff --git a/drivers/staging/renesas/rcar/pfc/M3N/pfc_init_m3n.c b/drivers/staging/renesas/rcar/pfc/M3N/pfc_init_m3n.c
index 07f08fa..408d879 100644
--- a/drivers/staging/renesas/rcar/pfc/M3N/pfc_init_m3n.c
+++ b/drivers/staging/renesas/rcar/pfc/M3N/pfc_init_m3n.c
@@ -1432,6 +1432,10 @@
 	mmio_write_32(GPIO_INOUTSEL2, 0x00000400U);
 	mmio_write_32(GPIO_INOUTSEL3, 0x0000C000U);
 	mmio_write_32(GPIO_INOUTSEL4, 0x00000000U);
+#if (RCAR_GEN3_ULCB == 1)
+	mmio_write_32(GPIO_INOUTSEL5, 0x0000000EU);
+#else
 	mmio_write_32(GPIO_INOUTSEL5, 0x0000020EU);
+#endif
 	mmio_write_32(GPIO_INOUTSEL6, 0x00013880U);
 }
diff --git a/drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v30.c b/drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v30.c
new file mode 100644
index 0000000..319e393
--- /dev/null
+++ b/drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v30.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <common/debug.h>
+
+#include "../qos_common.h"
+#include "../qos_reg.h"
+#include "qos_init_m3_v30.h"
+
+#define	RCAR_QOS_VERSION		"rev.0.1"
+
+#define QOSCTRL_EARLYR			(QOS_BASE1 + 0x0060U)
+#define QOSCTRL_FSS			(QOS_BASE1 + 0x0048U)
+
+#define QOSWT_TIME_BANK0				(20000000U)	//unit:ns
+
+#define	QOSWT_WTEN_ENABLE				(0x1U)
+
+#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_M3_30	(SL_INIT_SSLOTCLK_M3_30 - 0x5U)
+
+#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT	(3U)
+#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT	(9U)
+#define QOSWT_WTREF_SLOT0_EN			((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT))
+#define QOSWT_WTREF_SLOT1_EN			((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT))
+
+#define QOSWT_WTSET0_REQ_SSLOT0			(5U)
+#define WT_BASE_SUB_SLOT_NUM0			(12U)
+#define QOSWT_WTSET0_PERIOD0_M3_30		((QOSWT_TIME_BANK0/QOSWT_WTSET0_CYCLE_M3_30)-1U)
+#define QOSWT_WTSET0_SSLOT0				(QOSWT_WTSET0_REQ_SSLOT0 -1U)
+#define QOSWT_WTSET0_SLOTSLOT0			(WT_BASE_SUB_SLOT_NUM0 -1U)
+
+#define QOSWT_WTSET1_PERIOD1_M3_30		((QOSWT_TIME_BANK0/QOSWT_WTSET0_CYCLE_M3_30)-1U)
+#define QOSWT_WTSET1_SSLOT1				(QOSWT_WTSET0_REQ_SSLOT0 -1U)
+#define QOSWT_WTSET1_SLOTSLOT1			(WT_BASE_SUB_SLOT_NUM0 -1U)
+
+#if RCAR_QOS_TYPE  == RCAR_QOS_TYPE_DEFAULT
+
+/* Same as M3 Ver.1.1 default setting */
+#if RCAR_REF_INT == RCAR_REF_DEFAULT
+#include "qos_init_m3_v11_mstat195.h"
+#else
+#include "qos_init_m3_v11_mstat390.h"
+#endif
+
+#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE
+
+/* Same as M3 Ver.1.1 default setting */
+#if RCAR_REF_INT == RCAR_REF_DEFAULT
+#include "qos_init_m3_v11_qoswt195.h"
+#else
+#include "qos_init_m3_v11_qoswt390.h"
+#endif
+
+#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */
+#endif
+
+static void dbsc_setting(void)
+{
+	uint32_t md=0;
+
+	/* Register write enable */
+	io_write_32(DBSC_DBSYSCNT0, 0x00001234U);
+
+	/* BUFCAM settings */
+	io_write_32(DBSC_DBCAM0CNF1, 0x00043218);	//dbcam0cnf1
+	io_write_32(DBSC_DBCAM0CNF2, 0x000000F4);	//dbcam0cnf2
+	io_write_32(DBSC_DBCAM0CNF3, 0x00000000);	//dbcam0cnf3
+	io_write_32(DBSC_DBSCHCNT0,  0x000F0037);	//dbschcnt0
+	io_write_32(DBSC_DBSCHSZ0,   0x00000001);	//dbschsz0
+	io_write_32(DBSC_DBSCHRW0,   0x22421111);	//dbschrw0
+
+	md = (*((volatile uint32_t*)RST_MODEMR) & 0x000A0000) >> 17;
+
+	switch (md) {
+	case 0x0:
+		/* DDR3200 */
+		io_write_32(DBSC_SCFCTST2, 0x012F1123);
+		break;
+	case 0x1:	//MD19=0,MD17=1 : LPDDR4-3000, 4GByte(1GByte x4)
+		/* DDR2800 */
+		io_write_32(DBSC_SCFCTST2, 0x012F1123);
+		break;
+	case 0x4:	//MD19=1,MD17=0 : LPDDR4-2400, 4GByte(1GByte x4)
+		/* DDR2400 */
+		io_write_32(DBSC_SCFCTST2, 0x012F1123);
+		break;
+	default:	//MD19=1,MD17=1 : LPDDR4-1600, 4GByte(1GByte x4)
+		/* DDR1600 */
+		io_write_32(DBSC_SCFCTST2, 0x012F1123);
+		break;
+	}
+
+	/* QoS Settings */
+	io_write_32(DBSC_DBSCHQOS00,  0x00000F00);
+	io_write_32(DBSC_DBSCHQOS01,  0x00000B00);
+	io_write_32(DBSC_DBSCHQOS02,  0x00000000);
+	io_write_32(DBSC_DBSCHQOS03,  0x00000000);
+	io_write_32(DBSC_DBSCHQOS40,  0x00000300);
+	io_write_32(DBSC_DBSCHQOS41,  0x000002F0);
+	io_write_32(DBSC_DBSCHQOS42,  0x00000200);
+	io_write_32(DBSC_DBSCHQOS43,  0x00000100);
+	io_write_32(DBSC_DBSCHQOS90,  0x00000100);
+	io_write_32(DBSC_DBSCHQOS91,  0x000000F0);
+	io_write_32(DBSC_DBSCHQOS92,  0x000000A0);
+	io_write_32(DBSC_DBSCHQOS93,  0x00000040);
+	io_write_32(DBSC_DBSCHQOS120, 0x00000040);
+	io_write_32(DBSC_DBSCHQOS121, 0x00000030);
+	io_write_32(DBSC_DBSCHQOS122, 0x00000020);
+	io_write_32(DBSC_DBSCHQOS123, 0x00000010);
+	io_write_32(DBSC_DBSCHQOS130, 0x00000100);
+	io_write_32(DBSC_DBSCHQOS131, 0x000000F0);
+	io_write_32(DBSC_DBSCHQOS132, 0x000000A0);
+	io_write_32(DBSC_DBSCHQOS133, 0x00000040);
+	io_write_32(DBSC_DBSCHQOS140, 0x000000C0);
+	io_write_32(DBSC_DBSCHQOS141, 0x000000B0);
+	io_write_32(DBSC_DBSCHQOS142, 0x00000080);
+	io_write_32(DBSC_DBSCHQOS143, 0x00000040);
+	io_write_32(DBSC_DBSCHQOS150, 0x00000040);
+	io_write_32(DBSC_DBSCHQOS151, 0x00000030);
+	io_write_32(DBSC_DBSCHQOS152, 0x00000020);
+	io_write_32(DBSC_DBSCHQOS153, 0x00000010);
+
+	/* Register write protect */
+	io_write_32(DBSC_DBSYSCNT0, 0x00000000U);
+}
+
+void qos_init_m3_v30(void)
+{
+	dbsc_setting();
+
+	/* DRAM Split Address mapping */
+#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH
+ #if RCAR_LSI == RCAR_M3
+  #error "Don't set DRAM Split 4ch(M3)"
+ #else
+	ERROR("DRAM Split 4ch not supported.(M3)");
+	panic();
+ #endif
+#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \
+      (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO)
+	NOTICE("BL2: DRAM Split is 2ch\n");
+	io_write_32(AXI_ADSPLCR0, 0x00000000U);
+	io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT
+				  | ADSPLCR0_SPLITSEL(0xFFU)
+				  | ADSPLCR0_AREA(0x1DU)
+				  | ADSPLCR0_SWP);
+	io_write_32(AXI_ADSPLCR2, 0x00001004U);
+	io_write_32(AXI_ADSPLCR3, 0x00000000U);
+#else
+	NOTICE("BL2: DRAM Split is OFF\n");
+#endif
+
+#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE)
+#if RCAR_QOS_TYPE  == RCAR_QOS_TYPE_DEFAULT
+	NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION);
+#endif
+
+#if RCAR_REF_INT == RCAR_REF_DEFAULT
+	NOTICE("BL2: DRAM refresh interval 1.95 usec\n");
+#else
+	NOTICE("BL2: DRAM refresh interval 3.9 usec\n");
+#endif
+
+#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE
+	NOTICE("BL2: Periodic Write DQ Training\n");
+#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */
+
+	io_write_32(QOSCTRL_RAS, 0x00000044U);
+	io_write_64(QOSCTRL_DANN, 0x0404020002020201UL);
+	io_write_32(QOSCTRL_DANT, 0x0020100AU);
+	io_write_32(QOSCTRL_FSS, 0x0000000AU);
+	io_write_32(QOSCTRL_INSFC, 0x06330001U);
+	io_write_32(QOSCTRL_EARLYR, 0x00000001U);
+	io_write_32(QOSCTRL_RACNT0, 0x02010003U);	/* GPU Boost Mode ON */
+
+	/* GPU Boost Mode */
+	io_write_32(QOSCTRL_STATGEN0, 0x00000001U);
+
+	io_write_32(QOSCTRL_SL_INIT, SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK_M3_30);
+	io_write_32(QOSCTRL_REF_ARS, ((QOSCTRL_REF_ARS_ARBSTOPCYCLE_M3_30 << 16)));
+
+	{
+	uint32_t i;
+
+	for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) {
+		io_write_64(QOSBW_FIX_QOS_BANK0 + i*8,
+				mstat_fix[i]);
+		io_write_64(QOSBW_FIX_QOS_BANK1 + i*8,
+				mstat_fix[i]);
+	}
+	for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) {
+		io_write_64(QOSBW_BE_QOS_BANK0 + i*8,
+				mstat_be[i]);
+		io_write_64(QOSBW_BE_QOS_BANK1 + i*8,
+				mstat_be[i]);
+	}
+#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE
+	for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) {
+		io_write_64(QOSWT_FIX_WTQOS_BANK0 + i*8,
+				qoswt_fix[i]);
+		io_write_64(QOSWT_FIX_WTQOS_BANK1 + i*8,
+				qoswt_fix[i]);
+	}
+	for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) {
+		io_write_64(QOSWT_BE_WTQOS_BANK0 + i*8,
+				qoswt_be[i]);
+		io_write_64(QOSWT_BE_WTQOS_BANK1 + i*8,
+				qoswt_be[i]);
+	}
+#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */
+	}
+
+	/* RT bus Leaf setting */
+	io_write_32(RT_ACT0, 0x00000000U);
+	io_write_32(RT_ACT1, 0x00000000U);
+
+	/* CCI bus Leaf setting */
+	io_write_32(CPU_ACT0, 0x00000003U);
+	io_write_32(CPU_ACT1, 0x00000003U);
+	io_write_32(CPU_ACT2, 0x00000003U);
+	io_write_32(CPU_ACT3, 0x00000003U);
+
+	io_write_32(QOSCTRL_RAEN,  0x00000001U);
+
+#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE
+	/*  re-write training setting */
+	io_write_32(QOSWT_WTREF,  ((QOSWT_WTREF_SLOT1_EN << 16)       | QOSWT_WTREF_SLOT0_EN));
+	io_write_32(QOSWT_WTSET0, ((QOSWT_WTSET0_PERIOD0_M3_30 << 16) | (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0));
+	io_write_32(QOSWT_WTSET1, ((QOSWT_WTSET1_PERIOD1_M3_30 << 16) | (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1));
+
+	io_write_32(QOSWT_WTEN,   QOSWT_WTEN_ENABLE);
+#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */
+
+	io_write_32(QOSCTRL_STATQC, 0x00000001U);
+#else
+	NOTICE("BL2: QoS is None\n");
+
+	io_write_32(QOSCTRL_RAEN,  0x00000001U);
+#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */
+}
diff --git a/drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v30.h b/drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v30.h
new file mode 100644
index 0000000..a89d512
--- /dev/null
+++ b/drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v30.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef QOS_INIT_H_M3_V30__
+#define QOS_INIT_H_M3_V30__
+
+void qos_init_m3_v30(void);
+
+#endif	/* QOS_INIT_H_M3_V30__ */
diff --git a/drivers/staging/renesas/rcar/qos/qos.mk b/drivers/staging/renesas/rcar/qos/qos.mk
index 153d1d8..9fabc56 100644
--- a/drivers/staging/renesas/rcar/qos/qos.mk
+++ b/drivers/staging/renesas/rcar/qos/qos.mk
@@ -12,6 +12,7 @@
     BL2_SOURCES += drivers/staging/renesas/rcar/qos/H3/qos_init_h3_v30.c
     BL2_SOURCES += drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v10.c
     BL2_SOURCES += drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v11.c
+    BL2_SOURCES += drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v30.c
     BL2_SOURCES += drivers/staging/renesas/rcar/qos/M3N/qos_init_m3n_v10.c
 else ifdef RCAR_LSI_CUT_COMPAT
   ifeq (${RCAR_LSI},${RCAR_H3})
@@ -26,6 +27,7 @@
   ifeq (${RCAR_LSI},${RCAR_M3})
     BL2_SOURCES += drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v10.c
     BL2_SOURCES += drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v11.c
+    BL2_SOURCES += drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v30.c
   endif
   ifeq (${RCAR_LSI},${RCAR_M3N})
     BL2_SOURCES += drivers/staging/renesas/rcar/qos/M3N/qos_init_m3n_v10.c
@@ -61,9 +63,13 @@
      BL2_SOURCES += drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v10.c
     else ifeq (${LSI_CUT},11)
      BL2_SOURCES += drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v11.c
-    else
-#    LSI_CUT 11 or later
+    else ifeq (${LSI_CUT},13)
      BL2_SOURCES += drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v11.c
+    else ifeq (${LSI_CUT},30)
+     BL2_SOURCES += drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v30.c
+    else
+#    LSI_CUT 30 or later
+     BL2_SOURCES += drivers/staging/renesas/rcar/qos/M3/qos_init_m3_v30.c
     endif
   endif
   ifeq (${RCAR_LSI},${RCAR_M3N})
diff --git a/drivers/staging/renesas/rcar/qos/qos_common.h b/drivers/staging/renesas/rcar/qos/qos_common.h
index 9bad424..89dcf06 100644
--- a/drivers/staging/renesas/rcar/qos/qos_common.h
+++ b/drivers/staging/renesas/rcar/qos/qos_common.h
@@ -78,12 +78,16 @@
 /* define used for M3 */
 #if (RCAR_REF_INT == RCAR_REF_DEFAULT)	/* REF 1.95usec */
 #define SUB_SLOT_CYCLE_M3_11		(0x84U)	/* 132 */
+#define SUB_SLOT_CYCLE_M3_30		(0x84U)	/* 132 */
 #else /* REF 3.9usec */
 #define SUB_SLOT_CYCLE_M3_11		(0x108U)	/* 264 */
+#define SUB_SLOT_CYCLE_M3_30		(0x108U)	/* 264 */
 #endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */
 
 #define SL_INIT_SSLOTCLK_M3_11		(SUB_SLOT_CYCLE_M3_11 -1U)
+#define SL_INIT_SSLOTCLK_M3_30		(SUB_SLOT_CYCLE_M3_30 -1U)
 #define QOSWT_WTSET0_CYCLE_M3_11	((SUB_SLOT_CYCLE_M3_11 * BASE_SUB_SLOT_NUM * 1000U)/OPERATING_FREQ)	/* unit:ns */
+#define QOSWT_WTSET0_CYCLE_M3_30	((SUB_SLOT_CYCLE_M3_30 * BASE_SUB_SLOT_NUM * 1000U)/OPERATING_FREQ)	/* unit:ns */
 #endif
 
 #define OPERATING_FREQ			(400U)	/* MHz */
diff --git a/drivers/staging/renesas/rcar/qos/qos_init.c b/drivers/staging/renesas/rcar/qos/qos_init.c
index be4487a..affd425 100644
--- a/drivers/staging/renesas/rcar/qos/qos_init.c
+++ b/drivers/staging/renesas/rcar/qos/qos_init.c
@@ -18,6 +18,7 @@
 #include "H3/qos_init_h3_v30.h"
 #include "M3/qos_init_m3_v10.h"
 #include "M3/qos_init_m3_v11.h"
+#include "M3/qos_init_m3_v30.h"
 #include "M3N/qos_init_m3n_v10.h"
 #endif
 #if RCAR_LSI == RCAR_H3		/* H3 */
@@ -32,6 +33,7 @@
 #if RCAR_LSI == RCAR_M3		/* M3 */
 #include "M3/qos_init_m3_v10.h"
 #include "M3/qos_init_m3_v11.h"
+#include "M3/qos_init_m3_v30.h"
 #endif
 #if RCAR_LSI == RCAR_M3N	/* M3N */
 #include "M3N/qos_init_m3n_v10.h"
@@ -51,6 +53,7 @@
 #define PRR_PRODUCT_10		(0x00U)
 #define PRR_PRODUCT_11		(0x01U)
 #define PRR_PRODUCT_20		(0x10U)
+#define PRR_PRODUCT_21		(0x11U)
 #define PRR_PRODUCT_30		(0x20U)
 
 #if !(RCAR_LSI == RCAR_E3)
@@ -127,10 +130,13 @@
 		case PRR_PRODUCT_10:
 			qos_init_m3_v10();
 			break;
-		case PRR_PRODUCT_20:	/* M3 Cut 11 */
-		default:
+		case PRR_PRODUCT_21: /* M3 Cut 13 */
 			qos_init_m3_v11();
 			break;
+		case PRR_PRODUCT_30: /* M3 Cut 30 */
+		default:
+			qos_init_m3_v30();
+			break;
 		}
 #else
 		PRR_PRODUCT_ERR(reg);
@@ -210,13 +216,27 @@
 		PRR_PRODUCT_ERR(reg);
 	}
 	qos_init_m3_v10();
+#elif RCAR_LSI_CUT == RCAR_CUT_11
+	/* M3 Cut 11 */
+	if ((PRR_PRODUCT_M3 | PRR_PRODUCT_20)
+	    != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) {
+		PRR_PRODUCT_ERR(reg);
+	}
+	qos_init_m3_v11();
+#elif RCAR_LSI_CUT == RCAR_CUT_13
+	/* M3 Cut 13 */
+	if ((PRR_PRODUCT_M3 | PRR_PRODUCT_21)
+	    != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) {
+		PRR_PRODUCT_ERR(reg);
+	}
+	qos_init_m3_v11();
 #else
-	/* M3 Cut 11 or later */
+	/* M3 Cut 30 or later */
 	if ((PRR_PRODUCT_M3)
 	    != (reg & (PRR_PRODUCT_MASK))) {
 		PRR_PRODUCT_ERR(reg);
 	}
-	qos_init_m3_v11();
+	qos_init_m3_v30();
 #endif
 #elif RCAR_LSI == RCAR_M3N	/* M3N */
 	/* M3N Cut 10 or later */
@@ -277,6 +297,8 @@
 		case PRR_PRODUCT_10:
 			break;
 		case PRR_PRODUCT_20: /* M3 Cut 11 */
+		case PRR_PRODUCT_21: /* M3 Cut 13 */
+		case PRR_PRODUCT_30: /* M3 Cut 30 */
 		default:
 			refperiod = REFPERIOD_CYCLE;
 			break;
@@ -308,7 +330,9 @@
 #if RCAR_LSI_CUT == RCAR_CUT_10
 	/* M3 Cut 10 */
 #else
-	/* M3 Cut 11 or later */
+	/* M3 Cut 11 */
+	/* M3 Cut 13 */
+	/* M3 Cut 30 or later */
 	refperiod = REFPERIOD_CYCLE;
 #endif
 #elif RCAR_LSI == RCAR_M3N	/* for M3N */
diff --git a/drivers/synopsys/emmc/dw_mmc.c b/drivers/synopsys/emmc/dw_mmc.c
index 0c5c645..4cd1226 100644
--- a/drivers/synopsys/emmc/dw_mmc.c
+++ b/drivers/synopsys/emmc/dw_mmc.c
@@ -243,6 +243,11 @@
 		op = CMD_WAIT_PRVDATA_COMPLETE;
 		break;
 	case 8:
+		if (dw_params.mmc_dev_type == MMC_IS_EMMC)
+			op = CMD_DATA_TRANS_EXPECT | CMD_WAIT_PRVDATA_COMPLETE;
+		else
+			op = CMD_WAIT_PRVDATA_COMPLETE;
+		break;
 	case 17:
 	case 18:
 		op = CMD_DATA_TRANS_EXPECT | CMD_WAIT_PRVDATA_COMPLETE;
@@ -252,6 +257,9 @@
 		op = CMD_WRITE | CMD_DATA_TRANS_EXPECT |
 		     CMD_WAIT_PRVDATA_COMPLETE;
 		break;
+	case 51:
+		op = CMD_DATA_TRANS_EXPECT;
+		break;
 	default:
 		op = 0;
 		break;
@@ -337,7 +345,6 @@
 	uintptr_t base;
 
 	assert(((buf & DWMMC_ADDRESS_MASK) == 0) &&
-	       ((size % MMC_BLOCK_SIZE) == 0) &&
 	       (dw_params.desc_size > 0) &&
 	       ((dw_params.reg_base & MMC_BLOCK_MASK) == 0) &&
 	       ((dw_params.desc_base & MMC_BLOCK_MASK) == 0) &&
@@ -352,6 +359,12 @@
 	base = dw_params.reg_base;
 	desc = (struct dw_idmac_desc *)dw_params.desc_base;
 	mmio_write_32(base + DWMMC_BYTCNT, size);
+
+	if (size < MMC_BLOCK_SIZE)
+		mmio_write_32(base + DWMMC_BLKSIZ, size);
+	else
+		mmio_write_32(base + DWMMC_BLKSIZ, MMC_BLOCK_SIZE);
+
 	mmio_write_32(base + DWMMC_RINTSTS, ~0);
 	for (i = 0; i < desc_cnt; i++) {
 		desc[i].des0 = IDMAC_DES0_OWN | IDMAC_DES0_CH | IDMAC_DES0_DIC;
@@ -375,11 +388,22 @@
 	flush_dcache_range(dw_params.desc_base,
 			   desc_cnt * DWMMC_DMA_MAX_BUFFER_SIZE);
 
+
 	return 0;
 }
 
 static int dw_read(int lba, uintptr_t buf, size_t size)
 {
+	uint32_t data = 0;
+	int timeout = TIMEOUT;
+
+	do {
+		data = mmio_read_32(dw_params.reg_base + DWMMC_RINTSTS);
+		udelay(50);
+	} while (!(data & INT_DTO) && timeout-- > 0);
+
+	inv_dcache_range(buf, size);
+
 	return 0;
 }
 
@@ -401,6 +425,9 @@
 		(params->bus_width == MMC_BUS_WIDTH_8)));
 
 	memcpy(&dw_params, params, sizeof(dw_mmc_params_t));
+	mmio_write_32(dw_params.reg_base + DWMMC_FIFOTH, 0x103ff);
 	mmc_init(&dw_mmc_ops, params->clk_rate, params->bus_width,
 		 params->flags, info);
+
+	dw_params.mmc_dev_type = info->mmc_dev_type;
 }
diff --git a/fdts/stm32mp157a-dk1.dts b/fdts/stm32mp157a-dk1.dts
index cf0fe28..68188be 100644
--- a/fdts/stm32mp157a-dk1.dts
+++ b/fdts/stm32mp157a-dk1.dts
@@ -173,6 +173,7 @@
 /* ATF Specific */
 #include <dt-bindings/clock/stm32mp1-clksrc.h>
 #include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi"
+#include "stm32mp157c-security.dtsi"
 
 / {
 	aliases {
@@ -188,14 +189,6 @@
 		gpio25 = &gpioz;
 		i2c3 = &i2c4;
 	};
-
-	soc {
-		stgen: stgen@5C008000 {
-			compatible = "st,stm32-stgen";
-			reg = <0x5C008000 0x1000>;
-			status = "okay";
-		};
-	};
 };
 
 /* CLOCK init */
diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts
index 0fadffb..820e413 100644
--- a/fdts/stm32mp157c-ed1.dts
+++ b/fdts/stm32mp157c-ed1.dts
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2017-2019 - All Rights Reserved
  * Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
  */
 /dts-v1/;
@@ -191,6 +191,7 @@
 /* ATF Specific */
 #include <dt-bindings/clock/stm32mp1-clksrc.h>
 #include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi"
+#include "stm32mp157c-security.dtsi"
 
 / {
 	aliases {
@@ -208,14 +209,6 @@
 		gpio25 = &gpioz;
 		i2c3 = &i2c4;
 	};
-
-	soc {
-		stgen: stgen@5C008000 {
-			compatible = "st,stm32-stgen";
-			reg = <0x5C008000 0x1000>;
-			status = "okay";
-		};
-	};
 };
 
 /* CLOCK init */
diff --git a/fdts/stm32mp157c-security.dtsi b/fdts/stm32mp157c-security.dtsi
new file mode 100644
index 0000000..fb04e7d
--- /dev/null
+++ b/fdts/stm32mp157c-security.dtsi
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier:	GPL-2.0+	BSD-3-Clause
+ */
+
+/ {
+	soc {
+		stgen: stgen@5C008000 {
+			compatible = "st,stm32-stgen";
+			reg = <0x5C008000 0x1000>;
+			status = "okay";
+		};
+	};
+};
+
+&bsec {
+	mac_addr: mac_addr@e4 {
+		reg = <0xe4 0x6>;
+		status = "okay";
+		secure-status = "okay";
+	};
+	/* Spare field to align on 32-bit OTP granularity  */
+	spare_ns_ea: spare_ns_ea@ea {
+		reg = <0xea 0x2>;
+		status = "okay";
+		secure-status = "okay";
+	};
+	board_id: board_id@ec {
+		reg = <0xec 0x4>;
+		status = "okay";
+		secure-status = "okay";
+	};
+};
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index debe872..d3c5bea 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -843,4 +843,9 @@
 #define DIT			S3_3_C4_C2_5
 #define DIT_BIT			BIT(24)
 
+/*******************************************************************************
+ * Armv8.5 - new MSR encoding to directly access PSTATE.SSBS field
+ ******************************************************************************/
+#define SSBS			S3_3_C4_C2_6
+
 #endif /* ARCH_H */
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 495ecb3..6af1d03 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -34,10 +34,12 @@
 	return (read_id_aa64isar1_el1() & mask) != 0U;
 }
 
-static inline bool is_armv8_3_pauth_api_present(void)
+static inline bool is_armv8_3_pauth_apa_api_present(void)
 {
-	return ((read_id_aa64isar1_el1() >> ID_AA64ISAR1_API_SHIFT) &
-		ID_AA64ISAR1_API_MASK) != 0U;
+	uint64_t mask = (ID_AA64ISAR1_API_MASK << ID_AA64ISAR1_API_SHIFT) |
+			(ID_AA64ISAR1_APA_MASK << ID_AA64ISAR1_APA_SHIFT);
+
+	return (read_id_aa64isar1_el1() & mask) != 0U;
 }
 
 static inline bool is_armv8_4_ttst_present(void)
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 836d61e..2fce668 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -208,6 +208,7 @@
 DEFINE_SYSREG_READ_FUNC(id_pfr1_el1)
 DEFINE_SYSREG_READ_FUNC(id_aa64isar1_el1)
 DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1)
+DEFINE_SYSREG_READ_FUNC(id_aa64pfr1_el1)
 DEFINE_SYSREG_READ_FUNC(id_aa64dfr0_el1)
 DEFINE_SYSREG_READ_FUNC(id_afr0_el1)
 DEFINE_SYSREG_READ_FUNC(CurrentEl)
diff --git a/include/common/bl_common.h b/include/common/bl_common.h
index 9817ec7..457dc2a 100644
--- a/include/common/bl_common.h
+++ b/include/common/bl_common.h
@@ -57,6 +57,48 @@
 #define FIQ_AARCH32			U(0xe)
 #define SERROR_AARCH32			U(0xf)
 
+/*
+ * Mapping to connect linker symbols from .ld.S with their counterparts
+ * from .scat for the BL31 image
+ */
+#if defined(USE_ARM_LINK)
+#define __BL31_END__			Load$$LR$$LR_END$$Base
+#define __BSS_START__			Load$$LR$$LR_BSS$$Base
+#define __BSS_END__			Load$$LR$$LR_BSS$$Limit
+#define __BSS_SIZE__			Load$$LR$$LR_BSS$$Length
+#define __COHERENT_RAM_START__		Load$$LR$$LR_COHERENT_RAM$$Base
+#define __COHERENT_RAM_END_UNALIGNED__	Load$$__COHERENT_RAM_EPILOGUE_UNALIGNED__$$Base
+#define __COHERENT_RAM_END__		Load$$LR$$LR_COHERENT_RAM$$Limit
+#define __COHERENT_RAM_UNALIGNED_SIZE__	Load$$__COHERENT_RAM__$$Length
+#define __CPU_OPS_START__		Load$$__CPU_OPS__$$Base
+#define __CPU_OPS_END__			Load$$__CPU_OPS__$$Limit
+#define __DATA_START__			Load$$__DATA__$$Base
+#define __DATA_END__			Load$$__DATA__$$Limit
+#define __GOT_START__			Load$$__GOT__$$Base
+#define __GOT_END__			Load$$__GOT__$$Limit
+#define __PERCPU_BAKERY_LOCK_START__	Load$$__BAKERY_LOCKS__$$Base
+#define __PERCPU_BAKERY_LOCK_END__	Load$$__BAKERY_LOCKS_EPILOGUE__$$Base
+#define __PMF_SVC_DESCS_START__		Load$$__PMF_SVC_DESCS__$$Base
+#define __PMF_SVC_DESCS_END__		Load$$__PMF_SVC_DESCS__$$Limit
+#define __PMF_TIMESTAMP_START__		Load$$__PMF_TIMESTAMP__$$Base
+#define __PMF_TIMESTAMP_END__		Load$$__PER_CPU_TIMESTAMPS__$$Limit
+#define __PMF_PERCPU_TIMESTAMP_END__	Load$$__PMF_TIMESTAMP_EPILOGUE__$$Base
+#define __RELA_END__			Load$$__RELA__$$Limit
+#define __RELA_START__			Load$$__RELA__$$Base
+#define __RODATA_START__		Load$$__RODATA__$$Base
+#define __RODATA_END__			Load$$__RODATA_EPILOGUE__$$Base
+#define __RT_SVC_DESCS_START__		Load$$__RT_SVC_DESCS__$$Base
+#define __RT_SVC_DESCS_END__		Load$$__RT_SVC_DESCS__$$Limit
+#define __RW_START__			Load$$LR$$LR_RW_DATA$$Base
+#define __RW_END__			Load$$LR$$LR_END$$Base
+#define __SPM_SHIM_EXCEPTIONS_START__	Load$$__SPM_SHIM_EXCEPTIONS__$$Base
+#define __SPM_SHIM_EXCEPTIONS_END__	Load$$__SPM_SHIM_EXCEPTIONS_EPILOGUE__$$Base
+#define __STACKS_START__		Load$$__STACKS__$$Base
+#define __STACKS_END__			Load$$__STACKS__$$Limit
+#define __TEXT_START__			Load$$__TEXT__$$Base
+#define __TEXT_END__			Load$$__TEXT_EPILOGUE__$$Base
+#endif /* USE_ARM_LINK */
+
 #ifndef __ASSEMBLY__
 
 #include <stddef.h>
diff --git a/include/drivers/arm/css/css_mhu_doorbell.h b/include/drivers/arm/css/css_mhu_doorbell.h
index ecee563..e6f7a1b 100644
--- a/include/drivers/arm/css/css_mhu_doorbell.h
+++ b/include/drivers/arm/css/css_mhu_doorbell.h
@@ -12,7 +12,7 @@
 #include <lib/mmio.h>
 
 /* MHUv2 Base Address */
-#define MHUV2_BASE_ADDR		PLAT_CSS_MHU_BASE
+#define MHUV2_BASE_ADDR		PLAT_MHUV2_BASE
 
 /* MHUv2 Control Registers Offsets */
 #define MHU_V2_MSG_NO_CAP_OFFSET		0xF80
diff --git a/include/drivers/io/io_storage.h b/include/drivers/io/io_storage.h
index ec6db3f..084c67c 100644
--- a/include/drivers/io/io_storage.h
+++ b/include/drivers/io/io_storage.h
@@ -79,8 +79,6 @@
  * re-initialisation */
 int io_dev_init(uintptr_t dev_handle, const uintptr_t init_params);
 
-/* TODO: Consider whether an explicit "shutdown" API should be included */
-
 /* Close a connection to a device */
 int io_dev_close(uintptr_t dev_handle);
 
diff --git a/include/drivers/mmc.h b/include/drivers/mmc.h
index 2aaa28d..7611f01 100644
--- a/include/drivers/mmc.h
+++ b/include/drivers/mmc.h
@@ -220,6 +220,7 @@
 	unsigned long long	device_size;	/* Size of device in bytes */
 	unsigned int		block_size;	/* Block size in bytes */
 	unsigned int		max_bus_freq;	/* Max bus freq in Hz */
+	unsigned int		ocr_voltage;	/* OCR voltage */
 	enum mmc_device_type	mmc_dev_type;	/* Type of MMC */
 };
 
diff --git a/include/drivers/synopsys/dw_mmc.h b/include/drivers/synopsys/dw_mmc.h
index 7031e0f..2004355 100644
--- a/include/drivers/synopsys/dw_mmc.h
+++ b/include/drivers/synopsys/dw_mmc.h
@@ -16,6 +16,7 @@
 	int		clk_rate;
 	int		bus_width;
 	unsigned int	flags;
+	enum mmc_device_type	mmc_dev_type;
 } dw_mmc_params_t;
 
 void dw_mmc_init(dw_mmc_params_t *params, struct mmc_device_info *info);
diff --git a/include/lib/cpus/aarch32/cortex_a15.h b/include/lib/cpus/aarch32/cortex_a15.h
index 957afbd..9526a9c 100644
--- a/include/lib/cpus/aarch32/cortex_a15.h
+++ b/include/lib/cpus/aarch32/cortex_a15.h
@@ -10,6 +10,13 @@
 #include <lib/utils_def.h>
 
 /*******************************************************************************
+ * Auxiliary Control Register 2 specific definitions.
+ ******************************************************************************/
+#define CORTEX_A15_ACTLR2			p15, 1, c15, c0, 4
+
+#define CORTEX_A15_ACTLR2_INV_DCC_BIT		(U(1) << 0)
+
+/*******************************************************************************
  * Cortex-A15 midr with version/revision set to 0
  ******************************************************************************/
 #define CORTEX_A15_MIDR			U(0x410FC0F0)
diff --git a/include/lib/cpus/aarch32/cortex_a17.h b/include/lib/cpus/aarch32/cortex_a17.h
index 4b05216..89a8eb6 100644
--- a/include/lib/cpus/aarch32/cortex_a17.h
+++ b/include/lib/cpus/aarch32/cortex_a17.h
@@ -19,4 +19,9 @@
  ******************************************************************************/
 #define CORTEX_A17_ACTLR_SMP_BIT	(U(1) << 6)
 
+/*******************************************************************************
+ * Implementation defined register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A17_IMP_DEF_REG1		p15, 0, c15, c0, 1
+
 #endif /* CORTEX_A17_H */
diff --git a/include/lib/cpus/aarch64/cortex_a73.h b/include/lib/cpus/aarch64/cortex_a73.h
index 61b2b73..1238c0e 100644
--- a/include/lib/cpus/aarch64/cortex_a73.h
+++ b/include/lib/cpus/aarch64/cortex_a73.h
@@ -31,6 +31,8 @@
 
 #define CORTEX_A73_IMP_DEF_REG1_DISABLE_LOAD_PASS_STORE	(ULL(1) << 3)
 
+#define CORTEX_A73_DIAGNOSTIC_REGISTER	S3_0_C15_C0_1
+
 #define CORTEX_A73_IMP_DEF_REG2		S3_0_C15_C0_2
 
 #endif /* CORTEX_A73_H */
diff --git a/include/lib/cpus/aarch64/neoverse_zeus.h b/include/lib/cpus/aarch64/neoverse_zeus.h
new file mode 100644
index 0000000..f094727
--- /dev/null
+++ b/include/lib/cpus/aarch64/neoverse_zeus.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2019, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef NEOVERSE_ZEUS_H
+#define NEOVERSE_ZEUS_H
+
+#define NEOVERSE_ZEUS_MIDR					U(0x410FD400)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions.
+ ******************************************************************************/
+#define NEOVERSE_ZEUS_CPUECTLR_EL1				S3_0_C15_C1_4
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions
+ ******************************************************************************/
+#define NEOVERSE_ZEUS_CPUPWRCTLR_EL1				S3_0_C15_C2_7
+#define NEOVERSE_ZEUS_CPUPWRCTLR_EL1_CORE_PWRDN_BIT		U(1)
+
+#endif /* NEOVERSE_ZEUS_H */
diff --git a/include/lib/el3_runtime/pubsub.h b/include/lib/el3_runtime/pubsub.h
index 9c303f5..64fe5cc 100644
--- a/include/lib/el3_runtime/pubsub.h
+++ b/include/lib/el3_runtime/pubsub.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,13 +7,11 @@
 #ifndef PUBSUB_H
 #define PUBSUB_H
 
-#define __pubsub_start_sym(event)	__pubsub_##event##_start
-#define __pubsub_end_sym(event)		__pubsub_##event##_end
-
 #ifdef __LINKER__
 
 /* For the linker ... */
-
+#define __pubsub_start_sym(event)	__pubsub_##event##_start
+#define __pubsub_end_sym(event)		__pubsub_##event##_end
 #define __pubsub_section(event)		__pubsub_##event
 
 /*
@@ -21,10 +19,22 @@
  * contexts. In linker context, this collects pubsub sections for each event,
  * placing guard symbols around each.
  */
+#if defined(USE_ARM_LINK)
+#define REGISTER_PUBSUB_EVENT(event) \
+	__pubsub_start_sym(event) +0 FIXED \
+	{ \
+		*(__pubsub_section(event)) \
+	} \
+	__pubsub_end_sym(event) +0 FIXED EMPTY 0 \
+	{ \
+		/* placeholder */ \
+	}
+#else
 #define REGISTER_PUBSUB_EVENT(event) \
 	__pubsub_start_sym(event) = .; \
 	KEEP(*(__pubsub_section(event))); \
 	__pubsub_end_sym(event) = .
+#endif
 
 #else /* __LINKER__ */
 
@@ -36,6 +46,14 @@
 
 #include <arch_helpers.h>
 
+#if defined(USE_ARM_LINK)
+#define __pubsub_start_sym(event)	Load$$__pubsub_##event##_start$$Base
+#define __pubsub_end_sym(event)		Load$$__pubsub_##event##_end$$Base
+#else
+#define __pubsub_start_sym(event)	__pubsub_##event##_start
+#define __pubsub_end_sym(event)		__pubsub_##event##_end
+#endif
+
 #define __pubsub_section(event)		__section("__pubsub_" #event)
 
 /*
diff --git a/lib/aarch64/misc_helpers.S b/lib/aarch64/misc_helpers.S
index de11583..a24bf90 100644
--- a/lib/aarch64/misc_helpers.S
+++ b/lib/aarch64/misc_helpers.S
@@ -531,8 +531,8 @@
 #endif
 	/*
 	 * Calculate the offset based on return address in x30.
-	 * Assume that this funtion is called within a page of the start of
-	 * of fixup region.
+	 * Assume that this function is called within a page at the start of
+	 * fixup region.
 	 */
 	and	x2, x30, #~(PAGE_SIZE - 1)
 	sub	x0, x2, x6	/* Diff(S) = Current Address - Compiled Address */
@@ -580,13 +580,13 @@
 	 *
 	 * r_offset is address of reference
 	 * r_info is symbol index and type of relocation (in this case
-	 * 0x403 which corresponds to R_AARCH64_RELATIV).
+	 * 0x403 which corresponds to R_AARCH64_RELATIVE).
 	 * r_addend is constant part of expression.
 	 *
 	 * Size of Elf64_Rela structure is 24 bytes.
 	 */
 1:
-	/* Assert that the relocation type is R_AARCH64_RELATIV */
+	/* Assert that the relocation type is R_AARCH64_RELATIVE */
 #if ENABLE_ASSERTIONS
 	ldr	x3, [x1, #8]
 	cmp	x3, #0x403
diff --git a/lib/cpus/aarch32/cortex_a15.S b/lib/cpus/aarch32/cortex_a15.S
index b6c61ab..ab136ad 100644
--- a/lib/cpus/aarch32/cortex_a15.S
+++ b/lib/cpus/aarch32/cortex_a15.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -29,6 +29,13 @@
 	bic	r0, #CORTEX_A15_ACTLR_SMP_BIT
 	stcopr	r0, ACTLR
 	isb
+#if ERRATA_A15_816470
+	/*
+	 * Invalidate any TLB address
+	 */
+	mov	r0, #0
+	stcopr	r0, TLBIMVA
+#endif
 	dsb	sy
 	bx	lr
 endfunc cortex_a15_disable_smp
@@ -41,6 +48,49 @@
 	bx	lr
 endfunc cortex_a15_enable_smp
 
+	/* ----------------------------------------------------
+	 * Errata Workaround for Cortex A15 Errata #816470.
+	 * This applies only to revision >= r3p0 of Cortex A15.
+	 * ----------------------------------------------------
+	 */
+func check_errata_816470
+	/*
+	 * Even though this is only needed for revision >= r3p0, it is always
+	 * applied because of the low cost of the workaround.
+	 */
+	mov	r0, #ERRATA_APPLIES
+	bx	lr
+endfunc check_errata_816470
+
+	/* ----------------------------------------------------
+	 * Errata Workaround for Cortex A15 Errata #827671.
+	 * This applies only to revision >= r3p0 of Cortex A15.
+	 * Inputs:
+	 * r0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: r0-r3
+	 * ----------------------------------------------------
+	 */
+func errata_a15_827671_wa
+	/*
+	 * Compare r0 against revision r3p0
+	 */
+	mov	r2, lr
+	bl	check_errata_827671
+	cmp	r0, #ERRATA_NOT_APPLIES
+	beq	1f
+	ldcopr	r0, CORTEX_A15_ACTLR2
+	orr	r0, #CORTEX_A15_ACTLR2_INV_DCC_BIT
+	stcopr	r0, CORTEX_A15_ACTLR2
+	isb
+1:
+	bx	r2
+endfunc errata_a15_827671_wa
+
+func check_errata_827671
+	mov	r1, #0x30
+	b	cpu_rev_var_hs
+endfunc check_errata_827671
+
 func check_errata_cve_2017_5715
 #if WORKAROUND_CVE_2017_5715
 	mov	r0, #ERRATA_APPLIES
@@ -64,6 +114,8 @@
 	 * Report all errata. The revision-variant information is passed to
 	 * checking functions of each errata.
 	 */
+	report_errata ERRATA_A15_816470, cortex_a15, 816470
+	report_errata ERRATA_A15_827671, cortex_a15, 827671
 	report_errata WORKAROUND_CVE_2017_5715, cortex_a15, cve_2017_5715
 
 	pop	{r12, lr}
@@ -72,6 +124,13 @@
 #endif
 
 func cortex_a15_reset_func
+	mov	r5, lr
+	bl	cpu_get_rev_var
+
+#if ERRATA_A15_827671
+	bl	errata_a15_827671_wa
+#endif
+
 #if IMAGE_BL32 && WORKAROUND_CVE_2017_5715
 	ldcopr	r0, ACTLR
 	orr	r0, #CORTEX_A15_ACTLR_INV_BTB_BIT
@@ -81,6 +140,8 @@
 	stcopr	r0, MVBAR
 	/* isb will be applied in the course of the reset func */
 #endif
+
+	mov	lr, r5
 	b	cortex_a15_enable_smp
 endfunc cortex_a15_reset_func
 
diff --git a/lib/cpus/aarch32/cortex_a17.S b/lib/cpus/aarch32/cortex_a17.S
index b84c126..b8abd33 100644
--- a/lib/cpus/aarch32/cortex_a17.S
+++ b/lib/cpus/aarch32/cortex_a17.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -35,6 +35,62 @@
 	bx	lr
 endfunc cortex_a17_enable_smp
 
+	/* ----------------------------------------------------
+	 * Errata Workaround for Cortex A17 Errata #852421.
+	 * This applies only to revision <= r1p2 of Cortex A17.
+	 * Inputs:
+	 * r0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: r0-r3
+	 * ----------------------------------------------------
+	 */
+func errata_a17_852421_wa
+	/*
+	 * Compare r0 against revision r1p2
+	 */
+	mov	r2, lr
+	bl	check_errata_852421
+	cmp	r0, #ERRATA_NOT_APPLIES
+	beq	1f
+	ldcopr	r0, CORTEX_A17_IMP_DEF_REG1
+	orr	r0, r0, #(1<<24)
+	stcopr	r0, CORTEX_A17_IMP_DEF_REG1
+1:
+	bx	r2
+endfunc errata_a17_852421_wa
+
+func check_errata_852421
+	mov	r1, #0x12
+	b	cpu_rev_var_ls
+endfunc check_errata_852421
+
+	/* ----------------------------------------------------
+	 * Errata Workaround for Cortex A17 Errata #852423.
+	 * This applies only to revision <= r1p2 of Cortex A17.
+	 * Inputs:
+	 * r0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: r0-r3
+	 * ----------------------------------------------------
+	 */
+func errata_a17_852423_wa
+	/*
+	 * Compare r0 against revision r1p2
+	 */
+	mov	r2, lr
+	bl	check_errata_852423
+	cmp	r0, #ERRATA_NOT_APPLIES
+	beq	1f
+	ldcopr	r0, CORTEX_A17_IMP_DEF_REG1
+	orr	r0, r0, #(1<<12)
+	stcopr	r0, CORTEX_A17_IMP_DEF_REG1
+1:
+	bx	r2
+endfunc errata_a17_852423_wa
+
+func check_errata_852423
+	mov	r1, #0x12
+	b	cpu_rev_var_ls
+endfunc check_errata_852423
+
 func check_errata_cve_2017_5715
 #if WORKAROUND_CVE_2017_5715
 	mov	r0, #ERRATA_APPLIES
@@ -58,6 +114,8 @@
 	 * Report all errata. The revision-variant information is passed to
 	 * checking functions of each errata.
 	 */
+	report_errata ERRATA_A17_852421, cortex_a17, 852421
+	report_errata ERRATA_A17_852423, cortex_a17, 852423
 	report_errata WORKAROUND_CVE_2017_5715, cortex_a17, cve_2017_5715
 
 	pop	{r12, lr}
@@ -66,12 +124,28 @@
 #endif
 
 func cortex_a17_reset_func
+	mov	r5, lr
+	bl	cpu_get_rev_var
+	mov	r4, r0
+
+#if ERRATA_A17_852421
+	mov	r0, r4
+	bl	errata_a17_852421_wa
+#endif
+
+#if ERRATA_A17_852423
+	mov	r0, r4
+	bl	errata_a17_852423_wa
+#endif
+
 #if IMAGE_BL32 && WORKAROUND_CVE_2017_5715
 	ldr	r0, =workaround_bpiall_runtime_exceptions
 	stcopr	r0, VBAR
 	stcopr	r0, MVBAR
 	/* isb will be applied in the course of the reset func */
 #endif
+
+	mov	lr, r5
 	b	cortex_a17_enable_smp
 endfunc cortex_a17_reset_func
 
diff --git a/lib/cpus/aarch32/cpu_helpers.S b/lib/cpus/aarch32/cpu_helpers.S
index f84cd0d..9b5d787 100644
--- a/lib/cpus/aarch32/cpu_helpers.S
+++ b/lib/cpus/aarch32/cpu_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,7 @@
 #include <asm_macros.S>
 #include <assert_macros.S>
 #include <cpu_macros.S>
+#include <common/bl_common.h>
 #include <lib/el3_runtime/cpu_data.h>
 
 #if defined(IMAGE_BL1) || defined(IMAGE_BL32) || (defined(IMAGE_BL2) && BL2_AT_EL3)
@@ -21,9 +22,9 @@
 	 */
 	.globl	reset_handler
 func reset_handler
-	mov	r10, lr
+	mov	r8, lr
 
-	/* The plat_reset_handler can clobber r0 - r9 */
+	/* The plat_reset_handler can clobber r0 - r7 */
 	bl	plat_reset_handler
 
 	/* Get the matching cpu_ops pointer (clobbers: r0 - r5) */
@@ -37,7 +38,7 @@
 	/* Get the cpu_ops reset handler */
 	ldr	r1, [r0, #CPU_RESET_FUNC]
 	cmp	r1, #0
-	mov	lr, r10
+	mov	lr, r8
 	bxne	r1
 	bx	lr
 endfunc reset_handler
diff --git a/lib/cpus/aarch64/cortex_a73.S b/lib/cpus/aarch64/cortex_a73.S
index 6cfa4b5..5c8a887 100644
--- a/lib/cpus/aarch64/cortex_a73.S
+++ b/lib/cpus/aarch64/cortex_a73.S
@@ -36,6 +36,34 @@
 endfunc cortex_a73_disable_smp
 
 	/* ---------------------------------------------------
+	 * Errata Workaround for Cortex A73 Errata #852427.
+	 * This applies only to revision r0p0 of Cortex A73.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * ---------------------------------------------------
+	 */
+func errata_a73_852427_wa
+	/*
+	 * Compare x0 against revision r0p0
+	 */
+	mov	x17, x30
+	bl	check_errata_852427
+	cbz	x0, 1f
+	mrs	x1, CORTEX_A73_DIAGNOSTIC_REGISTER
+	orr	x1, x1, #(1 << 12)
+	msr	CORTEX_A73_DIAGNOSTIC_REGISTER, x1
+	isb
+1:
+	ret	x17
+endfunc errata_a73_852427_wa
+
+func check_errata_852427
+	mov	x1, #0x00
+	b	cpu_rev_var_ls
+endfunc check_errata_852427
+
+	/* ---------------------------------------------------
 	 * Errata Workaround for Cortex A73 Errata #855423.
 	 * This applies only to revision <= r0p1 of Cortex A73.
 	 * Inputs:
@@ -71,8 +99,15 @@
 func cortex_a73_reset_func
 	mov	x19, x30
 	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_A73_852427
+	mov	x0, x18
+	bl	errata_a73_852427_wa
+#endif
 
 #if ERRATA_A73_855423
+	mov	x0, x18
 	bl	errata_a73_855423_wa
 #endif
 
@@ -200,6 +235,7 @@
 	 * Report all errata. The revision-variant information is passed to
 	 * checking functions of each errata.
 	 */
+	report_errata ERRATA_A73_852427, cortex_a73, 852427
 	report_errata ERRATA_A73_855423, cortex_a73, 855423
 	report_errata WORKAROUND_CVE_2017_5715, cortex_a73, cve_2017_5715
 	report_errata WORKAROUND_CVE_2018_3639, cortex_a73, cve_2018_3639
diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S
index 74d7bb2..de1177c 100644
--- a/lib/cpus/aarch64/cpu_helpers.S
+++ b/lib/cpus/aarch64/cpu_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,6 +7,7 @@
 #include <arch.h>
 #include <asm_macros.S>
 #include <assert_macros.S>
+#include <common/bl_common.h>
 #include <common/debug.h>
 #include <cpu_macros.S>
 #include <lib/cpus/errata_report.h>
diff --git a/lib/cpus/aarch64/neoverse_n1.S b/lib/cpus/aarch64/neoverse_n1.S
index c6a5c08..060c625 100644
--- a/lib/cpus/aarch64/neoverse_n1.S
+++ b/lib/cpus/aarch64/neoverse_n1.S
@@ -46,6 +46,10 @@
 
 func neoverse_n1_reset_func
 	mov	x19, x30
+
+	/* Disables speculative loads */
+	msr	SSBS, xzr
+
 	bl	cpu_get_rev_var
 	mov	x18, x0
 
diff --git a/lib/cpus/aarch64/neoverse_zeus.S b/lib/cpus/aarch64/neoverse_zeus.S
new file mode 100644
index 0000000..79c8b2f
--- /dev/null
+++ b/lib/cpus/aarch64/neoverse_zeus.S
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <neoverse_zeus.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+	/* ---------------------------------------------
+	 * HW will do the cache maintenance while powering down
+	 * ---------------------------------------------
+	 */
+func neoverse_zeus_core_pwr_dwn
+	/* ---------------------------------------------
+	 * Enable CPU power down bit in power control register
+	 * ---------------------------------------------
+	 */
+	mrs	x0, NEOVERSE_ZEUS_CPUPWRCTLR_EL1
+	orr	x0, x0, #NEOVERSE_ZEUS_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+	msr	NEOVERSE_ZEUS_CPUPWRCTLR_EL1, x0
+	isb
+	ret
+endfunc neoverse_zeus_core_pwr_dwn
+
+	/*
+	 * Errata printing function for Neoverse Zeus. Must follow AAPCS.
+	 */
+#if REPORT_ERRATA
+func neoverse_zeus_errata_report
+	ret
+endfunc neoverse_zeus_errata_report
+#endif
+
+	/* ---------------------------------------------
+	 * This function provides Neoverse-Zeus specific
+	 * register information for crash reporting.
+	 * It needs to return with x6 pointing to
+	 * a list of register names in ascii and
+	 * x8 - x15 having values of registers to be
+	 * reported.
+	 * ---------------------------------------------
+	 */
+.section .rodata.neoverse_zeus_regs, "aS"
+neoverse_zeus_regs:  /* The ascii list of register names to be reported */
+	.asciz	"cpuectlr_el1", ""
+
+func neoverse_zeus_cpu_reg_dump
+	adr	x6, neoverse_zeus_regs
+	mrs	x8, NEOVERSE_ZEUS_CPUECTLR_EL1
+	ret
+endfunc neoverse_zeus_cpu_reg_dump
+
+declare_cpu_ops neoverse_zeus, NEOVERSE_ZEUS_MIDR, \
+	CPU_NO_RESET_FUNC, \
+	neoverse_zeus_core_pwr_dwn
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 2d3984e..c42eb1c 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -53,6 +53,22 @@
 # These should be enabled by the platform if the erratum workaround needs to be
 # applied.
 
+# Flag to apply erratum 816470 workaround during power down. This erratum
+# applies only to revision >= r3p0 of the Cortex A15 cpu.
+ERRATA_A15_816470	?=0
+
+# Flag to apply erratum 827671 workaround during reset. This erratum applies
+# only to revision >= r3p0 of the Cortex A15 cpu.
+ERRATA_A15_827671	?=0
+
+# Flag to apply erratum 852421 workaround during reset. This erratum applies
+# only to revision <= r1p2 of the Cortex A17 cpu.
+ERRATA_A17_852421	?=0
+
+# Flag to apply erratum 852423 workaround during reset. This erratum applies
+# only to revision <= r1p2 of the Cortex A17 cpu.
+ERRATA_A17_852423	?=0
+
 # Flag to apply erratum 819472 workaround during reset. This erratum applies
 # only to revision <= r0p1 of the Cortex A53 cpu.
 ERRATA_A53_819472	?=0
@@ -159,6 +175,10 @@
 # only to revision <= r0p3 of the Cortex A72 cpu.
 ERRATA_A72_859971	?=0
 
+# Flag to apply erratum 852427 workaround during reset. This erratum applies
+# only to revision r0p0 of the Cortex A73 cpu.
+ERRATA_A73_852427	?=0
+
 # Flag to apply erratum 855423 workaround during reset. This erratum applies
 # only to revision <= r0p1 of the Cortex A73 cpu.
 ERRATA_A73_855423	?=0
@@ -192,6 +212,22 @@
 # higher DSU power consumption on idle.
 ERRATA_DSU_936184	?=0
 
+# Process ERRATA_A15_816470 flag
+$(eval $(call assert_boolean,ERRATA_A15_816470))
+$(eval $(call add_define,ERRATA_A15_816470))
+
+# Process ERRATA_A15_827671 flag
+$(eval $(call assert_boolean,ERRATA_A15_827671))
+$(eval $(call add_define,ERRATA_A15_827671))
+
+# Process ERRATA_A17_852421 flag
+$(eval $(call assert_boolean,ERRATA_A17_852421))
+$(eval $(call add_define,ERRATA_A17_852421))
+
+# Process ERRATA_A17_852423 flag
+$(eval $(call assert_boolean,ERRATA_A17_852423))
+$(eval $(call add_define,ERRATA_A17_852423))
+
 # Process ERRATA_A53_819472 flag
 $(eval $(call assert_boolean,ERRATA_A53_819472))
 $(eval $(call add_define,ERRATA_A53_819472))
@@ -292,6 +328,10 @@
 $(eval $(call assert_boolean,ERRATA_A72_859971))
 $(eval $(call add_define,ERRATA_A72_859971))
 
+# Process ERRATA_A73_852427 flag
+$(eval $(call assert_boolean,ERRATA_A73_852427))
+$(eval $(call add_define,ERRATA_A73_852427))
+
 # Process ERRATA_A73_855423 flag
 $(eval $(call assert_boolean,ERRATA_A73_855423))
 $(eval $(call add_define,ERRATA_A73_855423))
diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c
index d7d8c22..7957b61 100644
--- a/lib/xlat_tables_v2/xlat_tables_core.c
+++ b/lib/xlat_tables_v2/xlat_tables_core.c
@@ -231,10 +231,103 @@
 
 } action_t;
 
+/*
+ * Function that returns the first VA of the table affected by the specified
+ * mmap region.
+ */
+static uintptr_t xlat_tables_find_start_va(mmap_region_t *mm,
+				   const uintptr_t table_base_va,
+				   const unsigned int level)
+{
+	uintptr_t table_idx_va;
+
+	if (mm->base_va > table_base_va) {
+		/* Find the first index of the table affected by the region. */
+		table_idx_va = mm->base_va & ~XLAT_BLOCK_MASK(level);
+	} else {
+		/* Start from the beginning of the table. */
+		table_idx_va = table_base_va;
+	}
+
+	return table_idx_va;
+}
+
+/*
+ * Function that returns table index for the given VA and level arguments.
+ */
+static inline unsigned int  xlat_tables_va_to_index(const uintptr_t table_base_va,
+						const uintptr_t va,
+						const unsigned int level)
+{
+	return (unsigned int)((va - table_base_va) >> XLAT_ADDR_SHIFT(level));
+}
+
 #if PLAT_XLAT_TABLES_DYNAMIC
 
 /*
+ * From the given arguments, it decides which action to take when unmapping the
+ * specified region.
+ */
+static action_t xlat_tables_unmap_region_action(const mmap_region_t *mm,
+		const uintptr_t table_idx_va, const uintptr_t table_idx_end_va,
+		const unsigned int level, const uint64_t desc_type)
+{
+	action_t action;
+	uintptr_t region_end_va = mm->base_va + mm->size - 1U;
+
+	if ((mm->base_va <= table_idx_va) &&
+	    (region_end_va >= table_idx_end_va)) {
+		/* Region covers all block */
+
+		if (level == 3U) {
+			/*
+			 * Last level, only page descriptors allowed,
+			 * erase it.
+			 */
+			assert(desc_type == PAGE_DESC);
+
+			action = ACTION_WRITE_BLOCK_ENTRY;
+		} else {
+			/*
+			 * Other levels can have table descriptors. If
+			 * so, recurse into it and erase descriptors
+			 * inside it as needed. If there is a block
+			 * descriptor, just erase it. If an invalid
+			 * descriptor is found, this table isn't
+			 * actually mapped, which shouldn't happen.
+			 */
+			if (desc_type == TABLE_DESC) {
+				action = ACTION_RECURSE_INTO_TABLE;
+			} else {
+				assert(desc_type == BLOCK_DESC);
+				action = ACTION_WRITE_BLOCK_ENTRY;
+			}
+		}
+
+	} else if ((mm->base_va <= table_idx_end_va) ||
+		   (region_end_va >= table_idx_va)) {
+		/*
+		 * Region partially covers block.
+		 *
+		 * It can't happen in level 3.
+		 *
+		 * There must be a table descriptor here, if not there
+		 * was a problem when mapping the region.
+		 */
+		assert(level < 3U);
+		assert(desc_type == TABLE_DESC);
+
+		action = ACTION_RECURSE_INTO_TABLE;
+	} else {
+		/* The region doesn't cover the block at all */
+		action = ACTION_NONE;
+	}
+
+	return action;
+}
+
+/*
- * Recursive function that writes to the translation tables and unmaps the
+ * Function that writes to the translation tables and unmaps the
  * specified region.
  */
 static void xlat_tables_unmap_region(xlat_ctx_t *ctx, mmap_region_t *mm,
@@ -245,127 +338,137 @@
 {
 	assert((level >= ctx->base_level) && (level <= XLAT_TABLE_LEVEL_MAX));
 
-	uint64_t *subtable;
-	uint64_t desc;
+	/*
+	 * data structure to track DESC_TABLE entry before iterate into subtable
+	 * of next translation level. it will be used to restore previous level
+	 * after finish subtable iteration.
+	 */
+	struct desc_table_unmap {
+		uint64_t *table_base;
+		uintptr_t table_idx_va;
+		unsigned int idx;
+	} desc_tables[XLAT_TABLE_LEVEL_MAX + 1] = {
+		{NULL, 0U, XLAT_TABLE_ENTRIES}, };
 
+	unsigned int this_level = level;
+	uint64_t *this_base = table_base;
+	unsigned int max_entries = table_entries;
+	size_t level_size = XLAT_BLOCK_SIZE(this_level);
+	unsigned int table_idx;
 	uintptr_t table_idx_va;
-	uintptr_t table_idx_end_va; /* End VA of this entry */
 
 	uintptr_t region_end_va = mm->base_va + mm->size - 1U;
 
-	unsigned int table_idx;
-
-	if (mm->base_va > table_base_va) {
-		/* Find the first index of the table affected by the region. */
-		table_idx_va = mm->base_va & ~XLAT_BLOCK_MASK(level);
+	table_idx_va = xlat_tables_find_start_va(mm, table_base_va, level);
+	table_idx = xlat_tables_va_to_index(table_base_va, table_idx_va, level);
 
-		table_idx = (unsigned int)((table_idx_va - table_base_va) >>
-			    XLAT_ADDR_SHIFT(level));
-
-		assert(table_idx < table_entries);
-	} else {
-		/* Start from the beginning of the table. */
-		table_idx_va = table_base_va;
-		table_idx = 0;
-	}
+	while (this_base != NULL) {
 
-	while (table_idx < table_entries) {
+		uint64_t desc;
+		uint64_t desc_type;
+		uintptr_t table_idx_end_va; /* End VA of this entry */
+		action_t action;
 
-		table_idx_end_va = table_idx_va + XLAT_BLOCK_SIZE(level) - 1U;
+		/* finish current xlat level iteration. */
+		if (table_idx >= max_entries) {
+			if (this_level > ctx->base_level) {
+				xlat_table_dec_regions_count(ctx, this_base);
+			}
 
-		desc = table_base[table_idx];
-		uint64_t desc_type = desc & DESC_MASK;
+			if (this_level > level) {
+				uint64_t *subtable;
 
-		action_t action;
+				/* back from subtable iteration, restore
+				 * previous DESC_TABLE entry.
+				 */
+				this_level--;
+				this_base = desc_tables[this_level].table_base;
+				table_idx = desc_tables[this_level].idx;
+				table_idx_va =
+					desc_tables[this_level].table_idx_va;
+				level_size = XLAT_BLOCK_SIZE(this_level);
 
-		if ((mm->base_va <= table_idx_va) &&
-		    (region_end_va >= table_idx_end_va)) {
-			/* Region covers all block */
+				if (this_level == level) {
+					max_entries = table_entries;
+				} else {
+					max_entries = XLAT_TABLE_ENTRIES;
+				}
 
-			if (level == 3U) {
+				desc = this_base[table_idx];
+				subtable =  (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
 				/*
-				 * Last level, only page descriptors allowed,
-				 * erase it.
+				 * If the subtable is now empty, remove its reference.
 				 */
-				assert(desc_type == PAGE_DESC);
+				if (xlat_table_is_empty(ctx, subtable)) {
+					this_base[table_idx] = INVALID_DESC;
+					xlat_arch_tlbi_va(table_idx_va,
+							ctx->xlat_regime);
+				}
+				table_idx++;
+				table_idx_va += level_size;
 
-				action = ACTION_WRITE_BLOCK_ENTRY;
 			} else {
-				/*
-				 * Other levels can have table descriptors. If
-				 * so, recurse into it and erase descriptors
-				 * inside it as needed. If there is a block
-				 * descriptor, just erase it. If an invalid
-				 * descriptor is found, this table isn't
-				 * actually mapped, which shouldn't happen.
-				 */
-				if (desc_type == TABLE_DESC) {
-					action = ACTION_RECURSE_INTO_TABLE;
-				} else {
-					assert(desc_type == BLOCK_DESC);
-					action = ACTION_WRITE_BLOCK_ENTRY;
-				}
+				/* reached end of top level, exit.*/
+				this_base = NULL;
+				break;
 			}
 
-		} else if ((mm->base_va <= table_idx_end_va) ||
-			   (region_end_va >= table_idx_va)) {
-			/*
-			 * Region partially covers block.
-			 *
-			 * It can't happen in level 3.
-			 *
-			 * There must be a table descriptor here, if not there
-			 * was a problem when mapping the region.
-			 */
-			assert(level < 3U);
-			assert(desc_type == TABLE_DESC);
+		}
 
-			action = ACTION_RECURSE_INTO_TABLE;
-		} else {
-			/* The region doesn't cover the block at all */
-			action = ACTION_NONE;
+		/* If reached the end of the region, stop iterating entries in
+		 * current xlat level.
+		 */
+		if (region_end_va <= table_idx_va) {
+			table_idx = max_entries;
+			continue;
 		}
 
-		if (action == ACTION_WRITE_BLOCK_ENTRY) {
 
-			table_base[table_idx] = INVALID_DESC;
+		table_idx_end_va = table_idx_va + XLAT_BLOCK_SIZE(this_level) - 1U;
+
+		desc = this_base[table_idx];
+		desc_type = desc & DESC_MASK;
+
+		action = xlat_tables_unmap_region_action(mm, table_idx_va,
+							 table_idx_end_va,
+							 this_level,
+							 desc_type);
+
+		if (action == ACTION_WRITE_BLOCK_ENTRY) {
+			this_base[table_idx] = INVALID_DESC;
 			xlat_arch_tlbi_va(table_idx_va, ctx->xlat_regime);
 
+			table_idx++;
+			table_idx_va += level_size;
 		} else if (action == ACTION_RECURSE_INTO_TABLE) {
 
+			uint64_t *subtable;
+			uintptr_t base_va;
+
 			subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
 
-			/* Recurse to write into subtable */
-			xlat_tables_unmap_region(ctx, mm, table_idx_va,
-						 subtable, XLAT_TABLE_ENTRIES,
-						 level + 1U);
-#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
-			xlat_clean_dcache_range((uintptr_t)subtable,
-				XLAT_TABLE_ENTRIES * sizeof(uint64_t));
-#endif
-			/*
-			 * If the subtable is now empty, remove its reference.
-			 */
-			if (xlat_table_is_empty(ctx, subtable)) {
-				table_base[table_idx] = INVALID_DESC;
-				xlat_arch_tlbi_va(table_idx_va,
-						  ctx->xlat_regime);
-			}
+			desc_tables[this_level].table_base = this_base;
+			desc_tables[this_level].table_idx_va = table_idx_va;
+			base_va = table_idx_va;
+			desc_tables[this_level].idx = table_idx;
+
+			this_base = subtable;
+			this_level++;
 
+			max_entries = XLAT_TABLE_ENTRIES;
+			level_size = XLAT_BLOCK_SIZE(this_level);
+
+			table_idx_va = xlat_tables_find_start_va(mm,
+					base_va, this_level);
+			table_idx = xlat_tables_va_to_index(base_va,
+					table_idx_va, this_level);
 		} else {
 			assert(action == ACTION_NONE);
-		}
-
-		table_idx++;
-		table_idx_va += XLAT_BLOCK_SIZE(level);
 
-		/* If reached the end of the region, exit */
-		if (region_end_va <= table_idx_va)
-			break;
+			table_idx++;
+			table_idx_va += level_size;
+		}
 	}
-
-	if (level > ctx->base_level)
-		xlat_table_dec_regions_count(ctx, table_base);
 }
 
 #endif /* PLAT_XLAT_TABLES_DYNAMIC */
@@ -502,116 +605,169 @@
 }
 
 /*
- * Recursive function that writes to the translation tables and maps the
+ * Function that writes to the translation tables and maps the
  * specified region. On success, it returns the VA of the last byte that was
  * successfully mapped. On error, it returns the VA of the next entry that
  * should have been mapped.
  */
 static uintptr_t xlat_tables_map_region(xlat_ctx_t *ctx, mmap_region_t *mm,
-				   uintptr_t table_base_va,
+				   const uintptr_t table_base_va,
 				   uint64_t *const table_base,
 				   unsigned int table_entries,
 				   unsigned int level)
 {
+
 	assert((level >= ctx->base_level) && (level <= XLAT_TABLE_LEVEL_MAX));
 
+	/*
+	 * data structure to track DESC_TABLE entry before iterate into subtable
+	 * of next translation level. it will be used to restore previous level
+	 * after finish subtable iteration.
+	 */
+	struct desc_table_map {
+		uint64_t *table_base;
+		uintptr_t table_idx_va;
+		unsigned int idx;
+	} desc_tables[XLAT_TABLE_LEVEL_MAX + 1] = {
+		{NULL, 0U, XLAT_TABLE_ENTRIES}, };
+
+	unsigned int this_level = level;
+	uint64_t *this_base = table_base;
+	unsigned int max_entries = table_entries;
+	size_t level_size = XLAT_BLOCK_SIZE(this_level);
 	uintptr_t mm_end_va = mm->base_va + mm->size - 1U;
 
 	uintptr_t table_idx_va;
-	unsigned long long table_idx_pa;
-
-	uint64_t *subtable;
-	uint64_t desc;
-
 	unsigned int table_idx;
 
-	if (mm->base_va > table_base_va) {
-		/* Find the first index of the table affected by the region. */
-		table_idx_va = mm->base_va & ~XLAT_BLOCK_MASK(level);
+	table_idx_va = xlat_tables_find_start_va(mm, table_base_va, level);
+	table_idx = xlat_tables_va_to_index(table_base_va, table_idx_va, level);
 
-		table_idx = (unsigned int)((table_idx_va - table_base_va) >>
-			    XLAT_ADDR_SHIFT(level));
+	while (this_base != NULL) {
 
-		assert(table_idx < table_entries);
-	} else {
-		/* Start from the beginning of the table. */
-		table_idx_va = table_base_va;
-		table_idx = 0U;
-	}
+		uint64_t desc;
+		uint64_t desc_type;
+		unsigned long long table_idx_pa;
+		action_t action;
 
-#if PLAT_XLAT_TABLES_DYNAMIC
-	if (level > ctx->base_level)
-		xlat_table_inc_regions_count(ctx, table_base);
+		/* finish current xlat level iteration. */
+		if (table_idx >= max_entries) {
+			if (this_level <= level) {
+				this_base = NULL;
+				break;
+			} else {
+
+				/* back from subtable iteration, restore
+				 * previous DESC_TABLE entry.
+				 */
+				this_level--;
+				level_size = XLAT_BLOCK_SIZE(this_level);
+				this_base = desc_tables[this_level].table_base;
+				table_idx = desc_tables[this_level].idx;
+				if (this_level == level) {
+					max_entries = table_entries;
+				} else {
+					max_entries = XLAT_TABLE_ENTRIES;
+				}
+#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
+				uintptr_t subtable;
+				desc = this_base[table_idx];
+				subtable = (uintptr_t)(desc & TABLE_ADDR_MASK);
+				xlat_clean_dcache_range(subtable,
+					XLAT_TABLE_ENTRIES * sizeof(uint64_t));
 #endif
 
-	while (table_idx < table_entries) {
+				table_idx++;
+				table_idx_va =
+					desc_tables[this_level].table_idx_va +
+					level_size;
+			}
+		}
 
-		desc = table_base[table_idx];
+		desc = this_base[table_idx];
+		desc_type = desc & DESC_MASK;
 
 		table_idx_pa = mm->base_pa + table_idx_va - mm->base_va;
 
-		action_t action = xlat_tables_map_region_action(mm,
-			(uint32_t)(desc & DESC_MASK), table_idx_pa,
-			table_idx_va, level);
-
-		if (action == ACTION_WRITE_BLOCK_ENTRY) {
+		/* If reached the end of the region, simply exit since we
+		 * already write all BLOCK entries and create all required
+		 * subtables.
+		 */
+		if (mm_end_va <= table_idx_va) {
+			this_base = NULL;
+			break;
+		}
 
-			table_base[table_idx] =
-				xlat_desc(ctx, (uint32_t)mm->attr, table_idx_pa,
-					  level);
+		action = xlat_tables_map_region_action(mm, desc_type,
+				table_idx_pa, table_idx_va, this_level);
 
+		if (action == ACTION_WRITE_BLOCK_ENTRY) {
+			this_base[table_idx] = xlat_desc(ctx, mm->attr,
+					table_idx_pa, this_level);
+			table_idx++;
+			table_idx_va += level_size;
 		} else if (action == ACTION_CREATE_NEW_TABLE) {
-			uintptr_t end_va;
 
-			subtable = xlat_table_get_empty(ctx);
+			uintptr_t base_va;
+
+			uint64_t *subtable = xlat_table_get_empty(ctx);
 			if (subtable == NULL) {
-				/* Not enough free tables to map this region */
+				/* Not enough free tables to map this region. */
 				return table_idx_va;
 			}
 
 			/* Point to new subtable from this one. */
-			table_base[table_idx] = TABLE_DESC | (unsigned long)subtable;
+			this_base[table_idx] = TABLE_DESC | (unsigned long)subtable;
 
-			/* Recurse to write into subtable */
-			end_va = xlat_tables_map_region(ctx, mm, table_idx_va,
-					       subtable, XLAT_TABLE_ENTRIES,
-					       level + 1U);
-#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
-			xlat_clean_dcache_range((uintptr_t)subtable,
-				XLAT_TABLE_ENTRIES * sizeof(uint64_t));
-#endif
-			if (end_va !=
-				(table_idx_va + XLAT_BLOCK_SIZE(level) - 1U))
-				return end_va;
+			desc_tables[this_level].table_base = this_base;
+			desc_tables[this_level].table_idx_va = table_idx_va;
+			desc_tables[this_level].idx = table_idx;
+			base_va = table_idx_va;
 
-		} else if (action == ACTION_RECURSE_INTO_TABLE) {
-			uintptr_t end_va;
+			this_level++;
+			this_base = subtable;
+			level_size = XLAT_BLOCK_SIZE(this_level);
+			table_idx_va = xlat_tables_find_start_va(mm, base_va,
+					this_level);
+			table_idx = xlat_tables_va_to_index(base_va,
+					table_idx_va, this_level);
+			max_entries = XLAT_TABLE_ENTRIES;
 
-			subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
-			/* Recurse to write into subtable */
-			end_va = xlat_tables_map_region(ctx, mm, table_idx_va,
-					       subtable, XLAT_TABLE_ENTRIES,
-					       level + 1U);
-#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
-			xlat_clean_dcache_range((uintptr_t)subtable,
-				XLAT_TABLE_ENTRIES * sizeof(uint64_t));
+#if PLAT_XLAT_TABLES_DYNAMIC
+			if (this_level > ctx->base_level) {
+				xlat_table_inc_regions_count(ctx, subtable);
+			}
 #endif
-			if (end_va !=
-				(table_idx_va + XLAT_BLOCK_SIZE(level) - 1U))
-				return end_va;
 
-		} else {
+		} else if (action == ACTION_RECURSE_INTO_TABLE) {
 
-			assert(action == ACTION_NONE);
+			uintptr_t base_va;
+			uint64_t *subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
 
-		}
+			desc_tables[this_level].table_base = this_base;
+			desc_tables[this_level].table_idx_va = table_idx_va;
+			desc_tables[this_level].idx = table_idx;
+			base_va = table_idx_va;
 
-		table_idx++;
-		table_idx_va += XLAT_BLOCK_SIZE(level);
+			this_level++;
+			level_size = XLAT_BLOCK_SIZE(this_level);
+			table_idx_va = xlat_tables_find_start_va(mm, base_va,
+					this_level);
+			table_idx = xlat_tables_va_to_index(base_va,
+					table_idx_va, this_level);
+			this_base = subtable;
+			max_entries = XLAT_TABLE_ENTRIES;
 
-		/* If reached the end of the region, exit */
-		if (mm_end_va <= table_idx_va)
-			break;
+#if PLAT_XLAT_TABLES_DYNAMIC
+			if (this_level > ctx->base_level) {
+				xlat_table_inc_regions_count(ctx, subtable);
+			}
+#endif
+		} else {
+			assert(action == ACTION_NONE);
+			table_idx++;
+			table_idx_va += level_size;
+		}
 	}
 
 	return table_idx_va - 1U;
diff --git a/lib/xlat_tables_v2/xlat_tables_utils.c b/lib/xlat_tables_v2/xlat_tables_utils.c
index f5848a2..7d0449a 100644
--- a/lib/xlat_tables_v2/xlat_tables_utils.c
+++ b/lib/xlat_tables_v2/xlat_tables_utils.c
@@ -109,7 +109,7 @@
 		"%s(%d invalid descriptors omitted)\n";
 
 /*
- * Recursive function that reads the translation tables passed as an argument
+ * Function that reads the translation tables passed as an argument
  * and prints their status.
  */
 static void xlat_tables_print_internal(xlat_ctx_t *ctx, uintptr_t table_base_va,
@@ -118,10 +118,23 @@
 {
 	assert(level <= XLAT_TABLE_LEVEL_MAX);
 
-	uint64_t desc;
-	uintptr_t table_idx_va = table_base_va;
+	/*
+	 * data structure to track DESC_TABLE entry before iterate into subtable
+	 * of next translation level. it will be restored after return from
+	 * subtable iteration.
+	 */
+	struct desc_table {
+		const uint64_t *table_base;
+		uintptr_t table_idx_va;
+		unsigned int idx;
+	} desc_tables[XLAT_TABLE_LEVEL_MAX + 1] = {
+		{NULL, 0U, XLAT_TABLE_ENTRIES}, };
+	unsigned int this_level = level;
+	const uint64_t *this_base = table_base;
+	unsigned int max_entries = table_entries;
+	size_t level_size = XLAT_BLOCK_SIZE(this_level);
 	unsigned int table_idx = 0U;
-	size_t level_size = XLAT_BLOCK_SIZE(level);
+	uintptr_t table_idx_va = table_base_va;
 
 	/*
 	 * Keep track of how many invalid descriptors are counted in a row.
@@ -131,67 +144,110 @@
 	 */
 	int invalid_row_count = 0;
 
-	while (table_idx < table_entries) {
-
-		desc = table_base[table_idx];
-
-		if ((desc & DESC_MASK) == INVALID_DESC) {
-
-			if (invalid_row_count == 0) {
-				printf("%sVA:0x%lx size:0x%zx\n",
-				       level_spacers[level],
-				       table_idx_va, level_size);
-			}
-			invalid_row_count++;
-
-		} else {
-
+	while (this_base != NULL) {
+		/* finish current xlat level */
+		if (table_idx >= max_entries) {
 			if (invalid_row_count > 1) {
 				printf(invalid_descriptors_ommited,
-				       level_spacers[level],
-				       invalid_row_count - 1);
+					  level_spacers[this_level],
+					  invalid_row_count - 1);
 			}
 			invalid_row_count = 0;
 
-			/*
-			 * Check if this is a table or a block. Tables are only
-			 * allowed in levels other than 3, but DESC_PAGE has the
-			 * same value as DESC_TABLE, so we need to check.
-			 */
-			if (((desc & DESC_MASK) == TABLE_DESC) &&
-					(level < XLAT_TABLE_LEVEL_MAX)) {
-				/*
-				 * Do not print any PA for a table descriptor,
-				 * as it doesn't directly map physical memory
-				 * but instead points to the next translation
-				 * table in the translation table walk.
+			/* no parent level to iterate. */
+			if (this_level <= level) {
+				this_base = NULL;
+				table_idx = max_entries + 1;
+			} else {
+				/* retore previous DESC_TABLE entry and start
+				 * to iterate.
 				 */
-				printf("%sVA:0x%lx size:0x%zx\n",
-				       level_spacers[level],
-				       table_idx_va, level_size);
+				this_level--;
+				level_size = XLAT_BLOCK_SIZE(this_level);
+				this_base = desc_tables[this_level].table_base;
+				table_idx = desc_tables[this_level].idx;
+				table_idx_va =
+					desc_tables[this_level].table_idx_va;
+				if (this_level == level) {
+					max_entries = table_entries;
+				} else {
+					max_entries = XLAT_TABLE_ENTRIES;
+				}
 
-				uintptr_t addr_inner = desc & TABLE_ADDR_MASK;
+				assert(this_base != NULL);
+			}
+		} else {
+			uint64_t desc = this_base[table_idx];
 
-				xlat_tables_print_internal(ctx, table_idx_va,
-					(uint64_t *)addr_inner,
-					XLAT_TABLE_ENTRIES, level + 1U);
+			if ((desc & DESC_MASK) == INVALID_DESC) {
+				if (invalid_row_count == 0) {
+					printf("%sVA:0x%lx size:0x%zx\n",
+						  level_spacers[this_level],
+						  table_idx_va, level_size);
+				}
+				invalid_row_count++;
+				table_idx++;
+				table_idx_va += level_size;
 			} else {
-				printf("%sVA:0x%lx PA:0x%llx size:0x%zx ",
-				       level_spacers[level], table_idx_va,
-				       (uint64_t)(desc & TABLE_ADDR_MASK),
-				       level_size);
-				xlat_desc_print(ctx, desc);
-				printf("\n");
-			}
-		}
+				if (invalid_row_count > 1) {
+					printf(invalid_descriptors_ommited,
+						  level_spacers[this_level],
+						  invalid_row_count - 1);
+				}
+				invalid_row_count = 0;
+				/*
+				 * Check if this is a table or a block. Tables
+				 * are only allowed in levels other than 3, but
+				 * DESC_PAGE has the same value as DESC_TABLE,
+				 * so we need to check.
+				 */
 
-		table_idx++;
-		table_idx_va += level_size;
-	}
+				if (((desc & DESC_MASK) == TABLE_DESC) &&
+				    (this_level < XLAT_TABLE_LEVEL_MAX)) {
+					uintptr_t addr_inner;
 
-	if (invalid_row_count > 1) {
-		printf(invalid_descriptors_ommited,
-		       level_spacers[level], invalid_row_count - 1);
+					/*
+					 * Do not print any PA for a table
+					 * descriptor, as it doesn't directly
+					 * map physical memory but instead
+					 * points to the next translation
+					 * table in the translation table walk.
+					 */
+					printf("%sVA:0x%lx size:0x%zx\n",
+					       level_spacers[this_level],
+					       table_idx_va, level_size);
+
+					addr_inner = desc & TABLE_ADDR_MASK;
+					/* save current xlat level */
+					desc_tables[this_level].table_base =
+						this_base;
+					desc_tables[this_level].idx =
+						table_idx + 1;
+					desc_tables[this_level].table_idx_va =
+						table_idx_va + level_size;
+
+					/* start iterating next level entries */
+					this_base = (uint64_t *)addr_inner;
+					max_entries = XLAT_TABLE_ENTRIES;
+					this_level++;
+					level_size =
+						XLAT_BLOCK_SIZE(this_level);
+					table_idx = 0U;
+				} else {
+					printf("%sVA:0x%lx PA:0x%llx size:0x%zx ",
+					       level_spacers[this_level],
+					       table_idx_va,
+					       (uint64_t)(desc & TABLE_ADDR_MASK),
+					       level_size);
+					xlat_desc_print(ctx, desc);
+					printf("\n");
+
+					table_idx++;
+					table_idx_va += level_size;
+
+				}
+			}
+		}
 	}
 }
 
diff --git a/maintainers.rst b/maintainers.rst
index 9f38b33..a1ad137 100644
--- a/maintainers.rst
+++ b/maintainers.rst
@@ -188,6 +188,8 @@
 -------------------------------
 :M: Jorge Ramirez-Ortiz  <jramirez@baylibre.com>
 :G: `ldts`_
+:M: Marek Vasut <marek.vasut@gmail.com>
+:G: `marex`_
 :F: docs/plat/rcar-gen3.rst
 :F: plat/renesas/rcar
 :F: drivers/renesas/rcar
@@ -263,6 +265,7 @@
 .. _JackyBai: https://github.com/JackyBai
 .. _jenswi-linaro: https://github.com/jenswi-linaro
 .. _ldts: https://github.com/ldts
+.. _marex: https://github.com/marex
 .. _niej: https://github.com/niej
 .. _kostapr: https://github.com/kostapr
 .. _masahir0y: https://github.com/masahir0y
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 4a264d7..5d33954 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -355,8 +355,13 @@
 .PHONY : lib${1}_dirs
 lib${1}_dirs: | ${BUILD_DIR} ${LIB_DIR}  ${ROMLIB_DIR} ${LIBWRAPPER_DIR}
 libraries: ${LIB_DIR}/lib$(1).a
+ifneq ($(findstring armlink,$(notdir $(LD))),)
+LDPATHS = --userlibpath=${LIB_DIR}
+LDLIBS += --library=$(1)
+else
 LDPATHS = -L${LIB_DIR}
 LDLIBS += -l$(1)
+endif
 
 ifeq ($(USE_ROMLIB),1)
 LIBWRAPPER = -lwrappers
@@ -421,9 +426,18 @@
 	       const char version_string[] = "${VERSION_STRING}";' | \
 		$$(CC) $$(TF_CFLAGS) $$(CFLAGS) -xc -c - -o $(BUILD_DIR)/build_message.o
 endif
+ifneq ($(findstring armlink,$(notdir $(LD))),)
+	$$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) --entry=bl${1}_entrypoint \
+		--predefine="-D__LINKER__=$(__LINKER__)" \
+		--predefine="-DTF_CFLAGS=$(TF_CFLAGS)" \
+		--map --list="$(MAPFILE)" --scatter=${PLAT_DIR}/scat/bl${1}.scat \
+		$(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS) \
+		$(BUILD_DIR)/build_message.o $(OBJS)
+else
 	$$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) -Map=$(MAPFILE) \
 		--script $(LINKERFILE) $(BUILD_DIR)/build_message.o \
 		$(OBJS) $(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS)
+endif
 
 $(DUMP): $(ELF)
 	$${ECHO} "  OD      $$@"
diff --git a/plat/allwinner/sun50i_a64/sunxi_power.c b/plat/allwinner/sun50i_a64/sunxi_power.c
index b4d16a0..07a3716 100644
--- a/plat/allwinner/sun50i_a64/sunxi_power.c
+++ b/plat/allwinner/sun50i_a64/sunxi_power.c
@@ -229,8 +229,8 @@
 
 	/* locate the PMIC DT node, bail out if not found */
 	node = fdt_node_offset_by_compatible(fdt, -1, "x-powers,axp803");
-	if (node == -FDT_ERR_NOTFOUND) {
-		WARN("BL31: PMIC: No AXP803 DT node, skipping initial setup.\n");
+	if (node < 0) {
+		WARN("BL31: PMIC: Cannot find AXP803 DT node, skipping initial setup.\n");
 		return;
 	}
 
@@ -241,11 +241,15 @@
 	}
 
 	/* descend into the "regulators" subnode */
-	node = fdt_first_subnode(fdt, node);
+	node = fdt_subnode_offset(fdt, node, "regulators");
+	if (node < 0) {
+		WARN("BL31: PMIC: Cannot find regulators subnode, skipping initial setup.\n");
+		return;
+	}
 
 	/* iterate over all regulators to find used ones */
 	for (node = fdt_first_subnode(fdt, node);
-	     node != -FDT_ERR_NOTFOUND;
+	     node >= 0;
 	     node = fdt_next_subnode(fdt, node)) {
 		const struct axp_regulator *reg;
 		const char *name;
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 780e6fc..6856a28 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -146,13 +146,7 @@
 #elif defined(IMAGE_BL2U)
 # define PLATFORM_STACK_SIZE		UL(0x400)
 #elif defined(IMAGE_BL31)
-# if ENABLE_SPM
-#  define PLATFORM_STACK_SIZE		UL(0x600)
-# elif PLAT_XLAT_TABLES_DYNAMIC
 #  define PLATFORM_STACK_SIZE		UL(0x800)
-# else
-#  define PLATFORM_STACK_SIZE		UL(0x400)
-# endif
 #elif defined(IMAGE_BL32)
 # define PLATFORM_STACK_SIZE		UL(0x440)
 #endif
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 8e69399..61a3734 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -104,7 +104,9 @@
 				lib/cpus/aarch64/cortex_a75.S			\
 				lib/cpus/aarch64/cortex_a76.S			\
 				lib/cpus/aarch64/neoverse_n1.S			\
-				lib/cpus/aarch64/cortex_deimos.S
+				lib/cpus/aarch64/cortex_deimos.S		\
+				lib/cpus/aarch64/neoverse_zeus.S
+
 else
 FVP_CPU_LIBS		+=	lib/cpus/aarch32/cortex_a32.S
 endif
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index ddbc9b7..e096e33 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -222,6 +222,7 @@
 
 /* MHU related constants */
 #define PLAT_CSS_MHU_BASE		UL(0x2b1f0000)
+#define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
 
 /*
  * Base address of the first memory region used for communication between AP
diff --git a/plat/arm/board/n1sdp/include/platform_def.h b/plat/arm/board/n1sdp/include/platform_def.h
index 83b9f52..03bd380 100644
--- a/plat/arm/board/n1sdp/include/platform_def.h
+++ b/plat/arm/board/n1sdp/include/platform_def.h
@@ -61,6 +61,7 @@
 
 #define PLAT_ARM_NSTIMER_FRAME_ID		0
 #define PLAT_CSS_MHU_BASE			0x45000000
+#define PLAT_MHUV2_BASE				PLAT_CSS_MHU_BASE
 #define PLAT_MAX_PWR_LVL			1
 
 #define PLAT_ARM_G1S_IRQS			ARM_G1S_IRQS,			\
diff --git a/plat/arm/board/rde1edge/include/platform_def.h b/plat/arm/board/rde1edge/include/platform_def.h
index 954a1cd..3b3ade0 100644
--- a/plat/arm/board/rde1edge/include/platform_def.h
+++ b/plat/arm/board/rde1edge/include/platform_def.h
@@ -16,6 +16,7 @@
 #define CSS_SGI_MAX_PE_PER_CPU		2
 
 #define PLAT_CSS_MHU_BASE		UL(0x45400000)
+#define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
 
 /* Base address of DMC-620 instances */
 #define RDE1EDGE_DMC620_BASE0		UL(0x4e000000)
diff --git a/plat/arm/board/rdn1edge/include/platform_def.h b/plat/arm/board/rdn1edge/include/platform_def.h
index 2ca0dd4..8480c08 100644
--- a/plat/arm/board/rdn1edge/include/platform_def.h
+++ b/plat/arm/board/rdn1edge/include/platform_def.h
@@ -16,6 +16,7 @@
 #define CSS_SGI_MAX_PE_PER_CPU		1
 
 #define PLAT_CSS_MHU_BASE		UL(0x45400000)
+#define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
 
 /* Base address of DMC-620 instances */
 #define RDN1EDGE_DMC620_BASE0		UL(0x4e000000)
diff --git a/plat/arm/board/sgi575/include/platform_def.h b/plat/arm/board/sgi575/include/platform_def.h
index 6aea522..ec51c9e 100644
--- a/plat/arm/board/sgi575/include/platform_def.h
+++ b/plat/arm/board/sgi575/include/platform_def.h
@@ -16,6 +16,7 @@
 #define CSS_SGI_MAX_PE_PER_CPU		1
 
 #define PLAT_CSS_MHU_BASE		UL(0x45000000)
+#define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
 
 /* Base address of DMC-620 instances */
 #define SGI575_DMC620_BASE0		UL(0x4e000000)
diff --git a/plat/arm/css/sgi/include/sgi_variant.h b/plat/arm/css/sgi/include/sgi_variant.h
index e9b96dd..c75f213 100644
--- a/plat/arm/css/sgi/include/sgi_variant.h
+++ b/plat/arm/css/sgi/include/sgi_variant.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,9 +10,9 @@
 /* SSC_VERSION values for SGI575 */
 #define SGI575_SSC_VER_PART_NUM		0x0783
 
-/* SID Version values for SGI-Clark */
-#define SGI_CLARK_SID_VER_PART_NUM		0x0786
-#define SGI_CLARK_HELIOS_CONFIG_ID		0x2
+/* SID Version values for RD-N1E1-Edge */
+#define RD_N1E1_EDGE_SID_VER_PART_NUM		0x0786
+#define RD_E1_EDGE_CONFIG_ID			0x2
 
 /* Structure containing SGI platform variant information */
 typedef struct sgi_platform_info {
diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c
index bfcb521..8fa5b01 100644
--- a/plat/arm/css/sgi/sgi_bl31_setup.c
+++ b/plat/arm/css/sgi/sgi_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -27,7 +27,7 @@
 		.ring_doorbell = &mhu_ring_doorbell,
 };
 
-static scmi_channel_plat_info_t sgi_clark_scmi_plat_info = {
+static scmi_channel_plat_info_t rd_n1e1_edge_scmi_plat_info = {
 		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
 		.db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0),
 		.db_preserve_mask = 0xfffffffe,
@@ -37,8 +37,8 @@
 
 scmi_channel_plat_info_t *plat_css_get_scmi_info()
 {
-	if (sgi_plat_info.platform_id == SGI_CLARK_SID_VER_PART_NUM)
-		return &sgi_clark_scmi_plat_info;
+	if (sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM)
+		return &rd_n1e1_edge_scmi_plat_info;
 	else if (sgi_plat_info.platform_id == SGI575_SSC_VER_PART_NUM)
 		return &sgi575_scmi_plat_info;
 	else
@@ -65,9 +65,9 @@
 
 const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
 {
-	/* For SGI-Clark.Helios platform only CPU ON/OFF is supported */
-	if ((sgi_plat_info.platform_id == SGI_CLARK_SID_VER_PART_NUM) &&
-	    (sgi_plat_info.config_id == SGI_CLARK_HELIOS_CONFIG_ID)) {
+	/* For RD-E1-Edge platform only CPU ON/OFF is supported */
+	if ((sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM) &&
+	    (sgi_plat_info.config_id == RD_E1_EDGE_CONFIG_ID)) {
 		ops->cpu_standby = NULL;
 		ops->system_off = NULL;
 		ops->system_reset = NULL;
diff --git a/plat/arm/css/sgi/sgi_topology.c b/plat/arm/css/sgi/sgi_topology.c
index dafaf40..f9dbdef 100644
--- a/plat/arm/css/sgi/sgi_topology.c
+++ b/plat/arm/css/sgi/sgi_topology.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,8 +21,8 @@
 	CSS_SGI_MAX_CPUS_PER_CLUSTER
 };
 
-/* SGI-Clark.Helios platform consists of 16 physical CPUS and 32 threads */
-const unsigned char sgi_clark_helios_pd_tree_desc[] = {
+/* RD-E1-Edge platform consists of 16 physical CPUS and 32 threads */
+const unsigned char rd_e1_edge_pd_tree_desc[] = {
 	PLAT_ARM_CLUSTER_COUNT,
 	CSS_SGI_MAX_CPUS_PER_CLUSTER,
 	CSS_SGI_MAX_CPUS_PER_CLUSTER,
@@ -49,9 +49,9 @@
  ******************************************************************************/
 const unsigned char *plat_get_power_domain_tree_desc(void)
 {
-	if (sgi_plat_info.platform_id == SGI_CLARK_SID_VER_PART_NUM &&
-	    sgi_plat_info.config_id == SGI_CLARK_HELIOS_CONFIG_ID)
-		return sgi_clark_helios_pd_tree_desc;
+	if (sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM &&
+	    sgi_plat_info.config_id == RD_E1_EDGE_CONFIG_ID)
+		return rd_e1_edge_pd_tree_desc;
 	else
 		return sgi_pd_tree_desc;
 }
diff --git a/plat/arm/css/sgm/include/sgm_base_platform_def.h b/plat/arm/css/sgm/include/sgm_base_platform_def.h
index 4647e74..8581844 100644
--- a/plat/arm/css/sgm/include/sgm_base_platform_def.h
+++ b/plat/arm/css/sgm/include/sgm_base_platform_def.h
@@ -86,6 +86,7 @@
 
 /* MHU related constants */
 #define PLAT_CSS_MHU_BASE		0x2b1f0000
+#define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
 
 #define PLAT_ARM_TRUSTED_ROM_BASE	0x00000000
 #define PLAT_ARM_TRUSTED_ROM_SIZE	0x00080000
diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c
index 2357edf..b46656c 100644
--- a/plat/common/plat_bl_common.c
+++ b/plat/common/plat_bl_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,9 +10,6 @@
 #include <arch_helpers.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
-#if TRUSTED_BOARD_BOOT
-#include <drivers/auth/mbedtls/mbedtls_config.h>
-#endif
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <plat/common/platform.h>
 
@@ -26,7 +23,6 @@
 #pragma weak bl2_plat_handle_pre_image_load
 #pragma weak bl2_plat_handle_post_image_load
 #pragma weak plat_try_next_boot_source
-#pragma weak plat_get_mbedtls_heap
 
 void bl2_el3_plat_prepare_exit(void)
 {
@@ -57,24 +53,6 @@
 	return 0;
 }
 
-#if TRUSTED_BOARD_BOOT
-/*
- * The following default implementation of the function simply returns the
- * by-default allocated heap.
- */
-int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
-{
-	static unsigned char heap[TF_MBEDTLS_HEAP_SIZE];
-
-	assert(heap_addr != NULL);
-	assert(heap_size != NULL);
-
-	*heap_addr = heap;
-	*heap_size = sizeof(heap);
-	return 0;
-}
-#endif /* TRUSTED_BOARD_BOOT */
-
 /*
  * Set up the page tables for the generic and platform-specific memory regions.
  * The size of the Trusted SRAM seen by the BL image must be specified as well
diff --git a/plat/imx/common/plat_imx8_gic.c b/plat/imx/common/plat_imx8_gic.c
index 27c525b..3a7dcfe 100644
--- a/plat/imx/common/plat_imx8_gic.c
+++ b/plat/imx/common/plat_imx8_gic.c
@@ -9,6 +9,8 @@
 #include <common/bl_common.h>
 #include <common/interrupt_props.h>
 #include <drivers/arm/gicv3.h>
+#include <drivers/arm/arm_gicv3_common.h>
+#include <lib/mmio.h>
 #include <lib/utils.h>
 #include <plat/common/platform.h>
 
@@ -52,8 +54,27 @@
 #endif
 }
 
+static __inline void plat_gicr_exit_sleep(void)
+{
+	unsigned int val = mmio_read_32(PLAT_GICR_BASE + GICR_WAKER);
+
+	/*
+	 * ProcessorSleep bit can ONLY be set to zero when
+	 * Quiescent bit and Sleep bit are both zero, so
+	 * need to make sure Quiescent bit and Sleep bit
+	 * are zero before clearing ProcessorSleep bit.
+	 */
+	if (val & WAKER_QSC_BIT) {
+		mmio_write_32(PLAT_GICR_BASE + GICR_WAKER, val & ~WAKER_SL_BIT);
+		/* Wait till the WAKER_QSC_BIT changes to 0 */
+		while ((mmio_read_32(PLAT_GICR_BASE + GICR_WAKER) & WAKER_QSC_BIT) != 0U)
+			;
+	}
+}
+
 void plat_gic_init(void)
 {
+	plat_gicr_exit_sleep();
 	gicv3_distif_init();
 	gicv3_rdistif_init(plat_my_core_pos());
 	gicv3_cpuif_enable(plat_my_core_pos());
diff --git a/plat/imx/imx8m/gpc_common.c b/plat/imx/imx8m/gpc_common.c
new file mode 100644
index 0000000..eb2801c
--- /dev/null
+++ b/plat/imx/imx8m/gpc_common.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <gpc.h>
+#include <imx8m_psci.h>
+#include <plat_imx8.h>
+
+static uint32_t gpc_imr_offset[] = { 0x30, 0x40, 0x1c0, 0x1d0, };
+
+#pragma weak imx_set_cpu_pwr_off
+#pragma weak imx_set_cpu_pwr_on
+#pragma weak imx_set_cpu_lpm
+#pragma weak imx_set_cluster_powerdown
+
+void imx_set_cpu_secure_entry(unsigned int core_id, uintptr_t sec_entrypoint)
+{
+	uint64_t temp_base;
+
+	temp_base = (uint64_t) sec_entrypoint;
+	temp_base >>= 2;
+
+	mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3),
+		((uint32_t)(temp_base >> 22) & 0xffff));
+	mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3) + 4,
+		((uint32_t)temp_base & 0x003fffff));
+}
+
+void imx_set_cpu_pwr_off(unsigned int core_id)
+{
+	/* enable the wfi power down of the core */
+	mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id));
+	/* assert the pcg pcr bit of the core */
+	mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+}
+
+void imx_set_cpu_pwr_on(unsigned int core_id)
+{
+	/* clear the wfi power down bit of the core */
+	mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id));
+	/* assert the ncpuporeset */
+	mmio_clrbits_32(IMX_SRC_BASE + SRC_A53RCR1, (1 << core_id));
+	/* assert the pcg pcr bit of the core */
+	mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+	/* sw power up the core */
+	mmio_setbits_32(IMX_GPC_BASE + CPU_PGC_UP_TRG, (1 << core_id));
+
+	/* wait for the power up finished */
+	while ((mmio_read_32(IMX_GPC_BASE + CPU_PGC_UP_TRG) & (1 << core_id)) != 0)
+		;
+
+	/* deassert the pcg pcr bit of the core */
+	mmio_clrbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+	/* deassert the ncpuporeset */
+	mmio_setbits_32(IMX_SRC_BASE + SRC_A53RCR1, (1 << core_id));
+}
+
+void imx_set_cpu_lpm(unsigned int core_id, bool pdn)
+{
+	if (pdn) {
+		/* enable the core WFI PDN & IRQ PUP */
+		mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) |
+				COREx_IRQ_WUP(core_id));
+		/* assert the pcg pcr bit of the core */
+		mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+	} else {
+		/* disbale CORE WFI PDN & IRQ PUP */
+		mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) |
+				COREx_IRQ_WUP(core_id));
+		/* deassert the pcg pcr bit of the core */
+		mmio_clrbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+	}
+}
+
+/*
+ * the plat and noc can only be power up & down by slot method,
+ * slot0: plat power down; slot1: noc power down; slot2: noc power up;
+ * slot3: plat power up. plat's pup&pdn ack is used by default. if
+ * noc is config to power down, then noc's pdn ack should be used.
+ */
+static void imx_a53_plat_slot_config(bool pdn)
+{
+	if (pdn) {
+		mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(0), PLAT_PDN_SLT_CTRL);
+		mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(3), PLAT_PUP_SLT_CTRL);
+		mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, A53_PLAT_PDN_ACK |
+			A53_PLAT_PUP_ACK);
+		mmio_setbits_32(IMX_GPC_BASE + PLAT_PGC_PCR, 0x1);
+	} else {
+		mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(0), PLAT_PDN_SLT_CTRL);
+		mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(3), PLAT_PUP_SLT_CTRL);
+		mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, A53_DUMMY_PUP_ACK |
+			A53_DUMMY_PDN_ACK);
+		mmio_clrbits_32(IMX_GPC_BASE + PLAT_PGC_PCR, 0x1);
+	}
+}
+
+void imx_set_cluster_standby(bool enter)
+{
+	/*
+	 * Enable BIT 6 of A53 AD register to make sure system
+	 * don't enter LPM mode.
+	 */
+	if (enter)
+		mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, (1 << 6));
+	else
+		mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, (1 << 6));
+}
+
+/* i.mx8mq need to override it */
+void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state)
+{
+	uint32_t val;
+
+	if (!is_local_state_run(power_state)) {
+		/* config C0~1's LPM, enable a53 clock off in LPM */
+		mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_BSC, A53_CLK_ON_LPM,
+			LPM_MODE(power_state));
+		/* config C2-3's LPM */
+		mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, LPM_MODE(power_state));
+
+		/* enable PLAT/SCU power down */
+		val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD);
+		val &= ~EN_L2_WFI_PDN;
+		/* L2 cache memory is on in WAIT mode */
+		if (is_local_state_off(power_state))
+			val |= (L2PGE | EN_PLAT_PDN);
+		else
+			val |= EN_PLAT_PDN;
+
+		mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val);
+
+		imx_a53_plat_slot_config(true);
+	} else {
+		/* clear the slot and ack for cluster power down */
+		imx_a53_plat_slot_config(false);
+		/* reverse the cluster level setting */
+		mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_BSC, 0xf, A53_CLK_ON_LPM);
+		mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, 0xf);
+
+		/* clear PLAT/SCU power down */
+		mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_AD, (L2PGE | EN_PLAT_PDN),
+			EN_L2_WFI_PDN);
+	}
+}
+
+static unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ISENABLER_SHIFT;
+
+	return mmio_read_32(base + GICD_ISENABLER + (n << 2));
+}
+
+/*
+ * gic's clock will be gated in system suspend, so gic has no ability to
+ * to wakeup the system, we need to config the imr based on the irq
+ * enable status in gic, then gpc will monitor the wakeup irq
+ */
+void imx_set_sys_wakeup(unsigned int last_core, bool pdn)
+{
+	uint32_t irq_mask;
+	uintptr_t gicd_base = PLAT_GICD_BASE;
+
+	if (pdn)
+		mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_BSC, A53_CORE_WUP_SRC(last_core),
+			IRQ_SRC_A53_WUP);
+	else
+		mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_BSC, IRQ_SRC_A53_WUP,
+			A53_CORE_WUP_SRC(last_core));
+
+	/* clear last core's IMR based on GIC's mask setting */
+	for (int i = 0; i < IRQ_IMR_NUM; i++) {
+		if (pdn)
+			/* set the wakeup irq base GIC */
+			irq_mask = ~gicd_read_isenabler(gicd_base, 32 * (i + 1));
+		else
+			irq_mask = IMR_MASK_ALL;
+
+		mmio_write_32(IMX_GPC_BASE + gpc_imr_offset[last_core] + i * 4,
+			      irq_mask);
+	}
+}
+
+#pragma weak imx_noc_slot_config
+/*
+ * this function only need to be override by platform
+ * that support noc power down, for example: imx8mm.
+ *  otherwize, keep it empty.
+ */
+void imx_noc_slot_config(bool pdn)
+{
+
+}
+
+/* this is common for all imx8m soc */
+void imx_set_sys_lpm(unsigned int last_core, bool retention)
+{
+	uint32_t val;
+
+	val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+	val &= ~(SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS |
+		 SLPCR_BYPASS_PMIC_READY | SLPCR_A53_FASTWUP_STOP_MODE);
+
+	if (retention)
+		val |= (SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS |
+			SLPCR_BYPASS_PMIC_READY | SLPCR_A53_FASTWUP_STOP_MODE);
+
+	mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+
+	/* config the noc power down */
+	imx_noc_slot_config(retention);
+
+	/* config wakeup irqs' mask in gpc */
+	imx_set_sys_wakeup(last_core, retention);
+}
+
+void imx_set_rbc_count(void)
+{
+	mmio_setbits_32(IMX_GPC_BASE + SLPCR, SLPCR_RBC_EN |
+		(0x8 << SLPCR_RBC_COUNT_SHIFT));
+}
+
+void imx_clear_rbc_count(void)
+{
+	mmio_clrbits_32(IMX_GPC_BASE + SLPCR, SLPCR_RBC_EN |
+		(0x3f << SLPCR_RBC_COUNT_SHIFT));
+}
diff --git a/plat/imx/imx8m/imx8m_psci_common.c b/plat/imx/imx8m/imx8m_psci_common.c
new file mode 100644
index 0000000..d641628
--- /dev/null
+++ b/plat/imx/imx8m/imx8m_psci_common.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <gpc.h>
+#include <imx8m_psci.h>
+#include <plat_imx8.h>
+
+/*
+ * below callback functions need to be override by i.mx8mq,
+ * for other i.mx8m soc, if no special requirement,
+ * reuse below ones.
+ */
+#pragma weak imx_validate_power_state
+#pragma weak imx_domain_suspend
+#pragma weak imx_domain_suspend_finish
+#pragma weak imx_get_sys_suspend_power_state
+
+int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
+{
+	/* The non-secure entrypoint should be in RAM space */
+	if (ns_entrypoint < PLAT_NS_IMAGE_OFFSET)
+		return PSCI_E_INVALID_PARAMS;
+
+	return PSCI_E_SUCCESS;
+}
+
+int imx_pwr_domain_on(u_register_t mpidr)
+{
+	unsigned int core_id;
+	uint64_t base_addr = BL31_BASE;
+
+	core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+	imx_set_cpu_secure_entry(core_id, base_addr);
+	imx_set_cpu_pwr_on(core_id);
+
+	return PSCI_E_SUCCESS;
+}
+
+void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	plat_gic_pcpu_init();
+	plat_gic_cpuif_enable();
+}
+
+void imx_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	uint64_t mpidr = read_mpidr_el1();
+	unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+	plat_gic_cpuif_disable();
+	imx_set_cpu_pwr_off(core_id);
+}
+
+int imx_validate_power_state(unsigned int power_state,
+			 psci_power_state_t *req_state)
+{
+	int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+	int pwr_type = psci_get_pstate_type(power_state);
+	int state_id = psci_get_pstate_id(power_state);
+
+	if (pwr_lvl > PLAT_MAX_PWR_LVL)
+		return PSCI_E_INVALID_PARAMS;
+
+	if (pwr_type == PSTATE_TYPE_STANDBY) {
+		CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
+		CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
+	}
+
+	if (pwr_type == PSTATE_TYPE_POWERDOWN && state_id == 0x33) {
+		CORE_PWR_STATE(req_state) = PLAT_MAX_OFF_STATE;
+		CLUSTER_PWR_STATE(req_state) = PLAT_WAIT_RET_STATE;
+	}
+
+	return PSCI_E_SUCCESS;
+}
+
+void imx_cpu_standby(plat_local_state_t cpu_state)
+{
+	dsb();
+	write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+	isb();
+
+	wfi();
+
+	write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
+	isb();
+}
+
+void imx_domain_suspend(const psci_power_state_t *target_state)
+{
+	uint64_t base_addr = BL31_BASE;
+	uint64_t mpidr = read_mpidr_el1();
+	unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+	if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+		plat_gic_cpuif_disable();
+		imx_set_cpu_secure_entry(core_id, base_addr);
+		imx_set_cpu_lpm(core_id, true);
+	} else {
+		dsb();
+		write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+		isb();
+	}
+
+	if (!is_local_state_run(CLUSTER_PWR_STATE(target_state)))
+		imx_set_cluster_powerdown(core_id, CLUSTER_PWR_STATE(target_state));
+
+	if (is_local_state_off(SYSTEM_PWR_STATE(target_state)))
+		imx_set_sys_lpm(core_id, true);
+}
+
+void imx_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+	uint64_t mpidr = read_mpidr_el1();
+	unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+	if (is_local_state_off(SYSTEM_PWR_STATE(target_state)))
+		imx_set_sys_lpm(core_id, false);
+
+	if (!is_local_state_run(CLUSTER_PWR_STATE(target_state))) {
+		imx_clear_rbc_count();
+		imx_set_cluster_powerdown(core_id, PSCI_LOCAL_STATE_RUN);
+	}
+
+	if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+		imx_set_cpu_lpm(core_id, false);
+		plat_gic_cpuif_enable();
+	} else {
+		write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
+		isb();
+	}
+}
+
+void imx_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+	unsigned int i;
+
+	for (i = IMX_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++)
+		req_state->pwr_domain_state[i] = PLAT_STOP_OFF_STATE;
+}
+
+void __dead2 imx_system_reset(void)
+{
+	uintptr_t wdog_base = IMX_WDOG_BASE;
+	unsigned int val;
+
+	/* WDOG_B reset */
+	val = mmio_read_16(wdog_base);
+#ifdef IMX_WDOG_B_RESET
+	val = (val & 0x00FF) | WDOG_WCR_WDZST | WDOG_WCR_WDE |
+		WDOG_WCR_WDT | WDOG_WCR_SRS;
+#else
+	val = (val & 0x00FF) | WDOG_WCR_WDZST | WDOG_WCR_SRS;
+#endif
+	mmio_write_16(wdog_base, val);
+
+	mmio_write_16(wdog_base + WDOG_WSR, 0x5555);
+	mmio_write_16(wdog_base + WDOG_WSR, 0xaaaa);
+	while (1)
+		;
+}
+
+void __dead2 imx_system_off(void)
+{
+	mmio_write_32(IMX_SNVS_BASE + SNVS_LPCR, SNVS_LPCR_SRTC_ENV |
+			SNVS_LPCR_DP_EN | SNVS_LPCR_TOP);
+
+	while (1)
+		;
+}
+
+void __dead2 imx_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
+{
+	/*
+	 * before enter WAIT or STOP mode with PLAT(SCU) power down,
+	 * rbc count need to be enabled to make sure PLAT is
+	 * power down successfully even if the the wakeup IRQ is pending
+	 * early before the power down sequence. the RBC counter is
+	 * drived by the 32K OSC, so delay 30us to make sure the counter
+	 * is really running.
+	 */
+	if (!is_local_state_run(CLUSTER_PWR_STATE(target_state))) {
+		imx_set_rbc_count();
+		udelay(30);
+	}
+
+	while (1)
+		wfi();
+}
diff --git a/plat/imx/imx8m/imx8mm/gpc.c b/plat/imx/imx8m/imx8mm/gpc.c
new file mode 100644
index 0000000..ab59292
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/gpc.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/smccc.h>
+#include <platform_def.h>
+#include <services/std_svc.h>
+
+#include <gpc.h>
+#include <imx_sip_svc.h>
+
+void imx_gpc_init(void)
+{
+	unsigned int val;
+	int i;
+
+	/* mask all the wakeup irq by default */
+	for (i = 0; i < 4; i++) {
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
+	}
+
+	val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+	/* use GIC wake_request to wakeup C0~C3 from LPM */
+	val |= 0x30c00000;
+	/* clear the MASTER0 LPM handshake */
+	val &= ~(1 << 6);
+	mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+	/* clear MASTER1 & MASTER2 mapping in CPU0(A53) */
+	mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING |
+		MASTER2_MAPPING));
+
+	/* set all mix/PU in A53 domain */
+	mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xffff);
+
+	/*
+	 * Set the CORE & SCU power up timing:
+	 * SW = 0x1, SW2ISO = 0x1;
+	 * the CPU CORE and SCU power up timming counter
+	 * is drived  by 32K OSC, each domain's power up
+	 * latency is (SW + SW2ISO) / 32768
+	 */
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x81);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x81);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x81);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x81);
+	mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x81);
+	mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING,
+		      (0x59 << 10) | 0x5B | (0x2 << 20));
+
+	/* set DUMMY PDN/PUP ACK by default for A53 domain */
+	mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53,
+		      A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK);
+
+	/* clear DSM by default */
+	val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+	val &= ~SLPCR_EN_DSM;
+	/* enable the fast wakeup wait mode */
+	val |= SLPCR_A53_FASTWUP_WAIT_MODE;
+	/* clear the RBC */
+	val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT);
+	/* set the STBY_COUNT to 0x5, (128 * 30)us */
+	val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT);
+	val |= (0x5 << SLPCR_STBY_COUNT_SHFT);
+	mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+
+	/*
+	 * USB PHY power up needs to make sure RESET bit in SRC is clear,
+	 * otherwise, the PU power up bit in GPC will NOT self-cleared.
+	 * only need to do it once.
+	 */
+	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
+	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1);
+
+	/* enable all the power domain by default */
+	mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, 0x3fcf);
+}
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
new file mode 100644
index 0000000..a541ed3
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/arm/tzc380.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables.h>
+#include <plat/common/platform.h>
+
+#include <gpc.h>
+#include <imx_uart.h>
+#include <plat_imx8.h>
+
+static const mmap_region_t imx_mmap[] = {
+	MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW),
+	MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW), /* AIPS map */
+	{0},
+};
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* get SPSR for BL33 entry */
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+	unsigned long el_status;
+	unsigned long mode;
+	uint32_t spsr;
+
+	/* figure out what mode we enter the non-secure world */
+	el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+	el_status &= ID_AA64PFR0_ELX_MASK;
+
+	mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+	spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+	return spsr;
+}
+
+void bl31_tzc380_setup(void)
+{
+	unsigned int val;
+
+	val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28);
+	if ((val & GPR_TZASC_EN) != GPR_TZASC_EN)
+		return;
+
+	tzc380_init(IMX_TZASC_BASE);
+
+	/*
+	 * Need to substact offset 0x40000000 from CPU address when
+	 * programming tzasc region for i.mx8mm.
+	 */
+
+	/* Enable 1G-5G S/NS RW */
+	tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) |
+		TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL);
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+		u_register_t arg2, u_register_t arg3)
+{
+	static console_uart_t console;
+	int i;
+
+	/* Enable CSU NS access permission */
+	for (i = 0; i < 64; i++) {
+		mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff);
+	}
+
+
+	console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+		IMX_CONSOLE_BAUDRATE, &console);
+	/* This console is only used for boot stage */
+	console_set_scope(&console.console, CONSOLE_FLAG_BOOT);
+
+	/*
+	 * tell BL3-1 where the non-secure software image is located
+	 * and the entry state information.
+	 */
+	bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
+	bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+	bl31_tzc380_setup();
+}
+
+void bl31_plat_arch_setup(void)
+{
+	mmap_add_region(BL31_BASE, BL31_BASE, (BL31_LIMIT - BL31_BASE),
+		MT_MEMORY | MT_RW | MT_SECURE);
+	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, (BL_CODE_END - BL_CODE_BASE),
+		MT_MEMORY | MT_RO | MT_SECURE);
+#if USE_COHERENT_MEM
+	mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
+		(BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE),
+		MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+	mmap_add(imx_mmap);
+
+	init_xlat_tables();
+
+	enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+	generic_delay_timer_init();
+
+	/* select the CKIL source to 32K OSC */
+	mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1);
+
+	plat_gic_driver_init();
+	plat_gic_init();
+
+	imx_gpc_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+{
+	if (type == NON_SECURE)
+		return &bl33_image_ep_info;
+	if (type == SECURE)
+		return &bl32_image_ep_info;
+
+	return NULL;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return COUNTER_FREQUENCY;
+}
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_psci.c b/plat/imx/imx8m/imx8mm/imx8mm_psci.c
new file mode 100644
index 0000000..e558724
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/imx8mm_psci.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <gpc.h>
+#include <imx8m_psci.h>
+#include <plat_imx8.h>
+
+static const plat_psci_ops_t imx_plat_psci_ops = {
+	.pwr_domain_on = imx_pwr_domain_on,
+	.pwr_domain_on_finish = imx_pwr_domain_on_finish,
+	.pwr_domain_off = imx_pwr_domain_off,
+	.validate_ns_entrypoint = imx_validate_ns_entrypoint,
+	.validate_power_state = imx_validate_power_state,
+	.cpu_standby = imx_cpu_standby,
+	.pwr_domain_suspend = imx_domain_suspend,
+	.pwr_domain_suspend_finish = imx_domain_suspend_finish,
+	.pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+	.get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+	.system_reset = imx_system_reset,
+	.system_off = imx_system_off,
+};
+
+/* export the platform specific psci ops */
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	/* sec_entrypoint is used for warm reset */
+	imx_mailbox_init(sec_entrypoint);
+
+	*psci_ops = &imx_plat_psci_ops;
+
+	return 0;
+}
diff --git a/plat/imx/imx8m/imx8mm/include/platform_def.h b/plat/imx/imx8m/imx8mm/include/platform_def.h
new file mode 100644
index 0000000..a95ab83
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/include/platform_def.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+#define PLATFORM_STACK_SIZE		0xB00
+#define CACHE_WRITEBACK_GRANULE		64
+
+#define PLAT_PRIMARY_CPU		0x0
+#define PLATFORM_MAX_CPU_PER_CLUSTER	4
+#define PLATFORM_CLUSTER_COUNT		1
+#define PLATFORM_CLUSTER0_CORE_COUNT	4
+#define PLATFORM_CLUSTER1_CORE_COUNT	0
+#define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define IMX_PWR_LVL0			MPIDR_AFFLVL0
+#define IMX_PWR_LVL1			MPIDR_AFFLVL1
+#define IMX_PWR_LVL2			MPIDR_AFFLVL2
+
+#define PWR_DOMAIN_AT_MAX_LVL		U(1)
+#define PLAT_MAX_PWR_LVL		U(2)
+#define PLAT_MAX_OFF_STATE		U(4)
+#define PLAT_MAX_RET_STATE		U(2)
+
+#define PLAT_WAIT_RET_STATE		U(1)
+#define PLAT_STOP_OFF_STATE		U(3)
+
+#define BL31_BASE			U(0x920000)
+#define BL31_LIMIT			U(0x940000)
+#define BL32_BASE			U(0xbe000000)
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET		U(0x40200000)
+
+/* GICv3 base address */
+#define PLAT_GICD_BASE			U(0x38800000)
+#define PLAT_GICR_BASE			U(0x38880000)
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ull << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ull << 32)
+
+#define MAX_XLAT_TABLES			8
+#define MAX_MMAP_REGIONS		16
+
+#define HAB_RVT_BASE			U(0x00000900) /* HAB_RVT for i.MX8MM */
+
+#define IMX_BOOT_UART_BASE		U(0x30890000)
+#define IMX_BOOT_UART_CLK_IN_HZ		24000000 /* Select 24MHz oscillator */
+
+#define PLAT_CRASH_UART_BASE		IMX_BOOT_UART_BASE
+#define PLAT_CRASH_UART_CLK_IN_HZ	24000000
+#define IMX_CONSOLE_BAUDRATE		115200
+
+#define IMX_AIPSTZ1			U(0x301f0000)
+#define IMX_AIPSTZ2			U(0x305f0000)
+#define IMX_AIPSTZ3			U(0x309f0000)
+#define IMX_AIPSTZ4			U(0x32df0000)
+
+#define IMX_AIPS_BASE			U(0x30000000)
+#define IMX_AIPS_SIZE			U(0xC00000)
+#define IMX_GPV_BASE			U(0x32000000)
+#define IMX_GPV_SIZE			U(0x800000)
+#define IMX_AIPS1_BASE			U(0x30200000)
+#define IMX_AIPS4_BASE			U(0x32c00000)
+#define IMX_ANAMIX_BASE			U(0x30360000)
+#define IMX_CCM_BASE			U(0x30380000)
+#define IMX_SRC_BASE			U(0x30390000)
+#define IMX_GPC_BASE			U(0x303a0000)
+#define IMX_RDC_BASE			U(0x303d0000)
+#define IMX_CSU_BASE			U(0x303e0000)
+#define IMX_WDOG_BASE			U(0x30280000)
+#define IMX_SNVS_BASE			U(0x30370000)
+#define IMX_NOC_BASE			U(0x32700000)
+#define IMX_TZASC_BASE			U(0x32F80000)
+#define IMX_IOMUX_GPR_BASE		U(0x30340000)
+#define IMX_DDRC_BASE			U(0x3d400000)
+#define IMX_DDRPHY_BASE			U(0x3c000000)
+#define IMX_DDR_IPS_BASE		U(0x3d000000)
+#define IMX_ROM_BASE			U(0x0)
+
+#define GPV_BASE			U(0x32000000)
+#define GPV_SIZE			U(0x800000)
+#define IMX_GIC_BASE			PLAT_GICD_BASE
+#define IMX_GIC_SIZE			U(0x200000)
+
+#define WDOG_WSR			U(0x2)
+#define WDOG_WCR_WDZST			BIT(0)
+#define WDOG_WCR_WDBG			BIT(1)
+#define WDOG_WCR_WDE			BIT(2)
+#define WDOG_WCR_WDT			BIT(3)
+#define WDOG_WCR_SRS			BIT(4)
+#define WDOG_WCR_WDA			BIT(5)
+#define WDOG_WCR_SRE			BIT(6)
+#define WDOG_WCR_WDW			BIT(7)
+
+#define SRC_A53RCR0			U(0x4)
+#define SRC_A53RCR1			U(0x8)
+#define SRC_OTG1PHY_SCR			U(0x20)
+#define SRC_OTG2PHY_SCR			U(0x24)
+#define SRC_GPR1_OFFSET			U(0x74)
+
+#define SNVS_LPCR			U(0x38)
+#define SNVS_LPCR_SRTC_ENV		BIT(0)
+#define SNVS_LPCR_DP_EN			BIT(5)
+#define SNVS_LPCR_TOP			BIT(6)
+
+#define IOMUXC_GPR10			U(0x28)
+#define GPR_TZASC_EN			BIT(0)
+#define GPR_TZASC_EN_LOCK		BIT(16)
+
+#define ANAMIX_MISC_CTL			U(0x124)
+
+#define MAX_CSU_NUM			U(64)
+
+#define OCRAM_S_BASE			U(0x00180000)
+#define OCRAM_S_SIZE			U(0x8000)
+#define OCRAM_S_LIMIT			(OCRAM_S_BASE + OCRAM_S_SIZE)
+
+#define COUNTER_FREQUENCY		8000000 /* 8MHz */
+
+#define IMX_WDOG_B_RESET
diff --git a/plat/imx/imx8m/imx8mm/platform.mk b/plat/imx/imx8m/imx8mm/platform.mk
new file mode 100644
index 0000000..d50af20
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/platform.mk
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES		:=	-Iplat/imx/common/include		\
+				-Iplat/imx/imx8m/include		\
+				-Iplat/imx/imx8m/imx8mm/include
+
+IMX_GIC_SOURCES		:=	drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/arm_gicv3_common.c   \
+				drivers/arm/gic/v3/gic500.c             \
+				drivers/arm/gic/v3/gicv3_main.c		\
+				drivers/arm/gic/common/gic_common.c	\
+				plat/common/plat_gicv3.c		\
+				plat/common/plat_psci_common.c		\
+				plat/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES		+=	plat/imx/common/imx8_helpers.S			\
+				plat/imx/imx8m/gpc_common.c			\
+				plat/imx/imx8m/imx8m_psci_common.c		\
+				plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c	\
+				plat/imx/imx8m/imx8mm/imx8mm_psci.c		\
+				plat/imx/imx8m/imx8mm/gpc.c			\
+				plat/imx/common/imx8_topology.c			\
+				plat/imx/common/imx_uart_console.S		\
+				lib/xlat_tables/aarch64/xlat_tables.c		\
+				lib/xlat_tables/xlat_tables_common.c		\
+				lib/cpus/aarch64/cortex_a53.S			\
+				drivers/console/aarch64/console.S		\
+				drivers/arm/tzc/tzc380.c			\
+				drivers/delay_timer/delay_timer.c		\
+				drivers/delay_timer/generic_delay_timer.c	\
+				${IMX_GIC_SOURCES}
+
+USE_COHERENT_MEM	:=	1
+RESET_TO_BL31		:=	1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+MULTI_CONSOLE_API	:=	1
+
+ERRATA_A53_835769	:=	1
+ERRATA_A53_843419	:=	1
+ERRATA_A53_855873	:=	1
diff --git a/plat/imx/imx8m/imx8mq/gpc.c b/plat/imx/imx8m/imx8mq/gpc.c
index 7fa5a3d..02c640b 100644
--- a/plat/imx/imx8m/imx8mq/gpc.c
+++ b/plat/imx/imx8m/imx8mq/gpc.c
@@ -16,19 +16,6 @@
 
 #include <gpc.h>
 
-void imx_set_cpu_secure_entry(unsigned int core_id, uintptr_t sec_entrypoint)
-{
-	uint64_t temp_base;
-
-	temp_base = (uint64_t) sec_entrypoint;
-	temp_base >>= 2;
-
-	mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3),
-		((uint32_t)(temp_base >> 22) & 0xffff));
-	mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3) + 4,
-		((uint32_t)temp_base & 0x003fffff));
-}
-
 /* use wfi power down the core */
 void imx_set_cpu_pwr_off(unsigned int core_id)
 {
@@ -39,28 +26,6 @@
 	mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
 };
 
-/* use the sw method to power up the core */
-void imx_set_cpu_pwr_on(unsigned int core_id)
-{
-	/* clear the wfi power down bit of the core */
-	mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id));
-	/* assert the ncpuporeset */
-	mmio_clrbits_32(IMX_SRC_BASE + SRC_A53RCR1, (1 << core_id));
-	/* assert the pcg pcr bit of the core */
-	mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
-	/* sw power up the core */
-	mmio_setbits_32(IMX_GPC_BASE + CPU_PGC_UP_TRG, (1 << core_id));
-
-	/* wait for the power up finished */
-	while ((mmio_read_32(IMX_GPC_BASE + CPU_PGC_UP_TRG) & (1 << core_id)) != 0)
-		;
-
-	/* deassert the pcg pcr bit of the core */
-	mmio_clrbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
-	/* deassert the ncpuporeset */
-	mmio_setbits_32(IMX_SRC_BASE + SRC_A53RCR1, (1 << core_id));
-}
-
 /* if out of lpm, we need to do reverse steps */
 void imx_set_cpu_lpm(unsigned int core_id, bool pdn)
 {
@@ -79,11 +44,6 @@
 	}
 }
 
-void imx_set_sys_wakeup(unsigned int last_core, bool pdn)
-{
-	/* TODO */
-}
-
 void imx_pup_pdn_slot_config(int last_core, bool pdn)
 {
 	if (pdn) {
@@ -105,18 +65,6 @@
 	}
 }
 
-void imx_set_cluster_standby(bool retention)
-{
-	/*
-	 * Enable BIT 6 of A53 AD register to make sure system
-	 * don't enter LPM mode.
-	 */
-	if (retention)
-		mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, (1 << 6));
-	else
-		mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, (1 << 6));
-}
-
 void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state)
 {
 	uint32_t val;
@@ -166,34 +114,6 @@
 	}
 }
 
-/* config the system level power mode */
-void imx_set_sys_lpm(bool retention)
-{
-	uint32_t val;
-
-	/* set system DSM mode SLPCR(0x14) */
-	val = mmio_read_32(IMX_GPC_BASE + SLPCR);
-	val &= ~(SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS |
-		 SLPCR_BYPASS_PMIC_READY | SLPCR_RBC_EN);
-
-	if (retention)
-		val |= (SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS |
-			 SLPCR_BYPASS_PMIC_READY | SLPCR_RBC_EN |
-			 SLPCR_A53_FASTWUP_STOP_MODE);
-
-	mmio_write_32(IMX_GPC_BASE + SLPCR, val);
-}
-
-void imx_set_rbc_count(void)
-{
-	mmio_setbits_32(IMX_GPC_BASE + SLPCR, 0x3f << SLPCR_RBC_COUNT_SHIFT);
-}
-
-void imx_clear_rbc_count(void)
-{
-	mmio_clrbits_32(IMX_GPC_BASE + SLPCR, 0x3f << SLPCR_RBC_COUNT_SHIFT);
-}
-
 void imx_gpc_init(void)
 {
 	uint32_t val;
diff --git a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
index b18edd9..9263354 100644
--- a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
@@ -15,6 +15,7 @@
 #include <context.h>
 #include <drivers/arm/tzc380.h>
 #include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
 #include <lib/el3_runtime/context_mgmt.h>
 #include <lib/mmio.h>
 #include <lib/xlat_tables/xlat_tables.h>
@@ -84,6 +85,11 @@
 		mmio_write_32(IMX_CSU_BASE + i * 4, 0xffffffff);
 	}
 
+	/* config CAAM JRaMID set MID to Cortex A */
+	mmio_write_32(CAAM_JR0MID, CAAM_NS_MID);
+	mmio_write_32(CAAM_JR1MID, CAAM_NS_MID);
+	mmio_write_32(CAAM_JR2MID, CAAM_NS_MID);
+
 #if DEBUG_CONSOLE
 	static console_uart_t console;
 
@@ -123,6 +129,8 @@
 
 void bl31_platform_setup(void)
 {
+	generic_delay_timer_init();
+
 	/* init the GICv3 cpu and distributor interface */
 	plat_gic_driver_init();
 	plat_gic_init();
diff --git a/plat/imx/imx8m/imx8mq/imx8mq_psci.c b/plat/imx/imx8m/imx8mq/imx8mq_psci.c
index ee58865..04e191f 100644
--- a/plat/imx/imx8m/imx8mq/imx8mq_psci.c
+++ b/plat/imx/imx8m/imx8mq/imx8mq_psci.c
@@ -13,55 +13,9 @@
 #include <lib/psci/psci.h>
 
 #include <gpc.h>
+#include <imx8m_psci.h>
 #include <plat_imx8.h>
 
-#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0])
-#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1])
-#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
-
-int imx_pwr_domain_on(u_register_t mpidr)
-{
-	unsigned int core_id;
-	uint64_t base_addr = BL31_BASE;
-
-	core_id = MPIDR_AFFLVL0_VAL(mpidr);
-
-	/* set the secure entrypoint */
-	imx_set_cpu_secure_entry(core_id, base_addr);
-	/* power up the core */
-	imx_set_cpu_pwr_on(core_id);
-
-	return PSCI_E_SUCCESS;
-}
-
-void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
-{
-	/* program the GIC per cpu dist and rdist interface */
-	plat_gic_pcpu_init();
-	/* enable the GICv3 cpu interface */
-	plat_gic_cpuif_enable();
-}
-
-void imx_pwr_domain_off(const psci_power_state_t *target_state)
-{
-	uint64_t mpidr = read_mpidr_el1();
-	unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
-
-	/* disable the GIC cpu interface first */
-	plat_gic_cpuif_disable();
-	/* config the core for power down */
-	imx_set_cpu_pwr_off(core_id);
-}
-
-int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
-{
-	/* The non-secure entrypoint should be in RAM space */
-	if (ns_entrypoint < PLAT_NS_IMAGE_OFFSET)
-		return PSCI_E_INVALID_PARAMS;
-
-	return PSCI_E_SUCCESS;
-}
-
 int imx_validate_power_state(unsigned int power_state,
 			 psci_power_state_t *req_state)
 {
@@ -85,18 +39,6 @@
 	return PSCI_E_SUCCESS;
 }
 
-void imx_cpu_standby(plat_local_state_t cpu_state)
-{
-	dsb();
-	write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
-	isb();
-
-	wfi();
-
-	write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
-	isb();
-}
-
 void imx_domain_suspend(const psci_power_state_t *target_state)
 {
 	uint64_t base_addr = BL31_BASE;
@@ -120,7 +62,7 @@
 		imx_set_cluster_standby(true);
 
 	if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
-		imx_set_sys_lpm(true);
+		imx_set_sys_lpm(core_id, true);
 	}
 }
 
@@ -131,7 +73,7 @@
 
 	/* check the system level status */
 	if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
-		imx_set_sys_lpm(false);
+		imx_set_sys_lpm(core_id, false);
 		imx_clear_rbc_count();
 	}
 
@@ -163,47 +105,6 @@
 	req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PLAT_MAX_RET_STATE;
 }
 
-void __dead2 imx_system_reset(void)
-{
-	uintptr_t wdog_base = IMX_WDOG_BASE;
-	unsigned int val;
-
-	/* WDOG_B reset */
-	val = mmio_read_16(wdog_base);
-#ifdef IMX_WDOG_B_RESET
-	val = (val & 0x00FF) | WDOG_WCR_WDZST | WDOG_WCR_WDE |
-		WDOG_WCR_WDT | WDOG_WCR_SRS;
-#else
-	val = (val & 0x00FF) | WDOG_WCR_WDZST | WDOG_WCR_SRS;
-#endif
-	mmio_write_16(wdog_base, val);
-
-	mmio_write_16(wdog_base + WDOG_WSR, 0x5555);
-	mmio_write_16(wdog_base + WDOG_WSR, 0xaaaa);
-	while (1)
-		;
-}
-
-
-
-void __dead2 imx_system_off(void)
-{
-	mmio_write_32(IMX_SNVS_BASE + SNVS_LPCR, SNVS_LPCR_SRTC_ENV |
-			SNVS_LPCR_DP_EN | SNVS_LPCR_TOP);
-
-	while (1)
-		;
-}
-
-void __dead2 imx_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
-{
-	if (is_local_state_off(CLUSTER_PWR_STATE(target_state)))
-		imx_set_rbc_count();
-
-	while (1)
-		wfi();
-}
-
 static const plat_psci_ops_t imx_plat_psci_ops = {
 	.pwr_domain_on = imx_pwr_domain_on,
 	.pwr_domain_on_finish = imx_pwr_domain_on_finish,
diff --git a/plat/imx/imx8m/imx8mq/include/platform_def.h b/plat/imx/imx8m/imx8mq/include/platform_def.h
index 4957582..b54201e 100644
--- a/plat/imx/imx8m/imx8mq/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mq/include/platform_def.h
@@ -26,6 +26,7 @@
 #define PLAT_MAX_OFF_STATE		U(4)
 #define PLAT_MAX_RET_STATE		U(1)
 
+#define PLAT_WAIT_RET_STATE		PLAT_MAX_RET_STATE
 #define PLAT_WAIT_OFF_STATE		U(2)
 #define PLAT_STOP_OFF_STATE		U(3)
 
@@ -119,3 +120,8 @@
 #define DEBUG_CONSOLE			0
 #define IMX_WDOG_B_RESET
 #define PLAT_IMX8M			1
+
+#define CAAM_JR0MID			U(0x30900010)
+#define CAAM_JR1MID			U(0x30900018)
+#define CAAM_JR2MID			U(0x30900020)
+#define CAAM_NS_MID			U(0x1)
diff --git a/plat/imx/imx8m/imx8mq/platform.mk b/plat/imx/imx8m/imx8mq/platform.mk
index 2681e57..7004c56 100644
--- a/plat/imx/imx8m/imx8mq/platform.mk
+++ b/plat/imx/imx8m/imx8mq/platform.mk
@@ -20,6 +20,8 @@
 BL31_SOURCES		+=	plat/imx/common/imx8_helpers.S			\
 				plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c	\
 				plat/imx/imx8m/imx8mq/imx8mq_psci.c		\
+				plat/imx/imx8m/gpc_common.c			\
+				plat/imx/imx8m/imx8m_psci_common.c		\
 				plat/imx/imx8m/imx8mq/gpc.c			\
 				plat/imx/common/imx8_topology.c			\
 				plat/imx/common/imx_uart_console.S		\
@@ -28,6 +30,8 @@
 				lib/cpus/aarch64/cortex_a53.S			\
 				drivers/console/aarch64/console.S		\
 				drivers/arm/tzc/tzc380.c			\
+				drivers/delay_timer/delay_timer.c		\
+				drivers/delay_timer/generic_delay_timer.c	\
 				${IMX_GIC_SOURCES}
 
 USE_COHERENT_MEM	:=	1
diff --git a/plat/imx/imx8m/include/gpc.h b/plat/imx/imx8m/include/gpc.h
index 6fdf6ad..139132c 100644
--- a/plat/imx/imx8m/include/gpc.h
+++ b/plat/imx/imx8m/include/gpc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -29,15 +29,18 @@
 #define PU_PGC_DN_TRG			0x104
 #define A53_CORE0_PGC			0x800
 #define A53_PLAT_PGC			0x900
+#define PLAT_PGC_PCR			0x900
 #define PGC_SCU_TIMING			0x910
 
 #define MASK_DSM_TRIGGER_A53		BIT(31)
 #define IRQ_SRC_A53_WUP			BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT		30
 #define IRQ_SRC_C1			BIT(29)
 #define IRQ_SRC_C0			BIT(28)
 #define IRQ_SRC_C3			BIT(23)
 #define IRQ_SRC_C2			BIT(22)
 #define CPU_CLOCK_ON_LPM		BIT(14)
+#define A53_CLK_ON_LPM			BIT(14)
 #define MASTER0_LPM_HSK			BIT(6)
 
 #define L2PGE				BIT(31)
@@ -52,19 +55,27 @@
 #define SLPCR_SBYOS			BIT(1)
 #define SLPCR_BYPASS_PMIC_READY		BIT(0)
 #define SLPCR_RBC_COUNT_SHIFT		24
+#define SLPCR_STBY_COUNT_SHFT		3
 
 #define A53_DUMMY_PDN_ACK		BIT(15)
 #define A53_DUMMY_PUP_ACK		BIT(31)
 #define A53_PLAT_PDN_ACK		BIT(2)
 #define A53_PLAT_PUP_ACK		BIT(18)
 
+#define PLAT_PUP_SLT_CTRL		BIT(9)
+#define PLAT_PDN_SLT_CTRL		BIT(8)
+
 #define SLT_PLAT_PDN			BIT(8)
 #define SLT_PLAT_PUP			BIT(9)
 
+#define MASTER1_MAPPING			BIT(1)
+#define MASTER2_MAPPING			BIT(2)
+
 /* helper macro */
 #define A53_LPM_MASK	U(0xF)
 #define A53_LPM_WAIT	U(0x5)
 #define A53_LPM_STOP	U(0xA)
+#define LPM_MODE(local_state)		((local_state) == PLAT_WAIT_RET_STATE ? A53_LPM_WAIT : A53_LPM_STOP)
 
 #define DSM_MODE_MASK	BIT(31)
 
@@ -76,6 +87,9 @@
 #define SLTx_CFG(n)			((SLT0_CFG + ((n) * 4)))
 #define SLT_COREx_PUP(core_id)		(0x2 << ((core_id) * 2))
 
+#define IRQ_IMR_NUM	4
+#define IMR_MASK_ALL	0xffffffff
+
 /* function declare */
 void imx_gpc_init(void);
 void imx_set_cpu_secure_entry(unsigned int core_index, uintptr_t sec_entrypoint);
@@ -84,7 +98,9 @@
 void imx_set_cpu_lpm(unsigned int core_index, bool pdn);
 void imx_set_cluster_standby(bool retention);
 void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state);
-void imx_set_sys_lpm(bool retention);
+void imx_noc_slot_config(bool pdn);
+void imx_set_sys_wakeup(unsigned int last_core, bool pdn);
+void imx_set_sys_lpm(unsigned last_core, bool retention);
 void imx_set_rbc_count(void);
 void imx_clear_rbc_count(void);
 
diff --git a/plat/imx/imx8m/include/imx8m_psci.h b/plat/imx/imx8m/include/imx8m_psci.h
new file mode 100644
index 0000000..4966403
--- /dev/null
+++ b/plat/imx/imx8m/include/imx8m_psci.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX8M_PSCI_H
+#define IMX8M_PSCI_H
+
+#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0])
+#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
+
+int imx_pwr_domain_on(u_register_t mpidr);
+void imx_pwr_domain_on_finish(const psci_power_state_t *target_state);
+void imx_pwr_domain_off(const psci_power_state_t *target_state);
+int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint);
+int imx_validate_power_state(unsigned int power_state, psci_power_state_t *rq_state);
+void imx_cpu_standby(plat_local_state_t cpu_state);
+void imx_domain_suspend(const psci_power_state_t *target_state);
+void imx_domain_suspend_finish(const psci_power_state_t *target_state);
+void imx_get_sys_suspend_power_state(psci_power_state_t *req_state);
+void __dead2 imx_system_reset(void);
+void __dead2 imx_system_off(void);
+void __dead2 imx_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state);
+
+#endif /* IMX8M_PSCI_H */
diff --git a/plat/intel/soc/stratix10/aarch64/stratix10_private.h b/plat/intel/soc/stratix10/aarch64/stratix10_private.h
index 89851ef..f437202 100644
--- a/plat/intel/soc/stratix10/aarch64/stratix10_private.h
+++ b/plat/intel/soc/stratix10/aarch64/stratix10_private.h
@@ -29,6 +29,6 @@
 } boot_source_type;
 
 void enable_nonsecure_access(void);
-void stratix10_io_setup(void);
+void stratix10_io_setup(int boot_source);
 
 #endif
diff --git a/plat/intel/soc/stratix10/bl2_plat_setup.c b/plat/intel/soc/stratix10/bl2_plat_setup.c
index 91e3b0a..9a2f9d3 100644
--- a/plat/intel/soc/stratix10/bl2_plat_setup.c
+++ b/plat/intel/soc/stratix10/bl2_plat_setup.c
@@ -30,17 +30,25 @@
 #include "s10_handoff.h"
 #include "s10_pinmux.h"
 #include "aarch64/stratix10_private.h"
+#include "include/s10_mailbox.h"
+#include "drivers/qspi/cadence_qspi.h"
+
 
 const mmap_region_t plat_stratix10_mmap[] = {
-	MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS),
-	MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_NS),
-	MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE,
+		MT_MEMORY | MT_RW | MT_NS),
+	MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE,
+		MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE,
+		MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE,
 		MT_NON_CACHEABLE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(DEVICE3_BASE, DEVICE3_SIZE,
 		MT_DEVICE | MT_RW | MT_SECURE),
-	MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE, MT_DEVICE | MT_RW | MT_NS),
-	MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE, MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE,
+		MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE,
+		MT_DEVICE | MT_RW | MT_NS),
 	{0},
 };
 
@@ -99,12 +107,23 @@
 	dw_mmc_params_t params = EMMC_INIT_PARAMS(0x100000);
 
 	info.mmc_dev_type = MMC_IS_SD;
+	info.ocr_voltage = OCR_3_3_3_4 | OCR_3_2_3_3;
 
 	switch (boot_source) {
 	case BOOT_SOURCE_SDMMC:
 		dw_mmc_init(&params, &info);
-		stratix10_io_setup();
+		stratix10_io_setup(boot_source);
 		break;
+
+	case BOOT_SOURCE_QSPI:
+		mailbox_set_qspi_open();
+		mailbox_set_qspi_direct();
+		cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL,
+			QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS,
+			QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0);
+		stratix10_io_setup(boot_source);
+		break;
+
 	default:
 		ERROR("Unsupported boot source\n");
 		panic();
diff --git a/plat/intel/soc/stratix10/drivers/qspi/cadence_qspi.c b/plat/intel/soc/stratix10/drivers/qspi/cadence_qspi.c
new file mode 100644
index 0000000..506a633
--- /dev/null
+++ b/plat/intel/soc/stratix10/drivers/qspi/cadence_qspi.c
@@ -0,0 +1,824 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <string.h>
+#include <drivers/delay_timer.h>
+#include <drivers/console.h>
+
+#include "cadence_qspi.h"
+#include <platform_def.h>
+
+#define LESS(a, b)   (((a) < (b)) ? (a) : (b))
+#define MORE(a, b)   (((a) > (b)) ? (a) : (b))
+
+
+uint32_t qspi_device_size;
+int cad_qspi_cs;
+
+int cad_qspi_idle(void)
+{
+	return (mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG)
+			& CAD_QSPI_CFG_IDLE) >> 31;
+}
+
+int cad_qspi_set_baudrate_div(uint32_t div)
+{
+	if (div > 0xf)
+		return CAD_INVALID;
+
+	mmio_clrsetbits_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG,
+			~CAD_QSPI_CFG_BAUDDIV_MSK,
+			CAD_QSPI_CFG_BAUDDIV(div));
+
+	return 0;
+}
+
+int cad_qspi_configure_dev_size(uint32_t addr_bytes,
+		uint32_t bytes_per_dev, uint32_t bytes_per_block)
+{
+
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVSZ,
+			CAD_QSPI_DEVSZ_ADDR_BYTES(addr_bytes) |
+			CAD_QSPI_DEVSZ_BYTES_PER_PAGE(bytes_per_dev) |
+			CAD_QSPI_DEVSZ_BYTES_PER_BLOCK(bytes_per_block));
+	return 0;
+}
+
+int cad_qspi_set_read_config(uint32_t opcode, uint32_t instr_type,
+		uint32_t addr_type, uint32_t data_type,
+		uint32_t mode_bit, uint32_t dummy_clk_cycle)
+{
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVRD,
+			CAD_QSPI_DEV_OPCODE(opcode) |
+			CAD_QSPI_DEV_INST_TYPE(instr_type) |
+			CAD_QSPI_DEV_ADDR_TYPE(addr_type) |
+			CAD_QSPI_DEV_DATA_TYPE(data_type) |
+			CAD_QSPI_DEV_MODE_BIT(mode_bit) |
+			CAD_QSPI_DEV_DUMMY_CLK_CYCLE(dummy_clk_cycle));
+
+	return 0;
+}
+
+int cat_qspi_set_write_config(uint32_t addr_type, uint32_t data_type,
+		uint32_t mode_bit, uint32_t dummy_clk_cycle)
+{
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVWR,
+			CAD_QSPI_DEV_ADDR_TYPE(addr_type) |
+			CAD_QSPI_DEV_DATA_TYPE(data_type) |
+			CAD_QSPI_DEV_MODE_BIT(mode_bit) |
+			CAD_QSPI_DEV_DUMMY_CLK_CYCLE(dummy_clk_cycle));
+
+	return 0;
+}
+
+int cad_qspi_timing_config(uint32_t clkphase, uint32_t clkpol, uint32_t csda,
+		uint32_t csdads, uint32_t cseot, uint32_t cssot,
+		uint32_t rddatacap)
+{
+	uint32_t cfg = mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG);
+
+	cfg &= CAD_QSPI_CFG_SELCLKPHASE_CLR_MSK &
+		CAD_QSPI_CFG_SELCLKPOL_CLR_MSK;
+	cfg |= CAD_QSPI_SELCLKPHASE(clkphase) | CAD_QSPI_SELCLKPOL(clkpol);
+
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, cfg);
+
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DELAY,
+		CAD_QSPI_DELAY_CSSOT(cssot) | CAD_QSPI_DELAY_CSEOT(cseot) |
+		CAD_QSPI_DELAY_CSDADS(csdads) | CAD_QSPI_DELAY_CSDA(csda));
+
+	return 0;
+}
+
+int cad_qspi_stig_cmd_helper(int cs, uint32_t cmd)
+{
+	uint32_t count = 0;
+
+	/* chip select */
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG,
+			(mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG)
+			 & CAD_QSPI_CFG_CS_MSK) | CAD_QSPI_CFG_CS(cs));
+
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD, cmd);
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD,
+			cmd | CAD_QSPI_FLASHCMD_EXECUTE);
+
+	do {
+		uint32_t reg = mmio_read_32(CAD_QSPI_OFFSET +
+					CAD_QSPI_FLASHCMD);
+		if (!(reg & CAD_QSPI_FLASHCMD_EXECUTE_STAT))
+			break;
+		count++;
+	} while (count < CAD_QSPI_COMMAND_TIMEOUT);
+
+	if (count >= CAD_QSPI_COMMAND_TIMEOUT) {
+		ERROR("Error sending QSPI command %x, timed out\n",
+				cmd);
+		return CAD_QSPI_ERROR;
+	}
+
+	return 0;
+}
+
+int cad_qspi_stig_cmd(uint32_t opcode, uint32_t dummy)
+{
+	if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) {
+		ERROR("Faulty dummy bytes\n");
+		return -1;
+	}
+
+	return cad_qspi_stig_cmd_helper(cad_qspi_cs,
+			CAD_QSPI_FLASHCMD_OPCODE(opcode) |
+			CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES(dummy));
+}
+
+int cad_qspi_stig_read_cmd(uint32_t opcode, uint32_t dummy, uint32_t num_bytes,
+		uint32_t *output)
+{
+	if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) {
+		ERROR("Faulty dummy byes\n");
+		return -1;
+	}
+
+	if ((num_bytes > 8) || (num_bytes == 0))
+		return -1;
+
+	uint32_t cmd =
+		CAD_QSPI_FLASHCMD_OPCODE(opcode) |
+		CAD_QSPI_FLASHCMD_ENRDDATA(1) |
+		CAD_QSPI_FLASHCMD_NUMRDDATABYTES(num_bytes - 1) |
+		CAD_QSPI_FLASHCMD_ENCMDADDR(0) |
+		CAD_QSPI_FLASHCMD_ENMODEBIT(0) |
+		CAD_QSPI_FLASHCMD_NUMADDRBYTES(0) |
+		CAD_QSPI_FLASHCMD_ENWRDATA(0) |
+		CAD_QSPI_FLASHCMD_NUMWRDATABYTES(0) |
+		CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy);
+
+	if (cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd)) {
+		ERROR("failed to send stig cmd");
+		return -1;
+	}
+
+	output[0] = mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_RDDATA0);
+
+	if (num_bytes > 4) {
+		output[1] = mmio_read_32(CAD_QSPI_OFFSET +
+				CAD_QSPI_FLASHCMD_RDDATA1);
+	}
+
+	return 0;
+}
+
+int cad_qspi_stig_wr_cmd(uint32_t opcode, uint32_t dummy, uint32_t num_bytes,
+		uint32_t *input)
+{
+	if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) {
+		ERROR("Faulty dummy byes\n");
+		return -1;
+	}
+
+	if ((num_bytes > 8) || (num_bytes == 0))
+		return -1;
+
+	uint32_t cmd = CAD_QSPI_FLASHCMD_OPCODE(opcode) |
+		CAD_QSPI_FLASHCMD_ENRDDATA(0) |
+		CAD_QSPI_FLASHCMD_NUMRDDATABYTES(0) |
+		CAD_QSPI_FLASHCMD_ENCMDADDR(0) |
+		CAD_QSPI_FLASHCMD_ENMODEBIT(0) |
+		CAD_QSPI_FLASHCMD_NUMADDRBYTES(0) |
+		CAD_QSPI_FLASHCMD_ENWRDATA(1) |
+		CAD_QSPI_FLASHCMD_NUMWRDATABYTES(num_bytes - 1) |
+		CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy);
+
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_WRDATA0, input[0]);
+
+	if (num_bytes > 4)
+		mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_WRDATA1,
+				input[1]);
+
+	return cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd);
+}
+
+int cad_qspi_stig_addr_cmd(uint32_t opcode, uint32_t dummy, uint32_t addr)
+{
+	uint32_t cmd;
+
+	if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1))
+		return -1;
+
+	cmd = CAD_QSPI_FLASHCMD_OPCODE(opcode) |
+		CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy) |
+		CAD_QSPI_FLASHCMD_ENCMDADDR(1) |
+		CAD_QSPI_FLASHCMD_NUMADDRBYTES(2);
+
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_ADDR, addr);
+
+	return cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd);
+}
+
+int cad_qspi_device_bank_select(uint32_t bank)
+{
+	int status = 0;
+
+	status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0);
+	if (status != 0)
+		return status;
+
+	status = cad_qspi_stig_wr_cmd(CAD_QSPI_STIG_OPCODE_WREN_EXT_REG,
+			0, 1, &bank);
+	if (status != 0)
+		return status;
+
+	return cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WRDIS, 0);
+}
+
+int cad_qspi_device_status(uint32_t *status)
+{
+	return cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDSR, 0, 1, status);
+}
+
+#if CAD_QSPI_MICRON_N25Q_SUPPORT
+int cad_qspi_n25q_enable(void)
+{
+	cad_qspi_set_read_config(QSPI_FAST_READ, CAD_QSPI_INST_SINGLE,
+			CAD_QSPI_ADDR_FASTREAD, CAT_QSPI_ADDR_SINGLE_IO, 1,
+			0);
+	return 0;
+}
+
+int cad_qspi_n25q_wait_for_program_and_erase(int program_only)
+{
+	uint32_t status, flag_sr;
+	int count = 0;
+
+	while (count < CAD_QSPI_COMMAND_TIMEOUT) {
+		status = cad_qspi_device_status(&status);
+		if (status != 0) {
+			ERROR("Error getting device status\n");
+			return -1;
+		}
+		if (!CAD_QSPI_STIG_SR_BUSY(status))
+			break;
+		count++;
+	}
+
+	if (count >= CAD_QSPI_COMMAND_TIMEOUT) {
+		ERROR("Timed out waiting for idle\n");
+		return -1;
+	}
+
+	count = 0;
+
+	while (count < CAD_QSPI_COMMAND_TIMEOUT) {
+		status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDFLGSR,
+				0, 1, &flag_sr);
+		if (status != 0) {
+			ERROR("Error waiting program and erase.\n");
+			return status;
+		}
+
+		if ((program_only &&
+			CAD_QSPI_STIG_FLAGSR_PROGRAMREADY(flag_sr)) ||
+			(!program_only &&
+			CAD_QSPI_STIG_FLAGSR_ERASEREADY(flag_sr)))
+			break;
+	}
+
+	if (count >= CAD_QSPI_COMMAND_TIMEOUT)
+		ERROR("Timed out waiting for program and erase\n");
+
+	if ((program_only && CAD_QSPI_STIG_FLAGSR_PROGRAMERROR(flag_sr)) ||
+			(!program_only &&
+			CAD_QSPI_STIG_FLAGSR_ERASEERROR(flag_sr))) {
+		ERROR("Error programming/erasing flash\n");
+		cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_CLFSR, 0);
+		return -1;
+	}
+
+	return 0;
+}
+#endif
+
+int cad_qspi_indirect_read_start_bank(uint32_t flash_addr, uint32_t num_bytes)
+{
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRDSTADDR, flash_addr);
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRDCNT, num_bytes);
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRD,
+			CAD_QSPI_INDRD_START |
+			CAD_QSPI_INDRD_IND_OPS_DONE);
+
+	return 0;
+}
+
+
+int cad_qspi_indirect_write_start_bank(uint32_t flash_addr,
+					uint32_t num_bytes)
+{
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWRSTADDR, flash_addr);
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWRCNT, num_bytes);
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWR,
+			CAD_QSPI_INDWR_START |
+			CAD_QSPI_INDWR_INDDONE);
+
+	return 0;
+}
+
+int cad_qspi_indirect_write_finish(void)
+{
+#if CAD_QSPI_MICRON_N25Q_SUPPORT
+	return cad_qspi_n25q_wait_for_program_and_erase(1);
+#else
+	return 0;
+#endif
+
+}
+
+int cad_qspi_enable(void)
+{
+	int status;
+
+	mmio_setbits_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, CAD_QSPI_CFG_ENABLE);
+
+#if CAD_QSPI_MICRON_N25Q_SUPPORT
+	status = cad_qspi_n25q_enable();
+	if (status != 0)
+		return status;
+#endif
+	return 0;
+}
+
+int cad_qspi_enable_subsector_bank(uint32_t addr)
+{
+	int status = 0;
+
+	status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0);
+	if (status != 0)
+		return status;
+
+	status = cad_qspi_stig_addr_cmd(CAD_QSPI_STIG_OPCODE_SUBSEC_ERASE, 0,
+					addr);
+	if (status != 0)
+		return status;
+
+#if CAD_QSPI_MICRON_N25Q_SUPPORT
+	status = cad_qspi_n25q_wait_for_program_and_erase(0);
+#endif
+	return status;
+}
+
+int cad_qspi_erase_subsector(uint32_t addr)
+{
+	int status = 0;
+
+	status = cad_qspi_device_bank_select(addr >> 24);
+	if (status != 0)
+		return status;
+
+	return cad_qspi_enable_subsector_bank(addr);
+}
+
+int cad_qspi_erase_sector(uint32_t addr)
+{
+	int status = 0;
+
+	status = cad_qspi_device_bank_select(addr >> 24);
+	if (status != 0)
+		return status;
+
+	status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0);
+	if (status != 0)
+		return status;
+
+	status = cad_qspi_stig_addr_cmd(CAD_QSPI_STIG_OPCODE_SEC_ERASE, 0,
+					addr);
+	if (status != 0)
+		return status;
+
+#if CAD_QSPI_MICRON_N25Q_SUPPORT
+	status = cad_qspi_n25q_wait_for_program_and_erase(0);
+#endif
+	return status;
+}
+
+void cad_qspi_calibration(uint32_t dev_clk, uint32_t qspi_clk_mhz)
+{
+	int status;
+	uint32_t dev_sclk_mhz = 27; /*min value to get biggest 0xF div factor*/
+	uint32_t data_cap_delay;
+	uint32_t sample_rdid;
+	uint32_t rdid;
+	uint32_t div_actual;
+	uint32_t div_bits;
+	int first_pass, last_pass;
+
+	/*1.  Set divider to bigger value (slowest SCLK)
+	 *2.  RDID and save the value
+	 */
+	div_actual = (qspi_clk_mhz + (dev_sclk_mhz - 1)) / dev_sclk_mhz;
+	div_bits = (((div_actual + 1) / 2) - 1);
+	status = cad_qspi_set_baudrate_div(0xf);
+
+	status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID,
+					0, 3, &sample_rdid);
+	if (status != 0)
+		return;
+
+	/*3. Set divider to the intended frequency
+	 *4.  Set the read delay = 0
+	 *5.  RDID and check whether the value is same as item 2
+	 *6.  Increase read delay and compared the value against item 2
+	 *7.  Find the range of read delay that have same as
+	 *    item 2 and divide it to 2
+	 */
+	div_actual = (qspi_clk_mhz + (dev_clk - 1)) / dev_clk;
+	div_bits = (((div_actual + 1) / 2) - 1);
+	status = cad_qspi_set_baudrate_div(div_bits);
+	if (status != 0)
+		return;
+
+	data_cap_delay = 0;
+	first_pass = -1;
+	last_pass = -1;
+
+	do {
+		if (status != 0)
+			break;
+		status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0,
+						3, &rdid);
+		if (status != 0)
+			break;
+		if (rdid == sample_rdid) {
+			if (first_pass == -1)
+				first_pass = data_cap_delay;
+			else
+				last_pass = data_cap_delay;
+		}
+
+		data_cap_delay++;
+
+		mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_RDDATACAP,
+				CAD_QSPI_RDDATACAP_BYP(1) |
+				CAD_QSPI_RDDATACAP_DELAY(data_cap_delay));
+
+	} while (data_cap_delay < 0x10);
+
+	if (first_pass > 0) {
+		int diff = first_pass - last_pass;
+
+		data_cap_delay = first_pass + diff / 2;
+	}
+
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_RDDATACAP,
+			CAD_QSPI_RDDATACAP_BYP(1) |
+			CAD_QSPI_RDDATACAP_DELAY(data_cap_delay));
+	status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0, 3, &rdid);
+
+	if (status != 0)
+		return;
+}
+
+int cad_qspi_int_disable(uint32_t mask)
+{
+	if (cad_qspi_idle() == 0)
+		return -1;
+
+	if ((CAD_QSPI_INT_STATUS_ALL & mask) == 0)
+		return -1;
+
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_IRQMSK, mask);
+	return 0;
+}
+
+void cad_qspi_set_chip_select(int cs)
+{
+	cad_qspi_cs = cs;
+}
+
+int cad_qspi_init(uint32_t desired_clk_freq, uint32_t clk_phase,
+			uint32_t clk_pol, uint32_t csda, uint32_t csdads,
+			uint32_t cseot, uint32_t cssot, uint32_t rddatacap)
+{
+	int status = 0;
+	uint32_t qspi_desired_clk_freq;
+	uint32_t rdid = 0;
+	uint32_t cap_code;
+
+	INFO("Initializing Qspi\n");
+
+	if (cad_qspi_idle() == 0) {
+		ERROR("device not idle");
+		return -1;
+	}
+
+
+	status = cad_qspi_timing_config(clk_phase, clk_pol, csda, csdads,
+					cseot, cssot, rddatacap);
+
+	if (status != 0) {
+		ERROR("config set timing failure\n");
+		return status;
+	}
+
+	mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_REMAPADDR,
+			CAD_QSPI_REMAPADDR_VALUE_SET(0));
+
+	status = cad_qspi_int_disable(CAD_QSPI_INT_STATUS_ALL);
+	if (status != 0) {
+		ERROR("failed disable\n");
+		return status;
+	}
+
+	cad_qspi_set_baudrate_div(0xf);
+	status = cad_qspi_enable();
+	if (status != 0) {
+		ERROR("failed enable\n");
+		return status;
+	}
+
+	qspi_desired_clk_freq = 100;
+	cad_qspi_calibration(qspi_desired_clk_freq, 50000000);
+
+	status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0, 3,
+					&rdid);
+
+	if (status != 0) {
+		ERROR("Error reading RDID\n");
+		return status;
+	}
+
+	/*
+	 * NOTE: The Size code seems to be a form of BCD (binary coded decimal).
+	 * The first nibble is the 10's digit and the second nibble is the 1's
+	 * digit in the number of bytes.
+	 *
+	 * Capacity ID samples:
+	 * 0x15 :   16 Mb =>   2 MiB => 1 << 21 ; BCD=15
+	 * 0x16 :   32 Mb =>   4 MiB => 1 << 22 ; BCD=16
+	 * 0x17 :   64 Mb =>   8 MiB => 1 << 23 ; BCD=17
+	 * 0x18 :  128 Mb =>  16 MiB => 1 << 24 ; BCD=18
+	 * 0x19 :  256 Mb =>  32 MiB => 1 << 25 ; BCD=19
+	 * 0x1a
+	 * 0x1b
+	 * 0x1c
+	 * 0x1d
+	 * 0x1e
+	 * 0x1f
+	 * 0x20 :  512 Mb =>  64 MiB => 1 << 26 ; BCD=20
+	 * 0x21 : 1024 Mb => 128 MiB => 1 << 27 ; BCD=21
+	 */
+
+	cap_code = CAD_QSPI_STIG_RDID_CAPACITYID(rdid);
+
+	if (!(((cap_code >> 4) > 0x9) || ((cap_code & 0xf) > 0x9))) {
+		uint32_t decoded_cap = ((cap_code >> 4) * 10) +
+					(cap_code & 0xf);
+		qspi_device_size = 1 << (decoded_cap + 6);
+		INFO("QSPI Capacity: %x\n\n", qspi_device_size);
+
+	} else {
+		ERROR("Invalid CapacityID encountered: 0x%02x\n",
+				cap_code);
+		return -1;
+	}
+
+	cad_qspi_configure_dev_size(S10_QSPI_ADDR_BYTES,
+				S10_QSPI_BYTES_PER_DEV, S10_BYTES_PER_BLOCK);
+
+	INFO("Flash size: %d Bytes\n", qspi_device_size);
+
+	return status;
+}
+
+int cad_qspi_indirect_page_bound_write(uint32_t offset,
+		uint8_t *buffer, uint32_t len)
+{
+	int status = 0, i;
+	uint32_t write_count, write_capacity, *write_data, space,
+		write_fill_level, sram_partition;
+
+	status = cad_qspi_indirect_write_start_bank(offset, len);
+	if (status != 0)
+		return status;
+
+	write_count = 0;
+	sram_partition = CAD_QSPI_SRAMPART_ADDR(mmio_read_32(CAD_QSPI_OFFSET +
+			 CAD_QSPI_SRAMPART));
+	write_capacity = (uint32_t) CAD_QSPI_SRAM_FIFO_ENTRY_COUNT -
+			sram_partition;
+
+	while (write_count < len) {
+		write_fill_level = CAD_QSPI_SRAMFILL_INDWRPART(
+					mmio_read_32(CAD_QSPI_OFFSET +
+							CAD_QSPI_SRAMFILL));
+		space = LESS(write_capacity - write_fill_level,
+				(len - write_count) / sizeof(uint32_t));
+		write_data = (uint32_t *)(buffer + write_count);
+		for (i = 0; i < space; ++i)
+			mmio_write_32(CAD_QSPIDATA_OFST, *write_data++);
+
+		write_count += space * sizeof(uint32_t);
+	}
+	return cad_qspi_indirect_write_finish();
+}
+
+int cad_qspi_read_bank(uint8_t *buffer, uint32_t offset, uint32_t size)
+{
+	int status;
+	uint32_t read_count = 0, *read_data;
+	int level = 1, count = 0, i;
+
+	status = cad_qspi_indirect_read_start_bank(offset, size);
+
+	if (status != 0)
+		return status;
+
+	while (read_count < size) {
+		do {
+			level = CAD_QSPI_SRAMFILL_INDRDPART(
+				mmio_read_32(CAD_QSPI_OFFSET +
+					CAD_QSPI_SRAMFILL));
+			read_data = (uint32_t *)(buffer + read_count);
+			for (i = 0; i < level; ++i)
+				*read_data++ = mmio_read_32(CAD_QSPIDATA_OFST);
+
+			read_count += level * sizeof(uint32_t);
+			count++;
+		} while (level > 0);
+	}
+
+	return 0;
+}
+
+int cad_qspi_write_bank(uint32_t offset, uint8_t *buffer, uint32_t size)
+{
+	int status = 0;
+	uint32_t page_offset  = offset & (CAD_QSPI_PAGE_SIZE - 1);
+	uint32_t write_size = LESS(size, CAD_QSPI_PAGE_SIZE - page_offset);
+
+	while (size) {
+		status = cad_qspi_indirect_page_bound_write(offset, buffer,
+							write_size);
+		if (status != 0)
+			break;
+
+		offset  += write_size;
+		buffer  += write_size;
+		size -= write_size;
+		write_size = LESS(size, CAD_QSPI_PAGE_SIZE);
+	}
+	return status;
+}
+
+int cad_qspi_read(void *buffer, uint32_t  offset, uint32_t  size)
+{
+	uint32_t bank_count, bank_addr, bank_offset, copy_len;
+	uint8_t *read_data;
+	int i, status;
+
+	status = 0;
+
+	if ((offset >= qspi_device_size) ||
+			(offset + size - 1 >= qspi_device_size) ||
+			(size == 0) ||
+			((long) ((int *)buffer) & 0x3)  ||
+			(offset & 0x3) ||
+			(size & 0x3)) {
+		ERROR("Invalid read parameter");
+		return -1;
+	}
+
+	if (CAD_QSPI_INDRD_RD_STAT(mmio_read_32(CAD_QSPI_OFFSET +
+						CAD_QSPI_INDRD))) {
+		ERROR("Read in progress");
+		return -1;
+	}
+
+	/*
+	 * bank_count : Number of bank(s) affected, including partial banks.
+	 * bank_addr  : Aligned address of the first bank,
+	 *		including partial bank.
+	 * bank_ofst  : The offset of the bank to read.
+	 *		Only used when reading the first bank.
+	 */
+	bank_count = CAD_QSPI_BANK_ADDR(offset + size - 1) -
+			CAD_QSPI_BANK_ADDR(offset) + 1;
+	bank_addr  = offset & CAD_QSPI_BANK_ADDR_MSK;
+	bank_offset  = offset & (CAD_QSPI_BANK_SIZE - 1);
+
+	read_data = (uint8_t *)buffer;
+
+	copy_len = LESS(size, CAD_QSPI_BANK_SIZE - bank_offset);
+
+	for (i = 0; i < bank_count; ++i) {
+		status = cad_qspi_device_bank_select(CAD_QSPI_BANK_ADDR(
+								bank_addr));
+		if (status != 0)
+			break;
+		status = cad_qspi_read_bank(read_data, bank_offset, copy_len);
+		if (status != 0)
+			break;
+
+		bank_addr += CAD_QSPI_BANK_SIZE;
+		read_data += copy_len;
+		size -= copy_len;
+		bank_offset = 0;
+		copy_len = LESS(size, CAD_QSPI_BANK_SIZE);
+	}
+
+	return status;
+}
+
+int cad_qspi_erase(uint32_t offset, uint32_t size)
+{
+	int status = 0;
+	uint32_t subsector_offset  = offset & (CAD_QSPI_SUBSECTOR_SIZE - 1);
+	uint32_t erase_size = LESS(size,
+				CAD_QSPI_SUBSECTOR_SIZE - subsector_offset);
+
+	while (size) {
+		status = cad_qspi_erase_subsector(offset);
+		if (status != 0)
+			break;
+
+		offset  += erase_size;
+		size -= erase_size;
+		erase_size = LESS(size, CAD_QSPI_SUBSECTOR_SIZE);
+	}
+	return status;
+}
+
+int cad_qspi_write(void *buffer, uint32_t offset, uint32_t size)
+{
+	int status, i;
+	uint32_t bank_count, bank_addr, bank_offset, copy_len;
+	uint8_t *write_data;
+
+	status = 0;
+
+	if ((offset >= qspi_device_size) ||
+			(offset + size - 1 >= qspi_device_size) ||
+			(size == 0) ||
+			((long)buffer & 0x3)  ||
+			(offset & 0x3) ||
+			(size & 0x3))
+		return -2;
+
+	if (CAD_QSPI_INDWR_RDSTAT(mmio_read_32(CAD_QSPI_OFFSET +
+						CAD_QSPI_INDWR))) {
+		ERROR("QSPI Error: Write in progress\n");
+		return -1;
+	}
+
+	bank_count = CAD_QSPI_BANK_ADDR(offset + size - 1) -
+			CAD_QSPI_BANK_ADDR(offset) + 1;
+	bank_addr = offset & CAD_QSPI_BANK_ADDR_MSK;
+	bank_offset = offset & (CAD_QSPI_BANK_SIZE - 1);
+
+	write_data = buffer;
+
+	copy_len = LESS(size, CAD_QSPI_BANK_SIZE - bank_offset);
+
+	for (i = 0; i < bank_count; ++i) {
+		status = cad_qspi_device_bank_select(
+				CAD_QSPI_BANK_ADDR(bank_addr));
+		if (status != 0)
+			break;
+
+		status = cad_qspi_write_bank(bank_offset, write_data,
+						copy_len);
+		if (status != 0)
+			break;
+
+		bank_addr += CAD_QSPI_BANK_SIZE;
+		write_data += copy_len;
+		size -= copy_len;
+		bank_offset = 0;
+
+		copy_len = LESS(size, CAD_QSPI_BANK_SIZE);
+	}
+	return status;
+}
+
+int cad_qspi_update(void *Buffer, uint32_t offset, uint32_t size)
+{
+	int status = 0;
+
+	status = cad_qspi_erase(offset, size);
+	if (status != 0)
+		return status;
+
+	return cad_qspi_write(Buffer, offset, size);
+}
+
+void cad_qspi_reset(void)
+{
+	cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_RESET_EN, 0);
+	cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_RESET_MEM, 0);
+}
+
diff --git a/plat/intel/soc/stratix10/drivers/qspi/cadence_qspi.h b/plat/intel/soc/stratix10/drivers/qspi/cadence_qspi.h
new file mode 100644
index 0000000..e419161
--- /dev/null
+++ b/plat/intel/soc/stratix10/drivers/qspi/cadence_qspi.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CAD_QSPI_H__
+#define __CAD_QSPI_H__
+
+#define CAD_QSPI_MICRON_N25Q_SUPPORT		1
+
+#define CAD_QSPI_OFFSET				0xff8d2000
+
+#define CAD_INVALID				-1
+#define CAD_QSPI_ERROR				-2
+
+#define CAD_QSPI_ADDR_FASTREAD			0
+#define CAD_QSPI_ADDR_FASTREAD_DUAL_IO		1
+#define CAD_QSPI_ADDR_FASTREAD_QUAD_IO		2
+#define CAT_QSPI_ADDR_SINGLE_IO			0
+#define CAT_QSPI_ADDR_DUAL_IO			1
+#define CAT_QSPI_ADDR_QUAD_IO			2
+
+#define CAD_QSPI_BANK_ADDR(x)			((x) >> 24)
+#define CAD_QSPI_BANK_ADDR_MSK			0xff000000
+
+#define CAD_QSPI_COMMAND_TIMEOUT		0x10000000
+
+#define CAD_QSPI_CFG				0x0
+#define CAD_QSPI_CFG_BAUDDIV_MSK		0xff87ffff
+#define CAD_QSPI_CFG_BAUDDIV(x)			(((x) << 19) & 0x780000)
+#define CAD_QSPI_CFG_CS_MSK			~0x3c00
+#define CAD_QSPI_CFG_CS(x)			(((x) << 11))
+#define CAD_QSPI_CFG_ENABLE			(1 << 0)
+#define CAD_QSPI_CFG_ENDMA_CLR_MSK		0xffff7fff
+#define CAD_QSPI_CFG_IDLE			(1 << 31)
+#define CAD_QSPI_CFG_SELCLKPHASE_CLR_MSK	0xfffffffb
+#define CAD_QSPI_CFG_SELCLKPOL_CLR_MSK		0xfffffffd
+
+#define CAD_QSPIDATA_OFST			0xff900000
+
+#define CAD_QSPI_DELAY				0xc
+#define CAD_QSPI_DELAY_CSSOT(x)			(((x) & 0xff) << 0)
+#define CAD_QSPI_DELAY_CSEOT(x)			(((x) & 0xff) << 8)
+#define CAD_QSPI_DELAY_CSDADS(x)		(((x) & 0xff) << 16)
+#define CAD_QSPI_DELAY_CSDA(x)			(((x) & 0xff) << 24)
+
+#define CAD_QSPI_DEVSZ				0x14
+#define CAD_QSPI_DEVSZ_ADDR_BYTES(x)		((x) << 0)
+#define CAD_QSPI_DEVSZ_BYTES_PER_PAGE(x)	((x) << 4)
+#define CAD_QSPI_DEVSZ_BYTES_PER_BLOCK(x)	((x) << 16)
+
+#define CAD_QSPI_DEVWR				0x8
+#define CAD_QSPI_DEVRD				0x4
+#define CAD_QSPI_DEV_OPCODE(x)			(((x) & 0xff) << 0)
+#define CAD_QSPI_DEV_INST_TYPE(x)		(((x) & 0x03) << 8)
+#define CAD_QSPI_DEV_ADDR_TYPE(x)		(((x) & 0x03) << 12)
+#define CAD_QSPI_DEV_DATA_TYPE(x)		(((x) & 0x03) << 16)
+#define CAD_QSPI_DEV_MODE_BIT(x)		(((x) & 0x01) << 20)
+#define CAD_QSPI_DEV_DUMMY_CLK_CYCLE(x)		(((x) & 0x0f) << 24)
+
+#define CAD_QSPI_FLASHCMD			0x90
+#define CAD_QSPI_FLASHCMD_ADDR			0x94
+#define CAD_QSPI_FLASHCMD_EXECUTE		0x1
+#define CAD_QSPI_FLASHCMD_EXECUTE_STAT		0x2
+#define CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX	5
+#define CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES(x)	(((x) << 7) & 0x000f80)
+#define CAD_QSPI_FLASHCMD_OPCODE(x)		(((x) & 0xff) << 24)
+#define CAD_QSPI_FLASHCMD_ENRDDATA(x)		(((x) & 1) << 23)
+#define CAD_QSPI_FLASHCMD_NUMRDDATABYTES(x)	(((x) & 0xf) << 20)
+#define CAD_QSPI_FLASHCMD_ENCMDADDR(x)		(((x) & 1) << 19)
+#define CAD_QSPI_FLASHCMD_ENMODEBIT(x)		(((x) & 1) << 18)
+#define CAD_QSPI_FLASHCMD_NUMADDRBYTES(x)	(((x) & 0x3) << 16)
+#define CAD_QSPI_FLASHCMD_ENWRDATA(x)		(((x) & 1) << 15)
+#define CAD_QSPI_FLASHCMD_NUMWRDATABYTES(x)	(((x) & 0x7) << 12)
+#define CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(x)	(((x) & 0x1f) << 7)
+#define CAD_QSPI_FLASHCMD_RDDATA0		0xa0
+#define CAD_QSPI_FLASHCMD_RDDATA1		0xa4
+#define CAD_QSPI_FLASHCMD_WRDATA0		0xa8
+#define CAD_QSPI_FLASHCMD_WRDATA1		0xac
+
+#define CAD_QSPI_RDDATACAP			0x10
+#define CAD_QSPI_RDDATACAP_BYP(x)		(((x) & 1) << 0)
+#define CAD_QSPI_RDDATACAP_DELAY(x)		(((x) & 0xf) << 1)
+
+#define CAD_QSPI_REMAPADDR			0x24
+#define CAD_QSPI_REMAPADDR_VALUE_SET(x)		(((x) & 0xffffffff) << 0)
+
+#define CAD_QSPI_SRAMPART			0x18
+#define CAD_QSPI_SRAMFILL			0x2c
+#define CAD_QSPI_SRAMPART_ADDR(x)		(((x) >> 0) & 0x3ff)
+#define CAD_QSPI_SRAM_FIFO_ENTRY_COUNT		(512 / sizeof(uint32_t))
+#define CAD_QSPI_SRAMFILL_INDWRPART(x)		(((x) >> 16) & 0x00ffff)
+#define CAD_QSPI_SRAMFILL_INDRDPART(x)		(((x) >> 0) & 0x00ffff)
+
+#define CAD_QSPI_SELCLKPHASE(x)			(((x) & 1) << 2)
+#define CAD_QSPI_SELCLKPOL(x)			(((x) & 1) << 1)
+
+#define CAD_QSPI_STIG_FLAGSR_PROGRAMREADY(x)	(((x) >> 7) & 1)
+#define CAD_QSPI_STIG_FLAGSR_ERASEREADY(x)	(((x) >> 7) & 1)
+#define CAD_QSPI_STIG_FLAGSR_ERASEERROR(x)	(((x) >> 5) & 1)
+#define CAD_QSPI_STIG_FLAGSR_PROGRAMERROR(x)	(((x) >> 4) & 1)
+#define CAD_QSPI_STIG_OPCODE_CLFSR		0x50
+#define CAD_QSPI_STIG_OPCODE_RDID		0x9f
+#define CAD_QSPI_STIG_OPCODE_WRDIS		0x4
+#define CAD_QSPI_STIG_OPCODE_WREN		0x6
+#define CAD_QSPI_STIG_OPCODE_SUBSEC_ERASE	0x20
+#define CAD_QSPI_STIG_OPCODE_SEC_ERASE		0xd8
+#define CAD_QSPI_STIG_OPCODE_WREN_EXT_REG	0xc5
+#define CAD_QSPI_STIG_OPCODE_DIE_ERASE		0xc4
+#define CAD_QSPI_STIG_OPCODE_BULK_ERASE		0xc7
+#define CAD_QSPI_STIG_OPCODE_RDSR		0x5
+#define CAD_QSPI_STIG_OPCODE_RDFLGSR		0x70
+#define CAD_QSPI_STIG_OPCODE_RESET_EN		0x66
+#define CAD_QSPI_STIG_OPCODE_RESET_MEM		0x99
+#define CAD_QSPI_STIG_RDID_CAPACITYID(x)	(((x) >> 16) & 0xff)
+#define CAD_QSPI_STIG_SR_BUSY(x)		(((x) >> 0) & 1)
+
+
+#define CAD_QSPI_INST_SINGLE			0
+#define CAD_QSPI_INST_DUAL			1
+#define CAD_QSPI_INST_QUAD			2
+
+#define CAD_QSPI_INDRDSTADDR			0x68
+#define CAD_QSPI_INDRDCNT			0x6c
+#define CAD_QSPI_INDRD				0x60
+#define CAD_QSPI_INDRD_RD_STAT(x)		(((x) >> 2) & 1)
+#define CAD_QSPI_INDRD_START			1
+#define CAD_QSPI_INDRD_IND_OPS_DONE		0x20
+
+#define CAD_QSPI_INDWR				0x70
+#define CAD_QSPI_INDWR_RDSTAT(x)		(((x) >> 2) & 1)
+#define CAD_QSPI_INDWRSTADDR			0x78
+#define CAD_QSPI_INDWRCNT			0x7c
+#define CAD_QSPI_INDWR				0x70
+#define CAD_QSPI_INDWR_START			0x1
+#define CAD_QSPI_INDWR_INDDONE			0x20
+
+#define CAD_QSPI_INT_STATUS_ALL			0x0000ffff
+
+#define CAD_QSPI_N25Q_DIE_SIZE			0x02000000
+#define CAD_QSPI_BANK_SIZE			0x01000000
+#define CAD_QSPI_PAGE_SIZE			0x00000100
+
+#define CAD_QSPI_IRQMSK				0x44
+
+#define CAD_QSPI_SUBSECTOR_SIZE			0x1000
+
+#define S10_QSPI_ADDR_BYTES			2
+#define S10_QSPI_BYTES_PER_DEV			256
+#define S10_BYTES_PER_BLOCK			16
+
+#define QSPI_FAST_READ				0xb
+
+// QSPI CONFIGURATIONS
+
+#define QSPI_CONFIG_CPOL			1
+#define QSPI_CONFIG_CPHA			1
+
+#define QSPI_CONFIG_CSSOT			0x14
+#define QSPI_CONFIG_CSEOT			0x14
+#define QSPI_CONFIG_CSDADS			0xff
+#define QSPI_CONFIG_CSDA			0xc8
+
+int cad_qspi_init(uint32_t desired_clk_freq, uint32_t clk_phase,
+	uint32_t clk_pol, uint32_t csda, uint32_t csdads,
+	uint32_t cseot, uint32_t cssot, uint32_t rddatacap);
+void cad_qspi_set_chip_select(int cs);
+int cad_qspi_erase(uint32_t offset, uint32_t size);
+int cad_qspi_write(void *buffer, uint32_t offset, uint32_t size);
+int cad_qspi_read(void *buffer, uint32_t offset, uint32_t size);
+int cad_qspi_update(void *buffer, uint32_t offset, uint32_t size);
+
+#endif
+
diff --git a/plat/intel/soc/stratix10/plat_storage.c b/plat/intel/soc/stratix10/plat_storage.c
index cedcf1e..f5fd871 100644
--- a/plat/intel/soc/stratix10/plat_storage.c
+++ b/plat/intel/soc/stratix10/plat_storage.c
@@ -21,17 +21,21 @@
 #include <lib/utils.h>
 #include <common/tbbr/tbbr_img_def.h>
 #include "platform_def.h"
+#include "aarch64/stratix10_private.h"
 
-#define STRATIX10_FIP_BASE	(0)
-#define STRATIX10_FIP_MAX_SIZE	(0x1000000)
-#define STRATIX10_MMC_DATA_BASE	(0xffe3c000)
-#define STRATIX10_MMC_DATA_SIZE	(0x2000)
+#define STRATIX10_FIP_BASE		(0)
+#define STRATIX10_FIP_MAX_SIZE		(0x1000000)
+#define STRATIX10_MMC_DATA_BASE		(0xffe3c000)
+#define STRATIX10_MMC_DATA_SIZE		(0x2000)
+#define STRATIX10_QSPI_DATA_BASE	(0x3C00000)
+#define STRATIX10_QSPI_DATA_SIZE	(0x1000000)
 
-static const io_dev_connector_t *mmc_dev_con;
+
 static const io_dev_connector_t *fip_dev_con;
+static const io_dev_connector_t *boot_dev_con;
 
 static uintptr_t fip_dev_handle;
-static uintptr_t mmc_dev_handle;
+static uintptr_t boot_dev_handle;
 
 static const io_uuid_spec_t bl2_uuid_spec = {
 	.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
@@ -46,47 +50,35 @@
 };
 
 uintptr_t a2_lba_offset;
+const char a2[] = {0xa2, 0x0};
 
 static const io_block_spec_t gpt_block_spec = {
 	.offset = 0,
 	.length = MMC_BLOCK_SIZE
 };
 
-static int check_mmc(const uintptr_t spec);
 static int check_fip(const uintptr_t spec);
+static int check_dev(const uintptr_t spec);
 
-static io_block_spec_t mmc_fip_spec = {
+static io_block_dev_spec_t boot_dev_spec;
+static int (*register_io_dev)(const io_dev_connector_t **);
+
+static io_block_spec_t fip_spec = {
 	.offset		= STRATIX10_FIP_BASE,
 	.length		= STRATIX10_FIP_MAX_SIZE,
 };
 
-const char a2[] = {0xa2, 0x0};
-
-static const io_block_dev_spec_t mmc_dev_spec = {
-	.buffer	= {
-		.offset = STRATIX10_MMC_DATA_BASE,
-		.length = MMC_BLOCK_SIZE,
-	},
-
-	.ops	= {
-		.read	= mmc_read_blocks,
-		.write	= mmc_write_blocks,
-	},
-
-	.block_size = MMC_BLOCK_SIZE,
-};
-
 struct plat_io_policy {
-	uintptr_t	*dev_handle;
-	uintptr_t	image_spec;
-	int		(*check)(const uintptr_t spec);
+	uintptr_t       *dev_handle;
+	uintptr_t       image_spec;
+	int             (*check)(const uintptr_t spec);
 };
 
 static const struct plat_io_policy policies[] = {
 	[FIP_IMAGE_ID] = {
-		&mmc_dev_handle,
-		(uintptr_t)&mmc_fip_spec,
-		check_mmc
+		&boot_dev_handle,
+		(uintptr_t)&fip_spec,
+		check_dev
 	},
 	[BL2_IMAGE_ID] = {
 	  &fip_dev_handle,
@@ -104,20 +96,20 @@
 		check_fip
 	},
 	[GPT_IMAGE_ID] = {
-		&mmc_dev_handle,
+		&boot_dev_handle,
 		(uintptr_t) &gpt_block_spec,
-		check_mmc
+		check_dev
 	},
 };
 
-static int check_mmc(const uintptr_t spec)
+static int check_dev(const uintptr_t spec)
 {
 	int result;
 	uintptr_t local_handle;
 
-	result = io_dev_init(mmc_dev_handle, (uintptr_t)NULL);
+	result = io_dev_init(boot_dev_handle, (uintptr_t)NULL);
 	if (result == 0) {
-		result = io_open(mmc_dev_handle, spec, &local_handle);
+		result = io_open(boot_dev_handle, spec, &local_handle);
 		if (result == 0)
 			io_close(local_handle);
 	}
@@ -138,26 +130,48 @@
 	return result;
 }
 
-void stratix10_io_setup(void)
+void stratix10_io_setup(int boot_source)
 {
 	int result;
 
+	switch (boot_source) {
+	case BOOT_SOURCE_SDMMC:
+		register_io_dev = &register_io_dev_block;
+		boot_dev_spec.buffer.offset	= STRATIX10_MMC_DATA_BASE;
+		boot_dev_spec.buffer.length	= MMC_BLOCK_SIZE;
+		boot_dev_spec.ops.read		= mmc_read_blocks;
+		boot_dev_spec.ops.write		= mmc_write_blocks;
+		boot_dev_spec.block_size	= MMC_BLOCK_SIZE;
+		break;
+
+	case BOOT_SOURCE_QSPI:
+		register_io_dev = &register_io_dev_memmap;
+		fip_spec.offset = fip_spec.offset + STRATIX10_QSPI_DATA_BASE;
+		break;
+
-	result = register_io_dev_block(&mmc_dev_con);
+	default:
+		ERROR("Unsupported boot source\n");
+		panic();
+		break;
+	}
+
+	result = (*register_io_dev)(&boot_dev_con);
 	assert(result == 0);
 
 	result = register_io_dev_fip(&fip_dev_con);
 	assert(result == 0);
 
-	result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_dev_spec,
-			&mmc_dev_handle);
+	result = io_dev_open(boot_dev_con, (uintptr_t)&boot_dev_spec,
+			&boot_dev_handle);
 	assert(result == 0);
 
 	result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle);
 	assert(result == 0);
 
-	partition_init(GPT_IMAGE_ID);
-
-	mmc_fip_spec.offset = get_partition_entry(a2)->start;
+	if (boot_source == BOOT_SOURCE_SDMMC) {
+		partition_init(GPT_IMAGE_ID);
+		fip_spec.offset = get_partition_entry(a2)->start;
+	}
 
 	(void)result;
 }
diff --git a/plat/intel/soc/stratix10/platform.mk b/plat/intel/soc/stratix10/platform.mk
index debdea1..1f06fbd 100644
--- a/plat/intel/soc/stratix10/platform.mk
+++ b/plat/intel/soc/stratix10/platform.mk
@@ -31,7 +31,7 @@
 		drivers/io/io_block.c					\
 		drivers/io/io_fip.c					\
 		drivers/gpio/gpio.c					\
-		drivers/io/io_memmap.c					\
+		drivers/intel/soc/stratix10/io/s10_memmap_qspi.c	\
 		plat/intel/soc/stratix10/bl2_plat_setup.c		\
 		plat/intel/soc/stratix10/plat_storage.c			\
                 plat/intel/soc/stratix10/bl2_plat_mem_params_desc.c	\
@@ -44,7 +44,9 @@
 		lib/cpus/aarch64/cortex_a53.S				\
 		plat/intel/soc/stratix10/stratix10_image_load.c		\
 		plat/intel/soc/stratix10/soc/s10_system_manager.c	\
-                common/desc_image_load.c
+		common/desc_image_load.c				\
+		plat/intel/soc/stratix10/soc/s10_mailbox.c		\
+		plat/intel/soc/stratix10/drivers/qspi/cadence_qspi.c
 
 BL31_SOURCES	+=	drivers/arm/cci/cci.c				\
 		lib/cpus/aarch64/cortex_a53.S				\
diff --git a/plat/intel/soc/stratix10/soc/s10_memory_controller.c b/plat/intel/soc/stratix10/soc/s10_memory_controller.c
index 851fc59..ed06f54 100644
--- a/plat/intel/soc/stratix10/soc/s10_memory_controller.c
+++ b/plat/intel/soc/stratix10/soc/s10_memory_controller.c
@@ -8,6 +8,7 @@
 #include <arch_helpers.h>
 #include <errno.h>
 #include <lib/mmio.h>
+#include <lib/utils.h>
 #include <common/debug.h>
 #include <drivers/delay_timer.h>
 #include <platform_def.h>
@@ -403,7 +404,7 @@
 		INFO("Scrubbing ECC\n");
 
 		/* ECC Scrubbing */
-		memset(DRAM_BASE, 0, DRAM_SIZE);
+		zeromem(DRAM_BASE, DRAM_SIZE);
 	} else {
 		INFO("ECC is disabled.\n");
 	}
diff --git a/plat/nvidia/tegra/common/tegra_common.mk b/plat/nvidia/tegra/common/tegra_common.mk
index d9eec4d..2a2f278 100644
--- a/plat/nvidia/tegra/common/tegra_common.mk
+++ b/plat/nvidia/tegra/common/tegra_common.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -22,6 +22,7 @@
 
 BL31_SOURCES		+=	drivers/console/aarch64/console.S		\
 				drivers/delay_timer/delay_timer.c		\
+				drivers/io/io_storage.c				\
 				${TEGRA_GICv2_SOURCES}				\
 				${COMMON_DIR}/aarch64/tegra_helpers.S		\
 				${COMMON_DIR}/drivers/pmc/pmc.c			\
@@ -29,6 +30,7 @@
 				${COMMON_DIR}/tegra_bl31_setup.c		\
 				${COMMON_DIR}/tegra_delay_timer.c		\
 				${COMMON_DIR}/tegra_fiq_glue.c			\
+				${COMMON_DIR}/tegra_io_storage.c		\
 				${COMMON_DIR}/tegra_platform.c			\
 				${COMMON_DIR}/tegra_pm.c			\
 				${COMMON_DIR}/tegra_sip_calls.c			\
diff --git a/plat/nvidia/tegra/common/tegra_io_storage.c b/plat/nvidia/tegra/common/tegra_io_storage.c
new file mode 100644
index 0000000..21641aa
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_io_storage.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2019, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <plat/common/platform.h>
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy.
+ *
+ * This function is not supported at this time
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	return -ENOTSUP;
+}
diff --git a/plat/nvidia/tegra/include/platform_def.h b/plat/nvidia/tegra/include/platform_def.h
index f68b898..eb55def 100644
--- a/plat/nvidia/tegra/include/platform_def.h
+++ b/plat/nvidia/tegra/include/platform_def.h
@@ -66,4 +66,10 @@
 #define CACHE_WRITEBACK_SHIFT		6
 #define CACHE_WRITEBACK_GRANULE		(0x40) /* (U(1) << CACHE_WRITEBACK_SHIFT) */
 
+/*******************************************************************************
+ * Dummy macros to compile io_storage support
+ ******************************************************************************/
+#define MAX_IO_DEVICES			U(0)
+#define MAX_IO_HANDLES			U(0)
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/nvidia/tegra/platform.mk b/plat/nvidia/tegra/platform.mk
index 6ef1900..0917d87 100644
--- a/plat/nvidia/tegra/platform.mk
+++ b/plat/nvidia/tegra/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -59,3 +59,17 @@
 
 INCLUDES	+=	-Iinclude/lib/libc		\
 			-Iinclude/lib/libc/$(ARCH)	\
+
+ifneq ($(findstring armlink,$(notdir $(LD))),)
+# o suppress warnings for section mismatches, undefined symbols
+# o use only those libraries that are specified in the input file
+#   list to resolve references
+# o create a static callgraph of functions
+# o resolve undefined symbols to el3_panic
+# o include only required sections
+TF_LDFLAGS	+= --diag_suppress=L6314,L6332 --no_scanlib --callgraph
+TF_LDFLAGS	+= --keep="*(__pubsub*)" --keep="*(rt_svc_descs*)" --keep="*(*cpu_ops)"
+ifeq (${ENABLE_PMF},1)
+TF_LDFLAGS	+= --keep="*(*pmf_svc_descs*)"
+endif
+endif
diff --git a/plat/nvidia/tegra/scat/bl31.scat b/plat/nvidia/tegra/scat/bl31.scat
new file mode 100644
index 0000000..2f5fd9e
--- /dev/null
+++ b/plat/nvidia/tegra/scat/bl31.scat
@@ -0,0 +1,284 @@
+#! armclang -E -x c
+
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#define PAGE_SIZE	(1024 * 4)
+
+LR_START BL31_BASE
+{
+	__BL31_START__ +0 FIXED EMPTY 0
+	{
+		/* placeholder */
+	}
+
+	/* BL31_BASE address must be aligned on a page boundary. */
+	ScatterAssert((ImageBase(__BL31_START__) AND 0xFFF) == 0)
+}
+
+LR_TEXT BL31_BASE
+{
+	__TEXT__ +0 FIXED
+	{
+		*(:gdef:bl31_entrypoint, +FIRST)
+		*(.text*)
+		*(.vectors)
+		.ANY1(+RO-CODE)
+	}
+
+	__TEXT_EPILOGUE__ AlignExpr(+0, PAGE_SIZE) FIXED EMPTY 0
+	{
+		/* section delimiter */
+	}
+}
+
+LR_RO_DATA +0
+{
+	__RODATA__ AlignExpr(ImageLimit(LR_TEXT), 0) FIXED
+	{
+		*(.rodata*)
+		.ANY2(+RO-DATA)
+	}
+
+	/* Ensure 8-byte alignment for descriptors and ensure inclusion */
+	__RT_SVC_DESCS__ AlignExpr(ImageLimit(__RODATA__), 8) FIXED
+	{
+		*(rt_svc_descs)
+	}
+
+#if ENABLE_PMF
+	/* Ensure 8-byte alignment for descriptors and ensure inclusion */
+	__PMF_SVC_DESCS__ AlignExpr(ImageLimit(__RT_SVC_DESCS__), 8) FIXED
+	{
+		*(pmf_svc_descs)
+	}
+#endif /* ENABLE_PMF */
+
+	/*
+	 * Ensure 8-byte alignment for cpu_ops so that its fields are also
+	 * aligned.
+	 */
+	__CPU_OPS__ AlignExpr(+0, 8) FIXED
+	{
+		*(cpu_ops)
+	}
+
+	/*
+	 * Keep the .got section in the RO section as it is patched
+	 * prior to enabling the MMU and having the .got in RO is better for
+	 * security. GOT is a table of addresses so ensure 8-byte alignment.
+	 */
+	__GOT__ AlignExpr(ImageLimit(__CPU_OPS__), 8) FIXED
+	{
+		*(.got)
+	}
+
+	/* Place pubsub sections for events */
+	__PUBSUB_EVENTS__ AlignExpr(+0, 8) EMPTY 0
+	{
+		/* placeholder */
+	}
+
+#include <lib/el3_runtime/pubsub_events.h>
+
+	__RODATA_EPILOGUE__ AlignExpr(+0, PAGE_SIZE) FIXED EMPTY 0
+	{
+		/* section delimiter */
+	}
+}
+
+	/* cpu_ops must always be defined */
+	ScatterAssert(ImageLength(__CPU_OPS__) > 0)
+
+#if ENABLE_SPM
+LR_SPM +0
+{
+	/*
+	 * Exception vectors of the SPM shim layer. They must be aligned to a 2K
+	 * address, but we need to place them in a separate page so that we can set
+	 * individual permissions to them, so the actual alignment needed is 4K.
+	 *
+	 * 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__ AlignExpr(ImageLimit(LR_RO_DATA), PAGE_SIZE) FIXED
+	{
+		*(.spm_shim_exceptions)
+	}
+
+	__SPM_SHIM_EXCEPTIONS_EPILOGUE__ AlignExpr(ImageLimit(__SPM_SHIM_EXCEPTIONS__), PAGE_SIZE) FIXED
+	{
+		/* placeholder */
+	}
+}
+#endif
+
+LR_RW_DATA +0
+{
+	__DATA__ AlignExpr(+0, 16) FIXED
+	{
+		*(.data*)
+		*(.constdata)
+		*(locale$$data)
+	}
+}
+
+LR_RELA +0
+{
+	/*
+	 * .rela.dyn needs to come after .data for the read-elf utility to parse
+	 * this section correctly. Ensure 8-byte alignment so that the fields of
+	 * RELA data structure are aligned.
+	 */
+	__RELA__ AlignExpr(ImageLimit(LR_RW_DATA), 8) FIXED
+	{
+		*(.rela.dyn)
+	}
+}
+
+#ifdef BL31_PROGBITS_LIMIT
+	/* BL31 progbits has exceeded its limit. */
+	ScatterAssert(ImageLimit(LR_RELA) <= BL31_PROGBITS_LIMIT)
+#endif
+
+LR_STACKS +0
+{
+	__STACKS__ AlignExpr(+0, 64) FIXED
+	{
+		*(tzfw_normal_stacks)
+	}
+}
+
+#define __BAKERY_LOCK_SIZE__		(ImageLimit(__BAKERY_LOCKS_EPILOGUE__) - \
+					 ImageBase(__BAKERY_LOCKS__))
+#define BAKERY_LOCK_SIZE		(__BAKERY_LOCK_SIZE__ * (PLATFORM_CORE_COUNT - 1))
+#define __PMF_TIMESTAMP_SIZE__		(ImageLimit(__PMF_TIMESTAMP__) - \
+					 ImageBase(__PMF_TIMESTAMP__))
+#define PER_CPU_TIMESTAMP_SIZE		(__PMF_TIMESTAMP_SIZE__ * (PLATFORM_CORE_COUNT - 1))
+
+LR_BSS +0
+{
+	__BSS__ AlignExpr(ImageLimit(LR_STACKS), 256) FIXED
+	{
+		*(.bss*)
+		*(COMDAT)
+	}
+
+#if !USE_COHERENT_MEM
+	/*
+	 * Bakery locks are stored in normal .bss memory
+	 *
+	 * Each lock's data is spread across multiple cache lines, one per CPU,
+	 * but multiple locks can share the same cache line.
+	 * The compiler will allocate enough memory for one CPU's bakery locks,
+	 * the remaining cache lines are allocated by the linker script
+	 */
+	__BAKERY_LOCKS__ AlignExpr(ImageLimit(__BSS__), CACHE_WRITEBACK_GRANULE) FIXED
+	{
+		*(bakery_lock)
+	}
+
+	__BAKERY_LOCKS_EPILOGUE__ AlignExpr(ImageLimit(__BAKERY_LOCKS__), CACHE_WRITEBACK_GRANULE) FIXED EMPTY 0
+	{
+		/* section delimiter */
+	}
+
+	__PER_CPU_BAKERY_LOCKS__ ImageLimit(__BAKERY_LOCKS_EPILOGUE__) FIXED FILL 0 BAKERY_LOCK_SIZE
+	{
+		/* padded memory section to store per cpu bakery locks */
+	}
+
+#ifdef PLAT_PERCPU_BAKERY_LOCK_SIZE
+	/* PLAT_PERCPU_BAKERY_LOCK_SIZE does not match bakery lock requirements */
+	ScatterAssert(__PER_CPU_BAKERY_LOCK_SIZE__ == PLAT_PERCPU_BAKERY_LOCK_SIZE)
+#endif
+#endif
+
+#if ENABLE_PMF
+	/*
+	 * Time-stamps are stored in normal .bss memory
+	 *
+	 * The compiler will allocate enough memory for one CPU's time-stamps,
+	 * the remaining memory for other CPU's is allocated by the
+	 * linker script
+	 */
+	__PMF_TIMESTAMP__ AlignExpr(+0, CACHE_WRITEBACK_GRANULE) FIXED EMPTY CACHE_WRITEBACK_GRANULE
+	{
+		/* store timestamps in this carved out memory */
+	}
+
+	__PMF_TIMESTAMP_EPILOGUE__ AlignExpr(ImageLimit(__PMF_TIMESTAMP__), CACHE_WRITEBACK_GRANULE) FIXED EMPTY 0
+	{
+		/*
+		 * placeholder to make __PMF_TIMESTAMP_START__ end on a
+		 * CACHE_WRITEBACK_GRANULE boundary
+		 */
+	}
+
+	__PER_CPU_TIMESTAMPS__ +0 FIXED FILL 0 PER_CPU_TIMESTAMP_SIZE
+	{
+		/* padded memory section to store per cpu timestamps */
+	}
+#endif /* ENABLE_PMF */
+}
+
+LR_XLAT_TABLE +0
+{
+	xlat_table +0 FIXED
+	{
+		*(xlat_table)
+	}
+}
+
+#if USE_COHERENT_MEM
+LR_COHERENT_RAM +0
+{
+	/*
+	 * The base address of the coherent memory section must be page-aligned (4K)
+	 * to guarantee that the coherent data are stored on their own pages and
+	 * are not mixed with normal data.  This is required to set up the correct
+	 * memory attributes for the coherent data page tables.
+	 */
+	__COHERENT_RAM__ AlignExpr(+0, PAGE_SIZE) FIXED
+	{
+		/*
+		 * Bakery locks are stored in coherent memory
+		 *
+		 * Each lock's data is contiguous and fully allocated by the compiler
+		 */
+		*(bakery_lock)
+		*(tzfw_coherent_mem)
+	}
+
+	__COHERENT_RAM_EPILOGUE_UNALIGNED__ +0 FIXED EMPTY 0
+	{
+		/* section delimiter */
+	}
+
+	/*
+	 * Memory page(s) mapped to this section will be marked
+	 * as device memory.  No other unexpected data must creep in.
+	 * Ensure the rest of the current memory page is unused.
+	 */
+	__COHERENT_RAM_EPILOGUE__ AlignExpr(ImageLimit(__COHERENT_RAM_START__), PAGE_SIZE) FIXED EMPTY 0
+	{
+		/* section delimiter */
+	}
+}
+#endif
+
+LR_END +0
+{
+	__BL31_END__ +0 FIXED EMPTY 0
+	{
+		/* placeholder */
+	}
+
+	/* BL31 image has exceeded its limit. */
+	ScatterAssert(ImageLimit(__BL31_END__) <= BL31_LIMIT)
+}
diff --git a/plat/renesas/rcar/bl2_plat_setup.c b/plat/renesas/rcar/bl2_plat_setup.c
index 2debbf9..350df12 100644
--- a/plat/renesas/rcar/bl2_plat_setup.c
+++ b/plat/renesas/rcar/bl2_plat_setup.c
@@ -236,7 +236,7 @@
 	product = reg & RCAR_PRODUCT_MASK;
 	cut = reg & RCAR_CUT_MASK;
 
-	if (product == RCAR_PRODUCT_M3)
+	if (product == RCAR_PRODUCT_M3 && RCAR_CUT_VER30 > cut)
 		goto tlb;
 
 	if (product == RCAR_PRODUCT_H3 && RCAR_CUT_VER20 > cut)
@@ -693,8 +693,17 @@
 		break;
 	}
 
-	if (RCAR_PRODUCT_M3_CUT11 == product_cut) {
-		NOTICE("BL2: PRR is R-Car %s Ver.1.1 / Ver.1.2\n", str);
+	if ((RCAR_PRODUCT_M3 == product) &&
+	    (RCAR_CUT_VER20 == (reg & RCAR_MAJOR_MASK))) {
+		if (RCAR_M3_CUT_VER11 == (reg & RCAR_CUT_MASK)) {
+			/* M3 Ver.1.1 or Ver.1.2 */
+			NOTICE("BL2: PRR is R-Car %s Ver.1.1 / Ver.1.2\n",
+				str);
+		} else {
+			NOTICE("BL2: PRR is R-Car %s Ver.1.%d\n",
+				str,
+				(reg & RCAR_MINOR_MASK) + RCAR_M3_MINOR_OFFSET);
+		}
 	} else {
 		major = (reg & RCAR_MAJOR_MASK) >> RCAR_MAJOR_SHIFT;
 		major = major + RCAR_MAJOR_OFFSET;
diff --git a/plat/renesas/rcar/include/rcar_def.h b/plat/renesas/rcar/include/rcar_def.h
index 3bb03f2..6bbd6fa 100644
--- a/plat/renesas/rcar/include/rcar_def.h
+++ b/plat/renesas/rcar/include/rcar_def.h
@@ -154,7 +154,7 @@
 #define RCAR_PRODUCT_M3N		U(0x00005500)
 #define RCAR_PRODUCT_E3			U(0x00005700)
 #define RCAR_CUT_VER10			U(0x00000000)
-#define RCAR_CUT_VER11			U(0x00000001)	/* H3/M3N Ver.1.1 */
+#define RCAR_CUT_VER11			U(0x00000001)	/* H3/M3N/E3 Ver.1.1 */
 #define RCAR_M3_CUT_VER11		U(0x00000010)	/* M3 Ver.1.1/Ver.1.2 */
 #define RCAR_CUT_VER20			U(0x00000010)
 #define RCAR_CUT_VER30			U(0x00000020)
@@ -164,6 +164,7 @@
 #define RCAR_MAJOR_SHIFT		U(4)
 #define RCAR_MINOR_SHIFT		U(0)
 #define RCAR_MAJOR_OFFSET		U(1)
+#define RCAR_M3_MINOR_OFFSET		U(2)
 #define RCAR_PRODUCT_H3_CUT10		(RCAR_PRODUCT_H3 | U(0x00))	/* 1.0 */
 #define RCAR_PRODUCT_H3_CUT11		(RCAR_PRODUCT_H3 | U(0x01))	/* 1.1 */
 #define RCAR_PRODUCT_H3_CUT20		(RCAR_PRODUCT_H3 | U(0x10))	/* 2.0 */
diff --git a/plat/renesas/rcar/include/rcar_version.h b/plat/renesas/rcar/include/rcar_version.h
index 5c8805c..e436324 100644
--- a/plat/renesas/rcar/include/rcar_version.h
+++ b/plat/renesas/rcar/include/rcar_version.h
@@ -9,7 +9,7 @@
 
 #include <arch_helpers.h>
 
-#define VERSION_OF_RENESAS		"2.0.0"
+#define VERSION_OF_RENESAS		"2.0.1"
 #define	VERSION_OF_RENESAS_MAXLEN	(128)
 
 extern const uint8_t version_of_renesas[VERSION_OF_RENESAS_MAXLEN];
diff --git a/plat/renesas/rcar/platform.mk b/plat/renesas/rcar/platform.mk
index 97d6ddc..715b8ae 100644
--- a/plat/renesas/rcar/platform.mk
+++ b/plat/renesas/rcar/platform.mk
@@ -38,10 +38,12 @@
 $(eval $(call add_define,RCAR_AUTO))
 RCAR_CUT_10:=0
 RCAR_CUT_11:=1
+RCAR_CUT_13:=3
 RCAR_CUT_20:=10
 RCAR_CUT_30:=20
 $(eval $(call add_define,RCAR_CUT_10))
 $(eval $(call add_define,RCAR_CUT_11))
+$(eval $(call add_define,RCAR_CUT_13))
 $(eval $(call add_define,RCAR_CUT_20))
 $(eval $(call add_define,RCAR_CUT_30))
 
@@ -98,6 +100,10 @@
         RCAR_LSI_CUT:=0
       else ifeq (${LSI_CUT},11)
         RCAR_LSI_CUT:=1
+      else ifeq (${LSI_CUT},13)
+        RCAR_LSI_CUT:=3
+      else ifeq (${LSI_CUT},30)
+        RCAR_LSI_CUT:=20
       else
         $(error "Error: ${LSI_CUT} is not supported.")
       endif
@@ -130,6 +136,8 @@
       # disable compatible function.
       ifeq (${LSI_CUT},10)
         RCAR_LSI_CUT:=0
+      else ifeq (${LSI_CUT},11)
+        RCAR_LSI_CUT:=1
       else
         $(error "Error: ${LSI_CUT} is not supported.")
       endif
diff --git a/plat/socionext/synquacer/drivers/scp/sq_scmi.c b/plat/socionext/synquacer/drivers/scp/sq_scmi.c
new file mode 100644
index 0000000..e2013cc
--- /dev/null
+++ b/plat/socionext/synquacer/drivers/scp/sq_scmi.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/css/css_mhu_doorbell.h>
+#include <drivers/arm/css/css_scp.h>
+#include <drivers/arm/css/scmi.h>
+#include <plat/arm/css/common/css_pm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include <scmi_sq.h>
+#include <sq_common.h>
+
+/*
+ * This file implements the SCP helper functions using SCMI protocol.
+ */
+
+DEFINE_BAKERY_LOCK(sq_scmi_lock);
+#define SQ_SCMI_LOCK_GET_INSTANCE	(&sq_scmi_lock)
+
+#define SQ_SCMI_PAYLOAD_BASE		PLAT_SQ_SCP_COM_SHARED_MEM_BASE
+#define MHU_CPU_INTR_S_SET_OFFSET	0x308
+
+const uint32_t sq_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = {
+	0,   1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
+	12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
+};
+
+static scmi_channel_plat_info_t sq_scmi_plat_info = {
+		.scmi_mbx_mem = SQ_SCMI_PAYLOAD_BASE,
+		.db_reg_addr = PLAT_SQ_MHU_BASE + MHU_CPU_INTR_S_SET_OFFSET,
+		.db_preserve_mask = 0xfffffffe,
+		.db_modify_mask = 0x1,
+		.ring_doorbell = &mhu_ring_doorbell,
+};
+
+/*
+ * SCMI power state parameter bit field encoding for SynQuacer platform.
+ *
+ * 31  20 19       16 15      12 11       8 7        4 3         0
+ * +-------------------------------------------------------------+
+ * | SBZ | Max level |  Level 3 |  Level 2 |  Level 1 |  Level 0 |
+ * |     |           |   state  |   state  |   state  |   state  |
+ * +-------------------------------------------------------------+
+ *
+ * `Max level` encodes the highest level that has a valid power state
+ * encoded in the power state.
+ */
+#define SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT	16
+#define SCMI_PWR_STATE_MAX_PWR_LVL_WIDTH	4
+#define SCMI_PWR_STATE_MAX_PWR_LVL_MASK		\
+				((1 << SCMI_PWR_STATE_MAX_PWR_LVL_WIDTH) - 1)
+#define SCMI_SET_PWR_STATE_MAX_PWR_LVL(_power_state, _max_level)		\
+		(_power_state) |= ((_max_level) & SCMI_PWR_STATE_MAX_PWR_LVL_MASK)\
+				<< SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT
+#define SCMI_GET_PWR_STATE_MAX_PWR_LVL(_power_state)		\
+		(((_power_state) >> SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT)	\
+				& SCMI_PWR_STATE_MAX_PWR_LVL_MASK)
+
+#define SCMI_PWR_STATE_LVL_WIDTH		4
+#define SCMI_PWR_STATE_LVL_MASK			\
+				((1 << SCMI_PWR_STATE_LVL_WIDTH) - 1)
+#define SCMI_SET_PWR_STATE_LVL(_power_state, _level, _level_state)		\
+		(_power_state) |= ((_level_state) & SCMI_PWR_STATE_LVL_MASK)	\
+				<< (SCMI_PWR_STATE_LVL_WIDTH * (_level))
+#define SCMI_GET_PWR_STATE_LVL(_power_state, _level)		\
+		(((_power_state) >> (SCMI_PWR_STATE_LVL_WIDTH * (_level))) &	\
+				SCMI_PWR_STATE_LVL_MASK)
+
+/*
+ * The SCMI power state enumeration for a power domain level
+ */
+typedef enum {
+	scmi_power_state_off = 0,
+	scmi_power_state_on = 1,
+	scmi_power_state_sleep = 2,
+} scmi_power_state_t;
+
+/*
+ * The global handle for invoking the SCMI driver APIs after the driver
+ * has been initialized.
+ */
+static void *sq_scmi_handle;
+
+/* The SCMI channel global object */
+static scmi_channel_t channel;
+
+/*
+ * Helper function to turn off a CPU power domain and
+ * its parent power domains if applicable.
+ */
+void sq_scmi_off(const struct psci_power_state *target_state)
+{
+	int lvl = 0, ret;
+	uint32_t scmi_pwr_state = 0;
+
+	/* At-least the CPU level should be specified to be OFF */
+	assert(target_state->pwr_domain_state[SQ_PWR_LVL0] ==
+							SQ_LOCAL_STATE_OFF);
+
+	for (; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
+		if (target_state->pwr_domain_state[lvl] == SQ_LOCAL_STATE_RUN)
+			break;
+
+		assert(target_state->pwr_domain_state[lvl] ==
+							SQ_LOCAL_STATE_OFF);
+		SCMI_SET_PWR_STATE_LVL(scmi_pwr_state, lvl,
+				scmi_power_state_off);
+	}
+
+	SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1);
+
+	ret = scmi_pwr_state_set(sq_scmi_handle,
+		sq_core_pos_to_scmi_dmn_id_map[plat_my_core_pos()],
+		scmi_pwr_state);
+
+	if (ret != SCMI_E_QUEUED && ret != SCMI_E_SUCCESS) {
+		ERROR("SCMI set power state command return 0x%x unexpected\n",
+				ret);
+		panic();
+	}
+}
+
+/*
+ * Helper function to turn ON a CPU power domain and
+ *its parent power domains if applicable.
+ */
+void sq_scmi_on(u_register_t mpidr)
+{
+	int lvl = 0, ret, core_pos;
+	uint32_t scmi_pwr_state = 0;
+
+	for (; lvl <= PLAT_MAX_PWR_LVL; lvl++)
+		SCMI_SET_PWR_STATE_LVL(scmi_pwr_state, lvl,
+				scmi_power_state_on);
+
+	SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1);
+
+	core_pos = plat_core_pos_by_mpidr(mpidr);
+	assert(core_pos >= 0 && core_pos < PLATFORM_CORE_COUNT);
+
+	ret = scmi_pwr_state_set(sq_scmi_handle,
+		sq_core_pos_to_scmi_dmn_id_map[core_pos],
+		scmi_pwr_state);
+
+	if (ret != SCMI_E_QUEUED && ret != SCMI_E_SUCCESS) {
+		ERROR("SCMI set power state command return 0x%x unexpected\n",
+				ret);
+		panic();
+	}
+}
+
+void __dead2 sq_scmi_system_off(int state)
+{
+	int ret;
+
+	/*
+	 * Disable GIC CPU interface to prevent pending interrupt from waking
+	 * up the AP from WFI.
+	 */
+	sq_gic_cpuif_disable();
+
+	/*
+	 * Issue SCMI command. First issue a graceful
+	 * request and if that fails force the request.
+	 */
+	ret = scmi_sys_pwr_state_set(sq_scmi_handle,
+			SCMI_SYS_PWR_FORCEFUL_REQ,
+			state);
+
+	if (ret != SCMI_E_SUCCESS) {
+		ERROR("SCMI system power state set 0x%x returns unexpected 0x%x\n",
+			state, ret);
+		panic();
+	}
+	wfi();
+	ERROR("SCMI set power state: operation not handled.\n");
+	panic();
+}
+
+/*
+ * Helper function to reset the system via SCMI.
+ */
+void __dead2 sq_scmi_sys_reboot(void)
+{
+	sq_scmi_system_off(SCMI_SYS_PWR_COLD_RESET);
+}
+
+static int scmi_ap_core_init(scmi_channel_t *ch)
+{
+#if PROGRAMMABLE_RESET_ADDRESS
+	uint32_t version;
+	int ret;
+
+	ret = scmi_proto_version(ch, SCMI_AP_CORE_PROTO_ID, &version);
+	if (ret != SCMI_E_SUCCESS) {
+		WARN("SCMI AP core protocol version message failed\n");
+		return -1;
+	}
+
+	if (!is_scmi_version_compatible(SCMI_AP_CORE_PROTO_VER, version)) {
+		WARN("SCMI AP core protocol version 0x%x incompatible with driver version 0x%x\n",
+						version, SCMI_AP_CORE_PROTO_VER);
+		return -1;
+	}
+	INFO("SCMI AP core protocol version 0x%x detected\n", version);
+#endif
+	return 0;
+}
+
+void __init plat_sq_pwrc_setup(void)
+{
+	channel.info = &sq_scmi_plat_info;
+	channel.lock = SQ_SCMI_LOCK_GET_INSTANCE;
+	sq_scmi_handle = scmi_init(&channel);
+	if (sq_scmi_handle == NULL) {
+		ERROR("SCMI Initialization failed\n");
+		panic();
+	}
+	if (scmi_ap_core_init(&channel) < 0) {
+		ERROR("SCMI AP core protocol initialization failed\n");
+		panic();
+	}
+}
+
+uint32_t sq_scmi_get_draminfo(struct draminfo *info)
+{
+	scmi_get_draminfo(sq_scmi_handle, info);
+
+	return 0;
+}
diff --git a/plat/socionext/synquacer/drivers/scp/sq_scp.c b/plat/socionext/synquacer/drivers/scp/sq_scp.c
new file mode 100644
index 0000000..e494022
--- /dev/null
+++ b/plat/socionext/synquacer/drivers/scp/sq_scp.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <sq_common.h>
+#include "sq_scpi.h"
+
+/*
+ * Helper function to get dram information from SCP.
+ */
+uint32_t sq_scp_get_draminfo(struct draminfo *info)
+{
+#if SQ_USE_SCMI_DRIVER
+	sq_scmi_get_draminfo(info);
+#else
+	scpi_get_draminfo(info);
+#endif
+	return 0;
+}
diff --git a/plat/socionext/synquacer/drivers/scpi/sq_scpi.h b/plat/socionext/synquacer/drivers/scpi/sq_scpi.h
index 38cc19e..eb6ce5c 100644
--- a/plat/socionext/synquacer/drivers/scpi/sq_scpi.h
+++ b/plat/socionext/synquacer/drivers/scpi/sq_scpi.h
@@ -78,5 +78,6 @@
 					scpi_power_state_t cluster_state,
 					scpi_power_state_t css_state);
 uint32_t scpi_sys_power_state(scpi_system_state_t system_state);
+uint32_t scpi_get_draminfo(struct draminfo *info);
 
 #endif /* SQ_SCPI_H */
diff --git a/plat/socionext/synquacer/include/platform_def.h b/plat/socionext/synquacer/include/platform_def.h
index 0cec81b..7e54b39 100644
--- a/plat/socionext/synquacer/include/platform_def.h
+++ b/plat/socionext/synquacer/include/platform_def.h
@@ -16,6 +16,16 @@
 #define PLATFORM_CORE_COUNT		(PLAT_CLUSTER_COUNT *	\
 					 PLAT_MAX_CORES_PER_CLUSTER)
 
+/* Macros to read the SQ power domain state */
+#define SQ_PWR_LVL0		MPIDR_AFFLVL0
+#define SQ_PWR_LVL1		MPIDR_AFFLVL1
+#define SQ_PWR_LVL2		MPIDR_AFFLVL2
+
+#define SQ_CORE_PWR_STATE(state)	(state)->pwr_domain_state[SQ_PWR_LVL0]
+#define SQ_CLUSTER_PWR_STATE(state)	(state)->pwr_domain_state[SQ_PWR_LVL1]
+#define SQ_SYSTEM_PWR_STATE(state)	((PLAT_MAX_PWR_LVL > SQ_PWR_LVL1) ?\
+				(state)->pwr_domain_state[SQ_PWR_LVL2] : 0)
+
 #define PLAT_MAX_PWR_LVL		U(1)
 #define PLAT_MAX_RET_STATE		U(1)
 #define PLAT_MAX_OFF_STATE		U(2)
@@ -70,6 +80,7 @@
 #define DRAMINFO_BASE			0x2E00FFC0
 
 #define PLAT_SQ_MHU_BASE		0x45000000
+#define PLAT_MHUV2_BASE			0xFFFFFFFF /* MHUV2 is not supported */
 
 #define PLAT_SQ_SCP_COM_SHARED_MEM_BASE		0x45400000
 #define SCPI_CMD_GET_DRAMINFO			0x1
diff --git a/plat/socionext/synquacer/include/sq_common.h b/plat/socionext/synquacer/include/sq_common.h
index abd9090..a985822 100644
--- a/plat/socionext/synquacer/include/sq_common.h
+++ b/plat/socionext/synquacer/include/sq_common.h
@@ -9,6 +9,7 @@
 
 #include <stdint.h>
 
+#include <lib/psci/psci.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 
 struct draminfo {
@@ -22,7 +23,7 @@
 	uint64_t	size3;
 };
 
-uint32_t scpi_get_draminfo(struct draminfo *info);
+uint32_t sq_scp_get_draminfo(struct draminfo *info);
 
 void plat_sq_pwrc_setup(void);
 
@@ -41,4 +42,12 @@
 void sq_mmap_setup(uintptr_t total_base, size_t total_size,
 		   const struct mmap_region *mmap);
 
+/* SCMI API for power management by SCP */
+void sq_scmi_off(const struct psci_power_state *target_state);
+void sq_scmi_on(u_register_t mpidr);
+void __dead2 sq_scmi_sys_reboot(void);
+void __dead2 sq_scmi_system_off(int state);
+/* SCMI API for vendor specific protocol */
+uint32_t sq_scmi_get_draminfo(struct draminfo *info);
+
 #endif /* SQ_COMMON_H */
diff --git a/plat/socionext/synquacer/platform.mk b/plat/socionext/synquacer/platform.mk
index 53c39a0..f5e72cb 100644
--- a/plat/socionext/synquacer/platform.mk
+++ b/plat/socionext/synquacer/platform.mk
@@ -10,9 +10,10 @@
 override USE_COHERENT_MEM		:= 1
 override SEPARATE_CODE_AND_RODATA	:= 1
 override ENABLE_SVE_FOR_NS		:= 0
-
 # Enable workarounds for selected Cortex-A53 erratas.
 ERRATA_A53_855873		:= 1
+# Enable SCMI support
+SQ_USE_SCMI_DRIVER		?= 0
 
 # Libraries
 include lib/xlat_tables_v2/xlat_tables.mk
@@ -20,7 +21,9 @@
 PLAT_PATH		:=	plat/socionext/synquacer
 PLAT_INCLUDES		:=	-I$(PLAT_PATH)/include		\
 				-I$(PLAT_PATH)/drivers/scpi	\
-				-I$(PLAT_PATH)/drivers/mhu
+				-I$(PLAT_PATH)/drivers/mhu \
+				-Idrivers/arm/css/scmi \
+				-Idrivers/arm/css/scmi/vendor
 
 PLAT_BL_COMMON_SOURCES	+=	$(PLAT_PATH)/sq_helpers.S		\
 				drivers/arm/pl011/aarch64/pl011_console.S \
@@ -40,12 +43,27 @@
 				$(PLAT_PATH)/sq_topology.c		\
 				$(PLAT_PATH)/sq_psci.c			\
 				$(PLAT_PATH)/sq_gicv3.c			\
-				$(PLAT_PATH)/sq_xlat_setup.c		\
-				$(PLAT_PATH)/drivers/scpi/sq_scpi.c	\
+				$(PLAT_PATH)/sq_xlat_setup.c	\
+				$(PLAT_PATH)/drivers/scp/sq_scp.c
+
+ifeq (${SQ_USE_SCMI_DRIVER},0)
+BL31_SOURCES		+=	$(PLAT_PATH)/drivers/scpi/sq_scpi.c	\
 				$(PLAT_PATH)/drivers/mhu/sq_mhu.c
+else
+BL31_SOURCES		+=	$(PLAT_PATH)/drivers/scp/sq_scmi.c		\
+				drivers/arm/css/scmi/scmi_common.c		\
+				drivers/arm/css/scmi/scmi_pwr_dmn_proto.c	\
+				drivers/arm/css/scmi/scmi_sys_pwr_proto.c	\
+				drivers/arm/css/scmi/vendor/scmi_sq.c	\
+				drivers/arm/css/mhu/css_mhu_doorbell.c
+endif
 
 ifeq (${ENABLE_SPM},1)
 $(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
 
 BL31_SOURCES		+=	$(PLAT_PATH)/sq_spm.c
 endif
+
+ifeq (${SQ_USE_SCMI_DRIVER},1)
+$(eval $(call add_define,SQ_USE_SCMI_DRIVER))
+endif
diff --git a/plat/socionext/synquacer/sq_bl31_setup.c b/plat/socionext/synquacer/sq_bl31_setup.c
index fef84ef..c78fe91 100644
--- a/plat/socionext/synquacer/sq_bl31_setup.c
+++ b/plat/socionext/synquacer/sq_bl31_setup.c
@@ -14,7 +14,6 @@
 #include <common/debug.h>
 #include <drivers/arm/pl011.h>
 #include <lib/mmio.h>
-
 #include <sq_common.h>
 
 static console_pl011_t console;
@@ -83,7 +82,7 @@
 #ifdef SPD_opteed
 	struct draminfo di = {0};
 
-	scpi_get_draminfo(&di);
+	sq_scp_get_draminfo(&di);
 
 	/*
 	 * Check if OP-TEE has been loaded in Secure RAM allocated
@@ -154,7 +153,7 @@
 {
 	struct draminfo *di = (struct draminfo *)(unsigned long)DRAMINFO_BASE;
 
-	scpi_get_draminfo(di);
+	sq_scp_get_draminfo(di);
 }
 
 void bl31_plat_arch_setup(void)
diff --git a/plat/socionext/synquacer/sq_psci.c b/plat/socionext/synquacer/sq_psci.c
index 134224d..731b19a 100644
--- a/plat/socionext/synquacer/sq_psci.c
+++ b/plat/socionext/synquacer/sq_psci.c
@@ -19,26 +19,20 @@
 #include <sq_common.h>
 #include "sq_scpi.h"
 
-/* Macros to read the SQ power domain state */
-#define SQ_PWR_LVL0	MPIDR_AFFLVL0
-#define SQ_PWR_LVL1	MPIDR_AFFLVL1
-#define SQ_PWR_LVL2	MPIDR_AFFLVL2
-
-#define SQ_CORE_PWR_STATE(state)	(state)->pwr_domain_state[SQ_PWR_LVL0]
-#define SQ_CLUSTER_PWR_STATE(state)	(state)->pwr_domain_state[SQ_PWR_LVL1]
-#define SQ_SYSTEM_PWR_STATE(state)	((PLAT_MAX_PWR_LVL > SQ_PWR_LVL1) ?\
-				(state)->pwr_domain_state[SQ_PWR_LVL2] : 0)
-
 uintptr_t sq_sec_entrypoint;
 
 int sq_pwr_domain_on(u_register_t mpidr)
 {
+#if SQ_USE_SCMI_DRIVER
+	sq_scmi_on(mpidr);
+#else
 	/*
 	 * SCP takes care of powering up parent power domains so we
 	 * only need to care about level 0
 	 */
 	scpi_set_sq_power_state(mpidr, scpi_power_on, scpi_power_on,
 				 scpi_power_on);
+#endif
 
 	return PSCI_E_SUCCESS;
 }
@@ -70,6 +64,7 @@
 	sq_gic_cpuif_enable();
 }
 
+#if !SQ_USE_SCMI_DRIVER
 static void sq_power_down_common(const psci_power_state_t *target_state)
 {
 	uint32_t cluster_state = scpi_power_on;
@@ -97,10 +92,15 @@
 				 cluster_state,
 				 system_state);
 }
+#endif
 
 void sq_pwr_domain_off(const psci_power_state_t *target_state)
 {
+#if SQ_USE_SCMI_DRIVER
+	sq_scmi_off(target_state);
+#else
 	sq_power_down_common(target_state);
+#endif
 }
 
 void __dead2 sq_system_off(void)
@@ -135,6 +135,9 @@
 
 void __dead2 sq_system_reset(void)
 {
+#if SQ_USE_SCMI_DRIVER
+	sq_scmi_sys_reboot();
+#else
 	uint32_t response;
 
 	/* Send the system reset request to the SCP */
@@ -147,6 +150,7 @@
 	wfi();
 	ERROR("SQ System Reset: operation not handled.\n");
 	panic();
+#endif
 }
 
 void sq_cpu_standby(plat_local_state_t cpu_state)
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index c8bb559..f172160 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -194,7 +194,8 @@
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
 		dmbsy();
 
-		memset(&params, 0, sizeof(struct stm32_sdmmc2_params));
+		zeromem(&device_info, sizeof(struct mmc_device_info));
+		zeromem(&params, sizeof(struct stm32_sdmmc2_params));
 
 		if (boot_context->boot_interface_selected ==
 		    BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC) {
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index f651880..e0b9816 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -356,7 +356,10 @@
  */
 enum pm_ret_status pm_set_configuration(unsigned int phys_addr)
 {
-	return PM_RET_ERROR_NOTSUPPORTED;
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD2(payload, PM_SET_CONFIGURATION, phys_addr);
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
 }
 
 /**
diff --git a/readme.rst b/readme.rst
index ae9ca80..1df8637 100644
--- a/readme.rst
+++ b/readme.rst
@@ -255,11 +255,24 @@
 
 Arm welcomes any feedback on TF-A. If you think you have found a security
 vulnerability, please report this using the process defined in the TF-A
-`Security Centre`_. For all other feedback, please use the
+`Security Center`_. For all other feedback, please use the
 `GitHub issue tracker`_.
 
 Arm licensees may contact Arm directly via their partner managers.
 
+Security advisories
+~~~~~~~~~~~~~~~~~~~
+
+-  `Security Advisory TFV-1`_
+-  `Security Advisory TFV-2`_
+-  `Security Advisory TFV-3`_
+-  `Security Advisory TFV-4`_
+-  `Security Advisory TFV-5`_
+-  `Security Advisory TFV-6`_
+-  `Security Advisory TFV-7`_
+-  `Security Advisory TFV-8`_
+
+
 --------------
 
 *Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.*
@@ -282,7 +295,7 @@
 .. _Trusty Secure OS: https://source.android.com/security/trusty
 .. _GitHub: https://www.github.com/ARM-software/arm-trusted-firmware
 .. _GitHub issue tracker: https://github.com/ARM-software/tf-issues/issues
-.. _Security Centre: https://github.com/ARM-software/arm-trusted-firmware/wiki/ARM-Trusted-Firmware-Security-Centre
+.. _Security Center: ./docs/security-center.rst
 .. _license: ./license.rst
 .. _Contributing Guidelines: ./contributing.rst
 .. _Acknowledgments: ./acknowledgements.rst
@@ -292,3 +305,11 @@
 .. _Porting Guide: ./docs/porting-guide.rst
 .. _FreeBSD: http://www.freebsd.org
 .. _SCC: http://www.simple-cc.org/
+.. _Security Advisory TFV-1: ./docs/security_advisories/security-advisory-tfv-1.rst
+.. _Security Advisory TFV-2: ./docs/security_advisories/security-advisory-tfv-2.rst
+.. _Security Advisory TFV-3: ./docs/security_advisories/security-advisory-tfv-3.rst
+.. _Security Advisory TFV-4: ./docs/security_advisories/security-advisory-tfv-4.rst
+.. _Security Advisory TFV-5: ./docs/security_advisories/security-advisory-tfv-5.rst
+.. _Security Advisory TFV-6: ./docs/security_advisories/security-advisory-tfv-6.rst
+.. _Security Advisory TFV-7: ./docs/security_advisories/security-advisory-tfv-7.rst
+.. _Security Advisory TFV-8: ./docs/security_advisories/security-advisory-tfv-8.rst
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index dfbe02c..1fc7827 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -41,7 +41,7 @@
 		 * PE implements architectural Speculation Store Bypass Safe
 		 * (SSBS) feature.
 		 */
-		ssbs = (read_id_aa64pfr0_el1() >> ID_AA64PFR1_EL1_SSBS_SHIFT) &
+		ssbs = (read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_SSBS_SHIFT) &
 			ID_AA64PFR1_EL1_SSBS_MASK;
 
 		/*
diff --git a/tools/cert_create/src/tbbr/tbb_ext.c b/tools/cert_create/src/tbbr/tbb_ext.c
index d0038a2..ee5377f 100644
--- a/tools/cert_create/src/tbbr/tbb_ext.c
+++ b/tools/cert_create/src/tbbr/tbb_ext.c
@@ -19,10 +19,6 @@
 #include "tbbr/tbb_ext.h"
 #include "tbbr/tbb_key.h"
 
-/* TODO: get these values from the command line */
-#define TRUSTED_WORLD_NVCTR_VALUE	0
-#define NORMAL_WORLD_NVCTR_VALUE	0
-
 static ext_t tbb_ext[] = {
 	[TRUSTED_FW_NVCOUNTER_EXT] = {
 		.oid = TRUSTED_FW_NVCOUNTER_OID,
diff --git a/tools/fiptool/tbbr_config.h b/tools/fiptool/tbbr_config.h
index 2d89777..1fc6cad 100644
--- a/tools/fiptool/tbbr_config.h
+++ b/tools/fiptool/tbbr_config.h
@@ -11,7 +11,6 @@
 
 #include <uuid.h>
 
-/* TODO: Update this number as required */
 #define TOC_HEADER_SERIAL_NUMBER 0x12345678
 
 typedef struct toc_entry {