[MIPS] Make SMTC_IDLE_HOOK_DEBUG a proper option in Kconfig.debug.
[linux-2.6] / arch / mips / sni / pcit.c
1 /*
2  * PCI Tower specific code
3  *
4  * This file is subject to the terms and conditions of the GNU General Public
5  * License.  See the file "COPYING" in the main directory of this archive
6  * for more details.
7  *
8  * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
9  */
10
11 #include <linux/init.h>
12 #include <linux/interrupt.h>
13 #include <linux/pci.h>
14 #include <linux/serial_8250.h>
15
16 #include <asm/mc146818-time.h>
17 #include <asm/sni.h>
18 #include <asm/time.h>
19 #include <asm/irq_cpu.h>
20
21
22 #define PORT(_base,_irq)                                \
23         {                                               \
24                 .iobase         = _base,                \
25                 .irq            = _irq,                 \
26                 .uartclk        = 1843200,              \
27                 .iotype         = UPIO_PORT,            \
28                 .flags          = UPF_BOOT_AUTOCONF,    \
29         }
30
31 static struct plat_serial8250_port pcit_data[] = {
32         PORT(0x3f8, 0),
33         PORT(0x2f8, 3),
34         { },
35 };
36
37 static struct platform_device pcit_serial8250_device = {
38         .name                   = "serial8250",
39         .id                     = PLAT8250_DEV_PLATFORM,
40         .dev                    = {
41                 .platform_data  = pcit_data,
42         },
43 };
44
45 static struct plat_serial8250_port pcit_cplus_data[] = {
46         PORT(0x3f8, 4),
47         PORT(0x2f8, 3),
48         PORT(0x3e8, 4),
49         PORT(0x2e8, 3),
50         { },
51 };
52
53 static struct platform_device pcit_cplus_serial8250_device = {
54         .name                   = "serial8250",
55         .id                     = PLAT8250_DEV_PLATFORM,
56         .dev                    = {
57                 .platform_data  = pcit_cplus_data,
58         },
59 };
60
61 static struct resource sni_io_resource = {
62         .start  = 0x00001000UL,
63         .end    = 0x03bfffffUL,
64         .name   = "PCIT IO MEM",
65         .flags  = IORESOURCE_IO,
66 };
67
68 static struct resource pcit_io_resources[] = {
69         {
70                 .start  = 0x00,
71                 .end    = 0x1f,
72                 .name   = "dma1",
73                 .flags  = IORESOURCE_BUSY
74         }, {
75                 .start  =  0x40,
76                 .end    = 0x5f,
77                 .name   = "timer",
78                 .flags  = IORESOURCE_BUSY
79         }, {
80                 .start  =  0x60,
81                 .end    = 0x6f,
82                 .name   = "keyboard",
83                 .flags  = IORESOURCE_BUSY
84         }, {
85                 .start  =  0x80,
86                 .end    = 0x8f,
87                 .name   = "dma page reg",
88                 .flags  = IORESOURCE_BUSY
89         }, {
90                 .start  =  0xc0,
91                 .end    = 0xdf,
92                 .name   = "dma2",
93                 .flags  = IORESOURCE_BUSY
94         }, {
95                 .start  =  0xcfc,
96                 .end    = 0xcff,
97                 .name   = "PCI config data",
98                 .flags  = IORESOURCE_BUSY
99         }
100 };
101
102 static struct resource sni_mem_resource = {
103         .start  = 0x10000000UL,
104         .end    = 0xffffffffUL,
105         .name   = "PCIT PCI MEM",
106         .flags  = IORESOURCE_MEM
107 };
108
109 /*
110  * The RM200/RM300 has a few holes in it's PCI/EISA memory address space used
111  * for other purposes.  Be paranoid and allocate all of the before the PCI
112  * code gets a chance to to map anything else there ...
113  *
114  * This leaves the following areas available:
115  *
116  * 0x10000000 - 0x1009ffff (640kB) PCI/EISA/ISA Bus Memory
117  * 0x10100000 - 0x13ffffff ( 15MB) PCI/EISA/ISA Bus Memory
118  * 0x18000000 - 0x1fbfffff (124MB) PCI/EISA Bus Memory
119  * 0x1ff08000 - 0x1ffeffff (816kB) PCI/EISA Bus Memory
120  * 0xa0000000 - 0xffffffff (1.5GB) PCI/EISA Bus Memory
121  */
122 static struct resource pcit_mem_resources[] = {
123         {
124                 .start  = 0x14000000,
125                 .end    = 0x17bfffff,
126                 .name   = "PCI IO",
127                 .flags  = IORESOURCE_BUSY
128         }, {
129                 .start  = 0x17c00000,
130                 .end    = 0x17ffffff,
131                 .name   = "Cache Replacement Area",
132                 .flags  = IORESOURCE_BUSY
133         }, {
134                 .start  = 0x180a0000,
135                 .end    = 0x180bffff,
136                 .name   = "Video RAM area",
137                 .flags  = IORESOURCE_BUSY
138         }, {
139                 .start  = 0x180c0000,
140                 .end    = 0x180fffff,
141                 .name   = "ISA Reserved",
142                 .flags  = IORESOURCE_BUSY
143         }, {
144                 .start  = 0x19000000,
145                 .end    = 0x1fbfffff,
146                 .name   = "PCI MEM",
147                 .flags  = IORESOURCE_BUSY
148         }, {
149                 .start  = 0x1fc00000,
150                 .end    = 0x1fc7ffff,
151                 .name   = "Boot PROM",
152                 .flags  = IORESOURCE_BUSY
153         }, {
154                 .start  = 0x1fc80000,
155                 .end    = 0x1fcfffff,
156                 .name   = "Diag PROM",
157                 .flags  = IORESOURCE_BUSY
158         }, {
159                 .start  = 0x1fd00000,
160                 .end    = 0x1fdfffff,
161                 .name   = "X-Bus",
162                 .flags  = IORESOURCE_BUSY
163         }, {
164                 .start  = 0x1fe00000,
165                 .end    = 0x1fefffff,
166                 .name   = "BIOS map",
167                 .flags  = IORESOURCE_BUSY
168         }, {
169                 .start  = 0x1ff00000,
170                 .end    = 0x1ff7ffff,
171                 .name   = "NVRAM / EEPROM",
172                 .flags  = IORESOURCE_BUSY
173         }, {
174                 .start  = 0x1fff0000,
175                 .end    = 0x1fffefff,
176                 .name   = "MAUI ASIC",
177                 .flags  = IORESOURCE_BUSY
178         }, {
179                 .start  = 0x1ffff000,
180                 .end    = 0x1fffffff,
181                 .name   = "MP Agent",
182                 .flags  = IORESOURCE_BUSY
183         }, {
184                 .start  = 0x20000000,
185                 .end    = 0x9fffffff,
186                 .name   = "Main Memory",
187                 .flags  = IORESOURCE_BUSY
188         }
189 };
190
191 static void __init sni_pcit_resource_init(void)
192 {
193         int i;
194
195         /* request I/O space for devices used on all i[345]86 PCs */
196         for (i = 0; i < ARRAY_SIZE(pcit_io_resources); i++)
197                 request_resource(&ioport_resource, pcit_io_resources + i);
198
199         /* request mem space for pcimt-specific devices */
200         for (i = 0; i < ARRAY_SIZE(pcit_mem_resources); i++)
201                 request_resource(&sni_mem_resource, pcit_mem_resources + i);
202
203         ioport_resource.end = sni_io_resource.end;
204 }
205
206
207 extern struct pci_ops sni_pcit_ops;
208
209 static struct pci_controller sni_pcit_controller = {
210         .pci_ops        = &sni_pcit_ops,
211         .mem_resource   = &sni_mem_resource,
212         .mem_offset     = 0x10000000UL,
213         .io_resource    = &sni_io_resource,
214         .io_offset      = 0x00000000UL
215 };
216
217 static void enable_pcit_irq(unsigned int irq)
218 {
219         u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24);
220
221         *(volatile u32 *)SNI_PCIT_INT_REG |= mask;
222 }
223
224 void disable_pcit_irq(unsigned int irq)
225 {
226         u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24);
227
228         *(volatile u32 *)SNI_PCIT_INT_REG &= ~mask;
229 }
230
231 void end_pcit_irq(unsigned int irq)
232 {
233         if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
234                 enable_pcit_irq(irq);
235 }
236
237 static struct irq_chip pcit_irq_type = {
238         .typename = "PCIT",
239         .ack = disable_pcit_irq,
240         .mask = disable_pcit_irq,
241         .mask_ack = disable_pcit_irq,
242         .unmask = enable_pcit_irq,
243         .end = end_pcit_irq,
244 };
245
246 static void pcit_hwint1(void)
247 {
248         u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG;
249         int irq;
250
251         clear_c0_status(IE_IRQ1);
252         irq = ffs((pending >> 16) & 0x7f);
253
254         if (likely(irq > 0))
255                 do_IRQ (irq + SNI_PCIT_INT_START - 1);
256         set_c0_status (IE_IRQ1);
257 }
258
259 static void pcit_hwint0(void)
260 {
261         u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG;
262         int irq;
263
264         clear_c0_status(IE_IRQ0);
265         irq = ffs((pending >> 16) & 0x7f);
266
267         if (likely(irq > 0))
268                 do_IRQ (irq + SNI_PCIT_INT_START - 1);
269         set_c0_status (IE_IRQ0);
270 }
271
272 static void sni_pcit_hwint(void)
273 {
274         u32 pending = (read_c0_cause() & read_c0_status());
275
276         if (pending & C_IRQ1)
277                 pcit_hwint1();
278         else if (pending & C_IRQ2)
279                 do_IRQ (MIPS_CPU_IRQ_BASE + 4);
280         else if (pending & C_IRQ3)
281                 do_IRQ (MIPS_CPU_IRQ_BASE + 5);
282         else if (pending & C_IRQ5)
283                 do_IRQ (MIPS_CPU_IRQ_BASE + 7);
284 }
285
286 static void sni_pcit_hwint_cplus(void)
287 {
288         u32 pending = (read_c0_cause() & read_c0_status());
289
290         if (pending & C_IRQ0)
291                 pcit_hwint0();
292         else if (pending & C_IRQ2)
293                 do_IRQ (MIPS_CPU_IRQ_BASE + 4);
294         else if (pending & C_IRQ3)
295                 do_IRQ (MIPS_CPU_IRQ_BASE + 5);
296         else if (pending & C_IRQ5)
297                 do_IRQ (MIPS_CPU_IRQ_BASE + 7);
298 }
299
300 void __init sni_pcit_irq_init(void)
301 {
302         int i;
303
304         mips_cpu_irq_init();
305         for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
306                 set_irq_chip(i, &pcit_irq_type);
307         *(volatile u32 *)SNI_PCIT_INT_REG = 0;
308         sni_hwint = sni_pcit_hwint;
309         change_c0_status(ST0_IM, IE_IRQ1);
310         setup_irq (SNI_PCIT_INT_START + 6, &sni_isa_irq);
311 }
312
313 void __init sni_pcit_cplus_irq_init(void)
314 {
315         int i;
316
317         mips_cpu_irq_init();
318         for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
319                 set_irq_chip(i, &pcit_irq_type);
320         *(volatile u32 *)SNI_PCIT_INT_REG = 0;
321         sni_hwint = sni_pcit_hwint_cplus;
322         change_c0_status(ST0_IM, IE_IRQ0);
323         setup_irq (SNI_PCIT_INT_START + 6, &sni_isa_irq);
324 }
325
326 void sni_pcit_init(void)
327 {
328         sni_pcit_resource_init();
329         rtc_mips_get_time = mc146818_get_cmos_time;
330         rtc_mips_set_time = mc146818_set_rtc_mmss;
331         board_time_init = sni_cpu_time_init;
332 #ifdef CONFIG_PCI
333         register_pci_controller(&sni_pcit_controller);
334 #endif
335 }
336
337 static int __init snirm_pcit_setup_devinit(void)
338 {
339         switch (sni_brd_type) {
340         case SNI_BRD_PCI_TOWER:
341                 platform_device_register(&pcit_serial8250_device);
342                 break;
343
344         case SNI_BRD_PCI_TOWER_CPLUS:
345                 platform_device_register(&pcit_cplus_serial8250_device);
346                 break;
347         }
348         return 0;
349 }
350
351 device_initcall(snirm_pcit_setup_devinit);