blob: ef5f22183067aaef3b654e0188e3c47b5eb441e8 [file] [log] [blame]
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -07001/*
2 * Copyright (c) 2008 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <err.h>
24#include <sys/types.h>
25#include <debug.h>
26#include <reg.h>
27#include <kernel/thread.h>
28#include <platform/interrupts.h>
29#include <arch/ops.h>
30#include <arch/arm.h>
31#include "platform_p.h"
32#include <platform/integrator.h>
33
34struct int_handler_struct {
35 int_handler handler;
36 void *arg;
37};
38
39static struct int_handler_struct int_handler_table[INT_VECTORS];
40
41#if 0
42static const uint32_t icBase[5] = {
43 INTCON0_BASE, INTCON1_BASE, INTCON2_BASE, INTCON3_BASE, INTCON4_BASE };
44
45/* a bitmap of the level triggered interrupt vectors */
46static uint32_t level_trigger[5] = {
47 0xb3fefe8f, // level 1 0-31
48 0xfdb3c1fd, // level 2 0-31
49 0xfffff7ff, // level 2 32-63
50 0xbfffffff, // level 2 64-95
51 0xffffffff // level 2 96-128
52};
53
54inline volatile uint32_t *ICReg(uint controller, uint reg)
55{
56 return (volatile uint32_t *)(icBase[controller] + reg);
57}
58
59inline uint32_t readICReg(uint controller, uint reg)
60{
61 return *ICReg(controller, reg);
62}
63inline void writeICReg(uint controller, uint reg, uint val)
64{
65 *ICReg(controller, reg) = val;
66}
67
68inline uint vectorToController(uint vector)
69{
70 return vector / 32;
71}
72#endif
73
74void platform_init_interrupts(void)
75{
76#if 0
77 unsigned int i;
78
79 // mask all interrupts
80 *ICReg(0, INTCON_MIR) = 0xfffffffa;
81 *ICReg(1, INTCON_MIR) = 0xffffffff;
82 *ICReg(2, INTCON_MIR) = 0xffffffff;
83 *ICReg(3, INTCON_MIR) = 0xffffffff;
84 *ICReg(4, INTCON_MIR) = 0xffffffff;
85
86 // set up each of the interrupts
87 for (i = 0; i < INT_VECTORS; i++) {
88 // set each vector up as high priority, IRQ, and default edge/level sensitivity
89 *ICReg(i / 32, INTCON_ILR_BASE + 4*(i%32)) = ((level_trigger[i/32] & (1<<(i%32))) ? (1<<1) : (0<<1)) | 0;
90 }
91
92 // clear any pending interrupts
93 *ICReg(0, INTCON_ITR) = 0;
94 *ICReg(1, INTCON_ITR) = 0;
95 *ICReg(2, INTCON_ITR) = 0;
96 *ICReg(3, INTCON_ITR) = 0;
97 *ICReg(4, INTCON_ITR) = 0;
98
99 // globally unmask interrupts
100 *ICReg(1, INTCON_CONTROL) = 3;
101 *ICReg(0, INTCON_CONTROL) = 3;
102 *ICReg(0, INTCON_GMR) = 0;
103
104 dprintf("end of platform_init_interrupts\n");
105
106#if 0
107 arch_enable_ints();
108
109 dprintf("&ITR0 0x%x\n", (uint32_t)ICReg(0, INTCON_ITR));
110
111 dprintf("ITR0 0x%x\n", *ICReg(0, INTCON_ITR));
112 dprintf("MIR0 0x%x\n", *ICReg(0, INTCON_MIR));
113 dprintf("SIR_IRQ0 0x%x\n", *ICReg(0, INTCON_SIR_IRQ));
114
115 *ICReg(0, INTCON_ILR_BASE + 4*7) = 0;
116 *ICReg(0, INTCON_MIR) &= ~0x80;
117
118 dprintf("triggering int\n");
119
120 *ICReg(0, INTCON_SISR) = 0x80;
121
122 dprintf("ITR0 0x%x\n", *ICReg(0, INTCON_ITR));
123 dprintf("MIR0 0x%x\n", *ICReg(0, INTCON_MIR));
124 dprintf("SIR_IRQ0 0x%x\n", *ICReg(0, INTCON_SIR_IRQ));
125
126 for(;;);
127#endif
128#endif
129}
130
131status_t mask_interrupt(unsigned int vector, bool *oldstate)
132{
133#if 0
134 if (vector >= INT_VECTORS)
135 return ERR_INVALID_ARGS;
136
137// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
138
139 enter_critical_section();
140
141 if (oldstate)
142 *oldstate = false;
143
144 volatile uint32_t *mir = ICReg(vectorToController(vector), INTCON_MIR);
145 *mir = *mir | (1<<(vector % 32));
146
147 exit_critical_section();
148#endif
149
150 return NO_ERROR;
151}
152
153status_t unmask_interrupt(unsigned int vector, bool *oldstate)
154{
155#if 0
156 if (vector >= INT_VECTORS)
157 return ERR_INVALID_ARGS;
158
159// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
160
161 enter_critical_section();
162
163 if (oldstate)
164 *oldstate = false;
165
166 volatile uint32_t *mir = ICReg(vectorToController(vector), INTCON_MIR);
167 *mir = *mir & ~(1<<(vector % 32));
168
169 exit_critical_section();
170#endif
171
172 return NO_ERROR;
173}
174
175void platform_irq(struct arm_iframe *frame)
176{
177 PANIC_UNIMPLEMENTED;
178#if 0
179 // get the current vector
180 unsigned int vector;
181
182 inc_critical_section();
183
184 // read from the first level int handler
185 vector = *ICReg(0, INTCON_SIR_IRQ);
186
187 // see if it's coming from the second level handler
188 if (vector == 0) {
189 vector = *ICReg(1, INTCON_SIR_IRQ) + 32;
190 }
191
192// dprintf("platform_irq: spsr 0x%x, pc 0x%x, currthread %p, vector %d\n", frame->spsr, frame->pc, current_thread, vector);
193
194 // deliver the interrupt
195 enum handler_return ret;
196
197 ret = INT_NO_RESCHEDULE;
198 if (int_handler_table[vector].handler)
199 ret = int_handler_table[vector].handler(int_handler_table[vector].arg);
200
201 // ack the interrupt
202 if (vector >= 32) {
203 // interrupt is chained, so ack the second level first, and then the first
204 *ICReg(vector / 32, INTCON_ITR) = ~(1 << (vector % 32));
205 *ICReg(1, INTCON_CONTROL) |= 1;
206 vector = 0; // force the following code to ack the chained first level vector
207 }
208
209 *ICReg(0, INTCON_ITR) = ~(1 << vector);
210 *ICReg(0, INTCON_CONTROL) = 1;
211
212 if (ret == INT_RESCHEDULE)
213 thread_preempt();
214
215 dec_critical_section();
216
217// dprintf("platform_irq: exit\n");
218#endif
219}
220
221void platform_fiq(struct arm_iframe *frame)
222{
223 PANIC_UNIMPLEMENTED;
224}
225
226void register_int_handler(unsigned int vector, int_handler handler, void *arg)
227{
228 if (vector >= INT_VECTORS)
229 panic("register_int_handler: vector out of range %d\n", vector);
230
231 enter_critical_section();
232
233 int_handler_table[vector].handler = handler;
234 int_handler_table[vector].arg = arg;
235
236 exit_critical_section();
237}
238