Merge changes from topic "fpga_generic" into integration

* changes:
  arm_fpga: Add platform documentation
  arm_fpga: Add post-build linker script
  arm_fpga: Add ROM trampoline
  arm_fpga: Add devicetree file
  arm_fpga: Remove SPE PMU DT node if SPE is not available
  arm_fpga: Adjust GICR size in DT to match number of cores
  fdt: Add function to adjust GICv3 redistributor size
  drivers: arm: gicv3: Allow detecting number of cores
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/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/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/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/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/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/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index ad9001b..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
 
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