aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68knommu/platform
diff options
context:
space:
mode:
authorGreg Ungerer <gerg@snapgear.com>2007-07-19 04:49:12 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:50 -0400
commit2502b667ea835ee16685c74b2a0d89ba8afe117a (patch)
tree31d492fb934df6d83819b679f3aa8d7f6952396d /arch/m68knommu/platform
parentf8af0bb890d6cdcb09ec042c128e217a7c500355 (diff)
m68knommu: generic irq handling
Change the m68knommu irq handling to use the generic irq framework. Signed-off-by: Greg Ungerer <gerg@uclinux.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/m68knommu/platform')
-rw-r--r--arch/m68knommu/platform/5307/Makefile2
-rw-r--r--arch/m68knommu/platform/5307/entry.S42
-rw-r--r--arch/m68knommu/platform/5307/ints.c279
-rw-r--r--arch/m68knommu/platform/5307/vectors.c29
-rw-r--r--arch/m68knommu/platform/68328/entry.S10
-rw-r--r--arch/m68knommu/platform/68328/ints.c130
-rw-r--r--arch/m68knommu/platform/68360/entry.S6
-rw-r--r--arch/m68knommu/platform/68360/ints.c233
8 files changed, 67 insertions, 664 deletions
diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile
index 2fd37dcc309b..719a313494bc 100644
--- a/arch/m68knommu/platform/5307/Makefile
+++ b/arch/m68knommu/platform/5307/Makefile
@@ -16,7 +16,7 @@ ifdef CONFIG_FULLDEBUG
16AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 16AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
17endif 17endif
18 18
19obj-$(CONFIG_COLDFIRE) += entry.o vectors.o ints.o 19obj-$(CONFIG_COLDFIRE) += entry.o vectors.o
20obj-$(CONFIG_M5206) += timers.o 20obj-$(CONFIG_M5206) += timers.o
21obj-$(CONFIG_M5206e) += timers.o 21obj-$(CONFIG_M5206e) += timers.o
22obj-$(CONFIG_M520x) += pit.o 22obj-$(CONFIG_M520x) += pit.o
diff --git a/arch/m68knommu/platform/5307/entry.S b/arch/m68knommu/platform/5307/entry.S
index f0dba84d9101..c358aebe0af3 100644
--- a/arch/m68knommu/platform/5307/entry.S
+++ b/arch/m68knommu/platform/5307/entry.S
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/arch/m68knommu/platform/5307/entry.S 2 * linux/arch/m68knommu/platform/5307/entry.S
3 * 3 *
4 * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) 4 * Copyright (C) 1999-2007, Greg Ungerer (gerg@snapgear.com)
5 * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, 5 * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
6 * Kenneth Albanowski <kjahds@kjahds.com>, 6 * Kenneth Albanowski <kjahds@kjahds.com>,
7 * Copyright (C) 2000 Lineo Inc. (www.lineo.com) 7 * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
@@ -155,34 +155,21 @@ Lsignal_return:
155 155
156/* 156/*
157 * This is the generic interrupt handler (for all hardware interrupt 157 * This is the generic interrupt handler (for all hardware interrupt
158 * sources). It figures out the vector number and calls the appropriate 158 * sources). Calls upto high level code to do all the work.
159 * interrupt service routine directly.
160 */ 159 */
161ENTRY(inthandler) 160ENTRY(inthandler)
162 SAVE_ALL 161 SAVE_ALL
163 moveq #-1,%d0 162 moveq #-1,%d0
164 movel %d0,%sp@(PT_ORIG_D0) 163 movel %d0,%sp@(PT_ORIG_D0)
165 addql #1,local_irq_count
166 164
167 movew %sp@(PT_FORMATVEC),%d0 /* put exception # in d0 */ 165 movew %sp@(PT_FORMATVEC),%d0 /* put exception # in d0 */
168 andl #0x03fc,%d0 /* mask out vector only */ 166 andl #0x03fc,%d0 /* mask out vector only */
169 167
170 leal per_cpu__kstat+STAT_IRQ,%a0 168 movel %sp,%sp@- /* push regs arg */
171 addql #1,%a0@(%d0)
172
173 lsrl #2,%d0 /* calculate real vector # */ 169 lsrl #2,%d0 /* calculate real vector # */
174 movel %d0,%d1 /* calculate array offset */ 170 movel %d0,%sp@- /* push vector number */
175 lsll #4,%d1 171 jbsr do_IRQ /* call high level irq handler */
176 lea irq_list,%a0 172 lea %sp@(8),%sp /* pop args off stack */
177 addl %d1,%a0 /* pointer to array struct */
178
179 movel %sp,%sp@- /* push regs arg onto stack */
180 movel %a0@(8),%sp@- /* push devid arg */
181 movel %d0,%sp@- /* push vector # on stack */
182
183 movel %a0@,%a0 /* get function to call */
184 jbsr %a0@ /* call vector handler */
185 lea %sp@(12),%sp /* pop parameters off stack */
186 173
187 bra ret_from_interrupt /* this was fallthrough */ 174 bra ret_from_interrupt /* this was fallthrough */
188 175
@@ -198,24 +185,15 @@ ENTRY(fasthandler)
198 movew %sp@(PT_FORMATVEC),%d0 185 movew %sp@(PT_FORMATVEC),%d0
199 andl #0x03fc,%d0 /* mask out vector only */ 186 andl #0x03fc,%d0 /* mask out vector only */
200 187
201 leal per_cpu__kstat+STAT_IRQ,%a0 188 movel %sp,%sp@- /* push regs arg */
202 addql #1,%a0@(%d0)
203
204 movel %sp,%sp@- /* push regs arg onto stack */
205 clrl %sp@- /* push devid arg */
206 lsrl #2,%d0 /* calculate real vector # */ 189 lsrl #2,%d0 /* calculate real vector # */
207 movel %d0,%sp@- /* push vector # on stack */ 190 movel %d0,%sp@- /* push vector number */
208 191 jbsr do_IRQ /* call high level irq handler */
209 lsll #4,%d0 /* adjust for array offset */ 192 lea %sp@(8),%sp /* pop args off stack */
210 lea irq_list,%a0
211 movel %a0@(%d0),%a0 /* get function to call */
212 jbsr %a0@ /* call vector handler */
213 lea %sp@(12),%sp /* pop parameters off stack */
214 193
215 RESTORE_LOCAL 194 RESTORE_LOCAL
216 195
217ENTRY(ret_from_interrupt) 196ENTRY(ret_from_interrupt)
218 subql #1,local_irq_count
219 jeq 2f 197 jeq 2f
2201: 1981:
221 RESTORE_ALL 199 RESTORE_ALL
diff --git a/arch/m68knommu/platform/5307/ints.c b/arch/m68knommu/platform/5307/ints.c
deleted file mode 100644
index 751633038c4b..000000000000
--- a/arch/m68knommu/platform/5307/ints.c
+++ /dev/null
@@ -1,279 +0,0 @@
1/*
2 * linux/arch/m68knommu/kernel/ints.c -- General interrupt handling code
3 *
4 * Copyright (C) 1999-2002 Greg Ungerer (gerg@snapgear.com)
5 * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
6 * Kenneth Albanowski <kjahds@kjahds.com>,
7 * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
8 *
9 * Based on:
10 *
11 * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code
12 *
13 * This file is subject to the terms and conditions of the GNU General Public
14 * License. See the file COPYING in the main directory of this archive
15 * for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/types.h>
20#include <linux/init.h>
21#include <linux/sched.h>
22#include <linux/interrupt.h>
23#include <linux/kernel_stat.h>
24#include <linux/errno.h>
25#include <linux/seq_file.h>
26
27#include <asm/system.h>
28#include <asm/irq.h>
29#include <asm/irqnode.h>
30#include <asm/traps.h>
31#include <asm/page.h>
32#include <asm/machdep.h>
33
34/*
35 * This table stores the address info for each vector handler.
36 */
37struct irq_entry irq_list[SYS_IRQS];
38
39#define NUM_IRQ_NODES 16
40static irq_node_t nodes[NUM_IRQ_NODES];
41
42/* The number of spurious interrupts */
43volatile unsigned int num_spurious;
44
45unsigned int local_irq_count[NR_CPUS];
46
47static irqreturn_t default_irq_handler(int irq, void *ptr)
48{
49#if 1
50 printk(KERN_INFO "%s(%d): default irq handler vec=%d [0x%x]\n",
51 __FILE__, __LINE__, irq, irq);
52#endif
53 return(IRQ_HANDLED);
54}
55
56/*
57 * void init_IRQ(void)
58 *
59 * Parameters: None
60 *
61 * Returns: Nothing
62 *
63 * This function should be called during kernel startup to initialize
64 * the IRQ handling routines.
65 */
66
67void __init init_IRQ(void)
68{
69 int i;
70
71 for (i = 0; i < SYS_IRQS; i++) {
72 if (mach_default_handler)
73 irq_list[i].handler = mach_default_handler;
74 else
75 irq_list[i].handler = default_irq_handler;
76 irq_list[i].flags = IRQ_FLG_STD;
77 irq_list[i].dev_id = NULL;
78 irq_list[i].devname = NULL;
79 }
80
81 for (i = 0; i < NUM_IRQ_NODES; i++)
82 nodes[i].handler = NULL;
83
84 if (mach_init_IRQ)
85 mach_init_IRQ();
86}
87
88irq_node_t *new_irq_node(void)
89{
90 irq_node_t *node;
91 short i;
92
93 for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
94 if (!node->handler)
95 return node;
96
97 printk(KERN_INFO "new_irq_node: out of nodes\n");
98 return NULL;
99}
100
101int request_irq(
102 unsigned int irq,
103 irq_handler_t handler,
104 unsigned long flags,
105 const char *devname,
106 void *dev_id)
107{
108 if (irq < 0 || irq >= NR_IRQS) {
109 printk(KERN_WARNING "%s: Incorrect IRQ %d from %s\n", __FUNCTION__,
110 irq, devname);
111 return -ENXIO;
112 }
113
114 if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
115 if (irq_list[irq].flags & IRQ_FLG_LOCK) {
116 printk(KERN_WARNING "%s: IRQ %d from %s is not replaceable\n",
117 __FUNCTION__, irq, irq_list[irq].devname);
118 return -EBUSY;
119 }
120 if (flags & IRQ_FLG_REPLACE) {
121 printk(KERN_WARNING "%s: %s can't replace IRQ %d from %s\n",
122 __FUNCTION__, devname, irq, irq_list[irq].devname);
123 return -EBUSY;
124 }
125 }
126
127 if (flags & IRQ_FLG_FAST) {
128 extern asmlinkage void fasthandler(void);
129 extern void set_evector(int vecnum, void (*handler)(void));
130 set_evector(irq, fasthandler);
131 }
132
133 irq_list[irq].handler = handler;
134 irq_list[irq].flags = flags;
135 irq_list[irq].dev_id = dev_id;
136 irq_list[irq].devname = devname;
137 return 0;
138}
139
140EXPORT_SYMBOL(request_irq);
141
142void free_irq(unsigned int irq, void *dev_id)
143{
144 if (irq >= NR_IRQS) {
145 printk(KERN_WARNING "%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
146 return;
147 }
148
149 if (irq_list[irq].dev_id != dev_id)
150 printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n",
151 __FUNCTION__, irq, irq_list[irq].devname);
152
153 if (irq_list[irq].flags & IRQ_FLG_FAST) {
154 extern asmlinkage void inthandler(void);
155 extern void set_evector(int vecnum, void (*handler)(void));
156 set_evector(irq, inthandler);
157 }
158
159 if (mach_default_handler)
160 irq_list[irq].handler = mach_default_handler;
161 else
162 irq_list[irq].handler = default_irq_handler;
163 irq_list[irq].flags = IRQ_FLG_STD;
164 irq_list[irq].dev_id = NULL;
165 irq_list[irq].devname = NULL;
166}
167
168EXPORT_SYMBOL(free_irq);
169
170
171int sys_request_irq(unsigned int irq, irq_handler_t handler,
172 unsigned long flags, const char *devname, void *dev_id)
173{
174 if (irq > IRQ7) {
175 printk(KERN_WARNING "%s: Incorrect IRQ %d from %s\n",
176 __FUNCTION__, irq, devname);
177 return -ENXIO;
178 }
179
180#if 0
181 if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
182 if (irq_list[irq].flags & IRQ_FLG_LOCK) {
183 printk(KERN_WARNING "%s: IRQ %d from %s is not replaceable\n",
184 __FUNCTION__, irq, irq_list[irq].devname);
185 return -EBUSY;
186 }
187 if (!(flags & IRQ_FLG_REPLACE)) {
188 printk(KERN_WARNING "%s: %s can't replace IRQ %d from %s\n",
189 __FUNCTION__, devname, irq, irq_list[irq].devname);
190 return -EBUSY;
191 }
192 }
193#endif
194
195 irq_list[irq].handler = handler;
196 irq_list[irq].flags = flags;
197 irq_list[irq].dev_id = dev_id;
198 irq_list[irq].devname = devname;
199 return 0;
200}
201
202void sys_free_irq(unsigned int irq, void *dev_id)
203{
204 if (irq > IRQ7) {
205 printk(KERN_WARNING "%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
206 return;
207 }
208
209 if (irq_list[irq].dev_id != dev_id)
210 printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n",
211 __FUNCTION__, irq, irq_list[irq].devname);
212
213 irq_list[irq].handler = mach_default_handler;
214 irq_list[irq].flags = 0;
215 irq_list[irq].dev_id = NULL;
216 irq_list[irq].devname = NULL;
217}
218
219/*
220 * Do we need these probe functions on the m68k?
221 *
222 * ... may be useful with ISA devices
223 */
224unsigned long probe_irq_on (void)
225{
226 return 0;
227}
228
229EXPORT_SYMBOL(probe_irq_on);
230
231int probe_irq_off (unsigned long irqs)
232{
233 return 0;
234}
235
236EXPORT_SYMBOL(probe_irq_off);
237
238asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
239{
240 if (vec >= VEC_INT1 && vec <= VEC_INT7) {
241 vec -= VEC_SPUR;
242 kstat_cpu(0).irqs[vec]++;
243 irq_list[vec].handler(vec, irq_list[vec].dev_id);
244 } else {
245 if (mach_process_int)
246 mach_process_int(vec, fp);
247 else
248 panic("Can't process interrupt vector %ld\n", vec);
249 return;
250 }
251}
252
253
254int show_interrupts(struct seq_file *p, void *v)
255{
256 int i = *(loff_t *) v;
257
258 if (i < NR_IRQS) {
259 if (! (irq_list[i].flags & IRQ_FLG_STD)) {
260 seq_printf(p, "%3d: %10u ", i,
261 (i ? kstat_cpu(0).irqs[i] : num_spurious));
262 if (irq_list[i].flags & IRQ_FLG_LOCK)
263 seq_printf(p, "L ");
264 else
265 seq_printf(p, " ");
266 seq_printf(p, "%s\n", irq_list[i].devname);
267 }
268 }
269
270 if (i == NR_IRQS && mach_get_irq_list)
271 mach_get_irq_list(p, v);
272 return 0;
273}
274
275void init_irq_proc(void)
276{
277 /* Insert /proc/irq driver here */
278}
279
diff --git a/arch/m68knommu/platform/5307/vectors.c b/arch/m68knommu/platform/5307/vectors.c
index 2a8b0d044ce5..6cf894620234 100644
--- a/arch/m68knommu/platform/5307/vectors.c
+++ b/arch/m68knommu/platform/5307/vectors.c
@@ -3,23 +3,17 @@
3/* 3/*
4 * linux/arch/m68knommu/platform/5307/vectors.c 4 * linux/arch/m68knommu/platform/5307/vectors.c
5 * 5 *
6 * Copyright (C) 1999-2003, Greg Ungerer <gerg@snapgear.com> 6 * Copyright (C) 1999-2007, Greg Ungerer <gerg@snapgear.com>
7 */ 7 */
8 8
9/***************************************************************************/ 9/***************************************************************************/
10 10
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/sched.h>
13#include <linux/param.h>
14#include <linux/init.h> 12#include <linux/init.h>
15#include <linux/unistd.h> 13#include <linux/irq.h>
16#include <linux/delay.h>
17#include <asm/irq.h>
18#include <asm/dma.h>
19#include <asm/traps.h> 14#include <asm/traps.h>
20#include <asm/machdep.h> 15#include <asm/machdep.h>
21#include <asm/coldfire.h> 16#include <asm/coldfire.h>
22#include <asm/mcftimer.h>
23#include <asm/mcfsim.h> 17#include <asm/mcfsim.h>
24#include <asm/mcfdma.h> 18#include <asm/mcfdma.h>
25#include <asm/mcfwdebug.h> 19#include <asm/mcfwdebug.h>
@@ -56,7 +50,7 @@ asmlinkage void trap(void);
56asmlinkage void system_call(void); 50asmlinkage void system_call(void);
57asmlinkage void inthandler(void); 51asmlinkage void inthandler(void);
58 52
59void __init coldfire_trap_init(void) 53void __init init_vectors(void)
60{ 54{
61 int i; 55 int i;
62 56
@@ -86,6 +80,23 @@ void __init coldfire_trap_init(void)
86 80
87/***************************************************************************/ 81/***************************************************************************/
88 82
83void enable_vector(unsigned int irq)
84{
85 /* Currently no action on ColdFire */
86}
87
88void disable_vector(unsigned int irq)
89{
90 /* Currently no action on ColdFire */
91}
92
93void ack_vector(unsigned int irq)
94{
95 /* Currently no action on ColdFire */
96}
97
98/***************************************************************************/
99
89void coldfire_reset(void) 100void coldfire_reset(void)
90{ 101{
91 HARD_RESET_NOW(); 102 HARD_RESET_NOW();
diff --git a/arch/m68knommu/platform/68328/entry.S b/arch/m68knommu/platform/68328/entry.S
index f97862715450..b1aef72f3baf 100644
--- a/arch/m68knommu/platform/68328/entry.S
+++ b/arch/m68knommu/platform/68328/entry.S
@@ -133,7 +133,6 @@ Lreturn:
133 */ 133 */
134inthandler1: 134inthandler1:
135 SAVE_ALL 135 SAVE_ALL
136 addql #1,local_irq_count /* put exception # in d0*/
137 movew %sp@(PT_VECTOR), %d0 136 movew %sp@(PT_VECTOR), %d0
138 and #0x3ff, %d0 137 and #0x3ff, %d0
139 138
@@ -145,7 +144,6 @@ inthandler1:
145 144
146inthandler2: 145inthandler2:
147 SAVE_ALL 146 SAVE_ALL
148 addql #1,local_irq_count /* put exception # in d0*/
149 movew %sp@(PT_VECTOR), %d0 147 movew %sp@(PT_VECTOR), %d0
150 and #0x3ff, %d0 148 and #0x3ff, %d0
151 149
@@ -157,7 +155,6 @@ inthandler2:
157 155
158inthandler3: 156inthandler3:
159 SAVE_ALL 157 SAVE_ALL
160 addql #1,local_irq_count /* put exception # in d0*/
161 movew %sp@(PT_VECTOR), %d0 158 movew %sp@(PT_VECTOR), %d0
162 and #0x3ff, %d0 159 and #0x3ff, %d0
163 160
@@ -169,7 +166,6 @@ inthandler3:
169 166
170inthandler4: 167inthandler4:
171 SAVE_ALL 168 SAVE_ALL
172 addql #1,local_irq_count /* put exception # in d0*/
173 movew %sp@(PT_VECTOR), %d0 169 movew %sp@(PT_VECTOR), %d0
174 and #0x3ff, %d0 170 and #0x3ff, %d0
175 171
@@ -181,7 +177,6 @@ inthandler4:
181 177
182inthandler5: 178inthandler5:
183 SAVE_ALL 179 SAVE_ALL
184 addql #1,local_irq_count /* put exception # in d0*/
185 movew %sp@(PT_VECTOR), %d0 180 movew %sp@(PT_VECTOR), %d0
186 and #0x3ff, %d0 181 and #0x3ff, %d0
187 182
@@ -193,7 +188,6 @@ inthandler5:
193 188
194inthandler6: 189inthandler6:
195 SAVE_ALL 190 SAVE_ALL
196 addql #1,local_irq_count /* put exception # in d0*/
197 movew %sp@(PT_VECTOR), %d0 191 movew %sp@(PT_VECTOR), %d0
198 and #0x3ff, %d0 192 and #0x3ff, %d0
199 193
@@ -205,7 +199,6 @@ inthandler6:
205 199
206inthandler7: 200inthandler7:
207 SAVE_ALL 201 SAVE_ALL
208 addql #1,local_irq_count /* put exception # in d0*/
209 movew %sp@(PT_VECTOR), %d0 202 movew %sp@(PT_VECTOR), %d0
210 and #0x3ff, %d0 203 and #0x3ff, %d0
211 204
@@ -217,7 +210,6 @@ inthandler7:
217 210
218inthandler: 211inthandler:
219 SAVE_ALL 212 SAVE_ALL
220 addql #1,local_irq_count /* put exception # in d0*/
221 movew %sp@(PT_VECTOR), %d0 213 movew %sp@(PT_VECTOR), %d0
222 and #0x3ff, %d0 214 and #0x3ff, %d0
223 215
@@ -228,7 +220,6 @@ inthandler:
228 bra ret_from_interrupt 220 bra ret_from_interrupt
229 221
230ret_from_interrupt: 222ret_from_interrupt:
231 subql #1,local_irq_count
232 jeq 1f 223 jeq 1f
2332: 2242:
234 RESTORE_ALL 225 RESTORE_ALL
@@ -238,7 +229,6 @@ ret_from_interrupt:
238 jhi 2b 229 jhi 2b
239 230
240 /* check if we need to do software interrupts */ 231 /* check if we need to do software interrupts */
241 movel local_irq_count,%d0
242 jeq ret_from_exception 232 jeq ret_from_exception
243 233
244 pea ret_from_exception 234 pea ret_from_exception
diff --git a/arch/m68knommu/platform/68328/ints.c b/arch/m68knommu/platform/68328/ints.c
index 3de6e337554e..72e56d554f4f 100644
--- a/arch/m68knommu/platform/68328/ints.c
+++ b/arch/m68knommu/platform/68328/ints.c
@@ -9,21 +9,14 @@
9 * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com> 9 * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com>
10 */ 10 */
11 11
12#include <linux/module.h>
13#include <linux/types.h> 12#include <linux/types.h>
14#include <linux/kernel.h> 13#include <linux/kernel.h>
15#include <linux/sched.h> 14#include <linux/init.h>
16#include <linux/kernel_stat.h>
17#include <linux/errno.h>
18#include <linux/interrupt.h> 15#include <linux/interrupt.h>
19 16#include <linux/irq.h>
20#include <asm/system.h>
21#include <asm/irq.h>
22#include <asm/irqnode.h>
23#include <asm/traps.h> 17#include <asm/traps.h>
24#include <asm/io.h> 18#include <asm/io.h>
25#include <asm/machdep.h> 19#include <asm/machdep.h>
26#include <asm/setup.h>
27 20
28#if defined(CONFIG_M68328) 21#if defined(CONFIG_M68328)
29#include <asm/MC68328.h> 22#include <asm/MC68328.h>
@@ -79,16 +72,12 @@ extern e_vector *_ramvec;
79 72
80/* The number of spurious interrupts */ 73/* The number of spurious interrupts */
81volatile unsigned int num_spurious; 74volatile unsigned int num_spurious;
82unsigned int local_irq_count[NR_CPUS];
83
84/* irq node variables for the 32 (potential) on chip sources */
85static irq_node_t int_irq_list[NR_IRQS];
86 75
87/* 76/*
88 * This function should be called during kernel startup to initialize 77 * This function should be called during kernel startup to initialize
89 * the IRQ handling routines. 78 * the machine vector table.
90 */ 79 */
91void init_IRQ(void) 80void __init init_vectors(void)
92{ 81{
93 int i; 82 int i;
94 83
@@ -108,96 +97,10 @@ void init_IRQ(void)
108 97
109 IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */ 98 IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */
110 99
111 /* initialize handlers */
112 for (i = 0; i < NR_IRQS; i++) {
113 int_irq_list[i].handler = bad_interrupt;
114 int_irq_list[i].flags = IRQ_FLG_STD;
115 int_irq_list[i].dev_id = NULL;
116 int_irq_list[i].devname = NULL;
117 }
118
119 /* turn off all interrupts */ 100 /* turn off all interrupts */
120 IMR = ~0; 101 IMR = ~0;
121} 102}
122 103
123int request_irq(
124 unsigned int irq,
125 irq_handler_t handler,
126 unsigned long flags,
127 const char *devname,
128 void *dev_id)
129{
130 if (irq >= NR_IRQS) {
131 printk (KERN_ERR "%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname);
132 return -ENXIO;
133 }
134
135 if (!(int_irq_list[irq].flags & IRQ_FLG_STD)) {
136 if (int_irq_list[irq].flags & IRQ_FLG_LOCK) {
137 printk(KERN_ERR "%s: IRQ %d from %s is not replaceable\n",
138 __FUNCTION__, irq, int_irq_list[irq].devname);
139 return -EBUSY;
140 }
141 if (flags & IRQ_FLG_REPLACE) {
142 printk(KERN_ERR "%s: %s can't replace IRQ %d from %s\n",
143 __FUNCTION__, devname, irq, int_irq_list[irq].devname);
144 return -EBUSY;
145 }
146 }
147
148 int_irq_list[irq].handler = handler;
149 int_irq_list[irq].flags = flags;
150 int_irq_list[irq].dev_id = dev_id;
151 int_irq_list[irq].devname = devname;
152
153 IMR &= ~(1<<irq);
154
155 return 0;
156}
157
158EXPORT_SYMBOL(request_irq);
159
160void free_irq(unsigned int irq, void *dev_id)
161{
162 if (irq >= NR_IRQS) {
163 printk (KERN_ERR "%s: Unknown IRQ %d\n", __FUNCTION__, irq);
164 return;
165 }
166
167 if (int_irq_list[irq].dev_id != dev_id)
168 printk(KERN_INFO "%s: removing probably wrong IRQ %d from %s\n",
169 __FUNCTION__, irq, int_irq_list[irq].devname);
170
171 int_irq_list[irq].handler = bad_interrupt;
172 int_irq_list[irq].flags = IRQ_FLG_STD;
173 int_irq_list[irq].dev_id = NULL;
174 int_irq_list[irq].devname = NULL;
175
176 IMR |= 1<<irq;
177}
178
179EXPORT_SYMBOL(free_irq);
180
181int show_interrupts(struct seq_file *p, void *v)
182{
183 int i = *(loff_t *) v;
184
185 if (i < NR_IRQS) {
186 if (int_irq_list[i].devname) {
187 seq_printf(p, "%3d: %10u ", i, kstat_cpu(0).irqs[i]);
188 if (int_irq_list[i].flags & IRQ_FLG_LOCK)
189 seq_printf(p, "L ");
190 else
191 seq_printf(p, " ");
192 seq_printf(p, "%s\n", int_irq_list[i].devname);
193 }
194 }
195 if (i == NR_IRQS)
196 seq_printf(p, " : %10u spurious\n", num_spurious);
197
198 return 0;
199}
200
201/* The 68k family did not have a good way to determine the source 104/* The 68k family did not have a good way to determine the source
202 * of interrupts until later in the family. The EC000 core does 105 * of interrupts until later in the family. The EC000 core does
203 * not provide the vector number on the stack, we vector everything 106 * not provide the vector number on the stack, we vector everything
@@ -255,14 +158,23 @@ void process_int(int vec, struct pt_regs *fp)
255 irq++; 158 irq++;
256 } 159 }
257 160
258 kstat_cpu(0).irqs[irq]++; 161 do_IRQ(irq, fp);
259
260 if (int_irq_list[irq].handler) {
261 int_irq_list[irq].handler(irq, int_irq_list[irq].dev_id, fp);
262 } else {
263 printk(KERN_ERR "unregistered interrupt %d!\nTurning it off in the IMR...\n", irq);
264 IMR |= mask;
265 }
266 pend &= ~mask; 162 pend &= ~mask;
267 } 163 }
268} 164}
165
166void enable_vector(unsigned int irq)
167{
168 IMR &= ~(1<<irq);
169}
170
171void disable_vector(unsigned int irq)
172{
173 IMR |= (1<<irq);
174}
175
176void ack_vector(unsigned int irq)
177{
178 /* Nothing needed */
179}
180
diff --git a/arch/m68knommu/platform/68360/entry.S b/arch/m68knommu/platform/68360/entry.S
index f1af8977f294..55dfefe38642 100644
--- a/arch/m68knommu/platform/68360/entry.S
+++ b/arch/m68knommu/platform/68360/entry.S
@@ -120,23 +120,21 @@ Lreturn:
120 RESTORE_ALL 120 RESTORE_ALL
121 121
122/* 122/*
123 * This is the main interrupt handler, responsible for calling process_int() 123 * This is the main interrupt handler, responsible for calling do_IRQ()
124 */ 124 */
125inthandler: 125inthandler:
126 SAVE_ALL 126 SAVE_ALL
127 addql #1,local_irq_count /* put exception # in d0*/
128 movew %sp@(PT_VECTOR), %d0 127 movew %sp@(PT_VECTOR), %d0
129 and.l #0x3ff, %d0 128 and.l #0x3ff, %d0
130 lsr.l #0x02, %d0 129 lsr.l #0x02, %d0
131 130
132 movel %sp,%sp@- 131 movel %sp,%sp@-
133 movel %d0,%sp@- /* put vector # on stack*/ 132 movel %d0,%sp@- /* put vector # on stack*/
134 jbsr process_int /* process the IRQ*/ 133 jbsr do_IRQ /* process the IRQ*/
1353: addql #8,%sp /* pop parameters off stack*/ 1343: addql #8,%sp /* pop parameters off stack*/
136 bra ret_from_interrupt 135 bra ret_from_interrupt
137 136
138ret_from_interrupt: 137ret_from_interrupt:
139 subql #1,local_irq_count
140 jeq 1f 138 jeq 1f
1412: 1392:
142 RESTORE_ALL 140 RESTORE_ALL
diff --git a/arch/m68knommu/platform/68360/ints.c b/arch/m68knommu/platform/68360/ints.c
index 4df3c146eb74..c36781157e09 100644
--- a/arch/m68knommu/platform/68360/ints.c
+++ b/arch/m68knommu/platform/68360/ints.c
@@ -10,20 +10,13 @@
10 * Copyright (c) 1999 D. Jeff Dionne <jeff@uclinux.org> 10 * Copyright (c) 1999 D. Jeff Dionne <jeff@uclinux.org>
11 */ 11 */
12 12
13#include <linux/module.h>
14#include <linux/types.h> 13#include <linux/types.h>
15#include <linux/kernel.h> 14#include <linux/kernel.h>
16#include <linux/sched.h> 15#include <linux/init.h>
17#include <linux/kernel_stat.h> 16#include <linux/interrupt.h>
18#include <linux/errno.h> 17#include <linux/irq.h>
19
20#include <asm/system.h>
21#include <asm/irq.h>
22#include <asm/irqnode.h>
23#include <asm/traps.h> 18#include <asm/traps.h>
24#include <asm/io.h>
25#include <asm/machdep.h> 19#include <asm/machdep.h>
26#include <asm/setup.h>
27#include <asm/m68360.h> 20#include <asm/m68360.h>
28 21
29/* from quicc/commproc.c: */ 22/* from quicc/commproc.c: */
@@ -36,26 +29,19 @@ extern void cpm_interrupt_init(void);
36asmlinkage void system_call(void); 29asmlinkage void system_call(void);
37asmlinkage void buserr(void); 30asmlinkage void buserr(void);
38asmlinkage void trap(void); 31asmlinkage void trap(void);
39asmlinkage irqreturn_t bad_interrupt(void); 32asmlinkage void bad_interrupt(void);
40asmlinkage irqreturn_t inthandler(void); 33asmlinkage void inthandler(void);
41 34
42extern void *_ramvec[]; 35extern void *_ramvec[];
43 36
44/* The number of spurious interrupts */ 37/* The number of spurious interrupts */
45volatile unsigned int num_spurious; 38volatile unsigned int num_spurious;
46unsigned int local_irq_count[NR_CPUS];
47
48/* irq node variables for the 32 (potential) on chip sources */
49static irq_node_t int_irq_list[INTERNAL_IRQS];
50
51static short int_irq_ablecount[INTERNAL_IRQS];
52 39
53/* 40/*
54 * This function should be called during kernel startup to initialize 41 * This function should be called during kernel startup to initialize
55 * IRQ handling routines. 42 * the vector table.
56 */ 43 */
57 44void init_vectors(void)
58void init_IRQ(void)
59{ 45{
60 int i; 46 int i;
61 int vba = (CPM_VECTOR_BASE<<4); 47 int vba = (CPM_VECTOR_BASE<<4);
@@ -79,7 +65,6 @@ void init_IRQ(void)
79 _ramvec[32] = system_call; 65 _ramvec[32] = system_call;
80 _ramvec[33] = trap; 66 _ramvec[33] = trap;
81 67
82
83 cpm_interrupt_init(); 68 cpm_interrupt_init();
84 69
85 /* set up CICR for vector base address and irq level */ 70 /* set up CICR for vector base address and irq level */
@@ -124,212 +109,20 @@ void init_IRQ(void)
124 109
125 /* turn off all CPM interrupts */ 110 /* turn off all CPM interrupts */
126 pquicc->intr_cimr = 0x00000000; 111 pquicc->intr_cimr = 0x00000000;
127
128 /* initialize handlers */
129 for (i = 0; i < INTERNAL_IRQS; i++) {
130 int_irq_list[i].handler = NULL;
131 int_irq_list[i].flags = IRQ_FLG_STD;
132 int_irq_list[i].dev_id = NULL;
133 int_irq_list[i].devname = NULL;
134 }
135}
136
137#if 0
138void M68360_insert_irq(irq_node_t **list, irq_node_t *node)
139{
140 unsigned long flags;
141 irq_node_t *cur;
142
143 if (!node->dev_id)
144 printk(KERN_INFO "%s: Warning: dev_id of %s is zero\n",
145 __FUNCTION__, node->devname);
146
147 local_irq_save(flags);
148
149 cur = *list;
150
151 while (cur) {
152 list = &cur->next;
153 cur = cur->next;
154 }
155
156 node->next = cur;
157 *list = node;
158
159 local_irq_restore(flags);
160} 112}
161 113
162void M68360_delete_irq(irq_node_t **list, void *dev_id) 114void enable_vector(unsigned int irq)
163{ 115{
164 unsigned long flags; 116 pquicc->intr_cimr |= (1 << irq);
165 irq_node_t *node;
166
167 local_irq_save(flags);
168
169 for (node = *list; node; list = &node->next, node = *list) {
170 if (node->dev_id == dev_id) {
171 *list = node->next;
172 /* Mark it as free. */
173 node->handler = NULL;
174 local_irq_restore(flags);
175 return;
176 }
177 }
178 local_irq_restore(flags);
179 printk (KERN_INFO "%s: tried to remove invalid irq\n", __FUNCTION__);
180} 117}
181#endif
182 118
183int request_irq( 119void disable_vector(unsigned int irq)
184 unsigned int irq,
185 irqreturn_t (*handler)(int, void *, struct pt_regs *),
186 unsigned long flags,
187 const char *devname,
188 void *dev_id)
189{ 120{
190 int mask = (1<<irq); 121 pquicc->intr_cimr &= ~(1 << irq);
191
192 irq += (CPM_VECTOR_BASE<<4);
193
194 if (irq >= INTERNAL_IRQS) {
195 printk (KERN_ERR "%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname);
196 return -ENXIO;
197 }
198
199 if (!(int_irq_list[irq].flags & IRQ_FLG_STD)) {
200 if (int_irq_list[irq].flags & IRQ_FLG_LOCK) {
201 printk(KERN_ERR "%s: IRQ %d from %s is not replaceable\n",
202 __FUNCTION__, irq, int_irq_list[irq].devname);
203 return -EBUSY;
204 }
205 if (flags & IRQ_FLG_REPLACE) {
206 printk(KERN_ERR "%s: %s can't replace IRQ %d from %s\n",
207 __FUNCTION__, devname, irq, int_irq_list[irq].devname);
208 return -EBUSY;
209 }
210 }
211 int_irq_list[irq].handler = handler;
212 int_irq_list[irq].flags = flags;
213 int_irq_list[irq].dev_id = dev_id;
214 int_irq_list[irq].devname = devname;
215
216 /* enable in the CIMR */
217 if (!int_irq_ablecount[irq])
218 pquicc->intr_cimr |= mask;
219 /* *(volatile unsigned long *)0xfffff304 &= ~(1<<irq); */
220
221 return 0;
222} 122}
223 123
224EXPORT_SYMBOL(request_irq); 124void ack_vector(unsigned int irq)
225
226void free_irq(unsigned int irq, void *dev_id)
227{ 125{
228 if (irq >= INTERNAL_IRQS) { 126 pquicc->intr_cisr = (1 << irq);
229 printk (KERN_ERR "%s: Unknown IRQ %d\n", __FUNCTION__, irq);
230 return;
231 }
232
233 if (int_irq_list[irq].dev_id != dev_id)
234 printk(KERN_INFO "%s: removing probably wrong IRQ %d from %s\n",
235 __FUNCTION__, irq, int_irq_list[irq].devname);
236 int_irq_list[irq].handler = NULL;
237 int_irq_list[irq].flags = IRQ_FLG_STD;
238 int_irq_list[irq].dev_id = NULL;
239 int_irq_list[irq].devname = NULL;
240
241 *(volatile unsigned long *)0xfffff304 |= 1<<irq;
242} 127}
243 128
244EXPORT_SYMBOL(free_irq);
245
246#if 0
247/*
248 * Enable/disable a particular machine specific interrupt source.
249 * Note that this may affect other interrupts in case of a shared interrupt.
250 * This function should only be called for a _very_ short time to change some
251 * internal data, that may not be changed by the interrupt at the same time.
252 * int_(enable|disable)_irq calls may also be nested.
253 */
254void M68360_enable_irq(unsigned int irq)
255{
256 if (irq >= INTERNAL_IRQS) {
257 printk(KERN_ERR "%s: Unknown IRQ %d\n", __FUNCTION__, irq);
258 return;
259 }
260
261 if (--int_irq_ablecount[irq])
262 return;
263
264 /* enable the interrupt */
265 *(volatile unsigned long *)0xfffff304 &= ~(1<<irq);
266}
267
268void M68360_disable_irq(unsigned int irq)
269{
270 if (irq >= INTERNAL_IRQS) {
271 printk(KERN_ERR "%s: Unknown IRQ %d\n", __FUNCTION__, irq);
272 return;
273 }
274
275 if (int_irq_ablecount[irq]++)
276 return;
277
278 /* disable the interrupt */
279 *(volatile unsigned long *)0xfffff304 |= 1<<irq;
280}
281#endif
282
283int show_interrupts(struct seq_file *p, void *v)
284{
285 int i = *(loff_t *) v;
286
287 if (i < NR_IRQS) {
288 if (int_irq_list[i].devname) {
289 seq_printf(p, "%3d: %10u ", i, kstat_cpu(0).irqs[i]);
290 if (int_irq_list[i].flags & IRQ_FLG_LOCK)
291 seq_printf(p, "L ");
292 else
293 seq_printf(p, " ");
294 seq_printf(p, "%s\n", int_irq_list[i].devname);
295 }
296 }
297 if (i == NR_IRQS)
298 seq_printf(p, " : %10u spurious\n", num_spurious);
299
300 return 0;
301}
302
303/* The 68k family did not have a good way to determine the source
304 * of interrupts until later in the family. The EC000 core does
305 * not provide the vector number on the stack, we vector everything
306 * into one vector and look in the blasted mask register...
307 * This code is designed to be fast, almost constant time, not clean!
308 */
309void process_int(int vec, struct pt_regs *fp)
310{
311 int irq;
312 int mask;
313
314 /* unsigned long pend = *(volatile unsigned long *)0xfffff30c; */
315
316 /* irq = vec + (CPM_VECTOR_BASE<<4); */
317 irq = vec;
318
319 /* unsigned long pend = *(volatile unsigned long *)pquicc->intr_cipr; */
320
321 /* Bugger all that weirdness. For the moment, I seem to know where I came from;
322 * vec is passed from a specific ISR, so I'll use it. */
323
324 if (int_irq_list[irq].handler) {
325 int_irq_list[irq].handler(irq , int_irq_list[irq].dev_id, fp);
326 kstat_cpu(0).irqs[irq]++;
327 pquicc->intr_cisr = (1 << vec); /* indicate that irq has been serviced */
328 } else {
329 printk(KERN_ERR "unregistered interrupt %d!\nTurning it off in the CIMR...\n", irq);
330 /* *(volatile unsigned long *)0xfffff304 |= mask; */
331 pquicc->intr_cimr &= ~(1 << vec);
332 num_spurious += 1;
333 }
334 return(IRQ_HANDLED);
335}