1 /* 2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch_helpers.h> 8 #include <arm_gic.h> 9 #include <assert.h> 10 #include <bl_common.h> 11 #include <debug.h> 12 #include <gic_v2.h> 13 #include <interrupt_mgmt.h> 14 #include <platform.h> 15 #include <stdint.h> 16 #include <tegra_def.h> 17 #include <tegra_private.h> 18 19 /* Value used to initialize Non-Secure IRQ priorities four at a time */ 20 #define GICD_IPRIORITYR_DEF_VAL \ 21 (GIC_HIGHEST_NS_PRIORITY | \ 22 (GIC_HIGHEST_NS_PRIORITY << 8) | \ 23 (GIC_HIGHEST_NS_PRIORITY << 16) | \ 24 (GIC_HIGHEST_NS_PRIORITY << 24)) 25 26 static const irq_sec_cfg_t *g_irq_sec_ptr; 27 static uint32_t g_num_irqs; 28 29 /******************************************************************************* 30 * Place the cpu interface in a state where it can never make a cpu exit wfi as 31 * as result of an asserted interrupt. This is critical for powering down a cpu 32 ******************************************************************************/ 33 void tegra_gic_cpuif_deactivate(void) 34 { 35 uint32_t val; 36 37 /* Disable secure, non-secure interrupts and disable their bypass */ 38 val = gicc_read_ctlr(TEGRA_GICC_BASE); 39 val &= ~(ENABLE_GRP0 | ENABLE_GRP1); 40 val |= FIQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP0; 41 val |= IRQ_BYP_DIS_GRP0 | IRQ_BYP_DIS_GRP1; 42 gicc_write_ctlr(TEGRA_GICC_BASE, val); 43 } 44 45 /******************************************************************************* 46 * Enable secure interrupts and set the priority mask register to allow all 47 * interrupts to trickle in. 48 ******************************************************************************/ 49 static void tegra_gic_cpuif_setup(uint32_t gicc_base) 50 { 51 uint32_t val; 52 53 val = ENABLE_GRP0 | ENABLE_GRP1 | FIQ_EN | FIQ_BYP_DIS_GRP0; 54 val |= IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP1 | IRQ_BYP_DIS_GRP1; 55 56 gicc_write_ctlr(gicc_base, val); 57 gicc_write_pmr(gicc_base, GIC_PRI_MASK); 58 } 59 60 /******************************************************************************* 61 * Per cpu gic distributor setup which will be done by all cpus after a cold 62 * boot/hotplug. This marks out the secure interrupts & enables them. 63 ******************************************************************************/ 64 static void tegra_gic_pcpu_distif_setup(uint32_t gicd_base) 65 { 66 uint32_t index, sec_ppi_sgi_mask = 0; 67 68 assert(gicd_base != 0U); 69 70 /* Setup PPI priorities doing four at a time */ 71 for (index = 0U; index < 32U; index += 4U) { 72 gicd_write_ipriorityr(gicd_base, index, 73 GICD_IPRIORITYR_DEF_VAL); 74 } 75 76 /* 77 * Invert the bitmask to create a mask for non-secure PPIs and 78 * SGIs. Program the GICD_IGROUPR0 with this bit mask. This write will 79 * update the GICR_IGROUPR0 as well in case we are running on a GICv3 80 * system. This is critical if GICD_CTLR.ARE_NS=1. 81 */ 82 gicd_write_igroupr(gicd_base, 0, ~sec_ppi_sgi_mask); 83 } 84 85 /******************************************************************************* 86 * Global gic distributor setup which will be done by the primary cpu after a 87 * cold boot. It marks out the non secure SPIs, PPIs & SGIs and enables them. 88 * It then enables the secure GIC distributor interface. 89 ******************************************************************************/ 90 static void tegra_gic_distif_setup(uint32_t gicd_base) 91 { 92 uint32_t index, num_ints, irq_num; 93 uint8_t target_cpus; 94 uint32_t val; 95 96 /* 97 * Mark out non-secure interrupts. Calculate number of 98 * IGROUPR registers to consider. Will be equal to the 99 * number of IT_LINES 100 */ 101 num_ints = gicd_read_typer(gicd_base) & IT_LINES_NO_MASK; 102 num_ints = (num_ints + 1U) << 5; 103 for (index = MIN_SPI_ID; index < num_ints; index += 32U) { 104 gicd_write_igroupr(gicd_base, index, 0xFFFFFFFFU); 105 } 106 107 /* Setup SPI priorities doing four at a time */ 108 for (index = MIN_SPI_ID; index < num_ints; index += 4U) { 109 gicd_write_ipriorityr(gicd_base, index, 110 GICD_IPRIORITYR_DEF_VAL); 111 } 112 113 /* Configure SPI secure interrupts now */ 114 if (g_irq_sec_ptr != NULL) { 115 116 for (index = 0U; index < g_num_irqs; index++) { 117 irq_num = g_irq_sec_ptr[index].irq; 118 target_cpus = (uint8_t)g_irq_sec_ptr[index].target_cpus; 119 120 if (irq_num >= MIN_SPI_ID) { 121 122 /* Configure as a secure interrupt */ 123 gicd_clr_igroupr(gicd_base, irq_num); 124 125 /* Configure SPI priority */ 126 mmio_write_8((uint64_t)gicd_base + 127 (uint64_t)GICD_IPRIORITYR + 128 (uint64_t)irq_num, 129 GIC_HIGHEST_SEC_PRIORITY & 130 GIC_PRI_MASK); 131 132 /* Configure as level triggered */ 133 val = gicd_read_icfgr(gicd_base, irq_num); 134 val |= (3U << ((irq_num & 0xFU) << 1U)); 135 gicd_write_icfgr(gicd_base, irq_num, val); 136 137 /* Route SPI to the target CPUs */ 138 gicd_set_itargetsr(gicd_base, irq_num, 139 target_cpus); 140 141 /* Enable this interrupt */ 142 gicd_set_isenabler(gicd_base, irq_num); 143 } 144 } 145 } 146 147 /* 148 * Configure the SGI and PPI. This is done in a separated function 149 * because each CPU is responsible for initializing its own private 150 * interrupts. 151 */ 152 tegra_gic_pcpu_distif_setup(gicd_base); 153 154 /* enable distributor */ 155 gicd_write_ctlr(gicd_base, ENABLE_GRP0 | ENABLE_GRP1); 156 } 157 158 void tegra_gic_setup(const irq_sec_cfg_t *irq_sec_ptr, uint32_t num_irqs) 159 { 160 g_irq_sec_ptr = irq_sec_ptr; 161 g_num_irqs = num_irqs; 162 163 tegra_gic_cpuif_setup(TEGRA_GICC_BASE); 164 tegra_gic_distif_setup(TEGRA_GICD_BASE); 165 } 166 167 /******************************************************************************* 168 * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins. 169 * The interrupt controller knows which pin/line it uses to signal a type of 170 * interrupt. This function provides a common implementation of 171 * plat_interrupt_type_to_line() in an ARM GIC environment for optional re-use 172 * across platforms. It lets the interrupt management framework determine 173 * for a type of interrupt and security state, which line should be used in the 174 * SCR_EL3 to control its routing to EL3. The interrupt line is represented as 175 * the bit position of the IRQ or FIQ bit in the SCR_EL3. 176 ******************************************************************************/ 177 static uint32_t tegra_gic_interrupt_type_to_line(uint32_t type, 178 uint32_t security_state) 179 { 180 assert((type == INTR_TYPE_S_EL1) || 181 (type == INTR_TYPE_EL3) || 182 (type == INTR_TYPE_NS)); 183 184 assert(sec_state_is_valid(security_state)); 185 186 /* 187 * We ignore the security state parameter under the assumption that 188 * both normal and secure worlds are using ARM GICv2. This parameter 189 * will be used when the secure world starts using GICv3. 190 */ 191 #if ARM_GIC_ARCH == 2 192 return gicv2_interrupt_type_to_line(TEGRA_GICC_BASE, type); 193 #else 194 #error "Invalid ARM GIC architecture version specified for platform port" 195 #endif /* ARM_GIC_ARCH */ 196 } 197 198 #if ARM_GIC_ARCH == 2 199 /******************************************************************************* 200 * This function returns the type of the highest priority pending interrupt at 201 * the GIC cpu interface. INTR_TYPE_INVAL is returned when there is no 202 * interrupt pending. 203 ******************************************************************************/ 204 static uint32_t tegra_gic_get_pending_interrupt_type(void) 205 { 206 uint32_t id; 207 uint32_t index; 208 uint32_t ret = INTR_TYPE_NS; 209 210 id = gicc_read_hppir(TEGRA_GICC_BASE) & INT_ID_MASK; 211 212 /* get the interrupt type */ 213 if (id < 1022U) { 214 for (index = 0U; index < g_num_irqs; index++) { 215 if (id == g_irq_sec_ptr[index].irq) { 216 ret = g_irq_sec_ptr[index].type; 217 break; 218 } 219 } 220 } else { 221 if (id == GIC_SPURIOUS_INTERRUPT) { 222 ret = INTR_TYPE_INVAL; 223 } 224 } 225 226 return ret; 227 } 228 229 /******************************************************************************* 230 * This function returns the id of the highest priority pending interrupt at 231 * the GIC cpu interface. INTR_ID_UNAVAILABLE is returned when there is no 232 * interrupt pending. 233 ******************************************************************************/ 234 static uint32_t tegra_gic_get_pending_interrupt_id(void) 235 { 236 uint32_t id, ret; 237 238 id = gicc_read_hppir(TEGRA_GICC_BASE) & INT_ID_MASK; 239 240 if (id < 1022U) { 241 ret = id; 242 } else if (id == 1023U) { 243 ret = 0xFFFFFFFFU; /* INTR_ID_UNAVAILABLE */ 244 } else { 245 /* 246 * Find out which non-secure interrupt it is under the assumption that 247 * the GICC_CTLR.AckCtl bit is 0. 248 */ 249 ret = gicc_read_ahppir(TEGRA_GICC_BASE) & INT_ID_MASK; 250 } 251 252 return ret; 253 } 254 255 /******************************************************************************* 256 * This functions reads the GIC cpu interface Interrupt Acknowledge register 257 * to start handling the pending interrupt. It returns the contents of the IAR. 258 ******************************************************************************/ 259 static uint32_t tegra_gic_acknowledge_interrupt(void) 260 { 261 return gicc_read_IAR(TEGRA_GICC_BASE); 262 } 263 264 /******************************************************************************* 265 * This functions writes the GIC cpu interface End Of Interrupt register with 266 * the passed value to finish handling the active interrupt 267 ******************************************************************************/ 268 static void tegra_gic_end_of_interrupt(uint32_t id) 269 { 270 gicc_write_EOIR(TEGRA_GICC_BASE, id); 271 } 272 273 /******************************************************************************* 274 * This function returns the type of the interrupt id depending upon the group 275 * this interrupt has been configured under by the interrupt controller i.e. 276 * group0 or group1. 277 ******************************************************************************/ 278 static uint32_t tegra_gic_get_interrupt_type(uint32_t id) 279 { 280 uint32_t group; 281 uint32_t index; 282 uint32_t ret = INTR_TYPE_NS; 283 284 group = gicd_get_igroupr(TEGRA_GICD_BASE, id); 285 286 /* get the interrupt type */ 287 if (group == GRP0) { 288 for (index = 0U; index < g_num_irqs; index++) { 289 if (id == g_irq_sec_ptr[index].irq) { 290 ret = g_irq_sec_ptr[index].type; 291 break; 292 } 293 } 294 } 295 296 return ret; 297 } 298 299 #else 300 #error "Invalid ARM GIC architecture version specified for platform port" 301 #endif /* ARM_GIC_ARCH */ 302 303 uint32_t plat_ic_get_pending_interrupt_id(void) 304 { 305 return tegra_gic_get_pending_interrupt_id(); 306 } 307 308 uint32_t plat_ic_get_pending_interrupt_type(void) 309 { 310 return tegra_gic_get_pending_interrupt_type(); 311 } 312 313 uint32_t plat_ic_acknowledge_interrupt(void) 314 { 315 return tegra_gic_acknowledge_interrupt(); 316 } 317 318 uint32_t plat_ic_get_interrupt_type(uint32_t id) 319 { 320 return tegra_gic_get_interrupt_type(id); 321 } 322 323 void plat_ic_end_of_interrupt(uint32_t id) 324 { 325 tegra_gic_end_of_interrupt(id); 326 } 327 328 uint32_t plat_interrupt_type_to_line(uint32_t type, 329 uint32_t security_state) 330 { 331 return tegra_gic_interrupt_type_to_line(type, security_state); 332 } 333