source: asp3_tinet_ecnl_arm/trunk/asp3_dcre/mbed/cmsis/TARGET_CORTEX_A/irq_ctrl_gic.c@ 374

Last change on this file since 374 was 374, checked in by coas-nagasima, 5 years ago

mbed関連を更新
シリアルドライバをmbedのHALを使うよう変更
ファイルディスクリプタの処理を更新

  • Property charset set to UTF-8
  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 8.9 KB
Line 
1/**************************************************************************//**
2 * @file irq_ctrl_gic.c
3 * @brief Interrupt controller handling implementation for GIC
4 * @version V1.0.1
5 * @date 9. April 2018
6 ******************************************************************************/
7/*
8 * Copyright (c) 2017 ARM Limited. All rights reserved.
9 *
10 * SPDX-License-Identifier: Apache-2.0
11 *
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
15 *
16 * www.apache.org/licenses/LICENSE-2.0
17 *
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.
23 */
24
25#include <stddef.h>
26
27#include "RTE_Components.h"
28#include CMSIS_device_header
29
30#include "irq_ctrl.h"
31
32#if defined(__GIC_PRESENT) && (__GIC_PRESENT == 1U)
33
34/// Number of implemented interrupt lines
35#ifndef IRQ_GIC_LINE_COUNT
36#define IRQ_GIC_LINE_COUNT (1020U)
37#endif
38
39extern IRQHandler_t IRQTable[IRQ_GIC_LINE_COUNT];
40static uint32_t IRQ_ID0;
41
42/// Initialize interrupt controller.
43__WEAK int32_t IRQ_Initialize (void) {
44 uint32_t i;
45
46 for (i = 0U; i < IRQ_GIC_LINE_COUNT; i++) {
47 IRQTable[i] = (IRQHandler_t)NULL;
48 }
49 GIC_Enable();
50 return (0);
51}
52
53
54/// Register interrupt handler.
55__WEAK int32_t IRQ_SetHandler (IRQn_ID_t irqn, IRQHandler_t handler) {
56 int32_t status;
57
58 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
59 IRQTable[irqn] = handler;
60 status = 0;
61 } else {
62 status = -1;
63 }
64
65 return (status);
66}
67
68
69/// Get the registered interrupt handler.
70__WEAK IRQHandler_t IRQ_GetHandler (IRQn_ID_t irqn) {
71 IRQHandler_t h;
72
73 // Ignore CPUID field (software generated interrupts)
74 irqn &= 0x3FFU;
75
76 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
77 h = IRQTable[irqn];
78 } else {
79 h = (IRQHandler_t)0;
80 }
81
82 return (h);
83}
84
85
86/// Enable interrupt.
87__WEAK int32_t IRQ_Enable (IRQn_ID_t irqn) {
88 int32_t status;
89
90 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
91 GIC_EnableIRQ ((IRQn_Type)irqn);
92 status = 0;
93 } else {
94 status = -1;
95 }
96
97 return (status);
98}
99
100
101/// Disable interrupt.
102__WEAK int32_t IRQ_Disable (IRQn_ID_t irqn) {
103 int32_t status;
104
105 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
106 GIC_DisableIRQ ((IRQn_Type)irqn);
107 status = 0;
108 } else {
109 status = -1;
110 }
111
112 return (status);
113}
114
115
116/// Get interrupt enable state.
117__WEAK uint32_t IRQ_GetEnableState (IRQn_ID_t irqn) {
118 uint32_t enable;
119
120 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
121 enable = GIC_GetEnableIRQ((IRQn_Type)irqn);
122 } else {
123 enable = 0U;
124 }
125
126 return (enable);
127}
128
129
130/// Configure interrupt request mode.
131__WEAK int32_t IRQ_SetMode (IRQn_ID_t irqn, uint32_t mode) {
132 uint32_t val;
133 uint8_t cfg;
134 uint8_t secure;
135 uint8_t cpu;
136 int32_t status = 0;
137
138 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
139 // Check triggering mode
140 val = (mode & IRQ_MODE_TRIG_Msk);
141
142 if (val == IRQ_MODE_TRIG_LEVEL) {
143 cfg = 0x00U;
144 } else if (val == IRQ_MODE_TRIG_EDGE) {
145 cfg = 0x02U;
146 } else {
147 cfg = 0x00U;
148 status = -1;
149 }
150
151 // Check interrupt type
152 val = mode & IRQ_MODE_TYPE_Msk;
153
154 if (val != IRQ_MODE_TYPE_IRQ) {
155 status = -1;
156 }
157
158 // Check interrupt domain
159 val = mode & IRQ_MODE_DOMAIN_Msk;
160
161 if (val == IRQ_MODE_DOMAIN_NONSECURE) {
162 secure = 0U;
163 } else {
164 // Check security extensions support
165 val = GIC_DistributorInfo() & (1UL << 10U);
166
167 if (val != 0U) {
168 // Security extensions are supported
169 secure = 1U;
170 } else {
171 secure = 0U;
172 status = -1;
173 }
174 }
175
176 // Check interrupt CPU targets
177 val = mode & IRQ_MODE_CPU_Msk;
178
179 if (val == IRQ_MODE_CPU_ALL) {
180 cpu = 0xFFU;
181 } else {
182 cpu = val >> IRQ_MODE_CPU_Pos;
183 }
184
185 // Apply configuration if no mode error
186 if (status == 0) {
187 GIC_SetConfiguration((IRQn_Type)irqn, cfg);
188 GIC_SetTarget ((IRQn_Type)irqn, cpu);
189
190 if (secure != 0U) {
191 GIC_SetGroup ((IRQn_Type)irqn, secure);
192 }
193 }
194 }
195
196 return (status);
197}
198
199
200/// Get interrupt mode configuration.
201__WEAK uint32_t IRQ_GetMode (IRQn_ID_t irqn) {
202 uint32_t mode;
203 uint32_t val;
204
205 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
206 mode = IRQ_MODE_TYPE_IRQ;
207
208 // Get trigger mode
209 val = GIC_GetConfiguration((IRQn_Type)irqn);
210
211 if ((val & 2U) != 0U) {
212 // Corresponding interrupt is edge triggered
213 mode |= IRQ_MODE_TRIG_EDGE;
214 } else {
215 // Corresponding interrupt is level triggered
216 mode |= IRQ_MODE_TRIG_LEVEL;
217 }
218
219 // Get interrupt CPU targets
220 mode |= GIC_GetTarget ((IRQn_Type)irqn) << IRQ_MODE_CPU_Pos;
221
222 } else {
223 mode = IRQ_MODE_ERROR;
224 }
225
226 return (mode);
227}
228
229
230/// Get ID number of current interrupt request (IRQ).
231__WEAK IRQn_ID_t IRQ_GetActiveIRQ (void) {
232 IRQn_ID_t irqn;
233 uint32_t prio;
234
235 /* Dummy read to avoid GIC 390 errata 801120 */
236 GIC_GetHighPendingIRQ();
237
238 irqn = GIC_AcknowledgePending();
239
240 __DSB();
241
242 /* Workaround GIC 390 errata 733075 (GIC-390_Errata_Notice_v6.pdf, 09-Jul-2014) */
243 /* The following workaround code is for a single-core system. It would be */
244 /* different in a multi-core system. */
245 /* If the ID is 0 or 0x3FE or 0x3FF, then the GIC CPU interface may be locked-up */
246 /* so unlock it, otherwise service the interrupt as normal. */
247 /* Special IDs 1020=0x3FC and 1021=0x3FD are reserved values in GICv1 and GICv2 */
248 /* so will not occur here. */
249
250 if ((irqn == 0) || (irqn >= 0x3FE)) {
251 /* Unlock the CPU interface with a dummy write to Interrupt Priority Register */
252 prio = GIC_GetPriority((IRQn_Type)0);
253 GIC_SetPriority ((IRQn_Type)0, prio);
254
255 __DSB();
256
257 if ((irqn == 0U) && ((GIC_GetIRQStatus ((IRQn_Type)irqn) & 1U) != 0U) && (IRQ_ID0 == 0U)) {
258 /* If the ID is 0, is active and has not been seen before */
259 IRQ_ID0 = 1U;
260 }
261 /* End of Workaround GIC 390 errata 733075 */
262 }
263
264 return (irqn);
265}
266
267
268/// Get ID number of current fast interrupt request (FIQ).
269__WEAK IRQn_ID_t IRQ_GetActiveFIQ (void) {
270 return ((IRQn_ID_t)-1);
271}
272
273
274/// Signal end of interrupt processing.
275__WEAK int32_t IRQ_EndOfInterrupt (IRQn_ID_t irqn) {
276 int32_t status;
277 IRQn_Type irq = (IRQn_Type)irqn;
278
279 irqn &= 0x3FFU;
280
281 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
282 GIC_EndInterrupt (irq);
283
284 if (irqn == 0) {
285 IRQ_ID0 = 0U;
286 }
287
288 status = 0;
289 } else {
290 status = -1;
291 }
292
293 return (status);
294}
295
296
297/// Set interrupt pending flag.
298__WEAK int32_t IRQ_SetPending (IRQn_ID_t irqn) {
299 int32_t status;
300
301 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
302 GIC_SetPendingIRQ ((IRQn_Type)irqn);
303 status = 0;
304 } else {
305 status = -1;
306 }
307
308 return (status);
309}
310
311/// Get interrupt pending flag.
312__WEAK uint32_t IRQ_GetPending (IRQn_ID_t irqn) {
313 uint32_t pending;
314
315 if ((irqn >= 16) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
316 pending = GIC_GetPendingIRQ ((IRQn_Type)irqn);
317 } else {
318 pending = 0U;
319 }
320
321 return (pending & 1U);
322}
323
324
325/// Clear interrupt pending flag.
326__WEAK int32_t IRQ_ClearPending (IRQn_ID_t irqn) {
327 int32_t status;
328
329 if ((irqn >= 16) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
330 GIC_ClearPendingIRQ ((IRQn_Type)irqn);
331 status = 0;
332 } else {
333 status = -1;
334 }
335
336 return (status);
337}
338
339
340/// Set interrupt priority value.
341__WEAK int32_t IRQ_SetPriority (IRQn_ID_t irqn, uint32_t priority) {
342 int32_t status;
343
344 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
345 GIC_SetPriority ((IRQn_Type)irqn, priority);
346 status = 0;
347 } else {
348 status = -1;
349 }
350
351 return (status);
352}
353
354
355/// Get interrupt priority.
356__WEAK uint32_t IRQ_GetPriority (IRQn_ID_t irqn) {
357 uint32_t priority;
358
359 if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
360 priority = GIC_GetPriority ((IRQn_Type)irqn);
361 } else {
362 priority = IRQ_PRIORITY_ERROR;
363 }
364
365 return (priority);
366}
367
368
369/// Set priority masking threshold.
370__WEAK int32_t IRQ_SetPriorityMask (uint32_t priority) {
371 GIC_SetInterfacePriorityMask (priority);
372 return (0);
373}
374
375
376/// Get priority masking threshold
377__WEAK uint32_t IRQ_GetPriorityMask (void) {
378 return GIC_GetInterfacePriorityMask();
379}
380
381
382/// Set priority grouping field split point
383__WEAK int32_t IRQ_SetPriorityGroupBits (uint32_t bits) {
384 int32_t status;
385
386 if (bits == IRQ_PRIORITY_Msk) {
387 bits = 7U;
388 }
389
390 if (bits < 8U) {
391 GIC_SetBinaryPoint (7U - bits);
392 status = 0;
393 } else {
394 status = -1;
395 }
396
397 return (status);
398}
399
400
401/// Get priority grouping field split point
402__WEAK uint32_t IRQ_GetPriorityGroupBits (void) {
403 uint32_t bp;
404
405 bp = GIC_GetBinaryPoint() & 0x07U;
406
407 return (7U - bp);
408}
409
410#endif
Note: See TracBrowser for help on using the repository browser.