drivers: arm: gicv3: Allow detecting number of cores

A GICv3 interrupt controller will be instantiated for a certain number
of cores. This will result in the respective number of GICR frames. The
last frame will have the "Last" bit set in its GICR_TYPER register.

For platforms with a topology unknown at build time (the Arm FPGAs, for
instance), we need to learn the number of used cores at runtime, to size
the GICR region in the devicetree accordingly.

Add a generic function that iterates over all GICR frames until it
encounters one with the "Last" bit set. It returns the number of cores
the GICv3 has been configured for.

Change-Id: I79f033c50dfc1c275aba7122725868811abcc4f8
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
This commit is contained in:
Andre Przywara 2020-09-07 14:53:58 +01:00
parent e89b813129
commit 79d89e3da0
2 changed files with 31 additions and 0 deletions

View File

@ -326,3 +326,33 @@ unsigned int gicv3_secure_ppi_sgi_config_props(uintptr_t gicr_base,
return ctlr_enable;
}
/**
* gicv3_rdistif_get_number_frames() - determine size of GICv3 GICR region
* @gicr_frame: base address of the GICR region to check
*
* This iterates over the GICR_TYPER registers of multiple GICR frames in
* a GICR region, to find the instance which has the LAST bit set. For most
* systems this corresponds to the number of cores handled by a redistributor,
* but there could be disabled cores among them.
* It assumes that each GICR region is fully accessible (till the LAST bit
* marks the end of the region).
* If a platform has multiple GICR regions, this function would need to be
* called multiple times, providing the respective GICR base address each time.
*
* Return: number of valid GICR frames (at least 1, up to PLATFORM_CORE_COUNT)
******************************************************************************/
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) {
break;
}
rdistif_base += (1U << GICR_PCPUBASE_SHIFT);
}
return count;
}

View File

@ -488,6 +488,7 @@ void gicv3_distif_init(void);
void gicv3_rdistif_init(unsigned int proc_num);
void gicv3_rdistif_on(unsigned int proc_num);
void gicv3_rdistif_off(unsigned int proc_num);
unsigned int gicv3_rdistif_get_number_frames(const uintptr_t gicr_frame);
void gicv3_cpuif_enable(unsigned int proc_num);
void gicv3_cpuif_disable(unsigned int proc_num);
unsigned int gicv3_get_pending_interrupt_type(void);