0
|
1 // Support of ARM PrimeCell Vectored Interrrupt Controller (PL190)
|
|
2 #include "types.h"
|
|
3 #include "defs.h"
|
|
4 #include "param.h"
|
|
5 #include "arm.h"
|
|
6 #include "memlayout.h"
|
|
7 #include "mmu.h"
|
|
8
|
|
9 // PL190 supports the vectored interrupts and non-vectored interrupts.
|
|
10 // In this code, we use non-vected interrupts (aka. simple interrupt).
|
|
11 // The flow to handle simple interrupts is as the following:
|
|
12 // 1. an interrupt (IRQ) occurs, trap.c branches to our IRQ handler
|
|
13 // 2. read the VICIRQStatus register, for each source generating
|
|
14 // the interrrupt:
|
|
15 // 2.1 locate the correct ISR
|
|
16 // 2.2 execute the ISR
|
|
17 // 2.3 clear the interrupt
|
|
18 // 3 return to trap.c, which will resume interrupted routines
|
|
19 // Note: must not read VICVectorAddr
|
|
20
|
|
21
|
|
22 // define the register offsets (in the unit of 4 bytes). The base address
|
|
23 // of the VIC depends on the board
|
|
24 static volatile uint* vic_base;
|
|
25
|
|
26 #define VIC_IRQSTATUS 0 // status of interrupts after masking by ENABLE and SEL
|
|
27 #define VIC_FIQSTATUS 1 // status of interrupts after masking
|
|
28 #define VIC_RAWINTR 2 // status of interrupts before masking
|
|
29 #define VIC_INTSEL 3 // interrupt select (IRQ or FIQ), by default IRQ
|
|
30 #define VIC_INTENABLE 4 // enable interrupts (1 - enabled, 0 - disabled)
|
|
31 #define VIC_INTCLEAR 5 // clear bits in ENABLE register (1 - clear it)
|
|
32 #define VIC_PROTECTIOIN 8 // who can access: user or privileged
|
|
33
|
|
34 #define NUM_INTSRC 32 // numbers of interrupt source supported
|
|
35
|
|
36 static ISR isrs[NUM_INTSRC];
|
|
37
|
|
38 static void default_isr (struct trapframe *tf, int n)
|
|
39 {
|
|
40 cprintf ("unhandled interrupt: %d\n", n);
|
|
41 }
|
|
42
|
|
43 // initialize the PL190 VIC
|
|
44 void pic_init (void * base)
|
|
45 {
|
|
46 int i;
|
|
47
|
|
48 // set the base for the controller and disable all interrupts
|
|
49 vic_base = base;
|
|
50 vic_base[VIC_INTCLEAR] = 0xFFFFFFFF;
|
|
51
|
|
52 for (i = 0; i < NUM_INTSRC; i++) {
|
|
53 isrs[i] = default_isr;
|
|
54 }
|
|
55 }
|
|
56
|
|
57 // enable an interrupt (with the ISR)
|
|
58 void pic_enable (int n, ISR isr)
|
|
59 {
|
|
60 if ((n<0) || (n >= NUM_INTSRC)) {
|
|
61 panic ("invalid interrupt source");
|
|
62 }
|
|
63
|
|
64 // write 1 bit enable the interrupt, 0 bit has no effect
|
|
65 isrs[n] = isr;
|
|
66 vic_base[VIC_INTENABLE] = (1 << n);
|
|
67 }
|
|
68
|
|
69 // disable an interrupt
|
|
70 void pic_disable (int n)
|
|
71 {
|
|
72 if ((n<0) || (n >= NUM_INTSRC)) {
|
|
73 panic ("invalid interrupt source");
|
|
74 }
|
|
75
|
|
76 vic_base[VIC_INTCLEAR] = (1 << n);
|
|
77 isrs[n] = default_isr;
|
|
78 }
|
|
79
|
|
80 // dispatch the interrupt
|
|
81 void pic_dispatch (struct trapframe *tp)
|
|
82 {
|
|
83 uint intstatus;
|
|
84 int i;
|
|
85
|
|
86 intstatus = vic_base[VIC_IRQSTATUS];
|
|
87
|
|
88 for (i = 0; i < NUM_INTSRC; i++) {
|
|
89 if (intstatus & (1<<i)) {
|
|
90 isrs[i](tp, i);
|
|
91 }
|
|
92 }
|
|
93
|
|
94 intstatus = vic_base[VIC_IRQSTATUS];
|
|
95 }
|
|
96
|