Annotation of prex/sys/arch/arm/gba/interrupt.c, Revision 1.1.1.1
1.1 nbrk 1: /*-
2: * Copyright (c) 2005-2007, Kohsuke Ohtani
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the author nor the names of any co-contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: /*
31: * interrupt.c - interrupt handling routines for GBA
32: */
33:
34: #include <kernel.h>
35: #include <irq.h>
36: #include <locore.h>
37: #include <cpu.h>
38:
39: /* Interrupt hook vector */
40: #define IRQ_VECTOR *(uint32_t *)0x3007ffc
41:
42: /* Registers for interrupt control unit - enable/flag/master */
43: #define ICU_IE (*(volatile uint16_t *)0x4000200)
44: #define ICU_IF (*(volatile uint16_t *)0x4000202)
45: #define ICU_IME (*(volatile uint16_t *)0x4000208)
46:
47: /* ICU_IE */
48: #define IRQ_VALID 0x3fff
49:
50: /* ICU_IME */
51: #define IRQ_OFF 0
52: #define IRQ_ON 1
53:
54: /*
55: * Interrupt priority level
56: *
57: * Each interrupt has its logical priority level, with 0 being the highest
58: * priority. While some ISR is running, all lower priority interrupts
59: * are masked off.
60: */
61: volatile int irq_level;
62:
63: /*
64: * Interrupt mapping table
65: */
66: static int ipl_table[NIRQS]; /* Vector -> level */
67: static uint16_t mask_table[NIPLS]; /* Level -> mask */
68:
69: /*
70: * Set mask for current ipl
71: */
72: #define update_mask() ICU_IE = mask_table[irq_level]
73:
74: /*
75: * Unmask interrupt in PIC for specified irq.
76: * The interrupt mask table is also updated.
77: * Assumed CPU interrupt is disabled in caller.
78: */
79: void
80: interrupt_unmask(int vector, int level)
81: {
82: int i;
83: uint16_t unmask = (uint16_t)1 << vector;
84:
85: ipl_table[vector] = level;
86: /*
87: * Unmask target interrupt for all
88: * lower interrupt levels.
89: */
90: for (i = 0; i < level; i++)
91: mask_table[i] |= unmask;
92: update_mask();
93: }
94:
95: /*
96: * Mask interrupt in PIC for specified irq.
97: * Interrupt must be disabled when this routine is called.
98: */
99: void
100: interrupt_mask(int vector)
101: {
102: int i, level;
103: u_int mask = (uint16_t)~(1 << vector);
104:
105: level = ipl_table[vector];
106: for (i = 0; i < level; i++)
107: mask_table[i] &= mask;
108: ipl_table[vector] = IPL_NONE;
109: update_mask();
110: }
111:
112: /*
113: * Setup interrupt mode.
114: * Select whether an interrupt trigger is edge or level.
115: */
116: void
117: interrupt_setup(int vector, int mode)
118: {
119: /* nop */
120: }
121:
122: /*
123: * Dispatch interrupt
124: *
125: */
126: void
127: interrupt_dispatch(int vector)
128: {
129: int old_ipl;
130:
131: /* Save & update interrupt level */
132: old_ipl = irq_level;
133: irq_level = ipl_table[vector];
134: update_mask();
135:
136: /* Send acknowledge to ICU for this irq */
137: ICU_IF = (uint16_t)(1 << vector);
138:
139: /* Allow another interrupt that has higher priority */
140: interrupt_enable();
141:
142: /* Dispatch interrupt */
143: irq_handler(vector);
144:
145: interrupt_disable();
146:
147: /* Restore interrupt level */
148: irq_level = old_ipl;
149: update_mask();
150: }
151:
152: /*
153: * Common interrupt handler.
154: */
155: void
156: interrupt_handler(void)
157: {
158: uint16_t bits;
159: int vector;
160:
161: bits = ICU_IF;
162: retry:
163: for (vector = 0; vector < NIRQS; vector++) {
164: if (bits & (uint16_t)(1 << vector))
165: break;
166: }
167: if (vector == NIRQS)
168: goto out;
169:
170: interrupt_dispatch(vector);
171:
172: /*
173: * Multiple interrupts can be fired in case of GBA.
174: * So, we have to check the interrupt status, again.
175: */
176: bits = ICU_IF;
177: if (bits & IRQ_VALID)
178: goto retry;
179: out:
180: return;
181: }
182:
183: /*
184: * Initialize interrupt controllers.
185: * All interrupts will be masked off.
186: */
187: void
188: interrupt_init(void)
189: {
190: int i;
191:
192: irq_level = IPL_NONE;
193:
194: for (i = 0; i < NIRQS; i++)
195: ipl_table[i] = IPL_NONE;
196:
197: for (i = 0; i < NIPLS; i++)
198: mask_table[i] = 0;
199:
200: ICU_IME = IRQ_OFF;
201: IRQ_VECTOR = (uint32_t)interrupt_entry; /* Interrupt hook address */
202: ICU_IE = 0; /* Mask all interrupts */
203: ICU_IME = IRQ_ON;
204: }
CVSweb