1 /* 2 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 #include <assert.h> 7 #include <gic_common.h> 8 #include <gicv2.h> 9 #include <interrupt_mgmt.h> 10 11 /* 12 * The following platform GIC functions are weakly defined. They 13 * provide typical implementations that may be re-used by multiple 14 * platforms but may also be overridden by a platform if required. 15 */ 16 #pragma weak plat_ic_get_pending_interrupt_id 17 #pragma weak plat_ic_get_pending_interrupt_type 18 #pragma weak plat_ic_acknowledge_interrupt 19 #pragma weak plat_ic_get_interrupt_type 20 #pragma weak plat_ic_end_of_interrupt 21 #pragma weak plat_interrupt_type_to_line 22 23 #pragma weak plat_ic_get_running_priority 24 #pragma weak plat_ic_is_spi 25 #pragma weak plat_ic_is_ppi 26 #pragma weak plat_ic_is_sgi 27 #pragma weak plat_ic_get_interrupt_active 28 #pragma weak plat_ic_enable_interrupt 29 #pragma weak plat_ic_disable_interrupt 30 31 /* 32 * This function returns the highest priority pending interrupt at 33 * the Interrupt controller 34 */ 35 uint32_t plat_ic_get_pending_interrupt_id(void) 36 { 37 unsigned int id; 38 39 id = gicv2_get_pending_interrupt_id(); 40 if (id == GIC_SPURIOUS_INTERRUPT) 41 return INTR_ID_UNAVAILABLE; 42 43 return id; 44 } 45 46 /* 47 * This function returns the type of the highest priority pending interrupt 48 * at the Interrupt controller. In the case of GICv2, the Highest Priority 49 * Pending interrupt register (`GICC_HPPIR`) is read to determine the id of 50 * the pending interrupt. The type of interrupt depends upon the id value 51 * as follows. 52 * 1. id < PENDING_G1_INTID (1022) is reported as a S-EL1 interrupt 53 * 2. id = PENDING_G1_INTID (1022) is reported as a Non-secure interrupt. 54 * 3. id = GIC_SPURIOUS_INTERRUPT (1023) is reported as an invalid interrupt 55 * type. 56 */ 57 uint32_t plat_ic_get_pending_interrupt_type(void) 58 { 59 unsigned int id; 60 61 id = gicv2_get_pending_interrupt_type(); 62 63 /* Assume that all secure interrupts are S-EL1 interrupts */ 64 if (id < PENDING_G1_INTID) 65 return INTR_TYPE_S_EL1; 66 67 if (id == GIC_SPURIOUS_INTERRUPT) 68 return INTR_TYPE_INVAL; 69 70 return INTR_TYPE_NS; 71 } 72 73 /* 74 * This function returns the highest priority pending interrupt at 75 * the Interrupt controller and indicates to the Interrupt controller 76 * that the interrupt processing has started. 77 */ 78 uint32_t plat_ic_acknowledge_interrupt(void) 79 { 80 return gicv2_acknowledge_interrupt(); 81 } 82 83 /* 84 * This function returns the type of the interrupt `id`, depending on how 85 * the interrupt has been configured in the interrupt controller 86 */ 87 uint32_t plat_ic_get_interrupt_type(uint32_t id) 88 { 89 unsigned int type; 90 91 type = gicv2_get_interrupt_group(id); 92 93 /* Assume that all secure interrupts are S-EL1 interrupts */ 94 return (type) ? INTR_TYPE_NS : INTR_TYPE_S_EL1; 95 } 96 97 /* 98 * This functions is used to indicate to the interrupt controller that 99 * the processing of the interrupt corresponding to the `id` has 100 * finished. 101 */ 102 void plat_ic_end_of_interrupt(uint32_t id) 103 { 104 gicv2_end_of_interrupt(id); 105 } 106 107 /* 108 * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins. 109 * The interrupt controller knows which pin/line it uses to signal a type of 110 * interrupt. It lets the interrupt management framework determine 111 * for a type of interrupt and security state, which line should be used in the 112 * SCR_EL3 to control its routing to EL3. The interrupt line is represented 113 * as the bit position of the IRQ or FIQ bit in the SCR_EL3. 114 */ 115 uint32_t plat_interrupt_type_to_line(uint32_t type, 116 uint32_t security_state) 117 { 118 assert(type == INTR_TYPE_S_EL1 || 119 type == INTR_TYPE_EL3 || 120 type == INTR_TYPE_NS); 121 122 /* Non-secure interrupts are signaled on the IRQ line always */ 123 if (type == INTR_TYPE_NS) 124 return __builtin_ctz(SCR_IRQ_BIT); 125 126 /* 127 * Secure interrupts are signaled using the IRQ line if the FIQ is 128 * not enabled else they are signaled using the FIQ line. 129 */ 130 return ((gicv2_is_fiq_enabled()) ? __builtin_ctz(SCR_FIQ_BIT) : 131 __builtin_ctz(SCR_IRQ_BIT)); 132 } 133 134 unsigned int plat_ic_get_running_priority(void) 135 { 136 return gicv2_get_running_priority(); 137 } 138 139 int plat_ic_is_spi(unsigned int id) 140 { 141 return (id >= MIN_SPI_ID) && (id <= MAX_SPI_ID); 142 } 143 144 int plat_ic_is_ppi(unsigned int id) 145 { 146 return (id >= MIN_PPI_ID) && (id < MIN_SPI_ID); 147 } 148 149 int plat_ic_is_sgi(unsigned int id) 150 { 151 return (id >= MIN_SGI_ID) && (id < MIN_PPI_ID); 152 } 153 154 unsigned int plat_ic_get_interrupt_active(unsigned int id) 155 { 156 return gicv2_get_interrupt_active(id); 157 } 158 159 void plat_ic_enable_interrupt(unsigned int id) 160 { 161 gicv2_enable_interrupt(id); 162 } 163 164 void plat_ic_disable_interrupt(unsigned int id) 165 { 166 gicv2_disable_interrupt(id); 167 } 168