1 /* 2 * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 #include <arch_helpers.h> 7 #include <assert.h> 8 #include <bl_common.h> 9 #include <cassert.h> 10 #include <gic_common.h> 11 #include <gicv3.h> 12 #include <interrupt_mgmt.h> 13 #include <platform.h> 14 15 #ifdef IMAGE_BL31 16 17 /* 18 * The following platform GIC functions are weakly defined. They 19 * provide typical implementations that may be re-used by multiple 20 * platforms but may also be overridden by a platform if required. 21 */ 22 #pragma weak plat_ic_get_pending_interrupt_id 23 #pragma weak plat_ic_get_pending_interrupt_type 24 #pragma weak plat_ic_acknowledge_interrupt 25 #pragma weak plat_ic_get_interrupt_type 26 #pragma weak plat_ic_end_of_interrupt 27 #pragma weak plat_interrupt_type_to_line 28 29 CASSERT((INTR_TYPE_S_EL1 == INTR_GROUP1S) && 30 (INTR_TYPE_NS == INTR_GROUP1NS) && 31 (INTR_TYPE_EL3 == INTR_GROUP0), assert_interrupt_type_mismatch); 32 33 /* 34 * This function returns the highest priority pending interrupt at 35 * the Interrupt controller 36 */ 37 uint32_t plat_ic_get_pending_interrupt_id(void) 38 { 39 unsigned int irqnr; 40 41 assert(IS_IN_EL3()); 42 irqnr = gicv3_get_pending_interrupt_id(); 43 return (gicv3_is_intr_id_special_identifier(irqnr)) ? 44 INTR_ID_UNAVAILABLE : irqnr; 45 } 46 47 /* 48 * This function returns the type of the highest priority pending interrupt 49 * at the Interrupt controller. In the case of GICv3, the Highest Priority 50 * Pending interrupt system register (`ICC_HPPIR0_EL1`) is read to determine 51 * the id of the pending interrupt. The type of interrupt depends upon the 52 * id value as follows. 53 * 1. id = PENDING_G1S_INTID (1020) is reported as a S-EL1 interrupt 54 * 2. id = PENDING_G1NS_INTID (1021) is reported as a Non-secure interrupt. 55 * 3. id = GIC_SPURIOUS_INTERRUPT (1023) is reported as an invalid interrupt 56 * type. 57 * 4. All other interrupt id's are reported as EL3 interrupt. 58 */ 59 uint32_t plat_ic_get_pending_interrupt_type(void) 60 { 61 unsigned int irqnr; 62 63 assert(IS_IN_EL3()); 64 irqnr = gicv3_get_pending_interrupt_type(); 65 66 switch (irqnr) { 67 case PENDING_G1S_INTID: 68 return INTR_TYPE_S_EL1; 69 case PENDING_G1NS_INTID: 70 return INTR_TYPE_NS; 71 case GIC_SPURIOUS_INTERRUPT: 72 return INTR_TYPE_INVAL; 73 default: 74 return INTR_TYPE_EL3; 75 } 76 } 77 78 /* 79 * This function returns the highest priority pending interrupt at 80 * the Interrupt controller and indicates to the Interrupt controller 81 * that the interrupt processing has started. 82 */ 83 uint32_t plat_ic_acknowledge_interrupt(void) 84 { 85 assert(IS_IN_EL3()); 86 return gicv3_acknowledge_interrupt(); 87 } 88 89 /* 90 * This function returns the type of the interrupt `id`, depending on how 91 * the interrupt has been configured in the interrupt controller 92 */ 93 uint32_t plat_ic_get_interrupt_type(uint32_t id) 94 { 95 assert(IS_IN_EL3()); 96 return gicv3_get_interrupt_type(id, plat_my_core_pos()); 97 } 98 99 /* 100 * This functions is used to indicate to the interrupt controller that 101 * the processing of the interrupt corresponding to the `id` has 102 * finished. 103 */ 104 void plat_ic_end_of_interrupt(uint32_t id) 105 { 106 assert(IS_IN_EL3()); 107 gicv3_end_of_interrupt(id); 108 } 109 110 /* 111 * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins. 112 * The interrupt controller knows which pin/line it uses to signal a type of 113 * interrupt. It lets the interrupt management framework determine for a type of 114 * interrupt and security state, which line should be used in the SCR_EL3 to 115 * control its routing to EL3. The interrupt line is represented as the bit 116 * position of the IRQ or FIQ bit in the SCR_EL3. 117 */ 118 uint32_t plat_interrupt_type_to_line(uint32_t type, 119 uint32_t security_state) 120 { 121 assert(type == INTR_TYPE_S_EL1 || 122 type == INTR_TYPE_EL3 || 123 type == INTR_TYPE_NS); 124 125 assert(sec_state_is_valid(security_state)); 126 assert(IS_IN_EL3()); 127 128 switch (type) { 129 case INTR_TYPE_S_EL1: 130 /* 131 * The S-EL1 interrupts are signaled as IRQ in S-EL0/1 contexts 132 * and as FIQ in the NS-EL0/1/2 contexts 133 */ 134 if (security_state == SECURE) 135 return __builtin_ctz(SCR_IRQ_BIT); 136 else 137 return __builtin_ctz(SCR_FIQ_BIT); 138 case INTR_TYPE_NS: 139 /* 140 * The Non secure interrupts will be signaled as FIQ in S-EL0/1 141 * contexts and as IRQ in the NS-EL0/1/2 contexts. 142 */ 143 if (security_state == SECURE) 144 return __builtin_ctz(SCR_FIQ_BIT); 145 else 146 return __builtin_ctz(SCR_IRQ_BIT); 147 default: 148 assert(0); 149 /* Fall through in the release build */ 150 case INTR_TYPE_EL3: 151 /* 152 * The EL3 interrupts are signaled as FIQ in both S-EL0/1 and 153 * NS-EL0/1/2 contexts 154 */ 155 return __builtin_ctz(SCR_FIQ_BIT); 156 } 157 } 158 #endif 159 #ifdef IMAGE_BL32 160 161 #pragma weak plat_ic_get_pending_interrupt_id 162 #pragma weak plat_ic_acknowledge_interrupt 163 #pragma weak plat_ic_end_of_interrupt 164 165 /* In AArch32, the secure group1 interrupts are targeted to Secure PL1 */ 166 #ifdef AARCH32 167 #define IS_IN_EL1() IS_IN_SECURE() 168 #endif 169 170 /* 171 * This function returns the highest priority pending interrupt at 172 * the Interrupt controller 173 */ 174 uint32_t plat_ic_get_pending_interrupt_id(void) 175 { 176 unsigned int irqnr; 177 178 assert(IS_IN_EL1()); 179 irqnr = gicv3_get_pending_interrupt_id_sel1(); 180 return (irqnr == GIC_SPURIOUS_INTERRUPT) ? 181 INTR_ID_UNAVAILABLE : irqnr; 182 } 183 184 /* 185 * This function returns the highest priority pending interrupt at 186 * the Interrupt controller and indicates to the Interrupt controller 187 * that the interrupt processing has started. 188 */ 189 uint32_t plat_ic_acknowledge_interrupt(void) 190 { 191 assert(IS_IN_EL1()); 192 return gicv3_acknowledge_interrupt_sel1(); 193 } 194 195 /* 196 * This functions is used to indicate to the interrupt controller that 197 * the processing of the interrupt corresponding to the `id` has 198 * finished. 199 */ 200 void plat_ic_end_of_interrupt(uint32_t id) 201 { 202 assert(IS_IN_EL1()); 203 gicv3_end_of_interrupt_sel1(id); 204 } 205 #endif 206