Annotation of prex-old/sys/arch/arm/cats/interrupt.c, Revision 1.2
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: /*
1.2 ! nbrk 31: * interrupt.c - interrupt handling routines for StrongARM-110 INTC.
1.1 nbrk 32: */
33:
34: #include <kernel.h>
35: #include <irq.h>
36: #include <locore.h>
37:
1.2 ! nbrk 38: /* Registers for interrupt control unit */
! 39: #define SAIC_BASE 0x90050000
! 40: #define SAIC_ICIP 0
! 41: #define SAIC_ICMR 0x04
! 42: #define SAIC_ICLR 0x08
! 43: #define SAIC_ICFP 0x10
! 44: #define SAIC_ICPR 0x20
! 45: #define SAIC_ICCR 0x0c
1.1 nbrk 46:
1.2 ! nbrk 47: /*
! 48: * Interrupt line routing (CPU IRQ/FIQ)
! 49: */
! 50: #define IMODE_CPUIRQ 0
! 51: #define IMODE_CPUFIQ 1
1.1 nbrk 52:
53: /*
54: * Interrupt priority level
55: *
56: * Each interrupt has its logical priority level, with 0 being the highest
57: * priority. While some ISR is running, all lower priority interrupts
58: * are masked off.
59: */
60: volatile int irq_level;
61:
62: /*
63: * Interrupt mapping table
64: */
65: static int ipl_table[NIRQS]; /* Vector -> level */
1.2 ! nbrk 66: static uint32_t mask_table[NIPLS]; /* Level -> mask */
! 67:
! 68: void saic_updatemask(uint32_t mask);
! 69: void saic_routeto(int intrno, int irqfiq);
1.1 nbrk 70:
71: /*
72: * Set mask for current ipl
73: */
1.2 ! nbrk 74: #define interrupt_updatemask() saic_updatemask(mask_table[irq_level]);
! 75:
! 76: /*
! 77: * Write new mask to Mask Register.
! 78: */
! 79: void
! 80: saic_updatemask(uint32_t mask)
! 81: {
! 82: /* XXX */
! 83: *(volatile uint32_t *)(SAIC_BASE + SAIC_ICMR) = mask;
! 84: }
! 85:
! 86: /*
! 87: * Interrupt line routing to IRQ/FIQ.
! 88: */
! 89: void
! 90: saic_routeto(int intrno, int irqfiq)
! 91: {
! 92: uint32_t bits;
! 93:
! 94:
! 95: bits = *(volatile uint32_t *)(SAIC_BASE + SAIC_ICLR);
! 96:
! 97: switch(irqfiq) {
! 98: case IMODE_CPUIRQ:
! 99: bits &= ~(1 << intrno);
! 100: break;
! 101:
! 102: case IMODE_CPUFIQ:
! 103: bits |= 1 << intrno;
! 104: break;
! 105:
! 106: default:
! 107: panic("saic_routeto: bogus irqfiq %u for intr %u", irqfiq, intrno);
! 108: /* NOTREACHED */
! 109: }
! 110: }
1.1 nbrk 111:
112: /*
113: * Unmask interrupt in PIC for specified irq.
114: * The interrupt mask table is also updated.
115: * Assumed CPU interrupt is disabled in caller.
116: */
117: void
118: interrupt_unmask(int vector, int level)
119: {
120: int i;
1.2 ! nbrk 121: uint32_t unmask = 1 << vector;
1.1 nbrk 122:
123: ipl_table[vector] = level;
124: /*
125: * Unmask target interrupt for all
126: * lower interrupt levels.
127: */
128: for (i = 0; i < level; i++)
129: mask_table[i] |= unmask;
1.2 ! nbrk 130:
! 131: interrupt_updatemask();
1.1 nbrk 132: }
133:
134: /*
135: * Mask interrupt in PIC for specified irq.
136: * Interrupt must be disabled when this routine is called.
137: */
138: void
139: interrupt_mask(int vector)
140: {
141: int i, level;
1.2 ! nbrk 142: uint32_t mask = (uint32_t)~(1 << vector);
1.1 nbrk 143:
144: level = ipl_table[vector];
145: for (i = 0; i < level; i++)
146: mask_table[i] &= mask;
1.2 ! nbrk 147:
1.1 nbrk 148: ipl_table[vector] = IPL_NONE;
1.2 ! nbrk 149:
! 150: interrupt_updatemask();
1.1 nbrk 151: }
152:
153: /*
154: * Setup interrupt mode.
155: * Select whether an interrupt trigger is edge or level.
156: */
157: void
158: interrupt_setup(int vector, int mode)
159: {
160: /* nop */
161: }
162:
163: /*
164: * Dispatch interrupt
165: *
166: */
167: void
168: interrupt_dispatch(int vector)
169: {
170: int old_ipl;
171:
1.2 ! nbrk 172: printk("interrupt_dispatch()\n");
! 173:
1.1 nbrk 174: /* Save & update interrupt level */
175: old_ipl = irq_level;
176: irq_level = ipl_table[vector];
1.2 ! nbrk 177: interrupt_updatemask();
1.1 nbrk 178:
179: /* Allow another interrupt that has higher priority */
180: interrupt_enable();
181:
182: /* Dispatch interrupt */
183: irq_handler(vector);
184:
185: interrupt_disable();
186:
187: /* Restore interrupt level */
188: irq_level = old_ipl;
1.2 ! nbrk 189: interrupt_updatemask();
1.1 nbrk 190: }
191:
192: /*
193: * Common interrupt handler.
1.2 ! nbrk 194: * Our task is to scan active pending intrs and dispatch them.
1.1 nbrk 195: */
196: void
197: interrupt_handler(void)
198: {
1.2 ! nbrk 199: uint32_t bits;
1.1 nbrk 200: int vector;
201:
1.2 ! nbrk 202:
! 203: /* XXX we use only IRQs for now, so don't count FIQs */
! 204: bits = *(volatile uint32_t *)(SAIC_BASE + SAIC_ICIP);
! 205:
! 206: /* dispatch all pending interrupts */
1.1 nbrk 207: for (vector = 0; vector < NIRQS; vector++) {
1.2 ! nbrk 208: if (bits & (1 << vector))
! 209: interrupt_dispatch(vector);
! 210:
! 211: /* XXX pending intr clears within interrupting device */
1.1 nbrk 212: }
213:
214: }
215:
216: /*
217: * Initialize interrupt controllers.
1.2 ! nbrk 218: * All interrupts will be masked off and routed to CPU IRQ line.
1.1 nbrk 219: */
220: void
221: interrupt_init(void)
222: {
223: int i;
224:
1.2 ! nbrk 225: interrupt_disable();
! 226:
1.1 nbrk 227: irq_level = IPL_NONE;
228:
229: for (i = 0; i < NIRQS; i++)
230: ipl_table[i] = IPL_NONE;
231:
232: for (i = 0; i < NIPLS; i++)
233: mask_table[i] = 0;
234:
1.2 ! nbrk 235: /*
! 236: * XXX route all Interrupt Controller interrupts to CPU IRQ line.
! 237: */
! 238: for (i = 0; i < NIRQS; i++)
! 239: saic_routeto(i, IMODE_CPUIRQ);
! 240:
! 241: interrupt_updatemask();
! 242:
! 243: interrupt_enable();
1.1 nbrk 244: }
CVSweb