Merge ../linux-2.6
[linux-2.6] / arch / m32r / kernel / setup_usrv.c
1 /*
2  *  linux/arch/m32r/kernel/setup_usrv.c
3  *
4  *  Setup routines for MITSUBISHI uServer
5  *
6  *  Copyright (c) 2001, 2002, 2003  Hiroyuki Kondo, Hirokazu Takata,
7  *                                  Hitoshi Yamamoto
8  */
9
10 #include <linux/config.h>
11 #include <linux/irq.h>
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14
15 #include <asm/system.h>
16 #include <asm/m32r.h>
17 #include <asm/io.h>
18
19 #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
20
21 icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
22
23 static void disable_mappi_irq(unsigned int irq)
24 {
25         unsigned long port, data;
26
27         port = irq2port(irq);
28         data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
29         outl(data, port);
30 }
31
32 static void enable_mappi_irq(unsigned int irq)
33 {
34         unsigned long port, data;
35
36         port = irq2port(irq);
37         data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
38         outl(data, port);
39 }
40
41 static void mask_and_ack_mappi(unsigned int irq)
42 {
43         disable_mappi_irq(irq);
44 }
45
46 static void end_mappi_irq(unsigned int irq)
47 {
48         enable_mappi_irq(irq);
49 }
50
51 static unsigned int startup_mappi_irq(unsigned int irq)
52 {
53         enable_mappi_irq(irq);
54         return 0;
55 }
56
57 static void shutdown_mappi_irq(unsigned int irq)
58 {
59         unsigned long port;
60
61         port = irq2port(irq);
62         outl(M32R_ICUCR_ILEVEL7, port);
63 }
64
65 static struct hw_interrupt_type mappi_irq_type =
66 {
67         .typename = "M32700-IRQ",
68         .startup = startup_mappi_irq,
69         .shutdown = shutdown_mappi_irq,
70         .enable = enable_mappi_irq,
71         .disable = disable_mappi_irq,
72         .ack = mask_and_ack_mappi,
73         .end = end_mappi_irq
74 };
75
76 /*
77  * Interrupt Control Unit of PLD on M32700UT (Level 2)
78  */
79 #define irq2pldirq(x)           ((x) - M32700UT_PLD_IRQ_BASE)
80 #define pldirq2port(x)          (unsigned long)((int)PLD_ICUCR1 + \
81                                  (((x) - 1) * sizeof(unsigned short)))
82
83 typedef struct {
84         unsigned short icucr;  /* ICU Control Register */
85 } pld_icu_data_t;
86
87 static pld_icu_data_t pld_icu_data[M32700UT_NUM_PLD_IRQ];
88
89 static void disable_m32700ut_pld_irq(unsigned int irq)
90 {
91         unsigned long port, data;
92         unsigned int pldirq;
93
94         pldirq = irq2pldirq(irq);
95         port = pldirq2port(pldirq);
96         data = pld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
97         outw(data, port);
98 }
99
100 static void enable_m32700ut_pld_irq(unsigned int irq)
101 {
102         unsigned long port, data;
103         unsigned int pldirq;
104
105         pldirq = irq2pldirq(irq);
106         port = pldirq2port(pldirq);
107         data = pld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
108         outw(data, port);
109 }
110
111 static void mask_and_ack_m32700ut_pld(unsigned int irq)
112 {
113         disable_m32700ut_pld_irq(irq);
114 }
115
116 static void end_m32700ut_pld_irq(unsigned int irq)
117 {
118         enable_m32700ut_pld_irq(irq);
119         end_mappi_irq(M32R_IRQ_INT1);
120 }
121
122 static unsigned int startup_m32700ut_pld_irq(unsigned int irq)
123 {
124         enable_m32700ut_pld_irq(irq);
125         return 0;
126 }
127
128 static void shutdown_m32700ut_pld_irq(unsigned int irq)
129 {
130         unsigned long port;
131         unsigned int pldirq;
132
133         pldirq = irq2pldirq(irq);
134         port = pldirq2port(pldirq);
135         outw(PLD_ICUCR_ILEVEL7, port);
136 }
137
138 static struct hw_interrupt_type m32700ut_pld_irq_type =
139 {
140         .typename = "USRV-PLD-IRQ",
141         .startup = startup_m32700ut_pld_irq,
142         .shutdown = shutdown_m32700ut_pld_irq,
143         .enable = enable_m32700ut_pld_irq,
144         .disable = disable_m32700ut_pld_irq,
145         .ack = mask_and_ack_m32700ut_pld,
146         .end = end_m32700ut_pld_irq
147 };
148
149 void __init init_IRQ(void)
150 {
151         static int once = 0;
152         int i;
153
154         if (once)
155                 return;
156         else
157                 once++;
158
159         /* MFT2 : system timer */
160         irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
161         irq_desc[M32R_IRQ_MFT2].handler = &mappi_irq_type;
162         irq_desc[M32R_IRQ_MFT2].action = 0;
163         irq_desc[M32R_IRQ_MFT2].depth = 1;
164         icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
165         disable_mappi_irq(M32R_IRQ_MFT2);
166
167 #if defined(CONFIG_SERIAL_M32R_SIO)
168         /* SIO0_R : uart receive data */
169         irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
170         irq_desc[M32R_IRQ_SIO0_R].handler = &mappi_irq_type;
171         irq_desc[M32R_IRQ_SIO0_R].action = 0;
172         irq_desc[M32R_IRQ_SIO0_R].depth = 1;
173         icu_data[M32R_IRQ_SIO0_R].icucr = 0;
174         disable_mappi_irq(M32R_IRQ_SIO0_R);
175
176         /* SIO0_S : uart send data */
177         irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
178         irq_desc[M32R_IRQ_SIO0_S].handler = &mappi_irq_type;
179         irq_desc[M32R_IRQ_SIO0_S].action = 0;
180         irq_desc[M32R_IRQ_SIO0_S].depth = 1;
181         icu_data[M32R_IRQ_SIO0_S].icucr = 0;
182         disable_mappi_irq(M32R_IRQ_SIO0_S);
183
184         /* SIO1_R : uart receive data */
185         irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
186         irq_desc[M32R_IRQ_SIO1_R].handler = &mappi_irq_type;
187         irq_desc[M32R_IRQ_SIO1_R].action = 0;
188         irq_desc[M32R_IRQ_SIO1_R].depth = 1;
189         icu_data[M32R_IRQ_SIO1_R].icucr = 0;
190         disable_mappi_irq(M32R_IRQ_SIO1_R);
191
192         /* SIO1_S : uart send data */
193         irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
194         irq_desc[M32R_IRQ_SIO1_S].handler = &mappi_irq_type;
195         irq_desc[M32R_IRQ_SIO1_S].action = 0;
196         irq_desc[M32R_IRQ_SIO1_S].depth = 1;
197         icu_data[M32R_IRQ_SIO1_S].icucr = 0;
198         disable_mappi_irq(M32R_IRQ_SIO1_S);
199 #endif  /* CONFIG_SERIAL_M32R_SIO */
200
201         /* INT#67-#71: CFC#0 IREQ on PLD */
202         for (i = 0 ; i < CONFIG_CFC_NUM ; i++ ) {
203                 irq_desc[PLD_IRQ_CF0 + i].status = IRQ_DISABLED;
204                 irq_desc[PLD_IRQ_CF0 + i].handler = &m32700ut_pld_irq_type;
205                 irq_desc[PLD_IRQ_CF0 + i].action = 0;
206                 irq_desc[PLD_IRQ_CF0 + i].depth = 1;    /* disable nested irq */
207                 pld_icu_data[irq2pldirq(PLD_IRQ_CF0 + i)].icucr
208                         = PLD_ICUCR_ISMOD01;    /* 'L' level sense */
209                 disable_m32700ut_pld_irq(PLD_IRQ_CF0 + i);
210         }
211
212 #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
213         /* INT#76: 16552D#0 IREQ on PLD */
214         irq_desc[PLD_IRQ_UART0].status = IRQ_DISABLED;
215         irq_desc[PLD_IRQ_UART0].handler = &m32700ut_pld_irq_type;
216         irq_desc[PLD_IRQ_UART0].action = 0;
217         irq_desc[PLD_IRQ_UART0].depth = 1;      /* disable nested irq */
218         pld_icu_data[irq2pldirq(PLD_IRQ_UART0)].icucr
219                 = PLD_ICUCR_ISMOD03;    /* 'H' level sense */
220         disable_m32700ut_pld_irq(PLD_IRQ_UART0);
221
222         /* INT#77: 16552D#1 IREQ on PLD */
223         irq_desc[PLD_IRQ_UART1].status = IRQ_DISABLED;
224         irq_desc[PLD_IRQ_UART1].handler = &m32700ut_pld_irq_type;
225         irq_desc[PLD_IRQ_UART1].action = 0;
226         irq_desc[PLD_IRQ_UART1].depth = 1;      /* disable nested irq */
227         pld_icu_data[irq2pldirq(PLD_IRQ_UART1)].icucr
228                 = PLD_ICUCR_ISMOD03;    /* 'H' level sense */
229         disable_m32700ut_pld_irq(PLD_IRQ_UART1);
230 #endif  /* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */
231
232 #if defined(CONFIG_IDC_AK4524) || defined(CONFIG_IDC_AK4524_MODULE)
233         /* INT#80: AK4524 IREQ on PLD */
234         irq_desc[PLD_IRQ_SNDINT].status = IRQ_DISABLED;
235         irq_desc[PLD_IRQ_SNDINT].handler = &m32700ut_pld_irq_type;
236         irq_desc[PLD_IRQ_SNDINT].action = 0;
237         irq_desc[PLD_IRQ_SNDINT].depth = 1;     /* disable nested irq */
238         pld_icu_data[irq2pldirq(PLD_IRQ_SNDINT)].icucr
239                 = PLD_ICUCR_ISMOD01;    /* 'L' level sense */
240         disable_m32700ut_pld_irq(PLD_IRQ_SNDINT);
241 #endif  /* CONFIG_IDC_AK4524 || CONFIG_IDC_AK4524_MODULE */
242
243         /*
244          * INT1# is used for UART, MMC, CF Controller in FPGA.
245          * We enable it here.
246          */
247         icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD11;
248         enable_mappi_irq(M32R_IRQ_INT1);
249 }
250