feat(versal): add infrastructure to handle multiple interrupts

Only one hardcode interrupt handler is supported as of now.
This is IPI interrupt between APU and PMC processor.
This patch adds infrastructure to register multiple interrupt
handlers. This infrastructure was used and tested for two
interrupts and so, interrupt id and handler container size is
2 which is defined by MAX_INTR_EL3. Interrupt id is not used
as container index due to size constraints. User is expected to
adjust MAX_INTR_EL3 based on how many interrupts are handled in
TF-A

Signed-off-by: Tanmay Shah <tanmay.shah@amd.com>
Change-Id: Id49d94f6773fbb6874ccf89c0d12572efc7e678e
diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c
index fef21f7..4e26d87 100644
--- a/plat/xilinx/versal/pm_service/pm_svc_main.c
+++ b/plat/xilinx/versal/pm_service/pm_svc_main.c
@@ -1,5 +1,6 @@
 /*
  * 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
  */
@@ -21,24 +22,46 @@
 
 #define XSCUGIC_SGIR_EL1_INITID_SHIFT    24U
 #define INVALID_SGI    0xFFU
+#define PM_INIT_SUSPEND_CB	(30U)
+#define PM_NOTIFY_CB		(32U)
 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r_el1, S3_0_C12_C11_6)
 
 /* pm_up = true - UP, pm_up = false - DOWN */
 static bool pm_up;
 static uint32_t sgi = (uint32_t)INVALID_SGI;
 
+static void notify_os(void)
+{
+	int32_t cpu;
+	uint32_t reg;
+
+	cpu = plat_my_core_pos() + 1U;
+
+	reg = (cpu | (sgi << XSCUGIC_SGIR_EL1_INITID_SHIFT));
+	write_icc_asgi1r_el1(reg);
+}
+
 static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle,
 				void *cookie)
 {
-	uint32_t cpu;
-	uint32_t reg;
+	uint32_t payload[4] = {0};
+
+	VERBOSE("Received IPI FIQ from firmware\n");
 
 	(void)plat_ic_acknowledge_interrupt();
-	cpu = plat_my_core_pos() + 1U;
 
-	if ((uint32_t)sgi != (uint32_t)INVALID_SGI) {
-		reg = (cpu | ((uint32_t)sgi << (uint32_t)XSCUGIC_SGIR_EL1_INITID_SHIFT));
-		write_icc_asgi1r_el1(reg);
+	pm_get_callbackdata(payload, ARRAY_SIZE(payload), 0, 0);
+	switch (payload[0]) {
+	case PM_INIT_SUSPEND_CB:
+	case PM_NOTIFY_CB:
+		if (sgi != INVALID_SGI) {
+			notify_os();
+		}
+		break;
+	default:
+		pm_ipi_irq_clear(primary_proc);
+		WARN("Invalid IPI payload\n");
+		break;
 	}
 
 	/* Clear FIQ */
@@ -253,7 +276,7 @@
 	{
 		uint32_t result[4] = {0};
 
-		pm_get_callbackdata(result, ARRAY_SIZE(result), security_flag);
+		pm_get_callbackdata(result, ARRAY_SIZE(result), security_flag, 1U);
 		SMC_RET2(handle,
 			(uint64_t)result[0] | ((uint64_t)result[1] << 32U),
 			(uint64_t)result[2] | ((uint64_t)result[3] << 32U));