aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k')
-rw-r--r--arch/m68k/kernel/entry.S11
-rw-r--r--arch/m68k/kernel/ints.c240
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c2
-rw-r--r--arch/m68k/kernel/setup.c3
-rw-r--r--arch/m68k/kernel/traps.c7
5 files changed, 163 insertions, 100 deletions
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 1fb88f3311de..48cccc556e13 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -48,6 +48,8 @@
48.globl sys_call_table 48.globl sys_call_table
49.globl sys_fork, sys_clone, sys_vfork 49.globl sys_fork, sys_clone, sys_vfork
50.globl ret_from_interrupt, bad_interrupt 50.globl ret_from_interrupt, bad_interrupt
51.globl auto_irqhandler_fixup
52.globl user_irqvec_fixup, user_irqhandler_fixup
51 53
52.text 54.text
53ENTRY(buserr) 55ENTRY(buserr)
@@ -212,6 +214,7 @@ ENTRY(auto_inthandler)
212 jbra 3f 214 jbra 3f
2131: 2151:
214#endif 216#endif
217auto_irqhandler_fixup = . + 2
215 jsr m68k_handle_int | process the IRQ 218 jsr m68k_handle_int | process the IRQ
2163: addql #8,%sp | pop parameters off stack 2193: addql #8,%sp | pop parameters off stack
217 220
@@ -234,17 +237,19 @@ ret_from_last_interrupt:
234 237
235/* Handler for user defined interrupt vectors */ 238/* Handler for user defined interrupt vectors */
236 239
237ENTRY(mach_inthandler) 240ENTRY(user_inthandler)
238 SAVE_ALL_INT 241 SAVE_ALL_INT
239 GET_CURRENT(%d0) 242 GET_CURRENT(%d0)
240 addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) 243 addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
241 | put exception # in d0 244 | put exception # in d0
242 bfextu %sp@(PT_VECTOR){#4,#10},%d0 245 bfextu %sp@(PT_VECTOR){#4,#10},%d0
246user_irqvec_fixup = . + 2
247 subw #VEC_USER,%d0
243 248
244 movel %sp,%sp@- 249 movel %sp,%sp@-
245 movel %d0,%sp@- | put vector # on stack 250 movel %d0,%sp@- | put vector # on stack
246 movel mach_process_int,%a0 251user_irqhandler_fixup = . + 2
247 jsr %a0@ | process the IRQ 252 jsr m68k_handle_int | process the IRQ
248 addql #8,%sp | pop parameters off stack 253 addql #8,%sp | pop parameters off stack
249 254
250 subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) 255 subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index c7f6ee67fd5a..5a8344b93547 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -39,14 +39,22 @@
39#include <asm/traps.h> 39#include <asm/traps.h>
40#include <asm/page.h> 40#include <asm/page.h>
41#include <asm/machdep.h> 41#include <asm/machdep.h>
42#include <asm/cacheflush.h>
42 43
43#ifdef CONFIG_Q40 44#ifdef CONFIG_Q40
44#include <asm/q40ints.h> 45#include <asm/q40ints.h>
45#endif 46#endif
46 47
48extern u32 auto_irqhandler_fixup[];
49extern u32 user_irqhandler_fixup[];
50extern u16 user_irqvec_fixup[];
51
47/* table for system interrupt handlers */ 52/* table for system interrupt handlers */
48static struct irq_node *irq_list[SYS_IRQS]; 53static struct irq_node *irq_list[NR_IRQS];
49static struct irq_controller *irq_controller[SYS_IRQS]; 54static struct irq_controller *irq_controller[NR_IRQS];
55static int irq_depth[NR_IRQS];
56
57static int m68k_first_user_vec;
50 58
51static struct irq_controller auto_irq_controller = { 59static struct irq_controller auto_irq_controller = {
52 .name = "auto", 60 .name = "auto",
@@ -55,39 +63,16 @@ static struct irq_controller auto_irq_controller = {
55 .shutdown = m68k_irq_shutdown, 63 .shutdown = m68k_irq_shutdown,
56}; 64};
57 65
58static const char *default_names[SYS_IRQS] = { 66static struct irq_controller user_irq_controller = {
59 [0] = "spurious int", 67 .name = "user",
60 [1] = "int1 handler", 68 .lock = SPIN_LOCK_UNLOCKED,
61 [2] = "int2 handler", 69 .startup = m68k_irq_startup,
62 [3] = "int3 handler", 70 .shutdown = m68k_irq_shutdown,
63 [4] = "int4 handler",
64 [5] = "int5 handler",
65 [6] = "int6 handler",
66 [7] = "int7 handler"
67}; 71};
68 72
69/* The number of spurious interrupts */
70volatile unsigned int num_spurious;
71
72#define NUM_IRQ_NODES 100 73#define NUM_IRQ_NODES 100
73static irq_node_t nodes[NUM_IRQ_NODES]; 74static irq_node_t nodes[NUM_IRQ_NODES];
74 75
75static void dummy_enable_irq(unsigned int irq);
76static void dummy_disable_irq(unsigned int irq);
77static int dummy_request_irq(unsigned int irq,
78 irqreturn_t (*handler) (int, void *, struct pt_regs *),
79 unsigned long flags, const char *devname, void *dev_id);
80static void dummy_free_irq(unsigned int irq, void *dev_id);
81
82void (*enable_irq) (unsigned int) = dummy_enable_irq;
83void (*disable_irq) (unsigned int) = dummy_disable_irq;
84
85int (*mach_request_irq) (unsigned int, irqreturn_t (*)(int, void *, struct pt_regs *),
86 unsigned long, const char *, void *) = dummy_request_irq;
87void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
88
89void init_irq_proc(void);
90
91/* 76/*
92 * void init_IRQ(void) 77 * void init_IRQ(void)
93 * 78 *
@@ -109,14 +94,70 @@ void __init init_IRQ(void)
109 hardirq_mask_is_broken(); 94 hardirq_mask_is_broken();
110 } 95 }
111 96
112 for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) { 97 for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++)
113 irq_controller[i] = &auto_irq_controller; 98 irq_controller[i] = &auto_irq_controller;
114 if (mach_default_handler && (*mach_default_handler)[i])
115 cpu_request_irq(i, (*mach_default_handler)[i],
116 0, default_names[i], NULL);
117 }
118 99
119 mach_init_IRQ (); 100 mach_init_IRQ();
101}
102
103/**
104 * m68k_setup_auto_interrupt
105 * @handler: called from auto vector interrupts
106 *
107 * setup the handler to be called from auto vector interrupts instead of the
108 * standard m68k_handle_int(), it will be called with irq numbers in the range
109 * from IRQ_AUTO_1 - IRQ_AUTO_7.
110 */
111void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *))
112{
113 if (handler)
114 *auto_irqhandler_fixup = (u32)handler;
115 flush_icache();
116}
117
118/**
119 * m68k_setup_user_interrupt
120 * @vec: first user vector interrupt to handle
121 * @cnt: number of active user vector interrupts
122 * @handler: called from user vector interrupts
123 *
124 * setup user vector interrupts, this includes activating the specified range
125 * of interrupts, only then these interrupts can be requested (note: this is
126 * different from auto vector interrupts). An optional handler can be installed
127 * to be called instead of the default m68k_handle_int(), it will be called
128 * with irq numbers starting from IRQ_USER.
129 */
130void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
131 void (*handler)(unsigned int, struct pt_regs *))
132{
133 int i;
134
135 m68k_first_user_vec = vec;
136 for (i = 0; i < cnt; i++)
137 irq_controller[IRQ_USER + i] = &user_irq_controller;
138 *user_irqvec_fixup = vec - IRQ_USER;
139 if (handler)
140 *user_irqhandler_fixup = (u32)handler;
141 flush_icache();
142}
143
144/**
145 * m68k_setup_irq_controller
146 * @contr: irq controller which controls specified irq
147 * @irq: first irq to be managed by the controller
148 *
149 * Change the controller for the specified range of irq, which will be used to
150 * manage these irq. auto/user irq already have a default controller, which can
151 * be changed as well, but the controller probably should use m68k_irq_startup/
152 * m68k_irq_shutdown.
153 */
154void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq,
155 unsigned int cnt)
156{
157 int i;
158
159 for (i = 0; i < cnt; i++)
160 irq_controller[irq + i] = contr;
120} 161}
121 162
122irq_node_t *new_irq_node(void) 163irq_node_t *new_irq_node(void)
@@ -135,34 +176,13 @@ irq_node_t *new_irq_node(void)
135 return NULL; 176 return NULL;
136} 177}
137 178
138/*
139 * We will keep these functions until I have convinced Linus to move
140 * the declaration of them from include/linux/sched.h to
141 * include/asm/irq.h.
142 */
143int request_irq(unsigned int irq,
144 irqreturn_t (*handler) (int, void *, struct pt_regs *),
145 unsigned long flags, const char *devname, void *dev_id)
146{
147 return mach_request_irq(irq, handler, flags, devname, dev_id);
148}
149
150EXPORT_SYMBOL(request_irq);
151
152void free_irq(unsigned int irq, void *dev_id)
153{
154 mach_free_irq(irq, dev_id);
155}
156
157EXPORT_SYMBOL(free_irq);
158
159int setup_irq(unsigned int irq, struct irq_node *node) 179int setup_irq(unsigned int irq, struct irq_node *node)
160{ 180{
161 struct irq_controller *contr; 181 struct irq_controller *contr;
162 struct irq_node **prev; 182 struct irq_node **prev;
163 unsigned long flags; 183 unsigned long flags;
164 184
165 if (irq >= SYS_IRQS || !(contr = irq_controller[irq])) { 185 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
166 printk("%s: Incorrect IRQ %d from %s\n", 186 printk("%s: Incorrect IRQ %d from %s\n",
167 __FUNCTION__, irq, node->devname); 187 __FUNCTION__, irq, node->devname);
168 return -ENXIO; 188 return -ENXIO;
@@ -195,9 +215,9 @@ int setup_irq(unsigned int irq, struct irq_node *node)
195 return 0; 215 return 0;
196} 216}
197 217
198int cpu_request_irq(unsigned int irq, 218int request_irq(unsigned int irq,
199 irqreturn_t (*handler)(int, void *, struct pt_regs *), 219 irqreturn_t (*handler) (int, void *, struct pt_regs *),
200 unsigned long flags, const char *devname, void *dev_id) 220 unsigned long flags, const char *devname, void *dev_id)
201{ 221{
202 struct irq_node *node; 222 struct irq_node *node;
203 int res; 223 int res;
@@ -218,13 +238,15 @@ int cpu_request_irq(unsigned int irq,
218 return res; 238 return res;
219} 239}
220 240
221void cpu_free_irq(unsigned int irq, void *dev_id) 241EXPORT_SYMBOL(request_irq);
242
243void free_irq(unsigned int irq, void *dev_id)
222{ 244{
223 struct irq_controller *contr; 245 struct irq_controller *contr;
224 struct irq_node **p, *node; 246 struct irq_node **p, *node;
225 unsigned long flags; 247 unsigned long flags;
226 248
227 if (irq >= SYS_IRQS || !(contr = irq_controller[irq])) { 249 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
228 printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); 250 printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
229 return; 251 return;
230 } 252 }
@@ -245,16 +267,69 @@ void cpu_free_irq(unsigned int irq, void *dev_id)
245 printk("%s: Removing probably wrong IRQ %d\n", 267 printk("%s: Removing probably wrong IRQ %d\n",
246 __FUNCTION__, irq); 268 __FUNCTION__, irq);
247 269
248 if (!irq_list[irq]) 270 if (!irq_list[irq]) {
249 contr->shutdown(irq); 271 if (contr->shutdown)
272 contr->shutdown(irq);
273 else
274 contr->disable(irq);
275 }
276
277 spin_unlock_irqrestore(&contr->lock, flags);
278}
279
280EXPORT_SYMBOL(free_irq);
281
282void enable_irq(unsigned int irq)
283{
284 struct irq_controller *contr;
285 unsigned long flags;
286
287 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
288 printk("%s: Incorrect IRQ %d\n",
289 __FUNCTION__, irq);
290 return;
291 }
292
293 spin_lock_irqsave(&contr->lock, flags);
294 if (irq_depth[irq]) {
295 if (!--irq_depth[irq]) {
296 if (contr->enable)
297 contr->enable(irq);
298 }
299 } else
300 WARN_ON(1);
301 spin_unlock_irqrestore(&contr->lock, flags);
302}
303
304EXPORT_SYMBOL(enable_irq);
250 305
306void disable_irq(unsigned int irq)
307{
308 struct irq_controller *contr;
309 unsigned long flags;
310
311 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
312 printk("%s: Incorrect IRQ %d\n",
313 __FUNCTION__, irq);
314 return;
315 }
316
317 spin_lock_irqsave(&contr->lock, flags);
318 if (!irq_depth[irq]++) {
319 if (contr->disable)
320 contr->disable(irq);
321 }
251 spin_unlock_irqrestore(&contr->lock, flags); 322 spin_unlock_irqrestore(&contr->lock, flags);
252} 323}
253 324
325EXPORT_SYMBOL(disable_irq);
326
254int m68k_irq_startup(unsigned int irq) 327int m68k_irq_startup(unsigned int irq)
255{ 328{
256 if (irq <= IRQ_AUTO_7) 329 if (irq <= IRQ_AUTO_7)
257 vectors[VEC_SPUR + irq] = auto_inthandler; 330 vectors[VEC_SPUR + irq] = auto_inthandler;
331 else
332 vectors[m68k_first_user_vec + irq - IRQ_USER] = user_inthandler;
258 return 0; 333 return 0;
259} 334}
260 335
@@ -262,6 +337,8 @@ void m68k_irq_shutdown(unsigned int irq)
262{ 337{
263 if (irq <= IRQ_AUTO_7) 338 if (irq <= IRQ_AUTO_7)
264 vectors[VEC_SPUR + irq] = bad_inthandler; 339 vectors[VEC_SPUR + irq] = bad_inthandler;
340 else
341 vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;
265} 342}
266 343
267 344
@@ -292,28 +369,16 @@ int probe_irq_off (unsigned long irqs)
292 369
293EXPORT_SYMBOL(probe_irq_off); 370EXPORT_SYMBOL(probe_irq_off);
294 371
295static void dummy_enable_irq(unsigned int irq) 372unsigned int irq_canonicalize(unsigned int irq)
296{ 373{
297 printk("calling uninitialized enable_irq()\n"); 374#ifdef CONFIG_Q40
298} 375 if (MACH_IS_Q40 && irq == 11)
299 376 irq = 10;
300static void dummy_disable_irq(unsigned int irq) 377#endif
301{ 378 return irq;
302 printk("calling uninitialized disable_irq()\n");
303}
304
305static int dummy_request_irq(unsigned int irq,
306 irqreturn_t (*handler) (int, void *, struct pt_regs *),
307 unsigned long flags, const char *devname, void *dev_id)
308{
309 printk("calling uninitialized request_irq()\n");
310 return 0;
311} 379}
312 380
313static void dummy_free_irq(unsigned int irq, void *dev_id) 381EXPORT_SYMBOL(irq_canonicalize);
314{
315 printk("calling uninitialized disable_irq()\n");
316}
317 382
318asmlinkage void m68k_handle_int(unsigned int irq, struct pt_regs *regs) 383asmlinkage void m68k_handle_int(unsigned int irq, struct pt_regs *regs)
319{ 384{
@@ -340,15 +405,14 @@ int show_interrupts(struct seq_file *p, void *v)
340 int i = *(loff_t *) v; 405 int i = *(loff_t *) v;
341 406
342 /* autovector interrupts */ 407 /* autovector interrupts */
343 if (i < SYS_IRQS && irq_list[i]) { 408 if (irq_list[i]) {
344 contr = irq_controller[i]; 409 contr = irq_controller[i];
345 node = irq_list[i]; 410 node = irq_list[i];
346 seq_printf(p, "%s %u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname); 411 seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname);
347 while ((node = node->next)) 412 while ((node = node->next))
348 seq_printf(p, ", %s", node->devname); 413 seq_printf(p, ", %s", node->devname);
349 seq_puts(p, "\n"); 414 seq_puts(p, "\n");
350 } else if (i == SYS_IRQS) 415 }
351 mach_get_irq_list(p, v);
352 return 0; 416 return 0;
353} 417}
354 418
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 5b7952ea2bae..1f5e1b5aeda4 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -57,8 +57,6 @@ EXPORT_SYMBOL(dump_thread);
57EXPORT_SYMBOL(strnlen); 57EXPORT_SYMBOL(strnlen);
58EXPORT_SYMBOL(strrchr); 58EXPORT_SYMBOL(strrchr);
59EXPORT_SYMBOL(strstr); 59EXPORT_SYMBOL(strstr);
60EXPORT_SYMBOL(enable_irq);
61EXPORT_SYMBOL(disable_irq);
62EXPORT_SYMBOL(kernel_thread); 60EXPORT_SYMBOL(kernel_thread);
63#ifdef CONFIG_VME 61#ifdef CONFIG_VME
64EXPORT_SYMBOL(vme_brdtype); 62EXPORT_SYMBOL(vme_brdtype);
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 750d5b3c971f..214a95f9f3ac 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -68,11 +68,8 @@ char m68k_debug_device[6] = "";
68void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) __initdata = NULL; 68void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
69/* machine dependent irq functions */ 69/* machine dependent irq functions */
70void (*mach_init_IRQ) (void) __initdata = NULL; 70void (*mach_init_IRQ) (void) __initdata = NULL;
71irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
72void (*mach_get_model) (char *model); 71void (*mach_get_model) (char *model);
73int (*mach_get_hardware_list) (char *buffer); 72int (*mach_get_hardware_list) (char *buffer);
74int (*mach_get_irq_list) (struct seq_file *, void *);
75irqreturn_t (*mach_process_int) (int, struct pt_regs *);
76/* machine dependent timer functions */ 73/* machine dependent timer functions */
77unsigned long (*mach_gettimeoffset) (void); 74unsigned long (*mach_gettimeoffset) (void);
78int (*mach_hwclk) (int, struct rtc_time*); 75int (*mach_hwclk) (int, struct rtc_time*);
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index b19b951fd3e7..e86de7b061cd 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -87,16 +87,15 @@ void __init trap_init (void)
87{ 87{
88 int i; 88 int i;
89 89
90 vectors[VEC_SPUR] = bad_inthandler; 90 for (i = VEC_SPUR; i <= VEC_INT7; i++)
91 for (i = VEC_INT1; i <= VEC_INT7; i++) 91 vectors[i] = bad_inthandler;
92 vectors[i] = auto_inthandler;
93 92
94 for (i = 0; i < VEC_USER; i++) 93 for (i = 0; i < VEC_USER; i++)
95 if (!vectors[i]) 94 if (!vectors[i])
96 vectors[i] = trap; 95 vectors[i] = trap;
97 96
98 for (i = VEC_USER; i < 256; i++) 97 for (i = VEC_USER; i < 256; i++)
99 vectors[i] = mach_inthandler; 98 vectors[i] = bad_inthandler;
100 99
101#ifdef CONFIG_M68KFPU_EMU 100#ifdef CONFIG_M68KFPU_EMU
102 if (FPU_IS_EMU) 101 if (FPU_IS_EMU)