1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <platform_def.h> 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <common/debug.h> 11*91f16700Schasinglulu #include <common/interrupt_props.h> 12*91f16700Schasinglulu #include <drivers/arm/gicv3.h> 13*91f16700Schasinglulu #include <fconf_hw_config_getter.h> 14*91f16700Schasinglulu #include <lib/utils.h> 15*91f16700Schasinglulu #include <plat/arm/common/plat_arm.h> 16*91f16700Schasinglulu #include <plat/arm/common/fconf_sec_intr_config.h> 17*91f16700Schasinglulu #include <plat/common/platform.h> 18*91f16700Schasinglulu 19*91f16700Schasinglulu #if FVP_GICR_REGION_PROTECTION 20*91f16700Schasinglulu /* To indicate GICR region of the core initialized as Read-Write */ 21*91f16700Schasinglulu static bool fvp_gicr_rw_region_init[PLATFORM_CORE_COUNT] = {false}; 22*91f16700Schasinglulu #endif /* FVP_GICR_REGION_PROTECTION */ 23*91f16700Schasinglulu 24*91f16700Schasinglulu /* The GICv3 driver only needs to be initialized in EL3 */ 25*91f16700Schasinglulu static uintptr_t fvp_rdistif_base_addrs[PLATFORM_CORE_COUNT]; 26*91f16700Schasinglulu 27*91f16700Schasinglulu /* Default GICR base address to be used for GICR probe. */ 28*91f16700Schasinglulu static uint64_t fvp_gicr_base_addrs[2] = { 0U }; 29*91f16700Schasinglulu 30*91f16700Schasinglulu /* List of zero terminated GICR frame addresses which CPUs will probe */ 31*91f16700Schasinglulu static uint64_t *fvp_gicr_frames = fvp_gicr_base_addrs; 32*91f16700Schasinglulu 33*91f16700Schasinglulu #if !(SEC_INT_DESC_IN_FCONF && ((!defined(__aarch64__) && defined(IMAGE_BL32)) || \ 34*91f16700Schasinglulu (defined(__aarch64__) && defined(IMAGE_BL31)))) 35*91f16700Schasinglulu static const interrupt_prop_t fvp_interrupt_props[] = { 36*91f16700Schasinglulu PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S), 37*91f16700Schasinglulu PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0) 38*91f16700Schasinglulu }; 39*91f16700Schasinglulu #endif 40*91f16700Schasinglulu 41*91f16700Schasinglulu /* 42*91f16700Schasinglulu * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register 43*91f16700Schasinglulu * to core position. 44*91f16700Schasinglulu * 45*91f16700Schasinglulu * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity 46*91f16700Schasinglulu * values read from GICR_TYPER don't have an MT field. To reuse the same 47*91f16700Schasinglulu * translation used for CPUs, we insert MT bit read from the PE's MPIDR into 48*91f16700Schasinglulu * that read from GICR_TYPER. 49*91f16700Schasinglulu * 50*91f16700Schasinglulu * Assumptions: 51*91f16700Schasinglulu * 52*91f16700Schasinglulu * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; 53*91f16700Schasinglulu * - No CPUs implemented in the system use affinity level 3. 54*91f16700Schasinglulu */ 55*91f16700Schasinglulu static unsigned int fvp_gicv3_mpidr_hash(u_register_t mpidr) 56*91f16700Schasinglulu { 57*91f16700Schasinglulu u_register_t temp_mpidr = mpidr; 58*91f16700Schasinglulu 59*91f16700Schasinglulu temp_mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); 60*91f16700Schasinglulu return plat_arm_calc_core_pos(temp_mpidr); 61*91f16700Schasinglulu } 62*91f16700Schasinglulu 63*91f16700Schasinglulu 64*91f16700Schasinglulu static gicv3_driver_data_t fvp_gic_data = { 65*91f16700Schasinglulu .rdistif_num = PLATFORM_CORE_COUNT, 66*91f16700Schasinglulu .rdistif_base_addrs = fvp_rdistif_base_addrs, 67*91f16700Schasinglulu .mpidr_to_core_pos = fvp_gicv3_mpidr_hash 68*91f16700Schasinglulu }; 69*91f16700Schasinglulu 70*91f16700Schasinglulu /****************************************************************************** 71*91f16700Schasinglulu * This function gets called per core to make its redistributor frame rw 72*91f16700Schasinglulu *****************************************************************************/ 73*91f16700Schasinglulu static void fvp_gicv3_make_rdistrif_rw(void) 74*91f16700Schasinglulu { 75*91f16700Schasinglulu #if FVP_GICR_REGION_PROTECTION 76*91f16700Schasinglulu unsigned int core_pos = plat_my_core_pos(); 77*91f16700Schasinglulu 78*91f16700Schasinglulu /* Make the redistributor frame RW if it is not done previously */ 79*91f16700Schasinglulu if (fvp_gicr_rw_region_init[core_pos] != true) { 80*91f16700Schasinglulu int ret = xlat_change_mem_attributes(BASE_GICR_BASE + 81*91f16700Schasinglulu (core_pos * BASE_GICR_SIZE), 82*91f16700Schasinglulu BASE_GICR_SIZE, 83*91f16700Schasinglulu MT_EXECUTE_NEVER | 84*91f16700Schasinglulu MT_DEVICE | MT_RW | 85*91f16700Schasinglulu MT_SECURE); 86*91f16700Schasinglulu 87*91f16700Schasinglulu if (ret != 0) { 88*91f16700Schasinglulu ERROR("Failed to make redistributor frame \ 89*91f16700Schasinglulu read write = %d\n", ret); 90*91f16700Schasinglulu panic(); 91*91f16700Schasinglulu } else { 92*91f16700Schasinglulu fvp_gicr_rw_region_init[core_pos] = true; 93*91f16700Schasinglulu } 94*91f16700Schasinglulu } 95*91f16700Schasinglulu #else 96*91f16700Schasinglulu return; 97*91f16700Schasinglulu #endif /* FVP_GICR_REGION_PROTECTION */ 98*91f16700Schasinglulu } 99*91f16700Schasinglulu 100*91f16700Schasinglulu void plat_arm_gic_driver_init(void) 101*91f16700Schasinglulu { 102*91f16700Schasinglulu fvp_gicv3_make_rdistrif_rw(); 103*91f16700Schasinglulu /* 104*91f16700Schasinglulu * Get GICD and GICR base addressed through FCONF APIs. 105*91f16700Schasinglulu * FCONF is not supported in BL32 for FVP. 106*91f16700Schasinglulu */ 107*91f16700Schasinglulu #if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ 108*91f16700Schasinglulu (defined(__aarch64__) && defined(IMAGE_BL31)) 109*91f16700Schasinglulu fvp_gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config, 110*91f16700Schasinglulu gicv3_config, 111*91f16700Schasinglulu gicd_base); 112*91f16700Schasinglulu fvp_gicr_base_addrs[0] = FCONF_GET_PROPERTY(hw_config, gicv3_config, 113*91f16700Schasinglulu gicr_base); 114*91f16700Schasinglulu #if SEC_INT_DESC_IN_FCONF 115*91f16700Schasinglulu fvp_gic_data.interrupt_props = FCONF_GET_PROPERTY(hw_config, 116*91f16700Schasinglulu sec_intr_prop, descriptor); 117*91f16700Schasinglulu fvp_gic_data.interrupt_props_num = FCONF_GET_PROPERTY(hw_config, 118*91f16700Schasinglulu sec_intr_prop, count); 119*91f16700Schasinglulu #else 120*91f16700Schasinglulu fvp_gic_data.interrupt_props = fvp_interrupt_props; 121*91f16700Schasinglulu fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props); 122*91f16700Schasinglulu #endif 123*91f16700Schasinglulu #else 124*91f16700Schasinglulu fvp_gic_data.gicd_base = PLAT_ARM_GICD_BASE; 125*91f16700Schasinglulu fvp_gicr_base_addrs[0] = PLAT_ARM_GICR_BASE; 126*91f16700Schasinglulu fvp_gic_data.interrupt_props = fvp_interrupt_props; 127*91f16700Schasinglulu fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props); 128*91f16700Schasinglulu #endif 129*91f16700Schasinglulu 130*91f16700Schasinglulu /* 131*91f16700Schasinglulu * The GICv3 driver is initialized in EL3 and does not need 132*91f16700Schasinglulu * to be initialized again in SEL1. This is because the S-EL1 133*91f16700Schasinglulu * can use GIC system registers to manage interrupts and does 134*91f16700Schasinglulu * not need GIC interface base addresses to be configured. 135*91f16700Schasinglulu */ 136*91f16700Schasinglulu 137*91f16700Schasinglulu #if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ 138*91f16700Schasinglulu (defined(__aarch64__) && defined(IMAGE_BL31)) 139*91f16700Schasinglulu gicv3_driver_init(&fvp_gic_data); 140*91f16700Schasinglulu if (gicv3_rdistif_probe((uintptr_t)fvp_gicr_base_addrs[0]) == -1) { 141*91f16700Schasinglulu ERROR("No GICR base frame found for Primary CPU\n"); 142*91f16700Schasinglulu panic(); 143*91f16700Schasinglulu } 144*91f16700Schasinglulu #endif 145*91f16700Schasinglulu } 146*91f16700Schasinglulu 147*91f16700Schasinglulu /****************************************************************************** 148*91f16700Schasinglulu * Function to iterate over all GICR frames and discover the corresponding 149*91f16700Schasinglulu * per-cpu redistributor frame as well as initialize the corresponding 150*91f16700Schasinglulu * interface in GICv3. 151*91f16700Schasinglulu *****************************************************************************/ 152*91f16700Schasinglulu void plat_arm_gic_pcpu_init(void) 153*91f16700Schasinglulu { 154*91f16700Schasinglulu int result; 155*91f16700Schasinglulu const uint64_t *plat_gicr_frames = fvp_gicr_frames; 156*91f16700Schasinglulu 157*91f16700Schasinglulu fvp_gicv3_make_rdistrif_rw(); 158*91f16700Schasinglulu 159*91f16700Schasinglulu do { 160*91f16700Schasinglulu result = gicv3_rdistif_probe(*plat_gicr_frames); 161*91f16700Schasinglulu 162*91f16700Schasinglulu /* If the probe is successful, no need to proceed further */ 163*91f16700Schasinglulu if (result == 0) 164*91f16700Schasinglulu break; 165*91f16700Schasinglulu 166*91f16700Schasinglulu plat_gicr_frames++; 167*91f16700Schasinglulu } while (*plat_gicr_frames != 0U); 168*91f16700Schasinglulu 169*91f16700Schasinglulu if (result == -1) { 170*91f16700Schasinglulu ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr()); 171*91f16700Schasinglulu panic(); 172*91f16700Schasinglulu } 173*91f16700Schasinglulu gicv3_rdistif_init(plat_my_core_pos()); 174*91f16700Schasinglulu } 175