From 283e5595afa28a5930ac5f0dcdf7c18804221070 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 24 Aug 2020 18:34:50 +0100 Subject: [PATCH] arm_fpga: Adjust GICR size in DT to match number of cores The size of a GICv3 redistributor region depends on the number of cores in the system. For the ARM FPGA port, we detect the topology at runtime, and adjust the CPU DT nodes accordingly. Now the size of the GICR region must also be adjusted, or Linux will fail to initialise the GICv3. Use the newly introduced function to overwrite the GICR size entry in the GICv3 reg property. We count the number of existing cores by iterating over the GICR frames until we find the LAST bit set in TYPER. Change-Id: Ib69565600859de9b1b15ceb8495172cd26d16fce Signed-off-by: Andre Przywara --- plat/arm/board/arm_fpga/fpga_bl31_setup.c | 11 +++++++++++ plat/arm/board/arm_fpga/fpga_gicv3.c | 5 +++++ plat/arm/board/arm_fpga/fpga_private.h | 1 + 3 files changed, 17 insertions(+) diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c index de6d9d5e3..d5478d2d6 100644 --- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c +++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -210,6 +211,16 @@ static void fpga_prepare_dtb(void) if (err < 0) { ERROR("Error %d creating the /cpus DT node\n", err); panic(); + } else { + unsigned int nr_cores = fpga_get_nr_gic_cores(); + + INFO("Adjusting GICR DT region to cover %u cores\n", + nr_cores); + err = fdt_adjust_gic_redist(fdt, nr_cores, + 1U << GICR_PCPUBASE_SHIFT); + 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 9fb5fa935..bfc116bef 100644 --- a/plat/arm/board/arm_fpga/fpga_gicv3.c +++ b/plat/arm/board/arm_fpga/fpga_gicv3.c @@ -77,3 +77,8 @@ void fpga_pwr_gic_off(void) gicv3_cpuif_disable(plat_my_core_pos()); gicv3_rdistif_off(plat_my_core_pos()); } + +unsigned int fpga_get_nr_gic_cores(void) +{ + return gicv3_rdistif_get_number_frames(fpga_gicv3_driver_data.gicr_base); +} diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h index 47059d64a..1ca241f26 100644 --- a/plat/arm/board/arm_fpga/fpga_private.h +++ b/plat/arm/board/arm_fpga/fpga_private.h @@ -24,6 +24,7 @@ void plat_fpga_gic_init(void); 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); #endif /* __ASSEMBLER__ */