feat(fvp): add GICv5 support

Factors out GICv3 specific code and replace it with GICv5. This can be
selected with FVP_USE_GIC_DRIVER=FVP_GICV5. Specifically, the FCONF
logic does not apply to GICv5 as the bindings are completely different.

This patch does not include a device tree. This will be added at a later
date.

Change-Id: Ifd0c7b4e0bc2ea1e53a6779ab4c50c4aec39dafb
Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
diff --git a/plat/arm/board/fvp/fconf/fconf_gicv3_config_getter.c b/plat/arm/board/fvp/fconf/fconf_gicv3_config_getter.c
new file mode 100644
index 0000000..7cb88ed
--- /dev/null
+++ b/plat/arm/board/fvp/fconf/fconf_gicv3_config_getter.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/arm/gicv3.h>
+
+#include <fconf_hw_config_getter.h>
+
+struct gicv3_config_t gicv3_config;
+
+int fconf_populate_gicv3_config(uintptr_t config)
+{
+	int err;
+	int node;
+	uintptr_t addr;
+
+	/* Necessary to work with libfdt APIs */
+	const void *hw_config_dtb = (const void *)config;
+
+	/*
+	 * Find the offset of the node containing "arm,gic-v3" compatible property.
+	 * Populating fconf strucutures dynamically is not supported for legacy
+	 * systems which use GICv2 IP. Simply skip extracting GIC properties.
+	 */
+	node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,gic-v3");
+	if (node < 0) {
+		WARN("FCONF: Unable to locate node with arm,gic-v3 compatible property\n");
+		return 0;
+	}
+	/* The GICv3 DT binding holds at least two address/size pairs,
+	 * the first describing the distributor, the second the redistributors.
+	 * See: bindings/interrupt-controller/arm,gic-v3.yaml
+	 */
+	err = fdt_get_reg_props_by_index(hw_config_dtb, node, 0, &addr, NULL);
+	if (err < 0) {
+		ERROR("FCONF: Failed to read GICD reg property of GIC node\n");
+		return err;
+	}
+	gicv3_config.gicd_base = addr;
+
+	err = fdt_get_reg_props_by_index(hw_config_dtb, node, 1, &addr, NULL);
+	if (err < 0) {
+		ERROR("FCONF: Failed to read GICR reg property of GIC node\n");
+	} else {
+		gicv3_config.gicr_base = addr;
+	}
+
+	return err;
+}
+FCONF_REGISTER_POPULATOR(HW_CONFIG, gicv3_config, fconf_populate_gicv3_config);
diff --git a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
index fb7f48e..abc78ce 100644
--- a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+++ b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
@@ -14,7 +14,6 @@
 #include <libfdt.h>
 #include <plat/common/platform.h>
 
-struct gicv3_config_t gicv3_config;
 struct hw_topology_t soc_topology;
 struct uart_serial_config_t uart_serial_config;
 struct cpu_timer_t cpu_timer;
@@ -32,45 +31,6 @@
 
 #define ILLEGAL_ADDR	ULL(~0)
 
-int fconf_populate_gicv3_config(uintptr_t config)
-{
-	int err;
-	int node;
-	uintptr_t addr;
-
-	/* Necessary to work with libfdt APIs */
-	const void *hw_config_dtb = (const void *)config;
-
-	/*
-	 * Find the offset of the node containing "arm,gic-v3" compatible property.
-	 * Populating fconf strucutures dynamically is not supported for legacy
-	 * systems which use GICv2 IP. Simply skip extracting GIC properties.
-	 */
-	node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,gic-v3");
-	if (node < 0) {
-		WARN("FCONF: Unable to locate node with arm,gic-v3 compatible property\n");
-		return 0;
-	}
-	/* The GICv3 DT binding holds at least two address/size pairs,
-	 * the first describing the distributor, the second the redistributors.
-	 * See: bindings/interrupt-controller/arm,gic-v3.yaml
-	 */
-	err = fdt_get_reg_props_by_index(hw_config_dtb, node, 0, &addr, NULL);
-	if (err < 0) {
-		ERROR("FCONF: Failed to read GICD reg property of GIC node\n");
-		return err;
-	}
-	gicv3_config.gicd_base = addr;
-
-	err = fdt_get_reg_props_by_index(hw_config_dtb, node, 1, &addr, NULL);
-	if (err < 0) {
-		ERROR("FCONF: Failed to read GICR reg property of GIC node\n");
-	} else {
-		gicv3_config.gicr_base = addr;
-	}
-
-	return err;
-}
 
 int fconf_populate_topology(uintptr_t config)
 {
@@ -447,7 +407,6 @@
 	return 0;
 }
 
-FCONF_REGISTER_POPULATOR(HW_CONFIG, gicv3_config, fconf_populate_gicv3_config);
 FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology);
 FCONF_REGISTER_POPULATOR(HW_CONFIG, uart_config, fconf_populate_uart_config);
 FCONF_REGISTER_POPULATOR(HW_CONFIG, cpu_timer, fconf_populate_cpu_timer);
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index 9d0463d..95dff53 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -68,6 +68,10 @@
 
 #define MAP_DEVICE1	MAP_REGION_FLAT(DEVICE1_BASE,			\
 					DEVICE1_SIZE,			\
+					MT_DEVICE | MT_RW | EL3_PAS)
+
+#define MAP_CCN		MAP_REGION_FLAT(CCN_BASE,			\
+					CCN_SIZE,			\
 					MT_DEVICE | MT_RW | MT_SECURE)
 
 #if FVP_GICR_REGION_PROTECTION
@@ -115,7 +119,7 @@
 	V2M_MAP_IOFPGA,
 	MAP_DEVICE0,
 #if FVP_INTERCONNECT_DRIVER == FVP_CCN
-	MAP_DEVICE1,
+	MAP_CCN,
 #endif
 #if TRUSTED_BOARD_BOOT
 	/* To access the Root of Trust Public Key registers. */
@@ -133,7 +137,7 @@
 	V2M_MAP_IOFPGA,
 	MAP_DEVICE0,
 #if FVP_INTERCONNECT_DRIVER == FVP_CCN
-	MAP_DEVICE1,
+	MAP_CCN,
 #endif
 	ARM_MAP_NS_DRAM1,
 #ifdef __aarch64__
@@ -208,6 +212,9 @@
 	MAP_GICD_MEM,
 	MAP_GICR_MEM,
 #else
+#if FVP_INTERCONNECT_DRIVER == FVP_CCN
+	MAP_CCN,
+#endif
 	MAP_DEVICE1,
 #endif /* FVP_GICR_REGION_PROTECTION */
 	ARM_V2M_MAP_MEM_PROTECT,
@@ -254,6 +261,9 @@
 #endif
 	V2M_MAP_IOFPGA,
 	MAP_DEVICE0,
+#if FVP_INTERCONNECT_DRIVER == FVP_CCN
+	MAP_CCN,
+#endif
 	MAP_DEVICE1,
 	{0}
 };
diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h
index 831eb35..d87be31 100644
--- a/plat/arm/board/fvp/fvp_def.h
+++ b/plat/arm/board/fvp/fvp_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -53,12 +53,12 @@
  *  In case of FVP models with CCN, the CCN register space overlaps into
  *  the NSRAM area.
  */
-#if FVP_INTERCONNECT_DRIVER == FVP_CCN
-#define DEVICE1_BASE			UL(0x2e000000)
-#define DEVICE1_SIZE			UL(0x1A00000)
-#else
-#define DEVICE1_BASE			BASE_GICD_BASE
+#define CCN_BASE			UL(0x2e000000)
+#define CCN_SIZE			UL(0x1000000)
 
+/* TODO: this covers gicv5, but macros should be adjusted */
+#if USE_GIC_DRIVER != 5
+#define DEVICE1_BASE			BASE_GICD_BASE
 #if GIC_ENABLE_V4_EXTN
 /* GICv4 mapping: GICD + CORE_COUNT * 256KB */
 #define DEVICE1_SIZE			((BASE_GICR_BASE - BASE_GICD_BASE) + \
@@ -68,10 +68,11 @@
 #define DEVICE1_SIZE			((BASE_GICR_BASE - BASE_GICD_BASE) + \
 					 (PLATFORM_CORE_COUNT * 0x20000))
 #endif /* GIC_ENABLE_V4_EXTN */
-
-#define NSRAM_BASE			UL(0x2e000000)
-#define NSRAM_SIZE			UL(0x10000)
+#else
+#define DEVICE1_BASE			BASE_IWB_BASE
+#define DEVICE1_SIZE			((BASE_IRS_BASE - BASE_IWB_BASE) + SZ_64K)
 #endif
+
 /* Devices in the second GB */
 #define DEVICE2_BASE			UL(0x7fe00000)
 #define DEVICE2_SIZE			UL(0x00200000)
@@ -124,6 +125,15 @@
 #define FVP_SP810_CTRL_TIM2_OV		BIT_32(20)
 #define FVP_SP810_CTRL_TIM3_OV		BIT_32(22)
 
+
+#define NSRAM_BASE			UL(0x2e000000)
+#define NSRAM_SIZE			UL(0x10000)
+/*
+ *  In case of FVP models with CCN, the CCN register space overlaps into
+ *  the NSRAM area.
+ */
+#define CCN_BASE			UL(0x2e000000)
+#define CCN_SIZE			UL(0x1000000)
 /*******************************************************************************
  * GIC & interrupt handling related constants
  ******************************************************************************/
@@ -138,6 +148,9 @@
 #define BASE_GICD_SIZE			UL(0x10000)
 #define BASE_GICR_BASE			UL(0x2f100000)
 
+#define BASE_IWB_BASE			UL(0x2f000000)
+#define BASE_IRS_BASE			UL(0x2f1c0000)
+
 #if GIC_ENABLE_V4_EXTN
 /* GICv4 redistributor size: 256KB */
 #define BASE_GICR_SIZE			UL(0x40000)
diff --git a/plat/arm/board/fvp/fvp_gicv5.c b/plat/arm/board/fvp/fvp_gicv5.c
new file mode 100644
index 0000000..73bd9c5
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_gicv5.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/gicv5.h>
+#include <platform_def.h>
+
+/* wire 26 is the timer interrupt. Will be assigned NS by default */
+struct gicv5_wire_props irs0_spis[] = {
+};
+
+struct gicv5_wire_props iwb0_wires[] = {
+};
+
+struct gicv5_irs irss[] = {{
+	.el3_config_frame = BASE_IRS_BASE,
+	.spis = irs0_spis,
+	.num_spis = ARRAY_SIZE(irs0_spis),
+}};
+
+struct gicv5_iwb iwbs[] = {{
+	.config_frame = BASE_IWB_BASE,
+	.wires = iwb0_wires,
+	.num_wires = ARRAY_SIZE(iwb0_wires)
+}};
+
+const struct gicv5_driver_data plat_gicv5_driver_data = {
+	.irss = irss,
+	.iwbs = iwbs,
+	.num_irss = ARRAY_SIZE(irss),
+	.num_iwbs = ARRAY_SIZE(iwbs)
+};
+
+void fvp_gic_driver_pre_init(void)
+{
+}
+
+void fvp_pcpu_init(void)
+{
+}
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 26ea58d..bf4aaf8 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -22,13 +22,6 @@
 # only; enable redistributor frames of all CPU cores by default.
 FVP_GICR_REGION_PROTECTION	:= 0
 
-ifeq (${HW_ASSISTED_COHERENCY}, 0)
-FVP_DT_PREFIX			:= fvp-base-gicv3-psci
-else
-FVP_DT_PREFIX			:= fvp-base-gicv3-psci-dynamiq
-endif
-# fdts is wrong otherwise
-
 # Size (in kilobytes) of the Trusted SRAM region to utilize when building for
 # the FVP platform.
 ifeq (${ENABLE_RME},1)
@@ -137,7 +130,20 @@
 GICV3_OVERRIDE_DISTIF_PWR_OPS	:=	1
 
 FVP_SECURITY_SOURCES += plat/arm/board/fvp/fvp_gicv3.c
+ifeq ($(filter 1,${RESET_TO_BL2} ${RESET_TO_BL31}),)
+BL31_SOURCES		+=	plat/arm/board/fvp/fconf/fconf_gicv3_config_getter.c
+endif
 
+ifeq (${HW_ASSISTED_COHERENCY}, 0)
+FVP_DT_PREFIX			:= fvp-base-gicv3-psci
+else
+FVP_DT_PREFIX			:= fvp-base-gicv3-psci-dynamiq
+endif
+else ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV5)
+USE_GIC_DRIVER		:=	5
+ENABLE_FEAT_GCIE	:=	1
+BL31_SOURCES		+=	plat/arm/board/fvp/fvp_gicv5.c
+FVP_DT_PREFIX		:=	"FVP does not provide a GICv5 dts yet"
 else ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV2)
 USE_GIC_DRIVER		:=	2