plat/arm/board/arm_fpga: Initialize the Generic Interrupt Controller

This initializes the GIC using the Arm GIC drivers in TF-A.
The initial FPGA image uses a GIC600 implementation, and so that its
power controller is enabled, this platform port calls the corresponding
implementation-specific routines.

Signed-off-by: Oliver Swede <oli.swede@arm.com>
Change-Id: I88d5a073eead4b653b1ca73273182cd98a95e4c5
diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
index 26228f6..d499379 100644
--- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c
+++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
@@ -51,11 +51,12 @@
 
 void bl31_platform_setup(void)
 {
+	/* Initialize the GIC driver, cpu and distributor interfaces */
+	plat_fpga_gic_init();
+
 	/* Write frequency to CNTCRL and initialize timer */
 	generic_delay_timer_init();
 	mmio_write_32(FPGA_TIMER_BASE, ((1 << 8) | 1UL));
-
-	/* TODO: initialize GIC using the specifications of the FPGA image */
 }
 
 entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
diff --git a/plat/arm/board/arm_fpga/fpga_gicv3.c b/plat/arm/board/arm_fpga/fpga_gicv3.c
new file mode 100644
index 0000000..be1684e
--- /dev/null
+++ b/plat/arm/board/arm_fpga/fpga_gicv3.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/gicv3.h>
+#include <drivers/arm/gic_common.h>
+
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+static const interrupt_prop_t fpga_interrupt_props[] = {
+	PLATFORM_G1S_PROPS(INTR_GROUP1S),
+	PLATFORM_G0_PROPS(INTR_GROUP0)
+};
+
+static uintptr_t fpga_rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static unsigned int fpga_mpidr_to_core_pos(unsigned long mpidr)
+{
+	return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+static const gicv3_driver_data_t fpga_gicv3_driver_data = {
+	.gicd_base = GICD_BASE,
+	.gicr_base = GICR_BASE,
+	.interrupt_props = fpga_interrupt_props,
+	.interrupt_props_num = ARRAY_SIZE(fpga_interrupt_props),
+	.rdistif_num = PLATFORM_CORE_COUNT,
+	.rdistif_base_addrs = fpga_rdistif_base_addrs,
+	.mpidr_to_core_pos = fpga_mpidr_to_core_pos
+};
+
+void plat_fpga_gic_init(void)
+{
+	gicv3_driver_init(&fpga_gicv3_driver_data);
+	gicv3_distif_init();
+	gicv3_rdistif_init(plat_my_core_pos());
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void fpga_pwr_gic_on_finish(void)
+{
+	gicv3_rdistif_init(plat_my_core_pos());
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void fpga_pwr_gic_off(void)
+{
+	gicv3_cpuif_disable(plat_my_core_pos());
+	gicv3_rdistif_off(plat_my_core_pos());
+}
diff --git a/plat/arm/board/arm_fpga/fpga_pm.c b/plat/arm/board/arm_fpga/fpga_pm.c
index a734e1d..4c37217 100644
--- a/plat/arm/board/arm_fpga/fpga_pm.c
+++ b/plat/arm/board/arm_fpga/fpga_pm.c
@@ -9,6 +9,8 @@
 #include <lib/psci/psci.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
+
+#include "fpga_private.h"
 #include <platform_def.h>
 
 /*
@@ -52,8 +54,15 @@
 	return PSCI_E_SUCCESS;
 }
 
+void fpga_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	fpga_pwr_gic_on_finish();
+}
+
 static void fpga_pwr_domain_off(const psci_power_state_t *target_state)
 {
+	fpga_pwr_gic_off();
+
 	while (1) {
 		wfi();
 	}
@@ -74,6 +83,7 @@
 
 plat_psci_ops_t plat_fpga_psci_pm_ops = {
 	.pwr_domain_on = fpga_pwr_domain_on,
+	.pwr_domain_on_finish = fpga_pwr_domain_on_finish,
 	.pwr_domain_off = fpga_pwr_domain_off,
 	.cpu_standby = fpga_cpu_standby
 };
diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h
index 28aaef2..7545bd1 100644
--- a/plat/arm/board/arm_fpga/fpga_private.h
+++ b/plat/arm/board/arm_fpga/fpga_private.h
@@ -11,4 +11,8 @@
 
 void fpga_console_init(void);
 
+void plat_fpga_gic_init(void);
+void fpga_pwr_gic_on_finish(void);
+void fpga_pwr_gic_off(void);
+
 #endif
diff --git a/plat/arm/board/arm_fpga/include/platform_def.h b/plat/arm/board/arm_fpga/include/platform_def.h
index bf3245e..6e87a26 100644
--- a/plat/arm/board/arm_fpga/include/platform_def.h
+++ b/plat/arm/board/arm_fpga/include/platform_def.h
@@ -28,8 +28,51 @@
 #define BL31_BASE			UL(0x80000000)
 #define BL31_LIMIT			UL(0x80100000)
 
-#define PLAT_MAX_RET_STATE		1
-#define PLAT_MAX_OFF_STATE		2
+#define GICD_BASE			0x30000000
+#define GICR_BASE			0x30040000
+
+#define PLAT_SDEI_NORMAL_PRI		0x70
+
+#define ARM_IRQ_SEC_PHY_TIMER		29
+
+#define ARM_IRQ_SEC_SGI_0		8
+#define ARM_IRQ_SEC_SGI_1		9
+#define ARM_IRQ_SEC_SGI_2		10
+#define ARM_IRQ_SEC_SGI_3		11
+#define ARM_IRQ_SEC_SGI_4		12
+#define ARM_IRQ_SEC_SGI_5		13
+#define ARM_IRQ_SEC_SGI_6		14
+#define ARM_IRQ_SEC_SGI_7		15
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLATFORM_G1S_PROPS(grp) \
+	INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+			GIC_INTR_CFG_LEVEL), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+			GIC_INTR_CFG_EDGE)
+
+#define PLATFORM_G0_PROPS(grp) \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, (grp), \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+			GIC_INTR_CFG_EDGE)
+
+#define PLAT_MAX_RET_STATE 		1
+#define PLAT_MAX_OFF_STATE 		2
 
 #define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL2
 
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index 73e1870..8ce0ae0 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -37,9 +37,14 @@
 FPGA_CPU_LIBS		:=	lib/cpus/${ARCH}/aem_generic.S		\
 				lib/cpus/aarch64/neoverse_zeus.S
 
-FPGA_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v3/gicv3_main.c		\
-				plat/common/plat_gicv3.c
+FPGA_GIC_SOURCES	:=	drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c     \
+                                drivers/arm/gic/v3/gicrv3_helpers.c     \
+                                drivers/arm/gic/v3/gicv3_main.c         \
+				drivers/arm/gic/v3/gic600.c		\
+				drivers/arm/gic/common/gic_common.c     \
+				plat/common/plat_gicv3.c		\
+				plat/arm/board/arm_fpga/fpga_gicv3.c
 
 PLAT_INCLUDES		:=	-Iplat/arm/board/arm_fpga/include