1*c97857dbSAmit Nagal /* 2*c97857dbSAmit Nagal * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. 3*c97857dbSAmit Nagal * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved. 4*c97857dbSAmit Nagal * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved. 5*c97857dbSAmit Nagal * 6*c97857dbSAmit Nagal * SPDX-License-Identifier: BSD-3-Clause 7*c97857dbSAmit Nagal */ 8*c97857dbSAmit Nagal 9*c97857dbSAmit Nagal #include <common/debug.h> 10*c97857dbSAmit Nagal #include <common/interrupt_props.h> 11*c97857dbSAmit Nagal #include <drivers/arm/gicv3.h> 12*c97857dbSAmit Nagal #include <lib/utils.h> 13*c97857dbSAmit Nagal #include <plat/common/platform.h> 14*c97857dbSAmit Nagal #include <platform_def.h> 15*c97857dbSAmit Nagal 16*c97857dbSAmit Nagal #include <plat_private.h> 17*c97857dbSAmit Nagal 18*c97857dbSAmit Nagal /****************************************************************************** 19*c97857dbSAmit Nagal * The following functions are defined as weak to allow a platform to override 20*c97857dbSAmit Nagal * the way the GICv3 driver is initialised and used. 21*c97857dbSAmit Nagal *****************************************************************************/ 22*c97857dbSAmit Nagal #pragma weak plat_gic_driver_init 23*c97857dbSAmit Nagal #pragma weak plat_gic_init 24*c97857dbSAmit Nagal #pragma weak plat_gic_cpuif_enable 25*c97857dbSAmit Nagal #pragma weak plat_gic_cpuif_disable 26*c97857dbSAmit Nagal #pragma weak plat_gic_pcpu_init 27*c97857dbSAmit Nagal #pragma weak plat_gic_redistif_on 28*c97857dbSAmit Nagal #pragma weak plat_gic_redistif_off 29*c97857dbSAmit Nagal 30*c97857dbSAmit Nagal /* The GICv3 driver only needs to be initialized in EL3 */ 31*c97857dbSAmit Nagal static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; 32*c97857dbSAmit Nagal 33*c97857dbSAmit Nagal static const interrupt_prop_t _interrupt_props[] = { 34*c97857dbSAmit Nagal PLAT_G1S_IRQ_PROPS(INTR_GROUP1S), 35*c97857dbSAmit Nagal PLAT_G0_IRQ_PROPS(INTR_GROUP0) 36*c97857dbSAmit Nagal }; 37*c97857dbSAmit Nagal 38*c97857dbSAmit Nagal /* 39*c97857dbSAmit Nagal * We save and restore the GICv3 context on system suspend. Allocate the 40*c97857dbSAmit Nagal * data in the designated EL3 Secure carve-out memory. 41*c97857dbSAmit Nagal */ 42*c97857dbSAmit Nagal static gicv3_redist_ctx_t rdist_ctx __section("._el3_tzc_dram"); 43*c97857dbSAmit Nagal static gicv3_dist_ctx_t dist_ctx __section("._el3_tzc_dram"); 44*c97857dbSAmit Nagal 45*c97857dbSAmit Nagal /* 46*c97857dbSAmit Nagal * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register 47*c97857dbSAmit Nagal * to core position. 48*c97857dbSAmit Nagal * 49*c97857dbSAmit Nagal * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity 50*c97857dbSAmit Nagal * values read from GICR_TYPER don't have an MT field. To reuse the same 51*c97857dbSAmit Nagal * translation used for CPUs, we insert MT bit read from the PE's MPIDR into 52*c97857dbSAmit Nagal * that read from GICR_TYPER. 53*c97857dbSAmit Nagal * 54*c97857dbSAmit Nagal * Assumptions: 55*c97857dbSAmit Nagal * 56*c97857dbSAmit Nagal * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; 57*c97857dbSAmit Nagal * - No CPUs implemented in the system use affinity level 3. 58*c97857dbSAmit Nagal */ 59*c97857dbSAmit Nagal static uint32_t _gicv3_mpidr_hash(u_register_t mpidr) 60*c97857dbSAmit Nagal { 61*c97857dbSAmit Nagal mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); 62*c97857dbSAmit Nagal return plat_core_pos_by_mpidr(mpidr); 63*c97857dbSAmit Nagal } 64*c97857dbSAmit Nagal 65*c97857dbSAmit Nagal static const gicv3_driver_data_t _gic_data __unused = { 66*c97857dbSAmit Nagal .gicd_base = PLAT_GICD_BASE_VALUE, 67*c97857dbSAmit Nagal .gicr_base = PLAT_GICR_BASE_VALUE, 68*c97857dbSAmit Nagal .interrupt_props = _interrupt_props, 69*c97857dbSAmit Nagal .interrupt_props_num = ARRAY_SIZE(_interrupt_props), 70*c97857dbSAmit Nagal .rdistif_num = PLATFORM_CORE_COUNT, 71*c97857dbSAmit Nagal .rdistif_base_addrs = rdistif_base_addrs, 72*c97857dbSAmit Nagal .mpidr_to_core_pos = _gicv3_mpidr_hash 73*c97857dbSAmit Nagal }; 74*c97857dbSAmit Nagal 75*c97857dbSAmit Nagal void __init plat_gic_driver_init(void) 76*c97857dbSAmit Nagal { 77*c97857dbSAmit Nagal /* 78*c97857dbSAmit Nagal * The GICv3 driver is initialized in EL3 and does not need 79*c97857dbSAmit Nagal * to be initialized again in SEL1. This is because the S-EL1 80*c97857dbSAmit Nagal * can use GIC system registers to manage interrupts and does 81*c97857dbSAmit Nagal * not need GIC interface base addresses to be configured. 82*c97857dbSAmit Nagal */ 83*c97857dbSAmit Nagal #if IMAGE_BL31 84*c97857dbSAmit Nagal gicv3_driver_init(&_gic_data); 85*c97857dbSAmit Nagal #endif 86*c97857dbSAmit Nagal } 87*c97857dbSAmit Nagal 88*c97857dbSAmit Nagal /****************************************************************************** 89*c97857dbSAmit Nagal * common helper to initialize the GIC. Only invoked by BL31 90*c97857dbSAmit Nagal *****************************************************************************/ 91*c97857dbSAmit Nagal void __init plat_gic_init(void) 92*c97857dbSAmit Nagal { 93*c97857dbSAmit Nagal gicv3_distif_init(); 94*c97857dbSAmit Nagal gicv3_rdistif_init(plat_my_core_pos()); 95*c97857dbSAmit Nagal gicv3_cpuif_enable(plat_my_core_pos()); 96*c97857dbSAmit Nagal } 97*c97857dbSAmit Nagal 98*c97857dbSAmit Nagal /****************************************************************************** 99*c97857dbSAmit Nagal * common helper to enable the GIC CPU interface 100*c97857dbSAmit Nagal *****************************************************************************/ 101*c97857dbSAmit Nagal void plat_gic_cpuif_enable(void) 102*c97857dbSAmit Nagal { 103*c97857dbSAmit Nagal gicv3_cpuif_enable(plat_my_core_pos()); 104*c97857dbSAmit Nagal } 105*c97857dbSAmit Nagal 106*c97857dbSAmit Nagal /****************************************************************************** 107*c97857dbSAmit Nagal * common helper to disable the GIC CPU interface 108*c97857dbSAmit Nagal *****************************************************************************/ 109*c97857dbSAmit Nagal void plat_gic_cpuif_disable(void) 110*c97857dbSAmit Nagal { 111*c97857dbSAmit Nagal gicv3_cpuif_disable(plat_my_core_pos()); 112*c97857dbSAmit Nagal } 113*c97857dbSAmit Nagal 114*c97857dbSAmit Nagal /****************************************************************************** 115*c97857dbSAmit Nagal * common helper to initialize the per-cpu redistributor interface in GICv3 116*c97857dbSAmit Nagal *****************************************************************************/ 117*c97857dbSAmit Nagal void plat_gic_pcpu_init(void) 118*c97857dbSAmit Nagal { 119*c97857dbSAmit Nagal gicv3_rdistif_init(plat_my_core_pos()); 120*c97857dbSAmit Nagal } 121*c97857dbSAmit Nagal 122*c97857dbSAmit Nagal /****************************************************************************** 123*c97857dbSAmit Nagal * common helpers to power GIC redistributor interface 124*c97857dbSAmit Nagal *****************************************************************************/ 125*c97857dbSAmit Nagal void plat_gic_redistif_on(void) 126*c97857dbSAmit Nagal { 127*c97857dbSAmit Nagal gicv3_rdistif_on(plat_my_core_pos()); 128*c97857dbSAmit Nagal } 129*c97857dbSAmit Nagal 130*c97857dbSAmit Nagal void plat_gic_redistif_off(void) 131*c97857dbSAmit Nagal { 132*c97857dbSAmit Nagal gicv3_rdistif_off(plat_my_core_pos()); 133*c97857dbSAmit Nagal } 134*c97857dbSAmit Nagal 135*c97857dbSAmit Nagal /****************************************************************************** 136*c97857dbSAmit Nagal * common helper to save & restore the GICv3 on resume from system suspend 137*c97857dbSAmit Nagal *****************************************************************************/ 138*c97857dbSAmit Nagal void plat_gic_save(void) 139*c97857dbSAmit Nagal { 140*c97857dbSAmit Nagal /* 141*c97857dbSAmit Nagal * If an ITS is available, save its context before 142*c97857dbSAmit Nagal * the Redistributor using: 143*c97857dbSAmit Nagal * gicv3_its_save_disable(gits_base, &its_ctx[i]) 144*c97857dbSAmit Nagal * Additionnaly, an implementation-defined sequence may 145*c97857dbSAmit Nagal * be required to save the whole ITS state. 146*c97857dbSAmit Nagal */ 147*c97857dbSAmit Nagal 148*c97857dbSAmit Nagal /* 149*c97857dbSAmit Nagal * Save the GIC Redistributors and ITS contexts before the 150*c97857dbSAmit Nagal * Distributor context. As we only handle SYSTEM SUSPEND API, 151*c97857dbSAmit Nagal * we only need to save the context of the CPU that is issuing 152*c97857dbSAmit Nagal * the SYSTEM SUSPEND call, i.e. the current CPU. 153*c97857dbSAmit Nagal */ 154*c97857dbSAmit Nagal gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx); 155*c97857dbSAmit Nagal 156*c97857dbSAmit Nagal /* Save the GIC Distributor context */ 157*c97857dbSAmit Nagal gicv3_distif_save(&dist_ctx); 158*c97857dbSAmit Nagal 159*c97857dbSAmit Nagal /* 160*c97857dbSAmit Nagal * From here, all the components of the GIC can be safely powered down 161*c97857dbSAmit Nagal * as long as there is an alternate way to handle wakeup interrupt 162*c97857dbSAmit Nagal * sources. 163*c97857dbSAmit Nagal */ 164*c97857dbSAmit Nagal } 165*c97857dbSAmit Nagal 166*c97857dbSAmit Nagal void plat_gic_resume(void) 167*c97857dbSAmit Nagal { 168*c97857dbSAmit Nagal /* Restore the GIC Distributor context */ 169*c97857dbSAmit Nagal gicv3_distif_init_restore(&dist_ctx); 170*c97857dbSAmit Nagal 171*c97857dbSAmit Nagal /* 172*c97857dbSAmit Nagal * Restore the GIC Redistributor and ITS contexts after the 173*c97857dbSAmit Nagal * Distributor context. As we only handle SYSTEM SUSPEND API, 174*c97857dbSAmit Nagal * we only need to restore the context of the CPU that issued 175*c97857dbSAmit Nagal * the SYSTEM SUSPEND call. 176*c97857dbSAmit Nagal */ 177*c97857dbSAmit Nagal gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx); 178*c97857dbSAmit Nagal 179*c97857dbSAmit Nagal /* 180*c97857dbSAmit Nagal * If an ITS is available, restore its context after 181*c97857dbSAmit Nagal * the Redistributor using: 182*c97857dbSAmit Nagal * gicv3_its_restore(gits_base, &its_ctx[i]) 183*c97857dbSAmit Nagal * An implementation-defined sequence may be required to 184*c97857dbSAmit Nagal * restore the whole ITS state. The ITS must also be 185*c97857dbSAmit Nagal * re-enabled after this sequence has been executed. 186*c97857dbSAmit Nagal */ 187*c97857dbSAmit Nagal } 188