refactor(fvp): use more arm generic code for gicv3

The arm generic implementation for the GIC is quite comprehensive and
the fvp's requirements don't diverge too much. Despite that, they
completely override a lot of code that is effectively reused. Use the
generic implementation instead to make it easier to follow and override
as little code as possible.

Change-Id: I3474aa970d7fbb91d75c0be6a255bc0da734f860
Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
diff --git a/plat/arm/board/fvp/fvp_bl31_setup.c b/plat/arm/board/fvp/fvp_bl31_setup.c
index aa7b875..83b514a 100644
--- a/plat/arm/board/fvp/fvp_bl31_setup.c
+++ b/plat/arm/board/fvp/fvp_bl31_setup.c
@@ -91,6 +91,14 @@
 	}
 }
 
+void __init bl31_platform_setup(void)
+{
+	arm_bl31_platform_setup();
+
+	fvp_pcpu_init();
+	fvp_gic_driver_pre_init();
+}
+
 #if !TRANSFER_LIST
 void __init bl31_plat_arch_setup(void)
 {
diff --git a/plat/arm/board/fvp/fvp_gicv3.c b/plat/arm/board/fvp/fvp_gicv3.c
index e780f21..fe64bec 100644
--- a/plat/arm/board/fvp/fvp_gicv3.c
+++ b/plat/arm/board/fvp/fvp_gicv3.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,51 +21,15 @@
 static bool fvp_gicr_rw_region_init[PLATFORM_CORE_COUNT] = {false};
 #endif /* FVP_GICR_REGION_PROTECTION */
 
-/* The GICv3 driver only needs to be initialized in EL3 */
-static uintptr_t fvp_rdistif_base_addrs[PLATFORM_CORE_COUNT];
-
 /* Default GICR base address to be used for GICR probe. */
-static uint64_t fvp_gicr_base_addrs[2] = { 0U };
+static uintptr_t __unused fvp_gicr_base_addrs[2] = { 0U };
 
-/* List of zero terminated GICR frame addresses which CPUs will probe */
-static uint64_t *fvp_gicr_frames = fvp_gicr_base_addrs;
-
-#if  !(SEC_INT_DESC_IN_FCONF && ((!defined(__aarch64__) && defined(IMAGE_BL32)) || \
-	(defined(__aarch64__) && defined(IMAGE_BL31))))
-static const interrupt_prop_t fvp_interrupt_props[] = {
+static const interrupt_prop_t __unused fvp_interrupt_props[] = {
 	PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
 	PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0)
 };
-#endif
 
-/*
- * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
- * to core position.
- *
- * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
- * values read from GICR_TYPER don't have an MT field. To reuse the same
- * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
- * that read from GICR_TYPER.
- *
- * Assumptions:
- *
- *   - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
- *   - No CPUs implemented in the system use affinity level 3.
- */
-static unsigned int fvp_gicv3_mpidr_hash(u_register_t mpidr)
-{
-	u_register_t temp_mpidr = mpidr;
-
-	temp_mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
-	return plat_arm_calc_core_pos(temp_mpidr);
-}
-
-
-static gicv3_driver_data_t fvp_gic_data = {
-	.rdistif_num = PLATFORM_CORE_COUNT,
-	.rdistif_base_addrs = fvp_rdistif_base_addrs,
-	.mpidr_to_core_pos = fvp_gicv3_mpidr_hash
-};
+extern gicv3_driver_data_t arm_gic_data;
 
 /******************************************************************************
  * This function gets called per core to make its redistributor frame rw
@@ -97,78 +61,41 @@
 #endif /* FVP_GICR_REGION_PROTECTION */
 }
 
-void plat_arm_gic_driver_init(void)
+void fvp_pcpu_init(void)
 {
 	fvp_gicv3_make_rdistrif_rw();
+}
+
+void fvp_gic_driver_pre_init(void)
+{
+/* FCONF won't be used in these cases, so we couldn't do this */
+#if !(BL2_AT_EL3 || RESET_TO_BL31 || RESET_TO_SP_MIN)
 	/*
 	 * Get GICD and GICR base addressed through FCONF APIs.
 	 * FCONF is not supported in BL32 for FVP.
 	 */
 #if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \
 	(defined(__aarch64__) && defined(IMAGE_BL31))
-	fvp_gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config,
+	arm_gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config,
 							       gicv3_config,
 							       gicd_base);
 	fvp_gicr_base_addrs[0] = FCONF_GET_PROPERTY(hw_config, gicv3_config,
 						    gicr_base);
 #if SEC_INT_DESC_IN_FCONF
-	fvp_gic_data.interrupt_props = FCONF_GET_PROPERTY(hw_config,
+	arm_gic_data.interrupt_props = FCONF_GET_PROPERTY(hw_config,
 					sec_intr_prop, descriptor);
-	fvp_gic_data.interrupt_props_num = FCONF_GET_PROPERTY(hw_config,
+	arm_gic_data.interrupt_props_num = FCONF_GET_PROPERTY(hw_config,
 					sec_intr_prop, count);
 #else
-	fvp_gic_data.interrupt_props = fvp_interrupt_props;
-	fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
+	arm_gic_data.interrupt_props = fvp_interrupt_props;
+	arm_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
 #endif
 #else
-	fvp_gic_data.gicd_base = PLAT_ARM_GICD_BASE;
+	arm_gic_data.gicd_base = PLAT_ARM_GICD_BASE;
 	fvp_gicr_base_addrs[0] = PLAT_ARM_GICR_BASE;
-	fvp_gic_data.interrupt_props = fvp_interrupt_props;
-	fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
+	arm_gic_data.interrupt_props = fvp_interrupt_props;
+	arm_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
 #endif
-
-	/*
-	 * The GICv3 driver is initialized in EL3 and does not need
-	 * to be initialized again in SEL1. This is because the S-EL1
-	 * can use GIC system registers to manage interrupts and does
-	 * not need GIC interface base addresses to be configured.
-	 */
-
-#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \
-	(defined(__aarch64__) && defined(IMAGE_BL31))
-	gicv3_driver_init(&fvp_gic_data);
-	if (gicv3_rdistif_probe((uintptr_t)fvp_gicr_base_addrs[0]) == -1) {
-		ERROR("No GICR base frame found for Primary CPU\n");
-		panic();
-	}
-#endif
-}
-
-/******************************************************************************
- * Function to iterate over all GICR frames and discover the corresponding
- * per-cpu redistributor frame as well as initialize the corresponding
- * interface in GICv3.
- *****************************************************************************/
-void plat_arm_gic_pcpu_init(void)
-{
-	int result;
-	const uint64_t *plat_gicr_frames = fvp_gicr_frames;
-
-	fvp_gicv3_make_rdistrif_rw();
-
-	do {
-		result = gicv3_rdistif_probe(*plat_gicr_frames);
-
-		/* If the probe is successful, no need to proceed further */
-		if (result == 0)
-			break;
-
-		plat_gicr_frames++;
-	} while (*plat_gicr_frames != 0U);
-
-	if (result == -1) {
-		ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr());
-		panic();
-	}
-	gicv3_rdistif_init(plat_my_core_pos());
+	plat_arm_override_gicr_frames(fvp_gicr_base_addrs);
+#endif /* !(BL2_AT_EL3 || RESET_TO_BL31 || RESET_TO_SP_MIN) */
 }
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 2a0bb93..f01678b 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -263,6 +263,7 @@
  ******************************************************************************/
 static void fvp_pwr_domain_on_finish_late(const psci_power_state_t *target_state)
 {
+	fvp_pcpu_init();
 	/* Program GIC per-cpu distributor or re-distributor interface */
 	plat_arm_gic_pcpu_init();
 
diff --git a/plat/arm/board/fvp/fvp_private.h b/plat/arm/board/fvp/fvp_private.h
index 3590370..9a51eb7 100644
--- a/plat/arm/board/fvp/fvp_private.h
+++ b/plat/arm/board/fvp/fvp_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,5 +20,7 @@
 void fvp_interconnect_disable(void);
 void fvp_timer_init(void);
 void tsp_early_platform_setup(void);
+void fvp_pcpu_init(void);
+void fvp_gic_driver_pre_init(void);
 
 #endif /* FVP_PRIVATE_H */
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 280aa39..888ab46 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -140,12 +140,8 @@
 
 FVP_GIC_SOURCES		:=	${GICV3_SOURCES}			\
 				plat/common/plat_gicv3.c		\
-				plat/arm/common/arm_gicv3.c
-
-	ifeq ($(filter 1,${RESET_TO_BL2} \
-		${RESET_TO_BL31} ${RESET_TO_SP_MIN}),)
-		FVP_GIC_SOURCES += plat/arm/board/fvp/fvp_gicv3.c
-	endif
+				plat/arm/common/arm_gicv3.c		\
+				plat/arm/board/fvp/fvp_gicv3.c
 
 else ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV2)
 
diff --git a/plat/arm/common/arm_gicv3.c b/plat/arm/common/arm_gicv3.c
index 5becbcd..180da2f 100644
--- a/plat/arm/common/arm_gicv3.c
+++ b/plat/arm/common/arm_gicv3.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -79,7 +79,7 @@
 	return plat_arm_calc_core_pos(mpidr);
 }
 
-static const gicv3_driver_data_t arm_gic_data __unused = {
+gicv3_driver_data_t arm_gic_data __unused = {
 	.gicd_base = PLAT_ARM_GICD_BASE,
 	.gicr_base = 0U,
 	.interrupt_props = arm_interrupt_props,