1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * Copyright (c) 2023, NVIDIA Corporation. All rights reserved. 4*91f16700Schasinglulu * 5*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <assert.h> 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <arch.h> 11*91f16700Schasinglulu #include <arch_helpers.h> 12*91f16700Schasinglulu #include <common/debug.h> 13*91f16700Schasinglulu #include <common/interrupt_props.h> 14*91f16700Schasinglulu #include <drivers/arm/gic600_multichip.h> 15*91f16700Schasinglulu #include <drivers/arm/gic_common.h> 16*91f16700Schasinglulu 17*91f16700Schasinglulu #include <platform_def.h> 18*91f16700Schasinglulu 19*91f16700Schasinglulu #include "../common/gic_common_private.h" 20*91f16700Schasinglulu #include "gicv3_private.h" 21*91f16700Schasinglulu 22*91f16700Schasinglulu uintptr_t gicv3_get_multichip_base(uint32_t spi_id, uintptr_t gicd_base) 23*91f16700Schasinglulu { 24*91f16700Schasinglulu #if GICV3_IMPL_GIC600_MULTICHIP 25*91f16700Schasinglulu if (gic600_multichip_is_initialized()) { 26*91f16700Schasinglulu return gic600_multichip_gicd_base_for_spi(spi_id); 27*91f16700Schasinglulu } 28*91f16700Schasinglulu #endif 29*91f16700Schasinglulu return gicd_base; 30*91f16700Schasinglulu } 31*91f16700Schasinglulu 32*91f16700Schasinglulu /****************************************************************************** 33*91f16700Schasinglulu * This function marks the core as awake in the re-distributor and 34*91f16700Schasinglulu * ensures that the interface is active. 35*91f16700Schasinglulu *****************************************************************************/ 36*91f16700Schasinglulu void gicv3_rdistif_mark_core_awake(uintptr_t gicr_base) 37*91f16700Schasinglulu { 38*91f16700Schasinglulu /* 39*91f16700Schasinglulu * The WAKER_PS_BIT should be changed to 0 40*91f16700Schasinglulu * only when WAKER_CA_BIT is 1. 41*91f16700Schasinglulu */ 42*91f16700Schasinglulu assert((gicr_read_waker(gicr_base) & WAKER_CA_BIT) != 0U); 43*91f16700Schasinglulu 44*91f16700Schasinglulu /* Mark the connected core as awake */ 45*91f16700Schasinglulu gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_PS_BIT); 46*91f16700Schasinglulu 47*91f16700Schasinglulu /* Wait till the WAKER_CA_BIT changes to 0 */ 48*91f16700Schasinglulu while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) != 0U) { 49*91f16700Schasinglulu } 50*91f16700Schasinglulu } 51*91f16700Schasinglulu 52*91f16700Schasinglulu /****************************************************************************** 53*91f16700Schasinglulu * This function marks the core as asleep in the re-distributor and ensures 54*91f16700Schasinglulu * that the interface is quiescent. 55*91f16700Schasinglulu *****************************************************************************/ 56*91f16700Schasinglulu void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base) 57*91f16700Schasinglulu { 58*91f16700Schasinglulu /* Mark the connected core as asleep */ 59*91f16700Schasinglulu gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_PS_BIT); 60*91f16700Schasinglulu 61*91f16700Schasinglulu /* Wait till the WAKER_CA_BIT changes to 1 */ 62*91f16700Schasinglulu while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) == 0U) { 63*91f16700Schasinglulu } 64*91f16700Schasinglulu } 65*91f16700Schasinglulu 66*91f16700Schasinglulu /******************************************************************************* 67*91f16700Schasinglulu * This function probes the Redistributor frames when the driver is initialised 68*91f16700Schasinglulu * and saves their base addresses. These base addresses are used later to 69*91f16700Schasinglulu * initialise each Redistributor interface. 70*91f16700Schasinglulu ******************************************************************************/ 71*91f16700Schasinglulu void gicv3_rdistif_base_addrs_probe(uintptr_t *rdistif_base_addrs, 72*91f16700Schasinglulu unsigned int rdistif_num, 73*91f16700Schasinglulu uintptr_t gicr_base, 74*91f16700Schasinglulu mpidr_hash_fn mpidr_to_core_pos) 75*91f16700Schasinglulu { 76*91f16700Schasinglulu u_register_t mpidr; 77*91f16700Schasinglulu unsigned int proc_num; 78*91f16700Schasinglulu uint64_t typer_val; 79*91f16700Schasinglulu uintptr_t rdistif_base = gicr_base; 80*91f16700Schasinglulu 81*91f16700Schasinglulu assert(rdistif_base_addrs != NULL); 82*91f16700Schasinglulu 83*91f16700Schasinglulu /* 84*91f16700Schasinglulu * Iterate over the Redistributor frames. Store the base address of each 85*91f16700Schasinglulu * frame in the platform provided array. Use the "Processor Number" 86*91f16700Schasinglulu * field to index into the array if the platform has not provided a hash 87*91f16700Schasinglulu * function to convert an MPIDR (obtained from the "Affinity Value" 88*91f16700Schasinglulu * field into a linear index. 89*91f16700Schasinglulu */ 90*91f16700Schasinglulu do { 91*91f16700Schasinglulu typer_val = gicr_read_typer(rdistif_base); 92*91f16700Schasinglulu if (mpidr_to_core_pos != NULL) { 93*91f16700Schasinglulu mpidr = mpidr_from_gicr_typer(typer_val); 94*91f16700Schasinglulu proc_num = mpidr_to_core_pos(mpidr); 95*91f16700Schasinglulu } else { 96*91f16700Schasinglulu proc_num = (typer_val >> TYPER_PROC_NUM_SHIFT) & 97*91f16700Schasinglulu TYPER_PROC_NUM_MASK; 98*91f16700Schasinglulu } 99*91f16700Schasinglulu 100*91f16700Schasinglulu if (proc_num < rdistif_num) { 101*91f16700Schasinglulu rdistif_base_addrs[proc_num] = rdistif_base; 102*91f16700Schasinglulu } 103*91f16700Schasinglulu rdistif_base += gicv3_redist_size(typer_val); 104*91f16700Schasinglulu } while ((typer_val & TYPER_LAST_BIT) == 0U); 105*91f16700Schasinglulu } 106*91f16700Schasinglulu 107*91f16700Schasinglulu /******************************************************************************* 108*91f16700Schasinglulu * Helper function to get the maximum SPI INTID + 1. 109*91f16700Schasinglulu ******************************************************************************/ 110*91f16700Schasinglulu unsigned int gicv3_get_spi_limit(uintptr_t gicd_base) 111*91f16700Schasinglulu { 112*91f16700Schasinglulu unsigned int spi_limit; 113*91f16700Schasinglulu unsigned int typer_reg = gicd_read_typer(gicd_base); 114*91f16700Schasinglulu 115*91f16700Schasinglulu /* (maximum SPI INTID + 1) is equal to 32 * (GICD_TYPER.ITLinesNumber+1) */ 116*91f16700Schasinglulu spi_limit = ((typer_reg & TYPER_IT_LINES_NO_MASK) + 1U) << 5; 117*91f16700Schasinglulu 118*91f16700Schasinglulu /* Filter out special INTIDs 1020-1023 */ 119*91f16700Schasinglulu if (spi_limit > (MAX_SPI_ID + 1U)) { 120*91f16700Schasinglulu return MAX_SPI_ID + 1U; 121*91f16700Schasinglulu } 122*91f16700Schasinglulu 123*91f16700Schasinglulu return spi_limit; 124*91f16700Schasinglulu } 125*91f16700Schasinglulu 126*91f16700Schasinglulu #if GIC_EXT_INTID 127*91f16700Schasinglulu /******************************************************************************* 128*91f16700Schasinglulu * Helper function to get the maximum ESPI INTID + 1. 129*91f16700Schasinglulu ******************************************************************************/ 130*91f16700Schasinglulu unsigned int gicv3_get_espi_limit(uintptr_t gicd_base) 131*91f16700Schasinglulu { 132*91f16700Schasinglulu unsigned int typer_reg = gicd_read_typer(gicd_base); 133*91f16700Schasinglulu 134*91f16700Schasinglulu /* Check if extended SPI range is implemented */ 135*91f16700Schasinglulu if ((typer_reg & TYPER_ESPI) != 0U) { 136*91f16700Schasinglulu /* 137*91f16700Schasinglulu * (maximum ESPI INTID + 1) is equal to 138*91f16700Schasinglulu * 32 * (GICD_TYPER.ESPI_range + 1) + 4096 139*91f16700Schasinglulu */ 140*91f16700Schasinglulu return ((((typer_reg >> TYPER_ESPI_RANGE_SHIFT) & 141*91f16700Schasinglulu TYPER_ESPI_RANGE_MASK) + 1U) << 5) + MIN_ESPI_ID; 142*91f16700Schasinglulu } 143*91f16700Schasinglulu 144*91f16700Schasinglulu return 0U; 145*91f16700Schasinglulu } 146*91f16700Schasinglulu #endif /* GIC_EXT_INTID */ 147*91f16700Schasinglulu 148*91f16700Schasinglulu /******************************************************************************* 149*91f16700Schasinglulu * Helper function to configure the default attributes of (E)SPIs. 150*91f16700Schasinglulu ******************************************************************************/ 151*91f16700Schasinglulu void gicv3_spis_config_defaults(uintptr_t gicd_base) 152*91f16700Schasinglulu { 153*91f16700Schasinglulu unsigned int i, num_ints; 154*91f16700Schasinglulu #if GIC_EXT_INTID 155*91f16700Schasinglulu unsigned int num_eints; 156*91f16700Schasinglulu #endif 157*91f16700Schasinglulu 158*91f16700Schasinglulu num_ints = gicv3_get_spi_limit(gicd_base); 159*91f16700Schasinglulu INFO("Maximum SPI INTID supported: %u\n", num_ints - 1); 160*91f16700Schasinglulu 161*91f16700Schasinglulu /* Treat all (E)SPIs as G1NS by default. We do 32 at a time. */ 162*91f16700Schasinglulu for (i = MIN_SPI_ID; i < num_ints; i += (1U << IGROUPR_SHIFT)) { 163*91f16700Schasinglulu gicd_write_igroupr(gicv3_get_multichip_base(i, gicd_base), i, ~0U); 164*91f16700Schasinglulu } 165*91f16700Schasinglulu 166*91f16700Schasinglulu #if GIC_EXT_INTID 167*91f16700Schasinglulu num_eints = gicv3_get_espi_limit(gicd_base); 168*91f16700Schasinglulu if (num_eints != 0U) { 169*91f16700Schasinglulu INFO("Maximum ESPI INTID supported: %u\n", num_eints - 1); 170*91f16700Schasinglulu 171*91f16700Schasinglulu for (i = MIN_ESPI_ID; i < num_eints; 172*91f16700Schasinglulu i += (1U << IGROUPR_SHIFT)) { 173*91f16700Schasinglulu gicd_write_igroupr(gicv3_get_multichip_base(i, gicd_base), i, ~0U); 174*91f16700Schasinglulu } 175*91f16700Schasinglulu } else { 176*91f16700Schasinglulu INFO("ESPI range is not implemented.\n"); 177*91f16700Schasinglulu } 178*91f16700Schasinglulu #endif 179*91f16700Schasinglulu 180*91f16700Schasinglulu /* Setup the default (E)SPI priorities doing four at a time */ 181*91f16700Schasinglulu for (i = MIN_SPI_ID; i < num_ints; i += (1U << IPRIORITYR_SHIFT)) { 182*91f16700Schasinglulu gicd_write_ipriorityr(gicv3_get_multichip_base(i, gicd_base), i, GICD_IPRIORITYR_DEF_VAL); 183*91f16700Schasinglulu } 184*91f16700Schasinglulu 185*91f16700Schasinglulu #if GIC_EXT_INTID 186*91f16700Schasinglulu for (i = MIN_ESPI_ID; i < num_eints; 187*91f16700Schasinglulu i += (1U << IPRIORITYR_SHIFT)) { 188*91f16700Schasinglulu gicd_write_ipriorityr(gicv3_get_multichip_base(i, gicd_base), i, GICD_IPRIORITYR_DEF_VAL); 189*91f16700Schasinglulu } 190*91f16700Schasinglulu #endif 191*91f16700Schasinglulu /* 192*91f16700Schasinglulu * Treat all (E)SPIs as level triggered by default, write 16 at a time 193*91f16700Schasinglulu */ 194*91f16700Schasinglulu for (i = MIN_SPI_ID; i < num_ints; i += (1U << ICFGR_SHIFT)) { 195*91f16700Schasinglulu gicd_write_icfgr(gicv3_get_multichip_base(i, gicd_base), i, 0U); 196*91f16700Schasinglulu } 197*91f16700Schasinglulu 198*91f16700Schasinglulu #if GIC_EXT_INTID 199*91f16700Schasinglulu for (i = MIN_ESPI_ID; i < num_eints; i += (1U << ICFGR_SHIFT)) { 200*91f16700Schasinglulu gicd_write_icfgr(gicv3_get_multichip_base(i, gicd_base), i, 0U); 201*91f16700Schasinglulu } 202*91f16700Schasinglulu #endif 203*91f16700Schasinglulu } 204*91f16700Schasinglulu 205*91f16700Schasinglulu /******************************************************************************* 206*91f16700Schasinglulu * Helper function to configure properties of secure (E)SPIs 207*91f16700Schasinglulu ******************************************************************************/ 208*91f16700Schasinglulu unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base, 209*91f16700Schasinglulu const interrupt_prop_t *interrupt_props, 210*91f16700Schasinglulu unsigned int interrupt_props_num) 211*91f16700Schasinglulu { 212*91f16700Schasinglulu unsigned int i; 213*91f16700Schasinglulu const interrupt_prop_t *current_prop; 214*91f16700Schasinglulu unsigned long long gic_affinity_val; 215*91f16700Schasinglulu unsigned int ctlr_enable = 0U; 216*91f16700Schasinglulu 217*91f16700Schasinglulu /* Make sure there's a valid property array */ 218*91f16700Schasinglulu if (interrupt_props_num > 0U) { 219*91f16700Schasinglulu assert(interrupt_props != NULL); 220*91f16700Schasinglulu } 221*91f16700Schasinglulu 222*91f16700Schasinglulu for (i = 0U; i < interrupt_props_num; i++) { 223*91f16700Schasinglulu current_prop = &interrupt_props[i]; 224*91f16700Schasinglulu 225*91f16700Schasinglulu unsigned int intr_num = current_prop->intr_num; 226*91f16700Schasinglulu uintptr_t multichip_gicd_base; 227*91f16700Schasinglulu 228*91f16700Schasinglulu /* Skip SGI, (E)PPI and LPI interrupts */ 229*91f16700Schasinglulu if (!IS_SPI(intr_num)) { 230*91f16700Schasinglulu continue; 231*91f16700Schasinglulu } 232*91f16700Schasinglulu 233*91f16700Schasinglulu multichip_gicd_base = 234*91f16700Schasinglulu gicv3_get_multichip_base(intr_num, gicd_base); 235*91f16700Schasinglulu 236*91f16700Schasinglulu /* Configure this interrupt as a secure interrupt */ 237*91f16700Schasinglulu gicd_clr_igroupr(multichip_gicd_base, intr_num); 238*91f16700Schasinglulu 239*91f16700Schasinglulu /* Configure this interrupt as G0 or a G1S interrupt */ 240*91f16700Schasinglulu assert((current_prop->intr_grp == INTR_GROUP0) || 241*91f16700Schasinglulu (current_prop->intr_grp == INTR_GROUP1S)); 242*91f16700Schasinglulu 243*91f16700Schasinglulu if (current_prop->intr_grp == INTR_GROUP1S) { 244*91f16700Schasinglulu gicd_set_igrpmodr(multichip_gicd_base, intr_num); 245*91f16700Schasinglulu ctlr_enable |= CTLR_ENABLE_G1S_BIT; 246*91f16700Schasinglulu } else { 247*91f16700Schasinglulu gicd_clr_igrpmodr(multichip_gicd_base, intr_num); 248*91f16700Schasinglulu ctlr_enable |= CTLR_ENABLE_G0_BIT; 249*91f16700Schasinglulu } 250*91f16700Schasinglulu 251*91f16700Schasinglulu /* Set interrupt configuration */ 252*91f16700Schasinglulu gicd_set_icfgr(multichip_gicd_base, intr_num, 253*91f16700Schasinglulu current_prop->intr_cfg); 254*91f16700Schasinglulu 255*91f16700Schasinglulu /* Set the priority of this interrupt */ 256*91f16700Schasinglulu gicd_set_ipriorityr(multichip_gicd_base, intr_num, 257*91f16700Schasinglulu current_prop->intr_pri); 258*91f16700Schasinglulu 259*91f16700Schasinglulu /* Target (E)SPIs to the primary CPU */ 260*91f16700Schasinglulu gic_affinity_val = 261*91f16700Schasinglulu gicd_irouter_val_from_mpidr(read_mpidr(), 0U); 262*91f16700Schasinglulu gicd_write_irouter(multichip_gicd_base, intr_num, 263*91f16700Schasinglulu gic_affinity_val); 264*91f16700Schasinglulu 265*91f16700Schasinglulu /* Enable this interrupt */ 266*91f16700Schasinglulu gicd_set_isenabler(multichip_gicd_base, intr_num); 267*91f16700Schasinglulu } 268*91f16700Schasinglulu 269*91f16700Schasinglulu return ctlr_enable; 270*91f16700Schasinglulu } 271*91f16700Schasinglulu 272*91f16700Schasinglulu /******************************************************************************* 273*91f16700Schasinglulu * Helper function to configure the default attributes of (E)PPIs/SGIs 274*91f16700Schasinglulu ******************************************************************************/ 275*91f16700Schasinglulu void gicv3_ppi_sgi_config_defaults(uintptr_t gicr_base) 276*91f16700Schasinglulu { 277*91f16700Schasinglulu unsigned int i, ppi_regs_num, regs_num; 278*91f16700Schasinglulu 279*91f16700Schasinglulu #if GIC_EXT_INTID 280*91f16700Schasinglulu /* Calculate number of PPI registers */ 281*91f16700Schasinglulu ppi_regs_num = (unsigned int)((gicr_read_typer(gicr_base) >> 282*91f16700Schasinglulu TYPER_PPI_NUM_SHIFT) & TYPER_PPI_NUM_MASK) + 1; 283*91f16700Schasinglulu /* All other values except PPInum [0-2] are reserved */ 284*91f16700Schasinglulu if (ppi_regs_num > 3U) { 285*91f16700Schasinglulu ppi_regs_num = 1U; 286*91f16700Schasinglulu } 287*91f16700Schasinglulu #else 288*91f16700Schasinglulu ppi_regs_num = 1U; 289*91f16700Schasinglulu #endif 290*91f16700Schasinglulu /* 291*91f16700Schasinglulu * Disable all SGIs (imp. def.)/(E)PPIs before configuring them. 292*91f16700Schasinglulu * This is a more scalable approach as it avoids clearing 293*91f16700Schasinglulu * the enable bits in the GICD_CTLR. 294*91f16700Schasinglulu */ 295*91f16700Schasinglulu for (i = 0U; i < ppi_regs_num; ++i) { 296*91f16700Schasinglulu gicr_write_icenabler(gicr_base, i, ~0U); 297*91f16700Schasinglulu } 298*91f16700Schasinglulu 299*91f16700Schasinglulu /* Wait for pending writes to GICR_ICENABLER */ 300*91f16700Schasinglulu gicr_wait_for_pending_write(gicr_base); 301*91f16700Schasinglulu 302*91f16700Schasinglulu /* 32 interrupt IDs per GICR_IGROUPR register */ 303*91f16700Schasinglulu for (i = 0U; i < ppi_regs_num; ++i) { 304*91f16700Schasinglulu /* Treat all SGIs/(E)PPIs as G1NS by default */ 305*91f16700Schasinglulu gicr_write_igroupr(gicr_base, i, ~0U); 306*91f16700Schasinglulu } 307*91f16700Schasinglulu 308*91f16700Schasinglulu /* 4 interrupt IDs per GICR_IPRIORITYR register */ 309*91f16700Schasinglulu regs_num = ppi_regs_num << 3; 310*91f16700Schasinglulu for (i = 0U; i < regs_num; ++i) { 311*91f16700Schasinglulu /* Setup the default (E)PPI/SGI priorities doing 4 at a time */ 312*91f16700Schasinglulu gicr_write_ipriorityr(gicr_base, i << 2, GICD_IPRIORITYR_DEF_VAL); 313*91f16700Schasinglulu } 314*91f16700Schasinglulu 315*91f16700Schasinglulu /* 16 interrupt IDs per GICR_ICFGR register */ 316*91f16700Schasinglulu regs_num = ppi_regs_num << 1; 317*91f16700Schasinglulu for (i = (MIN_PPI_ID >> ICFGR_SHIFT); i < regs_num; ++i) { 318*91f16700Schasinglulu /* Configure all (E)PPIs as level triggered by default */ 319*91f16700Schasinglulu gicr_write_icfgr(gicr_base, i, 0U); 320*91f16700Schasinglulu } 321*91f16700Schasinglulu } 322*91f16700Schasinglulu 323*91f16700Schasinglulu /******************************************************************************* 324*91f16700Schasinglulu * Helper function to configure properties of secure G0 and G1S (E)PPIs and SGIs 325*91f16700Schasinglulu ******************************************************************************/ 326*91f16700Schasinglulu unsigned int gicv3_secure_ppi_sgi_config_props(uintptr_t gicr_base, 327*91f16700Schasinglulu const interrupt_prop_t *interrupt_props, 328*91f16700Schasinglulu unsigned int interrupt_props_num) 329*91f16700Schasinglulu { 330*91f16700Schasinglulu unsigned int i; 331*91f16700Schasinglulu const interrupt_prop_t *current_prop; 332*91f16700Schasinglulu unsigned int ctlr_enable = 0U; 333*91f16700Schasinglulu 334*91f16700Schasinglulu /* Make sure there's a valid property array */ 335*91f16700Schasinglulu if (interrupt_props_num > 0U) { 336*91f16700Schasinglulu assert(interrupt_props != NULL); 337*91f16700Schasinglulu } 338*91f16700Schasinglulu 339*91f16700Schasinglulu for (i = 0U; i < interrupt_props_num; i++) { 340*91f16700Schasinglulu current_prop = &interrupt_props[i]; 341*91f16700Schasinglulu 342*91f16700Schasinglulu unsigned int intr_num = current_prop->intr_num; 343*91f16700Schasinglulu 344*91f16700Schasinglulu /* Skip (E)SPI interrupt */ 345*91f16700Schasinglulu if (!IS_SGI_PPI(intr_num)) { 346*91f16700Schasinglulu continue; 347*91f16700Schasinglulu } 348*91f16700Schasinglulu 349*91f16700Schasinglulu /* Configure this interrupt as a secure interrupt */ 350*91f16700Schasinglulu gicr_clr_igroupr(gicr_base, intr_num); 351*91f16700Schasinglulu 352*91f16700Schasinglulu /* Configure this interrupt as G0 or a G1S interrupt */ 353*91f16700Schasinglulu assert((current_prop->intr_grp == INTR_GROUP0) || 354*91f16700Schasinglulu (current_prop->intr_grp == INTR_GROUP1S)); 355*91f16700Schasinglulu 356*91f16700Schasinglulu if (current_prop->intr_grp == INTR_GROUP1S) { 357*91f16700Schasinglulu gicr_set_igrpmodr(gicr_base, intr_num); 358*91f16700Schasinglulu ctlr_enable |= CTLR_ENABLE_G1S_BIT; 359*91f16700Schasinglulu } else { 360*91f16700Schasinglulu gicr_clr_igrpmodr(gicr_base, intr_num); 361*91f16700Schasinglulu ctlr_enable |= CTLR_ENABLE_G0_BIT; 362*91f16700Schasinglulu } 363*91f16700Schasinglulu 364*91f16700Schasinglulu /* Set the priority of this interrupt */ 365*91f16700Schasinglulu gicr_set_ipriorityr(gicr_base, intr_num, 366*91f16700Schasinglulu current_prop->intr_pri); 367*91f16700Schasinglulu 368*91f16700Schasinglulu /* 369*91f16700Schasinglulu * Set interrupt configuration for (E)PPIs. 370*91f16700Schasinglulu * Configurations for SGIs 0-15 are ignored. 371*91f16700Schasinglulu */ 372*91f16700Schasinglulu if (intr_num >= MIN_PPI_ID) { 373*91f16700Schasinglulu gicr_set_icfgr(gicr_base, intr_num, 374*91f16700Schasinglulu current_prop->intr_cfg); 375*91f16700Schasinglulu } 376*91f16700Schasinglulu 377*91f16700Schasinglulu /* Enable this interrupt */ 378*91f16700Schasinglulu gicr_set_isenabler(gicr_base, intr_num); 379*91f16700Schasinglulu } 380*91f16700Schasinglulu 381*91f16700Schasinglulu return ctlr_enable; 382*91f16700Schasinglulu } 383*91f16700Schasinglulu 384*91f16700Schasinglulu /** 385*91f16700Schasinglulu * gicv3_rdistif_get_number_frames() - determine size of GICv3 GICR region 386*91f16700Schasinglulu * @gicr_frame: base address of the GICR region to check 387*91f16700Schasinglulu * 388*91f16700Schasinglulu * This iterates over the GICR_TYPER registers of multiple GICR frames in 389*91f16700Schasinglulu * a GICR region, to find the instance which has the LAST bit set. For most 390*91f16700Schasinglulu * systems this corresponds to the number of cores handled by a redistributor, 391*91f16700Schasinglulu * but there could be disabled cores among them. 392*91f16700Schasinglulu * It assumes that each GICR region is fully accessible (till the LAST bit 393*91f16700Schasinglulu * marks the end of the region). 394*91f16700Schasinglulu * If a platform has multiple GICR regions, this function would need to be 395*91f16700Schasinglulu * called multiple times, providing the respective GICR base address each time. 396*91f16700Schasinglulu * 397*91f16700Schasinglulu * Return: number of valid GICR frames (at least 1, up to PLATFORM_CORE_COUNT) 398*91f16700Schasinglulu ******************************************************************************/ 399*91f16700Schasinglulu unsigned int gicv3_rdistif_get_number_frames(const uintptr_t gicr_frame) 400*91f16700Schasinglulu { 401*91f16700Schasinglulu uintptr_t rdistif_base = gicr_frame; 402*91f16700Schasinglulu unsigned int count; 403*91f16700Schasinglulu 404*91f16700Schasinglulu for (count = 1U; count < PLATFORM_CORE_COUNT; count++) { 405*91f16700Schasinglulu uint64_t typer_val = gicr_read_typer(rdistif_base); 406*91f16700Schasinglulu 407*91f16700Schasinglulu if ((typer_val & TYPER_LAST_BIT) != 0U) { 408*91f16700Schasinglulu break; 409*91f16700Schasinglulu } 410*91f16700Schasinglulu rdistif_base += gicv3_redist_size(typer_val); 411*91f16700Schasinglulu } 412*91f16700Schasinglulu 413*91f16700Schasinglulu return count; 414*91f16700Schasinglulu } 415*91f16700Schasinglulu 416*91f16700Schasinglulu unsigned int gicv3_get_component_partnum(const uintptr_t gic_frame) 417*91f16700Schasinglulu { 418*91f16700Schasinglulu unsigned int part_id; 419*91f16700Schasinglulu 420*91f16700Schasinglulu /* 421*91f16700Schasinglulu * The lower 8 bits of PIDR0, complemented by the lower 4 bits of 422*91f16700Schasinglulu * PIDR1 contain a part number identifying the GIC component at a 423*91f16700Schasinglulu * particular base address. 424*91f16700Schasinglulu */ 425*91f16700Schasinglulu part_id = mmio_read_32(gic_frame + GICD_PIDR0_GICV3) & 0xff; 426*91f16700Schasinglulu part_id |= (mmio_read_32(gic_frame + GICD_PIDR1_GICV3) << 8) & 0xf00; 427*91f16700Schasinglulu 428*91f16700Schasinglulu return part_id; 429*91f16700Schasinglulu } 430*91f16700Schasinglulu 431*91f16700Schasinglulu /******************************************************************************* 432*91f16700Schasinglulu * Helper function to return product ID and revision of GIC 433*91f16700Schasinglulu * @gicd_base: base address of the GIC distributor 434*91f16700Schasinglulu * @gic_prod_id: retrieved product id of GIC 435*91f16700Schasinglulu * @gic_rev: retrieved revision of GIC 436*91f16700Schasinglulu ******************************************************************************/ 437*91f16700Schasinglulu void gicv3_get_component_prodid_rev(const uintptr_t gicd_base, 438*91f16700Schasinglulu unsigned int *gic_prod_id, 439*91f16700Schasinglulu uint8_t *gic_rev) 440*91f16700Schasinglulu { 441*91f16700Schasinglulu unsigned int gicd_iidr; 442*91f16700Schasinglulu uint8_t gic_variant; 443*91f16700Schasinglulu 444*91f16700Schasinglulu gicd_iidr = gicd_read_iidr(gicd_base); 445*91f16700Schasinglulu *gic_prod_id = gicd_iidr >> IIDR_PRODUCT_ID_SHIFT; 446*91f16700Schasinglulu *gic_prod_id &= IIDR_PRODUCT_ID_MASK; 447*91f16700Schasinglulu 448*91f16700Schasinglulu gic_variant = gicd_iidr >> IIDR_VARIANT_SHIFT; 449*91f16700Schasinglulu gic_variant &= IIDR_VARIANT_MASK; 450*91f16700Schasinglulu 451*91f16700Schasinglulu *gic_rev = gicd_iidr >> IIDR_REV_SHIFT; 452*91f16700Schasinglulu *gic_rev &= IIDR_REV_MASK; 453*91f16700Schasinglulu 454*91f16700Schasinglulu /* 455*91f16700Schasinglulu * pack gic variant and gic_rev in 1 byte 456*91f16700Schasinglulu * gic_rev = gic_variant[7:4] and gic_rev[0:3] 457*91f16700Schasinglulu */ 458*91f16700Schasinglulu *gic_rev = *gic_rev | gic_variant << 0x4; 459*91f16700Schasinglulu 460*91f16700Schasinglulu } 461