Merge changes from topic "trng-svc" into integration

* changes:
  plat/arm: juno: Use TRNG entropy source for SMCCC TRNG interface
  plat/arm: juno: Condition Juno entropy source with CRC instructions
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/iob.c b/drivers/marvell/iob.c
index 87f147a..29088aa 100644
--- a/drivers/marvell/iob.c
+++ b/drivers/marvell/iob.c
@@ -44,6 +44,10 @@
 #define IOB_WIN_ALR_OFFSET(win)		(iob_base + 0x8 + (0x20 * win))
 #define IOB_WIN_AHR_OFFSET(win)		(iob_base + 0xC + (0x20 * win))
 
+#define IOB_WIN_DIOB_CR_OFFSET(win)	(iob_base + 0x10 + (0x20 * win))
+#define IOB_WIN_XOR0_DIOB_EN		BIT(0)
+#define IOB_WIN_XOR1_DIOB_EN		BIT(1)
+
 uintptr_t iob_base;
 
 static void iob_win_check(struct addr_map_win *win, uint32_t win_num)
@@ -71,6 +75,17 @@
 	uint32_t iob_win_reg;
 	uint32_t alr, ahr;
 	uint64_t end_addr;
+	uint32_t reg_en;
+
+	/* move XOR (DMA) to use WIN1 which is used for PCI-EP address space */
+	reg_en = IOB_WIN_XOR0_DIOB_EN | IOB_WIN_XOR1_DIOB_EN;
+	iob_win_reg = mmio_read_32(IOB_WIN_DIOB_CR_OFFSET(0));
+	iob_win_reg &= ~reg_en;
+	mmio_write_32(IOB_WIN_DIOB_CR_OFFSET(0), iob_win_reg);
+
+	iob_win_reg = mmio_read_32(IOB_WIN_DIOB_CR_OFFSET(1));
+	iob_win_reg |= reg_en;
+	mmio_write_32(IOB_WIN_DIOB_CR_OFFSET(1), iob_win_reg);
 
 	end_addr = (win->base_addr + win->win_size - 1);
 	alr = (uint32_t)((win->base_addr >> ADDRESS_SHIFT) & ADDRESS_MASK);
diff --git a/drivers/marvell/mochi/ap807_setup.c b/drivers/marvell/mochi/ap807_setup.c
index 1069f8c..75e9654 100644
--- a/drivers/marvell/mochi/ap807_setup.c
+++ b/drivers/marvell/mochi/ap807_setup.c
@@ -15,8 +15,9 @@
 #include <drivers/marvell/mci.h>
 #include <drivers/marvell/mochi/ap_setup.h>
 #include <lib/mmio.h>
+#include <lib/utils_def.h>
 
-#include <mvebu_def.h>
+#include <a8k_plat_def.h>
 
 #define SMMU_sACR				(MVEBU_SMMU_BASE + 0x10)
 #define SMMU_sACR_PG_64K			(1 << 16)
@@ -71,6 +72,23 @@
 #define MVEBU_AXI_ATTR_REG(index)		(MVEBU_AXI_ATTR_BASE + \
 							0x4 * index)
 
+#define XOR_STREAM_ID_REG(ch)	(MVEBU_REGS_BASE + 0x410010 + (ch) * 0x20000)
+#define XOR_STREAM_ID_MASK	0xFFFF
+#define SDIO_STREAM_ID_REG	(MVEBU_RFU_BASE + 0x4600)
+#define SDIO_STREAM_ID_MASK	0xFF
+
+/* Do not use the default Stream ID 0 */
+#define A807_STREAM_ID_BASE	(0x1)
+
+static uintptr_t stream_id_reg[] = {
+	XOR_STREAM_ID_REG(0),
+	XOR_STREAM_ID_REG(1),
+	XOR_STREAM_ID_REG(2),
+	XOR_STREAM_ID_REG(3),
+	SDIO_STREAM_ID_REG,
+	0
+};
+
 enum axi_attr {
 	AXI_SDIO_ATTR = 0,
 	AXI_DFX_ATTR,
@@ -162,6 +180,21 @@
 				  MCI_REMAP_OFF_SHIFT);
 }
 
+/* Set a unique stream id for all DMA capable devices */
+static void ap807_stream_id_init(void)
+{
+	uint32_t i;
+
+	for (i = 0;
+	     stream_id_reg[i] != 0 && i < ARRAY_SIZE(stream_id_reg); i++) {
+		uint32_t mask = stream_id_reg[i] == SDIO_STREAM_ID_REG ?
+				SDIO_STREAM_ID_MASK : XOR_STREAM_ID_MASK;
+
+		mmio_clrsetbits_32(stream_id_reg[i], mask,
+				   i + A807_STREAM_ID_BASE);
+	}
+}
+
 static void ap807_axi_attr_init(void)
 {
 	uint32_t index, data;
@@ -265,6 +298,9 @@
 	/* configure CCU windows */
 	init_ccu(MVEBU_AP0);
 
+	/* Set the stream IDs for DMA masters */
+	ap807_stream_id_init();
+
 	/* configure the SMMU */
 	setup_smmu();
 
diff --git a/drivers/marvell/mochi/apn806_setup.c b/drivers/marvell/mochi/apn806_setup.c
index 8c3ba92..5c71fed 100644
--- a/drivers/marvell/mochi/apn806_setup.c
+++ b/drivers/marvell/mochi/apn806_setup.c
@@ -15,7 +15,7 @@
 #include <drivers/marvell/mochi/ap_setup.h>
 #include <lib/mmio.h>
 
-#include <mvebu_def.h>
+#include <a8k_plat_def.h>
 
 #define SMMU_sACR				(MVEBU_SMMU_BASE + 0x10)
 #define SMMU_sACR_PG_64K			(1 << 16)
@@ -67,6 +67,23 @@
 #define MVEBU_AXI_ATTR_REG(index)		(MVEBU_AXI_ATTR_BASE + \
 							0x4 * index)
 
+#define XOR_STREAM_ID_REG(ch)	(MVEBU_REGS_BASE + 0x410010 + (ch) * 0x20000)
+#define XOR_STREAM_ID_MASK	0xFFFF
+#define SDIO_STREAM_ID_REG	(MVEBU_RFU_BASE + 0x4600)
+#define SDIO_STREAM_ID_MASK	0xFF
+
+/* Do not use the default Stream ID 0 */
+#define A806_STREAM_ID_BASE	(0x1)
+
+static uintptr_t stream_id_reg[] = {
+	XOR_STREAM_ID_REG(0),
+	XOR_STREAM_ID_REG(1),
+	XOR_STREAM_ID_REG(2),
+	XOR_STREAM_ID_REG(3),
+	SDIO_STREAM_ID_REG,
+	0
+};
+
 enum axi_attr {
 	AXI_SDIO_ATTR = 0,
 	AXI_DFX_ATTR,
@@ -158,6 +175,20 @@
 			      MCI_REMAP_OFF_SHIFT);
 }
 
+/* Set a unique stream id for all DMA capable devices */
+static void ap806_stream_id_init(void)
+{
+	int i;
+
+	for (i = 0; stream_id_reg[i] != 0; i++) {
+		uint32_t mask = stream_id_reg[i] == SDIO_STREAM_ID_REG ?
+				SDIO_STREAM_ID_MASK : XOR_STREAM_ID_MASK;
+
+		mmio_clrsetbits_32(stream_id_reg[i], mask,
+				   i + A806_STREAM_ID_BASE);
+	}
+}
+
 static void apn806_axi_attr_init(void)
 {
 	uint32_t index, data;
@@ -236,6 +267,9 @@
 	/* configure DSS */
 	dss_setup();
 
+	/* Set the stream IDs for DMA masters */
+	ap806_stream_id_init();
+
 	/* configure the SMMU */
 	setup_smmu();
 
diff --git a/drivers/marvell/mochi/cp110_setup.c b/drivers/marvell/mochi/cp110_setup.c
index 0fa0497..906df66 100644
--- a/drivers/marvell/mochi/cp110_setup.c
+++ b/drivers/marvell/mochi/cp110_setup.c
@@ -12,6 +12,7 @@
 #include <drivers/marvell/amb_adec.h>
 #include <drivers/marvell/iob.h>
 #include <drivers/marvell/mochi/cp110_setup.h>
+#include <drivers/rambus/trng_ip_76.h>
 
 #include <plat_marvell.h>
 
@@ -105,6 +106,11 @@
 #define MVEBU_RTC_READ_OUTPUT_DELAY_MASK		0xFFFF
 #define MVEBU_RTC_READ_OUTPUT_DELAY_DEFAULT		0x1F
 
+/*******************************************************************************
+ * TRNG Configuration
+ ******************************************************************************/
+#define MVEBU_TRNG_BASE					(0x760000)
+
 enum axi_attr {
 	AXI_ADUNIT_ATTR = 0,
 	AXI_COMUNIT_ATTR,
@@ -130,7 +136,7 @@
 #define USB3H_1_STREAM_ID_REG	(RFU_STREAM_ID_BASE + 0x10)
 #define SATA_0_STREAM_ID_REG	(RFU_STREAM_ID_BASE + 0x14)
 #define SATA_1_STREAM_ID_REG	(RFU_STREAM_ID_BASE + 0x18)
-#define SDIO_0_STREAM_ID_REG	(RFU_STREAM_ID_BASE + 0x28)
+#define SDIO_STREAM_ID_REG	(RFU_STREAM_ID_BASE + 0x28)
 
 #define CP_DMA_0_STREAM_ID_REG  (0x6B0010)
 #define CP_DMA_1_STREAM_ID_REG  (0x6D0010)
@@ -138,14 +144,14 @@
 /* We allocate IDs 128-255 for PCIe */
 #define MAX_STREAM_ID		(0x80)
 
-uintptr_t stream_id_reg[] = {
+static uintptr_t stream_id_reg[] = {
 	USB3H_0_STREAM_ID_REG,
 	USB3H_1_STREAM_ID_REG,
 	CP_DMA_0_STREAM_ID_REG,
 	CP_DMA_1_STREAM_ID_REG,
 	SATA_0_STREAM_ID_REG,
 	SATA_1_STREAM_ID_REG,
-	SDIO_0_STREAM_ID_REG,
+	SDIO_STREAM_ID_REG,
 	0
 };
 
@@ -180,8 +186,9 @@
 	pcie0_clk = (reg & SAR_PCIE0_CLK_CFG_MASK) >> SAR_PCIE0_CLK_CFG_OFFSET;
 	pcie1_clk = (reg & SAR_PCIE1_CLK_CFG_MASK) >> SAR_PCIE1_CLK_CFG_OFFSET;
 
-	/* CP110 revision A2 */
-	if (cp110_rev_id_get(base) == MVEBU_CP110_REF_ID_A2) {
+	/* CP110 revision A2 or CN913x */
+	if (cp110_rev_id_get(base) == MVEBU_CP110_REF_ID_A2 ||
+	    cp110_device_id_get(base) == MVEBU_CN9130_DEV_ID) {
 		/*
 		 * PCIe Reference Clock Buffer Control register must be
 		 * set according to the clock direction (input/output)
@@ -378,6 +385,20 @@
 	init_amb_adec(base);
 }
 
+static void cp110_trng_init(uintptr_t base)
+{
+	static bool done;
+	int ret;
+
+	if (!done) {
+		ret = eip76_rng_probe(base + MVEBU_TRNG_BASE);
+		if (ret != 0) {
+			ERROR("Failed to init TRNG @ 0x%lx\n", base);
+			return;
+		}
+		done = true;
+	}
+}
 void cp110_init(uintptr_t cp110_base, uint32_t stream_id)
 {
 	INFO("%s: Initialize CPx - base = %lx\n", __func__, cp110_base);
@@ -405,6 +426,9 @@
 
 	/* Reset RTC if needed */
 	cp110_rtc_init(cp110_base);
+
+	/* TRNG init - for CP0 only */
+	cp110_trng_init(cp110_base);
 }
 
 /* Do the minimal setup required to configure the CP in BLE */
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/rambus/trng_ip_76.c b/drivers/rambus/trng_ip_76.c
new file mode 100644
index 0000000..8de12e9
--- /dev/null
+++ b/drivers/rambus/trng_ip_76.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2020, Marvell Technology Group Ltd. All rights reserved.
+ *
+ * Based on Linux kernel omap-rng.c - RNG driver for TI OMAP CPU family
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * Mostly based on original driver:
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/rambus/trng_ip_76.h>
+#include <lib/mmio.h>
+#include <lib/spinlock.h>
+#include <lib/utils.h>
+
+#define RNG_REG_STATUS_RDY			(1 << 0)
+
+#define RNG_REG_INTACK_RDY_MASK			(1 << 0)
+
+#define RNG_CONTROL_ENABLE_TRNG_MASK		(1 << 10)
+
+#define RNG_CONFIG_NOISE_BLOCKS(val)		((0xff & (val)) << 0)
+#define RNG_CONFIG_NOISE_BLK_VAL		0x5
+
+#define RNG_CONFIG_SAMPLE_CYCLES(val)		((0xff & (val)) << 16)
+#define RNG_CONFIG_SAMPLE_CYCLES_VAL		0x22
+
+#define RNG_REG_FRO_ENABLE_MASK			0xffffff
+#define RNG_REG_FRO_DETUNE_MASK			0x0
+
+#define EIP76_RNG_OUTPUT_SIZE			0x10
+#define EIP76_RNG_WAIT_ROUNDS			10
+
+#define RNG_HW_IS_EIP76(ver)			((ver) & (0xff == 0x4C))
+#define RNG_HW_VER_MAJOR(ver)			(((ver) & (0xf << 24)) >> 24)
+#define RNG_HW_VER_MINOR(ver)			(((ver) & (0xf << 20)) >> 20)
+#define RNG_HW_VER_PATCH(ver)			(((ver) & (0xf << 16)) >> 16)
+
+
+enum {
+	RNG_OUTPUT_0_REG = 0,
+	RNG_OUTPUT_1_REG,
+	RNG_OUTPUT_2_REG,
+	RNG_OUTPUT_3_REG,
+	RNG_STATUS_REG,
+	RNG_INTMASK_REG,
+	RNG_INTACK_REG,
+	RNG_CONTROL_REG,
+	RNG_CONFIG_REG,
+	RNG_ALARMCNT_REG,
+	RNG_FROENABLE_REG,
+	RNG_FRODETUNE_REG,
+	RNG_ALARMMASK_REG,
+	RNG_ALARMSTOP_REG,
+	RNG_REV_REG
+};
+
+static uint16_t reg_map_eip76[] = {
+	[RNG_OUTPUT_0_REG]	= 0x0,
+	[RNG_OUTPUT_1_REG]	= 0x4,
+	[RNG_OUTPUT_2_REG]	= 0x8,
+	[RNG_OUTPUT_3_REG]	= 0xc,
+	[RNG_STATUS_REG]	= 0x10,
+	[RNG_INTACK_REG]	= 0x10,
+	[RNG_CONTROL_REG]	= 0x14,
+	[RNG_CONFIG_REG]	= 0x18,
+	[RNG_ALARMCNT_REG]	= 0x1c,
+	[RNG_FROENABLE_REG]	= 0x20,
+	[RNG_FRODETUNE_REG]	= 0x24,
+	[RNG_ALARMMASK_REG]	= 0x28,
+	[RNG_ALARMSTOP_REG]	= 0x2c,
+	[RNG_REV_REG]		= 0x7c,
+};
+
+struct eip76_rng_dev {
+	uintptr_t	base;
+	uint16_t	*regs;
+};
+
+/* Locals */
+static struct eip76_rng_dev eip76_dev;
+static spinlock_t rng_lock;
+
+static inline uint32_t eip76_rng_read(struct eip76_rng_dev *dev, uint16_t reg)
+{
+	return mmio_read_32(dev->base + dev->regs[reg]);
+}
+
+static inline void eip76_rng_write(struct eip76_rng_dev *dev,
+				   uint16_t reg, uint32_t val)
+{
+	mmio_write_32(dev->base + dev->regs[reg], val);
+}
+
+static void eip76_rng_init(struct eip76_rng_dev *dev)
+{
+	uint32_t val;
+
+	/* Return if RNG is already running. */
+	if (eip76_rng_read(dev, RNG_CONTROL_REG) &
+			   RNG_CONTROL_ENABLE_TRNG_MASK) {
+		return;
+	}
+
+	/*  This field sets the number of 512-bit blocks of raw Noise Source
+	 * output data that must be processed by either the Conditioning
+	 * Function or the SP 800-90 DRBG ‘BC_DF’ functionality to yield
+	 * a ‘full entropy’ output value. As according to [SP 800-90B draft]
+	 * the amount of entropy input to this functionality must be twice
+	 * the amount that is output and the 8-bit samples output by the Noise
+	 * Source are supposed to have one bit of entropy each, the settings
+	 * for this field are as follows:
+	 * - SHA-1 Conditioning Function:
+	 *  generates 160 bits output, requiring 2560 sample bits,
+	 *  equivalent to 5 blocks of raw Noise Source input.
+	 * - SHA-256 Conditioning Function:
+	 *  generates 256 bits output, requiring 4096 sample bits, equivalent
+	 *  to 8 blocks of raw Noise Source input. Note that two blocks of 256
+	 *  bits are needed to start or re-seed the SP 800-90 DRBG
+	 *  (in the EIP-76d-*-SHA2 configurations)
+	 * - SP 800-90 DRBG ‘BC_DF’ functionality:
+	 *  generates 384 bits output, requiring 6144 sample bits, equivalent
+	 *  to 12 blocks of raw Noise Source input.
+	 *  This field can only be modified when ‘enable_trng’ in TRNG_CONTROL
+	 *  is ‘0’ or when either of the ‘test_known_noise’ or ‘test_cond_func’
+	 *  bits in TRNG_TEST is ‘1’. Value 0 in this field selects 256 blocks
+	 *  of 512 bits to be processed.
+	 */
+	val = RNG_CONFIG_NOISE_BLOCKS(RNG_CONFIG_NOISE_BLK_VAL);
+
+	/* This field sets the number of FRO samples that are XOR-ed together
+	 * into one bit to be shifted into the main shift register.
+	 * This value must be such that there is at least one bit of entropy
+	 * (in total) in each 8 bits that are shifted.
+	 * This field can only be modified when ‘enable_trng’ in TRNG_CONTROL
+	 * is ‘0’ or when either of the ‘test_known_noise’ or ‘test_cond_func’
+	 * bits in TRNG_TEST is ‘1’. Value 0 in this field selects 65536 FRO
+	 * samples to be XOR-ed together
+	 */
+	val |= RNG_CONFIG_SAMPLE_CYCLES(RNG_CONFIG_SAMPLE_CYCLES_VAL);
+	eip76_rng_write(dev, RNG_CONFIG_REG, val);
+
+	/* Enable all available FROs */
+	eip76_rng_write(dev, RNG_FRODETUNE_REG, RNG_REG_FRO_DETUNE_MASK);
+	eip76_rng_write(dev, RNG_FROENABLE_REG, RNG_REG_FRO_ENABLE_MASK);
+
+	/* Enable TRNG */
+	eip76_rng_write(dev, RNG_CONTROL_REG, RNG_CONTROL_ENABLE_TRNG_MASK);
+}
+
+int32_t eip76_rng_read_rand_buf(void *data, bool wait)
+{
+	uint32_t i, present;
+
+	if (!eip76_dev.base) /* not initialized */
+		return -1;
+
+	for (i = 0; i < EIP76_RNG_WAIT_ROUNDS; i++) {
+		present = eip76_rng_read(&eip76_dev, RNG_STATUS_REG) &
+					 RNG_REG_STATUS_RDY;
+		if (present || !wait) {
+			break;
+		}
+
+		udelay(10);
+	}
+
+	if (present != 0U) {
+		return 0;
+	}
+
+	memcpy(data,
+	       (void *)(eip76_dev.base + eip76_dev.regs[RNG_OUTPUT_0_REG]),
+	       EIP76_RNG_OUTPUT_SIZE);
+
+	eip76_rng_write(&eip76_dev, RNG_INTACK_REG, RNG_REG_INTACK_RDY_MASK);
+
+	return EIP76_RNG_OUTPUT_SIZE;
+}
+
+int32_t eip76_rng_probe(uintptr_t base_addr)
+{
+	uint32_t ver;
+
+	eip76_dev.base = base_addr;
+	eip76_dev.regs = reg_map_eip76;
+
+	eip76_rng_init(&eip76_dev);
+
+	ver = eip76_rng_read(&eip76_dev, RNG_REV_REG);
+
+	INFO("%s Random Number Generator HW ver. %01x.%01x.%01x\n",
+	     RNG_HW_IS_EIP76(ver) ? "TRNG-IP-76" : "Unknown",
+	     RNG_HW_VER_MAJOR(ver), RNG_HW_VER_MINOR(ver),
+	     RNG_HW_VER_PATCH(ver));
+
+	return 0;
+}
+
+int32_t eip76_rng_get_random(uint8_t *data, uint32_t len)
+{
+	static uint8_t rand[EIP76_RNG_OUTPUT_SIZE];
+	static uint8_t pos;
+	uint32_t i;
+	int32_t ret = 0;
+
+	if (!data)
+		return -1;
+
+	spin_lock(&rng_lock);
+
+	for (i = 0; i < len; i++) {
+		if (pos >= EIP76_RNG_OUTPUT_SIZE) {
+			pos = 0;
+		}
+
+		if (pos != 0U) {
+			ret = eip76_rng_read_rand_buf(rand, true);
+		}
+
+		/* Only advance FIFO index if it is non zero or
+		 * the update from TRNG HW was successful
+		 */
+		if (pos || ret > 0) {
+			data[i] = rand[pos++];
+			ret = 0;
+		} else {
+			ret = -1;
+			break;
+		}
+	}
+
+	spin_unlock(&rng_lock);
+
+	return ret;
+}
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/drivers/marvell/mochi/cp110_setup.h b/include/drivers/marvell/mochi/cp110_setup.h
index 11dc4e0..4a69257 100644
--- a/include/drivers/marvell/mochi/cp110_setup.h
+++ b/include/drivers/marvell/mochi/cp110_setup.h
@@ -31,6 +31,9 @@
 #define MAX_STREAM_ID_PER_CP		(0x10)
 #define STREAM_ID_BASE			(0x40)
 
+#define MVEBU_SECUREBOOT_CTRL_REG	(MVEBU_RFU_BASE + 0x4730)
+#define MVEBU_SECUREBOOT_EN_MASK	BIT(0)
+
 static inline uint32_t cp110_device_id_get(uintptr_t base)
 {
 	/* Returns:
@@ -50,6 +53,12 @@
 		MVEBU_DEVICE_REV_OFFSET;
 }
 
+static inline uint32_t is_secure(void)
+{
+	return !!(mmio_read_32(MVEBU_SECUREBOOT_CTRL_REG) &
+			       MVEBU_SECUREBOOT_EN_MASK);
+}
+
 void cp110_init(uintptr_t cp110_base, uint32_t stream_id);
 void cp110_ble_init(uintptr_t cp110_base);
 void cp110_amb_init(uintptr_t base);
diff --git a/include/drivers/rambus/trng_ip_76.h b/include/drivers/rambus/trng_ip_76.h
new file mode 100644
index 0000000..6de8fc7
--- /dev/null
+++ b/include/drivers/rambus/trng_ip_76.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020, Marvell Technology Group Ltd. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#ifndef __TRNG_IP_76_H__
+#define __TRNG_IP_76_H__
+
+#include <stdbool.h>
+#include <stdint.h>
+
+int32_t eip76_rng_read_rand_buf(void *data, bool wait);
+int32_t eip76_rng_probe(uintptr_t base_addr);
+int32_t eip76_rng_get_random(uint8_t *data, uint32_t len);
+
+#endif /* __TRNG_IP_76_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/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/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));
+	/* 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/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/marvell/armada/a8k/a80x0/board/dram_port.c b/plat/marvell/armada/a8k/a80x0/board/dram_port.c
index 381c871..47bc0a8 100644
--- a/plat/marvell/armada/a8k/a80x0/board/dram_port.c
+++ b/plat/marvell/armada/a8k/a80x0/board/dram_port.c
@@ -138,7 +138,7 @@
 		i2c_init((void *)MVEBU_CP0_I2C_BASE);
 
 		/* select SPD memory page 0 to access DRAM configuration */
-		i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 1);
+		i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
 
 		/* read data from spd */
 		i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
diff --git a/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c b/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c
index 50a68b3..85c931c 100644
--- a/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c
+++ b/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c
@@ -123,7 +123,7 @@
 		/* initialize the i2c */
 		i2c_init((void *)MVEBU_CP0_I2C_BASE);
 		/* select SPD memory page 0 to access DRAM configuration */
-		i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 1);
+		i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
 		/* read data from spd */
 		i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
 			 sizeof(tm->spd_data.all_bytes));
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c b/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c
index 3879c98..1d8e9d2 100644
--- a/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c
@@ -132,7 +132,7 @@
 		/* initialize the MVEBU_AP_I2C_BASE I2C bus */
 		i2c_init((void *)MVEBU_AP_I2C_BASE);
 		/* select SPD memory page 0 to access DRAM configuration */
-		i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 1);
+		i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
 		/* read data from spd */
 		i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
 			 sizeof(tm->spd_data.all_bytes));
diff --git a/plat/marvell/armada/a8k/common/a8k_common.mk b/plat/marvell/armada/a8k/common/a8k_common.mk
index 63cfce2..8a463ea 100644
--- a/plat/marvell/armada/a8k/common/a8k_common.mk
+++ b/plat/marvell/armada/a8k/common/a8k_common.mk
@@ -114,7 +114,8 @@
 				$(MARVELL_DRV_BASE)/cache_llc.c	\
 				$(MARVELL_DRV_BASE)/comphy/phy-comphy-cp110.c \
 				$(MARVELL_DRV_BASE)/mc_trustzone/mc_trustzone.c \
-				$(MARVELL_DRV_BASE)/mg_conf_cm3/mg_conf_cm3.c
+				$(MARVELL_DRV_BASE)/mg_conf_cm3/mg_conf_cm3.c \
+				drivers/rambus/trng_ip_76.c
 
 BL31_PORTING_SOURCES	:=	$(BOARD_DIR)/board/marvell_plat_config.c
 
diff --git a/plat/marvell/armada/a8k/common/ble/ble.mk b/plat/marvell/armada/a8k/common/ble/ble.mk
index 78c62a0..d6d72c1 100644
--- a/plat/marvell/armada/a8k/common/ble/ble.mk
+++ b/plat/marvell/armada/a8k/common/ble/ble.mk
@@ -13,6 +13,7 @@
 BLE_SOURCES		+= 	$(BLE_PATH)/ble_main.c				\
 				$(BLE_PATH)/ble_mem.S				\
 				drivers/delay_timer/delay_timer.c		\
+				drivers/marvell/iob.c				\
 				$(PLAT_MARVELL)/common/aarch64/marvell_helpers.S \
 				$(PLAT_MARVELL)/common/plat_delay_timer.c	\
 				$(PLAT_MARVELL)/common/marvell_console.c
diff --git a/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c b/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c
index b919cb3..71fa2b8 100644
--- a/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c
+++ b/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c
@@ -30,6 +30,10 @@
 #define MSS_EXTERNAL_ADDR_MASK		0xfffffff
 #define MSS_INTERNAL_ACCESS_BIT		28
 
+#define MSS_AP_REGS_OFFSET		0x580000
+#define MSS_CP_SRAM_OFFSET		0x220000
+#define MSS_CP_REGS_OFFSET		0x280000
+
 struct addr_map_win ccu_mem_map[] = {
 	{MVEBU_CP_REGS_BASE(0), 0x4000000, IO_0_TID}
 };
@@ -121,12 +125,21 @@
 
 uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx)
 {
-	return MVEBU_CP_REGS_BASE(cp_idx) + 0x280000;
+	return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_REGS_OFFSET;
+}
+
+uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx)
+{
+	if (is_secure()) {
+		return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_SRAM_OFFSET;
+	}
+
+	return 0; /* SRAM will not be used */
 }
 
 uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx)
 {
-	return MVEBU_REGS_BASE + 0x580000;
+	return MVEBU_REGS_BASE + MSS_AP_REGS_OFFSET;
 }
 
 uint32_t bl2_plat_get_cp_count(int ap_idx)
diff --git a/plat/marvell/armada/a8k/common/plat_ble_setup.c b/plat/marvell/armada/a8k/common/plat_ble_setup.c
index e4e09fb..4114327 100644
--- a/plat/marvell/armada/a8k/common/plat_ble_setup.c
+++ b/plat/marvell/armada/a8k/common/plat_ble_setup.c
@@ -720,7 +720,7 @@
 
 int ble_plat_setup(int *skip)
 {
-	int ret;
+	int ret, cp;
 	unsigned int freq_mode;
 
 	/* Power down unused CPUs */
@@ -745,6 +745,10 @@
 	/* Do required CP-110 setups for BLE stage */
 	cp110_ble_init(MVEBU_CP_REGS_BASE(0));
 
+	/* Config address for each cp other than cp0 */
+	for (cp = 1; cp < CP_COUNT; cp++)
+		update_cp110_default_win(cp);
+
 	/* Setup AVS */
 	ble_plat_svc_config();
 
diff --git a/plat/marvell/armada/common/mrvl_sip_svc.c b/plat/marvell/armada/common/mrvl_sip_svc.c
index 0291024..64187fb 100644
--- a/plat/marvell/armada/common/mrvl_sip_svc.c
+++ b/plat/marvell/armada/common/mrvl_sip_svc.c
@@ -9,6 +9,7 @@
 #include <common/runtime_svc.h>
 #include <drivers/marvell/cache_llc.h>
 #include <drivers/marvell/mochi/ap_setup.h>
+#include <drivers/rambus/trng_ip_76.h>
 #include <lib/smccc.h>
 
 #include <marvell_plat_priv.h>
@@ -37,6 +38,9 @@
 #define MV_SIP_PMU_IRQ_ENABLE	0x82000012
 #define MV_SIP_PMU_IRQ_DISABLE	0x82000013
 
+/* TRNG */
+#define MV_SIP_RNG_64		0xC200FF11
+
 #define MAX_LANE_NR		6
 #define MVEBU_COMPHY_OFFSET	0x441000
 #define MVEBU_CP_BASE_MASK	(~0xffffff)
@@ -68,6 +72,7 @@
 			       u_register_t flags)
 {
 	u_register_t ret;
+	uint32_t w2[2] = {0, 0};
 	int i;
 
 	debug("%s: got SMC (0x%x) x1 0x%lx, x2 0x%lx, x3 0x%lx\n",
@@ -131,7 +136,9 @@
 		mvebu_pmu_interrupt_disable();
 		SMC_RET1(handle, 0);
 #endif
-
+	case MV_SIP_RNG_64:
+		ret = eip76_rng_get_random((uint8_t *)&w2, 4 * (x1 % 2 + 1));
+		SMC_RET3(handle, ret, w2[0], w2[1]);
 	default:
 		ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
 		SMC_RET1(handle, SMC_UNK);
diff --git a/plat/marvell/armada/common/mss/mss_scp_bl2_format.h b/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
index 74dddc6..90913b0 100644
--- a/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
+++ b/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
@@ -13,6 +13,7 @@
 #define HEADER_VERSION	0x1
 
 #define MSS_IDRAM_SIZE	0x10000 /* 64KB */
+#define MSS_SRAM_SIZE	0x8000 /* 32KB */
 
 /* Types definitions */
 typedef struct file_header {
diff --git a/plat/marvell/armada/common/mss/mss_scp_bootloader.c b/plat/marvell/armada/common/mss/mss_scp_bootloader.c
index adf570e..f669a77 100644
--- a/plat/marvell/armada/common/mss/mss_scp_bootloader.c
+++ b/plat/marvell/armada/common/mss/mss_scp_bootloader.c
@@ -38,6 +38,8 @@
 #define MSS_DMA_TIMEOUT			1000
 #define MSS_EXTERNAL_SPACE		0x50000000
 #define MSS_EXTERNAL_ADDR_MASK		0xfffffff
+#define MSS_INTERNAL_SPACE		0x40000000
+#define MSS_INTERNAL_ADDR_MASK		0x00ffffff
 
 #define DMA_SIZE			128
 
@@ -60,60 +62,113 @@
 	return 0;
 }
 
-static int mss_image_load(uint32_t src_addr, uint32_t size, uintptr_t mss_regs)
+static int mss_iram_dma_load(uint32_t src_addr, uint32_t size,
+			     uintptr_t mss_regs)
 {
 	uint32_t i, loop_num, timeout;
 
+	/* load image to MSS RAM using DMA */
+	loop_num = (size / DMA_SIZE) + !!(size % DMA_SIZE);
+	for (i = 0; i < loop_num; i++) {
+		/* write source address */
+		mmio_write_32(MSS_DMA_SRCBR(mss_regs),
+			      src_addr + (i * DMA_SIZE));
+		/* write destination address */
+		mmio_write_32(MSS_DMA_DSTBR(mss_regs), (i * DMA_SIZE));
+		/* make sure DMA data is ready before triggering it */
+		dsb();
+		/* set the DMA control register */
+		mmio_write_32(MSS_DMA_CTRLR(mss_regs),
+			      ((MSS_DMA_CTRLR_REQ_SET <<
+				MSS_DMA_CTRLR_REQ_OFFSET) |
+			      (DMA_SIZE << MSS_DMA_CTRLR_SIZE_OFFSET)));
+		/* Poll DMA_ACK at MSS_DMACTLR until it is ready */
+		timeout = MSS_DMA_TIMEOUT;
+		while (timeout > 0U) {
+			if ((mmio_read_32(MSS_DMA_CTRLR(mss_regs)) >>
+					  (MSS_DMA_CTRLR_ACK_OFFSET &
+					   MSS_DMA_CTRLR_ACK_MASK))
+					  == MSS_DMA_CTRLR_ACK_READY) {
+				break;
+			}
+			udelay(50);
+			timeout--;
+		}
+		if (timeout == 0) {
+			ERROR("\nMSS DMA failed (timeout)\n");
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int mss_image_load(uint32_t src_addr, uint32_t size,
+			  uintptr_t mss_regs, uintptr_t sram)
+{
+	uint32_t chunks = 1; /* !sram case */
+	uint32_t chunk_num;
+	int ret;
+
 	/* Check if the img size is not bigger than ID-RAM size of MSS CM3 */
 	if (size > MSS_IDRAM_SIZE) {
 		ERROR("image is too big to fit into MSS CM3 memory\n");
 		return 1;
 	}
 
-	NOTICE("Loading MSS image from addr. 0x%x Size 0x%x to MSS at 0x%lx\n",
-	       src_addr, size, mss_regs);
-	/* load image to MSS RAM using DMA */
-	loop_num = (size / DMA_SIZE) + (((size & (DMA_SIZE - 1)) == 0) ? 0 : 1);
+	/* The CPx MSS DMA cannot access DRAM directly in secure boot mode
+	 * Copy the MSS FW image to MSS SRAM by the CPU first, then run
+	 * MSS DMA for SRAM to IRAM copy
+	 */
+	if (sram != 0) {
+		chunks = size / MSS_SRAM_SIZE + !!(size % MSS_SRAM_SIZE);
+	}
 
-	for (i = 0; i < loop_num; i++) {
-		/* write destination and source addresses */
-		mmio_write_32(MSS_DMA_SRCBR(mss_regs),
-			      MSS_EXTERNAL_SPACE |
-			      ((src_addr & MSS_EXTERNAL_ADDR_MASK) +
-			      (i * DMA_SIZE)));
-		mmio_write_32(MSS_DMA_DSTBR(mss_regs), (i * DMA_SIZE));
+	NOTICE("%s Loading MSS FW from addr. 0x%x Size 0x%x to MSS at 0x%lx\n",
+	       sram == 0 ? "" : "SECURELY", src_addr, size, mss_regs);
+	for (chunk_num = 0; chunk_num < chunks; chunk_num++) {
+		size_t chunk_size = size;
+		uint32_t img_src = MSS_EXTERNAL_SPACE | /* no SRAM */
+				   (src_addr & MSS_EXTERNAL_ADDR_MASK);
 
-		dsb(); /* make sure DMA data is ready before triggering it */
+		if (sram != 0) {
+			uintptr_t chunk_source =
+				  src_addr + MSS_SRAM_SIZE * chunk_num;
 
-		/* set the DMA control register */
-		mmio_write_32(MSS_DMA_CTRLR(mss_regs), ((MSS_DMA_CTRLR_REQ_SET
-			      << MSS_DMA_CTRLR_REQ_OFFSET) |
-			      (DMA_SIZE << MSS_DMA_CTRLR_SIZE_OFFSET)));
+			if (chunk_num != (size / MSS_SRAM_SIZE)) {
+				chunk_size = MSS_SRAM_SIZE;
+			} else {
+				chunk_size =  size % MSS_SRAM_SIZE;
+			}
 
-		/* Poll DMA_ACK at MSS_DMACTLR until it is ready */
-		timeout = MSS_DMA_TIMEOUT;
-		while (timeout) {
-			if ((mmio_read_32(MSS_DMA_CTRLR(mss_regs)) >>
-			     MSS_DMA_CTRLR_ACK_OFFSET & MSS_DMA_CTRLR_ACK_MASK)
-				== MSS_DMA_CTRLR_ACK_READY) {
+			if (chunk_size == 0) {
 				break;
 			}
 
-			udelay(50);
-			timeout--;
+			VERBOSE("Chunk %d -> SRAM 0x%lx from 0x%lx SZ 0x%lx\n",
+				chunk_num, sram, chunk_source, chunk_size);
+			memcpy((void *)sram, (void *)chunk_source, chunk_size);
+			dsb();
+			img_src = MSS_INTERNAL_SPACE |
+				  (sram & MSS_INTERNAL_ADDR_MASK);
 		}
 
-		if (timeout == 0) {
-			ERROR("\nDMA failed to load MSS image\n");
-			return 1;
+		ret = mss_iram_dma_load(img_src, chunk_size, mss_regs);
+		if (ret != 0) {
+			ERROR("MSS FW chunk %d load failed\n", chunk_num);
+			return ret;
 		}
 	}
 
 	bl2_plat_configure_mss_windows(mss_regs);
 
+	/* Wipe the MSS SRAM after using it as copy buffer */
+	if (sram) {
+		memset((void *)sram, 0, MSS_SRAM_SIZE);
+	}
+
 	/* Release M3 from reset */
-	mmio_write_32(MSS_M3_RSTCR(mss_regs), (MSS_M3_RSTCR_RST_OFF <<
-		      MSS_M3_RSTCR_RST_OFFSET));
+	mmio_write_32(MSS_M3_RSTCR(mss_regs),
+		     (MSS_M3_RSTCR_RST_OFF << MSS_M3_RSTCR_RST_OFFSET));
 
 	NOTICE("Done\n");
 
@@ -162,7 +217,7 @@
 	VERBOSE("Send info about the SCP_BL2 image to be transferred to SCP\n");
 
 	ret = mss_image_load(single_img, image_size,
-			     bl2_plat_get_ap_mss_regs(ap_idx));
+			     bl2_plat_get_ap_mss_regs(ap_idx), 0);
 	if (ret != 0) {
 		ERROR("SCP Image load failed\n");
 		return -1;
@@ -218,6 +273,8 @@
 			       cp_index, ap_idx);
 			ret = mss_image_load(single_img, image_size,
 					     bl2_plat_get_cp_mss_regs(
+						     ap_idx, cp_index),
+					     bl2_plat_get_cp_mss_sram(
 						     ap_idx, cp_index));
 			if (ret != 0) {
 				ERROR("SCP Image load failed\n");
diff --git a/plat/marvell/armada/common/mss/mss_scp_bootloader.h b/plat/marvell/armada/common/mss/mss_scp_bootloader.h
index 4950d24..d65354a 100644
--- a/plat/marvell/armada/common/mss/mss_scp_bootloader.h
+++ b/plat/marvell/armada/common/mss/mss_scp_bootloader.h
@@ -10,6 +10,7 @@
 
 int scp_bootloader_transfer(void *image, unsigned int image_size);
 uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx);
+uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx);
 uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx);
 uint32_t bl2_plat_get_cp_count(int ap_idx);
 uint32_t bl2_plat_get_ap_count(void);
diff --git a/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c b/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c
index 0befadf..82ce07b 100644
--- a/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c
+++ b/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c
@@ -149,7 +149,7 @@
 		i2c_init((void *)MVEBU_CP0_I2C_BASE);
 
 		/* select SPD memory page 0 to access DRAM configuration */
-		i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 1);
+		i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
 
 		/* read data from spd */
 		i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
diff --git a/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c b/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c
index 7debd65..fbacf54 100644
--- a/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c
+++ b/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c
@@ -46,15 +46,19 @@
  *****************************************************************************
  */
 struct addr_map_win io_win_memory_map[] = {
+#if (CP_COUNT > 1)
+	/* SB (MCi0) internal regs */
+	{0x00000000f4000000,		0x2000000,	MCI_0_TID},
+#if (CP_COUNT > 2)
+	/* SB (MCi1) internal regs */
+	{0x00000000f6000000,		0x2000000,	MCI_1_TID},
+#endif
+#endif
 #ifndef IMAGE_BLE
 	/* SB (MCi0) PCIe0-2 on CP1 */
 	{0x00000000e2000000,		0x3000000,	MCI_0_TID},
 	/* SB (MCi1) PCIe0-2 on CP2 */
 	{0x00000000e5000000,		0x3000000,	MCI_1_TID},
-	/* SB (MCi0) internal regs */
-	{0x00000000f4000000,		0x2000000,	MCI_0_TID},
-	/* SB (MCi1) internal regs */
-	{0x00000000f6000000,		0x2000000,	MCI_1_TID},
 	/* MCI 0 indirect window */
 	{MVEBU_MCI_REG_BASE_REMAP(0),	0x100000,	MCI_0_TID},
 	/* MCI 1 indirect window */
diff --git a/plat/qemu/common/qemu_bl31_setup.c b/plat/qemu/common/qemu_bl31_setup.c
index 4d36b03..4f60eb1 100644
--- a/plat/qemu/common/qemu_bl31_setup.c
+++ b/plat/qemu/common/qemu_bl31_setup.c
@@ -7,6 +7,7 @@
 #include <assert.h>
 
 #include <common/bl_common.h>
+#include <drivers/arm/pl061_gpio.h>
 #include <plat/common/platform.h>
 
 #include "qemu_private.h"
@@ -69,9 +70,18 @@
 			      BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END);
 }
 
+static void qemu_gpio_init(void)
+{
+#ifdef SECURE_GPIO_BASE
+	pl061_gpio_init();
+	pl061_gpio_register(SECURE_GPIO_BASE, 0);
+#endif
+}
+
 void bl31_platform_setup(void)
 {
 	plat_qemu_gic_init();
+	qemu_gpio_init();
 }
 
 unsigned int plat_get_syscnt_freq2(void)
diff --git a/plat/qemu/common/qemu_pm.c b/plat/qemu/common/qemu_pm.c
index cf80009..c4ffcf9 100644
--- a/plat/qemu/common/qemu_pm.c
+++ b/plat/qemu/common/qemu_pm.c
@@ -12,6 +12,7 @@
 #include <lib/psci/psci.h>
 #include <lib/semihosting.h>
 #include <plat/common/platform.h>
+#include <drivers/gpio.h>
 
 #include "qemu_private.h"
 
@@ -201,16 +202,31 @@
 /*******************************************************************************
  * Platform handlers to shutdown/reboot the system
  ******************************************************************************/
+
 static void __dead2 qemu_system_off(void)
 {
+#ifdef SECURE_GPIO_BASE
+	ERROR("QEMU System Power off: with GPIO.\n");
+	gpio_set_direction(SECURE_GPIO_POWEROFF, GPIO_DIR_OUT);
+	gpio_set_value(SECURE_GPIO_POWEROFF, GPIO_LEVEL_HIGH);
+	gpio_set_value(SECURE_GPIO_POWEROFF, GPIO_LEVEL_LOW);
+#else
 	semihosting_exit(ADP_STOPPED_APPLICATION_EXIT, 0);
 	ERROR("QEMU System Off: semihosting call unexpectedly returned.\n");
+#endif
 	panic();
 }
 
 static void __dead2 qemu_system_reset(void)
 {
+	ERROR("QEMU System Reset: with GPIO.\n");
+#ifdef SECURE_GPIO_BASE
+	gpio_set_direction(SECURE_GPIO_RESET, GPIO_DIR_OUT);
+	gpio_set_value(SECURE_GPIO_RESET, GPIO_LEVEL_HIGH);
+	gpio_set_value(SECURE_GPIO_RESET, GPIO_LEVEL_LOW);
+#else
 	ERROR("QEMU System Reset: operation not handled.\n");
+#endif
 	panic();
 }
 
diff --git a/plat/qemu/qemu/include/platform_def.h b/plat/qemu/qemu/include/platform_def.h
index e6bb1e6..fbcaa63 100644
--- a/plat/qemu/qemu/include/platform_def.h
+++ b/plat/qemu/qemu/include/platform_def.h
@@ -89,6 +89,11 @@
 #define SEC_DRAM_BASE			0x0e100000
 #define SEC_DRAM_SIZE			0x00f00000
 
+#define SECURE_GPIO_BASE		0x090b0000
+#define SECURE_GPIO_SIZE		0x00001000
+#define SECURE_GPIO_POWEROFF		0
+#define SECURE_GPIO_RESET		1
+
 /* Load pageable part of OP-TEE 2MB above secure DRAM base */
 #define QEMU_OPTEE_PAGEABLE_LOAD_BASE	(SEC_DRAM_BASE + 0x00200000)
 #define QEMU_OPTEE_PAGEABLE_LOAD_SIZE	0x00400000
@@ -210,7 +215,7 @@
 #define DEVICE0_BASE			0x08000000
 #define DEVICE0_SIZE			0x01000000
 #define DEVICE1_BASE			0x09000000
-#define DEVICE1_SIZE			0x00041000
+#define DEVICE1_SIZE			0x00c00000
 
 /*
  * GIC related constants
diff --git a/plat/qemu/qemu/platform.mk b/plat/qemu/qemu/platform.mk
index 14bf049..88a95c8 100644
--- a/plat/qemu/qemu/platform.mk
+++ b/plat/qemu/qemu/platform.mk
@@ -163,6 +163,8 @@
 				lib/semihosting/semihosting.c		\
 				lib/semihosting/${ARCH}/semihosting_call.S \
 				plat/common/plat_psci_common.c		\
+				drivers/arm/pl061/pl061_gpio.c		\
+				drivers/gpio/gpio.c			\
 				${PLAT_QEMU_COMMON_PATH}/qemu_pm.c			\
 				${PLAT_QEMU_COMMON_PATH}/topology.c			\
 				${PLAT_QEMU_COMMON_PATH}/aarch64/plat_helpers.S	\
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
 
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index a076be2..6aab558 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -109,7 +109,6 @@
 
 	/* Restore the context assigned above */
 	cm_el1_sysregs_context_restore(SECURE);
-
 #if SPMD_SPM_AT_SEL2
 	cm_el2_sysregs_context_restore(SECURE);
 #endif
@@ -349,18 +348,12 @@
 
 	/* Save incoming security state */
 	cm_el1_sysregs_context_save(secure_state_in);
-#if CTX_INCLUDE_FPREGS
-	fpregs_context_save(get_fpregs_ctx(cm_get_context(secure_state_in)));
-#endif
 #if SPMD_SPM_AT_SEL2
 	cm_el2_sysregs_context_save(secure_state_in);
 #endif
 
 	/* Restore outgoing security state */
 	cm_el1_sysregs_context_restore(secure_state_out);
-#if CTX_INCLUDE_FPREGS
-	fpregs_context_restore(get_fpregs_ctx(cm_get_context(secure_state_out)));
-#endif
 #if SPMD_SPM_AT_SEL2
 	cm_el2_sysregs_context_restore(secure_state_out);
 #endif