Merge changes Id49d94f6,I35316310 into integration

* changes:
  feat(versal): add infrastructure to handle multiple interrupts
  fix(versal): add SGI register call version check
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
index b8db4a6..349b856 100644
--- a/plat/xilinx/versal/bl31_versal_setup.c
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -140,16 +142,29 @@
 	NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc);
 }
 
-static interrupt_type_handler_t type_el3_interrupt_handler;
+static versal_intr_info_type_el3_t type_el3_interrupt_table[MAX_INTR_EL3];
 
-int32_t request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler)
+int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler)
 {
-	/* Validate 'handler'*/
-	if (handler == NULL) {
+	static uint32_t index;
+	uint32_t i;
+
+	/* Validate 'handler' and 'id' parameters */
+	if (handler == NULL || index >= MAX_INTR_EL3) {
 		return -EINVAL;
 	}
 
-	type_el3_interrupt_handler = handler;
+	/* Check if a handler has already been registered */
+	for (i = 0; i < index; i++) {
+		if (id == type_el3_interrupt_table[i].id) {
+			return -EALREADY;
+		}
+	}
+
+	type_el3_interrupt_table[index].id = id;
+	type_el3_interrupt_table[index].handler = handler;
+
+	index++;
 
 	return 0;
 }
@@ -158,19 +173,19 @@
 					  void *handle, void *cookie)
 {
 	uint32_t intr_id;
-	interrupt_type_handler_t handler;
+	uint32_t i;
+	interrupt_type_handler_t handler = NULL;
 
 	intr_id = plat_ic_get_pending_interrupt_id();
-	/* Currently we support one interrupt */
-	if (intr_id != PLAT_VERSAL_IPI_IRQ) {
-		WARN("Unexpected interrupt call: 0x%x\n", intr_id);
-		return 0;
+
+	for (i = 0; i < MAX_INTR_EL3; i++) {
+		if (intr_id == type_el3_interrupt_table[i].id) {
+			handler = type_el3_interrupt_table[i].handler;
+		}
 	}
 
-	handler = type_el3_interrupt_handler;
-	if (handler != NULL) {
-		return handler(intr_id, flags, handle, cookie);
-	}
+	if (handler != NULL)
+		handler(intr_id, flags, handle, cookie);
 
 	return 0;
 }
diff --git a/plat/xilinx/versal/include/plat_private.h b/plat/xilinx/versal/include/plat_private.h
index 109c95e..818797d 100644
--- a/plat/xilinx/versal/include/plat_private.h
+++ b/plat/xilinx/versal/include/plat_private.h
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +12,11 @@
 #include <lib/xlat_tables/xlat_tables.h>
 #include <bl31/interrupt_mgmt.h>
 
+typedef struct versal_intr_info_type_el3 {
+	uint32_t id;
+	interrupt_type_handler_t handler;
+} versal_intr_info_type_el3_t;
+
 void versal_config_setup(void);
 
 const mmap_region_t *plat_versal_get_mmap(void);
diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h
index 4b0b311..60431a5 100644
--- a/plat/xilinx/versal/include/versal_def.h
+++ b/plat/xilinx/versal/include/versal_def.h
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2018-2022, 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
  */
@@ -10,6 +12,8 @@
 #include <plat/arm/common/smccc_def.h>
 #include <plat/common/common_def.h>
 
+/* number of interrupt handlers. increase as required */
+#define MAX_INTR_EL3			2
 /* List all consoles */
 #define VERSAL_CONSOLE_ID_pl011	1
 #define VERSAL_CONSOLE_ID_pl011_0	1
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c
index 8fa8a44..ecd8d08 100644
--- a/plat/xilinx/versal/pm_service/pm_api_sys.c
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.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
  */
@@ -192,10 +193,12 @@
  * @data - array of PAYLOAD_ARG_CNT elements
  * @flag - 0 - Call from secure source
  *	   1 - Call from non-secure source
+ * @ack - 0 - Do not ack IPI after reading payload
+ *        1 - Ack IPI after reading payload
  *
  * Read value from ipi buffer response buffer.
  */
-void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag)
+void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag, uint32_t ack)
 {
 	/* Return if interrupt is not from PMU */
 	if (pm_ipi_irq_status(primary_proc) == 0) {
@@ -203,7 +206,10 @@
 	}
 
 	pm_ipi_buff_read_callb(data, count);
-	pm_ipi_irq_clear(primary_proc);
+
+	if (ack != 0U) {
+		pm_ipi_irq_clear(primary_proc);
+	}
 }
 
 /**
@@ -514,7 +520,7 @@
 	case PM_GET_TRUSTZONE_VERSION:
 		ret_payload[0] = PM_API_VERSION_2;
 		return PM_RET_SUCCESS;
-	case PM_LOAD_PDI:
+	case TF_A_PM_REGISTER_SGI:
 		ret_payload[0] = PM_API_BASE_VERSION;
 		return PM_RET_SUCCESS;
 	default:
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h
index 121ec1a..e2a3cf8 100644
--- a/plat/xilinx/versal/pm_service/pm_api_sys.h
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.h
@@ -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
  */
@@ -38,7 +39,8 @@
 				 uintptr_t address, uint8_t ack, uint32_t flag);
 enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t device_id,
 					uint8_t enable, uint32_t flag);
-void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag);
+void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag,
+			 uint32_t ack);
 enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param,
 				    uint32_t value, uint32_t flag);
 enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param,
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));