Commit 74c21244 authored by Vijayenthiran Subramaniam's avatar Vijayenthiran Subramaniam
Browse files

plat/arm/gicv3: add support for probing multiple GIC Redistributor frames



ARM platform can have a non-contiguous GICR frames. For instance, a
multi socket platform can have two or more GIC Redistributor frames
which are 4TB apart. Hence it is necessary for the `gicv3_rdistif_probe`
function to probe all the GICR frames available in the platform.

Introduce `plat_arm_override_gicr_frames` function which platforms can
use to override the default gicr_frames which holds the GICR base
address of the primary cpu.

Change-Id: I1f537b0d871a679cb256092944737f2e55ab866e
Signed-off-by: default avatarVijayenthiran Subramaniam <vijayenthiran.subramaniam@arm.com>
parent 1d2b4161
...@@ -254,6 +254,11 @@ void plat_arm_program_trusted_mailbox(uintptr_t address); ...@@ -254,6 +254,11 @@ void plat_arm_program_trusted_mailbox(uintptr_t address);
int plat_arm_bl1_fwu_needed(void); int plat_arm_bl1_fwu_needed(void);
__dead2 void plat_arm_error_handler(int err); __dead2 void plat_arm_error_handler(int err);
/*
* Optional function in ARM standard platforms
*/
void plat_arm_override_gicr_frames(const uintptr_t *plat_gicr_frames);
#if ARM_PLAT_MT #if ARM_PLAT_MT
unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr); unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr);
#endif #endif
......
...@@ -28,6 +28,15 @@ ...@@ -28,6 +28,15 @@
/* The GICv3 driver only needs to be initialized in EL3 */ /* The GICv3 driver only needs to be initialized in EL3 */
static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
/* Default GICR base address to be used for GICR probe. */
static const uintptr_t gicr_base_addrs[2] = {
PLAT_ARM_GICR_BASE, /* GICR Base address of the primary CPU */
0U /* Zero Termination */
};
/* List of zero terminated GICR frame addresses which CPUs will probe */
static const uintptr_t *gicr_frames = gicr_base_addrs;
static const interrupt_prop_t arm_interrupt_props[] = { static const interrupt_prop_t arm_interrupt_props[] = {
PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S), PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0) PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0)
...@@ -76,6 +85,18 @@ static const gicv3_driver_data_t arm_gic_data __unused = { ...@@ -76,6 +85,18 @@ static const gicv3_driver_data_t arm_gic_data __unused = {
.mpidr_to_core_pos = arm_gicv3_mpidr_hash .mpidr_to_core_pos = arm_gicv3_mpidr_hash
}; };
/*
* By default, gicr_frames will be pointing to gicr_base_addrs. If
* the platform supports a non-contiguous GICR frames (GICR frames located
* at uneven offset), plat_arm_override_gicr_frames function can be used by
* such platform to override the gicr_frames.
*/
void plat_arm_override_gicr_frames(const uintptr_t *plat_gicr_frames)
{
assert(plat_gicr_frames != NULL);
gicr_frames = plat_gicr_frames;
}
void __init plat_arm_gic_driver_init(void) void __init plat_arm_gic_driver_init(void)
{ {
/* /*
...@@ -88,7 +109,7 @@ void __init plat_arm_gic_driver_init(void) ...@@ -88,7 +109,7 @@ void __init plat_arm_gic_driver_init(void)
(defined(__aarch64__) && defined(IMAGE_BL31)) (defined(__aarch64__) && defined(IMAGE_BL31))
gicv3_driver_init(&arm_gic_data); gicv3_driver_init(&arm_gic_data);
if (gicv3_rdistif_probe(PLAT_ARM_GICR_BASE) == -1) { if (gicv3_rdistif_probe(gicr_base_addrs[0]) == -1) {
ERROR("No GICR base frame found for Primary CPU\n"); ERROR("No GICR base frame found for Primary CPU\n");
panic(); panic();
} }
...@@ -124,14 +145,23 @@ void plat_arm_gic_cpuif_disable(void) ...@@ -124,14 +145,23 @@ void plat_arm_gic_cpuif_disable(void)
/****************************************************************************** /******************************************************************************
* ARM common helper function to iterate over all GICR frames and discover the * ARM common helper function to iterate over all GICR frames and discover the
* corresponding per-cpu redistributor frame as well as initialize the * corresponding per-cpu redistributor frame as well as initialize the
* corresponding interface in GICv3. At the moment, Arm platforms do not have * corresponding interface in GICv3.
* non-contiguous GICR frames.
*****************************************************************************/ *****************************************************************************/
void plat_arm_gic_pcpu_init(void) void plat_arm_gic_pcpu_init(void)
{ {
int result; int result;
const uintptr_t *plat_gicr_frames = gicr_frames;
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);
result = gicv3_rdistif_probe(PLAT_ARM_GICR_BASE);
if (result == -1) { if (result == -1) {
ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr()); ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr());
panic(); panic();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment