015cf4bb51ddb4ab3fd92928e460df07d9509aff
[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 struct irq_chip r4030_irq_type = {
43         .name = "R4030",
44         .ack = disable_r4030_irq,
45         .mask = disable_r4030_irq,
46         .mask_ack = disable_r4030_irq,
47         .unmask = enable_r4030_irq,
48 };
49
50 void __init init_r4030_ints(void)
51 {
52         int i;
53
54         for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++)
55                 set_irq_chip_and_handler(i, &r4030_irq_type, handle_level_irq);
56
57         r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0);
58         r4030_read_reg16(JAZZ_IO_IRQ_SOURCE);           /* clear pending IRQs */
59         r4030_read_reg32(JAZZ_R4030_INVAL_ADDR);        /* clear error bits */
60 }
61
62 /*
63  * On systems with i8259-style interrupt controllers we assume for
64  * driver compatibility reasons interrupts 0 - 15 to be the i8259
65  * interrupts even if the hardware uses a different interrupt numbering.
66  */
67 void __init arch_init_irq(void)
68 {
69         init_i8259_irqs();                      /* Integrated i8259  */
70         init_r4030_ints();
71
72         change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
73 }
74
75 static void loc_call(unsigned int irq, unsigned int mask)
76 {
77         r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
78                           r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) & mask);
79         do_IRQ(irq);
80         r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
81                           r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | mask);
82 }
83
84 static void ll_local_dev(void)
85 {
86         switch (r4030_read_reg32(JAZZ_IO_IRQ_SOURCE)) {
87         case 0:
88                 panic("Unimplemented loc_no_irq handler");
89                 break;
90         case 4:
91                 loc_call(JAZZ_PARALLEL_IRQ, JAZZ_IE_PARALLEL);
92                 break;
93         case 8:
94                 loc_call(JAZZ_PARALLEL_IRQ, JAZZ_IE_FLOPPY);
95                 break;
96         case 12:
97                 panic("Unimplemented loc_sound handler");
98                 break;
99         case 16:
100                 panic("Unimplemented loc_video handler");
101                 break;
102         case 20:
103                 loc_call(JAZZ_ETHERNET_IRQ, JAZZ_IE_ETHERNET);
104                 break;
105         case 24:
106                 loc_call(JAZZ_SCSI_IRQ, JAZZ_IE_SCSI);
107                 break;
108         case 28:
109                 loc_call(JAZZ_KEYBOARD_IRQ, JAZZ_IE_KEYBOARD);
110                 break;
111         case 32:
112                 loc_call(JAZZ_MOUSE_IRQ, JAZZ_IE_MOUSE);
113                 break;
114         case 36:
115                 loc_call(JAZZ_SERIAL1_IRQ, JAZZ_IE_SERIAL1);
116                 break;
117         case 40:
118                 loc_call(JAZZ_SERIAL2_IRQ, JAZZ_IE_SERIAL2);
119                 break;
120         }
121 }
122
123 asmlinkage void plat_irq_dispatch(void)
124 {
125         unsigned int pending = read_c0_cause() & read_c0_status();
126
127         if (pending & IE_IRQ5)
128                 write_c0_compare(0);
129         else if (pending & IE_IRQ4) {
130                 r4030_read_reg32(JAZZ_TIMER_REGISTER);
131                 do_IRQ(JAZZ_TIMER_IRQ);
132         } else if (pending & IE_IRQ3)
133                 panic("Unimplemented ISA NMI handler");
134         else if (pending & IE_IRQ2)
135                 do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK));
136         else if (pending & IE_IRQ1) {
137                 ll_local_dev();
138         } else if (unlikely(pending & IE_IRQ0))
139                 panic("Unimplemented local_dma handler");
140         else if (pending & IE_SW1) {
141                 clear_c0_cause(IE_SW1);
142                 panic("Unimplemented sw1 handler");
143         } else if (pending & IE_SW0) {
144                 clear_c0_cause(IE_SW0);
145                 panic("Unimplemented sw0 handler");
146         }
147 }