Merge changes I23f600b5,Icf9ffdf2,Iee7a51d1,I99afc312,I4bf8e8c0, ... into integration

* changes:
  plat/marvell/armada: cleanup MSS SRAM if used for copy
  plat/marvell: cn913x: allow CP1/CP2 mapping at BLE stage
  plat/marvell/armada/common/mss: use MSS SRAM in secure mode
  include/drivers/marvell/mochi: add detection of secure mode
  plat/marvell: fix SPD handling in dram port
  marvell: drivers: move XOR0/1 DIOB from WIN 0 to 1
  drivers/marvell/mochi: add support for cn913x in PCIe EP mode
  drivers/marvell/mochi: add missing stream IDs configurations
  plat/marvell/armada/a8k: support HW RNG by SMC
  drivers/rambus: add TRNG-IP-76 driver
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/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/arm/tzc/tzc400.c b/drivers/arm/tzc/tzc400.c
index 95a5e7f..9798ed4 100644
--- a/drivers/arm/tzc/tzc400.c
+++ b/drivers/arm/tzc/tzc400.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -162,7 +162,9 @@
 /*
  * `tzc400_configure_region` is used to program regions into the TrustZone
  * controller. A region can be associated with more than one filter. The
- * associated filters are passed in as a bitmap (bit0 = filter0).
+ * associated filters are passed in as a bitmap (bit0 = filter0), except that
+ * the value TZC_400_REGION_ATTR_FILTER_BIT_ALL selects all filters, based on
+ * the value of tzc400.num_filters.
  * NOTE:
  * Region 0 is special; it is preferable to use tzc400_configure_region0
  * for this region (see comment for that function).
@@ -176,6 +178,11 @@
 {
 	assert(tzc400.base != 0U);
 
+	/* Adjust filter mask by real filter number */
+	if (filters == TZC_400_REGION_ATTR_FILTER_BIT_ALL) {
+		filters = (1U << tzc400.num_filters) - 1U;
+	}
+
 	/* Do range checks on filters and regions. */
 	assert(((filters >> tzc400.num_filters) == 0U) &&
 	       (region < tzc400.num_regions));
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/drivers/st/fmc/stm32_fmc2_nand.c b/drivers/st/fmc/stm32_fmc2_nand.c
index a58a243..453069b 100644
--- a/drivers/st/fmc/stm32_fmc2_nand.c
+++ b/drivers/st/fmc/stm32_fmc2_nand.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
  */
@@ -200,9 +200,6 @@
 	if ((twait < NAND_TCS_MIN) && (tset_mem < (NAND_TCS_MIN - twait))) {
 		tset_mem = NAND_TCS_MIN - twait;
 	}
-	if ((twait < NAND_TALS_MIN) && (tset_mem < (NAND_TALS_MIN - twait))) {
-		tset_mem = NAND_TALS_MIN - twait;
-	}
 	if ((twait > thiz) && ((twait - thiz) < NAND_TDS_MIN) &&
 	    (tset_mem < (NAND_TDS_MIN - (twait - thiz)))) {
 		tset_mem = NAND_TDS_MIN - (twait - thiz);
@@ -244,12 +241,6 @@
 	if ((twait < NAND_TCS_MIN) && (tset_att < (NAND_TCS_MIN - twait))) {
 		tset_att = NAND_TCS_MIN - twait;
 	}
-	if ((twait < NAND_TCLS_MIN) && (tset_att < (NAND_TCLS_MIN - twait))) {
-		tset_att = NAND_TCLS_MIN - twait;
-	}
-	if ((twait < NAND_TALS_MIN) && (tset_att < (NAND_TALS_MIN - twait))) {
-		tset_att = NAND_TALS_MIN - twait;
-	}
 	if ((thold_mem < NAND_TRHW_MIN) &&
 	    (tset_att < (NAND_TRHW_MIN - thold_mem))) {
 		tset_att = NAND_TRHW_MIN - thold_mem;
diff --git a/include/drivers/arm/tzc400.h b/include/drivers/arm/tzc400.h
index 32aeb03..cf2e82b 100644
--- a/include/drivers/arm/tzc400.h
+++ b/include/drivers/arm/tzc400.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -80,11 +80,8 @@
 
 /* Filter enable bits in a TZC */
 #define TZC_400_REGION_ATTR_F_EN_MASK		U(0xf)
-#define TZC_400_REGION_ATTR_FILTER_BIT(x)				\
-				((U(1) << (x)) << TZC_REGION_ATTR_F_EN_SHIFT)
-#define TZC_400_REGION_ATTR_FILTER_BIT_ALL				\
-				(TZC_400_REGION_ATTR_F_EN_MASK <<	\
-				TZC_REGION_ATTR_F_EN_SHIFT)
+#define TZC_400_REGION_ATTR_FILTER_BIT(x)	(U(1) << (x))
+#define TZC_400_REGION_ATTR_FILTER_BIT_ALL	TZC_400_REGION_ATTR_F_EN_MASK
 
 /*
  * All TZC region configuration registers are placed one after another. It
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/lib/cpus/aarch32/cpu_helpers.S b/lib/cpus/aarch32/cpu_helpers.S
index 9b5d787..6ed800c 100644
--- a/lib/cpus/aarch32/cpu_helpers.S
+++ b/lib/cpus/aarch32/cpu_helpers.S
@@ -78,6 +78,10 @@
 	mov	r1, #CPU_PWR_DWN_OPS
 	add	r1, r1, r2, lsl #2
 	ldr	r1, [r0, r1]
+#if ENABLE_ASSERTIONS
+	cmp	r1, #0
+	ASM_ASSERT(ne)
+#endif
 	bx	r1
 endfunc prepare_cpu_pwr_dwn
 
@@ -146,6 +150,10 @@
 
 	/* Subtract the increment and offset to get the cpu-ops pointer */
 	sub	r0, r4, #(CPU_OPS_SIZE + CPU_MIDR)
+#if ENABLE_ASSERTIONS
+	cmp	r0, #0
+	ASM_ASSERT(ne)
+#endif
 error_exit:
 	bx	lr
 endfunc get_cpu_ops_ptr
@@ -224,7 +232,15 @@
 	 * function. If it's non-NULL, jump to the function in turn.
 	 */
 	bl	_cpu_data
+#if ENABLE_ASSERTIONS
+	cmp	r0, #0
+	ASM_ASSERT(ne)
+#endif
 	ldr	r1, [r0, #CPU_DATA_CPU_OPS_PTR]
+#if ENABLE_ASSERTIONS
+	cmp	r1, #0
+	ASM_ASSERT(ne)
+#endif
 	ldr	r0, [r1, #CPU_ERRATA_FUNC]
 	cmp	r0, #0
 	beq	1f
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/memset.c b/lib/libc/memset.c
index f9dd4c5..17f798c 100644
--- a/lib/libc/memset.c
+++ b/lib/libc/memset.c
@@ -10,19 +10,20 @@
 
 void *memset(void *dst, int val, size_t count)
 {
-	char *ptr = dst;
+	uint8_t *ptr = dst;
 	uint64_t *ptr64;
 	uint64_t fill = (unsigned char)val;
 
 	/* Simplify code below by making sure we write at least one byte. */
-	if (count == 0) {
+	if (count == 0U) {
 		return dst;
 	}
 
 	/* Handle the first part, until the pointer becomes 64-bit aligned. */
-	while (((uintptr_t)ptr & 7)) {
-		*ptr++ = val;
-		if (--count == 0) {
+	while (((uintptr_t)ptr & 7U) != 0U) {
+		*ptr = (uint8_t)val;
+		ptr++;
+		if (--count == 0U) {
 			return dst;
 		}
 	}
@@ -33,15 +34,17 @@
 	fill |= fill << 32;
 
 	/* Use 64-bit writes for as long as possible. */
-	ptr64 = (void *)ptr;
-	for (; count >= 8; count -= 8) {
-		*ptr64++ = fill;
+	ptr64 = (uint64_t *)ptr;
+	for (; count >= 8U; count -= 8) {
+		*ptr64 = fill;
+		ptr64++;
 	}
 
 	/* Handle the remaining part byte-per-byte. */
-	ptr = (void *)ptr64;
-	while (count--) {
-		*ptr++ = val;
+	ptr = (uint8_t *)ptr64;
+	while (count-- > 0U)  {
+		*ptr = (uint8_t)val;
+		ptr++;
 	}
 
 	return dst;
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/plat/allwinner/common/allwinner-common.mk b/plat/allwinner/common/allwinner-common.mk
index 901d888..da83b5e 100644
--- a/plat/allwinner/common/allwinner-common.mk
+++ b/plat/allwinner/common/allwinner-common.mk
@@ -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
 #
@@ -20,8 +20,6 @@
 				${AW_PLAT}/common/sunxi_common.c
 
 BL31_SOURCES		+=	drivers/allwinner/axp/common.c		\
-				drivers/allwinner/sunxi_msgbox.c	\
-				drivers/arm/css/scpi/css_scpi.c		\
 				${GICV2_SOURCES}			\
 				drivers/delay_timer/delay_timer.c	\
 				drivers/delay_timer/generic_delay_timer.c \
@@ -29,12 +27,40 @@
 				plat/common/plat_gicv2.c		\
 				plat/common/plat_psci_common.c		\
 				${AW_PLAT}/common/sunxi_bl31_setup.c	\
-				${AW_PLAT}/common/sunxi_cpu_ops.c	\
 				${AW_PLAT}/common/sunxi_pm.c		\
 				${AW_PLAT}/${PLAT}/sunxi_power.c	\
 				${AW_PLAT}/common/sunxi_security.c	\
 				${AW_PLAT}/common/sunxi_topology.c
 
+# By default, attempt to use SCPI to the ARISC management processor. If SCPI
+# is not enabled or SCP firmware is not loaded, fall back to a simpler native
+# implementation that does not support CPU or system suspend.
+#
+# If SCP firmware will always be present (or absent), the unused implementation
+# can be compiled out.
+SUNXI_PSCI_USE_NATIVE	?=	1
+SUNXI_PSCI_USE_SCPI	?=	1
+
+$(eval $(call assert_boolean,SUNXI_PSCI_USE_NATIVE))
+$(eval $(call assert_boolean,SUNXI_PSCI_USE_SCPI))
+$(eval $(call add_define,SUNXI_PSCI_USE_NATIVE))
+$(eval $(call add_define,SUNXI_PSCI_USE_SCPI))
+
+ifeq (${SUNXI_PSCI_USE_NATIVE}${SUNXI_PSCI_USE_SCPI},00)
+$(error "At least one of SCPI or native PSCI ops must be enabled")
+endif
+
+ifeq (${SUNXI_PSCI_USE_NATIVE},1)
+BL31_SOURCES		+=	${AW_PLAT}/common/sunxi_cpu_ops.c	\
+				${AW_PLAT}/common/sunxi_native_pm.c
+endif
+
+ifeq (${SUNXI_PSCI_USE_SCPI},1)
+BL31_SOURCES		+=	drivers/allwinner/sunxi_msgbox.c	\
+				drivers/arm/css/scpi/css_scpi.c		\
+				${AW_PLAT}/common/sunxi_scpi_pm.c
+endif
+
 # The bootloader is guaranteed to only run on CPU 0 by the boot ROM.
 COLD_BOOT_SINGLE_CPU		:=	1
 
diff --git a/plat/allwinner/common/include/sunxi_private.h b/plat/allwinner/common/include/sunxi_private.h
index dcf3dc9..b68d23f 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,32 @@
 #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);
 
+#if SUNXI_PSCI_USE_NATIVE
+void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops);
+#else
+static inline void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops)
+{
+}
+#endif
+#if SUNXI_PSCI_USE_SCPI
+int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops);
+#else
+static inline int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops)
+{
+	return -1;
+}
+#endif
+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));
-
-	/* 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);
+	/* 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/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;
+			return false;
+	}
 
-		/* Fill entropy buffer. */
-		for (i = 0; i < TRNG_NOUTPUTS; i++) {
-			size_t n;
-			uint32_t val;
+	/* 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;
 
-			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;
-		}
+	ret |= mmio_read_32(TRNG_BASE + 8);
+	ret ^= mmio_read_32(TRNG_BASE + 12);
+	*buf = ret;
 
-		/* Reset TRNG outputs. */
-		mmio_write_32(TRNG_BASE + TRNG_STATUS, 1);
-	}
+	/* 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 0;
+	return true;
 }
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/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/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c
index 36c3fbb..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;
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/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S b/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
index 7eab337..d8439f7 100644
--- a/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
+++ b/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
@@ -12,9 +12,6 @@
 	.globl	plat_is_my_cpu_primary
 	.globl	zynqmp_calc_core_pos
 	.globl	plat_my_core_pos
-	.globl	plat_crash_console_init
-	.globl	plat_crash_console_putc
-	.globl	plat_crash_console_flush
 	.globl	platform_mem_init
 
 	/* -----------------------------------------------------
@@ -79,45 +76,6 @@
 	ret
 endfunc zynqmp_calc_core_pos
 
-	/* ---------------------------------------------
-	 * int plat_crash_console_init(void)
-	 * Function to initialize the crash console
-	 * without a C Runtime to print crash report.
-	 * Clobber list : x0 - x4
-	 * ---------------------------------------------
-	 */
-func plat_crash_console_init
-	mov_imm	x0, ZYNQMP_CRASH_UART_BASE
-	mov_imm	x1, ZYNQMP_CRASH_UART_CLK_IN_HZ
-	mov_imm	x2, ZYNQMP_UART_BAUDRATE
-	b	console_cdns_core_init
-endfunc plat_crash_console_init
-
-	/* ---------------------------------------------
-	 * int plat_crash_console_putc(int c)
-	 * Function to print a character on the crash
-	 * console without a C Runtime.
-	 * Clobber list : x1, x2
-	 * ---------------------------------------------
-	 */
-func plat_crash_console_putc
-	mov_imm	x1, ZYNQMP_CRASH_UART_BASE
-	b	console_cdns_core_putc
-endfunc plat_crash_console_putc
-
-	/* ---------------------------------------------
-	 * void plat_crash_console_flush()
-	 * Function to force a write of all buffered
-	 * data that hasn't been output.
-	 * Out : void.
-	 * Clobber list : r0
-	 * ---------------------------------------------
-	 */
-func plat_crash_console_flush
-	mov_imm	x0, ZYNQMP_CRASH_UART_BASE
-	b	console_cdns_core_flush
-endfunc plat_crash_console_flush
-
 	/* ---------------------------------------------------------------------
 	 * We don't need to carry out any memory initialization on ARM
 	 * platforms. The Secure RAM is accessible straight away.
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index 1cd168f..6e700b9 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -73,7 +73,8 @@
 				plat/arm/common/arm_gicv2.c			\
 				plat/common/plat_gicv2.c			\
 				plat/xilinx/common/ipi.c			\
-				plat/xilinx/zynqmp/zynqmp_ipi.c		\
+				plat/xilinx/zynqmp/zynqmp_ipi.c			\
+				plat/common/aarch64/crash_console_helpers.S	\
 				plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S	\
 				plat/xilinx/zynqmp/aarch64/zynqmp_common.c