feat(xilinx): add handler for power down req sgi irq

On receiving CPU power down callback, TF-A raises SGI interrupt to all active
cores to power down each active cores. Add handler for this SGI IRQ.

By default TF-A uses SGI 6 for CPU power down request. This can be
configurable through CPU_PWRDWN_SGI build flag.

e.g., If user wants to use SGI 7 instead of SGI 6 then provide build
flag CPU_PWRDWN_SGI=7

Signed-off-by: Jay Buddhabhatti <jay.buddhabhatti@amd.com>
Change-Id: Id0df32187d1de3f0af4486eb4d4930cb3ab01dbd
diff --git a/docs/plat/xilinx-versal-net.rst b/docs/plat/xilinx-versal-net.rst
index 1db7695..3f31d40 100644
--- a/docs/plat/xilinx-versal-net.rst
+++ b/docs/plat/xilinx-versal-net.rst
@@ -40,3 +40,16 @@
 *   `TFA_NO_PM` : Platform Management support.
     -    0 : Enable Platform Management (Default)
     -    1 : Disable Platform Management
+
+*   `CPU_PWRDWN_SGI`: Select the SGI for triggering CPU power down request to
+                      secondary cores on receiving power down callback from
+                      firmware. Options:
+
+    -   `0`   : SGI 0
+    -   `1`   : SGI 1
+    -   `2`   : SGI 2
+    -   `3`   : SGI 3
+    -   `4`   : SGI 4
+    -   `5`   : SGI 5
+    -   `6`   : SGI 6 (Default)
+    -   `7`   : SGI 7
diff --git a/docs/plat/xilinx-versal.rst b/docs/plat/xilinx-versal.rst
index e76b955..aa094f7 100644
--- a/docs/plat/xilinx-versal.rst
+++ b/docs/plat/xilinx-versal.rst
@@ -56,6 +56,19 @@
     -   `spp_itr6`	: SPP ITR6
     -   `emu_itr6`	: EMU ITR6
 
+*   `CPU_PWRDWN_SGI`: Select the SGI for triggering CPU power down request to
+                      secondary cores on receiving power down callback from
+                      firmware. Options:
+
+    -   `0`   : SGI 0
+    -   `1`   : SGI 1
+    -   `2`   : SGI 2
+    -   `3`   : SGI 3
+    -   `4`   : SGI 4
+    -   `5`   : SGI 5
+    -   `6`   : SGI 6 (Default)
+    -   `7`   : SGI 7
+
 # PLM->TF-A Parameter Passing
 ------------------------------
 The PLM populates a data structure with image information for the TF-A. The TF-A
diff --git a/plat/xilinx/common/include/plat_common.h b/plat/xilinx/common/include/plat_common.h
index 676baa2..2958868 100644
--- a/plat/xilinx/common/include/plat_common.h
+++ b/plat/xilinx/common/include/plat_common.h
@@ -14,4 +14,16 @@
 		(typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask));	\
 	})
 
+/*******************************************************************************
+ * interrupt handling related constants
+ ******************************************************************************/
+#define ARM_IRQ_SEC_SGI_0	8U
+#define ARM_IRQ_SEC_SGI_1	9U
+#define ARM_IRQ_SEC_SGI_2	10U
+#define ARM_IRQ_SEC_SGI_3	11U
+#define ARM_IRQ_SEC_SGI_4	12U
+#define ARM_IRQ_SEC_SGI_5	13U
+#define ARM_IRQ_SEC_SGI_6	14U
+#define ARM_IRQ_SEC_SGI_7	15U
+
 #endif /* PLAT_COMMON_H */
diff --git a/plat/xilinx/common/pm_service/pm_svc_main.c b/plat/xilinx/common/pm_service/pm_svc_main.c
index 622dc24..8ff4949 100644
--- a/plat/xilinx/common/pm_service/pm_svc_main.c
+++ b/plat/xilinx/common/pm_service/pm_svc_main.c
@@ -50,6 +50,19 @@
 	write_icc_asgi1r_el1(reg);
 }
 
+static uint64_t cpu_pwrdwn_req_handler(uint32_t id, uint32_t flags,
+				       void *handle, void *cookie)
+{
+	uint32_t cpu_id = plat_my_core_pos();
+
+	VERBOSE("Powering down CPU %d\n", cpu_id);
+
+	/* Deactivate CPU power down SGI */
+	plat_ic_end_of_interrupt(CPU_PWR_DOWN_REQ_INTR);
+
+	return psci_cpu_off();
+}
+
 static void request_cpu_pwrdwn(void)
 {
 	VERBOSE("CPU power down request received\n");
@@ -160,6 +173,12 @@
 	pm_ipi_init(primary_proc);
 	pm_up = true;
 
+	/* register SGI handler for CPU power down request */
+	ret = request_intr_type_el3(CPU_PWR_DOWN_REQ_INTR, cpu_pwrdwn_req_handler);
+	if (ret != 0) {
+		WARN("BL31: registering SGI interrupt failed\n");
+	}
+
 	/*
 	 * Enable IPI IRQ
 	 * assume the rich OS is OK to handle callback IRQs now.
diff --git a/plat/xilinx/versal/include/platform_def.h b/plat/xilinx/versal/include/platform_def.h
index 0ea21b2..d3a734b 100644
--- a/plat/xilinx/versal/include/platform_def.h
+++ b/plat/xilinx/versal/include/platform_def.h
@@ -9,6 +9,7 @@
 #define PLATFORM_DEF_H
 
 #include <arch.h>
+#include <plat_common.h>
 #include "versal_def.h"
 
 /*******************************************************************************
@@ -122,6 +123,8 @@
 #define PLAT_VERSAL_G0_IRQ_PROPS(grp) \
 	INTR_PROP_DESC(PLAT_VERSAL_IPI_IRQ, GIC_HIGHEST_SEC_PRIORITY, grp, \
 			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(CPU_PWR_DOWN_REQ_INTR, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE)
 
 #define IRQ_MAX		142U
 
diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk
index 35d6bc7..2f07996 100644
--- a/plat/xilinx/versal/platform.mk
+++ b/plat/xilinx/versal/platform.mk
@@ -11,6 +11,8 @@
 PL011_GENERIC_UART := 1
 IPI_CRC_CHECK := 0
 HARDEN_SLS_ALL := 0
+CPU_PWRDWN_SGI ?= 6
+$(eval $(call add_define_val,CPU_PWR_DOWN_REQ_INTR,ARM_IRQ_SEC_SGI_${CPU_PWRDWN_SGI}))
 
 # A72 Erratum for SoC
 ERRATA_A72_859971 := 1
diff --git a/plat/xilinx/versal_net/include/platform_def.h b/plat/xilinx/versal_net/include/platform_def.h
index 334714b..8cb7deb 100644
--- a/plat/xilinx/versal_net/include/platform_def.h
+++ b/plat/xilinx/versal_net/include/platform_def.h
@@ -10,6 +10,7 @@
 #define PLATFORM_DEF_H
 
 #include <arch.h>
+#include <plat_common.h>
 #include "versal_net_def.h"
 
 /*******************************************************************************
@@ -124,6 +125,8 @@
 
 #define PLAT_ARM_G0_IRQ_PROPS(grp) \
 	INTR_PROP_DESC(PLAT_VERSAL_IPI_IRQ, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(CPU_PWR_DOWN_REQ_INTR, GIC_HIGHEST_SEC_PRIORITY, grp, \
 			GIC_INTR_CFG_EDGE)
 
 #define IRQ_MAX		200U
diff --git a/plat/xilinx/versal_net/platform.mk b/plat/xilinx/versal_net/platform.mk
index b2aceca..da91abc 100644
--- a/plat/xilinx/versal_net/platform.mk
+++ b/plat/xilinx/versal_net/platform.mk
@@ -21,6 +21,8 @@
 GIC_ENABLE_V4_EXTN :=  0
 GICV3_SUPPORT_GIC600 := 1
 TFA_NO_PM := 0
+CPU_PWRDWN_SGI ?= 6
+$(eval $(call add_define_val,CPU_PWR_DOWN_REQ_INTR,ARM_IRQ_SEC_SGI_${CPU_PWRDWN_SGI}))
 
 override CTX_INCLUDE_AARCH32_REGS    := 0