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/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
new file mode 100644
index 0000000..a0612a8
--- /dev/null
+++ b/arch/ppc/platforms/4xx/Kconfig
@@ -0,0 +1,247 @@
+config 4xx
+	bool
+	depends on 40x || 44x
+	default y
+
+menu "IBM 4xx options"
+	depends on 4xx
+
+choice
+	prompt "Machine Type"
+	depends on 40x
+	default WALNUT
+
+config ASH
+	bool "Ash"
+	help
+	  This option enables support for the IBM NP405H evaluation board.
+
+config BUBINGA
+	bool "Bubinga"
+	help
+	  This option enables support for the IBM 405EP evaluation board.
+
+config CPCI405
+	bool "CPCI405"
+	help
+	  This option enables support for the CPCI405 board.
+
+config EP405
+	bool "EP405/EP405PC"
+	help
+	  This option enables support for the EP405/EP405PC boards.
+
+config OAK
+	bool "Oak"
+	help
+	  This option enables support for the IBM 403GCX evaluation board.
+
+config REDWOOD_5
+	bool "Redwood-5"
+	help
+	  This option enables support for the IBM STB04 evaluation board.
+
+config REDWOOD_6
+	bool "Redwood-6"
+	help
+	  This option enables support for the IBM STBx25xx evaluation board.
+
+config SYCAMORE
+	bool "Sycamore"
+	help
+	  This option enables support for the IBM PPC405GPr evaluation board.
+
+config WALNUT
+	bool "Walnut"
+	help
+	  This option enables support for the IBM PPC405GP evaluation board.
+
+config XILINX_ML300
+	bool "Xilinx-ML300"
+	help
+	  This option enables support for the Xilinx ML300 evaluation board.
+
+endchoice
+
+choice
+	prompt "Machine Type"
+	depends on 44x
+	default EBONY
+
+config EBONY
+	bool "Ebony"
+	help
+	  This option enables support for the IBM PPC440GP evaluation board.
+
+config LUAN
+	bool "Luan"
+	help
+	  This option enables support for the IBM PPC440SP evaluation board.
+
+config OCOTEA
+	bool "Ocotea"
+	help
+	  This option enables support for the IBM PPC440GX evaluation board.
+
+endchoice
+
+config EP405PC
+	bool "EP405PC Support"
+	depends on EP405
+
+
+# It's often necessary to know the specific 4xx processor type.
+# Fortunately, it is impled (so far) from the board type, so we
+# don't need to ask more redundant questions.
+config NP405H
+	bool
+	depends on ASH
+	default y
+
+config 440GP
+	bool
+	depends on EBONY
+	default y
+
+config 440GX
+	bool
+	depends on OCOTEA
+	default y
+
+config 440SP
+	bool
+	depends on LUAN
+	default y
+
+config 440
+	bool
+	depends on 440GP || 440SP
+	default y
+
+config 440A
+	bool
+	depends on 440GX
+	default y
+
+# All 405-based cores up until the 405GPR and 405EP have this errata.
+config IBM405_ERR77
+	bool
+	depends on 40x && !403GCX && !405GPR
+	default y
+
+# All 40x-based cores, up until the 405GPR and 405EP have this errata.
+config IBM405_ERR51
+	bool
+	depends on 40x && !405GPR
+	default y
+
+config BOOKE
+	bool
+	depends on 44x
+	default y
+
+config IBM_OCP
+	bool
+	depends on ASH || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
+	default y
+
+config XILINX_OCP
+	bool
+	depends on XILINX_ML300
+	default y
+
+config IBM_EMAC4
+	bool
+	depends on 440GX || 440SP
+	default y
+
+config BIOS_FIXUP
+	bool
+	depends on BUBINGA || EP405 || SYCAMORE || WALNUT
+	default y
+
+config 403GCX
+	bool
+	depends OAK
+	default y
+
+config 405EP
+	bool
+	depends on BUBINGA
+	default y
+
+config 405GP
+	bool
+	depends on CPCI405 || EP405 || WALNUT
+	default y
+
+config 405GPR
+	bool
+	depends on SYCAMORE
+	default y
+
+config VIRTEX_II_PRO
+	bool
+	depends on XILINX_ML300
+	default y
+
+config STB03xxx
+	bool
+	depends on REDWOOD_5 || REDWOOD_6
+	default y
+
+config EMBEDDEDBOOT
+	bool
+	depends on EP405 || XILINX_ML300
+	default y
+
+config IBM_OPENBIOS
+	bool
+	depends on ASH || BUBINGA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
+	default y
+
+config PPC4xx_DMA
+	bool "PPC4xx DMA controller support"
+	depends on 4xx
+
+config PPC4xx_EDMA
+	bool
+	depends on !STB03xxx && PPC4xx_DMA
+	default y
+
+config PPC_GEN550
+	bool
+	depends on 4xx
+	default y
+
+config PM
+	bool "Power Management support (EXPERIMENTAL)"
+	depends on 4xx && EXPERIMENTAL
+
+choice
+	prompt "TTYS0 device and default console"
+	depends on 40x
+	default UART0_TTYS0
+
+config UART0_TTYS0
+	bool "UART0"
+
+config UART0_TTYS1
+	bool "UART1"
+
+endchoice
+
+config SERIAL_SICC
+	bool "SICC Serial port support"
+	depends on STB03xxx
+
+config UART1_DFLT_CONSOLE
+	bool
+	depends on SERIAL_SICC && UART0_TTYS1
+	default y
+
+config SERIAL_SICC_CONSOLE
+	bool
+	depends on SERIAL_SICC && UART0_TTYS1
+	default y
+endmenu
diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile
new file mode 100644
index 0000000..ea470c6
--- /dev/null
+++ b/arch/ppc/platforms/4xx/Makefile
@@ -0,0 +1,27 @@
+#
+# Makefile for the PowerPC 4xx linux kernel.
+
+obj-$(CONFIG_ASH)		+= ash.o
+obj-$(CONFIG_CPCI405)		+= cpci405.o
+obj-$(CONFIG_EBONY)		+= ebony.o
+obj-$(CONFIG_EP405)		+= ep405.o
+obj-$(CONFIG_BUBINGA)		+= bubinga.o
+obj-$(CONFIG_LUAN)		+= luan.o
+obj-$(CONFIG_OAK)		+= oak.o
+obj-$(CONFIG_OCOTEA)		+= ocotea.o
+obj-$(CONFIG_REDWOOD_5)		+= redwood5.o
+obj-$(CONFIG_REDWOOD_6)		+= redwood6.o
+obj-$(CONFIG_SYCAMORE)		+= sycamore.o
+obj-$(CONFIG_WALNUT)		+= walnut.o
+obj-$(CONFIG_XILINX_ML300)	+= xilinx_ml300.o
+
+obj-$(CONFIG_405GP)		+= ibm405gp.o
+obj-$(CONFIG_REDWOOD_5)		+= ibmstb4.o
+obj-$(CONFIG_NP405H)		+= ibmnp405h.o
+obj-$(CONFIG_REDWOOD_6)		+= ibmstbx25.o
+obj-$(CONFIG_440GP)		+= ibm440gp.o
+obj-$(CONFIG_440GX)		+= ibm440gx.o
+obj-$(CONFIG_440SP)		+= ibm440sp.o
+obj-$(CONFIG_405EP)		+= ibm405ep.o
+obj-$(CONFIG_405GPR)		+= ibm405gpr.o
+obj-$(CONFIG_VIRTEX_II_PRO)	+= virtex-ii_pro.o
diff --git a/arch/ppc/platforms/4xx/ash.c b/arch/ppc/platforms/4xx/ash.c
new file mode 100644
index 0000000..ce29117
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ash.c
@@ -0,0 +1,250 @@
+/*
+ * arch/ppc/platforms/4xx/ash.c
+ *
+ * Support for the IBM NP405H ash eval board
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2001-2002 (c) MontaVista, Software, Inc.  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/init.h>
+#include <linux/pagemap.h>
+#include <linux/pci.h>
+
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/io.h>
+#include <asm/ocp.h>
+#include <asm/ibm_ocp_pci.h>
+#include <asm/todc.h>
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+void *ash_rtc_base;
+
+/* Some IRQs unique to Walnut.
+ * Used by the generic 405 PCI setup functions in ppc4xx_pci.c
+ */
+int __init
+ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	    /*
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *      A       B       C       D
+	     */
+	{
+		{24, 24, 24, 24},	/* IDSEL 1 - PCI slot 1 */
+		{25, 25, 25, 25},	/* IDSEL 2 - PCI slot 2 */
+		{26, 26, 26, 26},	/* IDSEL 3 - PCI slot 3 */
+		{27, 27, 27, 27},	/* IDSEL 4 - PCI slot 4 */
+	};
+
+	const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+void __init
+ash_setup_arch(void)
+{
+	ppc4xx_setup_arch();
+
+	ibm_ocp_set_emac(0, 3);
+
+#ifdef CONFIG_DEBUG_BRINGUP
+	int i;
+	printk("\n");
+	printk("machine\t: %s\n", PPC4xx_MACHINE_NAME);
+	printk("\n");
+	printk("bi_s_version\t %s\n", bip->bi_s_version);
+	printk("bi_r_version\t %s\n", bip->bi_r_version);
+	printk("bi_memsize\t 0x%8.8x\t %dMBytes\n", bip->bi_memsize,
+	       bip->bi_memsize / (1024 * 1000));
+	for (i = 0; i < EMAC_NUMS; i++) {
+		printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", i,
+		       bip->bi_enetaddr[i][0], bip->bi_enetaddr[i][1],
+		       bip->bi_enetaddr[i][2], bip->bi_enetaddr[i][3],
+		       bip->bi_enetaddr[i][4], bip->bi_enetaddr[i][5]);
+	}
+	printk("bi_pci_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 0,
+	       bip->bi_pci_enetaddr[0], bip->bi_pci_enetaddr[1],
+	       bip->bi_pci_enetaddr[2], bip->bi_pci_enetaddr[3],
+	       bip->bi_pci_enetaddr[4], bip->bi_pci_enetaddr[5]);
+
+	printk("bi_intfreq\t 0x%8.8x\t clock:\t %dMhz\n",
+	       bip->bi_intfreq, bip->bi_intfreq / 1000000);
+
+	printk("bi_busfreq\t 0x%8.8x\t plb bus clock:\t %dMHz\n",
+	       bip->bi_busfreq, bip->bi_busfreq / 1000000);
+	printk("bi_pci_busfreq\t 0x%8.8x\t pci bus clock:\t %dMHz\n",
+	       bip->bi_pci_busfreq, bip->bi_pci_busfreq / 1000000);
+
+	printk("\n");
+#endif
+	/* RTC step for ash */
+	ash_rtc_base = (void *) ASH_RTC_VADDR;
+	TODC_INIT(TODC_TYPE_DS1743, ash_rtc_base, ash_rtc_base, ash_rtc_base,
+		  8);
+}
+
+void __init
+bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
+{
+	/*
+	 * Expected PCI mapping:
+	 *
+	 *  PLB addr             PCI memory addr
+	 *  ---------------------       ---------------------
+	 *  0000'0000 - 7fff'ffff <---  0000'0000 - 7fff'ffff
+	 *  8000'0000 - Bfff'ffff --->  8000'0000 - Bfff'ffff
+	 *
+	 *  PLB addr             PCI io addr
+	 *  ---------------------       ---------------------
+	 *  e800'0000 - e800'ffff --->  0000'0000 - 0001'0000
+	 *
+	 * The following code is simplified by assuming that the bootrom
+	 * has been well behaved in following this mapping.
+	 */
+
+#ifdef DEBUG
+	int i;
+
+	printk("ioremap PCLIO_BASE = 0x%x\n", pcip);
+	printk("PCI bridge regs before fixup \n");
+	for (i = 0; i <= 2; i++) {
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+		printk(" pmm%dla\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+		printk(" pmm%dpcila\t0x%x\n", i,
+		       in_le32(&(pcip->pmm[i].pcila)));
+		printk(" pmm%dpciha\t0x%x\n", i,
+		       in_le32(&(pcip->pmm[i].pciha)));
+	}
+	printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+	printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+	printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+	printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+	for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+		early_read_config_dword(hose, hose->first_busno,
+					PCI_FUNC(hose->first_busno), bar,
+					&bar_response);
+		DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
+		    hose->first_busno, PCI_SLOT(hose->first_busno),
+		    PCI_FUNC(hose->first_busno), bar, bar_response);
+	}
+
+#endif
+	if (ppc_md.progress)
+		ppc_md.progress("bios_fixup(): enter", 0x800);
+
+	/* added for IBM boot rom version 1.15 bios bar changes  -AK */
+
+	/* Disable region first */
+	out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
+	/* PLB starting addr, PCI: 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
+	/* PCI start addr, 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
+	/* 512MB range of PLB to PCI */
+	out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
+	/* Enable no pre-fetch, enable region */
+	out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
+						(PPC405_PCI_UPPER_MEM -
+						 PPC405_PCI_MEM_BASE)) | 0x01));
+
+	/* Disable region one */
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+
+	/* Disable region two */
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+
+	/* Enable PTM1 and PTM2, mapped to PLB address 0. */
+
+	out_le32((void *) &(pcip->ptm1la), 0x00000000);
+	out_le32((void *) &(pcip->ptm1ms), 0x00000001);
+	out_le32((void *) &(pcip->ptm2la), 0x00000000);
+	out_le32((void *) &(pcip->ptm2ms), 0x00000001);
+
+	/* Write zero to PTM1 BAR. */
+
+	early_write_config_dword(hose, hose->first_busno,
+				 PCI_FUNC(hose->first_busno),
+				 PCI_BASE_ADDRESS_1,
+				 0x00000000);
+
+	/* Disable PTM2 (unused) */
+
+	out_le32((void *) &(pcip->ptm2la), 0x00000000);
+	out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+
+	/* end work arround */
+	if (ppc_md.progress)
+		ppc_md.progress("bios_fixup(): done", 0x800);
+
+#ifdef DEBUG
+	printk("PCI bridge regs after fixup \n");
+	for (i = 0; i <= 2; i++) {
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+		printk(" pmm%dla\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+		printk(" pmm%dpcila\t0x%x\n", i,
+		       in_le32(&(pcip->pmm[i].pcila)));
+		printk(" pmm%dpciha\t0x%x\n", i,
+		       in_le32(&(pcip->pmm[i].pciha)));
+	}
+	printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+	printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+	printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+	printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+	for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+		early_read_config_dword(hose, hose->first_busno,
+					PCI_FUNC(hose->first_busno), bar,
+					&bar_response);
+		DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
+		    hose->first_busno, PCI_SLOT(hose->first_busno),
+		    PCI_FUNC(hose->first_busno), bar, bar_response);
+	}
+
+
+#endif
+}
+
+void __init
+ash_map_io(void)
+{
+	ppc4xx_map_io();
+	io_block_mapping(ASH_RTC_VADDR, ASH_RTC_PADDR, ASH_RTC_SIZE, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	ppc4xx_init(r3, r4, r5, r6, r7);
+
+	ppc_md.setup_arch = ash_setup_arch;
+	ppc_md.setup_io_mappings = ash_map_io;
+
+#ifdef CONFIG_PPC_RTC
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+#endif
+}
diff --git a/arch/ppc/platforms/4xx/ash.h b/arch/ppc/platforms/4xx/ash.h
new file mode 100644
index 0000000..5f7448e
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ash.h
@@ -0,0 +1,83 @@
+/*
+ * arch/ppc/platforms/4xx/ash.h
+ *
+ * Macros, definitions, and data structures specific to the IBM PowerPC
+ * Ash eval board.
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2000-2002 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_ASH_H__
+#define __ASM_ASH_H__
+#include <platforms/4xx/ibmnp405h.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's "Ash" evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
+
+typedef struct board_info {
+	unsigned char	 bi_s_version[4];	/* Version of this structure */
+	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[4][6];	/* Local Ethernet MAC address */
+	unsigned char	 bi_pci_enetaddr[6];
+	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
+	unsigned int	 bi_pci_busfreq;	/* PCI speed in Hz */
+} bd_t;
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+/* Memory map for the IBM "Ash" NP405H evaluation board.
+ */
+
+extern  void *ash_rtc_base;
+#define ASH_RTC_PADDR		((uint)0xf0000000)
+#define ASH_RTC_VADDR		ASH_RTC_PADDR
+#define ASH_RTC_SIZE		((uint)8*1024)
+
+
+/* Early initialization address mapping for block_io.
+ * Standard 405GP map.
+ */
+#define PPC4xx_PCI_IO_PADDR	((uint)PPC405_PCI_PHY_IO_BASE)
+#define PPC4xx_PCI_IO_VADDR	PPC4xx_PCI_IO_PADDR
+#define PPC4xx_PCI_IO_SIZE	((uint)64*1024)
+#define PPC4xx_PCI_CFG_PADDR	((uint)PPC405_PCI_CONFIG_ADDR)
+#define PPC4xx_PCI_CFG_VADDR	PPC4xx_PCI_CFG_PADDR
+#define PPC4xx_PCI_CFG_SIZE	((uint)4*1024)
+#define PPC4xx_PCI_LCFG_PADDR	((uint)0xef400000)
+#define PPC4xx_PCI_LCFG_VADDR	PPC4xx_PCI_LCFG_PADDR
+#define PPC4xx_PCI_LCFG_SIZE	((uint)4*1024)
+#define PPC4xx_ONB_IO_PADDR	((uint)0xef600000)
+#define PPC4xx_ONB_IO_VADDR	PPC4xx_ONB_IO_PADDR
+#define PPC4xx_ONB_IO_SIZE	((uint)4*1024)
+
+#define NR_BOARD_IRQS 32
+
+#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
+#define BASE_BAUD		201600
+#else
+#define BASE_BAUD		691200
+#endif
+
+#define PPC4xx_MACHINE_NAME "IBM NP405H Ash"
+
+extern char pci_irq_table[][4];
+
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_ASH_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/bubinga.c b/arch/ppc/platforms/4xx/bubinga.c
new file mode 100644
index 0000000..3678abf
--- /dev/null
+++ b/arch/ppc/platforms/4xx/bubinga.c
@@ -0,0 +1,263 @@
+/*
+ * Support for IBM PPC 405EP evaluation board (Bubinga).
+ *
+ * Author: SAW (IBM), derived from walnut.c.
+ *         Maintained by MontaVista Software <source@mvista.com>
+ *
+ * 2003 (c) MontaVista Softare Inc.  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/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/blkdev.h>
+#include <linux/pci.h>
+#include <linux/rtc.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pci-bridge.h>
+#include <asm/processor.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/todc.h>
+#include <asm/kgdb.h>
+#include <asm/ocp.h>
+#include <asm/ibm_ocp_pci.h>
+
+#include <platforms/4xx/ibm405ep.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+extern bd_t __res;
+
+void *bubinga_rtc_base;
+
+/* Some IRQs unique to the board
+ * Used by the generic 405 PCI setup functions in ppc4xx_pci.c
+ */
+int __init
+ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	    /*
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *      A       B       C       D
+	     */
+	{
+		{28, 28, 28, 28},	/* IDSEL 1 - PCI slot 1 */
+		{29, 29, 29, 29},	/* IDSEL 2 - PCI slot 2 */
+		{30, 30, 30, 30},	/* IDSEL 3 - PCI slot 3 */
+		{31, 31, 31, 31},	/* IDSEL 4 - PCI slot 4 */
+	};
+
+	const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+};
+
+/* The serial clock for the chip is an internal clock determined by
+ * different clock speeds/dividers.
+ * Calculate the proper input baud rate and setup the serial driver.
+ */
+static void __init
+bubinga_early_serial_map(void)
+{
+	u32 uart_div;
+	int uart_clock;
+	struct uart_port port;
+
+         /* Calculate the serial clock input frequency
+          *
+          * The base baud is the PLL OUTA (provided in the board info
+          * structure) divided by the external UART Divisor, divided
+          * by 16.
+          */
+	uart_div = (mfdcr(DCRN_CPC0_UCR_BASE) & DCRN_CPC0_UCR_U0DIV);
+	uart_clock = __res.bi_pllouta_freq / uart_div;
+
+	/* Setup serial port access */
+	memset(&port, 0, sizeof(port));
+	port.membase = (void*)ACTING_UART0_IO_BASE;
+	port.irq = ACTING_UART0_INT;
+	port.uartclk = uart_clock;
+	port.regshift = 0;
+	port.iotype = SERIAL_IO_MEM;
+	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	port.line = 0;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 0 failed\n");
+	}
+
+	port.membase = (void*)ACTING_UART1_IO_BASE;
+	port.irq = ACTING_UART1_INT;
+	port.line = 1;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 1 failed\n");
+	}
+}
+
+void __init
+bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
+{
+
+	unsigned int bar_response, bar;
+	/*
+	 * Expected PCI mapping:
+	 *
+	 *  PLB addr             PCI memory addr
+	 *  ---------------------       ---------------------
+	 *  0000'0000 - 7fff'ffff <---  0000'0000 - 7fff'ffff
+	 *  8000'0000 - Bfff'ffff --->  8000'0000 - Bfff'ffff
+	 *
+	 *  PLB addr             PCI io addr
+	 *  ---------------------       ---------------------
+	 *  e800'0000 - e800'ffff --->  0000'0000 - 0001'0000
+	 *
+	 * The following code is simplified by assuming that the bootrom
+	 * has been well behaved in following this mapping.
+	 */
+
+#ifdef DEBUG
+	int i;
+
+	printk("ioremap PCLIO_BASE = 0x%x\n", pcip);
+	printk("PCI bridge regs before fixup \n");
+	for (i = 0; i <= 3; i++) {
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
+	}
+	printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+	printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+	printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+	printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+#endif
+
+	/* added for IBM boot rom version 1.15 bios bar changes  -AK */
+
+	/* Disable region first */
+	out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
+	/* PLB starting addr, PCI: 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
+	/* PCI start addr, 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
+	/* 512MB range of PLB to PCI */
+	out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
+	/* Enable no pre-fetch, enable region */
+	out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
+						(PPC405_PCI_UPPER_MEM -
+						 PPC405_PCI_MEM_BASE)) | 0x01));
+
+	/* Disable region one */
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->ptm1ms), 0x00000001);
+
+	/* Disable region two */
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+	out_le32((void *) &(pcip->ptm2la), 0x00000000);
+
+	/* Zero config bars */
+	for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+		early_write_config_dword(hose, hose->first_busno,
+					 PCI_FUNC(hose->first_busno), bar,
+					 0x00000000);
+		early_read_config_dword(hose, hose->first_busno,
+					PCI_FUNC(hose->first_busno), bar,
+					&bar_response);
+		DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
+		    hose->first_busno, PCI_SLOT(hose->first_busno),
+		    PCI_FUNC(hose->first_busno), bar, bar_response);
+	}
+	/* end work arround */
+
+#ifdef DEBUG
+	printk("PCI bridge regs after fixup \n");
+	for (i = 0; i <= 3; i++) {
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
+	}
+	printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+	printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+	printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+	printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+#endif
+}
+
+void __init
+bubinga_setup_arch(void)
+{
+	ppc4xx_setup_arch();
+
+	ibm_ocp_set_emac(0, 1);
+
+        bubinga_early_serial_map();
+
+        /* RTC step for the evb405ep */
+        bubinga_rtc_base = (void *) BUBINGA_RTC_VADDR;
+        TODC_INIT(TODC_TYPE_DS1743, bubinga_rtc_base, bubinga_rtc_base,
+                  bubinga_rtc_base, 8);
+        /* Identify the system */
+        printk("IBM Bubinga port (MontaVista Software, Inc. <source@mvista.com>)\n");
+}
+
+void __init
+bubinga_map_io(void)
+{
+	ppc4xx_map_io();
+     	io_block_mapping(BUBINGA_RTC_VADDR,
+                         BUBINGA_RTC_PADDR, BUBINGA_RTC_SIZE, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	ppc4xx_init(r3, r4, r5, r6, r7);
+
+	ppc_md.setup_arch = bubinga_setup_arch;
+	ppc_md.setup_io_mappings = bubinga_map_io;
+
+#ifdef CONFIG_GEN_RTC
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+#endif
+#ifdef CONFIG_KGDB
+	ppc_md.early_serial_map = bubinga_early_serial_map;
+#endif
+}
+
diff --git a/arch/ppc/platforms/4xx/bubinga.h b/arch/ppc/platforms/4xx/bubinga.h
new file mode 100644
index 0000000..b1df856
--- /dev/null
+++ b/arch/ppc/platforms/4xx/bubinga.h
@@ -0,0 +1,69 @@
+/*
+ * Support for IBM PPC 405EP evaluation board (Bubinga).
+ *
+ * Author: SAW (IBM), derived from walnut.h.
+ *         Maintained by MontaVista Software <source@mvista.com>
+ *
+ * 2003 (c) MontaVista Softare Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __BUBINGA_H__
+#define __BUBINGA_H__
+
+/* 405EP */
+#include <platforms/4xx/ibm405ep.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
+
+typedef struct board_info {
+        unsigned char    bi_s_version[4];       /* Version of this structure */
+        unsigned char    bi_r_version[30];      /* Version of the IBM ROM */
+        unsigned int     bi_memsize;            /* DRAM installed, in bytes */
+        unsigned char    bi_enetaddr[2][6];     /* Local Ethernet MAC address */        unsigned char    bi_pci_enetaddr[6];    /* PCI Ethernet MAC address */
+        unsigned int     bi_intfreq;            /* Processor speed, in Hz */
+        unsigned int     bi_busfreq;            /* PLB Bus speed, in Hz */
+        unsigned int     bi_pci_busfreq;        /* PCI Bus speed, in Hz */
+        unsigned int     bi_opb_busfreq;        /* OPB Bus speed, in Hz */
+        unsigned int     bi_pllouta_freq;       /* PLL OUTA speed, in Hz */
+} bd_t;
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+
+/* Memory map for the Bubinga board.
+ * Generic 4xx plus RTC.
+ */
+
+extern void *bubinga_rtc_base;
+#define BUBINGA_RTC_PADDR	((uint)0xf0000000)
+#define BUBINGA_RTC_VADDR	BUBINGA_RTC_PADDR
+#define BUBINGA_RTC_SIZE	((uint)8*1024)
+
+/* The UART clock is based off an internal clock -
+ * define BASE_BAUD based on the internal clock and divider(s).
+ * Since BASE_BAUD must be a constant, we will initialize it
+ * using clock/divider values which OpenBIOS initializes
+ * for typical configurations at various CPU speeds.
+ * The base baud is calculated as (FWDA / EXT UART DIV / 16)
+ */
+#define BASE_BAUD       0
+
+#define BUBINGA_FPGA_BASE      0xF0300000
+
+#define PPC4xx_MACHINE_NAME     "IBM Bubinga"
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __BUBINGA_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/cpci405.c b/arch/ppc/platforms/4xx/cpci405.c
new file mode 100644
index 0000000..ff96677
--- /dev/null
+++ b/arch/ppc/platforms/4xx/cpci405.c
@@ -0,0 +1,84 @@
+/*
+ * arch/ppc/platforms/cpci405.c
+ *
+ * Board setup routines for the esd CPCI-405 cPCI Board.
+ *
+ * Author: Stefan Roese
+ *         stefan.roese@esd-electronics.com
+ *
+ * Copyright 2001 esd electronic system design - hannover germany
+ *
+ * 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/init.h>
+#include <linux/pci.h>
+#include <asm/system.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/todc.h>
+#include <asm/ocp.h>
+
+void *cpci405_nvram;
+
+/*
+ * Some IRQs unique to CPCI-405.
+ */
+int __init
+ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	/*
+	 *      PCI IDSEL/INTPIN->INTLINE
+	 *      A       B       C       D
+	 */
+	{
+		{28,	28,	28,	28},	/* IDSEL 15 - cPCI slot 8 */
+		{29,	29,	29,	29},	/* IDSEL 16 - cPCI slot 7 */
+		{30,	30,	30,	30},	/* IDSEL 17 - cPCI slot 6 */
+		{27,	27,	27,	27},	/* IDSEL 18 - cPCI slot 5 */
+		{28,	28,	28,	28},	/* IDSEL 19 - cPCI slot 4 */
+		{29,	29,	29,	29},	/* IDSEL 20 - cPCI slot 3 */
+		{30,	30,	30,	30},	/* IDSEL 21 - cPCI slot 2 */
+        };
+	const long min_idsel = 15, max_idsel = 21, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+};
+
+void __init
+cpci405_setup_arch(void)
+{
+	ppc4xx_setup_arch();
+
+	ibm_ocp_set_emac(0, 0);
+
+	TODC_INIT(TODC_TYPE_MK48T35, cpci405_nvram, cpci405_nvram, cpci405_nvram, 8);
+}
+
+void __init
+cpci405_map_io(void)
+{
+	ppc4xx_map_io();
+	cpci405_nvram = ioremap(CPCI405_NVRAM_PADDR, CPCI405_NVRAM_SIZE);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	ppc4xx_init(r3, r4, r5, r6, r7);
+
+	ppc_md.setup_arch = cpci405_setup_arch;
+	ppc_md.setup_io_mappings = cpci405_map_io;
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+}
diff --git a/arch/ppc/platforms/4xx/cpci405.h b/arch/ppc/platforms/4xx/cpci405.h
new file mode 100644
index 0000000..e27f7cb
--- /dev/null
+++ b/arch/ppc/platforms/4xx/cpci405.h
@@ -0,0 +1,37 @@
+/*
+ * CPCI-405 board specific definitions
+ *
+ * Copyright (c) 2001 Stefan Roese (stefan.roese@esd-electronics.com)
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_CPCI405_H__
+#define __ASM_CPCI405_H__
+
+#include <linux/config.h>
+
+/* We have a 405GP core */
+#include <platforms/4xx/ibm405gp.h>
+
+#include <asm/ppcboot.h>
+
+#ifndef __ASSEMBLY__
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+/* Map for the NVRAM space */
+#define CPCI405_NVRAM_PADDR	((uint)0xf0200000)
+#define CPCI405_NVRAM_SIZE	((uint)32*1024)
+
+#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
+#define BASE_BAUD		201600
+#else
+#define BASE_BAUD		691200
+#endif
+
+#define PPC4xx_MACHINE_NAME "esd CPCI-405"
+
+#endif /* !__ASSEMBLY__ */
+#endif	/* __ASM_CPCI405_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
new file mode 100644
index 0000000..f63bca8
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ebony.c
@@ -0,0 +1,356 @@
+/*
+ * arch/ppc/platforms/4xx/ebony.c
+ *
+ * Ebony board specific routines
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2002-2005 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/initrd.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+#include <asm/pci-bridge.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/ppcboot.h>
+
+#include <syslib/gen550.h>
+#include <syslib/ibm440gp_common.h>
+
+/*
+ * This is a horrible kludge, we eventually need to abstract this
+ * generic PHY stuff, so the  standard phy mode defines can be
+ * easily used from arch code.
+ */
+#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
+
+bd_t __res;
+
+static struct ibm44x_clocks clocks __initdata;
+
+/*
+ * Ebony external IRQ triggering/polarity settings
+ */
+unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ0: PCI slot 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ1: PCI slot 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ2: PCI slot 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ3: PCI slot 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ4: IRDA */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_NEGATIVE),	/* IRQ5: SMI pushbutton */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ6: PHYs */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ7: AUX */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ8: EXT */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ9: EXT */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ10: EXT */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ11: EXT */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ12: EXT */
+};
+
+static void __init
+ebony_calibrate_decr(void)
+{
+	unsigned int freq;
+
+	/*
+	 * Determine system clock speed
+	 *
+	 * If we are on Rev. B silicon, then use
+	 * default external system clock.  If we are
+	 * on Rev. C silicon then errata forces us to
+	 * use the internal clock.
+	 */
+	switch (PVR_REV(mfspr(SPRN_PVR))) {
+		case PVR_REV(PVR_440GP_RB):
+			freq = EBONY_440GP_RB_SYSCLK;
+			break;
+		case PVR_REV(PVR_440GP_RC1):
+		default:
+			freq = EBONY_440GP_RC_SYSCLK;
+			break;
+	}
+
+	ibm44x_calibrate_decr(freq);
+}
+
+static int
+ebony_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: IBM\n");
+	seq_printf(m, "machine\t\t: Ebony\n");
+
+	return 0;
+}
+
+static inline int
+ebony_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	/*
+	 *	PCI IDSEL/INTPIN->INTLINE
+	 * 	   A   B   C   D
+	 */
+	{
+		{ 23, 23, 23, 23 },	/* IDSEL 1 - PCI Slot 0 */
+		{ 24, 24, 24, 24 },	/* IDSEL 2 - PCI Slot 1 */
+		{ 25, 25, 25, 25 },	/* IDSEL 3 - PCI Slot 2 */
+		{ 26, 26, 26, 26 },	/* IDSEL 4 - PCI Slot 3 */
+	};
+
+	const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+#define PCIX_WRITEL(value, offset) \
+	(writel(value, pcix_reg_base + offset))
+
+/*
+ * FIXME: This is only here to "make it work".  This will move
+ * to a ibm_pcix.c which will contain a generic IBM PCIX bridge
+ * configuration library. -Matt
+ */
+static void __init
+ebony_setup_pcix(void)
+{
+	void *pcix_reg_base;
+
+	pcix_reg_base = ioremap64(PCIX0_REG_BASE, PCIX_REG_SIZE);
+
+	/* Disable all windows */
+	PCIX_WRITEL(0, PCIX0_POM0SA);
+	PCIX_WRITEL(0, PCIX0_POM1SA);
+	PCIX_WRITEL(0, PCIX0_POM2SA);
+	PCIX_WRITEL(0, PCIX0_PIM0SA);
+	PCIX_WRITEL(0, PCIX0_PIM1SA);
+	PCIX_WRITEL(0, PCIX0_PIM2SA);
+
+	/* Setup 2GB PLB->PCI outbound mem window (3_8000_0000->0_8000_0000) */
+	PCIX_WRITEL(0x00000003, PCIX0_POM0LAH);
+	PCIX_WRITEL(0x80000000, PCIX0_POM0LAL);
+	PCIX_WRITEL(0x00000000, PCIX0_POM0PCIAH);
+	PCIX_WRITEL(0x80000000, PCIX0_POM0PCIAL);
+	PCIX_WRITEL(0x80000001, PCIX0_POM0SA);
+
+	/* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */
+	PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH);
+	PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL);
+	PCIX_WRITEL(0x80000007, PCIX0_PIM0SA);
+
+	eieio();
+}
+
+static void __init
+ebony_setup_hose(void)
+{
+	struct pci_controller *hose;
+
+	/* Configure windows on the PCI-X host bridge */
+	ebony_setup_pcix();
+
+	hose = pcibios_alloc_controller();
+
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	hose->pci_mem_offset = EBONY_PCI_MEM_OFFSET;
+
+	pci_init_resource(&hose->io_resource,
+			EBONY_PCI_LOWER_IO,
+			EBONY_PCI_UPPER_IO,
+			IORESOURCE_IO,
+			"PCI host bridge");
+
+	pci_init_resource(&hose->mem_resources[0],
+			EBONY_PCI_LOWER_MEM,
+			EBONY_PCI_UPPER_MEM,
+			IORESOURCE_MEM,
+			"PCI host bridge");
+
+	hose->io_space.start = EBONY_PCI_LOWER_IO;
+	hose->io_space.end = EBONY_PCI_UPPER_IO;
+	hose->mem_space.start = EBONY_PCI_LOWER_MEM;
+	hose->mem_space.end = EBONY_PCI_UPPER_MEM;
+	isa_io_base =
+		(unsigned long)ioremap64(EBONY_PCI_IO_BASE, EBONY_PCI_IO_SIZE);
+	hose->io_base_virt = (void *)isa_io_base;
+
+	setup_indirect_pci(hose,
+			EBONY_PCI_CFGA_PLB32,
+			EBONY_PCI_CFGD_PLB32);
+	hose->set_cfg_type = 1;
+
+	hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = ebony_map_irq;
+}
+
+TODC_ALLOC();
+
+static void __init
+ebony_early_serial_map(void)
+{
+	struct uart_port port;
+
+	/* Setup ioremapped serial port access */
+	memset(&port, 0, sizeof(port));
+	port.membase = ioremap64(PPC440GP_UART0_ADDR, 8);
+	port.irq = 0;
+	port.uartclk = clocks.uart0;
+	port.regshift = 0;
+	port.iotype = SERIAL_IO_MEM;
+	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	port.line = 0;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 0 failed\n");
+	}
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+	/* Configure debug serial access */
+	gen550_init(0, &port);
+#endif
+
+	port.membase = ioremap64(PPC440GP_UART1_ADDR, 8);
+	port.irq = 1;
+	port.uartclk = clocks.uart1;
+	port.line = 1;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 1 failed\n");
+	}
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+	/* Configure debug serial access */
+	gen550_init(1, &port);
+#endif
+}
+
+static void __init
+ebony_setup_arch(void)
+{
+	struct ocp_def *def;
+	struct ocp_func_emac_data *emacdata;
+
+	/* Set mac_addr for each EMAC */
+	def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0);
+	emacdata = def->additions;
+	emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
+	emacdata->phy_mode = PHY_MODE_RMII;
+	memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+
+	def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 1);
+	emacdata = def->additions;
+	emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
+	emacdata->phy_mode = PHY_MODE_RMII;
+	memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6);
+
+	/*
+	 * Determine various clocks.
+	 * To be completely correct we should get SysClk
+	 * from FPGA, because it can be changed by on-board switches
+	 * --ebs
+	 */
+	ibm440gp_get_clocks(&clocks, 33333333, 6 * 1843200);
+	ocp_sys_info.opb_bus_freq = clocks.opb;
+
+	/* Setup TODC access */
+	TODC_INIT(TODC_TYPE_DS1743,
+			0,
+			0,
+			ioremap64(EBONY_RTC_ADDR, EBONY_RTC_SIZE),
+			8);
+
+	/* init to some ~sane value until calibrate_delay() runs */
+        loops_per_jiffy = 50000000/HZ;
+
+	/* Setup PCI host bridge */
+	ebony_setup_hose();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+
+	ebony_early_serial_map();
+
+	/* Identify the system */
+	printk("IBM Ebony port (MontaVista Software, Inc. (source@mvista.com))\n");
+}
+
+void __init platform_init(unsigned long r3, unsigned long r4,
+		unsigned long r5, unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3)
+		__res = *(bd_t *)(r3 + KERNELBASE);
+
+	ibm44x_platform_init();
+
+	ppc_md.setup_arch = ebony_setup_arch;
+	ppc_md.show_cpuinfo = ebony_show_cpuinfo;
+	ppc_md.get_irq = NULL;		/* Set in ppc4xx_pic_init() */
+
+	ppc_md.calibrate_decr = ebony_calibrate_decr;
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+#ifdef CONFIG_KGDB
+	ppc_md.early_serial_map = ebony_early_serial_map;
+#endif
+}
+
diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h
new file mode 100644
index 0000000..47c391c
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ebony.h
@@ -0,0 +1,91 @@
+/*
+ * arch/ppc/platforms/ebony.h
+ *
+ * Ebony board definitions
+ *
+ * Matt Porter <mporter@mvista.com>
+ *
+ * Copyright 2002 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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_EBONY_H__
+#define __ASM_EBONY_H__
+
+#include <linux/config.h>
+#include <platforms/4xx/ibm440gp.h>
+
+/* F/W TLB mapping used in bootloader glue to reset EMAC */
+#define PPC44x_EMAC0_MR0	0xE0000800
+
+/* Where to find the MAC info */
+#define EBONY_OPENBIOS_MAC_BASE   0xfffffe0c
+#define EBONY_OPENBIOS_MAC_OFFSET 0x0c
+
+/* Default clock rates for Rev. B and Rev. C silicon */
+#define EBONY_440GP_RB_SYSCLK	33000000
+#define EBONY_440GP_RC_SYSCLK	400000000
+
+/* RTC/NVRAM location */
+#define EBONY_RTC_ADDR		0x0000000148000000ULL
+#define EBONY_RTC_SIZE		0x2000
+
+/* Flash */
+#define EBONY_FPGA_ADDR		0x0000000148300000ULL
+#define EBONY_BOOT_SMALL_FLASH(x)	(x & 0x20)
+#define EBONY_ONBRD_FLASH_EN(x)		(x & 0x02)
+#define EBONY_FLASH_SEL(x)		(x & 0x01)
+#define EBONY_SMALL_FLASH_LOW1	0x00000001ff800000ULL
+#define EBONY_SMALL_FLASH_LOW2	0x00000001ff880000ULL
+#define EBONY_SMALL_FLASH_HIGH1	0x00000001fff00000ULL
+#define EBONY_SMALL_FLASH_HIGH2	0x00000001fff80000ULL
+#define EBONY_SMALL_FLASH_SIZE	0x80000
+#define EBONY_LARGE_FLASH_LOW	0x00000001ff800000ULL
+#define EBONY_LARGE_FLASH_HIGH	0x00000001ffc00000ULL
+#define EBONY_LARGE_FLASH_SIZE	0x400000
+
+#define EBONY_SMALL_FLASH_BASE	0x00000001fff80000ULL
+#define EBONY_LARGE_FLASH_BASE	0x00000001ff800000ULL
+
+/*
+ * Serial port defines
+ */
+
+/* OpenBIOS defined UART mappings, used before early_serial_setup */
+#define UART0_IO_BASE	0xE0000200
+#define UART1_IO_BASE	0xE0000300
+
+/* external Epson SG-615P */
+#define BASE_BAUD	691200
+
+#define STD_UART_OP(num)					\
+	{ 0, BASE_BAUD, 0, UART##num##_INT,			\
+		(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),	\
+		iomem_base: UART##num##_IO_BASE,		\
+		io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)
+
+/* PCI support */
+#define EBONY_PCI_LOWER_IO	0x00000000
+#define EBONY_PCI_UPPER_IO	0x0000ffff
+#define EBONY_PCI_LOWER_MEM	0x80002000
+#define EBONY_PCI_UPPER_MEM	0xffffefff
+
+#define EBONY_PCI_CFGREGS_BASE	0x000000020ec00000
+#define EBONY_PCI_CFGA_PLB32	0x0ec00000
+#define EBONY_PCI_CFGD_PLB32	0x0ec00004
+
+#define EBONY_PCI_IO_BASE	0x0000000208000000ULL
+#define EBONY_PCI_IO_SIZE	0x00010000
+#define EBONY_PCI_MEM_OFFSET	0x00000000
+
+#endif				/* __ASM_EBONY_H__ */
+#endif				/* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ep405.c b/arch/ppc/platforms/4xx/ep405.c
new file mode 100644
index 0000000..26a07cd
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ep405.c
@@ -0,0 +1,197 @@
+/*
+ * arch/ppc/platforms/4xx/ep405.c
+ *
+ * Embedded Planet 405GP board
+ * http://www.embeddedplanet.com
+ *
+ * Author: Matthew Locke <mlocke@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc.  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/init.h>
+#include <linux/pci.h>
+#include <asm/system.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/todc.h>
+#include <asm/ocp.h>
+#include <asm/ibm_ocp_pci.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+u8 *ep405_bcsr;
+u8 *ep405_nvram;
+
+static struct {
+	u8 cpld_xirq_select;
+	int pci_idsel;
+	int irq;
+} ep405_devtable[] = {
+#ifdef CONFIG_EP405PC
+	{0x07, 0x0E, 25},		/* EP405PC: USB */
+#endif
+};
+
+int __init
+ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	int i;
+
+	/* AFAICT this is only called a few times during PCI setup, so
+	   performance is not critical */
+	for (i = 0; i < ARRAY_SIZE(ep405_devtable); i++) {
+		if (idsel == ep405_devtable[i].pci_idsel)
+			return ep405_devtable[i].irq;
+	}
+	return -1;
+};
+
+void __init
+ep405_setup_arch(void)
+{
+	ppc4xx_setup_arch();
+
+	ibm_ocp_set_emac(0, 0);
+
+	if (__res.bi_nvramsize == 512*1024) {
+		/* FIXME: we should properly handle NVRTCs of different sizes */
+		TODC_INIT(TODC_TYPE_DS1557, ep405_nvram, ep405_nvram, ep405_nvram, 8);
+	}
+}
+
+void __init
+bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
+{
+	unsigned int bar_response, bar;
+	/*
+	 * Expected PCI mapping:
+	 *
+	 *  PLB addr             PCI memory addr
+	 *  ---------------------       ---------------------
+	 *  0000'0000 - 7fff'ffff <---  0000'0000 - 7fff'ffff
+	 *  8000'0000 - Bfff'ffff --->  8000'0000 - Bfff'ffff
+	 *
+	 *  PLB addr             PCI io addr
+	 *  ---------------------       ---------------------
+	 *  e800'0000 - e800'ffff --->  0000'0000 - 0001'0000
+	 *
+	 */
+
+	/* Disable region zero first */
+	out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
+	/* PLB starting addr, PCI: 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
+	/* PCI start addr, 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
+	/* 512MB range of PLB to PCI */
+	out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
+	/* Enable no pre-fetch, enable region */
+	out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
+						(PPC405_PCI_UPPER_MEM -
+						 PPC405_PCI_MEM_BASE)) | 0x01));
+
+	/* Disable region one */
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->ptm1ms), 0x00000000);
+
+	/* Disable region two */
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+
+	/* Configure PTM (PCI->PLB) region 1 */
+	out_le32((void *) &(pcip->ptm1la), 0x00000000); /* PLB base address */
+	/* Disable PTM region 2 */
+	out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+
+	/* Zero config bars */
+	for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+		early_write_config_dword(hose, hose->first_busno,
+					 PCI_FUNC(hose->first_busno), bar,
+					 0x00000000);
+		early_read_config_dword(hose, hose->first_busno,
+					PCI_FUNC(hose->first_busno), bar,
+					&bar_response);
+		DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
+		    hose->first_busno, PCI_SLOT(hose->first_busno),
+		    PCI_FUNC(hose->first_busno), bar, bar_response);
+	}
+	/* end work arround */
+}
+
+void __init
+ep405_map_io(void)
+{
+	bd_t *bip = &__res;
+
+	ppc4xx_map_io();
+
+	ep405_bcsr = ioremap(EP405_BCSR_PADDR, EP405_BCSR_SIZE);
+
+	if (bip->bi_nvramsize > 0) {
+		ep405_nvram = ioremap(EP405_NVRAM_PADDR, bip->bi_nvramsize);
+	}
+}
+
+void __init
+ep405_init_IRQ(void)
+{
+	int i;
+
+	ppc4xx_init_IRQ();
+
+	/* Workaround for a bug in the firmware it incorrectly sets
+	   the IRQ polarities for XIRQ0 and XIRQ1 */
+	mtdcr(DCRN_UIC_PR(DCRN_UIC0_BASE), 0xffffff80); /* set the polarity */
+	mtdcr(DCRN_UIC_SR(DCRN_UIC0_BASE), 0x00000060); /* clear bogus interrupts */
+
+	/* Activate the XIRQs from the CPLD */
+	writeb(0xf0, ep405_bcsr+10);
+
+	/* Set up IRQ routing */
+	for (i = 0; i < ARRAY_SIZE(ep405_devtable); i++) {
+		if ( (ep405_devtable[i].irq >= 25)
+		     && (ep405_devtable[i].irq) <= 31) {
+			writeb(ep405_devtable[i].cpld_xirq_select, ep405_bcsr+5);
+			writeb(ep405_devtable[i].irq - 25, ep405_bcsr+6);
+		}
+	}
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	ppc4xx_init(r3, r4, r5, r6, r7);
+
+	ppc_md.setup_arch = ep405_setup_arch;
+	ppc_md.setup_io_mappings = ep405_map_io;
+	ppc_md.init_IRQ = ep405_init_IRQ;
+
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+
+	if (__res.bi_nvramsize == 512*1024) {
+		ppc_md.time_init = todc_time_init;
+		ppc_md.set_rtc_time = todc_set_rtc_time;
+		ppc_md.get_rtc_time = todc_get_rtc_time;
+	} else {
+		printk("EP405: NVRTC size is not 512k (not a DS1557).  Not sure what to do with it\n");
+	}
+}
diff --git a/arch/ppc/platforms/4xx/ep405.h b/arch/ppc/platforms/4xx/ep405.h
new file mode 100644
index 0000000..ea3eb21
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ep405.h
@@ -0,0 +1,54 @@
+/*
+ * arch/ppc/platforms/4xx/ep405.h
+ *
+ * Embedded Planet 405GP board
+ * http://www.embeddedplanet.com
+ *
+ * Author: Matthew Locke <mlocke@mvista.com>
+ *
+ * 2000 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_EP405_H__
+#define __ASM_EP405_H__
+
+/* We have a 405GP core */
+#include <platforms/4xx/ibm405gp.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+typedef struct board_info {
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address */
+	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
+	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
+	unsigned int	 bi_nvramsize;		/* Size of the NVRAM/RTC */
+} bd_t;
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+extern u8 *ep405_bcsr;
+extern u8 *ep405_nvram;
+
+/* Map for the BCSR and NVRAM space */
+#define EP405_BCSR_PADDR	((uint)0xf4000000)
+#define EP405_BCSR_SIZE		((uint)16)
+#define EP405_NVRAM_PADDR	((uint)0xf4200000)
+
+/* serial defines */
+#define BASE_BAUD		399193
+
+#define PPC4xx_MACHINE_NAME "Embedded Planet 405GP"
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_EP405_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibm405ep.c b/arch/ppc/platforms/4xx/ibm405ep.c
new file mode 100644
index 0000000..6d44567
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm405ep.c
@@ -0,0 +1,143 @@
+/*
+ * arch/ppc/platforms/ibm405ep.c
+ *
+ * Support for IBM PPC 405EP processors.
+ *
+ * Author: SAW (IBM), derived from ibmnp405l.c.
+ *         Maintained by MontaVista Software <source@mvista.com>
+ *
+ * 2003 (c) MontaVista Softare Inc.  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/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+
+#include <asm/ibm4xx.h>
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+
+#include <platforms/4xx/ibm405ep.h>
+
+static struct ocp_func_mal_data ibm405ep_mal0_def = {
+	.num_tx_chans	= 4,		/* Number of TX channels */
+	.num_rx_chans	= 2,		/* Number of RX channels */
+	.txeob_irq	= 11,		/* TX End Of Buffer IRQ  */
+	.rxeob_irq	= 12,		/* RX End Of Buffer IRQ  */
+	.txde_irq	= 13,		/* TX Descriptor Error IRQ */
+	.rxde_irq	= 14,		/* RX Descriptor Error IRQ */
+	.serr_irq	= 10,		/* MAL System Error IRQ    */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_emac_data ibm405ep_emac0_def = {
+	.rgmii_idx	= -1,		/* No RGMII */
+	.rgmii_mux	= -1,		/* No RGMII */
+	.zmii_idx	= -1,		/* ZMII device index */
+	.zmii_mux	= 0,		/* ZMII input of this EMAC */
+	.mal_idx	= 0,		/* MAL device index */
+	.mal_rx_chan	= 0,		/* MAL rx channel number */
+	.mal_tx_chan	= 0,		/* MAL tx channel number */
+	.wol_irq	= 9,		/* WOL interrupt number */
+	.mdio_idx	= 0,		/* MDIO via EMAC0 */
+	.tah_idx	= -1,		/* No TAH */
+};
+
+static struct ocp_func_emac_data ibm405ep_emac1_def = {
+	.rgmii_idx	= -1,		/* No RGMII */
+	.rgmii_mux	= -1,		/* No RGMII */
+	.zmii_idx	= -1,		/* ZMII device index */
+	.zmii_mux	= 0,		/* ZMII input of this EMAC */
+	.mal_idx	= 0,		/* MAL device index */
+	.mal_rx_chan	= 1,		/* MAL rx channel number */
+	.mal_tx_chan	= 2,		/* MAL tx channel number */
+	.wol_irq	= 9,		/* WOL interrupt number */
+	.mdio_idx	= 0,		/* MDIO via EMAC0 */
+	.tah_idx	= -1,		/* No TAH */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_iic_data ibm405ep_iic0_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_OPB,
+	  .index	= 0,
+	  .paddr	= 0xEF600000,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 0,
+	  .paddr	= UART0_IO_BASE,
+	  .irq		= UART0_INT,
+	  .pm		= IBM_CPM_UART0
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 1,
+	  .paddr	= UART1_IO_BASE,
+	  .irq		= UART1_INT,
+	  .pm		= IBM_CPM_UART1
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .paddr	= 0xEF600500,
+	  .irq		= 2,
+	  .pm		= IBM_CPM_IIC0,
+	  .additions	= &ibm405ep_iic0_def,
+	  .show		= &ocp_show_iic_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_GPIO,
+	  .paddr	= 0xEF600700,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= IBM_CPM_GPIO0
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_MAL,
+	  .paddr	= OCP_PADDR_NA,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm405ep_mal0_def,
+	  .show		= &ocp_show_mal_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 0,
+	  .paddr	= EMAC0_BASE,
+	  .irq		= 15,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm405ep_emac0_def,
+	  .show		= &ocp_show_emac_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 1,
+	  .paddr	= 0xEF600900,
+	  .irq		= 17,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm405ep_emac1_def,
+	  .show		= &ocp_show_emac_data
+	},
+	{ .vendor	= OCP_VENDOR_INVALID
+	}
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+	{ .polarity 	= 0xffff7f80,
+	  .triggering	= 0x00000000,
+	  .ext_irq_mask	= 0x0000007f,	/* IRQ0 - IRQ6 */
+	}
+};
diff --git a/arch/ppc/platforms/4xx/ibm405ep.h b/arch/ppc/platforms/4xx/ibm405ep.h
new file mode 100644
index 0000000..e051e3f
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm405ep.h
@@ -0,0 +1,148 @@
+/*
+ * arch/ppc/platforms/4xx/ibm405ep.h
+ *
+ * IBM PPC 405EP processor defines.
+ *
+ * Author: SAW (IBM), derived from ibm405gp.h.
+ *         Maintained by MontaVista Software <source@mvista.com>
+ *
+ * 2003 (c) MontaVista Softare Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IBM405EP_H__
+#define __ASM_IBM405EP_H__
+
+#include <linux/config.h>
+
+/* ibm405.h at bottom of this file */
+
+/* PCI
+ * PCI Bridge config reg definitions
+ * see 17-19 of manual
+ */
+
+#define PPC405_PCI_CONFIG_ADDR	0xeec00000
+#define PPC405_PCI_CONFIG_DATA	0xeec00004
+
+#define PPC405_PCI_PHY_MEM_BASE	0x80000000	/* hose_a->pci_mem_offset */
+						/* setbat */
+#define PPC405_PCI_MEM_BASE	PPC405_PCI_PHY_MEM_BASE	/* setbat */
+#define PPC405_PCI_PHY_IO_BASE	0xe8000000	/* setbat */
+#define PPC405_PCI_IO_BASE	PPC405_PCI_PHY_IO_BASE	/* setbat */
+
+#define PPC405_PCI_LOWER_MEM	0x80000000	/* hose_a->mem_space.start */
+#define PPC405_PCI_UPPER_MEM	0xBfffffff	/* hose_a->mem_space.end */
+#define PPC405_PCI_LOWER_IO	0x00000000	/* hose_a->io_space.start */
+#define PPC405_PCI_UPPER_IO	0x0000ffff	/* hose_a->io_space.end */
+
+#define PPC405_ISA_IO_BASE	PPC405_PCI_IO_BASE
+
+#define PPC4xx_PCI_IO_PADDR	((uint)PPC405_PCI_PHY_IO_BASE)
+#define PPC4xx_PCI_IO_VADDR	PPC4xx_PCI_IO_PADDR
+#define PPC4xx_PCI_IO_SIZE	((uint)64*1024)
+#define PPC4xx_PCI_CFG_PADDR	((uint)PPC405_PCI_CONFIG_ADDR)
+#define PPC4xx_PCI_CFG_VADDR	PPC4xx_PCI_CFG_PADDR
+#define PPC4xx_PCI_CFG_SIZE	((uint)4*1024)
+#define PPC4xx_PCI_LCFG_PADDR	((uint)0xef400000)
+#define PPC4xx_PCI_LCFG_VADDR	PPC4xx_PCI_LCFG_PADDR
+#define PPC4xx_PCI_LCFG_SIZE	((uint)4*1024)
+#define PPC4xx_ONB_IO_PADDR	((uint)0xef600000)
+#define PPC4xx_ONB_IO_VADDR	PPC4xx_ONB_IO_PADDR
+#define PPC4xx_ONB_IO_SIZE	((uint)4*1024)
+
+/* serial port defines */
+#define RS_TABLE_SIZE	2
+
+#define UART0_INT	0
+#define UART1_INT	1
+
+#define PCIL0_BASE	0xEF400000
+#define UART0_IO_BASE	0xEF600300
+#define UART1_IO_BASE	0xEF600400
+#define EMAC0_BASE	0xEF600800
+
+#define BD_EMAC_ADDR(e,i) bi_enetaddr[e][i]
+
+#if defined(CONFIG_UART0_TTYS0)
+#define ACTING_UART0_IO_BASE	UART0_IO_BASE
+#define ACTING_UART1_IO_BASE	UART1_IO_BASE
+#define ACTING_UART0_INT	UART0_INT
+#define ACTING_UART1_INT	UART1_INT
+#else
+#define ACTING_UART0_IO_BASE	UART1_IO_BASE
+#define ACTING_UART1_IO_BASE	UART0_IO_BASE
+#define ACTING_UART0_INT	UART1_INT
+#define ACTING_UART1_INT	UART0_INT
+#endif
+
+#define STD_UART_OP(num)					\
+	{ 0, BASE_BAUD, 0, ACTING_UART##num##_INT,			\
+		(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),	\
+		iomem_base: (u8 *)ACTING_UART##num##_IO_BASE,		\
+		io_type: SERIAL_IO_MEM},
+
+#define SERIAL_DEBUG_IO_BASE	ACTING_UART0_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)
+
+/* DCR defines */
+#define DCRN_CPMSR_BASE         0x0BA
+#define DCRN_CPMFR_BASE         0x0B9
+
+#define DCRN_CPC0_PLLMR0_BASE   0x0F0
+#define DCRN_CPC0_BOOT_BASE     0x0F1
+#define DCRN_CPC0_CR1_BASE      0x0F2
+#define DCRN_CPC0_EPRCSR_BASE   0x0F3
+#define DCRN_CPC0_PLLMR1_BASE   0x0F4
+#define DCRN_CPC0_UCR_BASE      0x0F5
+#define DCRN_CPC0_UCR_U0DIV     0x07F
+#define DCRN_CPC0_SRR_BASE      0x0F6
+#define DCRN_CPC0_JTAGID_BASE   0x0F7
+#define DCRN_CPC0_SPARE_BASE    0x0F8
+#define DCRN_CPC0_PCI_BASE      0x0F9
+
+
+#define IBM_CPM_GPT             0x80000000      /* GPT interface */
+#define IBM_CPM_PCI             0x40000000      /* PCI bridge */
+#define IBM_CPM_UIC             0x00010000      /* Universal Int Controller */
+#define IBM_CPM_CPU             0x00008000      /* processor core */
+#define IBM_CPM_EBC             0x00002000      /* EBC controller */
+#define IBM_CPM_SDRAM0          0x00004000      /* SDRAM memory controller */
+#define IBM_CPM_GPIO0           0x00001000      /* General Purpose IO */
+#define IBM_CPM_TMRCLK          0x00000400      /* CPU timers */
+#define IBM_CPM_PLB             0x00000100      /* PLB bus arbiter */
+#define IBM_CPM_OPB             0x00000080      /* PLB to OPB bridge */
+#define IBM_CPM_DMA             0x00000040      /* DMA controller */
+#define IBM_CPM_IIC0            0x00000010      /* IIC interface */
+#define IBM_CPM_UART1           0x00000002      /* serial port 0 */
+#define IBM_CPM_UART0           0x00000001      /* serial port 1 */
+#define DFLT_IBM4xx_PM          ~(IBM_CPM_PCI | IBM_CPM_CPU | IBM_CPM_DMA \
+                                        | IBM_CPM_OPB | IBM_CPM_EBC \
+                                        | IBM_CPM_SDRAM0 | IBM_CPM_PLB \
+                                        | IBM_CPM_UIC | IBM_CPM_TMRCLK)
+#define DCRN_DMA0_BASE          0x100
+#define DCRN_DMA1_BASE          0x108
+#define DCRN_DMA2_BASE          0x110
+#define DCRN_DMA3_BASE          0x118
+#define DCRNCAP_DMA_SG          1       /* have DMA scatter/gather capability */
+#define DCRN_DMASR_BASE         0x120
+#define DCRN_EBC_BASE           0x012
+#define DCRN_DCP0_BASE          0x014
+#define DCRN_MAL_BASE           0x180
+#define DCRN_OCM0_BASE          0x018
+#define DCRN_PLB0_BASE          0x084
+#define DCRN_PLLMR_BASE         0x0B0
+#define DCRN_POB0_BASE          0x0A0
+#define DCRN_SDRAM0_BASE        0x010
+#define DCRN_UIC0_BASE          0x0C0
+#define UIC0 DCRN_UIC0_BASE
+
+#include <asm/ibm405.h>
+
+#endif				/* __ASM_IBM405EP_H__ */
+#endif				/* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibm405gp.c b/arch/ppc/platforms/4xx/ibm405gp.c
new file mode 100644
index 0000000..dfd7ef3
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm405gp.c
@@ -0,0 +1,120 @@
+/*
+ *
+ *    Copyright 2000-2001 MontaVista Software Inc.
+ *      Original author: Armin Kuster akuster@mvista.com
+ *
+ *    Module name: ibm405gp.c
+ *
+ *
+ * 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/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <platforms/4xx/ibm405gp.h>
+#include <asm/ibm4xx.h>
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+
+static struct ocp_func_emac_data ibm405gp_emac0_def = {
+	.rgmii_idx	= -1,		/* No RGMII */
+	.rgmii_mux	= -1,		/* No RGMII */
+	.zmii_idx	= -1,		/* ZMII device index */
+	.zmii_mux	= 0,		/* ZMII input of this EMAC */
+	.mal_idx	= 0,		/* MAL device index */
+	.mal_rx_chan	= 0,		/* MAL rx channel number */
+	.mal_tx_chan	= 0,		/* MAL tx channel number */
+	.wol_irq	= 9,		/* WOL interrupt number */
+	.mdio_idx	= -1,		/* No shared MDIO */
+	.tah_idx	= -1,		/* No TAH */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ibm405gp_mal0_def = {
+	.num_tx_chans	= 1,		/* Number of TX channels */
+	.num_rx_chans	= 1,		/* Number of RX channels */
+	.txeob_irq	= 11,		/* TX End Of Buffer IRQ  */
+	.rxeob_irq	= 12,		/* RX End Of Buffer IRQ  */
+	.txde_irq	= 13,		/* TX Descriptor Error IRQ */
+	.rxde_irq	= 14,		/* RX Descriptor Error IRQ */
+	.serr_irq	= 10,		/* MAL System Error IRQ    */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ibm405gp_iic0_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_OPB,
+	  .index	= 0,
+	  .paddr	= 0xEF600000,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 0,
+	  .paddr	= UART0_IO_BASE,
+	  .irq		= UART0_INT,
+	  .pm		= IBM_CPM_UART0
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 1,
+	  .paddr	= UART1_IO_BASE,
+	  .irq		= UART1_INT,
+	  .pm		= IBM_CPM_UART1
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .paddr	= 0xEF600500,
+	  .irq		= 2,
+	  .pm		= IBM_CPM_IIC0,
+	  .additions	= &ibm405gp_iic0_def,
+	  .show		= &ocp_show_iic_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_GPIO,
+	  .paddr	= 0xEF600700,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= IBM_CPM_GPIO0
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_MAL,
+	  .paddr	= OCP_PADDR_NA,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm405gp_mal0_def,
+	  .show		= &ocp_show_mal_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 0,
+	  .paddr	= EMAC0_BASE,
+	  .irq		= 15,
+	  .pm		= IBM_CPM_EMAC0,
+	  .additions	= &ibm405gp_emac0_def,
+	  .show		= &ocp_show_emac_data,
+	},
+	{ .vendor	= OCP_VENDOR_INVALID
+	}
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+	{ .polarity 	= 0xffffff80,
+	  .triggering	= 0x10000000,
+	  .ext_irq_mask	= 0x0000007f,	/* IRQ0 - IRQ6 */
+	}
+};
diff --git a/arch/ppc/platforms/4xx/ibm405gp.h b/arch/ppc/platforms/4xx/ibm405gp.h
new file mode 100644
index 0000000..b2b642e
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm405gp.h
@@ -0,0 +1,151 @@
+/*
+ * arch/ppc/platforms/4xx/ibm405gp.h
+ *
+ * Author: Armin Kuster akuster@mvista.com
+ *
+ * 2001 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IBM405GP_H__
+#define __ASM_IBM405GP_H__
+
+#include <linux/config.h>
+
+/* ibm405.h at bottom of this file */
+
+/* PCI
+ * PCI Bridge config reg definitions
+ * see 17-19 of manual
+ */
+
+#define PPC405_PCI_CONFIG_ADDR	0xeec00000
+#define PPC405_PCI_CONFIG_DATA	0xeec00004
+
+#define PPC405_PCI_PHY_MEM_BASE	0x80000000	/* hose_a->pci_mem_offset */
+						/* setbat */
+#define PPC405_PCI_MEM_BASE	PPC405_PCI_PHY_MEM_BASE	/* setbat */
+#define PPC405_PCI_PHY_IO_BASE	0xe8000000	/* setbat */
+#define PPC405_PCI_IO_BASE	PPC405_PCI_PHY_IO_BASE	/* setbat */
+
+#define PPC405_PCI_LOWER_MEM	0x80000000	/* hose_a->mem_space.start */
+#define PPC405_PCI_UPPER_MEM	0xBfffffff	/* hose_a->mem_space.end */
+#define PPC405_PCI_LOWER_IO	0x00000000	/* hose_a->io_space.start */
+#define PPC405_PCI_UPPER_IO	0x0000ffff	/* hose_a->io_space.end */
+
+#define PPC405_ISA_IO_BASE	PPC405_PCI_IO_BASE
+
+#define PPC4xx_PCI_IO_PADDR	((uint)PPC405_PCI_PHY_IO_BASE)
+#define PPC4xx_PCI_IO_VADDR	PPC4xx_PCI_IO_PADDR
+#define PPC4xx_PCI_IO_SIZE	((uint)64*1024)
+#define PPC4xx_PCI_CFG_PADDR	((uint)PPC405_PCI_CONFIG_ADDR)
+#define PPC4xx_PCI_CFG_VADDR	PPC4xx_PCI_CFG_PADDR
+#define PPC4xx_PCI_CFG_SIZE	((uint)4*1024)
+#define PPC4xx_PCI_LCFG_PADDR	((uint)0xef400000)
+#define PPC4xx_PCI_LCFG_VADDR	PPC4xx_PCI_LCFG_PADDR
+#define PPC4xx_PCI_LCFG_SIZE	((uint)4*1024)
+#define PPC4xx_ONB_IO_PADDR	((uint)0xef600000)
+#define PPC4xx_ONB_IO_VADDR	PPC4xx_ONB_IO_PADDR
+#define PPC4xx_ONB_IO_SIZE	((uint)4*1024)
+
+/* serial port defines */
+#define RS_TABLE_SIZE	2
+
+#define UART0_INT	0
+#define UART1_INT	1
+
+#define PCIL0_BASE	0xEF400000
+#define UART0_IO_BASE	0xEF600300
+#define UART1_IO_BASE	0xEF600400
+#define EMAC0_BASE	0xEF600800
+
+#define BD_EMAC_ADDR(e,i) bi_enetaddr[i]
+
+#define STD_UART_OP(num)					\
+	{ 0, BASE_BAUD, 0, UART##num##_INT,			\
+		(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),	\
+		iomem_base: (u8 *)UART##num##_IO_BASE,		\
+		io_type: SERIAL_IO_MEM},
+
+#if defined(CONFIG_UART0_TTYS0)
+#define SERIAL_DEBUG_IO_BASE	UART0_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)
+#endif
+
+#if defined(CONFIG_UART0_TTYS1)
+#define SERIAL_DEBUG_IO_BASE	UART1_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(1)		\
+	STD_UART_OP(0)
+#endif
+
+/* DCR defines */
+#define DCRN_CHCR_BASE		0x0B1
+#define DCRN_CHPSR_BASE		0x0B4
+#define DCRN_CPMSR_BASE		0x0B8
+#define DCRN_CPMFR_BASE		0x0BA
+
+#define CHR0_U0EC	0x00000080	/* Select external clock for UART0 */
+#define CHR0_U1EC	0x00000040	/* Select external clock for UART1 */
+#define CHR0_UDIV	0x0000003E	/* UART internal clock divisor */
+#define CHR1_CETE	0x00800000	/* CPU external timer enable */
+
+#define DCRN_CHPSR_BASE         0x0B4
+#define  PSR_PLL_FWD_MASK        0xC0000000
+#define  PSR_PLL_FDBACK_MASK     0x30000000
+#define  PSR_PLL_TUNING_MASK     0x0E000000
+#define  PSR_PLB_CPU_MASK        0x01800000
+#define  PSR_OPB_PLB_MASK        0x00600000
+#define  PSR_PCI_PLB_MASK        0x00180000
+#define  PSR_EB_PLB_MASK         0x00060000
+#define  PSR_ROM_WIDTH_MASK      0x00018000
+#define  PSR_ROM_LOC             0x00004000
+#define  PSR_PCI_ASYNC_EN        0x00001000
+#define  PSR_PCI_ARBIT_EN        0x00000400
+
+#define IBM_CPM_IIC0		0x80000000	/* IIC interface */
+#define IBM_CPM_PCI		0x40000000	/* PCI bridge */
+#define IBM_CPM_CPU		0x20000000	/* processor core */
+#define IBM_CPM_DMA		0x10000000	/* DMA controller */
+#define IBM_CPM_OPB		0x08000000	/* PLB to OPB bridge */
+#define IBM_CPM_DCP		0x04000000	/* CodePack */
+#define IBM_CPM_EBC		0x02000000	/* ROM/SRAM peripheral controller */
+#define IBM_CPM_SDRAM0		0x01000000	/* SDRAM memory controller */
+#define IBM_CPM_PLB		0x00800000	/* PLB bus arbiter */
+#define IBM_CPM_GPIO0		0x00400000	/* General Purpose IO (??) */
+#define IBM_CPM_UART0		0x00200000	/* serial port 0 */
+#define IBM_CPM_UART1		0x00100000	/* serial port 1 */
+#define IBM_CPM_UIC		0x00080000	/* Universal Interrupt Controller */
+#define IBM_CPM_TMRCLK		0x00040000	/* CPU timers */
+#define IBM_CPM_EMAC0		0x00020000	/* on-chip ethernet MM unit */
+#define DFLT_IBM4xx_PM		~(IBM_CPM_PCI | IBM_CPM_CPU | IBM_CPM_DMA \
+					| IBM_CPM_OPB | IBM_CPM_EBC \
+					| IBM_CPM_SDRAM0 | IBM_CPM_PLB \
+					| IBM_CPM_UIC | IBM_CPM_TMRCLK)
+
+#define DCRN_DMA0_BASE		0x100
+#define DCRN_DMA1_BASE		0x108
+#define DCRN_DMA2_BASE		0x110
+#define DCRN_DMA3_BASE		0x118
+#define DCRNCAP_DMA_SG		1	/* have DMA scatter/gather capability */
+#define DCRN_DMASR_BASE		0x120
+#define DCRN_EBC_BASE		0x012
+#define DCRN_DCP0_BASE		0x014
+#define DCRN_MAL_BASE		0x180
+#define DCRN_OCM0_BASE		0x018
+#define DCRN_PLB0_BASE		0x084
+#define DCRN_PLLMR_BASE		0x0B0
+#define DCRN_POB0_BASE		0x0A0
+#define DCRN_SDRAM0_BASE	0x010
+#define DCRN_UIC0_BASE		0x0C0
+#define UIC0 DCRN_UIC0_BASE
+
+#include <asm/ibm405.h>
+
+#endif				/* __ASM_IBM405GP_H__ */
+#endif				/* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibm405gpr.c b/arch/ppc/platforms/4xx/ibm405gpr.c
new file mode 100644
index 0000000..01c8ccb
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm405gpr.c
@@ -0,0 +1,117 @@
+/*
+ * arch/ppc/platforms/4xx/ibm405gpr.c
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2002 (c) MontaVista, Software, Inc.  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/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <platforms/4xx/ibm405gpr.h>
+#include <asm/ibm4xx.h>
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+
+static struct ocp_func_emac_data ibm405gpr_emac0_def = {
+	.rgmii_idx	= -1,		/* No RGMII */
+	.rgmii_mux	= -1,		/* No RGMII */
+	.zmii_idx	= -1,		/* ZMII device index */
+	.zmii_mux	= 0,		/* ZMII input of this EMAC */
+	.mal_idx	= 0,		/* MAL device index */
+	.mal_rx_chan	= 0,		/* MAL rx channel number */
+	.mal_tx_chan	= 0,		/* MAL tx channel number */
+	.wol_irq	= 9,		/* WOL interrupt number */
+	.mdio_idx	= -1,		/* No shared MDIO */
+	.tah_idx	= -1,		/* No TAH */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ibm405gpr_mal0_def = {
+	.num_tx_chans	= 1,		/* Number of TX channels */
+	.num_rx_chans	= 1,		/* Number of RX channels */
+	.txeob_irq	= 11,		/* TX End Of Buffer IRQ  */
+	.rxeob_irq	= 12,		/* RX End Of Buffer IRQ  */
+	.txde_irq	= 13,		/* TX Descriptor Error IRQ */
+	.rxde_irq	= 14,		/* RX Descriptor Error IRQ */
+	.serr_irq	= 10,		/* MAL System Error IRQ    */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ibm405gpr_iic0_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_OPB,
+	  .index	= 0,
+	  .paddr	= 0xEF600000,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 0,
+	  .paddr	= UART0_IO_BASE,
+	  .irq		= UART0_INT,
+	  .pm		= IBM_CPM_UART0
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 1,
+	  .paddr	= UART1_IO_BASE,
+	  .irq		= UART1_INT,
+	  .pm		= IBM_CPM_UART1
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .paddr	= 0xEF600500,
+	  .irq		= 2,
+	  .pm		= IBM_CPM_IIC0,
+	  .additions	= &ibm405gpr_iic0_def,
+	  .show		= &ocp_show_iic_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_GPIO,
+	  .paddr	= 0xEF600700,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= IBM_CPM_GPIO0
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_MAL,
+	  .paddr	= OCP_PADDR_NA,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm405gpr_mal0_def,
+	  .show		= &ocp_show_mal_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 0,
+	  .paddr	= EMAC0_BASE,
+	  .irq		= 15,
+	  .pm		= IBM_CPM_EMAC0,
+	  .additions	= &ibm405gpr_emac0_def,
+	  .show		= &ocp_show_emac_data,
+	},
+	{ .vendor	= OCP_VENDOR_INVALID
+	}
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+	{ .polarity 	= 0xffffe000,
+	  .triggering	= 0x10000000,
+	  .ext_irq_mask	= 0x00001fff,	/* IRQ7 - IRQ12, IRQ0 - IRQ6 */
+	}
+};
diff --git a/arch/ppc/platforms/4xx/ibm405gpr.h b/arch/ppc/platforms/4xx/ibm405gpr.h
new file mode 100644
index 0000000..45412fb
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm405gpr.h
@@ -0,0 +1,151 @@
+/*
+ * arch/ppc/platforms/4xx/ibm405gpr.h
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2002 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IBM405GPR_H__
+#define __ASM_IBM405GPR_H__
+
+#include <linux/config.h>
+
+/* ibm405.h at bottom of this file */
+
+/* PCI
+ * PCI Bridge config reg definitions
+ * see 17-19 of manual
+ */
+
+#define PPC405_PCI_CONFIG_ADDR	0xeec00000
+#define PPC405_PCI_CONFIG_DATA	0xeec00004
+
+#define PPC405_PCI_PHY_MEM_BASE	0x80000000	/* hose_a->pci_mem_offset */
+						/* setbat */
+#define PPC405_PCI_MEM_BASE	PPC405_PCI_PHY_MEM_BASE	/* setbat */
+#define PPC405_PCI_PHY_IO_BASE	0xe8000000	/* setbat */
+#define PPC405_PCI_IO_BASE	PPC405_PCI_PHY_IO_BASE	/* setbat */
+
+#define PPC405_PCI_LOWER_MEM	0x80000000	/* hose_a->mem_space.start */
+#define PPC405_PCI_UPPER_MEM	0xBfffffff	/* hose_a->mem_space.end */
+#define PPC405_PCI_LOWER_IO	0x00000000	/* hose_a->io_space.start */
+#define PPC405_PCI_UPPER_IO	0x0000ffff	/* hose_a->io_space.end */
+
+#define PPC405_ISA_IO_BASE	PPC405_PCI_IO_BASE
+
+#define PPC4xx_PCI_IO_PADDR	((uint)PPC405_PCI_PHY_IO_BASE)
+#define PPC4xx_PCI_IO_VADDR	PPC4xx_PCI_IO_PADDR
+#define PPC4xx_PCI_IO_SIZE	((uint)64*1024)
+#define PPC4xx_PCI_CFG_PADDR	((uint)PPC405_PCI_CONFIG_ADDR)
+#define PPC4xx_PCI_CFG_VADDR	PPC4xx_PCI_CFG_PADDR
+#define PPC4xx_PCI_CFG_SIZE	((uint)4*1024)
+#define PPC4xx_PCI_LCFG_PADDR	((uint)0xef400000)
+#define PPC4xx_PCI_LCFG_VADDR	PPC4xx_PCI_LCFG_PADDR
+#define PPC4xx_PCI_LCFG_SIZE	((uint)4*1024)
+#define PPC4xx_ONB_IO_PADDR	((uint)0xef600000)
+#define PPC4xx_ONB_IO_VADDR	PPC4xx_ONB_IO_PADDR
+#define PPC4xx_ONB_IO_SIZE	((uint)4*1024)
+
+/* serial port defines */
+#define RS_TABLE_SIZE	2
+
+#define UART0_INT	0
+#define UART1_INT	1
+
+#define PCIL0_BASE	0xEF400000
+#define UART0_IO_BASE	0xEF600300
+#define UART1_IO_BASE	0xEF600400
+#define EMAC0_BASE	0xEF600800
+
+#define BD_EMAC_ADDR(e,i) bi_enetaddr[i]
+
+#define STD_UART_OP(num)					\
+	{ 0, BASE_BAUD, 0, UART##num##_INT,			\
+		(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),	\
+		iomem_base: (u8 *)UART##num##_IO_BASE,		\
+		io_type: SERIAL_IO_MEM},
+
+#if defined(CONFIG_UART0_TTYS0)
+#define SERIAL_DEBUG_IO_BASE	UART0_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)
+#endif
+
+#if defined(CONFIG_UART0_TTYS1)
+#define SERIAL_DEBUG_IO_BASE	UART1_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(1)		\
+	STD_UART_OP(0)
+#endif
+
+/* DCR defines */
+#define DCRN_CHCR_BASE		0x0B1
+#define DCRN_CHPSR_BASE		0x0B4
+#define DCRN_CPMSR_BASE		0x0B8
+#define DCRN_CPMFR_BASE		0x0BA
+
+#define CHR0_U0EC	0x00000080	/* Select external clock for UART0 */
+#define CHR0_U1EC	0x00000040	/* Select external clock for UART1 */
+#define CHR0_UDIV	0x0000003E	/* UART internal clock divisor */
+#define CHR1_CETE	0x00800000	/* CPU external timer enable */
+
+#define DCRN_CHPSR_BASE         0x0B4
+#define  PSR_PLL_FWD_MASK        0xC0000000
+#define  PSR_PLL_FDBACK_MASK     0x30000000
+#define  PSR_PLL_TUNING_MASK     0x0E000000
+#define  PSR_PLB_CPU_MASK        0x01800000
+#define  PSR_OPB_PLB_MASK        0x00600000
+#define  PSR_PCI_PLB_MASK        0x00180000
+#define  PSR_EB_PLB_MASK         0x00060000
+#define  PSR_ROM_WIDTH_MASK      0x00018000
+#define  PSR_ROM_LOC             0x00004000
+#define  PSR_PCI_ASYNC_EN        0x00001000
+#define  PSR_PCI_ARBIT_EN        0x00000400
+
+#define IBM_CPM_IIC0		0x80000000	/* IIC interface */
+#define IBM_CPM_PCI		0x40000000	/* PCI bridge */
+#define IBM_CPM_CPU		0x20000000	/* processor core */
+#define IBM_CPM_DMA		0x10000000	/* DMA controller */
+#define IBM_CPM_OPB		0x08000000	/* PLB to OPB bridge */
+#define IBM_CPM_DCP		0x04000000	/* CodePack */
+#define IBM_CPM_EBC		0x02000000	/* ROM/SRAM peripheral controller */
+#define IBM_CPM_SDRAM0		0x01000000	/* SDRAM memory controller */
+#define IBM_CPM_PLB		0x00800000	/* PLB bus arbiter */
+#define IBM_CPM_GPIO0		0x00400000	/* General Purpose IO (??) */
+#define IBM_CPM_UART0		0x00200000	/* serial port 0 */
+#define IBM_CPM_UART1		0x00100000	/* serial port 1 */
+#define IBM_CPM_UIC		0x00080000	/* Universal Interrupt Controller */
+#define IBM_CPM_TMRCLK		0x00040000	/* CPU timers */
+#define IBM_CPM_EMAC0		0x00020000	/* on-chip ethernet MM unit */
+#define DFLT_IBM4xx_PM		~(IBM_CPM_PCI | IBM_CPM_CPU | IBM_CPM_DMA \
+					| IBM_CPM_OPB | IBM_CPM_EBC \
+					| IBM_CPM_SDRAM0 | IBM_CPM_PLB \
+					| IBM_CPM_UIC | IBM_CPM_TMRCLK)
+
+#define DCRN_DMA0_BASE		0x100
+#define DCRN_DMA1_BASE		0x108
+#define DCRN_DMA2_BASE		0x110
+#define DCRN_DMA3_BASE		0x118
+#define DCRNCAP_DMA_SG		1	/* have DMA scatter/gather capability */
+#define DCRN_DMASR_BASE		0x120
+#define DCRN_EBC_BASE		0x012
+#define DCRN_DCP0_BASE		0x014
+#define DCRN_MAL_BASE		0x180
+#define DCRN_OCM0_BASE		0x018
+#define DCRN_PLB0_BASE		0x084
+#define DCRN_PLLMR_BASE		0x0B0
+#define DCRN_POB0_BASE		0x0A0
+#define DCRN_SDRAM0_BASE	0x010
+#define DCRN_UIC0_BASE		0x0C0
+#define UIC0 DCRN_UIC0_BASE
+
+#include <asm/ibm405.h>
+
+#endif				/* __ASM_IBM405GPR_H__ */
+#endif				/* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibm440gp.c b/arch/ppc/platforms/4xx/ibm440gp.c
new file mode 100644
index 0000000..27615ef
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm440gp.c
@@ -0,0 +1,164 @@
+/*
+ * arch/ppc/platforms/4xx/ibm440gp.c
+ *
+ * PPC440GP I/O descriptions
+ *
+ * Matt Porter <mporter@mvista.com>
+ * Copyright 2002-2004 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <platforms/4xx/ibm440gp.h>
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+
+static struct ocp_func_emac_data ibm440gp_emac0_def = {
+	.rgmii_idx	= -1,           /* No RGMII */
+	.rgmii_mux	= -1,           /* No RGMII */
+	.zmii_idx       = 0,            /* ZMII device index */
+	.zmii_mux       = 0,            /* ZMII input of this EMAC */
+	.mal_idx        = 0,            /* MAL device index */
+	.mal_rx_chan    = 0,            /* MAL rx channel number */
+	.mal_tx_chan    = 0,            /* MAL tx channel number */
+	.wol_irq        = 61,		/* WOL interrupt number */
+	.mdio_idx       = -1,           /* No shared MDIO */
+	.tah_idx	= -1,           /* No TAH */
+};
+
+static struct ocp_func_emac_data ibm440gp_emac1_def = {
+	.rgmii_idx	= -1,           /* No RGMII */
+	.rgmii_mux	= -1,           /* No RGMII */
+	.zmii_idx       = 0,            /* ZMII device index */
+	.zmii_mux       = 1,            /* ZMII input of this EMAC */
+	.mal_idx        = 0,            /* MAL device index */
+	.mal_rx_chan    = 1,            /* MAL rx channel number */
+	.mal_tx_chan    = 2,            /* MAL tx channel number */
+	.wol_irq        = 63,  		/* WOL interrupt number */
+	.mdio_idx       = -1,           /* No shared MDIO */
+	.tah_idx	= -1,           /* No TAH */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ibm440gp_mal0_def = {
+	.num_tx_chans   = 4,  		/* Number of TX channels */
+	.num_rx_chans   = 2,    	/* Number of RX channels */
+	.txeob_irq	= 10,		/* TX End Of Buffer IRQ  */
+	.rxeob_irq	= 11,		/* RX End Of Buffer IRQ  */
+	.txde_irq	= 33,		/* TX Descriptor Error IRQ */
+	.rxde_irq	= 34,		/* RX Descriptor Error IRQ */
+	.serr_irq	= 32,		/* MAL System Error IRQ    */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ibm440gp_iic0_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+
+static struct ocp_func_iic_data ibm440gp_iic1_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_OPB,
+	  .index	= 0,
+	  .paddr	= 0x0000000140000000ULL,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 0,
+	  .paddr	= PPC440GP_UART0_ADDR,
+	  .irq		= UART0_INT,
+	  .pm		= IBM_CPM_UART0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 1,
+	  .paddr	= PPC440GP_UART1_ADDR,
+	  .irq		= UART1_INT,
+	  .pm		= IBM_CPM_UART1,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .index	= 0,
+	  .paddr	= 0x0000000140000400ULL,
+	  .irq		= 2,
+	  .pm		= IBM_CPM_IIC0,
+	  .additions	= &ibm440gp_iic0_def,
+	  .show		= &ocp_show_iic_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .index	= 1,
+	  .paddr	= 0x0000000140000500ULL,
+	  .irq		= 3,
+	  .pm		= IBM_CPM_IIC1,
+	  .additions	= &ibm440gp_iic1_def,
+	  .show		= &ocp_show_iic_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_GPIO,
+	  .index	= 0,
+	  .paddr	= 0x0000000140000700ULL,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= IBM_CPM_GPIO0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_MAL,
+	  .paddr	= OCP_PADDR_NA,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm440gp_mal0_def,
+	  .show		= &ocp_show_mal_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 0,
+	  .paddr	= 0x0000000140000800ULL,
+	  .irq		= 60,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm440gp_emac0_def,
+	  .show		= &ocp_show_emac_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 1,
+	  .paddr	= 0x0000000140000900ULL,
+	  .irq		= 62,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm440gp_emac1_def,
+	  .show		= &ocp_show_emac_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_ZMII,
+	  .paddr	= 0x0000000140000780ULL,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_INVALID
+	}
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+	{ .polarity 	= 0xfffffe03,
+	  .triggering	= 0x01c00000,
+	  .ext_irq_mask	= 0x000001fc,	/* IRQ0 - IRQ6 */
+	},
+	{ .polarity 	= 0xffffc0ff,
+	  .triggering	= 0x00ff8000,
+	  .ext_irq_mask	= 0x00003f00,	/* IRQ7 - IRQ12 */
+	},
+};
diff --git a/arch/ppc/platforms/4xx/ibm440gp.h b/arch/ppc/platforms/4xx/ibm440gp.h
new file mode 100644
index 0000000..ae1efc0
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm440gp.h
@@ -0,0 +1,66 @@
+/*
+ * arch/ppc/platforms/4xx/ibm440gp.h
+ *
+ * PPC440GP definitions
+ *
+ * Roland Dreier <roland@digitalvampire.org>
+ *
+ * Copyright 2002 Roland Dreier
+ *
+ * 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.
+ *
+ * This file contains code that was originally in the files ibm44x.h
+ * and ebony.h, which were written by Matt Porter of MontaVista Software Inc.
+ */
+
+#ifdef __KERNEL__
+#ifndef __PPC_PLATFORMS_IBM440GP_H
+#define __PPC_PLATFORMS_IBM440GP_H
+
+#include <linux/config.h>
+
+/* UART */
+#define PPC440GP_UART0_ADDR	0x0000000140000200ULL
+#define PPC440GP_UART1_ADDR	0x0000000140000300ULL
+#define UART0_INT		0
+#define UART1_INT		1
+
+/* Clock and Power Management */
+#define IBM_CPM_IIC0		0x80000000	/* IIC interface */
+#define IBM_CPM_IIC1		0x40000000	/* IIC interface */
+#define IBM_CPM_PCI		0x20000000	/* PCI bridge */
+#define IBM_CPM_CPU		0x02000000	/* processor core */
+#define IBM_CPM_DMA		0x01000000	/* DMA controller */
+#define IBM_CPM_BGO		0x00800000	/* PLB to OPB bus arbiter */
+#define IBM_CPM_BGI		0x00400000	/* OPB to PLB bridge */
+#define IBM_CPM_EBC		0x00200000	/* External Bux Controller */
+#define IBM_CPM_EBM		0x00100000	/* Ext Bus Master Interface */
+#define IBM_CPM_DMC		0x00080000	/* SDRAM peripheral controller */
+#define IBM_CPM_PLB		0x00040000	/* PLB bus arbiter */
+#define IBM_CPM_SRAM		0x00020000	/* SRAM memory controller */
+#define IBM_CPM_PPM		0x00002000	/* PLB Performance Monitor */
+#define IBM_CPM_UIC1		0x00001000	/* Universal Interrupt Controller */
+#define IBM_CPM_GPIO0		0x00000800	/* General Purpose IO (??) */
+#define IBM_CPM_GPT		0x00000400	/* General Purpose Timers  */
+#define IBM_CPM_UART0		0x00000200	/* serial port 0 */
+#define IBM_CPM_UART1		0x00000100	/* serial port 1 */
+#define IBM_CPM_UIC0		0x00000080	/* Universal Interrupt Controller */
+#define IBM_CPM_TMRCLK		0x00000040	/* CPU timers */
+
+#define DFLT_IBM4xx_PM		~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \
+				| IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \
+				| IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \
+				| IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI)
+/*
+ * Serial port defines
+ */
+#define RS_TABLE_SIZE	2
+
+#include <asm/ibm44x.h>
+#include <syslib/ibm440gp_common.h>
+
+#endif /* __PPC_PLATFORMS_IBM440GP_H */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibm440gx.c b/arch/ppc/platforms/4xx/ibm440gx.c
new file mode 100644
index 0000000..1f38f42
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm440gx.c
@@ -0,0 +1,234 @@
+/*
+ * arch/ppc/platforms/4xx/ibm440gx.c
+ *
+ * PPC440GX I/O descriptions
+ *
+ * Matt Porter <mporter@mvista.com>
+ * Copyright 2002-2004 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <platforms/4xx/ibm440gx.h>
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+
+static struct ocp_func_emac_data ibm440gx_emac0_def = {
+	.rgmii_idx	= -1,		/* No RGMII */
+	.rgmii_mux	= -1,		/* No RGMII */
+	.zmii_idx       = 0,            /* ZMII device index */
+	.zmii_mux       = 0,            /* ZMII input of this EMAC */
+	.mal_idx        = 0,            /* MAL device index */
+	.mal_rx_chan    = 0,            /* MAL rx channel number */
+	.mal_tx_chan    = 0,            /* MAL tx channel number */
+	.wol_irq        = 61,   	/* WOL interrupt number */
+	.mdio_idx       = -1,           /* No shared MDIO */
+	.tah_idx	= -1,		/* No TAH */
+};
+
+static struct ocp_func_emac_data ibm440gx_emac1_def = {
+	.rgmii_idx	= -1,		/* No RGMII */
+	.rgmii_mux	= -1,		/* No RGMII */
+	.zmii_idx       = 0,            /* ZMII device index */
+	.zmii_mux       = 1,            /* ZMII input of this EMAC */
+	.mal_idx        = 0,            /* MAL device index */
+	.mal_rx_chan    = 1,            /* MAL rx channel number */
+	.mal_tx_chan    = 1,            /* MAL tx channel number */
+	.wol_irq        = 63,  		/* WOL interrupt number */
+	.mdio_idx       = -1,           /* No shared MDIO */
+	.tah_idx	= -1,		/* No TAH */
+};
+
+static struct ocp_func_emac_data ibm440gx_emac2_def = {
+	.rgmii_idx	= 0,		/* RGMII device index */
+	.rgmii_mux	= 0,		/* RGMII input of this EMAC */
+	.zmii_idx       = 0,            /* ZMII device index */
+	.zmii_mux       = 2,            /* ZMII input of this EMAC */
+	.mal_idx        = 0,            /* MAL device index */
+	.mal_rx_chan    = 2,            /* MAL rx channel number */
+	.mal_tx_chan    = 2,            /* MAL tx channel number */
+	.wol_irq        = 65,  		/* WOL interrupt number */
+	.mdio_idx       = -1,           /* No shared MDIO */
+	.tah_idx	= 0,		/* TAH device index */
+	.jumbo		= 1,		/* Jumbo frames supported */
+};
+
+static struct ocp_func_emac_data ibm440gx_emac3_def = {
+	.rgmii_idx	= 0,		/* RGMII device index */
+	.rgmii_mux	= 1,		/* RGMII input of this EMAC */
+	.zmii_idx       = 0,            /* ZMII device index */
+	.zmii_mux       = 3,            /* ZMII input of this EMAC */
+	.mal_idx        = 0,            /* MAL device index */
+	.mal_rx_chan    = 3,            /* MAL rx channel number */
+	.mal_tx_chan    = 3,            /* MAL tx channel number */
+	.wol_irq        = 67,  		/* WOL interrupt number */
+	.mdio_idx       = -1,           /* No shared MDIO */
+	.tah_idx	= 1,		/* TAH device index */
+	.jumbo		= 1,		/* Jumbo frames supported */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ibm440gx_mal0_def = {
+	.num_tx_chans   = 4,    	/* Number of TX channels */
+	.num_rx_chans   = 4,    	/* Number of RX channels */
+	.txeob_irq	= 10,		/* TX End Of Buffer IRQ  */
+	.rxeob_irq	= 11,		/* RX End Of Buffer IRQ  */
+	.txde_irq	= 33,		/* TX Descriptor Error IRQ */
+	.rxde_irq	= 34,		/* RX Descriptor Error IRQ */
+	.serr_irq	= 32,		/* MAL System Error IRQ    */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ibm440gx_iic0_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+
+static struct ocp_func_iic_data ibm440gx_iic1_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_OPB,
+	  .index	= 0,
+	  .paddr	= 0x0000000140000000ULL,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 0,
+	  .paddr	= PPC440GX_UART0_ADDR,
+	  .irq		= UART0_INT,
+	  .pm		= IBM_CPM_UART0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 1,
+	  .paddr	= PPC440GX_UART1_ADDR,
+	  .irq		= UART1_INT,
+	  .pm		= IBM_CPM_UART1,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .index	= 0,
+	  .paddr	= 0x0000000140000400ULL,
+	  .irq		= 2,
+	  .pm		= IBM_CPM_IIC0,
+	  .additions	= &ibm440gx_iic0_def,
+	  .show		= &ocp_show_iic_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .index	= 1,
+	  .paddr	= 0x0000000140000500ULL,
+	  .irq		= 3,
+	  .pm		= IBM_CPM_IIC1,
+	  .additions	= &ibm440gx_iic1_def,
+	  .show		= &ocp_show_iic_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_GPIO,
+	  .index	= 0,
+	  .paddr	= 0x0000000140000700ULL,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= IBM_CPM_GPIO0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_MAL,
+	  .paddr	= OCP_PADDR_NA,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm440gx_mal0_def,
+	  .show		= &ocp_show_mal_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 0,
+	  .paddr	= 0x0000000140000800ULL,
+	  .irq		= 60,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm440gx_emac0_def,
+	  .show		= &ocp_show_emac_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 1,
+	  .paddr	= 0x0000000140000900ULL,
+	  .irq		= 62,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm440gx_emac1_def,
+	  .show		= &ocp_show_emac_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 2,
+	  .paddr	= 0x0000000140000C00ULL,
+	  .irq		= 64,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm440gx_emac2_def,
+	  .show		= &ocp_show_emac_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 3,
+	  .paddr	= 0x0000000140000E00ULL,
+	  .irq		= 66,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm440gx_emac3_def,
+	  .show		= &ocp_show_emac_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_RGMII,
+	  .paddr	= 0x0000000140000790ULL,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_ZMII,
+	  .paddr	= 0x0000000140000780ULL,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_TAH,
+	  .index	= 0,
+	  .paddr	= 0x0000000140000b50ULL,
+	  .irq		= 68,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_TAH,
+	  .index	= 1,
+	  .paddr	= 0x0000000140000d50ULL,
+	  .irq		= 69,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_INVALID
+	}
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+	{ .polarity 	= 0xfffffe03,
+	  .triggering	= 0x01c00000,
+	  .ext_irq_mask	= 0x000001fc,	/* IRQ0 - IRQ6 */
+	},
+	{ .polarity 	= 0xffffc0ff,
+	  .triggering	= 0x00ff8000,
+	  .ext_irq_mask	= 0x00003f00,	/* IRQ7 - IRQ12 */
+	},
+	{ .polarity 	= 0xffff83ff,
+	  .triggering	= 0x000f83c0,
+	  .ext_irq_mask	= 0x00007c00,	/* IRQ13 - IRQ17 */
+	},
+};
diff --git a/arch/ppc/platforms/4xx/ibm440gx.h b/arch/ppc/platforms/4xx/ibm440gx.h
new file mode 100644
index 0000000..0b59d8d
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm440gx.h
@@ -0,0 +1,74 @@
+/*
+ * arch/ppc/platforms/ibm440gx.h
+ *
+ * PPC440GX definitions
+ *
+ * Matt Porter <mporter@mvista.com>
+ *
+ * Copyright 2002 Roland Dreier
+ * Copyright 2003 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.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __PPC_PLATFORMS_IBM440GX_H
+#define __PPC_PLATFORMS_IBM440GX_H
+
+#include <linux/config.h>
+
+#include <asm/ibm44x.h>
+
+/* UART */
+#define PPC440GX_UART0_ADDR	0x0000000140000200ULL
+#define PPC440GX_UART1_ADDR	0x0000000140000300ULL
+#define UART0_INT		0
+#define UART1_INT		1
+
+/* Clock and Power Management */
+#define IBM_CPM_IIC0		0x80000000	/* IIC interface */
+#define IBM_CPM_IIC1		0x40000000	/* IIC interface */
+#define IBM_CPM_PCI		0x20000000	/* PCI bridge */
+#define IBM_CPM_RGMII		0x10000000	/* RGMII */
+#define IBM_CPM_TAHOE0		0x08000000	/* TAHOE 0 */
+#define IBM_CPM_TAHOE1		0x04000000	/* TAHOE 1 */
+#define IBM_CPM_CPU		    0x02000000	/* processor core */
+#define IBM_CPM_DMA		    0x01000000	/* DMA controller */
+#define IBM_CPM_BGO		    0x00800000	/* PLB to OPB bus arbiter */
+#define IBM_CPM_BGI		    0x00400000	/* OPB to PLB bridge */
+#define IBM_CPM_EBC		    0x00200000	/* External Bux Controller */
+#define IBM_CPM_EBM		    0x00100000	/* Ext Bus Master Interface */
+#define IBM_CPM_DMC		    0x00080000	/* SDRAM peripheral controller */
+#define IBM_CPM_PLB		    0x00040000	/* PLB bus arbiter */
+#define IBM_CPM_SRAM		0x00020000	/* SRAM memory controller */
+#define IBM_CPM_PPM		    0x00002000	/* PLB Performance Monitor */
+#define IBM_CPM_UIC1		0x00001000	/* Universal Interrupt Controller */
+#define IBM_CPM_GPIO0		0x00000800	/* General Purpose IO (??) */
+#define IBM_CPM_GPT		    0x00000400	/* General Purpose Timers  */
+#define IBM_CPM_UART0		0x00000200	/* serial port 0 */
+#define IBM_CPM_UART1		0x00000100	/* serial port 1 */
+#define IBM_CPM_UIC0		0x00000080	/* Universal Interrupt Controller */
+#define IBM_CPM_TMRCLK		0x00000040	/* CPU timers */
+#define IBM_CPM_EMAC0  		0x00000020	/* EMAC 0     */
+#define IBM_CPM_EMAC1  		0x00000010	/* EMAC 1     */
+#define IBM_CPM_EMAC2  		0x00000008	/* EMAC 2     */
+#define IBM_CPM_EMAC3  		0x00000004	/* EMAC 3     */
+
+#define DFLT_IBM4xx_PM		~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \
+				| IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \
+				| IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \
+				| IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI \
+				| IBM_CPM_TAHOE0 | IBM_CPM_TAHOE1 \
+				| IBM_CPM_EMAC0 | IBM_CPM_EMAC1 \
+			  	| IBM_CPM_EMAC2 | IBM_CPM_EMAC3 )
+/*
+ * Serial port defines
+ */
+#define RS_TABLE_SIZE	2
+
+#endif /* __PPC_PLATFORMS_IBM440GX_H */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibm440sp.c b/arch/ppc/platforms/4xx/ibm440sp.c
new file mode 100644
index 0000000..a203efb4
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm440sp.c
@@ -0,0 +1,131 @@
+/*
+ * arch/ppc/platforms/4xx/ibm440sp.c
+ *
+ * PPC440SP I/O descriptions
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2002-2005 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <platforms/4xx/ibm440sp.h>
+#include <asm/ocp.h>
+
+static struct ocp_func_emac_data ibm440sp_emac0_def = {
+	.rgmii_idx	= -1,		/* No RGMII */
+	.rgmii_mux	= -1,		/* No RGMII */
+	.zmii_idx       = -1,           /* No ZMII */
+	.zmii_mux       = -1,           /* No ZMII */
+	.mal_idx        = 0,            /* MAL device index */
+	.mal_rx_chan    = 0,            /* MAL rx channel number */
+	.mal_tx_chan    = 0,            /* MAL tx channel number */
+	.wol_irq        = 61,  		/* WOL interrupt number */
+	.mdio_idx       = -1,           /* No shared MDIO */
+	.tah_idx	= -1,		/* No TAH */
+	.jumbo		= 1,		/* Jumbo frames supported */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ibm440sp_mal0_def = {
+	.num_tx_chans   = 4,    	/* Number of TX channels */
+	.num_rx_chans   = 4,    	/* Number of RX channels */
+	.txeob_irq	= 38,		/* TX End Of Buffer IRQ  */
+	.rxeob_irq	= 39,		/* RX End Of Buffer IRQ  */
+	.txde_irq	= 34,		/* TX Descriptor Error IRQ */
+	.rxde_irq	= 35,		/* RX Descriptor Error IRQ */
+	.serr_irq	= 33,		/* MAL System Error IRQ    */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ibm440sp_iic0_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+
+static struct ocp_func_iic_data ibm440sp_iic1_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_OPB,
+	  .index	= 0,
+	  .paddr	= 0x0000000140000000ULL,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 0,
+	  .paddr	= PPC440SP_UART0_ADDR,
+	  .irq		= UART0_INT,
+	  .pm		= IBM_CPM_UART0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 1,
+	  .paddr	= PPC440SP_UART1_ADDR,
+	  .irq		= UART1_INT,
+	  .pm		= IBM_CPM_UART1,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 2,
+	  .paddr	= PPC440SP_UART2_ADDR,
+	  .irq		= UART2_INT,
+	  .pm		= IBM_CPM_UART2,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .index	= 0,
+	  .paddr	= 0x00000001f0000400ULL,
+	  .irq		= 2,
+	  .pm		= IBM_CPM_IIC0,
+	  .additions	= &ibm440sp_iic0_def,
+	  .show		= &ocp_show_iic_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .index	= 1,
+	  .paddr	= 0x00000001f0000500ULL,
+	  .irq		= 3,
+	  .pm		= IBM_CPM_IIC1,
+	  .additions	= &ibm440sp_iic1_def,
+	  .show		= &ocp_show_iic_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_GPIO,
+	  .index	= 0,
+	  .paddr	= 0x00000001f0000700ULL,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= IBM_CPM_GPIO0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_MAL,
+	  .paddr	= OCP_PADDR_NA,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm440sp_mal0_def,
+	  .show		= &ocp_show_mal_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 0,
+	  .paddr	= 0x00000001f0000800ULL,
+	  .irq		= 60,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibm440sp_emac0_def,
+	  .show		= &ocp_show_emac_data,
+	},
+	{ .vendor	= OCP_VENDOR_INVALID
+	}
+};
diff --git a/arch/ppc/platforms/4xx/ibm440sp.h b/arch/ppc/platforms/4xx/ibm440sp.h
new file mode 100644
index 0000000..c71e46a
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm440sp.h
@@ -0,0 +1,64 @@
+/*
+ * arch/ppc/platforms/4xx/ibm440sp.h
+ *
+ * PPC440SP definitions
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Copyright 2004-2005 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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __PPC_PLATFORMS_IBM440SP_H
+#define __PPC_PLATFORMS_IBM440SP_H
+
+#include <linux/config.h>
+
+#include <asm/ibm44x.h>
+
+/* UART */
+#define PPC440SP_UART0_ADDR	0x00000001f0000200ULL
+#define PPC440SP_UART1_ADDR	0x00000001f0000300ULL
+#define PPC440SP_UART2_ADDR	0x00000001f0000600ULL
+#define UART0_INT		0
+#define UART1_INT		1
+#define UART2_INT		2
+
+/* Clock and Power Management */
+#define IBM_CPM_IIC0		0x80000000	/* IIC interface */
+#define IBM_CPM_IIC1		0x40000000	/* IIC interface */
+#define IBM_CPM_PCI		0x20000000	/* PCI bridge */
+#define IBM_CPM_CPU		    0x02000000	/* processor core */
+#define IBM_CPM_DMA		    0x01000000	/* DMA controller */
+#define IBM_CPM_BGO		    0x00800000	/* PLB to OPB bus arbiter */
+#define IBM_CPM_BGI		    0x00400000	/* OPB to PLB bridge */
+#define IBM_CPM_EBC		    0x00200000	/* External Bux Controller */
+#define IBM_CPM_EBM		    0x00100000	/* Ext Bus Master Interface */
+#define IBM_CPM_DMC		    0x00080000	/* SDRAM peripheral controller */
+#define IBM_CPM_PLB		    0x00040000	/* PLB bus arbiter */
+#define IBM_CPM_SRAM		0x00020000	/* SRAM memory controller */
+#define IBM_CPM_PPM		    0x00002000	/* PLB Performance Monitor */
+#define IBM_CPM_UIC1		0x00001000	/* Universal Interrupt Controller */
+#define IBM_CPM_GPIO0		0x00000800	/* General Purpose IO (??) */
+#define IBM_CPM_GPT		    0x00000400	/* General Purpose Timers  */
+#define IBM_CPM_UART0		0x00000200	/* serial port 0 */
+#define IBM_CPM_UART1		0x00000100	/* serial port 1 */
+#define IBM_CPM_UART2		0x00000100	/* serial port 1 */
+#define IBM_CPM_UIC0		0x00000080	/* Universal Interrupt Controller */
+#define IBM_CPM_TMRCLK		0x00000040	/* CPU timers */
+#define IBM_CPM_EMAC0  		0x00000020	/* EMAC 0     */
+
+#define DFLT_IBM4xx_PM		~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \
+				| IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \
+				| IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \
+				| IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI \
+				| IBM_CPM_TAHOE0 | IBM_CPM_TAHOE1 \
+				| IBM_CPM_EMAC0 | IBM_CPM_EMAC1 \
+			  	| IBM_CPM_EMAC2 | IBM_CPM_EMAC3 )
+#endif /* __PPC_PLATFORMS_IBM440SP_H */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibmnp405h.c b/arch/ppc/platforms/4xx/ibmnp405h.c
new file mode 100644
index 0000000..ecdc5be
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibmnp405h.c
@@ -0,0 +1,172 @@
+/*
+ * arch/ppc/platforms/4xx/ibmnp405h.c
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2000-2002 (c) MontaVista, Software, Inc.  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/init.h>
+#include <asm/ocp.h>
+#include <platforms/4xx/ibmnp405h.h>
+
+static struct ocp_func_emac_data ibmnp405h_emac0_def = {
+	.rgmii_idx	= -1,		/* No RGMII */
+	.rgmii_mux	= -1,		/* No RGMII */
+	.zmii_idx	= 0,		/* ZMII device index */
+	.zmii_mux	= 0,		/* ZMII input of this EMAC */
+	.mal_idx	= 0,		/* MAL device index */
+	.mal_rx_chan	= 0,		/* MAL rx channel number */
+	.mal_tx_chan	= 0,		/* MAL tx channel number */
+	.wol_irq	= 41,		/* WOL interrupt number */
+	.mdio_idx	= -1,		/* No shared MDIO */
+	.tah_idx	= -1,		/* No TAH */
+};
+
+static struct ocp_func_emac_data ibmnp405h_emac1_def = {
+	.rgmii_idx	= -1,		/* No RGMII */
+	.rgmii_mux	= -1,		/* No RGMII */
+	.zmii_idx	= 0,		/* ZMII device index */
+	.zmii_mux	= 1,		/* ZMII input of this EMAC */
+	.mal_idx	= 0,		/* MAL device index */
+	.mal_rx_chan	= 1,		/* MAL rx channel number */
+	.mal_tx_chan	= 1,		/* MAL tx channel number */
+	.wol_irq	= 41,		/* WOL interrupt number */
+	.mdio_idx	= -1,		/* No shared MDIO */
+	.tah_idx	= -1,		/* No TAH */
+};
+static struct ocp_func_emac_data ibmnp405h_emac2_def = {
+	.rgmii_idx	= -1,		/* No RGMII */
+	.rgmii_mux	= -1,		/* No RGMII */
+	.zmii_idx	= 0,		/* ZMII device index */
+	.zmii_mux	= 2,		/* ZMII input of this EMAC */
+	.mal_idx	= 0,		/* MAL device index */
+	.mal_rx_chan	= 2,		/* MAL rx channel number */
+	.mal_tx_chan	= 2,		/* MAL tx channel number */
+	.wol_irq	= 41,		/* WOL interrupt number */
+	.mdio_idx	= -1,		/* No shared MDIO */
+	.tah_idx	= -1,		/* No TAH */
+};
+static struct ocp_func_emac_data ibmnp405h_emac3_def = {
+	.rgmii_idx	= -1,		/* No RGMII */
+	.rgmii_mux	= -1,		/* No RGMII */
+	.zmii_idx	= 0,		/* ZMII device index */
+	.zmii_mux	= 3,		/* ZMII input of this EMAC */
+	.mal_idx	= 0,		/* MAL device index */
+	.mal_rx_chan	= 3,		/* MAL rx channel number */
+	.mal_tx_chan	= 3,		/* MAL tx channel number */
+	.wol_irq	= 41,		/* WOL interrupt number */
+	.mdio_idx	= -1,		/* No shared MDIO */
+	.tah_idx	= -1,		/* No TAH */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ibmnp405h_mal0_def = {
+	.num_tx_chans	= 8,		/* Number of TX channels */
+	.num_rx_chans	= 4,		/* Number of RX channels */
+	.txeob_irq	= 17,		/* TX End Of Buffer IRQ  */
+	.rxeob_irq	= 18,		/* RX End Of Buffer IRQ  */
+	.txde_irq	= 46,		/* TX Descriptor Error IRQ */
+	.rxde_irq	= 47,		/* RX Descriptor Error IRQ */
+	.serr_irq	= 45,		/* MAL System Error IRQ    */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ibmnp405h_iic0_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_OPB,
+	  .index	= 0,
+	  .paddr	= 0xEF600000,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 0,
+	  .paddr	= UART0_IO_BASE,
+	  .irq		= UART0_INT,
+	  .pm		= IBM_CPM_UART0
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 1,
+	  .paddr	= UART1_IO_BASE,
+	  .irq		= UART1_INT,
+	  .pm		= IBM_CPM_UART1
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .paddr	= 0xEF600500,
+	  .irq		= 2,
+	  .pm		= IBM_CPM_IIC0,
+	  .additions	= &ibmnp405h_iic0_def,
+	  .show		= &ocp_show_iic_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_GPIO,
+	  .paddr	= 0xEF600700,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= IBM_CPM_GPIO0
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_MAL,
+	  .paddr	= OCP_PADDR_NA,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ibmnp405h_mal0_def,
+	  .show		= &ocp_show_mal_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 0,
+	  .paddr	= EMAC0_BASE,
+	  .irq		= 37,
+	  .pm		= IBM_CPM_EMAC0,
+	  .additions	= &ibmnp405h_emac0_def,
+	  .show		= &ocp_show_emac_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 1,
+	  .paddr	= 0xEF600900,
+	  .irq		= 38,
+	  .pm		= IBM_CPM_EMAC1,
+	  .additions	= &ibmnp405h_emac1_def,
+	  .show		= &ocp_show_emac_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 2,
+	  .paddr	= 0xEF600a00,
+	  .irq		= 39,
+	  .pm		= IBM_CPM_EMAC2,
+	  .additions	= &ibmnp405h_emac2_def,
+	  .show		= &ocp_show_emac_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 3,
+	  .paddr	= 0xEF600b00,
+	  .irq		= 40,
+	  .pm		= IBM_CPM_EMAC3,
+	  .additions	= &ibmnp405h_emac3_def,
+	  .show		= &ocp_show_emac_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_ZMII,
+	  .paddr	= 0xEF600C10,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_INVALID
+	}
+};
diff --git a/arch/ppc/platforms/4xx/ibmnp405h.h b/arch/ppc/platforms/4xx/ibmnp405h.h
new file mode 100644
index 0000000..e2c2b06
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibmnp405h.h
@@ -0,0 +1,157 @@
+/*
+ * arch/ppc/platforms/4xx/ibmnp405h.h
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2002 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IBMNP405H_H__
+#define __ASM_IBMNP405H_H__
+
+#include <linux/config.h>
+
+/* ibm405.h at bottom of this file */
+
+#define PPC405_PCI_CONFIG_ADDR	0xeec00000
+#define PPC405_PCI_CONFIG_DATA	0xeec00004
+#define PPC405_PCI_PHY_MEM_BASE	0x80000000	/* hose_a->pci_mem_offset */
+						/* setbat */
+#define PPC405_PCI_MEM_BASE	PPC405_PCI_PHY_MEM_BASE	/* setbat */
+#define PPC405_PCI_PHY_IO_BASE	0xe8000000	/* setbat */
+#define PPC405_PCI_IO_BASE	PPC405_PCI_PHY_IO_BASE	/* setbat */
+
+#define PPC405_PCI_LOWER_MEM	0x00000000	/* hose_a->mem_space.start */
+#define PPC405_PCI_UPPER_MEM	0xBfffffff	/* hose_a->mem_space.end */
+#define PPC405_PCI_LOWER_IO	0x00000000	/* hose_a->io_space.start */
+#define PPC405_PCI_UPPER_IO	0x0000ffff	/* hose_a->io_space.end */
+
+#define PPC405_ISA_IO_BASE	PPC405_PCI_IO_BASE
+
+#define PPC4xx_PCI_IO_ADDR	((uint)PPC405_PCI_PHY_IO_BASE)
+#define PPC4xx_PCI_IO_SIZE	((uint)64*1024)
+#define PPC4xx_PCI_CFG_ADDR	((uint)PPC405_PCI_CONFIG_ADDR)
+#define PPC4xx_PCI_CFG_SIZE	((uint)4*1024)
+#define PPC4xx_PCI_LCFG_ADDR	((uint)0xef400000)
+#define PPC4xx_PCI_LCFG_SIZE	((uint)4*1024)
+#define PPC4xx_ONB_IO_ADDR	((uint)0xef600000)
+#define PPC4xx_ONB_IO_SIZE	((uint)4*1024)
+
+/* serial port defines */
+#define RS_TABLE_SIZE	4
+
+#define UART0_INT	0
+#define UART1_INT	1
+#define PCIL0_BASE	0xEF400000
+#define UART0_IO_BASE	0xEF600300
+#define UART1_IO_BASE	0xEF600400
+#define OPB0_BASE	0xEF600600
+#define EMAC0_BASE	0xEF600800
+
+#define BD_EMAC_ADDR(e,i) bi_enetaddr[e][i]
+
+#define STD_UART_OP(num)					\
+	{ 0, BASE_BAUD, 0, UART##num##_INT,			\
+		(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),	\
+		iomem_base:(u8 *) UART##num##_IO_BASE,		\
+		io_type: SERIAL_IO_MEM},
+
+#if defined(CONFIG_UART0_TTYS0)
+#define SERIAL_DEBUG_IO_BASE	UART0_IO_BASE
+#define SERIAL_PORT_DFNS        \
+        STD_UART_OP(0)          \
+        STD_UART_OP(1)
+#endif
+
+#if defined(CONFIG_UART0_TTYS1)
+#define SERIAL_DEBUG_IO_BASE	UART0_IO_BASE
+#define SERIAL_PORT_DFNS        \
+        STD_UART_OP(1)          \
+        STD_UART_OP(0)
+#endif
+
+/* DCR defines */
+/* ------------------------------------------------------------------------- */
+
+#define DCRN_CHCR_BASE	0x0F1
+#define DCRN_CHPSR_BASE	0x0B4
+#define DCRN_CPMSR_BASE	0x0BA
+#define DCRN_CPMFR_BASE	0x0B9
+#define DCRN_CPMER_BASE	0x0B8
+
+/* CPM Clocking & Power Mangement defines */
+#define IBM_CPM_PCI		0x40000000	/* PCI */
+#define IBM_CPM_EMAC2	0x20000000	/* EMAC 2 MII */
+#define IBM_CPM_EMAC3	0x04000000	/* EMAC 3 MII */
+#define IBM_CPM_EMAC0	0x00800000	/* EMAC 0 MII */
+#define IBM_CPM_EMAC1	0x00100000	/* EMAC 1 MII */
+#define IBM_CPM_EMMII	0	/* Shift value for MII */
+#define IBM_CPM_EMRX	1	/* Shift value for recv */
+#define IBM_CPM_EMTX	2	/* Shift value for MAC */
+#define IBM_CPM_UIC1	0x00020000	/* Universal Interrupt Controller */
+#define IBM_CPM_UIC0	0x00010000	/* Universal Interrupt Controller */
+#define IBM_CPM_CPU	0x00008000	/* processor core */
+#define IBM_CPM_EBC	0x00004000	/* ROM/SRAM peripheral controller */
+#define IBM_CPM_SDRAM0	0x00002000	/* SDRAM memory controller */
+#define IBM_CPM_GPIO0	0x00001000	/* General Purpose IO (??) */
+#define IBM_CPM_HDLC	0x00000800	/* HDCL */
+#define IBM_CPM_TMRCLK	0x00000400	/* CPU timers */
+#define IBM_CPM_PLB	0x00000100	/* PLB bus arbiter */
+#define IBM_CPM_OPB	0x00000080	/* PLB to OPB bridge */
+#define IBM_CPM_DMA	0x00000040	/* DMA controller */
+#define IBM_CPM_IIC0	0x00000010	/* IIC interface */
+#define IBM_CPM_UART0	0x00000002	/* serial port 0 */
+#define IBM_CPM_UART1	0x00000001	/* serial port 1 */
+/* this is the default setting for devices put to sleep when booting */
+
+#define DFLT_IBM4xx_PM	~(IBM_CPM_UIC0 | IBM_CPM_UIC1 | IBM_CPM_CPU 	\
+			| IBM_CPM_EBC | IBM_CPM_SDRAM0 | IBM_CPM_PLB 	\
+			| IBM_CPM_OPB | IBM_CPM_TMRCLK | IBM_CPM_DMA	\
+			| IBM_CPM_EMAC0 | IBM_CPM_EMAC1 | IBM_CPM_EMAC2	\
+			| IBM_CPM_EMAC3 | IBM_CPM_PCI)
+
+#define DCRN_DMA0_BASE	0x100
+#define DCRN_DMA1_BASE	0x108
+#define DCRN_DMA2_BASE	0x110
+#define DCRN_DMA3_BASE	0x118
+#define DCRNCAP_DMA_SG	1	/* have DMA scatter/gather capability */
+#define DCRN_DMASR_BASE	0x120
+#define DCRN_EBC_BASE	0x012
+#define DCRN_DCP0_BASE	0x014
+#define DCRN_MAL_BASE	0x180
+#define DCRN_OCM0_BASE	0x018
+#define DCRN_PLB0_BASE	0x084
+#define DCRN_PLLMR_BASE	0x0B0
+#define DCRN_POB0_BASE	0x0A0
+#define DCRN_SDRAM0_BASE 0x010
+#define DCRN_UIC0_BASE	0x0C0
+#define DCRN_UIC1_BASE	0x0D0
+#define DCRN_CPC0_EPRCSR 0x0F3
+
+#define UIC0_UIC1NC	0x00000002
+
+#define CHR1_CETE	0x00000004	/* CPU external timer enable */
+#define UIC0	DCRN_UIC0_BASE
+#define UIC1	DCRN_UIC1_BASE
+
+#undef NR_UICS
+#define NR_UICS	2
+
+/* EMAC DCRN's FIXME: armin */
+#define DCRN_MALRXCTP2R(base)	((base) + 0x42)	/* Channel Rx 2 Channel Table Pointer */
+#define DCRN_MALRXCTP3R(base)	((base) + 0x43)	/* Channel Rx 3 Channel Table Pointer */
+#define DCRN_MALTXCTP4R(base)	((base) + 0x24)	/* Channel Tx 4 Channel Table Pointer */
+#define DCRN_MALTXCTP5R(base)	((base) + 0x25)	/* Channel Tx 5 Channel Table Pointer */
+#define DCRN_MALTXCTP6R(base)	((base) + 0x26)	/* Channel Tx 6 Channel Table Pointer */
+#define DCRN_MALTXCTP7R(base)	((base) + 0x27)	/* Channel Tx 7 Channel Table Pointer */
+#define DCRN_MALRCBS2(base)	((base) + 0x62)	/* Channel Rx 2 Channel Buffer Size */
+#define DCRN_MALRCBS3(base)	((base) + 0x63)	/* Channel Rx 3 Channel Buffer Size */
+
+#include <asm/ibm405.h>
+
+#endif				/* __ASM_IBMNP405H_H__ */
+#endif				/* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibmstb4.c b/arch/ppc/platforms/4xx/ibmstb4.c
new file mode 100644
index 0000000..874d16b
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibmstb4.c
@@ -0,0 +1,83 @@
+/*
+ * arch/ppc/platforms/4xx/ibmstb4.c
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2000-2001 (c) MontaVista, Software, Inc.  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/init.h>
+#include <asm/ocp.h>
+#include <platforms/4xx/ibmstb4.h>
+
+static struct ocp_func_iic_data ibmstb4_iic0_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+
+static struct ocp_func_iic_data ibmstb4_iic1_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] __initdata = {
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 0,
+	  .paddr	= UART0_IO_BASE,
+	  .irq		= UART0_INT,
+	  .pm		= IBM_CPM_UART0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 1,
+	  .paddr	= UART1_IO_BASE,
+	  .irq		= UART1_INT,
+	  .pm		= IBM_CPM_UART1,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 2,
+	  .paddr	= UART2_IO_BASE,
+	  .irq		= UART2_INT,
+	  .pm		= IBM_CPM_UART2,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .paddr	= IIC0_BASE,
+	  .irq		= IIC0_IRQ,
+	  .pm		= IBM_CPM_IIC0,
+	  .additions	= &ibmstb4_iic0_def,
+	  .show		= &ocp_show_iic_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .paddr	= IIC1_BASE,
+	  .irq		= IIC1_IRQ,
+	  .pm		= IBM_CPM_IIC1,
+	  .additions	= &ibmstb4_iic1_def,
+	  .show		= &ocp_show_iic_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_GPIO,
+	  .paddr	= GPIO0_BASE,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= IBM_CPM_GPIO0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IDE,
+	  .paddr	= IDE0_BASE,
+	  .irq		= IDE0_IRQ,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_USB,
+	  .paddr	= USB0_BASE,
+	  .irq		= USB0_IRQ,
+	  .pm		= OCP_CPM_NA,
+	},
+	{ .vendor	= OCP_VENDOR_INVALID,
+	}
+};
diff --git a/arch/ppc/platforms/4xx/ibmstb4.h b/arch/ppc/platforms/4xx/ibmstb4.h
new file mode 100644
index 0000000..bcb4b1e
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibmstb4.h
@@ -0,0 +1,238 @@
+/*
+ * arch/ppc/platforms/4xx/ibmstb4.h
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IBMSTB4_H__
+#define __ASM_IBMSTB4_H__
+
+#include <linux/config.h>
+
+/* serial port defines */
+#define STB04xxx_IO_BASE	((uint)0xe0000000)
+#define PPC4xx_PCI_IO_ADDR	STB04xxx_IO_BASE
+#define PPC4xx_ONB_IO_PADDR	STB04xxx_IO_BASE
+#define PPC4xx_ONB_IO_VADDR	((uint)0xe0000000)
+#define PPC4xx_ONB_IO_SIZE	((uint)14*64*1024)
+
+/*
+ * map STB04xxx internal i/o address (0x400x00xx) to an address
+ * which is below the 2GB limit...
+ *
+ * 4000 000x	uart1		-> 0xe000 000x
+ * 4001 00xx	ppu
+ * 4002 00xx	smart card
+ * 4003 000x	iic
+ * 4004 000x	uart0
+ * 4005 0xxx	timer
+ * 4006 00xx	gpio
+ * 4007 00xx	smart card
+ * 400b 000x	iic
+ * 400c 000x	scp
+ * 400d 000x	modem
+ * 400e 000x	uart2
+*/
+#define STB04xxx_MAP_IO_ADDR(a)	(((uint)(a)) + (STB04xxx_IO_BASE - 0x40000000))
+
+#define RS_TABLE_SIZE		3
+#define UART0_INT		20
+
+#ifdef __BOOTER__
+#define UART0_IO_BASE		0x40040000
+#else
+#define UART0_IO_BASE		0xe0040000
+#endif
+
+#define UART1_INT		21
+
+#ifdef __BOOTER__
+#define UART1_IO_BASE		0x40000000
+#else
+#define UART1_IO_BASE		0xe0000000
+#endif
+
+#define UART2_INT		31
+#ifdef __BOOTER__
+#define UART2_IO_BASE		0x400e0000
+#else
+#define UART2_IO_BASE		0xe00e0000
+#endif
+
+#define IDE0_BASE	0x400F0000
+#define IDE0_SIZE	0x200
+#define IDE0_IRQ	25
+#define IIC0_BASE	0x40030000
+#define IIC1_BASE	0x400b0000
+#define OPB0_BASE	0x40000000
+#define GPIO0_BASE	0x40060000
+
+#define USB0_IRQ	18
+#define USB0_BASE	STB04xxx_MAP_IO_ADDR(0x40010000)
+#define USB0_EXTENT 4096
+
+#define IIC_NUMS 2
+#define UART_NUMS	3
+#define IIC0_IRQ	9
+#define IIC1_IRQ	10
+#define IIC_OWN		0x55
+#define IIC_CLOCK	50
+
+#define BD_EMAC_ADDR(e,i) bi_enetaddr[i]
+
+#define STD_UART_OP(num)					\
+	{ 0, BASE_BAUD, 0, UART##num##_INT,			\
+		(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),	\
+		iomem_base: (u8 *)UART##num##_IO_BASE,		\
+		io_type: SERIAL_IO_MEM},
+
+#if defined(CONFIG_UART0_TTYS0)
+#define SERIAL_DEBUG_IO_BASE	UART0_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)		\
+	STD_UART_OP(2)
+#endif
+
+#if defined(CONFIG_UART0_TTYS1)
+#define SERIAL_DEBUG_IO_BASE	UART2_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(1)		\
+	STD_UART_OP(0)		\
+	STD_UART_OP(2)
+#endif
+
+#if defined(CONFIG_UART0_TTYS2)
+#define SERIAL_DEBUG_IO_BASE	UART2_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(2)		\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)
+#endif
+
+#define DCRN_BE_BASE		0x090
+#define DCRN_DMA0_BASE		0x0C0
+#define DCRN_DMA1_BASE		0x0C8
+#define DCRN_DMA2_BASE		0x0D0
+#define DCRN_DMA3_BASE		0x0D8
+#define DCRNCAP_DMA_CC		1	/* have DMA chained count capability */
+#define DCRN_DMASR_BASE		0x0E0
+#define DCRN_PLB0_BASE		0x054
+#define DCRN_PLB1_BASE		0x064
+#define DCRN_POB0_BASE		0x0B0
+#define DCRN_SCCR_BASE		0x120
+#define DCRN_UIC0_BASE		0x040
+#define DCRN_BE_BASE		0x090
+#define DCRN_DMA0_BASE		0x0C0
+#define DCRN_DMA1_BASE		0x0C8
+#define DCRN_DMA2_BASE		0x0D0
+#define DCRN_DMA3_BASE		0x0D8
+#define DCRN_CIC_BASE 		0x030
+#define DCRN_DMASR_BASE		0x0E0
+#define DCRN_EBIMC_BASE		0x070
+#define DCRN_DCRX_BASE		0x020
+#define DCRN_CPMFR_BASE		0x102
+#define DCRN_SCCR_BASE		0x120
+#define UIC0 DCRN_UIC0_BASE
+
+#define IBM_CPM_IIC0	0x80000000	/* IIC 0 interface */
+#define IBM_CPM_USB0	0x40000000	/* IEEE-1284 */
+#define IBM_CPM_IIC1	0x20000000	/* IIC 1 interface */
+#define IBM_CPM_CPU	0x10000000	/* PPC405B3 clock control */
+#define IBM_CPM_AUD	0x08000000	/* Audio Decoder */
+#define IBM_CPM_EBIU	0x04000000	/* External Bus Interface Unit */
+#define IBM_CPM_SDRAM1	0x02000000	/* SDRAM 1 memory controller */
+#define IBM_CPM_DMA	0x01000000	/* DMA controller */
+#define IBM_CPM_DMA1	0x00800000	/* reserved */
+#define IBM_CPM_XPT1	0x00400000	/* reserved */
+#define IBM_CPM_XPT2	0x00200000	/* reserved */
+#define IBM_CPM_UART1	0x00100000	/* Serial 1 / Infrared */
+#define IBM_CPM_UART0	0x00080000	/* Serial 0 / 16550 */
+#define IBM_CPM_EPI	0x00040000	/* DCR Extension */
+#define IBM_CPM_SC0	0x00020000	/* Smart Card 0 */
+#define IBM_CPM_VID	0x00010000	/* reserved */
+#define IBM_CPM_SC1	0x00008000	/* Smart Card 1 */
+#define IBM_CPM_USBSDRA	0x00004000	/* SDRAM 0 memory controller */
+#define IBM_CPM_XPT0	0x00002000	/* Transport - 54 Mhz */
+#define IBM_CPM_CBS	0x00001000	/* Cross Bar Switch */
+#define IBM_CPM_GPT	0x00000800	/* GPTPWM */
+#define IBM_CPM_GPIO0	0x00000400	/* General Purpose IO 0 */
+#define IBM_CPM_DENC	0x00000200	/* Digital video Encoder */
+#define IBM_CPM_TMRCLK	0x00000100	/* CPU timers */
+#define IBM_CPM_XPT27	0x00000080	/* Transport - 27 Mhz */
+#define IBM_CPM_UIC	0x00000040	/* Universal Interrupt Controller */
+#define IBM_CPM_SSP	0x00000010	/* Modem Serial Interface (SSP) */
+#define IBM_CPM_UART2	0x00000008	/* Serial Control Port */
+#define IBM_CPM_DDIO	0x00000004	/* Descrambler */
+#define IBM_CPM_VID2	0x00000002	/* Video Decoder clock domain 2 */
+
+#define DFLT_IBM4xx_PM	~(IBM_CPM_CPU | IBM_CPM_EBIU | IBM_CPM_SDRAM1 \
+			| IBM_CPM_DMA | IBM_CPM_DMA1 | IBM_CPM_CBS \
+			| IBM_CPM_USBSDRA | IBM_CPM_XPT0 | IBM_CPM_TMRCLK \
+			| IBM_CPM_XPT27 | IBM_CPM_UIC )
+
+#define DCRN_BEAR	(DCRN_BE_BASE + 0x0)	/* Bus Error Address Register */
+#define DCRN_BESR	(DCRN_BE_BASE + 0x1)	/* Bus Error Syndrome Register */
+/* DCRN_BESR */
+#define BESR_DSES	0x80000000	/* Data-Side Error Status */
+#define BESR_DMES	0x40000000	/* DMA Error Status */
+#define BESR_RWS	0x20000000	/* Read/Write Status */
+#define BESR_ETMASK	0x1C000000	/* Error Type */
+#define ET_PROT		0
+#define ET_PARITY	1
+#define ET_NCFG		2
+#define ET_BUSERR	4
+#define ET_BUSTO	6
+
+#define CHR1_CETE	0x00800000	/* CPU external timer enable */
+#define CHR1_PCIPW	0x00008000	/* PCI Int enable/Peripheral Write enable */
+
+#define DCRN_CICCR	(DCRN_CIC_BASE + 0x0)	/* CIC Control Register */
+#define DCRN_DMAS1	(DCRN_CIC_BASE + 0x1)	/* DMA Select1 Register */
+#define DCRN_DMAS2	(DCRN_CIC_BASE + 0x2)	/* DMA Select2 Register */
+#define DCRN_CICVCR	(DCRN_CIC_BASE + 0x3)	/* CIC Video COntro Register */
+#define DCRN_CICSEL3	(DCRN_CIC_BASE + 0x5)	/* CIC Select 3 Register */
+#define DCRN_SGPO	(DCRN_CIC_BASE + 0x6)	/* CIC GPIO Output Register */
+#define DCRN_SGPOD	(DCRN_CIC_BASE + 0x7)	/* CIC GPIO OD Register */
+#define DCRN_SGPTC	(DCRN_CIC_BASE + 0x8)	/* CIC GPIO Tristate Ctrl Reg */
+#define DCRN_SGPI	(DCRN_CIC_BASE + 0x9)	/* CIC GPIO Input Reg */
+
+#define DCRN_DCRXICR	(DCRN_DCRX_BASE + 0x0)	/* Internal Control Register */
+#define DCRN_DCRXISR	(DCRN_DCRX_BASE + 0x1)	/* Internal Status Register */
+#define DCRN_DCRXECR	(DCRN_DCRX_BASE + 0x2)	/* External Control Register */
+#define DCRN_DCRXESR	(DCRN_DCRX_BASE + 0x3)	/* External Status Register */
+#define DCRN_DCRXTAR	(DCRN_DCRX_BASE + 0x4)	/* Target Address Register */
+#define DCRN_DCRXTDR	(DCRN_DCRX_BASE + 0x5)	/* Target Data Register */
+#define DCRN_DCRXIGR	(DCRN_DCRX_BASE + 0x6)	/* Interrupt Generation Register */
+#define DCRN_DCRXBCR	(DCRN_DCRX_BASE + 0x7)	/* Line Buffer Control Register */
+
+#define DCRN_BRCRH0	(DCRN_EBIMC_BASE + 0x0)	/* Bus Region Config High 0 */
+#define DCRN_BRCRH1	(DCRN_EBIMC_BASE + 0x1)	/* Bus Region Config High 1 */
+#define DCRN_BRCRH2	(DCRN_EBIMC_BASE + 0x2)	/* Bus Region Config High 2 */
+#define DCRN_BRCRH3	(DCRN_EBIMC_BASE + 0x3)	/* Bus Region Config High 3 */
+#define DCRN_BRCRH4	(DCRN_EBIMC_BASE + 0x4)	/* Bus Region Config High 4 */
+#define DCRN_BRCRH5	(DCRN_EBIMC_BASE + 0x5)	/* Bus Region Config High 5 */
+#define DCRN_BRCRH6	(DCRN_EBIMC_BASE + 0x6)	/* Bus Region Config High 6 */
+#define DCRN_BRCRH7	(DCRN_EBIMC_BASE + 0x7)	/* Bus Region Config High 7 */
+#define DCRN_BRCR0	(DCRN_EBIMC_BASE + 0x10)	/* BRC 0 */
+#define DCRN_BRCR1	(DCRN_EBIMC_BASE + 0x11)	/* BRC 1 */
+#define DCRN_BRCR2	(DCRN_EBIMC_BASE + 0x12)	/* BRC 2 */
+#define DCRN_BRCR3	(DCRN_EBIMC_BASE + 0x13)	/* BRC 3 */
+#define DCRN_BRCR4	(DCRN_EBIMC_BASE + 0x14)	/* BRC 4 */
+#define DCRN_BRCR5	(DCRN_EBIMC_BASE + 0x15)	/* BRC 5 */
+#define DCRN_BRCR6	(DCRN_EBIMC_BASE + 0x16)	/* BRC 6 */
+#define DCRN_BRCR7	(DCRN_EBIMC_BASE + 0x17)	/* BRC 7 */
+#define DCRN_BEAR0	(DCRN_EBIMC_BASE + 0x20)	/* Bus Error Address Register */
+#define DCRN_BESR0	(DCRN_EBIMC_BASE + 0x21)	/* Bus Error Status Register */
+#define DCRN_BIUCR	(DCRN_EBIMC_BASE + 0x2A)	/* Bus Interfac Unit Ctrl Reg */
+
+#include <asm/ibm405.h>
+
+#endif				/* __ASM_IBMSTB4_H__ */
+#endif				/* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibmstbx25.c b/arch/ppc/platforms/4xx/ibmstbx25.c
new file mode 100644
index 0000000..b895b9c
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibmstbx25.c
@@ -0,0 +1,68 @@
+/*
+ * arch/ppc/platforms/4xx/ibmstbx25.c
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2000-2002 (c) MontaVista, Software, Inc.  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/init.h>
+#include <asm/ocp.h>
+#include <platforms/4xx/ibmstbx25.h>
+#include <asm/ppc4xx_pic.h>
+
+static struct ocp_func_iic_data ibmstbx25_iic0_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] __initdata = {
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index        = 0,
+	  .paddr	= UART0_IO_BASE,
+	  .irq		= UART0_INT,
+	  .pm		= IBM_CPM_UART0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 1,
+	  .paddr	= UART1_IO_BASE,
+	  .irq		= UART1_INT,
+	  .pm		= IBM_CPM_UART1,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 2,
+	  .paddr	= UART2_IO_BASE,
+	  .irq		= UART2_INT,
+	  .pm		= IBM_CPM_UART2,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .paddr	= IIC0_BASE,
+	  .irq		= IIC0_IRQ,
+	  .pm		= IBM_CPM_IIC0,
+	  .additions	= &ibmstbx25_iic0_def,
+	  .show		= &ocp_show_iic_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_GPIO,
+	  .paddr	= GPIO0_BASE,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= IBM_CPM_GPIO0,
+	},
+	{ .vendor	= OCP_VENDOR_INVALID
+	}
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+	{ .polarity 	= 0xffff8f80,
+	  .triggering	= 0x00000000,
+	  .ext_irq_mask	= 0x0000707f,	/* IRQ7 - IRQ9, IRQ0 - IRQ6 */
+	}
+};
diff --git a/arch/ppc/platforms/4xx/ibmstbx25.h b/arch/ppc/platforms/4xx/ibmstbx25.h
new file mode 100644
index 0000000..9a2efc3
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibmstbx25.h
@@ -0,0 +1,261 @@
+/*
+ * arch/ppc/platforms/4xx/ibmstbx25.h
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2002 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IBMSTBX25_H__
+#define __ASM_IBMSTBX25_H__
+
+#include <linux/config.h>
+
+/* serial port defines */
+#define STBx25xx_IO_BASE	((uint)0xe0000000)
+#define PPC4xx_ONB_IO_PADDR	STBx25xx_IO_BASE
+#define PPC4xx_ONB_IO_VADDR	((uint)0xe0000000)
+#define PPC4xx_ONB_IO_SIZE	((uint)14*64*1024)
+
+/*
+ * map STBxxxx internal i/o address (0x400x00xx) to an address
+ * which is below the 2GB limit...
+ *
+ * 4000 000x	uart1		-> 0xe000 000x
+ * 4001 00xx	uart2
+ * 4002 00xx	smart card
+ * 4003 000x	iic
+ * 4004 000x	uart0
+ * 4005 0xxx	timer
+ * 4006 00xx	gpio
+ * 4007 00xx	smart card
+ * 400b 000x	iic
+ * 400c 000x	scp
+ * 400d 000x	modem
+ * 400e 000x	uart2
+*/
+#define STBx25xx_MAP_IO_ADDR(a)	(((uint)(a)) + (STBx25xx_IO_BASE - 0x40000000))
+
+#define RS_TABLE_SIZE	3
+
+#define OPB_BASE_START	0x40000000
+#define EBIU_BASE_START	0xF0100000
+#define DCR_BASE_START  0x0000
+
+#ifdef __BOOTER__
+#define UART1_IO_BASE	0x40000000
+#define UART2_IO_BASE	0x40010000
+#else
+#define UART1_IO_BASE	0xe0000000
+#define UART2_IO_BASE	0xe0010000
+#endif
+#define SC0_BASE	0x40020000	/* smart card #0 */
+#define IIC0_BASE	0x40030000
+#ifdef __BOOTER__
+#define UART0_IO_BASE	0x40040000
+#else
+#define UART0_IO_BASE	0xe0040000
+#endif
+#define SCC0_BASE	0x40040000	/* Serial 0 controller IrdA */
+#define GPT0_BASE	0x40050000	/* General purpose timers */
+#define GPIO0_BASE	0x40060000
+#define SC1_BASE	0x40070000	/* smart card #1 */
+#define SCP0_BASE	0x400C0000	/* Serial Controller Port */
+#define SSP0_BASE	0x400D0000	/* Sync serial port */
+
+#define IDE0_BASE		0xf0100000
+#define REDWOOD_IDE_CTRL	0xf1100000
+
+#define RTCFPC_IRQ	0
+#define XPORT_IRQ	1
+#define AUD_IRQ		2
+#define AID_IRQ		3
+#define DMA0		4
+#define DMA1_IRQ	5
+#define DMA2_IRQ	6
+#define DMA3_IRQ	7
+#define SC0_IRQ		8
+#define IIC0_IRQ	9
+#define IIR0_IRQ	10
+#define GPT0_IRQ	11
+#define GPT1_IRQ	12
+#define SCP0_IRQ	13
+#define SSP0_IRQ	14
+#define GPT2_IRQ	15	/* count down timer */
+#define SC1_IRQ		16
+/* IRQ 17 - 19  external */
+#define UART0_INT	20
+#define UART1_INT	21
+#define UART2_INT	22
+#define XPTDMA_IRQ	23
+#define DCRIDE_IRQ	24
+/* IRQ 25 - 30 external */
+#define IDE0_IRQ	26
+
+#define IIC_NUMS	1
+#define UART_NUMS	3
+#define IIC_OWN		0x55
+#define IIC_CLOCK	50
+
+#define BD_EMAC_ADDR(e,i) bi_enetaddr[i]
+
+#define STD_UART_OP(num)					\
+	{ 0, BASE_BAUD, 0, UART##num##_INT,			\
+		(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),	\
+		iomem_base: (u8 *)UART##num##_IO_BASE,		\
+		io_type: SERIAL_IO_MEM},
+
+#if defined(CONFIG_UART0_TTYS0)
+#define SERIAL_DEBUG_IO_BASE	UART0_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)		\
+	STD_UART_OP(2)
+#endif
+
+#if defined(CONFIG_UART0_TTYS1)
+#define SERIAL_DEBUG_IO_BASE	UART2_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(1)		\
+	STD_UART_OP(0)		\
+	STD_UART_OP(2)
+#endif
+
+#if defined(CONFIG_UART0_TTYS2)
+#define SERIAL_DEBUG_IO_BASE	UART2_IO_BASE
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(2)		\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)
+#endif
+
+#define DCRN_BE_BASE		0x090
+#define DCRN_DMA0_BASE		0x0C0
+#define DCRN_DMA1_BASE		0x0C8
+#define DCRN_DMA2_BASE		0x0D0
+#define DCRN_DMA3_BASE		0x0D8
+#define DCRNCAP_DMA_CC		1	/* have DMA chained count capability */
+#define DCRN_DMASR_BASE		0x0E0
+#define DCRN_PLB0_BASE		0x054
+#define DCRN_PLB1_BASE		0x064
+#define DCRN_POB0_BASE		0x0B0
+#define DCRN_SCCR_BASE		0x120
+#define DCRN_UIC0_BASE		0x040
+#define DCRN_BE_BASE		0x090
+#define DCRN_DMA0_BASE		0x0C0
+#define DCRN_DMA1_BASE		0x0C8
+#define DCRN_DMA2_BASE		0x0D0
+#define DCRN_DMA3_BASE		0x0D8
+#define DCRN_CIC_BASE 		0x030
+#define DCRN_DMASR_BASE		0x0E0
+#define DCRN_EBIMC_BASE		0x070
+#define DCRN_DCRX_BASE		0x020
+#define DCRN_CPMFR_BASE		0x102
+#define DCRN_SCCR_BASE		0x120
+#define DCRN_RTCFP_BASE		0x310
+
+#define UIC0 DCRN_UIC0_BASE
+
+#define IBM_CPM_IIC0	0x80000000	/* IIC 0 interface */
+#define IBM_CPM_CPU	0x10000000	/* PPC405B3 clock control */
+#define IBM_CPM_AUD	0x08000000	/* Audio Decoder */
+#define IBM_CPM_EBIU	0x04000000	/* External Bus Interface Unit */
+#define IBM_CPM_IRR	0x02000000	/* Infrared receiver */
+#define IBM_CPM_DMA	0x01000000	/* DMA controller */
+#define IBM_CPM_UART2	0x00200000	/* Serial Control Port */
+#define IBM_CPM_UART1	0x00100000	/* Serial 1 / Infrared */
+#define IBM_CPM_UART0	0x00080000	/* Serial 0 / 16550 */
+#define IBM_PM_DCRIDE	0x00040000	/* DCR timeout & IDE line Mode clock */
+#define IBM_CPM_SC0	0x00020000	/* Smart Card 0 */
+#define IBM_CPM_VID	0x00010000	/* reserved */
+#define IBM_CPM_SC1	0x00008000	/* Smart Card 0 */
+#define IBM_CPM_XPT0	0x00002000	/* Transport - 54 Mhz */
+#define IBM_CPM_CBS	0x00001000	/* Cross Bar Switch */
+#define IBM_CPM_GPT	0x00000800	/* GPTPWM */
+#define IBM_CPM_GPIO0	0x00000400	/* General Purpose IO 0 */
+#define IBM_CPM_DENC	0x00000200	/* Digital video Encoder */
+#define IBM_CPM_C405T	0x00000100	/* CPU timers */
+#define IBM_CPM_XPT27	0x00000080	/* Transport - 27 Mhz */
+#define IBM_CPM_UIC	0x00000040	/* Universal Interrupt Controller */
+#define IBM_CPM_RTCFPC	0x00000020	/* Realtime clock and front panel */
+#define IBM_CPM_SSP	0x00000010	/* Modem Serial Interface (SSP) */
+#define IBM_CPM_VID2	0x00000002	/* Video Decoder clock domain 2 */
+#define DFLT_IBM4xx_PM	~(IBM_CPM_CPU | IBM_CPM_EBIU | IBM_CPM_DMA	\
+			| IBM_CPM_CBS | IBM_CPM_XPT0 | IBM_CPM_C405T 	\
+			| IBM_CPM_XPT27 | IBM_CPM_UIC)
+
+#define DCRN_BEAR	(DCRN_BE_BASE + 0x0)	/* Bus Error Address Register */
+#define DCRN_BESR	(DCRN_BE_BASE + 0x1)	/* Bus Error Syndrome Register */
+/* DCRN_BESR */
+#define BESR_DSES	0x80000000	/* Data-Side Error Status */
+#define BESR_DMES	0x40000000	/* DMA Error Status */
+#define BESR_RWS	0x20000000	/* Read/Write Status */
+#define BESR_ETMASK	0x1C000000	/* Error Type */
+#define ET_PROT		0
+#define ET_PARITY	1
+#define ET_NCFG		2
+#define ET_BUSERR	4
+#define ET_BUSTO	6
+
+#define CHR1_CETE	0x00800000	/* CPU external timer enable */
+#define CHR1_PCIPW	0x00008000	/* PCI Int enable/Peripheral Write enable */
+
+#define DCRN_CICCR	(DCRN_CIC_BASE + 0x0)	/* CIC Control Register */
+#define DCRN_DMAS1	(DCRN_CIC_BASE + 0x1)	/* DMA Select1 Register */
+#define DCRN_DMAS2	(DCRN_CIC_BASE + 0x2)	/* DMA Select2 Register */
+#define DCRN_CICVCR	(DCRN_CIC_BASE + 0x3)	/* CIC Video COntro Register */
+#define DCRN_CICSEL3	(DCRN_CIC_BASE + 0x5)	/* CIC Select 3 Register */
+#define DCRN_SGPO	(DCRN_CIC_BASE + 0x6)	/* CIC GPIO Output Register */
+#define DCRN_SGPOD	(DCRN_CIC_BASE + 0x7)	/* CIC GPIO OD Register */
+#define DCRN_SGPTC	(DCRN_CIC_BASE + 0x8)	/* CIC GPIO Tristate Ctrl Reg */
+#define DCRN_SGPI	(DCRN_CIC_BASE + 0x9)	/* CIC GPIO Input Reg */
+
+#define DCRN_DCRXICR	(DCRN_DCRX_BASE + 0x0)	/* Internal Control Register */
+#define DCRN_DCRXISR	(DCRN_DCRX_BASE + 0x1)	/* Internal Status Register */
+#define DCRN_DCRXECR	(DCRN_DCRX_BASE + 0x2)	/* External Control Register */
+#define DCRN_DCRXESR	(DCRN_DCRX_BASE + 0x3)	/* External Status Register */
+#define DCRN_DCRXTAR	(DCRN_DCRX_BASE + 0x4)	/* Target Address Register */
+#define DCRN_DCRXTDR	(DCRN_DCRX_BASE + 0x5)	/* Target Data Register */
+#define DCRN_DCRXIGR	(DCRN_DCRX_BASE + 0x6)	/* Interrupt Generation Register */
+#define DCRN_DCRXBCR	(DCRN_DCRX_BASE + 0x7)	/* Line Buffer Control Register */
+
+#define DCRN_BRCRH0	(DCRN_EBIMC_BASE + 0x0)	/* Bus Region Config High 0 */
+#define DCRN_BRCRH1	(DCRN_EBIMC_BASE + 0x1)	/* Bus Region Config High 1 */
+#define DCRN_BRCRH2	(DCRN_EBIMC_BASE + 0x2)	/* Bus Region Config High 2 */
+#define DCRN_BRCRH3	(DCRN_EBIMC_BASE + 0x3)	/* Bus Region Config High 3 */
+#define DCRN_BRCRH4	(DCRN_EBIMC_BASE + 0x4)	/* Bus Region Config High 4 */
+#define DCRN_BRCRH5	(DCRN_EBIMC_BASE + 0x5)	/* Bus Region Config High 5 */
+#define DCRN_BRCRH6	(DCRN_EBIMC_BASE + 0x6)	/* Bus Region Config High 6 */
+#define DCRN_BRCRH7	(DCRN_EBIMC_BASE + 0x7)	/* Bus Region Config High 7 */
+#define DCRN_BRCR0	(DCRN_EBIMC_BASE + 0x10)	/* BRC 0 */
+#define DCRN_BRCR1	(DCRN_EBIMC_BASE + 0x11)	/* BRC 1 */
+#define DCRN_BRCR2	(DCRN_EBIMC_BASE + 0x12)	/* BRC 2 */
+#define DCRN_BRCR3	(DCRN_EBIMC_BASE + 0x13)	/* BRC 3 */
+#define DCRN_BRCR4	(DCRN_EBIMC_BASE + 0x14)	/* BRC 4 */
+#define DCRN_BRCR5	(DCRN_EBIMC_BASE + 0x15)	/* BRC 5 */
+#define DCRN_BRCR6	(DCRN_EBIMC_BASE + 0x16)	/* BRC 6 */
+#define DCRN_BRCR7	(DCRN_EBIMC_BASE + 0x17)	/* BRC 7 */
+#define DCRN_BEAR0	(DCRN_EBIMC_BASE + 0x20)	/* Bus Error Address Register */
+#define DCRN_BESR0	(DCRN_EBIMC_BASE + 0x21)	/* Bus Error Status Register */
+#define DCRN_BIUCR	(DCRN_EBIMC_BASE + 0x2A)	/* Bus Interfac Unit Ctrl Reg */
+
+#define DCRN_RTC_FPC0_CNTL 	(DCRN_RTCFP_BASE + 0x00)	/* RTC cntl */
+#define DCRN_RTC_FPC0_INT 	(DCRN_RTCFP_BASE + 0x01)	/* RTC Interrupt */
+#define DCRN_RTC_FPC0_TIME 	(DCRN_RTCFP_BASE + 0x02)	/* RTC time reg */
+#define DCRN_RTC_FPC0_ALRM 	(DCRN_RTCFP_BASE + 0x03)	/* RTC Alarm reg */
+#define DCRN_RTC_FPC0_D1 	(DCRN_RTCFP_BASE + 0x04)	/* LED Data 1 */
+#define DCRN_RTC_FPC0_D2 	(DCRN_RTCFP_BASE + 0x05)	/* LED Data 2 */
+#define DCRN_RTC_FPC0_D3 	(DCRN_RTCFP_BASE + 0x06)	/* LED Data 3 */
+#define DCRN_RTC_FPC0_D4 	(DCRN_RTCFP_BASE + 0x07)	/* LED Data 4 */
+#define DCRN_RTC_FPC0_D5 	(DCRN_RTCFP_BASE + 0x08)	/* LED Data 5 */
+#define DCRN_RTC_FPC0_FCNTL 	(DCRN_RTCFP_BASE + 0x09)	/* LED control */
+#define DCRN_RTC_FPC0_BRT 	(DCRN_RTCFP_BASE + 0x0A)	/* Brightness cntl */
+
+#include <asm/ibm405.h>
+
+#endif				/* __ASM_IBMSTBX25_H__ */
+#endif				/* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c
new file mode 100644
index 0000000..1df2339
--- /dev/null
+++ b/arch/ppc/platforms/4xx/luan.c
@@ -0,0 +1,387 @@
+/*
+ * arch/ppc/platforms/4xx/luan.c
+ *
+ * Luan board specific routines
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Copyright 2004-2005 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/initrd.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+#include <asm/pci-bridge.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/ppcboot.h>
+
+#include <syslib/ibm44x_common.h>
+#include <syslib/ibm440gx_common.h>
+#include <syslib/ibm440sp_common.h>
+
+/*
+ * This is a horrible kludge, we eventually need to abstract this
+ * generic PHY stuff, so the  standard phy mode defines can be
+ * easily used from arch code.
+ */
+#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
+
+bd_t __res;
+
+static struct ibm44x_clocks clocks __initdata;
+
+static void __init
+luan_calibrate_decr(void)
+{
+	unsigned int freq;
+
+	if (mfspr(SPRN_CCR1) & CCR1_TCS)
+		freq = LUAN_TMR_CLK;
+	else
+		freq = clocks.cpu;
+
+	ibm44x_calibrate_decr(freq);
+}
+
+static int
+luan_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: IBM\n");
+	seq_printf(m, "machine\t\t: PPC440SP EVB (Luan)\n");
+
+	return 0;
+}
+
+static inline int
+luan_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+
+	/* PCIX0 in adapter mode, no host interrupt routing */
+
+	/* PCIX1 */
+	if (hose->index == 0) {
+		static char pci_irq_table[][4] =
+		/*
+		 *	PCI IDSEL/INTPIN->INTLINE
+		 *	  A   B   C   D
+		 */
+		{
+			{ 49, 49, 49, 49 },	/* IDSEL 1 - PCIX1 Slot 0 */
+			{ 49, 49, 49, 49 },	/* IDSEL 2 - PCIX1 Slot 1 */
+			{ 49, 49, 49, 49 },	/* IDSEL 3 - PCIX1 Slot 2 */
+			{ 49, 49, 49, 49 },	/* IDSEL 4 - PCIX1 Slot 3 */
+		};
+		const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	/* PCIX2 */
+	} else if (hose->index == 1) {
+		static char pci_irq_table[][4] =
+		/*
+		 *	PCI IDSEL/INTPIN->INTLINE
+		 *	  A   B   C   D
+		 */
+		{
+			{ 50, 50, 50, 50 },	/* IDSEL 1 - PCIX2 Slot 0 */
+			{ 50, 50, 50, 50 },	/* IDSEL 2 - PCIX2 Slot 1 */
+			{ 50, 50, 50, 50 },	/* IDSEL 3 - PCIX2 Slot 2 */
+			{ 50, 50, 50, 50 },	/* IDSEL 4 - PCIX2 Slot 3 */
+		};
+		const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	}
+	return -1;
+}
+
+static void __init luan_set_emacdata(void)
+{
+	struct ocp_def *def;
+	struct ocp_func_emac_data *emacdata;
+
+	/* Set phy_map, phy_mode, and mac_addr for the EMAC */
+	def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0);
+	emacdata = def->additions;
+	emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
+	emacdata->phy_mode = PHY_MODE_GMII;
+	memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+}
+
+#define PCIX_READW(offset) \
+	(readw((void *)((u32)pcix_reg_base+offset)))
+
+#define PCIX_WRITEW(value, offset) \
+	(writew(value, (void *)((u32)pcix_reg_base+offset)))
+
+#define PCIX_WRITEL(value, offset) \
+	(writel(value, (void *)((u32)pcix_reg_base+offset)))
+
+static void __init
+luan_setup_pcix(void)
+{
+	int i;
+	void *pcix_reg_base;
+
+	for (i=0;i<3;i++) {
+		pcix_reg_base = ioremap64(PCIX0_REG_BASE + i*PCIX_REG_OFFSET, PCIX_REG_SIZE);
+
+		/* Enable PCIX0 I/O, Mem, and Busmaster cycles */
+		PCIX_WRITEW(PCIX_READW(PCIX0_COMMAND) | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER, PCIX0_COMMAND);
+
+		/* Disable all windows */
+		PCIX_WRITEL(0, PCIX0_POM0SA);
+		PCIX_WRITEL(0, PCIX0_POM1SA);
+		PCIX_WRITEL(0, PCIX0_POM2SA);
+		PCIX_WRITEL(0, PCIX0_PIM0SA);
+		PCIX_WRITEL(0, PCIX0_PIM0SAH);
+		PCIX_WRITEL(0, PCIX0_PIM1SA);
+		PCIX_WRITEL(0, PCIX0_PIM2SA);
+		PCIX_WRITEL(0, PCIX0_PIM2SAH);
+
+		/*
+		 * Setup 512MB PLB->PCI outbound mem window
+		 * (a_n000_0000->0_n000_0000)
+		 * */
+		PCIX_WRITEL(0x0000000a, PCIX0_POM0LAH);
+		PCIX_WRITEL(0x80000000 | i*LUAN_PCIX_MEM_SIZE, PCIX0_POM0LAL);
+		PCIX_WRITEL(0x00000000, PCIX0_POM0PCIAH);
+		PCIX_WRITEL(0x80000000 | i*LUAN_PCIX_MEM_SIZE, PCIX0_POM0PCIAL);
+		PCIX_WRITEL(0xe0000001, PCIX0_POM0SA);
+
+		/* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */
+		PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH);
+		PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL);
+		PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA);
+		PCIX_WRITEL(0xffffffff, PCIX0_PIM0SAH);
+
+		iounmap(pcix_reg_base);
+	}
+
+	eieio();
+}
+
+static void __init
+luan_setup_hose(struct pci_controller *hose,
+		int lower_mem,
+		int upper_mem,
+		int cfga,
+		int cfgd,
+		u64 pcix_io_base)
+{
+	char name[20];
+
+	sprintf(name, "PCIX%d host bridge", hose->index);
+
+	hose->pci_mem_offset = LUAN_PCIX_MEM_OFFSET;
+
+	pci_init_resource(&hose->io_resource,
+			LUAN_PCIX_LOWER_IO,
+			LUAN_PCIX_UPPER_IO,
+			IORESOURCE_IO,
+			name);
+
+	pci_init_resource(&hose->mem_resources[0],
+			lower_mem,
+			upper_mem,
+			IORESOURCE_MEM,
+			name);
+
+	hose->io_space.start = LUAN_PCIX_LOWER_IO;
+	hose->io_space.end = LUAN_PCIX_UPPER_IO;
+	hose->mem_space.start = lower_mem;
+	hose->mem_space.end = upper_mem;
+	isa_io_base =
+		(unsigned long)ioremap64(pcix_io_base, PCIX_IO_SIZE);
+	hose->io_base_virt = (void *)isa_io_base;
+
+	setup_indirect_pci(hose, cfga, cfgd);
+	hose->set_cfg_type = 1;
+}
+
+static void __init
+luan_setup_hoses(void)
+{
+	struct pci_controller *hose1, *hose2;
+
+	/* Configure windows on the PCI-X host bridge */
+	luan_setup_pcix();
+
+	/* Allocate hoses for PCIX1 and PCIX2 */
+	hose1 = pcibios_alloc_controller();
+	hose2 = pcibios_alloc_controller();
+	if (!hose1 || !hose2)
+		return;
+
+	/* Setup PCIX1 */
+	hose1->first_busno = 0;
+	hose1->last_busno = 0xff;
+
+	luan_setup_hose(hose1,
+			LUAN_PCIX1_LOWER_MEM,
+			LUAN_PCIX1_UPPER_MEM,
+			PCIX1_CFGA,
+			PCIX1_CFGD,
+			PCIX1_IO_BASE);
+
+	hose1->last_busno = pciauto_bus_scan(hose1, hose1->first_busno);
+
+	/* Setup PCIX2 */
+	hose2->first_busno = hose1->last_busno + 1;
+	hose2->last_busno = 0xff;
+
+	luan_setup_hose(hose2,
+			LUAN_PCIX2_LOWER_MEM,
+			LUAN_PCIX2_UPPER_MEM,
+			PCIX2_CFGA,
+			PCIX2_CFGD,
+			PCIX2_IO_BASE);
+
+	hose2->last_busno = pciauto_bus_scan(hose2, hose2->first_busno);
+
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = luan_map_irq;
+}
+
+TODC_ALLOC();
+
+static void __init
+luan_early_serial_map(void)
+{
+	struct uart_port port;
+
+	/* Setup ioremapped serial port access */
+	memset(&port, 0, sizeof(port));
+	port.membase = ioremap64(PPC440SP_UART0_ADDR, 8);
+	port.irq = UART0_INT;
+	port.uartclk = clocks.uart0;
+	port.regshift = 0;
+	port.iotype = SERIAL_IO_MEM;
+	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	port.line = 0;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 0 failed\n");
+	}
+
+	port.membase = ioremap64(PPC440SP_UART1_ADDR, 8);
+	port.irq = UART1_INT;
+	port.uartclk = clocks.uart1;
+	port.line = 1;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 1 failed\n");
+	}
+
+	port.membase = ioremap64(PPC440SP_UART2_ADDR, 8);
+	port.irq = UART2_INT;
+	port.uartclk = BASE_BAUD;
+	port.line = 2;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 2 failed\n");
+	}
+}
+
+static void __init
+luan_setup_arch(void)
+{
+	luan_set_emacdata();
+
+#if !defined(CONFIG_BDI_SWITCH)
+	/*
+	 * The Abatron BDI JTAG debugger does not tolerate others
+	 * mucking with the debug registers.
+	 */
+        mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM));
+#endif
+
+	/*
+	 * Determine various clocks.
+	 * To be completely correct we should get SysClk
+	 * from FPGA, because it can be changed by on-board switches
+	 * --ebs
+	 */
+	/* 440GX and 440SP clocking is the same -mdp */
+	ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
+	ocp_sys_info.opb_bus_freq = clocks.opb;
+
+	/* init to some ~sane value until calibrate_delay() runs */
+        loops_per_jiffy = 50000000/HZ;
+
+	/* Setup PCIXn host bridges */
+	luan_setup_hoses();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+
+	luan_early_serial_map();
+
+	/* Identify the system */
+	printk("Luan port (MontaVista Software, Inc. <source@mvista.com>)\n");
+}
+
+void __init platform_init(unsigned long r3, unsigned long r4,
+		unsigned long r5, unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3)
+		__res = *(bd_t *)(r3 + KERNELBASE);
+
+	ibm44x_platform_init();
+
+	ppc_md.setup_arch = luan_setup_arch;
+	ppc_md.show_cpuinfo = luan_show_cpuinfo;
+	ppc_md.find_end_of_memory = ibm440sp_find_end_of_memory;
+	ppc_md.get_irq = NULL;		/* Set in ppc4xx_pic_init() */
+
+	ppc_md.calibrate_decr = luan_calibrate_decr;
+#ifdef CONFIG_KGDB
+	ppc_md.early_serial_map = luan_early_serial_map;
+#endif
+}
diff --git a/arch/ppc/platforms/4xx/luan.h b/arch/ppc/platforms/4xx/luan.h
new file mode 100644
index 0000000..09b444c
--- /dev/null
+++ b/arch/ppc/platforms/4xx/luan.h
@@ -0,0 +1,80 @@
+/*
+ * arch/ppc/platforms/4xx/luan.h
+ *
+ * Luan board definitions
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Copyright 2004-2005 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.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_LUAN_H__
+#define __ASM_LUAN_H__
+
+#include <linux/config.h>
+#include <platforms/4xx/ibm440sp.h>
+
+/* F/W TLB mapping used in bootloader glue to reset EMAC */
+#define PPC44x_EMAC0_MR0	0xa0000800
+
+/* Location of MAC addresses in PIBS image */
+#define PIBS_FLASH_BASE		0xffe00000
+#define PIBS_MAC_BASE		(PIBS_FLASH_BASE+0x1b0400)
+
+/* External timer clock frequency */
+#define LUAN_TMR_CLK		25000000
+
+/* Flash */
+#define LUAN_FPGA_REG_0			0x0000000148300000ULL
+#define LUAN_BOOT_LARGE_FLASH(x)	(x & 0x40)
+#define LUAN_SMALL_FLASH_LOW		0x00000001ff900000ULL
+#define LUAN_SMALL_FLASH_HIGH		0x00000001ffe00000ULL
+#define LUAN_SMALL_FLASH_SIZE		0x100000
+#define LUAN_LARGE_FLASH_LOW		0x00000001ff800000ULL
+#define LUAN_LARGE_FLASH_HIGH		0x00000001ffc00000ULL
+#define LUAN_LARGE_FLASH_SIZE		0x400000
+
+/*
+ * Serial port defines
+ */
+#define RS_TABLE_SIZE	3
+
+/* PIBS defined UART mappings, used before early_serial_setup */
+#define UART0_IO_BASE	0xa0000200
+#define UART1_IO_BASE	0xa0000300
+#define UART2_IO_BASE	0xa0000600
+
+#define BASE_BAUD	11059200
+#define STD_UART_OP(num)					\
+	{ 0, BASE_BAUD, 0, UART##num##_INT,			\
+		(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),	\
+		iomem_base: UART##num##_IO_BASE,		\
+		io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)		\
+	STD_UART_OP(2)
+
+/* PCI support */
+#define LUAN_PCIX_LOWER_IO	0x00000000
+#define LUAN_PCIX_UPPER_IO	0x0000ffff
+#define LUAN_PCIX0_LOWER_MEM	0x80000000
+#define LUAN_PCIX0_UPPER_MEM	0x9fffffff
+#define LUAN_PCIX1_LOWER_MEM	0xa0000000
+#define LUAN_PCIX1_UPPER_MEM	0xbfffffff
+#define LUAN_PCIX2_LOWER_MEM	0xc0000000
+#define LUAN_PCIX2_UPPER_MEM	0xdfffffff
+
+#define LUAN_PCIX_MEM_SIZE	0x20000000
+#define LUAN_PCIX_MEM_OFFSET	0x00000000
+
+#endif				/* __ASM_LUAN_H__ */
+#endif				/* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/oak.c b/arch/ppc/platforms/4xx/oak.c
new file mode 100644
index 0000000..fa25ee1
--- /dev/null
+++ b/arch/ppc/platforms/4xx/oak.c
@@ -0,0 +1,255 @@
+/*
+ *
+ *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: oak.c
+ *
+ *    Description:
+ *      Architecture- / platform-specific boot-time initialization code for
+ *      the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
+ *      code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
+ *      <dan@net4x.com>.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/initrd.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+
+#include <asm/board.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/bootinfo.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/time.h>
+
+#include "oak.h"
+
+/* Function Prototypes */
+
+extern void abort(void);
+
+/* Global Variables */
+
+unsigned char __res[sizeof(bd_t)];
+
+
+/*
+ * void __init oak_init()
+ *
+ * Description:
+ *   This routine...
+ *
+ * Input(s):
+ *   r3 - Optional pointer to a board information structure.
+ *   r4 - Optional pointer to the physical starting address of the init RAM
+ *        disk.
+ *   r5 - Optional pointer to the physical ending address of the init RAM
+ *        disk.
+ *   r6 - Optional pointer to the physical starting address of any kernel
+ *        command-line parameters.
+ *   r7 - Optional pointer to the physical ending address of any kernel
+ *        command-line parameters.
+ *
+ * Output(s):
+ *   N/A
+ *
+ * Returns:
+ *   N/A
+ *
+ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3) {
+		memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
+	}
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+	/*
+	 * If the init RAM disk has been configured in, and there's a valid
+	 * starting address for it, set it up.
+	 */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	/* Copy the kernel command line arguments to a safe place. */
+
+	if (r6) {
+ 		*(char *)(r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *)(r6 + KERNELBASE));
+	}
+
+	/* Initialize machine-dependency vectors */
+
+	ppc_md.setup_arch	 	= oak_setup_arch;
+	ppc_md.show_percpuinfo	 	= oak_show_percpuinfo;
+	ppc_md.irq_canonicalize 	= NULL;
+	ppc_md.init_IRQ		 	= ppc4xx_pic_init;
+	ppc_md.get_irq		 	= NULL;  /* Set in ppc4xx_pic_init() */
+	ppc_md.init		 	= NULL;
+
+	ppc_md.restart		 	= oak_restart;
+	ppc_md.power_off	 	= oak_power_off;
+	ppc_md.halt		 	= oak_halt;
+
+	ppc_md.time_init	 	= oak_time_init;
+	ppc_md.set_rtc_time	 	= oak_set_rtc_time;
+	ppc_md.get_rtc_time	 	= oak_get_rtc_time;
+	ppc_md.calibrate_decr	 	= oak_calibrate_decr;
+}
+
+/*
+ * Document me.
+ */
+void __init
+oak_setup_arch(void)
+{
+	/* XXX - Implement me */
+}
+
+/*
+ * int oak_show_percpuinfo()
+ *
+ * Description:
+ *   This routine pretty-prints the platform's internal CPU and bus clock
+ *   frequencies into the buffer for usage in /proc/cpuinfo.
+ *
+ * Input(s):
+ *  *buffer - Buffer into which CPU and bus clock frequencies are to be
+ *            printed.
+ *
+ * Output(s):
+ *  *buffer - Buffer with the CPU and bus clock frequencies.
+ *
+ * Returns:
+ *   The number of bytes copied into 'buffer' if OK, otherwise zero or less
+ *   on error.
+ */
+int
+oak_show_percpuinfo(struct seq_file *m, int i)
+{
+	bd_t *bp = (bd_t *)__res;
+
+	seq_printf(m, "clock\t\t: %dMHz\n"
+		   "bus clock\t\t: %dMHz\n",
+		   bp->bi_intfreq / 1000000,
+		   bp->bi_busfreq / 1000000);
+
+	return 0;
+}
+
+/*
+ * Document me.
+ */
+void
+oak_restart(char *cmd)
+{
+	abort();
+}
+
+/*
+ * Document me.
+ */
+void
+oak_power_off(void)
+{
+	oak_restart(NULL);
+}
+
+/*
+ * Document me.
+ */
+void
+oak_halt(void)
+{
+	oak_restart(NULL);
+}
+
+/*
+ * Document me.
+ */
+long __init
+oak_time_init(void)
+{
+	/* XXX - Implement me */
+	return 0;
+}
+
+/*
+ * Document me.
+ */
+int __init
+oak_set_rtc_time(unsigned long time)
+{
+	/* XXX - Implement me */
+
+	return (0);
+}
+
+/*
+ * Document me.
+ */
+unsigned long __init
+oak_get_rtc_time(void)
+{
+	/* XXX - Implement me */
+
+	return (0);
+}
+
+/*
+ * void __init oak_calibrate_decr()
+ *
+ * Description:
+ *   This routine retrieves the internal processor frequency from the board
+ *   information structure, sets up the kernel timer decrementer based on
+ *   that value, enables the 403 programmable interval timer (PIT) and sets
+ *   it up for auto-reload.
+ *
+ * Input(s):
+ *   N/A
+ *
+ * Output(s):
+ *   N/A
+ *
+ * Returns:
+ *   N/A
+ *
+ */
+void __init
+oak_calibrate_decr(void)
+{
+	unsigned int freq;
+	bd_t *bip = (bd_t *)__res;
+
+	freq = bip->bi_intfreq;
+
+	decrementer_count = freq / HZ;
+	count_period_num = 1;
+	count_period_den = freq;
+
+	/* Enable the PIT and set auto-reload of its value */
+
+	mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
+
+	/* Clear any pending timer interrupts */
+
+	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
+}
diff --git a/arch/ppc/platforms/4xx/oak.h b/arch/ppc/platforms/4xx/oak.h
new file mode 100644
index 0000000..1b86a4c
--- /dev/null
+++ b/arch/ppc/platforms/4xx/oak.h
@@ -0,0 +1,96 @@
+/*
+ *
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: oak.h
+ *
+ *    Description:
+ *	Macros, definitions, and data structures specific to the IBM PowerPC
+ *      403G{A,B,C,CX} "Oak" evaluation board. Anything specific to the pro-
+ *      cessor itself is defined elsewhere.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_OAK_H__
+#define __ASM_OAK_H__
+
+/* We have an IBM 403G{A,B,C,CX} core */
+#include <asm/ibm403.h>
+
+#define _IO_BASE	0
+#define _ISA_MEM_BASE	0
+#define PCI_DRAM_OFFSET	0
+
+/* Memory map for the "Oak" evaluation board */
+
+#define	PPC403SPU_IO_BASE	0x40000000	/* 403 On-chip serial port */
+#define	PPC403SPU_IO_SIZE	0x00000008
+#define	OAKSERIAL_IO_BASE	0x7E000000	/* NS16550DV serial port */
+#define	OAKSERIAL_IO_SIZE	0x00000008
+#define	OAKNET_IO_BASE		0xF4000000	/* NS83902AV Ethernet */
+#define	OAKNET_IO_SIZE		0x00000040
+#define	OAKPROM_IO_BASE		0xFFFE0000	/* AMD 29F010 Flash ROM */
+#define	OAKPROM_IO_SIZE		0x00020000
+
+
+/* Interrupt assignments fixed by the hardware implementation */
+
+/* This is annoying kbuild-2.4 problem. -- Tom */
+
+#define	PPC403SPU_RX_INT	4	/* AIC_INT4 */
+#define	PPC403SPU_TX_INT	5	/* AIC_INT5 */
+#define	OAKNET_INT		27	/* AIC_INT27 */
+#define	OAKSERIAL_INT		28	/* AIC_INT28 */
+
+#ifndef __ASSEMBLY__
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's "Oak" evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
+
+typedef struct board_info {
+	unsigned char	 bi_s_version[4];	/* Version of this structure */
+	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[6];	/* Ethernet MAC address */
+	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_busfreq;		/* Bus speed, in Hz */
+} bd_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void		 oak_init(unsigned long r3,
+				  unsigned long ird_start,
+				  unsigned long ird_end,
+				  unsigned long cline_start,
+				  unsigned long cline_end);
+extern void		 oak_setup_arch(void);
+extern int		 oak_setup_residual(char *buffer);
+extern void		 oak_init_IRQ(void);
+extern int		 oak_get_irq(struct pt_regs *regs);
+extern void		 oak_restart(char *cmd);
+extern void		 oak_power_off(void);
+extern void		 oak_halt(void);
+extern void		 oak_time_init(void);
+extern int		 oak_set_rtc_time(unsigned long now);
+extern unsigned long	 oak_get_rtc_time(void);
+extern void		 oak_calibrate_decr(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+#define PPC4xx_MACHINE_NAME	"IBM Oak"
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_OAK_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/oak_setup.h b/arch/ppc/platforms/4xx/oak_setup.h
new file mode 100644
index 0000000..8648bd0
--- /dev/null
+++ b/arch/ppc/platforms/4xx/oak_setup.h
@@ -0,0 +1,50 @@
+/*
+ *
+ *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: oak_setup.h
+ *
+ *    Description:
+ *      Architecture- / platform-specific boot-time initialization code for
+ *      the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
+ *      code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
+ *      <dan@netx4.com>.
+ *
+ */
+
+#ifndef	__OAK_SETUP_H__
+#define	__OAK_SETUP_H__
+
+#include <asm/ptrace.h>
+#include <asm/board.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern unsigned char	 __res[sizeof(bd_t)];
+
+extern void		 oak_init(unsigned long r3,
+				  unsigned long ird_start,
+				  unsigned long ird_end,
+				  unsigned long cline_start,
+				  unsigned long cline_end);
+extern void		 oak_setup_arch(void);
+extern int		 oak_setup_residual(char *buffer);
+extern void		 oak_init_IRQ(void);
+extern int		 oak_get_irq(struct pt_regs *regs);
+extern void		 oak_restart(char *cmd);
+extern void		 oak_power_off(void);
+extern void		 oak_halt(void);
+extern void		 oak_time_init(void);
+extern int		 oak_set_rtc_time(unsigned long now);
+extern unsigned long	 oak_get_rtc_time(void);
+extern void		 oak_calibrate_decr(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __OAK_SETUP_H__ */
diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
new file mode 100644
index 0000000..28de707
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ocotea.c
@@ -0,0 +1,367 @@
+/*
+ * arch/ppc/platforms/4xx/ocotea.c
+ *
+ * Ocotea board specific routines
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Copyright 2003-2005 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/initrd.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+#include <asm/pci-bridge.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/ppcboot.h>
+
+#include <syslib/gen550.h>
+#include <syslib/ibm440gx_common.h>
+
+/*
+ * This is a horrible kludge, we eventually need to abstract this
+ * generic PHY stuff, so the  standard phy mode defines can be
+ * easily used from arch code.
+ */
+#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
+
+bd_t __res;
+
+static struct ibm44x_clocks clocks __initdata;
+
+static void __init
+ocotea_calibrate_decr(void)
+{
+	unsigned int freq;
+
+	if (mfspr(SPRN_CCR1) & CCR1_TCS)
+		freq = OCOTEA_TMR_CLK;
+	else
+		freq = clocks.cpu;
+
+	ibm44x_calibrate_decr(freq);
+}
+
+static int
+ocotea_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: IBM\n");
+	seq_printf(m, "machine\t\t: PPC440GX EVB (Ocotea)\n");
+	ibm440gx_show_cpuinfo(m);
+	return 0;
+}
+
+static inline int
+ocotea_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	/*
+	 *	PCI IDSEL/INTPIN->INTLINE
+	 * 	   A   B   C   D
+	 */
+	{
+		{ 23, 23, 23, 23 },	/* IDSEL 1 - PCI Slot 0 */
+		{ 24, 24, 24, 24 },	/* IDSEL 2 - PCI Slot 1 */
+		{ 25, 25, 25, 25 },	/* IDSEL 3 - PCI Slot 2 */
+		{ 26, 26, 26, 26 },	/* IDSEL 4 - PCI Slot 3 */
+	};
+
+	const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void __init ocotea_set_emacdata(void)
+{
+	struct ocp_def *def;
+	struct ocp_func_emac_data *emacdata;
+	int i;
+
+	/*
+	 * Note: Current rev. board only operates in Group 4a
+	 * mode, so we always set EMAC0-1 for SMII and EMAC2-3
+	 * for RGMII (though these could run in RTBI just the same).
+	 *
+	 * The FPGA reg 3 information isn't even suitable for
+	 * determining the phy_mode, so if the board becomes
+	 * usable in !4a, it will be necessary to parse an environment
+	 * variable from the firmware or similar to properly configure
+	 * the phy_map/phy_mode.
+	 */
+	/* Set phy_map, phy_mode, and mac_addr for each EMAC */
+	for (i=0; i<4; i++) {
+		def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i);
+		emacdata = def->additions;
+		if (i < 2) {
+			emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
+			emacdata->phy_mode = PHY_MODE_SMII;
+		}
+		else {
+			emacdata->phy_map = 0x0000ffff; /* Skip 0x00-0x0f */
+			emacdata->phy_mode = PHY_MODE_RGMII;
+		}
+		if (i == 0)
+			memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+		else if (i == 1)
+			memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6);
+		else if (i == 2)
+			memcpy(emacdata->mac_addr, __res.bi_enet2addr, 6);
+		else if (i == 3)
+			memcpy(emacdata->mac_addr, __res.bi_enet3addr, 6);
+	}
+}
+
+#define PCIX_READW(offset) \
+	(readw(pcix_reg_base+offset))
+
+#define PCIX_WRITEW(value, offset) \
+	(writew(value, pcix_reg_base+offset))
+
+#define PCIX_WRITEL(value, offset) \
+	(writel(value, pcix_reg_base+offset))
+
+/*
+ * FIXME: This is only here to "make it work".  This will move
+ * to a ibm_pcix.c which will contain a generic IBM PCIX bridge
+ * configuration library. -Matt
+ */
+static void __init
+ocotea_setup_pcix(void)
+{
+	void *pcix_reg_base;
+
+	pcix_reg_base = ioremap64(PCIX0_REG_BASE, PCIX_REG_SIZE);
+
+	/* Enable PCIX0 I/O, Mem, and Busmaster cycles */
+	PCIX_WRITEW(PCIX_READW(PCIX0_COMMAND) | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER, PCIX0_COMMAND);
+
+	/* Disable all windows */
+	PCIX_WRITEL(0, PCIX0_POM0SA);
+	PCIX_WRITEL(0, PCIX0_POM1SA);
+	PCIX_WRITEL(0, PCIX0_POM2SA);
+	PCIX_WRITEL(0, PCIX0_PIM0SA);
+	PCIX_WRITEL(0, PCIX0_PIM0SAH);
+	PCIX_WRITEL(0, PCIX0_PIM1SA);
+	PCIX_WRITEL(0, PCIX0_PIM2SA);
+	PCIX_WRITEL(0, PCIX0_PIM2SAH);
+
+	/* Setup 2GB PLB->PCI outbound mem window (3_8000_0000->0_8000_0000) */
+	PCIX_WRITEL(0x00000003, PCIX0_POM0LAH);
+	PCIX_WRITEL(0x80000000, PCIX0_POM0LAL);
+	PCIX_WRITEL(0x00000000, PCIX0_POM0PCIAH);
+	PCIX_WRITEL(0x80000000, PCIX0_POM0PCIAL);
+	PCIX_WRITEL(0x80000001, PCIX0_POM0SA);
+
+	/* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */
+	PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH);
+	PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL);
+	PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA);
+
+	eieio();
+}
+
+static void __init
+ocotea_setup_hose(void)
+{
+	struct pci_controller *hose;
+
+	/* Configure windows on the PCI-X host bridge */
+	ocotea_setup_pcix();
+
+	hose = pcibios_alloc_controller();
+
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	hose->pci_mem_offset = OCOTEA_PCI_MEM_OFFSET;
+
+	pci_init_resource(&hose->io_resource,
+			OCOTEA_PCI_LOWER_IO,
+			OCOTEA_PCI_UPPER_IO,
+			IORESOURCE_IO,
+			"PCI host bridge");
+
+	pci_init_resource(&hose->mem_resources[0],
+			OCOTEA_PCI_LOWER_MEM,
+			OCOTEA_PCI_UPPER_MEM,
+			IORESOURCE_MEM,
+			"PCI host bridge");
+
+	hose->io_space.start = OCOTEA_PCI_LOWER_IO;
+	hose->io_space.end = OCOTEA_PCI_UPPER_IO;
+	hose->mem_space.start = OCOTEA_PCI_LOWER_MEM;
+	hose->mem_space.end = OCOTEA_PCI_UPPER_MEM;
+	isa_io_base =
+		(unsigned long)ioremap64(OCOTEA_PCI_IO_BASE, OCOTEA_PCI_IO_SIZE);
+	hose->io_base_virt = (void *)isa_io_base;
+
+	setup_indirect_pci(hose,
+			OCOTEA_PCI_CFGA_PLB32,
+			OCOTEA_PCI_CFGD_PLB32);
+	hose->set_cfg_type = 1;
+
+	hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = ocotea_map_irq;
+}
+
+
+TODC_ALLOC();
+
+static void __init
+ocotea_early_serial_map(void)
+{
+	struct uart_port port;
+
+	/* Setup ioremapped serial port access */
+	memset(&port, 0, sizeof(port));
+	port.membase = ioremap64(PPC440GX_UART0_ADDR, 8);
+	port.irq = UART0_INT;
+	port.uartclk = clocks.uart0;
+	port.regshift = 0;
+	port.iotype = SERIAL_IO_MEM;
+	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	port.line = 0;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 0 failed\n");
+	}
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+	/* Configure debug serial access */
+	gen550_init(0, &port);
+#endif
+
+	port.membase = ioremap64(PPC440GX_UART1_ADDR, 8);
+	port.irq = UART1_INT;
+	port.uartclk = clocks.uart1;
+	port.line = 1;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 1 failed\n");
+	}
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+	/* Configure debug serial access */
+	gen550_init(1, &port);
+#endif
+}
+
+static void __init
+ocotea_setup_arch(void)
+{
+	ocotea_set_emacdata();
+
+	ibm440gx_tah_enable();
+
+	/* Setup TODC access */
+	TODC_INIT(TODC_TYPE_DS1743,
+			0,
+			0,
+			ioremap64(OCOTEA_RTC_ADDR, OCOTEA_RTC_SIZE),
+			8);
+
+	/* init to some ~sane value until calibrate_delay() runs */
+        loops_per_jiffy = 50000000/HZ;
+
+	/* Setup PCI host bridge */
+	ocotea_setup_hose();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+
+	ocotea_early_serial_map();
+
+	/* Identify the system */
+	printk("IBM Ocotea port (MontaVista Software, Inc. <source@mvista.com>)\n");
+}
+
+static void __init ocotea_init(void)
+{
+	ibm440gx_l2c_setup(&clocks);
+}
+
+void __init platform_init(unsigned long r3, unsigned long r4,
+		unsigned long r5, unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3)
+		__res = *(bd_t *)(r3 + KERNELBASE);
+
+	/*
+	 * Determine various clocks.
+	 * To be completely correct we should get SysClk
+	 * from FPGA, because it can be changed by on-board switches
+	 * --ebs
+	 */
+	ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
+	ocp_sys_info.opb_bus_freq = clocks.opb;
+
+	ibm44x_platform_init();
+
+	ppc_md.setup_arch = ocotea_setup_arch;
+	ppc_md.show_cpuinfo = ocotea_show_cpuinfo;
+	ppc_md.get_irq = NULL;		/* Set in ppc4xx_pic_init() */
+
+	ppc_md.calibrate_decr = ocotea_calibrate_decr;
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+#ifdef CONFIG_KGDB
+	ppc_md.early_serial_map = ocotea_early_serial_map;
+#endif
+	ppc_md.init = ocotea_init;
+}
diff --git a/arch/ppc/platforms/4xx/ocotea.h b/arch/ppc/platforms/4xx/ocotea.h
new file mode 100644
index 0000000..202dc82
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ocotea.h
@@ -0,0 +1,88 @@
+/*
+ * arch/ppc/platforms/ocotea.h
+ *
+ * Ocotea board definitions
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Copyright 2003-2005 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.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_OCOTEA_H__
+#define __ASM_OCOTEA_H__
+
+#include <linux/config.h>
+#include <platforms/4xx/ibm440gx.h>
+
+/* F/W TLB mapping used in bootloader glue to reset EMAC */
+#define PPC44x_EMAC0_MR0	0xe0000800
+
+/* Location of MAC addresses in PIBS image */
+#define PIBS_FLASH_BASE		0xfff00000
+#define PIBS_MAC_BASE		(PIBS_FLASH_BASE+0xb0500)
+#define PIBS_MAC_SIZE		0x200
+#define PIBS_MAC_OFFSET		0x100
+
+/* External timer clock frequency */
+#define OCOTEA_TMR_CLK	25000000
+
+/* RTC/NVRAM location */
+#define OCOTEA_RTC_ADDR		0x0000000148000000ULL
+#define OCOTEA_RTC_SIZE		0x2000
+
+/* Flash */
+#define OCOTEA_FPGA_REG_0		0x0000000148300000ULL
+#define OCOTEA_BOOT_LARGE_FLASH(x)	(x & 0x40)
+#define OCOTEA_SMALL_FLASH_LOW		0x00000001ff900000ULL
+#define OCOTEA_SMALL_FLASH_HIGH		0x00000001fff00000ULL
+#define OCOTEA_SMALL_FLASH_SIZE		0x100000
+#define OCOTEA_LARGE_FLASH_LOW		0x00000001ff800000ULL
+#define OCOTEA_LARGE_FLASH_HIGH		0x00000001ffc00000ULL
+#define OCOTEA_LARGE_FLASH_SIZE		0x400000
+
+/* FPGA_REG_3 (Ethernet Groups) */
+#define OCOTEA_FPGA_REG_3		0x0000000148300003ULL
+
+/*
+ * Serial port defines
+ */
+#define RS_TABLE_SIZE	2
+
+/* OpenBIOS defined UART mappings, used before early_serial_setup */
+#define UART0_IO_BASE	0xE0000200
+#define UART1_IO_BASE	0xE0000300
+
+#define BASE_BAUD	11059200/16
+#define STD_UART_OP(num)					\
+	{ 0, BASE_BAUD, 0, UART##num##_INT,			\
+		(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),	\
+		iomem_base: UART##num##_IO_BASE,		\
+		io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)
+
+/* PCI support */
+#define OCOTEA_PCI_LOWER_IO	0x00000000
+#define OCOTEA_PCI_UPPER_IO	0x0000ffff
+#define OCOTEA_PCI_LOWER_MEM	0x80000000
+#define OCOTEA_PCI_UPPER_MEM	0xffffefff
+
+#define OCOTEA_PCI_CFGREGS_BASE	0x000000020ec00000ULL
+#define OCOTEA_PCI_CFGA_PLB32	0x0ec00000
+#define OCOTEA_PCI_CFGD_PLB32	0x0ec00004
+
+#define OCOTEA_PCI_IO_BASE	0x0000000208000000ULL
+#define OCOTEA_PCI_IO_SIZE	0x00010000
+#define OCOTEA_PCI_MEM_OFFSET	0x00000000
+
+#endif				/* __ASM_OCOTEA_H__ */
+#endif				/* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/redwood5.c b/arch/ppc/platforms/4xx/redwood5.c
new file mode 100644
index 0000000..2f5e410
--- /dev/null
+++ b/arch/ppc/platforms/4xx/redwood5.c
@@ -0,0 +1,110 @@
+/*
+ * arch/ppc/platforms/4xx/redwood5.c
+ *
+ * Support for the IBM redwood5 eval board file
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2000-2001 (c) MontaVista, Software, Inc.  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/init.h>
+#include <linux/pagemap.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.start	= SMC91111_BASE_ADDR,
+		.end	= SMC91111_BASE_ADDR + SMC91111_REG_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= SMC91111_IRQ,
+		.end	= SMC91111_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(smc91x_resources),
+	.resource	= smc91x_resources,
+};
+
+static struct platform_device *redwood5_devs[] __initdata = {
+	&smc91x_device,
+};
+
+static int __init
+redwood5_platform_add_devices(void)
+{
+	return platform_add_devices(redwood5_devs, ARRAY_SIZE(redwood5_devs));
+}
+
+void __init
+redwood5_setup_arch(void)
+{
+	ppc4xx_setup_arch();
+
+#ifdef CONFIG_DEBUG_BRINGUP
+	printk("\n");
+	printk("machine\t: %s\n", PPC4xx_MACHINE_NAME);
+	printk("\n");
+	printk("bi_s_version\t %s\n",      bip->bi_s_version);
+	printk("bi_r_version\t %s\n",      bip->bi_r_version);
+	printk("bi_memsize\t 0x%8.8x\t %dMBytes\n", bip->bi_memsize,bip->bi_memsize/(1024*1000));
+	printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 0,
+	bip->bi_enetaddr[0], bip->bi_enetaddr[1],
+	bip->bi_enetaddr[2], bip->bi_enetaddr[3],
+	bip->bi_enetaddr[4], bip->bi_enetaddr[5]);
+
+	printk("bi_intfreq\t 0x%8.8x\t clock:\t %dMhz\n",
+	       bip->bi_intfreq, bip->bi_intfreq/ 1000000);
+
+	printk("bi_busfreq\t 0x%8.8x\t plb bus clock:\t %dMHz\n",
+		bip->bi_busfreq, bip->bi_busfreq / 1000000 );
+	printk("bi_tbfreq\t 0x%8.8x\t TB freq:\t %dMHz\n",
+	       bip->bi_tbfreq, bip->bi_tbfreq/1000000);
+
+	printk("\n");
+#endif
+	device_initcall(redwood5_platform_add_devices);
+}
+
+void __init
+redwood5_map_io(void)
+{
+	int i;
+
+	ppc4xx_map_io();
+	for (i = 0; i < 16; i++) {
+	 unsigned long v, p;
+
+	/* 0x400x0000 -> 0xe00x0000 */
+	p = 0x40000000 | (i << 16);
+	v = STB04xxx_IO_BASE | (i << 16);
+
+	io_block_mapping(v, p, PAGE_SIZE,
+		 _PAGE_NO_CACHE | pgprot_val(PAGE_KERNEL) | _PAGE_GUARDED);
+	}
+
+
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	ppc4xx_init(r3, r4, r5, r6, r7);
+
+	ppc_md.setup_arch = redwood5_setup_arch;
+	ppc_md.setup_io_mappings = redwood5_map_io;
+}
diff --git a/arch/ppc/platforms/4xx/redwood5.h b/arch/ppc/platforms/4xx/redwood5.h
new file mode 100644
index 0000000..264e34f
--- /dev/null
+++ b/arch/ppc/platforms/4xx/redwood5.h
@@ -0,0 +1,54 @@
+/*
+ * arch/ppc/platforms/4xx/redwood5.h
+ *
+ * Macros, definitions, and data structures specific to the IBM PowerPC
+ * STB03xxx "Redwood" evaluation board.
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_REDWOOD5_H__
+#define __ASM_REDWOOD5_H__
+
+/* Redwood5 has an STB04xxx core */
+#include <platforms/4xx/ibmstb4.h>
+
+#ifndef __ASSEMBLY__
+typedef struct board_info {
+	unsigned char	bi_s_version[4];	/* Version of this structure */
+	unsigned char	bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	bi_memsize;		/* DRAM installed, in bytes */
+	unsigned int	bi_dummy;		/* field shouldn't exist */
+	unsigned char	bi_enetaddr[6];		/* Ethernet MAC address */
+	unsigned int	bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	bi_busfreq;		/* Bus speed, in Hz */
+	unsigned int	bi_tbfreq;		/* Software timebase freq */
+} bd_t;
+#endif /* !__ASSEMBLY__ */
+
+
+#define SMC91111_BASE_ADDR	0xf2000300
+#define SMC91111_REG_SIZE	16
+#define SMC91111_IRQ		28
+
+#ifdef MAX_HWIFS
+#undef MAX_HWIFS
+#endif
+#define MAX_HWIFS		1
+
+#define _IO_BASE	0
+#define _ISA_MEM_BASE	0
+#define PCI_DRAM_OFFSET	0
+
+#define BASE_BAUD		(378000000 / 18 / 16)
+
+#define PPC4xx_MACHINE_NAME	"IBM Redwood5"
+
+#endif /* __ASM_REDWOOD5_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/redwood6.c b/arch/ppc/platforms/4xx/redwood6.c
new file mode 100644
index 0000000..8b10129
--- /dev/null
+++ b/arch/ppc/platforms/4xx/redwood6.c
@@ -0,0 +1,159 @@
+/*
+ * arch/ppc/platforms/4xx/redwood6.c
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2002 (c) MontaVista, Software, Inc.  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/init.h>
+#include <linux/pagemap.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/ppc4xx_pic.h>
+#include <linux/delay.h>
+#include <asm/machdep.h>
+
+/*
+ * Define external IRQ senses and polarities.
+ */
+unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 7 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 8 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 9 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 4 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 5 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 6 */
+};
+
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.start	= SMC91111_BASE_ADDR,
+		.end	= SMC91111_BASE_ADDR + SMC91111_REG_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= SMC91111_IRQ,
+		.end	= SMC91111_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(smc91x_resources),
+	.resource	= smc91x_resources,
+};
+
+static struct platform_device *redwood6_devs[] __initdata = {
+	&smc91x_device,
+};
+
+static int __init
+redwood6_platform_add_devices(void)
+{
+	return platform_add_devices(redwood6_devs, ARRAY_SIZE(redwood6_devs));
+}
+
+
+void __init
+redwood6_setup_arch(void)
+{
+#ifdef CONFIG_IDE
+	void *xilinx, *xilinx_1, *xilinx_2;
+	unsigned short us_reg5;
+#endif
+
+	ppc4xx_setup_arch();
+
+#ifdef CONFIG_IDE
+	xilinx = (unsigned long) ioremap(IDE_XLINUX_MUX_BASE, 0x10);
+	/* init xilinx control registers - enable ide mux, clear reset bit */
+	if (!xilinx) {
+		printk(KERN_CRIT
+		       "redwood6_setup_arch() xilinxi ioremap failed\n");
+		return;
+	}
+	xilinx_1 = xilinx + 0xa;
+	xilinx_2 = xilinx + 0xe;
+
+	us_reg5 = readb(xilinx_1);
+	writeb(0x01d1, xilinx_1);
+	writeb(0x0008, xilinx_2);
+
+	udelay(10 * 1000);
+
+	writeb(0x01d1, xilinx_1);
+	writeb(0x0008, xilinx_2);
+#endif
+
+#ifdef DEBUG_BRINGUP
+	bd_t *bip = (bd_t *) __res;
+	printk("\n");
+	printk("machine\t: %s\n", PPC4xx_MACHINE_NAME);
+	printk("\n");
+	printk("bi_s_version\t %s\n", bip->bi_s_version);
+	printk("bi_r_version\t %s\n", bip->bi_r_version);
+	printk("bi_memsize\t 0x%8.8x\t %dMBytes\n", bip->bi_memsize,
+	       bip->bi_memsize / (1024 * 1000));
+	printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 0,
+	       bip->bi_enetaddr[0], bip->bi_enetaddr[1], bip->bi_enetaddr[2],
+	       bip->bi_enetaddr[3], bip->bi_enetaddr[4], bip->bi_enetaddr[5]);
+
+	printk("bi_intfreq\t 0x%8.8x\t clock:\t %dMhz\n",
+	       bip->bi_intfreq, bip->bi_intfreq / 1000000);
+
+	printk("bi_busfreq\t 0x%8.8x\t plb bus clock:\t %dMHz\n",
+	       bip->bi_busfreq, bip->bi_busfreq / 1000000);
+	printk("bi_tbfreq\t 0x%8.8x\t TB freq:\t %dMHz\n",
+	       bip->bi_tbfreq, bip->bi_tbfreq / 1000000);
+
+	printk("\n");
+#endif
+
+	/* Identify the system */
+	printk(KERN_INFO "IBM Redwood6 (STBx25XX) Platform\n");
+	printk(KERN_INFO
+	       "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+
+	device_initcall(redwood6_platform_add_devices);
+}
+
+void __init
+redwood6_map_io(void)
+{
+	int i;
+
+	ppc4xx_map_io();
+	for (i = 0; i < 16; i++) {
+		unsigned long v, p;
+
+		/* 0x400x0000 -> 0xe00x0000 */
+		p = 0x40000000 | (i << 16);
+		v = STBx25xx_IO_BASE | (i << 16);
+
+		io_block_mapping(v, p, PAGE_SIZE,
+				 _PAGE_NO_CACHE | pgprot_val(PAGE_KERNEL) |
+				 _PAGE_GUARDED);
+	}
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	ppc4xx_init(r3, r4, r5, r6, r7);
+
+	ppc_md.setup_arch = redwood6_setup_arch;
+	ppc_md.setup_io_mappings = redwood6_map_io;
+}
diff --git a/arch/ppc/platforms/4xx/redwood6.h b/arch/ppc/platforms/4xx/redwood6.h
new file mode 100644
index 0000000..1814b9f
--- /dev/null
+++ b/arch/ppc/platforms/4xx/redwood6.h
@@ -0,0 +1,55 @@
+/*
+ * arch/ppc/platforms/4xx/redwood6.h
+ *
+ * Macros, definitions, and data structures specific to the IBM PowerPC
+ * STBx25xx "Redwood6" evaluation board.
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2002 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_REDWOOD5_H__
+#define __ASM_REDWOOD5_H__
+
+/* Redwood6 has an STBx25xx core */
+#include <platforms/4xx/ibmstbx25.h>
+
+#ifndef __ASSEMBLY__
+typedef struct board_info {
+	unsigned char bi_s_version[4];	/* Version of this structure */
+	unsigned char bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int bi_memsize;	/* DRAM installed, in bytes */
+	unsigned int bi_dummy;	/* field shouldn't exist */
+	unsigned char bi_enetaddr[6];	/* Ethernet MAC address */
+	unsigned int bi_intfreq;	/* Processor speed, in Hz */
+	unsigned int bi_busfreq;	/* Bus speed, in Hz */
+	unsigned int bi_tbfreq;	/* Software timebase freq */
+} bd_t;
+#endif				/* !__ASSEMBLY__ */
+
+#define SMC91111_BASE_ADDR	0xf2030300
+#define SMC91111_REG_SIZE	16
+#define SMC91111_IRQ		27
+#define IDE_XLINUX_MUX_BASE        0xf2040000
+#define IDE_DMA_ADDR	0xfce00000
+
+#ifdef MAX_HWIFS
+#undef MAX_HWIFS
+#endif
+#define MAX_HWIFS		1
+
+#define _IO_BASE	0
+#define _ISA_MEM_BASE	0
+#define PCI_DRAM_OFFSET	0
+
+#define BASE_BAUD		(378000000 / 18 / 16)
+
+#define PPC4xx_MACHINE_NAME	"IBM Redwood6"
+
+#endif				/* __ASM_REDWOOD5_H__ */
+#endif				/* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/sycamore.c b/arch/ppc/platforms/4xx/sycamore.c
new file mode 100644
index 0000000..d8019ee
--- /dev/null
+++ b/arch/ppc/platforms/4xx/sycamore.c
@@ -0,0 +1,278 @@
+/*
+ * arch/ppc/platforms/4xx/sycamore.c
+ *
+ * Architecture- / platform-specific boot-time initialization code for
+ * IBM PowerPC 4xx based boards.
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2000-2002 (c) MontaVista, Software, Inc.  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/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/rtc.h>
+
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/system.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/ibm_ocp_pci.h>
+#include <asm/todc.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+void *kb_cs;
+void *kb_data;
+void *sycamore_rtc_base;
+
+/*
+ * Define external IRQ senses and polarities.
+ */
+unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 7 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 8 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 9 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 10 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 11 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 12 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 4 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 5 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext Int 6 */
+};
+
+
+/* Some IRQs unique to Sycamore.
+ * Used by the generic 405 PCI setup functions in ppc4xx_pci.c
+ */
+int __init
+ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	    /*
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *      A       B       C       D
+	     */
+	{
+		{28, 28, 28, 28},	/* IDSEL 1 - PCI slot 1 */
+		{29, 29, 29, 29},	/* IDSEL 2 - PCI slot 2 */
+		{30, 30, 30, 30},	/* IDSEL 3 - PCI slot 3 */
+		{31, 31, 31, 31},	/* IDSEL 4 - PCI slot 4 */
+	};
+
+	const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+};
+
+void __init
+sycamore_setup_arch(void)
+{
+#define SYCAMORE_PS2_BASE	0xF0100000
+#define SYCAMORE_FPGA_BASE	0xF0300000
+
+	void *fpga_brdc;
+	unsigned char fpga_brdc_data;
+	void *fpga_enable;
+	void *fpga_polarity;
+	void *fpga_status;
+	void *fpga_trigger;
+
+	ppc4xx_setup_arch();
+
+	ibm_ocp_set_emac(0, 1);
+
+	kb_data = ioremap(SYCAMORE_PS2_BASE, 8);
+	if (!kb_data) {
+		printk(KERN_CRIT
+		       "sycamore_setup_arch() kb_data ioremap failed\n");
+		return;
+	}
+
+	kb_cs = kb_data + 1;
+
+	fpga_status = ioremap(SYCAMORE_FPGA_BASE, 8);
+	if (!fpga_status) {
+		printk(KERN_CRIT
+		       "sycamore_setup_arch() fpga_status ioremap failed\n");
+		return;
+	}
+
+	fpga_enable = fpga_status + 1;
+	fpga_polarity = fpga_status + 2;
+	fpga_trigger = fpga_status + 3;
+	fpga_brdc = fpga_status + 4;
+
+	/* split the keyboard and mouse interrupts */
+	fpga_brdc_data = readb(fpga_brdc);
+	fpga_brdc_data |= 0x80;
+	writeb(fpga_brdc_data, fpga_brdc);
+
+	writeb(0x3, fpga_enable);
+
+	writeb(0x3, fpga_polarity);
+
+	writeb(0x3, fpga_trigger);
+
+	/* RTC step for the sycamore */
+	sycamore_rtc_base = (void *) SYCAMORE_RTC_VADDR;
+	TODC_INIT(TODC_TYPE_DS1743, sycamore_rtc_base, sycamore_rtc_base,
+		  sycamore_rtc_base, 8);
+
+	/* Identify the system */
+	printk(KERN_INFO "IBM Sycamore (IBM405GPr) Platform\n");
+	printk(KERN_INFO
+	       "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+}
+
+void __init
+bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
+{
+#ifdef CONFIG_PCI
+	unsigned int bar_response, bar;
+	/*
+	 * Expected PCI mapping:
+	 *
+	 *  PLB addr             PCI memory addr
+	 *  ---------------------       ---------------------
+	 *  0000'0000 - 7fff'ffff <---  0000'0000 - 7fff'ffff
+	 *  8000'0000 - Bfff'ffff --->  8000'0000 - Bfff'ffff
+	 *
+	 *  PLB addr             PCI io addr
+	 *  ---------------------       ---------------------
+	 *  e800'0000 - e800'ffff --->  0000'0000 - 0001'0000
+	 *
+	 * The following code is simplified by assuming that the bootrom
+	 * has been well behaved in following this mapping.
+	 */
+
+#ifdef DEBUG
+	int i;
+
+	printk("ioremap PCLIO_BASE = 0x%x\n", pcip);
+	printk("PCI bridge regs before fixup \n");
+	for (i = 0; i <= 3; i++) {
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
+	}
+	printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+	printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+	printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+	printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+#endif
+
+	/* added for IBM boot rom version 1.15 bios bar changes  -AK */
+
+	/* Disable region first */
+	out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
+	/* PLB starting addr, PCI: 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
+	/* PCI start addr, 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
+	/* 512MB range of PLB to PCI */
+	out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
+	/* Enable no pre-fetch, enable region */
+	out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
+						(PPC405_PCI_UPPER_MEM -
+						 PPC405_PCI_MEM_BASE)) | 0x01));
+
+	/* Enable inbound region one - 1GB size */
+	out_le32((void *) &(pcip->ptm1ms), 0xc0000001);
+
+	/* Disable outbound region one */
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+
+	/* Disable inbound region two */
+	out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+
+	/* Disable outbound region two */
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+
+	/* Zero config bars */
+	for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+		early_write_config_dword(hose, hose->first_busno,
+					 PCI_FUNC(hose->first_busno), bar,
+					 0x00000000);
+		early_read_config_dword(hose, hose->first_busno,
+					PCI_FUNC(hose->first_busno), bar,
+					&bar_response);
+		DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
+		    hose->first_busno, PCI_SLOT(hose->first_busno),
+		    PCI_FUNC(hose->first_busno), bar, bar_response);
+	}
+	/* end work arround */
+
+#ifdef DEBUG
+	printk("PCI bridge regs after fixup \n");
+	for (i = 0; i <= 3; i++) {
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
+	}
+	printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+	printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+	printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+	printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+#endif
+#endif
+
+}
+
+void __init
+sycamore_map_io(void)
+{
+	ppc4xx_map_io();
+	io_block_mapping(SYCAMORE_RTC_VADDR,
+			 SYCAMORE_RTC_PADDR, SYCAMORE_RTC_SIZE, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	ppc4xx_init(r3, r4, r5, r6, r7);
+
+	ppc_md.setup_arch = sycamore_setup_arch;
+	ppc_md.setup_io_mappings = sycamore_map_io;
+
+#ifdef CONFIG_GEN_RTC
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+#endif
+}
diff --git a/arch/ppc/platforms/4xx/sycamore.h b/arch/ppc/platforms/4xx/sycamore.h
new file mode 100644
index 0000000..3e7b4e2
--- /dev/null
+++ b/arch/ppc/platforms/4xx/sycamore.h
@@ -0,0 +1,67 @@
+/*
+ * arch/ppc/platforms/4xx/sycamore.h
+ *
+ * Macros, definitions, and data structures specific to the IBM PowerPC
+ * 405GPr "Sycamore" evaluation board.
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2000 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_SYCAMORE_H__
+#define __ASM_SYCAMORE_H__
+
+#include <platforms/4xx/ibm405gpr.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's "Sycamore" evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
+
+typedef struct board_info {
+	unsigned char	 bi_s_version[4];	/* Version of this structure */
+	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address */
+	unsigned char	 bi_pci_enetaddr[6];	/* PCI Ethernet MAC address */
+	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
+	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
+} bd_t;
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+
+/* Memory map for the IBM "Sycamore" 405GP evaluation board.
+ * Generic 4xx plus RTC.
+ */
+
+extern void *sycamore_rtc_base;
+#define SYCAMORE_RTC_PADDR	((uint)0xf0000000)
+#define SYCAMORE_RTC_VADDR	SYCAMORE_RTC_PADDR
+#define SYCAMORE_RTC_SIZE		((uint)8*1024)
+
+#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
+#define BASE_BAUD		201600
+#else
+#define BASE_BAUD		691200
+#endif
+
+#define SYCAMORE_PS2_BASE		0xF0100000
+#define SYCAMORE_FPGA_BASE	0xF0300000
+
+#define PPC4xx_MACHINE_NAME	"IBM Sycamore"
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_SYCAMORE_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/virtex-ii_pro.c b/arch/ppc/platforms/4xx/virtex-ii_pro.c
new file mode 100644
index 0000000..097cc9d5
--- /dev/null
+++ b/arch/ppc/platforms/4xx/virtex-ii_pro.c
@@ -0,0 +1,60 @@
+/*
+ * arch/ppc/platforms/4xx/virtex-ii_pro.c
+ *
+ * Author: MontaVista Software, Inc.
+ *         source@mvista.com
+ *
+ * 2002-2004 (c) MontaVista Software, Inc.  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/init.h>
+#include <asm/ocp.h>
+#include "virtex-ii_pro.h"
+
+/* Have OCP take care of the serial ports. */
+struct ocp_def core_ocp[] = {
+#ifdef XPAR_UARTNS550_0_BASEADDR
+	{ .vendor	= OCP_VENDOR_XILINX,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 0,
+	  .paddr	= XPAR_UARTNS550_0_BASEADDR,
+	  .irq		= XPAR_INTC_0_UARTNS550_0_VEC_ID,
+	  .pm		= OCP_CPM_NA
+	},
+#ifdef XPAR_UARTNS550_1_BASEADDR
+	{ .vendor	= OCP_VENDOR_XILINX,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 1,
+	  .paddr	= XPAR_UARTNS550_1_BASEADDR,
+	  .irq		= XPAR_INTC_0_UARTNS550_1_VEC_ID,
+	  .pm		= OCP_CPM_NA
+	},
+#ifdef XPAR_UARTNS550_2_BASEADDR
+	{ .vendor	= OCP_VENDOR_XILINX,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 2,
+	  .paddr	= XPAR_UARTNS550_2_BASEADDR,
+	  .irq		= XPAR_INTC_0_UARTNS550_2_VEC_ID,
+	  .pm		= OCP_CPM_NA
+	},
+#ifdef XPAR_UARTNS550_3_BASEADDR
+	{ .vendor	= OCP_VENDOR_XILINX,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 3,
+	  .paddr	= XPAR_UARTNS550_3_BASEADDR,
+	  .irq		= XPAR_INTC_0_UARTNS550_3_VEC_ID,
+	  .pm		= OCP_CPM_NA
+	},
+#ifdef XPAR_UARTNS550_4_BASEADDR
+#error Edit this file to add more devices.
+#endif			/* 4 */
+#endif			/* 3 */
+#endif			/* 2 */
+#endif			/* 1 */
+#endif			/* 0 */
+	{ .vendor	= OCP_VENDOR_INVALID
+	}
+};
diff --git a/arch/ppc/platforms/4xx/virtex-ii_pro.h b/arch/ppc/platforms/4xx/virtex-ii_pro.h
new file mode 100644
index 0000000..9014c48
--- /dev/null
+++ b/arch/ppc/platforms/4xx/virtex-ii_pro.h
@@ -0,0 +1,99 @@
+/*
+ * arch/ppc/platforms/4xx/virtex-ii_pro.h
+ *
+ * Include file that defines the Xilinx Virtex-II Pro processor
+ *
+ * Author: MontaVista Software, Inc.
+ *         source@mvista.com
+ *
+ * 2002-2004 (c) MontaVista Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_VIRTEXIIPRO_H__
+#define __ASM_VIRTEXIIPRO_H__
+
+#include <linux/config.h>
+#include <asm/xparameters.h>
+
+/* serial defines */
+
+#define RS_TABLE_SIZE  4	/* change this and add more devices below
+				   if you have more then 4 16x50 UARTs */
+
+#define BASE_BAUD		(XPAR_UARTNS550_0_CLOCK_FREQ_HZ/16)
+
+/* The serial ports in the Virtex-II Pro have each I/O byte in the
+ * LSByte of a word.  This means that iomem_reg_shift needs to be 2 to
+ * change the byte offsets into word offsets.  In addition the base
+ * addresses need to have 3 added to them to get to the LSByte.
+ */
+#define STD_UART_OP(num)						 \
+	{ 0, BASE_BAUD, 0, XPAR_INTC_0_UARTNS550_##num##_VEC_ID,	 \
+		ASYNC_BOOT_AUTOCONF,		 			 \
+		.iomem_base = (u8 *)XPAR_UARTNS550_##num##_BASEADDR + 3, \
+		.iomem_reg_shift = 2,					 \
+		.io_type = SERIAL_IO_MEM},
+
+#if defined(XPAR_INTC_0_UARTNS550_0_VEC_ID)
+#define ML300_UART0 STD_UART_OP(0)
+#else
+#define ML300_UART0
+#endif
+
+#if defined(XPAR_INTC_0_UARTNS550_1_VEC_ID)
+#define ML300_UART1 STD_UART_OP(1)
+#else
+#define ML300_UART1
+#endif
+
+#if defined(XPAR_INTC_0_UARTNS550_2_VEC_ID)
+#define ML300_UART2 STD_UART_OP(2)
+#else
+#define ML300_UART2
+#endif
+
+#if defined(XPAR_INTC_0_UARTNS550_3_VEC_ID)
+#define ML300_UART3 STD_UART_OP(3)
+#else
+#define ML300_UART3
+#endif
+
+#if defined(XPAR_INTC_0_UARTNS550_4_VEC_ID)
+#error Edit this file to add more devices.
+#elif defined(XPAR_INTC_0_UARTNS550_3_VEC_ID)
+#define NR_SER_PORTS	4
+#elif defined(XPAR_INTC_0_UARTNS550_2_VEC_ID)
+#define NR_SER_PORTS	3
+#elif defined(XPAR_INTC_0_UARTNS550_1_VEC_ID)
+#define NR_SER_PORTS	2
+#elif defined(XPAR_INTC_0_UARTNS550_0_VEC_ID)
+#define NR_SER_PORTS	1
+#else
+#define NR_SER_PORTS	0
+#endif
+
+#if defined(CONFIG_UART0_TTYS0)
+#define SERIAL_PORT_DFNS	\
+	ML300_UART0		\
+	ML300_UART1		\
+	ML300_UART2		\
+	ML300_UART3
+#endif
+
+#if defined(CONFIG_UART0_TTYS1)
+#define SERIAL_PORT_DFNS	\
+	ML300_UART1		\
+	ML300_UART0		\
+	ML300_UART2		\
+	ML300_UART3
+#endif
+
+#define DCRN_CPMFR_BASE	0
+
+#include <asm/ibm405.h>
+
+#endif				/* __ASM_VIRTEXIIPRO_H__ */
+#endif				/* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/walnut.c b/arch/ppc/platforms/4xx/walnut.c
new file mode 100644
index 0000000..a33eda4
--- /dev/null
+++ b/arch/ppc/platforms/4xx/walnut.c
@@ -0,0 +1,249 @@
+/*
+ * arch/ppc/platforms/4xx/walnut.c
+ *
+ * Architecture- / platform-specific boot-time initialization code for
+ * IBM PowerPC 4xx based boards. Adapted from original
+ * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
+ * <dan@net4x.com>.
+ *
+ * Copyright(c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * 2002 (c) MontaVista, Software, Inc.  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/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/rtc.h>
+
+#include <asm/system.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/ocp.h>
+#include <asm/ibm_ocp_pci.h>
+#include <asm/todc.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+void *kb_cs;
+void *kb_data;
+void *walnut_rtc_base;
+
+/* Some IRQs unique to Walnut.
+ * Used by the generic 405 PCI setup functions in ppc4xx_pci.c
+ */
+int __init
+ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	    /*
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *      A       B       C       D
+	     */
+	{
+		{28, 28, 28, 28},	/* IDSEL 1 - PCI slot 1 */
+		{29, 29, 29, 29},	/* IDSEL 2 - PCI slot 2 */
+		{30, 30, 30, 30},	/* IDSEL 3 - PCI slot 3 */
+		{31, 31, 31, 31},	/* IDSEL 4 - PCI slot 4 */
+	};
+
+	const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+};
+
+void __init
+walnut_setup_arch(void)
+{
+
+	void *fpga_brdc;
+	unsigned char fpga_brdc_data;
+	void *fpga_enable;
+	void *fpga_polarity;
+	void *fpga_status;
+	void *fpga_trigger;
+
+	ppc4xx_setup_arch();
+
+	ibm_ocp_set_emac(0, 0);
+
+	kb_data = ioremap(WALNUT_PS2_BASE, 8);
+	if (!kb_data) {
+		printk(KERN_CRIT
+		       "walnut_setup_arch() kb_data ioremap failed\n");
+		return;
+	}
+
+	kb_cs = kb_data + 1;
+
+	fpga_status = ioremap(WALNUT_FPGA_BASE, 8);
+	if (!fpga_status) {
+		printk(KERN_CRIT
+		       "walnut_setup_arch() fpga_status ioremap failed\n");
+		return;
+	}
+
+	fpga_enable = fpga_status + 1;
+	fpga_polarity = fpga_status + 2;
+	fpga_trigger = fpga_status + 3;
+	fpga_brdc = fpga_status + 4;
+
+	/* split the keyboard and mouse interrupts */
+	fpga_brdc_data = readb(fpga_brdc);
+	fpga_brdc_data |= 0x80;
+	writeb(fpga_brdc_data, fpga_brdc);
+
+	writeb(0x3, fpga_enable);
+
+	writeb(0x3, fpga_polarity);
+
+	writeb(0x3, fpga_trigger);
+
+	/* RTC step for the walnut */
+	walnut_rtc_base = (void *) WALNUT_RTC_VADDR;
+	TODC_INIT(TODC_TYPE_DS1743, walnut_rtc_base, walnut_rtc_base,
+		  walnut_rtc_base, 8);
+	/* Identify the system */
+	printk("IBM Walnut port (C) 2000-2002 MontaVista Software, Inc. (source@mvista.com)\n");
+}
+
+void __init
+bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
+{
+#ifdef CONFIG_PCI
+	unsigned int bar_response, bar;
+	/*
+	 * Expected PCI mapping:
+	 *
+	 *  PLB addr             PCI memory addr
+	 *  ---------------------       ---------------------
+	 *  0000'0000 - 7fff'ffff <---  0000'0000 - 7fff'ffff
+	 *  8000'0000 - Bfff'ffff --->  8000'0000 - Bfff'ffff
+	 *
+	 *  PLB addr             PCI io addr
+	 *  ---------------------       ---------------------
+	 *  e800'0000 - e800'ffff --->  0000'0000 - 0001'0000
+	 *
+	 * The following code is simplified by assuming that the bootrom
+	 * has been well behaved in following this mapping.
+	 */
+
+#ifdef DEBUG
+	int i;
+
+	printk("ioremap PCLIO_BASE = 0x%x\n", pcip);
+	printk("PCI bridge regs before fixup \n");
+	for (i = 0; i <= 3; i++) {
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
+	}
+	printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+	printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+	printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+	printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+#endif
+
+	/* added for IBM boot rom version 1.15 bios bar changes  -AK */
+
+	/* Disable region first */
+	out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
+	/* PLB starting addr, PCI: 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
+	/* PCI start addr, 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
+	/* 512MB range of PLB to PCI */
+	out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
+	/* Enable no pre-fetch, enable region */
+	out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
+						(PPC405_PCI_UPPER_MEM -
+						 PPC405_PCI_MEM_BASE)) | 0x01));
+
+	/* Disable region one */
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->ptm1ms), 0x00000000);
+
+	/* Disable region two */
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+
+	/* Zero config bars */
+	for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+		early_write_config_dword(hose, hose->first_busno,
+					 PCI_FUNC(hose->first_busno), bar,
+					 0x00000000);
+		early_read_config_dword(hose, hose->first_busno,
+					PCI_FUNC(hose->first_busno), bar,
+					&bar_response);
+		DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
+		    hose->first_busno, PCI_SLOT(hose->first_busno),
+		    PCI_FUNC(hose->first_busno), bar, bar_response);
+	}
+	/* end work arround */
+
+#ifdef DEBUG
+	printk("PCI bridge regs after fixup \n");
+	for (i = 0; i <= 3; i++) {
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
+	}
+	printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+	printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+	printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+	printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+#endif
+#endif
+}
+
+void __init
+walnut_map_io(void)
+{
+	ppc4xx_map_io();
+	io_block_mapping(WALNUT_RTC_VADDR,
+			 WALNUT_RTC_PADDR, WALNUT_RTC_SIZE, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	ppc4xx_init(r3, r4, r5, r6, r7);
+
+	ppc_md.setup_arch = walnut_setup_arch;
+	ppc_md.setup_io_mappings = walnut_map_io;
+
+#ifdef CONFIG_GEN_RTC
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+#endif
+}
diff --git a/arch/ppc/platforms/4xx/walnut.h b/arch/ppc/platforms/4xx/walnut.h
new file mode 100644
index 0000000..04cfbf3
--- /dev/null
+++ b/arch/ppc/platforms/4xx/walnut.h
@@ -0,0 +1,72 @@
+/*
+ * arch/ppc/platforms/4xx/walnut.h
+ *
+ * Macros, definitions, and data structures specific to the IBM PowerPC
+ * 405GP "Walnut" evaluation board.
+ *
+ * Authors: Grant Erickson <grant@lcse.umn.edu>, Frank Rowand
+ * <frank_rowand@mvista.com>, Debbie Chu <debbie_chu@mvista.com> or
+ * source@mvista.com
+ *
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * 2000 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_WALNUT_H__
+#define __ASM_WALNUT_H__
+
+/* We have a 405GP core */
+#include <platforms/4xx/ibm405gp.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's "Walnut" evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
+
+typedef struct board_info {
+	unsigned char	 bi_s_version[4];	/* Version of this structure */
+	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address */
+	unsigned char	 bi_pci_enetaddr[6];	/* PCI Ethernet MAC address */
+	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
+	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
+} bd_t;
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+
+/* Memory map for the IBM "Walnut" 405GP evaluation board.
+ * Generic 4xx plus RTC.
+ */
+
+extern void *walnut_rtc_base;
+#define WALNUT_RTC_PADDR	((uint)0xf0000000)
+#define WALNUT_RTC_VADDR	WALNUT_RTC_PADDR
+#define WALNUT_RTC_SIZE		((uint)8*1024)
+
+#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
+#define BASE_BAUD		201600
+#else
+#define BASE_BAUD		691200
+#endif
+
+#define WALNUT_PS2_BASE		0xF0100000
+#define WALNUT_FPGA_BASE	0xF0300000
+
+#define PPC4xx_MACHINE_NAME	"IBM Walnut"
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_WALNUT_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.c b/arch/ppc/platforms/4xx/xilinx_ml300.c
new file mode 100644
index 0000000..0b1b77d
--- /dev/null
+++ b/arch/ppc/platforms/4xx/xilinx_ml300.c
@@ -0,0 +1,146 @@
+/*
+ * arch/ppc/platforms/4xx/xilinx_ml300.c
+ *
+ * Xilinx ML300 evaluation board initialization
+ *
+ * Author: MontaVista Software, Inc.
+ *         source@mvista.com
+ *
+ * 2002-2004 (c) MontaVista Software, Inc.  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/init.h>
+#include <linux/irq.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serialP.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+
+#include <platforms/4xx/virtex-ii_pro.h>	/* for NR_SER_PORTS */
+
+/*
+ * As an overview of how the following functions (platform_init,
+ * ml300_map_io, ml300_setup_arch and ml300_init_IRQ) fit into the
+ * kernel startup procedure, here's a call tree:
+ *
+ * start_here					arch/ppc/kernel/head_4xx.S
+ *  early_init					arch/ppc/kernel/setup.c
+ *  machine_init				arch/ppc/kernel/setup.c
+ *    platform_init				this file
+ *      ppc4xx_init				arch/ppc/syslib/ppc4xx_setup.c
+ *        parse_bootinfo
+ *          find_bootinfo
+ *        "setup some default ppc_md pointers"
+ *  MMU_init					arch/ppc/mm/init.c
+ *    *ppc_md.setup_io_mappings == ml300_map_io	this file
+ *      ppc4xx_map_io				arch/ppc/syslib/ppc4xx_setup.c
+ *  start_kernel				init/main.c
+ *    setup_arch				arch/ppc/kernel/setup.c
+ * #if defined(CONFIG_KGDB)
+ *      *ppc_md.kgdb_map_scc() == gen550_kgdb_map_scc
+ * #endif
+ *      *ppc_md.setup_arch == ml300_setup_arch	this file
+ *        ppc4xx_setup_arch			arch/ppc/syslib/ppc4xx_setup.c
+ *          ppc4xx_find_bridges			arch/ppc/syslib/ppc405_pci.c
+ *    init_IRQ					arch/ppc/kernel/irq.c
+ *      *ppc_md.init_IRQ == ml300_init_IRQ	this file
+ *        ppc4xx_init_IRQ			arch/ppc/syslib/ppc4xx_setup.c
+ *          ppc4xx_pic_init			arch/ppc/syslib/xilinx_pic.c
+ */
+
+#if defined(XPAR_POWER_0_POWERDOWN_BASEADDR)
+
+static volatile unsigned *powerdown_base =
+    (volatile unsigned *) XPAR_POWER_0_POWERDOWN_BASEADDR;
+
+static void
+xilinx_power_off(void)
+{
+	local_irq_disable();
+	out_be32(powerdown_base, XPAR_POWER_0_POWERDOWN_VALUE);
+	while (1) ;
+}
+#endif
+
+void __init
+ml300_map_io(void)
+{
+	ppc4xx_map_io();
+
+#if defined(XPAR_POWER_0_POWERDOWN_BASEADDR)
+	powerdown_base = ioremap((unsigned long) powerdown_base,
+				 XPAR_POWER_0_POWERDOWN_HIGHADDR -
+				 XPAR_POWER_0_POWERDOWN_BASEADDR + 1);
+#endif
+}
+
+static void __init
+ml300_early_serial_map(void)
+{
+#ifdef CONFIG_SERIAL_8250
+	struct serial_state old_ports[] = { SERIAL_PORT_DFNS };
+	struct uart_port port;
+	int i;
+
+	/* Setup ioremapped serial port access */
+	for (i = 0; i < ARRAY_SIZE(old_ports); i++ ) {
+		memset(&port, 0, sizeof(port));
+		port.membase = ioremap((phys_addr_t)(old_ports[i].iomem_base), 16);
+		port.irq = old_ports[i].irq;
+		port.uartclk = old_ports[i].baud_base * 16;
+		port.regshift = old_ports[i].iomem_reg_shift;
+		port.iotype = SERIAL_IO_MEM;
+		port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+		port.line = i;
+
+		if (early_serial_setup(&port) != 0) {
+			printk("Early serial init of port %d failed\n", i);
+		}
+	}
+#endif /* CONFIG_SERIAL_8250 */
+}
+
+void __init
+ml300_setup_arch(void)
+{
+	ppc4xx_setup_arch();	/* calls ppc4xx_find_bridges() */
+
+	ml300_early_serial_map();
+
+	/* Identify the system */
+	printk(KERN_INFO "Xilinx Virtex-II Pro port\n");
+	printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+}
+
+/* Called after board_setup_irq from ppc4xx_init_IRQ(). */
+void __init
+ml300_init_irq(void)
+{
+	ppc4xx_init_IRQ();
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	ppc4xx_init(r3, r4, r5, r6, r7);
+
+	ppc_md.setup_arch = ml300_setup_arch;
+	ppc_md.setup_io_mappings = ml300_map_io;
+	ppc_md.init_IRQ = ml300_init_irq;
+
+#if defined(XPAR_POWER_0_POWERDOWN_BASEADDR)
+	ppc_md.power_off = xilinx_power_off;
+#endif
+
+#ifdef CONFIG_KGDB
+	ppc_md.early_serial_map = ml300_early_serial_map;
+#endif
+}
+
diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.h b/arch/ppc/platforms/4xx/xilinx_ml300.h
new file mode 100644
index 0000000..f8c5884
--- /dev/null
+++ b/arch/ppc/platforms/4xx/xilinx_ml300.h
@@ -0,0 +1,47 @@
+/*
+ * arch/ppc/platforms/4xx/xilinx_ml300.h
+ *
+ * Include file that defines the Xilinx ML300 evaluation board
+ *
+ * Author: MontaVista Software, Inc.
+ *         source@mvista.com
+ *
+ * 2002-2004 (c) MontaVista Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_XILINX_ML300_H__
+#define __ASM_XILINX_ML300_H__
+
+/* ML300 has a Xilinx Virtex-II Pro processor */
+#include <platforms/4xx/virtex-ii_pro.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+typedef struct board_info {
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address */
+	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
+	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
+} bd_t;
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+#endif /* !__ASSEMBLY__ */
+
+/* We don't need anything mapped.  Size of zero will accomplish that. */
+#define PPC4xx_ONB_IO_PADDR	0u
+#define PPC4xx_ONB_IO_VADDR	0u
+#define PPC4xx_ONB_IO_SIZE	0u
+
+#define PPC4xx_MACHINE_NAME "Xilinx ML300"
+
+#endif /* __ASM_XILINX_ML300_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/xparameters/xparameters_ml300.h b/arch/ppc/platforms/4xx/xparameters/xparameters_ml300.h
new file mode 100644
index 0000000..97e3f4d
--- /dev/null
+++ b/arch/ppc/platforms/4xx/xparameters/xparameters_ml300.h
@@ -0,0 +1,310 @@
+/*******************************************************************
+*
+*     Author: Xilinx, 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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     You should have received a copy of the GNU General Public License along
+*     with this program; if not, write to the Free Software Foundation, Inc.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Description: Driver parameters
+*
+*******************************************************************/
+
+#define XPAR_XPCI_NUM_INSTANCES 1
+#define XPAR_XPCI_CLOCK_HZ 33333333
+#define XPAR_OPB_PCI_REF_0_DEVICE_ID 0
+#define XPAR_OPB_PCI_REF_0_BASEADDR 0x20000000
+#define XPAR_OPB_PCI_REF_0_HIGHADDR 0x3FFFFFFF
+#define XPAR_OPB_PCI_REF_0_CONFIG_ADDR 0x3C000000
+#define XPAR_OPB_PCI_REF_0_CONFIG_DATA 0x3C000004
+#define XPAR_OPB_PCI_REF_0_LCONFIG_ADDR 0x3E000000
+#define XPAR_OPB_PCI_REF_0_MEM_BASEADDR 0x20000000
+#define XPAR_OPB_PCI_REF_0_MEM_HIGHADDR 0x37FFFFFF
+#define XPAR_OPB_PCI_REF_0_IO_BASEADDR 0x38000000
+#define XPAR_OPB_PCI_REF_0_IO_HIGHADDR 0x3BFFFFFF
+
+/******************************************************************/
+
+#define XPAR_XEMAC_NUM_INSTANCES 1
+#define XPAR_OPB_ETHERNET_0_BASEADDR 0x60000000
+#define XPAR_OPB_ETHERNET_0_HIGHADDR 0x60003FFF
+#define XPAR_OPB_ETHERNET_0_DEVICE_ID 0
+#define XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST 1
+#define XPAR_OPB_ETHERNET_0_DMA_PRESENT 1
+#define XPAR_OPB_ETHERNET_0_MII_EXIST 1
+
+/******************************************************************/
+
+#define XPAR_MY_OPB_GPIO_0_DEVICE_ID_0 0
+#define XPAR_MY_OPB_GPIO_0_BASEADDR_0 0x90000000
+#define XPAR_MY_OPB_GPIO_0_HIGHADDR_0 (0x90000000+0x7)
+#define XPAR_MY_OPB_GPIO_0_DEVICE_ID_1 1
+#define XPAR_MY_OPB_GPIO_0_BASEADDR_1 (0x90000000+0x8)
+#define XPAR_MY_OPB_GPIO_0_HIGHADDR_1 (0x90000000+0x1F)
+#define XPAR_XGPIO_NUM_INSTANCES 2
+
+/******************************************************************/
+
+#define XPAR_XIIC_NUM_INSTANCES 1
+#define XPAR_OPB_IIC_0_BASEADDR 0xA8000000
+#define XPAR_OPB_IIC_0_HIGHADDR 0xA80001FF
+#define XPAR_OPB_IIC_0_DEVICE_ID 0
+#define XPAR_OPB_IIC_0_TEN_BIT_ADR 0
+
+/******************************************************************/
+
+#define XPAR_XUARTNS550_NUM_INSTANCES 2
+#define XPAR_XUARTNS550_CLOCK_HZ 100000000
+#define XPAR_OPB_UART16550_0_BASEADDR 0xA0000000
+#define XPAR_OPB_UART16550_0_HIGHADDR 0xA0001FFF
+#define XPAR_OPB_UART16550_0_DEVICE_ID 0
+#define XPAR_OPB_UART16550_1_BASEADDR 0xA0010000
+#define XPAR_OPB_UART16550_1_HIGHADDR 0xA0011FFF
+#define XPAR_OPB_UART16550_1_DEVICE_ID 1
+
+/******************************************************************/
+
+#define XPAR_XSPI_NUM_INSTANCES 1
+#define XPAR_OPB_SPI_0_BASEADDR 0xA4000000
+#define XPAR_OPB_SPI_0_HIGHADDR 0xA400007F
+#define XPAR_OPB_SPI_0_DEVICE_ID 0
+#define XPAR_OPB_SPI_0_FIFO_EXIST 1
+#define XPAR_OPB_SPI_0_SPI_SLAVE_ONLY 0
+#define XPAR_OPB_SPI_0_NUM_SS_BITS 1
+
+/******************************************************************/
+
+#define XPAR_XPS2_NUM_INSTANCES 2
+#define XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_0 0
+#define XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_0 0xA9000000
+#define XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_0 (0xA9000000+0x3F)
+#define XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_1 1
+#define XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_1 (0xA9000000+0x1000)
+#define XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_1 (0xA9000000+0x103F)
+
+/******************************************************************/
+
+#define XPAR_XTOUCHSCREEN_NUM_INSTANCES 1
+#define XPAR_OPB_TSD_REF_0_BASEADDR 0xAA000000
+#define XPAR_OPB_TSD_REF_0_HIGHADDR 0xAA000007
+#define XPAR_OPB_TSD_REF_0_DEVICE_ID 0
+
+/******************************************************************/
+
+#define XPAR_OPB_AC97_CONTROLLER_REF_0_BASEADDR 0xA6000000
+#define XPAR_OPB_AC97_CONTROLLER_REF_0_HIGHADDR 0xA60000FF
+#define XPAR_OPB_PAR_PORT_REF_0_BASEADDR 0x90010000
+#define XPAR_OPB_PAR_PORT_REF_0_HIGHADDR 0x900100FF
+#define XPAR_PLB_DDR_0_BASEADDR 0x00000000
+#define XPAR_PLB_DDR_0_HIGHADDR 0x0FFFFFFF
+
+/******************************************************************/
+
+#define XPAR_XINTC_HAS_IPR 1
+#define XPAR_INTC_MAX_NUM_INTR_INPUTS 18
+#define XPAR_XINTC_USE_DCR 0
+#define XPAR_XINTC_NUM_INSTANCES 1
+#define XPAR_DCR_INTC_0_BASEADDR 0xD0000FC0
+#define XPAR_DCR_INTC_0_HIGHADDR 0xD0000FDF
+#define XPAR_DCR_INTC_0_DEVICE_ID 0
+#define XPAR_DCR_INTC_0_KIND_OF_INTR 0x00038000
+
+/******************************************************************/
+
+#define XPAR_DCR_INTC_0_MISC_LOGIC_0_PHY_MII_INT_INTR 0
+#define XPAR_DCR_INTC_0_OPB_ETHERNET_0_IP2INTC_IRPT_INTR 1
+#define XPAR_DCR_INTC_0_MISC_LOGIC_0_IIC_TEMP_CRIT_INTR 2
+#define XPAR_DCR_INTC_0_MISC_LOGIC_0_IIC_IRQ_INTR 3
+#define XPAR_DCR_INTC_0_OPB_IIC_0_IP2INTC_IRPT_INTR 4
+#define XPAR_DCR_INTC_0_OPB_SYSACE_0_SYSACE_IRQ_INTR 5
+#define XPAR_DCR_INTC_0_OPB_UART16550_0_IP2INTC_IRPT_INTR 6
+#define XPAR_DCR_INTC_0_OPB_UART16550_1_IP2INTC_IRPT_INTR 7
+#define XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR1_INTR 8
+#define XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR2_INTR 9
+#define XPAR_DCR_INTC_0_OPB_SPI_0_IP2INTC_IRPT_INTR 10
+#define XPAR_DCR_INTC_0_OPB_TSD_REF_0_INTR_INTR 11
+#define XPAR_DCR_INTC_0_OPB_AC97_CONTROLLER_REF_0_PLAYBACK_INTERRUPT_INTR 12
+#define XPAR_DCR_INTC_0_OPB_AC97_CONTROLLER_REF_0_RECORD_INTERRUPT_INTR 13
+#define XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR 14
+#define XPAR_DCR_INTC_0_PLB2OPB_BRIDGE_0_BUS_ERROR_DET_INTR 15
+#define XPAR_DCR_INTC_0_PLB_V34_0_BUS_ERROR_DET_INTR 16
+#define XPAR_DCR_INTC_0_OPB2PLB_BRIDGE_0_BUS_ERROR_DET_INTR 17
+
+/******************************************************************/
+
+#define XPAR_XTFT_NUM_INSTANCES 1
+#define XPAR_PLB_TFT_CNTLR_REF_0_DCR_BASEADDR 0xD0000200
+#define XPAR_PLB_TFT_CNTLR_REF_0_DCR_HIGHADDR 0xD0000207
+#define XPAR_PLB_TFT_CNTLR_REF_0_DEVICE_ID 0
+
+/******************************************************************/
+
+#define XPAR_XSYSACE_MEM_WIDTH 8
+#define XPAR_XSYSACE_NUM_INSTANCES 1
+#define XPAR_OPB_SYSACE_0_BASEADDR 0xCF000000
+#define XPAR_OPB_SYSACE_0_HIGHADDR 0xCF0001FF
+#define XPAR_OPB_SYSACE_0_DEVICE_ID 0
+#define XPAR_OPB_SYSACE_0_MEM_WIDTH 8
+
+/******************************************************************/
+
+#define XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ 300000000
+
+/******************************************************************/
+
+/******************************************************************/
+
+/* Linux Redefines */
+
+/******************************************************************/
+
+#define XPAR_UARTNS550_0_BASEADDR (XPAR_OPB_UART16550_0_BASEADDR+0x1000)
+#define XPAR_UARTNS550_0_HIGHADDR XPAR_OPB_UART16550_0_HIGHADDR
+#define XPAR_UARTNS550_0_CLOCK_FREQ_HZ XPAR_XUARTNS550_CLOCK_HZ
+#define XPAR_UARTNS550_0_DEVICE_ID XPAR_OPB_UART16550_0_DEVICE_ID
+#define XPAR_UARTNS550_1_BASEADDR (XPAR_OPB_UART16550_1_BASEADDR+0x1000)
+#define XPAR_UARTNS550_1_HIGHADDR XPAR_OPB_UART16550_1_HIGHADDR
+#define XPAR_UARTNS550_1_CLOCK_FREQ_HZ XPAR_XUARTNS550_CLOCK_HZ
+#define XPAR_UARTNS550_1_DEVICE_ID XPAR_OPB_UART16550_1_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_GPIO_0_BASEADDR XPAR_MY_OPB_GPIO_0_BASEADDR_0
+#define XPAR_GPIO_0_HIGHADDR XPAR_MY_OPB_GPIO_0_HIGHADDR_0
+#define XPAR_GPIO_0_DEVICE_ID XPAR_MY_OPB_GPIO_0_DEVICE_ID_0
+#define XPAR_GPIO_1_BASEADDR XPAR_MY_OPB_GPIO_0_BASEADDR_1
+#define XPAR_GPIO_1_HIGHADDR XPAR_MY_OPB_GPIO_0_HIGHADDR_1
+#define XPAR_GPIO_1_DEVICE_ID XPAR_MY_OPB_GPIO_0_DEVICE_ID_1
+
+/******************************************************************/
+
+#define XPAR_IIC_0_BASEADDR XPAR_OPB_IIC_0_BASEADDR
+#define XPAR_IIC_0_HIGHADDR XPAR_OPB_IIC_0_HIGHADDR
+#define XPAR_IIC_0_TEN_BIT_ADR XPAR_OPB_IIC_0_TEN_BIT_ADR
+#define XPAR_IIC_0_DEVICE_ID XPAR_OPB_IIC_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_SYSACE_0_BASEADDR XPAR_OPB_SYSACE_0_BASEADDR
+#define XPAR_SYSACE_0_HIGHADDR XPAR_OPB_SYSACE_0_HIGHADDR
+#define XPAR_SYSACE_0_DEVICE_ID XPAR_OPB_SYSACE_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_INTC_0_BASEADDR XPAR_DCR_INTC_0_BASEADDR
+#define XPAR_INTC_0_HIGHADDR XPAR_DCR_INTC_0_HIGHADDR
+#define XPAR_INTC_0_KIND_OF_INTR XPAR_DCR_INTC_0_KIND_OF_INTR
+#define XPAR_INTC_0_DEVICE_ID XPAR_DCR_INTC_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_INTC_0_EMAC_0_VEC_ID XPAR_DCR_INTC_0_OPB_ETHERNET_0_IP2INTC_IRPT_INTR
+#define XPAR_INTC_0_IIC_0_VEC_ID XPAR_DCR_INTC_0_OPB_IIC_0_IP2INTC_IRPT_INTR
+#define XPAR_INTC_0_SYSACE_0_VEC_ID XPAR_DCR_INTC_0_OPB_SYSACE_0_SYSACE_IRQ_INTR
+#define XPAR_INTC_0_UARTNS550_0_VEC_ID XPAR_DCR_INTC_0_OPB_UART16550_0_IP2INTC_IRPT_INTR
+#define XPAR_INTC_0_UARTNS550_1_VEC_ID XPAR_DCR_INTC_0_OPB_UART16550_1_IP2INTC_IRPT_INTR
+#define XPAR_INTC_0_PS2_0_VEC_ID XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR1_INTR
+#define XPAR_INTC_0_PS2_1_VEC_ID XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR2_INTR
+#define XPAR_INTC_0_SPI_0_VEC_ID XPAR_DCR_INTC_0_OPB_SPI_0_IP2INTC_IRPT_INTR
+#define XPAR_INTC_0_TOUCHSCREEN_0_VEC_ID XPAR_DCR_INTC_0_OPB_TSD_REF_0_INTR_INTR
+#define XPAR_INTC_0_PCI_0_VEC_ID_A XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR
+#define XPAR_INTC_0_PCI_0_VEC_ID_B XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR
+#define XPAR_INTC_0_PCI_0_VEC_ID_C XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR
+#define XPAR_INTC_0_PCI_0_VEC_ID_D XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR
+
+/******************************************************************/
+
+#define XPAR_EMAC_0_BASEADDR XPAR_OPB_ETHERNET_0_BASEADDR
+#define XPAR_EMAC_0_HIGHADDR XPAR_OPB_ETHERNET_0_HIGHADDR
+#define XPAR_EMAC_0_DMA_PRESENT XPAR_OPB_ETHERNET_0_DMA_PRESENT
+#define XPAR_EMAC_0_MII_EXIST XPAR_OPB_ETHERNET_0_MII_EXIST
+#define XPAR_EMAC_0_ERR_COUNT_EXIST XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST
+#define XPAR_EMAC_0_DEVICE_ID XPAR_OPB_ETHERNET_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_SPI_0_BASEADDR XPAR_OPB_SPI_0_BASEADDR
+#define XPAR_SPI_0_HIGHADDR XPAR_OPB_SPI_0_HIGHADDR
+#define XPAR_SPI_0_DEVICE_ID XPAR_OPB_SPI_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_TOUCHSCREEN_0_BASEADDR XPAR_OPB_TSD_REF_0_BASEADDR
+#define XPAR_TOUCHSCREEN_0_HIGHADDR XPAR_OPB_TSD_REF_0_HIGHADDR
+#define XPAR_TOUCHSCREEN_0_DEVICE_ID XPAR_OPB_TSD_REF_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_TFT_0_BASEADDR XPAR_PLB_TFT_CNTLR_REF_0_DCR_BASEADDR
+
+/******************************************************************/
+
+#define XPAR_PCI_0_BASEADDR XPAR_OPB_PCI_REF_0_BASEADDR
+#define XPAR_PCI_0_HIGHADDR XPAR_OPB_PCI_REF_0_HIGHADDR
+#define XPAR_PCI_0_CONFIG_ADDR XPAR_OPB_PCI_REF_0_CONFIG_ADDR
+#define XPAR_PCI_0_CONFIG_DATA XPAR_OPB_PCI_REF_0_CONFIG_DATA
+#define XPAR_PCI_0_LCONFIG_ADDR XPAR_OPB_PCI_REF_0_LCONFIG_ADDR
+#define XPAR_PCI_0_MEM_BASEADDR XPAR_OPB_PCI_REF_0_MEM_BASEADDR
+#define XPAR_PCI_0_MEM_HIGHADDR XPAR_OPB_PCI_REF_0_MEM_HIGHADDR
+#define XPAR_PCI_0_IO_BASEADDR XPAR_OPB_PCI_REF_0_IO_BASEADDR
+#define XPAR_PCI_0_IO_HIGHADDR XPAR_OPB_PCI_REF_0_IO_HIGHADDR
+#define XPAR_PCI_0_CLOCK_FREQ_HZ XPAR_XPCI_CLOCK_HZ
+#define XPAR_PCI_0_DEVICE_ID XPAR_OPB_PCI_REF_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_PS2_0_BASEADDR XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_0
+#define XPAR_PS2_0_HIGHADDR XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_0
+#define XPAR_PS2_0_DEVICE_ID XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_0
+#define XPAR_PS2_1_BASEADDR XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_1
+#define XPAR_PS2_1_HIGHADDR XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_1
+#define XPAR_PS2_1_DEVICE_ID XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_1
+
+/******************************************************************/
+
+#define XPAR_PLB_CLOCK_FREQ_HZ 100000000
+#define XPAR_CORE_CLOCK_FREQ_HZ XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ
+#define XPAR_DDR_0_SIZE 0x08000000
+
+/******************************************************************/
+
+#define XPAR_PERSISTENT_0_IIC_0_BASEADDR 0x00000400
+#define XPAR_PERSISTENT_0_IIC_0_HIGHADDR 0x000007FF
+#define XPAR_PERSISTENT_0_IIC_0_EEPROMADDR 0xA0
+
+/******************************************************************/
+
+#define XPAR_POWER_0_POWERDOWN_BASEADDR 0x90000004
+#define XPAR_POWER_0_POWERDOWN_HIGHADDR 0x90000007
+#define XPAR_POWER_0_POWERDOWN_VALUE 0xFF
+
+/******************************************************************/
diff --git a/arch/ppc/platforms/83xx/Makefile b/arch/ppc/platforms/83xx/Makefile
new file mode 100644
index 0000000..eb55341
--- /dev/null
+++ b/arch/ppc/platforms/83xx/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for the PowerPC 83xx linux kernel.
+#
+obj-$(CONFIG_MPC834x_SYS)	+= mpc834x_sys.o
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c
new file mode 100644
index 0000000..b3b0f51
--- /dev/null
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
@@ -0,0 +1,289 @@
+/*
+ * arch/ppc/platforms/83xx/mpc834x_sys.c
+ *
+ * MPC834x SYS board specific routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>	/* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/ipic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc83xx.h>
+#include <asm/irq.h>
+#include <asm/kgdb.h>
+#include <asm/ppc_sys.h>
+#include <mm/mmu_decl.h>
+
+#include <syslib/ppc83xx_setup.h>
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+extern unsigned long total_memory;	/* in mm/init */
+
+unsigned char __res[sizeof (bd_t)];
+
+#ifdef CONFIG_PCI
+#error "PCI is not supported"
+/* NEED mpc83xx_map_irq & mpc83xx_exclude_device
+   see platforms/85xx/mpc85xx_ads_common.c */
+#endif /* CONFIG_PCI */
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init
+mpc834x_sys_setup_arch(void)
+{
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
+	struct gianfar_platform_data *pdata;
+
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
+
+	/* Set loops_per_jiffy to a half-way reasonable value,
+	   for use until calibrate_delay gets called. */
+	loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+	/* setup PCI host bridges */
+	mpc83xx_sys_setup_hose();
+#endif
+	mpc83xx_early_serial_map();
+
+	/* setup the board related information for the enet controllers */
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1);
+	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+	pdata->interruptPHY = MPC83xx_IRQ_EXT1;
+	pdata->phyid = 0;
+	/* fixup phy address */
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2);
+	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+	pdata->interruptPHY = MPC83xx_IRQ_EXT2;
+	pdata->phyid = 1;
+	/* fixup phy address */
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef  CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+}
+
+static void __init
+mpc834x_sys_map_io(void)
+{
+	/* we steal the lowest ioremap addr for virt space */
+	io_block_mapping(VIRT_IMMRBAR, immrbar, 1024*1024, _PAGE_IO);
+	io_block_mapping(BCSR_VIRT_ADDR, BCSR_PHYS_ADDR, BCSR_SIZE, _PAGE_IO);
+}
+
+int
+mpc834x_sys_show_cpuinfo(struct seq_file *m)
+{
+	uint pvid, svid, phid1;
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
+
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
+
+	pvid = mfspr(SPRN_PVR);
+	svid = mfspr(SPRN_SVR);
+
+	seq_printf(m, "Vendor\t\t: Freescale Inc.\n");
+	seq_printf(m, "Machine\t\t: mpc%s sys\n", cur_ppc_sys_spec->ppc_sys_name);
+	seq_printf(m, "core clock\t: %d MHz\n"
+			"bus  clock\t: %d MHz\n",
+			(int)(binfo->bi_intfreq / 1000000),
+			(int)(binfo->bi_busfreq / 1000000));
+	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+	/* Display cpu Pll setting */
+	phid1 = mfspr(SPRN_HID1);
+	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+	/* Display the amount of memory */
+	seq_printf(m, "Memory\t\t: %d MB\n", (int)(binfo->bi_memsize / (1024 * 1024)));
+
+	return 0;
+}
+
+
+void __init
+mpc834x_sys_init_IRQ(void)
+{
+	bd_t *binfo = (bd_t *) __res;
+
+	u8 senses[8] = {
+		0,			/* EXT 0 */
+		IRQ_SENSE_LEVEL,	/* EXT 1 */
+		IRQ_SENSE_LEVEL,	/* EXT 2 */
+		0,			/* EXT 3 */
+		0,			/* EXT 4 */
+		0,			/* EXT 5 */
+		0,			/* EXT 6 */
+		0,			/* EXT 7 */
+	};
+
+	ipic_init(binfo->bi_immr_base + 0x00700, 0, MPC83xx_IPIC_IRQ_OFFSET, senses, 8);
+
+	/* Initialize the default interrupt mapping priorities,
+	 * in case the boot rom changed something on us.
+	 */
+	ipic_set_default_priority();
+}
+
+static __inline__ void
+mpc834x_sys_set_bat(void)
+{
+	/* we steal the lowest ioremap addr for virt space */
+	mb();
+	mtspr(SPRN_DBAT1U, VIRT_IMMRBAR | 0x1e);
+	mtspr(SPRN_DBAT1L, immrbar | 0x2a);
+	mb();
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	bd_t *binfo = (bd_t *) __res;
+
+	/* parse_bootinfo must always be called first */
+	parse_bootinfo(find_bootinfo());
+
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3) {
+		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+		       sizeof (bd_t));
+	}
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+	/*
+	 * If the init RAM disk has been configured in, and there's a valid
+	 * starting address for it, set it up.
+	 */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	/* Copy the kernel command line arguments to a safe place. */
+	if (r6) {
+		*(char *) (r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+	}
+
+	immrbar = binfo->bi_immr_base;
+
+	mpc834x_sys_set_bat();
+
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+	{
+		struct uart_port p;
+
+		memset(&p, 0, sizeof (p));
+		p.iotype = SERIAL_IO_MEM;
+		p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4500);
+		p.uartclk = binfo->bi_busfreq;
+
+		gen550_init(0, &p);
+
+		memset(&p, 0, sizeof (p));
+		p.iotype = SERIAL_IO_MEM;
+		p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4600);
+		p.uartclk = binfo->bi_busfreq;
+
+		gen550_init(1, &p);
+	}
+#endif
+
+	identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+	/* setup the PowerPC module struct */
+	ppc_md.setup_arch = mpc834x_sys_setup_arch;
+	ppc_md.show_cpuinfo = mpc834x_sys_show_cpuinfo;
+
+	ppc_md.init_IRQ = mpc834x_sys_init_IRQ;
+	ppc_md.get_irq = ipic_get_irq;
+
+	ppc_md.restart = mpc83xx_restart;
+	ppc_md.power_off = mpc83xx_power_off;
+	ppc_md.halt = mpc83xx_halt;
+
+	ppc_md.find_end_of_memory = mpc83xx_find_end_of_memory;
+	ppc_md.setup_io_mappings  = mpc834x_sys_map_io;
+
+	ppc_md.time_init = mpc83xx_time_init;
+	ppc_md.set_rtc_time = NULL;
+	ppc_md.get_rtc_time = NULL;
+	ppc_md.calibrate_decr = mpc83xx_calibrate_decr;
+
+	ppc_md.early_serial_map = mpc83xx_early_serial_map;
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+	ppc_md.progress = gen550_progress;
+#endif	/* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc834x_sys_init(): exit", 0);
+
+	return;
+}
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h
new file mode 100644
index 0000000..f4d055a
--- /dev/null
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.h
@@ -0,0 +1,51 @@
+/*
+ * arch/ppc/platforms/83xx/mpc834x_sys.h
+ *
+ * MPC834X SYS common board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor, 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.
+ *
+ */
+
+#ifndef __MACH_MPC83XX_SYS_H__
+#define __MACH_MPC83XX_SYS_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <syslib/ppc83xx_setup.h>
+#include <asm/ppcboot.h>
+
+#define VIRT_IMMRBAR		((uint)0xfe000000)
+
+#define BCSR_PHYS_ADDR		((uint)0xf8000000)
+#define BCSR_VIRT_ADDR		((uint)0xfe100000)
+#define BCSR_SIZE		((uint)(32 * 1024))
+
+#ifdef CONFIG_PCI
+/* PCI interrupt controller */
+#define PIRQA        MPC83xx_IRQ_IRQ4
+#define PIRQB        MPC83xx_IRQ_IRQ5
+#define PIRQC        MPC83xx_IRQ_IRQ6
+#define PIRQD        MPC83xx_IRQ_IRQ7
+
+#define MPC834x_SYS_PCI1_LOWER_IO        0x00000000
+#define MPC834x_SYS_PCI1_UPPER_IO        0x00ffffff
+
+#define MPC834x_SYS_PCI1_LOWER_MEM       0x80000000
+#define MPC834x_SYS_PCI1_UPPER_MEM       0x9fffffff
+
+#define MPC834x_SYS_PCI1_IO_BASE         0xe2000000
+#define MPC834x_SYS_PCI1_MEM_OFFSET      0x00000000
+
+#define MPC834x_SYS_PCI1_IO_SIZE         0x01000000
+#endif /* CONFIG_PCI */
+
+#endif                /* __MACH_MPC83XX_SYS_H__ */
diff --git a/arch/ppc/platforms/85xx/Kconfig b/arch/ppc/platforms/85xx/Kconfig
new file mode 100644
index 0000000..ff92e38
--- /dev/null
+++ b/arch/ppc/platforms/85xx/Kconfig
@@ -0,0 +1,76 @@
+config 85xx
+	bool
+	depends on E500
+	default y
+
+config PPC_INDIRECT_PCI_BE
+	bool
+	depends on 85xx
+	default y
+
+menu "Freescale 85xx options"
+	depends on E500
+
+choice
+	prompt "Machine Type"
+	depends on 85xx
+	default MPC8540_ADS
+
+config MPC8540_ADS
+	bool "Freescale MPC8540 ADS"
+	help
+	  This option enables support for the MPC 8540 ADS evaluation board.
+
+config MPC8555_CDS
+	bool "Freescale MPC8555 CDS"
+	help
+	  This option enablese support for the MPC8555 CDS evaluation board.
+
+config MPC8560_ADS
+	bool "Freescale MPC8560 ADS"
+	help
+	  This option enables support for the MPC 8560 ADS evaluation board.
+
+config SBC8560
+	bool "WindRiver PowerQUICC III SBC8560"
+	help
+	  This option enables support for the WindRiver PowerQUICC III 
+	  SBC8560 board.
+
+config STX_GP3
+	bool "Silicon Turnkey Express GP3"
+	help
+	  This option enables support for the Silicon Turnkey Express GP3
+	  board.
+
+endchoice
+
+# It's often necessary to know the specific 85xx processor type.
+# Fortunately, it is implied (so far) from the board type, so we
+# don't need to ask more redundant questions.
+config MPC8540
+	bool
+	depends on MPC8540_ADS
+	default y
+
+config MPC8555
+	bool
+	depends on MPC8555_CDS
+	default y
+
+config MPC8560
+	bool
+	depends on SBC8560 || MPC8560_ADS || STX_GP3
+	default y
+
+config 85xx_PCI2
+	bool "Supprt for 2nd PCI host controller"
+	depends on MPC8555_CDS
+	default y
+
+config PPC_GEN550
+	bool
+	depends on MPC8540 || SBC8560 || MPC8555
+	default y
+
+endmenu
diff --git a/arch/ppc/platforms/85xx/Makefile b/arch/ppc/platforms/85xx/Makefile
new file mode 100644
index 0000000..854fbd2
--- /dev/null
+++ b/arch/ppc/platforms/85xx/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the PowerPC 85xx linux kernel.
+#
+obj-$(CONFIG_MPC8540_ADS)	+= mpc85xx_ads_common.o mpc8540_ads.o
+obj-$(CONFIG_MPC8555_CDS)	+= mpc85xx_cds_common.o
+obj-$(CONFIG_MPC8560_ADS)	+= mpc85xx_ads_common.o mpc8560_ads.o
+obj-$(CONFIG_SBC8560)		+= sbc85xx.o sbc8560.o
+obj-$(CONFIG_STX_GP3)		+= stx_gp3.o
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
new file mode 100644
index 0000000..4d857d6
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c
@@ -0,0 +1,218 @@
+/*
+ * arch/ppc/platforms/85xx/mpc8540_ads.c
+ *
+ * MPC8540ADS board specific routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>	/* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/kgdb.h>
+#include <asm/ppc_sys.h>
+#include <mm/mmu_decl.h>
+
+#include <syslib/ppc85xx_setup.h>
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init
+mpc8540ads_setup_arch(void)
+{
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
+	struct gianfar_platform_data *pdata;
+
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc8540ads_setup_arch()", 0);
+
+	/* Set loops_per_jiffy to a half-way reasonable value,
+	   for use until calibrate_delay gets called. */
+	loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+	/* setup PCI host bridges */
+	mpc85xx_setup_hose();
+#endif
+
+#ifdef CONFIG_SERIAL_8250
+	mpc85xx_early_serial_map();
+#endif
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	/* Invalidate the entry we stole earlier the serial ports
+	 * should be properly mapped */
+	invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+#endif
+
+	/* setup the board related information for the enet controllers */
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+	pdata->phyid = 0;
+	/* fixup phy address */
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+	pdata->phyid = 1;
+	/* fixup phy address */
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC);
+	pdata->board_flags = 0;
+	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+	pdata->phyid = 3;
+	/* fixup phy address */
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef  CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+}
+
+/* ************************************************************************ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	/* parse_bootinfo must always be called first */
+	parse_bootinfo(find_bootinfo());
+
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3) {
+		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+		       sizeof (bd_t));
+	}
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	{
+		bd_t *binfo = (bd_t *) __res;
+		struct uart_port p;
+
+		/* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
+		settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base,
+			  binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
+
+		memset(&p, 0, sizeof (p));
+		p.iotype = SERIAL_IO_MEM;
+		p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET;
+		p.uartclk = binfo->bi_busfreq;
+
+		gen550_init(0, &p);
+
+		memset(&p, 0, sizeof (p));
+		p.iotype = SERIAL_IO_MEM;
+		p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET;
+		p.uartclk = binfo->bi_busfreq;
+
+		gen550_init(1, &p);
+	}
+#endif
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+	/*
+	 * If the init RAM disk has been configured in, and there's a valid
+	 * starting address for it, set it up.
+	 */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif				/* CONFIG_BLK_DEV_INITRD */
+
+	/* Copy the kernel command line arguments to a safe place. */
+
+	if (r6) {
+		*(char *) (r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+	}
+
+	identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+	/* setup the PowerPC module struct */
+	ppc_md.setup_arch = mpc8540ads_setup_arch;
+	ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo;
+
+	ppc_md.init_IRQ = mpc85xx_ads_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+
+	ppc_md.restart = mpc85xx_restart;
+	ppc_md.power_off = mpc85xx_power_off;
+	ppc_md.halt = mpc85xx_halt;
+
+	ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
+
+	ppc_md.time_init = NULL;
+	ppc_md.set_rtc_time = NULL;
+	ppc_md.get_rtc_time = NULL;
+	ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+	ppc_md.progress = gen550_progress;
+#endif	/* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc8540ads_init(): exit", 0);
+
+	return;
+}
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.h b/arch/ppc/platforms/85xx/mpc8540_ads.h
new file mode 100644
index 0000000..3d05d7c
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.h
@@ -0,0 +1,25 @@
+/*
+ * arch/ppc/platforms/85xx/mpc8540_ads.h
+ *
+ * MPC8540ADS board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor 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.
+ *
+ */
+
+#ifndef __MACH_MPC8540ADS_H__
+#define __MACH_MPC8540ADS_H__
+
+#include <linux/config.h>
+#include <linux/initrd.h>
+#include <syslib/ppc85xx_setup.h>
+#include <platforms/85xx/mpc85xx_ads_common.h>
+
+#endif /* __MACH_MPC8540ADS_H__ */
diff --git a/arch/ppc/platforms/85xx/mpc8555_cds.h b/arch/ppc/platforms/85xx/mpc8555_cds.h
new file mode 100644
index 0000000..e0e7556
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc8555_cds.h
@@ -0,0 +1,26 @@
+/*
+ * arch/ppc/platforms/mpc8555_cds.h
+ *
+ * MPC8555CDS board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor 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.
+ *
+ */
+
+#ifndef __MACH_MPC8555CDS_H__
+#define __MACH_MPC8555CDS_H__
+
+#include <linux/config.h>
+#include <syslib/ppc85xx_setup.h>
+#include <platforms/85xx/mpc85xx_cds_common.h>
+
+#define CPM_MAP_ADDR	(CCSRBAR + MPC85xx_CPM_OFFSET)
+
+#endif /* __MACH_MPC8555CDS_H__ */
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
new file mode 100644
index 0000000..761b8c7
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
@@ -0,0 +1,210 @@
+/*
+ * arch/ppc/platforms/85xx/mpc8560_ads.c
+ *
+ * MPC8560ADS board specific routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>	/* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/kgdb.h>
+#include <asm/ppc_sys.h>
+#include <asm/cpm2.h>
+#include <mm/mmu_decl.h>
+
+#include <syslib/cpm2_pic.h>
+#include <syslib/ppc85xx_common.h>
+#include <syslib/ppc85xx_setup.h>
+
+extern void cpm2_reset(void);
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+
+static void __init
+mpc8560ads_setup_arch(void)
+{
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
+	struct gianfar_platform_data *pdata;
+
+	cpm2_reset();
+
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc8560ads_setup_arch()", 0);
+
+	/* Set loops_per_jiffy to a half-way reasonable value,
+	   for use until calibrate_delay gets called. */
+	loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+	/* setup PCI host bridges */
+	mpc85xx_setup_hose();
+#endif
+
+	/* setup the board related information for the enet controllers */
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+	pdata->phyid = 0;
+	/* fixup phy address */
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+	pdata->phyid = 1;
+	/* fixup phy address */
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef  CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+}
+
+static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
+{
+	while ((irq = cpm2_get_irq(regs)) >= 0)
+		__do_IRQ(irq, regs);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction cpm2_irqaction = {
+	.handler = cpm2_cascade,
+	.flags = SA_INTERRUPT,
+	.mask = CPU_MASK_NONE,
+	.name = "cpm2_cascade",
+};
+
+static void __init
+mpc8560_ads_init_IRQ(void)
+{
+	/* Setup OpenPIC */
+	mpc85xx_ads_init_IRQ();
+
+	/* Setup CPM2 PIC */
+        cpm2_init_IRQ();
+
+	setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
+
+	return;
+}
+
+
+
+/* ************************************************************************ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	/* parse_bootinfo must always be called first */
+	parse_bootinfo(find_bootinfo());
+
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3) {
+		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+		       sizeof (bd_t));
+
+	}
+#if defined(CONFIG_BLK_DEV_INITRD)
+	/*
+	 * If the init RAM disk has been configured in, and there's a valid
+	 * starting address for it, set it up.
+	 */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif				/* CONFIG_BLK_DEV_INITRD */
+
+	/* Copy the kernel command line arguments to a safe place. */
+
+	if (r6) {
+		*(char *) (r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+	}
+
+	identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+	/* setup the PowerPC module struct */
+	ppc_md.setup_arch = mpc8560ads_setup_arch;
+	ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo;
+
+	ppc_md.init_IRQ = mpc8560_ads_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+
+	ppc_md.restart = mpc85xx_restart;
+	ppc_md.power_off = mpc85xx_power_off;
+	ppc_md.halt = mpc85xx_halt;
+
+	ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
+
+	ppc_md.time_init = NULL;
+	ppc_md.set_rtc_time = NULL;
+	ppc_md.get_rtc_time = NULL;
+	ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc8560ads_init(): exit", 0);
+
+	return;
+}
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.h b/arch/ppc/platforms/85xx/mpc8560_ads.h
new file mode 100644
index 0000000..7df885d
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.h
@@ -0,0 +1,27 @@
+/*
+ * arch/ppc/platforms/mpc8560_ads.h
+ *
+ * MPC8540ADS board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor 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.
+ *
+ */
+
+#ifndef __MACH_MPC8560ADS_H
+#define __MACH_MPC8560ADS_H
+
+#include <linux/config.h>
+#include <syslib/ppc85xx_setup.h>
+#include <platforms/85xx/mpc85xx_ads_common.h>
+
+#define CPM_MAP_ADDR	(CCSRBAR + MPC85xx_CPM_OFFSET)
+#define PHY_INTERRUPT	MPC85xx_IRQ_EXT7
+
+#endif				/* __MACH_MPC8560ADS_H */
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
new file mode 100644
index 0000000..ba9f9f5
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
@@ -0,0 +1,225 @@
+/*
+ * arch/ppc/platforms/85xx/mpc85xx_ads_common.c
+ *
+ * MPC85xx ADS board common routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/ppc_sys.h>
+
+#include <mm/mmu_decl.h>
+
+#include <platforms/85xx/mpc85xx_ads_common.h>
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+extern unsigned long total_memory;	/* in mm/init */
+
+unsigned char __res[sizeof (bd_t)];
+
+/* Internal interrupts are all Level Sensitive, and Positive Polarity */
+
+static u_char mpc85xx_ads_openpic_initsenses[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: L2 Cache */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: ECM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  2: DDR DRAM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  3: LBIU */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  4: DMA 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  5: DMA 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  6: DMA 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  7: DMA 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  8: PCI/PCI-X */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: RIO Inbound Port Write Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10: RIO Doorbell Inbound */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11: RIO Outbound Message */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: RIO Inbound Message */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 0 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 0 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 0 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 1 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 1 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 1 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Fast Ethernet */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 27: I2C */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 28: Performance Monitor */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 29: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 30: CPM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
+	0x0,						/* External  0: */
+#if defined(CONFIG_PCI)
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 1: PCI slot 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 2: PCI slot 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 3: PCI slot 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 4: PCI slot 3 */
+#else
+	0x0,				/* External  1: */
+	0x0,				/* External  2: */
+	0x0,				/* External  3: */
+	0x0,				/* External  4: */
+#endif
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 5: PHY */
+	0x0,				/* External  6: */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 7: PHY */
+	0x0,				/* External  8: */
+	0x0,				/* External  9: */
+	0x0,				/* External 10: */
+	0x0,				/* External 11: */
+};
+
+/* ************************************************************************ */
+int
+mpc85xx_ads_show_cpuinfo(struct seq_file *m)
+{
+	uint pvid, svid, phid1;
+	uint memsize = total_memory;
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
+
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
+
+	pvid = mfspr(SPRN_PVR);
+	svid = mfspr(SPRN_SVR);
+
+	seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
+	seq_printf(m, "Machine\t\t: mpc%sads\n", cur_ppc_sys_spec->ppc_sys_name);
+	seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000);
+	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+	/* Display cpu Pll setting */
+	phid1 = mfspr(SPRN_HID1);
+	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+	/* Display the amount of memory */
+	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+
+	return 0;
+}
+
+void __init
+mpc85xx_ads_init_IRQ(void)
+{
+	bd_t *binfo = (bd_t *) __res;
+	/* Determine the Physical Address of the OpenPIC regs */
+	phys_addr_t OpenPIC_PAddr =
+	    binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+	OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
+	OpenPIC_InitSenses = mpc85xx_ads_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof (mpc85xx_ads_openpic_initsenses);
+
+	/* Skip reserved space and internal sources */
+	openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+	/* Map PIC IRQs 0-11 */
+	openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+
+	/* we let openpic interrupts starting from an offset, to
+	 * leave space for cascading interrupts underneath.
+	 */
+	openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
+
+	return;
+}
+
+#ifdef CONFIG_PCI
+/*
+ * interrupt routing
+ */
+
+int
+mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	    /*
+	     * This is little evil, but works around the fact
+	     * that revA boards have IDSEL starting at 18
+	     * and others boards (older) start at 12
+	     *
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *       A      B      C      D
+	     */
+	{
+		{PIRQA, PIRQB, PIRQC, PIRQD},	/* IDSEL 2 */
+		{PIRQD, PIRQA, PIRQB, PIRQC},
+		{PIRQC, PIRQD, PIRQA, PIRQB},
+		{PIRQB, PIRQC, PIRQD, PIRQA},	/* IDSEL 5 */
+		{0, 0, 0, 0},	/* -- */
+		{0, 0, 0, 0},	/* -- */
+		{0, 0, 0, 0},	/* -- */
+		{0, 0, 0, 0},	/* -- */
+		{0, 0, 0, 0},	/* -- */
+		{0, 0, 0, 0},	/* -- */
+		{PIRQA, PIRQB, PIRQC, PIRQD},	/* IDSEL 12 */
+		{PIRQD, PIRQA, PIRQB, PIRQC},
+		{PIRQC, PIRQD, PIRQA, PIRQB},
+		{PIRQB, PIRQC, PIRQD, PIRQA},	/* IDSEL 15 */
+		{0, 0, 0, 0},	/* -- */
+		{0, 0, 0, 0},	/* -- */
+		{PIRQA, PIRQB, PIRQC, PIRQD},	/* IDSEL 18 */
+		{PIRQD, PIRQA, PIRQB, PIRQC},
+		{PIRQC, PIRQD, PIRQA, PIRQB},
+		{PIRQB, PIRQC, PIRQD, PIRQA},	/* IDSEL 21 */
+	};
+
+	const long min_idsel = 2, max_idsel = 21, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+int
+mpc85xx_exclude_device(u_char bus, u_char devfn)
+{
+	if (bus == 0 && PCI_SLOT(devfn) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	else
+		return PCIBIOS_SUCCESSFUL;
+}
+
+#endif /* CONFIG_PCI */
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
new file mode 100644
index 0000000..3875e83
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
@@ -0,0 +1,50 @@
+/*
+ * arch/ppc/platforms/85xx/mpc85xx_ads_common.h
+ *
+ * MPC85XX ADS common board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor 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.
+ *
+ */
+
+#ifndef __MACH_MPC85XX_ADS_H__
+#define __MACH_MPC85XX_ADS_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <asm/ppcboot.h>
+
+#define BOARD_CCSRBAR		((uint)0xe0000000)
+#define BCSR_ADDR		((uint)0xf8000000)
+#define BCSR_SIZE		((uint)(32 * 1024))
+
+extern int mpc85xx_ads_show_cpuinfo(struct seq_file *m);
+extern void mpc85xx_ads_init_IRQ(void) __init;
+extern void mpc85xx_ads_map_io(void) __init;
+
+/* PCI interrupt controller */
+#define PIRQA		MPC85xx_IRQ_EXT1
+#define PIRQB		MPC85xx_IRQ_EXT2
+#define PIRQC		MPC85xx_IRQ_EXT3
+#define PIRQD		MPC85xx_IRQ_EXT4
+
+#define MPC85XX_PCI1_LOWER_IO	0x00000000
+#define MPC85XX_PCI1_UPPER_IO	0x00ffffff
+
+#define MPC85XX_PCI1_LOWER_MEM	0x80000000
+#define MPC85XX_PCI1_UPPER_MEM	0x9fffffff
+
+#define MPC85XX_PCI1_IO_BASE	0xe2000000
+#define MPC85XX_PCI1_MEM_OFFSET	0x00000000
+
+#define MPC85XX_PCI1_IO_SIZE	0x01000000
+
+#endif				/* __MACH_MPC85XX_ADS_H__ */
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
new file mode 100644
index 0000000..6c020d6
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -0,0 +1,467 @@
+/*
+ * arch/ppc/platform/85xx/mpc85xx_cds_common.c
+ *
+ * MPC85xx CDS board specific routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor, 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/immap_cpm2.h>
+#include <asm/ppc_sys.h>
+#include <asm/kgdb.h>
+
+#include <mm/mmu_decl.h>
+#include <syslib/cpm2_pic.h>
+#include <syslib/ppc85xx_common.h>
+#include <syslib/ppc85xx_setup.h>
+
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+extern unsigned long total_memory;      /* in mm/init */
+
+unsigned char __res[sizeof (bd_t)];
+
+static int cds_pci_slot = 2;
+static volatile u8 * cadmus;
+
+/* Internal interrupts are all Level Sensitive, and Positive Polarity */
+
+static u_char mpc85xx_cds_openpic_initsenses[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: L2 Cache */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: ECM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  2: DDR DRAM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  3: LBIU */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  4: DMA 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  5: DMA 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  6: DMA 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  7: DMA 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  8: PCI/PCI-X */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: RIO Inbound Port Write Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10: RIO Doorbell Inbound */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11: RIO Outbound Message */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: RIO Inbound Message */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 0 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 0 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 0 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 1 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 1 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 1 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Fast Ethernet */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 27: I2C */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 28: Performance Monitor */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 29: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 30: CPM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
+#if defined(CONFIG_PCI)
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 0: PCI1 slot */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 1: PCI1 slot */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 2: PCI1 slot */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 3: PCI1 slot */
+#else
+	0x0,						/* External  0: */
+	0x0,						/* External  1: */
+	0x0,						/* External  2: */
+	0x0,						/* External  3: */
+#endif
+	0x0,						/* External  4: */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External  5: PHY */
+	0x0,						/* External  6: */
+	0x0,						/* External  7: */
+	0x0,						/* External  8: */
+	0x0,						/* External  9: */
+	0x0,						/* External 10: */
+#if defined(CONFIG_85xx_PCI2) && defined(CONFIG_PCI)
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 11: PCI2 slot 0 */
+#else
+	0x0,						/* External 11: */
+#endif
+};
+
+/* ************************************************************************ */
+int
+mpc85xx_cds_show_cpuinfo(struct seq_file *m)
+{
+	uint pvid, svid, phid1;
+	uint memsize = total_memory;
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
+
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
+
+	pvid = mfspr(SPRN_PVR);
+	svid = mfspr(SPRN_SVR);
+
+	seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
+	seq_printf(m, "Machine\t\t: CDS - MPC%s (%x)\n", cur_ppc_sys_spec->ppc_sys_name, cadmus[CM_VER]);
+	seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000);
+	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+	/* Display cpu Pll setting */
+	phid1 = mfspr(SPRN_HID1);
+	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+	/* Display the amount of memory */
+	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+
+	return 0;
+}
+
+#ifdef CONFIG_CPM2
+static void cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
+{
+	while((irq = cpm2_get_irq(regs)) >= 0)
+		__do_IRQ(irq, regs);
+}
+
+static struct irqaction cpm2_irqaction = {
+	.handler = cpm2_cascade,
+	.flags = SA_INTERRUPT,
+	.mask = CPU_MASK_NONE,
+	.name = "cpm2_cascade",
+};
+#endif /* CONFIG_CPM2 */
+
+void __init
+mpc85xx_cds_init_IRQ(void)
+{
+	bd_t *binfo = (bd_t *) __res;
+
+	/* Determine the Physical Address of the OpenPIC regs */
+	phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+	OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
+	OpenPIC_InitSenses = mpc85xx_cds_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof (mpc85xx_cds_openpic_initsenses);
+
+	/* Skip reserved space and internal sources */
+	openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+	/* Map PIC IRQs 0-11 */
+	openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+
+	/* we let openpic interrupts starting from an offset, to
+	 * leave space for cascading interrupts underneath.
+	 */
+	openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
+
+#ifdef CONFIG_CPM2
+	/* Setup CPM2 PIC */
+        cpm2_init_IRQ();
+
+	setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
+#endif
+
+	return;
+}
+
+#ifdef CONFIG_PCI
+/*
+ * interrupt routing
+ */
+int
+mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+
+	if (!hose->index)
+	{
+		/* Handle PCI1 interrupts */
+		char pci_irq_table[][4] =
+			/*
+			 *      PCI IDSEL/INTPIN->INTLINE
+			 *        A      B      C      D
+			 */
+
+			/* Note IRQ assignment for slots is based on which slot the elysium is
+			 * in -- in this setup elysium is in slot #2 (this PIRQA as first
+			 * interrupt on slot */
+		{
+			{ 0, 1, 2, 3 }, /* 16 - PMC */
+			{ 3, 0, 0, 0 }, /* 17 P2P (Tsi320) */
+			{ 0, 1, 2, 3 }, /* 18 - Slot 1 */
+			{ 1, 2, 3, 0 }, /* 19 - Slot 2 */
+			{ 2, 3, 0, 1 }, /* 20 - Slot 3 */
+			{ 3, 0, 1, 2 }, /* 21 - Slot 4 */
+		};
+
+		const long min_idsel = 16, max_idsel = 21, irqs_per_slot = 4;
+		int i, j;
+
+		for (i = 0; i < 6; i++)
+			for (j = 0; j < 4; j++)
+				pci_irq_table[i][j] =
+					((pci_irq_table[i][j] + 5 -
+					  cds_pci_slot) & 0x3) + PIRQ0A;
+
+		return PCI_IRQ_TABLE_LOOKUP;
+	} else {
+		/* Handle PCI2 interrupts (if we have one) */
+		char pci_irq_table[][4] =
+		{
+			/*
+			 * We only have one slot and one interrupt
+			 * going to PIRQA - PIRQD */
+			{ PIRQ1A, PIRQ1A, PIRQ1A, PIRQ1A }, /* 21 - slot 0 */
+		};
+
+		const long min_idsel = 21, max_idsel = 21, irqs_per_slot = 4;
+
+		return PCI_IRQ_TABLE_LOOKUP;
+	}
+}
+
+#define ARCADIA_HOST_BRIDGE_IDSEL	17
+#define ARCADIA_2ND_BRIDGE_IDSEL	3
+
+extern int mpc85xx_pci1_last_busno;
+
+int
+mpc85xx_exclude_device(u_char bus, u_char devfn)
+{
+	if (bus == 0 && PCI_SLOT(devfn) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+#ifdef CONFIG_85xx_PCI2
+	if (mpc85xx_pci1_last_busno)
+		if (bus == (mpc85xx_pci1_last_busno + 1) && PCI_SLOT(devfn) == 0)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+#endif
+	/* We explicitly do not go past the Tundra 320 Bridge */
+	if (bus == 1)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	else
+		return PCIBIOS_SUCCESSFUL;
+}
+#endif /* CONFIG_PCI */
+
+TODC_ALLOC();
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init
+mpc85xx_cds_setup_arch(void)
+{
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
+	struct gianfar_platform_data *pdata;
+
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
+
+	printk("mpc85xx_cds_setup_arch\n");
+
+#ifdef CONFIG_CPM2
+	cpm2_reset();
+#endif
+
+	cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE);
+	cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1;
+	printk("CDS Version = %x in PCI slot %d\n", cadmus[CM_VER], cds_pci_slot);
+
+	/* Setup TODC access */
+	TODC_INIT(TODC_TYPE_DS1743,
+			0,
+			0,
+			ioremap(CDS_RTC_ADDR, CDS_RTC_SIZE),
+			8);
+
+	/* Set loops_per_jiffy to a half-way reasonable value,
+	   for use until calibrate_delay gets called. */
+	loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+	/* setup PCI host bridges */
+	mpc85xx_setup_hose();
+#endif
+
+#ifdef CONFIG_SERIAL_8250
+	mpc85xx_early_serial_map();
+#endif
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	/* Invalidate the entry we stole earlier the serial ports
+	 * should be properly mapped */
+	invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+#endif
+
+	/* setup the board related information for the enet controllers */
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+	pdata->phyid = 0;
+	/* fixup phy address */
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+	pdata->phyid = 1;
+	/* fixup phy address */
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef  CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+	ROOT_DEV = Root_HDA1;
+#endif
+}
+
+/* ************************************************************************ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+              unsigned long r6, unsigned long r7)
+{
+	/* parse_bootinfo must always be called first */
+	parse_bootinfo(find_bootinfo());
+
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3) {
+		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+				sizeof (bd_t));
+
+	}
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	{
+		bd_t *binfo = (bd_t *) __res;
+		struct uart_port p;
+
+		/* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
+		settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base,
+				binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
+
+		memset(&p, 0, sizeof (p));
+		p.iotype = SERIAL_IO_MEM;
+		p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET;
+		p.uartclk = binfo->bi_busfreq;
+
+		gen550_init(0, &p);
+
+		memset(&p, 0, sizeof (p));
+		p.iotype = SERIAL_IO_MEM;
+		p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET;
+		p.uartclk = binfo->bi_busfreq;
+
+		gen550_init(1, &p);
+	}
+#endif
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+	/*
+	 * If the init RAM disk has been configured in, and there's a valid
+	 * starting address for it, set it up.
+	 */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	/* Copy the kernel command line arguments to a safe place. */
+
+	if (r6) {
+		*(char *) (r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+	}
+
+	identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+	/* setup the PowerPC module struct */
+	ppc_md.setup_arch = mpc85xx_cds_setup_arch;
+	ppc_md.show_cpuinfo = mpc85xx_cds_show_cpuinfo;
+
+	ppc_md.init_IRQ = mpc85xx_cds_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+
+	ppc_md.restart = mpc85xx_restart;
+	ppc_md.power_off = mpc85xx_power_off;
+	ppc_md.halt = mpc85xx_halt;
+
+	ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
+
+	ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+	ppc_md.progress = gen550_progress;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc85xx_cds_init(): exit", 0);
+
+	return;
+}
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
new file mode 100644
index 0000000..7627d77
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
@@ -0,0 +1,80 @@
+/*
+ * arch/ppc/platforms/85xx/mpc85xx_cds_common.h
+ *
+ * MPC85xx CDS board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor, 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.
+ *
+ */
+
+#ifndef __MACH_MPC85XX_CDS_H__
+#define __MACH_MPC85XX_CDS_H__
+
+#include <linux/config.h>
+#include <linux/serial.h>
+#include <asm/ppcboot.h>
+#include <linux/initrd.h>
+#include <syslib/ppc85xx_setup.h>
+
+#define BOARD_CCSRBAR           ((uint)0xe0000000)
+#define CCSRBAR_SIZE            ((uint)1024*1024)
+
+/* CADMUS info */
+#define CADMUS_BASE (0xf8004000)
+#define CADMUS_SIZE (256)
+#define CM_VER	(0)
+#define CM_CSR	(1)
+#define CM_RST	(2)
+
+/* CDS NVRAM/RTC */
+#define CDS_RTC_ADDR	(0xf8000000)
+#define CDS_RTC_SIZE	(8 * 1024)
+
+/* PCI config */
+#define PCI1_CFG_ADDR_OFFSET	(0x8000)
+#define PCI1_CFG_DATA_OFFSET	(0x8004)
+
+#define PCI2_CFG_ADDR_OFFSET	(0x9000)
+#define PCI2_CFG_DATA_OFFSET	(0x9004)
+
+/* PCI interrupt controller */
+#define PIRQ0A                   MPC85xx_IRQ_EXT0
+#define PIRQ0B                   MPC85xx_IRQ_EXT1
+#define PIRQ0C                   MPC85xx_IRQ_EXT2
+#define PIRQ0D                   MPC85xx_IRQ_EXT3
+#define PIRQ1A                   MPC85xx_IRQ_EXT11
+
+/* PCI 1 memory map */
+#define MPC85XX_PCI1_LOWER_IO        0x00000000
+#define MPC85XX_PCI1_UPPER_IO        0x00ffffff
+
+#define MPC85XX_PCI1_LOWER_MEM       0x80000000
+#define MPC85XX_PCI1_UPPER_MEM       0x9fffffff
+
+#define MPC85XX_PCI1_IO_BASE         0xe2000000
+#define MPC85XX_PCI1_MEM_OFFSET      0x00000000
+
+#define MPC85XX_PCI1_IO_SIZE         0x01000000
+
+/* PCI 2 memory map */
+/* Note: the standard PPC fixups will cause IO space to get bumped by
+ * hose->io_base_virt - isa_io_base => MPC85XX_PCI1_IO_SIZE */
+#define MPC85XX_PCI2_LOWER_IO        0x00000000
+#define MPC85XX_PCI2_UPPER_IO        0x00ffffff
+
+#define MPC85XX_PCI2_LOWER_MEM       0xa0000000
+#define MPC85XX_PCI2_UPPER_MEM       0xbfffffff
+
+#define MPC85XX_PCI2_IO_BASE         0xe3000000
+#define MPC85XX_PCI2_MEM_OFFSET      0x00000000
+
+#define MPC85XX_PCI2_IO_SIZE         0x01000000
+
+#endif /* __MACH_MPC85XX_CDS_H__ */
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
new file mode 100644
index 0000000..9ab05e5
--- /dev/null
+++ b/arch/ppc/platforms/85xx/sbc8560.c
@@ -0,0 +1,227 @@
+/*
+ * arch/ppc/platforms/85xx/sbc8560.c
+ * 
+ * Wind River SBC8560 board specific routines
+ * 
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>	/* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/kgdb.h>
+#include <asm/ppc_sys.h>
+#include <mm/mmu_decl.h>
+
+#include <syslib/ppc85xx_common.h>
+#include <syslib/ppc85xx_setup.h>
+
+#ifdef CONFIG_SERIAL_8250
+static void __init
+sbc8560_early_serial_map(void)
+{
+        struct uart_port uart_req;
+ 
+        /* Setup serial port access */
+        memset(&uart_req, 0, sizeof (uart_req));
+	uart_req.irq = MPC85xx_IRQ_EXT9;
+	uart_req.flags = STD_COM_FLAGS;
+	uart_req.uartclk = BASE_BAUD * 16;
+        uart_req.iotype = SERIAL_IO_MEM;
+        uart_req.mapbase = UARTA_ADDR;
+        uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART0_SIZE);
+	uart_req.type = PORT_16650;
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+        gen550_init(0, &uart_req);
+#endif
+ 
+        if (early_serial_setup(&uart_req) != 0)
+                printk("Early serial init of port 0 failed\n");
+ 
+        /* Assume early_serial_setup() doesn't modify uart_req */
+	uart_req.line = 1;
+        uart_req.mapbase = UARTB_ADDR;
+        uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART1_SIZE);
+	uart_req.irq = MPC85xx_IRQ_EXT10;
+ 
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+        gen550_init(1, &uart_req);
+#endif
+ 
+        if (early_serial_setup(&uart_req) != 0)
+                printk("Early serial init of port 1 failed\n");
+}
+#endif
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init
+sbc8560_setup_arch(void)
+{
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
+	struct gianfar_platform_data *pdata;
+
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
+
+	if (ppc_md.progress)
+		ppc_md.progress("sbc8560_setup_arch()", 0);
+
+	/* Set loops_per_jiffy to a half-way reasonable value,
+	   for use until calibrate_delay gets called. */
+	loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+	/* setup PCI host bridges */
+	mpc85xx_setup_hose();
+#endif
+#ifdef CONFIG_SERIAL_8250
+	sbc8560_early_serial_map();
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	/* Invalidate the entry we stole earlier the serial ports
+	 * should be properly mapped */ 
+	invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+#endif
+
+	/* setup the board related information for the enet controllers */
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+	pdata->interruptPHY = MPC85xx_IRQ_EXT6;
+	pdata->phyid = 25;
+	/* fixup phy address */
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+	pdata->interruptPHY = MPC85xx_IRQ_EXT7;
+	pdata->phyid = 26;
+	/* fixup phy address */
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef  CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+}
+
+/* ************************************************************************ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	/* parse_bootinfo must always be called first */
+	parse_bootinfo(find_bootinfo());
+
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3) {
+		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+		       sizeof (bd_t));
+	}
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	/* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
+	settlbcam(NUM_TLBCAMS - 1, UARTA_ADDR,
+		  UARTA_ADDR, 0x1000, _PAGE_IO, 0);
+#endif
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+	/*
+	 * If the init RAM disk has been configured in, and there's a valid
+	 * starting address for it, set it up.
+	 */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif				/* CONFIG_BLK_DEV_INITRD */
+
+	/* Copy the kernel command line arguments to a safe place. */
+
+	if (r6) {
+		*(char *) (r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+	}
+
+	identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+	/* setup the PowerPC module struct */
+	ppc_md.setup_arch = sbc8560_setup_arch;
+	ppc_md.show_cpuinfo = sbc8560_show_cpuinfo;
+
+	ppc_md.init_IRQ = sbc8560_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+
+	ppc_md.restart = mpc85xx_restart;
+	ppc_md.power_off = mpc85xx_power_off;
+	ppc_md.halt = mpc85xx_halt;
+
+	ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
+
+	ppc_md.time_init = NULL;
+	ppc_md.set_rtc_time = NULL;
+	ppc_md.get_rtc_time = NULL;
+	ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+	ppc_md.progress = gen550_progress;
+#endif	/* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+
+	if (ppc_md.progress)
+		ppc_md.progress("sbc8560_init(): exit", 0);
+}
diff --git a/arch/ppc/platforms/85xx/sbc8560.h b/arch/ppc/platforms/85xx/sbc8560.h
new file mode 100644
index 0000000..5e1b00c
--- /dev/null
+++ b/arch/ppc/platforms/85xx/sbc8560.h
@@ -0,0 +1,49 @@
+/*
+ * arch/ppc/platforms/85xx/sbc8560.h
+ *
+ * Wind River SBC8560 board definitions
+ *
+ * Copyright 2003 Motorola 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.
+ *
+ */
+ 
+#ifndef __MACH_SBC8560_H__
+#define __MACH_SBC8560_H__
+ 
+#include <linux/config.h>
+#include <platforms/85xx/sbc85xx.h>
+
+#define CPM_MAP_ADDR    (CCSRBAR + MPC85xx_CPM_OFFSET)
+ 
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE  64
+#else
+#define RS_TABLE_SIZE  2
+#endif
+ 
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD ( 1843200 / 16 )
+ 
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_SKIP_TEST)
+#endif
+
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, UARTA_ADDR, MPC85xx_IRQ_EXT9, STD_COM_FLAGS, /* ttyS0 */ \
+                iomem_base: (u8 *)UARTA_ADDR,                       \
+                io_type: SERIAL_IO_MEM },                                 \
+        { 0, BASE_BAUD, UARTB_ADDR, MPC85xx_IRQ_EXT10, STD_COM_FLAGS, /* ttyS1 */ \
+                iomem_base: (u8 *)UARTB_ADDR,                       \
+                io_type: SERIAL_IO_MEM },
+ 
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
+ 
+#endif /* __MACH_SBC8560_H__ */
diff --git a/arch/ppc/platforms/85xx/sbc85xx.c b/arch/ppc/platforms/85xx/sbc85xx.c
new file mode 100644
index 0000000..2d638c1
--- /dev/null
+++ b/arch/ppc/platforms/85xx/sbc85xx.c
@@ -0,0 +1,203 @@
+/*
+ * arch/ppc/platform/85xx/sbc85xx.c
+ * 
+ * WindRiver PowerQUICC III SBC85xx board common routines
+ *
+ * Copyright 2002, 2003 Motorola Inc.
+ * Copyright 2004 Red Hat, 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/ppc_sys.h>
+
+#include <mm/mmu_decl.h>
+
+#include <platforms/85xx/sbc85xx.h>
+
+unsigned char __res[sizeof (bd_t)];
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+unsigned long pci_dram_offset = 0;
+#endif
+
+extern unsigned long total_memory;	/* in mm/init */
+
+/* Internal interrupts are all Level Sensitive, and Positive Polarity */
+
+static u_char sbc8560_openpic_initsenses[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: L2 Cache */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: ECM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  2: DDR DRAM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  3: LBIU */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  4: DMA 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  5: DMA 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  6: DMA 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  7: DMA 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  8: PCI/PCI-X */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: RIO Inbound Port Write Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10: RIO Doorbell Inbound */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11: RIO Outbound Message */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: RIO Inbound Message */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 0 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 0 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 0 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 1 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 1 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 1 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Fast Ethernet */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 27: I2C */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 28: Performance Monitor */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 29: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 30: CPM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
+	0x0,				/* External  0: */
+	0x0,				/* External  1: */
+#if defined(CONFIG_PCI)
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 2: PCI slot 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 3: PCI slot 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 4: PCI slot 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 5: PCI slot 3 */
+#else
+	0x0,				/* External  2: */
+	0x0,				/* External  3: */
+	0x0,				/* External  4: */
+	0x0,				/* External  5: */
+#endif
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 6: PHY */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 7: PHY */
+	0x0,				/* External  8: */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* External 9: PHY */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* External 10: PHY */
+	0x0,				/* External 11: */
+};
+
+/* ************************************************************************ */
+int
+sbc8560_show_cpuinfo(struct seq_file *m)
+{
+	uint pvid, svid, phid1;
+	uint memsize = total_memory;
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
+
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
+
+	pvid = mfspr(SPRN_PVR);
+	svid = mfspr(SPRN_SVR);
+
+	seq_printf(m, "Vendor\t\t: Wind River\n");
+	seq_printf(m, "Machine\t\t: SBC%s\n", cur_ppc_sys_spec->ppc_sys_name);
+	seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000);
+	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+	/* Display cpu Pll setting */
+	phid1 = mfspr(SPRN_HID1);
+	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+	/* Display the amount of memory */
+	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+
+	return 0;
+}
+
+void __init
+sbc8560_init_IRQ(void)
+{
+	bd_t *binfo = (bd_t *) __res;
+	/* Determine the Physical Address of the OpenPIC regs */
+	phys_addr_t OpenPIC_PAddr =
+	    binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+	OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
+	OpenPIC_InitSenses = sbc8560_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof (sbc8560_openpic_initsenses);
+
+	/* Skip reserved space and internal sources */
+	openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+	/* Map PIC IRQs 0-11 */
+	openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+
+	/* we let openpic interrupts starting from an offset, to 
+	 * leave space for cascading interrupts underneath.
+	 */
+	openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
+
+	return;
+}
+
+/*
+ * interrupt routing
+ */
+
+#ifdef CONFIG_PCI
+int mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel,
+		    unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	    /*
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *        A      B      C      D
+	     */
+	{
+		{PIRQA, PIRQB, PIRQC, PIRQD},
+		{PIRQD, PIRQA, PIRQB, PIRQC},
+		{PIRQC, PIRQD, PIRQA, PIRQB},
+		{PIRQB, PIRQC, PIRQD, PIRQA},
+	};
+
+	const long min_idsel = 12, max_idsel = 15, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+int mpc85xx_exclude_device(u_char bus, u_char devfn)
+{
+	if (bus == 0 && PCI_SLOT(devfn) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	else
+		return PCIBIOS_SUCCESSFUL;
+}
+#endif /* CONFIG_PCI */
diff --git a/arch/ppc/platforms/85xx/sbc85xx.h b/arch/ppc/platforms/85xx/sbc85xx.h
new file mode 100644
index 0000000..7af93c6
--- /dev/null
+++ b/arch/ppc/platforms/85xx/sbc85xx.h
@@ -0,0 +1,55 @@
+/*
+ * arch/ppc/platforms/85xx/sbc85xx.h
+ *
+ * WindRiver PowerQUICC III SBC85xx common board definitions
+ *
+ * Copyright 2003 Motorola Inc.
+ * Copyright 2004 Red Hat, 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.
+ *
+ */
+
+#ifndef __PLATFORMS_85XX_SBC85XX_H__
+#define __PLATFORMS_85XX_SBC85XX_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <asm/ppcboot.h>
+
+#define BOARD_CCSRBAR		((uint)0xff700000)
+#define CCSRBAR_SIZE		((uint)1024*1024)
+
+#define BCSR_ADDR		((uint)0xfc000000)
+#define BCSR_SIZE		((uint)(16 * 1024 * 1024))
+
+#define UARTA_ADDR		(BCSR_ADDR + 0x00700000)
+#define UARTB_ADDR		(BCSR_ADDR + 0x00800000)
+#define RTC_DEVICE_ADDR		(BCSR_ADDR + 0x00900000)
+#define EEPROM_ADDR		(BCSR_ADDR + 0x00b00000)
+
+extern int  sbc8560_show_cpuinfo(struct seq_file *m);
+extern void sbc8560_init_IRQ(void) __init; 
+
+/* PCI interrupt controller */
+#define PIRQA		MPC85xx_IRQ_EXT1
+#define PIRQB		MPC85xx_IRQ_EXT2
+#define PIRQC		MPC85xx_IRQ_EXT3
+#define PIRQD		MPC85xx_IRQ_EXT4
+
+#define MPC85XX_PCI1_LOWER_IO	0x00000000
+#define MPC85XX_PCI1_UPPER_IO	0x00ffffff
+
+#define MPC85XX_PCI1_LOWER_MEM	0x80000000
+#define MPC85XX_PCI1_UPPER_MEM	0x9fffffff
+
+#define MPC85XX_PCI1_IO_BASE	0xe2000000
+#define MPC85XX_PCI1_MEM_OFFSET	0x00000000
+
+#define MPC85XX_PCI1_IO_SIZE	0x01000000
+
+#endif /* __PLATFORMS_85XX_SBC85XX_H__ */
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
new file mode 100644
index 0000000..bc95836
--- /dev/null
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -0,0 +1,355 @@
+/*
+ * arch/ppc/platforms/85xx/stx_gp3.c
+ *
+ * STx GP3 board specific routines
+ *
+ * Dan Malek <dan@embeddededge.com>
+ * Copyright 2004 Embedded Edge, LLC
+ *
+ * Copied from mpc8560_ads.c
+ * Copyright 2002, 2003 Motorola Inc.
+ *
+ * Ported to 2.6, Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2004-2005 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/root_dev.h>
+#include <linux/seq_file.h>
+#include <linux/serial.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/immap_cpm2.h>
+#include <asm/mpc85xx.h>
+#include <asm/ppc_sys.h>
+
+#include <syslib/cpm2_pic.h>
+#include <syslib/ppc85xx_common.h>
+
+extern void cpm2_reset(void);
+
+unsigned char __res[sizeof(bd_t)];
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+unsigned long pci_dram_offset = 0;
+#endif
+
+/* Internal interrupts are all Level Sensitive, and Positive Polarity */
+static u8 gp3_openpic_initsenses[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: L2 Cache */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: ECM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  2: DDR DRAM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  3: LBIU */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  4: DMA 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  5: DMA 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  6: DMA 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  7: DMA 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  8: PCI/PCI-X */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: RIO Inbound Port Write Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10: RIO Doorbell Inbound */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11: RIO Outbound Message */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: RIO Inbound Message */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 0 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 0 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 0 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 1 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 1 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 1 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Fast Ethernet */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 27: I2C */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 28: Performance Monitor */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 29: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 30: CPM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
+	0x0,						/* External  0: */
+#if defined(CONFIG_PCI)
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 1: PCI slot 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 2: PCI slot 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 3: PCI slot 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 4: PCI slot 3 */
+#else
+	0x0,				/* External  1: */
+	0x0,				/* External  2: */
+	0x0,				/* External  3: */
+	0x0,				/* External  4: */
+#endif
+	0x0,				/* External  5: */
+	0x0,				/* External  6: */
+	0x0,				/* External  7: */
+	0x0,				/* External  8: */
+	0x0,				/* External  9: */
+	0x0,				/* External 10: */
+	0x0,				/* External 11: */
+};
+
+/*
+ * Setup the architecture
+ */
+static void __init
+gp3_setup_arch(void)
+{
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
+	struct gianfar_platform_data *pdata;
+
+	cpm2_reset();
+
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
+
+	if (ppc_md.progress)
+		ppc_md.progress("gp3_setup_arch()", 0);
+
+	/* Set loops_per_jiffy to a half-way reasonable value,
+	   for use until calibrate_delay gets called. */
+	loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+	/* setup PCI host bridges */
+	mpc85xx_setup_hose();
+#endif
+
+	/* setup the board related information for the enet controllers */
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+/*	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
+	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+	pdata->phyid = 2;
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+/*	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
+	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+	pdata->phyid = 4;
+	/* fixup phy address */
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef	CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+
+	printk ("bi_immr_base = %8.8lx\n", binfo->bi_immr_base);
+}
+
+static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
+{
+	while ((irq = cpm2_get_irq(regs)) >= 0)
+		__do_IRQ(irq, regs);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction cpm2_irqaction = {
+	.handler	= cpm2_cascade,
+	.flags		= SA_INTERRUPT,
+	.mask		= CPU_MASK_NONE,
+	.name		= "cpm2_cascade",
+};
+
+static void __init
+gp3_init_IRQ(void)
+{
+	int i;
+	bd_t *binfo = (bd_t *) __res;
+
+	/*
+	 * Setup OpenPIC
+	 */
+
+	/* Determine the Physical Address of the OpenPIC regs */
+	phys_addr_t OpenPIC_PAddr =
+	    binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+	OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
+	OpenPIC_InitSenses = gp3_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof (gp3_openpic_initsenses);
+
+	/* Skip reserved space and internal sources */
+	openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+
+	/* Map PIC IRQs 0-11 */
+	openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+
+	/*
+	 * Let openpic interrupts starting from an offset, to
+	 * leave space for cascading interrupts underneath.
+	 */
+	openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
+
+	/* Setup CPM2 PIC */
+        cpm2_init_IRQ();
+
+	setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
+
+	return;
+}
+
+static int
+gp3_show_cpuinfo(struct seq_file *m)
+{
+	uint pvid, svid, phid1;
+	bd_t *binfo = (bd_t *) __res;
+	uint	memsize;
+	unsigned int freq;
+	extern unsigned long total_memory;	/* in mm/init */
+
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
+
+	pvid = mfspr(SPRN_PVR);
+	svid = mfspr(SPRN_SVR);
+
+	memsize = total_memory;
+
+	seq_printf(m, "Vendor\t\t: RPC Electronics STx \n");
+	seq_printf(m, "Machine\t\t: GP3 - MPC%s\n", cur_ppc_sys_spec->ppc_sys_name);
+	seq_printf(m, "bus freq\t: %u.%.6u MHz\n", freq / 1000000,
+		   freq % 1000000);
+	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+	/* Display cpu Pll setting */
+	phid1 = mfspr(SPRN_HID1);
+	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+	/* Display the amount of memory */
+	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+
+	return 0;
+}
+
+#ifdef CONFIG_PCI
+int mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel,
+		    unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	    /*
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *        A      B      C      D
+	     */
+	{
+		{PIRQA, PIRQB, PIRQC, PIRQD},
+		{PIRQD, PIRQA, PIRQB, PIRQC},
+		{PIRQC, PIRQD, PIRQA, PIRQB},
+		{PIRQB, PIRQC, PIRQD, PIRQA},
+	};
+
+	const long min_idsel = 12, max_idsel = 15, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+int mpc85xx_exclude_device(u_char bus, u_char devfn)
+{
+	if (bus == 0 && PCI_SLOT(devfn) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	else
+		return PCIBIOS_SUCCESSFUL;
+}
+#endif /* CONFIG_PCI */
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	/* parse_bootinfo must always be called first */
+	parse_bootinfo(find_bootinfo());
+
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3) {
+		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+		       sizeof (bd_t));
+
+	}
+#if defined(CONFIG_BLK_DEV_INITRD)
+	/*
+	 * If the init RAM disk has been configured in, and there's a valid
+	 * starting address for it, set it up.
+	 */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif				/* CONFIG_BLK_DEV_INITRD */
+
+	/* Copy the kernel command line arguments to a safe place. */
+
+	if (r6) {
+		*(char *) (r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+	}
+
+	identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+	/* setup the PowerPC module struct */
+	ppc_md.setup_arch = gp3_setup_arch;
+	ppc_md.show_cpuinfo = gp3_show_cpuinfo;
+
+	ppc_md.init_IRQ = gp3_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+
+	ppc_md.restart = mpc85xx_restart;
+	ppc_md.power_off = mpc85xx_power_off;
+	ppc_md.halt = mpc85xx_halt;
+
+	ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
+
+	ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+
+	if (ppc_md.progress)
+		ppc_md.progress("platform_init(): exit", 0);
+
+	return;
+}
diff --git a/arch/ppc/platforms/85xx/stx_gp3.h b/arch/ppc/platforms/85xx/stx_gp3.h
new file mode 100644
index 0000000..7bcc6c3
--- /dev/null
+++ b/arch/ppc/platforms/85xx/stx_gp3.h
@@ -0,0 +1,74 @@
+/*
+ * arch/ppc/platforms/stx8560_gp3.h
+ *
+ * STx GP3 board definitions
+ *
+ * Dan Malek (dan@embeddededge.com)
+ * Copyright 2004 Embedded Edge, LLC
+ *
+ * Ported to 2.6, Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2004-2005 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.
+ *
+ */
+
+#ifndef __MACH_STX_GP3_H
+#define __MACH_STX_GP3_H
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <asm/ppcboot.h>
+
+#define BOARD_CCSRBAR		((uint)0xe0000000)
+#define CCSRBAR_SIZE		((uint)1024*1024)
+
+#define CPM_MAP_ADDR		(CCSRBAR + MPC85xx_CPM_OFFSET)
+
+#define BCSR_ADDR		((uint)0xfc000000)
+#define BCSR_SIZE		((uint)(16 * 1024))
+
+#define BCSR_TSEC1_RESET	0x00000080
+#define BCSR_TSEC2_RESET	0x00000040
+#define BCSR_LED1		0x00000008
+#define BCSR_LED2		0x00000004
+#define BCSR_LED3		0x00000002
+#define BCSR_LED4		0x00000001
+
+extern void mpc85xx_setup_hose(void) __init;
+extern void mpc85xx_restart(char *cmd);
+extern void mpc85xx_power_off(void);
+extern void mpc85xx_halt(void);
+extern int mpc85xx_show_cpuinfo(struct seq_file *m);
+extern void mpc85xx_init_IRQ(void) __init;
+extern unsigned long mpc85xx_find_end_of_memory(void) __init;
+extern void mpc85xx_calibrate_decr(void) __init;
+
+#define PCI_CFG_ADDR_OFFSET	(0x8000)
+#define PCI_CFG_DATA_OFFSET	(0x8004)
+
+/* PCI interrupt controller */
+#define PIRQA		MPC85xx_IRQ_EXT1
+#define PIRQB		MPC85xx_IRQ_EXT2
+#define PIRQC		MPC85xx_IRQ_EXT3
+#define PIRQD		MPC85xx_IRQ_EXT4
+#define PCI_MIN_IDSEL	16
+#define PCI_MAX_IDSEL	19
+#define PCI_IRQ_SLOT	4
+
+#define MPC85XX_PCI1_LOWER_IO	0x00000000
+#define MPC85XX_PCI1_UPPER_IO	0x00ffffff
+
+#define MPC85XX_PCI1_LOWER_MEM	0x80000000
+#define MPC85XX_PCI1_UPPER_MEM	0x9fffffff
+
+#define MPC85XX_PCI1_IO_BASE	0xe2000000
+#define MPC85XX_PCI1_MEM_OFFSET	0x00000000
+
+#define MPC85XX_PCI1_IO_SIZE	0x01000000
+
+#endif /* __MACH_STX_GP3_H */
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
new file mode 100644
index 0000000..5488a05
--- /dev/null
+++ b/arch/ppc/platforms/Makefile
@@ -0,0 +1,53 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Extra CFLAGS so we don't have to do relative includes
+CFLAGS_pmac_setup.o	+= -Iarch/$(ARCH)/mm
+
+obj-$(CONFIG_APUS)		+= apus_setup.o
+ifeq ($(CONFIG_APUS),y)
+obj-$(CONFIG_PCI)		+= apus_pci.o
+endif
+obj-$(CONFIG_PPC_PMAC)		+= pmac_pic.o pmac_setup.o pmac_time.o \
+					pmac_feature.o pmac_pci.o pmac_sleep.o \
+					pmac_low_i2c.o pmac_cache.o
+obj-$(CONFIG_PPC_CHRP)		+= chrp_setup.o chrp_time.o chrp_pci.o \
+					chrp_pegasos_eth.o
+obj-$(CONFIG_PPC_PREP)		+= prep_pci.o prep_setup.o
+ifeq ($(CONFIG_PPC_PMAC),y)
+obj-$(CONFIG_NVRAM)		+= pmac_nvram.o
+obj-$(CONFIG_CPU_FREQ_PMAC)	+= pmac_cpufreq.o
+endif
+obj-$(CONFIG_PMAC_BACKLIGHT)	+= pmac_backlight.o
+obj-$(CONFIG_PREP_RESIDUAL)	+= residual.o
+obj-$(CONFIG_ADIR)		+= adir_setup.o adir_pic.o adir_pci.o
+obj-$(CONFIG_PQ2ADS)		+= pq2ads.o
+obj-$(CONFIG_TQM8260)		+= tqm8260_setup.o
+obj-$(CONFIG_CPCI690)		+= cpci690.o
+obj-$(CONFIG_EV64260)		+= ev64260.o
+obj-$(CONFIG_CHESTNUT)		+= chestnut.o
+obj-$(CONFIG_GEMINI)		+= gemini_pci.o gemini_setup.o gemini_prom.o
+obj-$(CONFIG_K2)		+= k2.o
+obj-$(CONFIG_LOPEC)		+= lopec.o
+obj-$(CONFIG_KATANA)		+= katana.o
+obj-$(CONFIG_HDPU)		+= hdpu.o
+obj-$(CONFIG_MCPN765)		+= mcpn765.o
+obj-$(CONFIG_MENF1)		+= menf1_setup.o menf1_pci.o
+obj-$(CONFIG_MVME5100)		+= mvme5100.o
+obj-$(CONFIG_PAL4)		+= pal4_setup.o pal4_pci.o
+obj-$(CONFIG_PCORE)		+= pcore.o
+obj-$(CONFIG_POWERPMC250)	+= powerpmc250.o
+obj-$(CONFIG_PPLUS)		+= pplus.o
+obj-$(CONFIG_PRPMC750)		+= prpmc750.o
+obj-$(CONFIG_PRPMC800)		+= prpmc800.o
+obj-$(CONFIG_RADSTONE_PPC7D)	+= radstone_ppc7d.o
+obj-$(CONFIG_SANDPOINT)		+= sandpoint.o
+obj-$(CONFIG_SBC82xx)		+= sbc82xx.o
+obj-$(CONFIG_SPRUCE)		+= spruce.o
+obj-$(CONFIG_LITE5200)		+= lite5200.o
+
+ifeq ($(CONFIG_SMP),y)
+obj-$(CONFIG_PPC_PMAC)		+= pmac_smp.o
+obj-$(CONFIG_PPC_CHRP)		+= chrp_smp.o
+endif
diff --git a/arch/ppc/platforms/adir.h b/arch/ppc/platforms/adir.h
new file mode 100644
index 0000000..13a748b
--- /dev/null
+++ b/arch/ppc/platforms/adir.h
@@ -0,0 +1,95 @@
+/*
+ * arch/ppc/platforms/adir.h
+ *
+ * Definitions for SBS Adirondack board support
+ *
+ * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
+ */
+
+#ifndef __PPC_PLATFORMS_ADIR_H
+#define __PPC_PLATFORMS_ADIR_H
+
+/*
+ * SBS Adirondack definitions
+ */
+
+/* PPC physical address space layout. We use the one set up by the firmware. */
+#define	ADIR_PCI32_MEM_BASE	0x80000000
+#define	ADIR_PCI32_MEM_SIZE	0x20000000
+#define	ADIR_PCI64_MEM_BASE	0xA0000000
+#define	ADIR_PCI64_MEM_SIZE	0x20000000
+#define	ADIR_PCI32_IO_BASE	0xC0000000
+#define	ADIR_PCI32_IO_SIZE	0x10000000
+#define	ADIR_PCI64_IO_BASE	0xD0000000
+#define	ADIR_PCI64_IO_SIZE	0x10000000
+#define	ADIR_PCI64_PHB		0xFF400000
+#define	ADIR_PCI32_PHB		0xFF500000
+
+#define ADIR_PCI64_CONFIG_ADDR	(ADIR_PCI64_PHB + 0x000f8000)
+#define ADIR_PCI64_CONFIG_DATA	(ADIR_PCI64_PHB + 0x000f8010)
+
+#define ADIR_PCI32_CONFIG_ADDR	(ADIR_PCI32_PHB + 0x000f8000)
+#define ADIR_PCI32_CONFIG_DATA	(ADIR_PCI32_PHB + 0x000f8010)
+
+/* System memory as seen from PCI */
+#define ADIR_PCI_SYS_MEM_BASE	0x80000000
+
+/* Static virtual mapping of PCI I/O */
+#define	ADIR_PCI32_VIRT_IO_BASE	0xFE000000
+#define	ADIR_PCI32_VIRT_IO_SIZE	0x01000000
+#define	ADIR_PCI64_VIRT_IO_BASE	0xFF000000
+#define	ADIR_PCI64_VIRT_IO_SIZE	0x01000000
+
+/* Registers */
+#define	ADIR_NVRAM_RTC_ADDR	0x74
+#define	ADIR_NVRAM_RTC_DATA	0x75
+
+#define	ADIR_BOARD_ID_REG	(ADIR_PCI32_VIRT_IO_BASE + 0x08FFF0)
+#define	ADIR_CPLD1REV_REG	(ADIR_PCI32_VIRT_IO_BASE + 0x08FFF1)
+#define	ADIR_CPLD2REV_REG	(ADIR_PCI32_VIRT_IO_BASE + 0x08FFF2)
+#define	ADIR_FLASHCTL_REG	(ADIR_PCI32_VIRT_IO_BASE + 0x08FFF3)
+#define	ADIR_CPC710_STAT_REG	(ADIR_PCI32_VIRT_IO_BASE + 0x08FFF4)
+#define	ADIR_CLOCK_REG		(ADIR_PCI32_VIRT_IO_BASE + 0x08FFF5)
+#define	ADIR_GPIO_REG		(ADIR_PCI32_VIRT_IO_BASE + 0x08FFF8)
+#define	ADIR_MISC_REG		(ADIR_PCI32_VIRT_IO_BASE + 0x08FFF9)
+#define	ADIR_LED_REG		(ADIR_PCI32_VIRT_IO_BASE + 0x08FFFA)
+
+#define	ADIR_CLOCK_REG_PD	0x10
+#define	ADIR_CLOCK_REG_SPREAD	0x08
+#define	ADIR_CLOCK_REG_SEL133	0x04
+#define	ADIR_CLOCK_REG_SEL1	0x02
+#define	ADIR_CLOCK_REG_SEL0	0x01
+
+#define	ADIR_PROCA_INT_MASK	(ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF0)
+#define	ADIR_PROCB_INT_MASK	(ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF2)
+#define	ADIR_PROCA_INT_STAT	(ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF4)
+#define	ADIR_PROCB_INT_STAT	(ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF6)
+
+/* Linux IRQ numbers */
+#define	ADIR_IRQ_NONE		-1
+#define	ADIR_IRQ_SERIAL2	3
+#define	ADIR_IRQ_SERIAL1	4
+#define	ADIR_IRQ_FDC		6
+#define	ADIR_IRQ_PARALLEL	7
+#define	ADIR_IRQ_VIA_AUDIO	10
+#define	ADIR_IRQ_VIA_USB	11
+#define	ADIR_IRQ_IDE0		14
+#define	ADIR_IRQ_IDE1		15
+#define	ADIR_IRQ_PCI0_INTA	16
+#define	ADIR_IRQ_PCI0_INTB	17
+#define	ADIR_IRQ_PCI0_INTC	18
+#define	ADIR_IRQ_PCI0_INTD	19
+#define	ADIR_IRQ_PCI1_INTA	20
+#define	ADIR_IRQ_PCI1_INTB	21
+#define	ADIR_IRQ_PCI1_INTC	22
+#define	ADIR_IRQ_PCI1_INTD	23
+#define	ADIR_IRQ_MBSCSI		24	/* motherboard SCSI */
+#define	ADIR_IRQ_MBETH1		25	/* motherboard Ethernet 1 */
+#define	ADIR_IRQ_MBETH0		26	/* motherboard Ethernet 0 */
+#define	ADIR_IRQ_CPC710_INT1	27
+#define	ADIR_IRQ_CPC710_INT2	28
+#define	ADIR_IRQ_VT82C686_NMI	29
+#define	ADIR_IRQ_VT82C686_INTR	30
+#define	ADIR_IRQ_INTERPROC	31
+
+#endif /* __PPC_PLATFORMS_ADIR_H */
diff --git a/arch/ppc/platforms/adir_pci.c b/arch/ppc/platforms/adir_pci.c
new file mode 100644
index 0000000..f94ac53
--- /dev/null
+++ b/arch/ppc/platforms/adir_pci.c
@@ -0,0 +1,247 @@
+/*
+ * arch/ppc/platforms/adir_pci.c
+ *
+ * PCI support for SBS Adirondack
+ *
+ * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
+ * based on the K2 version by Matt Porter <mporter@mvista.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+
+#include <syslib/cpc710.h>
+#include "adir.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* DEBUG */
+
+static inline int __init
+adir_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+#define	PCIIRQ(a,b,c,d)	{ADIR_IRQ_##a,ADIR_IRQ_##b,ADIR_IRQ_##c,ADIR_IRQ_##d},
+	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+	/*
+	 * The three PCI devices on the motherboard have dedicated lines to the
+	 * CPLD interrupt controller, bypassing the standard PCI INTA-D and the
+	 * PC interrupt controller. All other PCI devices (slots) have usual
+	 * staggered INTA-D lines, resulting in 8 lines total (PCI0 INTA-D and
+	 * PCI1 INTA-D). All 8 go to the CPLD interrupt controller. PCI0 INTA-D
+	 * also go to the south bridge, so we have the option of taking them
+	 * via the CPLD interrupt controller or via the south bridge 8259
+	 * 8258 thingy. PCI1 INTA-D can only be taken via the CPLD interrupt
+	 * controller. We take all PCI interrupts via the CPLD interrupt
+	 * controller as recommended by SBS.
+	 *
+	 * We also have some monkey business with the PCI devices within the
+	 * VT82C686B south bridge itself. This chip actually has 7 functions on
+	 * its IDSEL. Function 0 is the actual south bridge, function 1 is IDE,
+	 * and function 4 is some special stuff. The other 4 functions are just
+	 * regular PCI devices bundled in the chip. 2 and 3 are USB UHCIs and 5
+	 * and 6 are audio (not supported on the Adirondack).
+	 *
+	 * This is where the monkey business begins. PCI devices are supposed
+	 * to signal normal PCI interrupts. But the 4 functions in question are
+	 * located in the south bridge chip, which is designed with the
+	 * assumption that it will be fielding PCI INTA-D interrupts rather
+	 * than generating them. Here's what it does. Each of the functions in
+	 * question routes its interrupt to one of the IRQs on the 8259 thingy.
+	 * Which one? It looks at the Interrupt Line register in the PCI config
+	 * space, even though the PCI spec says it's for BIOS/OS interaction
+	 * only.
+	 *
+	 * How do we deal with this? We take these interrupts via 8259 IRQs as
+	 * we have to. We return the desired IRQ numbers from this routine when
+	 * called for the functions in question. The PCI scan code will then
+	 * stick our return value into the Interrupt Line register in the PCI
+	 * config space, and the interrupt will actually go there. We identify
+	 * these functions within the south bridge IDSEL by their interrupt pin
+	 * numbers, as the VT82C686B has 04 in the Interrupt Pin register for
+	 * USB and 03 for audio.
+	 */
+	if (!hose->index) {
+		static char pci_irq_table[][4] =
+		/*
+		 *             PCI IDSEL/INTPIN->INTLINE
+		 *             A          B          C          D
+		 */
+		{
+    /* south bridge */	PCIIRQ(IDE0,      NONE,      VIA_AUDIO, VIA_USB)
+    /* Ethernet 0 */	PCIIRQ(MBETH0,    MBETH0,    MBETH0,    MBETH0)
+    /* PCI0 slot 1 */	PCIIRQ(PCI0_INTB, PCI0_INTC, PCI0_INTD, PCI0_INTA)
+    /* PCI0 slot 2 */	PCIIRQ(PCI0_INTC, PCI0_INTD, PCI0_INTA, PCI0_INTB)
+    /* PCI0 slot 3 */	PCIIRQ(PCI0_INTD, PCI0_INTA, PCI0_INTB, PCI0_INTC)
+		};
+		const long min_idsel = 3, max_idsel = 7, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	} else {
+		static char pci_irq_table[][4] =
+		/*
+		 *             PCI IDSEL/INTPIN->INTLINE
+		 *             A          B          C          D
+		 */
+		{
+    /* Ethernet 1 */	PCIIRQ(MBETH1,    MBETH1,    MBETH1,    MBETH1)
+    /* SCSI */		PCIIRQ(MBSCSI,    MBSCSI,    MBSCSI,    MBSCSI)
+    /* PCI1 slot 1 */	PCIIRQ(PCI1_INTB, PCI1_INTC, PCI1_INTD, PCI1_INTA)
+    /* PCI1 slot 2 */	PCIIRQ(PCI1_INTC, PCI1_INTD, PCI1_INTA, PCI1_INTB)
+    /* PCI1 slot 3 */	PCIIRQ(PCI1_INTD, PCI1_INTA, PCI1_INTB, PCI1_INTC)
+		};
+		const long min_idsel = 3, max_idsel = 7, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	}
+#undef PCIIRQ
+}
+
+static void
+adir_pcibios_fixup_resources(struct pci_dev *dev)
+{
+	int i;
+
+	if ((dev->vendor == PCI_VENDOR_ID_IBM) &&
+			(dev->device == PCI_DEVICE_ID_IBM_CPC710_PCI64))
+	{
+		DBG("Fixup CPC710 resources\n");
+		for (i=0; i<DEVICE_COUNT_RESOURCE; i++)
+		{
+			dev->resource[i].start = 0;
+			dev->resource[i].end = 0;
+		}
+	}
+}
+
+/*
+ * CPC710 DD3 has an errata causing it to hang the system if a type 0 config
+ * cycle is attempted on its PCI32 interface with a device number > 21.
+ * CPC710's PCI bridges map device numbers 1 through 21 to AD11 through AD31.
+ * Per the PCI spec it MUST accept all other device numbers and do nothing, and
+ * software MUST scan all device numbers without assuming how IDSELs are
+ * mapped. However, as the CPC710 DD3's errata causes such correct scanning
+ * procedure to hang the system, we have no choice but to introduce this hack
+ * of knowingly avoiding device numbers > 21 on PCI0,
+ */
+static int
+adir_exclude_device(u_char bus, u_char devfn)
+{
+	if ((bus == 0) && (PCI_SLOT(devfn) > 21))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	else
+		return PCIBIOS_SUCCESSFUL;
+}
+
+void adir_find_bridges(void)
+{
+	struct pci_controller *hose_a, *hose_b;
+
+	/* Setup PCI32 hose */
+	hose_a = pcibios_alloc_controller();
+	if (!hose_a)
+		return;
+
+	hose_a->first_busno = 0;
+	hose_a->last_busno = 0xff;
+	hose_a->pci_mem_offset = ADIR_PCI32_MEM_BASE;
+	hose_a->io_space.start = 0;
+	hose_a->io_space.end = ADIR_PCI32_VIRT_IO_SIZE - 1;
+	hose_a->mem_space.start = 0;
+	hose_a->mem_space.end = ADIR_PCI32_MEM_SIZE - 1;
+	hose_a->io_resource.start = 0;
+	hose_a->io_resource.end = ADIR_PCI32_VIRT_IO_SIZE - 1;
+	hose_a->io_resource.flags = IORESOURCE_IO;
+	hose_a->mem_resources[0].start = ADIR_PCI32_MEM_BASE;
+	hose_a->mem_resources[0].end = ADIR_PCI32_MEM_BASE +
+					ADIR_PCI32_MEM_SIZE - 1;
+	hose_a->mem_resources[0].flags = IORESOURCE_MEM;
+	hose_a->io_base_phys = ADIR_PCI32_IO_BASE;
+	hose_a->io_base_virt = (void *) ADIR_PCI32_VIRT_IO_BASE;
+
+	ppc_md.pci_exclude_device = adir_exclude_device;
+	setup_indirect_pci(hose_a, ADIR_PCI32_CONFIG_ADDR,
+			   ADIR_PCI32_CONFIG_DATA);
+
+	/* Initialize PCI32 bus registers */
+	early_write_config_byte(hose_a,
+			hose_a->first_busno,
+			PCI_DEVFN(0, 0),
+			CPC710_BUS_NUMBER,
+			hose_a->first_busno);
+	early_write_config_byte(hose_a,
+			hose_a->first_busno,
+			PCI_DEVFN(0, 0),
+			CPC710_SUB_BUS_NUMBER,
+			hose_a->last_busno);
+
+	hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
+
+	/* Write out correct max subordinate bus number for hose A */
+	early_write_config_byte(hose_a,
+			hose_a->first_busno,
+			PCI_DEVFN(0, 0),
+			CPC710_SUB_BUS_NUMBER,
+			hose_a->last_busno);
+
+	/* Setup PCI64 hose */
+	hose_b = pcibios_alloc_controller();
+	if (!hose_b)
+		return;
+
+	hose_b->first_busno = hose_a->last_busno + 1;
+	hose_b->last_busno = 0xff;
+	hose_b->pci_mem_offset = ADIR_PCI64_MEM_BASE;
+	hose_b->io_space.start = 0;
+	hose_b->io_space.end = ADIR_PCI64_VIRT_IO_SIZE - 1;
+	hose_b->mem_space.start = 0;
+	hose_b->mem_space.end = ADIR_PCI64_MEM_SIZE - 1;
+	hose_b->io_resource.start = 0;
+	hose_b->io_resource.end = ADIR_PCI64_VIRT_IO_SIZE - 1;
+	hose_b->io_resource.flags = IORESOURCE_IO;
+	hose_b->mem_resources[0].start = ADIR_PCI64_MEM_BASE;
+	hose_b->mem_resources[0].end = ADIR_PCI64_MEM_BASE +
+					ADIR_PCI64_MEM_SIZE - 1;
+	hose_b->mem_resources[0].flags = IORESOURCE_MEM;
+	hose_b->io_base_phys = ADIR_PCI64_IO_BASE;
+	hose_b->io_base_virt = (void *) ADIR_PCI64_VIRT_IO_BASE;
+
+	setup_indirect_pci(hose_b, ADIR_PCI64_CONFIG_ADDR,
+			   ADIR_PCI64_CONFIG_DATA);
+
+	/* Initialize PCI64 bus registers */
+	early_write_config_byte(hose_b,
+			0,
+			PCI_DEVFN(0, 0),
+			CPC710_SUB_BUS_NUMBER,
+			0xff);
+
+	early_write_config_byte(hose_b,
+			0,
+			PCI_DEVFN(0, 0),
+			CPC710_BUS_NUMBER,
+			hose_b->first_busno);
+
+	hose_b->last_busno = pciauto_bus_scan(hose_b,
+			hose_b->first_busno);
+
+	/* Write out correct max subordinate bus number for hose B */
+	early_write_config_byte(hose_b,
+			hose_b->first_busno,
+			PCI_DEVFN(0, 0),
+			CPC710_SUB_BUS_NUMBER,
+			hose_b->last_busno);
+
+	ppc_md.pcibios_fixup = NULL;
+	ppc_md.pcibios_fixup_resources = adir_pcibios_fixup_resources;
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = adir_map_irq;
+}
diff --git a/arch/ppc/platforms/adir_pic.c b/arch/ppc/platforms/adir_pic.c
new file mode 100644
index 0000000..9947cba
--- /dev/null
+++ b/arch/ppc/platforms/adir_pic.c
@@ -0,0 +1,130 @@
+/*
+ * arch/ppc/platforms/adir_pic.c
+ *
+ * Interrupt controller support for SBS Adirondack
+ *
+ * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
+ * based on the K2 and SCM versions by Matt Porter <mporter@mvista.com>
+ */
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/i8259.h>
+#include "adir.h"
+
+static void adir_onboard_pic_enable(unsigned int irq);
+static void adir_onboard_pic_disable(unsigned int irq);
+
+__init static void
+adir_onboard_pic_init(void)
+{
+	volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
+
+	/* Disable all Adirondack onboard interrupts */
+	out_be16(maskreg, 0xFFFF);
+}
+
+static int
+adir_onboard_pic_get_irq(void)
+{
+	volatile u_short *statreg = (volatile u_short *) ADIR_PROCA_INT_STAT;
+	int irq;
+	u_short int_status, int_test;
+
+	int_status = in_be16(statreg);
+	for (irq = 0, int_test = 1; irq < 16; irq++, int_test <<= 1) {
+		if (int_status & int_test)
+			break;
+	}
+
+	if (irq == 16)
+		return -1;
+
+	return (irq+16);
+}
+
+static void
+adir_onboard_pic_enable(unsigned int irq)
+{
+	volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
+
+	/* Change irq to Adirondack onboard native value */
+	irq -= 16;
+
+	/* Enable requested irq number */
+	out_be16(maskreg, in_be16(maskreg) & ~(1 << irq));
+}
+
+static void
+adir_onboard_pic_disable(unsigned int irq)
+{
+	volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
+
+	/* Change irq to Adirondack onboard native value */
+	irq -= 16;
+
+	/* Disable requested irq number */
+	out_be16(maskreg, in_be16(maskreg) | (1 << irq));
+}
+
+static struct hw_interrupt_type adir_onboard_pic = {
+	" ADIR PIC ",
+	NULL,
+	NULL,
+	adir_onboard_pic_enable,		/* unmask */
+	adir_onboard_pic_disable,		/* mask */
+	adir_onboard_pic_disable,		/* mask and ack */
+	NULL,
+	NULL
+};
+
+static struct irqaction noop_action = {
+	.handler	= no_action,
+	.flags          = SA_INTERRUPT,
+	.mask           = CPU_MASK_NONE,
+	.name           = "82c59 primary cascade",
+};
+
+/*
+ * Linux interrupt values are assigned as follows:
+ *
+ * 	0-15		VT82C686 8259 interrupts
+ * 	16-31		Adirondack CPLD interrupts
+ */
+__init void
+adir_init_IRQ(void)
+{
+	int	i;
+
+	/* Initialize the cascaded 8259's on the VT82C686 */
+	for (i=0; i<16; i++)
+		irq_desc[i].handler = &i8259_pic;
+	i8259_init(NULL);
+
+	/* Initialize Adirondack CPLD PIC and enable 8259 interrupt cascade */
+	for (i=16; i<32; i++)
+		irq_desc[i].handler = &adir_onboard_pic;
+	adir_onboard_pic_init();
+
+	/* Enable 8259 interrupt cascade */
+	setup_irq(ADIR_IRQ_VT82C686_INTR, &noop_action);
+}
+
+int
+adir_get_irq(struct pt_regs *regs)
+{
+	int	irq;
+
+	if ((irq = adir_onboard_pic_get_irq()) < 0)
+		return irq;
+
+	if (irq == ADIR_IRQ_VT82C686_INTR)
+		irq = i8259_irq(regs);
+
+	return irq;
+}
diff --git a/arch/ppc/platforms/adir_setup.c b/arch/ppc/platforms/adir_setup.c
new file mode 100644
index 0000000..6a6754e
--- /dev/null
+++ b/arch/ppc/platforms/adir_setup.c
@@ -0,0 +1,210 @@
+/*
+ * arch/ppc/platforms/adir_setup.c
+ *
+ * Board setup routines for SBS Adirondack
+ *
+ * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
+ * based on the K2 version by Matt Porter <mporter@mvista.com>
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+
+#include "adir.h"
+
+extern void adir_init_IRQ(void);
+extern int adir_get_irq(struct pt_regs *);
+extern void adir_find_bridges(void);
+extern unsigned long loops_per_jiffy;
+
+static unsigned int cpu_750cx[16] = {
+	5, 15, 14, 0, 4, 13, 0, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+
+static int
+adir_get_bus_speed(void)
+{
+	if (!(*((u_char *) ADIR_CLOCK_REG) & ADIR_CLOCK_REG_SEL133))
+		return 100000000;
+	else
+		return 133333333;
+}
+
+static int
+adir_get_cpu_speed(void)
+{
+	unsigned long hid1;
+	int cpu_speed;
+
+	hid1 = mfspr(SPRN_HID1) >> 28;
+
+	hid1 = cpu_750cx[hid1];
+
+	cpu_speed = adir_get_bus_speed()*hid1/2;
+	return cpu_speed;
+}
+
+static void __init
+adir_calibrate_decr(void)
+{
+	int freq, divisor = 4;
+
+	/* determine processor bus speed */
+	freq = adir_get_bus_speed();
+	tb_ticks_per_jiffy = freq / HZ / divisor;
+	tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+}
+
+static int
+adir_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: SBS\n");
+	seq_printf(m, "machine\t\t: Adirondack\n");
+	seq_printf(m, "cpu speed\t: %dMhz\n", adir_get_cpu_speed()/1000000);
+	seq_printf(m, "bus speed\t: %dMhz\n", adir_get_bus_speed()/1000000);
+	seq_printf(m, "memory type\t: SDRAM\n");
+
+	return 0;
+}
+
+extern char cmd_line[];
+
+TODC_ALLOC();
+
+static void __init
+adir_setup_arch(void)
+{
+	unsigned int cpu;
+
+	/* Setup TODC access */
+	TODC_INIT(TODC_TYPE_MC146818, ADIR_NVRAM_RTC_ADDR, 0,
+		  ADIR_NVRAM_RTC_DATA, 8);
+
+	/* init to some ~sane value until calibrate_delay() runs */
+        loops_per_jiffy = 50000000/HZ;
+
+       /* Setup PCI host bridges */
+        adir_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA1;
+#endif
+
+	/* Identify the system */
+	printk("System Identification: SBS Adirondack - PowerPC 750CXe @ %d Mhz\n", adir_get_cpu_speed()/1000000);
+	printk("SBS Adirondack port (C) 2001 SBS Technologies, Inc.\n");
+
+	/* Identify the CPU manufacturer */
+	cpu = mfspr(SPRN_PVR);
+	printk("CPU manufacturer: IBM [rev=%04x]\n", (cpu & 0xffff));
+}
+
+static void
+adir_restart(char *cmd)
+{
+	local_irq_disable();
+	/* SRR0 has system reset vector, SRR1 has default MSR value */
+	/* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
+	__asm__ __volatile__
+	("lis	3,0xfff0\n\t"
+	 "ori	3,3,0x0100\n\t"
+	 "mtspr	26,3\n\t"
+	 "li	3,0\n\t"
+	 "mtspr	27,3\n\t"
+	 "rfi\n\t");
+	for(;;);
+}
+
+static void
+adir_power_off(void)
+{
+	for(;;);
+}
+
+static void
+adir_halt(void)
+{
+	adir_restart(NULL);
+}
+
+static unsigned long __init
+adir_find_end_of_memory(void)
+{
+	return boot_mem_size;
+}
+
+static void __init
+adir_map_io(void)
+{
+	io_block_mapping(ADIR_PCI32_VIRT_IO_BASE, ADIR_PCI32_IO_BASE,
+				ADIR_PCI32_VIRT_IO_SIZE, _PAGE_IO);
+	io_block_mapping(ADIR_PCI64_VIRT_IO_BASE, ADIR_PCI64_IO_BASE,
+				ADIR_PCI64_VIRT_IO_SIZE, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	/*
+	 * On the Adirondack we use bi_recs and pass the pointer to them in R3.
+	 */
+	parse_bootinfo((struct bi_record *) (r3 + KERNELBASE));
+
+	/* Remember, isa_io_base is virtual but isa_mem_base is physical! */
+	isa_io_base = ADIR_PCI32_VIRT_IO_BASE;
+	isa_mem_base = ADIR_PCI32_MEM_BASE;
+	pci_dram_offset = ADIR_PCI_SYS_MEM_BASE;
+
+	ppc_md.setup_arch = adir_setup_arch;
+	ppc_md.show_cpuinfo = adir_show_cpuinfo;
+	ppc_md.irq_canonicalize = NULL;
+	ppc_md.init_IRQ = adir_init_IRQ;
+	ppc_md.get_irq = adir_get_irq;
+	ppc_md.init = NULL;
+
+	ppc_md.find_end_of_memory = adir_find_end_of_memory;
+	ppc_md.setup_io_mappings = adir_map_io;
+
+	ppc_md.restart = adir_restart;
+	ppc_md.power_off = adir_power_off;
+	ppc_md.halt = adir_halt;
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.nvram_read_val = todc_mc146818_read_val;
+	ppc_md.nvram_write_val = todc_mc146818_write_val;
+	ppc_md.calibrate_decr = adir_calibrate_decr;
+}
diff --git a/arch/ppc/platforms/apus_pci.c b/arch/ppc/platforms/apus_pci.c
new file mode 100644
index 0000000..33dad6d
--- /dev/null
+++ b/arch/ppc/platforms/apus_pci.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) Michel Dänzer <michdaen@iiic.ethz.ch>
+ *
+ * APUS PCI routines.
+ *
+ * Currently, only B/CVisionPPC cards (Permedia2) are supported.
+ *
+ * Thanks to Geert Uytterhoeven for the idea:
+ * Read values from given config space(s) for the first devices, -1 otherwise
+ *
+ */
+
+#include <linux/config.h>
+#ifdef CONFIG_AMIGA
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#include "apus_pci.h"
+
+
+/* These definitions are mostly adapted from pm2fb.c */
+
+#undef APUS_PCI_MASTER_DEBUG
+#ifdef APUS_PCI_MASTER_DEBUG
+#define DPRINTK(a,b...)	printk(KERN_DEBUG "apus_pci: %s: " a, __FUNCTION__ , ## b)
+#else
+#define DPRINTK(a,b...)
+#endif
+
+/*
+ * The _DEFINITIVE_ memory mapping/unmapping functions.
+ * This is due to the fact that they're changing soooo often...
+ */
+#define DEFW()		wmb()
+#define DEFR()		rmb()
+#define DEFRW()		mb()
+
+#define DEVNO(d)	((d)>>3)
+#define FNNO(d)		((d)&7)
+
+
+extern unsigned long powerup_PCI_present;
+
+static struct pci_controller *apus_hose;
+
+
+void *pci_io_base(unsigned int bus)
+{
+	return 0;
+}
+
+
+int
+apus_pcibios_read_config(struct pci_bus *bus, int devfn, int offset,
+			 int len, u32 *val)
+{
+	int fnno = FNNO(devfn);
+	int devno = DEVNO(devfn);
+	volatile unsigned char *cfg_data;
+
+	if (bus->number > 0 || devno != 1) {
+		*val = ~0;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+	/* base address + function offset + offset ^ endianness conversion */
+	/* XXX the fnno<<5 bit seems wacky  -- paulus */
+	cfg_data = apus_hose->cfg_data + (fnno<<5) + (offset ^ (len - 1));
+	switch (len) {
+	case 1:
+		*val = readb(cfg_data);
+		break;
+	case 2:
+		*val = readw(cfg_data);
+		break;
+	default:
+		*val = readl(cfg_data);
+		break;
+	}
+
+	DPRINTK("read b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, l: %d, v: 0x%x\n",
+		bus->number, devfn>>3, devfn&7, offset, len, *val);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+apus_pcibios_write_config(struct pci_bus *bus, int devfn, int offset,
+			  int len, u32 *val)
+{
+	int fnno = FNNO(devfn);
+	int devno = DEVNO(devfn);
+	volatile unsigned char *cfg_data;
+
+	if (bus->number > 0 || devno != 1) {
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+	/* base address + function offset + offset ^ endianness conversion */
+	/* XXX the fnno<<5 bit seems wacky  -- paulus */
+	cfg_data = apus_hose->cfg_data + (fnno<<5) + (offset ^ (len - 1));
+	switch (len) {
+	case 1:
+		writeb(val, cfg_data); DEFW();
+		break;
+	case 2:
+		writew(val, cfg_data); DEFW();
+		break;
+	default:
+		writel(val, cfg_data); DEFW();
+		break;
+	}
+
+	DPRINTK("write b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, l: %d, v: 0x%x\n",
+		bus->number, devfn>>3, devfn&7, offset, len, val);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops apus_pci_ops = {
+	apus_pcibios_read_config,
+	apus_pcibios_write_config
+};
+
+static struct resource pci_mem = { "B/CVisionPPC PCI mem", CVPPC_FB_APERTURE_ONE, CVPPC_PCI_CONFIG, IORESOURCE_MEM };
+
+void __init
+apus_pcibios_fixup(void)
+{
+/*	struct pci_dev *dev = pci_find_slot(0, 1<<3);
+	unsigned int reg, val, offset;*/
+
+	/* FIXME: interrupt? */
+	/*dev->interrupt = xxx;*/
+
+        request_resource(&iomem_resource, &pci_mem);
+    	printk("%s: PCI mem resource requested\n", __FUNCTION__);
+}
+
+static void __init apus_pcibios_fixup_bus(struct pci_bus *bus)
+{
+        bus->resource[1] = &pci_mem;
+}
+
+
+/*
+ * This is from pm2fb.c again
+ *
+ * Check if PCI (B/CVisionPPC) is available, initialize it and set up
+ * the pcibios_* pointers
+ */
+
+
+void __init
+apus_setup_pci_ptrs(void)
+{
+	if (!powerup_PCI_present) {
+		DPRINTK("no PCI bridge detected\n");
+		return;
+	}
+	DPRINTK("Phase5 B/CVisionPPC PCI bridge detected.\n");
+
+	apus_hose = pcibios_alloc_controller();
+	if (!apus_hose) {
+		printk("apus_pci: Can't allocate PCI controller structure\n");
+		return;
+	}
+
+	if (!(apus_hose->cfg_data = ioremap(CVPPC_PCI_CONFIG, 256))) {
+		printk("apus_pci: unable to map PCI config region\n");
+		return;
+	}
+
+	if (!(apus_hose->cfg_addr = ioremap(CSPPC_PCI_BRIDGE, 256))) {
+		printk("apus_pci: unable to map PCI bridge\n");
+		return;
+	}
+
+	writel(CSPPCF_BRIDGE_BIG_ENDIAN, apus_hose->cfg_addr + CSPPC_BRIDGE_ENDIAN);
+	DEFW();
+
+	writel(CVPPC_REGS_REGION,  apus_hose->cfg_data+ PCI_BASE_ADDRESS_0);
+	DEFW();
+	writel(CVPPC_FB_APERTURE_ONE, apus_hose->cfg_data + PCI_BASE_ADDRESS_1);
+	DEFW();
+	writel(CVPPC_FB_APERTURE_TWO, apus_hose->cfg_data + PCI_BASE_ADDRESS_2);
+	DEFW();
+	writel(CVPPC_ROM_ADDRESS, apus_hose->cfg_data + PCI_ROM_ADDRESS);
+	DEFW();
+
+	writel(0xef000000 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+		PCI_COMMAND_MASTER, apus_hose->cfg_data + PCI_COMMAND);
+	DEFW();
+
+	apus_hose->first_busno = 0;
+	apus_hose->last_busno = 0;
+	apus_hose->ops = &apus_pci_ops;
+	ppc_md.pcibios_fixup = apus_pcibios_fixup;
+	ppc_md.pcibios_fixup_bus = apus_pcibios_fixup_bus;
+
+	return;
+}
+
+#endif /* CONFIG_AMIGA */
diff --git a/arch/ppc/platforms/apus_pci.h b/arch/ppc/platforms/apus_pci.h
new file mode 100644
index 0000000..f15974a
--- /dev/null
+++ b/arch/ppc/platforms/apus_pci.h
@@ -0,0 +1,34 @@
+/*
+ * Phase5 CybervisionPPC (TVP4020) definitions for the Permedia2 framebuffer
+ * driver.
+ *
+ * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
+ * --------------------------------------------------------------------------
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file README.legal in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef APUS_PCI_H
+#define APUS_PCI_H
+
+
+#define CSPPC_PCI_BRIDGE		0xfffe0000
+#define CSPPC_BRIDGE_ENDIAN		0x0000
+#define CSPPC_BRIDGE_INT		0x0010
+
+#define	CVPPC_PCI_CONFIG		0xfffc0000
+#define CVPPC_ROM_ADDRESS		0xe2000001
+#define CVPPC_REGS_REGION		0xef000000
+#define CVPPC_FB_APERTURE_ONE		0xe0000000
+#define CVPPC_FB_APERTURE_TWO		0xe1000000
+#define CVPPC_FB_SIZE			0x00800000
+
+/* CVPPC_BRIDGE_ENDIAN */
+#define CSPPCF_BRIDGE_BIG_ENDIAN	0x02
+
+/* CVPPC_BRIDGE_INT */
+#define CSPPCF_BRIDGE_ACTIVE_INT2	0x01
+
+
+#endif	/* APUS_PCI_H */
diff --git a/arch/ppc/platforms/apus_setup.c b/arch/ppc/platforms/apus_setup.c
new file mode 100644
index 0000000..2f74fde
--- /dev/null
+++ b/arch/ppc/platforms/apus_setup.c
@@ -0,0 +1,815 @@
+/*
+ *  arch/ppc/platforms/apus_setup.c
+ *
+ *  Copyright (C) 1998, 1999  Jesper Skov
+ *
+ *  Basically what is needed to replace functionality found in
+ *  arch/m68k allowing Amiga drivers to work under APUS.
+ *  Bits of code and/or ideas from arch/m68k and arch/ppc files.
+ *
+ * TODO:
+ *  This file needs a *really* good cleanup. Restructure and optimize.
+ *  Make sure it can be compiled for non-APUS configs. Begin to move
+ *  Amiga specific stuff into mach/amiga.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/initrd.h>
+#include <linux/seq_file.h>
+
+/* Needs INITSERIAL call in head.S! */
+#undef APUS_DEBUG
+
+#include <asm/bootinfo.h>
+#include <asm/setup.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/amigappc.h>
+#include <asm/pgtable.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+
+unsigned long m68k_machtype;
+char debug_device[6] = "";
+
+extern void amiga_init_IRQ(void);
+
+extern void apus_setup_pci_ptrs(void);
+
+void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
+/* machine dependent irq functions */
+void (*mach_init_IRQ) (void) __initdata = NULL;
+void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
+void (*mach_get_model) (char *model) = NULL;
+int (*mach_get_hardware_list) (char *buffer) = NULL;
+int (*mach_get_irq_list) (struct seq_file *, void *) = NULL;
+void (*mach_process_int) (int, struct pt_regs *) = NULL;
+/* machine dependent timer functions */
+unsigned long (*mach_gettimeoffset) (void);
+void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
+int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
+int (*mach_set_clock_mmss) (unsigned long) = NULL;
+void (*mach_reset)( void );
+long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
+#if defined(CONFIG_AMIGA_FLOPPY)
+void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
+#endif
+#ifdef CONFIG_HEARTBEAT
+void (*mach_heartbeat) (int) = NULL;
+extern void apus_heartbeat (void);
+#endif
+
+extern unsigned long amiga_model;
+extern unsigned decrementer_count;/* count value for 1e6/HZ microseconds */
+extern unsigned count_period_num; /* 1 decrementer count equals */
+extern unsigned count_period_den; /* count_period_num / count_period_den us */
+
+int num_memory = 0;
+struct mem_info memory[NUM_MEMINFO];/* memory description */
+/* FIXME: Duplicate memory data to avoid conflicts with m68k shared code. */
+int m68k_realnum_memory = 0;
+struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
+
+struct mem_info ramdisk;
+
+extern void amiga_floppy_setup(char *, int *);
+extern void config_amiga(void);
+
+static int __60nsram = 0;
+
+/* for cpuinfo */
+static int __bus_speed = 0;
+static int __speed_test_failed = 0;
+
+/********************************************** COMPILE PROTECTION */
+/* Provide some stubs that links to Amiga specific functions.
+ * This allows CONFIG_APUS to be removed from generic PPC files while
+ * preventing link errors for other PPC targets.
+ */
+unsigned long apus_get_rtc_time(void)
+{
+#ifdef CONFIG_APUS
+	extern unsigned long m68k_get_rtc_time(void);
+
+	return m68k_get_rtc_time ();
+#else
+	return 0;
+#endif
+}
+
+int apus_set_rtc_time(unsigned long nowtime)
+{
+#ifdef CONFIG_APUS
+	extern int m68k_set_rtc_time(unsigned long nowtime);
+
+	return m68k_set_rtc_time (nowtime);
+#else
+	return 0;
+#endif
+}
+
+/*********************************************************** SETUP */
+/* From arch/m68k/kernel/setup.c. */
+void __init apus_setup_arch(void)
+{
+#ifdef CONFIG_APUS
+	extern char cmd_line[];
+	int i;
+	char *p, *q;
+
+	/* Let m68k-shared code know it should do the Amiga thing. */
+	m68k_machtype = MACH_AMIGA;
+
+	/* Parse the command line for arch-specific options.
+	 * For the m68k, this is currently only "debug=xxx" to enable printing
+	 * certain kernel messages to some machine-specific device.  */
+	for( p = cmd_line; p && *p; ) {
+	    i = 0;
+	    if (!strncmp( p, "debug=", 6 )) {
+		    strlcpy( debug_device, p+6, sizeof(debug_device) );
+		    if ((q = strchr( debug_device, ' ' ))) *q = 0;
+		    i = 1;
+	    } else if (!strncmp( p, "60nsram", 7 )) {
+		    APUS_WRITE (APUS_REG_WAITSTATE,
+				REGWAITSTATE_SETRESET
+				|REGWAITSTATE_PPCR
+				|REGWAITSTATE_PPCW);
+		    __60nsram = 1;
+		    i = 1;
+	    }
+
+	    if (i) {
+		/* option processed, delete it */
+		if ((q = strchr( p, ' ' )))
+		    strcpy( p, q+1 );
+		else
+		    *p = 0;
+	    } else {
+		if ((p = strchr( p, ' ' ))) ++p;
+	    }
+	}
+
+	config_amiga();
+
+#if 0 /* Enable for logging - also include logging.o in Makefile rule */
+	{
+#define LOG_SIZE 4096
+		void* base;
+
+		/* Throw away some memory - the P5 firmare stomps on top
+		 * of CHIP memory during bootup.
+		 */
+		amiga_chip_alloc(0x1000);
+
+		base = amiga_chip_alloc(LOG_SIZE+sizeof(klog_data_t));
+		LOG_INIT(base, base+sizeof(klog_data_t), LOG_SIZE);
+	}
+#endif
+#endif
+}
+
+int
+apus_show_cpuinfo(struct seq_file *m)
+{
+	extern int __map_without_bats;
+	extern unsigned long powerup_PCI_present;
+
+	seq_printf(m, "machine\t\t: Amiga\n");
+	seq_printf(m, "bus speed\t: %d%s", __bus_speed,
+		   (__speed_test_failed) ? " [failed]\n" : "\n");
+	seq_printf(m, "using BATs\t: %s\n",
+		   (__map_without_bats) ? "No" : "Yes");
+	seq_printf(m, "ram speed\t: %dns\n", (__60nsram) ? 60 : 70);
+	seq_printf(m, "PCI bridge\t: %s\n",
+		   (powerup_PCI_present) ? "Yes" : "No");
+	return 0;
+}
+
+static void get_current_tb(unsigned long long *time)
+{
+	__asm __volatile ("1:mftbu 4      \n\t"
+			  "  mftb  5      \n\t"
+			  "  mftbu 6      \n\t"
+			  "  cmpw  4,6    \n\t"
+			  "  bne   1b     \n\t"
+			  "  stw   4,0(%0)\n\t"
+			  "  stw   5,4(%0)\n\t"
+			  :
+			  : "r" (time)
+			  : "r4", "r5", "r6");
+}
+
+
+void apus_calibrate_decr(void)
+{
+#ifdef CONFIG_APUS
+	unsigned long freq;
+
+	/* This algorithm for determining the bus speed was
+           contributed by Ralph Schmidt. */
+	unsigned long long start, stop;
+	int bus_speed;
+	int speed_test_failed = 0;
+
+	{
+		unsigned long loop = amiga_eclock / 10;
+
+		get_current_tb (&start);
+		while (loop--) {
+			unsigned char tmp;
+
+			tmp = ciaa.pra;
+		}
+		get_current_tb (&stop);
+	}
+
+	bus_speed = (((unsigned long)(stop-start))*10*4) / 1000000;
+	if (AMI_1200 == amiga_model)
+		bus_speed /= 2;
+
+	if ((bus_speed >= 47) && (bus_speed < 53)) {
+		bus_speed = 50;
+		freq = 12500000;
+	} else if ((bus_speed >= 57) && (bus_speed < 63)) {
+		bus_speed = 60;
+		freq = 15000000;
+	} else if ((bus_speed >= 63) && (bus_speed < 69)) {
+		bus_speed = 67;
+		freq = 16666667;
+	} else {
+		printk ("APUS: Unable to determine bus speed (%d). "
+			"Defaulting to 50MHz", bus_speed);
+		bus_speed = 50;
+		freq = 12500000;
+		speed_test_failed = 1;
+	}
+
+	/* Ease diagnostics... */
+	{
+		extern int __map_without_bats;
+		extern unsigned long powerup_PCI_present;
+
+		printk ("APUS: BATs=%d, BUS=%dMHz",
+			(__map_without_bats) ? 0 : 1,
+			bus_speed);
+		if (speed_test_failed)
+			printk ("[FAILED - please report]");
+
+		printk (", RAM=%dns, PCI bridge=%d\n",
+			(__60nsram) ? 60 : 70,
+			(powerup_PCI_present) ? 1 : 0);
+
+		/* print a bit more if asked politely... */
+		if (!(ciaa.pra & 0x40)){
+			extern unsigned int bat_addrs[4][3];
+			int b;
+			for (b = 0; b < 4; ++b) {
+				printk ("APUS: BAT%d ", b);
+				printk ("%08x-%08x -> %08x\n",
+					bat_addrs[b][0],
+					bat_addrs[b][1],
+					bat_addrs[b][2]);
+			}
+		}
+
+	}
+
+        printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+	       freq/1000000, freq%1000000);
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+	__bus_speed = bus_speed;
+	__speed_test_failed = speed_test_failed;
+#endif
+}
+
+void arch_gettod(int *year, int *mon, int *day, int *hour,
+		 int *min, int *sec)
+{
+#ifdef CONFIG_APUS
+	if (mach_gettod)
+		mach_gettod(year, mon, day, hour, min, sec);
+	else
+		*year = *mon = *day = *hour = *min = *sec = 0;
+#endif
+}
+
+/* for "kbd-reset" cmdline param */
+__init
+void kbd_reset_setup(char *str, int *ints)
+{
+}
+
+/*********************************************************** FLOPPY */
+#if defined(CONFIG_AMIGA_FLOPPY)
+__init
+void floppy_setup(char *str, int *ints)
+{
+	if (mach_floppy_setup)
+		mach_floppy_setup (str, ints);
+}
+#endif
+
+/*********************************************************** MEMORY */
+#define KMAP_MAX 32
+unsigned long kmap_chunks[KMAP_MAX*3];
+int kmap_chunk_count = 0;
+
+/* From pgtable.h */
+static __inline__ pte_t *my_find_pte(struct mm_struct *mm,unsigned long va)
+{
+	pgd_t *dir = 0;
+	pmd_t *pmd = 0;
+	pte_t *pte = 0;
+
+	va &= PAGE_MASK;
+
+	dir = pgd_offset( mm, va );
+	if (dir)
+	{
+		pmd = pmd_offset(dir, va & PAGE_MASK);
+		if (pmd && pmd_present(*pmd))
+		{
+			pte = pte_offset(pmd, va);
+		}
+	}
+	return pte;
+}
+
+
+/* Again simulating an m68k/mm/kmap.c function. */
+void kernel_set_cachemode( unsigned long address, unsigned long size,
+			   unsigned int cmode )
+{
+	unsigned long mask, flags;
+
+	switch (cmode)
+	{
+	case IOMAP_FULL_CACHING:
+		mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED);
+		flags = 0;
+		break;
+	case IOMAP_NOCACHE_SER:
+		mask = ~0;
+		flags = (_PAGE_NO_CACHE | _PAGE_GUARDED);
+		break;
+	default:
+		panic ("kernel_set_cachemode() doesn't support mode %d\n",
+		       cmode);
+		break;
+	}
+
+	size /= PAGE_SIZE;
+	address &= PAGE_MASK;
+	while (size--)
+	{
+		pte_t *pte;
+
+		pte = my_find_pte(&init_mm, address);
+		if ( !pte )
+		{
+			printk("pte NULL in kernel_set_cachemode()\n");
+			return;
+		}
+
+                pte_val (*pte) &= mask;
+                pte_val (*pte) |= flags;
+                flush_tlb_page(find_vma(&init_mm,address),address);
+
+		address += PAGE_SIZE;
+	}
+}
+
+unsigned long mm_ptov (unsigned long paddr)
+{
+	unsigned long ret;
+	if (paddr < 16*1024*1024)
+		ret = ZTWO_VADDR(paddr);
+	else {
+		int i;
+
+		for (i = 0; i < kmap_chunk_count;){
+			unsigned long phys = kmap_chunks[i++];
+			unsigned long size = kmap_chunks[i++];
+			unsigned long virt = kmap_chunks[i++];
+			if (paddr >= phys
+			    && paddr < (phys + size)){
+				ret = virt + paddr - phys;
+				goto exit;
+			}
+		}
+
+		ret = (unsigned long) __va(paddr);
+	}
+exit:
+#ifdef DEBUGPV
+	printk ("PTOV(%lx)=%lx\n", paddr, ret);
+#endif
+	return ret;
+}
+
+int mm_end_of_chunk (unsigned long addr, int len)
+{
+	if (memory[0].addr + memory[0].size == addr + len)
+		return 1;
+	return 0;
+}
+
+/*********************************************************** CACHE */
+
+#define L1_CACHE_BYTES 32
+#define MAX_CACHE_SIZE 8192
+void cache_push(__u32 addr, int length)
+{
+	addr = mm_ptov(addr);
+
+	if (MAX_CACHE_SIZE < length)
+		length = MAX_CACHE_SIZE;
+
+	while(length > 0){
+		__asm ("dcbf 0,%0\n\t"
+		       : : "r" (addr));
+		addr += L1_CACHE_BYTES;
+		length -= L1_CACHE_BYTES;
+	}
+	/* Also flush trailing block */
+	__asm ("dcbf 0,%0\n\t"
+	       "sync \n\t"
+	       : : "r" (addr));
+}
+
+void cache_clear(__u32 addr, int length)
+{
+	if (MAX_CACHE_SIZE < length)
+		length = MAX_CACHE_SIZE;
+
+	addr = mm_ptov(addr);
+
+	__asm ("dcbf 0,%0\n\t"
+	       "sync \n\t"
+	       "icbi 0,%0 \n\t"
+	       "isync \n\t"
+	       : : "r" (addr));
+
+	addr += L1_CACHE_BYTES;
+	length -= L1_CACHE_BYTES;
+
+	while(length > 0){
+		__asm ("dcbf 0,%0\n\t"
+		       "sync \n\t"
+		       "icbi 0,%0 \n\t"
+		       "isync \n\t"
+		       : : "r" (addr));
+		addr += L1_CACHE_BYTES;
+		length -= L1_CACHE_BYTES;
+	}
+
+	__asm ("dcbf 0,%0\n\t"
+	       "sync \n\t"
+	       "icbi 0,%0 \n\t"
+	       "isync \n\t"
+	       : : "r" (addr));
+}
+
+/****************************************************** from setup.c */
+void
+apus_restart(char *cmd)
+{
+	local_irq_disable();
+
+	APUS_WRITE(APUS_REG_LOCK,
+		   REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK2);
+	APUS_WRITE(APUS_REG_LOCK,
+		   REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK3);
+	APUS_WRITE(APUS_REG_LOCK,
+		   REGLOCK_BLACKMAGICK2|REGLOCK_BLACKMAGICK3);
+	APUS_WRITE(APUS_REG_SHADOW, REGSHADOW_SELFRESET);
+	APUS_WRITE(APUS_REG_RESET, REGRESET_AMIGARESET);
+	for(;;);
+}
+
+void
+apus_power_off(void)
+{
+	for (;;);
+}
+
+void
+apus_halt(void)
+{
+   apus_restart(NULL);
+}
+
+/****************************************************** IRQ stuff */
+
+static unsigned char last_ipl[8];
+
+int apus_get_irq(struct pt_regs* regs)
+{
+	unsigned char ipl_emu, mask;
+	unsigned int level;
+
+	APUS_READ(APUS_IPL_EMU, ipl_emu);
+	level = (ipl_emu >> 3) & IPLEMU_IPLMASK;
+	mask = IPLEMU_SETRESET|IPLEMU_DISABLEINT|level;
+	level ^= 7;
+
+	/* Save previous IPL value */
+	if (last_ipl[level])
+		return -2;
+	last_ipl[level] = ipl_emu;
+
+	/* Set to current IPL value */
+	APUS_WRITE(APUS_IPL_EMU, mask);
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT|level);
+
+
+#ifdef __INTERRUPT_DEBUG
+	printk("<%d:%d>", level, ~ipl_emu & IPLEMU_IPLMASK);
+#endif
+	return level + IRQ_AMIGA_AUTO;
+}
+
+void apus_end_irq(unsigned int irq)
+{
+	unsigned char ipl_emu;
+	unsigned int level = irq - IRQ_AMIGA_AUTO;
+#ifdef __INTERRUPT_DEBUG
+	printk("{%d}", ~last_ipl[level] & IPLEMU_IPLMASK);
+#endif
+	/* Restore IPL to the previous value */
+	ipl_emu = last_ipl[level] & IPLEMU_IPLMASK;
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET|IPLEMU_DISABLEINT|ipl_emu);
+	last_ipl[level] = 0;
+	ipl_emu ^= 7;
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT|ipl_emu);
+}
+
+/****************************************************** debugging */
+
+/* some serial hardware definitions */
+#define SDR_OVRUN   (1<<15)
+#define SDR_RBF     (1<<14)
+#define SDR_TBE     (1<<13)
+#define SDR_TSRE    (1<<12)
+
+#define AC_SETCLR   (1<<15)
+#define AC_UARTBRK  (1<<11)
+
+#define SER_DTR     (1<<7)
+#define SER_RTS     (1<<6)
+#define SER_DCD     (1<<5)
+#define SER_CTS     (1<<4)
+#define SER_DSR     (1<<3)
+
+static __inline__ void ser_RTSon(void)
+{
+    ciab.pra &= ~SER_RTS; /* active low */
+}
+
+int __debug_ser_out( unsigned char c )
+{
+	custom.serdat = c | 0x100;
+	mb();
+	while (!(custom.serdatr & 0x2000))
+		barrier();
+	return 1;
+}
+
+unsigned char __debug_ser_in( void )
+{
+	unsigned char c;
+
+	/* XXX: is that ok?? derived from amiga_ser.c... */
+	while( !(custom.intreqr & IF_RBF) )
+		barrier();
+	c = custom.serdatr;
+	/* clear the interrupt, so that another character can be read */
+	custom.intreq = IF_RBF;
+	return c;
+}
+
+int __debug_serinit( void )
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/* turn off Rx and Tx interrupts */
+	custom.intena = IF_RBF | IF_TBE;
+
+	/* clear any pending interrupt */
+	custom.intreq = IF_RBF | IF_TBE;
+
+	local_irq_restore(flags);
+
+	/*
+	 * set the appropriate directions for the modem control flags,
+	 * and clear RTS and DTR
+	 */
+	ciab.ddra |= (SER_DTR | SER_RTS);   /* outputs */
+	ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR);  /* inputs */
+
+#ifdef CONFIG_KGDB
+	/* turn Rx interrupts on for GDB */
+	custom.intena = IF_SETCLR | IF_RBF;
+	ser_RTSon();
+#endif
+
+	return 0;
+}
+
+void __debug_print_hex(unsigned long x)
+{
+	int i;
+	char hexchars[] = "0123456789ABCDEF";
+
+	for (i = 0; i < 8; i++) {
+		__debug_ser_out(hexchars[(x >> 28) & 15]);
+		x <<= 4;
+	}
+	__debug_ser_out('\n');
+	__debug_ser_out('\r');
+}
+
+void __debug_print_string(char* s)
+{
+	unsigned char c;
+	while((c = *s++))
+		__debug_ser_out(c);
+	__debug_ser_out('\n');
+	__debug_ser_out('\r');
+}
+
+static void apus_progress(char *s, unsigned short value)
+{
+	__debug_print_string(s);
+}
+
+/****************************************************** init */
+
+/* The number of spurious interrupts */
+volatile unsigned int num_spurious;
+
+extern struct irqaction amiga_sys_irqaction[AUTO_IRQS];
+
+
+extern void amiga_enable_irq(unsigned int irq);
+extern void amiga_disable_irq(unsigned int irq);
+
+struct hw_interrupt_type amiga_sys_irqctrl = {
+	.typename = "Amiga IPL",
+	.end = apus_end_irq,
+};
+
+struct hw_interrupt_type amiga_irqctrl = {
+	.typename = "Amiga    ",
+	.enable = amiga_enable_irq,
+	.disable = amiga_disable_irq,
+};
+
+#define HARDWARE_MAPPED_SIZE (512*1024)
+unsigned long __init apus_find_end_of_memory(void)
+{
+	int shadow = 0;
+	unsigned long total;
+
+	/* The memory size reported by ADOS excludes the 512KB
+	   reserved for PPC exception registers and possibly 512KB
+	   containing a shadow of the ADOS ROM. */
+	{
+		unsigned long size = memory[0].size;
+
+		/* If 2MB aligned, size was probably user
+                   specified. We can't tell anything about shadowing
+                   in this case so skip shadow assignment. */
+		if (0 != (size & 0x1fffff)){
+			/* Align to 512KB to ensure correct handling
+			   of both memfile and system specified
+			   sizes. */
+			size = ((size+0x0007ffff) & 0xfff80000);
+			/* If memory is 1MB aligned, assume
+                           shadowing. */
+			shadow = !(size & 0x80000);
+		}
+
+		/* Add the chunk that ADOS does not see. by aligning
+                   the size to the nearest 2MB limit upwards.  */
+		memory[0].size = ((size+0x001fffff) & 0xffe00000);
+	}
+
+	ppc_memstart = memory[0].addr;
+	ppc_memoffset = PAGE_OFFSET - PPC_MEMSTART;
+	total = memory[0].size;
+
+	/* Remove the memory chunks that are controlled by special
+           Phase5 hardware. */
+
+	/* Remove the upper 512KB if it contains a shadow of
+	   the ADOS ROM. FIXME: It might be possible to
+	   disable this shadow HW. Check the booter
+	   (ppc_boot.c) */
+	if (shadow)
+		total -= HARDWARE_MAPPED_SIZE;
+
+	/* Remove the upper 512KB where the PPC exception
+	   vectors are mapped. */
+	total -= HARDWARE_MAPPED_SIZE;
+
+	/* Linux/APUS only handles one block of memory -- the one on
+	   the PowerUP board. Other system memory is horrible slow in
+	   comparison. The user can use other memory for swapping
+	   using the z2ram device. */
+	return total;
+}
+
+static void __init
+apus_map_io(void)
+{
+	/* Map PPC exception vectors. */
+	io_block_mapping(0xfff00000, 0xfff00000, 0x00020000, _PAGE_KERNEL);
+	/* Map chip and ZorroII memory */
+	io_block_mapping(zTwoBase,   0x00000000, 0x01000000, _PAGE_IO);
+}
+
+__init
+void apus_init_IRQ(void)
+{
+	struct irqaction *action;
+	int i;
+
+#ifdef CONFIG_PCI
+        apus_setup_pci_ptrs();
+#endif
+
+	for ( i = 0 ; i < AMI_IRQS; i++ ) {
+		irq_desc[i].status = IRQ_LEVEL;
+		if (i < IRQ_AMIGA_AUTO) {
+			irq_desc[i].handler = &amiga_irqctrl;
+		} else {
+			irq_desc[i].handler = &amiga_sys_irqctrl;
+			action = &amiga_sys_irqaction[i-IRQ_AMIGA_AUTO];
+			if (action->name)
+				setup_irq(i, action);
+		}
+	}
+
+	amiga_init_IRQ();
+
+}
+
+__init
+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+		   unsigned long r6, unsigned long r7)
+{
+	extern int parse_bootinfo(const struct bi_record *);
+	extern char _end[];
+
+	/* Parse bootinfo. The bootinfo is located right after
+           the kernel bss */
+	parse_bootinfo((const struct bi_record *)&_end);
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* Take care of initrd if we have one. Use data from
+	   bootinfo to avoid the need to initialize PPC
+	   registers when kernel is booted via a PPC reset. */
+	if ( ramdisk.addr ) {
+		initrd_start = (unsigned long) __va(ramdisk.addr);
+		initrd_end = (unsigned long)
+			__va(ramdisk.size + ramdisk.addr);
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	ISA_DMA_THRESHOLD = 0x00ffffff;
+
+	ppc_md.setup_arch     = apus_setup_arch;
+	ppc_md.show_cpuinfo   = apus_show_cpuinfo;
+	ppc_md.init_IRQ       = apus_init_IRQ;
+	ppc_md.get_irq        = apus_get_irq;
+
+#ifdef CONFIG_HEARTBEAT
+	ppc_md.heartbeat      = apus_heartbeat;
+	ppc_md.heartbeat_count = 1;
+#endif
+#ifdef APUS_DEBUG
+	__debug_serinit();
+	ppc_md.progress       = apus_progress;
+#endif
+	ppc_md.init           = NULL;
+
+	ppc_md.restart        = apus_restart;
+	ppc_md.power_off      = apus_power_off;
+	ppc_md.halt           = apus_halt;
+
+	ppc_md.time_init      = NULL;
+	ppc_md.set_rtc_time   = apus_set_rtc_time;
+	ppc_md.get_rtc_time   = apus_get_rtc_time;
+	ppc_md.calibrate_decr = apus_calibrate_decr;
+
+	ppc_md.find_end_of_memory = apus_find_end_of_memory;
+	ppc_md.setup_io_mappings = apus_map_io;
+}
diff --git a/arch/ppc/platforms/bseip.h b/arch/ppc/platforms/bseip.h
new file mode 100644
index 0000000..691f4a52
--- /dev/null
+++ b/arch/ppc/platforms/bseip.h
@@ -0,0 +1,38 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Bright Star Engineering ip-Engine board.  Copied from the MBX stuff.
+ *
+ * Copyright (c) 1998 Dan Malek (dmalek@jlc.net)
+ */
+#ifndef __MACH_BSEIP_DEFS
+#define __MACH_BSEIP_DEFS
+
+#ifndef __ASSEMBLY__
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
+	unsigned char	bi_enetaddr[6];
+	unsigned int	bi_baudrate;
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+/* Memory map is configured by the PROM startup.
+ * All we need to get started is the IMMR.
+ */
+#define IMAP_ADDR		((uint)0xff000000)
+#define IMAP_SIZE		((uint)(64 * 1024))
+#define PCMCIA_MEM_ADDR		((uint)0x04000000)
+#define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+#endif	/* !__ASSEMBLY__ */
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif
diff --git a/arch/ppc/platforms/ccm.h b/arch/ppc/platforms/ccm.h
new file mode 100644
index 0000000..edb87b5
--- /dev/null
+++ b/arch/ppc/platforms/ccm.h
@@ -0,0 +1,28 @@
+/*
+ * Siemens Card Controller Module specific definitions
+ *
+ * Copyright (C) 2001-2002 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __MACH_CCM_H
+#define __MACH_CCM_H
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define	CCM_IMMR_BASE    0xF0000000	/* phys. addr of IMMR			*/
+#define	CCM_IMAP_SIZE   (64 * 1024)	/* size of mapped area			*/
+
+#define	IMAP_ADDR     CCM_IMMR_BASE	/* physical base address of IMMR area	*/
+#define IMAP_SIZE     CCM_IMAP_SIZE	/* mapped size of IMMR area		*/
+
+#define	FEC_INTERRUPT	13		/* = SIU_LEVEL6				*/
+#define	DEC_INTERRUPT	11		/* = SIU_LEVEL5				*/
+#define	CPM_INTERRUPT	 9		/* = SIU_LEVEL4				*/
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif	/* __MACH_CCM_H */
diff --git a/arch/ppc/platforms/chestnut.c b/arch/ppc/platforms/chestnut.c
new file mode 100644
index 0000000..7786818
--- /dev/null
+++ b/arch/ppc/platforms/chestnut.c
@@ -0,0 +1,580 @@
+/*
+ * arch/ppc/platforms/chestnut.c
+ *
+ * Board setup routines for IBM Chestnut
+ *
+ * Author: <source@mvista.com>
+ *
+ * <2004> (c) MontaVista Software, Inc. 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/ide.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/mtd/physmap.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <linux/irq.h>
+#include <asm/hw_irq.h>
+#include <asm/machdep.h>
+#include <asm/kgdb.h>
+#include <asm/bootinfo.h>
+#include <asm/mv64x60.h>
+#include <platforms/chestnut.h>
+
+static void __iomem *sram_base; /* Virtual addr of Internal SRAM */
+static void __iomem *cpld_base; /* Virtual addr of CPLD Regs */
+
+static mv64x60_handle_t	bh;
+
+extern void gen550_progress(char *, unsigned short);
+extern void gen550_init(int, struct uart_port *);
+extern void mv64360_pcibios_fixup(mv64x60_handle_t *bh);
+
+#define BIT(x) (1<<x)
+#define CHESTNUT_PRESERVE_MASK (BIT(MV64x60_CPU2DEV_0_WIN) | \
+				BIT(MV64x60_CPU2DEV_1_WIN) | \
+				BIT(MV64x60_CPU2DEV_2_WIN) | \
+				BIT(MV64x60_CPU2DEV_3_WIN) | \
+				BIT(MV64x60_CPU2BOOT_WIN))
+/**************************************************************************
+ * FUNCTION: chestnut_calibrate_decr
+ *
+ * DESCRIPTION: initialize decrementer interrupt frequency (used as system
+ *              timer)
+ *
+ ****/
+static void __init
+chestnut_calibrate_decr(void)
+{
+	ulong freq;
+
+	freq = CHESTNUT_BUS_SPEED / 4;
+
+	printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+		freq/1000000, freq%1000000);
+
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
+
+static int
+chestnut_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: IBM\n");
+	seq_printf(m, "machine\t\t: 750FX/GX Eval Board (Chestnut/Buckeye)\n");
+
+	return 0;
+}
+
+/**************************************************************************
+ * FUNCTION: chestnut_find_end_of_memory
+ *
+ * DESCRIPTION: ppc_md memory size callback
+ *
+ ****/
+unsigned long __init
+chestnut_find_end_of_memory(void)
+{
+   	static int  mem_size = 0;
+
+   	if (mem_size == 0) {
+      		mem_size = mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
+				MV64x60_TYPE_MV64460);
+   	}
+   	return mem_size;
+}
+
+#if defined(CONFIG_SERIAL_8250)
+static void __init
+chestnut_early_serial_map(void)
+{
+	struct uart_port port;
+
+	/* Setup serial port access */
+	memset(&port, 0, sizeof(port));
+	port.uartclk = BASE_BAUD * 16;
+	port.irq = UART0_INT;
+	port.flags = STD_COM_FLAGS | UPF_IOREMAP;
+	port.iotype = SERIAL_IO_MEM;
+	port.mapbase = CHESTNUT_UART0_IO_BASE;
+	port.regshift = 0;
+
+	if (early_serial_setup(&port) != 0)
+		printk("Early serial init of port 0 failed\n");
+
+	/* Assume early_serial_setup() doesn't modify serial_req */
+	port.line = 1;
+	port.irq = UART1_INT;
+	port.mapbase = CHESTNUT_UART1_IO_BASE;
+
+	if (early_serial_setup(&port) != 0)
+		printk("Early serial init of port 1 failed\n");
+}
+#endif
+
+/**************************************************************************
+ * FUNCTION: chestnut_map_irq
+ *
+ * DESCRIPTION: 0 return since PCI IRQs not needed
+ *
+ ****/
+static int __init
+chestnut_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] = {
+		{CHESTNUT_PCI_SLOT0_IRQ, CHESTNUT_PCI_SLOT0_IRQ,
+		 CHESTNUT_PCI_SLOT0_IRQ, CHESTNUT_PCI_SLOT0_IRQ},
+		{CHESTNUT_PCI_SLOT1_IRQ, CHESTNUT_PCI_SLOT1_IRQ,
+		 CHESTNUT_PCI_SLOT1_IRQ, CHESTNUT_PCI_SLOT1_IRQ},
+		{CHESTNUT_PCI_SLOT2_IRQ, CHESTNUT_PCI_SLOT2_IRQ,
+		 CHESTNUT_PCI_SLOT2_IRQ, CHESTNUT_PCI_SLOT2_IRQ},
+		{CHESTNUT_PCI_SLOT3_IRQ, CHESTNUT_PCI_SLOT3_IRQ,
+		 CHESTNUT_PCI_SLOT3_IRQ, CHESTNUT_PCI_SLOT3_IRQ},
+	};
+	const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+
+/**************************************************************************
+ * FUNCTION: chestnut_setup_bridge
+ *
+ * DESCRIPTION: initalize board-specific settings on the MV64360
+ *
+ ****/
+static void __init
+chestnut_setup_bridge(void)
+{
+	struct mv64x60_setup_info	si;
+	int i;
+
+   	if ( ppc_md.progress )
+		ppc_md.progress("chestnut_setup_bridge: enter", 0);
+
+	memset(&si, 0, sizeof(si));
+
+	si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
+
+	/* setup only PCI bus 0 (bus 1 not used) */
+	si.pci_0.enable_bus = 1;
+	si.pci_0.pci_io.cpu_base = CHESTNUT_PCI0_IO_PROC_ADDR;
+	si.pci_0.pci_io.pci_base_hi = 0;
+	si.pci_0.pci_io.pci_base_lo = CHESTNUT_PCI0_IO_PCI_ADDR;
+	si.pci_0.pci_io.size = CHESTNUT_PCI0_IO_SIZE;
+	si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; /* no swapping */
+	si.pci_0.pci_mem[0].cpu_base = CHESTNUT_PCI0_MEM_PROC_ADDR;
+	si.pci_0.pci_mem[0].pci_base_hi = CHESTNUT_PCI0_MEM_PCI_HI_ADDR;
+	si.pci_0.pci_mem[0].pci_base_lo = CHESTNUT_PCI0_MEM_PCI_LO_ADDR;
+	si.pci_0.pci_mem[0].size = CHESTNUT_PCI0_MEM_SIZE;
+	si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; /* no swapping */
+	si.pci_0.pci_cmd_bits = 0;
+	si.pci_0.latency_timer = 0x80;
+
+	for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) {
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+		si.cpu_prot_options[i] = 0;
+		si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
+		si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
+		si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
+
+		si.pci_1.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+#else
+		si.cpu_prot_options[i] = 0;
+		si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; /* errata */
+		si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; /* errata */
+		si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; /* errata */
+
+		si.pci_1.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_WB |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+#endif
+	}
+
+   	/* Lookup host bridge - on CPU 0 - no SMP support */
+   	if (mv64x60_init(&bh, &si)) {
+        	printk("\n\nPCI Bridge initialization failed!\n");
+   	}
+
+	pci_dram_offset = 0;
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = chestnut_map_irq;
+	ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
+
+	mv64x60_set_bus(&bh, 0, 0);
+	bh.hose_a->first_busno = 0;
+	bh.hose_a->last_busno = 0xff;
+	bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
+}
+
+void __init
+chestnut_setup_peripherals(void)
+{
+   	mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+			CHESTNUT_BOOT_8BIT_BASE, CHESTNUT_BOOT_8BIT_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN,
+			CHESTNUT_32BIT_BASE, CHESTNUT_32BIT_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,
+			CHESTNUT_CPLD_BASE, CHESTNUT_CPLD_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+	cpld_base = ioremap(CHESTNUT_CPLD_BASE, CHESTNUT_CPLD_SIZE);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN,
+			CHESTNUT_UART_BASE, CHESTNUT_UART_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN,
+			CHESTNUT_FRAM_BASE, CHESTNUT_FRAM_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
+
+   	mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+			CHESTNUT_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+#ifdef CONFIG_NOT_COHERENT_CACHE
+   	mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b0);
+#else
+   	mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2);
+#endif
+	sram_base = ioremap(CHESTNUT_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE);
+   	memset(sram_base, 0, MV64360_SRAM_SIZE);
+
+	/*
+	 * Configure MPP pins for PCI DMA
+	 *
+	 * PCI Slot	GNT pin		REQ pin
+	 *	0	MPP16		MPP17
+	 *	1	MPP18		MPP19
+	 *	2	MPP20		MPP21
+	 *	3	MPP22		MPP23
+	 */
+	mv64x60_write(&bh, MV64x60_MPP_CNTL_2,
+			(0x1 << 0)  |	/* MPPSel16 PCI0_GNT[0] */
+			(0x1 << 4)  |	/* MPPSel17 PCI0_REQ[0] */
+			(0x1 << 8)  |	/* MPPSel18 PCI0_GNT[1] */
+			(0x1 << 12) |	/* MPPSel19 PCI0_REQ[1] */
+			(0x1 << 16) |	/* MPPSel20 PCI0_GNT[2] */
+			(0x1 << 20) |	/* MPPSel21 PCI0_REQ[2] */
+			(0x1 << 24) |	/* MPPSel22 PCI0_GNT[3] */
+			(0x1 << 28));	/* MPPSel23 PCI0_REQ[3] */
+	/*
+	 * Set unused MPP pins for output, as per schematic note
+	 *
+	 * Unused Pins: MPP01, MPP02, MPP04, MPP05, MPP06
+	 *		MPP09, MPP10, MPP13, MPP14, MPP15
+	 */
+	mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_0,
+			(0xf << 4)  |	/* MPPSel01 GPIO[1] */
+			(0xf << 8)  |	/* MPPSel02 GPIO[2] */
+			(0xf << 16) |	/* MPPSel04 GPIO[4] */
+			(0xf << 20) |	/* MPPSel05 GPIO[5] */
+			(0xf << 24));	/* MPPSel06 GPIO[6] */
+	mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1,
+			(0xf << 4)  |	/* MPPSel09 GPIO[9] */
+			(0xf << 8)  |	/* MPPSel10 GPIO[10] */
+			(0xf << 20) |	/* MPPSel13 GPIO[13] */
+			(0xf << 24) |	/* MPPSel14 GPIO[14] */
+			(0xf << 28));	/* MPPSel15 GPIO[15] */
+	mv64x60_set_bits(&bh, MV64x60_GPP_IO_CNTL, /* Output */
+			BIT(1)  | BIT(2)  | BIT(4)  | BIT(5)  | BIT(6)  |
+			BIT(9)  | BIT(10) | BIT(13) | BIT(14) | BIT(15));
+
+   	/*
+    	 * Configure the following MPP pins to indicate a level
+    	 * triggered interrupt
+    	 *
+       	 * MPP24 - Board Reset (just map the MPP & GPP for chestnut_reset)
+       	 * MPP25 - UART A  (high)
+       	 * MPP26 - UART B  (high)
+	 * MPP28 - PCI Slot 3 (low)
+	 * MPP29 - PCI Slot 2 (low)
+	 * MPP30 - PCI Slot 1 (low)
+	 * MPP31 - PCI Slot 0 (low)
+    	 */
+        mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_3,
+                        BIT(3) | BIT(2) | BIT(1) | BIT(0)	 | /* MPP 24 */
+                        BIT(7) | BIT(6) | BIT(5) | BIT(4)	 | /* MPP 25 */
+                        BIT(11) | BIT(10) | BIT(9) | BIT(8)	 | /* MPP 26 */
+			BIT(19) | BIT(18) | BIT(17) | BIT(16)	 | /* MPP 28 */
+			BIT(23) | BIT(22) | BIT(21) | BIT(20)	 | /* MPP 29 */
+			BIT(27) | BIT(26) | BIT(25) | BIT(24)	 | /* MPP 30 */
+			BIT(31) | BIT(30) | BIT(29) | BIT(28));    /* MPP 31 */
+
+   	/*
+	 * Define GPP 25 (high), 26 (high), 28 (low), 29 (low), 30 (low),
+	 * 31 (low) interrupt polarity input signal and level triggered
+    	 */
+   	mv64x60_clr_bits(&bh, MV64x60_GPP_LEVEL_CNTL, BIT(25) | BIT(26));
+   	mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL,
+			BIT(28) | BIT(29) | BIT(30) | BIT(31));
+   	mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL,
+			BIT(25) | BIT(26) | BIT(28) | BIT(29) | BIT(30) |
+			BIT(31));
+
+   	/* Config GPP interrupt controller to respond to level trigger */
+   	mv64x60_set_bits(&bh, MV64360_COMM_ARBITER_CNTL, BIT(10));
+
+   	/*
+    	 * Dismiss and then enable interrupt on GPP interrupt cause for CPU #0
+    	 */
+   	mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE,
+			~(BIT(25) | BIT(26) | BIT(28) | BIT(29) | BIT(30) |
+			  BIT(31)));
+   	mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK,
+			BIT(25) | BIT(26) | BIT(28) | BIT(29) | BIT(30) |
+			BIT(31));
+
+   	/*
+    	 * Dismiss and then enable interrupt on CPU #0 high cause register
+    	 * BIT27 summarizes GPP interrupts 24-31
+    	 */
+   	mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, BIT(27));
+
+   	if (ppc_md.progress)
+		ppc_md.progress("chestnut_setup_bridge: exit", 0);
+}
+
+/**************************************************************************
+ * FUNCTION: chestnut_setup_arch
+ *
+ * DESCRIPTION: ppc_md machine configuration callback
+ *
+ ****/
+static void __init
+chestnut_setup_arch(void)
+{
+	if (ppc_md.progress)
+      		ppc_md.progress("chestnut_setup_arch: enter", 0);
+
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000 / HZ;
+
+   	/* if the time base value is greater than bus freq/4 (the TB and
+    	* decrementer tick rate) + signed integer rollover value, we
+    	* can spend a fair amount of time waiting for the rollover to
+    	* happen.  To get around this, initialize the time base register
+    	* to a "safe" value.
+    	*/
+   	set_tb(0, 0);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA2;
+#endif
+
+   	/*
+    	* Set up the L2CR register.
+    	*/
+ 	_set_L2CR(_get_L2CR() | L2CR_L2E);
+
+	chestnut_setup_bridge();
+	chestnut_setup_peripherals();
+
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+
+#if defined(CONFIG_SERIAL_8250)
+	chestnut_early_serial_map();
+#endif
+
+	/* Identify the system */
+	printk(KERN_INFO "System Identification: IBM 750FX/GX Eval Board\n");
+	printk(KERN_INFO "IBM 750FX/GX port (C) 2004 MontaVista Software, Inc."
+		" (source@mvista.com)\n");
+
+	if (ppc_md.progress)
+      		ppc_md.progress("chestnut_setup_arch: exit", 0);
+}
+
+#ifdef CONFIG_MTD_PHYSMAP
+static struct mtd_partition ptbl;
+
+static int __init
+chestnut_setup_mtd(void)
+{
+	memset(&ptbl, 0, sizeof(ptbl));
+
+	ptbl.name = "User FS";
+	ptbl.size = CHESTNUT_32BIT_SIZE;
+
+	physmap_map.size = CHESTNUT_32BIT_SIZE;
+	physmap_set_partitions(&ptbl, 1);
+	return 0;
+}
+
+arch_initcall(chestnut_setup_mtd);
+#endif
+
+/**************************************************************************
+ * FUNCTION: chestnut_restart
+ *
+ * DESCRIPTION: ppc_md machine reset callback
+ *              reset the board via the CPLD command register
+ *
+ ****/
+static void
+chestnut_restart(char *cmd)
+{
+	volatile ulong i = 10000000;
+
+	local_irq_disable();
+
+        /*
+         * Set CPLD Reg 3 bit 0 to 1 to allow MPP signals on reset to work
+         *
+         * MPP24 - board reset
+         */
+   	writeb(0x1, cpld_base + 3);
+
+	/* GPP pin tied to MPP earlier */
+        mv64x60_set_bits(&bh, MV64x60_GPP_VALUE_SET, BIT(24));
+
+   	while (i-- > 0);
+   	panic("restart failed\n");
+}
+
+static void
+chestnut_halt(void)
+{
+	local_irq_disable();
+	for (;;);
+	/* NOTREACHED */
+}
+
+static void
+chestnut_power_off(void)
+{
+	chestnut_halt();
+	/* NOTREACHED */
+}
+
+/**************************************************************************
+ * FUNCTION: chestnut_map_io
+ *
+ * DESCRIPTION: configure fixed memory-mapped IO
+ *
+ ****/
+static void __init
+chestnut_map_io(void)
+{
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+	io_block_mapping(CHESTNUT_UART_BASE, CHESTNUT_UART_BASE, 0x100000,
+		_PAGE_IO);
+#endif
+}
+
+/**************************************************************************
+ * FUNCTION: chestnut_set_bat
+ *
+ * DESCRIPTION: configures a (temporary) bat mapping for early access to
+ *              device I/O
+ *
+ ****/
+static __inline__ void
+chestnut_set_bat(void)
+{
+        mb();
+        mtspr(SPRN_DBAT3U, 0xf0001ffe);
+        mtspr(SPRN_DBAT3L, 0xf000002a);
+        mb();
+}
+
+/**************************************************************************
+ * FUNCTION: platform_init
+ *
+ * DESCRIPTION: main entry point for configuring board-specific machine
+ *              callbacks
+ *
+ ****/
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+        /* Copy the kernel command line arguments to a safe place. */
+
+        if (r6) {
+                *(char *) (r7 + KERNELBASE) = 0;
+                strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+        }
+
+	isa_mem_base = 0;
+
+	ppc_md.setup_arch = chestnut_setup_arch;
+	ppc_md.show_cpuinfo = chestnut_show_cpuinfo;
+	ppc_md.irq_canonicalize = NULL;
+	ppc_md.init_IRQ = mv64360_init_irq;
+	ppc_md.get_irq = mv64360_get_irq;
+	ppc_md.init = NULL;
+
+	ppc_md.find_end_of_memory = chestnut_find_end_of_memory;
+	ppc_md.setup_io_mappings  = chestnut_map_io;
+
+	ppc_md.restart = chestnut_restart;
+   	ppc_md.power_off = chestnut_power_off;
+   	ppc_md.halt = chestnut_halt;
+
+	ppc_md.time_init = NULL;
+	ppc_md.set_rtc_time = NULL;
+	ppc_md.get_rtc_time = NULL;
+	ppc_md.calibrate_decr = chestnut_calibrate_decr;
+
+	ppc_md.nvram_read_val = NULL;
+	ppc_md.nvram_write_val = NULL;
+
+	ppc_md.heartbeat = NULL;
+
+	bh.p_base = CONFIG_MV64X60_NEW_BASE;
+
+	chestnut_set_bat();
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG)
+	ppc_md.progress = gen550_progress;
+#endif
+#if defined(CONFIG_KGDB)
+	ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
+
+	if (ppc_md.progress)
+                ppc_md.progress("chestnut_init(): exit", 0);
+}
diff --git a/arch/ppc/platforms/chestnut.h b/arch/ppc/platforms/chestnut.h
new file mode 100644
index 0000000..0400b2b
--- /dev/null
+++ b/arch/ppc/platforms/chestnut.h
@@ -0,0 +1,129 @@
+/*
+ * arch/ppc/platforms/chestnut.h
+ *
+ * Definitions for IBM 750FXGX Eval (Chestnut)
+ *
+ * Author: <source@mvista.com>
+ *
+ * Based on Artesyn Katana code done by Tim Montgomery <timm@artesyncp.com>
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by Mark A. Greer <mgreer@mvista.com>
+ *
+ * <2004> (c) MontaVista Software, Inc. 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.
+ */
+
+/*
+ * This is the CPU physical memory map (windows must be at least 1MB and start
+ * on a boundary that is a multiple of the window size):
+ *
+ * Seems on the IBM 750FXGX Eval board, the MV64460 Registers can be in
+ * only 2 places per switch U17 0x14000000 or 0xf1000000 easily - chose to
+ * implement at 0xf1000000 only at this time
+ *
+ *    0xfff00000-0xffffffff      - 8 Flash
+ *    0xffe00000-0xffefffff      - BOOT SRAM
+ *    0xffd00000-0xffd00004      - CPLD
+ *    0xffc00000-0xffc0000f      - UART
+ *    0xffb00000-0xffb07fff      - FRAM
+ *    0xff840000-0xffafffff      - *** HOLE ***
+ *    0xff800000-0xff83ffff      - MV64460 Integrated SRAM
+ *    0xfe000000-0xff8fffff      - *** HOLE ***
+ *    0xfc000000-0xfdffffff      - 32bit Flash
+ *    0xf1010000-0xfbffffff      - *** HOLE ***
+ *    0xf1000000-0xf100ffff      - MV64460 Registers
+ */
+
+#ifndef __PPC_PLATFORMS_CHESTNUT_H__
+#define __PPC_PLATFORMS_CHESTNUT_H__
+
+#define CHESTNUT_BOOT_8BIT_BASE			0xfff00000
+#define CHESTNUT_BOOT_8BIT_SIZE_ACTUAL		(1024*1024)
+#define CHESTNUT_BOOT_SRAM_BASE			0xffe00000
+#define CHESTNUT_BOOT_SRAM_SIZE_ACTUAL		(1024*1024)
+#define CHESTNUT_CPLD_BASE			0xffd00000
+#define CHESTNUT_CPLD_SIZE_ACTUAL		5
+#define CHESTNUT_CPLD_REG3			(CHESTNUT_CPLD_BASE+3)
+#define CHESTNUT_UART_BASE			0xffc00000
+#define CHESTNUT_UART_SIZE_ACTUAL		16
+#define CHESTNUT_FRAM_BASE			0xffb00000
+#define CHESTNUT_FRAM_SIZE_ACTUAL		(32*1024)
+#define CHESTNUT_INTERNAL_SRAM_BASE		0xff800000
+#define CHESTNUT_32BIT_BASE			0xfc000000
+#define CHESTNUT_32BIT_SIZE			(32*1024*1024)
+
+#define CHESTNUT_BOOT_8BIT_SIZE		max(MV64360_WINDOW_SIZE_MIN, \
+					CHESTNUT_BOOT_8BIT_SIZE_ACTUAL)
+#define CHESTNUT_BOOT_SRAM_SIZE		max(MV64360_WINDOW_SIZE_MIN, \
+					CHESTNUT_BOOT_SRAM_SIZE_ACTUAL)
+#define CHESTNUT_CPLD_SIZE		max(MV64360_WINDOW_SIZE_MIN, \
+					CHESTNUT_CPLD_SIZE_ACTUAL)
+#define CHESTNUT_UART_SIZE		max(MV64360_WINDOW_SIZE_MIN, \
+					CHESTNUT_UART_SIZE_ACTUAL)
+#define CHESTNUT_FRAM_SIZE		max(MV64360_WINDOW_SIZE_MIN, \
+					CHESTNUT_FRAM_SIZE_ACTUAL)
+
+#define CHESTNUT_BUS_SPEED		200000000
+#define CHESTNUT_PIBS_DATABASE		0xf0000 /* from PIBS src code */
+
+#define	KATANA_ETH0_PHY_ADDR			12
+#define	KATANA_ETH1_PHY_ADDR			11
+#define	KATANA_ETH2_PHY_ADDR			4
+
+#define CHESTNUT_ETH_TX_QUEUE_SIZE		800
+#define CHESTNUT_ETH_RX_QUEUE_SIZE		400
+
+/*
+ * PCI windows
+ */
+
+#define CHESTNUT_PCI0_MEM_PROC_ADDR	0x80000000
+#define CHESTNUT_PCI0_MEM_PCI_HI_ADDR	0x00000000
+#define CHESTNUT_PCI0_MEM_PCI_LO_ADDR	0x80000000
+#define CHESTNUT_PCI0_MEM_SIZE		0x10000000
+#define CHESTNUT_PCI0_IO_PROC_ADDR	0xa0000000
+#define CHESTNUT_PCI0_IO_PCI_ADDR	0x00000000
+#define CHESTNUT_PCI0_IO_SIZE		0x01000000
+
+/*
+ * Board-specific IRQ info
+ */
+#define CHESTNUT_PCI_SLOT0_IRQ	(64 + 31)
+#define CHESTNUT_PCI_SLOT1_IRQ	(64 + 30)
+#define CHESTNUT_PCI_SLOT2_IRQ	(64 + 29)
+#define CHESTNUT_PCI_SLOT3_IRQ	(64 + 28)
+
+/* serial port definitions */
+#define CHESTNUT_UART0_IO_BASE  (CHESTNUT_UART_BASE + 8)
+#define CHESTNUT_UART1_IO_BASE  CHESTNUT_UART_BASE
+
+#define UART0_INT           	(64 + 25)
+#define UART1_INT        	(64 + 26)
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE  64
+#else
+#define RS_TABLE_SIZE  2
+#endif
+
+/* Rate for the 3.6864 Mhz clock for the onboard serial chip */
+#define BASE_BAUD 		(3686400 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+#define STD_UART_OP(num)						\
+        { 0, BASE_BAUD, 0, UART##num##_INT, STD_COM_FLAGS,		\
+                iomem_base: (u8 *)CHESTNUT_UART##num##_IO_BASE,	\
+		io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS        \
+        STD_UART_OP(0)          \
+        STD_UART_OP(1)
+
+#endif /* __PPC_PLATFORMS_CHESTNUT_H__ */
diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c
new file mode 100644
index 0000000..5bb6492
--- /dev/null
+++ b/arch/ppc/platforms/chrp_pci.c
@@ -0,0 +1,309 @@
+/*
+ * CHRP pci routines.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/bootmem.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/hydra.h>
+#include <asm/prom.h>
+#include <asm/gg2.h>
+#include <asm/machdep.h>
+#include <asm/sections.h>
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
+
+/* LongTrail */
+void __iomem *gg2_pci_config_base;
+
+/*
+ * The VLSI Golden Gate II has only 512K of PCI configuration space, so we
+ * limit the bus number to 3 bits
+ */
+
+int __chrp gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off,
+			   int len, u32 *val)
+{
+	volatile void __iomem *cfg_data;
+	struct pci_controller *hose = bus->sysdata;
+
+	if (bus->number > 7)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that off is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
+	switch (len) {
+	case 1:
+		*val =  in_8(cfg_data);
+		break;
+	case 2:
+		*val = in_le16(cfg_data);
+		break;
+	default:
+		*val = in_le32(cfg_data);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int __chrp gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off,
+			    int len, u32 val)
+{
+	volatile void __iomem *cfg_data;
+	struct pci_controller *hose = bus->sysdata;
+
+	if (bus->number > 7)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that off is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
+	switch (len) {
+	case 1:
+		out_8(cfg_data, val);
+		break;
+	case 2:
+		out_le16(cfg_data, val);
+		break;
+	default:
+		out_le32(cfg_data, val);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops gg2_pci_ops =
+{
+	gg2_read_config,
+	gg2_write_config
+};
+
+/*
+ * Access functions for PCI config space using RTAS calls.
+ */
+int __chrp
+rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		 int len, u32 *val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
+		| (((bus->number - hose->first_busno) & 0xff) << 16)
+		| (hose->index << 24);
+        unsigned long ret = ~0UL;
+	int rval;
+
+	rval = call_rtas("read-pci-config", 2, 2, &ret, addr, len);
+	*val = ret;
+	return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
+}
+
+int __chrp
+rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		  int len, u32 val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
+		| (((bus->number - hose->first_busno) & 0xff) << 16)
+		| (hose->index << 24);
+	int rval;
+
+	rval = call_rtas("write-pci-config", 3, 1, NULL, addr, len, val);
+	return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops rtas_pci_ops =
+{
+	rtas_read_config,
+	rtas_write_config
+};
+
+volatile struct Hydra *Hydra = NULL;
+
+int __init
+hydra_init(void)
+{
+	struct device_node *np;
+
+	np = find_devices("mac-io");
+	if (np == NULL || np->n_addrs == 0)
+		return 0;
+	Hydra = ioremap(np->addrs[0].address, np->addrs[0].size);
+	printk("Hydra Mac I/O at %x\n", np->addrs[0].address);
+	printk("Hydra Feature_Control was %x",
+	       in_le32(&Hydra->Feature_Control));
+	out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN |
+					   HYDRA_FC_SCSI_CELL_EN |
+					   HYDRA_FC_SCCA_ENABLE |
+					   HYDRA_FC_SCCB_ENABLE |
+					   HYDRA_FC_ARB_BYPASS |
+					   HYDRA_FC_MPIC_ENABLE |
+					   HYDRA_FC_SLOW_SCC_PCLK |
+					   HYDRA_FC_MPIC_IS_MASTER));
+	printk(", now %x\n", in_le32(&Hydra->Feature_Control));
+	return 1;
+}
+
+void __init
+chrp_pcibios_fixup(void)
+{
+	struct pci_dev *dev = NULL;
+	struct device_node *np;
+
+	/* PCI interrupts are controlled by the OpenPIC */
+	for_each_pci_dev(dev) {
+		np = pci_device_to_OF_node(dev);
+		if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
+			dev->irq = np->intrs[0].line;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+	}
+}
+
+#define PRG_CL_RESET_VALID 0x00010000
+
+static void __init
+setup_python(struct pci_controller *hose, struct device_node *dev)
+{
+	u32 *reg, val;
+	unsigned long addr = dev->addrs[0].address;
+
+	setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010);
+
+	/* Clear the magic go-slow bit */
+	reg = (u32 *) ioremap(dev->addrs[0].address + 0xf6000, 0x40);
+	val = in_be32(&reg[12]);
+	if (val & PRG_CL_RESET_VALID) {
+		out_be32(&reg[12], val & ~PRG_CL_RESET_VALID);
+		in_be32(&reg[12]);
+	}
+	iounmap(reg);
+}
+
+/* Marvell Discovery II based Pegasos 2 */
+static void __init setup_peg2(struct pci_controller *hose, struct device_node *dev)
+{
+	struct device_node *root = find_path_device("/");
+	struct device_node *rtas;
+
+	rtas = of_find_node_by_name (root, "rtas");
+	if (rtas) {
+		hose->ops = &rtas_pci_ops;
+	} else {
+		printk ("RTAS supporting Pegasos OF not found, please upgrade"
+			" your firmware\n");
+	}
+	pci_assign_all_busses = 1;
+}
+
+void __init
+chrp_find_bridges(void)
+{
+	struct device_node *dev;
+	int *bus_range;
+	int len, index = -1;
+	struct pci_controller *hose;
+	unsigned int *dma;
+	char *model, *machine;
+	int is_longtrail = 0, is_mot = 0, is_pegasos = 0;
+	struct device_node *root = find_path_device("/");
+
+	/*
+	 * The PCI host bridge nodes on some machines don't have
+	 * properties to adequately identify them, so we have to
+	 * look at what sort of machine this is as well.
+	 */
+	machine = get_property(root, "model", NULL);
+	if (machine != NULL) {
+		is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0;
+		is_mot = strncmp(machine, "MOT", 3) == 0;
+		if (strncmp(machine, "Pegasos2", 8) == 0)
+			is_pegasos = 2;
+		else if (strncmp(machine, "Pegasos", 7) == 0)
+			is_pegasos = 1;
+	}
+	for (dev = root->child; dev != NULL; dev = dev->sibling) {
+		if (dev->type == NULL || strcmp(dev->type, "pci") != 0)
+			continue;
+		++index;
+		/* The GG2 bridge on the LongTrail doesn't have an address */
+		if (dev->n_addrs < 1 && !is_longtrail) {
+			printk(KERN_WARNING "Can't use %s: no address\n",
+			       dev->full_name);
+			continue;
+		}
+		bus_range = (int *) get_property(dev, "bus-range", &len);
+		if (bus_range == NULL || len < 2 * sizeof(int)) {
+			printk(KERN_WARNING "Can't get bus-range for %s\n",
+				dev->full_name);
+			continue;
+		}
+		if (bus_range[1] == bus_range[0])
+			printk(KERN_INFO "PCI bus %d", bus_range[0]);
+		else
+			printk(KERN_INFO "PCI buses %d..%d",
+			       bus_range[0], bus_range[1]);
+		printk(" controlled by %s", dev->type);
+		if (dev->n_addrs > 0)
+			printk(" at %x", dev->addrs[0].address);
+		printk("\n");
+
+		hose = pcibios_alloc_controller();
+		if (!hose) {
+			printk("Can't allocate PCI controller structure for %s\n",
+				dev->full_name);
+			continue;
+		}
+		hose->arch_data = dev;
+		hose->first_busno = bus_range[0];
+		hose->last_busno = bus_range[1];
+
+		model = get_property(dev, "model", NULL);
+		if (model == NULL)
+			model = "<none>";
+		if (device_is_compatible(dev, "IBM,python")) {
+			setup_python(hose, dev);
+		} else if (is_mot
+			   || strncmp(model, "Motorola, Grackle", 17) == 0) {
+			setup_grackle(hose);
+		} else if (is_longtrail) {
+			void __iomem *p = ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
+			hose->ops = &gg2_pci_ops;
+			hose->cfg_data = p;
+			gg2_pci_config_base = p;
+		} else if (is_pegasos == 1) {
+			setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc);
+		} else if (is_pegasos == 2) {
+			setup_peg2(hose, dev);
+		} else {
+			printk("No methods for %s (model %s), using RTAS\n",
+			       dev->full_name, model);
+			hose->ops = &rtas_pci_ops;
+		}
+
+		pci_process_bridge_OF_ranges(hose, dev, index == 0);
+
+		/* check the first bridge for a property that we can
+		   use to set pci_dram_offset */
+		dma = (unsigned int *)
+			get_property(dev, "ibm,dma-ranges", &len);
+		if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) {
+			pci_dram_offset = dma[2] - dma[3];
+			printk("pci_dram_offset = %lx\n", pci_dram_offset);
+		}
+	}
+
+	/* Do not fixup interrupts from OF tree on pegasos */
+	if (is_pegasos == 0)
+		ppc_md.pcibios_fixup = chrp_pcibios_fixup;
+}
diff --git a/arch/ppc/platforms/chrp_pegasos_eth.c b/arch/ppc/platforms/chrp_pegasos_eth.c
new file mode 100644
index 0000000..cad5bfa
--- /dev/null
+++ b/arch/ppc/platforms/chrp_pegasos_eth.c
@@ -0,0 +1,101 @@
+/*
+ *  arch/ppc/platforms/chrp_pegasos_eth.c
+ *
+ *  Copyright (C) 2005 Sven Luther <sl@bplan-gmbh.de>
+ *  Thanks to :
+ *	Dale Farnsworth <dale@farnsworth.org>
+ *	Mark A. Greer <mgreer@mvista.com>
+ *	Nicolas DET <nd@bplan-gmbh.de>
+ *	Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *  And anyone else who helped me on this.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/mv643xx.h>
+#include <linux/pci.h>
+
+/* Pegasos 2 specific Marvell MV 64361 gigabit ethernet port setup */
+static struct resource mv643xx_eth_shared_resources[] = {
+	[0] = {
+		.name	= "ethernet shared base",
+		.start	= 0xf1000000 + MV643XX_ETH_SHARED_REGS,
+		.end	= 0xf1000000 + MV643XX_ETH_SHARED_REGS +
+					MV643XX_ETH_SHARED_REGS_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device mv643xx_eth_shared_device = {
+	.name		= MV643XX_ETH_SHARED_NAME,
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(mv643xx_eth_shared_resources),
+	.resource	= mv643xx_eth_shared_resources,
+};
+
+static struct resource mv643xx_eth0_resources[] = {
+	[0] = {
+		.name	= "eth0 irq",
+		.start	= 9,
+		.end	= 9,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct mv643xx_eth_platform_data eth0_pd;
+
+static struct platform_device eth0_device = {
+	.name		= MV643XX_ETH_NAME,
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(mv643xx_eth0_resources),
+	.resource	= mv643xx_eth0_resources,
+	.dev = {
+		.platform_data = &eth0_pd,
+	},
+};
+
+static struct resource mv643xx_eth1_resources[] = {
+	[0] = {
+		.name	= "eth1 irq",
+		.start	= 9,
+		.end	= 9,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct mv643xx_eth_platform_data eth1_pd;
+
+static struct platform_device eth1_device = {
+	.name		= MV643XX_ETH_NAME,
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(mv643xx_eth1_resources),
+	.resource	= mv643xx_eth1_resources,
+	.dev = {
+		.platform_data = &eth1_pd,
+	},
+};
+
+static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
+	&mv643xx_eth_shared_device,
+	&eth0_device,
+	&eth1_device,
+};
+
+
+int
+mv643xx_eth_add_pds(void)
+{
+	int ret = 0;
+	static struct pci_device_id pci_marvell_mv64360[] = {
+		{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64360) },
+		{ }
+	};
+
+	if (pci_dev_present(pci_marvell_mv64360)) {
+		ret = platform_add_devices(mv643xx_eth_pd_devs, ARRAY_SIZE(mv643xx_eth_pd_devs));
+	}
+	return ret;
+}
+device_initcall(mv643xx_eth_add_pds);
diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c
new file mode 100644
index 0000000..f23c4f3
--- /dev/null
+++ b/arch/ppc/platforms/chrp_setup.c
@@ -0,0 +1,615 @@
+/*
+ *  arch/ppc/platforms/setup.c
+ *
+ *  Copyright (C) 1995  Linus Torvalds
+ *  Adapted from 'alpha' version by Gary Thomas
+ *  Modified by Cort Dougan (cort@cs.nmt.edu)
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/version.h>
+#include <linux/adb.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/irq.h>
+#include <linux/console.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/gg2.h>
+#include <asm/pci-bridge.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/hydra.h>
+#include <asm/sections.h>
+#include <asm/time.h>
+#include <asm/btext.h>
+#include <asm/i8259.h>
+#include <asm/open_pic.h>
+#include <asm/xmon.h>
+
+unsigned long chrp_get_rtc_time(void);
+int chrp_set_rtc_time(unsigned long nowtime);
+void chrp_calibrate_decr(void);
+long chrp_time_init(void);
+
+void chrp_find_bridges(void);
+void chrp_event_scan(void);
+void rtas_display_progress(char *, unsigned short);
+void rtas_indicator_progress(char *, unsigned short);
+void btext_progress(char *, unsigned short);
+
+extern unsigned long pmac_find_end_of_memory(void);
+extern int of_show_percpuinfo(struct seq_file *, int);
+
+int _chrp_type;
+EXPORT_SYMBOL(_chrp_type);
+
+/*
+ * XXX this should be in xmon.h, but putting it there means xmon.h
+ * has to include <linux/interrupt.h> (to get irqreturn_t), which
+ * causes all sorts of problems.  -- paulus
+ */
+extern irqreturn_t xmon_irq(int, void *, struct pt_regs *);
+
+extern dev_t boot_dev;
+
+extern PTE *Hash, *Hash_end;
+extern unsigned long Hash_size, Hash_mask;
+extern int probingmem;
+extern unsigned long loops_per_jiffy;
+static int max_width;
+
+#ifdef CONFIG_SMP
+extern struct smp_ops_t chrp_smp_ops;
+#endif
+
+static const char *gg2_memtypes[4] = {
+	"FPM", "SDRAM", "EDO", "BEDO"
+};
+static const char *gg2_cachesizes[4] = {
+	"256 KB", "512 KB", "1 MB", "Reserved"
+};
+static const char *gg2_cachetypes[4] = {
+	"Asynchronous", "Reserved", "Flow-Through Synchronous",
+	"Pipelined Synchronous"
+};
+static const char *gg2_cachemodes[4] = {
+	"Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
+};
+
+int __chrp
+chrp_show_cpuinfo(struct seq_file *m)
+{
+	int i, sdramen;
+	unsigned int t;
+	struct device_node *root;
+	const char *model = "";
+
+	root = find_path_device("/");
+	if (root)
+		model = get_property(root, "model", NULL);
+	seq_printf(m, "machine\t\t: CHRP %s\n", model);
+
+	/* longtrail (goldengate) stuff */
+	if (!strncmp(model, "IBM,LongTrail", 13)) {
+		/* VLSI VAS96011/12 `Golden Gate 2' */
+		/* Memory banks */
+		sdramen = (in_le32(gg2_pci_config_base + GG2_PCI_DRAM_CTRL)
+			   >>31) & 1;
+		for (i = 0; i < (sdramen ? 4 : 6); i++) {
+			t = in_le32(gg2_pci_config_base+
+						 GG2_PCI_DRAM_BANK0+
+						 i*4);
+			if (!(t & 1))
+				continue;
+			switch ((t>>8) & 0x1f) {
+			case 0x1f:
+				model = "4 MB";
+				break;
+			case 0x1e:
+				model = "8 MB";
+				break;
+			case 0x1c:
+				model = "16 MB";
+				break;
+			case 0x18:
+				model = "32 MB";
+				break;
+			case 0x10:
+				model = "64 MB";
+				break;
+			case 0x00:
+				model = "128 MB";
+				break;
+			default:
+				model = "Reserved";
+				break;
+			}
+			seq_printf(m, "memory bank %d\t: %s %s\n", i, model,
+				   gg2_memtypes[sdramen ? 1 : ((t>>1) & 3)]);
+		}
+		/* L2 cache */
+		t = in_le32(gg2_pci_config_base+GG2_PCI_CC_CTRL);
+		seq_printf(m, "board l2\t: %s %s (%s)\n",
+			   gg2_cachesizes[(t>>7) & 3],
+			   gg2_cachetypes[(t>>2) & 3],
+			   gg2_cachemodes[t & 3]);
+	}
+	return 0;
+}
+
+/*
+ *  Fixes for the National Semiconductor PC78308VUL SuperI/O
+ *
+ *  Some versions of Open Firmware incorrectly initialize the IRQ settings
+ *  for keyboard and mouse
+ */
+static inline void __init sio_write(u8 val, u8 index)
+{
+	outb(index, 0x15c);
+	outb(val, 0x15d);
+}
+
+static inline u8 __init sio_read(u8 index)
+{
+	outb(index, 0x15c);
+	return inb(0x15d);
+}
+
+static void __init sio_fixup_irq(const char *name, u8 device, u8 level,
+				     u8 type)
+{
+	u8 level0, type0, active;
+
+	/* select logical device */
+	sio_write(device, 0x07);
+	active = sio_read(0x30);
+	level0 = sio_read(0x70);
+	type0 = sio_read(0x71);
+	if (level0 != level || type0 != type || !active) {
+		printk(KERN_WARNING "sio: %s irq level %d, type %d, %sactive: "
+		       "remapping to level %d, type %d, active\n",
+		       name, level0, type0, !active ? "in" : "", level, type);
+		sio_write(0x01, 0x30);
+		sio_write(level, 0x70);
+		sio_write(type, 0x71);
+	}
+}
+
+static void __init sio_init(void)
+{
+	struct device_node *root;
+
+	if ((root = find_path_device("/")) &&
+	    !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) {
+		/* logical device 0 (KBC/Keyboard) */
+		sio_fixup_irq("keyboard", 0, 1, 2);
+		/* select logical device 1 (KBC/Mouse) */
+		sio_fixup_irq("mouse", 1, 12, 2);
+	}
+}
+
+
+static void __init pegasos_set_l2cr(void)
+{
+	struct device_node *np;
+
+	/* On Pegasos, enable the l2 cache if needed, as the OF forgets it */
+	if (_chrp_type != _CHRP_Pegasos)
+		return;
+
+	/* Enable L2 cache if needed */
+	np = find_type_devices("cpu");
+	if (np != NULL) {
+		unsigned int *l2cr = (unsigned int *)
+			get_property (np, "l2cr", NULL);
+		if (l2cr == NULL) {
+			printk ("Pegasos l2cr : no cpu l2cr property found\n");
+			return;
+		}
+		if (!((*l2cr) & 0x80000000)) {
+			printk ("Pegasos l2cr : L2 cache was not active, "
+				"activating\n");
+			_set_L2CR(0);
+			_set_L2CR((*l2cr) | 0x80000000);
+		}
+	}
+}
+
+void __init chrp_setup_arch(void)
+{
+	struct device_node *device;
+
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000/HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* this is fine for chrp */
+	initrd_below_start_ok = 1;
+
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+		ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
+
+	/* On pegasos, enable the L2 cache if not already done by OF */
+	pegasos_set_l2cr();
+
+	/* Lookup PCI host bridges */
+	chrp_find_bridges();
+
+#ifndef CONFIG_PPC64BRIDGE
+	/*
+	 *  Temporary fixes for PCI devices.
+	 *  -- Geert
+	 */
+	hydra_init();		/* Mac I/O */
+
+#endif /* CONFIG_PPC64BRIDGE */
+
+	/*
+	 *  Fix the Super I/O configuration
+	 */
+	sio_init();
+
+	/* Get the event scan rate for the rtas so we know how
+	 * often it expects a heartbeat. -- Cort
+	 */
+	if ( rtas_data ) {
+		struct property *p;
+		device = find_devices("rtas");
+		for ( p = device->properties;
+		      p && strncmp(p->name, "rtas-event-scan-rate", 20);
+		      p = p->next )
+			/* nothing */ ;
+		if ( p && *(unsigned long *)p->value ) {
+			ppc_md.heartbeat = chrp_event_scan;
+			ppc_md.heartbeat_reset = (HZ/(*(unsigned long *)p->value)*30)-1;
+			ppc_md.heartbeat_count = 1;
+			printk("RTAS Event Scan Rate: %lu (%lu jiffies)\n",
+			       *(unsigned long *)p->value, ppc_md.heartbeat_reset );
+		}
+	}
+
+	pci_create_OF_bus_map();
+}
+
+void __chrp
+chrp_event_scan(void)
+{
+	unsigned char log[1024];
+	unsigned long ret = 0;
+	/* XXX: we should loop until the hardware says no more error logs -- Cort */
+	call_rtas( "event-scan", 4, 1, &ret, 0xffffffff, 0,
+		   __pa(log), 1024 );
+	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+}
+
+void __chrp
+chrp_restart(char *cmd)
+{
+	printk("RTAS system-reboot returned %d\n",
+	       call_rtas("system-reboot", 0, 1, NULL));
+	for (;;);
+}
+
+void __chrp
+chrp_power_off(void)
+{
+	/* allow power on only with power button press */
+	printk("RTAS power-off returned %d\n",
+	       call_rtas("power-off", 2, 1, NULL,0xffffffff,0xffffffff));
+	for (;;);
+}
+
+void __chrp
+chrp_halt(void)
+{
+	chrp_power_off();
+}
+
+u_int __chrp
+chrp_irq_canonicalize(u_int irq)
+{
+	if (irq == 2)
+		return 9;
+	return irq;
+}
+
+/*
+ * Finds the open-pic node and sets OpenPIC_Addr based on its reg property.
+ * Then checks if it has an interrupt-ranges property.  If it does then
+ * we have a distributed open-pic, so call openpic_set_sources to tell
+ * the openpic code where to find the interrupt source registers.
+ */
+static void __init chrp_find_openpic(void)
+{
+	struct device_node *np;
+	int len, i;
+	unsigned int *iranges;
+	void *isu;
+
+	np = find_type_devices("open-pic");
+	if (np == NULL || np->n_addrs == 0)
+		return;
+	printk(KERN_INFO "OpenPIC at %x (size %x)\n",
+	       np->addrs[0].address, np->addrs[0].size);
+	OpenPIC_Addr = ioremap(np->addrs[0].address, 0x40000);
+	if (OpenPIC_Addr == NULL) {
+		printk(KERN_ERR "Failed to map OpenPIC!\n");
+		return;
+	}
+
+	iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len);
+	if (iranges == NULL || len < 2 * sizeof(unsigned int))
+		return;		/* not distributed */
+
+	/*
+	 * The first pair of cells in interrupt-ranges refers to the
+	 * IDU; subsequent pairs refer to the ISUs.
+	 */
+	len /= 2 * sizeof(unsigned int);
+	if (np->n_addrs < len) {
+		printk(KERN_ERR "Insufficient addresses for distributed"
+		       " OpenPIC (%d < %d)\n", np->n_addrs, len);
+		return;
+	}
+	if (iranges[1] != 0) {
+		printk(KERN_INFO "OpenPIC irqs %d..%d in IDU\n",
+		       iranges[0], iranges[0] + iranges[1] - 1);
+		openpic_set_sources(iranges[0], iranges[1], NULL);
+	}
+	for (i = 1; i < len; ++i) {
+		iranges += 2;
+		printk(KERN_INFO "OpenPIC irqs %d..%d in ISU at %x (%x)\n",
+		       iranges[0], iranges[0] + iranges[1] - 1,
+		       np->addrs[i].address, np->addrs[i].size);
+		isu = ioremap(np->addrs[i].address, np->addrs[i].size);
+		if (isu != NULL)
+			openpic_set_sources(iranges[0], iranges[1], isu);
+		else
+			printk(KERN_ERR "Failed to map OpenPIC ISU at %x!\n",
+			       np->addrs[i].address);
+	}
+}
+
+#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
+static struct irqaction xmon_irqaction = {
+	.handler = xmon_irq,
+	.mask = CPU_MASK_NONE,
+	.name = "XMON break",
+};
+#endif
+
+void __init chrp_init_IRQ(void)
+{
+	struct device_node *np;
+	int i;
+	unsigned long chrp_int_ack = 0;
+	unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
+#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
+	struct device_node *kbd;
+#endif
+
+	for (np = find_devices("pci"); np != NULL; np = np->next) {
+		unsigned int *addrp = (unsigned int *)
+			get_property(np, "8259-interrupt-acknowledge", NULL);
+
+		if (addrp == NULL)
+			continue;
+		chrp_int_ack = addrp[prom_n_addr_cells(np)-1];
+		break;
+	}
+	if (np == NULL)
+		printk(KERN_ERR "Cannot find PCI interrupt acknowledge address\n");
+
+	chrp_find_openpic();
+
+	if (OpenPIC_Addr) {
+		prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS);
+		OpenPIC_InitSenses = init_senses;
+		OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS;
+
+		openpic_init(NUM_8259_INTERRUPTS);
+		/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
+		openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+				       i8259_irq);
+
+	}
+	for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+		irq_desc[i].handler = &i8259_pic;
+	i8259_init(chrp_int_ack);
+
+#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
+	/* see if there is a keyboard in the device tree
+	   with a parent of type "adb" */
+	for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
+		if (kbd->parent && kbd->parent->type
+		    && strcmp(kbd->parent->type, "adb") == 0)
+			break;
+	if (kbd)
+		setup_irq(HYDRA_INT_ADB_NMI, &xmon_irqaction);
+#endif
+}
+
+void __init
+chrp_init2(void)
+{
+#ifdef CONFIG_NVRAM
+// XX replace this in a more saner way
+//	pmac_nvram_init();
+#endif
+
+	request_region(0x20,0x20,"pic1");
+	request_region(0xa0,0x20,"pic2");
+	request_region(0x00,0x20,"dma1");
+	request_region(0x40,0x20,"timer");
+	request_region(0x80,0x10,"dma page reg");
+	request_region(0xc0,0x20,"dma2");
+
+	if (ppc_md.progress)
+		ppc_md.progress("  Have fun!    ", 0x7777);
+}
+
+void __init
+chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	  unsigned long r6, unsigned long r7)
+{
+	struct device_node *root = find_path_device ("/");
+	char *machine = NULL;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* take care of initrd if we have one */
+	if ( r6 )
+	{
+		initrd_start = r6 + KERNELBASE;
+		initrd_end = r6 + r7 + KERNELBASE;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	ISA_DMA_THRESHOLD = ~0L;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+	isa_io_base = CHRP_ISA_IO_BASE;		/* default value */
+
+	if (root)
+		machine = get_property(root, "model", NULL);
+	if (machine && strncmp(machine, "Pegasos", 7) == 0) {
+		_chrp_type = _CHRP_Pegasos;
+	} else if (machine && strncmp(machine, "IBM", 3) == 0) {
+		_chrp_type = _CHRP_IBM;
+	} else if (machine && strncmp(machine, "MOT", 3) == 0) {
+		_chrp_type = _CHRP_Motorola;
+	} else {
+		/* Let's assume it is an IBM chrp if all else fails */
+		_chrp_type = _CHRP_IBM;
+	}
+
+	ppc_md.setup_arch     = chrp_setup_arch;
+	ppc_md.show_percpuinfo = of_show_percpuinfo;
+	ppc_md.show_cpuinfo   = chrp_show_cpuinfo;
+
+	ppc_md.irq_canonicalize = chrp_irq_canonicalize;
+	ppc_md.init_IRQ       = chrp_init_IRQ;
+	if (_chrp_type == _CHRP_Pegasos)
+		ppc_md.get_irq        = i8259_irq;
+	else
+		ppc_md.get_irq        = openpic_get_irq;
+
+	ppc_md.init           = chrp_init2;
+
+	ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
+
+	ppc_md.restart        = chrp_restart;
+	ppc_md.power_off      = chrp_power_off;
+	ppc_md.halt           = chrp_halt;
+
+	ppc_md.time_init      = chrp_time_init;
+	ppc_md.set_rtc_time   = chrp_set_rtc_time;
+	ppc_md.get_rtc_time   = chrp_get_rtc_time;
+	ppc_md.calibrate_decr = chrp_calibrate_decr;
+
+	ppc_md.find_end_of_memory = pmac_find_end_of_memory;
+
+	if (rtas_data) {
+		struct device_node *rtas;
+		unsigned int *p;
+
+		rtas = find_devices("rtas");
+		if (rtas != NULL) {
+			if (get_property(rtas, "display-character", NULL)) {
+				ppc_md.progress = rtas_display_progress;
+				p = (unsigned int *) get_property
+				       (rtas, "ibm,display-line-length", NULL);
+				if (p)
+					max_width = *p;
+			} else if (get_property(rtas, "set-indicator", NULL))
+				ppc_md.progress = rtas_indicator_progress;
+		}
+	}
+#ifdef CONFIG_BOOTX_TEXT
+	if (ppc_md.progress == NULL && boot_text_mapped)
+		ppc_md.progress = btext_progress;
+#endif
+
+#ifdef CONFIG_SMP
+	ppc_md.smp_ops = &chrp_smp_ops;
+#endif /* CONFIG_SMP */
+
+	/*
+	 * Print the banner, then scroll down so boot progress
+	 * can be printed.  -- Cort
+	 */
+	if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
+}
+
+void __chrp
+rtas_display_progress(char *s, unsigned short hex)
+{
+	int width;
+	char *os = s;
+
+	if ( call_rtas( "display-character", 1, 1, NULL, '\r' ) )
+		return;
+
+	width = max_width;
+	while ( *os )
+	{
+		if ( (*os == '\n') || (*os == '\r') )
+			width = max_width;
+		else
+			width--;
+		call_rtas( "display-character", 1, 1, NULL, *os++ );
+		/* if we overwrite the screen length */
+		if ( width == 0 )
+			while ( (*os != 0) && (*os != '\n') && (*os != '\r') )
+				os++;
+	}
+
+	/*while ( width-- > 0 )*/
+	call_rtas( "display-character", 1, 1, NULL, ' ' );
+}
+
+void __chrp
+rtas_indicator_progress(char *s, unsigned short hex)
+{
+	call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex);
+}
+
+#ifdef CONFIG_BOOTX_TEXT
+void
+btext_progress(char *s, unsigned short hex)
+{
+	prom_print(s);
+	prom_print("\n");
+}
+#endif /* CONFIG_BOOTX_TEXT */
diff --git a/arch/ppc/platforms/chrp_smp.c b/arch/ppc/platforms/chrp_smp.c
new file mode 100644
index 0000000..0ea1f7d
--- /dev/null
+++ b/arch/ppc/platforms/chrp_smp.c
@@ -0,0 +1,98 @@
+/*
+ * Smp support for CHRP machines.
+ *
+ * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
+ * deal of code from the sparc and intel versions.
+ *
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+
+#include <asm/ptrace.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/residual.h>
+#include <asm/time.h>
+#include <asm/open_pic.h>
+
+extern unsigned long smp_chrp_cpu_nr;
+
+static int __init
+smp_chrp_probe(void)
+{
+	if (smp_chrp_cpu_nr > 1)
+		openpic_request_IPIs();
+
+	return smp_chrp_cpu_nr;
+}
+
+static void __devinit
+smp_chrp_kick_cpu(int nr)
+{
+	*(unsigned long *)KERNELBASE = nr;
+	asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
+}
+
+static void __devinit
+smp_chrp_setup_cpu(int cpu_nr)
+{
+	if (OpenPIC_Addr)
+		do_openpic_setup_cpu();
+}
+
+static DEFINE_SPINLOCK(timebase_lock);
+static unsigned int timebase_upper = 0, timebase_lower = 0;
+
+void __devinit
+smp_chrp_give_timebase(void)
+{
+	spin_lock(&timebase_lock);
+	call_rtas("freeze-time-base", 0, 1, NULL);
+	timebase_upper = get_tbu();
+	timebase_lower = get_tbl();
+	spin_unlock(&timebase_lock);
+
+	while (timebase_upper || timebase_lower)
+		barrier();
+	call_rtas("thaw-time-base", 0, 1, NULL);
+}
+
+void __devinit
+smp_chrp_take_timebase(void)
+{
+	while (!(timebase_upper || timebase_lower))
+		barrier();
+	spin_lock(&timebase_lock);
+	set_tb(timebase_upper, timebase_lower);
+	timebase_upper = 0;
+	timebase_lower = 0;
+	spin_unlock(&timebase_lock);
+	printk("CPU %i taken timebase\n", smp_processor_id());
+}
+
+/* CHRP with openpic */
+struct smp_ops_t chrp_smp_ops __chrpdata = {
+	.message_pass = smp_openpic_message_pass,
+	.probe = smp_chrp_probe,
+	.kick_cpu = smp_chrp_kick_cpu,
+	.setup_cpu = smp_chrp_setup_cpu,
+	.give_timebase = smp_chrp_give_timebase,
+	.take_timebase = smp_chrp_take_timebase,
+};
diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c
new file mode 100644
index 0000000..e2be0c8
--- /dev/null
+++ b/arch/ppc/platforms/chrp_time.c
@@ -0,0 +1,194 @@
+/*
+ *  arch/ppc/platforms/chrp_time.c
+ *
+ *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ *
+ * Adapted for PowerPC (PReP) by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu).
+ * Copied and modified from arch/i386/kernel/time.c
+ *
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/kernel_stat.h>
+#include <linux/mc146818rtc.h>
+#include <linux/init.h>
+#include <linux/bcd.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/nvram.h>
+#include <asm/prom.h>
+#include <asm/sections.h>
+#include <asm/time.h>
+
+extern spinlock_t rtc_lock;
+
+static int nvram_as1 = NVRAM_AS1;
+static int nvram_as0 = NVRAM_AS0;
+static int nvram_data = NVRAM_DATA;
+
+long __init chrp_time_init(void)
+{
+	struct device_node *rtcs;
+	int base;
+
+	rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
+	if (rtcs == NULL)
+		rtcs = find_compatible_devices("rtc", "ds1385-rtc");
+	if (rtcs == NULL || rtcs->addrs == NULL)
+		return 0;
+	base = rtcs->addrs[0].address;
+	nvram_as1 = 0;
+	nvram_as0 = base;
+	nvram_data = base + 1;
+
+	return 0;
+}
+
+int __chrp chrp_cmos_clock_read(int addr)
+{
+	if (nvram_as1 != 0)
+		outb(addr>>8, nvram_as1);
+	outb(addr, nvram_as0);
+	return (inb(nvram_data));
+}
+
+void __chrp chrp_cmos_clock_write(unsigned long val, int addr)
+{
+	if (nvram_as1 != 0)
+		outb(addr>>8, nvram_as1);
+	outb(addr, nvram_as0);
+	outb(val, nvram_data);
+	return;
+}
+
+/*
+ * Set the hardware clock. -- Cort
+ */
+int __chrp chrp_set_rtc_time(unsigned long nowtime)
+{
+	unsigned char save_control, save_freq_select;
+	struct rtc_time tm;
+
+	spin_lock(&rtc_lock);
+	to_tm(nowtime, &tm);
+
+	save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
+
+	chrp_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = chrp_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
+
+	chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+        tm.tm_year -= 1900;
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+		BIN_TO_BCD(tm.tm_sec);
+		BIN_TO_BCD(tm.tm_min);
+		BIN_TO_BCD(tm.tm_hour);
+		BIN_TO_BCD(tm.tm_mon);
+		BIN_TO_BCD(tm.tm_mday);
+		BIN_TO_BCD(tm.tm_year);
+	}
+	chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
+	chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES);
+	chrp_cmos_clock_write(tm.tm_hour,RTC_HOURS);
+	chrp_cmos_clock_write(tm.tm_mon,RTC_MONTH);
+	chrp_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH);
+	chrp_cmos_clock_write(tm.tm_year,RTC_YEAR);
+
+	/* 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
+	 */
+	chrp_cmos_clock_write(save_control, RTC_CONTROL);
+	chrp_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);
+
+	if ( (time_state == TIME_ERROR) || (time_state == TIME_BAD) )
+		time_state = TIME_OK;
+	spin_unlock(&rtc_lock);
+	return 0;
+}
+
+unsigned long __chrp chrp_get_rtc_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	int uip, i;
+
+	/* 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.
+	 */
+
+	/* Since the UIP flag is set for about 2.2 ms and the clock
+	 * is typically written with a precision of 1 jiffy, trying
+	 * to obtain a precision better than a few milliseconds is
+	 * an illusion. Only consistency is interesting, this also
+	 * allows to use the routine for /dev/rtc without a potential
+	 * 1 second kernel busy loop triggered by any reader of /dev/rtc.
+	 */
+
+	for ( i = 0; i<1000000; i++) {
+		uip = chrp_cmos_clock_read(RTC_FREQ_SELECT);
+		sec = chrp_cmos_clock_read(RTC_SECONDS);
+		min = chrp_cmos_clock_read(RTC_MINUTES);
+		hour = chrp_cmos_clock_read(RTC_HOURS);
+		day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
+		mon = chrp_cmos_clock_read(RTC_MONTH);
+		year = chrp_cmos_clock_read(RTC_YEAR);
+		uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT);
+		if ((uip & RTC_UIP)==0) break;
+	}
+
+	if (!(chrp_cmos_clock_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);
+}
+
+
+void __init chrp_calibrate_decr(void)
+{
+	struct device_node *cpu;
+	unsigned int freq, *fp;
+
+	if (via_calibrate_decr())
+		return;
+
+	/*
+	 * The cpu node should have a timebase-frequency property
+	 * to tell us the rate at which the decrementer counts.
+	 */
+	freq = 16666000;		/* hardcoded default */
+	cpu = find_type_devices("cpu");
+	if (cpu != 0) {
+		fp = (unsigned int *)
+			get_property(cpu, "timebase-frequency", NULL);
+		if (fp != 0)
+			freq = *fp;
+	}
+	printk("time_init: decrementer frequency = %u.%.6u MHz\n",
+ 	       freq/1000000, freq%1000000);
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
diff --git a/arch/ppc/platforms/cpci690.c b/arch/ppc/platforms/cpci690.c
new file mode 100644
index 0000000..507870c
--- /dev/null
+++ b/arch/ppc/platforms/cpci690.c
@@ -0,0 +1,491 @@
+/*
+ * arch/ppc/platforms/cpci690.c
+ *
+ * Board setup routines for the Force CPCI690 board.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2003 (c) MontaVista Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This programr
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/irq.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <linux/console.h>
+#include <linux/initrd.h>
+#include <linux/root_dev.h>
+#include <linux/mv643xx.h>
+#include <asm/bootinfo.h>
+#include <asm/machdep.h>
+#include <asm/todc.h>
+#include <asm/time.h>
+#include <asm/mv64x60.h>
+#include <platforms/cpci690.h>
+
+#define BOARD_VENDOR	"Force"
+#define BOARD_MACHINE	"CPCI690"
+
+/* Set IDE controllers into Native mode? */
+#define SET_PCI_IDE_NATIVE
+
+static struct mv64x60_handle	bh;
+static u32 cpci690_br_base;
+
+static const unsigned int cpu_7xx[16] = { /* 7xx & 74xx (but not 745x) */
+	18, 15, 14, 2, 4, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+
+TODC_ALLOC();
+
+static int __init
+cpci690_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	struct pci_controller	*hose = pci_bus_to_hose(dev->bus->number);
+
+	if (hose->index == 0) {
+		static char pci_irq_table[][4] =
+		/*
+		 *	PCI IDSEL/INTPIN->INTLINE
+		 * 	   A   B   C   D
+		 */
+		{
+			{ 90, 91, 88, 89}, /* IDSEL 30/20 - Sentinel */
+		};
+
+		const long min_idsel = 20, max_idsel = 20, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	} else {
+		static char pci_irq_table[][4] =
+		/*
+		 *	PCI IDSEL/INTPIN->INTLINE
+		 * 	   A   B   C   D
+		 */
+		{
+			{ 93, 94, 95, 92}, /* IDSEL 28/18 - PMC slot 2 */
+			{  0,  0,  0,  0}, /* IDSEL 29/19 - Not used */
+			{ 94, 95, 92, 93}, /* IDSEL 30/20 - PMC slot 1 */
+		};
+
+		const long min_idsel = 18, max_idsel = 20, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	}
+}
+
+static int
+cpci690_get_cpu_speed(void)
+{
+	unsigned long	hid1;
+
+	hid1 = mfspr(SPRN_HID1) >> 28;
+	return CPCI690_BUS_FREQ * cpu_7xx[hid1]/2;
+}
+
+#define	KB	(1024UL)
+#define	MB	(1024UL * KB)
+#define	GB	(1024UL * MB)
+
+unsigned long __init
+cpci690_find_end_of_memory(void)
+{
+	u32		mem_ctlr_size;
+	static u32	board_size;
+	static u8	first_time = 1;
+
+	if (first_time) {
+		/* Using cpci690_set_bat() mapping ==> virt addr == phys addr */
+		switch (in_8((u8 *) (cpci690_br_base +
+			CPCI690_BR_MEM_CTLR)) & 0x07) {
+		case 0x01:
+			board_size = 256*MB;
+			break;
+		case 0x02:
+			board_size = 512*MB;
+			break;
+		case 0x03:
+			board_size = 768*MB;
+			break;
+		case 0x04:
+			board_size = 1*GB;
+			break;
+		case 0x05:
+			board_size = 1*GB + 512*MB;
+			break;
+		case 0x06:
+			board_size = 2*GB;
+			break;
+		default:
+			board_size = 0xffffffff; /* use mem ctlr size */
+		} /* switch */
+
+		mem_ctlr_size =  mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
+			MV64x60_TYPE_GT64260A);
+
+		/* Check that mem ctlr & board reg agree.  If not, pick MIN. */
+		if (board_size != mem_ctlr_size) {
+			printk(KERN_WARNING "Board register & memory controller"
+				"mem size disagree (board reg: 0x%lx, "
+				"mem ctlr: 0x%lx)\n",
+				(ulong)board_size, (ulong)mem_ctlr_size);
+			board_size = min(board_size, mem_ctlr_size);
+		}
+
+		first_time = 0;
+	} /* if */
+
+	return board_size;
+}
+
+static void __init
+cpci690_setup_bridge(void)
+{
+	struct mv64x60_setup_info	si;
+	int				i;
+
+	memset(&si, 0, sizeof(si));
+
+	si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
+
+	si.pci_0.enable_bus = 1;
+	si.pci_0.pci_io.cpu_base = CPCI690_PCI0_IO_START_PROC_ADDR;
+	si.pci_0.pci_io.pci_base_hi = 0;
+	si.pci_0.pci_io.pci_base_lo = CPCI690_PCI0_IO_START_PCI_ADDR;
+	si.pci_0.pci_io.size = CPCI690_PCI0_IO_SIZE;
+	si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_0.pci_mem[0].cpu_base = CPCI690_PCI0_MEM_START_PROC_ADDR;
+	si.pci_0.pci_mem[0].pci_base_hi = CPCI690_PCI0_MEM_START_PCI_HI_ADDR;
+	si.pci_0.pci_mem[0].pci_base_lo = CPCI690_PCI0_MEM_START_PCI_LO_ADDR;
+	si.pci_0.pci_mem[0].size = CPCI690_PCI0_MEM_SIZE;
+	si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_0.pci_cmd_bits = 0;
+	si.pci_0.latency_timer = 0x80;
+
+	si.pci_1.enable_bus = 1;
+	si.pci_1.pci_io.cpu_base = CPCI690_PCI1_IO_START_PROC_ADDR;
+	si.pci_1.pci_io.pci_base_hi = 0;
+	si.pci_1.pci_io.pci_base_lo = CPCI690_PCI1_IO_START_PCI_ADDR;
+	si.pci_1.pci_io.size = CPCI690_PCI1_IO_SIZE;
+	si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_1.pci_mem[0].cpu_base = CPCI690_PCI1_MEM_START_PROC_ADDR;
+	si.pci_1.pci_mem[0].pci_base_hi = CPCI690_PCI1_MEM_START_PCI_HI_ADDR;
+	si.pci_1.pci_mem[0].pci_base_lo = CPCI690_PCI1_MEM_START_PCI_LO_ADDR;
+	si.pci_1.pci_mem[0].size = CPCI690_PCI1_MEM_SIZE;
+	si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_1.pci_cmd_bits = 0;
+	si.pci_1.latency_timer = 0x80;
+
+	for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) {
+		si.cpu_prot_options[i] = 0;
+		si.cpu_snoop_options[i] = GT64260_CPU_SNOOP_WB;
+		si.pci_0.acc_cntl_options[i] =
+			GT64260_PCI_ACC_CNTL_DREADEN |
+			GT64260_PCI_ACC_CNTL_RDPREFETCH |
+			GT64260_PCI_ACC_CNTL_RDLINEPREFETCH |
+			GT64260_PCI_ACC_CNTL_RDMULPREFETCH |
+			GT64260_PCI_ACC_CNTL_SWAP_NONE |
+			GT64260_PCI_ACC_CNTL_MBURST_32_BTYES;
+		si.pci_0.snoop_options[i] = GT64260_PCI_SNOOP_WB;
+		si.pci_1.acc_cntl_options[i] =
+			GT64260_PCI_ACC_CNTL_DREADEN |
+			GT64260_PCI_ACC_CNTL_RDPREFETCH |
+			GT64260_PCI_ACC_CNTL_RDLINEPREFETCH |
+			GT64260_PCI_ACC_CNTL_RDMULPREFETCH |
+			GT64260_PCI_ACC_CNTL_SWAP_NONE |
+			GT64260_PCI_ACC_CNTL_MBURST_32_BTYES;
+		si.pci_1.snoop_options[i] = GT64260_PCI_SNOOP_WB;
+	}
+
+        /* Lookup PCI host bridges */
+        if (mv64x60_init(&bh, &si))
+                printk(KERN_ERR "Bridge initialization failed.\n");
+
+	pci_dram_offset = 0; /* System mem at same addr on PCI & cpu bus */
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = cpci690_map_irq;
+	ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
+
+	mv64x60_set_bus(&bh, 0, 0);
+	bh.hose_a->first_busno = 0;
+	bh.hose_a->last_busno = 0xff;
+	bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
+
+	bh.hose_b->first_busno = bh.hose_a->last_busno + 1;
+	mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno);
+	bh.hose_b->last_busno = 0xff;
+	bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b,
+		bh.hose_b->first_busno);
+}
+
+static void __init
+cpci690_setup_peripherals(void)
+{
+	/* Set up windows to CPLD, RTC/TODC, IPMI. */
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, CPCI690_BR_BASE,
+		CPCI690_BR_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
+	cpci690_br_base = (u32)ioremap(CPCI690_BR_BASE, CPCI690_BR_SIZE);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, CPCI690_TODC_BASE,
+		CPCI690_TODC_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+	TODC_INIT(TODC_TYPE_MK48T35, 0, 0,
+			ioremap(CPCI690_TODC_BASE, CPCI690_TODC_SIZE), 8);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN, CPCI690_IPMI_BASE,
+		CPCI690_IPMI_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+
+	mv64x60_set_bits(&bh, MV64x60_PCI0_ARBITER_CNTL, (1<<31));
+	mv64x60_set_bits(&bh, MV64x60_PCI1_ARBITER_CNTL, (1<<31));
+
+        mv64x60_set_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1<<9)); /* Only 1 cpu */
+
+	/*
+	 * Turn off timer/counters.  Not turning off watchdog timer because
+	 * can't read its reg on the 64260A so don't know if we'll be enabling
+	 * or disabling.
+	 */
+	mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL,
+			((1<<0) | (1<<8) | (1<<16) | (1<<24)));
+	mv64x60_clr_bits(&bh, GT64260_TIMR_CNTR_4_7_CNTL,
+			((1<<0) | (1<<8) | (1<<16) | (1<<24)));
+
+	/*
+	 * Set MPSC Multiplex RMII
+	 * NOTE: ethernet driver modifies bit 0 and 1
+	 */
+	mv64x60_write(&bh, GT64260_MPP_SERIAL_PORTS_MULTIPLEX, 0x00001102);
+
+#define GPP_EXTERNAL_INTERRUPTS \
+		((1<<24) | (1<<25) | (1<<26) | (1<<27) | \
+		 (1<<28) | (1<<29) | (1<<30) | (1<<31))
+	/* PCI interrupts are inputs */
+	mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, GPP_EXTERNAL_INTERRUPTS);
+	/* PCI interrupts are active low */
+	mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, GPP_EXTERNAL_INTERRUPTS);
+
+	/* Clear any pending interrupts for these inputs and enable them. */
+	mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~GPP_EXTERNAL_INTERRUPTS);
+	mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, GPP_EXTERNAL_INTERRUPTS);
+
+	/* Route MPP interrupt inputs to GPP */
+	mv64x60_write(&bh, MV64x60_MPP_CNTL_2, 0x00000000);
+	mv64x60_write(&bh, MV64x60_MPP_CNTL_3, 0x00000000);
+}
+
+static void __init
+cpci690_setup_arch(void)
+{
+	if (ppc_md.progress)
+		ppc_md.progress("cpci690_setup_arch: enter", 0);
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef   CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA2;
+#endif
+
+	if (ppc_md.progress)
+		ppc_md.progress("cpci690_setup_arch: Enabling L2 cache", 0);
+
+	/* Enable L2 and L3 caches (if 745x) */
+	_set_L2CR(_get_L2CR() | L2CR_L2E);
+	_set_L3CR(_get_L3CR() | L3CR_L3E);
+
+	if (ppc_md.progress)
+		ppc_md.progress("cpci690_setup_arch: Initializing bridge", 0);
+
+	cpci690_setup_bridge();		/* set up PCI bridge(s) */
+	cpci690_setup_peripherals();	/* set up chip selects/GPP/MPP etc */
+
+	if (ppc_md.progress)
+		ppc_md.progress("cpci690_setup_arch: bridge init complete", 0);
+
+	printk(KERN_INFO "%s %s port (C) 2003 MontaVista Software, Inc. "
+		"(source@mvista.com)\n", BOARD_VENDOR, BOARD_MACHINE);
+
+	if (ppc_md.progress)
+		ppc_md.progress("cpci690_setup_arch: exit", 0);
+}
+
+/* Platform device data fixup routines. */
+#if defined(CONFIG_SERIAL_MPSC)
+static void __init
+cpci690_fixup_mpsc_pdata(struct platform_device *pdev)
+{
+	struct mpsc_pdata *pdata;
+
+	pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
+
+	pdata->max_idle = 40;
+	pdata->default_baud = CPCI690_MPSC_BAUD;
+	pdata->brg_clk_src = CPCI690_MPSC_CLK_SRC;
+	pdata->brg_clk_freq = CPCI690_BUS_FREQ;
+}
+
+static int __init
+cpci690_platform_notify(struct device *dev)
+{
+	static struct {
+		char	*bus_id;
+		void	((*rtn)(struct platform_device *pdev));
+	} dev_map[] = {
+		{ MPSC_CTLR_NAME ".0", cpci690_fixup_mpsc_pdata },
+		{ MPSC_CTLR_NAME ".1", cpci690_fixup_mpsc_pdata },
+	};
+	struct platform_device	*pdev;
+	int	i;
+
+	if (dev && dev->bus_id)
+		for (i=0; i<ARRAY_SIZE(dev_map); i++)
+			if (!strncmp(dev->bus_id, dev_map[i].bus_id,
+				BUS_ID_SIZE)) {
+
+				pdev = container_of(dev,
+					struct platform_device, dev);
+				dev_map[i].rtn(pdev);
+			}
+
+	return 0;
+}
+#endif
+
+static void
+cpci690_reset_board(void)
+{
+	u32	i = 10000;
+
+	local_irq_disable();
+	out_8((u8 *)(cpci690_br_base + CPCI690_BR_SW_RESET), 0x11);
+
+	while (i != 0) i++;
+	panic("restart failed\n");
+}
+
+static void
+cpci690_restart(char *cmd)
+{
+	cpci690_reset_board();
+}
+
+static void
+cpci690_halt(void)
+{
+	while (1);
+	/* NOTREACHED */
+}
+
+static void
+cpci690_power_off(void)
+{
+	cpci690_halt();
+	/* NOTREACHED */
+}
+
+static int
+cpci690_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: " BOARD_VENDOR "\n");
+	seq_printf(m, "machine\t\t: " BOARD_MACHINE "\n");
+	seq_printf(m, "cpu MHz\t\t: %d\n", cpci690_get_cpu_speed()/1000/1000);
+	seq_printf(m, "bus MHz\t\t: %d\n", CPCI690_BUS_FREQ/1000/1000);
+
+	return 0;
+}
+
+static void __init
+cpci690_calibrate_decr(void)
+{
+	ulong freq;
+
+	freq = CPCI690_BUS_FREQ / 4;
+
+	printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+	       freq/1000000, freq%1000000);
+
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
+
+static __inline__ void
+cpci690_set_bat(u32 addr, u32 size)
+{
+	addr &= 0xfffe0000;
+	size &= 0x1ffe0000;
+	size = ((size >> 17) - 1) << 2;
+
+	mb();
+	mtspr(SPRN_DBAT1U, addr | size | 0x2); /* Vs == 1; Vp == 0 */
+	mtspr(SPRN_DBAT1L, addr | 0x2a); /* WIMG bits == 0101; PP == r/w access */
+	mb();
+}
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+static void __init
+cpci690_map_io(void)
+{
+	io_block_mapping(CONFIG_MV64X60_NEW_BASE, CONFIG_MV64X60_NEW_BASE,
+		128 * KB, _PAGE_IO);
+}
+#endif
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+	initrd_start=initrd_end=0;
+	initrd_below_start_ok=0;
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	parse_bootinfo(find_bootinfo());
+
+	loops_per_jiffy = cpci690_get_cpu_speed() / HZ;
+
+	isa_mem_base = 0;
+
+	ppc_md.setup_arch = cpci690_setup_arch;
+	ppc_md.show_cpuinfo = cpci690_show_cpuinfo;
+	ppc_md.init_IRQ = gt64260_init_irq;
+	ppc_md.get_irq = gt64260_get_irq;
+	ppc_md.restart = cpci690_restart;
+	ppc_md.power_off = cpci690_power_off;
+	ppc_md.halt = cpci690_halt;
+	ppc_md.find_end_of_memory = cpci690_find_end_of_memory;
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+	ppc_md.calibrate_decr = cpci690_calibrate_decr;
+
+	/*
+	 * Need to map in board regs (used by cpci690_find_end_of_memory())
+	 * and the bridge's regs (used by progress);
+	 */
+	cpci690_set_bat(CPCI690_BR_BASE, 32 * MB);
+	cpci690_br_base = CPCI690_BR_BASE;
+
+#ifdef	CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.setup_io_mappings = cpci690_map_io;
+	ppc_md.progress = mv64x60_mpsc_progress;
+	mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
+#endif	/* CONFIG_SERIAL_TEXT_DEBUG */
+#ifdef	CONFIG_KGDB
+	ppc_md.setup_io_mappings = cpci690_map_io;
+	ppc_md.early_serial_map = cpci690_early_serial_map;
+#endif	/* CONFIG_KGDB */
+
+#if defined(CONFIG_SERIAL_MPSC)
+	platform_notify = cpci690_platform_notify;
+#endif
+}
diff --git a/arch/ppc/platforms/cpci690.h b/arch/ppc/platforms/cpci690.h
new file mode 100644
index 0000000..36cd267
--- /dev/null
+++ b/arch/ppc/platforms/cpci690.h
@@ -0,0 +1,78 @@
+/*
+ * arch/ppc/platforms/cpci690.h
+ *
+ * Definitions for Force CPCI690
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2003 (c) MontaVista, Software, Inc.  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.
+ */
+
+/*
+ * The GT64260 has 2 PCI buses each with 1 window from the CPU bus to
+ * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
+ */
+
+#ifndef __PPC_PLATFORMS_CPCI690_H
+#define __PPC_PLATFORMS_CPCI690_H
+
+/*
+ * Define bd_t to pass in the MAC addresses used by the GT64260's enet ctlrs.
+ */
+#define	CPCI690_BI_MAGIC		0xFE8765DC
+
+typedef struct board_info {
+	u32	bi_magic;
+	u8	bi_enetaddr[3][6];
+} bd_t;
+
+/* PCI bus Resource setup */
+#define CPCI690_PCI0_MEM_START_PROC_ADDR	0x80000000
+#define CPCI690_PCI0_MEM_START_PCI_HI_ADDR	0x00000000
+#define CPCI690_PCI0_MEM_START_PCI_LO_ADDR	0x80000000
+#define CPCI690_PCI0_MEM_SIZE			0x10000000
+#define CPCI690_PCI0_IO_START_PROC_ADDR		0xa0000000
+#define CPCI690_PCI0_IO_START_PCI_ADDR		0x00000000
+#define CPCI690_PCI0_IO_SIZE			0x01000000
+
+#define CPCI690_PCI1_MEM_START_PROC_ADDR	0x90000000
+#define CPCI690_PCI1_MEM_START_PCI_HI_ADDR	0x00000000
+#define CPCI690_PCI1_MEM_START_PCI_LO_ADDR	0x90000000
+#define CPCI690_PCI1_MEM_SIZE			0x10000000
+#define CPCI690_PCI1_IO_START_PROC_ADDR		0xa1000000
+#define CPCI690_PCI1_IO_START_PCI_ADDR		0x01000000
+#define CPCI690_PCI1_IO_SIZE			0x01000000
+
+/* Board Registers */
+#define	CPCI690_BR_BASE				0xf0000000
+#define	CPCI690_BR_SIZE_ACTUAL			0x8
+#define	CPCI690_BR_SIZE			max(GT64260_WINDOW_SIZE_MIN,	\
+						CPCI690_BR_SIZE_ACTUAL)
+#define	CPCI690_BR_LED_CNTL			0x00
+#define	CPCI690_BR_SW_RESET			0x01
+#define	CPCI690_BR_MISC_STATUS			0x02
+#define	CPCI690_BR_SWITCH_STATUS		0x03
+#define	CPCI690_BR_MEM_CTLR			0x04
+#define	CPCI690_BR_LAST_RESET_1			0x05
+#define	CPCI690_BR_LAST_RESET_2			0x06
+
+#define	CPCI690_TODC_BASE			0xf0100000
+#define	CPCI690_TODC_SIZE_ACTUAL		0x8000 /* Size or NVRAM + RTC */
+#define	CPCI690_TODC_SIZE		max(GT64260_WINDOW_SIZE_MIN,	\
+						CPCI690_TODC_SIZE_ACTUAL)
+#define	CPCI690_MAC_OFFSET			0x7c10 /* MAC in RTC NVRAM */
+
+#define	CPCI690_IPMI_BASE			0xf0200000
+#define	CPCI690_IPMI_SIZE_ACTUAL		0x10 /* 16 bytes of IPMI */
+#define	CPCI690_IPMI_SIZE		max(GT64260_WINDOW_SIZE_MIN,	\
+						CPCI690_IPMI_SIZE_ACTUAL)
+
+#define	CPCI690_MPSC_BAUD			9600
+#define	CPCI690_MPSC_CLK_SRC			8 /* TCLK */
+
+#define	CPCI690_BUS_FREQ			133333333
+
+#endif /* __PPC_PLATFORMS_CPCI690_H */
diff --git a/arch/ppc/platforms/est8260.h b/arch/ppc/platforms/est8260.h
new file mode 100644
index 0000000..adba68e
--- /dev/null
+++ b/arch/ppc/platforms/est8260.h
@@ -0,0 +1,35 @@
+/* Board information for the EST8260, which should be generic for
+ * all 8260 boards.  The IMMR is now given to us so the hard define
+ * will soon be removed.  All of the clock values are computed from
+ * the configuration SCMR and the Power-On-Reset word.
+ */
+#ifndef __EST8260_PLATFORM
+#define __EST8260_PLATFORM
+
+#define CPM_MAP_ADDR		((uint)0xf0000000)
+
+#define BOOTROM_RESTART_ADDR	((uint)0xff000104)
+
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"EST Corporation"
+#define CPUINFO_MACHINE		"SBC8260 PowerPC"
+
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in MHz */
+	unsigned int	bi_cpmfreq;	/* CPM Freq, in MHz */
+	unsigned int	bi_brgfreq;	/* BRG Freq, in MHz */
+	unsigned int	bi_vco;		/* VCO Out from PLL */
+	unsigned int	bi_baudrate;	/* Default console baud rate */
+	unsigned int	bi_immr;	/* IMMR when called from boot rom */
+	unsigned char	bi_enetaddr[6];
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+#endif 	/* __EST8260_PLATFORM */
diff --git a/arch/ppc/platforms/ev64260.c b/arch/ppc/platforms/ev64260.c
new file mode 100644
index 0000000..aa50637
--- /dev/null
+++ b/arch/ppc/platforms/ev64260.c
@@ -0,0 +1,651 @@
+/*
+ * arch/ppc/platforms/ev64260.c
+ *
+ * Board setup routines for the Marvell/Galileo EV-64260-BP Evaluation Board.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2001-2003 (c) MontaVista, Software, Inc.  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.
+ */
+
+/*
+ * The EV-64260-BP port is the result of hard work from many people from
+ * many companies.  In particular, employees of Marvell/Galileo, Mission
+ * Critical Linux, Xyterra, and MontaVista Software were heavily involved.
+ *
+ * Note: I have not been able to get *all* PCI slots to work reliably
+ *	at 66 MHz.  I recommend setting jumpers J15 & J16 to short pins 1&2
+ *	so that 33 MHz is used. --MAG
+ * Note: The 750CXe and 7450 are not stable with a 125MHz or 133MHz TCLK/SYSCLK.
+ * 	At 100MHz, they are solid.
+ */
+#include <linux/config.h>
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/irq.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <linux/console.h>
+#include <linux/initrd.h>
+#include <linux/root_dev.h>
+#if !defined(CONFIG_SERIAL_MPSC_CONSOLE)
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#else
+#include <linux/mv643xx.h>
+#endif
+#include <asm/bootinfo.h>
+#include <asm/machdep.h>
+#include <asm/mv64x60.h>
+#include <asm/todc.h>
+#include <asm/time.h>
+
+#include <platforms/ev64260.h>
+
+#define BOARD_VENDOR	"Marvell/Galileo"
+#define BOARD_MACHINE	"EV-64260-BP"
+
+static struct mv64x60_handle	bh;
+
+#if !defined(CONFIG_SERIAL_MPSC_CONSOLE)
+extern void gen550_progress(char *, unsigned short);
+extern void gen550_init(int, struct uart_port *);
+#endif
+
+static const unsigned int cpu_7xx[16] = { /* 7xx & 74xx (but not 745x) */
+	18, 15, 14, 2, 4, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+static const unsigned int cpu_745x[2][16] = { /* PLL_EXT 0 & 1 */
+	{ 1, 15, 14,  2,  4, 13,  5,  9,  6, 11,  8, 10, 16, 12,  7,  0 },
+	{ 0, 30,  0,  2,  0, 26,  0, 18,  0, 22, 20, 24, 28, 32,  0,  0 }
+};
+
+
+TODC_ALLOC();
+
+static int
+ev64260_get_bus_speed(void)
+{
+	return 100000000;
+}
+
+static int
+ev64260_get_cpu_speed(void)
+{
+	unsigned long	pvr, hid1, pll_ext;
+
+	pvr = PVR_VER(mfspr(SPRN_PVR));
+
+	if (pvr != PVR_VER(PVR_7450)) {
+		hid1 = mfspr(SPRN_HID1) >> 28;
+		return ev64260_get_bus_speed() * cpu_7xx[hid1]/2;
+	}
+	else {
+		hid1 = (mfspr(SPRN_HID1) & 0x0001e000) >> 13;
+		pll_ext = 0; /* No way to read; must get from schematic */
+		return ev64260_get_bus_speed() * cpu_745x[pll_ext][hid1]/2;
+	}
+}
+
+unsigned long __init
+ev64260_find_end_of_memory(void)
+{
+	return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
+		MV64x60_TYPE_GT64260A);
+}
+
+/*
+ * Marvell/Galileo EV-64260-BP Evaluation Board PCI interrupt routing.
+ * Note: By playing with J8 and JP1-4, you can get 2 IRQ's from the first
+ *	PCI bus (in which cast, INTPIN B would be EV64260_PCI_1_IRQ).
+ *	This is the most IRQs you can get from one bus with this board, though.
+ */
+static int __init
+ev64260_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	struct pci_controller	*hose = pci_bus_to_hose(dev->bus->number);
+
+	if (hose->index == 0) {
+		static char pci_irq_table[][4] =
+		/*
+		 *	PCI IDSEL/INTPIN->INTLINE
+		 * 	   A   B   C   D
+		 */
+		{
+			{EV64260_PCI_0_IRQ,0,0,0}, /* IDSEL 7 - PCI bus 0 */
+			{EV64260_PCI_0_IRQ,0,0,0}, /* IDSEL 8 - PCI bus 0 */
+		};
+
+		const long min_idsel = 7, max_idsel = 8, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	}
+	else {
+		static char pci_irq_table[][4] =
+		/*
+		 *	PCI IDSEL/INTPIN->INTLINE
+		 * 	   A   B   C   D
+		 */
+		{
+			{ EV64260_PCI_1_IRQ,0,0,0}, /* IDSEL 7 - PCI bus 1 */
+			{ EV64260_PCI_1_IRQ,0,0,0}, /* IDSEL 8 - PCI bus 1 */
+		};
+
+		const long min_idsel = 7, max_idsel = 8, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	}
+}
+
+static void __init
+ev64260_setup_peripherals(void)
+{
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+		EV64260_EMB_FLASH_BASE, EV64260_EMB_FLASH_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN,
+		EV64260_EXT_SRAM_BASE, EV64260_EXT_SRAM_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,
+		EV64260_TODC_BASE, EV64260_TODC_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN,
+		EV64260_UART_BASE, EV64260_UART_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN,
+		EV64260_EXT_FLASH_BASE, EV64260_EXT_FLASH_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
+
+	TODC_INIT(TODC_TYPE_DS1501, 0, 0,
+			ioremap(EV64260_TODC_BASE, EV64260_TODC_SIZE), 8);
+
+	mv64x60_clr_bits(&bh, MV64x60_CPU_CONFIG,((1<<12) | (1<<28) | (1<<29)));
+	mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1<<27));
+
+	if (ev64260_get_bus_speed() > 100000000)
+		mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1<<23));
+
+	mv64x60_set_bits(&bh, MV64x60_PCI0_PCI_DECODE_CNTL, ((1<<0) | (1<<3)));
+	mv64x60_set_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, ((1<<0) | (1<<3)));
+
+        /*
+         * Enabling of PCI internal-vs-external arbitration
+         * is a platform- and errata-dependent decision.
+         */
+        if (bh.type == MV64x60_TYPE_GT64260A )  {
+                mv64x60_set_bits(&bh, MV64x60_PCI0_ARBITER_CNTL, (1<<31));
+                mv64x60_set_bits(&bh, MV64x60_PCI1_ARBITER_CNTL, (1<<31));
+        }
+
+        mv64x60_set_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1<<9)); /* Only 1 cpu */
+
+	/*
+	 * Turn off timer/counters.  Not turning off watchdog timer because
+	 * can't read its reg on the 64260A so don't know if we'll be enabling
+	 * or disabling.
+	 */
+	mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL,
+			((1<<0) | (1<<8) | (1<<16) | (1<<24)));
+	mv64x60_clr_bits(&bh, GT64260_TIMR_CNTR_4_7_CNTL,
+			((1<<0) | (1<<8) | (1<<16) | (1<<24)));
+
+	/*
+	 * Set MPSC Multiplex RMII
+	 * NOTE: ethernet driver modifies bit 0 and 1
+	 */
+	mv64x60_write(&bh, GT64260_MPP_SERIAL_PORTS_MULTIPLEX, 0x00001102);
+
+	/*
+	 * The EV-64260-BP uses several Multi-Purpose Pins (MPP) on the 64260
+	 * bridge as interrupt inputs (via the General Purpose Ports (GPP)
+	 * register).  Need to route the MPP inputs to the GPP and set the
+	 * polarity correctly.
+	 *
+	 * In MPP Control 2 Register
+	 *   MPP 21 -> GPP 21 (DUART channel A intr) bits 20-23 -> 0
+	 *   MPP 22 -> GPP 22 (DUART channel B intr) bits 24-27 -> 0
+	 */
+	mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_2, (0xf<<20) | (0xf<<24) );
+
+	/*
+	 * In MPP Control 3 Register
+	 *   MPP 26 -> GPP 26 (RTC INT)		bits  8-11 -> 0
+	 *   MPP 27 -> GPP 27 (PCI 0 INTA)	bits 12-15 -> 0
+	 *   MPP 29 -> GPP 29 (PCI 1 INTA)	bits 20-23 -> 0
+	 */
+	mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_3, (0xf<<8)|(0xf<<12)|(0xf<<20));
+
+#define GPP_EXTERNAL_INTERRUPTS \
+		((1<<21) | (1<<22) | (1<<26) | (1<<27) | (1<<29))
+	/* DUART & PCI interrupts are inputs */
+	mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, GPP_EXTERNAL_INTERRUPTS);
+	/* DUART & PCI interrupts are active low */
+	mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, GPP_EXTERNAL_INTERRUPTS);
+
+	/* Clear any pending interrupts for these inputs and enable them. */
+	mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~GPP_EXTERNAL_INTERRUPTS);
+	mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, GPP_EXTERNAL_INTERRUPTS);
+
+	return;
+}
+
+static void __init
+ev64260_setup_bridge(void)
+{
+	struct mv64x60_setup_info	si;
+	int				i;
+
+	memset(&si, 0, sizeof(si));
+
+	si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
+
+	si.pci_0.enable_bus = 1;
+	si.pci_0.pci_io.cpu_base = EV64260_PCI0_IO_CPU_BASE;
+	si.pci_0.pci_io.pci_base_hi = 0;
+	si.pci_0.pci_io.pci_base_lo = EV64260_PCI0_IO_PCI_BASE;
+	si.pci_0.pci_io.size = EV64260_PCI0_IO_SIZE;
+	si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_0.pci_mem[0].cpu_base = EV64260_PCI0_MEM_CPU_BASE;
+	si.pci_0.pci_mem[0].pci_base_hi = 0;
+	si.pci_0.pci_mem[0].pci_base_lo = EV64260_PCI0_MEM_PCI_BASE;
+	si.pci_0.pci_mem[0].size = EV64260_PCI0_MEM_SIZE;
+	si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_0.pci_cmd_bits = 0;
+	si.pci_0.latency_timer = 0x8;
+
+	si.pci_1.enable_bus = 1;
+	si.pci_1.pci_io.cpu_base = EV64260_PCI1_IO_CPU_BASE;
+	si.pci_1.pci_io.pci_base_hi = 0;
+	si.pci_1.pci_io.pci_base_lo = EV64260_PCI1_IO_PCI_BASE;
+	si.pci_1.pci_io.size = EV64260_PCI1_IO_SIZE;
+	si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_1.pci_mem[0].cpu_base = EV64260_PCI1_MEM_CPU_BASE;
+	si.pci_1.pci_mem[0].pci_base_hi = 0;
+	si.pci_1.pci_mem[0].pci_base_lo = EV64260_PCI1_MEM_PCI_BASE;
+	si.pci_1.pci_mem[0].size = EV64260_PCI1_MEM_SIZE;
+	si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_1.pci_cmd_bits = 0;
+	si.pci_1.latency_timer = 0x8;
+
+	for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) {
+		si.cpu_prot_options[i] = 0;
+		si.cpu_snoop_options[i] = GT64260_CPU_SNOOP_WB;
+		si.pci_0.acc_cntl_options[i] =
+			GT64260_PCI_ACC_CNTL_DREADEN |
+			GT64260_PCI_ACC_CNTL_RDPREFETCH |
+			GT64260_PCI_ACC_CNTL_RDLINEPREFETCH |
+			GT64260_PCI_ACC_CNTL_RDMULPREFETCH |
+			GT64260_PCI_ACC_CNTL_SWAP_NONE |
+			GT64260_PCI_ACC_CNTL_MBURST_32_BTYES;
+		si.pci_0.snoop_options[i] = GT64260_PCI_SNOOP_WB;
+		si.pci_1.acc_cntl_options[i] =
+			GT64260_PCI_ACC_CNTL_DREADEN |
+			GT64260_PCI_ACC_CNTL_RDPREFETCH |
+			GT64260_PCI_ACC_CNTL_RDLINEPREFETCH |
+			GT64260_PCI_ACC_CNTL_RDMULPREFETCH |
+			GT64260_PCI_ACC_CNTL_SWAP_NONE |
+			GT64260_PCI_ACC_CNTL_MBURST_32_BTYES;
+		si.pci_1.snoop_options[i] = GT64260_PCI_SNOOP_WB;
+	}
+
+        /* Lookup PCI host bridges */
+        if (mv64x60_init(&bh, &si))
+                printk(KERN_ERR "Bridge initialization failed.\n");
+
+	pci_dram_offset = 0; /* System mem at same addr on PCI & cpu bus */
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = ev64260_map_irq;
+	ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
+
+	mv64x60_set_bus(&bh, 0, 0);
+	bh.hose_a->first_busno = 0;
+	bh.hose_a->last_busno = 0xff;
+	bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
+
+	bh.hose_b->first_busno = bh.hose_a->last_busno + 1;
+	mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno);
+	bh.hose_b->last_busno = 0xff;
+	bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b,
+		bh.hose_b->first_busno);
+
+	return;
+}
+
+#if defined(CONFIG_SERIAL_8250) && !defined(CONFIG_SERIAL_MPSC_CONSOLE)
+static void __init
+ev64260_early_serial_map(void)
+{
+	struct uart_port	port;
+	static char		first_time = 1;
+
+	if (first_time) {
+		memset(&port, 0, sizeof(port));
+
+		port.membase = ioremap(EV64260_SERIAL_0, EV64260_UART_SIZE);
+		port.irq = EV64260_UART_0_IRQ;
+		port.uartclk = BASE_BAUD * 16;
+		port.regshift = 2;
+		port.iotype = SERIAL_IO_MEM;
+		port.flags = STD_COM_FLAGS;
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+		gen550_init(0, &port);
+#endif
+
+		if (early_serial_setup(&port) != 0)
+			printk(KERN_WARNING "Early serial init of port 0"
+				"failed\n");
+
+		first_time = 0;
+	}
+
+	return;
+}
+#elif defined(CONFIG_SERIAL_MPSC_CONSOLE)
+static void __init
+ev64260_early_serial_map(void)
+{
+}
+#endif
+
+static void __init
+ev64260_setup_arch(void)
+{
+	if (ppc_md.progress)
+		ppc_md.progress("ev64260_setup_arch: enter", 0);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef	CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA2;
+#endif
+
+	if (ppc_md.progress)
+		ppc_md.progress("ev64260_setup_arch: Enabling L2 cache", 0);
+
+	/* Enable L2 and L3 caches (if 745x) */
+	_set_L2CR(_get_L2CR() | L2CR_L2E);
+	_set_L3CR(_get_L3CR() | L3CR_L3E);
+
+	if (ppc_md.progress)
+		ppc_md.progress("ev64260_setup_arch: Initializing bridge", 0);
+
+	ev64260_setup_bridge();		/* set up PCI bridge(s) */
+	ev64260_setup_peripherals();	/* set up chip selects/GPP/MPP etc */
+
+	if (ppc_md.progress)
+		ppc_md.progress("ev64260_setup_arch: bridge init complete", 0);
+
+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_MPSC_CONSOLE)
+	ev64260_early_serial_map();
+#endif
+
+	printk(KERN_INFO "%s %s port (C) 2001 MontaVista Software, Inc."
+		"(source@mvista.com)\n", BOARD_VENDOR, BOARD_MACHINE);
+
+	if (ppc_md.progress)
+		ppc_md.progress("ev64260_setup_arch: exit", 0);
+
+	return;
+}
+
+/* Platform device data fixup routines. */
+#if defined(CONFIG_SERIAL_MPSC)
+static void __init
+ev64260_fixup_mpsc_pdata(struct platform_device *pdev)
+{
+	struct mpsc_pdata *pdata;
+
+	pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
+
+	pdata->max_idle = 40;
+	pdata->default_baud = EV64260_DEFAULT_BAUD;
+	pdata->brg_clk_src = EV64260_MPSC_CLK_SRC;
+	pdata->brg_clk_freq = EV64260_MPSC_CLK_FREQ;
+
+	return;
+}
+
+static int __init
+ev64260_platform_notify(struct device *dev)
+{
+	static struct {
+		char	*bus_id;
+		void	((*rtn)(struct platform_device *pdev));
+	} dev_map[] = {
+		{ MPSC_CTLR_NAME ".0", ev64260_fixup_mpsc_pdata },
+		{ MPSC_CTLR_NAME ".1", ev64260_fixup_mpsc_pdata },
+	};
+	struct platform_device	*pdev;
+	int	i;
+
+	if (dev && dev->bus_id)
+		for (i=0; i<ARRAY_SIZE(dev_map); i++)
+			if (!strncmp(dev->bus_id, dev_map[i].bus_id,
+				BUS_ID_SIZE)) {
+
+				pdev = container_of(dev,
+					struct platform_device, dev);
+				dev_map[i].rtn(pdev);
+			}
+
+	return 0;
+}
+#endif
+
+static void
+ev64260_reset_board(void *addr)
+{
+	local_irq_disable();
+
+	/* disable and invalidate the L2 cache */
+	_set_L2CR(0);
+	_set_L2CR(0x200000);
+
+	/* flush and disable L1 I/D cache */
+	__asm__ __volatile__
+	("mfspr   3,1008\n\t"
+	 "ori	5,5,0xcc00\n\t"
+	 "ori	4,3,0xc00\n\t"
+	 "andc	5,3,5\n\t"
+	 "sync\n\t"
+	 "mtspr	1008,4\n\t"
+	 "isync\n\t"
+	 "sync\n\t"
+	 "mtspr	1008,5\n\t"
+	 "isync\n\t"
+	 "sync\n\t");
+
+	/* unmap any other random cs's that might overlap with bootcs */
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, 0, 0, 0);
+	bh.ci->disable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, 0, 0, 0);
+	bh.ci->disable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN, 0, 0, 0);
+	bh.ci->disable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN, 0, 0, 0);
+	bh.ci->disable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
+
+	/* map bootrom back in to gt @ reset defaults */
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+						0xff800000, 8*1024*1024, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+
+	/* move reg base back to default, setup default pci0 */
+	mv64x60_write(&bh, MV64x60_INTERNAL_SPACE_DECODE,
+		(1<<24) | CONFIG_MV64X60_BASE >> 20);
+
+	/* NOTE: FROM NOW ON no more GT_REGS accesses.. 0x1 is not mapped
+	 * via BAT or MMU, and MSR IR/DR is ON */
+	/* SRR0 has system reset vector, SRR1 has default MSR value */
+	/* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
+	/* NOTE: assumes reset vector is at 0xfff00100 */
+	__asm__ __volatile__
+	("mtspr   26, %0\n\t"
+	 "li      4,(1<<6)\n\t"
+	 "mtspr   27,4\n\t"
+	 "rfi\n\t"
+	 :: "r" (addr):"r4");
+
+	return;
+}
+
+static void
+ev64260_restart(char *cmd)
+{
+	volatile ulong	i = 10000000;
+
+	ev64260_reset_board((void *)0xfff00100);
+
+	while (i-- > 0);
+	panic("restart failed\n");
+}
+
+static void
+ev64260_halt(void)
+{
+	local_irq_disable();
+	while (1);
+	/* NOTREACHED */
+}
+
+static void
+ev64260_power_off(void)
+{
+	ev64260_halt();
+	/* NOTREACHED */
+}
+
+static int
+ev64260_show_cpuinfo(struct seq_file *m)
+{
+	uint pvid;
+
+	pvid = mfspr(SPRN_PVR);
+	seq_printf(m, "vendor\t\t: " BOARD_VENDOR "\n");
+	seq_printf(m, "machine\t\t: " BOARD_MACHINE "\n");
+	seq_printf(m, "cpu MHz\t\t: %d\n", ev64260_get_cpu_speed()/1000/1000);
+	seq_printf(m, "bus MHz\t\t: %d\n", ev64260_get_bus_speed()/1000/1000);
+
+	return 0;
+}
+
+/* DS1501 RTC has too much variation to use RTC for calibration */
+static void __init
+ev64260_calibrate_decr(void)
+{
+	ulong freq;
+
+	freq = ev64260_get_bus_speed()/4;
+
+	printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+	       freq/1000000, freq%1000000);
+
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+	return;
+}
+
+/*
+ * Set BAT 3 to map 0xfb000000 to 0xfc000000 of physical memory space.
+ */
+static __inline__ void
+ev64260_set_bat(void)
+{
+	mb();
+	mtspr(SPRN_DBAT1U, 0xfb0001fe);
+	mtspr(SPRN_DBAT1L, 0xfb00002a);
+	mb();
+
+	return;
+}
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+static void __init
+ev64260_map_io(void)
+{
+	io_block_mapping(0xfb000000, 0xfb000000, 0x01000000, _PAGE_IO);
+}
+#endif
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+	extern int	initrd_below_start_ok;
+
+	initrd_start=initrd_end=0;
+	initrd_below_start_ok=0;
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	parse_bootinfo(find_bootinfo());
+
+	isa_mem_base = 0;
+	isa_io_base = EV64260_PCI0_IO_CPU_BASE;
+	pci_dram_offset = EV64260_PCI0_MEM_CPU_BASE;
+
+	loops_per_jiffy = ev64260_get_cpu_speed() / HZ;
+
+	ppc_md.setup_arch = ev64260_setup_arch;
+	ppc_md.show_cpuinfo = ev64260_show_cpuinfo;
+	ppc_md.init_IRQ = gt64260_init_irq;
+	ppc_md.get_irq = gt64260_get_irq;
+
+	ppc_md.restart = ev64260_restart;
+	ppc_md.power_off = ev64260_power_off;
+	ppc_md.halt = ev64260_halt;
+
+	ppc_md.find_end_of_memory = ev64260_find_end_of_memory;
+
+	ppc_md.init = NULL;
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+	ppc_md.calibrate_decr = ev64260_calibrate_decr;
+
+	bh.p_base = CONFIG_MV64X60_NEW_BASE;
+
+	ev64260_set_bat();
+
+#ifdef	CONFIG_SERIAL_8250
+#if defined(CONFIG_SERIAL_TEXT_DEBUG)
+	ppc_md.setup_io_mappings = ev64260_map_io;
+	ppc_md.progress = gen550_progress;
+#endif
+#if defined(CONFIG_KGDB)
+	ppc_md.setup_io_mappings = ev64260_map_io;
+	ppc_md.early_serial_map = ev64260_early_serial_map;
+#endif
+#elif defined(CONFIG_SERIAL_MPSC_CONSOLE)
+#ifdef	CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.setup_io_mappings = ev64260_map_io;
+	ppc_md.progress = mv64x60_mpsc_progress;
+	mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
+#endif	/* CONFIG_SERIAL_TEXT_DEBUG */
+#ifdef	CONFIG_KGDB
+	ppc_md.setup_io_mappings = ev64260_map_io;
+	ppc_md.early_serial_map = ev64260_early_serial_map;
+#endif	/* CONFIG_KGDB */
+
+#endif
+
+#if defined(CONFIG_SERIAL_MPSC)
+	platform_notify = ev64260_platform_notify;
+#endif
+
+	return;
+}
diff --git a/arch/ppc/platforms/ev64260.h b/arch/ppc/platforms/ev64260.h
new file mode 100644
index 0000000..bedffce
--- /dev/null
+++ b/arch/ppc/platforms/ev64260.h
@@ -0,0 +1,128 @@
+/*
+ * arch/ppc/platforms/ev64260.h
+ *
+ * Definitions for Marvell/Galileo EV-64260-BP Evaluation Board.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2001-2002 (c) MontaVista, Software, Inc.  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.
+ */
+
+/*
+ * The MV64x60 has 2 PCI buses each with 1 window from the CPU bus to
+ * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
+ * We'll only use one PCI MEM window on each PCI bus.
+ *
+ * This is the CPU physical memory map (windows must be at least 1MB and start
+ * on a boundary that is a multiple of the window size):
+ *
+ * 	0xfc000000-0xffffffff		- External FLASH on device module
+ * 	0xfbf00000-0xfbffffff		- Embedded (on board) FLASH
+ * 	0xfbe00000-0xfbefffff		- GT64260 Registers (preferably)
+ * 					  but really a config option
+ * 	0xfbd00000-0xfbdfffff		- External SRAM on device module
+ * 	0xfbc00000-0xfbcfffff		- TODC chip on device module
+ * 	0xfbb00000-0xfbbfffff		- External UART on device module
+ * 	0xa2000000-0xfbafffff		- <hole>
+ * 	0xa1000000-0xa1ffffff		- PCI 1 I/O (defined in gt64260.h)
+ * 	0xa0000000-0xa0ffffff		- PCI 0 I/O (defined in gt64260.h)
+ * 	0x90000000-0x9fffffff		- PCI 1 MEM (defined in gt64260.h)
+ * 	0x80000000-0x8fffffff		- PCI 0 MEM (defined in gt64260.h)
+ */
+
+#ifndef __PPC_PLATFORMS_EV64260_H
+#define __PPC_PLATFORMS_EV64260_H
+
+/* PCI mappings */
+#define	EV64260_PCI0_IO_CPU_BASE	0xa0000000
+#define	EV64260_PCI0_IO_PCI_BASE	0x00000000
+#define	EV64260_PCI0_IO_SIZE		0x01000000
+
+#define	EV64260_PCI0_MEM_CPU_BASE	0x80000000
+#define	EV64260_PCI0_MEM_PCI_BASE	0x80000000
+#define	EV64260_PCI0_MEM_SIZE		0x10000000
+
+#define	EV64260_PCI1_IO_CPU_BASE	(EV64260_PCI0_IO_CPU_BASE + \
+						EV64260_PCI0_IO_SIZE)
+#define	EV64260_PCI1_IO_PCI_BASE	(EV64260_PCI0_IO_PCI_BASE + \
+						EV64260_PCI0_IO_SIZE)
+#define	EV64260_PCI1_IO_SIZE		0x01000000
+
+#define	EV64260_PCI1_MEM_CPU_BASE	(EV64260_PCI0_MEM_CPU_BASE + \
+						EV64260_PCI0_MEM_SIZE)
+#define	EV64260_PCI1_MEM_PCI_BASE	(EV64260_PCI0_MEM_PCI_BASE + \
+						EV64260_PCI0_MEM_SIZE)
+#define	EV64260_PCI1_MEM_SIZE		0x10000000
+
+/* CPU Physical Memory Map setup (other than PCI) */
+#define	EV64260_EXT_FLASH_BASE		0xfc000000
+#define	EV64260_EMB_FLASH_BASE		0xfbf00000
+#define	EV64260_EXT_SRAM_BASE		0xfbd00000
+#define	EV64260_TODC_BASE		0xfbc00000
+#define	EV64260_UART_BASE		0xfbb00000
+
+#define	EV64260_EXT_FLASH_SIZE_ACTUAL	0x04000000  /* <= 64MB Extern FLASH */
+#define	EV64260_EMB_FLASH_SIZE_ACTUAL	0x00080000  /* 512KB of Embed FLASH */
+#define	EV64260_EXT_SRAM_SIZE_ACTUAL	0x00100000  /* 1MB SDRAM */
+#define	EV64260_TODC_SIZE_ACTUAL	0x00000020  /* 32 bytes for TODC */
+#define	EV64260_UART_SIZE_ACTUAL	0x00000040  /* 64 bytes for DUART */
+
+#define	EV64260_EXT_FLASH_SIZE		max(GT64260_WINDOW_SIZE_MIN,	\
+						EV64260_EXT_FLASH_SIZE_ACTUAL)
+#define	EV64260_EMB_FLASH_SIZE		max(GT64260_WINDOW_SIZE_MIN,	\
+						EV64260_EMB_FLASH_SIZE_ACTUAL)
+#define	EV64260_EXT_SRAM_SIZE		max(GT64260_WINDOW_SIZE_MIN,	\
+						EV64260_EXT_SRAM_SIZE_ACTUAL)
+#define	EV64260_TODC_SIZE		max(GT64260_WINDOW_SIZE_MIN,	\
+						EV64260_TODC_SIZE_ACTUAL)
+/* Assembler in bootwrapper blows up if 'max' is used */
+#define	EV64260_UART_SIZE		GT64260_WINDOW_SIZE_MIN
+#define	EV64260_UART_END		((EV64260_UART_BASE +		\
+					EV64260_UART_SIZE - 1) & 0xfff00000)
+
+/* Board-specific IRQ info */
+#define	EV64260_UART_0_IRQ		85
+#define	EV64260_UART_1_IRQ		86
+#define	EV64260_PCI_0_IRQ		91
+#define	EV64260_PCI_1_IRQ		93
+
+/* Serial port setup */
+#define	EV64260_DEFAULT_BAUD		115200
+
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+#define SERIAL_PORT_DFNS
+
+#define	EV64260_MPSC_CLK_SRC		8		/* TCLK */
+#define	EV64260_MPSC_CLK_FREQ		100000000	/* 100MHz clk */
+#else
+#define EV64260_SERIAL_0		(EV64260_UART_BASE + 0x20)
+#define EV64260_SERIAL_1		EV64260_UART_BASE
+
+#define BASE_BAUD	(EV64260_DEFAULT_BAUD * 2)
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE	64
+#else
+#define RS_TABLE_SIZE	2
+#endif
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+/* Required for bootloader's ns16550.c code */
+#define STD_SERIAL_PORT_DFNS 						\
+        { 0, BASE_BAUD, EV64260_SERIAL_0, EV64260_UART_0_IRQ, STD_COM_FLAGS, \
+	iomem_base: (u8 *)EV64260_SERIAL_0,	/* ttyS0 */		\
+	iomem_reg_shift: 2,						\
+	io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
+#endif
+#endif /* __PPC_PLATFORMS_EV64260_H */
diff --git a/arch/ppc/platforms/fads.h b/arch/ppc/platforms/fads.h
new file mode 100644
index 0000000..632b817
--- /dev/null
+++ b/arch/ppc/platforms/fads.h
@@ -0,0 +1,57 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Motorola 860T FADS board.  Copied from the MBX stuff.
+ *
+ * Copyright (c) 1998 Dan Malek (dmalek@jlc.net)
+ */
+#ifdef __KERNEL__
+#ifndef __ASM_FADS_H__
+#define __ASM_FADS_H__
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+/* Memory map is configured by the PROM startup.
+ * I tried to follow the FADS manual, although the startup PROM
+ * dictates this and we simply have to move some of the physical
+ * addresses for Linux.
+ */
+#define BCSR_ADDR		((uint)0xff010000)
+#define BCSR_SIZE		((uint)(64 * 1024))
+#define	BCSR0			((uint)0xff010000)
+#define	BCSR1			((uint)0xff010004)
+#define	BCSR2			((uint)0xff010008)
+#define	BCSR3			((uint)0xff01000c)
+#define	BCSR4			((uint)0xff010010)
+
+#define IMAP_ADDR		((uint)0xff000000)
+#define IMAP_SIZE		((uint)(64 * 1024))
+
+#define PCMCIA_MEM_ADDR		((uint)0xff020000)
+#define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+
+/* Bits of interest in the BCSRs.
+ */
+#define BCSR1_ETHEN		((uint)0x20000000)
+#define BCSR1_RS232EN_1		((uint)0x01000000)
+#define BCSR1_RS232EN_2		((uint)0x00040000)
+#define BCSR4_ETHLOOP		((uint)0x80000000)	/* EEST Loopback */
+#define BCSR4_EEFDX		((uint)0x40000000)	/* EEST FDX enable */
+#define BCSR4_FETH_EN		((uint)0x08000000)	/* PHY enable */
+#define BCSR4_FETHCFG0		((uint)0x04000000)	/* PHY autoneg mode */
+#define BCSR4_FETHCFG1		((uint)0x00400000)	/* PHY autoneg mode */
+#define BCSR4_FETHFDE		((uint)0x02000000)	/* PHY FDX advertise */
+#define BCSR4_FETHRST		((uint)0x00200000)	/* PHY Reset */
+
+/* Interrupt level assignments.
+ */
+#define FEC_INTERRUPT	SIU_LEVEL1	/* FEC interrupt */
+#define PHY_INTERRUPT	SIU_IRQ2	/* PHY link change interrupt */
+
+/* We don't use the 8259.
+ */
+#define NR_8259_INTS	0
+
+#endif /* __ASM_FADS_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/gemini.h b/arch/ppc/platforms/gemini.h
new file mode 100644
index 0000000..06de592
--- /dev/null
+++ b/arch/ppc/platforms/gemini.h
@@ -0,0 +1,168 @@
+/*
+ *  arch/ppc/platforms/gemini.h
+ *
+ *
+ *  Onboard registers and descriptions for Synergy Microsystems'
+ *  "Gemini" boards.
+ *
+ */
+#ifdef __KERNEL__
+#ifndef __PPC_GEMINI_H
+#define __PPC_GEMINI_H
+
+/*  Registers  */
+
+#define GEMINI_SERIAL_B     (0xffeffb00)
+#define GEMINI_SERIAL_A     (0xffeffb08)
+#define GEMINI_USWITCH      (0xffeffd00)
+#define GEMINI_BREV         (0xffeffe00)
+#define GEMINI_BECO         (0xffeffe08)
+#define GEMINI_FEAT         (0xffeffe10)
+#define GEMINI_BSTAT        (0xffeffe18)
+#define GEMINI_CPUSTAT      (0xffeffe20)
+#define GEMINI_L2CFG        (0xffeffe30)
+#define GEMINI_MEMCFG       (0xffeffe38)
+#define GEMINI_FLROM        (0xffeffe40)
+#define GEMINI_P0PCI        (0xffeffe48)
+#define GEMINI_FLWIN        (0xffeffe50)
+#define GEMINI_P0INTMASK    (0xffeffe60)
+#define GEMINI_P0INTAP      (0xffeffe68)
+#define GEMINI_PCIERR       (0xffeffe70)
+#define GEMINI_LEDBASE      (0xffeffe80)
+#define GEMINI_RTC          (0xffe9fff8)
+#define GEMINI_LEDS         8
+#define GEMINI_SWITCHES     8
+
+
+/* Flash ROM bit definitions */
+#define GEMINI_FLS_WEN      (1<<0)
+#define GEMINI_FLS_JMP      (1<<6)
+#define GEMINI_FLS_BOOT     (1<<7)
+
+/* Memory bit definitions */
+#define GEMINI_MEM_TYPE_MASK 0xc0
+#define GEMINI_MEM_SIZE_MASK 0x38
+#define GEMINI_MEM_BANK_MASK 0x07
+
+/* L2 cache bit definitions */
+#define GEMINI_L2_SIZE_MASK  0xc0
+#define GEMINI_L2_RATIO_MASK 0x03
+
+/* Timebase register bit definitons */
+#define GEMINI_TIMEB0_EN     (1<<0)
+#define GEMINI_TIMEB1_EN     (1<<1)
+#define GEMINI_TIMEB2_EN     (1<<2)
+#define GEMINI_TIMEB3_EN     (1<<3)
+
+/* CPU status bit definitions */
+#define GEMINI_CPU_ID_MASK   0x03
+#define GEMINI_CPU_COUNT_MASK 0x0c
+#define GEMINI_CPU0_HALTED   (1<<4)
+#define GEMINI_CPU1_HALTED   (1<<5)
+#define GEMINI_CPU2_HALTED   (1<<6)
+#define GEMINI_CPU3_HALTED   (1<<7)
+
+/* Board status bit definitions */
+#define GEMINI_BRD_FAIL      (1<<0)   /* FAIL led is lit */
+#define GEMINI_BRD_BUS_MASK  0x0c     /* PowerPC bus speed */
+
+/* Board family/feature bit descriptions */
+#define GEMINI_FEAT_HAS_FLASH (1<<0)
+#define GEMINI_FEAT_HAS_ETH   (1<<1)
+#define GEMINI_FEAT_HAS_SCSI  (1<<2)
+#define GEMINI_FEAT_HAS_P0    (1<<3)
+#define GEMINI_FEAT_FAM_MASK  0xf0
+
+/* Mod/ECO bit definitions */
+#define GEMINI_ECO_LEVEL_MASK 0x0f
+#define GEMINI_MOD_MASK       0xf0
+
+/* Type/revision bit definitions */
+#define GEMINI_REV_MASK       0x0f
+#define GEMINI_TYPE_MASK      0xf0
+
+/* User switch definitions */
+#define GEMINI_SWITCH_VERBOSE    1     /* adds "debug" to boot cmd line */
+#define GEMINI_SWITCH_SINGLE_USER 7    /* boots into "single-user" mode */
+
+#define SGS_RTC_CONTROL  0
+#define SGS_RTC_SECONDS  1
+#define SGS_RTC_MINUTES  2
+#define SGS_RTC_HOURS    3
+#define SGS_RTC_DAY      4
+#define SGS_RTC_DAY_OF_MONTH 5
+#define SGS_RTC_MONTH    6
+#define SGS_RTC_YEAR     7
+
+#define SGS_RTC_SET  0x80
+#define SGS_RTC_IS_STOPPED 0x80
+
+#define GRACKLE_CONFIG_ADDR_ADDR  (0xfec00000)
+#define GRACKLE_CONFIG_DATA_ADDR  (0xfee00000)
+
+#define GEMINI_BOOT_INIT  (0xfff00100)
+
+#ifndef __ASSEMBLY__
+
+static inline void grackle_write( unsigned long addr, unsigned long data )
+{
+  __asm__ __volatile__(
+  " stwbrx %1, 0, %0\n \
+    sync\n \
+    stwbrx %3, 0, %2\n \
+    sync "
+  : /* no output */
+  : "r" (GRACKLE_CONFIG_ADDR_ADDR), "r" (addr),
+    "r" (GRACKLE_CONFIG_DATA_ADDR), "r" (data));
+}
+
+static inline unsigned long grackle_read( unsigned long addr )
+{
+  unsigned long val;
+
+  __asm__ __volatile__(
+  " stwbrx %1, 0, %2\n \
+    sync\n \
+    lwbrx %0, 0, %3\n \
+    sync "
+  : "=r" (val)
+  : "r" (addr), "r" (GRACKLE_CONFIG_ADDR_ADDR),
+    "r" (GRACKLE_CONFIG_DATA_ADDR));
+
+  return val;
+}
+
+static inline void gemini_led_on( int led )
+{
+  if (led >= 0 && led < GEMINI_LEDS)
+    *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 1;
+}
+
+static inline void gemini_led_off(int led)
+{
+  if (led >= 0 && led < GEMINI_LEDS)
+    *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 0;
+}
+
+static inline int gemini_led_val(int led)
+{
+  int val = 0;
+  if (led >= 0 && led < GEMINI_LEDS)
+    val = *(unsigned char *)(GEMINI_LEDBASE + (led<<3));
+  return (val & 0x1);
+}
+
+/* returns processor id from the board */
+static inline int gemini_processor(void)
+{
+  unsigned char cpu = *(unsigned char *)(GEMINI_CPUSTAT);
+  return (int) ((cpu == 0) ? 4 : (cpu & GEMINI_CPU_ID_MASK));
+}
+
+
+extern void _gemini_reboot(void);
+extern void gemini_prom_init(void);
+extern void gemini_init_l2(void);
+#endif /* __ASSEMBLY__ */
+#endif
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/gemini_pci.c b/arch/ppc/platforms/gemini_pci.c
new file mode 100644
index 0000000..9565609
--- /dev/null
+++ b/arch/ppc/platforms/gemini_pci.c
@@ -0,0 +1,41 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <asm/machdep.h>
+#include <platforms/gemini.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pci-bridge.h>
+
+void __init gemini_pcibios_fixup(void)
+{
+	int i;
+	struct pci_dev *dev = NULL;
+	
+	for_each_pci_dev(dev) {
+		for(i = 0; i < 6; i++) {
+			if (dev->resource[i].flags & IORESOURCE_IO) {
+				dev->resource[i].start |= (0xfe << 24);
+				dev->resource[i].end |= (0xfe << 24);
+			}
+		}
+	}
+}
+
+
+/* The "bootloader" for Synergy boards does none of this for us, so we need to
+   lay it all out ourselves... --Dan */
+void __init gemini_find_bridges(void)
+{
+	struct pci_controller* hose;
+	
+	ppc_md.pcibios_fixup = gemini_pcibios_fixup;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+	setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
+}
diff --git a/arch/ppc/platforms/gemini_prom.S b/arch/ppc/platforms/gemini_prom.S
new file mode 100644
index 0000000..8c5065d
--- /dev/null
+++ b/arch/ppc/platforms/gemini_prom.S
@@ -0,0 +1,93 @@
+/*
+ *  arch/ppc/platforms/gemini_prom.S
+ *
+ *  Not really prom support code (yet), but sort of anti-prom code.  The current
+ *  bootloader does a number of things it shouldn't and doesn't do things that it
+ *  should.  The stuff in here is mainly a hodge-podge collection of setup code
+ *  to get the board up and running.
+ *    ---Dan
+ */
+
+#include <linux/config.h>
+#include <asm/reg.h>
+#include <asm/page.h>
+#include <platforms/gemini.h>
+#include <asm/ppc_asm.h>
+
+/*
+ *  On 750's the MMU is on when Linux is booted, so we need to clear out the
+ *  bootloader's BAT settings, make sure we're in supervisor state (gotcha!),
+ *  and turn off the MMU.
+ *
+ */
+
+_GLOBAL(gemini_prom_init)
+#ifdef CONFIG_SMP
+	/* Since the MMU's on, get stuff in rom space that we'll need */
+	lis	r4,GEMINI_CPUSTAT@h
+	ori	r4,r4,GEMINI_CPUSTAT@l
+	lbz	r5,0(r4)
+	andi.	r5,r5,3
+	mr	r24,r5		/* cpu # used later on */
+#endif
+	mfmsr	r4
+	li	r3,MSR_PR	/* ensure supervisor! */
+	ori	r3,r3,MSR_IR|MSR_DR
+	andc	r4,r4,r3
+	mtmsr	r4
+	isync
+#if 0
+	/* zero out the bats now that the MMU is off */
+prom_no_mmu:	
+	li	r3,0
+        mtspr   SPRN_IBAT0U,r3
+        mtspr   SPRN_IBAT0L,r3
+        mtspr   SPRN_IBAT1U,r3
+        mtspr   SPRN_IBAT1L,r3
+        mtspr   SPRN_IBAT2U,r3
+        mtspr   SPRN_IBAT2L,r3
+        mtspr   SPRN_IBAT3U,r3
+        mtspr   SPRN_IBAT3L,r3
+
+        mtspr   SPRN_DBAT0U,r3
+        mtspr   SPRN_DBAT0L,r3
+        mtspr   SPRN_DBAT1U,r3
+        mtspr   SPRN_DBAT1L,r3
+        mtspr   SPRN_DBAT2U,r3
+	mtspr   SPRN_DBAT2L,r3
+        mtspr   SPRN_DBAT3U,r3
+        mtspr   SPRN_DBAT3L,r3
+#endif
+
+	/* the bootloader (as far as I'm currently aware) doesn't mess with page
+	   tables, but since we're already here, might as well zap these, too */
+	li	r4,0
+	mtspr	SPRN_SDR1,r4
+
+	li	r4,16
+	mtctr	r4
+	li	r3,0
+	li	r4,0
+3:	mtsrin	r3,r4
+	addi	r3,r3,1
+	bdnz	3b
+
+#ifdef CONFIG_SMP
+	/* The 750 book (and Mot/IBM support) says that this will "assist" snooping
+	   when in SMP.  Not sure yet whether this should stay or leave... */
+	mfspr	r4,SPRN_HID0
+	ori	r4,r4,HID0_ABE
+	mtspr	SPRN_HID0,r4
+	sync
+#endif /* CONFIG_SMP */
+	blr
+
+/*  apparently, SMon doesn't pay attention to HID0[SRST].  Disable the MMU and
+    branch to 0xfff00100 */
+_GLOBAL(_gemini_reboot)
+	lis	r5,GEMINI_BOOT_INIT@h
+	ori	r5,r5,GEMINI_BOOT_INIT@l
+	li	r6,MSR_IP
+	mtspr	SPRN_SRR0,r5
+	mtspr	SPRN_SRR1,r6
+	rfi
diff --git a/arch/ppc/platforms/gemini_serial.h b/arch/ppc/platforms/gemini_serial.h
new file mode 100644
index 0000000..69855ae
--- /dev/null
+++ b/arch/ppc/platforms/gemini_serial.h
@@ -0,0 +1,41 @@
+#ifdef __KERNEL__
+#ifndef __ASMPPC_GEMINI_SERIAL_H
+#define __ASMPPC_GEMINI_SERIAL_H
+
+#include <linux/config.h>
+#include <platforms/gemini.h>
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE  64
+#else
+#define RS_TABLE_SIZE  4
+#endif
+
+/* Rate for the 24.576 Mhz clock for the onboard serial chip */
+#define BASE_BAUD  (24576000 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define STD_SERIAL_PORT_DEFNS \
+        { 0, BASE_BAUD, GEMINI_SERIAL_A, 15, STD_COM_FLAGS }, /* ttyS0 */ \
+        { 0, BASE_BAUD, GEMINI_SERIAL_B, 14, STD_COM_FLAGS }, /* ttyS1 */ \
+
+#ifdef CONFIG_GEMINI_PU32
+#define PU32_SERIAL_PORT_DEFNS \
+        { 0, BASE_BAUD, NULL, 0, STD_COM_FLAGS },
+#else
+#define PU32_SERIAL_PORT_DEFNS
+#endif
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DEFNS \
+        PU32_SERIAL_PORT_DEFNS
+
+#endif
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/gemini_setup.c b/arch/ppc/platforms/gemini_setup.c
new file mode 100644
index 0000000..1a42cb9
--- /dev/null
+++ b/arch/ppc/platforms/gemini_setup.c
@@ -0,0 +1,584 @@
+/*
+ *  arch/ppc/platforms/gemini_setup.c
+ *
+ *  Copyright (C) 1995 Linus Torvalds
+ *  Adapted from 'alpha' version by Gary Thomas
+ *  Modified by Cort Dougan (cort@cs.nmt.edu)
+ *  Synergy Microsystems board support by Dan Cox (dan@synergymicro.com)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/bcd.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/m48t35.h>
+#include <platforms/gemini.h>
+#include <asm/time.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+
+void gemini_find_bridges(void);
+static int gemini_get_clock_speed(void);
+extern void gemini_pcibios_fixup(void);
+
+static char *gemini_board_families[] = {
+  "VGM", "VSS", "KGM", "VGR", "VCM", "VCS", "KCM", "VCR"
+};
+static int gemini_board_count = sizeof(gemini_board_families) /
+                                 sizeof(gemini_board_families[0]);
+
+static unsigned int cpu_7xx[16] = {
+	0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+static unsigned int cpu_6xx[16] = {
+	0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0
+};
+
+/*
+ * prom_init is the Gemini version of prom.c:prom_init.  We only need
+ * the BSS clearing code, so I copied that out of prom.c.  This is a
+ * lot simpler than hacking prom.c so it will build with Gemini. -VAL
+ */
+
+#define PTRRELOC(x)	((typeof(x))((unsigned long)(x) + offset))
+
+unsigned long
+prom_init(void)
+{
+	unsigned long offset = reloc_offset();
+	unsigned long phys;
+	extern char __bss_start, _end;
+
+	/* First zero the BSS -- use memset, some arches don't have
+	 * caches on yet */
+	memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start);
+
+ 	/* Default */
+ 	phys = offset + KERNELBASE;
+
+	gemini_prom_init();
+
+	return phys;
+}
+
+int
+gemini_show_cpuinfo(struct seq_file *m)
+{
+	unsigned char reg, rev;
+	char *family;
+	unsigned int type;
+
+	reg = readb(GEMINI_FEAT);
+	family = gemini_board_families[((reg>>4) & 0xf)];
+	if (((reg>>4) & 0xf) > gemini_board_count)
+		printk(KERN_ERR "cpuinfo(): unable to determine board family\n");
+
+	reg = readb(GEMINI_BREV);
+	type = (reg>>4) & 0xf;
+	rev = reg & 0xf;
+
+	reg = readb(GEMINI_BECO);
+
+	seq_printf(m, "machine\t\t: Gemini %s%d, rev %c, eco %d\n",
+		   family, type, (rev + 'A'), (reg & 0xf));
+
+	seq_printf(m, "board\t\t: Gemini %s", family);
+	if (type > 9)
+		seq_printf(m, "%c", (type - 10) + 'A');
+	else
+		seq_printf(m, "%d", type);
+
+	seq_printf(m, ", rev %c, eco %d\n", (rev + 'A'), (reg & 0xf));
+
+	seq_printf(m, "clock\t\t: %dMhz\n", gemini_get_clock_speed());
+
+	return 0;
+}
+
+static u_char gemini_openpic_initsenses[] = {
+	1,
+	1,
+	1,
+	1,
+	0,
+	0,
+	1, /* remainder are level-triggered */
+};
+
+#define GEMINI_MPIC_ADDR (0xfcfc0000)
+#define GEMINI_MPIC_PCI_CFG (0x80005800)
+
+void __init gemini_openpic_init(void)
+{
+
+	OpenPIC_Addr = (volatile struct OpenPIC *)
+		grackle_read(GEMINI_MPIC_PCI_CFG + 0x10);
+	OpenPIC_InitSenses = gemini_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses );
+
+	ioremap( GEMINI_MPIC_ADDR, OPENPIC_SIZE);
+}
+
+
+extern unsigned long loops_per_jiffy;
+extern int root_mountflags;
+extern char cmd_line[];
+
+void
+gemini_heartbeat(void)
+{
+	static unsigned long led = GEMINI_LEDBASE+(4*8);
+	static char direction = 8;
+
+
+	/* We only want to do this on 1 CPU */
+	if (smp_processor_id())
+		return;
+	*(char *)led = 0;
+	if ( (led + direction) > (GEMINI_LEDBASE+(7*8)) ||
+	     (led + direction) < (GEMINI_LEDBASE+(4*8)) )
+		direction *= -1;
+	led += direction;
+	*(char *)led = 0xff;
+	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+}
+
+void __init gemini_setup_arch(void)
+{
+	extern char cmd_line[];
+
+
+	loops_per_jiffy = 50000000/HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* bootable off CDROM */
+	if (initrd_start)
+		ROOT_DEV = Root_SR0;
+	else
+#endif
+		ROOT_DEV = Root_SDA1;
+
+	/* nothing but serial consoles... */
+	sprintf(cmd_line, "%s console=ttyS0", cmd_line);
+
+	printk("Boot arguments: %s\n", cmd_line);
+
+	ppc_md.heartbeat = gemini_heartbeat;
+	ppc_md.heartbeat_reset = HZ/8;
+	ppc_md.heartbeat_count = 1;
+
+	/* Lookup PCI hosts */
+	gemini_find_bridges();
+	/* take special pains to map the MPIC, since it isn't mapped yet */
+	gemini_openpic_init();
+	/* start the L2 */
+	gemini_init_l2();
+}
+
+
+int
+gemini_get_clock_speed(void)
+{
+	unsigned long hid1, pvr;
+	int clock;
+
+	pvr = mfspr(SPRN_PVR);
+	hid1 = (mfspr(SPRN_HID1) >> 28) & 0xf;
+	if (PVR_VER(pvr) == 8 ||
+	    PVR_VER(pvr) == 12)
+		hid1 = cpu_7xx[hid1];
+	else
+		hid1 = cpu_6xx[hid1];
+
+	switch((readb(GEMINI_BSTAT) & 0xc) >> 2) {
+
+	case 0:
+	default:
+		clock = (hid1*100)/3;
+		break;
+
+	case 1:
+		clock = (hid1*125)/3;
+		break;
+
+	case 2:
+		clock = (hid1*50);
+		break;
+	}
+
+	return clock;
+}
+
+void __init gemini_init_l2(void)
+{
+        unsigned char reg, brev, fam, creg;
+        unsigned long cache;
+        unsigned long pvr;
+
+        reg = readb(GEMINI_L2CFG);
+        brev = readb(GEMINI_BREV);
+        fam = readb(GEMINI_FEAT);
+        pvr = mfspr(SPRN_PVR);
+
+        switch(PVR_VER(pvr)) {
+
+        case 8:
+                if (reg & 0xc0)
+                        cache = (((reg >> 6) & 0x3) << 28);
+                else
+                        cache = 0x3 << 28;
+
+#ifdef CONFIG_SMP
+                /* Pre-3.0 processor revs had snooping errata.  Leave
+                   their L2's disabled with SMP. -- Dan */
+                if (PVR_CFG(pvr) < 3) {
+                        printk("Pre-3.0 750; L2 left disabled!\n");
+                        return;
+                }
+#endif /* CONFIG_SMP */
+
+                /* Special case: VGM5-B's came before L2 ratios were set on
+                   the board.  Processor speed shouldn't be too high, so
+                   set L2 ratio to 1:1.5.  */
+                if ((brev == 0x51) && ((fam & 0xa0) >> 4) == 0)
+                        reg |= 1;
+
+                /* determine best cache ratio based upon what the board
+                   tells us (which sometimes _may_ not be true) and
+                   the processor speed. */
+                else {
+                        if (gemini_get_clock_speed() > 250)
+                                reg = 2;
+                }
+                break;
+        case 12:
+	{
+		static unsigned long l2_size_val = 0;
+
+		if (!l2_size_val)
+			l2_size_val = _get_L2CR();
+		cache = l2_size_val;
+                break;
+	}
+        case 4:
+        case 9:
+                creg = readb(GEMINI_CPUSTAT);
+                if (((creg & 0xc) >> 2) != 1)
+                        printk("Dual-604 boards don't support the use of L2\n");
+                else
+                        writeb(1, GEMINI_L2CFG);
+                return;
+        default:
+                printk("Unknown processor; L2 left disabled\n");
+                return;
+        }
+
+        cache |= ((1<<reg) << 25);
+        cache |= (L2CR_L2RAM_MASK|L2CR_L2CTL|L2CR_L2DO);
+        _set_L2CR(0);
+        _set_L2CR(cache | L2CR_L2E);
+
+}
+
+void
+gemini_restart(char *cmd)
+{
+	local_irq_disable();
+	/* make a clean restart, not via the MPIC */
+	_gemini_reboot();
+	for(;;);
+}
+
+void
+gemini_power_off(void)
+{
+	for(;;);
+}
+
+void
+gemini_halt(void)
+{
+	gemini_restart(NULL);
+}
+
+void __init gemini_init_IRQ(void)
+{
+	/* gemini has no 8259 */
+	openpic_init(1, 0, 0, -1);
+}
+
+#define gemini_rtc_read(x)       (readb(GEMINI_RTC+(x)))
+#define gemini_rtc_write(val,x)  (writeb((val),(GEMINI_RTC+(x))))
+
+/* ensure that the RTC is up and running */
+long __init gemini_time_init(void)
+{
+	unsigned char reg;
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+
+	if ( reg & M48T35_RTC_STOPPED ) {
+		printk(KERN_INFO "M48T35 real-time-clock was stopped. Now starting...\n");
+		gemini_rtc_write((reg & ~(M48T35_RTC_STOPPED)), M48T35_RTC_CONTROL);
+		gemini_rtc_write((reg | M48T35_RTC_SET), M48T35_RTC_CONTROL);
+	}
+	return 0;
+}
+
+#undef DEBUG_RTC
+
+unsigned long
+gemini_get_rtc_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	unsigned char reg;
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+	gemini_rtc_write((reg|M48T35_RTC_READ), M48T35_RTC_CONTROL);
+#ifdef DEBUG_RTC
+	printk("get rtc: reg = %x\n", reg);
+#endif
+
+	do {
+		sec = gemini_rtc_read(M48T35_RTC_SECONDS);
+		min = gemini_rtc_read(M48T35_RTC_MINUTES);
+		hour = gemini_rtc_read(M48T35_RTC_HOURS);
+		day = gemini_rtc_read(M48T35_RTC_DOM);
+		mon = gemini_rtc_read(M48T35_RTC_MONTH);
+		year = gemini_rtc_read(M48T35_RTC_YEAR);
+	} while( sec != gemini_rtc_read(M48T35_RTC_SECONDS));
+#ifdef DEBUG_RTC
+	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n",
+	       sec, min, hour, day, mon, year);
+#endif
+
+	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
+
+	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;
+#ifdef DEBUG_RTC
+	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n",
+	       sec, min, hour, day, mon, year);
+#endif
+
+	return mktime( year, mon, day, hour, min, sec );
+}
+
+
+int
+gemini_set_rtc_time( unsigned long now )
+{
+	unsigned char reg;
+	struct rtc_time tm;
+
+	to_tm( now, &tm );
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+#ifdef DEBUG_RTC
+	printk("set rtc: reg = %x\n", reg);
+#endif
+
+	gemini_rtc_write((reg|M48T35_RTC_SET), M48T35_RTC_CONTROL);
+#ifdef DEBUG_RTC
+	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
+	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
+#endif
+
+	tm.tm_year -= 1900;
+	BIN_TO_BCD(tm.tm_sec);
+	BIN_TO_BCD(tm.tm_min);
+	BIN_TO_BCD(tm.tm_hour);
+	BIN_TO_BCD(tm.tm_mon);
+	BIN_TO_BCD(tm.tm_mday);
+	BIN_TO_BCD(tm.tm_year);
+#ifdef DEBUG_RTC
+	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
+	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
+#endif
+
+	gemini_rtc_write(tm.tm_sec, M48T35_RTC_SECONDS);
+	gemini_rtc_write(tm.tm_min, M48T35_RTC_MINUTES);
+	gemini_rtc_write(tm.tm_hour, M48T35_RTC_HOURS);
+	gemini_rtc_write(tm.tm_mday, M48T35_RTC_DOM);
+	gemini_rtc_write(tm.tm_mon, M48T35_RTC_MONTH);
+	gemini_rtc_write(tm.tm_year, M48T35_RTC_YEAR);
+
+	/* done writing */
+	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
+
+	if ((time_state == TIME_ERROR) || (time_state == TIME_BAD))
+		time_state = TIME_OK;
+
+	return 0;
+}
+
+/*  use the RTC to determine the decrementer count */
+void __init gemini_calibrate_decr(void)
+{
+	int freq, divisor;
+	unsigned char reg;
+
+	/* determine processor bus speed */
+	reg = readb(GEMINI_BSTAT);
+
+	switch(((reg & 0x0c)>>2)&0x3) {
+	case 0:
+	default:
+		freq = 66667;
+		break;
+	case 1:
+		freq = 83000;
+		break;
+	case 2:
+		freq = 100000;
+		break;
+	}
+
+	freq *= 1000;
+	divisor = 4;
+	tb_ticks_per_jiffy = freq / HZ / divisor;
+	tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+}
+
+unsigned long __init gemini_find_end_of_memory(void)
+{
+	unsigned long total;
+	unsigned char reg;
+
+	reg = readb(GEMINI_MEMCFG);
+	total = ((1<<((reg & 0x7) - 1)) *
+		 (8<<((reg >> 3) & 0x7)));
+	total *= (1024*1024);
+	return total;
+}
+
+static void __init
+gemini_map_io(void)
+{
+	io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
+	io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO);
+}
+
+#ifdef CONFIG_SMP
+static int
+smp_gemini_probe(void)
+{
+	int i, nr;
+
+        nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK) >> 2;
+	if (nr == 0)
+		nr = 4;
+
+	if (nr > 1) {
+		openpic_request_IPIs();
+		for (i = 1; i < nr; ++i)
+			smp_hw_index[i] = i;
+	}
+
+	return nr;
+}
+
+static void
+smp_gemini_kick_cpu(int nr)
+{
+	openpic_reset_processor_phys(1 << nr);
+	openpic_reset_processor_phys(0);
+}
+
+static void
+smp_gemini_setup_cpu(int cpu_nr)
+{
+	if (OpenPIC_Addr)
+		do_openpic_setup_cpu();
+	if (cpu_nr > 0)
+		gemini_init_l2();
+}
+
+static struct smp_ops_t gemini_smp_ops = {
+	smp_openpic_message_pass,
+	smp_gemini_probe,
+	smp_gemini_kick_cpu,
+	smp_gemini_setup_cpu,
+	.give_timebase = smp_generic_give_timebase,
+	.take_timebase = smp_generic_take_timebase,
+};
+#endif /* CONFIG_SMP */
+
+void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+			  unsigned long r6, unsigned long r7)
+{
+	int i;
+
+	/* Restore BATs for now */
+	mtspr(SPRN_DBAT3U, 0xf0001fff);
+	mtspr(SPRN_DBAT3L, 0xf000002a);
+
+	parse_bootinfo(find_bootinfo());
+
+	for(i = 0; i < GEMINI_LEDS; i++)
+		gemini_led_off(i);
+
+	ISA_DMA_THRESHOLD = 0;
+	DMA_MODE_READ = 0;
+	DMA_MODE_WRITE = 0;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if ( r4 )
+	{
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif
+
+	ppc_md.setup_arch = gemini_setup_arch;
+	ppc_md.show_cpuinfo = gemini_show_cpuinfo;
+	ppc_md.irq_canonicalize = NULL;
+	ppc_md.init_IRQ = gemini_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+	ppc_md.init = NULL;
+
+	ppc_md.restart = gemini_restart;
+	ppc_md.power_off = gemini_power_off;
+	ppc_md.halt = gemini_halt;
+
+	ppc_md.time_init = gemini_time_init;
+	ppc_md.set_rtc_time = gemini_set_rtc_time;
+	ppc_md.get_rtc_time = gemini_get_rtc_time;
+	ppc_md.calibrate_decr = gemini_calibrate_decr;
+
+	ppc_md.find_end_of_memory = gemini_find_end_of_memory;
+	ppc_md.setup_io_mappings = gemini_map_io;
+
+	ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup;
+
+#ifdef CONFIG_SMP
+	ppc_md.smp_ops = &gemini_smp_ops;
+#endif /* CONFIG_SMP */
+}
diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c
new file mode 100644
index 0000000..b659d7b
--- /dev/null
+++ b/arch/ppc/platforms/hdpu.c
@@ -0,0 +1,1062 @@
+
+/*
+ * arch/ppc/platforms/hdpu_setup.c
+ *
+ * Board setup routines for the Sky Computers HDPU Compute Blade.
+ *
+ * Written by Brian Waite <waite@skycomputers.com>
+ *
+ * Based on code done by - Mark A. Greer <mgreer@mvista.com>
+ *                         Rabeeh Khoury - rabeeh@galileo.co.il
+ *
+ * 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/pci.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+
+#include <linux/initrd.h>
+#include <linux/root_dev.h>
+#include <linux/smp.h>
+
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/todc.h>
+#include <asm/mv64x60.h>
+#include <asm/ppcboot.h>
+#include <platforms/hdpu.h>
+#include <linux/mv643xx.h>
+#include <linux/hdpu_features.h>
+#include <linux/device.h>
+#include <linux/mtd/physmap.h>
+
+#define BOARD_VENDOR	"Sky Computers"
+#define BOARD_MACHINE	"HDPU-CB-A"
+
+bd_t ppcboot_bd;
+int ppcboot_bd_valid = 0;
+
+static mv64x60_handle_t bh;
+
+extern char cmd_line[];
+
+unsigned long hdpu_find_end_of_memory(void);
+void hdpu_mpsc_progress(char *s, unsigned short hex);
+void hdpu_heartbeat(void);
+
+static void parse_bootinfo(unsigned long r3,
+			   unsigned long r4, unsigned long r5,
+			   unsigned long r6, unsigned long r7);
+static void hdpu_set_l1pe(void);
+static void hdpu_cpustate_set(unsigned char new_state);
+#ifdef CONFIG_SMP
+static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
+static unsigned int timebase_upper = 0, timebase_lower = 0;
+extern int smp_tb_synchronized;
+
+void __devinit hdpu_tben_give(void);
+void __devinit hdpu_tben_take(void);
+#endif
+
+static int __init
+hdpu_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+
+	if (hose->index == 0) {
+		static char pci_irq_table[][4] = {
+			{HDPU_PCI_0_IRQ, 0, 0, 0},
+			{HDPU_PCI_0_IRQ, 0, 0, 0},
+		};
+
+		const long min_idsel = 1, max_idsel = 2, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	} else {
+		static char pci_irq_table[][4] = {
+			{HDPU_PCI_1_IRQ, 0, 0, 0},
+		};
+
+		const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	}
+}
+
+static void __init hdpu_intr_setup(void)
+{
+	mv64x60_write(&bh, MV64x60_GPP_IO_CNTL,
+		      (1 | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) |
+		       (1 << 6) | (1 << 7) | (1 << 12) | (1 << 16) |
+		       (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21) |
+		       (1 << 22) | (1 << 23) | (1 << 24) | (1 << 25) |
+		       (1 << 26) | (1 << 27) | (1 << 28) | (1 << 29)));
+
+	/* XXXX Erranum FEr PCI-#8 */
+	mv64x60_clr_bits(&bh, MV64x60_PCI0_CMD, (1 << 5) | (1 << 9));
+	mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1 << 5) | (1 << 9));
+
+	/*
+	 * Dismiss and then enable interrupt on GPP interrupt cause
+	 * for CPU #0
+	 */
+	mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~((1 << 8) | (1 << 13)));
+	mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, (1 << 8) | (1 << 13));
+
+	/*
+	 * Dismiss and then enable interrupt on CPU #0 high cause reg
+	 * BIT25 summarizes GPP interrupts 8-15
+	 */
+	mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, (1 << 25));
+}
+
+static void __init hdpu_setup_peripherals(void)
+{
+	unsigned int val;
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+				 HDPU_EMB_FLASH_BASE, HDPU_EMB_FLASH_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN,
+				 HDPU_TBEN_BASE, HDPU_TBEN_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,
+				 HDPU_NEXUS_ID_BASE, HDPU_NEXUS_ID_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+				 HDPU_INTERNAL_SRAM_BASE,
+				 HDPU_INTERNAL_SRAM_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+	bh.ci->disable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN);
+	mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN, 0, 0, 0);
+
+	mv64x60_clr_bits(&bh, MV64x60_PCI0_PCI_DECODE_CNTL, (1 << 3));
+	mv64x60_clr_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, (1 << 3));
+	mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL,
+			 ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24)));
+
+	/* Enable pipelining */
+	mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1 << 13));
+	/* Enable Snoop Pipelineing */
+	mv64x60_set_bits(&bh, MV64360_D_UNIT_CONTROL_HIGH, (1 << 24));
+
+	/*
+	 * Change DRAM read buffer assignment.
+	 * Assign read buffer 0 dedicated only for CPU,
+	 * and the rest read buffer 1.
+	 */
+	val = mv64x60_read(&bh, MV64360_SDRAM_CONFIG);
+	val = val & 0x03ffffff;
+	val = val | 0xf8000000;
+	mv64x60_write(&bh, MV64360_SDRAM_CONFIG, val);
+
+	/*
+	 * Configure internal SRAM -
+	 * Cache coherent write back, if CONFIG_MV64360_SRAM_CACHE_COHERENT set
+	 * Parity enabled.
+	 * Parity error propagation
+	 * Arbitration not parked for CPU only
+	 * Other bits are reserved.
+	 */
+#ifdef CONFIG_MV64360_SRAM_CACHE_COHERENT
+	mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2);
+#else
+	mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b0);
+#endif
+
+	hdpu_intr_setup();
+}
+
+static void __init hdpu_setup_bridge(void)
+{
+	struct mv64x60_setup_info si;
+	int i;
+
+	memset(&si, 0, sizeof(si));
+
+	si.phys_reg_base = HDPU_BRIDGE_REG_BASE;
+	si.pci_0.enable_bus = 1;
+	si.pci_0.pci_io.cpu_base = HDPU_PCI0_IO_START_PROC_ADDR;
+	si.pci_0.pci_io.pci_base_hi = 0;
+	si.pci_0.pci_io.pci_base_lo = HDPU_PCI0_IO_START_PCI_ADDR;
+	si.pci_0.pci_io.size = HDPU_PCI0_IO_SIZE;
+	si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_0.pci_mem[0].cpu_base = HDPU_PCI0_MEM_START_PROC_ADDR;
+	si.pci_0.pci_mem[0].pci_base_hi = HDPU_PCI0_MEM_START_PCI_HI_ADDR;
+	si.pci_0.pci_mem[0].pci_base_lo = HDPU_PCI0_MEM_START_PCI_LO_ADDR;
+	si.pci_0.pci_mem[0].size = HDPU_PCI0_MEM_SIZE;
+	si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_0.pci_cmd_bits = 0;
+	si.pci_0.latency_timer = 0x80;
+
+	si.pci_1.enable_bus = 1;
+	si.pci_1.pci_io.cpu_base = HDPU_PCI1_IO_START_PROC_ADDR;
+	si.pci_1.pci_io.pci_base_hi = 0;
+	si.pci_1.pci_io.pci_base_lo = HDPU_PCI1_IO_START_PCI_ADDR;
+	si.pci_1.pci_io.size = HDPU_PCI1_IO_SIZE;
+	si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_1.pci_mem[0].cpu_base = HDPU_PCI1_MEM_START_PROC_ADDR;
+	si.pci_1.pci_mem[0].pci_base_hi = HDPU_PCI1_MEM_START_PCI_HI_ADDR;
+	si.pci_1.pci_mem[0].pci_base_lo = HDPU_PCI1_MEM_START_PCI_LO_ADDR;
+	si.pci_1.pci_mem[0].size = HDPU_PCI1_MEM_SIZE;
+	si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_1.pci_cmd_bits = 0;
+	si.pci_1.latency_timer = 0x80;
+
+	for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) {
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+		si.cpu_prot_options[i] = 0;
+		si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
+		si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
+		si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
+
+		si.pci_1.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+
+		si.pci_0.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+
+#else
+		si.cpu_prot_options[i] = 0;
+		si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB;	/* errata */
+		si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB;	/* errata */
+		si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB;	/* errata */
+
+		si.pci_0.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_WB |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+
+		si.pci_1.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_WB |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+#endif
+	}
+
+	hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_INIT_PCI);
+
+	/* Lookup PCI host bridges */
+	mv64x60_init(&bh, &si);
+	pci_dram_offset = 0;	/* System mem at same addr on PCI & cpu bus */
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = hdpu_map_irq;
+
+	mv64x60_set_bus(&bh, 0, 0);
+	bh.hose_a->first_busno = 0;
+	bh.hose_a->last_busno = 0xff;
+	bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
+
+	bh.hose_b->first_busno = bh.hose_a->last_busno + 1;
+	mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno);
+	bh.hose_b->last_busno = 0xff;
+	bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b,
+		bh.hose_b->first_busno);
+
+	ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
+
+	hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_INIT_REG);
+	/*
+	 * Enabling of PCI internal-vs-external arbitration
+	 * is a platform- and errata-dependent decision.
+	 */
+	return;
+}
+
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+static void __init hdpu_early_serial_map(void)
+{
+#ifdef	CONFIG_KGDB
+	static char first_time = 1;
+
+#if defined(CONFIG_KGDB_TTYS0)
+#define KGDB_PORT 0
+#elif defined(CONFIG_KGDB_TTYS1)
+#define KGDB_PORT 1
+#else
+#error "Invalid kgdb_tty port"
+#endif
+
+	if (first_time) {
+		gt_early_mpsc_init(KGDB_PORT,
+				   B9600 | CS8 | CREAD | HUPCL | CLOCAL);
+		first_time = 0;
+	}
+
+	return;
+#endif
+}
+#endif
+
+static void hdpu_init2(void)
+{
+	return;
+}
+
+#if defined(CONFIG_MV643XX_ETH)
+static void __init hdpu_fixup_eth_pdata(struct platform_device *pd)
+{
+
+	struct mv643xx_eth_platform_data *eth_pd;
+	eth_pd = pd->dev.platform_data;
+
+	eth_pd->port_serial_control =
+	    mv64x60_read(&bh, MV643XX_ETH_PORT_SERIAL_CONTROL_REG(pd->id) & ~1);
+
+	eth_pd->force_phy_addr = 1;
+	eth_pd->phy_addr = pd->id;
+	eth_pd->tx_queue_size = 400;
+	eth_pd->rx_queue_size = 800;
+}
+#endif
+
+static void __init hdpu_fixup_mpsc_pdata(struct platform_device *pd)
+{
+
+	struct mpsc_pdata *pdata;
+
+	pdata = (struct mpsc_pdata *)pd->dev.platform_data;
+
+	pdata->max_idle = 40;
+	if (ppcboot_bd_valid)
+		pdata->default_baud = ppcboot_bd.bi_baudrate;
+	else
+		pdata->default_baud = HDPU_DEFAULT_BAUD;
+	pdata->brg_clk_src = HDPU_MPSC_CLK_SRC;
+	pdata->brg_clk_freq = HDPU_MPSC_CLK_FREQ;
+}
+
+#if defined(CONFIG_HDPU_FEATURES)
+static void __init hdpu_fixup_cpustate_pdata(struct platform_device *pd)
+{
+	struct platform_device *pds[1];
+	pds[0] = pd;
+	mv64x60_pd_fixup(&bh, pds, 1);
+}
+#endif
+
+static int __init hdpu_platform_notify(struct device *dev)
+{
+	static struct {
+		char *bus_id;
+		void ((*rtn) (struct platform_device * pdev));
+	} dev_map[] = {
+		{
+		MPSC_CTLR_NAME ".0", hdpu_fixup_mpsc_pdata},
+#if defined(CONFIG_MV643XX_ETH)
+		{
+		MV643XX_ETH_NAME ".0", hdpu_fixup_eth_pdata},
+#endif
+#if defined(CONFIG_HDPU_FEATURES)
+		{
+		HDPU_CPUSTATE_NAME ".0", hdpu_fixup_cpustate_pdata},
+#endif
+	};
+	struct platform_device *pdev;
+	int i;
+
+	if (dev && dev->bus_id)
+		for (i = 0; i < ARRAY_SIZE(dev_map); i++)
+			if (!strncmp(dev->bus_id, dev_map[i].bus_id,
+				     BUS_ID_SIZE)) {
+
+				pdev = container_of(dev,
+						    struct platform_device,
+						    dev);
+				dev_map[i].rtn(pdev);
+			}
+
+	return 0;
+}
+
+static void __init hdpu_setup_arch(void)
+{
+	if (ppc_md.progress)
+		ppc_md.progress("hdpu_setup_arch: enter", 0);
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef	CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA2;
+#endif
+
+	ppc_md.heartbeat = hdpu_heartbeat;
+
+	ppc_md.heartbeat_reset = HZ;
+	ppc_md.heartbeat_count = 1;
+
+	if (ppc_md.progress)
+		ppc_md.progress("hdpu_setup_arch: Enabling L2 cache", 0);
+
+	/* Enable L1 Parity Bits */
+	hdpu_set_l1pe();
+
+	/* Enable L2 and L3 caches (if 745x) */
+	_set_L2CR(0x80080000);
+
+	if (ppc_md.progress)
+		ppc_md.progress("hdpu_setup_arch: enter", 0);
+
+	hdpu_setup_bridge();
+
+	hdpu_setup_peripherals();
+
+#ifdef CONFIG_SERIAL_MPSC_CONSOLE
+	hdpu_early_serial_map();
+#endif
+
+	printk("SKY HDPU Compute Blade \n");
+
+	if (ppc_md.progress)
+		ppc_md.progress("hdpu_setup_arch: exit", 0);
+
+	hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_OK);
+	return;
+}
+static void __init hdpu_init_irq(void)
+{
+	mv64360_init_irq();
+}
+
+static void __init hdpu_set_l1pe()
+{
+	unsigned long ictrl;
+	asm volatile ("mfspr %0, 1011":"=r" (ictrl):);
+	ictrl |= ICTRL_EICE | ICTRL_EDC | ICTRL_EICP;
+	asm volatile ("mtspr 1011, %0"::"r" (ictrl));
+}
+
+/*
+ * Set BAT 1 to map 0xf1000000 to end of physical memory space.
+ */
+static __inline__ void hdpu_set_bat(void)
+{
+	mb();
+	mtspr(SPRN_DBAT1U, 0xf10001fe);
+	mtspr(SPRN_DBAT1L, 0xf100002a);
+	mb();
+
+	return;
+}
+
+unsigned long __init hdpu_find_end_of_memory(void)
+{
+	return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
+				    MV64x60_TYPE_MV64360);
+}
+
+static void hdpu_reset_board(void)
+{
+	volatile int infinite = 1;
+
+	hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_RESET);
+
+	local_irq_disable();
+
+	/* Clear all the LEDs */
+	mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, ((1 << 4) |
+						   (1 << 5) | (1 << 6)));
+
+	/* disable and invalidate the L2 cache */
+	_set_L2CR(0);
+	_set_L2CR(0x200000);
+
+	/* flush and disable L1 I/D cache */
+	__asm__ __volatile__
+	    ("\n"
+	     "mfspr   3,1008\n"
+	     "ori	5,5,0xcc00\n"
+	     "ori	4,3,0xc00\n"
+	     "andc	5,3,5\n"
+	     "sync\n"
+	     "mtspr	1008,4\n"
+	     "isync\n" "sync\n" "mtspr	1008,5\n" "isync\n" "sync\n");
+
+	/* Hit the reset bit */
+	mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (1 << 3));
+
+	while (infinite)
+		infinite = infinite;
+
+	return;
+}
+
+static void hdpu_restart(char *cmd)
+{
+	volatile ulong i = 10000000;
+
+	hdpu_reset_board();
+
+	while (i-- > 0) ;
+	panic("restart failed\n");
+}
+
+static void hdpu_halt(void)
+{
+	local_irq_disable();
+
+	hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_HALT);
+
+	/* Clear all the LEDs */
+	mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, ((1 << 4) | (1 << 5) |
+						   (1 << 6)));
+	while (1) ;
+	/* NOTREACHED */
+}
+
+static void hdpu_power_off(void)
+{
+	hdpu_halt();
+	/* NOTREACHED */
+}
+
+static int hdpu_show_cpuinfo(struct seq_file *m)
+{
+	uint pvid;
+
+	pvid = mfspr(SPRN_PVR);
+	seq_printf(m, "vendor\t\t: Sky Computers\n");
+	seq_printf(m, "machine\t\t: HDPU Compute Blade\n");
+	seq_printf(m, "PVID\t\t: 0x%x, vendor: %s\n",
+		   pvid, (pvid & (1 << 15) ? "IBM" : "Motorola"));
+
+	return 0;
+}
+
+static void __init hdpu_calibrate_decr(void)
+{
+	ulong freq;
+
+	if (ppcboot_bd_valid)
+		freq = ppcboot_bd.bi_busfreq / 4;
+	else
+		freq = 133000000;
+
+	printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+	       freq / 1000000, freq % 1000000);
+
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+	return;
+}
+
+static void parse_bootinfo(unsigned long r3,
+			   unsigned long r4, unsigned long r5,
+			   unsigned long r6, unsigned long r7)
+{
+	bd_t *bd = NULL;
+	char *cmdline_start = NULL;
+	int cmdline_len = 0;
+
+	if (r3) {
+		if ((r3 & 0xf0000000) == 0)
+			r3 += KERNELBASE;
+		if ((r3 & 0xf0000000) == KERNELBASE) {
+			bd = (void *)r3;
+
+			memcpy(&ppcboot_bd, bd, sizeof(ppcboot_bd));
+			ppcboot_bd_valid = 1;
+		}
+	}
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (r4 && r5 && r5 > r4) {
+		if ((r4 & 0xf0000000) == 0)
+			r4 += KERNELBASE;
+		if ((r5 & 0xf0000000) == 0)
+			r5 += KERNELBASE;
+		if ((r4 & 0xf0000000) == KERNELBASE) {
+			initrd_start = r4;
+			initrd_end = r5;
+			initrd_below_start_ok = 1;
+		}
+	}
+#endif				/* CONFIG_BLK_DEV_INITRD */
+
+	if (r6 && r7 && r7 > r6) {
+		if ((r6 & 0xf0000000) == 0)
+			r6 += KERNELBASE;
+		if ((r7 & 0xf0000000) == 0)
+			r7 += KERNELBASE;
+		if ((r6 & 0xf0000000) == KERNELBASE) {
+			cmdline_start = (void *)r6;
+			cmdline_len = (r7 - r6);
+			strncpy(cmd_line, cmdline_start, cmdline_len);
+		}
+	}
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+static int hdpu_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+	return check_region(from, extent);
+}
+
+static void
+hdpu_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name)
+{
+	request_region(from, extent, name);
+	return;
+}
+
+static void hdpu_ide_release_region(ide_ioreg_t from, unsigned int extent)
+{
+	release_region(from, extent);
+	return;
+}
+
+static void __init
+hdpu_ide_pci_init_hwif_ports(hw_regs_t * hw, ide_ioreg_t data_port,
+			     ide_ioreg_t ctrl_port, int *irq)
+{
+	struct pci_dev *dev;
+
+	pci_for_each_dev(dev) {
+		if (((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) ||
+		    ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID)) {
+			hw->irq = dev->irq;
+
+			if (irq != NULL) {
+				*irq = dev->irq;
+			}
+		}
+	}
+
+	return;
+}
+#endif
+
+void hdpu_heartbeat(void)
+{
+	if (mv64x60_read(&bh, MV64x60_GPP_VALUE) & (1 << 5))
+		mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (1 << 5));
+	else
+		mv64x60_write(&bh, MV64x60_GPP_VALUE_SET, (1 << 5));
+
+	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+
+}
+
+static void __init hdpu_map_io(void)
+{
+	io_block_mapping(0xf1000000, 0xf1000000, 0x20000, _PAGE_IO);
+}
+
+#ifdef CONFIG_SMP
+char hdpu_smp0[] = "SMP Cpu #0";
+char hdpu_smp1[] = "SMP Cpu #1";
+
+static irqreturn_t hdpu_smp_cpu0_int_handler(int irq, void *dev_id,
+					     struct pt_regs *regs)
+{
+	volatile unsigned int doorbell;
+
+	doorbell = mv64x60_read(&bh, MV64360_CPU0_DOORBELL);
+
+	/* Ack the doorbell interrupts */
+	mv64x60_write(&bh, MV64360_CPU0_DOORBELL_CLR, doorbell);
+
+	if (doorbell & 1) {
+		smp_message_recv(0, regs);
+	}
+	if (doorbell & 2) {
+		smp_message_recv(1, regs);
+	}
+	if (doorbell & 4) {
+		smp_message_recv(2, regs);
+	}
+	if (doorbell & 8) {
+		smp_message_recv(3, regs);
+	}
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t hdpu_smp_cpu1_int_handler(int irq, void *dev_id,
+					     struct pt_regs *regs)
+{
+	volatile unsigned int doorbell;
+
+	doorbell = mv64x60_read(&bh, MV64360_CPU1_DOORBELL);
+
+	/* Ack the doorbell interrupts */
+	mv64x60_write(&bh, MV64360_CPU1_DOORBELL_CLR, doorbell);
+
+	if (doorbell & 1) {
+		smp_message_recv(0, regs);
+	}
+	if (doorbell & 2) {
+		smp_message_recv(1, regs);
+	}
+	if (doorbell & 4) {
+		smp_message_recv(2, regs);
+	}
+	if (doorbell & 8) {
+		smp_message_recv(3, regs);
+	}
+	return IRQ_HANDLED;
+}
+
+static void smp_hdpu_CPU_two(void)
+{
+	__asm__ __volatile__
+	    ("\n"
+	     "lis     3,0x0000\n"
+	     "ori     3,3,0x00c0\n"
+	     "mtspr   26, 3\n" "li      4,0\n" "mtspr   27,4\n" "rfi");
+
+}
+
+static int smp_hdpu_probe(void)
+{
+	int *cpu_count_reg;
+	int num_cpus = 0;
+
+	cpu_count_reg = ioremap(HDPU_NEXUS_ID_BASE, HDPU_NEXUS_ID_SIZE);
+	if (cpu_count_reg) {
+		num_cpus = (*cpu_count_reg >> 20) & 0x3;
+		iounmap(cpu_count_reg);
+	}
+
+	/* Validate the bits in the CPLD. If we could not map the reg, return 2.
+	 * If the register reported 0 or 3, return 2.
+	 * Older CPLD revisions set these bits to all ones (val = 3).
+	 */
+	if ((num_cpus < 1) || (num_cpus > 2)) {
+		printk
+		    ("Unable to determine the number of processors %d . deafulting to 2.\n",
+		     num_cpus);
+		num_cpus = 2;
+	}
+	return num_cpus;
+}
+
+static void
+smp_hdpu_message_pass(int target, int msg, unsigned long data, int wait)
+{
+	if (msg > 0x3) {
+		printk("SMP %d: smp_message_pass: unknown msg %d\n",
+		       smp_processor_id(), msg);
+		return;
+	}
+	switch (target) {
+	case MSG_ALL:
+		mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg);
+		mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg);
+		break;
+	case MSG_ALL_BUT_SELF:
+		if (smp_processor_id())
+			mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg);
+		else
+			mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg);
+		break;
+	default:
+		if (target == 0)
+			mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg);
+		else
+			mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg);
+		break;
+	}
+}
+
+static void smp_hdpu_kick_cpu(int nr)
+{
+	volatile unsigned int *bootaddr;
+
+	if (ppc_md.progress)
+		ppc_md.progress("smp_hdpu_kick_cpu", 0);
+
+	hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_CPU1_KICK);
+
+       /* Disable BootCS. Must also reduce the windows size to zero. */
+	bh.ci->disable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, 0, 0, 0);
+
+	bootaddr = ioremap(HDPU_INTERNAL_SRAM_BASE, HDPU_INTERNAL_SRAM_SIZE);
+	if (!bootaddr) {
+		if (ppc_md.progress)
+			ppc_md.progress("smp_hdpu_kick_cpu: ioremap failed", 0);
+		return;
+	}
+
+	memcpy((void *)(bootaddr + 0x40), (void *)&smp_hdpu_CPU_two, 0x20);
+
+	/* map SRAM to 0xfff00000 */
+	bh.ci->disable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+				 0xfff00000, HDPU_INTERNAL_SRAM_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+	/* Enable CPU1 arbitration */
+	mv64x60_clr_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1 << 9));
+
+	/*
+	 * Wait 100mSecond until other CPU has reached __secondary_start.
+	 * When it reaches, it is permittable to rever the SRAM mapping etc...
+	 */
+	mdelay(100);
+	*(unsigned long *)KERNELBASE = nr;
+	asm volatile ("dcbf 0,%0"::"r" (KERNELBASE):"memory");
+
+	iounmap(bootaddr);
+
+	/* Set up window for internal sram (256KByte insize) */
+	bh.ci->disable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+				 HDPU_INTERNAL_SRAM_BASE,
+				 HDPU_INTERNAL_SRAM_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+	/*
+	 * Set up windows for embedded FLASH (using boot CS window).
+	 */
+
+	bh.ci->disable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+				 HDPU_EMB_FLASH_BASE, HDPU_EMB_FLASH_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+}
+
+static void smp_hdpu_setup_cpu(int cpu_nr)
+{
+	if (cpu_nr == 0) {
+		if (ppc_md.progress)
+			ppc_md.progress("smp_hdpu_setup_cpu 0", 0);
+		mv64x60_write(&bh, MV64360_CPU0_DOORBELL_CLR, 0xff);
+		mv64x60_write(&bh, MV64360_CPU0_DOORBELL_MASK, 0xff);
+		request_irq(60, hdpu_smp_cpu0_int_handler,
+			    SA_INTERRUPT, hdpu_smp0, 0);
+	}
+
+	if (cpu_nr == 1) {
+		if (ppc_md.progress)
+			ppc_md.progress("smp_hdpu_setup_cpu 1", 0);
+
+		hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR |
+				  CPUSTATE_KERNEL_CPU1_OK);
+
+		/* Enable L1 Parity Bits */
+		hdpu_set_l1pe();
+
+		/* Enable L2 cache */
+		_set_L2CR(0);
+		_set_L2CR(0x80080000);
+
+		mv64x60_write(&bh, MV64360_CPU1_DOORBELL_CLR, 0x0);
+		mv64x60_write(&bh, MV64360_CPU1_DOORBELL_MASK, 0xff);
+		request_irq(28, hdpu_smp_cpu1_int_handler,
+			    SA_INTERRUPT, hdpu_smp1, 0);
+	}
+
+}
+
+void __devinit hdpu_tben_give()
+{
+	volatile unsigned long *val = 0;
+
+	/* By writing 0 to the TBEN_BASE, the timebases is frozen */
+	val = ioremap(HDPU_TBEN_BASE, 4);
+	*val = 0;
+	mb();
+
+	spin_lock(&timebase_lock);
+	timebase_upper = get_tbu();
+	timebase_lower = get_tbl();
+	spin_unlock(&timebase_lock);
+
+	while (timebase_upper || timebase_lower)
+		barrier();
+
+	/* By writing 1 to the TBEN_BASE, the timebases is thawed */
+	*val = 1;
+	mb();
+
+	iounmap(val);
+
+}
+
+void __devinit hdpu_tben_take()
+{
+	while (!(timebase_upper || timebase_lower))
+		barrier();
+
+	spin_lock(&timebase_lock);
+	set_tb(timebase_upper, timebase_lower);
+	timebase_upper = 0;
+	timebase_lower = 0;
+	spin_unlock(&timebase_lock);
+}
+
+static struct smp_ops_t hdpu_smp_ops = {
+	.message_pass = smp_hdpu_message_pass,
+	.probe = smp_hdpu_probe,
+	.kick_cpu = smp_hdpu_kick_cpu,
+	.setup_cpu = smp_hdpu_setup_cpu,
+	.give_timebase = hdpu_tben_give,
+	.take_timebase = hdpu_tben_take,
+};
+#endif				/* CONFIG_SMP */
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(r3, r4, r5, r6, r7);
+
+	isa_mem_base = 0;
+
+	ppc_md.setup_arch = hdpu_setup_arch;
+	ppc_md.init = hdpu_init2;
+	ppc_md.show_cpuinfo = hdpu_show_cpuinfo;
+	ppc_md.init_IRQ = hdpu_init_irq;
+	ppc_md.get_irq = mv64360_get_irq;
+	ppc_md.restart = hdpu_restart;
+	ppc_md.power_off = hdpu_power_off;
+	ppc_md.halt = hdpu_halt;
+	ppc_md.find_end_of_memory = hdpu_find_end_of_memory;
+	ppc_md.calibrate_decr = hdpu_calibrate_decr;
+	ppc_md.setup_io_mappings = hdpu_map_io;
+
+	bh.p_base = CONFIG_MV64X60_NEW_BASE;
+	bh.v_base = (unsigned long *)bh.p_base;
+
+	hdpu_set_bat();
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG)
+	ppc_md.progress = hdpu_mpsc_progress;	/* embedded UART */
+	mv64x60_progress_init(bh.p_base);
+#endif				/* CONFIG_SERIAL_TEXT_DEBUG */
+
+#ifdef CONFIG_SMP
+	ppc_md.smp_ops = &hdpu_smp_ops;
+#endif				/* CONFIG_SMP */
+
+#if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH)
+	platform_notify = hdpu_platform_notify;
+#endif
+	return;
+}
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
+/* SMP safe version of the serial text debug routine. Uses Semaphore 0 */
+void hdpu_mpsc_progress(char *s, unsigned short hex)
+{
+	while (mv64x60_read(&bh, MV64360_WHO_AM_I) !=
+	       mv64x60_read(&bh, MV64360_SEMAPHORE_0)) {
+	}
+	mv64x60_mpsc_progress(s, hex);
+	mv64x60_write(&bh, MV64360_SEMAPHORE_0, 0xff);
+}
+#endif
+
+static void hdpu_cpustate_set(unsigned char new_state)
+{
+	unsigned int state = (new_state << 21);
+	mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (0xff << 21));
+	mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, state);
+}
+
+#ifdef CONFIG_MTD_PHYSMAP
+static struct mtd_partition hdpu_partitions[] = {
+	{
+	 .name = "Root FS",
+	 .size = 0x03400000,
+	 .offset = 0,
+	 .mask_flags = 0,
+	 },{
+	 .name = "User FS",
+	 .size = 0x00800000,
+	 .offset = 0x03400000,
+	 .mask_flags = 0,
+	 },{
+	 .name = "Kernel Image",
+	 .size = 0x002C0000,
+	 .offset = 0x03C00000,
+	 .mask_flags = 0,
+	 },{
+	 .name = "bootEnv",
+	 .size = 0x00040000,
+	 .offset = 0x03EC0000,
+	 .mask_flags = 0,
+	 },{
+	 .name = "bootROM",
+	 .size = 0x00100000,
+	 .offset = 0x03F00000,
+	 .mask_flags = 0,
+	 }
+};
+
+static int __init hdpu_setup_mtd(void)
+{
+
+	physmap_set_partitions(hdpu_partitions, 5);
+	return 0;
+}
+
+arch_initcall(hdpu_setup_mtd);
+#endif
+
+#ifdef CONFIG_HDPU_FEATURES
+
+static struct resource hdpu_cpustate_resources[] = {
+	[0] = {
+	       .name = "addr base",
+	       .start = MV64x60_GPP_VALUE_SET,
+	       .end = MV64x60_GPP_VALUE_CLR + 1,
+	       .flags = IORESOURCE_MEM,
+	       },
+};
+
+static struct resource hdpu_nexus_resources[] = {
+	[0] = {
+	       .name = "nexus register",
+	       .start = HDPU_NEXUS_ID_BASE,
+	       .end = HDPU_NEXUS_ID_BASE + HDPU_NEXUS_ID_SIZE,
+	       .flags = IORESOURCE_MEM,
+	       },
+};
+
+static struct platform_device hdpu_cpustate_device = {
+	.name = HDPU_CPUSTATE_NAME,
+	.id = 0,
+	.num_resources = ARRAY_SIZE(hdpu_cpustate_resources),
+	.resource = hdpu_cpustate_resources,
+};
+
+static struct platform_device hdpu_nexus_device = {
+	.name = HDPU_NEXUS_NAME,
+	.id = 0,
+	.num_resources = ARRAY_SIZE(hdpu_nexus_resources),
+	.resource = hdpu_nexus_resources,
+};
+
+static int __init hdpu_add_pds(void)
+{
+	platform_device_register(&hdpu_cpustate_device);
+	platform_device_register(&hdpu_nexus_device);
+	return 0;
+}
+
+arch_initcall(hdpu_add_pds);
+#endif
diff --git a/arch/ppc/platforms/hdpu.h b/arch/ppc/platforms/hdpu.h
new file mode 100644
index 0000000..07c3cff
--- /dev/null
+++ b/arch/ppc/platforms/hdpu.h
@@ -0,0 +1,82 @@
+/*
+ * arch/ppc/platforms/hdpu.h
+ *
+ * Definitions for Sky Computers HDPU board.
+ *
+ * Brian Waite <waite@skycomputers.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by Mark A. Greer <mgreer@mvista.com>
+ * Based on code done by  Tim Montgomery <timm@artesyncp.com>
+ *
+ *
+ * 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.
+ */
+
+/*
+ * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to
+ * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
+ * We'll only use one PCI MEM window on each PCI bus.
+ *
+ * This is the CPU physical memory map (windows must be at least 64K and start
+ * on a boundary that is a multiple of the window size):
+ *
+ *    0x80000000-0x8fffffff	 - PCI 0 MEM
+ *    0xa0000000-0xafffffff	 - PCI 1 MEM
+ *    0xc0000000-0xc0ffffff	 - PCI 0 I/O
+ *    0xc1000000-0xc1ffffff	 - PCI 1 I/O
+
+ *    0xf1000000-0xf100ffff      - MV64360 Registers
+ *    0xf1010000-0xfb9fffff      - HOLE
+ *    0xfbfa0000-0xfbfaffff      - TBEN
+ *    0xfbf00000-0xfbfbffff      - NEXUS
+ *    0xfbfc0000-0xfbffffff      - Internal SRAM
+ *    0xfc000000-0xffffffff      - Boot window
+ */
+
+#ifndef __PPC_PLATFORMS_HDPU_H
+#define __PPC_PLATFORMS_HDPU_H
+
+/* CPU Physical Memory Map setup. */
+#define	HDPU_BRIDGE_REG_BASE		     0xf1000000
+
+#define HDPU_TBEN_BASE                        0xfbfa0000
+#define HDPU_TBEN_SIZE                        0x00010000
+#define HDPU_NEXUS_ID_BASE                    0xfbfb0000
+#define HDPU_NEXUS_ID_SIZE                    0x00010000
+#define HDPU_INTERNAL_SRAM_BASE               0xfbfc0000
+#define HDPU_INTERNAL_SRAM_SIZE               0x00040000
+#define	HDPU_EMB_FLASH_BASE		      0xfc000000
+#define	HDPU_EMB_FLASH_SIZE      	      0x04000000
+
+/* PCI Mappings */
+
+#define HDPU_PCI0_MEM_START_PROC_ADDR         0x80000000
+#define HDPU_PCI0_MEM_START_PCI_HI_ADDR       0x00000000
+#define HDPU_PCI0_MEM_START_PCI_LO_ADDR       HDPU_PCI0_MEM_START_PROC_ADDR
+#define HDPU_PCI0_MEM_SIZE                    0x10000000
+
+#define HDPU_PCI1_MEM_START_PROC_ADDR         0xc0000000
+#define HDPU_PCI1_MEM_START_PCI_HI_ADDR       0x00000000
+#define HDPU_PCI1_MEM_START_PCI_LO_ADDR       HDPU_PCI1_MEM_START_PROC_ADDR
+#define HDPU_PCI1_MEM_SIZE                    0x20000000
+
+#define HDPU_PCI0_IO_START_PROC_ADDR          0xc0000000
+#define HDPU_PCI0_IO_START_PCI_ADDR           0x00000000
+#define HDPU_PCI0_IO_SIZE                     0x01000000
+
+#define HDPU_PCI1_IO_START_PROC_ADDR          0xc1000000
+#define HDPU_PCI1_IO_START_PCI_ADDR           0x01000000
+#define HDPU_PCI1_IO_SIZE                     0x01000000
+
+#define HDPU_DEFAULT_BAUD 115200
+#define HDPU_MPSC_CLK_SRC 8	/* TCLK */
+#define HDPU_MPSC_CLK_FREQ 133000000	/* 133 Mhz */
+
+#define	HDPU_PCI_0_IRQ		(8+64)
+#define	HDPU_PCI_1_IRQ		(13+64)
+
+#endif				/* __PPC_PLATFORMS_HDPU_H */
diff --git a/arch/ppc/platforms/hermes.h b/arch/ppc/platforms/hermes.h
new file mode 100644
index 0000000..198fc59
--- /dev/null
+++ b/arch/ppc/platforms/hermes.h
@@ -0,0 +1,27 @@
+/*
+ * Multidata HERMES-PRO ( / SL ) board specific definitions
+ *
+ * Copyright (c) 2000, 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __MACH_HERMES_H
+#define __MACH_HERMES_H
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define	HERMES_IMMR_BASE    0xFF000000	/* phys. addr of IMMR			*/
+#define	HERMES_IMAP_SIZE   (64 * 1024)	/* size of mapped area			*/
+
+#define	IMAP_ADDR     HERMES_IMMR_BASE	/* physical base address of IMMR area	*/
+#define IMAP_SIZE     HERMES_IMAP_SIZE	/* mapped size of IMMR area		*/
+
+#define	FEC_INTERRUPT	 9		/* = SIU_LEVEL4				*/
+#define	CPM_INTERRUPT	11		/* = SIU_LEVEL5 (was: SIU_LEVEL2)	*/
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif	/* __MACH_HERMES_H */
diff --git a/arch/ppc/platforms/ip860.h b/arch/ppc/platforms/ip860.h
new file mode 100644
index 0000000..8c3836c
--- /dev/null
+++ b/arch/ppc/platforms/ip860.h
@@ -0,0 +1,36 @@
+/*
+ * MicroSys IP860 VMEBus board specific definitions
+ *
+ * Copyright (c) 2000, 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __MACH_IP860_H
+#define __MACH_IP860_H
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define	IP860_IMMR_BASE	0xF1000000	/* phys. addr of IMMR			*/
+#define	IP860_IMAP_SIZE	(64 * 1024)	/* size of mapped area			*/
+
+#define	IMAP_ADDR	IP860_IMMR_BASE	/* physical base address of IMMR area	*/
+#define IMAP_SIZE	IP860_IMAP_SIZE	/* mapped size of IMMR area		*/
+
+/*
+ * MPC8xx Chip Select Usage
+ */
+#define	IP860_BOOT_CS		0	/* Boot (VMEBus or Flash) Chip Select 0	*/
+#define IP860_FLASH_CS		1	/* Flash	    is on Chip Select 1	*/
+#define IP860_SDRAM_CS		2	/* SDRAM	    is on Chip Select 2	*/
+#define	IP860_SRAM_CS		3	/* SRAM		    is on Chip Select 3	*/
+#define IP860_BCSR_CS		4	/* BCSR		    is on Chip Select 4	*/
+#define IP860_IP_CS		5	/* IP Slots	   are on Chip Select 5	*/
+#define IP860_VME_STD_CS	6	/* VME Standard I/O is on Chip Select 6	*/
+#define IP860_VME_SHORT_CS	7	/* VME Short    I/O is on Chip Select 7	*/
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif	/* __MACH_IP860_H */
diff --git a/arch/ppc/platforms/ivms8.h b/arch/ppc/platforms/ivms8.h
new file mode 100644
index 0000000..d4be310
--- /dev/null
+++ b/arch/ppc/platforms/ivms8.h
@@ -0,0 +1,56 @@
+/*
+ * Speech Design Integrated Voicemail board specific definitions
+ * - IVMS8  (small,  8 channels)
+ * - IVML24 (large, 24 channels)
+ *
+ * In 2.5 when we force a new bootloader, we can merge these two, and add
+ * in _MACH_'s for them. -- Tom
+ *
+ * Copyright (c) 2000, 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IVMS8_H__
+#define __ASM_IVMS8_H__
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define IVMS_IMMR_BASE	0xFFF00000	/* phys. addr of IMMR */
+#define IVMS_IMAP_SIZE	(64 * 1024)	/* size of mapped area */
+
+#define IMAP_ADDR	IVMS_IMMR_BASE	/* phys. base address of IMMR area */
+#define IMAP_SIZE	IVMS_IMAP_SIZE	/* mapped size of IMMR area */
+
+#define PCMCIA_MEM_ADDR	((uint)0xFE100000)
+#define PCMCIA_MEM_SIZE	((uint)(64 * 1024))
+
+#define FEC_INTERRUPT	 9		/* = SIU_LEVEL4 */
+#define IDE0_INTERRUPT	10		/* = IRQ5 */
+#define CPM_INTERRUPT	11		/* = SIU_LEVEL5 (was: SIU_LEVEL2) */
+#define PHY_INTERRUPT	12		/* = IRQ6 */
+
+/* override the default number of IDE hardware interfaces */
+#define MAX_HWIFS	1
+
+/*
+ * Definitions for IDE0 Interface
+ */
+#define IDE0_BASE_OFFSET		0x0000	/* Offset in PCMCIA memory */
+#define IDE0_DATA_REG_OFFSET		0x0000
+#define IDE0_ERROR_REG_OFFSET		0x0081
+#define IDE0_NSECTOR_REG_OFFSET		0x0082
+#define IDE0_SECTOR_REG_OFFSET		0x0083
+#define IDE0_LCYL_REG_OFFSET		0x0084
+#define IDE0_HCYL_REG_OFFSET		0x0085
+#define IDE0_SELECT_REG_OFFSET		0x0086
+#define IDE0_STATUS_REG_OFFSET		0x0087
+#define IDE0_CONTROL_REG_OFFSET		0x0106
+#define IDE0_IRQ_REG_OFFSET		0x000A	/* not used */
+
+/* We don't use the 8259. */
+#define NR_8259_INTS	0
+
+#endif /* __ASM_IVMS8_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/k2.c b/arch/ppc/platforms/k2.c
new file mode 100644
index 0000000..aacb438
--- /dev/null
+++ b/arch/ppc/platforms/k2.c
@@ -0,0 +1,613 @@
+/*
+ * arch/ppc/platforms/k2.c
+ *
+ * Board setup routines for SBS K2
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * Updated by: Randy Vinson <rvinson@mvista.com.
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc.  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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+
+#include <syslib/cpc710.h>
+#include "k2.h"
+
+extern unsigned long loops_per_jiffy;
+extern void gen550_progress(char *, unsigned short);
+
+static unsigned int cpu_7xx[16] = {
+	0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+static unsigned int cpu_6xx[16] = {
+	0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0
+};
+
+static inline int __init
+k2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+	/*
+	 * Check our hose index.  If we are zero then we are on the
+	 * local PCI hose, otherwise we are on the cPCI hose.
+	 */
+	if (!hose->index) {
+		static char pci_irq_table[][4] =
+			/*
+			 * 	PCI IDSEL/INTPIN->INTLINE
+			 * 	A	B	C	D
+			 */
+		{
+			{1, 	0,	0,	0},	/* Ethernet */
+			{5,	5,	5,	5},	/* PMC Site 1 */
+			{6,	6,	6,	6},	/* PMC Site 2 */
+			{0,     0,      0,      0},     /* unused */
+			{0,     0,      0,      0},     /* unused */
+			{0,     0,      0,      0},     /* PCI-ISA Bridge */
+			{0,     0,      0,      0},     /* unused */
+			{0,     0,      0,      0},     /* unused */
+			{0,     0,      0,      0},     /* unused */
+			{0,     0,      0,      0},     /* unused */
+			{0,     0,      0,      0},     /* unused */
+			{0,     0,      0,      0},     /* unused */
+			{0,     0,      0,      0},     /* unused */
+			{0,     0,      0,      0},     /* unused */
+			{15,	0,	0,	0},	/* M5229 IDE */
+		};
+		const long min_idsel = 3, max_idsel = 17, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	} else {
+		static char pci_irq_table[][4] =
+		/*
+		 * 	PCI IDSEL/INTPIN->INTLINE
+		 * 	A	B	C	D
+		 */
+		{
+			{10, 	11,	12,	9},	/* cPCI slot 8 */
+			{11, 	12,	9,	10},	/* cPCI slot 7 */
+			{12, 	9,	10,	11},	/* cPCI slot 6 */
+			{9, 	10,	11,	12},	/* cPCI slot 5 */
+			{10, 	11,	12,	9},	/* cPCI slot 4 */
+			{11, 	12,	9,	10},	/* cPCI slot 3 */
+			{12, 	9,	10,	11},	/* cPCI slot 2 */
+		};
+		const long min_idsel = 15, max_idsel = 21, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	}
+}
+
+void k2_pcibios_fixup(void)
+{
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+	struct pci_dev *ide_dev;
+
+	/*
+	 * Enable DMA support on hdc
+	 */
+	ide_dev = pci_get_device(PCI_VENDOR_ID_AL,
+				  PCI_DEVICE_ID_AL_M5229, NULL);
+
+	if (ide_dev) {
+
+		unsigned long ide_dma_base;
+
+		ide_dma_base = pci_resource_start(ide_dev, 4);
+		outb(0x00, ide_dma_base + 0x2);
+		outb(0x20, ide_dma_base + 0xa);
+		pci_dev_put(ide_dev);
+	}
+#endif
+}
+
+void k2_pcibios_fixup_resources(struct pci_dev *dev)
+{
+	int i;
+
+	if ((dev->vendor == PCI_VENDOR_ID_IBM) &&
+	    (dev->device == PCI_DEVICE_ID_IBM_CPC710_PCI64)) {
+		pr_debug("Fixup CPC710 resources\n");
+		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+			dev->resource[i].start = 0;
+			dev->resource[i].end = 0;
+		}
+	}
+}
+
+void k2_setup_hoses(void)
+{
+	struct pci_controller *hose_a, *hose_b;
+
+	/*
+	 * Reconfigure CPC710 memory map so
+	 * we have some more PCI memory space.
+	 */
+
+	/* Set FPHB mode */
+	__raw_writel(0x808000e0, PGCHP);	/* Set FPHB mode */
+
+	/* PCI32 mappings */
+	__raw_writel(0x00000000, K2_PCI32_BAR + PIBAR);	/* PCI I/O base */
+	__raw_writel(0x00000000, K2_PCI32_BAR + PMBAR);	/* PCI Mem base */
+	__raw_writel(0xf0000000, K2_PCI32_BAR + MSIZE);	/* 256MB */
+	__raw_writel(0xfff00000, K2_PCI32_BAR + IOSIZE); /* 1MB */
+	__raw_writel(0xc0000000, K2_PCI32_BAR + SMBAR);	/* Base@0xc0000000 */
+	__raw_writel(0x80000000, K2_PCI32_BAR + SIBAR);	/* Base@0x80000000 */
+	__raw_writel(0x000000c0, K2_PCI32_BAR + PSSIZE); /* 1GB space */
+	__raw_writel(0x000000c0, K2_PCI32_BAR + PPSIZE); /* 1GB space */
+	__raw_writel(0x00000000, K2_PCI32_BAR + BARPS);	/* Base@0x00000000 */
+	__raw_writel(0x00000000, K2_PCI32_BAR + BARPP);	/* Base@0x00000000 */
+	__raw_writel(0x00000080, K2_PCI32_BAR + PSBAR);	/* Base@0x80 */
+	__raw_writel(0x00000000, K2_PCI32_BAR + PPBAR);
+
+	__raw_writel(0xc0000000, K2_PCI32_BAR + BPMDLK);
+	__raw_writel(0xd0000000, K2_PCI32_BAR + TPMDLK);
+	__raw_writel(0x80000000, K2_PCI32_BAR + BIODLK);
+	__raw_writel(0x80100000, K2_PCI32_BAR + TIODLK);
+	__raw_writel(0xe0008000, K2_PCI32_BAR + DLKCTRL);
+	__raw_writel(0xffffffff, K2_PCI32_BAR + DLKDEV);
+
+	/* PCI64 mappings */
+	__raw_writel(0x00100000, K2_PCI64_BAR + PIBAR);	/* PCI I/O base */
+	__raw_writel(0x10000000, K2_PCI64_BAR + PMBAR);	/* PCI Mem base */
+	__raw_writel(0xf0000000, K2_PCI64_BAR + MSIZE);	/* 256MB */
+	__raw_writel(0xfff00000, K2_PCI64_BAR + IOSIZE); /* 1MB */
+	__raw_writel(0xd0000000, K2_PCI64_BAR + SMBAR);	/* Base@0xd0000000 */
+	__raw_writel(0x80100000, K2_PCI64_BAR + SIBAR);	/* Base@0x80100000 */
+	__raw_writel(0x000000c0, K2_PCI64_BAR + PSSIZE); /* 1GB space */
+	__raw_writel(0x000000c0, K2_PCI64_BAR + PPSIZE); /* 1GB space */
+	__raw_writel(0x00000000, K2_PCI64_BAR + BARPS);	/* Base@0x00000000 */
+	__raw_writel(0x00000000, K2_PCI64_BAR + BARPP);	/* Base@0x00000000 */
+
+	/* Setup PCI32 hose */
+	hose_a = pcibios_alloc_controller();
+	if (!hose_a)
+		return;
+
+	hose_a->first_busno = 0;
+	hose_a->last_busno = 0xff;
+	hose_a->pci_mem_offset = K2_PCI32_MEM_BASE;
+
+	pci_init_resource(&hose_a->io_resource,
+			  K2_PCI32_LOWER_IO,
+			  K2_PCI32_UPPER_IO,
+			  IORESOURCE_IO, "PCI32 host bridge");
+
+	pci_init_resource(&hose_a->mem_resources[0],
+			  K2_PCI32_LOWER_MEM + K2_PCI32_MEM_BASE,
+			  K2_PCI32_UPPER_MEM + K2_PCI32_MEM_BASE,
+			  IORESOURCE_MEM, "PCI32 host bridge");
+
+	hose_a->io_space.start = K2_PCI32_LOWER_IO;
+	hose_a->io_space.end = K2_PCI32_UPPER_IO;
+	hose_a->mem_space.start = K2_PCI32_LOWER_MEM;
+	hose_a->mem_space.end = K2_PCI32_UPPER_MEM;
+	hose_a->io_base_virt = (void *)K2_ISA_IO_BASE;
+
+	setup_indirect_pci(hose_a, K2_PCI32_CONFIG_ADDR, K2_PCI32_CONFIG_DATA);
+
+	/* Initialize PCI32 bus registers */
+	early_write_config_byte(hose_a,
+				hose_a->first_busno,
+				PCI_DEVFN(0, 0),
+				CPC710_BUS_NUMBER, hose_a->first_busno);
+
+	early_write_config_byte(hose_a,
+				hose_a->first_busno,
+				PCI_DEVFN(0, 0),
+				CPC710_SUB_BUS_NUMBER, hose_a->last_busno);
+
+	/* Enable PCI interrupt polling */
+	early_write_config_byte(hose_a,
+				hose_a->first_busno,
+				PCI_DEVFN(8, 0), 0x45, 0x80);
+
+	/* Route polled PCI interrupts */
+	early_write_config_byte(hose_a,
+				hose_a->first_busno,
+				PCI_DEVFN(8, 0), 0x48, 0x58);
+
+	early_write_config_byte(hose_a,
+				hose_a->first_busno,
+				PCI_DEVFN(8, 0), 0x49, 0x07);
+
+	early_write_config_byte(hose_a,
+				hose_a->first_busno,
+				PCI_DEVFN(8, 0), 0x4a, 0x31);
+
+	early_write_config_byte(hose_a,
+				hose_a->first_busno,
+				PCI_DEVFN(8, 0), 0x4b, 0xb9);
+
+	/* route secondary IDE channel interrupt to IRQ 15 */
+	early_write_config_byte(hose_a,
+				hose_a->first_busno,
+				PCI_DEVFN(8, 0), 0x75, 0x0f);
+
+	/* enable IDE controller IDSEL */
+	early_write_config_byte(hose_a,
+				hose_a->first_busno,
+				PCI_DEVFN(8, 0), 0x58, 0x48);
+
+	/* Enable IDE function */
+	early_write_config_byte(hose_a,
+				hose_a->first_busno,
+				PCI_DEVFN(17, 0), 0x50, 0x03);
+
+	/* Set M5229 IDE controller to native mode */
+	early_write_config_byte(hose_a,
+				hose_a->first_busno,
+				PCI_DEVFN(17, 0), PCI_CLASS_PROG, 0xdf);
+
+	hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
+
+	/* Write out correct max subordinate bus number for hose A */
+	early_write_config_byte(hose_a,
+				hose_a->first_busno,
+				PCI_DEVFN(0, 0),
+				CPC710_SUB_BUS_NUMBER, hose_a->last_busno);
+
+	/* Only setup PCI64 hose if we are in the system slot */
+	if (!(readb(K2_MISC_REG) & K2_SYS_SLOT_MASK)) {
+		/* Setup PCI64 hose */
+		hose_b = pcibios_alloc_controller();
+		if (!hose_b)
+			return;
+
+		hose_b->first_busno = hose_a->last_busno + 1;
+		hose_b->last_busno = 0xff;
+
+		/* Reminder: quit changing the following, it is correct. */
+		hose_b->pci_mem_offset = K2_PCI32_MEM_BASE;
+
+		pci_init_resource(&hose_b->io_resource,
+				  K2_PCI64_LOWER_IO,
+				  K2_PCI64_UPPER_IO,
+				  IORESOURCE_IO, "PCI64 host bridge");
+
+		pci_init_resource(&hose_b->mem_resources[0],
+				  K2_PCI64_LOWER_MEM + K2_PCI32_MEM_BASE,
+				  K2_PCI64_UPPER_MEM + K2_PCI32_MEM_BASE,
+				  IORESOURCE_MEM, "PCI64 host bridge");
+
+		hose_b->io_space.start = K2_PCI64_LOWER_IO;
+		hose_b->io_space.end = K2_PCI64_UPPER_IO;
+		hose_b->mem_space.start = K2_PCI64_LOWER_MEM;
+		hose_b->mem_space.end = K2_PCI64_UPPER_MEM;
+		hose_b->io_base_virt = (void *)K2_ISA_IO_BASE;
+
+		setup_indirect_pci(hose_b,
+				   K2_PCI64_CONFIG_ADDR, K2_PCI64_CONFIG_DATA);
+
+		/* Initialize PCI64 bus registers */
+		early_write_config_byte(hose_b,
+					0,
+					PCI_DEVFN(0, 0),
+					CPC710_SUB_BUS_NUMBER, 0xff);
+
+		early_write_config_byte(hose_b,
+					0,
+					PCI_DEVFN(0, 0),
+					CPC710_BUS_NUMBER, hose_b->first_busno);
+
+		hose_b->last_busno = pciauto_bus_scan(hose_b,
+						      hose_b->first_busno);
+
+		/* Write out correct max subordinate bus number for hose B */
+		early_write_config_byte(hose_b,
+					hose_b->first_busno,
+					PCI_DEVFN(0, 0),
+					CPC710_SUB_BUS_NUMBER,
+					hose_b->last_busno);
+
+		/* Configure PCI64 PSBAR */
+		early_write_config_dword(hose_b,
+					 hose_b->first_busno,
+					 PCI_DEVFN(0, 0),
+					 PCI_BASE_ADDRESS_0,
+					 K2_PCI64_SYS_MEM_BASE);
+	}
+
+	/* Configure i8259 level/edge settings */
+	outb(0x62, 0x4d0);
+	outb(0xde, 0x4d1);
+
+#ifdef CONFIG_CPC710_DATA_GATHERING
+	{
+		unsigned int tmp;
+		tmp = __raw_readl(ABCNTL);
+		/* Enable data gathering on both PCI interfaces */
+		__raw_writel(tmp | 0x05000000, ABCNTL);
+	}
+#endif
+
+	ppc_md.pcibios_fixup = k2_pcibios_fixup;
+	ppc_md.pcibios_fixup_resources = k2_pcibios_fixup_resources;
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = k2_map_irq;
+}
+
+static int k2_get_bus_speed(void)
+{
+	int bus_speed;
+	unsigned char board_id;
+
+	board_id = *(unsigned char *)K2_BOARD_ID_REG;
+
+	switch (K2_BUS_SPD(board_id)) {
+
+	case 0:
+	default:
+		bus_speed = 100000000;
+		break;
+
+	case 1:
+		bus_speed = 83333333;
+		break;
+
+	case 2:
+		bus_speed = 75000000;
+		break;
+
+	case 3:
+		bus_speed = 66666666;
+		break;
+	}
+	return bus_speed;
+}
+
+static int k2_get_cpu_speed(void)
+{
+	unsigned long hid1;
+	int cpu_speed;
+
+	hid1 = mfspr(SPRN_HID1) >> 28;
+
+	if ((mfspr(SPRN_PVR) >> 16) == 8)
+		hid1 = cpu_7xx[hid1];
+	else
+		hid1 = cpu_6xx[hid1];
+
+	cpu_speed = k2_get_bus_speed() * hid1 / 2;
+	return cpu_speed;
+}
+
+static void __init k2_calibrate_decr(void)
+{
+	int freq, divisor = 4;
+
+	/* determine processor bus speed */
+	freq = k2_get_bus_speed();
+	tb_ticks_per_jiffy = freq / HZ / divisor;
+	tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
+}
+
+static int k2_show_cpuinfo(struct seq_file *m)
+{
+	unsigned char k2_geo_bits, k2_system_slot;
+
+	seq_printf(m, "vendor\t\t: SBS\n");
+	seq_printf(m, "machine\t\t: K2\n");
+	seq_printf(m, "cpu speed\t: %dMhz\n", k2_get_cpu_speed() / 1000000);
+	seq_printf(m, "bus speed\t: %dMhz\n", k2_get_bus_speed() / 1000000);
+	seq_printf(m, "memory type\t: SDRAM\n");
+
+	k2_geo_bits = readb(K2_MSIZ_GEO_REG) & K2_GEO_ADR_MASK;
+	k2_system_slot = !(readb(K2_MISC_REG) & K2_SYS_SLOT_MASK);
+	seq_printf(m, "backplane\t: %s slot board",
+		   k2_system_slot ? "System" : "Non system");
+	seq_printf(m, "with geographical address %x\n", k2_geo_bits);
+
+	return 0;
+}
+
+TODC_ALLOC();
+
+static void __init k2_setup_arch(void)
+{
+	unsigned int cpu;
+
+	/* Setup TODC access */
+	TODC_INIT(TODC_TYPE_MK48T37, 0, 0,
+		  ioremap(K2_RTC_BASE_ADDRESS, K2_RTC_SIZE), 8);
+
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000 / HZ;
+
+	/* make FLASH transactions higher priority than PCI to avoid deadlock */
+	__raw_writel(__raw_readl(SIOC1) | 0x80000000, SIOC1);
+
+	/* Set hardware to access FLASH page 2 */
+	__raw_writel(1 << 29, GPOUT);
+
+	/* Setup PCI host bridges */
+	k2_setup_hoses();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDC1;
+#endif
+
+	/* Identify the system */
+	printk(KERN_INFO "System Identification: SBS K2 - PowerPC 750 @ "
+			"%d Mhz\n", k2_get_cpu_speed() / 1000000);
+	printk(KERN_INFO "Port by MontaVista Software, Inc. "
+			"(source@mvista.com)\n");
+
+	/* Identify the CPU manufacturer */
+	cpu = PVR_REV(mfspr(SPRN_PVR));
+	printk(KERN_INFO "CPU manufacturer: %s [rev=%04x]\n",
+			(cpu & (1 << 15)) ? "IBM" : "Motorola", cpu);
+}
+
+static void k2_restart(char *cmd)
+{
+	local_irq_disable();
+
+	/* Flip FLASH back to page 1 to access firmware image */
+	__raw_writel(0, GPOUT);
+
+	/* SRR0 has system reset vector, SRR1 has default MSR value */
+	/* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
+	mtspr(SPRN_SRR0, 0xfff00100);
+	mtspr(SPRN_SRR1, 0);
+	__asm__ __volatile__("rfi\n\t");
+
+	/* not reached */
+	for (;;) ;
+}
+
+static void k2_power_off(void)
+{
+	for (;;) ;
+}
+
+static void k2_halt(void)
+{
+	k2_restart(NULL);
+}
+
+/*
+ * Set BAT 3 to map PCI32 I/O space.
+ */
+static __inline__ void k2_set_bat(void)
+{
+	/* wait for all outstanding memory accesses to complete */
+	mb();
+
+	/* setup DBATs */
+	mtspr(SPRN_DBAT2U, 0x80001ffe);
+	mtspr(SPRN_DBAT2L, 0x8000002a);
+	mtspr(SPRN_DBAT3U, 0xf0001ffe);
+	mtspr(SPRN_DBAT3L, 0xf000002a);
+
+	/* wait for updates */
+	mb();
+}
+
+static unsigned long __init k2_find_end_of_memory(void)
+{
+	unsigned long total;
+	unsigned char msize = 7;	/* Default to 128MB */
+
+	msize = K2_MEM_SIZE(readb(K2_MSIZ_GEO_REG));
+
+	switch (msize) {
+	case 2:
+		/*
+		 * This will break without a lowered
+		 * KERNELBASE or CONFIG_HIGHMEM on.
+		 * It seems non 1GB builds exist yet,
+		 * though.
+		 */
+		total = K2_MEM_SIZE_1GB;
+		break;
+	case 3:
+	case 4:
+		total = K2_MEM_SIZE_512MB;
+		break;
+	case 5:
+	case 6:
+		total = K2_MEM_SIZE_256MB;
+		break;
+	case 7:
+		total = K2_MEM_SIZE_128MB;
+		break;
+	default:
+		printk
+		    ("K2: Invalid memory size detected, defaulting to 128MB\n");
+		total = K2_MEM_SIZE_128MB;
+		break;
+	}
+	return total;
+}
+
+static void __init k2_map_io(void)
+{
+	io_block_mapping(K2_PCI32_IO_BASE,
+			 K2_PCI32_IO_BASE, 0x00200000, _PAGE_IO);
+	io_block_mapping(0xff000000, 0xff000000, 0x01000000, _PAGE_IO);
+}
+
+static void __init k2_init_irq(void)
+{
+	int i;
+
+	for (i = 0; i < 16; i++)
+		irq_desc[i].handler = &i8259_pic;
+
+	i8259_init(0);
+}
+
+void __init platform_init(unsigned long r3, unsigned long r4,
+			  unsigned long r5, unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo((struct bi_record *)(r3 + KERNELBASE));
+
+	k2_set_bat();
+
+	isa_io_base = K2_ISA_IO_BASE;
+	isa_mem_base = K2_ISA_MEM_BASE;
+	pci_dram_offset = K2_PCI32_SYS_MEM_BASE;
+
+	ppc_md.setup_arch = k2_setup_arch;
+	ppc_md.show_cpuinfo = k2_show_cpuinfo;
+	ppc_md.init_IRQ = k2_init_irq;
+	ppc_md.get_irq = i8259_irq;
+
+	ppc_md.find_end_of_memory = k2_find_end_of_memory;
+	ppc_md.setup_io_mappings = k2_map_io;
+
+	ppc_md.restart = k2_restart;
+	ppc_md.power_off = k2_power_off;
+	ppc_md.halt = k2_halt;
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.calibrate_decr = k2_calibrate_decr;
+
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = gen550_progress;
+#endif
+}
diff --git a/arch/ppc/platforms/k2.h b/arch/ppc/platforms/k2.h
new file mode 100644
index 0000000..78326ab
--- /dev/null
+++ b/arch/ppc/platforms/k2.h
@@ -0,0 +1,82 @@
+/*
+ * arch/ppc/platforms/k2.h
+ *
+ * Definitions for SBS K2 board support
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifndef __PPC_PLATFORMS_K2_H
+#define __PPC_PLATFORMS_K2_H
+
+/*
+ * SBS K2 definitions
+ */
+
+#define	K2_PCI64_BAR		0xff400000
+#define	K2_PCI32_BAR		0xff500000
+
+#define K2_PCI64_CONFIG_ADDR	(K2_PCI64_BAR + 0x000f8000)
+#define K2_PCI64_CONFIG_DATA	(K2_PCI64_BAR + 0x000f8010)
+
+#define K2_PCI32_CONFIG_ADDR	(K2_PCI32_BAR + 0x000f8000)
+#define K2_PCI32_CONFIG_DATA	(K2_PCI32_BAR + 0x000f8010)
+
+#define K2_PCI64_MEM_BASE	0xd0000000
+#define K2_PCI64_IO_BASE	0x80100000
+
+#define K2_PCI32_MEM_BASE	0xc0000000
+#define K2_PCI32_IO_BASE	0x80000000
+
+#define K2_PCI32_SYS_MEM_BASE	0x80000000
+#define K2_PCI64_SYS_MEM_BASE	K2_PCI32_SYS_MEM_BASE
+
+#define K2_PCI32_LOWER_MEM	0x00000000
+#define K2_PCI32_UPPER_MEM	0x0fffffff
+#define K2_PCI32_LOWER_IO	0x00000000
+#define K2_PCI32_UPPER_IO	0x000fffff
+
+#define K2_PCI64_LOWER_MEM	0x10000000
+#define K2_PCI64_UPPER_MEM	0x1fffffff
+#define K2_PCI64_LOWER_IO	0x00100000
+#define	K2_PCI64_UPPER_IO	0x001fffff
+
+#define K2_ISA_IO_BASE		K2_PCI32_IO_BASE
+#define K2_ISA_MEM_BASE		K2_PCI32_MEM_BASE
+
+#define K2_BOARD_ID_REG		(K2_ISA_IO_BASE + 0x800)
+#define K2_MISC_REG		(K2_ISA_IO_BASE + 0x804)
+#define K2_MSIZ_GEO_REG		(K2_ISA_IO_BASE + 0x808)
+#define K2_HOT_SWAP_REG		(K2_ISA_IO_BASE + 0x80c)
+#define K2_PLD2_REG		(K2_ISA_IO_BASE + 0x80e)
+#define K2_PLD3_REG		(K2_ISA_IO_BASE + 0x80f)
+
+#define K2_BUS_SPD(board_id)	(board_id >> 2) & 3
+
+#define K2_RTC_BASE_OFFSET	0x90000
+#define K2_RTC_BASE_ADDRESS	(K2_PCI32_MEM_BASE + K2_RTC_BASE_OFFSET)
+#define K2_RTC_SIZE		0x8000
+
+#define K2_MEM_SIZE_MASK	0xe0
+#define K2_MEM_SIZE(size_reg)	(size_reg & K2_MEM_SIZE_MASK) >> 5
+#define	K2_MEM_SIZE_1GB		0x40000000
+#define K2_MEM_SIZE_512MB	0x20000000
+#define K2_MEM_SIZE_256MB	0x10000000
+#define K2_MEM_SIZE_128MB	0x08000000
+
+#define K2_L2CACHE_MASK		0x03	/* Mask for 2 L2 Cache bits */
+#define K2_L2CACHE_512KB	0x00	/* 512KB */
+#define K2_L2CACHE_256KB	0x01	/* 256KB */
+#define K2_L2CACHE_1MB		0x02	/* 1MB */
+#define K2_L2CACHE_NONE		0x03	/* None */
+
+#define K2_GEO_ADR_MASK		0x1f
+
+#define K2_SYS_SLOT_MASK	0x08
+
+#endif /* __PPC_PLATFORMS_K2_H */
diff --git a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c
new file mode 100644
index 0000000..eda922a
--- /dev/null
+++ b/arch/ppc/platforms/katana.c
@@ -0,0 +1,795 @@
+/*
+ * arch/ppc/platforms/katana.c
+ *
+ * Board setup routines for the Artesyn Katana cPCI boards.
+ *
+ * Author: Tim Montgomery <timm@artesyncp.com>
+ * Maintained by: Mark A. Greer <mgreer@mvista.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by - Mark A. Greer <mgreer@mvista.com>
+ *
+ * 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.
+ */
+/*
+ * Supports the Artesyn 750i, 752i, and 3750.  The 752i is virtually identical
+ * to the 750i except that it has an mv64460 bridge.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/console.h>
+#include <linux/initrd.h>
+#include <linux/root_dev.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/bootmem.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mv643xx.h>
+#ifdef CONFIG_BOOTIMG
+#include <linux/bootimg.h>
+#endif
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/smp.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/ppcboot.h>
+#include <asm/mv64x60.h>
+#include <platforms/katana.h>
+
+static struct		mv64x60_handle bh;
+static katana_id_t	katana_id;
+static void __iomem	*cpld_base;
+static void __iomem	*sram_base;
+
+static u32		katana_flash_size_0;
+static u32		katana_flash_size_1;
+
+static u32		katana_bus_frequency;
+
+unsigned char	__res[sizeof(bd_t)];
+
+/* PCI Interrupt routing */
+static int __init
+katana_irq_lookup_750i(unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] = {
+		/*
+		 * PCI IDSEL/INTPIN->INTLINE
+		 *       A   B   C   D
+		 */
+		/* IDSEL 4  (PMC 1) */
+		{ KATANA_PCI_INTB_IRQ_750i, KATANA_PCI_INTC_IRQ_750i,
+			KATANA_PCI_INTD_IRQ_750i, KATANA_PCI_INTA_IRQ_750i },
+		/* IDSEL 5  (PMC 2) */
+		{ KATANA_PCI_INTC_IRQ_750i, KATANA_PCI_INTD_IRQ_750i,
+			KATANA_PCI_INTA_IRQ_750i, KATANA_PCI_INTB_IRQ_750i },
+		/* IDSEL 6 (T8110) */
+		{KATANA_PCI_INTD_IRQ_750i, 0, 0, 0 },
+	};
+	const long min_idsel = 4, max_idsel = 6, irqs_per_slot = 4;
+
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static int __init
+katana_irq_lookup_3750(unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] = {
+		/*
+		 * PCI IDSEL/INTPIN->INTLINE
+		 *       A   B   C   D
+		 */
+		{ KATANA_PCI_INTA_IRQ_3750, 0, 0, 0 }, /* IDSEL 3 (BCM5691) */
+		{ KATANA_PCI_INTB_IRQ_3750, 0, 0, 0 }, /* IDSEL 4 (MV64360 #2)*/
+		{ KATANA_PCI_INTC_IRQ_3750, 0, 0, 0 }, /* IDSEL 5 (MV64360 #3)*/
+	};
+	const long min_idsel = 3, max_idsel = 5, irqs_per_slot = 4;
+
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static int __init
+katana_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	switch (katana_id) {
+	case KATANA_ID_750I:
+	case KATANA_ID_752I:
+		return katana_irq_lookup_750i(idsel, pin);
+
+	case KATANA_ID_3750:
+		return katana_irq_lookup_3750(idsel, pin);
+
+	default:
+		printk(KERN_ERR "Bogus board ID\n");
+		return 0;
+	}
+}
+
+/* Board info retrieval routines */
+void __init
+katana_get_board_id(void)
+{
+	switch (in_8(cpld_base + KATANA_CPLD_PRODUCT_ID)) {
+	case KATANA_PRODUCT_ID_3750:
+		katana_id = KATANA_ID_3750;
+		break;
+
+	case KATANA_PRODUCT_ID_750i:
+		katana_id = KATANA_ID_750I;
+		break;
+
+	case KATANA_PRODUCT_ID_752i:
+		katana_id = KATANA_ID_752I;
+		break;
+
+	default:
+		printk(KERN_ERR "Unsupported board\n");
+	}
+}
+
+int __init
+katana_get_proc_num(void)
+{
+	u16		val;
+	u8		save_exclude;
+	static int	proc = -1;
+	static u8	first_time = 1;
+
+	if (first_time) {
+		if (katana_id != KATANA_ID_3750)
+			proc = 0;
+		else {
+			save_exclude = mv64x60_pci_exclude_bridge;
+			mv64x60_pci_exclude_bridge = 0;
+
+			early_read_config_word(bh.hose_a, 0,
+				PCI_DEVFN(0,0), PCI_DEVICE_ID, &val);
+
+			mv64x60_pci_exclude_bridge = save_exclude;
+
+			switch(val) {
+			case PCI_DEVICE_ID_KATANA_3750_PROC0:
+				proc = 0;
+				break;
+
+			case PCI_DEVICE_ID_KATANA_3750_PROC1:
+				proc = 1;
+				break;
+
+			case PCI_DEVICE_ID_KATANA_3750_PROC2:
+				proc = 2;
+				break;
+
+			default:
+				printk(KERN_ERR "Bogus Device ID\n");
+			}
+		}
+
+		first_time = 0;
+	}
+
+	return proc;
+}
+
+static inline int
+katana_is_monarch(void)
+{
+	return in_8(cpld_base + KATANA_CPLD_BD_CFG_3) &
+		KATANA_CPLD_BD_CFG_3_MONARCH;
+}
+
+static void __init
+katana_setup_bridge(void)
+{
+	struct pci_controller hose;
+	struct mv64x60_setup_info si;
+	void __iomem *vaddr;
+	int i;
+	u16 val;
+	u8 save_exclude;
+
+	/*
+	 * Some versions of the Katana firmware mistakenly change the vendor
+	 * & device id fields in the bridge's pci device (visible via pci
+	 * config accesses).  This breaks mv64x60_init() because those values
+	 * are used to identify the type of bridge that's there.  Artesyn
+	 * claims that the subsystem vendor/device id's will have the correct
+	 * Marvell values so this code puts back the correct values from there.
+	 */
+	memset(&hose, 0, sizeof(hose));
+	vaddr = ioremap(CONFIG_MV64X60_NEW_BASE, MV64x60_INTERNAL_SPACE_SIZE);
+	setup_indirect_pci_nomap(&hose, vaddr + MV64x60_PCI0_CONFIG_ADDR,
+		vaddr + MV64x60_PCI0_CONFIG_DATA);
+	save_exclude = mv64x60_pci_exclude_bridge;
+	mv64x60_pci_exclude_bridge = 0;
+
+	early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID, &val);
+
+	if (val != PCI_VENDOR_ID_MARVELL) {
+		early_read_config_word(&hose, 0, PCI_DEVFN(0, 0),
+			PCI_SUBSYSTEM_VENDOR_ID, &val);
+		early_write_config_word(&hose, 0, PCI_DEVFN(0, 0),
+			PCI_VENDOR_ID, val);
+		early_read_config_word(&hose, 0, PCI_DEVFN(0, 0),
+			PCI_SUBSYSTEM_ID, &val);
+		early_write_config_word(&hose, 0, PCI_DEVFN(0, 0),
+			PCI_DEVICE_ID, val);
+	}
+
+	mv64x60_pci_exclude_bridge = save_exclude;
+	iounmap(vaddr);
+
+	memset(&si, 0, sizeof(si));
+
+	si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
+
+	si.pci_1.enable_bus = 1;
+	si.pci_1.pci_io.cpu_base = KATANA_PCI1_IO_START_PROC_ADDR;
+	si.pci_1.pci_io.pci_base_hi = 0;
+	si.pci_1.pci_io.pci_base_lo = KATANA_PCI1_IO_START_PCI_ADDR;
+	si.pci_1.pci_io.size = KATANA_PCI1_IO_SIZE;
+	si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_1.pci_mem[0].cpu_base = KATANA_PCI1_MEM_START_PROC_ADDR;
+	si.pci_1.pci_mem[0].pci_base_hi = KATANA_PCI1_MEM_START_PCI_HI_ADDR;
+	si.pci_1.pci_mem[0].pci_base_lo = KATANA_PCI1_MEM_START_PCI_LO_ADDR;
+	si.pci_1.pci_mem[0].size = KATANA_PCI1_MEM_SIZE;
+	si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_1.pci_cmd_bits = 0;
+	si.pci_1.latency_timer = 0x80;
+
+	for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) {
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+		si.cpu_prot_options[i] = 0;
+		si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
+		si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
+		si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
+
+		si.pci_1.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+#else
+		si.cpu_prot_options[i] = 0;
+		si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; /* errata */
+		si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; /* errata */
+		si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; /* errata */
+
+		si.pci_1.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_WB |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+#endif
+	}
+
+	/* Lookup PCI host bridges */
+	if (mv64x60_init(&bh, &si))
+		printk(KERN_WARNING "Bridge initialization failed.\n");
+
+	pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = katana_map_irq;
+	ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
+
+	mv64x60_set_bus(&bh, 1, 0);
+	bh.hose_b->first_busno = 0;
+	bh.hose_b->last_busno = 0xff;
+}
+
+/* Bridge & platform setup routines */
+void __init
+katana_intr_setup(void)
+{
+	/* MPP 8, 9, and 10 */
+	mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1, 0xfff);
+
+	/* MPP 14 */
+	if ((katana_id == KATANA_ID_750I) || (katana_id == KATANA_ID_752I))
+		mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1, 0x0f000000);
+
+	/*
+	 * Define GPP 8,9,and 10 interrupt polarity as active low
+	 * input signal and level triggered
+	 */
+	mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, 0x700);
+	mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, 0x700);
+
+	if ((katana_id == KATANA_ID_750I) || (katana_id == KATANA_ID_752I)) {
+		mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, (1<<14));
+		mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, (1<<14));
+	}
+
+	/* Config GPP intr ctlr to respond to level trigger */
+	mv64x60_set_bits(&bh, MV64x60_COMM_ARBITER_CNTL, (1<<10));
+
+	/* Erranum FEr PCI-#8 */
+	mv64x60_clr_bits(&bh, MV64x60_PCI0_CMD, (1<<5) | (1<<9));
+	mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1<<5) | (1<<9));
+
+	/*
+	 * Dismiss and then enable interrupt on GPP interrupt cause
+	 * for CPU #0
+	 */
+	mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~0x700);
+	mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, 0x700);
+
+	if ((katana_id == KATANA_ID_750I) || (katana_id == KATANA_ID_752I)) {
+		mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~(1<<14));
+		mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, (1<<14));
+	}
+
+	/*
+	 * Dismiss and then enable interrupt on CPU #0 high cause reg
+	 * BIT25 summarizes GPP interrupts 8-15
+	 */
+	mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, (1<<25));
+}
+
+void __init
+katana_setup_peripherals(void)
+{
+	u32 base;
+
+	/* Set up windows for boot CS, soldered & socketed flash, and CPLD */
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+		 KATANA_BOOT_WINDOW_BASE, KATANA_BOOT_WINDOW_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+
+	/* Assume firmware set up window sizes correctly for dev 0 & 1 */
+	mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, &base,
+		&katana_flash_size_0);
+
+	if (katana_flash_size_0 > 0) {
+		mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN,
+			 KATANA_SOLDERED_FLASH_BASE, katana_flash_size_0, 0);
+		bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
+	}
+
+	mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, &base,
+		&katana_flash_size_1);
+
+	if (katana_flash_size_1 > 0) {
+		mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,
+			 (KATANA_SOLDERED_FLASH_BASE + katana_flash_size_0),
+			 katana_flash_size_1, 0);
+		bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+	}
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN,
+		 KATANA_SOCKET_BASE, KATANA_SOCKETED_FLASH_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN,
+		 KATANA_CPLD_BASE, KATANA_CPLD_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
+	cpld_base = ioremap(KATANA_CPLD_BASE, KATANA_CPLD_SIZE);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+		 KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+	sram_base = ioremap(KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE);
+
+	/* Set up Enet->SRAM window */
+	mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN,
+		KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0x2);
+	bh.ci->enable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN);
+
+	/* Give enet r/w access to memory region */
+	mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_0, (0x3 << (4 << 1)));
+	mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_1, (0x3 << (4 << 1)));
+	mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_2, (0x3 << (4 << 1)));
+
+	mv64x60_clr_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, (1 << 3));
+	mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL,
+			 ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24)));
+
+	/* Must wait until window set up before retrieving board id */
+	katana_get_board_id();
+
+	/* Enumerate pci bus (must know board id before getting proc number) */
+	if (katana_get_proc_num() == 0)
+		bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b, 0);
+
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+	mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x00160000);
+#else
+	mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2);
+#endif
+
+	/*
+	 * Setting the SRAM to 0. Note that this generates parity errors on
+	 * internal data path in SRAM since it's first time accessing it
+	 * while after reset it's not configured.
+	 */
+	memset(sram_base, 0, MV64360_SRAM_SIZE);
+
+	/* Only processor zero [on 3750] is an PCI interrupt controller */
+	if (katana_get_proc_num() == 0)
+		katana_intr_setup();
+}
+
+static void __init
+katana_enable_ipmi(void)
+{
+	u8 reset_out;
+
+	/* Enable access to IPMI ctlr by clearing IPMI PORTSEL bit in CPLD */
+	reset_out = in_8(cpld_base + KATANA_CPLD_RESET_OUT);
+	reset_out &= ~KATANA_CPLD_RESET_OUT_PORTSEL;
+	out_8(cpld_base + KATANA_CPLD_RESET_OUT, reset_out);
+}
+
+static void __init
+katana_setup_arch(void)
+{
+	if (ppc_md.progress)
+		ppc_md.progress("katana_setup_arch: enter", 0);
+
+	set_tb(0, 0);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef   CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA2;
+#endif
+
+	/*
+	 * Set up the L2CR register.
+	 *
+	 * 750FX has only L2E, L2PE (bits 2-8 are reserved)
+	 * DD2.0 has bug that requires the L2 to be in WRT mode
+	 * avoid dirty data in cache
+	 */
+	if (PVR_REV(mfspr(SPRN_PVR)) == 0x0200) {
+		printk(KERN_INFO "DD2.0 detected. Setting L2 cache"
+			"to Writethrough mode\n");
+		_set_L2CR(L2CR_L2E | L2CR_L2PE | L2CR_L2WT);
+	} else
+		_set_L2CR(L2CR_L2E | L2CR_L2PE);
+
+	if (ppc_md.progress)
+		ppc_md.progress("katana_setup_arch: calling setup_bridge", 0);
+
+	katana_setup_bridge();
+	katana_setup_peripherals();
+	katana_enable_ipmi();
+
+	katana_bus_frequency = katana_bus_freq(cpld_base);
+
+	printk(KERN_INFO "Artesyn Communication Products, LLC - Katana(TM)\n");
+	if (ppc_md.progress)
+		ppc_md.progress("katana_setup_arch: exit", 0);
+}
+
+/* Platform device data fixup routines. */
+#if defined(CONFIG_SERIAL_MPSC)
+static void __init
+katana_fixup_mpsc_pdata(struct platform_device *pdev)
+{
+	struct mpsc_pdata *pdata;
+
+	pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
+
+	pdata->max_idle = 40;
+	pdata->default_baud = KATANA_DEFAULT_BAUD;
+	pdata->brg_clk_src = KATANA_MPSC_CLK_SRC;
+	/*
+	 * TCLK (not SysCLk) is routed to BRG, then to the MPSC.  On most parts,
+	 * TCLK == SysCLK but on 64460, they are separate pins.
+	 * SysCLK can go up to 200 MHz but TCLK can only go up to 133 MHz.
+	 */
+	pdata->brg_clk_freq = min(katana_bus_frequency, MV64x60_TCLK_FREQ_MAX);
+}
+#endif
+
+#if defined(CONFIG_MV643XX_ETH)
+static void __init
+katana_fixup_eth_pdata(struct platform_device *pdev)
+{
+	struct mv643xx_eth_platform_data *eth_pd;
+	static u16 phy_addr[] = {
+		KATANA_ETH0_PHY_ADDR,
+		KATANA_ETH1_PHY_ADDR,
+		KATANA_ETH2_PHY_ADDR,
+	};
+
+	eth_pd = pdev->dev.platform_data;
+	eth_pd->force_phy_addr = 1;
+	eth_pd->phy_addr = phy_addr[pdev->id];
+	eth_pd->tx_queue_size = KATANA_ETH_TX_QUEUE_SIZE;
+	eth_pd->rx_queue_size = KATANA_ETH_RX_QUEUE_SIZE;
+}
+#endif
+
+static int __init
+katana_platform_notify(struct device *dev)
+{
+	static struct {
+		char	*bus_id;
+		void	((*rtn)(struct platform_device *pdev));
+	} dev_map[] = {
+#if defined(CONFIG_SERIAL_MPSC)
+		{ MPSC_CTLR_NAME ".0", katana_fixup_mpsc_pdata },
+		{ MPSC_CTLR_NAME ".1", katana_fixup_mpsc_pdata },
+#endif
+#if defined(CONFIG_MV643XX_ETH)
+		{ MV643XX_ETH_NAME ".0", katana_fixup_eth_pdata },
+		{ MV643XX_ETH_NAME ".1", katana_fixup_eth_pdata },
+		{ MV643XX_ETH_NAME ".2", katana_fixup_eth_pdata },
+#endif
+	};
+	struct platform_device	*pdev;
+	int	i;
+
+	if (dev && dev->bus_id)
+		for (i=0; i<ARRAY_SIZE(dev_map); i++)
+			if (!strncmp(dev->bus_id, dev_map[i].bus_id,
+				BUS_ID_SIZE)) {
+
+				pdev = container_of(dev,
+					struct platform_device, dev);
+				dev_map[i].rtn(pdev);
+			}
+
+	return 0;
+}
+
+#ifdef CONFIG_MTD_PHYSMAP
+
+#ifndef MB
+#define MB	(1 << 20)
+#endif
+
+/*
+ * MTD Layout depends on amount of soldered FLASH in system. Sizes in MB.
+ *
+ * FLASH Amount:	128	64	32	16
+ * -------------	---	--	--	--
+ * Monitor:		1	1	1	1
+ * Primary Kernel:	1.5	1.5	1.5	1.5
+ * Primary fs:		30	30	<end>	<end>
+ * Secondary Kernel:	1.5	1.5	N/A	N/A
+ * Secondary fs:	<end>	<end>	N/A	N/A
+ * User: 		<overlays entire FLASH except for "Monitor" section>
+ */
+static int __init
+katana_setup_mtd(void)
+{
+	u32	size;
+	int	ptbl_entries;
+	static struct mtd_partition	*ptbl;
+
+	size = katana_flash_size_0 + katana_flash_size_1;
+	if (!size)
+		return -ENOMEM;
+
+	ptbl_entries = (size >= (64*MB)) ? 6 : 4;
+
+	if ((ptbl = kmalloc(ptbl_entries * sizeof(struct mtd_partition),
+		GFP_KERNEL)) == NULL) {
+
+		printk(KERN_WARNING "Can't alloc MTD partition table\n");
+		return -ENOMEM;
+	}
+	memset(ptbl, 0, ptbl_entries * sizeof(struct mtd_partition));
+
+	ptbl[0].name = "Monitor";
+	ptbl[0].size = KATANA_MTD_MONITOR_SIZE;
+	ptbl[1].name = "Primary Kernel";
+	ptbl[1].offset = MTDPART_OFS_NXTBLK;
+	ptbl[1].size = 0x00180000; /* 1.5 MB */
+	ptbl[2].name = "Primary Filesystem";
+	ptbl[2].offset = MTDPART_OFS_APPEND;
+	ptbl[2].size = MTDPART_SIZ_FULL; /* Correct for 16 & 32 MB */
+	ptbl[ptbl_entries-1].name = "User FLASH";
+	ptbl[ptbl_entries-1].offset = KATANA_MTD_MONITOR_SIZE;
+	ptbl[ptbl_entries-1].size = MTDPART_SIZ_FULL;
+
+	if (size >= (64*MB)) {
+		ptbl[2].size = 30*MB;
+		ptbl[3].name = "Secondary Kernel";
+		ptbl[3].offset = MTDPART_OFS_NXTBLK;
+		ptbl[3].size = 0x00180000; /* 1.5 MB */
+		ptbl[4].name = "Secondary Filesystem";
+		ptbl[4].offset = MTDPART_OFS_APPEND;
+		ptbl[4].size = MTDPART_SIZ_FULL;
+	}
+
+	physmap_map.size = size;
+	physmap_set_partitions(ptbl, ptbl_entries);
+	return 0;
+}
+
+arch_initcall(katana_setup_mtd);
+#endif
+
+static void
+katana_restart(char *cmd)
+{
+	ulong	i = 10000000;
+
+	/* issue hard reset to the reset command register */
+	out_8(cpld_base + KATANA_CPLD_RST_CMD, KATANA_CPLD_RST_CMD_HR);
+
+	while (i-- > 0) ;
+	panic("restart failed\n");
+}
+
+static void
+katana_halt(void)
+{
+	u8	v;
+
+	if (katana_id == KATANA_ID_752I) {
+		   v = in_8(cpld_base + HSL_PLD_BASE + HSL_PLD_HOT_SWAP_OFF);
+		   v |= HSL_PLD_HOT_SWAP_LED_BIT;
+		   out_8(cpld_base + HSL_PLD_BASE + HSL_PLD_HOT_SWAP_OFF, v);
+	}
+
+	while (1) ;
+	/* NOTREACHED */
+}
+
+static void
+katana_power_off(void)
+{
+	katana_halt();
+	/* NOTREACHED */
+}
+
+static int
+katana_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: Artesyn Communication Products, LLC\n");
+
+	seq_printf(m, "board\t\t: ");
+
+	switch (katana_id) {
+	case KATANA_ID_3750:
+		seq_printf(m, "Katana 3750\n");
+		break;
+
+	case KATANA_ID_750I:
+		seq_printf(m, "Katana 750i\n");
+		break;
+
+	case KATANA_ID_752I:
+		seq_printf(m, "Katana 752i\n");
+		break;
+
+	default:
+		seq_printf(m, "Unknown\n");
+		break;
+	}
+
+	seq_printf(m, "product ID\t: 0x%x\n",
+		   in_8(cpld_base + KATANA_CPLD_PRODUCT_ID));
+	seq_printf(m, "hardware rev\t: 0x%x\n",
+		   in_8(cpld_base+KATANA_CPLD_HARDWARE_VER));
+	seq_printf(m, "PLD rev\t\t: 0x%x\n",
+		   in_8(cpld_base + KATANA_CPLD_PLD_VER));
+	seq_printf(m, "PLB freq\t: %ldMhz\n",
+		(long)katana_bus_frequency / 1000000);
+	seq_printf(m, "PCI\t\t: %sMonarch\n", katana_is_monarch()? "" : "Non-");
+
+	return 0;
+}
+
+static void __init
+katana_calibrate_decr(void)
+{
+	u32 freq;
+
+	freq = katana_bus_frequency / 4;
+
+	printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+	       (long)freq / 1000000, (long)freq % 1000000);
+
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
+
+unsigned long __init
+katana_find_end_of_memory(void)
+{
+	return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
+		MV64x60_TYPE_MV64360);
+}
+
+#if defined(CONFIG_I2C_MV64XXX) && defined(CONFIG_SENSORS_M41T00)
+extern ulong	m41t00_get_rtc_time(void);
+extern int	m41t00_set_rtc_time(ulong);
+
+static int __init
+katana_rtc_hookup(void)
+{
+	struct timespec	tv;
+
+	ppc_md.get_rtc_time = m41t00_get_rtc_time;
+	ppc_md.set_rtc_time = m41t00_set_rtc_time;
+
+	tv.tv_nsec = 0;
+	tv.tv_sec = (ppc_md.get_rtc_time)();
+	do_settimeofday(&tv);
+
+	return 0;
+}
+late_initcall(katana_rtc_hookup);
+#endif
+
+static inline void
+katana_set_bat(void)
+{
+	mb();
+	mtspr(SPRN_DBAT2U, 0xf0001ffe);
+	mtspr(SPRN_DBAT2L, 0xf000002a);
+	mb();
+}
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
+static void __init
+katana_map_io(void)
+{
+	io_block_mapping(0xf8100000, 0xf8100000, 0x00020000, _PAGE_IO);
+}
+#endif
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	/* ASSUMPTION:  If both r3 (bd_t pointer) and r6 (cmdline pointer)
+	 * are non-zero, then we should use the board info from the bd_t
+	 * structure and the cmdline pointed to by r6 instead of the
+	 * information from birecs, if any.  Otherwise, use the information
+	 * from birecs as discovered by the preceeding call to
+	 * parse_bootinfo().  This rule should work with both PPCBoot, which
+	 * uses a bd_t board info structure, and the kernel boot wrapper,
+	 * which uses birecs.
+	 */
+	if (r3 && r6) {
+		/* copy board info structure */
+		memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+		/* copy command line */
+		*(char *)(r7+KERNELBASE) = 0;
+		strcpy(cmd_line, (char *)(r6+KERNELBASE));
+	}
+
+	isa_mem_base = 0;
+
+	ppc_md.setup_arch = katana_setup_arch;
+	ppc_md.show_cpuinfo = katana_show_cpuinfo;
+	ppc_md.init_IRQ = mv64360_init_irq;
+	ppc_md.get_irq = mv64360_get_irq;
+	ppc_md.restart = katana_restart;
+	ppc_md.power_off = katana_power_off;
+	ppc_md.halt = katana_halt;
+	ppc_md.find_end_of_memory = katana_find_end_of_memory;
+	ppc_md.calibrate_decr = katana_calibrate_decr;
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
+	ppc_md.setup_io_mappings = katana_map_io;
+	ppc_md.progress = mv64x60_mpsc_progress;
+	mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
+#endif
+
+#if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH)
+	platform_notify = katana_platform_notify;
+#endif
+
+	katana_set_bat(); /* Need for katana_find_end_of_memory and progress */
+}
diff --git a/arch/ppc/platforms/katana.h b/arch/ppc/platforms/katana.h
new file mode 100644
index 0000000..b82ed81
--- /dev/null
+++ b/arch/ppc/platforms/katana.h
@@ -0,0 +1,255 @@
+/*
+ * arch/ppc/platforms/katana.h
+ *
+ * Definitions for Artesyn Katana750i/3750 board.
+ *
+ * Author: Tim Montgomery <timm@artesyncp.com>
+ * Maintained by: Mark A. Greer <mgreer@mvista.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by Mark A. Greer <mgreer@mvista.com>
+ *
+ * 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.
+ */
+
+/*
+ * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to
+ * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
+ * We'll only use one PCI MEM window on each PCI bus.
+ *
+ * This is the CPU physical memory map (windows must be at least 64 KB and start
+ * on a boundary that is a multiple of the window size):
+ *
+ *    0xff800000-0xffffffff      - Boot window
+ *    0xf8400000-0xf843ffff      - Internal SRAM
+ *    0xf8200000-0xf83fffff      - CPLD
+ *    0xf8100000-0xf810ffff      - MV64360 Registers (CONFIG_MV64X60_NEW_BASE)
+ *    0xf8000000-0xf80fffff      - Socketed FLASH
+ *    0xe0000000-0xefffffff      - Soldered FLASH
+ *    0xc0000000-0xc3ffffff      - PCI I/O (second hose)
+ *    0x80000000-0xbfffffff      - PCI MEM (second hose)
+ */
+
+#ifndef __PPC_PLATFORMS_KATANA_H
+#define __PPC_PLATFORMS_KATANA_H
+
+/* CPU Physical Memory Map setup. */
+#define KATANA_BOOT_WINDOW_BASE			0xff800000
+#define KATANA_BOOT_WINDOW_SIZE			0x00800000 /* 8 MB */
+#define KATANA_INTERNAL_SRAM_BASE		0xf8400000
+#define KATANA_CPLD_BASE			0xf8200000
+#define KATANA_CPLD_SIZE			0x00200000 /* 2 MB */
+#define KATANA_SOCKET_BASE			0xf8000000
+#define KATANA_SOCKETED_FLASH_SIZE		0x00100000 /* 1 MB */
+#define KATANA_SOLDERED_FLASH_BASE		0xe0000000
+#define KATANA_SOLDERED_FLASH_SIZE		0x10000000 /* 256 MB */
+
+#define KATANA_PCI1_MEM_START_PROC_ADDR         0x80000000
+#define KATANA_PCI1_MEM_START_PCI_HI_ADDR       0x00000000
+#define KATANA_PCI1_MEM_START_PCI_LO_ADDR       0x80000000
+#define KATANA_PCI1_MEM_SIZE                    0x40000000 /* 1 GB */
+#define KATANA_PCI1_IO_START_PROC_ADDR          0xc0000000
+#define KATANA_PCI1_IO_START_PCI_ADDR           0x00000000
+#define KATANA_PCI1_IO_SIZE                     0x04000000 /* 64 MB */
+
+/* Board-specific IRQ info */
+#define  KATANA_PCI_INTA_IRQ_3750		64+8
+#define  KATANA_PCI_INTB_IRQ_3750		64+9
+#define  KATANA_PCI_INTC_IRQ_3750		64+10
+
+#define  KATANA_PCI_INTA_IRQ_750i		64+8
+#define  KATANA_PCI_INTB_IRQ_750i		64+9
+#define  KATANA_PCI_INTC_IRQ_750i		64+10
+#define  KATANA_PCI_INTD_IRQ_750i		64+14
+
+#define KATANA_CPLD_RST_EVENT			0x00000000
+#define KATANA_CPLD_RST_CMD			0x00001000
+#define KATANA_CPLD_PCI_ERR_INT_EN		0x00002000
+#define KATANA_CPLD_PCI_ERR_INT_PEND		0x00003000
+#define KATANA_CPLD_PRODUCT_ID			0x00004000
+#define KATANA_CPLD_EREADY			0x00005000
+
+#define KATANA_CPLD_HARDWARE_VER		0x00007000
+#define KATANA_CPLD_PLD_VER			0x00008000
+#define KATANA_CPLD_BD_CFG_0			0x00009000
+#define KATANA_CPLD_BD_CFG_1			0x0000a000
+#define KATANA_CPLD_BD_CFG_3			0x0000c000
+#define KATANA_CPLD_LED				0x0000d000
+#define KATANA_CPLD_RESET_OUT			0x0000e000
+
+#define KATANA_CPLD_RST_EVENT_INITACT		0x80
+#define KATANA_CPLD_RST_EVENT_SW		0x40
+#define KATANA_CPLD_RST_EVENT_WD		0x20
+#define KATANA_CPLD_RST_EVENT_COPS		0x10
+#define KATANA_CPLD_RST_EVENT_COPH		0x08
+#define KATANA_CPLD_RST_EVENT_CPCI		0x02
+#define KATANA_CPLD_RST_EVENT_FP		0x01
+
+#define KATANA_CPLD_RST_CMD_SCL			0x80
+#define KATANA_CPLD_RST_CMD_SDA			0x40
+#define KATANA_CPLD_RST_CMD_I2C			0x10
+#define KATANA_CPLD_RST_CMD_FR			0x08
+#define KATANA_CPLD_RST_CMD_SR			0x04
+#define KATANA_CPLD_RST_CMD_HR			0x01
+
+#define KATANA_CPLD_BD_CFG_0_SYSCLK_MASK	0xc0
+#define KATANA_CPLD_BD_CFG_0_SYSCLK_200		0x00
+#define KATANA_CPLD_BD_CFG_0_SYSCLK_166		0x80
+#define KATANA_CPLD_BD_CFG_0_SYSCLK_133		0xc0
+#define KATANA_CPLD_BD_CFG_0_SYSCLK_100		0x40
+
+#define KATANA_CPLD_BD_CFG_1_FL_BANK_MASK	0x03
+#define KATANA_CPLD_BD_CFG_1_FL_BANK_16MB	0x00
+#define KATANA_CPLD_BD_CFG_1_FL_BANK_32MB	0x01
+#define KATANA_CPLD_BD_CFG_1_FL_BANK_64MB	0x02
+#define KATANA_CPLD_BD_CFG_1_FL_BANK_128MB	0x03
+
+#define KATANA_CPLD_BD_CFG_1_FL_NUM_BANKS_MASK	0x04
+#define KATANA_CPLD_BD_CFG_1_FL_NUM_BANKS_ONE	0x00
+#define KATANA_CPLD_BD_CFG_1_FL_NUM_BANKS_TWO	0x04
+
+#define KATANA_CPLD_BD_CFG_3_MONARCH		0x04
+
+#define KATANA_CPLD_RESET_OUT_PORTSEL		0x80
+#define KATANA_CPLD_RESET_OUT_WD		0x20
+#define KATANA_CPLD_RESET_OUT_COPH		0x08
+#define KATANA_CPLD_RESET_OUT_PCI_RST_PCI	0x02
+#define KATANA_CPLD_RESET_OUT_PCI_RST_FP	0x01
+
+#define KATANA_MBOX_RESET_REQUEST		0xC83A
+#define KATANA_MBOX_RESET_ACK			0xE430
+#define KATANA_MBOX_RESET_DONE			0x32E5
+
+#define HSL_PLD_BASE				0x00010000
+#define HSL_PLD_J4SGA_REG_OFF			0
+#define HSL_PLD_J4GA_REG_OFF			1
+#define HSL_PLD_J2GA_REG_OFF			2
+#define HSL_PLD_HOT_SWAP_OFF			6
+#define HSL_PLD_HOT_SWAP_LED_BIT		0x1
+#define GA_MASK					0x1f
+#define HSL_PLD_SIZE				0x1000
+#define K3750_GPP_GEO_ADDR_PINS			0xf8000000
+#define K3750_GPP_GEO_ADDR_SHIFT		27
+
+#define K3750_GPP_EVENT_PROC_0			(1 << 21)
+#define K3750_GPP_EVENT_PROC_1_2		(1 << 2)
+
+#define PCI_VENDOR_ID_ARTESYN			0x1223
+#define PCI_DEVICE_ID_KATANA_3750_PROC0		0x0041
+#define PCI_DEVICE_ID_KATANA_3750_PROC1		0x0042
+#define PCI_DEVICE_ID_KATANA_3750_PROC2		0x0043
+
+#define COPROC_MEM_FUNCTION			0
+#define COPROC_MEM_BAR				0
+#define COPROC_REGS_FUNCTION			0
+#define COPROC_REGS_BAR				4
+#define COPROC_FLASH_FUNCTION			2
+#define COPROC_FLASH_BAR			4
+
+#define KATANA_IPMB_LOCAL_I2C_ADDR		0x08
+
+#define	KATANA_DEFAULT_BAUD			9600
+#define	KATANA_MPSC_CLK_SRC			8	  /* TCLK */
+
+#define	KATANA_MTD_MONITOR_SIZE			(1 << 20) /* 1 MB */
+
+#define	KATANA_ETH0_PHY_ADDR			12
+#define	KATANA_ETH1_PHY_ADDR			11
+#define	KATANA_ETH2_PHY_ADDR			4
+
+#define KATANA_PRODUCT_ID_3750			0x01
+#define KATANA_PRODUCT_ID_750i			0x02
+#define KATANA_PRODUCT_ID_752i			0x04
+
+#define KATANA_ETH_TX_QUEUE_SIZE		800
+#define KATANA_ETH_RX_QUEUE_SIZE		400
+
+#define	KATANA_ETH_PORT_CONFIG_VALUE			\
+	ETH_UNICAST_NORMAL_MODE			|	\
+	ETH_DEFAULT_RX_QUEUE_0			|	\
+	ETH_DEFAULT_RX_ARP_QUEUE_0		|	\
+	ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP		|	\
+	ETH_RECEIVE_BC_IF_IP			|	\
+	ETH_RECEIVE_BC_IF_ARP			|	\
+	ETH_CAPTURE_TCP_FRAMES_DIS		|	\
+	ETH_CAPTURE_UDP_FRAMES_DIS		|	\
+	ETH_DEFAULT_RX_TCP_QUEUE_0		|	\
+	ETH_DEFAULT_RX_UDP_QUEUE_0		|	\
+	ETH_DEFAULT_RX_BPDU_QUEUE_0
+
+#define	KATANA_ETH_PORT_CONFIG_EXTEND_VALUE		\
+	ETH_SPAN_BPDU_PACKETS_AS_NORMAL		|	\
+	ETH_PARTITION_DISABLE
+
+#define	GT_ETH_IPG_INT_RX(value)			\
+	((value & 0x3fff) << 8)
+
+#define	KATANA_ETH_PORT_SDMA_CONFIG_VALUE		\
+	ETH_RX_BURST_SIZE_4_64BIT		|	\
+	GT_ETH_IPG_INT_RX(0)			|	\
+	ETH_TX_BURST_SIZE_4_64BIT
+
+#define	KATANA_ETH_PORT_SERIAL_CONTROL_VALUE		\
+	ETH_FORCE_LINK_PASS			|	\
+	ETH_ENABLE_AUTO_NEG_FOR_DUPLX		|	\
+	ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL	|	\
+	ETH_ADV_SYMMETRIC_FLOW_CTRL		|	\
+	ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX	|	\
+	ETH_FORCE_BP_MODE_NO_JAM		|	\
+	BIT9					|	\
+	ETH_DO_NOT_FORCE_LINK_FAIL		|	\
+	ETH_RETRANSMIT_16_ATTEMPTS		|	\
+	ETH_ENABLE_AUTO_NEG_SPEED_GMII		|	\
+	ETH_DTE_ADV_0				|	\
+	ETH_DISABLE_AUTO_NEG_BYPASS		|	\
+	ETH_AUTO_NEG_NO_CHANGE			|	\
+	ETH_MAX_RX_PACKET_9700BYTE		|	\
+	ETH_CLR_EXT_LOOPBACK			|	\
+	ETH_SET_FULL_DUPLEX_MODE		|	\
+	ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
+
+#ifndef __ASSEMBLY__
+
+typedef enum {
+	KATANA_ID_3750,
+	KATANA_ID_750I,
+	KATANA_ID_752I,
+	KATANA_ID_MAX
+} katana_id_t;
+
+#endif
+
+static inline u32
+katana_bus_freq(void __iomem *cpld_base)
+{
+	u8 bd_cfg_0;
+
+	bd_cfg_0 = in_8(cpld_base + KATANA_CPLD_BD_CFG_0);
+
+	switch (bd_cfg_0 & KATANA_CPLD_BD_CFG_0_SYSCLK_MASK) {
+	case KATANA_CPLD_BD_CFG_0_SYSCLK_200:
+		return 200000000;
+		break;
+
+	case KATANA_CPLD_BD_CFG_0_SYSCLK_166:
+		return 166666666;
+		break;
+
+	case KATANA_CPLD_BD_CFG_0_SYSCLK_133:
+		return 133333333;
+		break;
+
+	case KATANA_CPLD_BD_CFG_0_SYSCLK_100:
+		return 100000000;
+		break;
+
+	default:
+		return 133333333;
+		break;
+	}
+}
+
+#endif	/* __PPC_PLATFORMS_KATANA_H */
diff --git a/arch/ppc/platforms/lantec.h b/arch/ppc/platforms/lantec.h
new file mode 100644
index 0000000..8c87642
--- /dev/null
+++ b/arch/ppc/platforms/lantec.h
@@ -0,0 +1,21 @@
+/*
+ * LANTEC board specific definitions
+ *
+ * Copyright (c) 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __MACH_LANTEC_H
+#define __MACH_LANTEC_H
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define	IMAP_ADDR	0xFFF00000	/* physical base address of IMMR area	*/
+#define IMAP_SIZE	(64 * 1024)	/* mapped size of IMMR area		*/
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif	/* __MACH_LANTEC_H */
diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c
new file mode 100644
index 0000000..b604cf8
--- /dev/null
+++ b/arch/ppc/platforms/lite5200.c
@@ -0,0 +1,236 @@
+/*
+ * arch/ppc/platforms/lite5200.c
+ *
+ * Platform support file for the Freescale LITE5200 based on MPC52xx.
+ * A maximum of this file should be moved to syslib/mpc52xx_?????
+ * so that new platform based on MPC52xx need a minimal platform file
+ * ( avoid code duplication )
+ *
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Based on the 2.4 code written by Kent Borg,
+ * Dale Farnsworth <dale.farnsworth@mvista.com> and
+ * Wolfgang Denk <wd@denx.de>
+ * 
+ * Copyright 2004-2005 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright 2003 Motorola Inc.
+ * Copyright 2003 MontaVista Software Inc.
+ * Copyright 2003 DENX Software Engineering (wd@denx.de)
+ *
+ * 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/initrd.h>
+#include <linux/seq_file.h>
+#include <linux/kdev_t.h>
+#include <linux/root_dev.h>
+#include <linux/console.h>
+#include <linux/module.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mpc52xx.h>
+#include <asm/ppc_sys.h>
+
+#include <syslib/mpc52xx_pci.h>
+
+
+extern int powersave_nap;
+
+/* Board data given by U-Boot */
+bd_t __res;
+EXPORT_SYMBOL(__res);	/* For modules */
+
+
+/* ======================================================================== */
+/* Platform specific code                                                   */
+/* ======================================================================== */
+
+/* Supported PSC function in "preference" order */
+struct mpc52xx_psc_func mpc52xx_psc_functions[] = {
+		{       .id     = 0,
+			.func   = "uart",
+		},
+		{       .id     = -1,   /* End entry */
+			.func   = NULL,
+		}
+	};
+
+
+static int
+lite5200_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "machine\t\t: Freescale LITE5200\n");
+	return 0;
+}
+
+#ifdef CONFIG_PCI
+static int
+lite5200_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	return (pin == 1) && (idsel==24) ? MPC52xx_IRQ0 : -1;
+}
+#endif
+
+static void __init
+lite5200_setup_cpu(void)
+{
+	struct mpc52xx_cdm  __iomem *cdm;
+	struct mpc52xx_gpio __iomem *gpio;
+	struct mpc52xx_intr __iomem *intr;
+	struct mpc52xx_xlb  __iomem *xlb;
+
+	u32 port_config;
+	u32 intr_ctrl;
+
+	/* Map zones */
+	cdm  = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
+	gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
+	xlb  = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE);
+	intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+
+	if (!cdm || !gpio || !xlb || !intr) {
+		printk("lite5200.c: Error while mapping CDM/GPIO/XLB/INTR during"
+				"lite5200_setup_cpu\n");
+		goto unmap_regs;
+	}
+
+	/* Use internal 48 Mhz */
+	out_8(&cdm->ext_48mhz_en, 0x00);
+	out_8(&cdm->fd_enable, 0x01);
+	if (in_be32(&cdm->rstcfg) & 0x40)	/* Assumes 33Mhz clock */
+		out_be16(&cdm->fd_counters, 0x0001);
+	else
+		out_be16(&cdm->fd_counters, 0x5555);
+
+	/* Get port mux config */
+	port_config = in_be32(&gpio->port_config);
+
+	/* 48Mhz internal, pin is GPIO */
+	port_config &= ~0x00800000;
+
+	/* USB port */
+	port_config &= ~0x00007000;	/* Differential mode - USB1 only */
+	port_config |=  0x00001000;
+
+	/* Commit port config */
+	out_be32(&gpio->port_config, port_config);
+
+	/* Configure the XLB Arbiter */
+	out_be32(&xlb->master_pri_enable, 0xff);
+	out_be32(&xlb->master_priority, 0x11111111);
+
+	/* Enable ram snooping for 1GB window */
+	out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP);
+	out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d);
+
+	/* IRQ[0-3] setup : IRQ0     - Level Active Low  */
+	/*                  IRQ[1-3] - Level Active High */
+	intr_ctrl = in_be32(&intr->ctrl);
+	intr_ctrl &= ~0x00ff0000;
+	intr_ctrl |=  0x00c00000;
+	out_be32(&intr->ctrl, intr_ctrl);
+
+	/* Unmap reg zone */
+unmap_regs:
+	if (cdm)  iounmap(cdm);
+	if (gpio) iounmap(gpio);
+	if (xlb)  iounmap(xlb);
+	if (intr) iounmap(intr);
+}
+
+static void __init
+lite5200_setup_arch(void)
+{
+	/* CPU & Port mux setup */
+	lite5200_setup_cpu();
+
+#ifdef CONFIG_PCI
+	/* PCI Bridge setup */
+	mpc52xx_find_bridges();
+#endif
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+              unsigned long r6, unsigned long r7)
+{
+	/* Generic MPC52xx platform initialization */
+	/* TODO Create one and move a max of stuff in it.
+	   Put this init in the syslib */
+
+	struct bi_record *bootinfo = find_bootinfo();
+
+	if (bootinfo)
+		parse_bootinfo(bootinfo);
+	else {
+		/* Load the bd_t board info structure */
+		if (r3)
+			memcpy((void*)&__res,(void*)(r3+KERNELBASE),
+					sizeof(bd_t));
+
+#ifdef CONFIG_BLK_DEV_INITRD
+		/* Load the initrd */
+		if (r4) {
+			initrd_start = r4 + KERNELBASE;
+			initrd_end = r5 + KERNELBASE;
+		}
+#endif
+
+		/* Load the command line */
+		if (r6) {
+			*(char *)(r7+KERNELBASE) = 0;
+			strcpy(cmd_line, (char *)(r6+KERNELBASE));
+		}
+	}
+
+	/* PPC Sys identification */
+	identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+	/* BAT setup */
+	mpc52xx_set_bat();
+
+	/* No ISA bus by default */
+	isa_io_base		= 0;
+	isa_mem_base		= 0;
+
+	/* Powersave */
+	/* This is provided as an example on how to do it. But you
+	   need to be aware that NAP disable bus snoop and that may
+	   be required for some devices to work properly, like USB ... */
+	/* powersave_nap = 1; */
+
+
+	/* Setup the ppc_md struct */
+	ppc_md.setup_arch	= lite5200_setup_arch;
+	ppc_md.show_cpuinfo	= lite5200_show_cpuinfo;
+	ppc_md.show_percpuinfo	= NULL;
+	ppc_md.init_IRQ		= mpc52xx_init_irq;
+	ppc_md.get_irq		= mpc52xx_get_irq;
+
+#ifdef CONFIG_PCI
+	ppc_md.pci_map_irq	= lite5200_map_irq;
+#endif
+
+	ppc_md.find_end_of_memory = mpc52xx_find_end_of_memory;
+	ppc_md.setup_io_mappings  = mpc52xx_map_io;
+
+	ppc_md.restart		= mpc52xx_restart;
+	ppc_md.power_off	= mpc52xx_power_off;
+	ppc_md.halt		= mpc52xx_halt;
+
+		/* No time keeper on the LITE5200 */
+	ppc_md.time_init	= NULL;
+	ppc_md.get_rtc_time	= NULL;
+	ppc_md.set_rtc_time	= NULL;
+
+	ppc_md.calibrate_decr	= mpc52xx_calibrate_decr;
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress		= mpc52xx_progress;
+#endif
+}
+
diff --git a/arch/ppc/platforms/lite5200.h b/arch/ppc/platforms/lite5200.h
new file mode 100644
index 0000000..c1de2aa
--- /dev/null
+++ b/arch/ppc/platforms/lite5200.h
@@ -0,0 +1,23 @@
+/*
+ * arch/ppc/platforms/lite5200.h
+ * 
+ * Definitions for Freescale LITE5200 : MPC52xx Standard Development
+ * Platform board support
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ * 
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+#ifndef __PLATFORMS_LITE5200_H__
+#define __PLATFORMS_LITE5200_H__
+
+/* Serial port used for low-level debug */
+#define MPC52xx_PF_CONSOLE_PORT 1	/* PSC1 */
+
+
+#endif /* __PLATFORMS_LITE5200_H__ */
diff --git a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c
new file mode 100644
index 0000000..a556952
--- /dev/null
+++ b/arch/ppc/platforms/lopec.c
@@ -0,0 +1,411 @@
+/*
+ * arch/ppc/platforms/lopec.c
+ *
+ * Setup routines for the Motorola LoPEC.
+ *
+ * Author: Dan Cox
+ * Maintainer: Tom Rini <trini@kernel.crashing.org>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc.  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/types.h>
+#include <linux/delay.h>
+#include <linux/pci_ids.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/root_dev.h>
+#include <linux/pci.h>
+
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/io.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/mpc10x.h>
+#include <asm/hw_irq.h>
+#include <asm/prep_nvram.h>
+#include <asm/kgdb.h>
+
+/*
+ * Define all of the IRQ senses and polarities.  Taken from the
+ * LoPEC Programmer's Reference Guide.
+ */
+static u_char lopec_openpic_initsenses[16] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 4 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 5 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 6 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 7 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 8 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 9 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 10 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 11 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* IRQ 12 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* IRQ 13 */
+	(IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE),	/* IRQ 14 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE)	/* IRQ 15 */
+};
+
+static inline int __init
+lopec_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	int irq;
+	static char pci_irq_table[][4] = {
+		{16, 0, 0, 0}, /* ID 11 - Winbond */
+		{22, 0, 0, 0}, /* ID 12 - SCSI */
+		{0, 0, 0, 0}, /* ID 13 - nothing */
+		{17, 0, 0, 0}, /* ID 14 - 82559 Ethernet */
+		{27, 0, 0, 0}, /* ID 15 - USB */
+		{23, 0, 0, 0}, /* ID 16 - PMC slot 1 */
+		{24, 0, 0, 0}, /* ID 17 - PMC slot 2 */
+		{25, 0, 0, 0}, /* ID 18 - PCI slot */
+		{0, 0, 0, 0}, /* ID 19 - nothing */
+		{0, 0, 0, 0}, /* ID 20 - nothing */
+		{0, 0, 0, 0}, /* ID 21 - nothing */
+		{0, 0, 0, 0}, /* ID 22 - nothing */
+		{0, 0, 0, 0}, /* ID 23 - nothing */
+		{0, 0, 0, 0}, /* ID 24 - PMC slot 1b */
+		{0, 0, 0, 0}, /* ID 25 - nothing */
+		{0, 0, 0, 0}  /* ID 26 - PMC Slot 2b */
+	};
+	const long min_idsel = 11, max_idsel = 26, irqs_per_slot = 4;
+
+	irq = PCI_IRQ_TABLE_LOOKUP;
+	if (!irq)
+		return 0;
+
+	return irq;
+}
+
+static void __init
+lopec_setup_winbond_83553(struct pci_controller *hose)
+{
+	int devfn;
+
+	devfn = PCI_DEVFN(11,0);
+
+	/* IDE interrupt routing (primary 14, secondary 15) */
+	early_write_config_byte(hose, 0, devfn, 0x43, 0xef);
+	/* PCI interrupt routing */
+	early_write_config_word(hose, 0, devfn, 0x44, 0x0000);
+
+	/* ISA-PCI address decoder */
+	early_write_config_byte(hose, 0, devfn, 0x48, 0xf0);
+
+	/* RTC, kb, not used in PPC */
+	early_write_config_byte(hose, 0, devfn, 0x4d, 0x00);
+	early_write_config_byte(hose, 0, devfn, 0x4e, 0x04);
+	devfn = PCI_DEVFN(11, 1);
+	early_write_config_byte(hose, 0, devfn, 0x09, 0x8f);
+	early_write_config_dword(hose, 0, devfn, 0x40, 0x00ff0011);
+}
+
+static void __init
+lopec_find_bridges(void)
+{
+	struct pci_controller *hose;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	if (mpc10x_bridge_init(hose, MPC10X_MEM_MAP_B, MPC10X_MEM_MAP_B,
+				MPC10X_MAPB_EUMB_BASE) == 0) {
+
+		hose->mem_resources[0].end = 0xffffffff;
+		lopec_setup_winbond_83553(hose);
+		hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+		ppc_md.pci_swizzle = common_swizzle;
+		ppc_md.pci_map_irq = lopec_map_irq;
+	}
+}
+
+static int
+lopec_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "machine\t\t: Motorola LoPEC\n");
+	return 0;
+}
+
+static u32
+lopec_irq_canonicalize(u32 irq)
+{
+	if (irq == 2)
+		return 9;
+	else
+		return irq;
+}
+
+static void
+lopec_restart(char *cmd)
+{
+#define LOPEC_SYSSTAT1 0xffe00000
+	/* force a hard reset, if possible */
+	unsigned char reg = *((unsigned char *) LOPEC_SYSSTAT1);
+	reg |= 0x80;
+	*((unsigned char *) LOPEC_SYSSTAT1) = reg;
+
+	local_irq_disable();
+	while(1);
+#undef LOPEC_SYSSTAT1
+}
+
+static void
+lopec_halt(void)
+{
+	local_irq_disable();
+	while(1);
+}
+
+static void
+lopec_power_off(void)
+{
+	lopec_halt();
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+int lopec_ide_ports_known = 0;
+static unsigned long lopec_ide_regbase[MAX_HWIFS];
+static unsigned long lopec_ide_ctl_regbase[MAX_HWIFS];
+static unsigned long lopec_idedma_regbase;
+
+static void
+lopec_ide_probe(void)
+{
+	struct pci_dev *dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+					      PCI_DEVICE_ID_WINBOND_82C105,
+					      NULL);
+	lopec_ide_ports_known = 1;
+
+	if (dev) {
+		lopec_ide_regbase[0] = dev->resource[0].start;
+		lopec_ide_regbase[1] = dev->resource[2].start;
+		lopec_ide_ctl_regbase[0] = dev->resource[1].start;
+		lopec_ide_ctl_regbase[1] = dev->resource[3].start;
+		lopec_idedma_regbase = dev->resource[4].start;
+		pci_dev_put(dev);
+	}
+}
+
+static int
+lopec_ide_default_irq(unsigned long base)
+{
+	if (lopec_ide_ports_known == 0)
+		lopec_ide_probe();
+
+	if (base == lopec_ide_regbase[0])
+		return 14;
+	else if (base == lopec_ide_regbase[1])
+		return 15;
+	else
+		return 0;
+}
+
+static unsigned long
+lopec_ide_default_io_base(int index)
+{
+	if (lopec_ide_ports_known == 0)
+		lopec_ide_probe();
+	return lopec_ide_regbase[index];
+}
+
+static void __init
+lopec_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data,
+			  unsigned long ctl, int *irq)
+{
+	unsigned long reg = data;
+	uint alt_status_base;
+	int i;
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+		hw->io_ports[i] = reg++;
+
+	if (data == lopec_ide_regbase[0]) {
+		alt_status_base = lopec_ide_ctl_regbase[0] + 2;
+		hw->irq = 14;
+	} else if (data == lopec_ide_regbase[1]) {
+		alt_status_base = lopec_ide_ctl_regbase[1] + 2;
+		hw->irq = 15;
+	} else {
+		alt_status_base = 0;
+		hw->irq = 0;
+	}
+
+	if (ctl)
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
+	else
+		hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
+
+	if (irq != NULL)
+		*irq = hw->irq;
+
+}
+#endif /* BLK_DEV_IDE */
+
+static void __init
+lopec_init_IRQ(void)
+{
+	int i;
+
+	/*
+	 * Provide the open_pic code with the correct table of interrupts.
+	 */
+	OpenPIC_InitSenses = lopec_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof(lopec_openpic_initsenses);
+
+	mpc10x_set_openpic();
+
+	/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
+	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+			&i8259_irq);
+
+	/* Map i8259 interrupts */
+	for(i = 0; i < NUM_8259_INTERRUPTS; i++)
+		irq_desc[i].handler = &i8259_pic;
+
+	/*
+	 * The EPIC allows for a read in the range of 0xFEF00000 ->
+	 * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction.
+	 */
+	i8259_init(0xfef00000);
+}
+
+static int __init
+lopec_request_io(void)
+{
+	outb(0x00, 0x4d0);
+	outb(0xc0, 0x4d1);
+
+	request_region(0x00, 0x20, "dma1");
+	request_region(0x20, 0x20, "pic1");
+	request_region(0x40, 0x20, "timer");
+	request_region(0x80, 0x10, "dma page reg");
+	request_region(0xa0, 0x20, "pic2");
+	request_region(0xc0, 0x20, "dma2");
+
+	return 0;
+}
+
+device_initcall(lopec_request_io);
+
+static void __init
+lopec_map_io(void)
+{
+	io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
+	io_block_mapping(0xb0000000, 0xb0000000, 0x10000000, _PAGE_IO);
+}
+
+/*
+ * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
+ */
+static __inline__ void
+lopec_set_bat(void)
+{
+	mb();
+	mtspr(SPRN_DBAT1U, 0xf8000ffe);
+	mtspr(SPRN_DBAT1L, 0xf800002a);
+	mb();
+}
+
+TODC_ALLOC();
+
+static void __init
+lopec_setup_arch(void)
+{
+
+	TODC_INIT(TODC_TYPE_MK48T37, 0, 0,
+		  ioremap(0xffe80000, 0x8000), 8);
+
+	loops_per_jiffy = 100000000/HZ;
+
+	lopec_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#elif defined(CONFIG_ROOT_NFS)
+        	ROOT_DEV = Root_NFS;
+#elif defined(CONFIG_BLK_DEV_IDEDISK)
+	        ROOT_DEV = Root_HDA1;
+#else
+        	ROOT_DEV = Root_SDA1;
+#endif
+
+#ifdef CONFIG_PPCBUG_NVRAM
+	/* Read in NVRAM data */
+	init_prep_nvram();
+
+	/* if no bootargs, look in NVRAM */
+	if ( cmd_line[0] == '\0' ) {
+		char *bootargs;
+		 bootargs = prep_nvram_get_var("bootargs");
+		 if (bootargs != NULL) {
+			 strcpy(cmd_line, bootargs);
+			 /* again.. */
+			 strcpy(saved_command_line, cmd_line);
+		}
+	}
+#endif
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+	lopec_set_bat();
+
+	isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
+	isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
+	pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
+	ISA_DMA_THRESHOLD = 0x00ffffff;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+
+	ppc_md.setup_arch = lopec_setup_arch;
+	ppc_md.show_cpuinfo = lopec_show_cpuinfo;
+	ppc_md.irq_canonicalize = lopec_irq_canonicalize;
+	ppc_md.init_IRQ = lopec_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+
+	ppc_md.restart = lopec_restart;
+	ppc_md.power_off = lopec_power_off;
+	ppc_md.halt = lopec_halt;
+
+	ppc_md.setup_io_mappings = lopec_map_io;
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.calibrate_decr = todc_calibrate_decr;
+
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+	ppc_ide_md.default_irq = lopec_ide_default_irq;
+	ppc_ide_md.default_io_base = lopec_ide_default_io_base;
+	ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports;
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = gen550_progress;
+#endif
+}
diff --git a/arch/ppc/platforms/lopec.h b/arch/ppc/platforms/lopec.h
new file mode 100644
index 0000000..5490edb
--- /dev/null
+++ b/arch/ppc/platforms/lopec.h
@@ -0,0 +1,39 @@
+/*
+ * include/asm-ppc/lopec_serial.h
+ *
+ * Definitions for Motorola LoPEC board.
+ *
+ * Author: Dan Cox
+ *         danc@mvista.com (or, alternately, source@mvista.com)
+ *
+ * 2001 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifndef __H_LOPEC_SERIAL
+#define __H_LOPEC_SERIAL
+
+#define RS_TABLE_SIZE 3
+
+#define BASE_BAUD (1843200 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+#define SERIAL_PORT_DFNS \
+         { 0, BASE_BAUD, 0xffe10000, 29, STD_COM_FLAGS, \
+           iomem_base: (u8 *) 0xffe10000, \
+           io_type: SERIAL_IO_MEM }, \
+         { 0, BASE_BAUD, 0xffe11000, 20, STD_COM_FLAGS, \
+           iomem_base: (u8 *) 0xffe11000, \
+           io_type: SERIAL_IO_MEM }, \
+         { 0, BASE_BAUD, 0xffe12000, 21, STD_COM_FLAGS, \
+           iomem_base: (u8 *) 0xffe12000, \
+           io_type: SERIAL_IO_MEM }
+
+#endif
diff --git a/arch/ppc/platforms/lwmon.h b/arch/ppc/platforms/lwmon.h
new file mode 100644
index 0000000..995bf51
--- /dev/null
+++ b/arch/ppc/platforms/lwmon.h
@@ -0,0 +1,60 @@
+/*
+ * Liebherr LWMON board specific definitions
+ *
+ * Copyright (c) 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __MACH_LWMON_H
+#define __MACH_LWMON_H
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define	IMAP_ADDR	0xFFF00000	/* physical base address of IMMR area	*/
+#define IMAP_SIZE	(64 * 1024)	/* mapped size of IMMR area		*/
+
+/*-----------------------------------------------------------------------
+ * PCMCIA stuff
+ *-----------------------------------------------------------------------
+ *
+ */
+#define PCMCIA_MEM_SIZE		( 64 << 20 )
+
+#define	MAX_HWIFS	1	/* overwrite default in include/asm-ppc/ide.h	*/
+
+/*
+ * Definitions for IDE0 Interface
+ */
+#define IDE0_BASE_OFFSET		0
+#define IDE0_DATA_REG_OFFSET		(PCMCIA_MEM_SIZE + 0x320)
+#define IDE0_ERROR_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 1)
+#define IDE0_NSECTOR_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 2)
+#define IDE0_SECTOR_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 3)
+#define IDE0_LCYL_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 4)
+#define IDE0_HCYL_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 5)
+#define IDE0_SELECT_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 6)
+#define IDE0_STATUS_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 7)
+#define IDE0_CONTROL_REG_OFFSET		0x0106
+#define IDE0_IRQ_REG_OFFSET		0x000A	/* not used			*/
+
+#define	IDE0_INTERRUPT			13
+
+/*
+ * Definitions for I2C devices
+ */
+#define I2C_ADDR_AUDIO		0x28	/* Audio volume control			*/
+#define I2C_ADDR_SYSMON		0x2E	/* LM87 System Monitor			*/
+#define I2C_ADDR_RTC		0x51	/* PCF8563 RTC				*/
+#define I2C_ADDR_POWER_A	0x52	/* PCMCIA/USB power switch, channel A	*/
+#define I2C_ADDR_POWER_B	0x53	/* PCMCIA/USB power switch, channel B	*/
+#define I2C_ADDR_KEYBD		0x56	/* PIC LWE keyboard			*/
+#define I2C_ADDR_PICIO		0x57	/* PIC IO Expander			*/
+#define I2C_ADDR_EEPROM		0x58	/* EEPROM AT24C164			*/
+
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif	/* __MACH_LWMON_H */
diff --git a/arch/ppc/platforms/mbx.h b/arch/ppc/platforms/mbx.h
new file mode 100644
index 0000000..fe81ca4
--- /dev/null
+++ b/arch/ppc/platforms/mbx.h
@@ -0,0 +1,117 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Motorola MBX boards.  This was originally created for the
+ * MBX860, and probably needs revisions for other boards (like the 821).
+ * When this file gets out of control, we can split it up into more
+ * meaningful pieces.
+ *
+ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_MBX_DEFS
+#define __MACH_MBX_DEFS
+
+#ifndef __ASSEMBLY__
+/* A Board Information structure that is given to a program when
+ * EPPC-Bug starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_tag;		/* Should be 0x42444944 "BDID" */
+	unsigned int	bi_size;	/* Size of this structure */
+	unsigned int	bi_revision;	/* revision of this structure */
+	unsigned int	bi_bdate;	/* EPPCbug date, i.e. 0x11061997 */
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
+	unsigned int	bi_clun;	/* Boot device controller */
+	unsigned int	bi_dlun;	/* Boot device logical dev */
+
+	/* These fields are not part of the board information structure
+	 * provided by the boot rom.  They are filled in by embed_config.c
+	 * so we have the information consistent with other platforms.
+	 */
+	unsigned char	bi_enetaddr[6];
+	unsigned int	bi_baudrate;
+} bd_t;
+
+/* Memory map for the MBX as configured by EPPC-Bug.  We could reprogram
+ * The SIU and PCI bridge, and try to use larger MMU pages, but the
+ * performance gain is not measureable and it certainly complicates the
+ * generic MMU model.
+ *
+ * In a effort to minimize memory usage for embedded applications, any
+ * PCI driver or ISA driver must request or map the region required by
+ * the device.  For convenience (and since we can map up to 4 Mbytes with
+ * a single page table page), the MMU initialization will map the
+ * NVRAM, Status/Control registers, CPM Dual Port RAM, and the PCI
+ * Bridge CSRs 1:1 into the kernel address space.
+ */
+#define PCI_ISA_IO_ADDR		((unsigned)0x80000000)
+#define PCI_ISA_IO_SIZE		((uint)(512 * 1024 * 1024))
+#define PCI_IDE_ADDR		((unsigned)0x81000000)
+#define PCI_ISA_MEM_ADDR	((unsigned)0xc0000000)
+#define PCI_ISA_MEM_SIZE	((uint)(512 * 1024 * 1024))
+#define PCMCIA_MEM_ADDR		((uint)0xe0000000)
+#define PCMCIA_MEM_SIZE		((uint)(64 * 1024 * 1024))
+#define PCMCIA_DMA_ADDR		((uint)0xe4000000)
+#define PCMCIA_DMA_SIZE		((uint)(64 * 1024 * 1024))
+#define PCMCIA_ATTRB_ADDR	((uint)0xe8000000)
+#define PCMCIA_ATTRB_SIZE	((uint)(64 * 1024 * 1024))
+#define PCMCIA_IO_ADDR		((uint)0xec000000)
+#define PCMCIA_IO_SIZE		((uint)(64 * 1024 * 1024))
+#define NVRAM_ADDR		((uint)0xfa000000)
+#define NVRAM_SIZE		((uint)(1 * 1024 * 1024))
+#define MBX_CSR_ADDR		((uint)0xfa100000)
+#define MBX_CSR_SIZE		((uint)(1 * 1024 * 1024))
+#define IMAP_ADDR		((uint)0xfa200000)
+#define IMAP_SIZE		((uint)(64 * 1024))
+#define PCI_CSR_ADDR		((uint)0xfa210000)
+#define PCI_CSR_SIZE		((uint)(64 * 1024))
+
+/* Map additional physical space into well known virtual addresses.  Due
+ * to virtual address mapping, these physical addresses are not accessible
+ * in a 1:1 virtual to physical mapping.
+ */
+#define ISA_IO_VIRT_ADDR	((uint)0xfa220000)
+#define ISA_IO_VIRT_SIZE	((uint)64 * 1024)
+
+/* Interrupt assignments.
+ * These are defined (and fixed) by the MBX hardware implementation.
+ */
+#define POWER_FAIL_INT	SIU_IRQ0	/* Power fail */
+#define TEMP_HILO_INT	SIU_IRQ1	/* Temperature sensor */
+#define QSPAN_INT	SIU_IRQ2	/* PCI Bridge (DMA CTLR?) */
+#define ISA_BRIDGE_INT	SIU_IRQ3	/* All those PC things */
+#define COMM_L_INT	SIU_IRQ6	/* MBX Comm expansion connector pin */
+#define STOP_ABRT_INT	SIU_IRQ7	/* Stop/Abort header pin */
+
+/* CPM Ethernet through SCCx.
+ *
+ * Bits in parallel I/O port registers that have to be set/cleared
+ * to configure the pins for SCC1 use.  The TCLK and RCLK seem unique
+ * to the MBX860 board.  Any two of the four available clocks could be
+ * used, and the MPC860 cookbook manual has an example using different
+ * clock pins.
+ */
+#define PA_ENET_RXD	((ushort)0x0001)
+#define PA_ENET_TXD	((ushort)0x0002)
+#define PA_ENET_TCLK	((ushort)0x0200)
+#define PA_ENET_RCLK	((ushort)0x0800)
+#define PC_ENET_TENA	((ushort)0x0001)
+#define PC_ENET_CLSN	((ushort)0x0010)
+#define PC_ENET_RENA	((ushort)0x0020)
+
+/* Control bits in the SICR to route TCLK (CLK2) and RCLK (CLK4) to
+ * SCC1.  Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero.
+ */
+#define SICR_ENET_MASK	((uint)0x000000ff)
+#define SICR_ENET_CLKRT	((uint)0x0000003d)
+
+/* The MBX uses the 8259.
+*/
+#define NR_8259_INTS	16
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __MACH_MBX_DEFS */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/mcpn765.c b/arch/ppc/platforms/mcpn765.c
new file mode 100644
index 0000000..e88d294
--- /dev/null
+++ b/arch/ppc/platforms/mcpn765.c
@@ -0,0 +1,527 @@
+/*
+ * arch/ppc/platforms/mcpn765.c
+ *
+ * Board setup routines for the Motorola MCG MCPN765 cPCI Board.
+ *
+ * Author: Mark A. Greer
+ *         mgreer@mvista.com
+ *
+ * Modified by Randy Vinson (rvinson@mvista.com)
+ *
+ * 2001-2002 (c) MontaVista, Software, Inc.  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.
+ */
+
+/*
+ * This file adds support for the Motorola MCG MCPN765.
+ */
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>	/* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/slab.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/pci-bridge.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/bootinfo.h>
+#include <asm/hawk.h>
+#include <asm/kgdb.h>
+
+#include "mcpn765.h"
+
+static u_char mcpn765_openpic_initsenses[] __initdata = {
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),/* 16: i8259 cascade */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 17: COM1,2,3,4 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 18: Enet 1 (front) */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 19: HAWK WDT XXXX */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 20: 21554 bridge */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 21: cPCI INTA# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 22: cPCI INTB# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 23: cPCI INTC# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 24: cPCI INTD# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 25: PMC1 INTA#,PMC2 INTB#*/
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 26: PMC1 INTB#,PMC2 INTC#*/
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 27: PMC1 INTC#,PMC2 INTD#*/
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 28: PMC1 INTD#,PMC2 INTA#*/
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 29: Enet 2 (J3) */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 30: Abort Switch */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 31: RTC Alarm */
+};
+
+extern void mcpn765_set_VIA_IDE_native(void);
+
+extern u_int openpic_irq(void);
+extern char cmd_line[];
+
+extern void gen550_progress(char *, unsigned short);
+extern void gen550_init(int, struct uart_port *);
+
+int use_of_interrupt_tree = 0;
+
+static void mcpn765_halt(void);
+
+TODC_ALLOC();
+
+/*
+ * Motorola MCG MCPN765 interrupt routing.
+ */
+static inline int
+mcpn765_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	/*
+	 *	PCI IDSEL/INTPIN->INTLINE
+	 * 	   A   B   C   D
+	 */
+	{
+		{ 14,  0,  0,  0 },	/* IDSEL 11 - have to manually set */
+		{  0,  0,  0,  0 },	/* IDSEL 12 - unused */
+		{  0,  0,  0,  0 },	/* IDSEL 13 - unused */
+		{ 18,  0,  0,  0 },	/* IDSEL 14 - Enet 0 */
+		{  0,  0,  0,  0 },	/* IDSEL 15 - unused */
+		{ 25, 26, 27, 28 },	/* IDSEL 16 - PMC Slot 1 */
+		{ 28, 25, 26, 27 },	/* IDSEL 17 - PMC Slot 2 */
+		{  0,  0,  0,  0 },	/* IDSEL 18 - PMC 2B Connector XXXX */
+		{ 29,  0,  0,  0 },	/* IDSEL 19 - Enet 1 */
+		{ 20,  0,  0,  0 },	/* IDSEL 20 - 21554 cPCI bridge */
+	};
+
+	const long min_idsel = 11, max_idsel = 20, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+void __init
+mcpn765_set_VIA_IDE_legacy(void)
+{
+	unsigned short vend, dev;
+
+	early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend);
+	early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev);
+
+	if ((vend == PCI_VENDOR_ID_VIA) &&
+	    (dev == PCI_DEVICE_ID_VIA_82C586_1)) {
+
+		unsigned char temp;
+
+		/* put back original "standard" port base addresses */
+		early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+				         PCI_BASE_ADDRESS_0, 0x1f1);
+		early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+				         PCI_BASE_ADDRESS_1, 0x3f5);
+		early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+				         PCI_BASE_ADDRESS_2, 0x171);
+		early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+				         PCI_BASE_ADDRESS_3, 0x375);
+		early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+				         PCI_BASE_ADDRESS_4, 0xcc01);
+
+		/* put into legacy mode */
+		early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+				       &temp);
+		temp &= ~0x05;
+		early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+					temp);
+	}
+}
+
+void
+mcpn765_set_VIA_IDE_native(void)
+{
+	unsigned short vend, dev;
+
+	early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend);
+	early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev);
+
+	if ((vend == PCI_VENDOR_ID_VIA) &&
+	    (dev == PCI_DEVICE_ID_VIA_82C586_1)) {
+
+		unsigned char temp;
+
+		/* put into native mode */
+		early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+				       &temp);
+		temp |= 0x05;
+		early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+					temp);
+	}
+}
+
+/*
+ * Initialize the VIA 82c586b.
+ */
+static void __init
+mcpn765_setup_via_82c586b(void)
+{
+	struct pci_dev	*dev;
+	u_char		c;
+
+	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+				   PCI_DEVICE_ID_VIA_82C586_0,
+				   NULL)) == NULL) {
+		printk("No VIA ISA bridge found\n");
+		mcpn765_halt();
+		/* NOTREACHED */
+	}
+
+	/*
+	 * If the firmware left the EISA 4d0/4d1 ports enabled, make sure
+	 * IRQ 14 is set for edge.
+	 */
+	pci_read_config_byte(dev, 0x47, &c);
+
+	if (c & (1<<5)) {
+		c = inb(0x4d1);
+		c &= ~(1<<6);
+		outb(c, 0x4d1);
+	}
+
+	/* Disable PNP IRQ routing since we use the Hawk's MPIC */
+	pci_write_config_dword(dev, 0x54, 0);
+	pci_write_config_byte(dev, 0x58, 0);
+
+	pci_dev_put(dev);
+	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+				   PCI_DEVICE_ID_VIA_82C586_1,
+				   NULL)) == NULL) {
+		printk("No VIA ISA bridge found\n");
+		mcpn765_halt();
+		/* NOTREACHED */
+	}
+
+	/*
+	 * PPCBug doesn't set the enable bits for the IDE device.
+	 * Turn them on now.
+	 */
+	pci_read_config_byte(dev, 0x40, &c);
+	c |= 0x03;
+	pci_write_config_byte(dev, 0x40, c);
+	pci_dev_put(dev);
+
+	return;
+}
+
+void __init
+mcpn765_pcibios_fixup(void)
+{
+	/* Do MCPN765 board specific initialization.  */
+	mcpn765_setup_via_82c586b();
+}
+
+void __init
+mcpn765_find_bridges(void)
+{
+	struct pci_controller	*hose;
+
+	hose = pcibios_alloc_controller();
+
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+	hose->pci_mem_offset = MCPN765_PCI_PHY_MEM_OFFSET;
+
+	pci_init_resource(&hose->io_resource,
+			MCPN765_PCI_IO_START,
+			MCPN765_PCI_IO_END,
+			IORESOURCE_IO,
+			"PCI host bridge");
+
+	pci_init_resource(&hose->mem_resources[0],
+			MCPN765_PCI_MEM_START,
+			MCPN765_PCI_MEM_END,
+			IORESOURCE_MEM,
+			"PCI host bridge");
+
+	hose->io_space.start = MCPN765_PCI_IO_START;
+	hose->io_space.end = MCPN765_PCI_IO_END;
+	hose->mem_space.start = MCPN765_PCI_MEM_START;
+	hose->mem_space.end = MCPN765_PCI_MEM_END - HAWK_MPIC_SIZE;
+
+	if (hawk_init(hose,
+		       MCPN765_HAWK_PPC_REG_BASE,
+		       MCPN765_PROC_PCI_MEM_START,
+		       MCPN765_PROC_PCI_MEM_END - HAWK_MPIC_SIZE,
+		       MCPN765_PROC_PCI_IO_START,
+		       MCPN765_PROC_PCI_IO_END,
+		       MCPN765_PCI_MEM_END - HAWK_MPIC_SIZE + 1) != 0) {
+		printk("Could not initialize HAWK bridge\n");
+	}
+
+	/* VIA IDE BAR decoders are only 16-bits wide. PCI Auto Config
+	 * will reassign the bars outside of 16-bit I/O space, which will 
+	 * "break" things. To prevent this, we'll set the IDE chip into
+	 * legacy mode and seed the bars with their legacy addresses (in 16-bit
+	 * I/O space). The Auto Config code will skip the IDE contoller in 
+	 * legacy mode, so our bar values will stick.
+	 */
+	mcpn765_set_VIA_IDE_legacy();
+
+	hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+	/* Now that we've got 16-bit addresses in the bars, we can switch the
+	 * IDE controller back into native mode so we can do "modern" resource
+	 * and interrupt management.
+	 */
+	mcpn765_set_VIA_IDE_native();
+
+	ppc_md.pcibios_fixup = mcpn765_pcibios_fixup;
+	ppc_md.pcibios_fixup_bus = NULL;
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = mcpn765_map_irq;
+
+	return;
+}
+static void __init
+mcpn765_setup_arch(void)
+{
+	struct pci_controller *hose;
+
+	if ( ppc_md.progress )
+		ppc_md.progress("mcpn765_setup_arch: enter", 0);
+
+	loops_per_jiffy = 50000000 / HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef	CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA2;
+#endif
+
+	if ( ppc_md.progress )
+		ppc_md.progress("mcpn765_setup_arch: find_bridges", 0);
+
+	/* Lookup PCI host bridges */
+	mcpn765_find_bridges();
+
+	hose = pci_bus_to_hose(0);
+	isa_io_base = (ulong)hose->io_base_virt;
+
+	TODC_INIT(TODC_TYPE_MK48T37,
+		  (MCPN765_PHYS_NVRAM_AS0 - isa_io_base),
+		  (MCPN765_PHYS_NVRAM_AS1 - isa_io_base),
+		  (MCPN765_PHYS_NVRAM_DATA - isa_io_base),
+		  8);
+
+	OpenPIC_InitSenses = mcpn765_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof(mcpn765_openpic_initsenses);
+
+	printk("Motorola MCG MCPN765 cPCI Non-System Board\n");
+	printk("MCPN765 port (MontaVista Software, Inc. (source@mvista.com))\n");
+
+	if ( ppc_md.progress )
+		ppc_md.progress("mcpn765_setup_arch: exit", 0);
+
+	return;
+}
+
+static void __init
+mcpn765_init2(void)
+{
+
+	request_region(0x00,0x20,"dma1");
+	request_region(0x20,0x20,"pic1");
+	request_region(0x40,0x20,"timer");
+	request_region(0x80,0x10,"dma page reg");
+	request_region(0xa0,0x20,"pic2");
+	request_region(0xc0,0x20,"dma2");
+
+	return;
+}
+
+/*
+ * Interrupt setup and service.
+ * Have MPIC on HAWK and cascaded 8259s on VIA 82586 cascaded to MPIC.
+ */
+static void __init
+mcpn765_init_IRQ(void)
+{
+	int i;
+
+	if ( ppc_md.progress )
+		ppc_md.progress("init_irq: enter", 0);
+
+	openpic_init(NUM_8259_INTERRUPTS);
+	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+			i8259_irq);
+
+	for(i=0; i < NUM_8259_INTERRUPTS; i++)
+		irq_desc[i].handler = &i8259_pic;
+
+	i8259_init(0);
+
+	if ( ppc_md.progress )
+		ppc_md.progress("init_irq: exit", 0);
+
+	return;
+}
+
+static u32
+mcpn765_irq_canonicalize(u32 irq)
+{
+	if (irq == 2)
+		return 9;
+	else
+		return irq;
+}
+
+static unsigned long __init
+mcpn765_find_end_of_memory(void)
+{
+	return hawk_get_mem_size(MCPN765_HAWK_SMC_BASE);
+}
+
+static void __init
+mcpn765_map_io(void)
+{
+	io_block_mapping(0xfe800000, 0xfe800000, 0x00800000, _PAGE_IO);
+}
+
+static void
+mcpn765_reset_board(void)
+{
+	local_irq_disable();
+
+	/* set VIA IDE controller into native mode */
+	mcpn765_set_VIA_IDE_native();
+
+	/* Set exception prefix high - to the firmware */
+	_nmask_and_or_msr(0, MSR_IP);
+
+	out_8((u_char *)MCPN765_BOARD_MODRST_REG, 0x01);
+
+	return;
+}
+
+static void
+mcpn765_restart(char *cmd)
+{
+	volatile ulong	i = 10000000;
+
+	mcpn765_reset_board();
+
+	while (i-- > 0);
+	panic("restart failed\n");
+}
+
+static void
+mcpn765_power_off(void)
+{
+	mcpn765_halt();
+	/* NOTREACHED */
+}
+
+static void
+mcpn765_halt(void)
+{
+	local_irq_disable();
+	while (1);
+	/* NOTREACHED */
+}
+
+static int
+mcpn765_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: Motorola MCG\n");
+	seq_printf(m, "machine\t\t: MCPN765\n");
+
+	return 0;
+}
+
+/*
+ * Set BAT 3 to map 0xf0000000 to end of physical memory space.
+ */
+static __inline__ void
+mcpn765_set_bat(void)
+{
+	mb();
+	mtspr(SPRN_DBAT1U, 0xfe8000fe);
+	mtspr(SPRN_DBAT1L, 0xfe80002a);
+	mb();
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+		unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	/* Map in board regs, etc. */
+	mcpn765_set_bat();
+
+	isa_mem_base = MCPN765_ISA_MEM_BASE;
+	pci_dram_offset = MCPN765_PCI_DRAM_OFFSET;
+	ISA_DMA_THRESHOLD = 0x00ffffff;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+
+	ppc_md.setup_arch = mcpn765_setup_arch;
+	ppc_md.show_cpuinfo = mcpn765_show_cpuinfo;
+	ppc_md.irq_canonicalize = mcpn765_irq_canonicalize;
+	ppc_md.init_IRQ = mcpn765_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+	ppc_md.init = mcpn765_init2;
+
+	ppc_md.restart = mcpn765_restart;
+	ppc_md.power_off = mcpn765_power_off;
+	ppc_md.halt = mcpn765_halt;
+
+	ppc_md.find_end_of_memory = mcpn765_find_end_of_memory;
+	ppc_md.setup_io_mappings = mcpn765_map_io;
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.calibrate_decr = todc_calibrate_decr;
+
+	ppc_md.nvram_read_val = todc_m48txx_read_val;
+	ppc_md.nvram_write_val = todc_m48txx_write_val;
+
+	ppc_md.heartbeat = NULL;
+	ppc_md.heartbeat_reset = 0;
+	ppc_md.heartbeat_count = 0;
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = gen550_progress;
+#endif
+#ifdef CONFIG_KGDB
+	ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
+
+	return;
+}
diff --git a/arch/ppc/platforms/mcpn765.h b/arch/ppc/platforms/mcpn765.h
new file mode 100644
index 0000000..4d35eca
--- /dev/null
+++ b/arch/ppc/platforms/mcpn765.h
@@ -0,0 +1,122 @@
+/*
+ * arch/ppc/platforms/mcpn765.h
+ *
+ * Definitions for Motorola MCG MCPN765 cPCI Board.
+ *
+ * Author: Mark A. Greer
+ *         mgreer@mvista.com
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc.  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.
+ */
+
+/*
+ * From Processor to PCI:
+ *   PCI Mem Space: 0x80000000 - 0xc0000000 -> 0x80000000 - 0xc0000000 (1 GB)
+ *   PCI I/O Space: 0xfd800000 - 0xfe000000 -> 0x00000000 - 0x00800000 (8 MB)
+ *	Note: Must skip 0xfe000000-0xfe400000 for CONFIG_HIGHMEM/PKMAP area
+ *   MPIC in PCI Mem Space: 0xfe800000 - 0xfe830000 (not all used by MPIC)
+ *
+ * From PCI to Processor:
+ *   System Memory: 0x00000000 -> 0x00000000
+ */
+
+#ifndef __PPC_PLATFORMS_MCPN765_H
+#define __PPC_PLATFORMS_MCPN765_H
+#include <linux/config.h>
+
+/* PCI Memory space mapping info */
+#define	MCPN765_PCI_MEM_SIZE		0x40000000U
+#define MCPN765_PROC_PCI_MEM_START	0x80000000U
+#define MCPN765_PROC_PCI_MEM_END	(MCPN765_PROC_PCI_MEM_START +	\
+					 MCPN765_PCI_MEM_SIZE - 1)
+#define MCPN765_PCI_MEM_START		0x80000000U
+#define MCPN765_PCI_MEM_END		(MCPN765_PCI_MEM_START +	\
+					 MCPN765_PCI_MEM_SIZE - 1)
+
+/* PCI I/O space mapping info */
+#define	MCPN765_PCI_IO_SIZE		0x00800000U
+#define MCPN765_PROC_PCI_IO_START	0xfd800000U
+#define MCPN765_PROC_PCI_IO_END		(MCPN765_PROC_PCI_IO_START +	\
+					 MCPN765_PCI_IO_SIZE - 1)
+#define MCPN765_PCI_IO_START		0x00000000U
+#define MCPN765_PCI_IO_END		(MCPN765_PCI_IO_START + 	\
+					 MCPN765_PCI_IO_SIZE - 1)
+
+/* System memory mapping info */
+#define MCPN765_PCI_DRAM_OFFSET		0x00000000U
+#define MCPN765_PCI_PHY_MEM_OFFSET	0x00000000U
+
+#define MCPN765_ISA_MEM_BASE		0x00000000U
+#define MCPN765_ISA_IO_BASE		MCPN765_PROC_PCI_IO_START
+
+/* Define base addresses for important sets of registers */
+#define MCPN765_HAWK_MPIC_BASE		0xfe800000U
+#define MCPN765_HAWK_SMC_BASE		0xfef80000U
+#define	MCPN765_HAWK_PPC_REG_BASE	0xfeff0000U
+
+/* Define MCPN765 board register addresses. */
+#define	MCPN765_BOARD_STATUS_REG	0xfef88080U
+#define	MCPN765_BOARD_MODFAIL_REG	0xfef88090U
+#define	MCPN765_BOARD_MODRST_REG	0xfef880a0U
+#define	MCPN765_BOARD_TBEN_REG		0xfef880c0U
+#define	MCPN765_BOARD_GEOGRAPHICAL_REG	0xfef880e8U
+#define	MCPN765_BOARD_EXT_FEATURE_REG	0xfef880f0U
+#define	MCPN765_BOARD_LAST_RESET_REG	0xfef880f8U
+
+/* Defines for UART */
+
+/* Define the UART base addresses */
+#define	MCPN765_SERIAL_1		0xfef88000
+#define	MCPN765_SERIAL_2		0xfef88200
+#define	MCPN765_SERIAL_3		0xfef88400
+#define	MCPN765_SERIAL_4		0xfef88600
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE  64
+#else
+#define RS_TABLE_SIZE  4
+#endif
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD	( 1843200 / 16 )
+#define UART_CLK	1843200
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+/* All UART IRQ's are wire-OR'd to IRQ 17 */
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, MCPN765_SERIAL_1, 17, STD_COM_FLAGS, /* ttyS0 */\
+		iomem_base: (u8 *)MCPN765_SERIAL_1,			\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },				\
+        { 0, BASE_BAUD, MCPN765_SERIAL_2, 17, STD_COM_FLAGS, /* ttyS1 */\
+		iomem_base: (u8 *)MCPN765_SERIAL_2,			\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },				\
+        { 0, BASE_BAUD, MCPN765_SERIAL_3, 17, STD_COM_FLAGS, /* ttyS2 */\
+		iomem_base: (u8 *)MCPN765_SERIAL_3,			\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },				\
+        { 0, BASE_BAUD, MCPN765_SERIAL_4, 17, STD_COM_FLAGS, /* ttyS3 */\
+		iomem_base: (u8 *)MCPN765_SERIAL_4,			\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
+
+/* Define the NVRAM/RTC address strobe & data registers */
+#define MCPN765_PHYS_NVRAM_AS0          0xfef880c8U
+#define MCPN765_PHYS_NVRAM_AS1          0xfef880d0U
+#define MCPN765_PHYS_NVRAM_DATA         0xfef880d8U
+
+extern void mcpn765_find_bridges(void);
+
+#endif /* __PPC_PLATFORMS_MCPN765_H */
diff --git a/arch/ppc/platforms/mpc5200.c b/arch/ppc/platforms/mpc5200.c
new file mode 100644
index 0000000..a58db43
--- /dev/null
+++ b/arch/ppc/platforms/mpc5200.c
@@ -0,0 +1,53 @@
+/*
+ * arch/ppc/platforms/mpc5200.c
+ *
+ * OCP Definitions for the boards based on MPC5200 processor. Contains
+ * definitions for every common peripherals. (Mostly all but PSCs)
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright 2004 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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 <asm/ocp.h>
+#include <asm/mpc52xx.h>
+
+
+static struct ocp_fs_i2c_data mpc5200_i2c_def = {
+        .flags  = FS_I2C_CLOCK_5200,
+};
+
+
+/* Here is the core_ocp struct.
+ * With all the devices common to all board. Even if port multiplexing is
+ * not setup for them (if the user don't want them, just don't select the
+ * config option). The potentially conflicting devices (like PSCs) goes in
+ * board specific file.
+ */
+struct ocp_def core_ocp[] = {
+	{
+		.vendor         = OCP_VENDOR_FREESCALE,
+		.function       = OCP_FUNC_IIC,
+		.index          = 0,
+		.paddr          = MPC52xx_I2C1,
+		.irq            = OCP_IRQ_NA,   /* MPC52xx_IRQ_I2C1 - Buggy */
+		.pm             = OCP_CPM_NA,
+		.additions      = &mpc5200_i2c_def,
+	},
+	{
+		.vendor         = OCP_VENDOR_FREESCALE,
+		.function       = OCP_FUNC_IIC,
+		.index          = 1,
+		.paddr          = MPC52xx_I2C2,
+		.irq            = OCP_IRQ_NA,   /* MPC52xx_IRQ_I2C2 - Buggy */
+		.pm             = OCP_CPM_NA,
+		.additions      = &mpc5200_i2c_def,
+	},
+	{	/* Terminating entry */
+		.vendor		= OCP_VENDOR_INVALID
+	}
+};
diff --git a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c
new file mode 100644
index 0000000..b292b44
--- /dev/null
+++ b/arch/ppc/platforms/mvme5100.c
@@ -0,0 +1,349 @@
+/*
+ * arch/ppc/platforms/mvme5100.c
+ *
+ * Board setup routines for the Motorola MVME5100.
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc.  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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/kdev_t.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/pci-bridge.h>
+#include <asm/bootinfo.h>
+#include <asm/hawk.h>
+
+#include <platforms/pplus.h>
+#include <platforms/mvme5100.h>
+
+static u_char mvme5100_openpic_initsenses[16] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* i8259 cascade */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* TL16C550 UART 1,2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Enet1 front panel or P2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Hawk Watchdog 1,2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* DS1621 thermal alarm */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT0# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT1# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT2# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT3# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTA#, PMC2 INTB# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTB#, PMC2 INTC# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTC#, PMC2 INTD# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTD#, PMC2 INTA# */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Enet 2 (front panel) */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Abort Switch */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* RTC Alarm */
+};
+
+static inline int
+mvme5100_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	int irq;
+
+	static char pci_irq_table[][4] =
+	/*
+	 *	PCI IDSEL/INTPIN->INTLINE
+	 * 	   A   B   C   D
+	 */
+	{
+		{  0,  0,  0,  0 },	/* IDSEL 11 - Winbond */
+		{  0,  0,  0,  0 },	/* IDSEL 12 - unused */
+		{ 21, 22, 23, 24 },	/* IDSEL 13 - Universe II */
+		{ 18,  0,  0,  0 },	/* IDSEL 14 - Enet 1 */
+		{  0,  0,  0,  0 },	/* IDSEL 15 - unused */
+		{ 25, 26, 27, 28 },	/* IDSEL 16 - PMC Slot 1 */
+		{ 28, 25, 26, 27 },	/* IDSEL 17 - PMC Slot 2 */
+		{  0,  0,  0,  0 },	/* IDSEL 18 - unused */
+		{ 29,  0,  0,  0 },	/* IDSEL 19 - Enet 2 */
+		{  0,  0,  0,  0 },	/* IDSEL 20 - PMCSPAN */
+	};
+
+	const long min_idsel = 11, max_idsel = 20, irqs_per_slot = 4;
+	irq = PCI_IRQ_TABLE_LOOKUP;
+	/* If lookup is zero, always return 0 */
+	if (!irq)
+		return 0;
+	else
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+	/* If IPMC761 present, return table value */
+	return irq;
+#else
+	/* If IPMC761 not present, we don't have an i8259 so adjust */
+	return (irq - NUM_8259_INTERRUPTS);
+#endif
+}
+
+static void
+mvme5100_pcibios_fixup_resources(struct pci_dev *dev)
+{
+	int i;
+
+	if ((dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
+			(dev->device == PCI_DEVICE_ID_MOTOROLA_HAWK))
+		for (i=0; i<DEVICE_COUNT_RESOURCE; i++)
+		{
+			dev->resource[i].start = 0;
+			dev->resource[i].end = 0;
+		}
+}
+
+static void __init
+mvme5100_setup_bridge(void)
+{
+	struct pci_controller*	hose;
+
+	hose = pcibios_alloc_controller();
+
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+	hose->pci_mem_offset = MVME5100_PCI_MEM_OFFSET;
+
+	pci_init_resource(&hose->io_resource, MVME5100_PCI_LOWER_IO,
+			MVME5100_PCI_UPPER_IO, IORESOURCE_IO,
+			"PCI host bridge");
+
+	pci_init_resource(&hose->mem_resources[0], MVME5100_PCI_LOWER_MEM,
+			MVME5100_PCI_UPPER_MEM, IORESOURCE_MEM,
+			"PCI host bridge");
+
+	hose->io_space.start = MVME5100_PCI_LOWER_IO;
+	hose->io_space.end = MVME5100_PCI_UPPER_IO;
+	hose->mem_space.start = MVME5100_PCI_LOWER_MEM;
+	hose->mem_space.end = MVME5100_PCI_UPPER_MEM;
+	hose->io_base_virt = (void *)MVME5100_ISA_IO_BASE;
+
+	/* Use indirect method of Hawk */
+	setup_indirect_pci(hose, MVME5100_PCI_CONFIG_ADDR,
+			MVME5100_PCI_CONFIG_DATA);
+
+	hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+	ppc_md.pcibios_fixup_resources = mvme5100_pcibios_fixup_resources;
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = mvme5100_map_irq;
+}
+
+static void __init
+mvme5100_setup_arch(void)
+{
+	if ( ppc_md.progress )
+		ppc_md.progress("mvme5100_setup_arch: enter", 0);
+
+	loops_per_jiffy = 50000000 / HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef	CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA2;
+#endif
+
+	if ( ppc_md.progress )
+		ppc_md.progress("mvme5100_setup_arch: find_bridges", 0);
+
+	/* Setup PCI host bridge */
+	mvme5100_setup_bridge();
+
+	/* Find and map our OpenPIC */
+	hawk_mpic_init(MVME5100_PCI_MEM_OFFSET);
+	OpenPIC_InitSenses = mvme5100_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof(mvme5100_openpic_initsenses);
+
+	printk("MVME5100 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n");
+
+	if ( ppc_md.progress )
+		ppc_md.progress("mvme5100_setup_arch: exit", 0);
+
+	return;
+}
+
+static void __init
+mvme5100_init2(void)
+{
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+		request_region(0x00,0x20,"dma1");
+		request_region(0x20,0x20,"pic1");
+		request_region(0x40,0x20,"timer");
+		request_region(0x80,0x10,"dma page reg");
+		request_region(0xa0,0x20,"pic2");
+		request_region(0xc0,0x20,"dma2");
+#endif
+	return;
+}
+
+/*
+ * Interrupt setup and service.
+ * Have MPIC on HAWK and cascaded 8259s on Winbond cascaded to MPIC.
+ */
+static void __init
+mvme5100_init_IRQ(void)
+{
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+	int i;
+#endif
+
+	if ( ppc_md.progress )
+		ppc_md.progress("init_irq: enter", 0);
+
+	openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000);
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+	openpic_init(NUM_8259_INTERRUPTS);
+	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+			&i8259_irq);
+
+	/* Map i8259 interrupts. */
+	for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+		irq_desc[i].handler = &i8259_pic;
+
+	i8259_init(0);
+#else
+	openpic_init(0);
+#endif
+
+	if ( ppc_md.progress )
+		ppc_md.progress("init_irq: exit", 0);
+
+	return;
+}
+
+/*
+ * Set BAT 3 to map 0xf0000000 to end of physical memory space.
+ */
+static __inline__ void
+mvme5100_set_bat(void)
+{
+	mb();
+	mtspr(SPRN_DBAT1U, 0xf0001ffe);
+	mtspr(SPRN_DBAT1L, 0xf000002a);
+	mb();
+}
+
+static unsigned long __init
+mvme5100_find_end_of_memory(void)
+{
+	return hawk_get_mem_size(MVME5100_HAWK_SMC_BASE);
+}
+
+static void __init
+mvme5100_map_io(void)
+{
+	io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+	ioremap_base = 0xfe000000;
+}
+
+static void
+mvme5100_reset_board(void)
+{
+	local_irq_disable();
+
+	/* Set exception prefix high - to the firmware */
+	_nmask_and_or_msr(0, MSR_IP);
+
+	out_8((u_char *)MVME5100_BOARD_MODRST_REG, 0x01);
+
+	return;
+}
+
+static void
+mvme5100_restart(char *cmd)
+{
+	volatile ulong i = 10000000;
+
+	mvme5100_reset_board();
+
+	while (i-- > 0);
+	panic("restart failed\n");
+}
+
+static void
+mvme5100_halt(void)
+{
+	local_irq_disable();
+	while (1);
+}
+
+static void
+mvme5100_power_off(void)
+{
+	mvme5100_halt();
+}
+
+static int
+mvme5100_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: Motorola\n");
+	seq_printf(m, "machine\t\t: MVME5100\n");
+
+	return 0;
+}
+
+TODC_ALLOC();
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+	mvme5100_set_bat();
+
+	isa_io_base = MVME5100_ISA_IO_BASE;
+	isa_mem_base = MVME5100_ISA_MEM_BASE;
+	pci_dram_offset = MVME5100_PCI_DRAM_OFFSET;
+
+	ppc_md.setup_arch = mvme5100_setup_arch;
+	ppc_md.show_cpuinfo = mvme5100_show_cpuinfo;
+	ppc_md.init_IRQ = mvme5100_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+	ppc_md.init = mvme5100_init2;
+
+	ppc_md.restart = mvme5100_restart;
+	ppc_md.power_off = mvme5100_power_off;
+	ppc_md.halt = mvme5100_halt;
+
+	ppc_md.find_end_of_memory = mvme5100_find_end_of_memory;
+	ppc_md.setup_io_mappings = mvme5100_map_io;
+
+	TODC_INIT(TODC_TYPE_MK48T37, MVME5100_NVRAM_AS0, MVME5100_NVRAM_AS1,
+			MVME5100_NVRAM_DATA, 8);
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.calibrate_decr = todc_calibrate_decr;
+
+	ppc_md.nvram_read_val = todc_m48txx_read_val;
+	ppc_md.nvram_write_val = todc_m48txx_write_val;
+}
diff --git a/arch/ppc/platforms/mvme5100.h b/arch/ppc/platforms/mvme5100.h
new file mode 100644
index 0000000..edd4794
--- /dev/null
+++ b/arch/ppc/platforms/mvme5100.h
@@ -0,0 +1,91 @@
+/*
+ * include/asm-ppc/platforms/mvme5100.h
+ *
+ * Definitions for Motorola MVME5100.
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_MVME5100_H__
+#define __ASM_MVME5100_H__
+
+#define MVME5100_HAWK_SMC_BASE		0xfef80000
+
+#define	MVME5100_PCI_CONFIG_ADDR	0xfe000cf8
+#define	MVME5100_PCI_CONFIG_DATA	0xfe000cfc
+
+#define MVME5100_PCI_IO_BASE		0xfe000000
+#define MVME5100_PCI_MEM_BASE		0x80000000
+
+#define MVME5100_PCI_MEM_OFFSET		0x00000000
+
+#define MVME5100_PCI_DRAM_OFFSET	0x00000000
+#define MVME5100_ISA_MEM_BASE		0x00000000
+#define MVME5100_ISA_IO_BASE		MVME5100_PCI_IO_BASE
+
+#define MVME5100_PCI_LOWER_MEM		0x80000000
+#define MVME5100_PCI_UPPER_MEM		0xf3f7ffff
+#define MVME5100_PCI_LOWER_IO		0x00000000
+#define MVME5100_PCI_UPPER_IO		0x0077ffff
+
+/* MVME5100 board register addresses. */
+#define	MVME5100_BOARD_STATUS_REG	0xfef88080
+#define	MVME5100_BOARD_MODFAIL_REG	0xfef88090
+#define	MVME5100_BOARD_MODRST_REG	0xfef880a0
+#define	MVME5100_BOARD_TBEN_REG		0xfef880c0
+#define MVME5100_BOARD_SW_READ_REG	0xfef880e0
+#define	MVME5100_BOARD_GEO_ADDR_REG	0xfef880e8
+#define	MVME5100_BOARD_EXT_FEATURE1_REG	0xfef880f0
+#define	MVME5100_BOARD_EXT_FEATURE2_REG	0xfef88100
+
+/* Define the NVRAM/RTC address strobe & data registers */
+#define MVME5100_PHYS_NVRAM_AS0		0xfef880c8
+#define MVME5100_PHYS_NVRAM_AS1		0xfef880d0
+#define MVME5100_PHYS_NVRAM_DATA	0xfef880d8
+
+#define MVME5100_NVRAM_AS0	(MVME5100_PHYS_NVRAM_AS0 - MVME5100_ISA_IO_BASE)
+#define MVME5100_NVRAM_AS1	(MVME5100_PHYS_NVRAM_AS1 - MVME5100_ISA_IO_BASE)
+#define MVME5100_NVRAM_DATA	(MVME5100_PHYS_NVRAM_DATA - MVME5100_ISA_IO_BASE)
+
+/* UART clock, addresses, and irq */
+#define MVME5100_BASE_BAUD		1843200
+#define	MVME5100_SERIAL_1		0xfef88000
+#define	MVME5100_SERIAL_2		0xfef88200
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+#define MVME5100_SERIAL_IRQ		17
+#else
+#define MVME5100_SERIAL_IRQ		1
+#endif
+
+#define RS_TABLE_SIZE  4
+
+#define BASE_BAUD ( MVME5100_BASE_BAUD / 16 )
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+/* All UART IRQ's are wire-OR'd to one MPIC IRQ */
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, MVME5100_SERIAL_1, \
+		MVME5100_SERIAL_IRQ, \
+		STD_COM_FLAGS, /* ttyS0 */ \
+		iomem_base: (unsigned char *)MVME5100_SERIAL_1,		\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },				\
+        { 0, BASE_BAUD, MVME5100_SERIAL_2, \
+		MVME5100_SERIAL_IRQ, \
+		STD_COM_FLAGS, /* ttyS1 */ \
+		iomem_base: (unsigned char *)MVME5100_SERIAL_2,		\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
+
+#endif /* __ASM_MVME5100_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/pal4.h b/arch/ppc/platforms/pal4.h
new file mode 100644
index 0000000..641a11a
--- /dev/null
+++ b/arch/ppc/platforms/pal4.h
@@ -0,0 +1,42 @@
+/*
+ * arch/ppc/platforms/pal4.h
+ *
+ * Definitions for SBS Palomar IV board
+ *
+ * Author: Dan Cox
+ *
+ * 2002 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifndef __PPC_PLATFORMS_PAL4_H
+#define __PPC_PLATFORMS_PAL4_H
+
+#define PAL4_NVRAM             0xfffc0000
+#define PAL4_NVRAM_SIZE        0x8000
+
+#define PAL4_DRAM              0xfff80000
+#define  PAL4_DRAM_BR_MASK     0xc0
+#define  PAL4_DRAM_BR_SHIFT    6
+#define  PAL4_DRAM_RESET       0x10
+#define  PAL4_DRAM_EREADY      0x40
+
+#define PAL4_MISC              0xfff80004
+#define  PAL4_MISC_FB_MASK     0xc0
+#define  PAL4_MISC_FLASH       0x20  /* StratFlash mapping: 1->0xff80, 0->0xfff0 */
+#define  PAL4_MISC_MISC        0x08
+#define  PAL4_MISC_BITF        0x02
+#define  PAL4_MISC_NVKS        0x01
+
+#define PAL4_L2                0xfff80008
+#define  PAL4_L2_MASK          0x07
+
+#define PAL4_PLDR              0xfff8000c
+
+/* Only two Ethernet devices on the board... */
+#define PAL4_ETH               31
+#define PAL4_INTA              20
+
+#endif /* __PPC_PLATFORMS_PAL4_H */
diff --git a/arch/ppc/platforms/pal4_pci.c b/arch/ppc/platforms/pal4_pci.c
new file mode 100644
index 0000000..c3b1b75
--- /dev/null
+++ b/arch/ppc/platforms/pal4_pci.c
@@ -0,0 +1,77 @@
+/*
+ * arch/ppc/platforms/pal4_pci.c
+ *
+ * PCI support for SBS Palomar IV
+ *
+ * Author: Dan Cox
+ *
+ * 2002 (c) MontaVista, Software, Inc.  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/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/byteorder.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/uaccess.h>
+
+#include <syslib/cpc700.h>
+
+#include "pal4.h"
+
+/* not much to this.... */
+static inline int __init
+pal4_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	if (idsel == 9)
+		return PAL4_ETH;
+	else
+		return PAL4_INTA + (idsel - 3);
+}
+
+void __init
+pal4_find_bridges(void)
+{
+	struct pci_controller *hose;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+	hose->pci_mem_offset = 0;
+
+	/* Could snatch these from the CPC700.... */
+	pci_init_resource(&hose->io_resource,
+			  0x0,
+			  0x03ffffff,
+			  IORESOURCE_IO,
+			  "PCI host bridge");
+
+	pci_init_resource(&hose->mem_resources[0],
+			  0x90000000,
+			  0x9fffffff,
+			  IORESOURCE_MEM,
+			  "PCI host bridge");
+
+	hose->io_space.start = 0x00800000;
+	hose->io_space.end = 0x03ffffff;
+	hose->mem_space.start = 0x90000000;
+	hose->mem_space.end = 0x9fffffff;
+	hose->io_base_virt = (void *) 0xf8000000;
+
+	setup_indirect_pci(hose, CPC700_PCI_CONFIG_ADDR,
+			   CPC700_PCI_CONFIG_DATA);
+
+	hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = pal4_map_irq;
+}
diff --git a/arch/ppc/platforms/pal4_serial.h b/arch/ppc/platforms/pal4_serial.h
new file mode 100644
index 0000000..a715c66
--- /dev/null
+++ b/arch/ppc/platforms/pal4_serial.h
@@ -0,0 +1,39 @@
+/*
+ * arch/ppc/platforms/pal4_serial.h
+ *
+ * Definitions for SBS PalomarIV serial support
+ *
+ * Author: Dan Cox
+ *
+ * 2002 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifndef __PPC_PAL4_SERIAL_H
+#define __PPC_PAL4_SERIAL_H
+
+#define CPC700_SERIAL_1       0xff600300
+#define CPC700_SERIAL_2       0xff600400
+
+#define RS_TABLE_SIZE     2
+#define BASE_BAUD         (33333333 / 4 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define SERIAL_PORT_DFNS \
+      {0, BASE_BAUD, CPC700_SERIAL_1, 3, STD_COM_FLAGS, \
+       iomem_base: (unsigned char *) CPC700_SERIAL_1, \
+       io_type: SERIAL_IO_MEM},   /* ttyS0 */ \
+      {0, BASE_BAUD, CPC700_SERIAL_2, 4, STD_COM_FLAGS, \
+       iomem_base: (unsigned char *) CPC700_SERIAL_2, \
+       io_type: SERIAL_IO_MEM}
+
+#endif
diff --git a/arch/ppc/platforms/pal4_setup.c b/arch/ppc/platforms/pal4_setup.c
new file mode 100644
index 0000000..12446b9
--- /dev/null
+++ b/arch/ppc/platforms/pal4_setup.c
@@ -0,0 +1,175 @@
+/*
+ * arch/ppc/platforms/pal4_setup.c
+ *
+ * Board setup routines for the SBS PalomarIV.
+ *
+ * Author: Dan Cox
+ *
+ * 2002 (c) MontaVista, Software, Inc.  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/types.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/time.h>
+#include <linux/irq.h>
+#include <linux/kdev_t.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/io.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+
+#include <syslib/cpc700.h>
+
+#include "pal4.h"
+
+extern void pal4_find_bridges(void);
+
+unsigned int cpc700_irq_assigns[][2] = {
+        {1, 1},    /* IRQ 0: ECC correctable error */
+        {1, 1},    /* IRQ 1: PCI write to memory range */
+        {0, 1},    /* IRQ 2: PCI write to command register */
+        {0, 1},    /* IRQ 3: UART 0 */
+        {0, 1},    /* IRQ 4: UART 1 */
+        {0, 1},    /* IRQ 5: ICC 0 */
+        {0, 1},    /* IRQ 6: ICC 1 */
+        {0, 1},    /* IRQ 7: GPT compare 0 */
+        {0, 1},    /* IRQ 8: GPT compare 1 */
+        {0, 1},    /* IRQ 9: GPT compare 2 */
+        {0, 1},    /* IRQ 10: GPT compare 3 */
+        {0, 1},    /* IRQ 11: GPT compare 4 */
+        {0, 1},    /* IRQ 12: GPT capture 0 */
+        {0, 1},    /* IRQ 13: GPT capture 1 */
+        {0, 1},    /* IRQ 14: GPT capture 2 */
+        {0, 1},    /* IRQ 15: GPT capture 3 */
+        {0, 1},    /* IRQ 16: GPT capture 4 */
+        {0, 0},    /* IRQ 17: reserved */
+        {0, 0},    /* IRQ 18: reserved */
+        {0, 0},    /* IRQ 19: reserved */
+        {0, 0},    /* IRQ 20: reserved */
+        {0, 1},    /* IRQ 21: Ethernet */
+        {0, 0},    /* IRQ 22: reserved */
+        {0, 0},    /* IRQ 23: reserved */
+        {0, 0},    /* IRQ 24: resreved */
+        {0, 0},    /* IRQ 25: reserved */
+        {0, 0},    /* IRQ 26: reserved */
+        {0, 0},    /* IRQ 27: reserved */
+        {0, 0},    /* IRQ 28: reserved */
+        {0, 0},    /* IRQ 29: reserved */
+        {0, 0},    /* IRQ 30: reserved */
+        {0, 0},    /* IRQ 31: reserved */
+};
+
+static int
+pal4_show_cpuinfo(struct seq_file *m)
+{
+        seq_printf(m, "board\t\t: SBS Palomar IV\n");
+
+        return 0;
+}
+
+static void
+pal4_restart(char *cmd)
+{
+        local_irq_disable();
+        __asm__ __volatile__("lis  3,0xfff0\n \
+                              ori  3,3,0x100\n \
+                              mtspr 26,3\n \
+                              li   3,0\n \
+                              mtspr 27,3\n \
+                              rfi");
+
+        for(;;);
+}
+
+static void
+pal4_power_off(void)
+{
+	local_irq_disable();
+	for(;;);
+}
+
+static void
+pal4_halt(void)
+{
+	pal4_power_off();
+}
+
+TODC_ALLOC();
+
+static void __init
+pal4_setup_arch(void)
+{
+	unsigned long l2;
+
+	TODC_INIT(TODC_TYPE_MK48T37, 0, 0,
+		  ioremap(PAL4_NVRAM, PAL4_NVRAM_SIZE), 8);
+
+	pal4_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+		ROOT_DEV = Root_NFS;
+
+	/* The L2 gets disabled in the bootloader, but all the proper
+	   bits should be present from the fw, so just re-enable it */
+	l2 = _get_L2CR();
+	if (!(l2 & L2CR_L2E)) {
+		/* presume that it was initially set if the size is
+		   still present. */
+		if (l2 ^ L2CR_L2SIZ_MASK)
+			_set_L2CR(l2 | L2CR_L2E);
+		else
+			printk("L2 not set by firmware; left disabled.\n");
+	}
+}
+
+static void __init
+pal4_map_io(void)
+{
+	io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	isa_io_base = 0 /*PAL4_ISA_IO_BASE*/;
+	pci_dram_offset = 0 /*PAL4_PCI_SYS_MEM_BASE*/;
+
+	ppc_md.setup_arch = pal4_setup_arch;
+	ppc_md.show_cpuinfo = pal4_show_cpuinfo;
+
+	ppc_md.setup_io_mappings = pal4_map_io;
+
+	ppc_md.init_IRQ = cpc700_init_IRQ;
+	ppc_md.get_irq = cpc700_get_irq;
+
+	ppc_md.restart = pal4_restart;
+	ppc_md.halt = pal4_halt;
+	ppc_md.power_off = pal4_power_off;
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.calibrate_decr = todc_calibrate_decr;
+
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+}
+
diff --git a/arch/ppc/platforms/pcore.c b/arch/ppc/platforms/pcore.c
new file mode 100644
index 0000000..d719163
--- /dev/null
+++ b/arch/ppc/platforms/pcore.c
@@ -0,0 +1,352 @@
+/*
+ * arch/ppc/platforms/pcore_setup.c
+ *
+ * Setup routines for Force PCORE boards
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc.  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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/i8259.h>
+#include <asm/mpc10x.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/kgdb.h>
+
+#include "pcore.h"
+
+extern unsigned long loops_per_jiffy;
+
+static int board_type;
+
+static inline int __init
+pcore_6750_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	/*
+	 *      PCI IDSEL/INTPIN->INTLINE
+	 *      A       B       C       D
+	 */
+	{
+		{9,	10,	11,	12},	/* IDSEL 24 - DEC 21554 */
+		{10,	0,	0,	0},	/* IDSEL 25 - DEC 21143 */
+		{11,	12,	9,	10},	/* IDSEL 26 - PMC I */
+		{12,	9,	10,	11},	/* IDSEL 27 - PMC II */
+		{0,	0,	0,	0},	/* IDSEL 28 - unused */
+		{0,	0,	9,	0},	/* IDSEL 29 - unused */
+		{0,	0,	0,	0},	/* IDSEL 30 - Winbond */
+		};
+	const long min_idsel = 24, max_idsel = 30, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+};
+
+static inline int __init
+pcore_680_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	/*
+	 *      PCI IDSEL/INTPIN->INTLINE
+	 *      A       B       C       D
+	 */
+	{
+		{9,	10,	11,	12},	/* IDSEL 24 - Sentinel */
+		{10,	0,	0,	0},	/* IDSEL 25 - i82559 #1 */
+		{11,	12,	9,	10},	/* IDSEL 26 - PMC I */
+		{12,	9,	10,	11},	/* IDSEL 27 - PMC II */
+		{9,	0,	0,	0},	/* IDSEL 28 - i82559 #2 */
+		{0,	0,	0,	0},	/* IDSEL 29 - unused */
+		{0,	0,	0,	0},	/* IDSEL 30 - Winbond */
+		};
+	const long min_idsel = 24, max_idsel = 30, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+};
+
+void __init
+pcore_pcibios_fixup(void)
+{
+	struct pci_dev *dev;
+
+	if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+				PCI_DEVICE_ID_WINBOND_83C553,
+				0)))
+	{
+		/* Reroute interrupts both IDE channels to 15 */
+		pci_write_config_byte(dev,
+				PCORE_WINBOND_IDE_INT,
+				0xff);
+
+		/* Route INTA-D to IRQ9-12, respectively */
+		pci_write_config_word(dev,
+				PCORE_WINBOND_PCI_INT,
+				0x9abc);
+
+		/*
+		 * Set up 8259 edge/level triggering
+		 */
+ 		outb(0x00, PCORE_WINBOND_PRI_EDG_LVL);
+		outb(0x1e, PCORE_WINBOND_SEC_EDG_LVL);
+		pci_dev_put(dev);
+	}
+}
+
+int __init
+pcore_find_bridges(void)
+{
+	struct pci_controller* hose;
+	int host_bridge, board_type;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return 0;
+
+	mpc10x_bridge_init(hose,
+			MPC10X_MEM_MAP_B,
+			MPC10X_MEM_MAP_B,
+			MPC10X_MAPB_EUMB_BASE);
+
+	/* Determine board type */
+	early_read_config_dword(hose,
+			0,
+			PCI_DEVFN(0,0),
+			PCI_VENDOR_ID,
+			&host_bridge);
+	if (host_bridge == MPC10X_BRIDGE_106)
+		board_type = PCORE_TYPE_6750;
+	else /* MPC10X_BRIDGE_107 */
+		board_type = PCORE_TYPE_680;
+
+	hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+	ppc_md.pcibios_fixup = pcore_pcibios_fixup;
+	ppc_md.pci_swizzle = common_swizzle;
+
+	if (board_type == PCORE_TYPE_6750)
+		ppc_md.pci_map_irq = pcore_6750_map_irq;
+	else /* PCORE_TYPE_680 */
+		ppc_md.pci_map_irq = pcore_680_map_irq;
+
+	return board_type;
+}
+
+/* Dummy variable to satisfy mpc10x_common.o */
+void *OpenPIC_Addr;
+
+static int
+pcore_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: Force Computers\n");
+
+	if (board_type == PCORE_TYPE_6750)
+		seq_printf(m, "machine\t\t: PowerCore 6750\n");
+	else /* PCORE_TYPE_680 */
+		seq_printf(m, "machine\t\t: PowerCore 680\n");
+
+	seq_printf(m, "L2\t\t: " );
+	if (board_type == PCORE_TYPE_6750)
+		switch (readb(PCORE_DCCR_REG) & PCORE_DCCR_L2_MASK)
+		{
+			case PCORE_DCCR_L2_0KB:
+				seq_printf(m, "nocache");
+				break;
+			case PCORE_DCCR_L2_256KB:
+				seq_printf(m, "256KB");
+				break;
+			case PCORE_DCCR_L2_1MB:
+				seq_printf(m, "1MB");
+				break;
+			case PCORE_DCCR_L2_512KB:
+				seq_printf(m, "512KB");
+				break;
+			default:
+				seq_printf(m, "error");
+				break;
+		}
+	else /* PCORE_TYPE_680 */
+		switch (readb(PCORE_DCCR_REG) & PCORE_DCCR_L2_MASK)
+		{
+			case PCORE_DCCR_L2_2MB:
+				seq_printf(m, "2MB");
+				break;
+			case PCORE_DCCR_L2_256KB:
+				seq_printf(m, "reserved");
+				break;
+			case PCORE_DCCR_L2_1MB:
+				seq_printf(m, "1MB");
+				break;
+			case PCORE_DCCR_L2_512KB:
+				seq_printf(m, "512KB");
+				break;
+			default:
+				seq_printf(m, "error");
+				break;
+		}
+
+	seq_printf(m, "\n");
+
+	return 0;
+}
+
+static void __init
+pcore_setup_arch(void)
+{
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000/HZ;
+
+	/* Lookup PCI host bridges */
+	board_type = pcore_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+        else
+#endif
+#ifdef CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA2;
+#endif
+
+ 	printk(KERN_INFO "Force PowerCore ");
+	if (board_type == PCORE_TYPE_6750)
+		printk("6750\n");
+	else
+		printk("680\n");
+	printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+	_set_L2CR(L2CR_L2E | _get_L2CR());
+
+}
+
+static void
+pcore_restart(char *cmd)
+{
+	local_irq_disable();
+	/* Hard reset */
+	writeb(0x11, 0xfe000332);
+	while(1);
+}
+
+static void
+pcore_halt(void)
+{
+	local_irq_disable();
+	/* Turn off user LEDs */
+	writeb(0x00, 0xfe000300);
+	while (1);
+}
+
+static void
+pcore_power_off(void)
+{
+	pcore_halt();
+}
+
+
+static void __init
+pcore_init_IRQ(void)
+{
+	int i;
+
+	for ( i = 0 ; i < 16 ; i++ )
+		irq_desc[i].handler = &i8259_pic;
+
+	i8259_init(0);
+}
+
+/*
+ * Set BAT 3 to map 0xf0000000 to end of physical memory space.
+ */
+static __inline__ void
+pcore_set_bat(void)
+{
+	mb();
+	mtspr(SPRN_DBAT3U, 0xf0001ffe);
+	mtspr(SPRN_DBAT3L, 0xfe80002a);
+	mb();
+
+}
+
+static unsigned long __init
+pcore_find_end_of_memory(void)
+{
+
+	return mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
+}
+
+static void __init
+pcore_map_io(void)
+{
+	io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+}
+
+TODC_ALLOC();
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+		unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	/* Cover I/O space with a BAT */
+	/* yuck, better hope your ram size is a power of 2  -- paulus */
+	pcore_set_bat();
+
+	isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
+	isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
+	pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
+
+	ppc_md.setup_arch	= pcore_setup_arch;
+	ppc_md.show_cpuinfo	= pcore_show_cpuinfo;
+	ppc_md.init_IRQ		= pcore_init_IRQ;
+	ppc_md.get_irq		= i8259_irq;
+
+	ppc_md.find_end_of_memory = pcore_find_end_of_memory;
+	ppc_md.setup_io_mappings = pcore_map_io;
+
+	ppc_md.restart		= pcore_restart;
+	ppc_md.power_off	= pcore_power_off;
+	ppc_md.halt		= pcore_halt;
+
+	TODC_INIT(TODC_TYPE_MK48T59,
+		  PCORE_NVRAM_AS0,
+		  PCORE_NVRAM_AS1,
+		  PCORE_NVRAM_DATA,
+		  8);
+
+	ppc_md.time_init	= todc_time_init;
+	ppc_md.get_rtc_time	= todc_get_rtc_time;
+	ppc_md.set_rtc_time	= todc_set_rtc_time;
+	ppc_md.calibrate_decr	= todc_calibrate_decr;
+
+	ppc_md.nvram_read_val	= todc_m48txx_read_val;
+	ppc_md.nvram_write_val	= todc_m48txx_write_val;
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = gen550_progress;
+#endif
+#ifdef CONFIG_KGDB
+	ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
+}
diff --git a/arch/ppc/platforms/pcore.h b/arch/ppc/platforms/pcore.h
new file mode 100644
index 0000000..c6a26e7
--- /dev/null
+++ b/arch/ppc/platforms/pcore.h
@@ -0,0 +1,39 @@
+/*
+ * arch/ppc/platforms/pcore.h
+ *
+ * Definitions for Force PowerCore board support
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifndef __PPC_PLATFORMS_PCORE_H
+#define __PPC_PLATFORMS_PCORE_H
+
+#include <asm/mpc10x.h>
+
+#define PCORE_TYPE_6750			1
+#define PCORE_TYPE_680			2
+
+#define PCORE_NVRAM_AS0			0x73
+#define PCORE_NVRAM_AS1			0x75
+#define PCORE_NVRAM_DATA		0x77
+
+#define PCORE_DCCR_REG			(MPC10X_MAPB_ISA_IO_BASE + 0x308)
+#define PCORE_DCCR_L2_MASK		0xc0
+#define PCORE_DCCR_L2_0KB		0x00
+#define PCORE_DCCR_L2_256KB		0x40
+#define PCORE_DCCR_L2_512KB		0xc0
+#define PCORE_DCCR_L2_1MB		0x80
+#define PCORE_DCCR_L2_2MB		0x00
+
+#define PCORE_WINBOND_IDE_INT		0x43
+#define PCORE_WINBOND_PCI_INT		0x44
+#define PCORE_WINBOND_PRI_EDG_LVL	0x4d0
+#define PCORE_WINBOND_SEC_EDG_LVL	0x4d1
+
+#endif /* __PPC_PLATFORMS_PCORE_H */
diff --git a/arch/ppc/platforms/pcu_e.h b/arch/ppc/platforms/pcu_e.h
new file mode 100644
index 0000000..91a820a
--- /dev/null
+++ b/arch/ppc/platforms/pcu_e.h
@@ -0,0 +1,28 @@
+/*
+ * Siemens PCU E board specific definitions
+ *
+ * Copyright (c) 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __MACH_PCU_E_H
+#define __MACH_PCU_E_H
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define	PCU_E_IMMR_BASE    0xFE000000	/* phys. addr of IMMR			*/
+#define	PCU_E_IMAP_SIZE   (64 * 1024)	/* size of mapped area			*/
+
+#define	IMAP_ADDR     PCU_E_IMMR_BASE	/* physical base address of IMMR area	*/
+#define IMAP_SIZE     PCU_E_IMAP_SIZE	/* mapped size of IMMR area		*/
+
+#define	FEC_INTERRUPT	15		/* = SIU_LEVEL7				*/
+#define	DEC_INTERRUPT	13		/* = SIU_LEVEL6				*/
+#define	CPM_INTERRUPT	11		/* = SIU_LEVEL5 (was: SIU_LEVEL2)	*/
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif	/* __MACH_PCU_E_H */
diff --git a/arch/ppc/platforms/pmac_backlight.c b/arch/ppc/platforms/pmac_backlight.c
new file mode 100644
index 0000000..ed2b1ce
--- /dev/null
+++ b/arch/ppc/platforms/pmac_backlight.c
@@ -0,0 +1,202 @@
+/*
+ * Miscellaneous procedures for dealing with the PowerMac hardware.
+ * Contains support for the backlight.
+ *
+ *   Copyright (C) 2000 Benjamin Herrenschmidt
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/reboot.h>
+#include <linux/nvram.h>
+#include <linux/console.h>
+#include <asm/sections.h>
+#include <asm/ptrace.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/nvram.h>
+#include <asm/backlight.h>
+
+#include <linux/adb.h>
+#include <linux/pmu.h>
+
+static struct backlight_controller *backlighter;
+static void* backlighter_data;
+static int backlight_autosave;
+static int backlight_level = BACKLIGHT_MAX;
+static int backlight_enabled = 1;
+static int backlight_req_level = -1;
+static int backlight_req_enable = -1;
+
+static void backlight_callback(void *);
+static DECLARE_WORK(backlight_work, backlight_callback, NULL);
+
+void __pmac register_backlight_controller(struct backlight_controller *ctrler,
+					  void *data, char *type)
+{
+	struct device_node* bk_node;
+	char *prop;
+	int valid = 0;
+
+	/* There's already a matching controller, bail out */
+	if (backlighter != NULL)
+		return;
+
+	bk_node = find_devices("backlight");
+
+#ifdef CONFIG_ADB_PMU
+	/* Special case for the old PowerBook since I can't test on it */
+	backlight_autosave = machine_is_compatible("AAPL,3400/2400")
+		|| machine_is_compatible("AAPL,3500");
+	if ((backlight_autosave
+	     || machine_is_compatible("AAPL,PowerBook1998")
+	     || machine_is_compatible("PowerBook1,1"))
+	    && !strcmp(type, "pmu"))
+		valid = 1;
+#endif
+	if (bk_node) {
+		prop = get_property(bk_node, "backlight-control", NULL);
+		if (prop && !strncmp(prop, type, strlen(type)))
+			valid = 1;
+	}
+	if (!valid)
+		return;
+	backlighter = ctrler;
+	backlighter_data = data;
+
+	if (bk_node && !backlight_autosave)
+		prop = get_property(bk_node, "bklt", NULL);
+	else
+		prop = NULL;
+	if (prop) {
+		backlight_level = ((*prop)+1) >> 1;
+		if (backlight_level > BACKLIGHT_MAX)
+			backlight_level = BACKLIGHT_MAX;
+	}
+
+#ifdef CONFIG_ADB_PMU
+	if (backlight_autosave) {
+		struct adb_request req;
+		pmu_request(&req, NULL, 2, 0xd9, 0);
+		while (!req.complete)
+			pmu_poll();
+		backlight_level = req.reply[0] >> 4;
+	}
+#endif
+	acquire_console_sem();
+	if (!backlighter->set_enable(1, backlight_level, data))
+		backlight_enabled = 1;
+	release_console_sem();
+
+	printk(KERN_INFO "Registered \"%s\" backlight controller,"
+	       "level: %d/15\n", type, backlight_level);
+}
+EXPORT_SYMBOL(register_backlight_controller);
+
+void __pmac unregister_backlight_controller(struct backlight_controller
+					    *ctrler, void *data)
+{
+	/* We keep the current backlight level (for now) */
+	if (ctrler == backlighter && data == backlighter_data)
+		backlighter = NULL;
+}
+EXPORT_SYMBOL(unregister_backlight_controller);
+
+static int __pmac __set_backlight_enable(int enable)
+{
+	int rc;
+
+	if (!backlighter)
+		return -ENODEV;
+	acquire_console_sem();
+	rc = backlighter->set_enable(enable, backlight_level,
+				     backlighter_data);
+	if (!rc)
+		backlight_enabled = enable;
+	release_console_sem();
+	return rc;
+}
+int __pmac set_backlight_enable(int enable)
+{
+	if (!backlighter)
+		return -ENODEV;
+	backlight_req_enable = enable;
+	schedule_work(&backlight_work);
+	return 0;
+}
+
+EXPORT_SYMBOL(set_backlight_enable);
+
+int __pmac get_backlight_enable(void)
+{
+	if (!backlighter)
+		return -ENODEV;
+	return backlight_enabled;
+}
+EXPORT_SYMBOL(get_backlight_enable);
+
+static int __pmac __set_backlight_level(int level)
+{
+	int rc = 0;
+
+	if (!backlighter)
+		return -ENODEV;
+	if (level < BACKLIGHT_MIN)
+		level = BACKLIGHT_OFF;
+	if (level > BACKLIGHT_MAX)
+		level = BACKLIGHT_MAX;
+	acquire_console_sem();
+	if (backlight_enabled)
+		rc = backlighter->set_level(level, backlighter_data);
+	if (!rc)
+		backlight_level = level;
+	release_console_sem();
+	if (!rc && !backlight_autosave) {
+		level <<=1;
+		if (level & 0x10)
+			level |= 0x01;
+		// -- todo: save to property "bklt"
+	}
+	return rc;
+}
+int __pmac set_backlight_level(int level)
+{
+	if (!backlighter)
+		return -ENODEV;
+	backlight_req_level = level;
+	schedule_work(&backlight_work);
+	return 0;
+}
+
+EXPORT_SYMBOL(set_backlight_level);
+
+int __pmac get_backlight_level(void)
+{
+	if (!backlighter)
+		return -ENODEV;
+	return backlight_level;
+}
+EXPORT_SYMBOL(get_backlight_level);
+
+static void backlight_callback(void *dummy)
+{
+	int level, enable;
+
+	do {
+		level = backlight_req_level;
+		enable = backlight_req_enable;
+		mb();
+
+		if (level >= 0)
+			__set_backlight_level(level);
+		if (enable >= 0)
+			__set_backlight_enable(enable);
+	} while(cmpxchg(&backlight_req_level, level, -1) != level ||
+		cmpxchg(&backlight_req_enable, enable, -1) != enable);
+}
diff --git a/arch/ppc/platforms/pmac_cache.S b/arch/ppc/platforms/pmac_cache.S
new file mode 100644
index 0000000..c00e035
--- /dev/null
+++ b/arch/ppc/platforms/pmac_cache.S
@@ -0,0 +1,325 @@
+/*
+ * This file contains low-level cache management functions
+ * used for sleep and CPU speed changes on Apple machines.
+ * (In fact the only thing that is Apple-specific is that we assume
+ * that we can read from ROM at physical address 0xfff00000.)
+ *
+ *    Copyright (C) 2004 Paul Mackerras (paulus@samba.org) and
+ *                       Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * 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 <asm/processor.h>
+#include <asm/ppc_asm.h>
+#include <asm/cputable.h>
+
+/*
+ * Flush and disable all data caches (dL1, L2, L3). This is used
+ * when going to sleep, when doing a PMU based cpufreq transition,
+ * or when "offlining" a CPU on SMP machines. This code is over
+ * paranoid, but I've had enough issues with various CPU revs and
+ * bugs that I decided it was worth beeing over cautious
+ */
+
+_GLOBAL(flush_disable_caches)
+BEGIN_FTR_SECTION
+	b	flush_disable_745x
+END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
+BEGIN_FTR_SECTION
+	b	flush_disable_75x
+END_FTR_SECTION_IFSET(CPU_FTR_L2CR)
+	b	__flush_disable_L1
+
+/* This is the code for G3 and 74[01]0 */
+flush_disable_75x:
+	mflr	r10
+
+	/* Turn off EE and DR in MSR */
+	mfmsr	r11
+	rlwinm	r0,r11,0,~MSR_EE
+	rlwinm	r0,r0,0,~MSR_DR
+	sync
+	mtmsr	r0
+	isync
+
+	/* Stop DST streams */
+BEGIN_FTR_SECTION
+	DSSALL
+	sync
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+
+	/* Stop DPM */
+	mfspr	r8,SPRN_HID0		/* Save SPRN_HID0 in r8 */
+	rlwinm	r4,r8,0,12,10		/* Turn off HID0[DPM] */
+	sync
+	mtspr	SPRN_HID0,r4		/* Disable DPM */
+	sync
+
+	/* disp-flush L1 */
+	li	r4,0x4000
+	mtctr	r4
+	lis	r4,0xfff0
+1:	lwzx	r0,r0,r4
+	addi	r4,r4,32
+	bdnz	1b
+	sync
+	isync
+
+	/* disable / invalidate / enable L1 data */
+	mfspr	r3,SPRN_HID0
+	rlwinm	r0,r0,0,~HID0_DCE
+	mtspr	SPRN_HID0,r3
+	sync
+	isync
+	ori	r3,r3,HID0_DCE|HID0_DCI
+	sync
+	isync
+	mtspr	SPRN_HID0,r3
+	xori	r3,r3,HID0_DCI
+	mtspr	SPRN_HID0,r3
+	sync
+
+	/* Get the current enable bit of the L2CR into r4 */
+	mfspr	r5,SPRN_L2CR
+	/* Set to data-only (pre-745x bit) */
+	oris	r3,r5,L2CR_L2DO@h
+	b	2f
+	/* When disabling L2, code must be in L1 */
+	.balign 32
+1:	mtspr	SPRN_L2CR,r3
+3:	sync
+	isync
+	b	1f
+2:	b	3f
+3:	sync
+	isync
+	b	1b
+1:	/* disp-flush L2. The interesting thing here is that the L2 can be
+	 * up to 2Mb ... so using the ROM, we'll end up wrapping back to memory
+	 * but that is probbaly fine. We disp-flush over 4Mb to be safe
+	 */
+	lis	r4,2
+	mtctr	r4
+	lis	r4,0xfff0
+1:	lwzx	r0,r0,r4
+	addi	r4,r4,32
+	bdnz	1b
+	sync
+	isync
+	/* now disable L2 */
+	rlwinm	r5,r5,0,~L2CR_L2E
+	b	2f
+	/* When disabling L2, code must be in L1 */
+	.balign 32
+1:	mtspr	SPRN_L2CR,r5
+3:	sync
+	isync
+	b	1f
+2:	b	3f
+3:	sync
+	isync
+	b	1b
+1:	sync
+	isync
+	/* Invalidate L2. This is pre-745x, we clear the L2I bit ourselves */
+	oris	r4,r5,L2CR_L2I@h
+	mtspr	SPRN_L2CR,r4
+	sync
+	isync
+	xoris	r4,r4,L2CR_L2I@h
+	sync
+	mtspr	SPRN_L2CR,r4
+	sync
+
+	/* now disable the L1 data cache */
+	mfspr	r0,SPRN_HID0
+	rlwinm	r0,r0,0,~HID0_DCE
+	mtspr	SPRN_HID0,r0
+	sync
+	isync
+
+	/* Restore HID0[DPM] to whatever it was before */
+	sync
+	mtspr	SPRN_HID0,r8
+	sync
+
+	/* restore DR and EE */
+	sync
+	mtmsr	r11
+	isync
+
+	mtlr	r10
+	blr
+
+/* This code is for 745x processors */
+flush_disable_745x:
+	/* Turn off EE and DR in MSR */
+	mfmsr	r11
+	rlwinm	r0,r11,0,~MSR_EE
+	rlwinm	r0,r0,0,~MSR_DR
+	sync
+	mtmsr	r0
+	isync
+
+	/* Stop prefetch streams */
+	DSSALL
+	sync
+
+	/* Disable L2 prefetching */
+	mfspr	r0,SPRN_MSSCR0
+	rlwinm	r0,r0,0,0,29
+	mtspr	SPRN_MSSCR0,r0
+	sync
+	isync
+	lis	r4,0
+	dcbf	0,r4
+	dcbf	0,r4
+	dcbf	0,r4
+	dcbf	0,r4
+	dcbf	0,r4
+	dcbf	0,r4
+	dcbf	0,r4
+	dcbf	0,r4
+
+	/* Due to a bug with the HW flush on some CPU revs, we occasionally
+	 * experience data corruption. I'm adding a displacement flush along
+	 * with a dcbf loop over a few Mb to "help". The problem isn't totally
+	 * fixed by this in theory, but at least, in practice, I couldn't reproduce
+	 * it even with a big hammer...
+	 */
+
+        lis     r4,0x0002
+        mtctr   r4
+ 	li      r4,0
+1:
+        lwzx    r0,r0,r4
+        addi    r4,r4,32                /* Go to start of next cache line */
+        bdnz    1b
+        isync
+
+        /* Now, flush the first 4MB of memory */
+        lis     r4,0x0002
+        mtctr   r4
+	li      r4,0
+        sync
+1:
+        dcbf    0,r4
+        addi    r4,r4,32                /* Go to start of next cache line */
+        bdnz    1b
+
+	/* Flush and disable the L1 data cache */
+	mfspr	r6,SPRN_LDSTCR
+	lis	r3,0xfff0	/* read from ROM for displacement flush */
+	li	r4,0xfe		/* start with only way 0 unlocked */
+	li	r5,128		/* 128 lines in each way */
+1:	mtctr	r5
+	rlwimi	r6,r4,0,24,31
+	mtspr	SPRN_LDSTCR,r6
+	sync
+	isync
+2:	lwz	r0,0(r3)	/* touch each cache line */
+	addi	r3,r3,32
+	bdnz	2b
+	rlwinm	r4,r4,1,24,30	/* move on to the next way */
+	ori	r4,r4,1
+	cmpwi	r4,0xff		/* all done? */
+	bne	1b
+	/* now unlock the L1 data cache */
+	li	r4,0
+	rlwimi	r6,r4,0,24,31
+	sync
+	mtspr	SPRN_LDSTCR,r6
+	sync
+	isync
+
+	/* Flush the L2 cache using the hardware assist */
+	mfspr	r3,SPRN_L2CR
+	cmpwi	r3,0		/* check if it is enabled first */
+	bge	4f
+	oris	r0,r3,(L2CR_L2IO_745x|L2CR_L2DO_745x)@h
+	b	2f
+	/* When disabling/locking L2, code must be in L1 */
+	.balign 32
+1:	mtspr	SPRN_L2CR,r0	/* lock the L2 cache */
+3:	sync
+	isync
+	b	1f
+2:	b	3f
+3:	sync
+	isync
+	b	1b
+1:	sync
+	isync
+	ori	r0,r3,L2CR_L2HWF_745x
+	sync
+	mtspr	SPRN_L2CR,r0	/* set the hardware flush bit */
+3:	mfspr	r0,SPRN_L2CR	/* wait for it to go to 0 */
+	andi.	r0,r0,L2CR_L2HWF_745x
+	bne	3b
+	sync
+	rlwinm	r3,r3,0,~L2CR_L2E
+	b	2f
+	/* When disabling L2, code must be in L1 */
+	.balign 32
+1:	mtspr	SPRN_L2CR,r3	/* disable the L2 cache */
+3:	sync
+	isync
+	b	1f
+2:	b	3f
+3:	sync
+	isync
+	b	1b
+1:	sync
+	isync
+	oris	r4,r3,L2CR_L2I@h
+	mtspr	SPRN_L2CR,r4
+	sync
+	isync
+1:	mfspr	r4,SPRN_L2CR
+	andis.	r0,r4,L2CR_L2I@h
+	bne	1b
+	sync
+
+BEGIN_FTR_SECTION
+	/* Flush the L3 cache using the hardware assist */
+4:	mfspr	r3,SPRN_L3CR
+	cmpwi	r3,0		/* check if it is enabled */
+	bge	6f
+	oris	r0,r3,L3CR_L3IO@h
+	ori	r0,r0,L3CR_L3DO
+	sync
+	mtspr	SPRN_L3CR,r0	/* lock the L3 cache */
+	sync
+	isync
+	ori	r0,r0,L3CR_L3HWF
+	sync
+	mtspr	SPRN_L3CR,r0	/* set the hardware flush bit */
+5:	mfspr	r0,SPRN_L3CR	/* wait for it to go to zero */
+	andi.	r0,r0,L3CR_L3HWF
+	bne	5b
+	rlwinm	r3,r3,0,~L3CR_L3E
+	sync
+	mtspr	SPRN_L3CR,r3	/* disable the L3 cache */
+	sync
+	ori	r4,r3,L3CR_L3I
+	mtspr	SPRN_L3CR,r4
+1:	mfspr	r4,SPRN_L3CR
+	andi.	r0,r4,L3CR_L3I
+	bne	1b
+	sync
+END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
+
+6:	mfspr	r0,SPRN_HID0	/* now disable the L1 data cache */
+	rlwinm	r0,r0,0,~HID0_DCE
+	mtspr	SPRN_HID0,r0
+	sync
+	isync
+	mtmsr	r11		/* restore DR and EE */
+	isync
+	blr
diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
new file mode 100644
index 0000000..9c85f9c
--- /dev/null
+++ b/arch/ppc/platforms/pmac_cpufreq.c
@@ -0,0 +1,571 @@
+/*
+ *  arch/ppc/platforms/pmac_cpufreq.c
+ *
+ *  Copyright (C) 2002 - 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *  Copyright (C) 2004        John Steele Scott <toojays@toojays.net>
+ *
+ * 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/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <linux/slab.h>
+#include <linux/cpufreq.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/i2c.h>
+#include <linux/hardirq.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/pmac_feature.h>
+#include <asm/mmu_context.h>
+#include <asm/sections.h>
+#include <asm/cputable.h>
+#include <asm/time.h>
+#include <asm/system.h>
+#include <asm/open_pic.h>
+
+/* WARNING !!! This will cause calibrate_delay() to be called,
+ * but this is an __init function ! So you MUST go edit
+ * init/main.c to make it non-init before enabling DEBUG_FREQ
+ */
+#undef DEBUG_FREQ
+
+/*
+ * There is a problem with the core cpufreq code on SMP kernels,
+ * it won't recalculate the Bogomips properly
+ */
+#ifdef CONFIG_SMP
+#warning "WARNING, CPUFREQ not recommended on SMP kernels"
+#endif
+
+extern void low_choose_7447a_dfs(int dfs);
+extern void low_choose_750fx_pll(int pll);
+extern void low_sleep_handler(void);
+
+/*
+ * Currently, PowerMac cpufreq supports only high & low frequencies
+ * that are set by the firmware
+ */
+static unsigned int low_freq;
+static unsigned int hi_freq;
+static unsigned int cur_freq;
+
+/*
+ * Different models uses different mecanisms to switch the frequency
+ */
+static int (*set_speed_proc)(int low_speed);
+
+/*
+ * Some definitions used by the various speedprocs
+ */
+static u32 voltage_gpio;
+static u32 frequency_gpio;
+static u32 slew_done_gpio;
+
+
+#define PMAC_CPU_LOW_SPEED	1
+#define PMAC_CPU_HIGH_SPEED	0
+
+/* There are only two frequency states for each processor. Values
+ * are in kHz for the time being.
+ */
+#define CPUFREQ_HIGH                  PMAC_CPU_HIGH_SPEED
+#define CPUFREQ_LOW                   PMAC_CPU_LOW_SPEED
+
+static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
+	{CPUFREQ_HIGH, 		0},
+	{CPUFREQ_LOW,		0},
+	{0,			CPUFREQ_TABLE_END},
+};
+
+static inline void wakeup_decrementer(void)
+{
+	set_dec(tb_ticks_per_jiffy);
+	/* No currently-supported powerbook has a 601,
+	 * so use get_tbl, not native
+	 */
+	last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
+}
+
+#ifdef DEBUG_FREQ
+static inline void debug_calc_bogomips(void)
+{
+	/* This will cause a recalc of bogomips and display the
+	 * result. We backup/restore the value to avoid affecting the
+	 * core cpufreq framework's own calculation.
+	 */
+	extern void calibrate_delay(void);
+
+	unsigned long save_lpj = loops_per_jiffy;
+	calibrate_delay();
+	loops_per_jiffy = save_lpj;
+}
+#endif /* DEBUG_FREQ */
+
+/* Switch CPU speed under 750FX CPU control
+ */
+static int __pmac cpu_750fx_cpu_speed(int low_speed)
+{
+#ifdef DEBUG_FREQ
+	printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
+#endif
+#ifdef CONFIG_6xx
+	low_choose_750fx_pll(low_speed);
+#endif
+#ifdef DEBUG_FREQ
+	printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
+	debug_calc_bogomips();
+#endif
+
+	return 0;
+}
+
+/* Switch CPU speed using DFS */
+static int __pmac dfs_set_cpu_speed(int low_speed)
+{
+	if (low_speed == 0) {
+		/* ramping up, set voltage first */
+		pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
+		/* Make sure we sleep for at least 1ms */
+		msleep(1);
+	}
+
+	/* set frequency */
+	low_choose_7447a_dfs(low_speed);
+
+	if (low_speed == 1) {
+		/* ramping down, set voltage last */
+		pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
+		msleep(1);
+	}
+
+	return 0;
+}
+
+static unsigned int __pmac dfs_get_cpu_speed(unsigned int cpu)
+{
+	if (mfspr(SPRN_HID1) & HID1_DFS)
+		return low_freq;
+	else
+		return hi_freq;
+}
+
+
+/* Switch CPU speed using slewing GPIOs
+ */
+static int __pmac gpios_set_cpu_speed(int low_speed)
+{
+	int gpio;
+
+	/* If ramping up, set voltage first */
+	if (low_speed == 0) {
+		pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
+		/* Delay is way too big but it's ok, we schedule */
+		msleep(10);
+	}
+
+	/* Set frequency */
+	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio,
+			  low_speed ? 0x04 : 0x05);
+	udelay(200);
+	do {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+		gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0);
+	} while((gpio & 0x02) == 0);
+
+	/* If ramping down, set voltage last */
+	if (low_speed == 1) {
+		pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
+		/* Delay is way too big but it's ok, we schedule */
+		msleep(10);
+	}
+
+#ifdef DEBUG_FREQ
+	debug_calc_bogomips();
+#endif
+
+	return 0;
+}
+
+/* Switch CPU speed under PMU control
+ */
+static int __pmac pmu_set_cpu_speed(int low_speed)
+{
+	struct adb_request req;
+	unsigned long save_l2cr;
+	unsigned long save_l3cr;
+
+	preempt_disable();
+
+#ifdef DEBUG_FREQ
+	printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
+#endif
+	/* Disable all interrupt sources on openpic */
+ 	openpic_set_priority(0xf);
+
+	/* Make sure the decrementer won't interrupt us */
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+	/* Make sure any pending DEC interrupt occuring while we did
+	 * the above didn't re-enable the DEC */
+	mb();
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+
+	/* We can now disable MSR_EE */
+	local_irq_disable();
+
+	/* Giveup the FPU & vec */
+	enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+	if (cpu_has_feature(CPU_FTR_ALTIVEC))
+		enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+	/* Save & disable L2 and L3 caches */
+	save_l3cr = _get_L3CR();	/* (returns -1 if not available) */
+	save_l2cr = _get_L2CR();	/* (returns -1 if not available) */
+
+	/* Send the new speed command. My assumption is that this command
+	 * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep
+	 */
+	pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed);
+	while (!req.complete)
+		pmu_poll();
+
+	/* Prepare the northbridge for the speed transition */
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1);
+
+	/* Call low level code to backup CPU state and recover from
+	 * hardware reset
+	 */
+	low_sleep_handler();
+
+	/* Restore the northbridge */
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0);
+
+	/* Restore L2 cache */
+	if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
+ 		_set_L2CR(save_l2cr);
+	/* Restore L3 cache */
+	if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)
+ 		_set_L3CR(save_l3cr);
+
+	/* Restore userland MMU context */
+	set_context(current->active_mm->context, current->active_mm->pgd);
+
+#ifdef DEBUG_FREQ
+	printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
+#endif
+
+	/* Restore low level PMU operations */
+	pmu_unlock();
+
+	/* Restore decrementer */
+	wakeup_decrementer();
+
+	/* Restore interrupts */
+ 	openpic_set_priority(0);
+
+	/* Let interrupts flow again ... */
+	local_irq_enable();
+
+#ifdef DEBUG_FREQ
+	debug_calc_bogomips();
+#endif
+
+	preempt_enable();
+
+	return 0;
+}
+
+static int __pmac do_set_cpu_speed(int speed_mode)
+{
+	struct cpufreq_freqs freqs;
+
+	freqs.old = cur_freq;
+	freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
+	freqs.cpu = smp_processor_id();
+
+	if (freqs.old == freqs.new)
+		return 0;
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	set_speed_proc(speed_mode == PMAC_CPU_LOW_SPEED);
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
+
+	return 0;
+}
+
+static int __pmac pmac_cpufreq_verify(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs);
+}
+
+static int __pmac pmac_cpufreq_target(	struct cpufreq_policy *policy,
+					unsigned int target_freq,
+					unsigned int relation)
+{
+	unsigned int    newstate = 0;
+
+	if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs,
+			target_freq, relation, &newstate))
+		return -EINVAL;
+
+	return do_set_cpu_speed(newstate);
+}
+
+unsigned int __pmac pmac_get_one_cpufreq(int i)
+{
+	/* Supports only one CPU for now */
+	return (i == 0) ? cur_freq : 0;
+}
+
+static int __pmac pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	if (policy->cpu != 0)
+		return -ENODEV;
+
+	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+	policy->cpuinfo.transition_latency	= CPUFREQ_ETERNAL;
+	policy->cur = cur_freq;
+
+	return cpufreq_frequency_table_cpuinfo(policy, &pmac_cpu_freqs[0]);
+}
+
+static u32 __pmac read_gpio(struct device_node *np)
+{
+	u32 *reg = (u32 *)get_property(np, "reg", NULL);
+
+	if (reg == NULL)
+		return 0;
+	/* That works for all keylargos but shall be fixed properly
+	 * some day...
+	 */
+	return 0x50 + (*reg);
+}
+
+static struct cpufreq_driver pmac_cpufreq_driver = {
+	.verify 	= pmac_cpufreq_verify,
+	.target 	= pmac_cpufreq_target,
+	.init		= pmac_cpufreq_cpu_init,
+	.name		= "powermac",
+	.owner		= THIS_MODULE,
+};
+
+
+static int __pmac pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
+{
+	struct device_node *volt_gpio_np = of_find_node_by_name(NULL,
+								"voltage-gpio");
+	struct device_node *freq_gpio_np = of_find_node_by_name(NULL,
+								"frequency-gpio");
+	struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL,
+								     "slewing-done");
+	u32 *value;
+
+	/*
+	 * Check to see if it's GPIO driven or PMU only
+	 *
+	 * The way we extract the GPIO address is slightly hackish, but it
+	 * works well enough for now. We need to abstract the whole GPIO
+	 * stuff sooner or later anyway
+	 */
+
+	if (volt_gpio_np)
+		voltage_gpio = read_gpio(volt_gpio_np);
+	if (freq_gpio_np)
+		frequency_gpio = read_gpio(freq_gpio_np);
+	if (slew_done_gpio_np)
+		slew_done_gpio = read_gpio(slew_done_gpio_np);
+
+	/* If we use the frequency GPIOs, calculate the min/max speeds based
+	 * on the bus frequencies
+	 */
+	if (frequency_gpio && slew_done_gpio) {
+		int lenp, rc;
+		u32 *freqs, *ratio;
+
+		freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp);
+		lenp /= sizeof(u32);
+		if (freqs == NULL || lenp != 2) {
+			printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n");
+			return 1;
+		}
+		ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL);
+		if (ratio == NULL) {
+			printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n");
+			return 1;
+		}
+
+		/* Get the min/max bus frequencies */
+		low_freq = min(freqs[0], freqs[1]);
+		hi_freq = max(freqs[0], freqs[1]);
+
+		/* Grrrr.. It _seems_ that the device-tree is lying on the low bus
+		 * frequency, it claims it to be around 84Mhz on some models while
+		 * it appears to be approx. 101Mhz on all. Let's hack around here...
+		 * fortunately, we don't need to be too precise
+		 */
+		if (low_freq < 98000000)
+			low_freq = 101000000;
+			
+		/* Convert those to CPU core clocks */
+		low_freq = (low_freq * (*ratio)) / 2000;
+		hi_freq = (hi_freq * (*ratio)) / 2000;
+
+		/* Now we get the frequencies, we read the GPIO to see what is out current
+		 * speed
+		 */
+		rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0);
+		cur_freq = (rc & 0x01) ? hi_freq : low_freq;
+
+		set_speed_proc = gpios_set_cpu_speed;
+		return 1;
+	}
+
+	/* If we use the PMU, look for the min & max frequencies in the
+	 * device-tree
+	 */
+	value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL);
+	if (!value)
+		return 1;
+	low_freq = (*value) / 1000;
+	/* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree
+	 * here */
+	if (low_freq < 100000)
+		low_freq *= 10;
+
+	value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL);
+	if (!value)
+		return 1;
+	hi_freq = (*value) / 1000;
+	set_speed_proc = pmu_set_cpu_speed;
+
+	return 0;
+}
+
+static int __pmac pmac_cpufreq_init_7447A(struct device_node *cpunode)
+{
+	struct device_node *volt_gpio_np;
+	u32 *reg;
+	struct cpufreq_driver *driver = &pmac_cpufreq_driver;
+
+	/* Look for voltage GPIO */
+	volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");
+	reg = (u32 *)get_property(volt_gpio_np, "reg", NULL);
+	voltage_gpio = *reg;
+	if (!volt_gpio_np){
+		printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n");
+		return 1;
+	}
+
+	/* OF only reports the high frequency */
+	hi_freq = cur_freq;
+	low_freq = cur_freq/2;
+
+	/* Read actual frequency from CPU */
+	driver->get = dfs_get_cpu_speed;
+	cur_freq = driver->get(0);
+	set_speed_proc = dfs_set_cpu_speed;
+
+	return 0;
+}
+
+/* Currently, we support the following machines:
+ *
+ *  - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz)
+ *  - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz)
+ *  - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz)
+ *  - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz)
+ *  - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz)
+ *  - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage)
+ *  - Recent MacRISC3 laptops
+ *  - All new machines with 7447A CPUs
+ */
+static int __init pmac_cpufreq_setup(void)
+{
+	struct device_node	*cpunode;
+	u32			*value;
+
+	if (strstr(cmd_line, "nocpufreq"))
+		return 0;
+
+	/* Assume only one CPU */
+	cpunode = find_type_devices("cpu");
+	if (!cpunode)
+		goto out;
+
+	/* Get current cpu clock freq */
+	value = (u32 *)get_property(cpunode, "clock-frequency", NULL);
+	if (!value)
+		goto out;
+	cur_freq = (*value) / 1000;
+
+	/*  Check for 7447A based MacRISC3 */
+	if (machine_is_compatible("MacRISC3") &&
+	    get_property(cpunode, "dynamic-power-step", NULL) &&
+	    PVR_VER(mfspr(SPRN_PVR)) == 0x8003) {
+		pmac_cpufreq_init_7447A(cpunode);
+	/* Check for other MacRISC3 machines */
+	} else if (machine_is_compatible("PowerBook3,4") ||
+		   machine_is_compatible("PowerBook3,5") ||
+		   machine_is_compatible("MacRISC3")) {
+		pmac_cpufreq_init_MacRISC3(cpunode);
+	/* Else check for iBook2 500/600 */
+	} else if (machine_is_compatible("PowerBook4,1")) {
+		hi_freq = cur_freq;
+		low_freq = 400000;
+		set_speed_proc = pmu_set_cpu_speed;
+	}
+	/* Else check for TiPb 400 & 500 */
+	else if (machine_is_compatible("PowerBook3,2")) {
+		/* We only know about the 400 MHz and the 500Mhz model
+		 * they both have 300 MHz as low frequency
+		 */
+		if (cur_freq < 350000 || cur_freq > 550000)
+			goto out;
+		hi_freq = cur_freq;
+		low_freq = 300000;
+		set_speed_proc = pmu_set_cpu_speed;
+	}
+	/* Else check for 750FX */
+	else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) {
+		if (get_property(cpunode, "dynamic-power-step", NULL) == NULL)
+			goto out;
+		hi_freq = cur_freq;
+		value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL);
+		if (!value)
+			goto out;
+		low_freq = (*value) / 1000;		
+		set_speed_proc = cpu_750fx_cpu_speed;
+	}
+out:
+	if (set_speed_proc == NULL)
+		return -ENODEV;
+
+	pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq;
+	pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq;
+
+	printk(KERN_INFO "Registering PowerMac CPU frequency driver\n");
+	printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n",
+	       low_freq/1000, hi_freq/1000, cur_freq/1000);
+
+	return cpufreq_register_driver(&pmac_cpufreq_driver);
+}
+
+module_init(pmac_cpufreq_setup);
+
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c
new file mode 100644
index 0000000..8e60550
--- /dev/null
+++ b/arch/ppc/platforms/pmac_feature.c
@@ -0,0 +1,2972 @@
+/*
+ *  arch/ppc/platforms/pmac_feature.c
+ *
+ *  Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au)
+ *                          Ben. Herrenschmidt (benh@kernel.crashing.org)
+ *
+ *  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.
+ *
+ *  TODO:
+ *
+ *   - Replace mdelay with some schedule loop if possible
+ *   - Shorten some obfuscated delays on some routines (like modem
+ *     power)
+ *   - Refcount some clocks (see darwin)
+ *   - Split split split...
+ *
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/sections.h>
+#include <asm/errno.h>
+#include <asm/ohare.h>
+#include <asm/heathrow.h>
+#include <asm/keylargo.h>
+#include <asm/uninorth.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/dbdma.h>
+#include <asm/pci-bridge.h>
+#include <asm/pmac_low_i2c.h>
+
+#undef DEBUG_FEATURE
+
+#ifdef DEBUG_FEATURE
+#define DBG(fmt,...) printk(KERN_DEBUG fmt)
+#else
+#define DBG(fmt,...)
+#endif
+
+#ifdef CONFIG_6xx
+extern int powersave_lowspeed;
+#endif
+
+extern int powersave_nap;
+extern struct device_node *k2_skiplist[2];
+
+
+/*
+ * We use a single global lock to protect accesses. Each driver has
+ * to take care of its own locking
+ */
+static DEFINE_SPINLOCK(feature_lock  __pmacdata);
+
+#define LOCK(flags)	spin_lock_irqsave(&feature_lock, flags);
+#define UNLOCK(flags)	spin_unlock_irqrestore(&feature_lock, flags);
+
+
+/*
+ * Instance of some macio stuffs
+ */
+struct macio_chip macio_chips[MAX_MACIO_CHIPS]  __pmacdata;
+
+struct macio_chip* __pmac
+macio_find(struct device_node* child, int type)
+{
+	while(child) {
+		int	i;
+
+		for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++)
+			if (child == macio_chips[i].of_node &&
+			    (!type || macio_chips[i].type == type))
+				return &macio_chips[i];
+		child = child->parent;
+	}
+	return NULL;
+}
+
+static const char* macio_names[] __pmacdata =
+{
+	"Unknown",
+	"Grand Central",
+	"OHare",
+	"OHareII",
+	"Heathrow",
+	"Gatwick",
+	"Paddington",
+	"Keylargo",
+	"Pangea",
+	"Intrepid",
+	"K2"
+};
+
+
+
+/*
+ * Uninorth reg. access. Note that Uni-N regs are big endian
+ */
+
+#define UN_REG(r)	(uninorth_base + ((r) >> 2))
+#define UN_IN(r)	(in_be32(UN_REG(r)))
+#define UN_OUT(r,v)	(out_be32(UN_REG(r), (v)))
+#define UN_BIS(r,v)	(UN_OUT((r), UN_IN(r) | (v)))
+#define UN_BIC(r,v)	(UN_OUT((r), UN_IN(r) & ~(v)))
+
+static struct device_node* uninorth_node __pmacdata;
+static u32 __iomem * uninorth_base __pmacdata;
+static u32 uninorth_rev __pmacdata;
+static int uninorth_u3 __pmacdata;
+static void __iomem *u3_ht;
+
+/*
+ * For each motherboard family, we have a table of functions pointers
+ * that handle the various features.
+ */
+
+typedef long (*feature_call)(struct device_node* node, long param, long value);
+
+struct feature_table_entry {
+	unsigned int	selector;
+	feature_call	function;
+};
+
+struct pmac_mb_def
+{
+	const char*			model_string;
+	const char*			model_name;
+	int				model_id;
+	struct feature_table_entry* 	features;
+	unsigned long			board_flags;
+};
+static struct pmac_mb_def pmac_mb __pmacdata;
+
+/*
+ * Here are the chip specific feature functions
+ */
+
+static inline int __pmac
+simple_feature_tweak(struct device_node* node, int type, int reg, u32 mask, int value)
+{
+	struct macio_chip*	macio;
+	unsigned long		flags;
+
+	macio = macio_find(node, type);
+	if (!macio)
+		return -ENODEV;
+	LOCK(flags);
+	if (value)
+		MACIO_BIS(reg, mask);
+	else
+		MACIO_BIC(reg, mask);
+	(void)MACIO_IN32(reg);
+	UNLOCK(flags);
+
+	return 0;
+}
+
+#ifndef CONFIG_POWER4
+
+static long __pmac
+ohare_htw_scc_enable(struct device_node* node, long param, long value)
+{
+	struct macio_chip*	macio;
+	unsigned long		chan_mask;
+	unsigned long		fcr;
+	unsigned long		flags;
+	int			htw, trans;
+	unsigned long		rmask;
+
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+	if (!strcmp(node->name, "ch-a"))
+		chan_mask = MACIO_FLAG_SCCA_ON;
+	else if (!strcmp(node->name, "ch-b"))
+		chan_mask = MACIO_FLAG_SCCB_ON;
+	else
+		return -ENODEV;
+
+	htw = (macio->type == macio_heathrow || macio->type == macio_paddington
+		|| macio->type == macio_gatwick);
+	/* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */
+	trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
+	    	 pmac_mb.model_id != PMAC_TYPE_YIKES);
+	if (value) {
+#ifdef CONFIG_ADB_PMU
+		if ((param & 0xfff) == PMAC_SCC_IRDA)
+			pmu_enable_irled(1);
+#endif /* CONFIG_ADB_PMU */
+		LOCK(flags);
+		fcr = MACIO_IN32(OHARE_FCR);
+		/* Check if scc cell need enabling */
+		if (!(fcr & OH_SCC_ENABLE)) {
+			fcr |= OH_SCC_ENABLE;
+			if (htw) {
+				/* Side effect: this will also power up the
+				 * modem, but it's too messy to figure out on which
+				 * ports this controls the tranceiver and on which
+				 * it controls the modem
+				 */
+				if (trans)
+					fcr &= ~HRW_SCC_TRANS_EN_N;
+				MACIO_OUT32(OHARE_FCR, fcr);
+				fcr |= (rmask = HRW_RESET_SCC);
+				MACIO_OUT32(OHARE_FCR, fcr);
+			} else {
+				fcr |= (rmask = OH_SCC_RESET);
+				MACIO_OUT32(OHARE_FCR, fcr);
+			}
+			UNLOCK(flags);
+			(void)MACIO_IN32(OHARE_FCR);
+			mdelay(15);
+			LOCK(flags);
+			fcr &= ~rmask;
+			MACIO_OUT32(OHARE_FCR, fcr);
+		}
+		if (chan_mask & MACIO_FLAG_SCCA_ON)
+			fcr |= OH_SCCA_IO;
+		if (chan_mask & MACIO_FLAG_SCCB_ON)
+			fcr |= OH_SCCB_IO;
+		MACIO_OUT32(OHARE_FCR, fcr);
+		macio->flags |= chan_mask;
+		UNLOCK(flags);
+		if (param & PMAC_SCC_FLAG_XMON)
+			macio->flags |= MACIO_FLAG_SCC_LOCKED;
+	} else {
+		if (macio->flags & MACIO_FLAG_SCC_LOCKED)
+			return -EPERM;
+		LOCK(flags);
+		fcr = MACIO_IN32(OHARE_FCR);
+		if (chan_mask & MACIO_FLAG_SCCA_ON)
+			fcr &= ~OH_SCCA_IO;
+		if (chan_mask & MACIO_FLAG_SCCB_ON)
+			fcr &= ~OH_SCCB_IO;
+		MACIO_OUT32(OHARE_FCR, fcr);
+		if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) {
+			fcr &= ~OH_SCC_ENABLE;
+			if (htw && trans)
+				fcr |= HRW_SCC_TRANS_EN_N;
+			MACIO_OUT32(OHARE_FCR, fcr);
+		}
+		macio->flags &= ~(chan_mask);
+		UNLOCK(flags);
+		mdelay(10);
+#ifdef CONFIG_ADB_PMU
+		if ((param & 0xfff) == PMAC_SCC_IRDA)
+			pmu_enable_irled(0);
+#endif /* CONFIG_ADB_PMU */
+	}
+	return 0;
+}
+
+static long __pmac
+ohare_floppy_enable(struct device_node* node, long param, long value)
+{
+	return simple_feature_tweak(node, macio_ohare,
+		OHARE_FCR, OH_FLOPPY_ENABLE, value);
+}
+
+static long __pmac
+ohare_mesh_enable(struct device_node* node, long param, long value)
+{
+	return simple_feature_tweak(node, macio_ohare,
+		OHARE_FCR, OH_MESH_ENABLE, value);
+}
+
+static long __pmac
+ohare_ide_enable(struct device_node* node, long param, long value)
+{
+	switch(param) {
+	    case 0:
+	    	/* For some reason, setting the bit in set_initial_features()
+	    	 * doesn't stick. I'm still investigating... --BenH.
+	    	 */
+	    	if (value)
+	    		simple_feature_tweak(node, macio_ohare,
+				OHARE_FCR, OH_IOBUS_ENABLE, 1);
+		return simple_feature_tweak(node, macio_ohare,
+			OHARE_FCR, OH_IDE0_ENABLE, value);
+	    case 1:
+		return simple_feature_tweak(node, macio_ohare,
+			OHARE_FCR, OH_BAY_IDE_ENABLE, value);
+	    default:
+	    	return -ENODEV;
+	}
+}
+
+static long __pmac
+ohare_ide_reset(struct device_node* node, long param, long value)
+{
+	switch(param) {
+	    case 0:
+		return simple_feature_tweak(node, macio_ohare,
+			OHARE_FCR, OH_IDE0_RESET_N, !value);
+	    case 1:
+		return simple_feature_tweak(node, macio_ohare,
+			OHARE_FCR, OH_IDE1_RESET_N, !value);
+	    default:
+	    	return -ENODEV;
+	}
+}
+
+static long __pmac
+ohare_sleep_state(struct device_node* node, long param, long value)
+{
+	struct macio_chip*	macio = &macio_chips[0];
+
+	if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
+		return -EPERM;
+	if (value == 1) {
+		MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE);
+	} else if (value == 0) {
+		MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+	}
+
+	return 0;
+}
+
+static long __pmac
+heathrow_modem_enable(struct device_node* node, long param, long value)
+{
+	struct macio_chip*	macio;
+	u8			gpio;
+	unsigned long		flags;
+
+	macio = macio_find(node, macio_unknown);
+	if (!macio)
+		return -ENODEV;
+	gpio = MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1;
+	if (!value) {
+		LOCK(flags);
+		MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
+		UNLOCK(flags);
+		(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
+		mdelay(250);
+	}
+	if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
+	    pmac_mb.model_id != PMAC_TYPE_YIKES) {
+	    	LOCK(flags);
+	    	if (value)
+	    		MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
+	    	else
+	    		MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
+	    	UNLOCK(flags);
+	    	(void)MACIO_IN32(HEATHROW_FCR);
+		mdelay(250);
+	}
+	if (value) {
+		LOCK(flags);
+		MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
+		(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250); LOCK(flags);
+		MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
+		(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250); LOCK(flags);
+		MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
+		(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250);
+	}
+	return 0;
+}
+
+static long __pmac
+heathrow_floppy_enable(struct device_node* node, long param, long value)
+{
+	return simple_feature_tweak(node, macio_unknown,
+		HEATHROW_FCR,
+		HRW_SWIM_ENABLE|HRW_BAY_FLOPPY_ENABLE,
+		value);
+}
+
+static long __pmac
+heathrow_mesh_enable(struct device_node* node, long param, long value)
+{
+	struct macio_chip*	macio;
+	unsigned long		flags;
+
+	macio = macio_find(node, macio_unknown);
+	if (!macio)
+		return -ENODEV;
+	LOCK(flags);
+	/* Set clear mesh cell enable */
+	if (value)
+		MACIO_BIS(HEATHROW_FCR, HRW_MESH_ENABLE);
+	else
+		MACIO_BIC(HEATHROW_FCR, HRW_MESH_ENABLE);
+	(void)MACIO_IN32(HEATHROW_FCR);
+	udelay(10);
+	/* Set/Clear termination power */
+	if (value)
+		MACIO_BIC(HEATHROW_MBCR, 0x04000000);
+	else
+		MACIO_BIS(HEATHROW_MBCR, 0x04000000);
+	(void)MACIO_IN32(HEATHROW_MBCR);
+	udelay(10);
+	UNLOCK(flags);
+
+	return 0;
+}
+
+static long __pmac
+heathrow_ide_enable(struct device_node* node, long param, long value)
+{
+	switch(param) {
+	    case 0:
+		return simple_feature_tweak(node, macio_unknown,
+			HEATHROW_FCR, HRW_IDE0_ENABLE, value);
+	    case 1:
+		return simple_feature_tweak(node, macio_unknown,
+			HEATHROW_FCR, HRW_BAY_IDE_ENABLE, value);
+	    default:
+	    	return -ENODEV;
+	}
+}
+
+static long __pmac
+heathrow_ide_reset(struct device_node* node, long param, long value)
+{
+	switch(param) {
+	    case 0:
+		return simple_feature_tweak(node, macio_unknown,
+			HEATHROW_FCR, HRW_IDE0_RESET_N, !value);
+	    case 1:
+		return simple_feature_tweak(node, macio_unknown,
+			HEATHROW_FCR, HRW_IDE1_RESET_N, !value);
+	    default:
+	    	return -ENODEV;
+	}
+}
+
+static long __pmac
+heathrow_bmac_enable(struct device_node* node, long param, long value)
+{
+	struct macio_chip*	macio;
+	unsigned long		flags;
+
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+	if (value) {
+		LOCK(flags);
+		MACIO_BIS(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);
+		MACIO_BIS(HEATHROW_FCR, HRW_BMAC_RESET);
+		UNLOCK(flags);
+		(void)MACIO_IN32(HEATHROW_FCR);
+		mdelay(10);
+		LOCK(flags);
+		MACIO_BIC(HEATHROW_FCR, HRW_BMAC_RESET);
+		UNLOCK(flags);
+		(void)MACIO_IN32(HEATHROW_FCR);
+		mdelay(10);
+	} else {
+		LOCK(flags);
+		MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);
+		UNLOCK(flags);
+	}
+	return 0;
+}
+
+static long __pmac
+heathrow_sound_enable(struct device_node* node, long param, long value)
+{
+	struct macio_chip*	macio;
+	unsigned long		flags;
+
+	/* B&W G3 and Yikes don't support that properly (the
+	 * sound appear to never come back after beeing shut down).
+	 */
+	if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE ||
+	    pmac_mb.model_id == PMAC_TYPE_YIKES)
+		return 0;
+
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+	if (value) {
+		LOCK(flags);
+		MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
+		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
+		UNLOCK(flags);
+		(void)MACIO_IN32(HEATHROW_FCR);
+	} else {
+		LOCK(flags);
+		MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
+		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
+		UNLOCK(flags);
+	}
+	return 0;
+}
+
+static u32 save_fcr[6] __pmacdata;
+static u32 save_mbcr __pmacdata;
+static u32 save_gpio_levels[2] __pmacdata;
+static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT] __pmacdata;
+static u8 save_gpio_normal[KEYLARGO_GPIO_CNT] __pmacdata;
+static u32 save_unin_clock_ctl __pmacdata;
+static struct dbdma_regs save_dbdma[13] __pmacdata;
+static struct dbdma_regs save_alt_dbdma[13] __pmacdata;
+
+static void __pmac
+dbdma_save(struct macio_chip* macio, struct dbdma_regs* save)
+{
+	int i;
+
+	/* Save state & config of DBDMA channels */
+	for (i=0; i<13; i++) {
+		volatile struct dbdma_regs __iomem * chan = (void __iomem *)
+			(macio->base + ((0x8000+i*0x100)>>2));
+		save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi);
+		save[i].cmdptr = in_le32(&chan->cmdptr);
+		save[i].intr_sel = in_le32(&chan->intr_sel);
+		save[i].br_sel = in_le32(&chan->br_sel);
+		save[i].wait_sel = in_le32(&chan->wait_sel);
+	}
+}
+
+static void __pmac
+dbdma_restore(struct macio_chip* macio, struct dbdma_regs* save)
+{
+	int i;
+
+	/* Save state & config of DBDMA channels */
+	for (i=0; i<13; i++) {
+		volatile struct dbdma_regs __iomem * chan = (void __iomem *)
+			(macio->base + ((0x8000+i*0x100)>>2));
+		out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);
+		while (in_le32(&chan->status) & ACTIVE)
+			mb();
+		out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi);
+		out_le32(&chan->cmdptr, save[i].cmdptr);
+		out_le32(&chan->intr_sel, save[i].intr_sel);
+		out_le32(&chan->br_sel, save[i].br_sel);
+		out_le32(&chan->wait_sel, save[i].wait_sel);
+	}
+}
+
+static void __pmac
+heathrow_sleep(struct macio_chip* macio, int secondary)
+{
+	if (secondary) {
+		dbdma_save(macio, save_alt_dbdma);
+		save_fcr[2] = MACIO_IN32(0x38);
+		save_fcr[3] = MACIO_IN32(0x3c);
+	} else {
+		dbdma_save(macio, save_dbdma);
+		save_fcr[0] = MACIO_IN32(0x38);
+		save_fcr[1] = MACIO_IN32(0x3c);
+		save_mbcr = MACIO_IN32(0x34);
+		/* Make sure sound is shut down */
+		MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
+		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
+		/* This seems to be necessary as well or the fan
+		 * keeps coming up and battery drains fast */
+		MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE);
+		MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N);
+		/* Make sure eth is down even if module or sleep
+		 * won't work properly */
+		MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET);
+	}
+	/* Make sure modem is shut down */
+	MACIO_OUT8(HRW_GPIO_MODEM_RESET,
+		MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1);
+	MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
+	MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE);
+
+	/* Let things settle */
+	(void)MACIO_IN32(HEATHROW_FCR);
+}
+
+static void __pmac
+heathrow_wakeup(struct macio_chip* macio, int secondary)
+{
+	if (secondary) {
+		MACIO_OUT32(0x38, save_fcr[2]);
+		(void)MACIO_IN32(0x38);
+		mdelay(1);
+		MACIO_OUT32(0x3c, save_fcr[3]);
+		(void)MACIO_IN32(0x38);
+		mdelay(10);
+		dbdma_restore(macio, save_alt_dbdma);
+	} else {
+		MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE);
+		(void)MACIO_IN32(0x38);
+		mdelay(1);
+		MACIO_OUT32(0x3c, save_fcr[1]);
+		(void)MACIO_IN32(0x38);
+		mdelay(1);
+		MACIO_OUT32(0x34, save_mbcr);
+		(void)MACIO_IN32(0x38);
+		mdelay(10);
+		dbdma_restore(macio, save_dbdma);
+	}
+}
+
+static long __pmac
+heathrow_sleep_state(struct device_node* node, long param, long value)
+{
+	if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
+		return -EPERM;
+	if (value == 1) {
+		if (macio_chips[1].type == macio_gatwick)
+			heathrow_sleep(&macio_chips[0], 1);
+		heathrow_sleep(&macio_chips[0], 0);
+	} else if (value == 0) {
+		heathrow_wakeup(&macio_chips[0], 0);
+		if (macio_chips[1].type == macio_gatwick)
+			heathrow_wakeup(&macio_chips[0], 1);
+	}
+	return 0;
+}
+
+static long __pmac
+core99_scc_enable(struct device_node* node, long param, long value)
+{
+	struct macio_chip*	macio;
+	unsigned long		flags;
+	unsigned long		chan_mask;
+	u32			fcr;
+
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+	if (!strcmp(node->name, "ch-a"))
+		chan_mask = MACIO_FLAG_SCCA_ON;
+	else if (!strcmp(node->name, "ch-b"))
+		chan_mask = MACIO_FLAG_SCCB_ON;
+	else
+		return -ENODEV;
+
+	if (value) {
+		int need_reset_scc = 0;
+		int need_reset_irda = 0;
+
+		LOCK(flags);
+		fcr = MACIO_IN32(KEYLARGO_FCR0);
+		/* Check if scc cell need enabling */
+		if (!(fcr & KL0_SCC_CELL_ENABLE)) {
+			fcr |= KL0_SCC_CELL_ENABLE;
+			need_reset_scc = 1;
+		}
+		if (chan_mask & MACIO_FLAG_SCCA_ON) {
+			fcr |= KL0_SCCA_ENABLE;
+			/* Don't enable line drivers for I2S modem */
+			if ((param & 0xfff) == PMAC_SCC_I2S1)
+				fcr &= ~KL0_SCC_A_INTF_ENABLE;
+			else
+				fcr |= KL0_SCC_A_INTF_ENABLE;
+		}
+		if (chan_mask & MACIO_FLAG_SCCB_ON) {
+			fcr |= KL0_SCCB_ENABLE;
+			/* Perform irda specific inits */
+			if ((param & 0xfff) == PMAC_SCC_IRDA) {
+				fcr &= ~KL0_SCC_B_INTF_ENABLE;
+				fcr |= KL0_IRDA_ENABLE;
+				fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE;
+				fcr |= KL0_IRDA_SOURCE1_SEL;
+				fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);
+				fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);
+				need_reset_irda = 1;
+			} else
+				fcr |= KL0_SCC_B_INTF_ENABLE;
+		}
+		MACIO_OUT32(KEYLARGO_FCR0, fcr);
+		macio->flags |= chan_mask;
+		if (need_reset_scc)  {
+			MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET);
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+			UNLOCK(flags);
+			mdelay(15);
+			LOCK(flags);
+			MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET);
+		}
+		if (need_reset_irda)  {
+			MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET);
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+			UNLOCK(flags);
+			mdelay(15);
+			LOCK(flags);
+			MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET);
+		}
+		UNLOCK(flags);
+		if (param & PMAC_SCC_FLAG_XMON)
+			macio->flags |= MACIO_FLAG_SCC_LOCKED;
+	} else {
+		if (macio->flags & MACIO_FLAG_SCC_LOCKED)
+			return -EPERM;
+		LOCK(flags);
+		fcr = MACIO_IN32(KEYLARGO_FCR0);
+		if (chan_mask & MACIO_FLAG_SCCA_ON)
+			fcr &= ~KL0_SCCA_ENABLE;
+		if (chan_mask & MACIO_FLAG_SCCB_ON) {
+			fcr &= ~KL0_SCCB_ENABLE;
+			/* Perform irda specific clears */
+			if ((param & 0xfff) == PMAC_SCC_IRDA) {
+				fcr &= ~KL0_IRDA_ENABLE;
+				fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE);
+				fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);
+				fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);
+			}
+		}
+		MACIO_OUT32(KEYLARGO_FCR0, fcr);
+		if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) {
+			fcr &= ~KL0_SCC_CELL_ENABLE;
+			MACIO_OUT32(KEYLARGO_FCR0, fcr);
+		}
+		macio->flags &= ~(chan_mask);
+		UNLOCK(flags);
+		mdelay(10);
+	}
+	return 0;
+}
+
+static long __pmac
+core99_modem_enable(struct device_node* node, long param, long value)
+{
+	struct macio_chip*	macio;
+	u8			gpio;
+	unsigned long		flags;
+
+	/* Hack for internal USB modem */
+	if (node == NULL) {
+		if (macio_chips[0].type != macio_keylargo)
+			return -ENODEV;
+		node = macio_chips[0].of_node;
+	}
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+	gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
+	gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
+	gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
+
+	if (!value) {
+		LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
+		UNLOCK(flags);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+		mdelay(250);
+	}
+    	LOCK(flags);
+    	if (value) {
+    		MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
+	    	UNLOCK(flags);
+	    	(void)MACIO_IN32(KEYLARGO_FCR2);
+		mdelay(250);
+    	} else {
+    		MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
+	    	UNLOCK(flags);
+    	}
+	if (value) {
+		LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250); LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250); LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250);
+	}
+	return 0;
+}
+
+static long __pmac
+pangea_modem_enable(struct device_node* node, long param, long value)
+{
+	struct macio_chip*	macio;
+	u8			gpio;
+	unsigned long		flags;
+
+	/* Hack for internal USB modem */
+	if (node == NULL) {
+		if (macio_chips[0].type != macio_pangea &&
+		    macio_chips[0].type != macio_intrepid)
+			return -ENODEV;
+		node = macio_chips[0].of_node;
+	}
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+	gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
+	gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
+	gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
+
+	if (!value) {
+		LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
+		UNLOCK(flags);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+		mdelay(250);
+	}
+    	LOCK(flags);
+	if (value) {
+		MACIO_OUT8(KL_GPIO_MODEM_POWER,
+			KEYLARGO_GPIO_OUTPUT_ENABLE);
+    		UNLOCK(flags);
+	    	(void)MACIO_IN32(KEYLARGO_FCR2);
+		mdelay(250);
+	} else {
+		MACIO_OUT8(KL_GPIO_MODEM_POWER,
+			KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
+    		UNLOCK(flags);
+	}
+	if (value) {
+		LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250); LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250); LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250);
+	}
+	return 0;
+}
+
+static long __pmac
+core99_ata100_enable(struct device_node* node, long value)
+{
+	unsigned long flags;
+	struct pci_dev *pdev = NULL;
+	u8 pbus, pid;
+
+    	if (uninorth_rev < 0x24)
+    		return -ENODEV;
+
+	LOCK(flags);
+	if (value)
+		UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);
+	else
+		UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);
+	(void)UN_IN(UNI_N_CLOCK_CNTL);
+	UNLOCK(flags);
+	udelay(20);
+
+	if (value) {
+		if (pci_device_from_OF_node(node, &pbus, &pid) == 0)
+			pdev = pci_find_slot(pbus, pid);
+		if (pdev == NULL)
+			return 0;
+		pci_enable_device(pdev);
+		pci_set_master(pdev);
+	}
+    	return 0;
+}
+
+static long __pmac
+core99_ide_enable(struct device_node* node, long param, long value)
+{
+	/* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2
+	 * based ata-100
+	 */
+	switch(param) {
+	    case 0:
+		return simple_feature_tweak(node, macio_unknown,
+			KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value);
+	    case 1:
+		return simple_feature_tweak(node, macio_unknown,
+			KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value);
+	    case 2:
+		return simple_feature_tweak(node, macio_unknown,
+			KEYLARGO_FCR1, KL1_UIDE_ENABLE, value);
+	    case 3:
+	    	return core99_ata100_enable(node, value);
+	    default:
+	    	return -ENODEV;
+	}
+}
+
+static long __pmac
+core99_ide_reset(struct device_node* node, long param, long value)
+{
+	switch(param) {
+	    case 0:
+		return simple_feature_tweak(node, macio_unknown,
+			KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value);
+	    case 1:
+		return simple_feature_tweak(node, macio_unknown,
+			KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value);
+	    case 2:
+		return simple_feature_tweak(node, macio_unknown,
+			KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value);
+	    default:
+	    	return -ENODEV;
+	}
+}
+
+static long __pmac
+core99_gmac_enable(struct device_node* node, long param, long value)
+{
+	unsigned long flags;
+
+	LOCK(flags);
+	if (value)
+		UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
+	else
+		UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
+	(void)UN_IN(UNI_N_CLOCK_CNTL);
+	UNLOCK(flags);
+	udelay(20);
+
+	return 0;
+}
+
+static long __pmac
+core99_gmac_phy_reset(struct device_node* node, long param, long value)
+{
+	unsigned long flags;
+	struct macio_chip* macio;
+
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+	    macio->type != macio_intrepid)
+		return -ENODEV;
+
+	LOCK(flags);
+	MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE);
+	(void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET);
+	UNLOCK(flags);
+	mdelay(10);
+	LOCK(flags);
+	MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */
+		KEYLARGO_GPIO_OUTOUT_DATA);
+	UNLOCK(flags);
+	mdelay(10);
+
+	return 0;
+}
+
+static long __pmac
+core99_sound_chip_enable(struct device_node* node, long param, long value)
+{
+	struct macio_chip*	macio;
+	unsigned long		flags;
+
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+
+	/* Do a better probe code, screamer G4 desktops &
+	 * iMacs can do that too, add a recalibrate  in
+	 * the driver as well
+	 */
+	if (pmac_mb.model_id == PMAC_TYPE_PISMO ||
+	    pmac_mb.model_id == PMAC_TYPE_TITANIUM) {
+		LOCK(flags);
+		if (value)
+	    		MACIO_OUT8(KL_GPIO_SOUND_POWER,
+	    			KEYLARGO_GPIO_OUTPUT_ENABLE |
+	    			KEYLARGO_GPIO_OUTOUT_DATA);
+	    	else
+	    		MACIO_OUT8(KL_GPIO_SOUND_POWER,
+	    			KEYLARGO_GPIO_OUTPUT_ENABLE);
+	    	(void)MACIO_IN8(KL_GPIO_SOUND_POWER);
+	    	UNLOCK(flags);
+	}
+	return 0;
+}
+
+static long __pmac
+core99_airport_enable(struct device_node* node, long param, long value)
+{
+	struct macio_chip*	macio;
+	unsigned long		flags;
+	int			state;
+
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+
+	/* Hint: we allow passing of macio itself for the sake of the
+	 * sleep code
+	 */
+	if (node != macio->of_node &&
+	    (!node->parent || node->parent != macio->of_node))
+		return -ENODEV;
+	state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0;
+	if (value == state)
+		return 0;
+	if (value) {
+		/* This code is a reproduction of OF enable-cardslot
+		 * and init-wireless methods, slightly hacked until
+		 * I got it working.
+		 */
+		LOCK(flags);
+		MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5);
+		(void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);
+		UNLOCK(flags);
+		mdelay(10);
+		LOCK(flags);
+		MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4);
+		(void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);
+		UNLOCK(flags);
+
+		mdelay(10);
+
+		LOCK(flags);
+		MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);
+		(void)MACIO_IN32(KEYLARGO_FCR2);
+		udelay(10);
+		MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xb, 0);
+		(void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xb);
+		udelay(10);
+		MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28);
+		(void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xa);
+		udelay(10);
+		MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28);
+		(void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xd);
+		udelay(10);
+		MACIO_OUT8(KEYLARGO_GPIO_0+0xd, 0x28);
+		(void)MACIO_IN8(KEYLARGO_GPIO_0+0xd);
+		udelay(10);
+		MACIO_OUT8(KEYLARGO_GPIO_0+0xe, 0x28);
+		(void)MACIO_IN8(KEYLARGO_GPIO_0+0xe);
+		UNLOCK(flags);
+		udelay(10);
+		MACIO_OUT32(0x1c000, 0);
+		mdelay(1);
+		MACIO_OUT8(0x1a3e0, 0x41);
+		(void)MACIO_IN8(0x1a3e0);
+		udelay(10);
+		LOCK(flags);
+		MACIO_BIS(KEYLARGO_FCR2, KL2_CARDSEL_16);
+		(void)MACIO_IN32(KEYLARGO_FCR2);
+		UNLOCK(flags);
+		mdelay(100);
+
+		macio->flags |= MACIO_FLAG_AIRPORT_ON;
+	} else {
+		LOCK(flags);
+		MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);
+		(void)MACIO_IN32(KEYLARGO_FCR2);
+		MACIO_OUT8(KL_GPIO_AIRPORT_0, 0);
+		MACIO_OUT8(KL_GPIO_AIRPORT_1, 0);
+		MACIO_OUT8(KL_GPIO_AIRPORT_2, 0);
+		MACIO_OUT8(KL_GPIO_AIRPORT_3, 0);
+		MACIO_OUT8(KL_GPIO_AIRPORT_4, 0);
+		(void)MACIO_IN8(KL_GPIO_AIRPORT_4);
+		UNLOCK(flags);
+
+		macio->flags &= ~MACIO_FLAG_AIRPORT_ON;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_SMP
+static long __pmac
+core99_reset_cpu(struct device_node* node, long param, long value)
+{
+	unsigned int reset_io = 0;
+	unsigned long flags;
+	struct macio_chip* macio;
+	struct device_node* np;
+	const int dflt_reset_lines[] = {	KL_GPIO_RESET_CPU0,
+						KL_GPIO_RESET_CPU1,
+						KL_GPIO_RESET_CPU2,
+						KL_GPIO_RESET_CPU3 };
+
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo)
+		return -ENODEV;
+
+	np = find_path_device("/cpus");
+	if (np == NULL)
+		return -ENODEV;
+	for (np = np->child; np != NULL; np = np->sibling) {
+		u32* num = (u32 *)get_property(np, "reg", NULL);
+		u32* rst = (u32 *)get_property(np, "soft-reset", NULL);
+		if (num == NULL || rst == NULL)
+			continue;
+		if (param == *num) {
+			reset_io = *rst;
+			break;
+		}
+	}
+	if (np == NULL || reset_io == 0)
+		reset_io = dflt_reset_lines[param];
+
+	LOCK(flags);
+	MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
+	(void)MACIO_IN8(reset_io);
+	udelay(1);
+	MACIO_OUT8(reset_io, 0);
+	(void)MACIO_IN8(reset_io);
+	UNLOCK(flags);
+
+	return 0;
+}
+#endif /* CONFIG_SMP */
+
+static long __pmac
+core99_usb_enable(struct device_node* node, long param, long value)
+{
+	struct macio_chip* macio;
+	unsigned long flags;
+	char* prop;
+	int number;
+	u32 reg;
+
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+	    macio->type != macio_intrepid)
+		return -ENODEV;
+
+	prop = (char *)get_property(node, "AAPL,clock-id", NULL);
+	if (!prop)
+		return -ENODEV;
+	if (strncmp(prop, "usb0u048", 8) == 0)
+		number = 0;
+	else if (strncmp(prop, "usb1u148", 8) == 0)
+		number = 2;
+	else if (strncmp(prop, "usb2u248", 8) == 0)
+		number = 4;
+	else
+		return -ENODEV;
+
+	/* Sorry for the brute-force locking, but this is only used during
+	 * sleep and the timing seem to be critical
+	 */
+	LOCK(flags);
+	if (value) {
+		/* Turn ON */
+		if (number == 0) {
+			MACIO_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+			UNLOCK(flags);
+			mdelay(1);
+			LOCK(flags);
+			MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
+		} else if (number == 2) {
+			MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
+			UNLOCK(flags);
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+			mdelay(1);
+			LOCK(flags);
+			MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
+		} else if (number == 4) {
+			MACIO_BIC(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1));
+			UNLOCK(flags);
+			(void)MACIO_IN32(KEYLARGO_FCR1);
+			mdelay(1);
+			LOCK(flags);
+			MACIO_BIS(KEYLARGO_FCR1, KL1_USB2_CELL_ENABLE);
+		}
+		if (number < 4) {
+			reg = MACIO_IN32(KEYLARGO_FCR4);
+			reg &=	~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |
+				KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number));
+			reg &=	~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |
+				KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1));
+			MACIO_OUT32(KEYLARGO_FCR4, reg);
+			(void)MACIO_IN32(KEYLARGO_FCR4);
+			udelay(10);
+		} else {
+			reg = MACIO_IN32(KEYLARGO_FCR3);
+			reg &=	~(KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) |
+				KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0));
+			reg &=	~(KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) |
+				KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1));
+			MACIO_OUT32(KEYLARGO_FCR3, reg);
+			(void)MACIO_IN32(KEYLARGO_FCR3);
+			udelay(10);
+		}
+		if (macio->type == macio_intrepid) {
+			/* wait for clock stopped bits to clear */
+			u32 test0 = 0, test1 = 0;
+			u32 status0, status1;
+			int timeout = 1000;
+
+			UNLOCK(flags);
+			switch (number) {
+			case 0:
+				test0 = UNI_N_CLOCK_STOPPED_USB0;
+				test1 = UNI_N_CLOCK_STOPPED_USB0PCI;
+				break;
+			case 2:
+				test0 = UNI_N_CLOCK_STOPPED_USB1;
+				test1 = UNI_N_CLOCK_STOPPED_USB1PCI;
+				break;
+			case 4:
+				test0 = UNI_N_CLOCK_STOPPED_USB2;
+				test1 = UNI_N_CLOCK_STOPPED_USB2PCI;
+				break;
+			}
+			do {
+				if (--timeout <= 0) {
+					printk(KERN_ERR "core99_usb_enable: "
+					       "Timeout waiting for clocks\n");
+					break;
+				}
+				mdelay(1);
+				status0 = UN_IN(UNI_N_CLOCK_STOP_STATUS0);
+				status1 = UN_IN(UNI_N_CLOCK_STOP_STATUS1);
+			} while ((status0 & test0) | (status1 & test1));
+			LOCK(flags);
+		}
+	} else {
+		/* Turn OFF */
+		if (number < 4) {
+			reg = MACIO_IN32(KEYLARGO_FCR4);
+			reg |=	KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |
+				KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number);
+			reg |=	KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |
+				KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1);
+			MACIO_OUT32(KEYLARGO_FCR4, reg);
+			(void)MACIO_IN32(KEYLARGO_FCR4);
+			udelay(1);
+		} else {
+			reg = MACIO_IN32(KEYLARGO_FCR3);
+			reg |=	KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) |
+				KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0);
+			reg |=	KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) |
+				KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1);
+			MACIO_OUT32(KEYLARGO_FCR3, reg);
+			(void)MACIO_IN32(KEYLARGO_FCR3);
+			udelay(1);
+		}
+		if (number == 0) {
+			if (macio->type != macio_intrepid)
+				MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+			udelay(1);
+			MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+		} else if (number == 2) {
+			if (macio->type != macio_intrepid)
+				MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+			udelay(1);
+			MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+		} else if (number == 4) {
+			udelay(1);
+			MACIO_BIS(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1));
+			(void)MACIO_IN32(KEYLARGO_FCR1);
+		}
+		udelay(1);
+	}
+	UNLOCK(flags);
+
+	return 0;
+}
+
+static long __pmac
+core99_firewire_enable(struct device_node* node, long param, long value)
+{
+	unsigned long flags;
+	struct macio_chip* macio;
+
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+	    macio->type != macio_intrepid)
+		return -ENODEV;
+	if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
+		return -ENODEV;
+
+	LOCK(flags);
+	if (value) {
+		UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
+		(void)UN_IN(UNI_N_CLOCK_CNTL);
+	} else {
+		UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
+		(void)UN_IN(UNI_N_CLOCK_CNTL);
+	}
+	UNLOCK(flags);
+	mdelay(1);
+
+	return 0;
+}
+
+static long __pmac
+core99_firewire_cable_power(struct device_node* node, long param, long value)
+{
+	unsigned long flags;
+	struct macio_chip* macio;
+
+	/* Trick: we allow NULL node */
+	if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0)
+	    	return -ENODEV;
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+	    macio->type != macio_intrepid)
+		return -ENODEV;
+	if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
+		return -ENODEV;
+
+	LOCK(flags);
+	if (value) {
+		MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 0);
+		MACIO_IN8(KL_GPIO_FW_CABLE_POWER);
+		udelay(10);
+	} else {
+		MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 4);
+		MACIO_IN8(KL_GPIO_FW_CABLE_POWER); udelay(10);
+	}
+	UNLOCK(flags);
+	mdelay(1);
+
+	return 0;
+}
+
+static long __pmac
+intrepid_aack_delay_enable(struct device_node* node, long param, long value)
+{
+	unsigned long flags;
+
+    	if (uninorth_rev < 0xd2)
+		return -ENODEV;
+
+	LOCK(flags);
+	if (param)
+		UN_BIS(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE);
+	else
+		UN_BIC(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE);
+	UNLOCK(flags);
+
+    	return 0;
+}
+
+
+#endif /* CONFIG_POWER4 */
+
+static long __pmac
+core99_read_gpio(struct device_node* node, long param, long value)
+{
+	struct macio_chip* macio = &macio_chips[0];
+
+	return MACIO_IN8(param);
+}
+
+
+static long __pmac
+core99_write_gpio(struct device_node* node, long param, long value)
+{
+	struct macio_chip* macio = &macio_chips[0];
+
+	MACIO_OUT8(param, (u8)(value & 0xff));
+	return 0;
+}
+
+#ifdef CONFIG_POWER4
+
+static long __pmac
+g5_gmac_enable(struct device_node* node, long param, long value)
+{
+	struct macio_chip* macio = &macio_chips[0];
+	unsigned long flags;
+	u8 pbus, pid;
+
+	LOCK(flags);
+	if (value) {
+		MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);
+		mb();
+		k2_skiplist[0] = NULL;
+	} else {
+		k2_skiplist[0] = node;
+		mb();
+		MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);
+	}
+	
+	UNLOCK(flags);
+	mdelay(1);
+
+	return 0;
+}
+
+static long __pmac
+g5_fw_enable(struct device_node* node, long param, long value)
+{
+	struct macio_chip* macio = &macio_chips[0];
+	unsigned long flags;
+
+	LOCK(flags);
+	if (value) {
+		MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);
+		mb();
+		k2_skiplist[1] = NULL;
+	} else {
+		k2_skiplist[1] = node;
+		mb();
+		MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);
+	}
+	
+	UNLOCK(flags);
+	mdelay(1);
+
+	return 0;
+}
+
+static long __pmac
+g5_mpic_enable(struct device_node* node, long param, long value)
+{
+	unsigned long flags;
+
+	if (node->parent == NULL || strcmp(node->parent->name, "u3"))
+		return 0;
+
+	LOCK(flags);
+	UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE);
+	UNLOCK(flags);
+
+	return 0;
+}
+
+#ifdef CONFIG_SMP
+static long __pmac
+g5_reset_cpu(struct device_node* node, long param, long value)
+{
+	unsigned int reset_io = 0;
+	unsigned long flags;
+	struct macio_chip* macio;
+	struct device_node* np;
+
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo2)
+		return -ENODEV;
+
+	np = find_path_device("/cpus");
+	if (np == NULL)
+		return -ENODEV;
+	for (np = np->child; np != NULL; np = np->sibling) {
+		u32* num = (u32 *)get_property(np, "reg", NULL);
+		u32* rst = (u32 *)get_property(np, "soft-reset", NULL);
+		if (num == NULL || rst == NULL)
+			continue;
+		if (param == *num) {
+			reset_io = *rst;
+			break;
+		}
+	}
+	if (np == NULL || reset_io == 0)
+		return -ENODEV;
+
+	LOCK(flags);
+	MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
+	(void)MACIO_IN8(reset_io);
+	udelay(1);
+	MACIO_OUT8(reset_io, 0);
+	(void)MACIO_IN8(reset_io);
+	UNLOCK(flags);
+
+	return 0;
+}
+#endif /* CONFIG_SMP */
+
+/*
+ * This can be called from pmac_smp so isn't static
+ *
+ * This takes the second CPU off the bus on dual CPU machines
+ * running UP
+ */
+void __pmac g5_phy_disable_cpu1(void)
+{
+	UN_OUT(U3_API_PHY_CONFIG_1, 0);
+}
+
+#endif /* CONFIG_POWER4 */
+
+#ifndef CONFIG_POWER4
+
+static void __pmac
+keylargo_shutdown(struct macio_chip* macio, int sleep_mode)
+{
+	u32 temp;
+
+	if (sleep_mode) {
+		mdelay(1);
+		MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);
+		(void)MACIO_IN32(KEYLARGO_FCR0);
+		mdelay(1);
+	}
+
+	MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
+				KL0_SCC_CELL_ENABLE |
+		      		KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE |
+		      		KL0_IRDA_CLK19_ENABLE);
+
+	MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK);
+	MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE);
+
+	MACIO_BIC(KEYLARGO_FCR1,
+		KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
+		KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
+		KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
+		KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
+		KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
+		KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N |
+		KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N |
+		KL1_UIDE_ENABLE);
+
+	MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
+ 	MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE);
+
+	temp = MACIO_IN32(KEYLARGO_FCR3);
+	if (macio->rev >= 2) {
+		temp |= KL3_SHUTDOWN_PLL2X;
+		if (sleep_mode)
+			temp |= KL3_SHUTDOWN_PLL_TOTAL;
+	}
+
+	temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
+		KL3_SHUTDOWN_PLLKW35;
+	if (sleep_mode)
+		temp |= KL3_SHUTDOWN_PLLKW12;
+	temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
+		| KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);
+	if (sleep_mode)
+		temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
+	MACIO_OUT32(KEYLARGO_FCR3, temp);
+
+	/* Flush posted writes & wait a bit */
+	(void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
+}
+
+static void __pmac
+pangea_shutdown(struct macio_chip* macio, int sleep_mode)
+{
+	u32 temp;
+
+	MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
+				KL0_SCC_CELL_ENABLE |
+				KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
+
+	MACIO_BIC(KEYLARGO_FCR1,
+		KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
+		KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
+		KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
+		KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
+		KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
+		KL1_UIDE_ENABLE);
+	if (pmac_mb.board_flags & PMAC_MB_MOBILE)
+		MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
+
+	MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
+
+	temp = MACIO_IN32(KEYLARGO_FCR3);
+	temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
+		KL3_SHUTDOWN_PLLKW35;
+	temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE
+		| KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE);
+	if (sleep_mode)
+		temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE);
+	MACIO_OUT32(KEYLARGO_FCR3, temp);
+
+	/* Flush posted writes & wait a bit */
+	(void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
+}
+
+static void __pmac
+intrepid_shutdown(struct macio_chip* macio, int sleep_mode)
+{
+	u32 temp;
+
+	MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
+		  KL0_SCC_CELL_ENABLE);
+
+	MACIO_BIC(KEYLARGO_FCR1,
+		  /*KL1_USB2_CELL_ENABLE |*/
+		KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
+		KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
+		KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE);
+	if (pmac_mb.board_flags & PMAC_MB_MOBILE)
+		MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
+
+	temp = MACIO_IN32(KEYLARGO_FCR3);
+	temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE |
+		  KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);
+	if (sleep_mode)
+		temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE);
+	MACIO_OUT32(KEYLARGO_FCR3, temp);
+
+	/* Flush posted writes & wait a bit */
+	(void)MACIO_IN32(KEYLARGO_FCR0);
+	mdelay(10);
+}
+
+static int __pmac
+core99_sleep(void)
+{
+	struct macio_chip* macio;
+	int i;
+
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+	    macio->type != macio_intrepid)
+		return -ENODEV;
+
+	/* The device-tree contains that in the hwclock node */
+	if (macio->type == macio_intrepid) {
+		UN_OUT(UNI_N_CLOCK_SPREADING, 0);
+		mdelay(40);
+	}
+
+	/* We power off the wireless slot in case it was not done
+	 * by the driver. We don't power it on automatically however
+	 */
+	if (macio->flags & MACIO_FLAG_AIRPORT_ON)
+		core99_airport_enable(macio->of_node, 0, 0);
+
+	/* We power off the FW cable. Should be done by the driver... */
+	if (macio->flags & MACIO_FLAG_FW_SUPPORTED) {
+		core99_firewire_enable(NULL, 0, 0);
+		core99_firewire_cable_power(NULL, 0, 0);
+	}
+
+	/* We make sure int. modem is off (in case driver lost it) */
+	if (macio->type == macio_keylargo)
+		core99_modem_enable(macio->of_node, 0, 0);
+	else
+		pangea_modem_enable(macio->of_node, 0, 0);
+
+	/* We make sure the sound is off as well */
+	core99_sound_chip_enable(macio->of_node, 0, 0);
+
+	/*
+	 * Save various bits of KeyLargo
+	 */
+
+	/* Save the state of the various GPIOs */
+	save_gpio_levels[0] = MACIO_IN32(KEYLARGO_GPIO_LEVELS0);
+	save_gpio_levels[1] = MACIO_IN32(KEYLARGO_GPIO_LEVELS1);
+	for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
+		save_gpio_extint[i] = MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+i);
+	for (i=0; i<KEYLARGO_GPIO_CNT; i++)
+		save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i);
+
+	/* Save the FCRs */
+	if (macio->type == macio_keylargo)
+		save_mbcr = MACIO_IN32(KEYLARGO_MBCR);
+	save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0);
+	save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1);
+	save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2);
+	save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3);
+	save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4);
+	if (macio->type == macio_pangea || macio->type == macio_intrepid)
+		save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5);
+
+	/* Save state & config of DBDMA channels */
+	dbdma_save(macio, save_dbdma);
+
+	/*
+	 * Turn off as much as we can
+	 */
+	if (macio->type == macio_pangea)
+		pangea_shutdown(macio, 1);
+	else if (macio->type == macio_intrepid)
+		intrepid_shutdown(macio, 1);
+	else if (macio->type == macio_keylargo)
+		keylargo_shutdown(macio, 1);
+
+	/*
+	 * Put the host bridge to sleep
+	 */
+
+	save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL);
+	/* Note: do not switch GMAC off, driver does it when necessary, WOL must keep it
+	 * enabled !
+	 */
+	UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl &
+	       ~(/*UNI_N_CLOCK_CNTL_GMAC|*/UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/));
+	udelay(100);
+	UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
+	UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP);
+	mdelay(10);
+
+	/*
+	 * FIXME: A bit of black magic with OpenPIC (don't ask me why)
+	 */
+	if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {
+		MACIO_BIS(0x506e0, 0x00400000);
+		MACIO_BIS(0x506e0, 0x80000000);
+	}
+	return 0;
+}
+
+static int __pmac
+core99_wake_up(void)
+{
+	struct macio_chip* macio;
+	int i;
+
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+	    macio->type != macio_intrepid)
+		return -ENODEV;
+
+	/*
+	 * Wakeup the host bridge
+	 */
+	UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
+	udelay(10);
+	UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
+	udelay(10);
+
+	/*
+	 * Restore KeyLargo
+	 */
+
+	if (macio->type == macio_keylargo) {
+		MACIO_OUT32(KEYLARGO_MBCR, save_mbcr);
+		(void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
+	}
+	MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]);
+	(void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
+	MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]);
+	(void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
+	MACIO_OUT32(KEYLARGO_FCR2, save_fcr[2]);
+	(void)MACIO_IN32(KEYLARGO_FCR2); udelay(10);
+	MACIO_OUT32(KEYLARGO_FCR3, save_fcr[3]);
+	(void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
+	MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]);
+	(void)MACIO_IN32(KEYLARGO_FCR4); udelay(10);
+	if (macio->type == macio_pangea || macio->type == macio_intrepid) {
+		MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]);
+		(void)MACIO_IN32(KEYLARGO_FCR5); udelay(10);
+	}
+
+	dbdma_restore(macio, save_dbdma);
+
+	MACIO_OUT32(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]);
+	MACIO_OUT32(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]);
+	for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
+		MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+i, save_gpio_extint[i]);
+	for (i=0; i<KEYLARGO_GPIO_CNT; i++)
+		MACIO_OUT8(KEYLARGO_GPIO_0+i, save_gpio_normal[i]);
+
+	/* FIXME more black magic with OpenPIC ... */
+	if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {
+		MACIO_BIC(0x506e0, 0x00400000);
+		MACIO_BIC(0x506e0, 0x80000000);
+	}
+
+	UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);
+	udelay(100);
+
+	/* Restore clock spreading */
+	if (macio->type == macio_intrepid) {
+		UN_OUT(UNI_N_CLOCK_SPREADING, 2);
+		mdelay(40);
+	}
+
+	return 0;
+}
+
+static long __pmac
+core99_sleep_state(struct device_node* node, long param, long value)
+{
+	/* Param == 1 means to enter the "fake sleep" mode that is
+	 * used for CPU speed switch
+	 */
+	if (param == 1) {
+		if (value == 1) {
+			UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
+			UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_IDLE2);
+		} else {
+			UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
+			udelay(10);
+			UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
+			udelay(10);
+		}
+		return 0;
+	}
+	if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
+		return -EPERM;
+
+#ifdef CONFIG_CPU_FREQ_PMAC
+	/* XXX should be elsewhere */
+	if (machine_is_compatible("PowerBook6,5") ||
+	    machine_is_compatible("PowerBook6,4") ||
+	    machine_is_compatible("PowerBook5,5") ||
+	    machine_is_compatible("PowerBook5,4")) {
+		struct device_node *volt_gpio_np;
+		u32 *reg = NULL;
+
+		volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");
+		if (volt_gpio_np != NULL)
+			reg = (u32 *)get_property(volt_gpio_np, "reg", NULL);
+		if (reg != NULL) {
+			/* Set the CPU voltage high if sleeping */
+			if (value == 1) {
+				pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL,
+						  *reg, 0x05);
+			} else if (value == 0 && (mfspr(SPRN_HID1) & HID1_DFS)) {
+				pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL,
+						  *reg, 0x04);
+			}
+			mdelay(2);
+		}
+	}
+#endif /* CONFIG_CPU_FREQ_PMAC */
+
+	if (value == 1)
+		return core99_sleep();
+	else if (value == 0)
+		return core99_wake_up();
+	return 0;
+}
+
+#endif /* CONFIG_POWER4 */
+
+static long __pmac
+generic_dev_can_wake(struct device_node* node, long param, long value)
+{
+	/* Todo: eventually check we are really dealing with on-board
+	 * video device ...
+	 */
+
+	if (pmac_mb.board_flags & PMAC_MB_MAY_SLEEP)
+		pmac_mb.board_flags |= PMAC_MB_CAN_SLEEP;
+	return 0;
+}
+
+static long __pmac
+generic_get_mb_info(struct device_node* node, long param, long value)
+{
+	switch(param) {
+		case PMAC_MB_INFO_MODEL:
+			return pmac_mb.model_id;
+		case PMAC_MB_INFO_FLAGS:
+			return pmac_mb.board_flags;
+		case PMAC_MB_INFO_NAME:
+			/* hack hack hack... but should work */
+			*((const char **)value) = pmac_mb.model_name;
+			return 0;
+	}
+	return -EINVAL;
+}
+
+
+/*
+ * Table definitions
+ */
+
+/* Used on any machine
+ */
+static struct feature_table_entry any_features[]  __pmacdata = {
+	{ PMAC_FTR_GET_MB_INFO,		generic_get_mb_info },
+	{ PMAC_FTR_DEVICE_CAN_WAKE,	generic_dev_can_wake },
+	{ 0, NULL }
+};
+
+#ifndef CONFIG_POWER4
+
+/* OHare based motherboards. Currently, we only use these on the
+ * 2400,3400 and 3500 series powerbooks. Some older desktops seem
+ * to have issues with turning on/off those asic cells
+ */
+static struct feature_table_entry ohare_features[]  __pmacdata = {
+	{ PMAC_FTR_SCC_ENABLE,		ohare_htw_scc_enable },
+	{ PMAC_FTR_SWIM3_ENABLE,	ohare_floppy_enable },
+	{ PMAC_FTR_MESH_ENABLE,		ohare_mesh_enable },
+	{ PMAC_FTR_IDE_ENABLE,		ohare_ide_enable},
+	{ PMAC_FTR_IDE_RESET,		ohare_ide_reset},
+	{ PMAC_FTR_SLEEP_STATE,		ohare_sleep_state },
+	{ 0, NULL }
+};
+
+/* Heathrow desktop machines (Beige G3).
+ * Separated as some features couldn't be properly tested
+ * and the serial port control bits appear to confuse it.
+ */
+static struct feature_table_entry heathrow_desktop_features[]  __pmacdata = {
+	{ PMAC_FTR_SWIM3_ENABLE,	heathrow_floppy_enable },
+	{ PMAC_FTR_MESH_ENABLE,		heathrow_mesh_enable },
+	{ PMAC_FTR_IDE_ENABLE,		heathrow_ide_enable },
+	{ PMAC_FTR_IDE_RESET,		heathrow_ide_reset },
+	{ PMAC_FTR_BMAC_ENABLE,		heathrow_bmac_enable },
+	{ 0, NULL }
+};
+
+/* Heathrow based laptop, that is the Wallstreet and mainstreet
+ * powerbooks.
+ */
+static struct feature_table_entry heathrow_laptop_features[]  __pmacdata = {
+	{ PMAC_FTR_SCC_ENABLE,		ohare_htw_scc_enable },
+	{ PMAC_FTR_MODEM_ENABLE,	heathrow_modem_enable },
+	{ PMAC_FTR_SWIM3_ENABLE,	heathrow_floppy_enable },
+	{ PMAC_FTR_MESH_ENABLE,		heathrow_mesh_enable },
+	{ PMAC_FTR_IDE_ENABLE,		heathrow_ide_enable },
+	{ PMAC_FTR_IDE_RESET,		heathrow_ide_reset },
+	{ PMAC_FTR_BMAC_ENABLE,		heathrow_bmac_enable },
+	{ PMAC_FTR_SOUND_CHIP_ENABLE,	heathrow_sound_enable },
+	{ PMAC_FTR_SLEEP_STATE,		heathrow_sleep_state },
+	{ 0, NULL }
+};
+
+/* Paddington based machines
+ * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4.
+ */
+static struct feature_table_entry paddington_features[]  __pmacdata = {
+	{ PMAC_FTR_SCC_ENABLE,		ohare_htw_scc_enable },
+	{ PMAC_FTR_MODEM_ENABLE,	heathrow_modem_enable },
+	{ PMAC_FTR_SWIM3_ENABLE,	heathrow_floppy_enable },
+	{ PMAC_FTR_MESH_ENABLE,		heathrow_mesh_enable },
+	{ PMAC_FTR_IDE_ENABLE,		heathrow_ide_enable },
+	{ PMAC_FTR_IDE_RESET,		heathrow_ide_reset },
+	{ PMAC_FTR_BMAC_ENABLE,		heathrow_bmac_enable },
+	{ PMAC_FTR_SOUND_CHIP_ENABLE,	heathrow_sound_enable },
+	{ PMAC_FTR_SLEEP_STATE,		heathrow_sleep_state },
+	{ 0, NULL }
+};
+
+/* Core99 & MacRISC 2 machines (all machines released since the
+ * iBook (included), that is all AGP machines, except pangea
+ * chipset. The pangea chipset is the "combo" UniNorth/KeyLargo
+ * used on iBook2 & iMac "flow power".
+ */
+static struct feature_table_entry core99_features[]  __pmacdata = {
+	{ PMAC_FTR_SCC_ENABLE,		core99_scc_enable },
+	{ PMAC_FTR_MODEM_ENABLE,	core99_modem_enable },
+	{ PMAC_FTR_IDE_ENABLE,		core99_ide_enable },
+	{ PMAC_FTR_IDE_RESET,		core99_ide_reset },
+	{ PMAC_FTR_GMAC_ENABLE,		core99_gmac_enable },
+	{ PMAC_FTR_GMAC_PHY_RESET,	core99_gmac_phy_reset },
+	{ PMAC_FTR_SOUND_CHIP_ENABLE,	core99_sound_chip_enable },
+	{ PMAC_FTR_AIRPORT_ENABLE,	core99_airport_enable },
+	{ PMAC_FTR_USB_ENABLE,		core99_usb_enable },
+	{ PMAC_FTR_1394_ENABLE,		core99_firewire_enable },
+	{ PMAC_FTR_1394_CABLE_POWER,	core99_firewire_cable_power },
+	{ PMAC_FTR_SLEEP_STATE,		core99_sleep_state },
+#ifdef CONFIG_SMP
+	{ PMAC_FTR_RESET_CPU,		core99_reset_cpu },
+#endif /* CONFIG_SMP */
+	{ PMAC_FTR_READ_GPIO,		core99_read_gpio },
+	{ PMAC_FTR_WRITE_GPIO,		core99_write_gpio },
+	{ 0, NULL }
+};
+
+/* RackMac
+ */
+static struct feature_table_entry rackmac_features[]  __pmacdata = {
+	{ PMAC_FTR_SCC_ENABLE,		core99_scc_enable },
+	{ PMAC_FTR_IDE_ENABLE,		core99_ide_enable },
+	{ PMAC_FTR_IDE_RESET,		core99_ide_reset },
+	{ PMAC_FTR_GMAC_ENABLE,		core99_gmac_enable },
+	{ PMAC_FTR_GMAC_PHY_RESET,	core99_gmac_phy_reset },
+	{ PMAC_FTR_USB_ENABLE,		core99_usb_enable },
+	{ PMAC_FTR_1394_ENABLE,		core99_firewire_enable },
+	{ PMAC_FTR_1394_CABLE_POWER,	core99_firewire_cable_power },
+	{ PMAC_FTR_SLEEP_STATE,		core99_sleep_state },
+#ifdef CONFIG_SMP
+	{ PMAC_FTR_RESET_CPU,		core99_reset_cpu },
+#endif /* CONFIG_SMP */
+	{ PMAC_FTR_READ_GPIO,		core99_read_gpio },
+	{ PMAC_FTR_WRITE_GPIO,		core99_write_gpio },
+	{ 0, NULL }
+};
+
+/* Pangea features
+ */
+static struct feature_table_entry pangea_features[]  __pmacdata = {
+	{ PMAC_FTR_SCC_ENABLE,		core99_scc_enable },
+	{ PMAC_FTR_MODEM_ENABLE,	pangea_modem_enable },
+	{ PMAC_FTR_IDE_ENABLE,		core99_ide_enable },
+	{ PMAC_FTR_IDE_RESET,		core99_ide_reset },
+	{ PMAC_FTR_GMAC_ENABLE,		core99_gmac_enable },
+	{ PMAC_FTR_GMAC_PHY_RESET,	core99_gmac_phy_reset },
+	{ PMAC_FTR_SOUND_CHIP_ENABLE,	core99_sound_chip_enable },
+	{ PMAC_FTR_AIRPORT_ENABLE,	core99_airport_enable },
+	{ PMAC_FTR_USB_ENABLE,		core99_usb_enable },
+	{ PMAC_FTR_1394_ENABLE,		core99_firewire_enable },
+	{ PMAC_FTR_1394_CABLE_POWER,	core99_firewire_cable_power },
+	{ PMAC_FTR_SLEEP_STATE,		core99_sleep_state },
+	{ PMAC_FTR_READ_GPIO,		core99_read_gpio },
+	{ PMAC_FTR_WRITE_GPIO,		core99_write_gpio },
+	{ 0, NULL }
+};
+
+/* Intrepid features
+ */
+static struct feature_table_entry intrepid_features[]  __pmacdata = {
+	{ PMAC_FTR_SCC_ENABLE,		core99_scc_enable },
+	{ PMAC_FTR_MODEM_ENABLE,	pangea_modem_enable },
+	{ PMAC_FTR_IDE_ENABLE,		core99_ide_enable },
+	{ PMAC_FTR_IDE_RESET,		core99_ide_reset },
+	{ PMAC_FTR_GMAC_ENABLE,		core99_gmac_enable },
+	{ PMAC_FTR_GMAC_PHY_RESET,	core99_gmac_phy_reset },
+	{ PMAC_FTR_SOUND_CHIP_ENABLE,	core99_sound_chip_enable },
+	{ PMAC_FTR_AIRPORT_ENABLE,	core99_airport_enable },
+	{ PMAC_FTR_USB_ENABLE,		core99_usb_enable },
+	{ PMAC_FTR_1394_ENABLE,		core99_firewire_enable },
+	{ PMAC_FTR_1394_CABLE_POWER,	core99_firewire_cable_power },
+	{ PMAC_FTR_SLEEP_STATE,		core99_sleep_state },
+	{ PMAC_FTR_READ_GPIO,		core99_read_gpio },
+	{ PMAC_FTR_WRITE_GPIO,		core99_write_gpio },
+	{ PMAC_FTR_AACK_DELAY_ENABLE,	intrepid_aack_delay_enable },
+	{ 0, NULL }
+};
+
+#else /* CONFIG_POWER4 */
+
+/* G5 features
+ */
+static struct feature_table_entry g5_features[]  __pmacdata = {
+	{ PMAC_FTR_GMAC_ENABLE,		g5_gmac_enable },
+	{ PMAC_FTR_1394_ENABLE,		g5_fw_enable },
+	{ PMAC_FTR_ENABLE_MPIC,		g5_mpic_enable },
+#ifdef CONFIG_SMP
+	{ PMAC_FTR_RESET_CPU,		g5_reset_cpu },
+#endif /* CONFIG_SMP */
+	{ PMAC_FTR_READ_GPIO,		core99_read_gpio },
+	{ PMAC_FTR_WRITE_GPIO,		core99_write_gpio },
+	{ 0, NULL }
+};
+
+#endif /* CONFIG_POWER4 */
+
+static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
+#ifndef CONFIG_POWER4
+	/*
+	 * Desktops
+	 */
+
+	{	"AAPL,8500",			"PowerMac 8500/8600",
+		PMAC_TYPE_PSURGE,		NULL,
+		0
+	},
+	{	"AAPL,9500",			"PowerMac 9500/9600",
+		PMAC_TYPE_PSURGE,		NULL,
+		0
+	},
+	{	"AAPL,7200",			"PowerMac 7200",
+		PMAC_TYPE_PSURGE,		NULL,
+		0
+	},
+	{	"AAPL,7300",			"PowerMac 7200/7300",
+		PMAC_TYPE_PSURGE,		NULL,
+		0
+	},
+	{	"AAPL,7500",			"PowerMac 7500",
+		PMAC_TYPE_PSURGE,		NULL,
+		0
+	},
+	{	"AAPL,ShinerESB",		"Apple Network Server",
+		PMAC_TYPE_ANS,			NULL,
+		0
+	},
+	{	"AAPL,e407",			"Alchemy",
+		PMAC_TYPE_ALCHEMY,		NULL,
+		0
+	},
+	{	"AAPL,e411",			"Gazelle",
+		PMAC_TYPE_GAZELLE,		NULL,
+		0
+	},
+	{	"AAPL,Gossamer",		"PowerMac G3 (Gossamer)",
+		PMAC_TYPE_GOSSAMER,		heathrow_desktop_features,
+		0
+	},
+	{	"AAPL,PowerMac G3",		"PowerMac G3 (Silk)",
+		PMAC_TYPE_SILK,			heathrow_desktop_features,
+		0
+	},
+	{	"PowerMac1,1",			"Blue&White G3",
+		PMAC_TYPE_YOSEMITE,		paddington_features,
+		0
+	},
+	{	"PowerMac1,2",			"PowerMac G4 PCI Graphics",
+		PMAC_TYPE_YIKES,		paddington_features,
+		0
+	},
+	{	"PowerMac2,1",			"iMac FireWire",
+		PMAC_TYPE_FW_IMAC,		core99_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
+	},
+	{	"PowerMac2,2",			"iMac FireWire",
+		PMAC_TYPE_FW_IMAC,		core99_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
+	},
+	{	"PowerMac3,1",			"PowerMac G4 AGP Graphics",
+		PMAC_TYPE_SAWTOOTH,		core99_features,
+		PMAC_MB_OLD_CORE99
+	},
+	{	"PowerMac3,2",			"PowerMac G4 AGP Graphics",
+		PMAC_TYPE_SAWTOOTH,		core99_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
+	},
+	{	"PowerMac3,3",			"PowerMac G4 AGP Graphics",
+		PMAC_TYPE_SAWTOOTH,		core99_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
+	},
+	{	"PowerMac3,4",			"PowerMac G4 Silver",
+		PMAC_TYPE_QUICKSILVER,		core99_features,
+		PMAC_MB_MAY_SLEEP
+	},
+	{	"PowerMac3,5",			"PowerMac G4 Silver",
+		PMAC_TYPE_QUICKSILVER,		core99_features,
+		PMAC_MB_MAY_SLEEP
+	},
+	{	"PowerMac3,6",			"PowerMac G4 Windtunnel",
+		PMAC_TYPE_WINDTUNNEL,		core99_features,
+		PMAC_MB_MAY_SLEEP,
+	},
+	{	"PowerMac4,1",			"iMac \"Flower Power\"",
+		PMAC_TYPE_PANGEA_IMAC,		pangea_features,
+		PMAC_MB_MAY_SLEEP
+	},
+	{	"PowerMac4,2",			"Flat panel iMac",
+		PMAC_TYPE_FLAT_PANEL_IMAC,	pangea_features,
+		PMAC_MB_CAN_SLEEP
+	},
+	{	"PowerMac4,4",			"eMac",
+		PMAC_TYPE_EMAC,			core99_features,
+		PMAC_MB_MAY_SLEEP
+	},
+	{	"PowerMac5,1",			"PowerMac G4 Cube",
+		PMAC_TYPE_CUBE,			core99_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
+	},
+	{	"PowerMac6,1",			"Flat panel iMac",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP,
+	},
+	{	"PowerMac6,3",			"Flat panel iMac",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP,
+	},
+	{	"PowerMac6,4",			"eMac",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP,
+	},
+	{	"PowerMac10,1",			"Mac mini",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER,
+	},
+	{	"iMac,1",			"iMac (first generation)",
+		PMAC_TYPE_ORIG_IMAC,		paddington_features,
+		0
+	},
+
+	/*
+	 * Xserve's
+	 */
+
+	{	"RackMac1,1",			"XServe",
+		PMAC_TYPE_RACKMAC,		rackmac_features,
+		0,
+	},
+	{	"RackMac1,2",			"XServe rev. 2",
+		PMAC_TYPE_RACKMAC,		rackmac_features,
+		0,
+	},
+
+	/*
+	 * Laptops
+	 */
+
+	{	"AAPL,3400/2400",		"PowerBook 3400",
+		PMAC_TYPE_HOOPER,		ohare_features,
+		PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
+	},
+	{	"AAPL,3500",			"PowerBook 3500",
+		PMAC_TYPE_KANGA,		ohare_features,
+		PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
+	},
+	{	"AAPL,PowerBook1998",		"PowerBook Wallstreet",
+		PMAC_TYPE_WALLSTREET,		heathrow_laptop_features,
+		PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
+	},
+	{	"PowerBook1,1",			"PowerBook 101 (Lombard)",
+		PMAC_TYPE_101_PBOOK,		paddington_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE
+	},
+	{	"PowerBook2,1",			"iBook (first generation)",
+		PMAC_TYPE_ORIG_IBOOK,		core99_features,
+		PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
+	},
+	{	"PowerBook2,2",			"iBook FireWire",
+		PMAC_TYPE_FW_IBOOK,		core99_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER |
+		PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
+	},
+	{	"PowerBook3,1",			"PowerBook Pismo",
+		PMAC_TYPE_PISMO,		core99_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER |
+		PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
+	},
+	{	"PowerBook3,2",			"PowerBook Titanium",
+		PMAC_TYPE_TITANIUM,		core99_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+	},
+	{	"PowerBook3,3",			"PowerBook Titanium II",
+		PMAC_TYPE_TITANIUM2,		core99_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+	},
+	{	"PowerBook3,4",			"PowerBook Titanium III",
+		PMAC_TYPE_TITANIUM3,		core99_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+	},
+	{	"PowerBook3,5",			"PowerBook Titanium IV",
+		PMAC_TYPE_TITANIUM4,		core99_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+	},
+	{	"PowerBook4,1",			"iBook 2",
+		PMAC_TYPE_IBOOK2,		pangea_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+	},
+	{	"PowerBook4,2",			"iBook 2",
+		PMAC_TYPE_IBOOK2,		pangea_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+	},
+	{	"PowerBook4,3",			"iBook 2 rev. 2",
+		PMAC_TYPE_IBOOK2,		pangea_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+	},
+	{	"PowerBook5,1",			"PowerBook G4 17\"",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+	{	"PowerBook5,2",			"PowerBook G4 15\"",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+	{	"PowerBook5,3",			"PowerBook G4 17\"",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+	{	"PowerBook5,4",			"PowerBook G4 15\"",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+	{	"PowerBook5,5",			"PowerBook G4 17\"",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+	{	"PowerBook5,6",			"PowerBook G4 15\"",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+	{	"PowerBook5,7",			"PowerBook G4 17\"",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+	{	"PowerBook6,1",			"PowerBook G4 12\"",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+	{	"PowerBook6,2",			"PowerBook G4",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+	{	"PowerBook6,3",			"iBook G4",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+	{	"PowerBook6,4",			"PowerBook G4 12\"",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+	{	"PowerBook6,5",			"iBook G4",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+	{	"PowerBook6,8",			"PowerBook G4 12\"",
+		PMAC_TYPE_UNKNOWN_INTREPID,	intrepid_features,
+		PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+	},
+#else /* CONFIG_POWER4 */
+	{	"PowerMac7,2",			"PowerMac G5",
+		PMAC_TYPE_POWERMAC_G5,		g5_features,
+		0,
+	},
+#endif /* CONFIG_POWER4 */
+};
+
+/*
+ * The toplevel feature_call callback
+ */
+long __pmac
+pmac_do_feature_call(unsigned int selector, ...)
+{
+	struct device_node* node;
+	long param, value;
+	int i;
+	feature_call func = NULL;
+	va_list args;
+
+	if (pmac_mb.features)
+		for (i=0; pmac_mb.features[i].function; i++)
+			if (pmac_mb.features[i].selector == selector) {
+				func = pmac_mb.features[i].function;
+				break;
+			}
+	if (!func)
+		for (i=0; any_features[i].function; i++)
+			if (any_features[i].selector == selector) {
+				func = any_features[i].function;
+				break;
+			}
+	if (!func)
+		return -ENODEV;
+
+	va_start(args, selector);
+	node = (struct device_node*)va_arg(args, void*);
+	param = va_arg(args, long);
+	value = va_arg(args, long);
+	va_end(args);
+
+	return func(node, param, value);
+}
+
+static int __init
+probe_motherboard(void)
+{
+	int i;
+	struct macio_chip* macio = &macio_chips[0];
+	const char* model = NULL;
+	struct device_node *dt;
+
+	/* Lookup known motherboard type in device-tree. First try an
+	 * exact match on the "model" property, then try a "compatible"
+	 * match is none is found.
+	 */
+	dt = find_devices("device-tree");
+	if (dt != NULL)
+		model = (const char *) get_property(dt, "model", NULL);
+	for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
+	    if (strcmp(model, pmac_mb_defs[i].model_string) == 0) {
+		pmac_mb = pmac_mb_defs[i];
+		goto found;
+	    }
+	}
+	for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
+	    if (machine_is_compatible(pmac_mb_defs[i].model_string)) {
+		pmac_mb = pmac_mb_defs[i];
+		goto found;
+	    }
+	}
+
+	/* Fallback to selection depending on mac-io chip type */
+	switch(macio->type) {
+#ifndef CONFIG_POWER4
+	    case macio_grand_central:
+		pmac_mb.model_id = PMAC_TYPE_PSURGE;
+		pmac_mb.model_name = "Unknown PowerSurge";
+		break;
+	    case macio_ohare:
+		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_OHARE;
+		pmac_mb.model_name = "Unknown OHare-based";
+	    	break;
+	    case macio_heathrow:
+		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_HEATHROW;
+		pmac_mb.model_name = "Unknown Heathrow-based";
+		pmac_mb.features = heathrow_desktop_features;
+		break;
+	    case macio_paddington:
+		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PADDINGTON;
+		pmac_mb.model_name = "Unknown Paddington-based";
+	    	pmac_mb.features = paddington_features;
+		break;
+	    case macio_keylargo:
+		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_CORE99;
+		pmac_mb.model_name = "Unknown Keylargo-based";
+	    	pmac_mb.features = core99_features;
+		break;
+	    case macio_pangea:
+		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA;
+		pmac_mb.model_name = "Unknown Pangea-based";
+	    	pmac_mb.features = pangea_features;
+		break;
+	    case macio_intrepid:
+		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_INTREPID;
+		pmac_mb.model_name = "Unknown Intrepid-based";
+	    	pmac_mb.features = intrepid_features;
+	    	break;
+#else /* CONFIG_POWER4 */
+	    case macio_keylargo2:
+		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2;
+		pmac_mb.model_name = "Unknown G5";
+	    	pmac_mb.features = g5_features;
+	    	break;
+#endif /* CONFIG_POWER4 */
+	    default:
+	    	return -ENODEV;
+	}
+found:
+#ifndef CONFIG_POWER4
+	/* Fixup Hooper vs. Comet */
+	if (pmac_mb.model_id == PMAC_TYPE_HOOPER) {
+		u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4);
+		if (!mach_id_ptr)
+			return -ENODEV;
+		/* Here, I used to disable the media-bay on comet. It
+		 * appears this is wrong, the floppy connector is actually
+		 * a kind of media-bay and works with the current driver.
+		 */
+		if (__raw_readl(mach_id_ptr) & 0x20000000UL)
+			pmac_mb.model_id = PMAC_TYPE_COMET;
+		iounmap(mach_id_ptr);
+	}
+#endif /* CONFIG_POWER4 */
+
+#ifdef CONFIG_6xx
+	/* Set default value of powersave_nap on machines that support it.
+	 * It appears that uninorth rev 3 has a problem with it, we don't
+	 * enable it on those. In theory, the flush-on-lock property is
+	 * supposed to be set when not supported, but I'm not very confident
+	 * that all Apple OF revs did it properly, I do it the paranoid way.
+	 */
+	while (uninorth_base && uninorth_rev > 3) {
+		struct device_node* np = find_path_device("/cpus");
+		if (!np || !np->child) {
+			printk(KERN_WARNING "Can't find CPU(s) in device tree !\n");
+			break;
+		}
+		np = np->child;
+		/* Nap mode not supported on SMP */
+		if (np->sibling)
+			break;
+		/* Nap mode not supported if flush-on-lock property is present */
+		if (get_property(np, "flush-on-lock", NULL))
+			break;
+		powersave_nap = 1;
+		printk(KERN_INFO "Processor NAP mode on idle enabled.\n");
+		break;
+	}
+
+	/* On CPUs that support it (750FX), lowspeed by default during
+	 * NAP mode
+	 */
+	powersave_lowspeed = 1;
+#endif /* CONFIG_6xx */
+#ifdef CONFIG_POWER4
+	powersave_nap = 1;
+#endif
+	/* Check for "mobile" machine */
+	if (model && (strncmp(model, "PowerBook", 9) == 0
+		   || strncmp(model, "iBook", 5) == 0))
+		pmac_mb.board_flags |= PMAC_MB_MOBILE;
+
+
+	printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);
+	return 0;
+}
+
+/* Initialize the Core99 UniNorth host bridge and memory controller
+ */
+static void __init
+probe_uninorth(void)
+{
+	unsigned long actrl;
+
+	/* Locate core99 Uni-N */
+	uninorth_node = of_find_node_by_name(NULL, "uni-n");
+	/* Locate G5 u3 */
+	if (uninorth_node == NULL) {
+		uninorth_node = of_find_node_by_name(NULL, "u3");
+		uninorth_u3 = 1;
+	}
+	if (uninorth_node && uninorth_node->n_addrs > 0) {
+		unsigned long address = uninorth_node->addrs[0].address;
+		uninorth_base = ioremap(address, 0x40000);
+		uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
+		if (uninorth_u3)
+			u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
+	} else
+		uninorth_node = NULL;
+
+	if (!uninorth_node)
+		return;
+
+	printk(KERN_INFO "Found %s memory controller & host bridge, revision: %d\n",
+	       uninorth_u3 ? "U3" : "UniNorth", uninorth_rev);
+	printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
+
+	/* Set the arbitrer QAck delay according to what Apple does
+	 */
+	if (uninorth_rev < 0x11) {
+		actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
+		actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
+			UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
+		UN_OUT(UNI_N_ARB_CTRL, actrl);
+	}
+
+	/* Some more magic as done by them in recent MacOS X on UniNorth
+	 * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI
+	 * memory timeout
+	 */
+	if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0)
+		UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff);
+}
+
+static void __init
+probe_one_macio(const char* name, const char* compat, int type)
+{
+	struct device_node*	node;
+	int			i;
+	volatile u32 __iomem *	base;
+	u32*			revp;
+
+	node = find_devices(name);
+	if (!node || !node->n_addrs)
+		return;
+	if (compat)
+		do {
+			if (device_is_compatible(node, compat))
+				break;
+			node = node->next;
+		} while (node);
+	if (!node)
+		return;
+	for(i=0; i<MAX_MACIO_CHIPS; i++) {
+		if (!macio_chips[i].of_node)
+			break;
+		if (macio_chips[i].of_node == node)
+			return;
+	}
+	if (i >= MAX_MACIO_CHIPS) {
+		printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");
+		printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name);
+		return;
+	}
+	base = ioremap(node->addrs[0].address, node->addrs[0].size);
+	if (!base) {
+		printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n");
+		return;
+	}
+	if (type == macio_keylargo) {
+		u32* did = (u32 *)get_property(node, "device-id", NULL);
+		if (*did == 0x00000025)
+			type = macio_pangea;
+		if (*did == 0x0000003e)
+			type = macio_intrepid;
+	}
+	macio_chips[i].of_node	= node;
+	macio_chips[i].type	= type;
+	macio_chips[i].base	= base;
+	macio_chips[i].flags	= MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON;
+	macio_chips[i].name 	= macio_names[type];
+	revp = (u32 *)get_property(node, "revision-id", NULL);
+	if (revp)
+		macio_chips[i].rev = *revp;
+	printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n",
+		macio_names[type], macio_chips[i].rev, macio_chips[i].base);
+}
+
+static int __init
+probe_macios(void)
+{
+	/* Warning, ordering is important */
+	probe_one_macio("gc", NULL, macio_grand_central);
+	probe_one_macio("ohare", NULL, macio_ohare);
+	probe_one_macio("pci106b,7", NULL, macio_ohareII);
+	probe_one_macio("mac-io", "keylargo", macio_keylargo);
+	probe_one_macio("mac-io", "paddington", macio_paddington);
+	probe_one_macio("mac-io", "gatwick", macio_gatwick);
+	probe_one_macio("mac-io", "heathrow", macio_heathrow);
+	probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2);
+
+	/* Make sure the "main" macio chip appear first */
+	if (macio_chips[0].type == macio_gatwick
+	    && macio_chips[1].type == macio_heathrow) {
+		struct macio_chip temp = macio_chips[0];
+		macio_chips[0] = macio_chips[1];
+		macio_chips[1] = temp;
+	}
+	if (macio_chips[0].type == macio_ohareII
+	    && macio_chips[1].type == macio_ohare) {
+		struct macio_chip temp = macio_chips[0];
+		macio_chips[0] = macio_chips[1];
+		macio_chips[1] = temp;
+	}
+	macio_chips[0].lbus.index = 0;
+	macio_chips[1].lbus.index = 1;
+
+	return (macio_chips[0].of_node == NULL) ? -ENODEV : 0;
+}
+
+static void __init
+initial_serial_shutdown(struct device_node* np)
+{
+	int len;
+	struct slot_names_prop {
+		int	count;
+		char	name[1];
+	} *slots;
+	char *conn;
+	int port_type = PMAC_SCC_ASYNC;
+	int modem = 0;
+
+	slots = (struct slot_names_prop *)get_property(np, "slot-names", &len);
+	conn = get_property(np, "AAPL,connector", &len);
+	if (conn && (strcmp(conn, "infrared") == 0))
+		port_type = PMAC_SCC_IRDA;
+	else if (device_is_compatible(np, "cobalt"))
+		modem = 1;
+	else if (slots && slots->count > 0) {
+		if (strcmp(slots->name, "IrDA") == 0)
+			port_type = PMAC_SCC_IRDA;
+		else if (strcmp(slots->name, "Modem") == 0)
+			modem = 1;
+	}
+	if (modem)
+		pmac_call_feature(PMAC_FTR_MODEM_ENABLE, np, 0, 0);
+	pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, port_type, 0);
+}
+
+static void __init
+set_initial_features(void)
+{
+	struct device_node* np;
+
+	/* That hack appears to be necessary for some StarMax motherboards
+	 * but I'm not too sure it was audited for side-effects on other
+	 * ohare based machines...
+	 * Since I still have difficulties figuring the right way to
+	 * differenciate them all and since that hack was there for a long
+	 * time, I'll keep it around
+	 */
+	if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) {
+		struct macio_chip* macio = &macio_chips[0];
+		MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES);
+	} else if (macio_chips[0].type == macio_ohare) {
+		struct macio_chip* macio = &macio_chips[0];
+		MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+	} else if (macio_chips[1].type == macio_ohare) {
+		struct macio_chip* macio = &macio_chips[1];
+		MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+	}
+
+#ifdef CONFIG_POWER4
+	if (macio_chips[0].type == macio_keylargo2) {
+#ifndef CONFIG_SMP
+		/* On SMP machines running UP, we have the second CPU eating
+		 * bus cycles. We need to take it off the bus. This is done
+		 * from pmac_smp for SMP kernels running on one CPU
+		 */
+		np = of_find_node_by_type(NULL, "cpu");
+		if (np != NULL)
+			np = of_find_node_by_type(np, "cpu");
+		if (np != NULL) {
+			g5_phy_disable_cpu1();
+			of_node_put(np);
+		}
+#endif /* CONFIG_SMP */
+		/* Enable GMAC for now for PCI probing. It will be disabled
+		 * later on after PCI probe
+		 */
+		np = of_find_node_by_name(NULL, "ethernet");
+		while(np) {
+			if (device_is_compatible(np, "K2-GMAC"))
+				g5_gmac_enable(np, 0, 1);
+			np = of_find_node_by_name(np, "ethernet");
+		}
+
+		/* Enable FW before PCI probe. Will be disabled later on
+		 * Note: We should have a batter way to check that we are
+		 * dealing with uninorth internal cell and not a PCI cell
+		 * on the external PCI. The code below works though.
+		 */
+		np = of_find_node_by_name(NULL, "firewire");
+		while(np) {
+			if (device_is_compatible(np, "pci106b,5811")) {
+				macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
+				g5_fw_enable(np, 0, 1);
+			}
+			np = of_find_node_by_name(np, "firewire");
+		}
+	}
+#else /* CONFIG_POWER4 */
+
+	if (macio_chips[0].type == macio_keylargo ||
+	    macio_chips[0].type == macio_pangea ||
+	    macio_chips[0].type == macio_intrepid) {
+		/* Enable GMAC for now for PCI probing. It will be disabled
+		 * later on after PCI probe
+		 */
+		np = of_find_node_by_name(NULL, "ethernet");
+		while(np) {
+			if (np->parent
+			    && device_is_compatible(np->parent, "uni-north")
+			    && device_is_compatible(np, "gmac"))
+				core99_gmac_enable(np, 0, 1);
+			np = of_find_node_by_name(np, "ethernet");
+		}
+
+		/* Enable FW before PCI probe. Will be disabled later on
+		 * Note: We should have a batter way to check that we are
+		 * dealing with uninorth internal cell and not a PCI cell
+		 * on the external PCI. The code below works though.
+		 */
+		np = of_find_node_by_name(NULL, "firewire");
+		while(np) {
+			if (np->parent
+			    && device_is_compatible(np->parent, "uni-north")
+			    && (device_is_compatible(np, "pci106b,18") ||
+	     		        device_is_compatible(np, "pci106b,30") ||
+	     		        device_is_compatible(np, "pci11c1,5811"))) {
+				macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
+				core99_firewire_enable(np, 0, 1);
+			}
+			np = of_find_node_by_name(np, "firewire");
+		}
+
+		/* Enable ATA-100 before PCI probe. */
+		np = of_find_node_by_name(NULL, "ata-6");
+		while(np) {
+			if (np->parent
+			    && device_is_compatible(np->parent, "uni-north")
+			    && device_is_compatible(np, "kauai-ata")) {
+				core99_ata100_enable(np, 1);
+			}
+			np = of_find_node_by_name(np, "ata-6");
+		}
+
+		/* Switch airport off */
+		np = find_devices("radio");
+		while(np) {
+			if (np && np->parent == macio_chips[0].of_node) {
+				macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON;
+				core99_airport_enable(np, 0, 0);
+			}
+			np = np->next;
+		}
+	}
+
+	/* On all machines that support sound PM, switch sound off */
+	if (macio_chips[0].of_node)
+		pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE,
+			macio_chips[0].of_node, 0, 0);
+
+	/* While on some desktop G3s, we turn it back on */
+	if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow
+		&& (pmac_mb.model_id == PMAC_TYPE_GOSSAMER ||
+		    pmac_mb.model_id == PMAC_TYPE_SILK)) {
+		struct macio_chip* macio = &macio_chips[0];
+		MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
+		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
+	}
+
+	/* Hack for bumping clock speed on the new PowerBooks and the
+	 * iBook G4. This implements the "platform-do-clockspreading" OF
+	 * property. For safety, we also check the product ID in the
+	 * device-tree to make reasonably sure we won't set wrong values
+	 * in the clock chip.
+	 *
+	 * Of course, ultimately, we have to implement a real parser for
+	 * the platform-do-* stuff...
+	 */
+	while (machine_is_compatible("PowerBook5,2") ||
+	       machine_is_compatible("PowerBook5,3") ||
+	       machine_is_compatible("PowerBook6,2") ||
+	       machine_is_compatible("PowerBook6,3")) {
+		struct device_node *ui2c = of_find_node_by_type(NULL, "i2c");
+		struct device_node *dt = of_find_node_by_name(NULL, "device-tree");
+		u8 buffer[9];
+		u32 *productID;
+		int i, rc, changed = 0;
+		
+		if (dt == NULL)
+			break;
+		productID = (u32 *)get_property(dt, "pid#", NULL);
+		if (productID == NULL)
+			break;
+		while(ui2c) {
+			struct device_node *p = of_get_parent(ui2c);
+			if (p && !strcmp(p->name, "uni-n"))
+				break;
+			ui2c = of_find_node_by_type(ui2c, "i2c");
+		}
+		if (ui2c == NULL)
+			break;
+		DBG("Trying to bump clock speed for PID: %08x...\n", *productID);
+		rc = pmac_low_i2c_open(ui2c, 1);
+		if (rc != 0)
+			break;
+		pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
+		rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
+		DBG("read result: %d,", rc);
+		if (rc != 0) {
+			pmac_low_i2c_close(ui2c);
+			break;
+		}
+		for (i=0; i<9; i++)
+			DBG(" %02x", buffer[i]);
+		DBG("\n");
+		
+		switch(*productID) {
+		case 0x1182:	/* AlBook 12" rev 2 */
+		case 0x1183:	/* iBook G4 12" */
+			buffer[0] = (buffer[0] & 0x8f) | 0x70;
+			buffer[2] = (buffer[2] & 0x7f) | 0x00;
+			buffer[5] = (buffer[5] & 0x80) | 0x31;
+			buffer[6] = (buffer[6] & 0x40) | 0xb0;
+			buffer[7] = (buffer[7] & 0x00) | 0xc0;
+			buffer[8] = (buffer[8] & 0x00) | 0x30;
+			changed = 1;
+			break;
+		case 0x3142:	/* AlBook 15" (ATI M10) */
+		case 0x3143:	/* AlBook 17" (ATI M10) */
+			buffer[0] = (buffer[0] & 0xaf) | 0x50;
+			buffer[2] = (buffer[2] & 0x7f) | 0x00;
+			buffer[5] = (buffer[5] & 0x80) | 0x31;
+			buffer[6] = (buffer[6] & 0x40) | 0xb0;
+			buffer[7] = (buffer[7] & 0x00) | 0xd0;
+			buffer[8] = (buffer[8] & 0x00) | 0x30;
+			changed = 1;
+			break;
+		default:
+			DBG("i2c-hwclock: Machine model not handled\n");
+			break;
+		}
+		if (!changed) {
+			pmac_low_i2c_close(ui2c);
+			break;
+		}
+		pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub);
+		rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9);
+		DBG("write result: %d,", rc);
+		pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
+		rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
+		DBG("read result: %d,", rc);
+		if (rc != 0) {
+			pmac_low_i2c_close(ui2c);
+			break;
+		}
+		for (i=0; i<9; i++)
+			DBG(" %02x", buffer[i]);
+		pmac_low_i2c_close(ui2c);
+		break;
+	}
+
+#endif /* CONFIG_POWER4 */
+
+	/* On all machines, switch modem & serial ports off */
+	np = find_devices("ch-a");
+	while(np) {
+		initial_serial_shutdown(np);
+		np = np->next;
+	}
+	np = find_devices("ch-b");
+	while(np) {
+		initial_serial_shutdown(np);
+		np = np->next;
+	}
+}
+
+void __init
+pmac_feature_init(void)
+{
+	/* Detect the UniNorth memory controller */
+	probe_uninorth();
+
+	/* Probe mac-io controllers */
+	if (probe_macios()) {
+		printk(KERN_WARNING "No mac-io chip found\n");
+		return;
+	}
+
+	/* Setup low-level i2c stuffs */
+	pmac_init_low_i2c();
+
+	/* Probe machine type */
+	if (probe_motherboard())
+		printk(KERN_WARNING "Unknown PowerMac !\n");
+
+	/* Set some initial features (turn off some chips that will
+	 * be later turned on)
+	 */
+	set_initial_features();
+}
+
+int __init
+pmac_feature_late_init(void)
+{
+	struct device_node* np;
+
+	/* Request some resources late */
+	if (uninorth_node)
+		request_OF_resource(uninorth_node, 0, NULL);
+	np = find_devices("hammerhead");
+	if (np)
+		request_OF_resource(np, 0, NULL);
+	np = find_devices("interrupt-controller");
+	if (np)
+		request_OF_resource(np, 0, NULL);
+	return 0;
+}
+
+device_initcall(pmac_feature_late_init);
+
+#ifdef CONFIG_POWER4
+
+static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
+{
+	int	freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 };
+	int	bits[8] = { 8,16,0,32,2,4,0,0 };
+	int	freq = (frq >> 8) & 0xf;
+
+	if (freqs[freq] == 0)
+		printk("%s: Unknown HT link frequency %x\n", name, freq);
+	else
+		printk("%s: %d MHz on main link, (%d in / %d out) bits width\n",
+		       name, freqs[freq],
+		       bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]);
+}
+
+void __init pmac_check_ht_link(void)
+{
+	u32	ufreq, freq, ucfg, cfg;
+	struct device_node *pcix_node;
+	u8  	px_bus, px_devfn;
+	struct pci_controller *px_hose;
+
+	(void)in_be32(u3_ht + U3_HT_LINK_COMMAND);
+	ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG);
+	ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ);
+	dump_HT_speeds("U3 HyperTransport", cfg, freq);
+
+	pcix_node = of_find_compatible_node(NULL, "pci", "pci-x");
+	if (pcix_node == NULL) {
+		printk("No PCI-X bridge found\n");
+		return;
+	}
+	if (pci_device_from_OF_node(pcix_node, &px_bus, &px_devfn) != 0) {
+		printk("PCI-X bridge found but not matched to pci\n");
+		return;
+	}
+	px_hose = pci_find_hose_for_OF_device(pcix_node);
+	if (px_hose == NULL) {
+		printk("PCI-X bridge found but not matched to host\n");
+		return;
+	}	
+	early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg);
+	early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq);
+	dump_HT_speeds("PCI-X HT Uplink", cfg, freq);
+	early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg);
+	early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq);
+	dump_HT_speeds("PCI-X HT Downlink", cfg, freq);
+}
+
+#endif /* CONFIG_POWER4 */
+
+/*
+ * Early video resume hook
+ */
+
+static void (*pmac_early_vresume_proc)(void *data) __pmacdata;
+static void *pmac_early_vresume_data __pmacdata;
+
+void pmac_set_early_video_resume(void (*proc)(void *data), void *data)
+{
+	if (_machine != _MACH_Pmac)
+		return;
+	preempt_disable();
+	pmac_early_vresume_proc = proc;
+	pmac_early_vresume_data = data;
+	preempt_enable();
+}
+EXPORT_SYMBOL(pmac_set_early_video_resume);
+
+void __pmac pmac_call_early_video_resume(void)
+{
+	if (pmac_early_vresume_proc)
+		pmac_early_vresume_proc(pmac_early_vresume_data);
+}
diff --git a/arch/ppc/platforms/pmac_low_i2c.c b/arch/ppc/platforms/pmac_low_i2c.c
new file mode 100644
index 0000000..d07579f
--- /dev/null
+++ b/arch/ppc/platforms/pmac_low_i2c.c
@@ -0,0 +1,513 @@
+/*
+ *  arch/ppc/platforms/pmac_low_i2c.c
+ *
+ *  Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.org)
+ *
+ *  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.
+ *
+ *  This file contains some low-level i2c access routines that
+ *  need to be used by various bits of the PowerMac platform code
+ *  at times where the real asynchronous & interrupt driven driver
+ *  cannot be used. The API borrows some semantics from the darwin
+ *  driver in order to ease the implementation of the platform
+ *  properties parser
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/keylargo.h>
+#include <asm/uninorth.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/pmac_low_i2c.h>
+
+#define MAX_LOW_I2C_HOST	4
+
+#if 1
+#define DBG(x...) do {\
+		printk(KERN_DEBUG "KW:" x);	\
+	} while(0)
+#else
+#define DBGG(x...)
+#endif
+
+struct low_i2c_host;
+
+typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len);
+
+struct low_i2c_host
+{
+	struct device_node	*np;		/* OF device node */
+	struct semaphore	mutex;		/* Access mutex for use by i2c-keywest */
+	low_i2c_func_t		func;		/* Access function */
+	int			is_open : 1;	/* Poor man's access control */
+	int			mode;		/* Current mode */
+	int			channel;	/* Current channel */
+	int			num_channels;	/* Number of channels */
+	unsigned long		base;		/* For keywest-i2c, base address */
+	int			bsteps;		/* And register stepping */
+	int			speed;		/* And speed */
+};
+
+static struct low_i2c_host	low_i2c_hosts[MAX_LOW_I2C_HOST];
+
+/* No locking is necessary on allocation, we are running way before
+ * anything can race with us
+ */
+static struct low_i2c_host *find_low_i2c_host(struct device_node *np)
+{
+	int i;
+
+	for (i = 0; i < MAX_LOW_I2C_HOST; i++)
+		if (low_i2c_hosts[i].np == np)
+			return &low_i2c_hosts[i];
+	return NULL;
+}
+
+/*
+ *
+ * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's)
+ *
+ */
+
+/*
+ * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h,
+ * should be moved somewhere in include/asm-ppc/
+ */
+/* Register indices */
+typedef enum {
+	reg_mode = 0,
+	reg_control,
+	reg_status,
+	reg_isr,
+	reg_ier,
+	reg_addr,
+	reg_subaddr,
+	reg_data
+} reg_t;
+
+
+/* Mode register */
+#define KW_I2C_MODE_100KHZ	0x00
+#define KW_I2C_MODE_50KHZ	0x01
+#define KW_I2C_MODE_25KHZ	0x02
+#define KW_I2C_MODE_DUMB	0x00
+#define KW_I2C_MODE_STANDARD	0x04
+#define KW_I2C_MODE_STANDARDSUB	0x08
+#define KW_I2C_MODE_COMBINED	0x0C
+#define KW_I2C_MODE_MODE_MASK	0x0C
+#define KW_I2C_MODE_CHAN_MASK	0xF0
+
+/* Control register */
+#define KW_I2C_CTL_AAK		0x01
+#define KW_I2C_CTL_XADDR	0x02
+#define KW_I2C_CTL_STOP		0x04
+#define KW_I2C_CTL_START	0x08
+
+/* Status register */
+#define KW_I2C_STAT_BUSY	0x01
+#define KW_I2C_STAT_LAST_AAK	0x02
+#define KW_I2C_STAT_LAST_RW	0x04
+#define KW_I2C_STAT_SDA		0x08
+#define KW_I2C_STAT_SCL		0x10
+
+/* IER & ISR registers */
+#define KW_I2C_IRQ_DATA		0x01
+#define KW_I2C_IRQ_ADDR		0x02
+#define KW_I2C_IRQ_STOP		0x04
+#define KW_I2C_IRQ_START	0x08
+#define KW_I2C_IRQ_MASK		0x0F
+
+/* State machine states */
+enum {
+	state_idle,
+	state_addr,
+	state_read,
+	state_write,
+	state_stop,
+	state_dead
+};
+
+#define WRONG_STATE(name) do {\
+		printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \
+		       name, __kw_state_names[state], isr); \
+	} while(0)
+
+static const char *__kw_state_names[] = {
+	"state_idle",
+	"state_addr",
+	"state_read",
+	"state_write",
+	"state_stop",
+	"state_dead"
+};
+
+static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg)
+{
+	return in_8(((volatile u8 *)host->base)
+		+ (((unsigned)reg) << host->bsteps));
+}
+
+static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val)
+{
+	out_8(((volatile u8 *)host->base)
+		+ (((unsigned)reg) << host->bsteps), val);
+	(void)__kw_read_reg(host, reg_subaddr);
+}
+
+#define kw_write_reg(reg, val)	__kw_write_reg(host, reg, val) 
+#define kw_read_reg(reg)	__kw_read_reg(host, reg) 
+
+
+/* Don't schedule, the g5 fan controller is too
+ * timing sensitive
+ */
+static u8 kw_wait_interrupt(struct low_i2c_host* host)
+{
+	int i;
+	u8 isr;
+	
+	for (i = 0; i < 200000; i++) {
+		isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK;
+		if (isr != 0)
+			return isr;
+		udelay(1);
+	}
+	return isr;
+}
+
+static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr)
+{
+	u8 ack;
+
+	if (isr == 0) {
+		if (state != state_stop) {
+			DBG("KW: Timeout !\n");
+			*rc = -EIO;
+			goto stop;
+		}
+		if (state == state_stop) {
+			ack = kw_read_reg(reg_status);
+			if (!(ack & KW_I2C_STAT_BUSY)) {
+				state = state_idle;
+				kw_write_reg(reg_ier, 0x00);
+			}
+		}
+		return state;
+	}
+
+	if (isr & KW_I2C_IRQ_ADDR) {
+		ack = kw_read_reg(reg_status);
+		if (state != state_addr) {
+			kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
+			WRONG_STATE("KW_I2C_IRQ_ADDR"); 
+			*rc = -EIO;
+			goto stop;
+		}
+		if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {			
+			*rc = -ENODEV;
+			DBG("KW: NAK on address\n");
+			return state_stop;		     
+		} else {
+			if (rw) {
+				state = state_read;
+				if (*len > 1)
+					kw_write_reg(reg_control, KW_I2C_CTL_AAK);
+			} else {
+				state = state_write;
+				kw_write_reg(reg_data, **data);
+				(*data)++; (*len)--;
+			}
+		}
+		kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
+	}
+
+	if (isr & KW_I2C_IRQ_DATA) {
+		if (state == state_read) {
+			**data = kw_read_reg(reg_data);
+			(*data)++; (*len)--;
+			kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
+			if ((*len) == 0)
+				state = state_stop;
+			else if ((*len) == 1)
+				kw_write_reg(reg_control, 0);
+		} else if (state == state_write) {
+			ack = kw_read_reg(reg_status);
+			if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
+				DBG("KW: nack on data write\n");
+				*rc = -EIO;
+				goto stop;
+			} else if (*len) {
+				kw_write_reg(reg_data, **data);
+				(*data)++; (*len)--;
+			} else {
+				kw_write_reg(reg_control, KW_I2C_CTL_STOP);
+				state = state_stop;
+				*rc = 0;
+			}
+			kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
+		} else {
+			kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
+			WRONG_STATE("KW_I2C_IRQ_DATA"); 
+			if (state != state_stop) {
+				*rc = -EIO;
+				goto stop;
+			}
+		}
+	}
+
+	if (isr & KW_I2C_IRQ_STOP) {
+		kw_write_reg(reg_isr, KW_I2C_IRQ_STOP);
+		if (state != state_stop) {
+			WRONG_STATE("KW_I2C_IRQ_STOP");
+			*rc = -EIO;
+		}
+		return state_idle;
+	}
+
+	if (isr & KW_I2C_IRQ_START)
+		kw_write_reg(reg_isr, KW_I2C_IRQ_START);
+
+	return state;
+
+ stop:
+	kw_write_reg(reg_control, KW_I2C_CTL_STOP);	
+	return state_stop;
+}
+
+static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len)
+{
+	u8 mode_reg = host->speed;
+	int state = state_addr;
+	int rc = 0;
+
+	/* Setup mode & subaddress if any */
+	switch(host->mode) {
+	case pmac_low_i2c_mode_dumb:
+		printk(KERN_ERR "low_i2c: Dumb mode not supported !\n");
+		return -EINVAL;
+	case pmac_low_i2c_mode_std:
+		mode_reg |= KW_I2C_MODE_STANDARD;
+		break;
+	case pmac_low_i2c_mode_stdsub:
+		mode_reg |= KW_I2C_MODE_STANDARDSUB;
+		kw_write_reg(reg_subaddr, subaddr);
+		break;
+	case pmac_low_i2c_mode_combined:
+		mode_reg |= KW_I2C_MODE_COMBINED;
+		kw_write_reg(reg_subaddr, subaddr);
+		break;
+	}
+
+	/* Setup channel & clear pending irqs */
+	kw_write_reg(reg_isr, kw_read_reg(reg_isr));
+	kw_write_reg(reg_mode, mode_reg | (host->channel << 4));
+	kw_write_reg(reg_status, 0);
+
+	/* Set up address and r/w bit */
+	kw_write_reg(reg_addr, addr);
+
+	/* Start sending address & disable interrupt*/
+	kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/);
+	kw_write_reg(reg_control, KW_I2C_CTL_XADDR);
+
+	/* State machine, to turn into an interrupt handler */
+	while(state != state_idle) {
+		u8 isr = kw_wait_interrupt(host);
+		state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr);
+	}
+
+	return rc;
+}
+
+static void keywest_low_i2c_add(struct device_node *np)
+{
+	struct low_i2c_host	*host = find_low_i2c_host(NULL);
+	unsigned long		*psteps, *prate, steps, aoffset = 0;
+	struct device_node	*parent;
+
+	if (host == NULL) {
+		printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",
+		       np->full_name);
+		return;
+	}
+	memset(host, 0, sizeof(*host));
+
+	init_MUTEX(&host->mutex);
+	host->np = of_node_get(np);	
+	psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL);
+	steps = psteps ? (*psteps) : 0x10;
+	for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++)
+		steps >>= 1;
+	parent = of_get_parent(np);
+	host->num_channels = 1;
+	if (parent && parent->name[0] == 'u') {
+		host->num_channels = 2;
+		aoffset = 3;
+	}
+	/* Select interface rate */
+	host->speed = KW_I2C_MODE_100KHZ;
+	prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL);
+	if (prate) switch(*prate) {
+	case 100:
+		host->speed = KW_I2C_MODE_100KHZ;
+		break;
+	case 50:
+		host->speed = KW_I2C_MODE_50KHZ;
+		break;
+	case 25:
+		host->speed = KW_I2C_MODE_25KHZ;
+		break;
+	}	
+	host->mode = pmac_low_i2c_mode_std;
+	host->base = (unsigned long)ioremap(np->addrs[0].address + aoffset,
+						np->addrs[0].size);
+	host->func = keywest_low_i2c_func;
+}
+
+/*
+ *
+ * PMU implementation
+ *
+ */
+
+
+#ifdef CONFIG_ADB_PMU
+
+static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len)
+{
+	// TODO
+	return -ENODEV;
+}
+
+static void pmu_low_i2c_add(struct device_node *np)
+{
+	struct low_i2c_host	*host = find_low_i2c_host(NULL);
+
+	if (host == NULL) {
+		printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",
+		       np->full_name);
+		return;
+	}
+	memset(host, 0, sizeof(*host));
+
+	init_MUTEX(&host->mutex);
+	host->np = of_node_get(np);	
+	host->num_channels = 3;
+	host->mode = pmac_low_i2c_mode_std;
+	host->func = pmu_low_i2c_func;
+}
+
+#endif /* CONFIG_ADB_PMU */
+
+void __init pmac_init_low_i2c(void)
+{
+	struct device_node *np;
+
+	/* Probe keywest-i2c busses */
+	np = of_find_compatible_node(NULL, "i2c", "keywest-i2c");
+	while(np) {
+		keywest_low_i2c_add(np);
+		np = of_find_compatible_node(np, "i2c", "keywest-i2c");
+	}
+
+#ifdef CONFIG_ADB_PMU
+	/* Probe PMU busses */
+	np = of_find_node_by_name(NULL, "via-pmu");
+	if (np)
+		pmu_low_i2c_add(np);
+#endif /* CONFIG_ADB_PMU */
+
+	/* TODO: Add CUDA support as well */
+}
+
+int pmac_low_i2c_lock(struct device_node *np)
+{
+	struct low_i2c_host *host = find_low_i2c_host(np);
+
+	if (!host)
+		return -ENODEV;
+	down(&host->mutex);
+	return 0;
+}
+EXPORT_SYMBOL(pmac_low_i2c_lock);
+
+int pmac_low_i2c_unlock(struct device_node *np)
+{
+	struct low_i2c_host *host = find_low_i2c_host(np);
+
+	if (!host)
+		return -ENODEV;
+	up(&host->mutex);
+	return 0;
+}
+EXPORT_SYMBOL(pmac_low_i2c_unlock);
+
+
+int pmac_low_i2c_open(struct device_node *np, int channel)
+{
+	struct low_i2c_host *host = find_low_i2c_host(np);
+
+	if (!host)
+		return -ENODEV;
+
+	if (channel >= host->num_channels)
+		return -EINVAL;
+
+	down(&host->mutex);
+	host->is_open = 1;
+	host->channel = channel;
+
+	return 0;
+}
+EXPORT_SYMBOL(pmac_low_i2c_open);
+
+int pmac_low_i2c_close(struct device_node *np)
+{
+	struct low_i2c_host *host = find_low_i2c_host(np);
+
+	if (!host)
+		return -ENODEV;
+
+	host->is_open = 0;
+	up(&host->mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(pmac_low_i2c_close);
+
+int pmac_low_i2c_setmode(struct device_node *np, int mode)
+{
+	struct low_i2c_host *host = find_low_i2c_host(np);
+
+	if (!host)
+		return -ENODEV;
+	WARN_ON(!host->is_open);
+	host->mode = mode;
+
+	return 0;
+}
+EXPORT_SYMBOL(pmac_low_i2c_setmode);
+
+int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len)
+{
+	struct low_i2c_host *host = find_low_i2c_host(np);
+
+	if (!host)
+		return -ENODEV;
+	WARN_ON(!host->is_open);
+
+	return host->func(host, addrdir, subaddr, data, len);
+}
+EXPORT_SYMBOL(pmac_low_i2c_xfer);
+
diff --git a/arch/ppc/platforms/pmac_nvram.c b/arch/ppc/platforms/pmac_nvram.c
new file mode 100644
index 0000000..c9de642
--- /dev/null
+++ b/arch/ppc/platforms/pmac_nvram.c
@@ -0,0 +1,584 @@
+/*
+ *  arch/ppc/platforms/pmac_nvram.c
+ *
+ *  Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *
+ *  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.
+ *
+ *  Todo: - add support for the OF persistent properties
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/string.h>
+#include <linux/nvram.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <linux/bootmem.h>
+#include <linux/completion.h>
+#include <linux/spinlock.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/nvram.h>
+
+#define DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+#define NVRAM_SIZE		0x2000	/* 8kB of non-volatile RAM */
+
+#define CORE99_SIGNATURE	0x5a
+#define CORE99_ADLER_START	0x14
+
+/* On Core99, nvram is either a sharp, a micron or an AMD flash */
+#define SM_FLASH_STATUS_DONE	0x80
+#define SM_FLASH_STATUS_ERR		0x38
+#define SM_FLASH_CMD_ERASE_CONFIRM	0xd0
+#define SM_FLASH_CMD_ERASE_SETUP	0x20
+#define SM_FLASH_CMD_RESET		0xff
+#define SM_FLASH_CMD_WRITE_SETUP	0x40
+#define SM_FLASH_CMD_CLEAR_STATUS	0x50
+#define SM_FLASH_CMD_READ_STATUS	0x70
+
+/* CHRP NVRAM header */
+struct chrp_header {
+  u8		signature;
+  u8		cksum;
+  u16		len;
+  char          name[12];
+  u8		data[0];
+};
+
+struct core99_header {
+  struct chrp_header	hdr;
+  u32			adler;
+  u32			generation;
+  u32			reserved[2];
+};
+
+/*
+ * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
+ */
+static int nvram_naddrs;
+static volatile unsigned char *nvram_addr;
+static volatile unsigned char *nvram_data;
+static int nvram_mult, is_core_99;
+static int core99_bank = 0;
+static int nvram_partitions[3];
+static DEFINE_SPINLOCK(nv_lock);
+
+extern int pmac_newworld;
+extern int system_running;
+
+static int (*core99_write_bank)(int bank, u8* datas);
+static int (*core99_erase_bank)(int bank);
+
+static char *nvram_image __pmacdata;
+
+
+static unsigned char __pmac core99_nvram_read_byte(int addr)
+{
+	if (nvram_image == NULL)
+		return 0xff;
+	return nvram_image[addr];
+}
+
+static void __pmac core99_nvram_write_byte(int addr, unsigned char val)
+{
+	if (nvram_image == NULL)
+		return;
+	nvram_image[addr] = val;
+}
+
+
+static unsigned char __openfirmware direct_nvram_read_byte(int addr)
+{
+	return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]);
+}
+
+static void __openfirmware direct_nvram_write_byte(int addr, unsigned char val)
+{
+	out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val);
+}
+
+
+static unsigned char __pmac indirect_nvram_read_byte(int addr)
+{
+	unsigned char val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&nv_lock, flags);
+	out_8(nvram_addr, addr >> 5);
+	val = in_8(&nvram_data[(addr & 0x1f) << 4]);
+	spin_unlock_irqrestore(&nv_lock, flags);
+
+	return val;
+}
+
+static void __pmac indirect_nvram_write_byte(int addr, unsigned char val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&nv_lock, flags);
+	out_8(nvram_addr, addr >> 5);
+	out_8(&nvram_data[(addr & 0x1f) << 4], val);
+	spin_unlock_irqrestore(&nv_lock, flags);
+}
+
+
+#ifdef CONFIG_ADB_PMU
+
+static void __pmac pmu_nvram_complete(struct adb_request *req)
+{
+	if (req->arg)
+		complete((struct completion *)req->arg);
+}
+
+static unsigned char __pmac pmu_nvram_read_byte(int addr)
+{
+	struct adb_request req;
+	DECLARE_COMPLETION(req_complete); 
+	
+	req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
+	if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM,
+			(addr >> 8) & 0xff, addr & 0xff))
+		return 0xff;
+	if (system_state == SYSTEM_RUNNING)
+		wait_for_completion(&req_complete);
+	while (!req.complete)
+		pmu_poll();
+	return req.reply[0];
+}
+
+static void __pmac pmu_nvram_write_byte(int addr, unsigned char val)
+{
+	struct adb_request req;
+	DECLARE_COMPLETION(req_complete); 
+	
+	req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
+	if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM,
+			(addr >> 8) & 0xff, addr & 0xff, val))
+		return;
+	if (system_state == SYSTEM_RUNNING)
+		wait_for_completion(&req_complete);
+	while (!req.complete)
+		pmu_poll();
+}
+
+#endif /* CONFIG_ADB_PMU */
+
+
+static u8 __pmac chrp_checksum(struct chrp_header* hdr)
+{
+	u8 *ptr;
+	u16 sum = hdr->signature;
+	for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
+		sum += *ptr;
+	while (sum > 0xFF)
+		sum = (sum & 0xFF) + (sum>>8);
+	return sum;
+}
+
+static u32 __pmac core99_calc_adler(u8 *buffer)
+{
+	int cnt;
+	u32 low, high;
+
+   	buffer += CORE99_ADLER_START;
+	low = 1;
+	high = 0;
+	for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
+		if ((cnt % 5000) == 0) {
+			high  %= 65521UL;
+			high %= 65521UL;
+		}
+		low += buffer[cnt];
+		high += low;
+	}
+	low  %= 65521UL;
+	high %= 65521UL;
+
+	return (high << 16) | low;
+}
+
+static u32 __pmac core99_check(u8* datas)
+{
+	struct core99_header* hdr99 = (struct core99_header*)datas;
+
+	if (hdr99->hdr.signature != CORE99_SIGNATURE) {
+		DBG("Invalid signature\n");
+		return 0;
+	}
+	if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
+		DBG("Invalid checksum\n");
+		return 0;
+	}
+	if (hdr99->adler != core99_calc_adler(datas)) {
+		DBG("Invalid adler\n");
+		return 0;
+	}
+	return hdr99->generation;
+}
+
+static int __pmac sm_erase_bank(int bank)
+{
+	int stat, i;
+	unsigned long timeout;
+
+	u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+
+       	DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank);
+
+	out_8(base, SM_FLASH_CMD_ERASE_SETUP);
+	out_8(base, SM_FLASH_CMD_ERASE_CONFIRM);
+	timeout = 0;
+	do {
+		if (++timeout > 1000000) {
+			printk(KERN_ERR "nvram: Sharp/Miron flash erase timeout !\n");
+			break;
+		}
+		out_8(base, SM_FLASH_CMD_READ_STATUS);
+		stat = in_8(base);
+	} while (!(stat & SM_FLASH_STATUS_DONE));
+
+	out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
+	out_8(base, SM_FLASH_CMD_RESET);
+
+	for (i=0; i<NVRAM_SIZE; i++)
+		if (base[i] != 0xff) {
+			printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n");
+			return -ENXIO;
+		}
+	return 0;
+}
+
+static int __pmac sm_write_bank(int bank, u8* datas)
+{
+	int i, stat = 0;
+	unsigned long timeout;
+
+	u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+
+       	DBG("nvram: Sharp/Micron Writing bank %d...\n", bank);
+
+	for (i=0; i<NVRAM_SIZE; i++) {
+		out_8(base+i, SM_FLASH_CMD_WRITE_SETUP);
+		udelay(1);
+		out_8(base+i, datas[i]);
+		timeout = 0;
+		do {
+			if (++timeout > 1000000) {
+				printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n");
+				break;
+			}
+			out_8(base, SM_FLASH_CMD_READ_STATUS);
+			stat = in_8(base);
+		} while (!(stat & SM_FLASH_STATUS_DONE));
+		if (!(stat & SM_FLASH_STATUS_DONE))
+			break;
+	}
+	out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
+	out_8(base, SM_FLASH_CMD_RESET);
+	for (i=0; i<NVRAM_SIZE; i++)
+		if (base[i] != datas[i]) {
+			printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n");
+			return -ENXIO;
+		}
+	return 0;
+}
+
+static int __pmac amd_erase_bank(int bank)
+{
+	int i, stat = 0;
+	unsigned long timeout;
+
+	u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+
+       	DBG("nvram: AMD Erasing bank %d...\n", bank);
+
+	/* Unlock 1 */
+	out_8(base+0x555, 0xaa);
+	udelay(1);
+	/* Unlock 2 */
+	out_8(base+0x2aa, 0x55);
+	udelay(1);
+
+	/* Sector-Erase */
+	out_8(base+0x555, 0x80);
+	udelay(1);
+	out_8(base+0x555, 0xaa);
+	udelay(1);
+	out_8(base+0x2aa, 0x55);
+	udelay(1);
+	out_8(base, 0x30);
+	udelay(1);
+
+	timeout = 0;
+	do {
+		if (++timeout > 1000000) {
+			printk(KERN_ERR "nvram: AMD flash erase timeout !\n");
+			break;
+		}
+		stat = in_8(base) ^ in_8(base);
+	} while (stat != 0);
+	
+	/* Reset */
+	out_8(base, 0xf0);
+	udelay(1);
+	
+	for (i=0; i<NVRAM_SIZE; i++)
+		if (base[i] != 0xff) {
+			printk(KERN_ERR "nvram: AMD flash erase failed !\n");
+			return -ENXIO;
+		}
+	return 0;
+}
+
+static int __pmac amd_write_bank(int bank, u8* datas)
+{
+	int i, stat = 0;
+	unsigned long timeout;
+
+	u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+
+       	DBG("nvram: AMD Writing bank %d...\n", bank);
+
+	for (i=0; i<NVRAM_SIZE; i++) {
+		/* Unlock 1 */
+		out_8(base+0x555, 0xaa);
+		udelay(1);
+		/* Unlock 2 */
+		out_8(base+0x2aa, 0x55);
+		udelay(1);
+
+		/* Write single word */
+		out_8(base+0x555, 0xa0);
+		udelay(1);
+		out_8(base+i, datas[i]);
+		
+		timeout = 0;
+		do {
+			if (++timeout > 1000000) {
+				printk(KERN_ERR "nvram: AMD flash write timeout !\n");
+				break;
+			}
+			stat = in_8(base) ^ in_8(base);
+		} while (stat != 0);
+		if (stat != 0)
+			break;
+	}
+
+	/* Reset */
+	out_8(base, 0xf0);
+	udelay(1);
+
+	for (i=0; i<NVRAM_SIZE; i++)
+		if (base[i] != datas[i]) {
+			printk(KERN_ERR "nvram: AMD flash write failed !\n");
+			return -ENXIO;
+		}
+	return 0;
+}
+
+static void __init lookup_partitions(void)
+{
+	u8 buffer[17];
+	int i, offset;
+	struct chrp_header* hdr;
+
+	if (pmac_newworld) {
+		nvram_partitions[pmac_nvram_OF] = -1;
+		nvram_partitions[pmac_nvram_XPRAM] = -1;
+		nvram_partitions[pmac_nvram_NR] = -1;
+		hdr = (struct chrp_header *)buffer;
+
+		offset = 0;
+		buffer[16] = 0;
+		do {
+			for (i=0;i<16;i++)
+				buffer[i] = nvram_read_byte(offset+i);
+			if (!strcmp(hdr->name, "common"))
+				nvram_partitions[pmac_nvram_OF] = offset + 0x10;
+			if (!strcmp(hdr->name, "APL,MacOS75")) {
+				nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
+				nvram_partitions[pmac_nvram_NR] = offset + 0x110;
+			}
+			offset += (hdr->len * 0x10);
+		} while(offset < NVRAM_SIZE);
+	} else {
+		nvram_partitions[pmac_nvram_OF] = 0x1800;
+		nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
+		nvram_partitions[pmac_nvram_NR] = 0x1400;
+	}
+	DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
+	DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
+	DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
+}
+
+static void __pmac core99_nvram_sync(void)
+{
+	struct core99_header* hdr99;
+	unsigned long flags;
+
+	if (!is_core_99 || !nvram_data || !nvram_image)
+		return;
+
+	spin_lock_irqsave(&nv_lock, flags);
+	if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
+		NVRAM_SIZE))
+		goto bail;
+
+	DBG("Updating nvram...\n");
+
+	hdr99 = (struct core99_header*)nvram_image;
+	hdr99->generation++;
+	hdr99->hdr.signature = CORE99_SIGNATURE;
+	hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
+	hdr99->adler = core99_calc_adler(nvram_image);
+	core99_bank = core99_bank ? 0 : 1;
+	if (core99_erase_bank)
+		if (core99_erase_bank(core99_bank)) {
+			printk("nvram: Error erasing bank %d\n", core99_bank);
+			goto bail;
+		}
+	if (core99_write_bank)
+		if (core99_write_bank(core99_bank, nvram_image))
+			printk("nvram: Error writing bank %d\n", core99_bank);
+ bail:
+	spin_unlock_irqrestore(&nv_lock, flags);
+
+#ifdef DEBUG
+       	mdelay(2000);
+#endif
+}
+
+void __init pmac_nvram_init(void)
+{
+	struct device_node *dp;
+
+	nvram_naddrs = 0;
+
+	dp = find_devices("nvram");
+	if (dp == NULL) {
+		printk(KERN_ERR "Can't find NVRAM device\n");
+		return;
+	}
+	nvram_naddrs = dp->n_addrs;
+	is_core_99 = device_is_compatible(dp, "nvram,flash");
+	if (is_core_99) {
+		int i;
+		u32 gen_bank0, gen_bank1;
+
+		if (nvram_naddrs < 1) {
+			printk(KERN_ERR "nvram: no address\n");
+			return;
+		}
+		nvram_image = alloc_bootmem(NVRAM_SIZE);
+		if (nvram_image == NULL) {
+			printk(KERN_ERR "nvram: can't allocate ram image\n");
+			return;
+		}
+		nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
+		nvram_naddrs = 1; /* Make sure we get the correct case */
+
+		DBG("nvram: Checking bank 0...\n");
+
+		gen_bank0 = core99_check((u8 *)nvram_data);
+		gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
+		core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
+
+		DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
+		DBG("nvram: Active bank is: %d\n", core99_bank);
+
+		for (i=0; i<NVRAM_SIZE; i++)
+			nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
+
+		ppc_md.nvram_read_val	= core99_nvram_read_byte;
+		ppc_md.nvram_write_val	= core99_nvram_write_byte;
+		ppc_md.nvram_sync	= core99_nvram_sync;
+		/* 
+		 * Maybe we could be smarter here though making an exclusive list
+		 * of known flash chips is a bit nasty as older OF didn't provide us
+		 * with a useful "compatible" entry. A solution would be to really
+		 * identify the chip using flash id commands and base ourselves on
+		 * a list of known chips IDs
+		 */
+		if (device_is_compatible(dp, "amd-0137")) {
+			core99_erase_bank = amd_erase_bank;
+			core99_write_bank = amd_write_bank;
+		} else {
+			core99_erase_bank = sm_erase_bank;
+			core99_write_bank = sm_write_bank;
+		}
+	} else if (_machine == _MACH_chrp && nvram_naddrs == 1) {
+		nvram_data = ioremap(dp->addrs[0].address + isa_mem_base,
+				     dp->addrs[0].size);
+		nvram_mult = 1;
+		ppc_md.nvram_read_val	= direct_nvram_read_byte;
+		ppc_md.nvram_write_val	= direct_nvram_write_byte;
+	} else if (nvram_naddrs == 1) {
+		nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
+		nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE;
+		ppc_md.nvram_read_val	= direct_nvram_read_byte;
+		ppc_md.nvram_write_val	= direct_nvram_write_byte;
+	} else if (nvram_naddrs == 2) {
+		nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size);
+		nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size);
+		ppc_md.nvram_read_val	= indirect_nvram_read_byte;
+		ppc_md.nvram_write_val	= indirect_nvram_write_byte;
+	} else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
+#ifdef CONFIG_ADB_PMU
+		nvram_naddrs = -1;
+		ppc_md.nvram_read_val	= pmu_nvram_read_byte;
+		ppc_md.nvram_write_val	= pmu_nvram_write_byte;
+#endif /* CONFIG_ADB_PMU */
+	} else {
+		printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n",
+		       nvram_naddrs);
+	}
+	lookup_partitions();
+}
+
+int __pmac pmac_get_partition(int partition)
+{
+	return nvram_partitions[partition];
+}
+
+u8 __pmac pmac_xpram_read(int xpaddr)
+{
+	int offset = nvram_partitions[pmac_nvram_XPRAM];
+
+	if (offset < 0)
+		return 0xff;
+
+	return ppc_md.nvram_read_val(xpaddr + offset);
+}
+
+void __pmac pmac_xpram_write(int xpaddr, u8 data)
+{
+	int offset = nvram_partitions[pmac_nvram_XPRAM];
+
+	if (offset < 0)
+		return;
+
+	ppc_md.nvram_write_val(xpaddr + offset, data);
+}
+
+EXPORT_SYMBOL(pmac_get_partition);
+EXPORT_SYMBOL(pmac_xpram_read);
+EXPORT_SYMBOL(pmac_xpram_write);
diff --git a/arch/ppc/platforms/pmac_pci.c b/arch/ppc/platforms/pmac_pci.c
new file mode 100644
index 0000000..f6ff519
--- /dev/null
+++ b/arch/ppc/platforms/pmac_pci.c
@@ -0,0 +1,1125 @@
+/*
+ * Support for PCI bridges found on Power Macintoshes.
+ * At present the "bandit" and "chaos" bridges are supported.
+ * Fortunately you access configuration space in the same
+ * way with either bridge.
+ *
+ * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#ifdef CONFIG_XMON
+extern void xmon_printf(const char *fmt, ...);
+#define DBG(x...) xmon_printf(x)
+#else
+#define DBG(x...) printk(x)
+#endif
+#else
+#define DBG(x...)
+#endif
+
+static int add_bridge(struct device_node *dev);
+extern void pmac_check_ht_link(void);
+
+/* XXX Could be per-controller, but I don't think we risk anything by
+ * assuming we won't have both UniNorth and Bandit */
+static int has_uninorth;
+#ifdef CONFIG_POWER4
+static struct pci_controller *u3_agp;
+#endif /* CONFIG_POWER4 */
+
+extern u8 pci_cache_line_size;
+extern int pcibios_assign_bus_offset;
+
+struct device_node *k2_skiplist[2];
+
+/*
+ * Magic constants for enabling cache coherency in the bandit/PSX bridge.
+ */
+#define BANDIT_DEVID_2	8
+#define BANDIT_REVID	3
+
+#define BANDIT_DEVNUM	11
+#define BANDIT_MAGIC	0x50
+#define BANDIT_COHERENT	0x40
+
+static int __init
+fixup_one_level_bus_range(struct device_node *node, int higher)
+{
+	for (; node != 0;node = node->sibling) {
+		int * bus_range;
+		unsigned int *class_code;
+		int len;
+
+		/* For PCI<->PCI bridges or CardBus bridges, we go down */
+		class_code = (unsigned int *) get_property(node, "class-code", NULL);
+		if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
+			continue;
+		bus_range = (int *) get_property(node, "bus-range", &len);
+		if (bus_range != NULL && len > 2 * sizeof(int)) {
+			if (bus_range[1] > higher)
+				higher = bus_range[1];
+		}
+		higher = fixup_one_level_bus_range(node->child, higher);
+	}
+	return higher;
+}
+
+/* This routine fixes the "bus-range" property of all bridges in the
+ * system since they tend to have their "last" member wrong on macs
+ *
+ * Note that the bus numbers manipulated here are OF bus numbers, they
+ * are not Linux bus numbers.
+ */
+static void __init
+fixup_bus_range(struct device_node *bridge)
+{
+	int * bus_range;
+	int len;
+
+	/* Lookup the "bus-range" property for the hose */
+	bus_range = (int *) get_property(bridge, "bus-range", &len);
+	if (bus_range == NULL || len < 2 * sizeof(int)) {
+		printk(KERN_WARNING "Can't get bus-range for %s\n",
+			       bridge->full_name);
+		return;
+	}
+	bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
+}
+
+/*
+ * Apple MacRISC (U3, UniNorth, Bandit, Chaos) PCI controllers.
+ *
+ * The "Bandit" version is present in all early PCI PowerMacs,
+ * and up to the first ones using Grackle. Some machines may
+ * have 2 bandit controllers (2 PCI busses).
+ *
+ * "Chaos" is used in some "Bandit"-type machines as a bridge
+ * for the separate display bus. It is accessed the same
+ * way as bandit, but cannot be probed for devices. It therefore
+ * has its own config access functions.
+ *
+ * The "UniNorth" version is present in all Core99 machines
+ * (iBook, G4, new IMacs, and all the recent Apple machines).
+ * It contains 3 controllers in one ASIC.
+ *
+ * The U3 is the bridge used on G5 machines. It contains an
+ * AGP bus which is dealt with the old UniNorth access routines
+ * and a HyperTransport bus which uses its own set of access
+ * functions.
+ */
+
+#define MACRISC_CFA0(devfn, off)	\
+	((1 << (unsigned long)PCI_SLOT(dev_fn)) \
+	| (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
+	| (((unsigned long)(off)) & 0xFCUL))
+
+#define MACRISC_CFA1(bus, devfn, off)	\
+	((((unsigned long)(bus)) << 16) \
+	|(((unsigned long)(devfn)) << 8) \
+	|(((unsigned long)(off)) & 0xFCUL) \
+	|1UL)
+
+static void volatile __iomem * __pmac
+macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset)
+{
+	unsigned int caddr;
+
+	if (bus == hose->first_busno) {
+		if (dev_fn < (11 << 3))
+			return NULL;
+		caddr = MACRISC_CFA0(dev_fn, offset);
+	} else
+		caddr = MACRISC_CFA1(bus, dev_fn, offset);
+
+	/* Uninorth will return garbage if we don't read back the value ! */
+	do {
+		out_le32(hose->cfg_addr, caddr);
+	} while (in_le32(hose->cfg_addr) != caddr);
+
+	offset &= has_uninorth ? 0x07 : 0x03;
+	return hose->cfg_data + offset;
+}
+
+static int __pmac
+macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		    int len, u32 *val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	void volatile __iomem *addr;
+
+	addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		*val = in_8(addr);
+		break;
+	case 2:
+		*val = in_le16(addr);
+		break;
+	default:
+		*val = in_le32(addr);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int __pmac
+macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		     int len, u32 val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	void volatile __iomem *addr;
+
+	addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		out_8(addr, val);
+		(void) in_8(addr);
+		break;
+	case 2:
+		out_le16(addr, val);
+		(void) in_le16(addr);
+		break;
+	default:
+		out_le32(addr, val);
+		(void) in_le32(addr);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops macrisc_pci_ops =
+{
+	macrisc_read_config,
+	macrisc_write_config
+};
+
+/*
+ * Verifiy that a specific (bus, dev_fn) exists on chaos
+ */
+static int __pmac
+chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
+{
+	struct device_node *np;
+	u32 *vendor, *device;
+
+	np = pci_busdev_to_OF_node(bus, devfn);
+	if (np == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	vendor = (u32 *)get_property(np, "vendor-id", NULL);
+	device = (u32 *)get_property(np, "device-id", NULL);
+	if (vendor == NULL || device == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if ((*vendor == 0x106b) && (*device == 3) && (offset >= 0x10)
+	    && (offset != 0x14) && (offset != 0x18) && (offset <= 0x24))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int __pmac
+chaos_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		  int len, u32 *val)
+{
+	int result = chaos_validate_dev(bus, devfn, offset);
+	if (result == PCIBIOS_BAD_REGISTER_NUMBER)
+		*val = ~0U;
+	if (result != PCIBIOS_SUCCESSFUL)
+		return result;
+	return macrisc_read_config(bus, devfn, offset, len, val);
+}
+
+static int __pmac
+chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		   int len, u32 val)
+{
+	int result = chaos_validate_dev(bus, devfn, offset);
+	if (result != PCIBIOS_SUCCESSFUL)
+		return result;
+	return macrisc_write_config(bus, devfn, offset, len, val);
+}
+
+static struct pci_ops chaos_pci_ops =
+{
+	chaos_read_config,
+	chaos_write_config
+};
+
+#ifdef CONFIG_POWER4
+
+/*
+ * These versions of U3 HyperTransport config space access ops do not
+ * implement self-view of the HT host yet
+ */
+
+#define U3_HT_CFA0(devfn, off)		\
+		((((unsigned long)devfn) << 8) | offset)
+#define U3_HT_CFA1(bus, devfn, off)	\
+		(U3_HT_CFA0(devfn, off) \
+		+ (((unsigned long)bus) << 16) \
+		+ 0x01000000UL)
+
+static void volatile __iomem * __pmac
+u3_ht_cfg_access(struct pci_controller* hose, u8 bus, u8 devfn, u8 offset)
+{
+	if (bus == hose->first_busno) {
+		/* For now, we don't self probe U3 HT bridge */
+		if (PCI_FUNC(devfn) != 0 || PCI_SLOT(devfn) > 7 ||
+		    PCI_SLOT(devfn) < 1)
+			return 0;
+		return hose->cfg_data + U3_HT_CFA0(devfn, offset);
+	} else
+		return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset);
+}
+
+static int __pmac
+u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		    int len, u32 *val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	void volatile __iomem *addr;
+	int i;
+
+	struct device_node *np = pci_busdev_to_OF_node(bus, devfn);
+	if (np == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/*
+	 * When a device in K2 is powered down, we die on config
+	 * cycle accesses. Fix that here.
+	 */
+	for (i=0; i<2; i++)
+		if (k2_skiplist[i] == np) {
+			switch (len) {
+			case 1:
+				*val = 0xff; break;
+			case 2:
+				*val = 0xffff; break;
+			default:
+				*val = 0xfffffffful; break;
+			}
+			return PCIBIOS_SUCCESSFUL;
+		}
+	    
+	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		*val = in_8(addr);
+		break;
+	case 2:
+		*val = in_le16(addr);
+		break;
+	default:
+		*val = in_le32(addr);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int __pmac
+u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		     int len, u32 val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	void volatile __iomem *addr;
+	int i;
+
+	struct device_node *np = pci_busdev_to_OF_node(bus, devfn);
+	if (np == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * When a device in K2 is powered down, we die on config
+	 * cycle accesses. Fix that here.
+	 */
+	for (i=0; i<2; i++)
+		if (k2_skiplist[i] == np)
+			return PCIBIOS_SUCCESSFUL;
+
+	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		out_8(addr, val);
+		(void) in_8(addr);
+		break;
+	case 2:
+		out_le16(addr, val);
+		(void) in_le16(addr);
+		break;
+	default:
+		out_le32(addr, val);
+		(void) in_le32(addr);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops u3_ht_pci_ops =
+{
+	u3_ht_read_config,
+	u3_ht_write_config
+};
+
+#endif /* CONFIG_POWER4 */
+
+/*
+ * For a bandit bridge, turn on cache coherency if necessary.
+ * N.B. we could clean this up using the hose ops directly.
+ */
+static void __init
+init_bandit(struct pci_controller *bp)
+{
+	unsigned int vendev, magic;
+	int rev;
+
+	/* read the word at offset 0 in config space for device 11 */
+	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);
+	udelay(2);
+	vendev = in_le32(bp->cfg_data);
+	if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) +
+			PCI_VENDOR_ID_APPLE) {
+		/* read the revision id */
+		out_le32(bp->cfg_addr,
+			 (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);
+		udelay(2);
+		rev = in_8(bp->cfg_data);
+		if (rev != BANDIT_REVID)
+			printk(KERN_WARNING
+			       "Unknown revision %d for bandit\n", rev);
+	} else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) {
+		printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);
+		return;
+	}
+
+	/* read the word at offset 0x50 */
+	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);
+	udelay(2);
+	magic = in_le32(bp->cfg_data);
+	if ((magic & BANDIT_COHERENT) != 0)
+		return;
+	magic |= BANDIT_COHERENT;
+	udelay(2);
+	out_le32(bp->cfg_data, magic);
+	printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n");
+}
+
+
+/*
+ * Tweak the PCI-PCI bridge chip on the blue & white G3s.
+ */
+static void __init
+init_p2pbridge(void)
+{
+	struct device_node *p2pbridge;
+	struct pci_controller* hose;
+	u8 bus, devfn;
+	u16 val;
+
+	/* XXX it would be better here to identify the specific
+	   PCI-PCI bridge chip we have. */
+	if ((p2pbridge = find_devices("pci-bridge")) == 0
+	    || p2pbridge->parent == NULL
+	    || strcmp(p2pbridge->parent->name, "pci") != 0)
+		return;
+	if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) {
+		DBG("Can't find PCI infos for PCI<->PCI bridge\n");
+		return;
+	}
+	/* Warning: At this point, we have not yet renumbered all busses.
+	 * So we must use OF walking to find out hose
+	 */
+	hose = pci_find_hose_for_OF_device(p2pbridge);
+	if (!hose) {
+		DBG("Can't find hose for PCI<->PCI bridge\n");
+		return;
+	}
+	if (early_read_config_word(hose, bus, devfn,
+				   PCI_BRIDGE_CONTROL, &val) < 0) {
+		printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n");
+		return;
+	}
+	val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;
+	early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);
+}
+
+/*
+ * Some Apple desktop machines have a NEC PD720100A USB2 controller
+ * on the motherboard. Open Firmware, on these, will disable the
+ * EHCI part of it so it behaves like a pair of OHCI's. This fixup
+ * code re-enables it ;)
+ */
+static void __init
+fixup_nec_usb2(void)
+{
+	struct device_node *nec;
+
+	for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) {
+		struct pci_controller *hose;
+		u32 data, *prop;
+		u8 bus, devfn;
+		
+		prop = (u32 *)get_property(nec, "vendor-id", NULL);
+		if (prop == NULL)
+			continue;
+		if (0x1033 != *prop)
+			continue;
+		prop = (u32 *)get_property(nec, "device-id", NULL);
+		if (prop == NULL)
+			continue;
+		if (0x0035 != *prop)
+			continue;
+		prop = (u32 *)get_property(nec, "reg", NULL);
+		if (prop == NULL)
+			continue;
+		devfn = (prop[0] >> 8) & 0xff;
+		bus = (prop[0] >> 16) & 0xff;
+		if (PCI_FUNC(devfn) != 0)
+			continue;
+		hose = pci_find_hose_for_OF_device(nec);
+		if (!hose)
+			continue;
+		early_read_config_dword(hose, bus, devfn, 0xe4, &data);
+		if (data & 1UL) {
+			printk("Found NEC PD720100A USB2 chip with disabled EHCI, fixing up...\n");
+			data &= ~1UL;
+			early_write_config_dword(hose, bus, devfn, 0xe4, data);
+			early_write_config_byte(hose, bus, devfn | 2, PCI_INTERRUPT_LINE,
+				nec->intrs[0].line);
+		}
+	}
+}
+
+void __init
+pmac_find_bridges(void)
+{
+	struct device_node *np, *root;
+	struct device_node *ht = NULL;
+
+	root = of_find_node_by_path("/");
+	if (root == NULL) {
+		printk(KERN_CRIT "pmac_find_bridges: can't find root of device tree\n");
+		return;
+	}
+	for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) {
+		if (np->name == NULL)
+			continue;
+		if (strcmp(np->name, "bandit") == 0
+		    || strcmp(np->name, "chaos") == 0
+		    || strcmp(np->name, "pci") == 0) {
+			if (add_bridge(np) == 0)
+				of_node_get(np);
+		}
+		if (strcmp(np->name, "ht") == 0) {
+			of_node_get(np);
+			ht = np;
+		}
+	}
+	of_node_put(root);
+
+	/* Probe HT last as it relies on the agp resources to be already
+	 * setup
+	 */
+	if (ht && add_bridge(ht) != 0)
+		of_node_put(ht);
+
+	init_p2pbridge();
+	fixup_nec_usb2();
+	
+	/* We are still having some issues with the Xserve G4, enabling
+	 * some offset between bus number and domains for now when we
+	 * assign all busses should help for now
+	 */
+	if (pci_assign_all_busses)
+		pcibios_assign_bus_offset = 0x10;
+
+#ifdef CONFIG_POWER4 
+	/* There is something wrong with DMA on U3/HT. I haven't figured out
+	 * the details yet, but if I set the cache line size to 128 bytes like
+	 * it should, I'm getting memory corruption caused by devices like
+	 * sungem (even without the MWI bit set, but maybe sungem doesn't
+	 * care). Right now, it appears that setting up a 64 bytes line size
+	 * works properly, 64 bytes beeing the max transfer size of HT, I
+	 * suppose this is related the way HT/PCI are hooked together. I still
+	 * need to dive into more specs though to be really sure of what's
+	 * going on. --BenH.
+	 *
+	 * Ok, apparently, it's just that HT can't do more than 64 bytes
+	 * transactions. MWI seem to be meaningless there as well, it may
+	 * be worth nop'ing out pci_set_mwi too though I haven't done that
+	 * yet.
+	 *
+	 * Note that it's a bit different for whatever is in the AGP slot.
+	 * For now, I don't care, but this can become a real issue, we
+	 * should probably hook pci_set_mwi anyway to make sure it sets
+	 * the real cache line size in there.
+	 */
+	if (machine_is_compatible("MacRISC4"))
+		pci_cache_line_size = 16; /* 64 bytes */
+
+	pmac_check_ht_link();
+#endif /* CONFIG_POWER4 */
+}
+
+#define GRACKLE_CFA(b, d, o)	(0x80 | ((b) << 8) | ((d) << 16) \
+				 | (((o) & ~3) << 24))
+
+#define GRACKLE_PICR1_STG		0x00000040
+#define GRACKLE_PICR1_LOOPSNOOP		0x00000010
+
+/* N.B. this is called before bridges is initialized, so we can't
+   use grackle_pcibios_{read,write}_config_dword. */
+static inline void grackle_set_stg(struct pci_controller* bp, int enable)
+{
+	unsigned int val;
+
+	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+	val = in_le32(bp->cfg_data);
+	val = enable? (val | GRACKLE_PICR1_STG) :
+		(val & ~GRACKLE_PICR1_STG);
+	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+	out_le32(bp->cfg_data, val);
+	(void)in_le32(bp->cfg_data);
+}
+
+static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable)
+{
+	unsigned int val;
+
+	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+	val = in_le32(bp->cfg_data);
+	val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) :
+		(val & ~GRACKLE_PICR1_LOOPSNOOP);
+	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+	out_le32(bp->cfg_data, val);
+	(void)in_le32(bp->cfg_data);
+}
+
+static int __init
+setup_uninorth(struct pci_controller* hose, struct reg_property* addr)
+{
+	pci_assign_all_busses = 1;
+	has_uninorth = 1;
+	hose->ops = &macrisc_pci_ops;
+	hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
+	hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
+	/* We "know" that the bridge at f2000000 has the PCI slots. */
+	return addr->address == 0xf2000000;
+}
+
+static void __init
+setup_bandit(struct pci_controller* hose, struct reg_property* addr)
+{
+	hose->ops = &macrisc_pci_ops;
+	hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
+	hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
+	init_bandit(hose);
+}
+
+static void __init
+setup_chaos(struct pci_controller* hose, struct reg_property* addr)
+{
+	/* assume a `chaos' bridge */
+	hose->ops = &chaos_pci_ops;
+	hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
+	hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
+}
+
+#ifdef CONFIG_POWER4
+
+static void __init
+setup_u3_agp(struct pci_controller* hose, struct reg_property* addr)
+{
+	/* On G5, we move AGP up to high bus number so we don't need
+	 * to reassign bus numbers for HT. If we ever have P2P bridges
+	 * on AGP, we'll have to move pci_assign_all_busses to the
+	 * pci_controller structure so we enable it for AGP and not for
+	 * HT childs.
+	 * We hard code the address because of the different size of
+	 * the reg address cell, we shall fix that by killing struct
+	 * reg_property and using some accessor functions instead
+	 */
+       	hose->first_busno = 0xf0;
+	hose->last_busno = 0xff;
+	has_uninorth = 1;
+	hose->ops = &macrisc_pci_ops;
+	hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
+	hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
+
+	u3_agp = hose;
+}
+
+static void __init
+setup_u3_ht(struct pci_controller* hose, struct reg_property *addr)
+{
+	struct device_node *np = (struct device_node *)hose->arch_data;
+	int i, cur;
+
+	hose->ops = &u3_ht_pci_ops;
+
+	/* We hard code the address because of the different size of
+	 * the reg address cell, we shall fix that by killing struct
+	 * reg_property and using some accessor functions instead
+	 */
+	hose->cfg_data = ioremap(0xf2000000, 0x02000000);
+
+	/*
+	 * /ht node doesn't expose a "ranges" property, so we "remove" regions that
+	 * have been allocated to AGP. So far, this version of the code doesn't assign
+	 * any of the 0xfxxxxxxx "fine" memory regions to /ht.
+	 * We need to fix that sooner or later by either parsing all child "ranges"
+	 * properties or figuring out the U3 address space decoding logic and
+	 * then read its configuration register (if any).
+	 */
+	hose->io_base_phys = 0xf4000000;
+	hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000);
+	isa_io_base = (unsigned long) hose->io_base_virt;
+	hose->io_resource.name = np->full_name;
+	hose->io_resource.start = 0;
+	hose->io_resource.end = 0x003fffff;
+	hose->io_resource.flags = IORESOURCE_IO;
+	hose->pci_mem_offset = 0;
+	hose->first_busno = 0;
+	hose->last_busno = 0xef;
+	hose->mem_resources[0].name = np->full_name;
+	hose->mem_resources[0].start = 0x80000000;
+	hose->mem_resources[0].end = 0xefffffff;
+	hose->mem_resources[0].flags = IORESOURCE_MEM;
+
+	if (u3_agp == NULL) {
+		DBG("U3 has no AGP, using full resource range\n");
+		return;
+	}
+
+	/* We "remove" the AGP resources from the resources allocated to HT, that
+	 * is we create "holes". However, that code does assumptions that so far
+	 * happen to be true (cross fingers...), typically that resources in the
+	 * AGP node are properly ordered
+	 */
+	cur = 0;
+	for (i=0; i<3; i++) {
+		struct resource *res = &u3_agp->mem_resources[i];
+		if (res->flags != IORESOURCE_MEM)
+			continue;
+		/* We don't care about "fine" resources */
+		if (res->start >= 0xf0000000)
+			continue;
+		/* Check if it's just a matter of "shrinking" us in one direction */
+		if (hose->mem_resources[cur].start == res->start) {
+			DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n",
+			    cur, hose->mem_resources[cur].start, res->end + 1);
+			hose->mem_resources[cur].start = res->end + 1;
+			continue;
+		}
+		if (hose->mem_resources[cur].end == res->end) {
+			DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n",
+			    cur, hose->mem_resources[cur].end, res->start - 1);
+			hose->mem_resources[cur].end = res->start - 1;
+			continue;
+		}
+		/* No, it's not the case, we need a hole */
+		if (cur == 2) {
+			/* not enough resources to make a hole, we drop part of the range */
+			printk(KERN_WARNING "Running out of resources for /ht host !\n");
+			hose->mem_resources[cur].end = res->start - 1;
+			continue;
+		}		
+		cur++;
+       		DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
+		    cur-1, res->start - 1, cur, res->end + 1);
+		hose->mem_resources[cur].name = np->full_name;
+		hose->mem_resources[cur].flags = IORESOURCE_MEM;
+		hose->mem_resources[cur].start = res->end + 1;
+		hose->mem_resources[cur].end = hose->mem_resources[cur-1].end;
+		hose->mem_resources[cur-1].end = res->start - 1;
+	}
+}
+
+#endif /* CONFIG_POWER4 */
+
+void __init
+setup_grackle(struct pci_controller *hose)
+{
+	setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
+	if (machine_is_compatible("AAPL,PowerBook1998"))
+		grackle_set_loop_snoop(hose, 1);
+#if 0	/* Disabled for now, HW problems ??? */
+	grackle_set_stg(hose, 1);
+#endif
+}
+
+/*
+ * We assume that if we have a G3 powermac, we have one bridge called
+ * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
+ * if we have one or more bandit or chaos bridges, we don't have a MPC106.
+ */
+static int __init
+add_bridge(struct device_node *dev)
+{
+	int len;
+	struct pci_controller *hose;
+	struct reg_property *addr;
+	char* disp_name;
+	int *bus_range;
+	int primary = 1;
+
+	DBG("Adding PCI host bridge %s\n", dev->full_name);
+
+       	addr = (struct reg_property *) get_property(dev, "reg", &len);
+       	if (addr == NULL || len < sizeof(*addr)) {
+       		printk(KERN_WARNING "Can't use %s: no address\n",
+       		       dev->full_name);
+       		return -ENODEV;
+       	}
+       	bus_range = (int *) get_property(dev, "bus-range", &len);
+       	if (bus_range == NULL || len < 2 * sizeof(int)) {
+       		printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
+       			       dev->full_name);
+       	}
+
+       	hose = pcibios_alloc_controller();
+       	if (!hose)
+       		return -ENOMEM;
+       	hose->arch_data = dev;
+       	hose->first_busno = bus_range ? bus_range[0] : 0;
+       	hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+	disp_name = NULL;
+#ifdef CONFIG_POWER4
+       	if (device_is_compatible(dev, "u3-agp")) {
+       		setup_u3_agp(hose, addr);
+       		disp_name = "U3-AGP";
+       		primary = 0;
+       	} else if (device_is_compatible(dev, "u3-ht")) {
+       		setup_u3_ht(hose, addr);
+       		disp_name = "U3-HT";
+       		primary = 1;
+       	} else
+#endif /* CONFIG_POWER4 */
+	if (device_is_compatible(dev, "uni-north")) {
+       		primary = setup_uninorth(hose, addr);
+       		disp_name = "UniNorth";
+       	} else if (strcmp(dev->name, "pci") == 0) {
+       		/* XXX assume this is a mpc106 (grackle) */
+       		setup_grackle(hose);
+       		disp_name = "Grackle (MPC106)";
+       	} else if (strcmp(dev->name, "bandit") == 0) {
+       		setup_bandit(hose, addr);
+       		disp_name = "Bandit";
+       	} else if (strcmp(dev->name, "chaos") == 0) {
+       		setup_chaos(hose, addr);
+       		disp_name = "Chaos";
+       		primary = 0;
+       	}
+       	printk(KERN_INFO "Found %s PCI host bridge at 0x%08x. Firmware bus number: %d->%d\n",
+       		disp_name, addr->address, hose->first_busno, hose->last_busno);
+       	DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
+       		hose, hose->cfg_addr, hose->cfg_data);
+
+       	/* Interpret the "ranges" property */
+       	/* This also maps the I/O region and sets isa_io/mem_base */
+       	pci_process_bridge_OF_ranges(hose, dev, primary);
+
+       	/* Fixup "bus-range" OF property */
+       	fixup_bus_range(dev);
+
+	return 0;
+}
+
+static void __init
+pcibios_fixup_OF_interrupts(void)
+{
+	struct pci_dev* dev = NULL;
+
+	/*
+	 * Open Firmware often doesn't initialize the
+	 * PCI_INTERRUPT_LINE config register properly, so we
+	 * should find the device node and apply the interrupt
+	 * obtained from the OF device-tree
+	 */
+	for_each_pci_dev(dev) {
+		struct device_node *node;
+		node = pci_device_to_OF_node(dev);
+		/* this is the node, see if it has interrupts */
+		if (node && node->n_intrs > 0)
+			dev->irq = node->intrs[0].line;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+	}
+}
+
+void __init
+pmac_pcibios_fixup(void)
+{
+	/* Fixup interrupts according to OF tree */
+	pcibios_fixup_OF_interrupts();
+}
+
+int __pmac
+pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
+{
+	struct device_node* node;
+	int updatecfg = 0;
+	int uninorth_child;
+
+	node = pci_device_to_OF_node(dev);
+
+	/* We don't want to enable USB controllers absent from the OF tree
+	 * (iBook second controller)
+	 */
+	if (dev->vendor == PCI_VENDOR_ID_APPLE
+	    && (dev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10))
+	    && !node) {
+		printk(KERN_INFO "Apple USB OHCI %s disabled by firmware\n",
+		       pci_name(dev));
+		return -EINVAL;
+	}
+
+	if (!node)
+		return 0;
+
+	uninorth_child = node->parent &&
+		device_is_compatible(node->parent, "uni-north");
+	
+	/* Firewire & GMAC were disabled after PCI probe, the driver is
+	 * claiming them, we must re-enable them now.
+	 */
+	if (uninorth_child && !strcmp(node->name, "firewire") &&
+	    (device_is_compatible(node, "pci106b,18") ||
+	     device_is_compatible(node, "pci106b,30") ||
+	     device_is_compatible(node, "pci11c1,5811"))) {
+		pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1);
+		pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1);
+		updatecfg = 1;
+	}
+	if (uninorth_child && !strcmp(node->name, "ethernet") &&
+	    device_is_compatible(node, "gmac")) {
+		pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1);
+		updatecfg = 1;
+	}
+
+	if (updatecfg) {
+		u16 cmd;
+	
+		/*
+		 * Make sure PCI is correctly configured
+		 *
+		 * We use old pci_bios versions of the function since, by
+		 * default, gmac is not powered up, and so will be absent
+		 * from the kernel initial PCI lookup.
+		 *
+		 * Should be replaced by 2.4 new PCI mechanisms and really
+		 * register the device.
+		 */
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
+    		pci_write_config_word(dev, PCI_COMMAND, cmd);
+    		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16);
+    		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cache_line_size);
+	}
+
+	return 0;
+}
+
+/* We power down some devices after they have been probed. They'll
+ * be powered back on later on
+ */
+void __init
+pmac_pcibios_after_init(void)
+{
+	struct device_node* nd;
+
+#ifdef CONFIG_BLK_DEV_IDE
+	struct pci_dev *dev = NULL;
+
+	/* OF fails to initialize IDE controllers on macs
+	 * (and maybe other machines)
+	 *
+	 * Ideally, this should be moved to the IDE layer, but we need
+	 * to check specifically with Andre Hedrick how to do it cleanly
+	 * since the common IDE code seem to care about the fact that the
+	 * BIOS may have disabled a controller.
+	 *
+	 * -- BenH
+	 */
+	for_each_pci_dev(dev) {
+		if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)
+			pci_enable_device(dev);
+	}
+#endif /* CONFIG_BLK_DEV_IDE */
+
+	nd = find_devices("firewire");
+	while (nd) {
+		if (nd->parent && (device_is_compatible(nd, "pci106b,18") ||
+				   device_is_compatible(nd, "pci106b,30") ||
+				   device_is_compatible(nd, "pci11c1,5811"))
+		    && device_is_compatible(nd->parent, "uni-north")) {
+			pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0);
+			pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0);
+		}
+		nd = nd->next;
+	}
+	nd = find_devices("ethernet");
+	while (nd) {
+		if (nd->parent && device_is_compatible(nd, "gmac")
+		    && device_is_compatible(nd->parent, "uni-north"))
+			pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0);
+		nd = nd->next;
+	}
+}
+
+void pmac_pci_fixup_cardbus(struct pci_dev* dev)
+{
+	if (_machine != _MACH_Pmac)
+		return;
+	/*
+	 * Fix the interrupt routing on the various cardbus bridges
+	 * used on powerbooks
+	 */
+	if (dev->vendor != PCI_VENDOR_ID_TI)
+		return;
+	if (dev->device == PCI_DEVICE_ID_TI_1130 ||
+	    dev->device == PCI_DEVICE_ID_TI_1131) {
+		u8 val;
+	    	/* Enable PCI interrupt */
+		if (pci_read_config_byte(dev, 0x91, &val) == 0)
+			pci_write_config_byte(dev, 0x91, val | 0x30);
+		/* Disable ISA interrupt mode */
+		if (pci_read_config_byte(dev, 0x92, &val) == 0)
+			pci_write_config_byte(dev, 0x92, val & ~0x06);
+	}
+	if (dev->device == PCI_DEVICE_ID_TI_1210 ||
+	    dev->device == PCI_DEVICE_ID_TI_1211 ||
+	    dev->device == PCI_DEVICE_ID_TI_1410 ||
+	    dev->device == PCI_DEVICE_ID_TI_1510) {
+		u8 val;
+		/* 0x8c == TI122X_IRQMUX, 2 says to route the INTA
+		   signal out the MFUNC0 pin */
+		if (pci_read_config_byte(dev, 0x8c, &val) == 0)
+			pci_write_config_byte(dev, 0x8c, (val & ~0x0f) | 2);
+		/* Disable ISA interrupt mode */
+		if (pci_read_config_byte(dev, 0x92, &val) == 0)
+			pci_write_config_byte(dev, 0x92, val & ~0x06);
+	}
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_ANY_ID, pmac_pci_fixup_cardbus);
+
+void pmac_pci_fixup_pciata(struct pci_dev* dev)
+{
+       u8 progif = 0;
+
+       /*
+        * On PowerMacs, we try to switch any PCI ATA controller to
+	* fully native mode
+        */
+	if (_machine != _MACH_Pmac)
+		return;
+	/* Some controllers don't have the class IDE */
+	if (dev->vendor == PCI_VENDOR_ID_PROMISE)
+		switch(dev->device) {
+		case PCI_DEVICE_ID_PROMISE_20246:
+		case PCI_DEVICE_ID_PROMISE_20262:
+		case PCI_DEVICE_ID_PROMISE_20263:
+		case PCI_DEVICE_ID_PROMISE_20265:
+		case PCI_DEVICE_ID_PROMISE_20267:
+		case PCI_DEVICE_ID_PROMISE_20268:
+		case PCI_DEVICE_ID_PROMISE_20269:
+		case PCI_DEVICE_ID_PROMISE_20270:
+		case PCI_DEVICE_ID_PROMISE_20271:
+		case PCI_DEVICE_ID_PROMISE_20275:
+		case PCI_DEVICE_ID_PROMISE_20276:
+		case PCI_DEVICE_ID_PROMISE_20277:
+			goto good;
+		}
+	/* Others, check PCI class */
+	if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
+		return;
+ good:
+	pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
+	if ((progif & 5) != 5) {
+		printk(KERN_INFO "Forcing PCI IDE into native mode: %s\n", pci_name(dev));
+		(void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
+		if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
+		    (progif & 5) != 5)
+			printk(KERN_ERR "Rewrite of PROGIF failed !\n");
+	}
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata);
+
+
+/*
+ * Disable second function on K2-SATA, it's broken
+ * and disable IO BARs on first one
+ */
+void __pmac pmac_pci_fixup_k2_sata(struct pci_dev* dev)
+{
+	int i;
+	u16 cmd;
+
+	if (PCI_FUNC(dev->devfn) > 0) {
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+		for (i = 0; i < 6; i++) {
+			dev->resource[i].start = dev->resource[i].end = 0;
+			dev->resource[i].flags = 0;
+			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);
+		}
+	} else {
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		cmd &= ~PCI_COMMAND_IO;
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+		for (i = 0; i < 5; i++) {
+			dev->resource[i].start = dev->resource[i].end = 0;
+			dev->resource[i].flags = 0;
+			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);
+		}
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, pmac_pci_fixup_k2_sata);
diff --git a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c
new file mode 100644
index 0000000..9f92e1b
--- /dev/null
+++ b/arch/ppc/platforms/pmac_pic.c
@@ -0,0 +1,689 @@
+/*
+ *  Support for the interrupt controllers found on Power Macintosh,
+ *  currently Apple's "Grand Central" interrupt controller in all
+ *  it's incarnations. OpenPIC support used on newer machines is
+ *  in a separate file
+ *
+ *  Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ *  Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *
+ *  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/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/time.h>
+#include <asm/open_pic.h>
+#include <asm/xmon.h>
+#include <asm/pmac_feature.h>
+
+#include "pmac_pic.h"
+
+/*
+ * XXX this should be in xmon.h, but putting it there means xmon.h
+ * has to include <linux/interrupt.h> (to get irqreturn_t), which
+ * causes all sorts of problems.  -- paulus
+ */
+extern irqreturn_t xmon_irq(int, void *, struct pt_regs *);
+
+struct pmac_irq_hw {
+        unsigned int    event;
+        unsigned int    enable;
+        unsigned int    ack;
+        unsigned int    level;
+};
+
+/* Default addresses */
+static volatile struct pmac_irq_hw *pmac_irq_hw[4] __pmacdata = {
+        (struct pmac_irq_hw *) 0xf3000020,
+        (struct pmac_irq_hw *) 0xf3000010,
+        (struct pmac_irq_hw *) 0xf4000020,
+        (struct pmac_irq_hw *) 0xf4000010,
+};
+
+#define GC_LEVEL_MASK		0x3ff00000
+#define OHARE_LEVEL_MASK	0x1ff00000
+#define HEATHROW_LEVEL_MASK	0x1ff00000
+
+static int max_irqs __pmacdata;
+static int max_real_irqs __pmacdata;
+static u32 level_mask[4] __pmacdata;
+
+static DEFINE_SPINLOCK(pmac_pic_lock __pmacdata);
+
+
+#define GATWICK_IRQ_POOL_SIZE        10
+static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE] __pmacdata;
+
+/*
+ * Mark an irq as "lost".  This is only used on the pmac
+ * since it can lose interrupts (see pmac_set_irq_mask).
+ * -- Cort
+ */
+void __pmac
+__set_lost(unsigned long irq_nr, int nokick)
+{
+	if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
+		atomic_inc(&ppc_n_lost_interrupts);
+		if (!nokick)
+			set_dec(1);
+	}
+}
+
+static void __pmac
+pmac_mask_and_ack_irq(unsigned int irq_nr)
+{
+        unsigned long bit = 1UL << (irq_nr & 0x1f);
+        int i = irq_nr >> 5;
+        unsigned long flags;
+
+        if ((unsigned)irq_nr >= max_irqs)
+                return;
+
+        clear_bit(irq_nr, ppc_cached_irq_mask);
+        if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))
+                atomic_dec(&ppc_n_lost_interrupts);
+	spin_lock_irqsave(&pmac_pic_lock, flags);
+        out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
+        out_le32(&pmac_irq_hw[i]->ack, bit);
+        do {
+                /* make sure ack gets to controller before we enable
+                   interrupts */
+                mb();
+        } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
+                != (ppc_cached_irq_mask[i] & bit));
+	spin_unlock_irqrestore(&pmac_pic_lock, flags);
+}
+
+static void __pmac pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
+{
+        unsigned long bit = 1UL << (irq_nr & 0x1f);
+        int i = irq_nr >> 5;
+        unsigned long flags;
+
+        if ((unsigned)irq_nr >= max_irqs)
+                return;
+
+	spin_lock_irqsave(&pmac_pic_lock, flags);
+        /* enable unmasked interrupts */
+        out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
+
+        do {
+                /* make sure mask gets to controller before we
+                   return to user */
+                mb();
+        } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
+                != (ppc_cached_irq_mask[i] & bit));
+
+        /*
+         * Unfortunately, setting the bit in the enable register
+         * when the device interrupt is already on *doesn't* set
+         * the bit in the flag register or request another interrupt.
+         */
+        if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level))
+		__set_lost((ulong)irq_nr, nokicklost);
+	spin_unlock_irqrestore(&pmac_pic_lock, flags);
+}
+
+/* When an irq gets requested for the first client, if it's an
+ * edge interrupt, we clear any previous one on the controller
+ */
+static unsigned int __pmac pmac_startup_irq(unsigned int irq_nr)
+{
+        unsigned long bit = 1UL << (irq_nr & 0x1f);
+        int i = irq_nr >> 5;
+
+	if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0)
+		out_le32(&pmac_irq_hw[i]->ack, bit);
+        set_bit(irq_nr, ppc_cached_irq_mask);
+        pmac_set_irq_mask(irq_nr, 0);
+
+	return 0;
+}
+
+static void __pmac pmac_mask_irq(unsigned int irq_nr)
+{
+        clear_bit(irq_nr, ppc_cached_irq_mask);
+        pmac_set_irq_mask(irq_nr, 0);
+        mb();
+}
+
+static void __pmac pmac_unmask_irq(unsigned int irq_nr)
+{
+        set_bit(irq_nr, ppc_cached_irq_mask);
+        pmac_set_irq_mask(irq_nr, 0);
+}
+
+static void __pmac pmac_end_irq(unsigned int irq_nr)
+{
+	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
+	    && irq_desc[irq_nr].action) {
+        	set_bit(irq_nr, ppc_cached_irq_mask);
+	        pmac_set_irq_mask(irq_nr, 1);
+	}
+}
+
+
+struct hw_interrupt_type pmac_pic = {
+	.typename	= " PMAC-PIC ",
+	.startup	= pmac_startup_irq,
+	.enable		= pmac_unmask_irq,
+	.disable	= pmac_mask_irq,
+	.ack		= pmac_mask_and_ack_irq,
+	.end		= pmac_end_irq,
+};
+
+struct hw_interrupt_type gatwick_pic = {
+	.typename	= " GATWICK  ",
+	.startup	= pmac_startup_irq,
+	.enable		= pmac_unmask_irq,
+	.disable	= pmac_mask_irq,
+	.ack		= pmac_mask_and_ack_irq,
+	.end		= pmac_end_irq,
+};
+
+static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+	int irq, bits;
+
+	for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
+		int i = irq >> 5;
+		bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
+		/* We must read level interrupts from the level register */
+		bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);
+		bits &= ppc_cached_irq_mask[i];
+		if (bits == 0)
+			continue;
+		irq += __ilog2(bits);
+		__do_IRQ(irq, regs);
+		return IRQ_HANDLED;
+	}
+	printk("gatwick irq not from gatwick pic\n");
+	return IRQ_NONE;
+}
+
+int
+pmac_get_irq(struct pt_regs *regs)
+{
+	int irq;
+	unsigned long bits = 0;
+
+#ifdef CONFIG_SMP
+	void psurge_smp_message_recv(struct pt_regs *);
+
+       	/* IPI's are a hack on the powersurge -- Cort */
+       	if ( smp_processor_id() != 0 ) {
+		psurge_smp_message_recv(regs);
+		return -2;	/* ignore, already handled */
+        }
+#endif /* CONFIG_SMP */
+	for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
+		int i = irq >> 5;
+		bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
+		/* We must read level interrupts from the level register */
+		bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);
+		bits &= ppc_cached_irq_mask[i];
+		if (bits == 0)
+			continue;
+		irq += __ilog2(bits);
+		break;
+	}
+
+	return irq;
+}
+
+/* This routine will fix some missing interrupt values in the device tree
+ * on the gatwick mac-io controller used by some PowerBooks
+ */
+static void __init
+pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
+{
+	struct device_node *node;
+	int count;
+
+	memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool));
+	node = gw->child;
+	count = 0;
+	while(node)
+	{
+		/* Fix SCC */
+		if (strcasecmp(node->name, "escc") == 0)
+			if (node->child) {
+				if (node->child->n_intrs < 3) {
+					node->child->intrs = &gatwick_int_pool[count];
+					count += 3;
+				}
+				node->child->n_intrs = 3;
+				node->child->intrs[0].line = 15+irq_base;
+				node->child->intrs[1].line =  4+irq_base;
+				node->child->intrs[2].line =  5+irq_base;
+				printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n",
+					node->child->intrs[0].line,
+					node->child->intrs[1].line,
+					node->child->intrs[2].line);
+			}
+		/* Fix media-bay & left SWIM */
+		if (strcasecmp(node->name, "media-bay") == 0) {
+			struct device_node* ya_node;
+
+			if (node->n_intrs == 0)
+				node->intrs = &gatwick_int_pool[count++];
+			node->n_intrs = 1;
+			node->intrs[0].line = 29+irq_base;
+			printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",
+					node->intrs[0].line);
+
+			ya_node = node->child;
+			while(ya_node)
+			{
+				if (strcasecmp(ya_node->name, "floppy") == 0) {
+					if (ya_node->n_intrs < 2) {
+						ya_node->intrs = &gatwick_int_pool[count];
+						count += 2;
+					}
+					ya_node->n_intrs = 2;
+					ya_node->intrs[0].line = 19+irq_base;
+					ya_node->intrs[1].line =  1+irq_base;
+					printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",
+						ya_node->intrs[0].line, ya_node->intrs[1].line);
+				}
+				if (strcasecmp(ya_node->name, "ata4") == 0) {
+					if (ya_node->n_intrs < 2) {
+						ya_node->intrs = &gatwick_int_pool[count];
+						count += 2;
+					}
+					ya_node->n_intrs = 2;
+					ya_node->intrs[0].line = 14+irq_base;
+					ya_node->intrs[1].line =  3+irq_base;
+					printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n",
+						ya_node->intrs[0].line, ya_node->intrs[1].line);
+				}
+				ya_node = ya_node->sibling;
+			}
+		}
+		node = node->sibling;
+	}
+	if (count > 10) {
+		printk("WARNING !! Gatwick interrupt pool overflow\n");
+		printk("  GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE);
+		printk("              requested = %d\n", count);
+	}
+}
+
+/*
+ * The PowerBook 3400/2400/3500 can have a combo ethernet/modem
+ * card which includes an ohare chip that acts as a second interrupt
+ * controller.  If we find this second ohare, set it up and fix the
+ * interrupt value in the device tree for the ethernet chip.
+ */
+static int __init enable_second_ohare(void)
+{
+	unsigned char bus, devfn;
+	unsigned short cmd;
+        unsigned long addr;
+	struct device_node *irqctrler = find_devices("pci106b,7");
+	struct device_node *ether;
+
+	if (irqctrler == NULL || irqctrler->n_addrs <= 0)
+		return -1;
+	addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40);
+	pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20);
+	max_irqs = 64;
+	if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) {
+		struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler);
+		if (!hose)
+		    printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");
+		else {
+		    early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);
+		    cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+	  	    cmd &= ~PCI_COMMAND_IO;
+		    early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);
+		}
+	}
+
+	/* Fix interrupt for the modem/ethernet combo controller. The number
+	   in the device tree (27) is bogus (correct for the ethernet-only
+	   board but not the combo ethernet/modem board).
+	   The real interrupt is 28 on the second controller -> 28+32 = 60.
+	*/
+	ether = find_devices("pci1011,14");
+	if (ether && ether->n_intrs > 0) {
+		ether->intrs[0].line = 60;
+		printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n",
+		       ether->intrs[0].line);
+	}
+
+	/* Return the interrupt number of the cascade */
+	return irqctrler->intrs[0].line;
+}
+
+#ifdef CONFIG_POWER4
+static irqreturn_t k2u3_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+	int irq;
+
+	irq = openpic2_get_irq(regs);
+	if (irq != -1)
+		__do_IRQ(irq, regs);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction k2u3_cascade_action = {
+	.handler	= k2u3_action,
+	.flags		= 0,
+	.mask		= CPU_MASK_NONE,
+	.name		= "U3->K2 Cascade",
+};
+#endif /* CONFIG_POWER4 */
+
+#ifdef CONFIG_XMON
+static struct irqaction xmon_action = {
+	.handler	= xmon_irq,
+	.flags		= 0,
+	.mask		= CPU_MASK_NONE,
+	.name		= "NMI - XMON"
+};
+#endif
+
+static struct irqaction gatwick_cascade_action = {
+	.handler	= gatwick_action,
+	.flags		= SA_INTERRUPT,
+	.mask		= CPU_MASK_NONE,
+	.name		= "cascade",
+};
+
+void __init pmac_pic_init(void)
+{
+        int i;
+        struct device_node *irqctrler  = NULL;
+        struct device_node *irqctrler2 = NULL;
+	struct device_node *np;
+        unsigned long addr;
+	int irq_cascade = -1;
+
+	/* We first try to detect Apple's new Core99 chipset, since mac-io
+	 * is quite different on those machines and contains an IBM MPIC2.
+	 */
+	np = find_type_devices("open-pic");
+	while(np) {
+		if (np->parent && !strcmp(np->parent->name, "u3"))
+			irqctrler2 = np;
+		else
+			irqctrler = np;
+		np = np->next;
+	}
+	if (irqctrler != NULL)
+	{
+		if (irqctrler->n_addrs > 0)
+		{
+			unsigned char senses[128];
+
+			printk(KERN_INFO "PowerMac using OpenPIC irq controller at 0x%08x\n",
+			       irqctrler->addrs[0].address);
+
+			prom_get_irq_senses(senses, 0, 128);
+			OpenPIC_InitSenses = senses;
+			OpenPIC_NumInitSenses = 128;
+			ppc_md.get_irq = openpic_get_irq;
+			pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler, 0, 0);
+			OpenPIC_Addr = ioremap(irqctrler->addrs[0].address,
+					       irqctrler->addrs[0].size);
+			openpic_init(0);
+
+#ifdef CONFIG_POWER4
+			if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 &&
+			    irqctrler2->n_addrs > 0) {
+				printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n",
+				       irqctrler2->addrs[0].address,
+				       irqctrler2->intrs[0].line);
+				pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0);
+				OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address,
+							irqctrler2->addrs[0].size);
+				prom_get_irq_senses(senses, PMAC_OPENPIC2_OFFSET,
+						    PMAC_OPENPIC2_OFFSET+128);
+				OpenPIC_InitSenses = senses;
+				OpenPIC_NumInitSenses = 128;
+				openpic2_init(PMAC_OPENPIC2_OFFSET);
+
+				if (setup_irq(irqctrler2->intrs[0].line,
+					      &k2u3_cascade_action))
+					printk("Unable to get OpenPIC IRQ for cascade\n");
+			}
+#endif /* CONFIG_POWER4 */
+
+#ifdef CONFIG_XMON
+			{
+				struct device_node* pswitch;
+				int nmi_irq;
+
+				pswitch = find_devices("programmer-switch");
+				if (pswitch && pswitch->n_intrs) {
+					nmi_irq = pswitch->intrs[0].line;
+					openpic_init_nmi_irq(nmi_irq);
+					setup_irq(nmi_irq, &xmon_action);
+				}
+			}
+#endif	/* CONFIG_XMON */
+			return;
+		}
+		irqctrler = NULL;
+	}
+
+	/* Get the level/edge settings, assume if it's not
+	 * a Grand Central nor an OHare, then it's an Heathrow
+	 * (or Paddington).
+	 */
+	if (find_devices("gc"))
+		level_mask[0] = GC_LEVEL_MASK;
+	else if (find_devices("ohare")) {
+		level_mask[0] = OHARE_LEVEL_MASK;
+		/* We might have a second cascaded ohare */
+		level_mask[1] = OHARE_LEVEL_MASK;
+	} else {
+		level_mask[0] = HEATHROW_LEVEL_MASK;
+		level_mask[1] = 0;
+		/* We might have a second cascaded heathrow */
+		level_mask[2] = HEATHROW_LEVEL_MASK;
+		level_mask[3] = 0;
+	}
+
+	/*
+	 * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts,
+	 * 1998 G3 Series PowerBooks have 128,
+	 * other powermacs have 32.
+	 * The combo ethernet/modem card for the Powerstar powerbooks
+	 * (2400/3400/3500, ohare based) has a second ohare chip
+	 * effectively making a total of 64.
+	 */
+	max_irqs = max_real_irqs = 32;
+	irqctrler = find_devices("mac-io");
+	if (irqctrler)
+	{
+		max_real_irqs = 64;
+		if (irqctrler->next)
+			max_irqs = 128;
+		else
+			max_irqs = 64;
+	}
+	for ( i = 0; i < max_real_irqs ; i++ )
+		irq_desc[i].handler = &pmac_pic;
+
+	/* get addresses of first controller */
+	if (irqctrler) {
+		if  (irqctrler->n_addrs > 0) {
+			addr = (unsigned long)
+				ioremap(irqctrler->addrs[0].address, 0x40);
+			for (i = 0; i < 2; ++i)
+				pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
+					(addr + (2 - i) * 0x10);
+		}
+
+		/* get addresses of second controller */
+		irqctrler = irqctrler->next;
+		if (irqctrler && irqctrler->n_addrs > 0) {
+			addr = (unsigned long)
+				ioremap(irqctrler->addrs[0].address, 0x40);
+			for (i = 2; i < 4; ++i)
+				pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
+					(addr + (4 - i) * 0x10);
+			irq_cascade = irqctrler->intrs[0].line;
+			if (device_is_compatible(irqctrler, "gatwick"))
+				pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
+		}
+	} else {
+		/* older powermacs have a GC (grand central) or ohare at
+		   f3000000, with interrupt control registers at f3000020. */
+		addr = (unsigned long) ioremap(0xf3000000, 0x40);
+		pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20);
+	}
+
+	/* PowerBooks 3400 and 3500 can have a second controller in a second
+	   ohare chip, on the combo ethernet/modem card */
+	if (machine_is_compatible("AAPL,3400/2400")
+	     || machine_is_compatible("AAPL,3500"))
+		irq_cascade = enable_second_ohare();
+
+	/* disable all interrupts in all controllers */
+	for (i = 0; i * 32 < max_irqs; ++i)
+		out_le32(&pmac_irq_hw[i]->enable, 0);
+	/* mark level interrupts */
+	for (i = 0; i < max_irqs; i++)
+		if (level_mask[i >> 5] & (1UL << (i & 0x1f)))
+			irq_desc[i].status = IRQ_LEVEL;
+
+	/* get interrupt line of secondary interrupt controller */
+	if (irq_cascade >= 0) {
+		printk(KERN_INFO "irq: secondary controller on irq %d\n",
+			(int)irq_cascade);
+		for ( i = max_real_irqs ; i < max_irqs ; i++ )
+			irq_desc[i].handler = &gatwick_pic;
+		setup_irq(irq_cascade, &gatwick_cascade_action);
+	}
+	printk("System has %d possible interrupts\n", max_irqs);
+	if (max_irqs != max_real_irqs)
+		printk(KERN_DEBUG "%d interrupts on main controller\n",
+			max_real_irqs);
+
+#ifdef CONFIG_XMON
+	setup_irq(20, &xmon_action);
+#endif	/* CONFIG_XMON */
+}
+
+#ifdef CONFIG_PM
+/*
+ * These procedures are used in implementing sleep on the powerbooks.
+ * sleep_save_intrs() saves the states of all interrupt enables
+ * and disables all interrupts except for the nominated one.
+ * sleep_restore_intrs() restores the states of all interrupt enables.
+ */
+unsigned long sleep_save_mask[2];
+
+/* This used to be passed by the PMU driver but that link got
+ * broken with the new driver model. We use this tweak for now...
+ */
+static int pmacpic_find_viaint(void)
+{
+	int viaint = -1;
+
+#ifdef CONFIG_ADB_PMU
+	struct device_node *np;
+
+	if (pmu_get_model() != PMU_OHARE_BASED)
+		goto not_found;
+	np = of_find_node_by_name(NULL, "via-pmu");
+	if (np == NULL)
+		goto not_found;
+	viaint = np->intrs[0].line;
+#endif /* CONFIG_ADB_PMU */
+
+not_found:
+	return viaint;
+}
+
+static int pmacpic_suspend(struct sys_device *sysdev, u32 state)
+{
+	int viaint = pmacpic_find_viaint();
+
+	sleep_save_mask[0] = ppc_cached_irq_mask[0];
+	sleep_save_mask[1] = ppc_cached_irq_mask[1];
+	ppc_cached_irq_mask[0] = 0;
+	ppc_cached_irq_mask[1] = 0;
+	if (viaint > 0)
+		set_bit(viaint, ppc_cached_irq_mask);
+	out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]);
+	if (max_real_irqs > 32)
+		out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);
+	(void)in_le32(&pmac_irq_hw[0]->event);
+	/* make sure mask gets to controller before we return to caller */
+	mb();
+        (void)in_le32(&pmac_irq_hw[0]->enable);
+
+        return 0;
+}
+
+static int pmacpic_resume(struct sys_device *sysdev)
+{
+	int i;
+
+	out_le32(&pmac_irq_hw[0]->enable, 0);
+	if (max_real_irqs > 32)
+		out_le32(&pmac_irq_hw[1]->enable, 0);
+	mb();
+	for (i = 0; i < max_real_irqs; ++i)
+		if (test_bit(i, sleep_save_mask))
+			pmac_unmask_irq(i);
+
+	return 0;
+}
+
+#endif /* CONFIG_PM */
+
+static struct sysdev_class pmacpic_sysclass = {
+	set_kset_name("pmac_pic"),
+};
+
+static struct sys_device device_pmacpic = {
+	.id		= 0,
+	.cls		= &pmacpic_sysclass,
+};
+
+static struct sysdev_driver driver_pmacpic = {
+#ifdef CONFIG_PM
+	.suspend	= &pmacpic_suspend,
+	.resume		= &pmacpic_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init init_pmacpic_sysfs(void)
+{
+	if (max_irqs == 0)
+		return -ENODEV;
+
+	printk(KERN_DEBUG "Registering pmac pic with sysfs...\n");
+	sysdev_class_register(&pmacpic_sysclass);
+	sysdev_register(&device_pmacpic);
+	sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic);
+	return 0;
+}
+
+subsys_initcall(init_pmacpic_sysfs);
+
diff --git a/arch/ppc/platforms/pmac_pic.h b/arch/ppc/platforms/pmac_pic.h
new file mode 100644
index 0000000..664103d
--- /dev/null
+++ b/arch/ppc/platforms/pmac_pic.h
@@ -0,0 +1,11 @@
+#ifndef __PPC_PLATFORMS_PMAC_PIC_H
+#define __PPC_PLATFORMS_PMAC_PIC_H
+
+#include <linux/irq.h>
+
+extern struct hw_interrupt_type pmac_pic;
+
+void pmac_pic_init(void);
+int pmac_get_irq(struct pt_regs *regs);
+
+#endif /* __PPC_PLATFORMS_PMAC_PIC_H */
diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c
new file mode 100644
index 0000000..4d324b6
--- /dev/null
+++ b/arch/ppc/platforms/pmac_setup.c
@@ -0,0 +1,745 @@
+/*
+ *  arch/ppc/platforms/setup.c
+ *
+ *  PowerPC version
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ *  Adapted for Power Macintosh by Paul Mackerras
+ *    Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ *  Derived from "arch/alpha/kernel/setup.c"
+ *    Copyright (C) 1995 Linus Torvalds
+ *
+ *  Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *
+ *  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.
+ *
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/vt_kern.h>
+#include <linux/console.h>
+#include <linux/ide.h>
+#include <linux/pci.h>
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <linux/pmu.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/bitops.h>
+#include <linux/suspend.h>
+
+#include <asm/reg.h>
+#include <asm/sections.h>
+#include <asm/prom.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/ohare.h>
+#include <asm/mediabay.h>
+#include <asm/machdep.h>
+#include <asm/dma.h>
+#include <asm/bootx.h>
+#include <asm/cputable.h>
+#include <asm/btext.h>
+#include <asm/pmac_feature.h>
+#include <asm/time.h>
+#include <asm/of_device.h>
+#include <asm/mmu_context.h>
+
+#include "pmac_pic.h"
+#include "mem_pieces.h"
+
+#undef SHOW_GATWICK_IRQS
+
+extern long pmac_time_init(void);
+extern unsigned long pmac_get_rtc_time(void);
+extern int pmac_set_rtc_time(unsigned long nowtime);
+extern void pmac_read_rtc_time(void);
+extern void pmac_calibrate_decr(void);
+extern void pmac_pcibios_fixup(void);
+extern void pmac_find_bridges(void);
+extern unsigned long pmac_ide_get_base(int index);
+extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
+	unsigned long data_port, unsigned long ctrl_port, int *irq);
+
+extern void pmac_nvram_update(void);
+extern unsigned char pmac_nvram_read_byte(int addr);
+extern void pmac_nvram_write_byte(int addr, unsigned char val);
+extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);
+extern void pmac_pcibios_after_init(void);
+extern int of_show_percpuinfo(struct seq_file *m, int i);
+
+struct device_node *memory_node;
+
+unsigned char drive_info;
+
+int ppc_override_l2cr = 0;
+int ppc_override_l2cr_value;
+int has_l2cache = 0;
+
+static int current_root_goodness = -1;
+
+extern int pmac_newworld;
+
+#define DEFAULT_ROOT_DEVICE Root_SDA1	/* sda1 - slightly silly choice */
+
+extern void zs_kgdb_hook(int tty_num);
+static void ohare_init(void);
+#ifdef CONFIG_BOOTX_TEXT
+void pmac_progress(char *s, unsigned short hex);
+#endif
+
+sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
+
+#ifdef CONFIG_SMP
+extern struct smp_ops_t psurge_smp_ops;
+extern struct smp_ops_t core99_smp_ops;
+#endif /* CONFIG_SMP */
+
+int __pmac
+pmac_show_cpuinfo(struct seq_file *m)
+{
+	struct device_node *np;
+	char *pp;
+	int plen;
+	int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO,
+		NULL, PMAC_MB_INFO_MODEL, 0);
+	unsigned int mbflags = (unsigned int)pmac_call_feature(PMAC_FTR_GET_MB_INFO,
+		NULL, PMAC_MB_INFO_FLAGS, 0);
+	char* mbname;
+
+	if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (int)&mbname) != 0)
+		mbname = "Unknown";
+
+	/* find motherboard type */
+	seq_printf(m, "machine\t\t: ");
+	np = find_devices("device-tree");
+	if (np != NULL) {
+		pp = (char *) get_property(np, "model", NULL);
+		if (pp != NULL)
+			seq_printf(m, "%s\n", pp);
+		else
+			seq_printf(m, "PowerMac\n");
+		pp = (char *) get_property(np, "compatible", &plen);
+		if (pp != NULL) {
+			seq_printf(m, "motherboard\t:");
+			while (plen > 0) {
+				int l = strlen(pp) + 1;
+				seq_printf(m, " %s", pp);
+				plen -= l;
+				pp += l;
+			}
+			seq_printf(m, "\n");
+		}
+	} else
+		seq_printf(m, "PowerMac\n");
+
+	/* print parsed model */
+	seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname);
+	seq_printf(m, "pmac flags\t: %08x\n", mbflags);
+
+	/* find l2 cache info */
+	np = find_devices("l2-cache");
+	if (np == 0)
+		np = find_type_devices("cache");
+	if (np != 0) {
+		unsigned int *ic = (unsigned int *)
+			get_property(np, "i-cache-size", NULL);
+		unsigned int *dc = (unsigned int *)
+			get_property(np, "d-cache-size", NULL);
+		seq_printf(m, "L2 cache\t:");
+		has_l2cache = 1;
+		if (get_property(np, "cache-unified", NULL) != 0 && dc) {
+			seq_printf(m, " %dK unified", *dc / 1024);
+		} else {
+			if (ic)
+				seq_printf(m, " %dK instruction", *ic / 1024);
+			if (dc)
+				seq_printf(m, "%s %dK data",
+					   (ic? " +": ""), *dc / 1024);
+		}
+		pp = get_property(np, "ram-type", NULL);
+		if (pp)
+			seq_printf(m, " %s", pp);
+		seq_printf(m, "\n");
+	}
+
+	/* find ram info */
+	np = find_devices("memory");
+	if (np != 0) {
+		int n;
+		struct reg_property *reg = (struct reg_property *)
+			get_property(np, "reg", &n);
+
+		if (reg != 0) {
+			unsigned long total = 0;
+
+			for (n /= sizeof(struct reg_property); n > 0; --n)
+				total += (reg++)->size;
+			seq_printf(m, "memory\t\t: %luMB\n", total >> 20);
+		}
+	}
+
+	/* Checks "l2cr-value" property in the registry */
+	np = find_devices("cpus");
+	if (np == 0)
+		np = find_type_devices("cpu");
+	if (np != 0) {
+		unsigned int *l2cr = (unsigned int *)
+			get_property(np, "l2cr-value", NULL);
+		if (l2cr != 0) {
+			seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr);
+		}
+	}
+
+	/* Indicate newworld/oldworld */
+	seq_printf(m, "pmac-generation\t: %s\n",
+		   pmac_newworld ? "NewWorld" : "OldWorld");
+
+
+	return 0;
+}
+
+int __openfirmware
+pmac_show_percpuinfo(struct seq_file *m, int i)
+{
+#ifdef CONFIG_CPU_FREQ_PMAC
+	extern unsigned int pmac_get_one_cpufreq(int i);
+	unsigned int freq = pmac_get_one_cpufreq(i);
+	if (freq != 0) {
+		seq_printf(m, "clock\t\t: %dMHz\n", freq/1000);
+		return 0;
+	}
+#endif /* CONFIG_CPU_FREQ_PMAC */
+	return of_show_percpuinfo(m, i);
+}
+
+static volatile u32 *sysctrl_regs;
+
+void __init
+pmac_setup_arch(void)
+{
+	struct device_node *cpu;
+	int *fp;
+	unsigned long pvr;
+
+	pvr = PVR_VER(mfspr(SPRN_PVR));
+
+	/* Set loops_per_jiffy to a half-way reasonable value,
+	   for use until calibrate_delay gets called. */
+	cpu = find_type_devices("cpu");
+	if (cpu != 0) {
+		fp = (int *) get_property(cpu, "clock-frequency", NULL);
+		if (fp != 0) {
+			if (pvr == 4 || pvr >= 8)
+				/* 604, G3, G4 etc. */
+				loops_per_jiffy = *fp / HZ;
+			else
+				/* 601, 603, etc. */
+				loops_per_jiffy = *fp / (2*HZ);
+		} else
+			loops_per_jiffy = 50000000 / HZ;
+	}
+
+	/* this area has the CPU identification register
+	   and some registers used by smp boards */
+	sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000);
+	ohare_init();
+
+	/* Lookup PCI hosts */
+	pmac_find_bridges();
+
+	/* Checks "l2cr-value" property in the registry */
+	if (cpu_has_feature(CPU_FTR_L2CR)) {
+		struct device_node *np = find_devices("cpus");
+		if (np == 0)
+			np = find_type_devices("cpu");
+		if (np != 0) {
+			unsigned int *l2cr = (unsigned int *)
+				get_property(np, "l2cr-value", NULL);
+			if (l2cr != 0) {
+				ppc_override_l2cr = 1;
+				ppc_override_l2cr_value = *l2cr;
+				_set_L2CR(0);
+				_set_L2CR(ppc_override_l2cr_value);
+			}
+		}
+	}
+
+	if (ppc_override_l2cr)
+		printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n",
+			ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000)
+				? "enabled" : "disabled");
+
+#ifdef CONFIG_KGDB
+	zs_kgdb_hook(0);
+#endif
+
+#ifdef CONFIG_ADB_CUDA
+	find_via_cuda();
+#else
+	if (find_devices("via-cuda")) {
+		printk("WARNING ! Your machine is Cuda based but your kernel\n");
+		printk("          wasn't compiled with CONFIG_ADB_CUDA option !\n");
+	}
+#endif
+#ifdef CONFIG_ADB_PMU
+	find_via_pmu();
+#else
+	if (find_devices("via-pmu")) {
+		printk("WARNING ! Your machine is PMU based but your kernel\n");
+		printk("          wasn't compiled with CONFIG_ADB_PMU option !\n");
+	}
+#endif
+#ifdef CONFIG_NVRAM
+	pmac_nvram_init();
+#endif
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+		ROOT_DEV = DEFAULT_ROOT_DEVICE;
+
+#ifdef CONFIG_SMP
+	/* Check for Core99 */
+	if (find_devices("uni-n") || find_devices("u3"))
+		ppc_md.smp_ops = &core99_smp_ops;
+	else
+		ppc_md.smp_ops = &psurge_smp_ops;
+#endif /* CONFIG_SMP */
+
+	pci_create_OF_bus_map();
+}
+
+static void __init ohare_init(void)
+{
+	/*
+	 * Turn on the L2 cache.
+	 * We assume that we have a PSX memory controller iff
+	 * we have an ohare I/O controller.
+	 */
+	if (find_devices("ohare") != NULL) {
+		if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {
+			if (sysctrl_regs[4] & 0x10)
+				sysctrl_regs[4] |= 0x04000020;
+			else
+				sysctrl_regs[4] |= 0x04000000;
+			if(has_l2cache)
+				printk(KERN_INFO "Level 2 cache enabled\n");
+		}
+	}
+}
+
+extern char *bootpath;
+extern char *bootdevice;
+void *boot_host;
+int boot_target;
+int boot_part;
+extern dev_t boot_dev;
+
+#ifdef CONFIG_SCSI
+void __init
+note_scsi_host(struct device_node *node, void *host)
+{
+	int l;
+	char *p;
+
+	l = strlen(node->full_name);
+	if (bootpath != NULL && bootdevice != NULL
+	    && strncmp(node->full_name, bootdevice, l) == 0
+	    && (bootdevice[l] == '/' || bootdevice[l] == 0)) {
+		boot_host = host;
+		/*
+		 * There's a bug in OF 1.0.5.  (Why am I not surprised.)
+		 * If you pass a path like scsi/sd@1:0 to canon, it returns
+		 * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0
+		 * That is, the scsi target number doesn't get preserved.
+		 * So we pick the target number out of bootpath and use that.
+		 */
+		p = strstr(bootpath, "/sd@");
+		if (p != NULL) {
+			p += 4;
+			boot_target = simple_strtoul(p, NULL, 10);
+			p = strchr(p, ':');
+			if (p != NULL)
+				boot_part = simple_strtoul(p + 1, NULL, 10);
+		}
+	}
+}
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
+static dev_t __init
+find_ide_boot(void)
+{
+	char *p;
+	int n;
+	dev_t __init pmac_find_ide_boot(char *bootdevice, int n);
+
+	if (bootdevice == NULL)
+		return 0;
+	p = strrchr(bootdevice, '/');
+	if (p == NULL)
+		return 0;
+	n = p - bootdevice;
+
+	return pmac_find_ide_boot(bootdevice, n);
+}
+#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
+
+void __init
+find_boot_device(void)
+{
+#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
+	boot_dev = find_ide_boot();
+#endif
+}
+
+static int initializing = 1;
+/* TODO: Merge the suspend-to-ram with the common code !!!
+ * currently, this is a stub implementation for suspend-to-disk
+ * only
+ */
+
+#ifdef CONFIG_SOFTWARE_SUSPEND
+
+static int pmac_pm_prepare(suspend_state_t state)
+{
+	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
+
+	return 0;
+}
+
+static int pmac_pm_enter(suspend_state_t state)
+{
+	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
+
+	/* Giveup the lazy FPU & vec so we don't have to back them
+	 * up from the low level code
+	 */
+	enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+		enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+	return 0;
+}
+
+static int pmac_pm_finish(suspend_state_t state)
+{
+	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
+
+	/* Restore userland MMU context */
+	set_context(current->active_mm->context, current->active_mm->pgd);
+
+	return 0;
+}
+
+static struct pm_ops pmac_pm_ops = {
+	.pm_disk_mode	= PM_DISK_SHUTDOWN,
+	.prepare	= pmac_pm_prepare,
+	.enter		= pmac_pm_enter,
+	.finish		= pmac_pm_finish,
+};
+
+#endif /* CONFIG_SOFTWARE_SUSPEND */
+
+static int pmac_late_init(void)
+{
+	initializing = 0;
+#ifdef CONFIG_SOFTWARE_SUSPEND
+	pm_set_ops(&pmac_pm_ops);
+#endif /* CONFIG_SOFTWARE_SUSPEND */
+	return 0;
+}
+
+late_initcall(pmac_late_init);
+
+/* can't be __init - can be called whenever a disk is first accessed */
+void __pmac
+note_bootable_part(dev_t dev, int part, int goodness)
+{
+	static int found_boot = 0;
+	char *p;
+
+	if (!initializing)
+		return;
+	if ((goodness <= current_root_goodness) &&
+	    ROOT_DEV != DEFAULT_ROOT_DEVICE)
+		return;
+	p = strstr(saved_command_line, "root=");
+	if (p != NULL && (p == saved_command_line || p[-1] == ' '))
+		return;
+
+	if (!found_boot) {
+		find_boot_device();
+		found_boot = 1;
+	}
+	if (!boot_dev || dev == boot_dev) {
+		ROOT_DEV = dev + part;
+		boot_dev = 0;
+		current_root_goodness = goodness;
+	}
+}
+
+void __pmac
+pmac_restart(char *cmd)
+{
+#ifdef CONFIG_ADB_CUDA
+	struct adb_request req;
+#endif /* CONFIG_ADB_CUDA */
+
+	switch (sys_ctrler) {
+#ifdef CONFIG_ADB_CUDA
+	case SYS_CTRLER_CUDA:
+		cuda_request(&req, NULL, 2, CUDA_PACKET,
+			     CUDA_RESET_SYSTEM);
+		for (;;)
+			cuda_poll();
+		break;
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_ADB_PMU
+	case SYS_CTRLER_PMU:
+		pmu_restart();
+		break;
+#endif /* CONFIG_ADB_PMU */
+	default: ;
+	}
+}
+
+void __pmac
+pmac_power_off(void)
+{
+#ifdef CONFIG_ADB_CUDA
+	struct adb_request req;
+#endif /* CONFIG_ADB_CUDA */
+
+	switch (sys_ctrler) {
+#ifdef CONFIG_ADB_CUDA
+	case SYS_CTRLER_CUDA:
+		cuda_request(&req, NULL, 2, CUDA_PACKET,
+			     CUDA_POWERDOWN);
+		for (;;)
+			cuda_poll();
+		break;
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_ADB_PMU
+	case SYS_CTRLER_PMU:
+		pmu_shutdown();
+		break;
+#endif /* CONFIG_ADB_PMU */
+	default: ;
+	}
+}
+
+void __pmac
+pmac_halt(void)
+{
+   pmac_power_off();
+}
+
+/*
+ * Read in a property describing some pieces of memory.
+ */
+
+static int __init
+get_mem_prop(char *name, struct mem_pieces *mp)
+{
+	struct reg_property *rp;
+	int i, s;
+	unsigned int *ip;
+	int nac = prom_n_addr_cells(memory_node);
+	int nsc = prom_n_size_cells(memory_node);
+
+	ip = (unsigned int *) get_property(memory_node, name, &s);
+	if (ip == NULL) {
+		printk(KERN_ERR "error: couldn't get %s property on /memory\n",
+		       name);
+		return 0;
+	}
+	s /= (nsc + nac) * 4;
+	rp = mp->regions;
+	for (i = 0; i < s; ++i, ip += nac+nsc) {
+		if (nac >= 2 && ip[nac-2] != 0)
+			continue;
+		rp->address = ip[nac-1];
+		if (nsc >= 2 && ip[nac+nsc-2] != 0)
+			rp->size = ~0U;
+		else
+			rp->size = ip[nac+nsc-1];
+		++rp;
+	}
+	mp->n_regions = rp - mp->regions;
+
+	/* Make sure the pieces are sorted. */
+	mem_pieces_sort(mp);
+	mem_pieces_coalesce(mp);
+	return 1;
+}
+
+/*
+ * On systems with Open Firmware, collect information about
+ * physical RAM and which pieces are already in use.
+ * At this point, we have (at least) the first 8MB mapped with a BAT.
+ * Our text, data, bss use something over 1MB, starting at 0.
+ * Open Firmware may be using 1MB at the 4MB point.
+ */
+unsigned long __init
+pmac_find_end_of_memory(void)
+{
+	unsigned long a, total;
+	struct mem_pieces phys_mem;
+
+	/*
+	 * Find out where physical memory is, and check that it
+	 * starts at 0 and is contiguous.  It seems that RAM is
+	 * always physically contiguous on Power Macintoshes.
+	 *
+	 * Supporting discontiguous physical memory isn't hard,
+	 * it just makes the virtual <-> physical mapping functions
+	 * more complicated (or else you end up wasting space
+	 * in mem_map).
+	 */
+	memory_node = find_devices("memory");
+	if (memory_node == NULL || !get_mem_prop("reg", &phys_mem)
+	    || phys_mem.n_regions == 0)
+		panic("No RAM??");
+	a = phys_mem.regions[0].address;
+	if (a != 0)
+		panic("RAM doesn't start at physical address 0");
+	total = phys_mem.regions[0].size;
+
+	if (phys_mem.n_regions > 1) {
+		printk("RAM starting at 0x%x is not contiguous\n",
+		       phys_mem.regions[1].address);
+		printk("Using RAM from 0 to 0x%lx\n", total-1);
+	}
+
+	return total;
+}
+
+void __init
+pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	  unsigned long r6, unsigned long r7)
+{
+	/* isa_io_base gets set in pmac_find_bridges */
+	isa_mem_base = PMAC_ISA_MEM_BASE;
+	pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
+	ISA_DMA_THRESHOLD = ~0L;
+	DMA_MODE_READ = 1;
+	DMA_MODE_WRITE = 2;
+
+	ppc_md.setup_arch     = pmac_setup_arch;
+	ppc_md.show_cpuinfo   = pmac_show_cpuinfo;
+	ppc_md.show_percpuinfo = pmac_show_percpuinfo;
+	ppc_md.irq_canonicalize = NULL;
+	ppc_md.init_IRQ       = pmac_pic_init;
+	ppc_md.get_irq        = pmac_get_irq; /* Changed later on ... */
+
+	ppc_md.pcibios_fixup  = pmac_pcibios_fixup;
+	ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook;
+	ppc_md.pcibios_after_init = pmac_pcibios_after_init;
+	ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
+
+	ppc_md.restart        = pmac_restart;
+	ppc_md.power_off      = pmac_power_off;
+	ppc_md.halt           = pmac_halt;
+
+	ppc_md.time_init      = pmac_time_init;
+	ppc_md.set_rtc_time   = pmac_set_rtc_time;
+	ppc_md.get_rtc_time   = pmac_get_rtc_time;
+	ppc_md.calibrate_decr = pmac_calibrate_decr;
+
+	ppc_md.find_end_of_memory = pmac_find_end_of_memory;
+
+	ppc_md.feature_call   = pmac_do_feature_call;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+        ppc_ide_md.ide_init_hwif	= pmac_ide_init_hwif_ports;
+        ppc_ide_md.default_io_base	= pmac_ide_get_base;
+#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
+
+#ifdef CONFIG_BOOTX_TEXT
+	ppc_md.progress = pmac_progress;
+#endif /* CONFIG_BOOTX_TEXT */
+
+	if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
+
+}
+
+#ifdef CONFIG_BOOTX_TEXT
+void __init
+pmac_progress(char *s, unsigned short hex)
+{
+	if (boot_text_mapped) {
+		btext_drawstring(s);
+		btext_drawchar('\n');
+	}
+}
+#endif /* CONFIG_BOOTX_TEXT */
+
+static int __init
+pmac_declare_of_platform_devices(void)
+{
+	struct device_node *np;
+
+	np = find_devices("uni-n");
+	if (np) {
+		for (np = np->child; np != NULL; np = np->sibling)
+			if (strncmp(np->name, "i2c", 3) == 0) {
+				of_platform_device_create(np, "uni-n-i2c");
+				break;
+			}
+	}
+	np = find_devices("u3");
+	if (np) {
+		for (np = np->child; np != NULL; np = np->sibling)
+			if (strncmp(np->name, "i2c", 3) == 0) {
+				of_platform_device_create(np, "u3-i2c");
+				break;
+			}
+	}
+
+	np = find_devices("valkyrie");
+	if (np)
+		of_platform_device_create(np, "valkyrie");
+	np = find_devices("platinum");
+	if (np)
+		of_platform_device_create(np, "platinum");
+
+	return 0;
+}
+
+device_initcall(pmac_declare_of_platform_devices);
diff --git a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S
new file mode 100644
index 0000000..3139b67
--- /dev/null
+++ b/arch/ppc/platforms/pmac_sleep.S
@@ -0,0 +1,390 @@
+/*
+ * This file contains sleep low-level functions for PowerBook G3.
+ *    Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *    and Paul Mackerras (paulus@samba.org).
+ *
+ * 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 <asm/processor.h>
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/cputable.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
+#include <asm/offsets.h>
+
+#define MAGIC	0x4c617273	/* 'Lars' */
+
+/*
+ * Structure for storing CPU registers on the stack.
+ */
+#define SL_SP		0
+#define SL_PC		4
+#define SL_MSR		8
+#define SL_SDR1		0xc
+#define SL_SPRG0	0x10	/* 4 sprg's */
+#define SL_DBAT0	0x20
+#define SL_IBAT0	0x28
+#define SL_DBAT1	0x30
+#define SL_IBAT1	0x38
+#define SL_DBAT2	0x40
+#define SL_IBAT2	0x48
+#define SL_DBAT3	0x50
+#define SL_IBAT3	0x58
+#define SL_TB		0x60
+#define SL_R2		0x68
+#define SL_CR		0x6c
+#define SL_R12		0x70	/* r12 to r31 */
+#define SL_SIZE		(SL_R12 + 80)
+
+	.section .text
+	.align	5
+
+#if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ_PMAC)
+
+/* This gets called by via-pmu.c late during the sleep process.
+ * The PMU was already send the sleep command and will shut us down
+ * soon. We need to save all that is needed and setup the wakeup
+ * vector that will be called by the ROM on wakeup
+ */
+_GLOBAL(low_sleep_handler)
+#ifndef CONFIG_6xx
+	blr
+#else
+	mflr	r0
+	stw	r0,4(r1)
+	stwu	r1,-SL_SIZE(r1)
+	mfcr	r0
+	stw	r0,SL_CR(r1)
+	stw	r2,SL_R2(r1)
+	stmw	r12,SL_R12(r1)
+
+	/* Save MSR & SDR1 */
+	mfmsr	r4
+	stw	r4,SL_MSR(r1)
+	mfsdr1	r4
+	stw	r4,SL_SDR1(r1)
+
+	/* Get a stable timebase and save it */
+1:	mftbu	r4
+	stw	r4,SL_TB(r1)
+	mftb	r5
+	stw	r5,SL_TB+4(r1)
+	mftbu	r3
+	cmpw	r3,r4
+	bne	1b
+
+	/* Save SPRGs */
+	mfsprg	r4,0
+	stw	r4,SL_SPRG0(r1)
+	mfsprg	r4,1
+	stw	r4,SL_SPRG0+4(r1)
+	mfsprg	r4,2
+	stw	r4,SL_SPRG0+8(r1)
+	mfsprg	r4,3
+	stw	r4,SL_SPRG0+12(r1)
+
+	/* Save BATs */
+	mfdbatu	r4,0
+	stw	r4,SL_DBAT0(r1)
+	mfdbatl	r4,0
+	stw	r4,SL_DBAT0+4(r1)
+	mfdbatu	r4,1
+	stw	r4,SL_DBAT1(r1)
+	mfdbatl	r4,1
+	stw	r4,SL_DBAT1+4(r1)
+	mfdbatu	r4,2
+	stw	r4,SL_DBAT2(r1)
+	mfdbatl	r4,2
+	stw	r4,SL_DBAT2+4(r1)
+	mfdbatu	r4,3
+	stw	r4,SL_DBAT3(r1)
+	mfdbatl	r4,3
+	stw	r4,SL_DBAT3+4(r1)
+	mfibatu	r4,0
+	stw	r4,SL_IBAT0(r1)
+	mfibatl	r4,0
+	stw	r4,SL_IBAT0+4(r1)
+	mfibatu	r4,1
+	stw	r4,SL_IBAT1(r1)
+	mfibatl	r4,1
+	stw	r4,SL_IBAT1+4(r1)
+	mfibatu	r4,2
+	stw	r4,SL_IBAT2(r1)
+	mfibatl	r4,2
+	stw	r4,SL_IBAT2+4(r1)
+	mfibatu	r4,3
+	stw	r4,SL_IBAT3(r1)
+	mfibatl	r4,3
+	stw	r4,SL_IBAT3+4(r1)
+
+	/* Backup various CPU config stuffs */
+	bl	__save_cpu_setup
+
+	/* The ROM can wake us up via 2 different vectors:
+	 *  - On wallstreet & lombard, we must write a magic
+	 *    value 'Lars' at address 4 and a pointer to a
+	 *    memory location containing the PC to resume from
+	 *    at address 0.
+	 *  - On Core99, we must store the wakeup vector at
+	 *    address 0x80 and eventually it's parameters
+	 *    at address 0x84. I've have some trouble with those
+	 *    parameters however and I no longer use them.
+	 */
+	lis	r5,grackle_wake_up@ha
+	addi	r5,r5,grackle_wake_up@l
+	tophys(r5,r5)
+	stw	r5,SL_PC(r1)
+	lis	r4,KERNELBASE@h
+	tophys(r5,r1)
+	addi	r5,r5,SL_PC
+	lis	r6,MAGIC@ha
+	addi	r6,r6,MAGIC@l
+	stw	r5,0(r4)
+	stw	r6,4(r4)
+	/* Setup stuffs at 0x80-0x84 for Core99 */
+	lis	r3,core99_wake_up@ha
+	addi	r3,r3,core99_wake_up@l
+	tophys(r3,r3)
+	stw	r3,0x80(r4)
+	stw	r5,0x84(r4)
+	/* Store a pointer to our backup storage into
+	 * a kernel global
+	 */
+	lis r3,sleep_storage@ha
+	addi r3,r3,sleep_storage@l
+	stw r5,0(r3)
+
+	/* Flush & disable all caches */
+	bl	flush_disable_caches
+
+	/* Turn off data relocation. */
+	mfmsr	r3		/* Save MSR in r7 */
+	rlwinm	r3,r3,0,28,26	/* Turn off DR bit */
+	sync
+	mtmsr	r3
+	isync
+
+BEGIN_FTR_SECTION
+	/* Flush any pending L2 data prefetches to work around HW bug */
+	sync
+	lis	r3,0xfff0
+	lwz	r0,0(r3)	/* perform cache-inhibited load to ROM */
+	sync			/* (caches are disabled at this point) */
+END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
+
+/*
+ * Set the HID0 and MSR for sleep.
+ */
+	mfspr	r2,SPRN_HID0
+	rlwinm	r2,r2,0,10,7	/* clear doze, nap */
+	oris	r2,r2,HID0_SLEEP@h
+	sync
+	isync
+	mtspr	SPRN_HID0,r2
+	sync
+
+/* This loop puts us back to sleep in case we have a spurrious
+ * wakeup so that the host bridge properly stays asleep. The
+ * CPU will be turned off, either after a known time (about 1
+ * second) on wallstreet & lombard, or as soon as the CPU enters
+ * SLEEP mode on core99
+ */
+	mfmsr	r2
+	oris	r2,r2,MSR_POW@h
+1:	sync
+	mtmsr	r2
+	isync
+	b	1b
+
+/*
+ * Here is the resume code.
+ */
+
+
+/*
+ * Core99 machines resume here
+ * r4 has the physical address of SL_PC(sp) (unused)
+ */
+_GLOBAL(core99_wake_up)
+	/* Make sure HID0 no longer contains any sleep bit and that data cache
+	 * is disabled
+	 */
+	mfspr	r3,SPRN_HID0
+	rlwinm	r3,r3,0,11,7		/* clear SLEEP, NAP, DOZE bits */
+	rlwinm	3,r3,0,18,15		/* clear DCE, ICE */
+	mtspr	SPRN_HID0,r3
+	sync
+	isync
+
+	/* sanitize MSR */
+	mfmsr	r3
+	ori	r3,r3,MSR_EE|MSR_IP
+	xori	r3,r3,MSR_EE|MSR_IP
+	sync
+	isync
+	mtmsr	r3
+	sync
+	isync
+
+	/* Recover sleep storage */
+	lis	r3,sleep_storage@ha
+	addi	r3,r3,sleep_storage@l
+	tophys(r3,r3)
+	lwz	r1,0(r3)
+
+	/* Pass thru to older resume code ... */
+/*
+ * Here is the resume code for older machines.
+ * r1 has the physical address of SL_PC(sp).
+ */
+
+grackle_wake_up:
+
+	/* Restore the kernel's segment registers before
+	 * we do any r1 memory access as we are not sure they
+	 * are in a sane state above the first 256Mb region
+	 */
+	li	r0,16		/* load up segment register values */
+	mtctr	r0		/* for context 0 */
+	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
+	li	r4,0
+3:	mtsrin	r3,r4
+	addi	r3,r3,0x111	/* increment VSID */
+	addis	r4,r4,0x1000	/* address of next segment */
+	bdnz	3b
+	sync
+	isync
+
+	subi	r1,r1,SL_PC
+
+	/* Restore various CPU config stuffs */
+	bl	__restore_cpu_setup
+
+	/* Invalidate & enable L1 cache, we don't care about
+	 * whatever the ROM may have tried to write to memory
+	 */
+	bl	__inval_enable_L1
+
+	/* Restore the BATs, and SDR1.  Then we can turn on the MMU. */
+	lwz	r4,SL_SDR1(r1)
+	mtsdr1	r4
+	lwz	r4,SL_SPRG0(r1)
+	mtsprg	0,r4
+	lwz	r4,SL_SPRG0+4(r1)
+	mtsprg	1,r4
+	lwz	r4,SL_SPRG0+8(r1)
+	mtsprg	2,r4
+	lwz	r4,SL_SPRG0+12(r1)
+	mtsprg	3,r4
+
+	lwz	r4,SL_DBAT0(r1)
+	mtdbatu	0,r4
+	lwz	r4,SL_DBAT0+4(r1)
+	mtdbatl	0,r4
+	lwz	r4,SL_DBAT1(r1)
+	mtdbatu	1,r4
+	lwz	r4,SL_DBAT1+4(r1)
+	mtdbatl	1,r4
+	lwz	r4,SL_DBAT2(r1)
+	mtdbatu	2,r4
+	lwz	r4,SL_DBAT2+4(r1)
+	mtdbatl	2,r4
+	lwz	r4,SL_DBAT3(r1)
+	mtdbatu	3,r4
+	lwz	r4,SL_DBAT3+4(r1)
+	mtdbatl	3,r4
+	lwz	r4,SL_IBAT0(r1)
+	mtibatu	0,r4
+	lwz	r4,SL_IBAT0+4(r1)
+	mtibatl	0,r4
+	lwz	r4,SL_IBAT1(r1)
+	mtibatu	1,r4
+	lwz	r4,SL_IBAT1+4(r1)
+	mtibatl	1,r4
+	lwz	r4,SL_IBAT2(r1)
+	mtibatu	2,r4
+	lwz	r4,SL_IBAT2+4(r1)
+	mtibatl	2,r4
+	lwz	r4,SL_IBAT3(r1)
+	mtibatu	3,r4
+	lwz	r4,SL_IBAT3+4(r1)
+	mtibatl	3,r4
+
+BEGIN_FTR_SECTION
+	li	r4,0
+	mtspr	SPRN_DBAT4U,r4
+	mtspr	SPRN_DBAT4L,r4
+	mtspr	SPRN_DBAT5U,r4
+	mtspr	SPRN_DBAT5L,r4
+	mtspr	SPRN_DBAT6U,r4
+	mtspr	SPRN_DBAT6L,r4
+	mtspr	SPRN_DBAT7U,r4
+	mtspr	SPRN_DBAT7L,r4
+	mtspr	SPRN_IBAT4U,r4
+	mtspr	SPRN_IBAT4L,r4
+	mtspr	SPRN_IBAT5U,r4
+	mtspr	SPRN_IBAT5L,r4
+	mtspr	SPRN_IBAT6U,r4
+	mtspr	SPRN_IBAT6L,r4
+	mtspr	SPRN_IBAT7U,r4
+	mtspr	SPRN_IBAT7L,r4
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)
+
+	/* Flush all TLBs */
+	lis	r4,0x1000
+1:	addic.	r4,r4,-0x1000
+	tlbie	r4
+	blt	1b
+	sync
+
+	/* restore the MSR and turn on the MMU */
+	lwz	r3,SL_MSR(r1)
+	bl	turn_on_mmu
+
+	/* get back the stack pointer */
+	tovirt(r1,r1)
+
+	/* Restore TB */
+	li	r3,0
+	mttbl	r3
+	lwz	r3,SL_TB(r1)
+	lwz	r4,SL_TB+4(r1)
+	mttbu	r3
+	mttbl	r4
+
+	/* Restore the callee-saved registers and return */
+	lwz	r0,SL_CR(r1)
+	mtcr	r0
+	lwz	r2,SL_R2(r1)
+	lmw	r12,SL_R12(r1)
+	addi	r1,r1,SL_SIZE
+	lwz	r0,4(r1)
+	mtlr	r0
+	blr
+
+turn_on_mmu:
+	mflr	r4
+	tovirt(r4,r4)
+	mtsrr0	r4
+	mtsrr1	r3
+	sync
+	isync
+	rfi
+
+#endif /* defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ) */
+
+	.section .data
+	.balign	L1_CACHE_LINE_SIZE
+sleep_storage:
+	.long 0
+	.balign	L1_CACHE_LINE_SIZE, 0
+
+#endif /* CONFIG_6xx */
+	.section .text
diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c
new file mode 100644
index 0000000..2b88745
--- /dev/null
+++ b/arch/ppc/platforms/pmac_smp.c
@@ -0,0 +1,640 @@
+/*
+ * SMP support for power macintosh.
+ *
+ * We support both the old "powersurge" SMP architecture
+ * and the current Core99 (G4 PowerMac) machines.
+ *
+ * Note that we don't support the very first rev. of
+ * Apple/DayStar 2 CPUs board, the one with the funky
+ * watchdog. Hopefully, none of these should be there except
+ * maybe internally to Apple. I should probably still add some
+ * code to detect this card though and disable SMP. --BenH.
+ *
+ * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net)
+ * and Ben Herrenschmidt <benh@kernel.crashing.org>.
+ *
+ * Support for DayStar quad CPU cards
+ * Copyright (C) XLR8, Inc. 1994-2000
+ *
+ *  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/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/hardirq.h>
+
+#include <asm/ptrace.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/residual.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/time.h>
+#include <asm/open_pic.h>
+#include <asm/cacheflush.h>
+#include <asm/keylargo.h>
+
+/*
+ * Powersurge (old powermac SMP) support.
+ */
+
+extern void __secondary_start_psurge(void);
+extern void __secondary_start_psurge2(void);	/* Temporary horrible hack */
+extern void __secondary_start_psurge3(void);	/* Temporary horrible hack */
+
+/* Addresses for powersurge registers */
+#define HAMMERHEAD_BASE		0xf8000000
+#define HHEAD_CONFIG		0x90
+#define HHEAD_SEC_INTR		0xc0
+
+/* register for interrupting the primary processor on the powersurge */
+/* N.B. this is actually the ethernet ROM! */
+#define PSURGE_PRI_INTR		0xf3019000
+
+/* register for storing the start address for the secondary processor */
+/* N.B. this is the PCI config space address register for the 1st bridge */
+#define PSURGE_START		0xf2800000
+
+/* Daystar/XLR8 4-CPU card */
+#define PSURGE_QUAD_REG_ADDR	0xf8800000
+
+#define PSURGE_QUAD_IRQ_SET	0
+#define PSURGE_QUAD_IRQ_CLR	1
+#define PSURGE_QUAD_IRQ_PRIMARY	2
+#define PSURGE_QUAD_CKSTOP_CTL	3
+#define PSURGE_QUAD_PRIMARY_ARB	4
+#define PSURGE_QUAD_BOARD_ID	6
+#define PSURGE_QUAD_WHICH_CPU	7
+#define PSURGE_QUAD_CKSTOP_RDBK	8
+#define PSURGE_QUAD_RESET_CTL	11
+
+#define PSURGE_QUAD_OUT(r, v)	(out_8(quad_base + ((r) << 4) + 4, (v)))
+#define PSURGE_QUAD_IN(r)	(in_8(quad_base + ((r) << 4) + 4) & 0x0f)
+#define PSURGE_QUAD_BIS(r, v)	(PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v)))
+#define PSURGE_QUAD_BIC(r, v)	(PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v)))
+
+/* virtual addresses for the above */
+static volatile u8 *hhead_base;
+static volatile u8 *quad_base;
+static volatile u32 *psurge_pri_intr;
+static volatile u8 *psurge_sec_intr;
+static volatile u32 *psurge_start;
+
+/* values for psurge_type */
+#define PSURGE_NONE		-1
+#define PSURGE_DUAL		0
+#define PSURGE_QUAD_OKEE	1
+#define PSURGE_QUAD_COTTON	2
+#define PSURGE_QUAD_ICEGRASS	3
+
+/* what sort of powersurge board we have */
+static int psurge_type = PSURGE_NONE;
+
+/* L2 and L3 cache settings to pass from CPU0 to CPU1 */
+volatile static long int core99_l2_cache;
+volatile static long int core99_l3_cache;
+
+/* Timebase freeze GPIO */
+static unsigned int core99_tb_gpio;
+
+/* Sync flag for HW tb sync */
+static volatile int sec_tb_reset = 0;
+
+static void __init core99_init_caches(int cpu)
+{
+	if (!cpu_has_feature(CPU_FTR_L2CR))
+		return;
+
+	if (cpu == 0) {
+		core99_l2_cache = _get_L2CR();
+		printk("CPU0: L2CR is %lx\n", core99_l2_cache);
+	} else {
+		printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR());
+		_set_L2CR(0);
+		_set_L2CR(core99_l2_cache);
+		printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
+	}
+
+	if (!cpu_has_feature(CPU_FTR_L3CR))
+		return;
+
+	if (cpu == 0){
+		core99_l3_cache = _get_L3CR();
+		printk("CPU0: L3CR is %lx\n", core99_l3_cache);
+	} else {
+		printk("CPU%d: L3CR was %lx\n", cpu, _get_L3CR());
+		_set_L3CR(0);
+		_set_L3CR(core99_l3_cache);
+		printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache);
+	}
+}
+
+/*
+ * Set and clear IPIs for powersurge.
+ */
+static inline void psurge_set_ipi(int cpu)
+{
+	if (psurge_type == PSURGE_NONE)
+		return;
+	if (cpu == 0)
+		in_be32(psurge_pri_intr);
+	else if (psurge_type == PSURGE_DUAL)
+		out_8(psurge_sec_intr, 0);
+	else
+		PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu);
+}
+
+static inline void psurge_clr_ipi(int cpu)
+{
+	if (cpu > 0) {
+		switch(psurge_type) {
+		case PSURGE_DUAL:
+			out_8(psurge_sec_intr, ~0);
+		case PSURGE_NONE:
+			break;
+		default:
+			PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu);
+		}
+	}
+}
+
+/*
+ * On powersurge (old SMP powermac architecture) we don't have
+ * separate IPIs for separate messages like openpic does.  Instead
+ * we have a bitmap for each processor, where a 1 bit means that
+ * the corresponding message is pending for that processor.
+ * Ideally each cpu's entry would be in a different cache line.
+ *  -- paulus.
+ */
+static unsigned long psurge_smp_message[NR_CPUS];
+
+void __pmac psurge_smp_message_recv(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+	int msg;
+
+	/* clear interrupt */
+	psurge_clr_ipi(cpu);
+
+	if (num_online_cpus() < 2)
+		return;
+
+	/* make sure there is a message there */
+	for (msg = 0; msg < 4; msg++)
+		if (test_and_clear_bit(msg, &psurge_smp_message[cpu]))
+			smp_message_recv(msg, regs);
+}
+
+irqreturn_t __pmac psurge_primary_intr(int irq, void *d, struct pt_regs *regs)
+{
+	psurge_smp_message_recv(regs);
+	return IRQ_HANDLED;
+}
+
+static void __pmac smp_psurge_message_pass(int target, int msg, unsigned long data,
+					   int wait)
+{
+	int i;
+
+	if (num_online_cpus() < 2)
+		return;
+
+	for (i = 0; i < NR_CPUS; i++) {
+		if (!cpu_online(i))
+			continue;
+		if (target == MSG_ALL
+		    || (target == MSG_ALL_BUT_SELF && i != smp_processor_id())
+		    || target == i) {
+			set_bit(msg, &psurge_smp_message[i]);
+			psurge_set_ipi(i);
+		}
+	}
+}
+
+/*
+ * Determine a quad card presence. We read the board ID register, we
+ * force the data bus to change to something else, and we read it again.
+ * It it's stable, then the register probably exist (ugh !)
+ */
+static int __init psurge_quad_probe(void)
+{
+	int type;
+	unsigned int i;
+
+	type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID);
+	if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS
+	    || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
+		return PSURGE_DUAL;
+
+	/* looks OK, try a slightly more rigorous test */
+	/* bogus is not necessarily cacheline-aligned,
+	   though I don't suppose that really matters.  -- paulus */
+	for (i = 0; i < 100; i++) {
+		volatile u32 bogus[8];
+		bogus[(0+i)%8] = 0x00000000;
+		bogus[(1+i)%8] = 0x55555555;
+		bogus[(2+i)%8] = 0xFFFFFFFF;
+		bogus[(3+i)%8] = 0xAAAAAAAA;
+		bogus[(4+i)%8] = 0x33333333;
+		bogus[(5+i)%8] = 0xCCCCCCCC;
+		bogus[(6+i)%8] = 0xCCCCCCCC;
+		bogus[(7+i)%8] = 0x33333333;
+		wmb();
+		asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory");
+		mb();
+		if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
+			return PSURGE_DUAL;
+	}
+	return type;
+}
+
+static void __init psurge_quad_init(void)
+{
+	int procbits;
+
+	if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351);
+	procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU);
+	if (psurge_type == PSURGE_QUAD_ICEGRASS)
+		PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
+	else
+		PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits);
+	mdelay(33);
+	out_8(psurge_sec_intr, ~0);
+	PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits);
+	PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
+	if (psurge_type != PSURGE_QUAD_ICEGRASS)
+		PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits);
+	PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits);
+	mdelay(33);
+	PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits);
+	mdelay(33);
+	PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits);
+	mdelay(33);
+}
+
+static int __init smp_psurge_probe(void)
+{
+	int i, ncpus;
+
+	/* We don't do SMP on the PPC601 -- paulus */
+	if (PVR_VER(mfspr(SPRN_PVR)) == 1)
+		return 1;
+
+	/*
+	 * The powersurge cpu board can be used in the generation
+	 * of powermacs that have a socket for an upgradeable cpu card,
+	 * including the 7500, 8500, 9500, 9600.
+	 * The device tree doesn't tell you if you have 2 cpus because
+	 * OF doesn't know anything about the 2nd processor.
+	 * Instead we look for magic bits in magic registers,
+	 * in the hammerhead memory controller in the case of the
+	 * dual-cpu powersurge board.  -- paulus.
+	 */
+	if (find_devices("hammerhead") == NULL)
+		return 1;
+
+	hhead_base = ioremap(HAMMERHEAD_BASE, 0x800);
+	quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024);
+	psurge_sec_intr = hhead_base + HHEAD_SEC_INTR;
+
+	psurge_type = psurge_quad_probe();
+	if (psurge_type != PSURGE_DUAL) {
+		psurge_quad_init();
+		/* All released cards using this HW design have 4 CPUs */
+		ncpus = 4;
+	} else {
+		iounmap((void *) quad_base);
+		if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
+			/* not a dual-cpu card */
+			iounmap((void *) hhead_base);
+			psurge_type = PSURGE_NONE;
+			return 1;
+		}
+		ncpus = 2;
+	}
+
+	psurge_start = ioremap(PSURGE_START, 4);
+	psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
+
+	/* this is not actually strictly necessary -- paulus. */
+	for (i = 1; i < ncpus; ++i)
+		smp_hw_index[i] = i;
+
+	if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352);
+
+	return ncpus;
+}
+
+static void __init smp_psurge_kick_cpu(int nr)
+{
+	void (*start)(void) = __secondary_start_psurge;
+	unsigned long a;
+
+	/* may need to flush here if secondary bats aren't setup */
+	for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
+		asm volatile("dcbf 0,%0" : : "r" (a) : "memory");
+	asm volatile("sync");
+
+	if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);
+
+	/* setup entry point of secondary processor */
+	switch (nr) {
+	case 2:
+		start = __secondary_start_psurge2;
+		break;
+	case 3:
+		start = __secondary_start_psurge3;
+		break;
+	}
+
+	out_be32(psurge_start, __pa(start));
+	mb();
+
+	psurge_set_ipi(nr);
+	udelay(10);
+	psurge_clr_ipi(nr);
+
+	if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
+}
+
+/*
+ * With the dual-cpu powersurge board, the decrementers and timebases
+ * of both cpus are frozen after the secondary cpu is started up,
+ * until we give the secondary cpu another interrupt.  This routine
+ * uses this to get the timebases synchronized.
+ *  -- paulus.
+ */
+static void __init psurge_dual_sync_tb(int cpu_nr)
+{
+	int t;
+
+	set_dec(tb_ticks_per_jiffy);
+	set_tb(0, 0);
+	last_jiffy_stamp(cpu_nr) = 0;
+
+	if (cpu_nr > 0) {
+		mb();
+		sec_tb_reset = 1;
+		return;
+	}
+
+	/* wait for the secondary to have reset its TB before proceeding */
+	for (t = 10000000; t > 0 && !sec_tb_reset; --t)
+		;
+
+	/* now interrupt the secondary, starting both TBs */
+	psurge_set_ipi(1);
+
+	smp_tb_synchronized = 1;
+}
+
+static struct irqaction psurge_irqaction = {
+	.handler = psurge_primary_intr,
+	.flags = SA_INTERRUPT,
+	.mask = CPU_MASK_NONE,
+	.name = "primary IPI",
+};
+
+static void __init smp_psurge_setup_cpu(int cpu_nr)
+{
+
+	if (cpu_nr == 0) {
+		/* If we failed to start the second CPU, we should still
+		 * send it an IPI to start the timebase & DEC or we might
+		 * have them stuck.
+		 */
+		if (num_online_cpus() < 2) {
+			if (psurge_type == PSURGE_DUAL)
+				psurge_set_ipi(1);
+			return;
+		}
+		/* reset the entry point so if we get another intr we won't
+		 * try to startup again */
+		out_be32(psurge_start, 0x100);
+		if (setup_irq(30, &psurge_irqaction))
+			printk(KERN_ERR "Couldn't get primary IPI interrupt");
+	}
+
+	if (psurge_type == PSURGE_DUAL)
+		psurge_dual_sync_tb(cpu_nr);
+}
+
+void __init smp_psurge_take_timebase(void)
+{
+	/* Dummy implementation */
+}
+
+void __init smp_psurge_give_timebase(void)
+{
+	/* Dummy implementation */
+}
+
+static int __init smp_core99_probe(void)
+{
+#ifdef CONFIG_6xx
+	extern int powersave_nap;
+#endif
+	struct device_node *cpus, *firstcpu;
+	int i, ncpus = 0, boot_cpu = -1;
+	u32 *tbprop;
+
+	if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
+	cpus = firstcpu = find_type_devices("cpu");
+	while(cpus != NULL) {
+		u32 *regprop = (u32 *)get_property(cpus, "reg", NULL);
+		char *stateprop = (char *)get_property(cpus, "state", NULL);
+		if (regprop != NULL && stateprop != NULL &&
+		    !strncmp(stateprop, "running", 7))
+			boot_cpu = *regprop;
+		++ncpus;
+		cpus = cpus->next;
+	}
+	if (boot_cpu == -1)
+		printk(KERN_WARNING "Couldn't detect boot CPU !\n");
+	if (boot_cpu != 0)
+		printk(KERN_WARNING "Boot CPU is %d, unsupported setup !\n", boot_cpu);
+
+	if (machine_is_compatible("MacRISC4")) {
+		extern struct smp_ops_t core99_smp_ops;
+
+		core99_smp_ops.take_timebase = smp_generic_take_timebase;
+		core99_smp_ops.give_timebase = smp_generic_give_timebase;
+	} else {
+		if (firstcpu != NULL)
+			tbprop = (u32 *)get_property(firstcpu, "timebase-enable", NULL);
+		if (tbprop)
+			core99_tb_gpio = *tbprop;
+		else
+			core99_tb_gpio = KL_GPIO_TB_ENABLE;
+	}
+
+	if (ncpus > 1) {
+		openpic_request_IPIs();
+		for (i = 1; i < ncpus; ++i)
+			smp_hw_index[i] = i;
+#ifdef CONFIG_6xx
+		powersave_nap = 0;
+#endif
+		core99_init_caches(0);
+	}
+
+	return ncpus;
+}
+
+static void __init smp_core99_kick_cpu(int nr)
+{
+	unsigned long save_vector, new_vector;
+	unsigned long flags;
+
+	volatile unsigned long *vector
+		 = ((volatile unsigned long *)(KERNELBASE+0x100));
+	if (nr < 1 || nr > 3)
+		return;
+	if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
+
+	local_irq_save(flags);
+	local_irq_disable();
+
+	/* Save reset vector */
+	save_vector = *vector;
+
+	/* Setup fake reset vector that does	
+	 *   b __secondary_start_psurge - KERNELBASE
+	 */
+	switch(nr) {
+		case 1:
+			new_vector = (unsigned long)__secondary_start_psurge;
+			break;
+		case 2:
+			new_vector = (unsigned long)__secondary_start_psurge2;
+			break;
+		case 3:
+			new_vector = (unsigned long)__secondary_start_psurge3;
+			break;
+	}
+	*vector = 0x48000002 + new_vector - KERNELBASE;
+
+	/* flush data cache and inval instruction cache */
+	flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
+
+	/* Put some life in our friend */
+	pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0);
+
+	/* FIXME: We wait a bit for the CPU to take the exception, I should
+	 * instead wait for the entry code to set something for me. Well,
+	 * ideally, all that crap will be done in prom.c and the CPU left
+	 * in a RAM-based wait loop like CHRP.
+	 */
+	mdelay(1);
+
+	/* Restore our exception vector */
+	*vector = save_vector;
+	flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
+
+	local_irq_restore(flags);
+	if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
+}
+
+static void __init smp_core99_setup_cpu(int cpu_nr)
+{
+	/* Setup L2/L3 */
+	if (cpu_nr != 0)
+		core99_init_caches(cpu_nr);
+
+	/* Setup openpic */
+	do_openpic_setup_cpu();
+
+	if (cpu_nr == 0) {
+#ifdef CONFIG_POWER4
+		extern void g5_phy_disable_cpu1(void);
+
+		/* If we didn't start the second CPU, we must take
+		 * it off the bus
+		 */
+		if (machine_is_compatible("MacRISC4") &&
+		    num_online_cpus() < 2)		
+			g5_phy_disable_cpu1();
+#endif /* CONFIG_POWER4 */
+		if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
+	}
+}
+
+void __init smp_core99_take_timebase(void)
+{
+	/* Secondary processor "takes" the timebase by freezing
+	 * it, resetting its local TB and telling CPU 0 to go on
+	 */
+	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4);
+	pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
+	mb();
+
+	set_dec(tb_ticks_per_jiffy);
+	set_tb(0, 0);
+	last_jiffy_stamp(smp_processor_id()) = 0;
+
+	mb();
+       	sec_tb_reset = 1;
+}
+
+void __init smp_core99_give_timebase(void)
+{
+	unsigned int t;
+
+	/* Primary processor waits for secondary to have frozen
+	 * the timebase, resets local TB, and kick timebase again
+	 */
+	/* wait for the secondary to have reset its TB before proceeding */
+	for (t = 1000; t > 0 && !sec_tb_reset; --t)
+		udelay(1000);
+	if (t == 0)
+		printk(KERN_WARNING "Timeout waiting sync on second CPU\n");
+
+       	set_dec(tb_ticks_per_jiffy);
+	set_tb(0, 0);
+	last_jiffy_stamp(smp_processor_id()) = 0;
+	mb();
+
+	/* Now, restart the timebase by leaving the GPIO to an open collector */
+       	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);
+        pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
+
+	smp_tb_synchronized = 1;
+}
+
+
+/* PowerSurge-style Macs */
+struct smp_ops_t psurge_smp_ops __pmacdata = {
+	.message_pass	= smp_psurge_message_pass,
+	.probe		= smp_psurge_probe,
+	.kick_cpu	= smp_psurge_kick_cpu,
+	.setup_cpu	= smp_psurge_setup_cpu,
+	.give_timebase	= smp_psurge_give_timebase,
+	.take_timebase	= smp_psurge_take_timebase,
+};
+
+/* Core99 Macs (dual G4s) */
+struct smp_ops_t core99_smp_ops __pmacdata = {
+	.message_pass	= smp_openpic_message_pass,
+	.probe		= smp_core99_probe,
+	.kick_cpu	= smp_core99_kick_cpu,
+	.setup_cpu	= smp_core99_setup_cpu,
+	.give_timebase	= smp_core99_give_timebase,
+	.take_timebase	= smp_core99_take_timebase,
+};
diff --git a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c
new file mode 100644
index 0000000..0963654
--- /dev/null
+++ b/arch/ppc/platforms/pmac_time.c
@@ -0,0 +1,292 @@
+/*
+ * Support for periodic interrupts (100 per second) and for getting
+ * the current time from the RTC on Power Macintoshes.
+ *
+ * We use the decrementer register for our periodic interrupts.
+ *
+ * Paul Mackerras	August 1996.
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <linux/pmu.h>
+#include <linux/hardirq.h>
+
+#include <asm/sections.h>
+#include <asm/prom.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/nvram.h>
+
+/* Apparently the RTC stores seconds since 1 Jan 1904 */
+#define RTC_OFFSET	2082844800
+
+/*
+ * Calibrate the decrementer frequency with the VIA timer 1.
+ */
+#define VIA_TIMER_FREQ_6	4700000	/* time 1 frequency * 6 */
+
+/* VIA registers */
+#define RS		0x200		/* skip between registers */
+#define T1CL		(4*RS)		/* Timer 1 ctr/latch (low 8 bits) */
+#define T1CH		(5*RS)		/* Timer 1 counter (high 8 bits) */
+#define T1LL		(6*RS)		/* Timer 1 latch (low 8 bits) */
+#define T1LH		(7*RS)		/* Timer 1 latch (high 8 bits) */
+#define ACR		(11*RS)		/* Auxiliary control register */
+#define IFR		(13*RS)		/* Interrupt flag register */
+
+/* Bits in ACR */
+#define T1MODE		0xc0		/* Timer 1 mode */
+#define T1MODE_CONT	0x40		/*  continuous interrupts */
+
+/* Bits in IFR and IER */
+#define T1_INT		0x40		/* Timer 1 interrupt */
+
+extern struct timezone sys_tz;
+
+long __init
+pmac_time_init(void)
+{
+#ifdef CONFIG_NVRAM
+	s32 delta = 0;
+	int dst;
+	
+	delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
+	delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8;
+	delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb);
+	if (delta & 0x00800000UL)
+		delta |= 0xFF000000UL;
+	dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
+	printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
+		dst ? "on" : "off");
+	return delta;
+#else
+	return 0;
+#endif
+}
+
+unsigned long __pmac
+pmac_get_rtc_time(void)
+{
+#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
+	struct adb_request req;
+	unsigned long now;
+#endif
+
+	/* Get the time from the RTC */
+	switch (sys_ctrler) {
+#ifdef CONFIG_ADB_CUDA
+	case SYS_CTRLER_CUDA:
+		if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
+			return 0;
+		while (!req.complete)
+			cuda_poll();
+		if (req.reply_len != 7)
+			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
+			       req.reply_len);
+		now = (req.reply[3] << 24) + (req.reply[4] << 16)
+			+ (req.reply[5] << 8) + req.reply[6];
+		return now - RTC_OFFSET;
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_ADB_PMU
+	case SYS_CTRLER_PMU:
+		if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
+			return 0;
+		while (!req.complete)
+			pmu_poll();
+		if (req.reply_len != 4)
+			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
+			       req.reply_len);
+		now = (req.reply[0] << 24) + (req.reply[1] << 16)
+			+ (req.reply[2] << 8) + req.reply[3];
+		return now - RTC_OFFSET;
+#endif /* CONFIG_ADB_PMU */
+	default: ;
+	}
+	return 0;
+}
+
+int __pmac
+pmac_set_rtc_time(unsigned long nowtime)
+{
+#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
+	struct adb_request req;
+#endif
+
+	nowtime += RTC_OFFSET;
+
+	switch (sys_ctrler) {
+#ifdef CONFIG_ADB_CUDA
+	case SYS_CTRLER_CUDA:
+		if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
+				 nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
+			return 0;
+		while (!req.complete)
+			cuda_poll();
+		if ((req.reply_len != 3) && (req.reply_len != 7))
+			printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
+			       req.reply_len);
+		return 1;
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_ADB_PMU
+	case SYS_CTRLER_PMU:
+		if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
+				nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
+			return 0;
+		while (!req.complete)
+			pmu_poll();
+		if (req.reply_len != 0)
+			printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
+			       req.reply_len);
+		return 1;
+#endif /* CONFIG_ADB_PMU */
+	default:
+		return 0;
+	}
+}
+
+/*
+ * Calibrate the decrementer register using VIA timer 1.
+ * This is used both on powermacs and CHRP machines.
+ */
+int __init
+via_calibrate_decr(void)
+{
+	struct device_node *vias;
+	volatile unsigned char *via;
+	int count = VIA_TIMER_FREQ_6 / 100;
+	unsigned int dstart, dend;
+
+	vias = find_devices("via-cuda");
+	if (vias == 0)
+		vias = find_devices("via-pmu");
+	if (vias == 0)
+		vias = find_devices("via");
+	if (vias == 0 || vias->n_addrs == 0)
+		return 0;
+	via = (volatile unsigned char *)
+		ioremap(vias->addrs[0].address, vias->addrs[0].size);
+
+	/* set timer 1 for continuous interrupts */
+	out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
+	/* set the counter to a small value */
+	out_8(&via[T1CH], 2);
+	/* set the latch to `count' */
+	out_8(&via[T1LL], count);
+	out_8(&via[T1LH], count >> 8);
+	/* wait until it hits 0 */
+	while ((in_8(&via[IFR]) & T1_INT) == 0)
+		;
+	dstart = get_dec();
+	/* clear the interrupt & wait until it hits 0 again */
+	in_8(&via[T1CL]);
+	while ((in_8(&via[IFR]) & T1_INT) == 0)
+		;
+	dend = get_dec();
+
+	tb_ticks_per_jiffy = (dstart - dend) / (6 * (HZ/100));
+	tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);
+
+	printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
+	       tb_ticks_per_jiffy, dstart - dend);
+
+	iounmap((void*)via);
+	
+	return 1;
+}
+
+#ifdef CONFIG_PMAC_PBOOK
+/*
+ * Reset the time after a sleep.
+ */
+static int __pmac
+time_sleep_notify(struct pmu_sleep_notifier *self, int when)
+{
+	static unsigned long time_diff;
+	unsigned long flags;
+	unsigned long seq;
+
+	switch (when) {
+	case PBOOK_SLEEP_NOW:
+		do {
+			seq = read_seqbegin_irqsave(&xtime_lock, flags);
+			time_diff = xtime.tv_sec - pmac_get_rtc_time();
+		} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
+		break;
+	case PBOOK_WAKE:
+		write_seqlock_irqsave(&xtime_lock, flags);
+		xtime.tv_sec = pmac_get_rtc_time() + time_diff;
+		xtime.tv_nsec = 0;
+		last_rtc_update = xtime.tv_sec;
+		write_sequnlock_irqrestore(&xtime_lock, flags);
+		break;
+	}
+	return PBOOK_SLEEP_OK;
+}
+
+static struct pmu_sleep_notifier time_sleep_notifier __pmacdata = {
+	time_sleep_notify, SLEEP_LEVEL_MISC,
+};
+#endif /* CONFIG_PMAC_PBOOK */
+
+/*
+ * Query the OF and get the decr frequency.
+ * This was taken from the pmac time_init() when merging the prep/pmac
+ * time functions.
+ */
+void __init
+pmac_calibrate_decr(void)
+{
+	struct device_node *cpu;
+	unsigned int freq, *fp;
+
+#ifdef CONFIG_PMAC_PBOOK
+	pmu_register_sleep_notifier(&time_sleep_notifier);
+#endif /* CONFIG_PMAC_PBOOK */
+
+	/* We assume MacRISC2 machines have correct device-tree
+	 * calibration. That's better since the VIA itself seems
+	 * to be slightly off. --BenH
+	 */
+	if (!machine_is_compatible("MacRISC2") &&
+	    !machine_is_compatible("MacRISC3") &&
+	    !machine_is_compatible("MacRISC4"))
+		if (via_calibrate_decr())
+			return;
+
+	/* Special case: QuickSilver G4s seem to have a badly calibrated
+	 * timebase-frequency in OF, VIA is much better on these. We should
+	 * probably implement calibration based on the KL timer on these
+	 * machines anyway... -BenH
+	 */
+	if (machine_is_compatible("PowerMac3,5"))
+		if (via_calibrate_decr())
+			return;
+	/*
+	 * The cpu node should have a timebase-frequency property
+	 * to tell us the rate at which the decrementer counts.
+	 */
+	cpu = find_type_devices("cpu");
+	if (cpu == 0)
+		panic("can't find cpu node in time_init");
+	fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL);
+	if (fp == 0)
+		panic("can't get cpu timebase frequency");
+	freq = *fp;
+	printk("time_init: decrementer frequency = %u.%.6u MHz\n",
+	       freq/1000000, freq%1000000);
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
diff --git a/arch/ppc/platforms/powerpmc250.c b/arch/ppc/platforms/powerpmc250.c
new file mode 100644
index 0000000..0abe151
--- /dev/null
+++ b/arch/ppc/platforms/powerpmc250.c
@@ -0,0 +1,383 @@
+/*
+ * arch/ppc/platforms/powerpmc250.c
+ *
+ * Board setup routines for Force PowerPMC-250 Processor PMC
+ *
+ * Author: Troy Benjegerdes <tbenjegerdes@mvista.com>
+ * Borrowed heavily from prpmc750_*.c by
+ * 	Matt Porter <mporter@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc.  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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <linux/ide.h>
+#include <linux/root_dev.h>
+
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <platforms/powerpmc250.h>
+#include <asm/open_pic.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc10x.h>
+#include <asm/uaccess.h>
+#include <asm/bootinfo.h>
+
+extern void powerpmc250_find_bridges(void);
+extern unsigned long loops_per_jiffy;
+
+static u_char powerpmc250_openpic_initsenses[] __initdata =
+{
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    1,	/* PMC INTA (also MPC107 output interrupt INTA) */
+    1,	/* PMC INTB (also I82559 Ethernet controller) */
+    1,	/* PMC INTC */
+    1,	/* PMC INTD */
+    0,	/* DUART interrupt (active high) */
+};
+
+static int
+powerpmc250_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m,"machine\t\t: Force PowerPMC250\n");
+
+	return 0;
+}
+
+static void __init
+powerpmc250_setup_arch(void)
+{
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000/HZ;
+
+	/* Lookup PCI host bridges */
+	powerpmc250_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA2;
+#endif
+
+	printk("Force PowerPMC250 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n");
+}
+
+#if 0
+/*
+ * Compute the PrPMC750's bus speed using the baud clock as a
+ * reference.
+ */
+unsigned long __init powerpmc250_get_bus_speed(void)
+{
+	unsigned long tbl_start, tbl_end;
+	unsigned long current_state, old_state, bus_speed;
+	unsigned char lcr, dll, dlm;
+	int baud_divisor, count;
+
+	/* Read the UART's baud clock divisor */
+	lcr = readb(PRPMC750_SERIAL_0_LCR);
+	writeb(lcr | UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR);
+	dll = readb(PRPMC750_SERIAL_0_DLL);
+	dlm = readb(PRPMC750_SERIAL_0_DLM);
+	writeb(lcr & ~UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR);
+	baud_divisor = (dlm << 8) | dll;
+
+	/*
+	 * Use the baud clock divisor and base baud clock
+	 * to determine the baud rate and use that as
+	 * the number of baud clock edges we use for
+	 * the time base sample.  Make it half the baud
+	 * rate.
+	 */
+	count = PRPMC750_BASE_BAUD / (baud_divisor * 16);
+
+	/* Find the first edge of the baud clock */
+	old_state = readb(PRPMC750_STATUS_REG) & PRPMC750_BAUDOUT_MASK;
+	do {
+		current_state = readb(PRPMC750_STATUS_REG) &
+			PRPMC750_BAUDOUT_MASK;
+	} while(old_state == current_state);
+
+	old_state = current_state;
+
+	/* Get the starting time base value */
+	tbl_start = get_tbl();
+
+	/*
+	 * Loop until we have found a number of edges equal
+	 * to half the count (half the baud rate)
+	 */
+	do {
+		do {
+			current_state = readb(PRPMC750_STATUS_REG) &
+				PRPMC750_BAUDOUT_MASK;
+		} while(old_state == current_state);
+		old_state = current_state;
+	} while (--count);
+
+	/* Get the ending time base value */
+	tbl_end = get_tbl();
+
+	/* Compute bus speed */
+	bus_speed = (tbl_end-tbl_start)*128;
+
+	return bus_speed;
+}
+#endif
+
+static void __init
+powerpmc250_calibrate_decr(void)
+{
+	unsigned long freq;
+	int divisor = 4;
+
+	//freq = powerpmc250_get_bus_speed();
+#warning hardcoded bus freq
+	freq = 100000000;
+
+	tb_ticks_per_jiffy = freq / (HZ * divisor);
+	tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+}
+
+static void
+powerpmc250_restart(char *cmd)
+{
+	local_irq_disable();
+	/* Hard reset */
+	writeb(0x11, 0xfe000332);
+	while(1);
+}
+
+static void
+powerpmc250_halt(void)
+{
+	local_irq_disable();
+	while (1);
+}
+
+static void
+powerpmc250_power_off(void)
+{
+	powerpmc250_halt();
+}
+
+static void __init
+powerpmc250_init_IRQ(void)
+{
+
+	OpenPIC_InitSenses = powerpmc250_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof(powerpmc250_openpic_initsenses);
+	mpc10x_set_openpic();
+}
+
+/*
+ * Set BAT 3 to map 0xf0000000 to end of physical memory space.
+ */
+static __inline__ void
+powerpmc250_set_bat(void)
+{
+	unsigned long   bat3u, bat3l;
+	static int	mapping_set = 0;
+
+	if (!mapping_set)
+	{
+		__asm__ __volatile__(
+				" lis %0,0xf000\n \
+				ori %1,%0,0x002a\n \
+				ori %0,%0,0x1ffe\n \
+				mtspr 0x21e,%0\n \
+				mtspr 0x21f,%1\n \
+				isync\n \
+				sync "
+				: "=r" (bat3u), "=r" (bat3l));
+
+		mapping_set = 1;
+	}
+	return;
+}
+
+static unsigned long __init
+powerpmc250_find_end_of_memory(void)
+{
+	/* Cover I/O space with a BAT */
+	/* yuck, better hope your ram size is a power of 2  -- paulus */
+	powerpmc250_set_bat();
+
+	return mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
+}
+
+static void __init
+powerpmc250_map_io(void)
+{
+	io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if ( r4 )
+	{
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif
+
+	/* Copy cmd_line parameters */
+	if ( r6)
+	{
+		*(char *)(r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *)(r6 + KERNELBASE));
+	}
+
+	isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
+	isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
+	pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
+
+	ppc_md.setup_arch	= powerpmc250_setup_arch;
+	ppc_md.show_cpuinfo	= powerpmc250_show_cpuinfo;
+	ppc_md.init_IRQ		= powerpmc250_init_IRQ;
+	ppc_md.get_irq		= openpic_get_irq;
+
+	ppc_md.find_end_of_memory = powerpmc250_find_end_of_memory;
+	ppc_md.setup_io_mappings = powerpmc250_map_io;
+
+	ppc_md.restart		= powerpmc250_restart;
+	ppc_md.power_off	= powerpmc250_power_off;
+	ppc_md.halt		= powerpmc250_halt;
+
+	/* PowerPMC250 has no timekeeper part */
+	ppc_md.time_init	= NULL;
+	ppc_md.get_rtc_time	= NULL;
+	ppc_md.set_rtc_time	= NULL;
+	ppc_md.calibrate_decr	= powerpmc250_calibrate_decr;
+}
+
+
+/*
+ * (This used to be arch/ppc/platforms/powerpmc250_pci.c)
+ *
+ * PCI support for Force PowerPMC250
+ *
+ */
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* DEBUG */
+
+static inline int __init
+powerpmc250_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	/*
+	 *      PCI IDSEL/INTPIN->INTLINE
+	 *      A       B       C       D
+	 */
+	{
+		{17,	0,	0,	0},	/* Device 11 - 82559 */
+		{0,	0,	0,	0},	/* 12 */
+		{0,	0,	0,	0},	/* 13 */
+		{0,	0,	0,	0},	/* 14 */
+		{0,	0,	0,	0},	/* 15 */
+		{16,	17,	18,	19},	/* Device 16 - PMC A1?? */
+		};
+	const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+};
+
+static int
+powerpmc250_exclude_device(u_char bus, u_char devfn)
+{
+	/*
+	 * While doing PCI Scan  the MPC107 will 'detect' itself as
+	 * device on the PCI Bus, will create an incorrect response and
+	 * later will respond incorrectly to Configuration read coming
+	 * from another device.
+	 *
+	 * The work around is that when doing a PCI Scan one
+	 * should skip its own device number in the scan.
+	 *
+	 * The top IDsel is AD13 and the middle is AD14.
+	 *
+	 * -- Note from force
+	 */
+
+	if ((bus == 0) && (PCI_SLOT(devfn) == 13 || PCI_SLOT(devfn) == 14)) {
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+	else {
+		return PCIBIOS_SUCCESSFUL;
+	}
+}
+
+void __init
+powerpmc250_find_bridges(void)
+{
+	struct pci_controller* hose;
+
+	hose = pcibios_alloc_controller();
+	if (!hose){
+		printk("Can't allocate PCI 'hose' structure!!!\n");
+		return;
+	}
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	if (mpc10x_bridge_init(hose,
+			MPC10X_MEM_MAP_B,
+			MPC10X_MEM_MAP_B,
+			MPC10X_MAPB_EUMB_BASE) == 0) {
+
+		hose->mem_resources[0].end = 0xffffffff;
+
+		hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+		/* ppc_md.pcibios_fixup = pcore_pcibios_fixup; */
+		ppc_md.pci_swizzle = common_swizzle;
+
+		ppc_md.pci_exclude_device = powerpmc250_exclude_device;
+		ppc_md.pci_map_irq = powerpmc250_map_irq;
+	} else {
+		if (ppc_md.progress)
+			ppc_md.progress("Bridge init failed", 0x100);
+		printk("Host bridge init failed\n");
+	}
+
+}
diff --git a/arch/ppc/platforms/powerpmc250.h b/arch/ppc/platforms/powerpmc250.h
new file mode 100644
index 0000000..41a6dc8
--- /dev/null
+++ b/arch/ppc/platforms/powerpmc250.h
@@ -0,0 +1,52 @@
+/*
+ * include/asm-ppc/platforms/powerpmc250.h
+ *
+ * Definitions for Force PowerPMC-250 board support
+ *
+ * Author: Troy Benjegerdes <tbenjegerdes@mvista.com>
+ *
+ * Borrowed heavily from prpmc750.h by Matt Porter <mporter@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifndef __ASMPPC_POWERPMC250_H
+#define __ASMPPC_POWERPMC250_H
+
+#define POWERPMC250_PCI_CONFIG_ADDR	0x80000cf8
+#define POWERPMC250_PCI_CONFIG_DATA	0x80000cfc
+
+#define POWERPMC250_PCI_PHY_MEM_BASE	0xc0000000
+#define POWERPMC250_PCI_MEM_BASE		0xf0000000
+#define POWERPMC250_PCI_IO_BASE		0x80000000
+
+#define POWERPMC250_ISA_IO_BASE		POWERPMC250_PCI_IO_BASE
+#define POWERPMC250_ISA_MEM_BASE		POWERPMC250_PCI_MEM_BASE
+#define POWERPMC250_PCI_MEM_OFFSET		POWERPMC250_PCI_PHY_MEM_BASE
+
+#define POWERPMC250_SYS_MEM_BASE		0x80000000
+
+#define POWERPMC250_HAWK_SMC_BASE		0xfef80000
+
+#define POWERPMC250_BASE_BAUD		12288000
+#define POWERPMC250_SERIAL		0xff000000
+#define POWERPMC250_SERIAL_IRQ		20
+
+/* UART Defines. */
+#define RS_TABLE_SIZE  1
+
+#define BASE_BAUD  (POWERPMC250_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+#define SERIAL_PORT_DFNS \
+	{ 0, BASE_BAUD, POWERPMC250_SERIAL, POWERPMC250_SERIAL_IRQ,	\
+		STD_COM_FLAGS, 				/* ttyS0 */	\
+		iomem_base: (u8 *)POWERPMC250_SERIAL,			\
+		iomem_reg_shift: 0,					\
+		io_type: SERIAL_IO_MEM }
+
+#endif /* __ASMPPC_POWERPMC250_H */
diff --git a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c
new file mode 100644
index 0000000..65705c9
--- /dev/null
+++ b/arch/ppc/platforms/pplus.c
@@ -0,0 +1,917 @@
+/*
+ * arch/ppc/platforms/pplus.c
+ *
+ * Board and PCI setup routines for MCG PowerPlus
+ *
+ * Author: Randy Vinson <rvinson@mvista.com>
+ *
+ * Derived from original PowerPlus PReP work by
+ * Cort Dougan, Johnnie Peters, Matt Porter, and
+ * Troy Benjegerdes.
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc.  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/interrupt.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/console.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/prep_nvram.h>
+#include <asm/vga.h>
+#include <asm/i8259.h>
+#include <asm/open_pic.h>
+#include <asm/hawk.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/kgdb.h>
+#include <asm/reg.h>
+
+#include "pplus.h"
+
+#undef DUMP_DBATS
+
+TODC_ALLOC();
+
+extern void pplus_setup_hose(void);
+extern void pplus_set_VIA_IDE_native(void);
+
+extern unsigned long loops_per_jiffy;
+unsigned char *Motherboard_map_name;
+
+/* Tables for known hardware */
+
+/* Motorola Mesquite */
+static inline int
+mesquite_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	    /*
+	     *      MPIC interrupts for various IDSEL values (MPIC IRQ0 =
+	     *      Linux IRQ16 (to leave room for ISA IRQs at 0-15).
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *         A   B   C   D
+	     */
+	{
+		{18,  0,  0,  0},	/* IDSEL 14 - Enet 0 */
+		{ 0,  0,  0,  0},	/* IDSEL 15 - unused */
+		{19, 19, 19, 19},	/* IDSEL 16 - PMC Slot 1 */
+		{ 0,  0,  0,  0},	/* IDSEL 17 - unused */
+		{ 0,  0,  0,  0},	/* IDSEL 18 - unused */
+		{ 0,  0,  0,  0},	/* IDSEL 19 - unused */
+		{24, 25, 26, 27},	/* IDSEL 20 - P2P bridge (to cPCI 1) */
+		{ 0,  0,  0,  0},	/* IDSEL 21 - unused */
+		{28, 29, 30, 31}	/* IDSEL 22 - P2P bridge (to cPCI 2) */
+	};
+
+	const long min_idsel = 14, max_idsel = 22, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+/* Motorola Sitka */
+static inline int
+sitka_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	    /*
+	     *      MPIC interrupts for various IDSEL values (MPIC IRQ0 =
+	     *      Linux IRQ16 (to leave room for ISA IRQs at 0-15).
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *         A   B   C   D
+	     */
+	{
+		{18,  0,  0,  0},	/* IDSEL 14 - Enet 0 */
+		{ 0,  0,  0,  0},	/* IDSEL 15 - unused */
+		{25, 26, 27, 28},	/* IDSEL 16 - PMC Slot 1 */
+		{28, 25, 26, 27},	/* IDSEL 17 - PMC Slot 2 */
+		{ 0,  0,  0,  0},	/* IDSEL 18 - unused */
+		{ 0,  0,  0,  0},	/* IDSEL 19 - unused */
+		{20,  0,  0,  0}	/* IDSEL 20 - P2P bridge (to cPCI) */
+	};
+
+	const long min_idsel = 14, max_idsel = 20, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+/* Motorola MTX */
+static inline int
+MTX_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	    /*
+	     *      MPIC interrupts for various IDSEL values (MPIC IRQ0 =
+	     *      Linux IRQ16 (to leave room for ISA IRQs at 0-15).
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *         A   B   C   D
+	     */
+	{
+		{19,  0,  0,  0},	/* IDSEL 12 - SCSI   */
+		{ 0,  0,  0,  0},	/* IDSEL 13 - unused */
+		{18,  0,  0,  0},	/* IDSEL 14 - Enet   */
+		{ 0,  0,  0,  0},	/* IDSEL 15 - unused */
+		{25, 26, 27, 28},	/* IDSEL 16 - PMC Slot 1 */
+		{26, 27, 28, 25},	/* IDSEL 17 - PMC Slot 2 */
+		{27, 28, 25, 26}	/* IDSEL 18 - PCI Slot 3 */
+	};
+
+	const long min_idsel = 12, max_idsel = 18, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+/* Motorola MTX Plus */
+/* Secondary bus interrupt routing is not supported yet */
+static inline int
+MTXplus_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	    /*
+	     *      MPIC interrupts for various IDSEL values (MPIC IRQ0 =
+	     *      Linux IRQ16 (to leave room for ISA IRQs at 0-15).
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *         A   B   C   D
+	     */
+	{
+		{19,  0,  0,  0},	/* IDSEL 12 - SCSI   */
+		{ 0,  0,  0,  0},	/* IDSEL 13 - unused */
+		{18,  0,  0,  0},	/* IDSEL 14 - Enet 1 */
+		{ 0,  0,  0,  0},	/* IDSEL 15 - unused */
+		{25, 26, 27, 28},	/* IDSEL 16 - PCI Slot 1P */
+		{26, 27, 28, 25},	/* IDSEL 17 - PCI Slot 2P */
+		{27, 28, 25, 26},	/* IDSEL 18 - PCI Slot 3P */
+		{26,  0,  0,  0},	/* IDSEL 19 - Enet 2 */
+		{ 0,  0,  0,  0}	/* IDSEL 20 - P2P Bridge */
+	};
+
+	const long min_idsel = 12, max_idsel = 20, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static inline int
+Genesis2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	/* 2600
+	 * Raven 31
+	 * ISA   11
+	 * SCSI  12 - IRQ3
+	 * Univ  13
+	 * eth   14 - IRQ2
+	 * VGA   15 - IRQ4
+	 * PMC1  16 - IRQ9,10,11,12 = PMC1 A-D
+	 * PMC2  17 - IRQ12,9,10,11 = A-D
+	 * SCSI2 18 - IRQ11
+	 * eth2  19 - IRQ10
+	 * PCIX  20 - IRQ9,10,11,12 = PCI A-D
+	 */
+
+	/* 2400
+	 * Hawk 31
+	 * ISA  11
+	 * Univ 13
+	 * eth  14 - IRQ2
+	 * PMC1 16 - IRQ9,10,11,12 = PMC A-D
+	 * PMC2 17 - IRQ12,9,10,11 = PMC A-D
+	 * PCIX 20 - IRQ9,10,11,12 = PMC A-D
+	 */
+
+	/* 2300
+	 * Raven 31
+	 * ISA   11
+	 * Univ  13
+	 * eth   14 - IRQ2
+	 * PMC1  16 - 9,10,11,12 = A-D
+	 * PMC2  17 - 9,10,11,12 = B,C,D,A
+	 */
+
+	static char pci_irq_table[][4] =
+	    /*
+	     *      MPIC interrupts for various IDSEL values (MPIC IRQ0 =
+	     *      Linux IRQ16 (to leave room for ISA IRQs at 0-15).
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *         A   B   C   D
+	     */
+	{
+		{19,  0,  0,  0},	/* IDSEL 12 - SCSI   */
+		{ 0,  0,  0,  0},	/* IDSEL 13 - Universe PCI - VME */
+		{18,  0,  0,  0},	/* IDSEL 14 - Enet 1 */
+		{ 0,  0,  0,  0},	/* IDSEL 15 - unused */
+		{25, 26, 27, 28},	/* IDSEL 16 - PCI/PMC Slot 1P */
+		{28, 25, 26, 27},	/* IDSEL 17 - PCI/PMC Slot 2P */
+		{27, 28, 25, 26},	/* IDSEL 18 - PCI Slot 3P */
+		{26,  0,  0,  0},	/* IDSEL 19 - Enet 2 */
+		{25, 26, 27, 28}	/* IDSEL 20 - P2P Bridge */
+	};
+
+	const long min_idsel = 12, max_idsel = 20, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+#define MOTOROLA_CPUTYPE_REG	0x800
+#define MOTOROLA_BASETYPE_REG	0x803
+#define MPIC_RAVEN_ID		0x48010000
+#define	MPIC_HAWK_ID		0x48030000
+#define	MOT_PROC2_BIT		0x800
+
+static u_char pplus_openpic_initsenses[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* MVME2600_INT_SIO */
+	(IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE),/*MVME2600_INT_FALCN_ECC_ERR */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/*MVME2600_INT_PCI_ETHERNET */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_SCSI */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/*MVME2600_INT_PCI_GRAPHICS */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTA */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTB */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTC */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTD */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_LM_SIG0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_LM_SIG1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),
+};
+
+int mot_entry = -1;
+int prep_keybd_present = 1;
+int mot_multi = 0;
+
+struct brd_info {
+	/* 0x100 mask assumes for Raven and Hawk boards that the level/edge
+	 * are set */
+	int cpu_type;
+	/* 0x200 if this board has a Hawk chip. */
+	int base_type;
+	/* or'ed with 0x80 if this board should be checked for multi CPU */
+	int max_cpu;
+	const char *name;
+	int (*map_irq) (struct pci_dev *, unsigned char, unsigned char);
+};
+struct brd_info mot_info[] = {
+	{0x300, 0x00, 0x00, "MVME 2400", Genesis2_map_irq},
+	{0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)", mesquite_map_irq},
+	{0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)", sitka_map_irq},
+	{0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC", mesquite_map_irq},
+	{0x1E0, 0xF6, 0x80, "MTX Plus", MTXplus_map_irq},
+	{0x1E0, 0xF6, 0x81, "Dual MTX Plus", MTXplus_map_irq},
+	{0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port", MTX_map_irq},
+	{0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port", MTX_map_irq},
+	{0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port", MTX_map_irq},
+	{0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port", MTX_map_irq},
+	{0x1E0, 0xF9, 0x00, "MVME 2300", Genesis2_map_irq},
+	{0x1E0, 0xFA, 0x00, "MVME 2300SC/2600", Genesis2_map_irq},
+	{0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M", Genesis2_map_irq},
+	{0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761", Genesis2_map_irq},
+	{0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M", Genesis2_map_irq},
+	{0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M", Genesis2_map_irq},
+	{0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761", Genesis2_map_irq},
+	{0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761", Genesis2_map_irq},
+	{0x000, 0x00, 0x00, "", NULL}
+};
+
+void __init pplus_set_board_type(void)
+{
+	unsigned char cpu_type;
+	unsigned char base_mod;
+	int entry;
+	unsigned short devid;
+	unsigned long *ProcInfo = NULL;
+
+	cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0;
+	base_mod = inb(MOTOROLA_BASETYPE_REG);
+	early_read_config_word(0, 0, 0, PCI_VENDOR_ID, &devid);
+
+	for (entry = 0; mot_info[entry].cpu_type != 0; entry++) {
+		/* Check for Hawk chip */
+		if (mot_info[entry].cpu_type & 0x200) {
+			if (devid != PCI_DEVICE_ID_MOTOROLA_HAWK)
+				continue;
+		} else {
+			/* store the system config register for later use. */
+			ProcInfo =
+			    (unsigned long *)ioremap(PPLUS_SYS_CONFIG_REG, 4);
+
+			/* Check non hawk boards */
+			if ((mot_info[entry].cpu_type & 0xff) != cpu_type)
+				continue;
+
+			if (mot_info[entry].base_type == 0) {
+				mot_entry = entry;
+				break;
+			}
+
+			if (mot_info[entry].base_type != base_mod)
+				continue;
+		}
+
+		if (!(mot_info[entry].max_cpu & 0x80)) {
+			mot_entry = entry;
+			break;
+		}
+
+		/* processor 1 not present and max processor zero indicated */
+		if ((*ProcInfo & MOT_PROC2_BIT)
+		    && !(mot_info[entry].max_cpu & 0x7f)) {
+			mot_entry = entry;
+			break;
+		}
+
+		/* processor 1 present and max processor zero indicated */
+		if (!(*ProcInfo & MOT_PROC2_BIT)
+		    && (mot_info[entry].max_cpu & 0x7f)) {
+			mot_entry = entry;
+			break;
+		}
+
+		/* Indicate to system if this is a multiprocessor board */
+		if (!(*ProcInfo & MOT_PROC2_BIT))
+			mot_multi = 1;
+	}
+
+	if (mot_entry == -1)
+		/* No particular cpu type found - assume Mesquite (MCP750) */
+		mot_entry = 1;
+
+	Motherboard_map_name = (unsigned char *)mot_info[mot_entry].name;
+	ppc_md.pci_map_irq = mot_info[mot_entry].map_irq;
+}
+void __init pplus_pib_init(void)
+{
+	unsigned char reg;
+	unsigned short short_reg;
+
+	struct pci_dev *dev = NULL;
+
+	/*
+	 * Perform specific configuration for the Via Tech or
+	 * or Winbond PCI-ISA-Bridge part.
+	 */
+	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+				   PCI_DEVICE_ID_VIA_82C586_1, dev))) {
+		/*
+		 * PPCBUG does not set the enable bits
+		 * for the IDE device. Force them on here.
+		 */
+		pci_read_config_byte(dev, 0x40, &reg);
+
+		reg |= 0x03;	/* IDE: Chip Enable Bits */
+		pci_write_config_byte(dev, 0x40, reg);
+	}
+
+	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+				   PCI_DEVICE_ID_VIA_82C586_2,
+				   dev)) && (dev->devfn = 0x5a)) {
+		/* Force correct USB interrupt */
+		dev->irq = 11;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+	}
+
+	if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+				   PCI_DEVICE_ID_WINBOND_83C553, dev))) {
+		/* Clear PCI Interrupt Routing Control Register. */
+		short_reg = 0x0000;
+		pci_write_config_word(dev, 0x44, short_reg);
+		/* Route IDE interrupts to IRQ 14 */
+		reg = 0xEE;
+		pci_write_config_byte(dev, 0x43, reg);
+	}
+
+	if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+				   PCI_DEVICE_ID_WINBOND_82C105, dev))) {
+		/*
+		 * Disable LEGIRQ mode so PCI INTS are routed
+		 * directly to the 8259 and enable both channels
+		 */
+		pci_write_config_dword(dev, 0x40, 0x10ff0033);
+
+		/* Force correct IDE interrupt */
+		dev->irq = 14;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+	}
+	pci_dev_put(dev);
+}
+
+void __init pplus_set_VIA_IDE_legacy(void)
+{
+	unsigned short vend, dev;
+
+	early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend);
+	early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev);
+
+	if ((vend == PCI_VENDOR_ID_VIA) &&
+			(dev == PCI_DEVICE_ID_VIA_82C586_1)) {
+		unsigned char temp;
+
+		/* put back original "standard" port base addresses */
+		early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+					 PCI_BASE_ADDRESS_0, 0x1f1);
+		early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+					 PCI_BASE_ADDRESS_1, 0x3f5);
+		early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+					 PCI_BASE_ADDRESS_2, 0x171);
+		early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+					 PCI_BASE_ADDRESS_3, 0x375);
+		early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+					 PCI_BASE_ADDRESS_4, 0xcc01);
+
+		/* put into legacy mode */
+		early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+				       &temp);
+		temp &= ~0x05;
+		early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+					temp);
+	}
+}
+
+void pplus_set_VIA_IDE_native(void)
+{
+	unsigned short vend, dev;
+
+	early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend);
+	early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev);
+
+	if ((vend == PCI_VENDOR_ID_VIA) &&
+			(dev == PCI_DEVICE_ID_VIA_82C586_1)) {
+		unsigned char temp;
+
+		/* put into native mode */
+		early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+				       &temp);
+		temp |= 0x05;
+		early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+					temp);
+	}
+}
+
+void __init pplus_pcibios_fixup(void)
+{
+
+	unsigned char reg;
+	unsigned short devid;
+	unsigned char base_mod;
+
+	printk(KERN_INFO "Setting PCI interrupts for a \"%s\"\n",
+			Motherboard_map_name);
+
+	/* Setup the Winbond or Via PIB */
+	pplus_pib_init();
+
+	/* Set up floppy in PS/2 mode */
+	outb(0x09, SIO_CONFIG_RA);
+	reg = inb(SIO_CONFIG_RD);
+	reg = (reg & 0x3F) | 0x40;
+	outb(reg, SIO_CONFIG_RD);
+	outb(reg, SIO_CONFIG_RD);	/* Have to write twice to change! */
+
+	/* This is a hack.  If this is a 2300 or 2400 mot board then there is
+	 * no keyboard controller and we have to indicate that.
+	 */
+
+	early_read_config_word(0, 0, 0, PCI_VENDOR_ID, &devid);
+	base_mod = inb(MOTOROLA_BASETYPE_REG);
+	if ((devid == PCI_DEVICE_ID_MOTOROLA_HAWK) ||
+	    (base_mod == 0xF9) || (base_mod == 0xFA) || (base_mod == 0xE1))
+		prep_keybd_present = 0;
+}
+
+void __init pplus_find_bridges(void)
+{
+	struct pci_controller *hose;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	hose->pci_mem_offset = PREP_ISA_MEM_BASE;
+	hose->io_base_virt = (void *)PREP_ISA_IO_BASE;
+
+	pci_init_resource(&hose->io_resource, PPLUS_PCI_IO_START,
+			  PPLUS_PCI_IO_END, IORESOURCE_IO, "PCI host bridge");
+	pci_init_resource(&hose->mem_resources[0], PPLUS_PROC_PCI_MEM_START,
+			  PPLUS_PROC_PCI_MEM_END, IORESOURCE_MEM,
+			  "PCI host bridge");
+
+	hose->io_space.start = PPLUS_PCI_IO_START;
+	hose->io_space.end = PPLUS_PCI_IO_END;
+	hose->mem_space.start = PPLUS_PCI_MEM_START;
+	hose->mem_space.end = PPLUS_PCI_MEM_END - HAWK_MPIC_SIZE;
+
+	if (hawk_init(hose, PPLUS_HAWK_PPC_REG_BASE, PPLUS_PROC_PCI_MEM_START,
+				PPLUS_PROC_PCI_MEM_END - HAWK_MPIC_SIZE,
+				PPLUS_PROC_PCI_IO_START, PPLUS_PROC_PCI_IO_END,
+				PPLUS_PROC_PCI_MEM_END - HAWK_MPIC_SIZE + 1)
+			!= 0) {
+		printk(KERN_CRIT "Could not initialize host bridge\n");
+
+	}
+
+	pplus_set_VIA_IDE_legacy();
+
+	hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+	ppc_md.pcibios_fixup = pplus_pcibios_fixup;
+	ppc_md.pci_swizzle = common_swizzle;
+}
+
+static int pplus_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: Motorola MCG\n");
+	seq_printf(m, "machine\t\t: %s\n", Motherboard_map_name);
+
+	return 0;
+}
+
+static void __init pplus_setup_arch(void)
+{
+	struct pci_controller *hose;
+
+	if (ppc_md.progress)
+		ppc_md.progress("pplus_setup_arch: enter", 0);
+
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000;
+
+	if (ppc_md.progress)
+		ppc_md.progress("pplus_setup_arch: find_bridges", 0);
+
+	/* Setup PCI host bridge */
+	pplus_find_bridges();
+
+	hose = pci_bus_to_hose(0);
+	isa_io_base = (ulong) hose->io_base_virt;
+
+	if (ppc_md.progress)
+		ppc_md.progress("pplus_setup_arch: set_board_type", 0);
+
+	pplus_set_board_type();
+
+	/* Enable L2.  Assume we don't need to flush -- Cort */
+	*(unsigned char *)(PPLUS_L2_CONTROL_REG) |= 3;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA2;
+#endif
+
+	printk(KERN_INFO "Motorola PowerPlus Platform\n");
+	printk(KERN_INFO
+	       "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+
+#ifdef CONFIG_VGA_CONSOLE
+	/* remap the VGA memory */
+	vgacon_remap_base = (unsigned long)ioremap(PPLUS_ISA_MEM_BASE,
+						   0x08000000);
+	conswitchp = &vga_con;
+#endif
+#ifdef CONFIG_PPCBUG_NVRAM
+	/* Read in NVRAM data */
+	init_prep_nvram();
+
+	/* if no bootargs, look in NVRAM */
+	if (cmd_line[0] == '\0') {
+		char *bootargs;
+		bootargs = prep_nvram_get_var("bootargs");
+		if (bootargs != NULL) {
+			strcpy(cmd_line, bootargs);
+			/* again.. */
+			strcpy(saved_command_line, cmd_line);
+		}
+	}
+#endif
+	if (ppc_md.progress)
+		ppc_md.progress("pplus_setup_arch: exit", 0);
+}
+
+static void pplus_restart(char *cmd)
+{
+	unsigned long i = 10000;
+
+	local_irq_disable();
+
+	/* set VIA IDE controller into native mode */
+	pplus_set_VIA_IDE_native();
+
+	/* set exception prefix high - to the prom */
+	_nmask_and_or_msr(0, MSR_IP);
+
+	/* make sure bit 0 (reset) is a 0 */
+	outb(inb(0x92) & ~1L, 0x92);
+	/* signal a reset to system control port A - soft reset */
+	outb(inb(0x92) | 1, 0x92);
+
+	while (i != 0)
+		i++;
+	panic("restart failed\n");
+}
+
+static void pplus_halt(void)
+{
+	/* set exception prefix high - to the prom */
+	_nmask_and_or_msr(MSR_EE, MSR_IP);
+
+	/* make sure bit 0 (reset) is a 0 */
+	outb(inb(0x92) & ~1L, 0x92);
+	/* signal a reset to system control port A - soft reset */
+	outb(inb(0x92) | 1, 0x92);
+
+	while (1) ;
+	/*
+	 * Not reached
+	 */
+}
+
+static void pplus_power_off(void)
+{
+	pplus_halt();
+}
+
+static unsigned int pplus_irq_canonicalize(u_int irq)
+{
+	if (irq == 2)
+		return 9;
+	else
+		return irq;
+}
+
+static void __init pplus_init_IRQ(void)
+{
+	int i;
+
+	if (ppc_md.progress)
+		ppc_md.progress("init_irq: enter", 0);
+
+	OpenPIC_InitSenses = pplus_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof(pplus_openpic_initsenses);
+
+	if (OpenPIC_Addr != NULL) {
+
+		openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000);
+		openpic_init(NUM_8259_INTERRUPTS);
+		openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+					i8259_irq);
+		ppc_md.get_irq = openpic_get_irq;
+	}
+
+	for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+		irq_desc[i].handler = &i8259_pic;
+
+	i8259_init(0);
+
+	if (ppc_md.progress)
+		ppc_md.progress("init_irq: exit", 0);
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+static int pplus_ide_default_irq(unsigned long base)
+{
+	switch (base) {
+	case 0x1f0:
+		return 14;
+	case 0x170:
+		return 15;
+	default:
+		return 0;
+	}
+}
+
+static unsigned long pplus_ide_default_io_base(int index)
+{
+	switch (index) {
+	case 0:
+		return 0x1f0;
+	case 1:
+		return 0x170;
+	default:
+		return 0;
+	}
+}
+
+static void __init
+pplus_ide_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
+			  unsigned long ctrl_port, int *irq)
+{
+	unsigned long reg = data_port;
+	int i;
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+
+	if (ctrl_port)
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	else
+		hw->io_ports[IDE_CONTROL_OFFSET] =
+		    hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+
+	if (irq != NULL)
+		*irq = pplus_ide_default_irq(data_port);
+}
+#endif
+
+#ifdef CONFIG_SMP
+/* PowerPlus (MTX) support */
+static int __init smp_pplus_probe(void)
+{
+	extern int mot_multi;
+
+	if (mot_multi) {
+		openpic_request_IPIs();
+		smp_hw_index[1] = 1;
+		return 2;
+	}
+
+	return 1;
+}
+
+static void __init smp_pplus_kick_cpu(int nr)
+{
+	*(unsigned long *)KERNELBASE = nr;
+	asm volatile ("dcbf 0,%0"::"r" (KERNELBASE):"memory");
+	printk(KERN_INFO "CPU1 reset, waiting\n");
+}
+
+static void __init smp_pplus_setup_cpu(int cpu_nr)
+{
+	if (OpenPIC_Addr)
+		do_openpic_setup_cpu();
+}
+
+static struct smp_ops_t pplus_smp_ops = {
+	smp_openpic_message_pass,
+	smp_pplus_probe,
+	smp_pplus_kick_cpu,
+	smp_pplus_setup_cpu,
+	.give_timebase = smp_generic_give_timebase,
+	.take_timebase = smp_generic_take_timebase,
+};
+#endif				/* CONFIG_SMP */
+
+#ifdef DUMP_DBATS
+static void print_dbat(int idx, u32 bat)
+{
+
+	char str[64];
+
+	sprintf(str, "DBAT%c%c = 0x%08x\n",
+		(char)((idx - DBAT0U) / 2) + '0', (idx & 1) ? 'L' : 'U', bat);
+	ppc_md.progress(str, 0);
+}
+
+#define DUMP_DBAT(x) \
+	do { \
+	u32 __temp = mfspr(x);\
+	print_dbat(x, __temp); \
+	} while (0)
+
+static void dump_dbats(void)
+{
+	if (ppc_md.progress) {
+		DUMP_DBAT(DBAT0U);
+		DUMP_DBAT(DBAT0L);
+		DUMP_DBAT(DBAT1U);
+		DUMP_DBAT(DBAT1L);
+		DUMP_DBAT(DBAT2U);
+		DUMP_DBAT(DBAT2L);
+		DUMP_DBAT(DBAT3U);
+		DUMP_DBAT(DBAT3L);
+	}
+}
+#endif
+
+static unsigned long __init pplus_find_end_of_memory(void)
+{
+	unsigned long total;
+
+	if (ppc_md.progress)
+		ppc_md.progress("pplus_find_end_of_memory", 0);
+
+#ifdef DUMP_DBATS
+	dump_dbats();
+#endif
+
+	total = hawk_get_mem_size(PPLUS_HAWK_SMC_BASE);
+	return (total);
+}
+
+static void __init pplus_map_io(void)
+{
+	io_block_mapping(PPLUS_ISA_IO_BASE, PPLUS_ISA_IO_BASE, 0x10000000,
+			 _PAGE_IO);
+	io_block_mapping(0xfef80000, 0xfef80000, 0x00080000, _PAGE_IO);
+}
+
+static void __init pplus_init2(void)
+{
+#ifdef CONFIG_NVRAM
+	request_region(PREP_NVRAM_AS0, 0x8, "nvram");
+#endif
+	request_region(0x20, 0x20, "pic1");
+	request_region(0xa0, 0x20, "pic2");
+	request_region(0x00, 0x20, "dma1");
+	request_region(0x40, 0x20, "timer");
+	request_region(0x80, 0x10, "dma page reg");
+	request_region(0xc0, 0x20, "dma2");
+}
+
+/*
+ * Set BAT 2 to access 0x8000000 so progress messages will work and set BAT 3
+ * to 0xf0000000 to access Falcon/Raven or Hawk registers
+ */
+static __inline__ void pplus_set_bat(void)
+{
+	/* wait for all outstanding memory accesses to complete */
+	mb();
+
+	/* setup DBATs */
+	mtspr(SPRN_DBAT2U, 0x80001ffe);
+	mtspr(SPRN_DBAT2L, 0x8000002a);
+	mtspr(SPRN_DBAT3U, 0xf0001ffe);
+	mtspr(SPRN_DBAT3L, 0xf000002a);
+
+	/* wait for updates */
+	mb();
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	/* Map in board regs, etc. */
+	pplus_set_bat();
+
+	isa_io_base = PREP_ISA_IO_BASE;
+	isa_mem_base = PREP_ISA_MEM_BASE;
+	pci_dram_offset = PREP_PCI_DRAM_OFFSET;
+	ISA_DMA_THRESHOLD = 0x00ffffff;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+
+	ppc_md.setup_arch = pplus_setup_arch;
+	ppc_md.show_cpuinfo = pplus_show_cpuinfo;
+	ppc_md.irq_canonicalize = pplus_irq_canonicalize;
+	ppc_md.init_IRQ = pplus_init_IRQ;
+	/* this gets changed later on if we have an OpenPIC -- Cort */
+	ppc_md.get_irq = i8259_irq;
+	ppc_md.init = pplus_init2;
+
+	ppc_md.restart = pplus_restart;
+	ppc_md.power_off = pplus_power_off;
+	ppc_md.halt = pplus_halt;
+
+	TODC_INIT(TODC_TYPE_MK48T59, PREP_NVRAM_AS0, PREP_NVRAM_AS1,
+		  PREP_NVRAM_DATA, 8);
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.calibrate_decr = todc_calibrate_decr;
+	ppc_md.nvram_read_val = todc_m48txx_read_val;
+	ppc_md.nvram_write_val = todc_m48txx_write_val;
+
+	ppc_md.find_end_of_memory = pplus_find_end_of_memory;
+	ppc_md.setup_io_mappings = pplus_map_io;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+	ppc_ide_md.default_irq = pplus_ide_default_irq;
+	ppc_ide_md.default_io_base = pplus_ide_default_io_base;
+	ppc_ide_md.ide_init_hwif = pplus_ide_init_hwif_ports;
+#endif
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = gen550_progress;
+#endif				/* CONFIG_SERIAL_TEXT_DEBUG */
+#ifdef CONFIG_KGDB
+	ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
+#ifdef CONFIG_SMP
+	ppc_md.smp_ops = &pplus_smp_ops;
+#endif				/* CONFIG_SMP */
+}
diff --git a/arch/ppc/platforms/pplus.h b/arch/ppc/platforms/pplus.h
new file mode 100644
index 0000000..90f0cb2
--- /dev/null
+++ b/arch/ppc/platforms/pplus.h
@@ -0,0 +1,67 @@
+/*
+ * arch/ppc/platforms/pplus.h
+ *
+ * Definitions for Motorola MCG Falcon/Raven & HAWK North Bridge & Memory ctlr.
+ *
+ * Author: Mark A. Greerinclude/asm-ppc/hawk.h
+ *         mgreer@mvista.com
+ *
+ * Modified by Randy Vinson (rvinson@mvista.com)
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifndef __PPC_PPLUS_H
+#define __PPC_PPLUS_H
+
+#include <asm/io.h>
+
+/*
+ * Due to limiations imposed by legacy hardware (primaryily IDE controllers),
+ * the PPLUS boards operate using a PReP address map.
+ *
+ * From Processor (physical) -> PCI:
+ *   PCI Mem Space: 0xc0000000 - 0xfe000000 -> 0x00000000 - 0x3e000000 (768 MB)
+ *   PCI I/O Space: 0x80000000 - 0x90000000 -> 0x00000000 - 0x10000000 (256 MB)
+ *	Note: Must skip 0xfe000000-0xfe400000 for CONFIG_HIGHMEM/PKMAP area
+ *
+ * From PCI -> Processor (physical):
+ *   System Memory: 0x80000000 -> 0x00000000
+ */
+
+#define PPLUS_ISA_MEM_BASE		PREP_ISA_MEM_BASE
+#define PPLUS_ISA_IO_BASE		PREP_ISA_IO_BASE
+
+/* PCI Memory space mapping info */
+#define PPLUS_PCI_MEM_SIZE		0x30000000U
+#define PPLUS_PROC_PCI_MEM_START	PPLUS_ISA_MEM_BASE
+#define PPLUS_PROC_PCI_MEM_END		(PPLUS_PROC_PCI_MEM_START +	\
+					 PPLUS_PCI_MEM_SIZE - 1)
+#define PPLUS_PCI_MEM_START		0x00000000U
+#define PPLUS_PCI_MEM_END		(PPLUS_PCI_MEM_START +	\
+					 PPLUS_PCI_MEM_SIZE - 1)
+
+/* PCI I/O space mapping info */
+#define PPLUS_PCI_IO_SIZE		0x10000000U
+#define PPLUS_PROC_PCI_IO_START		PPLUS_ISA_IO_BASE
+#define PPLUS_PROC_PCI_IO_END		(PPLUS_PROC_PCI_IO_START +	\
+					 PPLUS_PCI_IO_SIZE - 1)
+#define PPLUS_PCI_IO_START		0x00000000U
+#define PPLUS_PCI_IO_END		(PPLUS_PCI_IO_START + 	\
+					 PPLUS_PCI_IO_SIZE - 1)
+/* System memory mapping info */
+#define PPLUS_PCI_DRAM_OFFSET		PREP_PCI_DRAM_OFFSET
+#define PPLUS_PCI_PHY_MEM_OFFSET	(PPLUS_ISA_MEM_BASE-PPLUS_PCI_MEM_START)
+
+/* Define base addresses for important sets of registers */
+#define PPLUS_HAWK_SMC_BASE		0xfef80000U
+#define PPLUS_HAWK_PPC_REG_BASE		0xfeff0000U
+#define PPLUS_SYS_CONFIG_REG		0xfef80400U
+#define PPLUS_L2_CONTROL_REG		0x8000081cU
+
+#define PPLUS_VGA_MEM_BASE		0xf0000000U
+
+#endif	/* __PPC_PPLUS_H */
diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c
new file mode 100644
index 0000000..6a1475c
--- /dev/null
+++ b/arch/ppc/platforms/pq2ads.c
@@ -0,0 +1,26 @@
+/*
+ * arch/ppc/platforms/pq2ads.c
+ *
+ * PQ2ADS platform support
+ *
+ * Author: Kumar Gala <kumar.gala@freescale.com>
+ * Derived from: est8260_setup.c by Allen Curtis
+ *
+ * Copyright 2004 Freescale Semiconductor, 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/init.h>
+
+#include <asm/mpc8260.h>
+
+void __init
+m82xx_board_setup(void)
+{
+	/* Enable the 2nd UART port */
+	*(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_RS232_EN2;
+}
diff --git a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h
new file mode 100644
index 0000000..cf5e5dd
--- /dev/null
+++ b/arch/ppc/platforms/pq2ads.h
@@ -0,0 +1,96 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Motorola MPC8260ADS/MPC8266ADS-PCI boards.
+ * Copied from the RPX-Classic and SBS8260 stuff.
+ *
+ * Copyright (c) 2001 Dan Malek (dan@mvista.com)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_ADS8260_DEFS
+#define __MACH_ADS8260_DEFS
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+/* Memory map is configured by the PROM startup.
+ * We just map a few things we need.  The CSR is actually 4 byte-wide
+ * registers that can be accessed as 8-, 16-, or 32-bit values.
+ */
+#define CPM_MAP_ADDR		((uint)0xf0000000)
+#define BCSR_ADDR		((uint)0xf4500000)
+#define BCSR_SIZE		((uint)(32 * 1024))
+
+#define BOOTROM_RESTART_ADDR	((uint)0xff000104)
+
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"Motorola"
+#define CPUINFO_MACHINE		"PQ2 ADS PowerPC"
+
+/* The ADS8260 has 16, 32-bit wide control/status registers, accessed
+ * only on word boundaries.
+ * Not all are used (yet), or are interesting to us (yet).
+ */
+
+/* Things of interest in the CSR.
+*/
+#define BCSR0_LED0		((uint)0x02000000)	/* 0 == on */
+#define BCSR0_LED1		((uint)0x01000000)	/* 0 == on */
+#define BCSR1_FETHIEN		((uint)0x08000000)	/* 0 == enable */
+#define BCSR1_FETH_RST		((uint)0x04000000)	/* 0 == reset */
+#define BCSR1_RS232_EN1		((uint)0x02000000)	/* 0 == enable */
+#define BCSR1_RS232_EN2		((uint)0x01000000)	/* 0 == enable */
+#define BCSR3_FETHIEN2		((uint)0x10000000)	/* 0 == enable */
+#define BCSR3_FETH2_RST 	((uint)0x80000000)	/* 0 == reset */
+
+#define PHY_INTERRUPT	SIU_INT_IRQ7
+
+#ifdef CONFIG_PCI
+/* PCI interrupt controller */
+#define PCI_INT_STAT_REG	0xF8200000
+#define PCI_INT_MASK_REG	0xF8200004
+#define PIRQA			(NR_SIU_INTS + 0)
+#define PIRQB			(NR_SIU_INTS + 1)
+#define PIRQC			(NR_SIU_INTS + 2)
+#define PIRQD			(NR_SIU_INTS + 3)
+
+/*
+ * PCI memory map definitions for MPC8266ADS-PCI.
+ *
+ * processor view
+ *	local address		PCI address		target
+ *	0x80000000-0x9FFFFFFF	0x80000000-0x9FFFFFFF	PCI mem with prefetch
+ *	0xA0000000-0xBFFFFFFF	0xA0000000-0xBFFFFFFF	PCI mem w/o prefetch
+ *	0xF4000000-0xF7FFFFFF	0x00000000-0x03FFFFFF	PCI IO
+ *
+ * PCI master view
+ *	local address		PCI address		target
+ *	0x00000000-0x1FFFFFFF	0x00000000-0x1FFFFFFF	MPC8266 local memory
+ */
+
+/* window for a PCI master to access MPC8266 memory */
+#define PCI_SLV_MEM_LOCAL	0x00000000	/* Local base */
+#define PCI_SLV_MEM_BUS		0x00000000	/* PCI base */
+
+/* window for the processor to access PCI memory with prefetching */
+#define PCI_MSTR_MEM_LOCAL	0x80000000	/* Local base */
+#define PCI_MSTR_MEM_BUS	0x80000000	/* PCI base   */
+#define PCI_MSTR_MEM_SIZE	0x20000000	/* 512MB */
+
+/* window for the processor to access PCI memory without prefetching */
+#define PCI_MSTR_MEMIO_LOCAL	0xA0000000	/* Local base */
+#define PCI_MSTR_MEMIO_BUS	0xA0000000	/* PCI base   */
+#define PCI_MSTR_MEMIO_SIZE	0x20000000	/* 512MB */
+
+/* window for the processor to access PCI I/O */
+#define PCI_MSTR_IO_LOCAL	0xF4000000	/* Local base */
+#define PCI_MSTR_IO_BUS         0x00000000	/* PCI base   */
+#define PCI_MSTR_IO_SIZE        0x04000000	/* 64MB */
+
+#define _IO_BASE		PCI_MSTR_IO_LOCAL
+#define _ISA_MEM_BASE		PCI_MSTR_MEMIO_LOCAL
+#define PCI_DRAM_OFFSET		PCI_SLV_MEM_BUS
+#endif /* CONFIG_PCI */
+
+#endif /* __MACH_ADS8260_DEFS */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/prep_pci.c b/arch/ppc/platforms/prep_pci.c
new file mode 100644
index 0000000..8cd80eb
--- /dev/null
+++ b/arch/ppc/platforms/prep_pci.c
@@ -0,0 +1,1336 @@
+/*
+ * PReP pci functions.
+ * Originally by Gary Thomas
+ * rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
+ *
+ * The motherboard routes/maps will disappear shortly. -- Cort
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/sections.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/ptrace.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/residual.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/open_pic.h>
+
+extern void (*setup_ibm_pci)(char *irq_lo, char *irq_hi);
+
+/* Which PCI interrupt line does a given device [slot] use? */
+/* Note: This really should be two dimensional based in slot/pin used */
+static unsigned char *Motherboard_map;
+unsigned char *Motherboard_map_name;
+
+/* How is the 82378 PIRQ mapping setup? */
+static unsigned char *Motherboard_routes;
+
+static void (*Motherboard_non0)(struct pci_dev *);
+
+static void Powerplus_Map_Non0(struct pci_dev *);
+
+/* Used for Motorola to store system config register */
+static unsigned long	*ProcInfo;
+
+/* Tables for known hardware */
+
+/* Motorola PowerStackII - Utah */
+static char Utah_pci_IRQ_map[23] __prepdata =
+{
+        0,   /* Slot 0  - unused */
+        0,   /* Slot 1  - unused */
+        5,   /* Slot 2  - SCSI - NCR825A  */
+        0,   /* Slot 3  - unused */
+        3,   /* Slot 4  - Ethernet - DEC2114x */
+        0,   /* Slot 5  - unused */
+        2,   /* Slot 6  - PCI Card slot #1 */
+        3,   /* Slot 7  - PCI Card slot #2 */
+        5,   /* Slot 8  - PCI Card slot #3 */
+        5,   /* Slot 9  - PCI Bridge */
+             /* added here in case we ever support PCI bridges */
+             /* Secondary PCI bus cards are at slot-9,6 & slot-9,7 */
+        0,   /* Slot 10 - unused */
+        0,   /* Slot 11 - unused */
+        5,   /* Slot 12 - SCSI - NCR825A */
+        0,   /* Slot 13 - unused */
+        3,   /* Slot 14 - enet */
+        0,   /* Slot 15 - unused */
+        2,   /* Slot 16 - unused */
+        3,   /* Slot 17 - unused */
+        5,   /* Slot 18 - unused */
+        0,   /* Slot 19 - unused */
+        0,   /* Slot 20 - unused */
+        0,   /* Slot 21 - unused */
+        0,   /* Slot 22 - unused */
+};
+
+static char Utah_pci_IRQ_routes[] __prepdata =
+{
+        0,   /* Line 0 - Unused */
+        9,   /* Line 1 */
+	10,  /* Line 2 */
+        11,  /* Line 3 */
+        14,  /* Line 4 */
+        15,  /* Line 5 */
+};
+
+/* Motorola PowerStackII - Omaha */
+/* no integrated SCSI or ethernet */
+static char Omaha_pci_IRQ_map[23] __prepdata =
+{
+        0,   /* Slot 0  - unused */
+        0,   /* Slot 1  - unused */
+        3,   /* Slot 2  - Winbond EIDE */
+        0,   /* Slot 3  - unused */
+        0,   /* Slot 4  - unused */
+        0,   /* Slot 5  - unused */
+        1,   /* Slot 6  - PCI slot 1 */
+        2,   /* Slot 7  - PCI slot 2  */
+        3,   /* Slot 8  - PCI slot 3 */
+        4,   /* Slot 9  - PCI slot 4 */ /* needs indirect access */
+        0,   /* Slot 10 - unused */
+        0,   /* Slot 11 - unused */
+        0,   /* Slot 12 - unused */
+        0,   /* Slot 13 - unused */
+        0,   /* Slot 14 - unused */
+        0,   /* Slot 15 - unused */
+        1,   /* Slot 16  - PCI slot 1 */
+        2,   /* Slot 17  - PCI slot 2  */
+        3,   /* Slot 18  - PCI slot 3 */
+        4,   /* Slot 19  - PCI slot 4 */ /* needs indirect access */
+        0,
+        0,
+        0,
+};
+
+static char Omaha_pci_IRQ_routes[] __prepdata =
+{
+        0,   /* Line 0 - Unused */
+        9,   /* Line 1 */
+        11,  /* Line 2 */
+        14,  /* Line 3 */
+        15   /* Line 4 */
+};
+
+/* Motorola PowerStack */
+static char Blackhawk_pci_IRQ_map[19] __prepdata =
+{
+  	0,	/* Slot 0  - unused */
+  	0,	/* Slot 1  - unused */
+  	0,	/* Slot 2  - unused */
+  	0,	/* Slot 3  - unused */
+  	0,	/* Slot 4  - unused */
+  	0,	/* Slot 5  - unused */
+  	0,	/* Slot 6  - unused */
+  	0,	/* Slot 7  - unused */
+  	0,	/* Slot 8  - unused */
+  	0,	/* Slot 9  - unused */
+  	0,	/* Slot 10 - unused */
+  	0,	/* Slot 11 - unused */
+  	3,	/* Slot 12 - SCSI */
+  	0,	/* Slot 13 - unused */
+  	1,	/* Slot 14 - Ethernet */
+  	0,	/* Slot 15 - unused */
+ 	1,	/* Slot P7 */
+ 	2,	/* Slot P6 */
+ 	3,	/* Slot P5 */
+};
+
+static char Blackhawk_pci_IRQ_routes[] __prepdata =
+{
+   	0,	/* Line 0 - Unused */
+   	9,	/* Line 1 */
+   	11,	/* Line 2 */
+   	15,	/* Line 3 */
+   	15	/* Line 4 */
+};
+
+/* Motorola Mesquite */
+static char Mesquite_pci_IRQ_map[23] __prepdata =
+{
+	0,	/* Slot 0  - unused */
+	0,	/* Slot 1  - unused */
+	0,	/* Slot 2  - unused */
+	0,	/* Slot 3  - unused */
+	0,	/* Slot 4  - unused */
+	0,	/* Slot 5  - unused */
+	0,	/* Slot 6  - unused */
+	0,	/* Slot 7  - unused */
+	0,	/* Slot 8  - unused */
+	0,	/* Slot 9  - unused */
+	0,	/* Slot 10 - unused */
+	0,	/* Slot 11 - unused */
+	0,	/* Slot 12 - unused */
+	0,	/* Slot 13 - unused */
+	2,	/* Slot 14 - Ethernet */
+	0,	/* Slot 15 - unused */
+	3,	/* Slot 16 - PMC */
+	0,	/* Slot 17 - unused */
+	0,	/* Slot 18 - unused */
+	0,	/* Slot 19 - unused */
+	0,	/* Slot 20 - unused */
+	0,	/* Slot 21 - unused */
+	0,	/* Slot 22 - unused */
+};
+
+/* Motorola Sitka */
+static char Sitka_pci_IRQ_map[21] __prepdata =
+{
+	0,      /* Slot 0  - unused */
+	0,      /* Slot 1  - unused */
+	0,      /* Slot 2  - unused */
+	0,      /* Slot 3  - unused */
+	0,      /* Slot 4  - unused */
+	0,      /* Slot 5  - unused */
+	0,      /* Slot 6  - unused */
+	0,      /* Slot 7  - unused */
+	0,      /* Slot 8  - unused */
+	0,      /* Slot 9  - unused */
+	0,      /* Slot 10 - unused */
+	0,      /* Slot 11 - unused */
+	0,      /* Slot 12 - unused */
+	0,      /* Slot 13 - unused */
+	2,      /* Slot 14 - Ethernet */
+	0,      /* Slot 15 - unused */
+	9,      /* Slot 16 - PMC 1  */
+	12,     /* Slot 17 - PMC 2  */
+	0,      /* Slot 18 - unused */
+	0,      /* Slot 19 - unused */
+	4,      /* Slot 20 - NT P2P bridge */
+};
+
+/* Motorola MTX */
+static char MTX_pci_IRQ_map[23] __prepdata =
+{
+	0,	/* Slot 0  - unused */
+	0,	/* Slot 1  - unused */
+	0,	/* Slot 2  - unused */
+	0,	/* Slot 3  - unused */
+	0,	/* Slot 4  - unused */
+	0,	/* Slot 5  - unused */
+	0,	/* Slot 6  - unused */
+	0,	/* Slot 7  - unused */
+	0,	/* Slot 8  - unused */
+	0,	/* Slot 9  - unused */
+	0,	/* Slot 10 - unused */
+	0,	/* Slot 11 - unused */
+	3,	/* Slot 12 - SCSI */
+	0,	/* Slot 13 - unused */
+	2,	/* Slot 14 - Ethernet */
+	0,	/* Slot 15 - unused */
+	9,      /* Slot 16 - PCI/PMC slot 1 */
+	10,     /* Slot 17 - PCI/PMC slot 2 */
+	11,     /* Slot 18 - PCI slot 3 */
+	0,	/* Slot 19 - unused */
+	0,	/* Slot 20 - unused */
+	0,	/* Slot 21 - unused */
+	0,	/* Slot 22 - unused */
+};
+
+/* Motorola MTX Plus */
+/* Secondary bus interrupt routing is not supported yet */
+static char MTXplus_pci_IRQ_map[23] __prepdata =
+{
+        0,      /* Slot 0  - unused */
+        0,      /* Slot 1  - unused */
+        0,      /* Slot 2  - unused */
+        0,      /* Slot 3  - unused */
+        0,      /* Slot 4  - unused */
+        0,      /* Slot 5  - unused */
+        0,      /* Slot 6  - unused */
+        0,      /* Slot 7  - unused */
+        0,      /* Slot 8  - unused */
+        0,      /* Slot 9  - unused */
+        0,      /* Slot 10 - unused */
+        0,      /* Slot 11 - unused */
+        3,      /* Slot 12 - SCSI */
+        0,      /* Slot 13 - unused */
+        2,      /* Slot 14 - Ethernet 1 */
+        0,      /* Slot 15 - unused */
+        9,      /* Slot 16 - PCI slot 1P */
+        10,     /* Slot 17 - PCI slot 2P */
+        11,     /* Slot 18 - PCI slot 3P */
+        10,     /* Slot 19 - Ethernet 2 */
+        0,      /* Slot 20 - P2P Bridge */
+        0,      /* Slot 21 - unused */
+        0,      /* Slot 22 - unused */
+};
+
+static char Raven_pci_IRQ_routes[] __prepdata =
+{
+   	0,	/* This is a dummy structure */
+};
+
+/* Motorola MVME16xx */
+static char Genesis_pci_IRQ_map[16] __prepdata =
+{
+  	0,	/* Slot 0  - unused */
+  	0,	/* Slot 1  - unused */
+  	0,	/* Slot 2  - unused */
+  	0,	/* Slot 3  - unused */
+  	0,	/* Slot 4  - unused */
+  	0,	/* Slot 5  - unused */
+  	0,	/* Slot 6  - unused */
+  	0,	/* Slot 7  - unused */
+  	0,	/* Slot 8  - unused */
+  	0,	/* Slot 9  - unused */
+  	0,	/* Slot 10 - unused */
+  	0,	/* Slot 11 - unused */
+  	3,	/* Slot 12 - SCSI */
+  	0,	/* Slot 13 - unused */
+  	1,	/* Slot 14 - Ethernet */
+  	0,	/* Slot 15 - unused */
+};
+
+static char Genesis_pci_IRQ_routes[] __prepdata =
+{
+   	0,	/* Line 0 - Unused */
+   	10,	/* Line 1 */
+   	11,	/* Line 2 */
+   	14,	/* Line 3 */
+   	15	/* Line 4 */
+};
+
+static char Genesis2_pci_IRQ_map[23] __prepdata =
+{
+	0,	/* Slot 0  - unused */
+	0,	/* Slot 1  - unused */
+	0,	/* Slot 2  - unused */
+	0,	/* Slot 3  - unused */
+	0,	/* Slot 4  - unused */
+	0,	/* Slot 5  - unused */
+	0,	/* Slot 6  - unused */
+	0,	/* Slot 7  - unused */
+	0,	/* Slot 8  - unused */
+	0,	/* Slot 9  - unused */
+	0,	/* Slot 10 - unused */
+	0,	/* Slot 11 - IDE */
+	3,	/* Slot 12 - SCSI */
+	5,	/* Slot 13 - Universe PCI - VME Bridge */
+	2,	/* Slot 14 - Ethernet */
+	0,	/* Slot 15 - unused */
+	9,	/* Slot 16 - PMC 1 */
+	12,	/* Slot 17 - pci */
+	11,	/* Slot 18 - pci */
+	10,	/* Slot 19 - pci */
+	0,	/* Slot 20 - pci */
+	0,	/* Slot 21 - unused */
+	0,	/* Slot 22 - unused */
+};
+
+/* Motorola Series-E */
+static char Comet_pci_IRQ_map[23] __prepdata =
+{
+  	0,	/* Slot 0  - unused */
+  	0,	/* Slot 1  - unused */
+  	0,	/* Slot 2  - unused */
+  	0,	/* Slot 3  - unused */
+  	0,	/* Slot 4  - unused */
+  	0,	/* Slot 5  - unused */
+  	0,	/* Slot 6  - unused */
+  	0,	/* Slot 7  - unused */
+  	0,	/* Slot 8  - unused */
+  	0,	/* Slot 9  - unused */
+  	0,	/* Slot 10 - unused */
+  	0,	/* Slot 11 - unused */
+  	3,	/* Slot 12 - SCSI */
+  	0,	/* Slot 13 - unused */
+  	1,	/* Slot 14 - Ethernet */
+  	0,	/* Slot 15 - unused */
+	1,	/* Slot 16 - PCI slot 1 */
+	2,	/* Slot 17 - PCI slot 2 */
+	3,	/* Slot 18 - PCI slot 3 */
+	4,	/* Slot 19 - PCI bridge */
+	0,
+	0,
+	0,
+};
+
+static char Comet_pci_IRQ_routes[] __prepdata =
+{
+   	0,	/* Line 0 - Unused */
+   	10,	/* Line 1 */
+   	11,	/* Line 2 */
+   	14,	/* Line 3 */
+   	15	/* Line 4 */
+};
+
+/* Motorola Series-EX */
+static char Comet2_pci_IRQ_map[23] __prepdata =
+{
+	0,	/* Slot 0  - unused */
+	0,	/* Slot 1  - unused */
+	3,	/* Slot 2  - SCSI - NCR825A */
+	0,	/* Slot 3  - unused */
+	1,	/* Slot 4  - Ethernet - DEC2104X */
+	0,	/* Slot 5  - unused */
+	1,	/* Slot 6  - PCI slot 1 */
+	2,	/* Slot 7  - PCI slot 2 */
+	3,	/* Slot 8  - PCI slot 3 */
+	4,	/* Slot 9  - PCI bridge  */
+	0,	/* Slot 10 - unused */
+	0,	/* Slot 11 - unused */
+	3,	/* Slot 12 - SCSI - NCR825A */
+	0,	/* Slot 13 - unused */
+	1,	/* Slot 14 - Ethernet - DEC2104X */
+	0,	/* Slot 15 - unused */
+	1,	/* Slot 16 - PCI slot 1 */
+	2,	/* Slot 17 - PCI slot 2 */
+	3,	/* Slot 18 - PCI slot 3 */
+	4,	/* Slot 19 - PCI bridge */
+	0,
+	0,
+	0,
+};
+
+static char Comet2_pci_IRQ_routes[] __prepdata =
+{
+	0,	/* Line 0 - Unused */
+	10,	/* Line 1 */
+	11,	/* Line 2 */
+	14,	/* Line 3 */
+	15,	/* Line 4 */
+};
+
+/*
+ * ibm 830 (and 850?).
+ * This is actually based on the Carolina motherboard
+ * -- Cort
+ */
+static char ibm8xx_pci_IRQ_map[23] __prepdata = {
+        0, /* Slot 0  - unused */
+        0, /* Slot 1  - unused */
+        0, /* Slot 2  - unused */
+        0, /* Slot 3  - unused */
+        0, /* Slot 4  - unused */
+        0, /* Slot 5  - unused */
+        0, /* Slot 6  - unused */
+        0, /* Slot 7  - unused */
+        0, /* Slot 8  - unused */
+        0, /* Slot 9  - unused */
+        0, /* Slot 10 - unused */
+        0, /* Slot 11 - FireCoral */
+        4, /* Slot 12 - Ethernet  PCIINTD# */
+        2, /* Slot 13 - PCI Slot #2 */
+        2, /* Slot 14 - S3 Video PCIINTD# */
+        0, /* Slot 15 - onboard SCSI (INDI) [1] */
+        3, /* Slot 16 - NCR58C810 RS6000 Only PCIINTC# */
+        0, /* Slot 17 - unused */
+        2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */
+        0, /* Slot 19 - unused */
+        0, /* Slot 20 - unused */
+        0, /* Slot 21 - unused */
+        2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
+};
+
+static char ibm8xx_pci_IRQ_routes[] __prepdata = {
+        0,      /* Line 0 - unused */
+        15,     /* Line 1 */
+        15,     /* Line 2 */
+        15,     /* Line 3 */
+        15,     /* Line 4 */
+};
+
+/*
+ * a 6015 ibm board
+ * -- Cort
+ */
+static char ibm6015_pci_IRQ_map[23] __prepdata = {
+        0, /* Slot 0  - unused */
+        0, /* Slot 1  - unused */
+        0, /* Slot 2  - unused */
+        0, /* Slot 3  - unused */
+        0, /* Slot 4  - unused */
+        0, /* Slot 5  - unused */
+        0, /* Slot 6  - unused */
+        0, /* Slot 7  - unused */
+        0, /* Slot 8  - unused */
+        0, /* Slot 9  - unused */
+        0, /* Slot 10 - unused */
+        0, /* Slot 11 -  */
+        1, /* Slot 12 - SCSI */
+        2, /* Slot 13 -  */
+        2, /* Slot 14 -  */
+        1, /* Slot 15 -  */
+        1, /* Slot 16 -  */
+        0, /* Slot 17 -  */
+        2, /* Slot 18 -  */
+        0, /* Slot 19 -  */
+        0, /* Slot 20 -  */
+        0, /* Slot 21 -  */
+        2, /* Slot 22 -  */
+};
+
+static char ibm6015_pci_IRQ_routes[] __prepdata = {
+        0,      /* Line 0 - unused */
+        13,     /* Line 1 */
+        15,     /* Line 2 */
+        15,     /* Line 3 */
+        15,     /* Line 4 */
+};
+
+
+/* IBM Nobis and Thinkpad 850 */
+static char Nobis_pci_IRQ_map[23] __prepdata ={
+        0, /* Slot 0  - unused */
+        0, /* Slot 1  - unused */
+        0, /* Slot 2  - unused */
+        0, /* Slot 3  - unused */
+        0, /* Slot 4  - unused */
+        0, /* Slot 5  - unused */
+        0, /* Slot 6  - unused */
+        0, /* Slot 7  - unused */
+        0, /* Slot 8  - unused */
+        0, /* Slot 9  - unused */
+        0, /* Slot 10 - unused */
+        0, /* Slot 11 - unused */
+        3, /* Slot 12 - SCSI */
+        0, /* Slot 13 - unused */
+        0, /* Slot 14 - unused */
+        0, /* Slot 15 - unused */
+};
+
+static char Nobis_pci_IRQ_routes[] __prepdata = {
+        0, /* Line 0 - Unused */
+        13, /* Line 1 */
+        13, /* Line 2 */
+        13, /* Line 3 */
+        13      /* Line 4 */
+};
+
+/*
+ * IBM RS/6000 43p/140  -- paulus
+ * XXX we should get all this from the residual data
+ */
+static char ibm43p_pci_IRQ_map[23] __prepdata = {
+        0, /* Slot 0  - unused */
+        0, /* Slot 1  - unused */
+        0, /* Slot 2  - unused */
+        0, /* Slot 3  - unused */
+        0, /* Slot 4  - unused */
+        0, /* Slot 5  - unused */
+        0, /* Slot 6  - unused */
+        0, /* Slot 7  - unused */
+        0, /* Slot 8  - unused */
+        0, /* Slot 9  - unused */
+        0, /* Slot 10 - unused */
+        0, /* Slot 11 - FireCoral ISA bridge */
+        6, /* Slot 12 - Ethernet  */
+        0, /* Slot 13 - openpic */
+        0, /* Slot 14 - unused */
+        0, /* Slot 15 - unused */
+        7, /* Slot 16 - NCR58C825a onboard scsi */
+        0, /* Slot 17 - unused */
+        2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */
+        0, /* Slot 19 - unused */
+        0, /* Slot 20 - unused */
+        0, /* Slot 21 - unused */
+        1, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
+};
+
+static char ibm43p_pci_IRQ_routes[] __prepdata = {
+        0,      /* Line 0 - unused */
+        15,     /* Line 1 */
+        15,     /* Line 2 */
+        15,     /* Line 3 */
+        15,     /* Line 4 */
+};
+
+/* Motorola PowerPlus architecture PCI IRQ tables */
+/* Interrupt line values for INTA-D on primary/secondary MPIC inputs */
+
+struct powerplus_irq_list
+{
+	unsigned char primary[4];       /* INT A-D */
+	unsigned char secondary[4];     /* INT A-D */
+};
+
+/*
+ * For standard PowerPlus boards, bus 0 PCI INTs A-D are routed to
+ * OpenPIC inputs 9-12.  PCI INTs A-D from the on board P2P bridge
+ * are routed to OpenPIC inputs 5-8.  These values are offset by
+ * 16 in the table to reflect the Linux kernel interrupt value.
+ */
+struct powerplus_irq_list Powerplus_pci_IRQ_list __prepdata =
+{
+	{25, 26, 27, 28},
+	{21, 22, 23, 24}
+};
+
+/*
+ * For the MCP750 (system slot board), cPCI INTs A-D are routed to
+ * OpenPIC inputs 8-11 and the PMC INTs A-D are routed to OpenPIC
+ * input 3.  On a hot swap MCP750, the companion card PCI INTs A-D
+ * are routed to OpenPIC inputs 12-15. These values are offset by
+ * 16 in the table to reflect the Linux kernel interrupt value.
+ */
+struct powerplus_irq_list Mesquite_pci_IRQ_list __prepdata =
+{
+	{24, 25, 26, 27},
+	{28, 29, 30, 31}
+};
+
+/*
+ * This table represents the standard PCI swizzle defined in the
+ * PCI bus specification.
+ */
+static unsigned char prep_pci_intpins[4][4] __prepdata =
+{
+	{ 1, 2, 3, 4},  /* Buses 0, 4, 8, ... */
+	{ 2, 3, 4, 1},  /* Buses 1, 5, 9, ... */
+	{ 3, 4, 1, 2},  /* Buses 2, 6, 10 ... */
+	{ 4, 1, 2, 3},  /* Buses 3, 7, 11 ... */
+};
+
+/* We have to turn on LEVEL mode for changed IRQ's */
+/* All PCI IRQ's need to be level mode, so this should be something
+ * other than hard-coded as well... IRQ's are individually mappable
+ * to either edge or level.
+ */
+
+/*
+ * 8259 edge/level control definitions
+ */
+#define ISA8259_M_ELCR 0x4d0
+#define ISA8259_S_ELCR 0x4d1
+
+#define ELCRS_INT15_LVL         0x80
+#define ELCRS_INT14_LVL         0x40
+#define ELCRS_INT12_LVL         0x10
+#define ELCRS_INT11_LVL         0x08
+#define ELCRS_INT10_LVL         0x04
+#define ELCRS_INT9_LVL          0x02
+#define ELCRS_INT8_LVL          0x01
+#define ELCRM_INT7_LVL          0x80
+#define ELCRM_INT5_LVL          0x20
+
+#if 0
+/*
+ * PCI config space access.
+ */
+#define CFGADDR(dev)	((1<<(dev>>3)) | ((dev&7)<<8))
+#define DEVNO(dev)	(dev>>3)
+
+#define MIN_DEVNR	11
+#define MAX_DEVNR	22
+
+static int __prep
+prep_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		 int len, u32 *val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	volatile void __iomem *cfg_data;
+
+	if (bus->number != 0 || DEVNO(devfn) < MIN_DEVNR
+	    || DEVNO(devfn) > MAX_DEVNR)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	cfg_data = hose->cfg_data + CFGADDR(devfn) + offset;
+	switch (len) {
+	case 1:
+		*val = in_8(cfg_data);
+		break;
+	case 2:
+		*val = in_le16(cfg_data);
+		break;
+	default:
+		*val = in_le32(cfg_data);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int __prep
+prep_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		  int len, u32 val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	volatile void __iomem *cfg_data;
+
+	if (bus->number != 0 || DEVNO(devfn) < MIN_DEVNR
+	    || DEVNO(devfn) > MAX_DEVNR)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	cfg_data = hose->cfg_data + CFGADDR(devfn) + offset;
+	switch (len) {
+	case 1:
+		out_8(cfg_data, val);
+		break;
+	case 2:
+		out_le16(cfg_data, val);
+		break;
+	default:
+		out_le32(cfg_data, val);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops prep_pci_ops =
+{
+	prep_read_config,
+	prep_write_config
+};
+#endif
+
+#define MOTOROLA_CPUTYPE_REG	0x800
+#define MOTOROLA_BASETYPE_REG	0x803
+#define MPIC_RAVEN_ID		0x48010000
+#define	MPIC_HAWK_ID		0x48030000
+#define	MOT_PROC2_BIT		0x800
+
+static u_char prep_openpic_initsenses[] __initdata = {
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* MVME2600_INT_SIO */
+    (IRQ_SENSE_EDGE  | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_FALCN_ECC_ERR */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_ETHERNET */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_SCSI */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_GRAPHICS */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME0 */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME1 */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME2 */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME3 */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTA */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTB */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTC */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTD */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_LM_SIG0 */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_LM_SIG1 */
+};
+
+#define MOT_RAVEN_PRESENT	0x1
+#define MOT_HAWK_PRESENT	0x2
+
+int mot_entry = -1;
+int prep_keybd_present = 1;
+int MotMPIC;
+int mot_multi;
+
+int __init
+raven_init(void)
+{
+	unsigned int	devid;
+	unsigned int	pci_membase;
+	unsigned char	base_mod;
+
+	/* Check to see if the Raven chip exists. */
+	if ( _prep_type != _PREP_Motorola) {
+		OpenPIC_Addr = NULL;
+		return 0;
+	}
+
+	/* Check to see if this board is a type that might have a Raven. */
+	if ((inb(MOTOROLA_CPUTYPE_REG) & 0xF0) != 0xE0) {
+		OpenPIC_Addr = NULL;
+		return 0;
+	}
+
+	/* Check the first PCI device to see if it is a Raven. */
+	early_read_config_dword(NULL, 0, 0, PCI_VENDOR_ID, &devid);
+
+	switch (devid & 0xffff0000) {
+	case MPIC_RAVEN_ID:
+		MotMPIC = MOT_RAVEN_PRESENT;
+		break;
+	case MPIC_HAWK_ID:
+		MotMPIC = MOT_HAWK_PRESENT;
+		break;
+	default:
+		OpenPIC_Addr = NULL;
+		return 0;
+	}
+
+
+	/* Read the memory base register. */
+	early_read_config_dword(NULL, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
+
+	if (pci_membase == 0) {
+		OpenPIC_Addr = NULL;
+		return 0;
+	}
+
+	/* Map the Raven MPIC registers to virtual memory. */
+	OpenPIC_Addr = ioremap(pci_membase+0xC0000000, 0x22000);
+
+	OpenPIC_InitSenses = prep_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses);
+
+	ppc_md.get_irq = openpic_get_irq;
+
+	/* If raven is present on Motorola store the system config register
+	 * for later use.
+	 */
+	ProcInfo = (unsigned long *)ioremap(0xfef80400, 4);
+
+	/* Indicate to system if this is a multiprocessor board */
+	if (!(*ProcInfo & MOT_PROC2_BIT)) {
+		mot_multi = 1;
+	}
+
+	/* This is a hack.  If this is a 2300 or 2400 mot board then there is
+	 * no keyboard controller and we have to indicate that.
+	 */
+	base_mod = inb(MOTOROLA_BASETYPE_REG);
+	if ((MotMPIC == MOT_HAWK_PRESENT) || (base_mod == 0xF9) ||
+	    (base_mod == 0xFA) || (base_mod == 0xE1))
+		prep_keybd_present = 0;
+
+	return 1;
+}
+
+struct mot_info {
+	int		cpu_type;	/* 0x100 mask assumes for Raven and Hawk boards that the level/edge are set */
+					/* 0x200 if this board has a Hawk chip. */
+	int		base_type;
+	int		max_cpu;	/* ored with 0x80 if this board should be checked for multi CPU */
+	const char	*name;
+	unsigned char	*map;
+	unsigned char	*routes;
+	void            (*map_non0_bus)(struct pci_dev *);      /* For boards with more than bus 0 devices. */
+	struct powerplus_irq_list *pci_irq_list; /* List of PCI MPIC inputs */
+	unsigned char   secondary_bridge_devfn; /* devfn of secondary bus transparent bridge */
+} mot_info[] __prepdata = {
+	{0x300, 0x00, 0x00, "MVME 2400",			Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x010, 0x00, 0x00, "Genesis",				Genesis_pci_IRQ_map,	Genesis_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+	{0x020, 0x00, 0x00, "Powerstack (Series E)",		Comet_pci_IRQ_map,	Comet_pci_IRQ_routes, NULL, NULL, 0x00},
+	{0x040, 0x00, 0x00, "Blackhawk (Powerstack)",		Blackhawk_pci_IRQ_map,	Blackhawk_pci_IRQ_routes, NULL, NULL, 0x00},
+	{0x050, 0x00, 0x00, "Omaha (PowerStack II Pro3000)",	Omaha_pci_IRQ_map,	Omaha_pci_IRQ_routes, NULL, NULL, 0x00},
+	{0x060, 0x00, 0x00, "Utah (Powerstack II Pro4000)",	Utah_pci_IRQ_map,	Utah_pci_IRQ_routes, NULL, NULL, 0x00},
+	{0x0A0, 0x00, 0x00, "Powerstack (Series EX)",		Comet2_pci_IRQ_map,	Comet2_pci_IRQ_routes, NULL, NULL, 0x00},
+	{0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)",		Mesquite_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Mesquite_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)",		Sitka_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC",	Mesquite_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Mesquite_pci_IRQ_list, 0xC0},
+	{0x1E0, 0xF6, 0x80, "MTX Plus",				MTXplus_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xA0},
+	{0x1E0, 0xF6, 0x81, "Dual MTX Plus",			MTXplus_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xA0},
+	{0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port",		MTX_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+	{0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port",	MTX_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+	{0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port",		MTX_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+	{0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port",	MTX_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+	{0x1E0, 0xF9, 0x00, "MVME 2300",			Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xFA, 0x00, "MVME 2300SC/2600",			Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761",	Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+	{0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xFF, 0x00, "MVME 1600-001 or 1600-011",	Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x000, 0x00, 0x00, "",					NULL,			NULL, NULL, NULL, 0x00}
+};
+
+void __init
+ibm_prep_init(void)
+{
+	if (have_residual_data) {
+		u32 addr, real_addr, len, offset;
+		PPC_DEVICE *mpic;
+		PnP_TAG_PACKET *pkt;
+
+		/* Use the PReP residual data to determine if an OpenPIC is
+		 * present.  If so, get the large vendor packet which will
+		 * tell us the base address and length in memory.
+		 * If we are successful, ioremap the memory area and set
+		 * OpenPIC_Addr (this indicates that the OpenPIC was found).
+		 */
+		mpic = residual_find_device(-1, NULL, SystemPeripheral,
+				    ProgrammableInterruptController, MPIC, 0);
+		if (!mpic)
+			return;
+
+		pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+				mpic->AllocatedOffset, 9, 0);
+
+		if (!pkt)
+			return;
+
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+	 	if (p.PPCData[1] == 32) {
+			switch (p.PPCData[0]) {
+				case 1:  offset = PREP_ISA_IO_BASE;  break;
+				case 2:  offset = PREP_ISA_MEM_BASE; break;
+				default: return; /* Not I/O or memory?? */
+			}
+		}
+		else
+			return; /* Not a 32-bit address */
+
+		real_addr = ld_le32((unsigned int *) (p.PPCData + 4));
+		if (real_addr == 0xffffffff)
+			return;
+
+		/* Adjust address to be as seen by CPU */
+		addr = real_addr + offset;
+
+		len = ld_le32((unsigned int *) (p.PPCData + 12));
+		if (!len)
+			return;
+#undef p
+		OpenPIC_Addr = ioremap(addr, len);
+		ppc_md.get_irq = openpic_get_irq;
+
+		OpenPIC_InitSenses = prep_openpic_initsenses;
+		OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses);
+
+		printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x "
+		       "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr);
+	}
+}
+
+static void __init
+ibm43p_pci_map_non0(struct pci_dev *dev)
+{
+	unsigned char intpin;
+	static unsigned char bridge_intrs[4] = { 3, 4, 5, 8 };
+
+	if (dev == NULL)
+		return;
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &intpin);
+	if (intpin < 1 || intpin > 4)
+		return;
+	intpin = (PCI_SLOT(dev->devfn) + intpin - 1) & 3;
+	dev->irq = openpic_to_irq(bridge_intrs[intpin]);
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+}
+
+void __init
+prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+	if (have_residual_data) {
+		Motherboard_map_name = res->VitalProductData.PrintableModel;
+		Motherboard_map = NULL;
+		Motherboard_routes = NULL;
+		residual_irq_mask(irq_edge_mask_lo, irq_edge_mask_hi);
+	}
+}
+
+void __init
+prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+	Motherboard_map_name = "IBM 6015/7020 (Sandalfoot/Sandalbow)";
+	Motherboard_map = ibm6015_pci_IRQ_map;
+	Motherboard_routes = ibm6015_pci_IRQ_routes;
+	*irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
+	*irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
+}
+
+void __init
+prep_thinkpad_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+	Motherboard_map_name = "IBM Thinkpad 850/860";
+	Motherboard_map = Nobis_pci_IRQ_map;
+	Motherboard_routes = Nobis_pci_IRQ_routes;
+	*irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
+	*irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
+}
+
+void __init
+prep_carolina_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+	Motherboard_map_name = "IBM 7248, PowerSeries 830/850 (Carolina)";
+	Motherboard_map = ibm8xx_pci_IRQ_map;
+	Motherboard_routes = ibm8xx_pci_IRQ_routes;
+	*irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
+	*irq_edge_mask_hi = 0xA4; /* irq's 10, 13, 15 level-triggered */
+}
+
+void __init
+prep_tiger1_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+	Motherboard_map_name = "IBM 43P-140 (Tiger1)";
+	Motherboard_map = ibm43p_pci_IRQ_map;
+	Motherboard_routes = ibm43p_pci_IRQ_routes;
+	Motherboard_non0 = ibm43p_pci_map_non0;
+	*irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
+	*irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
+}
+
+void __init
+prep_route_pci_interrupts(void)
+{
+	unsigned char *ibc_pirq = (unsigned char *)0x80800860;
+	unsigned char *ibc_pcicon = (unsigned char *)0x80800840;
+	int i;
+
+	if ( _prep_type == _PREP_Motorola)
+	{
+		unsigned short irq_mode;
+		unsigned char  cpu_type;
+		unsigned char  base_mod;
+		int	       entry;
+
+		cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0;
+		base_mod = inb(MOTOROLA_BASETYPE_REG);
+
+		for (entry = 0; mot_info[entry].cpu_type != 0; entry++) {
+			if (mot_info[entry].cpu_type & 0x200) {		 	/* Check for Hawk chip */
+				if (!(MotMPIC & MOT_HAWK_PRESENT))
+					continue;
+			} else {						/* Check non hawk boards */
+				if ((mot_info[entry].cpu_type & 0xff) != cpu_type)
+					continue;
+
+				if (mot_info[entry].base_type == 0) {
+					mot_entry = entry;
+					break;
+				}
+
+				if (mot_info[entry].base_type != base_mod)
+					continue;
+			}
+
+			if (!(mot_info[entry].max_cpu & 0x80)) {
+				mot_entry = entry;
+				break;
+			}
+
+			/* processor 1 not present and max processor zero indicated */
+			if ((*ProcInfo & MOT_PROC2_BIT) && !(mot_info[entry].max_cpu & 0x7f)) {
+				mot_entry = entry;
+				break;
+			}
+
+			/* processor 1 present and max processor zero indicated */
+			if (!(*ProcInfo & MOT_PROC2_BIT) && (mot_info[entry].max_cpu & 0x7f)) {
+				mot_entry = entry;
+				break;
+			}
+		}
+
+		if (mot_entry == -1) 	/* No particular cpu type found - assume Blackhawk */
+			mot_entry = 3;
+
+		Motherboard_map_name = (unsigned char *)mot_info[mot_entry].name;
+		Motherboard_map = mot_info[mot_entry].map;
+		Motherboard_routes = mot_info[mot_entry].routes;
+		Motherboard_non0 = mot_info[mot_entry].map_non0_bus;
+
+		if (!(mot_info[entry].cpu_type & 0x100)) {
+			/* AJF adjust level/edge control according to routes */
+			irq_mode = 0;
+			for (i = 1;  i <= 4;  i++)
+				irq_mode |= ( 1 << Motherboard_routes[i] );
+			outb( irq_mode & 0xff, 0x4d0 );
+			outb( (irq_mode >> 8) & 0xff, 0x4d1 );
+		}
+	} else if ( _prep_type == _PREP_IBM ) {
+		unsigned char irq_edge_mask_lo, irq_edge_mask_hi;
+		unsigned short irq_edge_mask;
+		int i;
+
+		setup_ibm_pci(&irq_edge_mask_lo, &irq_edge_mask_hi);
+
+		outb(inb(0x04d0)|irq_edge_mask_lo, 0x4d0); /* primary 8259 */
+		outb(inb(0x04d1)|irq_edge_mask_hi, 0x4d1); /* cascaded 8259 */
+
+		irq_edge_mask = (irq_edge_mask_hi << 8) | irq_edge_mask_lo;
+		for (i = 0; i < 16; ++i, irq_edge_mask >>= 1)
+			if (irq_edge_mask & 1)
+				irq_desc[i].status |= IRQ_LEVEL;
+	} else {
+		printk("No known machine pci routing!\n");
+		return;
+	}
+
+	/* Set up mapping from slots */
+	if (Motherboard_routes) {
+		for (i = 1;  i <= 4;  i++)
+			ibc_pirq[i-1] = Motherboard_routes[i];
+
+		/* Enable PCI interrupts */
+		*ibc_pcicon |= 0x20;
+	}
+}
+
+void __init
+prep_pib_init(void)
+{
+	unsigned char   reg;
+	unsigned short  short_reg;
+
+	struct pci_dev *dev = NULL;
+
+	if (( _prep_type == _PREP_Motorola) && (OpenPIC_Addr)) {
+		/*
+		 * Perform specific configuration for the Via Tech or
+		 * or Winbond PCI-ISA-Bridge part.
+		 */
+		if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+					PCI_DEVICE_ID_VIA_82C586_1, dev))) {
+			/*
+			 * PPCBUG does not set the enable bits
+			 * for the IDE device. Force them on here.
+			 */
+			pci_read_config_byte(dev, 0x40, &reg);
+
+			reg |= 0x03; /* IDE: Chip Enable Bits */
+			pci_write_config_byte(dev, 0x40, reg);
+		}
+		if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+						PCI_DEVICE_ID_VIA_82C586_2,
+						dev)) && (dev->devfn = 0x5a)) {
+			/* Force correct USB interrupt */
+			dev->irq = 11;
+			pci_write_config_byte(dev,
+					PCI_INTERRUPT_LINE,
+					dev->irq);
+		}
+		if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+					PCI_DEVICE_ID_WINBOND_83C553, dev))) {
+			 /* Clear PCI Interrupt Routing Control Register. */
+			short_reg = 0x0000;
+			pci_write_config_word(dev, 0x44, short_reg);
+			if (OpenPIC_Addr){
+				/* Route IDE interrupts to IRQ 14 */
+				reg = 0xEE;
+				pci_write_config_byte(dev, 0x43, reg);
+			}
+		}
+		pci_dev_put(dev);
+	}
+
+	if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+				   PCI_DEVICE_ID_WINBOND_82C105, dev))){
+		if (OpenPIC_Addr){
+			/*
+			 * Disable LEGIRQ mode so PCI INTS are routed
+			 * directly to the 8259 and enable both channels
+			 */
+			pci_write_config_dword(dev, 0x40, 0x10ff0033);
+
+			/* Force correct IDE interrupt */
+			dev->irq = 14;
+			pci_write_config_byte(dev,
+					PCI_INTERRUPT_LINE,
+					dev->irq);
+		} else {
+			/* Enable LEGIRQ for PCI INT -> 8259 IRQ routing */
+			pci_write_config_dword(dev, 0x40, 0x10ff08a1);
+		}
+	}
+	pci_dev_put(dev);
+}
+
+static void __init
+Powerplus_Map_Non0(struct pci_dev *dev)
+{
+	struct pci_bus  *pbus;          /* Parent bus structure pointer */
+	struct pci_dev  *tdev = dev;    /* Temporary device structure */
+	unsigned int    devnum;         /* Accumulated device number */
+	unsigned char   intline;        /* Linux interrupt value */
+	unsigned char   intpin;         /* PCI interrupt pin */
+
+	/* Check for valid PCI dev pointer */
+	if (dev == NULL) return;
+
+	/* Initialize bridge IDSEL variable */
+	devnum = PCI_SLOT(tdev->devfn);
+
+	/* Read the interrupt pin of the device and adjust for indexing */
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &intpin);
+
+	/* If device doesn't request an interrupt, return */
+	if ( (intpin < 1) || (intpin > 4) )
+		return;
+
+	intpin--;
+
+	/*
+	 * Walk up to bus 0, adjusting the interrupt pin for the standard
+	 * PCI bus swizzle.
+	 */
+	do {
+		intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1;
+		pbus = tdev->bus;        /* up one level */
+		tdev = pbus->self;
+		devnum = PCI_SLOT(tdev->devfn);
+	} while(tdev->bus->number);
+
+	/* Use the primary interrupt inputs by default */
+	intline = mot_info[mot_entry].pci_irq_list->primary[intpin];
+
+	/*
+	 * If the board has secondary interrupt inputs, walk the bus and
+	 * note the devfn of the bridge from bus 0.  If it is the same as
+	 * the devfn of the bus bridge with secondary inputs, use those.
+	 * Otherwise, assume it's a PMC site and get the interrupt line
+	 * value from the interrupt routing table.
+	 */
+	if (mot_info[mot_entry].secondary_bridge_devfn) {
+		pbus = dev->bus;
+
+		while (pbus->primary != 0)
+			pbus = pbus->parent;
+
+		if ((pbus->self)->devfn != 0xA0) {
+			if ((pbus->self)->devfn == mot_info[mot_entry].secondary_bridge_devfn)
+				intline = mot_info[mot_entry].pci_irq_list->secondary[intpin];
+			else {
+				if ((char *)(mot_info[mot_entry].map) == (char *)Mesquite_pci_IRQ_map)
+					intline = mot_info[mot_entry].map[((pbus->self)->devfn)/8] + 16;
+				else {
+					int i;
+					for (i=0;i<3;i++)
+						intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1;
+					intline = mot_info[mot_entry].pci_irq_list->primary[intpin];
+				}
+			}
+		}
+	}
+
+	/* Write calculated interrupt value to header and device list */
+	dev->irq = intline;
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, (u8)dev->irq);
+}
+
+void __init
+prep_pcibios_fixup(void)
+{
+        struct pci_dev *dev = NULL;
+	int irq;
+	int have_openpic = (OpenPIC_Addr != NULL);
+
+	prep_route_pci_interrupts();
+
+	printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
+
+	/* Iterate through all the PCI devices, setting the IRQ */
+	for_each_pci_dev(dev) {
+		/*
+		 * If we have residual data, then this is easy: query the
+		 * residual data for the IRQ line allocated to the device.
+		 * This works the same whether we have an OpenPic or not.
+		 */
+		if (have_residual_data) {
+			irq = residual_pcidev_irq(dev);
+			dev->irq = have_openpic ? openpic_to_irq(irq) : irq;
+		}
+		/*
+		 * If we don't have residual data, then we need to use
+		 * tables to determine the IRQ.  The table organisation
+		 * is different depending on whether there is an OpenPIC
+		 * or not.  The tables are only used for bus 0, so check
+		 * this first.
+		 */
+		else if (dev->bus->number == 0) {
+			irq = Motherboard_map[PCI_SLOT(dev->devfn)];
+			dev->irq = have_openpic ? openpic_to_irq(irq)
+						: Motherboard_routes[irq];
+		}
+		/*
+		 * Finally, if we don't have residual data and the bus is
+		 * non-zero, use the callback (if provided)
+		 */
+		else {
+			if (Motherboard_non0 != NULL)
+				Motherboard_non0(dev);
+
+			continue;
+		}
+
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+	}
+
+	/* Setup the Winbond or Via PIB */
+	prep_pib_init();
+}
+
+static void __init
+prep_pcibios_after_init(void)
+{
+#if 0
+	struct pci_dev *dev;
+
+	/* If there is a WD 90C, reset the IO BAR to 0x0 (it started that
+	 * way, but the PCI layer relocated it because it thought 0x0 was
+	 * invalid for a BAR).
+	 * If you don't do this, the card's VGA base will be <IO BAR>+0xc0000
+	 * instead of 0xc0000. vgacon.c (for example) is completely unaware of
+	 * this little quirk.
+	 */
+	dev = pci_get_device(PCI_VENDOR_ID_WD, PCI_DEVICE_ID_WD_90C, NULL);
+	if (dev) {
+		dev->resource[1].end -= dev->resource[1].start;
+		dev->resource[1].start = 0;
+		/* tell the hardware */
+		pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0x0);
+		pci_dev_put(dev);
+	}
+#endif
+}
+
+static void __init
+prep_init_resource(struct resource *res, unsigned long start,
+		   unsigned long end, int flags)
+{
+	res->flags = flags;
+	res->start = start;
+	res->end = end;
+	res->name = "PCI host bridge";
+	res->parent = NULL;
+	res->sibling = NULL;
+	res->child = NULL;
+}
+
+void __init
+prep_find_bridges(void)
+{
+	struct pci_controller* hose;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+	hose->pci_mem_offset = PREP_ISA_MEM_BASE;
+	hose->io_base_phys = PREP_ISA_IO_BASE;
+	hose->io_base_virt = ioremap(PREP_ISA_IO_BASE, 0x800000);
+	prep_init_resource(&hose->io_resource, 0, 0x007fffff, IORESOURCE_IO);
+	prep_init_resource(&hose->mem_resources[0], 0xc0000000, 0xfeffffff,
+			   IORESOURCE_MEM);
+	setup_indirect_pci(hose, PREP_ISA_IO_BASE + 0xcf8,
+			   PREP_ISA_IO_BASE + 0xcfc);
+
+	printk("PReP architecture\n");
+
+	if (have_residual_data) {
+		PPC_DEVICE *hostbridge;
+
+		hostbridge = residual_find_device(PROCESSORDEVICE, NULL,
+			BridgeController, PCIBridge, -1, 0);
+		if (hostbridge &&
+			((hostbridge->DeviceId.Interface == PCIBridgeIndirect) ||
+			 (hostbridge->DeviceId.Interface == PCIBridgeRS6K))) {
+			PnP_TAG_PACKET * pkt;
+			pkt = PnP_find_large_vendor_packet(
+				res->DevicePnPHeap+hostbridge->AllocatedOffset,
+				3, 0);
+			if(pkt) {
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+				setup_indirect_pci(hose,
+					ld_le32((unsigned *) (p.PPCData)),
+					ld_le32((unsigned *) (p.PPCData+8)));
+#undef p
+			} else
+				setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc);
+		}
+	}
+
+	ppc_md.pcibios_fixup = prep_pcibios_fixup;
+	ppc_md.pcibios_after_init = prep_pcibios_after_init;
+}
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
new file mode 100644
index 0000000..bc926be
--- /dev/null
+++ b/arch/ppc/platforms/prep_setup.c
@@ -0,0 +1,1181 @@
+/*
+ *  arch/ppc/platforms/setup.c
+ *
+ *  Copyright (C) 1995  Linus Torvalds
+ *  Adapted from 'alpha' version by Gary Thomas
+ *  Modified by Cort Dougan (cort@cs.nmt.edu)
+ *
+ * Support for PReP (Motorola MTX/MVME)
+ * by Troy Benjegerdes (hozer@drgw.net)
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/initrd.h>
+#include <linux/ioport.h>
+#include <linux/console.h>
+#include <linux/timex.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/sections.h>
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <asm/residual.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/cache.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/mc146818rtc.h>
+#include <asm/mk48t59.h>
+#include <asm/prep_nvram.h>
+#include <asm/raven.h>
+#include <asm/vga.h>
+#include <asm/time.h>
+#include <asm/mpc10x.h>
+#include <asm/i8259.h>
+#include <asm/open_pic.h>
+#include <asm/pci-bridge.h>
+#include <asm/todc.h>
+
+TODC_ALLOC();
+
+unsigned char ucSystemType;
+unsigned char ucBoardRev;
+unsigned char ucBoardRevMaj, ucBoardRevMin;
+
+extern unsigned char prep_nvram_read_val(int addr);
+extern void prep_nvram_write_val(int addr,
+				 unsigned char val);
+extern unsigned char rs_nvram_read_val(int addr);
+extern void rs_nvram_write_val(int addr,
+				 unsigned char val);
+extern void ibm_prep_init(void);
+
+extern void prep_find_bridges(void);
+
+int _prep_type;
+
+extern void prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
+extern void prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
+extern void prep_thinkpad_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
+extern void prep_carolina_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
+extern void prep_tiger1_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
+
+
+#define cached_21	(((char *)(ppc_cached_irq_mask))[3])
+#define cached_A1	(((char *)(ppc_cached_irq_mask))[2])
+
+/* for the mac fs */
+dev_t boot_dev;
+
+#ifdef CONFIG_SOUND_CS4232
+long ppc_cs4232_dma, ppc_cs4232_dma2;
+#endif
+
+extern PTE *Hash, *Hash_end;
+extern unsigned long Hash_size, Hash_mask;
+extern int probingmem;
+extern unsigned long loops_per_jiffy;
+
+#ifdef CONFIG_SOUND_CS4232
+EXPORT_SYMBOL(ppc_cs4232_dma);
+EXPORT_SYMBOL(ppc_cs4232_dma2);
+#endif
+
+/* useful ISA ports */
+#define PREP_SYSCTL	0x81c
+/* present in the IBM reference design; possibly identical in Mot boxes: */
+#define PREP_IBM_SIMM_ID	0x803	/* SIMM size: 32 or 8 MiB */
+#define PREP_IBM_SIMM_PRESENCE	0x804
+#define PREP_IBM_EQUIPMENT	0x80c
+#define PREP_IBM_L2INFO	0x80d
+#define PREP_IBM_PM1	0x82a	/* power management register 1 */
+#define PREP_IBM_PLANAR	0x852	/* planar ID - identifies the motherboard */
+#define PREP_IBM_DISP	0x8c0	/* 4-digit LED display */
+
+/* Equipment Present Register masks: */
+#define PREP_IBM_EQUIPMENT_RESERVED	0x80
+#define PREP_IBM_EQUIPMENT_SCSIFUSE	0x40
+#define PREP_IBM_EQUIPMENT_L2_COPYBACK	0x08
+#define PREP_IBM_EQUIPMENT_L2_256	0x04
+#define PREP_IBM_EQUIPMENT_CPU	0x02
+#define PREP_IBM_EQUIPMENT_L2	0x01
+
+/* planar ID values: */
+/* Sandalfoot/Sandalbow (6015/7020) */
+#define PREP_IBM_SANDALFOOT	0xfc
+/* Woodfield, Thinkpad 850/860 (6042/7249) */
+#define PREP_IBM_THINKPAD	0xff /* planar ID unimplemented */
+/* PowerSeries 830/850 (6050/6070) */
+#define PREP_IBM_CAROLINA_IDE_0	0xf0
+#define PREP_IBM_CAROLINA_IDE_1	0xf1
+#define PREP_IBM_CAROLINA_IDE_2	0xf2
+#define PREP_IBM_CAROLINA_IDE_3	0xf3
+/* 7248-43P */
+#define PREP_IBM_CAROLINA_SCSI_0	0xf4
+#define PREP_IBM_CAROLINA_SCSI_1	0xf5
+#define PREP_IBM_CAROLINA_SCSI_2	0xf6
+#define PREP_IBM_CAROLINA_SCSI_3	0xf7 /* missing from Carolina Tech Spec */
+/* Tiger1 (7043-140) */
+#define PREP_IBM_TIGER1_133		0xd1
+#define PREP_IBM_TIGER1_166		0xd2
+#define PREP_IBM_TIGER1_180		0xd3
+#define PREP_IBM_TIGER1_xxx		0xd4 /* unknown, but probably exists */
+#define PREP_IBM_TIGER1_333		0xd5 /* missing from Tiger Tech Spec */
+
+/* setup_ibm_pci:
+ * 	set Motherboard_map_name, Motherboard_map, Motherboard_routes.
+ * 	return 8259 edge/level masks.
+ */
+void (*setup_ibm_pci)(char *irq_lo, char *irq_hi);
+
+extern char *Motherboard_map_name; /* for use in *_cpuinfo */
+
+/*
+ * As found in the PReP reference implementation.
+ * Used by Thinkpad, Sandalfoot (6015/7020), and all Motorola PReP.
+ */
+static void __init
+prep_gen_enable_l2(void)
+{
+	outb(inb(PREP_SYSCTL) | 0x3, PREP_SYSCTL);
+}
+
+/* Used by Carolina and Tiger1 */
+static void __init
+prep_carolina_enable_l2(void)
+{
+	outb(inb(PREP_SYSCTL) | 0xc0, PREP_SYSCTL);
+}
+
+/* cpuinfo code common to all IBM PReP */
+static void __prep
+prep_ibm_cpuinfo(struct seq_file *m)
+{
+	unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
+
+	seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name);
+
+	seq_printf(m, "upgrade cpu\t: ");
+	if (equip_reg & PREP_IBM_EQUIPMENT_CPU) {
+		seq_printf(m, "not ");
+	}
+	seq_printf(m, "present\n");
+
+	/* print info about the SCSI fuse */
+	seq_printf(m, "scsi fuse\t: ");
+	if (equip_reg & PREP_IBM_EQUIPMENT_SCSIFUSE)
+		seq_printf(m, "ok");
+	else
+		seq_printf(m, "bad");
+	seq_printf(m, "\n");
+
+	/* print info about SIMMs */
+	if (have_residual_data) {
+		int i;
+		seq_printf(m, "simms\t\t: ");
+		for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {
+			if (res->Memories[i].SIMMSize != 0)
+				seq_printf(m, "%d:%ldMiB ", i,
+					(res->Memories[i].SIMMSize > 1024) ?
+					res->Memories[i].SIMMSize>>20 :
+					res->Memories[i].SIMMSize);
+		}
+		seq_printf(m, "\n");
+	}
+}
+
+static int __prep
+prep_gen_cpuinfo(struct seq_file *m)
+{
+	prep_ibm_cpuinfo(m);
+	return 0;
+}
+
+static int __prep
+prep_sandalfoot_cpuinfo(struct seq_file *m)
+{
+	unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
+
+	prep_ibm_cpuinfo(m);
+
+	/* report amount and type of L2 cache present */
+	seq_printf(m, "L2 cache\t: ");
+	if (equip_reg & PREP_IBM_EQUIPMENT_L2) {
+		seq_printf(m, "not present");
+	} else {
+		if (equip_reg & PREP_IBM_EQUIPMENT_L2_256)
+			seq_printf(m, "256KiB");
+		else
+			seq_printf(m, "unknown size");
+
+		if (equip_reg & PREP_IBM_EQUIPMENT_L2_COPYBACK)
+			seq_printf(m, ", copy-back");
+		else
+			seq_printf(m, ", write-through");
+	}
+	seq_printf(m, "\n");
+
+	return 0;
+}
+
+static int __prep
+prep_thinkpad_cpuinfo(struct seq_file *m)
+{
+	unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
+	char *cpubus_speed, *pci_speed;
+
+	prep_ibm_cpuinfo(m);
+
+	/* report amount and type of L2 cache present */
+	seq_printf(m, "l2 cache\t: ");
+	if ((equip_reg & 0x1) == 0) {
+		switch ((equip_reg & 0xc) >> 2) {
+			case 0x0:
+				seq_printf(m, "128KiB look-aside 2-way write-through\n");
+				break;
+			case 0x1:
+				seq_printf(m, "512KiB look-aside direct-mapped write-back\n");
+				break;
+			case 0x2:
+				seq_printf(m, "256KiB look-aside 2-way write-through\n");
+				break;
+			case 0x3:
+				seq_printf(m, "256KiB look-aside direct-mapped write-back\n");
+				break;
+		}
+	} else {
+		seq_printf(m, "not present\n");
+	}
+
+	/* report bus speeds because we can */
+	if ((equip_reg & 0x80) == 0) {
+		switch ((equip_reg & 0x30) >> 4) {
+			case 0x1:
+				cpubus_speed = "50";
+				pci_speed = "25";
+				break;
+			case 0x3:
+				cpubus_speed = "66";
+				pci_speed = "33";
+				break;
+			default:
+				cpubus_speed = "unknown";
+				pci_speed = "unknown";
+				break;
+		}
+	} else {
+		switch ((equip_reg & 0x30) >> 4) {
+			case 0x1:
+				cpubus_speed = "25";
+				pci_speed = "25";
+				break;
+			case 0x2:
+				cpubus_speed = "60";
+				pci_speed = "30";
+				break;
+			case 0x3:
+				cpubus_speed = "33";
+				pci_speed = "33";
+				break;
+			default:
+				cpubus_speed = "unknown";
+				pci_speed = "unknown";
+				break;
+		}
+	}
+	seq_printf(m, "60x bus\t\t: %sMHz\n", cpubus_speed);
+	seq_printf(m, "pci bus\t\t: %sMHz\n", pci_speed);
+
+	return 0;
+}
+
+static int __prep
+prep_carolina_cpuinfo(struct seq_file *m)
+{
+	unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
+
+	prep_ibm_cpuinfo(m);
+
+	/* report amount and type of L2 cache present */
+	seq_printf(m, "l2 cache\t: ");
+	if ((equip_reg & 0x1) == 0) {
+		unsigned int l2_reg = inb(PREP_IBM_L2INFO);
+
+		/* L2 size */
+		if ((l2_reg & 0x60) == 0)
+			seq_printf(m, "256KiB");
+		else if ((l2_reg & 0x60) == 0x20)
+			seq_printf(m, "512KiB");
+		else
+			seq_printf(m, "unknown size");
+
+		/* L2 type */
+		if ((l2_reg & 0x3) == 0)
+			seq_printf(m, ", async");
+		else if ((l2_reg & 0x3) == 1)
+			seq_printf(m, ", sync");
+		else
+			seq_printf(m, ", unknown type");
+
+		seq_printf(m, "\n");
+	} else {
+		seq_printf(m, "not present\n");
+	}
+
+	return 0;
+}
+
+static int __prep
+prep_tiger1_cpuinfo(struct seq_file *m)
+{
+	unsigned int l2_reg = inb(PREP_IBM_L2INFO);
+
+	prep_ibm_cpuinfo(m);
+
+	/* report amount and type of L2 cache present */
+	seq_printf(m, "l2 cache\t: ");
+	if ((l2_reg & 0xf) == 0xf) {
+		seq_printf(m, "not present\n");
+	} else {
+		if (l2_reg & 0x8)
+			seq_printf(m, "async, ");
+		else
+			seq_printf(m, "sync burst, ");
+	
+		if (l2_reg & 0x4)
+			seq_printf(m, "parity, ");
+		else
+			seq_printf(m, "no parity, ");
+	
+		switch (l2_reg & 0x3) {
+			case 0x0:
+				seq_printf(m, "256KiB\n");
+				break;
+			case 0x1:
+				seq_printf(m, "512KiB\n");
+				break;
+			case 0x2:
+				seq_printf(m, "1MiB\n");
+				break;
+			default:
+				seq_printf(m, "unknown size\n");
+				break;
+		}
+	}
+
+	return 0;
+}
+
+
+/* Used by all Motorola PReP */
+static int __prep
+prep_mot_cpuinfo(struct seq_file *m)
+{
+	unsigned int cachew = *((unsigned char *)CACHECRBA);
+
+	seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name);
+
+	/* report amount and type of L2 cache present */
+	seq_printf(m, "l2 cache\t: ");
+	switch (cachew & L2CACHE_MASK) {
+		case L2CACHE_512KB:
+			seq_printf(m, "512KiB");
+			break;
+		case L2CACHE_256KB:
+			seq_printf(m, "256KiB");
+			break;
+		case L2CACHE_1MB:
+			seq_printf(m, "1MiB");
+			break;
+		case L2CACHE_NONE:
+			seq_printf(m, "none\n");
+			goto no_l2;
+			break;
+		default:
+			seq_printf(m, "%x\n", cachew);
+	}
+
+	seq_printf(m, ", parity %s",
+			(cachew & L2CACHE_PARITY)? "enabled" : "disabled");
+
+	seq_printf(m, " SRAM:");
+
+	switch ( ((cachew & 0xf0) >> 4) & ~(0x3) ) {
+		case 1: seq_printf(m, "synchronous, parity, flow-through\n");
+				break;
+		case 2: seq_printf(m, "asynchronous, no parity\n");
+				break;
+		case 3: seq_printf(m, "asynchronous, parity\n");
+				break;
+		default:seq_printf(m, "synchronous, pipelined, no parity\n");
+				break;
+	}
+
+no_l2:
+	/* print info about SIMMs */
+	if (have_residual_data) {
+		int i;
+		seq_printf(m, "simms\t\t: ");
+		for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {
+			if (res->Memories[i].SIMMSize != 0)
+				seq_printf(m, "%d:%ldM ", i,
+					(res->Memories[i].SIMMSize > 1024) ?
+					res->Memories[i].SIMMSize>>20 :
+					res->Memories[i].SIMMSize);
+		}
+		seq_printf(m, "\n");
+	}
+
+	return 0;
+}
+
+static void __prep
+prep_restart(char *cmd)
+{
+#define PREP_SP92	0x92	/* Special Port 92 */
+	local_irq_disable(); /* no interrupts */
+
+	/* set exception prefix high - to the prom */
+	_nmask_and_or_msr(0, MSR_IP);
+
+	/* make sure bit 0 (reset) is a 0 */
+	outb( inb(PREP_SP92) & ~1L , PREP_SP92);
+	/* signal a reset to system control port A - soft reset */
+	outb( inb(PREP_SP92) | 1 , PREP_SP92);
+
+	while ( 1 ) ;
+	/* not reached */
+#undef PREP_SP92
+}
+
+static void __prep
+prep_halt(void)
+{
+	local_irq_disable(); /* no interrupts */
+
+	/* set exception prefix high - to the prom */
+	_nmask_and_or_msr(0, MSR_IP);
+
+	while ( 1 ) ;
+	/* not reached */
+}
+
+/* Carrera is the power manager in the Thinkpads. Unfortunately not much is
+ * known about it, so we can't power down.
+ */
+static void __prep
+prep_carrera_poweroff(void)
+{
+	prep_halt();
+}
+
+/*
+ * On most IBM PReP's, power management is handled by a Signetics 87c750
+ * behind the Utah component on the ISA bus. To access the 750 you must write
+ * a series of nibbles to port 0x82a (decoded by the Utah). This is described
+ * somewhat in the IBM Carolina Technical Specification.
+ * -Hollis
+ */
+static void __prep
+utah_sig87c750_setbit(unsigned int bytenum, unsigned int bitnum, int value)
+{
+	/*
+	 * byte1: 0 0 0 1 0  d  a5 a4
+	 * byte2: 0 0 0 1 a3 a2 a1 a0
+	 *
+	 * d = the bit's value, enabled or disabled
+	 * (a5 a4 a3) = the byte number, minus 20
+	 * (a2 a1 a0) = the bit number
+	 *
+	 * example: set the 5th bit of byte 21 (21.5)
+	 *     a5 a4 a3 = 001 (byte 1)
+	 *     a2 a1 a0 = 101 (bit 5)
+	 *
+	 *     byte1 = 0001 0100 (0x14)
+	 *     byte2 = 0001 1101 (0x1d)
+	 */
+	unsigned char byte1=0x10, byte2=0x10;
+
+	/* the 750's '20.0' is accessed as '0.0' through Utah (which adds 20) */
+	bytenum -= 20;
+
+	byte1 |= (!!value) << 2;		/* set d */
+	byte1 |= (bytenum >> 1) & 0x3;	/* set a5, a4 */
+
+	byte2 |= (bytenum & 0x1) << 3;	/* set a3 */
+	byte2 |= bitnum & 0x7;			/* set a2, a1, a0 */
+
+	outb(byte1, PREP_IBM_PM1);	/* first nibble */
+	mb();
+	udelay(100);				/* important: let controller recover */
+
+	outb(byte2, PREP_IBM_PM1);	/* second nibble */
+	mb();
+	udelay(100);				/* important: let controller recover */
+}
+
+static void __prep
+prep_sig750_poweroff(void)
+{
+	/* tweak the power manager found in most IBM PRePs (except Thinkpads) */
+
+	local_irq_disable();
+	/* set exception prefix high - to the prom */
+	_nmask_and_or_msr(0, MSR_IP);
+
+	utah_sig87c750_setbit(21, 5, 1); /* set bit 21.5, "PMEXEC_OFF" */
+
+	while (1) ;
+	/* not reached */
+}
+
+static int __prep
+prep_show_percpuinfo(struct seq_file *m, int i)
+{
+	/* PREP's without residual data will give incorrect values here */
+	seq_printf(m, "clock\t\t: ");
+	if (have_residual_data)
+		seq_printf(m, "%ldMHz\n",
+			   (res->VitalProductData.ProcessorHz > 1024) ?
+			   res->VitalProductData.ProcessorHz / 1000000 :
+			   res->VitalProductData.ProcessorHz);
+	else
+		seq_printf(m, "???\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_SOUND_CS4232
+static long __init masktoint(unsigned int i)
+{
+	int t = -1;
+	while (i >> ++t)
+		;
+	return (t-1);
+}
+
+/*
+ * ppc_cs4232_dma and ppc_cs4232_dma2 are used in include/asm/dma.h
+ * to distinguish sound dma-channels from others. This is because
+ * blocksize on 16 bit dma-channels 5,6,7 is 128k, but
+ * the cs4232.c uses 64k like on 8 bit dma-channels 0,1,2,3
+ */
+
+static void __init prep_init_sound(void)
+{
+	PPC_DEVICE *audiodevice = NULL;
+
+	/*
+	 * Get the needed resource informations from residual data.
+	 *
+	 */
+	if (have_residual_data)
+		audiodevice = residual_find_device(~0, NULL,
+				MultimediaController, AudioController, -1, 0);
+
+	if (audiodevice != NULL) {
+		PnP_TAG_PACKET *pkt;
+
+		pkt = PnP_find_packet((unsigned char *)&res->DevicePnPHeap[audiodevice->AllocatedOffset],
+				S5_Packet, 0);
+		if (pkt != NULL)
+			ppc_cs4232_dma = masktoint(pkt->S5_Pack.DMAMask);
+		pkt = PnP_find_packet((unsigned char*)&res->DevicePnPHeap[audiodevice->AllocatedOffset],
+				S5_Packet, 1);
+		if (pkt != NULL)
+			ppc_cs4232_dma2 = masktoint(pkt->S5_Pack.DMAMask);
+	}
+
+	/*
+	 * These are the PReP specs' defaults for the cs4231.  We use these
+	 * as fallback incase we don't have residual data.
+	 * At least the IBM Thinkpad 850 with IDE DMA Channels at 6 and 7
+	 * will use the other values.
+	 */
+	if (audiodevice == NULL) {
+		switch (_prep_type) {
+		case _PREP_IBM:
+			ppc_cs4232_dma = 1;
+			ppc_cs4232_dma2 = -1;
+			break;
+		default:
+			ppc_cs4232_dma = 6;
+			ppc_cs4232_dma2 = 7;
+		}
+	}
+
+	/*
+	 * Find a way to push these informations to the cs4232 driver
+	 * Give it out with printk, when not in cmd_line?
+	 * Append it to  cmd_line and saved_command_line?
+	 * Format is cs4232=io,irq,dma,dma2
+	 */
+}
+#endif /* CONFIG_SOUND_CS4232 */
+
+/*
+ * Fill out screen_info according to the residual data. This allows us to use
+ * at least vesafb.
+ */
+static void __init
+prep_init_vesa(void)
+{
+#if     (defined(CONFIG_FB_VGA16) || defined(CONFIG_FB_VGA16_MODULE) || \
+	 defined(CONFIG_FB_VESA))
+	PPC_DEVICE *vgadev = NULL;
+
+	if (have_residual_data)
+		vgadev = residual_find_device(~0, NULL, DisplayController,
+							SVGAController, -1, 0);
+
+	if (vgadev != NULL) {
+		PnP_TAG_PACKET *pkt;
+
+		pkt = PnP_find_large_vendor_packet(
+				(unsigned char *)&res->DevicePnPHeap[vgadev->AllocatedOffset],
+				0x04, 0); /* 0x04 = Display Tag */
+		if (pkt != NULL) {
+			unsigned char *ptr = (unsigned char *)pkt;
+
+			if (ptr[4]) {
+				/* graphics mode */
+				screen_info.orig_video_isVGA = VIDEO_TYPE_VLFB;
+
+				screen_info.lfb_depth = ptr[4] * 8;
+
+				screen_info.lfb_width = swab16(*(short *)(ptr+6));
+				screen_info.lfb_height = swab16(*(short *)(ptr+8));
+				screen_info.lfb_linelength = swab16(*(short *)(ptr+10));
+
+				screen_info.lfb_base = swab32(*(long *)(ptr+12));
+				screen_info.lfb_size = swab32(*(long *)(ptr+20)) / 65536;
+			}
+		}
+	}
+#endif
+}
+
+/*
+ * Set DBAT 2 to access 0x80000000 so early progress messages will work
+ */
+static __inline__ void
+prep_set_bat(void)
+{
+	/* wait for all outstanding memory access to complete */
+	mb();
+
+	/* setup DBATs */
+	mtspr(SPRN_DBAT2U, 0x80001ffe);
+	mtspr(SPRN_DBAT2L, 0x8000002a);
+
+	/* wait for updates */
+	mb();
+}
+
+/*
+ * IBM 3-digit status LED
+ */
+static unsigned int ibm_statusled_base __prepdata;
+
+static void __prep
+ibm_statusled_progress(char *s, unsigned short hex);
+
+static int __prep
+ibm_statusled_panic(struct notifier_block *dummy1, unsigned long dummy2,
+		    void * dummy3)
+{
+	ibm_statusled_progress(NULL, 0x505); /* SOS */
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ibm_statusled_block __prepdata = {
+	ibm_statusled_panic,
+	NULL,
+	INT_MAX /* try to do it first */
+};
+
+static void __prep
+ibm_statusled_progress(char *s, unsigned short hex)
+{
+	static int notifier_installed;
+	/*
+	 * Progress uses 4 digits and we have only 3.  So, we map 0xffff to
+	 * 0xfff for display switch off.  Out of range values are mapped to
+	 * 0xeff, as I'm told 0xf00 and above are reserved for hardware codes.
+	 * Install the panic notifier when the display is first switched off.
+	 */
+	if (hex == 0xffff) {
+		hex = 0xfff;
+		if (!notifier_installed) {
+			++notifier_installed;
+			notifier_chain_register(&panic_notifier_list,
+						&ibm_statusled_block);
+		}
+	}
+	else
+		if (hex > 0xfff)
+			hex = 0xeff;
+
+	mb();
+	outw(hex, ibm_statusled_base);
+}
+
+static void __init
+ibm_statusled_init(void)
+{
+	/*
+	 * The IBM 3-digit LED display is specified in the residual data
+	 * as an operator panel device, type "System Status LED".  Find
+	 * that device and determine its address.  We validate all the
+	 * other parameters on the off-chance another, similar device
+	 * exists.
+	 */
+	if (have_residual_data) {
+		PPC_DEVICE *led;
+		PnP_TAG_PACKET *pkt;
+
+		led = residual_find_device(~0, NULL, SystemPeripheral,
+					   OperatorPanel, SystemStatusLED, 0);
+		if (!led)
+			return;
+
+		pkt = PnP_find_packet((unsigned char *)
+		       &res->DevicePnPHeap[led->AllocatedOffset], S8_Packet, 0);
+		if (!pkt)
+			return;
+
+		if (pkt->S8_Pack.IOInfo != ISAAddr16bit)
+			return;
+		if (*(unsigned short *)pkt->S8_Pack.RangeMin !=
+		    *(unsigned short *)pkt->S8_Pack.RangeMax)
+			return;
+		if (pkt->S8_Pack.IOAlign != 2)
+			return;
+		if (pkt->S8_Pack.IONum != 2)
+			return;
+
+		ibm_statusled_base = ld_le16((unsigned short *)
+					     (pkt->S8_Pack.RangeMin));
+		ppc_md.progress = ibm_statusled_progress;
+	}
+}
+
+static void __init
+prep_setup_arch(void)
+{
+	unsigned char reg;
+	int is_ide=0;
+
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000;
+
+	/* Lookup PCI host bridges */
+	prep_find_bridges();
+
+	/* Set up floppy in PS/2 mode */
+	outb(0x09, SIO_CONFIG_RA);
+	reg = inb(SIO_CONFIG_RD);
+	reg = (reg & 0x3F) | 0x40;
+	outb(reg, SIO_CONFIG_RD);
+	outb(reg, SIO_CONFIG_RD);	/* Have to write twice to change! */
+
+	switch ( _prep_type )
+	{
+	case _PREP_IBM:
+		reg = inb(PREP_IBM_PLANAR);
+		printk(KERN_INFO "IBM planar ID: %02x", reg);
+		switch (reg) {
+			case PREP_IBM_SANDALFOOT:
+				prep_gen_enable_l2();
+				setup_ibm_pci = prep_sandalfoot_setup_pci;
+				ppc_md.power_off = prep_sig750_poweroff;
+				ppc_md.show_cpuinfo = prep_sandalfoot_cpuinfo;
+				break;
+			case PREP_IBM_THINKPAD:
+				prep_gen_enable_l2();
+				setup_ibm_pci = prep_thinkpad_setup_pci;
+				ppc_md.power_off = prep_carrera_poweroff;
+				ppc_md.show_cpuinfo = prep_thinkpad_cpuinfo;
+				break;
+			default:
+				if (have_residual_data) {
+					prep_gen_enable_l2();
+					setup_ibm_pci = prep_residual_setup_pci;
+					ppc_md.power_off = prep_halt;
+					ppc_md.show_cpuinfo = prep_gen_cpuinfo;
+					break;
+				}
+				else
+					printk(" - unknown! Assuming Carolina");
+					/* fall through */
+			case PREP_IBM_CAROLINA_IDE_0:
+			case PREP_IBM_CAROLINA_IDE_1:
+			case PREP_IBM_CAROLINA_IDE_2:
+			case PREP_IBM_CAROLINA_IDE_3:
+				is_ide = 1;
+			case PREP_IBM_CAROLINA_SCSI_0:
+			case PREP_IBM_CAROLINA_SCSI_1:
+			case PREP_IBM_CAROLINA_SCSI_2:
+			case PREP_IBM_CAROLINA_SCSI_3:
+				prep_carolina_enable_l2();
+				setup_ibm_pci = prep_carolina_setup_pci;
+				ppc_md.power_off = prep_sig750_poweroff;
+				ppc_md.show_cpuinfo = prep_carolina_cpuinfo;
+				break;
+			case PREP_IBM_TIGER1_133:
+			case PREP_IBM_TIGER1_166:
+			case PREP_IBM_TIGER1_180:
+			case PREP_IBM_TIGER1_xxx:
+			case PREP_IBM_TIGER1_333:
+				prep_carolina_enable_l2();
+				setup_ibm_pci = prep_tiger1_setup_pci;
+				ppc_md.power_off = prep_sig750_poweroff;
+				ppc_md.show_cpuinfo = prep_tiger1_cpuinfo;
+				break;
+		}
+		printk("\n");
+
+		/* default root device */
+		if (is_ide)
+			ROOT_DEV = MKDEV(IDE0_MAJOR, 3);
+		else
+			ROOT_DEV = MKDEV(SCSI_DISK0_MAJOR, 3);
+
+		break;
+	case _PREP_Motorola:
+		prep_gen_enable_l2();
+		ppc_md.power_off = prep_halt;
+		ppc_md.show_cpuinfo = prep_mot_cpuinfo;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+		if (initrd_start)
+			ROOT_DEV = Root_RAM0;
+		else
+#endif
+#ifdef CONFIG_ROOT_NFS
+			ROOT_DEV = Root_NFS;
+#else
+			ROOT_DEV = Root_SDA2;
+#endif
+		break;
+	}
+
+	/* Read in NVRAM data */
+	init_prep_nvram();
+
+	/* if no bootargs, look in NVRAM */
+	if ( cmd_line[0] == '\0' ) {
+		char *bootargs;
+		 bootargs = prep_nvram_get_var("bootargs");
+		 if (bootargs != NULL) {
+			 strcpy(cmd_line, bootargs);
+			 /* again.. */
+			 strcpy(saved_command_line, cmd_line);
+		}
+	}
+
+#ifdef CONFIG_SOUND_CS4232
+	prep_init_sound();
+#endif /* CONFIG_SOUND_CS4232 */
+
+	prep_init_vesa();
+
+	switch (_prep_type) {
+	case _PREP_Motorola:
+		raven_init();
+		break;
+	case _PREP_IBM:
+		ibm_prep_init();
+		break;
+	}
+
+#ifdef CONFIG_VGA_CONSOLE
+	/* vgacon.c needs to know where we mapped IO memory in io_block_mapping() */
+	vgacon_remap_base = 0xf0000000;
+	conswitchp = &vga_con;
+#endif
+}
+
+/*
+ * First, see if we can get this information from the residual data.
+ * This is important on some IBM PReP systems.  If we cannot, we let the
+ * TODC code handle doing this.
+ */
+static void __init
+prep_calibrate_decr(void)
+{
+	if (have_residual_data) {
+		unsigned long freq, divisor = 4;
+
+		if ( res->VitalProductData.ProcessorBusHz ) {
+			freq = res->VitalProductData.ProcessorBusHz;
+			printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+					(freq/divisor)/1000000,
+					(freq/divisor)%1000000);
+			tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+			tb_ticks_per_jiffy = freq / HZ / divisor;
+		}
+	}
+	else
+		todc_calibrate_decr();
+}
+
+static unsigned int __prep
+prep_irq_canonicalize(u_int irq)
+{
+	if (irq == 2)
+	{
+		return 9;
+	}
+	else
+	{
+		return irq;
+	}
+}
+
+static void __init
+prep_init_IRQ(void)
+{
+	int i;
+	unsigned int pci_viddid, pci_did;
+
+	if (OpenPIC_Addr != NULL) {
+		openpic_init(NUM_8259_INTERRUPTS);
+		/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
+		openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+				       i8259_irq);
+	}
+	for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
+		irq_desc[i].handler = &i8259_pic;
+
+	if (have_residual_data) {
+		i8259_init(residual_isapic_addr());
+		return;
+	}
+
+	/* If we have a Raven PCI bridge or a Hawk PCI bridge / Memory
+	 * controller, we poll (as they have a different int-ack address). */
+	early_read_config_dword(NULL, 0, 0, PCI_VENDOR_ID, &pci_viddid);
+	pci_did = (pci_viddid & 0xffff0000) >> 16;
+	if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_MOTOROLA)
+			&& ((pci_did == PCI_DEVICE_ID_MOTOROLA_RAVEN)
+				|| (pci_did == PCI_DEVICE_ID_MOTOROLA_HAWK)))
+		i8259_init(0);
+	else
+		/* PCI interrupt ack address given in section 6.1.8 of the
+		 * PReP specification. */
+		i8259_init(MPC10X_MAPA_PCI_INTACK_ADDR);
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+static int __prep
+prep_ide_default_irq(unsigned long base)
+{
+	switch (base) {
+		case 0x1f0: return 13;
+		case 0x170: return 13;
+		case 0x1e8: return 11;
+		case 0x168: return 10;
+		case 0xfff0: return 14;		/* MCP(N)750 ide0 */
+		case 0xffe0: return 15;		/* MCP(N)750 ide1 */
+		default: return 0;
+	}
+}
+
+static unsigned long __prep
+prep_ide_default_io_base(int index)
+{
+	switch (index) {
+		case 0: return 0x1f0;
+		case 1: return 0x170;
+		case 2: return 0x1e8;
+		case 3: return 0x168;
+		default:
+			return 0;
+	}
+}
+#endif
+
+#ifdef CONFIG_SMP
+/* PReP (MTX) support */
+static int __init
+smp_prep_probe(void)
+{
+	extern int mot_multi;
+
+	if (mot_multi) {
+		openpic_request_IPIs();
+		smp_hw_index[1] = 1;
+		return 2;
+	}
+
+	return 1;
+}
+
+static void __init
+smp_prep_kick_cpu(int nr)
+{
+	*(unsigned long *)KERNELBASE = nr;
+	asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
+	printk("CPU1 released, waiting\n");
+}
+
+static void __init
+smp_prep_setup_cpu(int cpu_nr)
+{
+	if (OpenPIC_Addr)
+		do_openpic_setup_cpu();
+}
+
+static struct smp_ops_t prep_smp_ops __prepdata = {
+	smp_openpic_message_pass,
+	smp_prep_probe,
+	smp_prep_kick_cpu,
+	smp_prep_setup_cpu,
+	.give_timebase = smp_generic_give_timebase,
+	.take_timebase = smp_generic_take_timebase,
+};
+#endif /* CONFIG_SMP */
+
+/*
+ * Setup the bat mappings we're going to load that cover
+ * the io areas.  RAM was mapped by mapin_ram().
+ * -- Cort
+ */
+static void __init
+prep_map_io(void)
+{
+	io_block_mapping(0x80000000, PREP_ISA_IO_BASE, 0x10000000, _PAGE_IO);
+	io_block_mapping(0xf0000000, PREP_ISA_MEM_BASE, 0x08000000, _PAGE_IO);
+}
+
+static int __init
+prep_request_io(void)
+{
+	if (_machine == _MACH_prep) {
+#ifdef CONFIG_NVRAM
+		request_region(PREP_NVRAM_AS0, 0x8, "nvram");
+#endif
+		request_region(0x00,0x20,"dma1");
+		request_region(0x40,0x20,"timer");
+		request_region(0x80,0x10,"dma page reg");
+		request_region(0xc0,0x20,"dma2");
+	}
+
+	return 0;
+}
+
+device_initcall(prep_request_io);
+
+void __init
+prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
+		unsigned long r6, unsigned long r7)
+{
+#ifdef CONFIG_PREP_RESIDUAL
+	/* make a copy of residual data */
+	if ( r3 ) {
+		memcpy((void *)res,(void *)(r3+KERNELBASE),
+			 sizeof(RESIDUAL));
+	}
+#endif
+
+	isa_io_base = PREP_ISA_IO_BASE;
+	isa_mem_base = PREP_ISA_MEM_BASE;
+	pci_dram_offset = PREP_PCI_DRAM_OFFSET;
+	ISA_DMA_THRESHOLD = 0x00ffffff;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+
+	/* figure out what kind of prep workstation we are */
+	if (have_residual_data) {
+		if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
+			_prep_type = _PREP_IBM;
+		else
+			_prep_type = _PREP_Motorola;
+	}
+	else {
+		/* assume motorola if no residual (netboot?) */
+		_prep_type = _PREP_Motorola;
+	}
+
+#ifdef CONFIG_PREP_RESIDUAL
+	/* Switch off all residual data processing if the user requests it */
+	if (strstr(cmd_line, "noresidual") != NULL)
+			res = NULL;
+#endif
+
+	/* Initialise progress early to get maximum benefit */
+	prep_set_bat();
+	ibm_statusled_init();
+
+	ppc_md.setup_arch     = prep_setup_arch;
+	ppc_md.show_percpuinfo = prep_show_percpuinfo;
+	ppc_md.show_cpuinfo   = NULL; /* set in prep_setup_arch() */
+	ppc_md.irq_canonicalize = prep_irq_canonicalize;
+	ppc_md.init_IRQ       = prep_init_IRQ;
+	/* this gets changed later on if we have an OpenPIC -- Cort */
+	ppc_md.get_irq        = i8259_irq;
+
+	ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
+
+	ppc_md.restart        = prep_restart;
+	ppc_md.power_off      = NULL; /* set in prep_setup_arch() */
+	ppc_md.halt           = prep_halt;
+
+	ppc_md.nvram_read_val = prep_nvram_read_val;
+	ppc_md.nvram_write_val = prep_nvram_write_val;
+
+	ppc_md.time_init      = todc_time_init;
+	if (_prep_type == _PREP_IBM) {
+		ppc_md.rtc_read_val = todc_mc146818_read_val;
+		ppc_md.rtc_write_val = todc_mc146818_write_val;
+		TODC_INIT(TODC_TYPE_MC146818, RTC_PORT(0), NULL, RTC_PORT(1),
+				8);
+	} else {
+		TODC_INIT(TODC_TYPE_MK48T59, PREP_NVRAM_AS0, PREP_NVRAM_AS1,
+				PREP_NVRAM_DATA, 8);
+	}
+
+	ppc_md.calibrate_decr = prep_calibrate_decr;
+	ppc_md.set_rtc_time   = todc_set_rtc_time;
+	ppc_md.get_rtc_time   = todc_get_rtc_time;
+
+	ppc_md.setup_io_mappings = prep_map_io;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+	ppc_ide_md.default_irq = prep_ide_default_irq;
+	ppc_ide_md.default_io_base = prep_ide_default_io_base;
+#endif
+
+#ifdef CONFIG_SMP
+	ppc_md.smp_ops		 = &prep_smp_ops;
+#endif /* CONFIG_SMP */
+}
diff --git a/arch/ppc/platforms/prpmc750.c b/arch/ppc/platforms/prpmc750.c
new file mode 100644
index 0000000..c894e1a
--- /dev/null
+++ b/arch/ppc/platforms/prpmc750.c
@@ -0,0 +1,364 @@
+/*
+ * arch/ppc/platforms/prpmc750_setup.c
+ *
+ * Board setup routines for Motorola PrPMC750
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc.  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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/ide.h>
+#include <linux/root_dev.h>
+#include <linux/slab.h>
+
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/uaccess.h>
+#include <asm/time.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/hawk.h>
+
+#include "prpmc750.h"
+
+extern unsigned long loops_per_jiffy;
+
+extern void gen550_progress(char *, unsigned short);
+
+static u_char prpmc750_openpic_initsenses[] __initdata =
+{
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_HOSTINT0 */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_UART */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_DEBUGINT */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_HAWK_WDT */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_UNUSED */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_ABORT */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_HOSTINT1 */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_HOSTINT2 */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_HOSTINT3 */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_PMC_INTA */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_PMC_INTB */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_PMC_INTC */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_PMC_INTD */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_UNUSED */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_UNUSED */
+    (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC750_INT_UNUSED */
+};
+
+/*
+ * Motorola PrPMC750/PrPMC800 in PrPMCBASE or PrPMC-Carrier
+ * Combined irq tables.  Only Base has IDSEL 14, only Carrier has 21 and 22.
+ */
+static inline int
+prpmc_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	/*
+	 *      PCI IDSEL/INTPIN->INTLINE
+	 *      A       B       C       D
+	 */
+	{
+		{12,	0,	0,	0},  /* IDSEL 14 - Ethernet, base */
+		{0,	0,	0,	0},  /* IDSEL 15 - unused */
+		{10,	11,	12,	9},  /* IDSEL 16 - PMC A1, PMC1 */
+		{10,	11,	12,	9},  /* IDSEL 17 - PrPMC-A-B, PMC2-B */
+		{11,	12,	9,	10}, /* IDSEL 18 - PMC A1-B, PMC1-B */
+		{0,	0,	0,	0},  /* IDSEL 19 - unused */
+		{9,	10,	11,	12}, /* IDSEL 20 - P2P Bridge */
+		{11,	12,	9,	10}, /* IDSEL 21 - PMC A2, carrier */
+		{12,	9,	10,	11}, /* IDSEL 22 - PMC A2-B, carrier */
+	};
+	const long min_idsel = 14, max_idsel = 22, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+};
+
+static void __init prpmc750_pcibios_fixup(void)
+{
+	struct pci_dev *dev;
+	unsigned short wtmp;
+
+	/*
+	 * Kludge to clean up after PPC6BUG which doesn't
+	 * configure the CL5446 VGA card.  Also the
+	 * resource subsystem doesn't fixup the
+	 * PCI mem resources on the CL5446.
+	 */
+	if ((dev = pci_get_device(PCI_VENDOR_ID_CIRRUS,
+				   PCI_DEVICE_ID_CIRRUS_5446, 0))) {
+		dev->resource[0].start += PRPMC750_PCI_PHY_MEM_OFFSET;
+		dev->resource[0].end += PRPMC750_PCI_PHY_MEM_OFFSET;
+		pci_read_config_word(dev, PCI_COMMAND, &wtmp);
+		pci_write_config_word(dev, PCI_COMMAND, wtmp | 3);
+		/* Enable Color mode in MISC reg */
+		outb(0x03, 0x3c2);
+		/* Select DRAM config reg */
+		outb(0x0f, 0x3c4);
+		/* Set proper DRAM config */
+		outb(0xdf, 0x3c5);
+		pci_dev_put(dev);
+	}
+}
+
+void __init prpmc750_find_bridges(void)
+{
+	struct pci_controller *hose;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+	hose->io_base_virt = (void *)PRPMC750_ISA_IO_BASE;
+	hose->pci_mem_offset = PRPMC750_PCI_PHY_MEM_OFFSET;
+
+	pci_init_resource(&hose->io_resource,
+			  PRPMC750_PCI_IO_START,
+			  PRPMC750_PCI_IO_END,
+			  IORESOURCE_IO, "PCI host bridge");
+
+	pci_init_resource(&hose->mem_resources[0],
+			  PRPMC750_PROC_PCI_MEM_START,
+			  PRPMC750_PROC_PCI_MEM_END,
+			  IORESOURCE_MEM, "PCI host bridge");
+
+	hose->io_space.start = PRPMC750_PCI_IO_START;
+	hose->io_space.end = PRPMC750_PCI_IO_END;
+	hose->mem_space.start = PRPMC750_PCI_MEM_START;
+	hose->mem_space.end = PRPMC750_PCI_MEM_END - HAWK_MPIC_SIZE;
+
+	if (hawk_init(hose, PRPMC750_HAWK_PPC_REG_BASE,
+		      PRPMC750_PROC_PCI_MEM_START,
+		      PRPMC750_PROC_PCI_MEM_END - HAWK_MPIC_SIZE,
+		      PRPMC750_PROC_PCI_IO_START, PRPMC750_PROC_PCI_IO_END,
+		      PRPMC750_PROC_PCI_MEM_END - HAWK_MPIC_SIZE + 1)
+	    != 0) {
+		printk(KERN_CRIT "Could not initialize host bridge\n");
+	}
+
+	hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+	ppc_md.pcibios_fixup = prpmc750_pcibios_fixup;
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = prpmc_map_irq;
+}
+static int prpmc750_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "machine\t\t: PrPMC750\n");
+
+	return 0;
+}
+
+static void __init prpmc750_setup_arch(void)
+{
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000 / HZ;
+
+	/* Lookup PCI host bridges */
+	prpmc750_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA2;
+#endif
+
+	OpenPIC_InitSenses = prpmc750_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof(prpmc750_openpic_initsenses);
+
+	printk(KERN_INFO "Port by MontaVista Software, Inc. "
+			"(source@mvista.com)\n");
+}
+
+/*
+ * Compute the PrPMC750's bus speed using the baud clock as a
+ * reference.
+ */
+static unsigned long __init prpmc750_get_bus_speed(void)
+{
+	unsigned long tbl_start, tbl_end;
+	unsigned long current_state, old_state, bus_speed;
+	unsigned char lcr, dll, dlm;
+	int baud_divisor, count;
+
+	/* Read the UART's baud clock divisor */
+	lcr = readb(PRPMC750_SERIAL_0_LCR);
+	writeb(lcr | UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR);
+	dll = readb(PRPMC750_SERIAL_0_DLL);
+	dlm = readb(PRPMC750_SERIAL_0_DLM);
+	writeb(lcr & ~UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR);
+	baud_divisor = (dlm << 8) | dll;
+
+	/*
+	 * Use the baud clock divisor and base baud clock
+	 * to determine the baud rate and use that as
+	 * the number of baud clock edges we use for
+	 * the time base sample.  Make it half the baud
+	 * rate.
+	 */
+	count = PRPMC750_BASE_BAUD / (baud_divisor * 16);
+
+	/* Find the first edge of the baud clock */
+	old_state = readb(PRPMC750_STATUS_REG) & PRPMC750_BAUDOUT_MASK;
+	do {
+		current_state = readb(PRPMC750_STATUS_REG) &
+		    PRPMC750_BAUDOUT_MASK;
+	} while (old_state == current_state);
+
+	old_state = current_state;
+
+	/* Get the starting time base value */
+	tbl_start = get_tbl();
+
+	/*
+	 * Loop until we have found a number of edges equal
+	 * to half the count (half the baud rate)
+	 */
+	do {
+		do {
+			current_state = readb(PRPMC750_STATUS_REG) &
+			    PRPMC750_BAUDOUT_MASK;
+		} while (old_state == current_state);
+		old_state = current_state;
+	} while (--count);
+
+	/* Get the ending time base value */
+	tbl_end = get_tbl();
+
+	/* Compute bus speed */
+	bus_speed = (tbl_end - tbl_start) * 128;
+
+	return bus_speed;
+}
+
+static void __init prpmc750_calibrate_decr(void)
+{
+	unsigned long freq;
+	int divisor = 4;
+
+	freq = prpmc750_get_bus_speed();
+
+	tb_ticks_per_jiffy = freq / (HZ * divisor);
+	tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
+}
+
+static void prpmc750_restart(char *cmd)
+{
+	local_irq_disable();
+	writeb(PRPMC750_MODRST_MASK, PRPMC750_MODRST_REG);
+	while (1) ;
+}
+
+static void prpmc750_halt(void)
+{
+	local_irq_disable();
+	while (1) ;
+}
+
+static void prpmc750_power_off(void)
+{
+	prpmc750_halt();
+}
+
+static void __init prpmc750_init_IRQ(void)
+{
+	openpic_init(0);
+}
+
+/*
+ * Set BAT 3 to map 0xf0000000 to end of physical memory space.
+ */
+static __inline__ void prpmc750_set_bat(void)
+{
+	mb();
+	mtspr(SPRN_DBAT1U, 0xf0001ffe);
+	mtspr(SPRN_DBAT1L, 0xf000002a);
+	mb();
+}
+
+/*
+ * We need to read the Falcon/Hawk memory controller
+ * to properly determine this value
+ */
+static unsigned long __init prpmc750_find_end_of_memory(void)
+{
+	/* Read the memory size from the Hawk SMC */
+	return hawk_get_mem_size(PRPMC750_HAWK_SMC_BASE);
+}
+
+static void __init prpmc750_map_io(void)
+{
+	io_block_mapping(PRPMC750_ISA_IO_BASE, PRPMC750_ISA_IO_BASE,
+			 0x10000000, _PAGE_IO);
+#if 0
+	io_block_mapping(0xf0000000, 0xc0000000, 0x08000000, _PAGE_IO);
+#endif
+	io_block_mapping(0xf8000000, 0xf8000000, 0x08000000, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	/* Cover the Hawk registers with a BAT */
+	prpmc750_set_bat();
+
+	isa_io_base = PRPMC750_ISA_IO_BASE;
+	isa_mem_base = PRPMC750_ISA_MEM_BASE;
+	pci_dram_offset = PRPMC750_PCI_DRAM_OFFSET;
+
+	ppc_md.setup_arch = prpmc750_setup_arch;
+	ppc_md.show_cpuinfo = prpmc750_show_cpuinfo;
+	ppc_md.init_IRQ = prpmc750_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+
+	ppc_md.find_end_of_memory = prpmc750_find_end_of_memory;
+	ppc_md.setup_io_mappings = prpmc750_map_io;
+
+	ppc_md.restart = prpmc750_restart;
+	ppc_md.power_off = prpmc750_power_off;
+	ppc_md.halt = prpmc750_halt;
+
+	/* PrPMC750 has no timekeeper part */
+	ppc_md.time_init = NULL;
+	ppc_md.get_rtc_time = NULL;
+	ppc_md.set_rtc_time = NULL;
+	ppc_md.calibrate_decr = prpmc750_calibrate_decr;
+
+#ifdef  CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = gen550_progress;
+#endif				/* CONFIG_SERIAL_TEXT_DEBUG */
+}
diff --git a/arch/ppc/platforms/prpmc750.h b/arch/ppc/platforms/prpmc750.h
new file mode 100644
index 0000000..015b4f5
--- /dev/null
+++ b/arch/ppc/platforms/prpmc750.h
@@ -0,0 +1,95 @@
+/*
+ * include/asm-ppc/platforms/prpmc750.h
+ *
+ * Definitions for Motorola PrPMC750 board support
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_PRPMC750_H__
+#define __ASM_PRPMC750_H__
+
+/*
+ * Due to limiations imposed by legacy hardware (primaryily IDE controllers),
+ * the PrPMC750 carrier board operates using a PReP address map.
+ *
+ * From Processor (physical) -> PCI:
+ *   PCI Mem Space: 0xc0000000 - 0xfe000000 -> 0x00000000 - 0x3e000000 (768 MB)
+ *   PCI I/O Space: 0x80000000 - 0x90000000 -> 0x00000000 - 0x10000000 (256 MB)
+ *	Note: Must skip 0xfe000000-0xfe400000 for CONFIG_HIGHMEM/PKMAP area
+ *
+ * From PCI -> Processor (physical):
+ *   System Memory: 0x80000000 -> 0x00000000
+ */
+
+#define PRPMC750_ISA_IO_BASE		PREP_ISA_IO_BASE
+#define PRPMC750_ISA_MEM_BASE		PREP_ISA_MEM_BASE
+
+/* PCI Memory space mapping info */
+#define PRPMC750_PCI_MEM_SIZE		0x30000000U
+#define PRPMC750_PROC_PCI_MEM_START	PRPMC750_ISA_MEM_BASE
+#define PRPMC750_PROC_PCI_MEM_END	(PRPMC750_PROC_PCI_MEM_START +	\
+					 PRPMC750_PCI_MEM_SIZE - 1)
+#define PRPMC750_PCI_MEM_START		0x00000000U
+#define PRPMC750_PCI_MEM_END		(PRPMC750_PCI_MEM_START +	\
+					 PRPMC750_PCI_MEM_SIZE - 1)
+
+/* PCI I/O space mapping info */
+#define PRPMC750_PCI_IO_SIZE		0x10000000U
+#define PRPMC750_PROC_PCI_IO_START	PRPMC750_ISA_IO_BASE
+#define PRPMC750_PROC_PCI_IO_END	(PRPMC750_PROC_PCI_IO_START +	\
+					 PRPMC750_PCI_IO_SIZE - 1)
+#define PRPMC750_PCI_IO_START		0x00000000U
+#define PRPMC750_PCI_IO_END		(PRPMC750_PCI_IO_START + 	\
+					 PRPMC750_PCI_IO_SIZE - 1)
+
+/* System memory mapping info */
+#define PRPMC750_PCI_DRAM_OFFSET	PREP_PCI_DRAM_OFFSET
+#define PRPMC750_PCI_PHY_MEM_OFFSET	(PRPMC750_ISA_MEM_BASE-PRPMC750_PCI_MEM_START)
+
+/* Register address definitions */
+#define PRPMC750_HAWK_SMC_BASE		0xfef80000U
+#define PRPMC750_HAWK_PPC_REG_BASE	0xfeff0000U
+
+#define PRPMC750_BASE_BAUD		1843200
+#define PRPMC750_SERIAL_0		0xfef88000
+#define PRPMC750_SERIAL_0_DLL		(PRPMC750_SERIAL_0 + (UART_DLL << 4))
+#define PRPMC750_SERIAL_0_DLM		(PRPMC750_SERIAL_0 + (UART_DLM << 4))
+#define PRPMC750_SERIAL_0_LCR		(PRPMC750_SERIAL_0 + (UART_LCR << 4))
+
+#define PRPMC750_STATUS_REG		0xfef88080
+#define PRPMC750_BAUDOUT_MASK		0x02
+#define PRPMC750_MONARCH_MASK		0x01
+
+#define PRPMC750_MODRST_REG		0xfef880a0
+#define PRPMC750_MODRST_MASK		0x01
+
+#define PRPMC750_PIRQ_REG		0xfef880b0
+#define PRPMC750_SEL1_MASK		0x02
+#define PRPMC750_SEL0_MASK		0x01
+
+#define PRPMC750_TBEN_REG		0xfef880c0
+#define PRPMC750_TBEN_MASK		0x01
+
+/* UART Defines. */
+#define RS_TABLE_SIZE  4
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD  (PRPMC750_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+#define SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, PRPMC750_SERIAL_0, 1, STD_COM_FLAGS, \
+		iomem_base: (unsigned char *)PRPMC750_SERIAL_0, \
+		iomem_reg_shift: 4, \
+		io_type: SERIAL_IO_MEM } /* ttyS0 */
+
+#endif				/* __ASM_PRPMC750_H__ */
+#endif				/* __KERNEL__ */
diff --git a/arch/ppc/platforms/prpmc800.c b/arch/ppc/platforms/prpmc800.c
new file mode 100644
index 0000000..8b09fa6
--- /dev/null
+++ b/arch/ppc/platforms/prpmc800.c
@@ -0,0 +1,477 @@
+/*
+ * arch/ppc/platforms/prpmc800.c
+ *
+ * Author: Dale Farnsworth <dale.farnsworth@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc.  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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/ide.h>
+#include <linux/root_dev.h>
+#include <linux/harrier_defs.h>
+
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/harrier.h>
+
+#include "prpmc800.h"
+
+#define HARRIER_REVI_REG	(PRPMC800_HARRIER_XCSR_BASE+HARRIER_REVI_OFF)
+#define HARRIER_UCTL_REG	(PRPMC800_HARRIER_XCSR_BASE+HARRIER_UCTL_OFF)
+#define HARRIER_MISC_CSR_REG   (PRPMC800_HARRIER_XCSR_BASE+HARRIER_MISC_CSR_OFF)
+#define HARRIER_IFEVP_REG    (PRPMC800_HARRIER_MPIC_BASE+HARRIER_MPIC_IFEVP_OFF)
+#define HARRIER_IFEDE_REG    (PRPMC800_HARRIER_MPIC_BASE+HARRIER_MPIC_IFEDE_OFF)
+#define HARRIER_FEEN_REG	(PRPMC800_HARRIER_XCSR_BASE+HARRIER_FEEN_OFF)
+#define HARRIER_FEMA_REG	(PRPMC800_HARRIER_XCSR_BASE+HARRIER_FEMA_OFF)
+
+#define HARRIER_VENI_REG	(PRPMC800_HARRIER_XCSR_BASE + HARRIER_VENI_OFF)
+#define HARRIER_MISC_CSR	(PRPMC800_HARRIER_XCSR_BASE + \
+				 HARRIER_MISC_CSR_OFF)
+
+#define MONARCH	(monarch != 0)
+#define NON_MONARCH (monarch == 0)
+
+extern int mpic_init(void);
+extern unsigned long loops_per_jiffy;
+extern void gen550_progress(char *, unsigned short);
+
+static int monarch = 0;
+static int found_self = 0;
+static int self = 0;
+
+static u_char prpmc800_openpic_initsenses[] __initdata =
+{
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_HOSTINT0 */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_UNUSED */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_DEBUGINT */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_HARRIER_WDT */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_UNUSED */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_UNUSED */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_HOSTINT1 */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_HOSTINT2 */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_HOSTINT3 */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_PMC_INTA */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_PMC_INTB */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_PMC_INTC */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_PMC_INTD */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_UNUSED */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_UNUSED */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_UNUSED */
+   (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* PRPMC800_INT_HARRIER_INT (UARTS, ABORT, DMA) */
+};
+
+/*
+ * Motorola PrPMC750/PrPMC800 in PrPMCBASE or PrPMC-Carrier
+ * Combined irq tables.  Only Base has IDSEL 14, only Carrier has 21 and 22.
+ */
+static inline int
+prpmc_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	/*
+	 *      PCI IDSEL/INTPIN->INTLINE
+	 *      A       B       C       D
+	 */
+	{
+		{12,	0,	0,	0},  /* IDSEL 14 - Ethernet, base */
+		{0,	0,	0,	0},  /* IDSEL 15 - unused */
+		{10,	11,	12,	9},  /* IDSEL 16 - PMC A1, PMC1 */
+		{10,	11,	12,	9},  /* IDSEL 17 - PrPMC-A-B, PMC2-B */
+		{11,	12,	9,	10}, /* IDSEL 18 - PMC A1-B, PMC1-B */
+		{0,	0,	0,	0},  /* IDSEL 19 - unused */
+		{9,	10,	11,	12}, /* IDSEL 20 - P2P Bridge */
+		{11,	12,	9,	10}, /* IDSEL 21 - PMC A2, carrier */
+		{12,	9,	10,	11}, /* IDSEL 22 - PMC A2-B, carrier */
+	};
+	const long min_idsel = 14, max_idsel = 22, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+};
+
+static int
+prpmc_read_config_dword(struct pci_controller *hose, u8 bus, u8 devfn,
+			int offset, u32 * val)
+{
+	/* paranoia */
+	if ((hose == NULL) ||
+	    (hose->cfg_addr == NULL) || (hose->cfg_data == NULL))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	out_be32(hose->cfg_addr, ((offset & 0xfc) << 24) | (devfn << 16)
+		 | ((bus - hose->bus_offset) << 8) | 0x80);
+	*val = in_le32((u32 *) (hose->cfg_data + (offset & 3)));
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+#define HARRIER_PCI_VEND_DEV_ID	(PCI_VENDOR_ID_MOTOROLA | \
+				 (PCI_DEVICE_ID_MOTOROLA_HARRIER << 16))
+static int prpmc_self(u8 bus, u8 devfn)
+{
+	/*
+	 * Harriers always view themselves as being on bus 0. If we're not
+	 * looking at bus 0, we're not going to find ourselves.
+	 */
+	if (bus != 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	else {
+		int result;
+		int val;
+		struct pci_controller *hose;
+
+		hose = pci_bus_to_hose(bus);
+
+		/* See if target device is a Harrier */
+		result = prpmc_read_config_dword(hose, bus, devfn,
+						 PCI_VENDOR_ID, &val);
+		if ((result != PCIBIOS_SUCCESSFUL) ||
+		    (val != HARRIER_PCI_VEND_DEV_ID))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+		/*
+		 * LBA bit is set if target Harrier == initiating Harrier
+		 * (i.e. if we are reading our own PCI header).
+		 */
+		result = prpmc_read_config_dword(hose, bus, devfn,
+						 HARRIER_LBA_OFF, &val);
+		if ((result != PCIBIOS_SUCCESSFUL) ||
+		    ((val & HARRIER_LBA_MSK) != HARRIER_LBA_MSK))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+		/* It's us, save our location for later */
+		self = devfn;
+		found_self = 1;
+		return PCIBIOS_SUCCESSFUL;
+	}
+}
+
+static int prpmc_exclude_device(u8 bus, u8 devfn)
+{
+	/*
+	 * Monarch is allowed to access all PCI devices. Non-monarch is
+	 * only allowed to access its own Harrier.
+	 */
+
+	if (MONARCH)
+		return PCIBIOS_SUCCESSFUL;
+	if (found_self)
+		if ((bus == 0) && (devfn == self))
+			return PCIBIOS_SUCCESSFUL;
+		else
+			return PCIBIOS_DEVICE_NOT_FOUND;
+	else
+		return prpmc_self(bus, devfn);
+}
+
+void __init prpmc800_find_bridges(void)
+{
+	struct pci_controller *hose;
+	int host_bridge;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	ppc_md.pci_exclude_device = prpmc_exclude_device;
+	ppc_md.pcibios_fixup = NULL;
+	ppc_md.pcibios_fixup_bus = NULL;
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = prpmc_map_irq;
+
+	setup_indirect_pci(hose,
+			   PRPMC800_PCI_CONFIG_ADDR, PRPMC800_PCI_CONFIG_DATA);
+
+	/* Get host bridge vendor/dev id */
+
+	host_bridge = in_be32((uint *) (HARRIER_VENI_REG));
+
+	if (host_bridge != HARRIER_VEND_DEV_ID) {
+		printk(KERN_CRIT "Host bridge 0x%x not supported\n",
+				host_bridge);
+		return;
+	}
+
+	monarch = in_be32((uint *) HARRIER_MISC_CSR) & HARRIER_SYSCON;
+
+	printk(KERN_INFO "Running as %s.\n",
+			MONARCH ? "Monarch" : "Non-Monarch");
+
+	hose->io_space.start = PRPMC800_PCI_IO_START;
+	hose->io_space.end = PRPMC800_PCI_IO_END;
+	hose->io_base_virt = (void *)PRPMC800_ISA_IO_BASE;
+	hose->pci_mem_offset = PRPMC800_PCI_PHY_MEM_OFFSET;
+
+	pci_init_resource(&hose->io_resource,
+			  PRPMC800_PCI_IO_START, PRPMC800_PCI_IO_END,
+			  IORESOURCE_IO, "PCI host bridge");
+
+	if (MONARCH) {
+		hose->mem_space.start = PRPMC800_PCI_MEM_START;
+		hose->mem_space.end = PRPMC800_PCI_MEM_END;
+
+		pci_init_resource(&hose->mem_resources[0],
+				  PRPMC800_PCI_MEM_START,
+				  PRPMC800_PCI_MEM_END,
+				  IORESOURCE_MEM, "PCI host bridge");
+
+		if (harrier_init(hose,
+				 PRPMC800_HARRIER_XCSR_BASE,
+				 PRPMC800_PROC_PCI_MEM_START,
+				 PRPMC800_PROC_PCI_MEM_END,
+				 PRPMC800_PROC_PCI_IO_START,
+				 PRPMC800_PROC_PCI_IO_END,
+				 PRPMC800_HARRIER_MPIC_BASE) != 0)
+			printk(KERN_CRIT "Could not initialize HARRIER "
+					 "bridge\n");
+
+		harrier_release_eready(PRPMC800_HARRIER_XCSR_BASE);
+		harrier_wait_eready(PRPMC800_HARRIER_XCSR_BASE);
+		hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+	} else {
+		pci_init_resource(&hose->mem_resources[0],
+				  PRPMC800_NM_PCI_MEM_START,
+				  PRPMC800_NM_PCI_MEM_END,
+				  IORESOURCE_MEM, "PCI host bridge");
+
+		hose->mem_space.start = PRPMC800_NM_PCI_MEM_START;
+		hose->mem_space.end = PRPMC800_NM_PCI_MEM_END;
+
+		if (harrier_init(hose,
+				 PRPMC800_HARRIER_XCSR_BASE,
+				 PRPMC800_NM_PROC_PCI_MEM_START,
+				 PRPMC800_NM_PROC_PCI_MEM_END,
+				 PRPMC800_PROC_PCI_IO_START,
+				 PRPMC800_PROC_PCI_IO_END,
+				 PRPMC800_HARRIER_MPIC_BASE) != 0)
+			printk(KERN_CRIT "Could not initialize HARRIER "
+					 "bridge\n");
+
+		harrier_setup_nonmonarch(PRPMC800_HARRIER_XCSR_BASE,
+					 HARRIER_ITSZ_1MB);
+		harrier_release_eready(PRPMC800_HARRIER_XCSR_BASE);
+	}
+}
+
+static int prpmc800_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "machine\t\t: PrPMC800\n");
+
+	return 0;
+}
+
+static void __init prpmc800_setup_arch(void)
+{
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000 / HZ;
+
+	/* Lookup PCI host bridges */
+	prpmc800_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA2;
+#endif
+
+	printk(KERN_INFO "Port by MontaVista Software, Inc. "
+			 "(source@mvista.com)\n");
+}
+
+/*
+ * Compute the PrPMC800's tbl frequency using the baud clock as a reference.
+ */
+static void __init prpmc800_calibrate_decr(void)
+{
+	unsigned long tbl_start, tbl_end;
+	unsigned long current_state, old_state, tb_ticks_per_second;
+	unsigned int count;
+	unsigned int harrier_revision;
+
+	harrier_revision = readb(HARRIER_REVI_REG);
+	if (harrier_revision < 2) {
+		/* XTAL64 was broken in harrier revision 1 */
+		printk(KERN_INFO "time_init: Harrier revision %d, assuming "
+				 "100 Mhz bus\n", harrier_revision);
+		tb_ticks_per_second = 100000000 / 4;
+		tb_ticks_per_jiffy = tb_ticks_per_second / HZ;
+		tb_to_us = mulhwu_scale_factor(tb_ticks_per_second, 1000000);
+		return;
+	}
+
+	/*
+	 * The XTAL64 bit oscillates at the 1/64 the base baud clock
+	 * Set count to XTAL64 cycles per second.  Since we'll count
+	 * half-cycles, we'll reach the count in half a second.
+	 */
+	count = PRPMC800_BASE_BAUD / 64;
+
+	/* Find the first edge of the baud clock */
+	old_state = readb(HARRIER_UCTL_REG) & HARRIER_XTAL64_MASK;
+	do {
+		current_state = readb(HARRIER_UCTL_REG) & HARRIER_XTAL64_MASK;
+	} while (old_state == current_state);
+
+	old_state = current_state;
+
+	/* Get the starting time base value */
+	tbl_start = get_tbl();
+
+	/*
+	 * Loop until we have found a number of edges (half-cycles)
+	 * equal to the count (half a second)
+	 */
+	do {
+		do {
+			current_state = readb(HARRIER_UCTL_REG) &
+			    HARRIER_XTAL64_MASK;
+		} while (old_state == current_state);
+		old_state = current_state;
+	} while (--count);
+
+	/* Get the ending time base value */
+	tbl_end = get_tbl();
+
+	/* We only counted for half a second, so double to get ticks/second */
+	tb_ticks_per_second = (tbl_end - tbl_start) * 2;
+	tb_ticks_per_jiffy = tb_ticks_per_second / HZ;
+	tb_to_us = mulhwu_scale_factor(tb_ticks_per_second, 1000000);
+}
+
+static void prpmc800_restart(char *cmd)
+{
+	ulong temp;
+
+	local_irq_disable();
+	temp = in_be32((uint *) HARRIER_MISC_CSR_REG);
+	temp |= HARRIER_RSTOUT;
+	out_be32((uint *) HARRIER_MISC_CSR_REG, temp);
+	while (1) ;
+}
+
+static void prpmc800_halt(void)
+{
+	local_irq_disable();
+	while (1) ;
+}
+
+static void prpmc800_power_off(void)
+{
+	prpmc800_halt();
+}
+
+static void __init prpmc800_init_IRQ(void)
+{
+	OpenPIC_InitSenses = prpmc800_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof(prpmc800_openpic_initsenses);
+
+	/* Setup external interrupt sources. */
+	openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000);
+	/* Setup internal UART interrupt source. */
+	openpic_set_sources(16, 1, OpenPIC_Addr + 0x10200);
+
+	/* Do the MPIC initialization based on the above settings. */
+	openpic_init(0);
+
+	/* enable functional exceptions for uarts and abort */
+	out_8((u8 *) HARRIER_FEEN_REG, (HARRIER_FE_UA0 | HARRIER_FE_UA1));
+	out_8((u8 *) HARRIER_FEMA_REG, ~(HARRIER_FE_UA0 | HARRIER_FE_UA1));
+}
+
+/*
+ * Set BAT 3 to map 0xf0000000 to end of physical memory space.
+ */
+static __inline__ void prpmc800_set_bat(void)
+{
+	mb();
+	mtspr(SPRN_DBAT1U, 0xf0001ffe);
+	mtspr(SPRN_DBAT1L, 0xf000002a);
+	mb();
+}
+
+/*
+ * We need to read the Harrier memory controller
+ * to properly determine this value
+ */
+static unsigned long __init prpmc800_find_end_of_memory(void)
+{
+	/* Read the memory size from the Harrier XCSR */
+	return harrier_get_mem_size(PRPMC800_HARRIER_XCSR_BASE);
+}
+
+static void __init prpmc800_map_io(void)
+{
+	io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO);
+	io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	prpmc800_set_bat();
+
+	isa_io_base = PRPMC800_ISA_IO_BASE;
+	isa_mem_base = PRPMC800_ISA_MEM_BASE;
+	pci_dram_offset = PRPMC800_PCI_DRAM_OFFSET;
+
+	ppc_md.setup_arch = prpmc800_setup_arch;
+	ppc_md.show_cpuinfo = prpmc800_show_cpuinfo;
+	ppc_md.init_IRQ = prpmc800_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+
+	ppc_md.find_end_of_memory = prpmc800_find_end_of_memory;
+	ppc_md.setup_io_mappings = prpmc800_map_io;
+
+	ppc_md.restart = prpmc800_restart;
+	ppc_md.power_off = prpmc800_power_off;
+	ppc_md.halt = prpmc800_halt;
+
+	/* PrPMC800 has no timekeeper part */
+	ppc_md.time_init = NULL;
+	ppc_md.get_rtc_time = NULL;
+	ppc_md.set_rtc_time = NULL;
+	ppc_md.calibrate_decr = prpmc800_calibrate_decr;
+#ifdef  CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = gen550_progress;
+#else				/* !CONFIG_SERIAL_TEXT_DEBUG */
+	ppc_md.progress = NULL;
+#endif				/* CONFIG_SERIAL_TEXT_DEBUG */
+}
diff --git a/arch/ppc/platforms/prpmc800.h b/arch/ppc/platforms/prpmc800.h
new file mode 100644
index 0000000..e53ec9b
--- /dev/null
+++ b/arch/ppc/platforms/prpmc800.h
@@ -0,0 +1,82 @@
+/*
+ * include/asm-ppc/platforms/prpmc800.h
+ *
+ * Definitions for Motorola PrPMC800 board support
+ *
+ * Author: Dale Farnsworth <dale.farnsworth@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc.  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.
+ */
+ /*
+  * From Processor to PCI:
+  *   PCI Mem Space: 0x80000000 - 0xa0000000 -> 0x80000000 - 0xa0000000 (512 MB)
+  *   PCI I/O Space: 0xfe400000 - 0xfeef0000 -> 0x00000000 - 0x00b00000 (11 MB)
+  *      Note: Must skip 0xfe000000-0xfe400000 for CONFIG_HIGHMEM/PKMAP area
+  *
+  * From PCI to Processor:
+  *   System Memory: 0x00000000 -> 0x00000000
+  */
+
+#ifndef __ASMPPC_PRPMC800_H
+#define __ASMPPC_PRPMC800_H
+
+#define PRPMC800_PCI_CONFIG_ADDR		0xfe000cf8
+#define PRPMC800_PCI_CONFIG_DATA		0xfe000cfc
+
+#define PRPMC800_PROC_PCI_IO_START		0xfe400000U
+#define PRPMC800_PROC_PCI_IO_END		0xfeefffffU
+#define PRPMC800_PCI_IO_START			0x00000000U
+#define PRPMC800_PCI_IO_END			0x00afffffU
+
+#define PRPMC800_PROC_PCI_MEM_START		0x80000000U
+#define PRPMC800_PROC_PCI_MEM_END		0x9fffffffU
+#define PRPMC800_PCI_MEM_START			0x80000000U
+#define PRPMC800_PCI_MEM_END			0x9fffffffU
+
+#define PRPMC800_NM_PROC_PCI_MEM_START		0x40000000U
+#define PRPMC800_NM_PROC_PCI_MEM_END		0xdfffffffU
+#define PRPMC800_NM_PCI_MEM_START		0x40000000U
+#define PRPMC800_NM_PCI_MEM_END			0xdfffffffU
+
+#define PRPMC800_PCI_DRAM_OFFSET		0x00000000U
+#define PRPMC800_PCI_PHY_MEM_OFFSET		0x00000000U
+
+#define PRPMC800_ISA_IO_BASE			PRPMC800_PROC_PCI_IO_START
+#define PRPMC800_ISA_MEM_BASE			0x00000000U
+
+#define PRPMC800_HARRIER_XCSR_BASE		HARRIER_DEFAULT_XCSR_BASE
+#define PRPMC800_HARRIER_MPIC_BASE		0xff000000
+
+#define PRPMC800_SERIAL_1			0xfeff00c0
+
+#define PRPMC800_BASE_BAUD			1843200
+
+/*
+ * interrupt vector number and priority for harrier internal interrupt
+ * sources
+ */
+#define PRPMC800_INT_IRQ			16
+#define PRPMC800_INT_PRI			15
+
+/* UART Defines. */
+#define RS_TABLE_SIZE  4
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD (PRPMC800_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+/* UARTS are at IRQ 16 */
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, PRPMC800_SERIAL_1, 16, STD_COM_FLAGS, /* ttyS0 */\
+		iomem_base: (unsigned char *)PRPMC800_SERIAL_1,		\
+		iomem_reg_shift: 0,					\
+		io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
+
+#endif				/* __ASMPPC_PRPMC800_H */
diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c
new file mode 100644
index 0000000..2a99b43
--- /dev/null
+++ b/arch/ppc/platforms/radstone_ppc7d.c
@@ -0,0 +1,1452 @@
+/*
+ * arch/ppc/platforms/radstone_ppc7d.c
+ *
+ * Board setup routines for the Radstone PPC7D boards.
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by - Mark A. Greer <mgreer@mvista.com>
+ *
+ * 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.
+ */
+
+/* Radstone PPC7D boards are rugged VME boards with PPC 7447A CPUs,
+ * Discovery-II, dual gigabit ethernet, dual PMC, USB, keyboard/mouse,
+ * 4 serial ports, 2 high speed serial ports (MPSCs) and optional
+ * SCSI / VGA.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>		/* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/mv643xx.h>
+#include <linux/netdevice.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/vga.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/mpc10x.h>
+#include <asm/pci-bridge.h>
+#include <asm/mv64x60.h>
+#include <asm/i8259.h>
+
+#include "radstone_ppc7d.h"
+
+#undef DEBUG
+
+#define PPC7D_RST_PIN			17 	/* GPP17 */
+
+extern u32 mv64360_irq_base;
+
+static struct mv64x60_handle bh;
+static int ppc7d_has_alma;
+
+extern void gen550_progress(char *, unsigned short);
+extern void gen550_init(int, struct uart_port *);
+
+/* residual data */
+unsigned char __res[sizeof(bd_t)];
+
+/*****************************************************************************
+ * Serial port code
+ *****************************************************************************/
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+static void __init ppc7d_early_serial_map(void)
+{
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+	mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
+#elif defined(CONFIG_SERIAL_8250)
+	struct uart_port serial_req;
+
+	/* Setup serial port access */
+	memset(&serial_req, 0, sizeof(serial_req));
+	serial_req.uartclk = UART_CLK;
+	serial_req.irq = 4;
+	serial_req.flags = STD_COM_FLAGS;
+	serial_req.iotype = SERIAL_IO_MEM;
+	serial_req.membase = (u_char *) PPC7D_SERIAL_0;
+
+	gen550_init(0, &serial_req);
+	if (early_serial_setup(&serial_req) != 0)
+		printk(KERN_ERR "Early serial init of port 0 failed\n");
+
+	/* Assume early_serial_setup() doesn't modify serial_req */
+	serial_req.line = 1;
+	serial_req.irq = 3;
+	serial_req.membase = (u_char *) PPC7D_SERIAL_1;
+
+	gen550_init(1, &serial_req);
+	if (early_serial_setup(&serial_req) != 0)
+		printk(KERN_ERR "Early serial init of port 1 failed\n");
+#else
+#error CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
+#endif
+}
+#endif /* CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG */
+
+/*****************************************************************************
+ * Low-level board support code
+ *****************************************************************************/
+
+static unsigned long __init ppc7d_find_end_of_memory(void)
+{
+	bd_t *bp = (bd_t *) __res;
+
+	if (bp->bi_memsize)
+		return bp->bi_memsize;
+
+	return (256 * 1024 * 1024);
+}
+
+static void __init ppc7d_map_io(void)
+{
+	/* remove temporary mapping */
+	mtspr(SPRN_DBAT3U, 0x00000000);
+	mtspr(SPRN_DBAT3L, 0x00000000);
+
+	io_block_mapping(0xe8000000, 0xe8000000, 0x08000000, _PAGE_IO);
+	io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+}
+
+static void ppc7d_restart(char *cmd)
+{
+	u32 data;
+
+	/* Disable GPP17 interrupt */
+	data = mv64x60_read(&bh, MV64x60_GPP_INTR_MASK);
+	data &= ~(1 << PPC7D_RST_PIN);
+	mv64x60_write(&bh, MV64x60_GPP_INTR_MASK, data);
+
+	/* Configure MPP17 as GPP */
+	data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2);
+	data &= ~(0x0000000f << 4);
+	mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data);
+
+	/* Enable pin GPP17 for output */
+	data = mv64x60_read(&bh, MV64x60_GPP_IO_CNTL);
+	data |= (1 << PPC7D_RST_PIN);
+	mv64x60_write(&bh, MV64x60_GPP_IO_CNTL, data);
+
+	/* Toggle GPP9 pin to reset the board */
+	mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, 1 << PPC7D_RST_PIN);
+	mv64x60_write(&bh, MV64x60_GPP_VALUE_SET, 1 << PPC7D_RST_PIN);
+
+	for (;;) ;		/* Spin until reset happens */
+	/* NOTREACHED */
+}
+
+static void ppc7d_power_off(void)
+{
+	u32 data;
+
+	local_irq_disable();
+
+	/* Ensure that internal MV643XX watchdog is disabled.
+	 * The Disco watchdog uses MPP17 on this hardware.
+	 */
+	data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2);
+	data &= ~(0x0000000f << 4);
+	mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data);
+
+	data = mv64x60_read(&bh, MV64x60_WDT_WDC);
+	if (data & 0x80000000) {
+		mv64x60_write(&bh, MV64x60_WDT_WDC, 1 << 24);
+		mv64x60_write(&bh, MV64x60_WDT_WDC, 2 << 24);
+	}
+
+	for (;;) ;		/* No way to shut power off with software */
+	/* NOTREACHED */
+}
+
+static void ppc7d_halt(void)
+{
+	ppc7d_power_off();
+	/* NOTREACHED */
+}
+
+static unsigned long ppc7d_led_no_pulse;
+
+static int __init ppc7d_led_pulse_disable(char *str)
+{
+	ppc7d_led_no_pulse = 1;
+	return 1;
+}
+
+/* This kernel option disables the heartbeat pulsing of a board LED */
+__setup("ledoff", ppc7d_led_pulse_disable);
+
+static void ppc7d_heartbeat(void)
+{
+	u32 data32;
+	u8 data8;
+	static int max706_wdog = 0;
+
+	/* Unfortunately we can't access the LED control registers
+	 * during early init because they're on the CPLD which is the
+	 * other side of a PCI bridge which goes unreachable during
+	 * PCI scan. So write the LEDs only if the MV64360 watchdog is
+	 * enabled (i.e. userspace apps are running so kernel is up)..
+	 */
+	data32 = mv64x60_read(&bh, MV64x60_WDT_WDC);
+	if (data32 & 0x80000000) {
+		/* Enable MAX706 watchdog if not done already */
+		if (!max706_wdog) {
+			outb(3, PPC7D_CPLD_RESET);
+			max706_wdog = 1;
+		}
+
+		/* Hit the MAX706 watchdog */
+		outb(0, PPC7D_CPLD_WATCHDOG_TRIG);
+
+		/* Pulse LED DS219 if not disabled */
+		if (!ppc7d_led_no_pulse) {
+			static int led_on = 0;
+
+			data8 = inb(PPC7D_CPLD_LEDS);
+			if (led_on)
+				data8 &= ~PPC7D_CPLD_LEDS_DS219_MASK;
+			else
+				data8 |= PPC7D_CPLD_LEDS_DS219_MASK;
+
+			outb(data8, PPC7D_CPLD_LEDS);
+			led_on = !led_on;
+		}
+	}
+	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+}
+
+static int ppc7d_show_cpuinfo(struct seq_file *m)
+{
+	u8 val;
+	u8 val1, val2;
+	static int flash_sizes[4] = { 64, 32, 0, 16 };
+	static int flash_banks[4] = { 4, 3, 2, 1 };
+	static char *pci_modes[] = { "PCI33", "PCI66",
+		"Unknown", "Unknown",
+		"PCIX33", "PCIX66",
+		"PCIX100", "PCIX133"
+	};
+
+	seq_printf(m, "vendor\t\t: Radstone Technology\n");
+	seq_printf(m, "machine\t\t: PPC7D\n");
+
+	val = inb(PPC7D_CPLD_BOARD_REVISION);
+	val1 = (val & PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK) >> 5;
+	val2 = (val & PPC7D_CPLD_BOARD_REVISION_LETTER_MASK);
+	seq_printf(m, "revision\t: %hd%c%c\n",
+		   val1,
+		   (val2 <= 0x18) ? 'A' + val2 : 'Y',
+		   (val2 > 0x18) ? 'A' + (val2 - 0x19) : ' ');
+
+	val = inb(PPC7D_CPLD_MOTHERBOARD_TYPE);
+	val1 = val & PPC7D_CPLD_MB_TYPE_PLL_MASK;
+	val2 = val & (PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK |
+		      PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK);
+	seq_printf(m, "bus speed\t: %dMHz\n",
+		   (val1 == PPC7D_CPLD_MB_TYPE_PLL_133) ? 133 :
+		   (val1 == PPC7D_CPLD_MB_TYPE_PLL_100) ? 100 :
+		   (val1 == PPC7D_CPLD_MB_TYPE_PLL_64) ? 64 : 0);
+
+	val = inb(PPC7D_CPLD_MEM_CONFIG_EXTEND);
+	val1 = val & PPC7D_CPLD_SDRAM_BANK_SIZE_MASK;
+	seq_printf(m, "SDRAM\t\t: %d%c",
+		   (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_128M) ? 128 :
+		   (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_256M) ? 256 :
+		   (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_512M) ? 512 : 1,
+		   (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_1G) ? 'G' : 'M');
+	if (val2 & PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK) {
+		seq_printf(m, " [ECC %sabled]",
+			   (val2 & PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK) ? "en" :
+			   "dis");
+	}
+	seq_printf(m, "\n");
+
+	val1 = (val & PPC7D_CPLD_FLASH_DEV_SIZE_MASK);
+	val2 = (val & PPC7D_CPLD_FLASH_BANK_NUM_MASK) >> 2;
+	seq_printf(m, "FLASH\t\t: %d banks of %dM, total %dM\n",
+		   flash_banks[val2], flash_sizes[val1],
+		   flash_banks[val2] * flash_sizes[val1]);
+
+	val = inb(PPC7D_CPLD_FLASH_WRITE_CNTL);
+	val1 = inb(PPC7D_CPLD_SW_FLASH_WRITE_PROTECT);
+	seq_printf(m, "  write links\t: %s%s%s%s\n",
+		   (val & PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK) ? "WRITE " : "",
+		   (val & PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK) ? "BOOT " : "",
+		   (val & PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK) ? "USER " : "",
+		   (val & (PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK |
+			   PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK |
+			   PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK)) ==
+		   0 ? "NONE" : "");
+	seq_printf(m, "  write sector h/w enables: %s%s%s%s%s\n",
+		   (val & PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK) ? "RECOVERY " :
+		   "",
+		   (val & PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK) ? "BOOT " : "",
+		   (val & PPD7D_CPLD_FLASH_CNTL_USER_WR_MASK) ? "USER " : "",
+		   (val1 & PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK) ? "NVRAM " :
+		   "",
+		   (((val &
+		      (PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK |
+		       PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK |
+		       PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK)) == 0)
+		    && ((val1 & PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK) ==
+			0)) ? "NONE" : "");
+	val1 =
+	    inb(PPC7D_CPLD_SW_FLASH_WRITE_PROTECT) &
+	    (PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK |
+	     PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK);
+	seq_printf(m, "  software sector enables: %s%s%s\n",
+		   (val1 & PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK) ? "SYSBOOT "
+		   : "",
+		   (val1 & PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK) ? "USER " : "",
+		   (val1 == 0) ? "NONE " : "");
+
+	seq_printf(m, "Boot options\t: %s%s%s%s\n",
+		   (val & PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK) ?
+		   "ALTERNATE " : "",
+		   (val & PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK) ? "VME " :
+		   "",
+		   (val & PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK) ? "RECOVERY "
+		   : "",
+		   ((val &
+		     (PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK |
+		      PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK |
+		      PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK)) ==
+		    0) ? "NONE" : "");
+
+	val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_1);
+	seq_printf(m, "Fitted modules\t: %s%s%s%s\n",
+		   (val & PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK) ? "" : "PMC1 ",
+		   (val & PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK) ? "" : "PMC2 ",
+		   (val & PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK) ? "AFIX " : "",
+		   ((val & (PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK |
+			    PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK |
+			    PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK)) ==
+		    (PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK |
+		     PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK)) ? "NONE" : "");
+
+	if (val & PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK) {
+		static const char *ids[] = {
+			"unknown",
+			"1553 (Dual Channel)",
+			"1553 (Single Channel)",
+			"8-bit SCSI + VGA",
+			"16-bit SCSI + VGA",
+			"1553 (Single Channel with sideband)",
+			"1553 (Dual Channel with sideband)",
+			NULL
+		};
+		u8 id = __raw_readb((void *)PPC7D_AFIX_REG_BASE + 0x03);
+		seq_printf(m, "AFIX module\t: 0x%hx [%s]\n", id,
+			   id < 7 ? ids[id] : "unknown");
+	}
+
+	val = inb(PPC7D_CPLD_PCI_CONFIG);
+	val1 = (val & PPC7D_CPLD_PCI_CONFIG_PCI0_MASK) >> 4;
+	val2 = (val & PPC7D_CPLD_PCI_CONFIG_PCI1_MASK);
+	seq_printf(m, "PCI#0\t\t: %s\nPCI#1\t\t: %s\n",
+		   pci_modes[val1], pci_modes[val2]);
+
+	val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_2);
+	seq_printf(m, "PMC1\t\t: %s\nPMC2\t\t: %s\n",
+		   (val & PPC7D_CPLD_EQPT_PRES_3_PMC1_V_MASK) ? "3.3v" : "5v",
+		   (val & PPC7D_CPLD_EQPT_PRES_3_PMC2_V_MASK) ? "3.3v" : "5v");
+	seq_printf(m, "PMC power source: %s\n",
+		   (val & PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_MASK) ? "VME" :
+		   "internal");
+
+	val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_4);
+	val2 = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_2);
+	seq_printf(m, "Fit options\t: %s%s%s%s%s%s%s\n",
+		   (val & PPC7D_CPLD_EQPT_PRES_4_LPT_MASK) ? "LPT " : "",
+		   (val & PPC7D_CPLD_EQPT_PRES_4_PS2_FITTED) ? "PS2 " : "",
+		   (val & PPC7D_CPLD_EQPT_PRES_4_USB2_FITTED) ? "USB2 " : "",
+		   (val2 & PPC7D_CPLD_EQPT_PRES_2_UNIVERSE_MASK) ? "VME " : "",
+		   (val2 & PPC7D_CPLD_EQPT_PRES_2_COM36_MASK) ? "COM3-6 " : "",
+		   (val2 & PPC7D_CPLD_EQPT_PRES_2_GIGE_MASK) ? "eth0 " : "",
+		   (val2 & PPC7D_CPLD_EQPT_PRES_2_DUALGIGE_MASK) ? "eth1 " :
+		   "");
+
+	val = inb(PPC7D_CPLD_ID_LINK);
+	val1 = val & (PPC7D_CPLD_ID_LINK_E6_MASK |
+		      PPC7D_CPLD_ID_LINK_E7_MASK |
+		      PPC7D_CPLD_ID_LINK_E12_MASK |
+		      PPC7D_CPLD_ID_LINK_E13_MASK);
+
+	val = inb(PPC7D_CPLD_FLASH_WRITE_CNTL) &
+	    (PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK |
+	     PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK |
+	     PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK);
+
+	seq_printf(m, "Board links present: %s%s%s%s%s%s%s%s\n",
+		   (val1 & PPC7D_CPLD_ID_LINK_E6_MASK) ? "E6 " : "",
+		   (val1 & PPC7D_CPLD_ID_LINK_E7_MASK) ? "E7 " : "",
+		   (val & PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK) ? "E9 " : "",
+		   (val & PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK) ? "E10 " : "",
+		   (val & PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK) ? "E11 " : "",
+		   (val1 & PPC7D_CPLD_ID_LINK_E12_MASK) ? "E12 " : "",
+		   (val1 & PPC7D_CPLD_ID_LINK_E13_MASK) ? "E13 " : "",
+		   ((val == 0) && (val1 == 0)) ? "NONE" : "");
+
+	val = inb(PPC7D_CPLD_WDOG_RESETSW_MASK);
+	seq_printf(m, "Front panel reset switch: %sabled\n",
+		   (val & PPC7D_CPLD_WDOG_RESETSW_MASK) ? "dis" : "en");
+
+	return 0;
+}
+
+static void __init ppc7d_calibrate_decr(void)
+{
+	ulong freq;
+
+	freq = 100000000 / 4;
+
+	pr_debug("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+		 freq / 1000000, freq % 1000000);
+
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
+
+/*****************************************************************************
+ * Interrupt stuff
+ *****************************************************************************/
+
+static irqreturn_t ppc7d_i8259_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	u32 temp = mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE);
+	if (temp & (1 << 28)) {
+		i8259_irq(regs);
+		mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, temp & (~(1 << 28)));
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+/*
+ * Each interrupt cause is assigned an IRQ number.
+ * Southbridge has 16*2 (two 8259's) interrupts.
+ * Discovery-II has 96 interrupts (cause-hi, cause-lo, gpp x 32).
+ * If multiple interrupts are pending, get_irq() returns the
+ * lowest pending irq number first.
+ *
+ *
+ * IRQ #   Source                              Trig   Active
+ * =============================================================
+ *
+ * Southbridge
+ * -----------
+ * IRQ #   Source                              Trig
+ * =============================================================
+ * 0       ISA High Resolution Counter         Edge
+ * 1       Keyboard                            Edge
+ * 2       Cascade From (IRQ 8-15)             Edge
+ * 3       Com 2 (Uart 2)                      Edge
+ * 4       Com 1 (Uart 1)                      Edge
+ * 5       PCI Int D/AFIX IRQZ ID4 (2,7)       Level
+ * 6       GPIO                                Level
+ * 7       LPT                                 Edge
+ * 8       RTC Alarm                           Edge
+ * 9       PCI Int A/PMC 2/AFIX IRQW ID1 (2,0) Level
+ * 10      PCI Int B/PMC 1/AFIX IRQX ID2 (2,1) Level
+ * 11      USB2                                Level
+ * 12      Mouse                               Edge
+ * 13      Reserved internally by Ali M1535+
+ * 14      PCI Int C/VME/AFIX IRQY ID3 (2,6)   Level
+ * 15      COM 5/6                             Level
+ *
+ * 16..112 Discovery-II...
+ *
+ * MPP28   Southbridge                         Edge   High
+ *
+ *
+ * Interrupts are cascaded through to the Discovery-II.
+ *
+ *  PCI ---
+ *         \
+ * CPLD --> ALI1535 -------> DISCOVERY-II
+ *        INTF           MPP28
+ */
+static void __init ppc7d_init_irq(void)
+{
+	int irq;
+
+	pr_debug("%s\n", __FUNCTION__);
+	i8259_init(0);
+	mv64360_init_irq();
+
+	/* IRQ 0..15 are handled by the cascaded 8259's of the Ali1535 */
+	for (irq = 0; irq < 16; irq++) {
+		irq_desc[irq].handler = &i8259_pic;
+	}
+	/* IRQs 5,6,9,10,11,14,15 are level sensitive */
+	irq_desc[5].status |= IRQ_LEVEL;
+	irq_desc[6].status |= IRQ_LEVEL;
+	irq_desc[9].status |= IRQ_LEVEL;
+	irq_desc[10].status |= IRQ_LEVEL;
+	irq_desc[11].status |= IRQ_LEVEL;
+	irq_desc[14].status |= IRQ_LEVEL;
+	irq_desc[15].status |= IRQ_LEVEL;
+
+	/* GPP28 is edge triggered */
+	irq_desc[mv64360_irq_base + MV64x60_IRQ_GPP28].status &= ~IRQ_LEVEL;
+}
+
+static u32 ppc7d_irq_canonicalize(u32 irq)
+{
+	if ((irq >= 16) && (irq < (16 + 96)))
+		irq -= 16;
+
+	return irq;
+}
+
+static int ppc7d_get_irq(struct pt_regs *regs)
+{
+	int irq;
+
+	irq = mv64360_get_irq(regs);
+	if (irq == (mv64360_irq_base + MV64x60_IRQ_GPP28))
+		irq = i8259_irq(regs);
+	return irq;
+}
+
+/*
+ * 9       PCI Int A/PMC 2/AFIX IRQW ID1 (2,0) Level
+ * 10      PCI Int B/PMC 1/AFIX IRQX ID2 (2,1) Level
+ * 14      PCI Int C/VME/AFIX IRQY ID3 (2,6)   Level
+ * 5       PCI Int D/AFIX IRQZ ID4 (2,7)       Level
+ */
+static int __init ppc7d_map_irq(struct pci_dev *dev, unsigned char idsel,
+				unsigned char pin)
+{
+	static const char pci_irq_table[][4] =
+	    /*
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *         A   B   C   D
+	     */
+	{
+		{10, 14, 5, 9},	/* IDSEL 10 - PMC2 / AFIX IRQW */
+		{9, 10, 14, 5},	/* IDSEL 11 - PMC1 / AFIX IRQX */
+		{5, 9, 10, 14},	/* IDSEL 12 - AFIX IRQY */
+		{14, 5, 9, 10},	/* IDSEL 13 - AFIX IRQZ */
+	};
+	const long min_idsel = 10, max_idsel = 14, irqs_per_slot = 4;
+
+	pr_debug("%s: %04x/%04x/%x: idsel=%hx pin=%hu\n", __FUNCTION__,
+		 dev->vendor, dev->device, PCI_FUNC(dev->devfn), idsel, pin);
+
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+void __init ppc7d_intr_setup(void)
+{
+	u32 data;
+
+	/*
+	 * Define GPP 28 interrupt polarity as active high
+	 * input signal and level triggered
+	 */
+	data = mv64x60_read(&bh, MV64x60_GPP_LEVEL_CNTL);
+	data &= ~(1 << 28);
+	mv64x60_write(&bh, MV64x60_GPP_LEVEL_CNTL, data);
+	data = mv64x60_read(&bh, MV64x60_GPP_IO_CNTL);
+	data &= ~(1 << 28);
+	mv64x60_write(&bh, MV64x60_GPP_IO_CNTL, data);
+
+	/* Config GPP intr ctlr to respond to level trigger */
+	data = mv64x60_read(&bh, MV64x60_COMM_ARBITER_CNTL);
+	data |= (1 << 10);
+	mv64x60_write(&bh, MV64x60_COMM_ARBITER_CNTL, data);
+
+	/* XXXX Erranum FEr PCI-#8 */
+	data = mv64x60_read(&bh, MV64x60_PCI0_CMD);
+	data &= ~((1 << 5) | (1 << 9));
+	mv64x60_write(&bh, MV64x60_PCI0_CMD, data);
+	data = mv64x60_read(&bh, MV64x60_PCI1_CMD);
+	data &= ~((1 << 5) | (1 << 9));
+	mv64x60_write(&bh, MV64x60_PCI1_CMD, data);
+
+	/*
+	 * Dismiss and then enable interrupt on GPP interrupt cause
+	 * for CPU #0
+	 */
+	mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~(1 << 28));
+	data = mv64x60_read(&bh, MV64x60_GPP_INTR_MASK);
+	data |= (1 << 28);
+	mv64x60_write(&bh, MV64x60_GPP_INTR_MASK, data);
+
+	/*
+	 * Dismiss and then enable interrupt on CPU #0 high cause reg
+	 * BIT27 summarizes GPP interrupts 23-31
+	 */
+	mv64x60_write(&bh, MV64360_IC_MAIN_CAUSE_HI, ~(1 << 27));
+	data = mv64x60_read(&bh, MV64360_IC_CPU0_INTR_MASK_HI);
+	data |= (1 << 27);
+	mv64x60_write(&bh, MV64360_IC_CPU0_INTR_MASK_HI, data);
+}
+
+/*****************************************************************************
+ * Platform device data fixup routines.
+ *****************************************************************************/
+
+#if defined(CONFIG_SERIAL_MPSC)
+static void __init ppc7d_fixup_mpsc_pdata(struct platform_device *pdev)
+{
+	struct mpsc_pdata *pdata;
+
+	pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
+
+	pdata->max_idle = 40;
+	pdata->default_baud = PPC7D_DEFAULT_BAUD;
+	pdata->brg_clk_src = PPC7D_MPSC_CLK_SRC;
+	pdata->brg_clk_freq = PPC7D_MPSC_CLK_FREQ;
+
+	return;
+}
+#endif
+
+#if defined(CONFIG_MV643XX_ETH)
+static void __init ppc7d_fixup_eth_pdata(struct platform_device *pdev)
+{
+	struct mv643xx_eth_platform_data *eth_pd;
+	static u16 phy_addr[] = {
+		PPC7D_ETH0_PHY_ADDR,
+		PPC7D_ETH1_PHY_ADDR,
+		PPC7D_ETH2_PHY_ADDR,
+	};
+	int i;
+
+	eth_pd = pdev->dev.platform_data;
+	eth_pd->force_phy_addr = 1;
+	eth_pd->phy_addr = phy_addr[pdev->id];
+	eth_pd->tx_queue_size = PPC7D_ETH_TX_QUEUE_SIZE;
+	eth_pd->rx_queue_size = PPC7D_ETH_RX_QUEUE_SIZE;
+
+	/* Adjust IRQ by mv64360_irq_base */
+	for (i = 0; i < pdev->num_resources; i++) {
+		struct resource *r = &pdev->resource[i];
+
+		if (r->flags & IORESOURCE_IRQ) {
+			r->start += mv64360_irq_base;
+			r->end += mv64360_irq_base;
+			pr_debug("%s, uses IRQ %d\n", pdev->name,
+				 (int)r->start);
+		}
+	}
+
+}
+#endif
+
+#if defined(CONFIG_I2C_MV64XXX)
+static void __init
+ppc7d_fixup_i2c_pdata(struct platform_device *pdev)
+{
+	struct mv64xxx_i2c_pdata *pdata;
+	int i;
+
+	pdata = pdev->dev.platform_data;
+	if (pdata == NULL) {
+		pdata = kmalloc(sizeof(*pdata), GFP_KERNEL);
+		if (pdata == NULL)
+			return;
+
+		memset(pdata, 0, sizeof(*pdata));
+		pdev->dev.platform_data = pdata;
+	}
+
+	/* divisors M=8, N=3 for 100kHz I2C from 133MHz system clock */
+	pdata->freq_m = 8;
+	pdata->freq_n = 3;
+	pdata->timeout = 500;
+	pdata->retries = 3;
+
+	/* Adjust IRQ by mv64360_irq_base */
+	for (i = 0; i < pdev->num_resources; i++) {
+		struct resource *r = &pdev->resource[i];
+
+		if (r->flags & IORESOURCE_IRQ) {
+			r->start += mv64360_irq_base;
+			r->end += mv64360_irq_base;
+			pr_debug("%s, uses IRQ %d\n", pdev->name, (int) r->start);
+		}
+	}
+}
+#endif
+
+static int __init ppc7d_platform_notify(struct device *dev)
+{
+	static struct {
+		char *bus_id;
+		void ((*rtn) (struct platform_device * pdev));
+	} dev_map[] = {
+#if defined(CONFIG_SERIAL_MPSC)
+		{ MPSC_CTLR_NAME ".0", ppc7d_fixup_mpsc_pdata },
+		{ MPSC_CTLR_NAME ".1", ppc7d_fixup_mpsc_pdata },
+#endif
+#if defined(CONFIG_MV643XX_ETH)
+		{ MV643XX_ETH_NAME ".0", ppc7d_fixup_eth_pdata },
+		{ MV643XX_ETH_NAME ".1", ppc7d_fixup_eth_pdata },
+		{ MV643XX_ETH_NAME ".2", ppc7d_fixup_eth_pdata },
+#endif
+#if defined(CONFIG_I2C_MV64XXX)
+		{ MV64XXX_I2C_CTLR_NAME ".0", ppc7d_fixup_i2c_pdata },
+#endif
+	};
+	struct platform_device *pdev;
+	int i;
+
+	if (dev && dev->bus_id)
+		for (i = 0; i < ARRAY_SIZE(dev_map); i++)
+			if (!strncmp(dev->bus_id, dev_map[i].bus_id,
+				     BUS_ID_SIZE)) {
+
+				pdev = container_of(dev,
+						    struct platform_device,
+						    dev);
+				dev_map[i].rtn(pdev);
+			}
+
+	return 0;
+}
+
+/*****************************************************************************
+ * PCI device fixups.
+ * These aren't really fixups per se. They are used to init devices as they
+ * are found during PCI scan.
+ *
+ * The PPC7D has an HB8 PCI-X bridge which must be set up during a PCI
+ * scan in order to find other devices on its secondary side.
+ *****************************************************************************/
+
+static void __init ppc7d_fixup_hb8(struct pci_dev *dev)
+{
+	u16 val16;
+
+	if (dev->bus->number == 0) {
+		pr_debug("PCI: HB8 init\n");
+
+		pci_write_config_byte(dev, 0x1c,
+				      ((PPC7D_PCI0_IO_START_PCI_ADDR & 0xf000)
+				       >> 8) | 0x01);
+		pci_write_config_byte(dev, 0x1d,
+				      (((PPC7D_PCI0_IO_START_PCI_ADDR +
+					 PPC7D_PCI0_IO_SIZE -
+					 1) & 0xf000) >> 8) | 0x01);
+		pci_write_config_word(dev, 0x30,
+				      PPC7D_PCI0_IO_START_PCI_ADDR >> 16);
+		pci_write_config_word(dev, 0x32,
+				      ((PPC7D_PCI0_IO_START_PCI_ADDR +
+					PPC7D_PCI0_IO_SIZE -
+					1) >> 16) & 0xffff);
+
+		pci_write_config_word(dev, 0x20,
+				      PPC7D_PCI0_MEM0_START_PCI_LO_ADDR >> 16);
+		pci_write_config_word(dev, 0x22,
+				      ((PPC7D_PCI0_MEM0_START_PCI_LO_ADDR +
+					PPC7D_PCI0_MEM0_SIZE -
+					1) >> 16) & 0xffff);
+		pci_write_config_word(dev, 0x24, 0);
+		pci_write_config_word(dev, 0x26, 0);
+		pci_write_config_dword(dev, 0x28, 0);
+		pci_write_config_dword(dev, 0x2c, 0);
+
+		pci_read_config_word(dev, 0x3e, &val16);
+		val16 |= ((1 << 5) | (1 << 1));	/* signal master aborts and
+						 * SERR to primary
+						 */
+		val16 &= ~(1 << 2);		/* ISA disable, so all ISA
+						 * ports forwarded to secondary
+						 */
+		pci_write_config_word(dev, 0x3e, val16);
+	}
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HINT, 0x0028, ppc7d_fixup_hb8);
+
+/* This should perhaps be a separate driver as we're actually initializing
+ * the chip for this board here. It's hardly a fixup...
+ */
+static void __init ppc7d_fixup_ali1535(struct pci_dev *dev)
+{
+	pr_debug("PCI: ALI1535 init\n");
+
+	if (dev->bus->number == 1) {
+		/* Configure the ISA Port Settings */
+		pci_write_config_byte(dev, 0x43, 0x00);
+
+		/* Disable PCI Interrupt polling mode */
+		pci_write_config_byte(dev, 0x45, 0x00);
+
+		/* Multifunction pin select INTFJ -> INTF */
+		pci_write_config_byte(dev, 0x78, 0x00);
+
+		/* Set PCI INT -> IRQ Routing control in for external
+		 * pins south bridge.
+		 */
+		pci_write_config_byte(dev, 0x48, 0x31);	/* [7-4] INT B -> IRQ10
+							 * [3-0] INT A -> IRQ9
+							 */
+		pci_write_config_byte(dev, 0x49, 0x5D);	/* [7-4] INT D -> IRQ5
+							 * [3-0] INT C -> IRQ14
+							 */
+
+		/* PPC7D setup */
+		/* NEC USB device on IRQ 11 (INTE) - INTF disabled */
+		pci_write_config_byte(dev, 0x4A, 0x09);
+
+		/* GPIO on IRQ 6 */
+		pci_write_config_byte(dev, 0x76, 0x07);
+
+		/* SIRQ I (COMS 5/6) use IRQ line 15.
+		 * Positive (not subtractive) address decode.
+		 */
+		pci_write_config_byte(dev, 0x44, 0x0f);
+
+		/* SIRQ II disabled */
+		pci_write_config_byte(dev, 0x75, 0x0);
+
+		/* On board USB and RTC disabled */
+		pci_write_config_word(dev, 0x52, (1 << 14));
+		pci_write_config_byte(dev, 0x74, 0x00);
+
+		/* On board IDE disabled */
+		pci_write_config_byte(dev, 0x58, 0x00);
+
+		/* Decode 32-bit addresses */
+		pci_write_config_byte(dev, 0x5b, 0);
+
+		/* Disable docking IO */
+		pci_write_config_word(dev, 0x5c, 0x0000);
+
+		/* Disable modem, enable sound */
+		pci_write_config_byte(dev, 0x77, (1 << 6));
+
+		/* Disable hot-docking mode */
+		pci_write_config_byte(dev, 0x7d, 0x00);
+	}
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1533, ppc7d_fixup_ali1535);
+
+static int ppc7d_pci_exclude_device(u8 bus, u8 devfn)
+{
+	/* Early versions of this board were fitted with IBM ALMA
+	 * PCI-VME bridge chips. The PCI config space of these devices
+	 * was not set up correctly and causes PCI scan problems.
+	 */
+	if ((bus == 1) && (PCI_SLOT(devfn) == 4) && ppc7d_has_alma)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return mv64x60_pci_exclude_device(bus, devfn);
+}
+
+/* This hook is called when each PCI bus is probed.
+ */
+static void ppc7d_pci_fixup_bus(struct pci_bus *bus)
+{
+	pr_debug("PCI BUS %hu: %lx/%lx %lx/%lx %lx/%lx %lx/%lx\n",
+		 bus->number,
+		 bus->resource[0] ? bus->resource[0]->start : 0,
+		 bus->resource[0] ? bus->resource[0]->end : 0,
+		 bus->resource[1] ? bus->resource[1]->start : 0,
+		 bus->resource[1] ? bus->resource[1]->end : 0,
+		 bus->resource[2] ? bus->resource[2]->start : 0,
+		 bus->resource[2] ? bus->resource[2]->end : 0,
+		 bus->resource[3] ? bus->resource[3]->start : 0,
+		 bus->resource[3] ? bus->resource[3]->end : 0);
+
+	if ((bus->number == 1) && (bus->resource[2] != NULL)) {
+		/* Hide PCI window 2 of Bus 1 which is used only to
+		 * map legacy ISA memory space.
+		 */
+		bus->resource[2]->start = 0;
+		bus->resource[2]->end = 0;
+		bus->resource[2]->flags = 0;
+	}
+}
+
+/*****************************************************************************
+ * Board device setup code
+ *****************************************************************************/
+
+void __init ppc7d_setup_peripherals(void)
+{
+	u32 val32;
+
+	/* Set up windows for boot CS */
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+				 PPC7D_BOOT_WINDOW_BASE, PPC7D_BOOT_WINDOW_SIZE,
+				 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+
+	/* Boot firmware configures the following DevCS addresses.
+	 * DevCS0 - board control/status
+	 * DevCS1 - test registers
+	 * DevCS2 - AFIX port/address registers (for identifying)
+	 * DevCS3 - FLASH
+	 *
+	 * We don't use DevCS0, DevCS1.
+	 */
+	val32 = mv64x60_read(&bh, MV64360_CPU_BAR_ENABLE);
+	val32 |= ((1 << 4) | (1 << 5));
+	mv64x60_write(&bh, MV64360_CPU_BAR_ENABLE, val32);
+	mv64x60_write(&bh, MV64x60_CPU2DEV_0_BASE, 0);
+	mv64x60_write(&bh, MV64x60_CPU2DEV_0_SIZE, 0);
+	mv64x60_write(&bh, MV64x60_CPU2DEV_1_BASE, 0);
+	mv64x60_write(&bh, MV64x60_CPU2DEV_1_SIZE, 0);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN,
+				 PPC7D_AFIX_REG_BASE, PPC7D_AFIX_REG_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN,
+				 PPC7D_FLASH_BASE, PPC7D_FLASH_SIZE_ACTUAL, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+				 PPC7D_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE,
+				 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+	/* Set up Enet->SRAM window */
+	mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN,
+				 PPC7D_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE,
+				 0x2);
+	bh.ci->enable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN);
+
+	/* Give enet r/w access to memory region */
+	val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_0);
+	val32 |= (0x3 << (4 << 1));
+	mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_0, val32);
+	val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_1);
+	val32 |= (0x3 << (4 << 1));
+	mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_1, val32);
+	val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_2);
+	val32 |= (0x3 << (4 << 1));
+	mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_2, val32);
+
+	val32 = mv64x60_read(&bh, MV64x60_TIMR_CNTR_0_3_CNTL);
+	val32 &= ~((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24));
+	mv64x60_write(&bh, MV64x60_TIMR_CNTR_0_3_CNTL, val32);
+
+	/* Enumerate pci bus.
+	 *
+	 * We scan PCI#0 first (the bus with the HB8 and other
+	 * on-board peripherals). We must configure the 64360 before
+	 * each scan, according to the bus number assignments.  Busses
+	 * are assigned incrementally, starting at 0.  PCI#0 is
+	 * usually assigned bus#0, the secondary side of the HB8 gets
+	 * bus#1 and PCI#1 (second PMC site) gets bus#2.  However, if
+	 * any PMC card has a PCI bridge, these bus assignments will
+	 * change.
+	 */
+
+	/* Turn off PCI retries */
+	val32 = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+	val32 |= (1 << 17);
+	mv64x60_write(&bh, MV64x60_CPU_CONFIG, val32);
+
+	/* Scan PCI#0 */
+	mv64x60_set_bus(&bh, 0, 0);
+	bh.hose_a->first_busno = 0;
+	bh.hose_a->last_busno = 0xff;
+	bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
+	printk(KERN_INFO "PCI#0: first=%d last=%d\n",
+	       bh.hose_a->first_busno, bh.hose_a->last_busno);
+
+	/* Scan PCI#1 */
+	bh.hose_b->first_busno = bh.hose_a->last_busno + 1;
+	mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno);
+	bh.hose_b->last_busno = 0xff;
+	bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b,
+		bh.hose_b->first_busno);
+	printk(KERN_INFO "PCI#1: first=%d last=%d\n",
+	       bh.hose_b->first_busno, bh.hose_b->last_busno);
+
+	/* Turn on PCI retries */
+	val32 = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+	val32 &= ~(1 << 17);
+	mv64x60_write(&bh, MV64x60_CPU_CONFIG, val32);
+
+	/* Setup interrupts */
+	ppc7d_intr_setup();
+}
+
+static void __init ppc7d_setup_bridge(void)
+{
+	struct mv64x60_setup_info si;
+	int i;
+	u32 temp;
+
+	mv64360_irq_base = 16;	/* first 16 intrs are 2 x 8259's */
+
+	memset(&si, 0, sizeof(si));
+
+	si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
+
+	si.pci_0.enable_bus = 1;
+	si.pci_0.pci_io.cpu_base = PPC7D_PCI0_IO_START_PROC_ADDR;
+	si.pci_0.pci_io.pci_base_hi = 0;
+	si.pci_0.pci_io.pci_base_lo = PPC7D_PCI0_IO_START_PCI_ADDR;
+	si.pci_0.pci_io.size = PPC7D_PCI0_IO_SIZE;
+	si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_0.pci_mem[0].cpu_base = PPC7D_PCI0_MEM0_START_PROC_ADDR;
+	si.pci_0.pci_mem[0].pci_base_hi = PPC7D_PCI0_MEM0_START_PCI_HI_ADDR;
+	si.pci_0.pci_mem[0].pci_base_lo = PPC7D_PCI0_MEM0_START_PCI_LO_ADDR;
+	si.pci_0.pci_mem[0].size = PPC7D_PCI0_MEM0_SIZE;
+	si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_0.pci_mem[1].cpu_base = PPC7D_PCI0_MEM1_START_PROC_ADDR;
+	si.pci_0.pci_mem[1].pci_base_hi = PPC7D_PCI0_MEM1_START_PCI_HI_ADDR;
+	si.pci_0.pci_mem[1].pci_base_lo = PPC7D_PCI0_MEM1_START_PCI_LO_ADDR;
+	si.pci_0.pci_mem[1].size = PPC7D_PCI0_MEM1_SIZE;
+	si.pci_0.pci_mem[1].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_0.pci_cmd_bits = 0;
+	si.pci_0.latency_timer = 0x80;
+
+	si.pci_1.enable_bus = 1;
+	si.pci_1.pci_io.cpu_base = PPC7D_PCI1_IO_START_PROC_ADDR;
+	si.pci_1.pci_io.pci_base_hi = 0;
+	si.pci_1.pci_io.pci_base_lo = PPC7D_PCI1_IO_START_PCI_ADDR;
+	si.pci_1.pci_io.size = PPC7D_PCI1_IO_SIZE;
+	si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_1.pci_mem[0].cpu_base = PPC7D_PCI1_MEM0_START_PROC_ADDR;
+	si.pci_1.pci_mem[0].pci_base_hi = PPC7D_PCI1_MEM0_START_PCI_HI_ADDR;
+	si.pci_1.pci_mem[0].pci_base_lo = PPC7D_PCI1_MEM0_START_PCI_LO_ADDR;
+	si.pci_1.pci_mem[0].size = PPC7D_PCI1_MEM0_SIZE;
+	si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_1.pci_mem[1].cpu_base = PPC7D_PCI1_MEM1_START_PROC_ADDR;
+	si.pci_1.pci_mem[1].pci_base_hi = PPC7D_PCI1_MEM1_START_PCI_HI_ADDR;
+	si.pci_1.pci_mem[1].pci_base_lo = PPC7D_PCI1_MEM1_START_PCI_LO_ADDR;
+	si.pci_1.pci_mem[1].size = PPC7D_PCI1_MEM1_SIZE;
+	si.pci_1.pci_mem[1].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_1.pci_cmd_bits = 0;
+	si.pci_1.latency_timer = 0x80;
+
+	/* Don't clear the SRAM window since we use it for debug */
+	si.window_preserve_mask_32_lo = (1 << MV64x60_CPU2SRAM_WIN);
+
+	printk(KERN_INFO "PCI: MV64360 PCI#0 IO at %x, size %x\n",
+	       si.pci_0.pci_io.cpu_base, si.pci_0.pci_io.size);
+	printk(KERN_INFO "PCI: MV64360 PCI#1 IO at %x, size %x\n",
+	       si.pci_1.pci_io.cpu_base, si.pci_1.pci_io.size);
+
+	for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) {
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+		si.cpu_prot_options[i] = 0;
+		si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
+		si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
+		si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
+
+		si.pci_0.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+
+		si.pci_1.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+#else
+		si.cpu_prot_options[i] = 0;
+		/* All PPC7D hardware uses B0 or newer MV64360 silicon which
+		 * does not have snoop bugs.
+		 */
+		si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB;
+		si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB;
+		si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB;
+
+		si.pci_0.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_WB |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+
+		si.pci_1.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_WB |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+#endif
+	}
+
+	/* Lookup PCI host bridges */
+	if (mv64x60_init(&bh, &si))
+		printk(KERN_ERR "MV64360 initialization failed.\n");
+
+	pr_debug("MV64360 regs @ %lx/%p\n", bh.p_base, bh.v_base);
+
+	/* Enable WB Cache coherency on SRAM */
+	temp = mv64x60_read(&bh, MV64360_SRAM_CONFIG);
+	pr_debug("SRAM_CONFIG: %x\n", temp);
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+	mv64x60_write(&bh, MV64360_SRAM_CONFIG, temp & ~0x2);
+#else
+	mv64x60_write(&bh, MV64360_SRAM_CONFIG, temp | 0x2);
+#endif
+	/* If system operates with internal bus arbiter (CPU master
+	 * control bit8) clear AACK Delay bit [25] in CPU
+	 * configuration register.
+	 */
+	temp = mv64x60_read(&bh, MV64x60_CPU_MASTER_CNTL);
+	if (temp & (1 << 8)) {
+		temp = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+		mv64x60_write(&bh, MV64x60_CPU_CONFIG, (temp & ~(1 << 25)));
+	}
+
+	/* Data and address parity is enabled */
+	temp = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+	mv64x60_write(&bh, MV64x60_CPU_CONFIG,
+		      (temp | (1 << 26) | (1 << 19)));
+
+	pci_dram_offset = 0;	/* sys mem at same addr on PCI & cpu bus */
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = ppc7d_map_irq;
+	ppc_md.pci_exclude_device = ppc7d_pci_exclude_device;
+
+	mv64x60_set_bus(&bh, 0, 0);
+	bh.hose_a->first_busno = 0;
+	bh.hose_a->last_busno = 0xff;
+	bh.hose_a->mem_space.start = PPC7D_PCI0_MEM0_START_PCI_LO_ADDR;
+	bh.hose_a->mem_space.end =
+	    PPC7D_PCI0_MEM0_START_PCI_LO_ADDR + PPC7D_PCI0_MEM0_SIZE;
+
+	/* These will be set later, as a result of PCI0 scan */
+	bh.hose_b->first_busno = 0;
+	bh.hose_b->last_busno = 0xff;
+	bh.hose_b->mem_space.start = PPC7D_PCI1_MEM0_START_PCI_LO_ADDR;
+	bh.hose_b->mem_space.end =
+	    PPC7D_PCI1_MEM0_START_PCI_LO_ADDR + PPC7D_PCI1_MEM0_SIZE;
+
+	pr_debug("MV64360: PCI#0 IO decode %08x/%08x IO remap %08x\n",
+		 mv64x60_read(&bh, 0x48), mv64x60_read(&bh, 0x50),
+		 mv64x60_read(&bh, 0xf0));
+}
+
+static void __init ppc7d_setup_arch(void)
+{
+	int port;
+
+	loops_per_jiffy = 100000000 / HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef	CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+
+	if ((cur_cpu_spec[0]->cpu_features & CPU_FTR_SPEC7450) ||
+	    (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR))
+		/* 745x is different.  We only want to pass along enable. */
+		_set_L2CR(L2CR_L2E);
+	else if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)
+		/* All modules have 1MB of L2.  We also assume that an
+		 * L2 divisor of 3 will work.
+		 */
+		_set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3
+			  | L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
+
+	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR)
+		/* No L3 cache */
+		_set_L3CR(0);
+
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+
+	/* Lookup PCI host bridges */
+	if (ppc_md.progress)
+		ppc_md.progress("ppc7d_setup_arch: calling setup_bridge", 0);
+
+	ppc7d_setup_bridge();
+	ppc7d_setup_peripherals();
+
+	/* Disable ethernet. It might have been setup by the bootrom */
+	for (port = 0; port < 3; port++)
+		mv64x60_write(&bh, MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port),
+			      0x0000ff00);
+
+	/* Clear queue pointers to ensure they are all initialized,
+	 * otherwise since queues 1-7 are unused, they have random
+	 * pointers which look strange in register dumps. Don't bother
+	 * with queue 0 since it will be initialized later.
+	 */
+	for (port = 0; port < 3; port++) {
+		mv64x60_write(&bh,
+			      MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port),
+			      0x00000000);
+		mv64x60_write(&bh,
+			      MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port),
+			      0x00000000);
+		mv64x60_write(&bh,
+			      MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port),
+			      0x00000000);
+		mv64x60_write(&bh,
+			      MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port),
+			      0x00000000);
+		mv64x60_write(&bh,
+			      MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port),
+			      0x00000000);
+		mv64x60_write(&bh,
+			      MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port),
+			      0x00000000);
+		mv64x60_write(&bh,
+			      MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port),
+			      0x00000000);
+	}
+
+	printk(KERN_INFO "Radstone Technology PPC7D\n");
+	if (ppc_md.progress)
+		ppc_md.progress("ppc7d_setup_arch: exit", 0);
+}
+
+/* This kernel command line parameter can be used to have the target
+ * wait for a JTAG debugger to attach. Of course, a JTAG debugger
+ * with hardware breakpoint support can have the target stop at any
+ * location during init, but this is a convenience feature that makes
+ * it easier in the common case of loading the code using the ppcboot
+ * bootloader..
+ */
+static unsigned long ppc7d_wait_debugger;
+
+static int __init ppc7d_waitdbg(char *str)
+{
+	ppc7d_wait_debugger = 1;
+	return 1;
+}
+
+__setup("waitdbg", ppc7d_waitdbg);
+
+/* Second phase board init, called after other (architecture common)
+ * low-level services have been initialized.
+ */
+static void ppc7d_init2(void)
+{
+	unsigned long flags;
+	u32 data;
+	u8 data8;
+
+	pr_debug("%s: enter\n", __FUNCTION__);
+
+	/* Wait for debugger? */
+	if (ppc7d_wait_debugger) {
+		printk("Waiting for debugger...\n");
+
+		while (readl(&ppc7d_wait_debugger)) ;
+	}
+
+	/* Hook up i8259 interrupt which is connected to GPP28 */
+	request_irq(mv64360_irq_base + MV64x60_IRQ_GPP28, ppc7d_i8259_intr,
+		    SA_INTERRUPT, "I8259 (GPP28) interrupt", (void *)0);
+
+	/* Configure MPP16 as watchdog NMI, MPP17 as watchdog WDE */
+	spin_lock_irqsave(&mv64x60_lock, flags);
+	data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2);
+	data &= ~(0x0000000f << 0);
+	data |= (0x00000004 << 0);
+	data &= ~(0x0000000f << 4);
+	data |= (0x00000004 << 4);
+	mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data);
+	spin_unlock_irqrestore(&mv64x60_lock, flags);
+
+	/* All LEDs off */
+	data8 = inb(PPC7D_CPLD_LEDS);
+	data8 &= ~0x08;
+	data8 |= 0x07;
+	outb(data8, PPC7D_CPLD_LEDS);
+
+	pr_debug("%s: exit\n", __FUNCTION__);
+}
+
+/* Called from machine_init(), early, before any of the __init functions
+ * have run. We must init software-configurable pins before other functions
+ * such as interrupt controllers are initialised.
+ */
+void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+			  unsigned long r6, unsigned long r7)
+{
+	u8 val8;
+	u8 rev_num;
+
+	/* Map 0xe0000000-0xffffffff early because we need access to SRAM
+	 * and the ISA memory space (for serial port) here. This mapping
+	 * is redone properly in ppc7d_map_io() later.
+	 */
+	mtspr(SPRN_DBAT3U, 0xe0003fff);
+	mtspr(SPRN_DBAT3L, 0xe000002a);
+
+	/*
+	 * Zero SRAM. Note that this generates parity errors on
+	 * internal data path in SRAM if it's first time accessing it
+	 * after reset.
+	 *
+	 * We do this ASAP to avoid parity errors when reading
+	 * uninitialized SRAM.
+	 */
+	memset((void *)PPC7D_INTERNAL_SRAM_BASE, 0, MV64360_SRAM_SIZE);
+
+	pr_debug("platform_init: r3-r7: %lx %lx %lx %lx %lx\n",
+		 r3, r4, r5, r6, r7);
+
+	parse_bootinfo(find_bootinfo());
+
+	/* ASSUMPTION:  If both r3 (bd_t pointer) and r6 (cmdline pointer)
+	 * are non-zero, then we should use the board info from the bd_t
+	 * structure and the cmdline pointed to by r6 instead of the
+	 * information from birecs, if any.  Otherwise, use the information
+	 * from birecs as discovered by the preceeding call to
+	 * parse_bootinfo().  This rule should work with both PPCBoot, which
+	 * uses a bd_t board info structure, and the kernel boot wrapper,
+	 * which uses birecs.
+	 */
+	if (r3 && r6) {
+		bd_t *bp = (bd_t *) __res;
+
+		/* copy board info structure */
+		memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
+		/* copy command line */
+		*(char *)(r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *)(r6 + KERNELBASE));
+
+		printk(KERN_INFO "Board info data:-\n");
+		printk(KERN_INFO "  Internal freq: %lu MHz, bus freq: %lu MHz\n",
+		       bp->bi_intfreq, bp->bi_busfreq);
+		printk(KERN_INFO "  Memory: %lx, size %lx\n", bp->bi_memstart,
+		       bp->bi_memsize);
+		printk(KERN_INFO "  Console baudrate: %lu\n", bp->bi_baudrate);
+		printk(KERN_INFO "  Ethernet address: "
+		       "%02x:%02x:%02x:%02x:%02x:%02x\n",
+		       bp->bi_enetaddr[0], bp->bi_enetaddr[1],
+		       bp->bi_enetaddr[2], bp->bi_enetaddr[3],
+		       bp->bi_enetaddr[4], bp->bi_enetaddr[5]);
+	}
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* take care of initrd if we have one */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+		printk(KERN_INFO "INITRD @ %lx/%lx\n", initrd_start, initrd_end);
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	/* Map in board regs, etc. */
+	isa_io_base = 0xe8000000;
+	isa_mem_base = 0xe8000000;
+	pci_dram_offset = 0x00000000;
+	ISA_DMA_THRESHOLD = 0x00ffffff;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+
+	ppc_md.setup_arch = ppc7d_setup_arch;
+	ppc_md.init = ppc7d_init2;
+	ppc_md.show_cpuinfo = ppc7d_show_cpuinfo;
+	ppc_md.irq_canonicalize = ppc7d_irq_canonicalize;
+	ppc_md.init_IRQ = ppc7d_init_irq;
+	ppc_md.get_irq = ppc7d_get_irq;
+
+	ppc_md.restart = ppc7d_restart;
+	ppc_md.power_off = ppc7d_power_off;
+	ppc_md.halt = ppc7d_halt;
+
+	ppc_md.find_end_of_memory = ppc7d_find_end_of_memory;
+	ppc_md.setup_io_mappings = ppc7d_map_io;
+
+	ppc_md.time_init = NULL;
+	ppc_md.set_rtc_time = NULL;
+	ppc_md.get_rtc_time = NULL;
+	ppc_md.calibrate_decr = ppc7d_calibrate_decr;
+	ppc_md.nvram_read_val = NULL;
+	ppc_md.nvram_write_val = NULL;
+
+	ppc_md.heartbeat = ppc7d_heartbeat;
+	ppc_md.heartbeat_reset = HZ;
+	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+
+	ppc_md.pcibios_fixup_bus = ppc7d_pci_fixup_bus;
+
+#if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH) || \
+    defined(CONFIG_I2C_MV64XXX)
+	platform_notify = ppc7d_platform_notify;
+#endif
+
+#ifdef CONFIG_SERIAL_MPSC
+	/* On PPC7D, we must configure MPSC support via CPLD control
+	 * registers.
+	 */
+	outb(PPC7D_CPLD_RTS_COM4_SCLK |
+	     PPC7D_CPLD_RTS_COM56_ENABLED, PPC7D_CPLD_RTS);
+	outb(PPC7D_CPLD_COMS_COM3_TCLKEN |
+	     PPC7D_CPLD_COMS_COM3_TXEN |
+	     PPC7D_CPLD_COMS_COM4_TCLKEN |
+	     PPC7D_CPLD_COMS_COM4_TXEN, PPC7D_CPLD_COMS);
+#endif /* CONFIG_SERIAL_MPSC */
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+	ppc7d_early_serial_map();
+#ifdef  CONFIG_SERIAL_TEXT_DEBUG
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+	ppc_md.progress = mv64x60_mpsc_progress;
+#elif defined(CONFIG_SERIAL_8250)
+	ppc_md.progress = gen550_progress;
+#else
+#error CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
+#endif /* CONFIG_SERIAL_8250 */
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+#endif /* CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG */
+
+	/* Enable write access to user flash.  This is necessary for
+	 * flash probe.
+	 */
+	val8 = readb((void *)isa_io_base + PPC7D_CPLD_SW_FLASH_WRITE_PROTECT);
+	writeb(val8 | (PPC7D_CPLD_SW_FLASH_WRPROT_ENABLED &
+		       PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK),
+	       (void *)isa_io_base + PPC7D_CPLD_SW_FLASH_WRITE_PROTECT);
+
+	/* Determine if this board has IBM ALMA VME devices */
+	val8 = readb((void *)isa_io_base + PPC7D_CPLD_BOARD_REVISION);
+	rev_num = (val8 & PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK) >> 5;
+	if (rev_num <= 1)
+		ppc7d_has_alma = 1;
+
+#ifdef DEBUG
+	console_printk[0] = 8;
+#endif
+}
diff --git a/arch/ppc/platforms/radstone_ppc7d.h b/arch/ppc/platforms/radstone_ppc7d.h
new file mode 100644
index 0000000..4546fff2
--- /dev/null
+++ b/arch/ppc/platforms/radstone_ppc7d.h
@@ -0,0 +1,434 @@
+/*
+ * arch/ppc/platforms/radstone_ppc7d.h
+ *
+ * Board definitions for the Radstone PPC7D boards.
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by - Mark A. Greer <mgreer@mvista.com>
+ *
+ * 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.
+ */
+
+/*
+ * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to
+ * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
+ * We'll only use one PCI MEM window on each PCI bus.
+ *
+ * This is the CPU physical memory map (windows must be at least 1MB
+ * and start on a boundary that is a multiple of the window size):
+ *
+ *    0xff800000-0xffffffff      - Boot window
+ *    0xff000000-0xff000fff	 - AFIX registers (DevCS2)
+ *    0xfef00000-0xfef0ffff      - Internal MV64x60 registers
+ *    0xfef40000-0xfef7ffff      - Internal SRAM
+ *    0xfef00000-0xfef0ffff      - MV64360 Registers
+ *    0x70000000-0x7fffffff      - soldered flash (DevCS3)
+ *    0xe8000000-0xe9ffffff      - PCI I/O
+ *    0x80000000-0xbfffffff      - PCI MEM
+ */
+
+#ifndef __PPC_PLATFORMS_PPC7D_H
+#define __PPC_PLATFORMS_PPC7D_H
+
+#include <asm/ppcboot.h>
+
+/*****************************************************************************
+ * CPU Physical Memory Map setup.
+ *****************************************************************************/
+
+#define PPC7D_BOOT_WINDOW_BASE			0xff800000
+#define PPC7D_AFIX_REG_BASE			0xff000000
+#define PPC7D_INTERNAL_SRAM_BASE		0xfef40000
+#define PPC7D_FLASH_BASE			0x70000000
+
+#define PPC7D_BOOT_WINDOW_SIZE_ACTUAL		0x00800000 /* 8MB */
+#define PPC7D_FLASH_SIZE_ACTUAL			0x10000000 /* 256MB */
+
+#define PPC7D_BOOT_WINDOW_SIZE		max(MV64360_WINDOW_SIZE_MIN,	\
+		PPC7D_BOOT_WINDOW_SIZE_ACTUAL)
+#define PPC7D_FLASH_SIZE		max(MV64360_WINDOW_SIZE_MIN,	\
+		PPC7D_FLASH_SIZE_ACTUAL)
+#define PPC7D_AFIX_REG_SIZE		max(MV64360_WINDOW_SIZE_MIN, 0xff)
+
+
+#define PPC7D_PCI0_MEM0_START_PROC_ADDR        0x80000000UL
+#define PPC7D_PCI0_MEM0_START_PCI_HI_ADDR      0x00000000UL
+#define PPC7D_PCI0_MEM0_START_PCI_LO_ADDR      0x80000000UL
+#define PPC7D_PCI0_MEM0_SIZE                   0x20000000UL
+#define PPC7D_PCI0_MEM1_START_PROC_ADDR        0xe8010000UL
+#define PPC7D_PCI0_MEM1_START_PCI_HI_ADDR      0x00000000UL
+#define PPC7D_PCI0_MEM1_START_PCI_LO_ADDR      0x00000000UL
+#define PPC7D_PCI0_MEM1_SIZE                   0x000f0000UL
+#define PPC7D_PCI0_IO_START_PROC_ADDR          0xe8000000UL
+#define PPC7D_PCI0_IO_START_PCI_ADDR           0x00000000UL
+#define PPC7D_PCI0_IO_SIZE                     0x00010000UL
+
+#define PPC7D_PCI1_MEM0_START_PROC_ADDR        0xa0000000UL
+#define PPC7D_PCI1_MEM0_START_PCI_HI_ADDR      0x00000000UL
+#define PPC7D_PCI1_MEM0_START_PCI_LO_ADDR      0xa0000000UL
+#define PPC7D_PCI1_MEM0_SIZE                   0x20000000UL
+#define PPC7D_PCI1_MEM1_START_PROC_ADDR        0xe9800000UL
+#define PPC7D_PCI1_MEM1_START_PCI_HI_ADDR      0x00000000UL
+#define PPC7D_PCI1_MEM1_START_PCI_LO_ADDR      0x00000000UL
+#define PPC7D_PCI1_MEM1_SIZE                   0x00800000UL
+#define PPC7D_PCI1_IO_START_PROC_ADDR          0xe9000000UL
+#define PPC7D_PCI1_IO_START_PCI_ADDR           0x00000000UL
+#define PPC7D_PCI1_IO_SIZE                     0x00010000UL
+
+#define	PPC7D_DEFAULT_BAUD			9600
+#define	PPC7D_MPSC_CLK_SRC			8	  /* TCLK */
+#define	PPC7D_MPSC_CLK_FREQ			133333333 /* 133.3333... MHz */
+
+#define	PPC7D_ETH0_PHY_ADDR			8
+#define	PPC7D_ETH1_PHY_ADDR			9
+#define	PPC7D_ETH2_PHY_ADDR			0
+
+#define PPC7D_ETH_TX_QUEUE_SIZE			400
+#define PPC7D_ETH_RX_QUEUE_SIZE			400
+
+#define	PPC7D_ETH_PORT_CONFIG_VALUE			\
+	MV64340_ETH_UNICAST_NORMAL_MODE			|	\
+	MV64340_ETH_DEFAULT_RX_QUEUE_0			|	\
+	MV64340_ETH_DEFAULT_RX_ARP_QUEUE_0		|	\
+	MV64340_ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP		|	\
+	MV64340_ETH_RECEIVE_BC_IF_IP			|	\
+	MV64340_ETH_RECEIVE_BC_IF_ARP			|	\
+	MV64340_ETH_CAPTURE_TCP_FRAMES_DIS		|	\
+	MV64340_ETH_CAPTURE_UDP_FRAMES_DIS		|	\
+	MV64340_ETH_DEFAULT_RX_TCP_QUEUE_0		|	\
+	MV64340_ETH_DEFAULT_RX_UDP_QUEUE_0		|	\
+	MV64340_ETH_DEFAULT_RX_BPDU_QUEUE_0
+
+#define	PPC7D_ETH_PORT_CONFIG_EXTEND_VALUE		\
+	MV64340_ETH_SPAN_BPDU_PACKETS_AS_NORMAL		|	\
+	MV64340_ETH_PARTITION_DISABLE
+
+#define	GT_ETH_IPG_INT_RX(value)			\
+	((value & 0x3fff) << 8)
+
+#define	PPC7D_ETH_PORT_SDMA_CONFIG_VALUE		\
+	MV64340_ETH_RX_BURST_SIZE_4_64BIT		|	\
+	GT_ETH_IPG_INT_RX(0)			|	\
+	MV64340_ETH_TX_BURST_SIZE_4_64BIT
+
+#define	PPC7D_ETH_PORT_SERIAL_CONTROL_VALUE		\
+	MV64340_ETH_ENABLE_AUTO_NEG_FOR_DUPLX		|	\
+	MV64340_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL	|	\
+	MV64340_ETH_ADV_SYMMETRIC_FLOW_CTRL		|	\
+	MV64340_ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX	|	\
+	MV64340_ETH_FORCE_BP_MODE_NO_JAM		|	\
+	(1 << 9)					|	\
+	MV64340_ETH_DO_NOT_FORCE_LINK_FAIL		|	\
+	MV64340_ETH_RETRANSMIT_16_ATTEMPTS		|	\
+	MV64340_ETH_ENABLE_AUTO_NEG_SPEED_GMII		|	\
+	MV64340_ETH_DTE_ADV_0				|	\
+	MV64340_ETH_DISABLE_AUTO_NEG_BYPASS		|	\
+	MV64340_ETH_AUTO_NEG_NO_CHANGE			|	\
+	MV64340_ETH_MAX_RX_PACKET_9700BYTE		|	\
+	MV64340_ETH_CLR_EXT_LOOPBACK			|	\
+	MV64340_ETH_SET_FULL_DUPLEX_MODE		|	\
+	MV64340_ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
+
+/*****************************************************************************
+ * Serial defines.
+ *****************************************************************************/
+
+#define PPC7D_SERIAL_0		0xe80003f8
+#define PPC7D_SERIAL_1		0xe80002f8
+
+#define RS_TABLE_SIZE  2
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define UART_CLK			1843200
+#define BASE_BAUD			( UART_CLK / 16 )
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, PPC7D_SERIAL_0, 4, STD_COM_FLAGS, /* ttyS0 */ \
+		iomem_base: (u8 *)PPC7D_SERIAL_0,			  \
+		io_type: SERIAL_IO_MEM, },				  \
+        { 0, BASE_BAUD, PPC7D_SERIAL_1, 3, STD_COM_FLAGS, /* ttyS1 */ \
+		iomem_base: (u8 *)PPC7D_SERIAL_1,			  \
+		io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
+
+/*****************************************************************************
+ * CPLD defines.
+ *
+ * Register map:-
+ *
+ * 0000 to 000F 	South Bridge DMA 1 Control
+ * 0020 and 0021 	South Bridge Interrupt 1 Control
+ * 0040 to 0043 	South Bridge Counter Control
+ * 0060 		Keyboard
+ * 0061 		South Bridge NMI Status and Control
+ * 0064 		Keyboard
+ * 0071 and 0072 	RTC R/W
+ * 0078 to 007B 	South Bridge BIOS Timer
+ * 0080 to 0090 	South Bridge DMA Pages
+ * 00A0 and 00A1 	South Bridge Interrupt 2 Control
+ * 00C0 to 00DE 	South Bridge DMA 2 Control
+ * 02E8 to 02EF 	COM6 R/W
+ * 02F8 to 02FF 	South Bridge COM2 R/W
+ * 03E8 to 03EF 	COM5 R/W
+ * 03F8 to 03FF 	South Bridge COM1 R/W
+ * 040A 		South Bridge DMA Scatter/Gather RO
+ * 040B 		DMA 1 Extended Mode WO
+ * 0410 to 043F 	South Bridge DMA Scatter/Gather
+ * 0481 to 048B 	South Bridge DMA High Pages
+ * 04D0 and 04D1 	South Bridge Edge/Level Control
+ * 04D6 		DMA 2 Extended Mode WO
+ * 0804 		Memory Configuration RO
+ * 0806 		Memory Configuration Extend RO
+ * 0808 		SCSI Activity LED R/W
+ * 080C 		Equipment Present 1 RO
+ * 080E 		Equipment Present 2 RO
+ * 0810 		Equipment Present 3 RO
+ * 0812 		Equipment Present 4 RO
+ * 0818 		Key Lock RO
+ * 0820 		LEDS R/W
+ * 0824 		COMs R/W
+ * 0826 		RTS R/W
+ * 0828 		Reset R/W
+ * 082C 		Watchdog Trig R/W
+ * 082E 		Interrupt R/W
+ * 0830 		Interrupt Status RO
+ * 0832 		PCI configuration RO
+ * 0854 		Board Revision RO
+ * 0858 		Extended ID RO
+ * 0864 		ID Link RO
+ * 0866 		Motherboard Type RO
+ * 0868 		FLASH Write control RO
+ * 086A 		Software FLASH write protect R/W
+ * 086E 		FLASH Control R/W
+ *****************************************************************************/
+
+#define PPC7D_CPLD_MEM_CONFIG			0x0804
+#define PPC7D_CPLD_MEM_CONFIG_EXTEND		0x0806
+#define PPC7D_CPLD_SCSI_ACTIVITY_LED		0x0808
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_1		0x080C
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_2		0x080E
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_3		0x0810
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_4		0x0812
+#define PPC7D_CPLD_KEY_LOCK			0x0818
+#define PPC7D_CPLD_LEDS				0x0820
+#define PPC7D_CPLD_COMS				0x0824
+#define PPC7D_CPLD_RTS				0x0826
+#define PPC7D_CPLD_RESET			0x0828
+#define PPC7D_CPLD_WATCHDOG_TRIG		0x082C
+#define PPC7D_CPLD_INTR				0x082E
+#define PPC7D_CPLD_INTR_STATUS			0x0830
+#define PPC7D_CPLD_PCI_CONFIG			0x0832
+#define PPC7D_CPLD_BOARD_REVISION		0x0854
+#define PPC7D_CPLD_EXTENDED_ID			0x0858
+#define PPC7D_CPLD_ID_LINK			0x0864
+#define PPC7D_CPLD_MOTHERBOARD_TYPE		0x0866
+#define PPC7D_CPLD_FLASH_WRITE_CNTL		0x0868
+#define PPC7D_CPLD_SW_FLASH_WRITE_PROTECT	0x086A
+#define PPC7D_CPLD_FLASH_CNTL			0x086E
+
+/* MEMORY_CONFIG_EXTEND */
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_MASK		0xc0
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_128M		0
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_256M		0x40
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_512M		0x80
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_1G		0xc0
+#define PPC7D_CPLD_FLASH_DEV_SIZE_MASK		0x03
+#define PPC7D_CPLD_FLASH_BANK_NUM_MASK		0x0c
+#define PPC7D_CPLD_FLASH_DEV_SIZE_64M		0
+#define PPC7D_CPLD_FLASH_DEV_SIZE_32M		1
+#define PPC7D_CPLD_FLASH_DEV_SIZE_16M		3
+#define PPC7D_CPLD_FLASH_BANK_NUM_4		0x00
+#define PPC7D_CPLD_FLASH_BANK_NUM_3		0x04
+#define PPC7D_CPLD_FLASH_BANK_NUM_2		0x08
+#define PPC7D_CPLD_FLASH_BANK_NUM_1		0x0c
+
+/* SCSI_LED */
+#define PPC7D_CPLD_SCSI_ACTIVITY_LED_OFF	0
+#define PPC7D_CPLD_SCSI_ACTIVITY_LED_ON		1
+
+/* EQUIPMENT_PRESENT_1 */
+#define PPC7D_CPLD_EQPT_PRES_1_FITTED		0
+#define PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK	(0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK	(0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK	(0x80 >> 4)
+
+/* EQUIPMENT_PRESENT_2 */
+#define PPC7D_CPLD_EQPT_PRES_2_FITTED		!0
+#define PPC7D_CPLD_EQPT_PRES_2_UNIVERSE_MASK	(0x80 >> 0)
+#define PPC7D_CPLD_EQPT_PRES_2_COM36_MASK	(0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_2_GIGE_MASK	(0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_2_DUALGIGE_MASK	(0x80 >> 4)
+
+/* EQUIPMENT_PRESENT_3 */
+#define PPC7D_CPLD_EQPT_PRES_3_PMC2_V_MASK	(0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC2_5V		(0 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC2_3V		(0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC1_V_MASK	(0x80 >> 4)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC1_5V		(0 >> 4)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC1_3V		(0x80 >> 4)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_MASK	(0x80 >> 5)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_INTER	(0 >> 5)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_VME	(0x80 >> 5)
+
+/* EQUIPMENT_PRESENT_4 */
+#define PPC7D_CPLD_EQPT_PRES_4_LPT_MASK		(0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_4_LPT_FITTED	(0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_4_PS2_USB2_MASK	(0xc0 >> 6)
+#define PPC7D_CPLD_EQPT_PRES_4_PS2_FITTED	(0x40 >> 6)
+#define PPC7D_CPLD_EQPT_PRES_4_USB2_FITTED	(0x80 >> 6)
+
+/* CPLD_LEDS */
+#define PPC7D_CPLD_LEDS_ON			(!0)
+#define PPC7D_CPLD_LEDS_OFF			(0)
+#define PPC7D_CPLD_LEDS_NVRAM_PAGE_MASK		(0xc0 >> 2)
+#define PPC7D_CPLD_LEDS_DS201_MASK		(0x80 >> 4)
+#define PPC7D_CPLD_LEDS_DS219_MASK		(0x80 >> 5)
+#define PPC7D_CPLD_LEDS_DS220_MASK		(0x80 >> 6)
+#define PPC7D_CPLD_LEDS_DS221_MASK		(0x80 >> 7)
+
+/* CPLD_COMS */
+#define PPC7D_CPLD_COMS_COM3_TCLKEN		(0x80 >> 0)
+#define PPC7D_CPLD_COMS_COM3_RTCLKEN		(0x80 >> 1)
+#define PPC7D_CPLD_COMS_COM3_MODE_MASK		(0x80 >> 2)
+#define PPC7D_CPLD_COMS_COM3_MODE_RS232		(0)
+#define PPC7D_CPLD_COMS_COM3_MODE_RS422		(0x80 >> 2)
+#define PPC7D_CPLD_COMS_COM3_TXEN		(0x80 >> 3)
+#define PPC7D_CPLD_COMS_COM4_TCLKEN		(0x80 >> 4)
+#define PPC7D_CPLD_COMS_COM4_RTCLKEN		(0x80 >> 5)
+#define PPC7D_CPLD_COMS_COM4_MODE_MASK		(0x80 >> 6)
+#define PPC7D_CPLD_COMS_COM4_MODE_RS232		(0)
+#define PPC7D_CPLD_COMS_COM4_MODE_RS422		(0x80 >> 6)
+#define PPC7D_CPLD_COMS_COM4_TXEN		(0x80 >> 7)
+
+/* CPLD_RTS */
+#define PPC7D_CPLD_RTS_COM36_LOOPBACK		(0x80 >> 0)
+#define PPC7D_CPLD_RTS_COM4_SCLK		(0x80 >> 1)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_MASK		(0xc0 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_DISABLED	(0 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED	(0x80 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED_RTG3	(0xc0 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED_RTG3S (0xc0 >> 2)
+#define PPC7D_CPLD_RTS_COM56_MODE_MASK		(0x80 >> 4)
+#define PPC7D_CPLD_RTS_COM56_MODE_RS232		(0)
+#define PPC7D_CPLD_RTS_COM56_MODE_RS422		(0x80 >> 4)
+#define PPC7D_CPLD_RTS_COM56_ENABLE_MASK	(0x80 >> 5)
+#define PPC7D_CPLD_RTS_COM56_DISABLED		(0)
+#define PPC7D_CPLD_RTS_COM56_ENABLED		(0x80 >> 5)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_MASK		(0xc0 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_DISABLED	(0 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED	(0x80 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED_RTG3	(0x40 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED_RTG3S (0x40 >> 6)
+
+/* WATCHDOG_TRIG */
+#define PPC7D_CPLD_WDOG_CAUSE_MASK		(0x80 >> 0)
+#define PPC7D_CPLD_WDOG_CAUSE_NORMAL_RESET	(0 >> 0)
+#define PPC7D_CPLD_WDOG_CAUSE_WATCHDOG		(0x80 >> 0)
+#define PPC7D_CPLD_WDOG_ENABLE_MASK		(0x80 >> 6)
+#define PPC7D_CPLD_WDOG_ENABLE_OFF		(0 >> 6)
+#define PPC7D_CPLD_WDOG_ENABLE_ON		(0x80 >> 6)
+#define PPC7D_CPLD_WDOG_RESETSW_MASK		(0x80 >> 7)
+#define PPC7D_CPLD_WDOG_RESETSW_OFF		(0 >> 7)
+#define PPC7D_CPLD_WDOG_RESETSW_ON		(0x80 >> 7)
+
+/* Interrupt mask and status bits */
+#define PPC7D_CPLD_INTR_TEMP_MASK		(0x80 >> 0)
+#define PPC7D_CPLD_INTR_HB8_MASK		(0x80 >> 1)
+#define PPC7D_CPLD_INTR_PHY1_MASK		(0x80 >> 2)
+#define PPC7D_CPLD_INTR_PHY0_MASK		(0x80 >> 3)
+#define PPC7D_CPLD_INTR_ISANMI_MASK		(0x80 >> 5)
+#define PPC7D_CPLD_INTR_CRITTEMP_MASK		(0x80 >> 6)
+
+/* CPLD_INTR */
+#define PPC7D_CPLD_INTR_ENABLE_OFF		(0)
+#define PPC7D_CPLD_INTR_ENABLE_ON		(!0)
+
+/* CPLD_INTR_STATUS */
+#define PPC7D_CPLD_INTR_STATUS_OFF		(0)
+#define PPC7D_CPLD_INTR_STATUS_ON		(!0)
+
+/* CPLD_PCI_CONFIG */
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_MASK		0x70
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCI33	0x00
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCI66	0x10
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX33	0x40
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX66	0x50
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX100      0x60
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX133	0x70
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_MASK		0x07
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCI33	0x00
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCI66	0x01
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX33	0x04
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX66	0x05
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX100	0x06
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX133	0x07
+
+/* CPLD_BOARD_REVISION */
+#define PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK	0xe0
+#define PPC7D_CPLD_BOARD_REVISION_LETTER_MASK	0x1f
+
+/* CPLD_EXTENDED_ID */
+#define PPC7D_CPLD_EXTENDED_ID_PPC7D		0x18
+
+/* CPLD_ID_LINK */
+#define PPC7D_CPLD_ID_LINK_VME64_GAP_MASK	(0x80 >> 2)
+#define PPC7D_CPLD_ID_LINK_VME64_GA4_MASK	(0x80 >> 3)
+#define PPC7D_CPLD_ID_LINK_E13_MASK		(0x80 >> 4)
+#define PPC7D_CPLD_ID_LINK_E12_MASK		(0x80 >> 5)
+#define PPC7D_CPLD_ID_LINK_E7_MASK		(0x80 >> 6)
+#define PPC7D_CPLD_ID_LINK_E6_MASK		(0x80 >> 7)
+
+/* CPLD_MOTHERBOARD_TYPE */
+#define PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK	(0x80 >> 0)
+#define PPC7D_CPLD_MB_TYPE_ECC_ENABLED		(0x80 >> 0)
+#define PPC7D_CPLD_MB_TYPE_ECC_DISABLED		(0 >> 0)
+#define PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK	(0x80 >> 3)
+#define PPC7D_CPLD_MB_TYPE_PLL_MASK		0x0c
+#define PPC7D_CPLD_MB_TYPE_PLL_133		0x00
+#define PPC7D_CPLD_MB_TYPE_PLL_100		0x08
+#define PPC7D_CPLD_MB_TYPE_PLL_64		0x04
+#define PPC7D_CPLD_MB_TYPE_HW_ID_MASK		0x03
+
+/* CPLD_FLASH_WRITE_CNTL */
+#define PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK	(0x80 >> 0)
+#define PPD7D_CPLD_FLASH_CNTL_WR_LINK_FITTED	(0x80 >> 0)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK	(0x80 >> 2)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_FITTED	(0x80 >> 2)
+#define PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK	(0x80 >> 3)
+#define PPD7D_CPLD_FLASH_CNTL_USER_LINK_FITTED	(0x80 >> 3)
+#define PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK	(0x80 >> 5)
+#define PPD7D_CPLD_FLASH_CNTL_RECO_WR_ENABLED	(0x80 >> 5)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK	(0x80 >> 6)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_WR_ENABLED	(0x80 >> 6)
+#define PPD7D_CPLD_FLASH_CNTL_USER_WR_MASK	(0x80 >> 7)
+#define PPD7D_CPLD_FLASH_CNTL_USER_WR_ENABLED	(0x80 >> 7)
+
+/* CPLD_SW_FLASH_WRITE_PROTECT */
+#define PPC7D_CPLD_SW_FLASH_WRPROT_ENABLED	(!0)
+#define PPC7D_CPLD_SW_FLASH_WRPROT_DISABLED	(0)
+#define PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK	(0x80 >> 6)
+#define PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK	(0x80 >> 7)
+
+/* CPLD_FLASH_WRITE_CNTL */
+#define PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK	(0x80 >> 0)
+#define PPC7D_CPLD_FLASH_CNTL_NVRAM_DISABLED	(0 >> 0)
+#define PPC7D_CPLD_FLASH_CNTL_NVRAM_ENABLED	(0x80 >> 0)
+#define PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK	(0x80 >> 1)
+#define PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK	(0x80 >> 2)
+#define PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK	(0x80 >> 3)
+
+
+#endif /* __PPC_PLATFORMS_PPC7D_H */
diff --git a/arch/ppc/platforms/residual.c b/arch/ppc/platforms/residual.c
new file mode 100644
index 0000000..0f84ca6
--- /dev/null
+++ b/arch/ppc/platforms/residual.c
@@ -0,0 +1,1034 @@
+/*
+ * Code to deal with the PReP residual data.
+ *
+ * Written by: Cort Dougan (cort@cs.nmt.edu)
+ * Improved _greatly_ and rewritten by Gabriel Paubert (paubert@iram.es)
+ *
+ *  This file is based on the following documentation:
+ *
+ *	IBM Power Personal Systems Architecture
+ *	Residual Data
+ * 	Document Number: PPS-AR-FW0001
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ *
+ */
+
+#include <linux/string.h>
+#include <asm/residual.h>
+#include <asm/pnp.h>
+#include <asm/byteorder.h>
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/sections.h>
+#include <asm/mmu.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/ide.h>
+
+
+unsigned char __res[sizeof(RESIDUAL)] __prepdata = {0,};
+RESIDUAL *res = (RESIDUAL *)&__res;
+
+char * PnP_BASE_TYPES[] __initdata = {
+  "Reserved",
+  "MassStorageDevice",
+  "NetworkInterfaceController",
+  "DisplayController",
+  "MultimediaController",
+  "MemoryController",
+  "BridgeController",
+  "CommunicationsDevice",
+  "SystemPeripheral",
+  "InputDevice",
+  "ServiceProcessor"
+  };
+
+/* Device Sub Type Codes */
+
+unsigned char * PnP_SUB_TYPES[] __initdata = {
+  "\001\000SCSIController",
+  "\001\001IDEController",
+  "\001\002FloppyController",
+  "\001\003IPIController",
+  "\001\200OtherMassStorageController",
+  "\002\000EthernetController",
+  "\002\001TokenRingController",
+  "\002\002FDDIController",
+  "\002\0x80OtherNetworkController",
+  "\003\000VGAController",
+  "\003\001SVGAController",
+  "\003\002XGAController",
+  "\003\200OtherDisplayController",
+  "\004\000VideoController",
+  "\004\001AudioController",
+  "\004\200OtherMultimediaController",
+  "\005\000RAM",
+  "\005\001FLASH",
+  "\005\200OtherMemoryDevice",
+  "\006\000HostProcessorBridge",
+  "\006\001ISABridge",
+  "\006\002EISABridge",
+  "\006\003MicroChannelBridge",
+  "\006\004PCIBridge",
+  "\006\005PCMCIABridge",
+  "\006\006VMEBridge",
+  "\006\200OtherBridgeDevice",
+  "\007\000RS232Device",
+  "\007\001ATCompatibleParallelPort",
+  "\007\200OtherCommunicationsDevice",
+  "\010\000ProgrammableInterruptController",
+  "\010\001DMAController",
+  "\010\002SystemTimer",
+  "\010\003RealTimeClock",
+  "\010\004L2Cache",
+  "\010\005NVRAM",
+  "\010\006PowerManagement",
+  "\010\007CMOS",
+  "\010\010OperatorPanel",
+  "\010\011ServiceProcessorClass1",
+  "\010\012ServiceProcessorClass2",
+  "\010\013ServiceProcessorClass3",
+  "\010\014GraphicAssist",
+  "\010\017SystemPlanar",
+  "\010\200OtherSystemPeripheral",
+  "\011\000KeyboardController",
+  "\011\001Digitizer",
+  "\011\002MouseController",
+  "\011\003TabletController",
+  "\011\0x80OtherInputController",
+  "\012\000GeneralMemoryController",
+  NULL
+};
+
+/* Device Interface Type Codes */
+
+unsigned char * PnP_INTERFACES[] __initdata = {
+  "\000\000\000General",
+  "\001\000\000GeneralSCSI",
+  "\001\001\000GeneralIDE",
+  "\001\001\001ATACompatible",
+
+  "\001\002\000GeneralFloppy",
+  "\001\002\001Compatible765",
+  "\001\002\002NS398_Floppy",         /* NS Super I/O wired to use index
+                                         register at port 398 and data
+                                         register at port 399               */
+  "\001\002\003NS26E_Floppy",         /* Ports 26E and 26F                  */
+  "\001\002\004NS15C_Floppy",         /* Ports 15C and 15D                  */
+  "\001\002\005NS2E_Floppy",          /* Ports 2E and 2F                    */
+  "\001\002\006CHRP_Floppy",          /* CHRP Floppy in PR*P system         */
+
+  "\001\003\000GeneralIPI",
+
+  "\002\000\000GeneralEther",
+  "\002\001\000GeneralToken",
+  "\002\002\000GeneralFDDI",
+
+  "\003\000\000GeneralVGA",
+  "\003\001\000GeneralSVGA",
+  "\003\002\000GeneralXGA",
+
+  "\004\000\000GeneralVideo",
+  "\004\001\000GeneralAudio",
+  "\004\001\001CS4232Audio",            /* CS 4232 Plug 'n Play Configured    */
+
+  "\005\000\000GeneralRAM",
+  /* This one is obviously wrong ! */
+  "\005\000\000PCIMemoryController",    /* PCI Config Method                  */
+  "\005\000\001RS6KMemoryController",   /* RS6K Config Method                 */
+  "\005\001\000GeneralFLASH",
+
+  "\006\000\000GeneralHostBridge",
+  "\006\001\000GeneralISABridge",
+  "\006\002\000GeneralEISABridge",
+  "\006\003\000GeneralMCABridge",
+  /* GeneralPCIBridge = 0, */
+  "\006\004\000PCIBridgeDirect",
+  "\006\004\001PCIBridgeIndirect",
+  "\006\004\002PCIBridgeRS6K",
+  "\006\005\000GeneralPCMCIABridge",
+  "\006\006\000GeneralVMEBridge",
+
+  "\007\000\000GeneralRS232",
+  "\007\000\001COMx",
+  "\007\000\002Compatible16450",
+  "\007\000\003Compatible16550",
+  "\007\000\004NS398SerPort",         /* NS Super I/O wired to use index
+                                         register at port 398 and data
+                                         register at port 399               */
+  "\007\000\005NS26ESerPort",         /* Ports 26E and 26F                  */
+  "\007\000\006NS15CSerPort",         /* Ports 15C and 15D                  */
+  "\007\000\007NS2ESerPort",          /* Ports 2E and 2F                    */
+
+  "\007\001\000GeneralParPort",
+  "\007\001\001LPTx",
+  "\007\001\002NS398ParPort",         /* NS Super I/O wired to use index
+                                         register at port 398 and data
+                                         register at port 399               */
+  "\007\001\003NS26EParPort",         /* Ports 26E and 26F                  */
+  "\007\001\004NS15CParPort",         /* Ports 15C and 15D                  */
+  "\007\001\005NS2EParPort",          /* Ports 2E and 2F                    */
+
+  "\010\000\000GeneralPIC",
+  "\010\000\001ISA_PIC",
+  "\010\000\002EISA_PIC",
+  "\010\000\003MPIC",
+  "\010\000\004RS6K_PIC",
+
+  "\010\001\000GeneralDMA",
+  "\010\001\001ISA_DMA",
+  "\010\001\002EISA_DMA",
+
+  "\010\002\000GeneralTimer",
+  "\010\002\001ISA_Timer",
+  "\010\002\002EISA_Timer",
+  "\010\003\000GeneralRTC",
+  "\010\003\001ISA_RTC",
+
+  "\010\004\001StoreThruOnly",
+  "\010\004\002StoreInEnabled",
+  "\010\004\003RS6KL2Cache",
+
+  "\010\005\000IndirectNVRAM",        /* Indirectly addressed               */
+  "\010\005\001DirectNVRAM",          /* Memory Mapped                      */
+  "\010\005\002IndirectNVRAM24",      /* Indirectly addressed - 24 bit      */
+
+  "\010\006\000GeneralPowerManagement",
+  "\010\006\001EPOWPowerManagement",
+  "\010\006\002PowerControl",         // d1378
+
+  "\010\007\000GeneralCMOS",
+
+  "\010\010\000GeneralOPPanel",
+  "\010\010\001HarddiskLight",
+  "\010\010\002CDROMLight",
+  "\010\010\003PowerLight",
+  "\010\010\004KeyLock",
+  "\010\010\005ANDisplay",            /* AlphaNumeric Display               */
+  "\010\010\006SystemStatusLED",      /* 3 digit 7 segment LED              */
+  "\010\010\007CHRP_SystemStatusLED", /* CHRP LEDs in PR*P system           */
+
+  "\010\011\000GeneralServiceProcessor",
+  "\010\012\000GeneralServiceProcessor",
+  "\010\013\000GeneralServiceProcessor",
+
+  "\010\014\001TransferData",
+  "\010\014\002IGMC32",
+  "\010\014\003IGMC64",
+
+  "\010\017\000GeneralSystemPlanar",   /* 10/5/95                            */
+  NULL
+  };
+
+static const unsigned char __init *PnP_SUB_TYPE_STR(unsigned char BaseType,
+					     unsigned char SubType) {
+	unsigned char ** s=PnP_SUB_TYPES;
+	while (*s && !((*s)[0]==BaseType
+		       && (*s)[1]==SubType)) s++;
+	if (*s) return *s+2;
+	else return("Unknown !");
+};
+
+static const unsigned char __init *PnP_INTERFACE_STR(unsigned char BaseType,
+					      unsigned char SubType,
+					      unsigned char Interface) {
+	unsigned char ** s=PnP_INTERFACES;
+	while (*s && !((*s)[0]==BaseType
+		       && (*s)[1]==SubType
+		       && (*s)[2]==Interface)) s++;
+	if (*s) return *s+3;
+	else return NULL;
+};
+
+static void __init printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
+	int i, c;
+	char decomp[4];
+#define p pkt->S14_Pack.S14_Data.S14_PPCPack
+	switch(p.Type) {
+	case 1:
+	  /* Decompress first 3 chars */
+	  c = *(unsigned short *)p.PPCData;
+	  decomp[0]='A'-1+((c>>10)&0x1F);
+	  decomp[1]='A'-1+((c>>5)&0x1F);
+	  decomp[2]='A'-1+(c&0x1F);
+	  decomp[3]=0;
+	  printk("    Chip identification: %s%4.4X\n",
+		 decomp, ld_le16((unsigned short *)(p.PPCData+2)));
+	  break;
+	default:
+	  printk("    Small vendor item type 0x%2.2x, data (hex): ",
+		 p.Type);
+	  for(i=0; i<size-2; i++) printk("%2.2x ", p.PPCData[i]);
+	  printk("\n");
+	  break;
+	}
+#undef p
+}
+
+static void __init printsmallpacket(PnP_TAG_PACKET * pkt, int size) {
+	static const unsigned char * intlevel[] = {"high", "low"};
+	static const unsigned char * intsense[] = {"edge", "level"};
+
+	switch (tag_small_item_name(pkt->S1_Pack.Tag)) {
+	case PnPVersion:
+	  printk("    PnPversion 0x%x.%x\n",
+		 pkt->S1_Pack.Version[0], /* How to interpret version ? */
+		 pkt->S1_Pack.Version[1]);
+	  break;
+//	case Logicaldevice:
+	  break;
+//	case CompatibleDevice:
+	  break;
+	case IRQFormat:
+#define p pkt->S4_Pack
+	  printk("    IRQ Mask 0x%4.4x, %s %s sensitive\n",
+		 ld_le16((unsigned short *)p.IRQMask),
+		 intlevel[(size>3) ? !(p.IRQInfo&0x05) : 0],
+		 intsense[(size>3) ? !(p.IRQInfo&0x03) : 0]);
+#undef p
+	  break;
+	case DMAFormat:
+#define p pkt->S5_Pack
+	  printk("    DMA channel mask 0x%2.2x, info 0x%2.2x\n",
+		 p.DMAMask, p.DMAInfo);
+#undef p
+	  break;
+	case StartDepFunc:
+	  printk("Start dependent function:\n");
+	  break;
+	case EndDepFunc:
+	  printk("End dependent function\n");
+	  break;
+	case IOPort:
+#define p pkt->S8_Pack
+	  printk("    Variable (%d decoded bits) I/O port\n"
+		 "      from 0x%4.4x to 0x%4.4x, alignment %d, %d ports\n",
+		 p.IOInfo&ISAAddr16bit?16:10,
+		 ld_le16((unsigned short *)p.RangeMin),
+ 		 ld_le16((unsigned short *)p.RangeMax),
+		 p.IOAlign, p.IONum);
+#undef p
+	  break;
+	case FixedIOPort:
+#define p pkt->S9_Pack
+	  printk("    Fixed (10 decoded bits) I/O port from %3.3x to %3.3x\n",
+		 (p.Range[1]<<8)|p.Range[0],
+		 ((p.Range[1]<<8)|p.Range[0])+p.IONum-1);
+#undef p
+	  break;
+	case Res1:
+	case Res2:
+	case Res3:
+	  printk("    Undefined packet type %d!\n",
+		 tag_small_item_name(pkt->S1_Pack.Tag));
+	  break;
+	case SmallVendorItem:
+	  printsmallvendor(pkt,size);
+	  break;
+	default:
+	  printk("    Type 0x2.2x%d, size=%d\n",
+		 pkt->S1_Pack.Tag, size);
+	  break;
+	}
+}
+
+static void __init printlargevendor(PnP_TAG_PACKET * pkt, int size) {
+	static const unsigned char * addrtype[] = {"I/O", "Memory", "System"};
+	static const unsigned char * inttype[] = {"8259", "MPIC", "RS6k BUID %d"};
+	static const unsigned char * convtype[] = {"Bus Memory", "Bus I/O", "DMA"};
+	static const unsigned char * transtype[] = {"direct", "mapped", "direct-store segment"};
+	static const unsigned char * L2type[] = {"WriteThru", "CopyBack"};
+	static const unsigned char * L2assoc[] = {"DirectMapped", "2-way set"};
+
+	int i;
+	char tmpstr[30], *t;
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+	switch(p.Type) {
+	case 2:
+	  printk("    %d K %s %s L2 cache, %d/%d bytes line/sector size\n",
+		 ld_le32((unsigned int *)p.PPCData),
+		 L2type[p.PPCData[10]-1],
+		 L2assoc[p.PPCData[4]-1],
+		 ld_le16((unsigned short *)p.PPCData+3),
+		 ld_le16((unsigned short *)p.PPCData+4));
+	  break;
+	case 3:
+	  printk("    PCI Bridge parameters\n"
+		 "      ConfigBaseAddress %0x\n"
+		 "      ConfigBaseData %0x\n"
+		 "      Bus number %d\n",
+		 ld_le32((unsigned int *)p.PPCData),
+		 ld_le32((unsigned int *)(p.PPCData+8)),
+		 p.PPCData[16]);
+	  for(i=20; i<size-4; i+=12) {
+	  	int j, first;
+	  	if(p.PPCData[i]) printk("      PCI Slot %d", p.PPCData[i]);
+		else printk ("      Integrated PCI device");
+		for(j=0, first=1, t=tmpstr; j<4; j++) {
+			int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
+			if(line!=0xffff){
+			        if(first) first=0; else *t++='/';
+				*t++='A'+j;
+			}
+		}
+		*t='\0';
+		printk(" DevFunc 0x%x interrupt line(s) %s routed to",
+		       p.PPCData[i+1],tmpstr);
+		sprintf(tmpstr,
+			inttype[p.PPCData[i+2]-1],
+			p.PPCData[i+3]);
+		printk(" %s line(s) ",
+		       tmpstr);
+		for(j=0, first=1, t=tmpstr; j<4; j++) {
+			int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
+			if(line!=0xffff){
+				if(first) first=0; else *t++='/';
+				t+=sprintf(t,"%d(%c)",
+					   line&0x7fff,
+					   line&0x8000?'E':'L');
+			}
+		}
+		printk("%s\n",tmpstr);
+	  }
+	  break;
+	case 5:
+	  printk("    Bridge address translation, %s decoding:\n"
+		 "      Processor  Bus        Size       Conversion Translation\n"
+		 "      0x%8.8x 0x%8.8x 0x%8.8x %s %s\n",
+		 p.PPCData[0]&1 ? "positive" : "subtractive",
+		 ld_le32((unsigned int *)p.PPCData+1),
+		 ld_le32((unsigned int *)p.PPCData+3),
+		 ld_le32((unsigned int *)p.PPCData+5),
+		 convtype[p.PPCData[2]-1],
+		 transtype[p.PPCData[1]-1]);
+	  break;
+	case 6:
+	  printk("    Bus speed %d Hz, %d slot(s)\n",
+		 ld_le32((unsigned int *)p.PPCData),
+		 p.PPCData[4]);
+	  break;
+	case 7:
+	  printk("    SCSI buses: %d, id(s):", p.PPCData[0]);
+	  for(i=1; i<=p.PPCData[0]; i++)
+	    printk(" %d%c", p.PPCData[i], i==p.PPCData[0] ? '\n' : ',');
+	  break;
+	case 9:
+	  printk("    %s address (%d bits), at 0x%x size 0x%x bytes\n",
+		 addrtype[p.PPCData[0]-1],
+		 p.PPCData[1],
+		 ld_le32((unsigned int *)(p.PPCData+4)),
+		 ld_le32((unsigned int *)(p.PPCData+12)));
+	  break;
+	case 10:
+	  sprintf(tmpstr,
+		  inttype[p.PPCData[0]-1],
+		  p.PPCData[1]);
+
+	  printk("    ISA interrupts routed to %s\n"
+		 "      lines",
+		 tmpstr);
+	  for(i=0; i<16; i++) {
+	  	int line=ld_le16((unsigned short *)p.PPCData+i+1);
+		if (line!=0xffff) printk(" %d(IRQ%d)", line, i);
+	  }
+	  printk("\n");
+	  break;
+	default:
+	  printk("    Large vendor item type 0x%2.2x\n      Data (hex):",
+		 p.Type);
+	  for(i=0; i<size-4; i++) printk(" %2.2x", p.PPCData[i]);
+	  printk("\n");
+#undef p
+	}
+}
+
+static void __init printlargepacket(PnP_TAG_PACKET * pkt, int size) {
+	switch (tag_large_item_name(pkt->S1_Pack.Tag)) {
+	case LargeVendorItem:
+	  printlargevendor(pkt, size);
+	  break;
+	default:
+	  printk("    Type 0x2.2x%d, size=%d\n",
+		 pkt->S1_Pack.Tag, size);
+	  break;
+	}
+}
+
+static void __init printpackets(PnP_TAG_PACKET * pkt, const char * cat)
+{
+	if (pkt->S1_Pack.Tag== END_TAG) {
+		printk("  No packets describing %s resources.\n", cat);
+		return;
+	}
+	printk(  "  Packets describing %s resources:\n",cat);
+	do {
+		int size;
+		if (tag_type(pkt->S1_Pack.Tag)) {
+		  	size= 3 +
+			  pkt->L1_Pack.Count0 +
+			  pkt->L1_Pack.Count1*256;
+			printlargepacket(pkt, size);
+		} else {
+			size=tag_small_count(pkt->S1_Pack.Tag)+1;
+			printsmallpacket(pkt, size);
+		}
+		pkt = (PnP_TAG_PACKET *)((unsigned char *) pkt + size);
+	} while (pkt->S1_Pack.Tag != END_TAG);
+}
+
+void __init print_residual_device_info(void)
+{
+	int i;
+	PPC_DEVICE *dev;
+#define did dev->DeviceId
+
+	/* make sure we have residual data first */
+	if (!have_residual_data)
+		return;
+
+	printk("Residual: %ld devices\n", res->ActualNumDevices);
+	for ( i = 0;
+	      i < res->ActualNumDevices ;
+	      i++)
+	{
+	  	char decomp[4], sn[20];
+		const char * s;
+		dev = &res->Devices[i];
+		s = PnP_INTERFACE_STR(did.BaseType, did.SubType,
+				      did.Interface);
+		if(!s) {
+			sprintf(sn, "interface %d", did.Interface);
+			s=sn;
+		}
+		if ( did.BusId & PCIDEVICE )
+		  printk("PCI Device, Bus %d, DevFunc 0x%x:",
+			 dev->BusAccess.PCIAccess.BusNumber,
+			 dev->BusAccess.PCIAccess.DevFuncNumber);
+	       	if ( did.BusId & PNPISADEVICE ) printk("PNPISA Device:");
+		if ( did.BusId & ISADEVICE )
+		  printk("ISA Device, Slot %d, LogicalDev %d:",
+			 dev->BusAccess.ISAAccess.SlotNumber,
+			 dev->BusAccess.ISAAccess.LogicalDevNumber);
+		if ( did.BusId & EISADEVICE ) printk("EISA Device:");
+		if ( did.BusId & PROCESSORDEVICE )
+		  printk("ProcBus Device, Bus %d, BUID %d: ",
+			 dev->BusAccess.ProcBusAccess.BusNumber,
+			 dev->BusAccess.ProcBusAccess.BUID);
+		if ( did.BusId & PCMCIADEVICE ) printk("PCMCIA ");
+		if ( did.BusId & VMEDEVICE ) printk("VME ");
+		if ( did.BusId & MCADEVICE ) printk("MCA ");
+		if ( did.BusId & MXDEVICE ) printk("MX ");
+		/* Decompress first 3 chars */
+		decomp[0]='A'-1+((did.DevId>>26)&0x1F);
+		decomp[1]='A'-1+((did.DevId>>21)&0x1F);
+		decomp[2]='A'-1+((did.DevId>>16)&0x1F);
+		decomp[3]=0;
+		printk(" %s%4.4lX, %s, %s, %s\n",
+		       decomp, did.DevId&0xffff,
+		       PnP_BASE_TYPES[did.BaseType],
+		       PnP_SUB_TYPE_STR(did.BaseType,did.SubType),
+		       s);
+		if ( dev->AllocatedOffset )
+			printpackets( (union _PnP_TAG_PACKET *)
+				      &res->DevicePnPHeap[dev->AllocatedOffset],
+				      "allocated");
+		if ( dev->PossibleOffset )
+			printpackets( (union _PnP_TAG_PACKET *)
+				      &res->DevicePnPHeap[dev->PossibleOffset],
+				      "possible");
+		if ( dev->CompatibleOffset )
+			printpackets( (union _PnP_TAG_PACKET *)
+				      &res->DevicePnPHeap[dev->CompatibleOffset],
+				      "compatible");
+	}
+}
+
+
+#if 0
+static void __init printVPD(void) {
+#define vpd res->VitalProductData
+	int ps=vpd.PageSize, i, j;
+	static const char* Usage[]={
+	  "FirmwareStack",  "FirmwareHeap",  "FirmwareCode", "BootImage",
+	  "Free", "Unpopulated", "ISAAddr", "PCIConfig",
+	  "IOMemory", "SystemIO", "SystemRegs", "PCIAddr",
+	  "UnPopSystemRom", "SystemROM", "ResumeBlock", "Other"
+	};
+	static const unsigned char *FWMan[]={
+	  "IBM", "Motorola", "FirmWorks", "Bull"
+	};
+	static const unsigned char *FWFlags[]={
+	  "Conventional", "OpenFirmware", "Diagnostics", "LowDebug",
+	  "MultiBoot", "LowClient", "Hex41", "FAT",
+	  "ISO9660", "SCSI_ID_Override", "Tape_Boot", "FW_Boot_Path"
+	};
+	static const unsigned char *ESM[]={
+	  "Port92", "PCIConfigA8", "FF001030", "????????"
+	};
+	static const unsigned char *SIOM[]={
+	  "Port850", "????????", "PCIConfigA8", "????????"
+	};
+
+	printk("Model: %s\n",vpd.PrintableModel);
+	printk("Serial: %s\n", vpd.Serial);
+	printk("FirmwareSupplier: %s\n", FWMan[vpd.FirmwareSupplier]);
+	printk("FirmwareFlags:");
+	for(j=0; j<12; j++) {
+	  	if (vpd.FirmwareSupports & (1<<j)) {
+			printk(" %s%c", FWFlags[j],
+			       vpd.FirmwareSupports&(-2<<j) ? ',' : '\n');
+		}
+	}
+	printk("NVRamSize: %ld\n", vpd.NvramSize);
+	printk("SIMMslots: %ld\n", vpd.NumSIMMSlots);
+	printk("EndianSwitchMethod: %s\n",
+	       ESM[vpd.EndianSwitchMethod>2 ? 2 : vpd.EndianSwitchMethod]);
+	printk("SpreadIOMethod: %s\n",
+	       SIOM[vpd.SpreadIOMethod>3 ? 3 : vpd.SpreadIOMethod]);
+	printk("Processor/Bus frequencies (Hz): %ld/%ld\n",
+	       vpd.ProcessorHz, vpd.ProcessorBusHz);
+	printk("Time Base Divisor: %ld\n", vpd.TimeBaseDivisor);
+	printk("WordWidth, PageSize: %ld, %d\n", vpd.WordWidth, ps);
+	printk("Cache sector size, Lock granularity: %ld, %ld\n",
+	       vpd.CoherenceBlockSize, vpd.GranuleSize);
+	for (i=0; i<res->ActualNumMemSegs; i++) {
+		int mask=res->Segs[i].Usage, first, j;
+		printk("%8.8lx-%8.8lx ",
+		       res->Segs[i].BasePage*ps,
+		       (res->Segs[i].PageCount+res->Segs[i].BasePage)*ps-1);
+		for(j=15, first=1; j>=0; j--) {
+			if (mask&(1<<j)) {
+				if (first) first=0;
+				else printk(", ");
+				printk("%s", Usage[j]);
+			}
+		}
+		printk("\n");
+	}
+}
+
+/*
+ * Spit out some info about residual data
+ */
+void print_residual_device_info(void)
+{
+	int i;
+	union _PnP_TAG_PACKET *pkt;
+	PPC_DEVICE *dev;
+#define did dev->DeviceId
+
+	/* make sure we have residual data first */
+	if (!have_residual_data)
+		return;
+	printk("Residual: %ld devices\n", res->ActualNumDevices);
+	for ( i = 0;
+	      i < res->ActualNumDevices ;
+	      i++)
+	{
+		dev = &res->Devices[i];
+		/*
+		 * pci devices
+		 */
+		if ( did.BusId & PCIDEVICE )
+		{
+			printk("PCI Device:");
+			/* unknown vendor */
+			if ( !strncmp( "Unknown", pci_strvendor(did.DevId>>16), 7) )
+				printk(" id %08lx types %d/%d", did.DevId,
+				       did.BaseType, did.SubType);
+			/* known vendor */
+			else
+				printk(" %s %s",
+				       pci_strvendor(did.DevId>>16),
+				       pci_strdev(did.DevId>>16,
+						  did.DevId&0xffff)
+					);
+
+			if ( did.BusId & PNPISADEVICE )
+			{
+				printk(" pnp:");
+				/* get pnp info on the device */
+				pkt = (union _PnP_TAG_PACKET *)
+					&res->DevicePnPHeap[dev->AllocatedOffset];
+				for (; pkt->S1_Pack.Tag != DF_END_TAG;
+				     pkt++ )
+				{
+					if ( (pkt->S1_Pack.Tag == S4_Packet) ||
+					     (pkt->S1_Pack.Tag == S4_Packet_flags) )
+						printk(" irq %02x%02x",
+						       pkt->S4_Pack.IRQMask[0],
+						       pkt->S4_Pack.IRQMask[1]);
+				}
+			}
+			printk("\n");
+			continue;
+		}
+		/*
+		 * isa devices
+		 */
+		if ( did.BusId & ISADEVICE )
+		{
+			printk("ISA Device: basetype: %d subtype: %d",
+			       did.BaseType, did.SubType);
+			printk("\n");
+			continue;
+		}
+		/*
+		 * eisa devices
+		 */
+		if ( did.BusId & EISADEVICE )
+		{
+			printk("EISA Device: basetype: %d subtype: %d",
+			       did.BaseType, did.SubType);
+			printk("\n");
+			continue;
+		}
+		/*
+		 * proc bus devices
+		 */
+		if ( did.BusId & PROCESSORDEVICE )
+		{
+			printk("ProcBus Device: basetype: %d subtype: %d",
+			       did.BaseType, did.SubType);
+			printk("\n");
+			continue;
+		}
+		/*
+		 * pcmcia devices
+		 */
+		if ( did.BusId & PCMCIADEVICE )
+		{
+			printk("PCMCIA Device: basetype: %d subtype: %d",
+			       did.BaseType, did.SubType);
+			printk("\n");
+			continue;
+		}
+		printk("Unknown bus access device: busid %lx\n",
+		       did.BusId);
+	}
+}
+#endif
+
+/* Returns the device index in the residual data,
+   any of the search items may be set as -1 for wildcard,
+   DevID number field (second halfword) is big endian !
+
+   Examples:
+   - search for the Interrupt controller (8259 type), 2 methods:
+     1) i8259 = residual_find_device(~0,
+                                     NULL,
+				     SystemPeripheral,
+				     ProgrammableInterruptController,
+				     ISA_PIC,
+				     0);
+     2) i8259 = residual_find_device(~0, "PNP0000", -1, -1, -1, 0)
+
+   - search for the first two serial devices, whatever their type)
+     iserial1 = residual_find_device(~0,NULL,
+                                     CommunicationsDevice,
+				     RS232Device,
+				     -1, 0)
+     iserial2 = residual_find_device(~0,NULL,
+                                     CommunicationsDevice,
+				     RS232Device,
+				     -1, 1)
+   - but search for typical COM1 and COM2 is not easy due to the
+     fact that the interface may be anything and the name "PNP0500" or
+     "PNP0501". Quite bad.
+
+*/
+
+/* devid are easier to uncompress than to compress, so to minimize bloat
+in this rarely used area we unencode and compare */
+
+/* in residual data number is big endian in the device table and
+little endian in the heap, so we use two parameters to avoid writing
+two very similar functions */
+
+static int __init same_DevID(unsigned short vendor,
+	       unsigned short Number,
+	       char * str)
+{
+	static unsigned const char hexdigit[]="0123456789ABCDEF";
+	if (strlen(str)!=7) return 0;
+	if ( ( ((vendor>>10)&0x1f)+'A'-1 == str[0])  &&
+	     ( ((vendor>>5)&0x1f)+'A'-1 == str[1])   &&
+	     ( (vendor&0x1f)+'A'-1 == str[2])        &&
+	     (hexdigit[(Number>>12)&0x0f] == str[3]) &&
+	     (hexdigit[(Number>>8)&0x0f] == str[4])  &&
+	     (hexdigit[(Number>>4)&0x0f] == str[5])  &&
+	     (hexdigit[Number&0x0f] == str[6]) ) return 1;
+	return 0;
+}
+
+PPC_DEVICE __init *residual_find_device(unsigned long BusMask,
+			 unsigned char * DevID,
+			 int BaseType,
+			 int SubType,
+			 int Interface,
+			 int n)
+{
+	int i;
+	if (!have_residual_data) return NULL;
+	for (i=0; i<res->ActualNumDevices; i++) {
+#define Dev res->Devices[i].DeviceId
+		if ( (Dev.BusId&BusMask)                                  &&
+		     (BaseType==-1 || Dev.BaseType==BaseType)             &&
+		     (SubType==-1 || Dev.SubType==SubType)                &&
+		     (Interface==-1 || Dev.Interface==Interface)          &&
+		     (DevID==NULL || same_DevID((Dev.DevId>>16)&0xffff,
+						Dev.DevId&0xffff, DevID)) &&
+		     !(n--) ) return res->Devices+i;
+#undef Dev
+	}
+	return NULL;
+}
+
+PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask,
+			 unsigned short DevID,
+			 int BaseType,
+			 int SubType,
+			 int Interface,
+			 int n)
+{
+	int i;
+	if (!have_residual_data) return NULL;
+	for (i=0; i<res->ActualNumDevices; i++) {
+#define Dev res->Devices[i].DeviceId
+		if ( (Dev.BusId&BusMask)                                  &&
+		     (BaseType==-1 || Dev.BaseType==BaseType)             &&
+		     (SubType==-1 || Dev.SubType==SubType)                &&
+		     (Interface==-1 || Dev.Interface==Interface)          &&
+		     (DevID==0xffff || (Dev.DevId&0xffff) == DevID)	  &&
+		     !(n--) ) return res->Devices+i;
+#undef Dev
+	}
+	return NULL;
+}
+
+static int __init
+residual_scan_pcibridge(PnP_TAG_PACKET * pkt, struct pci_dev *dev)
+{
+	int irq = -1;
+
+#define data pkt->L4_Pack.L4_Data.L4_PPCPack.PPCData
+	if (dev->bus->number == data[16]) {
+		int i, size;
+
+		size = 3 + ld_le16((u_short *) (&pkt->L4_Pack.Count0));
+		for (i = 20; i < size - 4; i += 12) {
+			unsigned char pin;
+			int line_irq;
+
+			if (dev->devfn != data[i + 1])
+				continue;
+
+			pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+			if (pin) {
+				line_irq = ld_le16((unsigned short *)
+						(&data[i + 4 + 2 * (pin - 1)]));
+				irq = (line_irq == 0xffff) ? 0
+							   : line_irq & 0x7fff;
+			} else
+				irq = 0;
+
+			break;
+		}
+	}
+#undef data
+
+	return irq;
+}
+
+int __init
+residual_pcidev_irq(struct pci_dev *dev)
+{
+	int i = 0;
+	int irq = -1;
+	PPC_DEVICE *bridge;
+
+	while ((bridge = residual_find_device
+	       (-1, NULL, BridgeController, PCIBridge, -1, i++))) {
+
+		PnP_TAG_PACKET *pkt;
+		if (bridge->AllocatedOffset) {
+			pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+					   bridge->AllocatedOffset, 3, 0);
+			if (!pkt)
+				continue;
+
+			irq = residual_scan_pcibridge(pkt, dev);
+			if (irq != -1)
+				break;
+		}
+	}
+
+	return (irq < 0) ? 0 : irq;
+}
+
+void __init residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+	PPC_DEVICE *dev;
+	int i = 0;
+	unsigned short irq_mask = 0x000; /* default to edge */
+
+	while ((dev = residual_find_device(-1, NULL, -1, -1, -1, i++))) {
+		PnP_TAG_PACKET *pkt;
+		unsigned short mask;
+		int size;
+		int offset = dev->AllocatedOffset;
+
+		if (!offset)
+			continue;
+
+		pkt = PnP_find_packet(res->DevicePnPHeap + offset,
+					      IRQFormat, 0);
+		if (!pkt)
+			continue;
+
+		size = tag_small_count(pkt->S1_Pack.Tag) + 1;
+		mask = ld_le16((unsigned short *)pkt->S4_Pack.IRQMask);
+		if (size > 3 && (pkt->S4_Pack.IRQInfo & 0x0c))
+			irq_mask |= mask;
+	}
+
+	*irq_edge_mask_lo = irq_mask & 0xff;
+	*irq_edge_mask_hi = irq_mask >> 8;
+}
+
+unsigned int __init residual_isapic_addr(void)
+{
+	PPC_DEVICE *isapic;
+	PnP_TAG_PACKET *pkt;
+	unsigned int addr;
+
+	isapic = residual_find_device(~0, NULL, SystemPeripheral,
+				      ProgrammableInterruptController,
+				      ISA_PIC, 0);
+	if (!isapic)
+		goto unknown;
+
+	pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+						isapic->AllocatedOffset, 9, 0);
+	if (!pkt)
+		goto unknown;
+
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+	/* Must be 32-bit system address */
+	if (!((p.PPCData[0] == 3) && (p.PPCData[1] == 32)))
+		goto unknown;
+
+	/* It doesn't seem to work where length != 1 (what can I say? :-/ ) */
+	if (ld_le32((unsigned int *)(p.PPCData + 12)) != 1)
+		goto unknown;
+
+	addr = ld_le32((unsigned int *) (p.PPCData + 4));
+#undef p
+	return addr;
+unknown:
+	return 0;
+}
+
+PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
+				unsigned packet_tag,
+				int n)
+{
+	unsigned mask, masked_tag, size;
+	if(!p) return NULL;
+	if (tag_type(packet_tag)) mask=0xff; else mask=0xF8;
+	masked_tag = packet_tag&mask;
+	for(; *p != END_TAG; p+=size) {
+		if ((*p & mask) == masked_tag && !(n--))
+			return (PnP_TAG_PACKET *) p;
+		if (tag_type(*p))
+			size=ld_le16((unsigned short *)(p+1))+3;
+		else
+			size=tag_small_count(*p)+1;
+	}
+	return NULL; /* not found */
+}
+
+PnP_TAG_PACKET __init *PnP_find_small_vendor_packet(unsigned char *p,
+					     unsigned packet_type,
+					     int n)
+{
+	int next=0;
+	while (p) {
+		p = (unsigned char *) PnP_find_packet(p, 0x70, next);
+		if (p && p[1]==packet_type && !(n--))
+			return (PnP_TAG_PACKET *) p;
+		next = 1;
+	};
+	return NULL; /* not found */
+}
+
+PnP_TAG_PACKET __init *PnP_find_large_vendor_packet(unsigned char *p,
+					   unsigned packet_type,
+					   int n)
+{
+	int next=0;
+	while (p) {
+		p = (unsigned char *) PnP_find_packet(p, 0x84, next);
+		if (p && p[3]==packet_type && !(n--))
+			return (PnP_TAG_PACKET *) p;
+		next = 1;
+	};
+	return NULL; /* not found */
+}
+
+#ifdef CONFIG_PROC_PREPRESIDUAL
+static int proc_prep_residual_read(char * buf, char ** start, off_t off,
+		int count, int *eof, void *data)
+{
+	int n;
+
+	n = res->ResidualLength - off;
+	if (n < 0) {
+		*eof = 1;
+		n = 0;
+	}
+	else {
+		if (n > count)
+			n = count;
+		else
+			*eof = 1;
+
+		memcpy(buf, (char *)res + off, n);
+		*start = buf;
+	}
+
+	return n;
+}
+
+int __init
+proc_prep_residual_init(void)
+{
+	if (have_residual_data)
+		create_proc_read_entry("residual", S_IRUGO, NULL,
+					proc_prep_residual_read, NULL);
+	return 0;
+}
+
+__initcall(proc_prep_residual_init);
+#endif
diff --git a/arch/ppc/platforms/rpx8260.h b/arch/ppc/platforms/rpx8260.h
new file mode 100644
index 0000000..843494a
--- /dev/null
+++ b/arch/ppc/platforms/rpx8260.h
@@ -0,0 +1,81 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Embedded Planet RPX6 (or RPX Super) MPC8260 board.
+ * Copied from the RPX-Classic and SBS8260 stuff.
+ *
+ * Copyright (c) 2001 Dan Malek <dan@embeddededge.com>
+ */
+#ifdef __KERNEL__
+#ifndef __ASM_PLATFORMS_RPX8260_H__
+#define __ASM_PLATFORMS_RPX8260_H__
+
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_nvsize;	/* NVRAM size in bytes (can be 0) */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in MHz */
+	unsigned int	bi_cpmfreq;	/* CPM Freq, in MHz */
+	unsigned int	bi_brgfreq;	/* BRG Freq, in MHz */
+	unsigned int	bi_vco;		/* VCO Out from PLL */
+	unsigned int	bi_baudrate;	/* Default console baud rate */
+	unsigned int	bi_immr;	/* IMMR when called from boot rom */
+	unsigned char	bi_enetaddr[6];
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+/* Memory map is configured by the PROM startup.
+ * We just map a few things we need.  The CSR is actually 4 byte-wide
+ * registers that can be accessed as 8-, 16-, or 32-bit values.
+ */
+#define CPM_MAP_ADDR		((uint)0xf0000000)
+#define RPX_CSR_ADDR		((uint)0xfa000000)
+#define RPX_CSR_SIZE		((uint)(512 * 1024))
+#define RPX_NVRTC_ADDR		((uint)0xfa080000)
+#define RPX_NVRTC_SIZE		((uint)(512 * 1024))
+
+/* The RPX6 has 16, byte wide control/status registers.
+ * Not all are used (yet).
+ */
+extern volatile u_char *rpx6_csr_addr;
+
+/* Things of interest in the CSR.
+*/
+#define BCSR0_ID_MASK		((u_char)0xf0)		/* Read only */
+#define BCSR0_SWITCH_MASK	((u_char)0x0f)		/* Read only */
+#define BCSR1_XCVR_SMC1		((u_char)0x80)
+#define BCSR1_XCVR_SMC2		((u_char)0x40)
+#define BCSR2_FLASH_WENABLE	((u_char)0x20)
+#define BCSR2_NVRAM_ENABLE	((u_char)0x10)
+#define BCSR2_ALT_IRQ2		((u_char)0x08)
+#define BCSR2_ALT_IRQ3		((u_char)0x04)
+#define BCSR2_PRST		((u_char)0x02)		/* Force reset */
+#define BCSR2_ENPRST		((u_char)0x01)		/* Enable POR */
+#define BCSR3_MODCLK_MASK	((u_char)0xe0)
+#define BCSR3_ENCLKHDR		((u_char)0x10)
+#define BCSR3_LED5		((u_char)0x04)		/* 0 == on */
+#define BCSR3_LED6		((u_char)0x02)		/* 0 == on */
+#define BCSR3_LED7		((u_char)0x01)		/* 0 == on */
+#define BCSR4_EN_PHY		((u_char)0x80)		/* Enable PHY */
+#define BCSR4_EN_MII		((u_char)0x40)		/* Enable PHY */
+#define BCSR4_MII_READ		((u_char)0x04)
+#define BCSR4_MII_MDC		((u_char)0x02)
+#define BCSR4_MII_MDIO		((u_char)0x01)
+#define BCSR13_FETH_IRQMASK	((u_char)0xf0)
+#define BCSR15_FETH_IRQ		((u_char)0x20)
+
+#define PHY_INTERRUPT	SIU_INT_IRQ7
+
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"Embedded Planet"
+#define CPUINFO_MACHINE		"EP8260 PowerPC"
+
+/* Warm reset vector. */
+#define BOOTROM_RESTART_ADDR	((uint)0xfff00104)
+
+#endif /* __ASM_PLATFORMS_RPX8260_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/rpxclassic.h b/arch/ppc/platforms/rpxclassic.h
new file mode 100644
index 0000000..6daa109
--- /dev/null
+++ b/arch/ppc/platforms/rpxclassic.h
@@ -0,0 +1,119 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the RPCG RPX-Classic board.  Copied from the RPX-Lite stuff.
+ *
+ * Copyright (c) 1998 Dan Malek (dmalek@jlc.net)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_RPX_DEFS
+#define __MACH_RPX_DEFS
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
+	unsigned char	bi_enetaddr[6];
+	unsigned int	bi_baudrate;
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+/* Memory map is configured by the PROM startup.
+ * We just map a few things we need.  The CSR is actually 4 byte-wide
+ * registers that can be accessed as 8-, 16-, or 32-bit values.
+ */
+#define PCI_ISA_IO_ADDR		((unsigned)0x80000000)
+#define PCI_ISA_IO_SIZE		((uint)(512 * 1024 * 1024))
+#define PCI_ISA_MEM_ADDR	((unsigned)0xc0000000)
+#define PCI_ISA_MEM_SIZE	((uint)(512 * 1024 * 1024))
+#define RPX_CSR_ADDR		((uint)0xfa400000)
+#define RPX_CSR_SIZE		((uint)(4 * 1024))
+#define IMAP_ADDR		((uint)0xfa200000)
+#define IMAP_SIZE		((uint)(64 * 1024))
+#define PCI_CSR_ADDR		((uint)0x80000000)
+#define PCI_CSR_SIZE		((uint)(64 * 1024))
+#define PCMCIA_MEM_ADDR		((uint)0xe0000000)
+#define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+#define PCMCIA_IO_ADDR		((uint)0xe4000000)
+#define PCMCIA_IO_SIZE		((uint)(4 * 1024))
+#define PCMCIA_ATTRB_ADDR	((uint)0xe8000000)
+#define PCMCIA_ATTRB_SIZE	((uint)(4 * 1024))
+
+/* Things of interest in the CSR.
+*/
+#define BCSR0_ETHEN		((uint)0x80000000)
+#define BCSR0_ETHLPBK		((uint)0x40000000)
+#define BCSR0_COLTESTDIS	((uint)0x20000000)
+#define BCSR0_FULLDPLXDIS	((uint)0x10000000)
+#define BCSR0_ENFLSHSEL		((uint)0x04000000)
+#define BCSR0_FLASH_SEL		((uint)0x02000000)
+#define BCSR0_ENMONXCVR		((uint)0x01000000)
+
+#define BCSR0_PCMCIAVOLT	((uint)0x000f0000)	/* CLLF */
+#define BCSR0_PCMCIA3VOLT	((uint)0x000a0000)	/* CLLF */
+#define BCSR0_PCMCIA5VOLT	((uint)0x00060000)	/* CLLF */
+
+#define BCSR1_IPB5SEL           ((uint)0x00100000)
+#define BCSR1_PCVCTL4           ((uint)0x00080000)
+#define BCSR1_PCVCTL5           ((uint)0x00040000)
+#define BCSR1_PCVCTL6           ((uint)0x00020000)
+#define BCSR1_PCVCTL7           ((uint)0x00010000)
+
+#define BCSR2_EN232XCVR		((uint)0x00008000)
+#define BCSR2_QSPACESEL		((uint)0x00004000)
+#define BCSR2_FETHLEDMODE	((uint)0x00000800)	/* CLLF */
+
+#if defined(CONFIG_HTDMSOUND)
+#include <platforms/rpxhiox.h>
+#endif
+
+/* define IO_BASE for pcmcia, CLLF only */
+#if !defined(CONFIG_PCI)
+#define _IO_BASE 0x80000000
+#define _IO_BASE_SIZE 0x1000
+
+/* for pcmcia sandisk */
+#ifdef CONFIG_IDE
+# define MAX_HWIFS 1
+#endif
+#endif
+
+/* Interrupt level assignments.
+*/
+#define FEC_INTERRUPT	SIU_LEVEL1	/* FEC interrupt */
+
+
+/* CPM Ethernet through SCCx.
+ *
+ * Bits in parallel I/O port registers that have to be set/cleared
+ * to configure the pins for SCC1 use.
+ */
+#define PA_ENET_RXD	((ushort)0x0001)
+#define PA_ENET_TXD	((ushort)0x0002)
+#define PA_ENET_TCLK	((ushort)0x0200)
+#define PA_ENET_RCLK	((ushort)0x0800)
+#define PB_ENET_TENA	((uint)0x00001000)
+#define PC_ENET_CLSN	((ushort)0x0010)
+#define PC_ENET_RENA	((ushort)0x0020)
+
+/* Control bits in the SICR to route TCLK (CLK2) and RCLK (CLK4) to
+ * SCC1.  Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero.
+ */
+#define SICR_ENET_MASK	((uint)0x000000ff)
+#define SICR_ENET_CLKRT	((uint)0x0000003d)
+
+/* We don't use the 8259.
+*/
+
+#define NR_8259_INTS	0
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __MACH_RPX_DEFS */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/rpxhiox.h b/arch/ppc/platforms/rpxhiox.h
new file mode 100644
index 0000000..c3fa5a6
--- /dev/null
+++ b/arch/ppc/platforms/rpxhiox.h
@@ -0,0 +1,41 @@
+/*
+ * The Embedded Planet HIOX expansion card definitions.
+ * There were a few different versions of these cards, but only
+ * the one that escaped real production is defined here.
+ *
+ * Copyright (c) 2000 Dan Malek (dmalek@jlc.net)
+ */
+#ifndef __MACH_RPX_HIOX_DEFS
+#define __MACH_RPX_HIOX_DEFS
+
+#define HIOX_CSR_ADDR		((uint)0xfac00000)
+#define HIOX_CSR_SIZE		((uint)(4 * 1024))
+#define HIOX_CSR0_ADDR		HIOX_CSR_ADDR
+#define HIOX_CSR4_ADDR		((uint)0xfac00004)
+
+#define HIOX_CSR0_DEFAULT	((uint)0x380f3c00)
+#define HIOX_CSR0_ENSCC2	((uint)0x80000000)
+#define HIOX_CSR0_ENSMC2	((uint)0x04000000)
+#define HIOX_CSR0_ENVDOCLK	((uint)0x02000000)
+#define HIOX_CSR0_VDORST_HL	((uint)0x01000000)
+#define HIOX_CSR0_RS232SEL	((uint)0x0000c000)
+#define HIOX_CSR0_SCC3SEL	((uint)0x0000c000)
+#define HIOX_CSR0_SMC1SEL	((uint)0x00008000)
+#define HIOX_CSR0_SCC1SEL	((uint)0x00004000)
+#define HIOX_CSR0_ENTOUCH	((uint)0x00000080)
+#define HIOX_CSR0_PDOWN100	((uint)0x00000060)
+#define HIOX_CSR0_PDOWN10	((uint)0x00000040)
+#define HIOX_CSR0_PDOWN1	((uint)0x00000020)
+#define HIOX_CSR0_TSELSPI	((uint)0x00000010)
+#define HIOX_CSR0_TIRQSTAT	((uint)0x00000008)
+#define HIOX_CSR4_DEFAULT	((uint)0x00000000)
+#define HIOX_CSR4_ENTIRQ2	((uint)0x20000000)
+#define HIOX_CSR4_ENTIRQ3	((uint)0x10000000)
+#define HIOX_CSR4_ENAUDIO	((uint)0x00000080)
+#define HIOX_CSR4_RSTAUDIO	((uint)0x00000040)	/* 0 == reset */
+#define HIOX_CSR4_AUDCLKHI	((uint)0x00000020)
+#define HIOX_CSR4_AUDSPISEL	((uint)0x00000010)
+#define HIOX_CSR4_AUDIRQSTAT	((uint)0x00000008)
+#define HIOX_CSR4_AUDCLKSEL	((uint)0x00000007)
+
+#endif
diff --git a/arch/ppc/platforms/rpxlite.h b/arch/ppc/platforms/rpxlite.h
new file mode 100644
index 0000000..deee5bd
--- /dev/null
+++ b/arch/ppc/platforms/rpxlite.h
@@ -0,0 +1,96 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the RPCG RPX-Lite board.  Copied from the MBX stuff.
+ *
+ * Copyright (c) 1998 Dan Malek (dmalek@jlc.net)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_RPX_DEFS
+#define __MACH_RPX_DEFS
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
+	unsigned char	bi_enetaddr[6];
+	unsigned int	bi_baudrate;
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+/* Memory map is configured by the PROM startup.
+ * We just map a few things we need.  The CSR is actually 4 byte-wide
+ * registers that can be accessed as 8-, 16-, or 32-bit values.
+ */
+#define RPX_CSR_ADDR		((uint)0xfa400000)
+#define RPX_CSR_SIZE		((uint)(4 * 1024))
+#define IMAP_ADDR		((uint)0xfa200000)
+#define IMAP_SIZE		((uint)(64 * 1024))
+#define PCMCIA_MEM_ADDR		((uint)0x04000000)
+#define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+#define PCMCIA_IO_ADDR		((uint)0x04400000)
+#define PCMCIA_IO_SIZE		((uint)(4 * 1024))
+
+/* Things of interest in the CSR.
+*/
+#define BCSR0_ETHEN		((uint)0x80000000)
+#define BCSR0_ETHLPBK		((uint)0x40000000)
+#define BCSR0_COLTESTDIS	((uint)0x20000000)
+#define BCSR0_FULLDPLXDIS	((uint)0x10000000)
+#define BCSR0_LEDOFF		((uint)0x08000000)
+#define BCSR0_USBDISABLE	((uint)0x04000000)
+#define BCSR0_USBHISPEED	((uint)0x02000000)
+#define BCSR0_USBPWREN		((uint)0x01000000)
+#define BCSR0_PCMCIAVOLT	((uint)0x000f0000)
+#define BCSR0_PCMCIA3VOLT	((uint)0x000a0000)
+#define BCSR0_PCMCIA5VOLT	((uint)0x00060000)
+
+#define BCSR1_IPB5SEL          ((uint)0x00100000)
+#define BCSR1_PCVCTL4          ((uint)0x00080000)
+#define BCSR1_PCVCTL5          ((uint)0x00040000)
+#define BCSR1_PCVCTL6          ((uint)0x00020000)
+#define BCSR1_PCVCTL7          ((uint)0x00010000)
+
+#if defined(CONFIG_HTDMSOUND)
+#include <platforms/rpxhiox.h>
+#endif
+
+/* define IO_BASE for pcmcia */
+#define _IO_BASE 0x80000000
+#define _IO_BASE_SIZE 0x1000
+
+#ifdef CONFIG_IDE
+# define MAX_HWIFS 1
+#endif
+
+/* CPM Ethernet through SCCx.
+ *
+ * This ENET stuff is for the MPC850 with ethernet on SCC2.  Some of
+ * this may be unique to the RPX-Lite configuration.
+ * Note TENA is on Port B.
+ */
+#define PA_ENET_RXD	((ushort)0x0004)
+#define PA_ENET_TXD	((ushort)0x0008)
+#define PA_ENET_TCLK	((ushort)0x0200)
+#define PA_ENET_RCLK	((ushort)0x0800)
+#define PB_ENET_TENA	((uint)0x00002000)
+#define PC_ENET_CLSN	((ushort)0x0040)
+#define PC_ENET_RENA	((ushort)0x0080)
+
+#define SICR_ENET_MASK	((uint)0x0000ff00)
+#define SICR_ENET_CLKRT	((uint)0x00003d00)
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __MACH_RPX_DEFS */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c
new file mode 100644
index 0000000..531bfa0
--- /dev/null
+++ b/arch/ppc/platforms/sandpoint.c
@@ -0,0 +1,742 @@
+/*
+ * arch/ppc/platforms/sandpoint_setup.c
+ *
+ * Board setup routines for the Motorola SPS Sandpoint Test Platform.
+ *
+ * Author: Mark A. Greer
+ *	 mgreer@mvista.com
+ *
+ * 2000-2003 (c) MontaVista Software, Inc.  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.
+ */
+
+/*
+ * This file adds support for the Motorola SPS Sandpoint Test Platform.
+ * These boards have a PPMC slot for the processor so any combination
+ * of cpu and host bridge can be attached.  This port is for an 8240 PPMC
+ * module from Motorola SPS and other closely related cpu/host bridge
+ * combinations (e.g., 750/755/7400 with MPC107 host bridge).
+ * The sandpoint itself has a Windbond 83c553 (PCI-ISA bridge, 2 DMA ctlrs, 2
+ * cascaded 8259 interrupt ctlrs, 8254 Timer/Counter, and an IDE ctlr), a
+ * National 87308 (RTC, 2 UARTs, Keyboard & mouse ctlrs, and a floppy ctlr),
+ * and 4 PCI slots (only 2 of which are usable; the other 2 are keyed for 3.3V
+ * but are really 5V).
+ *
+ * The firmware on the sandpoint is called DINK (not my acronym :).  This port
+ * depends on DINK to do some basic initialization (e.g., initialize the memory
+ * ctlr) and to ensure that the processor is using MAP B (CHRP map).
+ *
+ * The switch settings for the Sandpoint board MUST be as follows:
+ * 	S3: down
+ * 	S4: up
+ * 	S5: up
+ * 	S6: down
+ *
+ * 'down' is in the direction from the PCI slots towards the PPMC slot;
+ * 'up' is in the direction from the PPMC slot towards the PCI slots.
+ * Be careful, the way the sandpoint board is installed in XT chasses will
+ * make the directions reversed.
+ *
+ * Since Motorola listened to our suggestions for improvement, we now have
+ * the Sandpoint X3 board.  All of the PCI slots are available, it uses
+ * the serial interrupt interface (just a hardware thing we need to
+ * configure properly).
+ *
+ * Use the default X3 switch settings.  The interrupts are then:
+ *		EPIC	Source
+ *		  0	SIOINT 		(8259, active low)
+ *		  1	PCI #1
+ *		  2	PCI #2
+ *		  3	PCI #3
+ *		  4	PCI #4
+ *		  7	Winbond INTC	(IDE interrupt)
+ *		  8	Winbond INTD	(IDE interrupt)
+ *
+ *
+ * Motorola has finally released a version of DINK32 that correctly
+ * (seemingly) initalizes the memory controller correctly, regardless
+ * of the amount of memory in the system.  Once a method of determining
+ * what version of DINK initializes the system for us, if applicable, is
+ * found, we can hopefully stop hardcoding 32MB of RAM.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>	/* for linux/serial_core.h */
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/vga.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/mpc10x.h>
+#include <asm/pci-bridge.h>
+#include <asm/kgdb.h>
+
+#include "sandpoint.h"
+
+/* Set non-zero if an X2 Sandpoint detected. */
+static int sandpoint_is_x2;
+
+unsigned char __res[sizeof(bd_t)];
+
+static void sandpoint_halt(void);
+static void sandpoint_probe_type(void);
+
+/*
+ * Define all of the IRQ senses and polarities.  Taken from the
+ * Sandpoint X3 User's manual.
+ */
+static u_char sandpoint_openpic_initsenses[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 0: SIOINT */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 2: PCI Slot 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 3: PCI Slot 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 4: PCI Slot 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 5: PCI Slot 4 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 8: IDE (INT C) */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE)	/* 9: IDE (INT D) */
+};
+
+/*
+ * Motorola SPS Sandpoint interrupt routing.
+ */
+static inline int
+x3_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	/*
+	 *	PCI IDSEL/INTPIN->INTLINE
+	 * 	   A   B   C   D
+	 */
+	{
+		{ 16,  0,  0,  0 },	/* IDSEL 11 - i8259 on Winbond */
+		{  0,  0,  0,  0 },	/* IDSEL 12 - unused */
+		{ 18, 21, 20, 19 },	/* IDSEL 13 - PCI slot 1 */
+		{ 19, 18, 21, 20 },	/* IDSEL 14 - PCI slot 2 */
+		{ 20, 19, 18, 21 },	/* IDSEL 15 - PCI slot 3 */
+		{ 21, 20, 19, 18 },	/* IDSEL 16 - PCI slot 4 */
+	};
+
+	const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static inline int
+x2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	/*
+	 *	PCI IDSEL/INTPIN->INTLINE
+	 * 	   A   B   C   D
+	 */
+	{
+		{ 18,  0,  0,  0 },	/* IDSEL 11 - i8259 on Windbond */
+		{  0,  0,  0,  0 },	/* IDSEL 12 - unused */
+		{ 16, 17, 18, 19 },	/* IDSEL 13 - PCI slot 1 */
+		{ 17, 18, 19, 16 },	/* IDSEL 14 - PCI slot 2 */
+		{ 18, 19, 16, 17 },	/* IDSEL 15 - PCI slot 3 */
+		{ 19, 16, 17, 18 },	/* IDSEL 16 - PCI slot 4 */
+	};
+
+	const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void __init
+sandpoint_setup_winbond_83553(struct pci_controller *hose)
+{
+	int		devfn;
+
+	/*
+	 * Route IDE interrupts directly to the 8259's IRQ 14 & 15.
+	 * We can't route the IDE interrupt to PCI INTC# or INTD# because those
+	 * woule interfere with the PMC's INTC# and INTD# lines.
+	 */
+	/*
+	 * Winbond Fcn 0
+	 */
+	devfn = PCI_DEVFN(11,0);
+
+	early_write_config_byte(hose,
+				0,
+				devfn,
+				0x43, /* IDE Interrupt Routing Control */
+				0xef);
+	early_write_config_word(hose,
+				0,
+				devfn,
+				0x44, /* PCI Interrupt Routing Control */
+				0x0000);
+
+	/* Want ISA memory cycles to be forwarded to PCI bus */
+	early_write_config_byte(hose,
+				0,
+				devfn,
+				0x48, /* ISA-to-PCI Addr Decoder Control */
+				0xf0);
+
+	/* Enable Port 92.  */
+	early_write_config_byte(hose,
+				0,
+				devfn,
+				0x4e,	/* AT System Control Register */
+				0x06);
+	/*
+	 * Winbond Fcn 1
+	 */
+	devfn = PCI_DEVFN(11,1);
+
+	/* Put IDE controller into native mode. */
+	early_write_config_byte(hose,
+				0,
+				devfn,
+				0x09,	/* Programming interface Register */
+				0x8f);
+
+	/* Init IRQ routing, enable both ports, disable fast 16 */
+	early_write_config_dword(hose,
+				0,
+				devfn,
+				0x40,	/* IDE Control/Status Register */
+				0x00ff0011);
+	return;
+}
+
+/* On the sandpoint X2, we must avoid sending configuration cycles to
+ * device #12 (IDSEL addr = AD12).
+ */
+static int
+x2_exclude_device(u_char bus, u_char devfn)
+{
+	if ((bus == 0) && (PCI_SLOT(devfn) == SANDPOINT_HOST_BRIDGE_IDSEL))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	else
+		return PCIBIOS_SUCCESSFUL;
+}
+
+static void __init
+sandpoint_find_bridges(void)
+{
+	struct pci_controller	*hose;
+
+	hose = pcibios_alloc_controller();
+
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	if (mpc10x_bridge_init(hose,
+			       MPC10X_MEM_MAP_B,
+			       MPC10X_MEM_MAP_B,
+			       MPC10X_MAPB_EUMB_BASE) == 0) {
+
+		/* Do early winbond init, then scan PCI bus */
+		sandpoint_setup_winbond_83553(hose);
+		hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+		ppc_md.pcibios_fixup = NULL;
+		ppc_md.pcibios_fixup_bus = NULL;
+		ppc_md.pci_swizzle = common_swizzle;
+		if (sandpoint_is_x2) {
+			ppc_md.pci_map_irq = x2_map_irq;
+			ppc_md.pci_exclude_device = x2_exclude_device;
+		} else
+			ppc_md.pci_map_irq = x3_map_irq;
+	}
+	else {
+		if (ppc_md.progress)
+			ppc_md.progress("Bridge init failed", 0x100);
+		printk("Host bridge init failed\n");
+	}
+
+	return;
+}
+
+static void __init
+sandpoint_setup_arch(void)
+{
+	/* Probe for Sandpoint model */
+	sandpoint_probe_type();
+	if (sandpoint_is_x2)
+		epic_serial_mode = 0;
+
+	loops_per_jiffy = 100000000 / HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef	CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+
+	/* Lookup PCI host bridges */
+	sandpoint_find_bridges();
+
+	printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n");
+	printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+
+	/* DINK32 12.3 and below do not correctly enable any caches.
+	 * We will do this now with good known values.  Future versions
+	 * of DINK32 are supposed to get this correct.
+	 */
+	if (cpu_has_feature(CPU_FTR_SPEC7450))
+		/* 745x is different.  We only want to pass along enable. */
+		_set_L2CR(L2CR_L2E);
+	else if (cpu_has_feature(CPU_FTR_L2CR))
+		/* All modules have 1MB of L2.  We also assume that an
+		 * L2 divisor of 3 will work.
+		 */
+		_set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3
+				| L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
+#if 0
+	/* Untested right now. */
+	if (cpu_has_feature(CPU_FTR_L3CR)) {
+		/* Magic value. */
+		_set_L3CR(0x8f032000);
+	}
+#endif
+}
+
+#define	SANDPOINT_87308_CFG_ADDR		0x15c
+#define	SANDPOINT_87308_CFG_DATA		0x15d
+
+#define	SANDPOINT_87308_CFG_INB(addr, byte) {				\
+	outb((addr), SANDPOINT_87308_CFG_ADDR);				\
+	(byte) = inb(SANDPOINT_87308_CFG_DATA);				\
+}
+
+#define	SANDPOINT_87308_CFG_OUTB(addr, byte) {				\
+	outb((addr), SANDPOINT_87308_CFG_ADDR);				\
+	outb((byte), SANDPOINT_87308_CFG_DATA);				\
+}
+
+#define SANDPOINT_87308_SELECT_DEV(dev_num) {				\
+	SANDPOINT_87308_CFG_OUTB(0x07, (dev_num));			\
+}
+
+#define	SANDPOINT_87308_DEV_ENABLE(dev_num) {				\
+	SANDPOINT_87308_SELECT_DEV(dev_num);				\
+	SANDPOINT_87308_CFG_OUTB(0x30, 0x01);				\
+}
+
+/*
+ * To probe the Sandpoint type, we need to check for a connection between GPIO
+ * pins 6 and 7 on the NS87308 SuperIO.
+ */
+static void __init sandpoint_probe_type(void)
+{
+	u8 x;
+	/* First, ensure that the GPIO pins are enabled. */
+	SANDPOINT_87308_SELECT_DEV(0x07); /* Select GPIO logical device */
+	SANDPOINT_87308_CFG_OUTB(0x60, 0x07); /* Base address 0x700 */
+	SANDPOINT_87308_CFG_OUTB(0x61, 0x00);
+	SANDPOINT_87308_CFG_OUTB(0x30, 0x01); /* Enable */
+
+	/* Now, set pin 7 to output and pin 6 to input. */
+	outb((inb(0x701) | 0x80) & 0xbf, 0x701);
+	/* Set push-pull output */
+	outb(inb(0x702) | 0x80, 0x702);
+	/* Set pull-up on input */
+	outb(inb(0x703) | 0x40, 0x703);
+	/* Set output high and check */
+	x = inb(0x700);
+	outb(x | 0x80, 0x700);
+	x = inb(0x700);
+	sandpoint_is_x2 = ! (x & 0x40);
+	if (ppc_md.progress && sandpoint_is_x2)
+		ppc_md.progress("High output says X2", 0);
+	/* Set output low and check */
+	outb(x & 0x7f, 0x700);
+	sandpoint_is_x2 |= inb(0x700) & 0x40;
+	if (ppc_md.progress && sandpoint_is_x2)
+		ppc_md.progress("Low output says X2", 0);
+	if (ppc_md.progress && ! sandpoint_is_x2)
+		ppc_md.progress("Sandpoint is X3", 0);
+}
+
+/*
+ * Fix IDE interrupts.
+ */
+static int __init
+sandpoint_fix_winbond_83553(void)
+{
+	/* Make some 8259 interrupt level sensitive */
+	outb(0xe0, 0x4d0);
+	outb(0xde, 0x4d1);
+
+	return 0;
+}
+
+arch_initcall(sandpoint_fix_winbond_83553);
+
+/*
+ * Initialize the ISA devices on the Nat'l PC87308VUL SuperIO chip.
+ */
+static int __init
+sandpoint_setup_natl_87308(void)
+{
+	u_char	reg;
+
+	/*
+	 * Enable all the devices on the Super I/O chip.
+	 */
+	SANDPOINT_87308_SELECT_DEV(0x00); /* Select kbd logical device */
+	SANDPOINT_87308_CFG_OUTB(0xf0, 0x00); /* Set KBC clock to 8 Mhz */
+	SANDPOINT_87308_DEV_ENABLE(0x00); /* Enable keyboard */
+	SANDPOINT_87308_DEV_ENABLE(0x01); /* Enable mouse */
+	SANDPOINT_87308_DEV_ENABLE(0x02); /* Enable rtc */
+	SANDPOINT_87308_DEV_ENABLE(0x03); /* Enable fdc (floppy) */
+	SANDPOINT_87308_DEV_ENABLE(0x04); /* Enable parallel */
+	SANDPOINT_87308_DEV_ENABLE(0x05); /* Enable UART 2 */
+	SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
+	SANDPOINT_87308_DEV_ENABLE(0x06); /* Enable UART 1 */
+	SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
+
+	/* Set up floppy in PS/2 mode */
+	outb(0x09, SIO_CONFIG_RA);
+	reg = inb(SIO_CONFIG_RD);
+	reg = (reg & 0x3F) | 0x40;
+	outb(reg, SIO_CONFIG_RD);
+	outb(reg, SIO_CONFIG_RD);	/* Have to write twice to change! */
+
+	return 0;
+}
+
+arch_initcall(sandpoint_setup_natl_87308);
+
+static int __init
+sandpoint_request_io(void)
+{
+	request_region(0x00,0x20,"dma1");
+	request_region(0x20,0x20,"pic1");
+	request_region(0x40,0x20,"timer");
+	request_region(0x80,0x10,"dma page reg");
+	request_region(0xa0,0x20,"pic2");
+	request_region(0xc0,0x20,"dma2");
+
+	return 0;
+}
+
+arch_initcall(sandpoint_request_io);
+
+/*
+ * Interrupt setup and service.  Interrrupts on the Sandpoint come
+ * from the four PCI slots plus the 8259 in the Winbond Super I/O (SIO).
+ * The 8259 is cascaded from EPIC IRQ0, IRQ1-4 map to PCI slots 1-4,
+ * IDE is on EPIC 7 and 8.
+ */
+static void __init
+sandpoint_init_IRQ(void)
+{
+	int i;
+
+	OpenPIC_InitSenses = sandpoint_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof(sandpoint_openpic_initsenses);
+
+	mpc10x_set_openpic();
+	openpic_hookup_cascade(sandpoint_is_x2 ? 17 : NUM_8259_INTERRUPTS, "82c59 cascade",
+			i8259_irq);
+
+	/*
+	 * openpic_init() has set up irq_desc[16-31] to be openpic
+	 * interrupts.  We need to set irq_desc[0-15] to be i8259
+	 * interrupts.
+	 */
+	for(i=0; i < NUM_8259_INTERRUPTS; i++)
+		irq_desc[i].handler = &i8259_pic;
+
+	/*
+	 * The EPIC allows for a read in the range of 0xFEF00000 ->
+	 * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction.
+	 */
+	i8259_init(0xfef00000);
+}
+
+static u32
+sandpoint_irq_canonicalize(u32 irq)
+{
+	if (irq == 2)
+		return 9;
+	else
+		return irq;
+}
+
+static unsigned long __init
+sandpoint_find_end_of_memory(void)
+{
+	bd_t *bp = (bd_t *)__res;
+
+	if (bp->bi_memsize)
+		return bp->bi_memsize;
+
+	/* DINK32 13.0 correctly initalizes things, so iff you use
+	 * this you _should_ be able to change this instead of a
+	 * hardcoded value. */
+#if 0
+	return mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
+#else
+	return 32*1024*1024;
+#endif
+}
+
+static void __init
+sandpoint_map_io(void)
+{
+	io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+}
+
+static void
+sandpoint_restart(char *cmd)
+{
+	local_irq_disable();
+
+	/* Set exception prefix high - to the firmware */
+	_nmask_and_or_msr(0, MSR_IP);
+
+	/* Reset system via Port 92 */
+	outb(0x00, 0x92);
+	outb(0x01, 0x92);
+	for(;;);	/* Spin until reset happens */
+}
+
+static void
+sandpoint_power_off(void)
+{
+	local_irq_disable();
+	for(;;);	/* No way to shut power off with software */
+	/* NOTREACHED */
+}
+
+static void
+sandpoint_halt(void)
+{
+	sandpoint_power_off();
+	/* NOTREACHED */
+}
+
+static int
+sandpoint_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: Motorola SPS\n");
+	seq_printf(m, "machine\t\t: Sandpoint\n");
+
+	return 0;
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE support.
+ */
+static int		sandpoint_ide_ports_known = 0;
+static unsigned long	sandpoint_ide_regbase[MAX_HWIFS];
+static unsigned long	sandpoint_ide_ctl_regbase[MAX_HWIFS];
+static unsigned long	sandpoint_idedma_regbase;
+
+static void
+sandpoint_ide_probe(void)
+{
+	struct pci_dev *pdev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+			PCI_DEVICE_ID_WINBOND_82C105, NULL);
+
+	if (pdev) {
+		sandpoint_ide_regbase[0]=pdev->resource[0].start;
+		sandpoint_ide_regbase[1]=pdev->resource[2].start;
+		sandpoint_ide_ctl_regbase[0]=pdev->resource[1].start;
+		sandpoint_ide_ctl_regbase[1]=pdev->resource[3].start;
+		sandpoint_idedma_regbase=pdev->resource[4].start;
+		pci_dev_put(pdev);
+	}
+
+	sandpoint_ide_ports_known = 1;
+}
+
+static int
+sandpoint_ide_default_irq(unsigned long base)
+{
+	if (sandpoint_ide_ports_known == 0)
+		sandpoint_ide_probe();
+
+	if (base == sandpoint_ide_regbase[0])
+		return SANDPOINT_IDE_INT0;
+	else if (base == sandpoint_ide_regbase[1])
+		return SANDPOINT_IDE_INT1;
+	else
+		return 0;
+}
+
+static unsigned long
+sandpoint_ide_default_io_base(int index)
+{
+	if (sandpoint_ide_ports_known == 0)
+		sandpoint_ide_probe();
+
+	return sandpoint_ide_regbase[index];
+}
+
+static void __init
+sandpoint_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+		unsigned long ctrl_port, int *irq)
+{
+	unsigned long reg = data_port;
+	uint	alt_status_base;
+	int	i;
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg++;
+	}
+
+	if (data_port == sandpoint_ide_regbase[0]) {
+		alt_status_base = sandpoint_ide_ctl_regbase[0] + 2;
+		hw->irq = 14;
+	}
+	else if (data_port == sandpoint_ide_regbase[1]) {
+		alt_status_base = sandpoint_ide_ctl_regbase[1] + 2;
+		hw->irq = 15;
+	}
+	else {
+		alt_status_base = 0;
+		hw->irq = 0;
+	}
+
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
+	}
+
+	if (irq != NULL) {
+		*irq = hw->irq;
+	}
+}
+#endif
+
+/*
+ * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
+ */
+static __inline__ void
+sandpoint_set_bat(void)
+{
+	unsigned long bat3u, bat3l;
+
+	__asm__ __volatile__(
+			" lis %0,0xf800\n	\
+			ori %1,%0,0x002a\n	\
+			ori %0,%0,0x0ffe\n	\
+			mtspr 0x21e,%0\n	\
+			mtspr 0x21f,%1\n	\
+			isync\n			\
+			sync "
+			: "=r" (bat3u), "=r" (bat3l));
+}
+
+TODC_ALLOC();
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+		unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	/* ASSUMPTION:  If both r3 (bd_t pointer) and r6 (cmdline pointer)
+	 * are non-zero, then we should use the board info from the bd_t
+	 * structure and the cmdline pointed to by r6 instead of the
+	 * information from birecs, if any.  Otherwise, use the information
+	 * from birecs as discovered by the preceeding call to
+	 * parse_bootinfo().  This rule should work with both PPCBoot, which
+	 * uses a bd_t board info structure, and the kernel boot wrapper,
+	 * which uses birecs.
+	 */
+	if (r3 && r6) {
+		/* copy board info structure */
+		memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+		/* copy command line */
+		*(char *)(r7+KERNELBASE) = 0;
+		strcpy(cmd_line, (char *)(r6+KERNELBASE));
+	}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* take care of initrd if we have one */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	/* Map in board regs, etc. */
+	sandpoint_set_bat();
+
+	isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
+	isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
+	pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
+	ISA_DMA_THRESHOLD = 0x00ffffff;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+
+	ppc_md.setup_arch = sandpoint_setup_arch;
+	ppc_md.show_cpuinfo = sandpoint_show_cpuinfo;
+	ppc_md.irq_canonicalize = sandpoint_irq_canonicalize;
+	ppc_md.init_IRQ = sandpoint_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+
+	ppc_md.restart = sandpoint_restart;
+	ppc_md.power_off = sandpoint_power_off;
+	ppc_md.halt = sandpoint_halt;
+
+	ppc_md.find_end_of_memory = sandpoint_find_end_of_memory;
+	ppc_md.setup_io_mappings = sandpoint_map_io;
+
+	TODC_INIT(TODC_TYPE_PC97307, 0x70, 0x00, 0x71, 8);
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.calibrate_decr = todc_calibrate_decr;
+
+	ppc_md.nvram_read_val = todc_mc146818_read_val;
+	ppc_md.nvram_write_val = todc_mc146818_write_val;
+
+#ifdef CONFIG_KGDB
+	ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = gen550_progress;
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+	ppc_ide_md.default_irq = sandpoint_ide_default_irq;
+	ppc_ide_md.default_io_base = sandpoint_ide_default_io_base;
+	ppc_ide_md.ide_init_hwif = sandpoint_ide_init_hwif_ports;
+#endif
+}
diff --git a/arch/ppc/platforms/sandpoint.h b/arch/ppc/platforms/sandpoint.h
new file mode 100644
index 0000000..f4e982cb
--- /dev/null
+++ b/arch/ppc/platforms/sandpoint.h
@@ -0,0 +1,80 @@
+/*
+ * arch/ppc/platforms/sandpoint.h
+ *
+ * Definitions for Motorola SPS Sandpoint Test Platform
+ *
+ * Author: Mark A. Greer
+ *         mgreer@mvista.com
+ *
+ * 2000-2003 (c) MontaVista, Software, Inc.  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.
+ */
+
+/*
+ * Sandpoint uses the CHRP map (Map B).
+ */
+
+#ifndef __PPC_PLATFORMS_SANDPOINT_H
+#define __PPC_PLATFORMS_SANDPOINT_H
+
+#include <asm/ppcboot.h>
+
+#if 0
+/* The Sandpoint X3 allows the IDE interrupt to be directly connected
+ * from the Windbond (PCI INTC or INTD) to the serial EPIC.  Someday
+ * we should try this, but it was easier to use the existing 83c553
+ * initialization than change it to route the different interrupts :-).
+ *	-- Dan
+ */
+#define SANDPOINT_IDE_INT0		23	/* EPIC 7 */
+#define SANDPOINT_IDE_INT1		24	/* EPIC 8 */
+#else
+#define SANDPOINT_IDE_INT0		14	/* 8259 Test */
+#define SANDPOINT_IDE_INT1		15	/* 8259 Test */
+#endif
+
+/*
+ * The sandpoint boards have processor modules that either have an 8240 or
+ * an MPC107 host bridge on them.  These bridges have an IDSEL line that allows
+ * them to respond to PCI transactions as if they were a normal PCI devices.
+ * However, the processor on the processor side of the bridge can not reach
+ * out onto the PCI bus and then select the bridge or bad things will happen
+ * (documented in the 8240 and 107 manuals).
+ * Because of this, we always skip the bridge PCI device when accessing the
+ * PCI bus.  The PCI slot that the bridge occupies is defined by the macro
+ * below.
+ */
+#define SANDPOINT_HOST_BRIDGE_IDSEL     12
+
+/*
+ * Serial defines.
+ */
+#define SANDPOINT_SERIAL_0		0xfe0003f8
+#define SANDPOINT_SERIAL_1		0xfe0002f8
+
+#define RS_TABLE_SIZE  2
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD			( 1843200 / 16 )
+#define UART_CLK			1843200
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, SANDPOINT_SERIAL_0, 4, STD_COM_FLAGS, /* ttyS0 */ \
+		iomem_base: (u8 *)SANDPOINT_SERIAL_0,			  \
+		io_type: SERIAL_IO_MEM },				  \
+        { 0, BASE_BAUD, SANDPOINT_SERIAL_1, 3, STD_COM_FLAGS, /* ttyS1 */ \
+		iomem_base: (u8 *)SANDPOINT_SERIAL_1,			  \
+		io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
+
+#endif /* __PPC_PLATFORMS_SANDPOINT_H */
diff --git a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c
new file mode 100644
index 0000000..74c9ff7
--- /dev/null
+++ b/arch/ppc/platforms/sbc82xx.c
@@ -0,0 +1,259 @@
+/*
+ * arch/ppc/platforms/sbc82xx.c
+ *
+ * SBC82XX platform support
+ *
+ * Author: Guy Streeter <streeter@redhat.com>
+ *
+ * Derived from: est8260_setup.c by Allen Curtis, ONZ
+ *
+ * Copyright 2004 Red Hat, 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/stddef.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/mpc8260.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/todc.h>
+#include <asm/immap_cpm2.h>
+#include <asm/pci.h>
+
+static void (*callback_init_IRQ)(void);
+
+extern unsigned char __res[sizeof(bd_t)];
+
+extern void (*late_time_init)(void);
+
+#ifdef CONFIG_GEN_RTC
+TODC_ALLOC();
+
+/*
+ * Timer init happens before mem_init but after paging init, so we cannot
+ * directly use ioremap() at that time.
+ * late_time_init() is call after paging init.
+ */
+
+static void sbc82xx_time_init(void)
+{
+	volatile memctl_cpm2_t *mc = &cpm2_immr->im_memctl;
+
+	/* Set up CS11 for RTC chip */
+	mc->memc_br11=0;
+	mc->memc_or11=0xffff0836;
+	mc->memc_br11=SBC82xx_TODC_NVRAM_ADDR | 0x0801;
+
+	TODC_INIT(TODC_TYPE_MK48T59, 0, 0, SBC82xx_TODC_NVRAM_ADDR, 0);
+
+	todc_info->nvram_data =
+		(unsigned int)ioremap(todc_info->nvram_data, 0x2000);
+	BUG_ON(!todc_info->nvram_data);
+	ppc_md.get_rtc_time	= todc_get_rtc_time;
+	ppc_md.set_rtc_time	= todc_set_rtc_time;
+	ppc_md.nvram_read_val	= todc_direct_read_val;
+	ppc_md.nvram_write_val	= todc_direct_write_val;
+	todc_time_init();
+}
+#endif /* CONFIG_GEN_RTC */
+
+static volatile char *sbc82xx_i8259_map;
+static char sbc82xx_i8259_mask = 0xff;
+static DEFINE_SPINLOCK(sbc82xx_i8259_lock);
+
+static void sbc82xx_i8259_mask_and_ack_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+
+	irq_nr -= NR_SIU_INTS;
+
+	spin_lock_irqsave(&sbc82xx_i8259_lock, flags);
+	sbc82xx_i8259_mask |= 1 << irq_nr;
+	(void) sbc82xx_i8259_map[1];	/* Dummy read */
+	sbc82xx_i8259_map[1] = sbc82xx_i8259_mask;
+	sbc82xx_i8259_map[0] = 0x20;	/* OCW2: Non-specific EOI */
+	spin_unlock_irqrestore(&sbc82xx_i8259_lock, flags);
+}
+
+static void sbc82xx_i8259_mask_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+
+	irq_nr -= NR_SIU_INTS;
+
+	spin_lock_irqsave(&sbc82xx_i8259_lock, flags);
+	sbc82xx_i8259_mask |= 1 << irq_nr;
+	sbc82xx_i8259_map[1] = sbc82xx_i8259_mask;
+	spin_unlock_irqrestore(&sbc82xx_i8259_lock, flags);
+}
+
+static void sbc82xx_i8259_unmask_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+
+	irq_nr -= NR_SIU_INTS;
+
+	spin_lock_irqsave(&sbc82xx_i8259_lock, flags);
+	sbc82xx_i8259_mask &= ~(1 << irq_nr);
+	sbc82xx_i8259_map[1] = sbc82xx_i8259_mask;
+	spin_unlock_irqrestore(&sbc82xx_i8259_lock, flags);
+}
+
+static void sbc82xx_i8259_end_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))
+	    && irq_desc[irq].action)
+		sbc82xx_i8259_unmask_irq(irq);
+}
+
+
+struct hw_interrupt_type sbc82xx_i8259_ic = {
+	.typename = " i8259     ",
+	.enable = sbc82xx_i8259_unmask_irq,
+	.disable = sbc82xx_i8259_mask_irq,
+	.ack = sbc82xx_i8259_mask_and_ack_irq,
+	.end = sbc82xx_i8259_end_irq,
+};
+
+static irqreturn_t sbc82xx_i8259_demux(int irq, void *dev_id, struct pt_regs *regs)
+{
+	spin_lock(&sbc82xx_i8259_lock);
+
+	sbc82xx_i8259_map[0] = 0x0c;	/* OCW3: Read IR register on RD# pulse */
+	irq = sbc82xx_i8259_map[0] & 7;	/* Read IRR */
+
+	if (irq == 7) {
+		/* Possible spurious interrupt */
+		int isr;
+		sbc82xx_i8259_map[0] = 0x0b;	/* OCW3: Read IS register on RD# pulse */
+		isr = sbc82xx_i8259_map[0];	/* Read ISR */
+
+		if (!(isr & 0x80)) {
+			printk(KERN_INFO "Spurious i8259 interrupt\n");
+			return IRQ_HANDLED;
+		}
+	}
+	__do_IRQ(NR_SIU_INTS + irq, regs);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction sbc82xx_i8259_irqaction = {
+	.handler = sbc82xx_i8259_demux,
+	.flags = SA_INTERRUPT,
+	.mask = CPU_MASK_NONE,
+	.name = "i8259 demux",
+};
+
+void __init sbc82xx_init_IRQ(void)
+{
+	volatile memctl_cpm2_t *mc = &cpm2_immr->im_memctl;
+	volatile intctl_cpm2_t *ic = &cpm2_immr->im_intctl;
+	int i;
+
+	callback_init_IRQ();
+
+	/* u-boot doesn't always set the board up correctly */
+	mc->memc_br5 = 0;
+	mc->memc_or5 = 0xfff00856;
+	mc->memc_br5 = 0x22000801;
+
+	sbc82xx_i8259_map = ioremap(0x22008000, 2);
+	if (!sbc82xx_i8259_map) {
+		printk(KERN_CRIT "Mapping i8259 interrupt controller failed\n");
+		return;
+	}
+	
+	/* Set up the interrupt handlers for the i8259 IRQs */
+	for (i = NR_SIU_INTS; i < NR_SIU_INTS + 8; i++) {
+                irq_desc[i].handler = &sbc82xx_i8259_ic;
+		irq_desc[i].status |= IRQ_LEVEL;
+	}
+
+	/* make IRQ6 level sensitive */
+	ic->ic_siexr &= ~(1 << (14 - (SIU_INT_IRQ6 - SIU_INT_IRQ1)));
+	irq_desc[SIU_INT_IRQ6].status |= IRQ_LEVEL;
+
+	/* Initialise the i8259 */
+	sbc82xx_i8259_map[0] = 0x1b;	/* ICW1: Level, no cascade, ICW4 */
+	sbc82xx_i8259_map[1] = 0x00;	/* ICW2: vector base */
+					/* No ICW3 (no cascade) */
+	sbc82xx_i8259_map[1] = 0x01;	/* ICW4: 8086 mode, normal EOI */
+
+	sbc82xx_i8259_map[0] = 0x0b;	/* OCW3: Read IS register on RD# pulse */
+
+	sbc82xx_i8259_map[1] = sbc82xx_i8259_mask; /* Set interrupt mask */
+
+	/* Request cascade IRQ */
+	if (setup_irq(SIU_INT_IRQ6, &sbc82xx_i8259_irqaction)) {
+		printk("Installation of i8259 IRQ demultiplexer failed.\n");
+	}
+}
+
+static int sbc82xx_pci_map_irq(struct pci_dev *dev, unsigned char idsel,
+			       unsigned char pin)
+{
+	static char pci_irq_table[][4] = {
+		/*
+		 * PCI IDSEL/INTPIN->INTLINE
+		 *  A      B      C      D
+		 */
+		{ SBC82xx_PIRQA, SBC82xx_PIRQB, SBC82xx_PIRQC, SBC82xx_PIRQD },	/* IDSEL 16 - PMC slot */
+		{ SBC82xx_PC_IRQA, SBC82xx_PC_IRQB, -1,  -1  },			/* IDSEL 17 - CardBus */
+		{ SBC82xx_PIRQA, SBC82xx_PIRQB, SBC82xx_PIRQC, SBC82xx_PIRQD }, /* IDSEL 18 - PCI-X bridge */
+	};
+
+	const long min_idsel = 16, max_idsel = 18, irqs_per_slot = 4;
+
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void __devinit quirk_sbc8260_cardbus(struct pci_dev *pdev)
+{
+	uint32_t ctrl;
+
+	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(17, 0))
+		return;
+
+	printk(KERN_INFO "Setting up CardBus controller\n");
+
+	/* Set P2CCLK bit in System Control Register */
+	pci_read_config_dword(pdev, 0x80, &ctrl);
+	ctrl |= (1<<27);
+	pci_write_config_dword(pdev, 0x80, ctrl);
+
+	/* Set MFUNC up for PCI IRQ routing via INTA and INTB, and LEDs. */
+	pci_write_config_dword(pdev, 0x8c, 0x00c01d22);
+
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, quirk_sbc8260_cardbus);
+
+void __init
+m82xx_board_init(void)
+{
+	/* u-boot may be using one of the FCC Ethernet devices.
+	   Use the MAC address to the SCC. */
+	__res[offsetof(bd_t, bi_enetaddr[5])] &= ~3;
+
+	/* Anything special for this platform */
+	callback_init_IRQ	= ppc_md.init_IRQ;
+
+	ppc_md.init_IRQ		= sbc82xx_init_IRQ;
+	ppc_md.pci_map_irq	= sbc82xx_pci_map_irq;
+#ifdef CONFIG_GEN_RTC
+	ppc_md.time_init        = NULL;
+	ppc_md.get_rtc_time     = NULL;
+	ppc_md.set_rtc_time     = NULL;
+	ppc_md.nvram_read_val   = NULL;
+	ppc_md.nvram_write_val  = NULL;
+	late_time_init		= sbc82xx_time_init;
+#endif /* CONFIG_GEN_RTC */
+}
diff --git a/arch/ppc/platforms/sbc82xx.h b/arch/ppc/platforms/sbc82xx.h
new file mode 100644
index 0000000..e4042d4
--- /dev/null
+++ b/arch/ppc/platforms/sbc82xx.h
@@ -0,0 +1,36 @@
+/* Board information for the SBCPowerQUICCII, which should be generic for
+ * all 8260 boards.  The IMMR is now given to us so the hard define
+ * will soon be removed.  All of the clock values are computed from
+ * the configuration SCMR and the Power-On-Reset word.
+ */
+
+#ifndef __PPC_SBC82xx_H__
+#define __PPC_SBC82xx_H__
+
+#include <asm/ppcboot.h>
+
+#define CPM_MAP_ADDR			0xf0000000
+
+#define SBC82xx_TODC_NVRAM_ADDR		0xd0000000
+
+#define SBC82xx_MACADDR_NVRAM_FCC1	0x220000c9	/* JP6B */
+#define SBC82xx_MACADDR_NVRAM_SCC1	0x220000cf	/* JP6A */
+#define SBC82xx_MACADDR_NVRAM_FCC2	0x220000d5	/* JP7A */
+#define SBC82xx_MACADDR_NVRAM_FCC3	0x220000db	/* JP7B */
+
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"Wind River"
+#define CPUINFO_MACHINE		"SBC PowerQUICC II"
+
+#define BOOTROM_RESTART_ADDR      ((uint)0x40000104)
+
+#define SBC82xx_PC_IRQA (NR_SIU_INTS+0)
+#define SBC82xx_PC_IRQB (NR_SIU_INTS+1)
+#define SBC82xx_MPC185_IRQ (NR_SIU_INTS+2)
+#define SBC82xx_ATM_IRQ (NR_SIU_INTS+3)
+#define SBC82xx_PIRQA (NR_SIU_INTS+4)
+#define SBC82xx_PIRQB (NR_SIU_INTS+5)
+#define SBC82xx_PIRQC (NR_SIU_INTS+6)
+#define SBC82xx_PIRQD (NR_SIU_INTS+7)
+
+#endif /* __PPC_SBC82xx_H__ */
diff --git a/arch/ppc/platforms/sbs8260.h b/arch/ppc/platforms/sbs8260.h
new file mode 100644
index 0000000..d51427a
--- /dev/null
+++ b/arch/ppc/platforms/sbs8260.h
@@ -0,0 +1,28 @@
+#ifndef __ASSEMBLY__
+/* Board information for various SBS 8260 cards, which should be generic for
+ * all 8260 boards.  The IMMR is now given to us so the hard define
+ * will soon be removed.  All of the clock values are computed from
+ * the configuration SCMR and the Power-On-Reset word.
+ */
+
+#define CPM_MAP_ADDR	((uint)0xfe000000)
+
+
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in MHz */
+	unsigned int	bi_cpmfreq;	/* CPM Freq, in MHz */
+	unsigned int	bi_brgfreq;	/* BRG Freq, in MHz */
+	unsigned int	bi_vco;		/* VCO Out from PLL */
+	unsigned int	bi_baudrate;	/* Default console baud rate */
+	unsigned int	bi_immr;	/* IMMR when called from boot rom */
+	unsigned char	bi_enetaddr[6];
+} bd_t;
+
+extern bd_t m8xx_board_info;
+#endif /* !__ASSEMBLY__ */
diff --git a/arch/ppc/platforms/spd8xx.h b/arch/ppc/platforms/spd8xx.h
new file mode 100644
index 0000000..ed48d14
--- /dev/null
+++ b/arch/ppc/platforms/spd8xx.h
@@ -0,0 +1,92 @@
+/*
+ * Speech Design SPD8xxTS board specific definitions
+ *
+ * Copyright (c) 2000,2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_SPD8XX_H__
+#define __ASM_SPD8XX_H__
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#ifndef __ASSEMBLY__
+#define SPD_IMMR_BASE	0xFFF00000	/* phys. addr of IMMR */
+#define SPD_IMAP_SIZE	(64 * 1024)	/* size of mapped area */
+
+#define IMAP_ADDR	SPD_IMMR_BASE	/* physical base address of IMMR area */
+#define IMAP_SIZE	SPD_IMAP_SIZE	/* mapped size of IMMR area */
+
+#define PCMCIA_MEM_ADDR	((uint)0xFE100000)
+#define PCMCIA_MEM_SIZE	((uint)(64 * 1024))
+
+#define IDE0_INTERRUPT	10		/* = IRQ5 */
+#define IDE1_INTERRUPT	12		/* = IRQ6 */
+#define CPM_INTERRUPT	13		/* = SIU_LEVEL6 (was: SIU_LEVEL2) */
+
+/* override the default number of IDE hardware interfaces */
+#define MAX_HWIFS	2
+
+/*
+ * Definitions for IDE0 Interface
+ */
+#define IDE0_BASE_OFFSET		0x0000	/* Offset in PCMCIA memory */
+#define IDE0_DATA_REG_OFFSET		0x0000
+#define IDE0_ERROR_REG_OFFSET		0x0081
+#define IDE0_NSECTOR_REG_OFFSET		0x0082
+#define IDE0_SECTOR_REG_OFFSET		0x0083
+#define IDE0_LCYL_REG_OFFSET		0x0084
+#define IDE0_HCYL_REG_OFFSET		0x0085
+#define IDE0_SELECT_REG_OFFSET		0x0086
+#define IDE0_STATUS_REG_OFFSET		0x0087
+#define IDE0_CONTROL_REG_OFFSET		0x0106
+#define IDE0_IRQ_REG_OFFSET		0x000A	/* not used */
+
+/*
+ * Definitions for IDE1 Interface
+ */
+#define IDE1_BASE_OFFSET		0x0C00	/* Offset in PCMCIA memory */
+#define IDE1_DATA_REG_OFFSET		0x0000
+#define IDE1_ERROR_REG_OFFSET		0x0081
+#define IDE1_NSECTOR_REG_OFFSET		0x0082
+#define IDE1_SECTOR_REG_OFFSET		0x0083
+#define IDE1_LCYL_REG_OFFSET		0x0084
+#define IDE1_HCYL_REG_OFFSET		0x0085
+#define IDE1_SELECT_REG_OFFSET		0x0086
+#define IDE1_STATUS_REG_OFFSET		0x0087
+#define IDE1_CONTROL_REG_OFFSET		0x0106
+#define IDE1_IRQ_REG_OFFSET		0x000A	/* not used */
+
+/* CPM Ethernet through SCCx.
+ *
+ * Bits in parallel I/O port registers that have to be set/cleared
+ * to configure the pins for SCC2 use.
+ */
+#define PA_ENET_MDC	((ushort)0x0001)	/* PA 15 !!! */
+#define PA_ENET_MDIO	((ushort)0x0002)	/* PA 14 !!! */
+#define PA_ENET_RXD	((ushort)0x0004)	/* PA 13 */
+#define PA_ENET_TXD	((ushort)0x0008)	/* PA 12 */
+#define PA_ENET_RCLK	((ushort)0x0200)	/* PA  6 */
+#define PA_ENET_TCLK	((ushort)0x0400)	/* PA  5 */
+
+#define PB_ENET_TENA	((uint)0x00002000)	/* PB 18 */
+
+#define PC_ENET_CLSN	((ushort)0x0040)	/* PC  9 */
+#define PC_ENET_RENA	((ushort)0x0080)	/* PC  8 */
+#define PC_ENET_RESET	((ushort)0x0100)	/* PC  7 !!! */
+
+/* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK2) to
+ * SCC2.  Also, make sure GR2 (bit 16) and SC2 (bit 17) are zero.
+ */
+#define SICR_ENET_MASK	((uint)0x0000ff00)
+#define SICR_ENET_CLKRT	((uint)0x00002E00)
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_SPD8XX_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c
new file mode 100644
index 0000000..5ad70d3
--- /dev/null
+++ b/arch/ppc/platforms/spruce.c
@@ -0,0 +1,325 @@
+/*
+ * arch/ppc/platforms/spruce.c
+ *
+ * Board and PCI setup routines for IBM Spruce
+ *
+ * Author: MontaVista Software <source@mvista.com>
+ *
+ * 2000-2004 (c) MontaVista, Software, Inc.  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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/ide.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/kgdb.h>
+
+#include <syslib/cpc700.h>
+
+#include "spruce.h"
+
+static inline int
+spruce_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+		/*
+		 * 	PCI IDSEL/INTPIN->INTLINE
+		 * 	A	B	C	D
+		 */
+	{
+		{23, 24, 25, 26},	/* IDSEL 1 - PCI slot 3 */
+		{24, 25, 26, 23},	/* IDSEL 2 - PCI slot 2 */
+		{25, 26, 23, 24},	/* IDSEL 3 - PCI slot 1 */
+		{26, 23, 24, 25},	/* IDSEL 4 - PCI slot 0 */
+	};
+
+	const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void __init
+spruce_setup_hose(void)
+{
+	struct pci_controller *hose;
+
+	/* Setup hose */
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	pci_init_resource(&hose->io_resource,
+			SPRUCE_PCI_LOWER_IO,
+			SPRUCE_PCI_UPPER_IO,
+			IORESOURCE_IO,
+			"PCI host bridge");
+
+	pci_init_resource(&hose->mem_resources[0],
+			SPRUCE_PCI_LOWER_MEM,
+			SPRUCE_PCI_UPPER_MEM,
+			IORESOURCE_MEM,
+			"PCI host bridge");
+
+	hose->io_space.start = SPRUCE_PCI_LOWER_IO;
+	hose->io_space.end = SPRUCE_PCI_UPPER_IO;
+	hose->mem_space.start = SPRUCE_PCI_LOWER_MEM;
+	hose->mem_space.end = SPRUCE_PCI_UPPER_MEM;
+	hose->io_base_virt = (void *)SPRUCE_ISA_IO_BASE;
+
+	setup_indirect_pci(hose,
+			SPRUCE_PCI_CONFIG_ADDR,
+			SPRUCE_PCI_CONFIG_DATA);
+
+	hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = spruce_map_irq;
+}
+
+/*
+ * CPC700 PIC interrupt programming table
+ *
+ * First entry is the sensitivity (level/edge), second is the polarity.
+ */
+unsigned int cpc700_irq_assigns[32][2] = {
+	{ 1, 1 },       /* IRQ  0: ECC Correctable Error - rising edge */
+	{ 1, 1 },       /* IRQ  1: PCI Write Mem Range   - rising edge */
+	{ 0, 1 },       /* IRQ  2: PCI Write Command Reg - active high */
+	{ 0, 1 },       /* IRQ  3: UART 0                - active high */
+	{ 0, 1 },       /* IRQ  4: UART 1                - active high */
+	{ 0, 1 },       /* IRQ  5: ICC 0                 - active high */
+	{ 0, 1 },       /* IRQ  6: ICC 1                 - active high */
+	{ 0, 1 },       /* IRQ  7: GPT Compare 0         - active high */
+	{ 0, 1 },       /* IRQ  8: GPT Compare 1         - active high */
+	{ 0, 1 },       /* IRQ  9: GPT Compare 2         - active high */
+	{ 0, 1 },       /* IRQ 10: GPT Compare 3         - active high */
+	{ 0, 1 },       /* IRQ 11: GPT Compare 4         - active high */
+	{ 0, 1 },       /* IRQ 12: GPT Capture 0         - active high */
+	{ 0, 1 },       /* IRQ 13: GPT Capture 1         - active high */
+	{ 0, 1 },       /* IRQ 14: GPT Capture 2         - active high */
+	{ 0, 1 },       /* IRQ 15: GPT Capture 3         - active high */
+	{ 0, 1 },       /* IRQ 16: GPT Capture 4         - active high */
+	{ 0, 0 },       /* IRQ 17: Reserved */
+	{ 0, 0 },       /* IRQ 18: Reserved */
+	{ 0, 0 },       /* IRQ 19: Reserved */
+	{ 0, 1 },       /* IRQ 20: FPGA EXT_IRQ0         - active high */
+	{ 1, 1 },       /* IRQ 21: Mouse                 - rising edge */
+	{ 1, 1 },       /* IRQ 22: Keyboard              - rising edge */
+	{ 0, 0 },       /* IRQ 23: PCI Slot 3            - active low */
+	{ 0, 0 },       /* IRQ 24: PCI Slot 2            - active low */
+	{ 0, 0 },       /* IRQ 25: PCI Slot 1            - active low */
+	{ 0, 0 },       /* IRQ 26: PCI Slot 0            - active low */
+};
+
+static void __init
+spruce_calibrate_decr(void)
+{
+	int freq, divisor = 4;
+
+	/* determine processor bus speed */
+	freq = SPRUCE_BUS_SPEED;
+	tb_ticks_per_jiffy = freq / HZ / divisor;
+	tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+}
+
+static int
+spruce_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: IBM\n");
+	seq_printf(m, "machine\t\t: Spruce\n");
+
+	return 0;
+}
+
+static void __init
+spruce_early_serial_map(void)
+{
+	u32 uart_clk;
+	struct uart_port serial_req;
+
+	if (SPRUCE_UARTCLK_IS_33M(readb(SPRUCE_FPGA_REG_A)))
+		uart_clk = SPRUCE_BAUD_33M * 16;
+	else
+		uart_clk = SPRUCE_BAUD_30M * 16;
+
+	/* Setup serial port access */
+	memset(&serial_req, 0, sizeof(serial_req));
+	serial_req.uartclk = uart_clk;
+	serial_req.irq = UART0_INT;
+	serial_req.flags = ASYNC_BOOT_AUTOCONF;
+	serial_req.iotype = SERIAL_IO_MEM;
+	serial_req.membase = (u_char *)UART0_IO_BASE;
+	serial_req.regshift = 0;
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+	gen550_init(0, &serial_req);
+#endif
+#ifdef CONFIG_SERIAL_8250
+	if (early_serial_setup(&serial_req) != 0)
+		printk("Early serial init of port 0 failed\n");
+#endif
+
+	/* Assume early_serial_setup() doesn't modify serial_req */
+	serial_req.line = 1;
+	serial_req.irq = UART1_INT;
+	serial_req.membase = (u_char *)UART1_IO_BASE;
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+	gen550_init(1, &serial_req);
+#endif
+#ifdef CONFIG_SERIAL_8250
+	if (early_serial_setup(&serial_req) != 0)
+		printk("Early serial init of port 1 failed\n");
+#endif
+}
+
+TODC_ALLOC();
+
+static void __init
+spruce_setup_arch(void)
+{
+	/* Setup TODC access */
+	TODC_INIT(TODC_TYPE_DS1643, 0, 0, SPRUCE_RTC_BASE_ADDR, 8);
+
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000 / HZ;
+
+	/* Setup PCI host bridge */
+	spruce_setup_hose();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_SDA1;
+#endif
+
+	/* Identify the system */
+	printk(KERN_INFO "System Identification: IBM Spruce\n");
+	printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+}
+
+static void
+spruce_restart(char *cmd)
+{
+	local_irq_disable();
+
+	/* SRR0 has system reset vector, SRR1 has default MSR value */
+	/* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
+	__asm__ __volatile__
+	("\n\
+	lis	3,0xfff0	\n\
+	ori	3,3,0x0100	\n\
+	mtspr	26,3		\n\
+	li	3,0		\n\
+	mtspr	27,3		\n\
+	rfi			\n\
+	");
+	for(;;);
+}
+
+static void
+spruce_power_off(void)
+{
+	for(;;);
+}
+
+static void
+spruce_halt(void)
+{
+	spruce_restart(NULL);
+}
+
+static void __init
+spruce_map_io(void)
+{
+	io_block_mapping(SPRUCE_PCI_IO_BASE, SPRUCE_PCI_PHY_IO_BASE,
+			 0x08000000, _PAGE_IO);
+}
+
+/*
+ * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
+ */
+static __inline__ void
+spruce_set_bat(void)
+{
+	mb();
+	mtspr(SPRN_DBAT1U, 0xf8000ffe);
+	mtspr(SPRN_DBAT1L, 0xf800002a);
+	mb();
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	/* Map in board regs, etc. */
+	spruce_set_bat();
+
+	isa_io_base = SPRUCE_ISA_IO_BASE;
+	pci_dram_offset = SPRUCE_PCI_SYS_MEM_BASE;
+
+	ppc_md.setup_arch = spruce_setup_arch;
+	ppc_md.show_cpuinfo = spruce_show_cpuinfo;
+	ppc_md.init_IRQ = cpc700_init_IRQ;
+	ppc_md.get_irq = cpc700_get_irq;
+
+	ppc_md.setup_io_mappings = spruce_map_io;
+
+	ppc_md.restart = spruce_restart;
+	ppc_md.power_off = spruce_power_off;
+	ppc_md.halt = spruce_halt;
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.calibrate_decr = spruce_calibrate_decr;
+
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
+
+	spruce_early_serial_map();
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = gen550_progress;
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+#ifdef CONFIG_KGDB
+	ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
+}
diff --git a/arch/ppc/platforms/spruce.h b/arch/ppc/platforms/spruce.h
new file mode 100644
index 0000000..a31ff7e
--- /dev/null
+++ b/arch/ppc/platforms/spruce.h
@@ -0,0 +1,71 @@
+/*
+ * include/asm-ppc/platforms/spruce.h
+ *
+ * Definitions for IBM Spruce reference board support
+ *
+ * Authors: Matt Porter and Johnnie Peters
+ *          mporter@mvista.com
+ *          jpeters@mvista.com
+ *
+ * 2001 (c) MontaVista, Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_SPRUCE_H__
+#define __ASM_SPRUCE_H__
+
+#define SPRUCE_PCI_CONFIG_ADDR	0xfec00000
+#define SPRUCE_PCI_CONFIG_DATA	0xfec00004
+
+#define SPRUCE_PCI_PHY_IO_BASE	0xf8000000
+#define SPRUCE_PCI_IO_BASE	SPRUCE_PCI_PHY_IO_BASE
+
+#define SPRUCE_PCI_SYS_MEM_BASE	0x00000000
+
+#define SPRUCE_PCI_LOWER_MEM	0x80000000
+#define SPRUCE_PCI_UPPER_MEM	0x9fffffff
+#define SPRUCE_PCI_LOWER_IO	0x00000000
+#define SPRUCE_PCI_UPPER_IO	0x03ffffff
+
+#define	SPRUCE_ISA_IO_BASE	SPRUCE_PCI_IO_BASE
+
+#define SPRUCE_MEM_SIZE		0x04000000
+#define SPRUCE_BUS_SPEED	66666667
+
+#define SPRUCE_NVRAM_BASE_ADDR	0xff800000
+#define SPRUCE_RTC_BASE_ADDR	SPRUCE_NVRAM_BASE_ADDR
+
+/*
+ * Serial port defines
+ */
+#define SPRUCE_FPGA_REG_A	0xff820000
+#define SPRUCE_UARTCLK_33M	0x02
+#define SPRUCE_UARTCLK_IS_33M(reg)	(reg & SPRUCE_UARTCLK_33M)
+
+#define UART0_IO_BASE	0xff600300
+#define UART1_IO_BASE	0xff600400
+
+#define RS_TABLE_SIZE	2
+
+#define SPRUCE_BAUD_33M	(33000000/64)
+#define SPRUCE_BAUD_30M	(30000000/64)
+#define BASE_BAUD	SPRUCE_BAUD_33M
+
+#define UART0_INT	3
+#define UART1_INT	4
+
+#define STD_UART_OP(num)						\
+	{ 0, BASE_BAUD, 0, UART##num##_INT,				\
+		ASYNC_BOOT_AUTOCONF,					\
+		iomem_base: (unsigned char *) UART##num##_IO_BASE,	\
+		io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)
+
+#endif /* __ASM_SPRUCE_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/tqm8260.h b/arch/ppc/platforms/tqm8260.h
new file mode 100644
index 0000000..c7a78a6
--- /dev/null
+++ b/arch/ppc/platforms/tqm8260.h
@@ -0,0 +1,23 @@
+/*
+ * TQM8260 board specific definitions
+ *
+ * Copyright (c) 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __TQM8260_PLATFORM
+#define __TQM8260_PLATFORM
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define CPM_MAP_ADDR		((uint)0xFFF00000)
+#define PHY_INTERRUPT		25
+
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"IN2 Systems"
+#define CPUINFO_MACHINE		"TQM8260 PowerPC"
+
+#define BOOTROM_RESTART_ADDR	((uint)0x40000104)
+
+#endif	/* __TQM8260_PLATFORM */
diff --git a/arch/ppc/platforms/tqm8260_setup.c b/arch/ppc/platforms/tqm8260_setup.c
new file mode 100644
index 0000000..a8880bf
--- /dev/null
+++ b/arch/ppc/platforms/tqm8260_setup.c
@@ -0,0 +1,44 @@
+/*
+ * arch/ppc/platforms/tqm8260_setup.c
+ *
+ * TQM8260 platform support
+ *
+ * Author: Allen Curtis <acurtis@onz.com>
+ * Derived from: m8260_setup.c by Dan Malek, MVista
+ *
+ * Copyright 2002 Ones and Zeros, 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/init.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+#include <asm/machdep.h>
+
+static int
+tqm8260_set_rtc_time(unsigned long time)
+{
+	((cpm2_map_t *)CPM_MAP_ADDR)->im_sit.sit_tmcnt = time;
+	((cpm2_map_t *)CPM_MAP_ADDR)->im_sit.sit_tmcntsc = 0x3;
+
+	return(0);
+}
+
+static unsigned long
+tqm8260_get_rtc_time(void)
+{
+	return ((cpm2_map_t *)CPM_MAP_ADDR)->im_sit.sit_tmcnt;
+}
+
+void __init
+m82xx_board_init(void)
+{
+	/* Anything special for this platform */
+	ppc_md.set_rtc_time	= tqm8260_set_rtc_time;
+	ppc_md.get_rtc_time	= tqm8260_get_rtc_time;
+}
diff --git a/arch/ppc/platforms/tqm8xx.h b/arch/ppc/platforms/tqm8xx.h
new file mode 100644
index 0000000..2150dc8
--- /dev/null
+++ b/arch/ppc/platforms/tqm8xx.h
@@ -0,0 +1,179 @@
+/*
+ * TQM8xx(L) board specific definitions
+ *
+ * Copyright (c) 1999-2002 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifdef __KERNEL__
+#ifndef __MACH_TQM8xx_H
+#define __MACH_TQM8xx_H
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#ifndef __ASSEMBLY__
+#define	TQM_IMMR_BASE	0xFFF00000	/* phys. addr of IMMR */
+#define	TQM_IMAP_SIZE	(64 * 1024)	/* size of mapped area */
+
+#define	IMAP_ADDR	TQM_IMMR_BASE	/* physical base address of IMMR area */
+#define IMAP_SIZE	TQM_IMAP_SIZE	/* mapped size of IMMR area */
+
+/*-----------------------------------------------------------------------
+ * PCMCIA stuff
+ *-----------------------------------------------------------------------
+ *
+ */
+#define PCMCIA_MEM_SIZE		( 64 << 20 )
+
+#ifndef CONFIG_KUP4K
+# define	MAX_HWIFS	1	/* overwrite default in include/asm-ppc/ide.h	*/
+
+#else	/* CONFIG_KUP4K */
+
+# define	MAX_HWIFS	2	/* overwrite default in include/asm-ppc/ide.h	*/
+# ifndef __ASSEMBLY__
+# include <asm/8xx_immap.h>
+static __inline__ void ide_led(int on)
+{
+	volatile immap_t	*immap = (immap_t *)IMAP_ADDR;
+
+	if (on) {
+		immap->im_ioport.iop_padat &= ~0x80;
+	} else {
+		immap->im_ioport.iop_padat |= 0x80;
+	}
+}
+# endif	/* __ASSEMBLY__ */
+# define IDE_LED(x) ide_led((x))
+#endif	/* CONFIG_KUP4K */
+
+/*
+ * Definitions for IDE0 Interface
+ */
+#define IDE0_BASE_OFFSET		0
+#define IDE0_DATA_REG_OFFSET		(PCMCIA_MEM_SIZE + 0x320)
+#define IDE0_ERROR_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 1)
+#define IDE0_NSECTOR_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 2)
+#define IDE0_SECTOR_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 3)
+#define IDE0_LCYL_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 4)
+#define IDE0_HCYL_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 5)
+#define IDE0_SELECT_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 6)
+#define IDE0_STATUS_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 7)
+#define IDE0_CONTROL_REG_OFFSET		0x0106
+#define IDE0_IRQ_REG_OFFSET		0x000A	/* not used */
+
+/* define IO_BASE for PCMCIA */
+#define _IO_BASE 0x80000000
+#define _IO_BASE_SIZE  (64<<10)
+
+#define	FEC_INTERRUPT		 9	/* = SIU_LEVEL4			*/
+#define PHY_INTERRUPT		12	/* = IRQ6			*/
+#define	IDE0_INTERRUPT		13
+
+#ifdef CONFIG_IDE
+#endif
+
+/*-----------------------------------------------------------------------
+ * CPM Ethernet through SCCx.
+ *-----------------------------------------------------------------------
+ *
+ */
+
+/***  TQM823L, TQM850L  ***********************************************/
+
+#if defined(CONFIG_TQM823L) || defined(CONFIG_TQM850L)
+/* Bits in parallel I/O port registers that have to be set/cleared
+ * to configure the pins for SCC1 use.
+ */
+#define PA_ENET_RXD	((ushort)0x0004)	/* PA 13 */
+#define PA_ENET_TXD	((ushort)0x0008)	/* PA 12 */
+#define PA_ENET_RCLK	((ushort)0x0100)	/* PA  7 */
+#define PA_ENET_TCLK	((ushort)0x0400)	/* PA  5 */
+
+#define PB_ENET_TENA	((uint)0x00002000)	/* PB 18 */
+
+#define PC_ENET_CLSN	((ushort)0x0040)	/* PC  9 */
+#define PC_ENET_RENA	((ushort)0x0080)	/* PC  8 */
+
+/* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK1) to
+ * SCC2.  Also, make sure GR2 (bit 16) and SC2 (bit 17) are zero.
+ */
+#define SICR_ENET_MASK	((uint)0x0000ff00)
+#define SICR_ENET_CLKRT	((uint)0x00002600)
+#endif	/* CONFIG_TQM823L, CONFIG_TQM850L */
+
+/***  TQM860L  ********************************************************/
+
+#ifdef CONFIG_TQM860L
+/* Bits in parallel I/O port registers that have to be set/cleared
+ * to configure the pins for SCC1 use.
+ */
+#define PA_ENET_RXD	((ushort)0x0001)	/* PA 15 */
+#define PA_ENET_TXD	((ushort)0x0002)	/* PA 14 */
+#define PA_ENET_RCLK	((ushort)0x0100)	/* PA  7 */
+#define PA_ENET_TCLK	((ushort)0x0400)	/* PA  5 */
+
+#define PC_ENET_TENA	((ushort)0x0001)	/* PC 15 */
+#define PC_ENET_CLSN	((ushort)0x0010)	/* PC 11 */
+#define PC_ENET_RENA	((ushort)0x0020)	/* PC 10 */
+
+/* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK1) to
+ * SCC1.  Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero.
+ */
+#define SICR_ENET_MASK	((uint)0x000000ff)
+#define SICR_ENET_CLKRT	((uint)0x00000026)
+#endif	/* CONFIG_TQM860L */
+
+/***  FPS850L  *********************************************************/
+
+#ifdef CONFIG_FPS850L
+/* Bits in parallel I/O port registers that have to be set/cleared
+ * to configure the pins for SCC1 use.
+ */
+#define PA_ENET_RXD	((ushort)0x0004)	/* PA 13 */
+#define PA_ENET_TXD	((ushort)0x0008)	/* PA 12 */
+#define PA_ENET_RCLK	((ushort)0x0100)	/* PA  7 */
+#define PA_ENET_TCLK	((ushort)0x0400)	/* PA  5 */
+
+#define PC_ENET_TENA	((ushort)0x0002)	/* PC 14 */
+#define PC_ENET_CLSN	((ushort)0x0040)	/* PC  9 */
+#define PC_ENET_RENA	((ushort)0x0080)	/* PC  8 */
+
+/* Control bits in the SICR to route TCLK (CLK2) and RCLK (CLK4) to
+ * SCC2.  Also, make sure GR2 (bit 16) and SC2 (bit 17) are zero.
+ */
+#define SICR_ENET_MASK	((uint)0x0000ff00)
+#define SICR_ENET_CLKRT	((uint)0x00002600)
+#endif	/* CONFIG_FPS850L */
+
+/***  SM850  *********************************************************/
+
+/* The SM850 Service Module uses SCC2 for IrDA and SCC3 for Ethernet */
+
+#ifdef CONFIG_SM850
+#define PB_ENET_RXD	((uint)0x00000004)	/* PB 29 */
+#define PB_ENET_TXD	((uint)0x00000002)	/* PB 30 */
+#define PA_ENET_RCLK	((ushort)0x0100)	/* PA  7 */
+#define PA_ENET_TCLK	((ushort)0x0400)	/* PA  5 */
+
+#define PC_ENET_LBK	((ushort)0x0008)	/* PC 12 */
+#define PC_ENET_TENA	((ushort)0x0004)	/* PC 13 */
+
+#define PC_ENET_RENA	((ushort)0x0800)	/* PC  4 */
+#define PC_ENET_CLSN	((ushort)0x0400)	/* PC  5 */
+
+/* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK1) to
+ * SCC3.  Also, make sure GR3 (bit 8) and SC3 (bit 9) are zero.
+ */
+#define SICR_ENET_MASK	((uint)0x00FF0000)
+#define SICR_ENET_CLKRT	((uint)0x00260000)
+#endif	/* CONFIG_SM850 */
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif /* !__ASSEMBLY__ */
+#endif	/* __MACH_TQM8xx_H */
+#endif /* __KERNEL__ */