Merge changes from topic "stm32_exceptions" into integration

* changes:
  stm32mp1: correct crash console GPIO alternate configuration
  stm32mp1: add plat_panic_handler function
  stm32mp1: update plat_report_exception
  Align AARCH32 version of debug.S with AARCH64
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 735d1fc..cd6549b 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -7,6 +7,12 @@
 ################################################################################
 # Include Makefile for the SPM-MM implementation
 ################################################################################
+ifeq (${SUPPORT_UNKNOWN_MPID},1)
+  ifeq (${DEBUG},0)
+    $(warning WARNING: SUPPORT_UNKNOWN_MPID enabled)
+  endif
+endif
+
 ifeq (${SPM_MM},1)
   ifeq (${EL3_EXCEPTION_HANDLING},0)
     $(error EL3_EXCEPTION_HANDLING must be 1 for SPM-MM support)
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c
index 92a2027..44bf32c 100644
--- a/bl31/bl31_main.c
+++ b/bl31/bl31_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -41,6 +41,15 @@
  ******************************************************************************/
 static uint32_t next_image_type = NON_SECURE;
 
+#ifdef SUPPORT_UNKNOWN_MPID
+/*
+ * Flag to know whether an unsupported MPID has been detected. To avoid having it
+ * landing on the .bss section, it is initialized to a non-zero value, this way
+ * we avoid potential WAW hazards during system bring up.
+ * */
+volatile uint32_t unsupported_mpid_flag = 1;
+#endif
+
 /*
  * Implement the ARM Standard Service function to get arguments for a
  * particular service.
@@ -98,6 +107,12 @@
 	NOTICE("BL31: %s\n", version_string);
 	NOTICE("BL31: %s\n", build_message);
 
+#ifdef SUPPORT_UNKNOWN_MPID
+	if (unsupported_mpid_flag == 0) {
+		NOTICE("Unsupported MPID detected!\n");
+	}
+#endif
+
 	/* Perform platform setup in BL31 */
 	bl31_platform_setup();
 
diff --git a/common/fdt_fixup.c b/common/fdt_fixup.c
index 980e60d..a1604e7 100644
--- a/common/fdt_fixup.c
+++ b/common/fdt_fixup.c
@@ -377,3 +377,64 @@
 
 	return offs;
 }
+
+/**
+ * fdt_adjust_gic_redist() - Adjust GICv3 redistributor size
+ * @dtb: Pointer to the DT blob in memory
+ * @nr_cores: Number of CPU cores on this system.
+ * @gicr_frame_size: Size of the GICR frame per core
+ *
+ * On a GICv3 compatible interrupt controller, the redistributor provides
+ * a number of 64k pages per each supported core. So with a dynamic topology,
+ * this size cannot be known upfront and thus can't be hardcoded into the DTB.
+ *
+ * Find the DT node describing the GICv3 interrupt controller, and adjust
+ * the size of the redistributor to match the number of actual cores on
+ * this system.
+ * A GICv4 compatible redistributor uses four 64K pages per core, whereas GICs
+ * without support for direct injection of virtual interrupts use two 64K pages.
+ * The @gicr_frame_size parameter should be 262144 and 131072, respectively.
+ *
+ * Return: 0 on success, negative error value otherwise.
+ */
+int fdt_adjust_gic_redist(void *dtb, unsigned int nr_cores,
+			  unsigned int gicr_frame_size)
+{
+	int offset = fdt_node_offset_by_compatible(dtb, 0, "arm,gic-v3");
+	uint64_t redist_size_64;
+	uint32_t redist_size_32;
+	void *val;
+	int parent;
+	int ac, sc;
+
+	if (offset < 0) {
+		return offset;
+	}
+
+	parent = fdt_parent_offset(dtb, offset);
+	if (parent < 0) {
+		return parent;
+	}
+	ac = fdt_address_cells(dtb, parent);
+	sc = fdt_size_cells(dtb, parent);
+	if (ac < 0 || sc < 0) {
+		return -EINVAL;
+	}
+
+	if (sc == 1) {
+		redist_size_32 = cpu_to_fdt32(nr_cores * gicr_frame_size);
+		val = &redist_size_32;
+	} else {
+		redist_size_64 = cpu_to_fdt64(nr_cores * gicr_frame_size);
+		val = &redist_size_64;
+	}
+
+	/*
+	 * The redistributor is described in the second "reg" entry.
+	 * So we have to skip one address and one size cell, then another
+	 * address cell to get to the second size cell.
+	 */
+	return fdt_setprop_inplace_namelen_partial(dtb, offset, "reg", 3,
+						   (ac + sc + ac) * 4,
+						   val, sc * 4);
+}
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 3c0e30f..e9ff17e 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -251,6 +251,9 @@
 
 For Cortex-A77, the following errata build flags are defined :
 
+-  ``ERRATA_A77_1508412``: This applies errata 1508412 workaround to Cortex-A77
+   CPU. This needs to be enabled only for revision <= r1p0 of the CPU.
+
 -  ``ERRATA_A77_1800714``: This applies errata 1800714 workaround to Cortex-A77
    CPU. This needs to be enabled only for revision <= r1p1 of the CPU.
 
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index b4fe404..40fc5db 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -300,6 +300,10 @@
    handled at EL3, and a panic will result. This is supported only for AArch64
    builds.
 
+-  ``EVENT_LOG_LEVEL``: Chooses the log level to use for Measured Boot when
+   ``MEASURED_BOOT`` is enabled. For a list of valid values, see ``LOG_LEVEL``.
+   Default value is 40 (LOG_LEVEL_INFO).
+
 -  ``FAULT_INJECTION_SUPPORT``: ARMv8.4 extensions introduced support for fault
    injection from lower ELs, and this build option enables lower ELs to use
    Error Records accessed via System Registers to inject faults. This is
diff --git a/docs/plat/arm/arm_fpga/index.rst b/docs/plat/arm/arm_fpga/index.rst
new file mode 100644
index 0000000..5427c1d
--- /dev/null
+++ b/docs/plat/arm/arm_fpga/index.rst
@@ -0,0 +1,97 @@
+Arm FPGA Platform
+=================
+
+This platform supports FPGA images used internally in Arm Ltd., for
+testing and bringup of new cores. With that focus, peripheral support is
+minimal: there is no mass storage or display output, for instance. Also
+this port ignores any power management features of the platform.
+Some interconnect setup is done internally by the platform, so the TF-A code
+just needs to setup UART and GIC.
+
+The FPGA platform requires to pass on a DTB for the non-secure payload
+(mostly Linux), so we let TF-A use information from the DTB for dynamic
+configuration: the UART and GIC base addresses are read from there.
+
+As a result this port is a fairly generic BL31-only port, which can serve
+as a template for a minimal new (and possibly DT-based) platform port.
+
+The aim of this port is to support as many FPGA images as possible with
+a single build. Image specific data must be described in the DTB or should
+be auto-detected at runtime.
+
+As the number and topology layout of the CPU cores differs significantly
+across the various images, this is detected at runtime by BL31.
+The /cpus node in the DT will be added and filled accordingly, as long as
+it does not exist already.
+
+Platform-specific build options
+-------------------------------
+
+-  ``SUPPORT_UNKNOWN_MPID`` : Boolean option to allow unknown MPIDR registers.
+   Normally TF-A panics if it encounters a MPID value not matched to its
+   internal list, but for new or experimental cores this creates a lot of
+   churn. With this option, the code will fall back to some basic CPU support
+   code (only architectural system registers, and no errata).
+   Default value of this flag is 1.
+
+-  ``PRELOADED_BL33_BASE`` : Physical address of the BL33 non-secure payload.
+   It must have been loaded into DRAM already, typically this is done by
+   the script that also loads BL31 and the DTB.
+   It defaults to 0x80080000, which is the traditional load address for an
+   arm64 Linux kernel.
+
+-  ``FPGA_PRELOADED_DTB_BASE`` : Physical address of the flattened device
+   tree blob (DTB). This DT will be used by TF-A for dynamic configuration,
+   so it must describe at least the UART and a GICv3 interrupt controller.
+   The DT gets amended by the code, to potentially add a command line and
+   fill the CPU topology nodes. It will also be passed on to BL33, by
+   putting its address into the x0 register before jumping to the entry
+   point (following the Linux kernel boot protocol).
+   It defaults to 0x80070000, which is 64KB before the BL33 load address.
+
+-  ``FPGA_PRELOADED_CMD_LINE`` : Physical address of the command line to
+   put into the devicetree blob. Due to the lack of a proper bootloader,
+   a command line can be put somewhere into memory, so that BL31 will
+   detect it and copy it into the DTB passed on to BL33.
+   To avoid random garbage, there needs to be a "CMD:" signature before the
+   actual command line.
+   Defaults to 0x1000, which is normally in the "ROM" space of the typical
+   FPGA image (which can be written by the FPGA payload uploader, but is
+   read-only to the CPU). The FPGA payload tool should be given a text file
+   containing the desired command line, prefixed by the "CMD:" signature.
+
+Building the TF-A image
+-----------------------
+
+   .. code:: shell
+
+       make PLAT=arm_fgpa DEBUG=1
+
+   This will use the default load addresses as described above. When those
+   addresses need to differ for a certain setup, they can be passed on the
+   make command line:
+
+   .. code:: shell
+
+       make PLAT=arm_fgpa DEBUG=1 PRELOADED_BL33_BASE=0x80200000 FPGA_PRELOADED_DTB_BASE=0x80180000 bl31
+
+Running the TF-A image
+----------------------
+
+After building TF-A, the actual TF-A code will be located in ``bl31.bin`` in
+the build directory.
+Additionally there is a ``bl31.axf`` ELF file, which contains BL31, as well
+as some simple ROM trampoline code (required by the Arm FPGA boot flow) and
+a generic DTB to support most of the FPGA images. This can be simply handed
+over to the FPGA payload uploader, which will take care of loading the
+components at their respective load addresses. In addition to this file
+you need at least a BL33 payload (typically a Linux kernel image), optionally
+a Linux initrd image file and possibly a command line:
+
+   .. code:: shell
+
+       fpga-run ... -m bl31.axf -l auto -m Image -l 0x80080000 -m initrd.gz -l 0x84000000 -m cmdline.txt -l 0x1000
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/docs/plat/arm/index.rst b/docs/plat/arm/index.rst
index 1afe475..9c2fcb1 100644
--- a/docs/plat/arm/index.rst
+++ b/docs/plat/arm/index.rst
@@ -9,6 +9,7 @@
    fvp/index
    fvp-ve/index
    tc0/index
+   arm_fpga/index
    arm-build-options
 
 This chapter holds documentation related to Arm's development platforms,
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index bd23410..fb60e56 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -54,6 +54,7 @@
    - Arm Neoverse Reference Design E1 Edge (RD-E1-Edge) FVP
    - Arm SGI-575 and SGM-775
    - MediaTek MT6795 and MT8173 SoCs
+   - Arm Morello Platform
 
 --------------
 
diff --git a/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/arm/gic/v3/gicv3_helpers.c
index 09fa678..ff346f9 100644
--- a/drivers/arm/gic/v3/gicv3_helpers.c
+++ b/drivers/arm/gic/v3/gicv3_helpers.c
@@ -326,3 +326,33 @@
 
 	return ctlr_enable;
 }
+
+/**
+ * gicv3_rdistif_get_number_frames() - determine size of GICv3 GICR region
+ * @gicr_frame: base address of the GICR region to check
+ *
+ * This iterates over the GICR_TYPER registers of multiple GICR frames in
+ * a GICR region, to find the instance which has the LAST bit set. For most
+ * systems this corresponds to the number of cores handled by a redistributor,
+ * but there could be disabled cores among them.
+ * It assumes that each GICR region is fully accessible (till the LAST bit
+ * marks the end of the region).
+ * If a platform has multiple GICR regions, this function would need to be
+ * called multiple times, providing the respective GICR base address each time.
+ *
+ * Return: number of valid GICR frames (at least 1, up to PLATFORM_CORE_COUNT)
+ ******************************************************************************/
+unsigned int gicv3_rdistif_get_number_frames(const uintptr_t gicr_frame)
+{
+	uintptr_t rdistif_base = gicr_frame;
+	unsigned int count;
+
+	for (count = 1; count < PLATFORM_CORE_COUNT; count++) {
+		if ((gicr_read_typer(rdistif_base) & TYPER_LAST_BIT) != 0U) {
+			break;
+		}
+		rdistif_base += (1U << GICR_PCPUBASE_SHIFT);
+	}
+
+	return count;
+}
diff --git a/drivers/marvell/ccu.c b/drivers/marvell/ccu.c
index c73516e..ecf5091 100644
--- a/drivers/marvell/ccu.c
+++ b/drivers/marvell/ccu.c
@@ -30,6 +30,9 @@
 					((tgt) == DRAM_1_TID) || \
 					((tgt) == RAR_TID)) ? 1 : 0)
 
+#define CCU_RGF(win)			(MVEBU_CCU_BASE(MVEBU_AP0) +	\
+					 0x90 + 4 * (win))
+
 /* For storage of CR, SCR, ALR, AHR abd GCR */
 static uint32_t ccu_regs_save[MVEBU_CCU_MAX_WINS * 4 + 1];
 
@@ -366,3 +369,17 @@
 
 	return 0;
 }
+
+void errata_wa_init(void)
+{
+	/*
+	 * EERATA ID: RES-3033912 - Internal Address Space Init state causes
+	 * a hang upon accesses to [0xf070_0000, 0xf07f_ffff]
+	 * Workaround: Boot Firmware (ATF) should configure CCU_RGF_WIN(4) to
+	 * split [0x6e_0000, 0xff_ffff] to values [0x6e_0000, 0x6f_ffff] and
+	 * [0x80_0000, 0xff_ffff] that cause accesses to the
+	 * segment of [0xf070_0000, 0xf07f_ffff] to act as RAZWI.
+	 */
+	mmio_write_32(CCU_RGF(4), 0x37f9b809);
+	mmio_write_32(CCU_RGF(5), 0x7ffa0009);
+}
diff --git a/drivers/marvell/mochi/ap807_setup.c b/drivers/marvell/mochi/ap807_setup.c
index 7b68195..7cdfe05 100644
--- a/drivers/marvell/mochi/ap807_setup.c
+++ b/drivers/marvell/mochi/ap807_setup.c
@@ -117,6 +117,8 @@
 	reg |= (0x1 << CCU_SET_POC_OFFSET);
 	mmio_write_32(CCU_HTC_CR, reg);
 #endif /* LLC_ENABLE */
+
+	errata_wa_init();
 }
 
 
diff --git a/drivers/marvell/mochi/apn806_setup.c b/drivers/marvell/mochi/apn806_setup.c
index 1a02bd4..b8925d9 100644
--- a/drivers/marvell/mochi/apn806_setup.c
+++ b/drivers/marvell/mochi/apn806_setup.c
@@ -28,9 +28,6 @@
 							0x200)
 #define CCU_SET_POC_OFFSET			5
 
-#define CCU_RGF(win)				(MVEBU_CCU_BASE(MVEBU_AP0) + \
-							0x90 + 4 * (win))
-
 #define DSS_CR0					(MVEBU_RFU_BASE + 0x100)
 #define DVM_48BIT_VA_ENABLE			(1 << 21)
 
@@ -95,20 +92,6 @@
 	mmio_write_32(SMMU_sACR, reg);
 }
 
-static void apn806_errata_wa_init(void)
-{
-	/*
-	 * ERRATA ID: RES-3033912 - Internal Address Space Init state causes
-	 * a hang upon accesses to [0xf070_0000, 0xf07f_ffff]
-	 * Workaround: Boot Firmware (ATF) should configure CCU_RGF_WIN(4) to
-	 * split [0x6e_0000, 0xff_ffff] to values [0x6e_0000, 0x6f_ffff] and
-	 * [0x80_0000, 0xff_ffff] that cause accesses to the
-	 * segment of [0xf070_0000, 0xf07f_ffff] to act as RAZWI.
-	 */
-	mmio_write_32(CCU_RGF(4), 0x37f9b809);
-	mmio_write_32(CCU_RGF(5), 0x7ffa0009);
-}
-
 static void init_aurora2(void)
 {
 	uint32_t reg;
@@ -131,7 +114,7 @@
 	mmio_write_32(CCU_HTC_CR, reg);
 #endif /* LLC_ENABLE */
 
-	apn806_errata_wa_init();
+	errata_wa_init();
 }
 
 
diff --git a/drivers/measured_boot/measured_boot.mk b/drivers/measured_boot/measured_boot.mk
index b7aa48b..497fdba 100644
--- a/drivers/measured_boot/measured_boot.mk
+++ b/drivers/measured_boot/measured_boot.mk
@@ -4,6 +4,9 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# Default log level to dump the event log (LOG_LEVEL_INFO)
+EVENT_LOG_LEVEL         ?= 40
+
 # TPM hash algorithm
 TPM_HASH_ALG			:=	sha256
 
@@ -31,6 +34,7 @@
         TPM_ALG_ID \
         TCG_DIGEST_SIZE \
         EVENT_LOG_SIZE \
+        EVENT_LOG_LEVEL \
 )))
 
 ifeq (${HASH_ALG}, sha256)
diff --git a/drivers/mtd/nand/raw_nand.c b/drivers/mtd/nand/raw_nand.c
index 48131fc..1fb5fac 100644
--- a/drivers/mtd/nand/raw_nand.c
+++ b/drivers/mtd/nand/raw_nand.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -190,7 +190,7 @@
 	return ret;
 }
 
-int nand_wait_ready(unsigned long delay)
+int nand_wait_ready(unsigned int delay_ms)
 {
 	uint8_t status;
 	int ret;
@@ -204,7 +204,7 @@
 		return ret;
 	}
 
-	timeout = timeout_init_us(delay);
+	timeout = timeout_init_us(delay_ms * 1000U);
 	while (!timeout_elapsed(timeout)) {
 		ret = nand_read_data(&status, 1U, true);
 		if (ret != 0) {
diff --git a/drivers/mtd/nor/spi_nor.c b/drivers/mtd/nor/spi_nor.c
index 22d3ae3..108f893 100644
--- a/drivers/mtd/nor/spi_nor.c
+++ b/drivers/mtd/nor/spi_nor.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -368,7 +368,7 @@
 	if (nor_dev.read_op.data.buswidth == 4U) {
 		switch (id) {
 		case MACRONIX_ID:
-			WARN("Enable Macronix quad support\n");
+			INFO("Enable Macronix quad support\n");
 			ret = spi_nor_macronix_quad_enable();
 			break;
 		case MICRON_ID:
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index d6cd8b1..f8bc5a2 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -653,15 +653,17 @@
 bool stm32mp1_rcc_is_secure(void)
 {
 	uintptr_t rcc_base = stm32mp_rcc_base();
+	uint32_t mask = RCC_TZCR_TZEN;
 
-	return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_TZEN) != 0;
+	return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask;
 }
 
 bool stm32mp1_rcc_is_mckprot(void)
 {
 	uintptr_t rcc_base = stm32mp_rcc_base();
+	uint32_t mask = RCC_TZCR_TZEN | RCC_TZCR_MCKPROT;
 
-	return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_MCKPROT) != 0;
+	return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask;
 }
 
 void stm32mp1_clk_rcc_regs_lock(void)
diff --git a/drivers/st/crypto/stm32_hash.c b/drivers/st/crypto/stm32_hash.c
index 515947c..317fd9e 100644
--- a/drivers/st/crypto/stm32_hash.c
+++ b/drivers/st/crypto/stm32_hash.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -252,6 +252,8 @@
 		mmio_clrsetbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK,
 				   8U * stm32_remain.length);
 		zeromem(&stm32_remain, sizeof(stm32_remain));
+	} else {
+		mmio_clrbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK);
 	}
 
 	mmio_setbits_32(hash_base() + HASH_STR, HASH_STR_DCAL);
diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c
index bb77371..7d63262 100644
--- a/drivers/st/gpio/stm32_gpio.c
+++ b/drivers/st/gpio/stm32_gpio.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2016-2020, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -161,13 +161,14 @@
 	const fdt32_t *cuint;
 	int lenp = 0;
 	uint32_t i;
-	uint8_t status = fdt_get_status(node);
+	uint8_t status;
 	void *fdt;
 
 	if (fdt_get_address(&fdt) == 0) {
 		return -FDT_ERR_NOTFOUND;
 	}
 
+	status = fdt_get_status(node);
 	if (status == DT_DISABLED) {
 		return -FDT_ERR_NOTFOUND;
 	}
diff --git a/drivers/st/io/io_mmc.c b/drivers/st/io/io_mmc.c
index 44b7d19..0ed7154 100644
--- a/drivers/st/io/io_mmc.c
+++ b/drivers/st/io/io_mmc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -97,14 +97,21 @@
 static int mmc_block_read(io_entity_t *entity, uintptr_t buffer,
 			  size_t length, size_t *length_read)
 {
-	*length_read = mmc_read_blocks(seek_offset / MMC_BLOCK_SIZE,
-				       buffer, length);
+	uint8_t retries;
 
-	if (*length_read != length) {
-		return -EIO;
+	for (retries = 0U; retries < 3U; retries++) {
+		*length_read = mmc_read_blocks(seek_offset / MMC_BLOCK_SIZE,
+					       buffer, length);
+
+		if (*length_read == length) {
+			return 0;
+		}
+		WARN("%s: length_read = %lu (!= %lu), retry %u\n", __func__,
+		     (unsigned long)*length_read, (unsigned long)length,
+		     retries + 1U);
 	}
 
-	return 0;
+	return -EIO;
 }
 
 /* Close a file on the mmc device */
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
index 63fbb07..cff3a34 100644
--- a/drivers/st/mmc/stm32_sdmmc2.c
+++ b/drivers/st/mmc/stm32_sdmmc2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -258,6 +258,18 @@
 		break;
 	}
 
+	mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
+
+	/*
+	 * Clear the SDMMC_DCTRLR if the command does not await data.
+	 * Skip CMD55 as the next command could be data related, and
+	 * the register could have been set in prepare function.
+	 */
+	if (((cmd_reg & SDMMC_CMDR_CMDTRANS) == 0U) &&
+	    (cmd->cmd_idx != MMC_CMD(55))) {
+		mmio_write_32(base + SDMMC_DCTRLR, 0U);
+	}
+
 	if ((cmd->resp_type & MMC_RSP_BUSY) != 0U) {
 		mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX);
 	}
@@ -373,15 +385,15 @@
 
 static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd)
 {
-	int8_t retry;
-	int err = 0;
+	uint8_t retry;
+	int err;
 
 	assert(cmd != NULL);
 
-	for (retry = 0; retry <= 3; retry++) {
+	for (retry = 0U; retry < 3U; retry++) {
 		err = stm32_sdmmc2_send_cmd_req(cmd);
 		if (err == 0) {
-			return err;
+			return 0;
 		}
 
 		if ((cmd->cmd_idx == MMC_CMD(1)) ||
@@ -390,12 +402,12 @@
 		}
 
 		/* Command 8 is expected to fail for eMMC */
-		if (!(cmd->cmd_idx == MMC_CMD(8))) {
-			WARN(" CMD%d, Retry: %d, Error: %d\n",
-			     cmd->cmd_idx, retry, err);
+		if (cmd->cmd_idx != MMC_CMD(8)) {
+			WARN(" CMD%u, Retry: %u, Error: %d\n",
+			     cmd->cmd_idx, retry + 1U, err);
 		}
 
-		udelay(10);
+		udelay(10U);
 	}
 
 	return err;
diff --git a/fdts/arm_fpga.dts b/fdts/arm_fpga.dts
new file mode 100644
index 0000000..6a966fd
--- /dev/null
+++ b/fdts/arm_fpga.dts
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause)
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * Devicetree for the Arm Ltd. FPGA platform
+ * Number and kind of CPU cores differs from image to image, so the
+ * topology is auto-detected by BL31, and the /cpus node is created and
+ * populated accordingly at runtime.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/dts-v1/;
+
+/ {
+	model = "ARM FPGA";
+	compatible = "arm,fpga", "arm,vexpress";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &dbg_uart;
+	};
+
+	chosen {
+		stdout-path = "serial0:38400n8";
+		bootargs = "console=ttyAMA0,38400n8 earlycon";
+		/* Allow to upload a generous 100MB initrd payload. */
+		linux,initrd-start = <0x0 0x84000000>;
+		linux,initrd-end = <0x0 0x85400000>;
+	};
+
+	/* /cpus node will be added by BL31 at runtime. */
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		clock-frequency = <10000000>;
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	pmu {
+		compatible = "arm,armv8-pmuv3";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	/* This node will be removed at runtime on cores without SPE. */
+	spe-pmu {
+		compatible = "arm,statistical-profiling-extension-v1";
+		interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x0 0x80000000>,
+		      <0x8 0x80000000 0x1 0x80000000>;
+	};
+
+
+	bus_refclk: refclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
+		clock-output-names = "apb_pclk";
+	};
+
+	uartclk: baudclock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <10000000>;
+		clock-output-names = "uartclk";
+	};
+
+	dbg_uart: serial@7ff80000 {
+		compatible = "arm,pl011", "arm,primecell";
+		reg = <0x0 0x7ff80000 0x0 0x00001000>;
+		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&uartclk>, <&bus_refclk>;
+		clock-names = "uartclk", "apb_pclk";
+	};
+
+	gic: interrupt-controller@30000000 {
+		compatible = "arm,gic-v3";
+		#address-cells = <2>;
+		#interrupt-cells = <3>;
+		#size-cells = <2>;
+		ranges;
+		interrupt-controller;
+		reg = <0x0 0x30000000 0x0 0x00010000>,	/* GICD */
+	/* The GICR size will be adjusted at runtime to match the cores. */
+		      <0x0 0x30040000 0x0 0x00020000>;	/* GICR for one core */
+		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
diff --git a/fdts/morello-fvp.dts b/fdts/morello-fvp.dts
new file mode 100644
index 0000000..ecbed5e
--- /dev/null
+++ b/fdts/morello-fvp.dts
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+#include "morello.dtsi"
+
+/ {
+
+	chosen {
+		stdout-path = "soc_uart0:115200n8";
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		secure-firmware@ff000000 {
+			reg = <0 0xff000000 0 0x01000000>;
+			no-map;
+		};
+	};
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+		cpu0@0 {
+			compatible = "arm,armv8";
+			reg = <0x0 0x0>;
+			device_type = "cpu";
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 0>;
+		};
+		cpu1@100 {
+			compatible = "arm,armv8";
+			reg = <0x0 0x100>;
+			device_type = "cpu";
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 0>;
+		};
+		cpu2@10000 {
+			compatible = "arm,armv8";
+			reg = <0x0 0x10000>;
+			device_type = "cpu";
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 0>;
+		};
+		cpu3@10100 {
+			compatible = "arm,armv8";
+			reg = <0x0 0x10100>;
+			device_type = "cpu";
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 0>;
+		};
+	};
+
+	/* The first bank of memory, memory map is actually provided by UEFI. */
+	memory@80000000 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		device_type = "memory";
+		/* [0x80000000-0xffffffff] */
+		reg = <0x00000000 0x80000000 0x0 0x80000000>;
+	};
+
+	memory@8080000000 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		device_type = "memory";
+		/* [0x8080000000-0x83ffffffff] */
+		reg = <0x00000080 0x80000000 0x1 0x80000000>;
+	};
+
+	virtio_block@1c170000 {
+		compatible = "virtio,mmio";
+		reg = <0x0 0x1c170000 0x0 0x200>;
+		interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	ethernet@1d100000 {
+		compatible = "smsc,lan91c111";
+		reg = <0x0 0x1d100000 0x0 0x10000>;
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	kmi@1c150000 {
+		compatible = "arm,pl050", "arm,primecell";
+		reg = <0x0 0x1c150000 0x0 0x1000>;
+		interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bp_clock24mhz>, <&bp_clock24mhz>;
+		clock-names = "KMIREFCLK", "apb_pclk";
+	};
+
+	kmi@1c160000 {
+		compatible = "arm,pl050", "arm,primecell";
+		reg = <0x0 0x1c160000 0x0 0x1000>;
+		interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bp_clock24mhz>, <&bp_clock24mhz>;
+		clock-names = "KMIREFCLK", "apb_pclk";
+	};
+
+	firmware {
+		scmi {
+			compatible = "arm,scmi";
+			mbox-names = "tx", "rx";
+			mboxes = <&mailbox 1 0 &mailbox 1 1>;
+			shmem = <&cpu_scp_hpri0 &cpu_scp_hpri1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			scmi_dvfs: protocol@13 {
+				reg = <0x13>;
+				#clock-cells = <1>;
+			};
+		};
+	};
+
+	bp_clock24mhz: clock24mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-output-names = "bp:clock24mhz";
+	};
+};
+
+&gic {
+	reg = <0x0 0x30000000 0 0x10000>,	/* GICD */
+	      <0x0 0x300c0000 0 0x80000>;	/* GICR */
+	interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+};
diff --git a/fdts/morello.dtsi b/fdts/morello.dtsi
new file mode 100644
index 0000000..52c04cd
--- /dev/null
+++ b/fdts/morello.dtsi
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	compatible = "arm,morello";
+
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &soc_uart0;
+	};
+
+	gic: interrupt-controller@2c010000 {
+		compatible = "arm,gic-600", "arm,gic-v3";
+		#address-cells = <2>;
+		#interrupt-cells = <3>;
+		#size-cells = <2>;
+		ranges;
+		interrupt-controller;
+	};
+
+	pmu {
+		compatible = "arm,armv8-pmuv3";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	spe-pmu {
+		compatible = "arm,statistical-profiling-extension-v1";
+		interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	mailbox: mhu@45000000 {
+		compatible = "arm,mhu-doorbell", "arm,primecell";
+		reg = <0x0 0x45000000 0x0 0x1000>;
+		interrupts = <GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "mhu_lpri_rx",
+				  "mhu_hpri_rx";
+		#mbox-cells = <2>;
+		mbox-name = "ARM-MHU";
+		clocks = <&soc_refclk100mhz>;
+		clock-names = "apb_pclk";
+	};
+
+	sram: sram@45200000 {
+		compatible = "mmio-sram";
+		reg = <0x0 0x45200000 0x0 0x8000>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x0 0x45200000 0x8000>;
+
+		cpu_scp_hpri0: scp-shmem@0 {
+			compatible = "arm,scmi-shmem";
+			reg = <0x0 0x80>;
+		};
+
+		cpu_scp_hpri1: scp-shmem@80 {
+			compatible = "arm,scmi-shmem";
+			reg = <0x80 0x80>;
+		};
+	};
+
+	soc_refclk100mhz: refclk100mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
+		clock-output-names = "apb_pclk";
+	};
+
+	soc_uartclk:  uartclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <50000000>;
+		clock-output-names = "uartclk";
+	};
+
+	soc_uart0: uart@2a400000 {
+		compatible = "arm,pl011", "arm,primecell";
+		reg = <0x0 0x2a400000 0x0 0x1000>;
+		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&soc_uartclk>, <&soc_refclk100mhz>;
+		clock-names = "uartclk", "apb_pclk";
+		status = "okay";
+	};
+};
diff --git a/fdts/tc0.dts b/fdts/tc0.dts
index ac097cd..15c14ca 100644
--- a/fdts/tc0.dts
+++ b/fdts/tc0.dts
@@ -134,7 +134,7 @@
 		clocks = <&soc_refclk100mhz>;
 		clock-names = "apb_pclk";
 		#mbox-cells = <1>;
-		interrupts = <0 316 4>;
+		interrupts = <0 317 4>;
 		interrupt-names = "mhu_rx";
 		mhu-protocol = "doorbell";
 	};
diff --git a/include/common/fdt_fixup.h b/include/common/fdt_fixup.h
index 29d8b3a..2e9d49d 100644
--- a/include/common/fdt_fixup.h
+++ b/include/common/fdt_fixup.h
@@ -13,5 +13,7 @@
 			    uintptr_t base, size_t size);
 int fdt_add_cpus_node(void *dtb, unsigned int afflv0,
 		      unsigned int afflv1, unsigned int afflv2);
+int fdt_adjust_gic_redist(void *dtb, unsigned int nr_cores,
+			  unsigned int gicr_frame_size);
 
 #endif /* FDT_FIXUP_H */
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index 18d5b73..d8ac4cb 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -488,6 +488,7 @@
 void gicv3_rdistif_init(unsigned int proc_num);
 void gicv3_rdistif_on(unsigned int proc_num);
 void gicv3_rdistif_off(unsigned int proc_num);
+unsigned int gicv3_rdistif_get_number_frames(const uintptr_t gicr_frame);
 void gicv3_cpuif_enable(unsigned int proc_num);
 void gicv3_cpuif_disable(unsigned int proc_num);
 unsigned int gicv3_get_pending_interrupt_type(void);
diff --git a/include/drivers/marvell/ccu.h b/include/drivers/marvell/ccu.h
index 413ffb9..f8f0adf 100644
--- a/include/drivers/marvell/ccu.h
+++ b/include/drivers/marvell/ccu.h
@@ -47,6 +47,7 @@
 void ccu_save_win_all(int ap_id);
 void ccu_restore_win_all(int ap_id);
 int ccu_is_win_enabled(int ap_index, uint32_t win_id);
+void errata_wa_init(void);
 #endif
 
 #endif /* CCU_H */
diff --git a/include/drivers/measured_boot/event_log.h b/include/drivers/measured_boot/event_log.h
index 10dfbb3..efde117 100644
--- a/include/drivers/measured_boot/event_log.h
+++ b/include/drivers/measured_boot/event_log.h
@@ -20,8 +20,6 @@
  * LOG_LEVEL_WARNING
  * LOG_LEVEL_VERBOSE
  */
-#define	EVENT_LOG_LEVEL	LOG_LEVEL_INFO
-
 #if EVENT_LOG_LEVEL   == LOG_LEVEL_ERROR
 #define	LOG_EVENT	ERROR
 #elif EVENT_LOG_LEVEL == LOG_LEVEL_NOTICE
diff --git a/include/drivers/raw_nand.h b/include/drivers/raw_nand.h
index 9018f02..7152300 100644
--- a/include/drivers/raw_nand.h
+++ b/include/drivers/raw_nand.h
@@ -169,7 +169,7 @@
 };
 
 int nand_raw_init(unsigned long long *size, unsigned int *erase_size);
-int nand_wait_ready(unsigned long delay);
+int nand_wait_ready(unsigned int delay_ms);
 int nand_read_page_cmd(unsigned int page, unsigned int offset,
 		       uintptr_t buffer, unsigned int len);
 int nand_change_read_column_cmd(unsigned int offset, uintptr_t buffer,
diff --git a/include/drivers/st/etzpc.h b/include/drivers/st/etzpc.h
index 6e3fec1..4cd2b4e 100644
--- a/include/drivers/st/etzpc.h
+++ b/include/drivers/st/etzpc.h
@@ -7,6 +7,9 @@
 #ifndef DRIVERS_ST_ETZPC_H
 #define DRIVERS_ST_ETZPC_H
 
+#include <stdbool.h>
+#include <stdint.h>
+
 /* Define security level for each peripheral (DECPROT) */
 enum etzpc_decprot_attributes {
 	ETZPC_DECPROT_S_RW = 0,
diff --git a/include/lib/cpus/aarch64/cortex_a77.h b/include/lib/cpus/aarch64/cortex_a77.h
index bbd647c..41aced8 100644
--- a/include/lib/cpus/aarch64/cortex_a77.h
+++ b/include/lib/cpus/aarch64/cortex_a77.h
@@ -24,4 +24,11 @@
 #define CORTEX_A77_CPUPWRCTLR_EL1			S3_0_C15_C2_7
 #define CORTEX_A77_CPUPWRCTLR_EL1_CORE_PWRDN_BIT	(U(1) << 0)
 
+#define CORTEX_A77_CPUPSELR_EL3				S3_6_C15_C8_0
+#define CORTEX_A77_CPUPCR_EL3				S3_6_C15_C8_1
+#define CORTEX_A77_CPUPOR_EL3				S3_6_C15_C8_2
+#define CORTEX_A77_CPUPMR_EL3				S3_6_C15_C8_3
+#define CORTEX_A77_CPUPOR2_EL3				S3_6_C15_C8_4
+#define CORTEX_A77_CPUPMR2_EL3				S3_6_C15_C8_5
+
 #endif /* CORTEX_A77_H */
diff --git a/include/lib/cpus/aarch64/generic.h b/include/lib/cpus/aarch64/generic.h
new file mode 100644
index 0000000..53df587
--- /dev/null
+++ b/include/lib/cpus/aarch64/generic.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserverd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef AARCH64_GENERIC_H
+#define AARCH64_GENERIC_H
+
+#include <lib/utils_def.h>
+
+/*
+ * 0x0 value on the MIDR implementer value is reserved for software use,
+ * so use an MIDR value of 0 for a default CPU library.
+ */
+#define AARCH64_GENERIC_MIDR			U(0)
+
+#endif /* AARCH64_GENERIC_H */
diff --git a/include/lib/cpus/aarch64/rainier.h b/include/lib/cpus/aarch64/rainier.h
new file mode 100644
index 0000000..9ff1669
--- /dev/null
+++ b/include/lib/cpus/aarch64/rainier.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RAINIER_H
+#define RAINIER_H
+
+#include <lib/utils_def.h>
+
+/* RAINIER MIDR for revision 0 */
+#define RAINIER_MIDR			U(0x3f0f4100)
+
+/* Exception Syndrome register EC code for IC Trap */
+#define RAINIER_EC_IC_TRAP		U(0x1f)
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions.
+ ******************************************************************************/
+#define RAINIER_CPUPWRCTLR_EL1		S3_0_C15_C2_7
+
+/* Definitions of register field mask in RAINIER_CPUPWRCTLR_EL1 */
+#define RAINIER_CORE_PWRDN_EN_MASK	U(0x1)
+
+#define RAINIER_ACTLR_AMEN_BIT		(U(1) << 4)
+
+#define RAINIER_AMU_NR_COUNTERS		U(5)
+#define RAINIER_AMU_GROUP0_MASK		U(0x1f)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions.
+ ******************************************************************************/
+#define RAINIER_CPUECTLR_EL1			S3_0_C15_C1_4
+
+#define RAINIER_WS_THR_L2_MASK			(ULL(3) << 24)
+#define RAINIER_CPUECTLR_EL1_MM_TLBPF_DIS_BIT	(ULL(1) << 51)
+
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define RAINIER_CPUACTLR_EL1		S3_0_C15_C1_0
+
+#define RAINIER_CPUACTLR_EL1_BIT_6	(ULL(1) << 6)
+#define RAINIER_CPUACTLR_EL1_BIT_13	(ULL(1) << 13)
+
+#define RAINIER_CPUACTLR2_EL1		S3_0_C15_C1_1
+
+#define RAINIER_CPUACTLR2_EL1_BIT_0	(ULL(1) << 0)
+#define RAINIER_CPUACTLR2_EL1_BIT_2	(ULL(1) << 2)
+#define RAINIER_CPUACTLR2_EL1_BIT_11	(ULL(1) << 11)
+#define RAINIER_CPUACTLR2_EL1_BIT_15	(ULL(1) << 15)
+#define RAINIER_CPUACTLR2_EL1_BIT_16	(ULL(1) << 16)
+#define RAINIER_CPUACTLR2_EL1_BIT_59	(ULL(1) << 59)
+
+#define RAINIER_CPUACTLR3_EL1		S3_0_C15_C1_2
+
+#define RAINIER_CPUACTLR3_EL1_BIT_10	(ULL(1) << 10)
+
+/* Instruction patching registers */
+#define CPUPSELR_EL3	S3_6_C15_C8_0
+#define CPUPCR_EL3	S3_6_C15_C8_1
+#define CPUPOR_EL3	S3_6_C15_C8_2
+#define CPUPMR_EL3	S3_6_C15_C8_3
+
+#endif /* RAINIER_H */
diff --git a/include/lib/libc/string.h b/include/lib/libc/string.h
index 91cbafb..9894483 100644
--- a/include/lib/libc/string.h
+++ b/include/lib/libc/string.h
@@ -27,5 +27,6 @@
 char *strrchr(const char *p, int ch);
 size_t strlcpy(char * dst, const char * src, size_t dsize);
 size_t strlcat(char * dst, const char * src, size_t dsize);
+char *strtok_r(char *s, const char *delim, char **last);
 
 #endif /* STRING_H */
diff --git a/lib/cpus/aarch64/cortex_a77.S b/lib/cpus/aarch64/cortex_a77.S
index 0c30460..ea21999 100644
--- a/lib/cpus/aarch64/cortex_a77.S
+++ b/lib/cpus/aarch64/cortex_a77.S
@@ -22,6 +22,70 @@
 #endif
 
 	/* --------------------------------------------------
+	 * Errata Workaround for Cortex A77 Errata #1508412.
+	 * This applies only to revision <= r1p0 of Cortex A77.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_a77_1508412_wa
+	/*
+	 * Compare x0 against revision r1p0
+	 */
+	mov	x17, x30
+	bl	check_errata_1508412
+	cbz	x0, 3f
+	/*
+	 * Compare x0 against revision r0p0
+	 */
+	bl	check_errata_1508412_0
+	cbz	x0, 1f
+	ldr	x0, =0x0
+	msr	CORTEX_A77_CPUPSELR_EL3, x0
+	ldr 	x0, =0x00E8400000
+	msr	CORTEX_A77_CPUPOR_EL3, x0
+	ldr	x0, =0x00FFE00000
+	msr	CORTEX_A77_CPUPMR_EL3, x0
+	ldr	x0, =0x4004003FF
+	msr	CORTEX_A77_CPUPCR_EL3, x0
+	ldr	x0, =0x1
+	msr	CORTEX_A77_CPUPSELR_EL3, x0
+	ldr	x0, =0x00E8C00040
+	msr	CORTEX_A77_CPUPOR_EL3, x0
+	ldr	x0, =0x00FFE00040
+	msr	CORTEX_A77_CPUPMR_EL3, x0
+	b	2f
+1:
+	ldr	x0, =0x0
+	msr	CORTEX_A77_CPUPSELR_EL3, x0
+	ldr	x0, =0x00E8400000
+	msr	CORTEX_A77_CPUPOR_EL3, x0
+	ldr	x0, =0x00FF600000
+	msr	CORTEX_A77_CPUPMR_EL3, x0
+	ldr	x0, =0x00E8E00080
+	msr	CORTEX_A77_CPUPOR2_EL3, x0
+	ldr	x0, =0x00FFE000C0
+	msr	CORTEX_A77_CPUPMR2_EL3, x0
+2:
+	ldr	x0, =0x04004003FF
+	msr	CORTEX_A77_CPUPCR_EL3, x0
+	isb
+3:
+	ret	x17
+endfunc errata_a77_1508412_wa
+
+func check_errata_1508412
+	mov	x1, #0x10
+	b	cpu_rev_var_ls
+endfunc check_errata_1508412
+
+func check_errata_1508412_0
+	mov	x1, #0x0
+	b	cpu_rev_var_ls
+endfunc check_errata_1508412_0
+
+	/* --------------------------------------------------
 	 * Errata Workaround for Cortex A77 Errata #1800714.
 	 * This applies to revision <= r1p1 of Cortex A77.
 	 * Inputs:
@@ -60,6 +124,11 @@
 	bl	cpu_get_rev_var
 	mov	x18, x0
 
+#if ERRATA_A77_1508412
+	mov	x0, x18
+	bl	errata_a77_1508412_wa
+#endif
+
 #if ERRATA_A77_1800714
 	mov	x0, x18
 	bl	errata_a77_1800714_wa
@@ -98,6 +167,7 @@
 	 * Report all errata. The revision-variant information is passed to
 	 * checking functions of each errata.
 	 */
+	report_errata ERRATA_A77_1508412, cortex_a77, 1508412
 	report_errata ERRATA_A77_1800714, cortex_a77, 1800714
 
 	ldp	x8, x30, [sp], #16
diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S
index da663be..730b09b 100644
--- a/lib/cpus/aarch64/cpu_helpers.S
+++ b/lib/cpus/aarch64/cpu_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -140,6 +140,13 @@
 	 * midr of the core. It reads the MIDR_EL1 and finds the matching
 	 * entry in cpu_ops entries. Only the implementation and part number
 	 * are used to match the entries.
+	 *
+	 * If cpu_ops for the MIDR_EL1 cannot be found and
+	 * SUPPORT_UNKNOWN_MPID is enabled, it will try to look for a
+	 * default cpu_ops with an MIDR value of 0.
+	 * (Implementation number 0x0 should be reseverd for software use
+	 * and therefore no clashes should happen with that default value).
+	 *
 	 * Return :
 	 *     x0 - The matching cpu_ops pointer on Success
 	 *     x0 - 0 on failure.
@@ -147,23 +154,26 @@
 	 */
 	.globl	get_cpu_ops_ptr
 func get_cpu_ops_ptr
-	/* Get the cpu_ops start and end locations */
-	adr	x4, (__CPU_OPS_START__ + CPU_MIDR)
-	adr	x5, (__CPU_OPS_END__ + CPU_MIDR)
-
-	/* Initialize the return parameter */
-	mov	x0, #0
-
 	/* Read the MIDR_EL1 */
 	mrs	x2, midr_el1
 	mov_imm	x3, CPU_IMPL_PN_MASK
 
 	/* Retain only the implementation and part number using mask */
 	and	w2, w2, w3
+
+	/* Get the cpu_ops end location */
+	adr	x5, (__CPU_OPS_END__ + CPU_MIDR)
+
+	/* Initialize the return parameter */
+	mov	x0, #0
 1:
+	/* Get the cpu_ops start location */
+	adr	x4, (__CPU_OPS_START__ + CPU_MIDR)
+
+2:
 	/* Check if we have reached end of list */
 	cmp	x4, x5
-	b.eq	error_exit
+	b.eq	search_def_ptr
 
 	/* load the midr from the cpu_ops */
 	ldr	x1, [x4], #CPU_OPS_SIZE
@@ -171,7 +181,7 @@
 
 	/* Check if midr matches to midr of this core */
 	cmp	w1, w2
-	b.ne	1b
+	b.ne	2b
 
 	/* Subtract the increment and offset to get the cpu-ops pointer */
 	sub	x0, x4, #(CPU_OPS_SIZE + CPU_MIDR)
@@ -179,7 +189,27 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif
+#ifdef SUPPORT_UNKNOWN_MPID
+	cbnz	x2, exit_mpid_found
+	/* Mark the unsupported MPID flag */
+	adrp	x1, unsupported_mpid_flag
+	add	x1, x1, :lo12:unsupported_mpid_flag
+	str	w2, [x1]
+exit_mpid_found:
+#endif
+	ret
+
+	/*
+	 * Search again for a default pointer (MIDR = 0x0)
+	 * or return error if already searched.
+	 */
+search_def_ptr:
+#ifdef SUPPORT_UNKNOWN_MPID
+	cbz	x2, error_exit
+	mov	x2, #0
+	b	1b
 error_exit:
+#endif
 	ret
 endfunc get_cpu_ops_ptr
 
diff --git a/lib/cpus/aarch64/generic.S b/lib/cpus/aarch64/generic.S
new file mode 100644
index 0000000..ef1f048
--- /dev/null
+++ b/lib/cpus/aarch64/generic.S
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <generic.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+	/* ---------------------------------------------
+	 * Disable L1 data cache and unified L2 cache
+	 * ---------------------------------------------
+	 */
+func generic_disable_dcache
+	mrs	x1, sctlr_el3
+	bic	x1, x1, #SCTLR_C_BIT
+	msr	sctlr_el3, x1
+	isb
+	ret
+endfunc generic_disable_dcache
+
+func generic_core_pwr_dwn
+	mov	x18, x30
+
+	/* ---------------------------------------------
+	 * Turn off caches.
+	 * ---------------------------------------------
+	 */
+	bl	generic_disable_dcache
+
+	/* ---------------------------------------------
+	 * Flush L1 caches.
+	 * ---------------------------------------------
+	 */
+	mov	x0, #DCCISW
+	bl	dcsw_op_level1
+
+	ret	x18
+endfunc generic_core_pwr_dwn
+
+func generic_cluster_pwr_dwn
+	mov	x18, x30
+
+	/* ---------------------------------------------
+	 * Turn off caches.
+	 * ---------------------------------------------
+	 */
+	bl	generic_disable_dcache
+
+	/* ---------------------------------------------
+	 * Flush L1 caches.
+	 * ---------------------------------------------
+	 */
+	mov	x0, #DCCISW
+	bl	dcsw_op_level1
+
+	/* ---------------------------------------------
+	 * Disable the optional ACP.
+	 * ---------------------------------------------
+	 */
+	bl	plat_disable_acp
+
+	/* ---------------------------------------------
+	 * Flush L2 caches.
+	 * ---------------------------------------------
+	 */
+	mov	x0, #DCCISW
+	bl	dcsw_op_level2
+
+	ret	x18
+
+endfunc generic_cluster_pwr_dwn
+
+/* ---------------------------------------------
+ * Unimplemented functions.
+ * ---------------------------------------------
+ */
+.equ	generic_errata_report,		0
+.equ	generic_cpu_reg_dump,		0
+.equ	generic_reset_func,		0
+
+declare_cpu_ops generic, AARCH64_GENERIC_MIDR, \
+	generic_reset_func, \
+	generic_core_pwr_dwn, \
+	generic_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/rainier.S b/lib/cpus/aarch64/rainier.S
new file mode 100644
index 0000000..f7afd0b
--- /dev/null
+++ b/lib/cpus/aarch64/rainier.S
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <context.h>
+#include <cpu_macros.S>
+#include <cpuamu.h>
+#include <rainier.h>
+
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Rainier CPU must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
+/* 64-bit only core */
+#if CTX_INCLUDE_AARCH32_REGS == 1
+#error "Rainier CPU supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
+#endif
+
+#if ERRATA_RAINIER_IC_TRAP
+	.global rainier_errata_ic_trap_handler
+#endif
+
+/* --------------------------------------------------
+ * Disable speculative loads if Rainier supports
+ * SSBS.
+ *
+ * Shall clobber: x0.
+ * --------------------------------------------------
+ */
+func rainier_disable_speculative_loads
+	/* Check if the PE implements SSBS */
+	mrs	x0, id_aa64pfr1_el1
+	tst	x0, #(ID_AA64PFR1_EL1_SSBS_MASK << ID_AA64PFR1_EL1_SSBS_SHIFT)
+	b.eq	1f
+
+	/* Disable speculative loads */
+	msr	SSBS, xzr
+
+1:
+	ret
+endfunc rainier_disable_speculative_loads
+
+/* --------------------------------------------------
+ * Errata Workaround for Neoverse N1 Erratum 1542419.
+ * This applies to revisions r3p0 - r4p0 of Neoverse N1
+ * Since Rainier core is based on Neoverse N1 r4p0, this
+ * errata applies to Rainier core r0p0
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_n1_1542419_wa
+	/* Compare x0 against revision r3p0 and r4p0 */
+	mov	x17, x30
+	bl	check_errata_1542419
+	cbz	x0, 1f
+
+        /* Apply instruction patching sequence */
+	mov	x0, xzr
+	msr	CPUPSELR_EL3, x0
+	ldr	x0, =0xEE670D35
+	msr	CPUPOR_EL3, x0
+	ldr	x0, =0xFFFF0FFF
+	msr	CPUPMR_EL3, x0
+	ldr	x0, =0x08000020007D
+	msr	CPUPCR_EL3, x0
+	isb
+1:
+	ret	x17
+endfunc errata_n1_1542419_wa
+
+func check_errata_1542419
+	/* Applies to Rainier core r0p0. */
+	mov	x1, #0x00
+	b	cpu_rev_var_ls
+endfunc check_errata_1542419
+
+func rainier_reset_func
+	mov	x19, x30
+
+	bl	rainier_disable_speculative_loads
+
+	/* Forces all cacheable atomic instructions to be near */
+	mrs	x0, RAINIER_CPUACTLR2_EL1
+	orr	x0, x0, #RAINIER_CPUACTLR2_EL1_BIT_2
+	msr	RAINIER_CPUACTLR2_EL1, x0
+	isb
+
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_N1_1542419
+	mov	x0, x18
+	bl	errata_n1_1542419_wa
+#endif
+
+#if ENABLE_AMU
+	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
+	mrs	x0, actlr_el3
+	orr	x0, x0, #RAINIER_ACTLR_AMEN_BIT
+	msr	actlr_el3, x0
+
+	/* Make sure accesses from EL0/EL1 are not trapped to EL2 */
+	mrs	x0, actlr_el2
+	orr	x0, x0, #RAINIER_ACTLR_AMEN_BIT
+	msr	actlr_el2, x0
+
+	/* Enable group0 counters */
+	mov	x0, #RAINIER_AMU_GROUP0_MASK
+	msr	CPUAMCNTENSET_EL0, x0
+#endif
+
+	isb
+	ret	x19
+endfunc rainier_reset_func
+
+	/* ---------------------------------------------
+	 * HW will do the cache maintenance while powering down
+	 * ---------------------------------------------
+	 */
+func rainier_core_pwr_dwn
+	/* ---------------------------------------------
+	 * Enable CPU power down bit in power control register
+	 * ---------------------------------------------
+	 */
+	mrs	x0, RAINIER_CPUPWRCTLR_EL1
+	orr	x0, x0, #RAINIER_CORE_PWRDN_EN_MASK
+	msr	RAINIER_CPUPWRCTLR_EL1, x0
+	isb
+	ret
+endfunc rainier_core_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Rainier. Must follow AAPCS.
+ */
+func rainier_errata_report
+	stp	x8, x30, [sp, #-16]!
+
+	bl	cpu_get_rev_var
+	mov	x8, x0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_N1_1542419, rainier, 1542419
+
+	ldp	x8, x30, [sp], #16
+	ret
+endfunc rainier_errata_report
+#endif
+
+/*
+ * Handle trap of EL0 IC IVAU instructions to EL3 by executing a TLB
+ * inner-shareable invalidation to an arbitrary address followed by a DSB.
+ *
+ * x1: Exception Syndrome
+ */
+func rainier_errata_ic_trap_handler
+	cmp	x1, #RAINIER_EC_IC_TRAP
+	b.ne	1f
+	tlbi	vae3is, xzr
+	dsb	sy
+
+        # Skip the IC instruction itself
+        mrs     x3, elr_el3
+        add     x3, x3, #4
+        msr     elr_el3, x3
+
+	ldp	x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+	ldp	x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
+	ldp	x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
+	ldr	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+
+#if IMAGE_BL31 && RAS_EXTENSION
+	/*
+	 * Issue Error Synchronization Barrier to synchronize SErrors before
+	 * exiting EL3. We're running with EAs unmasked, so any synchronized
+	 * errors would be taken immediately; therefore no need to inspect
+	 * DISR_EL1 register.
+	 */
+	esb
+#endif
+	eret
+1:
+	ret
+endfunc rainier_errata_ic_trap_handler
+
+	/* ---------------------------------------------
+	 * This function provides Rainier specific
+	 * register information for crash reporting.
+	 * It needs to return with x6 pointing to
+	 * a list of register names in ascii and
+	 * x8 - x15 having values of registers to be
+	 * reported.
+	 * ---------------------------------------------
+	 */
+.section .rodata.rainier_regs, "aS"
+rainier_regs:  /* The ascii list of register names to be reported */
+	.asciz	"cpuectlr_el1", ""
+
+func rainier_cpu_reg_dump
+	adr	x6, rainier_regs
+	mrs	x8, RAINIER_CPUECTLR_EL1
+	ret
+endfunc rainier_cpu_reg_dump
+
+declare_cpu_ops_eh rainier, RAINIER_MIDR, \
+	rainier_reset_func, \
+	rainier_errata_ic_trap_handler, \
+	rainier_core_pwr_dwn
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 7cd8ed9..5df94cc 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -278,6 +278,10 @@
 # to all revisions of Cortex A76 cpu.
 ERRATA_A76_1165522	?=0
 
+# Flag to apply erratum 1508412 workaround during reset. This erratum applies
+# only to revision <= r1p0 of the Cortex A77 cpu.
+ERRATA_A77_1508412	?=0
+
 # Flag to apply erratum 1800714 workaround during reset. This erratum applies
 # only to revision <= r1p1 of the Cortex A77 cpu.
 ERRATA_A77_1800714	?=0
@@ -551,6 +555,10 @@
 $(eval $(call assert_boolean,ERRATA_A76_1165522))
 $(eval $(call add_define,ERRATA_A76_1165522))
 
+# Process ERRATA_A77_1508412 flag
+$(eval $(call assert_boolean,ERRATA_A77_1508412))
+$(eval $(call add_define,ERRATA_A77_1508412))
+
 # Process ERRATA_A77_1800714 flag
 $(eval $(call assert_boolean,ERRATA_A77_1800714))
 $(eval $(call add_define,ERRATA_A77_1800714))
diff --git a/lib/libc/aarch32/memset.S b/lib/libc/aarch32/memset.S
new file mode 100644
index 0000000..880ba83
--- /dev/null
+++ b/lib/libc/aarch32/memset.S
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+	.syntax unified
+	.global	memset
+
+/* -----------------------------------------------------------------------
+ * void *memset(void *dst, int val, size_t count)
+ *
+ * Copy the value of 'val' (converted to an unsigned char) into
+ * each of the first 'count' characters of the object pointed to by 'dst'.
+ *
+ * Returns the value of 'dst'.
+ * -----------------------------------------------------------------------
+ */
+func memset
+	mov	r12, r0			/* keep r0 */
+	tst	r0, #3
+	beq	aligned			/* 4-bytes aligned */
+
+	/* Unaligned 'dst' */
+unaligned:
+	subs	r2, r2, #1
+	strbhs	r1, [r12], #1
+	bxls	lr			/* return if 0 */
+	tst	r12, #3
+	bne	unaligned		/* continue while unaligned */
+
+	/* 4-bytes aligned */
+aligned:bfi	r1, r1, #8, #8		/* propagate 'val' */
+	bfi	r1, r1, #16, #16
+
+	mov	r3, r1
+
+	cmp	r2, #16
+	blo	less_16			/* < 16 */
+
+	push	{r4, lr}
+	mov	r4, r1
+	mov	lr, r1
+
+write_32:
+	subs	r2, r2, #32
+	stmiahs	r12!, {r1, r3, r4, lr}
+	stmiahs	r12!, {r1, r3, r4, lr}
+	bhi	write_32		/* write 32 bytes in a loop */
+	popeq	{r4, pc}		/* return if 0 */
+	lsls	r2, r2, #28		/* C = r2[4]; N = r2[3]; Z = r2[3:0] */
+	stmiacs	r12!, {r1, r3, r4, lr}	/* write 16 bytes */
+	popeq	{r4, pc}		/* return if 16 */
+	stmiami	r12!, {r1, r3}		/* write 8 bytes */
+	lsls	r2, r2, #2		/* C = r2[2]; N = r2[1]; Z = r2[1:0] */
+	strcs	r1, [r12], #4		/* write 4 bytes */
+	popeq	{r4, pc}		/* return if 8 or 4 */
+	strhmi	r1, [r12], #2		/* write 2 bytes */
+	lsls	r2, r2, #1		/* N = Z = r2[0] */
+	strbmi	r1, [r12]		/* write 1 byte */
+	pop	{r4, pc}
+
+less_16:lsls	r2, r2, #29		/* C = r2[3]; N = r2[2]; Z = r2[2:0] */
+	stmiacs	r12!, {r1, r3}		/* write 8 bytes */
+	bxeq	lr			/* return if 8 */
+	strmi	r1, [r12], #4		/* write 4 bytes */
+	lsls	r2, r2, #2		/* C = r2[1]; N = Z = r2[0] */
+	strhcs	r1, [r12], #2		/* write 2 bytes */
+	strbmi	r1, [r12]		/* write 1 byte */
+	bx	lr
+
+endfunc memset
diff --git a/lib/libc/aarch64/memset.S b/lib/libc/aarch64/memset.S
new file mode 100644
index 0000000..0543704
--- /dev/null
+++ b/lib/libc/aarch64/memset.S
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+	.global	memset
+
+/* -----------------------------------------------------------------------
+ * void *memset(void *dst, int val, size_t count)
+ *
+ * Copy the value of 'val' (converted to an unsigned char) into
+ * each of the first 'count' characters of the object pointed to by 'dst'.
+ *
+ * Returns the value of 'dst'.
+ * -----------------------------------------------------------------------
+ */
+func memset
+	cbz	x2, exit		/* exit if 'count' = 0 */
+	mov	x3, x0			/* keep x0 */
+	tst	x0, #7
+	b.eq	aligned			/* 8-bytes aligned */
+
+	/* Unaligned 'dst' */
+unaligned:
+	strb	w1, [x3], #1
+	subs	x2, x2, #1
+	b.eq	exit			/* exit if 0 */
+	tst	x3, #7
+	b.ne	unaligned		/* continue while unaligned */
+
+	/* 8-bytes aligned */
+aligned:cbz	x1, x1_zero
+	bfi	w1, w1, #8, #8		/* propagate 'val' */
+	bfi	w1, w1, #16, #16
+	bfi	x1, x1, #32, #32
+
+x1_zero:ands	x4, x2, #~0x3f
+	b.eq	less_64
+
+write_64:
+	.rept	4
+	stp	x1, x1, [x3], #16	/* write 64 bytes in a loop */
+	.endr
+	subs	x4, x4, #64
+	b.ne	write_64
+less_64:tbz	w2, #5, less_32		/* < 32 bytes */
+	stp	x1, x1, [x3], #16	/* write 32 bytes */
+	stp	x1, x1, [x3], #16
+less_32:tbz	w2, #4, less_16		/* < 16 bytes */
+	stp	x1, x1, [x3], #16	/* write 16 bytes */
+less_16:tbz	w2, #3, less_8		/* < 8 bytes */
+	str	x1, [x3], #8		/* write 8 bytes */
+less_8:	tbz	w2, #2, less_4		/* < 4 bytes */
+	str	w1, [x3], #4		/* write 4 bytes */
+less_4:	tbz	w2, #1, less_2		/* < 2 bytes */
+	strh	w1, [x3], #2		/* write 2 bytes */
+less_2:	tbz	w2, #0, exit
+	strb	w1, [x3]		/* write 1 byte */
+exit:	ret
+
+endfunc	memset
diff --git a/lib/libc/libc_asm.mk b/lib/libc/libc_asm.mk
new file mode 100644
index 0000000..6416a3c
--- /dev/null
+++ b/lib/libc/libc_asm.mk
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LIBC_SRCS	:=	$(addprefix lib/libc/,		\
+			abort.c				\
+			assert.c			\
+			exit.c				\
+			memchr.c			\
+			memcmp.c			\
+			memcpy.c			\
+			memmove.c			\
+			memrchr.c			\
+			printf.c			\
+			putchar.c			\
+			puts.c				\
+			snprintf.c			\
+			strchr.c			\
+			strcmp.c			\
+			strlcpy.c			\
+			strlen.c			\
+			strncmp.c			\
+			strnlen.c			\
+			strrchr.c)
+
+ifeq (${ARCH},aarch64)
+LIBC_SRCS	+=	$(addprefix lib/libc/aarch64/,	\
+			memset.S			\
+			setjmp.S)
+else
+LIBC_SRCS	+=	$(addprefix lib/libc/aarch32/,	\
+			memset.S)
+endif
+
+INCLUDES	+=	-Iinclude/lib/libc		\
+			-Iinclude/lib/libc/$(ARCH)	\
diff --git a/lib/libc/strtok.c b/lib/libc/strtok.c
new file mode 100644
index 0000000..7e1a4d2
--- /dev/null
+++ b/lib/libc/strtok.c
@@ -0,0 +1,83 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1998 Softweyr LLC.  All rights reserved.
+ *
+ * strtok_r, from Berkeley strtok
+ * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
+ *
+ * Copyright (c) 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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
+ *    notices, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notices, 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 SOFTWEYR LLC, 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 SOFTWEYR LLC, 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 <string.h>
+
+char *
+strtok_r(char *s, const char *delim, char **last)
+{
+	char *spanp, *tok;
+	int c, sc;
+
+	if (s == NULL && (s = *last) == NULL)
+		return (NULL);
+
+	/*
+	 * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+	 */
+cont:
+	c = *s++;
+	for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
+		if (c == sc)
+			goto cont;
+	}
+
+	if (c == 0) {		/* no non-delimiter characters */
+		*last = NULL;
+		return (NULL);
+	}
+	tok = s - 1;
+
+	/*
+	 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+	 * Note that delim must have one NUL; we stop if we see that, too.
+	 */
+	for (;;) {
+		c = *s++;
+		spanp = (char *)delim;
+		do {
+			if ((sc = *spanp++) == c) {
+				if (c == 0)
+					s = NULL;
+				else
+					s[-1] = '\0';
+				*last = s;
+				return (tok);
+			}
+		} while (sc != 0);
+	}
+	/* NOTREACHED */
+}
diff --git a/plat/arm/board/arm_fpga/build_axf.ld.S b/plat/arm/board/arm_fpga/build_axf.ld.S
new file mode 100644
index 0000000..d7cd008
--- /dev/null
+++ b/plat/arm/board/arm_fpga/build_axf.ld.S
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Linker script for the Arm Ltd. FPGA boards to generate an ELF file that
+ * contains the ROM trampoline, BL31 and the DTB.
+ *
+ * This allows to pass just one file to the uploader tool, and automatically
+ * provides the correct load addresses.
+ */
+
+#include <platform_def.h>
+
+OUTPUT_FORMAT("elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+
+INPUT(./bl31/bl31.elf)
+INPUT(./rom_trampoline.o)
+
+TARGET(binary)
+INPUT(./fdts/arm_fpga.dtb)
+
+ENTRY(_start)
+
+SECTIONS
+{
+	.rom (0x0): {
+		*rom_trampoline.o(.text*)
+		KEEP(*(.rom))
+	}
+
+	.bl31 (BL31_BASE): {
+		ASSERT(. == ALIGN(PAGE_SIZE), "BL31_BASE is not page aligned");
+		*bl31.elf(.text* .data* .rodata* ro* .bss*)
+		*bl31.elf(.stack)
+	}
+
+	.dtb (FPGA_PRELOADED_DTB_BASE): {
+		ASSERT(. == ALIGN(8), "DTB address is not 8-byte aligned");
+		*arm_fpga.dtb
+	}
+
+	/DISCARD/ : { *(.debug_*) }
+	/DISCARD/ : { *(.note*) }
+	/DISCARD/ : { *(.comment*) }
+}
diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
index de6d9d5..a5f5ea0 100644
--- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c
+++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
@@ -9,8 +9,10 @@
 
 #include <common/fdt_fixup.h>
 #include <common/fdt_wrappers.h>
+#include <drivers/arm/gicv3.h>
 #include <drivers/delay_timer.h>
 #include <drivers/generic_delay_timer.h>
+#include <lib/extensions/spe.h>
 #include <libfdt.h>
 
 #include "fpga_private.h"
@@ -210,6 +212,26 @@
 		if (err < 0) {
 			ERROR("Error %d creating the /cpus DT node\n", err);
 			panic();
+		} else {
+			unsigned int nr_cores = fpga_get_nr_gic_cores();
+
+			INFO("Adjusting GICR DT region to cover %u cores\n",
+			      nr_cores);
+			err = fdt_adjust_gic_redist(fdt, nr_cores,
+						    1U << GICR_PCPUBASE_SHIFT);
+			if (err < 0) {
+				ERROR("Error %d fixing up GIC DT node\n", err);
+			}
+		}
+	}
+
+	/* Check whether we support the SPE PMU. Remove the DT node if not. */
+	if (!spe_supported()) {
+		int node = fdt_node_offset_by_compatible(fdt, 0,
+				     "arm,statistical-profiling-extension-v1");
+
+		if (node >= 0) {
+			fdt_del_node(fdt, node);
 		}
 	}
 
diff --git a/plat/arm/board/arm_fpga/fpga_gicv3.c b/plat/arm/board/arm_fpga/fpga_gicv3.c
index 9fb5fa9..bfc116b 100644
--- a/plat/arm/board/arm_fpga/fpga_gicv3.c
+++ b/plat/arm/board/arm_fpga/fpga_gicv3.c
@@ -77,3 +77,8 @@
 	gicv3_cpuif_disable(plat_my_core_pos());
 	gicv3_rdistif_off(plat_my_core_pos());
 }
+
+unsigned int fpga_get_nr_gic_cores(void)
+{
+	return gicv3_rdistif_get_number_frames(fpga_gicv3_driver_data.gicr_base);
+}
diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h
index 47059d6..1ca241f 100644
--- a/plat/arm/board/arm_fpga/fpga_private.h
+++ b/plat/arm/board/arm_fpga/fpga_private.h
@@ -24,6 +24,7 @@
 void fpga_pwr_gic_on_finish(void);
 void fpga_pwr_gic_off(void);
 unsigned int plat_fpga_calc_core_pos(uint32_t mpid);
+unsigned int fpga_get_nr_gic_cores(void);
 
 #endif /* __ASSEMBLER__ */
 
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index 8904339..ab576b6 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2020, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -40,6 +40,8 @@
 
 PL011_GENERIC_UART	:=	1
 
+SUPPORT_UNKNOWN_MPID	?=	1
+
 FPGA_CPU_LIBS	:=	lib/cpus/${ARCH}/aem_generic.S
 
 # select a different set of CPU files, depending on whether we compile for
@@ -71,6 +73,12 @@
 				lib/cpus/aarch64/cortex_a75.S
 endif
 
+ifeq (${SUPPORT_UNKNOWN_MPID}, 1)
+# Add support for unknown/invalid MPIDs (aarch64 only)
+$(eval $(call add_define,SUPPORT_UNKNOWN_MPID))
+	FPGA_CPU_LIBS	+=	lib/cpus/aarch64/generic.S
+endif
+
 # Allow detection of GIC-600
 GICV3_SUPPORT_GIC600	:=	1
 
@@ -81,6 +89,8 @@
 				plat/common/plat_gicv3.c		\
 				plat/arm/board/arm_fpga/fpga_gicv3.c
 
+FDT_SOURCES		:=	fdts/arm_fpga.dts
+
 PLAT_INCLUDES		:=	-Iplat/arm/board/arm_fpga/include
 
 PLAT_BL_COMMON_SOURCES	:=	plat/arm/board/arm_fpga/${ARCH}/fpga_helpers.S
@@ -98,4 +108,11 @@
 				${FPGA_CPU_LIBS}				\
 				${FPGA_GIC_SOURCES}
 
+$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/rom_trampoline.S,31))
+$(eval $(call MAKE_LD,$(BUILD_PLAT)/build_axf.ld,plat/arm/board/arm_fpga/build_axf.ld.S,31))
+
+bl31.axf: bl31 dtbs ${BUILD_PLAT}/rom_trampoline.o ${BUILD_PLAT}/build_axf.ld
+	$(ECHO) "  LD      $@"
+	$(Q)$(LD) -T ${BUILD_PLAT}/build_axf.ld -L ${BUILD_PLAT} --strip-debug -o ${BUILD_PLAT}/bl31.axf
+
-all: bl31
+all: bl31.axf
diff --git a/plat/arm/board/arm_fpga/rom_trampoline.S b/plat/arm/board/arm_fpga/rom_trampoline.S
new file mode 100644
index 0000000..cd66c79
--- /dev/null
+++ b/plat/arm/board/arm_fpga/rom_trampoline.S
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * The Arm Ltd. FPGA images start execution at address 0x0, which is
+ * mapped at an (emulated) ROM image. The payload uploader can write to
+ * this memory, but write access by the CPU cores is prohibited.
+ *
+ * Provide a simple trampoline to start BL31 execution at the actual
+ * load address. We put the DTB address in x0, so any code in DRAM could
+ * make use of that information (not yet used in BL31 right now).
+ */
+
+#include <asm_macros.S>
+#include <common/bl_common.ld.h>
+
+.text
+.global _start
+
+_start:
+	mov_imm	x1, BL31_BASE			/* beginning of DRAM */
+	mov_imm	x0, FPGA_PRELOADED_DTB_BASE
+	br	x1
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
index ca42da0..934a01a 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -44,14 +44,14 @@
 			is_ffa_partition;
 			debug_name = "cactus-secondary";
 			load_address = <0x7100000>;
-			vcpu_count = <2>;
+			vcpu_count = <8>;
 			mem_size = <1048576>;
 		};
 		vm3 {
 			is_ffa_partition;
 			debug_name = "cactus-tertiary";
 			load_address = <0x7200000>;
-			vcpu_count = <2>;
+			vcpu_count = <8>;
 			mem_size = <1048576>;
 		};
 	};
diff --git a/plat/arm/board/morello/aarch64/morello_helper.S b/plat/arm/board/morello/aarch64/morello_helper.S
new file mode 100644
index 0000000..60470a8
--- /dev/null
+++ b/plat/arm/board/morello/aarch64/morello_helper.S
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+#include <rainier.h>
+
+#include <platform_def.h>
+
+	.globl	plat_arm_calc_core_pos
+	.globl	plat_reset_handler
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+	 *
+	 * Helper function to calculate the core position.
+	 * ((ChipId * MORELLO_MAX_CLUSTERS_PER_CHIP + ClusterId) *
+	 * MORELLO_MAX_CPUS_PER_CLUSTER * MORELLO_MAX_PE_PER_CPU) +
+	 * (CPUId * MORELLO_MAX_PE_PER_CPU) + ThreadId
+	 *
+	 * which can be simplified as:
+	 *
+	 * (((ChipId * MORELLO_MAX_CLUSTERS_PER_CHIP + ClusterId) *
+	 * MORELLO_MAX_CPUS_PER_CLUSTER + CPUId) * MORELLO_MAX_PE_PER_CPU) +
+	 * ThreadId
+	 * ------------------------------------------------------
+	 */
+
+func plat_arm_calc_core_pos
+	mov	x4, x0
+
+	/*
+	 * The MT bit in MPIDR is always set for morello and the
+	 * affinity level 0 corresponds to thread affinity level.
+	 */
+
+	/* Extract individual affinity fields from MPIDR */
+	ubfx	x0, x4, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x1, x4, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x2, x4, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x3, x4, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS
+
+	/* Compute linear position */
+	mov	x4, #MORELLO_MAX_CLUSTERS_PER_CHIP
+	madd	x2, x3, x4, x2
+	mov	x4, #MORELLO_MAX_CPUS_PER_CLUSTER
+	madd	x1, x2, x4, x1
+	mov	x4, #MORELLO_MAX_PE_PER_CPU
+	madd	x0, x1, x4, x0
+	ret
+endfunc plat_arm_calc_core_pos
diff --git a/plat/arm/board/morello/include/plat_macros.S b/plat/arm/board/morello/include/plat_macros.S
new file mode 100644
index 0000000..195be84
--- /dev/null
+++ b/plat/arm/board/morello/include/plat_macros.S
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <css_macros.S>
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ *
+ * There are currently no platform specific regs
+ * to print.
+ * ---------------------------------------------
+ */
+	.macro plat_crash_print_regs
+	.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/arm/board/morello/include/platform_def.h b/plat/arm/board/morello/include/platform_def.h
new file mode 100644
index 0000000..07c06a1
--- /dev/null
+++ b/plat/arm/board/morello/include/platform_def.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/common/arm_def.h>
+#include <plat/arm/css/common/css_def.h>
+
+/* UART related constants */
+#define PLAT_ARM_BOOT_UART_BASE 		ULL(0x2A400000)
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ		U(50000000)
+
+#define PLAT_ARM_RUN_UART_BASE			ULL(0x2A410000)
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ		U(50000000)
+
+#define PLAT_ARM_CRASH_UART_BASE		PLAT_ARM_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ		PLAT_ARM_RUN_UART_CLK_IN_HZ
+
+#define PLAT_ARM_DRAM2_BASE			ULL(0x8080000000)
+#define PLAT_ARM_DRAM2_SIZE			ULL(0xF80000000)
+
+/*
+ * To access the complete DDR memory along with remote chip's DDR memory,
+ * which is at 4 TB offset, physical and virtual address space limits are
+ * extended to 43-bits.
+ */
+#define PLAT_PHY_ADDR_SPACE_SIZE		(1ULL << 43)
+#define PLAT_VIRT_ADDR_SPACE_SIZE		(1ULL << 43)
+
+#if CSS_USE_SCMI_SDS_DRIVER
+#define MORELLO_SCMI_PAYLOAD_BASE		ULL(0x45400000)
+#else
+#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE	ULL(0x45400000)
+#endif
+
+#define PLAT_ARM_TRUSTED_SRAM_SIZE		UL(0x00080000)
+#define PLAT_ARM_MAX_BL31_SIZE			UL(0x20000)
+
+/*******************************************************************************
+ * MORELLO topology related constants
+ ******************************************************************************/
+#define MORELLO_MAX_CPUS_PER_CLUSTER		U(2)
+#define PLAT_ARM_CLUSTER_COUNT			U(2)
+#define PLAT_MORELLO_CHIP_COUNT			U(1)
+#define MORELLO_MAX_CLUSTERS_PER_CHIP		U(2)
+#define MORELLO_MAX_PE_PER_CPU			U(1)
+
+#define PLATFORM_CORE_COUNT			(PLAT_MORELLO_CHIP_COUNT *	\
+						PLAT_ARM_CLUSTER_COUNT *	\
+						MORELLO_MAX_CPUS_PER_CLUSTER *	\
+						MORELLO_MAX_PE_PER_CPU)
+
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL			ARM_PWR_LVL3
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+#define PLAT_ARM_MMAP_ENTRIES			U(9)
+#define MAX_XLAT_TABLES				U(10)
+
+#define PLATFORM_STACK_SIZE			U(0x400)
+
+#define PLAT_ARM_NSTIMER_FRAME_ID		U(0)
+#define PLAT_CSS_MHU_BASE			UL(0x45000000)
+#define PLAT_MHUV2_BASE				PLAT_CSS_MHU_BASE
+#define PLAT_MAX_PWR_LVL			U(2)
+
+#define PLAT_ARM_G1S_IRQ_PROPS(grp)		CSS_G1S_IRQ_PROPS(grp)
+#define PLAT_ARM_G0_IRQ_PROPS(grp)		ARM_G0_IRQ_PROPS(grp)
+
+#define MORELLO_DEVICE_BASE			ULL(0x08000000)
+#define MORELLO_DEVICE_SIZE			ULL(0x48000000)
+
+#define MORELLO_MAP_DEVICE			MAP_REGION_FLAT(	\
+						MORELLO_DEVICE_BASE,	\
+						MORELLO_DEVICE_SIZE,	\
+						MT_DEVICE | MT_RW | MT_SECURE)
+
+#define ARM_MAP_DRAM1				MAP_REGION_FLAT(	\
+						ARM_DRAM1_BASE,		\
+						ARM_DRAM1_SIZE,		\
+						MT_MEMORY | MT_RW | MT_NS)
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE			UL(0x30000000)
+#define PLAT_ARM_GICC_BASE			UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE			UL(0x300C0000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/morello/morello_bl31_setup.c b/plat/arm/board/morello/morello_bl31_setup.c
new file mode 100644
index 0000000..43f5f7f
--- /dev/null
+++ b/plat/arm/board/morello/morello_bl31_setup.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/css/css_mhu_doorbell.h>
+#include <drivers/arm/css/scmi.h>
+#include <drivers/arm/css/sds.h>
+#include <plat/arm/common/plat_arm.h>
+
+#include "morello_def.h"
+#include <platform_def.h>
+
+/*
+ * 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
+ */
+struct morello_plat_info {
+	bool multichip_mode;
+	uint8_t slave_count;
+	uint8_t local_ddr_size;
+	uint8_t remote_ddr_size;
+} __packed;
+
+/*
+ * BL33 image information structure stored in SDS.
+ * This structure holds the source & destination addresses and
+ * the size of the BL33 image which will be loaded by BL31.
+ */
+struct morello_bl33_info {
+	uint32_t bl33_src_addr;
+	uint32_t bl33_dst_addr;
+	uint32_t bl33_size;
+};
+
+static scmi_channel_plat_info_t morello_scmi_plat_info = {
+	.scmi_mbx_mem = MORELLO_SCMI_PAYLOAD_BASE,
+	.db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
+	.db_preserve_mask = 0xfffffffe,
+	.db_modify_mask = 0x1,
+	.ring_doorbell = &mhu_ring_doorbell
+};
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info()
+{
+	return &morello_scmi_plat_info;
+}
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return css_scmi_override_pm_ops(ops);
+}
+
+static void copy_bl33(uint32_t src, uint32_t dst, uint32_t size)
+{
+	unsigned int i;
+
+	INFO("Copying BL33 to DDR memory...\n");
+	for (i = 0U; i < size; (i = i + 8U))
+		mmio_write_64((dst + i), mmio_read_64(src + i));
+
+	for (i = 0U; i < size; (i = i + 8U)) {
+		if (mmio_read_64(src + i) != mmio_read_64(dst + i)) {
+			ERROR("Copy failed!\n");
+			panic();
+		}
+	}
+	INFO("done\n");
+}
+
+void bl31_platform_setup(void)
+{
+	int ret;
+	struct morello_plat_info plat_info;
+	struct morello_bl33_info bl33_info;
+
+	ret = sds_init();
+	if (ret != SDS_OK) {
+		ERROR("SDS initialization failed. ret:%d\n", ret);
+		panic();
+	}
+
+	ret = sds_struct_read(MORELLO_SDS_PLATFORM_INFO_STRUCT_ID,
+				MORELLO_SDS_PLATFORM_INFO_OFFSET,
+				&plat_info,
+				MORELLO_SDS_PLATFORM_INFO_SIZE,
+				SDS_ACCESS_MODE_NON_CACHED);
+	if (ret != SDS_OK) {
+		ERROR("Error getting platform info from SDS. ret:%d\n", ret);
+		panic();
+	}
+
+	/* 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.slave_count > MORELLO_MAX_SLAVE_COUNT)) {
+		ERROR("platform info SDS is corrupted\n");
+		panic();
+	}
+
+	arm_bl31_platform_setup();
+
+	ret = sds_struct_read(MORELLO_SDS_BL33_INFO_STRUCT_ID,
+				MORELLO_SDS_BL33_INFO_OFFSET,
+				&bl33_info,
+				MORELLO_SDS_BL33_INFO_SIZE,
+				SDS_ACCESS_MODE_NON_CACHED);
+	if (ret != SDS_OK) {
+		ERROR("Error getting BL33 info from SDS. ret:%d\n", ret);
+		panic();
+	}
+	copy_bl33(bl33_info.bl33_src_addr,
+			bl33_info.bl33_dst_addr,
+			bl33_info.bl33_size);
+	/*
+	 * Pass platform information to BL33. This method is followed as
+	 * currently there is no BL1/BL2 involved in boot flow of MORELLO.
+	 * When TBBR is implemented for MORELLO, this method should be removed
+	 * 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);
+}
diff --git a/plat/arm/board/morello/morello_def.h b/plat/arm/board/morello/morello_def.h
new file mode 100644
index 0000000..09db303
--- /dev/null
+++ b/plat/arm/board/morello/morello_def.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MORELLO_DEF_H
+#define MORELLO_DEF_H
+
+/* Non-secure SRAM MMU mapping */
+#define MORELLO_NS_SRAM_BASE			UL(0x06000000)
+#define MORELLO_NS_SRAM_SIZE			UL(0x00010000)
+#define MORELLO_MAP_NS_SRAM			MAP_REGION_FLAT(	\
+						MORELLO_NS_SRAM_BASE,	\
+						MORELLO_NS_SRAM_SIZE,	\
+						MT_DEVICE | MT_RW | MT_SECURE)
+
+/* 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_MAX_SLAVE_COUNT			U(16)
+
+/* SDS BL33 image information defines */
+#define MORELLO_SDS_BL33_INFO_STRUCT_ID		U(9)
+#define MORELLO_SDS_BL33_INFO_OFFSET		U(0)
+#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)
+
+#endif /* MORELLO_DEF_H */
diff --git a/plat/arm/board/morello/morello_interconnect.c b/plat/arm/board/morello/morello_interconnect.c
new file mode 100644
index 0000000..d941bfe
--- /dev/null
+++ b/plat/arm/board/morello/morello_interconnect.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/*
+ * For MORELLO which supports FCM (with automatic interconnect enter/exit),
+ * we should not do anything in these interface functions.
+ * They are used to override the weak functions in cci drivers.
+ */
+
+/******************************************************************************
+ * Helper function to initialize ARM interconnect driver.
+ *****************************************************************************/
+void plat_arm_interconnect_init(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to place current master into coherency
+ *****************************************************************************/
+void plat_arm_interconnect_enter_coherency(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to remove current master from coherency
+ *****************************************************************************/
+void plat_arm_interconnect_exit_coherency(void)
+{
+}
diff --git a/plat/arm/board/morello/morello_plat.c b/plat/arm/board/morello/morello_plat.c
new file mode 100644
index 0000000..3830687
--- /dev/null
+++ b/plat/arm/board/morello/morello_plat.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+#include "morello_def.h"
+
+/*
+ * Table of regions to map using the MMU.
+ * Replace or extend the below regions as required
+ */
+
+const mmap_region_t plat_arm_mmap[] = {
+	ARM_MAP_SHARED_RAM,
+	MORELLO_MAP_DEVICE,
+	MORELLO_MAP_NS_SRAM,
+	ARM_MAP_DRAM1,
+	{0}
+};
diff --git a/plat/arm/board/morello/morello_security.c b/plat/arm/board/morello/morello_security.c
new file mode 100644
index 0000000..a388a80
--- /dev/null
+++ b/plat/arm/board/morello/morello_security.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * TZC programming is currently not done.
+ */
+void plat_arm_security_setup(void)
+{
+}
diff --git a/plat/arm/board/morello/morello_topology.c b/plat/arm/board/morello/morello_topology.c
new file mode 100644
index 0000000..ef2f753
--- /dev/null
+++ b/plat/arm/board/morello/morello_topology.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/cassert.h>
+#include <plat/arm/common/plat_arm.h>
+
+/* Compile time assertion to ensure the core count is 4 */
+CASSERT(PLATFORM_CORE_COUNT == 4U, assert_invalid_platform_core_count);
+
+/* Topology */
+typedef struct morello_topology {
+	const unsigned char *power_tree;
+	unsigned int plat_cluster_core_count;
+} morello_topology_t;
+
+/*
+ * The power domain tree descriptor. The cluster power domains are
+ * arranged so that when the PSCI generic code creates the power domain tree,
+ * the indices of the CPU power domain nodes it allocates match the linear
+ * indices returned by plat_core_pos_by_mpidr().
+ */
+const unsigned char morello_pd_tree_desc[] = {
+	PLAT_MORELLO_CHIP_COUNT,
+	PLAT_ARM_CLUSTER_COUNT,
+	MORELLO_MAX_CPUS_PER_CLUSTER,
+	MORELLO_MAX_CPUS_PER_CLUSTER,
+};
+
+/* Topology configuration for morello */
+const morello_topology_t morello_topology = {
+	.power_tree = morello_pd_tree_desc,
+	.plat_cluster_core_count = MORELLO_MAX_CPUS_PER_CLUSTER
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return morello_topology.power_tree;
+}
+
+/*******************************************************************************
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ ******************************************************************************/
+unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr)
+{
+	return morello_topology.plat_cluster_core_count;
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = {
+	0, 1, 2, 3};
diff --git a/plat/arm/board/morello/platform.mk b/plat/arm/board/morello/platform.mk
new file mode 100644
index 0000000..f62cd67
--- /dev/null
+++ b/plat/arm/board/morello/platform.mk
@@ -0,0 +1,66 @@
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MORELLO_BASE		:=	plat/arm/board/morello
+
+INTERCONNECT_SOURCES	:=	${MORELLO_BASE}/morello_interconnect.c
+
+PLAT_INCLUDES		:=	-I${MORELLO_BASE}/include
+
+MORELLO_CPU_SOURCES	:=	lib/cpus/aarch64/rainier.S
+
+MORELLO_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
+				drivers/arm/gic/v3/gicv3_main.c		\
+				drivers/arm/gic/v3/gicv3_helpers.c	\
+				plat/common/plat_gicv3.c		\
+				plat/arm/common/arm_gicv3.c		\
+				drivers/arm/gic/v3/gic600.c
+
+PLAT_BL_COMMON_SOURCES	:=	${MORELLO_BASE}/morello_plat.c		\
+				${MORELLO_BASE}/aarch64/morello_helper.S
+
+BL31_SOURCES		:=	${MORELLO_CPU_SOURCES}			\
+				${INTERCONNECT_SOURCES}			\
+				${MORELLO_GIC_SOURCES}			\
+				${MORELLO_BASE}/morello_bl31_setup.c	\
+				${MORELLO_BASE}/morello_topology.c	\
+				${MORELLO_BASE}/morello_security.c	\
+				drivers/arm/css/sds/sds.c
+
+FDT_SOURCES		+=	fdts/morello-fvp.dts
+
+# TF-A not required to load the SCP Images
+override CSS_LOAD_SCP_IMAGES		:=	0
+
+# BL1/BL2 Image not a part of the capsule Image for morello
+override NEED_BL1			:=	no
+override NEED_BL2			:=	no
+override NEED_BL2U			:=	no
+
+#TF-A for morello starts from BL31
+override RESET_TO_BL31			:=	1
+
+# 32 bit mode not supported
+override CTX_INCLUDE_AARCH32_REGS	:=	0
+
+override ARM_PLAT_MT			:=	1
+
+# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the
+# SCP during power management operations and for SCP RAM Firmware transfer.
+CSS_USE_SCMI_SDS_DRIVER			:=	1
+
+# System coherency is managed in hardware
+HW_ASSISTED_COHERENCY			:=	1
+
+# When building for systems with hardware-assisted coherency, there's no need to
+# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
+USE_COHERENT_MEM			:=	0
+
+include plat/arm/common/arm_common.mk
+include plat/arm/css/common/css_common.mk
+include plat/arm/board/common/board_common.mk
+
+override ERRATA_N1_1542419		:=	1
diff --git a/plat/arm/board/tc0/include/platform_def.h b/plat/arm/board/tc0/include/platform_def.h
index a8d471e..075c403 100644
--- a/plat/arm/board/tc0/include/platform_def.h
+++ b/plat/arm/board/tc0/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -191,4 +191,19 @@
  */
 #define PLAT_CSS_MAX_SCP_BL2U_SIZE	0x20000
 
+/* TZC Related Constants */
+#define PLAT_ARM_TZC_BASE		UL(0x25000000)
+#define PLAT_ARM_TZC_FILTERS		TZC_400_REGION_ATTR_FILTER_BIT(0)
+
+#define TZC400_OFFSET			UL(0x1000000)
+#define TZC400_COUNT			4
+
+#define TZC400_BASE(n)			(PLAT_ARM_TZC_BASE + \
+					 (n * TZC400_OFFSET))
+
+#define TZC_NSAID_DEFAULT		U(0)
+
+#define PLAT_ARM_TZC_NS_DEV_ACCESS	\
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_DEFAULT))
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/tc0/platform.mk b/plat/arm/board/tc0/platform.mk
index 903fabf..05d691e 100644
--- a/plat/arm/board/tc0/platform.mk
+++ b/plat/arm/board/tc0/platform.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2020, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -61,6 +61,8 @@
 				${TC0_BASE}/tc0_err.c		\
 				${TC0_BASE}/tc0_trusted_boot.c		\
 				lib/utils/mem_region.c			\
+				drivers/arm/tzc/tzc400.c		\
+				plat/arm/common/arm_tzc400.c		\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
 BL31_SOURCES		+=	${INTERCONNECT_SOURCES}	\
diff --git a/plat/arm/board/tc0/tc0_security.c b/plat/arm/board/tc0/tc0_security.c
index 6aa38c8..5f1cb11 100644
--- a/plat/arm/board/tc0/tc0_security.c
+++ b/plat/arm/board/tc0/tc0_security.c
@@ -1,12 +1,23 @@
 /*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <plat/arm/common/plat_arm.h>
 #include <platform_def.h>
 
+static const arm_tzc_regions_info_t tzc_regions[] = {
+	ARM_TZC_REGIONS_DEF,
+	{}
+};
+
 /* Initialize the secure environment */
 void plat_arm_security_setup(void)
 {
+	unsigned int i;
+
+	for (i = 0U; i < TZC400_COUNT; i++) {
+		arm_tzc400_setup(TZC400_BASE(i), tzc_regions);
+	}
 }
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 1832c65..74afc53 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -121,6 +121,12 @@
 ENABLE_PSCI_STAT		:=	1
 ENABLE_PMF			:=	1
 
+# Override the standard libc with optimised libc_asm
+OVERRIDE_LIBC			:=	1
+ifeq (${OVERRIDE_LIBC},1)
+    include lib/libc/libc_asm.mk
+endif
+
 # On ARM platforms, separate the code and read-only data sections to allow
 # mapping the former as executable and the latter as execute-never.
 SEPARATE_CODE_AND_RODATA	:=	1
diff --git a/plat/arm/css/sgi/include/sgi_base_platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h
index 14cdb7e..159084f 100644
--- a/plat/arm/css/sgi/include/sgi_base_platform_def.h
+++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -39,7 +39,7 @@
 #  define PLAT_SP_IMAGE_MAX_XLAT_TABLES	10
 # else
 #  define PLAT_ARM_MMAP_ENTRIES		(5 + ((CSS_SGI_CHIP_COUNT - 1) * 3))
-#  define MAX_XLAT_TABLES		(5 + ((CSS_SGI_CHIP_COUNT - 1) * 3))
+#  define MAX_XLAT_TABLES		(6 + ((CSS_SGI_CHIP_COUNT - 1) * 3))
 # endif
 #elif defined(IMAGE_BL32)
 # define PLAT_ARM_MMAP_ENTRIES		8
diff --git a/plat/arm/css/sgi/sgi_plat.c b/plat/arm/css/sgi/sgi_plat.c
index a2117f6..39eb89e 100644
--- a/plat/arm/css/sgi/sgi_plat.c
+++ b/plat/arm/css/sgi/sgi_plat.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -43,6 +43,9 @@
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
 	SGI_MAP_FLASH0_RO,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+	ARM_V2M_MAP_MEM_PROTECT,
+#endif
 	CSS_SGI_MAP_DEVICE,
 	SOC_CSS_MAP_DEVICE,
 	ARM_MAP_NS_DRAM1,
@@ -63,6 +66,9 @@
 	ARM_MAP_SHARED_RAM,
 	V2M_MAP_IOFPGA,
 	CSS_SGI_MAP_DEVICE,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+	ARM_V2M_MAP_MEM_PROTECT,
+#endif
 	SOC_CSS_MAP_DEVICE,
 #if SPM_MM
 	ARM_SPM_BUF_EL3_MMAP,