plat: xilinx: Error management support

Add support for the trapping the IPI in TF-A.
Register handler for the irq no 62 which is the IPI interrupt.

Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
Change-Id: I9c04fdae7be3dda6a34a9b196274c0b5fdf39223
Signed-off-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@xilinx.com>
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
index de36efc..8b8714c 100644
--- a/plat/xilinx/versal/bl31_versal_setup.c
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -117,6 +117,40 @@
 	NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc);
 }
 
+static interrupt_type_handler_t type_el3_interrupt_handler;
+
+int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler)
+{
+	/* Validate 'handler'*/
+	if (!handler) {
+		return -EINVAL;
+	}
+
+	type_el3_interrupt_handler = handler;
+
+	return 0;
+}
+
+static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags,
+					  void *handle, void *cookie)
+{
+	uint32_t intr_id;
+	interrupt_type_handler_t handler;
+
+	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;
+	}
+
+	handler = type_el3_interrupt_handler;
+	if (handler) {
+		return handler(intr_id, flags, handle, cookie);
+	}
+
+	return 0;
+}
 void bl31_platform_setup(void)
 {
 	/* Initialize the gic cpu and distributor interfaces */
@@ -126,6 +160,15 @@
 
 void bl31_plat_runtime_setup(void)
 {
+	uint64_t flags = 0;
+	uint64_t rc;
+
+	set_interrupt_rm_flag(flags, NON_SECURE);
+	rc = register_interrupt_type_handler(INTR_TYPE_EL3,
+					     rdo_el3_interrupt_handler, flags);
+	if (rc) {
+		panic();
+	}
 }
 
 /*
diff --git a/plat/xilinx/versal/include/plat_private.h b/plat/xilinx/versal/include/plat_private.h
index e302096..d12d13a 100644
--- a/plat/xilinx/versal/include/plat_private.h
+++ b/plat/xilinx/versal/include/plat_private.h
@@ -8,6 +8,7 @@
 #define PLAT_PRIVATE_H
 
 #include <lib/xlat_tables/xlat_tables.h>
+#include <bl31/interrupt_mgmt.h>
 
 void versal_config_setup(void);
 
@@ -22,5 +23,10 @@
 void plat_versal_gic_resume(void);
 
 unsigned int versal_calc_core_pos(u_register_t mpidr);
+/*
+ * Register handler to specific GIC entrance
+ * for INTR_TYPE_EL3 type of interrupt
+ */
+int request_intr_type_el3(uint32_t irq, interrupt_type_handler_t fiq_handler);
 
 #endif /* PLAT_PRIVATE_H */
diff --git a/plat/xilinx/versal/include/platform_def.h b/plat/xilinx/versal/include/platform_def.h
index 4cdaea2..8b513ef 100644
--- a/plat/xilinx/versal/include/platform_def.h
+++ b/plat/xilinx/versal/include/platform_def.h
@@ -91,11 +91,14 @@
  */
 #define PLAT_VERSAL_G1S_IRQS	VERSAL_IRQ_SEC_PHY_TIMER
 #define PLAT_VERSAL_G0_IRQS	VERSAL_IRQ_SEC_PHY_TIMER
+#define PLAT_VERSAL_IPI_IRQ	62
 
 #define PLAT_VERSAL_G1S_IRQ_PROPS(grp) \
 	INTR_PROP_DESC(VERSAL_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
 			GIC_INTR_CFG_LEVEL)
 
-#define PLAT_VERSAL_G0_IRQ_PROPS(grp)
+#define PLAT_VERSAL_G0_IRQ_PROPS(grp) \
+	INTR_PROP_DESC(PLAT_VERSAL_IPI_IRQ, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
 
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c
index a578543..4fe3553 100644
--- a/plat/xilinx/versal/pm_service/pm_api_sys.c
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.c
@@ -15,6 +15,7 @@
 #include "pm_api_sys.h"
 #include "pm_client.h"
 #include "pm_defs.h"
+#include "pm_svc_main.h"
 
 /*********************************************************************
  * Target module IDs macros
diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c
index 55a0956..c3d28f5 100644
--- a/plat/xilinx/versal/pm_service/pm_svc_main.c
+++ b/plat/xilinx/versal/pm_service/pm_svc_main.c
@@ -13,6 +13,7 @@
 #include <plat_private.h>
 #include <stdbool.h>
 #include <common/runtime_svc.h>
+#include <plat/common/platform.h>
 #include "pm_api_sys.h"
 #include "pm_client.h"
 #include "pm_ipi.h"
@@ -20,6 +21,17 @@
 /* pm_up = true - UP, pm_up = false - DOWN */
 static bool pm_up;
 
+static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle,
+				void *cookie)
+{
+	(void)plat_ic_acknowledge_interrupt();
+
+	/* Clear FIQ */
+	plat_ic_end_of_interrupt(id);
+
+	return 0;
+}
+
 /**
  * pm_setup() - PM service setup
  *
@@ -46,6 +58,18 @@
 		pm_up = true;
 	}
 
+	/*
+	 * Enable IPI IRQ
+	 * assume the rich OS is OK to handle callback IRQs now.
+	 * Even if we were wrong, it would not enable the IRQ in
+	 * the GIC.
+	 */
+	pm_ipi_irq_enable(primary_proc);
+
+	ret = request_intr_type_el3(PLAT_VERSAL_IPI_IRQ, ipi_fiq_handler);
+	if (ret) {
+		WARN("BL31: registering IPI interrupt failed\n");
+	}
 	return ret;
 }