blob: 187f3cb655b908c4758c764a62a8a4a0944b7ac7 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/**
2 * \file interrupt.c
3 *
4 * \brief Interrupt related APIs.
5 *
6 * This file contains the APIs for configuring AINTC
7 */
8
9/*
10* Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
11*/
12/*
13* Redistribution and use in source and binary forms, with or without
14* modification, are permitted provided that the following conditions
15* are met:
16*
17* Redistributions of source code must retain the above copyright
18* notice, this list of conditions and the following disclaimer.
19*
20* Redistributions in binary form must reproduce the above copyright
21* notice, this list of conditions and the following disclaimer in the
22* documentation and/or other materials provided with the
23* distribution.
24*
25* Neither the name of Texas Instruments Incorporated nor the names of
26* its contributors may be used to endorse or promote products derived
27* from this software without specific prior written permission.
28*
29* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40*
41*/
42
43
44#include "hw_intc.h"
45#include "interrupt.h"
46#include "hw_types.h"
47#include "soc_AM335x.h"
48#include "cpu.h"
49
50/******************************************************************************
51** INTERNAL MACRO DEFINITIONS
52******************************************************************************/
53#define REG_IDX_SHIFT (0x05)
54#define REG_BIT_MASK (0x1F)
55#define NUM_INTERRUPTS (128u)
56
57/**************** *************************************************************
58** STATIC VARIABLE DEFINITIONS
59******************************************************************************/
60void (*fnRAMVectors[NUM_INTERRUPTS])(void);
61
62/******************************************************************************
63** STATIC FUNCTION DECLARATIONS
64******************************************************************************/
65static void IntDefaultHandler(void);
66
67/******************************************************************************
68** API FUNCTION DEFINITIONS
69******************************************************************************/
70
71/**
72 *
73 * The Default Interrupt Handler.
74 *
75 * This is the default interrupt handler for all interrupts. It simply loops
76 * forever so that the system state is preserved for observation by a
77 * debugger. Since interrupts should be disabled before unregistering the
78 * corresponding handler, this should never be called.
79 *
80 *
81 **/
82static void IntDefaultHandler(void)
83{
84 /* Go into an infinite loop.*/
85 while(1)
86 {
87 ;
88 }
89}
90
91/**
92 * \brief Registers an interrupt Handler in the interrupt vector table for
93 * system interrupts.
94 *
95 * \param intrNum - Interrupt Number
96 * \param fnHandler - Function pointer to the ISR
97 *
98 * Note: When the interrupt occurs for the sytem interrupt number indicated,
99 * the control goes to the ISR given as the parameter.
100 *
101 * \return None.
102 **/
103void IntRegister(unsigned int intrNum, void (*fnHandler)(void))
104{
105 /* Assign ISR */
106 fnRAMVectors[intrNum] = fnHandler;
107}
108
109/**
110 * \brief Unregisters an interrupt
111 *
112 * \param intrNum - Interrupt Number
113 *
114 * Note: Once an interrupt is unregistered it will enter infinite loop once
115 * an interrupt occurs
116 *
117 * \return None.
118 **/
119void IntUnRegister(unsigned int intrNum)
120{
121 /* Assign default ISR */
122 fnRAMVectors[intrNum] = IntDefaultHandler;
123}
124
125/**
126 * \brief This API is used to initialize the interrupt controller. This API
127 * shall be called before using the interrupt controller.
128 *
129 * \param None
130 *
131 * \return None.
132 *
133 **/
134void IntAINTCInit(void)
135{
136 /* Reset the ARM interrupt controller */
137 HWREG(SOC_AINTC_REGS + INTC_SYSCONFIG) = INTC_SYSCONFIG_SOFTRESET;
138
139 /* Wait for the reset to complete */
140 while((HWREG(SOC_AINTC_REGS + INTC_SYSSTATUS)
141 & INTC_SYSSTATUS_RESETDONE) != INTC_SYSSTATUS_RESETDONE);
142
143 /* Enable any interrupt generation by setting priority threshold */
144 HWREG(SOC_AINTC_REGS + INTC_THRESHOLD) =
145 INTC_THRESHOLD_PRIORITYTHRESHOLD;
146}
147
148/**
149 * \brief This API assigns a priority to an interrupt and routes it to
150 * either IRQ or to FIQ. Priority 0 is the highest priority level
151 * Among the host interrupts, FIQ has more priority than IRQ.
152 *
153 * \param intrNum - Interrupt number
154 * \param priority - Interrupt priority level
155 * \param hostIntRoute - The host interrupt IRQ/FIQ to which the interrupt
156 * is to be routed.
157 * 'priority' can take any value from 0 to 127, 0 being the highest and
158 * 127 being the lowest priority.
159 *
160 * 'hostIntRoute' can take one of the following values \n
161 * AINTC_HOSTINT_ROUTE_IRQ - To route the interrupt to IRQ \n
162 * AINTC_HOSTINT_ROUTE_FIQ - To route the interrupt to FIQ
163 *
164 * \return None.
165 *
166 **/
167void IntPrioritySet(unsigned int intrNum, unsigned int priority,
168 unsigned int hostIntRoute)
169{
170 HWREG(SOC_AINTC_REGS + INTC_ILR(intrNum)) =
171 ((priority << INTC_ILR_PRIORITY_SHIFT)
172 & INTC_ILR_PRIORITY)
173 | hostIntRoute ;
174}
175
176/**
177 * \brief This API enables the system interrupt in AINTC. However, for
178 * the interrupt generation, make sure that the interrupt is
179 * enabled at the peripheral level also.
180 *
181 * \param intrNum - Interrupt number
182 *
183 * \return None.
184 *
185 **/
186void IntSystemEnable(unsigned int intrNum)
187{
188 /* Disable the system interrupt in the corresponding MIR_CLEAR register */
189 HWREG(SOC_AINTC_REGS + INTC_MIR_CLEAR(intrNum >> REG_IDX_SHIFT))
190 = (0x01 << (intrNum & REG_BIT_MASK));
191}
192
193/**
194 * \brief This API disables the system interrupt in AINTC.
195 *
196 * \param intrNum - Interrupt number
197 *
198 * \return None.
199 *
200 **/
201void IntSystemDisable(unsigned int intrNum)
202{
203 /* Enable the system interrupt in the corresponding MIR_SET register */
204 HWREG(SOC_AINTC_REGS + INTC_MIR_SET(intrNum >> REG_IDX_SHIFT))
205 = (0x01 << (intrNum & REG_BIT_MASK));
206}
207
208/**
209 * \brief Sets the interface clock to be free running
210 *
211 * \param None.
212 *
213 * \return None.
214 *
215 **/
216void IntIfClkFreeRunSet(void)
217{
218 HWREG(SOC_AINTC_REGS + INTC_SYSCONFIG)&= ~INTC_SYSCONFIG_AUTOIDLE;
219}
220
221/**
222 * \brief When this API is called, automatic clock gating strategy is applied
223 * based on the interface bus activity.
224 *
225 * \param None.
226 *
227 * \return None.
228 *
229 **/
230void IntIfClkAutoGateSet(void)
231{
232 HWREG(SOC_AINTC_REGS + INTC_SYSCONFIG)|= INTC_SYSCONFIG_AUTOIDLE;
233}
234
235/**
236 * \brief Reads the active IRQ number.
237 *
238 * \param None
239 *
240 * \return Active IRQ number.
241 *
242 **/
243unsigned int IntActiveIrqNumGet(void)
244{
245 return (HWREG(SOC_AINTC_REGS + INTC_SIR_IRQ) & INTC_SIR_IRQ_ACTIVEIRQ);
246}
247
248/**
249 * \brief Reads the active FIQ number.
250 *
251 * \param None
252 *
253 * \return Active FIQ number.
254 *
255 **/
256unsigned int IntActiveFiqNumGet(void)
257{
258 return (HWREG(SOC_AINTC_REGS + INTC_SIR_FIQ) & INTC_SIR_FIQ_ACTIVEFIQ);
259}
260
261/**
262 * \brief Reads the spurious IRQ Flag. Spurious IRQ flag is reflected in both
263 * SIR_IRQ and IRQ_PRIORITY registers of the interrupt controller.
264 *
265 * \param None
266 *
267 * \return Spurious IRQ Flag.
268 *
269 **/
270unsigned int IntSpurIrqFlagGet(void)
271{
272 return ((HWREG(SOC_AINTC_REGS + INTC_SIR_IRQ)
273 & INTC_SIR_IRQ_SPURIOUSIRQ)
274 >> INTC_SIR_IRQ_SPURIOUSIRQ_SHIFT);
275}
276
277/**
278 * \brief Reads the spurious FIQ Flag. Spurious FIQ flag is reflected in both
279 * SIR_FIQ and FIQ_PRIORITY registers of the interrupt controller.
280 *
281 * \param None
282 *
283 * \return Spurious IRQ Flag.
284 *
285 **/
286unsigned int IntSpurFiqFlagGet(void)
287{
288 return ((HWREG(SOC_AINTC_REGS + INTC_SIR_FIQ)
289 & INTC_SIR_FIQ_SPURIOUSFIQ)
290 >> INTC_SIR_FIQ_SPURIOUSFIQ_SHIFT);
291}
292
293/**
294 * \brief Enables protection mode for the interrupt controller register access.
295 * When the protection is enabled, the registers will be accessible only
296 * in privileged mode of the CPU.
297 *
298 * \param None
299 *
300 * \return None
301 *
302 **/
303void IntProtectionEnable(void)
304{
305 HWREG(SOC_AINTC_REGS + INTC_PROTECTION) = INTC_PROTECTION_PROTECTION;
306}
307
308/**
309 * \brief Disables protection mode for the interrupt controller register access.
310 * When the protection is disabled, the registers will be accessible
311 * in both unprivileged and privileged mode of the CPU.
312 *
313 * \param None
314 *
315 * \return None
316 *
317 **/
318void IntProtectionDisable(void)
319{
320 HWREG(SOC_AINTC_REGS + INTC_PROTECTION) &= ~INTC_PROTECTION_PROTECTION;
321}
322
323/**
324 * \brief Enables the free running of input synchronizer clock
325 *
326 * \param None
327 *
328 * \return None
329 *
330 **/
331void IntSyncClkFreeRunSet(void)
332{
333 HWREG(SOC_AINTC_REGS + INTC_IDLE) &= ~INTC_IDLE_TURBO;
334}
335
336/**
337 * \brief When this API is called, Input synchronizer clock is auto-gated
338 * based on interrupt input activity
339 *
340 * \param None
341 *
342 * \return None
343 *
344 **/
345void IntSyncClkAutoGateSet(void)
346{
347 HWREG(SOC_AINTC_REGS + INTC_IDLE) |= INTC_IDLE_TURBO;
348}
349
350/**
351 * \brief Enables the free running of functional clock
352 *
353 * \param None
354 *
355 * \return None
356 *
357 **/
358void IntFuncClkFreeRunSet(void)
359{
360 HWREG(SOC_AINTC_REGS + INTC_IDLE) |= INTC_IDLE_FUNCIDLE;
361}
362
363/**
364 * \brief When this API is called, functional clock gating strategy
365 * is applied.
366 *
367 * \param None
368 *
369 * \return None
370 *
371 **/
372void IntFuncClkAutoGateSet(void)
373{
374 HWREG(SOC_AINTC_REGS + INTC_IDLE) &= ~INTC_IDLE_FUNCIDLE;
375}
376
377/**
378 * \brief Returns the currently active IRQ priority level.
379 *
380 * \param None
381 *
382 * \return Current IRQ priority
383 *
384 **/
385unsigned int IntCurrIrqPriorityGet(void)
386{
387 return (HWREG(SOC_AINTC_REGS + INTC_IRQ_PRIORITY)
388 & INTC_IRQ_PRIORITY_IRQPRIORITY);
389}
390
391/**
392 * \brief Returns the currently active FIQ priority level.
393 *
394 * \param None
395 *
396 * \return Current FIQ priority
397 *
398 **/
399unsigned int IntCurrFiqPriorityGet(void)
400{
401 return (HWREG(SOC_AINTC_REGS + INTC_FIQ_PRIORITY)
402 & INTC_FIQ_PRIORITY_FIQPRIORITY);
403}
404
405/**
406 * \brief Returns the priority threshold.
407 *
408 * \param None
409 *
410 * \return Priority threshold value.
411 *
412 **/
413unsigned int IntPriorityThresholdGet(void)
414{
415 return (HWREG(SOC_AINTC_REGS + INTC_THRESHOLD)
416 & INTC_THRESHOLD_PRIORITYTHRESHOLD);
417}
418
419/**
420 * \brief Sets the given priority threshold value.
421 *
422 * \param threshold - Priority threshold value
423 *
424 * 'threshold' can take any value from 0x00 to 0x7F. To disable
425 * priority threshold, write 0xFF.
426 *
427 * \return None.
428 *
429 **/
430void IntPriorityThresholdSet(unsigned int threshold)
431{
432 HWREG(SOC_AINTC_REGS + INTC_THRESHOLD) =
433 threshold & INTC_THRESHOLD_PRIORITYTHRESHOLD;
434}
435
436/**
437 * \brief Returns the raw interrupt status before masking.
438 *
439 * \param intrNum - the system interrupt number.
440 *
441 * \return TRUE - if the raw status is set \n
442 * FALSE - if the raw status is not set.
443 *
444 **/
445unsigned int IntRawStatusGet(unsigned int intrNum)
446{
447 return ((0 == ((HWREG(SOC_AINTC_REGS + INTC_ITR(intrNum >> REG_IDX_SHIFT))
448 >> (intrNum & REG_BIT_MASK))& 0x01)) ? FALSE : TRUE);
449}
450
451/**
452 * \brief Sets software interrupt for the given interrupt number.
453 *
454 * \param intrNum - the system interrupt number, for which software interrupt
455 * to be generated
456 *
457 * \return None
458 *
459 **/
460void IntSoftwareIntSet(unsigned int intrNum)
461{
462 /* Enable the software interrupt in the corresponding ISR_SET register */
463 HWREG(SOC_AINTC_REGS + INTC_ISR_SET(intrNum >> REG_IDX_SHIFT))
464 = (0x01 << (intrNum & REG_BIT_MASK));
465
466}
467
468/**
469 * \brief Clears the software interrupt for the given interrupt number.
470 *
471 * \param intrNum - the system interrupt number, for which software interrupt
472 * to be cleared.
473 *
474 * \return None
475 *
476 **/
477void IntSoftwareIntClear(unsigned int intrNum)
478{
479 /* Disable the software interrupt in the corresponding ISR_CLEAR register */
480 HWREG(SOC_AINTC_REGS + INTC_ISR_CLEAR(intrNum >> REG_IDX_SHIFT))
481 = (0x01 << (intrNum & REG_BIT_MASK));
482
483}
484
485/**
486 * \brief Returns the IRQ status after masking.
487 *
488 * \param intrNum - the system interrupt number
489 *
490 * \return TRUE - if interrupt is pending \n
491 * FALSE - in no interrupt is pending
492 *
493 **/
494unsigned int IntPendingIrqMaskedStatusGet(unsigned int intrNum)
495{
496 return ((0 ==(HWREG(SOC_AINTC_REGS + INTC_PENDING_IRQ(intrNum >> REG_IDX_SHIFT))
497 >> (((intrNum & REG_BIT_MASK)) & 0x01))) ? FALSE : TRUE);
498}
499
500/**
501 * \brief Returns the FIQ status after masking.
502 *
503 * \param intrNum - the system interrupt number
504 *
505 * \return TRUE - if interrupt is pending \n
506 * FALSE - in no interrupt is pending
507 *
508 **/
509unsigned int IntPendingFiqMaskedStatusGet(unsigned int intrNum)
510{
511 return ((0 ==(HWREG(SOC_AINTC_REGS + INTC_PENDING_FIQ(intrNum >> REG_IDX_SHIFT))
512 >> (((intrNum & REG_BIT_MASK)) & 0x01))) ? FALSE : TRUE);
513}
514
515/**
516 * \brief Enables the processor IRQ only in CPSR. Makes the processor to
517 * respond to IRQs. This does not affect the set of interrupts
518 * enabled/disabled in the AINTC.
519 *
520 * \param None
521 *
522 * \return None
523 *
524 * Note: This function call shall be done only in previleged mode of ARM
525 **/
526void IntMasterIRQEnable(void)
527{
528 /* Enable IRQ in CPSR.*/
529 CPUirqe();
530
531}
532
533/**
534 * \brief Disables the processor IRQ only in CPSR.Prevents the processor to
535 * respond to IRQs. This does not affect the set of interrupts
536 * enabled/disabled in the AINTC.
537 *
538 * \param None
539 *
540 * \return None
541 *
542 * Note: This function call shall be done only in previleged mode of ARM
543 **/
544void IntMasterIRQDisable(void)
545{
546 /* Disable IRQ in CPSR.*/
547 CPUirqd();
548}
549
550/**
551 * \brief Enables the processor FIQ only in CPSR. Makes the processor to
552 * respond to FIQs. This does not affect the set of interrupts
553 * enabled/disabled in the AINTC.
554 *
555 * \param None
556 *
557 * \return None
558 *
559 * Note: This function call shall be done only in previleged mode of ARM
560 **/
561void IntMasterFIQEnable(void)
562{
563 /* Enable FIQ in CPSR.*/
564 CPUfiqe();
565}
566
567/**
568 * \brief Disables the processor FIQ only in CPSR.Prevents the processor to
569 * respond to FIQs. This does not affect the set of interrupts
570 * enabled/disabled in the AINTC.
571 *
572 * \param None
573 *
574 * \return None
575 *
576 * Note: This function call shall be done only in previleged mode of ARM
577 **/
578void IntMasterFIQDisable(void)
579{
580 /* Disable FIQ in CPSR.*/
581 CPUfiqd();
582}
583
584/**
585 * \brief Returns the status of the interrupts FIQ and IRQ.
586 *
587 * \param None
588 *
589 * \return Status of interrupt as in CPSR.
590 *
591 * Note: This function call shall be done only in previleged mode of ARM
592 **/
593unsigned int IntMasterStatusGet(void)
594{
595 return CPUIntStatus();
596}
597
598/**
599 * \brief Read and save the stasus and Disables the processor IRQ .
600 * Prevents the processor to respond to IRQs.
601 *
602 * \param None
603 *
604 * \return Current status of IRQ
605 *
606 * Note: This function call shall be done only in previleged mode of ARM
607 **/
608unsigned char IntDisable(void)
609{
610 unsigned char status;
611
612 /* Reads the current status.*/
613 status = (IntMasterStatusGet() & 0xFF);
614
615 /* Disable the Interrupts.*/
616 IntMasterIRQDisable();
617
618 return status;
619}
620
621/**
622 * \brief Restore the processor IRQ only status. This does not affect
623 * the set of interrupts enabled/disabled in the AINTC.
624 *
625 * \param The status returned by the IntDisable fundtion.
626 *
627 * \return None
628 *
629 * Note: This function call shall be done only in previleged mode of ARM
630 **/
631void IntEnable(unsigned char status)
632{
633 if((status & 0x80) == 0)
634 {
635 IntMasterIRQEnable();
636 }
637}
638
639/********************************** End Of File ******************************/
640
641