Browse Source
Query the GICD and GICR base addresses in runtime using fconf getter APIs. Signed-off-by: Lauren Wehrmeister <lauren.wehrmeister@arm.com> Change-Id: I309fb2874f3329ddeb8677ddb53ed4c02199a1e9pull/1979/head
laurenw-arm
5 years ago
3 changed files with 125 additions and 2 deletions
@ -0,0 +1,119 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <assert.h> |
|||
#include <platform_def.h> |
|||
|
|||
#include <common/interrupt_props.h> |
|||
#include <drivers/arm/gicv3.h> |
|||
#include <fconf_hw_config_getter.h> |
|||
#include <lib/utils.h> |
|||
#include <plat/arm/common/plat_arm.h> |
|||
#include <plat/common/platform.h> |
|||
|
|||
/* The GICv3 driver only needs to be initialized in EL3 */ |
|||
static uintptr_t fvp_rdistif_base_addrs[PLATFORM_CORE_COUNT]; |
|||
|
|||
/* Default GICR base address to be used for GICR probe. */ |
|||
static uint64_t fvp_gicr_base_addrs[2] = { 0U }; |
|||
|
|||
/* List of zero terminated GICR frame addresses which CPUs will probe */ |
|||
static uint64_t *fvp_gicr_frames = fvp_gicr_base_addrs; |
|||
|
|||
static const interrupt_prop_t fvp_interrupt_props[] = { |
|||
PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S), |
|||
PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0) |
|||
}; |
|||
|
|||
/*
|
|||
* MPIDR hashing function for translating MPIDRs read from GICR_TYPER register |
|||
* to core position. |
|||
* |
|||
* Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity |
|||
* values read from GICR_TYPER don't have an MT field. To reuse the same |
|||
* translation used for CPUs, we insert MT bit read from the PE's MPIDR into |
|||
* that read from GICR_TYPER. |
|||
* |
|||
* Assumptions: |
|||
* |
|||
* - All CPUs implemented in the system have MPIDR_EL1.MT bit set; |
|||
* - No CPUs implemented in the system use affinity level 3. |
|||
*/ |
|||
static unsigned int fvp_gicv3_mpidr_hash(u_register_t mpidr) |
|||
{ |
|||
u_register_t temp_mpidr = mpidr; |
|||
|
|||
temp_mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); |
|||
return plat_arm_calc_core_pos(temp_mpidr); |
|||
} |
|||
|
|||
|
|||
static gicv3_driver_data_t fvp_gic_data = { |
|||
.interrupt_props = fvp_interrupt_props, |
|||
.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props), |
|||
.rdistif_num = PLATFORM_CORE_COUNT, |
|||
.rdistif_base_addrs = fvp_rdistif_base_addrs, |
|||
.mpidr_to_core_pos = fvp_gicv3_mpidr_hash |
|||
}; |
|||
|
|||
void plat_arm_gic_driver_init(void) |
|||
{ |
|||
/* Get GICD and GICR base addressed through FCONF APIs */ |
|||
#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ |
|||
(defined(__aarch64__) && defined(IMAGE_BL31)) |
|||
fvp_gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config, |
|||
gicv3_config, |
|||
gicd_base); |
|||
fvp_gicr_base_addrs[0] = FCONF_GET_PROPERTY(hw_config, gicv3_config, |
|||
gicr_base); |
|||
#else |
|||
fvp_gic_data.gicd_base = PLAT_ARM_GICD_BASE; |
|||
fvp_gicr_base_addrs[0] = PLAT_ARM_GICR_BASE; |
|||
#endif |
|||
|
|||
/*
|
|||
* The GICv3 driver is initialized in EL3 and does not need |
|||
* to be initialized again in SEL1. This is because the S-EL1 |
|||
* can use GIC system registers to manage interrupts and does |
|||
* not need GIC interface base addresses to be configured. |
|||
*/ |
|||
|
|||
#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ |
|||
(defined(__aarch64__) && defined(IMAGE_BL31)) |
|||
gicv3_driver_init(&fvp_gic_data); |
|||
if (gicv3_rdistif_probe((uintptr_t)fvp_gicr_base_addrs[0]) == -1) { |
|||
ERROR("No GICR base frame found for Primary CPU\n"); |
|||
panic(); |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
/******************************************************************************
|
|||
* Function to iterate over all GICR frames and discover the corresponding |
|||
* per-cpu redistributor frame as well as initialize the corresponding |
|||
* interface in GICv3. |
|||
*****************************************************************************/ |
|||
void plat_arm_gic_pcpu_init(void) |
|||
{ |
|||
int result; |
|||
const uint64_t *plat_gicr_frames = fvp_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); |
|||
|
|||
if (result == -1) { |
|||
ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr()); |
|||
panic(); |
|||
} |
|||
gicv3_rdistif_init(plat_my_core_pos()); |
|||
} |
Loading…
Reference in new issue