Rework use of ARM GIC drivers on ARM platforms

Suport for ARM GIC v2.0 and v3.0 drivers has been reworked to create three
separate drivers instead of providing a single driver that can work on both
versions of the GIC architecture. These drivers correspond to the following
software use cases:

1. A GICv2 only driver that can run only on ARM GIC v2.0 implementations
   e.g. GIC-400

2. A GICv3 only driver that can run only on ARM GIC v3.0 implementations
   e.g. GIC-500 in a mode where all interrupt regimes use GICv3 features

3. A deprecated GICv3 driver that operates in legacy mode. This driver can
   operate only in the GICv2 mode in the secure world. On a GICv3 system, this
   driver allows normal world to run in either GICv3 mode (asymmetric mode)
   or in the GICv2 mode. Both modes of operation are deprecated on GICv3
   systems.

ARM platforms implement both versions of the GIC architecture. This patch adds a
layer of abstraction to help ARM platform ports chose the right GIC driver and
corresponding platform support. This is as described below:

1. A set of ARM common functions have been introduced to initialise the GIC and
   the driver during cold and warm boot. These functions are prefixed as
   "plat_arm_gic_". Weak definitions of these functions have been provided for
   each type of driver.

2. Each platform includes the sources that implement the right functions
   directly into the its makefile. The FVP can be instantiated with different
   versions of the GIC architecture. It uses the FVP_USE_GIC_DRIVER build option
   to specify which of the three drivers should be included in the build.

3. A list of secure interrupts has to be provided to initialise each of the
  three GIC drivers. For GIC v3.0 the interrupt ids have to be further
  categorised as Group 0 and Group 1 Secure interrupts. For GIC v2.0, the two
  types are merged and treated as Group 0 interrupts.

  The two lists of interrupts are exported from the platform_def.h. The lists
  are constructed by adding a list of board specific interrupt ids to a list of
  ids common to all ARM platforms and Compute sub-systems.

This patch also makes some fields of `arm_config` data structure in FVP redundant
and these unused fields are removed.

Change-Id: Ibc8c087be7a8a6b041b78c2c3bd0c648cd2035d8
diff --git a/plat/arm/board/fvp/aarch64/fvp_common.c b/plat/arm/board/fvp/aarch64/fvp_common.c
index 8771e5b..e089405 100644
--- a/plat/arm/board/fvp/aarch64/fvp_common.c
+++ b/plat/arm/board/fvp/aarch64/fvp_common.c
@@ -30,14 +30,23 @@
 
 #include <arm_config.h>
 #include <arm_def.h>
-#include <arm_gic.h>
 #include <cci.h>
 #include <debug.h>
+#include <gicv2.h>
 #include <mmio.h>
 #include <plat_arm.h>
 #include <v2m_def.h>
 #include "../fvp_def.h"
 
+#if (FVP_USE_GIC_DRIVER == FVP_GICV2)
+extern gicv2_driver_data_t arm_gic_data;
+#endif
+
+/* Defines for GIC Driver build time selection */
+#define FVP_GICV2		1
+#define FVP_GICV3		2
+#define FVP_GICV3_LEGACY	3
+
 /*******************************************************************************
  * arm_config holds the characteristics of the differences between the three FVP
  * platforms (Base, A53_A57 & Foundation). It will be populated during cold boot
@@ -109,33 +118,6 @@
 
 ARM_CASSERT_MMAP
 
-
-#if IMAGE_BL31 || IMAGE_BL32
-/* Array of secure interrupts to be configured by the gic driver */
-const unsigned int irq_sec_array[] = {
-	ARM_IRQ_SEC_PHY_TIMER,
-	ARM_IRQ_SEC_SGI_0,
-	ARM_IRQ_SEC_SGI_1,
-	ARM_IRQ_SEC_SGI_2,
-	ARM_IRQ_SEC_SGI_3,
-	ARM_IRQ_SEC_SGI_4,
-	ARM_IRQ_SEC_SGI_5,
-	ARM_IRQ_SEC_SGI_6,
-	ARM_IRQ_SEC_SGI_7,
-	FVP_IRQ_TZ_WDOG,
-	FVP_IRQ_SEC_SYS_TIMER
-};
-
-void plat_arm_gic_init(void)
-{
-	arm_gic_init(arm_config.gicc_base,
-		arm_config.gicd_base,
-		BASE_GICR_BASE,
-		irq_sec_array,
-		ARRAY_SIZE(irq_sec_array));
-}
-
-#endif
 
 /*******************************************************************************
  * A single boot loader stack is expected to work on both the Foundation FVP
@@ -165,16 +147,28 @@
 	 */
 	switch (bld) {
 	case BLD_GIC_VE_MMAP:
-		arm_config.gicd_base = VE_GICD_BASE;
-		arm_config.gicc_base = VE_GICC_BASE;
-		arm_config.gich_base = VE_GICH_BASE;
-		arm_config.gicv_base = VE_GICV_BASE;
+#if IMAGE_BL31 || IMAGE_BL32
+#if FVP_USE_GIC_DRIVER == FVP_GICV2
+		/*
+		 * If the FVP implements the VE compatible memory map, then the
+		 * GICv2 driver must be included in the build. Update the platform
+		 * data with the correct GICv2 base addresses before it is used
+		 * to initialise the driver.
+		 *
+		 * This update of platform data is temporary and will be removed
+		 * once VE memory map for FVP is no longer supported by Trusted
+		 * Firmware.
+		 */
+		arm_gic_data.gicd_base = VE_GICD_BASE;
+		arm_gic_data.gicc_base = VE_GICC_BASE;
+
+#else
+		ERROR("Only GICv2 driver supported for VE memory map\n");
+		panic();
+#endif /* __FVP_USE_GIC_DRIVER == FVP_GICV2__ */
+#endif /* __IMAGE_BL31 || IMAGE_BL32__ */
 		break;
 	case BLD_GIC_A53A57_MMAP:
-		arm_config.gicd_base = BASE_GICD_BASE;
-		arm_config.gicc_base = BASE_GICC_BASE;
-		arm_config.gich_base = BASE_GICH_BASE;
-		arm_config.gicv_base = BASE_GICV_BASE;
 		break;
 	default:
 		ERROR("Unsupported board build %x\n", bld);
@@ -187,8 +181,6 @@
 	 */
 	switch (hbi) {
 	case HBI_FOUNDATION_FVP:
-		arm_config.max_aff0 = 4;
-		arm_config.max_aff1 = 1;
 		arm_config.flags = 0;
 
 		/*
@@ -206,8 +198,6 @@
 		}
 		break;
 	case HBI_BASE_FVP:
-		arm_config.max_aff0 = 4;
-		arm_config.max_aff1 = 2;
 		arm_config.flags |= ARM_CONFIG_BASE_MMAP |
 			ARM_CONFIG_HAS_CCI | ARM_CONFIG_HAS_TZC;
 
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index d7b459d..c5129a6 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -30,7 +30,6 @@
 
 #include <arch_helpers.h>
 #include <arm_config.h>
-#include <arm_gic.h>
 #include <assert.h>
 #include <debug.h>
 #include <errno.h>
@@ -72,7 +71,7 @@
 static void fvp_cpu_pwrdwn_common(void)
 {
 	/* Prevent interrupts from spuriously waking up this cpu */
-	arm_gic_cpuif_deactivate();
+	plat_arm_gic_cpuif_disable();
 
 	/* Program the power controller to power off this cpu. */
 	fvp_pwrc_write_ppoffr(read_mpidr_el1());
@@ -235,9 +234,10 @@
 	fvp_power_domain_on_finish_common(target_state);
 
 	/* Enable the gic cpu interface */
-	arm_gic_cpuif_setup();
-	/* Program the gic per-cpu distributor interface */
-	arm_gic_pcpu_distif_setup();
+	plat_arm_gic_pcpu_init();
+
+	/* Program the gic per-cpu distributor or re-distributor interface */
+	plat_arm_gic_cpuif_enable();
 }
 
 /*******************************************************************************
@@ -259,7 +259,7 @@
 	fvp_power_domain_on_finish_common(target_state);
 
 	/* Enable the gic cpu interface */
-	arm_gic_cpuif_setup();
+	plat_arm_gic_cpuif_enable();
 }
 
 /*******************************************************************************
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 9ada6b2..9cb88de 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -121,5 +121,24 @@
 		TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO)	|	\
 		TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO_OLD))
 
+/*
+ * GIC related constants to cater for both GICv2 and GICv3 instances of an
+ * FVP. They could be overriden at runtime in case the FVP implements the legacy
+ * VE memory map.
+ */
+#define PLAT_ARM_GICD_BASE		BASE_GICD_BASE
+#define PLAT_ARM_GICR_BASE		BASE_GICR_BASE
+#define PLAT_ARM_GICC_BASE		BASE_GICC_BASE
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_ARM_G1S_IRQS		ARM_G1S_IRQS,			\
+					FVP_IRQ_TZ_WDOG,		\
+					FVP_IRQ_SEC_SYS_TIMER
+
+#define PLAT_ARM_G0_IRQS		ARM_G0_IRQS
 
 #endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index c46d3b7..b6f0739 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -28,6 +28,35 @@
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
+# Use the Legacy GICv3 driver on the FVP by default to maintain compatibility.
+FVP_USE_GIC_DRIVER	:= FVP_GICV3_LEGACY
+
+# The FVP platform depends on this macro to build with correct GIC driver.
+$(eval $(call add_define,FVP_USE_GIC_DRIVER))
+
+# Choose the GIC sources depending upon the how the FVP will be invoked
+ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3)
+FVP_GIC_SOURCES		:=	drivers/arm/gic/common/gic_common.c	\
+				drivers/arm/gic/v3/gicv3_main.c		\
+				drivers/arm/gic/v3/gicv3_helpers.c	\
+				plat/common/plat_gicv3.c		\
+				plat/arm/common/arm_gicv3.c
+else ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV2)
+FVP_GIC_SOURCES		:=	drivers/arm/gic/common/gic_common.c	\
+				drivers/arm/gic/v2/gicv2_main.c		\
+				drivers/arm/gic/v2/gicv2_helpers.c	\
+				plat/common/plat_gicv2.c		\
+				plat/arm/common/arm_gicv2.c
+else ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3_LEGACY)
+FVP_GIC_SOURCES		:=	drivers/arm/gic/arm_gic.c		\
+				drivers/arm/gic/gic_v2.c		\
+				drivers/arm/gic/gic_v3.c		\
+				plat/common/plat_gic.c			\
+				plat/arm/common/arm_gicv3_legacy.c
+else
+$(error "Incorrect GIC driver chosen on FVP port")
+endif
+
 PLAT_INCLUDES		:=	-Iplat/arm/board/fvp/include
 
 
@@ -62,7 +91,8 @@
 				plat/arm/board/fvp/fvp_security.c		\
 				plat/arm/board/fvp/fvp_topology.c		\
 				plat/arm/board/fvp/aarch64/fvp_helpers.S	\
-				plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c
+				plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c	\
+				${FVP_GIC_SOURCES}
 
 # Disable the PSCI platform compatibility layer
 ENABLE_PLAT_COMPAT	:= 	0
diff --git a/plat/arm/board/fvp/tsp/tsp-fvp.mk b/plat/arm/board/fvp/tsp/tsp-fvp.mk
index 99db2f4..54a76fd 100644
--- a/plat/arm/board/fvp/tsp/tsp-fvp.mk
+++ b/plat/arm/board/fvp/tsp/tsp-fvp.mk
@@ -31,6 +31,7 @@
 # TSP source files specific to FVP platform
 BL32_SOURCES		+=	plat/arm/board/fvp/fvp_topology.c		\
 				plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c	\
-				plat/arm/board/fvp/tsp/fvp_tsp_setup.c
+				plat/arm/board/fvp/tsp/fvp_tsp_setup.c		\
+				${FVP_GIC_SOURCES}
 
 include plat/arm/common/tsp/arm_tsp.mk