Merge changes from topic "provencore-spd" into integration

* changes:
  feat(zynqmp): add support for ProvenCore
  feat(services): add a SPD for ProvenCore
  feat(gic): add APIs to raise NS and S-EL1 SGIs
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index 339ebbe..afe89b9 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -152,6 +152,11 @@
     to select the appropriate platform variant for the build. The range of
     valid values is platform specific.
 
+- ``CSS_SYSTEM_GRACEFUL_RESET``: Build option to enable graceful powerdown of
+   CPU core on reset. This build option can be used on CSS platforms that
+   require all the CPUs to execute the CPU specific power down sequence to
+   complete a warm reboot sequence in which only the CPUs are power cycled.
+
 --------------
 
 .. |FIP in a GPT image| image:: ../../resources/diagrams/FIP_in_a_GPT_image.png
diff --git a/drivers/arm/css/scp/css_pm_scmi.c b/drivers/arm/css/scp/css_pm_scmi.c
index 5de2604..9fe8b37 100644
--- a/drivers/arm/css/scp/css_pm_scmi.c
+++ b/drivers/arm/css/scp/css_pm_scmi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,7 @@
 #include <common/debug.h>
 #include <drivers/arm/css/css_scp.h>
 #include <drivers/arm/css/scmi.h>
+#include <lib/mmio.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/arm/css/common/css_pm.h>
 #include <plat/common/platform.h>
@@ -286,15 +287,42 @@
 	return HW_OFF;
 }
 
+/*
+ * Callback function to raise a SGI designated to trigger the CPU power down
+ * sequence on all the online secondary cores.
+ */
+static void css_raise_pwr_down_interrupt(u_register_t mpidr)
+{
+#if CSS_SYSTEM_GRACEFUL_RESET
+	plat_ic_raise_el3_sgi(CSS_CPU_PWR_DOWN_REQ_INTR, mpidr);
+#endif
+}
+
 void __dead2 css_scp_system_off(int state)
 {
 	int ret;
 
 	/*
+	 * Before issuing the system power down command, set the trusted mailbox
+	 * to 0. This will ensure that in the case of a warm/cold reset, the
+	 * primary CPU executes from the cold boot sequence.
+	 */
+	mmio_write_64(PLAT_ARM_TRUSTED_MAILBOX_BASE, 0U);
+
+	/*
+	 * Send powerdown request to online secondary core(s)
+	 */
+	ret = psci_stop_other_cores(0, css_raise_pwr_down_interrupt);
+	if (ret != PSCI_E_SUCCESS) {
+		ERROR("Failed to powerdown secondary core(s)\n");
+	}
+
+	/*
 	 * Disable GIC CPU interface to prevent pending interrupt from waking
 	 * up the AP from WFI.
 	 */
 	plat_arm_gic_cpuif_disable();
+	plat_arm_gic_redistif_off();
 
 	/*
 	 * Issue SCMI command. First issue a graceful
@@ -309,6 +337,9 @@
 			state, ret);
 		panic();
 	}
+
+	/* Powerdown of primary core */
+	psci_pwrdown_cpu(PLAT_MAX_PWR_LVL);
 	wfi();
 	ERROR("CSS set power state: operation not handled.\n");
 	panic();
diff --git a/drivers/arm/gic/v3/gic600_multichip.c b/drivers/arm/gic/v3/gic600_multichip.c
index 5f42ad9..e85dbc1 100644
--- a/drivers/arm/gic/v3/gic600_multichip.c
+++ b/drivers/arm/gic/v3/gic600_multichip.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2022, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -97,16 +98,28 @@
 		spi_id_max = GIC600_SPI_ID_MIN;
 	}
 
-	spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
-	spi_blocks    = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);
-
 	switch ((gicd_iidr_val & IIDR_MODEL_MASK)) {
 	case IIDR_MODEL_ARM_GIC_600:
+		spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
+		spi_blocks    = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);
+
 		chipr_n_val = GICD_CHIPR_VALUE_GIC_600(chip_addr,
 						       spi_block_min,
 						       spi_blocks);
 		break;
 	case IIDR_MODEL_ARM_GIC_700:
+		/* Calculate the SPI_ID_MIN value for ESPI */
+		if (spi_id_min >= GIC700_ESPI_ID_MIN) {
+			spi_block_min = ESPI_BLOCK_MIN_VALUE(spi_id_min);
+			spi_block_min += SPI_BLOCKS_VALUE(GIC700_SPI_ID_MIN,
+				GIC700_SPI_ID_MAX);
+		} else {
+			spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
+		}
+
+		/* Calculate the total number of blocks */
+		spi_blocks = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);
+
 		chipr_n_val = GICD_CHIPR_VALUE_GIC_700(chip_addr,
 						       spi_block_min,
 						       spi_blocks);
@@ -202,13 +215,104 @@
 }
 
 /*******************************************************************************
- * Intialize GIC-600 Multichip operation.
+ * Validates the GIC-700 Multichip data structure passed by the platform.
+ ******************************************************************************/
+static void gic700_multichip_validate_data(
+		struct gic600_multichip_data *multichip_data)
+{
+	unsigned int i, spi_id_min, spi_id_max, blocks_of_32;
+	unsigned int multichip_spi_blocks = 0U, multichip_espi_blocks = 0U;
+
+	assert(multichip_data != NULL);
+
+	if (multichip_data->chip_count > GIC600_MAX_MULTICHIP) {
+		ERROR("GIC-700 Multichip count (%u) should not exceed %u\n",
+				multichip_data->chip_count, GIC600_MAX_MULTICHIP);
+		panic();
+	}
+
+	for (i = 0U; i < multichip_data->chip_count; i++) {
+		spi_id_min = multichip_data->spi_ids[i][SPI_MIN_INDEX];
+		spi_id_max = multichip_data->spi_ids[i][SPI_MAX_INDEX];
+
+		if ((spi_id_min == 0U) || (spi_id_max == 0U)) {
+			continue;
+		}
+
+		/* MIN SPI ID check */
+		if ((spi_id_min < GIC700_SPI_ID_MIN) ||
+		    ((spi_id_min >= GIC700_SPI_ID_MAX) &&
+		     (spi_id_min < GIC700_ESPI_ID_MIN))) {
+			ERROR("Invalid MIN SPI ID {%u} passed for "
+					"Chip %u\n", spi_id_min, i);
+			panic();
+		}
+
+		if ((spi_id_min > spi_id_max) ||
+		    ((spi_id_max - spi_id_min + 1) % 32 != 0)) {
+			ERROR("Unaligned SPI IDs {%u, %u} passed for "
+					"Chip %u\n", spi_id_min,
+					spi_id_max, i);
+			panic();
+		}
+
+		/* ESPI IDs range check */
+		if ((spi_id_min >= GIC700_ESPI_ID_MIN) &&
+		    (spi_id_max > GIC700_ESPI_ID_MAX)) {
+			ERROR("Invalid ESPI IDs {%u, %u} passed for "
+					"Chip %u\n", spi_id_min,
+					spi_id_max, i);
+			panic();
+
+		}
+
+		/* SPI IDs range check */
+		if (((spi_id_min < GIC700_SPI_ID_MAX) &&
+		     (spi_id_max > GIC700_SPI_ID_MAX))) {
+			ERROR("Invalid SPI IDs {%u, %u} passed for "
+					"Chip %u\n", spi_id_min,
+					spi_id_max, i);
+			panic();
+		}
+
+		/* SPI IDs overlap check */
+		if (spi_id_max < GIC700_SPI_ID_MAX) {
+			blocks_of_32 = BLOCKS_OF_32(spi_id_min, spi_id_max);
+			if ((multichip_spi_blocks & blocks_of_32) != 0) {
+				ERROR("SPI IDs of Chip %u overlapping\n", i);
+				panic();
+			}
+			multichip_spi_blocks |= blocks_of_32;
+		}
+
+		/* ESPI IDs overlap check */
+		if (spi_id_max > GIC700_ESPI_ID_MIN) {
+			blocks_of_32 = BLOCKS_OF_32(spi_id_min - GIC700_ESPI_ID_MIN,
+					spi_id_max - GIC700_ESPI_ID_MIN);
+			if ((multichip_espi_blocks & blocks_of_32) != 0) {
+				ERROR("SPI IDs of Chip %u overlapping\n", i);
+				panic();
+			}
+			multichip_espi_blocks |= blocks_of_32;
+		}
+	}
+}
+
+/*******************************************************************************
+ * Intialize GIC-600 and GIC-700 Multichip operation.
  ******************************************************************************/
 void gic600_multichip_init(struct gic600_multichip_data *multichip_data)
 {
 	unsigned int i;
+	uint32_t gicd_iidr_val = gicd_read_iidr(multichip_data->rt_owner_base);
 
-	gic600_multichip_validate_data(multichip_data);
+	if ((gicd_iidr_val & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) {
+		gic600_multichip_validate_data(multichip_data);
+	}
+
+	if ((gicd_iidr_val & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700) {
+		gic700_multichip_validate_data(multichip_data);
+	}
 
 	/*
 	 * Ensure that G0/G1S/G1NS interrupts are disabled. This also ensures
diff --git a/drivers/arm/gic/v3/gic600_multichip_private.h b/drivers/arm/gic/v3/gic600_multichip_private.h
index 5d1ff6a..c7b15c1 100644
--- a/drivers/arm/gic/v3/gic600_multichip_private.h
+++ b/drivers/arm/gic/v3/gic600_multichip_private.h
@@ -41,6 +41,11 @@
 #define GIC600_SPI_ID_MIN		32
 #define GIC600_SPI_ID_MAX		960
 
+#define GIC700_SPI_ID_MIN		32
+#define GIC700_SPI_ID_MAX		991
+#define GIC700_ESPI_ID_MIN		4096
+#define GIC700_ESPI_ID_MAX		5119
+
 /* Number of retries for PUP update */
 #define GICD_PUP_UPDATE_RETRIES		10000
 
@@ -53,6 +58,9 @@
 #define SPI_BLOCKS_VALUE(spi_id_min, spi_id_max) \
 			(((spi_id_max) - (spi_id_min) + 1) / \
 			GIC600_SPI_ID_MIN)
+#define ESPI_BLOCK_MIN_VALUE(spi_id_min) \
+			(((spi_id_min) - GIC700_ESPI_ID_MIN + 1) / \
+			GIC700_SPI_ID_MIN)
 #define GICD_CHIPR_VALUE_GIC_700(chip_addr, spi_block_min, spi_blocks) \
 			(((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \
 			((spi_block_min) << GIC_700_SPI_BLOCK_MIN_SHIFT) | \
diff --git a/fdts/morello-fvp.dts b/fdts/morello-fvp.dts
index 55c87bf..dc3df41 100644
--- a/fdts/morello-fvp.dts
+++ b/fdts/morello-fvp.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,7 @@
 #include "morello.dtsi"
 
 / {
+	model = "Arm Morello Fixed Virtual Platform";
 
 	chosen {
 		stdout-path = "serial0:115200n8";
@@ -78,16 +79,12 @@
 
 	/* 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>;
@@ -143,8 +140,8 @@
 		scmi {
 			compatible = "arm,scmi";
 			mbox-names = "tx", "rx";
-			mboxes = <&mailbox 1 0 &mailbox 1 1>;
-			shmem = <&cpu_scp_hpri0 &cpu_scp_hpri1>;
+			mboxes = <&mailbox 1 0>, <&mailbox 1 1>;
+			shmem = <&cpu_scp_hpri0>, <&cpu_scp_hpri1>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 
diff --git a/fdts/morello-soc.dts b/fdts/morello-soc.dts
index 8464634..5f147b7 100644
--- a/fdts/morello-soc.dts
+++ b/fdts/morello-soc.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,9 +8,10 @@
 #include "morello.dtsi"
 
 / {
+	model = "Arm Morello System Development Platform";
 
 	chosen {
-		stdout-path = "soc_uart0:115200n8";
+		stdout-path = "serial0:115200n8";
 	};
 
 	reserved-memory {
@@ -59,16 +60,12 @@
 
 	/* 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 0x7F000000>;
 	};
 
 	memory@8080000000 {
-		#address-cells = <2>;
-		#size-cells = <2>;
 		device_type = "memory";
 		/* [0x8080000000-0x83f7ffffff] */
 		reg = <0x00000080 0x80000000 0x3 0x78000000>;
@@ -78,10 +75,10 @@
 		compatible = "arm,smmu-v3";
 		reg = <0 0x4f400000 0 0x40000>;
 		interrupts = <GIC_SPI 235 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 237 IRQ_TYPE_EDGE_RISING>,
 				<GIC_SPI 40 IRQ_TYPE_EDGE_RISING>,
-				<GIC_SPI 236 IRQ_TYPE_EDGE_RISING>,
-				<GIC_SPI 237 IRQ_TYPE_EDGE_RISING>;
-		interrupt-names = "eventq", "priq", "cmdq-sync", "gerror";
+				<GIC_SPI 236 IRQ_TYPE_EDGE_RISING>;
+		interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
 		msi-parent = <&its2 0>;
 		#iommu-cells = <1>;
 		dma-coherent;
@@ -114,10 +111,10 @@
 		compatible = "arm,smmu-v3";
 		reg = <0 0x4f000000 0 0x40000>;
 		interrupts = <GIC_SPI 228 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 230 IRQ_TYPE_EDGE_RISING>,
 				<GIC_SPI 41 IRQ_TYPE_EDGE_RISING>,
-				<GIC_SPI 229 IRQ_TYPE_EDGE_RISING>,
-				<GIC_SPI 230 IRQ_TYPE_EDGE_RISING>;
-		interrupt-names = "eventq", "priq", "cmdq-sync", "gerror";
+				<GIC_SPI 229 IRQ_TYPE_EDGE_RISING>;
+		interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
 		msi-parent = <&its1 0>;
 		#iommu-cells = <1>;
 		dma-coherent;
@@ -150,16 +147,16 @@
 		compatible = "arm,smmu-v3";
 		reg = <0 0x2ce00000 0 0x40000>;
 		interrupts = <GIC_SPI 76 IRQ_TYPE_EDGE_RISING>,
-				<GIC_SPI 78 IRQ_TYPE_EDGE_RISING>,
-				<GIC_SPI 80 IRQ_TYPE_EDGE_RISING>;
-		interrupt-names = "eventq", "cmdq-sync", "gerror";
+				<GIC_SPI 80 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 78 IRQ_TYPE_EDGE_RISING>;
+		interrupt-names = "eventq", "gerror", "cmdq-sync";
 		#iommu-cells = <1>;
 	};
 
 	dp0: display@2cc00000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
-		compatible = "arm,mali-d32";
+		compatible = "arm,mali-d32", "arm,mali-d71";
 		reg = <0 0x2cc00000 0 0x20000>;
 		interrupts = <0 69 4>;
 		interrupt-names = "DPU";
@@ -220,8 +217,8 @@
 		scmi {
 			compatible = "arm,scmi";
 			mbox-names = "tx", "rx";
-			mboxes = <&mailbox 1 0 &mailbox 1 1>;
-			shmem = <&cpu_scp_hpri0 &cpu_scp_hpri1>;
+			mboxes = <&mailbox 1 0>, <&mailbox 1 1>;
+			shmem = <&cpu_scp_hpri0>, <&cpu_scp_hpri1>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			scmi_dvfs: protocol@13 {
@@ -241,28 +238,28 @@
 	      <0x0 0x300c0000 0 0x80000>;	/* GICR */
 	interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
 
-	its1: its@30040000 {
+	its1: msi-controller@30040000 {
 		compatible = "arm,gic-v3-its";
 		msi-controller;
 		#msi-cells = <1>;
 		reg = <0x0 0x30040000 0x0 0x20000>;
 	};
 
-	its2: its@30060000 {
+	its2: msi-controller@30060000 {
 		compatible = "arm,gic-v3-its";
 		msi-controller;
 		#msi-cells = <1>;
 		reg = <0x0 0x30060000 0x0 0x20000>;
 	};
 
-	its_ccix: its@30080000 {
+	its_ccix: msi-controller@30080000 {
 		compatible = "arm,gic-v3-its";
 		msi-controller;
 		#msi-cells = <1>;
 		reg = <0x0 0x30080000 0x0 0x20000>;
 	};
 
-	its_pcie: its@300a0000 {
+	its_pcie: msi-controller@300a0000 {
 		compatible = "arm,gic-v3-its";
 		msi-controller;
 		#msi-cells = <1>;
diff --git a/fdts/morello.dtsi b/fdts/morello.dtsi
index f119820..20640c5 100644
--- a/fdts/morello.dtsi
+++ b/fdts/morello.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,7 +18,7 @@
 	};
 
 	gic: interrupt-controller@2c010000 {
-		compatible = "arm,gic-600", "arm,gic-v3";
+		compatible = "arm,gic-v3";
 		#address-cells = <2>;
 		#interrupt-cells = <3>;
 		#size-cells = <2>;
@@ -70,12 +70,12 @@
 		#size-cells = <1>;
 		ranges = <0 0x0 0x06000000 0x8000>;
 
-		cpu_scp_hpri0: scp-shmem@0 {
+		cpu_scp_hpri0: scp-sram@0 {
 			compatible = "arm,scmi-shmem";
 			reg = <0x0 0x80>;
 		};
 
-		cpu_scp_hpri1: scp-shmem@80 {
+		cpu_scp_hpri1: scp-sram@80 {
 			compatible = "arm,scmi-shmem";
 			reg = <0x80 0x80>;
 		};
@@ -95,7 +95,7 @@
 		clock-output-names = "uartclk";
 	};
 
-	soc_uart0: uart@2a400000 {
+	soc_uart0: serial@2a400000 {
 		compatible = "arm,pl011", "arm,primecell";
 		reg = <0x0 0x2a400000 0x0 0x1000>;
 		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index 1c71149..5bb22fd 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -315,7 +315,7 @@
 #define SGIR_IRM_SHIFT			40
 #define SGIR_IRM_MASK			ULL(0x1)
 #define SGIR_AFF3_SHIFT			48
-#define SGIR_AFF_MASK			ULL(0xf)
+#define SGIR_AFF_MASK			ULL(0xff)
 
 #define SGIR_IRM_TO_AFF			U(0)
 
diff --git a/include/lib/psci/psci_lib.h b/include/lib/psci/psci_lib.h
index 43e2f96..3edc50b 100644
--- a/include/lib/psci/psci_lib.h
+++ b/include/lib/psci/psci_lib.h
@@ -92,6 +92,7 @@
 int psci_stop_other_cores(unsigned int wait_ms,
 			  void (*stop_func)(u_register_t mpidr));
 bool psci_is_last_on_cpu_safe(void);
+void psci_pwrdown_cpu(unsigned int power_level);
 
 #endif /* __ASSEMBLER__ */
 
diff --git a/include/plat/arm/css/common/css_pm.h b/include/plat/arm/css/common/css_pm.h
index e5357f5..84e6b38 100644
--- a/include/plat/arm/css/common/css_pm.h
+++ b/include/plat/arm/css/common/css_pm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,6 +12,9 @@
 
 #include <lib/psci/psci.h>
 
+/* SGI used to trigger per-core power down request */
+#define CSS_CPU_PWR_DOWN_REQ_INTR	ARM_IRQ_SEC_SGI_7
+
 /* Macros to read the CSS power domain state */
 #define CSS_CORE_PWR_STATE(state)	(state)->pwr_domain_state[ARM_PWR_LVL0]
 #define CSS_CLUSTER_PWR_STATE(state)	(state)->pwr_domain_state[ARM_PWR_LVL1]
@@ -37,6 +40,9 @@
 void css_cpu_standby(plat_local_state_t cpu_state);
 void css_get_sys_suspend_power_state(psci_power_state_t *req_state);
 int css_node_hw_state(u_register_t mpidr, unsigned int power_level);
+void css_setup_cpu_pwr_down_intr(void);
+int css_reboot_interrupt_handler(uint32_t intr_raw, uint32_t flags,
+		void *handle, void *cookie);
 
 /*
  * This mapping array has to be exported by the platform. Each element at
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 68aacc1..4355b12 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -229,14 +230,11 @@
 			sctlr_el2);
 
 	/*
-	 * The GICv3 driver initializes the ICC_SRE_EL2 register during
-	 * platform setup. Use the same setting for the corresponding
-	 * context register to make sure the correct bits are set when
-	 * restoring NS context.
+	 * Program the ICC_SRE_EL2 to make sure the correct bits are set
+	 * when restoring NS context.
 	 */
-	u_register_t icc_sre_el2 = read_icc_sre_el2();
-	icc_sre_el2 |= (ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT);
-	icc_sre_el2 |= (ICC_SRE_EN_BIT | ICC_SRE_SRE_BIT);
+	u_register_t icc_sre_el2 = ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT |
+				   ICC_SRE_EN_BIT | ICC_SRE_SRE_BIT;
 	write_ctx_reg(get_el2_sysregs_ctx(ctx), CTX_ICC_SRE_EL2,
 			icc_sre_el2);
 #endif /* CTX_INCLUDE_EL2_REGS */
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index b60ddbb..efcfed8 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -954,7 +954,7 @@
  * Initiate power down sequence, by calling power down operations registered for
  * this CPU.
  ******************************************************************************/
-void psci_do_pwrdown_sequence(unsigned int power_level)
+void psci_pwrdown_cpu(unsigned int power_level)
 {
 #if HW_ASSISTED_COHERENCY
 	/*
diff --git a/lib/psci/psci_off.c b/lib/psci/psci_off.c
index 5447045..637adb9 100644
--- a/lib/psci/psci_off.c
+++ b/lib/psci/psci_off.c
@@ -109,7 +109,7 @@
 	/*
 	 * Arch. management. Initiate power down sequence.
 	 */
-	psci_do_pwrdown_sequence(psci_find_max_off_lvl(&state_info));
+	psci_pwrdown_cpu(psci_find_max_off_lvl(&state_info));
 
 #if ENABLE_RUNTIME_INSTRUMENTATION
 	PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h
index 61bd966..caade9c 100644
--- a/lib/psci/psci_private.h
+++ b/lib/psci/psci_private.h
@@ -296,7 +296,6 @@
 void psci_print_power_domain_map(void);
 unsigned int psci_is_last_on_cpu(void);
 int psci_spd_migrate_info(u_register_t *mpidr);
-void psci_do_pwrdown_sequence(unsigned int power_level);
 
 /*
  * CPU power down is directly called only when HW_ASSISTED_COHERENCY is
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index ffe3a91..f71994d 100644
--- a/lib/psci/psci_suspend.c
+++ b/lib/psci/psci_suspend.c
@@ -124,7 +124,7 @@
 	 * TODO : Introduce a mechanism to query the cache level to flush
 	 * and the cpu-ops power down to perform from the platform.
 	 */
-	psci_do_pwrdown_sequence(max_off_lvl);
+	psci_pwrdown_cpu(max_off_lvl);
 
 #if ENABLE_RUNTIME_INSTRUMENTATION
 	PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
diff --git a/plat/arm/board/rdn2/include/platform_def.h b/plat/arm/board/rdn2/include/platform_def.h
index 464a157..3474016 100644
--- a/plat/arm/board/rdn2/include/platform_def.h
+++ b/plat/arm/board/rdn2/include/platform_def.h
@@ -96,4 +96,8 @@
 #define PLAT_ARM_GICR_BASE		UL(0x301C0000)
 #endif
 
+/* Interrupt priority level for shutdown/reboot */
+#define PLAT_REBOOT_PRI		GIC_HIGHEST_SEC_PRIORITY
+#define PLAT_EHF_DESC		EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_REBOOT_PRI)
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk
index b882dc8..cfe4e28 100644
--- a/plat/arm/board/rdn2/platform.mk
+++ b/plat/arm/board/rdn2/platform.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -24,6 +24,9 @@
 GICV3_IMPL_GIC600_MULTICHIP	:=	1
 endif
 
+override CSS_SYSTEM_GRACEFUL_RESET	:= 1
+override EL3_EXCEPTION_HANDLING		:= 1
+
 include plat/arm/css/sgi/sgi-common.mk
 
 RDN2_BASE		=	plat/arm/board/rdn2
diff --git a/plat/arm/css/common/css_common.mk b/plat/arm/css/common/css_common.mk
index 2fbbe45..1e4851c 100644
--- a/plat/arm/css/common/css_common.mk
+++ b/plat/arm/css/common/css_common.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -35,6 +35,7 @@
 				drivers/arm/css/scmi/scmi_common.c		\
 				drivers/arm/css/scmi/scmi_pwr_dmn_proto.c	\
 				drivers/arm/css/scmi/scmi_sys_pwr_proto.c	\
+				drivers/delay_timer/delay_timer.c		\
 				drivers/arm/css/scp/css_pm_scmi.c
 endif
 
@@ -88,3 +89,9 @@
 $(eval $(call assert_boolean,CSS_NON_SECURE_UART))
 $(eval $(call add_define,CSS_NON_SECURE_UART))
 
+# Process CSS_SYSTEM_GRACEFUL_RESET flag
+# This build option can be used on CSS platforms that require all the CPUs
+# to execute the CPU specific power down sequence to complete a warm reboot
+# sequence in which only the CPUs are power cycled.
+CSS_SYSTEM_GRACEFUL_RESET	:= 0
+$(eval $(call add_define,CSS_SYSTEM_GRACEFUL_RESET))
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index 926b8ec..9b2639c 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,10 +9,14 @@
 #include <platform_def.h>
 
 #include <arch_helpers.h>
+#include <bl31/interrupt_mgmt.h>
 #include <common/debug.h>
 #include <drivers/arm/css/css_scp.h>
 #include <lib/cassert.h>
 #include <plat/arm/common/plat_arm.h>
+
+#include <plat/common/platform.h>
+
 #include <plat/arm/css/common/css_pm.h>
 
 /* Allow CSS platforms to override `plat_arm_psci_pm_ops` */
@@ -110,6 +114,9 @@
 
 	/* Enable the gic cpu interface */
 	plat_arm_gic_cpuif_enable();
+
+	/* Setup the CPU power down request interrupt for secondary core(s) */
+	css_setup_cpu_pwr_down_intr();
 }
 
 /*******************************************************************************
@@ -331,6 +338,52 @@
 	return arm_validate_power_state(power_state, output_state);
 }
 
+/*
+ * Setup the SGI interrupt that will be used trigger the execution of power
+ * down sequence for all the secondary cores. This interrupt is setup to be
+ * handled in EL3 context at a priority defined by the platform.
+ */
+void css_setup_cpu_pwr_down_intr(void)
+{
+#if CSS_SYSTEM_GRACEFUL_RESET
+	plat_ic_set_interrupt_type(CSS_CPU_PWR_DOWN_REQ_INTR, INTR_TYPE_EL3);
+	plat_ic_set_interrupt_priority(CSS_CPU_PWR_DOWN_REQ_INTR,
+			PLAT_REBOOT_PRI);
+	plat_ic_enable_interrupt(CSS_CPU_PWR_DOWN_REQ_INTR);
+#endif
+}
+
+/*
+ * For a graceful shutdown/reboot, each CPU in the system should do their power
+ * down sequence. On a PSCI shutdown/reboot request, only one CPU gets an
+ * opportunity to do the powerdown sequence. To achieve graceful reset, of all
+ * cores in the system, the CPU gets the opportunity raise warm reboot SGI to
+ * rest of the CPUs which are online. Add handler for the reboot SGI where the
+ * rest of the CPU execute the powerdown sequence.
+ */
+int css_reboot_interrupt_handler(uint32_t intr_raw, uint32_t flags,
+		void *handle, void *cookie)
+{
+	assert(intr_raw == CSS_CPU_PWR_DOWN_REQ_INTR);
+
+	/* Deactivate warm reboot SGI */
+	plat_ic_end_of_interrupt(CSS_CPU_PWR_DOWN_REQ_INTR);
+
+	/*
+	 * Disable GIC CPU interface to prevent pending interrupt from waking
+	 * up the AP from WFI.
+	 */
+	plat_arm_gic_cpuif_disable();
+	plat_arm_gic_redistif_off();
+
+	psci_pwrdown_cpu(PLAT_MAX_PWR_LVL);
+
+	dmbsy();
+
+	wfi();
+	return 0;
+}
+
 /*******************************************************************************
  * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
  * platform will take care of registering the handlers with PSCI.
diff --git a/plat/arm/css/common/sp_min/css_sp_min.mk b/plat/arm/css/common/sp_min/css_sp_min.mk
index 6523a16..ae489fd 100644
--- a/plat/arm/css/common/sp_min/css_sp_min.mk
+++ b/plat/arm/css/common/sp_min/css_sp_min.mk
@@ -15,6 +15,7 @@
 else
 BL32_SOURCES		+=	drivers/arm/css/mhu/css_mhu_doorbell.c		\
 				drivers/arm/css/scp/css_pm_scmi.c		\
+				drivers/delay_timer/delay_timer.c		\
 				drivers/arm/css/scmi/scmi_common.c		\
 				drivers/arm/css/scmi/scmi_pwr_dmn_proto.c	\
 				drivers/arm/css/scmi/scmi_sys_pwr_proto.c
diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c
index 99f2f20..7ef7e6f 100644
--- a/plat/arm/css/sgi/sgi_bl31_setup.c
+++ b/plat/arm/css/sgi/sgi_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,8 +13,11 @@
 #include <drivers/arm/css/css_mhu_doorbell.h>
 #include <drivers/arm/css/scmi.h>
 #include <plat/arm/common/plat_arm.h>
+
 #include <plat/common/platform.h>
 
+#include <plat/arm/css/common/css_pm.h>
+
 #include <sgi_ras.h>
 #include <sgi_variant.h>
 
@@ -105,6 +108,15 @@
 #if RAS_EXTENSION
 	sgi_ras_intr_handler_setup();
 #endif
+
+	/* Configure the warm reboot SGI for primary core */
+	css_setup_cpu_pwr_down_intr();
+
+#if CSS_SYSTEM_GRACEFUL_RESET
+	/* Register priority level handlers for reboot */
+	ehf_register_priority_handler(PLAT_REBOOT_PRI,
+			css_reboot_interrupt_handler);
+#endif
 }
 
 const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
diff --git a/plat/xilinx/common/include/pm_client.h b/plat/xilinx/common/include/pm_client.h
index dc012b7..eae1d98 100644
--- a/plat/xilinx/common/include/pm_client.h
+++ b/plat/xilinx/common/include/pm_client.h
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -23,9 +25,9 @@
 /* Global variables to be set in pm_client.c */
 extern const struct pm_proc *primary_proc;
 
-#ifndef VERSAL_PLATFORM
+#if defined(PLAT_zynqmp)
 enum pm_ret_status pm_set_suspend_mode(uint32_t mode);
 const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid);
-#endif
+#endif /* PLAT_zynqmp */
 
 #endif /* PM_CLIENT_H */
diff --git a/plat/xilinx/common/include/pm_ipi.h b/plat/xilinx/common/include/pm_ipi.h
index 2d20b9f..8a15668 100644
--- a/plat/xilinx/common/include/pm_ipi.h
+++ b/plat/xilinx/common/include/pm_ipi.h
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +10,7 @@
 #define PM_IPI_H
 
 #include <plat_ipi.h>
+#include <stddef.h>
 #include "pm_common.h"
 
 #define IPI_BLOCKING		1
diff --git a/plat/xilinx/common/ipi.c b/plat/xilinx/common/ipi.c
index 2f52f38..318079b 100644
--- a/plat/xilinx/common/ipi.c
+++ b/plat/xilinx/common/ipi.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,7 +18,6 @@
 #include <lib/mmio.h>
 
 #include <ipi.h>
-#include <plat_ipi.h>
 #include <plat_private.h>
 
 /*********************************************************************
diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c
index 12313f2..9c9fd62 100644
--- a/plat/xilinx/common/pm_service/pm_ipi.c
+++ b/plat/xilinx/common/pm_service/pm_ipi.c
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +15,7 @@
 #include <plat_private.h>
 #include <plat/common/platform.h>
 
+#include "pm_defs.h"
 #include "pm_ipi.h"
 
 #define ERROR_CODE_MASK		0xFFFFU
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
index 349b856..9b36208 100644
--- a/plat/xilinx/versal/bl31_versal_setup.c
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -184,8 +184,9 @@
 		}
 	}
 
-	if (handler != NULL)
-		handler(intr_id, flags, handle, cookie);
+	if (handler != NULL) {
+		return handler(intr_id, flags, handle, cookie);
+	}
 
 	return 0;
 }
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c
index ecd8d08..db9fae4 100644
--- a/plat/xilinx/versal/pm_service/pm_api_sys.c
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.c
@@ -17,7 +17,6 @@
 #include "pm_client.h"
 #include "pm_defs.h"
 #include "pm_svc_main.h"
-#include "../drivers/arm/gic/v3/gicv3_private.h"
 
 /* default shutdown/reboot scope is system(2) */
 static uint32_t pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM;
@@ -466,8 +465,6 @@
 		if (ret != 0) {
 			return PM_RET_ERROR_ARGS;
 		}
-		gicd_write_irouter(gicv3_driver_data->gicd_base,
-				  (uint32_t)PLAT_VERSAL_IPI_IRQ, MODE);
 		ret = PM_RET_SUCCESS;
 		break;
 	default:
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h
index e2a3cf8..c539aa7 100644
--- a/plat/xilinx/versal/pm_service/pm_api_sys.h
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.h
@@ -17,7 +17,6 @@
 #define LIBPM_MODULE_ID		0x2U
 #define LOADER_MODULE_ID	0x7U
 
-#define MODE			0x80000000U
 #define MODULE_ID_MASK		0x0000ff00U
 /**********************************************************
  * PM API function declarations
diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c
index 4e26d87..929008a 100644
--- a/plat/xilinx/versal/pm_service/pm_svc_main.c
+++ b/plat/xilinx/versal/pm_service/pm_svc_main.c
@@ -19,6 +19,9 @@
 #include "pm_client.h"
 #include "pm_ipi.h"
 #include <drivers/arm/gicv3.h>
+#include "../drivers/arm/gic/v3/gicv3_private.h"
+
+#define MODE				0x80000000U
 
 #define XSCUGIC_SGIR_EL1_INITID_SHIFT    24U
 #define INVALID_SGI    0xFFU
@@ -139,6 +142,8 @@
 	if (ret != 0) {
 		WARN("BL31: registering IPI interrupt failed\n");
 	}
+
+	gicd_write_irouter(gicv3_driver_data->gicd_base, PLAT_VERSAL_IPI_IRQ, MODE);
 	return ret;
 }
 
@@ -253,7 +258,7 @@
  *
  * These EEMI calls performs functionality that does not require
  * IPI transaction. The handler ends in TF-A and returns requested data to
- * kernel from TF-A
+ * kernel from TF-A.
  */
 static uintptr_t TF_A_specific_handler(uint32_t api_id, uint32_t *pm_arg,
 				       void *handle, uint32_t security_flag)
@@ -355,7 +360,7 @@
 	uint32_t api_id;
 
 	/* Handle case where PM wasn't initialized properly */
-	if (!pm_up) {
+	if (pm_up == false) {
 		SMC_RET1(handle, SMC_UNK);
 	}
 
@@ -363,7 +368,7 @@
 	 * Mark BIT24 payload (i.e 1st bit of pm_arg[3] ) as non-secure (1)
 	 * if smc called is non secure
 	 */
-	if (is_caller_non_secure(flags)) {
+	if (is_caller_non_secure(flags) != 0) {
 		security_flag = NON_SECURE_FLAG;
 	}
 
diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
index 38ad32b..1d59537 100644
--- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
+++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
@@ -176,7 +176,7 @@
 
 	/* Return if no device tree is detected */
 	if (fdt_check_header(dtb) != 0) {
-		NOTICE("Can't read DT at 0x%p\n", dtb);
+		NOTICE("Can't read DT at %p\n", dtb);
 		return;
 	}
 
diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h
index 66bbf30..c2d22c2 100644
--- a/plat/xilinx/zynqmp/include/platform_def.h
+++ b/plat/xilinx/zynqmp/include/platform_def.h
@@ -40,7 +40,7 @@
 # define BL31_BASE			U(0xfffea000)
 # define BL31_LIMIT			U(0x100000000)
 #else
-# define BL31_BASE			U(0xfff5a000)
+# define BL31_BASE			U(0xfffe5000)
 # define BL31_LIMIT			U(0x100000000)
 #endif
 #else
diff --git a/plat/xilinx/zynqmp/include/zynqmp_def.h b/plat/xilinx/zynqmp/include/zynqmp_def.h
index 877127b..428bed5 100644
--- a/plat/xilinx/zynqmp/include/zynqmp_def.h
+++ b/plat/xilinx/zynqmp/include/zynqmp_def.h
@@ -352,7 +352,7 @@
 #define RESTART_SCOPE_SHIFT			(3)
 #define RESTART_SCOPE_MASK			(0x3U << RESTART_SCOPE_SHIFT)
 
-/*AFI registers */
+/* AFI registers */
 #define  AFIFM6_WRCTRL		U(13)
 #define  FABRIC_WIDTH		U(3)
 
diff --git a/tools/sptool/sp_mk_generator.py b/tools/sptool/sp_mk_generator.py
index 814d051..c0beb65 100644
--- a/tools/sptool/sp_mk_generator.py
+++ b/tools/sptool/sp_mk_generator.py
@@ -196,7 +196,7 @@
     ''' Generate arguments for the FIP Tool. '''
     if "uuid" in sp_layout[sp]:
         # Extract the UUID from the JSON file if the SP entry has a 'uuid' field
-        uuid_std = uuid.UUID(data[key]['uuid'])
+        uuid_std = uuid.UUID(sp_layout[sp]['uuid'])
     else:
         with open(get_sp_manifest_full_path(sp_layout[sp], args), "r") as pm_f:
             uuid_lines = [l for l in pm_f if 'uuid' in l]