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-footbridge/Kconfig b/arch/arm/mach-footbridge/Kconfig
new file mode 100644
index 0000000..1090c68
--- /dev/null
+++ b/arch/arm/mach-footbridge/Kconfig
@@ -0,0 +1,80 @@
+if ARCH_FOOTBRIDGE
+
+menu "Footbridge Implementations"
+
+config ARCH_CATS
+	bool "CATS"
+	select FOOTBRIDGE_HOST
+	help
+	  Say Y here if you intend to run this kernel on the CATS.
+
+	  Saying N will reduce the size of the Footbridge kernel.
+
+config ARCH_PERSONAL_SERVER
+	bool "Compaq Personal Server"
+	select FOOTBRIDGE_HOST
+	---help---
+	  Say Y here if you intend to run this kernel on the Compaq
+	  Personal Server.
+
+	  Saying N will reduce the size of the Footbridge kernel.
+
+	  The Compaq Personal Server is not available for purchase.
+	  There are no product plans beyond the current research
+	  prototypes at this time.  Information is available at:
+
+	  <http://www.crl.hpl.hp.com/projects/personalserver/>
+
+	  If you have any questions or comments about the  Compaq Personal
+	  Server, send e-mail to <skiff@crl.dec.com>.
+
+config ARCH_EBSA285_ADDIN
+	bool "EBSA285 (addin mode)"
+	select ARCH_EBSA285
+	select FOOTBRIDGE_ADDIN
+	help
+	  Say Y here if you intend to run this kernel on the EBSA285 card
+	  in addin mode.
+
+	  Saying N will reduce the size of the Footbridge kernel.
+
+config ARCH_EBSA285_HOST
+	bool "EBSA285 (host mode)"
+	select ARCH_EBSA285
+	select FOOTBRIDGE_HOST
+	help
+	  Say Y here if you intend to run this kernel on the EBSA285 card
+	  in host ("central function") mode.
+
+	  Saying N will reduce the size of the Footbridge kernel.
+
+config ARCH_NETWINDER
+	bool "NetWinder"
+	select FOOTBRIDGE_HOST
+	help
+	  Say Y here if you intend to run this kernel on the Rebel.COM
+	  NetWinder.  Information about this machine can be found at:
+
+	  <http://www.netwinder.org/>
+
+	  Saying N will reduce the size of the Footbridge kernel.
+
+endmenu
+
+# Footbridge support
+config FOOTBRIDGE
+	bool
+
+# Footbridge in host mode
+config FOOTBRIDGE_HOST
+	bool
+
+# Footbridge in addin mode
+config FOOTBRIDGE_ADDIN
+	bool
+
+# EBSA285 board in either host or addin mode
+config ARCH_EBSA285
+	bool
+
+endif
diff --git a/arch/arm/mach-footbridge/Makefile b/arch/arm/mach-footbridge/Makefile
new file mode 100644
index 0000000..0694ad6
--- /dev/null
+++ b/arch/arm/mach-footbridge/Makefile
@@ -0,0 +1,30 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Object file lists.
+
+obj-y			:= common.o dc21285.o dma.o isa-irq.o time.o
+obj-m			:=
+obj-n			:=
+obj-			:=
+
+pci-$(CONFIG_ARCH_CATS) += cats-pci.o
+pci-$(CONFIG_ARCH_EBSA285_HOST) += ebsa285-pci.o
+pci-$(CONFIG_ARCH_NETWINDER) += netwinder-pci.o
+pci-$(CONFIG_ARCH_PERSONAL_SERVER) += personal-pci.o
+
+leds-$(CONFIG_ARCH_CO285) += ebsa285-leds.o
+leds-$(CONFIG_ARCH_EBSA285) += ebsa285-leds.o
+leds-$(CONFIG_ARCH_NETWINDER) += netwinder-leds.o
+
+obj-$(CONFIG_ARCH_CATS) += cats-hw.o isa-timer.o
+obj-$(CONFIG_ARCH_CO285) += co285.o dc21285-timer.o
+obj-$(CONFIG_ARCH_EBSA285) += ebsa285.o dc21285-timer.o
+obj-$(CONFIG_ARCH_NETWINDER) += netwinder-hw.o isa-timer.o
+obj-$(CONFIG_ARCH_PERSONAL_SERVER) += personal.o dc21285-timer.o
+
+obj-$(CONFIG_PCI)	+=$(pci-y)
+obj-$(CONFIG_LEDS)	+=$(leds-y)
+
+obj-$(CONFIG_ISA)	+= isa.o
diff --git a/arch/arm/mach-footbridge/Makefile.boot b/arch/arm/mach-footbridge/Makefile.boot
new file mode 100644
index 0000000..c7e75ac
--- /dev/null
+++ b/arch/arm/mach-footbridge/Makefile.boot
@@ -0,0 +1,4 @@
+   zreladdr-y	:= 0x00008000
+params_phys-y	:= 0x00000100
+initrd_phys-y	:= 0x00800000
+
diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
new file mode 100644
index 0000000..d1ced86
--- /dev/null
+++ b/arch/arm/mach-footbridge/cats-hw.c
@@ -0,0 +1,95 @@
+/*
+ * linux/arch/arm/mach-footbridge/cats-hw.c
+ *
+ * CATS machine fixup
+ *
+ * Copyright (C) 1998, 1999 Russell King, Phil Blundell
+ */
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+
+#include <asm/hardware/dec21285.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/setup.h>
+
+#include <asm/mach/arch.h>
+
+#include "common.h"
+
+#define CFG_PORT	0x370
+#define INDEX_PORT	(CFG_PORT)
+#define DATA_PORT	(CFG_PORT + 1)
+
+static int __init cats_hw_init(void)
+{
+	if (machine_is_cats()) {
+		/* Set Aladdin to CONFIGURE mode */
+		outb(0x51, CFG_PORT);
+		outb(0x23, CFG_PORT);
+
+		/* Select logical device 3 */
+		outb(0x07, INDEX_PORT);
+		outb(0x03, DATA_PORT);
+
+		/* Set parallel port to DMA channel 3, ECP+EPP1.9, 
+		   enable EPP timeout */
+		outb(0x74, INDEX_PORT);
+		outb(0x03, DATA_PORT);
+	
+		outb(0xf0, INDEX_PORT);
+		outb(0x0f, DATA_PORT);
+
+		outb(0xf1, INDEX_PORT);
+		outb(0x07, DATA_PORT);
+
+		/* Select logical device 4 */
+		outb(0x07, INDEX_PORT);
+		outb(0x04, DATA_PORT);
+
+		/* UART1 high speed mode */
+		outb(0xf0, INDEX_PORT);
+		outb(0x02, DATA_PORT);
+
+		/* Select logical device 5 */
+		outb(0x07, INDEX_PORT);
+		outb(0x05, DATA_PORT);
+
+		/* UART2 high speed mode */
+		outb(0xf0, INDEX_PORT);
+		outb(0x02, DATA_PORT);
+
+		/* Set Aladdin to RUN mode */
+		outb(0xbb, CFG_PORT);
+	}
+
+	return 0;
+}
+
+__initcall(cats_hw_init);
+
+/*
+ * CATS uses soft-reboot by default, since
+ * hard reboots fail on early boards.
+ */
+static void __init
+fixup_cats(struct machine_desc *desc, struct tag *tags,
+	   char **cmdline, struct meminfo *mi)
+{
+	ORIG_VIDEO_LINES  = 25;
+	ORIG_VIDEO_POINTS = 16;
+	ORIG_Y = 24;
+}
+
+MACHINE_START(CATS, "Chalice-CATS")
+	MAINTAINER("Philip Blundell")
+	BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
+	BOOT_PARAMS(0x00000100)
+	SOFT_REBOOT
+	FIXUP(fixup_cats)
+	MAPIO(footbridge_map_io)
+	INITIRQ(footbridge_init_irq)
+	.timer		= &isa_timer,
+MACHINE_END
diff --git a/arch/arm/mach-footbridge/cats-pci.c b/arch/arm/mach-footbridge/cats-pci.c
new file mode 100644
index 0000000..4f984fd
--- /dev/null
+++ b/arch/arm/mach-footbridge/cats-pci.c
@@ -0,0 +1,55 @@
+/*
+ * linux/arch/arm/mach-footbridge/cats-pci.c
+ *
+ * PCI bios-type initialisation for PCI machines
+ *
+ * Bits taken from various places.
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+/* cats host-specific stuff */
+static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
+
+static int __init cats_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (dev->irq >= 128)
+		return dev->irq & 0x1f;
+
+	if (dev->irq >= 1 && dev->irq <= 4)
+		return irqmap_cats[dev->irq - 1];
+
+	if (dev->irq != 0)
+		printk("PCI: device %02x:%02x has unknown irq line %x\n",
+		       dev->bus->number, dev->devfn, dev->irq);
+
+	return -1;
+}
+
+/*
+ * why not the standard PCI swizzle?  does this prevent 4-port tulip
+ * cards being used (ie, pci-pci bridge based cards)?
+ */
+static struct hw_pci cats_pci __initdata = {
+	.swizzle		= NULL,
+	.map_irq		= cats_map_irq,
+	.nr_controllers		= 1,
+	.setup			= dc21285_setup,
+	.scan			= dc21285_scan_bus,
+	.preinit		= dc21285_preinit,
+	.postinit		= dc21285_postinit,
+};
+
+static int cats_pci_init(void)
+{
+	if (machine_is_cats())
+		pci_common_init(&cats_pci);
+	return 0;
+}
+
+subsys_initcall(cats_pci_init);
diff --git a/arch/arm/mach-footbridge/co285.c b/arch/arm/mach-footbridge/co285.c
new file mode 100644
index 0000000..e154191
--- /dev/null
+++ b/arch/arm/mach-footbridge/co285.c
@@ -0,0 +1,38 @@
+/*
+ * linux/arch/arm/mach-footbridge/co285.c
+ *
+ * CO285 machine fixup
+ */
+#include <linux/init.h>
+
+#include <asm/hardware/dec21285.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+
+#include "common.h"
+
+static void __init
+fixup_coebsa285(struct machine_desc *desc, struct tag *tags,
+		char **cmdline, struct meminfo *mi)
+{
+	extern unsigned long boot_memory_end;
+	extern char boot_command_line[];
+
+	mi->nr_banks      = 1;
+	mi->bank[0].start = PHYS_OFFSET;
+	mi->bank[0].size  = boot_memory_end;
+	mi->bank[0].node  = 0;
+
+	*cmdline = boot_command_line;
+}
+
+MACHINE_START(CO285, "co-EBSA285")
+	MAINTAINER("Mark van Doesburg")
+	BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0x7cf00000)
+	FIXUP(fixup_coebsa285)
+	MAPIO(footbridge_map_io)
+	INITIRQ(footbridge_init_irq)
+	.timer		= &footbridge_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c
new file mode 100644
index 0000000..eb8238c
--- /dev/null
+++ b/arch/arm/mach-footbridge/common.c
@@ -0,0 +1,205 @@
+/*
+ *  linux/arch/arm/mach-footbridge/common.c
+ *
+ *  Copyright (C) 1998-2000 Russell King, Dave Gilbert.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/list.h>
+#include <linux/init.h>
+ 
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/setup.h>
+#include <asm/hardware/dec21285.h>
+
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+
+#include "common.h"
+
+extern void __init isa_init_irq(unsigned int irq);
+
+unsigned int mem_fclk_21285 = 50000000;
+
+EXPORT_SYMBOL(mem_fclk_21285);
+
+static int __init parse_tag_memclk(const struct tag *tag)
+{
+	mem_fclk_21285 = tag->u.memclk.fmemclk;
+	return 0;
+}
+
+__tagtable(ATAG_MEMCLK, parse_tag_memclk);
+
+/*
+ * Footbridge IRQ translation table
+ *  Converts from our IRQ numbers into FootBridge masks
+ */
+static const int fb_irq_mask[] = {
+	IRQ_MASK_UART_RX,	/*  0 */
+	IRQ_MASK_UART_TX,	/*  1 */
+	IRQ_MASK_TIMER1,	/*  2 */
+	IRQ_MASK_TIMER2,	/*  3 */
+	IRQ_MASK_TIMER3,	/*  4 */
+	IRQ_MASK_IN0,		/*  5 */
+	IRQ_MASK_IN1,		/*  6 */
+	IRQ_MASK_IN2,		/*  7 */
+	IRQ_MASK_IN3,		/*  8 */
+	IRQ_MASK_DOORBELLHOST,	/*  9 */
+	IRQ_MASK_DMA1,		/* 10 */
+	IRQ_MASK_DMA2,		/* 11 */
+	IRQ_MASK_PCI,		/* 12 */
+	IRQ_MASK_SDRAMPARITY,	/* 13 */
+	IRQ_MASK_I2OINPOST,	/* 14 */
+	IRQ_MASK_PCI_ABORT,	/* 15 */
+	IRQ_MASK_PCI_SERR,	/* 16 */
+	IRQ_MASK_DISCARD_TIMER,	/* 17 */
+	IRQ_MASK_PCI_DPERR,	/* 18 */
+	IRQ_MASK_PCI_PERR,	/* 19 */
+};
+
+static void fb_mask_irq(unsigned int irq)
+{
+	*CSR_IRQ_DISABLE = fb_irq_mask[_DC21285_INR(irq)];
+}
+
+static void fb_unmask_irq(unsigned int irq)
+{
+	*CSR_IRQ_ENABLE = fb_irq_mask[_DC21285_INR(irq)];
+}
+
+static struct irqchip fb_chip = {
+	.ack	= fb_mask_irq,
+	.mask	= fb_mask_irq,
+	.unmask = fb_unmask_irq,
+};
+
+static void __init __fb_init_irq(void)
+{
+	unsigned int irq;
+
+	/*
+	 * setup DC21285 IRQs
+	 */
+	*CSR_IRQ_DISABLE = -1;
+	*CSR_FIQ_DISABLE = -1;
+
+	for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(20); irq++) {
+		set_irq_chip(irq, &fb_chip);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+}
+
+void __init footbridge_init_irq(void)
+{
+	__fb_init_irq();
+
+	if (!footbridge_cfn_mode())
+		return;
+
+	if (machine_is_ebsa285())
+		/* The following is dependent on which slot
+		 * you plug the Southbridge card into.  We
+		 * currently assume that you plug it into
+		 * the right-hand most slot.
+		 */
+		isa_init_irq(IRQ_PCI);
+
+	if (machine_is_cats())
+		isa_init_irq(IRQ_IN2);
+
+	if (machine_is_netwinder())
+		isa_init_irq(IRQ_IN3);
+}
+
+/*
+ * Common mapping for all systems.  Note that the outbound write flush is
+ * commented out since there is a "No Fix" problem with it.  Not mapping
+ * it means that we have extra bullet protection on our feet.
+ */
+static struct map_desc fb_common_io_desc[] __initdata = {
+ { ARMCSR_BASE,	 DC21285_ARMCSR_BASE,	    ARMCSR_SIZE,  MT_DEVICE },
+ { XBUS_BASE,    0x40000000,		    XBUS_SIZE,    MT_DEVICE }
+};
+
+/*
+ * The mapping when the footbridge is in host mode.  We don't map any of
+ * this when we are in add-in mode.
+ */
+static struct map_desc ebsa285_host_io_desc[] __initdata = {
+#if defined(CONFIG_ARCH_FOOTBRIDGE) && defined(CONFIG_FOOTBRIDGE_HOST)
+ { PCIMEM_BASE,  DC21285_PCI_MEM,	    PCIMEM_SIZE,  MT_DEVICE },
+ { PCICFG0_BASE, DC21285_PCI_TYPE_0_CONFIG, PCICFG0_SIZE, MT_DEVICE },
+ { PCICFG1_BASE, DC21285_PCI_TYPE_1_CONFIG, PCICFG1_SIZE, MT_DEVICE },
+ { PCIIACK_BASE, DC21285_PCI_IACK,	    PCIIACK_SIZE, MT_DEVICE },
+ { PCIO_BASE,    DC21285_PCI_IO,	    PCIO_SIZE,	  MT_DEVICE }
+#endif
+};
+
+/*
+ * The CO-ebsa285 mapping.
+ */
+static struct map_desc co285_io_desc[] __initdata = {
+#ifdef CONFIG_ARCH_CO285
+ { PCIO_BASE,	 DC21285_PCI_IO,	    PCIO_SIZE,    MT_DEVICE },
+ { PCIMEM_BASE,	 DC21285_PCI_MEM,	    PCIMEM_SIZE,  MT_DEVICE }
+#endif
+};
+
+void __init footbridge_map_io(void)
+{
+	/*
+	 * Set up the common mapping first; we need this to
+	 * determine whether we're in host mode or not.
+	 */
+	iotable_init(fb_common_io_desc, ARRAY_SIZE(fb_common_io_desc));
+
+	/*
+	 * Now, work out what we've got to map in addition on this
+	 * platform.
+	 */
+	if (machine_is_co285())
+		iotable_init(co285_io_desc, ARRAY_SIZE(co285_io_desc));
+	if (footbridge_cfn_mode())
+		iotable_init(ebsa285_host_io_desc, ARRAY_SIZE(ebsa285_host_io_desc));
+}
+
+#ifdef CONFIG_FOOTBRIDGE_ADDIN
+
+/*
+ * These two functions convert virtual addresses to PCI addresses and PCI
+ * addresses to virtual addresses.  Note that it is only legal to use these
+ * on memory obtained via get_zeroed_page or kmalloc.
+ */
+unsigned long __virt_to_bus(unsigned long res)
+{
+	WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory);
+
+	return (res - PAGE_OFFSET) + (*CSR_PCISDRAMBASE & 0xfffffff0);
+}
+EXPORT_SYMBOL(__virt_to_bus);
+
+unsigned long __bus_to_virt(unsigned long res)
+{
+	res -= (*CSR_PCISDRAMBASE & 0xfffffff0);
+	res += PAGE_OFFSET;
+
+	WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory);
+
+	return res;
+}
+EXPORT_SYMBOL(__bus_to_virt);
+
+#endif
diff --git a/arch/arm/mach-footbridge/common.h b/arch/arm/mach-footbridge/common.h
new file mode 100644
index 0000000..580e31b
--- /dev/null
+++ b/arch/arm/mach-footbridge/common.h
@@ -0,0 +1,9 @@
+
+extern struct sys_timer footbridge_timer;
+extern struct sys_timer isa_timer;
+
+extern void isa_rtc_init(void);
+
+extern void footbridge_map_io(void);
+extern void footbridge_init_irq(void);
+
diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c
new file mode 100644
index 0000000..580e1d4
--- /dev/null
+++ b/arch/arm/mach-footbridge/dc21285-timer.c
@@ -0,0 +1,68 @@
+/*
+ *  linux/arch/arm/mach-footbridge/dc21285-timer.c
+ *
+ *  Copyright (C) 1998 Russell King.
+ *  Copyright (C) 1998 Phil Blundell
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq.h>
+
+#include <asm/hardware/dec21285.h>
+#include <asm/mach/time.h>
+
+#include "common.h"
+
+/*
+ * Footbridge timer 1 support.
+ */
+static unsigned long timer1_latch;
+
+static unsigned long timer1_gettimeoffset (void)
+{
+	unsigned long value = timer1_latch - *CSR_TIMER1_VALUE;
+
+	return ((tick_nsec / 1000) * value) / timer1_latch;
+}
+
+static irqreturn_t
+timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	write_seqlock(&xtime_lock);
+
+	*CSR_TIMER1_CLR = 0;
+
+	timer_tick(regs);
+
+	write_sequnlock(&xtime_lock);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction footbridge_timer_irq = {
+	.name		= "Timer1 timer tick",
+	.handler	= timer1_interrupt,
+	.flags		= SA_INTERRUPT,
+};
+
+/*
+ * Set up timer interrupt.
+ */
+static void __init footbridge_timer_init(void)
+{
+	isa_rtc_init();
+
+	timer1_latch = (mem_fclk_21285 + 8 * HZ) / (16 * HZ);
+
+	*CSR_TIMER1_CLR  = 0;
+	*CSR_TIMER1_LOAD = timer1_latch;
+	*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
+
+	setup_irq(IRQ_TIMER1, &footbridge_timer_irq);
+}
+
+struct sys_timer footbridge_timer = {
+	.init		= footbridge_timer_init,
+	.offset		= timer1_gettimeoffset,
+};
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
new file mode 100644
index 0000000..e79884ee
--- /dev/null
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -0,0 +1,384 @@
+/*
+ *  linux/arch/arm/kernel/dec21285.c: PCI functions for DC21285
+ *
+ *  Copyright (C) 1998-2001 Russell King
+ *  Copyright (C) 1998-2000 Phil Blundell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/mach/pci.h>
+#include <asm/hardware/dec21285.h>
+
+#define MAX_SLOTS		21
+
+#define PCICMD_ABORT		((PCI_STATUS_REC_MASTER_ABORT| \
+				  PCI_STATUS_REC_TARGET_ABORT)<<16)
+
+#define PCICMD_ERROR_BITS	((PCI_STATUS_DETECTED_PARITY | \
+				  PCI_STATUS_REC_MASTER_ABORT | \
+				  PCI_STATUS_REC_TARGET_ABORT | \
+				  PCI_STATUS_PARITY) << 16)
+
+extern int setup_arm_irq(int, struct irqaction *);
+extern void pcibios_report_status(u_int status_mask, int warn);
+extern void register_isa_ports(unsigned int, unsigned int, unsigned int);
+
+static unsigned long
+dc21285_base_address(struct pci_bus *bus, unsigned int devfn)
+{
+	unsigned long addr = 0;
+
+	if (bus->number == 0) {
+		if (PCI_SLOT(devfn) == 0)
+			/*
+			 * For devfn 0, point at the 21285
+			 */
+			addr = ARMCSR_BASE;
+		else {
+			devfn -= 1 << 3;
+
+			if (devfn < PCI_DEVFN(MAX_SLOTS, 0))
+				addr = PCICFG0_BASE | 0xc00000 | (devfn << 8);
+		}
+	} else
+		addr = PCICFG1_BASE | (bus->number << 16) | (devfn << 8);
+
+	return addr;
+}
+
+static int
+dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+		    int size, u32 *value)
+{
+	unsigned long addr = dc21285_base_address(bus, devfn);
+	u32 v = 0xffffffff;
+
+	if (addr)
+		switch (size) {
+		case 1:
+			asm("ldr%?b	%0, [%1, %2]"
+				: "=r" (v) : "r" (addr), "r" (where));
+			break;
+		case 2:
+			asm("ldr%?h	%0, [%1, %2]"
+				: "=r" (v) : "r" (addr), "r" (where));
+			break;
+		case 4:
+			asm("ldr%?	%0, [%1, %2]"
+				: "=r" (v) : "r" (addr), "r" (where));
+			break;
+		}
+
+	*value = v;
+
+	v = *CSR_PCICMD;
+	if (v & PCICMD_ABORT) {
+		*CSR_PCICMD = v & (0xffff|PCICMD_ABORT);
+		return -1;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+dc21285_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+		     int size, u32 value)
+{
+	unsigned long addr = dc21285_base_address(bus, devfn);
+	u32 v;
+
+	if (addr)
+		switch (size) {
+		case 1:
+			asm("str%?b	%0, [%1, %2]"
+				: : "r" (value), "r" (addr), "r" (where));
+			break;
+		case 2:
+			asm("str%?h	%0, [%1, %2]"
+				: : "r" (value), "r" (addr), "r" (where));
+			break;
+		case 4:
+			asm("str%?	%0, [%1, %2]"
+				: : "r" (value), "r" (addr), "r" (where));
+			break;
+		}
+
+	v = *CSR_PCICMD;
+	if (v & PCICMD_ABORT) {
+		*CSR_PCICMD = v & (0xffff|PCICMD_ABORT);
+		return -1;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops dc21285_ops = {
+	.read	= dc21285_read_config,
+	.write	= dc21285_write_config,
+};
+
+static struct timer_list serr_timer;
+static struct timer_list perr_timer;
+
+static void dc21285_enable_error(unsigned long __data)
+{
+	switch (__data) {
+	case IRQ_PCI_SERR:
+		del_timer(&serr_timer);
+		break;
+
+	case IRQ_PCI_PERR:
+		del_timer(&perr_timer);
+		break;
+	}
+
+	enable_irq(__data);
+}
+
+/*
+ * Warn on PCI errors.
+ */
+static irqreturn_t dc21285_abort_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned int cmd;
+	unsigned int status;
+
+	cmd = *CSR_PCICMD;
+	status = cmd >> 16;
+	cmd = cmd & 0xffff;
+
+	if (status & PCI_STATUS_REC_MASTER_ABORT) {
+		printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n",
+			instruction_pointer(regs));
+		cmd |= PCI_STATUS_REC_MASTER_ABORT << 16;
+	}
+
+	if (status & PCI_STATUS_REC_TARGET_ABORT) {
+		printk(KERN_DEBUG "PCI: target abort: ");
+		pcibios_report_status(PCI_STATUS_REC_MASTER_ABORT |
+				      PCI_STATUS_SIG_TARGET_ABORT |
+				      PCI_STATUS_REC_TARGET_ABORT, 1);
+		printk("\n");
+
+		cmd |= PCI_STATUS_REC_TARGET_ABORT << 16;
+	}
+
+	*CSR_PCICMD = cmd;
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t dc21285_serr_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct timer_list *timer = dev_id;
+	unsigned int cntl;
+
+	printk(KERN_DEBUG "PCI: system error received: ");
+	pcibios_report_status(PCI_STATUS_SIG_SYSTEM_ERROR, 1);
+	printk("\n");
+
+	cntl = *CSR_SA110_CNTL & 0xffffdf07;
+	*CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR;
+
+	/*
+	 * back off this interrupt
+	 */
+	disable_irq(irq);
+	timer->expires = jiffies + HZ;
+	add_timer(timer);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t dc21285_discard_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	printk(KERN_DEBUG "PCI: discard timer expired\n");
+	*CSR_SA110_CNTL &= 0xffffde07;
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t dc21285_dparity_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned int cmd;
+
+	printk(KERN_DEBUG "PCI: data parity error detected: ");
+	pcibios_report_status(PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY, 1);
+	printk("\n");
+
+	cmd = *CSR_PCICMD & 0xffff;
+	*CSR_PCICMD = cmd | 1 << 24;
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t dc21285_parity_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct timer_list *timer = dev_id;
+	unsigned int cmd;
+
+	printk(KERN_DEBUG "PCI: parity error detected: ");
+	pcibios_report_status(PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY, 1);
+	printk("\n");
+
+	cmd = *CSR_PCICMD & 0xffff;
+	*CSR_PCICMD = cmd | 1 << 31;
+
+	/*
+	 * back off this interrupt
+	 */
+	disable_irq(irq);
+	timer->expires = jiffies + HZ;
+	add_timer(timer);
+
+	return IRQ_HANDLED;
+}
+
+int __init dc21285_setup(int nr, struct pci_sys_data *sys)
+{
+	struct resource *res;
+
+	if (nr || !footbridge_cfn_mode())
+		return 0;
+
+	res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+	if (!res) {
+		printk("out of memory for root bus resources");
+		return 0;
+	}
+
+	memset(res, 0, sizeof(struct resource) * 2);
+
+	res[0].flags = IORESOURCE_MEM;
+	res[0].name  = "Footbridge non-prefetch";
+	res[1].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
+	res[1].name  = "Footbridge prefetch";
+
+	allocate_resource(&iomem_resource, &res[1], 0x20000000,
+			  0xa0000000, 0xffffffff, 0x20000000, NULL, NULL);
+	allocate_resource(&iomem_resource, &res[0], 0x40000000,
+			  0x80000000, 0xffffffff, 0x40000000, NULL, NULL);
+
+	sys->resource[0] = &ioport_resource;
+	sys->resource[1] = &res[0];
+	sys->resource[2] = &res[1];
+	sys->mem_offset  = DC21285_PCI_MEM;
+
+	return 1;
+}
+
+struct pci_bus * __init dc21285_scan_bus(int nr, struct pci_sys_data *sys)
+{
+	return pci_scan_bus(0, &dc21285_ops, sys);
+}
+
+void __init dc21285_preinit(void)
+{
+	unsigned int mem_size, mem_mask;
+	int cfn_mode;
+
+	mem_size = (unsigned int)high_memory - PAGE_OFFSET;
+	for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
+		if (mem_mask >= mem_size)
+			break;		
+
+	/*
+	 * These registers need to be set up whether we're the
+	 * central function or not.
+	 */
+	*CSR_SDRAMBASEMASK    = (mem_mask - 1) & 0x0ffc0000;
+	*CSR_SDRAMBASEOFFSET  = 0;
+	*CSR_ROMBASEMASK      = 0x80000000;
+	*CSR_CSRBASEMASK      = 0;
+	*CSR_CSRBASEOFFSET    = 0;
+	*CSR_PCIADDR_EXTN     = 0;
+
+	cfn_mode = __footbridge_cfn_mode();
+
+	printk(KERN_INFO "PCI: DC21285 footbridge, revision %02lX, in "
+		"%s mode\n", *CSR_CLASSREV & 0xff, cfn_mode ?
+		"central function" : "addin");
+
+	if (footbridge_cfn_mode()) {
+		/*
+		 * Clear any existing errors - we aren't
+		 * interested in historical data...
+		 */
+		*CSR_SA110_CNTL	= (*CSR_SA110_CNTL & 0xffffde07) |
+				  SA110_CNTL_RXSERR;
+		*CSR_PCICMD = (*CSR_PCICMD & 0xffff) | PCICMD_ERROR_BITS;
+	}
+
+	init_timer(&serr_timer);
+	init_timer(&perr_timer);
+
+	serr_timer.data = IRQ_PCI_SERR;
+	serr_timer.function = dc21285_enable_error;
+	perr_timer.data = IRQ_PCI_PERR;
+	perr_timer.function = dc21285_enable_error;
+
+	/*
+	 * We don't care if these fail.
+	 */
+	request_irq(IRQ_PCI_SERR, dc21285_serr_irq, SA_INTERRUPT,
+		    "PCI system error", &serr_timer);
+	request_irq(IRQ_PCI_PERR, dc21285_parity_irq, SA_INTERRUPT,
+		    "PCI parity error", &perr_timer);
+	request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, SA_INTERRUPT,
+		    "PCI abort", NULL);
+	request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, SA_INTERRUPT,
+		    "Discard timer", NULL);
+	request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, SA_INTERRUPT,
+		    "PCI data parity", NULL);
+
+	if (cfn_mode) {
+		static struct resource csrio;
+
+		csrio.flags  = IORESOURCE_IO;
+		csrio.name   = "Footbridge";
+
+		allocate_resource(&ioport_resource, &csrio, 128,
+				  0xff00, 0xffff, 128, NULL, NULL);
+
+		/*
+		 * Map our SDRAM at a known address in PCI space, just in case
+		 * the firmware had other ideas.  Using a nonzero base is
+		 * necessary, since some VGA cards forcefully use PCI addresses
+		 * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards).
+		 */
+		*CSR_PCICSRBASE       = 0xf4000000;
+		*CSR_PCICSRIOBASE     = csrio.start;
+		*CSR_PCISDRAMBASE     = __virt_to_bus(PAGE_OFFSET);
+		*CSR_PCIROMBASE       = 0;
+		*CSR_PCICMD = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+			      PCI_COMMAND_INVALIDATE | PCICMD_ERROR_BITS;
+	} else if (footbridge_cfn_mode() != 0) {
+		/*
+		 * If we are not compiled to accept "add-in" mode, then
+		 * we are using a constant virt_to_bus translation which
+		 * can not hope to cater for the way the host BIOS  has
+		 * set up the machine.
+		 */
+		panic("PCI: this kernel is compiled for central "
+			"function mode only");
+	}
+}
+
+void __init dc21285_postinit(void)
+{
+	register_isa_ports(DC21285_PCI_MEM, DC21285_PCI_IO, 0);
+}
diff --git a/arch/arm/mach-footbridge/dma.c b/arch/arm/mach-footbridge/dma.c
new file mode 100644
index 0000000..a6b1396
--- /dev/null
+++ b/arch/arm/mach-footbridge/dma.c
@@ -0,0 +1,54 @@
+/*
+ *  linux/arch/arm/kernel/dma-ebsa285.c
+ *
+ *  Copyright (C) 1998 Phil Blundell
+ *
+ * DMA functions specific to EBSA-285/CATS architectures
+ *
+ *  Changelog:
+ *   09-Nov-1998 RMK	Split out ISA DMA functions to dma-isa.c
+ *   17-Mar-1999 RMK	Allow any EBSA285-like architecture to have
+ *			ISA DMA controllers.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+
+#include <asm/mach/dma.h>
+#include <asm/hardware/dec21285.h>
+
+#if 0
+static int fb_dma_request(dmach_t channel, dma_t *dma)
+{
+	return -EINVAL;
+}
+
+static void fb_dma_enable(dmach_t channel, dma_t *dma)
+{
+}
+
+static void fb_dma_disable(dmach_t channel, dma_t *dma)
+{
+}
+
+static struct dma_ops fb_dma_ops = {
+	.type		= "fb",
+	.request	= fb_dma_request,
+	.enable		= fb_dma_enable,
+	.disable	= fb_dma_disable,
+};
+#endif
+
+void __init arch_dma_init(dma_t *dma)
+{
+#if 0
+	dma[_DC21285_DMA(0)].d_ops = &fb_dma_ops;
+	dma[_DC21285_DMA(1)].d_ops = &fb_dma_ops;
+#endif
+#ifdef CONFIG_ISA_DMA
+	if (footbridge_cfn_mode())
+		isa_init_dma(dma + _ISA_DMA(0));
+#endif
+}
diff --git a/arch/arm/mach-footbridge/ebsa285-leds.c b/arch/arm/mach-footbridge/ebsa285-leds.c
new file mode 100644
index 0000000..2c7c363
--- /dev/null
+++ b/arch/arm/mach-footbridge/ebsa285-leds.c
@@ -0,0 +1,140 @@
+/*
+ *  linux/arch/arm/mach-footbridge/ebsa285-leds.c
+ *
+ *  Copyright (C) 1998-1999 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ * EBSA-285 control routines.
+ *
+ * The EBSA-285 uses the leds as follows:
+ *  - Green - toggles state every 50 timer interrupts
+ *  - Amber - On if system is not idle
+ *  - Red   - currently unused
+ *
+ * Changelog:
+ *   02-05-1999	RMK	Various cleanups
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+#include <asm/system.h>
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+static char led_state;
+static char hw_led_state;
+
+static DEFINE_SPINLOCK(leds_lock);
+
+static void ebsa285_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&leds_lock, flags);
+
+	switch (evt) {
+	case led_start:
+		hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN;
+#ifndef CONFIG_LEDS_CPU
+		hw_led_state |= XBUS_LED_AMBER;
+#endif
+		led_state |= LED_STATE_ENABLED;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN | XBUS_LED_AMBER;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN | XBUS_LED_AMBER;
+		break;
+
+#ifdef CONFIG_LEDS_TIMER
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= XBUS_LED_GREEN;
+		break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= XBUS_LED_AMBER;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~XBUS_LED_AMBER;
+		break;
+#endif
+
+	case led_halted:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~XBUS_LED_RED;
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~XBUS_LED_GREEN;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= XBUS_LED_GREEN;
+		break;
+
+	case led_amber_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~XBUS_LED_AMBER;
+		break;
+
+	case led_amber_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= XBUS_LED_AMBER;
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~XBUS_LED_RED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= XBUS_LED_RED;
+		break;
+
+	default:
+		break;
+	}
+
+	if  (led_state & LED_STATE_ENABLED)
+		*XBUS_LEDS = hw_led_state;
+
+	spin_unlock_irqrestore(&leds_lock, flags);
+}
+
+static int __init leds_init(void)
+{
+	if (machine_is_ebsa285() || machine_is_co285())
+		leds_event = ebsa285_leds_event;
+
+	leds_event(led_start);
+
+	return 0;
+}
+
+__initcall(leds_init);
diff --git a/arch/arm/mach-footbridge/ebsa285-pci.c b/arch/arm/mach-footbridge/ebsa285-pci.c
new file mode 100644
index 0000000..720c0ba
--- /dev/null
+++ b/arch/arm/mach-footbridge/ebsa285-pci.c
@@ -0,0 +1,48 @@
+/*
+ * linux/arch/arm/mach-footbridge/ebsa285-pci.c
+ *
+ * PCI bios-type initialisation for PCI machines
+ *
+ * Bits taken from various places.
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+static int irqmap_ebsa285[] __initdata = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI };
+
+static int __init ebsa285_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
+	    dev->device == PCI_DEVICE_ID_CONTAQ_82C693)
+		switch (PCI_FUNC(dev->devfn)) {
+			case 1:	return 14;
+			case 2:	return 15;
+			case 3:	return 12;
+		}
+
+	return irqmap_ebsa285[(slot + pin) & 3];
+}
+
+static struct hw_pci ebsa285_pci __initdata = {
+	.swizzle		= pci_std_swizzle,
+	.map_irq		= ebsa285_map_irq,
+	.nr_controllers		= 1,
+	.setup			= dc21285_setup,
+	.scan			= dc21285_scan_bus,
+	.preinit		= dc21285_preinit,
+	.postinit		= dc21285_postinit,
+};
+
+static int __init ebsa285_init_pci(void)
+{
+	if (machine_is_ebsa285())
+		pci_common_init(&ebsa285_pci);
+	return 0;
+}
+
+subsys_initcall(ebsa285_init_pci);
diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c
new file mode 100644
index 0000000..d0931f5a
--- /dev/null
+++ b/arch/arm/mach-footbridge/ebsa285.c
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/arm/mach-footbridge/ebsa285.c
+ *
+ * EBSA285 machine fixup
+ */
+#include <linux/init.h>
+
+#include <asm/hardware/dec21285.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+
+#include "common.h"
+
+MACHINE_START(EBSA285, "EBSA285")
+	MAINTAINER("Russell King")
+	BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
+	BOOT_PARAMS(0x00000100)
+	VIDEO(0x000a0000, 0x000bffff)
+	MAPIO(footbridge_map_io)
+	INITIRQ(footbridge_init_irq)
+	.timer		= &footbridge_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c
new file mode 100644
index 0000000..b210160
--- /dev/null
+++ b/arch/arm/mach-footbridge/isa-irq.c
@@ -0,0 +1,168 @@
+/*
+ *  linux/arch/arm/mach-footbridge/irq.c
+ *
+ *  Copyright (C) 1996-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Changelog:
+ *   22-Aug-1998 RMK	Restructured IRQ routines
+ *   03-Sep-1998 PJB	Merged CATS support
+ *   20-Jan-1998 RMK	Started merge of EBSA286, CATS and NetWinder
+ *   26-Jan-1999 PJB	Don't use IACK on CATS
+ *   16-Mar-1999 RMK	Added autodetect of ISA PICs
+ */
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/init.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/dec21285.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+
+static void isa_mask_pic_lo_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 7);
+
+	outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
+}
+
+static void isa_ack_pic_lo_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 7);
+
+	outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
+	outb(0x20, PIC_LO);
+}
+
+static void isa_unmask_pic_lo_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 7);
+
+	outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO);
+}
+
+static struct irqchip isa_lo_chip = {
+	.ack	= isa_ack_pic_lo_irq,
+	.mask	= isa_mask_pic_lo_irq,
+	.unmask = isa_unmask_pic_lo_irq,
+};
+
+static void isa_mask_pic_hi_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 7);
+
+	outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
+}
+
+static void isa_ack_pic_hi_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 7);
+
+	outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
+	outb(0x62, PIC_LO);
+	outb(0x20, PIC_HI);
+}
+
+static void isa_unmask_pic_hi_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 7);
+
+	outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
+}
+
+static struct irqchip isa_hi_chip = {
+	.ack	= isa_ack_pic_hi_irq,
+	.mask	= isa_mask_pic_hi_irq,
+	.unmask = isa_unmask_pic_hi_irq,
+};
+
+static void
+isa_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+	unsigned int isa_irq = *(unsigned char *)PCIIACK_BASE;
+
+	if (isa_irq < _ISA_IRQ(0) || isa_irq >= _ISA_IRQ(16)) {
+		do_bad_IRQ(isa_irq, desc, regs);
+		return;
+	}
+
+	desc = irq_desc + isa_irq;
+	desc->handle(isa_irq, desc, regs);
+}
+
+static struct irqaction irq_cascade = { .handler = no_action, .name = "cascade", };
+static struct resource pic1_resource = { "pic1", 0x20, 0x3f };
+static struct resource pic2_resource = { "pic2", 0xa0, 0xbf };
+
+void __init isa_init_irq(unsigned int host_irq)
+{
+	unsigned int irq;
+
+	/*
+	 * Setup, and then probe for an ISA PIC
+	 * If the PIC is not there, then we
+	 * ignore the PIC.
+	 */
+	outb(0x11, PIC_LO);
+	outb(_ISA_IRQ(0), PIC_MASK_LO);	/* IRQ number		*/
+	outb(0x04, PIC_MASK_LO);	/* Slave on Ch2		*/
+	outb(0x01, PIC_MASK_LO);	/* x86			*/
+	outb(0xf5, PIC_MASK_LO);	/* pattern: 11110101	*/
+
+	outb(0x11, PIC_HI);
+	outb(_ISA_IRQ(8), PIC_MASK_HI);	/* IRQ number		*/
+	outb(0x02, PIC_MASK_HI);	/* Slave on Ch1		*/
+	outb(0x01, PIC_MASK_HI);	/* x86			*/
+	outb(0xfa, PIC_MASK_HI);	/* pattern: 11111010	*/
+
+	outb(0x0b, PIC_LO);
+	outb(0x0b, PIC_HI);
+
+	if (inb(PIC_MASK_LO) == 0xf5 && inb(PIC_MASK_HI) == 0xfa) {
+		outb(0xff, PIC_MASK_LO);/* mask all IRQs	*/
+		outb(0xff, PIC_MASK_HI);/* mask all IRQs	*/
+	} else {
+		printk(KERN_INFO "IRQ: ISA PIC not found\n");
+		host_irq = (unsigned int)-1;
+	}
+
+	if (host_irq != (unsigned int)-1) {
+		for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) {
+			set_irq_chip(irq, &isa_lo_chip);
+			set_irq_handler(irq, do_level_IRQ);
+			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		}
+
+		for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) {
+			set_irq_chip(irq, &isa_hi_chip);
+			set_irq_handler(irq, do_level_IRQ);
+			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		}
+
+		request_resource(&ioport_resource, &pic1_resource);
+		request_resource(&ioport_resource, &pic2_resource);
+		setup_irq(IRQ_ISA_CASCADE, &irq_cascade);
+
+		set_irq_chained_handler(host_irq, isa_irq_handler);
+
+		/*
+		 * On the NetWinder, don't automatically
+		 * enable ISA IRQ11 when it is requested.
+		 * There appears to be a missing pull-up
+		 * resistor on this line.
+		 */
+		if (machine_is_netwinder())
+			set_irq_flags(_ISA_IRQ(11), IRQF_VALID |
+				      IRQF_PROBE | IRQF_NOAUTOEN);
+	}
+}
+
+
diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c
new file mode 100644
index 0000000..a4fefa0
--- /dev/null
+++ b/arch/arm/mach-footbridge/isa-timer.c
@@ -0,0 +1,94 @@
+/*
+ *  linux/arch/arm/mach-footbridge/isa-timer.c
+ *
+ *  Copyright (C) 1998 Russell King.
+ *  Copyright (C) 1998 Phil Blundell
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/mach/time.h>
+
+#include "common.h"
+
+/*
+ * ISA timer tick support
+ */
+#define mSEC_10_from_14 ((14318180 + 100) / 200)
+
+static unsigned long isa_gettimeoffset(void)
+{
+	int count;
+
+	static int count_p = (mSEC_10_from_14/6);    /* for the first call after boot */
+	static unsigned long jiffies_p = 0;
+
+	/*
+	 * cache volatile jiffies temporarily; we have IRQs turned off. 
+	 */
+	unsigned long jiffies_t;
+
+	/* timer count may underflow right here */
+	outb_p(0x00, 0x43);	/* latch the count ASAP */
+
+	count = inb_p(0x40);	/* read the latched count */
+
+	/*
+	 * We do this guaranteed double memory access instead of a _p 
+	 * postfix in the previous port access. Wheee, hackady hack
+	 */
+ 	jiffies_t = jiffies;
+
+	count |= inb_p(0x40) << 8;
+
+	/* Detect timer underflows.  If we haven't had a timer tick since 
+	   the last time we were called, and time is apparently going
+	   backwards, the counter must have wrapped during this routine. */
+	if ((jiffies_t == jiffies_p) && (count > count_p))
+		count -= (mSEC_10_from_14/6);
+	else
+		jiffies_p = jiffies_t;
+
+	count_p = count;
+
+	count = (((mSEC_10_from_14/6)-1) - count) * (tick_nsec / 1000);
+	count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
+
+	return count;
+}
+
+static irqreturn_t
+isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	write_seqlock(&xtime_lock);
+	timer_tick(regs);
+	write_sequnlock(&xtime_lock);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction isa_timer_irq = {
+	.name		= "ISA timer tick",
+	.handler	= isa_timer_interrupt,
+	.flags		= SA_INTERRUPT,
+};
+
+static void __init isa_timer_init(void)
+{
+	isa_rtc_init();
+
+	/* enable PIT timer */
+	/* set for periodic (4) and LSB/MSB write (0x30) */
+	outb(0x34, 0x43);
+	outb((mSEC_10_from_14/6) & 0xFF, 0x40);
+	outb((mSEC_10_from_14/6) >> 8, 0x40);
+
+	setup_irq(IRQ_ISA_TIMER, &isa_timer_irq);
+}
+
+struct sys_timer isa_timer = {
+	.init		= isa_timer_init,
+	.offset		= isa_gettimeoffset,
+};
diff --git a/arch/arm/mach-footbridge/isa.c b/arch/arm/mach-footbridge/isa.c
new file mode 100644
index 0000000..aa3a1fe
--- /dev/null
+++ b/arch/arm/mach-footbridge/isa.c
@@ -0,0 +1,48 @@
+/*
+ *  linux/arch/arm/mach-footbridge/isa.c
+ *
+ *  Copyright (C) 2004 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#include <asm/irq.h>
+
+static struct plat_serial8250_port serial_platform_data[] = {
+	{
+		.iobase		= 0x3f8,
+		.irq		= IRQ_ISA_UART,
+		.uartclk	= 1843200,
+		.regshift	= 0,
+		.iotype		= UPIO_PORT,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+	},
+	{
+		.iobase		= 0x2f8,
+		.irq		= IRQ_ISA_UART2,
+		.uartclk	= 1843200,
+		.regshift	= 0,
+		.iotype		= UPIO_PORT,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+	},
+	{ },
+};
+
+static struct platform_device serial_device = {
+	.name			= "serial8250",
+	.id			= 0,
+	.dev			= {
+		.platform_data	= serial_platform_data,
+	},
+};
+
+static int __init footbridge_isa_init(void)
+{
+	return platform_device_register(&serial_device);
+}
+
+arch_initcall(footbridge_isa_init);
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
new file mode 100644
index 0000000..1e1dfd7
--- /dev/null
+++ b/arch/arm/mach-footbridge/netwinder-hw.c
@@ -0,0 +1,660 @@
+/*
+ * linux/arch/arm/mach-footbridge/netwinder-hw.c
+ *
+ * Netwinder machine fixup
+ *
+ * Copyright (C) 1998, 1999 Russell King, Phil Blundell
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <asm/hardware/dec21285.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+#include <asm/setup.h>
+
+#include <asm/mach/arch.h>
+
+#include "common.h"
+
+#define IRDA_IO_BASE		0x180
+#define GP1_IO_BASE		0x338
+#define GP2_IO_BASE		0x33a
+
+
+#ifdef CONFIG_LEDS
+#define DEFAULT_LEDS	0
+#else
+#define DEFAULT_LEDS	GPIO_GREEN_LED
+#endif
+
+/*
+ * Winbond WB83977F accessibility stuff
+ */
+static inline void wb977_open(void)
+{
+	outb(0x87, 0x370);
+	outb(0x87, 0x370);
+}
+
+static inline void wb977_close(void)
+{
+	outb(0xaa, 0x370);
+}
+
+static inline void wb977_wb(int reg, int val)
+{
+	outb(reg, 0x370);
+	outb(val, 0x371);
+}
+
+static inline void wb977_ww(int reg, int val)
+{
+	outb(reg, 0x370);
+	outb(val >> 8, 0x371);
+	outb(reg + 1, 0x370);
+	outb(val & 255, 0x371);
+}
+
+#define wb977_device_select(dev)	wb977_wb(0x07, dev)
+#define wb977_device_disable()		wb977_wb(0x30, 0x00)
+#define wb977_device_enable()		wb977_wb(0x30, 0x01)
+
+/*
+ * This is a lock for accessing ports GP1_IO_BASE and GP2_IO_BASE
+ */
+DEFINE_SPINLOCK(gpio_lock);
+
+static unsigned int current_gpio_op;
+static unsigned int current_gpio_io;
+static unsigned int current_cpld;
+
+void gpio_modify_op(int mask, int set)
+{
+	unsigned int new_gpio, changed;
+
+	new_gpio = (current_gpio_op & ~mask) | set;
+	changed = new_gpio ^ current_gpio_op;
+	current_gpio_op = new_gpio;
+
+	if (changed & 0xff)
+		outb(new_gpio, GP1_IO_BASE);
+	if (changed & 0xff00)
+		outb(new_gpio >> 8, GP2_IO_BASE);
+}
+
+static inline void __gpio_modify_io(int mask, int in)
+{
+	unsigned int new_gpio, changed;
+	int port;
+
+	new_gpio = (current_gpio_io & ~mask) | in;
+	changed = new_gpio ^ current_gpio_io;
+	current_gpio_io = new_gpio;
+
+	changed >>= 1;
+	new_gpio >>= 1;
+
+	wb977_device_select(7);
+
+	for (port = 0xe1; changed && port < 0xe8; changed >>= 1) {
+		wb977_wb(port, new_gpio & 1);
+
+		port += 1;
+		new_gpio >>= 1;
+	}
+
+	wb977_device_select(8);
+
+	for (port = 0xe8; changed && port < 0xec; changed >>= 1) {
+		wb977_wb(port, new_gpio & 1);
+
+		port += 1;
+		new_gpio >>= 1;
+	}
+}
+
+void gpio_modify_io(int mask, int in)
+{
+	/* Open up the SuperIO chip */
+	wb977_open();
+
+	__gpio_modify_io(mask, in);
+
+	/* Close up the EFER gate */
+	wb977_close();
+}
+
+int gpio_read(void)
+{
+	return inb(GP1_IO_BASE) | inb(GP2_IO_BASE) << 8;
+}
+
+/*
+ * Initialise the Winbond W83977F global registers
+ */
+static inline void wb977_init_global(void)
+{
+	/*
+	 * Enable R/W config registers
+	 */
+	wb977_wb(0x26, 0x40);
+
+	/*
+	 * Power down FDC (not used)
+	 */
+	wb977_wb(0x22, 0xfe);
+
+	/*
+	 * GP12, GP11, CIRRX, IRRXH, GP10
+	 */
+	wb977_wb(0x2a, 0xc1);
+
+	/*
+	 * GP23, GP22, GP21, GP20, GP13
+	 */
+	wb977_wb(0x2b, 0x6b);
+
+	/*
+	 * GP17, GP16, GP15, GP14
+	 */
+	wb977_wb(0x2c, 0x55);
+}
+
+/*
+ * Initialise the Winbond W83977F printer port
+ */
+static inline void wb977_init_printer(void)
+{
+	wb977_device_select(1);
+
+	/*
+	 * mode 1 == EPP
+	 */
+	wb977_wb(0xf0, 0x01);
+}
+
+/*
+ * Initialise the Winbond W83977F keyboard controller
+ */
+static inline void wb977_init_keyboard(void)
+{
+	wb977_device_select(5);
+
+	/*
+	 * Keyboard controller address
+	 */
+	wb977_ww(0x60, 0x0060);
+	wb977_ww(0x62, 0x0064);
+
+	/*
+	 * Keyboard IRQ 1, active high, edge trigger
+	 */
+	wb977_wb(0x70, 1);
+	wb977_wb(0x71, 0x02);
+
+	/*
+	 * Mouse IRQ 5, active high, edge trigger
+	 */
+	wb977_wb(0x72, 5);
+	wb977_wb(0x73, 0x02);
+
+	/*
+	 * KBC 8MHz
+	 */
+	wb977_wb(0xf0, 0x40);
+
+	/*
+	 * Enable device
+	 */
+	wb977_device_enable();
+}
+
+/*
+ * Initialise the Winbond W83977F Infra-Red device
+ */
+static inline void wb977_init_irda(void)
+{
+	wb977_device_select(6);
+
+	/*
+	 * IR base address
+	 */
+	wb977_ww(0x60, IRDA_IO_BASE);
+
+	/*
+	 * IRDA IRQ 6, active high, edge trigger
+	 */
+	wb977_wb(0x70, 6);
+	wb977_wb(0x71, 0x02);
+
+	/*
+	 * RX DMA - ISA DMA 0
+	 */
+	wb977_wb(0x74, 0x00);
+
+	/*
+	 * TX DMA - Disable Tx DMA
+	 */
+	wb977_wb(0x75, 0x04);
+
+	/*
+	 * Append CRC, Enable bank selection
+	 */
+	wb977_wb(0xf0, 0x03);
+
+	/*
+	 * Enable device
+	 */
+	wb977_device_enable();
+}
+
+/*
+ * Initialise Winbond W83977F general purpose IO
+ */
+static inline void wb977_init_gpio(void)
+{
+	unsigned long flags;
+
+	/*
+	 * Set up initial I/O definitions
+	 */
+	current_gpio_io = -1;
+	__gpio_modify_io(-1, GPIO_DONE | GPIO_WDTIMER);
+
+	wb977_device_select(7);
+
+	/*
+	 * Group1 base address
+	 */
+	wb977_ww(0x60, GP1_IO_BASE);
+	wb977_ww(0x62, 0);
+	wb977_ww(0x64, 0);
+
+	/*
+	 * GP10 (Orage button) IRQ 10, active high, edge trigger
+	 */
+	wb977_wb(0x70, 10);
+	wb977_wb(0x71, 0x02);
+
+	/*
+	 * GP10: Debounce filter enabled, IRQ, input
+	 */
+	wb977_wb(0xe0, 0x19);
+
+	/*
+	 * Enable Group1
+	 */
+	wb977_device_enable();
+
+	wb977_device_select(8);
+
+	/*
+	 * Group2 base address
+	 */
+	wb977_ww(0x60, GP2_IO_BASE);
+
+	/*
+	 * Clear watchdog timer regs
+	 *  - timer disable
+	 */
+	wb977_wb(0xf2, 0x00);
+
+	/*
+	 *  - disable LED, no mouse nor keyboard IRQ
+	 */
+	wb977_wb(0xf3, 0x00);
+
+	/*
+	 *  - timer counting, disable power LED, disable timeouot
+	 */
+	wb977_wb(0xf4, 0x00);
+
+	/*
+	 * Enable group2
+	 */
+	wb977_device_enable();
+
+	/*
+	 * Set Group1/Group2 outputs
+	 */
+	spin_lock_irqsave(&gpio_lock, flags);
+	gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN);
+	spin_unlock_irqrestore(&gpio_lock, flags);
+}
+
+/*
+ * Initialise the Winbond W83977F chip.
+ */
+static void __init wb977_init(void)
+{
+	request_region(0x370, 2, "W83977AF configuration");
+
+	/*
+	 * Open up the SuperIO chip
+	 */
+	wb977_open();
+
+	/*
+	 * Initialise the global registers
+	 */
+	wb977_init_global();
+
+	/*
+	 * Initialise the various devices in
+	 * the multi-IO chip.
+	 */
+	wb977_init_printer();
+	wb977_init_keyboard();
+	wb977_init_irda();
+	wb977_init_gpio();
+
+	/*
+	 * Close up the EFER gate
+	 */
+	wb977_close();
+}
+
+void cpld_modify(int mask, int set)
+{
+	int msk;
+
+	current_cpld = (current_cpld & ~mask) | set;
+
+	gpio_modify_io(GPIO_DATA | GPIO_IOCLK | GPIO_IOLOAD, 0);
+	gpio_modify_op(GPIO_IOLOAD, 0);
+
+	for (msk = 8; msk; msk >>= 1) {
+		int bit = current_cpld & msk;
+
+		gpio_modify_op(GPIO_DATA | GPIO_IOCLK, bit ? GPIO_DATA : 0);
+		gpio_modify_op(GPIO_IOCLK, GPIO_IOCLK);
+	}
+
+	gpio_modify_op(GPIO_IOCLK|GPIO_DATA, 0);
+	gpio_modify_op(GPIO_IOLOAD|GPIO_DSCLK, GPIO_IOLOAD|GPIO_DSCLK);
+	gpio_modify_op(GPIO_IOLOAD, 0);
+}
+
+static void __init cpld_init(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+	cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE);
+	spin_unlock_irqrestore(&gpio_lock, flags);
+}
+
+static unsigned char rwa_unlock[] __initdata =
+{ 0x00, 0x00, 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b,
+  0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, 0xe8, 0x74,
+  0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 };
+
+#ifndef DEBUG
+#define dprintk(x...)
+#else
+#define dprintk(x...) printk(x)
+#endif
+
+#define WRITE_RWA(r,v) do { outb((r), 0x279); udelay(10); outb((v), 0xa79); } while (0)
+
+static inline void rwa010_unlock(void)
+{
+	int i;
+
+	WRITE_RWA(2, 2);
+	mdelay(10);
+
+	for (i = 0; i < sizeof(rwa_unlock); i++) {
+		outb(rwa_unlock[i], 0x279);
+		udelay(10);
+	}
+}
+
+static inline void rwa010_read_ident(void)
+{
+	unsigned char si[9];
+	int i, j;
+
+	WRITE_RWA(3, 0);
+	WRITE_RWA(0, 128);
+
+	outb(1, 0x279);
+
+	mdelay(1);
+
+	dprintk("Identifier: ");
+	for (i = 0; i < 9; i++) {
+		si[i] = 0;
+		for (j = 0; j < 8; j++) {
+			int bit;
+			udelay(250);
+			inb(0x203);
+			udelay(250);
+			bit = inb(0x203);
+			dprintk("%02X ", bit);
+			bit = (bit == 0xaa) ? 1 : 0;
+			si[i] |= bit << j;
+		}
+		dprintk("(%02X) ", si[i]);
+	}
+	dprintk("\n");
+}
+
+static inline void rwa010_global_init(void)
+{
+	WRITE_RWA(6, 2);	// Assign a card no = 2
+
+	dprintk("Card no = %d\n", inb(0x203));
+
+	/* disable the modem section of the chip */
+	WRITE_RWA(7, 3);
+	WRITE_RWA(0x30, 0);
+
+	/* disable the cdrom section of the chip */
+	WRITE_RWA(7, 4);
+	WRITE_RWA(0x30, 0);
+
+	/* disable the MPU-401 section of the chip */
+	WRITE_RWA(7, 2);
+	WRITE_RWA(0x30, 0);
+}
+
+static inline void rwa010_game_port_init(void)
+{
+	int i;
+
+	WRITE_RWA(7, 5);
+
+	dprintk("Slider base: ");
+	WRITE_RWA(0x61, 1);
+	i = inb(0x203);
+
+	WRITE_RWA(0x60, 2);
+	dprintk("%02X%02X (201)\n", inb(0x203), i);
+
+	WRITE_RWA(0x30, 1);
+}
+
+static inline void rwa010_waveartist_init(int base, int irq, int dma)
+{
+	int i;
+
+	WRITE_RWA(7, 0);
+
+	dprintk("WaveArtist base: ");
+	WRITE_RWA(0x61, base & 255);
+	i = inb(0x203);
+
+	WRITE_RWA(0x60, base >> 8);
+	dprintk("%02X%02X (%X),", inb(0x203), i, base);
+
+	WRITE_RWA(0x70, irq);
+	dprintk(" irq: %d (%d),", inb(0x203), irq);
+
+	WRITE_RWA(0x74, dma);
+	dprintk(" dma: %d (%d)\n", inb(0x203), dma);
+
+	WRITE_RWA(0x30, 1);
+}
+
+static inline void rwa010_soundblaster_init(int sb_base, int al_base, int irq, int dma)
+{
+	int i;
+
+	WRITE_RWA(7, 1);
+
+	dprintk("SoundBlaster base: ");
+	WRITE_RWA(0x61, sb_base & 255);
+	i = inb(0x203);
+
+	WRITE_RWA(0x60, sb_base >> 8);
+	dprintk("%02X%02X (%X),", inb(0x203), i, sb_base);
+
+	dprintk(" irq: ");
+	WRITE_RWA(0x70, irq);
+	dprintk("%d (%d),", inb(0x203), irq);
+
+	dprintk(" 8-bit DMA: ");
+	WRITE_RWA(0x74, dma);
+	dprintk("%d (%d)\n", inb(0x203), dma);
+
+	dprintk("AdLib base: ");
+	WRITE_RWA(0x63, al_base & 255);
+	i = inb(0x203);
+
+	WRITE_RWA(0x62, al_base >> 8);
+	dprintk("%02X%02X (%X)\n", inb(0x203), i, al_base);
+
+	WRITE_RWA(0x30, 1);
+}
+
+static void rwa010_soundblaster_reset(void)
+{
+	int i;
+
+	outb(1, 0x226);
+	udelay(3);
+	outb(0, 0x226);
+
+	for (i = 0; i < 5; i++) {
+		if (inb(0x22e) & 0x80)
+			break;
+		mdelay(1);
+	}
+	if (i == 5)
+		printk("SoundBlaster: DSP reset failed\n");
+
+	dprintk("SoundBlaster DSP reset: %02X (AA)\n", inb(0x22a));
+
+	for (i = 0; i < 5; i++) {
+		if ((inb(0x22c) & 0x80) == 0)
+			break;
+		mdelay(1);
+	}
+
+	if (i == 5)
+		printk("SoundBlaster: DSP not ready\n");
+	else {
+		outb(0xe1, 0x22c);
+
+		dprintk("SoundBlaster DSP id: ");
+		i = inb(0x22a);
+		udelay(1);
+		i |= inb(0x22a) << 8;
+		dprintk("%04X\n", i);
+
+		for (i = 0; i < 5; i++) {
+			if ((inb(0x22c) & 0x80) == 0)
+				break;
+			mdelay(1);
+		}
+
+		if (i == 5)
+			printk("SoundBlaster: could not turn speaker off\n");
+
+		outb(0xd3, 0x22c);
+	}
+
+	/* turn on OPL3 */
+	outb(5, 0x38a);
+	outb(1, 0x38b);
+}
+
+static void __init rwa010_init(void)
+{
+	rwa010_unlock();
+	rwa010_read_ident();
+	rwa010_global_init();
+	rwa010_game_port_init();
+	rwa010_waveartist_init(0x250, 3, 7);
+	rwa010_soundblaster_init(0x220, 0x388, 3, 1);
+	rwa010_soundblaster_reset();
+}
+
+EXPORT_SYMBOL(gpio_lock);
+EXPORT_SYMBOL(gpio_modify_op);
+EXPORT_SYMBOL(gpio_modify_io);
+EXPORT_SYMBOL(cpld_modify);
+
+/*
+ * Initialise any other hardware after we've got the PCI bus
+ * initialised.  We may need the PCI bus to talk to this other
+ * hardware.
+ */
+static int __init nw_hw_init(void)
+{
+	if (machine_is_netwinder()) {
+		unsigned long flags;
+
+		wb977_init();
+		cpld_init();
+		rwa010_init();
+
+		spin_lock_irqsave(&gpio_lock, flags);
+		gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS);
+		spin_unlock_irqrestore(&gpio_lock, flags);
+	}
+	return 0;
+}
+
+__initcall(nw_hw_init);
+
+/*
+ * Older NeTTroms either do not provide a parameters
+ * page, or they don't supply correct information in
+ * the parameter page.
+ */
+static void __init
+fixup_netwinder(struct machine_desc *desc, struct tag *tags,
+		char **cmdline, struct meminfo *mi)
+{
+#ifdef CONFIG_ISAPNP
+	extern int isapnp_disable;
+
+	/*
+	 * We must not use the kernels ISAPnP code
+	 * on the NetWinder - it will reset the settings
+	 * for the WaveArtist chip and render it inoperable.
+	 */
+	isapnp_disable = 1;
+#endif
+}
+
+MACHINE_START(NETWINDER, "Rebel-NetWinder")
+	MAINTAINER("Russell King/Rebel.com")
+	BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
+	BOOT_PARAMS(0x00000100)
+	VIDEO(0x000a0000, 0x000bffff)
+	DISABLE_PARPORT(0)
+	DISABLE_PARPORT(2)
+	FIXUP(fixup_netwinder)
+	MAPIO(footbridge_map_io)
+	INITIRQ(footbridge_init_irq)
+	.timer		= &isa_timer,
+MACHINE_END
diff --git a/arch/arm/mach-footbridge/netwinder-leds.c b/arch/arm/mach-footbridge/netwinder-leds.c
new file mode 100644
index 0000000..7451fc0
--- /dev/null
+++ b/arch/arm/mach-footbridge/netwinder-leds.c
@@ -0,0 +1,141 @@
+/*
+ *  linux/arch/arm/mach-footbridge/netwinder-leds.c
+ *
+ *  Copyright (C) 1998-1999 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * NetWinder LED control routines.
+ *
+ * The Netwinder uses the leds as follows:
+ *  - Green - toggles state every 50 timer interrupts
+ *  - Red   - On if the system is not idle
+ *
+ * Changelog:
+ *   02-05-1999	RMK	Various cleanups
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+#include <asm/system.h>
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+static char led_state;
+static char hw_led_state;
+
+static DEFINE_SPINLOCK(leds_lock);
+extern spinlock_t gpio_lock;
+
+static void netwinder_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&leds_lock, flags);
+
+	switch (evt) {
+	case led_start:
+		led_state |= LED_STATE_ENABLED;
+		hw_led_state = GPIO_GREEN_LED;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = 0;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = 0;
+		break;
+
+#ifdef CONFIG_LEDS_TIMER
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= GPIO_GREEN_LED;
+		break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~GPIO_RED_LED;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= GPIO_RED_LED;
+		break;
+#endif
+
+	case led_halted:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= GPIO_RED_LED;
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= GPIO_GREEN_LED;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~GPIO_GREEN_LED;
+		break;
+
+	case led_amber_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= GPIO_GREEN_LED | GPIO_RED_LED;
+		break;
+
+	case led_amber_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~(GPIO_GREEN_LED | GPIO_RED_LED);
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= GPIO_RED_LED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~GPIO_RED_LED;
+		break;
+
+	default:
+		break;
+	}
+
+	spin_unlock_irqrestore(&leds_lock, flags);
+
+	if  (led_state & LED_STATE_ENABLED) {
+		spin_lock_irqsave(&gpio_lock, flags);
+		gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state);
+		spin_unlock_irqrestore(&gpio_lock, flags);
+	}
+}
+
+static int __init leds_init(void)
+{
+	if (machine_is_netwinder())
+		leds_event = netwinder_leds_event;
+
+	leds_event(led_start);
+
+	return 0;
+}
+
+__initcall(leds_init);
diff --git a/arch/arm/mach-footbridge/netwinder-pci.c b/arch/arm/mach-footbridge/netwinder-pci.c
new file mode 100644
index 0000000..e263d6d
--- /dev/null
+++ b/arch/arm/mach-footbridge/netwinder-pci.c
@@ -0,0 +1,62 @@
+/*
+ * linux/arch/arm/mach-footbridge/netwinder-pci.c
+ *
+ * PCI bios-type initialisation for PCI machines
+ *
+ * Bits taken from various places.
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+/*
+ * We now use the slot ID instead of the device identifiers to select
+ * which interrupt is routed where.
+ */
+static int __init netwinder_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	switch (slot) {
+	case 0:  /* host bridge */
+		return 0;
+
+	case 9:  /* CyberPro */
+		return IRQ_NETWINDER_VGA;
+
+	case 10: /* DC21143 */
+		return IRQ_NETWINDER_ETHER100;
+
+	case 12: /* Winbond 553 */
+		return IRQ_ISA_HARDDISK1;
+
+	case 13: /* Winbond 89C940F */
+		return IRQ_NETWINDER_ETHER10;
+
+	default:
+		printk(KERN_ERR "PCI: unknown device in slot %s\n",
+			pci_name(dev));
+		return 0;
+	}
+}
+
+static struct hw_pci netwinder_pci __initdata = {
+	.swizzle		= pci_std_swizzle,
+	.map_irq		= netwinder_map_irq,
+	.nr_controllers		= 1,
+	.setup			= dc21285_setup,
+	.scan			= dc21285_scan_bus,
+	.preinit		= dc21285_preinit,
+	.postinit		= dc21285_postinit,
+};
+
+static int __init netwinder_pci_init(void)
+{
+	if (machine_is_netwinder())
+		pci_common_init(&netwinder_pci);
+	return 0;
+}
+
+subsys_initcall(netwinder_pci_init);
diff --git a/arch/arm/mach-footbridge/personal-pci.c b/arch/arm/mach-footbridge/personal-pci.c
new file mode 100644
index 0000000..d5fca95
--- /dev/null
+++ b/arch/arm/mach-footbridge/personal-pci.c
@@ -0,0 +1,56 @@
+/*
+ * linux/arch/arm/mach-footbridge/personal-pci.c
+ *
+ * PCI bios-type initialisation for PCI machines
+ *
+ * Bits taken from various places.
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+static int irqmap_personal_server[] __initdata = {
+	IRQ_IN0, IRQ_IN1, IRQ_IN2, IRQ_IN3, 0, 0, 0,
+	IRQ_DOORBELLHOST, IRQ_DMA1, IRQ_DMA2, IRQ_PCI
+};
+
+static int __init personal_server_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	unsigned char line;
+
+	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line);
+
+	if (line > 0x40 && line <= 0x5f) {
+		/* line corresponds to the bit controlling this interrupt
+		 * in the footbridge.  Ignore the first 8 interrupt bits,
+		 * look up the rest in the map.  IN0 is bit number 8
+		 */
+		return irqmap_personal_server[(line & 0x1f) - 8];
+	} else if (line == 0) {
+		/* no interrupt */
+		return 0;
+	} else
+		return irqmap_personal_server[(line - 1) & 3];
+}
+
+static struct hw_pci personal_server_pci __initdata = {
+	.map_irq		= personal_server_map_irq,
+	.nr_controllers		= 1,
+	.setup			= dc21285_setup,
+	.scan			= dc21285_scan_bus,
+	.preinit		= dc21285_preinit,
+	.postinit		= dc21285_postinit,
+};
+
+static int __init personal_pci_init(void)
+{
+	if (machine_is_personal_server())
+		pci_common_init(&personal_server_pci);
+	return 0;
+}
+
+subsys_initcall(personal_pci_init);
diff --git a/arch/arm/mach-footbridge/personal.c b/arch/arm/mach-footbridge/personal.c
new file mode 100644
index 0000000..415086d
--- /dev/null
+++ b/arch/arm/mach-footbridge/personal.c
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-footbridge/personal.c
+ *
+ * Personal server (Skiff) machine fixup
+ */
+#include <linux/init.h>
+
+#include <asm/hardware/dec21285.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+
+#include "common.h"
+
+MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer")
+	MAINTAINER("Jamey Hicks / George France")
+	BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
+	BOOT_PARAMS(0x00000100)
+	MAPIO(footbridge_map_io)
+	INITIRQ(footbridge_init_irq)
+	.timer		= &footbridge_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-footbridge/time.c b/arch/arm/mach-footbridge/time.c
new file mode 100644
index 0000000..2c64a0b
--- /dev/null
+++ b/arch/arm/mach-footbridge/time.c
@@ -0,0 +1,180 @@
+/*
+ *  linux/include/asm-arm/arch-ebsa285/time.h
+ *
+ *  Copyright (C) 1998 Russell King.
+ *  Copyright (C) 1998 Phil Blundell
+ *
+ * CATS has a real-time clock, though the evaluation board doesn't.
+ *
+ * Changelog:
+ *  21-Mar-1998	RMK	Created
+ *  27-Aug-1998	PJB	CATS support
+ *  28-Dec-1998	APH	Made leds optional
+ *  20-Jan-1999	RMK	Started merge of EBSA285, CATS and NetWinder
+ *  16-Mar-1999	RMK	More support for EBSA285-like machines with RTCs in
+ */
+
+#define RTC_PORT(x)		(rtc_base+(x))
+#define RTC_ALWAYS_BCD		0
+
+#include <linux/timex.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mc146818rtc.h>
+#include <linux/bcd.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/mach/time.h>
+#include "common.h"
+
+static int rtc_base;
+
+static unsigned long __init get_isa_cmos_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	int i;
+
+	// check to see if the RTC makes sense.....
+	if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0)
+		return mktime(1970, 1, 1, 0, 0, 0);
+
+	/* The Linux interpretation of the CMOS clock register contents:
+	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+	 * RTC registers show the second which has precisely just started.
+	 * Let's hope other operating systems interpret the RTC the same way.
+	 */
+	/* read RTC exactly on falling edge of update flag */
+	for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
+		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+			break;
+
+	for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
+		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+			break;
+
+	do { /* Isn't this overkill ? UIP above should guarantee consistency */
+		sec  = CMOS_READ(RTC_SECONDS);
+		min  = CMOS_READ(RTC_MINUTES);
+		hour = CMOS_READ(RTC_HOURS);
+		day  = CMOS_READ(RTC_DAY_OF_MONTH);
+		mon  = CMOS_READ(RTC_MONTH);
+		year = CMOS_READ(RTC_YEAR);
+	} while (sec != CMOS_READ(RTC_SECONDS));
+
+	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+		BCD_TO_BIN(sec);
+		BCD_TO_BIN(min);
+		BCD_TO_BIN(hour);
+		BCD_TO_BIN(day);
+		BCD_TO_BIN(mon);
+		BCD_TO_BIN(year);
+	}
+	if ((year += 1900) < 1970)
+		year += 100;
+	return mktime(year, mon, day, hour, min, sec);
+}
+
+static int set_isa_cmos_time(void)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+	unsigned char save_control, save_freq_select;
+	unsigned long nowtime = xtime.tv_sec;
+
+	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+	cmos_minutes = CMOS_READ(RTC_MINUTES);
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+		BCD_TO_BIN(cmos_minutes);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;		/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+			BIN_TO_BCD(real_seconds);
+			BIN_TO_BCD(real_minutes);
+		}
+		CMOS_WRITE(real_seconds,RTC_SECONDS);
+		CMOS_WRITE(real_minutes,RTC_MINUTES);
+	} else
+		retval = -1;
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+	return retval;
+}
+
+void __init isa_rtc_init(void)
+{
+	if (machine_is_co285() ||
+	    machine_is_personal_server())
+		/*
+		 * Add-in 21285s shouldn't access the RTC
+		 */
+		rtc_base = 0;
+	else
+		rtc_base = 0x70;
+
+	if (rtc_base) {
+		int reg_d, reg_b;
+
+		/*
+		 * Probe for the RTC.
+		 */
+		reg_d = CMOS_READ(RTC_REG_D);
+
+		/*
+		 * make sure the divider is set
+		 */
+		CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_REG_A);
+
+		/*
+		 * Set control reg B
+		 *   (24 hour mode, update enabled)
+		 */
+		reg_b = CMOS_READ(RTC_REG_B) & 0x7f;
+		reg_b |= 2;
+		CMOS_WRITE(reg_b, RTC_REG_B);
+
+		if ((CMOS_READ(RTC_REG_A) & 0x7f) == RTC_REF_CLCK_32KHZ &&
+		    CMOS_READ(RTC_REG_B) == reg_b) {
+			struct timespec tv;
+
+			/*
+			 * We have a RTC.  Check the battery
+			 */
+			if ((reg_d & 0x80) == 0)
+				printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n");
+
+			tv.tv_nsec = 0;
+			tv.tv_sec = get_isa_cmos_time();
+			do_settimeofday(&tv);
+			set_rtc = set_isa_cmos_time;
+		} else
+			rtc_base = 0;
+	}
+}