[MIPS] use generic_handle_irq, handle_level_irq, handle_percpu_irq
[linux-2.6.git] / arch / mips / jazz / irq.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 1992 Linus Torvalds
7  * Copyright (C) 1994 - 2001, 2003 Ralf Baechle
8  */
9 #include <linux/init.h>
10 #include <linux/interrupt.h>
11 #include <linux/kernel.h>
12 #include <linux/spinlock.h>
13
14 #include <asm/i8259.h>
15 #include <asm/io.h>
16 #include <asm/jazz.h>
17
18 static DEFINE_SPINLOCK(r4030_lock);
19
20 static void enable_r4030_irq(unsigned int irq)
21 {
22         unsigned int mask = 1 << (irq - JAZZ_PARALLEL_IRQ);
23         unsigned long flags;
24
25         spin_lock_irqsave(&r4030_lock, flags);
26         mask |= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
27         r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
28         spin_unlock_irqrestore(&r4030_lock, flags);
29 }
30
31 void disable_r4030_irq(unsigned int irq)
32 {
33         unsigned int mask = ~(1 << (irq - JAZZ_PARALLEL_IRQ));
34         unsigned long flags;
35
36         spin_lock_irqsave(&r4030_lock, flags);
37         mask &= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
38         r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
39         spin_unlock_irqrestore(&r4030_lock, flags);
40 }
41
42 static void end_r4030_irq(unsigned int irq)
43 {
44         if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
45                 enable_r4030_irq(irq);
46 }
47
48 static struct irq_chip r4030_irq_type = {
49         .typename = "R4030",
50         .ack = disable_r4030_irq,
51         .mask = disable_r4030_irq,
52         .mask_ack = disable_r4030_irq,
53         .unmask = enable_r4030_irq,
54         .end = end_r4030_irq,
55 };
56
57 void __init init_r4030_ints(void)
58 {
59         int i;
60
61         for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++)
62                 set_irq_chip_and_handler(i, &r4030_irq_type, handle_level_irq);
63
64         r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0);
65         r4030_read_reg16(JAZZ_IO_IRQ_SOURCE);           /* clear pending IRQs */
66         r4030_read_reg32(JAZZ_R4030_INVAL_ADDR);        /* clear error bits */
67 }
68
69 /*
70  * On systems with i8259-style interrupt controllers we assume for
71  * driver compatibility reasons interrupts 0 - 15 to be the i8259
72  * interrupts even if the hardware uses a different interrupt numbering.
73  */
74 void __init arch_init_irq(void)
75 {
76         init_i8259_irqs();                      /* Integrated i8259  */
77         init_r4030_ints();
78
79         change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
80 }
81
82 static void loc_call(unsigned int irq, unsigned int mask)
83 {
84         r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
85                           r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) & mask);
86         do_IRQ(irq);
87         r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
88                           r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | mask);
89 }
90
91 static void ll_local_dev(void)
92 {
93         switch (r4030_read_reg32(JAZZ_IO_IRQ_SOURCE)) {
94         case 0:
95                 panic("Unimplemented loc_no_irq handler");
96                 break;
97         case 4:
98                 loc_call(JAZZ_PARALLEL_IRQ, JAZZ_IE_PARALLEL);
99                 break;
100         case 8:
101                 loc_call(JAZZ_PARALLEL_IRQ, JAZZ_IE_FLOPPY);
102                 break;
103         case 12:
104                 panic("Unimplemented loc_sound handler");
105                 break;
106         case 16:
107                 panic("Unimplemented loc_video handler");
108                 break;
109         case 20:
110                 loc_call(JAZZ_ETHERNET_IRQ, JAZZ_IE_ETHERNET);
111                 break;
112         case 24:
113                 loc_call(JAZZ_SCSI_IRQ, JAZZ_IE_SCSI);
114                 break;
115         case 28:
116                 loc_call(JAZZ_KEYBOARD_IRQ, JAZZ_IE_KEYBOARD);
117                 break;
118         case 32:
119                 loc_call(JAZZ_MOUSE_IRQ, JAZZ_IE_MOUSE);
120                 break;
121         case 36:
122                 loc_call(JAZZ_SERIAL1_IRQ, JAZZ_IE_SERIAL1);
123                 break;
124         case 40:
125                 loc_call(JAZZ_SERIAL2_IRQ, JAZZ_IE_SERIAL2);
126                 break;
127         }
128 }
129
130 asmlinkage void plat_irq_dispatch(void)
131 {
132         unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
133
134         if (pending & IE_IRQ5)
135                 write_c0_compare(0);
136         else if (pending & IE_IRQ4) {
137                 r4030_read_reg32(JAZZ_TIMER_REGISTER);
138                 do_IRQ(JAZZ_TIMER_IRQ);
139         } else if (pending & IE_IRQ3)
140                 panic("Unimplemented ISA NMI handler");
141         else if (pending & IE_IRQ2)
142                 do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK));
143         else if (pending & IE_IRQ1) {
144                 ll_local_dev();
145         } else if (unlikely(pending & IE_IRQ0))
146                 panic("Unimplemented local_dma handler");
147         else if (pending & IE_SW1) {
148                 clear_c0_cause(IE_SW1);
149                 panic("Unimplemented sw1 handler");
150         } else if (pending & IE_SW0) {
151                 clear_c0_cause(IE_SW0);
152                 panic("Unimplemented sw0 handler");
153         }
154 }