Merge changes Ie5c48303,I5d363c46 into integration

* changes:
  tzc400: adjust filter flag if it is set to FILTER_BIT_ALL
  tzc400: fix logical error in FILTER_BIT definitions
diff --git a/Makefile b/Makefile
index 1501f46..f899dac 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -1018,6 +1018,7 @@
         SPM_MM \
         SPMD_SPM_AT_SEL2 \
         TRUSTED_BOARD_BOOT \
+        TRNG_SUPPORT \
         USE_COHERENT_MEM \
         USE_DEBUGFS \
         ARM_IO_IN_DTB \
diff --git a/bl31/aarch64/ea_delegate.S b/bl31/aarch64/ea_delegate.S
index 1d28d5e..f9c789f 100644
--- a/bl31/aarch64/ea_delegate.S
+++ b/bl31/aarch64/ea_delegate.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,6 +15,7 @@
 #include <context.h>
 
 	.globl	handle_lower_el_ea_esb
+	.globl  handle_lower_el_async_ea
 	.globl	enter_lower_el_sync_ea
 	.globl	enter_lower_el_async_ea
 
@@ -133,6 +134,7 @@
 	 */
 	str	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
 
+handle_lower_el_async_ea:
 	/*
 	 * Save general purpose and ARMv8.3-PAuth registers (if enabled).
 	 * If Secure Cycle Counter is not disabled in MDCR_EL3 when
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index bfe13f3..51eb2bd 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -45,8 +45,9 @@
 	 * instruction. When an error is thus synchronized, the handling is
 	 * delegated to platform EA handler.
 	 *
-	 * Without RAS_EXTENSION, this macro just saves x30, and unmasks
-	 * Asynchronous External Aborts.
+	 * Without RAS_EXTENSION, this macro synchronizes pending errors using
+         * a DSB, unmasks Asynchronous External Aborts and saves X30 before
+	 * setting the flag CTX_IS_IN_EL3.
 	 */
 	.macro check_and_unmask_ea
 #if RAS_EXTENSION
@@ -79,13 +80,89 @@
 	bl	restore_gp_pmcr_pauth_regs
 1:
 #else
+	/*
+	 * For SoCs which do not implement RAS, use DSB as a barrier to
+	 * synchronize pending external aborts.
+	 */
+	dsb	sy
+
 	/* Unmask the SError interrupt */
 	msr	daifclr, #DAIF_ABT_BIT
 
+	/* Use ISB for the above unmask operation to take effect immediately */
+	isb
+
+	/*
+	 * Refer Note 1. No need to restore X30 as both handle_sync_exception
+	 * and handle_interrupt_exception macro which follow this macro modify
+	 * X30 anyway.
+	 */
 	str	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+	mov 	x30, #1
+	str	x30, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3]
+	dmb	sy
 #endif
 	.endm
 
+#if !RAS_EXTENSION
+	/*
+	 * Note 1: The explicit DSB at the entry of various exception vectors
+	 * for handling exceptions from lower ELs can inadvertently trigger an
+	 * SError exception in EL3 due to pending asynchronous aborts in lower
+	 * ELs. This will end up being handled by serror_sp_elx which will
+	 * ultimately panic and die.
+	 * The way to workaround is to update a flag to indicate if the exception
+	 * truly came from EL3. This flag is allocated in the cpu_context
+	 * structure and located at offset "CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3"
+	 * This is not a bullet proof solution to the problem at hand because
+	 * we assume the instructions following "isb" that help to update the
+	 * flag execute without causing further exceptions.
+	 */
+
+	/* ---------------------------------------------------------------------
+	 * This macro handles Asynchronous External Aborts.
+	 * ---------------------------------------------------------------------
+	 */
+	.macro	handle_async_ea
+	/*
+	 * Use a barrier to synchronize pending external aborts.
+	 */
+	dsb	sy
+
+	/* Unmask the SError interrupt */
+	msr	daifclr, #DAIF_ABT_BIT
+
+	/* Use ISB for the above unmask operation to take effect immediately */
+	isb
+
+	/* Refer Note 1 */
+	str	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+	mov 	x30, #1
+	str	x30, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3]
+	dmb	sy
+
+	b	handle_lower_el_async_ea
+	.endm
+
+	/*
+	 * This macro checks if the exception was taken due to SError in EL3 or
+	 * because of pending asynchronous external aborts from lower EL that got
+	 * triggered due to explicit synchronization in EL3. Refer Note 1.
+	 */
+	.macro check_if_serror_from_EL3
+	/* Assumes SP_EL3 on entry */
+	str	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+	ldr	x30, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3]
+	cbnz	x30, exp_from_EL3
+
+	/* Handle asynchronous external abort from lower EL */
+	b	handle_lower_el_async_ea
+
+exp_from_EL3:
+	/* Jump to plat_handle_el3_ea which does not return */
+	.endm
+#endif
+
 	/* ---------------------------------------------------------------------
 	 * This macro handles Synchronous exceptions.
 	 * Only SMC exceptions are supported.
@@ -272,6 +349,9 @@
 end_vector_entry fiq_sp_elx
 
 vector_entry serror_sp_elx
+#if !RAS_EXTENSION
+	check_if_serror_from_EL3
+#endif
 	no_ret	plat_handle_el3_ea
 end_vector_entry serror_sp_elx
 
@@ -305,8 +385,12 @@
 
 vector_entry serror_aarch64
 	apply_at_speculative_wa
+#if RAS_EXTENSION
 	msr	daifclr, #DAIF_ABT_BIT
 	b	enter_lower_el_async_ea
+#else
+	handle_async_ea
+#endif
 end_vector_entry serror_aarch64
 
 	/* ---------------------------------------------------------------------
@@ -339,8 +423,12 @@
 
 vector_entry serror_aarch32
 	apply_at_speculative_wa
+#if RAS_EXTENSION
 	msr	daifclr, #DAIF_ABT_BIT
 	b	enter_lower_el_async_ea
+#else
+	handle_async_ea
+#endif
 end_vector_entry serror_aarch32
 
 #ifdef MONITOR_TRAPS
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index e299fe1..2088533 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -68,6 +68,11 @@
 				services/std_svc/sdei/sdei_state.c
 endif
 
+ifeq (${TRNG_SUPPORT},1)
+BL31_SOURCES		+=	services/std_svc/trng/trng_main.c	\
+				services/std_svc/trng/trng_entropy_pool.c
+endif
+
 ifeq (${ENABLE_SPE_FOR_LOWER_ELS},1)
 BL31_SOURCES		+=	lib/extensions/spe/spe.c
 endif
diff --git a/bl32/sp_min/sp_min.mk b/bl32/sp_min/sp_min.mk
index afd7ae1..8b5eddd 100644
--- a/bl32/sp_min/sp_min.mk
+++ b/bl32/sp_min/sp_min.mk
@@ -37,6 +37,11 @@
 				bl32/sp_min/wa_cve_2017_5715_icache_inv.S
 endif
 
+ifeq (${TRNG_SUPPORT},1)
+BL32_SOURCES		+=	services/std_svc/trng/trng_main.c	\
+				services/std_svc/trng/trng_entropy_pool.c
+endif
+
 BL32_LINKERFILE	:=	bl32/sp_min/sp_min.ld.S
 
 # Include the platform-specific SP_MIN Makefile
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index d063ec7..be3f0bb 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -2009,6 +2009,53 @@
 
 The default implementation only prints out a warning message.
 
+.. _porting_guide_trng_requirements:
+
+TRNG porting requirements
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The |TRNG| backend requires the platform to provide the following values
+and mandatory functions.
+
+Values
+......
+
+value: uuid_t plat_trng_uuid [mandatory]
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This value must be defined to the UUID of the TRNG backend that is specific to
+the hardware after ``plat_trng_setup`` function is called. This value must
+conform to the SMCCC calling convention; The most significant 32 bits of the
+UUID must not equal ``0xffffffff`` or the signed integer ``-1`` as this value in
+w0 indicates failure to get a TRNG source.
+
+Functions
+.........
+
+Function: void plat_entropy_setup(void) [mandatory]
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+::
+
+  Argument: none
+  Return: none
+
+This function is expected to do platform-specific initialization of any TRNG
+hardware. This may include generating a UUID from a hardware-specific seed.
+
+Function: bool plat_get_entropy(uint64_t \*out) [mandatory]
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+::
+
+  Argument: uint64_t *
+  Return: bool
+  Out : when the return value is true, the entropy has been written into the
+  storage pointed to
+
+This function writes entropy into storage provided by the caller. If no entropy
+is available, it must return false and the storage must not be written.
+
 Power State Coordination Interface (in BL31)
 --------------------------------------------
 
@@ -2941,7 +2988,7 @@
 
 --------------
 
-*Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.*
 
 .. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf
 .. _Arm Generic Interrupt Controller version 2.0 (GICv2): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0048b/index.html
diff --git a/docs/global_substitutions.txt b/docs/global_substitutions.txt
index d33155b..24ac830 100644
--- a/docs/global_substitutions.txt
+++ b/docs/global_substitutions.txt
@@ -56,6 +56,7 @@
 .. |TF-M| replace:: :term:`TF-M`
 .. |TLB| replace:: :term:`TLB`
 .. |TLK| replace:: :term:`TLK`
+.. |TRNG| replace:: :term:`TRNG`
 .. |TSP| replace:: :term:`TSP`
 .. |TZC| replace:: :term:`TZC`
 .. |UBSAN| replace:: :term:`UBSAN`
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 08add3a..54820e4 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -193,6 +193,9 @@
    TLK
       Trusted Little Kernel. A Trusted OS from NVIDIA.
 
+   TRNG
+      True Randon Number Generator (hardware based)
+
    TSP
       Test Secure Payload
 
diff --git a/docs/plat/arm/fvp/index.rst b/docs/plat/arm/fvp/index.rst
index ea72962..235b7b6 100644
--- a/docs/plat/arm/fvp/index.rst
+++ b/docs/plat/arm/fvp/index.rst
@@ -142,6 +142,11 @@
    HW_CONFIG blob instead of the DTS file. This option is useful to override
    the default HW_CONFIG selected by the build system.
 
+-  ``FVP_GICR_REGION_PROTECTION``: Mark the redistributor pages of
+   inactive/fused CPU cores as read-only. The default value of this option
+   is ``0``, which means the redistributor pages of all CPU cores are marked
+   as read and write.
+
 Booting Firmware Update images
 ------------------------------
 
diff --git a/docs/plat/marvell/armada/build.rst b/docs/plat/marvell/armada/build.rst
index 29fe4d4..e55ce3c 100644
--- a/docs/plat/marvell/armada/build.rst
+++ b/docs/plat/marvell/armada/build.rst
@@ -51,6 +51,18 @@
 
 There are several build options:
 
+- PLAT
+
+        Supported Marvell platforms are:
+
+            - a3700        - A3720 DB, EspressoBin and Turris MOX
+            - a70x0
+            - a70x0_amc    - AMC board
+            - a80x0
+            - a80x0_mcbin  - MacchiatoBin
+            - a80x0_puzzle - IEI Puzzle-M801
+            - t9130        - CN913x
+
 - DEBUG
 
         Default is without debug information (=0). in order to enable it use ``DEBUG=1``.
@@ -123,6 +135,9 @@
 
         For the mv_ddr source location, check the section "Tools and external components installation"
 
+        If MV_DDR_PATH source code is a git snapshot then provide path to the full git
+        repository (including .git subdir) because mv_ddr build process calls git commands.
+
 - CP_NUM
 
         Total amount of CPs (South Bridge) connected to AP. When the parameter is omitted,
@@ -136,15 +151,15 @@
         For Armada37x0 only, the DDR topology map index/name, default is 0.
 
         Supported Options:
-            -    0 - DDR3 1CS: DB-88F3720-DDR3-Modular (512MB); EspressoBIN (512MB)
-            -    1 - DDR4 1CS: DB-88F3720-DDR4-Modular (512MB)
-            -    2 - DDR3 2CS: EspressoBIN V3-V5 (1GB 2CS)
-            -    3 - DDR4 2CS: DB-88F3720-DDR4-Modular (4GB)
-            -    4 - DDR3 1CS: DB-88F3720-DDR3-Modular (1GB); EspressoBIN V3-V5 (1GB 1CS)
-            -    5 - DDR4 1CS: EspressoBin V7 (1GB)
-            -    6 - DDR4 2CS: EspressoBin V7 (2GB)
-            -    7 - DDR3 2CS: EspressoBin V3-V5 (2GB)
-            - CUST - CUSTOMER: Customer board, DDR3 1CS 512MB
+            -    0 - DDR3 1CS 512MB (DB-88F3720-DDR3-Modular, EspressoBin V3-V5)
+            -    1 - DDR4 1CS 512MB (DB-88F3720-DDR4-Modular)
+            -    2 - DDR3 2CS   1GB (EspressoBin V3-V5)
+            -    3 - DDR4 2CS   4GB (DB-88F3720-DDR4-Modular)
+            -    4 - DDR3 1CS   1GB (DB-88F3720-DDR3-Modular, EspressoBin V3-V5)
+            -    5 - DDR4 1CS   1GB (EspressoBin V7, EspressoBin-Ultra)
+            -    6 - DDR4 2CS   2GB (EspressoBin V7)
+            -    7 - DDR3 2CS   2GB (EspressoBin V3-V5)
+            - CUST - CUSTOMER BOARD (Customer board settings)
 
 - CLOCKSPRESET
 
@@ -156,6 +171,13 @@
             - CPU_1000_DDR_800 - CPU at 1000 MHz, DDR at 800 MHz
             - CPU_1200_DDR_750 - CPU at 1200 MHz, DDR at 750 MHz
 
+        Look at Armada37x0 chip package marking on board to identify correct CPU frequency.
+        The last line on package marking (next line after the 88F37x0 line) should contain:
+
+            - C080 or I080 - chip with  800 MHz CPU - use ``CLOCKSPRESET=CPU_800_DDR_800``
+            - C100 or I100 - chip with 1000 MHz CPU - use ``CLOCKSPRESET=CPU_1000_DDR_800``
+            - C120         - chip with 1200 MHz CPU - use ``CLOCKSPRESET=CPU_1200_DDR_750``
+
 - BOOTDEV
 
         For Armada37x0 only, the flash boot device, default is ``SPINOR``.
@@ -171,6 +193,10 @@
 
             - SATA - SATA device boot
 
+                Image needs to be stored at disk LBA 0 or at disk partition with
+                MBR type 0x4d (ASCII 'M' as in Marvell) or at disk partition with
+                GPT name ``MARVELL BOOT PARTITION``.
+
 - PARTNUM
 
         For Armada37x0 only, the boot partition number, default is 0.
@@ -182,22 +208,43 @@
 
 - WTMI_IMG
 
-        For Armada37x0 only, the path of the WTMI image can point to an image which
+        For Armada37x0 only, the path of the binary can point to an image which
         does nothing, an image which supports EFUSE or a customized CM3 firmware
-        binary. The default image is wtmi.bin that built from sources in WTP
+        binary. The default image is ``fuse.bin`` that built from sources in WTP
         folder, which is the next option. If the default image is OK, then this
         option should be skipped.
 
+        Please note that this is not a full WTMI image, just a main loop without
+        hardware initialization code. Final WTMI image is built from this WTMI_IMG
+        binary and sys-init code from the WTP directory which sets DDR and CPU
+        clocks according to DDR_TOPOLOGY and CLOCKSPRESET options.
+
 - WTP
 
         For Armada37x0 only, use this parameter to point to wtptools source code
         directory, which can be found as a3700_utils.zip in the release. Usage
         example: ``WTP=/path/to/a3700_utils``
 
+        If WTP source code is a git snapshot then provide path to the full git
+        repository (including .git subdir) because WTP build process calls git commands.
+
 - CRYPTOPP_PATH
 
-        For Armada37x0 only, use this parameter tp point to Crypto++ source code
-        directory, which is required for building WTP image tool.
+        For Armada37x0 only, use this parameter to point to Crypto++ source code
+        directory. If this option is specified then Crypto++ source code in
+        CRYPTOPP_PATH directory will be automatically compiled. Crypto++ library
+        is required for building WTP image tool. Either CRYPTOPP_PATH or
+        CRYPTOPP_LIBDIR with CRYPTOPP_INCDIR needs to be specified for Armada37x0.
+
+- CRYPTOPP_LIBDIR
+
+        For Armada37x0 only, use this parameter to point to the directory with
+        compiled Crypto++ library. By default it points to the CRYPTOPP_PATH.
+
+- CRYPTOPP_INCDIR
+
+        For Armada37x0 only, use this parameter to point to the directory with
+        header files of Crypto++ library. By default it points to the CRYPTOPP_PATH.
 
 
 For example, in order to build the image in debug mode with log level up to 'notice' level run
@@ -217,7 +264,7 @@
         MARVELL_SECURE_BOOT=0 DDR_TOPOLOGY=3 BOOTDEV=SPINOR PARTNUM=0 PLAT=a3700 \
         MV_DDR_PATH=/path/to/mv-ddr-marvell/ WTP=/path/to/A3700-utils-marvell/ \
         CRYPTOPP_PATH=/path/to/cryptopp/ BL33=/path/to/u-boot.bin \
-        all fip mrvl_bootimage mrvl_flash
+        all fip mrvl_bootimage mrvl_flash mrvl_uart
 
 To build just TF-A without WTMI image (useful for A3720 Turris MOX board), run following command:
 
@@ -226,24 +273,24 @@
     > make USE_COHERENT_MEM=0 PLAT=a3700 CM3_SYSTEM_RESET=1 BL33=/path/to/u-boot.bin \
         CROSS_COMPILE=aarch64-linux-gnu- mrvl_bootimage
 
-You can build TF-A for the Globalscale ESPRESSObin-Ultra board (DDR4, 1 GB) by running the following command:
+Here is full example how to build production release of Marvell firmware image (concatenated
+binary of Marvell secure firmware, TF-A and U-Boot) for EspressoBin board (PLAT=a3700) with
+1GHz CPU (CLOCKSPRESET=CPU_1000_DDR_800) and 1GB DDR4 RAM (DDR_TOPOLOGY=5):
 
 .. code:: shell
 
-    > make DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 CLOCKSPRESET=CPU_1200_DDR_750 \
-        MARVELL_SECURE_BOOT=0 DDR_TOPOLOGY=5 BOOTDEV=SPINOR PARTNUM=0 PLAT=a3700 \
-        MV_DDR_PATH=/path/to/mv-ddr-marvell/ WTP=/path/to/A3700-utils-marvell/ \
-        CRYPTOPP_PATH=/path/to/cryptopp/ BL33=/path/to/u-boot.bin \
-        all fip mrvl_bootimage mrvl_flash
+    > git clone https://review.trustedfirmware.org/TF-A/trusted-firmware-a
+    > git clone https://gitlab.denx.de/u-boot/u-boot.git
+    > git clone https://github.com/weidai11/cryptopp.git
+    > git clone https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git -b master
+    > git clone https://github.com/MarvellEmbeddedProcessors/A3700-utils-marvell.git -b master
+    > make -C u-boot CROSS_COMPILE=aarch64-linux-gnu- mvebu_espressobin-88f3720_defconfig u-boot.bin
+    > make -C trusted-firmware-a CROSS_COMPILE=aarch64-linux-gnu- CROSS_CM3=arm-linux-gnueabi- \
+        USE_COHERENT_MEM=0 PLAT=a3700 CLOCKSPRESET=CPU_1000_DDR_800 DDR_TOPOLOGY=5 \
+        MV_DDR_PATH=$PWD/mv-ddr-marvell/ WTP=$PWD/A3700-utils-marvell/ CRYPTOPP_PATH=$PWD/cryptopp/ \
+        BL33=$PWD/u-boot/u-boot.bin mrvl_flash
 
-Supported MARVELL_PLATFORM are:
-    - a3700 (for both A3720 DB and EspressoBin)
-    - a70x0
-    - a70x0_amc (for AMC board)
-    - a80x0
-    - a80x0_mcbin (for MacchiatoBin)
-    - a80x0_puzzle (for IEI Puzzle-M801)
-    - t9130 (OcteonTX2 CN913x)
+Produced Marvell firmware flash image: ``trusted-firmware-a/build/a3700/release/flash-image.bin``
 
 Special Build Flags
 --------------------
@@ -267,20 +314,22 @@
 ------------
 Marvell's TF-A compilation generates 8 files:
 
-    - ble.bin		- BLe image
+    - ble.bin		- BLe image (not available for Armada37x0)
     - bl1.bin		- BL1 image
     - bl2.bin		- BL2 image
     - bl31.bin		- BL31 image
     - fip.bin		- FIP image (contains BL2, BL31 & BL33 (U-Boot) images)
     - boot-image.bin	- TF-A image (contains BL1 and FIP images)
-    - flash-image.bin	- Image which contains boot-image.bin and SPL image.
-      Should be placed on the boot flash/device.
+    - flash-image.bin	- Flashable Marvell firmware image. For Armada37x0 it
+      contains TIM, WTMI and boot-image.bin images. For other platforms it contains
+      BLe and boot-image.bin images. Should be placed on the boot flash/device.
     - uart-images.tgz.bin - GZIPed TAR archive which contains Armada37x0 images
       for booting via UART. Could be loaded via Marvell's WtpDownload tool from
       A3700-utils-marvell repository.
 
-Additional make target ``mrvl_bootimage`` produce ``boot-image.bin`` file and target
-``mrvl_flash`` produce final ``flash-image.bin`` and ``uart-images.tgz.bin`` files.
+Additional make target ``mrvl_bootimage`` produce ``boot-image.bin`` file. Target
+``mrvl_flash`` produce final ``flash-image.bin`` file and target ``mrvl_uart``
+produce ``uart-images.tgz.bin`` file.
 
 
 Tools and external components installation
@@ -307,12 +356,12 @@
         > export CROSS_CM3=/opt/arm-cross/bin/arm-linux-gnueabi
 
 (2) DDR initialization library sources (mv_ddr) available at the following repository
-    (use the "mv-ddr-devel" branch):
+    (use the "master" branch):
 
     https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git
 
 (3) Armada3700 tools available at the following repository
-    (use the "A3700_utils-armada-18.12-fixed" branch):
+    (use the "master" branch):
 
     https://github.com/MarvellEmbeddedProcessors/A3700-utils-marvell.git
 
@@ -324,6 +373,6 @@
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 (1) DDR initialization library sources (mv_ddr) available at the following repository
-    (use the "mv-ddr-devel" branch):
+    (use the "master" branch):
 
     https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git
diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst
index f597460..0ef2923 100644
--- a/docs/plat/stm32mp1.rst
+++ b/docs/plat/stm32mp1.rst
@@ -95,6 +95,7 @@
 ------------------
 Boot media(s) supported by BL2 must be specified in the build command.
 Available storage medias are:
+
 - ``STM32MP_SDMMC``
 - ``STM32MP_EMMC``
 - ``STM32MP_RAW_NAND``
@@ -112,6 +113,7 @@
     make DEVICE_TREE=stm32mp157c-ev1 all
 
 To build TF-A with OP-TEE support for all bootable devices:
+
 .. code:: bash
 
     make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=optee STM32MP_SDMMC=1 STM32MP_EMMC=1 STM32MP_RAW_NAND=1 STM32MP_SPI_NAND=1 STM32MP_SPI_NOR=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb
diff --git a/drivers/marvell/uart/a3700_console.S b/drivers/marvell/uart/a3700_console.S
index 58dad7a..b377321 100644
--- a/drivers/marvell/uart/a3700_console.S
+++ b/drivers/marvell/uart/a3700_console.S
@@ -60,10 +60,10 @@
 	str	w3, [x0, #UART_POSSR_REG]
 
 	/*
-	 * Wait for the TX (THR and TSR) to be empty. If wait for 20ms, the TX FIFO is
+	 * Wait for the TX (THR and TSR) to be empty. If wait for 3ms, the TX FIFO is
 	 * still not empty, TX FIFO will reset by all means.
 	 */
-	mov	w1, #20				/* max time out 20ms */
+	mov	w1, #30				/* max time out 30 * 100 us */
 2:
 	/* Check whether TX (THR and TSR) is empty */
 	ldr	w3, [x0, #UART_STATUS_REG]
@@ -72,13 +72,13 @@
 	b.ne	4f
 
 	/* Delay */
-	mov	w2, #30000
+	mov	w2, #60000	/* 60000 cycles of below 3 instructions on 1200 MHz CPU ~~ 100 us */
 3:
 	sub     w2, w2, #1
 	cmp	w2, #0
 	b.ne	3b
 
-	/* Check whether 10ms is waited */
+	/* Check whether wait timeout expired */
 	sub     w1, w1, #1
 	cmp	w1, #0
 	b.ne	2b
diff --git a/fdts/tc0.dts b/fdts/tc0.dts
index f1ade19..2d7611c 100644
--- a/fdts/tc0.dts
+++ b/fdts/tc0.dts
@@ -38,6 +38,18 @@
 				core3 {
 					cpu = <&CPU3>;
 				};
+				core4 {
+					cpu = <&CPU4>;
+				};
+				core5 {
+					cpu = <&CPU5>;
+				};
+				core6 {
+					cpu = <&CPU6>;
+				};
+				core7 {
+					cpu = <&CPU7>;
+				};
 			};
 		};
 
@@ -102,6 +114,42 @@
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 		};
 
+		CPU4:cpu@400 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x400>;
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 1>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		};
+
+		CPU5:cpu@500 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x500>;
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 1>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		};
+
+		CPU6:cpu@600 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x600>;
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 1>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		};
+
+		CPU7:cpu@700 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x700>;
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 1>;
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		};
+
 	};
 
 	memory@80000000 {
diff --git a/include/drivers/st/stm32mp1_ddr_regs.h b/include/drivers/st/stm32mp1_ddr_regs.h
index 342239a..01d6638 100644
--- a/include/drivers/st/stm32mp1_ddr_regs.h
+++ b/include/drivers/st/stm32mp1_ddr_regs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
  */
@@ -284,7 +284,7 @@
 #define DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE	BIT(3)
 #define DDRCTRL_PWRCTL_SELFREF_SW		BIT(5)
 
-#define DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK	GENMASK(19, 12)
+#define DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK	GENMASK(23, 16)
 #define DDRCTRL_PWRTMG_SELFREF_TO_X32_0		BIT(16)
 
 #define DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH	BIT(0)
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 3490414..3135fb4 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -60,7 +60,8 @@
 #define CTX_SPSR_EL3		U(0x18)
 #define CTX_ELR_EL3		U(0x20)
 #define CTX_PMCR_EL0		U(0x28)
-#define CTX_EL3STATE_END	U(0x30)
+#define CTX_IS_IN_EL3		U(0x30)
+#define CTX_EL3STATE_END	U(0x40) /* Align to the next 16 byte boundary */
 
 /*******************************************************************************
  * Constants that allow assembler code to access members of and the
diff --git a/include/lib/libc/stdlib.h b/include/lib/libc/stdlib.h
index 24e7bae..4641e56 100644
--- a/include/lib/libc/stdlib.h
+++ b/include/lib/libc/stdlib.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017 Roberto E. Vargas Caballero
+ * Copyright (c) 2012-2021 Roberto E. Vargas Caballero
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,8 +18,15 @@
 
 #define _ATEXIT_MAX 1
 
+#define isspace(x)    (((x) == ' ') || ((x) == '\r') || ((x) == '\n') || \
+			((x) == '\t') || ((x) == '\b'))
+
 extern void abort(void);
 extern int atexit(void (*func)(void));
 extern void exit(int status);
 
+long strtol(const char *nptr, char **endptr, int base);
+unsigned long strtoul(const char *nptr, char **endptr, int base);
+long long strtoll(const char *nptr, char **endptr, int base);
+unsigned long long strtoull(const char *nptr, char **endptr, int base);
 #endif /* STDLIB_H */
diff --git a/include/plat/common/plat_trng.h b/include/plat/common/plat_trng.h
new file mode 100644
index 0000000..a9f73b6
--- /dev/null
+++ b/include/plat/common/plat_trng.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_TRNG_H
+#define PLAT_TRNG_H
+
+#include <tools_share/uuid.h>
+
+/* TRNG platform functions */
+
+extern uuid_t plat_trng_uuid;
+void plat_entropy_setup(void);
+bool plat_get_entropy(uint64_t *out);
+
+#endif /* PLAT_TRNG_H */
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index ebcc855..1def86e 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +13,9 @@
 #if defined(SPD_spmd)
  #include <services/spm_core_manifest.h>
 #endif
+#if TRNG_SUPPORT
+#include "plat_trng.h"
+#endif
 
 /*******************************************************************************
  * Forward declarations
diff --git a/include/services/trng_svc.h b/include/services/trng_svc.h
new file mode 100644
index 0000000..ed4d557
--- /dev/null
+++ b/include/services/trng_svc.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TRNG_SVC_H
+#define TRNG_SVC_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <lib/smccc.h>
+
+/* SMC function IDs for TRNG queries */
+#define ARM_TRNG_VERSION	U(0x84000050)
+#define ARM_TRNG_FEATURES	U(0x84000051)
+#define ARM_TRNG_GET_UUID	U(0x84000052)
+#define ARM_TRNG_RND32		U(0x84000053)
+#define ARM_TRNG_RND64		U(0xc4000053)
+
+/* TRNG version numbers */
+#define TRNG_VERSION_MAJOR	(0x1)
+#define TRNG_VERSION_MINOR	(0x0)
+
+/* TRNG Error Numbers */
+#define TRNG_E_SUCCESS		(0)
+#define TRNG_E_NOT_SUPPORTED	(-1)
+#define TRNG_E_INVALID_PARAMS	(-2)
+#define TRNG_E_NO_ENTROPY	(-3)
+#define TRNG_E_NOT_IMPLEMENTED	(-4)
+
+#if TRNG_SUPPORT
+void trng_setup(void);
+bool is_trng_fid(uint32_t smc_fid);
+#else
+static inline void trng_setup(void)
+{
+}
+
+static inline bool is_trng_fid(uint32_t smc_fid)
+{
+	return false;
+}
+#endif
+uintptr_t trng_smc_handler(
+	uint32_t smc_fid,
+	u_register_t x1,
+	u_register_t x2,
+	u_register_t x3,
+	u_register_t x4,
+	void *cookie,
+	void *handle,
+	u_register_t flags
+);
+
+#endif /* TRNG_SVC_H */
diff --git a/lib/cpus/aarch64/rainier.S b/lib/cpus/aarch64/rainier.S
index f7afd0b..3017a50 100644
--- a/lib/cpus/aarch64/rainier.S
+++ b/lib/cpus/aarch64/rainier.S
@@ -21,10 +21,6 @@
 #error "Rainier CPU supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
-#if ERRATA_RAINIER_IC_TRAP
-	.global rainier_errata_ic_trap_handler
-#endif
-
 /* --------------------------------------------------
  * Disable speculative loads if Rainier supports
  * SSBS.
@@ -45,42 +41,6 @@
 	ret
 endfunc rainier_disable_speculative_loads
 
-/* --------------------------------------------------
- * Errata Workaround for Neoverse N1 Erratum 1542419.
- * This applies to revisions r3p0 - r4p0 of Neoverse N1
- * Since Rainier core is based on Neoverse N1 r4p0, this
- * errata applies to Rainier core r0p0
- * Inputs:
- * x0: variant[4:7] and revision[0:3] of current cpu.
- * Shall clobber: x0-x17
- * --------------------------------------------------
- */
-func errata_n1_1542419_wa
-	/* Compare x0 against revision r3p0 and r4p0 */
-	mov	x17, x30
-	bl	check_errata_1542419
-	cbz	x0, 1f
-
-        /* Apply instruction patching sequence */
-	mov	x0, xzr
-	msr	CPUPSELR_EL3, x0
-	ldr	x0, =0xEE670D35
-	msr	CPUPOR_EL3, x0
-	ldr	x0, =0xFFFF0FFF
-	msr	CPUPMR_EL3, x0
-	ldr	x0, =0x08000020007D
-	msr	CPUPCR_EL3, x0
-	isb
-1:
-	ret	x17
-endfunc errata_n1_1542419_wa
-
-func check_errata_1542419
-	/* Applies to Rainier core r0p0. */
-	mov	x1, #0x00
-	b	cpu_rev_var_ls
-endfunc check_errata_1542419
-
 func rainier_reset_func
 	mov	x19, x30
 
@@ -95,11 +55,6 @@
 	bl	cpu_get_rev_var
 	mov	x18, x0
 
-#if ERRATA_N1_1542419
-	mov	x0, x18
-	bl	errata_n1_1542419_wa
-#endif
-
 #if ENABLE_AMU
 	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
 	mrs	x0, actlr_el3
@@ -146,53 +101,11 @@
 	bl	cpu_get_rev_var
 	mov	x8, x0
 
-	/*
-	 * Report all errata. The revision-variant information is passed to
-	 * checking functions of each errata.
-	 */
-	report_errata ERRATA_N1_1542419, rainier, 1542419
-
 	ldp	x8, x30, [sp], #16
 	ret
 endfunc rainier_errata_report
 #endif
 
-/*
- * Handle trap of EL0 IC IVAU instructions to EL3 by executing a TLB
- * inner-shareable invalidation to an arbitrary address followed by a DSB.
- *
- * x1: Exception Syndrome
- */
-func rainier_errata_ic_trap_handler
-	cmp	x1, #RAINIER_EC_IC_TRAP
-	b.ne	1f
-	tlbi	vae3is, xzr
-	dsb	sy
-
-        # Skip the IC instruction itself
-        mrs     x3, elr_el3
-        add     x3, x3, #4
-        msr     elr_el3, x3
-
-	ldp	x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
-	ldp	x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
-	ldp	x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
-	ldr	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
-
-#if IMAGE_BL31 && RAS_EXTENSION
-	/*
-	 * Issue Error Synchronization Barrier to synchronize SErrors before
-	 * exiting EL3. We're running with EAs unmasked, so any synchronized
-	 * errors would be taken immediately; therefore no need to inspect
-	 * DISR_EL1 register.
-	 */
-	esb
-#endif
-	eret
-1:
-	ret
-endfunc rainier_errata_ic_trap_handler
-
 	/* ---------------------------------------------
 	 * This function provides Rainier specific
 	 * register information for crash reporting.
@@ -212,7 +125,6 @@
 	ret
 endfunc rainier_cpu_reg_dump
 
-declare_cpu_ops_eh rainier, RAINIER_MIDR, \
+declare_cpu_ops rainier, RAINIER_MIDR, \
 	rainier_reset_func, \
-	rainier_errata_ic_trap_handler, \
 	rainier_core_pwr_dwn
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 773082a..75e214d 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -995,6 +995,11 @@
  	 * ----------------------------------------------------------
 	 */
 	esb
+#else
+	dsb	sy
+#endif
+#ifdef IMAGE_BL31
+	str	xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3]
 #endif
 	exception_return
 
diff --git a/lib/libc/libc.mk b/lib/libc/libc.mk
index 93d30d0..b75d09c 100644
--- a/lib/libc/libc.mk
+++ b/lib/libc/libc.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -20,11 +20,17 @@
 			snprintf.c			\
 			strchr.c			\
 			strcmp.c			\
+			strlcat.c			\
 			strlcpy.c			\
 			strlen.c			\
 			strncmp.c			\
 			strnlen.c			\
-			strrchr.c)
+			strrchr.c			\
+			strtok.c			\
+			strtoul.c			\
+			strtoll.c			\
+			strtoull.c			\
+			strtol.c)
 
 ifeq (${ARCH},aarch64)
 LIBC_SRCS	+=	$(addprefix lib/libc/aarch64/,	\
diff --git a/lib/libc/libc_asm.mk b/lib/libc/libc_asm.mk
index 6416a3c..2f27265 100644
--- a/lib/libc/libc_asm.mk
+++ b/lib/libc/libc_asm.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2020, Arm Limited. All rights reserved.
+# Copyright (c) 2020-2021, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -19,11 +19,17 @@
 			snprintf.c			\
 			strchr.c			\
 			strcmp.c			\
+			strlcat.c			\
 			strlcpy.c			\
 			strlen.c			\
 			strncmp.c			\
 			strnlen.c			\
-			strrchr.c)
+			strrchr.c			\
+			strtok.c			\
+			strtoul.c			\
+			strtoll.c			\
+			strtoull.c			\
+			strtol.c)
 
 ifeq (${ARCH},aarch64)
 LIBC_SRCS	+=	$(addprefix lib/libc/aarch64/,	\
diff --git a/lib/libc/strtol.c b/lib/libc/strtol.c
new file mode 100644
index 0000000..deb862c
--- /dev/null
+++ b/lib/libc/strtol.c
@@ -0,0 +1,133 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+long strtol(const char *nptr, char **endptr, int base)
+{
+	const char *s;
+	unsigned long acc;
+	char c;
+	unsigned long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * Skip white space and pick up leading +/- sign if any.
+	 * If base is 0, allow 0x for hex and 0 for octal, else
+	 * assume decimal; if base is already 16, allow 0x.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (isspace((unsigned char)c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == '+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X') &&
+	    ((s[1] >= '0' && s[1] <= '9') ||
+	    (s[1] >= 'A' && s[1] <= 'F') ||
+	    (s[1] >= 'a' && s[1] <= 'f'))) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+	acc = any = 0;
+
+	/*
+	 * Compute the cutoff value between legal numbers and illegal
+	 * numbers.  That is the largest legal value, divided by the
+	 * base.  An input number that is greater than this value, if
+	 * followed by a legal input character, is too big.  One that
+	 * is equal to this value may be valid or not; the limit
+	 * between valid and invalid numbers is then based on the last
+	 * digit.  For instance, if the range for longs is
+	 * [-2147483648..2147483647] and the input base is 10,
+	 * cutoff will be set to 214748364 and cutlim to either
+	 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+	 * a value > 214748364, or equal but the next digit is > 7 (or 8),
+	 * the number is too big, and we will return a range error.
+	 *
+	 * Set 'any' if any `digits' consumed; make it negative to indicate
+	 * overflow.
+	 */
+	cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX
+	    : LONG_MAX;
+	cutlim = cutoff % base;
+	cutoff /= base;
+	for ( ; ; c = *s++) {
+		if (c >= '0' && c <= '9')
+			c -= '0';
+		else if (c >= 'A' && c <= 'Z')
+			c -= 'A' - 10;
+		else if (c >= 'a' && c <= 'z')
+			c -= 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = neg ? LONG_MIN : LONG_MAX;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (char *)(any ? s - 1 : nptr);
+	return (acc);
+}
diff --git a/lib/libc/strtoll.c b/lib/libc/strtoll.c
new file mode 100644
index 0000000..4e101e8
--- /dev/null
+++ b/lib/libc/strtoll.c
@@ -0,0 +1,134 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+/*
+ * Convert a string to a long long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+long long strtoll(const char *nptr, char **endptr, int base)
+{
+	const char *s;
+	unsigned long long acc;
+	char c;
+	unsigned long long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * Skip white space and pick up leading +/- sign if any.
+	 * If base is 0, allow 0x for hex and 0 for octal, else
+	 * assume decimal; if base is already 16, allow 0x.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (isspace((unsigned char)c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == '+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X') &&
+	    ((s[1] >= '0' && s[1] <= '9') ||
+	    (s[1] >= 'A' && s[1] <= 'F') ||
+	    (s[1] >= 'a' && s[1] <= 'f'))) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+	acc = any = 0;
+
+	/*
+	 * Compute the cutoff value between legal numbers and illegal
+	 * numbers.  That is the largest legal value, divided by the
+	 * base.  An input number that is greater than this value, if
+	 * followed by a legal input character, is too big.  One that
+	 * is equal to this value may be valid or not; the limit
+	 * between valid and invalid numbers is then based on the last
+	 * digit.  For instance, if the range for quads is
+	 * [-9223372036854775808..9223372036854775807] and the input base
+	 * is 10, cutoff will be set to 922337203685477580 and cutlim to
+	 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
+	 * accumulated a value > 922337203685477580, or equal but the
+	 * next digit is > 7 (or 8), the number is too big, and we will
+	 * return a range error.
+	 *
+	 * Set 'any' if any `digits' consumed; make it negative to indicate
+	 * overflow.
+	 */
+	cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX
+	    : LLONG_MAX;
+	cutlim = cutoff % base;
+	cutoff /= base;
+	for ( ; ; c = *s++) {
+		if (c >= '0' && c <= '9')
+			c -= '0';
+		else if (c >= 'A' && c <= 'Z')
+			c -= 'A' - 10;
+		else if (c >= 'a' && c <= 'z')
+			c -= 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = neg ? LLONG_MIN : LLONG_MAX;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (char *)(any ? s - 1 : nptr);
+	return (acc);
+}
diff --git a/lib/libc/strtoul.c b/lib/libc/strtoul.c
new file mode 100644
index 0000000..b42fb14
--- /dev/null
+++ b/lib/libc/strtoul.c
@@ -0,0 +1,112 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+/*
+ * Convert a string to an unsigned long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long strtoul(const char *nptr, char **endptr, int base)
+{
+	const char *s;
+	unsigned long acc;
+	char c;
+	unsigned long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * See strtol for comments as to the logic used.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (isspace((unsigned char)c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == '+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X') &&
+	    ((s[1] >= '0' && s[1] <= '9') ||
+	    (s[1] >= 'A' && s[1] <= 'F') ||
+	    (s[1] >= 'a' && s[1] <= 'f'))) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+	acc = any = 0;
+
+	cutoff = ULONG_MAX / base;
+	cutlim = ULONG_MAX % base;
+	for ( ; ; c = *s++) {
+		if (c >= '0' && c <= '9')
+			c -= '0';
+		else if (c >= 'A' && c <= 'Z')
+			c -= 'A' - 10;
+		else if (c >= 'a' && c <= 'z')
+			c -= 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = ULONG_MAX;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (char *)(any ? s - 1 : nptr);
+	return (acc);
+}
diff --git a/lib/libc/strtoull.c b/lib/libc/strtoull.c
new file mode 100644
index 0000000..2e65a43
--- /dev/null
+++ b/lib/libc/strtoull.c
@@ -0,0 +1,112 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+/*
+ * Convert a string to an unsigned long long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long long strtoull(const char *nptr, char **endptr, int base)
+{
+	const char *s;
+	unsigned long long acc;
+	char c;
+	unsigned long long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * See strtoq for comments as to the logic used.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (isspace((unsigned char)c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == '+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X') &&
+	    ((s[1] >= '0' && s[1] <= '9') ||
+	    (s[1] >= 'A' && s[1] <= 'F') ||
+	    (s[1] >= 'a' && s[1] <= 'f'))) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+	acc = any = 0;
+
+	cutoff = ULLONG_MAX / base;
+	cutlim = ULLONG_MAX % base;
+	for ( ; ; c = *s++) {
+		if (c >= '0' && c <= '9')
+			c -= '0';
+		else if (c >= 'A' && c <= 'Z')
+			c -= 'A' - 10;
+		else if (c >= 'a' && c <= 'z')
+			c -= 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = ULLONG_MAX;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (char *)(any ? s - 1 : nptr);
+	return (acc);
+}
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 5217a85..e94f3c3 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016-2020, ARM Limited. All rights reserved.
+# Copyright (c) 2016-2021, ARM Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -209,6 +209,9 @@
 # Software Delegated Exception support
 SDEI_SUPPORT            	:= 0
 
+# True Random Number firmware Interface
+TRNG_SUPPORT            	:= 0
+
 # Whether code and read-only data should be put on separate memory pages. The
 # platform Makefile is free to override this value.
 SEPARATE_CODE_AND_RODATA	:= 0
diff --git a/plat/allwinner/common/allwinner-common.mk b/plat/allwinner/common/allwinner-common.mk
index 901d888..bf48a70 100644
--- a/plat/allwinner/common/allwinner-common.mk
+++ b/plat/allwinner/common/allwinner-common.mk
@@ -30,7 +30,9 @@
 				plat/common/plat_psci_common.c		\
 				${AW_PLAT}/common/sunxi_bl31_setup.c	\
 				${AW_PLAT}/common/sunxi_cpu_ops.c	\
+				${AW_PLAT}/common/sunxi_native_pm.c	\
 				${AW_PLAT}/common/sunxi_pm.c		\
+				${AW_PLAT}/common/sunxi_scpi_pm.c	\
 				${AW_PLAT}/${PLAT}/sunxi_power.c	\
 				${AW_PLAT}/common/sunxi_security.c	\
 				${AW_PLAT}/common/sunxi_topology.c
diff --git a/plat/allwinner/common/include/sunxi_private.h b/plat/allwinner/common/include/sunxi_private.h
index dcf3dc9..79474e5 100644
--- a/plat/allwinner/common/include/sunxi_private.h
+++ b/plat/allwinner/common/include/sunxi_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,13 +7,19 @@
 #ifndef SUNXI_PRIVATE_H
 #define SUNXI_PRIVATE_H
 
+#include <lib/psci/psci.h>
+
 void sunxi_configure_mmu_el3(int flags);
 
 void sunxi_cpu_on(u_register_t mpidr);
-void sunxi_cpu_off(u_register_t mpidr);
-void sunxi_disable_secondary_cpus(u_register_t primary_mpidr);
+void sunxi_cpu_power_off_others(void);
+void sunxi_cpu_power_off_self(void);
 void sunxi_power_down(void);
 
+void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops);
+int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops);
+int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint);
+
 int sunxi_pmic_setup(uint16_t socid, const void *fdt);
 void sunxi_security_setup(void);
 
diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c
index 6e29b69..cbad720 100644
--- a/plat/allwinner/common/sunxi_cpu_ops.c
+++ b/plat/allwinner/common/sunxi_cpu_ops.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -45,7 +45,8 @@
 	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00);
 }
 
-void sunxi_cpu_off(u_register_t mpidr)
+/* We can't turn ourself off like this, but it works for other cores. */
+static void sunxi_cpu_off(u_register_t mpidr)
 {
 	unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
 	unsigned int core    = MPIDR_AFFLVL0_VAL(mpidr);
@@ -54,23 +55,22 @@
 
 	/* Deassert DBGPWRDUP */
 	mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
+	/* Activate the core output clamps, but not for core 0. */
+	if (core != 0)
+		mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core));
+	/* Assert CPU power-on reset */
+	mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
+	/* Remove power from the CPU */
+	sunxi_cpu_disable_power(cluster, core);
+}
 
-	/* We can't turn ourself off like this, but it works for other cores. */
-	if (read_mpidr() != mpidr) {
-		/* Activate the core output clamps, but not for core 0. */
-		if (core != 0)
-			mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster),
-					BIT(core));
-		/* Assert CPU power-on reset */
-		mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
-		/* Remove power from the CPU */
-		sunxi_cpu_disable_power(cluster, core);
-
-		return;
-	}
+void sunxi_cpu_power_off_self(void)
+{
+	u_register_t mpidr = read_mpidr();
+	unsigned int core  = MPIDR_AFFLVL0_VAL(mpidr);
 
 	/* Simplifies assembly, all SoCs so far are single cluster anyway. */
-	assert(cluster == 0);
+	assert(MPIDR_AFFLVL1_VAL(mpidr) == 0);
 
 	/*
 	 * If we are supposed to turn ourself off, tell the arisc SCP
@@ -106,8 +106,9 @@
 	mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
 }
 
-void sunxi_disable_secondary_cpus(u_register_t primary_mpidr)
+void sunxi_cpu_power_off_others(void)
 {
+	u_register_t self = read_mpidr();
 	unsigned int cluster;
 	unsigned int core;
 
@@ -116,7 +117,7 @@
 			u_register_t mpidr = (cluster << MPIDR_AFF1_SHIFT) |
 					     (core    << MPIDR_AFF0_SHIFT) |
 					     BIT(31);
-			if (mpidr != primary_mpidr)
+			if (mpidr != self)
 				sunxi_cpu_off(mpidr);
 		}
 	}
diff --git a/plat/allwinner/common/sunxi_native_pm.c b/plat/allwinner/common/sunxi_native_pm.c
new file mode 100644
index 0000000..148f50e
--- /dev/null
+++ b/plat/allwinner/common/sunxi_native_pm.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
+
+#define SUNXI_WDOG0_CTRL_REG		(SUNXI_R_WDOG_BASE + 0x0010)
+#define SUNXI_WDOG0_CFG_REG		(SUNXI_R_WDOG_BASE + 0x0014)
+#define SUNXI_WDOG0_MODE_REG		(SUNXI_R_WDOG_BASE + 0x0018)
+
+static int sunxi_pwr_domain_on(u_register_t mpidr)
+{
+	sunxi_cpu_on(mpidr);
+
+	return PSCI_E_SUCCESS;
+}
+
+static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	gicv2_cpuif_disable();
+
+	sunxi_cpu_power_off_self();
+}
+
+static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	gicv2_pcpu_distif_init();
+	gicv2_cpuif_enable();
+}
+
+static void __dead2 sunxi_system_off(void)
+{
+	gicv2_cpuif_disable();
+
+	/* Attempt to power down the board (may not return) */
+	sunxi_power_down();
+
+	/* Turn off all CPUs */
+	sunxi_cpu_power_off_others();
+	sunxi_cpu_power_off_self();
+	psci_power_down_wfi();
+}
+
+static void __dead2 sunxi_system_reset(void)
+{
+	gicv2_cpuif_disable();
+
+	/* Reset the whole system when the watchdog times out */
+	mmio_write_32(SUNXI_WDOG0_CFG_REG, 1);
+	/* Enable the watchdog with the shortest timeout (0.5 seconds) */
+	mmio_write_32(SUNXI_WDOG0_MODE_REG, (0 << 4) | 1);
+	/* Wait for twice the watchdog timeout before panicking */
+	mdelay(1000);
+
+	ERROR("PSCI: System reset failed\n");
+	panic();
+}
+
+static const plat_psci_ops_t sunxi_native_psci_ops = {
+	.pwr_domain_on			= sunxi_pwr_domain_on,
+	.pwr_domain_off			= sunxi_pwr_domain_off,
+	.pwr_domain_on_finish		= sunxi_pwr_domain_on_finish,
+	.system_off			= sunxi_system_off,
+	.system_reset			= sunxi_system_reset,
+	.validate_ns_entrypoint		= sunxi_validate_ns_entrypoint,
+};
+
+void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops)
+{
+	*psci_ops = &sunxi_native_psci_ops;
+}
diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c
index aa80c52..eb1b7e7 100644
--- a/plat/allwinner/common/sunxi_pm.c
+++ b/plat/allwinner/common/sunxi_pm.c
@@ -8,203 +8,14 @@
 
 #include <platform_def.h>
 
-#include <arch_helpers.h>
 #include <common/debug.h>
-#include <drivers/arm/css/css_scpi.h>
-#include <drivers/arm/gicv2.h>
-#include <drivers/delay_timer.h>
 #include <lib/mmio.h>
 #include <lib/psci/psci.h>
-#include <plat/common/platform.h>
 
 #include <sunxi_cpucfg.h>
-#include <sunxi_def.h>
-#include <sunxi_mmap.h>
 #include <sunxi_private.h>
 
-#define SUNXI_WDOG0_CTRL_REG		(SUNXI_R_WDOG_BASE + 0x0010)
-#define SUNXI_WDOG0_CFG_REG		(SUNXI_R_WDOG_BASE + 0x0014)
-#define SUNXI_WDOG0_MODE_REG		(SUNXI_R_WDOG_BASE + 0x0018)
-
-#define CPU_PWR_LVL			MPIDR_AFFLVL0
-#define CLUSTER_PWR_LVL			MPIDR_AFFLVL1
-#define SYSTEM_PWR_LVL			MPIDR_AFFLVL2
-
-#define CPU_PWR_STATE(state) \
-	((state)->pwr_domain_state[CPU_PWR_LVL])
-#define CLUSTER_PWR_STATE(state) \
-	((state)->pwr_domain_state[CLUSTER_PWR_LVL])
-#define SYSTEM_PWR_STATE(state) \
-	((state)->pwr_domain_state[SYSTEM_PWR_LVL])
-
-/*
- * The addresses for the SCP exception vectors are defined in the or1k
- * architecture specification.
- */
-#define OR1K_VEC_FIRST			0x01
-#define OR1K_VEC_LAST			0x0e
-#define OR1K_VEC_ADDR(n)		(0x100 * (n))
-
-/*
- * This magic value is the little-endian representation of the or1k
- * instruction "l.mfspr r2, r0, 0x12", which is guaranteed to be the
- * first instruction in the SCP firmware.
- */
-#define SCP_FIRMWARE_MAGIC		0xb4400012
-
-static bool scpi_available;
-
-static inline scpi_power_state_t scpi_map_state(plat_local_state_t psci_state)
-{
-	if (is_local_state_run(psci_state))
-		return scpi_power_on;
-	if (is_local_state_retn(psci_state))
-		return scpi_power_retention;
-	return scpi_power_off;
-}
-
-static void sunxi_cpu_standby(plat_local_state_t cpu_state)
-{
-	u_register_t scr = read_scr_el3();
-
-	assert(is_local_state_retn(cpu_state));
-
-	write_scr_el3(scr | SCR_IRQ_BIT);
-	wfi();
-	write_scr_el3(scr);
-}
-
-static int sunxi_pwr_domain_on(u_register_t mpidr)
-{
-	if (scpi_available) {
-		scpi_set_css_power_state(mpidr,
-					 scpi_power_on,
-					 scpi_power_on,
-					 scpi_power_on);
-	} else {
-		sunxi_cpu_on(mpidr);
-	}
-
-	return PSCI_E_SUCCESS;
-}
-
-static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
-{
-	plat_local_state_t cpu_pwr_state     = CPU_PWR_STATE(target_state);
-	plat_local_state_t cluster_pwr_state = CLUSTER_PWR_STATE(target_state);
-	plat_local_state_t system_pwr_state  = SYSTEM_PWR_STATE(target_state);
-
-	if (is_local_state_off(cpu_pwr_state))
-		gicv2_cpuif_disable();
-
-	if (scpi_available) {
-		scpi_set_css_power_state(read_mpidr(),
-					 scpi_map_state(cpu_pwr_state),
-					 scpi_map_state(cluster_pwr_state),
-					 scpi_map_state(system_pwr_state));
-	}
-}
-
-static void __dead2 sunxi_pwr_down_wfi(const psci_power_state_t *target_state)
-{
-	sunxi_cpu_off(read_mpidr());
-
-	while (1)
-		wfi();
-}
-
-static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
-{
-	if (is_local_state_off(SYSTEM_PWR_STATE(target_state)))
-		gicv2_distif_init();
-	if (is_local_state_off(CPU_PWR_STATE(target_state))) {
-		gicv2_pcpu_distif_init();
-		gicv2_cpuif_enable();
-	}
-}
-
-static void __dead2 sunxi_system_off(void)
-{
-	gicv2_cpuif_disable();
-
-	if (scpi_available) {
-		/* Send the power down request to the SCP */
-		uint32_t ret = scpi_sys_power_state(scpi_system_shutdown);
-
-		if (ret != SCP_OK)
-			ERROR("PSCI: SCPI %s failed: %d\n", "shutdown", ret);
-	}
-
-	/* Turn off all secondary CPUs */
-	sunxi_disable_secondary_cpus(read_mpidr());
-
-	sunxi_power_down();
-
-	udelay(1000);
-	ERROR("PSCI: Cannot turn off system, halting\n");
-	wfi();
-	panic();
-}
-
-static void __dead2 sunxi_system_reset(void)
-{
-	gicv2_cpuif_disable();
-
-	if (scpi_available) {
-		/* Send the system reset request to the SCP */
-		uint32_t ret = scpi_sys_power_state(scpi_system_reboot);
-
-		if (ret != SCP_OK)
-			ERROR("PSCI: SCPI %s failed: %d\n", "reboot", ret);
-	}
-
-	/* Reset the whole system when the watchdog times out */
-	mmio_write_32(SUNXI_WDOG0_CFG_REG, 1);
-	/* Enable the watchdog with the shortest timeout (0.5 seconds) */
-	mmio_write_32(SUNXI_WDOG0_MODE_REG, (0 << 4) | 1);
-	/* Wait for twice the watchdog timeout before panicking */
-	mdelay(1000);
-
-	ERROR("PSCI: System reset failed\n");
-	wfi();
-	panic();
-}
-
-static int sunxi_validate_power_state(unsigned int power_state,
-				      psci_power_state_t *req_state)
-{
-	unsigned int power_level = psci_get_pstate_pwrlvl(power_state);
-	unsigned int type = psci_get_pstate_type(power_state);
-
-	assert(req_state != NULL);
-
-	if (power_level > PLAT_MAX_PWR_LVL)
-		return PSCI_E_INVALID_PARAMS;
-
-	if (type == PSTATE_TYPE_STANDBY) {
-		/* Only one retention power state is supported. */
-		if (psci_get_pstate_id(power_state) > 0)
-			return PSCI_E_INVALID_PARAMS;
-		/* The SoC cannot be suspended without losing state */
-		if (power_level == SYSTEM_PWR_LVL)
-			return PSCI_E_INVALID_PARAMS;
-		for (unsigned int i = 0; i <= power_level; ++i)
-			req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE;
-	} else {
-		/* Only one off power state is supported. */
-		if (psci_get_pstate_id(power_state) > 0)
-			return PSCI_E_INVALID_PARAMS;
-		for (unsigned int i = 0; i <= power_level; ++i)
-			req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
-	}
-	/* Higher power domain levels should all remain running */
-	for (unsigned int i = power_level + 1; i <= PLAT_MAX_PWR_LVL; ++i)
-		req_state->pwr_domain_state[i] = PSCI_LOCAL_STATE_RUN;
-
-	return PSCI_E_SUCCESS;
-}
-
-static int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint)
+int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint)
 {
 	/* The non-secure entry point must be in DRAM */
 	if (ns_entrypoint < SUNXI_DRAM_BASE) {
@@ -214,25 +25,6 @@
 	return PSCI_E_SUCCESS;
 }
 
-static void sunxi_get_sys_suspend_power_state(psci_power_state_t *req_state)
-{
-	assert(req_state);
-
-	for (unsigned int i = 0; i <= PLAT_MAX_PWR_LVL; ++i)
-		req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
-}
-
-static plat_psci_ops_t sunxi_psci_ops = {
-	.cpu_standby			= sunxi_cpu_standby,
-	.pwr_domain_on			= sunxi_pwr_domain_on,
-	.pwr_domain_off			= sunxi_pwr_domain_off,
-	.pwr_domain_on_finish		= sunxi_pwr_domain_on_finish,
-	.system_off			= sunxi_system_off,
-	.system_reset			= sunxi_system_reset,
-	.validate_power_state		= sunxi_validate_power_state,
-	.validate_ns_entrypoint		= sunxi_validate_ns_entrypoint,
-};
-
 int plat_setup_psci_ops(uintptr_t sec_entrypoint,
 			const plat_psci_ops_t **psci_ops)
 {
@@ -246,36 +38,12 @@
 			      sec_entrypoint >> 32);
 	}
 
-	/* Check for a valid SCP firmware, and boot the SCP if found. */
-	if (mmio_read_32(SUNXI_SCP_BASE) == SCP_FIRMWARE_MAGIC) {
-		/* Program SCP exception vectors to the firmware entrypoint. */
-		for (unsigned int i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) {
-			uint32_t vector = SUNXI_SRAM_A2_BASE + OR1K_VEC_ADDR(i);
-			uint32_t offset = SUNXI_SCP_BASE - vector;
-
-			mmio_write_32(vector, offset >> 2);
-			clean_dcache_range(vector, sizeof(uint32_t));
-		}
-		/* Take the SCP out of reset. */
-		mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0));
-		/* Wait for the SCP firmware to boot. */
-		if (scpi_wait_ready() == 0)
-			scpi_available = true;
-	}
-
-	NOTICE("PSCI: System suspend is %s\n",
-	       scpi_available ? "available via SCPI" : "unavailable");
-	if (scpi_available) {
-		/* Suspend is only available via SCPI. */
-		sunxi_psci_ops.pwr_domain_suspend = sunxi_pwr_domain_off;
-		sunxi_psci_ops.pwr_domain_suspend_finish = sunxi_pwr_domain_on_finish;
-		sunxi_psci_ops.get_sys_suspend_power_state = sunxi_get_sys_suspend_power_state;
+	if (sunxi_set_scpi_psci_ops(psci_ops) == 0) {
+		INFO("PSCI: Suspend is available via SCPI\n");
 	} else {
-		/* This is only needed when SCPI is unavailable. */
-		sunxi_psci_ops.pwr_domain_pwr_down_wfi = sunxi_pwr_down_wfi;
+		INFO("PSCI: Suspend is unavailable\n");
+		sunxi_set_native_psci_ops(psci_ops);
 	}
 
-	*psci_ops = &sunxi_psci_ops;
-
 	return 0;
 }
diff --git a/plat/allwinner/common/sunxi_scpi_pm.c b/plat/allwinner/common/sunxi_scpi_pm.c
new file mode 100644
index 0000000..74763ef
--- /dev/null
+++ b/plat/allwinner/common/sunxi_scpi_pm.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/css/css_scpi.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
+
+/*
+ * The addresses for the SCP exception vectors are defined in the or1k
+ * architecture specification.
+ */
+#define OR1K_VEC_FIRST			0x01
+#define OR1K_VEC_LAST			0x0e
+#define OR1K_VEC_ADDR(n)		(0x100 * (n))
+
+/*
+ * This magic value is the little-endian representation of the or1k
+ * instruction "l.mfspr r2, r0, 0x12", which is guaranteed to be the
+ * first instruction in the SCP firmware.
+ */
+#define SCP_FIRMWARE_MAGIC		0xb4400012
+
+#define CPU_PWR_LVL			MPIDR_AFFLVL0
+#define CLUSTER_PWR_LVL			MPIDR_AFFLVL1
+#define SYSTEM_PWR_LVL			MPIDR_AFFLVL2
+
+#define CPU_PWR_STATE(state) \
+	((state)->pwr_domain_state[CPU_PWR_LVL])
+#define CLUSTER_PWR_STATE(state) \
+	((state)->pwr_domain_state[CLUSTER_PWR_LVL])
+#define SYSTEM_PWR_STATE(state) \
+	((state)->pwr_domain_state[SYSTEM_PWR_LVL])
+
+static inline scpi_power_state_t scpi_map_state(plat_local_state_t psci_state)
+{
+	if (is_local_state_run(psci_state)) {
+		return scpi_power_on;
+	}
+	if (is_local_state_retn(psci_state)) {
+		return scpi_power_retention;
+	}
+	return scpi_power_off;
+}
+
+static void sunxi_cpu_standby(plat_local_state_t cpu_state)
+{
+	u_register_t scr = read_scr_el3();
+
+	assert(is_local_state_retn(cpu_state));
+
+	write_scr_el3(scr | SCR_IRQ_BIT);
+	wfi();
+	write_scr_el3(scr);
+}
+
+static int sunxi_pwr_domain_on(u_register_t mpidr)
+{
+	scpi_set_css_power_state(mpidr,
+				 scpi_power_on,
+				 scpi_power_on,
+				 scpi_power_on);
+
+	return PSCI_E_SUCCESS;
+}
+
+static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	plat_local_state_t cpu_pwr_state     = CPU_PWR_STATE(target_state);
+	plat_local_state_t cluster_pwr_state = CLUSTER_PWR_STATE(target_state);
+	plat_local_state_t system_pwr_state  = SYSTEM_PWR_STATE(target_state);
+
+	if (is_local_state_off(cpu_pwr_state)) {
+		gicv2_cpuif_disable();
+	}
+
+	scpi_set_css_power_state(read_mpidr(),
+				 scpi_map_state(cpu_pwr_state),
+				 scpi_map_state(cluster_pwr_state),
+				 scpi_map_state(system_pwr_state));
+}
+
+static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
+		gicv2_distif_init();
+	}
+	if (is_local_state_off(CPU_PWR_STATE(target_state))) {
+		gicv2_pcpu_distif_init();
+		gicv2_cpuif_enable();
+	}
+}
+
+static void __dead2 sunxi_system_off(void)
+{
+	uint32_t ret;
+
+	gicv2_cpuif_disable();
+
+	/* Send the power down request to the SCP. */
+	ret = scpi_sys_power_state(scpi_system_shutdown);
+	if (ret != SCP_OK) {
+		ERROR("PSCI: SCPI %s failed: %d\n", "shutdown", ret);
+	}
+
+	psci_power_down_wfi();
+}
+
+static void __dead2 sunxi_system_reset(void)
+{
+	uint32_t ret;
+
+	gicv2_cpuif_disable();
+
+	/* Send the system reset request to the SCP. */
+	ret = scpi_sys_power_state(scpi_system_reboot);
+	if (ret != SCP_OK) {
+		ERROR("PSCI: SCPI %s failed: %d\n", "reboot", ret);
+	}
+
+	psci_power_down_wfi();
+}
+
+static int sunxi_validate_power_state(unsigned int power_state,
+				      psci_power_state_t *req_state)
+{
+	unsigned int power_level = psci_get_pstate_pwrlvl(power_state);
+	unsigned int type = psci_get_pstate_type(power_state);
+
+	assert(req_state != NULL);
+
+	if (power_level > PLAT_MAX_PWR_LVL) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	if (type == PSTATE_TYPE_STANDBY) {
+		/* Only one retention power state is supported. */
+		if (psci_get_pstate_id(power_state) > 0) {
+			return PSCI_E_INVALID_PARAMS;
+		}
+		/* The SoC cannot be suspended without losing state */
+		if (power_level == SYSTEM_PWR_LVL) {
+			return PSCI_E_INVALID_PARAMS;
+		}
+		for (unsigned int i = 0; i <= power_level; ++i) {
+			req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE;
+		}
+	} else {
+		/* Only one off power state is supported. */
+		if (psci_get_pstate_id(power_state) > 0) {
+			return PSCI_E_INVALID_PARAMS;
+		}
+		for (unsigned int i = 0; i <= power_level; ++i) {
+			req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+		}
+	}
+	/* Higher power domain levels should all remain running */
+	for (unsigned int i = power_level + 1; i <= PLAT_MAX_PWR_LVL; ++i) {
+		req_state->pwr_domain_state[i] = PSCI_LOCAL_STATE_RUN;
+	}
+
+	return PSCI_E_SUCCESS;
+}
+
+static void sunxi_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+	assert(req_state != NULL);
+
+	for (unsigned int i = 0; i <= PLAT_MAX_PWR_LVL; ++i) {
+		req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+	}
+}
+
+static const plat_psci_ops_t sunxi_scpi_psci_ops = {
+	.cpu_standby			= sunxi_cpu_standby,
+	.pwr_domain_on			= sunxi_pwr_domain_on,
+	.pwr_domain_off			= sunxi_pwr_domain_off,
+	.pwr_domain_suspend		= sunxi_pwr_domain_off,
+	.pwr_domain_on_finish		= sunxi_pwr_domain_on_finish,
+	.pwr_domain_suspend_finish	= sunxi_pwr_domain_on_finish,
+	.system_off			= sunxi_system_off,
+	.system_reset			= sunxi_system_reset,
+	.validate_power_state		= sunxi_validate_power_state,
+	.validate_ns_entrypoint		= sunxi_validate_ns_entrypoint,
+	.get_sys_suspend_power_state	= sunxi_get_sys_suspend_power_state,
+};
+
+int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops)
+{
+	*psci_ops = &sunxi_scpi_psci_ops;
+
+	/* Check for a valid SCP firmware. */
+	if (mmio_read_32(SUNXI_SCP_BASE) != SCP_FIRMWARE_MAGIC) {
+		return -1;
+	}
+
+	/* Program SCP exception vectors to the firmware entrypoint. */
+	for (unsigned int i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) {
+		uint32_t vector = SUNXI_SRAM_A2_BASE + OR1K_VEC_ADDR(i);
+		uint32_t offset = SUNXI_SCP_BASE - vector;
+
+		mmio_write_32(vector, offset >> 2);
+		clean_dcache_range(vector, sizeof(uint32_t));
+	}
+
+	/* Take the SCP out of reset. */
+	mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0));
+
+	/* Wait for the SCP firmware to boot. */
+	return scpi_wait_ready();
+}
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index 6e479ac..52686fa 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -48,6 +48,18 @@
 					DEVICE1_SIZE,			\
 					MT_DEVICE | MT_RW | MT_SECURE)
 
+#if FVP_GICR_REGION_PROTECTION
+#define MAP_GICD_MEM	MAP_REGION_FLAT(BASE_GICD_BASE,			\
+					BASE_GICD_SIZE,			\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+/* Map all core's redistributor memory as read-only. After boots up,
+ * per-core map its redistributor memory as read-write */
+#define MAP_GICR_MEM	MAP_REGION_FLAT(BASE_GICR_BASE,			\
+					(BASE_GICR_SIZE * PLATFORM_CORE_COUNT),\
+					MT_DEVICE | MT_RO | MT_SECURE)
+#endif /* FVP_GICR_REGION_PROTECTION */
+
 /*
  * Need to be mapped with write permissions in order to set a new non-volatile
  * counter value.
@@ -70,7 +82,9 @@
 	V2M_MAP_FLASH0_RW,
 	V2M_MAP_IOFPGA,
 	MAP_DEVICE0,
+#if FVP_INTERCONNECT_DRIVER == FVP_CCN
 	MAP_DEVICE1,
+#endif
 #if TRUSTED_BOARD_BOOT
 	/* To access the Root of Trust Public Key registers. */
 	MAP_DEVICE2,
@@ -86,7 +100,9 @@
 	V2M_MAP_FLASH0_RW,
 	V2M_MAP_IOFPGA,
 	MAP_DEVICE0,
+#if FVP_INTERCONNECT_DRIVER == FVP_CCN
 	MAP_DEVICE1,
+#endif
 	ARM_MAP_NS_DRAM1,
 #ifdef __aarch64__
 	ARM_MAP_DRAM2,
@@ -134,7 +150,12 @@
 	ARM_MAP_EL3_TZC_DRAM,
 	V2M_MAP_IOFPGA,
 	MAP_DEVICE0,
+#if FVP_GICR_REGION_PROTECTION
+	MAP_GICD_MEM,
+	MAP_GICR_MEM,
+#else
 	MAP_DEVICE1,
+#endif /* FVP_GICR_REGION_PROTECTION */
 	ARM_V2M_MAP_MEM_PROTECT,
 #if SPM_MM
 	ARM_SPM_BUF_EL3_MMAP,
diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h
index 4efe692..831eb35 100644
--- a/plat/arm/board/fvp/fvp_def.h
+++ b/plat/arm/board/fvp/fvp_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -135,7 +135,16 @@
 
 /* Base FVP compatible GIC memory map */
 #define BASE_GICD_BASE			UL(0x2f000000)
+#define BASE_GICD_SIZE			UL(0x10000)
 #define BASE_GICR_BASE			UL(0x2f100000)
+
+#if GIC_ENABLE_V4_EXTN
+/* GICv4 redistributor size: 256KB */
+#define BASE_GICR_SIZE			UL(0x40000)
+#else
+#define BASE_GICR_SIZE			UL(0x20000)
+#endif /* GIC_ENABLE_V4_EXTN */
+
 #define BASE_GICC_BASE			UL(0x2c000000)
 #define BASE_GICH_BASE			UL(0x2c010000)
 #define BASE_GICV_BASE			UL(0x2c02f000)
diff --git a/plat/arm/board/fvp/fvp_gicv3.c b/plat/arm/board/fvp/fvp_gicv3.c
index 3e04d6b..8f3e7b7 100644
--- a/plat/arm/board/fvp/fvp_gicv3.c
+++ b/plat/arm/board/fvp/fvp_gicv3.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,6 +15,11 @@
 #include <plat/arm/common/fconf_sec_intr_config.h>
 #include <plat/common/platform.h>
 
+#if FVP_GICR_REGION_PROTECTION
+/* To indicate GICR region of the core initialized as Read-Write */
+static bool fvp_gicr_rw_region_init[PLATFORM_CORE_COUNT] = {false};
+#endif /* FVP_GICR_REGION_PROTECTION */
+
 /* The GICv3 driver only needs to be initialized in EL3 */
 static uintptr_t fvp_rdistif_base_addrs[PLATFORM_CORE_COUNT];
 
@@ -61,8 +66,39 @@
 	.mpidr_to_core_pos = fvp_gicv3_mpidr_hash
 };
 
+/******************************************************************************
+ * This function gets called per core to make its redistributor frame rw
+ *****************************************************************************/
+static void fvp_gicv3_make_rdistrif_rw(void)
+{
+#if FVP_GICR_REGION_PROTECTION
+	unsigned int core_pos = plat_my_core_pos();
+
+	/* Make the redistributor frame RW if it is not done previously */
+	if (fvp_gicr_rw_region_init[core_pos] != true) {
+		int ret = xlat_change_mem_attributes(BASE_GICR_BASE +
+						     (core_pos * BASE_GICR_SIZE),
+						     BASE_GICR_SIZE,
+						     MT_EXECUTE_NEVER |
+						     MT_DEVICE | MT_RW |
+						     MT_SECURE);
+
+		if (ret != 0) {
+			ERROR("Failed to make redistributor frame \
+			       read write = %d\n", ret);
+			panic();
+		} else {
+			fvp_gicr_rw_region_init[core_pos] = true;
+		}
+	}
+#else
+	return;
+#endif /* FVP_GICR_REGION_PROTECTION */
+}
+
 void plat_arm_gic_driver_init(void)
 {
+	fvp_gicv3_make_rdistrif_rw();
 	/*
 	 * Get GICD and GICR base addressed through FCONF APIs.
 	 * FCONF is not supported in BL32 for FVP.
@@ -117,6 +153,8 @@
 	int result;
 	const uint64_t *plat_gicr_frames = fvp_gicr_frames;
 
+	fvp_gicv3_make_rdistrif_rw();
+
 	do {
 		result = gicv3_rdistif_probe(*plat_gicr_frames);
 
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 0a6fa56..6c09d72 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -16,6 +16,10 @@
 # Default number of threads per CPU on FVP
 FVP_MAX_PE_PER_CPU	:= 1
 
+# Disable redistributor frame of inactive/fused CPU cores by marking it as read
+# only; enable redistributor frames of all CPU cores by default.
+FVP_GICR_REGION_PROTECTION		:= 0
+
 FVP_DT_PREFIX		:= fvp-base-gicv3-psci
 
 # The FVP platform depends on this macro to build with correct GIC driver.
@@ -30,6 +34,9 @@
 # Pass FVP_MAX_PE_PER_CPU to the build system.
 $(eval $(call add_define,FVP_MAX_PE_PER_CPU))
 
+# Pass FVP_GICR_REGION_PROTECTION to the build system.
+$(eval $(call add_define,FVP_GICR_REGION_PROTECTION))
+
 # Sanity check the cluster count and if FVP_CLUSTER_COUNT <= 2,
 # choose the CCI driver , else the CCN driver
 ifeq ($(FVP_CLUSTER_COUNT), 0)
diff --git a/plat/arm/board/juno/juno_decl.h b/plat/arm/board/juno/juno_decl.h
index cd87c3b..21e56c0 100644
--- a/plat/arm/board/juno/juno_decl.h
+++ b/plat/arm/board/juno/juno_decl.h
@@ -7,6 +7,6 @@
 #ifndef JUNO_DECL_H
 #define JUNO_DECL_H
 
-int juno_getentropy(void *buf, size_t len);
+bool juno_getentropy(uint64_t *buf);
 
 #endif /* JUNO_DECL_H */
diff --git a/plat/arm/board/juno/juno_stack_protector.c b/plat/arm/board/juno/juno_stack_protector.c
index 236eb5b..8c51f57 100644
--- a/plat/arm/board/juno/juno_stack_protector.c
+++ b/plat/arm/board/juno/juno_stack_protector.c
@@ -13,20 +13,16 @@
 
 u_register_t plat_get_stack_protector_canary(void)
 {
-	u_register_t c[TRNG_NBYTES / sizeof(u_register_t)];
-	u_register_t ret = 0;
-	size_t i;
+	uint64_t entropy;
 
-	if (juno_getentropy(c, sizeof(c)) != 0) {
+	if (!juno_getentropy(&entropy)) {
 		ERROR("Not enough entropy to initialize canary value\n");
 		panic();
 	}
 
-	/*
-	 * On Juno we get 128-bits of entropy in one round.
-	 * Fuse the values together to form the canary.
-	 */
-	for (i = 0; i < ARRAY_SIZE(c); i++)
-		ret ^= c[i];
-	return ret;
+	if (sizeof(entropy) == sizeof(u_register_t)) {
+		return entropy;
+	}
+
+	return (entropy & 0xffffffffULL) ^ (entropy >> 32);
 }
diff --git a/plat/arm/board/juno/juno_trng.c b/plat/arm/board/juno/juno_trng.c
index 7869d3e..b38e49f 100644
--- a/plat/arm/board/juno/juno_trng.c
+++ b/plat/arm/board/juno/juno_trng.c
@@ -5,6 +5,8 @@
  */
 
 #include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
 #include <string.h>
 
 #include <lib/mmio.h>
@@ -16,7 +18,10 @@
 #define NSAMPLE_CLOCKS	1 /* min 1 cycle, max 231 cycles */
 #define NRETRIES	5
 
-static inline int output_valid(void)
+/* initialised to false */
+static bool juno_trng_initialized;
+
+static bool output_valid(void)
 {
 	int i;
 
@@ -25,59 +30,58 @@
 
 		val = mmio_read_32(TRNG_BASE + TRNG_STATUS);
 		if (val & 1U)
-			break;
+			return true;
 	}
-	if (i >= NRETRIES)
-		return 0; /* No output data available. */
-	return 1;
+	return false; /* No output data available. */
 }
 
 /*
- * This function fills `buf` with `len` bytes of entropy.
+ * This function fills `buf` with 8 bytes of entropy.
  * It uses the Trusted Entropy Source peripheral on Juno.
- * Returns 0 when the buffer has been filled with entropy
- * successfully and -1 otherwise.
+ * Returns 'true' when the buffer has been filled with entropy
+ * successfully, or 'false' otherwise.
  */
-int juno_getentropy(void *buf, size_t len)
+bool juno_getentropy(uint64_t *buf)
 {
-	uint8_t *bp = buf;
+	uint64_t ret;
 
 	assert(buf);
-	assert(len);
-	assert(!check_uptr_overflow((uintptr_t)bp, len));
+	assert(!check_uptr_overflow((uintptr_t)buf, sizeof(*buf)));
 
-	/* Disable interrupt mode. */
-	mmio_write_32(TRNG_BASE + TRNG_INTMASK, 0);
-	/* Program TRNG to sample for `NSAMPLE_CLOCKS`. */
-	mmio_write_32(TRNG_BASE + TRNG_CONFIG, NSAMPLE_CLOCKS);
+	if (!juno_trng_initialized) {
+		/* Disable interrupt mode. */
+		mmio_write_32(TRNG_BASE + TRNG_INTMASK, 0);
+		/* Program TRNG to sample for `NSAMPLE_CLOCKS`. */
+		mmio_write_32(TRNG_BASE + TRNG_CONFIG, NSAMPLE_CLOCKS);
+		/* Abort any potentially pending sampling. */
+		mmio_write_32(TRNG_BASE + TRNG_CONTROL, 2);
+		/* Reset TRNG outputs. */
+		mmio_write_32(TRNG_BASE + TRNG_STATUS, 1);
 
-	while (len > 0) {
-		int i;
+		juno_trng_initialized = true;
+	}
 
+	if (!output_valid()) {
 		/* Start TRNG. */
 		mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1);
 
-		/* Check if output is valid. */
 		if (!output_valid())
-			return -1;
-
-		/* Fill entropy buffer. */
-		for (i = 0; i < TRNG_NOUTPUTS; i++) {
-			size_t n;
-			uint32_t val;
-
-			val = mmio_read_32(TRNG_BASE + i * sizeof(uint32_t));
-			n = MIN(len, sizeof(uint32_t));
-			memcpy(bp, &val, n);
-			bp += n;
-			len -= n;
-			if (len == 0)
-				break;
-		}
-
-		/* Reset TRNG outputs. */
-		mmio_write_32(TRNG_BASE + TRNG_STATUS, 1);
+			return false;
 	}
 
-	return 0;
+	/* XOR each two 32-bit registers together, combine the pairs */
+	ret = mmio_read_32(TRNG_BASE + 0);
+	ret ^= mmio_read_32(TRNG_BASE + 4);
+	ret <<= 32;
+
+	ret |= mmio_read_32(TRNG_BASE + 8);
+	ret ^= mmio_read_32(TRNG_BASE + 12);
+	*buf = ret;
+
+	/* Acknowledge current cycle, clear output registers. */
+	mmio_write_32(TRNG_BASE + TRNG_STATUS, 1);
+	/* Trigger next TRNG cycle. */
+	mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1);
+
+	return true;
 }
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 78704b5..61cfb61 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -108,7 +108,7 @@
 all : bl1_romlib.bin
 endif
 
-bl1_romlib.bin : $(BUILD_PLAT)/bl1.bin $(BUILD_PLAT)/romlib/romlib.bin
+bl1_romlib.bin : $(BUILD_PLAT)/bl1.bin romlib.bin
 	@echo "Building combined BL1 and ROMLIB binary for Juno $@"
 	./lib/romlib/gen_combined_bl1_romlib.sh -o bl1_romlib.bin $(BUILD_PLAT)
 
diff --git a/plat/arm/board/morello/morello_bl31_setup.c b/plat/arm/board/morello/morello_bl31_setup.c
index 5b91e87..59dd37b 100644
--- a/plat/arm/board/morello/morello_bl31_setup.c
+++ b/plat/arm/board/morello/morello_bl31_setup.c
@@ -8,6 +8,7 @@
 #include <drivers/arm/css/css_mhu_doorbell.h>
 #include <drivers/arm/css/scmi.h>
 #include <drivers/arm/css/sds.h>
+#include <lib/cassert.h>
 #include <plat/arm/common/plat_arm.h>
 
 #include "morello_def.h"
@@ -17,18 +18,21 @@
  * Platform information structure stored in SDS.
  * This structure holds information about platform's DDR
  * size which is an information about multichip setup
- * 	- multichip mode
- * 	- slave_count
- * 	- Local DDR size in GB, DDR memory in master board
- * 	- Remote DDR size in GB, DDR memory in slave board
+ *	- Local DDR size in bytes, DDR memory in master board
+ *	- Remote DDR size in bytes, DDR memory in slave board
+ *	- slave_count
+ *	- multichip mode
  */
 struct morello_plat_info {
-	bool multichip_mode;
+	uint64_t local_ddr_size;
+	uint64_t remote_ddr_size;
 	uint8_t slave_count;
-	uint8_t local_ddr_size;
-	uint8_t remote_ddr_size;
+	bool multichip_mode;
 } __packed;
 
+/* Compile time assertion to ensure the size of structure is 18 bytes */
+CASSERT(sizeof(struct morello_plat_info) == MORELLO_SDS_PLATFORM_INFO_SIZE,
+		assert_invalid_plat_info_size);
 /*
  * BL33 image information structure stored in SDS.
  * This structure holds the source & destination addresses and
@@ -80,6 +84,7 @@
 	int ret;
 	struct morello_plat_info plat_info;
 	struct morello_bl33_info bl33_info;
+	struct morello_plat_info *copy_dest;
 
 	ret = sds_init();
 	if (ret != SDS_OK) {
@@ -99,8 +104,8 @@
 
 	/* Validate plat_info SDS */
 	if ((plat_info.local_ddr_size == 0U)
-		|| (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY_GB)
-		|| (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY_GB)
+		|| (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY)
+		|| (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY)
 		|| (plat_info.slave_count > MORELLO_MAX_SLAVE_COUNT)) {
 		ERROR("platform info SDS is corrupted\n");
 		panic();
@@ -127,5 +132,6 @@
 	 * and platform information should be passed to BL33 using NT_FW_CONFIG
 	 * passing mechanism.
 	 */
-	mmio_write_32(MORELLO_PLATFORM_INFO_BASE, *(uint32_t *)&plat_info);
+	copy_dest = (struct morello_plat_info *)MORELLO_PLATFORM_INFO_BASE;
+	*copy_dest = plat_info;
 }
diff --git a/plat/arm/board/morello/morello_def.h b/plat/arm/board/morello/morello_def.h
index 09db303..793729b 100644
--- a/plat/arm/board/morello/morello_def.h
+++ b/plat/arm/board/morello/morello_def.h
@@ -18,8 +18,8 @@
 /* SDS Platform information defines */
 #define MORELLO_SDS_PLATFORM_INFO_STRUCT_ID	U(8)
 #define MORELLO_SDS_PLATFORM_INFO_OFFSET	U(0)
-#define MORELLO_SDS_PLATFORM_INFO_SIZE		U(4)
-#define MORELLO_MAX_DDR_CAPACITY_GB		U(64)
+#define MORELLO_SDS_PLATFORM_INFO_SIZE		U(18)
+#define MORELLO_MAX_DDR_CAPACITY		U(0x1000000000)
 #define MORELLO_MAX_SLAVE_COUNT			U(16)
 
 /* SDS BL33 image information defines */
@@ -28,6 +28,6 @@
 #define MORELLO_SDS_BL33_INFO_SIZE		U(12)
 
 /* Base address of non-secure SRAM where Platform information will be filled */
-#define MORELLO_PLATFORM_INFO_BASE		UL(0x06008000)
+#define MORELLO_PLATFORM_INFO_BASE		UL(0x06000000)
 
 #endif /* MORELLO_DEF_H */
diff --git a/plat/arm/board/morello/platform.mk b/plat/arm/board/morello/platform.mk
index 2a23bc6..fc7d4d3 100644
--- a/plat/arm/board/morello/platform.mk
+++ b/plat/arm/board/morello/platform.mk
@@ -65,5 +65,3 @@
 include plat/arm/common/arm_common.mk
 include plat/arm/css/common/css_common.mk
 include plat/arm/board/common/board_common.mk
-
-override ERRATA_N1_1542419		:=	1
diff --git a/plat/arm/board/rdn2/include/platform_def.h b/plat/arm/board/rdn2/include/platform_def.h
index 5561f8c..3f753f7 100644
--- a/plat/arm/board/rdn2/include/platform_def.h
+++ b/plat/arm/board/rdn2/include/platform_def.h
@@ -22,7 +22,7 @@
 #define PLAT_MAX_PWR_LVL		ARM_PWR_LVL1
 
 /* TZC Related Constants */
-#define PLAT_ARM_TZC_BASE		UL(0x10820000)
+#define PLAT_ARM_TZC_BASE		UL(0x10720000)
 #define PLAT_ARM_TZC_FILTERS		TZC_400_REGION_ATTR_FILTER_BIT(0)
 
 #define TZC400_OFFSET			UL(0x1000000)
diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk
index 6be6113..03771dc 100644
--- a/plat/arm/board/rdn2/platform.mk
+++ b/plat/arm/board/rdn2/platform.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -57,3 +57,4 @@
 $(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
 
 override CTX_INCLUDE_AARCH32_REGS	:= 0
+override ENABLE_AMU			:= 1
diff --git a/plat/arm/board/rdv1/platform.mk b/plat/arm/board/rdv1/platform.mk
index 5033b18..2ffd139 100644
--- a/plat/arm/board/rdv1/platform.mk
+++ b/plat/arm/board/rdv1/platform.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -57,3 +57,4 @@
 $(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG}))
 
 override CTX_INCLUDE_AARCH32_REGS	:= 0
+override ENABLE_AMU			:= 1
diff --git a/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts b/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts
index b6c543a..2f459b0 100644
--- a/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts
+++ b/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts
@@ -20,30 +20,27 @@
 		binary_size = <0x80000>;
 	};
 
-	chosen {
-		linux,initrd-start = <0>;
-		linux,initrd-end = <0>;
-	};
-
 	hypervisor {
 		compatible = "hafnium,hafnium";
 		vm1 {
 			is_ffa_partition;
 			debug_name = "cactus-primary";
 			load_address = <0xfe000000>;
+			vcpu_count = <8>;
+			mem_size = <1048576>;
 		};
 		vm2 {
 			is_ffa_partition;
 			debug_name = "cactus-secondary";
 			load_address = <0xfe100000>;
-			vcpu_count = <4>;
+			vcpu_count = <8>;
 			mem_size = <1048576>;
 		};
 		vm3 {
 			is_ffa_partition;
 			debug_name = "cactus-tertiary";
 			load_address = <0xfe200000>;
-			vcpu_count = <4>;
+			vcpu_count = <8>;
 			mem_size = <1048576>;
 		};
 	};
@@ -60,9 +57,37 @@
 		};
 
 		/*
-		 * SPM(Hafnium) requires secondary cpu nodes are declared in
+		 * SPMC (Hafnium) requires secondary cpu nodes are declared in
 		 * descending order
 		 */
+		CPU7:cpu@700 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x700>;
+			enable-method = "psci";
+		};
+
+		CPU6:cpu@600 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x600>;
+			enable-method = "psci";
+		};
+
+		CPU5:cpu@500 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x500>;
+			enable-method = "psci";
+		};
+
+		CPU4:cpu@400 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x400>;
+			enable-method = "psci";
+		};
+
 		CPU3:cpu@300 {
 			device_type = "cpu";
 			compatible = "arm,armv8";
diff --git a/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts b/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts
index a58b911..221039c 100644
--- a/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts
+++ b/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts
@@ -5,13 +5,6 @@
  */
 /dts-v1/;
 
-#define	AFF	00
-
-#include "fvp-defs.dtsi"
-#undef POST
-#define	POST \
-	};
-
 / {
 	compatible = "arm,ffa-core-manifest-1.0";
 	#address-cells = <2>;
@@ -27,21 +20,14 @@
 		binary_size = <0x80000>;
 	};
 
-	/*
-	 * temporary: This entry is added based on v2.4 hafnium and will be
-	 * removed when rebased to upstream master.
-	 */
-	chosen {
-	       linux,initrd-start = <0>;
-	       linux,initrd-end = <0>;
-	};
-
 	hypervisor {
 		compatible = "hafnium,hafnium";
 		vm1 {
 			is_ffa_partition;
 			debug_name = "op-tee";
 			load_address = <0xfd280000>;
+			vcpu_count = <8>;
+			mem_size = <30928896>; /* 32MB TZC DRAM - SPMC region */
 		};
 	};
 
@@ -49,25 +35,65 @@
 		#address-cells = <0x2>;
 		#size-cells = <0x0>;
 
-		CPU_0
+		CPU0:cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+		};
 
 		/*
-		 * SPMC (Hafnium) requires secondary core nodes are declared
-		 * in descending order.
+		 * SPMC (Hafnium) requires secondary cpu nodes are declared in
+		 * descending order
 		 */
-		CPU_3
-		CPU_2
-		CPU_1
-	};
+		CPU7:cpu@700 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x700>;
+			enable-method = "psci";
+		};
 
-	/*
-	 * temporary: This device-memory region is added based on v2.4 hafnium
-	 * and will be removed when rebased to upstream master. As first
-	 * Secure Partition no longer maps device memory.
-	 */
-	device-memory@21000000 {
-		device_type = "device-memory";
-		reg = <0x0 0x21000000 0x5f000000>;
+		CPU6:cpu@600 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x600>;
+			enable-method = "psci";
+		};
+
+		CPU5:cpu@500 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x500>;
+			enable-method = "psci";
+		};
+
+		CPU4:cpu@400 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x400>;
+			enable-method = "psci";
+		};
+
+		CPU3:cpu@300 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x300>;
+			enable-method = "psci";
+		};
+
+		CPU2:cpu@200 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x200>;
+			enable-method = "psci";
+		};
+
+		CPU1:cpu@100 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x100>;
+			enable-method = "psci";
+		};
 	};
 
 	/* 32MB of TC0_TZC_DRAM1_BASE */
diff --git a/plat/arm/board/tc0/include/platform_def.h b/plat/arm/board/tc0/include/platform_def.h
index 2ff2699..30b5ab7 100644
--- a/plat/arm/board/tc0/include/platform_def.h
+++ b/plat/arm/board/tc0/include/platform_def.h
@@ -17,7 +17,7 @@
 #include <plat/arm/soc/common/soc_css_def.h>
 #include <plat/common/common_def.h>
 
-#define PLATFORM_CORE_COUNT		4
+#define PLATFORM_CORE_COUNT		8
 
 #define PLAT_ARM_TRUSTED_SRAM_SIZE	0x00080000	/* 512 KB */
 
@@ -202,7 +202,7 @@
 #define PLAT_ARM_SCMI_CHANNEL_COUNT	1
 
 #define PLAT_ARM_CLUSTER_COUNT		U(1)
-#define PLAT_MAX_CPUS_PER_CLUSTER	U(4)
+#define PLAT_MAX_CPUS_PER_CLUSTER	U(8)
 #define PLAT_MAX_PE_PER_CPU		U(1)
 
 #define PLAT_CSS_MHU_BASE		UL(0x45400000)
diff --git a/plat/arm/board/tc0/platform.mk b/plat/arm/board/tc0/platform.mk
index 6cc5f46..393d09c 100644
--- a/plat/arm/board/tc0/platform.mk
+++ b/plat/arm/board/tc0/platform.mk
@@ -43,7 +43,8 @@
 
 PLAT_INCLUDES		+=	-I${TC0_BASE}/include/
 
-TC0_CPU_SOURCES	:=	lib/cpus/aarch64/cortex_matterhorn.S
+TC0_CPU_SOURCES	:=	lib/cpus/aarch64/cortex_klein.S         \
+			lib/cpus/aarch64/cortex_matterhorn.S
 
 INTERCONNECT_SOURCES	:=	${TC0_BASE}/tc0_interconnect.c
 
diff --git a/plat/arm/board/tc0/tc0_topology.c b/plat/arm/board/tc0/tc0_topology.c
index 5478fbc..8cfc3b5 100644
--- a/plat/arm/board/tc0/tc0_topology.c
+++ b/plat/arm/board/tc0/tc0_topology.c
@@ -33,6 +33,9 @@
 	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)),
 	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)),
 	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)),
 };
 
 /*******************************************************************************
diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c
index 89e2cab..e8238ba 100644
--- a/plat/arm/css/sgi/sgi_bl31_setup.c
+++ b/plat/arm/css/sgi/sgi_bl31_setup.c
@@ -28,7 +28,7 @@
 		.ring_doorbell = &mhu_ring_doorbell,
 };
 
-static scmi_channel_plat_info_t rd_n1e1_edge_scmi_plat_info[] = {
+static scmi_channel_plat_info_t plat_rd_scmi_info[] = {
 	{
 		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
 		.db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0),
@@ -76,9 +76,9 @@
 	if (sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM ||
 		sgi_plat_info.platform_id == RD_V1_SID_VER_PART_NUM ||
 		sgi_plat_info.platform_id == RD_N2_SID_VER_PART_NUM) {
-		if (channel_id >= ARRAY_SIZE(rd_n1e1_edge_scmi_plat_info))
+		if (channel_id >= ARRAY_SIZE(plat_rd_scmi_info))
 			panic();
-		return &rd_n1e1_edge_scmi_plat_info[channel_id];
+		return &plat_rd_scmi_info[channel_id];
 	}
 	else if (sgi_plat_info.platform_id == SGI575_SSC_VER_PART_NUM)
 		return &sgi575_scmi_plat_info;
@@ -108,12 +108,11 @@
 const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
 {
 	/*
-	 * For RD-E1-Edge and RD-V1 platforms, only CPU power ON/OFF
-	 * PSCI platform callbacks are supported.
+	 * For RD-E1-Edge, only CPU power ON/OFF, PSCI platform callbacks are
+	 * supported.
 	 */
 	if (((sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM) &&
-	    (sgi_plat_info.config_id == RD_E1_EDGE_CONFIG_ID)) ||
-	    (sgi_plat_info.platform_id == RD_V1_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/marvell/armada/a3k/common/a3700_common.mk b/plat/marvell/armada/a3k/common/a3700_common.mk
index 824a3c6..8775e89 100644
--- a/plat/marvell/armada/a3k/common/a3700_common.mk
+++ b/plat/marvell/armada/a3k/common/a3700_common.mk
@@ -71,19 +71,27 @@
 
 ifdef WTP
 
+$(if $(wildcard $(value WTP)/*),,$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' directory does not exist"))
+$(if $(shell test -s "$(value WTP)/branch.txt" || git -C $(value WTP) rev-parse --show-cdup 2>&1),$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' does not contain valid Marvell a3700_utils release tarball nor git repository"))
+
 DOIMAGEPATH	:= $(WTP)
 DOIMAGETOOL	:= $(DOIMAGEPATH)/wtptp/src/TBB_Linux/release/TBB_linux
 
-ifeq ($(MARVELL_SECURE_BOOT),1)
-DOIMAGE_CFG	:= $(DOIMAGEPATH)/atf-tim.txt
-IMAGESPATH	:= $(DOIMAGEPATH)/tim/trusted
+BUILD_UART	:= uart-images
+UART_IMAGE	:= $(BUILD_UART).tgz.bin
 
-TIMNCFG		:= $(DOIMAGEPATH)/atf-timN.txt
+ifeq ($(MARVELL_SECURE_BOOT),1)
+DOIMAGE_CFG	:= $(BUILD_PLAT)/atf-tim.txt
+DOIMAGEUART_CFG	:= $(BUILD_PLAT)/$(BUILD_UART)/atf-tim.txt
+IMAGESPATH	:= $(DOIMAGEPATH)/tim/trusted
+TIMNCFG		:= $(BUILD_PLAT)/atf-timN.txt
+TIMNUARTCFG	:= $(BUILD_PLAT)/$(BUILD_UART)/atf-timN.txt
 TIMNSIG		:= $(IMAGESPATH)/timnsign.txt
 TIM2IMGARGS	:= -i $(DOIMAGE_CFG) -n $(TIMNCFG)
 TIMN_IMAGE	:= $$(grep "Image Filename:" -m 1 $(TIMNCFG) | cut -c 17-)
 else #MARVELL_SECURE_BOOT
-DOIMAGE_CFG	:= $(DOIMAGEPATH)/atf-ntim.txt
+DOIMAGE_CFG	:= $(BUILD_PLAT)/atf-ntim.txt
+DOIMAGEUART_CFG	:= $(BUILD_PLAT)/$(BUILD_UART)/atf-ntim.txt
 IMAGESPATH	:= $(DOIMAGEPATH)/tim/untrusted
 TIM2IMGARGS	:= -i $(DOIMAGE_CFG)
 endif #MARVELL_SECURE_BOOT
@@ -99,18 +107,11 @@
 # baremetal binary of fuse programming in A3700_utils.
 WTMI_IMG	:= $(DOIMAGEPATH)/wtmi/fuse/build/fuse.bin
 
-# WTMI_SYSINIT_IMG is used for the system early initialization,
-# such as AVS settings, clock-tree setup and dynamic DDR PHY training.
-# After the initialization is done, this image will be wiped out
-# from the memory and CM3 will continue with RTOS image or other application.
-WTMI_SYSINIT_IMG	:= $(DOIMAGEPATH)/wtmi/sys_init/build/sys_init.bin
-
 # WTMI_MULTI_IMG is composed of CM3 RTOS image (WTMI_IMG)
-# and sys-init image (WTMI_SYSINIT_IMG).
+# and sys-init image.
 WTMI_MULTI_IMG		:= $(DOIMAGEPATH)/wtmi/build/wtmi.bin
 
-WTMI_ENC_IMG		:= $(BUILD_PLAT)/wtmi-enc.bin
-BUILD_UART		:= uart-images
+WTMI_ENC_IMG		:= wtmi-enc.bin
 
 SRCPATH			:= $(dir $(BL33))
 
@@ -125,90 +126,108 @@
 TIMBLDARGS		:= $(MARVELL_SECURE_BOOT) $(BOOTDEV) $(IMAGESPATH) $(DOIMAGEPATH) $(CLOCKSPRESET) \
 				$(DDR_TOPOLOGY) $(PARTNUM) $(DEBUG) $(DOIMAGE_CFG) $(TIMNCFG) $(TIMNSIG) 1
 TIMBLDUARTARGS		:= $(MARVELL_SECURE_BOOT) UART $(IMAGESPATH) $(DOIMAGEPATH) $(CLOCKSPRESET) \
-				$(DDR_TOPOLOGY) 0 0 $(DOIMAGE_CFG) $(TIMNCFG) $(TIMNSIG) 0
-DOIMAGE_FLAGS		:= -r $(DOIMAGE_CFG) -v -D
+				$(DDR_TOPOLOGY) 0 0 $(DOIMAGEUART_CFG) $(TIMNUARTCFG) $(TIMNSIG) 0
+
+CRYPTOPP_LIBDIR		?= $(CRYPTOPP_PATH)
+CRYPTOPP_INCDIR		?= $(CRYPTOPP_PATH)
 
 $(DOIMAGETOOL): FORCE
-	$(if $(value CRYPTOPP_PATH),,$(error "Platform '${PLAT}' for WTP image tool requires CRYPTOPP_PATH. Please set CRYPTOPP_PATH to point to the right directory"))
+	$(if $(CRYPTOPP_LIBDIR),,$(error "Platform '$(PLAT)' for WTP image tool requires CRYPTOPP_PATH or CRYPTOPP_LIBDIR. Please set CRYPTOPP_PATH or CRYPTOPP_LIBDIR to point to the right directory"))
+	$(if $(CRYPTOPP_INCDIR),,$(error "Platform '$(PLAT)' for WTP image tool requires CRYPTOPP_PATH or CRYPTOPP_INCDIR. Please set CRYPTOPP_PATH or CRYPTOPP_INCDIR to point to the right directory"))
+	$(if $(wildcard $(CRYPTOPP_LIBDIR)/*),,$(error "Either 'CRYPTOPP_PATH' or 'CRYPTOPP_LIB' was set to '$(CRYPTOPP_LIBDIR)', but '$(CRYPTOPP_LIBDIR)' does not exist"))
+	$(if $(wildcard $(CRYPTOPP_INCDIR)/*),,$(error "Either 'CRYPTOPP_PATH' or 'CRYPTOPP_INCDIR' was set to '$(CRYPTOPP_INCDIR)', but '$(CRYPTOPP_INCDIR)' does not exist"))
+ifdef CRYPTOPP_PATH
 	$(Q)$(MAKE) --no-print-directory -C $(CRYPTOPP_PATH) -f GNUmakefile
-	$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH)/wtptp/src/TBB_Linux -f TBB_linux.mak LIBDIR=$(CRYPTOPP_PATH)
+endif
+	$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH)/wtptp/src/TBB_Linux -f TBB_linux.mak LIBDIR=$(CRYPTOPP_LIBDIR) INCDIR=$(CRYPTOPP_INCDIR)
 
 $(WTMI_MULTI_IMG): FORCE
-	$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH) WTMI_IMG=$(WTMI_IMG) WTMI
+	$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH) WTMI_IMG=$(WTMI_IMG) DDR_TOPOLOGY=$(DDR_TOPOLOGY) CLOCKSPRESET=$(CLOCKSPRESET) WTMI
+
+$(BUILD_PLAT)/wtmi.bin: $(WTMI_MULTI_IMG)
+	$(Q)cp -a $(WTMI_MULTI_IMG) $(BUILD_PLAT)/wtmi.bin
 
 $(TIMDDRTOOL): FORCE
 	$(if $(value MV_DDR_PATH),,$(error "Platform '${PLAT}' for ddr tool requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory"))
-	$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH) MV_DDR_PATH=$(MV_DDR_PATH) mv_ddr
+	$(if $(wildcard $(value MV_DDR_PATH)/*),,$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' directory does not exist"))
+	$(if $(shell test -s "$(value MV_DDR_PATH)/branch.txt" || git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid Marvell mv_ddr release tarball nor git repository"))
+	$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH) MV_DDR_PATH=$(MV_DDR_PATH) DDR_TOPOLOGY=$(DDR_TOPOLOGY) mv_ddr
 
-.PHONY: mrvl_flash
-mrvl_flash: ${BUILD_PLAT}/${BOOT_IMAGE} ${WTMI_MULTI_IMG} ${DOIMAGETOOL} ${TIMBUILD}
-	@echo
+$(BUILD_PLAT)/$(UART_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(DOIMAGETOOL) $(TIMBUILD) $(TIMDDRTOOL)
+	@$(ECHO_BLANK_LINE)
 	@echo "Building uart images"
-	$(TIMBUILD) $(TIMBLDUARTARGS)
-	@sed -i 's|WTMI_IMG|$(WTMI_MULTI_IMG)|1' $(DOIMAGE_CFG)
-	@sed -i 's|BOOT_IMAGE|$(BUILD_PLAT)/$(BOOT_IMAGE)|1' $(DOIMAGE_CFG)
+	$(Q)mkdir -p $(BUILD_PLAT)/$(BUILD_UART)
+	$(Q)cp -a $(BUILD_PLAT)/wtmi.bin $(BUILD_PLAT)/$(BUILD_UART)/wtmi.bin
+	$(Q)cp -a $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/$(BUILD_UART)/$(BOOT_IMAGE)
+	$(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TIMBUILD) $(TIMBLDUARTARGS)
+	$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(DOIMAGEUART_CFG)
+	$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(DOIMAGEUART_CFG)
 ifeq ($(MARVELL_SECURE_BOOT),1)
-	@sed -i 's|WTMI_IMG|$(WTMI_MULTI_IMG)|1' $(TIMNCFG)
-	@sed -i 's|BOOT_IMAGE|$(BUILD_PLAT)/$(BOOT_IMAGE)|1' $(TIMNCFG)
+	$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIMNUARTCFG)
+	$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIMNUARTCFG)
 endif
-	$(DOIMAGETOOL) $(DOIMAGE_FLAGS)
-	@if [ -e "$(TIMNCFG)" ]; then $(DOIMAGETOOL) -r $(TIMNCFG); fi
-	@rm -rf $(BUILD_PLAT)/$(BUILD_UART)*
-	@mkdir $(BUILD_PLAT)/$(BUILD_UART)
-	@mv -t $(BUILD_PLAT)/$(BUILD_UART) $(TIM_IMAGE) $(DOIMAGE_CFG) $(TIMN_IMAGE) $(TIMNCFG)
-	@find . -name "*_h.*" |xargs cp -ut $(BUILD_PLAT)/$(BUILD_UART)
-	@mv $(subst .bin,_h.bin,$(WTMI_MULTI_IMG)) $(BUILD_PLAT)/$(BUILD_UART)/wtmi_h.bin
-	@tar czf $(BUILD_PLAT)/$(BUILD_UART).tgz.bin -C $(BUILD_PLAT) ./$(BUILD_UART)
-	@echo
-	@echo "Building flash image"
-	$(TIMBUILD) $(TIMBLDARGS)
-	sed -i 's|WTMI_IMG|$(WTMI_MULTI_IMG)|1' $(DOIMAGE_CFG)
-	sed -i 's|BOOT_IMAGE|$(BUILD_PLAT)/$(BOOT_IMAGE)|1' $(DOIMAGE_CFG)
+	$(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(DOIMAGETOOL) -r $(DOIMAGEUART_CFG) -v -D
 ifeq ($(MARVELL_SECURE_BOOT),1)
-	@sed -i 's|WTMI_IMG|$(WTMI_MULTI_IMG)|1' $(TIMNCFG)
-	@sed -i 's|BOOT_IMAGE|$(BUILD_PLAT)/$(BOOT_IMAGE)|1' $(TIMNCFG)
-	@echo -e "\n\t=======================================================\n";
-	@echo -e "\t  Secure boot. Encrypting wtmi and boot-image \n";
-	@echo -e "\t=======================================================\n";
-	@cp $(WTMI_MULTI_IMG) $(BUILD_PLAT)/wtmi-align.bin
-	@truncate -s %16 $(BUILD_PLAT)/wtmi-align.bin
-	@openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/wtmi-align.bin \
-	-out $(WTMI_ENC_IMG) \
+	$(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(DOIMAGETOOL) -r $(TIMNUARTCFG)
+endif
+	$(Q)tar czf $(BUILD_PLAT)/$(UART_IMAGE) -C $(BUILD_PLAT) $(BUILD_UART)/$(TIM_IMAGE) $(BUILD_UART)/wtmi_h.bin $(BUILD_UART)/boot-image_h.bin
+	@$(ECHO_BLANK_LINE)
+	@echo "Built $@ successfully"
+	@$(ECHO_BLANK_LINE)
+
+$(BUILD_PLAT)/$(FLASH_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(DOIMAGETOOL) $(TIMBUILD) $(TIMDDRTOOL) $(TIM2IMG)
+	@$(ECHO_BLANK_LINE)
+	@echo "Building flash image"
+	$(Q)cd $(BUILD_PLAT) && $(TIMBUILD) $(TIMBLDARGS)
+	$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(DOIMAGE_CFG)
+	$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(DOIMAGE_CFG)
+ifeq ($(MARVELL_SECURE_BOOT),1)
+	$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIMNCFG)
+	$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIMNCFG)
+	@$(ECHO_BLANK_LINE)
+	@echo "=======================================================";
+	@echo "  Secure boot. Encrypting wtmi and boot-image";
+	@echo "=======================================================";
+	@$(ECHO_BLANK_LINE)
+	$(Q)cp $(BUILD_PLAT)/wtmi.bin $(BUILD_PLAT)/wtmi-align.bin
+	$(Q)truncate -s %16 $(BUILD_PLAT)/wtmi-align.bin
+	$(Q)openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/wtmi-align.bin \
+	-out $(BUILD_PLAT)/$(WTMI_ENC_IMG) \
 	-K `cat $(IMAGESPATH)/aes-256.txt` -nosalt \
 	-iv `cat $(IMAGESPATH)/iv.txt` -p
-	@truncate -s %16 $(BUILD_PLAT)/$(BOOT_IMAGE);
-	@openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/$(BOOT_IMAGE) \
+	$(Q)truncate -s %16 $(BUILD_PLAT)/$(BOOT_IMAGE);
+	$(Q)openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/$(BOOT_IMAGE) \
 	-out $(BUILD_PLAT)/$(BOOT_ENC_IMAGE) \
 	-K `cat $(IMAGESPATH)/aes-256.txt` -nosalt \
 	-iv `cat $(IMAGESPATH)/iv.txt` -p
 endif
-	$(DOIMAGETOOL) $(DOIMAGE_FLAGS)
-	@if [ -e "$(TIMNCFG)" ]; then $(DOIMAGETOOL) -r $(TIMNCFG); fi
+	$(Q)cd $(BUILD_PLAT) && $(DOIMAGETOOL) -r $(DOIMAGE_CFG) -v -D
 ifeq ($(MARVELL_SECURE_BOOT),1)
-	@sed -i 's|$(WTMI_MULTI_IMG)|$(WTMI_ENC_IMG)|1;s|$(BOOT_IMAGE)|$(BOOT_ENC_IMAGE)|1;' $(TIMNCFG)
+	$(Q)cd $(BUILD_PLAT) && $(DOIMAGETOOL) -r $(TIMNCFG)
+	$(Q)sed -i 's|wtmi.bin|$(WTMI_ENC_IMG)|1' $(TIMNCFG)
+	$(Q)sed -i 's|$(BOOT_IMAGE)|$(BOOT_ENC_IMAGE)|1' $(TIMNCFG)
 endif
-	$(TIM2IMG) $(TIM2IMGARGS) -o $(BUILD_PLAT)/$(FLASH_IMAGE)
-	@mv -t $(BUILD_PLAT) $(TIM_IMAGE) $(DOIMAGE_CFG) $(TIMN_IMAGE) $(TIMNCFG)
-	@cp -t $(BUILD_PLAT) $(WTMI_IMG) $(WTMI_SYSINIT_IMG) $(WTMI_MULTI_IMG)
-ifeq ($(MARVELL_SECURE_BOOT),1)
-	@mv -t $(BUILD_PLAT) OtpHash.txt
-endif
-	@find . -name "*.txt" | grep -E "CSK[[:alnum:]]_KeyHash.txt|Tim_msg.txt|TIMHash.txt" | xargs rm -f
+	$(Q)cd $(BUILD_PLAT) && $(TIM2IMG) $(TIM2IMGARGS) -o $(BUILD_PLAT)/$(FLASH_IMAGE)
+	@$(ECHO_BLANK_LINE)
+	@echo "Built $@ successfully"
+	@$(ECHO_BLANK_LINE)
 
 clean realclean distclean: mrvl_clean
 
 .PHONY: mrvl_clean
 mrvl_clean:
 	-$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH) MV_DDR_PATH=$(MV_DDR_PATH) clean
-	-$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH)/wtptp/src/TBB_Linux -f TBB_linux.mak LIBDIR=$(CRYPTOPP_PATH) clean
+	-$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH)/wtptp/src/TBB_Linux -f TBB_linux.mak clean
 ifdef CRYPTOPP_PATH
 	-$(Q)$(MAKE) --no-print-directory -C $(CRYPTOPP_PATH) -f GNUmakefile clean
 endif
 
 else # WTP
 
-.PHONY: mrvl_flash
-mrvl_flash:
+$(BUILD_PLAT)/$(UART_IMAGE) $(BUILD_PLAT)/$(FLASH_IMAGE):
 	$(error "Platform '${PLAT}' for target '$@' requires WTP. Please set WTP to point to the right directory")
 
 endif # WTP
+
+.PHONY: mrvl_uart
+mrvl_uart: $(BUILD_PLAT)/$(UART_IMAGE)
diff --git a/plat/marvell/armada/a8k/common/a8k_common.mk b/plat/marvell/armada/a8k/common/a8k_common.mk
index b7c7d84..63cfce2 100644
--- a/plat/marvell/armada/a8k/common/a8k_common.mk
+++ b/plat/marvell/armada/a8k/common/a8k_common.mk
@@ -163,6 +163,10 @@
 	@$(DOIMAGE_LIBS_CHECK)
 	${Q}${MAKE} --no-print-directory -C ${DOIMAGEPATH}
 
-.PHONY: mrvl_flash
-mrvl_flash: ${BUILD_PLAT}/${BOOT_IMAGE} ${DOIMAGETOOL}
-	${DOIMAGETOOL} ${DOIMAGE_FLAGS} ${BUILD_PLAT}/${BOOT_IMAGE} ${BUILD_PLAT}/${FLASH_IMAGE}
+${BUILD_PLAT}/${FLASH_IMAGE}: ${ROM_BIN_EXT} ${BUILD_PLAT}/${BOOT_IMAGE} ${DOIMAGETOOL}
+	@${ECHO_BLANK_LINE}
+	@echo "Building flash image"
+	${Q}${DOIMAGETOOL} ${DOIMAGE_FLAGS} ${BUILD_PLAT}/${BOOT_IMAGE} ${BUILD_PLAT}/${FLASH_IMAGE}
+	@${ECHO_BLANK_LINE}
+	@echo "Built $@ successfully"
+	@${ECHO_BLANK_LINE}
diff --git a/plat/marvell/armada/common/marvell_common.mk b/plat/marvell/armada/common/marvell_common.mk
index e5ee710..04eb51c 100644
--- a/plat/marvell/armada/common/marvell_common.mk
+++ b/plat/marvell/armada/common/marvell_common.mk
@@ -92,7 +92,12 @@
 	@truncate -s %128K $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; }
 	@cat $(BUILD_PLAT)/$(FIP_NAME) >> $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; }
 	@truncate -s %4 $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; }
+	@$(ECHO_BLANK_LINE)
 	@echo "Built $@ successfully"
+	@$(ECHO_BLANK_LINE)
 
 .PHONY: mrvl_bootimage
 mrvl_bootimage: $(BUILD_PLAT)/$(BOOT_IMAGE)
+
+.PHONY: mrvl_flash
+mrvl_flash: $(BUILD_PLAT)/$(FLASH_IMAGE)
diff --git a/plat/nxp/common/plat_make_helper/plat_build_macros.mk b/plat/nxp/common/plat_make_helper/plat_build_macros.mk
new file mode 100644
index 0000000..bba5e36
--- /dev/null
+++ b/plat/nxp/common/plat_make_helper/plat_build_macros.mk
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2020, NXP.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+
+define	SET_NXP_MAKE_FLAG
+$1	:= yes
+$2_$1	:= yes
+endef
diff --git a/plat/qti/common/src/spmi_arb.c b/plat/qti/common/src/spmi_arb.c
index 16e85a6..4213ed1 100644
--- a/plat/qti/common/src/spmi_arb.c
+++ b/plat/qti/common/src/spmi_arb.c
@@ -10,8 +10,8 @@
 
 #include <spmi_arb.h>
 
-#define REG_APID_MAP(apid)	(0x0C440900U + 4U * i)
-#define NUM_APID		0x80
+#define REG_APID_MAP(apid)	(0x0C440900U + sizeof(uint32_t) * apid)
+#define NUM_APID		((0x1100U - 0x900U) / sizeof(uint32_t))
 
 #define PPID_MASK		(0xfffU << 8)
 
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
index cdd17bc..23f13ab 100644
--- a/services/std_svc/std_svc_setup.c
+++ b/services/std_svc/std_svc_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,6 +17,7 @@
 #include <services/spm_mm_svc.h>
 #include <services/spmd_svc.h>
 #include <services/std_svc.h>
+#include <services/trng_svc.h>
 #include <smccc_helpers.h>
 #include <tools_share/uuid.h>
 
@@ -63,6 +64,8 @@
 	sdei_init();
 #endif
 
+	trng_setup();
+
 	return ret;
 }
 
@@ -139,6 +142,13 @@
 	}
 #endif
 
+#if TRNG_SUPPORT
+	if (is_trng_fid(smc_fid)) {
+		return trng_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
+				flags);
+	}
+#endif
+
 	switch (smc_fid) {
 	case ARM_STD_SVC_CALL_COUNT:
 		/*
diff --git a/services/std_svc/trng/trng_entropy_pool.c b/services/std_svc/trng/trng_entropy_pool.c
new file mode 100644
index 0000000..ac13b1d
--- /dev/null
+++ b/services/std_svc/trng/trng_entropy_pool.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <lib/spinlock.h>
+#include <plat/common/plat_trng.h>
+
+/*
+ * # Entropy pool
+ * Note that the TRNG Firmware interface can request up to 192 bits of entropy
+ * in a single call or three 64bit words per call. We have 4 words in the pool
+ * so that when we have 1-63 bits in the pool, and we have a request for
+ * 192 bits of entropy, we don't have to throw out the leftover 1-63 bits of
+ * entropy.
+ */
+#define WORDS_IN_POOL (4)
+static uint64_t entropy[WORDS_IN_POOL];
+/* index in bits of the first bit of usable entropy */
+static uint32_t entropy_bit_index;
+/* then number of valid bits in the entropy pool */
+static uint32_t entropy_bit_size;
+
+static spinlock_t trng_pool_lock;
+
+#define BITS_PER_WORD (sizeof(entropy[0]) * 8)
+#define BITS_IN_POOL (WORDS_IN_POOL * BITS_PER_WORD)
+#define ENTROPY_MIN_WORD (entropy_bit_index / BITS_PER_WORD)
+#define ENTROPY_FREE_BIT (entropy_bit_size + entropy_bit_index)
+#define _ENTROPY_FREE_WORD (ENTROPY_FREE_BIT / BITS_PER_WORD)
+#define ENTROPY_FREE_INDEX (_ENTROPY_FREE_WORD % WORDS_IN_POOL)
+/* ENTROPY_WORD_INDEX(0) includes leftover bits in the lower bits */
+#define ENTROPY_WORD_INDEX(i) ((ENTROPY_MIN_WORD + i) % WORDS_IN_POOL)
+
+/*
+ * Fill the entropy pool until we have at least as many bits as requested.
+ * Returns true after filling the pool, and false if the entropy source is out
+ * of entropy and the pool could not be filled.
+ * Assumes locks are taken.
+ */
+static bool trng_fill_entropy(uint32_t nbits)
+{
+	while (nbits > entropy_bit_size) {
+		bool valid = plat_get_entropy(&entropy[ENTROPY_FREE_INDEX]);
+
+		if (valid) {
+			entropy_bit_size += BITS_PER_WORD;
+			assert(entropy_bit_size <= BITS_IN_POOL);
+		} else {
+			return false;
+		}
+	}
+	return true;
+}
+
+/*
+ * Pack entropy into the out buffer, filling and taking locks as needed.
+ * Returns true on success, false on failure.
+ *
+ * Note: out must have enough space for nbits of entropy
+ */
+bool trng_pack_entropy(uint32_t nbits, uint64_t *out)
+{
+	bool success = true;
+
+	spin_lock(&trng_pool_lock);
+
+	if (!trng_fill_entropy(nbits)) {
+		success = false;
+		goto out;
+	}
+
+	const unsigned int rshift = entropy_bit_index % BITS_PER_WORD;
+	const unsigned int lshift = BITS_PER_WORD - rshift;
+	const int to_fill = ((nbits + BITS_PER_WORD - 1) / BITS_PER_WORD);
+	int word_i;
+
+	for (word_i = 0; word_i < to_fill; word_i++) {
+		/*
+		 * Repack the entropy from the pool into the passed in out
+		 * buffer. This takes the lower bits from the valid upper bits
+		 * of word_i and the upper bits from the lower bits of
+		 * (word_i + 1).
+		 *
+		 * I found the following diagram useful. note: `e` represents
+		 * valid entropy, ` ` represents invalid bits (not entropy) and
+		 * `x` represents valid entropy that must not end up in the
+		 * packed word.
+		 *
+		 *          |---------entropy pool----------|
+		 * C var    |--(word_i + 1)-|----word_i-----|
+		 * bit idx  |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
+		 *          [x,x,e,e,e,e,e,e|e,e, , , , , , ]
+		 *          |   [e,e,e,e,e,e,e,e]           |
+		 *          |   |--out[word_i]--|           |
+		 *    lshift|---|               |--rshift---|
+		 *
+		 *          ==== Which is implemented as ====
+		 *
+		 *          |---------entropy pool----------|
+		 * C var    |--(word_i + 1)-|----word_i-----|
+		 * bit idx  |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
+		 *          [x,x,e,e,e,e,e,e|e,e, , , , , , ]
+		 * C expr       << lshift       >> rshift
+		 * bit idx   5 4 3 2 1 0                 7 6
+		 *          [e,e,e,e,e,e,0,0|0,0,0,0,0,0,e,e]
+		 *                ==== bit-wise or ====
+		 *                   5 4 3 2 1 0 7 6
+		 *                  [e,e,e,e,e,e,e,e]
+		 */
+		out[word_i] = 0;
+		out[word_i] |= entropy[ENTROPY_WORD_INDEX(word_i)] >> rshift;
+
+		/*
+		 * Note that a shift of 64 bits is treated as a shift of 0 bits.
+		 * When the shift amount is the same as the BITS_PER_WORD, we
+		 * don't want to include the next word of entropy, so we skip
+		 * the `|=` operation.
+		 */
+		if (lshift != BITS_PER_WORD) {
+			out[word_i] |= entropy[ENTROPY_WORD_INDEX(word_i + 1)]
+				<< lshift;
+		}
+	}
+	const uint64_t mask = ~0ULL >> (BITS_PER_WORD - (nbits % BITS_PER_WORD));
+
+	out[to_fill - 1] &= mask;
+
+	entropy_bit_index = (entropy_bit_index + nbits) % BITS_IN_POOL;
+	entropy_bit_size -= nbits;
+
+out:
+	spin_unlock(&trng_pool_lock);
+
+	return success;
+}
+
+void trng_entropy_pool_setup(void)
+{
+	int i;
+
+	for (i = 0; i < WORDS_IN_POOL; i++) {
+		entropy[i] = 0;
+	}
+	entropy_bit_index = 0;
+	entropy_bit_size = 0;
+}
diff --git a/services/std_svc/trng/trng_entropy_pool.h b/services/std_svc/trng/trng_entropy_pool.h
new file mode 100644
index 0000000..fab2367
--- /dev/null
+++ b/services/std_svc/trng/trng_entropy_pool.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TRNG_ENTROPY_POOL_H
+#define TRNG_ENTROPY_POOL_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+bool trng_pack_entropy(uint32_t nbits, uint64_t *out);
+void trng_entropy_pool_setup(void);
+
+#endif /* TRNG_ENTROPY_POOL_H */
diff --git a/services/std_svc/trng/trng_main.c b/services/std_svc/trng/trng_main.c
new file mode 100644
index 0000000..38aa649
--- /dev/null
+++ b/services/std_svc/trng/trng_main.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <arch_features.h>
+#include <lib/smccc.h>
+#include <services/trng_svc.h>
+#include <smccc_helpers.h>
+
+#include <plat/common/plat_trng.h>
+
+#include "trng_entropy_pool.h"
+
+static const uuid_t uuid_null;
+
+/* handle the RND call in SMC 32 bit mode */
+static uintptr_t trng_rnd32(uint32_t nbits, void *handle)
+{
+	uint32_t mask = ~0U;
+	uint64_t ent[2];
+
+	if (nbits == 0U || nbits > 96U) {
+		SMC_RET1(handle, TRNG_E_INVALID_PARAMS);
+	}
+
+	if (!trng_pack_entropy(nbits, &ent[0])) {
+		SMC_RET1(handle, TRNG_E_NO_ENTROPY);
+	}
+
+	if ((nbits % 32U) != 0U) {
+		mask >>= 32U - (nbits % 32U);
+	}
+
+	switch ((nbits - 1U) / 32U) {
+	case 0:
+		SMC_RET4(handle, TRNG_E_SUCCESS, 0, 0, ent[0] & mask);
+		break; /* unreachable */
+	case 1:
+		SMC_RET4(handle, TRNG_E_SUCCESS, 0, (ent[0] >> 32) & mask,
+			 ent[0] & 0xFFFFFFFF);
+		break; /* unreachable */
+	case 2:
+		SMC_RET4(handle, TRNG_E_SUCCESS, ent[1] & mask,
+			 (ent[0] >> 32) & 0xFFFFFFFF, ent[0] & 0xFFFFFFFF);
+		break; /* unreachable */
+	default:
+		SMC_RET1(handle, TRNG_E_INVALID_PARAMS);
+		break; /* unreachable */
+	}
+}
+
+/* handle the RND call in SMC 64 bit mode */
+static uintptr_t trng_rnd64(uint32_t nbits, void *handle)
+{
+	uint64_t mask = ~0ULL;
+	uint64_t ent[3];
+
+	if (nbits == 0U || nbits > 192U) {
+		SMC_RET1(handle, TRNG_E_INVALID_PARAMS);
+	}
+
+	if (!trng_pack_entropy(nbits, &ent[0])) {
+		SMC_RET1(handle, TRNG_E_NO_ENTROPY);
+	}
+
+	/* Mask off higher bits if only part of register requested */
+	if ((nbits % 64U) != 0U) {
+		mask >>= 64U - (nbits % 64U);
+	}
+
+	switch ((nbits - 1U) / 64U) {
+	case 0:
+		SMC_RET4(handle, TRNG_E_SUCCESS, 0, 0, ent[0] & mask);
+		break; /* unreachable */
+	case 1:
+		SMC_RET4(handle, TRNG_E_SUCCESS, 0, ent[1] & mask, ent[0]);
+		break; /* unreachable */
+	case 2:
+		SMC_RET4(handle, TRNG_E_SUCCESS, ent[2] & mask, ent[1], ent[0]);
+		break; /* unreachable */
+	default:
+		SMC_RET1(handle, TRNG_E_INVALID_PARAMS);
+		break; /* unreachable */
+	}
+}
+
+void trng_setup(void)
+{
+	trng_entropy_pool_setup();
+	plat_entropy_setup();
+}
+
+/* Predicate indicating that a function id is part of TRNG */
+bool is_trng_fid(uint32_t smc_fid)
+{
+	return ((smc_fid == ARM_TRNG_VERSION) ||
+		(smc_fid == ARM_TRNG_FEATURES) ||
+		(smc_fid == ARM_TRNG_GET_UUID) ||
+		(smc_fid == ARM_TRNG_RND32) ||
+		(smc_fid == ARM_TRNG_RND64));
+}
+
+uintptr_t trng_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
+			   u_register_t x3, u_register_t x4, void *cookie,
+			   void *handle, u_register_t flags)
+{
+	if (!memcmp(&plat_trng_uuid, &uuid_null, sizeof(uuid_t))) {
+		SMC_RET1(handle, TRNG_E_NOT_IMPLEMENTED);
+	}
+
+	switch (smc_fid) {
+	case ARM_TRNG_VERSION:
+		SMC_RET1(handle, MAKE_SMCCC_VERSION(
+			TRNG_VERSION_MAJOR, TRNG_VERSION_MINOR
+		));
+		break; /* unreachable */
+	case ARM_TRNG_FEATURES:
+		if (is_trng_fid((uint32_t)x1)) {
+			SMC_RET1(handle, TRNG_E_SUCCESS);
+		} else {
+			SMC_RET1(handle, TRNG_E_NOT_SUPPORTED);
+		}
+		break; /* unreachable */
+	case ARM_TRNG_GET_UUID:
+		SMC_UUID_RET(handle, plat_trng_uuid);
+		break; /* unreachable */
+	case ARM_TRNG_RND32:
+		return trng_rnd32((uint32_t)x1, handle);
+	case ARM_TRNG_RND64:
+		return trng_rnd64((uint32_t)x1, handle);
+	default:
+		WARN("Unimplemented TRNG Service Call: 0x%x\n",
+			smc_fid);
+		SMC_RET1(handle, TRNG_E_NOT_IMPLEMENTED);
+		break; /* unreachable */
+	}
+}