1 /**************************************************************************//**
3 * @brief Interrupt controller handling implementation for GIC
6 ******************************************************************************/
8 * Copyright (c) 2017-2020 ARM Limited. All rights reserved.
10 * SPDX-License-Identifier: Apache-2.0
12 * Licensed under the Apache License, Version 2.0 (the License); you may
13 * not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
16 * www.apache.org/licenses/LICENSE-2.0
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
20 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
27 #include "RTE_Components.h"
28 #include CMSIS_device_header
32 #if defined(__GIC_PRESENT) && (__GIC_PRESENT == 1U)
34 /// Number of implemented interrupt lines
35 #ifndef IRQ_GIC_LINE_COUNT
36 #define IRQ_GIC_LINE_COUNT (1020U)
39 static IRQHandler_t IRQTable[IRQ_GIC_LINE_COUNT] = { 0U };
40 static uint32_t IRQ_ID0;
42 /// Initialize interrupt controller.
43 __WEAK int32_t IRQ_Initialize (void) {
46 for (i = 0U; i < IRQ_GIC_LINE_COUNT; i++) {
47 IRQTable[i] = (IRQHandler_t)NULL;
54 /// Register interrupt handler.
55 __WEAK int32_t IRQ_SetHandler (IRQn_ID_t irqn, IRQHandler_t handler) {
58 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
59 IRQTable[irqn] = handler;
69 /// Get the registered interrupt handler.
70 __WEAK IRQHandler_t IRQ_GetHandler (IRQn_ID_t irqn) {
73 // Ignore CPUID field (software generated interrupts)
76 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
87 __WEAK int32_t IRQ_Enable (IRQn_ID_t irqn) {
90 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
91 GIC_EnableIRQ ((IRQn_Type)irqn);
101 /// Disable interrupt.
102 __WEAK int32_t IRQ_Disable (IRQn_ID_t irqn) {
105 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
106 GIC_DisableIRQ ((IRQn_Type)irqn);
116 /// Get interrupt enable state.
117 __WEAK uint32_t IRQ_GetEnableState (IRQn_ID_t irqn) {
120 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
121 enable = GIC_GetEnableIRQ((IRQn_Type)irqn);
130 /// Configure interrupt request mode.
131 __WEAK int32_t IRQ_SetMode (IRQn_ID_t irqn, uint32_t mode) {
138 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
139 // Check triggering mode
140 val = (mode & IRQ_MODE_TRIG_Msk);
142 if (val == IRQ_MODE_TRIG_LEVEL) {
144 } else if (val == IRQ_MODE_TRIG_EDGE) {
151 val = (mode & IRQ_MODE_MODEL_Msk);
152 if (val == IRQ_MODE_MODEL_1N) {
153 cfg |= 1; // 1-N model
156 // Check interrupt type
157 val = mode & IRQ_MODE_TYPE_Msk;
159 if (val != IRQ_MODE_TYPE_IRQ) {
163 // Check interrupt domain
164 val = mode & IRQ_MODE_DOMAIN_Msk;
166 if (val == IRQ_MODE_DOMAIN_NONSECURE) {
169 // Check security extensions support
170 val = GIC_DistributorInfo() & (1UL << 10U);
173 // Security extensions are supported
181 // Check interrupt CPU targets
182 val = mode & IRQ_MODE_CPU_Msk;
184 if (val == IRQ_MODE_CPU_ALL) {
187 cpu = (uint8_t)(val >> IRQ_MODE_CPU_Pos);
190 // Apply configuration if no mode error
192 GIC_SetConfiguration((IRQn_Type)irqn, cfg);
193 GIC_SetTarget ((IRQn_Type)irqn, cpu);
196 GIC_SetGroup ((IRQn_Type)irqn, secure);
205 /// Get interrupt mode configuration.
206 __WEAK uint32_t IRQ_GetMode (IRQn_ID_t irqn) {
210 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
211 mode = IRQ_MODE_TYPE_IRQ;
214 val = GIC_GetConfiguration((IRQn_Type)irqn);
216 if ((val & 2U) != 0U) {
217 // Corresponding interrupt is edge triggered
218 mode |= IRQ_MODE_TRIG_EDGE;
220 // Corresponding interrupt is level triggered
221 mode |= IRQ_MODE_TRIG_LEVEL;
225 mode |= IRQ_MODE_MODEL_1N;
227 // Get interrupt CPU targets
228 mode |= GIC_GetTarget ((IRQn_Type)irqn) << IRQ_MODE_CPU_Pos;
231 mode = IRQ_MODE_ERROR;
238 /// Get ID number of current interrupt request (IRQ).
239 __WEAK IRQn_ID_t IRQ_GetActiveIRQ (void) {
243 /* Dummy read to avoid GIC 390 errata 801120 */
244 GIC_GetHighPendingIRQ();
246 irqn = GIC_AcknowledgePending();
250 /* Workaround GIC 390 errata 733075 (GIC-390_Errata_Notice_v6.pdf, 09-Jul-2014) */
251 /* The following workaround code is for a single-core system. It would be */
252 /* different in a multi-core system. */
253 /* If the ID is 0 or 0x3FE or 0x3FF, then the GIC CPU interface may be locked-up */
254 /* so unlock it, otherwise service the interrupt as normal. */
255 /* Special IDs 1020=0x3FC and 1021=0x3FD are reserved values in GICv1 and GICv2 */
256 /* so will not occur here. */
258 if ((irqn == 0) || (irqn >= 0x3FE)) {
259 /* Unlock the CPU interface with a dummy write to Interrupt Priority Register */
260 prio = GIC_GetPriority((IRQn_Type)0);
261 GIC_SetPriority ((IRQn_Type)0, prio);
265 if ((irqn == 0U) && ((GIC_GetIRQStatus ((IRQn_Type)irqn) & 1U) != 0U) && (IRQ_ID0 == 0U)) {
266 /* If the ID is 0, is active and has not been seen before */
269 /* End of Workaround GIC 390 errata 733075 */
276 /// Get ID number of current fast interrupt request (FIQ).
277 __WEAK IRQn_ID_t IRQ_GetActiveFIQ (void) {
278 return ((IRQn_ID_t)-1);
282 /// Signal end of interrupt processing.
283 __WEAK int32_t IRQ_EndOfInterrupt (IRQn_ID_t irqn) {
285 IRQn_Type irq = (IRQn_Type)irqn;
289 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
290 GIC_EndInterrupt (irq);
305 /// Set interrupt pending flag.
306 __WEAK int32_t IRQ_SetPending (IRQn_ID_t irqn) {
309 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
310 GIC_SetPendingIRQ ((IRQn_Type)irqn);
319 /// Get interrupt pending flag.
320 __WEAK uint32_t IRQ_GetPending (IRQn_ID_t irqn) {
323 if ((irqn >= 16) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
324 pending = GIC_GetPendingIRQ ((IRQn_Type)irqn);
329 return (pending & 1U);
333 /// Clear interrupt pending flag.
334 __WEAK int32_t IRQ_ClearPending (IRQn_ID_t irqn) {
337 if ((irqn >= 16) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
338 GIC_ClearPendingIRQ ((IRQn_Type)irqn);
348 /// Set interrupt priority value.
349 __WEAK int32_t IRQ_SetPriority (IRQn_ID_t irqn, uint32_t priority) {
352 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
353 GIC_SetPriority ((IRQn_Type)irqn, priority);
363 /// Get interrupt priority.
364 __WEAK uint32_t IRQ_GetPriority (IRQn_ID_t irqn) {
367 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
368 priority = GIC_GetPriority ((IRQn_Type)irqn);
370 priority = IRQ_PRIORITY_ERROR;
377 /// Set priority masking threshold.
378 __WEAK int32_t IRQ_SetPriorityMask (uint32_t priority) {
379 GIC_SetInterfacePriorityMask (priority);
384 /// Get priority masking threshold
385 __WEAK uint32_t IRQ_GetPriorityMask (void) {
386 return GIC_GetInterfacePriorityMask();
390 /// Set priority grouping field split point
391 __WEAK int32_t IRQ_SetPriorityGroupBits (uint32_t bits) {
394 if (bits == IRQ_PRIORITY_Msk) {
399 GIC_SetBinaryPoint (7U - bits);
409 /// Get priority grouping field split point
410 __WEAK uint32_t IRQ_GetPriorityGroupBits (void) {
413 bp = GIC_GetBinaryPoint() & 0x07U;