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/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.