Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/arch/arm/mach-ixp2000/Kconfig b/arch/arm/mach-ixp2000/Kconfig
new file mode 100644
index 0000000..9361e05
--- /dev/null
+++ b/arch/arm/mach-ixp2000/Kconfig
@@ -0,0 +1,59 @@
+
+if ARCH_IXP2000
+
+config ARCH_SUPPORTS_BIG_ENDIAN
+	bool
+	default y
+
+menu "Intel IXP2400/2800 Implementation Options"
+
+comment "IXP2400/2800 Platforms"
+
+config ARCH_ENP2611
+	bool "Support Radisys ENP-2611"
+	help
+	  Say 'Y' here if you want your kernel to support the Radisys
+	  ENP2611 PCI network processing card. For more information on
+	  this card, see <file:Documentation/arm/ENP2611>.
+
+config ARCH_IXDP2400
+	bool "Support Intel IXDP2400"
+	help
+	  Say 'Y' here if you want your kernel to support the Intel
+	  IXDP2400 reference platform. For more information on
+	  this platform, see <file:Documentation/arm/IXP2000>.
+
+config ARCH_IXDP2800
+	bool "Support Intel IXDP2800"
+	help
+	  Say 'Y' here if you want your kernel to support the Intel
+	  IXDP2800 reference platform. For more information on
+	  this platform, see <file:Documentation/arm/IXP2000>.
+
+config ARCH_IXDP2X00
+	bool
+	depends on ARCH_IXDP2400 || ARCH_IXDP2800
+	default y	
+
+config ARCH_IXDP2401
+	bool "Support Intel IXDP2401"
+	help
+	  Say 'Y' here if you want your kernel to support the Intel
+	  IXDP2401 reference platform. For more information on
+	  this platform, see <file:Documentation/arm/IXP2000>.
+
+config ARCH_IXDP2801
+	bool "Support Intel IXDP2801"
+	help
+	  Say 'Y' here if you want your kernel to support the Intel
+	  IXDP2801 reference platform. For more information on
+	  this platform, see <file:Documentation/arm/IXP2000>.
+
+config ARCH_IXDP2X01
+	bool
+	depends on ARCH_IXDP2401 || ARCH_IXDP2801
+	default y	
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-ixp2000/Makefile b/arch/arm/mach-ixp2000/Makefile
new file mode 100644
index 0000000..1e6139d
--- /dev/null
+++ b/arch/arm/mach-ixp2000/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for the linux kernel.
+#
+obj-y			:= core.o pci.o
+obj-m			:=
+obj-n			:=
+obj-			:=
+
+obj-$(CONFIG_ARCH_ENP2611)	+= enp2611.o
+obj-$(CONFIG_ARCH_IXDP2400)	+= ixdp2400.o
+obj-$(CONFIG_ARCH_IXDP2800)	+= ixdp2800.o
+obj-$(CONFIG_ARCH_IXDP2X00)	+= ixdp2x00.o
+obj-$(CONFIG_ARCH_IXDP2X01)	+= ixdp2x01.o
+
diff --git a/arch/arm/mach-ixp2000/Makefile.boot b/arch/arm/mach-ixp2000/Makefile.boot
new file mode 100644
index 0000000..d84c580
--- /dev/null
+++ b/arch/arm/mach-ixp2000/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0x00008000
+params_phys-y	:= 0x00000100
+
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
new file mode 100644
index 0000000..4f3c3d5
--- /dev/null
+++ b/arch/arm/mach-ixp2000/core.c
@@ -0,0 +1,390 @@
+/*
+ * arch/arm/mach-ixp2000/common.c
+ *
+ * Common routines used by all IXP2400/2800 based platforms.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2004 (C) MontaVista Software, Inc. 
+ *
+ * Based on work Copyright (C) 2002-2003 Intel Corporation
+ * 
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any 
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/bitops.h>
+#include <linux/serial_core.h>
+#include <linux/mm.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+
+static DEFINE_SPINLOCK(ixp2000_slowport_lock);
+static unsigned long ixp2000_slowport_irq_flags;
+
+/*************************************************************************
+ * Slowport access routines
+ *************************************************************************/
+void ixp2000_acquire_slowport(struct slowport_cfg *new_cfg, struct slowport_cfg *old_cfg)
+{
+
+	spin_lock_irqsave(&ixp2000_slowport_lock, ixp2000_slowport_irq_flags);
+
+	old_cfg->CCR = *IXP2000_SLOWPORT_CCR;
+	old_cfg->WTC = *IXP2000_SLOWPORT_WTC2;
+	old_cfg->RTC = *IXP2000_SLOWPORT_RTC2;
+	old_cfg->PCR = *IXP2000_SLOWPORT_PCR;
+	old_cfg->ADC = *IXP2000_SLOWPORT_ADC;
+
+	ixp2000_reg_write(IXP2000_SLOWPORT_CCR, new_cfg->CCR);
+	ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, new_cfg->WTC);
+	ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, new_cfg->RTC);
+	ixp2000_reg_write(IXP2000_SLOWPORT_PCR, new_cfg->PCR);
+	ixp2000_reg_write(IXP2000_SLOWPORT_ADC, new_cfg->ADC);
+}
+
+void ixp2000_release_slowport(struct slowport_cfg *old_cfg)
+{
+	ixp2000_reg_write(IXP2000_SLOWPORT_CCR, old_cfg->CCR);
+	ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, old_cfg->WTC);
+	ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, old_cfg->RTC);
+	ixp2000_reg_write(IXP2000_SLOWPORT_PCR, old_cfg->PCR);
+	ixp2000_reg_write(IXP2000_SLOWPORT_ADC, old_cfg->ADC);
+
+	spin_unlock_irqrestore(&ixp2000_slowport_lock, 
+					ixp2000_slowport_irq_flags);
+}
+
+/*************************************************************************
+ * Chip specific mappings shared by all IXP2000 systems
+ *************************************************************************/
+static struct map_desc ixp2000_io_desc[] __initdata = {
+	{
+		.virtual	= IXP2000_CAP_VIRT_BASE,
+		.physical	= IXP2000_CAP_PHYS_BASE,
+		.length		= IXP2000_CAP_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_INTCTL_VIRT_BASE,
+		.physical	= IXP2000_INTCTL_PHYS_BASE,
+		.length		= IXP2000_INTCTL_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_PCI_CREG_VIRT_BASE,
+		.physical	= IXP2000_PCI_CREG_PHYS_BASE,
+		.length		= IXP2000_PCI_CREG_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_PCI_CSR_VIRT_BASE,
+		.physical	= IXP2000_PCI_CSR_PHYS_BASE,
+		.length		= IXP2000_PCI_CSR_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_PCI_IO_VIRT_BASE,
+		.physical	= IXP2000_PCI_IO_PHYS_BASE,
+		.length		= IXP2000_PCI_IO_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_PCI_CFG0_VIRT_BASE,
+		.physical	= IXP2000_PCI_CFG0_PHYS_BASE,
+		.length		= IXP2000_PCI_CFG0_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_PCI_CFG1_VIRT_BASE,
+		.physical	= IXP2000_PCI_CFG1_PHYS_BASE,
+		.length		= IXP2000_PCI_CFG1_SIZE,
+		.type		= MT_DEVICE
+	}
+};
+
+static struct uart_port ixp2000_serial_port = {
+	.membase	= (char *)(IXP2000_UART_VIRT_BASE + 3),
+	.mapbase	= IXP2000_UART_PHYS_BASE + 3,
+	.irq		= IRQ_IXP2000_UART,
+	.flags		= UPF_SKIP_TEST,
+	.iotype		= UPIO_MEM,
+	.regshift	= 2,
+	.uartclk	= 50000000,
+	.line		= 0,
+	.type		= PORT_XSCALE,
+	.fifosize	= 16
+};
+
+void __init ixp2000_map_io(void)
+{
+	extern unsigned int processor_id;
+
+	/*
+	 * On IXP2400 CPUs we need to use MT_IXP2000_DEVICE for
+	 * tweaking the PMDs so XCB=101. On IXP2800s we use the normal
+	 * PMD flags.
+	 */
+	if ((processor_id & 0xfffffff0) == 0x69054190) {
+		int i;
+
+		printk(KERN_INFO "Enabling IXP2400 erratum #66 workaround\n");
+
+		for(i=0;i<ARRAY_SIZE(ixp2000_io_desc);i++)
+			ixp2000_io_desc[i].type = MT_IXP2000_DEVICE;
+	}
+
+	iotable_init(ixp2000_io_desc, ARRAY_SIZE(ixp2000_io_desc));
+	early_serial_setup(&ixp2000_serial_port);
+
+	/* Set slowport to 8-bit mode.  */
+	ixp2000_reg_write(IXP2000_SLOWPORT_FRM, 1);
+}
+
+/*************************************************************************
+ * Timer-tick functions for IXP2000
+ *************************************************************************/
+static unsigned ticks_per_jiffy;
+static unsigned ticks_per_usec;
+static unsigned next_jiffy_time;
+
+unsigned long ixp2000_gettimeoffset (void)
+{
+ 	unsigned long offset;
+
+	offset = next_jiffy_time - *IXP2000_T4_CSR;
+
+	return offset / ticks_per_usec;
+}
+
+static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	write_seqlock(&xtime_lock);
+
+	/* clear timer 1 */
+	ixp2000_reg_write(IXP2000_T1_CLR, 1);
+	
+	while ((next_jiffy_time - *IXP2000_T4_CSR) > ticks_per_jiffy) {
+		timer_tick(regs);
+		next_jiffy_time -= ticks_per_jiffy;
+	}
+
+	write_sequnlock(&xtime_lock);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction ixp2000_timer_irq = {
+	.name		= "IXP2000 Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= ixp2000_timer_interrupt
+};
+
+void __init ixp2000_init_time(unsigned long tick_rate)
+{
+	ixp2000_reg_write(IXP2000_T1_CLR, 0);
+	ixp2000_reg_write(IXP2000_T4_CLR, 0);
+
+	ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
+	ticks_per_usec = tick_rate / 1000000;
+
+	ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1);
+	ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));
+
+	/*
+	 * We use T4 as a monotonic counter to track missed jiffies
+	 */
+	ixp2000_reg_write(IXP2000_T4_CLD, -1);
+	ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
+ 	next_jiffy_time = 0xffffffff;
+
+	/* register for interrupt */
+	setup_irq(IRQ_IXP2000_TIMER1, &ixp2000_timer_irq);
+}
+
+/*************************************************************************
+ * GPIO helpers
+ *************************************************************************/
+static unsigned long GPIO_IRQ_rising_edge;
+static unsigned long GPIO_IRQ_falling_edge;
+static unsigned long GPIO_IRQ_level_low;
+static unsigned long GPIO_IRQ_level_high;
+
+void gpio_line_config(int line, int style)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	if(style == GPIO_OUT) {
+		/* if it's an output, it ain't an interrupt anymore */
+		ixp2000_reg_write(IXP2000_GPIO_PDSR, (1 << line));
+		GPIO_IRQ_falling_edge &= ~(1 << line);
+		GPIO_IRQ_rising_edge &= ~(1 << line);
+		GPIO_IRQ_level_low &= ~(1 << line);
+		GPIO_IRQ_level_high &= ~(1 << line);
+		ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge);
+		ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge);
+		ixp2000_reg_write(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);
+		ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low);
+		irq_desc[line+IRQ_IXP2000_GPIO0].valid = 0;
+	} else if(style == GPIO_IN) {
+		ixp2000_reg_write(IXP2000_GPIO_PDCR, (1 << line));
+	}
+		
+	local_irq_restore(flags);
+}	
+
+
+/*************************************************************************
+ * IRQ handling IXP2000
+ *************************************************************************/
+static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{                               
+	int i;
+	unsigned long status = *IXP2000_GPIO_INST;
+		   
+	for (i = 0; i <= 7; i++) {
+		if (status & (1<<i)) {
+			desc = irq_desc + i + IRQ_IXP2000_GPIO0;
+			desc->handle(i + IRQ_IXP2000_GPIO0, desc, regs);
+		}
+	}
+}
+
+static void ixp2000_GPIO_irq_mask_ack(unsigned int irq)
+{
+	ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+	ixp2000_reg_write(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0)));
+}
+
+static void ixp2000_GPIO_irq_mask(unsigned int irq)
+{
+	ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+}
+
+static void ixp2000_GPIO_irq_unmask(unsigned int irq)
+{
+	ixp2000_reg_write(IXP2000_GPIO_INSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+}
+
+static struct irqchip ixp2000_GPIO_irq_chip = {
+	.ack	= ixp2000_GPIO_irq_mask_ack,
+	.mask	= ixp2000_GPIO_irq_mask,
+	.unmask	= ixp2000_GPIO_irq_unmask
+};
+
+static void ixp2000_pci_irq_mask(unsigned int irq)
+{
+	unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;
+	if (irq == IRQ_IXP2000_PCIA)
+		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 26)));
+	else if (irq == IRQ_IXP2000_PCIB)
+		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 27)));
+}
+
+static void ixp2000_pci_irq_unmask(unsigned int irq)
+{
+	unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;
+	if (irq == IRQ_IXP2000_PCIA)
+		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 26)));
+	else if (irq == IRQ_IXP2000_PCIB)
+		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 27)));
+}
+
+static struct irqchip ixp2000_pci_irq_chip = {
+	.ack	= ixp2000_pci_irq_mask,
+	.mask	= ixp2000_pci_irq_mask,
+	.unmask	= ixp2000_pci_irq_unmask
+};
+
+static void ixp2000_irq_mask(unsigned int irq)
+{
+	ixp2000_reg_write(IXP2000_IRQ_ENABLE_CLR, (1 << irq));
+}
+
+static void ixp2000_irq_unmask(unsigned int irq)
+{
+	ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET,  (1 << irq));
+}
+
+static struct irqchip ixp2000_irq_chip = {
+	.ack	= ixp2000_irq_mask,
+	.mask	= ixp2000_irq_mask,
+	.unmask	= ixp2000_irq_unmask
+};
+
+void __init ixp2000_init_irq(void)
+{
+	int irq;
+
+	/*
+	 * Mask all sources
+	 */
+	ixp2000_reg_write(IXP2000_IRQ_ENABLE_CLR, 0xffffffff);
+	ixp2000_reg_write(IXP2000_FIQ_ENABLE_CLR, 0xffffffff);
+
+	/* clear all GPIO edge/level detects */
+	ixp2000_reg_write(IXP2000_GPIO_REDR, 0);
+	ixp2000_reg_write(IXP2000_GPIO_FEDR, 0);
+	ixp2000_reg_write(IXP2000_GPIO_LSHR, 0);
+	ixp2000_reg_write(IXP2000_GPIO_LSLR, 0);
+	ixp2000_reg_write(IXP2000_GPIO_INCR, -1);
+
+	/* clear PCI interrupt sources */
+	ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, 0);
+
+	/*
+	 * Certain bits in the IRQ status register of the 
+	 * IXP2000 are reserved. Instead of trying to map
+	 * things non 1:1 from bit position to IRQ number,
+	 * we mark the reserved IRQs as invalid. This makes
+	 * our mask/unmask code much simpler.
+	 */
+	for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) {
+		if((1 << irq) & IXP2000_VALID_IRQ_MASK) {
+			set_irq_chip(irq, &ixp2000_irq_chip);
+			set_irq_handler(irq, do_level_IRQ);
+			set_irq_flags(irq, IRQF_VALID);
+		} else set_irq_flags(irq, 0);
+	}
+	
+	/*
+	 * GPIO IRQs are invalid until someone sets the interrupt mode
+	 * by calling gpio_line_set();
+	 */
+	for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) {
+		set_irq_chip(irq, &ixp2000_GPIO_irq_chip);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, 0);
+	}
+	set_irq_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler);
+
+	/*
+	 * Enable PCI irqs.  The actual PCI[AB] decoding is done in
+	 * entry-macro.S, so we don't need a chained handler for the
+	 * PCI interrupt source.
+	 */
+	ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << IRQ_IXP2000_PCI));
+	for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) {
+		set_irq_chip(irq, &ixp2000_pci_irq_chip);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+}
+
diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
new file mode 100644
index 0000000..04b38bc
--- /dev/null
+++ b/arch/arm/mach-ixp2000/enp2611.c
@@ -0,0 +1,220 @@
+/*
+ * arch/arm/mach-ixp2000/enp2611.c
+ *
+ * Radisys ENP-2611 support.
+ *
+ * Created 2004 by Lennert Buytenhek from the ixdp2x01 code.  The
+ * original version carries the following notices:
+ *
+ * Original Author: Andrzej Mialkowski <andrzej.mialkowski@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002-2003 Intel Corp.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+/*************************************************************************
+ * ENP-2611 timer tick configuration
+ *************************************************************************/
+static void __init enp2611_timer_init(void)
+{
+	ixp2000_init_time(50 * 1000 * 1000);
+}
+
+static struct sys_timer enp2611_timer = {
+	.init		= enp2611_timer_init,
+	.offset		= ixp2000_gettimeoffset,
+};
+
+
+/*************************************************************************
+ * ENP-2611 PCI
+ *************************************************************************/
+static int enp2611_pci_setup(int nr, struct pci_sys_data *sys)
+{
+	sys->mem_offset = 0xe0000000;
+	ixp2000_pci_setup(nr, sys);
+	return 1;
+}
+
+static void __init enp2611_pci_preinit(void)
+{
+	ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00100000);
+	ixp2000_pci_preinit();
+}
+
+static inline int enp2611_pci_valid_device(struct pci_bus *bus,
+						unsigned int devfn)
+{
+	/* The 82559 ethernet controller appears at both PCI:1:0:0 and
+	 * PCI:1:2:0, so let's pretend the second one isn't there.
+	 */
+	if (bus->number == 0x01 && devfn == 0x10)
+		return 0;
+
+	return 1;
+}
+
+static int enp2611_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+					int where, int size, u32 *value)
+{
+	if (enp2611_pci_valid_device(bus, devfn))
+		return ixp2000_pci_read_config(bus, devfn, where, size, value);
+
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static int enp2611_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+					int where, int size, u32 value)
+{
+	if (enp2611_pci_valid_device(bus, devfn))
+		return ixp2000_pci_write_config(bus, devfn, where, size, value);
+
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static struct pci_ops enp2611_pci_ops = {
+	.read   = enp2611_pci_read_config,
+	.write  = enp2611_pci_write_config
+};
+
+static struct pci_bus * __init enp2611_pci_scan_bus(int nr,
+						struct pci_sys_data *sys)
+{
+	return pci_scan_bus(sys->busnr, &enp2611_pci_ops, sys);
+}
+
+static int __init enp2611_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq;
+
+	if (dev->bus->number == 0 && PCI_SLOT(dev->devfn) == 0) {
+		/* IXP2400. */
+		irq = IRQ_IXP2000_PCIA;
+	} else if (dev->bus->number == 0 && PCI_SLOT(dev->devfn) == 1) {
+		/* 21555 non-transparent bridge.  */
+		irq = IRQ_IXP2000_PCIB;
+	} else if (dev->bus->number == 0 && PCI_SLOT(dev->devfn) == 4) {
+		/* PCI2050B transparent bridge.  */
+		irq = -1;
+	} else if (dev->bus->number == 1 && PCI_SLOT(dev->devfn) == 0) {
+		/* 82559 ethernet.  */
+		irq = IRQ_IXP2000_PCIA;
+	} else if (dev->bus->number == 1 && PCI_SLOT(dev->devfn) == 1) {
+		/* SPI-3 option board.  */
+		irq = IRQ_IXP2000_PCIB;
+	} else {
+		printk(KERN_ERR "enp2611_pci_map_irq() called for unknown "
+				"device PCI:%d:%d:%d\n", dev->bus->number,
+				PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+		irq = -1;
+	}
+
+	return irq;
+}
+
+struct hw_pci enp2611_pci __initdata = {
+	.nr_controllers	= 1,
+	.setup		= enp2611_pci_setup,
+	.preinit	= enp2611_pci_preinit,
+	.scan		= enp2611_pci_scan_bus,
+	.map_irq	= enp2611_pci_map_irq,
+};
+
+int __init enp2611_pci_init(void)
+{
+	if (machine_is_enp2611())
+		pci_common_init(&enp2611_pci);
+
+	return 0;
+}
+
+subsys_initcall(enp2611_pci_init);
+
+
+/*************************************************************************
+ * ENP-2611 Machine Intialization
+ *************************************************************************/
+static struct flash_platform_data enp2611_flash_platform_data = {
+	.map_name	= "cfi_probe",
+	.width		= 1,
+};
+
+static struct ixp2000_flash_data enp2611_flash_data = {
+	.platform_data	= &enp2611_flash_platform_data,
+	.nr_banks	= 1
+};
+
+static struct resource enp2611_flash_resource = {
+	.start		= 0xc4000000,
+	.end		= 0xc4000000 + 0x00ffffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device enp2611_flash = {
+	.name		= "IXP2000-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &enp2611_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &enp2611_flash_resource,
+};
+
+static struct platform_device *enp2611_devices[] __initdata = {
+	&enp2611_flash
+};
+
+static void __init enp2611_init_machine(void)
+{
+	platform_add_devices(enp2611_devices, ARRAY_SIZE(enp2611_devices));
+}
+
+
+MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
+	MAINTAINER("Lennert Buytenhek <buytenh@wantstofly.org>")
+	BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+	BOOT_PARAMS(0x00000100)
+	MAPIO(ixp2000_map_io)
+	INITIRQ(ixp2000_init_irq)
+	.timer		= &enp2611_timer,
+	INIT_MACHINE(enp2611_init_machine)
+MACHINE_END
+
+
diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c
new file mode 100644
index 0000000..df3ff26
--- /dev/null
+++ b/arch/arm/mach-ixp2000/ixdp2400.c
@@ -0,0 +1,179 @@
+/*
+ * arch/arm/mach-ixp2000/ixdp2400.c
+ *
+ * IXDP2400 platform support
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/arch.h>
+
+/*************************************************************************
+ * IXDP2400 timer tick
+ *************************************************************************/
+static void __init ixdp2400_timer_init(void)
+{
+	int numerator, denominator;
+	int denom_array[] = {2, 4, 8, 16, 1, 2, 4, 8};
+
+	numerator = (*(IXDP2400_CPLD_SYS_CLK_M) & 0xFF) *2;
+	denominator = denom_array[(*(IXDP2400_CPLD_SYS_CLK_N) & 0x7)];
+
+	ixp2000_init_time(((3125000 * numerator) / (denominator)) / 2);
+}
+
+static struct sys_timer ixdp2400_timer = {
+	.init		= ixdp2400_timer_init,
+	.offset		= ixp2000_gettimeoffset,
+};
+
+/*************************************************************************
+ * IXDP2400 PCI
+ *************************************************************************/
+void __init ixdp2400_pci_preinit(void)
+{
+	ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00100000);
+	ixp2000_pci_preinit();
+}
+
+int ixdp2400_pci_setup(int nr, struct pci_sys_data *sys)
+{
+	sys->mem_offset = 0xe0000000;
+
+	ixp2000_pci_setup(nr, sys);
+
+	return 1;
+}
+
+static int __init ixdp2400_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (ixdp2x00_master_npu()) {
+
+		/*
+		 * Root bus devices.  Slave NPU is only one with interrupt.
+		 * Everything else, we just return -1 b/c nothing else
+		 * on the root bus has interrupts.
+		 */
+		if(!dev->bus->self) {
+			if(dev->devfn == IXDP2X00_SLAVE_NPU_DEVFN )
+				return IRQ_IXDP2400_INGRESS_NPU;
+
+			return -1;
+		}
+
+		/*
+		 * Bridge behind the PMC slot.
+		 * NOTE: Only INTA from the PMC slot is routed. VERY BAD.
+		 */
+		if(dev->bus->self->devfn == IXDP2X00_PMC_DEVFN &&
+			dev->bus->parent->self->devfn == IXDP2X00_P2P_DEVFN &&
+			!dev->bus->parent->self->bus->parent)
+				  return IRQ_IXDP2400_PMC;
+
+		/*
+		 * Device behind the first bridge
+		 */
+		if(dev->bus->self->devfn == IXDP2X00_P2P_DEVFN) {
+			switch(dev->devfn) {
+				case IXDP2400_MASTER_ENET_DEVFN:	
+					return IRQ_IXDP2400_ENET;	
+			
+				case IXDP2400_MEDIA_DEVFN:
+					return IRQ_IXDP2400_MEDIA_PCI;
+
+				case IXDP2400_SWITCH_FABRIC_DEVFN:
+					return IRQ_IXDP2400_SF_PCI;
+
+				case IXDP2X00_PMC_DEVFN:
+					return IRQ_IXDP2400_PMC;
+			}
+		}
+
+		return -1;
+	} else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */
+}
+
+
+static void ixdp2400_pci_postinit(void)
+{
+	struct pci_dev *dev;
+
+	if (ixdp2x00_master_npu()) {
+		dev = pci_find_slot(1, IXDP2400_SLAVE_ENET_DEVFN);
+		pci_remove_bus_device(dev);
+	} else {
+		dev = pci_find_slot(1, IXDP2400_MASTER_ENET_DEVFN);
+		pci_remove_bus_device(dev);
+
+		ixdp2x00_slave_pci_postinit();
+	}
+}
+
+static struct hw_pci ixdp2400_pci __initdata = {
+	.nr_controllers	= 1,
+	.setup		= ixdp2400_pci_setup,
+	.preinit	= ixdp2400_pci_preinit,
+	.postinit	= ixdp2400_pci_postinit,
+	.scan		= ixp2000_pci_scan_bus,
+	.map_irq	= ixdp2400_pci_map_irq,
+};
+
+int __init ixdp2400_pci_init(void)
+{
+	if (machine_is_ixdp2400())
+		pci_common_init(&ixdp2400_pci);
+
+	return 0;
+}
+
+subsys_initcall(ixdp2400_pci_init);
+
+void ixdp2400_init_irq(void)
+{
+	ixdp2x00_init_irq(IXDP2400_CPLD_INT_STAT, IXDP2400_CPLD_INT_MASK, IXDP2400_NR_IRQS);
+}
+
+MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
+	MAINTAINER("MontaVista Software, Inc.")
+	BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+	BOOT_PARAMS(0x00000100)
+	MAPIO(ixdp2x00_map_io)
+	INITIRQ(ixdp2400_init_irq)
+	.timer		= &ixdp2400_timer,
+	INIT_MACHINE(ixdp2x00_init_machine)
+MACHINE_END
+
diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c
new file mode 100644
index 0000000..c4683aa
--- /dev/null
+++ b/arch/arm/mach-ixp2000/ixdp2800.c
@@ -0,0 +1,180 @@
+/*
+ * arch/arm/mach-ixp2000/ixdp2800.c
+ *
+ * IXDP2800 platform support
+ *
+ * Original Author: Jeffrey Daly <jeffrey.daly@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/arch.h>
+
+
+void ixdp2400_init_irq(void)
+{
+	ixdp2x00_init_irq(IXDP2800_CPLD_INT_STAT, IXDP2800_CPLD_INT_MASK, IXDP2400_NR_IRQS);
+}
+
+/*************************************************************************
+ * IXDP2800 timer tick
+ *************************************************************************/
+
+static void __init ixdp2800_timer_init(void)
+{
+	ixp2000_init_time(50000000);
+}
+
+static struct sys_timer ixdp2800_timer = {
+	.init		= ixdp2800_timer_init,
+	.offset		= ixp2000_gettimeoffset,
+};
+
+/*************************************************************************
+ * IXDP2800 PCI
+ *************************************************************************/
+void __init ixdp2800_pci_preinit(void)
+{
+	printk("ixdp2x00_pci_preinit called\n");
+
+	*IXP2000_PCI_ADDR_EXT =  0x0000e000;
+
+	*IXP2000_PCI_DRAM_BASE_ADDR_MASK = (0x40000000 - 1) & ~0xfffff;
+	*IXP2000_PCI_SRAM_BASE_ADDR_MASK = (0x2000000 - 1) & ~0x3ffff;
+
+	ixp2000_pci_preinit();
+}
+
+int ixdp2800_pci_setup(int nr, struct pci_sys_data *sys)
+{
+	sys->mem_offset = 0x00000000;
+
+	ixp2000_pci_setup(nr, sys);
+
+	return 1;
+}
+
+static int __init ixdp2800_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (ixdp2x00_master_npu()) {
+
+		/*
+		 * Root bus devices.  Slave NPU is only one with interrupt.
+		 * Everything else, we just return -1 which is invalid.
+		 */
+		if(!dev->bus->self) {
+			if(dev->devfn == IXDP2X00_SLAVE_NPU_DEVFN )
+				return IRQ_IXDP2800_INGRESS_NPU;
+
+			return -1;
+		}
+
+		/*
+		 * Bridge behind the PMC slot.
+		 */
+		if(dev->bus->self->devfn == IXDP2X00_PMC_DEVFN &&
+			dev->bus->parent->self->devfn == IXDP2X00_P2P_DEVFN &&
+			!dev->bus->parent->self->bus->parent)
+				  return IRQ_IXDP2800_PMC;
+
+		/*
+		 * Device behind the first bridge
+		 */
+		if(dev->bus->self->devfn == IXDP2X00_P2P_DEVFN) {
+			switch(dev->devfn) {
+				case IXDP2X00_PMC_DEVFN:
+					return IRQ_IXDP2800_PMC;	
+			
+				case IXDP2800_MASTER_ENET_DEVFN:
+					return IRQ_IXDP2800_EGRESS_ENET;
+
+				case IXDP2800_SWITCH_FABRIC_DEVFN:
+					return IRQ_IXDP2800_FABRIC;
+			}
+		}
+
+		return -1;
+	} else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */
+}
+
+static void ixdp2800_pci_postinit(void)
+{
+	struct pci_dev *dev;
+
+	if (ixdp2x00_master_npu()) {
+		dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN);
+		pci_remove_bus_device(dev);
+	} else {
+		dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN);
+		pci_remove_bus_device(dev);
+
+		ixdp2x00_slave_pci_postinit();
+	}
+}
+
+struct hw_pci ixdp2800_pci __initdata = {
+	.nr_controllers	= 1,
+	.setup		= ixdp2800_pci_setup,
+	.preinit	= ixdp2800_pci_preinit,
+	.postinit	= ixdp2800_pci_postinit,
+	.scan		= ixp2000_pci_scan_bus,
+	.map_irq	= ixdp2800_pci_map_irq,
+};
+
+int __init ixdp2800_pci_init(void)
+{
+	if (machine_is_ixdp2800())
+		pci_common_init(&ixdp2800_pci);
+
+	return 0;
+}
+
+subsys_initcall(ixdp2800_pci_init);
+
+void ixdp2800_init_irq(void)
+{
+	ixdp2x00_init_irq(IXDP2800_CPLD_INT_STAT, IXDP2800_CPLD_INT_MASK, IXDP2800_NR_IRQS);
+}
+
+MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")
+	MAINTAINER("MontaVista Software, Inc.")
+	BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+	BOOT_PARAMS(0x00000100)
+	MAPIO(ixdp2x00_map_io)
+	INITIRQ(ixdp2800_init_irq)
+	.timer		= &ixdp2800_timer,
+	INIT_MACHINE(ixdp2x00_init_machine)
+MACHINE_END
+
diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c
new file mode 100644
index 0000000..21c41fe
--- /dev/null
+++ b/arch/arm/mach-ixp2000/ixdp2x00.c
@@ -0,0 +1,304 @@
+/*
+ * arch/arm/mach-ixp2000/ixdp2x00.c
+ *
+ * Code common to IXDP2400 and IXDP2800 platforms.
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/arch.h>
+
+/*************************************************************************
+ * IXDP2x00 IRQ Initialization
+ *************************************************************************/
+static volatile unsigned long *board_irq_mask;
+static volatile unsigned long *board_irq_stat;
+static unsigned long board_irq_count;
+
+#ifdef CONFIG_ARCH_IXDP2400
+/*
+ * Slowport configuration for accessing CPLD registers on IXDP2x00
+ */
+static struct slowport_cfg slowport_cpld_cfg = {
+	.CCR =	SLOWPORT_CCR_DIV_2,
+	.WTC = 0x00000070,
+	.RTC = 0x00000070,
+	.PCR = SLOWPORT_MODE_FLASH,
+	.ADC = SLOWPORT_ADDR_WIDTH_24 | SLOWPORT_DATA_WIDTH_8
+};
+#endif
+
+static void ixdp2x00_irq_mask(unsigned int irq)
+{
+	unsigned long dummy;
+	static struct slowport_cfg old_cfg;
+
+	/*
+	 * This is ugly in common code but really don't know
+	 * of a better way to handle it. :(
+	 */
+#ifdef CONFIG_ARCH_IXDP2400
+	if (machine_is_ixdp2400())
+		ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
+#endif
+
+	dummy = *board_irq_mask;
+	dummy |=  IXP2000_BOARD_IRQ_MASK(irq);
+	ixp2000_reg_write(board_irq_mask, dummy);
+
+#ifdef CONFIG_ARCH_IXDP2400
+	if (machine_is_ixdp2400())
+		ixp2000_release_slowport(&old_cfg);
+#endif
+}
+
+static void ixdp2x00_irq_unmask(unsigned int irq)
+{
+	unsigned long dummy;
+	static struct slowport_cfg old_cfg;
+
+#ifdef CONFIG_ARCH_IXDP2400
+	if (machine_is_ixdp2400())
+		ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
+#endif
+
+	dummy = *board_irq_mask;
+	dummy &=  ~IXP2000_BOARD_IRQ_MASK(irq);
+	ixp2000_reg_write(board_irq_mask, dummy);
+
+	if (machine_is_ixdp2400()) 
+		ixp2000_release_slowport(&old_cfg);
+}
+
+static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+        volatile u32 ex_interrupt = 0;
+	static struct slowport_cfg old_cfg;
+	int i;
+
+	desc->chip->mask(irq);
+
+#ifdef CONFIG_ARCH_IXDP2400
+	if (machine_is_ixdp2400())
+		ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
+#endif
+        ex_interrupt = *board_irq_stat & 0xff;
+	if (machine_is_ixdp2400())
+		ixp2000_release_slowport(&old_cfg);
+
+	if(!ex_interrupt) {
+		printk(KERN_ERR "Spurious IXDP2x00 CPLD interrupt!\n");
+		return;
+	}
+
+	for(i = 0; i < board_irq_count; i++) {
+		if(ex_interrupt & (1 << i))  {
+			struct irqdesc *cpld_desc;
+			int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
+			cpld_desc = irq_desc + cpld_irq;
+			cpld_desc->handle(cpld_irq, cpld_desc, regs);
+		}
+	}
+
+	desc->chip->unmask(irq);
+}
+
+static struct irqchip ixdp2x00_cpld_irq_chip = {
+	.ack	= ixdp2x00_irq_mask,
+	.mask	= ixdp2x00_irq_mask,
+	.unmask	= ixdp2x00_irq_unmask
+};
+
+void ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long *mask_reg, unsigned long nr_irqs)
+{
+	unsigned int irq;
+
+	ixp2000_init_irq();
+	
+	if (!ixdp2x00_master_npu())
+		return;
+
+	board_irq_stat = stat_reg;
+	board_irq_mask = mask_reg;
+	board_irq_count = nr_irqs;
+
+	*board_irq_mask = 0xffffffff;
+
+	for(irq = IXP2000_BOARD_IRQ(0); irq < IXP2000_BOARD_IRQ(board_irq_count); irq++) {
+		set_irq_chip(irq, &ixdp2x00_cpld_irq_chip);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+
+	/* Hook into PCI interrupt */
+	set_irq_chained_handler(IRQ_IXP2000_PCIB, &ixdp2x00_irq_handler);
+}
+
+/*************************************************************************
+ * IXDP2x00 memory map
+ *************************************************************************/
+static struct map_desc ixdp2x00_io_desc __initdata = {
+	.virtual	= IXDP2X00_VIRT_CPLD_BASE, 
+	.physical	= IXDP2X00_PHYS_CPLD_BASE,
+	.length		= IXDP2X00_CPLD_SIZE,
+	.type		= MT_DEVICE
+};
+
+void __init ixdp2x00_map_io(void)
+{
+	ixp2000_map_io();	
+
+	iotable_init(&ixdp2x00_io_desc, 1);
+}
+
+/*************************************************************************
+ * IXDP2x00-common PCI init
+ *
+ * The IXDP2[48]00 has a horrid PCI bus layout. Basically the board 
+ * contains two NPUs (ingress and egress) connected over PCI,  both running 
+ * instances  of the kernel. So far so good. Peers on the PCI bus running 
+ * Linux is a common design in telecom systems. The problem is that instead 
+ * of all the devices being controlled by a single host, different
+ * devices are controlles by different NPUs on the same bus, leading to
+ * multiple hosts on the bus. The exact bus layout looks like:
+ *
+ *                   Bus 0
+ *    Master NPU <-------------------+-------------------> Slave NPU
+ *                                   |
+ *                                   |
+ *                                  P2P 
+ *                                   |
+ *
+ *                  Bus 1            |
+ *               <--+------+---------+---------+------+-->
+ *                  |      |         |         |      |
+ *                  |      |         |         |      |
+ *             ... Dev    PMC       Media     Eth0   Eth1 ...
+ *
+ * The master controlls all but Eth1, which is controlled by the
+ * slave. What this means is that the both the master and the slave
+ * have to scan the bus, but only one of them can enumerate the bus.
+ * In addition, after the bus is scanned, each kernel must remove
+ * the device(s) it does not control from the PCI dev list otherwise
+ * a driver on each NPU will try to manage it and we will have horrible
+ * conflicts. Oh..and the slave NPU needs to see the master NPU
+ * for Intel's drivers to work properly. Closed source drivers...
+ *
+ * The way we deal with this is fairly simple but ugly:
+ *
+ * 1) Let master scan and enumerate the bus completely.
+ * 2) Master deletes Eth1 from device list.
+ * 3) Slave scans bus and then deletes all but Eth1 (Eth0 on slave)
+ *    from device list.
+ * 4) Find HW designers and LART them.
+ *
+ * The boards also do not do normal PCI IRQ routing, or any sort of 
+ * sensical  swizzling, so we just need to check where on the  bus a
+ * device sits and figure out to which CPLD pin the interrupt is routed.
+ * See ixdp2[48]00.c files.
+ *
+ *************************************************************************/
+void ixdp2x00_slave_pci_postinit(void)
+{
+	struct pci_dev *dev;
+
+	/*
+	 * Remove PMC device is there is one
+	 */
+	if((dev = pci_find_slot(1, IXDP2X00_PMC_DEVFN)))
+		pci_remove_bus_device(dev);
+
+	dev = pci_find_slot(0, IXDP2X00_21555_DEVFN);
+	pci_remove_bus_device(dev);
+}
+
+/**************************************************************************
+ * IXDP2x00 Machine Setup
+ *************************************************************************/
+static struct flash_platform_data ixdp2x00_platform_data = {
+	.map_name	= "cfi_probe",
+	.width		= 1,
+};
+
+static struct ixp2000_flash_data ixdp2x00_flash_data = {
+	.platform_data	= &ixdp2x00_platform_data,
+	.nr_banks	= 1
+};
+
+static struct resource ixdp2x00_flash_resource = {
+	.start		= 0xc4000000,
+	.end		= 0xc4000000 + 0x00ffffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp2x00_flash = {
+	.name		= "IXP2000-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &ixdp2x00_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &ixdp2x00_flash_resource,
+};
+
+static struct ixp2000_i2c_pins ixdp2x00_i2c_gpio_pins = {
+	.sda_pin	= IXDP2X00_GPIO_SDA,
+	.scl_pin	= IXDP2X00_GPIO_SCL,
+};
+
+static struct platform_device ixdp2x00_i2c_controller = {
+	.name		= "IXP2000-I2C",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &ixdp2x00_i2c_gpio_pins,
+	},
+	.num_resources	= 0
+};
+
+static struct platform_device *ixdp2x00_devices[] __initdata = {
+	&ixdp2x00_flash,
+	&ixdp2x00_i2c_controller
+};
+
+void __init ixdp2x00_init_machine(void)
+{
+	gpio_line_set(IXDP2X00_GPIO_I2C_ENABLE, 1);
+	gpio_line_config(IXDP2X00_GPIO_I2C_ENABLE, GPIO_OUT);
+
+	platform_add_devices(ixdp2x00_devices, ARRAY_SIZE(ixdp2x00_devices));
+}
+
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
new file mode 100644
index 0000000..e94dace
--- /dev/null
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -0,0 +1,400 @@
+/*
+ * arch/arm/mach-ixp2000/ixdp2x01.c
+ *
+ * Code common to Intel IXDP2401 and IXDP2801 platforms
+ *
+ * Original Author: Andrzej Mialkowski <andrzej.mialkowski@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002-2003 Intel Corp.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+/*************************************************************************
+ * IXDP2x01 IRQ Handling
+ *************************************************************************/
+static void ixdp2x01_irq_mask(unsigned int irq)
+{
+	ixp2000_reg_write(IXDP2X01_INT_MASK_SET_REG,
+				IXP2000_BOARD_IRQ_MASK(irq));
+}
+
+static void ixdp2x01_irq_unmask(unsigned int irq)
+{
+	ixp2000_reg_write(IXDP2X01_INT_MASK_CLR_REG,
+				IXP2000_BOARD_IRQ_MASK(irq));
+}
+
+static u32 valid_irq_mask;
+
+static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+	u32 ex_interrupt;
+	int i;
+
+	desc->chip->mask(irq);
+
+	ex_interrupt = *IXDP2X01_INT_STAT_REG & valid_irq_mask;
+
+	if (!ex_interrupt) {
+		printk(KERN_ERR "Spurious IXDP2X01 CPLD interrupt!\n");
+		return;
+	}
+
+	for (i = 0; i < IXP2000_BOARD_IRQS; i++) {
+		if (ex_interrupt & (1 << i)) {
+			struct irqdesc *cpld_desc;
+			int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
+			cpld_desc = irq_desc + cpld_irq;
+			cpld_desc->handle(cpld_irq, cpld_desc, regs);
+		}
+	}
+
+	desc->chip->unmask(irq);
+}
+
+static struct irqchip ixdp2x01_irq_chip = {
+	.mask	= ixdp2x01_irq_mask,
+	.ack	= ixdp2x01_irq_mask,
+	.unmask	= ixdp2x01_irq_unmask
+};
+
+/*
+ * We only do anything if we are the master NPU on the board.
+ * The slave NPU only has the ethernet chip going directly to
+ * the PCIB interrupt input.
+ */
+void __init ixdp2x01_init_irq(void)
+{
+	int irq = 0;
+
+	/* initialize chip specific interrupts */
+	ixp2000_init_irq();
+
+	if (machine_is_ixdp2401())
+		valid_irq_mask = IXDP2401_VALID_IRQ_MASK;
+	else
+		valid_irq_mask = IXDP2801_VALID_IRQ_MASK;
+
+	/* Mask all interrupts from CPLD, disable simulation */
+	ixp2000_reg_write(IXDP2X01_INT_MASK_SET_REG, 0xffffffff);
+	ixp2000_reg_write(IXDP2X01_INT_SIM_REG, 0);
+
+	for (irq = NR_IXP2000_IRQS; irq < NR_IXDP2X01_IRQS; irq++) {
+		if (irq & valid_irq_mask) {
+			set_irq_chip(irq, &ixdp2x01_irq_chip);
+			set_irq_handler(irq, do_level_IRQ);
+			set_irq_flags(irq, IRQF_VALID);
+		} else {
+			set_irq_flags(irq, 0);
+		}
+	}
+
+	/* Hook into PCI interrupts */
+	set_irq_chained_handler(IRQ_IXP2000_PCIB, &ixdp2x01_irq_handler);
+}
+
+
+/*************************************************************************
+ * IXDP2x01 memory map and serial ports
+ *************************************************************************/
+static struct map_desc ixdp2x01_io_desc __initdata = {
+	.virtual	= IXDP2X01_VIRT_CPLD_BASE, 
+	.physical	= IXDP2X01_PHYS_CPLD_BASE,
+	.length		= IXDP2X01_CPLD_REGION_SIZE,
+	.type		= MT_DEVICE
+};
+
+static struct uart_port ixdp2x01_serial_ports[2] = {
+	{
+		.membase	= (char *)(IXDP2X01_UART1_VIRT_BASE),
+		.mapbase	= (unsigned long)IXDP2X01_UART1_PHYS_BASE,
+		.irq		= IRQ_IXDP2X01_UART1,
+		.flags		= UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM32,
+		.regshift	= 2,
+		.uartclk	= IXDP2X01_UART_CLK,
+		.line		= 1,
+		.type		= PORT_16550A,
+		.fifosize	= 16
+	}, {
+		.membase	= (char *)(IXDP2X01_UART2_VIRT_BASE),
+		.mapbase	= (unsigned long)IXDP2X01_UART2_PHYS_BASE,
+		.irq		= IRQ_IXDP2X01_UART2,
+		.flags		= UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM32,
+		.regshift	= 2,
+		.uartclk	= IXDP2X01_UART_CLK,
+		.line		= 2,
+		.type		= PORT_16550A,
+		.fifosize	= 16
+	}, 
+};
+
+static void __init ixdp2x01_map_io(void)
+{
+	ixp2000_map_io();	
+
+	iotable_init(&ixdp2x01_io_desc, 1);
+
+	early_serial_setup(&ixdp2x01_serial_ports[0]);
+	early_serial_setup(&ixdp2x01_serial_ports[1]);
+}
+
+
+/*************************************************************************
+ * IXDP2x01 timer tick configuration
+ *************************************************************************/
+static unsigned int ixdp2x01_clock;
+
+static int __init ixdp2x01_clock_setup(char *str)
+{
+	ixdp2x01_clock = simple_strtoul(str, NULL, 10);
+
+	return 1;
+}
+
+__setup("ixdp2x01_clock=", ixdp2x01_clock_setup);
+
+static void __init ixdp2x01_timer_init(void)
+{
+	if (!ixdp2x01_clock)
+		ixdp2x01_clock = 50000000;
+
+	ixp2000_init_time(ixdp2x01_clock);
+}
+
+static struct sys_timer ixdp2x01_timer = {
+	.init		= ixdp2x01_timer_init,
+	.offset		= ixp2000_gettimeoffset,
+};
+
+/*************************************************************************
+ * IXDP2x01 PCI
+ *************************************************************************/
+void __init ixdp2x01_pci_preinit(void)
+{
+	ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00000000);
+	ixp2000_pci_preinit();
+}
+
+#define DEVPIN(dev, pin) ((pin) | ((dev) << 3))
+
+static int __init ixdp2x01_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	u8 bus = dev->bus->number;
+	u32 devpin = DEVPIN(PCI_SLOT(dev->devfn), pin);
+	struct pci_bus *tmp_bus = dev->bus;
+
+	/* Primary bus, no interrupts here */
+	if (bus == 0) {
+		return -1;
+	}
+
+	/* Lookup first leaf in bus tree */
+	while ((tmp_bus->parent != NULL) && (tmp_bus->parent->parent != NULL)) {
+		tmp_bus = tmp_bus->parent;
+	}
+
+	/* Select between known bridges */
+	switch (tmp_bus->self->devfn | (tmp_bus->self->bus->number << 8)) {
+	/* Device is located after first MB bridge */
+	case 0x0008:
+		if (tmp_bus == dev->bus) {
+			/* Device is located directy after first MB bridge */
+			switch (devpin) {
+			case DEVPIN(1, 1):	/* Onboard 82546 ch 0 */
+				if (machine_is_ixdp2401())
+					return IRQ_IXDP2401_INTA_82546;
+				return -1;
+			case DEVPIN(1, 2):	/* Onboard 82546 ch 1 */
+				if (machine_is_ixdp2401())
+					return IRQ_IXDP2401_INTB_82546;
+				return -1;
+			case DEVPIN(0, 1):	/* PMC INTA# */
+				return IRQ_IXDP2X01_SPCI_PMC_INTA;
+			case DEVPIN(0, 2):	/* PMC INTB# */
+				return IRQ_IXDP2X01_SPCI_PMC_INTB;
+			case DEVPIN(0, 3):	/* PMC INTC# */
+				return IRQ_IXDP2X01_SPCI_PMC_INTC;
+			case DEVPIN(0, 4):	/* PMC INTD# */
+				return IRQ_IXDP2X01_SPCI_PMC_INTD;
+			}
+		}
+		break;
+	case 0x0010:
+		if (tmp_bus == dev->bus) {
+			/* Device is located directy after second MB bridge */
+			/* Secondary bus of second bridge */
+			switch (devpin) {
+			case DEVPIN(0, 1):	/* DB#0 */
+				return IRQ_IXDP2X01_SPCI_DB_0;
+			case DEVPIN(1, 1):	/* DB#1 */
+				return IRQ_IXDP2X01_SPCI_DB_1;
+			}
+		} else {
+			/* Device is located indirectly after second MB bridge */
+			/* Not supported now */
+		}
+		break;
+	}
+
+	return -1;
+}
+
+
+static int ixdp2x01_pci_setup(int nr, struct pci_sys_data *sys)
+{
+	sys->mem_offset = 0xe0000000;
+
+	if (machine_is_ixdp2801())
+		sys->mem_offset -= ((*IXP2000_PCI_ADDR_EXT & 0xE000) << 16);
+
+	return ixp2000_pci_setup(nr, sys);
+}
+
+struct hw_pci ixdp2x01_pci __initdata = {
+	.nr_controllers	= 1,
+	.setup		= ixdp2x01_pci_setup,
+	.preinit	= ixdp2x01_pci_preinit,
+	.scan		= ixp2000_pci_scan_bus,
+	.map_irq	= ixdp2x01_pci_map_irq,
+};
+
+int __init ixdp2x01_pci_init(void)
+{
+
+	pci_common_init(&ixdp2x01_pci);
+	return 0;
+}
+
+subsys_initcall(ixdp2x01_pci_init);
+
+/*************************************************************************
+ * IXDP2x01 Machine Intialization
+ *************************************************************************/
+static struct flash_platform_data ixdp2x01_flash_platform_data = {
+	.map_name	= "cfi_probe",
+	.width		= 1,
+};
+
+static unsigned long ixdp2x01_flash_bank_setup(unsigned long ofs)
+{
+	ixp2000_reg_write(IXDP2X01_CPLD_FLASH_REG,
+		((ofs >> IXDP2X01_FLASH_WINDOW_BITS) | IXDP2X01_CPLD_FLASH_INTERN));
+	return (ofs & IXDP2X01_FLASH_WINDOW_MASK);
+}
+
+static struct ixp2000_flash_data ixdp2x01_flash_data = {
+	.platform_data	= &ixdp2x01_flash_platform_data,
+	.bank_setup	= ixdp2x01_flash_bank_setup
+};
+
+static struct resource ixdp2x01_flash_resource = {
+	.start		= 0xc4000000,
+	.end		= 0xc4000000 + 0x01ffffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp2x01_flash = {
+	.name		= "IXP2000-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &ixdp2x01_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &ixdp2x01_flash_resource,
+};
+
+static struct ixp2000_i2c_pins ixdp2x01_i2c_gpio_pins = {
+	.sda_pin	= IXDP2X01_GPIO_SDA,
+	.scl_pin	= IXDP2X01_GPIO_SCL,
+};
+
+static struct platform_device ixdp2x01_i2c_controller = {
+	.name		= "IXP2000-I2C",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &ixdp2x01_i2c_gpio_pins,
+	},
+	.num_resources	= 0
+};
+
+static struct platform_device *ixdp2x01_devices[] __initdata = {
+	&ixdp2x01_flash,
+	&ixdp2x01_i2c_controller
+};
+
+static void __init ixdp2x01_init_machine(void)
+{
+	ixp2000_reg_write(IXDP2X01_CPLD_FLASH_REG,
+		(IXDP2X01_CPLD_FLASH_BANK_MASK | IXDP2X01_CPLD_FLASH_INTERN));
+	
+	ixdp2x01_flash_data.nr_banks =
+		((*IXDP2X01_CPLD_FLASH_REG & IXDP2X01_CPLD_FLASH_BANK_MASK) + 1);
+
+	platform_add_devices(ixdp2x01_devices, ARRAY_SIZE(ixdp2x01_devices));
+}
+
+
+#ifdef CONFIG_ARCH_IXDP2401
+MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform")
+	MAINTAINER("MontaVista Software, Inc.")
+	BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+	BOOT_PARAMS(0x00000100)
+	MAPIO(ixdp2x01_map_io)
+	INITIRQ(ixdp2x01_init_irq)
+	.timer		= &ixdp2x01_timer,
+	INIT_MACHINE(ixdp2x01_init_machine)
+MACHINE_END
+#endif
+
+#ifdef CONFIG_ARCH_IXDP2801
+MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform")
+	MAINTAINER("MontaVista Software, Inc.")
+	BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+	BOOT_PARAMS(0x00000100)
+	MAPIO(ixdp2x01_map_io)
+	INITIRQ(ixdp2x01_init_irq)
+	.timer		= &ixdp2x01_timer,
+	INIT_MACHINE(ixdp2x01_init_machine)
+MACHINE_END
+#endif
+
+
diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c
new file mode 100644
index 0000000..831f8ff
--- /dev/null
+++ b/arch/arm/mach-ixp2000/pci.c
@@ -0,0 +1,235 @@
+/*
+ * arch/arm/mach-ixp2000/pci.c
+ *
+ * PCI routines for IXDP2400/IXDP2800 boards
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintained by: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2002 Intel Corp.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/pci.h>
+
+static int pci_master_aborts = 0;
+
+static int clear_master_aborts(void);
+
+static u32 *
+ixp2000_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where)
+{
+	u32 *paddress;
+
+	if (PCI_SLOT(devfn) > 7)
+		return 0;
+
+	/* Must be dword aligned */
+	where &= ~3;
+
+	/*
+	 * For top bus, generate type 0, else type 1
+	 */
+	if (!bus_nr) {
+		/* only bits[23:16] are used for IDSEL */
+		paddress = (u32 *) (IXP2000_PCI_CFG0_VIRT_BASE
+				    | (1 << (PCI_SLOT(devfn) + 16))
+				    | (PCI_FUNC(devfn) << 8) | where);
+	} else {
+		paddress = (u32 *) (IXP2000_PCI_CFG1_VIRT_BASE 
+				    | (bus_nr << 16)
+				    | (PCI_SLOT(devfn) << 11)
+				    | (PCI_FUNC(devfn) << 8) | where);
+	}
+
+	return paddress;
+}
+
+/*
+ * Mask table, bits to mask for quantity of size 1, 2 or 4 bytes.
+ * 0 and 3 are not valid indexes...
+ */
+static u32 bytemask[] = {
+	/*0*/	0,
+	/*1*/	0xff,
+	/*2*/	0xffff,
+	/*3*/	0,
+	/*4*/	0xffffffff,
+};
+
+
+int ixp2000_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+				int size, u32 *value)
+{
+	u32 n;
+	u32 *addr;
+
+	n = where % 4;
+
+	addr = ixp2000_pci_config_addr(bus->number, devfn, where);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	pci_master_aborts = 0;
+	*value = (*addr >> (8*n)) & bytemask[size];
+	if (pci_master_aborts) {
+		pci_master_aborts = 0;
+		*value = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * We don't do error checks by callling clear_master_aborts() b/c the
+ * assumption is that the caller did a read first to make sure a device
+ * exists.
+ */
+int ixp2000_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+				int size, u32 value)
+{
+	u32 mask;
+	u32 *addr;
+	u32 temp;
+
+	mask = ~(bytemask[size] << ((where % 0x4) * 8));
+	addr = ixp2000_pci_config_addr(bus->number, devfn, where);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	temp = (u32) (value) << ((where % 0x4) * 8);
+	*addr = (*addr & mask) | temp;
+
+	clear_master_aborts();
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+static struct pci_ops ixp2000_pci_ops = {
+	.read	= ixp2000_pci_read_config,
+	.write	= ixp2000_pci_write_config
+};
+
+struct pci_bus *ixp2000_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
+{
+	return pci_scan_bus(sysdata->busnr, &ixp2000_pci_ops, sysdata);
+}
+
+
+int ixp2000_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+
+	volatile u32 temp;
+	unsigned long flags;
+
+	pci_master_aborts = 1;
+
+	local_irq_save(flags);
+	temp = *(IXP2000_PCI_CONTROL);
+	if (temp & ((1 << 8) | (1 << 5))) {
+		ixp2000_reg_write(IXP2000_PCI_CONTROL, temp);
+	}
+
+	temp = *(IXP2000_PCI_CMDSTAT);
+	if (temp & (1 << 29)) {
+		while (temp & (1 << 29)) {	
+			ixp2000_reg_write(IXP2000_PCI_CMDSTAT, temp);
+			temp = *(IXP2000_PCI_CMDSTAT);
+		}
+	}
+	local_irq_restore(flags);
+
+	/*
+	 * If it was an imprecise abort, then we need to correct the
+	 * return address to be _after_ the instruction.
+	 */
+	if (fsr & (1 << 10))
+		regs->ARM_pc += 4;
+
+	return 0;
+}
+
+int
+clear_master_aborts(void)
+{
+	volatile u32 temp;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	temp = *(IXP2000_PCI_CONTROL);
+	if (temp & ((1 << 8) | (1 << 5))) {	
+		ixp2000_reg_write(IXP2000_PCI_CONTROL, temp);
+	}
+
+	temp = *(IXP2000_PCI_CMDSTAT);
+	if (temp & (1 << 29)) {
+		while (temp & (1 << 29)) {
+			ixp2000_reg_write(IXP2000_PCI_CMDSTAT, temp);
+			temp = *(IXP2000_PCI_CMDSTAT);
+		}
+	}
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+void __init
+ixp2000_pci_preinit(void)
+{
+	hook_fault_code(16+6, ixp2000_pci_abort_handler, SIGBUS,
+				"PCI config cycle to non-existent device");
+}
+
+
+/*
+ * IXP2000 systems often have large resource requirements, so we just
+ * use our own resource space.
+ */
+static struct resource ixp2000_pci_mem_space = {
+	.start	= 0x00000000,
+	.end	= 0xffffffff,
+	.flags	= IORESOURCE_MEM,
+	.name	= "PCI Mem Space"
+};
+
+static struct resource ixp2000_pci_io_space = {
+	.start	= 0x00000000,
+	.end	= 0xffffffff,
+	.flags	= IORESOURCE_IO,
+	.name	= "PCI I/O Space"
+};
+
+int ixp2000_pci_setup(int nr, struct pci_sys_data *sys)
+{
+	if (nr >= 1)
+		return 0;
+
+	sys->resource[0] = &ixp2000_pci_io_space;
+	sys->resource[1] = &ixp2000_pci_mem_space;
+	sys->resource[2] = NULL;
+
+	return 1;
+}
+