18370c8ceSlaurenw-arm /* 28370c8ceSlaurenw-arm * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. 38370c8ceSlaurenw-arm * 48370c8ceSlaurenw-arm * SPDX-License-Identifier: BSD-3-Clause 58370c8ceSlaurenw-arm */ 68370c8ceSlaurenw-arm 78370c8ceSlaurenw-arm #include <assert.h> 88370c8ceSlaurenw-arm #include <platform_def.h> 98370c8ceSlaurenw-arm 108370c8ceSlaurenw-arm #include <common/interrupt_props.h> 118370c8ceSlaurenw-arm #include <drivers/arm/gicv3.h> 128370c8ceSlaurenw-arm #include <fconf_hw_config_getter.h> 138370c8ceSlaurenw-arm #include <lib/utils.h> 148370c8ceSlaurenw-arm #include <plat/arm/common/plat_arm.h> 15*452d5e5eSMadhukar Pappireddy #include <plat/arm/common/fconf_sec_intr_config.h> 168370c8ceSlaurenw-arm #include <plat/common/platform.h> 178370c8ceSlaurenw-arm 188370c8ceSlaurenw-arm /* The GICv3 driver only needs to be initialized in EL3 */ 198370c8ceSlaurenw-arm static uintptr_t fvp_rdistif_base_addrs[PLATFORM_CORE_COUNT]; 208370c8ceSlaurenw-arm 218370c8ceSlaurenw-arm /* Default GICR base address to be used for GICR probe. */ 228370c8ceSlaurenw-arm static uint64_t fvp_gicr_base_addrs[2] = { 0U }; 238370c8ceSlaurenw-arm 248370c8ceSlaurenw-arm /* List of zero terminated GICR frame addresses which CPUs will probe */ 258370c8ceSlaurenw-arm static uint64_t *fvp_gicr_frames = fvp_gicr_base_addrs; 268370c8ceSlaurenw-arm 27*452d5e5eSMadhukar Pappireddy #if !(SEC_INT_DESC_IN_FCONF && ((!defined(__aarch64__) && defined(IMAGE_BL32)) || \ 28*452d5e5eSMadhukar Pappireddy (defined(__aarch64__) && defined(IMAGE_BL31)))) 298370c8ceSlaurenw-arm static const interrupt_prop_t fvp_interrupt_props[] = { 308370c8ceSlaurenw-arm PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S), 318370c8ceSlaurenw-arm PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0) 328370c8ceSlaurenw-arm }; 33*452d5e5eSMadhukar Pappireddy #endif 348370c8ceSlaurenw-arm 358370c8ceSlaurenw-arm /* 368370c8ceSlaurenw-arm * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register 378370c8ceSlaurenw-arm * to core position. 388370c8ceSlaurenw-arm * 398370c8ceSlaurenw-arm * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity 408370c8ceSlaurenw-arm * values read from GICR_TYPER don't have an MT field. To reuse the same 418370c8ceSlaurenw-arm * translation used for CPUs, we insert MT bit read from the PE's MPIDR into 428370c8ceSlaurenw-arm * that read from GICR_TYPER. 438370c8ceSlaurenw-arm * 448370c8ceSlaurenw-arm * Assumptions: 458370c8ceSlaurenw-arm * 468370c8ceSlaurenw-arm * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; 478370c8ceSlaurenw-arm * - No CPUs implemented in the system use affinity level 3. 488370c8ceSlaurenw-arm */ 498370c8ceSlaurenw-arm static unsigned int fvp_gicv3_mpidr_hash(u_register_t mpidr) 508370c8ceSlaurenw-arm { 518370c8ceSlaurenw-arm u_register_t temp_mpidr = mpidr; 528370c8ceSlaurenw-arm 538370c8ceSlaurenw-arm temp_mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); 548370c8ceSlaurenw-arm return plat_arm_calc_core_pos(temp_mpidr); 558370c8ceSlaurenw-arm } 568370c8ceSlaurenw-arm 578370c8ceSlaurenw-arm 588370c8ceSlaurenw-arm static gicv3_driver_data_t fvp_gic_data = { 598370c8ceSlaurenw-arm .rdistif_num = PLATFORM_CORE_COUNT, 608370c8ceSlaurenw-arm .rdistif_base_addrs = fvp_rdistif_base_addrs, 618370c8ceSlaurenw-arm .mpidr_to_core_pos = fvp_gicv3_mpidr_hash 628370c8ceSlaurenw-arm }; 638370c8ceSlaurenw-arm 648370c8ceSlaurenw-arm void plat_arm_gic_driver_init(void) 658370c8ceSlaurenw-arm { 66*452d5e5eSMadhukar Pappireddy /* 67*452d5e5eSMadhukar Pappireddy * Get GICD and GICR base addressed through FCONF APIs. 68*452d5e5eSMadhukar Pappireddy * FCONF is not supported in BL32 for FVP. 69*452d5e5eSMadhukar Pappireddy */ 708370c8ceSlaurenw-arm #if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ 718370c8ceSlaurenw-arm (defined(__aarch64__) && defined(IMAGE_BL31)) 728370c8ceSlaurenw-arm fvp_gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config, 738370c8ceSlaurenw-arm gicv3_config, 748370c8ceSlaurenw-arm gicd_base); 758370c8ceSlaurenw-arm fvp_gicr_base_addrs[0] = FCONF_GET_PROPERTY(hw_config, gicv3_config, 768370c8ceSlaurenw-arm gicr_base); 77*452d5e5eSMadhukar Pappireddy #if SEC_INT_DESC_IN_FCONF 78*452d5e5eSMadhukar Pappireddy fvp_gic_data.interrupt_props = FCONF_GET_PROPERTY(hw_config, 79*452d5e5eSMadhukar Pappireddy sec_intr_prop, descriptor); 80*452d5e5eSMadhukar Pappireddy fvp_gic_data.interrupt_props_num = FCONF_GET_PROPERTY(hw_config, 81*452d5e5eSMadhukar Pappireddy sec_intr_prop, count); 82*452d5e5eSMadhukar Pappireddy #else 83*452d5e5eSMadhukar Pappireddy fvp_gic_data.interrupt_props = fvp_interrupt_props; 84*452d5e5eSMadhukar Pappireddy fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props); 85*452d5e5eSMadhukar Pappireddy #endif 868370c8ceSlaurenw-arm #else 878370c8ceSlaurenw-arm fvp_gic_data.gicd_base = PLAT_ARM_GICD_BASE; 888370c8ceSlaurenw-arm fvp_gicr_base_addrs[0] = PLAT_ARM_GICR_BASE; 89*452d5e5eSMadhukar Pappireddy fvp_gic_data.interrupt_props = fvp_interrupt_props; 90*452d5e5eSMadhukar Pappireddy fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props); 918370c8ceSlaurenw-arm #endif 928370c8ceSlaurenw-arm 938370c8ceSlaurenw-arm /* 948370c8ceSlaurenw-arm * The GICv3 driver is initialized in EL3 and does not need 958370c8ceSlaurenw-arm * to be initialized again in SEL1. This is because the S-EL1 968370c8ceSlaurenw-arm * can use GIC system registers to manage interrupts and does 978370c8ceSlaurenw-arm * not need GIC interface base addresses to be configured. 988370c8ceSlaurenw-arm */ 998370c8ceSlaurenw-arm 1008370c8ceSlaurenw-arm #if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ 1018370c8ceSlaurenw-arm (defined(__aarch64__) && defined(IMAGE_BL31)) 1028370c8ceSlaurenw-arm gicv3_driver_init(&fvp_gic_data); 1038370c8ceSlaurenw-arm if (gicv3_rdistif_probe((uintptr_t)fvp_gicr_base_addrs[0]) == -1) { 1048370c8ceSlaurenw-arm ERROR("No GICR base frame found for Primary CPU\n"); 1058370c8ceSlaurenw-arm panic(); 1068370c8ceSlaurenw-arm } 1078370c8ceSlaurenw-arm #endif 1088370c8ceSlaurenw-arm } 1098370c8ceSlaurenw-arm 1108370c8ceSlaurenw-arm /****************************************************************************** 1118370c8ceSlaurenw-arm * Function to iterate over all GICR frames and discover the corresponding 1128370c8ceSlaurenw-arm * per-cpu redistributor frame as well as initialize the corresponding 1138370c8ceSlaurenw-arm * interface in GICv3. 1148370c8ceSlaurenw-arm *****************************************************************************/ 1158370c8ceSlaurenw-arm void plat_arm_gic_pcpu_init(void) 1168370c8ceSlaurenw-arm { 1178370c8ceSlaurenw-arm int result; 1188370c8ceSlaurenw-arm const uint64_t *plat_gicr_frames = fvp_gicr_frames; 1198370c8ceSlaurenw-arm 1208370c8ceSlaurenw-arm do { 1218370c8ceSlaurenw-arm result = gicv3_rdistif_probe(*plat_gicr_frames); 1228370c8ceSlaurenw-arm 1238370c8ceSlaurenw-arm /* If the probe is successful, no need to proceed further */ 1248370c8ceSlaurenw-arm if (result == 0) 1258370c8ceSlaurenw-arm break; 1268370c8ceSlaurenw-arm 1278370c8ceSlaurenw-arm plat_gicr_frames++; 1288370c8ceSlaurenw-arm } while (*plat_gicr_frames != 0U); 1298370c8ceSlaurenw-arm 1308370c8ceSlaurenw-arm if (result == -1) { 1318370c8ceSlaurenw-arm ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr()); 1328370c8ceSlaurenw-arm panic(); 1338370c8ceSlaurenw-arm } 1348370c8ceSlaurenw-arm gicv3_rdistif_init(plat_my_core_pos()); 1358370c8ceSlaurenw-arm } 136