File: /usr/src/linux/arch/cris/kernel/irq.c

1     /* $Id: irq.c,v 1.17 2001/07/25 16:08:01 bjornw Exp $
2      *
3      *	linux/arch/cris/kernel/irq.c
4      *
5      *      Copyright (c) 2000,2001 Axis Communications AB
6      *
7      *      Authors: Bjorn Wesen (bjornw@axis.com)
8      *
9      * This file contains the code used by various IRQ handling routines:
10      * asking for different IRQ's should be done through these routines
11      * instead of just grabbing them. Thus setups with different IRQ numbers
12      * shouldn't result in any weird surprises, and installing new handlers
13      * should be easier.
14      *
15      * Notice Linux/CRIS: these routines do not care about SMP
16      *
17      */
18     
19     /*
20      * IRQ's are in fact implemented a bit like signal handlers for the kernel.
21      * Naturally it's not a 1:1 relation, but there are similarities.
22      */
23     
24     #include <linux/config.h>
25     #include <linux/ptrace.h>
26     #include <linux/errno.h>
27     #include <linux/kernel_stat.h>
28     #include <linux/signal.h>
29     #include <linux/sched.h>
30     #include <linux/ioport.h>
31     #include <linux/interrupt.h>
32     #include <linux/timex.h>
33     #include <linux/slab.h>
34     #include <linux/random.h>
35     #include <linux/init.h>
36     
37     #include <asm/system.h>
38     #include <asm/io.h>
39     #include <asm/irq.h>
40     #include <asm/bitops.h>
41     
42     #include <asm/svinto.h>
43     
44     char *hw_bp_msg = "BP 0x%x\n";
45     
46     static inline void
47     mask_irq(unsigned int irq_nr)
48     {
49     	*R_VECT_MASK_CLR = 1 << irq_nr;
50     }
51     
52     static inline void
53     unmask_irq(unsigned int irq_nr)
54     {
55     	*R_VECT_MASK_SET = 1 << irq_nr;
56     }
57     
58     void
59     disable_irq(unsigned int irq_nr)
60     {
61     	unsigned long flags;
62     	
63     	save_flags(flags);
64     	cli();
65     	mask_irq(irq_nr);
66     	restore_flags(flags);
67     }
68     
69     void
70     enable_irq(unsigned int irq_nr)
71     {
72     	unsigned long flags;
73     	save_flags(flags);
74     	cli();
75     	unmask_irq(irq_nr);
76     	restore_flags(flags);
77     }
78     
79     unsigned long
80     probe_irq_on()
81     {
82     	return 0;
83     }
84     
85     int
86     probe_irq_off(unsigned long x)
87     {
88     	return 0;
89     }
90     
91     irqvectptr irq_shortcuts[NR_IRQS]; /* vector of shortcut jumps after the irq prologue */
92     
93     /* don't use set_int_vector, it bypasses the linux interrupt handlers. it is
94      * global just so that the kernel gdb can use it.
95      */
96     
97     void
98     set_int_vector(int n, irqvectptr addr, irqvectptr saddr)
99     {
100     	/* remember the shortcut entry point, after the prologue */
101     
102     	irq_shortcuts[n] = saddr;
103     
104     	etrax_irv->v[n + 0x20] = (irqvectptr)addr;
105     }
106     
107     /* the breakpoint vector is obviously not made just like the normal irq handlers
108      * but needs to contain _code_ to jump to addr.
109      *
110      * the BREAK n instruction jumps to IBR + n * 8
111      */
112     
113     void
114     set_break_vector(int n, irqvectptr addr)
115     {
116     	unsigned short *jinstr = (unsigned short *)&etrax_irv->v[n*2];
117     	unsigned long *jaddr = (unsigned long *)(jinstr + 1);
118     
119     	/* if you don't know what this does, do not touch it! */
120     	
121     	*jinstr = 0x0d3f;
122     	*jaddr = (unsigned long)addr;
123     
124     	/* 00000026 <clrlop+1a> 3f0d82000000     jump  0x82 */
125     }
126     
127     
128     /*
129      * This builds up the IRQ handler stubs using some ugly macros in irq.h
130      *
131      * These macros create the low-level assembly IRQ routines that do all
132      * the operations that are needed. They are also written to be fast - and to
133      * disable interrupts as little as humanly possible.
134      *
135      */
136     
137     /* IRQ0 and 1 are special traps */
138     void hwbreakpoint(void);
139     void IRQ1_interrupt(void);
140     BUILD_IRQ(2, 0x04)             /* the timer interrupt */
141     BUILD_IRQ(3, 0x08)
142     BUILD_IRQ(4, 0x10)
143     BUILD_IRQ(5, 0x20)
144     BUILD_IRQ(6, 0x40)
145     BUILD_IRQ(7, 0x80)
146     BUILD_IRQ(8, 0x100)
147     BUILD_IRQ(9, 0x200)
148     BUILD_IRQ(10, 0x400)
149     BUILD_IRQ(11, 0x800)
150     BUILD_IRQ(12, 0x1000)
151     BUILD_IRQ(13, 0x2000)
152     void mmu_bus_fault(void);      /* IRQ 14 is the bus fault interrupt */
153     void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */
154     BUILD_IRQ(16, 0x10000)
155     BUILD_IRQ(17, 0x20000)
156     BUILD_IRQ(18, 0x40000)
157     BUILD_IRQ(19, 0x80000)
158     BUILD_IRQ(20, 0x100000)
159     BUILD_IRQ(21, 0x200000)
160     BUILD_IRQ(22, 0x400000)
161     BUILD_IRQ(23, 0x800000)
162     BUILD_IRQ(24, 0x1000000)
163     BUILD_IRQ(25, 0x2000000)
164     /* IRQ 26-30 are reserved */
165     BUILD_IRQ(31, 0x80000000)
166      
167     /*
168      * Pointers to the low-level handlers 
169      */
170     
171     static void (*interrupt[NR_IRQS])(void) = {
172     	NULL, NULL, IRQ2_interrupt, IRQ3_interrupt,
173     	IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt,
174     	IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt,
175     	IRQ12_interrupt, IRQ13_interrupt, NULL, NULL,	
176     	IRQ16_interrupt, IRQ17_interrupt, IRQ18_interrupt, IRQ19_interrupt,	
177     	IRQ20_interrupt, IRQ21_interrupt, IRQ22_interrupt, IRQ23_interrupt,	
178     	IRQ24_interrupt, IRQ25_interrupt, NULL, NULL, NULL, NULL, NULL,
179     	IRQ31_interrupt
180     };
181     
182     static void (*sinterrupt[NR_IRQS])(void) = {
183     	NULL, NULL, sIRQ2_interrupt, sIRQ3_interrupt,
184     	sIRQ4_interrupt, sIRQ5_interrupt, sIRQ6_interrupt, sIRQ7_interrupt,
185     	sIRQ8_interrupt, sIRQ9_interrupt, sIRQ10_interrupt, sIRQ11_interrupt,
186     	sIRQ12_interrupt, sIRQ13_interrupt, NULL, NULL,	
187     	sIRQ16_interrupt, sIRQ17_interrupt, sIRQ18_interrupt, sIRQ19_interrupt,	
188     	sIRQ20_interrupt, sIRQ21_interrupt, sIRQ22_interrupt, sIRQ23_interrupt,	
189     	sIRQ24_interrupt, sIRQ25_interrupt, NULL, NULL, NULL, NULL, NULL,
190     	sIRQ31_interrupt
191     };
192     
193     static void (*bad_interrupt[NR_IRQS])(void) = {
194             NULL, NULL,
195     	NULL, bad_IRQ3_interrupt,
196     	bad_IRQ4_interrupt, bad_IRQ5_interrupt,
197     	bad_IRQ6_interrupt, bad_IRQ7_interrupt,
198     	bad_IRQ8_interrupt, bad_IRQ9_interrupt,
199     	bad_IRQ10_interrupt, bad_IRQ11_interrupt,
200     	bad_IRQ12_interrupt, bad_IRQ13_interrupt,
201     	NULL, NULL,
202     	bad_IRQ16_interrupt, bad_IRQ17_interrupt,
203     	bad_IRQ18_interrupt, bad_IRQ19_interrupt,
204     	bad_IRQ20_interrupt, bad_IRQ21_interrupt,
205     	bad_IRQ22_interrupt, bad_IRQ23_interrupt,
206     	bad_IRQ24_interrupt, bad_IRQ25_interrupt,
207     	NULL, NULL, NULL, NULL, NULL,
208     	bad_IRQ31_interrupt
209     };
210     
211     /*
212      * Initial irq handlers.
213      */
214     
215     static struct irqaction *irq_action[NR_IRQS] = {
216     	NULL, NULL, NULL, NULL,
217     	NULL, NULL, NULL, NULL,
218     	NULL, NULL, NULL, NULL,
219     	NULL, NULL, NULL, NULL,
220     	NULL, NULL, NULL, NULL,
221     	NULL, NULL, NULL, NULL,
222     	NULL, NULL, NULL, NULL,
223     	NULL, NULL, NULL, NULL
224     };
225     
226     int get_irq_list(char *buf)
227     {
228     	int i, len = 0;
229     	struct irqaction * action;
230     
231     	for (i = 0; i < NR_IRQS; i++) {
232     		action = irq_action[i];
233     		if (!action) 
234     			continue;
235     		len += sprintf(buf+len, "%2d: %10u %c %s",
236     			i, kstat.irqs[0][i],
237     			(action->flags & SA_INTERRUPT) ? '+' : ' ',
238     			action->name);
239     		for (action = action->next; action; action = action->next) {
240     			len += sprintf(buf+len, ",%s %s",
241     				(action->flags & SA_INTERRUPT) ? " +" : "",
242     				action->name);
243     		}
244     		len += sprintf(buf+len, "\n");
245     	}
246     	return len;
247     }
248     
249     /* called by the assembler IRQ entry functions defined in irq.h
250      * to dispatch the interrupts to registred handlers
251      * interrupts are disabled upon entry - depending on if the
252      * interrupt was registred with SA_INTERRUPT or not, interrupts
253      * are re-enabled or not.
254      */
255     
256     asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
257     {
258     	struct irqaction *action;
259     	int do_random, cpu;
260     
261             cpu = smp_processor_id();
262             irq_enter(cpu);
263     	kstat.irqs[cpu][irq]++;
264     
265     	action = irq_action[irq];
266             if (action) {
267                     if (!(action->flags & SA_INTERRUPT))
268                             __sti();
269                     action = irq_action[irq];
270                     do_random = 0;
271                     do {
272                             do_random |= action->flags;
273                             action->handler(irq, action->dev_id, regs);
274                             action = action->next;
275                     } while (action);
276                     if (do_random & SA_SAMPLE_RANDOM)
277                             add_interrupt_randomness(irq);
278                     __cli();
279             }
280             irq_exit(cpu);
281     
282     	if (softirq_pending(cpu))
283                     do_softirq();
284     
285             /* unmasking and bottom half handling is done magically for us. */
286     }
287     
288     /* this function links in a handler into the chain of handlers for the
289        given irq, and if the irq has never been registred, the appropriate
290        handler is entered into the interrupt vector
291     */
292     
293     int setup_etrax_irq(int irq, struct irqaction * new)
294     {
295     	int shared = 0;
296     	struct irqaction *old, **p;
297     	unsigned long flags;
298     
299     	p = irq_action + irq;
300     	if ((old = *p) != NULL) {
301     		/* Can't share interrupts unless both agree to */
302     		if (!(old->flags & new->flags & SA_SHIRQ))
303     			return -EBUSY;
304     
305     		/* Can't share interrupts unless both are same type */
306     		if ((old->flags ^ new->flags) & SA_INTERRUPT)
307     			return -EBUSY;
308     
309     		/* add new interrupt at end of irq queue */
310     		do {
311     			p = &old->next;
312     			old = *p;
313     		} while (old);
314     		shared = 1;
315     	}
316     
317     	if (new->flags & SA_SAMPLE_RANDOM)
318     		rand_initialize_irq(irq);
319     
320     	save_flags(flags);
321     	cli();
322     	*p = new;
323     
324     	if (!shared) {
325     		/* if the irq wasn't registred before, enter it into the vector table
326     		   and unmask it physically 
327     		*/
328     		set_int_vector(irq, interrupt[irq], sinterrupt[irq]);
329     		unmask_irq(irq);
330     	}
331     	
332     	restore_flags(flags);
333     	return 0;
334     }
335     
336     /* this function is called by a driver to register an irq handler
337        Valid flags:
338        SA_INTERRUPT -> it's a fast interrupt, handler called with irq disabled and
339                        no signal checking etc is performed upon exit
340        SA_SHIRQ -> the interrupt can be shared between different handlers, the handler
341                     is required to check if the irq was "aimed" at it explicitely
342        SA_RANDOM -> the interrupt will add to the random generators entropy
343     */
344     
345     int request_irq(unsigned int irq, 
346     		void (*handler)(int, void *, struct pt_regs *),
347     		unsigned long irqflags, 
348     		const char * devname,
349     		void *dev_id)
350     {
351     	int retval;
352     	struct irqaction * action;
353     
354     	/* interrupts 0 and 1 are hardware breakpoint and NMI and we can't support
355     	   these yet. interrupt 15 is the multiple irq, it's special. */
356     
357     	if(irq < 2 || irq == 15 || irq >= NR_IRQS)
358     		return -EINVAL;
359     
360     	if(!handler)
361     		return -EINVAL;
362     
363     	/* allocate and fill in a handler structure and setup the irq */
364     
365     	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
366     	if (!action)
367     		return -ENOMEM;
368     
369     	action->handler = handler;
370     	action->flags = irqflags;
371     	action->mask = 0;
372     	action->name = devname;
373     	action->next = NULL;
374     	action->dev_id = dev_id;
375     
376     	retval = setup_etrax_irq(irq, action);
377     
378     	if (retval)
379     		kfree(action);
380     	return retval;
381     }
382     		
383     void free_irq(unsigned int irq, void *dev_id)
384     {
385     	struct irqaction * action, **p;
386     	unsigned long flags;
387     
388     	if (irq >= NR_IRQS) {
389     		printk("Trying to free IRQ%d\n",irq);
390     		return;
391     	}
392     	for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
393     		if (action->dev_id != dev_id)
394     			continue;
395     
396     		/* Found it - now free it */
397     		save_flags(flags);
398     		cli();
399     		*p = action->next;
400     		if (!irq_action[irq]) {
401     			mask_irq(irq);
402     			set_int_vector(irq, bad_interrupt[irq], 0);
403     		}
404     		restore_flags(flags);
405     		kfree(action);
406     		return;
407     	}
408     	printk("Trying to free free IRQ%d\n",irq);
409     }
410     
411     void weird_irq(void)
412     {
413     	__asm__("di");
414     	printk("weird irq\n");
415     	while(1);
416     }
417     
418     /* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and
419        setting the irq vector table to point to bad_interrupt ptrs.
420     */
421     
422     void system_call(void);  /* from entry.S */
423     void do_sigtrap(void); /* from entry.S */
424     void gdb_handle_breakpoint(void); /* from entry.S */
425     
426     void __init
427     init_IRQ(void)
428     {
429     	int i;
430     
431     	/* clear all interrupt masks */
432     
433     #ifndef CONFIG_SVINTO_SIM
434     	*R_IRQ_MASK0_CLR = 0xffffffff;
435     	*R_IRQ_MASK1_CLR = 0xffffffff;
436     	*R_IRQ_MASK2_CLR = 0xffffffff;
437     #endif
438     
439     	*R_VECT_MASK_CLR = 0xffffffff;
440     
441     	/* clear the shortcut entry points */
442     
443     	for(i = 0; i < NR_IRQS; i++)
444     		irq_shortcuts[i] = NULL;
445             
446             for (i = 0; i < 256; i++)
447                    etrax_irv->v[i] = weird_irq;
448     
449             /* the entries in the break vector contain actual code to be
450                executed by the associated break handler, rather than just a jump
451                address. therefore we need to setup a default breakpoint handler
452                for all breakpoints */
453     
454     	for (i = 0; i < 16; i++)
455                     set_break_vector(i, do_sigtrap);
456             
457     	/* set all etrax irq's to the bad handlers */
458     	for (i = 2; i < NR_IRQS; i++)
459     		set_int_vector(i, bad_interrupt[i], 0);
460             
461     	/* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */
462     
463     	set_int_vector(15, multiple_interrupt, 0);
464     	
465     	/* 0 and 1 which are special breakpoint/NMI traps */
466     
467     	set_int_vector(0, hwbreakpoint, 0);
468     	set_int_vector(1, IRQ1_interrupt, 0);
469     
470     	/* and irq 14 which is the mmu bus fault handler */
471     
472     	set_int_vector(14, mmu_bus_fault, 0);
473     
474     	/* setup the system-call trap, which is reached by BREAK 13 */
475     
476     	set_break_vector(13, system_call);
477     
478             /* setup a breakpoint handler for debugging used for both user and
479                kernel mode debugging  (which is why it is not inside an ifdef
480                CONFIG_ETRAX_KGDB) */
481             set_break_vector(8, gdb_handle_breakpoint);
482     
483     #ifdef CONFIG_ETRAX_KGDB
484     	/* setup kgdb if its enabled, and break into the debugger */
485     	kgdb_init();
486     	breakpoint();
487     #endif
488     
489     }
490     
491     #if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
492     /* Used by other archs to show/control IRQ steering during SMP */
493     void __init
494     init_irq_proc(void)
495     {
496     }
497     #endif
498