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,