[MIPS] TXx9: Make single kernel can support multiple boards
[linux-2.6.git] / arch / mips / txx9 / rbtx4938 / irq.c
1 /*
2  * Toshiba RBTX4938 specific interrupt handlers
3  * Copyright (C) 2000-2001 Toshiba Corporation
4  *
5  * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
6  * terms of the GNU General Public License version 2. This program is
7  * licensed "as is" without any warranty of any kind, whether express
8  * or implied.
9  *
10  * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
11  */
12
13 /*
14 IRQ  Device
15
16 16   TX4938-CP0/00 Software 0
17 17   TX4938-CP0/01 Software 1
18 18   TX4938-CP0/02 Cascade TX4938-CP0
19 19   TX4938-CP0/03 Multiplexed -- do not use
20 20   TX4938-CP0/04 Multiplexed -- do not use
21 21   TX4938-CP0/05 Multiplexed -- do not use
22 22   TX4938-CP0/06 Multiplexed -- do not use
23 23   TX4938-CP0/07 CPU TIMER
24
25 24   TX4938-PIC/00
26 25   TX4938-PIC/01
27 26   TX4938-PIC/02 Cascade RBTX4938-IOC
28 27   TX4938-PIC/03 RBTX4938 RTL-8019AS Ethernet
29 28   TX4938-PIC/04
30 29   TX4938-PIC/05 TX4938 ETH1
31 30   TX4938-PIC/06 TX4938 ETH0
32 31   TX4938-PIC/07
33 32   TX4938-PIC/08 TX4938 SIO 0
34 33   TX4938-PIC/09 TX4938 SIO 1
35 34   TX4938-PIC/10 TX4938 DMA0
36 35   TX4938-PIC/11 TX4938 DMA1
37 36   TX4938-PIC/12 TX4938 DMA2
38 37   TX4938-PIC/13 TX4938 DMA3
39 38   TX4938-PIC/14
40 39   TX4938-PIC/15
41 40   TX4938-PIC/16 TX4938 PCIC
42 41   TX4938-PIC/17 TX4938 TMR0
43 42   TX4938-PIC/18 TX4938 TMR1
44 43   TX4938-PIC/19 TX4938 TMR2
45 44   TX4938-PIC/20
46 45   TX4938-PIC/21
47 46   TX4938-PIC/22 TX4938 PCIERR
48 47   TX4938-PIC/23
49 48   TX4938-PIC/24
50 49   TX4938-PIC/25
51 50   TX4938-PIC/26
52 51   TX4938-PIC/27
53 52   TX4938-PIC/28
54 53   TX4938-PIC/29
55 54   TX4938-PIC/30
56 55   TX4938-PIC/31 TX4938 SPI
57
58 56 RBTX4938-IOC/00 PCI-D
59 57 RBTX4938-IOC/01 PCI-C
60 58 RBTX4938-IOC/02 PCI-B
61 59 RBTX4938-IOC/03 PCI-A
62 60 RBTX4938-IOC/04 RTC
63 61 RBTX4938-IOC/05 ATA
64 62 RBTX4938-IOC/06 MODEM
65 63 RBTX4938-IOC/07 SWINT
66 */
67 #include <linux/init.h>
68 #include <linux/interrupt.h>
69 #include <asm/mipsregs.h>
70 #include <asm/txx9/generic.h>
71 #include <asm/txx9/rbtx4938.h>
72
73 static void toshiba_rbtx4938_irq_ioc_enable(unsigned int irq);
74 static void toshiba_rbtx4938_irq_ioc_disable(unsigned int irq);
75
76 #define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC"
77 static struct irq_chip toshiba_rbtx4938_irq_ioc_type = {
78         .name = TOSHIBA_RBTX4938_IOC_NAME,
79         .ack = toshiba_rbtx4938_irq_ioc_disable,
80         .mask = toshiba_rbtx4938_irq_ioc_disable,
81         .mask_ack = toshiba_rbtx4938_irq_ioc_disable,
82         .unmask = toshiba_rbtx4938_irq_ioc_enable,
83 };
84
85 static int toshiba_rbtx4938_irq_nested(int sw_irq)
86 {
87         u8 level3;
88
89         level3 = readb(rbtx4938_imstat_addr);
90         if (level3)
91                 /* must use fls so onboard ATA has priority */
92                 sw_irq = RBTX4938_IRQ_IOC + fls(level3) - 1;
93         return sw_irq;
94 }
95
96 /**********************************************************************************/
97 /* Functions for ioc                                                              */
98 /**********************************************************************************/
99 static void __init
100 toshiba_rbtx4938_irq_ioc_init(void)
101 {
102         int i;
103
104         for (i = RBTX4938_IRQ_IOC;
105              i < RBTX4938_IRQ_IOC + RBTX4938_NR_IRQ_IOC; i++)
106                 set_irq_chip_and_handler(i, &toshiba_rbtx4938_irq_ioc_type,
107                                          handle_level_irq);
108
109         set_irq_chained_handler(RBTX4938_IRQ_IOCINT, handle_simple_irq);
110 }
111
112 static void
113 toshiba_rbtx4938_irq_ioc_enable(unsigned int irq)
114 {
115         unsigned char v;
116
117         v = readb(rbtx4938_imask_addr);
118         v |= (1 << (irq - RBTX4938_IRQ_IOC));
119         writeb(v, rbtx4938_imask_addr);
120         mmiowb();
121 }
122
123 static void
124 toshiba_rbtx4938_irq_ioc_disable(unsigned int irq)
125 {
126         unsigned char v;
127
128         v = readb(rbtx4938_imask_addr);
129         v &= ~(1 << (irq - RBTX4938_IRQ_IOC));
130         writeb(v, rbtx4938_imask_addr);
131         mmiowb();
132 }
133
134 static int rbtx4938_irq_dispatch(int pending)
135 {
136         int irq;
137
138         if (pending & STATUSF_IP7)
139                 irq = MIPS_CPU_IRQ_BASE + 7;
140         else if (pending & STATUSF_IP2) {
141                 irq = txx9_irq();
142                 if (irq == RBTX4938_IRQ_IOCINT)
143                         irq = toshiba_rbtx4938_irq_nested(irq);
144         } else if (pending & STATUSF_IP1)
145                 irq = MIPS_CPU_IRQ_BASE + 0;
146         else if (pending & STATUSF_IP0)
147                 irq = MIPS_CPU_IRQ_BASE + 1;
148         else
149                 irq = -1;
150         return irq;
151 }
152
153 void __init rbtx4938_irq_setup(void)
154 {
155         txx9_irq_dispatch = rbtx4938_irq_dispatch;
156         /* Now, interrupt control disabled, */
157         /* all IRC interrupts are masked, */
158         /* all IRC interrupt mode are Low Active. */
159
160         /* mask all IOC interrupts */
161         writeb(0, rbtx4938_imask_addr);
162
163         /* clear SoftInt interrupts */
164         writeb(0, rbtx4938_softint_addr);
165         tx4938_irq_init();
166         toshiba_rbtx4938_irq_ioc_init();
167         /* Onboard 10M Ether: High Active */
168         set_irq_type(RBTX4938_IRQ_ETHER, IRQF_TRIGGER_HIGH);
169 }