1 /* 2 * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 #include <arch_helpers.h> 31 #include <assert.h> 32 #include <bl_common.h> 33 #include <cassert.h> 34 #include <gic_common.h> 35 #include <gicv3.h> 36 #include <interrupt_mgmt.h> 37 #include <platform.h> 38 39 #ifdef IMAGE_BL31 40 41 /* 42 * The following platform GIC functions are weakly defined. They 43 * provide typical implementations that may be re-used by multiple 44 * platforms but may also be overridden by a platform if required. 45 */ 46 #pragma weak plat_ic_get_pending_interrupt_id 47 #pragma weak plat_ic_get_pending_interrupt_type 48 #pragma weak plat_ic_acknowledge_interrupt 49 #pragma weak plat_ic_get_interrupt_type 50 #pragma weak plat_ic_end_of_interrupt 51 #pragma weak plat_interrupt_type_to_line 52 53 CASSERT((INTR_TYPE_S_EL1 == INTR_GROUP1S) && 54 (INTR_TYPE_NS == INTR_GROUP1NS) && 55 (INTR_TYPE_EL3 == INTR_GROUP0), assert_interrupt_type_mismatch); 56 57 /* 58 * This function returns the highest priority pending interrupt at 59 * the Interrupt controller 60 */ 61 uint32_t plat_ic_get_pending_interrupt_id(void) 62 { 63 unsigned int irqnr; 64 65 assert(IS_IN_EL3()); 66 irqnr = gicv3_get_pending_interrupt_id(); 67 return (gicv3_is_intr_id_special_identifier(irqnr)) ? 68 INTR_ID_UNAVAILABLE : irqnr; 69 } 70 71 /* 72 * This function returns the type of the highest priority pending interrupt 73 * at the Interrupt controller. In the case of GICv3, the Highest Priority 74 * Pending interrupt system register (`ICC_HPPIR0_EL1`) is read to determine 75 * the id of the pending interrupt. The type of interrupt depends upon the 76 * id value as follows. 77 * 1. id = PENDING_G1S_INTID (1020) is reported as a S-EL1 interrupt 78 * 2. id = PENDING_G1NS_INTID (1021) is reported as a Non-secure interrupt. 79 * 3. id = GIC_SPURIOUS_INTERRUPT (1023) is reported as an invalid interrupt 80 * type. 81 * 4. All other interrupt id's are reported as EL3 interrupt. 82 */ 83 uint32_t plat_ic_get_pending_interrupt_type(void) 84 { 85 unsigned int irqnr; 86 87 assert(IS_IN_EL3()); 88 irqnr = gicv3_get_pending_interrupt_type(); 89 90 switch (irqnr) { 91 case PENDING_G1S_INTID: 92 return INTR_TYPE_S_EL1; 93 case PENDING_G1NS_INTID: 94 return INTR_TYPE_NS; 95 case GIC_SPURIOUS_INTERRUPT: 96 return INTR_TYPE_INVAL; 97 default: 98 return INTR_TYPE_EL3; 99 } 100 } 101 102 /* 103 * This function returns the highest priority pending interrupt at 104 * the Interrupt controller and indicates to the Interrupt controller 105 * that the interrupt processing has started. 106 */ 107 uint32_t plat_ic_acknowledge_interrupt(void) 108 { 109 assert(IS_IN_EL3()); 110 return gicv3_acknowledge_interrupt(); 111 } 112 113 /* 114 * This function returns the type of the interrupt `id`, depending on how 115 * the interrupt has been configured in the interrupt controller 116 */ 117 uint32_t plat_ic_get_interrupt_type(uint32_t id) 118 { 119 assert(IS_IN_EL3()); 120 return gicv3_get_interrupt_type(id, plat_my_core_pos()); 121 } 122 123 /* 124 * This functions is used to indicate to the interrupt controller that 125 * the processing of the interrupt corresponding to the `id` has 126 * finished. 127 */ 128 void plat_ic_end_of_interrupt(uint32_t id) 129 { 130 assert(IS_IN_EL3()); 131 gicv3_end_of_interrupt(id); 132 } 133 134 /* 135 * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins. 136 * The interrupt controller knows which pin/line it uses to signal a type of 137 * interrupt. It lets the interrupt management framework determine for a type of 138 * interrupt and security state, which line should be used in the SCR_EL3 to 139 * control its routing to EL3. The interrupt line is represented as the bit 140 * position of the IRQ or FIQ bit in the SCR_EL3. 141 */ 142 uint32_t plat_interrupt_type_to_line(uint32_t type, 143 uint32_t security_state) 144 { 145 assert(type == INTR_TYPE_S_EL1 || 146 type == INTR_TYPE_EL3 || 147 type == INTR_TYPE_NS); 148 149 assert(sec_state_is_valid(security_state)); 150 assert(IS_IN_EL3()); 151 152 switch (type) { 153 case INTR_TYPE_S_EL1: 154 /* 155 * The S-EL1 interrupts are signaled as IRQ in S-EL0/1 contexts 156 * and as FIQ in the NS-EL0/1/2 contexts 157 */ 158 if (security_state == SECURE) 159 return __builtin_ctz(SCR_IRQ_BIT); 160 else 161 return __builtin_ctz(SCR_FIQ_BIT); 162 case INTR_TYPE_NS: 163 /* 164 * The Non secure interrupts will be signaled as FIQ in S-EL0/1 165 * contexts and as IRQ in the NS-EL0/1/2 contexts. 166 */ 167 if (security_state == SECURE) 168 return __builtin_ctz(SCR_FIQ_BIT); 169 else 170 return __builtin_ctz(SCR_IRQ_BIT); 171 default: 172 assert(0); 173 /* Fall through in the release build */ 174 case INTR_TYPE_EL3: 175 /* 176 * The EL3 interrupts are signaled as FIQ in both S-EL0/1 and 177 * NS-EL0/1/2 contexts 178 */ 179 return __builtin_ctz(SCR_FIQ_BIT); 180 } 181 } 182 #endif 183 #ifdef IMAGE_BL32 184 185 #pragma weak plat_ic_get_pending_interrupt_id 186 #pragma weak plat_ic_acknowledge_interrupt 187 #pragma weak plat_ic_end_of_interrupt 188 189 /* In AArch32, the secure group1 interrupts are targeted to Secure PL1 */ 190 #ifdef AARCH32 191 #define IS_IN_EL1() IS_IN_SECURE() 192 #endif 193 194 /* 195 * This function returns the highest priority pending interrupt at 196 * the Interrupt controller 197 */ 198 uint32_t plat_ic_get_pending_interrupt_id(void) 199 { 200 unsigned int irqnr; 201 202 assert(IS_IN_EL1()); 203 irqnr = gicv3_get_pending_interrupt_id_sel1(); 204 return (irqnr == GIC_SPURIOUS_INTERRUPT) ? 205 INTR_ID_UNAVAILABLE : irqnr; 206 } 207 208 /* 209 * This function returns the highest priority pending interrupt at 210 * the Interrupt controller and indicates to the Interrupt controller 211 * that the interrupt processing has started. 212 */ 213 uint32_t plat_ic_acknowledge_interrupt(void) 214 { 215 assert(IS_IN_EL1()); 216 return gicv3_acknowledge_interrupt_sel1(); 217 } 218 219 /* 220 * This functions is used to indicate to the interrupt controller that 221 * the processing of the interrupt corresponding to the `id` has 222 * finished. 223 */ 224 void plat_ic_end_of_interrupt(uint32_t id) 225 { 226 assert(IS_IN_EL1()); 227 gicv3_end_of_interrupt_sel1(id); 228 } 229 #endif 230