18370c8ceSlaurenw-arm /* 2*f98630fbSManish V Badarkhe * Copyright (c) 2015-2021, 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> 15452d5e5eSMadhukar Pappireddy #include <plat/arm/common/fconf_sec_intr_config.h> 168370c8ceSlaurenw-arm #include <plat/common/platform.h> 178370c8ceSlaurenw-arm 18*f98630fbSManish V Badarkhe #if FVP_GICR_REGION_PROTECTION 19*f98630fbSManish V Badarkhe /* To indicate GICR region of the core initialized as Read-Write */ 20*f98630fbSManish V Badarkhe static bool fvp_gicr_rw_region_init[PLATFORM_CORE_COUNT] = {false}; 21*f98630fbSManish V Badarkhe #endif /* FVP_GICR_REGION_PROTECTION */ 22*f98630fbSManish V Badarkhe 238370c8ceSlaurenw-arm /* The GICv3 driver only needs to be initialized in EL3 */ 248370c8ceSlaurenw-arm static uintptr_t fvp_rdistif_base_addrs[PLATFORM_CORE_COUNT]; 258370c8ceSlaurenw-arm 268370c8ceSlaurenw-arm /* Default GICR base address to be used for GICR probe. */ 278370c8ceSlaurenw-arm static uint64_t fvp_gicr_base_addrs[2] = { 0U }; 288370c8ceSlaurenw-arm 298370c8ceSlaurenw-arm /* List of zero terminated GICR frame addresses which CPUs will probe */ 308370c8ceSlaurenw-arm static uint64_t *fvp_gicr_frames = fvp_gicr_base_addrs; 318370c8ceSlaurenw-arm 32452d5e5eSMadhukar Pappireddy #if !(SEC_INT_DESC_IN_FCONF && ((!defined(__aarch64__) && defined(IMAGE_BL32)) || \ 33452d5e5eSMadhukar Pappireddy (defined(__aarch64__) && defined(IMAGE_BL31)))) 348370c8ceSlaurenw-arm static const interrupt_prop_t fvp_interrupt_props[] = { 358370c8ceSlaurenw-arm PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S), 368370c8ceSlaurenw-arm PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0) 378370c8ceSlaurenw-arm }; 38452d5e5eSMadhukar Pappireddy #endif 398370c8ceSlaurenw-arm 408370c8ceSlaurenw-arm /* 418370c8ceSlaurenw-arm * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register 428370c8ceSlaurenw-arm * to core position. 438370c8ceSlaurenw-arm * 448370c8ceSlaurenw-arm * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity 458370c8ceSlaurenw-arm * values read from GICR_TYPER don't have an MT field. To reuse the same 468370c8ceSlaurenw-arm * translation used for CPUs, we insert MT bit read from the PE's MPIDR into 478370c8ceSlaurenw-arm * that read from GICR_TYPER. 488370c8ceSlaurenw-arm * 498370c8ceSlaurenw-arm * Assumptions: 508370c8ceSlaurenw-arm * 518370c8ceSlaurenw-arm * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; 528370c8ceSlaurenw-arm * - No CPUs implemented in the system use affinity level 3. 538370c8ceSlaurenw-arm */ 548370c8ceSlaurenw-arm static unsigned int fvp_gicv3_mpidr_hash(u_register_t mpidr) 558370c8ceSlaurenw-arm { 568370c8ceSlaurenw-arm u_register_t temp_mpidr = mpidr; 578370c8ceSlaurenw-arm 588370c8ceSlaurenw-arm temp_mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); 598370c8ceSlaurenw-arm return plat_arm_calc_core_pos(temp_mpidr); 608370c8ceSlaurenw-arm } 618370c8ceSlaurenw-arm 628370c8ceSlaurenw-arm 638370c8ceSlaurenw-arm static gicv3_driver_data_t fvp_gic_data = { 648370c8ceSlaurenw-arm .rdistif_num = PLATFORM_CORE_COUNT, 658370c8ceSlaurenw-arm .rdistif_base_addrs = fvp_rdistif_base_addrs, 668370c8ceSlaurenw-arm .mpidr_to_core_pos = fvp_gicv3_mpidr_hash 678370c8ceSlaurenw-arm }; 688370c8ceSlaurenw-arm 69*f98630fbSManish V Badarkhe /****************************************************************************** 70*f98630fbSManish V Badarkhe * This function gets called per core to make its redistributor frame rw 71*f98630fbSManish V Badarkhe *****************************************************************************/ 72*f98630fbSManish V Badarkhe static void fvp_gicv3_make_rdistrif_rw(void) 73*f98630fbSManish V Badarkhe { 74*f98630fbSManish V Badarkhe #if FVP_GICR_REGION_PROTECTION 75*f98630fbSManish V Badarkhe unsigned int core_pos = plat_my_core_pos(); 76*f98630fbSManish V Badarkhe 77*f98630fbSManish V Badarkhe /* Make the redistributor frame RW if it is not done previously */ 78*f98630fbSManish V Badarkhe if (fvp_gicr_rw_region_init[core_pos] != true) { 79*f98630fbSManish V Badarkhe int ret = xlat_change_mem_attributes(BASE_GICR_BASE + 80*f98630fbSManish V Badarkhe (core_pos * BASE_GICR_SIZE), 81*f98630fbSManish V Badarkhe BASE_GICR_SIZE, 82*f98630fbSManish V Badarkhe MT_EXECUTE_NEVER | 83*f98630fbSManish V Badarkhe MT_DEVICE | MT_RW | 84*f98630fbSManish V Badarkhe MT_SECURE); 85*f98630fbSManish V Badarkhe 86*f98630fbSManish V Badarkhe if (ret != 0) { 87*f98630fbSManish V Badarkhe ERROR("Failed to make redistributor frame \ 88*f98630fbSManish V Badarkhe read write = %d\n", ret); 89*f98630fbSManish V Badarkhe panic(); 90*f98630fbSManish V Badarkhe } else { 91*f98630fbSManish V Badarkhe fvp_gicr_rw_region_init[core_pos] = true; 92*f98630fbSManish V Badarkhe } 93*f98630fbSManish V Badarkhe } 94*f98630fbSManish V Badarkhe #else 95*f98630fbSManish V Badarkhe return; 96*f98630fbSManish V Badarkhe #endif /* FVP_GICR_REGION_PROTECTION */ 97*f98630fbSManish V Badarkhe } 98*f98630fbSManish V Badarkhe 998370c8ceSlaurenw-arm void plat_arm_gic_driver_init(void) 1008370c8ceSlaurenw-arm { 101*f98630fbSManish V Badarkhe fvp_gicv3_make_rdistrif_rw(); 102452d5e5eSMadhukar Pappireddy /* 103452d5e5eSMadhukar Pappireddy * Get GICD and GICR base addressed through FCONF APIs. 104452d5e5eSMadhukar Pappireddy * FCONF is not supported in BL32 for FVP. 105452d5e5eSMadhukar Pappireddy */ 1068370c8ceSlaurenw-arm #if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ 1078370c8ceSlaurenw-arm (defined(__aarch64__) && defined(IMAGE_BL31)) 1088370c8ceSlaurenw-arm fvp_gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config, 1098370c8ceSlaurenw-arm gicv3_config, 1108370c8ceSlaurenw-arm gicd_base); 1118370c8ceSlaurenw-arm fvp_gicr_base_addrs[0] = FCONF_GET_PROPERTY(hw_config, gicv3_config, 1128370c8ceSlaurenw-arm gicr_base); 113452d5e5eSMadhukar Pappireddy #if SEC_INT_DESC_IN_FCONF 114452d5e5eSMadhukar Pappireddy fvp_gic_data.interrupt_props = FCONF_GET_PROPERTY(hw_config, 115452d5e5eSMadhukar Pappireddy sec_intr_prop, descriptor); 116452d5e5eSMadhukar Pappireddy fvp_gic_data.interrupt_props_num = FCONF_GET_PROPERTY(hw_config, 117452d5e5eSMadhukar Pappireddy sec_intr_prop, count); 118452d5e5eSMadhukar Pappireddy #else 119452d5e5eSMadhukar Pappireddy fvp_gic_data.interrupt_props = fvp_interrupt_props; 120452d5e5eSMadhukar Pappireddy fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props); 121452d5e5eSMadhukar Pappireddy #endif 1228370c8ceSlaurenw-arm #else 1238370c8ceSlaurenw-arm fvp_gic_data.gicd_base = PLAT_ARM_GICD_BASE; 1248370c8ceSlaurenw-arm fvp_gicr_base_addrs[0] = PLAT_ARM_GICR_BASE; 125452d5e5eSMadhukar Pappireddy fvp_gic_data.interrupt_props = fvp_interrupt_props; 126452d5e5eSMadhukar Pappireddy fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props); 1278370c8ceSlaurenw-arm #endif 1288370c8ceSlaurenw-arm 1298370c8ceSlaurenw-arm /* 1308370c8ceSlaurenw-arm * The GICv3 driver is initialized in EL3 and does not need 1318370c8ceSlaurenw-arm * to be initialized again in SEL1. This is because the S-EL1 1328370c8ceSlaurenw-arm * can use GIC system registers to manage interrupts and does 1338370c8ceSlaurenw-arm * not need GIC interface base addresses to be configured. 1348370c8ceSlaurenw-arm */ 1358370c8ceSlaurenw-arm 1368370c8ceSlaurenw-arm #if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ 1378370c8ceSlaurenw-arm (defined(__aarch64__) && defined(IMAGE_BL31)) 1388370c8ceSlaurenw-arm gicv3_driver_init(&fvp_gic_data); 1398370c8ceSlaurenw-arm if (gicv3_rdistif_probe((uintptr_t)fvp_gicr_base_addrs[0]) == -1) { 1408370c8ceSlaurenw-arm ERROR("No GICR base frame found for Primary CPU\n"); 1418370c8ceSlaurenw-arm panic(); 1428370c8ceSlaurenw-arm } 1438370c8ceSlaurenw-arm #endif 1448370c8ceSlaurenw-arm } 1458370c8ceSlaurenw-arm 1468370c8ceSlaurenw-arm /****************************************************************************** 1478370c8ceSlaurenw-arm * Function to iterate over all GICR frames and discover the corresponding 1488370c8ceSlaurenw-arm * per-cpu redistributor frame as well as initialize the corresponding 1498370c8ceSlaurenw-arm * interface in GICv3. 1508370c8ceSlaurenw-arm *****************************************************************************/ 1518370c8ceSlaurenw-arm void plat_arm_gic_pcpu_init(void) 1528370c8ceSlaurenw-arm { 1538370c8ceSlaurenw-arm int result; 1548370c8ceSlaurenw-arm const uint64_t *plat_gicr_frames = fvp_gicr_frames; 1558370c8ceSlaurenw-arm 156*f98630fbSManish V Badarkhe fvp_gicv3_make_rdistrif_rw(); 157*f98630fbSManish V Badarkhe 1588370c8ceSlaurenw-arm do { 1598370c8ceSlaurenw-arm result = gicv3_rdistif_probe(*plat_gicr_frames); 1608370c8ceSlaurenw-arm 1618370c8ceSlaurenw-arm /* If the probe is successful, no need to proceed further */ 1628370c8ceSlaurenw-arm if (result == 0) 1638370c8ceSlaurenw-arm break; 1648370c8ceSlaurenw-arm 1658370c8ceSlaurenw-arm plat_gicr_frames++; 1668370c8ceSlaurenw-arm } while (*plat_gicr_frames != 0U); 1678370c8ceSlaurenw-arm 1688370c8ceSlaurenw-arm if (result == -1) { 1698370c8ceSlaurenw-arm ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr()); 1708370c8ceSlaurenw-arm panic(); 1718370c8ceSlaurenw-arm } 1728370c8ceSlaurenw-arm gicv3_rdistif_init(plat_my_core_pos()); 1738370c8ceSlaurenw-arm } 174