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/gicv3.h> 16*91f16700Schasinglulu #include <lib/spinlock.h> 17*91f16700Schasinglulu #include <plat/common/platform.h> 18*91f16700Schasinglulu 19*91f16700Schasinglulu #include "gicv3_private.h" 20*91f16700Schasinglulu 21*91f16700Schasinglulu const gicv3_driver_data_t *gicv3_driver_data; 22*91f16700Schasinglulu 23*91f16700Schasinglulu /* 24*91f16700Schasinglulu * Spinlock to guard registers needing read-modify-write. APIs protected by this 25*91f16700Schasinglulu * spinlock are used either at boot time (when only a single CPU is active), or 26*91f16700Schasinglulu * when the system is fully coherent. 27*91f16700Schasinglulu */ 28*91f16700Schasinglulu static spinlock_t gic_lock; 29*91f16700Schasinglulu 30*91f16700Schasinglulu /* 31*91f16700Schasinglulu * Redistributor power operations are weakly bound so that they can be 32*91f16700Schasinglulu * overridden 33*91f16700Schasinglulu */ 34*91f16700Schasinglulu #pragma weak gicv3_rdistif_off 35*91f16700Schasinglulu #pragma weak gicv3_rdistif_on 36*91f16700Schasinglulu 37*91f16700Schasinglulu /* Check interrupt ID for SGI/(E)PPI and (E)SPIs */ 38*91f16700Schasinglulu static bool is_sgi_ppi(unsigned int id); 39*91f16700Schasinglulu 40*91f16700Schasinglulu /* 41*91f16700Schasinglulu * Helper macros to save and restore GICR and GICD registers 42*91f16700Schasinglulu * corresponding to their numbers to and from the context 43*91f16700Schasinglulu */ 44*91f16700Schasinglulu #define RESTORE_GICR_REG(base, ctx, name, i) \ 45*91f16700Schasinglulu gicr_write_##name((base), (i), (ctx)->gicr_##name[(i)]) 46*91f16700Schasinglulu 47*91f16700Schasinglulu #define SAVE_GICR_REG(base, ctx, name, i) \ 48*91f16700Schasinglulu (ctx)->gicr_##name[(i)] = gicr_read_##name((base), (i)) 49*91f16700Schasinglulu 50*91f16700Schasinglulu /* Helper macros to save and restore GICD registers to and from the context */ 51*91f16700Schasinglulu #define RESTORE_GICD_REGS(base, ctx, intr_num, reg, REG) \ 52*91f16700Schasinglulu do { \ 53*91f16700Schasinglulu for (unsigned int int_id = MIN_SPI_ID; int_id < (intr_num);\ 54*91f16700Schasinglulu int_id += (1U << REG##R_SHIFT)) { \ 55*91f16700Schasinglulu gicd_write_##reg((base), int_id, \ 56*91f16700Schasinglulu (ctx)->gicd_##reg[(int_id - MIN_SPI_ID) >> \ 57*91f16700Schasinglulu REG##R_SHIFT]); \ 58*91f16700Schasinglulu } \ 59*91f16700Schasinglulu } while (false) 60*91f16700Schasinglulu 61*91f16700Schasinglulu #define SAVE_GICD_REGS(base, ctx, intr_num, reg, REG) \ 62*91f16700Schasinglulu do { \ 63*91f16700Schasinglulu for (unsigned int int_id = MIN_SPI_ID; int_id < (intr_num);\ 64*91f16700Schasinglulu int_id += (1U << REG##R_SHIFT)) { \ 65*91f16700Schasinglulu (ctx)->gicd_##reg[(int_id - MIN_SPI_ID) >> \ 66*91f16700Schasinglulu REG##R_SHIFT] = gicd_read_##reg((base), int_id); \ 67*91f16700Schasinglulu } \ 68*91f16700Schasinglulu } while (false) 69*91f16700Schasinglulu 70*91f16700Schasinglulu #if GIC_EXT_INTID 71*91f16700Schasinglulu #define RESTORE_GICD_EREGS(base, ctx, intr_num, reg, REG) \ 72*91f16700Schasinglulu do { \ 73*91f16700Schasinglulu for (unsigned int int_id = MIN_ESPI_ID; int_id < (intr_num);\ 74*91f16700Schasinglulu int_id += (1U << REG##R_SHIFT)) { \ 75*91f16700Schasinglulu gicd_write_##reg((base), int_id, \ 76*91f16700Schasinglulu (ctx)->gicd_##reg[(int_id - (MIN_ESPI_ID - \ 77*91f16700Schasinglulu round_up(TOTAL_SPI_INTR_NUM, 1U << REG##R_SHIFT)))\ 78*91f16700Schasinglulu >> REG##R_SHIFT]); \ 79*91f16700Schasinglulu } \ 80*91f16700Schasinglulu } while (false) 81*91f16700Schasinglulu 82*91f16700Schasinglulu #define SAVE_GICD_EREGS(base, ctx, intr_num, reg, REG) \ 83*91f16700Schasinglulu do { \ 84*91f16700Schasinglulu for (unsigned int int_id = MIN_ESPI_ID; int_id < (intr_num);\ 85*91f16700Schasinglulu int_id += (1U << REG##R_SHIFT)) { \ 86*91f16700Schasinglulu (ctx)->gicd_##reg[(int_id - (MIN_ESPI_ID - \ 87*91f16700Schasinglulu round_up(TOTAL_SPI_INTR_NUM, 1U << REG##R_SHIFT)))\ 88*91f16700Schasinglulu >> REG##R_SHIFT] = gicd_read_##reg((base), int_id);\ 89*91f16700Schasinglulu } \ 90*91f16700Schasinglulu } while (false) 91*91f16700Schasinglulu #else 92*91f16700Schasinglulu #define SAVE_GICD_EREGS(base, ctx, intr_num, reg, REG) 93*91f16700Schasinglulu #define RESTORE_GICD_EREGS(base, ctx, intr_num, reg, REG) 94*91f16700Schasinglulu #endif /* GIC_EXT_INTID */ 95*91f16700Schasinglulu 96*91f16700Schasinglulu /******************************************************************************* 97*91f16700Schasinglulu * This function initialises the ARM GICv3 driver in EL3 with provided platform 98*91f16700Schasinglulu * inputs. 99*91f16700Schasinglulu ******************************************************************************/ 100*91f16700Schasinglulu void __init gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data) 101*91f16700Schasinglulu { 102*91f16700Schasinglulu unsigned int gic_version; 103*91f16700Schasinglulu unsigned int gicv2_compat; 104*91f16700Schasinglulu 105*91f16700Schasinglulu assert(plat_driver_data != NULL); 106*91f16700Schasinglulu assert(plat_driver_data->gicd_base != 0U); 107*91f16700Schasinglulu assert(plat_driver_data->rdistif_num != 0U); 108*91f16700Schasinglulu assert(plat_driver_data->rdistif_base_addrs != NULL); 109*91f16700Schasinglulu 110*91f16700Schasinglulu assert(IS_IN_EL3()); 111*91f16700Schasinglulu 112*91f16700Schasinglulu assert((plat_driver_data->interrupt_props_num != 0U) ? 113*91f16700Schasinglulu (plat_driver_data->interrupt_props != NULL) : 1); 114*91f16700Schasinglulu 115*91f16700Schasinglulu /* Check for system register support */ 116*91f16700Schasinglulu #ifndef __aarch64__ 117*91f16700Schasinglulu assert((read_id_pfr1() & 118*91f16700Schasinglulu (ID_PFR1_GIC_MASK << ID_PFR1_GIC_SHIFT)) != 0U); 119*91f16700Schasinglulu #else 120*91f16700Schasinglulu assert((read_id_aa64pfr0_el1() & 121*91f16700Schasinglulu (ID_AA64PFR0_GIC_MASK << ID_AA64PFR0_GIC_SHIFT)) != 0U); 122*91f16700Schasinglulu #endif /* !__aarch64__ */ 123*91f16700Schasinglulu 124*91f16700Schasinglulu gic_version = gicd_read_pidr2(plat_driver_data->gicd_base); 125*91f16700Schasinglulu gic_version >>= PIDR2_ARCH_REV_SHIFT; 126*91f16700Schasinglulu gic_version &= PIDR2_ARCH_REV_MASK; 127*91f16700Schasinglulu 128*91f16700Schasinglulu /* Check GIC version */ 129*91f16700Schasinglulu #if !GIC_ENABLE_V4_EXTN 130*91f16700Schasinglulu assert(gic_version == ARCH_REV_GICV3); 131*91f16700Schasinglulu #endif 132*91f16700Schasinglulu /* 133*91f16700Schasinglulu * Find out whether the GIC supports the GICv2 compatibility mode. 134*91f16700Schasinglulu * The ARE_S bit resets to 0 if supported 135*91f16700Schasinglulu */ 136*91f16700Schasinglulu gicv2_compat = gicd_read_ctlr(plat_driver_data->gicd_base); 137*91f16700Schasinglulu gicv2_compat >>= CTLR_ARE_S_SHIFT; 138*91f16700Schasinglulu gicv2_compat = gicv2_compat & CTLR_ARE_S_MASK; 139*91f16700Schasinglulu 140*91f16700Schasinglulu if (plat_driver_data->gicr_base != 0U) { 141*91f16700Schasinglulu /* 142*91f16700Schasinglulu * Find the base address of each implemented Redistributor interface. 143*91f16700Schasinglulu * The number of interfaces should be equal to the number of CPUs in the 144*91f16700Schasinglulu * system. The memory for saving these addresses has to be allocated by 145*91f16700Schasinglulu * the platform port 146*91f16700Schasinglulu */ 147*91f16700Schasinglulu gicv3_rdistif_base_addrs_probe(plat_driver_data->rdistif_base_addrs, 148*91f16700Schasinglulu plat_driver_data->rdistif_num, 149*91f16700Schasinglulu plat_driver_data->gicr_base, 150*91f16700Schasinglulu plat_driver_data->mpidr_to_core_pos); 151*91f16700Schasinglulu #if !HW_ASSISTED_COHERENCY 152*91f16700Schasinglulu /* 153*91f16700Schasinglulu * Flush the rdistif_base_addrs[] contents linked to the GICv3 driver. 154*91f16700Schasinglulu */ 155*91f16700Schasinglulu flush_dcache_range((uintptr_t)(plat_driver_data->rdistif_base_addrs), 156*91f16700Schasinglulu plat_driver_data->rdistif_num * 157*91f16700Schasinglulu sizeof(*(plat_driver_data->rdistif_base_addrs))); 158*91f16700Schasinglulu #endif 159*91f16700Schasinglulu } 160*91f16700Schasinglulu gicv3_driver_data = plat_driver_data; 161*91f16700Schasinglulu 162*91f16700Schasinglulu /* 163*91f16700Schasinglulu * The GIC driver data is initialized by the primary CPU with caches 164*91f16700Schasinglulu * enabled. When the secondary CPU boots up, it initializes the 165*91f16700Schasinglulu * GICC/GICR interface with the caches disabled. Hence flush the 166*91f16700Schasinglulu * driver data to ensure coherency. This is not required if the 167*91f16700Schasinglulu * platform has HW_ASSISTED_COHERENCY enabled. 168*91f16700Schasinglulu */ 169*91f16700Schasinglulu #if !HW_ASSISTED_COHERENCY 170*91f16700Schasinglulu flush_dcache_range((uintptr_t)&gicv3_driver_data, 171*91f16700Schasinglulu sizeof(gicv3_driver_data)); 172*91f16700Schasinglulu flush_dcache_range((uintptr_t)gicv3_driver_data, 173*91f16700Schasinglulu sizeof(*gicv3_driver_data)); 174*91f16700Schasinglulu #endif 175*91f16700Schasinglulu gicv3_check_erratas_applies(plat_driver_data->gicd_base); 176*91f16700Schasinglulu 177*91f16700Schasinglulu INFO("GICv%u with%s legacy support detected.\n", gic_version, 178*91f16700Schasinglulu (gicv2_compat == 0U) ? "" : "out"); 179*91f16700Schasinglulu INFO("ARM GICv%u driver initialized in EL3\n", gic_version); 180*91f16700Schasinglulu } 181*91f16700Schasinglulu 182*91f16700Schasinglulu /******************************************************************************* 183*91f16700Schasinglulu * This function initialises the GIC distributor interface based upon the data 184*91f16700Schasinglulu * provided by the platform while initialising the driver. 185*91f16700Schasinglulu ******************************************************************************/ 186*91f16700Schasinglulu void __init gicv3_distif_init(void) 187*91f16700Schasinglulu { 188*91f16700Schasinglulu unsigned int bitmap; 189*91f16700Schasinglulu 190*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 191*91f16700Schasinglulu assert(gicv3_driver_data->gicd_base != 0U); 192*91f16700Schasinglulu 193*91f16700Schasinglulu assert(IS_IN_EL3()); 194*91f16700Schasinglulu 195*91f16700Schasinglulu /* 196*91f16700Schasinglulu * Clear the "enable" bits for G0/G1S/G1NS interrupts before configuring 197*91f16700Schasinglulu * the ARE_S bit. The Distributor might generate a system error 198*91f16700Schasinglulu * otherwise. 199*91f16700Schasinglulu */ 200*91f16700Schasinglulu gicd_clr_ctlr(gicv3_driver_data->gicd_base, 201*91f16700Schasinglulu CTLR_ENABLE_G0_BIT | 202*91f16700Schasinglulu CTLR_ENABLE_G1S_BIT | 203*91f16700Schasinglulu CTLR_ENABLE_G1NS_BIT, 204*91f16700Schasinglulu RWP_TRUE); 205*91f16700Schasinglulu 206*91f16700Schasinglulu /* Set the ARE_S and ARE_NS bit now that interrupts have been disabled */ 207*91f16700Schasinglulu gicd_set_ctlr(gicv3_driver_data->gicd_base, 208*91f16700Schasinglulu CTLR_ARE_S_BIT | CTLR_ARE_NS_BIT, RWP_TRUE); 209*91f16700Schasinglulu 210*91f16700Schasinglulu /* Set the default attribute of all (E)SPIs */ 211*91f16700Schasinglulu gicv3_spis_config_defaults(gicv3_driver_data->gicd_base); 212*91f16700Schasinglulu 213*91f16700Schasinglulu bitmap = gicv3_secure_spis_config_props( 214*91f16700Schasinglulu gicv3_driver_data->gicd_base, 215*91f16700Schasinglulu gicv3_driver_data->interrupt_props, 216*91f16700Schasinglulu gicv3_driver_data->interrupt_props_num); 217*91f16700Schasinglulu 218*91f16700Schasinglulu /* Enable the secure (E)SPIs now that they have been configured */ 219*91f16700Schasinglulu gicd_set_ctlr(gicv3_driver_data->gicd_base, bitmap, RWP_TRUE); 220*91f16700Schasinglulu } 221*91f16700Schasinglulu 222*91f16700Schasinglulu /******************************************************************************* 223*91f16700Schasinglulu * This function initialises the GIC Redistributor interface of the calling CPU 224*91f16700Schasinglulu * (identified by the 'proc_num' parameter) based upon the data provided by the 225*91f16700Schasinglulu * platform while initialising the driver. 226*91f16700Schasinglulu ******************************************************************************/ 227*91f16700Schasinglulu void gicv3_rdistif_init(unsigned int proc_num) 228*91f16700Schasinglulu { 229*91f16700Schasinglulu uintptr_t gicr_base; 230*91f16700Schasinglulu unsigned int bitmap; 231*91f16700Schasinglulu uint32_t ctlr; 232*91f16700Schasinglulu 233*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 234*91f16700Schasinglulu assert(proc_num < gicv3_driver_data->rdistif_num); 235*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs != NULL); 236*91f16700Schasinglulu assert(gicv3_driver_data->gicd_base != 0U); 237*91f16700Schasinglulu 238*91f16700Schasinglulu ctlr = gicd_read_ctlr(gicv3_driver_data->gicd_base); 239*91f16700Schasinglulu assert((ctlr & CTLR_ARE_S_BIT) != 0U); 240*91f16700Schasinglulu 241*91f16700Schasinglulu assert(IS_IN_EL3()); 242*91f16700Schasinglulu 243*91f16700Schasinglulu /* Power on redistributor */ 244*91f16700Schasinglulu gicv3_rdistif_on(proc_num); 245*91f16700Schasinglulu 246*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 247*91f16700Schasinglulu assert(gicr_base != 0U); 248*91f16700Schasinglulu 249*91f16700Schasinglulu /* Set the default attribute of all SGIs and (E)PPIs */ 250*91f16700Schasinglulu gicv3_ppi_sgi_config_defaults(gicr_base); 251*91f16700Schasinglulu 252*91f16700Schasinglulu bitmap = gicv3_secure_ppi_sgi_config_props(gicr_base, 253*91f16700Schasinglulu gicv3_driver_data->interrupt_props, 254*91f16700Schasinglulu gicv3_driver_data->interrupt_props_num); 255*91f16700Schasinglulu 256*91f16700Schasinglulu /* Enable interrupt groups as required, if not already */ 257*91f16700Schasinglulu if ((ctlr & bitmap) != bitmap) { 258*91f16700Schasinglulu gicd_set_ctlr(gicv3_driver_data->gicd_base, bitmap, RWP_TRUE); 259*91f16700Schasinglulu } 260*91f16700Schasinglulu } 261*91f16700Schasinglulu 262*91f16700Schasinglulu /******************************************************************************* 263*91f16700Schasinglulu * Functions to perform power operations on GIC Redistributor 264*91f16700Schasinglulu ******************************************************************************/ 265*91f16700Schasinglulu void gicv3_rdistif_off(unsigned int proc_num) 266*91f16700Schasinglulu { 267*91f16700Schasinglulu } 268*91f16700Schasinglulu 269*91f16700Schasinglulu void gicv3_rdistif_on(unsigned int proc_num) 270*91f16700Schasinglulu { 271*91f16700Schasinglulu } 272*91f16700Schasinglulu 273*91f16700Schasinglulu /******************************************************************************* 274*91f16700Schasinglulu * This function enables the GIC CPU interface of the calling CPU using only 275*91f16700Schasinglulu * system register accesses. 276*91f16700Schasinglulu ******************************************************************************/ 277*91f16700Schasinglulu void gicv3_cpuif_enable(unsigned int proc_num) 278*91f16700Schasinglulu { 279*91f16700Schasinglulu uintptr_t gicr_base; 280*91f16700Schasinglulu u_register_t scr_el3; 281*91f16700Schasinglulu unsigned int icc_sre_el3; 282*91f16700Schasinglulu 283*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 284*91f16700Schasinglulu assert(proc_num < gicv3_driver_data->rdistif_num); 285*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs != NULL); 286*91f16700Schasinglulu assert(IS_IN_EL3()); 287*91f16700Schasinglulu 288*91f16700Schasinglulu /* Mark the connected core as awake */ 289*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 290*91f16700Schasinglulu gicv3_rdistif_mark_core_awake(gicr_base); 291*91f16700Schasinglulu 292*91f16700Schasinglulu /* Disable the legacy interrupt bypass */ 293*91f16700Schasinglulu icc_sre_el3 = ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT; 294*91f16700Schasinglulu 295*91f16700Schasinglulu /* 296*91f16700Schasinglulu * Enable system register access for EL3 and allow lower exception 297*91f16700Schasinglulu * levels to configure the same for themselves. If the legacy mode is 298*91f16700Schasinglulu * not supported, the SRE bit is RAO/WI 299*91f16700Schasinglulu */ 300*91f16700Schasinglulu icc_sre_el3 |= (ICC_SRE_EN_BIT | ICC_SRE_SRE_BIT); 301*91f16700Schasinglulu write_icc_sre_el3(read_icc_sre_el3() | icc_sre_el3); 302*91f16700Schasinglulu 303*91f16700Schasinglulu scr_el3 = read_scr_el3(); 304*91f16700Schasinglulu 305*91f16700Schasinglulu /* 306*91f16700Schasinglulu * Switch to NS state to write Non secure ICC_SRE_EL1 and 307*91f16700Schasinglulu * ICC_SRE_EL2 registers. 308*91f16700Schasinglulu */ 309*91f16700Schasinglulu write_scr_el3(scr_el3 | SCR_NS_BIT); 310*91f16700Schasinglulu isb(); 311*91f16700Schasinglulu 312*91f16700Schasinglulu write_icc_sre_el2(read_icc_sre_el2() | icc_sre_el3); 313*91f16700Schasinglulu write_icc_sre_el1(ICC_SRE_SRE_BIT); 314*91f16700Schasinglulu isb(); 315*91f16700Schasinglulu 316*91f16700Schasinglulu /* Switch to secure state. */ 317*91f16700Schasinglulu write_scr_el3(scr_el3 & (~SCR_NS_BIT)); 318*91f16700Schasinglulu isb(); 319*91f16700Schasinglulu 320*91f16700Schasinglulu /* Write the secure ICC_SRE_EL1 register */ 321*91f16700Schasinglulu write_icc_sre_el1(ICC_SRE_SRE_BIT); 322*91f16700Schasinglulu isb(); 323*91f16700Schasinglulu 324*91f16700Schasinglulu /* Program the idle priority in the PMR */ 325*91f16700Schasinglulu write_icc_pmr_el1(GIC_PRI_MASK); 326*91f16700Schasinglulu 327*91f16700Schasinglulu /* Enable Group0 interrupts */ 328*91f16700Schasinglulu write_icc_igrpen0_el1(IGRPEN1_EL1_ENABLE_G0_BIT); 329*91f16700Schasinglulu 330*91f16700Schasinglulu /* Enable Group1 Secure interrupts */ 331*91f16700Schasinglulu write_icc_igrpen1_el3(read_icc_igrpen1_el3() | 332*91f16700Schasinglulu IGRPEN1_EL3_ENABLE_G1S_BIT); 333*91f16700Schasinglulu /* and restore the original */ 334*91f16700Schasinglulu write_scr_el3(scr_el3); 335*91f16700Schasinglulu isb(); 336*91f16700Schasinglulu /* Add DSB to ensure visibility of System register writes */ 337*91f16700Schasinglulu dsb(); 338*91f16700Schasinglulu } 339*91f16700Schasinglulu 340*91f16700Schasinglulu /******************************************************************************* 341*91f16700Schasinglulu * This function disables the GIC CPU interface of the calling CPU using 342*91f16700Schasinglulu * only system register accesses. 343*91f16700Schasinglulu ******************************************************************************/ 344*91f16700Schasinglulu void gicv3_cpuif_disable(unsigned int proc_num) 345*91f16700Schasinglulu { 346*91f16700Schasinglulu uintptr_t gicr_base; 347*91f16700Schasinglulu 348*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 349*91f16700Schasinglulu assert(proc_num < gicv3_driver_data->rdistif_num); 350*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs != NULL); 351*91f16700Schasinglulu 352*91f16700Schasinglulu assert(IS_IN_EL3()); 353*91f16700Schasinglulu 354*91f16700Schasinglulu /* Disable legacy interrupt bypass */ 355*91f16700Schasinglulu write_icc_sre_el3(read_icc_sre_el3() | 356*91f16700Schasinglulu (ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT)); 357*91f16700Schasinglulu 358*91f16700Schasinglulu /* Disable Group0 interrupts */ 359*91f16700Schasinglulu write_icc_igrpen0_el1(read_icc_igrpen0_el1() & 360*91f16700Schasinglulu ~IGRPEN1_EL1_ENABLE_G0_BIT); 361*91f16700Schasinglulu 362*91f16700Schasinglulu /* Disable Group1 Secure and Non-Secure interrupts */ 363*91f16700Schasinglulu write_icc_igrpen1_el3(read_icc_igrpen1_el3() & 364*91f16700Schasinglulu ~(IGRPEN1_EL3_ENABLE_G1NS_BIT | 365*91f16700Schasinglulu IGRPEN1_EL3_ENABLE_G1S_BIT)); 366*91f16700Schasinglulu 367*91f16700Schasinglulu /* Synchronise accesses to group enable registers */ 368*91f16700Schasinglulu isb(); 369*91f16700Schasinglulu /* Add DSB to ensure visibility of System register writes */ 370*91f16700Schasinglulu dsb(); 371*91f16700Schasinglulu 372*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 373*91f16700Schasinglulu assert(gicr_base != 0UL); 374*91f16700Schasinglulu 375*91f16700Schasinglulu /* 376*91f16700Schasinglulu * dsb() already issued previously after clearing the CPU group 377*91f16700Schasinglulu * enabled, apply below workaround to toggle the "DPG*" 378*91f16700Schasinglulu * bits of GICR_CTLR register for unblocking event. 379*91f16700Schasinglulu */ 380*91f16700Schasinglulu gicv3_apply_errata_wa_2384374(gicr_base); 381*91f16700Schasinglulu 382*91f16700Schasinglulu /* Mark the connected core as asleep */ 383*91f16700Schasinglulu gicv3_rdistif_mark_core_asleep(gicr_base); 384*91f16700Schasinglulu } 385*91f16700Schasinglulu 386*91f16700Schasinglulu /******************************************************************************* 387*91f16700Schasinglulu * This function returns the id of the highest priority pending interrupt at 388*91f16700Schasinglulu * the GIC cpu interface. 389*91f16700Schasinglulu ******************************************************************************/ 390*91f16700Schasinglulu unsigned int gicv3_get_pending_interrupt_id(void) 391*91f16700Schasinglulu { 392*91f16700Schasinglulu unsigned int id; 393*91f16700Schasinglulu 394*91f16700Schasinglulu assert(IS_IN_EL3()); 395*91f16700Schasinglulu id = (uint32_t)read_icc_hppir0_el1() & HPPIR0_EL1_INTID_MASK; 396*91f16700Schasinglulu 397*91f16700Schasinglulu /* 398*91f16700Schasinglulu * If the ID is special identifier corresponding to G1S or G1NS 399*91f16700Schasinglulu * interrupt, then read the highest pending group 1 interrupt. 400*91f16700Schasinglulu */ 401*91f16700Schasinglulu if ((id == PENDING_G1S_INTID) || (id == PENDING_G1NS_INTID)) { 402*91f16700Schasinglulu return (uint32_t)read_icc_hppir1_el1() & HPPIR1_EL1_INTID_MASK; 403*91f16700Schasinglulu } 404*91f16700Schasinglulu 405*91f16700Schasinglulu return id; 406*91f16700Schasinglulu } 407*91f16700Schasinglulu 408*91f16700Schasinglulu /******************************************************************************* 409*91f16700Schasinglulu * This function returns the type of the highest priority pending interrupt at 410*91f16700Schasinglulu * the GIC cpu interface. The return values can be one of the following : 411*91f16700Schasinglulu * PENDING_G1S_INTID : The interrupt type is secure Group 1. 412*91f16700Schasinglulu * PENDING_G1NS_INTID : The interrupt type is non secure Group 1. 413*91f16700Schasinglulu * 0 - 1019 : The interrupt type is secure Group 0. 414*91f16700Schasinglulu * GIC_SPURIOUS_INTERRUPT : there is no pending interrupt with 415*91f16700Schasinglulu * sufficient priority to be signaled 416*91f16700Schasinglulu ******************************************************************************/ 417*91f16700Schasinglulu unsigned int gicv3_get_pending_interrupt_type(void) 418*91f16700Schasinglulu { 419*91f16700Schasinglulu assert(IS_IN_EL3()); 420*91f16700Schasinglulu return (uint32_t)read_icc_hppir0_el1() & HPPIR0_EL1_INTID_MASK; 421*91f16700Schasinglulu } 422*91f16700Schasinglulu 423*91f16700Schasinglulu /******************************************************************************* 424*91f16700Schasinglulu * This function returns the group that has been configured under by the 425*91f16700Schasinglulu * interrupt controller for the given interrupt id i.e. either group0 or group1 426*91f16700Schasinglulu * Secure / Non Secure. The return value can be one of the following : 427*91f16700Schasinglulu * INTR_GROUP0 : The interrupt type is a Secure Group 0 interrupt 428*91f16700Schasinglulu * INTR_GROUP1S : The interrupt type is a Secure Group 1 secure interrupt 429*91f16700Schasinglulu * INTR_GROUP1NS: The interrupt type is a Secure Group 1 non secure 430*91f16700Schasinglulu * interrupt. 431*91f16700Schasinglulu ******************************************************************************/ 432*91f16700Schasinglulu unsigned int gicv3_get_interrupt_group(unsigned int id, unsigned int proc_num) 433*91f16700Schasinglulu { 434*91f16700Schasinglulu unsigned int igroup, grpmodr; 435*91f16700Schasinglulu uintptr_t gicr_base; 436*91f16700Schasinglulu uintptr_t gicd_base; 437*91f16700Schasinglulu 438*91f16700Schasinglulu assert(IS_IN_EL3()); 439*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 440*91f16700Schasinglulu 441*91f16700Schasinglulu /* Ensure the parameters are valid */ 442*91f16700Schasinglulu assert((id < PENDING_G1S_INTID) || (id >= MIN_LPI_ID)); 443*91f16700Schasinglulu assert(proc_num < gicv3_driver_data->rdistif_num); 444*91f16700Schasinglulu 445*91f16700Schasinglulu /* All LPI interrupts are Group 1 non secure */ 446*91f16700Schasinglulu if (id >= MIN_LPI_ID) { 447*91f16700Schasinglulu return INTR_GROUP1NS; 448*91f16700Schasinglulu } 449*91f16700Schasinglulu 450*91f16700Schasinglulu /* Check interrupt ID */ 451*91f16700Schasinglulu if (is_sgi_ppi(id)) { 452*91f16700Schasinglulu /* SGIs: 0-15, PPIs: 16-31, EPPIs: 1056-1119 */ 453*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs != NULL); 454*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 455*91f16700Schasinglulu igroup = gicr_get_igroupr(gicr_base, id); 456*91f16700Schasinglulu grpmodr = gicr_get_igrpmodr(gicr_base, id); 457*91f16700Schasinglulu } else { 458*91f16700Schasinglulu /* SPIs: 32-1019, ESPIs: 4096-5119 */ 459*91f16700Schasinglulu assert(gicv3_driver_data->gicd_base != 0U); 460*91f16700Schasinglulu gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); 461*91f16700Schasinglulu igroup = gicd_get_igroupr(gicd_base, id); 462*91f16700Schasinglulu grpmodr = gicd_get_igrpmodr(gicd_base, id); 463*91f16700Schasinglulu } 464*91f16700Schasinglulu 465*91f16700Schasinglulu /* 466*91f16700Schasinglulu * If the IGROUP bit is set, then it is a Group 1 Non secure 467*91f16700Schasinglulu * interrupt 468*91f16700Schasinglulu */ 469*91f16700Schasinglulu if (igroup != 0U) { 470*91f16700Schasinglulu return INTR_GROUP1NS; 471*91f16700Schasinglulu } 472*91f16700Schasinglulu 473*91f16700Schasinglulu /* If the GRPMOD bit is set, then it is a Group 1 Secure interrupt */ 474*91f16700Schasinglulu if (grpmodr != 0U) { 475*91f16700Schasinglulu return INTR_GROUP1S; 476*91f16700Schasinglulu } 477*91f16700Schasinglulu 478*91f16700Schasinglulu /* Else it is a Group 0 Secure interrupt */ 479*91f16700Schasinglulu return INTR_GROUP0; 480*91f16700Schasinglulu } 481*91f16700Schasinglulu 482*91f16700Schasinglulu /***************************************************************************** 483*91f16700Schasinglulu * Function to save and disable the GIC ITS register context. The power 484*91f16700Schasinglulu * management of GIC ITS is implementation-defined and this function doesn't 485*91f16700Schasinglulu * save any memory structures required to support ITS. As the sequence to save 486*91f16700Schasinglulu * this state is implementation defined, it should be executed in platform 487*91f16700Schasinglulu * specific code. Calling this function alone and then powering down the GIC and 488*91f16700Schasinglulu * ITS without implementing the aforementioned platform specific code will 489*91f16700Schasinglulu * corrupt the ITS state. 490*91f16700Schasinglulu * 491*91f16700Schasinglulu * This function must be invoked after the GIC CPU interface is disabled. 492*91f16700Schasinglulu *****************************************************************************/ 493*91f16700Schasinglulu void gicv3_its_save_disable(uintptr_t gits_base, 494*91f16700Schasinglulu gicv3_its_ctx_t * const its_ctx) 495*91f16700Schasinglulu { 496*91f16700Schasinglulu unsigned int i; 497*91f16700Schasinglulu 498*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 499*91f16700Schasinglulu assert(IS_IN_EL3()); 500*91f16700Schasinglulu assert(its_ctx != NULL); 501*91f16700Schasinglulu assert(gits_base != 0U); 502*91f16700Schasinglulu 503*91f16700Schasinglulu its_ctx->gits_ctlr = gits_read_ctlr(gits_base); 504*91f16700Schasinglulu 505*91f16700Schasinglulu /* Disable the ITS */ 506*91f16700Schasinglulu gits_write_ctlr(gits_base, its_ctx->gits_ctlr & ~GITS_CTLR_ENABLED_BIT); 507*91f16700Schasinglulu 508*91f16700Schasinglulu /* Wait for quiescent state */ 509*91f16700Schasinglulu gits_wait_for_quiescent_bit(gits_base); 510*91f16700Schasinglulu 511*91f16700Schasinglulu its_ctx->gits_cbaser = gits_read_cbaser(gits_base); 512*91f16700Schasinglulu its_ctx->gits_cwriter = gits_read_cwriter(gits_base); 513*91f16700Schasinglulu 514*91f16700Schasinglulu for (i = 0U; i < ARRAY_SIZE(its_ctx->gits_baser); i++) { 515*91f16700Schasinglulu its_ctx->gits_baser[i] = gits_read_baser(gits_base, i); 516*91f16700Schasinglulu } 517*91f16700Schasinglulu } 518*91f16700Schasinglulu 519*91f16700Schasinglulu /***************************************************************************** 520*91f16700Schasinglulu * Function to restore the GIC ITS register context. The power 521*91f16700Schasinglulu * management of GIC ITS is implementation defined and this function doesn't 522*91f16700Schasinglulu * restore any memory structures required to support ITS. The assumption is 523*91f16700Schasinglulu * that these structures are in memory and are retained during system suspend. 524*91f16700Schasinglulu * 525*91f16700Schasinglulu * This must be invoked before the GIC CPU interface is enabled. 526*91f16700Schasinglulu *****************************************************************************/ 527*91f16700Schasinglulu void gicv3_its_restore(uintptr_t gits_base, 528*91f16700Schasinglulu const gicv3_its_ctx_t * const its_ctx) 529*91f16700Schasinglulu { 530*91f16700Schasinglulu unsigned int i; 531*91f16700Schasinglulu 532*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 533*91f16700Schasinglulu assert(IS_IN_EL3()); 534*91f16700Schasinglulu assert(its_ctx != NULL); 535*91f16700Schasinglulu assert(gits_base != 0U); 536*91f16700Schasinglulu 537*91f16700Schasinglulu /* Assert that the GITS is disabled and quiescent */ 538*91f16700Schasinglulu assert((gits_read_ctlr(gits_base) & GITS_CTLR_ENABLED_BIT) == 0U); 539*91f16700Schasinglulu assert((gits_read_ctlr(gits_base) & GITS_CTLR_QUIESCENT_BIT) != 0U); 540*91f16700Schasinglulu 541*91f16700Schasinglulu gits_write_cbaser(gits_base, its_ctx->gits_cbaser); 542*91f16700Schasinglulu gits_write_cwriter(gits_base, its_ctx->gits_cwriter); 543*91f16700Schasinglulu 544*91f16700Schasinglulu for (i = 0U; i < ARRAY_SIZE(its_ctx->gits_baser); i++) { 545*91f16700Schasinglulu gits_write_baser(gits_base, i, its_ctx->gits_baser[i]); 546*91f16700Schasinglulu } 547*91f16700Schasinglulu 548*91f16700Schasinglulu /* Restore the ITS CTLR but leave the ITS disabled */ 549*91f16700Schasinglulu gits_write_ctlr(gits_base, its_ctx->gits_ctlr & ~GITS_CTLR_ENABLED_BIT); 550*91f16700Schasinglulu } 551*91f16700Schasinglulu 552*91f16700Schasinglulu /***************************************************************************** 553*91f16700Schasinglulu * Function to save the GIC Redistributor register context. This function 554*91f16700Schasinglulu * must be invoked after CPU interface disable and prior to Distributor save. 555*91f16700Schasinglulu *****************************************************************************/ 556*91f16700Schasinglulu void gicv3_rdistif_save(unsigned int proc_num, 557*91f16700Schasinglulu gicv3_redist_ctx_t * const rdist_ctx) 558*91f16700Schasinglulu { 559*91f16700Schasinglulu uintptr_t gicr_base; 560*91f16700Schasinglulu unsigned int i, ppi_regs_num, regs_num; 561*91f16700Schasinglulu 562*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 563*91f16700Schasinglulu assert(proc_num < gicv3_driver_data->rdistif_num); 564*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs != NULL); 565*91f16700Schasinglulu assert(IS_IN_EL3()); 566*91f16700Schasinglulu assert(rdist_ctx != NULL); 567*91f16700Schasinglulu 568*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 569*91f16700Schasinglulu 570*91f16700Schasinglulu #if GIC_EXT_INTID 571*91f16700Schasinglulu /* Calculate number of PPI registers */ 572*91f16700Schasinglulu ppi_regs_num = (unsigned int)((gicr_read_typer(gicr_base) >> 573*91f16700Schasinglulu TYPER_PPI_NUM_SHIFT) & TYPER_PPI_NUM_MASK) + 1; 574*91f16700Schasinglulu /* All other values except PPInum [0-2] are reserved */ 575*91f16700Schasinglulu if (ppi_regs_num > 3U) { 576*91f16700Schasinglulu ppi_regs_num = 1U; 577*91f16700Schasinglulu } 578*91f16700Schasinglulu #else 579*91f16700Schasinglulu ppi_regs_num = 1U; 580*91f16700Schasinglulu #endif 581*91f16700Schasinglulu /* 582*91f16700Schasinglulu * Wait for any write to GICR_CTLR to complete before trying to save any 583*91f16700Schasinglulu * state. 584*91f16700Schasinglulu */ 585*91f16700Schasinglulu gicr_wait_for_pending_write(gicr_base); 586*91f16700Schasinglulu 587*91f16700Schasinglulu rdist_ctx->gicr_ctlr = gicr_read_ctlr(gicr_base); 588*91f16700Schasinglulu 589*91f16700Schasinglulu rdist_ctx->gicr_propbaser = gicr_read_propbaser(gicr_base); 590*91f16700Schasinglulu rdist_ctx->gicr_pendbaser = gicr_read_pendbaser(gicr_base); 591*91f16700Schasinglulu 592*91f16700Schasinglulu /* 32 interrupt IDs per register */ 593*91f16700Schasinglulu for (i = 0U; i < ppi_regs_num; ++i) { 594*91f16700Schasinglulu SAVE_GICR_REG(gicr_base, rdist_ctx, igroupr, i); 595*91f16700Schasinglulu SAVE_GICR_REG(gicr_base, rdist_ctx, isenabler, i); 596*91f16700Schasinglulu SAVE_GICR_REG(gicr_base, rdist_ctx, ispendr, i); 597*91f16700Schasinglulu SAVE_GICR_REG(gicr_base, rdist_ctx, isactiver, i); 598*91f16700Schasinglulu SAVE_GICR_REG(gicr_base, rdist_ctx, igrpmodr, i); 599*91f16700Schasinglulu } 600*91f16700Schasinglulu 601*91f16700Schasinglulu /* 16 interrupt IDs per GICR_ICFGR register */ 602*91f16700Schasinglulu regs_num = ppi_regs_num << 1; 603*91f16700Schasinglulu for (i = 0U; i < regs_num; ++i) { 604*91f16700Schasinglulu SAVE_GICR_REG(gicr_base, rdist_ctx, icfgr, i); 605*91f16700Schasinglulu } 606*91f16700Schasinglulu 607*91f16700Schasinglulu rdist_ctx->gicr_nsacr = gicr_read_nsacr(gicr_base); 608*91f16700Schasinglulu 609*91f16700Schasinglulu /* 4 interrupt IDs per GICR_IPRIORITYR register */ 610*91f16700Schasinglulu regs_num = ppi_regs_num << 3; 611*91f16700Schasinglulu for (i = 0U; i < regs_num; ++i) { 612*91f16700Schasinglulu rdist_ctx->gicr_ipriorityr[i] = 613*91f16700Schasinglulu gicr_ipriorityr_read(gicr_base, i); 614*91f16700Schasinglulu } 615*91f16700Schasinglulu 616*91f16700Schasinglulu /* 617*91f16700Schasinglulu * Call the pre-save hook that implements the IMP DEF sequence that may 618*91f16700Schasinglulu * be required on some GIC implementations. As this may need to access 619*91f16700Schasinglulu * the Redistributor registers, we pass it proc_num. 620*91f16700Schasinglulu */ 621*91f16700Schasinglulu gicv3_distif_pre_save(proc_num); 622*91f16700Schasinglulu } 623*91f16700Schasinglulu 624*91f16700Schasinglulu /***************************************************************************** 625*91f16700Schasinglulu * Function to restore the GIC Redistributor register context. We disable 626*91f16700Schasinglulu * LPI and per-cpu interrupts before we start restore of the Redistributor. 627*91f16700Schasinglulu * This function must be invoked after Distributor restore but prior to 628*91f16700Schasinglulu * CPU interface enable. The pending and active interrupts are restored 629*91f16700Schasinglulu * after the interrupts are fully configured and enabled. 630*91f16700Schasinglulu *****************************************************************************/ 631*91f16700Schasinglulu void gicv3_rdistif_init_restore(unsigned int proc_num, 632*91f16700Schasinglulu const gicv3_redist_ctx_t * const rdist_ctx) 633*91f16700Schasinglulu { 634*91f16700Schasinglulu uintptr_t gicr_base; 635*91f16700Schasinglulu unsigned int i, ppi_regs_num, regs_num; 636*91f16700Schasinglulu 637*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 638*91f16700Schasinglulu assert(proc_num < gicv3_driver_data->rdistif_num); 639*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs != NULL); 640*91f16700Schasinglulu assert(IS_IN_EL3()); 641*91f16700Schasinglulu assert(rdist_ctx != NULL); 642*91f16700Schasinglulu 643*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 644*91f16700Schasinglulu 645*91f16700Schasinglulu #if GIC_EXT_INTID 646*91f16700Schasinglulu /* Calculate number of PPI registers */ 647*91f16700Schasinglulu ppi_regs_num = (unsigned int)((gicr_read_typer(gicr_base) >> 648*91f16700Schasinglulu TYPER_PPI_NUM_SHIFT) & TYPER_PPI_NUM_MASK) + 1; 649*91f16700Schasinglulu /* All other values except PPInum [0-2] are reserved */ 650*91f16700Schasinglulu if (ppi_regs_num > 3U) { 651*91f16700Schasinglulu ppi_regs_num = 1U; 652*91f16700Schasinglulu } 653*91f16700Schasinglulu #else 654*91f16700Schasinglulu ppi_regs_num = 1U; 655*91f16700Schasinglulu #endif 656*91f16700Schasinglulu /* Power on redistributor */ 657*91f16700Schasinglulu gicv3_rdistif_on(proc_num); 658*91f16700Schasinglulu 659*91f16700Schasinglulu /* 660*91f16700Schasinglulu * Call the post-restore hook that implements the IMP DEF sequence that 661*91f16700Schasinglulu * may be required on some GIC implementations. As this may need to 662*91f16700Schasinglulu * access the Redistributor registers, we pass it proc_num. 663*91f16700Schasinglulu */ 664*91f16700Schasinglulu gicv3_distif_post_restore(proc_num); 665*91f16700Schasinglulu 666*91f16700Schasinglulu /* 667*91f16700Schasinglulu * Disable all SGIs (imp. def.)/(E)PPIs before configuring them. 668*91f16700Schasinglulu * This is a more scalable approach as it avoids clearing the enable 669*91f16700Schasinglulu * bits in the GICD_CTLR. 670*91f16700Schasinglulu */ 671*91f16700Schasinglulu for (i = 0U; i < ppi_regs_num; ++i) { 672*91f16700Schasinglulu gicr_write_icenabler(gicr_base, i, ~0U); 673*91f16700Schasinglulu } 674*91f16700Schasinglulu 675*91f16700Schasinglulu /* Wait for pending writes to GICR_ICENABLER */ 676*91f16700Schasinglulu gicr_wait_for_pending_write(gicr_base); 677*91f16700Schasinglulu 678*91f16700Schasinglulu /* 679*91f16700Schasinglulu * Disable the LPIs to avoid unpredictable behavior when writing to 680*91f16700Schasinglulu * GICR_PROPBASER and GICR_PENDBASER. 681*91f16700Schasinglulu */ 682*91f16700Schasinglulu gicr_write_ctlr(gicr_base, 683*91f16700Schasinglulu rdist_ctx->gicr_ctlr & ~(GICR_CTLR_EN_LPIS_BIT)); 684*91f16700Schasinglulu 685*91f16700Schasinglulu /* Restore registers' content */ 686*91f16700Schasinglulu gicr_write_propbaser(gicr_base, rdist_ctx->gicr_propbaser); 687*91f16700Schasinglulu gicr_write_pendbaser(gicr_base, rdist_ctx->gicr_pendbaser); 688*91f16700Schasinglulu 689*91f16700Schasinglulu /* 32 interrupt IDs per register */ 690*91f16700Schasinglulu for (i = 0U; i < ppi_regs_num; ++i) { 691*91f16700Schasinglulu RESTORE_GICR_REG(gicr_base, rdist_ctx, igroupr, i); 692*91f16700Schasinglulu RESTORE_GICR_REG(gicr_base, rdist_ctx, igrpmodr, i); 693*91f16700Schasinglulu } 694*91f16700Schasinglulu 695*91f16700Schasinglulu /* 4 interrupt IDs per GICR_IPRIORITYR register */ 696*91f16700Schasinglulu regs_num = ppi_regs_num << 3; 697*91f16700Schasinglulu for (i = 0U; i < regs_num; ++i) { 698*91f16700Schasinglulu gicr_ipriorityr_write(gicr_base, i, 699*91f16700Schasinglulu rdist_ctx->gicr_ipriorityr[i]); 700*91f16700Schasinglulu } 701*91f16700Schasinglulu 702*91f16700Schasinglulu /* 16 interrupt IDs per GICR_ICFGR register */ 703*91f16700Schasinglulu regs_num = ppi_regs_num << 1; 704*91f16700Schasinglulu for (i = 0U; i < regs_num; ++i) { 705*91f16700Schasinglulu RESTORE_GICR_REG(gicr_base, rdist_ctx, icfgr, i); 706*91f16700Schasinglulu } 707*91f16700Schasinglulu 708*91f16700Schasinglulu gicr_write_nsacr(gicr_base, rdist_ctx->gicr_nsacr); 709*91f16700Schasinglulu 710*91f16700Schasinglulu /* Restore after group and priorities are set. 711*91f16700Schasinglulu * 32 interrupt IDs per register 712*91f16700Schasinglulu */ 713*91f16700Schasinglulu for (i = 0U; i < ppi_regs_num; ++i) { 714*91f16700Schasinglulu RESTORE_GICR_REG(gicr_base, rdist_ctx, ispendr, i); 715*91f16700Schasinglulu RESTORE_GICR_REG(gicr_base, rdist_ctx, isactiver, i); 716*91f16700Schasinglulu } 717*91f16700Schasinglulu 718*91f16700Schasinglulu /* 719*91f16700Schasinglulu * Wait for all writes to the Distributor to complete before enabling 720*91f16700Schasinglulu * the SGI and (E)PPIs. 721*91f16700Schasinglulu */ 722*91f16700Schasinglulu gicr_wait_for_upstream_pending_write(gicr_base); 723*91f16700Schasinglulu 724*91f16700Schasinglulu /* 32 interrupt IDs per GICR_ISENABLER register */ 725*91f16700Schasinglulu for (i = 0U; i < ppi_regs_num; ++i) { 726*91f16700Schasinglulu RESTORE_GICR_REG(gicr_base, rdist_ctx, isenabler, i); 727*91f16700Schasinglulu } 728*91f16700Schasinglulu 729*91f16700Schasinglulu /* 730*91f16700Schasinglulu * Restore GICR_CTLR.Enable_LPIs bit and wait for pending writes in case 731*91f16700Schasinglulu * the first write to GICR_CTLR was still in flight (this write only 732*91f16700Schasinglulu * restores GICR_CTLR.Enable_LPIs and no waiting is required for this 733*91f16700Schasinglulu * bit). 734*91f16700Schasinglulu */ 735*91f16700Schasinglulu gicr_write_ctlr(gicr_base, rdist_ctx->gicr_ctlr); 736*91f16700Schasinglulu gicr_wait_for_pending_write(gicr_base); 737*91f16700Schasinglulu } 738*91f16700Schasinglulu 739*91f16700Schasinglulu /***************************************************************************** 740*91f16700Schasinglulu * Function to save the GIC Distributor register context. This function 741*91f16700Schasinglulu * must be invoked after CPU interface disable and Redistributor save. 742*91f16700Schasinglulu *****************************************************************************/ 743*91f16700Schasinglulu void gicv3_distif_save(gicv3_dist_ctx_t * const dist_ctx) 744*91f16700Schasinglulu { 745*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 746*91f16700Schasinglulu assert(gicv3_driver_data->gicd_base != 0U); 747*91f16700Schasinglulu assert(IS_IN_EL3()); 748*91f16700Schasinglulu assert(dist_ctx != NULL); 749*91f16700Schasinglulu 750*91f16700Schasinglulu uintptr_t gicd_base = gicv3_driver_data->gicd_base; 751*91f16700Schasinglulu unsigned int num_ints = gicv3_get_spi_limit(gicd_base); 752*91f16700Schasinglulu #if GIC_EXT_INTID 753*91f16700Schasinglulu unsigned int num_eints = gicv3_get_espi_limit(gicd_base); 754*91f16700Schasinglulu #endif 755*91f16700Schasinglulu 756*91f16700Schasinglulu /* Wait for pending write to complete */ 757*91f16700Schasinglulu gicd_wait_for_pending_write(gicd_base); 758*91f16700Schasinglulu 759*91f16700Schasinglulu /* Save the GICD_CTLR */ 760*91f16700Schasinglulu dist_ctx->gicd_ctlr = gicd_read_ctlr(gicd_base); 761*91f16700Schasinglulu 762*91f16700Schasinglulu /* Save GICD_IGROUPR for INTIDs 32 - 1019 */ 763*91f16700Schasinglulu SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUP); 764*91f16700Schasinglulu 765*91f16700Schasinglulu /* Save GICD_IGROUPRE for INTIDs 4096 - 5119 */ 766*91f16700Schasinglulu SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, igroupr, IGROUP); 767*91f16700Schasinglulu 768*91f16700Schasinglulu /* Save GICD_ISENABLER for INT_IDs 32 - 1019 */ 769*91f16700Schasinglulu SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, isenabler, ISENABLE); 770*91f16700Schasinglulu 771*91f16700Schasinglulu /* Save GICD_ISENABLERE for INT_IDs 4096 - 5119 */ 772*91f16700Schasinglulu SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, isenabler, ISENABLE); 773*91f16700Schasinglulu 774*91f16700Schasinglulu /* Save GICD_ISPENDR for INTIDs 32 - 1019 */ 775*91f16700Schasinglulu SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, ispendr, ISPEND); 776*91f16700Schasinglulu 777*91f16700Schasinglulu /* Save GICD_ISPENDRE for INTIDs 4096 - 5119 */ 778*91f16700Schasinglulu SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, ispendr, ISPEND); 779*91f16700Schasinglulu 780*91f16700Schasinglulu /* Save GICD_ISACTIVER for INTIDs 32 - 1019 */ 781*91f16700Schasinglulu SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, isactiver, ISACTIVE); 782*91f16700Schasinglulu 783*91f16700Schasinglulu /* Save GICD_ISACTIVERE for INTIDs 4096 - 5119 */ 784*91f16700Schasinglulu SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, isactiver, ISACTIVE); 785*91f16700Schasinglulu 786*91f16700Schasinglulu /* Save GICD_IPRIORITYR for INTIDs 32 - 1019 */ 787*91f16700Schasinglulu SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, ipriorityr, IPRIORITY); 788*91f16700Schasinglulu 789*91f16700Schasinglulu /* Save GICD_IPRIORITYRE for INTIDs 4096 - 5119 */ 790*91f16700Schasinglulu SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, ipriorityr, IPRIORITY); 791*91f16700Schasinglulu 792*91f16700Schasinglulu /* Save GICD_ICFGR for INTIDs 32 - 1019 */ 793*91f16700Schasinglulu SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, icfgr, ICFG); 794*91f16700Schasinglulu 795*91f16700Schasinglulu /* Save GICD_ICFGRE for INTIDs 4096 - 5119 */ 796*91f16700Schasinglulu SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, icfgr, ICFG); 797*91f16700Schasinglulu 798*91f16700Schasinglulu /* Save GICD_IGRPMODR for INTIDs 32 - 1019 */ 799*91f16700Schasinglulu SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, igrpmodr, IGRPMOD); 800*91f16700Schasinglulu 801*91f16700Schasinglulu /* Save GICD_IGRPMODRE for INTIDs 4096 - 5119 */ 802*91f16700Schasinglulu SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, igrpmodr, IGRPMOD); 803*91f16700Schasinglulu 804*91f16700Schasinglulu /* Save GICD_NSACR for INTIDs 32 - 1019 */ 805*91f16700Schasinglulu SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, nsacr, NSAC); 806*91f16700Schasinglulu 807*91f16700Schasinglulu /* Save GICD_NSACRE for INTIDs 4096 - 5119 */ 808*91f16700Schasinglulu SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, nsacr, NSAC); 809*91f16700Schasinglulu 810*91f16700Schasinglulu /* Save GICD_IROUTER for INTIDs 32 - 1019 */ 811*91f16700Schasinglulu SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, irouter, IROUTE); 812*91f16700Schasinglulu 813*91f16700Schasinglulu /* Save GICD_IROUTERE for INTIDs 4096 - 5119 */ 814*91f16700Schasinglulu SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, irouter, IROUTE); 815*91f16700Schasinglulu 816*91f16700Schasinglulu /* 817*91f16700Schasinglulu * GICD_ITARGETSR<n> and GICD_SPENDSGIR<n> are RAZ/WI when 818*91f16700Schasinglulu * GICD_CTLR.ARE_(S|NS) bits are set which is the case for our GICv3 819*91f16700Schasinglulu * driver. 820*91f16700Schasinglulu */ 821*91f16700Schasinglulu } 822*91f16700Schasinglulu 823*91f16700Schasinglulu /***************************************************************************** 824*91f16700Schasinglulu * Function to restore the GIC Distributor register context. We disable G0, G1S 825*91f16700Schasinglulu * and G1NS interrupt groups before we start restore of the Distributor. This 826*91f16700Schasinglulu * function must be invoked prior to Redistributor restore and CPU interface 827*91f16700Schasinglulu * enable. The pending and active interrupts are restored after the interrupts 828*91f16700Schasinglulu * are fully configured and enabled. 829*91f16700Schasinglulu *****************************************************************************/ 830*91f16700Schasinglulu void gicv3_distif_init_restore(const gicv3_dist_ctx_t * const dist_ctx) 831*91f16700Schasinglulu { 832*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 833*91f16700Schasinglulu assert(gicv3_driver_data->gicd_base != 0U); 834*91f16700Schasinglulu assert(IS_IN_EL3()); 835*91f16700Schasinglulu assert(dist_ctx != NULL); 836*91f16700Schasinglulu 837*91f16700Schasinglulu uintptr_t gicd_base = gicv3_driver_data->gicd_base; 838*91f16700Schasinglulu 839*91f16700Schasinglulu /* 840*91f16700Schasinglulu * Clear the "enable" bits for G0/G1S/G1NS interrupts before configuring 841*91f16700Schasinglulu * the ARE_S bit. The Distributor might generate a system error 842*91f16700Schasinglulu * otherwise. 843*91f16700Schasinglulu */ 844*91f16700Schasinglulu gicd_clr_ctlr(gicd_base, 845*91f16700Schasinglulu CTLR_ENABLE_G0_BIT | 846*91f16700Schasinglulu CTLR_ENABLE_G1S_BIT | 847*91f16700Schasinglulu CTLR_ENABLE_G1NS_BIT, 848*91f16700Schasinglulu RWP_TRUE); 849*91f16700Schasinglulu 850*91f16700Schasinglulu /* Set the ARE_S and ARE_NS bit now that interrupts have been disabled */ 851*91f16700Schasinglulu gicd_set_ctlr(gicd_base, CTLR_ARE_S_BIT | CTLR_ARE_NS_BIT, RWP_TRUE); 852*91f16700Schasinglulu 853*91f16700Schasinglulu unsigned int num_ints = gicv3_get_spi_limit(gicd_base); 854*91f16700Schasinglulu #if GIC_EXT_INTID 855*91f16700Schasinglulu unsigned int num_eints = gicv3_get_espi_limit(gicd_base); 856*91f16700Schasinglulu #endif 857*91f16700Schasinglulu /* Restore GICD_IGROUPR for INTIDs 32 - 1019 */ 858*91f16700Schasinglulu RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUP); 859*91f16700Schasinglulu 860*91f16700Schasinglulu /* Restore GICD_IGROUPRE for INTIDs 4096 - 5119 */ 861*91f16700Schasinglulu RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, igroupr, IGROUP); 862*91f16700Schasinglulu 863*91f16700Schasinglulu /* Restore GICD_IPRIORITYR for INTIDs 32 - 1019 */ 864*91f16700Schasinglulu RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, ipriorityr, IPRIORITY); 865*91f16700Schasinglulu 866*91f16700Schasinglulu /* Restore GICD_IPRIORITYRE for INTIDs 4096 - 5119 */ 867*91f16700Schasinglulu RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, ipriorityr, IPRIORITY); 868*91f16700Schasinglulu 869*91f16700Schasinglulu /* Restore GICD_ICFGR for INTIDs 32 - 1019 */ 870*91f16700Schasinglulu RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, icfgr, ICFG); 871*91f16700Schasinglulu 872*91f16700Schasinglulu /* Restore GICD_ICFGRE for INTIDs 4096 - 5119 */ 873*91f16700Schasinglulu RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, icfgr, ICFG); 874*91f16700Schasinglulu 875*91f16700Schasinglulu /* Restore GICD_IGRPMODR for INTIDs 32 - 1019 */ 876*91f16700Schasinglulu RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igrpmodr, IGRPMOD); 877*91f16700Schasinglulu 878*91f16700Schasinglulu /* Restore GICD_IGRPMODRE for INTIDs 4096 - 5119 */ 879*91f16700Schasinglulu RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, igrpmodr, IGRPMOD); 880*91f16700Schasinglulu 881*91f16700Schasinglulu /* Restore GICD_NSACR for INTIDs 32 - 1019 */ 882*91f16700Schasinglulu RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, nsacr, NSAC); 883*91f16700Schasinglulu 884*91f16700Schasinglulu /* Restore GICD_NSACRE for INTIDs 4096 - 5119 */ 885*91f16700Schasinglulu RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, nsacr, NSAC); 886*91f16700Schasinglulu 887*91f16700Schasinglulu /* Restore GICD_IROUTER for INTIDs 32 - 1019 */ 888*91f16700Schasinglulu RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, irouter, IROUTE); 889*91f16700Schasinglulu 890*91f16700Schasinglulu /* Restore GICD_IROUTERE for INTIDs 4096 - 5119 */ 891*91f16700Schasinglulu RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, irouter, IROUTE); 892*91f16700Schasinglulu 893*91f16700Schasinglulu /* 894*91f16700Schasinglulu * Restore ISENABLER(E), ISPENDR(E) and ISACTIVER(E) after 895*91f16700Schasinglulu * the interrupts are configured. 896*91f16700Schasinglulu */ 897*91f16700Schasinglulu 898*91f16700Schasinglulu /* Restore GICD_ISENABLER for INT_IDs 32 - 1019 */ 899*91f16700Schasinglulu RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, isenabler, ISENABLE); 900*91f16700Schasinglulu 901*91f16700Schasinglulu /* Restore GICD_ISENABLERE for INT_IDs 4096 - 5119 */ 902*91f16700Schasinglulu RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, isenabler, ISENABLE); 903*91f16700Schasinglulu 904*91f16700Schasinglulu /* Restore GICD_ISPENDR for INTIDs 32 - 1019 */ 905*91f16700Schasinglulu RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, ispendr, ISPEND); 906*91f16700Schasinglulu 907*91f16700Schasinglulu /* Restore GICD_ISPENDRE for INTIDs 4096 - 5119 */ 908*91f16700Schasinglulu RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, ispendr, ISPEND); 909*91f16700Schasinglulu 910*91f16700Schasinglulu /* Restore GICD_ISACTIVER for INTIDs 32 - 1019 */ 911*91f16700Schasinglulu RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, isactiver, ISACTIVE); 912*91f16700Schasinglulu 913*91f16700Schasinglulu /* Restore GICD_ISACTIVERE for INTIDs 4096 - 5119 */ 914*91f16700Schasinglulu RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, isactiver, ISACTIVE); 915*91f16700Schasinglulu 916*91f16700Schasinglulu /* Restore the GICD_CTLR */ 917*91f16700Schasinglulu gicd_write_ctlr(gicd_base, dist_ctx->gicd_ctlr); 918*91f16700Schasinglulu gicd_wait_for_pending_write(gicd_base); 919*91f16700Schasinglulu } 920*91f16700Schasinglulu 921*91f16700Schasinglulu /******************************************************************************* 922*91f16700Schasinglulu * This function gets the priority of the interrupt the processor is currently 923*91f16700Schasinglulu * servicing. 924*91f16700Schasinglulu ******************************************************************************/ 925*91f16700Schasinglulu unsigned int gicv3_get_running_priority(void) 926*91f16700Schasinglulu { 927*91f16700Schasinglulu return (unsigned int)read_icc_rpr_el1(); 928*91f16700Schasinglulu } 929*91f16700Schasinglulu 930*91f16700Schasinglulu /******************************************************************************* 931*91f16700Schasinglulu * This function checks if the interrupt identified by id is active (whether the 932*91f16700Schasinglulu * state is either active, or active and pending). The proc_num is used if the 933*91f16700Schasinglulu * interrupt is SGI or (E)PPI and programs the corresponding Redistributor 934*91f16700Schasinglulu * interface. 935*91f16700Schasinglulu ******************************************************************************/ 936*91f16700Schasinglulu unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num) 937*91f16700Schasinglulu { 938*91f16700Schasinglulu uintptr_t gicd_base; 939*91f16700Schasinglulu 940*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 941*91f16700Schasinglulu assert(gicv3_driver_data->gicd_base != 0U); 942*91f16700Schasinglulu assert(proc_num < gicv3_driver_data->rdistif_num); 943*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs != NULL); 944*91f16700Schasinglulu 945*91f16700Schasinglulu /* Check interrupt ID */ 946*91f16700Schasinglulu if (is_sgi_ppi(id)) { 947*91f16700Schasinglulu /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ 948*91f16700Schasinglulu return gicr_get_isactiver( 949*91f16700Schasinglulu gicv3_driver_data->rdistif_base_addrs[proc_num], id); 950*91f16700Schasinglulu } 951*91f16700Schasinglulu 952*91f16700Schasinglulu /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ 953*91f16700Schasinglulu gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); 954*91f16700Schasinglulu return gicd_get_isactiver(gicd_base, id); 955*91f16700Schasinglulu } 956*91f16700Schasinglulu 957*91f16700Schasinglulu /******************************************************************************* 958*91f16700Schasinglulu * This function enables the interrupt identified by id. The proc_num 959*91f16700Schasinglulu * is used if the interrupt is SGI or PPI, and programs the corresponding 960*91f16700Schasinglulu * Redistributor interface. 961*91f16700Schasinglulu ******************************************************************************/ 962*91f16700Schasinglulu void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num) 963*91f16700Schasinglulu { 964*91f16700Schasinglulu uintptr_t gicd_base; 965*91f16700Schasinglulu 966*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 967*91f16700Schasinglulu assert(gicv3_driver_data->gicd_base != 0U); 968*91f16700Schasinglulu assert(proc_num < gicv3_driver_data->rdistif_num); 969*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs != NULL); 970*91f16700Schasinglulu 971*91f16700Schasinglulu /* 972*91f16700Schasinglulu * Ensure that any shared variable updates depending on out of band 973*91f16700Schasinglulu * interrupt trigger are observed before enabling interrupt. 974*91f16700Schasinglulu */ 975*91f16700Schasinglulu dsbishst(); 976*91f16700Schasinglulu 977*91f16700Schasinglulu /* Check interrupt ID */ 978*91f16700Schasinglulu if (is_sgi_ppi(id)) { 979*91f16700Schasinglulu /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ 980*91f16700Schasinglulu gicr_set_isenabler( 981*91f16700Schasinglulu gicv3_driver_data->rdistif_base_addrs[proc_num], id); 982*91f16700Schasinglulu } else { 983*91f16700Schasinglulu /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ 984*91f16700Schasinglulu gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); 985*91f16700Schasinglulu gicd_set_isenabler(gicd_base, id); 986*91f16700Schasinglulu } 987*91f16700Schasinglulu } 988*91f16700Schasinglulu 989*91f16700Schasinglulu /******************************************************************************* 990*91f16700Schasinglulu * This function disables the interrupt identified by id. The proc_num 991*91f16700Schasinglulu * is used if the interrupt is SGI or PPI, and programs the corresponding 992*91f16700Schasinglulu * Redistributor interface. 993*91f16700Schasinglulu ******************************************************************************/ 994*91f16700Schasinglulu void gicv3_disable_interrupt(unsigned int id, unsigned int proc_num) 995*91f16700Schasinglulu { 996*91f16700Schasinglulu uintptr_t gicd_base; 997*91f16700Schasinglulu 998*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 999*91f16700Schasinglulu assert(gicv3_driver_data->gicd_base != 0U); 1000*91f16700Schasinglulu assert(proc_num < gicv3_driver_data->rdistif_num); 1001*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs != NULL); 1002*91f16700Schasinglulu 1003*91f16700Schasinglulu /* 1004*91f16700Schasinglulu * Disable interrupt, and ensure that any shared variable updates 1005*91f16700Schasinglulu * depending on out of band interrupt trigger are observed afterwards. 1006*91f16700Schasinglulu */ 1007*91f16700Schasinglulu 1008*91f16700Schasinglulu /* Check interrupt ID */ 1009*91f16700Schasinglulu if (is_sgi_ppi(id)) { 1010*91f16700Schasinglulu /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ 1011*91f16700Schasinglulu gicr_set_icenabler( 1012*91f16700Schasinglulu gicv3_driver_data->rdistif_base_addrs[proc_num], id); 1013*91f16700Schasinglulu 1014*91f16700Schasinglulu /* Write to clear enable requires waiting for pending writes */ 1015*91f16700Schasinglulu gicr_wait_for_pending_write( 1016*91f16700Schasinglulu gicv3_driver_data->rdistif_base_addrs[proc_num]); 1017*91f16700Schasinglulu } else { 1018*91f16700Schasinglulu /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ 1019*91f16700Schasinglulu gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); 1020*91f16700Schasinglulu gicd_set_icenabler(gicd_base, id); 1021*91f16700Schasinglulu 1022*91f16700Schasinglulu /* Write to clear enable requires waiting for pending writes */ 1023*91f16700Schasinglulu gicd_wait_for_pending_write(gicd_base); 1024*91f16700Schasinglulu } 1025*91f16700Schasinglulu 1026*91f16700Schasinglulu dsbishst(); 1027*91f16700Schasinglulu } 1028*91f16700Schasinglulu 1029*91f16700Schasinglulu /******************************************************************************* 1030*91f16700Schasinglulu * This function sets the interrupt priority as supplied for the given interrupt 1031*91f16700Schasinglulu * id. 1032*91f16700Schasinglulu ******************************************************************************/ 1033*91f16700Schasinglulu void gicv3_set_interrupt_priority(unsigned int id, unsigned int proc_num, 1034*91f16700Schasinglulu unsigned int priority) 1035*91f16700Schasinglulu { 1036*91f16700Schasinglulu uintptr_t gicr_base; 1037*91f16700Schasinglulu uintptr_t gicd_base; 1038*91f16700Schasinglulu 1039*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 1040*91f16700Schasinglulu assert(gicv3_driver_data->gicd_base != 0U); 1041*91f16700Schasinglulu assert(proc_num < gicv3_driver_data->rdistif_num); 1042*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs != NULL); 1043*91f16700Schasinglulu 1044*91f16700Schasinglulu /* Check interrupt ID */ 1045*91f16700Schasinglulu if (is_sgi_ppi(id)) { 1046*91f16700Schasinglulu /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ 1047*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 1048*91f16700Schasinglulu gicr_set_ipriorityr(gicr_base, id, priority); 1049*91f16700Schasinglulu } else { 1050*91f16700Schasinglulu /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ 1051*91f16700Schasinglulu gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); 1052*91f16700Schasinglulu gicd_set_ipriorityr(gicd_base, id, priority); 1053*91f16700Schasinglulu } 1054*91f16700Schasinglulu } 1055*91f16700Schasinglulu 1056*91f16700Schasinglulu /******************************************************************************* 1057*91f16700Schasinglulu * This function assigns group for the interrupt identified by id. The proc_num 1058*91f16700Schasinglulu * is used if the interrupt is SGI or (E)PPI, and programs the corresponding 1059*91f16700Schasinglulu * Redistributor interface. The group can be any of GICV3_INTR_GROUP* 1060*91f16700Schasinglulu ******************************************************************************/ 1061*91f16700Schasinglulu void gicv3_set_interrupt_group(unsigned int id, unsigned int proc_num, 1062*91f16700Schasinglulu unsigned int group) 1063*91f16700Schasinglulu { 1064*91f16700Schasinglulu bool igroup = false, grpmod = false; 1065*91f16700Schasinglulu uintptr_t gicr_base; 1066*91f16700Schasinglulu uintptr_t gicd_base; 1067*91f16700Schasinglulu 1068*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 1069*91f16700Schasinglulu assert(gicv3_driver_data->gicd_base != 0U); 1070*91f16700Schasinglulu assert(proc_num < gicv3_driver_data->rdistif_num); 1071*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs != NULL); 1072*91f16700Schasinglulu 1073*91f16700Schasinglulu switch (group) { 1074*91f16700Schasinglulu case INTR_GROUP1S: 1075*91f16700Schasinglulu igroup = false; 1076*91f16700Schasinglulu grpmod = true; 1077*91f16700Schasinglulu break; 1078*91f16700Schasinglulu case INTR_GROUP0: 1079*91f16700Schasinglulu igroup = false; 1080*91f16700Schasinglulu grpmod = false; 1081*91f16700Schasinglulu break; 1082*91f16700Schasinglulu case INTR_GROUP1NS: 1083*91f16700Schasinglulu igroup = true; 1084*91f16700Schasinglulu grpmod = false; 1085*91f16700Schasinglulu break; 1086*91f16700Schasinglulu default: 1087*91f16700Schasinglulu assert(false); 1088*91f16700Schasinglulu break; 1089*91f16700Schasinglulu } 1090*91f16700Schasinglulu 1091*91f16700Schasinglulu /* Check interrupt ID */ 1092*91f16700Schasinglulu if (is_sgi_ppi(id)) { 1093*91f16700Schasinglulu /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ 1094*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 1095*91f16700Schasinglulu 1096*91f16700Schasinglulu igroup ? gicr_set_igroupr(gicr_base, id) : 1097*91f16700Schasinglulu gicr_clr_igroupr(gicr_base, id); 1098*91f16700Schasinglulu grpmod ? gicr_set_igrpmodr(gicr_base, id) : 1099*91f16700Schasinglulu gicr_clr_igrpmodr(gicr_base, id); 1100*91f16700Schasinglulu } else { 1101*91f16700Schasinglulu /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ 1102*91f16700Schasinglulu 1103*91f16700Schasinglulu /* Serialize read-modify-write to Distributor registers */ 1104*91f16700Schasinglulu spin_lock(&gic_lock); 1105*91f16700Schasinglulu 1106*91f16700Schasinglulu gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); 1107*91f16700Schasinglulu 1108*91f16700Schasinglulu igroup ? gicd_set_igroupr(gicd_base, id) : 1109*91f16700Schasinglulu gicd_clr_igroupr(gicd_base, id); 1110*91f16700Schasinglulu grpmod ? gicd_set_igrpmodr(gicd_base, id) : 1111*91f16700Schasinglulu gicd_clr_igrpmodr(gicd_base, id); 1112*91f16700Schasinglulu 1113*91f16700Schasinglulu spin_unlock(&gic_lock); 1114*91f16700Schasinglulu } 1115*91f16700Schasinglulu } 1116*91f16700Schasinglulu 1117*91f16700Schasinglulu /******************************************************************************* 1118*91f16700Schasinglulu * This function raises the specified SGI of the specified group. 1119*91f16700Schasinglulu * 1120*91f16700Schasinglulu * The target parameter must be a valid MPIDR in the system. 1121*91f16700Schasinglulu ******************************************************************************/ 1122*91f16700Schasinglulu void gicv3_raise_sgi(unsigned int sgi_num, gicv3_irq_group_t group, 1123*91f16700Schasinglulu u_register_t target) 1124*91f16700Schasinglulu { 1125*91f16700Schasinglulu unsigned int tgt, aff3, aff2, aff1, aff0; 1126*91f16700Schasinglulu uint64_t sgi_val; 1127*91f16700Schasinglulu 1128*91f16700Schasinglulu /* Verify interrupt number is in the SGI range */ 1129*91f16700Schasinglulu assert((sgi_num >= MIN_SGI_ID) && (sgi_num < MIN_PPI_ID)); 1130*91f16700Schasinglulu 1131*91f16700Schasinglulu /* Extract affinity fields from target */ 1132*91f16700Schasinglulu aff0 = MPIDR_AFFLVL0_VAL(target); 1133*91f16700Schasinglulu aff1 = MPIDR_AFFLVL1_VAL(target); 1134*91f16700Schasinglulu aff2 = MPIDR_AFFLVL2_VAL(target); 1135*91f16700Schasinglulu aff3 = MPIDR_AFFLVL3_VAL(target); 1136*91f16700Schasinglulu 1137*91f16700Schasinglulu /* 1138*91f16700Schasinglulu * Make target list from affinity 0, and ensure GICv3 SGI can target 1139*91f16700Schasinglulu * this PE. 1140*91f16700Schasinglulu */ 1141*91f16700Schasinglulu assert(aff0 < GICV3_MAX_SGI_TARGETS); 1142*91f16700Schasinglulu tgt = BIT_32(aff0); 1143*91f16700Schasinglulu 1144*91f16700Schasinglulu /* Raise SGI to PE specified by its affinity */ 1145*91f16700Schasinglulu sgi_val = GICV3_SGIR_VALUE(aff3, aff2, aff1, sgi_num, SGIR_IRM_TO_AFF, 1146*91f16700Schasinglulu tgt); 1147*91f16700Schasinglulu 1148*91f16700Schasinglulu /* 1149*91f16700Schasinglulu * Ensure that any shared variable updates depending on out of band 1150*91f16700Schasinglulu * interrupt trigger are observed before raising SGI. 1151*91f16700Schasinglulu */ 1152*91f16700Schasinglulu dsbishst(); 1153*91f16700Schasinglulu 1154*91f16700Schasinglulu switch (group) { 1155*91f16700Schasinglulu case GICV3_G0: 1156*91f16700Schasinglulu write_icc_sgi0r_el1(sgi_val); 1157*91f16700Schasinglulu break; 1158*91f16700Schasinglulu case GICV3_G1NS: 1159*91f16700Schasinglulu write_icc_asgi1r(sgi_val); 1160*91f16700Schasinglulu break; 1161*91f16700Schasinglulu case GICV3_G1S: 1162*91f16700Schasinglulu write_icc_sgi1r(sgi_val); 1163*91f16700Schasinglulu break; 1164*91f16700Schasinglulu default: 1165*91f16700Schasinglulu assert(false); 1166*91f16700Schasinglulu break; 1167*91f16700Schasinglulu } 1168*91f16700Schasinglulu 1169*91f16700Schasinglulu isb(); 1170*91f16700Schasinglulu } 1171*91f16700Schasinglulu 1172*91f16700Schasinglulu /******************************************************************************* 1173*91f16700Schasinglulu * This function sets the interrupt routing for the given (E)SPI interrupt id. 1174*91f16700Schasinglulu * The interrupt routing is specified in routing mode and mpidr. 1175*91f16700Schasinglulu * 1176*91f16700Schasinglulu * The routing mode can be either of: 1177*91f16700Schasinglulu * - GICV3_IRM_ANY 1178*91f16700Schasinglulu * - GICV3_IRM_PE 1179*91f16700Schasinglulu * 1180*91f16700Schasinglulu * The mpidr is the affinity of the PE to which the interrupt will be routed, 1181*91f16700Schasinglulu * and is ignored for routing mode GICV3_IRM_ANY. 1182*91f16700Schasinglulu ******************************************************************************/ 1183*91f16700Schasinglulu void gicv3_set_spi_routing(unsigned int id, unsigned int irm, u_register_t mpidr) 1184*91f16700Schasinglulu { 1185*91f16700Schasinglulu unsigned long long aff; 1186*91f16700Schasinglulu uint64_t router; 1187*91f16700Schasinglulu uintptr_t gicd_base; 1188*91f16700Schasinglulu 1189*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 1190*91f16700Schasinglulu assert(gicv3_driver_data->gicd_base != 0U); 1191*91f16700Schasinglulu 1192*91f16700Schasinglulu assert((irm == GICV3_IRM_ANY) || (irm == GICV3_IRM_PE)); 1193*91f16700Schasinglulu 1194*91f16700Schasinglulu assert(IS_SPI(id)); 1195*91f16700Schasinglulu 1196*91f16700Schasinglulu aff = gicd_irouter_val_from_mpidr(mpidr, irm); 1197*91f16700Schasinglulu gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); 1198*91f16700Schasinglulu gicd_write_irouter(gicd_base, id, aff); 1199*91f16700Schasinglulu 1200*91f16700Schasinglulu /* 1201*91f16700Schasinglulu * In implementations that do not require 1 of N distribution of SPIs, 1202*91f16700Schasinglulu * IRM might be RAZ/WI. Read back and verify IRM bit. 1203*91f16700Schasinglulu */ 1204*91f16700Schasinglulu if (irm == GICV3_IRM_ANY) { 1205*91f16700Schasinglulu router = gicd_read_irouter(gicd_base, id); 1206*91f16700Schasinglulu if (((router >> IROUTER_IRM_SHIFT) & IROUTER_IRM_MASK) == 0U) { 1207*91f16700Schasinglulu ERROR("GICv3 implementation doesn't support routing ANY\n"); 1208*91f16700Schasinglulu panic(); 1209*91f16700Schasinglulu } 1210*91f16700Schasinglulu } 1211*91f16700Schasinglulu } 1212*91f16700Schasinglulu 1213*91f16700Schasinglulu /******************************************************************************* 1214*91f16700Schasinglulu * This function clears the pending status of an interrupt identified by id. 1215*91f16700Schasinglulu * The proc_num is used if the interrupt is SGI or (E)PPI, and programs the 1216*91f16700Schasinglulu * corresponding Redistributor interface. 1217*91f16700Schasinglulu ******************************************************************************/ 1218*91f16700Schasinglulu void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num) 1219*91f16700Schasinglulu { 1220*91f16700Schasinglulu uintptr_t gicd_base; 1221*91f16700Schasinglulu 1222*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 1223*91f16700Schasinglulu assert(gicv3_driver_data->gicd_base != 0U); 1224*91f16700Schasinglulu assert(proc_num < gicv3_driver_data->rdistif_num); 1225*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs != NULL); 1226*91f16700Schasinglulu 1227*91f16700Schasinglulu /* 1228*91f16700Schasinglulu * Clear pending interrupt, and ensure that any shared variable updates 1229*91f16700Schasinglulu * depending on out of band interrupt trigger are observed afterwards. 1230*91f16700Schasinglulu */ 1231*91f16700Schasinglulu 1232*91f16700Schasinglulu /* Check interrupt ID */ 1233*91f16700Schasinglulu if (is_sgi_ppi(id)) { 1234*91f16700Schasinglulu /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ 1235*91f16700Schasinglulu gicr_set_icpendr( 1236*91f16700Schasinglulu gicv3_driver_data->rdistif_base_addrs[proc_num], id); 1237*91f16700Schasinglulu } else { 1238*91f16700Schasinglulu /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ 1239*91f16700Schasinglulu gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); 1240*91f16700Schasinglulu gicd_set_icpendr(gicd_base, id); 1241*91f16700Schasinglulu } 1242*91f16700Schasinglulu 1243*91f16700Schasinglulu dsbishst(); 1244*91f16700Schasinglulu } 1245*91f16700Schasinglulu 1246*91f16700Schasinglulu /******************************************************************************* 1247*91f16700Schasinglulu * This function sets the pending status of an interrupt identified by id. 1248*91f16700Schasinglulu * The proc_num is used if the interrupt is SGI or PPI and programs the 1249*91f16700Schasinglulu * corresponding Redistributor interface. 1250*91f16700Schasinglulu ******************************************************************************/ 1251*91f16700Schasinglulu void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num) 1252*91f16700Schasinglulu { 1253*91f16700Schasinglulu uintptr_t gicd_base; 1254*91f16700Schasinglulu 1255*91f16700Schasinglulu assert(gicv3_driver_data != NULL); 1256*91f16700Schasinglulu assert(gicv3_driver_data->gicd_base != 0U); 1257*91f16700Schasinglulu assert(proc_num < gicv3_driver_data->rdistif_num); 1258*91f16700Schasinglulu assert(gicv3_driver_data->rdistif_base_addrs != NULL); 1259*91f16700Schasinglulu 1260*91f16700Schasinglulu /* 1261*91f16700Schasinglulu * Ensure that any shared variable updates depending on out of band 1262*91f16700Schasinglulu * interrupt trigger are observed before setting interrupt pending. 1263*91f16700Schasinglulu */ 1264*91f16700Schasinglulu dsbishst(); 1265*91f16700Schasinglulu 1266*91f16700Schasinglulu /* Check interrupt ID */ 1267*91f16700Schasinglulu if (is_sgi_ppi(id)) { 1268*91f16700Schasinglulu /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ 1269*91f16700Schasinglulu gicr_set_ispendr( 1270*91f16700Schasinglulu gicv3_driver_data->rdistif_base_addrs[proc_num], id); 1271*91f16700Schasinglulu } else { 1272*91f16700Schasinglulu /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ 1273*91f16700Schasinglulu gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); 1274*91f16700Schasinglulu gicd_set_ispendr(gicd_base, id); 1275*91f16700Schasinglulu } 1276*91f16700Schasinglulu } 1277*91f16700Schasinglulu 1278*91f16700Schasinglulu /******************************************************************************* 1279*91f16700Schasinglulu * This function sets the PMR register with the supplied value. Returns the 1280*91f16700Schasinglulu * original PMR. 1281*91f16700Schasinglulu ******************************************************************************/ 1282*91f16700Schasinglulu unsigned int gicv3_set_pmr(unsigned int mask) 1283*91f16700Schasinglulu { 1284*91f16700Schasinglulu unsigned int old_mask; 1285*91f16700Schasinglulu 1286*91f16700Schasinglulu old_mask = (unsigned int)read_icc_pmr_el1(); 1287*91f16700Schasinglulu 1288*91f16700Schasinglulu /* 1289*91f16700Schasinglulu * Order memory updates w.r.t. PMR write, and ensure they're visible 1290*91f16700Schasinglulu * before potential out of band interrupt trigger because of PMR update. 1291*91f16700Schasinglulu * PMR system register writes are self-synchronizing, so no ISB required 1292*91f16700Schasinglulu * thereafter. 1293*91f16700Schasinglulu */ 1294*91f16700Schasinglulu dsbishst(); 1295*91f16700Schasinglulu write_icc_pmr_el1(mask); 1296*91f16700Schasinglulu 1297*91f16700Schasinglulu return old_mask; 1298*91f16700Schasinglulu } 1299*91f16700Schasinglulu 1300*91f16700Schasinglulu /******************************************************************************* 1301*91f16700Schasinglulu * This function delegates the responsibility of discovering the corresponding 1302*91f16700Schasinglulu * Redistributor frames to each CPU itself. It is a modified version of 1303*91f16700Schasinglulu * gicv3_rdistif_base_addrs_probe() and is executed by each CPU in the platform 1304*91f16700Schasinglulu * unlike the previous way in which only the Primary CPU did the discovery of 1305*91f16700Schasinglulu * all the Redistributor frames for every CPU. It also handles the scenario in 1306*91f16700Schasinglulu * which the frames of various CPUs are not contiguous in physical memory. 1307*91f16700Schasinglulu ******************************************************************************/ 1308*91f16700Schasinglulu int gicv3_rdistif_probe(const uintptr_t gicr_frame) 1309*91f16700Schasinglulu { 1310*91f16700Schasinglulu u_register_t mpidr, mpidr_self; 1311*91f16700Schasinglulu unsigned int proc_num; 1312*91f16700Schasinglulu uint64_t typer_val; 1313*91f16700Schasinglulu uintptr_t rdistif_base; 1314*91f16700Schasinglulu bool gicr_frame_found = false; 1315*91f16700Schasinglulu 1316*91f16700Schasinglulu assert(gicv3_driver_data->gicr_base == 0U); 1317*91f16700Schasinglulu 1318*91f16700Schasinglulu if (plat_can_cmo()) { 1319*91f16700Schasinglulu /* Ensure this function is called with Data Cache enabled */ 1320*91f16700Schasinglulu #ifndef __aarch64__ 1321*91f16700Schasinglulu assert((read_sctlr() & SCTLR_C_BIT) != 0U); 1322*91f16700Schasinglulu #else 1323*91f16700Schasinglulu assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U); 1324*91f16700Schasinglulu #endif /* !__aarch64__ */ 1325*91f16700Schasinglulu } 1326*91f16700Schasinglulu 1327*91f16700Schasinglulu mpidr_self = read_mpidr_el1() & MPIDR_AFFINITY_MASK; 1328*91f16700Schasinglulu rdistif_base = gicr_frame; 1329*91f16700Schasinglulu do { 1330*91f16700Schasinglulu typer_val = gicr_read_typer(rdistif_base); 1331*91f16700Schasinglulu mpidr = mpidr_from_gicr_typer(typer_val); 1332*91f16700Schasinglulu if (gicv3_driver_data->mpidr_to_core_pos != NULL) { 1333*91f16700Schasinglulu proc_num = gicv3_driver_data->mpidr_to_core_pos(mpidr); 1334*91f16700Schasinglulu } else { 1335*91f16700Schasinglulu proc_num = (unsigned int)(typer_val >> 1336*91f16700Schasinglulu TYPER_PROC_NUM_SHIFT) & TYPER_PROC_NUM_MASK; 1337*91f16700Schasinglulu } 1338*91f16700Schasinglulu if (mpidr == mpidr_self) { 1339*91f16700Schasinglulu /* The base address doesn't need to be initialized on 1340*91f16700Schasinglulu * every warm boot. 1341*91f16700Schasinglulu */ 1342*91f16700Schasinglulu if (gicv3_driver_data->rdistif_base_addrs[proc_num] 1343*91f16700Schasinglulu != 0U) { 1344*91f16700Schasinglulu return 0; 1345*91f16700Schasinglulu } 1346*91f16700Schasinglulu gicv3_driver_data->rdistif_base_addrs[proc_num] = 1347*91f16700Schasinglulu rdistif_base; 1348*91f16700Schasinglulu gicr_frame_found = true; 1349*91f16700Schasinglulu break; 1350*91f16700Schasinglulu } 1351*91f16700Schasinglulu rdistif_base += gicv3_redist_size(typer_val); 1352*91f16700Schasinglulu } while ((typer_val & TYPER_LAST_BIT) == 0U); 1353*91f16700Schasinglulu 1354*91f16700Schasinglulu if (!gicr_frame_found) { 1355*91f16700Schasinglulu return -1; 1356*91f16700Schasinglulu } 1357*91f16700Schasinglulu 1358*91f16700Schasinglulu /* 1359*91f16700Schasinglulu * Flush the driver data to ensure coherency. This is 1360*91f16700Schasinglulu * not required if platform has HW_ASSISTED_COHERENCY 1361*91f16700Schasinglulu * enabled. 1362*91f16700Schasinglulu */ 1363*91f16700Schasinglulu #if !HW_ASSISTED_COHERENCY 1364*91f16700Schasinglulu /* 1365*91f16700Schasinglulu * Flush the rdistif_base_addrs[] contents linked to the GICv3 driver. 1366*91f16700Schasinglulu */ 1367*91f16700Schasinglulu flush_dcache_range((uintptr_t)&(gicv3_driver_data->rdistif_base_addrs[proc_num]), 1368*91f16700Schasinglulu sizeof(*(gicv3_driver_data->rdistif_base_addrs))); 1369*91f16700Schasinglulu #endif 1370*91f16700Schasinglulu return 0; /* Found matching GICR frame */ 1371*91f16700Schasinglulu } 1372*91f16700Schasinglulu 1373*91f16700Schasinglulu /****************************************************************************** 1374*91f16700Schasinglulu * This function checks the interrupt ID and returns true for SGIs and (E)PPIs 1375*91f16700Schasinglulu * and false for (E)SPIs IDs. 1376*91f16700Schasinglulu *****************************************************************************/ 1377*91f16700Schasinglulu static bool is_sgi_ppi(unsigned int id) 1378*91f16700Schasinglulu { 1379*91f16700Schasinglulu /* SGIs: 0-15, PPIs: 16-31, EPPIs: 1056-1119 */ 1380*91f16700Schasinglulu if (IS_SGI_PPI(id)) { 1381*91f16700Schasinglulu return true; 1382*91f16700Schasinglulu } 1383*91f16700Schasinglulu 1384*91f16700Schasinglulu /* SPIs: 32-1019, ESPIs: 4096-5119 */ 1385*91f16700Schasinglulu if (IS_SPI(id)) { 1386*91f16700Schasinglulu return false; 1387*91f16700Schasinglulu } 1388*91f16700Schasinglulu 1389*91f16700Schasinglulu assert(false); 1390*91f16700Schasinglulu panic(); 1391*91f16700Schasinglulu } 1392