aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ixp23xx
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2006-03-28 15:18:54 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-03-28 15:18:54 -0500
commitc4713074375c61f939310b04e92090afe29810dc (patch)
treef09441eac8bd29a4a48f0360e1207d6def04b5fd /arch/arm/mach-ixp23xx
parente9937d4b0a9382c4c78411d1c53e62be396ee9a9 (diff)
[ARM] 3388/1: ixp23xx: add core ixp23xx support
Patch from Lennert Buytenhek This patch adds support for the Intel ixp23xx series of CPUs. The ixp23xx is an XSC3 based CPU with 512K of L2 cache, a 64bit 66MHz PCI interface, two DDR RAM interfaces, QDR RAM interfaces, two gigabit MACs, two 10/100 MACs, expansion bus, four microengines, a Media and Switch Fabric unit almost identical to the one on the ixp2400, two xscale (8250ish) UARTs and a bunch of other stuff. This patch adds the core ixp23xx support code, and support for the ADI Engineering Roadrunner, Intel IXDP2351, and IP Fabrics Double Espresso platforms. Signed-off-by: Deepak Saxena <dsaxena@plexity.net> Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-ixp23xx')
-rw-r--r--arch/arm/mach-ixp23xx/Kconfig25
-rw-r--r--arch/arm/mach-ixp23xx/Makefile11
-rw-r--r--arch/arm/mach-ixp23xx/Makefile.boot2
-rw-r--r--arch/arm/mach-ixp23xx/core.c431
-rw-r--r--arch/arm/mach-ixp23xx/espresso.c69
-rw-r--r--arch/arm/mach-ixp23xx/ixdp2351.c325
-rw-r--r--arch/arm/mach-ixp23xx/pci.c275
-rw-r--r--arch/arm/mach-ixp23xx/roadrunner.c164
8 files changed, 1302 insertions, 0 deletions
diff --git a/arch/arm/mach-ixp23xx/Kconfig b/arch/arm/mach-ixp23xx/Kconfig
new file mode 100644
index 000000000000..982670ec3866
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/Kconfig
@@ -0,0 +1,25 @@
1if ARCH_IXP23XX
2
3config ARCH_SUPPORTS_BIG_ENDIAN
4 bool
5 default y
6
7menu "Intel IXP23xx Implementation Options"
8
9comment "IXP23xx Platforms"
10
11config MACH_ESPRESSO
12 bool "Support IP Fabrics Double Espresso platform"
13 help
14
15config MACH_IXDP2351
16 bool "Support Intel IXDP2351 platform"
17 help
18
19config MACH_ROADRUNNER
20 bool "Support ADI RoadRunner platform"
21 help
22
23endmenu
24
25endif
diff --git a/arch/arm/mach-ixp23xx/Makefile b/arch/arm/mach-ixp23xx/Makefile
new file mode 100644
index 000000000000..288b371b6d03
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/Makefile
@@ -0,0 +1,11 @@
1#
2# Makefile for the linux kernel.
3#
4obj-y := core.o pci.o
5obj-m :=
6obj-n :=
7obj- :=
8
9obj-$(CONFIG_MACH_ESPRESSO) += espresso.o
10obj-$(CONFIG_MACH_IXDP2351) += ixdp2351.o
11obj-$(CONFIG_MACH_ROADRUNNER) += roadrunner.o
diff --git a/arch/arm/mach-ixp23xx/Makefile.boot b/arch/arm/mach-ixp23xx/Makefile.boot
new file mode 100644
index 000000000000..d5561ad15bad
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/Makefile.boot
@@ -0,0 +1,2 @@
1 zreladdr-y := 0x00008000
2params_phys-y := 0x00000100
diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c
new file mode 100644
index 000000000000..092ee12ced42
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/core.c
@@ -0,0 +1,431 @@
1/*
2 * arch/arm/mach-ixp23xx/core.c
3 *
4 * Core routines for IXP23xx chips
5 *
6 * Author: Deepak Saxena <dsaxena@plexity.net>
7 *
8 * Copyright 2005 (c) MontaVista Software, Inc.
9 *
10 * Based on 2.4 code Copyright 2004 (c) Intel Corporation
11 *
12 * This file is licensed under the terms of the GNU General Public
13 * License version 2. This program is licensed "as is" without any
14 * warranty of any kind, whether express or implied.
15 */
16
17#include <linux/config.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/spinlock.h>
21#include <linux/sched.h>
22#include <linux/interrupt.h>
23#include <linux/serial.h>
24#include <linux/tty.h>
25#include <linux/bitops.h>
26#include <linux/serial.h>
27#include <linux/serial_8250.h>
28#include <linux/serial_core.h>
29#include <linux/device.h>
30#include <linux/mm.h>
31#include <linux/time.h>
32#include <linux/timex.h>
33
34#include <asm/types.h>
35#include <asm/setup.h>
36#include <asm/memory.h>
37#include <asm/hardware.h>
38#include <asm/mach-types.h>
39#include <asm/irq.h>
40#include <asm/system.h>
41#include <asm/tlbflush.h>
42#include <asm/pgtable.h>
43
44#include <asm/mach/map.h>
45#include <asm/mach/time.h>
46#include <asm/mach/irq.h>
47#include <asm/mach/arch.h>
48
49
50/*************************************************************************
51 * Chip specific mappings shared by all IXP23xx systems
52 *************************************************************************/
53static struct map_desc ixp23xx_io_desc[] __initdata = {
54 { /* XSI-CPP CSRs */
55 .virtual = IXP23XX_XSI2CPP_CSR_VIRT,
56 .pfn = __phys_to_pfn(IXP23XX_XSI2CPP_CSR_PHYS),
57 .length = IXP23XX_XSI2CPP_CSR_SIZE,
58 .type = MT_DEVICE,
59 }, { /* Expansion Bus Config */
60 .virtual = IXP23XX_EXP_CFG_VIRT,
61 .pfn = __phys_to_pfn(IXP23XX_EXP_CFG_PHYS),
62 .length = IXP23XX_EXP_CFG_SIZE,
63 .type = MT_DEVICE,
64 }, { /* UART, Interrupt ctrl, GPIO, timers, NPEs, MACS,.... */
65 .virtual = IXP23XX_PERIPHERAL_VIRT,
66 .pfn = __phys_to_pfn(IXP23XX_PERIPHERAL_PHYS),
67 .length = IXP23XX_PERIPHERAL_SIZE,
68 .type = MT_DEVICE,
69 }, { /* CAP CSRs */
70 .virtual = IXP23XX_CAP_CSR_VIRT,
71 .pfn = __phys_to_pfn(IXP23XX_CAP_CSR_PHYS),
72 .length = IXP23XX_CAP_CSR_SIZE,
73 .type = MT_DEVICE,
74 }, { /* MSF CSRs */
75 .virtual = IXP23XX_MSF_CSR_VIRT,
76 .pfn = __phys_to_pfn(IXP23XX_MSF_CSR_PHYS),
77 .length = IXP23XX_MSF_CSR_SIZE,
78 .type = MT_DEVICE,
79 }, { /* PCI I/O Space */
80 .virtual = IXP23XX_PCI_IO_VIRT,
81 .pfn = __phys_to_pfn(IXP23XX_PCI_IO_PHYS),
82 .length = IXP23XX_PCI_IO_SIZE,
83 .type = MT_DEVICE,
84 }, { /* PCI Config Space */
85 .virtual = IXP23XX_PCI_CFG_VIRT,
86 .pfn = __phys_to_pfn(IXP23XX_PCI_CFG_PHYS),
87 .length = IXP23XX_PCI_CFG_SIZE,
88 .type = MT_DEVICE,
89 }, { /* PCI local CFG CSRs */
90 .virtual = IXP23XX_PCI_CREG_VIRT,
91 .pfn = __phys_to_pfn(IXP23XX_PCI_CREG_PHYS),
92 .length = IXP23XX_PCI_CREG_SIZE,
93 .type = MT_DEVICE,
94 }, { /* PCI MEM Space */
95 .virtual = IXP23XX_PCI_MEM_VIRT,
96 .pfn = __phys_to_pfn(IXP23XX_PCI_MEM_PHYS),
97 .length = IXP23XX_PCI_MEM_SIZE,
98 .type = MT_DEVICE,
99 }
100};
101
102void __init ixp23xx_map_io(void)
103{
104 iotable_init(ixp23xx_io_desc, ARRAY_SIZE(ixp23xx_io_desc));
105}
106
107
108/***************************************************************************
109 * IXP23xx Interrupt Handling
110 ***************************************************************************/
111enum ixp23xx_irq_type {
112 IXP23XX_IRQ_LEVEL, IXP23XX_IRQ_EDGE
113};
114
115static void ixp23xx_config_irq(unsigned int, enum ixp23xx_irq_type);
116
117static int ixp23xx_irq_set_type(unsigned int irq, unsigned int type)
118{
119 int line = irq - IRQ_IXP23XX_GPIO6 + 6;
120 u32 int_style;
121 enum ixp23xx_irq_type irq_type;
122 volatile u32 *int_reg;
123
124 /*
125 * Only GPIOs 6-15 are wired to interrupts on IXP23xx
126 */
127 if (line < 6 || line > 15)
128 return -EINVAL;
129
130 switch (type) {
131 case IRQT_BOTHEDGE:
132 int_style = IXP23XX_GPIO_STYLE_TRANSITIONAL;
133 irq_type = IXP23XX_IRQ_EDGE;
134 break;
135 case IRQT_RISING:
136 int_style = IXP23XX_GPIO_STYLE_RISING_EDGE;
137 irq_type = IXP23XX_IRQ_EDGE;
138 break;
139 case IRQT_FALLING:
140 int_style = IXP23XX_GPIO_STYLE_FALLING_EDGE;
141 irq_type = IXP23XX_IRQ_EDGE;
142 break;
143 case IRQT_HIGH:
144 int_style = IXP23XX_GPIO_STYLE_ACTIVE_HIGH;
145 irq_type = IXP23XX_IRQ_LEVEL;
146 break;
147 case IRQT_LOW:
148 int_style = IXP23XX_GPIO_STYLE_ACTIVE_LOW;
149 irq_type = IXP23XX_IRQ_LEVEL;
150 break;
151 default:
152 return -EINVAL;
153 }
154
155 ixp23xx_config_irq(irq, irq_type);
156
157 if (line >= 8) { /* pins 8-15 */
158 line -= 8;
159 int_reg = (volatile u32 *)IXP23XX_GPIO_GPIT2R;
160 } else { /* pins 0-7 */
161 int_reg = (volatile u32 *)IXP23XX_GPIO_GPIT1R;
162 }
163
164 /*
165 * Clear pending interrupts
166 */
167 *IXP23XX_GPIO_GPISR = (1 << line);
168
169 /* Clear the style for the appropriate pin */
170 *int_reg &= ~(IXP23XX_GPIO_STYLE_MASK <<
171 (line * IXP23XX_GPIO_STYLE_SIZE));
172
173 /* Set the new style */
174 *int_reg |= (int_style << (line * IXP23XX_GPIO_STYLE_SIZE));
175
176 return 0;
177}
178
179static void ixp23xx_irq_mask(unsigned int irq)
180{
181 volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
182
183 *intr_reg &= ~(1 << (irq % 32));
184}
185
186static void ixp23xx_irq_ack(unsigned int irq)
187{
188 int line = irq - IRQ_IXP23XX_GPIO6 + 6;
189
190 if ((line < 6) || (line > 15))
191 return;
192
193 *IXP23XX_GPIO_GPISR = (1 << line);
194}
195
196/*
197 * Level triggered interrupts on GPIO lines can only be cleared when the
198 * interrupt condition disappears.
199 */
200static void ixp23xx_irq_level_unmask(unsigned int irq)
201{
202 volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
203
204 ixp23xx_irq_ack(irq);
205
206 *intr_reg |= (1 << (irq % 32));
207}
208
209static void ixp23xx_irq_edge_unmask(unsigned int irq)
210{
211 volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
212
213 *intr_reg |= (1 << (irq % 32));
214}
215
216static struct irqchip ixp23xx_irq_level_chip = {
217 .ack = ixp23xx_irq_mask,
218 .mask = ixp23xx_irq_mask,
219 .unmask = ixp23xx_irq_level_unmask,
220 .set_type = ixp23xx_irq_set_type
221};
222
223static struct irqchip ixp23xx_irq_edge_chip = {
224 .ack = ixp23xx_irq_ack,
225 .mask = ixp23xx_irq_mask,
226 .unmask = ixp23xx_irq_edge_unmask,
227 .set_type = ixp23xx_irq_set_type
228};
229
230static void ixp23xx_pci_irq_mask(unsigned int irq)
231{
232 *IXP23XX_PCI_XSCALE_INT_ENABLE &= ~(1 << (IRQ_IXP23XX_INTA + 27 - irq));
233}
234
235static void ixp23xx_pci_irq_unmask(unsigned int irq)
236{
237 *IXP23XX_PCI_XSCALE_INT_ENABLE |= (1 << (IRQ_IXP23XX_INTA + 27 - irq));
238}
239
240/*
241 * TODO: Should this just be done at ASM level?
242 */
243static void pci_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
244{
245 u32 pci_interrupt;
246 unsigned int irqno;
247 struct irqdesc *int_desc;
248
249 pci_interrupt = *IXP23XX_PCI_XSCALE_INT_STATUS;
250
251 desc->chip->ack(irq);
252
253 /* See which PCI_INTA, or PCI_INTB interrupted */
254 if (pci_interrupt & (1 << 26)) {
255 irqno = IRQ_IXP23XX_INTB;
256 } else if (pci_interrupt & (1 << 27)) {
257 irqno = IRQ_IXP23XX_INTA;
258 } else {
259 BUG();
260 }
261
262 int_desc = irq_desc + irqno;
263 int_desc->handle(irqno, int_desc, regs);
264
265 desc->chip->unmask(irq);
266}
267
268static struct irqchip ixp23xx_pci_irq_chip = {
269 .ack = ixp23xx_pci_irq_mask,
270 .mask = ixp23xx_pci_irq_mask,
271 .unmask = ixp23xx_pci_irq_unmask
272};
273
274static void ixp23xx_config_irq(unsigned int irq, enum ixp23xx_irq_type type)
275{
276 switch (type) {
277 case IXP23XX_IRQ_LEVEL:
278 set_irq_chip(irq, &ixp23xx_irq_level_chip);
279 set_irq_handler(irq, do_level_IRQ);
280 break;
281 case IXP23XX_IRQ_EDGE:
282 set_irq_chip(irq, &ixp23xx_irq_edge_chip);
283 set_irq_handler(irq, do_edge_IRQ);
284 break;
285 }
286 set_irq_flags(irq, IRQF_VALID);
287}
288
289void __init ixp23xx_init_irq(void)
290{
291 int irq;
292
293 /* Route everything to IRQ */
294 *IXP23XX_INTR_SEL1 = 0x0;
295 *IXP23XX_INTR_SEL2 = 0x0;
296 *IXP23XX_INTR_SEL3 = 0x0;
297 *IXP23XX_INTR_SEL4 = 0x0;
298
299 /* Mask all sources */
300 *IXP23XX_INTR_EN1 = 0x0;
301 *IXP23XX_INTR_EN2 = 0x0;
302 *IXP23XX_INTR_EN3 = 0x0;
303 *IXP23XX_INTR_EN4 = 0x0;
304
305 /*
306 * Configure all IRQs for level-sensitive operation
307 */
308 for (irq = 0; irq <= NUM_IXP23XX_RAW_IRQS; irq++) {
309 ixp23xx_config_irq(irq, IXP23XX_IRQ_LEVEL);
310 }
311
312 for (irq = IRQ_IXP23XX_INTA; irq <= IRQ_IXP23XX_INTB; irq++) {
313 set_irq_chip(irq, &ixp23xx_pci_irq_chip);
314 set_irq_handler(irq, do_level_IRQ);
315 set_irq_flags(irq, IRQF_VALID);
316 }
317
318 set_irq_chained_handler(IRQ_IXP23XX_PCI_INT_RPH, pci_handler);
319}
320
321
322/*************************************************************************
323 * Timer-tick functions for IXP23xx
324 *************************************************************************/
325#define CLOCK_TICKS_PER_USEC CLOCK_TICK_RATE / (USEC_PER_SEC)
326
327static unsigned long next_jiffy_time;
328
329static unsigned long
330ixp23xx_gettimeoffset(void)
331{
332 unsigned long elapsed;
333
334 elapsed = *IXP23XX_TIMER_CONT - (next_jiffy_time - LATCH);
335
336 return elapsed / CLOCK_TICKS_PER_USEC;
337}
338
339static irqreturn_t
340ixp23xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
341{
342 /* Clear Pending Interrupt by writing '1' to it */
343 *IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND;
344 while ((*IXP23XX_TIMER_CONT - next_jiffy_time) > LATCH) {
345 timer_tick(regs);
346 next_jiffy_time += LATCH;
347 }
348
349 return IRQ_HANDLED;
350}
351
352static struct irqaction ixp23xx_timer_irq = {
353 .name = "IXP23xx Timer Tick",
354 .handler = ixp23xx_timer_interrupt,
355 .flags = SA_INTERRUPT | SA_TIMER,
356};
357
358void __init ixp23xx_init_timer(void)
359{
360 /* Clear Pending Interrupt by writing '1' to it */
361 *IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND;
362
363 /* Setup the Timer counter value */
364 *IXP23XX_TIMER1_RELOAD =
365 (LATCH & ~IXP23XX_TIMER_RELOAD_MASK) | IXP23XX_TIMER_ENABLE;
366
367 *IXP23XX_TIMER_CONT = 0;
368 next_jiffy_time = LATCH;
369
370 /* Connect the interrupt handler and enable the interrupt */
371 setup_irq(IRQ_IXP23XX_TIMER1, &ixp23xx_timer_irq);
372}
373
374struct sys_timer ixp23xx_timer = {
375 .init = ixp23xx_init_timer,
376 .offset = ixp23xx_gettimeoffset,
377};
378
379
380/*************************************************************************
381 * IXP23xx Platform Initializaion
382 *************************************************************************/
383static struct resource ixp23xx_uart_resources[] = {
384 {
385 .start = IXP23XX_UART1_PHYS,
386 .end = IXP23XX_UART1_PHYS + 0x0fff,
387 .flags = IORESOURCE_MEM
388 }, {
389 .start = IXP23XX_UART2_PHYS,
390 .end = IXP23XX_UART2_PHYS + 0x0fff,
391 .flags = IORESOURCE_MEM
392 }
393};
394
395static struct plat_serial8250_port ixp23xx_uart_data[] = {
396 {
397 .mapbase = IXP23XX_UART1_PHYS,
398 .membase = (char *)(IXP23XX_UART1_VIRT + 3),
399 .irq = IRQ_IXP23XX_UART1,
400 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
401 .iotype = UPIO_MEM,
402 .regshift = 2,
403 .uartclk = IXP23XX_UART_XTAL,
404 }, {
405 .mapbase = IXP23XX_UART2_PHYS,
406 .membase = (char *)(IXP23XX_UART2_VIRT + 3),
407 .irq = IRQ_IXP23XX_UART2,
408 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
409 .iotype = UPIO_MEM,
410 .regshift = 2,
411 .uartclk = IXP23XX_UART_XTAL,
412 },
413 { },
414};
415
416static struct platform_device ixp23xx_uart = {
417 .name = "serial8250",
418 .id = 0,
419 .dev.platform_data = ixp23xx_uart_data,
420 .num_resources = 2,
421 .resource = ixp23xx_uart_resources,
422};
423
424static struct platform_device *ixp23xx_devices[] __initdata = {
425 &ixp23xx_uart,
426};
427
428void __init ixp23xx_sys_init(void)
429{
430 platform_add_devices(ixp23xx_devices, ARRAY_SIZE(ixp23xx_devices));
431}
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c
new file mode 100644
index 000000000000..2327c9790416
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/espresso.c
@@ -0,0 +1,69 @@
1/*
2 * arch/arm/mach-ixp23xx/espresso.c
3 *
4 * Double Espresso-specific routines
5 *
6 * Author: Lennert Buytenhek <buytenh@wantstofly.org>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/config.h>
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/spinlock.h>
17#include <linux/sched.h>
18#include <linux/interrupt.h>
19#include <linux/serial.h>
20#include <linux/tty.h>
21#include <linux/bitops.h>
22#include <linux/ioport.h>
23#include <linux/serial.h>
24#include <linux/serial_8250.h>
25#include <linux/serial_core.h>
26#include <linux/device.h>
27#include <linux/mm.h>
28#include <linux/pci.h>
29#include <linux/mtd/physmap.h>
30
31#include <asm/types.h>
32#include <asm/setup.h>
33#include <asm/memory.h>
34#include <asm/hardware.h>
35#include <asm/mach-types.h>
36#include <asm/irq.h>
37#include <asm/system.h>
38#include <asm/tlbflush.h>
39#include <asm/pgtable.h>
40
41#include <asm/mach/map.h>
42#include <asm/mach/irq.h>
43#include <asm/mach/arch.h>
44#include <asm/mach/irq.h>
45#include <asm/mach/pci.h>
46
47static void __init espresso_init(void)
48{
49 physmap_configure(0x90000000, 0x02000000, 2, NULL);
50
51 /*
52 * Mark flash as writeable.
53 */
54 IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE;
55 IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE;
56
57 ixp23xx_sys_init();
58}
59
60MACHINE_START(ESPRESSO, "IP Fabrics Double Espresso")
61 /* Maintainer: Lennert Buytenhek */
62 .phys_io = IXP23XX_PERIPHERAL_PHYS,
63 .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
64 .map_io = ixp23xx_map_io,
65 .init_irq = ixp23xx_init_irq,
66 .timer = &ixp23xx_timer,
67 .boot_params = 0x00000100,
68 .init_machine = espresso_init,
69MACHINE_END
diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c
new file mode 100644
index 000000000000..00146c35daac
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/ixdp2351.c
@@ -0,0 +1,325 @@
1/*
2 * arch/arm/mach-ixp23xx/ixdp2351.c
3 *
4 * IXDP2351 board-specific routines
5 *
6 * Author: Deepak Saxena <dsaxena@plexity.net>
7 *
8 * Copyright 2005 (c) MontaVista Software, Inc.
9 *
10 * Based on 2.4 code Copyright 2004 (c) Intel Corporation
11 *
12 * This file is licensed under the terms of the GNU General Public
13 * License version 2. This program is licensed "as is" without any
14 * warranty of any kind, whether express or implied.
15 */
16
17#include <linux/config.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/spinlock.h>
21#include <linux/sched.h>
22#include <linux/interrupt.h>
23#include <linux/serial.h>
24#include <linux/tty.h>
25#include <linux/bitops.h>
26#include <linux/ioport.h>
27#include <linux/serial.h>
28#include <linux/serial_8250.h>
29#include <linux/serial_core.h>
30#include <linux/device.h>
31#include <linux/mm.h>
32#include <linux/pci.h>
33#include <linux/mtd/physmap.h>
34
35#include <asm/types.h>
36#include <asm/setup.h>
37#include <asm/memory.h>
38#include <asm/hardware.h>
39#include <asm/mach-types.h>
40#include <asm/irq.h>
41#include <asm/system.h>
42#include <asm/tlbflush.h>
43#include <asm/pgtable.h>
44
45#include <asm/mach/map.h>
46#include <asm/mach/irq.h>
47#include <asm/mach/arch.h>
48#include <asm/mach/irq.h>
49#include <asm/mach/pci.h>
50
51/*
52 * IXDP2351 Interrupt Handling
53 */
54static void ixdp2351_inta_mask(unsigned int irq)
55{
56 *IXDP2351_CPLD_INTA_MASK_SET_REG = IXDP2351_INTA_IRQ_MASK(irq);
57}
58
59static void ixdp2351_inta_unmask(unsigned int irq)
60{
61 *IXDP2351_CPLD_INTA_MASK_CLR_REG = IXDP2351_INTA_IRQ_MASK(irq);
62}
63
64static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
65{
66 u16 ex_interrupt =
67 *IXDP2351_CPLD_INTA_STAT_REG & IXDP2351_INTA_IRQ_VALID;
68 int i;
69
70 desc->chip->mask(irq);
71
72 for (i = 0; i < IXDP2351_INTA_IRQ_NUM; i++) {
73 if (ex_interrupt & (1 << i)) {
74 struct irqdesc *cpld_desc;
75 int cpld_irq =
76 IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + i);
77 cpld_desc = irq_desc + cpld_irq;
78 cpld_desc->handle(cpld_irq, cpld_desc, regs);
79 }
80 }
81
82 desc->chip->unmask(irq);
83}
84
85static struct irqchip ixdp2351_inta_chip = {
86 .ack = ixdp2351_inta_mask,
87 .mask = ixdp2351_inta_mask,
88 .unmask = ixdp2351_inta_unmask
89};
90
91static void ixdp2351_intb_mask(unsigned int irq)
92{
93 *IXDP2351_CPLD_INTB_MASK_SET_REG = IXDP2351_INTB_IRQ_MASK(irq);
94}
95
96static void ixdp2351_intb_unmask(unsigned int irq)
97{
98 *IXDP2351_CPLD_INTB_MASK_CLR_REG = IXDP2351_INTB_IRQ_MASK(irq);
99}
100
101static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
102{
103 u16 ex_interrupt =
104 *IXDP2351_CPLD_INTB_STAT_REG & IXDP2351_INTB_IRQ_VALID;
105 int i;
106
107 desc->chip->ack(irq);
108
109 for (i = 0; i < IXDP2351_INTB_IRQ_NUM; i++) {
110 if (ex_interrupt & (1 << i)) {
111 struct irqdesc *cpld_desc;
112 int cpld_irq =
113 IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i);
114 cpld_desc = irq_desc + cpld_irq;
115 cpld_desc->handle(cpld_irq, cpld_desc, regs);
116 }
117 }
118
119 desc->chip->unmask(irq);
120}
121
122static struct irqchip ixdp2351_intb_chip = {
123 .ack = ixdp2351_intb_mask,
124 .mask = ixdp2351_intb_mask,
125 .unmask = ixdp2351_intb_unmask
126};
127
128void ixdp2351_init_irq(void)
129{
130 int irq;
131
132 /* Mask all interrupts from CPLD, disable simulation */
133 *IXDP2351_CPLD_INTA_MASK_SET_REG = (u16) -1;
134 *IXDP2351_CPLD_INTB_MASK_SET_REG = (u16) -1;
135 *IXDP2351_CPLD_INTA_SIM_REG = 0;
136 *IXDP2351_CPLD_INTB_SIM_REG = 0;
137
138 ixp23xx_init_irq();
139
140 for (irq = IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE);
141 irq <
142 IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + IXDP2351_INTA_IRQ_NUM);
143 irq++) {
144 if (IXDP2351_INTA_IRQ_MASK(irq) & IXDP2351_INTA_IRQ_VALID) {
145 set_irq_flags(irq, IRQF_VALID);
146 set_irq_handler(irq, do_level_IRQ);
147 set_irq_chip(irq, &ixdp2351_inta_chip);
148 }
149 }
150
151 for (irq = IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE);
152 irq <
153 IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + IXDP2351_INTB_IRQ_NUM);
154 irq++) {
155 if (IXDP2351_INTB_IRQ_MASK(irq) & IXDP2351_INTB_IRQ_VALID) {
156 set_irq_flags(irq, IRQF_VALID);
157 set_irq_handler(irq, do_level_IRQ);
158 set_irq_chip(irq, &ixdp2351_intb_chip);
159 }
160 }
161
162 set_irq_chained_handler(IRQ_IXP23XX_INTA, &ixdp2351_inta_handler);
163 set_irq_chained_handler(IRQ_IXP23XX_INTB, &ixdp2351_intb_handler);
164}
165
166/*
167 * IXDP2351 PCI
168 */
169
170/*
171 * This board does not do normal PCI IRQ routing, or any
172 * sort of swizzling, so we just need to check where on the
173 * bus the device is and figure out what CPLD pin it is
174 * being routed to.
175 */
176#define DEVPIN(dev, pin) ((pin) | ((dev) << 3))
177
178static int __init ixdp2351_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
179{
180 u8 bus = dev->bus->number;
181 u32 devpin = DEVPIN(PCI_SLOT(dev->devfn), pin);
182 struct pci_bus *tmp_bus = dev->bus;
183
184 /* Primary bus, no interrupts here */
185 if (!bus)
186 return -1;
187
188 /* Lookup first leaf in bus tree */
189 while ((tmp_bus->parent != NULL) && (tmp_bus->parent->parent != NULL))
190 tmp_bus = tmp_bus->parent;
191
192 /* Select between known bridges */
193 switch (tmp_bus->self->devfn | (tmp_bus->self->bus->number << 8)) {
194 /* Device is located after first bridge */
195 case 0x0008:
196 if (tmp_bus == dev->bus) {
197 /* Device is located directy after first bridge */
198 switch (devpin) {
199 /* Onboard 82546 */
200 case DEVPIN(1, 1): /* Onboard 82546 ch 0 */
201 return IRQ_IXDP2351_INTA_82546;
202 case DEVPIN(1, 2): /* Onboard 82546 ch 1 */
203 return IRQ_IXDP2351_INTB_82546;
204 /* PMC SLOT */
205 case DEVPIN(0, 1): /* PMCP INTA# */
206 case DEVPIN(2, 4): /* PMCS INTD# */
207 return IRQ_IXDP2351_SPCI_PMC_INTA;
208 case DEVPIN(0, 2): /* PMCP INTB# */
209 case DEVPIN(2, 1): /* PMCS INTA# */
210 return IRQ_IXDP2351_SPCI_PMC_INTB;
211 case DEVPIN(0, 3): /* PMCP INTC# */
212 case DEVPIN(2, 2): /* PMCS INTB# */
213 return IRQ_IXDP2351_SPCI_PMC_INTC;
214 case DEVPIN(0, 4): /* PMCP INTD# */
215 case DEVPIN(2, 3): /* PMCS INTC# */
216 return IRQ_IXDP2351_SPCI_PMC_INTD;
217 }
218 } else {
219 /* Device is located indirectly after first bridge */
220 /* Not supported now */
221 return -1;
222 }
223 break;
224 case 0x0010:
225 if (tmp_bus == dev->bus) {
226 /* Device is located directy after second bridge */
227 /* Secondary bus of second bridge */
228 switch (devpin) {
229 case DEVPIN(0, 1): /* DB#0 */
230 case DEVPIN(0, 2):
231 case DEVPIN(0, 3):
232 case DEVPIN(0, 4):
233 return IRQ_IXDP2351_SPCI_DB_0;
234 case DEVPIN(1, 1): /* DB#1 */
235 case DEVPIN(1, 2):
236 case DEVPIN(1, 3):
237 case DEVPIN(1, 4):
238 return IRQ_IXDP2351_SPCI_DB_1;
239 case DEVPIN(2, 1): /* FIC1 */
240 case DEVPIN(2, 2):
241 case DEVPIN(2, 3):
242 case DEVPIN(2, 4):
243 case DEVPIN(3, 1): /* FIC2 */
244 case DEVPIN(3, 2):
245 case DEVPIN(3, 3):
246 case DEVPIN(3, 4):
247 return IRQ_IXDP2351_SPCI_FIC;
248 }
249 } else {
250 /* Device is located indirectly after second bridge */
251 /* Not supported now */
252 return -1;
253 }
254 break;
255 }
256
257 return -1;
258}
259
260struct hw_pci ixdp2351_pci __initdata = {
261 .nr_controllers = 1,
262 .preinit = ixp23xx_pci_preinit,
263 .setup = ixp23xx_pci_setup,
264 .scan = ixp23xx_pci_scan_bus,
265 .map_irq = ixdp2351_map_irq,
266};
267
268int __init ixdp2351_pci_init(void)
269{
270 if (machine_is_ixdp2351())
271 pci_common_init(&ixdp2351_pci);
272
273 return 0;
274}
275
276subsys_initcall(ixdp2351_pci_init);
277
278/*
279 * IXDP2351 Static Mapped I/O
280 */
281static struct map_desc ixdp2351_io_desc[] __initdata = {
282 {
283 .virtual = IXDP2351_NP_VIRT_BASE,
284 .pfn = __phys_to_pfn((u64)IXDP2351_NP_PHYS_BASE),
285 .length = IXDP2351_NP_PHYS_SIZE,
286 .type = MT_DEVICE
287 }, {
288 .virtual = IXDP2351_BB_BASE_VIRT,
289 .pfn = __phys_to_pfn((u64)IXDP2351_BB_BASE_PHYS),
290 .length = IXDP2351_BB_SIZE,
291 .type = MT_DEVICE
292 }
293};
294
295static void __init ixdp2351_map_io(void)
296{
297 ixp23xx_map_io();
298 iotable_init(ixdp2351_io_desc, ARRAY_SIZE(ixdp2351_io_desc));
299}
300
301static void __init ixdp2351_init(void)
302{
303 physmap_configure(0x90000000, 0x04000000, 1, NULL);
304
305 /*
306 * Mark flash as writeable
307 */
308 IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE;
309 IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE;
310 IXP23XX_EXP_CS0[2] |= IXP23XX_FLASH_WRITABLE;
311 IXP23XX_EXP_CS0[3] |= IXP23XX_FLASH_WRITABLE;
312
313 ixp23xx_sys_init();
314}
315
316MACHINE_START(IXDP2351, "Intel IXDP2351 Development Platform")
317 /* Maintainer: MontaVista Software, Inc. */
318 .phys_io = IXP23XX_PERIPHERAL_PHYS,
319 .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
320 .map_io = ixdp2351_map_io,
321 .init_irq = ixdp2351_init_irq,
322 .timer = &ixp23xx_timer,
323 .boot_params = 0x00000100,
324 .init_machine = ixdp2351_init,
325MACHINE_END
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c
new file mode 100644
index 000000000000..5330ad78c1bb
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/pci.c
@@ -0,0 +1,275 @@
1/*
2 * arch/arm/mach-ixp23xx/pci.c
3 *
4 * PCI routines for IXP23XX based systems
5 *
6 * Copyright (c) 2005 MontaVista Software, Inc.
7 *
8 * based on original code:
9 *
10 * Author: Naeem Afzal <naeem.m.afzal@intel.com>
11 * Copyright 2002-2005 Intel Corp.
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 */
18
19#include <linux/config.h>
20#include <linux/sched.h>
21#include <linux/kernel.h>
22#include <linux/pci.h>
23#include <linux/interrupt.h>
24#include <linux/mm.h>
25#include <linux/init.h>
26#include <linux/ioport.h>
27#include <linux/slab.h>
28#include <linux/delay.h>
29
30#include <asm/io.h>
31#include <asm/irq.h>
32#include <asm/sizes.h>
33#include <asm/system.h>
34#include <asm/mach/pci.h>
35#include <asm/mach-types.h>
36#include <asm/hardware.h>
37
38extern int (*external_fault) (unsigned long, struct pt_regs *);
39
40static int pci_master_aborts = 0;
41
42#ifdef DEBUG
43#define DBG(x...) printk(x)
44#else
45#define DBG(x...)
46#endif
47
48int clear_master_aborts(void);
49
50static u32
51*ixp23xx_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where)
52{
53 u32 *paddress;
54
55 /*
56 * Must be dword aligned
57 */
58 where &= ~3;
59
60 /*
61 * For top bus, generate type 0, else type 1
62 */
63 if (!bus_nr) {
64 if (PCI_SLOT(devfn) >= 8)
65 return 0;
66
67 paddress = (u32 *) (IXP23XX_PCI_CFG0_VIRT
68 | (1 << (PCI_SLOT(devfn) + 16))
69 | (PCI_FUNC(devfn) << 8) | where);
70 } else {
71 paddress = (u32 *) (IXP23XX_PCI_CFG1_VIRT
72 | (bus_nr << 16)
73 | (PCI_SLOT(devfn) << 11)
74 | (PCI_FUNC(devfn) << 8) | where);
75 }
76
77 return paddress;
78}
79
80/*
81 * Mask table, bits to mask for quantity of size 1, 2 or 4 bytes.
82 * 0 and 3 are not valid indexes...
83 */
84static u32 bytemask[] = {
85 /*0*/ 0,
86 /*1*/ 0xff,
87 /*2*/ 0xffff,
88 /*3*/ 0,
89 /*4*/ 0xffffffff,
90};
91
92static int ixp23xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
93 int where, int size, u32 *value)
94{
95 u32 n;
96 u32 *addr;
97
98 n = where % 4;
99
100 DBG("In config_read(%d) %d from dev %d:%d:%d\n", size, where,
101 bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
102
103 addr = ixp23xx_pci_config_addr(bus->number, devfn, where);
104 if (!addr)
105 return PCIBIOS_DEVICE_NOT_FOUND;
106
107 pci_master_aborts = 0;
108 *value = (*addr >> (8*n)) & bytemask[size];
109 if (pci_master_aborts) {
110 pci_master_aborts = 0;
111 *value = 0xffffffff;
112 return PCIBIOS_DEVICE_NOT_FOUND;
113 }
114
115 return PCIBIOS_SUCCESSFUL;
116}
117
118/*
119 * We don't do error checking on the address for writes.
120 * It's assumed that the user checked for the device existing first
121 * by doing a read first.
122 */
123static int ixp23xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
124 int where, int size, u32 value)
125{
126 u32 mask;
127 u32 *addr;
128 u32 temp;
129
130 mask = ~(bytemask[size] << ((where % 0x4) * 8));
131 addr = ixp23xx_pci_config_addr(bus->number, devfn, where);
132 if (!addr)
133 return PCIBIOS_DEVICE_NOT_FOUND;
134 temp = (u32) (value) << ((where % 0x4) * 8);
135 *addr = (*addr & mask) | temp;
136
137 clear_master_aborts();
138
139 return PCIBIOS_SUCCESSFUL;
140}
141
142struct pci_ops ixp23xx_pci_ops = {
143 .read = ixp23xx_pci_read_config,
144 .write = ixp23xx_pci_write_config,
145};
146
147struct pci_bus *ixp23xx_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
148{
149 return pci_scan_bus(sysdata->busnr, &ixp23xx_pci_ops, sysdata);
150}
151
152int ixp23xx_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
153{
154 volatile unsigned long temp;
155 unsigned long flags;
156
157 pci_master_aborts = 1;
158
159 local_irq_save(flags);
160 temp = *IXP23XX_PCI_CONTROL;
161
162 /*
163 * master abort and cmd tgt err
164 */
165 if (temp & ((1 << 8) | (1 << 5)))
166 *IXP23XX_PCI_CONTROL = temp;
167
168 temp = *IXP23XX_PCI_CMDSTAT;
169
170 if (temp & (1 << 29))
171 *IXP23XX_PCI_CMDSTAT = temp;
172 local_irq_restore(flags);
173
174 /*
175 * If it was an imprecise abort, then we need to correct the
176 * return address to be _after_ the instruction.
177 */
178 if (fsr & (1 << 10))
179 regs->ARM_pc += 4;
180
181 return 0;
182}
183
184int clear_master_aborts(void)
185{
186 volatile u32 temp;
187
188 temp = *IXP23XX_PCI_CONTROL;
189
190 /*
191 * master abort and cmd tgt err
192 */
193 if (temp & ((1 << 8) | (1 << 5)))
194 *IXP23XX_PCI_CONTROL = temp;
195
196 temp = *IXP23XX_PCI_CMDSTAT;
197
198 if (temp & (1 << 29))
199 *IXP23XX_PCI_CMDSTAT = temp;
200
201 return 0;
202}
203
204void __init ixp23xx_pci_preinit(void)
205{
206#ifdef __ARMEB__
207 *IXP23XX_PCI_CONTROL |= 0x20000; /* set I/O swapping */
208#endif
209 /*
210 * ADDR_31 needs to be clear for PCI memory access to CPP memory
211 */
212 *IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_ADDR_31;
213 *IXP23XX_CPP2XSI_CURR_XFER_REG3 |= IXP23XX_CPP2XSI_PSH_OFF;
214
215 /*
216 * Select correct memory for PCI inbound transactions
217 */
218 if (ixp23xx_cpp_boot()) {
219 *IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1);
220 } else {
221 *IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1);
222 }
223
224 hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS,
225 "PCI config cycle to non-existent device");
226
227 *IXP23XX_PCI_ADDR_EXT = 0x0000e000;
228}
229
230/*
231 * Prevent PCI layer from seeing the inbound host-bridge resources
232 */
233static void __devinit pci_fixup_ixp23xx(struct pci_dev *dev)
234{
235 int i;
236
237 dev->class &= 0xff;
238 dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
239 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
240 dev->resource[i].start = 0;
241 dev->resource[i].end = 0;
242 dev->resource[i].flags = 0;
243 }
244}
245DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9002, pci_fixup_ixp23xx);
246
247/*
248 * IXP2300 systems often have large resource requirements, so we just
249 * use our own resource space.
250 */
251static struct resource ixp23xx_pci_mem_space = {
252 .start = IXP23XX_PCI_MEM_START,
253 .end = IXP23XX_PCI_MEM_START + IXP23XX_PCI_MEM_SIZE - 1,
254 .flags = IORESOURCE_MEM,
255 .name = "PCI Mem Space"
256};
257
258static struct resource ixp23xx_pci_io_space = {
259 .start = 0x00000100,
260 .end = 0x01ffffff,
261 .flags = IORESOURCE_IO,
262 .name = "PCI I/O Space"
263};
264
265int ixp23xx_pci_setup(int nr, struct pci_sys_data *sys)
266{
267 if (nr >= 1)
268 return 0;
269
270 sys->resource[0] = &ixp23xx_pci_io_space;
271 sys->resource[1] = &ixp23xx_pci_mem_space;
272 sys->resource[2] = NULL;
273
274 return 1;
275}
diff --git a/arch/arm/mach-ixp23xx/roadrunner.c b/arch/arm/mach-ixp23xx/roadrunner.c
new file mode 100644
index 000000000000..43c14e740794
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/roadrunner.c
@@ -0,0 +1,164 @@
1/*
2 * arch/arm/mach-ixp23xx/roadrunner.c
3 *
4 * RoadRunner board-specific routines
5 *
6 * Author: Deepak Saxena <dsaxena@plexity.net>
7 *
8 * Copyright 2005 (c) MontaVista Software, Inc.
9 *
10 * Based on 2.4 code Copyright 2005 (c) ADI Engineering Corporation
11 *
12 * This file is licensed under the terms of the GNU General Public
13 * License version 2. This program is licensed "as is" without any
14 * warranty of any kind, whether express or implied.
15 */
16
17#include <linux/config.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/spinlock.h>
21#include <linux/sched.h>
22#include <linux/interrupt.h>
23#include <linux/serial.h>
24#include <linux/tty.h>
25#include <linux/bitops.h>
26#include <linux/ioport.h>
27#include <linux/serial.h>
28#include <linux/serial_8250.h>
29#include <linux/serial_core.h>
30#include <linux/device.h>
31#include <linux/mm.h>
32#include <linux/pci.h>
33#include <linux/mtd/physmap.h>
34
35#include <asm/types.h>
36#include <asm/setup.h>
37#include <asm/memory.h>
38#include <asm/hardware.h>
39#include <asm/mach-types.h>
40#include <asm/irq.h>
41#include <asm/system.h>
42#include <asm/tlbflush.h>
43#include <asm/pgtable.h>
44
45#include <asm/mach/map.h>
46#include <asm/mach/irq.h>
47#include <asm/mach/arch.h>
48#include <asm/mach/irq.h>
49#include <asm/mach/pci.h>
50
51/*
52 * Interrupt mapping
53 */
54#define INTA IRQ_ROADRUNNER_PCI_INTA
55#define INTB IRQ_ROADRUNNER_PCI_INTB
56#define INTC IRQ_ROADRUNNER_PCI_INTC
57#define INTD IRQ_ROADRUNNER_PCI_INTD
58
59#define INTC_PIN IXP23XX_GPIO_PIN_11
60#define INTD_PIN IXP23XX_GPIO_PIN_12
61
62static int __init roadrunner_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
63{
64 static int pci_card_slot_irq[] = {INTB, INTC, INTD, INTA};
65 static int pmc_card_slot_irq[] = {INTA, INTB, INTC, INTD};
66 static int usb_irq[] = {INTB, INTC, INTD, -1};
67 static int mini_pci_1_irq[] = {INTB, INTC, -1, -1};
68 static int mini_pci_2_irq[] = {INTC, INTD, -1, -1};
69
70 switch(dev->bus->number) {
71 case 0:
72 switch(dev->devfn) {
73 case 0x0: // PCI-PCI bridge
74 break;
75 case 0x8: // PCI Card Slot
76 return pci_card_slot_irq[pin - 1];
77 case 0x10: // PMC Slot
78 return pmc_card_slot_irq[pin - 1];
79 case 0x18: // PMC Slot Secondary Agent
80 break;
81 case 0x20: // IXP Processor
82 break;
83 default:
84 return NO_IRQ;
85 }
86 break;
87
88 case 1:
89 switch(dev->devfn) {
90 case 0x0: // IDE Controller
91 return (pin == 1) ? INTC : -1;
92 case 0x8: // USB fun 0
93 case 0x9: // USB fun 1
94 case 0xa: // USB fun 2
95 return usb_irq[pin - 1];
96 case 0x10: // Mini PCI 1
97 return mini_pci_1_irq[pin-1];
98 case 0x18: // Mini PCI 2
99 return mini_pci_2_irq[pin-1];
100 case 0x20: // MEM slot
101 return (pin == 1) ? INTA : -1;
102 default:
103 return NO_IRQ;
104 }
105 break;
106
107 default:
108 return NO_IRQ;
109 }
110
111 return NO_IRQ;
112}
113
114static void roadrunner_pci_preinit(void)
115{
116 set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQT_LOW);
117 set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQT_LOW);
118
119 ixp23xx_pci_preinit();
120}
121
122static struct hw_pci roadrunner_pci __initdata = {
123 .nr_controllers = 1,
124 .preinit = roadrunner_pci_preinit,
125 .setup = ixp23xx_pci_setup,
126 .scan = ixp23xx_pci_scan_bus,
127 .map_irq = roadrunner_map_irq,
128};
129
130static int __init roadrunner_pci_init(void)
131{
132 if (machine_is_roadrunner())
133 pci_common_init(&roadrunner_pci);
134
135 return 0;
136};
137
138subsys_initcall(roadrunner_pci_init);
139
140static void __init roadrunner_init(void)
141{
142 physmap_configure(0x90000000, 0x04000000, 2, NULL);
143
144 /*
145 * Mark flash as writeable
146 */
147 IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE;
148 IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE;
149 IXP23XX_EXP_CS0[2] |= IXP23XX_FLASH_WRITABLE;
150 IXP23XX_EXP_CS0[3] |= IXP23XX_FLASH_WRITABLE;
151
152 ixp23xx_sys_init();
153}
154
155MACHINE_START(ROADRUNNER, "ADI Engineering RoadRunner Development Platform")
156 /* Maintainer: Deepak Saxena */
157 .phys_io = IXP23XX_PERIPHERAL_PHYS,
158 .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
159 .map_io = ixp23xx_map_io,
160 .init_irq = ixp23xx_init_irq,
161 .timer = &ixp23xx_timer,
162 .boot_params = 0x00000100,
163 .init_machine = roadrunner_init,
164MACHINE_END