aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/sni/pcit.c
diff options
context:
space:
mode:
authorThomas Bogendoerfer <tsbogend@alpha.franken.de>2006-12-28 12:22:32 -0500
committerRalf Baechle <ralf@linux-mips.org>2007-02-18 16:31:37 -0500
commitc066a32a890c50ce59e91f8cea8eb5fd8d5821b9 (patch)
treed129af235d11d44c649f0743bc38535c3a229e41 /arch/mips/sni/pcit.c
parent5759906ca9e5201c3fd40d61c861ec1e441d3a24 (diff)
[MIPS] Support for several more SNI RM models.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/sni/pcit.c')
-rw-r--r--arch/mips/sni/pcit.c351
1 files changed, 351 insertions, 0 deletions
diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c
new file mode 100644
index 000000000000..3921096023c3
--- /dev/null
+++ b/arch/mips/sni/pcit.c
@@ -0,0 +1,351 @@
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
31static struct plat_serial8250_port pcit_data[] = {
32 PORT(0x3f8, 0),
33 PORT(0x2f8, 3),
34 { },
35};
36
37static struct platform_device pcit_serial8250_device = {
38 .name = "serial8250",
39 .id = PLAT8250_DEV_PLATFORM,
40 .dev = {
41 .platform_data = pcit_data,
42 },
43};
44
45static 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
53static 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
61static struct resource sni_io_resource = {
62 .start = 0x00001000UL,
63 .end = 0x03bfffffUL,
64 .name = "PCIT IO MEM",
65 .flags = IORESOURCE_IO,
66};
67
68static 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
102static 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 */
122static 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
191static 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
207extern struct pci_ops sni_pcit_ops;
208
209static 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
217static 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
224void 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
231void end_pcit_irq(unsigned int irq)
232{
233 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
234 enable_pcit_irq(irq);
235}
236
237static 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
246static 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
259static 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
272static 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 (SNI_MIPS_IRQ_CPU_BASE + 4);
280 else if (pending & C_IRQ3)
281 do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 5);
282 else if (pending & C_IRQ5)
283 do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 7);
284}
285
286static 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 (SNI_MIPS_IRQ_CPU_BASE + 4);
294 else if (pending & C_IRQ3)
295 do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 5);
296 else if (pending & C_IRQ5)
297 do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 7);
298}
299
300void __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
313void __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
326void 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
337static 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
351device_initcall(snirm_pcit_setup_devinit);