1*8370c8ceSlaurenw-arm /* 2*8370c8ceSlaurenw-arm * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. 3*8370c8ceSlaurenw-arm * 4*8370c8ceSlaurenw-arm * SPDX-License-Identifier: BSD-3-Clause 5*8370c8ceSlaurenw-arm */ 6*8370c8ceSlaurenw-arm 7*8370c8ceSlaurenw-arm #include <assert.h> 8*8370c8ceSlaurenw-arm #include <platform_def.h> 9*8370c8ceSlaurenw-arm 10*8370c8ceSlaurenw-arm #include <common/interrupt_props.h> 11*8370c8ceSlaurenw-arm #include <drivers/arm/gicv3.h> 12*8370c8ceSlaurenw-arm #include <fconf_hw_config_getter.h> 13*8370c8ceSlaurenw-arm #include <lib/utils.h> 14*8370c8ceSlaurenw-arm #include <plat/arm/common/plat_arm.h> 15*8370c8ceSlaurenw-arm #include <plat/common/platform.h> 16*8370c8ceSlaurenw-arm 17*8370c8ceSlaurenw-arm /* The GICv3 driver only needs to be initialized in EL3 */ 18*8370c8ceSlaurenw-arm static uintptr_t fvp_rdistif_base_addrs[PLATFORM_CORE_COUNT]; 19*8370c8ceSlaurenw-arm 20*8370c8ceSlaurenw-arm /* Default GICR base address to be used for GICR probe. */ 21*8370c8ceSlaurenw-arm static uint64_t fvp_gicr_base_addrs[2] = { 0U }; 22*8370c8ceSlaurenw-arm 23*8370c8ceSlaurenw-arm /* List of zero terminated GICR frame addresses which CPUs will probe */ 24*8370c8ceSlaurenw-arm static uint64_t *fvp_gicr_frames = fvp_gicr_base_addrs; 25*8370c8ceSlaurenw-arm 26*8370c8ceSlaurenw-arm static const interrupt_prop_t fvp_interrupt_props[] = { 27*8370c8ceSlaurenw-arm PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S), 28*8370c8ceSlaurenw-arm PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0) 29*8370c8ceSlaurenw-arm }; 30*8370c8ceSlaurenw-arm 31*8370c8ceSlaurenw-arm /* 32*8370c8ceSlaurenw-arm * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register 33*8370c8ceSlaurenw-arm * to core position. 34*8370c8ceSlaurenw-arm * 35*8370c8ceSlaurenw-arm * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity 36*8370c8ceSlaurenw-arm * values read from GICR_TYPER don't have an MT field. To reuse the same 37*8370c8ceSlaurenw-arm * translation used for CPUs, we insert MT bit read from the PE's MPIDR into 38*8370c8ceSlaurenw-arm * that read from GICR_TYPER. 39*8370c8ceSlaurenw-arm * 40*8370c8ceSlaurenw-arm * Assumptions: 41*8370c8ceSlaurenw-arm * 42*8370c8ceSlaurenw-arm * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; 43*8370c8ceSlaurenw-arm * - No CPUs implemented in the system use affinity level 3. 44*8370c8ceSlaurenw-arm */ 45*8370c8ceSlaurenw-arm static unsigned int fvp_gicv3_mpidr_hash(u_register_t mpidr) 46*8370c8ceSlaurenw-arm { 47*8370c8ceSlaurenw-arm u_register_t temp_mpidr = mpidr; 48*8370c8ceSlaurenw-arm 49*8370c8ceSlaurenw-arm temp_mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); 50*8370c8ceSlaurenw-arm return plat_arm_calc_core_pos(temp_mpidr); 51*8370c8ceSlaurenw-arm } 52*8370c8ceSlaurenw-arm 53*8370c8ceSlaurenw-arm 54*8370c8ceSlaurenw-arm static gicv3_driver_data_t fvp_gic_data = { 55*8370c8ceSlaurenw-arm .interrupt_props = fvp_interrupt_props, 56*8370c8ceSlaurenw-arm .interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props), 57*8370c8ceSlaurenw-arm .rdistif_num = PLATFORM_CORE_COUNT, 58*8370c8ceSlaurenw-arm .rdistif_base_addrs = fvp_rdistif_base_addrs, 59*8370c8ceSlaurenw-arm .mpidr_to_core_pos = fvp_gicv3_mpidr_hash 60*8370c8ceSlaurenw-arm }; 61*8370c8ceSlaurenw-arm 62*8370c8ceSlaurenw-arm void plat_arm_gic_driver_init(void) 63*8370c8ceSlaurenw-arm { 64*8370c8ceSlaurenw-arm /* Get GICD and GICR base addressed through FCONF APIs */ 65*8370c8ceSlaurenw-arm #if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ 66*8370c8ceSlaurenw-arm (defined(__aarch64__) && defined(IMAGE_BL31)) 67*8370c8ceSlaurenw-arm fvp_gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config, 68*8370c8ceSlaurenw-arm gicv3_config, 69*8370c8ceSlaurenw-arm gicd_base); 70*8370c8ceSlaurenw-arm fvp_gicr_base_addrs[0] = FCONF_GET_PROPERTY(hw_config, gicv3_config, 71*8370c8ceSlaurenw-arm gicr_base); 72*8370c8ceSlaurenw-arm #else 73*8370c8ceSlaurenw-arm fvp_gic_data.gicd_base = PLAT_ARM_GICD_BASE; 74*8370c8ceSlaurenw-arm fvp_gicr_base_addrs[0] = PLAT_ARM_GICR_BASE; 75*8370c8ceSlaurenw-arm #endif 76*8370c8ceSlaurenw-arm 77*8370c8ceSlaurenw-arm /* 78*8370c8ceSlaurenw-arm * The GICv3 driver is initialized in EL3 and does not need 79*8370c8ceSlaurenw-arm * to be initialized again in SEL1. This is because the S-EL1 80*8370c8ceSlaurenw-arm * can use GIC system registers to manage interrupts and does 81*8370c8ceSlaurenw-arm * not need GIC interface base addresses to be configured. 82*8370c8ceSlaurenw-arm */ 83*8370c8ceSlaurenw-arm 84*8370c8ceSlaurenw-arm #if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ 85*8370c8ceSlaurenw-arm (defined(__aarch64__) && defined(IMAGE_BL31)) 86*8370c8ceSlaurenw-arm gicv3_driver_init(&fvp_gic_data); 87*8370c8ceSlaurenw-arm if (gicv3_rdistif_probe((uintptr_t)fvp_gicr_base_addrs[0]) == -1) { 88*8370c8ceSlaurenw-arm ERROR("No GICR base frame found for Primary CPU\n"); 89*8370c8ceSlaurenw-arm panic(); 90*8370c8ceSlaurenw-arm } 91*8370c8ceSlaurenw-arm #endif 92*8370c8ceSlaurenw-arm } 93*8370c8ceSlaurenw-arm 94*8370c8ceSlaurenw-arm /****************************************************************************** 95*8370c8ceSlaurenw-arm * Function to iterate over all GICR frames and discover the corresponding 96*8370c8ceSlaurenw-arm * per-cpu redistributor frame as well as initialize the corresponding 97*8370c8ceSlaurenw-arm * interface in GICv3. 98*8370c8ceSlaurenw-arm *****************************************************************************/ 99*8370c8ceSlaurenw-arm void plat_arm_gic_pcpu_init(void) 100*8370c8ceSlaurenw-arm { 101*8370c8ceSlaurenw-arm int result; 102*8370c8ceSlaurenw-arm const uint64_t *plat_gicr_frames = fvp_gicr_frames; 103*8370c8ceSlaurenw-arm 104*8370c8ceSlaurenw-arm do { 105*8370c8ceSlaurenw-arm result = gicv3_rdistif_probe(*plat_gicr_frames); 106*8370c8ceSlaurenw-arm 107*8370c8ceSlaurenw-arm /* If the probe is successful, no need to proceed further */ 108*8370c8ceSlaurenw-arm if (result == 0) 109*8370c8ceSlaurenw-arm break; 110*8370c8ceSlaurenw-arm 111*8370c8ceSlaurenw-arm plat_gicr_frames++; 112*8370c8ceSlaurenw-arm } while (*plat_gicr_frames != 0U); 113*8370c8ceSlaurenw-arm 114*8370c8ceSlaurenw-arm if (result == -1) { 115*8370c8ceSlaurenw-arm ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr()); 116*8370c8ceSlaurenw-arm panic(); 117*8370c8ceSlaurenw-arm } 118*8370c8ceSlaurenw-arm gicv3_rdistif_init(plat_my_core_pos()); 119*8370c8ceSlaurenw-arm } 120