From 0c9f91cf699565c858e650d19bbdcab513d5001a Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 20 Jul 2021 19:20:07 +0100 Subject: [PATCH 1/5] refactor(gicv3): rename GIC Clayton to GIC-700 The GIC IP formerly known as "GIC Clayton" has been released under the name of "GIC-700". Rename occurences of Clayton in comments and macro names to reflect the official name. Change-Id: Ie8c55f7da7753127d58c8382b0033c1b486f7909 Signed-off-by: Andre Przywara --- drivers/arm/gic/v3/gic-x00.c | 8 ++++---- drivers/arm/gic/v3/gic600_multichip_private.h | 4 ++-- plat/arm/board/rdn2/platform.mk | 2 +- plat/arm/board/rdv1/platform.mk | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/arm/gic/v3/gic-x00.c b/drivers/arm/gic/v3/gic-x00.c index 6e106babf..eccfd976f 100644 --- a/drivers/arm/gic/v3/gic-x00.c +++ b/drivers/arm/gic/v3/gic-x00.c @@ -24,7 +24,7 @@ #define GICR_PWRR 0x24U #define IIDR_MODEL_ARM_GIC_600 U(0x0200043b) #define IIDR_MODEL_ARM_GIC_600AE U(0x0300043b) -#define IIDR_MODEL_ARM_GIC_CLAYTON U(0x0400043b) +#define IIDR_MODEL_ARM_GIC_700 U(0x0400043b) /* GICR_PWRR fields */ #define PWRR_RDPD_SHIFT 0 @@ -46,7 +46,7 @@ #if GICV3_SUPPORT_GIC600 -/* GIC-600/Clayton specific accessor functions */ +/* GIC-600/700 specific accessor functions */ static void gicr_write_pwrr(uintptr_t base, unsigned int val) { mmio_write_32(base + GICR_PWRR, val); @@ -123,12 +123,12 @@ static bool gicv3_redists_need_power_mgmt(uintptr_t gicr_base) uint32_t reg = mmio_read_32(gicr_base + GICR_IIDR); /* - * The Arm GIC-600 and GIC-Clayton models have their redistributors + * The Arm GIC-600 and GIC-700 models have their redistributors * powered down at reset. */ return (((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) || ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600AE) || - ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_CLAYTON)); + ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700)); } #endif /* GICV3_SUPPORT_GIC600 */ diff --git a/drivers/arm/gic/v3/gic600_multichip_private.h b/drivers/arm/gic/v3/gic600_multichip_private.h index fe4134cba..27b8e817f 100644 --- a/drivers/arm/gic/v3/gic600_multichip_private.h +++ b/drivers/arm/gic/v3/gic600_multichip_private.h @@ -28,8 +28,8 @@ #define GICD_DCHIPR_RT_OWNER_SHIFT 4 /* - * If GIC v4 extension is enabled, then use SPI macros specific to GIC-Clayton. - * Other shifts and mask remains same between GIC-600 and GIC-Clayton. + * If GIC v4 extension is enabled, then use SPI macros specific to GIC-700. + * Other shifts and mask remains same between GIC-600 and GIC-700. */ #if GIC_ENABLE_V4_EXTN #define GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT 9 diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk index 794f8974f..5b24c32bd 100644 --- a/plat/arm/board/rdn2/platform.mk +++ b/plat/arm/board/rdn2/platform.mk @@ -3,7 +3,7 @@ # SPDX-License-Identifier: BSD-3-Clause # -# RD-N2 platform uses GIC-Clayton which is based on GICv4.1 +# RD-N2 platform uses GIC-700 which is based on GICv4.1 GIC_ENABLE_V4_EXTN := 1 include plat/arm/css/sgi/sgi-common.mk diff --git a/plat/arm/board/rdv1/platform.mk b/plat/arm/board/rdv1/platform.mk index 1ae85de7c..11f52127e 100644 --- a/plat/arm/board/rdv1/platform.mk +++ b/plat/arm/board/rdv1/platform.mk @@ -3,7 +3,7 @@ # SPDX-License-Identifier: BSD-3-Clause # -# RD-V1 platform uses GIC-Clayton which is based on GICv4.1 +# RD-V1 platform uses GIC-700 which is based on GICv4.1 GIC_ENABLE_V4_EXTN := 1 include plat/arm/css/sgi/sgi-common.mk From 1fe27d71353dd35f60555012c5ace246836517cc Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 24 Aug 2021 10:02:52 +0100 Subject: [PATCH 2/5] refactor(gic): move GIC IIDR numbers For the GIC power management we need to identify certain GIC implementations, so we have the IIDR values for some Arm Ltd. GIC models defined. We will need those number elsewhere very soon, so export them to a shared header file, to avoid defining them again. Change-Id: I1b8e2d93d6cea0d066866143c89eef736231134f Signed-off-by: Andre Przywara --- drivers/arm/gic/v3/gic-x00.c | 4 +--- include/drivers/arm/arm_gicv3_common.h | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/arm/gic/v3/gic-x00.c b/drivers/arm/gic/v3/gic-x00.c index eccfd976f..aaef485ff 100644 --- a/drivers/arm/gic/v3/gic-x00.c +++ b/drivers/arm/gic/v3/gic-x00.c @@ -16,15 +16,13 @@ #include #include +#include #include #include "gicv3_private.h" /* GIC-600 specific register offsets */ #define GICR_PWRR 0x24U -#define IIDR_MODEL_ARM_GIC_600 U(0x0200043b) -#define IIDR_MODEL_ARM_GIC_600AE U(0x0300043b) -#define IIDR_MODEL_ARM_GIC_700 U(0x0400043b) /* GICR_PWRR fields */ #define PWRR_RDPD_SHIFT 0 diff --git a/include/drivers/arm/arm_gicv3_common.h b/include/drivers/arm/arm_gicv3_common.h index b88b59fbf..e5df31136 100644 --- a/include/drivers/arm/arm_gicv3_common.h +++ b/include/drivers/arm/arm_gicv3_common.h @@ -17,4 +17,8 @@ #define WAKER_SL_BIT (1U << WAKER_SL_SHIFT) #define WAKER_QSC_BIT (1U << WAKER_QSC_SHIFT) +#define IIDR_MODEL_ARM_GIC_600 U(0x0200043b) +#define IIDR_MODEL_ARM_GIC_600AE U(0x0300043b) +#define IIDR_MODEL_ARM_GIC_700 U(0x0400043b) + #endif /* ARM_GICV3_COMMON_H */ From feb7081863f454b9e465efc074ca669f7a4c783d Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 18 May 2021 15:46:58 +0100 Subject: [PATCH 3/5] feat(gicv3): multichip: detect GIC-700 at runtime At the moment we have a GIC_ENABLE_V4_EXTN build time variable to determine whether the GIC interrupt controller is compliant to version 4.0 of the GIC spec or not. In case of the GIC-600 multichip support we were somewhat abusing that flag to differentiate between a GIC-700 and GIC-600 implementation being used in the system. To avoid a build time dependency on this flag, look at the GICD_IIDR register and check if the hardware is a GIC-600 or not, to make this decision at runtime. We then use the values for either GIC-700 or the GIC-600, respectively. Change-Id: I8c09ec1cd6fd60d28da879ed55ffef5506f9869d Signed-off-by: Andre Przywara --- drivers/arm/gic/v3/gic600_multichip.c | 22 ++++++++++++++-- drivers/arm/gic/v3/gic600_multichip_private.h | 26 +++++++++---------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/arm/gic/v3/gic600_multichip.c b/drivers/arm/gic/v3/gic600_multichip.c index ca7c43bf9..fd3d8c207 100644 --- a/drivers/arm/gic/v3/gic600_multichip.c +++ b/drivers/arm/gic/v3/gic600_multichip.c @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -73,6 +74,7 @@ static void set_gicd_chipr_n(uintptr_t base, unsigned int spi_id_max) { unsigned int spi_block_min, spi_blocks; + unsigned int gicd_iidr_val = gicd_read_iidr(base); uint64_t chipr_n_val; /* @@ -100,8 +102,24 @@ static void set_gicd_chipr_n(uintptr_t base, spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min); spi_blocks = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max); - chipr_n_val = (GICD_CHIPR_VALUE(chip_addr, spi_block_min, spi_blocks)) | - GICD_CHIPRx_SOCKET_STATE; + switch ((gicd_iidr_val & IIDR_MODEL_MASK)) { + case IIDR_MODEL_ARM_GIC_600: + chipr_n_val = GICD_CHIPR_VALUE_GIC_600(chip_addr, + spi_block_min, + spi_blocks); + break; + case IIDR_MODEL_ARM_GIC_700: + chipr_n_val = GICD_CHIPR_VALUE_GIC_700(chip_addr, + spi_block_min, + spi_blocks); + break; + default: + ERROR("Unsupported GIC model 0x%x for multichip setup.\n", + gicd_iidr_val); + panic(); + break; + } + chipr_n_val |= GICD_CHIPRx_SOCKET_STATE; /* * Wait for DCHIPR.PUP to be zero before commencing writes to diff --git a/drivers/arm/gic/v3/gic600_multichip_private.h b/drivers/arm/gic/v3/gic600_multichip_private.h index 27b8e817f..5d1ff6a19 100644 --- a/drivers/arm/gic/v3/gic600_multichip_private.h +++ b/drivers/arm/gic/v3/gic600_multichip_private.h @@ -27,17 +27,11 @@ #define GICD_CHIPSR_RTS_SHIFT 4 #define GICD_DCHIPR_RT_OWNER_SHIFT 4 -/* - * If GIC v4 extension is enabled, then use SPI macros specific to GIC-700. - * Other shifts and mask remains same between GIC-600 and GIC-700. - */ -#if GIC_ENABLE_V4_EXTN -#define GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT 9 -#define GICD_CHIPRx_SPI_BLOCKS_SHIFT 3 -#else -#define GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT 10 -#define GICD_CHIPRx_SPI_BLOCKS_SHIFT 5 -#endif +/* Other shifts and masks remain the same between GIC-600 and GIC-700. */ +#define GIC_700_SPI_BLOCK_MIN_SHIFT 9 +#define GIC_700_SPI_BLOCKS_SHIFT 3 +#define GIC_600_SPI_BLOCK_MIN_SHIFT 10 +#define GIC_600_SPI_BLOCKS_SHIFT 5 #define GICD_CHIPSR_RTS_STATE_DISCONNECTED U(0) #define GICD_CHIPSR_RTS_STATE_UPDATING U(1) @@ -59,10 +53,14 @@ #define SPI_BLOCKS_VALUE(spi_id_min, spi_id_max) \ (((spi_id_max) - (spi_id_min) + 1) / \ GIC600_SPI_ID_MIN) -#define GICD_CHIPR_VALUE(chip_addr, spi_block_min, spi_blocks) \ +#define GICD_CHIPR_VALUE_GIC_700(chip_addr, spi_block_min, spi_blocks) \ (((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \ - ((spi_block_min) << GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT) | \ - ((spi_blocks) << GICD_CHIPRx_SPI_BLOCKS_SHIFT)) + ((spi_block_min) << GIC_700_SPI_BLOCK_MIN_SHIFT) | \ + ((spi_blocks) << GIC_700_SPI_BLOCKS_SHIFT)) +#define GICD_CHIPR_VALUE_GIC_600(chip_addr, spi_block_min, spi_blocks) \ + (((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \ + ((spi_block_min) << GIC_600_SPI_BLOCK_MIN_SHIFT) | \ + ((spi_blocks) << GIC_600_SPI_BLOCKS_SHIFT)) /* * Multichip data assertion macros From 858f40e379684fefc8b52c7b9e60576bc3794a69 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 18 May 2021 15:51:06 +0100 Subject: [PATCH 4/5] feat(gicv3): detect GICv4 feature at runtime At the moment we have a GIC_ENABLE_V4_EXTN build time variable to determine whether the GIC interrupt controller is compliant to version 4.0 of the spec or not. This just changes the number of 64K MMIO pages we expect per redistributor. To support firmware builds which run on variable systems (emulators, fast model or FPGAs), let's make this decision at runtime. The GIC specification provides several architected flags to learn the size of the MMIO frame per redistributor, we use GICR_TYPER[VLPI] here. Provide a (static inline) function to return the size of each redistributor. We keep the GIC_ENABLE_V4_EXTN build time variable around, but change its meaning to enable this autodetection code. Systems not defining this rely on a "pure" GICv3 (as before), but platforms setting it to "1" can now deal with both configurations. Change-Id: I9ede4acf058846157a0a9e2ef6103bf07c7655d9 Signed-off-by: Andre Przywara --- drivers/arm/gic/v3/gicv3_helpers.c | 11 ++++++----- drivers/arm/gic/v3/gicv3_main.c | 10 ++-------- include/drivers/arm/gicv3.h | 22 +++++++++++++++++----- plat/arm/board/arm_fpga/fpga_bl31_setup.c | 2 +- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/arm/gic/v3/gicv3_helpers.c index a0f44e966..d752013e2 100644 --- a/drivers/arm/gic/v3/gicv3_helpers.c +++ b/drivers/arm/gic/v3/gicv3_helpers.c @@ -86,8 +86,7 @@ void gicv3_rdistif_base_addrs_probe(uintptr_t *rdistif_base_addrs, if (proc_num < rdistif_num) { rdistif_base_addrs[proc_num] = rdistif_base; } - - rdistif_base += (1U << GICR_PCPUBASE_SHIFT); + rdistif_base += gicv3_redist_size(typer_val); } while ((typer_val & TYPER_LAST_BIT) == 0U); } @@ -383,11 +382,13 @@ unsigned int gicv3_rdistif_get_number_frames(const uintptr_t gicr_frame) uintptr_t rdistif_base = gicr_frame; unsigned int count; - for (count = 1; count < PLATFORM_CORE_COUNT; count++) { - if ((gicr_read_typer(rdistif_base) & TYPER_LAST_BIT) != 0U) { + for (count = 1U; count < PLATFORM_CORE_COUNT; count++) { + uint64_t typer_val = gicr_read_typer(rdistif_base); + + if ((typer_val & TYPER_LAST_BIT) != 0U) { break; } - rdistif_base += (1U << GICR_PCPUBASE_SHIFT); + rdistif_base += gicv3_redist_size(typer_val); } return count; diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c index b1139b5e9..53a8fae3b 100644 --- a/drivers/arm/gic/v3/gicv3_main.c +++ b/drivers/arm/gic/v3/gicv3_main.c @@ -123,13 +123,7 @@ void __init gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data) gic_version &= PIDR2_ARCH_REV_MASK; /* Check GIC version */ -#if GIC_ENABLE_V4_EXTN - assert(gic_version == ARCH_REV_GICV4); - - /* GICv4 supports Direct Virtual LPI injection */ - assert((gicd_read_typer(plat_driver_data->gicd_base) - & TYPER_DVIS) != 0); -#else +#if !GIC_ENABLE_V4_EXTN assert(gic_version == ARCH_REV_GICV3); #endif /* @@ -1298,7 +1292,7 @@ int gicv3_rdistif_probe(const uintptr_t gicr_frame) gicr_frame_found = true; break; } - rdistif_base += (uintptr_t)(ULL(1) << GICR_PCPUBASE_SHIFT); + rdistif_base += gicv3_redist_size(typer_val); } while ((typer_val & TYPER_LAST_BIT) == 0U); if (!gicr_frame_found) { diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h index d8ac4cb33..fa8946b16 100644 --- a/include/drivers/arm/gicv3.h +++ b/include/drivers/arm/gicv3.h @@ -153,11 +153,8 @@ /******************************************************************************* * Common GIC Redistributor interface registers & constants ******************************************************************************/ -#if GIC_ENABLE_V4_EXTN -#define GICR_PCPUBASE_SHIFT 0x12 -#else -#define GICR_PCPUBASE_SHIFT 0x11 -#endif +#define GICR_V4_PCPUBASE_SHIFT 0x12 +#define GICR_V3_PCPUBASE_SHIFT 0x11 #define GICR_SGIBASE_OFFSET U(65536) /* 64 KB */ #define GICR_CTLR U(0x0) #define GICR_IIDR U(0x04) @@ -212,12 +209,14 @@ #define TYPER_AFF_VAL_SHIFT 32 #define TYPER_PROC_NUM_SHIFT 8 #define TYPER_LAST_SHIFT 4 +#define TYPER_VLPI_SHIFT 1 #define TYPER_AFF_VAL_MASK U(0xffffffff) #define TYPER_PROC_NUM_MASK U(0xffff) #define TYPER_LAST_MASK U(0x1) #define TYPER_LAST_BIT BIT_32(TYPER_LAST_SHIFT) +#define TYPER_VLPI_BIT BIT_32(TYPER_VLPI_SHIFT) #define TYPER_PPI_NUM_SHIFT U(27) #define TYPER_PPI_NUM_MASK U(0x1f) @@ -312,6 +311,19 @@ #include #include +static inline uintptr_t gicv3_redist_size(uint64_t typer_val) +{ +#if GIC_ENABLE_V4_EXTN + if ((typer_val & TYPER_VLPI_BIT) != 0U) { + return 1U << GICR_V4_PCPUBASE_SHIFT; + } else { + return 1U << GICR_V3_PCPUBASE_SHIFT; + } +#else + return 1U << GICR_V3_PCPUBASE_SHIFT; +#endif +} + static inline bool gicv3_is_intr_id_special_identifier(unsigned int id) { return (id >= PENDING_G1S_INTID) && (id <= GIC_SPURIOUS_INTERRUPT); diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c index a5f5ea0f3..1c015d51e 100644 --- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c +++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c @@ -218,7 +218,7 @@ static void fpga_prepare_dtb(void) INFO("Adjusting GICR DT region to cover %u cores\n", nr_cores); err = fdt_adjust_gic_redist(fdt, nr_cores, - 1U << GICR_PCPUBASE_SHIFT); + 1U << GICR_V3_PCPUBASE_SHIFT); if (err < 0) { ERROR("Error %d fixing up GIC DT node\n", err); } From c69f815b09ab85d3ace8fd2979ffafb1184ec76c Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 18 May 2021 15:53:05 +0100 Subject: [PATCH 5/5] feat(arm_fpga): support GICv4 images Up until now we relied on the GICs used in our FPGA images to be GICv3 compliant, without the "direct virtual injection" feature (aka GICv4) enabled. To support newer images which have GICv4 compliant GICs, enable the newly introduced GICv4 detection code, and use that also when we adjust the redistributor region size in the devicetree. This allows the same BL31 image to be used with GICv3 or GICv4 FPGA images. Change-Id: I9f6435a6d5150983625efe3650a8b7d1ef11b1d1 Signed-off-by: Andre Przywara --- plat/arm/board/arm_fpga/fpga_bl31_setup.c | 2 +- plat/arm/board/arm_fpga/fpga_gicv3.c | 9 +++++++++ plat/arm/board/arm_fpga/fpga_private.h | 1 + plat/arm/board/arm_fpga/platform.mk | 2 ++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c index 1c015d51e..81d040cba 100644 --- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c +++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c @@ -218,7 +218,7 @@ static void fpga_prepare_dtb(void) INFO("Adjusting GICR DT region to cover %u cores\n", nr_cores); err = fdt_adjust_gic_redist(fdt, nr_cores, - 1U << GICR_V3_PCPUBASE_SHIFT); + fpga_get_redist_size()); if (err < 0) { ERROR("Error %d fixing up GIC DT node\n", err); } diff --git a/plat/arm/board/arm_fpga/fpga_gicv3.c b/plat/arm/board/arm_fpga/fpga_gicv3.c index bfc116bef..4a97beb96 100644 --- a/plat/arm/board/arm_fpga/fpga_gicv3.c +++ b/plat/arm/board/arm_fpga/fpga_gicv3.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -82,3 +83,11 @@ unsigned int fpga_get_nr_gic_cores(void) { return gicv3_rdistif_get_number_frames(fpga_gicv3_driver_data.gicr_base); } + +uintptr_t fpga_get_redist_size(void) +{ + uint64_t typer_val = mmio_read_64(fpga_gicv3_driver_data.gicr_base + + GICR_TYPER); + + return gicv3_redist_size(typer_val); +} diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h index 1ca241f26..cc809c4e4 100644 --- a/plat/arm/board/arm_fpga/fpga_private.h +++ b/plat/arm/board/arm_fpga/fpga_private.h @@ -25,6 +25,7 @@ void fpga_pwr_gic_on_finish(void); void fpga_pwr_gic_off(void); unsigned int plat_fpga_calc_core_pos(uint32_t mpid); unsigned int fpga_get_nr_gic_cores(void); +uintptr_t fpga_get_redist_size(void); #endif /* __ASSEMBLER__ */ diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk index f80ea2fef..baffbcf62 100644 --- a/plat/arm/board/arm_fpga/platform.mk +++ b/plat/arm/board/arm_fpga/platform.mk @@ -89,6 +89,8 @@ endif # Allow detection of GIC-600 GICV3_SUPPORT_GIC600 := 1 +GIC_ENABLE_V4_EXTN := 1 + # Include GICv3 driver files include drivers/arm/gic/v3/gicv3.mk