diff options
Diffstat (limited to 'arch/m68k/platform/68328/ints.c')
-rw-r--r-- | arch/m68k/platform/68328/ints.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/arch/m68k/platform/68328/ints.c b/arch/m68k/platform/68328/ints.c new file mode 100644 index 000000000000..e5631831a200 --- /dev/null +++ b/arch/m68k/platform/68328/ints.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * linux/arch/m68knommu/platform/68328/ints.c | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file COPYING in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright 1996 Roman Zippel | ||
9 | * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com> | ||
10 | */ | ||
11 | |||
12 | #include <linux/types.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/irq.h> | ||
17 | #include <asm/traps.h> | ||
18 | #include <asm/io.h> | ||
19 | #include <asm/machdep.h> | ||
20 | |||
21 | #if defined(CONFIG_M68328) | ||
22 | #include <asm/MC68328.h> | ||
23 | #elif defined(CONFIG_M68EZ328) | ||
24 | #include <asm/MC68EZ328.h> | ||
25 | #elif defined(CONFIG_M68VZ328) | ||
26 | #include <asm/MC68VZ328.h> | ||
27 | #endif | ||
28 | |||
29 | /* assembler routines */ | ||
30 | asmlinkage void system_call(void); | ||
31 | asmlinkage void buserr(void); | ||
32 | asmlinkage void trap(void); | ||
33 | asmlinkage void trap3(void); | ||
34 | asmlinkage void trap4(void); | ||
35 | asmlinkage void trap5(void); | ||
36 | asmlinkage void trap6(void); | ||
37 | asmlinkage void trap7(void); | ||
38 | asmlinkage void trap8(void); | ||
39 | asmlinkage void trap9(void); | ||
40 | asmlinkage void trap10(void); | ||
41 | asmlinkage void trap11(void); | ||
42 | asmlinkage void trap12(void); | ||
43 | asmlinkage void trap13(void); | ||
44 | asmlinkage void trap14(void); | ||
45 | asmlinkage void trap15(void); | ||
46 | asmlinkage void trap33(void); | ||
47 | asmlinkage void trap34(void); | ||
48 | asmlinkage void trap35(void); | ||
49 | asmlinkage void trap36(void); | ||
50 | asmlinkage void trap37(void); | ||
51 | asmlinkage void trap38(void); | ||
52 | asmlinkage void trap39(void); | ||
53 | asmlinkage void trap40(void); | ||
54 | asmlinkage void trap41(void); | ||
55 | asmlinkage void trap42(void); | ||
56 | asmlinkage void trap43(void); | ||
57 | asmlinkage void trap44(void); | ||
58 | asmlinkage void trap45(void); | ||
59 | asmlinkage void trap46(void); | ||
60 | asmlinkage void trap47(void); | ||
61 | asmlinkage irqreturn_t bad_interrupt(int, void *); | ||
62 | asmlinkage irqreturn_t inthandler(void); | ||
63 | asmlinkage irqreturn_t inthandler1(void); | ||
64 | asmlinkage irqreturn_t inthandler2(void); | ||
65 | asmlinkage irqreturn_t inthandler3(void); | ||
66 | asmlinkage irqreturn_t inthandler4(void); | ||
67 | asmlinkage irqreturn_t inthandler5(void); | ||
68 | asmlinkage irqreturn_t inthandler6(void); | ||
69 | asmlinkage irqreturn_t inthandler7(void); | ||
70 | |||
71 | extern e_vector *_ramvec; | ||
72 | |||
73 | /* The number of spurious interrupts */ | ||
74 | volatile unsigned int num_spurious; | ||
75 | |||
76 | /* The 68k family did not have a good way to determine the source | ||
77 | * of interrupts until later in the family. The EC000 core does | ||
78 | * not provide the vector number on the stack, we vector everything | ||
79 | * into one vector and look in the blasted mask register... | ||
80 | * This code is designed to be fast, almost constant time, not clean! | ||
81 | */ | ||
82 | void process_int(int vec, struct pt_regs *fp) | ||
83 | { | ||
84 | int irq; | ||
85 | int mask; | ||
86 | |||
87 | unsigned long pend = ISR; | ||
88 | |||
89 | while (pend) { | ||
90 | if (pend & 0x0000ffff) { | ||
91 | if (pend & 0x000000ff) { | ||
92 | if (pend & 0x0000000f) { | ||
93 | mask = 0x00000001; | ||
94 | irq = 0; | ||
95 | } else { | ||
96 | mask = 0x00000010; | ||
97 | irq = 4; | ||
98 | } | ||
99 | } else { | ||
100 | if (pend & 0x00000f00) { | ||
101 | mask = 0x00000100; | ||
102 | irq = 8; | ||
103 | } else { | ||
104 | mask = 0x00001000; | ||
105 | irq = 12; | ||
106 | } | ||
107 | } | ||
108 | } else { | ||
109 | if (pend & 0x00ff0000) { | ||
110 | if (pend & 0x000f0000) { | ||
111 | mask = 0x00010000; | ||
112 | irq = 16; | ||
113 | } else { | ||
114 | mask = 0x00100000; | ||
115 | irq = 20; | ||
116 | } | ||
117 | } else { | ||
118 | if (pend & 0x0f000000) { | ||
119 | mask = 0x01000000; | ||
120 | irq = 24; | ||
121 | } else { | ||
122 | mask = 0x10000000; | ||
123 | irq = 28; | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | |||
128 | while (! (mask & pend)) { | ||
129 | mask <<=1; | ||
130 | irq++; | ||
131 | } | ||
132 | |||
133 | do_IRQ(irq, fp); | ||
134 | pend &= ~mask; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | static void intc_irq_unmask(struct irq_data *d) | ||
139 | { | ||
140 | IMR &= ~(1 << d->irq); | ||
141 | } | ||
142 | |||
143 | static void intc_irq_mask(struct irq_data *d) | ||
144 | { | ||
145 | IMR |= (1 << d->irq); | ||
146 | } | ||
147 | |||
148 | static struct irq_chip intc_irq_chip = { | ||
149 | .name = "M68K-INTC", | ||
150 | .irq_mask = intc_irq_mask, | ||
151 | .irq_unmask = intc_irq_unmask, | ||
152 | }; | ||
153 | |||
154 | /* | ||
155 | * This function should be called during kernel startup to initialize | ||
156 | * the machine vector table. | ||
157 | */ | ||
158 | void __init init_IRQ(void) | ||
159 | { | ||
160 | int i; | ||
161 | |||
162 | /* set up the vectors */ | ||
163 | for (i = 72; i < 256; ++i) | ||
164 | _ramvec[i] = (e_vector) bad_interrupt; | ||
165 | |||
166 | _ramvec[32] = system_call; | ||
167 | |||
168 | _ramvec[65] = (e_vector) inthandler1; | ||
169 | _ramvec[66] = (e_vector) inthandler2; | ||
170 | _ramvec[67] = (e_vector) inthandler3; | ||
171 | _ramvec[68] = (e_vector) inthandler4; | ||
172 | _ramvec[69] = (e_vector) inthandler5; | ||
173 | _ramvec[70] = (e_vector) inthandler6; | ||
174 | _ramvec[71] = (e_vector) inthandler7; | ||
175 | |||
176 | IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */ | ||
177 | |||
178 | /* turn off all interrupts */ | ||
179 | IMR = ~0; | ||
180 | |||
181 | for (i = 0; (i < NR_IRQS); i++) { | ||
182 | set_irq_chip(i, &intc_irq_chip); | ||
183 | set_irq_handler(i, handle_level_irq); | ||
184 | } | ||
185 | } | ||
186 | |||