[PATCH] m68knommu: use irq_handler_t for passing handler types in 68328 setup
[deliverable/linux.git] / arch / m68knommu / platform / 68328 / ints.c
CommitLineData
1da177e4
LT
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/module.h>
13#include <linux/types.h>
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/kernel_stat.h>
17#include <linux/errno.h>
18
19#include <asm/system.h>
20#include <asm/irq.h>
0d44269e 21#include <asm/irqnode.h>
1da177e4
LT
22#include <asm/traps.h>
23#include <asm/io.h>
24#include <asm/machdep.h>
25#include <asm/setup.h>
26
27#if defined(CONFIG_M68328)
28#include <asm/MC68328.h>
29#elif defined(CONFIG_M68EZ328)
30#include <asm/MC68EZ328.h>
31#elif defined(CONFIG_M68VZ328)
32#include <asm/MC68VZ328.h>
33#endif
34
35/* assembler routines */
36asmlinkage void system_call(void);
37asmlinkage void buserr(void);
38asmlinkage void trap(void);
39asmlinkage void trap3(void);
40asmlinkage void trap4(void);
41asmlinkage void trap5(void);
42asmlinkage void trap6(void);
43asmlinkage void trap7(void);
44asmlinkage void trap8(void);
45asmlinkage void trap9(void);
46asmlinkage void trap10(void);
47asmlinkage void trap11(void);
48asmlinkage void trap12(void);
49asmlinkage void trap13(void);
50asmlinkage void trap14(void);
51asmlinkage void trap15(void);
52asmlinkage void trap33(void);
53asmlinkage void trap34(void);
54asmlinkage void trap35(void);
55asmlinkage void trap36(void);
56asmlinkage void trap37(void);
57asmlinkage void trap38(void);
58asmlinkage void trap39(void);
59asmlinkage void trap40(void);
60asmlinkage void trap41(void);
61asmlinkage void trap42(void);
62asmlinkage void trap43(void);
63asmlinkage void trap44(void);
64asmlinkage void trap45(void);
65asmlinkage void trap46(void);
66asmlinkage void trap47(void);
67asmlinkage irqreturn_t bad_interrupt(int, void *, struct pt_regs *);
68asmlinkage irqreturn_t inthandler(void);
69asmlinkage irqreturn_t inthandler1(void);
70asmlinkage irqreturn_t inthandler2(void);
71asmlinkage irqreturn_t inthandler3(void);
72asmlinkage irqreturn_t inthandler4(void);
73asmlinkage irqreturn_t inthandler5(void);
74asmlinkage irqreturn_t inthandler6(void);
75asmlinkage irqreturn_t inthandler7(void);
76
77extern e_vector *_ramvec;
78
79/* The number of spurious interrupts */
80volatile unsigned int num_spurious;
81unsigned int local_irq_count[NR_CPUS];
82
83/* irq node variables for the 32 (potential) on chip sources */
84static irq_node_t int_irq_list[NR_IRQS];
85
1da177e4
LT
86/*
87 * This function should be called during kernel startup to initialize
88 * the IRQ handling routines.
89 */
90void init_IRQ(void)
91{
92 int i;
93
94 /* set up the vectors */
95 for (i = 72; i < 256; ++i)
96 _ramvec[i] = (e_vector) bad_interrupt;
97
98 _ramvec[32] = system_call;
99
100 _ramvec[65] = (e_vector) inthandler1;
101 _ramvec[66] = (e_vector) inthandler2;
102 _ramvec[67] = (e_vector) inthandler3;
103 _ramvec[68] = (e_vector) inthandler4;
104 _ramvec[69] = (e_vector) inthandler5;
105 _ramvec[70] = (e_vector) inthandler6;
106 _ramvec[71] = (e_vector) inthandler7;
107
108 IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */
109
110 /* initialize handlers */
111 for (i = 0; i < NR_IRQS; i++) {
112 int_irq_list[i].handler = bad_interrupt;
113 int_irq_list[i].flags = IRQ_FLG_STD;
114 int_irq_list[i].dev_id = NULL;
115 int_irq_list[i].devname = NULL;
116 }
117
118 /* turn off all interrupts */
119 IMR = ~0;
120}
121
122int request_irq(
123 unsigned int irq,
124 irqreturn_t (*handler)(int, void *, struct pt_regs *),
125 unsigned long flags,
126 const char *devname,
127 void *dev_id)
128{
129 if (irq >= NR_IRQS) {
130 printk (KERN_ERR "%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname);
131 return -ENXIO;
132 }
133
134 if (!(int_irq_list[irq].flags & IRQ_FLG_STD)) {
135 if (int_irq_list[irq].flags & IRQ_FLG_LOCK) {
136 printk(KERN_ERR "%s: IRQ %d from %s is not replaceable\n",
137 __FUNCTION__, irq, int_irq_list[irq].devname);
138 return -EBUSY;
139 }
140 if (flags & IRQ_FLG_REPLACE) {
141 printk(KERN_ERR "%s: %s can't replace IRQ %d from %s\n",
142 __FUNCTION__, devname, irq, int_irq_list[irq].devname);
143 return -EBUSY;
144 }
145 }
146
147 int_irq_list[irq].handler = handler;
148 int_irq_list[irq].flags = flags;
149 int_irq_list[irq].dev_id = dev_id;
150 int_irq_list[irq].devname = devname;
151
152 IMR &= ~(1<<irq);
153
154 return 0;
155}
156
157EXPORT_SYMBOL(request_irq);
158
159void free_irq(unsigned int irq, void *dev_id)
160{
161 if (irq >= NR_IRQS) {
162 printk (KERN_ERR "%s: Unknown IRQ %d\n", __FUNCTION__, irq);
163 return;
164 }
165
166 if (int_irq_list[irq].dev_id != dev_id)
167 printk(KERN_INFO "%s: removing probably wrong IRQ %d from %s\n",
168 __FUNCTION__, irq, int_irq_list[irq].devname);
169
170 int_irq_list[irq].handler = bad_interrupt;
171 int_irq_list[irq].flags = IRQ_FLG_STD;
172 int_irq_list[irq].dev_id = NULL;
173 int_irq_list[irq].devname = NULL;
174
175 IMR |= 1<<irq;
176}
177
178EXPORT_SYMBOL(free_irq);
179
180int show_interrupts(struct seq_file *p, void *v)
181{
182 int i = *(loff_t *) v;
183
184 if (i < NR_IRQS) {
185 if (int_irq_list[i].devname) {
186 seq_printf(p, "%3d: %10u ", i, kstat_cpu(0).irqs[i]);
187 if (int_irq_list[i].flags & IRQ_FLG_LOCK)
188 seq_printf(p, "L ");
189 else
190 seq_printf(p, " ");
191 seq_printf(p, "%s\n", int_irq_list[i].devname);
192 }
193 }
194 if (i == NR_IRQS)
195 seq_printf(p, " : %10u spurious\n", num_spurious);
196
197 return 0;
198}
199
200/* The 68k family did not have a good way to determine the source
201 * of interrupts until later in the family. The EC000 core does
202 * not provide the vector number on the stack, we vector everything
203 * into one vector and look in the blasted mask register...
204 * This code is designed to be fast, almost constant time, not clean!
205 */
206void process_int(int vec, struct pt_regs *fp)
207{
208 int irq;
209 int mask;
210
211 unsigned long pend = ISR;
212
213 while (pend) {
214 if (pend & 0x0000ffff) {
215 if (pend & 0x000000ff) {
216 if (pend & 0x0000000f) {
217 mask = 0x00000001;
218 irq = 0;
219 } else {
220 mask = 0x00000010;
221 irq = 4;
222 }
223 } else {
224 if (pend & 0x00000f00) {
225 mask = 0x00000100;
226 irq = 8;
227 } else {
228 mask = 0x00001000;
229 irq = 12;
230 }
231 }
232 } else {
233 if (pend & 0x00ff0000) {
234 if (pend & 0x000f0000) {
235 mask = 0x00010000;
236 irq = 16;
237 } else {
238 mask = 0x00100000;
239 irq = 20;
240 }
241 } else {
242 if (pend & 0x0f000000) {
243 mask = 0x01000000;
244 irq = 24;
245 } else {
246 mask = 0x10000000;
247 irq = 28;
248 }
249 }
250 }
251
252 while (! (mask & pend)) {
253 mask <<=1;
254 irq++;
255 }
256
257 kstat_cpu(0).irqs[irq]++;
258
259 if (int_irq_list[irq].handler) {
260 int_irq_list[irq].handler(irq, int_irq_list[irq].dev_id, fp);
261 } else {
262 printk(KERN_ERR "unregistered interrupt %d!\nTurning it off in the IMR...\n", irq);
263 IMR |= mask;
264 }
265 pend &= ~mask;
266 }
267}
This page took 0.220566 seconds and 5 git commands to generate.