Move arch/ppc to arch/powerpc

As discussed on the list, move "arch/ppc" to "arch/powerpc" to
better match the Linux directory structure.

Please note that this patch also changes the "ppc" target in
MAKEALL to "powerpc" to match this new infrastructure. But "ppc"
is kept as an alias for now, to not break compatibility with
scripts using this name.

Signed-off-by: Stefan Roese <sr@denx.de>
Acked-by: Wolfgang Denk <wd@denx.de>
Acked-by: Detlev Zundel <dzu@denx.de>
Acked-by: Kim Phillips <kim.phillips@freescale.com>
Cc: Peter Tyser <ptyser@xes-inc.com>
Cc: Anatolij Gustschin <agust@denx.de>
diff --git a/arch/powerpc/config.mk b/arch/powerpc/config.mk
new file mode 100644
index 0000000..06a3b10
--- /dev/null
+++ b/arch/powerpc/config.mk
@@ -0,0 +1,44 @@
+#
+# (C) Copyright 2000-2002
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+CROSS_COMPILE ?= ppc_8xx-
+
+STANDALONE_LOAD_ADDR = 0x40000
+
+PLATFORM_RELFLAGS += -mrelocatable
+PLATFORM_CPPFLAGS += -DCONFIG_PPC -D__powerpc__
+PLATFORM_LDFLAGS  += -n
+
+#
+# When cross-compiling on NetBSD, we have to define __PPC__ or else we
+# will pick up a va_list declaration that is incompatible with the
+# actual argument lists emitted by the compiler.
+#
+# [Tested on NetBSD/i386 1.5 + cross-powerpc-netbsd-1.3]
+
+ifeq ($(CROSS_COMPILE),powerpc-netbsd-)
+PLATFORM_CPPFLAGS+= -D__PPC__
+endif
+ifeq ($(CROSS_COMPILE),powerpc-openbsd-)
+PLATFORM_CPPFLAGS+= -D__PPC__
+endif
diff --git a/arch/powerpc/cpu/74xx_7xx/Makefile b/arch/powerpc/cpu/74xx_7xx/Makefile
new file mode 100644
index 0000000..fe905f3
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/Makefile
@@ -0,0 +1,51 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2001
+# Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(CPU).a
+
+START	= start.o
+SOBJS	= cache.o kgdb.o io.o
+COBJS	= traps.o cpu.o cpu_init.o speed.o interrupts.o
+
+SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/74xx_7xx/cache.S b/arch/powerpc/cpu/74xx_7xx/cache.S
new file mode 100644
index 0000000..66c7298
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/cache.S
@@ -0,0 +1,404 @@
+#include <config.h>
+#include <74xx_7xx.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef CACHE_LINE_SIZE
+# define CACHE_LINE_SIZE L1_CACHE_BYTES
+#endif
+
+#if CACHE_LINE_SIZE == 128
+#define LG_CACHE_LINE_SIZE 7
+#elif CACHE_LINE_SIZE == 32
+#define LG_CACHE_LINE_SIZE 5
+#elif CACHE_LINE_SIZE == 16
+#define LG_CACHE_LINE_SIZE 4
+#elif CACHE_LINE_SIZE == 8
+#define LG_CACHE_LINE_SIZE 3
+#else
+# error "Invalid cache line size!"
+#endif
+
+/*
+ * Invalidate L1 instruction cache.
+ */
+_GLOBAL(invalidate_l1_instruction_cache)
+	mfspr	r3,PVR
+	rlwinm	r3,r3,16,16,31
+	cmpi	0,r3,1
+	beqlr			/* for 601, do nothing */
+	/* 603/604 processor - use invalidate-all bit in HID0 */
+	mfspr	r3,HID0
+	ori	r3,r3,HID0_ICFI
+	mtspr	HID0,r3
+	isync
+	blr
+
+/*
+ * Invalidate L1 data cache.
+ */
+_GLOBAL(invalidate_l1_data_cache)
+	mfspr	r3,HID0
+	ori	r3,r3,HID0_DCFI
+	mtspr	HID0,r3
+	isync
+	blr
+
+/*
+ * Flush data cache.
+ */
+_GLOBAL(flush_dcache)
+	lis	r3,0
+	lis	r5,CACHE_LINE_SIZE
+flush:
+	cmp	0,1,r3,r5
+	bge	done
+	lwz	r5,0(r3)
+	lis	r5,CACHE_LINE_SIZE
+	addi	r3,r3,0x4
+	b	flush
+done:
+	blr
+/*
+ * Write any modified data cache blocks out to memory
+ * and invalidate the corresponding instruction cache blocks.
+ * This is a no-op on the 601.
+ *
+ * flush_icache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_icache_range)
+	mfspr	r5,PVR
+	rlwinm	r5,r5,16,16,31
+	cmpi	0,r5,1
+	beqlr				/* for 601, do nothing */
+	li	r5,CACHE_LINE_SIZE-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,LG_CACHE_LINE_SIZE
+	beqlr
+	mtctr	r4
+	mr	r6,r3
+1:	dcbst	0,r3
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	1b
+	sync				/* wait for dcbst's to get to ram */
+	mtctr	r4
+2:	icbi	0,r6
+	addi	r6,r6,CACHE_LINE_SIZE
+	bdnz	2b
+	sync				/* additional sync needed on g4 */
+	isync
+	blr
+/*
+ * Write any modified data cache blocks out to memory.
+ * Does not invalidate the corresponding cache lines (especially for
+ * any corresponding instruction cache).
+ *
+ * clean_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(clean_dcache_range)
+	li	r5,CACHE_LINE_SIZE-1
+	andc	r3,r3,r5	/* align r3 down to cache line */
+	subf	r4,r3,r4	/* r4 = offset of stop from start of cache line */
+	add	r4,r4,r5	/* r4 += cache_line_size-1 */
+	srwi.	r4,r4,LG_CACHE_LINE_SIZE  /* r4 = number of cache lines to flush */
+	beqlr				  /* if r4 == 0 return */
+	mtctr	r4			  /* ctr = r4 */
+
+	sync
+1:	dcbst	0,r3
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	1b
+	sync				/* wait for dcbst's to get to ram */
+	blr
+
+/*
+ * Write any modified data cache blocks out to memory
+ * and invalidate the corresponding instruction cache blocks.
+ *
+ * flush_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_dcache_range)
+	li	r5,CACHE_LINE_SIZE-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,LG_CACHE_LINE_SIZE
+	beqlr
+	mtctr	r4
+
+	sync
+1:	dcbf	0,r3
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	1b
+	sync				/* wait for dcbf's to get to ram */
+	blr
+
+/*
+ * Like above, but invalidate the D-cache.  This is used by the 8xx
+ * to invalidate the cache so the PPC core doesn't get stale data
+ * from the CPM (no cache snooping here :-).
+ *
+ * invalidate_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(invalidate_dcache_range)
+	li	r5,CACHE_LINE_SIZE-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,LG_CACHE_LINE_SIZE
+	beqlr
+	mtctr	r4
+
+	sync
+1:	dcbi	0,r3
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	1b
+	sync				/* wait for dcbi's to get to ram */
+	blr
+
+/*
+ * Flush a particular page from the data cache to RAM.
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ * This is a no-op on the 601 which has a unified cache.
+ *
+ *	void __flush_page_to_ram(void *page)
+ */
+_GLOBAL(__flush_page_to_ram)
+	mfspr	r5,PVR
+	rlwinm	r5,r5,16,16,31
+	cmpi	0,r5,1
+	beqlr				/* for 601, do nothing */
+	rlwinm	r3,r3,0,0,19		/* Get page base address */
+	li	r4,4096/CACHE_LINE_SIZE	/* Number of lines in a page */
+	mtctr	r4
+	mr	r6,r3
+0:	dcbst	0,r3			/* Write line to ram */
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	0b
+	sync
+	mtctr	r4
+1:	icbi	0,r6
+	addi	r6,r6,CACHE_LINE_SIZE
+	bdnz	1b
+	sync
+	isync
+	blr
+
+/*
+ * Flush a particular page from the instruction cache.
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ * This is a no-op on the 601 which has a unified cache.
+ *
+ *	void __flush_icache_page(void *page)
+ */
+_GLOBAL(__flush_icache_page)
+	mfspr	r5,PVR
+	rlwinm	r5,r5,16,16,31
+	cmpi	0,r5,1
+	beqlr				/* for 601, do nothing */
+	li	r4,4096/CACHE_LINE_SIZE	/* Number of lines in a page */
+	mtctr	r4
+1:	icbi	0,r3
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	1b
+	sync
+	isync
+	blr
+
+/*
+ * Clear a page using the dcbz instruction, which doesn't cause any
+ * memory traffic (except to write out any cache lines which get
+ * displaced).  This only works on cacheable memory.
+ */
+_GLOBAL(clear_page)
+	li	r0,4096/CACHE_LINE_SIZE
+	mtctr	r0
+1:	dcbz	0,r3
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	1b
+	blr
+
+/*
+ * Enable L1 Instruction cache
+ */
+_GLOBAL(icache_enable)
+	mfspr	r3, HID0
+	li	r5, HID0_ICFI|HID0_ILOCK
+	andc	r3, r3, r5
+	ori	r3, r3, HID0_ICE
+	ori	r5, r3, HID0_ICFI
+	mtspr	HID0, r5
+	mtspr	HID0, r3
+	isync
+	blr
+
+/*
+ * Disable L1 Instruction cache
+ */
+_GLOBAL(icache_disable)
+	mflr	r4
+	bl	invalidate_l1_instruction_cache		/* uses r3 */
+	sync
+	mtlr	r4
+	mfspr	r3, HID0
+	li	r5, 0
+	ori	r5, r5, HID0_ICE
+	andc	r3, r3, r5
+	mtspr	HID0, r3
+	isync
+	blr
+
+/*
+ * Is instruction cache enabled?
+ */
+_GLOBAL(icache_status)
+	mfspr	r3, HID0
+	andi.	r3, r3, HID0_ICE
+	blr
+
+
+_GLOBAL(l1dcache_enable)
+	mfspr	r3, HID0
+	li	r5, HID0_DCFI|HID0_DLOCK
+	andc	r3, r3, r5
+	mtspr	HID0, r3		/* no invalidate, unlock */
+	ori	r3, r3, HID0_DCE
+	ori	r5, r3, HID0_DCFI
+	mtspr	HID0, r5		/* enable + invalidate */
+	mtspr	HID0, r3		/* enable */
+	sync
+	blr
+
+/*
+ * Enable data cache(s) - L1 and optionally L2
+ * Calls l2cache_enable. LR saved in r5
+ */
+_GLOBAL(dcache_enable)
+	mfspr	r3, HID0
+	li	r5, HID0_DCFI|HID0_DLOCK
+	andc	r3, r3, r5
+	mtspr	HID0, r3		/* no invalidate, unlock */
+	ori	r3, r3, HID0_DCE
+	ori	r5, r3, HID0_DCFI
+	mtspr	HID0, r5		/* enable + invalidate */
+	mtspr	HID0, r3		/* enable */
+	sync
+#ifdef CONFIG_SYS_L2
+	mflr	r5
+	bl	l2cache_enable		/* uses r3 and r4 */
+	sync
+	mtlr	r5
+#endif
+	blr
+
+
+/*
+ * Disable data cache(s) - L1 and optionally L2
+ * Calls flush_dcache and l2cache_disable_no_flush.
+ * LR saved in r4
+ */
+_GLOBAL(dcache_disable)
+	mflr	r4			/* save link register */
+	bl	flush_dcache	/* uses r3 and r5 */
+	sync
+	mfspr	r3, HID0
+	li	r5, HID0_DCFI|HID0_DLOCK
+	andc	r3, r3, r5
+	mtspr	HID0, r3		/* no invalidate, unlock */
+	li	r5, HID0_DCE|HID0_DCFI
+	andc	r3, r3, r5		/* no enable, no invalidate */
+	mtspr	HID0, r3
+	sync
+#ifdef CONFIG_SYS_L2
+	bl	l2cache_disable_no_flush /* uses r3 */
+#endif
+	mtlr	r4			/* restore link register */
+	blr
+
+/*
+ * Is data cache enabled?
+ */
+_GLOBAL(dcache_status)
+	mfspr	r3, HID0
+	andi.	r3, r3, HID0_DCE
+	blr
+
+/*
+ * Invalidate L2 cache using L2I and polling L2IP or L2I
+ */
+_GLOBAL(l2cache_invalidate)
+	sync
+	mfspr r3, l2cr
+	oris	r3, r3, L2CR_L2I@h
+	sync
+	mtspr	l2cr, r3
+	sync
+	mfspr r3, PVR
+	sync
+	rlwinm r3, r3, 16,16,31
+	cmpli 0,r3,0x8000  /* 7451, 7441 */
+	beq 0,inv_7450
+	cmpli 0,r3,0x8001  /* 7455, 7445 */
+	beq 0,inv_7450
+	cmpli 0,r3,0x8002  /* 7457, 7447 */
+	beq 0,inv_7450
+	cmpli 0,r3,0x8003  /* 7447A */
+	beq 0,inv_7450
+	cmpli 0,r3,0x8004  /* 7448 */
+	beq 0,inv_7450
+invl2:
+	mfspr	r3, l2cr
+	andi.	r3, r3, L2CR_L2IP
+	bne	invl2
+	/* turn off the global invalidate bit */
+	mfspr	r3, l2cr
+	rlwinm	r3, r3, 0, 11, 9
+	sync
+	mtspr	l2cr, r3
+	sync
+	blr
+inv_7450:
+	mfspr	r3, l2cr
+	andis. r3, r3, L2CR_L2I@h
+	bne inv_7450
+	blr
+
+/*
+ * Enable L2 cache
+ * Calls l2cache_invalidate. LR is saved in r4
+ */
+_GLOBAL(l2cache_enable)
+	mflr	r4			/* save link register */
+	bl	l2cache_invalidate	/* uses r3 */
+	sync
+	lis	r3, L2_ENABLE@h
+	ori	r3, r3, L2_ENABLE@l
+	mtspr	l2cr, r3
+	isync
+	mtlr	r4			/* restore link register */
+	blr
+
+/*
+ * Disable L2 cache
+ * Calls flush_dcache. LR is saved in r4
+ */
+_GLOBAL(l2cache_disable)
+	mflr	r4			/* save link register */
+	bl	flush_dcache		/* uses r3 and r5 */
+	sync
+	mtlr	r4			/* restore link register */
+l2cache_disable_no_flush:		/* provide way to disable L2 w/o flushing */
+	lis	r3, L2_INIT@h
+	ori	r3, r3, L2_INIT@l
+	mtspr	l2cr, r3
+	isync
+	blr
diff --git a/arch/powerpc/cpu/74xx_7xx/config.mk b/arch/powerpc/cpu/74xx_7xx/config.mk
new file mode 100644
index 0000000..df1f6ac
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/config.mk
@@ -0,0 +1,26 @@
+#
+# (C) Copyright 2001
+# Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -fPIC -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_74xx_7xx -ffixed-r2 -mstring
diff --git a/arch/powerpc/cpu/74xx_7xx/cpu.c b/arch/powerpc/cpu/74xx_7xx/cpu.c
new file mode 100644
index 0000000..3c17277
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/cpu.c
@@ -0,0 +1,320 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * cpu.c
+ *
+ * CPU specific code
+ *
+ * written or collected and sometimes rewritten by
+ * Magnus Damm <damm@bitsmart.com>
+ *
+ * minor modifications by
+ * Wolfgang Denk <wd@denx.de>
+ *
+ * more modifications by
+ * Josh Huber <huber@mclx.com>
+ * added support for the 74xx series of cpus
+ * added support for the 7xx series of cpus
+ * made the code a little less hard-coded, and more auto-detectish
+ */
+
+#include <common.h>
+#include <command.h>
+#include <74xx_7xx.h>
+#include <asm/cache.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <fdt_support.h>
+#endif
+
+#ifdef CONFIG_AMIGAONEG3SE
+#include "../board/MAI/AmigaOneG3SE/via686.h"
+#include "../board/MAI/AmigaOneG3SE/memio.h"
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+cpu_t
+get_cpu_type(void)
+{
+	uint pvr = get_pvr();
+	cpu_t type;
+
+	type = CPU_UNKNOWN;
+
+	switch (PVR_VER(pvr)) {
+	case 0x000c:
+		type = CPU_7400;
+		break;
+	case 0x0008:
+		type = CPU_750;
+
+		if (((pvr >> 8) & 0xff) == 0x01) {
+			type = CPU_750CX;	/* old CX (80100 and 8010x?)*/
+		} else if (((pvr >> 8) & 0xff) == 0x22) {
+			type = CPU_750CX;	/* CX (82201,82202) and CXe (82214) */
+		} else if (((pvr >> 8) & 0xff) == 0x33) {
+			type = CPU_750CX;	/* CXe (83311) */
+		} else if (((pvr >> 12) & 0xF) == 0x3) {
+			type = CPU_755;
+		}
+		break;
+
+	case 0x7000:
+		type = CPU_750FX;
+		break;
+
+	case 0x7002:
+		type = CPU_750GX;
+		break;
+
+	case 0x800C:
+		type = CPU_7410;
+		break;
+
+	case 0x8000:
+		type = CPU_7450;
+		break;
+
+	case 0x8001:
+		type = CPU_7455;
+		break;
+
+	case 0x8002:
+		type = CPU_7457;
+		break;
+
+	case 0x8003:
+		type = CPU_7447A;
+		break;
+
+	case 0x8004:
+		type = CPU_7448;
+		break;
+
+	default:
+		break;
+	}
+
+	return type;
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if !defined(CONFIG_BAB7xx)
+int checkcpu (void)
+{
+	uint type   = get_cpu_type();
+	uint pvr    = get_pvr();
+	ulong clock = gd->cpu_clk;
+	char buf[32];
+	char *str;
+
+	puts ("CPU:   ");
+
+	switch (type) {
+	case CPU_750CX:
+		printf ("750CX%s v%d.%d", (pvr&0xf0)?"e":"",
+			(pvr>>8) & 0xf,
+			pvr & 0xf);
+		goto	PR_CLK;
+
+	case CPU_750:
+		str = "750";
+		break;
+
+	case CPU_750FX:
+		str = "750FX";
+		break;
+
+	case CPU_750GX:
+		str = "750GX";
+		break;
+
+	case CPU_755:
+		str = "755";
+		break;
+
+	case CPU_7400:
+		str = "MPC7400";
+		break;
+
+	case CPU_7410:
+		str = "MPC7410";
+		break;
+
+	case CPU_7447A:
+		str = "MPC7447A";
+		break;
+
+	case CPU_7448:
+		str = "MPC7448";
+		break;
+
+	case CPU_7450:
+		str = "MPC7450";
+		break;
+
+	case CPU_7455:
+		str = "MPC7455";
+		break;
+
+	case CPU_7457:
+		str = "MPC7457";
+		break;
+
+	default:
+		printf("Unknown CPU -- PVR: 0x%08x\n", pvr);
+		return -1;
+	}
+
+	printf ("%s v%d.%d", str, (pvr >> 8) & 0xFF, pvr & 0xFF);
+PR_CLK:
+	printf (" @ %s MHz\n", strmhz(buf, clock));
+
+	return (0);
+}
+#endif
+/* these two functions are unimplemented currently [josh] */
+
+/* -------------------------------------------------------------------- */
+/* L1 i-cache								*/
+
+int
+checkicache(void)
+{
+	return 0; /* XXX */
+}
+
+/* -------------------------------------------------------------------- */
+/* L1 d-cache								*/
+
+int
+checkdcache(void)
+{
+	return 0; /* XXX */
+}
+
+/* -------------------------------------------------------------------- */
+
+static inline void
+soft_restart(unsigned long addr)
+{
+	/* 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__ ("mtspr	26, %0"		:: "r" (addr));
+	__asm__ __volatile__ ("li	4, (1 << 6)"	::: "r4");
+	__asm__ __volatile__ ("mtspr	27, 4");
+	__asm__ __volatile__ ("rfi");
+
+	while(1);	/* not reached */
+}
+
+
+#if !defined(CONFIG_PCIPPC2) && \
+    !defined(CONFIG_BAB7xx)  && \
+    !defined(CONFIG_ELPPC)   && \
+    !defined(CONFIG_PPMC7XX)
+/* no generic way to do board reset. simply call soft_reset. */
+void
+do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	ulong addr;
+	/* flush and disable I/D cache */
+	__asm__ __volatile__ ("mfspr	3, 1008"	::: "r3");
+	__asm__ __volatile__ ("ori	5, 5, 0xcc00"	::: "r5");
+	__asm__ __volatile__ ("ori	4, 3, 0xc00"	::: "r4");
+	__asm__ __volatile__ ("andc	5, 3, 5"	::: "r5");
+	__asm__ __volatile__ ("sync");
+	__asm__ __volatile__ ("mtspr	1008, 4");
+	__asm__ __volatile__ ("isync");
+	__asm__ __volatile__ ("sync");
+	__asm__ __volatile__ ("mtspr	1008, 5");
+	__asm__ __volatile__ ("isync");
+	__asm__ __volatile__ ("sync");
+
+#ifdef CONFIG_SYS_RESET_ADDRESS
+	addr = CONFIG_SYS_RESET_ADDRESS;
+#else
+	/*
+	 * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address,
+	 * CONFIG_SYS_MONITOR_BASE - sizeof (ulong) is usually a valid
+	 * address. Better pick an address known to be invalid on your
+	 * system and assign it to CONFIG_SYS_RESET_ADDRESS.
+	 */
+	addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong);
+#endif
+	soft_restart(addr);
+	while(1);	/* not reached */
+}
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * For the 7400 the TB clock runs at 1/4 the cpu bus speed.
+ */
+#if defined(CONFIG_AMIGAONEG3SE) || defined(CONFIG_SYS_CONFIG_BUS_CLK)
+unsigned long get_tbclk(void)
+{
+	return (gd->bus_clk / 4);
+}
+#else	/* ! CONFIG_AMIGAONEG3SE and !CONFIG_SYS_CONFIG_BUS_CLK*/
+
+unsigned long get_tbclk (void)
+{
+	return CONFIG_SYS_BUS_HZ / 4;
+}
+#endif	/* CONFIG_AMIGAONEG3SE or CONFIG_SYS_CONFIG_BUS_CLK*/
+/* ------------------------------------------------------------------------- */
+#if defined(CONFIG_WATCHDOG)
+#if !defined(CONFIG_PCIPPC2) && !defined(CONFIG_BAB7xx)
+void
+watchdog_reset(void)
+{
+
+}
+#endif  /* !CONFIG_PCIPPC2 && !CONFIG_BAB7xx */
+#endif	/* CONFIG_WATCHDOG */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_OF_LIBFDT
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+			     "timebase-frequency", bd->bi_busfreq / 4, 1);
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+			     "bus-frequency", bd->bi_busfreq, 1);
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+			     "clock-frequency", bd->bi_intfreq, 1);
+
+	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+
+	fdt_fixup_ethernet(blob);
+}
+#endif
+/* ------------------------------------------------------------------------- */
diff --git a/arch/powerpc/cpu/74xx_7xx/cpu_init.c b/arch/powerpc/cpu/74xx_7xx/cpu_init.c
new file mode 100644
index 0000000..1dd1b2c
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/cpu_init.c
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * cpu_init.c - low level cpu init
+ *
+ * there's really nothing going on here yet.  future work area?
+ */
+
+#include <common.h>
+#include <74xx_7xx.h>
+
+/*
+ * Breath some life into the CPU...
+ *
+ * there's basically nothing to do here since the memory controller
+ * isn't on the CPU in this case.
+ */
+void
+cpu_init_f (void)
+{
+	switch (get_cpu_type()) {
+	case CPU_7450:
+	case CPU_7455:
+	case CPU_7457:
+	case CPU_7447A:
+	case CPU_7448:
+		/* enable the timebase bit in HID0 */
+		set_hid0(get_hid0() | 0x4000000);
+		break;
+	default:
+		/* do nothing */
+		break;
+	}
+}
+
+/*
+ * initialize higher level parts of CPU like timers
+ */
+int cpu_init_r (void)
+{
+	return (0);
+}
diff --git a/arch/powerpc/cpu/74xx_7xx/interrupts.c b/arch/powerpc/cpu/74xx_7xx/interrupts.c
new file mode 100644
index 0000000..0ea1aec
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/interrupts.c
@@ -0,0 +1,105 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * interrupts.c - just enough support for the decrementer/timer
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <mpc8xx_irq.h>
+#include <asm/processor.h>
+#include <commproc.h>
+#include <command.h>
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+#if defined(DEBUG) && !defined(CONFIG_AMIGAONEG3SE)
+	printf("interrupt_init: GT main cause reg: %08x:%08x\n",
+	       GTREGREAD(LOW_INTERRUPT_CAUSE_REGISTER),
+	       GTREGREAD(HIGH_INTERRUPT_CAUSE_REGISTER));
+	printf("interrupt_init: ethernet cause regs: %08x %08x %08x\n",
+	       GTREGREAD(ETHERNET0_INTERRUPT_CAUSE_REGISTER),
+	       GTREGREAD(ETHERNET1_INTERRUPT_CAUSE_REGISTER),
+	       GTREGREAD(ETHERNET2_INTERRUPT_CAUSE_REGISTER));
+	printf("interrupt_init: ethernet mask regs:  %08x %08x %08x\n",
+	       GTREGREAD(ETHERNET0_INTERRUPT_MASK_REGISTER),
+	       GTREGREAD(ETHERNET1_INTERRUPT_MASK_REGISTER),
+	       GTREGREAD(ETHERNET2_INTERRUPT_MASK_REGISTER));
+	puts("interrupt_init: setting decrementer_count\n");
+#endif
+	*decrementer_count = get_tbclk() / CONFIG_SYS_HZ;
+
+	return (0);
+}
+
+/****************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void
+external_interrupt(struct pt_regs *regs)
+{
+	puts("external_interrupt (oops!)\n");
+}
+
+volatile ulong timestamp = 0;
+
+/*
+ * timer_interrupt - gets called when the decrementer overflows,
+ * with interrupts disabled.
+ * Trivial implementation - no need to be really accurate.
+ */
+void
+timer_interrupt_cpu (struct pt_regs *regs)
+{
+	/* nothing to do here */
+	return;
+}
+
+/****************************************************************************/
+
+/*
+ * Install and free a interrupt handler.
+ */
+
+void
+irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
+{
+
+}
+
+void
+irq_free_handler(int vec)
+{
+
+}
+
+/****************************************************************************/
+
+void
+do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+	puts("IRQ related functions are unimplemented currently.\n");
+}
diff --git a/arch/powerpc/cpu/74xx_7xx/io.S b/arch/powerpc/cpu/74xx_7xx/io.S
new file mode 100644
index 0000000..af2e6d1
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/io.S
@@ -0,0 +1,128 @@
+/*
+ *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2001	Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ *			Andreas Heppel <aheppel@sysgo.de>
+ *  Copyright (C) 2002	Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <ppc_asm.tmpl>
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     in8 */
+/*  Description:  Input 8 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  in8
+in8:
+	lbz     r3,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     in16 */
+/*  Description:  Input 16 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  in16
+in16:
+	lhz     r3,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     in16r */
+/*  Description:  Input 16 bits and byte reverse */
+/* ------------------------------------------------------------------------------- */
+	.globl  in16r
+in16r:
+	lhbrx   r3,0,r3
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     in32 */
+/*  Description:  Input 32 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  in32
+in32:
+	lwz     3,0(3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     in32r */
+/*  Description:  Input 32 bits and byte reverse */
+/* ------------------------------------------------------------------------------- */
+    .globl  in32r
+in32r:
+	lwbrx   r3,0,r3
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     out8 */
+/*  Description:  Output 8 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  out8
+out8:
+	stb     r4,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     out16 */
+/*  Description:  Output 16 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  out16
+out16:
+	sth     r4,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     out16r */
+/*  Description:  Byte reverse and output 16 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  out16r
+out16r:
+	sthbrx  r4,0,r3
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     out32 */
+/*  Description:  Output 32 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  out32
+out32:
+	stw     r4,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     out32r */
+/*  Description:  Byte reverse and output 32 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  out32r
+out32r:
+	stwbrx  r4,0,r3
+	sync
+	blr
diff --git a/arch/powerpc/cpu/74xx_7xx/kgdb.S b/arch/powerpc/cpu/74xx_7xx/kgdb.S
new file mode 100644
index 0000000..ad487cd
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/kgdb.S
@@ -0,0 +1,77 @@
+/*
+ *  Copyright (C) 2000	Murray Jensen <Murray.Jensen@cmst.csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307USA
+ */
+
+#include <config.h>
+#include <command.h>
+#include <74xx_7xx.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#if defined(CONFIG_CMD_KGDB)
+
+ /*
+ * cache flushing routines for kgdb
+ */
+
+	.globl	kgdb_flush_cache_all
+kgdb_flush_cache_all:
+	lis	r3,0
+	addis	r4,r0,0x0040
+kgdb_flush_loop:
+	lwz	r5,0(r3)
+	addi	r3,r3,CONFIG_SYS_CACHELINE_SIZE
+	cmp	0,0,r3,r4
+	bne	kgdb_flush_loop
+	SYNC
+	mfspr	r3,1008
+	ori	r3,r3,0x8800
+	mtspr	1008,r3
+	sync
+	blr
+
+	.globl	kgdb_flush_cache_range
+kgdb_flush_cache_range:
+	li	r5,CONFIG_SYS_CACHELINE_SIZE-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,CONFIG_SYS_CACHELINE_SHIFT
+	beqlr
+	mtctr	r4
+	mr	r6,r3
+1:	dcbst	0,r3
+	addi	r3,r3,CONFIG_SYS_CACHELINE_SIZE
+	bdnz	1b
+	sync				/* wait for dcbst's to get to ram */
+	mtctr	r4
+2:	icbi	0,r6
+	addi	r6,r6,CONFIG_SYS_CACHELINE_SIZE
+	bdnz	2b
+	SYNC
+	blr
+
+#endif
diff --git a/arch/powerpc/cpu/74xx_7xx/speed.c b/arch/powerpc/cpu/74xx_7xx/speed.c
new file mode 100644
index 0000000..f2fdcd5
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/speed.c
@@ -0,0 +1,185 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <74xx_7xx.h>
+#include <asm/processor.h>
+
+#ifdef CONFIG_AMIGAONEG3SE
+#include "../board/MAI/AmigaOneG3SE/via686.h"
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern unsigned long get_board_bus_clk (void);
+
+static const int hid1_multipliers_x_10[] = {
+	25,	/* 0000 - 2.5x */
+	75,	/* 0001 - 7.5x */
+	70,	/* 0010 - 7x */
+	10,	/* 0011 - bypass */
+	20,	/* 0100 - 2x */
+	65,	/* 0101 - 6.5x */
+	100,	/* 0110 - 10x */
+	45,	/* 0111 - 4.5x */
+	30,	/* 1000 - 3x */
+	55,	/* 1001 - 5.5x */
+	40,	/* 1010 - 4x */
+	50,	/* 1011 - 5x */
+	80,	/* 1100 - 8x */
+	60,	/* 1101 - 6x */
+	35,	/* 1110 - 3.5x */
+	0	/* 1111 - off */
+};
+
+/* PLL_CFG[0:4] table for cpu 7448/7447A/7455/7457 */
+static const int hid1_74xx_multipliers_x_10[] = {
+	115,	/* 00000 - 11.5x  */
+	170,	/* 00001 - 17x    */
+	75,	/* 00010 -  7.5x  */
+	150,	/* 00011 - 15x    */
+	70,	/* 00100 -  7x    */
+	180,	/* 00101 - 18x    */
+	10,	/* 00110 - bypass */
+	200,	/* 00111 - 20x    */
+	20,	/* 01000 -  2x    */
+	210,	/* 01001 - 21x    */
+	65,	/* 01010 -  6.5x  */
+	130,	/* 01011 - 13x    */
+	85,	/* 01100 -  8.5x  */
+	240,	/* 01101 - 24x    */
+	95,	/* 01110 -  9.5x  */
+	90,	/* 01111 -  9x    */
+	30,	/* 10000 -  3x    */
+	105,	/* 10001 - 10.5x  */
+	55,	/* 10010 -  5.5x  */
+	110,	/* 10011 - 11x    */
+	40,	/* 10100 -  4x    */
+	100,	/* 10101 - 10x    */
+	50,	/* 10110 -  5x    */
+	120,	/* 10111 - 12x    */
+	80,	/* 11000 -  8x    */
+	140,	/* 11001 - 14x    */
+	60,	/* 11010 -  6x    */
+	160,	/* 11011 - 16x    */
+	135,	/* 11100 - 13.5x  */
+	280,	/* 11101 - 28x    */
+	0,	/* 11110 - off    */
+	125	/* 11111 - 12.5x  */
+};
+
+static const int hid1_fx_multipliers_x_10[] = {
+	00,	/* 0000 - off */
+	00,	/* 0001 - off */
+	10,	/* 0010 - bypass */
+	10,	/* 0011 - bypass */
+	20,	/* 0100 - 2x */
+	25,	/* 0101 - 2.5x */
+	30,	/* 0110 - 3x */
+	35,	/* 0111 - 3.5x */
+	40,	/* 1000 - 4x */
+	45,	/* 1001 - 4.5x */
+	50,	/* 1010 - 5x */
+	55,	/* 1011 - 5.5x */
+	60,	/* 1100 - 6x */
+	65,	/* 1101 - 6.5x */
+	70,	/* 1110 - 7x */
+	75,	/* 1111 - 7.5 */
+	80,	/* 10000 - 8x */
+	85,	/* 10001 - 8.5x */
+	90,	/* 10010 - 9x */
+	95,	/* 10011 - 9.5x */
+	100,	/* 10100 - 10x */
+	110,	/* 10101 - 11x */
+	120,	/* 10110 - 12x */
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Measure CPU clock speed (core clock GCLK1, GCLK2)
+ *
+ * (Approx. GCLK frequency in Hz)
+ */
+
+int get_clocks (void)
+{
+	ulong clock = 0;
+
+#ifdef CONFIG_SYS_BUS_CLK
+	gd->bus_clk = CONFIG_SYS_BUS_CLK;	/* bus clock is a fixed frequency */
+#else
+	gd->bus_clk = get_board_bus_clk ();	/* bus clock is configurable */
+#endif
+
+	/* calculate the clock frequency based upon the CPU type */
+	switch (get_cpu_type()) {
+	case CPU_7447A:
+	case CPU_7448:
+	case CPU_7455:
+	case CPU_7457:
+		/*
+		 * Make sure division is done before multiplication to prevent 32-bit
+		 * arithmetic overflows which will cause a negative number
+		 */
+		clock = (gd->bus_clk / 10) *
+			hid1_74xx_multipliers_x_10[(get_hid1 () >> 12) & 0x1F];
+		break;
+
+	case CPU_750GX:
+	case CPU_750FX:
+		clock = (gd->bus_clk / 10) *
+			hid1_fx_multipliers_x_10[get_hid1 () >> 27];
+		break;
+
+	case CPU_7450:
+	case CPU_740:
+	case CPU_740P:
+	case CPU_745:
+	case CPU_750CX:
+	case CPU_750:
+	case CPU_750P:
+	case CPU_755:
+	case CPU_7400:
+	case CPU_7410:
+		/*
+		 * Make sure division is done before multiplication to prevent 32-bit
+		 * arithmetic overflows which will cause a negative number
+		 */
+		clock = (gd->bus_clk / 10) *
+			hid1_multipliers_x_10[get_hid1 () >> 28];
+		break;
+
+	case CPU_UNKNOWN:
+	       printf ("get_gclk_freq(): unknown CPU type\n");
+	       clock = 0;
+	       return (1);
+	}
+
+	gd->cpu_clk = clock;
+
+	return (0);
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/arch/powerpc/cpu/74xx_7xx/start.S b/arch/powerpc/cpu/74xx_7xx/start.S
new file mode 100644
index 0000000..88fdf88
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/start.S
@@ -0,0 +1,874 @@
+/*
+ *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
+ *  Copyright (C) 2001  Josh Huber <huber@mclx.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*  U-Boot - Startup Code for PowerPC based Embedded Boards
+ *
+ *
+ *  The processor starts at 0xfff00100 and the code is executed
+ *  from flash. The code is organized to be at an other address
+ *  in memory, but as long we don't jump around before relocating.
+ *  board_init lies at a quite high address and when the cpu has
+ *  jumped there, everything is ok.
+ */
+#include <config.h>
+#include <74xx_7xx.h>
+#include <timestamp.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#if !defined(CONFIG_DB64360) && \
+    !defined(CONFIG_DB64460) && \
+    !defined(CONFIG_CPCI750) && \
+    !defined(CONFIG_P3Mx)
+#include <galileo/gt64260R.h>
+#endif
+
+#ifndef  CONFIG_IDENT_STRING
+#define  CONFIG_IDENT_STRING ""
+#endif
+
+/* We don't want the  MMU yet.
+*/
+#undef	MSR_KERNEL
+/* Machine Check and Recoverable Interr. */
+#define MSR_KERNEL ( MSR_ME | MSR_RI )
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+	START_GOT
+	GOT_ENTRY(_GOT2_TABLE_)
+	GOT_ENTRY(_FIXUP_TABLE_)
+
+	GOT_ENTRY(_start)
+	GOT_ENTRY(_start_of_vectors)
+	GOT_ENTRY(_end_of_vectors)
+	GOT_ENTRY(transfer_to_handler)
+
+	GOT_ENTRY(__init_end)
+	GOT_ENTRY(_end)
+	GOT_ENTRY(__bss_start)
+	END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+	.text
+	.long	0x27051956		/* U-Boot Magic Number		*/
+	.globl	version_string
+version_string:
+	.ascii	U_BOOT_VERSION
+	.ascii	" (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
+	.ascii	CONFIG_IDENT_STRING, "\0"
+
+	. = EXC_OFF_SYS_RESET
+	.globl	_start
+_start:
+	li	r21, BOOTFLAG_COLD	/* Normal Power-On: Boot from FLASH */
+	b	boot_cold
+	sync
+
+	. = EXC_OFF_SYS_RESET + 0x10
+
+	.globl	_start_warm
+_start_warm:
+	li	r21, BOOTFLAG_WARM	/* Software reboot		*/
+	b	boot_warm
+	sync
+
+	/* the boot code is located below the exception table */
+
+	.globl	_start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception.  "Never" generated on the 860. */
+	STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception.  "Never" generated on the 860. */
+	STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+	STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+	. = 0x600
+Alignment:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	mfspr	r4,DAR
+	stw	r4,_DAR(r21)
+	mfspr	r5,DSISR
+	stw	r5,_DSISR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+	. = 0x700
+ProgramCheck:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+		MSR_KERNEL, COPY_EE)
+
+	/* No FPU on MPC8xx.  This exception is not supposed to happen.
+	*/
+	STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+	/* I guess we could implement decrementer, and may have
+	 * to someday for timekeeping.
+	 */
+	STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+	STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+	STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+	STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+	STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+	STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+	/*
+	 * On the MPC8xx, this is a software emulation interrupt. It
+	 * occurs for all unimplemented and illegal instructions.
+	 */
+	STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
+
+	STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
+	STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
+
+	STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+	STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+	STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+	STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+	STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+	STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+	STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+
+	STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
+	STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
+	STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
+	STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
+
+	.globl	_end_of_vectors
+_end_of_vectors:
+
+	. = 0x2000
+
+boot_cold:
+boot_warm:
+	/* disable everything */
+	li	r0, 0
+	mtspr	HID0, r0
+	sync
+	mtmsr	0
+	bl	invalidate_bats
+	sync
+
+#ifdef CONFIG_SYS_L2
+	/* init the L2 cache */
+	addis	r3, r0, L2_INIT@h
+	ori	r3, r3, L2_INIT@l
+	sync
+	mtspr	l2cr, r3
+#endif
+#if defined(CONFIG_ALTIVEC) && defined(CONFIG_74xx)
+	.long	0x7e00066c
+		/*
+		 * dssall instruction, gas doesn't have it yet
+		 * ...for altivec, data stream stop all this probably
+		 * isn't needed unless we warm (software) reboot U-Boot
+		 */
+#endif
+
+#ifdef CONFIG_SYS_L2
+	/* invalidate the L2 cache */
+	bl	l2cache_invalidate
+	sync
+#endif
+#ifdef CONFIG_SYS_BOARD_ASM_INIT
+	/* do early init */
+	bl	board_asm_init
+#endif
+
+	/*
+	 * Calculate absolute address in FLASH and jump there
+	 *------------------------------------------------------*/
+	lis	r3, CONFIG_SYS_MONITOR_BASE@h
+	ori	r3, r3, CONFIG_SYS_MONITOR_BASE@l
+	addi	r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+	mtlr	r3
+	blr
+
+in_flash:
+	/* let the C-code set up the rest			*/
+	/*							*/
+	/* Be careful to keep code relocatable !		*/
+	/*------------------------------------------------------*/
+
+	/* perform low-level init */
+	/* sdram init, galileo init, etc */
+	/* r3:	NHR bit from HID0 */
+
+	/* setup the bats */
+	bl	setup_bats
+	sync
+
+	/*
+	 * Cache must be enabled here for stack-in-cache trick.
+	 * This means we need to enable the BATS.
+	 * This means:
+	 *   1) for the EVB, original gt regs need to be mapped
+	 *   2) need to have an IBAT for the 0xf region,
+	 *      we are running there!
+	 * Cache should be turned on after BATs, since by default
+	 * everything is write-through.
+	 * The init-mem BAT can be reused after reloc. The old
+	 * gt-regs BAT can be reused after board_init_f calls
+	 * board_early_init_f (EVB only).
+	 */
+#if !defined(CONFIG_BAB7xx) && !defined(CONFIG_ELPPC) && !defined(CONFIG_P3Mx)
+	/* enable address translation */
+	bl	enable_addr_trans
+	sync
+
+	/* enable and invalidate the data cache */
+	bl	l1dcache_enable
+	sync
+#endif
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+	bl	lock_ram_in_cache
+	sync
+#endif
+
+	/* set up the stack pointer in our newly created
+	 * cache-ram (r1) */
+	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
+	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
+
+	li	r0, 0		/* Make room for stack frame header and	*/
+	stwu	r0, -4(r1)	/* clear final stack frame so that	*/
+	stwu	r0, -4(r1)	/* stack backtraces terminate cleanly	*/
+
+	GET_GOT			/* initialize GOT access	*/
+
+	/* run low-level CPU init code     (from Flash)	*/
+	bl	cpu_init_f
+	sync
+
+	mr	r3, r21
+
+	/* r3: BOOTFLAG */
+	/* run 1st part of board init code (from Flash)   */
+	bl	board_init_f
+	sync
+
+	/* NOTREACHED */
+
+	.globl	invalidate_bats
+invalidate_bats:
+	/* invalidate BATs */
+	mtspr	IBAT0U, r0
+	mtspr	IBAT1U, r0
+	mtspr	IBAT2U, r0
+	mtspr	IBAT3U, r0
+#ifdef CONFIG_HIGH_BATS
+	mtspr   IBAT4U, r0
+	mtspr   IBAT5U, r0
+	mtspr   IBAT6U, r0
+	mtspr   IBAT7U, r0
+#endif
+	isync
+	mtspr	DBAT0U, r0
+	mtspr	DBAT1U, r0
+	mtspr	DBAT2U, r0
+	mtspr	DBAT3U, r0
+#ifdef CONFIG_HIGH_BATS
+	mtspr   DBAT4U, r0
+	mtspr   DBAT5U, r0
+	mtspr   DBAT6U, r0
+	mtspr   DBAT7U, r0
+#endif
+	isync
+	sync
+	blr
+
+	/* setup_bats - set them up to some initial state */
+	.globl	setup_bats
+setup_bats:
+	addis	r0, r0, 0x0000
+
+	/* IBAT 0 */
+	addis	r4, r0, CONFIG_SYS_IBAT0L@h
+	ori	r4, r4, CONFIG_SYS_IBAT0L@l
+	addis	r3, r0, CONFIG_SYS_IBAT0U@h
+	ori	r3, r3, CONFIG_SYS_IBAT0U@l
+	mtspr	IBAT0L, r4
+	mtspr	IBAT0U, r3
+	isync
+
+	/* DBAT 0 */
+	addis	r4, r0, CONFIG_SYS_DBAT0L@h
+	ori	r4, r4, CONFIG_SYS_DBAT0L@l
+	addis	r3, r0, CONFIG_SYS_DBAT0U@h
+	ori	r3, r3, CONFIG_SYS_DBAT0U@l
+	mtspr	DBAT0L, r4
+	mtspr	DBAT0U, r3
+	isync
+
+	/* IBAT 1 */
+	addis	r4, r0, CONFIG_SYS_IBAT1L@h
+	ori	r4, r4, CONFIG_SYS_IBAT1L@l
+	addis	r3, r0, CONFIG_SYS_IBAT1U@h
+	ori	r3, r3, CONFIG_SYS_IBAT1U@l
+	mtspr	IBAT1L, r4
+	mtspr	IBAT1U, r3
+	isync
+
+	/* DBAT 1 */
+	addis	r4, r0, CONFIG_SYS_DBAT1L@h
+	ori	r4, r4, CONFIG_SYS_DBAT1L@l
+	addis	r3, r0, CONFIG_SYS_DBAT1U@h
+	ori	r3, r3, CONFIG_SYS_DBAT1U@l
+	mtspr	DBAT1L, r4
+	mtspr	DBAT1U, r3
+	isync
+
+	/* IBAT 2 */
+	addis	r4, r0, CONFIG_SYS_IBAT2L@h
+	ori	r4, r4, CONFIG_SYS_IBAT2L@l
+	addis	r3, r0, CONFIG_SYS_IBAT2U@h
+	ori	r3, r3, CONFIG_SYS_IBAT2U@l
+	mtspr	IBAT2L, r4
+	mtspr	IBAT2U, r3
+	isync
+
+	/* DBAT 2 */
+	addis	r4, r0, CONFIG_SYS_DBAT2L@h
+	ori	r4, r4, CONFIG_SYS_DBAT2L@l
+	addis	r3, r0, CONFIG_SYS_DBAT2U@h
+	ori	r3, r3, CONFIG_SYS_DBAT2U@l
+	mtspr	DBAT2L, r4
+	mtspr	DBAT2U, r3
+	isync
+
+	/* IBAT 3 */
+	addis	r4, r0, CONFIG_SYS_IBAT3L@h
+	ori	r4, r4, CONFIG_SYS_IBAT3L@l
+	addis	r3, r0, CONFIG_SYS_IBAT3U@h
+	ori	r3, r3, CONFIG_SYS_IBAT3U@l
+	mtspr	IBAT3L, r4
+	mtspr	IBAT3U, r3
+	isync
+
+	/* DBAT 3 */
+	addis	r4, r0, CONFIG_SYS_DBAT3L@h
+	ori	r4, r4, CONFIG_SYS_DBAT3L@l
+	addis	r3, r0, CONFIG_SYS_DBAT3U@h
+	ori	r3, r3, CONFIG_SYS_DBAT3U@l
+	mtspr	DBAT3L, r4
+	mtspr	DBAT3U, r3
+	isync
+
+#ifdef CONFIG_HIGH_BATS
+	/* IBAT 4 */
+	addis   r4, r0, CONFIG_SYS_IBAT4L@h
+	ori     r4, r4, CONFIG_SYS_IBAT4L@l
+	addis   r3, r0, CONFIG_SYS_IBAT4U@h
+	ori     r3, r3, CONFIG_SYS_IBAT4U@l
+	mtspr   IBAT4L, r4
+	mtspr   IBAT4U, r3
+	isync
+
+	/* DBAT 4 */
+	addis   r4, r0, CONFIG_SYS_DBAT4L@h
+	ori     r4, r4, CONFIG_SYS_DBAT4L@l
+	addis   r3, r0, CONFIG_SYS_DBAT4U@h
+	ori     r3, r3, CONFIG_SYS_DBAT4U@l
+	mtspr   DBAT4L, r4
+	mtspr   DBAT4U, r3
+	isync
+
+	/* IBAT 5 */
+	addis   r4, r0, CONFIG_SYS_IBAT5L@h
+	ori     r4, r4, CONFIG_SYS_IBAT5L@l
+	addis   r3, r0, CONFIG_SYS_IBAT5U@h
+	ori     r3, r3, CONFIG_SYS_IBAT5U@l
+	mtspr   IBAT5L, r4
+	mtspr   IBAT5U, r3
+	isync
+
+	/* DBAT 5 */
+	addis   r4, r0, CONFIG_SYS_DBAT5L@h
+	ori     r4, r4, CONFIG_SYS_DBAT5L@l
+	addis   r3, r0, CONFIG_SYS_DBAT5U@h
+	ori     r3, r3, CONFIG_SYS_DBAT5U@l
+	mtspr   DBAT5L, r4
+	mtspr   DBAT5U, r3
+	isync
+
+	/* IBAT 6 */
+	addis   r4, r0, CONFIG_SYS_IBAT6L@h
+	ori     r4, r4, CONFIG_SYS_IBAT6L@l
+	addis   r3, r0, CONFIG_SYS_IBAT6U@h
+	ori     r3, r3, CONFIG_SYS_IBAT6U@l
+	mtspr   IBAT6L, r4
+	mtspr   IBAT6U, r3
+	isync
+
+	/* DBAT 6 */
+	addis   r4, r0, CONFIG_SYS_DBAT6L@h
+	ori     r4, r4, CONFIG_SYS_DBAT6L@l
+	addis   r3, r0, CONFIG_SYS_DBAT6U@h
+	ori     r3, r3, CONFIG_SYS_DBAT6U@l
+	mtspr   DBAT6L, r4
+	mtspr   DBAT6U, r3
+	isync
+
+	/* IBAT 7 */
+	addis   r4, r0, CONFIG_SYS_IBAT7L@h
+	ori     r4, r4, CONFIG_SYS_IBAT7L@l
+	addis   r3, r0, CONFIG_SYS_IBAT7U@h
+	ori     r3, r3, CONFIG_SYS_IBAT7U@l
+	mtspr   IBAT7L, r4
+	mtspr   IBAT7U, r3
+	isync
+
+	/* DBAT 7 */
+	addis   r4, r0, CONFIG_SYS_DBAT7L@h
+	ori     r4, r4, CONFIG_SYS_DBAT7L@l
+	addis   r3, r0, CONFIG_SYS_DBAT7U@h
+	ori     r3, r3, CONFIG_SYS_DBAT7U@l
+	mtspr   DBAT7L, r4
+	mtspr   DBAT7U, r3
+	isync
+#endif
+
+	/* bats are done, now invalidate the TLBs */
+
+	addis	r3, 0, 0x0000
+	addis	r5, 0, 0x4    /* upper bound of 0x00040000 for 7400/750 */
+
+	isync
+
+tlblp:
+	tlbie	r3
+	sync
+	addi	r3, r3, 0x1000
+	cmp	0, 0, r3, r5
+	blt tlblp
+
+	blr
+
+	.globl enable_addr_trans
+enable_addr_trans:
+	/* enable address translation */
+	mfmsr	r5
+	ori	r5, r5, (MSR_IR | MSR_DR)
+	mtmsr	r5
+	isync
+	blr
+
+	.globl disable_addr_trans
+disable_addr_trans:
+	/* disable address translation */
+	mflr	r4
+	mfmsr	r3
+	andi.	r0, r3, (MSR_IR | MSR_DR)
+	beqlr
+	andc	r3, r3, r0
+	mtspr	SRR0, r4
+	mtspr	SRR1, r3
+	rfi
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+	.globl	transfer_to_handler
+transfer_to_handler:
+	stw	r22,_NIP(r21)
+	lis	r22,MSR_POW@h
+	andc	r23,r23,r22
+	stw	r23,_MSR(r21)
+	SAVE_GPR(7, r21)
+	SAVE_4GPRS(8, r21)
+	SAVE_8GPRS(12, r21)
+	SAVE_8GPRS(24, r21)
+	mflr	r23
+	andi.	r24,r23,0x3f00		/* get vector offset */
+	stw	r24,TRAP(r21)
+	li	r22,0
+	stw	r22,RESULT(r21)
+	mtspr	SPRG2,r22		/* r1 is now kernel sp */
+	lwz	r24,0(r23)		/* virtual address of handler */
+	lwz	r23,4(r23)		/* where to go when done */
+	mtspr	SRR0,r24
+	mtspr	SRR1,r20
+	mtlr	r23
+	SYNC
+	rfi				/* jump to handler, enable MMU */
+
+int_return:
+	mfmsr	r28		/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC			/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SRR0,r2
+	mtspr	SRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfi
+
+	.globl	dc_read
+dc_read:
+	blr
+
+	.globl get_pvr
+get_pvr:
+	mfspr	r3, PVR
+	blr
+
+/*-----------------------------------------------------------------------*/
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+	.globl	relocate_code
+relocate_code:
+	mr	r1,  r3		/* Set new stack pointer		*/
+	mr	r9,  r4		/* Save copy of Global Data pointer	*/
+	mr	r10, r5		/* Save copy of Destination Address	*/
+
+	GET_GOT
+	mr	r3,  r5				/* Destination Address	*/
+	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address	*/
+	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
+	lwz	r5, GOT(__init_end)
+	sub	r5, r5, r4
+	li	r6, CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size	*/
+
+	/*
+	 * Fix GOT pointer:
+	 *
+	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+	 *
+	 * Offset:
+	 */
+	sub	r15, r10, r4
+
+	/* First our own GOT */
+	add	r12, r12, r15
+	/* then the one used by the C code */
+	add	r30, r30, r15
+
+	/*
+	 * Now relocate code
+	 */
+#ifdef CONFIG_ECC
+	bl	board_relocate_rom
+	sync
+	mr	r3, r10				/* Destination Address	*/
+	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address	*/
+	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
+	lwz	r5, GOT(__init_end)
+	sub	r5, r5, r4
+	li	r6, CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size	*/
+#else
+	cmplw	cr1,r3,r4
+	addi	r0,r5,3
+	srwi.	r0,r0,2
+	beq	cr1,4f		/* In place copy is not necessary	*/
+	beq	7f		/* Protect against 0 count		*/
+	mtctr	r0
+	bge	cr1,2f
+
+	la	r8,-4(r4)
+	la	r7,-4(r3)
+1:	lwzu	r0,4(r8)
+	stwu	r0,4(r7)
+	bdnz	1b
+	b	4f
+
+2:	slwi	r0,r0,2
+	add	r8,r4,r0
+	add	r7,r3,r0
+3:	lwzu	r0,-4(r8)
+	stwu	r0,-4(r7)
+	bdnz	3b
+#endif
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:	cmpwi	r6,0
+	add	r5,r3,r5
+	beq	7f		/* Always flush prefetch queue in any case */
+	subi	r0,r6,1
+	andc	r3,r3,r0
+	mr	r4,r3
+5:	dcbst	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	5b
+	sync			/* Wait for all dcbst to complete on bus */
+	mr	r4,r3
+6:	icbi	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	6b
+7:	sync			/* Wait for all icbi to complete on bus	*/
+	isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+	mtlr	r0
+	blr
+
+in_ram:
+#ifdef CONFIG_ECC
+	bl	board_init_ecc
+#endif
+	/*
+	 * Relocation Function, r12 point to got2+0x8000
+	 *
+	 * Adjust got2 pointers, no need to check for 0, this code
+	 * already puts a few entries in the table.
+	 */
+	li	r0,__got2_entries@sectoff@l
+	la	r3,GOT(_GOT2_TABLE_)
+	lwz	r11,GOT(_GOT2_TABLE_)
+	mtctr	r0
+	sub	r11,r3,r11
+	addi	r3,r3,-4
+1:	lwzu	r0,4(r3)
+	cmpwi	r0,0
+	beq-	2f
+	add	r0,r0,r11
+	stw	r0,0(r3)
+2:	bdnz	1b
+
+	/*
+	 * Now adjust the fixups and the pointers to the fixups
+	 * in case we need to move ourselves again.
+	 */
+	li	r0,__fixup_entries@sectoff@l
+	lwz	r3,GOT(_FIXUP_TABLE_)
+	cmpwi	r0,0
+	mtctr	r0
+	addi	r3,r3,-4
+	beq	4f
+3:	lwzu	r4,4(r3)
+	lwzux	r0,r4,r11
+	add	r0,r0,r11
+	stw	r10,0(r3)
+	stw	r0,0(r4)
+	bdnz	3b
+4:
+/* clear_bss: */
+	/*
+	 * Now clear BSS segment
+	 */
+	lwz	r3,GOT(__bss_start)
+	lwz	r4,GOT(_end)
+
+	cmplw	0, r3, r4
+	beq	6f
+
+	li	r0, 0
+5:
+	stw	r0, 0(r3)
+	addi	r3, r3, 4
+	cmplw	0, r3, r4
+	bne	5b
+6:
+	mr	r3, r10		/* Destination Address		*/
+#if defined(CONFIG_AMIGAONEG3SE) || \
+    defined(CONFIG_DB64360)	 || \
+    defined(CONFIG_DB64460)      || \
+    defined(CONFIG_CPCI750)	|| \
+    defined(CONFIG_PPMC7XX)     || \
+    defined(CONFIG_P3Mx)
+	mr	r4, r9		/* Use RAM copy of the global data */
+#endif
+	bl	after_reloc
+
+	/* not reached - end relocate_code */
+/*-----------------------------------------------------------------------*/
+
+	/*
+	 * Copy exception vector code to low memory
+	 *
+	 * r3: dest_addr
+	 * r7: source address, r8: end address, r9: target address
+	 */
+	.globl	trap_init
+trap_init:
+	mflr	r4			/* save link register		*/
+	GET_GOT
+	lwz	r7, GOT(_start)
+	lwz	r8, GOT(_end_of_vectors)
+
+	li	r9, 0x100		/* reset vector always at 0x100 */
+
+	cmplw	0, r7, r8
+	bgelr				/* return if r7>=r8 - just in case */
+1:
+	lwz	r0, 0(r7)
+	stw	r0, 0(r9)
+	addi	r7, r7, 4
+	addi	r9, r9, 4
+	cmplw	0, r7, r8
+	bne	1b
+
+	/*
+	 * relocate `hdlr' and `int_return' entries
+	 */
+	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+	li	r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	2b
+
+	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	3b
+
+	li	r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	4b
+
+	/* enable execptions from RAM vectors */
+	mfmsr	r7
+	li	r8,MSR_IP
+	andc	r7,r7,r8
+	mtmsr	r7
+
+	mtlr	r4			/* restore link register	*/
+	blr
+
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+lock_ram_in_cache:
+	/* Allocate Initial RAM in data cache.
+	 */
+	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
+	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
+	li	r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \
+		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
+	mtctr	r4
+1:
+	dcbz	r0, r3
+	addi	r3, r3, 32
+	bdnz	1b
+
+	/* Lock the data cache */
+	mfspr	r0, HID0
+	ori	r0, r0, 0x1000
+	sync
+	mtspr	HID0, r0
+	sync
+	blr
+
+.globl unlock_ram_in_cache
+unlock_ram_in_cache:
+	/* invalidate the INIT_RAM section */
+	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
+	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
+	li	r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \
+		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
+	mtctr	r4
+1:	icbi	r0, r3
+	addi	r3, r3, 32
+	bdnz	1b
+	sync			/* Wait for all icbi to complete on bus	*/
+	isync
+
+	/* Unlock the data cache and invalidate it */
+	mfspr   r0, HID0
+	li      r3,0x1000
+	andc    r0,r0,r3
+	li	r3,0x0400
+	or	r0,r0,r3
+	sync
+	mtspr   HID0, r0
+	sync
+	blr
+#endif
diff --git a/arch/powerpc/cpu/74xx_7xx/traps.c b/arch/powerpc/cpu/74xx_7xx/traps.c
new file mode 100644
index 0000000..5073b05
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/traps.c
@@ -0,0 +1,252 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+#ifdef CONFIG_AMIGAONEG3SE
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#ifdef CONFIG_AMIGAONEG3SE
+#define END_OF_MEM (gd->bd->bi_memstart + gd->bd->bi_memsize)
+#else
+#define END_OF_MEM	0x02000000
+#endif
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace(unsigned long *sp)
+{
+	int cnt = 0;
+	unsigned long i;
+
+	printf("Call backtrace: ");
+	while (sp) {
+		if ((uint)sp > END_OF_MEM)
+			break;
+
+		i = sp[1];
+		if (cnt++ % 7 == 0)
+			printf("\n");
+		printf("%08lX ", i);
+		if (cnt > 32) break;
+		sp = (unsigned long *)*sp;
+	}
+	printf("\n");
+}
+
+void
+show_regs(struct pt_regs * regs)
+{
+	int i;
+
+	printf("NIP: %08lX XER: %08lX LR: %08lX REGS:"
+	       " %p TRAP: %04lx DAR: %08lX\n",
+	       regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+	printf("MSR: %08lx EE: %01x PR: %01x FP:"
+	       " %01x ME: %01x IR/DR: %01x%01x\n",
+	       regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+	       regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+	       regs->msr&MSR_IR ? 1 : 0,
+	       regs->msr&MSR_DR ? 1 : 0);
+
+	printf("\n");
+	for (i = 0;  i < 32;  i++) {
+		if ((i % 8) == 0)
+		{
+			printf("GPR%02d: ", i);
+		}
+
+		printf("%08lX ", regs->gpr[i]);
+		if ((i % 8) == 7)
+		{
+			printf("\n");
+		}
+	}
+}
+
+
+void
+_exception(int signr, struct pt_regs *regs)
+{
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+void
+MachineCheckException(struct pt_regs *regs)
+{
+	unsigned long fixup;
+
+	/* Probing PCI using config cycles cause this exception
+	 * when a device is not present.  Catch it and return to
+	 * the PCI exception handler.
+	 */
+	if ((fixup = search_exception_table(regs->nip)) != 0) {
+		regs->nip = fixup;
+		return;
+	}
+
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	printf("Machine check in kernel mode.\n");
+	printf("Caused by (from msr): ");
+	printf("regs %p ",regs);
+	switch( regs->msr & 0x000F0000) {
+	case (0x80000000>>12):
+		printf("Machine check signal - probably due to mm fault\n"
+			"with mmu off\n");
+		break;
+	case (0x80000000>>13):
+		printf("Transfer error ack signal\n");
+		break;
+	case (0x80000000>>14):
+		printf("Data parity signal\n");
+		break;
+	case (0x80000000>>15):
+		printf("Address parity signal\n");
+		break;
+	default:
+		printf("Unknown values in msr\n");
+	}
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+	unsigned char *p = regs ? (unsigned char *)(regs->nip) : NULL;
+	int i, j;
+
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+
+	p = (unsigned char *) ((unsigned long)p & 0xFFFFFFE0);
+	p -= 32;
+	for (i = 0; i < 256; i+=16) {
+		printf("%08x: ", (unsigned int)p+i);
+		for (j = 0; j < 16; j++) {
+			printf("%02x ", p[i+j]);
+		}
+		printf("\n");
+	}
+
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Program Check Exception");
+}
+
+void
+SoftEmuException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Software Emulation Exception");
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+	       regs->nip, regs->msr, regs->trap);
+	_exception(0, regs);
+}
+
+/* Probe an address by reading.  If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+#if 0
+	int	retval;
+
+	__asm__ __volatile__(			\
+		"1:	lwz %0,0(%1)\n"		\
+		"	eieio\n"		\
+		"	li %0,0\n"		\
+		"2:\n"				\
+		".section .fixup,\"ax\"\n"	\
+		"3:	li %0,-1\n"		\
+		"	b 2b\n"			\
+		".section __ex_table,\"a\"\n"	\
+		"	.align 2\n"		\
+		"	.long 1b,3b\n"		\
+		".text"				\
+		: "=r" (retval) : "r"(addr));
+
+	return (retval);
+#endif
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc512x/Makefile b/arch/powerpc/cpu/mpc512x/Makefile
new file mode 100644
index 0000000..1719c66
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/Makefile
@@ -0,0 +1,63 @@
+#
+# (C) Copyright 2007-2009 DENX Software Engineering
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+$(shell mkdir -p $(OBJTREE)/board/freescale/common)
+
+LIB	= $(obj)lib$(CPU).a
+
+START	= start.o
+COBJS-y	:= cpu.o
+COBJS-y	+= traps.o
+COBJS-y += cpu_init.o
+COBJS-y += fixed_sdram.o
+COBJS-y += i2c.o
+COBJS-y += interrupts.o
+COBJS-y += iopin.o
+COBJS-y += serial.o
+COBJS-y += speed.o
+COBJS-${CONFIG_FSL_DIU_FB} += diu.o
+COBJS-${CONFIG_FSL_DIU_FB} += ../../../../board/freescale/common/fsl_diu_fb.o
+COBJS-${CONFIG_FSL_DIU_FB} += ../../../../board/freescale/common/fsl_logo_bmp.o
+COBJS-${CONFIG_CMD_IDE} += ide.o
+COBJS-${CONFIG_IIM} += iim.o
+COBJS-$(CONFIG_PCI) += pci.o
+
+COBJS	:= $(COBJS-y)
+SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc512x/asm-offsets.h b/arch/powerpc/cpu/mpc512x/asm-offsets.h
new file mode 100644
index 0000000..957d4be2
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/asm-offsets.h
@@ -0,0 +1,15 @@
+/*
+ * needed for arch/powerpc/cpu/mpc512x/start.S
+ *
+ * These should be auto-generated
+ */
+#define LPCS0AW			0x0024
+#define SRAMBAR			0x00C4
+#define SWCRR			0x0904
+#define LPC_OFFSET		0x10000
+#define CS0_CONFIG		0x00000
+#define CS_CTRL			0x00020
+#define CS_CTRL_ME		0x01000000	/* CS Master Enable bit */
+
+#define EXC_OFF_SYS_RESET	0x0100
+#define	_START_OFFSET		EXC_OFF_SYS_RESET
diff --git a/arch/powerpc/cpu/mpc512x/config.mk b/arch/powerpc/cpu/mpc512x/config.mk
new file mode 100644
index 0000000..b29edb1
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/config.mk
@@ -0,0 +1,29 @@
+#
+# (C) Copyright 2007-2009 DENX Software Engineering
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+PLATFORM_RELFLAGS += -fPIC -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_MPC512X -DCONFIG_E300 \
+			-ffixed-r2 -msoft-float -mcpu=603e
+
+# Use default linker script.
+# A board port can override this setting in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/arch/powerpc/cpu/mpc512x/u-boot.lds
diff --git a/arch/powerpc/cpu/mpc512x/cpu.c b/arch/powerpc/cpu/mpc512x/cpu.c
new file mode 100644
index 0000000..09cbd20
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/cpu.c
@@ -0,0 +1,216 @@
+/*
+ * (C) Copyright 2007-2010 DENX Software Engineering
+ * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * CPU specific code for the MPC512x family.
+ *
+ * Derived from the MPC83xx code.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <netdev.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <fdt_support.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int checkcpu (void)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	ulong clock = gd->cpu_clk;
+	u32 pvr = get_pvr ();
+	u32 spridr = in_be32(&immr->sysconf.spridr);
+	char buf1[32], buf2[32];
+
+	puts ("CPU:   ");
+
+	switch (spridr & 0xffff0000) {
+	case SPR_5121E:
+		puts ("MPC5121e ");
+		break;
+	default:
+		printf ("Unknown part ID %08x ", spridr & 0xffff0000);
+	}
+	printf ("rev. %d.%d, Core ", SVR_MJREV (spridr), SVR_MNREV (spridr));
+
+	switch (pvr & 0xffff0000) {
+	case PVR_E300C4:
+		puts ("e300c4 ");
+		break;
+	default:
+		puts ("unknown ");
+	}
+	printf ("at %s MHz, CSB at %s MHz (RSR=0x%04lx)\n",
+		strmhz(buf1, clock),
+		strmhz(buf2, gd->csb_clk),
+		gd->reset_status & 0xffff);
+	return 0;
+}
+
+
+int
+do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	ulong msr;
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+
+	/* Interrupts and MMU off */
+	__asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
+
+	msr &= ~( MSR_EE | MSR_IR | MSR_DR);
+	__asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
+
+	/*
+	 * Enable Reset Control Reg - "RSTE" is the magic word that let us go
+	 */
+	out_be32(&immap->reset.rpr, 0x52535445);
+
+	/* Verify Reset Control Reg is enabled */
+	while (!(in_be32(&immap->reset.rcer) & RCER_CRE))
+		;
+
+	printf ("Resetting the board.\n");
+	udelay(200);
+
+	/* Perform reset */
+	out_be32(&immap->reset.rcr, RCR_SWHR);
+
+	/* Unreached... */
+	return 1;
+}
+
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ */
+unsigned long get_tbclk (void)
+{
+	ulong tbclk;
+
+	tbclk = (gd->bus_clk + 3L) / 4L;
+
+	return tbclk;
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset (void)
+{
+	int re_enable = disable_interrupts ();
+
+	/* Reset watchdog */
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	out_be32(&immr->wdt.swsrr, 0x556c);
+	out_be32(&immr->wdt.swsrr, 0xaa39);
+
+	if (re_enable)
+		enable_interrupts ();
+}
+#endif
+
+#ifdef CONFIG_OF_LIBFDT
+
+#ifdef CONFIG_OF_SUPPORT_OLD_DEVICE_TREES
+/*
+ * fdt setup for old device trees
+ * fix up
+ * 	cpu clocks
+ * 	soc clocks
+ * 	ethernet addresses
+ */
+static void old_ft_cpu_setup(void *blob, bd_t *bd)
+{
+	/*
+	 * avoid fixing up by path because that
+	 * produces scary error messages
+	 */
+	uchar enetaddr[6];
+
+	/*
+	 * old device trees have ethernet nodes with
+	 * device_type = "network"
+	 */
+	eth_getenv_enetaddr("ethaddr", enetaddr);
+	do_fixup_by_prop(blob, "device_type", "network", 8,
+		"local-mac-address", enetaddr, 6, 0);
+	do_fixup_by_prop(blob, "device_type", "network", 8,
+		"address", enetaddr, 6, 0);
+	/*
+	 * old device trees have soc nodes with
+	 * device_type = "soc"
+	 */
+	do_fixup_by_prop_u32(blob, "device_type", "soc", 4,
+		"bus-frequency", bd->bi_ipsfreq, 0);
+}
+#endif
+
+static void ft_clock_setup(void *blob, bd_t *bd)
+{
+	char *cpu_path = "/cpus/" OF_CPU;
+
+	/*
+	 * fixup cpu clocks using path
+	 */
+	do_fixup_by_path_u32(blob, cpu_path,
+		"timebase-frequency", OF_TBCLK, 1);
+	do_fixup_by_path_u32(blob, cpu_path,
+		"bus-frequency", bd->bi_busfreq, 1);
+	do_fixup_by_path_u32(blob, cpu_path,
+		"clock-frequency", bd->bi_intfreq, 1);
+	/*
+	 * fixup soc clocks using compatible
+	 */
+	do_fixup_by_compat_u32(blob, OF_SOC_COMPAT,
+		"bus-frequency", bd->bi_ipsfreq, 1);
+}
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+#ifdef CONFIG_OF_SUPPORT_OLD_DEVICE_TREES
+	old_ft_cpu_setup(blob, bd);
+#endif
+	ft_clock_setup(blob, bd);
+#ifdef CONFIG_HAS_ETH0
+	fdt_fixup_ethernet(blob);
+#endif
+	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+}
+#endif
+
+#ifdef CONFIG_MPC512x_FEC
+/* Default initializations for FEC controllers.  To override,
+ * create a board-specific function called:
+ * 	int board_eth_init(bd_t *bis)
+ */
+
+int cpu_eth_init(bd_t *bis)
+{
+	return mpc512x_fec_initialize(bis);
+}
+#endif
diff --git a/arch/powerpc/cpu/mpc512x/cpu_init.c b/arch/powerpc/cpu/mpc512x/cpu_init.c
new file mode 100644
index 0000000..fe6beaf
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/cpu_init.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
+ * Copyright (C) 2007-2009 DENX Software Engineering
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Derived from the MPC83xx code.
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Set up the memory map, initialize registers,
+ */
+void cpu_init_f (volatile immap_t * im)
+{
+	u32 ips_div;
+
+	/* Pointer is writable since we allocated a register for it */
+	gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+	/* Clear initial global data */
+	memset ((void *) gd, 0, sizeof (gd_t));
+
+	/* system performance tweaking */
+
+#ifdef CONFIG_SYS_ACR_PIPE_DEP
+	/* Arbiter pipeline depth */
+	out_be32(&im->arbiter.acr,
+		(im->arbiter.acr & ~ACR_PIPE_DEP) |
+		(CONFIG_SYS_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT)
+	);
+#endif
+
+#ifdef CONFIG_SYS_ACR_RPTCNT
+	/* Arbiter repeat count */
+	out_be32(im->arbiter.acr,
+		(im->arbiter.acr & ~(ACR_RPTCNT)) |
+		(CONFIG_SYS_ACR_RPTCNT << ACR_RPTCNT_SHIFT)
+	);
+#endif
+
+	/* RSR - Reset Status Register - clear all status */
+	gd->reset_status = im->reset.rsr;
+	out_be32(&im->reset.rsr, ~RSR_RES);
+
+	/*
+	 * RMR - Reset Mode Register - enable checkstop reset
+	 */
+	out_be32(&im->reset.rmr, RMR_CSRE & (1 << RMR_CSRE_SHIFT));
+
+	/* Set IPS-CSB divider: IPS = 1/2 CSB */
+	ips_div = in_be32(&im->clk.scfr[0]);
+	ips_div &= ~(SCFR1_IPS_DIV_MASK);
+	ips_div |= SCFR1_IPS_DIV << SCFR1_IPS_DIV_SHIFT;
+	out_be32(&im->clk.scfr[0], ips_div);
+
+	/*
+	 * Enable Time Base/Decrementer
+	 *
+	 * NOTICE: TB needs to be enabled as early as possible in order to
+	 * have udelay() working; if not enabled, usually leads to a hang, like
+	 * during FLASH chip identification etc.
+	 */
+	setbits_be32(&im->sysconf.spcr, SPCR_TBEN);
+}
+
+int cpu_init_r (void)
+{
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc512x/diu.c b/arch/powerpc/cpu/mpc512x/diu.c
new file mode 100644
index 0000000..9361161
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/diu.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ * York Sun <yorksun@freescale.com>
+ *
+ * FSL DIU Framebuffer driver
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/io.h>
+
+#include "../../../../board/freescale/common/fsl_diu_fb.h"
+
+#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
+#include <stdio_dev.h>
+#include <video_fb.h>
+#endif
+
+#ifdef CONFIG_FSL_DIU_LOGO_BMP
+extern unsigned int FSL_Logo_BMP[];
+#else
+#define FSL_Logo_BMP NULL
+#endif
+
+static int xres, yres;
+
+void diu_set_pixel_clock(unsigned int pixclock)
+{
+	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+	volatile clk512x_t *clk = &immap->clk;
+	volatile unsigned int *clkdvdr = &clk->scfr[0];
+	unsigned long speed_ccb, temp, pixval;
+
+	speed_ccb = get_bus_freq(0) * 4;
+	temp = 1000000000/pixclock;
+	temp *= 1000;
+	pixval = speed_ccb / temp;
+	debug("DIU pixval = %lu\n", pixval);
+
+	/* Modify PXCLK in GUTS CLKDVDR */
+	debug("DIU: Current value of CLKDVDR = 0x%08x\n", in_be32(clkdvdr));
+	temp = in_be32(clkdvdr) & 0xFFFFFF00;
+	out_be32(clkdvdr, temp | (pixval & 0xFF));
+	debug("DIU: Modified value of CLKDVDR = 0x%08x\n", in_be32(clkdvdr));
+}
+
+char *valid_bmp(char *addr)
+{
+	unsigned long h_addr;
+
+	h_addr = simple_strtoul(addr, NULL, 16);
+	if (h_addr < CONFIG_SYS_FLASH_BASE ||
+			h_addr >= (CONFIG_SYS_FLASH_BASE + CONFIG_SYS_FLASH_SIZE - 1)) {
+		printf("bmp addr %lx is not a valid flash address\n", h_addr);
+		return 0;
+	} else if ((*(char *)(h_addr) != 'B') || (*(char *)(h_addr+1) != 'M')) {
+		printf("bmp addr is not a bmp\n");
+		return 0;
+	} else
+		return (char *)h_addr;
+}
+
+int mpc5121_diu_init(void)
+{
+	unsigned int pixel_format;
+	char *bmp = NULL;
+	char *bmp_env;
+
+	xres = 1024;
+	yres = 768;
+	pixel_format = 0x88883316;
+
+	debug("mpc5121_diu_init\n");
+	bmp_env = getenv("diu_bmp_addr");
+	if (bmp_env) {
+		bmp = valid_bmp(bmp_env);
+	}
+	if (!bmp)
+		bmp = (char *)FSL_Logo_BMP;
+	return fsl_diu_init(xres, pixel_format, 0, (unsigned char *)bmp);
+}
+
+int mpc5121diu_init_show_bmp(cmd_tbl_t *cmdtp,
+			     int flag, int argc, char *argv[])
+{
+	unsigned int addr;
+
+	if (argc < 2) {
+		cmd_usage(cmdtp);
+		return 1;
+	}
+
+	if (!strncmp(argv[1], "init", 4)) {
+#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
+		fsl_diu_clear_screen();
+		drv_video_init();
+#else
+		return mpc5121_diu_init();
+#endif
+	} else {
+		addr = simple_strtoul(argv[1], NULL, 16);
+		fsl_diu_clear_screen();
+		fsl_diu_display_bmp((unsigned char *)addr, 0, 0, 0);
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	diufb, CONFIG_SYS_MAXARGS, 1, mpc5121diu_init_show_bmp,
+	"Init or Display BMP file",
+	"init\n    - initialize DIU\n"
+	"addr\n    - display bmp at address 'addr'"
+	);
+
+
+#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
+
+/*
+ * The Graphic Device
+ */
+GraphicDevice ctfb;
+void *video_hw_init(void)
+{
+	GraphicDevice *pGD = (GraphicDevice *) &ctfb;
+	struct fb_info *info;
+
+	if (mpc5121_diu_init() < 0)
+		return NULL;
+
+	/* fill in Graphic device struct */
+	sprintf(pGD->modeIdent, "%dx%dx%d %dkHz %dHz",
+		xres, yres, 32, 64, 60);
+
+	pGD->frameAdrs = (unsigned int)fsl_fb_open(&info);
+	pGD->winSizeX = xres;
+	pGD->winSizeY = yres - info->logo_height;
+	pGD->plnSizeX = pGD->winSizeX;
+	pGD->plnSizeY = pGD->winSizeY;
+
+	pGD->gdfBytesPP = 4;
+	pGD->gdfIndex = GDF_32BIT_X888RGB;
+
+	pGD->isaBase = 0;
+	pGD->pciBase = 0;
+	pGD->memSize = info->screen_size - info->logo_size;
+
+	/* Cursor Start Address */
+	pGD->dprBase = 0;
+	pGD->vprBase = 0;
+	pGD->cprBase = 0;
+
+	return (void *)pGD;
+}
+
+/**
+  * Set the LUT
+  *
+  * @index: color number
+  * @r: red
+  * @b: blue
+  * @g: green
+  */
+void video_set_lut
+	(unsigned int index, unsigned char r, unsigned char g, unsigned char b)
+{
+	return;
+}
+
+#endif /* defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) */
diff --git a/arch/powerpc/cpu/mpc512x/fixed_sdram.c b/arch/powerpc/cpu/mpc512x/fixed_sdram.c
new file mode 100644
index 0000000..442b5fc
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/fixed_sdram.c
@@ -0,0 +1,152 @@
+/*
+ * (C) Copyright 2007-2009 DENX Software Engineering
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/mpc512x.h>
+
+/*
+ * MDDRC Config Runtime Settings
+ */
+ddr512x_config_t default_mddrc_config = {
+	.ddr_sys_config   = CONFIG_SYS_MDDRC_SYS_CFG,
+	.ddr_time_config0 = CONFIG_SYS_MDDRC_TIME_CFG0,
+	.ddr_time_config1 = CONFIG_SYS_MDDRC_TIME_CFG1,
+	.ddr_time_config2 = CONFIG_SYS_MDDRC_TIME_CFG2,
+};
+
+u32 default_init_seq[] = {
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_DDRCMD_PCHG_ALL,
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_DDRCMD_RFSH,
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_DDRCMD_RFSH,
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_MICRON_INIT_DEV_OP,
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_DDRCMD_EM2,
+	CONFIG_SYS_DDRCMD_NOP,
+	CONFIG_SYS_DDRCMD_PCHG_ALL,
+	CONFIG_SYS_DDRCMD_EM2,
+	CONFIG_SYS_DDRCMD_EM3,
+	CONFIG_SYS_DDRCMD_EN_DLL,
+	CONFIG_SYS_MICRON_INIT_DEV_OP,
+	CONFIG_SYS_DDRCMD_PCHG_ALL,
+	CONFIG_SYS_DDRCMD_RFSH,
+	CONFIG_SYS_MICRON_INIT_DEV_OP,
+	CONFIG_SYS_DDRCMD_OCD_DEFAULT,
+	CONFIG_SYS_DDRCMD_PCHG_ALL,
+	CONFIG_SYS_DDRCMD_NOP
+};
+
+/*
+ * fixed sdram init:
+ * The board doesn't use memory modules that have serial presence
+ * detect or similar mechanism for discovery of the DRAM settings
+ */
+long int fixed_sdram(ddr512x_config_t *mddrc_config,
+			u32 *dram_init_seq, int seq_sz)
+{
+	volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+	u32 msize = CONFIG_SYS_DDR_SIZE * 1024 * 1024;
+	u32 msize_log2 = __ilog2(msize);
+	u32 i;
+
+	/* take default settings and init sequence if necessary */
+	if (mddrc_config == NULL)
+		mddrc_config = &default_mddrc_config;
+	if (dram_init_seq == NULL) {
+		dram_init_seq = default_init_seq;
+		seq_sz = sizeof(default_init_seq)/sizeof(u32);
+	}
+
+	/* Initialize IO Control */
+	out_be32(&im->io_ctrl.io_control_mem, IOCTRL_MUX_DDR);
+
+	/* Initialize DDR Local Window */
+	out_be32(&im->sysconf.ddrlaw.bar, CONFIG_SYS_DDR_BASE & 0xFFFFF000);
+	out_be32(&im->sysconf.ddrlaw.ar, msize_log2 - 1);
+	sync_law(&im->sysconf.ddrlaw.ar);
+
+	/* DDR Enable */
+	out_be32(&im->mddrc.ddr_sys_config, MDDRC_SYS_CFG_EN);
+
+	/* Initialize DDR Priority Manager */
+	out_be32(&im->mddrc.prioman_config1, CONFIG_SYS_MDDRCGRP_PM_CFG1);
+	out_be32(&im->mddrc.prioman_config2, CONFIG_SYS_MDDRCGRP_PM_CFG2);
+	out_be32(&im->mddrc.hiprio_config, CONFIG_SYS_MDDRCGRP_HIPRIO_CFG);
+	out_be32(&im->mddrc.lut_table0_main_upper, CONFIG_SYS_MDDRCGRP_LUT0_MU);
+	out_be32(&im->mddrc.lut_table0_main_lower, CONFIG_SYS_MDDRCGRP_LUT0_ML);
+	out_be32(&im->mddrc.lut_table1_main_upper, CONFIG_SYS_MDDRCGRP_LUT1_MU);
+	out_be32(&im->mddrc.lut_table1_main_lower, CONFIG_SYS_MDDRCGRP_LUT1_ML);
+	out_be32(&im->mddrc.lut_table2_main_upper, CONFIG_SYS_MDDRCGRP_LUT2_MU);
+	out_be32(&im->mddrc.lut_table2_main_lower, CONFIG_SYS_MDDRCGRP_LUT2_ML);
+	out_be32(&im->mddrc.lut_table3_main_upper, CONFIG_SYS_MDDRCGRP_LUT3_MU);
+	out_be32(&im->mddrc.lut_table3_main_lower, CONFIG_SYS_MDDRCGRP_LUT3_ML);
+	out_be32(&im->mddrc.lut_table4_main_upper, CONFIG_SYS_MDDRCGRP_LUT4_MU);
+	out_be32(&im->mddrc.lut_table4_main_lower, CONFIG_SYS_MDDRCGRP_LUT4_ML);
+	out_be32(&im->mddrc.lut_table0_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT0_AU);
+	out_be32(&im->mddrc.lut_table0_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT0_AL);
+	out_be32(&im->mddrc.lut_table1_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT1_AU);
+	out_be32(&im->mddrc.lut_table1_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT1_AL);
+	out_be32(&im->mddrc.lut_table2_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT2_AU);
+	out_be32(&im->mddrc.lut_table2_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT2_AL);
+	out_be32(&im->mddrc.lut_table3_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT3_AU);
+	out_be32(&im->mddrc.lut_table3_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT3_AL);
+	out_be32(&im->mddrc.lut_table4_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT4_AU);
+	out_be32(&im->mddrc.lut_table4_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT4_AL);
+
+	/*
+	 * Initialize MDDRC
+	 *  put MDDRC in CMD mode and
+	 *  set the max time between refreshes to 0 during init process
+	 */
+	out_be32(&im->mddrc.ddr_sys_config,
+		mddrc_config->ddr_sys_config | MDDRC_SYS_CFG_CMD_MASK);
+	out_be32(&im->mddrc.ddr_time_config0,
+		mddrc_config->ddr_time_config0 & MDDRC_REFRESH_ZERO_MASK);
+	out_be32(&im->mddrc.ddr_time_config1,
+		mddrc_config->ddr_time_config1);
+	out_be32(&im->mddrc.ddr_time_config2,
+		mddrc_config->ddr_time_config2);
+
+	/* Initialize DDR with either default or supplied init sequence */
+	for (i = 0; i < seq_sz; i++)
+		out_be32(&im->mddrc.ddr_command, dram_init_seq[i]);
+
+	/* Start MDDRC */
+	out_be32(&im->mddrc.ddr_time_config0, mddrc_config->ddr_time_config0);
+	out_be32(&im->mddrc.ddr_sys_config, mddrc_config->ddr_sys_config);
+
+	return msize;
+}
diff --git a/arch/powerpc/cpu/mpc512x/i2c.c b/arch/powerpc/cpu/mpc512x/i2c.c
new file mode 100644
index 0000000..e2d9097
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/i2c.c
@@ -0,0 +1,403 @@
+/*
+ * (C) Copyright 2003 - 2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Based on the MPC5xxx code.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_HARD_I2C
+
+#include <i2c.h>
+
+/* by default set I2C bus 0 active */
+static unsigned int bus_num __attribute__ ((section (".data"))) = 0;
+
+#define I2C_TIMEOUT	100
+#define I2C_RETRIES	3
+
+struct mpc512x_i2c_tap {
+	int scl2tap;
+	int tap2tap;
+};
+
+static int  mpc_reg_in(volatile u32 *reg);
+static void mpc_reg_out(volatile u32 *reg, int val, int mask);
+static int  wait_for_bb(void);
+static int  wait_for_pin(int *status);
+static int  do_address(uchar chip, char rdwr_flag);
+static int  send_bytes(uchar chip, char *buf, int len);
+static int  receive_bytes(uchar chip, char *buf, int len);
+static int  mpc_get_fdr(int);
+
+static int mpc_reg_in (volatile u32 *reg)
+{
+	int ret = in_be32(reg) >> 24;
+
+	return ret;
+}
+
+static void mpc_reg_out (volatile u32 *reg, int val, int mask)
+{
+	if (!mask) {
+		out_be32(reg, val << 24);
+	} else {
+		clrsetbits_be32(reg, mask << 24, (val & mask) << 24);
+	}
+}
+
+static int wait_for_bb (void)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+	int timeout = I2C_TIMEOUT;
+	int status;
+
+	status = mpc_reg_in (&regs->msr);
+
+	while (timeout-- && (status & I2C_BB)) {
+		volatile int temp;
+		mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
+		temp = mpc_reg_in (&regs->mdr);
+		mpc_reg_out (&regs->mcr, 0, I2C_STA);
+		mpc_reg_out (&regs->mcr, 0, 0);
+		mpc_reg_out (&regs->mcr, I2C_EN, 0);
+
+		udelay (1000);
+		status = mpc_reg_in (&regs->msr);
+	}
+
+	return (status & I2C_BB);
+}
+
+static int wait_for_pin (int *status)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+	int timeout = I2C_TIMEOUT;
+
+	*status = mpc_reg_in (&regs->msr);
+
+	while (timeout-- && !(*status & I2C_IF)) {
+		udelay (1000);
+		*status = mpc_reg_in (&regs->msr);
+	}
+
+	if (!(*status & I2C_IF)) {
+		return -1;
+	}
+
+	mpc_reg_out (&regs->msr, 0, I2C_IF);
+
+	return 0;
+}
+
+static int do_address (uchar chip, char rdwr_flag)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+	int status;
+
+	chip <<= 1;
+
+	if (rdwr_flag) {
+		chip |= 1;
+	}
+
+	mpc_reg_out (&regs->mcr, I2C_TX, I2C_TX);
+	mpc_reg_out (&regs->mdr, chip, 0);
+
+	if (wait_for_pin (&status)) {
+		return -2;
+	}
+
+	if (status & I2C_RXAK) {
+		return -3;
+	}
+
+	return 0;
+}
+
+static int send_bytes (uchar chip, char *buf, int len)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+	int wrcount;
+	int status;
+
+	for (wrcount = 0; wrcount < len; ++wrcount) {
+
+		mpc_reg_out (&regs->mdr, buf[wrcount], 0);
+
+		if (wait_for_pin (&status)) {
+			break;
+		}
+
+		if (status & I2C_RXAK) {
+			break;
+		}
+
+	}
+
+	return !(wrcount == len);
+}
+
+static int receive_bytes (uchar chip, char *buf, int len)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+	int dummy   = 1;
+	int rdcount = 0;
+	int status;
+	int i;
+
+	mpc_reg_out (&regs->mcr, 0, I2C_TX);
+
+	for (i = 0; i < len; ++i) {
+		buf[rdcount] = mpc_reg_in (&regs->mdr);
+
+		if (dummy) {
+			dummy = 0;
+		} else {
+			rdcount++;
+		}
+
+		if (wait_for_pin (&status)) {
+			return -4;
+		}
+	}
+
+	mpc_reg_out (&regs->mcr, I2C_TXAK, I2C_TXAK);
+	buf[rdcount++] = mpc_reg_in (&regs->mdr);
+
+	if (wait_for_pin (&status)) {
+		return -5;
+	}
+
+	mpc_reg_out (&regs->mcr, 0, I2C_TXAK);
+
+	return 0;
+}
+
+/**************** I2C API ****************/
+
+void i2c_init (int speed, int saddr)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	int i;
+
+	for (i = 0; i < I2C_BUS_CNT; i++){
+		volatile i2c512x_dev_t *regs = &im->i2c.dev[i];
+
+		mpc_reg_out (&regs->mcr, 0, 0);
+
+		/* Set clock */
+		mpc_reg_out (&regs->mfdr, mpc_get_fdr (speed), 0);
+		mpc_reg_out (&regs->madr, saddr << 1, 0);
+
+		/* Enable module */
+		mpc_reg_out (&regs->mcr, I2C_EN, I2C_INIT_MASK);
+		mpc_reg_out (&regs->msr, 0, I2C_IF);
+	}
+
+	/* Disable interrupts */
+	out_be32(&im->i2c.icr, 0);
+
+	/* Turn off filters */
+	out_be32(&im->i2c.mifr, 0);
+}
+
+static int mpc_get_fdr (int speed)
+{
+	static int fdr = -1;
+
+	if (fdr == -1) {
+		ulong best_speed = 0;
+		ulong divider;
+		ulong ips, scl;
+		ulong bestmatch = 0xffffffffUL;
+		int best_i = 0, best_j = 0, i, j;
+		int SCL_Tap[] = { 9, 10, 12, 15, 5, 6, 7, 8};
+		struct mpc512x_i2c_tap scltap[] = {
+			{4, 1},
+			{4, 2},
+			{6, 4},
+			{6, 8},
+			{14, 16},
+			{30, 32},
+			{62, 64},
+			{126, 128}
+		};
+
+		ips = gd->ips_clk;
+		for (i = 7; i >= 0; i--) {
+			for (j = 7; j >= 0; j--) {
+				scl = 2 * (scltap[j].scl2tap +
+					   (SCL_Tap[i] - 1) * scltap[j].tap2tap
+					   + 2);
+				if (ips <= speed*scl) {
+					if ((speed*scl - ips) < bestmatch) {
+						bestmatch = speed*scl - ips;
+						best_i = i;
+						best_j = j;
+						best_speed = ips/scl;
+					}
+				}
+			}
+		}
+		divider = (best_i & 3) | ((best_i & 4) << 3) | (best_j << 2);
+		if (gd->flags & GD_FLG_RELOC) {
+			fdr = divider;
+		} else {
+			debug("%ld kHz, \n", best_speed / 1000);
+			return divider;
+		}
+	}
+
+	return fdr;
+}
+
+int i2c_probe (uchar chip)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+	int i;
+
+	for (i = 0; i < I2C_RETRIES; i++) {
+		mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
+
+		if (! do_address (chip, 0)) {
+			mpc_reg_out (&regs->mcr, 0, I2C_STA);
+			udelay (500);
+			break;
+		}
+
+		mpc_reg_out (&regs->mcr, 0, I2C_STA);
+		udelay (500);
+	}
+
+	return (i == I2C_RETRIES);
+}
+
+int i2c_read (uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+	char xaddr[4];
+	int ret = -1;
+
+	xaddr[0] = (addr >> 24) & 0xFF;
+	xaddr[1] = (addr >> 16) & 0xFF;
+	xaddr[2] = (addr >>  8) & 0xFF;
+	xaddr[3] =  addr	& 0xFF;
+
+	if (wait_for_bb ()) {
+		printf ("i2c_read: bus is busy\n");
+		goto Done;
+	}
+
+	mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
+	if (do_address (chip, 0)) {
+		printf ("i2c_read: failed to address chip\n");
+		goto Done;
+	}
+
+	if (send_bytes (chip, &xaddr[4-alen], alen)) {
+		printf ("i2c_read: send_bytes failed\n");
+		goto Done;
+	}
+
+	mpc_reg_out (&regs->mcr, I2C_RSTA, I2C_RSTA);
+	if (do_address (chip, 1)) {
+		printf ("i2c_read: failed to address chip\n");
+		goto Done;
+	}
+
+	if (receive_bytes (chip, (char *)buf, len)) {
+		printf ("i2c_read: receive_bytes failed\n");
+		goto Done;
+	}
+
+	ret = 0;
+Done:
+	mpc_reg_out (&regs->mcr, 0, I2C_STA);
+	return ret;
+}
+
+int i2c_write (uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+	char xaddr[4];
+	int ret = -1;
+
+	xaddr[0] = (addr >> 24) & 0xFF;
+	xaddr[1] = (addr >> 16) & 0xFF;
+	xaddr[2] = (addr >>  8) & 0xFF;
+	xaddr[3] =  addr	& 0xFF;
+
+	if (wait_for_bb ()) {
+		printf ("i2c_write: bus is busy\n");
+		goto Done;
+	}
+
+	mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
+	if (do_address (chip, 0)) {
+		printf ("i2c_write: failed to address chip\n");
+		goto Done;
+	}
+
+	if (send_bytes (chip, &xaddr[4-alen], alen)) {
+		printf ("i2c_write: send_bytes failed\n");
+		goto Done;
+	}
+
+	if (send_bytes (chip, (char *)buf, len)) {
+		printf ("i2c_write: send_bytes failed\n");
+		goto Done;
+	}
+
+	ret = 0;
+Done:
+	mpc_reg_out (&regs->mcr, 0, I2C_STA);
+	return ret;
+}
+
+int i2c_set_bus_num (unsigned int bus)
+{
+	if (bus >= I2C_BUS_CNT) {
+		return -1;
+	}
+	bus_num = bus;
+
+	return 0;
+}
+
+unsigned int i2c_get_bus_num (void)
+{
+	return bus_num;
+}
+
+#endif	/* CONFIG_HARD_I2C */
diff --git a/arch/powerpc/cpu/mpc512x/ide.c b/arch/powerpc/cpu/mpc512x/ide.c
new file mode 100644
index 0000000..dd6b2f4
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/ide.c
@@ -0,0 +1,128 @@
+/*
+ * (C) Copyright 2007-2009 DENX Software Engineering
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_IDE_RESET)
+
+void ide_set_reset (int idereset)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	debug ("ide_set_reset(%d)\n", idereset);
+
+	if (idereset) {
+		out_be32(&im->pata.pata_ata_control, 0);
+	} else {
+		out_be32(&im->pata.pata_ata_control, FSL_ATA_CTRL_ATA_RST_B);
+	}
+	udelay(100);
+}
+
+void init_ide_reset (void)
+{
+	debug ("init_ide_reset\n");
+
+	/*
+	 * Clear the reset bit to reset the interface
+	 * cf. RefMan MPC5121EE: 28.4.1 Resetting the ATA Bus
+	 */
+	ide_set_reset(1);
+
+	/* Assert the reset bit to enable the interface */
+	ide_set_reset(0);
+
+}
+
+#define CALC_TIMING(t) (t + period - 1) / period
+
+int ide_preinit (void)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	long t;
+	const struct {
+		short t0;
+		short t1;
+		short t2_8;
+		short t2_16;
+		short t2i;
+		short t4;
+		short t9;
+		short tA;
+	} pio_specs = {
+		.t0    = 600,
+		.t1    =  70,
+		.t2_8  = 290,
+		.t2_16 = 165,
+		.t2i   =   0,
+		.t4    =  30,
+		.t9    =  20,
+		.tA    =  50,
+	};
+	union {
+		u32 config;
+		struct {
+			u8 field1;
+			u8 field2;
+			u8 field3;
+			u8 field4;
+		}bytes;
+	} cfg;
+
+	debug ("IDE preinit using PATA peripheral at IMMR-ADDR %08x\n",
+		(u32)&im->pata);
+
+	/* Set the reset bit to 1 to enable the interface */
+	ide_set_reset(0);
+
+	/* Init timings : we use PIO mode 0 timings */
+	t = 1000000000 / gd->ips_clk;	/* period in ns */
+	cfg.bytes.field1 = 3;
+	cfg.bytes.field2 = 3;
+	cfg.bytes.field3 = (pio_specs.t1 + t) / t;
+	cfg.bytes.field4 = (pio_specs.t2_8 + t) / t;
+
+	out_be32(&im->pata.pata_time1, cfg.config);
+
+	cfg.bytes.field1 = (pio_specs.t2_8 + t) / t;
+	cfg.bytes.field2 = (pio_specs.tA + t) / t + 2;
+	cfg.bytes.field3 = 1;
+	cfg.bytes.field4 = (pio_specs.t4 + t) / t;
+
+	out_be32(&im->pata.pata_time2, cfg.config);
+
+	cfg.config = in_be32(&im->pata.pata_time3);
+	cfg.bytes.field1 = (pio_specs.t9 + t) / t;
+
+	out_be32(&im->pata.pata_time3, cfg.config);
+
+	debug ("PATA preinit complete.\n");
+
+	return 0;
+}
+
+#endif /* defined(CONFIG_IDE_RESET) */
diff --git a/arch/powerpc/cpu/mpc512x/iim.c b/arch/powerpc/cpu/mpc512x/iim.c
new file mode 100644
index 0000000..8f2eb37
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/iim.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright 2008 Silicon Turnkey Express, Inc.
+ * Martha Marx <mmarx@silicontkx.com>
+ *
+ * ADS5121 IIM (Fusebox) Interface
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_CMD_FUSE
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static char cur_bank = '1';
+
+char *iim_err_msg(u32 err)
+{
+	static char *IIM_errs[] = {
+		"Parity Error in cache",
+		"Explicit Sense Cycle Error",
+		"Write to Locked Register Error",
+		"Read Protect Error",
+		"Override Protect Error",
+		"Write Protect Error"};
+
+	int i;
+
+	if (!err)
+		return "";
+	for (i = 1; i < 8; i++)
+		if (err & (1 << i))
+			printf("IIM - %s\n", IIM_errs[i-1]);
+	return "";
+}
+
+int in_range(int n, int min, int max, char *err, char *usg)
+{
+	if (n > max || n < min) {
+		printf(err);
+		printf("Usage:\n%s\n", usg);
+		return 0;
+	}
+	return 1;
+}
+
+int ads5121_fuse_read(int bank, int fstart, int num)
+{
+	iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+	u32 *iim_fb, dummy;
+	int f, ctr;
+
+	out_be32(&iim->err, in_be32(&iim->err));
+	if (bank == 0)
+		iim_fb = (u32 *)&(iim->fbac0);
+	else
+		iim_fb = (u32 *)&(iim->fbac1);
+/* try a read to see if Read Protect is set */
+	dummy = in_be32(&iim_fb[0]);
+	if (in_be32(&iim->err) & IIM_ERR_RPE) {
+		printf("\tRead protect fuse is set\n");
+		out_be32(&iim->err, IIM_ERR_RPE);
+		return 0;
+	}
+	printf("Reading Bank %d cache\n", bank);
+	for (f = fstart, ctr = 0; num > 0; ctr++, num--, f++) {
+		if (ctr % 4 == 0)
+			printf("F%2d:", f);
+		printf("\t%#04x", (u8)(iim_fb[f]));
+		if (ctr % 4 == 3)
+			printf("\n");
+	}
+	if (ctr % 4 != 0)
+		printf("\n");
+}
+
+int ads5121_fuse_override(int bank, int f, u8 val)
+{
+	iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+	u32 *iim_fb;
+	u32 iim_stat;
+	int i;
+
+	out_be32(&iim->err, in_be32(&iim->err));
+	if (bank == 0)
+		iim_fb = (u32 *)&(iim->fbac0);
+	else
+		iim_fb = (u32 *)&(iim->fbac1);
+/* try a read to see if Read Protect is set */
+	iim_stat = in_be32(&iim_fb[0]);
+	if (in_be32(&iim->err) & IIM_ERR_RPE) {
+		printf("Read protect fuse is set on bank %d;"
+			"Override protect may also be set\n", bank);
+		printf("An attempt will be made to override\n");
+		out_be32(&iim->err, IIM_ERR_RPE);
+	}
+	if (iim_stat & IIM_FBAC_FBOP) {
+		printf("Override protect fuse is set on bank %d\n", bank);
+		return 1;
+	}
+	if (f > IIM_FMAX) /* reset the entire bank */
+		for (i = 0; i < IIM_FMAX + 1; i++)
+			out_be32(&iim_fb[i],  0);
+	else
+		out_be32(&iim_fb[f], val);
+	return 0;
+}
+
+int ads5121_fuse_prog(cmd_tbl_t *cmdtp, int bank, char *fuseno_bitno)
+{
+	iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+	int f, i, bitno;
+	u32 stat, err;
+
+	f = simple_strtol(fuseno_bitno, NULL, 10);
+	if (f == 0 && fuseno_bitno[0] != '0')
+		f = -1;
+	if (!in_range(f, 0, IIM_FMAX,
+		"<frow> must be between 0-31\n\n", cmdtp->usage))
+		return 1;
+	bitno = -1;
+	for (i = 0; i < 6; i++) {
+		if (fuseno_bitno[i] == '_') {
+			bitno = simple_strtol(&(fuseno_bitno[i+1]), NULL, 10);
+			if (bitno == 0 && fuseno_bitno[i+1] != '0')
+				bitno = -1;
+			break;
+		}
+	}
+	if (!in_range(bitno, 0, 7, "Bit number ranges from 0-7\n"
+		"Example of <frow_bitno>: \"18_4\" sets bit 4 of row 18\n",
+		cmdtp->usage))
+		return 1;
+	out_be32(&iim->err, in_be32(&iim->err));
+	out_be32(&iim->prg_p, IIM_PRG_P_SET);
+	out_be32(&iim->ua, IIM_SET_UA(bank, f));
+	out_be32(&iim->la, IIM_SET_LA(f, bitno));
+#ifdef DEBUG
+	printf("Programming disabled with DEBUG defined \n");
+	printf(""Set up to pro
+	printf("iim.ua = %x; iim.la = %x\n", iim->ua, iim->la);
+#else
+	out_be32(&iim->fctl, IIM_FCTL_PROG_PULSE | IIM_FCTL_PROG);
+	do
+		udelay(20);
+	while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
+	out_be32(&iim->prg_p, 0);
+	err = in_be32(&iim->err);
+	if (stat & IIM_STAT_PRGD) {
+		if (!(err & (IIM_ERR_WPE | IIM_ERR_WPE))) {
+			printf("Fuse is successfully set");
+			if (err)
+				printf(" - however there are other errors");
+			printf("\n");
+		}
+		iim->stat = 0;
+	}
+	if (err) {
+		iim_err_msg(err);
+		out_be32(&iim->err, in_be32(&iim->err));
+	}
+#endif
+}
+
+int ads5121_fuse_sense(int bank, int fstart, int num)
+{
+	iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+	u32 iim_fbac;
+	u32 stat, err, err_hold = 0;
+	int f, ctr;
+
+	out_be32(&iim->err, in_be32(&iim->err));
+	if (bank == 0)
+		iim_fbac = in_be32(&iim->fbac0);
+	else
+		iim_fbac = in_be32(&iim->fbac1);
+	if (iim_fbac & IIM_FBAC_FBESP) {
+		printf("\tSense Protect disallows this operation\n");
+		out_be32(&iim->err, IIM_FBAC_FBESP);
+		return 1;
+	}
+	err = in_be32(&iim->err);
+	if (err) {
+		iim_err_msg(err);
+		err_hold |= err;
+	}
+	if (err & IIM_ERR_RPE)
+		printf("\tRead protect fuse is set; "
+			"Sense Protect may be set but will be attempted\n");
+	if (err)
+		out_be32(&iim->err, err);
+	printf("Sensing fuse(s) on Bank %d\n", bank);
+	for (f = fstart, ctr = 0; num > 0; ctr++, f++, num--) {
+		out_be32(&iim->ua, IIM_SET_UA(bank, f));
+		out_be32(&iim->la, IIM_SET_LA(f, 0));
+		out_be32(&iim->fctl,  IIM_FCTL_ESNS_N);
+		do
+			udelay(20);
+		while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
+		err = in_be32(&iim->err);
+		if (err & IIM_ERR_SNSE) {
+			iim_err_msg(err);
+			out_be32(&iim->err, IIM_ERR_SNSE);
+			return 1;
+		}
+		if (stat & IIM_STAT_SNSD) {
+			out_be32(&iim->stat, 0);
+			if (ctr % 4 == 0)
+				printf("F%2d:", f);
+			printf("\t%#04x", (u8)iim->sdat);
+			if (ctr % 4 == 3)
+				printf("\n");
+		}
+		if (err) {
+			err_hold |= err;
+			out_be32(&iim->err, err);
+		}
+	}
+	if (ctr % 4 != 0)
+		printf("\n");
+	if (err_hold)
+		iim_err_msg(err_hold);
+
+	return 0;
+}
+
+int ads5121_fuse_stat(int bank)
+{
+	iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
+	u32 iim_fbac;
+	u32 err;
+
+	out_be32(&iim->err, in_be32(&iim->err));
+	if (bank == 0)
+		iim_fbac = in_be32(&iim->fbac0);
+	else
+		iim_fbac = in_be32(&iim->fbac1);
+	err = in_be32(&iim->err);
+	if (err)
+		iim_err_msg(err);
+	if (err & IIM_ERR_RPE  || iim_fbac & IIM_FBAC_FBRP) {
+		if (iim_fbac == 0)
+			printf("Since protection settings can't be read - "
+				"try sensing fuse row 0;\n");
+		return 0;
+	}
+	if (iim_fbac & IIM_PROTECTION)
+		printf("Protection Fuses Bank %d = %#04x:\n", bank, iim_fbac);
+	else if (!(err & IIM_ERR_RPE))
+		printf("No Protection fuses are set\n");
+	if (iim_fbac & IIM_FBAC_FBWP)
+		printf("\tWrite Protect fuse is set\n");
+	if (iim_fbac & IIM_FBAC_FBOP)
+		printf("\tOverride Protect fuse is set\n");
+	if (iim_fbac & IIM_FBAC_FBESP)
+		printf("\tSense Protect Fuse is set\n");
+	out_be32(&iim->err, in_be32(&iim->err));
+
+	return 0;
+}
+
+int do_ads5121_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	int frow, n, v, bank;
+
+	if (cur_bank == '0')
+		bank = 0;
+	else
+		bank = 1;
+
+	switch (argc) {
+	case 0:
+	case 1:
+		printf("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	case 2:
+		if (strncmp(argv[1], "stat", 4) == 0)
+			return ads5121_fuse_stat(bank);
+		if (strncmp(argv[1], "read", 4) == 0)
+			return ads5121_fuse_read(bank, 0, IIM_FMAX + 1);
+		if (strncmp(argv[1], "sense", 5) == 0)
+			return ads5121_fuse_sense(bank, 0, IIM_FMAX + 1);
+		if (strncmp(argv[1], "ovride", 6) == 0)
+			return ads5121_fuse_override(bank, IIM_FMAX + 1, 0);
+		if (strncmp(argv[1], "bank", 4) == 0) {
+			printf("Active Fuse Bank is %c\n", cur_bank);
+			return 0;
+		}
+		printf("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	case 3:
+		if (strncmp(argv[1], "bank", 4) == 0) {
+			if (argv[2][0] == '0')
+				cur_bank = '0';
+			else if (argv[2][0] == '1')
+				cur_bank = '1';
+			else {
+				printf("Usage:\n%s\n", cmdtp->usage);
+				return 1;
+			}
+
+			printf("Setting Active Fuse Bank to %c\n", cur_bank);
+			return 0;
+		}
+		if (strncmp(argv[1], "prog", 4) == 0)
+			return ads5121_fuse_prog(cmdtp, bank, argv[2]);
+
+		frow = (int)simple_strtol(argv[2], NULL, 10);
+		if (frow == 0 && argv[2][0] != '0')
+			frow = -1;
+		if (!in_range(frow, 0, IIM_FMAX,
+			"<frow> must be between 0-31\n\n", cmdtp->usage))
+			return 1;
+		if (strncmp(argv[1], "read", 4) == 0)
+			return ads5121_fuse_read(bank, frow, 1);
+		if (strncmp(argv[1], "ovride", 6) == 0)
+			return ads5121_fuse_override(bank, frow, 0);
+		if (strncmp(argv[1], "sense", 5) == 0)
+			return ads5121_fuse_sense(bank, frow, 1);
+		printf("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	case 4:
+		frow = (int)simple_strtol(argv[2], NULL, 10);
+		if (frow == 0 && argv[2][0] != '0')
+			frow = -1;
+		if (!in_range(frow, 0, IIM_FMAX,
+			"<frow> must be between 0-31\n\n", cmdtp->usage))
+			return 1;
+		if (strncmp(argv[1], "read", 4) == 0) {
+			n = (int)simple_strtol(argv[3], NULL, 10);
+			if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
+				"<frow>+<n> must be between 1-32\n\n",
+				cmdtp->usage))
+				return 1;
+			return ads5121_fuse_read(bank, frow, n);
+		}
+		if (strncmp(argv[1], "ovride", 6) == 0) {
+			v = (int)simple_strtol(argv[3], NULL, 10);
+			return ads5121_fuse_override(bank, frow, v);
+		}
+		if (strncmp(argv[1], "sense", 5) == 0) {
+			n = (int)simple_strtol(argv[3], NULL, 10);
+			if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
+				"<frow>+<n> must be between 1-32\n\n",
+				cmdtp->usage))
+				return 1;
+			return ads5121_fuse_sense(bank, frow, n);
+		}
+		printf("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	default: /* at least 5 args */
+		printf("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+}
+
+U_BOOT_CMD(
+	fuse, CONFIG_SYS_MAXARGS, 0, do_ads5121_fuse,
+	"   - Read, Sense, Override or Program Fuses\n",
+	"bank <n>		- sets active Fuse Bank to 0 or 1\n"
+	"			    no args shows current active bank\n"
+	"fuse stat		- print active fuse bank's protection status\n"
+	"fuse read [<frow> [<n>]] - print <n> fuse rows starting at <frow>\n"
+	"			    no args to print entire bank's fuses\n"
+	"fuse ovride [<frow> [<v>]]- override fuses at <frow> with <v>\n"
+	"			    no <v> defaults to 0 for the row\n"
+	"			    no args resets entire bank to 0\n"
+	"			  NOTE - settings persist until hard reset\n"
+	"fuse sense [<frow>]	- senses current fuse at <frow>\n"
+	"			    no args for entire bank\n"
+	"fuse prog <frow_bit> 	- program fuse at row <frow>, bit <_bit>\n"
+	"			    <frow> is 0-31, <bit> is 0-7; eg. 13_2 \n"
+	"			  WARNING - this is permanent"
+);
+#endif /* CONFIG_CMD_FUSE */
diff --git a/arch/powerpc/cpu/mpc512x/interrupts.c b/arch/powerpc/cpu/mpc512x/interrupts.c
new file mode 100644
index 0000000..ef7c773
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/interrupts.c
@@ -0,0 +1,61 @@
+/*
+ * (C) Copyright 2000-2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Derived from the MPC83xx code.
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct irq_action {
+	interrupt_handler_t *handler;
+	void *arg;
+	ulong count;
+};
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+	*decrementer_count = get_tbclk () / CONFIG_SYS_HZ;
+
+	return 0;
+}
+
+/*
+ * Install and free an interrupt handler.
+ */
+void
+irq_install_handler (int irq, interrupt_handler_t * handler, void *arg)
+{
+}
+
+void irq_free_handler (int irq)
+{
+}
+
+void timer_interrupt_cpu (struct pt_regs *regs)
+{
+	/* nothing to do here */
+	return;
+}
diff --git a/arch/powerpc/cpu/mpc512x/iopin.c b/arch/powerpc/cpu/mpc512x/iopin.c
new file mode 100644
index 0000000..be20947
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/iopin.c
@@ -0,0 +1,49 @@
+/*
+ * (C) Copyright 2008
+ * Martha J Marx, Silicon Turnkey Express, mmarx@silicontkx.com
+ * mpc512x I/O pin/pad initialization for the ADS5121 board
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+void iopin_initialize(iopin_t *ioregs_init, int len)
+{
+	short i, j, p;
+	u32 *reg;
+	immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+
+	reg = (u32 *)&(im->io_ctrl);
+
+	if (sizeof(ioregs_init) == 0)
+		return;
+
+	for (i = 0; i < len; i++) {
+		for (p = 0, j = ioregs_init[i].p_offset / sizeof(u_long);
+			p < ioregs_init[i].nr_pins; p++, j++) {
+			if (ioregs_init[i].bit_or)
+				setbits_be32(reg + j, ioregs_init[i].val);
+			else
+				out_be32 (reg + j, ioregs_init[i].val);
+		}
+	}
+	return;
+}
diff --git a/arch/powerpc/cpu/mpc512x/pci.c b/arch/powerpc/cpu/mpc512x/pci.c
new file mode 100644
index 0000000..141db8b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/pci.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2009-2010 DENX Software Engineering <wd@denx.de>
+ * Copyright (C) Freescale Semiconductor, Inc. 2006, 2007.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/global_data.h>
+#include <pci.h>
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <fdt_support.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* System RAM mapped to PCI space */
+#define CONFIG_PCI_SYS_MEM_BUS	CONFIG_SYS_SDRAM_BASE
+#define CONFIG_PCI_SYS_MEM_PHYS	CONFIG_SYS_SDRAM_BASE
+
+static struct pci_controller pci_hose;
+
+
+/**************************************************************************
+ * pci_init_board()
+ *
+ */
+void
+pci_init_board(void)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile law512x_t *pci_law;
+	volatile pot512x_t *pci_pot;
+	volatile pcictrl512x_t *pci_ctrl;
+	volatile pciconf512x_t *pci_conf;
+	u16 reg16;
+	u32 reg32;
+	u32 dev;
+	int i;
+	struct pci_controller *hose;
+
+	/* Set PCI divider for 33MHz */
+	reg32 = in_be32(&im->clk.scfr[0]);
+	reg32 &= ~(SCFR1_PCI_DIV_MASK);
+	reg32 |= SCFR1_PCI_DIV << SCFR1_PCI_DIV_SHIFT;
+	out_be32(&im->clk.scfr[0], reg32);
+
+	clrsetbits_be32(&im->clk.scfr[0],
+			SCFR1_PCI_DIV_MASK,
+			SCFR1_PCI_DIV << SCFR1_PCI_DIV_SHIFT
+	);
+
+	pci_law = im->sysconf.pcilaw;
+	pci_pot = im->ios.pot;
+	pci_ctrl = &im->pci_ctrl;
+	pci_conf = &im->pci_conf;
+
+	hose = &pci_hose;
+
+	/*
+	 * Release PCI RST Output signal
+	 */
+	out_be32(&pci_ctrl->gcr, 0);
+	udelay(2000);
+	out_be32(&pci_ctrl->gcr, 1);
+
+	/* We need to wait at least a 1sec based on PCI specs */
+	for (i = 0; i < 1000; i++)
+		udelay(1000);
+
+	/*
+	 * Configure PCI Local Access Windows
+	 */
+	out_be32(&pci_law[0].bar, CONFIG_SYS_PCI_MEM_PHYS & LAWBAR_BAR);
+	out_be32(&pci_law[0].ar, LAWAR_EN | LAWAR_SIZE_512M);
+
+	out_be32(&pci_law[1].bar, CONFIG_SYS_PCI_IO_PHYS & LAWBAR_BAR);
+	out_be32(&pci_law[1].ar, LAWAR_EN | LAWAR_SIZE_16M);
+
+	/*
+	 * Configure PCI Outbound Translation Windows
+	 */
+
+	/* PCI mem space - prefetch */
+	out_be32(&pci_pot[0].potar,
+		(CONFIG_SYS_PCI_MEM_BASE >> 12) & POTAR_TA_MASK);
+	out_be32(&pci_pot[0].pobar,
+		(CONFIG_SYS_PCI_MEM_PHYS >> 12) & POBAR_BA_MASK);
+	out_be32(&pci_pot[0].pocmr,
+		POCMR_EN | POCMR_PRE | POCMR_CM_256M);
+
+	/* PCI IO space */
+	out_be32(&pci_pot[1].potar,
+		(CONFIG_SYS_PCI_IO_BASE >> 12) & POTAR_TA_MASK);
+	out_be32(&pci_pot[1].pobar,
+		(CONFIG_SYS_PCI_IO_PHYS >> 12) & POBAR_BA_MASK);
+	out_be32(&pci_pot[1].pocmr,
+		POCMR_EN | POCMR_IO | POCMR_CM_16M);
+
+	/* PCI mmio - non-prefetch mem space */
+	out_be32(&pci_pot[2].potar,
+		(CONFIG_SYS_PCI_MMIO_BASE >> 12) & POTAR_TA_MASK);
+	out_be32(&pci_pot[2].pobar,
+		(CONFIG_SYS_PCI_MMIO_PHYS >> 12) & POBAR_BA_MASK);
+	out_be32(&pci_pot[2].pocmr,
+		POCMR_EN | POCMR_CM_256M);
+
+	/*
+	 * Configure PCI Inbound Translation Windows
+	 */
+
+	/* we need RAM mapped to PCI space for the devices to
+	 * access main memory */
+	out_be32(&pci_ctrl[0].pitar1, 0x0);
+	out_be32(&pci_ctrl[0].pibar1, 0x0);
+	out_be32(&pci_ctrl[0].piebar1, 0x0);
+	out_be32(&pci_ctrl[0].piwar1,
+		PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP |
+		PIWAR_WTT_SNOOP | (__ilog2(gd->ram_size) - 1));
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	/* PCI memory prefetch space */
+	pci_set_region(hose->regions + 0,
+		       CONFIG_SYS_PCI_MEM_BASE,
+		       CONFIG_SYS_PCI_MEM_PHYS,
+		       CONFIG_SYS_PCI_MEM_SIZE,
+		       PCI_REGION_MEM|PCI_REGION_PREFETCH);
+
+	/* PCI memory space */
+	pci_set_region(hose->regions + 1,
+		       CONFIG_SYS_PCI_MMIO_BASE,
+		       CONFIG_SYS_PCI_MMIO_PHYS,
+		       CONFIG_SYS_PCI_MMIO_SIZE,
+		       PCI_REGION_MEM);
+
+	/* PCI IO space */
+	pci_set_region(hose->regions + 2,
+		       CONFIG_SYS_PCI_IO_BASE,
+		       CONFIG_SYS_PCI_IO_PHYS,
+		       CONFIG_SYS_PCI_IO_SIZE,
+		       PCI_REGION_IO);
+
+	/* System memory space */
+	pci_set_region(hose->regions + 3,
+		       CONFIG_PCI_SYS_MEM_BUS,
+		       CONFIG_PCI_SYS_MEM_PHYS,
+		       gd->ram_size,
+		       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+	hose->region_count = 4;
+
+	pci_setup_indirect(hose,
+			   (CONFIG_SYS_IMMR + 0x8300),
+			   (CONFIG_SYS_IMMR + 0x8304));
+
+	pci_register_hose(hose);
+
+	/*
+	 * Write to Command register
+	 */
+	reg16 = 0xff;
+	dev = PCI_BDF(hose->first_busno, 0, 0);
+	pci_hose_read_config_word(hose, dev, PCI_COMMAND, &reg16);
+	reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
+
+	/*
+	 * Clear non-reserved bits in status register.
+	 */
+	pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
+	pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
+	pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);
+
+#ifdef CONFIG_PCI_SCAN_SHOW
+	printf("PCI:   Bus Dev VenId DevId Class Int\n");
+#endif
+	/*
+	 * Hose scan.
+	 */
+	hose->last_busno = pci_hose_scan(hose);
+}
+
+#if defined(CONFIG_OF_LIBFDT)
+void ft_pci_setup(void *blob, bd_t *bd)
+{
+	int nodeoffset;
+	int tmp[2];
+	const char *path;
+
+	nodeoffset = fdt_path_offset(blob, "/aliases");
+	if (nodeoffset >= 0) {
+		path = fdt_getprop(blob, nodeoffset, "pci", NULL);
+		if (path) {
+			tmp[0] = cpu_to_be32(pci_hose.first_busno);
+			tmp[1] = cpu_to_be32(pci_hose.last_busno);
+			do_fixup_by_path(blob, path, "bus-range",
+				&tmp, sizeof(tmp), 1);
+
+			tmp[0] = cpu_to_be32(gd->pci_clk);
+			do_fixup_by_path(blob, path, "clock-frequency",
+				&tmp, sizeof(tmp[0]), 1);
+		}
+	}
+}
+#endif /* CONFIG_OF_LIBFDT */
diff --git a/arch/powerpc/cpu/mpc512x/serial.c b/arch/powerpc/cpu/mpc512x/serial.c
new file mode 100644
index 0000000..ec2f41b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/serial.c
@@ -0,0 +1,193 @@
+/*
+ * (C) Copyright 2000 - 2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Based ont the MPC5200 PSC driver.
+ * Adapted for MPC512x by Jan Wrobel <wrr@semihalf.com>
+ */
+
+/*
+ * Minimal serial functions needed to use one of the PSC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_PSC_CONSOLE)
+
+static void fifo_init (volatile psc512x_t *psc)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+
+	/* reset Rx & Tx fifo slice */
+	out_be32(&psc->rfcmd, PSC_FIFO_RESET_SLICE);
+	out_be32(&psc->tfcmd, PSC_FIFO_RESET_SLICE);
+
+	/* disable Tx & Rx FIFO interrupts */
+	out_be32(&psc->rfintmask, 0);
+	out_be32(&psc->tfintmask, 0);
+
+	out_be32(&psc->tfsize, CONSOLE_FIFO_TX_SIZE | (CONSOLE_FIFO_TX_ADDR << 16));
+	out_be32(&psc->rfsize, CONSOLE_FIFO_RX_SIZE | (CONSOLE_FIFO_RX_ADDR << 16));
+
+	/* enable Tx & Rx FIFO slice */
+	out_be32(&psc->rfcmd, PSC_FIFO_ENABLE_SLICE);
+	out_be32(&psc->tfcmd, PSC_FIFO_ENABLE_SLICE);
+
+	out_be32(&im->fifoc.fifoc_cmd, FIFOC_DISABLE_CLOCK_GATE);
+	__asm__ volatile ("sync");
+}
+
+void serial_setbrg(void)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+	unsigned long baseclk, div;
+
+	/* calculate dividor for setting PSC CTUR and CTLR registers */
+	baseclk = (gd->ips_clk + 8) / 16;
+	div = (baseclk + (gd->baudrate / 2)) / gd->baudrate;
+
+	out_8(&psc->ctur, (div >> 8) & 0xff);
+	out_8(&psc->ctlr,  div & 0xff); /* set baudrate */
+}
+
+int serial_init(void)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+
+	fifo_init (psc);
+
+	/* set MR register to point to MR1 */
+	out_8(&psc->command, PSC_SEL_MODE_REG_1);
+
+	/* disable Tx/Rx */
+	out_8(&psc->command, PSC_TX_DISABLE | PSC_RX_DISABLE);
+
+	/* choose the prescaler	by 16 for the Tx/Rx clock generation */
+	out_be16(&psc->psc_clock_select, 0xdd00);
+
+	/* switch to UART mode */
+	out_be32(&psc->sicr, 0);
+
+	/* mode register points to mr1 */
+	/* configure parity, bit length and so on in mode register 1*/
+	out_8(&psc->mode, PSC_MODE_8_BITS | PSC_MODE_PARNONE);
+	/* now, mode register points to mr2 */
+	out_8(&psc->mode, PSC_MODE_1_STOPBIT);
+
+	/* set baudrate */
+	serial_setbrg();
+
+	/* disable all interrupts */
+	out_be16(&psc->psc_imr, 0);
+
+	/* reset and enable Rx/Tx */
+	out_8(&psc->command, PSC_RST_RX);
+	out_8(&psc->command, PSC_RST_TX);
+	out_8(&psc->command, PSC_RX_ENABLE | PSC_TX_ENABLE);
+
+	return 0;
+}
+
+void serial_putc (const char c)
+{
+	volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+
+	if (c == '\n')
+		serial_putc ('\r');
+
+	/* Wait for last character to go. */
+	while (!(in_be16(&psc->psc_status) & PSC_SR_TXEMP))
+		;
+
+	out_8(&psc->tfdata_8, c);
+}
+
+void serial_putc_raw (const char c)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+
+	/* Wait for last character to go. */
+	while (!(in_be16(&psc->psc_status) & PSC_SR_TXEMP))
+		;
+
+	out_8(&psc->tfdata_8, c);
+}
+
+
+void serial_puts (const char *s)
+{
+	while (*s) {
+		serial_putc (*s++);
+	}
+}
+
+int serial_getc (void)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+
+	/* Wait for a character to arrive. */
+	while (in_be32(&psc->rfstat) & PSC_FIFO_EMPTY)
+		;
+
+	return in_8(&psc->rfdata_8);
+}
+
+int serial_tstc (void)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+
+	return !(in_be32(&psc->rfstat) & PSC_FIFO_EMPTY);
+}
+
+void serial_setrts(int s)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+
+	if (s) {
+		/* Assert RTS (become LOW) */
+		out_8(&psc->op1, 0x1);
+	}
+	else {
+		/* Negate RTS (become HIGH) */
+		out_8(&psc->op0, 0x1);
+	}
+}
+
+int serial_getcts(void)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
+
+	return (in_8(&psc->ip) & 0x1) ? 0 : 1;
+}
+#endif /* CONFIG_PSC_CONSOLE */
diff --git a/arch/powerpc/cpu/mpc512x/speed.c b/arch/powerpc/cpu/mpc512x/speed.c
new file mode 100644
index 0000000..ce8d094
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/speed.c
@@ -0,0 +1,156 @@
+/*
+ * (C) Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Based on the MPC83xx code.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int spmf_mult[] = {
+	68, 1, 12, 16,
+	20, 24, 28, 32,
+	36, 40, 44, 48,
+	52, 56, 60, 64
+};
+
+static int cpmf_mult[][2] = {
+	{0, 1}, {0, 1}, /* 0 and 1 are not valid */
+	{1, 1}, {3, 2},
+	{2, 1}, {5, 2},
+	{3, 1}, {7, 2},
+	{0, 1}, {0, 1}, /* and all above 7 are not valid too */
+	{0, 1}, {0, 1},
+	{0, 1}, {0, 1},
+	{0, 1}, {0, 1}
+};
+
+static int sys_dividors[][2] = {
+	{2, 1}, {5, 2}, {3, 1}, {7, 2}, {4, 1},
+	{9, 2}, {5, 1}, {7, 1}, {6, 1}, {8, 1},
+	{9, 1}, {11, 1}, {10, 1}, {12, 1}, {13, 1},
+	{15, 1}, {14, 1}, {16, 1}, {17, 1}, {19, 1},
+	{18, 1}, {20, 1}, {21, 1}, {23, 1}, {22, 1},
+	{24, 1}, {25, 1}, {27, 1}, {26, 1}, {28, 1},
+	{29, 1}, {31, 1}, {30, 1}, {32, 1}, {33, 1}
+};
+
+int get_clocks (void)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	u8 spmf;
+	u8 cpmf;
+	u8 sys_div;
+	u8 ips_div;
+	u8 pci_div;
+	u32 ref_clk = CONFIG_SYS_MPC512X_CLKIN;
+	u32 spll;
+	u32 sys_clk;
+	u32 core_clk;
+	u32 csb_clk;
+	u32 ips_clk;
+	u32 pci_clk;
+	u32 reg;
+
+	reg = in_be32(&im->sysconf.immrbar);
+	if ((reg & IMMRBAR_BASE_ADDR) != (u32) im)
+		return -1;
+
+	reg = in_be32(&im->clk.spmr);
+	spmf = (reg & SPMR_SPMF) >> SPMR_SPMF_SHIFT;
+	spll = ref_clk * spmf_mult[spmf];
+
+	reg = in_be32(&im->clk.scfr[1]);
+	sys_div = (reg & SCFR2_SYS_DIV) >> SCFR2_SYS_DIV_SHIFT;
+	sys_clk = (spll * sys_dividors[sys_div][1]) / sys_dividors[sys_div][0];
+
+	csb_clk = sys_clk / 2;
+
+	reg = in_be32(&im->clk.spmr);
+	cpmf = (reg & SPMR_CPMF) >> SPMR_CPMF_SHIFT;
+	core_clk = (csb_clk * cpmf_mult[cpmf][0]) / cpmf_mult[cpmf][1];
+
+	reg = in_be32(&im->clk.scfr[0]);
+	ips_div = (reg & SCFR1_IPS_DIV_MASK) >> SCFR1_IPS_DIV_SHIFT;
+	if (ips_div != 0) {
+		ips_clk = csb_clk / ips_div;
+	} else {
+		/* in case we cannot get a sane IPS divisor, fail gracefully */
+		ips_clk = 0;
+	}
+
+	reg = in_be32(&im->clk.scfr[0]);
+	pci_div = (reg & SCFR1_PCI_DIV_MASK) >> SCFR1_PCI_DIV_SHIFT;
+	if (pci_div != 0) {
+		pci_clk = csb_clk / pci_div;
+	} else {
+		/* in case we cannot get a sane IPS divisor, fail gracefully */
+		pci_clk = 333333;
+	}
+
+	gd->ips_clk = ips_clk;
+	gd->pci_clk = pci_clk;
+	gd->csb_clk = csb_clk;
+	gd->cpu_clk = core_clk;
+	gd->bus_clk = csb_clk;
+	return 0;
+
+}
+
+/********************************************
+ * get_bus_freq
+ * return system bus freq in Hz
+ *********************************************/
+ulong get_bus_freq (ulong dummy)
+{
+	return gd->csb_clk;
+}
+
+int do_clocks (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	char buf[32];
+
+	printf("Clock configuration:\n");
+	printf("  CPU:                 %-4s MHz\n", strmhz(buf, gd->cpu_clk));
+	printf("  Coherent System Bus: %-4s MHz\n", strmhz(buf, gd->csb_clk));
+	printf("  IPS Bus:             %-4s MHz\n", strmhz(buf, gd->ips_clk));
+	printf("  PCI:                 %-4s MHz\n", strmhz(buf, gd->pci_clk));
+	printf("  DDR:                 %-4s MHz\n", strmhz(buf, 2*gd->csb_clk));
+	return 0;
+}
+
+U_BOOT_CMD(clocks, 1, 0, do_clocks,
+	"print clock configuration",
+	"    clocks"
+);
+
+int prt_mpc512x_clks (void)
+{
+	do_clocks (NULL, 0, 0, NULL);
+	return (0);
+}
diff --git a/arch/powerpc/cpu/mpc512x/start.S b/arch/powerpc/cpu/mpc512x/start.S
new file mode 100644
index 0000000..d26b617
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/start.S
@@ -0,0 +1,711 @@
+/*
+ * Copyright (C) 1998  Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000-2009 Wolfgang Denk <wd@denx.de>
+ * Copyright Freescale Semiconductor, Inc. 2004, 2006.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Based on the MPC83xx code.
+ */
+
+/*
+ *  U-Boot - Startup Code for MPC512x based Embedded Boards
+ */
+
+#include <config.h>
+#include <timestamp.h>
+#include <version.h>
+
+#define CONFIG_521X	1		/* needed for Linux kernel header files*/
+
+#include <asm/immap_512x.h>
+#include "asm-offsets.h"
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef  CONFIG_IDENT_STRING
+#define  CONFIG_IDENT_STRING "MPC512X"
+#endif
+
+/*
+ * Floating Point enable, Machine Check and Recoverable Interr.
+ */
+#undef	MSR_KERNEL
+#ifdef DEBUG
+#define MSR_KERNEL (MSR_FP|MSR_RI)
+#else
+#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
+#endif
+
+/* Macros for manipulating CSx_START/STOP */
+#define START_REG(start)	((start) >> 16)
+#define STOP_REG(start, size)	(((start) + (size) - 1) >> 16)
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+	START_GOT
+	GOT_ENTRY(_GOT2_TABLE_)
+	GOT_ENTRY(_FIXUP_TABLE_)
+
+	GOT_ENTRY(_start)
+	GOT_ENTRY(_start_of_vectors)
+	GOT_ENTRY(_end_of_vectors)
+	GOT_ENTRY(transfer_to_handler)
+
+	GOT_ENTRY(__init_end)
+	GOT_ENTRY(_end)
+	GOT_ENTRY(__bss_start)
+	END_GOT
+
+/*
+ * Magic number and version string
+ */
+	.long	0x27051956		/* U-Boot Magic Number */
+	.globl	version_string
+version_string:
+	.ascii U_BOOT_VERSION
+	.ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
+	.ascii " ", CONFIG_IDENT_STRING, "\0"
+
+/*
+ * Vector Table
+ */
+	.text
+	. = EXC_OFF_SYS_RESET
+
+	.globl	_start
+	/* Start from here after reset/power on */
+_start:
+	li	r21, BOOTFLAG_COLD  /* Normal Power-On: Boot from FLASH */
+	b	boot_cold
+
+	.globl	_start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+	STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+	STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+	STD_EXCEPTION(0x500, ExtInterrupt, UnknownException)
+
+/* Alignment exception. */
+	. = 0x600
+Alignment:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	mfspr	r4,DAR
+	stw	r4,_DAR(r21)
+	mfspr	r5,DSISR
+	stw	r5,_DSISR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+	. = 0x700
+ProgramCheck:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+		MSR_KERNEL, COPY_EE)
+
+/* Floating Point Unit unavailable exception */
+	STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+/* Decrementer */
+	STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+
+/* Critical interrupt */
+	STD_EXCEPTION(0xa00, Critical, UnknownException)
+
+/* System Call */
+	STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+
+/* Trace interrupt */
+	STD_EXCEPTION(0xd00, Trace, UnknownException)
+
+/* Performance Monitor interrupt */
+	STD_EXCEPTION(0xf00, PerfMon, UnknownException)
+
+/* Intruction Translation Miss */
+	STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
+
+/* Data Load Translation Miss */
+	STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
+
+/* Data Store Translation Miss */
+	STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
+
+/* Instruction Address Breakpoint */
+	STD_EXCEPTION(0x1300, InstructionAddrBreakpoint, DebugException)
+
+/* System Management interrupt */
+	STD_EXCEPTION(0x1400, SystemMgmtInterrupt, UnknownException)
+
+	.globl	_end_of_vectors
+_end_of_vectors:
+
+	. = 0x3000
+boot_cold:
+	/* Save msr contents */
+	mfmsr	r5
+
+	/* Set IMMR area to our preferred location */
+	lis	r4, CONFIG_DEFAULT_IMMR@h
+	lis	r3, CONFIG_SYS_IMMR@h
+	ori	r3, r3, CONFIG_SYS_IMMR@l
+	stw	r3, IMMRBAR(r4)
+	mtspr	MBAR, r3		/* IMMRBAR is mirrored into the MBAR SPR (311) */
+
+	/* Initialise the machine */
+	bl	cpu_early_init
+
+	/*
+	 * Set up Local Access Windows:
+	 *
+	 * 1) Boot/CS0 (boot FLASH)
+	 * 2) On-chip SRAM (initial stack purposes)
+	 */
+
+	/* Boot CS/CS0 window range */
+	lis     r3, CONFIG_SYS_IMMR@h
+	ori     r3, r3, CONFIG_SYS_IMMR@l
+
+	lis	r4, START_REG(CONFIG_SYS_FLASH_BASE)
+	ori	r4, r4, STOP_REG(CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_SIZE)
+	stw	r4, LPCS0AW(r3)
+
+	/*
+	 * The SRAM window has a fixed size (256K), so only the start address
+	 * is necessary
+	 */
+	lis	r4, START_REG(CONFIG_SYS_SRAM_BASE) & 0xff00
+	stw	r4, SRAMBAR(r3)
+
+	/*
+	 * According to MPC5121e RM, configuring local access windows should
+	 * be followed by a dummy read of the config register that was
+	 * modified last and an isync
+	 */
+	lwz	r4, SRAMBAR(r3)
+	isync
+
+	/*
+	 * Set configuration of the Boot/CS0, the SRAM window does not have a
+	 * config register so no params can be set for it
+	 */
+	lis     r3, (CONFIG_SYS_IMMR + LPC_OFFSET)@h
+	ori     r3, r3, (CONFIG_SYS_IMMR + LPC_OFFSET)@l
+
+	lis     r4, CONFIG_SYS_CS0_CFG@h
+	ori     r4, r4, CONFIG_SYS_CS0_CFG@l
+	stw     r4, CS0_CONFIG(r3)
+
+	/* Master enable all CS's */
+	lis	r4, CS_CTRL_ME@h
+	ori	r4, r4, CS_CTRL_ME@l
+	stw	r4, CS_CTRL(r3)
+
+	lis	r4, (CONFIG_SYS_MONITOR_BASE)@h
+	ori	r4, r4, (CONFIG_SYS_MONITOR_BASE)@l
+	addi	r5, r4, in_flash - _start + EXC_OFF_SYS_RESET
+	mtlr	r5
+	blr
+
+in_flash:
+	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
+	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
+
+	li	r0, 0		/* Make room for stack frame header and	*/
+	stwu	r0, -4(r1)	/* clear final stack frame so that	*/
+	stwu	r0, -4(r1)	/* stack backtraces terminate cleanly	*/
+
+	/* let the C-code set up the rest			*/
+	/*							*/
+	/* Be careful to keep code relocatable & stack humble	*/
+	/*------------------------------------------------------*/
+
+	GET_GOT			/* initialize GOT access	*/
+
+	/* r3: IMMR */
+	lis	r3, CONFIG_SYS_IMMR@h
+	/* run low-level CPU init code (in Flash) */
+	bl	cpu_init_f
+
+	/* r3: BOOTFLAG */
+	mr	r3, r21
+	/* run 1st part of board init code (in Flash) */
+	bl	board_init_f
+
+	/* NOTREACHED - board_init_f() does not return */
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+	.globl	transfer_to_handler
+transfer_to_handler:
+	stw	r22,_NIP(r21)
+	lis	r22,MSR_POW@h
+	andc	r23,r23,r22
+	stw	r23,_MSR(r21)
+	SAVE_GPR(7, r21)
+	SAVE_4GPRS(8, r21)
+	SAVE_8GPRS(12, r21)
+	SAVE_8GPRS(24, r21)
+	mflr	r23
+	andi.	r24,r23,0x3f00		/* get vector offset */
+	stw	r24,TRAP(r21)
+	li	r22,0
+	stw	r22,RESULT(r21)
+	lwz	r24,0(r23)		/* virtual address of handler */
+	lwz	r23,4(r23)		/* where to go when done */
+	mtspr	SRR0,r24
+	mtspr	SRR1,r20
+	mtlr	r23
+	SYNC
+	rfi				/* jump to handler, enable MMU */
+
+int_return:
+	mfmsr	r28		/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC			/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SRR0,r2
+	mtspr	SRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfi
+
+/*
+ * This code initialises the machine, it expects original MSR contents to be in r5.
+ */
+cpu_early_init:
+	/* Initialize machine status; enable machine check interrupt */
+	/*-----------------------------------------------------------*/
+
+	li	r3, MSR_KERNEL			/* Set ME and RI flags */
+	rlwimi	r3, r5, 0, 25, 25		/* preserve IP bit */
+#ifdef DEBUG
+	rlwimi	r3, r5, 0, 21, 22		/* debugger might set SE, BE bits */
+#endif
+	mtmsr	r3
+	SYNC
+	mtspr	SRR1, r3			/* Mirror current MSR state in SRR1 */
+
+	lis	r3, CONFIG_SYS_IMMR@h
+
+#if defined(CONFIG_WATCHDOG)
+	/* Initialise the watchdog and reset it */
+	/*--------------------------------------*/
+	lis r4, CONFIG_SYS_WATCHDOG_VALUE
+	ori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR)
+	stw r4, SWCRR(r3)
+
+	/* reset */
+	li	r4, 0x556C
+	sth	r4, SWSRR@l(r3)
+	li	r4, 0x0
+	ori	r4, r4, 0xAA39
+	sth	r4, SWSRR@l(r3)
+#else
+	/* Disable the watchdog */
+	/*----------------------*/
+	lwz r4, SWCRR(r3)
+	/*
+	 * Check to see if it's enabled for disabling: once disabled by s/w
+	 * it's not possible to re-enable it
+	 */
+	andi. r4, r4, 0x4
+	beq 1f
+	xor r4, r4, r4
+	stw r4, SWCRR(r3)
+1:
+#endif /* CONFIG_WATCHDOG */
+
+	/* Initialize the Hardware Implementation-dependent Registers */
+	/* HID0 also contains cache control			*/
+	/*------------------------------------------------------*/
+	lis	r3, CONFIG_SYS_HID0_INIT@h
+	ori	r3, r3, CONFIG_SYS_HID0_INIT@l
+	SYNC
+	mtspr	HID0, r3
+
+	lis	r3, CONFIG_SYS_HID0_FINAL@h
+	ori	r3, r3, CONFIG_SYS_HID0_FINAL@l
+	SYNC
+	mtspr	HID0, r3
+
+	lis	r3, CONFIG_SYS_HID2@h
+	ori	r3, r3, CONFIG_SYS_HID2@l
+	SYNC
+	mtspr	HID2, r3
+	sync
+	blr
+
+
+/* Cache functions.
+ *
+ * Note: requires that all cache bits in
+ * HID0 are in the low half word.
+ */
+	.globl	icache_enable
+icache_enable:
+	mfspr	r3, HID0
+	ori	r3, r3, HID0_ICE
+	lis	r4, 0
+	ori	r4, r4, HID0_ILOCK
+	andc	r3, r3, r4
+	ori	r4, r3, HID0_ICFI
+	isync
+	mtspr	HID0, r4    /* sets enable and invalidate, clears lock */
+	isync
+	mtspr	HID0, r3	/* clears invalidate */
+	blr
+
+	.globl	icache_disable
+icache_disable:
+	mfspr	r3, HID0
+	lis	r4, 0
+	ori	r4, r4, HID0_ICE|HID0_ILOCK
+	andc	r3, r3, r4
+	ori	r4, r3, HID0_ICFI
+	isync
+	mtspr	HID0, r4     /* sets invalidate, clears enable and lock*/
+	isync
+	mtspr	HID0, r3	/* clears invalidate */
+	blr
+
+	.globl	icache_status
+icache_status:
+	mfspr	r3, HID0
+	rlwinm	r3, r3, (31 - HID0_ICE_SHIFT + 1), 31, 31
+	blr
+
+	.globl	dcache_enable
+dcache_enable:
+	mfspr	r3, HID0
+	li	r5, HID0_DCFI|HID0_DLOCK
+	andc	r3, r3, r5
+	mtspr	HID0, r3		/* no invalidate, unlock */
+	ori	r3, r3, HID0_DCE
+	ori	r5, r3, HID0_DCFI
+	mtspr	HID0, r5		/* enable + invalidate */
+	mtspr	HID0, r3		/* enable */
+	sync
+	blr
+
+	.globl	dcache_disable
+dcache_disable:
+	mfspr	r3, HID0
+	lis	r4, 0
+	ori	r4, r4, HID0_DCE|HID0_DLOCK
+	andc	r3, r3, r4
+	ori	r4, r3, HID0_DCI
+	sync
+	mtspr	HID0, r4	/* sets invalidate, clears enable and lock */
+	sync
+	mtspr	HID0, r3	/* clears invalidate */
+	blr
+
+	.globl	dcache_status
+dcache_status:
+	mfspr	r3, HID0
+	rlwinm	r3, r3, (31 - HID0_DCE_SHIFT + 1), 31, 31
+	blr
+
+	.globl get_pvr
+get_pvr:
+	mfspr	r3, PVR
+	blr
+
+/*-------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+	.globl	relocate_code
+relocate_code:
+	mr	r1,  r3		/* Set new stack pointer	*/
+	mr	r9,  r4		/* Save copy of Global Data pointer */
+	mr	r10, r5		/* Save copy of Destination Address */
+
+	GET_GOT
+	mr	r3,  r5				/* Destination Address */
+	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address */
+	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
+	lwz	r5, GOT(__init_end)
+	sub	r5, r5, r4
+	li	r6, CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size */
+
+	/*
+	 * Fix GOT pointer:
+	 *
+	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE)
+	 *		+ Destination Address
+	 *
+	 * Offset:
+	 */
+	sub	r15, r10, r4
+
+	/* First our own GOT */
+	add	r12, r12, r15
+	/* then the one used by the C code */
+	add	r30, r30, r15
+
+	/*
+	 * Now relocate code
+	 */
+	cmplw	cr1,r3,r4
+	addi	r0,r5,3
+	srwi.	r0,r0,2
+	beq	cr1,4f		/* In place copy is not necessary */
+	beq	7f		/* Protect against 0 count	  */
+	mtctr	r0
+	bge	cr1,2f
+	la	r8,-4(r4)
+	la	r7,-4(r3)
+
+	/* copy */
+1:	lwzu	r0,4(r8)
+	stwu	r0,4(r7)
+	bdnz	1b
+
+	addi	r0,r5,3
+	srwi.	r0,r0,2
+	mtctr	r0
+	la	r8,-4(r4)
+	la	r7,-4(r3)
+
+	/* and compare */
+20:	lwzu	r20,4(r8)
+	lwzu	r21,4(r7)
+	xor. r22, r20, r21
+	bne  30f
+	bdnz	20b
+	b 4f
+
+	/* compare failed */
+30:	li r3, 0
+	blr
+
+2:	slwi	r0,r0,2 /* re copy in reverse order ... y do we needed it? */
+	add	r8,r4,r0
+	add	r7,r3,r0
+3:	lwzu	r0,-4(r8)
+	stwu	r0,-4(r7)
+	bdnz	3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:	cmpwi	r6,0
+	add	r5,r3,r5
+	beq	7f		/* Always flush prefetch queue in any case */
+	subi	r0,r6,1
+	andc	r3,r3,r0
+	mr	r4,r3
+5:	dcbst	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	5b
+	sync			/* Wait for all dcbst to complete on bus */
+	mr	r4,r3
+6:	icbi	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	6b
+7:	sync			/* Wait for all icbi to complete on bus	*/
+	isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+	mtlr	r0
+	blr
+
+in_ram:
+	/*
+	 * Relocation Function, r12 point to got2+0x8000
+	 *
+	 * Adjust got2 pointers, no need to check for 0, this code
+	 * already puts a few entries in the table.
+	 */
+	li	r0,__got2_entries@sectoff@l
+	la	r3,GOT(_GOT2_TABLE_)
+	lwz	r11,GOT(_GOT2_TABLE_)
+	mtctr	r0
+	sub	r11,r3,r11
+	addi	r3,r3,-4
+1:	lwzu	r0,4(r3)
+	cmpwi	r0,0
+	beq-	2f
+	add	r0,r0,r11
+	stw	r0,0(r3)
+2:	bdnz	1b
+
+	/*
+	 * Now adjust the fixups and the pointers to the fixups
+	 * in case we need to move ourselves again.
+	 */
+	li	r0,__fixup_entries@sectoff@l
+	lwz	r3,GOT(_FIXUP_TABLE_)
+	cmpwi	r0,0
+	mtctr	r0
+	addi	r3,r3,-4
+	beq	4f
+3:	lwzu	r4,4(r3)
+	lwzux	r0,r4,r11
+	add	r0,r0,r11
+	stw	r10,0(r3)
+	stw	r0,0(r4)
+	bdnz	3b
+4:
+clear_bss:
+	/*
+	 * Now clear BSS segment
+	 */
+	lwz	r3,GOT(__bss_start)
+	lwz	r4,GOT(_end)
+
+	cmplw	0, r3, r4
+	beq	6f
+
+	li	r0, 0
+5:
+	stw	r0, 0(r3)
+	addi	r3, r3, 4
+	cmplw	0, r3, r4
+	bne	5b
+6:
+	mr	r3, r9		/* Global Data pointer		*/
+	mr	r4, r10		/* Destination Address		*/
+	bl	board_init_r
+
+	/*
+	 * Copy exception vector code to low memory
+	 *
+	 * r3: dest_addr
+	 * r7: source address, r8: end address, r9: target address
+	 */
+	.globl	trap_init
+trap_init:
+	mflr	r4		/* save link register */
+	GET_GOT
+	lwz	r7, GOT(_start)
+	lwz	r8, GOT(_end_of_vectors)
+
+	li	r9, 0x100	/* reset vector at 0x100 */
+
+	cmplw	0, r7, r8
+	bgelr			/* return if r7>=r8 - just in case */
+1:
+	lwz	r0, 0(r7)
+	stw	r0, 0(r9)
+	addi	r7, r7, 4
+	addi	r9, r9, 4
+	cmplw	0, r7, r8
+	bne	1b
+
+	/*
+	 * relocate `hdlr' and `int_return' entries
+	 */
+	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+	li	r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector */
+	cmplw	0, r7, r8
+	blt	2b
+
+	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector */
+	cmplw	0, r7, r8
+	blt	3b
+
+	li	r7, .L_Trace - _start + EXC_OFF_SYS_RESET
+	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector */
+	cmplw	0, r7, r8
+	blt	4b
+
+	mfmsr	r3			/* now that the vectors have */
+	lis	r7, MSR_IP@h		/* relocated into low memory */
+	ori	r7, r7, MSR_IP@l	/* MSR[IP] can be turned off */
+	andc	r3, r3, r7		/* (if it was on) */
+	SYNC				/* Some chip revs need this... */
+	mtmsr	r3
+	SYNC
+
+	mtlr	r4			/* restore link register    */
+	blr
diff --git a/arch/powerpc/cpu/mpc512x/traps.c b/arch/powerpc/cpu/mpc512x/traps.c
new file mode 100644
index 0000000..786f4a5
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/traps.c
@@ -0,0 +1,212 @@
+/*
+ * (C) Copyright 2000 - 2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Derived from the MPC83xx code.
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware
+ * exceptions
+ */
+
+#include <common.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern unsigned long search_exception_table(unsigned long);
+
+/*
+ * End of addressable memory.  This may be less than the actual
+ * amount of memory on the system if we're unable to keep all
+ * the memory mapped in.
+ */
+extern ulong get_effective_memsize(void);
+#define END_OF_MEM (gd->bd->bi_memstart + get_effective_memsize())
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace (unsigned long *sp)
+{
+	int cnt = 0;
+	unsigned long i;
+
+	puts ("Call backtrace: ");
+	while (sp) {
+		if ((uint)sp > END_OF_MEM)
+			break;
+
+		i = sp[1];
+		if (cnt++ % 7 == 0)
+			putc ('\n');
+		printf ("%08lX ", i);
+		if (cnt > 32) break;
+		sp = (unsigned long *) *sp;
+	}
+	putc ('\n');
+}
+
+void show_regs (struct pt_regs * regs)
+{
+	int i;
+
+	printf ("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+	       regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+	printf ("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+	       regs->msr, regs->msr & MSR_EE ? 1 : 0, regs->msr & MSR_PR ? 1 : 0,
+	       regs->msr & MSR_FP ? 1 : 0,regs->msr & MSR_ME ? 1 : 0,
+	       regs->msr & MSR_IR ? 1 : 0,
+	       regs->msr & MSR_DR ? 1 : 0);
+
+	putc ('\n');
+	for (i = 0;  i < 32;  i++) {
+		if ((i % 8) == 0) {
+			printf ("GPR%02d: ", i);
+		}
+
+		printf ("%08lX ", regs->gpr[i]);
+		if ((i % 8) == 7) {
+			putc ('\n');
+		}
+	}
+}
+
+
+void
+_exception (int signr, struct pt_regs *regs)
+{
+	show_regs (regs);
+	print_backtrace ((unsigned long *)regs->gpr[1]);
+	panic ("Exception at pc %lx signal %d", regs->nip,signr);
+}
+
+
+void
+MachineCheckException (struct pt_regs *regs)
+{
+	unsigned long fixup;
+
+	if ((fixup = search_exception_table (regs->nip)) != 0) {
+		regs->nip = fixup;
+		return;
+	}
+
+#ifdef CONFIG_CMD_KGDB
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	puts ("Machine check.\nCaused by (from msr): ");
+	printf ("regs %p ",regs);
+	switch (regs->msr & 0x00FF0000) {
+	case (0x80000000 >> 10):
+		puts ("Instruction cache parity signal\n");
+		break;
+	case (0x80000000 >> 11):
+		puts ("Data cache parity signal\n");
+		break;
+	case (0x80000000 >> 12):
+		puts ("Machine check signal\n");
+		break;
+	case (0x80000000 >> 13):
+		puts ("Transfer error ack signal\n");
+		break;
+	case (0x80000000 >> 14):
+		puts ("Data parity signal\n");
+		break;
+	case (0x80000000 >> 15):
+		puts ("Address parity signal\n");
+		break;
+	default:
+		puts ("Unknown values in msr\n");
+	}
+	show_regs (regs);
+	print_backtrace ((unsigned long *)regs->gpr[1]);
+
+	panic ("machine check");
+}
+
+void
+AlignmentException (struct pt_regs *regs)
+{
+#ifdef CONFIG_CMD_KGDB
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs (regs);
+	print_backtrace ((unsigned long *)regs->gpr[1]);
+	panic ("Alignment Exception");
+}
+
+void
+ProgramCheckException (struct pt_regs *regs)
+{
+#ifdef CONFIG_CMD_KGDB
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs (regs);
+	print_backtrace ((unsigned long *)regs->gpr[1]);
+	panic ("Program Check Exception");
+}
+
+void
+SoftEmuException (struct pt_regs *regs)
+{
+#ifdef CONFIG_CMD_KGDB
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs (regs);
+	print_backtrace ((unsigned long *)regs->gpr[1]);
+	panic ("Software Emulation Exception");
+}
+
+
+void
+UnknownException (struct pt_regs *regs)
+{
+#ifdef CONFIG_CMD_KGDB
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	printf ("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+	       regs->nip, regs->msr, regs->trap);
+	_exception (0, regs);
+}
+
+#ifdef CONFIG_CMD_BEDBUG
+extern void do_bedbug_breakpoint (struct pt_regs *);
+#endif
+
+void
+DebugException (struct pt_regs *regs)
+{
+	printf ("Debugger trap at @ %lx\n", regs->nip );
+	show_regs (regs);
+#ifdef CONFIG_CMD_BEDBUG
+	do_bedbug_breakpoint (regs);
+#endif
+}
diff --git a/arch/powerpc/cpu/mpc512x/u-boot.lds b/arch/powerpc/cpu/mpc512x/u-boot.lds
new file mode 100644
index 0000000..c716799
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/u-boot.lds
@@ -0,0 +1,120 @@
+/*
+ * (C) Copyright 2007 DENX Software Engineering.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text)	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data)	}
+  .rel.rodata    : { *(.rel.rodata)	}
+  .rela.rodata   : { *(.rela.rodata)	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	}
+  .plt : { *(.plt) }
+  .text      :
+  {
+    arch/powerpc/cpu/mpc512x/start.o	(.text)
+    *(.text)
+    *(.got1)
+    . = ALIGN(16);
+    *(.eh_frame)
+    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x0FFF) & 0xFFFFF000;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+  __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  . = .;
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+
+  . = .;
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(4096);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss (NOLOAD)       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+   . = ALIGN(4);
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}
+ENTRY(_start)
diff --git a/arch/powerpc/cpu/mpc5xx/Makefile b/arch/powerpc/cpu/mpc5xx/Makefile
new file mode 100644
index 0000000..80c5320
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/Makefile
@@ -0,0 +1,59 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2003
+# Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+#
+# File:			arch/powerpc/cpu/mpc5xx/Makefile
+#
+# Discription:		Makefile to build mpc5xx cpu configuration.
+#			Will include top config.mk which itselfs
+#			uses the definitions made in arch/powerpc/cpu/mpc5xx/config.mk
+#
+
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(CPU).a
+
+START	= start.o
+COBJS	= serial.o cpu.o cpu_init.o interrupts.o traps.o speed.o spi.o
+
+SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc5xx/config.mk b/arch/powerpc/cpu/mpc5xx/config.mk
new file mode 100644
index 0000000..5f9285d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/config.mk
@@ -0,0 +1,36 @@
+#
+# (C) Copyright 2003
+# Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+#
+# File:			config.mk
+#
+# Discription:		compiler flags and make definitions
+#
+
+
+PLATFORM_RELFLAGS +=	-fPIC -meabi
+
+PLATFORM_CPPFLAGS +=	-DCONFIG_5xx -ffixed-r2 -mpowerpc -msoft-float
+
+# Use default linker script.  Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/arch/powerpc/cpu/mpc5xx/u-boot.lds
diff --git a/arch/powerpc/cpu/mpc5xx/cpu.c b/arch/powerpc/cpu/mpc5xx/cpu.c
new file mode 100644
index 0000000..7fffebc
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/cpu.c
@@ -0,0 +1,171 @@
+/*
+ * (C) Copyright 2003
+ * Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,
+ */
+
+/*
+ * File:		cpu.c
+ *
+ * Discription:		Some cpu specific function for watchdog,
+ *                      cpu version test, clock setting ...
+ *
+ */
+
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc5xx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if (defined(CONFIG_MPC555))
+#  define	ID_STR	"MPC555/556"
+
+/*
+ * Check version of cpu with Processor Version Register (PVR)
+ */
+static int check_cpu_version (long clock, uint pvr, uint immr)
+{
+    char buf[32];
+	/* The highest 16 bits should be 0x0002 for a MPC555/556 */
+	if ((pvr >> 16) == 0x0002) {
+		printf (" " ID_STR " Version %x", (pvr >> 16));
+		printf (" at %s MHz:", strmhz (buf, clock));
+	} else {
+		printf ("Not supported cpu version");
+		return -1;
+	}
+	return 0;
+}
+#endif /* CONFIG_MPC555 */
+
+
+/*
+ * Check version of mpc5xx
+ */
+int checkcpu (void)
+{
+	ulong clock = gd->cpu_clk;
+	uint immr = get_immr (0);	/* Return full IMMR contents */
+	uint pvr = get_pvr ();		/* Retrieve PVR register */
+
+	puts ("CPU:   ");
+
+	return check_cpu_version (clock, pvr, immr);
+}
+
+/*
+ * Called by macro WATCHDOG_RESET
+ */
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset (void)
+{
+	int re_enable = disable_interrupts ();
+
+	reset_5xx_watchdog ((immap_t *) CONFIG_SYS_IMMR);
+	if (re_enable)
+		enable_interrupts ();
+}
+
+/*
+ * Will clear software reset
+ */
+void reset_5xx_watchdog (volatile immap_t * immr)
+{
+	/* Use the MPC5xx Internal Watchdog */
+	immr->im_siu_conf.sc_swsr = 0x556c;	/* Prevent SW time-out */
+	immr->im_siu_conf.sc_swsr = 0xaa39;
+}
+
+#endif /* CONFIG_WATCHDOG */
+
+
+/*
+ * Get timebase clock frequency
+ */
+unsigned long get_tbclk (void)
+{
+	volatile immap_t *immr = (volatile immap_t *) CONFIG_SYS_IMMR;
+	ulong oscclk, factor;
+
+	if (immr->im_clkrst.car_sccr & SCCR_TBS) {
+		return (gd->cpu_clk / 16);
+	}
+
+	factor = (((CONFIG_SYS_PLPRCR) & PLPRCR_MF_MSK) >> PLPRCR_MF_SHIFT) + 1;
+
+	oscclk = gd->cpu_clk / factor;
+
+	if ((immr->im_clkrst.car_sccr & SCCR_RTSEL) == 0 || factor > 2) {
+		return (oscclk / 4);
+	}
+	return (oscclk / 16);
+}
+
+void dcache_enable (void)
+{
+	return;
+}
+
+void dcache_disable (void)
+{
+	return;
+}
+
+int dcache_status (void)
+{
+	return 0;	/* always off */
+}
+
+/*
+ * Reset board
+ */
+int do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+#if defined(CONFIG_PATI)
+	volatile ulong *addr = (ulong *) CONFIG_SYS_RESET_ADDRESS;
+	*addr = 1;
+#else
+	ulong addr;
+
+	/* Interrupts off, enable reset */
+	__asm__ volatile	("  mtspr	81, %r0		\n\t"
+				 "  mfmsr	%r3		\n\t"
+				 "  rlwinm	%r31,%r3,0,25,23\n\t"
+				 "  mtmsr	%r31		\n\t");
+	/*
+	 * Trying to execute the next instruction at a non-existing address
+	 * should cause a machine check, resulting in reset
+	 */
+#ifdef CONFIG_SYS_RESET_ADDRESS
+	addr = CONFIG_SYS_RESET_ADDRESS;
+#else
+	/*
+	 * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address, CONFIG_SYS_MONITOR_BASE         * - sizeof (ulong) is usually a valid address. Better pick an address
+	 * known to be invalid on your system and assign it to CONFIG_SYS_RESET_ADDRESS.
+	 * "(ulong)-1" used to be a good choice for many systems...
+	 */
+	addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong);
+#endif
+	((void (*) (void)) addr) ();
+#endif  /* #if defined(CONFIG_PATI) */
+	return 1;
+}
diff --git a/arch/powerpc/cpu/mpc5xx/cpu_init.c b/arch/powerpc/cpu/mpc5xx/cpu_init.c
new file mode 100644
index 0000000..cb4bf84
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/cpu_init.c
@@ -0,0 +1,123 @@
+/*
+ * (C) Copyright 2003  Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,
+ */
+
+/*
+ * File:		cpu_init.c
+ *
+ * Discription:		Contains initialisation functions to setup
+ *			the cpu properly
+ *
+ */
+
+#include <common.h>
+#include <mpc5xx.h>
+#include <watchdog.h>
+
+/*
+ * Setup essential cpu registers to run
+ */
+void cpu_init_f (volatile immap_t * immr)
+{
+	volatile memctl5xx_t *memctl = &immr->im_memctl;
+	ulong reg;
+
+	/* SYPCR - contains watchdog control. This will enable watchdog */
+	/* if CONFIG_WATCHDOG is set */
+	immr->im_siu_conf.sc_sypcr = CONFIG_SYS_SYPCR;
+
+#if defined(CONFIG_WATCHDOG)
+	reset_5xx_watchdog (immr);
+#endif
+
+	/* SIUMCR - contains debug pin configuration */
+	immr->im_siu_conf.sc_siumcr |= CONFIG_SYS_SIUMCR;
+
+	/* Initialize timebase. Unlock TBSCRK */
+	immr->im_sitk.sitk_tbscrk = KAPWR_KEY;
+	immr->im_sit.sit_tbscr = CONFIG_SYS_TBSCR;
+
+	/* Full IMB bus speed */
+	immr->im_uimb.uimb_umcr = CONFIG_SYS_UMCR;
+
+	/* Time base and decrementer will be enables (TBE) */
+	/* in init_timebase() in time.c called from board_init_f(). */
+
+	/* Initialize the PIT. Unlock PISCRK */
+	immr->im_sitk.sitk_piscrk = KAPWR_KEY;
+	immr->im_sit.sit_piscr = CONFIG_SYS_PISCR;
+
+#if !defined(CONFIG_PATI)
+	/* PATI sest PLL in start.S */
+	/* PLL (CPU clock) settings */
+	immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
+
+	/* If CONFIG_SYS_PLPRCR (set in the various *_config.h files) tries to
+	 * set the MF field, then just copy CONFIG_SYS_PLPRCR over car_plprcr,
+	 * otherwise OR in CONFIG_SYS_PLPRCR so we do not change the currentMF
+	 * field value.
+	 */
+#if ((CONFIG_SYS_PLPRCR & PLPRCR_MF_MSK) != 0)
+	reg = CONFIG_SYS_PLPRCR;			/* reset control bits   */
+#else
+	reg = immr->im_clkrst.car_plprcr;
+	reg &= PLPRCR_MF_MSK;			/* isolate MF field */
+	reg |= CONFIG_SYS_PLPRCR;			/* reset control bits   */
+#endif
+	immr->im_clkrst.car_plprcr = reg;
+
+#endif /* !defined(CONFIG_PATI) */
+
+	/* System integration timers. CONFIG_SYS_MASK has EBDF configuration */
+	immr->im_clkrstk.cark_sccrk = KAPWR_KEY;
+	reg = immr->im_clkrst.car_sccr;
+	reg &= SCCR_MASK;
+	reg |= CONFIG_SYS_SCCR;
+	immr->im_clkrst.car_sccr = reg;
+
+	/* Memory Controller */
+	memctl->memc_br0 = CONFIG_SYS_BR0_PRELIM;
+	memctl->memc_or0 = CONFIG_SYS_OR0_PRELIM;
+
+#if (defined(CONFIG_SYS_OR1_PRELIM) && defined(CONFIG_SYS_BR1_PRELIM))
+	memctl->memc_or1 = CONFIG_SYS_OR1_PRELIM;
+	memctl->memc_br1 = CONFIG_SYS_BR1_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR2_PRELIM) && defined(CONFIG_SYS_BR2_PRELIM)
+	memctl->memc_or2 = CONFIG_SYS_OR2_PRELIM;
+	memctl->memc_br2 = CONFIG_SYS_BR2_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR3_PRELIM) && defined(CONFIG_SYS_BR3_PRELIM)
+	memctl->memc_or3 = CONFIG_SYS_OR3_PRELIM;
+	memctl->memc_br3 = CONFIG_SYS_BR3_PRELIM;
+#endif
+
+}
+
+/*
+ * Initialize higher level parts of cpu
+ */
+int cpu_init_r (void)
+{
+	/* Nothing to do at the moment */
+	return (0);
+}
diff --git a/arch/powerpc/cpu/mpc5xx/interrupts.c b/arch/powerpc/cpu/mpc5xx/interrupts.c
new file mode 100644
index 0000000..167543f
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/interrupts.c
@@ -0,0 +1,207 @@
+/*
+ * (C) Copyright 2000-2002	Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * (C) Copyright 2003		Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,
+ */
+
+/*
+ * File:		interrupt.c
+ *
+ * Discription:		Contains interrupt routines needed by U-Boot
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <mpc5xx.h>
+#include <asm/processor.h>
+
+#if defined(CONFIG_PATI)
+/* PATI uses IRQs for PCI doorbell */
+#undef NR_IRQS
+#define NR_IRQS 16
+#endif
+
+struct interrupt_action {
+	interrupt_handler_t *handler;
+	void *arg;
+	int count;
+};
+
+static struct interrupt_action irq_vecs[NR_IRQS];
+
+/*
+ * Initialise interrupts
+ */
+
+int interrupt_init_cpu (ulong *decrementer_count)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	int vec;
+
+	/* Decrementer used here for status led */
+	*decrementer_count = get_tbclk () / CONFIG_SYS_HZ;
+
+	/* Disable all interrupts */
+	immr->im_siu_conf.sc_simask = 0;
+	for (vec=0; vec<NR_IRQS; vec++) {
+		irq_vecs[vec].handler = NULL;
+		irq_vecs[vec].arg = NULL;
+		irq_vecs[vec].count = 0;
+	}
+
+	return (0);
+}
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt (struct pt_regs *regs)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	int irq;
+	ulong simask, newmask;
+	ulong vec, v_bit;
+
+	/*
+	 * read the SIVEC register and shift the bits down
+	 * to get the irq number
+	 */
+	vec = immr->im_siu_conf.sc_sivec;
+	irq = vec >> 26;
+	v_bit = 0x80000000UL >> irq;
+
+	/*
+	 * Read Interrupt Mask Register and Mask Interrupts
+	 */
+	simask = immr->im_siu_conf.sc_simask;
+	newmask = simask & (~(0xFFFF0000 >> irq));
+	immr->im_siu_conf.sc_simask = newmask;
+
+	if (!(irq & 0x1)) {		/* External Interrupt ?     */
+		ulong siel;
+
+		/*
+		 * Read Interrupt Edge/Level Register
+		 */
+		siel = immr->im_siu_conf.sc_siel;
+
+		if (siel & v_bit) {	/* edge triggered interrupt ?   */
+			/*
+			 * Rewrite SIPEND Register to clear interrupt
+			 */
+			immr->im_siu_conf.sc_sipend = v_bit;
+		}
+	}
+
+	if (irq_vecs[irq].handler != NULL) {
+		irq_vecs[irq].handler (irq_vecs[irq].arg);
+	} else {
+		printf ("\nBogus External Interrupt IRQ %d Vector %ld\n",
+				irq, vec);
+		/* turn off the bogus interrupt to avoid it from now */
+		simask &= ~v_bit;
+	}
+	/*
+	 * Re-Enable old Interrupt Mask
+	 */
+	immr->im_siu_conf.sc_simask = simask;
+}
+
+/*
+ * Install and free an interrupt handler
+ */
+void irq_install_handler (int vec, interrupt_handler_t * handler,
+						  void *arg)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	/* SIU interrupt */
+	if (irq_vecs[vec].handler != NULL) {
+		printf ("SIU interrupt %d 0x%x\n",
+			vec,
+			(uint) handler);
+	}
+	irq_vecs[vec].handler = handler;
+	irq_vecs[vec].arg = arg;
+	immr->im_siu_conf.sc_simask |= 1 << (31 - vec);
+#if 0
+	printf ("Install SIU interrupt for vector %d ==> %p\n",
+		vec, handler);
+#endif
+}
+
+void irq_free_handler (int vec)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	/* SIU interrupt */
+#if 0
+	printf ("Free CPM interrupt for vector %d\n",
+		vec);
+#endif
+	immr->im_siu_conf.sc_simask &= ~(1 << (31 - vec));
+	irq_vecs[vec].handler = NULL;
+	irq_vecs[vec].arg = NULL;
+}
+
+/*
+ *  Timer interrupt - gets called when  bit 0 of DEC changes from
+ *  0. Decrementer is enabled with bit TBE in TBSCR.
+ */
+void timer_interrupt_cpu (struct pt_regs *regs)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+#if 0
+	printf ("*** Timer Interrupt *** ");
+#endif
+	/* Reset Timer Status Bit and Timers Interrupt Status */
+	immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
+	__asm__ ("nop");
+	immr->im_clkrst.car_plprcr |= PLPRCR_TEXPS | PLPRCR_TMIST;
+
+	return;
+}
+
+#if defined(CONFIG_CMD_IRQ)
+/*******************************************************************************
+ *
+ * irqinfo - print information about IRQs
+ *
+ */
+int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	int vec;
+
+	printf ("\nInterrupt-Information:\n");
+	printf ("Nr  Routine   Arg       Count\n");
+
+	for (vec=0; vec<NR_IRQS; vec++) {
+		if (irq_vecs[vec].handler != NULL) {
+			printf ("%02d  %08lx  %08lx  %d\n",
+				vec,
+				(ulong)irq_vecs[vec].handler,
+				(ulong)irq_vecs[vec].arg,
+				irq_vecs[vec].count);
+		}
+	}
+	return 0;
+}
+
+
+#endif
diff --git a/arch/powerpc/cpu/mpc5xx/serial.c b/arch/powerpc/cpu/mpc5xx/serial.c
new file mode 100644
index 0000000..88c6db8
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/serial.c
@@ -0,0 +1,170 @@
+/*
+ * (C) Copyright 2003
+ * Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,
+ */
+
+/*
+ * File:		serial.c
+ *
+ * Discription:		Serial interface driver for SCI1 and SCI2.
+ *			Since this code will be called from ROM use
+ *			only non-static local variables.
+ *
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc5xx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Local function prototypes
+ */
+
+static int ready_to_send(void);
+
+/*
+ * Minimal global serial functions needed to use one of the SCI modules.
+ */
+
+int serial_init (void)
+{
+	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+
+	serial_setbrg();
+
+#if defined(CONFIG_5xx_CONS_SCI1)
+	/* 10-Bit, 1 start bit, 8 data bit, no parity, 1 stop bit */
+	immr->im_qsmcm.qsmcm_scc1r1 = SCI_M_10;
+	immr->im_qsmcm.qsmcm_scc1r1 = SCI_TE | SCI_RE;
+#else
+	immr->im_qsmcm.qsmcm_scc2r1 = SCI_M_10;
+	immr->im_qsmcm.qsmcm_scc2r1 = SCI_TE | SCI_RE;
+#endif
+	return 0;
+}
+
+void serial_putc(const char c)
+{
+	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+
+	/* Test for completition */
+	if(ready_to_send()) {
+#if defined(CONFIG_5xx_CONS_SCI1)
+		immr->im_qsmcm.qsmcm_sc1dr = (short)c;
+#else
+		immr->im_qsmcm.qsmcm_sc2dr = (short)c;
+#endif
+		if(c == '\n') {
+			if(ready_to_send());
+#if defined(CONFIG_5xx_CONS_SCI1)
+			immr->im_qsmcm.qsmcm_sc1dr = (short)'\r';
+#else
+			immr->im_qsmcm.qsmcm_sc2dr = (short)'\r';
+#endif
+		}
+	}
+}
+
+int serial_getc(void)
+{
+	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	volatile short status;
+	unsigned char tmp;
+
+	/* New data ? */
+	do {
+#if defined(CONFIG_5xx_CONS_SCI1)
+		status = immr->im_qsmcm.qsmcm_sc1sr;
+#else
+		status = immr->im_qsmcm.qsmcm_sc2sr;
+#endif
+
+#if defined(CONFIG_WATCHDOG)
+		reset_5xx_watchdog (immr);
+#endif
+	} while ((status & SCI_RDRF) == 0);
+
+	/* Read data */
+#if defined(CONFIG_5xx_CONS_SCI1)
+	tmp = (unsigned char)(immr->im_qsmcm.qsmcm_sc1dr & SCI_SCXDR_MK);
+#else
+	tmp = (unsigned char)( immr->im_qsmcm.qsmcm_sc2dr & SCI_SCXDR_MK);
+#endif
+	return	tmp;
+}
+
+int serial_tstc()
+{
+	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	short status;
+
+	/* New data character ? */
+#if defined(CONFIG_5xx_CONS_SCI1)
+	status = immr->im_qsmcm.qsmcm_sc1sr;
+#else
+	status = immr->im_qsmcm.qsmcm_sc2sr;
+#endif
+	return (status & SCI_RDRF);
+}
+
+void serial_setbrg (void)
+{
+	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	short scxbr;
+
+	/* Set baudrate */
+	scxbr = (gd->cpu_clk / (32 * gd->baudrate));
+#if defined(CONFIG_5xx_CONS_SCI1)
+	immr->im_qsmcm.qsmcm_scc1r0 = (scxbr & SCI_SCXBR_MK);
+#else
+	immr->im_qsmcm.qsmcm_scc2r0 = (scxbr & SCI_SCXBR_MK);
+#endif
+}
+
+void serial_puts (const char *s)
+{
+	while (*s) {
+		serial_putc(*s);
+		++s;
+	}
+}
+
+int ready_to_send(void)
+{
+	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	volatile short status;
+
+	do {
+#if defined(CONFIG_5xx_CONS_SCI1)
+		status = immr->im_qsmcm.qsmcm_sc1sr;
+#else
+		status = immr->im_qsmcm.qsmcm_sc2sr;
+#endif
+
+#if defined(CONFIG_WATCHDOG)
+		reset_5xx_watchdog (immr);
+#endif
+	} while ((status & SCI_TDRE) == 0);
+	return 1;
+
+}
diff --git a/arch/powerpc/cpu/mpc5xx/speed.c b/arch/powerpc/cpu/mpc5xx/speed.c
new file mode 100644
index 0000000..ea5c1de
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/speed.c
@@ -0,0 +1,67 @@
+/*
+ * (C) Copyright 2003
+ * Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,
+ */
+
+/*
+ * File:		speed.c
+ *
+ * Discription:		Provides cpu speed calculation
+ *
+ */
+
+#include <common.h>
+#include <mpc5xx.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Get cpu and bus clock
+ */
+int get_clocks (void)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+#ifndef	CONFIG_5xx_GCLK_FREQ
+	uint divf = (immr->im_clkrst.car_plprcr & PLPRCR_DIVF_MSK);
+	uint mf = ((immr->im_clkrst.car_plprcr & PLPRCR_MF_MSK) >> PLPRCR_MF_SHIFT);
+	ulong vcoout;
+
+	vcoout = (CONFIG_SYS_OSC_CLK / (divf + 1)) * (mf + 1) * 2;
+	if(immr->im_clkrst.car_plprcr & PLPRCR_CSRC_MSK) {
+		gd->cpu_clk = vcoout / (2^(((immr->im_clkrst.car_sccr & SCCR_DFNL_MSK) >> SCCR_DFNL_SHIFT) + 1));
+	} else {
+		gd->cpu_clk = vcoout / (2^(immr->im_clkrst.car_sccr & SCCR_DFNH_MSK));
+	}
+
+#else /* CONFIG_5xx_GCLK_FREQ */
+	gd->bus_clk = CONFIG_5xx_GCLK_FREQ;
+#endif /* CONFIG_5xx_GCLK_FREQ */
+
+	if ((immr->im_clkrst.car_sccr & SCCR_EBDF11) == 0) {
+		/* No Bus Divider active */
+		gd->bus_clk = gd->cpu_clk;
+	} else {
+		/* CLKOUT is GCLK / 2 */
+		gd->bus_clk = gd->cpu_clk / 2;
+	}
+	return (0);
+}
diff --git a/arch/powerpc/cpu/mpc5xx/spi.c b/arch/powerpc/cpu/mpc5xx/spi.c
new file mode 100644
index 0000000..3ca15ea
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/spi.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2001 Navin Boppuri / Prashant Patel
+ *	<nboppuri@trinetcommunication.com>,
+ *	<pmpatel@trinetcommunication.com>
+ * Copyright (c) 2001 Gerd Mennchen <Gerd.Mennchen@icn.siemens.de>
+ * Copyright (c) 2001 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * MPC5xx CPM SPI interface.
+ *
+ * Parts of this code are probably not portable and/or specific to
+ * the board which I used for the tests. Please send fixes/complaints
+ * to wd@denx.de
+ *
+ * Ported to MPC5xx
+ * Copyright (c) 2003 Denis Peter, MPL AG Switzerland, d.petr@mpl.ch.
+ */
+
+#include <common.h>
+#include <mpc5xx.h>
+#include <asm/5xx_immap.h>
+#include <linux/ctype.h>
+#include <malloc.h>
+#include <post.h>
+#include <net.h>
+
+#if defined(CONFIG_SPI)
+
+#undef	DEBUG
+
+#define SPI_EEPROM_WREN		0x06
+#define SPI_EEPROM_RDSR		0x05
+#define SPI_EEPROM_READ		0x03
+#define SPI_EEPROM_WRITE	0x02
+
+
+#ifdef	DEBUG
+
+#define	DPRINT(a)	printf a;
+/* -----------------------------------------------
+ * Helper functions to peek into tx and rx buffers
+ * ----------------------------------------------- */
+static const char * const hex_digit = "0123456789ABCDEF";
+
+static char quickhex (int i)
+{
+	return hex_digit[i];
+}
+
+static void memdump (void *pv, int num)
+{
+	int i;
+	unsigned char *pc = (unsigned char *) pv;
+
+	for (i = 0; i < num; i++)
+		printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f));
+	printf ("\t");
+	for (i = 0; i < num; i++)
+		printf ("%c", isprint (pc[i]) ? pc[i] : '.');
+	printf ("\n");
+}
+#else	/* !DEBUG */
+
+#define	DPRINT(a)
+
+#endif	/* DEBUG */
+
+/* -------------------
+ * Function prototypes
+ * ------------------- */
+void spi_init (void);
+
+ssize_t spi_read (uchar *, int, uchar *, int);
+ssize_t spi_write (uchar *, int, uchar *, int);
+ssize_t spi_xfer (size_t);
+
+
+/* **************************************************************************
+ *
+ *  Function:    spi_init_f
+ *
+ *  Description: Init SPI-Controller (ROM part)
+ *
+ *  return:      ---
+ *
+ * *********************************************************************** */
+
+void spi_init_f (void)
+{
+	int i;
+
+	volatile immap_t *immr;
+	volatile qsmcm5xx_t *qsmcm;
+
+	immr = (immap_t *)  CONFIG_SYS_IMMR;
+	qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
+
+	qsmcm->qsmcm_qsmcr = 0; /* all accesses enabled */
+	qsmcm->qsmcm_qspi_il = 0; /* lowest IRQ */
+
+	/* --------------------------------------------
+	 * GPIO or per. Function
+	 * PQSPAR[00] = 0 reserved
+	 * PQSPAR[01] = 1 [0x4000] -> PERI: (SPICS3)
+	 * PQSPAR[02] = 0 [0x0000] -> GPIO
+	 * PQSPAR[03] = 0 [0x0000] -> GPIO
+	 * PQSPAR[04] = 1 [0x0800] -> PERI: (SPICS0)
+	 * PQSPAR[05] = 0 reseved
+	 * PQSPAR[06] = 1 [0x0200] -> PERI: (SPIMOSI)
+	 * PQSPAR[07] = 1 [0x0100] -> PERI: (SPIMISO)
+	 * -------------------------------------------- */
+	qsmcm->qsmcm_pqspar =  0x3 | (CONFIG_SYS_SPI_CS_USED << 3);
+
+	 /* --------------------------------------------
+	 * DDRQS[00] = 0 reserved
+	 * DDRQS[01] = 1 [0x0040] -> SPICS3 Output
+	 * DDRQS[02] = 0 [0x0000] -> GPIO Output
+	 * DDRQS[03] = 0 [0x0000] -> GPIO Output
+	 * DDRQS[04] = 1 [0x0008] -> SPICS0 Output
+	 * DDRQS[05] = 1 [0x0004] -> SPICLK Output
+	 * DDRQS[06] = 1 [0x0002] -> SPIMOSI Output
+	 * DDRQS[07] = 0 [0x0001] -> SPIMISO Input
+	 * -------------------------------------------- */
+	qsmcm->qsmcm_ddrqs = 0x7E;
+	 /* --------------------------------------------
+	 * Base state for used SPI CS pins, if base = 0 active must be 1
+	 * PORTQS[00] = 0 reserved
+	 * PORTQS[01] = 0 reserved
+	 * PORTQS[02] = 0 reserved
+	 * PORTQS[03] = 0 reserved
+	 * PORTQS[04] = 0 [0x0000] RxD2
+	 * PORTQS[05] = 1 [0x0400] TxD2
+	 * PORTQS[06] = 0 [0x0000] RxD1
+	 * PORTQS[07] = 1 [0x0100] TxD1
+	 * PORTQS[08] = 0 reserved
+	 * PORTQS[09] = 0 [0x0000] -> SPICS3 Base Output
+	 * PORTQS[10] = 0 [0x0000] -> SPICS2 Base Output
+	 * PORTQS[11] = 0 [0x0000] -> SPICS1 Base Output
+	 * PORTQS[12] = 0 [0x0000] -> SPICS0 Base Output
+	 * PORTQS[13] = 0 [0x0004] -> SPICLK Output
+	 * PORTQS[14] = 0 [0x0002] -> SPIMOSI Output
+	 * PORTQS[15] = 0 [0x0001] -> SPIMISO Input
+	 * -------------------------------------------- */
+	qsmcm->qsmcm_portqs |= (CONFIG_SYS_SPI_CS_BASE << 3);
+	/* --------------------------------------------
+	 * Controll Register 0
+	 * SPCR0[00] = 1 (0x8000) Master
+	 * SPCR0[01] = 0 (0x0000) Wired-Or
+	 * SPCR0[2..5] = (0x2000) Bits per transfer (default 8)
+	 * SPCR0[06] = 0 (0x0000) Normal polarity
+	 * SPCR0[07] = 0 (0x0000) Normal Clock Phase
+	 * SPCR0[08..15] = 14 1.4MHz
+	 */
+	qsmcm->qsmcm_spcr0=0xA00E;
+	/* --------------------------------------------
+	 * Controll Register 1
+	 * SPCR1[00] = 0 (0x0000) QSPI enabled
+	 * SPCR1[1..7] =  (0x7F00) Delay before Transfer
+	 * SPCR1[8..15] = (0x0000) Delay After transfer (204.8usec@40MHz)
+	 */
+	qsmcm->qsmcm_spcr1=0x7F00;
+	/* --------------------------------------------
+	 * Controll Register 2
+	 * SPCR2[00] = 0 (0x0000) SPI IRQs Disabeld
+	 * SPCR2[01] = 0 (0x0000) No Wrap around
+	 * SPCR2[02] = 0 (0x0000) Wrap to 0
+	 * SPCR2[3..7] = (0x0000) End Queue pointer = 0
+	 * SPCR2[8..10] = 0 (0x0000) reserved
+	 * SPCR2[11..15] = 0 (0x0000) NewQueue Address = 0
+	 */
+	qsmcm->qsmcm_spcr2=0x0000;
+	/* --------------------------------------------
+	 * Controll Register 3
+	 * SPCR3[00..04] = 0 (0x0000) reserved
+	 * SPCR3[05] = 0 (0x0000) Feedback disabled
+	 * SPCR3[06] = 0 (0x0000) IRQ on HALTA & MODF disabled
+	 * SPCR3[07] = 0 (0x0000) Not halted
+	 */
+	qsmcm->qsmcm_spcr3=0x00;
+	/* --------------------------------------------
+	 * SPSR (Controll Register 3) Read only/ reset Flags 08,09,10
+	 * SPCR3[08] = 1 (0x80) QSPI finished
+	 * SPCR3[09] = 1 (0x40) Mode Fault Flag
+	 * SPCR3[10] = 1 (0x20) HALTA
+	 * SPCR3[11..15] = 0 (0x0000) Last executed command
+	 */
+	qsmcm->qsmcm_spsr=0xE0;
+	/*-------------------------------------------
+	 * Setup RAM
+	 */
+	for(i=0;i<32;i++) {
+		 qsmcm->qsmcm_recram[i]=0x0000;
+		 qsmcm->qsmcm_tranram[i]=0x0000;
+		 qsmcm->qsmcm_comdram[i]=0x00;
+	}
+	return;
+}
+
+/* **************************************************************************
+ *
+ *  Function:    spi_init_r
+ *  Dummy, all initializations have been done in spi_init_r
+ * *********************************************************************** */
+void spi_init_r (void)
+{
+	return;
+
+}
+
+/****************************************************************************
+ *  Function:    spi_write
+ **************************************************************************** */
+ssize_t short_spi_write (uchar *addr, int alen, uchar *buffer, int len)
+{
+	int i,dlen;
+	volatile immap_t *immr;
+	volatile qsmcm5xx_t *qsmcm;
+
+	immr = (immap_t *)  CONFIG_SYS_IMMR;
+	qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
+	for(i=0;i<32;i++) {
+		 qsmcm->qsmcm_recram[i]=0x0000;
+		 qsmcm->qsmcm_tranram[i]=0x0000;
+		 qsmcm->qsmcm_comdram[i]=0x00;
+	}
+	qsmcm->qsmcm_tranram[0] =  SPI_EEPROM_WREN; /* write enable */
+	spi_xfer(1);
+	i=0;
+	qsmcm->qsmcm_tranram[i++] =  SPI_EEPROM_WRITE; /* WRITE memory array */
+	qsmcm->qsmcm_tranram[i++] =  addr[0];
+	qsmcm->qsmcm_tranram[i++] =  addr[1];
+
+	for(dlen=0;dlen<len;dlen++) {
+		qsmcm->qsmcm_tranram[i+dlen] = buffer[dlen]; /* WRITE memory array */
+	}
+	/* transmit it */
+	spi_xfer(i+dlen);
+	/* ignore received data	*/
+	for (i = 0; i < 1000; i++) {
+		qsmcm->qsmcm_tranram[0] =  SPI_EEPROM_RDSR; /* read status */
+		qsmcm->qsmcm_tranram[1] = 0;
+		spi_xfer(2);
+		if (!(qsmcm->qsmcm_recram[1] & 1)) {
+			break;
+		}
+		udelay(1000);
+	}
+	if (i >= 1000) {
+		printf ("*** spi_write: Time out while writing!\n");
+	}
+	return len;
+}
+
+#define TRANSFER_LEN 16
+
+ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
+{
+	int index,i,newlen;
+	uchar newaddr[2];
+	int curraddr;
+
+	curraddr=(addr[alen-2]<<8)+addr[alen-1];
+	i=len;
+	index=0;
+	do {
+		newaddr[1]=(curraddr & 0xff);
+		newaddr[0]=((curraddr>>8) & 0xff);
+		if(i>TRANSFER_LEN) {
+			newlen=TRANSFER_LEN;
+			i-=TRANSFER_LEN;
+		}
+		else {
+			newlen=i;
+			i=0;
+		}
+		short_spi_write (newaddr, 2, &buffer[index], newlen);
+		index+=newlen;
+		curraddr+=newlen;
+	}while(i);
+	return (len);
+}
+
+/****************************************************************************
+ *  Function:    spi_read
+ **************************************************************************** */
+ssize_t short_spi_read (uchar *addr, int alen, uchar *buffer, int len)
+{
+	int i;
+	volatile immap_t *immr;
+	volatile qsmcm5xx_t *qsmcm;
+
+	immr = (immap_t *)  CONFIG_SYS_IMMR;
+	qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
+
+	for(i=0;i<32;i++) {
+		 qsmcm->qsmcm_recram[i]=0x0000;
+		 qsmcm->qsmcm_tranram[i]=0x0000;
+		 qsmcm->qsmcm_comdram[i]=0x00;
+	}
+	i=0;
+	qsmcm->qsmcm_tranram[i++] = (SPI_EEPROM_READ); /* READ memory array */
+	qsmcm->qsmcm_tranram[i++] = addr[0] & 0xff;
+	qsmcm->qsmcm_tranram[i++] = addr[1] & 0xff;
+	spi_xfer(3 + len);
+	for(i=0;i<len;i++) {
+		*buffer++=(char)qsmcm->qsmcm_recram[i+3];
+	}
+	return len;
+}
+
+ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len)
+{
+	int index,i,newlen;
+	uchar newaddr[2];
+	int curraddr;
+
+	curraddr=(addr[alen-2]<<8)+addr[alen-1];
+	i=len;
+	index=0;
+	do {
+		newaddr[1]=(curraddr & 0xff);
+		newaddr[0]=((curraddr>>8) & 0xff);
+		if(i>TRANSFER_LEN) {
+			newlen=TRANSFER_LEN;
+			i-=TRANSFER_LEN;
+		}
+		else {
+			newlen=i;
+			i=0;
+		}
+		short_spi_read (newaddr, 2, &buffer[index], newlen);
+		index+=newlen;
+		curraddr+=newlen;
+	}while(i);
+	return (len);
+}
+
+/****************************************************************************
+ *  Function:    spi_xfer
+ **************************************************************************** */
+ssize_t spi_xfer (size_t count)
+{
+	volatile immap_t *immr;
+	volatile qsmcm5xx_t *qsmcm;
+	int i;
+	int tm;
+	ushort status;
+	immr = (immap_t *)  CONFIG_SYS_IMMR;
+	qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
+	DPRINT (("*** spi_xfer entered count %d***\n",count));
+
+	/* Set CS for device */
+	for(i=0;i<(count-1);i++)
+		qsmcm->qsmcm_comdram[i] = 0x80 | CONFIG_SYS_SPI_CS_ACT;  /* CS3 is connected to the SPI EEPROM */
+
+	qsmcm->qsmcm_comdram[i] = CONFIG_SYS_SPI_CS_ACT; /* CS3 is connected to the SPI EEPROM */
+	qsmcm->qsmcm_spcr2=((count-1)&0x1F)<<8;
+
+	DPRINT (("*** spi_xfer: Bytes to be xferred: %d ***\n", count));
+
+	qsmcm->qsmcm_spsr=0xE0; /* clear all flags */
+
+	/* start spi transfer */
+	DPRINT (("*** spi_xfer: Performing transfer ...\n"));
+	qsmcm->qsmcm_spcr1 |= 0x8000;		/* Start transmit */
+
+	/* --------------------------------
+	 * Wait for SPI transmit to get out
+	 * or time out (1 second = 1000 ms)
+	 * -------------------------------- */
+	for (tm=0; tm<1000; ++tm) {
+		status=qsmcm->qsmcm_spcr1;
+		if((status & 0x8000)==0)
+			break;
+		udelay (1000);
+	}
+	if (tm >= 1000) {
+		printf ("*** spi_xfer: Time out while xferring to/from SPI!\n");
+	}
+#ifdef	DEBUG
+	printf ("\nspi_xfer: txbuf after xfer\n");
+	memdump ((void *) qsmcm->qsmcm_tranram, 32);	/* dump of txbuf before transmit */
+	printf ("spi_xfer: rxbuf after xfer\n");
+	memdump ((void *) qsmcm->qsmcm_recram, 32);	/* dump of rxbuf after transmit */
+	printf ("\nspi_xfer: commbuf after xfer\n");
+	memdump ((void *) qsmcm->qsmcm_comdram, 32);	/* dump of txbuf before transmit */
+	printf ("\n");
+#endif
+
+	return count;
+}
+
+#endif	/* CONFIG_SPI  */
diff --git a/arch/powerpc/cpu/mpc5xx/start.S b/arch/powerpc/cpu/mpc5xx/start.S
new file mode 100644
index 0000000..0af879e
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/start.S
@@ -0,0 +1,576 @@
+/*
+ *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000, 2001, 2002 Wolfgang Denk <wd@denx.de>
+ *  Copyright (C) 2003  Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * File:		start.S
+ *
+ * Discription:		startup code
+ *
+ */
+
+#include <config.h>
+#include <mpc5xx.h>
+#include <timestamp.h>
+#include <version.h>
+
+#define CONFIG_5xx 1		/* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1	/* avoid reading Linux autoconf.h file	*/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <linux/config.h>
+#include <asm/processor.h>
+
+#ifndef  CONFIG_IDENT_STRING
+#define  CONFIG_IDENT_STRING ""
+#endif
+
+/* We don't have a MMU.
+*/
+#undef	MSR_KERNEL
+#define MSR_KERNEL ( MSR_ME | MSR_RI )		/* Machine Check and Recoverable Interr. */
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+	START_GOT
+	GOT_ENTRY(_GOT2_TABLE_)
+	GOT_ENTRY(_FIXUP_TABLE_)
+
+	GOT_ENTRY(_start)
+	GOT_ENTRY(_start_of_vectors)
+	GOT_ENTRY(_end_of_vectors)
+	GOT_ENTRY(transfer_to_handler)
+
+	GOT_ENTRY(__init_end)
+	GOT_ENTRY(_end)
+	GOT_ENTRY(__bss_start)
+	END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+	.text
+	.long	0x27051956			/* U-Boot Magic Number */
+	.globl	version_string
+version_string:
+	.ascii U_BOOT_VERSION
+	.ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
+	.ascii CONFIG_IDENT_STRING, "\0"
+
+	. = EXC_OFF_SYS_RESET
+	.globl	_start
+_start:
+	mfspr	r3, 638
+	li	r4, CONFIG_SYS_ISB			/* Set ISB bit */
+	or	r3, r3, r4
+	mtspr	638, r3
+	li	r21, BOOTFLAG_COLD		/* Normal Power-On: Boot from FLASH	*/
+	b	boot_cold
+
+	. = EXC_OFF_SYS_RESET + 0x20
+
+	.globl	_start_warm
+_start_warm:
+	li	r21, BOOTFLAG_WARM		/* Software reboot */
+	b	boot_warm
+
+boot_cold:
+boot_warm:
+
+	/* Initialize machine status; enable machine check interrupt		*/
+	/*----------------------------------------------------------------------*/
+	li	r3, MSR_KERNEL			/* Set ME, RI flags */
+	mtmsr	r3
+	mtspr	SRR1, r3			/* Make SRR1 match MSR */
+
+	/* Initialize debug port registers					*/
+	/*----------------------------------------------------------------------*/
+	xor	r0, r0, r0			/* Clear R0 */
+	mtspr	LCTRL1, r0			/* Initialize debug port regs */
+	mtspr	LCTRL2, r0
+	mtspr	COUNTA, r0
+	mtspr	COUNTB, r0
+
+#if defined(CONFIG_PATI)
+	/* the external flash access on PATI fails if programming the PLL to 40MHz.
+	 * Copy the PLL programming code to the internal RAM and execute it
+	 *----------------------------------------------------------------------*/
+	lis	r3, CONFIG_SYS_MONITOR_BASE@h
+	ori	r3, r3, CONFIG_SYS_MONITOR_BASE@l
+	addi	r3, r3, pll_prog_code_start - _start + EXC_OFF_SYS_RESET
+
+	lis	r4, CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r4, r4, CONFIG_SYS_INIT_RAM_ADDR@l
+	mtlr	r4
+	addis	r5,0,0x0
+	ori	r5,r5,((pll_prog_code_end - pll_prog_code_start) >>2)
+	mtctr	r5
+	addi	r3, r3, -4
+	addi	r4, r4, -4
+0:
+	lwzu	r0,4(r3)
+	stwu	r0,4(r4)
+	bdnz	0b                /* copy loop */
+	blrl
+#endif
+
+	/*
+	 * Calculate absolute address in FLASH and jump there
+	 *----------------------------------------------------------------------*/
+
+	lis	r3, CONFIG_SYS_MONITOR_BASE@h
+	ori	r3, r3, CONFIG_SYS_MONITOR_BASE@l
+	addi	r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+	mtlr	r3
+	blr
+
+in_flash:
+
+	/* Initialize some SPRs that are hard to access from C			*/
+	/*----------------------------------------------------------------------*/
+
+	lis     r3, CONFIG_SYS_IMMR@h			/* Pass IMMR as arg1 to C routine */
+	lis	r2, CONFIG_SYS_INIT_SP_ADDR@h
+	ori	r1, r2, CONFIG_SYS_INIT_SP_ADDR@l	/* Set up the stack in internal SRAM */
+	/* Note: R0 is still 0 here */
+	stwu	r0, -4(r1)			/* Clear final stack frame so that	*/
+	stwu	r0, -4(r1)			/* stack backtraces terminate cleanly	*/
+
+	/*
+	 * Disable serialized ifetch and show cycles
+	 * (i.e. set processor to normal mode) for maximum
+	 * performance.
+	 */
+
+	li	r2, 0x0007
+	mtspr	ICTRL, r2
+
+	/* Set up debug mode entry */
+
+	lis	r2, CONFIG_SYS_DER@h
+	ori	r2, r2, CONFIG_SYS_DER@l
+	mtspr	DER, r2
+
+	/* Let the C-code set up the rest					*/
+	/*									*/
+	/* Be careful to keep code relocatable !				*/
+	/*----------------------------------------------------------------------*/
+
+	GET_GOT			/* initialize GOT access			*/
+
+	/* r3: IMMR */
+	bl	cpu_init_f	/* run low-level CPU init code     (from Flash)	*/
+
+	mr	r3, r21
+	/* r3: BOOTFLAG */
+	bl	board_init_f	/* run 1st part of board init code (from Flash) */
+
+
+	.globl	_start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception.  "Never" generated on the 860. */
+	STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception.  "Never" generated on the 860. */
+	STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+	STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+	. = 0x600
+Alignment:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	mfspr	r4,DAR
+	stw	r4,_DAR(r21)
+	mfspr	r5,DSISR
+	stw	r5,_DSISR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+	. = 0x700
+ProgramCheck:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+		MSR_KERNEL, COPY_EE)
+
+	/* FPU on MPC5xx available. We will use it later.
+	*/
+	STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+	/* I guess we could implement decrementer, and may have
+	 * to someday for timekeeping.
+	 */
+	STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+	STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+	STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+	STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+	STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+	STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+	/* On the MPC8xx, this is a software emulation interrupt.  It occurs
+	 * for all unimplemented and illegal instructions.
+	 */
+	STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
+	STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
+	STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
+
+	STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+	STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+	STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+	STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+	STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+	STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+	STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+
+	STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
+	STD_EXCEPTION(0x1d00, InstructionBreakpoint, DebugException)
+	STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
+	STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
+
+
+	.globl	_end_of_vectors
+_end_of_vectors:
+
+
+	. = 0x2000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+	.globl	transfer_to_handler
+transfer_to_handler:
+	stw	r22,_NIP(r21)
+	lis	r22,MSR_POW@h
+	andc	r23,r23,r22
+	stw	r23,_MSR(r21)
+	SAVE_GPR(7, r21)
+	SAVE_4GPRS(8, r21)
+	SAVE_8GPRS(12, r21)
+	SAVE_8GPRS(24, r21)
+	mflr	r23
+	andi.	r24,r23,0x3f00		/* get vector offset */
+	stw	r24,TRAP(r21)
+	li	r22,0
+	stw	r22,RESULT(r21)
+	mtspr	SPRG2,r22		/* r1 is now kernel sp */
+	lwz	r24,0(r23)		/* virtual address of handler */
+	lwz	r23,4(r23)		/* where to go when done */
+	mtspr	SRR0,r24
+	mtspr	SRR1,r20
+	mtlr	r23
+	SYNC
+	rfi				/* jump to handler, enable MMU */
+
+int_return:
+	mfmsr	r28			/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC				/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)		/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SRR0,r2
+	mtspr	SRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfi
+
+
+/*
+ * unsigned int get_immr (unsigned int mask)
+ *
+ * return (mask ? (IMMR & mask) : IMMR);
+ */
+	.globl	get_immr
+get_immr:
+	mr	r4,r3		/* save mask */
+	mfspr	r3, IMMR	/* IMMR */
+	cmpwi	0,r4,0		/* mask != 0 ? */
+	beq	4f
+	and	r3,r3,r4	/* IMMR & mask */
+4:
+	blr
+
+	.globl get_pvr
+get_pvr:
+	mfspr	r3, PVR
+	blr
+
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+	.globl	relocate_code
+relocate_code:
+	mr	r1,  r3		/* Set new stack pointer in SRAM	*/
+	mr	r9,  r4		/* Save copy of global data pointer in SRAM */
+	mr	r10, r5		/* Save copy of monitor destination Address in SRAM */
+
+	GET_GOT
+	mr	r3,  r5				/* Destination Address	*/
+	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address	*/
+	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
+	lwz	r5, GOT(__init_end)
+	sub	r5, r5, r4
+
+	/*
+	 * Fix GOT pointer:
+	 *
+	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+	 *
+	 * Offset:
+	 */
+	sub	r15, r10, r4
+
+	/* First our own GOT */
+	add	r12, r12, r15
+	/* the the one used by the C code */
+	add	r30, r30, r15
+
+	/*
+	 * Now relocate code
+	 */
+
+	cmplw	cr1,r3,r4
+	addi	r0,r5,3
+	srwi.	r0,r0,2
+	beq	cr1,4f		/* In place copy is not necessary	*/
+	beq	4f		/* Protect against 0 count		*/
+	mtctr	r0
+	bge	cr1,2f
+
+	la	r8,-4(r4)
+	la	r7,-4(r3)
+1:	lwzu	r0,4(r8)
+	stwu	r0,4(r7)
+	bdnz	1b
+	b	4f
+
+2:	slwi	r0,r0,2
+	add	r8,r4,r0
+	add	r7,r3,r0
+3:	lwzu	r0,-4(r8)
+	stwu	r0,-4(r7)
+	bdnz	3b
+
+4:	sync
+	isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+	mtlr	r0
+	blr
+
+in_ram:
+
+	/*
+	 * Relocation Function, r12 point to got2+0x8000
+	 *
+	 * Adjust got2 pointers, no need to check for 0, this code
+	 * already puts a few entries in the table.
+	 */
+	li	r0,__got2_entries@sectoff@l
+	la	r3,GOT(_GOT2_TABLE_)
+	lwz	r11,GOT(_GOT2_TABLE_)
+	mtctr	r0
+	sub	r11,r3,r11
+	addi	r3,r3,-4
+1:	lwzu	r0,4(r3)
+	cmpwi	r0,0
+	beq-	2f
+	add	r0,r0,r11
+	stw	r0,0(r3)
+2:	bdnz	1b
+
+	/*
+	 * Now adjust the fixups and the pointers to the fixups
+	 * in case we need to move ourselves again.
+	 */
+	li	r0,__fixup_entries@sectoff@l
+	lwz	r3,GOT(_FIXUP_TABLE_)
+	cmpwi	r0,0
+	mtctr	r0
+	addi	r3,r3,-4
+	beq	4f
+3:	lwzu	r4,4(r3)
+	lwzux	r0,r4,r11
+	add	r0,r0,r11
+	stw	r10,0(r3)
+	stw	r0,0(r4)
+	bdnz	3b
+4:
+clear_bss:
+	/*
+	 * Now clear BSS segment
+	 */
+	lwz	r3,GOT(__bss_start)
+	lwz	r4,GOT(_end)
+	cmplw	0, r3, r4
+	beq	6f
+
+	li	r0, 0
+5:
+	stw	r0, 0(r3)
+	addi	r3, r3, 4
+	cmplw	0, r3, r4
+	bne	5b
+6:
+
+	mr	r3, r9		/* Global Data pointer		*/
+	mr	r4, r10		/* Destination Address		*/
+	bl	board_init_r
+
+	/*
+	 * Copy exception vector code to low memory
+	 *
+	 * r3: dest_addr
+	 * r7: source address, r8: end address, r9: target address
+	 */
+	.globl	trap_init
+trap_init:
+	mflr	r4			/* save link register		*/
+	GET_GOT
+	lwz	r7, GOT(_start)
+	lwz	r8, GOT(_end_of_vectors)
+
+	li	r9, 0x100		/* reset vector always at 0x100 */
+
+	cmplw	0, r7, r8
+	bgelr				/* return if r7>=r8 - just in case */
+1:
+	lwz	r0, 0(r7)
+	stw	r0, 0(r9)
+	addi	r7, r7, 4
+	addi	r9, r9, 4
+	cmplw	0, r7, r8
+	bne	1b
+
+	/*
+	 * relocate `hdlr' and `int_return' entries
+	 */
+	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+	li	r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	2b
+
+	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	3b
+
+	li	r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	4b
+
+	mtlr	r4			/* restore link register	*/
+	blr
+
+#if defined(CONFIG_PATI)
+/* Program the PLL */
+pll_prog_code_start:
+	lis	r4, (CONFIG_SYS_IMMR + 0x002fc384)@h
+	ori	r4, r4, (CONFIG_SYS_IMMR + 0x002fc384)@l
+	lis	r3, (0x55ccaa33)@h
+	ori	r3, r3, (0x55ccaa33)@l
+	stw	r3, 0(r4)
+	lis	r4, (CONFIG_SYS_IMMR + 0x002fc284)@h
+	ori	r4, r4, (CONFIG_SYS_IMMR + 0x002fc284)@l
+	lis	r3, CONFIG_SYS_PLPRCR@h
+	ori	r3, r3, CONFIG_SYS_PLPRCR@l
+	stw	r3, 0(r4)
+	addis	r3,0,0x0
+	ori	r3,r3,0xA000
+	mtctr	r3
+..spinlp:
+  bdnz    ..spinlp                /* spin loop */
+	blr
+pll_prog_code_end:
+	nop
+	blr
+#endif
diff --git a/arch/powerpc/cpu/mpc5xx/traps.c b/arch/powerpc/cpu/mpc5xx/traps.c
new file mode 100644
index 0000000..e3ce11b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/traps.c
@@ -0,0 +1,227 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM	0x0001000
+
+
+/*
+ * Print stack backtrace
+ */
+void print_backtrace(unsigned long *sp)
+{
+	int cnt = 0;
+	unsigned long i;
+
+	printf("Call backtrace: ");
+	while (sp) {
+		if ((uint)sp > END_OF_MEM)
+			break;
+
+		i = sp[1];
+		if (cnt++ % 7 == 0)
+			printf("\n");
+		printf("%08lX ", i);
+		if (cnt > 32) break;
+		sp = (unsigned long *)*sp;
+	}
+	printf("\n");
+}
+
+/*
+ * Print current registers
+ */
+void show_regs(struct pt_regs * regs)
+{
+	int i;
+	printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+	       regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+	printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+	       regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+	       regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+	       regs->msr&MSR_IR ? 1 : 0,
+	       regs->msr&MSR_DR ? 1 : 0);
+
+	printf("\n");
+	for (i = 0;  i < 32;  i++) {
+		if ((i % 8) == 0)
+		{
+			printf("GPR%02d: ", i);
+		}
+
+		printf("%08lX ", regs->gpr[i]);
+		if ((i % 8) == 7)
+		{
+			printf("\n");
+		}
+	}
+}
+
+
+/*
+ * General exception handler routine
+ */
+void _exception(int signr, struct pt_regs *regs)
+{
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+/*
+ * Machine check exception handler routine
+ */
+void MachineCheckException(struct pt_regs *regs)
+{
+	unsigned long fixup;
+
+	/* Probing PCI using config cycles cause this exception
+	 * when a device is not present.  Catch it and return to
+	 * the PCI exception handler.
+	 */
+	if ((fixup = search_exception_table(regs->nip)) != 0) {
+		regs->nip = fixup;
+		return;
+	}
+
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	printf("Machine check in kernel mode.\n");
+	printf("Caused by (from msr): ");
+	printf("regs %p ",regs);
+	switch( regs->msr & 0x000F0000) {
+	case (0x80000000>>12):
+		printf("Machine check signal\n");
+		break;
+	case (0x80000000>>13):
+		printf("Transfer error ack signal\n");
+		break;
+	case (0x80000000>>14):
+		printf("Data parity signal\n");
+		break;
+	case (0x80000000>>15):
+		printf("Address parity signal\n");
+		break;
+	default:
+		printf("Unknown values in msr\n");
+	}
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("machine check");
+}
+
+/*
+ * Alignment exception handler routine
+ */
+void AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Alignment Exception");
+}
+
+/*
+ * Program check exception handler routine
+ */
+void ProgramCheckException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Program Check Exception");
+}
+
+/*
+ * Software emulation exception handler routine
+ */
+void SoftEmuException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Software Emulation Exception");
+}
+
+
+/*
+ * Unknown exception handler routine
+ */
+void UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+	       regs->nip, regs->msr, regs->trap);
+	_exception(0, regs);
+}
+
+/*
+ * Debug exception handler routine
+ */
+void DebugException(struct pt_regs *regs)
+{
+	printf("Debugger trap at @ %lx\n", regs->nip );
+	show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+	do_bedbug_breakpoint( regs );
+#endif
+}
diff --git a/arch/powerpc/cpu/mpc5xx/u-boot.lds b/arch/powerpc/cpu/mpc5xx/u-boot.lds
new file mode 100644
index 0000000..d5e5dc1
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/u-boot.lds
@@ -0,0 +1,137 @@
+/*
+ * (C) Copyright 2001	Wolfgang Denk, DENX Software Engineering, wd@denx.de
+ * (C) Copyright 2003	Martin Winistoerfer, martinwinistoerfer@gmx.ch
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text)	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data)	}
+  .rel.rodata    : { *(.rel.rodata)	}
+  .rela.rodata   : { *(.rela.rodata)	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	}
+  .plt : { *(.plt) }
+  .text      :
+  {
+    /* WARNING - the following is hand-optimized to fit within	*/
+    /* the sector layout of our flash chips!	XXX FIXME XXX	*/
+
+    arch/powerpc/cpu/mpc5xx/start.o	(.text)
+
+    *(.text)
+    *(.got1)
+  }
+  _etext = .;
+  PROVIDE (etext = .);
+  .rodata    :
+  {
+    *(.eh_frame)
+    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x00FF) & 0xFFFFFF00;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+  __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  . = .;
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+
+  . = .;
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(256);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(256);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss (NOLOAD)       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+   . = ALIGN(4);
+  }
+
+  _end = . ;
+  PROVIDE (end = .);
+/*   . = env_start;
+	.ppcenv	:
+	{
+		common/env_embedded.o (.ppcenv)
+	}
+*/
+}
diff --git a/arch/powerpc/cpu/mpc5xxx/Makefile b/arch/powerpc/cpu/mpc5xxx/Makefile
new file mode 100644
index 0000000..0ee0611
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/Makefile
@@ -0,0 +1,49 @@
+#
+# (C) Copyright 2003-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(CPU).a
+
+START	= start.o
+SOBJS	= io.o firmware_sc_task_bestcomm.impl.o
+COBJS	= i2c.o traps.o cpu.o cpu_init.o ide.o interrupts.o \
+	  loadtask.o pci_mpc5200.o serial.o speed.o usb_ohci.o usb.o
+
+SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc5xxx/config.mk b/arch/powerpc/cpu/mpc5xxx/config.mk
new file mode 100644
index 0000000..7ef8a47
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/config.mk
@@ -0,0 +1,30 @@
+#
+# (C) Copyright 2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -fPIC -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_MPC5xxx -ffixed-r2 \
+		     -mstring -mcpu=603e -mmultiple
+
+# Use default linker script.  Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/arch/powerpc/cpu/mpc5xxx/u-boot.lds
diff --git a/arch/powerpc/cpu/mpc5xxx/cpu.c b/arch/powerpc/cpu/mpc5xxx/cpu.c
new file mode 100644
index 0000000..b20234d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/cpu.c
@@ -0,0 +1,205 @@
+/*
+ * (C) Copyright 2000-2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * CPU specific code for the MPC5xxx CPUs
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <net.h>
+#include <mpc5xxx.h>
+#include <netdev.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <libfdt_env.h>
+#include <fdt_support.h>
+#endif
+
+#if defined(CONFIG_OF_IDE_FIXUP)
+#include <ide.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int checkcpu (void)
+{
+	ulong clock = gd->cpu_clk;
+	char buf[32];
+	uint svr, pvr;
+
+	puts ("CPU:   ");
+
+	svr = get_svr();
+	pvr = get_pvr();
+
+	switch (pvr) {
+	case PVR_5200:
+		printf("MPC5200");
+		break;
+	case PVR_5200B:
+		printf("MPC5200B");
+		break;
+	default:
+		printf("Unknown MPC5xxx");
+		break;
+	}
+
+	printf (" v%d.%d, Core v%d.%d", SVR_MJREV (svr), SVR_MNREV (svr),
+		PVR_MAJ(pvr), PVR_MIN(pvr));
+	printf (" at %s MHz\n", strmhz (buf, clock));
+	return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int
+do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	ulong msr;
+	/* Interrupts and MMU off */
+	__asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
+
+	msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
+	__asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
+
+	/* Charge the watchdog timer */
+	*(vu_long *)(MPC5XXX_GPT0_COUNTER) = 0x0001000f;
+	*(vu_long *)(MPC5XXX_GPT0_ENABLE) = 0x9004; /* wden|ce|timer_ms */
+	while(1);
+
+	return 1;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ *
+ */
+unsigned long get_tbclk (void)
+{
+	ulong tbclk;
+
+	tbclk = (gd->bus_clk + 3L) / 4L;
+
+	return (tbclk);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(CONFIG_OF_LIBFDT) && defined (CONFIG_OF_BOARD_SETUP)
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+	int div = in_8((void*)CONFIG_SYS_MBAR + 0x204) & 0x0020 ? 8 : 4;
+	char * cpu_path = "/cpus/" OF_CPU;
+#ifdef CONFIG_MPC5xxx_FEC
+	uchar enetaddr[6];
+	char * eth_path = "/" OF_SOC "/ethernet@3000";
+#endif
+
+	do_fixup_by_path_u32(blob, cpu_path, "timebase-frequency", OF_TBCLK, 1);
+	do_fixup_by_path_u32(blob, cpu_path, "bus-frequency", bd->bi_busfreq, 1);
+	do_fixup_by_path_u32(blob, cpu_path, "clock-frequency", bd->bi_intfreq, 1);
+	do_fixup_by_path_u32(blob, "/" OF_SOC, "bus-frequency", bd->bi_ipbfreq, 1);
+	do_fixup_by_path_u32(blob, "/" OF_SOC, "system-frequency",
+				bd->bi_busfreq*div, 1);
+#ifdef CONFIG_MPC5xxx_FEC
+	eth_getenv_enetaddr("ethaddr", enetaddr);
+	do_fixup_by_path(blob, eth_path, "mac-address", enetaddr, 6, 0);
+	do_fixup_by_path(blob, eth_path, "local-mac-address", enetaddr, 6, 0);
+#endif
+#if defined(CONFIG_OF_IDE_FIXUP)
+	if (!ide_device_present(0)) {
+		/* NO CF card detected -> delete ata node in DTS */
+		int nodeoffset = 0;
+		char nodename[] = "/soc5200@f0000000/ata@3a00";
+
+		nodeoffset = fdt_path_offset(blob, nodename);
+		if (nodeoffset >= 0) {
+			fdt_del_node(blob, nodeoffset);
+		} else {
+			printf("%s: cannot find %s node err:%s\n",
+				__func__, nodename, fdt_strerror(nodeoffset));
+		}
+	}
+
+#endif
+	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+}
+#endif
+
+#ifdef CONFIG_BOOTCOUNT_LIMIT
+
+void bootcount_store (ulong a)
+{
+	volatile ulong *save_addr = (volatile ulong *) (MPC5XXX_CDM_BRDCRMB);
+
+	*save_addr = (BOOTCOUNT_MAGIC & 0xffff0000) | a;
+}
+
+ulong bootcount_load (void)
+{
+	volatile ulong *save_addr = (volatile ulong *) (MPC5XXX_CDM_BRDCRMB);
+
+	if ((*save_addr & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000))
+		return 0;
+	else
+		return (*save_addr & 0x0000ffff);
+}
+#endif /* CONFIG_BOOTCOUNT_LIMIT */
+
+#ifdef CONFIG_MPC5xxx_FEC
+/* Default initializations for FEC controllers.  To override,
+ * create a board-specific function called:
+ * 	int board_eth_init(bd_t *bis)
+ */
+
+int cpu_eth_init(bd_t *bis)
+{
+	return mpc5xxx_fec_initialize(bis);
+}
+#endif
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset(void)
+{
+	int re_enable = disable_interrupts();
+	reset_5xxx_watchdog();
+	if (re_enable) enable_interrupts();
+}
+
+void reset_5xxx_watchdog(void)
+{
+	volatile struct mpc5xxx_gpt *gpt0 =
+		(struct mpc5xxx_gpt *) MPC5XXX_GPT;
+
+	/* Trigger TIMER_0 by writing A5 to OCPW */
+	clrsetbits_be32(&gpt0->emsr, 0xff000000, 0xa5000000);
+}
+#endif	/* CONFIG_WATCHDOG */
diff --git a/arch/powerpc/cpu/mpc5xxx/cpu_init.c b/arch/powerpc/cpu/mpc5xxx/cpu_init.c
new file mode 100644
index 0000000..9daf375
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/cpu_init.c
@@ -0,0 +1,233 @@
+/*
+ * (C) Copyright 2000-2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc5xxx.h>
+#include <asm/io.h>
+#include <watchdog.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers.
+ */
+void cpu_init_f (void)
+{
+	volatile struct mpc5xxx_mmap_ctl *mm =
+		(struct mpc5xxx_mmap_ctl *) CONFIG_SYS_MBAR;
+	volatile struct mpc5xxx_lpb *lpb =
+		(struct mpc5xxx_lpb *) MPC5XXX_LPB;
+	volatile struct mpc5xxx_gpio *gpio =
+		(struct mpc5xxx_gpio *) MPC5XXX_GPIO;
+	volatile struct mpc5xxx_xlb *xlb =
+		(struct mpc5xxx_xlb *) MPC5XXX_XLBARB;
+#if defined(CONFIG_SYS_IPBCLK_EQUALS_XLBCLK)
+	volatile struct mpc5xxx_cdm *cdm =
+		(struct mpc5xxx_cdm *) MPC5XXX_CDM;
+#endif	/* CONFIG_SYS_IPBCLK_EQUALS_XLBCLK */
+#if defined(CONFIG_WATCHDOG)
+	volatile struct mpc5xxx_gpt *gpt0 =
+		(struct mpc5xxx_gpt *) MPC5XXX_GPT;
+#endif /* CONFIG_WATCHDOG */
+	unsigned long addecr = (1 << 25); /* Boot_CS */
+	/* Pointer is writable since we allocated a register for it */
+	gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+	/* Clear initial global data */
+	memset ((void *) gd, 0, sizeof (gd_t));
+
+	/*
+	 * Memory Controller: configure chip selects and enable them
+	 */
+#if defined(CONFIG_SYS_BOOTCS_START) && defined(CONFIG_SYS_BOOTCS_SIZE)
+	out_be32(&mm->boot_start, START_REG(CONFIG_SYS_BOOTCS_START));
+	out_be32(&mm->boot_stop, STOP_REG(CONFIG_SYS_BOOTCS_START,
+					  CONFIG_SYS_BOOTCS_SIZE));
+#endif
+#if defined(CONFIG_SYS_BOOTCS_CFG)
+	out_be32(&lpb->cs0_cfg, CONFIG_SYS_BOOTCS_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS0_START) && defined(CONFIG_SYS_CS0_SIZE)
+	out_be32(&mm->cs0_start, START_REG(CONFIG_SYS_CS0_START));
+	out_be32(&mm->cs0_stop, STOP_REG(CONFIG_SYS_CS0_START,
+					 CONFIG_SYS_CS0_SIZE));
+	/* CS0 and BOOT_CS cannot be enabled at once. */
+	/*	addecr |= (1 << 16); */
+#endif
+#if defined(CONFIG_SYS_CS0_CFG)
+	out_be32(&lpb->cs0_cfg, CONFIG_SYS_CS0_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS1_START) && defined(CONFIG_SYS_CS1_SIZE)
+	out_be32(&mm->cs1_start, START_REG(CONFIG_SYS_CS1_START));
+	out_be32(&mm->cs1_stop, STOP_REG(CONFIG_SYS_CS1_START,
+					 CONFIG_SYS_CS1_SIZE));
+	addecr |= (1 << 17);
+#endif
+#if defined(CONFIG_SYS_CS1_CFG)
+	out_be32(&lpb->cs1_cfg, CONFIG_SYS_CS1_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS2_START) && defined(CONFIG_SYS_CS2_SIZE)
+	out_be32(&mm->cs2_start, START_REG(CONFIG_SYS_CS2_START));
+	out_be32(&mm->cs2_stop, STOP_REG(CONFIG_SYS_CS2_START,
+					 CONFIG_SYS_CS2_SIZE));
+	addecr |= (1 << 18);
+#endif
+#if defined(CONFIG_SYS_CS2_CFG)
+	out_be32(&lpb->cs2_cfg, CONFIG_SYS_CS2_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS3_START) && defined(CONFIG_SYS_CS3_SIZE)
+	out_be32(&mm->cs3_start, START_REG(CONFIG_SYS_CS3_START));
+	out_be32(&mm->cs3_stop, STOP_REG(CONFIG_SYS_CS3_START,
+					 CONFIG_SYS_CS3_SIZE));
+	addecr |= (1 << 19);
+#endif
+#if defined(CONFIG_SYS_CS3_CFG)
+	out_be32(&lpb->cs3_cfg, CONFIG_SYS_CS3_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS4_START) && defined(CONFIG_SYS_CS4_SIZE)
+	out_be32(&mm->cs4_start, START_REG(CONFIG_SYS_CS4_START));
+	out_be32(&mm->cs4_stop, STOP_REG(CONFIG_SYS_CS4_START,
+					  CONFIG_SYS_CS4_SIZE));
+	addecr |= (1 << 20);
+#endif
+#if defined(CONFIG_SYS_CS4_CFG)
+	out_be32(&lpb->cs4_cfg, CONFIG_SYS_CS4_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS5_START) && defined(CONFIG_SYS_CS5_SIZE)
+	out_be32(&mm->cs5_start, START_REG(CONFIG_SYS_CS5_START));
+	out_be32(&mm->cs5_stop, STOP_REG(CONFIG_SYS_CS5_START,
+					  CONFIG_SYS_CS5_SIZE));
+	addecr |= (1 << 21);
+#endif
+#if defined(CONFIG_SYS_CS5_CFG)
+	out_be32(&lpb->cs5_cfg, CONFIG_SYS_CS5_CFG);
+#endif
+
+	addecr |= 1;
+#if defined(CONFIG_SYS_CS6_START) && defined(CONFIG_SYS_CS6_SIZE)
+	out_be32(&mm->cs6_start, START_REG(CONFIG_SYS_CS6_START));
+	out_be32(&mm->cs6_stop, STOP_REG(CONFIG_SYS_CS6_START,
+					  CONFIG_SYS_CS6_SIZE));
+	addecr |= (1 << 26);
+#endif
+#if defined(CONFIG_SYS_CS6_CFG)
+	out_be32(&lpb->cs6_cfg, CONFIG_SYS_CS6_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS7_START) && defined(CONFIG_SYS_CS7_SIZE)
+	out_be32(&mm->cs7_start, START_REG(CONFIG_SYS_CS7_START));
+	out_be32(&mm->cs7_stop, STOP_REG(CONFIG_SYS_CS7_START,
+					  CONFIG_SYS_CS7_SIZE));
+	addecr |= (1 << 27);
+#endif
+#if defined(CONFIG_SYS_CS7_CFG)
+	out_be32(&lpb->cs7_cfg, CONFIG_SYS_CS7_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS_BURST)
+	out_be32(&lpb->cs_burst, CONFIG_SYS_CS_BURST);
+#endif
+#if defined(CONFIG_SYS_CS_DEADCYCLE)
+	out_be32(&lpb->cs_deadcycle, CONFIG_SYS_CS_DEADCYCLE);
+#endif
+
+	/* Enable chip selects */
+	out_be32(&mm->ipbi_ws_ctrl, addecr);
+	out_be32(&lpb->cs_ctrl, (1 << 24));
+
+	/* Setup pin multiplexing */
+#if defined(CONFIG_SYS_GPS_PORT_CONFIG)
+	out_be32(&gpio->port_config, CONFIG_SYS_GPS_PORT_CONFIG);
+#endif
+
+	/* enable timebase */
+	setbits_be32(&xlb->config, (1 << 13));
+
+	/* Enable snooping for RAM */
+	setbits_be32(&xlb->config, (1 << 15));
+	out_be32(&xlb->snoop_window, CONFIG_SYS_SDRAM_BASE | 0x1d);
+
+#if defined(CONFIG_SYS_IPBCLK_EQUALS_XLBCLK)
+	/* Motorola reports IPB should better run at 133 MHz. */
+	setbits_be32(&mm->ipbi_ws_ctrl, 1);
+	/* pci_clk_sel = 0x02, ipb_clk_sel = 0x00; */
+	addecr = in_be32(&cdm->cfg);
+	addecr &= ~0x103;
+# if defined(CONFIG_SYS_PCICLK_EQUALS_IPBCLK_DIV2)
+	/* pci_clk_sel = 0x01 -> IPB_CLK/2 */
+	addecr |= 0x01;
+# else
+	/* pci_clk_sel = 0x02 -> XLB_CLK/4 = IPB_CLK/4 */
+	addecr |= 0x02;
+# endif /* CONFIG_SYS_PCICLK_EQUALS_IPBCLK_DIV2 */
+	out_be32(&cdm->cfg, addecr);
+#endif	/* CONFIG_SYS_IPBCLK_EQUALS_XLBCLK */
+	/* Configure the XLB Arbiter */
+	out_be32(&xlb->master_pri_enable, 0xff);
+	out_be32(&xlb->master_priority, 0x11111111);
+
+#if defined(CONFIG_SYS_XLB_PIPELINING)
+	/* Enable piplining */
+	clrbits_be32(&xlb->config, (1 << 31));
+#endif
+
+#if defined(CONFIG_WATCHDOG)
+	/* Charge the watchdog timer - prescaler = 64k, count = 64k*/
+	out_be32(&gpt0->cir, 0x0000ffff);
+	out_be32(&gpt0->emsr, 0x9004);	/* wden|ce|timer_ms */
+
+	reset_5xxx_watchdog();
+#endif /* CONFIG_WATCHDOG */
+}
+
+/*
+ * initialize higher level parts of CPU like time base and timers
+ */
+int cpu_init_r (void)
+{
+	volatile struct mpc5xxx_intr *intr =
+		(struct mpc5xxx_intr *) MPC5XXX_ICTL;
+
+	/* mask all interrupts */
+	out_be32(&intr->per_mask, 0xffffff00);
+	setbits_be32(&intr->main_mask, 0x0001ffff);
+	clrbits_be32(&intr->ctrl, 0x00000f00);
+	/* route critical ints to normal ints */
+	setbits_be32(&intr->ctrl, 0x00000001);
+
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_MPC5xxx_FEC)
+	/* load FEC microcode */
+	loadtask(0, 2);
+#endif
+
+	return (0);
+}
diff --git a/arch/powerpc/cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S b/arch/powerpc/cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S
new file mode 100644
index 0000000..00c2312
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2001, Software Center, Motorola China.
+ *
+ * This file contains microcode for the FEC controller of the MPC5200 CPU.
+ */
+
+#include <config.h>
+
+/* sas/sccg, gas target */
+.section        smartdmaInitData,"aw",@progbits	/* Initialized data for task variables */
+.section        smartdmaTaskTable,"aw",@progbits	/* Task tables */
+.align  9
+.globl taskTable
+taskTable:
+.globl scEthernetRecv_Entry
+scEthernetRecv_Entry:		/* Task 0 */
+.long   scEthernetRecv_TDT - taskTable	/* Task 0 Descriptor Table */
+.long   scEthernetRecv_TDT - taskTable + 0x000000a4
+.long   scEthernetRecv_VarTab - taskTable	/* Task 0 Variable Table */
+.long   scEthernetRecv_FDT - taskTable + 0x03	/* Task 0 Function Descriptor Table & Flags */
+.long   0x00000000
+.long   0x00000000
+.long   scEthernetRecv_CSave - taskTable	/* Task 0 context save space */
+.long   CONFIG_SYS_MBAR
+.globl scEthernetXmit_Entry
+scEthernetXmit_Entry:		/* Task 1 */
+.long   scEthernetXmit_TDT - taskTable	/* Task 1 Descriptor Table */
+.long   scEthernetXmit_TDT - taskTable + 0x000000d0
+.long   scEthernetXmit_VarTab - taskTable	/* Task 1 Variable Table */
+.long   scEthernetXmit_FDT - taskTable + 0x03	/* Task 1 Function Descriptor Table & Flags */
+.long   0x00000000
+.long   0x00000000
+.long   scEthernetXmit_CSave - taskTable	/* Task 1 context save space */
+.long   CONFIG_SYS_MBAR
+
+
+.globl scEthernetRecv_TDT
+scEthernetRecv_TDT:	/* Task 0 Descriptor Table */
+.long   0xc4c50000	/* 0000:  LCDEXT: idx0 = var9 + var10; idx0 once var0; idx0 += inc0 */
+.long   0x84c5e000	/* 0004:  LCD: idx1 = var9 + var11; ; idx1 += inc0 */
+.long   0x10001f08	/* 0008:    DRD1A: var7 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x10000380	/* 000C:    DRD1A: var0 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x00000f88	/* 0010:    DRD1A: var3 = *idx1; FN=0 init=0 WS=0 RS=0 */
+.long   0x81980000	/* 0014:  LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
+.long   0x10000780	/* 0018:    DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x60000000	/* 001C:    DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long   0x010cf04c	/* 0020:    DRD2B1: var4 = EU3(); EU3(var1,var12)  */
+.long   0x82180349	/* 0024:  LCD: idx0 = var4; idx0 != var13; idx0 += inc1 */
+.long   0x81c68004	/* 0028:    LCD: idx1 = var3 + var13 + 4; idx1 once var0; idx1 += inc0 */
+.long   0x70000000	/* 002C:      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long   0x018cf04e	/* 0030:      DRD2B1: var6 = EU3(); EU3(var1,var14)  */
+.long   0x70000000	/* 0034:      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long   0x020cf04f	/* 0038:      DRD2B1: var8 = EU3(); EU3(var1,var15)  */
+.long   0x00000b88	/* 003C:      DRD1A: var2 = *idx1; FN=0 init=0 WS=0 RS=0 */
+.long   0x8000d184	/* 0040:    LCDEXT: idx1 = 0xf0003184; ; */
+.long   0xc6990452	/* 0044:    LCDEXT: idx2 = var13; idx2 < var17; idx2 += inc2 */
+.long   0x81486010	/* 0048:    LCD: idx3 = var2 + var16; ; idx3 += inc2 */
+.long   0x006acf88	/* 004C:      DRD1A: *idx3 = *idx1; FN=0 init=3 WS=1 RS=1 */
+.long   0x8000d184	/* 0050:    LCDEXT: idx1 = 0xf0003184; ; */
+.long   0x86810492	/* 0054:    LCD: idx2 = var13, idx3 = var2; idx2 < var18; idx2 += inc2, idx3 += inc2 */
+.long   0x006acf88	/* 0058:      DRD1A: *idx3 = *idx1; FN=0 init=3 WS=1 RS=1 */
+.long   0x8000d184	/* 005C:    LCDEXT: idx1 = 0xf0003184; ; */
+.long   0x868184d2	/* 0060:    LCD: idx2 = var13, idx3 = var3; idx2 < var19; idx2 += inc2, idx3 += inc2 */
+.long   0x000acf88	/* 0064:      DRD1A: *idx3 = *idx1; FN=0 init=0 WS=1 RS=1 */
+.long   0xc318839b	/* 0068:    LCDEXT: idx1 = var6; idx1 == var14; idx1 += inc3 */
+.long   0x80190000	/* 006C:    LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
+.long   0x04008468	/* 0070:      DRD1A: idx1 = var13; FN=0 INT init=0 WS=0 RS=0 */
+.long   0xc4038358	/* 0074:    LCDEXT: idx1 = var8, idx2 = var7; idx1 == var13; idx1 += inc3, idx2 += inc0 */
+.long   0x81c50000	/* 0078:    LCD: idx3 = var3 + var10; idx3 once var0; idx3 += inc0 */
+.long   0x1000cb18	/* 007C:      DRD1A: *idx2 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x00000f18	/* 0080:      DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
+.long   0xc4188364	/* 0084:    LCDEXT: idx1 = var8; idx1 > var13; idx1 += inc4 */
+.long   0x83990000	/* 0088:    LCD: idx2 = var7; idx2 once var0; idx2 += inc0 */
+.long   0x10000c00	/* 008C:      DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x0000c800	/* 0090:      DRD1A: *idx2 = var0; FN=0 init=0 WS=0 RS=0 */
+.long   0x81988000	/* 0094:    LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long   0x10000788	/* 0098:      DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x60000000	/* 009C:      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long   0x080cf04c	/* 00A0:      DRD2B1: idx0 = EU3(); EU3(var1,var12)  */
+.long   0x000001f8	/* 00A4(:0):    NOP */
+
+
+.globl scEthernetXmit_TDT
+scEthernetXmit_TDT:	/* Task 1 Descriptor Table */
+.long   0x80024800	/* 0000:  LCDEXT: idx0 = 0xf0008800; ; */
+.long   0x85c60004	/* 0004:  LCD: idx1 = var11 + var12 + 4; idx1 once var0; idx1 += inc0 */
+.long   0x10002308	/* 0008:    DRD1A: var8 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x10000f88	/* 000C:    DRD1A: var3 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x00000380	/* 0010:    DRD1A: var0 = *idx0; FN=0 init=0 WS=0 RS=0 */
+.long   0x81980000	/* 0014:  LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
+.long   0x10000780	/* 0018:    DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x60000000	/* 001C:    DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long   0x024cf04d	/* 0020:    DRD2B1: var9 = EU3(); EU3(var1,var13)  */
+.long   0x84980309	/* 0024:  LCD: idx0 = var9; idx0 != var12; idx0 += inc1 */
+.long   0xc0004003	/* 0028:    LCDEXT: idx1 = 0x00000003; ; */
+.long   0x81c60004	/* 002C:    LCD: idx2 = var3 + var12 + 4; idx2 once var0; idx2 += inc0 */
+.long   0x70000000	/* 0030:      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long   0x010cf04e	/* 0034:      DRD2B1: var4 = EU3(); EU3(var1,var14)  */
+.long   0x70000000	/* 0038:      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long   0x014cf04f	/* 003C:      DRD2B1: var5 = EU3(); EU3(var1,var15)  */
+.long   0x70000000	/* 0040:      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long   0x028cf050	/* 0044:      DRD2B1: var10 = EU3(); EU3(var1,var16)  */
+.long   0x70000000	/* 0048:      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long   0x018cf051	/* 004C:      DRD2B1: var6 = EU3(); EU3(var1,var17)  */
+.long   0x10000b90	/* 0050:      DRD1A: var2 = *idx2; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x60000000	/* 0054:      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long   0x01ccf0a1	/* 0058:      DRD2B1: var7 = EU3(); EU3(var2,idx1)  */
+.long   0xc2988312	/* 005C:    LCDEXT: idx1 = var5; idx1 > var12; idx1 += inc2 */
+.long   0x83490000	/* 0060:    LCD: idx2 = var6 + var18; idx2 once var0; idx2 += inc0 */
+.long   0x00001b10	/* 0064:      DRD1A: var6 = idx2; FN=0 init=0 WS=0 RS=0 */
+.long   0x8000d1a4	/* 0068:    LCDEXT: idx1 = 0xf00031a4; ; */
+.long   0x8301031c	/* 006C:    LCD: idx2 = var6, idx3 = var2; idx2 > var12; idx2 += inc3, idx3 += inc4 */
+.long   0x008ac798	/* 0070:      DRD1A: *idx1 = *idx3; FN=0 init=4 WS=1 RS=1 */
+.long   0x8000d1a4	/* 0074:    LCDEXT: idx1 = 0xf00031a4; ; */
+.long   0xc1430000	/* 0078:    LCDEXT: idx2 = var2 + var6; idx2 once var0; idx2 += inc0 */
+.long   0x82998312	/* 007C:    LCD: idx3 = var5; idx3 > var12; idx3 += inc2 */
+.long   0x088ac790	/* 0080:      DRD1A: *idx1 = *idx2; FN=0 TFD init=4 WS=1 RS=1 */
+.long   0x81988000	/* 0084:    LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long   0x60000001	/* 0088:      DRD2A: EU0=0 EU1=0 EU2=0 EU3=1 EXT init=0 WS=0 RS=0 */
+.long   0x0c4cfc4d	/* 008C:      DRD2B1: *idx1 = EU3(); EU3(*idx1,var13)  */
+.long   0xc21883ad	/* 0090:    LCDEXT: idx1 = var4; idx1 == var14; idx1 += inc5 */
+.long   0x80190000	/* 0094:    LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
+.long   0x04008460	/* 0098:      DRD1A: idx1 = var12; FN=0 INT init=0 WS=0 RS=0 */
+.long   0xc4052305	/* 009C:    LCDEXT: idx1 = var8, idx2 = var10; idx2 == var12; idx1 += inc0, idx2 += inc5 */
+.long   0x81c98000	/* 00A0:    LCD: idx3 = var3 + var19; idx3 once var0; idx3 += inc0 */
+.long   0x1000c718	/* 00A4:      DRD1A: *idx1 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x00000f18	/* 00A8:      DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
+.long   0xc4188000	/* 00AC:    LCDEXT: idx1 = var8; idx1 once var0; idx1 += inc0 */
+.long   0x85190312	/* 00B0:    LCD: idx2 = var10; idx2 > var12; idx2 += inc2 */
+.long   0x10000c00	/* 00B4:      DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x1000c400	/* 00B8:      DRD1A: *idx1 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x00008860	/* 00BC:      DRD1A: idx2 = var12; FN=0 init=0 WS=0 RS=0 */
+.long   0x81988000	/* 00C0:    LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long   0x10000788	/* 00C4:      DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x60000000	/* 00C8:      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long   0x080cf04d	/* 00CC:      DRD2B1: idx0 = EU3(); EU3(var1,var13)  */
+.long   0x000001f8	/* 00D0(:0):    NOP */
+
+.align  8
+
+.globl scEthernetRecv_VarTab
+scEthernetRecv_VarTab:	/* Task 0 Variable Table */
+.long   0x00000000	/* var[0] */
+.long   0x00000000	/* var[1] */
+.long   0x00000000	/* var[2] */
+.long   0x00000000	/* var[3] */
+.long   0x00000000	/* var[4] */
+.long   0x00000000	/* var[5] */
+.long   0x00000000	/* var[6] */
+.long   0x00000000	/* var[7] */
+.long   0x00000000	/* var[8] */
+.long   (CONFIG_SYS_MBAR + 0x8800)	/* var[9] */
+.long   0x00000008	/* var[10] */
+.long   0x0000000c	/* var[11] */
+.long   0x80000000	/* var[12] */
+.long   0x00000000	/* var[13] */
+.long   0x10000000	/* var[14] */
+.long   0x20000000	/* var[15] */
+.long   0x000005e4	/* var[16] */
+.long   0x0000000e	/* var[17] */
+.long   0x000005e0	/* var[18] */
+.long   0x00000004	/* var[19] */
+.long   0x00000000	/* var[20] */
+.long   0x00000000	/* var[21] */
+.long   0x00000000	/* var[22] */
+.long   0x00000000	/* var[23] */
+.long   0x00000000	/* inc[0] */
+.long   0x60000000	/* inc[1] */
+.long   0x20000001	/* inc[2] */
+.long   0x80000000	/* inc[3] */
+.long   0x40000000	/* inc[4] */
+.long   0x00000000	/* inc[5] */
+.long   0x00000000	/* inc[6] */
+.long   0x00000000	/* inc[7] */
+
+.align  8
+
+.globl scEthernetXmit_VarTab
+scEthernetXmit_VarTab:	/* Task 1 Variable Table */
+.long   0x00000000	/* var[0] */
+.long   0x00000000	/* var[1] */
+.long   0x00000000	/* var[2] */
+.long   0x00000000	/* var[3] */
+.long   0x00000000	/* var[4] */
+.long   0x00000000	/* var[5] */
+.long   0x00000000	/* var[6] */
+.long   0x00000000	/* var[7] */
+.long   0x00000000	/* var[8] */
+.long   0x00000000	/* var[9] */
+.long   0x00000000	/* var[10] */
+.long   (CONFIG_SYS_MBAR + 0x8800)	/* var[11] */
+.long   0x00000000	/* var[12] */
+.long   0x80000000	/* var[13] */
+.long   0x10000000	/* var[14] */
+.long   0x08000000	/* var[15] */
+.long   0x20000000	/* var[16] */
+.long   0x0000ffff	/* var[17] */
+.long   0xffffffff	/* var[18] */
+.long   0x00000008	/* var[19] */
+.long   0x00000000	/* var[20] */
+.long   0x00000000	/* var[21] */
+.long   0x00000000	/* var[22] */
+.long   0x00000000	/* var[23] */
+.long   0x00000000	/* inc[0] */
+.long   0x60000000	/* inc[1] */
+.long   0x40000000	/* inc[2] */
+.long   0x4000ffff	/* inc[3] */
+.long   0xe0000001	/* inc[4] */
+.long   0x80000000	/* inc[5] */
+.long   0x00000000	/* inc[6] */
+.long   0x00000000	/* inc[7] */
+
+.align  8
+
+.globl scEthernetRecv_FDT
+scEthernetRecv_FDT:	/* Task 0 Function Descriptor Table */
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x21800000	/* and(), EU# 3 */
+.long   0x21400000	/* andn(), EU# 3 */
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+
+.align  8
+
+.globl scEthernetXmit_FDT
+scEthernetXmit_FDT:	/* Task 1 Function Descriptor Table */
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x21800000	/* and(), EU# 3 */
+.long   0x21400000	/* andn(), EU# 3 */
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+
+
+.globl scEthernetRecv_CSave
+scEthernetRecv_CSave:	/* Task 0 context save space */
+.space  128, 0x0
+
+
+.globl scEthernetXmit_CSave
+scEthernetXmit_CSave:	/* Task 1 context save space */
+.space  128, 0x0
diff --git a/arch/powerpc/cpu/mpc5xxx/i2c.c b/arch/powerpc/cpu/mpc5xxx/i2c.c
new file mode 100644
index 0000000..4f7f716
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/i2c.c
@@ -0,0 +1,442 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_HARD_I2C
+
+#include <mpc5xxx.h>
+#include <i2c.h>
+
+#if (CONFIG_SYS_I2C_MODULE == 2)
+#define I2C_BASE	MPC5XXX_I2C2
+#elif (CONFIG_SYS_I2C_MODULE == 1)
+#define I2C_BASE	MPC5XXX_I2C1
+#else
+#error CONFIG_SYS_I2C_MODULE is not properly configured
+#endif
+
+#define I2C_TIMEOUT	6667
+#define I2C_RETRIES	3
+
+struct mpc5xxx_i2c_tap {
+	int scl2tap;
+	int tap2tap;
+};
+
+static int  mpc_reg_in    (volatile u32 *reg);
+static void mpc_reg_out   (volatile u32 *reg, int val, int mask);
+static int  wait_for_bb   (void);
+static int  wait_for_pin  (int *status);
+static int  do_address    (uchar chip, char rdwr_flag);
+static int  send_bytes    (uchar chip, char *buf, int len);
+static int  receive_bytes (uchar chip, char *buf, int len);
+static int  mpc_get_fdr   (int);
+
+static int mpc_reg_in(volatile u32 *reg)
+{
+	int ret = *reg >> 24;
+	__asm__ __volatile__ ("eieio");
+	return ret;
+}
+
+static void mpc_reg_out(volatile u32 *reg, int val, int mask)
+{
+	int tmp;
+
+	if (!mask) {
+		*reg = val << 24;
+	} else {
+		tmp = mpc_reg_in(reg);
+		*reg = ((tmp & ~mask) | (val & mask)) << 24;
+	}
+	__asm__ __volatile__ ("eieio");
+
+	return;
+}
+
+static int wait_for_bb(void)
+{
+	struct mpc5xxx_i2c *regs    = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                 timeout = I2C_TIMEOUT;
+	int                 status;
+
+	status = mpc_reg_in(&regs->msr);
+
+	while (timeout-- && (status & I2C_BB)) {
+#if 1
+		volatile int temp;
+		mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+		temp = mpc_reg_in(&regs->mdr);
+		mpc_reg_out(&regs->mcr, 0, I2C_STA);
+		mpc_reg_out(&regs->mcr, 0, 0);
+		mpc_reg_out(&regs->mcr, I2C_EN, 0);
+#endif
+		udelay(15);
+		status = mpc_reg_in(&regs->msr);
+	}
+
+	return (status & I2C_BB);
+}
+
+static int wait_for_pin(int *status)
+{
+	struct mpc5xxx_i2c *regs    = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                 timeout = I2C_TIMEOUT;
+
+	*status = mpc_reg_in(&regs->msr);
+
+	while (timeout-- && !(*status & I2C_IF)) {
+		udelay(15);
+		*status = mpc_reg_in(&regs->msr);
+	}
+
+	if (!(*status & I2C_IF)) {
+		return -1;
+	}
+
+	mpc_reg_out(&regs->msr, 0, I2C_IF);
+
+	return 0;
+}
+
+static int do_address(uchar chip, char rdwr_flag)
+{
+	struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                 status;
+
+	chip <<= 1;
+
+	if (rdwr_flag) {
+		chip |= 1;
+	}
+
+	mpc_reg_out(&regs->mcr, I2C_TX, I2C_TX);
+	mpc_reg_out(&regs->mdr, chip, 0);
+
+	if (wait_for_pin(&status)) {
+		return -2;
+	}
+
+	if (status & I2C_RXAK) {
+		return -3;
+	}
+
+	return 0;
+}
+
+static int send_bytes(uchar chip, char *buf, int len)
+{
+	struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                 wrcount;
+	int                 status;
+
+	for (wrcount = 0; wrcount < len; ++wrcount) {
+
+		mpc_reg_out(&regs->mdr, buf[wrcount], 0);
+
+		if (wait_for_pin(&status)) {
+			break;
+		}
+
+		if (status & I2C_RXAK) {
+			break;
+		}
+
+	}
+
+	return !(wrcount == len);
+}
+
+static int receive_bytes(uchar chip, char *buf, int len)
+{
+	struct mpc5xxx_i2c *regs    = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                 dummy   = 1;
+	int                 rdcount = 0;
+	int                 status;
+	int                 i;
+
+	mpc_reg_out(&regs->mcr, 0, I2C_TX);
+
+	for (i = 0; i < len; ++i) {
+		buf[rdcount] = mpc_reg_in(&regs->mdr);
+
+		if (dummy) {
+			dummy = 0;
+		} else {
+			rdcount++;
+		}
+
+
+		if (wait_for_pin(&status)) {
+			return -4;
+		}
+	}
+
+	mpc_reg_out(&regs->mcr, I2C_TXAK, I2C_TXAK);
+	buf[rdcount++] = mpc_reg_in(&regs->mdr);
+
+	if (wait_for_pin(&status)) {
+		return -5;
+	}
+
+	mpc_reg_out(&regs->mcr, 0, I2C_TXAK);
+
+	return 0;
+}
+
+#if defined(CONFIG_SYS_I2C_INIT_MPC5XXX)
+
+#define FDR510(x) (u8) (((x & 0x20) >> 3) | (x & 0x3))
+#define FDR432(x) (u8) ((x & 0x1C) >> 2)
+/*
+ * Reset any i2c devices that may have been interrupted during a system reset.
+ * Normally this would be accomplished by clocking the line until SCL and SDA
+ * are released and then sending a start condtiion (From an Atmel datasheet).
+ * There is no direct access to the i2c pins so instead create start commands
+ * through the i2c interface.  Send a start command then delay for the SDA Hold
+ * time, repeat this by disabling/enabling the bus a total of 9 times.
+ */
+static void send_reset(void)
+{
+	struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+	int i;
+	u32 delay;
+	u8 fdr;
+	int SDA_Tap[] = { 3, 3, 4, 4, 1, 1, 2, 2};
+	struct mpc5xxx_i2c_tap scltap[] = {
+		{4, 1},
+		{4, 2},
+		{6, 4},
+		{6, 8},
+		{14, 16},
+		{30, 32},
+		{62, 64},
+		{126, 128}
+	};
+
+	fdr = (u8)mpc_reg_in(&regs->mfdr);
+
+	delay = scltap[FDR432(fdr)].scl2tap + ((SDA_Tap[FDR510(fdr)] - 1) * \
+		scltap[FDR432(fdr)].tap2tap) + 3;
+
+	for (i = 0; i < 9; i++) {
+		mpc_reg_out(&regs->mcr, I2C_EN|I2C_STA|I2C_TX, I2C_INIT_MASK);
+		udelay(delay);
+		mpc_reg_out(&regs->mcr, 0, I2C_INIT_MASK);
+		udelay(delay);
+	}
+
+	mpc_reg_out(&regs->mcr, I2C_EN, I2C_INIT_MASK);
+}
+#endif /* CONFIG_SYS_I2c_INIT_MPC5XXX */
+
+/**************** I2C API ****************/
+
+void i2c_init(int speed, int saddr)
+{
+	struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+
+	mpc_reg_out(&regs->mcr, 0, 0);
+	mpc_reg_out(&regs->madr, saddr << 1, 0);
+
+	/* Set clock
+	 */
+	mpc_reg_out(&regs->mfdr, mpc_get_fdr(speed), 0);
+
+	/* Enable module
+	 */
+	mpc_reg_out(&regs->mcr, I2C_EN, I2C_INIT_MASK);
+	mpc_reg_out(&regs->msr, 0, I2C_IF);
+
+#if defined(CONFIG_SYS_I2C_INIT_MPC5XXX)
+	send_reset();
+#endif
+	return;
+}
+
+static int mpc_get_fdr(int speed)
+{
+	static int fdr = -1;
+
+	if (fdr == -1) {
+		ulong best_speed = 0;
+		ulong divider;
+		ulong ipb, scl;
+		ulong bestmatch = 0xffffffffUL;
+		int best_i = 0, best_j = 0, i, j;
+		int SCL_Tap[] = { 9, 10, 12, 15, 5, 6, 7, 8};
+		struct mpc5xxx_i2c_tap scltap[] = {
+			{4, 1},
+			{4, 2},
+			{6, 4},
+			{6, 8},
+			{14, 16},
+			{30, 32},
+			{62, 64},
+			{126, 128}
+		};
+
+		ipb = gd->ipb_clk;
+		for (i = 7; i >= 0; i--) {
+			for (j = 7; j >= 0; j--) {
+				scl = 2 * (scltap[j].scl2tap +
+					(SCL_Tap[i] - 1) * scltap[j].tap2tap + 2);
+				if (ipb <= speed*scl) {
+					if ((speed*scl - ipb) < bestmatch) {
+						bestmatch = speed*scl - ipb;
+						best_i = i;
+						best_j = j;
+						best_speed = ipb/scl;
+					}
+				}
+			}
+		}
+		divider = (best_i & 3) | ((best_i & 4) << 3) | (best_j << 2);
+		if (gd->flags & GD_FLG_RELOC) {
+			fdr = divider;
+		} else {
+			if (gd->have_console)
+				printf("%ld kHz, ", best_speed / 1000);
+			return divider;
+		}
+	}
+
+	return fdr;
+}
+
+int i2c_probe(uchar chip)
+{
+	struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                 i;
+
+	for (i = 0; i < I2C_RETRIES; i++) {
+		mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+
+		if (! do_address(chip, 0)) {
+			mpc_reg_out(&regs->mcr, 0, I2C_STA);
+			udelay(500);
+			break;
+		}
+
+		mpc_reg_out(&regs->mcr, 0, I2C_STA);
+		udelay(500);
+	}
+
+	return (i == I2C_RETRIES);
+}
+
+int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+	char                xaddr[4];
+	struct mpc5xxx_i2c * regs        = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                  ret         = -1;
+
+	xaddr[0] = (addr >> 24) & 0xFF;
+	xaddr[1] = (addr >> 16) & 0xFF;
+	xaddr[2] = (addr >>  8) & 0xFF;
+	xaddr[3] =  addr	& 0xFF;
+
+	if (wait_for_bb()) {
+		if (gd->have_console)
+			printf("i2c_read: bus is busy\n");
+		goto Done;
+	}
+
+	mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+	if (do_address(chip, 0)) {
+		if (gd->have_console)
+			printf("i2c_read: failed to address chip\n");
+		goto Done;
+	}
+
+	if (send_bytes(chip, &xaddr[4-alen], alen)) {
+		if (gd->have_console)
+			printf("i2c_read: send_bytes failed\n");
+		goto Done;
+	}
+
+	mpc_reg_out(&regs->mcr, I2C_RSTA, I2C_RSTA);
+	if (do_address(chip, 1)) {
+		if (gd->have_console)
+			printf("i2c_read: failed to address chip\n");
+		goto Done;
+	}
+
+	if (receive_bytes(chip, (char *)buf, len)) {
+		if (gd->have_console)
+			printf("i2c_read: receive_bytes failed\n");
+		goto Done;
+	}
+
+	ret = 0;
+Done:
+	mpc_reg_out(&regs->mcr, 0, I2C_STA);
+	return ret;
+}
+
+int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+	char               xaddr[4];
+	struct mpc5xxx_i2c *regs        = (struct mpc5xxx_i2c *)I2C_BASE;
+	int                 ret         = -1;
+
+	xaddr[0] = (addr >> 24) & 0xFF;
+	xaddr[1] = (addr >> 16) & 0xFF;
+	xaddr[2] = (addr >>  8) & 0xFF;
+	xaddr[3] =  addr	& 0xFF;
+
+	if (wait_for_bb()) {
+		if (gd->have_console)
+			printf("i2c_write: bus is busy\n");
+		goto Done;
+	}
+
+	mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+	if (do_address(chip, 0)) {
+		if (gd->have_console)
+			printf("i2c_write: failed to address chip\n");
+		goto Done;
+	}
+
+	if (send_bytes(chip, &xaddr[4-alen], alen)) {
+		if (gd->have_console)
+			printf("i2c_write: send_bytes failed\n");
+		goto Done;
+	}
+
+	if (send_bytes(chip, (char *)buf, len)) {
+		if (gd->have_console)
+			printf("i2c_write: send_bytes failed\n");
+		goto Done;
+	}
+
+	ret = 0;
+Done:
+	mpc_reg_out(&regs->mcr, 0, I2C_STA);
+	return ret;
+}
+
+#endif	/* CONFIG_HARD_I2C */
diff --git a/arch/powerpc/cpu/mpc5xxx/ide.c b/arch/powerpc/cpu/mpc5xxx/ide.c
new file mode 100644
index 0000000..d337abb
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/ide.c
@@ -0,0 +1,99 @@
+/*
+ * (C) Copyright 2004
+ * Pierre AUBERT, Staubli Faverges, <p.aubert@staubli.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Init is derived from Linux code.
+ */
+#include <common.h>
+
+#if defined(CONFIG_CMD_IDE)
+#include <mpc5xxx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define CALC_TIMING(t) (t + period - 1) / period
+
+#ifdef CONFIG_IDE_RESET
+extern void init_ide_reset (void);
+#endif
+
+int ide_preinit (void)
+{
+	long period, t0, t1, t2_8, t2_16, t4, ta;
+	vu_long reg;
+	struct mpc5xxx_sdma *psdma = (struct mpc5xxx_sdma *) MPC5XXX_SDMA;
+
+	reg = *(vu_long *) MPC5XXX_GPS_PORT_CONFIG;
+#if defined(CONFIG_SYS_ATA_CS_ON_I2C2)
+	/* ATA cs0/1 on i2c2 clk/io */
+	reg = (reg & ~0x03000000ul) | 0x02000000ul;
+#elif defined(CONFIG_SYS_ATA_CS_ON_TIMER01)
+	/* ATA cs0/1 on Timer 0/1 */
+	reg = (reg & ~0x03000000ul) | 0x03000000ul;
+#else
+	/* ATA cs0/1 on Local Plus cs4/5 */
+	reg = (reg & ~0x03000000ul) | 0x01000000ul;
+#endif	/* CONFIG_TOTAL5200 */
+	*(vu_long *) MPC5XXX_GPS_PORT_CONFIG = reg;
+
+	/* All sample codes do that... */
+	*(vu_long *) MPC5XXX_ATA_SHARE_COUNT = 0;
+
+#if defined(CONFIG_UC101)
+	/* Configure and reset host */
+	*(vu_long *) MPC5XXX_ATA_HOST_CONFIG =
+		MPC5xxx_ATA_HOSTCONF_SMR | MPC5xxx_ATA_HOSTCONF_FR;
+	udelay (10);
+	*(vu_long *) MPC5XXX_ATA_HOST_CONFIG = 0;
+#else
+	/* Configure and reset host */
+	*(vu_long *) MPC5XXX_ATA_HOST_CONFIG = MPC5xxx_ATA_HOSTCONF_IORDY |
+		MPC5xxx_ATA_HOSTCONF_SMR | MPC5xxx_ATA_HOSTCONF_FR;
+	udelay (10);
+	*(vu_long *) MPC5XXX_ATA_HOST_CONFIG = MPC5xxx_ATA_HOSTCONF_IORDY;
+#endif
+
+	/* Disable prefetch on Commbus */
+	psdma->PtdCntrl |= 1;
+
+	/* Init timings : we use PIO mode 0 timings */
+	period = 1000000000 / gd->ipb_clk;	/* period in ns */
+
+	t0 = CALC_TIMING (600);
+	t2_8 = CALC_TIMING (290);
+	t2_16 = CALC_TIMING (165);
+	reg = (t0 << 24) | (t2_8 << 16) | (t2_16 << 8);
+	*(vu_long *) MPC5XXX_ATA_PIO1 = reg;
+
+	t4 = CALC_TIMING (30);
+	t1 = CALC_TIMING (70);
+	ta = CALC_TIMING (35);
+	reg = (t4 << 24) | (t1 << 16) | (ta << 8);
+
+	*(vu_long *) MPC5XXX_ATA_PIO2 = reg;
+
+#ifdef CONFIG_IDE_RESET
+	init_ide_reset ();
+#endif /* CONFIG_IDE_RESET */
+
+	return (0);
+}
+#endif
diff --git a/arch/powerpc/cpu/mpc5xxx/interrupts.c b/arch/powerpc/cpu/mpc5xxx/interrupts.c
new file mode 100644
index 0000000..16eee3a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/interrupts.c
@@ -0,0 +1,346 @@
+/*
+ * (C) Copyright 2006
+ * Detlev Zundel, DENX Software Engineering, dzu@denx.de
+ *
+ * (C) Copyright -2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* this section was ripped out of arch/powerpc/syslib/mpc52xx_pic.c in the
+ * Linux 2.6 source with the following copyright.
+ *
+ * Based on (well, mostly copied from) the code from the 2.4 kernel by
+ * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
+ *
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Montavista Software, Inc
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <command.h>
+
+struct irq_action {
+	interrupt_handler_t *handler;
+	void *arg;
+	ulong count;
+};
+
+static struct irq_action irq_handlers[NR_IRQS];
+
+static struct mpc5xxx_intr *intr;
+static struct mpc5xxx_sdma *sdma;
+
+static void mpc5xxx_ic_disable(unsigned int irq)
+{
+	u32 val;
+
+	if (irq == MPC5XXX_IRQ0) {
+		val = in_be32(&intr->ctrl);
+		val &= ~(1 << 11);
+		out_be32(&intr->ctrl, val);
+	} else if (irq < MPC5XXX_IRQ1) {
+		BUG();
+	} else if (irq <= MPC5XXX_IRQ3) {
+		val = in_be32(&intr->ctrl);
+		val &= ~(1 << (10 - (irq - MPC5XXX_IRQ1)));
+		out_be32(&intr->ctrl, val);
+	} else if (irq < MPC5XXX_SDMA_IRQ_BASE) {
+		val = in_be32(&intr->main_mask);
+		val |= 1 << (16 - (irq - MPC5XXX_MAIN_IRQ_BASE));
+		out_be32(&intr->main_mask, val);
+	} else if (irq < MPC5XXX_PERP_IRQ_BASE) {
+		val = in_be32(&sdma->IntMask);
+		val |= 1 << (irq - MPC5XXX_SDMA_IRQ_BASE);
+		out_be32(&sdma->IntMask, val);
+	} else {
+		val = in_be32(&intr->per_mask);
+		val |= 1 << (31 - (irq - MPC5XXX_PERP_IRQ_BASE));
+		out_be32(&intr->per_mask, val);
+	}
+}
+
+static void mpc5xxx_ic_enable(unsigned int irq)
+{
+	u32 val;
+
+	if (irq == MPC5XXX_IRQ0) {
+		val = in_be32(&intr->ctrl);
+		val |= 1 << 11;
+		out_be32(&intr->ctrl, val);
+	} else if (irq < MPC5XXX_IRQ1) {
+		BUG();
+	} else if (irq <= MPC5XXX_IRQ3) {
+		val = in_be32(&intr->ctrl);
+		val |= 1 << (10 - (irq - MPC5XXX_IRQ1));
+		out_be32(&intr->ctrl, val);
+	} else if (irq < MPC5XXX_SDMA_IRQ_BASE) {
+		val = in_be32(&intr->main_mask);
+		val &= ~(1 << (16 - (irq - MPC5XXX_MAIN_IRQ_BASE)));
+		out_be32(&intr->main_mask, val);
+	} else if (irq < MPC5XXX_PERP_IRQ_BASE) {
+		val = in_be32(&sdma->IntMask);
+		val &= ~(1 << (irq - MPC5XXX_SDMA_IRQ_BASE));
+		out_be32(&sdma->IntMask, val);
+	} else {
+		val = in_be32(&intr->per_mask);
+		val &= ~(1 << (31 - (irq - MPC5XXX_PERP_IRQ_BASE)));
+		out_be32(&intr->per_mask, val);
+	}
+}
+
+static void mpc5xxx_ic_ack(unsigned int irq)
+{
+	u32 val;
+
+	/*
+	 * Only some irqs are reset here, others in interrupting hardware.
+	 */
+
+	switch (irq) {
+	case MPC5XXX_IRQ0:
+		val = in_be32(&intr->ctrl);
+		val |= 0x08000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	case MPC5XXX_CCS_IRQ:
+		val = in_be32(&intr->enc_status);
+		val |= 0x00000400;
+		out_be32(&intr->enc_status, val);
+		break;
+	case MPC5XXX_IRQ1:
+		val = in_be32(&intr->ctrl);
+		val |= 0x04000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	case MPC5XXX_IRQ2:
+		val = in_be32(&intr->ctrl);
+		val |= 0x02000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	case MPC5XXX_IRQ3:
+		val = in_be32(&intr->ctrl);
+		val |= 0x01000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	default:
+		if (irq >= MPC5XXX_SDMA_IRQ_BASE
+		    && irq < (MPC5XXX_SDMA_IRQ_BASE + MPC5XXX_SDMA_IRQ_NUM)) {
+			out_be32(&sdma->IntPend,
+				 1 << (irq - MPC5XXX_SDMA_IRQ_BASE));
+		}
+		break;
+	}
+}
+
+static void mpc5xxx_ic_disable_and_ack(unsigned int irq)
+{
+	mpc5xxx_ic_disable(irq);
+	mpc5xxx_ic_ack(irq);
+}
+
+static void mpc5xxx_ic_end(unsigned int irq)
+{
+	mpc5xxx_ic_enable(irq);
+}
+
+void mpc5xxx_init_irq(void)
+{
+	u32 intr_ctrl;
+
+	/* Remap the necessary zones */
+	intr = (struct mpc5xxx_intr *)(MPC5XXX_ICTL);
+	sdma = (struct mpc5xxx_sdma *)(MPC5XXX_SDMA);
+
+	/* Disable all interrupt sources. */
+	out_be32(&sdma->IntPend, 0xffffffff);	/* 1 means clear pending */
+	out_be32(&sdma->IntMask, 0xffffffff);	/* 1 means disabled */
+	out_be32(&intr->per_mask, 0x7ffffc00);	/* 1 means disabled */
+	out_be32(&intr->main_mask, 0x00010fff);	/* 1 means disabled */
+	intr_ctrl = in_be32(&intr->ctrl);
+	intr_ctrl |= 0x0f000000 |	/* clear IRQ 0-3 */
+	    0x00ff0000 |	/* IRQ 0-3 level sensitive low active */
+	    0x00001000 |	/* MEE master external enable */
+	    0x00000000 |	/* 0 means disable IRQ 0-3 */
+	    0x00000001;		/* CEb route critical normally */
+	out_be32(&intr->ctrl, intr_ctrl);
+
+	/* Zero a bunch of the priority settings.  */
+	out_be32(&intr->per_pri1, 0);
+	out_be32(&intr->per_pri2, 0);
+	out_be32(&intr->per_pri3, 0);
+	out_be32(&intr->main_pri1, 0);
+	out_be32(&intr->main_pri2, 0);
+}
+
+int mpc5xxx_get_irq(struct pt_regs *regs)
+{
+	u32 status;
+	int irq = -1;
+
+	status = in_be32(&intr->enc_status);
+
+	if (status & 0x00000400) {	/* critical */
+		irq = (status >> 8) & 0x3;
+		if (irq == 2)	/* high priority peripheral */
+			goto peripheral;
+		irq += MPC5XXX_CRIT_IRQ_BASE;
+	} else if (status & 0x00200000) {	/* main */
+		irq = (status >> 16) & 0x1f;
+		if (irq == 4)	/* low priority peripheral */
+			goto peripheral;
+		irq += MPC5XXX_MAIN_IRQ_BASE;
+	} else if (status & 0x20000000) {	/* peripheral */
+	      peripheral:
+		irq = (status >> 24) & 0x1f;
+		if (irq == 0) {	/* bestcomm */
+			status = in_be32(&sdma->IntPend);
+			irq = ffs(status) + MPC5XXX_SDMA_IRQ_BASE - 1;
+		} else
+			irq += MPC5XXX_PERP_IRQ_BASE;
+	}
+
+	return irq;
+}
+
+/****************************************************************************/
+
+int interrupt_init_cpu(ulong * decrementer_count)
+{
+	*decrementer_count = get_tbclk() / CONFIG_SYS_HZ;
+
+	mpc5xxx_init_irq();
+
+	return (0);
+}
+
+/****************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt(struct pt_regs *regs)
+{
+	int irq, unmask = 1;
+
+	irq = mpc5xxx_get_irq(regs);
+
+	mpc5xxx_ic_disable_and_ack(irq);
+
+	enable_interrupts();
+
+	if (irq_handlers[irq].handler != NULL)
+		(*irq_handlers[irq].handler) (irq_handlers[irq].arg);
+	else {
+		printf("\nBogus External Interrupt IRQ %d\n", irq);
+		/*
+		 * turn off the bogus interrupt, otherwise it
+		 * might repeat forever
+		 */
+		unmask = 0;
+	}
+
+	if (unmask)
+		mpc5xxx_ic_end(irq);
+}
+
+void timer_interrupt_cpu(struct pt_regs *regs)
+{
+	/* nothing to do here */
+	return;
+}
+
+/****************************************************************************/
+
+/*
+ * Install and free a interrupt handler.
+ */
+
+void irq_install_handler(int irq, interrupt_handler_t * handler, void *arg)
+{
+	if (irq < 0 || irq >= NR_IRQS) {
+		printf("irq_install_handler: bad irq number %d\n", irq);
+		return;
+	}
+
+	if (irq_handlers[irq].handler != NULL)
+		printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
+		       (ulong) handler, (ulong) irq_handlers[irq].handler);
+
+	irq_handlers[irq].handler = handler;
+	irq_handlers[irq].arg = arg;
+
+	mpc5xxx_ic_enable(irq);
+}
+
+void irq_free_handler(int irq)
+{
+	if (irq < 0 || irq >= NR_IRQS) {
+		printf("irq_free_handler: bad irq number %d\n", irq);
+		return;
+	}
+
+	mpc5xxx_ic_disable(irq);
+
+	irq_handlers[irq].handler = NULL;
+	irq_handlers[irq].arg = NULL;
+}
+
+/****************************************************************************/
+
+#if defined(CONFIG_CMD_IRQ)
+void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
+{
+	int irq, re_enable;
+	u32 intr_ctrl;
+	char *irq_config[] = { "level sensitive, active high",
+		"edge sensitive, rising active edge",
+		"edge sensitive, falling active edge",
+		"level sensitive, active low"
+	};
+
+	re_enable = disable_interrupts();
+
+	intr_ctrl = in_be32(&intr->ctrl);
+	printf("Interrupt configuration:\n");
+
+	for (irq = 0; irq <= 3; irq++) {
+		printf("IRQ%d: %s\n", irq,
+		       irq_config[(intr_ctrl >> (22 - 2 * irq)) & 0x3]);
+	}
+
+	puts("\nInterrupt-Information:\n" "Nr  Routine   Arg       Count\n");
+
+	for (irq = 0; irq < NR_IRQS; irq++)
+		if (irq_handlers[irq].handler != NULL)
+			printf("%02d  %08lx  %08lx  %ld\n", irq,
+			       (ulong) irq_handlers[irq].handler,
+			       (ulong) irq_handlers[irq].arg,
+			       irq_handlers[irq].count);
+
+	if (re_enable)
+		enable_interrupts();
+}
+#endif
diff --git a/arch/powerpc/cpu/mpc5xxx/io.S b/arch/powerpc/cpu/mpc5xxx/io.S
new file mode 100644
index 0000000..2178a26
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/io.S
@@ -0,0 +1,128 @@
+/*
+ *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2001	Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ *			Andreas Heppel <aheppel@sysgo.de>
+ *  Copyright (C) 2003	Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <ppc_asm.tmpl>
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     in8 */
+/*  Description:  Input 8 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  in8
+in8:
+	lbz     r3,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     in16 */
+/*  Description:  Input 16 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  in16
+in16:
+	lhz     r3,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     in16r */
+/*  Description:  Input 16 bits and byte reverse */
+/* ------------------------------------------------------------------------------- */
+	.globl  in16r
+in16r:
+	lhbrx   r3,0,r3
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     in32 */
+/*  Description:  Input 32 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  in32
+in32:
+	lwz     3,0(3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     in32r */
+/*  Description:  Input 32 bits and byte reverse */
+/* ------------------------------------------------------------------------------- */
+    .globl  in32r
+in32r:
+	lwbrx   r3,0,r3
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     out8 */
+/*  Description:  Output 8 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  out8
+out8:
+	stb     r4,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     out16 */
+/*  Description:  Output 16 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  out16
+out16:
+	sth     r4,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     out16r */
+/*  Description:  Byte reverse and output 16 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  out16r
+out16r:
+	sthbrx  r4,0,r3
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     out32 */
+/*  Description:  Output 32 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  out32
+out32:
+	stw     r4,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:     out32r */
+/*  Description:  Byte reverse and output 32 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl  out32r
+out32r:
+	stwbrx  r4,0,r3
+	sync
+	blr
diff --git a/arch/powerpc/cpu/mpc5xxx/loadtask.c b/arch/powerpc/cpu/mpc5xxx/loadtask.c
new file mode 100644
index 0000000..47e7b59
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/loadtask.c
@@ -0,0 +1,76 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * This file is based on code
+ * (C) Copyright Motorola, Inc., 2000
+ */
+
+#include <common.h>
+#include <mpc5xxx.h>
+
+/* BestComm/SmartComm microcode */
+extern int taskTable;
+
+void loadtask(int basetask, int tasks)
+{
+	int *sram = (int *)MPC5XXX_SRAM;
+	int *task_org = &taskTable;
+	unsigned int start, offset, end;
+	int i;
+
+#ifdef DEBUG
+	printf("basetask = %d, tasks = %d\n", basetask, tasks);
+	printf("task_org = 0x%08x\n", (unsigned int)task_org);
+#endif
+
+	/* setup TaskBAR register */
+	*(vu_long *)MPC5XXX_SDMA = MPC5XXX_SRAM;
+
+	/* relocate task table entries */
+	offset = (unsigned int)sram;
+	for (i = basetask; i < basetask + tasks; i++) {
+		sram[i * 8 + 0] = task_org[i * 8 + 0] + offset;
+		sram[i * 8 + 1] = task_org[i * 8 + 1] + offset;
+		sram[i * 8 + 2] = task_org[i * 8 + 2] + offset;
+		sram[i * 8 + 3] = task_org[i * 8 + 3] + offset;
+		sram[i * 8 + 4] = task_org[i * 8 + 4];
+		sram[i * 8 + 5] = task_org[i * 8 + 5];
+		sram[i * 8 + 6] = task_org[i * 8 + 6] + offset;
+		sram[i * 8 + 7] = task_org[i * 8 + 7];
+	}
+
+	/* relocate task descriptors */
+	start = (sram[basetask * 8] - (unsigned int)sram);
+	end = (sram[(basetask + tasks - 1) * 8 + 1] - (unsigned int)sram);
+
+#ifdef DEBUG
+	printf ("TDT start = 0x%08x, end = 0x%08x\n", start, end);
+#endif
+
+	start /= 4;
+	end /= 4;
+	for (i = start; i <= end; i++) {
+		sram[i] = task_org[i];
+	}
+
+	/* relocate variables */
+	start = (sram[basetask * 8 + 2] - (unsigned int)sram);
+	end = (sram[(basetask + tasks - 1) * 8 + 2] + 256 - (unsigned int)sram);
+	start /= 4;
+	end /= 4;
+	for (i = start; i < end; i++) {
+		sram[i] = task_org[i];
+	}
+
+	/* relocate function decriptors */
+	start = ((sram[basetask * 8 + 3] & 0xfffffffc) - (unsigned int)sram);
+	end = ((sram[(basetask + tasks - 1) * 8 + 3] & 0xfffffffc) + 256 - (unsigned int)sram);
+	start /= 4;
+	end /= 4;
+	for (i = start; i < end; i++) {
+		sram[i] = task_org[i];
+	}
+
+	asm volatile ("sync");
+}
diff --git a/arch/powerpc/cpu/mpc5xxx/pci_mpc5200.c b/arch/powerpc/cpu/mpc5xxx/pci_mpc5200.c
new file mode 100644
index 0000000..8268f8a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/pci_mpc5200.c
@@ -0,0 +1,187 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_PCI)
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <pci.h>
+#include <mpc5xxx.h>
+
+/* System RAM mapped over PCI */
+#define CONFIG_PCI_MEMORY_BUS	CONFIG_SYS_SDRAM_BASE
+#define CONFIG_PCI_MEMORY_PHYS	CONFIG_SYS_SDRAM_BASE
+#define CONFIG_PCI_MEMORY_SIZE	(1024 * 1024 * 1024)
+
+/* PCIIWCR bit fields */
+#define IWCR_MEM	(0 << 3)
+#define IWCR_IO		(1 << 3)
+#define IWCR_READ	(0 << 1)
+#define IWCR_READLINE	(1 << 1)
+#define IWCR_READMULT	(2 << 1)
+#define IWCR_EN		(1 << 0)
+
+static int mpc5200_read_config_dword(struct pci_controller *hose,
+			      pci_dev_t dev, int offset, u32* value)
+{
+	*(volatile u32 *)MPC5XXX_PCI_CAR = (1 << 31) | dev | offset;
+	eieio();
+	udelay(10);
+#if (defined CONFIG_PF5200 || defined CONFIG_CPCI5200)
+	if (dev & 0x00ff0000) {
+		u32 val;
+		val  = in_le16((volatile u16 *)(CONFIG_PCI_IO_PHYS+2));
+		udelay(10);
+		val = val << 16;
+		val |= in_le16((volatile u16 *)(CONFIG_PCI_IO_PHYS+0));
+		*value = val;
+	} else {
+		*value = in_le32((volatile u32 *)CONFIG_PCI_IO_PHYS);
+	}
+	udelay(10);
+#else
+	*value = in_le32((volatile u32 *)CONFIG_PCI_IO_PHYS);
+#endif
+	eieio();
+	*(volatile u32 *)MPC5XXX_PCI_CAR = 0;
+	udelay(10);
+	return 0;
+}
+
+static int mpc5200_write_config_dword(struct pci_controller *hose,
+			      pci_dev_t dev, int offset, u32 value)
+{
+	*(volatile u32 *)MPC5XXX_PCI_CAR = (1 << 31) | dev | offset;
+	eieio();
+	udelay(10);
+	out_le32((volatile u32 *)CONFIG_PCI_IO_PHYS, value);
+	eieio();
+	*(volatile u32 *)MPC5XXX_PCI_CAR = 0;
+	udelay(10);
+	return 0;
+}
+
+void pci_mpc5xxx_init (struct pci_controller *hose)
+{
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	/* System space */
+	pci_set_region(hose->regions + 0,
+		       CONFIG_PCI_MEMORY_BUS,
+		       CONFIG_PCI_MEMORY_PHYS,
+		       CONFIG_PCI_MEMORY_SIZE,
+		       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+	/* PCI memory space */
+	pci_set_region(hose->regions + 1,
+		       CONFIG_PCI_MEM_BUS,
+		       CONFIG_PCI_MEM_PHYS,
+		       CONFIG_PCI_MEM_SIZE,
+		       PCI_REGION_MEM);
+
+	/* PCI IO space */
+	pci_set_region(hose->regions + 2,
+		       CONFIG_PCI_IO_BUS,
+		       CONFIG_PCI_IO_PHYS,
+		       CONFIG_PCI_IO_SIZE,
+		       PCI_REGION_IO);
+
+	hose->region_count = 3;
+
+	pci_register_hose(hose);
+
+	/* GPIO Multiplexing - enable PCI */
+	*(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~(1 << 15);
+
+	/* Set host bridge as pci master and enable memory decoding */
+	*(vu_long *)MPC5XXX_PCI_CMD |=
+		PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+
+	/* Set maximum latency timer */
+	*(vu_long *)MPC5XXX_PCI_CFG |= (0xf800);
+
+	/* Set cache line size */
+	*(vu_long *)MPC5XXX_PCI_CFG = (*(vu_long *)MPC5XXX_PCI_CFG & ~0xff) |
+		(CONFIG_SYS_CACHELINE_SIZE / 4);
+
+	/* Map MBAR to PCI space */
+	*(vu_long *)MPC5XXX_PCI_BAR0 = CONFIG_SYS_MBAR;
+	*(vu_long *)MPC5XXX_PCI_TBATR0 = CONFIG_SYS_MBAR | 1;
+
+	/* Map RAM to PCI space */
+	*(vu_long *)MPC5XXX_PCI_BAR1 = CONFIG_PCI_MEMORY_BUS | (1 << 3);
+	*(vu_long *)MPC5XXX_PCI_TBATR1 = CONFIG_PCI_MEMORY_PHYS | 1;
+
+	/* Park XLB on PCI */
+	*(vu_long *)(MPC5XXX_XLBARB + 0x40) &= ~((7 << 8) | (3 << 5));
+	*(vu_long *)(MPC5XXX_XLBARB + 0x40) |= (3 << 8) | (3 << 5);
+
+	/* Disable interrupts from PCI controller */
+	*(vu_long *)MPC5XXX_PCI_GSCR &= ~(7 << 12);
+	*(vu_long *)MPC5XXX_PCI_ICR  &= ~(7 << 24);
+
+	/* Set PCI retry counter to 0 = infinite retry. */
+	/* The default of 255 is too short for slow devices. */
+	*(vu_long *)MPC5XXX_PCI_ICR &= 0xFFFFFF00;
+
+	/* Disable initiator windows */
+	*(vu_long *)MPC5XXX_PCI_IWCR = 0;
+
+	/* Map PCI memory to physical space */
+	*(vu_long *)MPC5XXX_PCI_IW0BTAR = CONFIG_PCI_MEM_PHYS |
+		(((CONFIG_PCI_MEM_SIZE - 1) >> 8) & 0x00ff0000) |
+		(CONFIG_PCI_MEM_BUS >> 16);
+	*(vu_long *)MPC5XXX_PCI_IWCR |= (IWCR_MEM | IWCR_READ | IWCR_EN) << 24;
+
+	/* Map PCI I/O to physical space */
+	*(vu_long *)MPC5XXX_PCI_IW1BTAR = CONFIG_PCI_IO_PHYS |
+		(((CONFIG_PCI_IO_SIZE - 1) >> 8) & 0x00ff0000) |
+		(CONFIG_PCI_IO_BUS >> 16);
+	*(vu_long *)MPC5XXX_PCI_IWCR |= (IWCR_IO | IWCR_READ | IWCR_EN) << 16;
+
+	/* Reset the PCI bus */
+	*(vu_long *)MPC5XXX_PCI_GSCR |= 1;
+	udelay(1000);
+	*(vu_long *)MPC5XXX_PCI_GSCR &= ~1;
+	udelay(1000);
+
+	pci_set_ops(hose,
+		pci_hose_read_config_byte_via_dword,
+		pci_hose_read_config_word_via_dword,
+		mpc5200_read_config_dword,
+		pci_hose_write_config_byte_via_dword,
+		pci_hose_write_config_word_via_dword,
+		mpc5200_write_config_dword);
+
+	udelay(1000);
+
+#ifdef CONFIG_PCI_SCAN_SHOW
+	printf("PCI:   Bus Dev VenId DevId Class Int\n");
+#endif
+
+	hose->last_busno = pci_hose_scan(hose);
+}
+#endif /* CONFIG_PCI */
diff --git a/arch/powerpc/cpu/mpc5xxx/serial.c b/arch/powerpc/cpu/mpc5xxx/serial.c
new file mode 100644
index 0000000..59a877a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/serial.c
@@ -0,0 +1,363 @@
+/*
+ * (C) Copyright 2000 - 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00, with
+ * changes based on the file arch/powerpc/mbxboot/m8260_tty.c from the
+ * Linux/PPC sources (m8260_tty.c had no copyright info in it).
+ *
+ * Martin Krause, 8 Jun 2006
+ * Added CONFIG_SERIAL_MULTI support
+ */
+
+/*
+ * Minimal serial functions needed to use one of the PSC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <mpc5xxx.h>
+
+#if defined (CONFIG_SERIAL_MULTI)
+#include <serial.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_PSC_CONSOLE)
+
+#if CONFIG_PSC_CONSOLE == 1
+#define PSC_BASE MPC5XXX_PSC1
+#elif CONFIG_PSC_CONSOLE == 2
+#define PSC_BASE MPC5XXX_PSC2
+#elif CONFIG_PSC_CONSOLE == 3
+#define PSC_BASE MPC5XXX_PSC3
+#elif CONFIG_PSC_CONSOLE == 4
+#define PSC_BASE MPC5XXX_PSC4
+#elif CONFIG_PSC_CONSOLE == 5
+#define PSC_BASE MPC5XXX_PSC5
+#elif CONFIG_PSC_CONSOLE == 6
+#define PSC_BASE MPC5XXX_PSC6
+#else
+#error CONFIG_PSC_CONSOLE must be in 1 ... 6
+#endif
+
+#if defined(CONFIG_SERIAL_MULTI) && !defined(CONFIG_PSC_CONSOLE2)
+#error you must define CONFIG_PSC_CONSOLE2 if CONFIG_SERIAL_MULTI is set
+#endif
+
+#if defined(CONFIG_SERIAL_MULTI)
+#if CONFIG_PSC_CONSOLE2 == 1
+#define PSC_BASE2 MPC5XXX_PSC1
+#elif CONFIG_PSC_CONSOLE2 == 2
+#define PSC_BASE2 MPC5XXX_PSC2
+#elif CONFIG_PSC_CONSOLE2 == 3
+#define PSC_BASE2 MPC5XXX_PSC3
+#elif CONFIG_PSC_CONSOLE2 == 4
+#define PSC_BASE2 MPC5XXX_PSC4
+#elif CONFIG_PSC_CONSOLE2 == 5
+#define PSC_BASE2 MPC5XXX_PSC5
+#elif CONFIG_PSC_CONSOLE2 == 6
+#define PSC_BASE2 MPC5XXX_PSC6
+#else
+#error CONFIG_PSC_CONSOLE2 must be in 1 ... 6
+#endif
+#endif /* CONFIG_SERIAL_MULTI */
+
+#if defined(CONFIG_SERIAL_MULTI)
+int serial_init_dev (unsigned long dev_base)
+#else
+int serial_init (void)
+#endif
+{
+#if defined(CONFIG_SERIAL_MULTI)
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+#else
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
+#endif
+	unsigned long baseclk;
+	int div;
+
+	/* reset PSC */
+	psc->command = PSC_SEL_MODE_REG_1;
+
+	/* select clock sources */
+	psc->psc_clock_select = 0;
+	baseclk = (gd->ipb_clk + 16) / 32;
+
+	/* switch to UART mode */
+	psc->sicr = 0;
+
+	/* configure parity, bit length and so on */
+	psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE;
+	psc->mode = PSC_MODE_ONE_STOP;
+
+	/* set up UART divisor */
+	div = (baseclk + (gd->baudrate/2)) / gd->baudrate;
+	psc->ctur = (div >> 8) & 0xff;
+	psc->ctlr = div & 0xff;
+
+	/* disable all interrupts */
+	psc->psc_imr = 0;
+
+	/* reset and enable Rx/Tx */
+	psc->command = PSC_RST_RX;
+	psc->command = PSC_RST_TX;
+	psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE;
+
+	return (0);
+}
+
+#if defined(CONFIG_SERIAL_MULTI)
+void serial_putc_dev (unsigned long dev_base, const char c)
+#else
+void serial_putc(const char c)
+#endif
+{
+#if defined(CONFIG_SERIAL_MULTI)
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+#else
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
+#endif
+
+	if (c == '\n')
+#if defined(CONFIG_SERIAL_MULTI)
+		serial_putc_dev (dev_base, '\r');
+#else
+		serial_putc('\r');
+#endif
+
+	/* Wait for last character to go. */
+	while (!(psc->psc_status & PSC_SR_TXEMP))
+		;
+
+	psc->psc_buffer_8 = c;
+}
+
+#if defined(CONFIG_SERIAL_MULTI)
+void serial_putc_raw_dev(unsigned long dev_base, const char c)
+#else
+void serial_putc_raw(const char c)
+#endif
+{
+#if defined(CONFIG_SERIAL_MULTI)
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+#else
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
+#endif
+	/* Wait for last character to go. */
+	while (!(psc->psc_status & PSC_SR_TXEMP))
+		;
+
+	psc->psc_buffer_8 = c;
+}
+
+
+#if defined(CONFIG_SERIAL_MULTI)
+void serial_puts_dev (unsigned long dev_base, const char *s)
+#else
+void serial_puts (const char *s)
+#endif
+{
+	while (*s) {
+#if defined(CONFIG_SERIAL_MULTI)
+		serial_putc_dev (dev_base, *s++);
+#else
+		serial_putc (*s++);
+#endif
+	}
+}
+
+#if defined(CONFIG_SERIAL_MULTI)
+int serial_getc_dev (unsigned long dev_base)
+#else
+int serial_getc(void)
+#endif
+{
+#if defined(CONFIG_SERIAL_MULTI)
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+#else
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
+#endif
+
+	/* Wait for a character to arrive. */
+	while (!(psc->psc_status & PSC_SR_RXRDY))
+		;
+
+	return psc->psc_buffer_8;
+}
+
+#if defined(CONFIG_SERIAL_MULTI)
+int serial_tstc_dev (unsigned long dev_base)
+#else
+int serial_tstc(void)
+#endif
+{
+#if defined(CONFIG_SERIAL_MULTI)
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+#else
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
+#endif
+
+	return (psc->psc_status & PSC_SR_RXRDY);
+}
+
+#if defined(CONFIG_SERIAL_MULTI)
+void serial_setbrg_dev (unsigned long dev_base)
+#else
+void serial_setbrg(void)
+#endif
+{
+#if defined(CONFIG_SERIAL_MULTI)
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+#else
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
+#endif
+	unsigned long baseclk, div;
+
+	baseclk = (gd->ipb_clk + 16) / 32;
+
+	/* set up UART divisor */
+	div = (baseclk + (gd->baudrate/2)) / gd->baudrate;
+	psc->ctur = (div >> 8) & 0xFF;
+	psc->ctlr =  div & 0xff;
+}
+
+#if defined(CONFIG_SERIAL_MULTI)
+void serial_setrts_dev (unsigned long dev_base, int s)
+#else
+void serial_setrts(int s)
+#endif
+{
+#if defined(CONFIG_SERIAL_MULTI)
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+#else
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
+#endif
+
+	if (s) {
+		/* Assert RTS (become LOW) */
+		psc->op1 = 0x1;
+	}
+	else {
+		/* Negate RTS (become HIGH) */
+		psc->op0 = 0x1;
+	}
+}
+
+#if defined(CONFIG_SERIAL_MULTI)
+int serial_getcts_dev (unsigned long dev_base)
+#else
+int serial_getcts(void)
+#endif
+{
+#if defined(CONFIG_SERIAL_MULTI)
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+#else
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
+#endif
+
+	return (psc->ip & 0x1) ? 0 : 1;
+}
+
+#if defined(CONFIG_SERIAL_MULTI)
+int serial0_init(void)
+{
+	return (serial_init_dev(PSC_BASE));
+}
+
+int serial1_init(void)
+{
+	return (serial_init_dev(PSC_BASE2));
+}
+void serial0_setbrg (void)
+{
+	serial_setbrg_dev(PSC_BASE);
+}
+void serial1_setbrg (void)
+{
+	serial_setbrg_dev(PSC_BASE2);
+}
+
+void serial0_putc(const char c)
+{
+	serial_putc_dev(PSC_BASE,c);
+}
+
+void serial1_putc(const char c)
+{
+	serial_putc_dev(PSC_BASE2, c);
+}
+void serial0_puts(const char *s)
+{
+	serial_puts_dev(PSC_BASE, s);
+}
+
+void serial1_puts(const char *s)
+{
+	serial_puts_dev(PSC_BASE2, s);
+}
+
+int serial0_getc(void)
+{
+	return(serial_getc_dev(PSC_BASE));
+}
+
+int serial1_getc(void)
+{
+	return(serial_getc_dev(PSC_BASE2));
+}
+int serial0_tstc(void)
+{
+	return (serial_tstc_dev(PSC_BASE));
+}
+
+int serial1_tstc(void)
+{
+	return (serial_tstc_dev(PSC_BASE2));
+}
+
+struct serial_device serial0_device =
+{
+	"serial0",
+	"UART0",
+	serial0_init,
+	serial0_setbrg,
+	serial0_getc,
+	serial0_tstc,
+	serial0_putc,
+	serial0_puts,
+};
+
+struct serial_device serial1_device =
+{
+	"serial1",
+	"UART1",
+	serial1_init,
+	serial1_setbrg,
+	serial1_getc,
+	serial1_tstc,
+	serial1_putc,
+	serial1_puts,
+};
+#endif /* CONFIG_SERIAL_MULTI */
+
+#endif /* CONFIG_PSC_CONSOLE */
diff --git a/arch/powerpc/cpu/mpc5xxx/speed.c b/arch/powerpc/cpu/mpc5xxx/speed.c
new file mode 100644
index 0000000..8027d3e
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/speed.c
@@ -0,0 +1,94 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc5xxx.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* ------------------------------------------------------------------------- */
+
+/* Bus-to-Core Multipliers */
+
+static int bus2core[] = {
+	3, 2, 2, 2, 4, 4, 5, 9,
+	6, 11, 8, 10, 3, 12, 7, 0,
+	6, 5, 13, 2, 14, 4, 15, 9,
+	0, 11, 8, 10, 16, 12, 7, 0
+};
+/* ------------------------------------------------------------------------- */
+
+/*
+ *
+ */
+
+int get_clocks (void)
+{
+	ulong val, vco;
+
+#if !defined(CONFIG_SYS_MPC5XXX_CLKIN)
+#error clock measuring not implemented yet - define CONFIG_SYS_MPC5XXX_CLKIN
+#endif
+
+	val = *(vu_long *)MPC5XXX_CDM_PORCFG;
+	if (val & (1 << 6)) {
+		vco = CONFIG_SYS_MPC5XXX_CLKIN * 12;
+	} else {
+		vco = CONFIG_SYS_MPC5XXX_CLKIN * 16;
+	}
+	if (val & (1 << 5)) {
+		gd->bus_clk = vco / 8;
+	} else {
+		gd->bus_clk = vco / 4;
+	}
+	gd->cpu_clk = gd->bus_clk * bus2core[val & 0x1f] / 2;
+
+	val = *(vu_long *)MPC5XXX_CDM_CFG;
+	if (val & (1 << 8)) {
+		gd->ipb_clk = gd->bus_clk / 2;
+	} else {
+		gd->ipb_clk = gd->bus_clk;
+	}
+	switch (val & 3) {
+		case 0: gd->pci_clk = gd->ipb_clk; break;
+		case 1: gd->pci_clk = gd->ipb_clk / 2; break;
+		default: gd->pci_clk = gd->bus_clk / 4; break;
+	}
+
+	return (0);
+}
+
+int prt_mpc5xxx_clks (void)
+{
+	char buf1[32], buf2[32], buf3[32];
+
+	printf ("       Bus %s MHz, IPB %s MHz, PCI %s MHz\n",
+		strmhz(buf1, gd->bus_clk),
+		strmhz(buf2, gd->ipb_clk),
+		strmhz(buf3, gd->pci_clk)
+	);
+	return (0);
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/arch/powerpc/cpu/mpc5xxx/start.S b/arch/powerpc/cpu/mpc5xxx/start.S
new file mode 100644
index 0000000..8b9f09b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/start.S
@@ -0,0 +1,777 @@
+/*
+ *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000 - 2003 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ *  U-Boot - Startup Code for MPC5xxx CPUs
+ */
+#include <config.h>
+#include <mpc5xxx.h>
+#include <timestamp.h>
+#include <version.h>
+
+#define CONFIG_MPC5xxx 1	/* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1	/* avoid reading Linux autoconf.h file	*/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef  CONFIG_IDENT_STRING
+#define  CONFIG_IDENT_STRING ""
+#endif
+
+/* We don't want the  MMU yet.
+*/
+#undef	MSR_KERNEL
+/* Floating Point enable, Machine Check and Recoverable Interr. */
+#ifdef DEBUG
+#define MSR_KERNEL (MSR_FP|MSR_RI)
+#else
+#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
+#endif
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+	START_GOT
+	GOT_ENTRY(_GOT2_TABLE_)
+	GOT_ENTRY(_FIXUP_TABLE_)
+
+	GOT_ENTRY(_start)
+	GOT_ENTRY(_start_of_vectors)
+	GOT_ENTRY(_end_of_vectors)
+	GOT_ENTRY(transfer_to_handler)
+
+	GOT_ENTRY(__init_end)
+	GOT_ENTRY(_end)
+	GOT_ENTRY(__bss_start)
+	END_GOT
+
+/*
+ * Version string
+ */
+	.data
+	.globl	version_string
+version_string:
+	.ascii U_BOOT_VERSION
+	.ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
+	.ascii CONFIG_IDENT_STRING, "\0"
+
+/*
+ * Exception vectors
+ */
+	.text
+	. = EXC_OFF_SYS_RESET
+	.globl	_start
+_start:
+	li	r21, BOOTFLAG_COLD	/* Normal Power-On		*/
+	nop
+	b	boot_cold
+
+	. = EXC_OFF_SYS_RESET + 0x10
+
+	.globl	_start_warm
+_start_warm:
+	li	r21, BOOTFLAG_WARM	/* Software reboot		*/
+	b	boot_warm
+
+boot_cold:
+boot_warm:
+	mfmsr	r5			/* save msr contents		*/
+
+	/* Move CSBoot and adjust instruction pointer                   */
+	/*--------------------------------------------------------------*/
+
+#if defined(CONFIG_SYS_LOWBOOT)
+# if defined(CONFIG_SYS_RAMBOOT)
+#  error CONFIG_SYS_LOWBOOT is incompatible with CONFIG_SYS_RAMBOOT
+# endif /* CONFIG_SYS_RAMBOOT */
+	lis	r4, CONFIG_SYS_DEFAULT_MBAR@h
+	lis	r3,	START_REG(CONFIG_SYS_BOOTCS_START)@h
+	ori	r3, r3, START_REG(CONFIG_SYS_BOOTCS_START)@l
+	stw	r3, 0x4(r4)		/* CS0 start */
+	lis	r3,	STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@h
+	ori	r3, r3, STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@l
+	stw	r3, 0x8(r4)		/* CS0 stop */
+	lis	r3,     0x02010000@h
+	ori	r3, r3, 0x02010000@l
+	stw	r3, 0x54(r4)		/* CS0 and Boot enable */
+
+	lis     r3,	lowboot_reentry@h	/* jump from bootlow address space (0x0000xxxx) */
+	ori     r3, r3, lowboot_reentry@l	/* to the address space the linker used */
+	mtlr	r3
+	blr
+
+lowboot_reentry:
+	lis	r3,	START_REG(CONFIG_SYS_BOOTCS_START)@h
+	ori	r3, r3, START_REG(CONFIG_SYS_BOOTCS_START)@l
+	stw	r3, 0x4c(r4)		/* Boot start */
+	lis	r3,	STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@h
+	ori	r3, r3, STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@l
+	stw	r3, 0x50(r4)		/* Boot stop */
+	lis	r3,     0x02000001@h
+	ori	r3, r3, 0x02000001@l
+	stw	r3, 0x54(r4)		/* Boot enable, CS0 disable */
+#endif	/* CONFIG_SYS_LOWBOOT */
+
+#if defined(CONFIG_SYS_DEFAULT_MBAR) && !defined(CONFIG_SYS_RAMBOOT)
+	lis	r3, CONFIG_SYS_MBAR@h
+	ori	r3, r3, CONFIG_SYS_MBAR@l
+	/* MBAR is mirrored into the MBAR SPR */
+	mtspr	MBAR,r3
+	rlwinm	r3, r3, 16, 16, 31
+	lis	r4, CONFIG_SYS_DEFAULT_MBAR@h
+	stw	r3, 0(r4)
+#endif /* CONFIG_SYS_DEFAULT_MBAR */
+
+	/* Initialise the MPC5xxx processor core			*/
+	/*--------------------------------------------------------------*/
+
+	bl	init_5xxx_core
+
+	/* initialize some things that are hard to access from C	*/
+	/*--------------------------------------------------------------*/
+
+	/* set up stack in on-chip SRAM */
+	lis	r3, CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l
+	ori	r1, r3, CONFIG_SYS_INIT_SP_OFFSET
+	li	r0, 0			/* Make room for stack frame header and	*/
+	stwu	r0, -4(r1)		/* clear final stack frame so that	*/
+	stwu	r0, -4(r1)		/* stack backtraces terminate cleanly	*/
+
+	/* let the C-code set up the rest				*/
+	/*								*/
+	/* Be careful to keep code relocatable !			*/
+	/*--------------------------------------------------------------*/
+
+	GET_GOT			/* initialize GOT access		*/
+
+	/* r3: IMMR */
+	bl	cpu_init_f	/* run low-level CPU init code (in Flash)*/
+
+	mr	r3, r21
+	/* r3: BOOTFLAG */
+	bl	board_init_f	/* run 1st part of board init code (in Flash)*/
+
+/*
+ * Vector Table
+ */
+
+	.globl	_start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+	STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+	STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+	STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+	. = 0x600
+Alignment:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	mfspr	r4,DAR
+	stw	r4,_DAR(r21)
+	mfspr	r5,DSISR
+	stw	r5,_DSISR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+	. = 0x700
+ProgramCheck:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+		MSR_KERNEL, COPY_EE)
+
+	STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+	/* I guess we could implement decrementer, and may have
+	 * to someday for timekeeping.
+	 */
+	STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+
+	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+	STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+	STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+	STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+	STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+	STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+	STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
+#ifdef DEBUG
+	. = 0x1300
+	/*
+	 * This exception occurs when the program counter matches the
+	 * Instruction Address Breakpoint Register (IABR).
+	 *
+	 * I want the cpu to halt if this occurs so I can hunt around
+	 * with the debugger and look at things.
+	 *
+	 * When DEBUG is defined, both machine check enable (in the MSR)
+	 * and checkstop reset enable (in the reset mode register) are
+	 * turned off and so a checkstop condition will result in the cpu
+	 * halting.
+	 *
+	 * I force the cpu into a checkstop condition by putting an illegal
+	 * instruction here (at least this is the theory).
+	 *
+	 * well - that didnt work, so just do an infinite loop!
+	 */
+1:	b	1b
+#else
+	STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
+#endif
+	STD_EXCEPTION(0x1400, SMI, UnknownException)
+
+	STD_EXCEPTION(0x1500, Trap_15, UnknownException)
+	STD_EXCEPTION(0x1600, Trap_16, UnknownException)
+	STD_EXCEPTION(0x1700, Trap_17, UnknownException)
+	STD_EXCEPTION(0x1800, Trap_18, UnknownException)
+	STD_EXCEPTION(0x1900, Trap_19, UnknownException)
+	STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
+	STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+	STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
+	STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
+	STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
+	STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
+	STD_EXCEPTION(0x2000, Trap_20, UnknownException)
+	STD_EXCEPTION(0x2100, Trap_21, UnknownException)
+	STD_EXCEPTION(0x2200, Trap_22, UnknownException)
+	STD_EXCEPTION(0x2300, Trap_23, UnknownException)
+	STD_EXCEPTION(0x2400, Trap_24, UnknownException)
+	STD_EXCEPTION(0x2500, Trap_25, UnknownException)
+	STD_EXCEPTION(0x2600, Trap_26, UnknownException)
+	STD_EXCEPTION(0x2700, Trap_27, UnknownException)
+	STD_EXCEPTION(0x2800, Trap_28, UnknownException)
+	STD_EXCEPTION(0x2900, Trap_29, UnknownException)
+	STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
+	STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
+	STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
+	STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
+	STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
+	STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
+
+
+	.globl	_end_of_vectors
+_end_of_vectors:
+
+	. = 0x3000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+	.globl	transfer_to_handler
+transfer_to_handler:
+	stw	r22,_NIP(r21)
+	lis	r22,MSR_POW@h
+	andc	r23,r23,r22
+	stw	r23,_MSR(r21)
+	SAVE_GPR(7, r21)
+	SAVE_4GPRS(8, r21)
+	SAVE_8GPRS(12, r21)
+	SAVE_8GPRS(24, r21)
+	mflr	r23
+	andi.	r24,r23,0x3f00		/* get vector offset */
+	stw	r24,TRAP(r21)
+	li	r22,0
+	stw	r22,RESULT(r21)
+	lwz	r24,0(r23)		/* virtual address of handler */
+	lwz	r23,4(r23)		/* where to go when done */
+	mtspr	SRR0,r24
+	mtspr	SRR1,r20
+	mtlr	r23
+	SYNC
+	rfi				/* jump to handler, enable MMU */
+
+int_return:
+	mfmsr	r28		/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC			/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SRR0,r2
+	mtspr	SRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfi
+
+/*
+ * This code initialises the MPC5xxx processor core
+ * (conforms to PowerPC 603e spec)
+ * Note: expects original MSR contents to be in r5.
+ */
+
+	.globl	init_5xx_core
+init_5xxx_core:
+
+	/* Initialize machine status; enable machine check interrupt	*/
+	/*--------------------------------------------------------------*/
+
+	li	r3, MSR_KERNEL		/* Set ME and RI flags */
+	rlwimi	r3, r5, 0, 25, 25	/* preserve IP bit set by HRCW */
+#ifdef DEBUG
+	rlwimi	r3, r5, 0, 21, 22	/* debugger might set SE & BE bits */
+#endif
+	SYNC				/* Some chip revs need this... */
+	mtmsr	r3
+	SYNC
+	mtspr	SRR1, r3		/* Make SRR1 match MSR */
+
+	/* Initialize the Hardware Implementation-dependent Registers	*/
+	/* HID0 also contains cache control				*/
+	/*--------------------------------------------------------------*/
+
+	lis	r3, CONFIG_SYS_HID0_INIT@h
+	ori	r3, r3, CONFIG_SYS_HID0_INIT@l
+	SYNC
+	mtspr	HID0, r3
+
+	lis	r3, CONFIG_SYS_HID0_FINAL@h
+	ori	r3, r3, CONFIG_SYS_HID0_FINAL@l
+	SYNC
+	mtspr	HID0, r3
+
+	/* clear all BAT's						*/
+	/*--------------------------------------------------------------*/
+
+	li	r0, 0
+	mtspr	DBAT0U, r0
+	mtspr	DBAT0L, r0
+	mtspr	DBAT1U, r0
+	mtspr	DBAT1L, r0
+	mtspr	DBAT2U, r0
+	mtspr	DBAT2L, r0
+	mtspr	DBAT3U, r0
+	mtspr	DBAT3L, r0
+	mtspr	DBAT4U, r0
+	mtspr	DBAT4L, r0
+	mtspr	DBAT5U, r0
+	mtspr	DBAT5L, r0
+	mtspr	DBAT6U, r0
+	mtspr	DBAT6L, r0
+	mtspr	DBAT7U, r0
+	mtspr	DBAT7L, r0
+	mtspr	IBAT0U, r0
+	mtspr	IBAT0L, r0
+	mtspr	IBAT1U, r0
+	mtspr	IBAT1L, r0
+	mtspr	IBAT2U, r0
+	mtspr	IBAT2L, r0
+	mtspr	IBAT3U, r0
+	mtspr	IBAT3L, r0
+	mtspr	IBAT4U, r0
+	mtspr	IBAT4L, r0
+	mtspr	IBAT5U, r0
+	mtspr	IBAT5L, r0
+	mtspr	IBAT6U, r0
+	mtspr	IBAT6L, r0
+	mtspr	IBAT7U, r0
+	mtspr	IBAT7L, r0
+	SYNC
+
+	/* invalidate all tlb's						*/
+	/*								*/
+	/* From the 603e User Manual: "The 603e provides the ability to	*/
+	/* invalidate a TLB entry. The TLB Invalidate Entry (tlbie)	*/
+	/* instruction invalidates the TLB entry indexed by the EA, and	*/
+	/* operates on both the instruction and data TLBs simultaneously*/
+	/* invalidating four TLB entries (both sets in each TLB). The	*/
+	/* index corresponds to bits 15-19 of the EA. To invalidate all	*/
+	/* entries within both TLBs, 32 tlbie instructions should be	*/
+	/* issued, incrementing this field by one each time."		*/
+	/*								*/
+	/* "Note that the tlbia instruction is not implemented on the	*/
+	/* 603e."							*/
+	/*								*/
+	/* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000	*/
+	/* incrementing by 0x1000 each time. The code below is sort of	*/
+	/* based on code in "flush_tlbs" from arch/powerpc/kernel/head.S	*/
+	/*								*/
+	/*--------------------------------------------------------------*/
+
+	li	r3, 32
+	mtctr	r3
+	li	r3, 0
+1:	tlbie	r3
+	addi	r3, r3, 0x1000
+	bdnz	1b
+	SYNC
+
+	/* Done!							*/
+	/*--------------------------------------------------------------*/
+
+	blr
+
+/* Cache functions.
+ *
+ * Note: requires that all cache bits in
+ * HID0 are in the low half word.
+ */
+	.globl	icache_enable
+icache_enable:
+	mfspr	r3, HID0
+	ori	r3, r3, HID0_ICE
+	lis	r4, 0
+	ori	r4, r4, HID0_ILOCK
+	andc	r3, r3, r4
+	ori	r4, r3, HID0_ICFI
+	isync
+	mtspr	HID0, r4	/* sets enable and invalidate, clears lock */
+	isync
+	mtspr	HID0, r3	/* clears invalidate */
+	blr
+
+	.globl	icache_disable
+icache_disable:
+	mfspr	r3, HID0
+	lis	r4, 0
+	ori	r4, r4, HID0_ICE|HID0_ILOCK
+	andc	r3, r3, r4
+	ori	r4, r3, HID0_ICFI
+	isync
+	mtspr	HID0, r4	/* sets invalidate, clears enable and lock */
+	isync
+	mtspr	HID0, r3	/* clears invalidate */
+	blr
+
+	.globl	icache_status
+icache_status:
+	mfspr	r3, HID0
+	rlwinm	r3, r3, HID0_ICE_BITPOS + 1, 31, 31
+	blr
+
+	.globl	dcache_enable
+dcache_enable:
+	mfspr	r3, HID0
+	ori	r3, r3, HID0_DCE
+	lis	r4, 0
+	ori	r4, r4, HID0_DLOCK
+	andc	r3, r3, r4
+	ori	r4, r3, HID0_DCI
+	sync
+	mtspr	HID0, r4	/* sets enable and invalidate, clears lock */
+	sync
+	mtspr	HID0, r3	/* clears invalidate */
+	blr
+
+	.globl	dcache_disable
+dcache_disable:
+	mfspr	r3, HID0
+	lis	r4, 0
+	ori	r4, r4, HID0_DCE|HID0_DLOCK
+	andc	r3, r3, r4
+	ori	r4, r3, HID0_DCI
+	sync
+	mtspr	HID0, r4	/* sets invalidate, clears enable and lock */
+	sync
+	mtspr	HID0, r3	/* clears invalidate */
+	blr
+
+	.globl	dcache_status
+dcache_status:
+	mfspr	r3, HID0
+	rlwinm	r3, r3, HID0_DCE_BITPOS + 1, 31, 31
+	blr
+
+	.globl get_svr
+get_svr:
+	mfspr	r3, SVR
+	blr
+
+	.globl get_pvr
+get_pvr:
+	mfspr	r3, PVR
+	blr
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+	.globl	relocate_code
+relocate_code:
+	mr	r1,  r3		/* Set new stack pointer		*/
+	mr	r9,  r4		/* Save copy of Global Data pointer	*/
+	mr	r10, r5		/* Save copy of Destination Address	*/
+
+	GET_GOT
+	mr	r3,  r5				/* Destination Address	*/
+	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address	*/
+	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
+	lwz	r5, GOT(__init_end)
+	sub	r5, r5, r4
+	li	r6, CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size	*/
+
+	/*
+	 * Fix GOT pointer:
+	 *
+	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+	 *
+	 * Offset:
+	 */
+	sub	r15, r10, r4
+
+	/* First our own GOT */
+	add	r12, r12, r15
+	/* then the one used by the C code */
+	add	r30, r30, r15
+
+	/*
+	 * Now relocate code
+	 */
+
+	cmplw	cr1,r3,r4
+	addi	r0,r5,3
+	srwi.	r0,r0,2
+	beq	cr1,4f		/* In place copy is not necessary	*/
+	beq	7f		/* Protect against 0 count		*/
+	mtctr	r0
+	bge	cr1,2f
+
+	la	r8,-4(r4)
+	la	r7,-4(r3)
+1:	lwzu	r0,4(r8)
+	stwu	r0,4(r7)
+	bdnz	1b
+	b	4f
+
+2:	slwi	r0,r0,2
+	add	r8,r4,r0
+	add	r7,r3,r0
+3:	lwzu	r0,-4(r8)
+	stwu	r0,-4(r7)
+	bdnz	3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:	cmpwi	r6,0
+	add	r5,r3,r5
+	beq	7f		/* Always flush prefetch queue in any case */
+	subi	r0,r6,1
+	andc	r3,r3,r0
+	mfspr	r7,HID0		/* don't do dcbst if dcache is disabled */
+	rlwinm	r7,r7,HID0_DCE_BITPOS+1,31,31
+	cmpwi	r7,0
+	beq	9f
+	mr	r4,r3
+5:	dcbst	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	5b
+	sync			/* Wait for all dcbst to complete on bus */
+9:	mfspr	r7,HID0		/* don't do icbi if icache is disabled */
+	rlwinm	r7,r7,HID0_ICE_BITPOS+1,31,31
+	cmpwi	r7,0
+	beq	7f
+	mr	r4,r3
+6:	icbi	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	6b
+7:	sync			/* Wait for all icbi to complete on bus	*/
+	isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+	mtlr	r0
+	blr
+
+in_ram:
+
+	/*
+	 * Relocation Function, r12 point to got2+0x8000
+	 *
+	 * Adjust got2 pointers, no need to check for 0, this code
+	 * already puts a few entries in the table.
+	 */
+	li	r0,__got2_entries@sectoff@l
+	la	r3,GOT(_GOT2_TABLE_)
+	lwz	r11,GOT(_GOT2_TABLE_)
+	mtctr	r0
+	sub	r11,r3,r11
+	addi	r3,r3,-4
+1:	lwzu	r0,4(r3)
+	cmpwi	r0,0
+	beq-	2f
+	add	r0,r0,r11
+	stw	r0,0(r3)
+2:	bdnz	1b
+
+	/*
+	 * Now adjust the fixups and the pointers to the fixups
+	 * in case we need to move ourselves again.
+	 */
+	li	r0,__fixup_entries@sectoff@l
+	lwz	r3,GOT(_FIXUP_TABLE_)
+	cmpwi	r0,0
+	mtctr	r0
+	addi	r3,r3,-4
+	beq	4f
+3:	lwzu	r4,4(r3)
+	lwzux	r0,r4,r11
+	add	r0,r0,r11
+	stw	r10,0(r3)
+	stw	r0,0(r4)
+	bdnz	3b
+4:
+clear_bss:
+	/*
+	 * Now clear BSS segment
+	 */
+	lwz	r3,GOT(__bss_start)
+	lwz	r4,GOT(_end)
+
+	cmplw	0, r3, r4
+	beq	6f
+
+	li	r0, 0
+5:
+	stw	r0, 0(r3)
+	addi	r3, r3, 4
+	cmplw	0, r3, r4
+	bne	5b
+6:
+
+	mr	r3, r9		/* Global Data pointer		*/
+	mr	r4, r10		/* Destination Address		*/
+	bl	board_init_r
+
+	/*
+	 * Copy exception vector code to low memory
+	 *
+	 * r3: dest_addr
+	 * r7: source address, r8: end address, r9: target address
+	 */
+	.globl	trap_init
+trap_init:
+	mflr	r4			/* save link register		*/
+	GET_GOT
+	lwz	r7, GOT(_start)
+	lwz	r8, GOT(_end_of_vectors)
+
+	li	r9, 0x100		/* reset vector always at 0x100 */
+
+	cmplw	0, r7, r8
+	bgelr				/* return if r7>=r8 - just in case */
+1:
+	lwz	r0, 0(r7)
+	stw	r0, 0(r9)
+	addi	r7, r7, 4
+	addi	r9, r9, 4
+	cmplw	0, r7, r8
+	bne	1b
+
+	/*
+	 * relocate `hdlr' and `int_return' entries
+	 */
+	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+	li	r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	2b
+
+	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	3b
+
+	li	r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	4b
+
+	mfmsr	r3			/* now that the vectors have	*/
+	lis	r7, MSR_IP@h		/* relocated into low memory	*/
+	ori	r7, r7, MSR_IP@l	/* MSR[IP] can be turned off	*/
+	andc	r3, r3, r7		/* (if it was on)		*/
+	SYNC				/* Some chip revs need this... */
+	mtmsr	r3
+	SYNC
+
+	mtlr	r4			/* restore link register    */
+	blr
diff --git a/arch/powerpc/cpu/mpc5xxx/traps.c b/arch/powerpc/cpu/mpc5xxx/traps.c
new file mode 100644
index 0000000..5972f34
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/traps.c
@@ -0,0 +1,245 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ * fixed Machine Check Reasons by Reinhard Meyer (r.meyer@emk-elektronik.de)
+ *
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM	0x02000000
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace(unsigned long *sp)
+{
+	int cnt = 0;
+	unsigned long i;
+
+	printf("Call backtrace: ");
+	while (sp) {
+		if ((uint)sp > END_OF_MEM)
+			break;
+
+		i = sp[1];
+		if (cnt++ % 7 == 0)
+			printf("\n");
+		printf("%08lX ", i);
+		if (cnt > 32) break;
+		sp = (unsigned long *)*sp;
+	}
+	printf("\n");
+}
+
+void show_regs(struct pt_regs * regs)
+{
+	int i;
+
+	printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+	       regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+	printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+	       regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+	       regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+	       regs->msr&MSR_IR ? 1 : 0,
+	       regs->msr&MSR_DR ? 1 : 0);
+
+	printf("\n");
+	for (i = 0;  i < 32;  i++) {
+		if ((i % 8) == 0)
+		{
+			printf("GPR%02d: ", i);
+		}
+
+		printf("%08lX ", regs->gpr[i]);
+		if ((i % 8) == 7)
+		{
+			printf("\n");
+		}
+	}
+}
+
+
+void
+_exception(int signr, struct pt_regs *regs)
+{
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+void
+MachineCheckException(struct pt_regs *regs)
+{
+	unsigned long fixup;
+
+	/* Probing PCI using config cycles cause this exception
+	 * when a device is not present.  Catch it and return to
+	 * the PCI exception handler.
+	 */
+	if ((fixup = search_exception_table(regs->nip)) != 0) {
+		regs->nip = fixup;
+		return;
+	}
+
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	printf("Machine check in kernel mode.\n");
+	printf("Caused by (from msr): ");
+	printf("regs %p ",regs);
+	/* refer to 603e Manual (MPC603EUM/AD), chapter 4.5.2.1 */
+	switch( regs->msr & 0x000F0000)
+	{
+	case (0x80000000>>12) :
+		printf("Machine check signal - probably due to mm fault\n"
+			"with mmu off\n");
+		break;
+	case (0x80000000>>13) :
+		printf("Transfer error ack signal\n");
+		break;
+	case (0x80000000>>14) :
+		printf("Data parity signal\n");
+		break;
+	case (0x80000000>>15) :
+		printf("Address parity signal\n");
+		break;
+	default:
+		printf("Unknown values in msr\n");
+	}
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Program Check Exception");
+}
+
+void
+SoftEmuException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Software Emulation Exception");
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+	       regs->nip, regs->msr, regs->trap);
+	_exception(0, regs);
+}
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+void
+DebugException(struct pt_regs *regs)
+{
+
+  printf("Debugger trap at @ %lx\n", regs->nip );
+  show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+  do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading.  If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+#if 0
+	int	retval;
+
+	__asm__ __volatile__(			\
+		"1:	lwz %0,0(%1)\n"		\
+		"	eieio\n"		\
+		"	li %0,0\n"		\
+		"2:\n"				\
+		".section .fixup,\"ax\"\n"	\
+		"3:	li %0,-1\n"		\
+		"	b 2b\n"			\
+		".section __ex_table,\"a\"\n"	\
+		"	.align 2\n"		\
+		"	.long 1b,3b\n"		\
+		".text"				\
+		: "=r" (retval) : "r"(addr));
+
+	return (retval);
+#endif
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc5xxx/u-boot-customlayout.lds b/arch/powerpc/cpu/mpc5xxx/u-boot-customlayout.lds
new file mode 100644
index 0000000..ecffc1b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/u-boot-customlayout.lds
@@ -0,0 +1,133 @@
+/*
+ * (C) Copyright 2003-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text)	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data)	}
+  .rel.rodata    : { *(.rel.rodata)	}
+  .rela.rodata   : { *(.rela.rodata)	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	}
+  .plt : { *(.plt) }
+  .text      :
+  {
+    /* WARNING - the following is hand-optimized to fit within  */
+    /* the sector layout of our flash chips!    XXX FIXME XXX   */
+
+    arch/powerpc/cpu/mpc5xxx/start.o          (.text)
+    arch/powerpc/cpu/mpc5xxx/traps.o          (.text)
+    lib/crc32.o         (.text)
+    arch/powerpc/lib/cache.o             (.text)
+    arch/powerpc/lib/time.o              (.text)
+
+    . = DEFINED(env_offset) ? env_offset : .;
+    common/env_embedded.o        (.ppcenv)
+
+    *(.text)
+    *(.got1)
+    . = ALIGN(16);
+    *(.eh_frame)
+    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x0FFF) & 0xFFFFF000;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+  __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  . = .;
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+
+  . = .;
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(4096);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss (NOLOAD)       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+   . = ALIGN(4);
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc5xxx/u-boot.lds b/arch/powerpc/cpu/mpc5xxx/u-boot.lds
new file mode 100644
index 0000000..ea4060d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/u-boot.lds
@@ -0,0 +1,122 @@
+/*
+ * (C) Copyright 2003-2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text)	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data)	}
+  .rel.rodata    : { *(.rel.rodata)	}
+  .rela.rodata   : { *(.rela.rodata)	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	}
+  .plt : { *(.plt) }
+  .text      :
+  {
+    arch/powerpc/cpu/mpc5xxx/start.o	(.text)
+    *(.text)
+    *(.got1)
+    . = ALIGN(16);
+    *(.eh_frame)
+    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x0FFF) & 0xFFFFF000;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+  __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  . = .;
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+
+  . = .;
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(4096);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss (NOLOAD)       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+   . = ALIGN(4);
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc5xxx/usb.c b/arch/powerpc/cpu/mpc5xxx/usb.c
new file mode 100644
index 0000000..bec7da3
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/usb.c
@@ -0,0 +1,58 @@
+/*
+ * (C) Copyright 2007
+ * Markus Klotzbuecher, DENX Software Engineering <mk@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT)
+
+#include <mpc5xxx.h>
+
+int usb_cpu_init(void)
+{
+	/* Set the USB Clock						     */
+	*(vu_long *)MPC5XXX_CDM_48_FDC = CONFIG_USB_CLOCK;
+
+#ifdef CONFIG_PSC3_USB /* USB is using the alternate configuration */
+	/* remove all PSC3 USB bits first before ORing in ours */
+	*(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~0x00804f00;
+#else
+	/* remove all USB bits first before ORing in ours */
+	*(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~0x00807000;
+#endif
+	/* Activate USB port						     */
+	*(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= CONFIG_USB_CONFIG;
+
+	return 0;
+}
+
+int usb_cpu_stop(void)
+{
+	return 0;
+}
+
+int usb_cpu_init_fail(void)
+{
+	return 0;
+}
+
+#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) */
diff --git a/arch/powerpc/cpu/mpc5xxx/usb_ohci.c b/arch/powerpc/cpu/mpc5xxx/usb_ohci.c
new file mode 100644
index 0000000..7976e4d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/usb_ohci.c
@@ -0,0 +1,1646 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB on the MPC5200.
+ *
+ * (C) Copyright 2003-2004
+ * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
+ *
+ * (C) Copyright 2004
+ * Pierre Aubert, Staubli Faverges <p.aubert@staubli.com>
+ *
+ * Note: Much of this code has been derived from Linux 2.4
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+/*
+ * IMPORTANT NOTES
+ * 1 - this driver is intended for use with USB Mass Storage Devices
+ *     (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes!
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_USB_OHCI
+
+#include <malloc.h>
+#include <usb.h>
+#include "usb_ohci.h"
+
+#include <mpc5xxx.h>
+
+#define OHCI_USE_NPS		/* force NoPowerSwitching mode */
+#undef OHCI_VERBOSE_DEBUG	/* not always helpful */
+#undef DEBUG
+#undef SHOW_INFO
+#undef OHCI_FILL_TRACE
+
+/* For initializing controller (mask in an HCFS mode too) */
+#define OHCI_CONTROL_INIT \
+	(OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
+
+#define readl(a) (*((volatile u32 *)(a)))
+#define writel(a, b) (*((volatile u32 *)(b)) = ((volatile u32)a))
+
+#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+
+#ifdef DEBUG
+#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg)
+#else
+#define dbg(format, arg...) do {} while(0)
+#endif /* DEBUG */
+#define err(format, arg...) printf("ERROR: " format "\n", ## arg)
+#ifdef SHOW_INFO
+#define info(format, arg...) printf("INFO: " format "\n", ## arg)
+#else
+#define info(format, arg...) do {} while(0)
+#endif
+
+#define m16_swap(x) swap_16(x)
+#define m32_swap(x) swap_32(x)
+
+#define ohci_cpu_to_le16(x) (x)
+#define ohci_cpu_to_le32(x) (x)
+
+/* global ohci_t */
+static ohci_t gohci;
+/* this must be aligned to a 256 byte boundary */
+struct ohci_hcca ghcca[1];
+/* a pointer to the aligned storage */
+struct ohci_hcca *phcca;
+/* this allocates EDs for all possible endpoints */
+struct ohci_device ohci_dev;
+/* urb_priv */
+urb_priv_t urb_priv;
+/* RHSC flag */
+int got_rhsc;
+/* device which was disconnected */
+struct usb_device *devgone;
+/* flag guarding URB transation */
+int urb_finished = 0;
+
+/*-------------------------------------------------------------------------*/
+
+/* AMD-756 (D2 rev) reports corrupt register contents in some cases.
+ * The erratum (#4) description is incorrect.  AMD's workaround waits
+ * till some bits (mostly reserved) are clear; ok for all revs.
+ */
+#define OHCI_QUIRK_AMD756 0xabcd
+#define read_roothub(hc, register, mask) ({ \
+	u32 temp = readl (&hc->regs->roothub.register); \
+	if (hc->flags & OHCI_QUIRK_AMD756) \
+		while (temp & mask) \
+			temp = readl (&hc->regs->roothub.register); \
+	temp; })
+
+static u32 roothub_a (struct ohci *hc)
+	{ return read_roothub (hc, a, 0xfc0fe000); }
+static inline u32 roothub_b (struct ohci *hc)
+	{ return readl (&hc->regs->roothub.b); }
+static inline u32 roothub_status (struct ohci *hc)
+	{ return readl (&hc->regs->roothub.status); }
+static u32 roothub_portstatus (struct ohci *hc, int i)
+	{ return read_roothub (hc, portstatus [i], 0xffe0fce0); }
+
+
+/* forward declaration */
+static int hc_interrupt (void);
+static void
+td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer,
+	int transfer_len, struct devrequest * setup, urb_priv_t * urb, int interval);
+
+/*-------------------------------------------------------------------------*
+ * URB support functions
+ *-------------------------------------------------------------------------*/
+
+/* free HCD-private data associated with this URB */
+
+static void urb_free_priv (urb_priv_t * urb)
+{
+	int		i;
+	int		last;
+	struct td	* td;
+
+	last = urb->length - 1;
+	if (last >= 0) {
+		for (i = 0; i <= last; i++) {
+			td = urb->td[i];
+			if (td) {
+				td->usb_dev = NULL;
+				urb->td[i] = NULL;
+			}
+		}
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+static int sohci_get_current_frame_number (struct usb_device * dev);
+
+/* debug| print the main components of an URB
+ * small: 0) header + data packets 1) just header */
+
+static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffer,
+	int transfer_len, struct devrequest * setup, char * str, int small)
+{
+	urb_priv_t * purb = &urb_priv;
+
+	dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx",
+			str,
+			sohci_get_current_frame_number (dev),
+			usb_pipedevice (pipe),
+			usb_pipeendpoint (pipe),
+			usb_pipeout (pipe)? 'O': 'I',
+			usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"):
+				(usb_pipecontrol (pipe)? "CTRL": "BULK"),
+			purb->actual_length,
+			transfer_len, dev->status);
+#ifdef	OHCI_VERBOSE_DEBUG
+	if (!small) {
+		int i, len;
+
+		if (usb_pipecontrol (pipe)) {
+			printf (__FILE__ ": cmd(8):");
+			for (i = 0; i < 8 ; i++)
+				printf (" %02x", ((__u8 *) setup) [i]);
+			printf ("\n");
+		}
+		if (transfer_len > 0 && buffer) {
+			printf (__FILE__ ": data(%d/%d):",
+				purb->actual_length,
+				transfer_len);
+			len = usb_pipeout (pipe)?
+					transfer_len: purb->actual_length;
+			for (i = 0; i < 16 && i < len; i++)
+				printf (" %02x", ((__u8 *) buffer) [i]);
+			printf ("%s\n", i < len? "...": "");
+		}
+	}
+#endif
+}
+
+/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/
+void ep_print_int_eds (ohci_t *ohci, char * str) {
+	int i, j;
+	 __u32 * ed_p;
+	for (i= 0; i < 32; i++) {
+		j = 5;
+		ed_p = &(ohci->hcca->int_table [i]);
+		if (*ed_p == 0)
+		    continue;
+		printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i);
+		while (*ed_p != 0 && j--) {
+			ed_t *ed = (ed_t *)ohci_cpu_to_le32(ed_p);
+			printf (" ed: %4x;", ed->hwINFO);
+			ed_p = &ed->hwNextED;
+		}
+		printf ("\n");
+	}
+}
+
+static void ohci_dump_intr_mask (char *label, __u32 mask)
+{
+	dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s",
+		label,
+		mask,
+		(mask & OHCI_INTR_MIE) ? " MIE" : "",
+		(mask & OHCI_INTR_OC) ? " OC" : "",
+		(mask & OHCI_INTR_RHSC) ? " RHSC" : "",
+		(mask & OHCI_INTR_FNO) ? " FNO" : "",
+		(mask & OHCI_INTR_UE) ? " UE" : "",
+		(mask & OHCI_INTR_RD) ? " RD" : "",
+		(mask & OHCI_INTR_SF) ? " SF" : "",
+		(mask & OHCI_INTR_WDH) ? " WDH" : "",
+		(mask & OHCI_INTR_SO) ? " SO" : ""
+		);
+}
+
+static void maybe_print_eds (char *label, __u32 value)
+{
+	ed_t *edp = (ed_t *)value;
+
+	if (value) {
+		dbg ("%s %08x", label, value);
+		dbg ("%08x", edp->hwINFO);
+		dbg ("%08x", edp->hwTailP);
+		dbg ("%08x", edp->hwHeadP);
+		dbg ("%08x", edp->hwNextED);
+	}
+}
+
+static char * hcfs2string (int state)
+{
+	switch (state) {
+		case OHCI_USB_RESET:	return "reset";
+		case OHCI_USB_RESUME:	return "resume";
+		case OHCI_USB_OPER:	return "operational";
+		case OHCI_USB_SUSPEND:	return "suspend";
+	}
+	return "?";
+}
+
+/* dump control and status registers */
+static void ohci_dump_status (ohci_t *controller)
+{
+	struct ohci_regs	*regs = controller->regs;
+	__u32			temp;
+
+	temp = readl (&regs->revision) & 0xff;
+	if (temp != 0x10)
+		dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f));
+
+	temp = readl (&regs->control);
+	dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp,
+		(temp & OHCI_CTRL_RWE) ? " RWE" : "",
+		(temp & OHCI_CTRL_RWC) ? " RWC" : "",
+		(temp & OHCI_CTRL_IR) ? " IR" : "",
+		hcfs2string (temp & OHCI_CTRL_HCFS),
+		(temp & OHCI_CTRL_BLE) ? " BLE" : "",
+		(temp & OHCI_CTRL_CLE) ? " CLE" : "",
+		(temp & OHCI_CTRL_IE) ? " IE" : "",
+		(temp & OHCI_CTRL_PLE) ? " PLE" : "",
+		temp & OHCI_CTRL_CBSR
+		);
+
+	temp = readl (&regs->cmdstatus);
+	dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp,
+		(temp & OHCI_SOC) >> 16,
+		(temp & OHCI_OCR) ? " OCR" : "",
+		(temp & OHCI_BLF) ? " BLF" : "",
+		(temp & OHCI_CLF) ? " CLF" : "",
+		(temp & OHCI_HCR) ? " HCR" : ""
+		);
+
+	ohci_dump_intr_mask ("intrstatus", readl (&regs->intrstatus));
+	ohci_dump_intr_mask ("intrenable", readl (&regs->intrenable));
+
+	maybe_print_eds ("ed_periodcurrent", readl (&regs->ed_periodcurrent));
+
+	maybe_print_eds ("ed_controlhead", readl (&regs->ed_controlhead));
+	maybe_print_eds ("ed_controlcurrent", readl (&regs->ed_controlcurrent));
+
+	maybe_print_eds ("ed_bulkhead", readl (&regs->ed_bulkhead));
+	maybe_print_eds ("ed_bulkcurrent", readl (&regs->ed_bulkcurrent));
+
+	maybe_print_eds ("donehead", readl (&regs->donehead));
+}
+
+static void ohci_dump_roothub (ohci_t *controller, int verbose)
+{
+	__u32			temp, ndp, i;
+
+	temp = roothub_a (controller);
+	ndp = (temp & RH_A_NDP);
+
+	if (verbose) {
+		dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp,
+			((temp & RH_A_POTPGT) >> 24) & 0xff,
+			(temp & RH_A_NOCP) ? " NOCP" : "",
+			(temp & RH_A_OCPM) ? " OCPM" : "",
+			(temp & RH_A_DT) ? " DT" : "",
+			(temp & RH_A_NPS) ? " NPS" : "",
+			(temp & RH_A_PSM) ? " PSM" : "",
+			ndp
+			);
+		temp = roothub_b (controller);
+		dbg ("roothub.b: %08x PPCM=%04x DR=%04x",
+			temp,
+			(temp & RH_B_PPCM) >> 16,
+			(temp & RH_B_DR)
+			);
+		temp = roothub_status (controller);
+		dbg ("roothub.status: %08x%s%s%s%s%s%s",
+			temp,
+			(temp & RH_HS_CRWE) ? " CRWE" : "",
+			(temp & RH_HS_OCIC) ? " OCIC" : "",
+			(temp & RH_HS_LPSC) ? " LPSC" : "",
+			(temp & RH_HS_DRWE) ? " DRWE" : "",
+			(temp & RH_HS_OCI) ? " OCI" : "",
+			(temp & RH_HS_LPS) ? " LPS" : ""
+			);
+	}
+
+	for (i = 0; i < ndp; i++) {
+		temp = roothub_portstatus (controller, i);
+		dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s",
+			i,
+			temp,
+			(temp & RH_PS_PRSC) ? " PRSC" : "",
+			(temp & RH_PS_OCIC) ? " OCIC" : "",
+			(temp & RH_PS_PSSC) ? " PSSC" : "",
+			(temp & RH_PS_PESC) ? " PESC" : "",
+			(temp & RH_PS_CSC) ? " CSC" : "",
+
+			(temp & RH_PS_LSDA) ? " LSDA" : "",
+			(temp & RH_PS_PPS) ? " PPS" : "",
+			(temp & RH_PS_PRS) ? " PRS" : "",
+			(temp & RH_PS_POCI) ? " POCI" : "",
+			(temp & RH_PS_PSS) ? " PSS" : "",
+
+			(temp & RH_PS_PES) ? " PES" : "",
+			(temp & RH_PS_CCS) ? " CCS" : ""
+			);
+	}
+}
+
+static void ohci_dump (ohci_t *controller, int verbose)
+{
+	dbg ("OHCI controller usb-%s state", controller->slot_name);
+
+	/* dumps some of the state we know about */
+	ohci_dump_status (controller);
+	if (verbose)
+		ep_print_int_eds (controller, "hcca");
+	dbg ("hcca frame #%04x", controller->hcca->frame_no);
+	ohci_dump_roothub (controller, 1);
+}
+
+
+#endif /* DEBUG */
+
+/*-------------------------------------------------------------------------*
+ * Interface functions (URB)
+ *-------------------------------------------------------------------------*/
+
+/* get a transfer request */
+
+int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer,
+		int transfer_len, struct devrequest *setup, int interval)
+{
+	ohci_t *ohci;
+	ed_t * ed;
+	urb_priv_t *purb_priv;
+	int i, size = 0;
+
+	ohci = &gohci;
+
+	/* when controller's hung, permit only roothub cleanup attempts
+	 * such as powering down ports */
+	if (ohci->disabled) {
+		err("sohci_submit_job: EPIPE");
+		return -1;
+	}
+
+	/* if we have an unfinished URB from previous transaction let's
+	 * fail and scream as quickly as possible so as not to corrupt
+	 * further communication */
+	if (!urb_finished) {
+		err("sohci_submit_job: URB NOT FINISHED");
+		return -1;
+	}
+	/* we're about to begin a new transaction here so mark the URB unfinished */
+	urb_finished = 0;
+
+	/* every endpoint has a ed, locate and fill it */
+	if (!(ed = ep_add_ed (dev, pipe))) {
+		err("sohci_submit_job: ENOMEM");
+		return -1;
+	}
+
+	/* for the private part of the URB we need the number of TDs (size) */
+	switch (usb_pipetype (pipe)) {
+		case PIPE_BULK: /* one TD for every 4096 Byte */
+			size = (transfer_len - 1) / 4096 + 1;
+			break;
+		case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */
+			size = (transfer_len == 0)? 2:
+						(transfer_len - 1) / 4096 + 3;
+			break;
+	}
+
+	if (size >= (N_URB_TD - 1)) {
+		err("need %d TDs, only have %d", size, N_URB_TD);
+		return -1;
+	}
+	purb_priv = &urb_priv;
+	purb_priv->pipe = pipe;
+
+	/* fill the private part of the URB */
+	purb_priv->length = size;
+	purb_priv->ed = ed;
+	purb_priv->actual_length = 0;
+
+	/* allocate the TDs */
+	/* note that td[0] was allocated in ep_add_ed */
+	for (i = 0; i < size; i++) {
+		purb_priv->td[i] = td_alloc (dev);
+		if (!purb_priv->td[i]) {
+			purb_priv->length = i;
+			urb_free_priv (purb_priv);
+			err("sohci_submit_job: ENOMEM");
+			return -1;
+		}
+	}
+
+	if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
+		urb_free_priv (purb_priv);
+		err("sohci_submit_job: EINVAL");
+		return -1;
+	}
+
+	/* link the ed into a chain if is not already */
+	if (ed->state != ED_OPER)
+		ep_link (ohci, ed);
+
+	/* fill the TDs and link it to the ed */
+	td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, interval);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+/* tell us the current USB frame number */
+
+static int sohci_get_current_frame_number (struct usb_device *usb_dev)
+{
+	ohci_t *ohci = &gohci;
+
+	return ohci_cpu_to_le16 (ohci->hcca->frame_no);
+}
+#endif
+
+/*-------------------------------------------------------------------------*
+ * ED handling functions
+ *-------------------------------------------------------------------------*/
+
+/* link an ed into one of the HC chains */
+
+static int ep_link (ohci_t *ohci, ed_t *edi)
+{
+	volatile ed_t *ed = edi;
+
+	ed->state = ED_OPER;
+
+	switch (ed->type) {
+	case PIPE_CONTROL:
+		ed->hwNextED = 0;
+		if (ohci->ed_controltail == NULL) {
+			writel (ed, &ohci->regs->ed_controlhead);
+		} else {
+			ohci->ed_controltail->hwNextED = ohci_cpu_to_le32 ((unsigned long)ed);
+		}
+		ed->ed_prev = ohci->ed_controltail;
+		if (!ohci->ed_controltail && !ohci->ed_rm_list[0] &&
+			!ohci->ed_rm_list[1] && !ohci->sleeping) {
+			ohci->hc_control |= OHCI_CTRL_CLE;
+			writel (ohci->hc_control, &ohci->regs->control);
+		}
+		ohci->ed_controltail = edi;
+		break;
+
+	case PIPE_BULK:
+		ed->hwNextED = 0;
+		if (ohci->ed_bulktail == NULL) {
+			writel (ed, &ohci->regs->ed_bulkhead);
+		} else {
+			ohci->ed_bulktail->hwNextED = ohci_cpu_to_le32 ((unsigned long)ed);
+		}
+		ed->ed_prev = ohci->ed_bulktail;
+		if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] &&
+			!ohci->ed_rm_list[1] && !ohci->sleeping) {
+			ohci->hc_control |= OHCI_CTRL_BLE;
+			writel (ohci->hc_control, &ohci->regs->control);
+		}
+		ohci->ed_bulktail = edi;
+		break;
+	}
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* unlink an ed from one of the HC chains.
+ * just the link to the ed is unlinked.
+ * the link from the ed still points to another operational ed or 0
+ * so the HC can eventually finish the processing of the unlinked ed */
+
+static int ep_unlink (ohci_t *ohci, ed_t *edi)
+{
+	volatile ed_t *ed = edi;
+
+	ed->hwINFO |= ohci_cpu_to_le32 (OHCI_ED_SKIP);
+
+	switch (ed->type) {
+	case PIPE_CONTROL:
+		if (ed->ed_prev == NULL) {
+			if (!ed->hwNextED) {
+				ohci->hc_control &= ~OHCI_CTRL_CLE;
+				writel (ohci->hc_control, &ohci->regs->control);
+			}
+			writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_controlhead);
+		} else {
+			ed->ed_prev->hwNextED = ed->hwNextED;
+		}
+		if (ohci->ed_controltail == ed) {
+			ohci->ed_controltail = ed->ed_prev;
+		} else {
+			((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
+		}
+		break;
+
+	case PIPE_BULK:
+		if (ed->ed_prev == NULL) {
+			if (!ed->hwNextED) {
+				ohci->hc_control &= ~OHCI_CTRL_BLE;
+				writel (ohci->hc_control, &ohci->regs->control);
+			}
+			writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_bulkhead);
+		} else {
+			ed->ed_prev->hwNextED = ed->hwNextED;
+		}
+		if (ohci->ed_bulktail == ed) {
+			ohci->ed_bulktail = ed->ed_prev;
+		} else {
+			((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
+		}
+		break;
+	}
+	ed->state = ED_UNLINK;
+	return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/* add/reinit an endpoint; this should be done once at the usb_set_configuration command,
+ * but the USB stack is a little bit stateless	so we do it at every transaction
+ * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK
+ * in all other cases the state is left unchanged
+ * the ed info fields are setted anyway even though most of them should not change */
+
+static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe)
+{
+	td_t *td;
+	ed_t *ed_ret;
+	volatile ed_t *ed;
+
+	ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint (pipe) << 1) |
+			(usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))];
+
+	if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) {
+		err("ep_add_ed: pending delete");
+		/* pending delete request */
+		return NULL;
+	}
+
+	if (ed->state == ED_NEW) {
+		ed->hwINFO = ohci_cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */
+		/* dummy td; end of td list for ed */
+		td = td_alloc (usb_dev);
+		ed->hwTailP = ohci_cpu_to_le32 ((unsigned long)td);
+		ed->hwHeadP = ed->hwTailP;
+		ed->state = ED_UNLINK;
+		ed->type = usb_pipetype (pipe);
+		ohci_dev.ed_cnt++;
+	}
+
+	ed->hwINFO = ohci_cpu_to_le32 (usb_pipedevice (pipe)
+			| usb_pipeendpoint (pipe) << 7
+			| (usb_pipeisoc (pipe)? 0x8000: 0)
+			| (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000))
+			| usb_pipeslow (pipe) << 13
+			| usb_maxpacket (usb_dev, pipe) << 16);
+
+	return ed_ret;
+}
+
+/*-------------------------------------------------------------------------*
+ * TD handling functions
+ *-------------------------------------------------------------------------*/
+
+/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
+
+static void td_fill (ohci_t *ohci, unsigned int info,
+	void *data, int len,
+	struct usb_device *dev, int index, urb_priv_t *urb_priv)
+{
+	volatile td_t  *td, *td_pt;
+#ifdef OHCI_FILL_TRACE
+	int i;
+#endif
+
+	if (index > urb_priv->length) {
+		err("index > length");
+		return;
+	}
+	/* use this td as the next dummy */
+	td_pt = urb_priv->td [index];
+	td_pt->hwNextTD = 0;
+
+	/* fill the old dummy TD */
+	td = urb_priv->td [index] = (td_t *)(ohci_cpu_to_le32 (urb_priv->ed->hwTailP) & ~0xf);
+
+	td->ed = urb_priv->ed;
+	td->next_dl_td = NULL;
+	td->index = index;
+	td->data = (__u32)data;
+#ifdef OHCI_FILL_TRACE
+	if (usb_pipebulk(urb_priv->pipe) && usb_pipeout(urb_priv->pipe)) {
+		for (i = 0; i < len; i++)
+		printf("td->data[%d] %#2x ",i, ((unsigned char *)td->data)[i]);
+		printf("\n");
+	}
+#endif
+	if (!len)
+		data = 0;
+
+	td->hwINFO = ohci_cpu_to_le32 (info);
+	td->hwCBP = ohci_cpu_to_le32 ((unsigned long)data);
+	if (data)
+		td->hwBE = ohci_cpu_to_le32 ((unsigned long)(data + len - 1));
+	else
+		td->hwBE = 0;
+	td->hwNextTD = ohci_cpu_to_le32 ((unsigned long)td_pt);
+
+	/* append to queue */
+	td->ed->hwTailP = td->hwNextTD;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* prepare all TDs of a transfer */
+static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer,
+	int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval)
+{
+	ohci_t *ohci = &gohci;
+	int data_len = transfer_len;
+	void *data;
+	int cnt = 0;
+	__u32 info = 0;
+	unsigned int toggle = 0;
+
+	/* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */
+	if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) {
+		toggle = TD_T_TOGGLE;
+	} else {
+		toggle = TD_T_DATA0;
+		usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1);
+	}
+	urb->td_cnt = 0;
+	if (data_len)
+		data = buffer;
+	else
+		data = 0;
+
+	switch (usb_pipetype (pipe)) {
+	case PIPE_BULK:
+		info = usb_pipeout (pipe)?
+			TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ;
+		while(data_len > 4096) {
+			td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, dev, cnt, urb);
+			data += 4096; data_len -= 4096; cnt++;
+		}
+		info = usb_pipeout (pipe)?
+			TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
+		td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, dev, cnt, urb);
+		cnt++;
+
+		if (!ohci->sleeping)
+			writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
+		break;
+
+	case PIPE_CONTROL:
+		info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
+		td_fill (ohci, info, setup, 8, dev, cnt++, urb);
+		if (data_len > 0) {
+			info = usb_pipeout (pipe)?
+				TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1;
+			/* NOTE:  mishandles transfers >8K, some >4K */
+			td_fill (ohci, info, data, data_len, dev, cnt++, urb);
+		}
+		info = usb_pipeout (pipe)?
+			TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1;
+		td_fill (ohci, info, data, 0, dev, cnt++, urb);
+		if (!ohci->sleeping)
+			writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
+		break;
+	}
+	if (urb->length != cnt)
+		dbg("TD LENGTH %d != CNT %d", urb->length, cnt);
+}
+
+/*-------------------------------------------------------------------------*
+ * Done List handling functions
+ *-------------------------------------------------------------------------*/
+
+
+/* calculate the transfer length and update the urb */
+
+static void dl_transfer_length(td_t * td)
+{
+	__u32 tdINFO, tdBE, tdCBP;
+	urb_priv_t *lurb_priv = &urb_priv;
+
+	tdINFO = ohci_cpu_to_le32 (td->hwINFO);
+	tdBE   = ohci_cpu_to_le32 (td->hwBE);
+	tdCBP  = ohci_cpu_to_le32 (td->hwCBP);
+
+
+	if (!(usb_pipecontrol(lurb_priv->pipe) &&
+	    ((td->index == 0) || (td->index == lurb_priv->length - 1)))) {
+		if (tdBE != 0) {
+			if (td->hwCBP == 0)
+				lurb_priv->actual_length += tdBE - td->data + 1;
+			else
+				lurb_priv->actual_length += tdCBP - td->data;
+		}
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* replies to the request have to be on a FIFO basis so
+ * we reverse the reversed done-list */
+
+static td_t * dl_reverse_done_list (ohci_t *ohci)
+{
+	__u32 td_list_hc;
+	td_t *td_rev = NULL;
+	td_t *td_list = NULL;
+	urb_priv_t *lurb_priv = NULL;
+
+	td_list_hc = ohci_cpu_to_le32 (ohci->hcca->done_head) & 0xfffffff0;
+	ohci->hcca->done_head = 0;
+
+	while (td_list_hc) {
+		td_list = (td_t *)td_list_hc;
+
+		if (TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO))) {
+			lurb_priv = &urb_priv;
+			dbg(" USB-error/status: %x : %p",
+					TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO)), td_list);
+			if (td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x1)) {
+				if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) {
+					td_list->ed->hwHeadP =
+						(lurb_priv->td[lurb_priv->length - 1]->hwNextTD & ohci_cpu_to_le32 (0xfffffff0)) |
+									(td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x2));
+					lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1;
+				} else
+					td_list->ed->hwHeadP &= ohci_cpu_to_le32 (0xfffffff2);
+			}
+			td_list->hwNextTD = 0;
+		}
+
+		td_list->next_dl_td = td_rev;
+		td_rev = td_list;
+		td_list_hc = ohci_cpu_to_le32 (td_list->hwNextTD) & 0xfffffff0;
+	}
+	return td_list;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* td done list */
+static int dl_done_list (ohci_t *ohci, td_t *td_list)
+{
+	td_t *td_list_next = NULL;
+	ed_t *ed;
+	int cc = 0;
+	int stat = 0;
+	/* urb_t *urb; */
+	urb_priv_t *lurb_priv;
+	__u32 tdINFO, edHeadP, edTailP;
+
+	while (td_list) {
+		td_list_next = td_list->next_dl_td;
+
+		lurb_priv = &urb_priv;
+		tdINFO = ohci_cpu_to_le32 (td_list->hwINFO);
+
+		ed = td_list->ed;
+
+		dl_transfer_length(td_list);
+
+		/* error code of transfer */
+		cc = TD_CC_GET (tdINFO);
+		if (++(lurb_priv->td_cnt) == lurb_priv->length) {
+			if ((ed->state & (ED_OPER | ED_UNLINK))
+					&& (lurb_priv->state != URB_DEL)) {
+				dbg("ConditionCode %#x", cc);
+				stat = cc_to_error[cc];
+				urb_finished = 1;
+			}
+		}
+
+		if (ed->state != ED_NEW) {
+			edHeadP = ohci_cpu_to_le32 (ed->hwHeadP) & 0xfffffff0;
+			edTailP = ohci_cpu_to_le32 (ed->hwTailP);
+
+			/* unlink eds if they are not busy */
+			if ((edHeadP == edTailP) && (ed->state == ED_OPER))
+				ep_unlink (ohci, ed);
+		}
+
+		td_list = td_list_next;
+	}
+	return stat;
+}
+
+/*-------------------------------------------------------------------------*
+ * Virtual Root Hub
+ *-------------------------------------------------------------------------*/
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] =
+{
+	0x12,	    /*	__u8  bLength; */
+	0x01,	    /*	__u8  bDescriptorType; Device */
+	0x10,	    /*	__u16 bcdUSB; v1.1 */
+	0x01,
+	0x09,	    /*	__u8  bDeviceClass; HUB_CLASSCODE */
+	0x00,	    /*	__u8  bDeviceSubClass; */
+	0x00,	    /*	__u8  bDeviceProtocol; */
+	0x08,	    /*	__u8  bMaxPacketSize0; 8 Bytes */
+	0x00,	    /*	__u16 idVendor; */
+	0x00,
+	0x00,	    /*	__u16 idProduct; */
+	0x00,
+	0x00,	    /*	__u16 bcdDevice; */
+	0x00,
+	0x00,	    /*	__u8  iManufacturer; */
+	0x01,	    /*	__u8  iProduct; */
+	0x00,	    /*	__u8  iSerialNumber; */
+	0x01	    /*	__u8  bNumConfigurations; */
+};
+
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+	0x09,	    /*	__u8  bLength; */
+	0x02,	    /*	__u8  bDescriptorType; Configuration */
+	0x19,	    /*	__u16 wTotalLength; */
+	0x00,
+	0x01,	    /*	__u8  bNumInterfaces; */
+	0x01,	    /*	__u8  bConfigurationValue; */
+	0x00,	    /*	__u8  iConfiguration; */
+	0x40,	    /*	__u8  bmAttributes;
+		 Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+	0x00,	    /*	__u8  MaxPower; */
+
+	/* interface */
+	0x09,	    /*	__u8  if_bLength; */
+	0x04,	    /*	__u8  if_bDescriptorType; Interface */
+	0x00,	    /*	__u8  if_bInterfaceNumber; */
+	0x00,	    /*	__u8  if_bAlternateSetting; */
+	0x01,	    /*	__u8  if_bNumEndpoints; */
+	0x09,	    /*	__u8  if_bInterfaceClass; HUB_CLASSCODE */
+	0x00,	    /*	__u8  if_bInterfaceSubClass; */
+	0x00,	    /*	__u8  if_bInterfaceProtocol; */
+	0x00,	    /*	__u8  if_iInterface; */
+
+	/* endpoint */
+	0x07,	    /*	__u8  ep_bLength; */
+	0x05,	    /*	__u8  ep_bDescriptorType; Endpoint */
+	0x81,	    /*	__u8  ep_bEndpointAddress; IN Endpoint 1 */
+	0x03,	    /*	__u8  ep_bmAttributes; Interrupt */
+	0x02,	    /*	__u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+	0x00,
+	0xff	    /*	__u8  ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] =
+{
+	0x04,			/*  __u8  bLength; */
+	0x03,			/*  __u8  bDescriptorType; String-descriptor */
+	0x09,			/*  __u8  lang ID */
+	0x04,			/*  __u8  lang ID */
+};
+
+static unsigned char root_hub_str_index1[] =
+{
+	28,			/*  __u8  bLength; */
+	0x03,			/*  __u8  bDescriptorType; String-descriptor */
+	'O',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'H',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'C',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'I',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	' ',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'R',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'o',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'o',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	't',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	' ',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'H',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'u',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'b',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+};
+
+/* Hub class-specific descriptor is constructed dynamically */
+
+
+/*-------------------------------------------------------------------------*/
+
+#define OK(x)			len = (x); break
+#ifdef DEBUG
+#define WR_RH_STAT(x)		{info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);}
+#define WR_RH_PORTSTAT(x)	{info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);}
+#else
+#define WR_RH_STAT(x)		writel((x), &gohci.regs->roothub.status)
+#define WR_RH_PORTSTAT(x)	writel((x), &gohci.regs->roothub.portstatus[wIndex-1])
+#endif
+#define RD_RH_STAT		roothub_status(&gohci)
+#define RD_RH_PORTSTAT		roothub_portstatus(&gohci,wIndex-1)
+
+/* request to virtual root hub */
+
+int rh_check_port_status(ohci_t *controller)
+{
+	__u32 temp, ndp, i;
+	int res;
+
+	res = -1;
+	temp = roothub_a (controller);
+	ndp = (temp & RH_A_NDP);
+	for (i = 0; i < ndp; i++) {
+		temp = roothub_portstatus (controller, i);
+		/* check for a device disconnect */
+		if (((temp & (RH_PS_PESC | RH_PS_CSC)) ==
+			(RH_PS_PESC | RH_PS_CSC)) &&
+			((temp & RH_PS_CCS) == 0)) {
+			res = i;
+			break;
+		}
+	}
+	return res;
+}
+
+static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+		void *buffer, int transfer_len, struct devrequest *cmd)
+{
+	void * data = buffer;
+	int leni = transfer_len;
+	int len = 0;
+	int stat = 0;
+	__u32 datab[4];
+	__u8 *data_buf = (__u8 *)datab;
+	__u16 bmRType_bReq;
+	__u16 wValue;
+	__u16 wIndex;
+	__u16 wLength;
+
+#ifdef DEBUG
+urb_priv.actual_length = 0;
+pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));
+#endif
+	if (usb_pipeint(pipe)) {
+		info("Root-Hub submit IRQ: NOT implemented");
+		return 0;
+	}
+
+	bmRType_bReq  = cmd->requesttype | (cmd->request << 8);
+	wValue	      = m16_swap (cmd->value);
+	wIndex	      = m16_swap (cmd->index);
+	wLength	      = m16_swap (cmd->length);
+
+	info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x",
+		dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
+
+	switch (bmRType_bReq) {
+	/* Request Destination:
+	   without flags: Device,
+	   RH_INTERFACE: interface,
+	   RH_ENDPOINT: endpoint,
+	   RH_CLASS means HUB here,
+	   RH_OTHER | RH_CLASS	almost ever means HUB_PORT here
+	*/
+
+	case RH_GET_STATUS:
+			*(__u16 *) data_buf = m16_swap (1); OK (2);
+	case RH_GET_STATUS | RH_INTERFACE:
+			*(__u16 *) data_buf = m16_swap (0); OK (2);
+	case RH_GET_STATUS | RH_ENDPOINT:
+			*(__u16 *) data_buf = m16_swap (0); OK (2);
+	case RH_GET_STATUS | RH_CLASS:
+			*(__u32 *) data_buf = m32_swap (
+				RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));
+			OK (4);
+	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+			*(__u32 *) data_buf = m32_swap (RD_RH_PORTSTAT); OK (4);
+
+	case RH_CLEAR_FEATURE | RH_ENDPOINT:
+		switch (wValue) {
+			case (RH_ENDPOINT_STALL): OK (0);
+		}
+		break;
+
+	case RH_CLEAR_FEATURE | RH_CLASS:
+		switch (wValue) {
+			case RH_C_HUB_LOCAL_POWER:
+				OK(0);
+			case (RH_C_HUB_OVER_CURRENT):
+					WR_RH_STAT(RH_HS_OCIC); OK (0);
+		}
+		break;
+
+	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+		switch (wValue) {
+			case (RH_PORT_ENABLE):
+					WR_RH_PORTSTAT (RH_PS_CCS ); OK (0);
+			case (RH_PORT_SUSPEND):
+					WR_RH_PORTSTAT (RH_PS_POCI); OK (0);
+			case (RH_PORT_POWER):
+					WR_RH_PORTSTAT (RH_PS_LSDA); OK (0);
+			case (RH_C_PORT_CONNECTION):
+					WR_RH_PORTSTAT (RH_PS_CSC ); OK (0);
+			case (RH_C_PORT_ENABLE):
+					WR_RH_PORTSTAT (RH_PS_PESC); OK (0);
+			case (RH_C_PORT_SUSPEND):
+					WR_RH_PORTSTAT (RH_PS_PSSC); OK (0);
+			case (RH_C_PORT_OVER_CURRENT):
+					WR_RH_PORTSTAT (RH_PS_OCIC); OK (0);
+			case (RH_C_PORT_RESET):
+					WR_RH_PORTSTAT (RH_PS_PRSC); OK (0);
+		}
+		break;
+
+	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+		switch (wValue) {
+			case (RH_PORT_SUSPEND):
+					WR_RH_PORTSTAT (RH_PS_PSS ); OK (0);
+			case (RH_PORT_RESET): /* BUG IN HUP CODE *********/
+					if (RD_RH_PORTSTAT & RH_PS_CCS)
+					    WR_RH_PORTSTAT (RH_PS_PRS);
+					OK (0);
+			case (RH_PORT_POWER):
+					WR_RH_PORTSTAT (RH_PS_PPS ); OK (0);
+			case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/
+					if (RD_RH_PORTSTAT & RH_PS_CCS)
+					    WR_RH_PORTSTAT (RH_PS_PES );
+					OK (0);
+		}
+		break;
+
+	case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0);
+
+	case RH_GET_DESCRIPTOR:
+		switch ((wValue & 0xff00) >> 8) {
+			case (0x01): /* device descriptor */
+				len = min_t(unsigned int,
+					  leni,
+					  min_t(unsigned int,
+					      sizeof (root_hub_dev_des),
+					      wLength));
+				data_buf = root_hub_dev_des; OK(len);
+			case (0x02): /* configuration descriptor */
+				len = min_t(unsigned int,
+					  leni,
+					  min_t(unsigned int,
+					      sizeof (root_hub_config_des),
+					      wLength));
+				data_buf = root_hub_config_des; OK(len);
+			case (0x03): /* string descriptors */
+				if(wValue==0x0300) {
+					len = min_t(unsigned int,
+						  leni,
+						  min_t(unsigned int,
+						      sizeof (root_hub_str_index0),
+						      wLength));
+					data_buf = root_hub_str_index0;
+					OK(len);
+				}
+				if(wValue==0x0301) {
+					len = min_t(unsigned int,
+						  leni,
+						  min_t(unsigned int,
+						      sizeof (root_hub_str_index1),
+						      wLength));
+					data_buf = root_hub_str_index1;
+					OK(len);
+			}
+			default:
+				stat = USB_ST_STALLED;
+		}
+		break;
+
+	case RH_GET_DESCRIPTOR | RH_CLASS:
+	    {
+		    __u32 temp = roothub_a (&gohci);
+
+		    data_buf [0] = 9;		/* min length; */
+		    data_buf [1] = 0x29;
+		    data_buf [2] = temp & RH_A_NDP;
+		    data_buf [3] = 0;
+		    if (temp & RH_A_PSM)	/* per-port power switching? */
+			data_buf [3] |= 0x1;
+		    if (temp & RH_A_NOCP)	/* no overcurrent reporting? */
+			data_buf [3] |= 0x10;
+		    else if (temp & RH_A_OCPM)	/* per-port overcurrent reporting? */
+			data_buf [3] |= 0x8;
+
+		    /* corresponds to data_buf[4-7] */
+		    datab [1] = 0;
+		    data_buf [5] = (temp & RH_A_POTPGT) >> 24;
+		    temp = roothub_b (&gohci);
+		    data_buf [7] = temp & RH_B_DR;
+		    if (data_buf [2] < 7) {
+			data_buf [8] = 0xff;
+		    } else {
+			data_buf [0] += 2;
+			data_buf [8] = (temp & RH_B_DR) >> 8;
+			data_buf [10] = data_buf [9] = 0xff;
+		    }
+
+		    len = min_t(unsigned int, leni,
+			      min_t(unsigned int, data_buf [0], wLength));
+		    OK (len);
+		}
+
+	case RH_GET_CONFIGURATION:	*(__u8 *) data_buf = 0x01; OK (1);
+
+	case RH_SET_CONFIGURATION:	WR_RH_STAT (0x10000); OK (0);
+
+	default:
+		dbg ("unsupported root hub command");
+		stat = USB_ST_STALLED;
+	}
+
+#ifdef	DEBUG
+	ohci_dump_roothub (&gohci, 1);
+#endif
+
+	len = min_t(int, len, leni);
+	if (data != data_buf)
+	    memcpy (data, data_buf, len);
+	dev->act_len = len;
+	dev->status = stat;
+
+#ifdef DEBUG
+	if (transfer_len)
+		urb_priv.actual_length = transfer_len;
+	pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/);
+#endif
+
+	return stat;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* common code for handling submit messages - used for all but root hub */
+/* accesses. */
+int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		int transfer_len, struct devrequest *setup, int interval)
+{
+	int stat = 0;
+	int maxsize = usb_maxpacket(dev, pipe);
+	int timeout;
+
+	/* device pulled? Shortcut the action. */
+	if (devgone == dev) {
+		dev->status = USB_ST_CRC_ERR;
+		return 0;
+	}
+
+#ifdef DEBUG
+	urb_priv.actual_length = 0;
+	pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
+#endif
+	if (!maxsize) {
+		err("submit_common_message: pipesize for pipe %lx is zero",
+			pipe);
+		return -1;
+	}
+
+	if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < 0) {
+		err("sohci_submit_job failed");
+		return -1;
+	}
+
+	/* allow more time for a BULK device to react - some are slow */
+#define BULK_TO	 5000	/* timeout in milliseconds */
+	if (usb_pipebulk(pipe))
+		timeout = BULK_TO;
+	else
+		timeout = 100;
+
+	/* wait for it to complete */
+	for (;;) {
+		/* check whether the controller is done */
+		stat = hc_interrupt();
+		if (stat < 0) {
+			stat = USB_ST_CRC_ERR;
+			break;
+		}
+
+		/* NOTE: since we are not interrupt driven in U-Boot and always
+		 * handle only one URB at a time, we cannot assume the
+		 * transaction finished on the first successful return from
+		 * hc_interrupt().. unless the flag for current URB is set,
+		 * meaning that all TD's to/from device got actually
+		 * transferred and processed. If the current URB is not
+		 * finished we need to re-iterate this loop so as
+		 * hc_interrupt() gets called again as there needs to be some
+		 * more TD's to process still */
+		if ((stat >= 0) && (stat != 0xff) && (urb_finished)) {
+			/* 0xff is returned for an SF-interrupt */
+			break;
+		}
+
+		if (--timeout) {
+			wait_ms(1);
+			if (!urb_finished)
+				dbg("\%");
+
+		} else {
+			err("CTL:TIMEOUT ");
+			dbg("submit_common_msg: TO status %x\n", stat);
+			stat = USB_ST_CRC_ERR;
+			urb_finished = 1;
+			break;
+		}
+	}
+#if 0
+	/* we got an Root Hub Status Change interrupt */
+	if (got_rhsc) {
+#ifdef DEBUG
+		ohci_dump_roothub (&gohci, 1);
+#endif
+		got_rhsc = 0;
+		/* abuse timeout */
+		timeout = rh_check_port_status(&gohci);
+		if (timeout >= 0) {
+#if 0 /* this does nothing useful, but leave it here in case that changes */
+			/* the called routine adds 1 to the passed value */
+			usb_hub_port_connect_change(gohci.rh.dev, timeout - 1);
+#endif
+			/*
+			 * XXX
+			 * This is potentially dangerous because it assumes
+			 * that only one device is ever plugged in!
+			 */
+			devgone = dev;
+		}
+	}
+#endif
+
+	dev->status = stat;
+	dev->act_len = transfer_len;
+
+#ifdef DEBUG
+	pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe));
+#endif
+
+	/* free TDs in urb_priv */
+	urb_free_priv (&urb_priv);
+	return 0;
+}
+
+/* submit routines called from usb.c */
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		int transfer_len)
+{
+	info("submit_bulk_msg");
+	return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0);
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		int transfer_len, struct devrequest *setup)
+{
+	int maxsize = usb_maxpacket(dev, pipe);
+
+	info("submit_control_msg");
+#ifdef DEBUG
+	urb_priv.actual_length = 0;
+	pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
+#endif
+	if (!maxsize) {
+		err("submit_control_message: pipesize for pipe %lx is zero",
+			pipe);
+		return -1;
+	}
+	if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) {
+		gohci.rh.dev = dev;
+		/* root hub - redirect */
+		return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len,
+			setup);
+	}
+
+	return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0);
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		int transfer_len, int interval)
+{
+	info("submit_int_msg");
+	return -1;
+}
+
+/*-------------------------------------------------------------------------*
+ * HC functions
+ *-------------------------------------------------------------------------*/
+
+/* reset the HC and BUS */
+
+static int hc_reset (ohci_t *ohci)
+{
+	int timeout = 30;
+	int smm_timeout = 50; /* 0,5 sec */
+
+	if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */
+		writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */
+		info("USB HC TakeOver from SMM");
+		while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
+			wait_ms (10);
+			if (--smm_timeout == 0) {
+				err("USB HC TakeOver failed!");
+				return -1;
+			}
+		}
+	}
+
+	/* Disable HC interrupts */
+	writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
+
+	dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;",
+		ohci->slot_name,
+		readl (&ohci->regs->control));
+
+	/* Reset USB (needed by some controllers) */
+	ohci->hc_control = 0;
+	writel (ohci->hc_control, &ohci->regs->control);
+
+	/* HC Reset requires max 10 us delay */
+	writel (OHCI_HCR,  &ohci->regs->cmdstatus);
+	while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
+		if (--timeout == 0) {
+			err("USB HC reset timed out!");
+			return -1;
+		}
+		udelay (1);
+	}
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Start an OHCI controller, set the BUS operational
+ * enable interrupts
+ * connect the virtual root hub */
+
+static int hc_start (ohci_t * ohci)
+{
+	__u32 mask;
+	unsigned int fminterval;
+
+	ohci->disabled = 1;
+
+	/* Tell the controller where the control and bulk lists are
+	 * The lists are empty now. */
+
+	writel (0, &ohci->regs->ed_controlhead);
+	writel (0, &ohci->regs->ed_bulkhead);
+
+	writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */
+
+	fminterval = 0x2edf;
+	writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);
+	fminterval |= ((((fminterval - 210) * 6) / 7) << 16);
+	writel (fminterval, &ohci->regs->fminterval);
+	writel (0x628, &ohci->regs->lsthresh);
+
+	/* start controller operations */
+	ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+	ohci->disabled = 0;
+	writel (ohci->hc_control, &ohci->regs->control);
+
+	/* disable all interrupts */
+	mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD |
+			OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC |
+			OHCI_INTR_OC | OHCI_INTR_MIE);
+	writel (mask, &ohci->regs->intrdisable);
+	/* clear all interrupts */
+	mask &= ~OHCI_INTR_MIE;
+	writel (mask, &ohci->regs->intrstatus);
+	/* Choose the interrupts we care about now  - but w/o MIE */
+	mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO;
+	writel (mask, &ohci->regs->intrenable);
+
+#ifdef	OHCI_USE_NPS
+	/* required for AMD-756 and some Mac platforms */
+	writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM,
+		&ohci->regs->roothub.a);
+	writel (RH_HS_LPSC, &ohci->regs->roothub.status);
+#endif	/* OHCI_USE_NPS */
+
+#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);})
+	/* POTPGT delay is bits 24-31, in 2 ms units. */
+	mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
+
+	/* connect the virtual root hub */
+	ohci->rh.devnum = 0;
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* an interrupt happens */
+
+static int
+hc_interrupt (void)
+{
+	ohci_t *ohci = &gohci;
+	struct ohci_regs *regs = ohci->regs;
+	int ints;
+	int stat = -1;
+
+	if ((ohci->hcca->done_head != 0) &&
+	     !(ohci_cpu_to_le32(ohci->hcca->done_head) & 0x01)) {
+
+		ints =  OHCI_INTR_WDH;
+
+	} else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
+		ohci->disabled++;
+		err ("%s device removed!", ohci->slot_name);
+		return -1;
+
+	} else if ((ints &= readl (&regs->intrenable)) == 0) {
+		dbg("hc_interrupt: returning..\n");
+		return 0xff;
+	}
+
+	/* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */
+
+	if (ints & OHCI_INTR_RHSC) {
+		got_rhsc = 1;
+		stat = 0xff;
+	}
+
+	if (ints & OHCI_INTR_UE) {
+		ohci->disabled++;
+		err ("OHCI Unrecoverable Error, controller usb-%s disabled",
+			ohci->slot_name);
+		/* e.g. due to PCI Master/Target Abort */
+
+#ifdef	DEBUG
+		ohci_dump (ohci, 1);
+#endif
+		/* FIXME: be optimistic, hope that bug won't repeat often. */
+		/* Make some non-interrupt context restart the controller. */
+		/* Count and limit the retries though; either hardware or */
+		/* software errors can go forever... */
+		hc_reset (ohci);
+		return -1;
+	}
+
+	if (ints & OHCI_INTR_WDH) {
+		writel (OHCI_INTR_WDH, &regs->intrdisable);
+		stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci));
+		writel (OHCI_INTR_WDH, &regs->intrenable);
+	}
+
+	if (ints & OHCI_INTR_SO) {
+		dbg("USB Schedule overrun\n");
+		writel (OHCI_INTR_SO, &regs->intrenable);
+		stat = -1;
+	}
+
+	/* FIXME:  this assumes SOF (1/ms) interrupts don't get lost... */
+	if (ints & OHCI_INTR_SF) {
+		unsigned int frame = ohci_cpu_to_le16 (ohci->hcca->frame_no) & 1;
+		wait_ms(1);
+		writel (OHCI_INTR_SF, &regs->intrdisable);
+		if (ohci->ed_rm_list[frame] != NULL)
+			writel (OHCI_INTR_SF, &regs->intrenable);
+		stat = 0xff;
+	}
+
+	writel (ints, &regs->intrstatus);
+	return stat;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+
+/* De-allocate all resources.. */
+
+static void hc_release_ohci (ohci_t *ohci)
+{
+	dbg ("USB HC release ohci usb-%s", ohci->slot_name);
+
+	if (!ohci->disabled)
+		hc_reset (ohci);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * low level initalisation routine, called from usb.c
+ */
+static char ohci_inited = 0;
+
+int usb_lowlevel_init(void)
+{
+
+	/* Set the USB Clock						     */
+	*(vu_long *)MPC5XXX_CDM_48_FDC = CONFIG_USB_CLOCK;
+
+#ifdef CONFIG_PSC3_USB /* USB is using the alternate configuration */
+	/* remove all PSC3 USB bits first before ORing in ours */
+	*(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~0x00804f00;
+#else
+	/* remove all USB bits first before ORing in ours */
+	*(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~0x00807000;
+#endif
+	/* Activate USB port						     */
+	*(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= CONFIG_USB_CONFIG;
+
+	memset (&gohci, 0, sizeof (ohci_t));
+	memset (&urb_priv, 0, sizeof (urb_priv_t));
+
+	/* align the storage */
+	if ((__u32)&ghcca[0] & 0xff) {
+		err("HCCA not aligned!!");
+		return -1;
+	}
+	phcca = &ghcca[0];
+	info("aligned ghcca %p", phcca);
+	memset(&ohci_dev, 0, sizeof(struct ohci_device));
+	if ((__u32)&ohci_dev.ed[0] & 0x7) {
+		err("EDs not aligned!!");
+		return -1;
+	}
+	memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1));
+	if ((__u32)gtd & 0x7) {
+		err("TDs not aligned!!");
+		return -1;
+	}
+	ptd = gtd;
+	gohci.hcca = phcca;
+	memset (phcca, 0, sizeof (struct ohci_hcca));
+
+	gohci.disabled = 1;
+	gohci.sleeping = 0;
+	gohci.irq = -1;
+	gohci.regs = (struct ohci_regs *)MPC5XXX_USB;
+
+	gohci.flags = 0;
+	gohci.slot_name = "mpc5200";
+
+	if (hc_reset (&gohci) < 0) {
+		hc_release_ohci (&gohci);
+		return -1;
+	}
+
+	if (hc_start (&gohci) < 0) {
+		err ("can't start usb-%s", gohci.slot_name);
+		hc_release_ohci (&gohci);
+		return -1;
+	}
+
+#ifdef	DEBUG
+	ohci_dump (&gohci, 1);
+#endif
+	ohci_inited = 1;
+	urb_finished = 1;
+
+	return 0;
+}
+
+int usb_lowlevel_stop(void)
+{
+	/* this gets called really early - before the controller has */
+	/* even been initialized! */
+	if (!ohci_inited)
+		return 0;
+	/* TODO release any interrupts, etc. */
+	/* call hc_release_ohci() here ? */
+	hc_reset (&gohci);
+	return 0;
+}
+
+#endif /* CONFIG_USB_OHCI */
diff --git a/arch/powerpc/cpu/mpc5xxx/usb_ohci.h b/arch/powerpc/cpu/mpc5xxx/usb_ohci.h
new file mode 100644
index 0000000..629b529
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/usb_ohci.h
@@ -0,0 +1,418 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ *
+ * usb-ohci.h
+ */
+
+
+static int cc_to_error[16] = {
+
+/* mapping of the OHCI CC status to error codes */
+	/* No  Error  */	       0,
+	/* CRC Error  */	       USB_ST_CRC_ERR,
+	/* Bit Stuff  */	       USB_ST_BIT_ERR,
+	/* Data Togg  */	       USB_ST_CRC_ERR,
+	/* Stall      */	       USB_ST_STALLED,
+	/* DevNotResp */	       -1,
+	/* PIDCheck   */	       USB_ST_BIT_ERR,
+	/* UnExpPID   */	       USB_ST_BIT_ERR,
+	/* DataOver   */	       USB_ST_BUF_ERR,
+	/* DataUnder  */	       USB_ST_BUF_ERR,
+	/* reservd    */	       -1,
+	/* reservd    */	       -1,
+	/* BufferOver */	       USB_ST_BUF_ERR,
+	/* BuffUnder  */	       USB_ST_BUF_ERR,
+	/* Not Access */	       -1,
+	/* Not Access */	       -1
+};
+
+/* ED States */
+
+#define ED_NEW		0x00
+#define ED_UNLINK	0x01
+#define ED_OPER		0x02
+#define ED_DEL		0x04
+#define ED_URB_DEL	0x08
+
+/* usb_ohci_ed */
+struct ed {
+	__u32 hwINFO;
+	__u32 hwTailP;
+	__u32 hwHeadP;
+	__u32 hwNextED;
+
+	struct ed *ed_prev;
+	__u8 int_period;
+	__u8 int_branch;
+	__u8 int_load;
+	__u8 int_interval;
+	__u8 state;
+	__u8 type;
+	__u16 last_iso;
+	struct ed *ed_rm_list;
+
+	struct usb_device *usb_dev;
+	__u32 unused[3];
+} __attribute__((aligned(16)));
+typedef struct ed ed_t;
+
+
+/* TD info field */
+#define TD_CC	    0xf0000000
+#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
+#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
+#define TD_EC	    0x0C000000
+#define TD_T	    0x03000000
+#define TD_T_DATA0  0x02000000
+#define TD_T_DATA1  0x03000000
+#define TD_T_TOGGLE 0x00000000
+#define TD_R	    0x00040000
+#define TD_DI	    0x00E00000
+#define TD_DI_SET(X) (((X) & 0x07)<< 21)
+#define TD_DP	    0x00180000
+#define TD_DP_SETUP 0x00000000
+#define TD_DP_IN    0x00100000
+#define TD_DP_OUT   0x00080000
+
+#define TD_ISO	    0x00010000
+#define TD_DEL	    0x00020000
+
+/* CC Codes */
+#define TD_CC_NOERROR	   0x00
+#define TD_CC_CRC	   0x01
+#define TD_CC_BITSTUFFING  0x02
+#define TD_CC_DATATOGGLEM  0x03
+#define TD_CC_STALL	   0x04
+#define TD_DEVNOTRESP	   0x05
+#define TD_PIDCHECKFAIL	   0x06
+#define TD_UNEXPECTEDPID   0x07
+#define TD_DATAOVERRUN	   0x08
+#define TD_DATAUNDERRUN	   0x09
+#define TD_BUFFEROVERRUN   0x0C
+#define TD_BUFFERUNDERRUN  0x0D
+#define TD_NOTACCESSED	   0x0F
+
+
+#define MAXPSW 1
+
+struct td {
+	__u32 hwINFO;
+	__u32 hwCBP;		/* Current Buffer Pointer */
+	__u32 hwNextTD;		/* Next TD Pointer */
+	__u32 hwBE;		/* Memory Buffer End Pointer */
+
+	__u8 unused;
+	__u8 index;
+	struct ed *ed;
+	struct td *next_dl_td;
+	struct usb_device *usb_dev;
+	int transfer_len;
+	__u32 data;
+
+	__u32 unused2[2];
+} __attribute__((aligned(32)));
+typedef struct td td_t;
+
+#define OHCI_ED_SKIP	(1 << 14)
+
+/*
+ * The HCCA (Host Controller Communications Area) is a 256 byte
+ * structure defined in the OHCI spec. that the host controller is
+ * told the base address of.  It must be 256-byte aligned.
+ */
+
+#define NUM_INTS 32	/* part of the OHCI standard */
+struct ohci_hcca {
+	__u32	int_table[NUM_INTS];	/* Interrupt ED table */
+	__u16	pad1;			/* set to 0 on each frame_no change */
+	__u16	frame_no;		/* current frame number */
+	__u32	done_head;		/* info returned for an interrupt */
+	u8		reserved_for_hc[116];
+} __attribute__((aligned(256)));
+
+
+/*
+ * Maximum number of root hub ports.
+ */
+#define MAX_ROOT_PORTS	15	/* maximum OHCI root hub ports */
+
+/*
+ * This is the structure of the OHCI controller's memory mapped I/O
+ * region.  This is Memory Mapped I/O.	You must use the readl() and
+ * writel() macros defined in asm/io.h to access these!!
+ */
+struct ohci_regs {
+	/* control and status registers */
+	__u32	revision;
+	__u32	control;
+	__u32	cmdstatus;
+	__u32	intrstatus;
+	__u32	intrenable;
+	__u32	intrdisable;
+	/* memory pointers */
+	__u32	hcca;
+	__u32	ed_periodcurrent;
+	__u32	ed_controlhead;
+	__u32	ed_controlcurrent;
+	__u32	ed_bulkhead;
+	__u32	ed_bulkcurrent;
+	__u32	donehead;
+	/* frame counters */
+	__u32	fminterval;
+	__u32	fmremaining;
+	__u32	fmnumber;
+	__u32	periodicstart;
+	__u32	lsthresh;
+	/* Root hub ports */
+	struct	ohci_roothub_regs {
+		__u32	a;
+		__u32	b;
+		__u32	status;
+		__u32	portstatus[MAX_ROOT_PORTS];
+	} roothub;
+} __attribute__((aligned(32)));
+
+
+/* OHCI CONTROL AND STATUS REGISTER MASKS */
+
+/*
+ * HcControl (control) register masks
+ */
+#define OHCI_CTRL_CBSR	(3 << 0)	/* control/bulk service ratio */
+#define OHCI_CTRL_PLE	(1 << 2)	/* periodic list enable */
+#define OHCI_CTRL_IE	(1 << 3)	/* isochronous enable */
+#define OHCI_CTRL_CLE	(1 << 4)	/* control list enable */
+#define OHCI_CTRL_BLE	(1 << 5)	/* bulk list enable */
+#define OHCI_CTRL_HCFS	(3 << 6)	/* host controller functional state */
+#define OHCI_CTRL_IR	(1 << 8)	/* interrupt routing */
+#define OHCI_CTRL_RWC	(1 << 9)	/* remote wakeup connected */
+#define OHCI_CTRL_RWE	(1 << 10)	/* remote wakeup enable */
+
+/* pre-shifted values for HCFS */
+#	define OHCI_USB_RESET	(0 << 6)
+#	define OHCI_USB_RESUME	(1 << 6)
+#	define OHCI_USB_OPER	(2 << 6)
+#	define OHCI_USB_SUSPEND (3 << 6)
+
+/*
+ * HcCommandStatus (cmdstatus) register masks
+ */
+#define OHCI_HCR	(1 << 0)	/* host controller reset */
+#define OHCI_CLF	(1 << 1)	/* control list filled */
+#define OHCI_BLF	(1 << 2)	/* bulk list filled */
+#define OHCI_OCR	(1 << 3)	/* ownership change request */
+#define OHCI_SOC	(3 << 16)	/* scheduling overrun count */
+
+/*
+ * masks used with interrupt registers:
+ * HcInterruptStatus (intrstatus)
+ * HcInterruptEnable (intrenable)
+ * HcInterruptDisable (intrdisable)
+ */
+#define OHCI_INTR_SO	(1 << 0)	/* scheduling overrun */
+#define OHCI_INTR_WDH	(1 << 1)	/* writeback of done_head */
+#define OHCI_INTR_SF	(1 << 2)	/* start frame */
+#define OHCI_INTR_RD	(1 << 3)	/* resume detect */
+#define OHCI_INTR_UE	(1 << 4)	/* unrecoverable error */
+#define OHCI_INTR_FNO	(1 << 5)	/* frame number overflow */
+#define OHCI_INTR_RHSC	(1 << 6)	/* root hub status change */
+#define OHCI_INTR_OC	(1 << 30)	/* ownership change */
+#define OHCI_INTR_MIE	(1 << 31)	/* master interrupt enable */
+
+
+/* Virtual Root HUB */
+struct virt_root_hub {
+	int devnum; /* Address of Root Hub endpoint */
+	void *dev;  /* was urb */
+	void *int_addr;
+	int send;
+	int interval;
+};
+
+/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
+
+/* destination of request */
+#define RH_INTERFACE		   0x01
+#define RH_ENDPOINT		   0x02
+#define RH_OTHER		   0x03
+
+#define RH_CLASS		   0x20
+#define RH_VENDOR		   0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS		0x0080
+#define RH_CLEAR_FEATURE	0x0100
+#define RH_SET_FEATURE		0x0300
+#define RH_SET_ADDRESS		0x0500
+#define RH_GET_DESCRIPTOR	0x0680
+#define RH_SET_DESCRIPTOR	0x0700
+#define RH_GET_CONFIGURATION	0x0880
+#define RH_SET_CONFIGURATION	0x0900
+#define RH_GET_STATE		0x0280
+#define RH_GET_INTERFACE	0x0A80
+#define RH_SET_INTERFACE	0x0B00
+#define RH_SYNC_FRAME		0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP		0x2000
+
+
+/* Hub port features */
+#define RH_PORT_CONNECTION	   0x00
+#define RH_PORT_ENABLE		   0x01
+#define RH_PORT_SUSPEND		   0x02
+#define RH_PORT_OVER_CURRENT	   0x03
+#define RH_PORT_RESET		   0x04
+#define RH_PORT_POWER		   0x08
+#define RH_PORT_LOW_SPEED	   0x09
+
+#define RH_C_PORT_CONNECTION	   0x10
+#define RH_C_PORT_ENABLE	   0x11
+#define RH_C_PORT_SUSPEND	   0x12
+#define RH_C_PORT_OVER_CURRENT	   0x13
+#define RH_C_PORT_RESET		   0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER	   0x00
+#define RH_C_HUB_OVER_CURRENT	   0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP	   0x00
+#define RH_ENDPOINT_STALL	   0x01
+
+#define RH_ACK			   0x01
+#define RH_REQ_ERR		   -1
+#define RH_NACK			   0x00
+
+
+/* OHCI ROOT HUB REGISTER MASKS */
+
+/* roothub.portstatus [i] bits */
+#define RH_PS_CCS	     0x00000001		/* current connect status */
+#define RH_PS_PES	     0x00000002		/* port enable status*/
+#define RH_PS_PSS	     0x00000004		/* port suspend status */
+#define RH_PS_POCI	     0x00000008		/* port over current indicator */
+#define RH_PS_PRS	     0x00000010		/* port reset status */
+#define RH_PS_PPS	     0x00000100		/* port power status */
+#define RH_PS_LSDA	     0x00000200		/* low speed device attached */
+#define RH_PS_CSC	     0x00010000		/* connect status change */
+#define RH_PS_PESC	     0x00020000		/* port enable status change */
+#define RH_PS_PSSC	     0x00040000		/* port suspend status change */
+#define RH_PS_OCIC	     0x00080000		/* over current indicator change */
+#define RH_PS_PRSC	     0x00100000		/* port reset status change */
+
+/* roothub.status bits */
+#define RH_HS_LPS	     0x00000001		/* local power status */
+#define RH_HS_OCI	     0x00000002		/* over current indicator */
+#define RH_HS_DRWE	     0x00008000		/* device remote wakeup enable */
+#define RH_HS_LPSC	     0x00010000		/* local power status change */
+#define RH_HS_OCIC	     0x00020000		/* over current indicator change */
+#define RH_HS_CRWE	     0x80000000		/* clear remote wakeup enable */
+
+/* roothub.b masks */
+#define RH_B_DR		0x0000ffff		/* device removable flags */
+#define RH_B_PPCM	0xffff0000		/* port power control mask */
+
+/* roothub.a masks */
+#define RH_A_NDP	(0xff << 0)		/* number of downstream ports */
+#define RH_A_PSM	(1 << 8)		/* power switching mode */
+#define RH_A_NPS	(1 << 9)		/* no power switching */
+#define RH_A_DT		(1 << 10)		/* device type (mbz) */
+#define RH_A_OCPM	(1 << 11)		/* over current protection mode */
+#define RH_A_NOCP	(1 << 12)		/* no over current protection */
+#define RH_A_POTPGT	(0xff << 24)		/* power on to power good time */
+
+/* urb */
+#define N_URB_TD 48
+typedef struct
+{
+	ed_t *ed;
+	__u16 length;	/* number of tds associated with this request */
+	__u16 td_cnt;	/* number of tds already serviced */
+	int   state;
+	unsigned long pipe;
+	int actual_length;
+	td_t *td[N_URB_TD];	/* list pointer to all corresponding TDs associated with this request */
+} urb_priv_t;
+#define URB_DEL 1
+
+/*
+ * This is the full ohci controller description
+ *
+ * Note how the "proper" USB information is just
+ * a subset of what the full implementation needs. (Linus)
+ */
+
+
+typedef struct ohci {
+	struct ohci_hcca *hcca;		/* hcca */
+	/*dma_addr_t hcca_dma;*/
+
+	int irq;
+	int disabled;			/* e.g. got a UE, we're hung */
+	int sleeping;
+	unsigned long flags;		/* for HC bugs */
+
+	struct ohci_regs *regs; /* OHCI controller's memory */
+
+	ed_t *ed_rm_list[2];	 /* lists of all endpoints to be removed */
+	ed_t *ed_bulktail;	 /* last endpoint of bulk list */
+	ed_t *ed_controltail;	 /* last endpoint of control list */
+	int intrstatus;
+	__u32 hc_control;		/* copy of the hc control reg */
+	struct usb_device *dev[32];
+	struct virt_root_hub rh;
+
+	const char	*slot_name;
+} ohci_t;
+
+#define NUM_EDS 8		/* num of preallocated endpoint descriptors */
+
+struct ohci_device {
+	ed_t	ed[NUM_EDS];
+	int ed_cnt;
+};
+
+/* hcd */
+/* endpoint */
+static int ep_link(ohci_t * ohci, ed_t * ed);
+static int ep_unlink(ohci_t * ohci, ed_t * ed);
+static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe);
+
+/*-------------------------------------------------------------------------*/
+
+/* we need more TDs than EDs */
+#define NUM_TD 64
+
+/* +1 so we can align the storage */
+td_t gtd[NUM_TD+1];
+/* pointers to aligned storage */
+td_t *ptd;
+
+/* TDs ... */
+static inline struct td *
+td_alloc (struct usb_device *usb_dev)
+{
+	int i;
+	struct td	*td;
+
+	td = NULL;
+	for (i = 0; i < NUM_TD; i++)
+	{
+		if (ptd[i].usb_dev == NULL)
+		{
+			td = &ptd[i];
+			td->usb_dev = usb_dev;
+			break;
+		}
+	}
+
+	return td;
+}
+
+static inline void
+ed_free (struct ed *ed)
+{
+	ed->usb_dev = NULL;
+}
diff --git a/arch/powerpc/cpu/mpc8220/Makefile b/arch/powerpc/cpu/mpc8220/Makefile
new file mode 100644
index 0000000..b4fad28
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/Makefile
@@ -0,0 +1,50 @@
+#
+# (C) Copyright 2003-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(CPU).a
+
+START	= start.o
+SOBJS	= io.o fec_dma_tasks.o
+COBJS	= cpu.o cpu_init.o dramSetup.o fec.o i2c.o \
+	  interrupts.o loadtask.o speed.o \
+	  traps.o uart.o pci.o
+
+SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc8220/config.mk b/arch/powerpc/cpu/mpc8220/config.mk
new file mode 100644
index 0000000..e706883
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/config.mk
@@ -0,0 +1,30 @@
+#
+# (C) Copyright 2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -fPIC -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_MPC8220 -ffixed-r2 \
+		     -mstring -mcpu=603e -mmultiple
+
+# Use default linker script.  Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/arch/powerpc/cpu/mpc8220/u-boot.lds
diff --git a/arch/powerpc/cpu/mpc8220/cpu.c b/arch/powerpc/cpu/mpc8220/cpu.c
new file mode 100644
index 0000000..563cfe0
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/cpu.c
@@ -0,0 +1,104 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * CPU specific code for the MPC8220 CPUs
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc8220.h>
+#include <netdev.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int checkcpu (void)
+{
+	ulong clock = gd->cpu_clk;
+	char buf[32];
+
+	puts ("CPU:   ");
+
+	printf (CPU_ID_STR);
+
+	printf (" (JTAG ID %08lx)", *(vu_long *) (CONFIG_SYS_MBAR + 0x50));
+
+	printf (" at %s MHz\n", strmhz (buf, clock));
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	volatile gptmr8220_t *gptmr = (volatile gptmr8220_t *) MMAP_GPTMR;
+	ulong msr;
+
+	/* Interrupts and MMU off */
+	__asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
+
+	msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
+	__asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
+
+	/* Charge the watchdog timer */
+	gptmr->Prescl = 10;
+	gptmr->Count = 1;
+
+	gptmr->Mode = GPT_TMS_SGPIO;
+
+	gptmr->Control = GPT_CTRL_WDEN | GPT_CTRL_CE;
+
+	return 1;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ *
+ */
+unsigned long get_tbclk (void)
+{
+	ulong tbclk;
+
+	tbclk = (gd->bus_clk + 3L) / 4L;
+
+	return (tbclk);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_MPC8220_FEC)
+	mpc8220_fec_initialize(bis);
+#endif
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8220/cpu_init.c b/arch/powerpc/cpu/mpc8220/cpu_init.c
new file mode 100644
index 0000000..8f52c7d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/cpu_init.c
@@ -0,0 +1,136 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8220.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers.
+ */
+void cpu_init_f (void)
+{
+	volatile flexbus8220_t *flexbus = (volatile flexbus8220_t *) MMAP_FB;
+	volatile pcfg8220_t *portcfg = (volatile pcfg8220_t *) MMAP_PCFG;
+	volatile xlbarb8220_t *xlbarb = (volatile xlbarb8220_t *) MMAP_XLBARB;
+
+	/* Pointer is writable since we allocated a register for it */
+	gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+	/* Clear initial global data */
+	memset ((void *) gd, 0, sizeof (gd_t));
+
+	/* Clear all port configuration */
+	portcfg->pcfg0 = 0;
+	portcfg->pcfg1 = 0;
+	portcfg->pcfg2 = 0;
+	portcfg->pcfg3 = 0;
+	portcfg->pcfg2 = CONFIG_SYS_GP1_PORT2_CONFIG;
+	portcfg->pcfg3 = CONFIG_SYS_PCI_PORT3_CONFIG | CONFIG_SYS_GP2_PORT3_CONFIG;
+
+	/*
+	 * Flexbus Controller: configure chip selects and enable them
+	 */
+#if defined (CONFIG_SYS_CS0_BASE)
+	flexbus->csar0 = CONFIG_SYS_CS0_BASE;
+
+/* Sorcery-C can hang-up after CTRL reg initialization */
+#if defined (CONFIG_SYS_CS0_CTRL)
+	flexbus->cscr0 = CONFIG_SYS_CS0_CTRL;
+#endif
+	flexbus->csmr0 = ((CONFIG_SYS_CS0_MASK - 1) & 0xffff0000) | 1;
+	__asm__ volatile ("sync");
+#endif
+#if defined (CONFIG_SYS_CS1_BASE)
+	flexbus->csar1 = CONFIG_SYS_CS1_BASE;
+	flexbus->cscr1 = CONFIG_SYS_CS1_CTRL;
+	flexbus->csmr1 = ((CONFIG_SYS_CS1_MASK - 1) & 0xffff0000) | 1;
+	__asm__ volatile ("sync");
+#endif
+#if defined (CONFIG_SYS_CS2_BASE)
+	flexbus->csar2 = CONFIG_SYS_CS2_BASE;
+	flexbus->cscr2 = CONFIG_SYS_CS2_CTRL;
+	flexbus->csmr2 = ((CONFIG_SYS_CS2_MASK - 1) & 0xffff0000) | 1;
+	portcfg->pcfg3 |= CONFIG_SYS_CS2_PORT3_CONFIG;
+	__asm__ volatile ("sync");
+#endif
+#if defined (CONFIG_SYS_CS3_BASE)
+	flexbus->csar3 = CONFIG_SYS_CS3_BASE;
+	flexbus->cscr3 = CONFIG_SYS_CS3_CTRL;
+	flexbus->csmr3 = ((CONFIG_SYS_CS3_MASK - 1) & 0xffff0000) | 1;
+	portcfg->pcfg3 |= CONFIG_SYS_CS3_PORT3_CONFIG;
+	__asm__ volatile ("sync");
+#endif
+#if defined (CONFIG_SYS_CS4_BASE)
+	flexbus->csar4 = CONFIG_SYS_CS4_BASE;
+	flexbus->cscr4 = CONFIG_SYS_CS4_CTRL;
+	flexbus->csmr4 = ((CONFIG_SYS_CS4_MASK - 1) & 0xffff0000) | 1;
+	portcfg->pcfg3 |= CONFIG_SYS_CS4_PORT3_CONFIG;
+	__asm__ volatile ("sync");
+#endif
+#if defined (CONFIG_SYS_CS5_BASE)
+	flexbus->csar5 = CONFIG_SYS_CS5_BASE;
+	flexbus->cscr5 = CONFIG_SYS_CS5_CTRL;
+	flexbus->csmr5 = ((CONFIG_SYS_CS5_MASK - 1) & 0xffff0000) | 1;
+	portcfg->pcfg3 |= CONFIG_SYS_CS5_PORT3_CONFIG;
+	__asm__ volatile ("sync");
+#endif
+
+	/* This section of the code cannot place in cpu_init_r(),
+	   it will cause the system to hang */
+	/* enable timebase */
+	xlbarb->addrTenTimeOut = 0x1000;
+	xlbarb->dataTenTimeOut = 0x1000;
+	xlbarb->busActTimeOut = 0x2000;
+
+	xlbarb->config = 0x00002000;
+
+	/* Master Priority Enable */
+	xlbarb->mastPriority = 0;
+	xlbarb->mastPriEn = 0xff;
+}
+
+/*
+ * initialize higher level parts of CPU like time base and timers
+ */
+int cpu_init_r (void)
+{
+	/* this may belongs to disable interrupt section */
+	/* mask all interrupts */
+	*(vu_long *) 0xf0000700 = 0xfffffc00;
+	*(vu_long *) 0xf0000714 |= 0x0001ffff;
+	*(vu_long *) 0xf0000710 &= ~0x00000f00;
+
+	/* route critical ints to normal ints */
+	*(vu_long *) 0xf0000710 |= 0x00000001;
+
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_MPC8220_FEC)
+	/* load FEC microcode */
+	loadtask (0, 2);
+#endif
+	return (0);
+}
diff --git a/arch/powerpc/cpu/mpc8220/dma.h b/arch/powerpc/cpu/mpc8220/dma.h
new file mode 100644
index 0000000..d06ee63
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/dma.h
@@ -0,0 +1,68 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * This file is based on code
+ * (C) Copyright Motorola, Inc., 2000
+ *
+ * MPC8220 dma header file
+ */
+
+#ifndef __MPC8220_DMA_H
+#define __MPC8220_DMA_H
+
+#include <common.h>
+#include <mpc8220.h>
+
+/* Task number assignment */
+#define FEC_RECV_TASK_NO            0
+#define FEC_XMIT_TASK_NO            1
+
+/*---------------------------------------------------------------------
+ * Stuff for Ethernet Tx/Rx tasks
+ *---------------------------------------------------------------------
+ */
+
+/* Layout of Ethernet controller Parameter SRAM area:
+ * ----------------------------------------------------------------
+ * 0x00: TBD_BASE, base address of TX BD ring
+ * 0x04: TBD_NEXT, address of next TX BD to be processed
+ * 0x08: RBD_BASE, base address of RX BD ring
+ * 0x0C: RBD_NEXT, address of next RX BD to be processed
+ * ---------------------------------------------------------------
+ * ALL PARAMETERS ARE ALL LONGWORDS (FOUR BYTES EACH).
+ */
+
+/* base address of SRAM area to store parameters used by Ethernet tasks */
+#define FEC_PARAM_BASE  (MMAP_SRAM + 0x5b00)
+
+/* base address of SRAM area for buffer descriptors */
+#define FEC_BD_BASE     (MMAP_SRAM + 0x5b20)
+
+/*---------------------------------------------------------------------
+ * common shortcuts  used  by driver C code
+ *---------------------------------------------------------------------
+ */
+
+/* Disable SmartDMA task */
+#define DMA_TASK_DISABLE(tasknum)						\
+{										\
+	volatile ushort *tcr = (ushort *)(MMAP_DMA + 0x0000001c + 2 * tasknum); \
+	*tcr = (*tcr) & (~0x8000);						\
+}
+
+/* Enable SmartDMA task */
+#define DMA_TASK_ENABLE(tasknum)						\
+{										\
+	volatile ushort *tcr = (ushort *) (MMAP_DMA + 0x0000001c + 2 * tasknum);\
+	*tcr = (*tcr)  | 0x8000;						\
+}
+
+/* Clear interrupt pending bits */
+#define DMA_CLEAR_IEVENT(tasknum)						\
+{										\
+	struct mpc8220_dma *dma = (struct mpc8220_dma *)MMAP_DMA;		\
+	dma->IntPend = (1 << tasknum);						\
+}
+
+#endif  /* __MPC8220_DMA_H */
diff --git a/arch/powerpc/cpu/mpc8220/dramSetup.c b/arch/powerpc/cpu/mpc8220/dramSetup.c
new file mode 100644
index 0000000..52cf133
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/dramSetup.c
@@ -0,0 +1,752 @@
+/*
+ * (C) Copyright 2004, Freescale, Inc
+ * TsiChung Liew, Tsi-Chung.Liew@freescale.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+DESCRIPTION
+Read Dram spd and base on its information to calculate the memory size,
+characteristics to initialize the dram on MPC8220
+*/
+
+#include <common.h>
+#include <mpc8220.h>
+#include "i2cCore.h"
+#include "dramSetup.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define SPD_SIZE	CONFIG_SYS_SDRAM_SPD_SIZE
+#define DRAM_SPD	(CONFIG_SYS_SDRAM_SPD_I2C_ADDR)<<1	/* on Board SPD eeprom */
+#define TOTAL_BANK	CONFIG_SYS_SDRAM_TOTAL_BANKS
+
+int spd_status (volatile i2c8220_t * pi2c, u8 sta_bit, u8 truefalse)
+{
+	int i;
+
+	for (i = 0; i < I2C_POLL_COUNT; i++) {
+		if ((pi2c->sr & sta_bit) == (truefalse ? sta_bit : 0))
+			return (OK);
+	}
+
+	return (ERROR);
+}
+
+int spd_clear (volatile i2c8220_t * pi2c)
+{
+	pi2c->adr = 0;
+	pi2c->fdr = 0;
+	pi2c->cr = 0;
+	pi2c->sr = 0;
+
+	return (OK);
+}
+
+int spd_stop (volatile i2c8220_t * pi2c)
+{
+	pi2c->cr &= ~I2C_CTL_STA;	/* Generate stop signal         */
+	if (spd_status (pi2c, I2C_STA_BB, 0) != OK)
+		return ERROR;
+
+	return (OK);
+}
+
+int spd_readbyte (volatile i2c8220_t * pi2c, u8 * readb, int *index)
+{
+	pi2c->sr &= ~I2C_STA_IF;	/* Clear Interrupt Bit          */
+	*readb = pi2c->dr;	/* Read a byte                  */
+
+	/*
+	   Set I2C_CTRL_TXAK will cause Transfer pending and
+	   set I2C_CTRL_STA will cause Interrupt pending
+	 */
+	if (*index != 2) {
+		if (spd_status (pi2c, I2C_STA_CF, 1) != OK)	/* Transfer not complete?       */
+			return ERROR;
+	}
+
+	if (*index != 1) {
+		if (spd_status (pi2c, I2C_STA_IF, 1) != OK)
+			return ERROR;
+	}
+
+	return (OK);
+}
+
+int readSpdData (u8 * spdData)
+{
+	volatile i2c8220_t *pi2cReg;
+	volatile pcfg8220_t *pcfg;
+	u8 slvAdr = DRAM_SPD;
+	u8 Tmp;
+	int Length = SPD_SIZE;
+	int i = 0;
+
+	/* Enable Port Configuration for SDA and SDL signals */
+	pcfg = (volatile pcfg8220_t *) (MMAP_PCFG);
+	__asm__ ("sync");
+	pcfg->pcfg3 &= ~CONFIG_SYS_I2C_PORT3_CONFIG;
+	__asm__ ("sync");
+
+	/* Points the structure to I2c mbar memory offset */
+	pi2cReg = (volatile i2c8220_t *) (MMAP_I2C);
+
+
+	/* Clear FDR, ADR, SR and CR reg */
+	pi2cReg->adr = 0;
+	pi2cReg->fdr = 0;
+	pi2cReg->cr = 0;
+	pi2cReg->sr = 0;
+
+	/* Set for fix XLB Bus Frequency */
+	switch (gd->bus_clk) {
+	case 60000000:
+		pi2cReg->fdr = 0x15;
+		break;
+	case 70000000:
+		pi2cReg->fdr = 0x16;
+		break;
+	case 80000000:
+		pi2cReg->fdr = 0x3a;
+		break;
+	case 90000000:
+		pi2cReg->fdr = 0x17;
+		break;
+	case 100000000:
+		pi2cReg->fdr = 0x3b;
+		break;
+	case 110000000:
+		pi2cReg->fdr = 0x18;
+		break;
+	case 120000000:
+		pi2cReg->fdr = 0x19;
+		break;
+	case 130000000:
+		pi2cReg->fdr = 0x1a;
+		break;
+	}
+
+	pi2cReg->adr = CONFIG_SYS_I2C_SLAVE<<1;
+
+	pi2cReg->cr = I2C_CTL_EN;	/* Set Enable         */
+
+	/*
+	   The I2C bus should be in Idle state. If the bus is busy,
+	   clear the STA bit in control register
+	 */
+	if (spd_status (pi2cReg, I2C_STA_BB, 0) != OK) {
+		if ((pi2cReg->cr & I2C_CTL_STA) == I2C_CTL_STA)
+			pi2cReg->cr &= ~I2C_CTL_STA;
+
+		/* Check again if it is still busy, return error if found */
+		if (spd_status (pi2cReg, I2C_STA_BB, 1) == OK)
+			return ERROR;
+	}
+
+	pi2cReg->cr |= I2C_CTL_TX;	/* Enable the I2c for TX, Ack   */
+	pi2cReg->cr |= I2C_CTL_STA;	/* Generate start signal        */
+
+	if (spd_status (pi2cReg, I2C_STA_BB, 1) != OK)
+		return ERROR;
+
+
+	/* Write slave address */
+	pi2cReg->sr &= ~I2C_STA_IF;	/* Clear Interrupt              */
+	pi2cReg->dr = slvAdr;	/* Write a byte                 */
+
+	if (spd_status (pi2cReg, I2C_STA_CF, 1) != OK) {	/* Transfer not complete?       */
+		spd_stop (pi2cReg);
+		return ERROR;
+	}
+
+	if (spd_status (pi2cReg, I2C_STA_IF, 1) != OK) {
+		spd_stop (pi2cReg);
+		return ERROR;
+	}
+
+
+	/* Issue the offset to start */
+	pi2cReg->sr &= ~I2C_STA_IF;	/* Clear Interrupt              */
+	pi2cReg->dr = 0;	/* Write a byte                 */
+
+	if (spd_status (pi2cReg, I2C_STA_CF, 1) != OK) {	/* Transfer not complete?       */
+		spd_stop (pi2cReg);
+		return ERROR;
+	}
+
+	if (spd_status (pi2cReg, I2C_STA_IF, 1) != OK) {
+		spd_stop (pi2cReg);
+		return ERROR;
+	}
+
+
+	/* Set repeat start */
+	pi2cReg->cr |= I2C_CTL_RSTA;	/* Repeat Start                 */
+
+	pi2cReg->sr &= ~I2C_STA_IF;	/* Clear Interrupt              */
+	pi2cReg->dr = slvAdr | 1;	/* Write a byte                 */
+
+	if (spd_status (pi2cReg, I2C_STA_CF, 1) != OK) {	/* Transfer not complete?       */
+		spd_stop (pi2cReg);
+		return ERROR;
+	}
+
+	if (spd_status (pi2cReg, I2C_STA_IF, 1) != OK) {
+		spd_stop (pi2cReg);
+		return ERROR;
+	}
+
+	if (((pi2cReg->sr & 0x07) == 0x07) || (pi2cReg->sr & 0x01))
+		return ERROR;
+
+	pi2cReg->cr &= ~I2C_CTL_TX;	/* Set receive mode             */
+
+	if (((pi2cReg->sr & 0x07) == 0x07) || (pi2cReg->sr & 0x01))
+		return ERROR;
+
+	/* Dummy Read */
+	if (spd_readbyte (pi2cReg, &Tmp, &i) != OK) {
+		spd_stop (pi2cReg);
+		return ERROR;
+	}
+
+	i = 0;
+	while (Length) {
+		if (Length == 2)
+			pi2cReg->cr |= I2C_CTL_TXAK;
+
+		if (Length == 1)
+			pi2cReg->cr &= ~I2C_CTL_STA;
+
+		if (spd_readbyte (pi2cReg, spdData, &Length) != OK) {
+			return spd_stop (pi2cReg);
+		}
+		i++;
+		Length--;
+		spdData++;
+	}
+
+	/* Stop the service */
+	spd_stop (pi2cReg);
+
+	return OK;
+}
+
+int getBankInfo (int bank, draminfo_t * pBank)
+{
+	int status;
+	int checksum;
+	int count;
+	u8 spdData[SPD_SIZE];
+
+
+	if (bank > 2 || pBank == 0) {
+		/* illegal values */
+		return (-42);
+	}
+
+	status = readSpdData (&spdData[0]);
+	if (status < 0)
+		return (-1);
+
+	/* check the checksum */
+	for (count = 0, checksum = 0; count < LOC_CHECKSUM; count++)
+		checksum += spdData[count];
+
+	checksum = checksum - ((checksum / 256) * 256);
+
+	if (checksum != spdData[LOC_CHECKSUM])
+		return (-2);
+
+	/* Get the memory type */
+	if (!
+	    ((spdData[LOC_TYPE] == TYPE_DDR)
+	     || (spdData[LOC_TYPE] == TYPE_SDR)))
+		/* not one of the types we support */
+		return (-3);
+
+	pBank->type = spdData[LOC_TYPE];
+
+	/* Set logical banks */
+	pBank->banks = spdData[LOC_LOGICAL_BANKS];
+
+	/* Check that we have enough physical banks to cover the bank we are
+	 * figuring out.  Odd-numbered banks correspond to the second bank
+	 * on the device.
+	 */
+	if (bank & 1) {
+		/* Second bank of a "device" */
+		if (spdData[LOC_PHYS_BANKS] < 2)
+			/* this bank doesn't exist on the "device" */
+			return (-4);
+
+		if (spdData[LOC_ROWS] & 0xf0)
+			/* Two asymmetric banks */
+			pBank->rows = spdData[LOC_ROWS] >> 4;
+		else
+			pBank->rows = spdData[LOC_ROWS];
+
+		if (spdData[LOC_COLS] & 0xf0)
+			/* Two asymmetric banks */
+			pBank->cols = spdData[LOC_COLS] >> 4;
+		else
+			pBank->cols = spdData[LOC_COLS];
+	} else {
+		/* First bank of a "device" */
+		pBank->rows = spdData[LOC_ROWS];
+		pBank->cols = spdData[LOC_COLS];
+	}
+
+	pBank->width = spdData[LOC_WIDTH_HIGH] << 8 | spdData[LOC_WIDTH_LOW];
+	pBank->bursts = spdData[LOC_BURSTS];
+	pBank->CAS = spdData[LOC_CAS];
+	pBank->CS = spdData[LOC_CS];
+	pBank->WE = spdData[LOC_WE];
+	pBank->Trp = spdData[LOC_Trp];
+	pBank->Trcd = spdData[LOC_Trcd];
+	pBank->buffered = spdData[LOC_Buffered] & 1;
+	pBank->refresh = spdData[LOC_REFRESH];
+
+	return (0);
+}
+
+
+/* checkMuxSetting -- given a row/column device geometry, return a mask
+ *                    of the valid DRAM controller addr_mux settings for
+ *                    that geometry.
+ *
+ *  Arguments:        u8 rows:     number of row addresses in this device
+ *                    u8 columns:  number of column addresses in this device
+ *
+ *  Returns:          a mask of the allowed addr_mux settings for this
+ *                    geometry.  Each bit in the mask represents a
+ *                    possible addr_mux settings (for example, the
+ *                    (1<<2) bit in the mask represents the 0b10 setting)/
+ *
+ */
+u8 checkMuxSetting (u8 rows, u8 columns)
+{
+	muxdesc_t *pIdx, *pMux;
+	u8 mask;
+	int lrows, lcolumns;
+	u32 mux[4] = { 0x00080c04, 0x01080d03, 0x02080e02, 0xffffffff };
+
+	/* Setup MuxDescriptor in SRAM space */
+	/* MUXDESC AddressRuns [] = {
+	   { 0, 8, 12, 4 },         / setting, columns, rows, extra columns /
+	   { 1, 8, 13, 3 },         / setting, columns, rows, extra columns /
+	   { 2, 8, 14, 2 },         / setting, columns, rows, extra columns /
+	   { 0xff }                 / list terminator /
+	   }; */
+
+	pIdx = (muxdesc_t *) & mux[0];
+
+	/* Check rows x columns against each possible address mux setting */
+	for (pMux = pIdx, mask = 0;; pMux++) {
+		lrows = rows;
+		lcolumns = columns;
+
+		if (pMux->MuxValue == 0xff)
+			break;	/* end of list */
+
+		/* For a given mux setting, since we want all the memory in a
+		 * device to be contiguous, we want the device "use up" the
+		 * address lines such that there are no extra column or row
+		 * address lines on the device.
+		 */
+
+		lcolumns -= pMux->Columns;
+		if (lcolumns < 0)
+			/* Not enough columns to get to the rows */
+			continue;
+
+		lrows -= pMux->Rows;
+		if (lrows > 0)
+			/* we have extra rows left -- can't do that! */
+			continue;
+
+		/* At this point, we either have to have used up all the
+		 * rows or we have to have no columns left.
+		 */
+
+		if (lcolumns != 0 && lrows != 0)
+			/* rows AND columns are left.  Bad! */
+			continue;
+
+		lcolumns -= pMux->MoreColumns;
+
+		if (lcolumns <= 0)
+			mask |= (1 << pMux->MuxValue);
+	}
+
+	return (mask);
+}
+
+
+u32 dramSetup (void)
+{
+	draminfo_t DramInfo[TOTAL_BANK];
+	draminfo_t *pDramInfo;
+	u32 size, temp, cfg_value, mode_value, refresh;
+	u8 *ptr;
+	u8 bursts, Trp, Trcd, type, buffered;
+	u8 muxmask, rows, columns;
+	int count, banknum;
+	u32 *prefresh, *pIdx;
+	u32 refrate[8] = { 15625, 3900, 7800, 31300,
+		62500, 125000, 0xffffffff, 0xffffffff
+	};
+	volatile sysconf8220_t *sysconf;
+	volatile memctl8220_t *memctl;
+
+	sysconf = (volatile sysconf8220_t *) MMAP_MBAR;
+	memctl = (volatile memctl8220_t *) MMAP_MEMCTL;
+
+	/* Set everything in the descriptions to zero */
+	ptr = (u8 *) & DramInfo[0];
+	for (count = 0; count < sizeof (DramInfo); count++)
+		*ptr++ = 0;
+
+	for (banknum = 0; banknum < TOTAL_BANK; banknum++)
+		sysconf->cscfg[banknum];
+
+	/* Descriptions of row/column address muxing for various
+	 * addr_mux settings.
+	 */
+
+	pIdx = prefresh = (u32 *) & refrate[0];
+
+	/* Get all the info for all three logical banks */
+	bursts = 0xff;
+	Trp = 0;
+	Trcd = 0;
+	type = 0;
+	buffered = 0xff;
+	refresh = 0xffffffff;
+	muxmask = 0xff;
+
+	/* Two bank, CS0 and CS1 */
+	for (banknum = 0, pDramInfo = &DramInfo[0];
+	     banknum < TOTAL_BANK; banknum++, pDramInfo++) {
+		pDramInfo->ordinal = banknum;	/* initial sorting */
+		if (getBankInfo (banknum, pDramInfo) < 0)
+			continue;
+
+		/* get cumulative parameters of all three banks */
+		if (type && pDramInfo->type != type)
+			return 0;
+
+		type = pDramInfo->type;
+		rows = pDramInfo->rows;
+		columns = pDramInfo->cols;
+
+		/* This chip only supports 13 DRAM memory lines, but some devices
+		 * have 14 rows.  To deal with this, ignore the 14th address line
+		 * by limiting the number of rows (and columns) to 13.  This will
+		 * mean that for 14-row devices we will only be able to use
+		 * half of the memory, but it's better than nothing.
+		 */
+		if (rows > 13)
+			rows = 13;
+		if (columns > 13)
+			columns = 13;
+
+		pDramInfo->size =
+			((1 << (rows + columns)) * pDramInfo->width);
+		pDramInfo->size *= pDramInfo->banks;
+		pDramInfo->size >>= 3;
+
+		/* figure out which addr_mux configurations will support this device */
+		muxmask &= checkMuxSetting (rows, columns);
+		if (muxmask == 0)
+			return 0;
+
+		buffered = pDramInfo->buffered;
+		bursts &= pDramInfo->bursts;	/* union of all bursts */
+		if (pDramInfo->Trp > Trp)	/* worst case (longest) Trp */
+			Trp = pDramInfo->Trp;
+
+		if (pDramInfo->Trcd > Trcd)	/* worst case (longest) Trcd */
+			Trcd = pDramInfo->Trcd;
+
+		prefresh = pIdx;
+		/* worst case (shortest) Refresh period */
+		if (refresh > prefresh[pDramInfo->refresh & 7])
+			refresh = prefresh[pDramInfo->refresh & 7];
+
+	}			/* for loop */
+
+
+	/* We only allow a burst length of 8! */
+	if (!(bursts & 8))
+		bursts = 8;
+
+	/* Sort the devices.  In order to get each chip select region
+	 * aligned properly, put the biggest device at the lowest address.
+	 * A simple bubble sort will do the trick.
+	 */
+	for (banknum = 0, pDramInfo = &DramInfo[0];
+	     banknum < TOTAL_BANK; banknum++, pDramInfo++) {
+		int i;
+
+		for (i = 0; i < TOTAL_BANK; i++) {
+			if (pDramInfo->size < DramInfo[i].size &&
+			    pDramInfo->ordinal < DramInfo[i].ordinal) {
+				/* If the current bank is smaller, but if the ordinal is also
+				 * smaller, swap the ordinals
+				 */
+				u8 temp8;
+
+				temp8 = DramInfo[i].ordinal;
+				DramInfo[i].ordinal = pDramInfo->ordinal;
+				pDramInfo->ordinal = temp8;
+			}
+		}
+	}
+
+
+	/* Now figure out the base address for each bank.  While
+	 * we're at it, figure out how much memory there is.
+	 *
+	 */
+	size = 0;
+	for (banknum = 0; banknum < TOTAL_BANK; banknum++) {
+		int i;
+
+		for (i = 0; i < TOTAL_BANK; i++) {
+			if (DramInfo[i].ordinal == banknum
+			    && DramInfo[i].size != 0) {
+				DramInfo[i].base = size;
+				size += DramInfo[i].size;
+			}
+		}
+	}
+
+	/* Set up the Drive Strength register */
+	sysconf->sdramds = CONFIG_SYS_SDRAM_DRIVE_STRENGTH;
+
+	/* ********************** Cfg 1 ************************* */
+
+	/* Set the single read to read/write/precharge delay */
+	cfg_value = CFG1_SRD2RWP ((type == TYPE_DDR) ? 7 : 0xb);
+
+	/* Set the single write to read/write/precharge delay.
+	 * This may or may not be correct.  The controller spec
+	 * says "tWR", but "tWR" does not appear in the SPD.  It
+	 * always seems to be 15nsec for the class of device we're
+	 * using, which turns out to be 2 clock cycles at 133MHz,
+	 * so that's what we're going to use.
+	 *
+	 * HOWEVER, because of a bug in the controller, for DDR
+	 * we need to set this to be the same as the value
+	 * calculated for bwt2rwp.
+	 */
+	cfg_value |= CFG1_SWT2RWP ((type == TYPE_DDR) ? 7 : 2);
+
+	/* Set the Read CAS latency.  We're going to use a CL of
+	 * 2.5 for DDR and 2 SDR.
+	 */
+	cfg_value |= CFG1_RLATENCY ((type == TYPE_DDR) ? 7 : 2);
+
+
+	/* Set the Active to Read/Write delay.  This depends
+	 * on Trcd which is reported as nanoseconds times 4.
+	 * We want to calculate Trcd (in nanoseconds) times XLB clock (in Hz)
+	 * which gives us a dimensionless quantity.  Play games with
+	 * the divisions so we don't run out of dynamic ranges.
+	 */
+	/* account for megaherz and the times 4 */
+	temp = (Trcd * (gd->bus_clk / 1000000)) / 4;
+
+	/* account for nanoseconds and round up, with a minimum value of 2 */
+	temp = ((temp + 999) / 1000) - 1;
+	if (temp < 2)
+		temp = 2;
+
+	cfg_value |= CFG1_ACT2WR (temp);
+
+	/* Set the precharge to active delay.  This depends
+	 * on Trp which is reported as nanoseconds times 4.
+	 * We want to calculate Trp (in nanoseconds) times XLB clock (in Hz)
+	 * which gives us a dimensionless quantity.  Play games with
+	 * the divisions so we don't run out of dynamic ranges.
+	 */
+	/* account for megaherz and the times 4 */
+	temp = (Trp * (gd->bus_clk / 1000000)) / 4;
+
+	/* account for nanoseconds and round up, then subtract 1, with a
+	 * minumum value of 1 and a maximum value of 7.
+	 */
+	temp = (((temp + 999) / 1000) - 1) & 7;
+	if (temp < 1)
+		temp = 1;
+
+	cfg_value |= CFG1_PRE2ACT (temp);
+
+	/* Set refresh to active delay.  This depends
+	 * on Trfc which is not reported in the SPD.
+	 * We'll use a nominal value of 75nsec which is
+	 * what the controller spec uses.
+	 */
+	temp = (75 * (gd->bus_clk / 1000000));
+	/* account for nanoseconds and round up, then subtract 1 */
+	cfg_value |= CFG1_REF2ACT (((temp + 999) / 1000) - 1);
+
+	/* Set the write latency, using the values given in the controller spec */
+	cfg_value |= CFG1_WLATENCY ((type == TYPE_DDR) ? 3 : 0);
+	memctl->cfg1 = cfg_value;	/* cfg 1 */
+	asm volatile ("sync");
+
+
+	/* ********************** Cfg 2 ************************* */
+
+	/* Set the burst read to read/precharge delay */
+	cfg_value = CFG2_BRD2RP ((type == TYPE_DDR) ? 5 : 8);
+
+	/* Set the burst write to read/precharge delay.  Semi-magic numbers
+	 * based on the controller spec recommendations, assuming tWR is
+	 * two clock cycles.
+	 */
+	cfg_value |= CFG2_BWT2RWP ((type == TYPE_DDR) ? 7 : 10);
+
+	/* Set the Burst read to write delay.  Semi-magic numbers
+	 * based on the DRAM controller documentation.
+	 */
+	cfg_value |= CFG2_BRD2WT ((type == TYPE_DDR) ? 7 : 0xb);
+
+	/* Set the burst length -- must be 8!! Well, 7, actually, becuase
+	 * it's burst lenght minus 1.
+	 */
+	cfg_value |= CFG2_BURSTLEN (7);
+	memctl->cfg2 = cfg_value;	/* cfg 2 */
+	asm volatile ("sync");
+
+
+	/* ********************** mode ************************* */
+
+	/* Set enable bit, CKE high/low bits, and the DDR/SDR mode bit,
+	 * disable automatic refresh.
+	 */
+	cfg_value = CTL_MODE_ENABLE | CTL_CKE_HIGH |
+		((type == TYPE_DDR) ? CTL_DDR_MODE : 0);
+
+	/* Set the address mux based on whichever setting(s) is/are common
+	 * to all the devices we have.  If there is more than one, choose
+	 * one arbitrarily.
+	 */
+	if (muxmask & 0x4)
+		cfg_value |= CTL_ADDRMUX (2);
+	else if (muxmask & 0x2)
+		cfg_value |= CTL_ADDRMUX (1);
+	else
+		cfg_value |= CTL_ADDRMUX (0);
+
+	/* Set the refresh interval. */
+	temp = ((refresh * (gd->bus_clk / 1000000)) / (1000 * 64)) - 1;
+	cfg_value |= CTL_REFRESH_INTERVAL (temp);
+
+	/* Set buffered/non-buffered memory */
+	if (buffered)
+		cfg_value |= CTL_BUFFERED;
+
+	memctl->ctrl = cfg_value;	/* ctrl */
+	asm volatile ("sync");
+
+	if (type == TYPE_DDR) {
+		/* issue precharge all */
+		temp = cfg_value | CTL_PRECHARGE_CMD;
+		memctl->ctrl = temp;	/* ctrl */
+		asm volatile ("sync");
+	}
+
+
+	/* Set up mode value for CAS latency */
+#if (CONFIG_SYS_SDRAM_CAS_LATENCY==5) /* CL=2.5 */
+	mode_value = (MODE_MODE | MODE_BURSTLEN (MODE_BURSTLEN_8) |
+		MODE_BT_SEQUENTIAL | MODE_CL (MODE_CL_2p5) | MODE_CMD);
+#else
+	mode_value = (MODE_MODE | MODE_BURSTLEN (MODE_BURSTLEN_8) |
+		      MODE_BT_SEQUENTIAL | MODE_CL (MODE_CL_2) | MODE_CMD);
+#endif
+	asm volatile ("sync");
+
+	/* Write Extended Mode  - enable DLL */
+	if (type == TYPE_DDR) {
+		temp = MODE_EXTENDED | MODE_X_DLL_ENABLE |
+			MODE_X_DS_NORMAL | MODE_CMD;
+		memctl->mode = (temp >> 16);	/* mode */
+		asm volatile ("sync");
+
+		/* Write Mode - reset DLL, set CAS latency */
+		temp = mode_value | MODE_OPMODE (MODE_OPMODE_RESETDLL);
+		memctl->mode = (temp >> 16);	/* mode */
+		asm volatile ("sync");
+	}
+
+	/* Program the chip selects. */
+	for (banknum = 0; banknum < TOTAL_BANK; banknum++) {
+		if (DramInfo[banknum].size != 0) {
+			u32 mask;
+			int i;
+
+			for (i = 0, mask = 1; i < 32; mask <<= 1, i++) {
+				if (DramInfo[banknum].size & mask)
+					break;
+			}
+			temp = (DramInfo[banknum].base & 0xfff00000) | (i -
+									1);
+
+			sysconf->cscfg[banknum] = temp;
+			asm volatile ("sync");
+		}
+	}
+
+	/* Wait for DLL lock */
+	udelay (200);
+
+	temp = cfg_value | CTL_PRECHARGE_CMD;	/* issue precharge all */
+	memctl->ctrl = temp;	/* ctrl */
+	asm volatile ("sync");
+
+	temp = cfg_value | CTL_REFRESH_CMD;	/* issue precharge all */
+	memctl->ctrl = temp;	/* ctrl */
+	asm volatile ("sync");
+
+	memctl->ctrl = temp;	/* ctrl */
+	asm volatile ("sync");
+
+	/* Write Mode - DLL normal */
+	temp = mode_value | MODE_OPMODE (MODE_OPMODE_NORMAL);
+	memctl->mode = (temp >> 16);	/* mode */
+	asm volatile ("sync");
+
+	/* Enable refresh, enable DQS's (if DDR), and lock the control register */
+	cfg_value &= ~CTL_MODE_ENABLE;	/* lock register */
+	cfg_value |= CTL_REFRESH_ENABLE;	/* enable refresh */
+
+	if (type == TYPE_DDR)
+		cfg_value |= CTL_DQSOEN (0xf);	/* enable DQS's for DDR */
+
+	memctl->ctrl = cfg_value;	/* ctrl */
+	asm volatile ("sync");
+
+	return size;
+}
diff --git a/arch/powerpc/cpu/mpc8220/dramSetup.h b/arch/powerpc/cpu/mpc8220/dramSetup.h
new file mode 100644
index 0000000..3b64e08
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/dramSetup.h
@@ -0,0 +1,108 @@
+/*
+ * dramSetup.h
+ *
+ * Prototypes, etc. for the Motorola MPC8220
+ * embedded cpu chips
+ *
+ * 2004 (c) Freescale, Inc.
+ * Author: TsiChung Liew <Tsi-Chung.Liew@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __INCdramsetuph
+#define __INCdramsetuph
+#ifndef __ASSEMBLY__
+/* Where various things are in the SPD */
+#define LOC_TYPE                    2
+#define LOC_CHECKSUM                63
+#define LOC_PHYS_BANKS              5
+#define LOC_LOGICAL_BANKS           17
+#define LOC_ROWS                    3
+#define LOC_COLS                    4
+#define LOC_WIDTH_HIGH              7
+#define LOC_WIDTH_LOW               6
+#define LOC_REFRESH                 12
+#define LOC_BURSTS                  16
+#define LOC_CAS                     18
+#define LOC_CS                      19
+#define LOC_WE                      20
+#define LOC_Tcyc                    9
+#define LOC_Tac                     10
+#define LOC_Trp                     27
+#define LOC_Trrd                    28
+#define LOC_Trcd                    29
+#define LOC_Tras                    30
+#define LOC_Buffered                21
+/* Types of memory the SPD can tell us about.
+ * We can actually only use SDRAM and DDR.
+ */
+#define TYPE_DRAM                   1	/* plain old dram */
+#define TYPE_EDO                    2	/* EDO dram */
+#define TYPE_Nibble                 3	/* serial nibble memory */
+#define TYPE_SDR                    4	/* SDRAM */
+#define TYPE_ROM                    5	/*  */
+#define TYPE_SGRRAM                 6	/* graphics memory */
+#define TYPE_DDR                    7	/* DDR sdram */
+#define SDRAMDS_MASK        0x3	/* each field is 2 bits wide */
+#define SDRAMDS_SBE_SHIFT     8	/* Clock enable drive strength */
+#define SDRAMDS_SBC_SHIFT     6	/* Clocks drive strength */
+#define SDRAMDS_SBA_SHIFT     4	/* Address drive strength */
+#define SDRAMDS_SBS_SHIFT     2	/* SDR DQS drive strength */
+#define SDRAMDS_SBD_SHIFT     0	/* Data and DQS drive strength */
+#define  DRIVE_STRENGTH_HIGH 0
+#define  DRIVE_STRENGTH_MED  1
+#define  DRIVE_STRENGTH_LOW  2
+#define  DRIVE_STRENGTH_OFF  3
+
+#define OK      0
+#define ERROR   -1
+/* Structure to hold information about address muxing. */
+	typedef struct tagMuxDescriptor {
+	u8 MuxValue;
+	u8 Columns;
+	u8 Rows;
+	u8 MoreColumns;
+} muxdesc_t;
+
+/* Structure to define one physical bank of
+ * memory.  Note that dram size in bytes is
+ * (2^^(rows+columns)) * width * banks / 8
+*/
+typedef struct tagDramInfo {
+	u32 size;		/* size in bytes */
+	u32 base;		/* base address */
+	u8 ordinal;		/* where in the memory map will we put this */
+	u8 type;
+	u8 rows;
+	u8 cols;
+	u16 width;		/* width of each chip in bits */
+	u8 banks;		/* number of chips, aka logical banks */
+	u8 bursts;		/* bit-encoded allowable burst length */
+	u8 CAS;			/* bit-encoded CAS latency values */
+	u8 CS;			/* bit-encoded CS latency values */
+	u8 WE;			/* bit-encoded WE latency values */
+	u8 Trp;			/* bit-encoded row precharge time */
+	u8 Trcd;		/* bit-encoded RAS to CAS delay */
+	u8 buffered;		/* buffered or not */
+	u8 refresh;		/* encoded refresh rate */
+} draminfo_t;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __INCdramsetuph */
diff --git a/arch/powerpc/cpu/mpc8220/fec.c b/arch/powerpc/cpu/mpc8220/fec.c
new file mode 100644
index 0000000..992e0ff
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/fec.c
@@ -0,0 +1,1000 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * This file is based on mpc4200fec.c,
+ * (C) Copyright Motorola, Inc., 2000
+ */
+
+#include <common.h>
+#include <mpc8220.h>
+#include <malloc.h>
+#include <net.h>
+#include <miiphy.h>
+#include "dma.h"
+#include "fec.h"
+
+#undef  DEBUG
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
+    defined(CONFIG_MPC8220_FEC)
+
+#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
+#error "CONFIG_MII has to be defined!"
+#endif
+
+#ifdef DEBUG
+static void tfifo_print (char *devname, mpc8220_fec_priv * fec);
+static void rfifo_print (char *devname, mpc8220_fec_priv * fec);
+#endif /* DEBUG */
+
+#ifdef DEBUG
+static u32 local_crc32 (char *string, unsigned int crc_value, int len);
+#endif
+
+typedef struct {
+	u8 data[1500];		/* actual data */
+	int length;		/* actual length */
+	int used;		/* buffer in use or not */
+	u8 head[16];		/* MAC header(6 + 6 + 2) + 2(aligned) */
+} NBUF;
+
+int fec8220_miiphy_read (char *devname, u8 phyAddr, u8 regAddr, u16 * retVal);
+int fec8220_miiphy_write (char *devname, u8 phyAddr, u8 regAddr, u16 data);
+
+/********************************************************************/
+#ifdef DEBUG
+static void mpc8220_fec_phydump (char *devname)
+{
+	u16 phyStatus, i;
+	u8 phyAddr = CONFIG_PHY_ADDR;
+	u8 reg_mask[] = {
+#if CONFIG_PHY_TYPE == 0x79c874 /* AMD Am79C874 */
+		/* regs to print: 0...7, 16...19, 21, 23, 24 */
+		1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+		1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+#else
+		/* regs to print: 0...8, 16...20 */
+		1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+		1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#endif
+	};
+
+	for (i = 0; i < 32; i++) {
+		if (reg_mask[i]) {
+			miiphy_read (devname, phyAddr, i, &phyStatus);
+			printf ("Mii reg %d: 0x%04x\n", i, phyStatus);
+		}
+	}
+}
+#endif
+
+/********************************************************************/
+static int mpc8220_fec_rbd_init (mpc8220_fec_priv * fec)
+{
+	int ix;
+	char *data;
+	static int once = 0;
+
+	for (ix = 0; ix < FEC_RBD_NUM; ix++) {
+		if (!once) {
+			data = (char *) malloc (FEC_MAX_PKT_SIZE);
+			if (data == NULL) {
+				printf ("RBD INIT FAILED\n");
+				return -1;
+			}
+			fec->rbdBase[ix].dataPointer = (u32) data;
+		}
+		fec->rbdBase[ix].status = FEC_RBD_EMPTY;
+		fec->rbdBase[ix].dataLength = 0;
+	}
+	once++;
+
+	/*
+	 * have the last RBD to close the ring
+	 */
+	fec->rbdBase[ix - 1].status |= FEC_RBD_WRAP;
+	fec->rbdIndex = 0;
+
+	return 0;
+}
+
+/********************************************************************/
+static void mpc8220_fec_tbd_init (mpc8220_fec_priv * fec)
+{
+	int ix;
+
+	for (ix = 0; ix < FEC_TBD_NUM; ix++) {
+		fec->tbdBase[ix].status = 0;
+	}
+
+	/*
+	 * Have the last TBD to close the ring
+	 */
+	fec->tbdBase[ix - 1].status |= FEC_TBD_WRAP;
+
+	/*
+	 * Initialize some indices
+	 */
+	fec->tbdIndex = 0;
+	fec->usedTbdIndex = 0;
+	fec->cleanTbdNum = FEC_TBD_NUM;
+}
+
+/********************************************************************/
+static void mpc8220_fec_rbd_clean (mpc8220_fec_priv * fec, FEC_RBD * pRbd)
+{
+	/*
+	 * Reset buffer descriptor as empty
+	 */
+	if ((fec->rbdIndex) == (FEC_RBD_NUM - 1))
+		pRbd->status = (FEC_RBD_WRAP | FEC_RBD_EMPTY);
+	else
+		pRbd->status = FEC_RBD_EMPTY;
+
+	pRbd->dataLength = 0;
+
+	/*
+	 * Now, we have an empty RxBD, restart the SmartDMA receive task
+	 */
+	DMA_TASK_ENABLE (FEC_RECV_TASK_NO);
+
+	/*
+	 * Increment BD count
+	 */
+	fec->rbdIndex = (fec->rbdIndex + 1) % FEC_RBD_NUM;
+}
+
+/********************************************************************/
+static void mpc8220_fec_tbd_scrub (mpc8220_fec_priv * fec)
+{
+	FEC_TBD *pUsedTbd;
+
+#ifdef DEBUG
+	printf ("tbd_scrub: fec->cleanTbdNum = %d, fec->usedTbdIndex = %d\n",
+		fec->cleanTbdNum, fec->usedTbdIndex);
+#endif
+
+	/*
+	 * process all the consumed TBDs
+	 */
+	while (fec->cleanTbdNum < FEC_TBD_NUM) {
+		pUsedTbd = &fec->tbdBase[fec->usedTbdIndex];
+		if (pUsedTbd->status & FEC_TBD_READY) {
+#ifdef DEBUG
+			printf ("Cannot clean TBD %d, in use\n",
+				fec->cleanTbdNum);
+#endif
+			return;
+		}
+
+		/*
+		 * clean this buffer descriptor
+		 */
+		if (fec->usedTbdIndex == (FEC_TBD_NUM - 1))
+			pUsedTbd->status = FEC_TBD_WRAP;
+		else
+			pUsedTbd->status = 0;
+
+		/*
+		 * update some indeces for a correct handling of the TBD ring
+		 */
+		fec->cleanTbdNum++;
+		fec->usedTbdIndex = (fec->usedTbdIndex + 1) % FEC_TBD_NUM;
+	}
+}
+
+/********************************************************************/
+static void mpc8220_fec_set_hwaddr (mpc8220_fec_priv * fec, char *mac)
+{
+	u8 currByte;		/* byte for which to compute the CRC */
+	int byte;		/* loop - counter */
+	int bit;		/* loop - counter */
+	u32 crc = 0xffffffff;	/* initial value */
+
+	/*
+	 * The algorithm used is the following:
+	 * we loop on each of the six bytes of the provided address,
+	 * and we compute the CRC by left-shifting the previous
+	 * value by one position, so that each bit in the current
+	 * byte of the address may contribute the calculation. If
+	 * the latter and the MSB in the CRC are different, then
+	 * the CRC value so computed is also ex-ored with the
+	 * "polynomium generator". The current byte of the address
+	 * is also shifted right by one bit at each iteration.
+	 * This is because the CRC generatore in hardware is implemented
+	 * as a shift-register with as many ex-ores as the radixes
+	 * in the polynomium. This suggests that we represent the
+	 * polynomiumm itself as a 32-bit constant.
+	 */
+	for (byte = 0; byte < 6; byte++) {
+		currByte = mac[byte];
+		for (bit = 0; bit < 8; bit++) {
+			if ((currByte & 0x01) ^ (crc & 0x01)) {
+				crc >>= 1;
+				crc = crc ^ 0xedb88320;
+			} else {
+				crc >>= 1;
+			}
+			currByte >>= 1;
+		}
+	}
+
+	crc = crc >> 26;
+
+	/*
+	 * Set individual hash table register
+	 */
+	if (crc >= 32) {
+		fec->eth->iaddr1 = (1 << (crc - 32));
+		fec->eth->iaddr2 = 0;
+	} else {
+		fec->eth->iaddr1 = 0;
+		fec->eth->iaddr2 = (1 << crc);
+	}
+
+	/*
+	 * Set physical address
+	 */
+	fec->eth->paddr1 =
+		(mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3];
+	fec->eth->paddr2 = (mac[4] << 24) + (mac[5] << 16) + 0x8808;
+}
+
+/********************************************************************/
+static int mpc8220_fec_init (struct eth_device *dev, bd_t * bis)
+{
+	mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
+	struct mpc8220_dma *dma = (struct mpc8220_dma *) MMAP_DMA;
+	const u8 phyAddr = CONFIG_PHY_ADDR;	/* Only one PHY */
+
+#ifdef DEBUG
+	printf ("mpc8220_fec_init... Begin\n");
+#endif
+
+	/*
+	 * Initialize RxBD/TxBD rings
+	 */
+	mpc8220_fec_rbd_init (fec);
+	mpc8220_fec_tbd_init (fec);
+
+	/*
+	 * Set up Pin Muxing for FEC 1
+	 */
+	*(vu_long *) MMAP_PCFG = 0;
+	*(vu_long *) (MMAP_PCFG + 4) = 0;
+	/*
+	 * Clear FEC-Lite interrupt event register(IEVENT)
+	 */
+	fec->eth->ievent = 0xffffffff;
+
+	/*
+	 * Set interrupt mask register
+	 */
+	fec->eth->imask = 0x00000000;
+
+	/*
+	 * Set FEC-Lite receive control register(R_CNTRL):
+	 */
+	if (fec->xcv_type == SEVENWIRE) {
+		/*
+		 * Frame length=1518; 7-wire mode
+		 */
+		fec->eth->r_cntrl = 0x05ee0020; /*0x05ee0000;FIXME */
+	} else {
+		/*
+		 * Frame length=1518; MII mode;
+		 */
+		fec->eth->r_cntrl = 0x05ee0024; /*0x05ee0004;FIXME */
+	}
+
+	fec->eth->x_cntrl = 0x00000000; /* half-duplex, heartbeat disabled */
+	if (fec->xcv_type != SEVENWIRE) {
+		/*
+		 * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
+		 * and do not drop the Preamble.
+		 */
+		/* tbd - rtm */
+		/*fec->eth->mii_speed = (((gd->ipb_clk >> 20) / 5) << 1); */
+		/* No MII for 7-wire mode */
+		fec->eth->mii_speed = 0x00000030;
+	}
+
+	/*
+	 * Set Opcode/Pause Duration Register
+	 */
+	fec->eth->op_pause = 0x00010020;	/*FIXME0xffff0020; */
+
+	/*
+	 * Set Rx FIFO alarm and granularity value
+	 */
+	fec->eth->rfifo_cntrl = 0x0c000000;
+	fec->eth->rfifo_alarm = 0x0000030c;
+#ifdef DEBUG
+	if (fec->eth->rfifo_status & 0x00700000) {
+		printf ("mpc8220_fec_init() RFIFO error\n");
+	}
+#endif
+
+	/*
+	 * Set Tx FIFO granularity value
+	 */
+	/*fec->eth->tfifo_cntrl = 0x0c000000; */ /*tbd - rtm */
+	fec->eth->tfifo_cntrl = 0x0e000000;
+#ifdef DEBUG
+	printf ("tfifo_status: 0x%08x\n", fec->eth->tfifo_status);
+	printf ("tfifo_alarm: 0x%08x\n", fec->eth->tfifo_alarm);
+#endif
+
+	/*
+	 * Set transmit fifo watermark register(X_WMRK), default = 64
+	 */
+	fec->eth->tfifo_alarm = 0x00000080;
+	fec->eth->x_wmrk = 0x2;
+
+	/*
+	 * Set individual address filter for unicast address
+	 * and set physical address registers.
+	 */
+	mpc8220_fec_set_hwaddr (fec, (char *)(dev->enetaddr));
+
+	/*
+	 * Set multicast address filter
+	 */
+	fec->eth->gaddr1 = 0x00000000;
+	fec->eth->gaddr2 = 0x00000000;
+
+	/*
+	 * Turn ON cheater FSM: ????
+	 */
+	fec->eth->xmit_fsm = 0x03000000;
+
+#if 1
+/*#if defined(CONFIG_MPC5200)*/
+	/*
+	 * Turn off COMM bus prefetch in the MGT5200 BestComm. It doesn't
+	 * work w/ the current receive task.
+	 */
+	dma->PtdCntrl |= 0x00000001;
+#endif
+
+	/*
+	 * Set priority of different initiators
+	 */
+	dma->IPR0 = 7;		/* always */
+	dma->IPR3 = 6;		/* Eth RX */
+	dma->IPR4 = 5;		/* Eth Tx */
+
+	/*
+	 * Clear SmartDMA task interrupt pending bits
+	 */
+	DMA_CLEAR_IEVENT (FEC_RECV_TASK_NO);
+
+	/*
+	 * Initialize SmartDMA parameters stored in SRAM
+	 */
+	*(int *) FEC_TBD_BASE = (int) fec->tbdBase;
+	*(int *) FEC_RBD_BASE = (int) fec->rbdBase;
+	*(int *) FEC_TBD_NEXT = (int) fec->tbdBase;
+	*(int *) FEC_RBD_NEXT = (int) fec->rbdBase;
+
+	if (fec->xcv_type != SEVENWIRE) {
+		/*
+		 * Initialize PHY(LXT971A):
+		 *
+		 *   Generally, on power up, the LXT971A reads its configuration
+		 *   pins to check for forced operation, If not cofigured for
+		 *   forced operation, it uses auto-negotiation/parallel detection
+		 *   to automatically determine line operating conditions.
+		 *   If the PHY device on the other side of the link supports
+		 *   auto-negotiation, the LXT971A auto-negotiates with it
+		 *   using Fast Link Pulse(FLP) Bursts. If the PHY partner does not
+		 *   support auto-negotiation, the LXT971A automatically detects
+		 *   the presence of either link pulses(10Mbps PHY) or Idle
+		 *   symbols(100Mbps) and sets its operating conditions accordingly.
+		 *
+		 *   When auto-negotiation is controlled by software, the following
+		 *   steps are recommended.
+		 *
+		 * Note:
+		 *   The physical address is dependent on hardware configuration.
+		 *
+		 */
+		int timeout = 1;
+		u16 phyStatus;
+
+		/*
+		 * Reset PHY, then delay 300ns
+		 */
+		miiphy_write (dev->name, phyAddr, 0x0, 0x8000);
+		udelay (1000);
+
+		if (fec->xcv_type == MII10) {
+			/*
+			 * Force 10Base-T, FDX operation
+			 */
+#ifdef DEBUG
+			printf ("Forcing 10 Mbps ethernet link... ");
+#endif
+			miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
+			/*
+			   miiphy_write(fec, phyAddr, 0x0, 0x0100);
+			 */
+			miiphy_write (dev->name, phyAddr, 0x0, 0x0180);
+
+			timeout = 20;
+			do {	/* wait for link status to go down */
+				udelay (10000);
+				if ((timeout--) == 0) {
+#ifdef DEBUG
+					printf ("hmmm, should not have waited...");
+#endif
+					break;
+				}
+				miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
+#ifdef DEBUG
+				printf ("=");
+#endif
+			} while ((phyStatus & 0x0004)); /* !link up */
+
+			timeout = 1000;
+			do {	/* wait for link status to come back up */
+				udelay (10000);
+				if ((timeout--) == 0) {
+					printf ("failed. Link is down.\n");
+					break;
+				}
+				miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
+#ifdef DEBUG
+				printf ("+");
+#endif
+			} while (!(phyStatus & 0x0004));	/* !link up */
+
+#ifdef DEBUG
+			printf ("done.\n");
+#endif
+		} else {	/* MII100 */
+			/*
+			 * Set the auto-negotiation advertisement register bits
+			 */
+			miiphy_write (dev->name, phyAddr, 0x4, 0x01e1);
+
+			/*
+			 * Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation
+			 */
+			miiphy_write (dev->name, phyAddr, 0x0, 0x1200);
+
+			/*
+			 * Wait for AN completion
+			 */
+			timeout = 5000;
+			do {
+				udelay (1000);
+
+				if ((timeout--) == 0) {
+#ifdef DEBUG
+					printf ("PHY auto neg 0 failed...\n");
+#endif
+					return -1;
+				}
+
+				if (miiphy_read (dev->name, phyAddr, 0x1, &phyStatus) !=
+				    0) {
+#ifdef DEBUG
+					printf ("PHY auto neg 1 failed 0x%04x...\n", phyStatus);
+#endif
+					return -1;
+				}
+			} while (!(phyStatus & 0x0004));
+
+#ifdef DEBUG
+			printf ("PHY auto neg complete! \n");
+#endif
+		}
+
+	}
+
+	/*
+	 * Enable FEC-Lite controller
+	 */
+	fec->eth->ecntrl |= 0x00000006;
+
+#ifdef DEBUG
+	if (fec->xcv_type != SEVENWIRE)
+		mpc8220_fec_phydump (dev->name);
+#endif
+
+	/*
+	 * Enable SmartDMA receive task
+	 */
+	DMA_TASK_ENABLE (FEC_RECV_TASK_NO);
+
+#ifdef DEBUG
+	printf ("mpc8220_fec_init... Done \n");
+#endif
+
+	return 1;
+}
+
+/********************************************************************/
+static void mpc8220_fec_halt (struct eth_device *dev)
+{
+	mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
+	int counter = 0xffff;
+
+#ifdef DEBUG
+	if (fec->xcv_type != SEVENWIRE)
+		mpc8220_fec_phydump (dev->name);
+#endif
+
+	/*
+	 * mask FEC chip interrupts
+	 */
+	fec->eth->imask = 0;
+
+	/*
+	 * issue graceful stop command to the FEC transmitter if necessary
+	 */
+	fec->eth->x_cntrl |= 0x00000001;
+
+	/*
+	 * wait for graceful stop to register
+	 */
+	while ((counter--) && (!(fec->eth->ievent & 0x10000000)));
+
+	/*
+	 * Disable SmartDMA tasks
+	 */
+	DMA_TASK_DISABLE (FEC_XMIT_TASK_NO);
+	DMA_TASK_DISABLE (FEC_RECV_TASK_NO);
+
+	/*
+	 * Disable the Ethernet Controller
+	 */
+	fec->eth->ecntrl &= 0xfffffffd;
+
+	/*
+	 * Clear FIFO status registers
+	 */
+	fec->eth->rfifo_status &= 0x00700000;
+	fec->eth->tfifo_status &= 0x00700000;
+
+	fec->eth->reset_cntrl = 0x01000000;
+
+	/*
+	 * Issue a reset command to the FEC chip
+	 */
+	fec->eth->ecntrl |= 0x1;
+
+	/*
+	 * wait at least 16 clock cycles
+	 */
+	udelay (10);
+
+#ifdef DEBUG
+	printf ("Ethernet task stopped\n");
+#endif
+}
+
+#ifdef DEBUG
+/********************************************************************/
+
+static void tfifo_print (char *devname, mpc8220_fec_priv * fec)
+{
+	u16 phyAddr = CONFIG_PHY_ADDR;
+	u16 phyStatus;
+
+	if ((fec->eth->tfifo_lrf_ptr != fec->eth->tfifo_lwf_ptr)
+	    || (fec->eth->tfifo_rdptr != fec->eth->tfifo_wrptr)) {
+
+		miiphy_read (devname, phyAddr, 0x1, &phyStatus);
+		printf ("\nphyStatus: 0x%04x\n", phyStatus);
+		printf ("ecntrl:   0x%08x\n", fec->eth->ecntrl);
+		printf ("ievent:   0x%08x\n", fec->eth->ievent);
+		printf ("x_status: 0x%08x\n", fec->eth->x_status);
+		printf ("tfifo: status	0x%08x\n", fec->eth->tfifo_status);
+
+		printf ("	control 0x%08x\n", fec->eth->tfifo_cntrl);
+		printf ("	lrfp	0x%08x\n", fec->eth->tfifo_lrf_ptr);
+		printf ("	lwfp	0x%08x\n", fec->eth->tfifo_lwf_ptr);
+		printf ("	alarm	0x%08x\n", fec->eth->tfifo_alarm);
+		printf ("	readptr 0x%08x\n", fec->eth->tfifo_rdptr);
+		printf ("	writptr 0x%08x\n", fec->eth->tfifo_wrptr);
+	}
+}
+
+static void rfifo_print (char *devname, mpc8220_fec_priv * fec)
+{
+	u16 phyAddr = CONFIG_PHY_ADDR;
+	u16 phyStatus;
+
+	if ((fec->eth->rfifo_lrf_ptr != fec->eth->rfifo_lwf_ptr)
+	    || (fec->eth->rfifo_rdptr != fec->eth->rfifo_wrptr)) {
+
+		miiphy_read (devname, phyAddr, 0x1, &phyStatus);
+		printf ("\nphyStatus: 0x%04x\n", phyStatus);
+		printf ("ecntrl:   0x%08x\n", fec->eth->ecntrl);
+		printf ("ievent:   0x%08x\n", fec->eth->ievent);
+		printf ("x_status: 0x%08x\n", fec->eth->x_status);
+		printf ("rfifo: status	0x%08x\n", fec->eth->rfifo_status);
+
+		printf ("	control 0x%08x\n", fec->eth->rfifo_cntrl);
+		printf ("	lrfp	0x%08x\n", fec->eth->rfifo_lrf_ptr);
+		printf ("	lwfp	0x%08x\n", fec->eth->rfifo_lwf_ptr);
+		printf ("	alarm	0x%08x\n", fec->eth->rfifo_alarm);
+		printf ("	readptr 0x%08x\n", fec->eth->rfifo_rdptr);
+		printf ("	writptr 0x%08x\n", fec->eth->rfifo_wrptr);
+	}
+}
+#endif /* DEBUG */
+
+/********************************************************************/
+
+static int mpc8220_fec_send (struct eth_device *dev, volatile void *eth_data,
+			     int data_length)
+{
+	/*
+	 * This routine transmits one frame.  This routine only accepts
+	 * 6-byte Ethernet addresses.
+	 */
+	mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
+	FEC_TBD *pTbd;
+
+#ifdef DEBUG
+	printf ("tbd status: 0x%04x\n", fec->tbdBase[0].status);
+	tfifo_print (dev->name, fec);
+#endif
+
+	/*
+	 * Clear Tx BD ring at first
+	 */
+	mpc8220_fec_tbd_scrub (fec);
+
+	/*
+	 * Check for valid length of data.
+	 */
+	if ((data_length > 1500) || (data_length <= 0)) {
+		return -1;
+	}
+
+	/*
+	 * Check the number of vacant TxBDs.
+	 */
+	if (fec->cleanTbdNum < 1) {
+#ifdef DEBUG
+		printf ("No available TxBDs ...\n");
+#endif
+		return -1;
+	}
+
+	/*
+	 * Get the first TxBD to send the mac header
+	 */
+	pTbd = &fec->tbdBase[fec->tbdIndex];
+	pTbd->dataLength = data_length;
+	pTbd->dataPointer = (u32) eth_data;
+	pTbd->status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
+	fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM;
+
+#ifdef DEBUG
+	printf ("DMA_TASK_ENABLE, fec->tbdIndex = %d \n", fec->tbdIndex);
+#endif
+
+	/*
+	 * Kick the MII i/f
+	 */
+	if (fec->xcv_type != SEVENWIRE) {
+		u16 phyStatus;
+
+		miiphy_read (dev->name, 0, 0x1, &phyStatus);
+	}
+
+	/*
+	 * Enable SmartDMA transmit task
+	 */
+
+#ifdef DEBUG
+	tfifo_print (dev->name, fec);
+#endif
+
+	DMA_TASK_ENABLE (FEC_XMIT_TASK_NO);
+
+#ifdef DEBUG
+	tfifo_print (dev->name, fec);
+#endif
+
+#ifdef DEBUG
+	printf ("+");
+#endif
+
+	fec->cleanTbdNum -= 1;
+
+#ifdef DEBUG
+	printf ("smartDMA ethernet Tx task enabled\n");
+#endif
+	/*
+	 * wait until frame is sent .
+	 */
+	while (pTbd->status & FEC_TBD_READY) {
+		udelay (10);
+#ifdef DEBUG
+		printf ("TDB status = %04x\n", pTbd->status);
+#endif
+	}
+
+	return 0;
+}
+
+
+/********************************************************************/
+static int mpc8220_fec_recv (struct eth_device *dev)
+{
+	/*
+	 * This command pulls one frame from the card
+	 */
+	mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
+	FEC_RBD *pRbd = &fec->rbdBase[fec->rbdIndex];
+	unsigned long ievent;
+	int frame_length, len = 0;
+	NBUF *frame;
+
+#ifdef DEBUG
+	printf ("mpc8220_fec_recv %d Start...\n", fec->rbdIndex);
+	printf ("-");
+#endif
+
+	/*
+	 * Check if any critical events have happened
+	 */
+	ievent = fec->eth->ievent;
+	fec->eth->ievent = ievent;
+	if (ievent & 0x20060000) {
+		/* BABT, Rx/Tx FIFO errors */
+		mpc8220_fec_halt (dev);
+		mpc8220_fec_init (dev, NULL);
+		return 0;
+	}
+	if (ievent & 0x80000000) {
+		/* Heartbeat error */
+		fec->eth->x_cntrl |= 0x00000001;
+	}
+	if (ievent & 0x10000000) {
+		/* Graceful stop complete */
+		if (fec->eth->x_cntrl & 0x00000001) {
+			mpc8220_fec_halt (dev);
+			fec->eth->x_cntrl &= ~0x00000001;
+			mpc8220_fec_init (dev, NULL);
+		}
+	}
+
+	if (!(pRbd->status & FEC_RBD_EMPTY)) {
+		if ((pRbd->status & FEC_RBD_LAST)
+		    && !(pRbd->status & FEC_RBD_ERR)
+		    && ((pRbd->dataLength - 4) > 14)) {
+
+			/*
+			 * Get buffer address and size
+			 */
+			frame = (NBUF *) pRbd->dataPointer;
+			frame_length = pRbd->dataLength - 4;
+
+#if (0)
+			{
+				int i;
+
+				printf ("recv data hdr:");
+				for (i = 0; i < 14; i++)
+					printf ("%x ", *(frame->head + i));
+				printf ("\n");
+			}
+#endif
+			/*
+			 *  Fill the buffer and pass it to upper layers
+			 */
+/*			memcpy(buff, frame->head, 14);
+			memcpy(buff + 14, frame->data, frame_length);*/
+			NetReceive ((volatile uchar *) pRbd->dataPointer,
+				    frame_length);
+			len = frame_length;
+		}
+		/*
+		 * Reset buffer descriptor as empty
+		 */
+		mpc8220_fec_rbd_clean (fec, pRbd);
+	}
+	DMA_CLEAR_IEVENT (FEC_RECV_TASK_NO);
+	return len;
+}
+
+
+/********************************************************************/
+int mpc8220_fec_initialize (bd_t * bis)
+{
+	mpc8220_fec_priv *fec;
+
+#ifdef CONFIG_HAS_ETH1
+	mpc8220_fec_priv *fec2;
+#endif
+	struct eth_device *dev;
+	char *tmp, *end;
+	char env_enetaddr[6];
+
+#ifdef CONFIG_HAS_ETH1
+	char env_enet1addr[6];
+#endif
+	int i;
+
+	fec = (mpc8220_fec_priv *) malloc (sizeof (*fec));
+	dev = (struct eth_device *) malloc (sizeof (*dev));
+	memset (dev, 0, sizeof *dev);
+
+	fec->eth = (ethernet_regs *) MMAP_FEC1;
+#ifdef CONFIG_HAS_ETH1
+	fec2 = (mpc8220_fec_priv *) malloc (sizeof (*fec));
+	fec2->eth = (ethernet_regs *) MMAP_FEC2;
+#endif
+	fec->tbdBase = (FEC_TBD *) FEC_BD_BASE;
+	fec->rbdBase =
+		(FEC_RBD *) (FEC_BD_BASE + FEC_TBD_NUM * sizeof (FEC_TBD));
+	fec->xcv_type = MII100;
+
+	dev->priv = (void *) fec;
+	dev->iobase = MMAP_FEC1;
+	dev->init = mpc8220_fec_init;
+	dev->halt = mpc8220_fec_halt;
+	dev->send = mpc8220_fec_send;
+	dev->recv = mpc8220_fec_recv;
+
+	sprintf (dev->name, "FEC ETHERNET");
+	eth_register (dev);
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+	miiphy_register (dev->name,
+			fec8220_miiphy_read, fec8220_miiphy_write);
+#endif
+
+	/*
+	 * Try to set the mac address now. The fec mac address is
+	 * a garbage after reset. When not using fec for booting
+	 * the Linux fec driver will try to work with this garbage.
+	 */
+	tmp = getenv ("ethaddr");
+	if (tmp) {
+		for (i = 0; i < 6; i++) {
+			env_enetaddr[i] =
+				tmp ? simple_strtoul (tmp, &end, 16) : 0;
+			if (tmp)
+				tmp = (*end) ? end + 1 : end;
+		}
+		mpc8220_fec_set_hwaddr (fec, env_enetaddr);
+	}
+#ifdef CONFIG_HAS_ETH1
+	tmp = getenv ("eth1addr");
+	if (tmp) {
+		for (i = 0; i < 6; i++) {
+			env_enet1addr[i] =
+				tmp ? simple_strtoul (tmp, &end, 16) : 0;
+			if (tmp)
+				tmp = (*end) ? end + 1 : end;
+		}
+		mpc8220_fec_set_hwaddr (fec2, env_enet1addr);
+	}
+#endif
+
+	return 1;
+}
+
+/* MII-interface related functions */
+/********************************************************************/
+int fec8220_miiphy_read (char *devname, u8 phyAddr, u8 regAddr, u16 * retVal)
+{
+	ethernet_regs *eth = (ethernet_regs *) MMAP_FEC1;
+	u32 reg;		/* convenient holder for the PHY register */
+	u32 phy;		/* convenient holder for the PHY */
+	int timeout = 0xffff;
+
+	/*
+	 * reading from any PHY's register is done by properly
+	 * programming the FEC's MII data register.
+	 */
+	reg = regAddr << FEC_MII_DATA_RA_SHIFT;
+	phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
+
+	eth->mii_data =
+		(FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA | phy
+		 | reg);
+
+	/*
+	 * wait for the related interrupt
+	 */
+	while ((timeout--) && (!(eth->ievent & 0x00800000)));
+
+	if (timeout == 0) {
+#ifdef DEBUG
+		printf ("Read MDIO failed...\n");
+#endif
+		return -1;
+	}
+
+	/*
+	 * clear mii interrupt bit
+	 */
+	eth->ievent = 0x00800000;
+
+	/*
+	 * it's now safe to read the PHY's register
+	 */
+	*retVal = (u16) eth->mii_data;
+
+	return 0;
+}
+
+/********************************************************************/
+int fec8220_miiphy_write (char *devname, u8 phyAddr, u8 regAddr, u16 data)
+{
+	ethernet_regs *eth = (ethernet_regs *) MMAP_FEC1;
+	u32 reg;		/* convenient holder for the PHY register */
+	u32 phy;		/* convenient holder for the PHY */
+	int timeout = 0xffff;
+
+	reg = regAddr << FEC_MII_DATA_RA_SHIFT;
+	phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
+
+	eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
+			 FEC_MII_DATA_TA | phy | reg | data);
+
+	/*
+	 * wait for the MII interrupt
+	 */
+	while ((timeout--) && (!(eth->ievent & 0x00800000)));
+
+	if (timeout == 0) {
+#ifdef DEBUG
+		printf ("Write MDIO failed...\n");
+#endif
+		return -1;
+	}
+
+	/*
+	 * clear MII interrupt bit
+	 */
+	eth->ievent = 0x00800000;
+
+	return 0;
+}
+
+#ifdef DEBUG
+static u32 local_crc32 (char *string, unsigned int crc_value, int len)
+{
+	int i;
+	char c;
+	unsigned int crc, count;
+
+	/*
+	 * crc32 algorithm
+	 */
+	/*
+	 * crc = 0xffffffff; * The initialized value should be 0xffffffff
+	 */
+	crc = crc_value;
+
+	for (i = len; --i >= 0;) {
+		c = *string++;
+		for (count = 0; count < 8; count++) {
+			if ((c & 0x01) ^ (crc & 0x01)) {
+				crc >>= 1;
+				crc = crc ^ 0xedb88320;
+			} else {
+				crc >>= 1;
+			}
+			c >>= 1;
+		}
+	}
+
+	/*
+	 * In big endian system, do byte swaping for crc value
+	 */
+	return crc;
+}
+#endif /* DEBUG */
+
+#endif /* CONFIG_MPC8220_FEC */
diff --git a/arch/powerpc/cpu/mpc8220/fec.h b/arch/powerpc/cpu/mpc8220/fec.h
new file mode 100644
index 0000000..a8927fc
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/fec.h
@@ -0,0 +1,283 @@
+/*
+ * (C) Copyright 2003-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * This file is based on mpc4200fec.h
+ * (C) Copyright Motorola, Inc., 2000
+ *
+ * odin ethernet header file
+ */
+
+#ifndef __MPC8220_FEC_H
+#define __MPC8220_FEC_H
+
+#include <common.h>
+#include <mpc8220.h>
+#include "dma.h"
+
+typedef struct ethernet_register_set {
+
+/* [10:2]addr = 00 */
+
+/*  Control and status Registers (offset 000-1FF) */
+
+	volatile u32 fec_id;		/* MBAR_ETH + 0x000 */
+	volatile u32 ievent;		/* MBAR_ETH + 0x004 */
+	volatile u32 imask;		/* MBAR_ETH + 0x008 */
+
+	volatile u32 RES0[1];		/* MBAR_ETH + 0x00C */
+	volatile u32 r_des_active;	/* MBAR_ETH + 0x010 */
+	volatile u32 x_des_active;	/* MBAR_ETH + 0x014 */
+	volatile u32 r_des_active_cl;	/* MBAR_ETH + 0x018 */
+	volatile u32 x_des_active_cl;	/* MBAR_ETH + 0x01C */
+	volatile u32 ivent_set;		/* MBAR_ETH + 0x020 */
+	volatile u32 ecntrl;		/* MBAR_ETH + 0x024 */
+
+	volatile u32 RES1[6];		/* MBAR_ETH + 0x028-03C */
+	volatile u32 mii_data;		/* MBAR_ETH + 0x040 */
+	volatile u32 mii_speed;		/* MBAR_ETH + 0x044 */
+	volatile u32 mii_status;	/* MBAR_ETH + 0x048 */
+
+	volatile u32 RES2[5];		/* MBAR_ETH + 0x04C-05C */
+	volatile u32 mib_data;		/* MBAR_ETH + 0x060 */
+	volatile u32 mib_control;	/* MBAR_ETH + 0x064 */
+
+	volatile u32 RES3[6];		/* MBAR_ETH + 0x068-7C */
+	volatile u32 r_activate;	/* MBAR_ETH + 0x080 */
+	volatile u32 r_cntrl;		/* MBAR_ETH + 0x084 */
+	volatile u32 r_hash;		/* MBAR_ETH + 0x088 */
+	volatile u32 r_data;		/* MBAR_ETH + 0x08C */
+	volatile u32 ar_done;		/* MBAR_ETH + 0x090 */
+	volatile u32 r_test;		/* MBAR_ETH + 0x094 */
+	volatile u32 r_mib;		/* MBAR_ETH + 0x098 */
+	volatile u32 r_da_low;		/* MBAR_ETH + 0x09C */
+	volatile u32 r_da_high;		/* MBAR_ETH + 0x0A0 */
+
+	volatile u32 RES4[7];		/* MBAR_ETH + 0x0A4-0BC */
+	volatile u32 x_activate;	/* MBAR_ETH + 0x0C0 */
+	volatile u32 x_cntrl;		/* MBAR_ETH + 0x0C4 */
+	volatile u32 backoff;		/* MBAR_ETH + 0x0C8 */
+	volatile u32 x_data;		/* MBAR_ETH + 0x0CC */
+	volatile u32 x_status;		/* MBAR_ETH + 0x0D0 */
+	volatile u32 x_mib;		/* MBAR_ETH + 0x0D4 */
+	volatile u32 x_test;		/* MBAR_ETH + 0x0D8 */
+	volatile u32 fdxfc_da1;		/* MBAR_ETH + 0x0DC */
+	volatile u32 fdxfc_da2;		/* MBAR_ETH + 0x0E0 */
+	volatile u32 paddr1;		/* MBAR_ETH + 0x0E4 */
+	volatile u32 paddr2;		/* MBAR_ETH + 0x0E8 */
+	volatile u32 op_pause;		/* MBAR_ETH + 0x0EC */
+
+	volatile u32 RES5[4];		/* MBAR_ETH + 0x0F0-0FC */
+	volatile u32 instr_reg;		/* MBAR_ETH + 0x100 */
+	volatile u32 context_reg;	/* MBAR_ETH + 0x104 */
+	volatile u32 test_cntrl;	/* MBAR_ETH + 0x108 */
+	volatile u32 acc_reg;		/* MBAR_ETH + 0x10C */
+	volatile u32 ones;		/* MBAR_ETH + 0x110 */
+	volatile u32 zeros;		/* MBAR_ETH + 0x114 */
+	volatile u32 iaddr1;		/* MBAR_ETH + 0x118 */
+	volatile u32 iaddr2;		/* MBAR_ETH + 0x11C */
+	volatile u32 gaddr1;		/* MBAR_ETH + 0x120 */
+	volatile u32 gaddr2;		/* MBAR_ETH + 0x124 */
+	volatile u32 random;		/* MBAR_ETH + 0x128 */
+	volatile u32 rand1;		/* MBAR_ETH + 0x12C */
+	volatile u32 tmp;		/* MBAR_ETH + 0x130 */
+
+	volatile u32 RES6[3];		/* MBAR_ETH + 0x134-13C */
+	volatile u32 fifo_id;		/* MBAR_ETH + 0x140 */
+	volatile u32 x_wmrk;		/* MBAR_ETH + 0x144 */
+	volatile u32 fcntrl;		/* MBAR_ETH + 0x148 */
+	volatile u32 r_bound;		/* MBAR_ETH + 0x14C */
+	volatile u32 r_fstart;		/* MBAR_ETH + 0x150 */
+	volatile u32 r_count;		/* MBAR_ETH + 0x154 */
+	volatile u32 r_lag;		/* MBAR_ETH + 0x158 */
+	volatile u32 r_read;		/* MBAR_ETH + 0x15C */
+	volatile u32 r_write;		/* MBAR_ETH + 0x160 */
+	volatile u32 x_count;		/* MBAR_ETH + 0x164 */
+	volatile u32 x_lag;		/* MBAR_ETH + 0x168 */
+	volatile u32 x_retry;		/* MBAR_ETH + 0x16C */
+	volatile u32 x_write;		/* MBAR_ETH + 0x170 */
+	volatile u32 x_read;		/* MBAR_ETH + 0x174 */
+
+	volatile u32 RES7[2];		/* MBAR_ETH + 0x178-17C */
+	volatile u32 fm_cntrl;		/* MBAR_ETH + 0x180 */
+	volatile u32 rfifo_data;	/* MBAR_ETH + 0x184 */
+	volatile u32 rfifo_status;	/* MBAR_ETH + 0x188 */
+	volatile u32 rfifo_cntrl;	/* MBAR_ETH + 0x18C */
+	volatile u32 rfifo_lrf_ptr;	/* MBAR_ETH + 0x190 */
+	volatile u32 rfifo_lwf_ptr;	/* MBAR_ETH + 0x194 */
+	volatile u32 rfifo_alarm;	/* MBAR_ETH + 0x198 */
+	volatile u32 rfifo_rdptr;	/* MBAR_ETH + 0x19C */
+	volatile u32 rfifo_wrptr;	/* MBAR_ETH + 0x1A0 */
+	volatile u32 tfifo_data;	/* MBAR_ETH + 0x1A4 */
+	volatile u32 tfifo_status;	/* MBAR_ETH + 0x1A8 */
+	volatile u32 tfifo_cntrl;	/* MBAR_ETH + 0x1AC */
+	volatile u32 tfifo_lrf_ptr;	/* MBAR_ETH + 0x1B0 */
+	volatile u32 tfifo_lwf_ptr;	/* MBAR_ETH + 0x1B4 */
+	volatile u32 tfifo_alarm;	/* MBAR_ETH + 0x1B8 */
+	volatile u32 tfifo_rdptr;	/* MBAR_ETH + 0x1BC */
+	volatile u32 tfifo_wrptr;	/* MBAR_ETH + 0x1C0 */
+
+	volatile u32 reset_cntrl;	/* MBAR_ETH + 0x1C4 */
+	volatile u32 xmit_fsm;		/* MBAR_ETH + 0x1C8 */
+
+	volatile u32 RES8[3];		/* MBAR_ETH + 0x1CC-1D4 */
+	volatile u32 rdes_data0;	/* MBAR_ETH + 0x1D8 */
+	volatile u32 rdes_data1;	/* MBAR_ETH + 0x1DC */
+	volatile u32 r_length;		/* MBAR_ETH + 0x1E0 */
+	volatile u32 x_length;		/* MBAR_ETH + 0x1E4 */
+	volatile u32 x_addr;		/* MBAR_ETH + 0x1E8 */
+	volatile u32 cdes_data;		/* MBAR_ETH + 0x1EC */
+	volatile u32 status;		/* MBAR_ETH + 0x1F0 */
+	volatile u32 dma_control;	/* MBAR_ETH + 0x1F4 */
+	volatile u32 des_cmnd;		/* MBAR_ETH + 0x1F8 */
+	volatile u32 data;		/* MBAR_ETH + 0x1FC */
+
+	/*  MIB COUNTERS (Offset 200-2FF) */
+
+	volatile u32 rmon_t_drop;	/* MBAR_ETH + 0x200 */
+	volatile u32 rmon_t_packets;	/* MBAR_ETH + 0x204 */
+	volatile u32 rmon_t_bc_pkt;	/* MBAR_ETH + 0x208 */
+	volatile u32 rmon_t_mc_pkt;	/* MBAR_ETH + 0x20C */
+	volatile u32 rmon_t_crc_align;	/* MBAR_ETH + 0x210 */
+	volatile u32 rmon_t_undersize;	/* MBAR_ETH + 0x214 */
+	volatile u32 rmon_t_oversize;	/* MBAR_ETH + 0x218 */
+	volatile u32 rmon_t_frag;	/* MBAR_ETH + 0x21C */
+	volatile u32 rmon_t_jab;	/* MBAR_ETH + 0x220 */
+	volatile u32 rmon_t_col;	/* MBAR_ETH + 0x224 */
+	volatile u32 rmon_t_p64;	/* MBAR_ETH + 0x228 */
+	volatile u32 rmon_t_p65to127;	/* MBAR_ETH + 0x22C */
+	volatile u32 rmon_t_p128to255;	/* MBAR_ETH + 0x230 */
+	volatile u32 rmon_t_p256to511;	/* MBAR_ETH + 0x234 */
+	volatile u32 rmon_t_p512to1023;	/* MBAR_ETH + 0x238 */
+	volatile u32 rmon_t_p1024to2047;/* MBAR_ETH + 0x23C */
+	volatile u32 rmon_t_p_gte2048;	/* MBAR_ETH + 0x240 */
+	volatile u32 rmon_t_octets;	/* MBAR_ETH + 0x244 */
+	volatile u32 ieee_t_drop;	/* MBAR_ETH + 0x248 */
+	volatile u32 ieee_t_frame_ok;	/* MBAR_ETH + 0x24C */
+	volatile u32 ieee_t_1col;	/* MBAR_ETH + 0x250 */
+	volatile u32 ieee_t_mcol;	/* MBAR_ETH + 0x254 */
+	volatile u32 ieee_t_def;	/* MBAR_ETH + 0x258 */
+	volatile u32 ieee_t_lcol;	/* MBAR_ETH + 0x25C */
+	volatile u32 ieee_t_excol;	/* MBAR_ETH + 0x260 */
+	volatile u32 ieee_t_macerr;	/* MBAR_ETH + 0x264 */
+	volatile u32 ieee_t_cserr;	/* MBAR_ETH + 0x268 */
+	volatile u32 ieee_t_sqe;	/* MBAR_ETH + 0x26C */
+	volatile u32 t_fdxfc;		/* MBAR_ETH + 0x270 */
+	volatile u32 ieee_t_octets_ok;	/* MBAR_ETH + 0x274 */
+
+	volatile u32 RES9[2];		/* MBAR_ETH + 0x278-27C */
+	volatile u32 rmon_r_drop;	/* MBAR_ETH + 0x280 */
+	volatile u32 rmon_r_packets;	/* MBAR_ETH + 0x284 */
+	volatile u32 rmon_r_bc_pkt;	/* MBAR_ETH + 0x288 */
+	volatile u32 rmon_r_mc_pkt;	/* MBAR_ETH + 0x28C */
+	volatile u32 rmon_r_crc_align;	/* MBAR_ETH + 0x290 */
+	volatile u32 rmon_r_undersize;	/* MBAR_ETH + 0x294 */
+	volatile u32 rmon_r_oversize;	/* MBAR_ETH + 0x298 */
+	volatile u32 rmon_r_frag;	/* MBAR_ETH + 0x29C */
+	volatile u32 rmon_r_jab;	/* MBAR_ETH + 0x2A0 */
+
+	volatile u32 rmon_r_resvd_0;	/* MBAR_ETH + 0x2A4 */
+
+	volatile u32 rmon_r_p64;	/* MBAR_ETH + 0x2A8 */
+	volatile u32 rmon_r_p65to127;	/* MBAR_ETH + 0x2AC */
+	volatile u32 rmon_r_p128to255;	/* MBAR_ETH + 0x2B0 */
+	volatile u32 rmon_r_p256to511;	/* MBAR_ETH + 0x2B4 */
+	volatile u32 rmon_r_p512to1023;	/* MBAR_ETH + 0x2B8 */
+	volatile u32 rmon_r_p1024to2047;/* MBAR_ETH + 0x2BC */
+	volatile u32 rmon_r_p_gte2048;	/* MBAR_ETH + 0x2C0 */
+	volatile u32 rmon_r_octets;	/* MBAR_ETH + 0x2C4 */
+	volatile u32 ieee_r_drop;	/* MBAR_ETH + 0x2C8 */
+	volatile u32 ieee_r_frame_ok;	/* MBAR_ETH + 0x2CC */
+	volatile u32 ieee_r_crc;	/* MBAR_ETH + 0x2D0 */
+	volatile u32 ieee_r_align;	/* MBAR_ETH + 0x2D4 */
+	volatile u32 r_macerr;		/* MBAR_ETH + 0x2D8 */
+	volatile u32 r_fdxfc;		/* MBAR_ETH + 0x2DC */
+	volatile u32 ieee_r_octets_ok;	/* MBAR_ETH + 0x2E0 */
+
+	volatile u32 RES10[6];		/* MBAR_ETH + 0x2E4-2FC */
+
+	volatile u32 RES11[64];		/* MBAR_ETH + 0x300-3FF */
+} ethernet_regs;
+
+/* Receive & Transmit Buffer Descriptor definitions */
+typedef struct BufferDescriptor {
+	u16 status;
+	u16 dataLength;
+	u32 dataPointer;
+} FEC_RBD;
+
+typedef struct {
+	u16 status;
+	u16 dataLength;
+	u32 dataPointer;
+} FEC_TBD;
+
+/* private structure */
+typedef enum {
+	SEVENWIRE,		/* 7-wire       */
+	MII10,			/* MII 10Mbps   */
+	MII100			/* MII 100Mbps  */
+} xceiver_type;
+
+typedef struct {
+	ethernet_regs *eth;
+	xceiver_type xcv_type;	/* transceiver type */
+	FEC_RBD *rbdBase;	/* RBD ring */
+	FEC_TBD *tbdBase;	/* TBD ring */
+	u16 rbdIndex;		/* next receive BD to read */
+	u16 tbdIndex;		/* next transmit BD to send */
+	u16 usedTbdIndex;	/* next transmit BD to clean */
+	u16 cleanTbdNum;	/* the number of available transmit BDs */
+} mpc8220_fec_priv;
+
+/* Ethernet parameter area */
+#define FEC_TBD_BASE	    (FEC_PARAM_BASE + 0x00)
+#define FEC_TBD_NEXT	    (FEC_PARAM_BASE + 0x04)
+#define FEC_RBD_BASE	    (FEC_PARAM_BASE + 0x08)
+#define FEC_RBD_NEXT	    (FEC_PARAM_BASE + 0x0c)
+
+/* BD Numer definitions */
+#define FEC_TBD_NUM	   48	/* The user can adjust this value */
+#define FEC_RBD_NUM	   32	/* The user can adjust this value */
+
+/* packet size limit */
+#define FEC_MAX_PKT_SIZE   1536
+
+/* RBD bits definitions */
+#define FEC_RBD_EMPTY	0x8000	/* Buffer is empty */
+#define FEC_RBD_WRAP	0x2000	/* Last BD in ring */
+#define FEC_RBD_INT	0x1000	/* Interrupt */
+#define FEC_RBD_LAST	0x0800	/* Buffer is last in frame(useless) */
+#define FEC_RBD_MISS	0x0100	/* Miss bit for prom mode */
+#define FEC_RBD_BC	0x0080	/* The received frame is broadcast frame */
+#define FEC_RBD_MC	0x0040	/* The received frame is multicast frame */
+#define FEC_RBD_LG	0x0020	/* Frame length violation */
+#define FEC_RBD_NO	0x0010	/* Nonoctet align frame */
+#define FEC_RBD_SH	0x0008	/* Short frame */
+#define FEC_RBD_CR	0x0004	/* CRC error */
+#define FEC_RBD_OV	0x0002	/* Receive FIFO overrun */
+#define FEC_RBD_TR	0x0001	/* Frame is truncated */
+#define FEC_RBD_ERR	(FEC_RBD_LG | FEC_RBD_NO | FEC_RBD_CR | \
+			 FEC_RBD_OV | FEC_RBD_TR)
+
+/* TBD bits definitions */
+#define FEC_TBD_READY	0x8000	/* Buffer is ready */
+#define FEC_TBD_WRAP	0x2000	/* Last BD in ring */
+#define FEC_TBD_INT	0x1000	/* Interrupt */
+#define FEC_TBD_LAST	0x0800	/* Buffer is last in frame */
+#define FEC_TBD_TC	0x0400	/* Transmit the CRC */
+#define FEC_TBD_ABC	0x0200	/* Append bad CRC */
+
+/* MII-related definitios */
+#define FEC_MII_DATA_ST		0x40000000	/* Start of frame delimiter */
+#define FEC_MII_DATA_OP_RD	0x20000000	/* Perform a read operation */
+#define FEC_MII_DATA_OP_WR	0x10000000	/* Perform a write operation */
+#define FEC_MII_DATA_PA_MSK	0x0f800000	/* PHY Address field mask */
+#define FEC_MII_DATA_RA_MSK	0x007c0000	/* PHY Register field mask */
+#define FEC_MII_DATA_TA		0x00020000	/* Turnaround */
+#define FEC_MII_DATA_DATAMSK	0x0000ffff	/* PHY data field */
+
+#define FEC_MII_DATA_RA_SHIFT	18	/* MII Register address bits */
+#define FEC_MII_DATA_PA_SHIFT	23	/* MII PHY address bits */
+
+#endif /* __MPC8220_FEC_H */
diff --git a/arch/powerpc/cpu/mpc8220/fec_dma_tasks.S b/arch/powerpc/cpu/mpc8220/fec_dma_tasks.S
new file mode 100644
index 0000000..3f8a03b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/fec_dma_tasks.S
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2004, Freescale Semiconductor, Inc.
+ *
+ * This file contains microcode for the FEC controller of the MPC8220.
+ */
+
+#include <config.h>
+
+#if defined(CONFIG_MPC8220)
+
+/* sas/sccg, gas target */
+.section        smartdmaInitData,"aw",@progbits	/* Initialized data for task variables */
+.section        smartdmaTaskTable,"aw",@progbits	/* Task tables */
+.align  9
+.globl taskTable
+taskTable:
+.globl scEthernetRecv_Entry
+scEthernetRecv_Entry:		/* Task 0 */
+.long   scEthernetRecv_TDT - taskTable	/* Task 0 Descriptor Table */
+.long   scEthernetRecv_TDT - taskTable + 0x00000094
+.long   scEthernetRecv_VarTab - taskTable	/* Task 0 Variable Table */
+.long   scEthernetRecv_FDT - taskTable + 0x03	/* Task 0 Function Descriptor Table & Flags */
+.long   0x00000000
+.long   0x00000000
+.long   scEthernetRecv_CSave - taskTable	/* Task 0 context save space */
+.long   0xf0000000
+.globl scEthernetXmit_Entry
+scEthernetXmit_Entry:		/* Task 1 */
+.long   scEthernetXmit_TDT - taskTable	/* Task 1 Descriptor Table */
+.long   scEthernetXmit_TDT - taskTable + 0x000000e0
+.long   scEthernetXmit_VarTab - taskTable	/* Task 1 Variable Table */
+.long   scEthernetXmit_FDT - taskTable + 0x03	/* Task 1 Function Descriptor Table & Flags */
+.long   0x00000000
+.long   0x00000000
+.long   scEthernetXmit_CSave - taskTable	/* Task 1 context save space */
+.long   0xf0000000
+
+
+.globl scEthernetRecv_TDT
+scEthernetRecv_TDT:	/* Task 0 Descriptor Table */
+.long   0xc4c50000	/* 0000(153):  LCDEXT: idx0 = var9 + var10; idx0 once var0; idx0 += inc0 */
+.long   0x84c5e000	/* 0004(153):  LCD: idx1 = var9 + var11; ; idx1 += inc0 */
+.long   0x10001f08	/* 0008(156):    DRD1A: var7 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x10000380	/* 000C(157):    DRD1A: var0 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x00000f88	/* 0010(158):    DRD1A: var3 = *idx1; FN=0 init=0 WS=0 RS=0 */
+.long   0x81980000	/* 0014(162):  LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
+.long   0x10000780	/* 0018(164):    DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x60000000	/* 001C(165):    DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long   0x010cf04c	/* 0020(165):    DRD2B1: var4 = EU3(); EU3(var1,var12)  */
+.long   0x82180349	/* 0024(169):  LCD: idx0 = var4; idx0 != var13; idx0 += inc1 */
+.long   0x81c68004	/* 0028(172):    LCD: idx1 = var3 + var13 + 4; idx1 once var0; idx1 += inc0 */
+.long   0x70000000	/* 002C(174):      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long   0x018cf04e	/* 0030(174):      DRD2B1: var6 = EU3(); EU3(var1,var14)  */
+.long   0x70000000	/* 0034(175):      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long   0x020cf04f	/* 0038(175):      DRD2B1: var8 = EU3(); EU3(var1,var15)  */
+.long   0x00000b88	/* 003C(176):      DRD1A: var2 = *idx1; FN=0 init=0 WS=0 RS=0 */
+.long   0x80025184	/* 0040(205):    LCDEXT: idx1 = 0xf0009184; ; */
+.long   0x86810412	/* 0044(205):    LCD: idx2 = var13, idx3 = var2; idx2 < var16; idx2 += inc2, idx3 += inc2 */
+.long   0x0200cf88	/* 0048(209):      DRD1A: *idx3 = *idx1; FN=0 init=16 WS=0 RS=0 */
+.long   0x80025184	/* 004C(217):    LCDEXT: idx1 = 0xf0009184; ; */
+.long   0x8681845b	/* 0050(217):    LCD: idx2 = var13, idx3 = var3; idx2 < var17; idx2 += inc3, idx3 += inc3 */
+.long   0x0000cf88	/* 0054(221):      DRD1A: *idx3 = *idx1; FN=0 init=0 WS=0 RS=0 */
+.long   0xc31883a4	/* 0058(225):    LCDEXT: idx1 = var6; idx1 == var14; idx1 += inc4 */
+.long   0x80190000	/* 005C(225):    LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
+.long   0x04008468	/* 0060(227):      DRD1A: idx1 = var13; FN=0 INT init=0 WS=0 RS=0 */
+.long   0xc4038360	/* 0064(232):    LCDEXT: idx1 = var8, idx2 = var7; idx1 == var13; idx1 += inc4, idx2 += inc0 */
+.long   0x81c50000	/* 0068(233):    LCD: idx3 = var3 + var10; idx3 once var0; idx3 += inc0 */
+.long   0x1000cb18	/* 006C(235):      DRD1A: *idx2 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x00000f18	/* 0070(236):      DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
+.long   0xc418836d	/* 0074(238):    LCDEXT: idx1 = var8; idx1 > var13; idx1 += inc5 */
+.long   0x83990000	/* 0078(238):    LCD: idx2 = var7; idx2 once var0; idx2 += inc0 */
+.long   0x10000c00	/* 007C(240):      DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x0000c800	/* 0080(241):      DRD1A: *idx2 = var0; FN=0 init=0 WS=0 RS=0 */
+.long   0x81988000	/* 0084(245):    LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long   0x10000788	/* 0088(247):      DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x60000000	/* 008C(248):      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long   0x080cf04c	/* 0090(248):      DRD2B1: idx0 = EU3(); EU3(var1,var12)  */
+.long   0x000001f8	/* 0094(:0):    NOP */
+
+
+.globl scEthernetXmit_TDT
+scEthernetXmit_TDT:	/* Task 1 Descriptor Table */
+.long   0x80095b00	/* 0000(280):  LCDEXT: idx0 = 0xf0025b00; ; */
+.long   0x85c60004	/* 0004(280):  LCD: idx1 = var11 + var12 + 4; idx1 once var0; idx1 += inc0 */
+.long   0x10002308	/* 0008(283):    DRD1A: var8 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x10000f88	/* 000C(284):    DRD1A: var3 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x00000380	/* 0010(285):    DRD1A: var0 = *idx0; FN=0 init=0 WS=0 RS=0 */
+.long   0x81980000	/* 0014(288):  LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
+.long   0x10000780	/* 0018(290):    DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x60000000	/* 001C(291):    DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long   0x024cf04d	/* 0020(291):    DRD2B1: var9 = EU3(); EU3(var1,var13)  */
+.long   0x84980309	/* 0024(294):  LCD: idx0 = var9; idx0 != var12; idx0 += inc1 */
+.long   0xc0004003	/* 0028(297):    LCDEXT: idx1 = 0x00000003; ; */
+.long   0x81c60004	/* 002C(297):    LCD: idx2 = var3 + var12 + 4; idx2 once var0; idx2 += inc0 */
+.long   0x70000000	/* 0030(299):      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long   0x010cf04e	/* 0034(299):      DRD2B1: var4 = EU3(); EU3(var1,var14)  */
+.long   0x70000000	/* 0038(300):      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long   0x014cf04f	/* 003C(300):      DRD2B1: var5 = EU3(); EU3(var1,var15)  */
+.long   0x70000000	/* 0040(301):      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long   0x028cf050	/* 0044(301):      DRD2B1: var10 = EU3(); EU3(var1,var16)  */
+.long   0x70000000	/* 0048(302):      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long   0x018cf051	/* 004C(302):      DRD2B1: var6 = EU3(); EU3(var1,var17)  */
+.long   0x10000b90	/* 0050(303):      DRD1A: var2 = *idx2; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x60000000	/* 0054(304):      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long   0x01ccf0a1	/* 0058(304):      DRD2B1: var7 = EU3(); EU3(var2,idx1)  */
+.long   0xc2988312	/* 005C(308):    LCDEXT: idx1 = var5; idx1 > var12; idx1 += inc2 */
+.long   0x83490000	/* 0060(308):    LCD: idx2 = var6 + var18; idx2 once var0; idx2 += inc0 */
+.long   0x00001b10	/* 0064(310):      DRD1A: var6 = idx2; FN=0 init=0 WS=0 RS=0 */
+.long   0x800251a4	/* 0068(315):    LCDEXT: idx1 = 0xf00091a4; ; */
+.long   0xc30104dc	/* 006C(315):    LCDEXT: idx2 = var6, idx3 = var2; idx2 >= var19; idx2 += inc3, idx3 += inc4 */
+.long   0x839a032d	/* 0070(316):    LCD: idx4 = var7; idx4 == var12; idx4 += inc5 */
+.long   0x0220c798	/* 0074(321):      DRD1A: *idx1 = *idx3; FN=0 init=17 WS=0 RS=0 */
+.long   0x800251a4	/* 0078(329):    LCDEXT: idx1 = 0xf00091a4; ; */
+.long   0x99198337	/* 007C(329):    LCD: idx2 = idx2, idx3 = idx3; idx2 > var12; idx2 += inc6, idx3 += inc7 */
+.long   0x022ac798	/* 0080(333):      DRD1A: *idx1 = *idx3; FN=0 init=17 WS=1 RS=1 */
+.long   0x800251a4	/* 0084(350):    LCDEXT: idx1 = 0xf00091a4; ; */
+.long   0xc1430000	/* 0088(350):    LCDEXT: idx2 = var2 + var6; idx2 once var0; idx2 += inc0 */
+.long   0x82998312	/* 008C(351):    LCD: idx3 = var5; idx3 > var12; idx3 += inc2 */
+.long   0x0a2ac790	/* 0090(354):      DRD1A: *idx1 = *idx2; FN=0 TFD init=17 WS=1 RS=1 */
+.long   0x81988000	/* 0094(359):    LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long   0x60000002	/* 0098(361):      DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=0 RS=0 */
+.long   0x0c4cfc4d	/* 009C(361):      DRD2B1: *idx1 = EU3(); EU3(*idx1,var13)  */
+.long   0xc21883ad	/* 00A0(365):    LCDEXT: idx1 = var4; idx1 == var14; idx1 += inc5 */
+.long   0x80190000	/* 00A4(365):    LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
+.long   0x04008460	/* 00A8(367):      DRD1A: idx1 = var12; FN=0 INT init=0 WS=0 RS=0 */
+.long   0xc4052305	/* 00AC(371):    LCDEXT: idx1 = var8, idx2 = var10; idx2 == var12; idx1 += inc0, idx2 += inc5 */
+.long   0x81ca0000	/* 00B0(372):    LCD: idx3 = var3 + var20; idx3 once var0; idx3 += inc0 */
+.long   0x1000c718	/* 00B4(374):      DRD1A: *idx1 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x00000f18	/* 00B8(375):      DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
+.long   0xc4188000	/* 00BC(378):    LCDEXT: idx1 = var8; idx1 once var0; idx1 += inc0 */
+.long   0x85190312	/* 00C0(378):    LCD: idx2 = var10; idx2 > var12; idx2 += inc2 */
+.long   0x10000c00	/* 00C4(380):      DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x1000c400	/* 00C8(381):      DRD1A: *idx1 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x00008860	/* 00CC(382):      DRD1A: idx2 = var12; FN=0 init=0 WS=0 RS=0 */
+.long   0x81988000	/* 00D0(386):    LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long   0x10000788	/* 00D4(388):      DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long   0x60000000	/* 00D8(389):      DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long   0x080cf04d	/* 00DC(389):      DRD2B1: idx0 = EU3(); EU3(var1,var13)  */
+.long   0x000001f8	/* 00E0(:0):    NOP */
+
+.align 8
+
+.globl scEthernetRecv_VarTab
+scEthernetRecv_VarTab:	/* Task 0 Variable Table */
+.long   0x00000000	/* var[0] */
+.long   0x00000000	/* var[1] */
+.long   0x00000000	/* var[2] */
+.long   0x00000000	/* var[3] */
+.long   0x00000000	/* var[4] */
+.long   0x00000000	/* var[5] */
+.long   0x00000000	/* var[6] */
+.long   0x00000000	/* var[7] */
+.long   0x00000000	/* var[8] */
+.long   0xf0025b00	/* var[9] */
+.long   0x00000008	/* var[10] */
+.long   0x0000000c	/* var[11] */
+.long   0x80000000	/* var[12] */
+.long   0x00000000	/* var[13] */
+.long   0x10000000	/* var[14] */
+.long   0x20000000	/* var[15] */
+.long   0x00000800	/* var[16] */
+.long   0x00000001	/* var[17] */
+.long   0x00000000	/* var[18] */
+.long   0x00000000	/* var[19] */
+.long   0x00000000	/* var[20] */
+.long   0x00000000	/* var[21] */
+.long   0x00000000	/* var[22] */
+.long   0x00000000	/* var[23] */
+.long   0x00000000	/* inc[0] */
+.long   0x60000000	/* inc[1] */
+.long   0x20000004	/* inc[2] */
+.long   0x20000001	/* inc[3] */
+.long   0x80000000	/* inc[4] */
+.long   0x40000000	/* inc[5] */
+.long   0x00000000	/* inc[6] */
+.long   0x00000000	/* inc[7] */
+
+.align  8
+
+.globl scEthernetXmit_VarTab
+scEthernetXmit_VarTab:	/* Task 1 Variable Table */
+.long   0x00000000	/* var[0] */
+.long   0x00000000	/* var[1] */
+.long   0x00000000	/* var[2] */
+.long   0x00000000	/* var[3] */
+.long   0x00000000	/* var[4] */
+.long   0x00000000	/* var[5] */
+.long   0x00000000	/* var[6] */
+.long   0x00000000	/* var[7] */
+.long   0x00000000	/* var[8] */
+.long   0x00000000	/* var[9] */
+.long   0x00000000	/* var[10] */
+.long   0xf0025b00	/* var[11] */
+.long   0x00000000	/* var[12] */
+.long   0x80000000	/* var[13] */
+.long   0x10000000	/* var[14] */
+.long   0x08000000	/* var[15] */
+.long   0x20000000	/* var[16] */
+.long   0x0000ffff	/* var[17] */
+.long   0xffffffff	/* var[18] */
+.long   0x00000004	/* var[19] */
+.long   0x00000008	/* var[20] */
+.long   0x00000000	/* var[21] */
+.long   0x00000000	/* var[22] */
+.long   0x00000000	/* var[23] */
+.long   0x00000000	/* inc[0] */
+.long   0x60000000	/* inc[1] */
+.long   0x40000000	/* inc[2] */
+.long   0xc000fffc	/* inc[3] */
+.long   0xe0000004	/* inc[4] */
+.long   0x80000000	/* inc[5] */
+.long   0x4000ffff	/* inc[6] */
+.long   0xe0000001	/* inc[7] */
+
+.align 8
+
+.globl scEthernetRecv_FDT
+scEthernetRecv_FDT:	/* Task 0 Function Descriptor Table */
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x21800000	/* and(), EU# 3 */
+.long   0x21e00000	/* or(), EU# 3 */
+.long   0x21400000	/* andn(), EU# 3 */
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+
+.align 8
+
+.globl scEthernetXmit_FDT
+scEthernetXmit_FDT:	/* Task 1 Function Descriptor Table */
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x21800000	/* and(), EU# 3 */
+.long   0x21e00000	/* or(), EU# 3 */
+.long   0x21400000	/* andn(), EU# 3 */
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+.long   0x00000000
+
+
+.globl scEthernetRecv_CSave
+scEthernetRecv_CSave:	/* Task 0 context save space */
+.space  128, 0x0
+
+
+.globl scEthernetXmit_CSave
+scEthernetXmit_CSave:	/* Task 1 context save space */
+.space  128, 0x0
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8220/i2c.c b/arch/powerpc/cpu/mpc8220/i2c.c
new file mode 100644
index 0000000..76ecdf1
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/i2c.c
@@ -0,0 +1,390 @@
+/*
+ * (C) Copyright 2004, Freescale, Inc
+ * TsiChung Liew, Tsi-Chung.Liew@freescale.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_HARD_I2C
+
+#include <mpc8220.h>
+#include <i2c.h>
+
+typedef struct mpc8220_i2c {
+	volatile u32 adr;	/* I2Cn + 0x00 */
+	volatile u32 fdr;	/* I2Cn + 0x04 */
+	volatile u32 cr;	/* I2Cn + 0x08 */
+	volatile u32 sr;	/* I2Cn + 0x0C */
+	volatile u32 dr;	/* I2Cn + 0x10 */
+} i2c_t;
+
+/* I2Cn control register bits */
+#define I2C_EN      0x80
+#define I2C_IEN     0x40
+#define I2C_STA     0x20
+#define I2C_TX      0x10
+#define I2C_TXAK    0x08
+#define I2C_RSTA    0x04
+#define I2C_INIT_MASK   (I2C_EN | I2C_STA | I2C_TX | I2C_RSTA)
+
+/* I2Cn status register bits */
+#define I2C_CF      0x80
+#define I2C_AAS     0x40
+#define I2C_BB      0x20
+#define I2C_AL      0x10
+#define I2C_SRW     0x04
+#define I2C_IF      0x02
+#define I2C_RXAK    0x01
+
+#define I2C_TIMEOUT 100
+#define I2C_RETRIES 1
+
+struct mpc8220_i2c_tap {
+	int scl2tap;
+	int tap2tap;
+};
+
+static int mpc_reg_in (volatile u32 * reg);
+static void mpc_reg_out (volatile u32 * reg, int val, int mask);
+static int wait_for_bb (void);
+static int wait_for_pin (int *status);
+static int do_address (uchar chip, char rdwr_flag);
+static int send_bytes (uchar chip, char *buf, int len);
+static int receive_bytes (uchar chip, char *buf, int len);
+static int mpc_get_fdr (int);
+
+static int mpc_reg_in (volatile u32 * reg)
+{
+	int ret;
+	ret = *reg >> 24;
+	__asm__ __volatile__ ("eieio");
+	return ret;
+}
+
+static void mpc_reg_out (volatile u32 * reg, int val, int mask)
+{
+	int tmp;
+
+	if (!mask) {
+		*reg = val << 24;
+	} else {
+		tmp = mpc_reg_in (reg);
+		*reg = ((tmp & ~mask) | (val & mask)) << 24;
+	}
+	__asm__ __volatile__ ("eieio");
+
+	return;
+}
+
+static int wait_for_bb (void)
+{
+	i2c_t *regs = (i2c_t *) MMAP_I2C;
+	int timeout = I2C_TIMEOUT;
+	int status;
+
+	status = mpc_reg_in (&regs->sr);
+
+	while (timeout-- && (status & I2C_BB)) {
+#if 1
+		volatile int temp;
+
+		mpc_reg_out (&regs->cr, I2C_STA, I2C_STA);
+		temp = mpc_reg_in (&regs->dr);
+		mpc_reg_out (&regs->cr, 0, I2C_STA);
+		mpc_reg_out (&regs->cr, 0, 0);
+		mpc_reg_out (&regs->cr, I2C_EN, 0);
+#endif
+		udelay (1000);
+		status = mpc_reg_in (&regs->sr);
+	}
+
+	return (status & I2C_BB);
+}
+
+static int wait_for_pin (int *status)
+{
+	i2c_t *regs = (i2c_t *) MMAP_I2C;
+	int timeout = I2C_TIMEOUT;
+
+	*status = mpc_reg_in (&regs->sr);
+
+	while (timeout-- && !(*status & I2C_IF)) {
+		udelay (1000);
+		*status = mpc_reg_in (&regs->sr);
+	}
+
+	if (!(*status & I2C_IF)) {
+		return -1;
+	}
+
+	mpc_reg_out (&regs->sr, 0, I2C_IF);
+	return 0;
+}
+
+static int do_address (uchar chip, char rdwr_flag)
+{
+	i2c_t *regs = (i2c_t *) MMAP_I2C;
+	int status;
+
+	chip <<= 1;
+
+	if (rdwr_flag)
+		chip |= 1;
+
+	mpc_reg_out (&regs->cr, I2C_TX, I2C_TX);
+	mpc_reg_out (&regs->dr, chip, 0);
+
+	if (wait_for_pin (&status))
+		return -2;
+	if (status & I2C_RXAK)
+		return -3;
+	return 0;
+}
+
+static int send_bytes (uchar chip, char *buf, int len)
+{
+	i2c_t *regs = (i2c_t *) MMAP_I2C;
+	int wrcount;
+	int status;
+
+	for (wrcount = 0; wrcount < len; ++wrcount) {
+
+		mpc_reg_out (&regs->dr, buf[wrcount], 0);
+
+		if (wait_for_pin (&status))
+			break;
+
+		if (status & I2C_RXAK)
+			break;
+
+	}
+
+	return !(wrcount == len);
+	return 0;
+}
+
+static int receive_bytes (uchar chip, char *buf, int len)
+{
+	i2c_t *regs = (i2c_t *) MMAP_I2C;
+	int dummy = 1;
+	int rdcount = 0;
+	int status;
+	int i;
+
+	mpc_reg_out (&regs->cr, 0, I2C_TX);
+
+	for (i = 0; i < len; ++i) {
+		buf[rdcount] = mpc_reg_in (&regs->dr);
+
+		if (dummy)
+			dummy = 0;
+		else
+			rdcount++;
+
+		if (wait_for_pin (&status))
+			return -4;
+	}
+
+	mpc_reg_out (&regs->cr, I2C_TXAK, I2C_TXAK);
+	buf[rdcount++] = mpc_reg_in (&regs->dr);
+
+	if (wait_for_pin (&status))
+		return -5;
+
+	mpc_reg_out (&regs->cr, 0, I2C_TXAK);
+	return 0;
+}
+
+/**************** I2C API ****************/
+
+void i2c_init (int speed, int saddr)
+{
+	i2c_t *regs = (i2c_t *) MMAP_I2C;
+
+	mpc_reg_out (&regs->cr, 0, 0);
+	mpc_reg_out (&regs->adr, saddr << 1, 0);
+
+	/* Set clock
+	 */
+	mpc_reg_out (&regs->fdr, mpc_get_fdr (speed), 0);
+
+	/* Enable module
+	 */
+	mpc_reg_out (&regs->cr, I2C_EN, I2C_INIT_MASK);
+	mpc_reg_out (&regs->sr, 0, I2C_IF);
+	return;
+}
+
+static int mpc_get_fdr (int speed)
+{
+	static int fdr = -1;
+
+	if (fdr == -1) {
+		ulong best_speed = 0;
+		ulong divider;
+		ulong ipb, scl;
+		ulong bestmatch = 0xffffffffUL;
+		int best_i = 0, best_j = 0, i, j;
+		int SCL_Tap[] = { 9, 10, 12, 15, 5, 6, 7, 8 };
+		struct mpc8220_i2c_tap scltap[] = {
+			{4, 1},
+			{4, 2},
+			{6, 4},
+			{6, 8},
+			{14, 16},
+			{30, 32},
+			{62, 64},
+			{126, 128}
+		};
+
+		ipb = gd->bus_clk;
+		for (i = 7; i >= 0; i--) {
+			for (j = 7; j >= 0; j--) {
+				scl = 2 * (scltap[j].scl2tap +
+					   (SCL_Tap[i] -
+					    1) * scltap[j].tap2tap + 2);
+				if (ipb <= speed * scl) {
+					if ((speed * scl - ipb) < bestmatch) {
+						bestmatch = speed * scl - ipb;
+						best_i = i;
+						best_j = j;
+						best_speed = ipb / scl;
+					}
+				}
+			}
+		}
+		divider = (best_i & 3) | ((best_i & 4) << 3) | (best_j << 2);
+		if (gd->flags & GD_FLG_RELOC) {
+			fdr = divider;
+		} else {
+			printf ("%ld kHz, ", best_speed / 1000);
+			return divider;
+		}
+	}
+
+	return fdr;
+}
+
+int i2c_probe (uchar chip)
+{
+	i2c_t *regs = (i2c_t *) MMAP_I2C;
+	int i;
+
+	for (i = 0; i < I2C_RETRIES; i++) {
+		mpc_reg_out (&regs->cr, I2C_STA, I2C_STA);
+
+		if (!do_address (chip, 0)) {
+			mpc_reg_out (&regs->cr, 0, I2C_STA);
+			break;
+		}
+
+		mpc_reg_out (&regs->cr, 0, I2C_STA);
+		udelay (50);
+	}
+
+	return (i == I2C_RETRIES);
+}
+
+int i2c_read (uchar chip, uint addr, int alen, uchar * buf, int len)
+{
+	uchar xaddr[4];
+	i2c_t *regs = (i2c_t *) MMAP_I2C;
+	int ret = -1;
+
+	xaddr[0] = (addr >> 24) & 0xFF;
+	xaddr[1] = (addr >> 16) & 0xFF;
+	xaddr[2] = (addr >> 8) & 0xFF;
+	xaddr[3] = addr & 0xFF;
+
+	if (wait_for_bb ()) {
+		printf ("i2c_read: bus is busy\n");
+		goto Done;
+	}
+
+	mpc_reg_out (&regs->cr, I2C_STA, I2C_STA);
+	if (do_address (chip, 0)) {
+		printf ("i2c_read: failed to address chip\n");
+		goto Done;
+	}
+
+	if (send_bytes (chip, (char *)&xaddr[4 - alen], alen)) {
+		printf ("i2c_read: send_bytes failed\n");
+		goto Done;
+	}
+
+	mpc_reg_out (&regs->cr, I2C_RSTA, I2C_RSTA);
+	if (do_address (chip, 1)) {
+		printf ("i2c_read: failed to address chip\n");
+		goto Done;
+	}
+
+	if (receive_bytes (chip, (char *)buf, len)) {
+		printf ("i2c_read: receive_bytes failed\n");
+		goto Done;
+	}
+
+	ret = 0;
+      Done:
+	mpc_reg_out (&regs->cr, 0, I2C_STA);
+	return ret;
+}
+
+int i2c_write (uchar chip, uint addr, int alen, uchar * buf, int len)
+{
+	uchar xaddr[4];
+	i2c_t *regs = (i2c_t *) MMAP_I2C;
+	int ret = -1;
+
+	xaddr[0] = (addr >> 24) & 0xFF;
+	xaddr[1] = (addr >> 16) & 0xFF;
+	xaddr[2] = (addr >> 8) & 0xFF;
+	xaddr[3] = addr & 0xFF;
+
+	if (wait_for_bb ()) {
+		printf ("i2c_write: bus is busy\n");
+		goto Done;
+	}
+
+	mpc_reg_out (&regs->cr, I2C_STA, I2C_STA);
+	if (do_address (chip, 0)) {
+		printf ("i2c_write: failed to address chip\n");
+		goto Done;
+	}
+
+	if (send_bytes (chip, (char *)&xaddr[4 - alen], alen)) {
+		printf ("i2c_write: send_bytes failed\n");
+		goto Done;
+	}
+
+	if (send_bytes (chip, (char *)buf, len)) {
+		printf ("i2c_write: send_bytes failed\n");
+		goto Done;
+	}
+
+	ret = 0;
+      Done:
+	mpc_reg_out (&regs->cr, 0, I2C_STA);
+	return ret;
+}
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/arch/powerpc/cpu/mpc8220/i2cCore.c b/arch/powerpc/cpu/mpc8220/i2cCore.c
new file mode 100644
index 0000000..b89ad03
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/i2cCore.c
@@ -0,0 +1,627 @@
+/* I2cCore.c - MPC8220 PPC I2C Library */
+
+/* Copyright 2004      Freescale Semiconductor, Inc. */
+
+/*
+modification history
+--------------------
+01c,29jun04,tcl	 1.3	removed CR. Added two bytes offset support.
+01b,19jan04,tcl	 1.2	removed i2cMsDelay and sysDecGet. renamed i2cMsDelay
+			back to sysMsDelay
+01a,19jan04,tcl	 1.1	created and seperated from i2c.c
+*/
+
+/*
+DESCRIPTION
+This file contain I2C low level handling library functions
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vxWorks.h>
+#include <sysLib.h>
+#include <iosLib.h>
+#include <logLib.h>
+#include <tickLib.h>
+
+/* BSP Includes */
+#include "config.h"
+#include "mpc8220.h"
+#include "i2cCore.h"
+
+#ifdef DEBUG_I2CCORE
+int I2CCDbg = 0;
+#endif
+
+#define ABS(x)	((x < 0)? -x : x)
+
+char *I2CERR[16] = {
+	"Transfer in Progress\n",	/* 0 */
+	"Transfer complete\n",
+	"Not Addressed\n",		/* 2 */
+	"Addressed as a slave\n",
+	"Bus is Idle\n",		/* 4 */
+	"Bus is busy\n",
+	"Arbitration Lost\n",		/* 6 */
+	"Arbitration on Track\n",
+	"Slave receive, master writing to slave\n",	/* 8 */
+	"Slave transmit, master reading from slave\n",
+	"Interrupt is pending\n",	/* 10 */
+	"Interrupt complete\n",
+	"Acknowledge received\n",	/* 12 */
+	"No acknowledge received\n",
+	"Unknown status\n",		/* 14 */
+	"\n"
+};
+
+/******************************************************************************
+ *
+ * chk_status - Check I2C status bit
+ *
+ * RETURNS: OK, or ERROR if the bit encounter
+ *
+ */
+
+STATUS chk_status (PSI2C pi2c, UINT8 sta_bit, UINT8 truefalse)
+{
+	int i, status = 0;
+
+	for (i = 0; i < I2C_POLL_COUNT; i++) {
+		if ((pi2c->sr & sta_bit) == (truefalse ? sta_bit : 0))
+			return (OK);
+	}
+
+	I2CCDBG (L2, ("--- sr %x stabit %x truefalse %d\n",
+		      pi2c->sr, sta_bit, truefalse, 0, 0, 0));
+
+	if (i == I2C_POLL_COUNT) {
+		switch (sta_bit) {
+		case I2C_STA_CF:
+			status = 0;
+			break;
+		case I2C_STA_AAS:
+			status = 2;
+			break;
+		case I2C_STA_BB:
+			status = 4;
+			break;
+		case I2C_STA_AL:
+			status = 6;
+			break;
+		case I2C_STA_SRW:
+			status = 8;
+			break;
+		case I2C_STA_IF:
+			status = 10;
+			break;
+		case I2C_STA_RXAK:
+			status = 12;
+			break;
+		default:
+			status = 14;
+			break;
+		}
+
+		if (!truefalse)
+			status++;
+
+		I2CCDBG (NO, ("--- status %d\n", status, 0, 0, 0, 0, 0));
+		I2CCDBG (NO, (I2CERR[status], 0, 0, 0, 0, 0, 0));
+	}
+
+	return (ERROR);
+}
+
+/******************************************************************************
+ *
+ * I2C Enable - Enable the I2C Controller
+ *
+ */
+STATUS i2c_enable (SI2C * pi2c, PI2CSET pi2cSet)
+{
+	int fdr = pi2cSet->bit_rate;
+	UINT8 adr = pi2cSet->i2c_adr;
+
+	I2CCDBG (L2, ("i2c_enable fdr %d adr %x\n", fdr, adr, 0, 0, 0, 0));
+
+	i2c_clear (pi2c);	/* Clear FDR, ADR, SR and CR reg */
+
+	SetI2cFDR (pi2c, fdr);	/* Frequency			*/
+	pi2c->adr = adr;
+
+	pi2c->cr = I2C_CTL_EN;	/* Set Enable			*/
+
+	/*
+	   The I2C bus should be in Idle state. If the bus is busy,
+	   clear the STA bit in control register
+	 */
+	if (chk_status (pi2c, I2C_STA_BB, 0) != OK) {
+		if ((pi2c->cr & I2C_CTL_STA) == I2C_CTL_STA)
+			pi2c->cr &= ~I2C_CTL_STA;
+
+		/* Check again if it is still busy, return error if found */
+		if (chk_status (pi2c, I2C_STA_BB, 1) == OK)
+			return ERROR;
+	}
+
+	return (OK);
+}
+
+/******************************************************************************
+ *
+ * I2C Disable - Disable the I2C Controller
+ *
+ */
+STATUS i2c_disable (PSI2C pi2c)
+{
+	i2c_clear (pi2c);
+
+	pi2c->cr &= I2C_CTL_EN; /* Disable I2c			*/
+
+	if ((pi2c->cr & I2C_CTL_STA) == I2C_CTL_STA)
+		pi2c->cr &= ~I2C_CTL_STA;
+
+	if (chk_status (pi2c, I2C_STA_BB, 0) != OK)
+		return ERROR;
+
+	return (OK);
+}
+
+/******************************************************************************
+ *
+ * I2C Clear - Clear the I2C Controller
+ *
+ */
+STATUS i2c_clear (PSI2C pi2c)
+{
+	pi2c->adr = 0;
+	pi2c->fdr = 0;
+	pi2c->cr = 0;
+	pi2c->sr = 0;
+
+	return (OK);
+}
+
+
+STATUS i2c_start (PSI2C pi2c, PI2CSET pi2cSet)
+{
+#ifdef TWOBYTES
+	UINT16 ByteOffset = pi2cSet->str_adr;
+#else
+	UINT8 ByteOffset = pi2cSet->str_adr;
+#endif
+#if 1
+	UINT8 tmp = 0;
+#endif
+	UINT8 Addr = pi2cSet->slv_adr;
+
+	pi2c->cr |= I2C_CTL_STA;	/* Generate start signal	*/
+
+	if (chk_status (pi2c, I2C_STA_BB, 1) != OK)
+		return ERROR;
+
+	/* Write slave address */
+	if (i2c_writebyte (pi2c, &Addr) != OK) {
+		i2c_stop (pi2c);	/* Disable I2c			*/
+		return ERROR;
+	}
+#ifdef TWOBYTES
+#   if 0
+	/* Issue the offset to start */
+	if (i2c_write2byte (pi2c, &ByteOffset) != OK) {
+		i2c_stop (pi2c);	/* Disable I2c			*/
+		return ERROR;
+	}
+#endif
+	tmp = (ByteOffset >> 8) & 0xff;
+	if (i2c_writebyte (pi2c, &tmp) != OK) {
+		i2c_stop (pi2c);	/* Disable I2c			*/
+		return ERROR;
+	}
+	tmp = ByteOffset & 0xff;
+	if (i2c_writebyte (pi2c, &tmp) != OK) {
+		i2c_stop (pi2c);	/* Disable I2c			*/
+		return ERROR;
+	}
+#else
+	if (i2c_writebyte (pi2c, &ByteOffset) != OK) {
+		i2c_stop (pi2c);	/* Disable I2c			*/
+		return ERROR;
+	}
+#endif
+
+	return (OK);
+}
+
+STATUS i2c_stop (PSI2C pi2c)
+{
+	pi2c->cr &= ~I2C_CTL_STA;	/* Generate stop signal		*/
+	if (chk_status (pi2c, I2C_STA_BB, 0) != OK)
+		return ERROR;
+
+	return (OK);
+}
+
+/******************************************************************************
+ *
+ * Read Len bytes to the location pointed to by *Data from the device
+ * with address Addr.
+ */
+int i2c_readblock (SI2C * pi2c, PI2CSET pi2cSet, UINT8 * Data)
+{
+	int i = 0;
+	UINT8 Tmp;
+
+/*    UINT8 ByteOffset = pi2cSet->str_adr; not used? */
+	UINT8 Addr = pi2cSet->slv_adr;
+	int Length = pi2cSet->xfer_size;
+
+	I2CCDBG (L1, ("i2c_readblock addr %x data 0x%08x len %d offset %d\n",
+		      Addr, (int) Data, Length, ByteOffset, 0, 0));
+
+	if (pi2c->sr & I2C_STA_AL) {	/* Check if Arbitration lost	*/
+		I2CCDBG (FN, ("Arbitration lost\n", 0, 0, 0, 0, 0, 0));
+		pi2c->sr &= ~I2C_STA_AL;	/* Clear Arbitration status bit */
+		return ERROR;
+	}
+
+	pi2c->cr |= I2C_CTL_TX; /* Enable the I2c for TX, Ack	*/
+
+	if (i2c_start (pi2c, pi2cSet) == ERROR)
+		return ERROR;
+
+	pi2c->cr |= I2C_CTL_RSTA;	/* Repeat Start */
+
+	Tmp = Addr | 1;
+
+	if (i2c_writebyte (pi2c, &Tmp) != OK) {
+		i2c_stop (pi2c);	/* Disable I2c	*/
+		return ERROR;
+	}
+
+	if (((pi2c->sr & 0x07) == 0x07) || (pi2c->sr & 0x01))
+		return ERROR;
+
+	pi2c->cr &= ~I2C_CTL_TX;	/* Set receive mode	*/
+
+	if (((pi2c->sr & 0x07) == 0x07) || (pi2c->sr & 0x01))
+		return ERROR;
+
+	/* Dummy Read */
+	if (i2c_readbyte (pi2c, &Tmp, &i) != OK) {
+		i2c_stop (pi2c);	/* Disable I2c	*/
+		return ERROR;
+	}
+
+	i = 0;
+	while (Length) {
+		if (Length == 2)
+			pi2c->cr |= I2C_CTL_TXAK;
+
+		if (Length == 1)
+			pi2c->cr &= ~I2C_CTL_STA;
+
+		if (i2c_readbyte (pi2c, Data, &Length) != OK) {
+			return i2c_stop (pi2c);
+		}
+		i++;
+		Length--;
+		Data++;
+	}
+
+	if (i2c_stop (pi2c) == ERROR)
+		return ERROR;
+
+	return i;
+}
+
+STATUS i2c_writeblock (SI2C * pi2c, PI2CSET pi2cSet, UINT8 * Data)
+{
+	int Length = pi2cSet->xfer_size;
+
+#ifdef TWOBYTES
+	UINT16 ByteOffset = pi2cSet->str_adr;
+#else
+	UINT8 ByteOffset = pi2cSet->str_adr;
+#endif
+	int j, k;
+
+	I2CCDBG (L2, ("i2c_writeblock\n", 0, 0, 0, 0, 0, 0));
+
+	if (pi2c->sr & I2C_STA_AL) {
+		/* Check if arbitration lost */
+		I2CCDBG (L2, ("Arbitration lost\n", 0, 0, 0, 0, 0, 0));
+		pi2c->sr &= ~I2C_STA_AL;	/* Clear the condition	*/
+		return ERROR;
+	}
+
+	pi2c->cr |= I2C_CTL_TX; /* Enable the I2c for TX, Ack	*/
+
+	/* Do the not even offset first */
+	if ((ByteOffset % 8) != 0) {
+		int remain;
+
+		if (Length > 8) {
+			remain = 8 - (ByteOffset % 8);
+			Length -= remain;
+
+			pi2cSet->str_adr = ByteOffset;
+
+			if (i2c_start (pi2c, pi2cSet) == ERROR)
+				return ERROR;
+
+			for (j = ByteOffset; j < remain; j++) {
+				if (i2c_writebyte (pi2c, Data++) != OK)
+					return ERROR;
+			}
+
+			if (i2c_stop (pi2c) == ERROR)
+				return ERROR;
+
+			sysMsDelay (32);
+
+			/* Update the new ByteOffset */
+			ByteOffset += remain;
+		}
+	}
+
+	for (j = ByteOffset, k = 0; j < (Length + ByteOffset); j++) {
+		if ((j % 8) == 0) {
+			pi2cSet->str_adr = j;
+			if (i2c_start (pi2c, pi2cSet) == ERROR)
+				return ERROR;
+		}
+
+		k++;
+
+		if (i2c_writebyte (pi2c, Data++) != OK)
+			return ERROR;
+
+		if ((j == (Length - 1)) || ((k % 8) == 0)) {
+			if (i2c_stop (pi2c) == ERROR)
+				return ERROR;
+
+			sysMsDelay (50);
+		}
+
+	}
+
+	return k;
+}
+
+STATUS i2c_readbyte (SI2C * pi2c, UINT8 * readb, int *index)
+{
+	pi2c->sr &= ~I2C_STA_IF;	/* Clear Interrupt Bit	*/
+	*readb = pi2c->dr;		/* Read a byte		*/
+
+	/*
+	   Set I2C_CTRL_TXAK will cause Transfer pending and
+	   set I2C_CTRL_STA will cause Interrupt pending
+	 */
+	if (*index != 2) {
+		if (chk_status (pi2c, I2C_STA_CF, 1) != OK)	/* Transfer not complete?	*/
+			return ERROR;
+	}
+
+	if (*index != 1) {
+		if (chk_status (pi2c, I2C_STA_IF, 1) != OK)
+			return ERROR;
+	}
+
+	return (OK);
+}
+
+
+STATUS i2c_writebyte (SI2C * pi2c, UINT8 * writeb)
+{
+	pi2c->sr &= ~I2C_STA_IF;	/* Clear Interrupt	*/
+	pi2c->dr = *writeb;		/* Write a byte		*/
+
+	if (chk_status (pi2c, I2C_STA_CF, 1) != OK)	/* Transfer not complete?	*/
+		return ERROR;
+
+	if (chk_status (pi2c, I2C_STA_IF, 1) != OK)
+		return ERROR;
+
+	return OK;
+}
+
+STATUS i2c_write2byte (SI2C * pi2c, UINT16 * writeb)
+{
+	UINT8 data;
+
+	data = (UINT8) ((*writeb >> 8) & 0xff);
+	if (i2c_writebyte (pi2c, &data) != OK)
+		return ERROR;
+	data = (UINT8) (*writeb & 0xff);
+	if (i2c_writebyte (pi2c, &data) != OK)
+		return ERROR;
+	return OK;
+}
+
+/* FDR table base on 33MHz - more detail please refer to Odini2c_dividers.xls
+FDR FDR scl sda scl2tap2
+510 432 tap tap tap tap scl_per	    sda_hold	I2C Freq    0	1   2	3   4	5
+000 000 9   3	4   1	28 Clocks   9 Clocks	1190 KHz    0	0   0	0   0	0
+000 001 9   3	4   2	44 Clocks   11 Clocks	758 KHz	    0	0   1	0   0	0
+000 010 9   3	6   4	80 Clocks   17 Clocks	417 KHz	    0	0   0	1   0	0
+000 011 9   3	6   8	144 Clocks  25 Clocks	231 KHz	    0	0   1	1   0	0
+000 100 9   3	14  16	288 Clocks  49 Clocks	116 KHz	    0	0   0	0   1	0
+000 101 9   3	30  32	576 Clocks  97 Clocks	58 KHz	    0	0   1	0   1	0
+000 110 9   3	62  64	1152 Clocks 193 Clocks	29 KHz	    0	0   0	1   1	0
+000 111 9   3	126 128 2304 Clocks 385 Clocks	14 KHz	    0	0   1	1   1	0
+001 000 10  3	4   1	30 Clocks   9 Clocks	1111 KHz1   0	0   0	0   0
+001 001 10  3	4   2	48 Clocks   11 Clocks	694 KHz	    1	0   1	0   0	0
+001 010 10  3	6   4	88 Clocks   17 Clocks	379 KHz	    1	0   0	1   0	0
+001 011 10  3	6   8	160 Clocks  25 Clocks	208 KHz	    1	0   1	1   0	0
+001 100 10  3	14  16	320 Clocks  49 Clocks	104 KHz	    1	0   0	0   1	0
+001 101 10  3	30  32	640 Clocks  97 Clocks	52 KHz	    1	0   1	0   1	0
+001 110 10  3	62  64	1280 Clocks 193 Clocks	26 KHz	    1	0   0	1   1	0
+001 111 10  3	126 128 2560 Clocks 385 Clocks	13 KHz	    1	0   1	1   1	0
+010 000 12  4	4   1	34 Clocks   10 Clocks	980 KHz	    0	1   0	0   0	0
+010 001 12  4	4   2	56 Clocks   13 Clocks	595 KHz	    0	1   1	0   0	0
+010 010 12  4	6   4	104 Clocks  21 Clocks	321 KHz	    0	1   0	1   0	0
+010 011 12  4	6   8	192 Clocks  33 Clocks	174 KHz	    0	1   1	1   0	0
+010 100 12  4	14  16	384 Clocks  65 Clocks	87 KHz	    0	1   0	0   1	0
+010 101 12  4	30  32	768 Clocks  129 Clocks	43 KHz	    0	1   1	0   1	0
+010 110 12  4	62  64	1536 Clocks 257 Clocks	22 KHz	    0	1   0	1   1	0
+010 111 12  4	126 128 3072 Clocks 513 Clocks	11 KHz	    0	1   1	1   1	0
+011 000 15  4	4   1	40 Clocks   10 Clocks	833 KHz	    1	1   0	0   0	0
+011 001 15  4	4   2	68 Clocks   13 Clocks	490 KHz	    1	1   1	0   0	0
+011 010 15  4	6   4	128 Clocks  21 Clocks	260 KHz	    1	1   0	1   0	0
+011 011 15  4	6   8	240 Clocks  33 Clocks	139 KHz	    1	1   1	1   0	0
+011 100 15  4	14  16	480 Clocks  65 Clocks	69 KHz	    1	1   0	0   1	0
+011 101 15  4	30  32	960 Clocks  129 Clocks	35 KHz	    1	1   1	0   1	0
+011 110 15  4	62  64	1920 Clocks 257 Clocks	17 KHz	    1	1   0	1   1	0
+011 111 15  4	126 128 3840 Clocks 513 Clocks	9 KHz	    1	1   1	1   1	0
+100 000 5   1	4   1	20 Clocks   7 Clocks	1667 KHz    0	0   0	0   0	1
+100 001 5   1	4   2	28 Clocks   7 Clocks	1190 KHz    0	0   1	0   0	1
+100 010 5   1	6   4	48 Clocks   9 Clocks	694 KHz	    0	0   0	1   0	1
+100 011 5   1	6   8	80 Clocks   9 Clocks	417 KHz	    0	0   1	1   0	1
+100 100 5   1	14  16	160 Clocks  17 Clocks	208 KHz	    0	0   0	0   1	1
+100 101 5   1	30  32	320 Clocks  33 Clocks	104 KHz	    0	0   1	0   1	1
+100 110 5   1	62  64	640 Clocks  65 Clocks	52 KHz	    0	0   0	1   1	1
+100 111 5   1	126 128 1280 Clocks 129 Clocks	26 KHz	    0	0   1	1   1	1
+101 000 6   1	4   1	22 Clocks   7 Clocks	1515 KHz    1	0   0	0   0	1
+101 001 6   1	4   2	32 Clocks   7 Clocks	1042 KHz    1	0   1	0   0	1
+101 010 6   1	6   4	56 Clocks   9 Clocks	595 KHz	    1	0   0	1   0	1
+101 011 6   1	6   8	96 Clocks   9 Clocks	347 KHz	    1	0   1	1   0	1
+101 100 6   1	14  16	192 Clocks  17 Clocks	174 KHz	    1	0   0	0   1	1
+101 101 6   1	30  32	384 Clocks  33 Clocks	87 KHz	    1	0   1	0   1	1
+101 110 6   1	62  64	768 Clocks  65 Clocks	43 KHz	    1	0   0	1   1	1
+101 111 6   1	126 128 1536 Clocks 129 Clocks	22 KHz	    1	0   1	1   1	1
+110 000 7   2	4   1	24 Clocks   8 Clocks	1389 KHz    0	1   0	0   0	1
+110 001 7   2	4   2	36 Clocks   9 Clocks	926 KHz	    0	1   1	0   0	1
+110 010 7   2	6   4	64 Clocks   13 Clocks	521 KHz	    0	1   0	1   0	1
+110 011 7   2	6   8	112 Clocks  17 Clocks	298 KHz	    0	1   1	1   0	1
+110 100 7   2	14  16	224 Clocks  33 Clocks	149 KHz	    0	1   0	0   1	1
+110 101 7   2	30  32	448 Clocks  65 Clocks	74 KHz	    0	1   1	0   1	1
+110 110 7   2	62  64	896 Clocks  129 Clocks	37 KHz	    0	1   0	1   1	1
+110 111 7   2	126 128 1792 Clocks 257 Clocks	19 KHz	    0	1   1	1   1	1
+111 000 8   2	4   1	26 Clocks   8 Clocks	1282 KHz    1	1   0	0   0	1
+111 001 8   2	4   2	40 Clocks   9 Clocks	833 KHz	    1	1   1	0   0	1
+111 010 8   2	6   4	72 Clocks   13 Clocks	463 KHz	    1	1   0	1   0	1
+111 011 8   2	6   8	128 Clocks  17 Clocks	260 KHz	    1	1   1	1   0	1
+111 100 8   2	14  16	256 Clocks  33 Clocks	130 KHz	    1	1   0	0   1	1
+111 101 8   2	30  32	512 Clocks  65 Clocks	65 KHz	    1	1   1	0   1	1
+111 110 8   2	62  64	1024 Clocks 129 Clocks	33 KHz	    1	1   0	1   1	1
+111 111 8   2	126 128 2048 Clocks 257 Clocks	16 KHz	    1	1   1	1   1	1
+*/
+STATUS SetI2cFDR (PSI2C pi2cRegs, int bitrate)
+{
+/* Constants */
+	const UINT8 div_hold[8][3] = { {9, 3}, {10, 3},
+	{12, 4}, {15, 4},
+	{5, 1}, {6, 1},
+	{7, 2}, {8, 2}
+	};
+
+	const UINT8 scl_tap[8][2] = { {4, 1}, {4, 2},
+	{6, 4}, {6, 8},
+	{14, 16}, {30, 32},
+	{62, 64}, {126, 128}
+	};
+
+	UINT8 mfdr_bits;
+
+	int i = 0;
+	int j = 0;
+
+	int Diff, min;
+	int WhichFreq, iRec, jRec;
+	int SCL_Period;
+	int SCL_Hold;
+	int I2C_Freq;
+
+	I2CCDBG (L2, ("Entering getBitRate: bitrate %d pi2cRegs 0x%08x\n",
+		      bitrate, (int) pi2cRegs, 0, 0, 0, 0));
+
+	if (bitrate < 0) {
+		I2CCDBG (NO, ("Invalid bitrate\n", 0, 0, 0, 0, 0, 0));
+		return ERROR;
+	}
+
+	/* Initialize */
+	mfdr_bits = 0;
+	min = 0x7fffffff;
+	WhichFreq = iRec = jRec = 0;
+
+	for (i = 0; i < 8; i++) {
+		for (j = 0; j < 8; j++) {
+			/* SCL Period = 2 * (scl2tap + [(SCL_Tap - 1) * tap2tap] + 2)
+			 * SCL Hold   = scl2tap + ((SDA_Tap - 1) * tap2tap) + 3
+			 * Bit Rate (I2C Freq) = System Freq / SCL Period
+			 */
+			SCL_Period =
+				2 * (scl_tap[i][0] +
+				     ((div_hold[j][0] - 1) * scl_tap[i][1]) +
+				     2);
+
+			/* Now get the I2C Freq */
+			I2C_Freq = DEV_CLOCK_FREQ / SCL_Period;
+
+			/* Take equal or slower */
+			if (I2C_Freq > bitrate)
+				continue;
+
+			/* Take the differences */
+			Diff = I2C_Freq - bitrate;
+
+			Diff = ABS (Diff);
+
+			/* Find the closer value */
+			if (Diff < min) {
+				min = Diff;
+				WhichFreq = I2C_Freq;
+				iRec = i;
+				jRec = j;
+			}
+
+			I2CCDBG (L2,
+				 ("--- (%d,%d) I2C_Freq %d minDiff %d min %d\n",
+				  i, j, I2C_Freq, Diff, min, 0));
+		}
+	}
+
+	SCL_Period =
+		2 * (scl_tap[iRec][0] +
+		     ((div_hold[jRec][0] - 1) * scl_tap[iRec][1]) + 2);
+
+	I2CCDBG (L2, ("\nmin %d WhichFreq %d iRec %d jRec %d\n",
+		      min, WhichFreq, iRec, jRec, 0, 0));
+	I2CCDBG (L2, ("--- scl2tap %d SCL_Tap %d tap2tap %d\n",
+		      scl_tap[iRec][0], div_hold[jRec][0], scl_tap[iRec][1],
+		      0, 0, 0));
+
+	/* This may no require */
+	SCL_Hold =
+		scl_tap[iRec][0] +
+		((div_hold[jRec][1] - 1) * scl_tap[iRec][1]) + 3;
+	I2CCDBG (L2,
+		 ("--- SCL_Period %d SCL_Hold %d\n", SCL_Period, SCL_Hold, 0,
+		  0, 0, 0));
+
+	I2CCDBG (L2, ("--- mfdr_bits %x\n", mfdr_bits, 0, 0, 0, 0, 0));
+
+	/* FDR 4,3,2 */
+	if ((iRec & 1) == 1)
+		mfdr_bits |= 0x04;	/* FDR 2 */
+	if ((iRec & 2) == 2)
+		mfdr_bits |= 0x08;	/* FDR 3 */
+	if ((iRec & 4) == 4)
+		mfdr_bits |= 0x10;	/* FDR 4 */
+	/* FDR 5,1,0 */
+	if ((jRec & 1) == 1)
+		mfdr_bits |= 0x01;	/* FDR 0 */
+	if ((jRec & 2) == 2)
+		mfdr_bits |= 0x02;	/* FDR 1 */
+	if ((jRec & 4) == 4)
+		mfdr_bits |= 0x20;	/* FDR 5 */
+
+	I2CCDBG (L2, ("--- mfdr_bits %x\n", mfdr_bits, 0, 0, 0, 0, 0));
+
+	pi2cRegs->fdr = mfdr_bits;
+
+	return OK;
+}
diff --git a/arch/powerpc/cpu/mpc8220/i2cCore.h b/arch/powerpc/cpu/mpc8220/i2cCore.h
new file mode 100644
index 0000000..72783fd
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/i2cCore.h
@@ -0,0 +1,103 @@
+/*
+ * i2cCore.h
+ *
+ * Prototypes, etc. for the Motorola MPC8220
+ * embedded cpu chips
+ *
+ * 2004 (c) Freescale, Inc.
+ * Author: TsiChung Liew <Tsi-Chung.Liew@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __INCi2ccoreh
+#define __INCi2ccoreh
+#ifndef __ASSEMBLY__
+/* device types */
+#define I2C_DEVICE_TYPE_EEPROM 0
+#define I2C_EEPROM_ADRS 0xa0
+#define I2C_CTRL_ADRS   I2C_EEPROM_ADRS
+#define EEPROM_ADDR0    0xA2	/* on Dimm SPD eeprom */
+#define EEPROM_ADDR1    0xA4	/* on Board SPD eeprom */
+#define EEPROM_ADDR2    0xD2	/* non-standard eeprom - clock generator */
+/* Control Register */
+#define I2C_CTL_EN      0x80	/* I2C Enable                   */
+#define I2C_CTL_IEN     0x40	/* I2C Interrupt Enable         */
+#define I2C_CTL_STA     0x20	/* Master/Slave Mode select     */
+#define I2C_CTL_TX      0x10	/* Transmit/Receive Mode Select */
+#define I2C_CTL_TXAK    0x08	/* Transmit Acknowledge Enable  */
+#define I2C_CTL_RSTA    0x04	/* Repeat Start                 */
+/* Status Register */
+#define I2C_STA_CF      0x80	/* Data Transfer       */
+#define I2C_STA_AAS     0x40	/* Adressed As Slave   */
+#define I2C_STA_BB      0x20	/* Bus Busy            */
+#define I2C_STA_AL      0x10	/* Arbitration Lost    */
+#define I2C_STA_SRW     0x04	/* Slave Read/Write    */
+#define I2C_STA_IF      0x02	/* I2C Interrupt       */
+#define I2C_STA_RXAK    0x01	/* Receive Acknowledge */
+/* Interrupt Contol Register */
+#define I2C_INT_BNBE2   0x80	/* Bus Not Busy Enable 2 */
+#define I2C_INT_TE2     0x40	/* Transmit Enable 2     */
+#define I2C_INT_RE2     0x20	/* Receive Enable 2      */
+#define I2C_INT_IE2     0x10	/* Interrupt Enable 2    */
+#define I2C_INT_BNBE1   0x08	/* Bus Not Busy Enable 1 */
+#define I2C_INT_TE1     0x04	/* Transmit Enable 1     */
+#define I2C_INT_RE1     0x02	/* Receive Enable 1      */
+#define I2C_INT_IE1     0x01	/* Interrupt Enable 1    */
+#define I2C_POLL_COUNT 0x100000
+#define I2C_ENABLE      0x00000001
+#define I2C_DISABLE     0x00000002
+#define I2C_START       0x00000004
+#define I2C_REPSTART    0x00000008
+#define I2C_STOP        0x00000010
+#define I2C_BITRATE     0x00000020
+#define I2C_SLAVEADR    0x00000040
+#define I2C_STARTADR    0x00000080
+#undef TWOBYTES
+typedef struct i2c_settings {
+	/* Device settings */
+	int bit_rate;		/* Device bit rate */
+	u8 i2c_adr;		/* I2C address */
+	u8 slv_adr;		/* Slave address */
+#ifdef TWOBYTES
+	u16 str_adr;		/* Start address */
+#else
+	u8 str_adr;		/* Start address */
+#endif
+	int xfer_size;		/* Transfer Size */
+
+	int bI2c_en;		/* Enable or Disable */
+	int cmdFlag;		/* I2c Command Flags */
+} i2cset_t;
+
+/*
+int check_status(PSI2C pi2c, u8 sta_bit, u8 truefalse);
+int i2c_enable(PSI2C pi2c, PI2CSET pi2cSet);
+int i2c_disable(PSI2C pi2c);
+int i2c_start(PSI2C pi2c, PI2CSET pi2cSet);
+int i2c_stop(PSI2C pi2c);
+int i2c_clear(PSI2C pi2c);
+int i2c_readblock (PSI2C pi2c, PI2CSET pi2cSet, u8 *Data);
+int i2c_writeblock (PSI2C pi2c, PI2CSET pi2cSet, u8 *Data);
+int i2c_readbyte(PSI2C pi2c, u8 *readb, int *index);
+int i2c_writebyte(PSI2C pi2c, u8 *writeb);
+int SetI2cFDR( PSI2C pi2cRegs, int bitrate );
+*/
+#endif /* __ASSEMBLY__ */
+
+#endif /* __INCi2ccoreh */
diff --git a/arch/powerpc/cpu/mpc8220/interrupts.c b/arch/powerpc/cpu/mpc8220/interrupts.c
new file mode 100644
index 0000000..78e9917
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/interrupts.c
@@ -0,0 +1,80 @@
+/*
+ * (C) Copyright -2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * interrupts.c - just enough support for the decrementer/timer
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <command.h>
+
+int interrupt_init_cpu (ulong * decrementer_count)
+{
+	*decrementer_count = get_tbclk () / CONFIG_SYS_HZ;
+
+	return (0);
+}
+
+/****************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt (struct pt_regs *regs)
+{
+	puts ("external_interrupt (oops!)\n");
+}
+
+void timer_interrupt_cpu (struct pt_regs *regs)
+{
+	/* nothing to do here */
+	return;
+}
+
+/****************************************************************************/
+
+/*
+ * Install and free a interrupt handler.
+ */
+
+void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
+{
+
+}
+
+void irq_free_handler (int vec)
+{
+
+}
+
+/****************************************************************************/
+
+void
+do_irqinfo (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
+{
+	puts ("IRQ related functions are unimplemented currently.\n");
+}
diff --git a/arch/powerpc/cpu/mpc8220/io.S b/arch/powerpc/cpu/mpc8220/io.S
new file mode 100644
index 0000000..5ecdf55
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/io.S
@@ -0,0 +1,128 @@
+/*
+ *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2001	Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ *			Andreas Heppel <aheppel@sysgo.de>
+ *  Copyright (C) 2003	Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <ppc_asm.tmpl>
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:	  in8 */
+/*  Description:  Input 8 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl	in8
+in8:
+	lbz	r3,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:	  in16 */
+/*  Description:  Input 16 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl	in16
+in16:
+	lhz	r3,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:	  in16r */
+/*  Description:  Input 16 bits and byte reverse */
+/* ------------------------------------------------------------------------------- */
+	.globl	in16r
+in16r:
+	lhbrx	r3,0,r3
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:	  in32 */
+/*  Description:  Input 32 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl	in32
+in32:
+	lwz	3,0(3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:	  in32r */
+/*  Description:  Input 32 bits and byte reverse */
+/* ------------------------------------------------------------------------------- */
+	.globl	in32r
+in32r:
+	lwbrx	r3,0,r3
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:	  out8 */
+/*  Description:  Output 8 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl	out8
+out8:
+	stb	r4,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:	  out16 */
+/*  Description:  Output 16 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl	out16
+out16:
+	sth	r4,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:	  out16r */
+/*  Description:  Byte reverse and output 16 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl	out16r
+out16r:
+	sthbrx	r4,0,r3
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:	  out32 */
+/*  Description:  Output 32 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl	out32
+out32:
+	stw	r4,0(r3)
+	sync
+	blr
+
+/* ------------------------------------------------------------------------------- */
+/*  Function:	  out32r */
+/*  Description:  Byte reverse and output 32 bits */
+/* ------------------------------------------------------------------------------- */
+	.globl	out32r
+out32r:
+	stwbrx	r4,0,r3
+	sync
+	blr
diff --git a/arch/powerpc/cpu/mpc8220/loadtask.c b/arch/powerpc/cpu/mpc8220/loadtask.c
new file mode 100644
index 0000000..6d8b627
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/loadtask.c
@@ -0,0 +1,78 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * This file is based on code
+ * (C) Copyright Motorola, Inc., 2000
+ */
+
+#include <common.h>
+#include <mpc8220.h>
+
+/* Multichannel DMA microcode */
+extern int taskTable;
+
+void loadtask (int basetask, int tasks)
+{
+	int *sram = (int *) (MMAP_SRAM + 512);
+	int *task_org = &taskTable;
+	unsigned int start, offset, end;
+	int i;
+
+#ifdef DEBUG
+	printf ("basetask = %d, tasks = %d\n", basetask, tasks);
+	printf ("task_org = 0x%08x\n", (unsigned int) task_org);
+#endif
+
+	/* setup TaskBAR register */
+	*(vu_long *) MMAP_DMA = (MMAP_SRAM + 512);
+
+	/* relocate task table entries */
+	offset = (unsigned int) sram;
+	for (i = basetask; i < basetask + tasks; i++) {
+		sram[i * 8 + 0] = task_org[i * 8 + 0] + offset;
+		sram[i * 8 + 1] = task_org[i * 8 + 1] + offset;
+		sram[i * 8 + 2] = task_org[i * 8 + 2] + offset;
+		sram[i * 8 + 3] = task_org[i * 8 + 3] + offset;
+		sram[i * 8 + 4] = task_org[i * 8 + 4];
+		sram[i * 8 + 5] = task_org[i * 8 + 5];
+		sram[i * 8 + 6] = task_org[i * 8 + 6] + offset;
+		sram[i * 8 + 7] = task_org[i * 8 + 7];
+	}
+
+	/* relocate task descriptors */
+	start = (sram[basetask * 8] - (unsigned int) sram);
+	end = (sram[(basetask + tasks - 1) * 8 + 1] - (unsigned int) sram);
+
+#ifdef DEBUG
+	printf ("TDT start = 0x%08x, end = 0x%08x\n", start, end);
+#endif
+
+	start /= 4;
+	end /= 4;
+	for (i = start; i <= end; i++) {
+		sram[i] = task_org[i];
+	}
+
+	/* relocate variables */
+	start = (sram[basetask * 8 + 2] - (unsigned int) sram);
+	end = (sram[(basetask + tasks - 1) * 8 + 2] + 256 -
+	       (unsigned int) sram);
+	start /= 4;
+	end /= 4;
+	for (i = start; i < end; i++) {
+		sram[i] = task_org[i];
+	}
+
+	/* relocate function decriptors */
+	start = ((sram[basetask * 8 + 3] & 0xfffffffc) - (unsigned int) sram);
+	end = ((sram[(basetask + tasks - 1) * 8 + 3] & 0xfffffffc) + 256 -
+	       (unsigned int) sram);
+	start /= 4;
+	end /= 4;
+	for (i = start; i < end; i++) {
+		sram[i] = task_org[i];
+	}
+
+	asm volatile ("sync");
+}
diff --git a/arch/powerpc/cpu/mpc8220/pci.c b/arch/powerpc/cpu/mpc8220/pci.c
new file mode 100644
index 0000000..7ef43b7
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/pci.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2004 Freescale Semiconductor.
+ * Copyright (C) 2003 Motorola Inc.
+ * Xianghua Xiao (x.xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * PCI Configuration space access support for MPC8220 PCI Bridge
+ */
+#include <common.h>
+#include <mpc8220.h>
+#include <pci.h>
+#include <asm/io.h>
+
+#if defined(CONFIG_PCI)
+
+/* System RAM mapped over PCI */
+#define CONFIG_PCI_SYS_MEM_BUS	 CONFIG_SYS_SDRAM_BASE
+#define CONFIG_PCI_SYS_MEM_PHYS	 CONFIG_SYS_SDRAM_BASE
+#define CONFIG_PCI_SYS_MEM_SIZE	 (1024 * 1024 * 1024)
+
+#define cfg_read(val, addr, type, op)		*val = op((type)(addr));
+#define cfg_write(val, addr, type, op)		op((type *)(addr), (val));
+
+#define PCI_OP(rw, size, type, op, mask)				\
+int mpc8220_pci_##rw##_config_##size(struct pci_controller *hose,	\
+	pci_dev_t dev, int offset, type val)				\
+{									\
+	u32 addr = 0;							\
+	u16 cfg_type = 0;						\
+	addr = ((offset & 0xfc) | cfg_type | (dev)  | 0x80000000);	\
+	out_be32(hose->cfg_addr, addr);					\
+	__asm__ __volatile__("sync");					\
+	cfg_##rw(val, hose->cfg_data + (offset & mask), type, op);	\
+	out_be32(hose->cfg_addr, addr & 0x7fffffff);			\
+	__asm__ __volatile__("sync");					\
+	return 0;							\
+}
+
+PCI_OP(read, byte, u8 *, in_8, 3)
+PCI_OP(read, word, u16 *, in_le16, 2)
+PCI_OP(write, byte, u8, out_8, 3)
+PCI_OP(write, word, u16, out_le16, 2)
+PCI_OP(write, dword, u32, out_le32, 0)
+
+int mpc8220_pci_read_config_dword(struct pci_controller *hose, pci_dev_t dev,
+	int offset, u32 *val)
+{
+	u32 addr;
+	u32 tmpv;
+	u32 mask = 2;	 /* word access */
+	/* Read lower 16 bits */
+	addr = ((offset & 0xfc) | (dev) | 0x80000000);
+	out_be32(hose->cfg_addr, addr);
+	__asm__ __volatile__("sync");
+	*val = (u32) in_le16((u16 *) (hose->cfg_data + (offset & mask)));
+	out_be32(hose->cfg_addr, addr & 0x7fffffff);
+	__asm__ __volatile__("sync");
+
+	/* Read upper 16 bits */
+	offset += 2;
+	addr = ((offset & 0xfc) | 1 | (dev) | 0x80000000);
+	out_be32(hose->cfg_addr, addr);
+	__asm__ __volatile__("sync");
+	tmpv = (u32) in_le16((u16 *) (hose->cfg_data + (offset & mask)));
+	out_be32(hose->cfg_addr, addr & 0x7fffffff);
+	__asm__ __volatile__("sync");
+
+	/* combine results into dword value */
+	*val = (tmpv << 16) | *val;
+
+	return 0;
+}
+
+void
+pci_mpc8220_init(struct pci_controller *hose)
+{
+	u32 win0, win1, win2;
+	volatile mpc8220_xcpci_t *xcpci =
+		(volatile mpc8220_xcpci_t *) MMAP_XCPCI;
+
+	volatile pcfg8220_t *portcfg = (volatile pcfg8220_t *) MMAP_PCFG;
+
+	win0 = (u32) CONFIG_PCI_MEM_PHYS;
+	win1 = (u32) CONFIG_PCI_IO_PHYS;
+	win2 = (u32) CONFIG_PCI_CFG_PHYS;
+
+	/* Assert PCI reset */
+	out_be32 (&xcpci->glb_stat_ctl, PCI_GLB_STAT_CTRL_PR);
+
+	/* Disable prefetching but read-multiples will still prefetch */
+	out_be32 (&xcpci->target_ctrl, 0x00000000);
+
+	/* Initiator windows */
+	out_be32 (&xcpci->init_win0,  (win0 >> 16) | win0 | 0x003f0000);
+	out_be32 (&xcpci->init_win1, ((win1 >> 16) | win1 ));
+	out_be32 (&xcpci->init_win2, ((win2 >> 16) | win2 ));
+
+	out_be32 (&xcpci->init_win_cfg,
+		PCI_INIT_WIN_CFG_WIN0_CTRL_EN |
+		PCI_INIT_WIN_CFG_WIN1_CTRL_EN | PCI_INIT_WIN_CFG_WIN1_CTRL_IO |
+		PCI_INIT_WIN_CFG_WIN2_CTRL_EN | PCI_INIT_WIN_CFG_WIN2_CTRL_IO);
+
+	out_be32 (&xcpci->init_ctrl, 0x00000000);
+
+	/* Enable bus master and mem access */
+	out_be32 (&xcpci->stat_cmd_reg, PCI_STAT_CMD_B | PCI_STAT_CMD_M);
+
+	/* Cache line size and master latency */
+	out_be32 (&xcpci->bist_htyp_lat_cshl, (0xf8 << PCI_CFG1_LT_SHIFT));
+
+	out_be32 (&xcpci->base0, PCI_BASE_ADDR_REG0); /* 256MB - MBAR space */
+	out_be32 (&xcpci->base1, PCI_BASE_ADDR_REG1); /* 1GB - SDRAM space */
+
+	out_be32 (&xcpci->target_bar0,
+		PCI_TARGET_BASE_ADDR_REG0 | PCI_TARGET_BASE_ADDR_EN);
+	out_be32 (&xcpci->target_bar1,
+		PCI_TARGET_BASE_ADDR_REG1 | PCI_TARGET_BASE_ADDR_EN);
+
+	/* Deassert reset bit */
+	out_be32 (&xcpci->glb_stat_ctl, 0x00000000);
+
+	/* Enable PCI bus master support */
+	/* Set PCIGNT1, PCIREQ1, PCIREQ0/PCIGNTIN, PCIGNT0/PCIREQOUT,
+	       PCIREQ2, PCIGNT2 */
+	out_be32((volatile u32 *)&portcfg->pcfg3,
+		(in_be32((volatile u32 *)&portcfg->pcfg3) & 0xFC3FCE7F));
+	out_be32((volatile u32 *)&portcfg->pcfg3,
+		(in_be32((volatile u32 *)&portcfg->pcfg3) | 0x01400180));
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	pci_set_region(hose->regions + 0,
+		CONFIG_PCI_MEM_BUS,
+		CONFIG_PCI_MEM_PHYS,
+		CONFIG_PCI_MEM_SIZE,
+		PCI_REGION_MEM);
+
+	pci_set_region(hose->regions + 1,
+		CONFIG_PCI_IO_BUS,
+		CONFIG_PCI_IO_PHYS,
+		CONFIG_PCI_IO_SIZE,
+		PCI_REGION_IO);
+
+	pci_set_region(hose->regions + 2,
+		CONFIG_PCI_SYS_MEM_BUS,
+		CONFIG_PCI_SYS_MEM_PHYS,
+		CONFIG_PCI_SYS_MEM_SIZE,
+		PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+	hose->region_count = 3;
+
+	hose->cfg_addr = &(xcpci->cfg_adr);
+	hose->cfg_data = (volatile unsigned char *)CONFIG_PCI_CFG_BUS;
+
+	pci_set_ops(hose,
+		mpc8220_pci_read_config_byte,
+		mpc8220_pci_read_config_word,
+		mpc8220_pci_read_config_dword,
+		mpc8220_pci_write_config_byte,
+		mpc8220_pci_write_config_word,
+		mpc8220_pci_write_config_dword);
+
+	/* Hose scan */
+	pci_register_hose(hose);
+	hose->last_busno = pci_hose_scan(hose);
+
+	out_be32 (&xcpci->base0, PCI_BASE_ADDR_REG0); /* 256MB - MBAR space */
+	out_be32 (&xcpci->base1, PCI_BASE_ADDR_REG1); /* 1GB - SDRAM space */
+}
+
+#endif /* CONFIG_PCI */
diff --git a/arch/powerpc/cpu/mpc8220/speed.c b/arch/powerpc/cpu/mpc8220/speed.c
new file mode 100644
index 0000000..62ac845
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/speed.c
@@ -0,0 +1,123 @@
+/*
+ * (C) Copyright 2004, Freescale, Inc
+ * TsiChung Liew, Tsi-Chung.Liew@freescale.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8220.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+typedef struct pllmultiplier {
+	u8 hid1;
+	int multi;
+	int vco_div;
+} pllcfg_t;
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ *
+ */
+
+int get_clocks (void)
+{
+	pllcfg_t bus2core[] = {
+		{0x02, 2, 8},	/* 1 */
+		{0x01, 2, 4},
+		{0x0C, 3, 8},	/* 1.5 */
+		{0x00, 3, 4},
+		{0x18, 3, 2},
+		{0x05, 4, 4},	/* 2 */
+		{0x04, 4, 2},
+		{0x11, 5, 4},	/* 2.5 */
+		{0x06, 5, 2},
+		{0x10, 6, 4},	/* 3 */
+		{0x08, 6, 2},
+		{0x0E, 7, 2},	/* 3.5 */
+		{0x0A, 8, 2},	/* 4 */
+		{0x07, 9, 2},	/* 4.5 */
+		{0x0B, 10, 2},	/* 5 */
+		{0x09, 11, 2},	/* 5.5 */
+		{0x0D, 12, 2},	/* 6 */
+		{0x12, 13, 2},	/* 6.5 */
+		{0x14, 14, 2},	/* 7 */
+		{0x16, 15, 2},	/* 7.5 */
+		{0x1C, 16, 2}	/* 8 */
+	};
+	u32 hid1;
+	int i, size, pci2bus;
+
+#if !defined(CONFIG_SYS_MPC8220_CLKIN)
+#error clock measuring not implemented yet - define CONFIG_SYS_MPC8220_CLKIN
+#endif
+
+	gd->inp_clk = CONFIG_SYS_MPC8220_CLKIN;
+
+	/* Read XLB to PCI(INP) clock multiplier */
+	pci2bus = (*((volatile u32 *)PCI_REG_PCIGSCR) &
+		PCI_REG_PCIGSCR_PCI2XLB_CLK_MASK)>>PCI_REG_PCIGSCR_PCI2XLB_CLK_BIT;
+
+	/* XLB bus clock */
+	gd->bus_clk = CONFIG_SYS_MPC8220_CLKIN * pci2bus;
+
+	/* PCI clock is same as input clock */
+	gd->pci_clk = CONFIG_SYS_MPC8220_CLKIN;
+
+	/* FlexBus is temporary set as the same as input clock */
+	/* will do dynamic in the future */
+	gd->flb_clk = CONFIG_SYS_MPC8220_CLKIN;
+
+	/* CPU Clock - Read HID1 */
+	asm volatile ("mfspr %0, 1009":"=r" (hid1):);
+
+	size = sizeof (bus2core) / sizeof (pllcfg_t);
+
+	hid1 >>= 27;
+
+	for (i = 0; i < size; i++)
+		if (hid1 == bus2core[i].hid1) {
+			gd->cpu_clk = (bus2core[i].multi * gd->bus_clk) >> 1;
+			gd->vco_clk = CONFIG_SYS_MPC8220_SYSPLL_VCO_MULTIPLIER * (gd->pci_clk * bus2core[i].vco_div)/2;
+			break;
+		}
+
+	/* hardcoded 81MHz for now */
+	gd->pev_clk = 81000000;
+
+	return (0);
+}
+
+int prt_mpc8220_clks (void)
+{
+	char buf1[32], buf2[32], buf3[32], buf4[32];
+
+	printf ("       Bus %s MHz, CPU %s MHz, PCI %s MHz, VCO %s MHz\n",
+		strmhz(buf1, gd->bus_clk),
+		strmhz(buf2, gd->cpu_clk),
+		strmhz(buf3, gd->pci_clk),
+		strmhz(buf4, gd->vco_clk)
+	);
+	return (0);
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/arch/powerpc/cpu/mpc8220/start.S b/arch/powerpc/cpu/mpc8220/start.S
new file mode 100644
index 0000000..3d79d8e
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/start.S
@@ -0,0 +1,750 @@
+/*
+ *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000 - 2003 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ *  U-Boot - Startup Code for MPC8220 CPUs
+ */
+#include <config.h>
+#include <mpc8220.h>
+#include <timestamp.h>
+#include <version.h>
+
+#define _LINUX_CONFIG_H 1   /* avoid reading Linux autoconf.h file  */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef	 CONFIG_IDENT_STRING
+#define	 CONFIG_IDENT_STRING ""
+#endif
+
+/* We don't want the  MMU yet.
+*/
+#undef	MSR_KERNEL
+/* Floating Point enable, Machine Check and Recoverable Interr. */
+#ifdef DEBUG
+#define MSR_KERNEL (MSR_FP|MSR_RI)
+#else
+#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
+#endif
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+	START_GOT
+	GOT_ENTRY(_GOT2_TABLE_)
+	GOT_ENTRY(_FIXUP_TABLE_)
+
+	GOT_ENTRY(_start)
+	GOT_ENTRY(_start_of_vectors)
+	GOT_ENTRY(_end_of_vectors)
+	GOT_ENTRY(transfer_to_handler)
+
+	GOT_ENTRY(__init_end)
+	GOT_ENTRY(_end)
+	GOT_ENTRY(__bss_start)
+	END_GOT
+
+/*
+ * Version string
+ */
+	.data
+	.globl	version_string
+version_string:
+	.ascii U_BOOT_VERSION
+	.ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
+	.ascii CONFIG_IDENT_STRING, "\0"
+
+/*
+ * Exception vectors
+ */
+	.text
+	. = EXC_OFF_SYS_RESET
+	.globl	_start
+_start:
+	li	r21, BOOTFLAG_COLD  /* Normal Power-On	    */
+	nop
+	b	boot_cold
+
+	. = EXC_OFF_SYS_RESET + 0x10
+
+	.globl	_start_warm
+_start_warm:
+	li	r21, BOOTFLAG_WARM  /* Software reboot	    */
+	b	boot_warm
+
+boot_cold:
+boot_warm:
+	mfmsr	r5		    /* save msr contents    */
+
+	/* replace default MBAR base address from 0x80000000
+	    to 0xf0000000 */
+
+#if defined(CONFIG_SYS_DEFAULT_MBAR) && !defined(CONFIG_SYS_RAMBOOT)
+	lis	r3, CONFIG_SYS_MBAR@h
+	ori	r3, r3, CONFIG_SYS_MBAR@l
+
+	/* MBAR is mirrored into the MBAR SPR */
+	mtspr	MBAR,r3
+	mtspr	SPRN_SPRG7W,r3
+	lis	r4, CONFIG_SYS_DEFAULT_MBAR@h
+	stw	r3, 0(r4)
+#endif /* CONFIG_SYS_DEFAULT_MBAR */
+
+	/* Initialise the MPC8220 processor core			*/
+	/*--------------------------------------------------------------*/
+
+	bl  init_8220_core
+
+	/* initialize some things that are hard to access from C	*/
+	/*--------------------------------------------------------------*/
+
+	/* set up stack in on-chip SRAM */
+	lis	r3, CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l
+	ori	r1, r3, CONFIG_SYS_INIT_SP_OFFSET
+
+	li	r0, 0		/* Make room for stack frame header and */
+	stwu	r0, -4(r1)	/* clear final stack frame so that	*/
+	stwu	r0, -4(r1)	/* stack backtraces terminate cleanly	*/
+
+	/* let the C-code set up the rest				*/
+	/*								*/
+	/* Be careful to keep code relocatable !			*/
+	/*--------------------------------------------------------------*/
+
+	GET_GOT			/* initialize GOT access		*/
+
+	/* r3: IMMR */
+	bl	cpu_init_f	/* run low-level CPU init code (in Flash)*/
+
+	mr	r3, r21
+	/* r3: BOOTFLAG */
+	bl	board_init_f	/* run 1st part of board init code (in Flash)*/
+
+/*
+ * Vector Table
+ */
+
+	.globl	_start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+	STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+	STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+	STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+	. = 0x600
+Alignment:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	mfspr	r4,DAR
+	stw	r4,_DAR(r21)
+	mfspr	r5,DSISR
+	stw	r5,_DSISR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+	. = 0x700
+ProgramCheck:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+		MSR_KERNEL, COPY_EE)
+
+	STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+	/* I guess we could implement decrementer, and may have
+	 * to someday for timekeeping.
+	 */
+	STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+
+	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+	STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+	STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+	STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+	STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+	STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+	STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
+#ifdef DEBUG
+	. = 0x1300
+	/*
+	 * This exception occurs when the program counter matches the
+	 * Instruction Address Breakpoint Register (IABR).
+	 *
+	 * I want the cpu to halt if this occurs so I can hunt around
+	 * with the debugger and look at things.
+	 *
+	 * When DEBUG is defined, both machine check enable (in the MSR)
+	 * and checkstop reset enable (in the reset mode register) are
+	 * turned off and so a checkstop condition will result in the cpu
+	 * halting.
+	 *
+	 * I force the cpu into a checkstop condition by putting an illegal
+	 * instruction here (at least this is the theory).
+	 *
+	 * well - that didnt work, so just do an infinite loop!
+	 */
+1:	b	1b
+#else
+	STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
+#endif
+	STD_EXCEPTION(0x1400, SMI, UnknownException)
+
+	STD_EXCEPTION(0x1500, Trap_15, UnknownException)
+	STD_EXCEPTION(0x1600, Trap_16, UnknownException)
+	STD_EXCEPTION(0x1700, Trap_17, UnknownException)
+	STD_EXCEPTION(0x1800, Trap_18, UnknownException)
+	STD_EXCEPTION(0x1900, Trap_19, UnknownException)
+	STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
+	STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+	STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
+	STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
+	STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
+	STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
+	STD_EXCEPTION(0x2000, Trap_20, UnknownException)
+	STD_EXCEPTION(0x2100, Trap_21, UnknownException)
+	STD_EXCEPTION(0x2200, Trap_22, UnknownException)
+	STD_EXCEPTION(0x2300, Trap_23, UnknownException)
+	STD_EXCEPTION(0x2400, Trap_24, UnknownException)
+	STD_EXCEPTION(0x2500, Trap_25, UnknownException)
+	STD_EXCEPTION(0x2600, Trap_26, UnknownException)
+	STD_EXCEPTION(0x2700, Trap_27, UnknownException)
+	STD_EXCEPTION(0x2800, Trap_28, UnknownException)
+	STD_EXCEPTION(0x2900, Trap_29, UnknownException)
+	STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
+	STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
+	STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
+	STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
+	STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
+	STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
+
+
+	.globl	_end_of_vectors
+_end_of_vectors:
+
+	. = 0x3000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+	.globl	transfer_to_handler
+transfer_to_handler:
+	stw	r22,_NIP(r21)
+	lis	r22,MSR_POW@h
+	andc	r23,r23,r22
+	stw	r23,_MSR(r21)
+	SAVE_GPR(7, r21)
+	SAVE_4GPRS(8, r21)
+	SAVE_8GPRS(12, r21)
+	SAVE_8GPRS(24, r21)
+	mflr	r23
+	andi.	r24,r23,0x3f00	    /* get vector offset */
+	stw	r24,TRAP(r21)
+	li	r22,0
+	stw	r22,RESULT(r21)
+	lwz	r24,0(r23)		/* virtual address of handler */
+	lwz	r23,4(r23)		/* where to go when done */
+	mtspr	SRR0,r24
+	mtspr	SRR1,r20
+	mtlr	r23
+	SYNC
+	rfi			    /* jump to handler, enable MMU */
+
+int_return:
+	mfmsr	r28		    /* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC			    /* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	    /* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SRR0,r2
+	mtspr	SRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfi
+
+/*
+ * This code initialises the MPC8220 processor core
+ * (conforms to PowerPC 603e spec)
+ * Note: expects original MSR contents to be in r5.
+ */
+
+	.globl	init_8220_core
+init_8220_core:
+
+	/* Initialize machine status; enable machine check interrupt	*/
+	/*--------------------------------------------------------------*/
+
+	li	r3, MSR_KERNEL	    /* Set ME and RI flags		*/
+	rlwimi	r3, r5, 0, 25, 25   /* preserve IP bit set by HRCW	*/
+#ifdef DEBUG
+	rlwimi	r3, r5, 0, 21, 22   /* debugger might set SE & BE bits	*/
+#endif
+	SYNC			    /* Some chip revs need this...	*/
+	mtmsr	r3
+	SYNC
+	mtspr	SRR1, r3	    /* Make SRR1 match MSR		*/
+
+	/* Initialize the Hardware Implementation-dependent Registers	*/
+	/* HID0 also contains cache control				*/
+	/*--------------------------------------------------------------*/
+
+	lis	r3, CONFIG_SYS_HID0_INIT@h
+	ori	r3, r3, CONFIG_SYS_HID0_INIT@l
+	SYNC
+	mtspr	HID0, r3
+
+	lis	r3, CONFIG_SYS_HID0_FINAL@h
+	ori	r3, r3, CONFIG_SYS_HID0_FINAL@l
+	SYNC
+	mtspr	HID0, r3
+
+	/* Enable Extra BATs */
+	mfspr	r3, 1011    /* HID2 */
+	lis	r4, 0x0004
+	ori	r4, r4, 0x0000
+	or	r4, r4, r3
+	mtspr	1011, r4
+	sync
+
+	/* clear all BAT's						*/
+	/*--------------------------------------------------------------*/
+
+	li	r0, 0
+	mtspr	DBAT0U, r0
+	mtspr	DBAT0L, r0
+	mtspr	DBAT1U, r0
+	mtspr	DBAT1L, r0
+	mtspr	DBAT2U, r0
+	mtspr	DBAT2L, r0
+	mtspr	DBAT3U, r0
+	mtspr	DBAT3L, r0
+	mtspr	DBAT4U, r0
+	mtspr	DBAT4L, r0
+	mtspr	DBAT5U, r0
+	mtspr	DBAT5L, r0
+	mtspr	DBAT6U, r0
+	mtspr	DBAT6L, r0
+	mtspr	DBAT7U, r0
+	mtspr	DBAT7L, r0
+	mtspr	IBAT0U, r0
+	mtspr	IBAT0L, r0
+	mtspr	IBAT1U, r0
+	mtspr	IBAT1L, r0
+	mtspr	IBAT2U, r0
+	mtspr	IBAT2L, r0
+	mtspr	IBAT3U, r0
+	mtspr	IBAT3L, r0
+	mtspr	IBAT4U, r0
+	mtspr	IBAT4L, r0
+	mtspr	IBAT5U, r0
+	mtspr	IBAT5L, r0
+	mtspr	IBAT6U, r0
+	mtspr	IBAT6L, r0
+	mtspr	IBAT7U, r0
+	mtspr	IBAT7L, r0
+	SYNC
+
+	/* invalidate all tlb's						*/
+	/*								*/
+	/* From the 603e User Manual: "The 603e provides the ability to */
+	/* invalidate a TLB entry. The TLB Invalidate Entry (tlbie)	*/
+	/* instruction invalidates the TLB entry indexed by the EA, and */
+	/* operates on both the instruction and data TLBs simultaneously*/
+	/* invalidating four TLB entries (both sets in each TLB). The	*/
+	/* index corresponds to bits 15-19 of the EA. To invalidate all */
+	/* entries within both TLBs, 32 tlbie instructions should be	*/
+	/* issued, incrementing this field by one each time."		*/
+	/*								*/
+	/* "Note that the tlbia instruction is not implemented on the	*/
+	/* 603e."							*/
+	/*								*/
+	/* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000	*/
+	/* incrementing by 0x1000 each time. The code below is sort of	*/
+	/* based on code in "flush_tlbs" from arch/powerpc/kernel/head.S	*/
+	/*								*/
+	/*--------------------------------------------------------------*/
+
+	li	r3, 32
+	mtctr	r3
+	li	r3, 0
+1:	tlbie	r3
+	addi	r3, r3, 0x1000
+	bdnz	1b
+	SYNC
+
+	/* Done!							*/
+	/*--------------------------------------------------------------*/
+
+	blr
+
+/* Cache functions.
+ *
+ * Note: requires that all cache bits in
+ * HID0 are in the low half word.
+ */
+	.globl	icache_enable
+icache_enable:
+	lis	r4, 0
+	ori	r4, r4, CONFIG_SYS_HID0_INIT /* set ICE & ICFI bit		*/
+	rlwinm	r3, r4, 0, 21, 19     /* clear the ICFI bit		*/
+
+	/*
+	 * The setting of the instruction cache enable (ICE) bit must be
+	 * preceded by an isync instruction to prevent the cache from being
+	 * enabled or disabled while an instruction access is in progress.
+	 */
+	isync
+	mtspr	HID0, r4	      /* Enable Instr Cache & Inval cache */
+	mtspr	HID0, r3	      /* using 2 consec instructions	*/
+	isync
+	blr
+
+	.globl	icache_disable
+icache_disable:
+	mfspr	r3, HID0
+	rlwinm	r3, r3, 0, 17, 15     /* clear the ICE bit		*/
+	mtspr	HID0, r3
+	isync
+	blr
+
+	.globl	icache_status
+icache_status:
+	mfspr	r3, HID0
+	rlwinm	r3, r3, HID0_ICE_BITPOS + 1, 31, 31
+	blr
+
+	.globl	dcache_enable
+dcache_enable:
+	lis	r4, 0
+	ori	r4, r4, HID0_DCE|HID0_DCFI /* set DCE & DCFI bit	*/
+	rlwinm	r3, r4, 0, 22, 20     /* clear the DCFI bit		*/
+
+	/* Enable address translation in MSR bit */
+	mfmsr	r5
+	ori	r5, r5, 0x
+
+
+	/*
+	 * The setting of the instruction cache enable (ICE) bit must be
+	 * preceded by an isync instruction to prevent the cache from being
+	 * enabled or disabled while an instruction access is in progress.
+	 */
+	isync
+	mtspr	HID0, r4	      /* Enable Data Cache & Inval cache*/
+	mtspr	HID0, r3	      /* using 2 consec instructions	*/
+	isync
+	blr
+
+	.globl	dcache_disable
+dcache_disable:
+	mfspr	r3, HID0
+	rlwinm	r3, r3, 0, 18, 16     /* clear the DCE bit */
+	mtspr	HID0, r3
+	isync
+	blr
+
+	.globl	dcache_status
+dcache_status:
+	mfspr	r3, HID0
+	rlwinm	r3, r3, HID0_DCE_BITPOS + 1, 31, 31
+	blr
+
+	.globl	get_pvr
+get_pvr:
+	mfspr	r3, PVR
+	blr
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+	.globl	relocate_code
+relocate_code:
+	mr	r1,  r3	    /* Set new stack pointer		*/
+	mr	r9,  r4	    /* Save copy of Global Data pointer */
+	mr	r10, r5	    /* Save copy of Destination Address */
+
+	GET_GOT
+	mr	r3,  r5	    /* Destination Address		*/
+	lis	r4, CONFIG_SYS_MONITOR_BASE@h	/* Source Address	*/
+	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
+	lwz	r5, GOT(__init_end)
+	sub	r5, r5, r4
+	li	r6, CONFIG_SYS_CACHELINE_SIZE	/* Cache Line Size	*/
+
+	/*
+	 * Fix GOT pointer:
+	 *
+	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+	 *
+	 * Offset:
+	 */
+	sub	r15, r10, r4
+
+	/* First our own GOT */
+	add	r12, r12, r15
+	/* then the one used by the C code */
+	add	r30, r30, r15
+
+	/*
+	 * Now relocate code
+	 */
+
+	cmplw	cr1,r3,r4
+	addi	r0,r5,3
+	srwi.	r0,r0,2
+	beq	cr1,4f	    /* In place copy is not necessary	*/
+	beq	7f	    /* Protect against 0 count		*/
+	mtctr	r0
+	bge	cr1,2f
+
+	la	r8,-4(r4)
+	la	r7,-4(r3)
+1:	lwzu	r0,4(r8)
+	stwu	r0,4(r7)
+	bdnz	1b
+	b	4f
+
+2:	slwi	r0,r0,2
+	add	r8,r4,r0
+	add	r7,r3,r0
+3:	lwzu	r0,-4(r8)
+	stwu	r0,-4(r7)
+	bdnz	3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:	cmpwi	r6,0
+	add	r5,r3,r5
+	beq	7f	    /* Always flush prefetch queue in any case	*/
+	subi	r0,r6,1
+	andc	r3,r3,r0
+	mfspr	r7,HID0	    /* don't do dcbst if dcache is disabled	*/
+	rlwinm	r7,r7,HID0_DCE_BITPOS+1,31,31
+	cmpwi	r7,0
+	beq	9f
+	mr	r4,r3
+5:	dcbst	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	5b
+	sync		    /* Wait for all dcbst to complete on bus	*/
+9:	mfspr	r7,HID0	    /* don't do icbi if icache is disabled	*/
+	rlwinm	r7,r7,HID0_ICE_BITPOS+1,31,31
+	cmpwi	r7,0
+	beq	7f
+	mr	r4,r3
+6:	icbi	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	6b
+7:	sync		    /* Wait for all icbi to complete on bus	*/
+	isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+	mtlr	r0
+	blr
+
+in_ram:
+
+	/*
+	 * Relocation Function, r12 point to got2+0x8000
+	 *
+	 * Adjust got2 pointers, no need to check for 0, this code
+	 * already puts a few entries in the table.
+	 */
+	li	r0,__got2_entries@sectoff@l
+	la	r3,GOT(_GOT2_TABLE_)
+	lwz	r11,GOT(_GOT2_TABLE_)
+	mtctr	r0
+	sub	r11,r3,r11
+	addi	r3,r3,-4
+1:	lwzu	r0,4(r3)
+	cmpwi	r0,0
+	beq-	2f
+	add	r0,r0,r11
+	stw	r0,0(r3)
+2:	bdnz	1b
+
+	/*
+	 * Now adjust the fixups and the pointers to the fixups
+	 * in case we need to move ourselves again.
+	 */
+	li	r0,__fixup_entries@sectoff@l
+	lwz	r3,GOT(_FIXUP_TABLE_)
+	cmpwi	r0,0
+	mtctr	r0
+	addi	r3,r3,-4
+	beq	4f
+3:	lwzu	r4,4(r3)
+	lwzux	r0,r4,r11
+	add	r0,r0,r11
+	stw	r10,0(r3)
+	stw	r0,0(r4)
+	bdnz	3b
+4:
+clear_bss:
+	/*
+	 * Now clear BSS segment
+	 */
+	lwz	r3,GOT(__bss_start)
+	lwz	r4,GOT(_end)
+
+	cmplw	0, r3, r4
+	beq	6f
+
+	li	r0, 0
+5:
+	stw	r0, 0(r3)
+	addi	r3, r3, 4
+	cmplw	0, r3, r4
+	bne	5b
+6:
+
+	mr	r3, r9	    /* Global Data pointer	*/
+	mr	r4, r10	    /* Destination Address	*/
+	bl	board_init_r
+
+	/*
+	 * Copy exception vector code to low memory
+	 *
+	 * r3: dest_addr
+	 * r7: source address, r8: end address, r9: target address
+	 */
+	.globl	trap_init
+trap_init:
+	mflr	r4	    /* save link register		*/
+	GET_GOT
+	lwz	r7, GOT(_start)
+	lwz	r8, GOT(_end_of_vectors)
+
+	li	r9, 0x100   /* reset vector always at 0x100	*/
+
+	cmplw	0, r7, r8
+	bgelr		    /* return if r7>=r8 - just in case	*/
+1:
+	lwz	r0, 0(r7)
+	stw	r0, 0(r9)
+	addi	r7, r7, 4
+	addi	r9, r9, 4
+	cmplw	0, r7, r8
+	bne	1b
+
+	/*
+	 * relocate `hdlr' and `int_return' entries
+	 */
+	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+	li	r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+	bl	trap_reloc
+	addi	r7, r7, 0x100	    /* next exception vector	    */
+	cmplw	0, r7, r8
+	blt	2b
+
+	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+	bl	trap_reloc
+	addi	r7, r7, 0x100	    /* next exception vector	    */
+	cmplw	0, r7, r8
+	blt	3b
+
+	li	r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+	bl	trap_reloc
+	addi	r7, r7, 0x100	    /* next exception vector	    */
+	cmplw	0, r7, r8
+	blt	4b
+
+	mfmsr	r3		    /* now that the vectors have    */
+	lis	r7, MSR_IP@h	    /* relocated into low memory    */
+	ori	r7, r7, MSR_IP@l    /* MSR[IP] can be turned off    */
+	andc	r3, r3, r7	    /* (if it was on)		    */
+	SYNC			    /* Some chip revs need this...  */
+	mtmsr	r3
+	SYNC
+
+	mtlr	r4		    /* restore link register	    */
+	blr
diff --git a/arch/powerpc/cpu/mpc8220/traps.c b/arch/powerpc/cpu/mpc8220/traps.c
new file mode 100644
index 0000000..13894c9
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/traps.c
@@ -0,0 +1,236 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ * fixed Machine Check Reasons by Reinhard Meyer (r.meyer@emk-elektronik.de)
+ *
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table (unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM      0x02000000
+
+/*
+ * Trap & Exception support
+ */
+
+void print_backtrace (unsigned long *sp)
+{
+	int cnt = 0;
+	unsigned long i;
+
+	printf ("Call backtrace: ");
+	while (sp) {
+		if ((uint) sp > END_OF_MEM)
+			break;
+
+		i = sp[1];
+		if (cnt++ % 7 == 0)
+			printf ("\n");
+		printf ("%08lX ", i);
+		if (cnt > 32)
+			break;
+		sp = (unsigned long *) *sp;
+	}
+	printf ("\n");
+}
+
+void show_regs (struct pt_regs *regs)
+{
+	int i;
+
+	printf ("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+		regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+	printf ("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+		regs->msr,
+		regs->msr & MSR_EE ? 1 : 0, regs->msr & MSR_PR ? 1 : 0,
+		regs->msr & MSR_FP ? 1 : 0, regs->msr & MSR_ME ? 1 : 0,
+		regs->msr & MSR_IR ? 1 : 0, regs->msr & MSR_DR ? 1 : 0);
+
+	printf ("\n");
+	for (i = 0; i < 32; i++) {
+		if ((i % 8) == 0) {
+			printf ("GPR%02d: ", i);
+		}
+
+		printf ("%08lX ", regs->gpr[i]);
+		if ((i % 8) == 7) {
+			printf ("\n");
+		}
+	}
+}
+
+
+void _exception (int signr, struct pt_regs *regs)
+{
+	show_regs (regs);
+	print_backtrace ((unsigned long *) regs->gpr[1]);
+	panic ("Exception in kernel pc %lx signal %d", regs->nip, signr);
+}
+
+void MachineCheckException (struct pt_regs *regs)
+{
+	unsigned long fixup;
+
+	/* Probing PCI using config cycles cause this exception
+	 * when a device is not present.  Catch it and return to
+	 * the PCI exception handler.
+	 */
+	if ((fixup = search_exception_table (regs->nip)) != 0) {
+		regs->nip = fixup;
+		return;
+	}
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler
+	    && (*debugger_exception_handler) (regs))
+		return;
+#endif
+
+	printf ("Machine check in kernel mode.\n");
+	printf ("Caused by (from msr): ");
+	printf ("regs %p ", regs);
+	/* refer to 603e Manual (MPC603EUM/AD), chapter 4.5.2.1 */
+	switch (regs->msr & 0x000F0000) {
+	case (0x80000000 >> 12):
+		printf ("Machine check signal - probably due to mm fault\n"
+			"with mmu off\n");
+		break;
+	case (0x80000000 >> 13):
+		printf ("Transfer error ack signal\n");
+		break;
+	case (0x80000000 >> 14):
+		printf ("Data parity signal\n");
+		break;
+	case (0x80000000 >> 15):
+		printf ("Address parity signal\n");
+		break;
+	default:
+		printf ("Unknown values in msr\n");
+	}
+	show_regs (regs);
+	print_backtrace ((unsigned long *) regs->gpr[1]);
+	panic ("machine check");
+}
+
+void AlignmentException (struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler
+	    && (*debugger_exception_handler) (regs))
+		return;
+#endif
+	show_regs (regs);
+	print_backtrace ((unsigned long *) regs->gpr[1]);
+	panic ("Alignment Exception");
+}
+
+void ProgramCheckException (struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler
+	    && (*debugger_exception_handler) (regs))
+		return;
+#endif
+	show_regs (regs);
+	print_backtrace ((unsigned long *) regs->gpr[1]);
+	panic ("Program Check Exception");
+}
+
+void SoftEmuException (struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler
+	    && (*debugger_exception_handler) (regs))
+		return;
+#endif
+	show_regs (regs);
+	print_backtrace ((unsigned long *) regs->gpr[1]);
+	panic ("Software Emulation Exception");
+}
+
+
+void UnknownException (struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler
+	    && (*debugger_exception_handler) (regs))
+		return;
+#endif
+	printf ("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+		regs->nip, regs->msr, regs->trap);
+	_exception (0, regs);
+}
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint (struct pt_regs *);
+#endif
+
+void DebugException (struct pt_regs *regs)
+{
+
+	printf ("Debugger trap at @ %lx\n", regs->nip);
+	show_regs (regs);
+#if defined(CONFIG_CMD_BEDBUG)
+	do_bedbug_breakpoint (regs);
+#endif
+}
+
+/* Probe an address by reading.  If not present, return -1, otherwise
+ * return 0.
+ */
+int addr_probe (uint * addr)
+{
+#if 0
+	int retval;
+
+	__asm__ __volatile__ ("1: lwz %0,0(%1)\n"
+			      "   eieio\n"
+			      "   li %0,0\n"
+			      "2:\n"
+			      ".section .fixup,\"ax\"\n"
+			      "3: li %0,-1\n"
+			      "   b 2b\n"
+			      ".section __ex_table,\"a\"\n"
+			      "   .align 2\n"
+			      "   .long 1b,3b\n"
+			      ".text":"=r" (retval):"r" (addr));
+
+	return (retval);
+#endif
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8220/u-boot.lds b/arch/powerpc/cpu/mpc8220/u-boot.lds
new file mode 100644
index 0000000..31a7a0e
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/u-boot.lds
@@ -0,0 +1,122 @@
+/*
+ * (C) Copyright 2003-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text)	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data)	}
+  .rel.rodata    : { *(.rel.rodata)	}
+  .rela.rodata   : { *(.rela.rodata)	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	}
+  .plt : { *(.plt) }
+  .text      :
+  {
+    arch/powerpc/cpu/mpc8220/start.o	(.text)
+    *(.text)
+    *(.got1)
+    . = ALIGN(16);
+    *(.eh_frame)
+    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x0FFF) & 0xFFFFF000;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+  __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  . = .;
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+
+  . = .;
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(4096);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss (NOLOAD)       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+   . = ALIGN(4);
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc8220/uart.c b/arch/powerpc/cpu/mpc8220/uart.c
new file mode 100644
index 0000000..0c4b536
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8220/uart.c
@@ -0,0 +1,126 @@
+/*
+ * (C) Copyright 2004, Freescale, Inc
+ * TsiChung Liew, Tsi-Chung.Liew@freescale.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/*
+ * Minimal serial functions needed to use one of the PSC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <mpc8220.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define PSC_BASE   MMAP_PSC1
+
+#if defined(CONFIG_PSC_CONSOLE)
+int serial_init (void)
+{
+	volatile psc8220_t *psc = (psc8220_t *) PSC_BASE;
+	u32 counter;
+
+	/* write to SICR: SIM2 = uart mode,dcd does not affect rx */
+	psc->cr = 0;
+	psc->ipcr_acr = 0;
+	psc->isr_imr = 0;
+
+	/* write to CSR: RX/TX baud rate from timers */
+	psc->sr_csr = 0xdd000000;
+
+	psc->mr1_2 = PSC_MR1_BITS_CHAR_8 | PSC_MR1_NO_PARITY | PSC_MR2_STOP_BITS_1;
+
+	/* Setting up BaudRate */
+	counter = ((gd->bus_clk / gd->baudrate)) >> 5;
+	counter++;
+
+	/* write to CTUR: divide counter upper byte */
+	psc->ctur = ((counter & 0xff00) << 16);
+	/* write to CTLR: divide counter lower byte */
+	psc->ctlr = ((counter & 0x00ff) << 24);
+
+	psc->cr = PSC_CR_RST_RX_CMD;
+	psc->cr = PSC_CR_RST_TX_CMD;
+	psc->cr = PSC_CR_RST_ERR_STS_CMD;
+	psc->cr = PSC_CR_RST_BRK_INT_CMD;
+	psc->cr = PSC_CR_RST_MR_PTR_CMD;
+
+	psc->cr = PSC_CR_RX_ENABLE | PSC_CR_TX_ENABLE;
+	return (0);
+}
+
+void serial_putc (const char c)
+{
+	volatile psc8220_t *psc = (psc8220_t *) PSC_BASE;
+
+	if (c == '\n')
+		serial_putc ('\r');
+
+	/* Wait for last character to go. */
+	while (!(psc->sr_csr & PSC_SR_TXRDY));
+
+	psc->xmitbuf[0] = c;
+}
+
+void serial_puts (const char *s)
+{
+	while (*s) {
+		serial_putc (*s++);
+	}
+}
+
+int serial_getc (void)
+{
+	volatile psc8220_t *psc = (psc8220_t *) PSC_BASE;
+
+	/* Wait for a character to arrive. */
+	while (!(psc->sr_csr & PSC_SR_RXRDY));
+	return psc->xmitbuf[2];
+}
+
+int serial_tstc (void)
+{
+	volatile psc8220_t *psc = (psc8220_t *) PSC_BASE;
+
+	return (psc->sr_csr & PSC_SR_RXRDY);
+}
+
+void serial_setbrg (void)
+{
+	volatile psc8220_t *psc = (psc8220_t *) PSC_BASE;
+	u32 counter;
+
+	counter = ((gd->bus_clk / gd->baudrate)) >> 5;
+	counter++;
+
+	/* write to CTUR: divide counter upper byte */
+	psc->ctur = ((counter & 0xff00) << 16);
+	/* write to CTLR: divide counter lower byte */
+	psc->ctlr = ((counter & 0x00ff) << 24);
+
+	psc->cr = PSC_CR_RST_RX_CMD;
+	psc->cr = PSC_CR_RST_TX_CMD;
+
+	psc->cr = PSC_CR_RX_ENABLE | PSC_CR_TX_ENABLE;
+}
+#endif /* CONFIG_PSC_CONSOLE */
diff --git a/arch/powerpc/cpu/mpc824x/.gitignore b/arch/powerpc/cpu/mpc824x/.gitignore
new file mode 100644
index 0000000..2d79931
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/.gitignore
@@ -0,0 +1 @@
+/bedbug_603e.c
diff --git a/arch/powerpc/cpu/mpc824x/Makefile b/arch/powerpc/cpu/mpc824x/Makefile
new file mode 100644
index 0000000..a57ad12
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/Makefile
@@ -0,0 +1,56 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+ifneq ($(OBJTREE),$(SRCTREE))
+$(shell mkdir -p $(obj)drivers/epic)
+$(shell mkdir -p $(obj)drivers/i2c)
+endif
+
+LIB	= $(obj)lib$(CPU).a
+
+START	= start.o
+COBJS	= traps.o cpu.o cpu_init.o interrupts.o speed.o \
+	  drivers/epic/epic1.o drivers/i2c/i2c.o pci.o
+COBJS_LN = bedbug_603e.o
+
+SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) $(addprefix $(obj),$(COBJS_LN:.o=.c))
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS) $(COBJS_LN))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+$(obj)bedbug_603e.c:
+	ln -sf $(src)../mpc8260/bedbug_603e.c $(obj)bedbug_603e.c
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc824x/config.mk b/arch/powerpc/cpu/mpc824x/config.mk
new file mode 100644
index 0000000..27c2873
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/config.mk
@@ -0,0 +1,29 @@
+#
+# (C) Copyright 2000
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -fPIC -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_MPC824X -ffixed-r2 -mstring -mcpu=603e -msoft-float
+
+# Use default linker script.  Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/arch/powerpc/cpu/mpc824x/u-boot.lds
diff --git a/arch/powerpc/cpu/mpc824x/cpu.c b/arch/powerpc/cpu/mpc824x/cpu.c
new file mode 100644
index 0000000..08f6a94
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/cpu.c
@@ -0,0 +1,280 @@
+/*
+ * (C) Copyright 2000 - 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <mpc824x.h>
+#include <common.h>
+#include <command.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int checkcpu (void)
+{
+	unsigned int pvr = get_pvr ();
+	unsigned int version = pvr >> 16;
+	unsigned char revision;
+	ulong clock = gd->cpu_clk;
+	char buf[32];
+
+	puts ("CPU:   ");
+
+	switch (version) {
+	case CPU_TYPE_8240:
+		puts ("MPC8240");
+		break;
+
+	case CPU_TYPE_8245:
+		puts ("MPC8245");
+		break;
+
+	default:
+		return -1;		/*not valid for this source */
+	}
+
+	CONFIG_READ_BYTE (REVID, revision);
+
+	if (revision) {
+		printf (" Revision %d.%d",
+			(revision & 0xf0) >> 4,
+			(revision & 0x0f));
+	} else {
+		return -1;		/* no valid CPU revision info */
+	}
+
+	printf (" at %s MHz:", strmhz (buf, clock));
+
+	printf (" %u kB I-Cache", checkicache () >> 10);
+	printf (" %u kB D-Cache", checkdcache () >> 10);
+
+	puts ("\n");
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+/* L1 i-cache                                                                */
+
+int checkicache (void)
+{
+	 /*TODO*/
+	 return 128 * 4 * 32;
+};
+
+/* ------------------------------------------------------------------------- */
+/* L1 d-cache                                                                */
+
+int checkdcache (void)
+{
+	 /*TODO*/
+	 return 128 * 4 * 32;
+
+};
+
+/*------------------------------------------------------------------- */
+
+int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	ulong msr, addr;
+
+	/* Interrupts and MMU off */
+	__asm__ ("mtspr    81, 0");
+
+	/* Interrupts and MMU off */
+	__asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
+
+	msr &= ~0x1030;
+	__asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
+
+	/*
+	 * Trying to execute the next instruction at a non-existing address
+	 * should cause a machine check, resulting in reset
+	 */
+#ifdef CONFIG_SYS_RESET_ADDRESS
+	addr = CONFIG_SYS_RESET_ADDRESS;
+#else
+	/*
+	 * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address,
+	 * CONFIG_SYS_MONITOR_BASE - sizeof (ulong) is usually a valid
+	 * address. Better pick an address known to be invalid on
+	 * your system and assign it to CONFIG_SYS_RESET_ADDRESS.
+	 * "(ulong)-1" used to be a good choice for many systems...
+	 */
+	addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong);
+#endif
+	((void (*)(void)) addr) ();
+	return 1;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ * This is the sys_logic_clk (memory bus) divided by 4
+ */
+unsigned long get_tbclk (void)
+{
+	return ((get_bus_freq (0) + 2L) / 4L);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * The MPC824x has an integrated PCI controller known as the MPC107.
+ * The following are MPC107 Bridge Controller and PCI Support functions
+ *
+ */
+
+/*
+ *  This procedure reads a 32-bit address MPC107 register, and returns
+ *  a 32 bit value.  It swaps the address to little endian before
+ *  writing it to config address, and swaps the value to big endian
+ *  before returning to the caller.
+ */
+unsigned int mpc824x_mpc107_getreg (unsigned int regNum)
+{
+	unsigned int temp;
+
+	/* swap the addr. to little endian */
+	*(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
+	temp = *(volatile unsigned int *) CHRP_REG_DATA;
+	return PCISWAP (temp);		/* swap the data upon return */
+}
+
+/*
+ *  This procedure writes a 32-bit address MPC107 register.  It swaps
+ *  the address to little endian before writing it to config address.
+ */
+
+void mpc824x_mpc107_setreg (unsigned int regNum, unsigned int regVal)
+{
+	/* swap the addr. to little endian */
+	*(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
+	*(volatile unsigned int *) CHRP_REG_DATA = PCISWAP (regVal);
+	return;
+}
+
+
+/*
+ *  Write a byte (8 bits) to a memory location.
+ */
+void mpc824x_mpc107_write8 (unsigned int addr, unsigned char data)
+{
+	*(unsigned char *) addr = data;
+	__asm__ ("sync");
+}
+
+/*
+ *  Write a word (16 bits) to a memory location after the value
+ *  has been byte swapped (big to little endian or vice versa)
+ */
+
+void mpc824x_mpc107_write16 (unsigned int address, unsigned short data)
+{
+	*(volatile unsigned short *) address = BYTE_SWAP_16_BIT (data);
+	__asm__ ("sync");
+}
+
+/*
+ *  Write a long word (32 bits) to a memory location after the value
+ *  has been byte swapped (big to little endian or vice versa)
+ */
+
+void mpc824x_mpc107_write32 (unsigned int address, unsigned int data)
+{
+	*(volatile unsigned int *) address = LONGSWAP (data);
+	__asm__ ("sync");
+}
+
+/*
+ *  Read a byte (8 bits) from a memory location.
+ */
+unsigned char mpc824x_mpc107_read8 (unsigned int addr)
+{
+	return *(volatile unsigned char *) addr;
+}
+
+
+/*
+ *  Read a word (16 bits) from a memory location, and byte swap the
+ *  value before returning to the caller.
+ */
+unsigned short mpc824x_mpc107_read16 (unsigned int address)
+{
+	unsigned short retVal;
+
+	retVal = BYTE_SWAP_16_BIT (*(unsigned short *) address);
+	return retVal;
+}
+
+
+/*
+ *  Read a long word (32 bits) from a memory location, and byte
+ *  swap the value before returning to the caller.
+ */
+unsigned int mpc824x_mpc107_read32 (unsigned int address)
+{
+	unsigned int retVal;
+
+	retVal = LONGSWAP (*(unsigned int *) address);
+	return (retVal);
+}
+
+
+/*
+ *  Read a register in the Embedded Utilities Memory Block address
+ *  space.
+ *  Input: regNum - register number + utility base address.  Example,
+ *         the base address of EPIC is 0x40000, the register number
+ *	   being passed is 0x40000+the address of the target register.
+ *	   (See epic.h for register addresses).
+ *  Output:  The 32 bit little endian value of the register.
+ */
+
+unsigned int mpc824x_eummbar_read (unsigned int regNum)
+{
+	unsigned int temp;
+
+	temp = *(volatile unsigned int *) (EUMBBAR_VAL + regNum);
+	temp = PCISWAP (temp);
+	return temp;
+}
+
+
+/*
+ *  Write a value to a register in the Embedded Utilities Memory
+ *  Block address space.
+ *  Input: regNum - register number + utility base address.  Example,
+ *                  the base address of EPIC is 0x40000, the register
+ *	            number is 0x40000+the address of the target register.
+ *	            (See epic.h for register addresses).
+ *         regVal - value to be written to the register.
+ */
+
+void mpc824x_eummbar_write (unsigned int regNum, unsigned int regVal)
+{
+	*(volatile unsigned int *) (EUMBBAR_VAL + regNum) = PCISWAP (regVal);
+	return;
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/arch/powerpc/cpu/mpc824x/cpu_init.c b/arch/powerpc/cpu/mpc824x/cpu_init.c
new file mode 100644
index 0000000..395f776
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/cpu_init.c
@@ -0,0 +1,417 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor. Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <mpc824x.h>
+
+#ifndef CONFIG_SYS_BANK0_ROW
+#define CONFIG_SYS_BANK0_ROW 0
+#endif
+#ifndef CONFIG_SYS_BANK1_ROW
+#define CONFIG_SYS_BANK1_ROW 0
+#endif
+#ifndef CONFIG_SYS_BANK2_ROW
+#define CONFIG_SYS_BANK2_ROW 0
+#endif
+#ifndef CONFIG_SYS_BANK3_ROW
+#define CONFIG_SYS_BANK3_ROW 0
+#endif
+#ifndef CONFIG_SYS_BANK4_ROW
+#define CONFIG_SYS_BANK4_ROW 0
+#endif
+#ifndef CONFIG_SYS_BANK5_ROW
+#define CONFIG_SYS_BANK5_ROW 0
+#endif
+#ifndef CONFIG_SYS_BANK6_ROW
+#define CONFIG_SYS_BANK6_ROW 0
+#endif
+#ifndef CONFIG_SYS_BANK7_ROW
+#define CONFIG_SYS_BANK7_ROW 0
+#endif
+#ifndef CONFIG_SYS_DBUS_SIZE2
+#define CONFIG_SYS_DBUS_SIZE2 0
+#endif
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ */
+void
+cpu_init_f (void)
+{
+/* MOUSSE board is initialized in asm */
+#if !defined(CONFIG_MOUSSE) && !defined(CONFIG_BMW)
+    register unsigned long val;
+    CONFIG_WRITE_HALFWORD(PCICR, 0x06); /* Bus Master, respond to PCI memory space acesses*/
+/*    CONFIG_WRITE_HALFWORD(PCISR, 0xffff); */ /*reset PCISR*/
+
+#if defined(CONFIG_MUSENKI) || defined(CONFIG_PN62)
+/* Why is this here, you ask?  Try, just try setting 0x8000
+ * in PCIACR with CONFIG_WRITE_HALFWORD()
+ * this one was a stumper, and we are annoyed
+ */
+
+#define M_CONFIG_WRITE_HALFWORD( addr, data ) \
+	__asm__ __volatile__("		\
+		stw  %2,0(%0)\n		\
+		sync\n			\
+		sth  %3,2(%1)\n		\
+		sync\n			\
+		"			\
+		: /* no output */	\
+		: "r" (CONFIG_ADDR), "r" (CONFIG_DATA),			\
+		"r" (PCISWAP(addr & ~3)), "r" (PCISWAP(data << 16))	\
+	);
+
+	M_CONFIG_WRITE_HALFWORD(PCIACR, 0x8000);
+#endif
+
+	CONFIG_WRITE_BYTE(PCLSR, 0x8);	/* set PCI cache line size */
+	CONFIG_WRITE_BYTE (PLTR, 0x40); /* set PCI latency timer */
+	/*
+	* Note that although this bit is cleared after a hard reset, it
+	* must be explicitly set and then cleared by software during
+	* initialization in order to guarantee correct operation of the
+	* DLL and the SDRAM_CLK[0:3] signals (if they are used).
+	*/
+	CONFIG_READ_BYTE (AMBOR, val);
+	CONFIG_WRITE_BYTE(AMBOR, val & 0xDF);
+	CONFIG_WRITE_BYTE(AMBOR, val | 0x20);
+	CONFIG_WRITE_BYTE(AMBOR, val & 0xDF);
+#ifdef CONFIG_MPC8245
+	/* silicon bug 28 MPC8245 */
+	CONFIG_READ_BYTE(AMBOR,val);
+	CONFIG_WRITE_BYTE(AMBOR,val|0x1);
+
+#if 0
+	/*
+	 * The following bug only affects older (XPC8245) processors.
+	 * DMA transfers initiated by external devices get corrupted due
+	 * to a hardware scheduling problem.
+	 *
+	 * The effect is:
+	 * when transferring X words, the first 32 words are transferred
+	 * OK, the next 3 x 32 words are 'old' data (from previous DMA)
+	 * while the rest of the X words is xferred fine.
+	 *
+	 * Disabling 3 of the 4 32 word hardware buffers solves the problem
+	 * with no significant performance loss.
+	 */
+
+	CONFIG_READ_BYTE(PCMBCR,val);
+	/* in order not to corrupt data which is being read over the PCI bus
+	* with the PPC as slave, we need to reduce the number of PCMRBs to 1,
+	* 4.11 in the  processor user manual
+	* */
+
+#if 1
+	CONFIG_WRITE_BYTE(PCMBCR,(val|0xC0)); /* 1 PCMRB */
+#else
+	CONFIG_WRITE_BYTE(PCMBCR,(val|0x80)); /* 2 PCMRBs */
+	CONFIG_WRITE_BYTE(PCMBCR,(val|0x40)); /* 3 PCMRBs */
+	/* default, 4 PCMRBs are used */
+#endif
+#endif
+#endif
+
+	CONFIG_READ_WORD(PICR1, val);
+#if defined(CONFIG_MPC8240)
+	CONFIG_WRITE_WORD( PICR1,
+		(val & (PICR1_ADDRESS_MAP | PICR1_RCS0)) |
+		       PIRC1_MSK | PICR1_PROC_TYPE_603E |
+		       PICR1_FLASH_WR_EN | PICR1_MCP_EN |
+		       PICR1_CF_DPARK | PICR1_EN_PCS |
+		       PICR1_CF_APARK );
+#elif defined(CONFIG_MPC8245)
+	CONFIG_WRITE_WORD( PICR1,
+		(val & (PICR1_RCS0)) |
+		       PICR1_PROC_TYPE_603E |
+		       PICR1_FLASH_WR_EN | PICR1_MCP_EN |
+		       PICR1_CF_DPARK | PICR1_NO_BUSW_CK |
+		       PICR1_DEC| PICR1_CF_APARK | 0x10); /* 8245 UM says bit 4 must be set */
+#else
+#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
+#endif
+
+	CONFIG_READ_WORD(PICR2, val);
+	val= val & ~ (PICR2_CF_SNOOP_WS_MASK | PICR2_CF_APHASE_WS_MASK); /*mask off waitstate bits*/
+#ifndef CONFIG_PN62
+	val |= PICR2_CF_SNOOP_WS_1WS | PICR2_CF_APHASE_WS_1WS; /*1 wait state*/
+#endif
+	CONFIG_WRITE_WORD(PICR2, val);
+
+	CONFIG_WRITE_WORD(EUMBBAR, CONFIG_SYS_EUMB_ADDR);
+#ifndef CONFIG_SYS_RAMBOOT
+	CONFIG_WRITE_WORD(MCCR1, (CONFIG_SYS_ROMNAL << MCCR1_ROMNAL_SHIFT) |
+				 (CONFIG_SYS_BANK0_ROW) |
+				 (CONFIG_SYS_BANK1_ROW << MCCR1_BANK1ROW_SHIFT) |
+				 (CONFIG_SYS_BANK2_ROW << MCCR1_BANK2ROW_SHIFT) |
+				 (CONFIG_SYS_BANK3_ROW << MCCR1_BANK3ROW_SHIFT) |
+				 (CONFIG_SYS_BANK4_ROW << MCCR1_BANK4ROW_SHIFT) |
+				 (CONFIG_SYS_BANK5_ROW << MCCR1_BANK5ROW_SHIFT) |
+				 (CONFIG_SYS_BANK6_ROW << MCCR1_BANK6ROW_SHIFT) |
+				 (CONFIG_SYS_BANK7_ROW << MCCR1_BANK7ROW_SHIFT) |
+				 (CONFIG_SYS_ROMFAL << MCCR1_ROMFAL_SHIFT));
+#endif
+
+#if defined(CONFIG_SYS_ASRISE) && defined(CONFIG_SYS_ASFALL)
+	CONFIG_WRITE_WORD(MCCR2, CONFIG_SYS_REFINT << MCCR2_REFINT_SHIFT |
+				 CONFIG_SYS_ASRISE << MCCR2_ASRISE_SHIFT |
+				 CONFIG_SYS_ASFALL << MCCR2_ASFALL_SHIFT);
+#else
+	CONFIG_WRITE_WORD(MCCR2, CONFIG_SYS_REFINT << MCCR2_REFINT_SHIFT);
+#endif
+
+#if defined(CONFIG_MPC8240)
+	CONFIG_WRITE_WORD(MCCR3,
+		(((CONFIG_SYS_BSTOPRE & 0x003c) >> 2) << MCCR3_BSTOPRE2TO5_SHIFT) |
+		(CONFIG_SYS_REFREC << MCCR3_REFREC_SHIFT) |
+		(CONFIG_SYS_RDLAT  << MCCR3_RDLAT_SHIFT));
+#elif defined(CONFIG_MPC8245)
+	CONFIG_WRITE_WORD(MCCR3,
+		(((CONFIG_SYS_BSTOPRE & 0x003c) >> 2) << MCCR3_BSTOPRE2TO5_SHIFT) |
+		(CONFIG_SYS_REFREC << MCCR3_REFREC_SHIFT));
+#else
+#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
+#endif
+
+/* this is gross.  We think these should all be the same, and various boards
+ *  should define CONFIG_SYS_ACTORW to 0 if they don't want to set it, or even, if
+ *  its not set, we define it to zero in this file
+ */
+#if defined(CONFIG_CU824) || defined(CONFIG_PN62)
+	CONFIG_WRITE_WORD(MCCR4,
+	(CONFIG_SYS_PRETOACT << MCCR4_PRETOACT_SHIFT) |
+	(CONFIG_SYS_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) |
+	MCCR4_BIT21 |
+	(CONFIG_SYS_REGISTERD_TYPE_BUFFER ? MCCR4_REGISTERED: 0) |
+	((CONFIG_SYS_BSTOPRE & 0x0003) <<MCCR4_BSTOPRE0TO1_SHIFT ) |
+	(((CONFIG_SYS_SDMODE_CAS_LAT <<4) | (CONFIG_SYS_SDMODE_WRAP <<3) |
+		  CONFIG_SYS_SDMODE_BURSTLEN) << MCCR4_SDMODE_SHIFT) |
+	(CONFIG_SYS_ACTORW << MCCR4_ACTTORW_SHIFT) |
+	(((CONFIG_SYS_BSTOPRE & 0x03c0) >> 6) << MCCR4_BSTOPRE6TO9_SHIFT));
+#elif defined(CONFIG_MPC8240)
+	CONFIG_WRITE_WORD(MCCR4,
+	(CONFIG_SYS_PRETOACT << MCCR4_PRETOACT_SHIFT) |
+	(CONFIG_SYS_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) |
+	MCCR4_BIT21 |
+	(CONFIG_SYS_REGISTERD_TYPE_BUFFER ? MCCR4_REGISTERED: 0) |
+	((CONFIG_SYS_BSTOPRE & 0x0003) <<MCCR4_BSTOPRE0TO1_SHIFT ) |
+	(((CONFIG_SYS_SDMODE_CAS_LAT <<4) | (CONFIG_SYS_SDMODE_WRAP <<3) |
+		  (CONFIG_SYS_SDMODE_BURSTLEN)) <<MCCR4_SDMODE_SHIFT) |
+	(((CONFIG_SYS_BSTOPRE & 0x03c0) >> 6) <<MCCR4_BSTOPRE6TO9_SHIFT ));
+#elif defined(CONFIG_MPC8245)
+	CONFIG_READ_WORD(MCCR1, val);
+	val &= MCCR1_DBUS_SIZE0;    /* test for 64-bit mem bus */
+
+	CONFIG_WRITE_WORD(MCCR4,
+		(CONFIG_SYS_PRETOACT << MCCR4_PRETOACT_SHIFT) |
+		(CONFIG_SYS_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) |
+		(CONFIG_SYS_EXTROM ? MCCR4_EXTROM : 0) |
+		(CONFIG_SYS_REGDIMM ? MCCR4_REGDIMM : 0) |
+		(CONFIG_SYS_REGISTERD_TYPE_BUFFER ? MCCR4_REGISTERED: 0) |
+		((CONFIG_SYS_BSTOPRE & 0x0003) <<MCCR4_BSTOPRE0TO1_SHIFT ) |
+		(CONFIG_SYS_DBUS_SIZE2 << MCCR4_DBUS_SIZE2_SHIFT) |
+		(((CONFIG_SYS_SDMODE_CAS_LAT <<4) | (CONFIG_SYS_SDMODE_WRAP <<3) |
+		      (val ? 2 : 3)) << MCCR4_SDMODE_SHIFT)  |
+		(CONFIG_SYS_ACTORW << MCCR4_ACTTORW_SHIFT) |
+		(((CONFIG_SYS_BSTOPRE & 0x03c0) >> 6) <<MCCR4_BSTOPRE6TO9_SHIFT ));
+#else
+#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
+#endif
+
+	CONFIG_WRITE_WORD(MSAR1,
+		( (CONFIG_SYS_BANK0_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) |
+		(((CONFIG_SYS_BANK1_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) |
+		(((CONFIG_SYS_BANK2_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) |
+		(((CONFIG_SYS_BANK3_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24));
+	CONFIG_WRITE_WORD(EMSAR1,
+		( (CONFIG_SYS_BANK0_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) |
+		(((CONFIG_SYS_BANK1_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) |
+		(((CONFIG_SYS_BANK2_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) |
+		(((CONFIG_SYS_BANK3_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24));
+	CONFIG_WRITE_WORD(MSAR2,
+		( (CONFIG_SYS_BANK4_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) |
+		(((CONFIG_SYS_BANK5_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) |
+		(((CONFIG_SYS_BANK6_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) |
+		(((CONFIG_SYS_BANK7_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24));
+	CONFIG_WRITE_WORD(EMSAR2,
+		( (CONFIG_SYS_BANK4_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) |
+		(((CONFIG_SYS_BANK5_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) |
+		(((CONFIG_SYS_BANK6_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) |
+		(((CONFIG_SYS_BANK7_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24));
+	CONFIG_WRITE_WORD(MEAR1,
+		( (CONFIG_SYS_BANK0_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) |
+		(((CONFIG_SYS_BANK1_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) |
+		(((CONFIG_SYS_BANK2_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) |
+		(((CONFIG_SYS_BANK3_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24));
+	CONFIG_WRITE_WORD(EMEAR1,
+		( (CONFIG_SYS_BANK0_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) |
+		(((CONFIG_SYS_BANK1_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) |
+		(((CONFIG_SYS_BANK2_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) |
+		(((CONFIG_SYS_BANK3_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24));
+	CONFIG_WRITE_WORD(MEAR2,
+		( (CONFIG_SYS_BANK4_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) |
+		(((CONFIG_SYS_BANK5_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) |
+		(((CONFIG_SYS_BANK6_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) |
+		(((CONFIG_SYS_BANK7_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24));
+	CONFIG_WRITE_WORD(EMEAR2,
+		( (CONFIG_SYS_BANK4_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) |
+		(((CONFIG_SYS_BANK5_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) |
+		(((CONFIG_SYS_BANK6_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) |
+		(((CONFIG_SYS_BANK7_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24));
+
+	CONFIG_WRITE_BYTE(ODCR, CONFIG_SYS_ODCR);
+#ifdef CONFIG_SYS_DLL_MAX_DELAY
+	CONFIG_WRITE_BYTE(MIOCR1, CONFIG_SYS_DLL_MAX_DELAY);	/* needed to make DLL lock */
+#endif
+#if defined(CONFIG_SYS_DLL_EXTEND) && defined(CONFIG_SYS_PCI_HOLD_DEL)
+	CONFIG_WRITE_BYTE(PMCR2, CONFIG_SYS_DLL_EXTEND | CONFIG_SYS_PCI_HOLD_DEL);
+#endif
+#if defined(MIOCR2) && defined(CONFIG_SYS_SDRAM_DSCD)
+	CONFIG_WRITE_BYTE(MIOCR2, CONFIG_SYS_SDRAM_DSCD);	/* change memory input */
+#endif /* setup & hold time */
+
+	CONFIG_WRITE_BYTE(MBER,
+		 CONFIG_SYS_BANK0_ENABLE |
+		(CONFIG_SYS_BANK1_ENABLE << 1) |
+		(CONFIG_SYS_BANK2_ENABLE << 2) |
+		(CONFIG_SYS_BANK3_ENABLE << 3) |
+		(CONFIG_SYS_BANK4_ENABLE << 4) |
+		(CONFIG_SYS_BANK5_ENABLE << 5) |
+		(CONFIG_SYS_BANK6_ENABLE << 6) |
+		(CONFIG_SYS_BANK7_ENABLE << 7));
+
+#ifdef CONFIG_SYS_PGMAX
+	CONFIG_WRITE_BYTE(MPMR, CONFIG_SYS_PGMAX);
+#endif
+
+	/* ! Wait 200us before initialize other registers */
+	/*FIXME: write a decent udelay wait */
+	__asm__ __volatile__(
+		" mtctr	%0 \n \
+		0: bdnz	 0b\n"
+		:
+		: "r" (0x10000));
+
+	CONFIG_READ_WORD(MCCR1, val);
+	CONFIG_WRITE_WORD(MCCR1, val | MCCR1_MEMGO); /* set memory access going */
+	__asm__ __volatile__("eieio");
+
+#endif /* !CONFIG_MOUSSE && !CONFIG_BMW */
+}
+
+
+#ifdef CONFIG_MOUSSE
+#ifdef INCLUDE_MPC107_REPORT
+struct MPC107_s {
+	unsigned int iobase;
+	char desc[120];
+} MPC107Regs[] = {
+	{ BMC_BASE +  0x00, "MPC107 Vendor/Device ID"		},
+	{ BMC_BASE +  0x04, "MPC107 PCI Command/Status Register" },
+	{ BMC_BASE +  0x08, "MPC107 Revision"			},
+	{ BMC_BASE +  0x0C, "MPC107 Cache Line Size"		},
+	{ BMC_BASE +  0x10, "MPC107 LMBAR"			},
+	{ BMC_BASE +  0x14, "MPC824x PCSR"			},
+	{ BMC_BASE +  0xA8, "MPC824x PICR1"			},
+	{ BMC_BASE +  0xAC, "MPC824x PICR2"			},
+	{ BMC_BASE +  0x46, "MPC824x PACR"			},
+	{ BMC_BASE + 0x310, "MPC824x ITWR"			},
+	{ BMC_BASE + 0x300, "MPC824x OMBAR"			},
+	{ BMC_BASE + 0x308, "MPC824x OTWR"			},
+	{ BMC_BASE +  0x14, "MPC107 Peripheral Control and Status Register" },
+	{ BMC_BASE + 0x78, "MPC107 EUMBAR"			},
+	{ BMC_BASE + 0xC0, "MPC107 Processor Bus Error Status"	},
+	{ BMC_BASE + 0xC4, "MPC107 PCI Bus Error Status"	},
+	{ BMC_BASE + 0xC8, "MPC107 Processor/PCI Error Address"	},
+	{ BMC_BASE + 0xE0, "MPC107 AMBOR Register"		},
+	{ BMC_BASE + 0xF0, "MPC107 MCCR1 Register"		},
+	{ BMC_BASE + 0xF4, "MPC107 MCCR2 Register"		},
+	{ BMC_BASE + 0xF8, "MPC107 MCCR3 Register"		},
+	{ BMC_BASE + 0xFC, "MPC107 MCCR4 Register"		},
+};
+#define N_MPC107_Regs	(sizeof(MPC107Regs)/sizeof(MPC107Regs[0]))
+#endif /* INCLUDE_MPC107_REPORT */
+#endif /* CONFIG_MOUSSE */
+
+/*
+ * initialize higher level parts of CPU like time base and timers
+ */
+int cpu_init_r (void)
+{
+#ifdef CONFIG_MOUSSE
+#ifdef INCLUDE_MPC107_REPORT
+	unsigned int tmp = 0, i;
+#endif
+	/*
+	 * Initialize the EUMBBAR (Embedded Util Mem Block Base Addr Reg).
+	 * This is necessary before the EPIC, DMA ctlr, I2C ctlr, etc. can
+	 * be accessed.
+	 */
+
+#ifdef CONFIG_MPC8240			/* only on MPC8240 */
+	mpc824x_mpc107_setreg (EUMBBAR, EUMBBAR_VAL);
+	/* MOT/SPS: Issue #10002, PCI (FD Alias enable) */
+	mpc824x_mpc107_setreg (AMBOR, 0x000000C0);
+#endif
+
+
+#ifdef INCLUDE_MPC107_REPORT
+	/* Check MPC824x PCI Device and Vendor ID */
+	while ((tmp = mpc824x_mpc107_getreg (BMC_BASE)) != 0x31057) {
+		printf ("	MPC107: offset=0x%x, val = 0x%x\n",
+			BMC_BASE,
+			tmp);
+	}
+
+	for (i = 0; i < N_MPC107_Regs; i++) {
+		printf ("	0x%x/%s = 0x%x\n",
+			MPC107Regs[i].iobase,
+			MPC107Regs[i].desc,
+			mpc824x_mpc107_getreg (MPC107Regs[i].iobase));
+	}
+
+	printf ("IBAT0L = 0x%08X\n", mfspr (IBAT0L));
+	printf ("IBAT0U = 0x%08X\n", mfspr (IBAT0U));
+	printf ("IBAT1L = 0x%08X\n", mfspr (IBAT1L));
+	printf ("IBAT1U = 0x%08X\n", mfspr (IBAT1U));
+	printf ("IBAT2L = 0x%08X\n", mfspr (IBAT2L));
+	printf ("IBAT2U = 0x%08X\n", mfspr (IBAT2U));
+	printf ("IBAT3L = 0x%08X\n", mfspr (IBAT3L));
+	printf ("IBAT3U = 0x%08X\n", mfspr (IBAT3U));
+	printf ("DBAT0L = 0x%08X\n", mfspr (DBAT0L));
+	printf ("DBAT0U = 0x%08X\n", mfspr (DBAT0U));
+	printf ("DBAT1L = 0x%08X\n", mfspr (DBAT1L));
+	printf ("DBAT1U = 0x%08X\n", mfspr (DBAT1U));
+	printf ("DBAT2L = 0x%08X\n", mfspr (DBAT2L));
+	printf ("DBAT2U = 0x%08X\n", mfspr (DBAT2U));
+	printf ("DBAT3L = 0x%08X\n", mfspr (DBAT3L));
+	printf ("DBAT3U = 0x%08X\n", mfspr (DBAT3U));
+#endif /* INCLUDE_MPC107_REPORT */
+#endif /* CONFIG_MOUSSE */
+	return (0);
+}
diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic.h b/arch/powerpc/cpu/mpc824x/drivers/epic.h
new file mode 100644
index 0000000..2803f63
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/epic.h
@@ -0,0 +1 @@
+#include "epic/epic.h"
diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/README b/arch/powerpc/cpu/mpc824x/drivers/epic/README
new file mode 100644
index 0000000..5798996
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/epic/README
@@ -0,0 +1,102 @@
+CONTENT:
+
+   epic.h
+   epic1.c
+   epic2.s
+
+WHAT ARE THESE FILES:
+
+These files contain MPC8240 (Kahlua) EPIC
+driver routines. The driver routines are not
+written for any specific operating system.
+They serves the purpose of code sample, and
+jump-start for using the MPC8240 EPIC unit.
+
+For the reason of correctness of C language
+syntax, these files are compiled by Metaware
+C compiler and assembler.
+
+ENDIAN NOTATION:
+
+The algorithm is designed for big-endian mode,
+software is responsible for byte swapping.
+
+USAGE:
+
+1. The host system that is running on MPC8240
+   shall link the files listed here. The memory
+   location of driver routines shall take into
+   account of that driver routines need to run
+   in supervisor mode and they process external
+   interrupts.
+
+   The routine epic_exception shall be called by
+   exception vector at location 0x500, i.e.,
+   603e core external exception vector.
+
+2. The host system is responsible for configuring
+   the MPC8240 including Embedded Utilities Memory
+   Block. All EPIC driver functions require the
+   content of Embedded Utilities Memory Block
+   Base Address Register, EUMBBAR, as the first
+   parameter.
+
+3. Before EPIC unit of MPC8240 can be used,
+   initialize EPIC unit by calling epicInit
+   with the corresponding parameters.
+
+   The initialization shall disable the 603e
+   core External Exception by calling CoreExtIntDisable( ).
+   Next, call epicInit( ). Last, enable the 603e core
+   External Exception by calling CoreExtIntEnable( ).
+
+4. After EPIC unit has been successfully initialized,
+   epicIntSourceSet( ) shall be used to register each
+   external interrupt source. Anytime, an external
+   interrupt source can be disabled or enabled by
+   calling corresponding function, epicIntDisable( ),
+   or epicIntEnable( ).
+
+   Global Timers' resource, base count and frequency,
+   can be changed by calling epicTmFrequencySet( )
+   and epicTmBaseSet( ).
+
+   To stop counting a specific global timer, use
+   the function, epicTmInhibit while epicTmEnable
+   can be used to start counting a timer.
+
+5. To mask a set of external interrupts that are
+   are certain level below, epicIntPrioritySet( )
+   can be used. For example, if the processor's
+   current task priority register is set to 0x7,
+   only interrupts of priority 0x8 or higher will
+   be passed to the processor.
+
+   Be careful when using this function. It may
+   corrupt the current interrupt pending, selector,
+   and request registers, resulting an invalid vetor.
+
+   After enabling an interrupt, disable it may also
+   cause an invalid vector. User may consider using
+   the spurious vector interrupt service routine to
+   handle this case.
+
+6. The EPIC driver routines contains a set
+   of utilities, Set and Get, for host system
+   to query and modify the desired EPIC source
+   registers.
+
+7. Each external interrupt source shall register
+   its interrupt service routine. The routine
+   shall contain all interrupt source specific
+   processes and keep as short as possible.
+
+   Special customized end of interrupt routine
+   is optional. If it is needed, it shall contain
+   the external interrupt source specific end of
+   interrupt process.
+
+   External interrupt exception vector at 0x500
+   shall always call the epicEOI just before
+   rfi instruction. Refer to the routine,
+   epic_exception, for a code sample.
diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/epic.h b/arch/powerpc/cpu/mpc824x/drivers/epic/epic.h
new file mode 100644
index 0000000..58f81c5
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/epic/epic.h
@@ -0,0 +1,163 @@
+/*********************************************************************
+ * mpc8240epic.h - EPIC module of the MPC8240 micro-controller
+ *
+ * Copyrigh 1999  Motorola Inc.
+ *
+ * Modification History:
+ * =====================
+ * 01a,04Feb99,My  Created.
+ * 15Nov200, robt -modified to use in U-Boot
+ *
+*/
+
+#ifndef __INCEPICh
+#define __INCEPICh
+
+#define ULONG unsigned long
+#define MAXVEC             20
+#define MAXIRQ        5 /* IRQs */
+#define EPIC_DIRECT_IRQ     0 /* Direct interrupt type */
+
+/* EPIC register addresses */
+
+#define EPIC_EUMBBAR      0x40000     /* EUMBBAR of EPIC  */
+#define EPIC_FEATURES_REG (EPIC_EUMBBAR + 0x01000)/* Feature reporting */
+#define EPIC_GLOBAL_REG   (EPIC_EUMBBAR + 0x01020)/* Global config.  */
+#define EPIC_INT_CONF_REG (EPIC_EUMBBAR + 0x01030)/* Interrupt config. */
+#define EPIC_VENDOR_ID_REG  (EPIC_EUMBBAR + 0x01080)/* Vendor id */
+#define EPIC_PROC_INIT_REG  (EPIC_EUMBBAR + 0x01090)/* Processor init. */
+#define EPIC_SPUR_VEC_REG (EPIC_EUMBBAR + 0x010e0)/* Spurious vector */
+#define EPIC_TM_FREQ_REG  (EPIC_EUMBBAR + 0x010f0)/* Timer Frequency */
+
+#define EPIC_TM0_CUR_COUNT_REG  (EPIC_EUMBBAR + 0x01100)/* Gbl TM0 Cur. Count*/
+#define EPIC_TM0_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01110)/* Gbl TM0 Base Count*/
+#define EPIC_TM0_VEC_REG  (EPIC_EUMBBAR + 0x01120)/* Gbl TM0 Vector Pri*/
+#define EPIC_TM0_DES_REG  (EPIC_EUMBBAR + 0x01130)/* Gbl TM0 Dest. */
+
+#define EPIC_TM1_CUR_COUNT_REG  (EPIC_EUMBBAR + 0x01140)/* Gbl TM1 Cur. Count*/
+#define EPIC_TM1_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01150)/* Gbl TM1 Base Count*/
+#define EPIC_TM1_VEC_REG  (EPIC_EUMBBAR + 0x01160)/* Gbl TM1 Vector Pri*/
+#define EPIC_TM1_DES_REG  (EPIC_EUMBBAR + 0x01170)/* Gbl TM1 Dest. */
+
+#define EPIC_TM2_CUR_COUNT_REG  (EPIC_EUMBBAR + 0x01180)/* Gbl TM2 Cur. Count*/
+#define EPIC_TM2_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01190)/* Gbl TM2 Base Count*/
+#define EPIC_TM2_VEC_REG  (EPIC_EUMBBAR + 0x011a0)/* Gbl TM2 Vector Pri*/
+#define EPIC_TM2_DES_REG  (EPIC_EUMBBAR + 0x011b0)/* Gbl TM2 Dest */
+
+#define EPIC_TM3_CUR_COUNT_REG  (EPIC_EUMBBAR + 0x011c0)/* Gbl TM3 Cur. Count*/
+#define EPIC_TM3_BASE_COUNT_REG (EPIC_EUMBBAR + 0x011d0)/* Gbl TM3 Base Count*/
+#define EPIC_TM3_VEC_REG  (EPIC_EUMBBAR + 0x011e0)/* Gbl TM3 Vector Pri*/
+#define EPIC_TM3_DES_REG  (EPIC_EUMBBAR + 0x011f0)/* Gbl TM3 Dest. */
+
+#define EPIC_EX_INT0_VEC_REG  (EPIC_EUMBBAR + 0x10200)/* Ext. Int. Sr0 Des */
+#define EPIC_EX_INT0_DES_REG  (EPIC_EUMBBAR + 0x10210)/* Ext. Int. Sr0 Vect*/
+#define EPIC_EX_INT1_VEC_REG  (EPIC_EUMBBAR + 0x10220)/* Ext. Int. Sr1 Des */
+#define EPIC_EX_INT1_DES_REG  (EPIC_EUMBBAR + 0x10230)/* Ext. Int. Sr1 Vect*/
+#define EPIC_EX_INT2_VEC_REG  (EPIC_EUMBBAR + 0x10240)/* Ext. Int. Sr2 Des */
+#define EPIC_EX_INT2_DES_REG  (EPIC_EUMBBAR + 0x10250)/* Ext. Int. Sr2 Vect*/
+#define EPIC_EX_INT3_VEC_REG  (EPIC_EUMBBAR + 0x10260)/* Ext. Int. Sr3 Des */
+#define EPIC_EX_INT3_DES_REG  (EPIC_EUMBBAR + 0x10270)/* Ext. Int. Sr3 Vect*/
+#define EPIC_EX_INT4_VEC_REG  (EPIC_EUMBBAR + 0x10280)/* Ext. Int. Sr4 Des */
+#define EPIC_EX_INT4_DES_REG  (EPIC_EUMBBAR + 0x10290)/* Ext. Int. Sr4 Vect*/
+
+#define EPIC_SR_INT0_VEC_REG  (EPIC_EUMBBAR + 0x10200)/* Sr. Int. Sr0 Des */
+#define EPIC_SR_INT0_DES_REG  (EPIC_EUMBBAR + 0x10210)/* Sr. Int. Sr0 Vect */
+#define EPIC_SR_INT1_VEC_REG  (EPIC_EUMBBAR + 0x10220)/* Sr. Int. Sr1 Des */
+#define EPIC_SR_INT1_DES_REG  (EPIC_EUMBBAR + 0x10230)/* Sr. Int. Sr1 Vect.*/
+#define EPIC_SR_INT2_VEC_REG  (EPIC_EUMBBAR + 0x10240)/* Sr. Int. Sr2 Des */
+#define EPIC_SR_INT2_DES_REG  (EPIC_EUMBBAR + 0x10250)/* Sr. Int. Sr2 Vect.*/
+#define EPIC_SR_INT3_VEC_REG  (EPIC_EUMBBAR + 0x10260)/* Sr. Int. Sr3 Des */
+#define EPIC_SR_INT3_DES_REG  (EPIC_EUMBBAR + 0x10270)/* Sr. Int. Sr3 Vect.*/
+#define EPIC_SR_INT4_VEC_REG  (EPIC_EUMBBAR + 0x10280)/* Sr. Int. Sr4 Des */
+#define EPIC_SR_INT4_DES_REG  (EPIC_EUMBBAR + 0x10290)/* Sr. Int. Sr4 Vect.*/
+
+#define EPIC_SR_INT5_VEC_REG  (EPIC_EUMBBAR + 0x102a0)/* Sr. Int. Sr5 Des */
+#define EPIC_SR_INT5_DES_REG  (EPIC_EUMBBAR + 0x102b0)/* Sr. Int. Sr5 Vect.*/
+#define EPIC_SR_INT6_VEC_REG  (EPIC_EUMBBAR + 0x102c0)/* Sr. Int. Sr6 Des */
+#define EPIC_SR_INT6_DES_REG  (EPIC_EUMBBAR + 0x102d0)/* Sr. Int. Sr6 Vect.*/
+#define EPIC_SR_INT7_VEC_REG  (EPIC_EUMBBAR + 0x102e0)/* Sr. Int. Sr7 Des */
+#define EPIC_SR_INT7_DES_REG  (EPIC_EUMBBAR + 0x102f0)/* Sr. Int. Sr7 Vect.*/
+#define EPIC_SR_INT8_VEC_REG  (EPIC_EUMBBAR + 0x10300)/* Sr. Int. Sr8 Des */
+#define EPIC_SR_INT8_DES_REG  (EPIC_EUMBBAR + 0x10310)/* Sr. Int. Sr8 Vect.*/
+#define EPIC_SR_INT9_VEC_REG  (EPIC_EUMBBAR + 0x10320)/* Sr. Int. Sr9 Des */
+#define EPIC_SR_INT9_DES_REG  (EPIC_EUMBBAR + 0x10330)/* Sr. Int. Sr9 Vect.*/
+
+#define EPIC_SR_INT10_VEC_REG (EPIC_EUMBBAR + 0x10340)/* Sr. Int. Sr10 Des */
+#define EPIC_SR_INT10_DES_REG (EPIC_EUMBBAR + 0x10350)/* Sr. Int. Sr10 Vect*/
+#define EPIC_SR_INT11_VEC_REG (EPIC_EUMBBAR + 0x10360)/* Sr. Int. Sr11 Des */
+#define EPIC_SR_INT11_DES_REG (EPIC_EUMBBAR + 0x10370)/* Sr. Int. Sr11 Vect*/
+#define EPIC_SR_INT12_VEC_REG (EPIC_EUMBBAR + 0x10380)/* Sr. Int. Sr12 Des */
+#define EPIC_SR_INT12_DES_REG (EPIC_EUMBBAR + 0x10390)/* Sr. Int. Sr12 Vect*/
+#define EPIC_SR_INT13_VEC_REG (EPIC_EUMBBAR + 0x103a0)/* Sr. Int. Sr13 Des */
+#define EPIC_SR_INT13_DES_REG (EPIC_EUMBBAR + 0x103b0)/* Sr. Int. Sr13 Vect*/
+#define EPIC_SR_INT14_VEC_REG (EPIC_EUMBBAR + 0x103c0)/* Sr. Int. Sr14 Des */
+#define EPIC_SR_INT14_DES_REG (EPIC_EUMBBAR + 0x103d0)/* Sr. Int. Sr14 Vect*/
+#define EPIC_SR_INT15_VEC_REG (EPIC_EUMBBAR + 0x103e0)/* Sr. Int. Sr15 Des */
+#define EPIC_SR_INT15_DES_REG (EPIC_EUMBBAR + 0x103f0)/* Sr. Int. Sr15 Vect*/
+
+#define EPIC_I2C_INT_VEC_REG  (EPIC_EUMBBAR + 0x11020)/* I2C Int. Vect Pri.*/
+#define EPIC_I2C_INT_DES_REG  (EPIC_EUMBBAR + 0x11030)/* I2C Int. Dest */
+#define EPIC_DMA0_INT_VEC_REG (EPIC_EUMBBAR + 0x11040)/* DMA0 Int. Vect Pri*/
+#define EPIC_DMA0_INT_DES_REG (EPIC_EUMBBAR + 0x11050)/* DMA0 Int. Dest */
+#define EPIC_DMA1_INT_VEC_REG (EPIC_EUMBBAR + 0x11060)/* DMA1 Int. Vect Pri*/
+#define EPIC_DMA1_INT_DES_REG (EPIC_EUMBBAR + 0x11070)/* DMA1 Int. Dest */
+#define EPIC_MSG_INT_VEC_REG  (EPIC_EUMBBAR + 0x110c0)/* Msg Int. Vect Pri*/
+#define EPIC_MSG_INT_DES_REG  (EPIC_EUMBBAR + 0x110d0)/* Msg Int. Dest  */
+
+#define EPIC_PROC_CTASK_PRI_REG (EPIC_EUMBBAR + 0x20080)/* Proc. current task*/
+#define EPIC_PROC_INT_ACK_REG (EPIC_EUMBBAR + 0x200a0)/* Int. acknowledge */
+#define EPIC_PROC_EOI_REG (EPIC_EUMBBAR + 0x200b0)/* End of interrupt */
+
+#define EPIC_VEC_PRI_MASK      0x80000000 /* Mask Interrupt bit in IVPR */
+#define EPIC_VEC_PRI_DFLT_PRI  8          /* Interrupt Priority in IVPR */
+
+/* Error code */
+
+#define OK       0
+#define ERROR    -1
+
+/* function prototypes */
+
+void epicVendorId( unsigned int *step,
+       unsigned int *devId,
+       unsigned int *venId
+     );
+void epicFeatures( unsigned int *noIRQs,
+	     unsigned int *noCPUs,
+       unsigned int *VerId );
+extern void epicInit( unsigned int IRQType, unsigned int clkRatio);
+ULONG sysEUMBBARRead ( ULONG regNum );
+void sysEUMBBARWrite ( ULONG regNum, ULONG regVal);
+extern void epicTmFrequencySet( unsigned int frq );
+extern unsigned int epicTmFrequencyGet(void);
+extern unsigned int epicTmBaseSet( ULONG srcAddr,
+		 unsigned int cnt,
+		 unsigned int inhibit );
+extern unsigned int epicTmBaseGet ( ULONG srcAddr, unsigned int *val );
+extern unsigned int epicTmCountGet( ULONG srcAddr, unsigned int *val );
+extern unsigned int epicTmInhibit( unsigned int timer );
+extern unsigned int epicTmEnable( ULONG srcAdr );
+extern void CoreExtIntEnable(void);  /* Enable 603e external interrupts */
+extern void CoreExtIntDisable(void); /* Disable 603e external interrupts */
+extern unsigned char epicIntTaskGet(void);
+extern void epicIntTaskSet( unsigned char val );
+extern unsigned int epicIntAck(void);
+extern void epicSprSet( unsigned int eumbbar, unsigned char );
+extern void epicConfigGet( unsigned int *clkRatio,
+	       unsigned int *serEnable );
+extern void SrcVecTableInit(void);
+extern unsigned int  epicModeGet(void);
+extern void epicIntEnable(int Vect);
+extern void epicIntDisable(int Vect);
+extern int epicIntSourceConfig(int Vect, int Polarity, int Sense, int Prio);
+extern unsigned int epicIntAck(void);
+extern void epicEOI(void);
+extern int epicCurTaskPrioSet(int Vect);
+
+struct SrcVecTable
+    {
+     ULONG srcAddr;
+     char  srcName[40];
+    };
+
+#endif   /*  EPIC_H */
diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/epic1.c b/arch/powerpc/cpu/mpc824x/drivers/epic/epic1.c
new file mode 100644
index 0000000..ecbb42d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/epic/epic1.c
@@ -0,0 +1,517 @@
+/**************************************************
+ *
+ * copyright @ motorola, 1999
+ *
+ *************************************************/
+#include <mpc824x.h>
+#include <common.h>
+#include "epic.h"
+
+
+#define PRINT(format, args...) printf(format , ## args)
+
+typedef void (*VOIDFUNCPTR)  (void);  /* ptr to function returning void */
+struct SrcVecTable SrcVecTable[MAXVEC] = /* Addr/Vector cross-reference tbl */
+    {
+    { EPIC_EX_INT0_VEC_REG,  "External Direct/Serial Source 0"},
+    { EPIC_EX_INT1_VEC_REG,  "External Direct/Serial Source 1"},
+    { EPIC_EX_INT2_VEC_REG,  "External Direct/Serial Source 2"},
+    { EPIC_EX_INT3_VEC_REG,  "External Direct/Serial Source 3"},
+    { EPIC_EX_INT4_VEC_REG,  "External Direct/Serial Source 4"},
+
+    { EPIC_SR_INT5_VEC_REG,  "External Serial Source 5"},
+    { EPIC_SR_INT6_VEC_REG,  "External Serial Source 6"},
+    { EPIC_SR_INT7_VEC_REG,  "External Serial Source 7"},
+    { EPIC_SR_INT8_VEC_REG,  "External Serial Source 8"},
+    { EPIC_SR_INT9_VEC_REG,  "External Serial Source 9"},
+    { EPIC_SR_INT10_VEC_REG, "External Serial Source 10"},
+    { EPIC_SR_INT11_VEC_REG, "External Serial Source 11"},
+    { EPIC_SR_INT12_VEC_REG, "External Serial Source 12"},
+    { EPIC_SR_INT13_VEC_REG, "External Serial Source 13"},
+    { EPIC_SR_INT14_VEC_REG, "External Serial Source 14"},
+    { EPIC_SR_INT15_VEC_REG, "External Serial Source 15"},
+
+    { EPIC_I2C_INT_VEC_REG,  "Internal I2C Source"},
+    { EPIC_DMA0_INT_VEC_REG, "Internal DMA0 Source"},
+    { EPIC_DMA1_INT_VEC_REG, "Internal DMA1 Source"},
+    { EPIC_MSG_INT_VEC_REG,  "Internal Message Source"},
+    };
+
+VOIDFUNCPTR intVecTbl[MAXVEC];    /* Interrupt vector table */
+
+
+/****************************************************************************
+*  epicInit - Initialize the EPIC registers
+*
+*  This routine resets the Global Configuration Register, thus it:
+*     -  Disables all interrupts
+*     -  Sets epic registers to reset values
+*     -  Sets the value of the Processor Current Task Priority to the
+*        highest priority (0xF).
+*  epicInit then sets the EPIC operation mode to Mixed Mode (vs. Pass
+*  Through or 8259 compatible mode).
+*
+*  If IRQType (input) is Direct IRQs:
+*     - IRQType is written to the SIE bit of the EPIC Interrupt
+*       Configuration register (ICR).
+*     - clkRatio is ignored.
+*  If IRQType is Serial IRQs:
+*     - both IRQType and clkRatio will be written to the ICR register
+*/
+
+void epicInit
+    (
+    unsigned int IRQType,      /* Direct or Serial */
+    unsigned int clkRatio      /* Clk Ratio for Serial IRQs */
+    )
+    {
+    ULONG tmp;
+
+    tmp = sysEUMBBARRead(EPIC_GLOBAL_REG);
+    tmp |= 0xa0000000;                  /* Set the Global Conf. register */
+    sysEUMBBARWrite(EPIC_GLOBAL_REG, tmp);
+	/*
+	 * Wait for EPIC to reset - CLH
+	 */
+    while( (sysEUMBBARRead(EPIC_GLOBAL_REG) & 0x80000000) == 1);
+    sysEUMBBARWrite(EPIC_GLOBAL_REG, 0x20000000);
+    tmp = sysEUMBBARRead(EPIC_INT_CONF_REG);    /* Read interrupt conf. reg */
+
+    if (IRQType == EPIC_DIRECT_IRQ)             /* direct mode */
+	sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp & 0xf7ffffff);
+    else                                        /* Serial mode */
+	{
+	tmp = (clkRatio << 28) | 0x08000000;    /* Set clock ratio */
+	sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp);
+	}
+
+    while (epicIntAck() != 0xff)       /* Clear all pending interrupts */
+		epicEOI();
+}
+
+/****************************************************************************
+ *  epicIntEnable - Enable an interrupt source
+ *
+ *  This routine clears the mask bit of an external, an internal or
+ *  a Timer register to enable the interrupt.
+ *
+ *  RETURNS:  None
+ */
+void epicIntEnable(int intVec)
+{
+    ULONG tmp;
+    ULONG srAddr;
+
+    srAddr = SrcVecTable[intVec].srcAddr;  /* Retrieve src Vec/Prio register */
+    tmp = sysEUMBBARRead(srAddr);
+    tmp &= ~EPIC_VEC_PRI_MASK;             /* Clear the mask bit */
+    tmp |= (EPIC_VEC_PRI_DFLT_PRI << 16);   /* Set priority to Default - CLH */
+    tmp |= intVec;				           /* Set Vector number */
+    sysEUMBBARWrite(srAddr, tmp);
+
+    return;
+    }
+
+/****************************************************************************
+ *  epicIntDisable - Disable an interrupt source
+ *
+ *  This routine sets the mask bit of an external, an internal or
+ *  a Timer register to disable the interrupt.
+ *
+ *  RETURNS:  OK or ERROR
+ *
+ */
+
+void epicIntDisable
+    (
+    int intVec        /* Interrupt vector number */
+    )
+    {
+
+    ULONG tmp, srAddr;
+
+    srAddr = SrcVecTable[intVec].srcAddr;
+    tmp = sysEUMBBARRead(srAddr);
+    tmp |= 0x80000000;                      /* Set the mask bit */
+    sysEUMBBARWrite(srAddr, tmp);
+    return;
+    }
+
+/****************************************************************************
+ * epicIntSourceConfig - Set properties of an interrupt source
+ *
+ * This function sets interrupt properites (Polarity, Sense, Interrupt
+ * Prority, and Interrupt Vector) of an Interrupt Source.  The properties
+ * can be set when the current source is not in-request or in-service,
+ * which is determined by the Activity bit.  This routine return ERROR
+ * if the the Activity bit is 1 (in-request or in-service).
+ *
+ * This function assumes that the Source Vector/Priority register (input)
+ * is a valid address.
+ *
+ * RETURNS:  OK or ERROR
+ */
+
+int epicIntSourceConfig
+    (
+    int   Vect,                         /* interrupt source vector number */
+    int   Polarity,                     /* interrupt source polarity */
+    int   Sense,                        /* interrupt source Sense */
+    int   Prio                          /* interrupt source priority */
+    )
+
+    {
+    ULONG tmp, newVal;
+    ULONG actBit, srAddr;
+
+    srAddr = SrcVecTable[Vect].srcAddr;
+    tmp = sysEUMBBARRead(srAddr);
+    actBit = (tmp & 40000000) >> 30;    /* retrieve activity bit - bit 30 */
+    if (actBit == 1)
+	return ERROR;
+
+    tmp &= 0xff30ff00;     /* Erase previously set P,S,Prio,Vector bits */
+    newVal = (Polarity << 23) | (Sense << 22) | (Prio << 16) | Vect;
+    sysEUMBBARWrite(srAddr, tmp | newVal );
+    return (OK);
+    }
+
+/****************************************************************************
+ * epicIntAck - acknowledge an interrupt
+ *
+ * This function reads the Interrupt acknowldge register and return
+ * the vector number of the highest pending interrupt.
+ *
+ * RETURNS: Interrupt Vector number.
+ */
+
+unsigned int epicIntAck(void)
+{
+    return(sysEUMBBARRead( EPIC_PROC_INT_ACK_REG ));
+}
+
+/****************************************************************************
+ * epicEOI - signal an end of interrupt
+ *
+ * This function writes 0x0 to the EOI register to signal end of interrupt.
+ * It is usually called after an interrupt routine is served.
+ *
+ * RETURNS: None
+ */
+
+void epicEOI(void)
+    {
+    sysEUMBBARWrite(EPIC_PROC_EOI_REG, 0x0);
+    }
+
+/****************************************************************************
+ *  epicCurTaskPrioSet - sets the priority of the Processor Current Task
+ *
+ *  This function should be called after epicInit() to lower the priority
+ *  of the processor current task.
+ *
+ *  RETURNS:  OK or ERROR
+ */
+
+int epicCurTaskPrioSet
+    (
+    int prioNum                 /* New priority value */
+    )
+    {
+
+    if ( (prioNum < 0) || (prioNum > 0xF))
+	return ERROR;
+    sysEUMBBARWrite(EPIC_PROC_CTASK_PRI_REG, prioNum);
+    return OK;
+    }
+
+
+/************************************************************************
+ * function: epicIntTaskGet
+ *
+ * description: Get value of processor current interrupt task priority register
+ *
+ * note:
+ ***********************************************************************/
+unsigned char epicIntTaskGet()
+{
+  /* get the interrupt task priority register */
+    ULONG reg;
+    unsigned char rec;
+
+    reg = sysEUMBBARRead( EPIC_PROC_CTASK_PRI_REG );
+    rec = ( reg & 0x0F );
+    return rec;
+}
+
+
+/**************************************************************
+ * function: epicISR
+ *
+ * description: EPIC service routine called by the core exception
+ *              at 0x500
+ *
+ * note:
+ **************************************************************/
+unsigned int epicISR(void)
+{
+   return 0;
+}
+
+
+/************************************************************
+ * function: epicModeGet
+ *
+ * description: query EPIC mode, return 0 if pass through mode
+ *                               return 1 if mixed mode
+ *
+ * note:
+ *************************************************************/
+unsigned int epicModeGet(void)
+{
+    ULONG val;
+
+    val = sysEUMBBARRead( EPIC_GLOBAL_REG );
+    return (( val & 0x20000000 ) >> 29);
+}
+
+
+/*********************************************
+ * function: epicConfigGet
+ *
+ * description: Get the EPIC interrupt Configuration
+ *              return 0 if not error, otherwise return 1
+ *
+ * note:
+ ********************************************/
+void epicConfigGet( unsigned int *clkRatio, unsigned int *serEnable)
+{
+    ULONG val;
+
+    val = sysEUMBBARRead( EPIC_INT_CONF_REG );
+    *clkRatio = ( val & 0x70000000 ) >> 28;
+    *serEnable = ( val & 0x8000000 ) >> 27;
+}
+
+
+/*******************************************************************
+ *  sysEUMBBARRead - Read a 32-bit EUMBBAR register
+ *
+ *  This routine reads the content of a register in the Embedded
+ *  Utilities Memory Block, and swaps to big endian before returning
+ *  the value.
+ *
+ *  RETURNS:  The content of the specified EUMBBAR register.
+ */
+
+ULONG sysEUMBBARRead
+    (
+    ULONG regNum
+    )
+    {
+    ULONG temp;
+
+    temp = *(ULONG *) (CONFIG_SYS_EUMB_ADDR + regNum);
+    return ( LONGSWAP(temp));
+    }
+
+/*******************************************************************
+ *  sysEUMBBARWrite - Write a 32-bit EUMBBAR register
+ *
+ *  This routine swaps the value to little endian then writes it to
+ *  a register in the Embedded Utilities Memory Block address space.
+ *
+ *  RETURNS: N/A
+ */
+
+void sysEUMBBARWrite
+    (
+    ULONG regNum,               /* EUMBBAR register address */
+    ULONG regVal                /* Value to be written */
+    )
+    {
+
+    *(ULONG *) (CONFIG_SYS_EUMB_ADDR + regNum) = LONGSWAP(regVal);
+    return ;
+    }
+
+
+/********************************************************
+ * function: epicVendorId
+ *
+ * description: return the EPIC Vendor Identification
+ *              register:
+ *
+ *              siliccon version, device id, and vendor id
+ *
+ * note:
+ ********************************************************/
+void epicVendorId
+   (
+    unsigned int *step,
+    unsigned int *devId,
+    unsigned int *venId
+   )
+   {
+    ULONG val;
+    val = sysEUMBBARRead( EPIC_VENDOR_ID_REG );
+    *step  = ( val & 0x00FF0000 ) >> 16;
+    *devId = ( val & 0x0000FF00 ) >> 8;
+    *venId = ( val & 0x000000FF );
+    }
+
+/**************************************************
+ * function: epicFeatures
+ *
+ * description: return the number of IRQ supported,
+ *              number of CPU, and the version of the
+ *              OpenEPIC
+ *
+ * note:
+ *************************************************/
+void epicFeatures
+    (
+    unsigned int *noIRQs,
+    unsigned int *noCPUs,
+    unsigned int *verId
+    )
+    {
+    ULONG val;
+
+    val = sysEUMBBARRead( EPIC_FEATURES_REG );
+    *noIRQs  = ( val & 0x07FF0000 ) >> 16;
+    *noCPUs  = ( val & 0x00001F00 ) >> 8;
+    *verId   = ( val & 0x000000FF );
+}
+
+
+/*********************************************************
+ * function: epciTmFrequncySet
+ *
+ * description: Set the timer frequency reporting register
+ ********************************************************/
+void epicTmFrequencySet( unsigned int frq )
+{
+    sysEUMBBARWrite(EPIC_TM_FREQ_REG, frq);
+}
+
+/*******************************************************
+ * function: epicTmFrequncyGet
+ *
+ * description: Get the current value of the Timer Frequency
+ * Reporting register
+ *
+ ******************************************************/
+unsigned int epicTmFrequencyGet(void)
+{
+    return( sysEUMBBARRead(EPIC_TM_FREQ_REG)) ;
+}
+
+
+/****************************************************
+ * function: epicTmBaseSet
+ *
+ * description: Set the #n global timer base count register
+ *              return 0 if no error, otherwise return 1.
+ *
+ * note:
+ ****************************************************/
+unsigned int epicTmBaseSet
+    (
+    ULONG srcAddr,         /* Address of the Timer Base register */
+    unsigned int cnt,    /* Base count */
+    unsigned int inhibit   /* 1 - count inhibit */
+    )
+{
+
+    unsigned int val = 0x80000000;
+    /* First inhibit counting the timer */
+    sysEUMBBARWrite(srcAddr, val) ;
+
+    /* set the new value */
+    val = (cnt & 0x7fffffff) | ((inhibit & 0x1) << 31);
+    sysEUMBBARWrite(srcAddr, val) ;
+    return 0;
+}
+
+/***********************************************************************
+ * function: epicTmBaseGet
+ *
+ * description: Get the current value of the global timer base count register
+ *              return 0 if no error, otherwise return 1.
+ *
+ * note:
+ ***********************************************************************/
+unsigned int epicTmBaseGet( ULONG srcAddr, unsigned int *val )
+{
+    *val = sysEUMBBARRead( srcAddr );
+    *val = *val & 0x7fffffff;
+    return 0;
+}
+
+/***********************************************************
+ * function: epicTmCountGet
+ *
+ * description: Get the value of a given global timer
+ *              current count register
+ *              return 0 if no error, otherwise return 1
+ * note:
+ **********************************************************/
+unsigned int epicTmCountGet( ULONG srcAddr, unsigned int *val )
+{
+    *val = sysEUMBBARRead( srcAddr );
+    *val = *val & 0x7fffffff;
+    return 0;
+}
+
+
+/***********************************************************
+ * function: epicTmInhibit
+ *
+ * description: Stop counting of a given global timer
+ *              return 0 if no error, otherwise return 1
+ *
+ * note:
+ ***********************************************************/
+unsigned int epicTmInhibit( unsigned int srcAddr )
+{
+    ULONG val;
+
+    val = sysEUMBBARRead( srcAddr );
+    val |= 0x80000000;
+    sysEUMBBARWrite( srcAddr, val );
+    return 0;
+}
+
+/******************************************************************
+ * function: epicTmEnable
+ *
+ * description: Enable counting of a given global timer
+ *              return 0 if no error, otherwise return 1
+ *
+ * note:
+ *****************************************************************/
+unsigned int epicTmEnable( ULONG srcAddr )
+{
+    ULONG val;
+
+    val = sysEUMBBARRead( srcAddr );
+    val &= 0x7fffffff;
+    sysEUMBBARWrite( srcAddr, val );
+    return 0;
+}
+
+void epicSourcePrint(int Vect)
+    {
+    ULONG srcVal;
+
+    srcVal = sysEUMBBARRead(SrcVecTable[Vect].srcAddr);
+    PRINT("%s\n", SrcVecTable[Vect].srcName);
+    PRINT("Address   = 0x%lx\n", SrcVecTable[Vect].srcAddr);
+    PRINT("Vector    = %ld\n", (srcVal & 0x000000FF) );
+    PRINT("Mask      = %ld\n", srcVal >> 31);
+    PRINT("Activitiy = %ld\n", (srcVal & 40000000) >> 30);
+    PRINT("Polarity  = %ld\n", (srcVal & 0x00800000) >> 23);
+    PRINT("Sense     = %ld\n", (srcVal & 0x00400000) >> 22);
+    PRINT("Priority  = %ld\n", (srcVal & 0x000F0000) >> 16);
+    }
diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/epic2.S b/arch/powerpc/cpu/mpc824x/drivers/epic/epic2.S
new file mode 100644
index 0000000..52d19aa
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/epic/epic2.S
@@ -0,0 +1,196 @@
+/**************************************
+ *
+ * copyright @ Motorola, 1999
+ *
+ **************************************/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <asm/processor.h>
+
+/*********************************************
+ * function: CoreExtIntEnable
+ *
+ * description: Enable 603e core external interrupt
+ *
+ * note: mtmsr is context-synchronization
+ **********************************************/
+		.text
+		.align 2
+	.global CoreExtIntEnable
+CoreExtIntEnable:
+	 mfmsr    r3
+
+	 ori      r3,r3,0x8000         /* enable external interrupt */
+	 mtmsr    r3
+
+	 bclr 20, 0
+
+/*******************************************
+ * function: CoreExtIntDisable
+ *
+ * description: Disable 603e core external interrupt
+ *
+ * note:
+ *******************************************/
+		.text
+		.align 2
+	.global CoreExtIntDisable
+CoreExtIntDisable:
+	mfmsr    r4
+
+	xor	r3,r3,r3
+	or      r3,r3,r4
+
+	andis.	r4,r4,0xffff
+	andi.   r3,r3,0x7fff         /* disable external interrupt */
+
+	or      r3,r3,r4
+	mtmsr    r3
+
+	bclr 20, 0
+
+/*********************************************************
+ * function: epicEOI
+ *
+ * description: signal the EOI and restore machine status
+ *       Input: r3 - value of eumbbar
+ *       Output: r3 - value of eumbbar
+ *               r4 - ISR vector value
+ * note:
+ ********************************************************/
+		.text
+		.align 2
+	.global epicEOI
+epicEOI:
+	lis	r5,0x0006	        /* Build End Of Interrupt Register offset */
+	ori	r5,r5,0x00b0
+	xor	r7,r7,r7	        /* Clear r7 */
+	stwbrx	r7,r5,r3	    /* Save r7, writing to this register will
+					     * intidate the end of processing the
+					     * highest interrupt.
+			     */
+	sync
+
+	/* ---RESTORE MACHINE STATE */
+	mfmsr	r13		        /* Clear Recoverable Interrupt bit in MSR */
+	or      r7,r7,r13
+
+	andis.  r7,r7,0xffff
+	andi.	r13,r13,0x7ffd	/* (and disable interrupts) */
+	or      r13,r13,r7
+	mtmsr	r13
+
+	lwz   r13,0x1c(r1)      /* pull ctr */
+	mtctr r13
+
+	lwz   r13,0x18(r1)      /* pull xer */
+	mtctr r13
+
+	lwz   r13,0x14(r1)      /* pull lr */
+	mtctr r13
+
+	lwz	    r13,0x10(r1)	/* Pull SRR1 from stack */
+	mtspr   SRR1,r13	    /* Restore SRR1 */
+
+	lwz	    r13,0xc(r1)	    /* Pull SRR0 from stack */
+	mtspr   SRR0,r13	    /* Restore SRR0 */
+
+	lwz	    r13,0x8(r1)	    /* Pull User stack pointer from stack */
+	mtspr   SPRG1,r13	    /* Restore SPRG1 */
+
+	lwz	r4,0x4(r1)          /* vector value */
+	lwz	r3,0x0(r1)          /* eumbbar */
+	sync
+
+	addi	r1,r1,0x20	/* Deallocate stack */
+	mtspr   SPRG0,r1	/* Save updated Supervisor stack pointer */
+	mfspr   r1,SPRG1	/* Restore User stack pointer */
+
+	bclr     20,0
+
+/***********************************************************
+ * function: exception routine called by exception vector
+ *           at 0x500, external interrupt
+ *
+ * description: Kahlua EPIC controller
+ *
+ * input:  r3 - content of eumbbar
+ * output: r3 - ISR return value
+ *         r4 - Interrupt vector number
+ * note:
+ ***********************************************************/
+
+       .text
+	   .align 2
+       .global epic_exception
+
+epic_exception:
+
+	/*---SAVE MACHINE STATE TO A STACK */
+	mtspr   SPRG1,r1	/* Save User stack pointer to SPRG1 */
+	mfspr	r1,SPRG0	/* Load Supervisor stack pointer into r1 */
+
+	stwu	r3,-0x20(r1)	/* Push the value of eumbbar onto stack */
+
+	mfspr	r3,SPRG1	/* Push User stack pointer onto stack */
+	stw	    r3,0x8(r1)
+	mfspr	r3,SRR0	    /* Push SRR0 onto stack */
+	stw	    r1,0xc(r1)
+	mfspr	r3,SRR1	    /* Push SRR1 onto stack */
+	stw	    r3,0x10(r1)
+	mflr    r3
+	stw     r3,0x14(r1) /* Push LR */
+	mfxer   r3
+	stw     r3,0x18(r1) /* Push Xer */
+	mfctr   r3
+	stw     r3,0x1c(r1) /* Push CTR */
+
+	mtspr	SPRG0,r1	/* Save updated Supervisor stack pointer
+					 * value to SPRG0
+			 */
+	mfmsr	r3
+	ori	    r3,r3,0x0002	/* Set Recoverable Interrupt bit in MSR */
+	mtmsr	r3
+
+	/* ---READ IN THE EUMBAR REGISTER */
+    lwz     r6,0(r1)       /* this is eumbbar */
+    sync
+
+	/* ---READ EPIC REGISTER:	PROCESSOR INTERRUPT ACKNOWLEDGE REGISTER */
+	lis	r5,0x0006	        /* Build Interrupt Acknowledge Register
+					     * offset
+			     */
+	ori	r5,r5,0x00a0
+	lwbrx	r7,r5,r6    /* Load interrupt vector into r7 */
+	sync
+
+	/* --MASK OFF ALL BITS EXCEPT THE VECTOR */
+	xor	r3,r3,r3
+    xor r4,r4,r4
+	or    r3, r3, r6        /*  eumbbar in r3 */
+	andi. r4,r7,0x00ff	/* Mask off bits, vector in r4 */
+
+    stw     r4,0x04(r1)     /* save the vector value */
+
+    lis     r5,epicISR@ha
+	ori     r5,r5,epicISR@l
+	mtlr    r5
+	blrl
+
+    xor   r30,r30,r30
+	or    r30,r30,r3        /* save the r3 which containts the return value from epicISR */
+
+	/* ---READ IN THE EUMBAR REGISTER */
+    lwz     r3,0(r1)
+    sync
+
+    lis     r5,epicEOI@ha
+	ori     r5,r5,epicEOI@l
+	mtlr    r5
+	blrl
+
+    xor  r3,r3,r3
+	or   r3,r3,r30           /* restore the ISR return value  */
+
+	bclr     20,0
diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/epicutil.S b/arch/powerpc/cpu/mpc824x/drivers/epic/epicutil.S
new file mode 100644
index 0000000..4877050
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/epic/epicutil.S
@@ -0,0 +1,57 @@
+/**************************************
+ *
+ * copyright @ Motorola, 1999
+ *
+ *
+ * This file contains two commonly used
+ * lower level utility routines.
+ *
+ * The utility routines are also in other
+ * Kahlua device driver libraries. The
+ * need to be linked in only once.
+ **************************************/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+/**********************************************************
+ * function: load_runtime_reg
+ *
+ * input:  r3 - value of eumbbar
+ *         r4 - register offset in embedded utility space
+ *
+ * output: r3 - register content
+ **********************************************************/
+      .text
+      .align 2
+      .global load_runtime_reg
+
+load_runtime_reg:
+
+		  xor r5,r5,r5
+	  or  r5,r5,r3       /* save eumbbar */
+
+	      lwbrx	r3,r4,r5
+	      sync
+
+	      bclr 20, 0
+
+/****************************************************************
+ * function: store_runtime_reg
+ *
+ * input: r3 - value of eumbbar
+ *        r4 - register offset in embedded utility space
+ *        r5 - new value to be stored
+ *
+ ****************************************************************/
+	   .text
+	   .align 2
+	   .global store_runtime_reg
+store_runtime_reg:
+
+		  xor r0,r0,r0
+
+	      stwbrx r5,  r4, r3
+	      sync
+
+		  bclr   20,0
diff --git a/arch/powerpc/cpu/mpc824x/drivers/errors.h b/arch/powerpc/cpu/mpc824x/drivers/errors.h
new file mode 100644
index 0000000..20794a2
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/errors.h
@@ -0,0 +1,212 @@
+/*	Copyright Motorola, Inc. 1993, 1994
+	ALL RIGHTS RESERVED
+
+	You are hereby granted a copyright license to use, modify, and
+	distribute the SOFTWARE so long as this entire notice is retained
+	without alteration in any modified and/or redistributed versions,
+	and that such modified versions are clearly identified as such.
+	No licenses are granted by implication, estoppel or otherwise under
+	any patents or trademarks of Motorola, Inc.
+
+	The SOFTWARE is provided on an "AS IS" basis and without warranty.
+	To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS
+	ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED
+	WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+	PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH
+	REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS
+	THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS.
+
+	To the maximum extent permitted by applicable law, IN NO EVENT SHALL
+	MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
+	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF
+	BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
+	INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR
+	INABILITY TO USE THE SOFTWARE.   Motorola assumes no responsibility
+	for the maintenance and support of the SOFTWARE.
+
+*/
+
+
+#include "config.h"
+
+/*
+	 1         2         3         4         5         6         7         8
+01234567890123456789012345678901234567890123456789012345678901234567890123456789
+*/
+/* List define statements here */
+
+/* These are for all the toolboxes and functions to use. These will help
+to standardize the error handling in the current project */
+
+				/* this is the "data type" for the error
+				messages in the system */
+#define STATUS unsigned int
+
+				/* this is a success status code */
+#define SUCCESS 1
+
+				/* likewise this is failure */
+#define FAILURE 0
+
+#define NUM_ERRORS 47
+
+/* This first section of "defines" are for error codes ONLY.  The called
+   routine will return one of these error codes to the caller.  If the final
+   returned code is "VALID", then everything is a-okay.  However, if one
+   of the functions returns a non-valid status, that error code should be
+   propogated back to all the callers.  At the end, the last caller will
+   call an error_processing function, and send in the status which was
+   returned.  It's up to the error_processing function to determine which
+   error occured (as indicated by the status), and print an appropriate
+   message back to the user.
+*/
+/*----------------------------------------------------------------------*/
+/* these are specifically for the parser routines			*/
+
+#define UNKNOWN_COMMAND		0xfb00 /* "unrecognized command " */
+#define UNKNOWN_REGISTER	0xfb01 /* "unknown register "*/
+#define ILLEGAL_RD_STAGE	0xfb02 /* cannot specify reg. family in range*/
+#define ILLEGAL_REG_FAMILY	0xfb03 /* "cannot specify a range of special
+					or miscellaneous registers"*/
+#define RANGE_CROSS_FAMILY	0xfb04 /* "cannot specify a range across
+					register families" */
+#define UNIMPLEMENTED_STAGE	0xfb05 /* invalid rd or rmm parameter format */
+#define REG_NOT_WRITEABLE	0xfb06 /* "unknown operator in arguements"*/
+#define INVALID_FILENAME	0xfb07 /* "invalid download filename" */
+#define INVALID_BAUD_RATE	0xfb08	/* invalid baud rate from sb command */
+#define UNSUPPORTED_REGISTER	0xfb09	/* Special register is not supported */
+#define FOR_BOARD_ONLY		0xfb0a  /* "Not available for Unix." */
+
+
+/*----------------------------------------------------------------------*/
+/* these are for the error checking toolbox				*/
+
+#define INVALID			0xfd00 /* NOT valid */
+#define VALID			0xfd01 /* valid */
+
+					/* This error is found in the fcn:
+					is_right_size_input() to indicate
+					that the input was not 8 characters
+					long.  */
+#define INVALID_SIZE		0xfd02
+
+					/* This error is found in the fcn:
+					is_valid_address_range() to indicate
+					that the address given falls outside
+					of valid memory defined by MEM_START
+					to MEM_END.
+					*/
+#define OUT_OF_BOUNDS_ADDRESS	0xfd03
+
+					/* This error is found in the fcn:
+					is_valid_hex_input() to indicate that
+					one of more of the characters entered
+					are not valid hex characters.  Valid
+					hex characters are 0-9, A-F, a-f.
+					*/
+#define INVALID_HEX_INPUT	0xfd04
+
+					/* This error is found in the fcn:
+					is_valid_register_number() to indicate
+					that a given register does not exist.
+					*/
+#define REG_NOT_READABLE	0xfd05
+
+					/* This error is found in the fcn:
+					is_word_aligned_address() to indicate
+					that the given address is not word-
+					aligned.  A word-aligned address ends
+					in 0x0,0x4,0x8,0xc.
+					*/
+#define	NOT_WORD_ALIGNED	0xfd07
+
+					/* This error is found in the fcn:
+					is_valid_address_range() to indicate
+					that the starting address is greater
+					than the ending address.
+					*/
+#define REVERSED_ADDRESS	0xfd08
+
+					/* this error tells us that the address
+					specified as the destination is within
+					the source addresses  */
+#define RANGE_OVERLAP		0xfd09
+
+
+#define	ERROR			0xfd0a /* An error occured */
+#define INVALID_PARAM		0xfd0b /* "invalid input parameter " */
+
+
+#define INVALID_FLAG		0xfd0c	/* invalid flag */
+
+/*----------------------------------------------------------------------*/
+/* these are for the getarg toolbox					*/
+
+#define INVALID_NUMBER_ARGS	0xFE00 /* invalid number of commd arguements */
+#define UNKNOWN_PARAMETER	0xFE01 /* "unknown type of parameter "*/
+
+
+/*----------------------------------------------------------------------*/
+/* these are for the tokenizer toolbox					*/
+
+#define ILLEGAL_CHARACTER	0xFF00 /* unrecognized char. in input stream*/
+#define TTL_NOT_SORTED		0xFF01 /* token translation list not sorted */
+#define TTL_NOT_DEFINED		0xFF02 /* token translation list not assigned*/
+#define INVALID_STRING		0xFF03 /* unable to extract string from input */
+#define BUFFER_EMPTY		0xFF04 /* "input buffer is empty" */
+#define INVALID_MODE		0xFF05 /* input buf is in an unrecognized mode*/
+#define TOK_INTERNAL_ERROR	0xFF06 /* "internal tokenizer error" */
+#define TOO_MANY_IBS		0xFF07 /* "too many open input buffers" */
+#define NO_OPEN_IBS		0xFF08 /* "no open input buffers" */
+
+
+/* these are for the read from screen toolbox */
+
+#define RESERVED_WORD		0xFC00 /* used a reserved word as an arguement*/
+
+
+/* these are for the breakpoint routines */
+
+#define FULL_BPDS		0xFA00 /* breakpoint data structure is full */
+
+
+/* THESE are for the downloader */
+
+#define NOT_IN_S_RECORD_FORMAT	0xf900 /* "not in S-Record Format" */
+#define UNREC_RECORD_TYPE	0xf901 /* "unrecognized record type" */
+#define CONVERSION_ERROR	0xf902 /* "ascii to int conversion error" */
+#define INVALID_MEMORY		0xf903 /* "bad s-record memory address " */
+
+
+/* these are for the compression and decompression stuff */
+
+#define COMP_UNK_CHARACTER	0xf800 /* "unknown compressed character " */
+
+#define COMP_UNKNOWN_STATE	0xf801 /* "unknown binary state" */
+
+#define NOT_IN_COMPRESSED_FORMAT 0xf802 /* not in compressed S-Record format */
+
+
+/* these are for the DUART handling things */
+
+					/* "unrecognized serial port configuration" */
+#define UNKNOWN_PORT_STATE	0xf700
+
+
+/* these are for the register toolbox */
+
+					/* "cannot find register in special
+					 purpose register file " */
+#define SPR_NOT_FOUND		0xf600
+
+
+/* these are for the duart specific stuff */
+
+					/* "transparent mode needs access to
+						two serial ports" */
+#define TM_NEEDS_BOTH_PORTS	0xf500
+
+
+/*----------------------------------------------------------------------*/
+/* these are specifically for the flash routines			*/
+#define FLASH_ERROR		0xf100		/* general flash error */
diff --git a/arch/powerpc/cpu/mpc824x/drivers/i2c/i2c.c b/arch/powerpc/cpu/mpc824x/drivers/i2c/i2c.c
new file mode 100644
index 0000000..637ae4c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/i2c/i2c.c
@@ -0,0 +1,270 @@
+/*
+ * (C) Copyright 2003
+ * Gleb Natapov <gnatapov@mrv.com>
+ * Some bits are taken from linux driver writen by adrian@humboldt.co.uk
+ *
+ * Hardware I2C driver for MPC107 PCI bridge.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#undef I2CDBG
+
+#ifdef CONFIG_HARD_I2C
+#include <i2c.h>
+
+#define TIMEOUT (CONFIG_SYS_HZ/4)
+
+#define I2C_Addr ((unsigned *)(CONFIG_SYS_EUMB_ADDR + 0x3000))
+
+#define I2CADR &I2C_Addr[0]
+#define I2CFDR  &I2C_Addr[1]
+#define I2CCCR  &I2C_Addr[2]
+#define I2CCSR  &I2C_Addr[3]
+#define I2CCDR  &I2C_Addr[4]
+
+#define MPC107_CCR_MEN  0x80
+#define MPC107_CCR_MIEN 0x40
+#define MPC107_CCR_MSTA 0x20
+#define MPC107_CCR_MTX  0x10
+#define MPC107_CCR_TXAK 0x08
+#define MPC107_CCR_RSTA 0x04
+
+#define MPC107_CSR_MCF  0x80
+#define MPC107_CSR_MAAS 0x40
+#define MPC107_CSR_MBB  0x20
+#define MPC107_CSR_MAL  0x10
+#define MPC107_CSR_SRW  0x04
+#define MPC107_CSR_MIF  0x02
+#define MPC107_CSR_RXAK 0x01
+
+#define I2C_READ  1
+#define I2C_WRITE 0
+
+/* taken from linux include/asm-ppc/io.h */
+inline unsigned in_le32 (volatile unsigned *addr)
+{
+	unsigned ret;
+
+	__asm__ __volatile__ ("lwbrx %0,0,%1;\n"
+			      "twi 0,%0,0;\n"
+			      "isync":"=r" (ret): "r" (addr), "m" (*addr));
+	return ret;
+}
+
+inline void out_le32 (volatile unsigned *addr, int val)
+{
+	__asm__ __volatile__ ("stwbrx %1,0,%2; eieio":"=m" (*addr):"r" (val),
+			      "r" (addr));
+}
+
+#define writel(val, addr) out_le32(addr, val)
+#define readl(addr) in_le32(addr)
+
+void i2c_init (int speed, int slaveadd)
+{
+	/* stop I2C controller */
+	writel (0x0, I2CCCR);
+	/* set clock */
+	writel (0x1020, I2CFDR);
+	/* write slave address */
+	writel (slaveadd, I2CADR);
+	/* clear status register */
+	writel (0x0, I2CCSR);
+	/* start I2C controller */
+	writel (MPC107_CCR_MEN, I2CCCR);
+
+	return;
+}
+
+static __inline__ int i2c_wait4bus (void)
+{
+	ulong timeval = get_timer (0);
+
+	while (readl (I2CCSR) & MPC107_CSR_MBB)
+		if (get_timer (timeval) > TIMEOUT)
+			return -1;
+
+	return 0;
+}
+
+static __inline__ int i2c_wait (int write)
+{
+	u32 csr;
+	ulong timeval = get_timer (0);
+
+	do {
+		csr = readl (I2CCSR);
+
+		if (!(csr & MPC107_CSR_MIF))
+			continue;
+
+		writel (0x0, I2CCSR);
+
+		if (csr & MPC107_CSR_MAL) {
+#ifdef I2CDBG
+			printf ("i2c_wait: MAL\n");
+#endif
+			return -1;
+		}
+
+		if (!(csr & MPC107_CSR_MCF)) {
+#ifdef I2CDBG
+			printf ("i2c_wait: unfinished\n");
+#endif
+			return -1;
+		}
+
+		if (write == I2C_WRITE && (csr & MPC107_CSR_RXAK)) {
+#ifdef I2CDBG
+			printf ("i2c_wait: No RXACK\n");
+#endif
+			return -1;
+		}
+
+		return 0;
+	} while (get_timer (timeval) < TIMEOUT);
+
+#ifdef I2CDBG
+	printf ("i2c_wait: timed out\n");
+#endif
+	return -1;
+}
+
+static __inline__ int i2c_write_addr (u8 dev, u8 dir, int rsta)
+{
+	writel (MPC107_CCR_MEN | MPC107_CCR_MSTA | MPC107_CCR_MTX |
+		(rsta ? MPC107_CCR_RSTA : 0), I2CCCR);
+
+	writel ((dev << 1) | dir, I2CCDR);
+
+	if (i2c_wait (I2C_WRITE) < 0)
+		return 0;
+
+	return 1;
+}
+
+static __inline__ int __i2c_write (u8 * data, int length)
+{
+	int i;
+
+	writel (MPC107_CCR_MEN | MPC107_CCR_MSTA | MPC107_CCR_MTX, I2CCCR);
+
+	for (i = 0; i < length; i++) {
+		writel (data[i], I2CCDR);
+
+		if (i2c_wait (I2C_WRITE) < 0)
+			break;
+	}
+
+	return i;
+}
+
+static __inline__ int __i2c_read (u8 * data, int length)
+{
+	int i;
+
+	writel (MPC107_CCR_MEN | MPC107_CCR_MSTA |
+		((length == 1) ? MPC107_CCR_TXAK : 0), I2CCCR);
+
+	/* dummy read */
+	readl (I2CCDR);
+
+	for (i = 0; i < length; i++) {
+		if (i2c_wait (I2C_READ) < 0)
+			break;
+
+		/* Generate ack on last next to last byte */
+		if (i == length - 2)
+			writel (MPC107_CCR_MEN | MPC107_CCR_MSTA |
+				MPC107_CCR_TXAK, I2CCCR);
+
+		/* Generate stop on last byte */
+		if (i == length - 1)
+			writel (MPC107_CCR_MEN | MPC107_CCR_TXAK, I2CCCR);
+
+		data[i] = readl (I2CCDR);
+	}
+
+	return i;
+}
+
+int i2c_read (u8 dev, uint addr, int alen, u8 * data, int length)
+{
+	int i = 0;
+	u8 *a = (u8 *) & addr;
+
+	if (i2c_wait4bus () < 0)
+		goto exit;
+
+	if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
+		goto exit;
+
+	if (__i2c_write (&a[4 - alen], alen) != alen)
+		goto exit;
+
+	if (i2c_write_addr (dev, I2C_READ, 1) == 0)
+		goto exit;
+
+	i = __i2c_read (data, length);
+
+exit:
+	writel (MPC107_CCR_MEN, I2CCCR);
+
+	return !(i == length);
+}
+
+int i2c_write (u8 dev, uint addr, int alen, u8 * data, int length)
+{
+	int i = 0;
+	u8 *a = (u8 *) & addr;
+
+	if (i2c_wait4bus () < 0)
+		goto exit;
+
+	if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
+		goto exit;
+
+	if (__i2c_write (&a[4 - alen], alen) != alen)
+		goto exit;
+
+	i = __i2c_write (data, length);
+
+exit:
+	writel (MPC107_CCR_MEN, I2CCCR);
+
+	return !(i == length);
+}
+
+int i2c_probe (uchar chip)
+{
+	int tmp;
+
+	/*
+	 * Try to read the first location of the chip.  The underlying
+	 * driver doesn't appear to support sending just the chip address
+	 * and looking for an <ACK> back.
+	 */
+	udelay (10000);
+	return i2c_read (chip, 0, 1, (uchar *) &tmp, 1);
+}
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/arch/powerpc/cpu/mpc824x/drivers/i2c_export.h b/arch/powerpc/cpu/mpc824x/drivers/i2c_export.h
new file mode 100644
index 0000000..6264d18
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/i2c_export.h
@@ -0,0 +1,103 @@
+#ifndef I2C_EXPORT_H
+#define I2C_EXPORT_H
+
+/****************************************************
+ *
+ * Copyright Motrola 1999
+ *
+ ****************************************************/
+
+/* These are the defined return values for the I2C_do_transaction function.
+ * Any non-zero value indicates failure.  Failure modes can be added for
+ * more detailed error reporting.
+ */
+typedef enum _i2c_status
+{
+ I2C_SUCCESS     = 0,
+ I2C_ERROR,
+} I2C_Status;
+
+/* These are the defined tasks for I2C_do_transaction.
+ * Modes for SLAVE_RCV and SLAVE_XMIT will be added.
+ */
+typedef enum _i2c_transaction_mode
+{
+	I2C_MASTER_RCV =  0,
+	I2C_MASTER_XMIT = 1,
+} I2C_TRANSACTION_MODE;
+
+typedef enum _i2c_interrupt_mode
+{
+	I2C_INT_DISABLE =  0,
+	I2C_INT_ENABLE = 1,
+} I2C_INTERRUPT_MODE;
+
+typedef enum _i2c_stop
+{
+	I2C_NO_STOP =  0,
+	I2C_STOP = 1,
+} I2C_STOP_MODE;
+
+typedef enum _i2c_restart
+{
+	I2C_NO_RESTART =  0,
+	I2C_RESTART = 1,
+} I2C_RESTART_MODE;
+
+/******************** App. API ********************
+ * The application API is for user level application
+ * to use the functionality provided by I2C driver.
+ * This is a "generic" I2C interface, it should contain
+ * nothing specific to the Kahlua implementation.
+ * Only the generic functions are exported by the library.
+ *
+ * Note: Its App.s responsibility to swap the data
+ *       byte. In our API, we just transfer whatever
+ *       we are given
+ **************************************************/
+
+
+/*  Initialize I2C unit with the following:
+ *  driver's slave address
+ *  interrupt enabled
+ *  optional pointer to application layer print function
+ *
+ *  These parameters may be added:
+ *  desired clock rate
+ *  digital filter frequency sampling rate
+ *
+ *  This function must be called before I2C unit can be used.
+ */
+extern I2C_Status I2C_Initialize(
+	unsigned char addr,            /* driver's I2C slave address */
+	I2C_INTERRUPT_MODE en_int,     /* 1 - enable I2C interrupt
+					* 0 - disable I2C interrupt
+					*/
+	int (*app_print_function)(char *,...)); /* pointer to optional "printf"
+						 * provided by application
+						 */
+
+/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV
+ * are implemented.  Both are only in polling mode.
+ *
+ * en_int controls interrupt/polling mode
+ * act is the type of transaction
+ * addr is the I2C address of the slave device
+ * len is the length of data to send or receive
+ * buffer is the address of the data buffer
+ * stop = I2C_NO_STOP, don't signal STOP at end of transaction
+ *        I2C_STOP, signal STOP at end of transaction
+ * retry is the timeout retry value, currently ignored
+ * rsta = I2C_NO_RESTART, this is not continuation of existing transaction
+ *        I2C_RESTART, this is a continuation of existing transaction
+ */
+extern I2C_Status I2C_do_transaction( I2C_INTERRUPT_MODE en_int,
+				      I2C_TRANSACTION_MODE act,
+				      unsigned char i2c_addr,
+				      unsigned char data_addr,
+				      int len,
+				      char *buffer,
+				      I2C_STOP_MODE stop,
+				      int retry,
+				      I2C_RESTART_MODE rsta);
+#endif
diff --git a/arch/powerpc/cpu/mpc824x/interrupts.c b/arch/powerpc/cpu/mpc824x/interrupts.c
new file mode 100644
index 0000000..139c52c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/interrupts.c
@@ -0,0 +1,93 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc824x.h>
+#include <asm/processor.h>
+#include <asm/pci_io.h>
+#include <commproc.h>
+#include "drivers/epic.h"
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+	*decrementer_count = (get_bus_freq (0) / 4) / CONFIG_SYS_HZ;
+
+	/*
+	 * It's all broken at the moment and I currently don't need
+	 * interrupts. If you want to fix it, have a look at the epic
+	 * drivers in dink32 v12. They do everthing and Motorola said
+	 * I could use the dink source in this project as long as
+	 * copyright notices remain intact.
+	 */
+
+	epicInit (EPIC_DIRECT_IRQ, 0);
+	/* EPIC won't generate INT unless Current Task Pri < 15 */
+	epicCurTaskPrioSet(0);
+
+	return (0);
+}
+
+/****************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt (struct pt_regs *regs)
+{
+	register unsigned long temp;
+
+	pci_readl (CONFIG_SYS_EUMB_ADDR + EPIC_PROC_INT_ACK_REG, temp);
+	sync ();					/* i'm not convinced this is needed, but dink source has it */
+	temp &= 0xff;				/*get vector */
+
+	/*TODO: handle them -... */
+	epicEOI ();
+}
+
+/****************************************************************************/
+
+/*
+ * blank int handlers.
+ */
+
+void
+irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
+{
+}
+
+void irq_free_handler (int vec)
+{
+
+}
+
+/*TODO: some handlers for winbond and 87308 interrupts
+ and what about generic pci inteerupts?
+ vga?
+ */
+
+void timer_interrupt_cpu (struct pt_regs *regs)
+{
+	/* nothing to do here */
+	return;
+}
diff --git a/arch/powerpc/cpu/mpc824x/pci.c b/arch/powerpc/cpu/mpc824x/pci.c
new file mode 100644
index 0000000..72aaec7
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/pci.c
@@ -0,0 +1,78 @@
+/*
+ * arch/powerpc/kernel/mpc10x_common.c
+ *
+ * Common routines for the Motorola SPS MPC106, MPC107 and MPC8240 Host bridge,
+ * Mem ctlr, EPIC, etc.
+ *
+ * Author: Mark A. Greer
+ *         mgreer@mvista.com
+ *
+ * Copyright 2001 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 <common.h>
+
+#ifdef CONFIG_PCI
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <pci.h>
+#include <mpc824x.h>
+
+void pci_mpc824x_init (struct pci_controller *hose)
+{
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	/* System memory space */
+	pci_set_region(hose->regions + 0,
+		       CHRP_PCI_MEMORY_BUS,
+		       CHRP_PCI_MEMORY_PHYS,
+		       CHRP_PCI_MEMORY_SIZE,
+		       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+	/* PCI memory space */
+	pci_set_region(hose->regions + 1,
+		       CHRP_PCI_MEM_BUS,
+		       CHRP_PCI_MEM_PHYS,
+		       CHRP_PCI_MEM_SIZE,
+		       PCI_REGION_MEM);
+
+	/* ISA/PCI memory space */
+	pci_set_region(hose->regions + 2,
+		       CHRP_ISA_MEM_BUS,
+		       CHRP_ISA_MEM_PHYS,
+		       CHRP_ISA_MEM_SIZE,
+		       PCI_REGION_MEM);
+
+	/* PCI I/O space */
+	pci_set_region(hose->regions + 3,
+		       CHRP_PCI_IO_BUS,
+		       CHRP_PCI_IO_PHYS,
+		       CHRP_PCI_IO_SIZE,
+		       PCI_REGION_IO);
+
+	/* ISA/PCI I/O space */
+	pci_set_region(hose->regions + 4,
+		       CHRP_ISA_IO_BUS,
+		       CHRP_ISA_IO_PHYS,
+		       CHRP_ISA_IO_SIZE,
+		       PCI_REGION_IO);
+
+	hose->region_count = 5;
+
+	pci_setup_indirect(hose,
+			   CHRP_REG_ADDR,
+			   CHRP_REG_DATA);
+
+	pci_register_hose(hose);
+
+	hose->last_busno = pci_hose_scan(hose);
+}
+
+#endif
diff --git a/arch/powerpc/cpu/mpc824x/speed.c b/arch/powerpc/cpu/mpc824x/speed.c
new file mode 100644
index 0000000..fdcb972
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/speed.c
@@ -0,0 +1,118 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002
+ * Gregory E. Allen, gallen@arlut.utexas.edu
+ * Applied Research Laboratories, The University of Texas at Austin
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc824x.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* ------------------------------------------------------------------------- */
+/* NOTE: This describes the proper use of this file.
+ *
+ * CONFIG_SYS_CLK_FREQ should be defined as the input frequency on
+ * PCI_SYNC_IN .
+ *
+ * CONFIG_PLL_PCI_TO_MEM_MULTIPLIER is only required on MPC8240
+ * boards. It should be defined as the PCI to Memory Multiplier as
+ * documented in the MPC8240 Hardware Specs.
+ *
+ * Other mpc824x boards don't need CONFIG_PLL_PCI_TO_MEM_MULTIPLIER
+ * because they can determine it from the PCR.
+ *
+ * Gary Milliorn <gary.milliorn@motorola.com> (who should know since
+ * he designed the Sandpoint) told us that the PCR is not in all revs
+ * of the MPC8240 CPU, so it's not guaranteeable and we cannot do
+ * away with CONFIG_PLL_PCI_TO_MEM_MULTIPLIER altogether.
+ */
+/* ------------------------------------------------------------------------- */
+
+/* This gives the PCI to Memory multiplier times 10 */
+/* The index is the value of PLL_CFG[0:4] */
+/* This is documented in the MPC8240/5 Hardware Specs */
+
+short pll_pci_to_mem_multiplier[] = {
+#if defined(CONFIG_MPC8240)
+	30, 30, 10, 10, 20, 10,  0, 10,
+	10,  0, 20,  0, 20,  0, 20,  0,
+	30,  0, 15,  0, 20,  0, 20,  0,
+	25,  0, 10,  0, 15, 15,  0,  0,
+#elif defined(CONFIG_MPC8245)
+	30, 30, 10, 10, 20, 10, 10, 10,
+	10, 20, 20, 15, 20, 15, 20, 30,
+	30, 40, 15, 40, 20, 25, 20, 40,
+	25, 20, 10, 20, 15, 15, 15,  0,
+#else
+#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
+#endif
+};
+
+#define CU824_PLL_STATE_REG	0xFE80002F
+#define PCR			0x800000E2
+
+/* ------------------------------------------------------------------------- */
+
+/* compute the memory bus clock frequency */
+ulong get_bus_freq (ulong dummy)
+{
+	unsigned char pll_cfg;
+#if defined(CONFIG_MPC8240) && !defined(CONFIG_CU824)
+	return (CONFIG_SYS_CLK_FREQ) * (CONFIG_PLL_PCI_TO_MEM_MULTIPLIER);
+#elif defined(CONFIG_CU824)
+	pll_cfg = *(volatile unsigned char *) (CU824_PLL_STATE_REG);
+	pll_cfg &= 0x1f;
+#else
+	CONFIG_READ_BYTE(PCR, pll_cfg);
+	pll_cfg = (pll_cfg >> 3) & 0x1f;
+#endif
+	return ((CONFIG_SYS_CLK_FREQ) * pll_pci_to_mem_multiplier[pll_cfg] + 5) / 10;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+/* This gives the Memory to CPU Core multiplier times 10 */
+/* The index is the value of PLLRATIO in HID1 */
+/* This is documented in the MPC8240 Hardware Specs */
+/* This is not documented for MPC8245 ? FIXME */
+short pllratio_to_factor[] = {
+     0,  0,  0, 10, 20, 20, 25, 45,
+    30,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0, 10,  0,  0,  0, 45,
+    30,  0, 40,  0,  0,  0, 35,  0,
+};
+
+/* compute the CPU and memory bus clock frequencies */
+int get_clocks (void)
+{
+	uint hid1 = mfspr(HID1);
+	hid1 = (hid1 >> (32-5)) & 0x1f;
+	gd->cpu_clk = (pllratio_to_factor[hid1] * get_bus_freq(0) + 5)
+			  / 10;
+	gd->bus_clk = get_bus_freq(0);
+	return (0);
+}
diff --git a/arch/powerpc/cpu/mpc824x/start.S b/arch/powerpc/cpu/mpc824x/start.S
new file mode 100644
index 0000000..f3f595a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/start.S
@@ -0,0 +1,766 @@
+/*
+ *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* U-Boot - Startup Code for PowerPC based Embedded Boards
+ *
+ *
+ * The processor starts at 0x00000100 and the code is executed
+ * from flash. The code is organized to be at an other address
+ * in memory, but as long we don't jump around before relocating.
+ * board_init lies at a quite high address and when the cpu has
+ * jumped there, everything is ok.
+ * This works because the cpu gives the FLASH (CS0) the whole
+ * address space at startup, and board_init lies as a echo of
+ * the flash somewhere up there in the memorymap.
+ *
+ * board_init will change CS0 to be positioned at the correct
+ * address and (s)dram will be positioned at address 0
+ */
+#include <config.h>
+#include <mpc824x.h>
+#include <timestamp.h>
+#include <version.h>
+
+#define _LINUX_CONFIG_H 1	/* avoid reading Linux autoconf.h file	*/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef CONFIG_IDENT_STRING
+#define CONFIG_IDENT_STRING ""
+#endif
+
+/* We don't want the MMU yet.
+*/
+#undef	MSR_KERNEL
+/* FP, Machine Check and Recoverable Interr. */
+#define MSR_KERNEL ( MSR_FP | MSR_ME | MSR_RI )
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+	START_GOT
+	GOT_ENTRY(_GOT2_TABLE_)
+	GOT_ENTRY(_FIXUP_TABLE_)
+
+	GOT_ENTRY(_start)
+	GOT_ENTRY(_start_of_vectors)
+	GOT_ENTRY(_end_of_vectors)
+	GOT_ENTRY(transfer_to_handler)
+
+	GOT_ENTRY(__init_end)
+	GOT_ENTRY(_end)
+	GOT_ENTRY(__bss_start)
+#if defined(CONFIG_FADS)
+	GOT_ENTRY(environment)
+#endif
+	END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+	.text
+	.long	0x27051956		/* U-Boot Magic Number			*/
+	.globl	version_string
+version_string:
+	.ascii U_BOOT_VERSION
+	.ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
+	.ascii CONFIG_IDENT_STRING, "\0"
+
+	. = EXC_OFF_SYS_RESET
+	.globl	_start
+_start:
+	li	r21, BOOTFLAG_COLD	/* Normal Power-On: Boot from FLASH	*/
+	b	boot_cold
+
+	. = EXC_OFF_SYS_RESET + 0x10
+
+	.globl	_start_warm
+_start_warm:
+	li	r21, BOOTFLAG_WARM	/* Software reboot			*/
+	b	boot_warm
+
+boot_cold:
+boot_warm:
+
+	/* Initialize machine status; enable machine check interrupt		*/
+	/*----------------------------------------------------------------------*/
+	li	r3, MSR_KERNEL		/* Set FP, ME, RI flags */
+	mtmsr	r3
+	mtspr	SRR1, r3		/* Make SRR1 match MSR */
+
+	addis	r0,0,0x0000		/* lets make sure that r0 is really 0 */
+	mtspr   HID0, r0		/* disable I and D caches */
+
+	mfspr	r3, ICR			/* clear Interrupt Cause Register */
+
+	mfmsr	r3			/* turn off address translation */
+	addis	r4,0,0xffff
+	ori	r4,r4,0xffcf
+	and	r3,r3,r4
+	mtmsr	r3
+	isync
+	sync				/* the MMU should be off... */
+
+
+in_flash:
+#if defined(CONFIG_BMW)
+	bl early_init_f /* Must be ASM: no stack yet! */
+#endif
+	/*
+	 * Setup BATs - cannot be done in C since we don't have a stack yet
+	 */
+	bl	setup_bats
+
+	/* Enable MMU.
+	 */
+	mfmsr	r3
+	ori	r3, r3, (MSR_IR | MSR_DR)
+	mtmsr	r3
+#if !defined(CONFIG_BMW)
+	/* Enable and invalidate data cache.
+	 */
+	mfspr	r3, HID0
+	mr	r2, r3
+	ori	r3, r3, HID0_DCE | HID0_DCI
+	ori	r2, r2, HID0_DCE
+	sync
+	mtspr	HID0, r3
+	mtspr	HID0, r2
+	sync
+
+	/* Allocate Initial RAM in data cache.
+	 */
+	lis	r3, CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l
+	li	r2, 128
+	mtctr	r2
+1:
+	dcbz	r0, r3
+	addi	r3, r3, 32
+	bdnz	1b
+
+	/* Lock way0 in data cache.
+	 */
+	mfspr	r3, 1011
+	lis	r2, 0xffff
+	ori	r2, r2, 0xff1f
+	and	r3, r3, r2
+	ori	r3, r3, 0x0080
+	sync
+	mtspr	1011, r3
+#endif /* !CONFIG_BMW */
+	/*
+	 * Thisk the stack pointer *somewhere* sensible. Doesnt
+	 * matter much where as we'll move it when we relocate
+	 */
+	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
+	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
+
+	li	r0, 0			/* Make room for stack frame header and	*/
+	stwu	r0, -4(r1)		/* clear final stack frame so that	*/
+	stwu	r0, -4(r1)		/* stack backtraces terminate cleanly	*/
+
+	/* let the C-code set up the rest					*/
+	/*									*/
+	/* Be careful to keep code relocatable !				*/
+	/*----------------------------------------------------------------------*/
+
+	GET_GOT			/* initialize GOT access			*/
+
+	/* r3: IMMR */
+	bl	cpu_init_f	/* run low-level CPU init code     (from Flash)	*/
+
+	mr	r3, r21
+	/* r3: BOOTFLAG */
+	bl	board_init_f	/* run 1st part of board init code (from Flash) */
+
+
+	.globl	_start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+	STD_EXCEPTION(EXC_OFF_MACH_CHCK, MachineCheck, MachineCheckException)
+
+/* Data Storage exception.  "Never" generated on the 860. */
+	STD_EXCEPTION(EXC_OFF_DATA_STOR, DataStorage, UnknownException)
+
+/* Instruction Storage exception.  "Never" generated on the 860. */
+	STD_EXCEPTION(EXC_OFF_INS_STOR, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+	STD_EXCEPTION(EXC_OFF_EXTERNAL, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+	. = EXC_OFF_ALIGN
+Alignment:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	mfspr	r4,DAR
+	stw	r4,_DAR(r21)
+	mfspr	r5,DSISR
+	stw	r5,_DSISR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+	. = EXC_OFF_PROGRAM
+ProgramCheck:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+		MSR_KERNEL, COPY_EE)
+
+	/* No FPU on MPC8xx. This exception is not supposed to happen.
+	*/
+	STD_EXCEPTION(EXC_OFF_FPUNAVAIL, FPUnavailable, UnknownException)
+
+	/* I guess we could implement decrementer, and may have
+	 * to someday for timekeeping.
+	 */
+	STD_EXCEPTION(EXC_OFF_DECR, Decrementer, timer_interrupt)
+	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+	STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+	STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+
+	STD_EXCEPTION(EXC_OFF_TRACE, SingleStep, UnknownException)
+
+	STD_EXCEPTION(EXC_OFF_FPUNASSIST, Trap_0e, UnknownException)
+	STD_EXCEPTION(EXC_OFF_PMI, Trap_0f, UnknownException)
+
+	STD_EXCEPTION(EXC_OFF_ITME, InstructionTransMiss, UnknownException)
+	STD_EXCEPTION(EXC_OFF_DLTME, DataLoadTransMiss, UnknownException)
+	STD_EXCEPTION(EXC_OFF_DSTME, DataStoreTransMiss, UnknownException)
+	STD_EXCEPTION(EXC_OFF_IABE, InstructionBreakpoint, DebugException)
+	STD_EXCEPTION(EXC_OFF_SMIE, SysManageInt, UnknownException)
+	STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+	STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+	STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+	STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+	STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+	STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+	STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+	STD_EXCEPTION(0x1c00, ReservedC, UnknownException)
+	STD_EXCEPTION(0x1d00, ReservedD, UnknownException)
+	STD_EXCEPTION(0x1e00, ReservedE, UnknownException)
+	STD_EXCEPTION(0x1f00, ReservedF, UnknownException)
+
+	STD_EXCEPTION(EXC_OFF_RMTE, RunModeTrace, UnknownException)
+
+	.globl	_end_of_vectors
+_end_of_vectors:
+
+
+	. = 0x3000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+	.globl	transfer_to_handler
+transfer_to_handler:
+	stw	r22,_NIP(r21)
+	lis	r22,MSR_POW@h
+	andc	r23,r23,r22
+	stw	r23,_MSR(r21)
+	SAVE_GPR(7, r21)
+	SAVE_4GPRS(8, r21)
+	SAVE_8GPRS(12, r21)
+	SAVE_8GPRS(24, r21)
+#if 0
+	andi.	r23,r23,MSR_PR
+	mfspr	r23,SPRG3		/* if from user, fix up tss.regs */
+	beq	2f
+	addi	r24,r1,STACK_FRAME_OVERHEAD
+	stw	r24,PT_REGS(r23)
+2:	addi	r2,r23,-TSS		/* set r2 to current */
+	tovirt(r2,r2,r23)
+#endif
+	mflr	r23
+	andi.	r24,r23,0x3f00		/* get vector offset */
+	stw	r24,TRAP(r21)
+	li	r22,0
+	stw	r22,RESULT(r21)
+	mtspr	SPRG2,r22		/* r1 is now kernel sp */
+#if 0
+	addi	r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */
+	cmplw	0,r1,r2
+	cmplw	1,r1,r24
+	crand	1,1,4
+	bgt	stack_ovf		/* if r2 < r1 < r2+TASK_STRUCT_SIZE */
+#endif
+	lwz	r24,0(r23)		/* virtual address of handler */
+	lwz	r23,4(r23)		/* where to go when done */
+	mtspr	SRR0,r24
+	ori	r20,r20,0x30		/* enable IR, DR */
+	mtspr	SRR1,r20
+	mtlr	r23
+	SYNC
+	rfi				/* jump to handler, enable MMU */
+
+int_return:
+	mfmsr	r28		/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC			/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SRR0,r2
+	mtspr	SRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfi
+
+/* Cache functions.
+*/
+	.globl	icache_enable
+icache_enable:
+	mfspr	r5,HID0		/* turn on the I cache. */
+	ori	r5,r5,0x8800	/* Instruction cache only! */
+	addis	r6,0,0xFFFF
+	ori	r6,r6,0xF7FF
+	and	r6,r5,r6	/* clear the invalidate bit */
+	sync
+	mtspr	HID0,r5
+	mtspr	HID0,r6
+	isync
+	sync
+	blr
+
+	.globl	icache_disable
+icache_disable:
+	mfspr	r5,HID0
+	addis	r6,0,0xFFFF
+	ori	r6,r6,0x7FFF
+	and	r5,r5,r6
+	sync
+	mtspr	HID0,r5
+	isync
+	sync
+	blr
+
+	.globl	icache_status
+icache_status:
+	mfspr	r3, HID0
+	srwi	r3, r3, 15	/* >>15 & 1=> select bit 16 */
+	andi.	r3, r3, 1
+	blr
+
+	.globl	dcache_enable
+dcache_enable:
+	mfspr	r5,HID0		/* turn on the D cache. */
+	ori	r5,r5,0x4400	/* Data cache only! */
+	mfspr	r4, PVR		/* read PVR */
+	srawi	r3, r4, 16	/* shift off the least 16 bits */
+	cmpi	0, 0, r3, 0xC	/* Check for Max pvr */
+	bne	NotMax
+	ori	r5,r5,0x0040	/* setting the DCFA bit, for Max rev 1 errata */
+NotMax:
+	addis	r6,0,0xFFFF
+	ori	r6,r6,0xFBFF
+	and	r6,r5,r6	/* clear the invalidate bit */
+	sync
+	mtspr	HID0,r5
+	mtspr	HID0,r6
+	isync
+	sync
+	blr
+
+	.globl	dcache_disable
+dcache_disable:
+	mfspr	r5,HID0
+	addis	r6,0,0xFFFF
+	ori	r6,r6,0xBFFF
+	and	r5,r5,r6
+	sync
+	mtspr	HID0,r5
+	isync
+	sync
+	blr
+
+	.globl	dcache_status
+dcache_status:
+	mfspr	r3, HID0
+	srwi	r3, r3, 14	/* >>14 & 1=> select bit 17 */
+	andi.	r3, r3, 1
+	blr
+
+	.globl	dc_read
+dc_read:
+/*TODO : who uses this, what should it do?
+*/
+	blr
+
+
+	.globl get_pvr
+get_pvr:
+	mfspr	r3, PVR
+	blr
+
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+	.globl	relocate_code
+relocate_code:
+
+	mr	r1,  r3		/* Set new stack pointer		*/
+	mr	r9,  r4		/* Save copy of Global Data pointer	*/
+	mr	r10, r5		/* Save copy of Destination Address	*/
+
+	GET_GOT
+	mr	r3,  r5				/* Destination Address	*/
+#ifdef CONFIG_SYS_RAMBOOT
+	lis	r4, CONFIG_SYS_SDRAM_BASE@h		/* Source      Address	*/
+	ori	r4, r4, CONFIG_SYS_SDRAM_BASE@l
+#else
+	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address	*/
+	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
+#endif
+	lwz	r5, GOT(__init_end)
+	sub	r5, r5, r4
+	li	r6, CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size	*/
+
+	/*
+	 * Fix GOT pointer:
+	 *
+	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+	 *
+	 * Offset:
+	 */
+	sub	r15, r10, r4
+
+	/* First our own GOT */
+	add	r12, r12, r15
+	/* the the one used by the C code */
+	add	r30, r30, r15
+
+	/*
+	 * Now relocate code
+	 */
+
+	cmplw	cr1,r3,r4
+	addi	r0,r5,3
+	srwi.	r0,r0,2
+	beq	cr1,4f		/* In place copy is not necessary	*/
+	beq	7f		/* Protect against 0 count		*/
+	mtctr	r0
+	bge	cr1,2f
+
+	la	r8,-4(r4)
+	la	r7,-4(r3)
+1:	lwzu	r0,4(r8)
+	stwu	r0,4(r7)
+	bdnz	1b
+	b	4f
+
+2:	slwi	r0,r0,2
+	add	r8,r4,r0
+	add	r7,r3,r0
+3:	lwzu	r0,-4(r8)
+	stwu	r0,-4(r7)
+	bdnz	3b
+
+4:
+#if !defined(CONFIG_BMW)
+/* Unlock the data cache and invalidate locked area */
+	xor	r0, r0, r0
+	mtspr	1011, r0
+	lis	r4, CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r4, r4, CONFIG_SYS_INIT_RAM_ADDR@l
+	li	r0, 128
+	mtctr	r0
+41:
+	dcbi	r0, r4
+	addi	r4, r4, 32
+	bdnz	41b
+#endif
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+	cmpwi	r6,0
+	add	r5,r3,r5
+	beq	7f		/* Always flush prefetch queue in any case */
+	subi	r0,r6,1
+	andc	r3,r3,r0
+	mr	r4,r3
+5:	dcbst	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	5b
+	sync			/* Wait for all dcbst to complete on bus */
+	mr	r4,r3
+6:	icbi	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	6b
+7:	sync			/* Wait for all icbi to complete on bus	*/
+	isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+	mtlr	r0
+	blr
+
+in_ram:
+
+	/*
+	 * Relocation Function, r12 point to got2+0x8000
+	 *
+	 * Adjust got2 pointers, no need to check for 0, this code
+	 * already puts a few entries in the table.
+	 */
+	li	r0,__got2_entries@sectoff@l
+	la	r3,GOT(_GOT2_TABLE_)
+	lwz	r11,GOT(_GOT2_TABLE_)
+	mtctr	r0
+	sub	r11,r3,r11
+	addi	r3,r3,-4
+1:	lwzu	r0,4(r3)
+	cmpwi	r0,0
+	beq-	2f
+	add	r0,r0,r11
+	stw	r0,0(r3)
+2:	bdnz	1b
+
+	/*
+	 * Now adjust the fixups and the pointers to the fixups
+	 * in case we need to move ourselves again.
+	 */
+	li	r0,__fixup_entries@sectoff@l
+	lwz	r3,GOT(_FIXUP_TABLE_)
+	cmpwi	r0,0
+	mtctr	r0
+	addi	r3,r3,-4
+	beq	4f
+3:	lwzu	r4,4(r3)
+	lwzux	r0,r4,r11
+	add	r0,r0,r11
+	stw	r10,0(r3)
+	stw	r0,0(r4)
+	bdnz	3b
+4:
+clear_bss:
+	/*
+	 * Now clear BSS segment
+	 */
+	lwz	r3,GOT(__bss_start)
+	lwz	r4,GOT(_end)
+
+	cmplw	0, r3, r4
+	beq	6f
+
+	li	r0, 0
+5:
+	stw	r0, 0(r3)
+	addi	r3, r3, 4
+	cmplw	0, r3, r4
+	blt	5b
+6:
+
+	mr	r3, r9		/* Global Data pointer		*/
+	mr	r4, r10		/* Destination Address		*/
+	bl	board_init_r
+
+	/*
+	 * Copy exception vector code to low memory
+	 *
+	 * r3: dest_addr
+	 * r7: source address, r8: end address, r9: target address
+	 */
+	.globl	trap_init
+trap_init:
+	mflr	r4			/* save link register		*/
+	GET_GOT
+	lwz	r7, GOT(_start)
+	lwz	r8, GOT(_end_of_vectors)
+
+	li	r9, 0x100		/* reset vector always at 0x100 */
+
+	cmplw	0, r7, r8
+	bgelr				/* return if r7>=r8 - just in case */
+1:
+	lwz	r0, 0(r7)
+	stw	r0, 0(r9)
+	addi	r7, r7, 4
+	addi	r9, r9, 4
+	cmplw	0, r7, r8
+	bne	1b
+
+	/*
+	 * relocate `hdlr' and `int_return' entries
+	 */
+	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+	li	r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	2b
+
+	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	3b
+
+	li	r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	4b
+
+	mtlr	r4			/* restore link register	*/
+	blr
+
+	/* Setup the BAT registers.
+	 */
+setup_bats:
+	lis	r4, CONFIG_SYS_IBAT0L@h
+	ori	r4, r4, CONFIG_SYS_IBAT0L@l
+	lis	r3, CONFIG_SYS_IBAT0U@h
+	ori	r3, r3, CONFIG_SYS_IBAT0U@l
+	mtspr	IBAT0L, r4
+	mtspr	IBAT0U, r3
+	isync
+
+	lis	r4, CONFIG_SYS_DBAT0L@h
+	ori	r4, r4, CONFIG_SYS_DBAT0L@l
+	lis	r3, CONFIG_SYS_DBAT0U@h
+	ori	r3, r3, CONFIG_SYS_DBAT0U@l
+	mtspr	DBAT0L, r4
+	mtspr	DBAT0U, r3
+	isync
+
+	lis	r4, CONFIG_SYS_IBAT1L@h
+	ori	r4, r4, CONFIG_SYS_IBAT1L@l
+	lis	r3, CONFIG_SYS_IBAT1U@h
+	ori	r3, r3, CONFIG_SYS_IBAT1U@l
+	mtspr	IBAT1L, r4
+	mtspr	IBAT1U, r3
+	isync
+
+	lis	r4, CONFIG_SYS_DBAT1L@h
+	ori	r4, r4, CONFIG_SYS_DBAT1L@l
+	lis	r3, CONFIG_SYS_DBAT1U@h
+	ori	r3, r3, CONFIG_SYS_DBAT1U@l
+	mtspr	DBAT1L, r4
+	mtspr	DBAT1U, r3
+	isync
+
+	lis	r4, CONFIG_SYS_IBAT2L@h
+	ori	r4, r4, CONFIG_SYS_IBAT2L@l
+	lis	r3, CONFIG_SYS_IBAT2U@h
+	ori	r3, r3, CONFIG_SYS_IBAT2U@l
+	mtspr	IBAT2L, r4
+	mtspr	IBAT2U, r3
+	isync
+
+	lis	r4, CONFIG_SYS_DBAT2L@h
+	ori	r4, r4, CONFIG_SYS_DBAT2L@l
+	lis	r3, CONFIG_SYS_DBAT2U@h
+	ori	r3, r3, CONFIG_SYS_DBAT2U@l
+	mtspr	DBAT2L, r4
+	mtspr	DBAT2U, r3
+	isync
+
+	lis	r4, CONFIG_SYS_IBAT3L@h
+	ori	r4, r4, CONFIG_SYS_IBAT3L@l
+	lis	r3, CONFIG_SYS_IBAT3U@h
+	ori	r3, r3, CONFIG_SYS_IBAT3U@l
+	mtspr	IBAT3L, r4
+	mtspr	IBAT3U, r3
+	isync
+
+	lis	r4, CONFIG_SYS_DBAT3L@h
+	ori	r4, r4, CONFIG_SYS_DBAT3L@l
+	lis	r3, CONFIG_SYS_DBAT3U@h
+	ori	r3, r3, CONFIG_SYS_DBAT3U@l
+	mtspr	DBAT3L, r4
+	mtspr	DBAT3U, r3
+	isync
+
+	/* Invalidate TLBs.
+	 * -> for (val = 0; val < 0x20000; val+=0x1000)
+	 * ->   tlbie(val);
+	 */
+	lis	r3, 0
+	lis	r5, 2
+
+1:
+	tlbie	r3
+	addi	r3, r3, 0x1000
+	cmp	0, 0, r3, r5
+	blt	1b
+
+	blr
diff --git a/arch/powerpc/cpu/mpc824x/traps.c b/arch/powerpc/cpu/mpc824x/traps.c
new file mode 100644
index 0000000..163b983
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/traps.c
@@ -0,0 +1,219 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM	0x00400000
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace(unsigned long *sp)
+{
+	int cnt = 0;
+	unsigned long i;
+
+	printf("Call backtrace: ");
+	while (sp) {
+		if ((uint)sp > END_OF_MEM)
+			break;
+
+		i = sp[1];
+		if (cnt++ % 7 == 0)
+			printf("\n");
+		printf("%08lX ", i);
+		if (cnt > 32) break;
+		sp = (unsigned long *)*sp;
+	}
+	printf("\n");
+}
+
+void show_regs(struct pt_regs * regs)
+{
+	int i;
+
+	printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+	       regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+	printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+	       regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+	       regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+	       regs->msr&MSR_IR ? 1 : 0,
+	       regs->msr&MSR_DR ? 1 : 0);
+
+	printf("\n");
+	for (i = 0;  i < 32;  i++) {
+		if ((i % 8) == 0)
+		{
+			printf("GPR%02d: ", i);
+		}
+
+		printf("%08lX ", regs->gpr[i]);
+		if ((i % 8) == 7)
+		{
+			printf("\n");
+		}
+	}
+}
+
+
+void
+_exception(int signr, struct pt_regs *regs)
+{
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+void
+MachineCheckException(struct pt_regs *regs)
+{
+	unsigned long fixup;
+
+	/* Probing PCI using config cycles cause this exception
+	 * when a device is not present.  Catch it and return to
+	 * the PCI exception handler.
+	 */
+	if ((fixup = search_exception_table(regs->nip)) != 0) {
+		regs->nip = fixup;
+		return;
+	}
+
+	printf("Machine check in kernel mode.\n");
+	printf("Caused by (from msr): ");
+	printf("regs %p ",regs);
+	switch( regs->msr & 0x000F0000) {
+	case (0x80000000>>12):
+		printf("Machine check signal - probably due to mm fault\n"
+			"with mmu off\n");
+		break;
+	case (0x80000000>>13):
+		printf("Transfer error ack signal\n");
+		break;
+	case (0x80000000>>14):
+		printf("Data parity signal\n");
+		break;
+	case (0x80000000>>15):
+		printf("Address parity signal\n");
+		break;
+	default:
+		printf("Unknown values in msr\n");
+	}
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Program Check Exception");
+}
+
+void
+SoftEmuException(struct pt_regs *regs)
+{
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Software Emulation Exception");
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+	printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+	       regs->nip, regs->msr, regs->trap);
+	_exception(0, regs);
+}
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+void
+DebugException(struct pt_regs *regs)
+{
+
+  printf("Debugger trap at @ %lx\n", regs->nip );
+  show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+  do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading.  If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+#if 0
+	int	retval;
+
+	__asm__ __volatile__(			\
+		"1:	lwz %0,0(%1)\n"		\
+		"	eieio\n"		\
+		"	li %0,0\n"		\
+		"2:\n"				\
+		".section .fixup,\"ax\"\n"	\
+		"3:	li %0,-1\n"		\
+		"	b 2b\n"			\
+		".section __ex_table,\"a\"\n"	\
+		"	.align 2\n"		\
+		"	.long 1b,3b\n"		\
+		".text"				\
+		: "=r" (retval) : "r"(addr));
+
+	return (retval);
+#endif
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc824x/u-boot.lds b/arch/powerpc/cpu/mpc824x/u-boot.lds
new file mode 100644
index 0000000..d1fcd7c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/u-boot.lds
@@ -0,0 +1,122 @@
+/*
+ * (C) Copyright 2001-2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text)	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data)	}
+  .rel.rodata    : { *(.rel.rodata)	}
+  .rela.rodata   : { *(.rela.rodata)	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	}
+  .plt : { *(.plt) }
+  .text      :
+  {
+    arch/powerpc/cpu/mpc824x/start.o		(.text)
+    *(.text)
+    *(.got1)
+    . = ALIGN(16);
+    *(.eh_frame)
+    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x0FFF) & 0xFFFFF000;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+  __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  . = .;
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+
+  . = .;
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(4096);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss (NOLOAD)       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+   . = ALIGN(4);
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc8260/Makefile b/arch/powerpc/cpu/mpc8260/Makefile
new file mode 100644
index 0000000..9f0c2dd
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/Makefile
@@ -0,0 +1,53 @@
+#
+# (C) Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(CPU).a
+
+START	= start.o kgdb.o
+COBJS	= traps.o serial_smc.o serial_scc.o cpu.o cpu_init.o speed.o \
+	  interrupts.o ether_fcc.o i2c.o commproc.o \
+	  bedbug_603e.o pci.o spi.o
+
+COBJS-$(CONFIG_ETHER_ON_SCC) = ether_scc.o
+
+COBJS	+= $(COBJS-y)
+
+SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS) $(obj)kgdb.o
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc8260/bedbug_603e.c b/arch/powerpc/cpu/mpc8260/bedbug_603e.c
new file mode 100644
index 0000000..c969ff6
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/bedbug_603e.c
@@ -0,0 +1,238 @@
+/*
+ * Bedbug Functions specific to the MPC603e core
+ */
+
+#include <common.h>
+#include <command.h>
+#include <linux/ctype.h>
+#include <bedbug/type.h>
+#include <bedbug/bedbug.h>
+#include <bedbug/regs.h>
+#include <bedbug/ppc.h>
+
+#if defined(CONFIG_CMD_BEDBUG) \
+	&& (defined(CONFIG_MPC824X) || defined(CONFIG_MPC8260))
+
+#define MAX_BREAK_POINTS 1
+
+extern CPU_DEBUG_CTX bug_ctx;
+
+void bedbug603e_init __P((void));
+void bedbug603e_do_break __P((cmd_tbl_t*,int,int,char*[]));
+void bedbug603e_break_isr __P((struct pt_regs*));
+int  bedbug603e_find_empty __P((void));
+int  bedbug603e_set __P((int,unsigned long));
+int  bedbug603e_clear __P((int));
+
+
+/* ======================================================================
+ * Initialize the global bug_ctx structure for the processor.  Clear all
+ * of the breakpoints.
+ * ====================================================================== */
+
+void bedbug603e_init( void )
+{
+  int	i;
+  /* -------------------------------------------------- */
+
+  bug_ctx.hw_debug_enabled = 0;
+  bug_ctx.stopped = 0;
+  bug_ctx.current_bp = 0;
+  bug_ctx.regs = NULL;
+
+  bug_ctx.do_break   = bedbug603e_do_break;
+  bug_ctx.break_isr  = bedbug603e_break_isr;
+  bug_ctx.find_empty = bedbug603e_find_empty;
+  bug_ctx.set        = bedbug603e_set;
+  bug_ctx.clear      = bedbug603e_clear;
+
+  for( i = 1; i <= MAX_BREAK_POINTS; ++i )
+    (*bug_ctx.clear)( i );
+
+  puts ("BEDBUG:ready\n");
+  return;
+} /* bedbug_init_breakpoints */
+
+
+
+/* ======================================================================
+ * Set/clear/show the hardware breakpoint for the 603e.  The "off"
+ * string will disable a specific breakpoint.  The "show" string will
+ * display the current breakpoints.  Otherwise an address will set a
+ * breakpoint at that address.  Setting a breakpoint uses the CPU-specific
+ * set routine which will assign a breakpoint number.
+ * ====================================================================== */
+
+void bedbug603e_do_break (cmd_tbl_t *cmdtp, int flag, int argc,
+			 char *argv[])
+{
+  long		addr;           /* Address to break at  */
+  int		which_bp;       /* Breakpoint number    */
+  /* -------------------------------------------------- */
+
+  if (argc < 2)
+  {
+    cmd_usage(cmdtp);
+    return;
+  }
+
+  /* Turn off a breakpoint */
+
+  if( strcmp( argv[ 1 ], "off" ) == 0 )
+  {
+    if( bug_ctx.hw_debug_enabled == 0 )
+    {
+      puts ( "No breakpoints enabled\n" );
+      return;
+    }
+
+    which_bp = simple_strtoul( argv[ 2 ], NULL, 10 );
+
+    if( bug_ctx.clear )
+      (*bug_ctx.clear)( which_bp );
+
+    printf( "Breakpoint %d removed\n", which_bp );
+    return;
+  }
+
+  /* Show a list of breakpoints */
+
+  if( strcmp( argv[ 1 ], "show" ) == 0 )
+  {
+    for( which_bp = 1; which_bp <= MAX_BREAK_POINTS; ++which_bp )
+    {
+
+      addr = GET_IABR();
+
+      printf( "Breakpoint [%d]: ", which_bp );
+      if( (addr & 0x00000002) == 0 )
+	puts ( "NOT SET\n" );
+      else
+	disppc( (unsigned char *)(addr & 0xFFFFFFFC), 0, 1, bedbug_puts, F_RADHEX );
+    }
+    return;
+  }
+
+  /* Set a breakpoint at the address */
+
+  if(!(( isdigit( argv[ 1 ][ 0 ] )) ||
+	(( argv[ 1 ][ 0 ] >= 'a' ) && ( argv[ 1 ][ 0 ] <= 'f' )) ||
+	(( argv[ 1 ][ 0 ] >= 'A' ) && ( argv[ 1 ][ 0 ] <= 'F' ))))
+  {
+    cmd_usage(cmdtp);
+    return;
+  }
+
+  addr = simple_strtoul( argv[ 1 ], NULL, 16 );
+
+  if(( bug_ctx.set ) && ( which_bp = (*bug_ctx.set)( 0, addr )) > 0 )
+  {
+    printf( "Breakpoint [%d]: ", which_bp );
+    disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
+  }
+
+  return;
+} /* bedbug603e_do_break */
+
+
+
+/* ======================================================================
+ * Handle a breakpoint.  Enter a mini main loop.  Stay in the loop until
+ * the stopped flag in the debug context is cleared.
+ * ====================================================================== */
+
+void bedbug603e_break_isr( struct pt_regs *regs )
+{
+  unsigned long	addr;           /* Address stopped at   */
+  /* -------------------------------------------------- */
+
+  bug_ctx.current_bp = 1;
+  addr = GET_IABR() & 0xFFFFFFFC;
+
+  bedbug_main_loop( addr, regs );
+  return;
+} /* bedbug603e_break_isr */
+
+
+
+/* ======================================================================
+ * See if the hardware breakpoint is available.
+ * ====================================================================== */
+
+int bedbug603e_find_empty( void )
+{
+  /* -------------------------------------------------- */
+
+  if( (GET_IABR() && 0x00000002) == 0 )
+    return 1;
+
+  return 0;
+} /* bedbug603e_find_empty */
+
+
+
+/* ======================================================================
+ * Set a breakpoint.  If 'which_bp' is zero then find an unused breakpoint
+ * number, otherwise reassign the given breakpoint.  If hardware debugging
+ * is not enabled, then turn it on via the MSR and DBCR0.  Set the break
+ * address in the IABR register.
+ * ====================================================================== */
+
+int bedbug603e_set( int which_bp, unsigned long addr )
+{
+  /* -------------------------------------------------- */
+
+  if(( addr & 0x00000003 ) != 0 )
+  {
+    puts ( "Breakpoints must be on a 32 bit boundary\n" );
+    return 0;
+  }
+
+  /* Only look if which_bp == 0, else use which_bp */
+  if(( bug_ctx.find_empty ) && ( !which_bp ) &&
+     ( which_bp = (*bug_ctx.find_empty)()) == 0 )
+  {
+    puts ( "All breakpoints in use\n" );
+    return 0;
+  }
+
+  if( which_bp < 1 || which_bp > MAX_BREAK_POINTS )
+  {
+    printf( "Invalid break point # %d\n", which_bp );
+    return 0;
+  }
+
+  if( ! bug_ctx.hw_debug_enabled )
+  {
+    bug_ctx.hw_debug_enabled = 1;
+  }
+
+  SET_IABR( addr | 0x00000002 );
+
+  return which_bp;
+} /* bedbug603e_set */
+
+
+
+/* ======================================================================
+ * Disable a specific breakoint by setting the IABR register to zero.
+ * ====================================================================== */
+
+int bedbug603e_clear( int which_bp )
+{
+  /* -------------------------------------------------- */
+
+  if( which_bp < 1 || which_bp > MAX_BREAK_POINTS )
+  {
+    printf( "Invalid break point # (%d)\n", which_bp );
+    return -1;
+  }
+
+  SET_IABR( 0 );
+
+  return 0;
+} /* bedbug603e_clear */
+
+
+/* ====================================================================== */
+#endif
diff --git a/arch/powerpc/cpu/mpc8260/commproc.c b/arch/powerpc/cpu/mpc8260/commproc.c
new file mode 100644
index 0000000..111a67c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/commproc.c
@@ -0,0 +1,221 @@
+/*
+ * This file is based on "arch/powerpc/8260_io/commproc.c" - here is it's
+ * copyright notice:
+ *
+ * General Purpose functions for the global management of the
+ * 8260 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
+ *	2.3.99 Updates
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space.  The allocator for that is here.  When the communication
+ * process is reset, we reclaim the memory available.  There is
+ * currently no deallocator for this memory.
+ */
+#include <common.h>
+#include <asm/cpm_8260.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void
+m8260_cpm_reset(void)
+{
+	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	volatile ulong count;
+
+	/* Reclaim the DP memory for our use.
+	*/
+	gd->dp_alloc_base = CPM_DATAONLY_BASE;
+	gd->dp_alloc_top = gd->dp_alloc_base + CPM_DATAONLY_SIZE;
+
+	/*
+	 * Reset CPM
+	 */
+	immr->im_cpm.cp_cpcr = CPM_CR_RST;
+	count = 0;
+	do {			/* Spin until command processed		*/
+		__asm__ __volatile__ ("eieio");
+	} while ((immr->im_cpm.cp_cpcr & CPM_CR_FLG) && ++count < 1000000);
+
+#ifdef CONFIG_HARD_I2C
+	*((unsigned short*)(&immr->im_dprambase[PROFF_I2C_BASE])) = 0;
+#endif
+}
+
+/* Allocate some memory from the dual ported ram.
+ * To help protocols with object alignment restrictions, we do that
+ * if they ask.
+ */
+uint
+m8260_cpm_dpalloc(uint size, uint align)
+{
+	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	uint	retloc;
+	uint	align_mask, off;
+	uint	savebase;
+
+	align_mask = align - 1;
+	savebase = gd->dp_alloc_base;
+
+	if ((off = (gd->dp_alloc_base & align_mask)) != 0)
+		gd->dp_alloc_base += (align - off);
+
+	if ((off = size & align_mask) != 0)
+		size += align - off;
+
+	if ((gd->dp_alloc_base + size) >= gd->dp_alloc_top) {
+		gd->dp_alloc_base = savebase;
+		panic("m8260_cpm_dpalloc: ran out of dual port ram!");
+	}
+
+	retloc = gd->dp_alloc_base;
+	gd->dp_alloc_base += size;
+
+	memset((void *)&immr->im_dprambase[retloc], 0, size);
+
+	return(retloc);
+}
+
+/* We also own one page of host buffer space for the allocation of
+ * UART "fifos" and the like.
+ */
+uint
+m8260_cpm_hostalloc(uint size, uint align)
+{
+	/* the host might not even have RAM yet - just use dual port RAM */
+	return (m8260_cpm_dpalloc(size, align));
+}
+
+/* Set a baud rate generator.  This needs lots of work.  There are
+ * eight BRGs, which can be connected to the CPM channels or output
+ * as clocks.  The BRGs are in two different block of internal
+ * memory mapped space.
+ * The baud rate clock is the system clock divided by something.
+ * It was set up long ago during the initial boot phase and is
+ * is given to us.
+ * Baud rate clocks are zero-based in the driver code (as that maps
+ * to port numbers).  Documentation uses 1-based numbering.
+ */
+#define BRG_INT_CLK	gd->brg_clk
+#define BRG_UART_CLK	(BRG_INT_CLK / 16)
+
+/* This function is used by UARTs, or anything else that uses a 16x
+ * oversampled clock.
+ */
+void
+m8260_cpm_setbrg(uint brg, uint rate)
+{
+	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	volatile uint	*bp;
+	uint cd = BRG_UART_CLK / rate;
+
+	if ((BRG_UART_CLK % rate) < (rate / 2))
+		cd--;
+	if (brg < 4) {
+		bp = (uint *)&immr->im_brgc1;
+	}
+	else {
+		bp = (uint *)&immr->im_brgc5;
+		brg -= 4;
+	}
+	bp += brg;
+	*bp = (cd << 1) | CPM_BRG_EN;
+}
+
+/* This function is used to set high speed synchronous baud rate
+ * clocks.
+ */
+void
+m8260_cpm_fastbrg(uint brg, uint rate, int div16)
+{
+	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	volatile uint	*bp;
+
+	/* This is good enough to get SMCs running.....
+	*/
+	if (brg < 4) {
+		bp = (uint *)&immr->im_brgc1;
+	}
+	else {
+		bp = (uint *)&immr->im_brgc5;
+		brg -= 4;
+	}
+	bp += brg;
+	*bp = (((((BRG_INT_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
+	if (div16)
+		*bp |= CPM_BRG_DIV16;
+}
+
+/* This function is used to set baud rate generators using an external
+ * clock source and 16x oversampling.
+ */
+
+void
+m8260_cpm_extcbrg(uint brg, uint rate, uint extclk, int pinsel)
+{
+	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	volatile uint	*bp;
+
+	if (brg < 4) {
+		bp = (uint *)&immr->im_brgc1;
+	}
+	else {
+		bp = (uint *)&immr->im_brgc5;
+		brg -= 4;
+	}
+	bp += brg;
+	*bp = ((((((extclk/16)+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
+	if (pinsel == 0)
+		*bp |= CPM_BRG_EXTC_CLK3_9;
+	else
+		*bp |= CPM_BRG_EXTC_CLK5_15;
+}
+
+#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER)
+
+void post_word_store (ulong a)
+{
+	volatile ulong *save_addr =
+		(volatile ulong *)(CONFIG_SYS_IMMR + CPM_POST_WORD_ADDR);
+
+	*save_addr = a;
+}
+
+ulong post_word_load (void)
+{
+	volatile ulong *save_addr =
+		(volatile ulong *)(CONFIG_SYS_IMMR + CPM_POST_WORD_ADDR);
+
+	return *save_addr;
+}
+
+#endif	/* CONFIG_POST || CONFIG_LOGBUFFER*/
+
+#ifdef CONFIG_BOOTCOUNT_LIMIT
+
+void bootcount_store (ulong a)
+{
+	volatile ulong *save_addr =
+		(volatile ulong *)(CONFIG_SYS_IMMR + CPM_BOOTCOUNT_ADDR);
+
+	save_addr[0] = a;
+	save_addr[1] = BOOTCOUNT_MAGIC;
+}
+
+ulong bootcount_load (void)
+{
+	volatile ulong *save_addr =
+		(volatile ulong *)(CONFIG_SYS_IMMR + CPM_BOOTCOUNT_ADDR);
+
+	if (save_addr[1] != BOOTCOUNT_MAGIC)
+		return 0;
+	else
+		return save_addr[0];
+}
+
+#endif /* CONFIG_BOOTCOUNT_LIMIT */
diff --git a/arch/powerpc/cpu/mpc8260/config.mk b/arch/powerpc/cpu/mpc8260/config.mk
new file mode 100644
index 0000000..a9bb688
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/config.mk
@@ -0,0 +1,30 @@
+#
+# (C) Copyright 2000
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -fPIC -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_8260 -DCONFIG_CPM2 -ffixed-r2 \
+		     -mstring -mcpu=603e -mmultiple
+
+# Use default linker script.  Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/arch/powerpc/cpu/mpc8260/u-boot.lds
diff --git a/arch/powerpc/cpu/mpc8260/cpu.c b/arch/powerpc/cpu/mpc8260/cpu.c
new file mode 100644
index 0000000..aedbf29
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/cpu.c
@@ -0,0 +1,338 @@
+/*
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * CPU specific code for the MPC825x / MPC826x / MPC827x / MPC828x
+ *
+ * written or collected and sometimes rewritten by
+ * Magnus Damm <damm@bitsmart.com>
+ *
+ * modified by
+ * Wolfgang Denk <wd@denx.de>
+ *
+ * modified for 8260 by
+ * Murray Jensen <Murray.Jensen@cmst.csiro.au>
+ *
+ * added 8260 masks by
+ * Marius Groeger <mag@sysgo.de>
+ *
+ * added HiP7 (824x/827x/8280) processors support by
+ * Yuli Barcohen <yuli@arabellasw.com>
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc8260.h>
+#include <netdev.h>
+#include <asm/processor.h>
+#include <asm/cpm_8260.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <libfdt_env.h>
+#include <fdt_support.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_GET_CPU_STR_F)
+extern int get_cpu_str_f (char *buf);
+#endif
+
+int checkcpu (void)
+{
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	ulong clock = gd->cpu_clk;
+	uint pvr = get_pvr ();
+	uint immr, rev, m, k;
+	char buf[32];
+
+	puts ("CPU:   ");
+
+	switch (pvr) {
+	case PVR_8260:
+	case PVR_8260_HIP3:
+		k = 3;
+		break;
+	case PVR_8260_HIP4:
+		k = 4;
+		break;
+	case PVR_8260_HIP7R1:
+	case PVR_8260_HIP7RA:
+	case PVR_8260_HIP7:
+		k = 7;
+		break;
+	default:
+		return -1;	/* whoops! not an MPC8260 */
+	}
+	rev = pvr & 0xff;
+
+	immr = immap->im_memctl.memc_immr;
+	if ((immr & IMMR_ISB_MSK) != CONFIG_SYS_IMMR)
+		return -1;	/* whoops! someone moved the IMMR */
+
+#if defined(CONFIG_GET_CPU_STR_F)
+	get_cpu_str_f (buf);
+	printf ("%s (HiP%d Rev %02x, Mask ", buf, k, rev);
+#else
+	printf (CPU_ID_STR " (HiP%d Rev %02x, Mask ", k, rev);
+#endif
+
+	/*
+	 * the bottom 16 bits of the immr are the Part Number and Mask Number
+	 * (4-34); the 16 bits at PROFF_REVNUM (0x8af0) in dual port ram is the
+	 * RISC Microcode Revision Number (13-10).
+	 * For the 8260, Motorola doesn't include the Microcode Revision
+	 * in the mask.
+	 */
+	m = immr & (IMMR_PARTNUM_MSK | IMMR_MASKNUM_MSK);
+	k = *((ushort *) & immap->im_dprambase[PROFF_REVNUM]);
+
+	switch (m) {
+	case 0x0000:
+		puts ("0.2 2J24M");
+		break;
+	case 0x0010:
+		puts ("A.0 K22A");
+		break;
+	case 0x0011:
+		puts ("A.1 1K22A-XC");
+		break;
+	case 0x0001:
+		puts ("B.1 1K23A");
+		break;
+	case 0x0021:
+		puts ("B.2 2K23A-XC");
+		break;
+	case 0x0023:
+		puts ("B.3 3K23A");
+		break;
+	case 0x0024:
+		puts ("C.2 6K23A");
+		break;
+	case 0x0060:
+		puts ("A.0(A) 2K25A");
+		break;
+	case 0x0062:
+		puts ("B.1 4K25A");
+		break;
+	case 0x0064:
+		puts ("C.0 5K25A");
+		break;
+	case 0x0A00:
+		puts ("0.0 0K49M");
+		break;
+	case 0x0A01:
+		puts ("0.1 1K49M");
+		break;
+	case 0x0A10:
+		puts ("1.0 1K49M");
+		break;
+	case 0x0C00:
+		puts ("0.0 0K50M");
+		break;
+	case 0x0C10:
+		puts ("1.0 1K50M");
+		break;
+	case 0x0D00:
+		puts ("0.0 0K50M");
+		break;
+	case 0x0D10:
+		puts ("1.0 1K50M");
+		break;
+	default:
+		printf ("unknown [immr=0x%04x,k=0x%04x]", m, k);
+		break;
+	}
+
+	printf (") at %s MHz\n", strmhz (buf, clock));
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+/* configures a UPM by writing into the UPM RAM array			     */
+/* uses bank 11 and a dummy physical address (=BRx_BA_MSK)		     */
+/* NOTE: the physical address chosen must not overlap into any other area    */
+/* mapped by the memory controller because bank 11 has the lowest priority   */
+
+void upmconfig (uint upm, uint * table, uint size)
+{
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	volatile memctl8260_t *memctl = &immap->im_memctl;
+	volatile uchar *dummy = (uchar *) BRx_BA_MSK;	/* set all BA bits */
+	uint i;
+
+	/* first set up bank 11 to reference the correct UPM at a dummy address */
+
+	memctl->memc_or11 = ORxU_AM_MSK;	/* set all AM bits */
+
+	switch (upm) {
+
+	case UPMA:
+		memctl->memc_br11 =
+			((uint)dummy & BRx_BA_MSK) | BRx_PS_32 | BRx_MS_UPMA |
+			BRx_V;
+		memctl->memc_mamr = MxMR_OP_WARR;
+		break;
+
+	case UPMB:
+		memctl->memc_br11 =
+			((uint)dummy & BRx_BA_MSK) | BRx_PS_32 | BRx_MS_UPMB |
+			BRx_V;
+		memctl->memc_mbmr = MxMR_OP_WARR;
+		break;
+
+	case UPMC:
+		memctl->memc_br11 =
+			((uint)dummy & BRx_BA_MSK) | BRx_PS_32 | BRx_MS_UPMC |
+			BRx_V;
+		memctl->memc_mcmr = MxMR_OP_WARR;
+		break;
+
+	default:
+		panic ("upmconfig passed invalid UPM number (%u)\n", upm);
+		break;
+
+	}
+
+	/*
+	 * at this point, the dummy address is set up to access the selected UPM,
+	 * the MAD pointer is zero, and the MxMR OP is set for writing to RAM
+	 *
+	 * now we simply load the mdr with each word and poke the dummy address.
+	 * the MAD is incremented on each access.
+	 */
+
+	for (i = 0; i < size; i++) {
+		memctl->memc_mdr = table[i];
+		*dummy = 0;
+	}
+
+	/* now kill bank 11 */
+	memctl->memc_br11 = 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if !defined(CONFIG_HAVE_OWN_RESET)
+int
+do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	ulong msr, addr;
+
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+
+	immap->im_clkrst.car_rmr = RMR_CSRE;	/* Checkstop Reset enable */
+
+	/* Interrupts and MMU off */
+	__asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
+
+	msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
+	__asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
+
+	/*
+	 * Trying to execute the next instruction at a non-existing address
+	 * should cause a machine check, resulting in reset
+	 */
+#ifdef CONFIG_SYS_RESET_ADDRESS
+	addr = CONFIG_SYS_RESET_ADDRESS;
+#else
+	/*
+	 * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address, CONFIG_SYS_MONITOR_BASE
+	 * - sizeof (ulong) is usually a valid address. Better pick an address
+	 * known to be invalid on your system and assign it to CONFIG_SYS_RESET_ADDRESS.
+	 */
+	addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong);
+#endif
+	((void (*)(void)) addr) ();
+	return 1;
+
+}
+#endif	/* CONFIG_HAVE_OWN_RESET */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ *
+ */
+unsigned long get_tbclk (void)
+{
+	ulong tbclk;
+
+	tbclk = (gd->bus_clk + 3L) / 4L;
+
+	return (tbclk);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset (void)
+{
+	int re_enable = disable_interrupts ();
+
+	reset_8260_watchdog ((immap_t *) CONFIG_SYS_IMMR);
+	if (re_enable)
+		enable_interrupts ();
+}
+#endif /* CONFIG_WATCHDOG */
+
+/* ------------------------------------------------------------------------- */
+#if defined(CONFIG_OF_LIBFDT) && defined (CONFIG_OF_BOARD_SETUP)
+void ft_cpu_setup (void *blob, bd_t *bd)
+{
+#if defined(CONFIG_HAS_ETH0) || defined(CONFIG_HAS_ETH1) ||\
+    defined(CONFIG_HAS_ETH2) || defined(CONFIG_HAS_ETH3)
+	fdt_fixup_ethernet(blob);
+#endif
+
+	do_fixup_by_compat_u32(blob, "fsl,cpm2-brg",
+			       "clock-frequency", bd->bi_brgfreq, 1);
+
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+		"bus-frequency", bd->bi_busfreq, 1);
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+		"timebase-frequency", OF_TBCLK, 1);
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+		"clock-frequency", bd->bi_intfreq, 1);
+	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+}
+#endif /* CONFIG_OF_LIBFDT */
+
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_ETHER_ON_FCC)
+	fec_initialize(bis);
+#endif
+#if defined(CONFIG_ETHER_ON_SCC)
+	mpc82xx_scc_enet_initialize(bis);
+#endif
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8260/cpu_init.c b/arch/powerpc/cpu/mpc8260/cpu_init.c
new file mode 100644
index 0000000..1d52773
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/cpu_init.c
@@ -0,0 +1,292 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8260.h>
+#include <asm/cpm_8260.h>
+#include <ioports.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_BOARD_GET_CPU_CLK_F)
+extern unsigned long board_get_cpu_clk_f (void);
+#endif
+
+static void config_8260_ioports (volatile immap_t * immr)
+{
+	int portnum;
+
+	for (portnum = 0; portnum < 4; portnum++) {
+		uint pmsk = 0,
+		     ppar = 0,
+		     psor = 0,
+		     pdir = 0,
+		     podr = 0,
+		     pdat = 0;
+		iop_conf_t *iopc = (iop_conf_t *) & iop_conf_tab[portnum][0];
+		iop_conf_t *eiopc = iopc + 32;
+		uint msk = 1;
+
+		/*
+		 * NOTE:
+		 * index 0 refers to pin 31,
+		 * index 31 refers to pin 0
+		 */
+		while (iopc < eiopc) {
+			if (iopc->conf) {
+				pmsk |= msk;
+				if (iopc->ppar)
+					ppar |= msk;
+				if (iopc->psor)
+					psor |= msk;
+				if (iopc->pdir)
+					pdir |= msk;
+				if (iopc->podr)
+					podr |= msk;
+				if (iopc->pdat)
+					pdat |= msk;
+			}
+
+			msk <<= 1;
+			iopc++;
+		}
+
+		if (pmsk != 0) {
+			volatile ioport_t *iop = ioport_addr (immr, portnum);
+			uint tpmsk = ~pmsk;
+
+			/*
+			 * the (somewhat confused) paragraph at the
+			 * bottom of page 35-5 warns that there might
+			 * be "unknown behaviour" when programming
+			 * PSORx and PDIRx, if PPARx = 1, so I
+			 * decided this meant I had to disable the
+			 * dedicated function first, and enable it
+			 * last.
+			 */
+			iop->ppar &= tpmsk;
+			iop->psor = (iop->psor & tpmsk) | psor;
+			iop->podr = (iop->podr & tpmsk) | podr;
+			iop->pdat = (iop->pdat & tpmsk) | pdat;
+			iop->pdir = (iop->pdir & tpmsk) | pdir;
+			iop->ppar |= ppar;
+		}
+	}
+}
+
+#define SET_VAL_MASK(a, b, mask) ((a & mask) | (b & ~mask))
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ * initialize the UPM's
+ */
+void cpu_init_f (volatile immap_t * immr)
+{
+#if !defined(CONFIG_COGENT)		/* done in start.S for the cogent */
+	uint sccr;
+#endif
+#if defined(CONFIG_BOARD_GET_CPU_CLK_F)
+	unsigned long cpu_clk;
+#endif
+	volatile memctl8260_t *memctl = &immr->im_memctl;
+	extern void m8260_cpm_reset (void);
+
+	/* Pointer is writable since we allocated a register for it */
+	gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+	/* Clear initial global data */
+	memset ((void *) gd, 0, sizeof (gd_t));
+
+	/* RSR - Reset Status Register - clear all status (5-4) */
+	gd->reset_status = immr->im_clkrst.car_rsr;
+	immr->im_clkrst.car_rsr = RSR_ALLBITS;
+
+	/* RMR - Reset Mode Register - contains checkstop reset enable (5-5) */
+	immr->im_clkrst.car_rmr = CONFIG_SYS_RMR;
+
+	/* BCR - Bus Configuration Register (4-25) */
+#if defined(CONFIG_SYS_BCR_60x) && (CONFIG_SYS_BCR_SINGLE)
+	if (immr->im_siu_conf.sc_bcr & BCR_EBM) {
+		immr->im_siu_conf.sc_bcr = SET_VAL_MASK(immr->im_siu_conf.sc_bcr, CONFIG_SYS_BCR_60x, 0x80000010);
+	} else {
+		immr->im_siu_conf.sc_bcr = SET_VAL_MASK(immr->im_siu_conf.sc_bcr, CONFIG_SYS_BCR_SINGLE, 0x80000010);
+	}
+#else
+	immr->im_siu_conf.sc_bcr = CONFIG_SYS_BCR;
+#endif
+
+	/* SIUMCR - contains debug pin configuration (4-31) */
+#if defined(CONFIG_SYS_SIUMCR_LOW) && (CONFIG_SYS_SIUMCR_HIGH)
+	cpu_clk = board_get_cpu_clk_f ();
+	if (cpu_clk >= 100000000) {
+		immr->im_siu_conf.sc_siumcr = SET_VAL_MASK(immr->im_siu_conf.sc_siumcr, CONFIG_SYS_SIUMCR_HIGH, 0x9f3cc000);
+	} else {
+		immr->im_siu_conf.sc_siumcr = SET_VAL_MASK(immr->im_siu_conf.sc_siumcr, CONFIG_SYS_SIUMCR_LOW, 0x9f3cc000);
+	}
+#else
+	immr->im_siu_conf.sc_siumcr = CONFIG_SYS_SIUMCR;
+#endif
+
+	config_8260_ioports (immr);
+
+	/* initialize time counter status and control register (4-40) */
+	immr->im_sit.sit_tmcntsc = CONFIG_SYS_TMCNTSC;
+
+	/* initialize the PIT (4-42) */
+	immr->im_sit.sit_piscr = CONFIG_SYS_PISCR;
+
+#if !defined(CONFIG_COGENT)		/* done in start.S for the cogent */
+	/* System clock control register (9-8) */
+	sccr = immr->im_clkrst.car_sccr &
+		(SCCR_PCI_MODE | SCCR_PCI_MODCK | SCCR_PCIDF_MSK);
+	immr->im_clkrst.car_sccr = sccr |
+		(CONFIG_SYS_SCCR & ~(SCCR_PCI_MODE | SCCR_PCI_MODCK | SCCR_PCIDF_MSK) );
+#endif /* !CONFIG_COGENT */
+
+	/*
+	 * Memory Controller:
+	 */
+
+	/* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary
+	 * addresses - these have to be modified later when FLASH size
+	 * has been determined
+	 */
+
+#if defined(CONFIG_SYS_OR0_REMAP)
+	memctl->memc_or0 = CONFIG_SYS_OR0_REMAP;
+#endif
+#if defined(CONFIG_SYS_OR1_REMAP)
+	memctl->memc_or1 = CONFIG_SYS_OR1_REMAP;
+#endif
+
+	/* now restrict to preliminary range */
+	/* the PS came from the HRCW, don´t change it */
+	memctl->memc_br0 = SET_VAL_MASK(memctl->memc_br0 , CONFIG_SYS_BR0_PRELIM, BRx_PS_MSK);
+	memctl->memc_or0 = CONFIG_SYS_OR0_PRELIM;
+
+#if defined(CONFIG_SYS_BR1_PRELIM) && defined(CONFIG_SYS_OR1_PRELIM)
+	memctl->memc_or1 = CONFIG_SYS_OR1_PRELIM;
+	memctl->memc_br1 = CONFIG_SYS_BR1_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR2_PRELIM) && defined(CONFIG_SYS_OR2_PRELIM)
+	memctl->memc_or2 = CONFIG_SYS_OR2_PRELIM;
+	memctl->memc_br2 = CONFIG_SYS_BR2_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR3_PRELIM) && defined(CONFIG_SYS_OR3_PRELIM)
+	memctl->memc_or3 = CONFIG_SYS_OR3_PRELIM;
+	memctl->memc_br3 = CONFIG_SYS_BR3_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR4_PRELIM) && defined(CONFIG_SYS_OR4_PRELIM)
+	memctl->memc_or4 = CONFIG_SYS_OR4_PRELIM;
+	memctl->memc_br4 = CONFIG_SYS_BR4_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR5_PRELIM) && defined(CONFIG_SYS_OR5_PRELIM)
+	memctl->memc_or5 = CONFIG_SYS_OR5_PRELIM;
+	memctl->memc_br5 = CONFIG_SYS_BR5_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR6_PRELIM) && defined(CONFIG_SYS_OR6_PRELIM)
+	memctl->memc_or6 = CONFIG_SYS_OR6_PRELIM;
+	memctl->memc_br6 = CONFIG_SYS_BR6_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR7_PRELIM) && defined(CONFIG_SYS_OR7_PRELIM)
+	memctl->memc_or7 = CONFIG_SYS_OR7_PRELIM;
+	memctl->memc_br7 = CONFIG_SYS_BR7_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR8_PRELIM) && defined(CONFIG_SYS_OR8_PRELIM)
+	memctl->memc_or8 = CONFIG_SYS_OR8_PRELIM;
+	memctl->memc_br8 = CONFIG_SYS_BR8_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR9_PRELIM) && defined(CONFIG_SYS_OR9_PRELIM)
+	memctl->memc_or9 = CONFIG_SYS_OR9_PRELIM;
+	memctl->memc_br9 = CONFIG_SYS_BR9_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR10_PRELIM) && defined(CONFIG_SYS_OR10_PRELIM)
+	memctl->memc_or10 = CONFIG_SYS_OR10_PRELIM;
+	memctl->memc_br10 = CONFIG_SYS_BR10_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR11_PRELIM) && defined(CONFIG_SYS_OR11_PRELIM)
+	memctl->memc_or11 = CONFIG_SYS_OR11_PRELIM;
+	memctl->memc_br11 = CONFIG_SYS_BR11_PRELIM;
+#endif
+
+	m8260_cpm_reset ();
+}
+
+/*
+ * initialize higher level parts of CPU like time base and timers
+ */
+int cpu_init_r (void)
+{
+	volatile immap_t *immr = (immap_t *) gd->bd->bi_immr_base;
+
+	immr->im_cpm.cp_rccr = CONFIG_SYS_RCCR;
+
+	return (0);
+}
+
+/*
+ * print out the reason for the reset
+ */
+int prt_8260_rsr (void)
+{
+	static struct {
+		ulong mask;
+		char *desc;
+	} bits[] = {
+		{
+		RSR_JTRS, "JTAG"}, {
+		RSR_CSRS, "Check Stop"}, {
+		RSR_SWRS, "Software Watchdog"}, {
+		RSR_BMRS, "Bus Monitor"}, {
+		RSR_ESRS, "External Soft"}, {
+		RSR_EHRS, "External Hard"}
+	};
+	static int n = sizeof bits / sizeof bits[0];
+	ulong rsr = gd->reset_status;
+	int i;
+	char *sep;
+
+	puts (CPU_ID_STR " Reset Status:");
+
+	sep = " ";
+	for (i = 0; i < n; i++)
+		if (rsr & bits[i].mask) {
+			printf ("%s%s", sep, bits[i].desc);
+			sep = ", ";
+		}
+
+	puts ("\n\n");
+	return (0);
+}
diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c b/arch/powerpc/cpu/mpc8260/ether_fcc.c
new file mode 100644
index 0000000..5ac02a0
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
@@ -0,0 +1,1190 @@
+/*
+ * MPC8260 FCC Fast Ethernet
+ *
+ * Copyright (c) 2000 MontaVista Software, Inc.   Dan Malek (dmalek@jlc.net)
+ *
+ * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * MPC8260 FCC Fast Ethernet
+ * Basic ET HW initialization and packet RX/TX routines
+ *
+ * This code will not perform the IO port configuration. This should be
+ * done in the iop_conf_t structure specific for the board.
+ *
+ * TODO:
+ * add a PHY driver to do the negotiation
+ * reflect negotiation results in FPSMR
+ * look for ways to configure the board specific stuff elsewhere, eg.
+ *    config_xxx.h or the board directory
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/cpm_8260.h>
+#include <mpc8260.h>
+#include <command.h>
+#include <config.h>
+#include <net.h>
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+#include <miiphy.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_ETHER_ON_FCC) && defined(CONFIG_CMD_NET) && \
+	defined(CONFIG_NET_MULTI)
+
+static struct ether_fcc_info_s
+{
+	int ether_index;
+	int proff_enet;
+	ulong cpm_cr_enet_sblock;
+	ulong cpm_cr_enet_page;
+	ulong cmxfcr_mask;
+	ulong cmxfcr_value;
+}
+	ether_fcc_info[] =
+{
+#ifdef CONFIG_ETHER_ON_FCC1
+{
+	0,
+	PROFF_FCC1,
+	CPM_CR_FCC1_SBLOCK,
+	CPM_CR_FCC1_PAGE,
+	CONFIG_SYS_CMXFCR_MASK1,
+	CONFIG_SYS_CMXFCR_VALUE1
+},
+#endif
+
+#ifdef CONFIG_ETHER_ON_FCC2
+{
+	1,
+	PROFF_FCC2,
+	CPM_CR_FCC2_SBLOCK,
+	CPM_CR_FCC2_PAGE,
+	CONFIG_SYS_CMXFCR_MASK2,
+	CONFIG_SYS_CMXFCR_VALUE2
+},
+#endif
+
+#ifdef CONFIG_ETHER_ON_FCC3
+{
+	2,
+	PROFF_FCC3,
+	CPM_CR_FCC3_SBLOCK,
+	CPM_CR_FCC3_PAGE,
+	CONFIG_SYS_CMXFCR_MASK3,
+	CONFIG_SYS_CMXFCR_VALUE3
+},
+#endif
+};
+
+/*---------------------------------------------------------------------*/
+
+/* Maximum input DMA size.  Must be a should(?) be a multiple of 4. */
+#define PKT_MAXDMA_SIZE         1520
+
+/* The FCC stores dest/src/type, data, and checksum for receive packets. */
+#define PKT_MAXBUF_SIZE         1518
+#define PKT_MINBUF_SIZE         64
+
+/* Maximum input buffer size.  Must be a multiple of 32. */
+#define PKT_MAXBLR_SIZE         1536
+
+#define TOUT_LOOP 1000000
+
+#define TX_BUF_CNT 2
+#ifdef __GNUC__
+static char txbuf[TX_BUF_CNT][PKT_MAXBLR_SIZE] __attribute__ ((aligned(8)));
+#else
+#error "txbuf must be 64-bit aligned"
+#endif
+
+static uint rxIdx;	/* index of the current RX buffer */
+static uint txIdx;	/* index of the current TX buffer */
+
+/*
+ * FCC Ethernet Tx and Rx buffer descriptors.
+ * Provide for Double Buffering
+ * Note: PKTBUFSRX is defined in net.h
+ */
+
+typedef volatile struct rtxbd {
+    cbd_t rxbd[PKTBUFSRX];
+    cbd_t txbd[TX_BUF_CNT];
+} RTXBD;
+
+/*  Good news: the FCC supports external BDs! */
+#ifdef __GNUC__
+static RTXBD rtx __attribute__ ((aligned(8)));
+#else
+#error "rtx must be 64-bit aligned"
+#endif
+
+static int fec_send(struct eth_device* dev, volatile void *packet, int length)
+{
+    int i;
+    int result = 0;
+
+    if (length <= 0) {
+	printf("fec: bad packet size: %d\n", length);
+	goto out;
+    }
+
+    for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+	if (i >= TOUT_LOOP) {
+	    puts ("fec: tx buffer not ready\n");
+	    goto out;
+	}
+    }
+
+    rtx.txbd[txIdx].cbd_bufaddr = (uint)packet;
+    rtx.txbd[txIdx].cbd_datlen = length;
+    rtx.txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST |
+			       BD_ENET_TX_WRAP);
+
+    for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+	if (i >= TOUT_LOOP) {
+	    puts ("fec: tx error\n");
+	    goto out;
+	}
+    }
+
+#ifdef ET_DEBUG
+    printf("cycles: %d status: %04x\n", i, rtx.txbd[txIdx].cbd_sc);
+#endif
+
+    /* return only status bits */
+    result = rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_STATS;
+
+out:
+    return result;
+}
+
+static int fec_recv(struct eth_device* dev)
+{
+    int length;
+
+    for (;;)
+    {
+	if (rtx.rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+	    length = -1;
+	    break;     /* nothing received - leave for() loop */
+	}
+	length = rtx.rxbd[rxIdx].cbd_datlen;
+
+	if (rtx.rxbd[rxIdx].cbd_sc & 0x003f) {
+	    printf("fec: rx error %04x\n", rtx.rxbd[rxIdx].cbd_sc);
+	}
+	else {
+	    /* Pass the packet up to the protocol layers. */
+	    NetReceive(NetRxPackets[rxIdx], length - 4);
+	}
+
+
+	/* Give the buffer back to the FCC. */
+	rtx.rxbd[rxIdx].cbd_datlen = 0;
+
+	/* wrap around buffer index when necessary */
+	if ((rxIdx + 1) >= PKTBUFSRX) {
+	    rtx.rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
+	    rxIdx = 0;
+	}
+	else {
+	    rtx.rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+	    rxIdx++;
+	}
+    }
+    return length;
+}
+
+
+static int fec_init(struct eth_device* dev, bd_t *bis)
+{
+    struct ether_fcc_info_s * info = dev->priv;
+    int i;
+    volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+    volatile cpm8260_t *cp = &(immr->im_cpm);
+    fcc_enet_t *pram_ptr;
+    unsigned long mem_addr;
+
+#if 0
+    mii_discover_phy();
+#endif
+
+    /* 28.9 - (1-2): ioports have been set up already */
+
+    /* 28.9 - (3): connect FCC's tx and rx clocks */
+    immr->im_cpmux.cmx_uar = 0;
+    immr->im_cpmux.cmx_fcr = (immr->im_cpmux.cmx_fcr & ~info->cmxfcr_mask) |
+							info->cmxfcr_value;
+
+    /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, Mode Ethernet */
+    immr->im_fcc[info->ether_index].fcc_gfmr =
+      FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+
+    /* 28.9 - (5): FPSMR: enable full duplex, select CCITT CRC for Ethernet */
+    immr->im_fcc[info->ether_index].fcc_fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
+
+    /* 28.9 - (6): FDSR: Ethernet Syn */
+    immr->im_fcc[info->ether_index].fcc_fdsr = 0xD555;
+
+    /* reset indeces to current rx/tx bd (see eth_send()/eth_rx()) */
+    rxIdx = 0;
+    txIdx = 0;
+
+    /* Setup Receiver Buffer Descriptors */
+    for (i = 0; i < PKTBUFSRX; i++)
+    {
+      rtx.rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+      rtx.rxbd[i].cbd_datlen = 0;
+      rtx.rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i];
+    }
+    rtx.rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+    /* Setup Ethernet Transmitter Buffer Descriptors */
+    for (i = 0; i < TX_BUF_CNT; i++)
+    {
+      rtx.txbd[i].cbd_sc = (BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+      rtx.txbd[i].cbd_datlen = 0;
+      rtx.txbd[i].cbd_bufaddr = (uint)&txbuf[i][0];
+    }
+    rtx.txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+    /* 28.9 - (7): initialise parameter ram */
+    pram_ptr = (fcc_enet_t *)&(immr->im_dprambase[info->proff_enet]);
+
+    /* clear whole structure to make sure all reserved fields are zero */
+    memset((void*)pram_ptr, 0, sizeof(fcc_enet_t));
+
+    /*
+     * common Parameter RAM area
+     *
+     * Allocate space in the reserved FCC area of DPRAM for the
+     * internal buffers.  No one uses this space (yet), so we
+     * can do this.  Later, we will add resource management for
+     * this area.
+     */
+    mem_addr = CPM_FCC_SPECIAL_BASE + ((info->ether_index) * 64);
+    pram_ptr->fen_genfcc.fcc_riptr = mem_addr;
+    pram_ptr->fen_genfcc.fcc_tiptr = mem_addr+32;
+    /*
+     * Set maximum bytes per receive buffer.
+     * It must be a multiple of 32.
+     */
+    pram_ptr->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
+    pram_ptr->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB |
+				       CONFIG_SYS_CPMFCR_RAMTYPE) << 24;
+    pram_ptr->fen_genfcc.fcc_rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
+    pram_ptr->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB |
+				       CONFIG_SYS_CPMFCR_RAMTYPE) << 24;
+    pram_ptr->fen_genfcc.fcc_tbase = (unsigned int)(&rtx.txbd[txIdx]);
+
+    /* protocol-specific area */
+    pram_ptr->fen_cmask = 0xdebb20e3;	/* CRC mask */
+    pram_ptr->fen_cpres = 0xffffffff;	/* CRC preset */
+    pram_ptr->fen_retlim = 15;		/* Retry limit threshold */
+    pram_ptr->fen_mflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
+    /*
+     * Set Ethernet station address.
+     *
+     * This is supplied in the board information structure, so we
+     * copy that into the controller.
+     * So, far we have only been given one Ethernet address. We make
+     * it unique by setting a few bits in the upper byte of the
+     * non-static part of the address.
+     */
+#define ea eth_get_dev()->enetaddr
+    pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
+    pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
+    pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
+#undef ea
+    pram_ptr->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register */
+    /* pad pointer. use tiptr since we don't need a specific padding char */
+    pram_ptr->fen_padptr = pram_ptr->fen_genfcc.fcc_tiptr;
+    pram_ptr->fen_maxd1 = PKT_MAXDMA_SIZE;	/* maximum DMA1 length */
+    pram_ptr->fen_maxd2 = PKT_MAXDMA_SIZE;	/* maximum DMA2 length */
+    pram_ptr->fen_rfthr = 1;
+    pram_ptr->fen_rfcnt = 1;
+#if 0
+    printf("pram_ptr->fen_genfcc.fcc_rbase %08lx\n",
+	pram_ptr->fen_genfcc.fcc_rbase);
+    printf("pram_ptr->fen_genfcc.fcc_tbase %08lx\n",
+	pram_ptr->fen_genfcc.fcc_tbase);
+#endif
+
+    /* 28.9 - (8): clear out events in FCCE */
+    immr->im_fcc[info->ether_index].fcc_fcce = ~0x0;
+
+    /* 28.9 - (9): FCCM: mask all events */
+    immr->im_fcc[info->ether_index].fcc_fccm = 0;
+
+    /* 28.9 - (10-12): we don't use ethernet interrupts */
+
+    /* 28.9 - (13)
+     *
+     * Let's re-initialize the channel now.  We have to do it later
+     * than the manual describes because we have just now finished
+     * the BD initialization.
+     */
+    cp->cp_cpcr = mk_cr_cmd(info->cpm_cr_enet_page,
+			    info->cpm_cr_enet_sblock,
+			    0x0c,
+			    CPM_CR_INIT_TRX) | CPM_CR_FLG;
+    do {
+	__asm__ __volatile__ ("eieio");
+    } while (cp->cp_cpcr & CPM_CR_FLG);
+
+    /* 28.9 - (14): enable tx/rx in gfmr */
+    immr->im_fcc[info->ether_index].fcc_gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+
+    return 1;
+}
+
+static void fec_halt(struct eth_device* dev)
+{
+    struct ether_fcc_info_s * info = dev->priv;
+    volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+
+    /* write GFMR: disable tx/rx */
+    immr->im_fcc[info->ether_index].fcc_gfmr &=
+						~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+}
+
+int fec_initialize(bd_t *bis)
+{
+	struct eth_device* dev;
+	int i;
+
+	for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
+	{
+		dev = (struct eth_device*) malloc(sizeof *dev);
+		memset(dev, 0, sizeof *dev);
+
+		sprintf(dev->name, "FCC%d ETHERNET",
+			ether_fcc_info[i].ether_index + 1);
+		dev->priv   = &ether_fcc_info[i];
+		dev->init   = fec_init;
+		dev->halt   = fec_halt;
+		dev->send   = fec_send;
+		dev->recv   = fec_recv;
+
+		eth_register(dev);
+
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
+		&& defined(CONFIG_BITBANGMII)
+		miiphy_register(dev->name,
+				bb_miiphy_read,	bb_miiphy_write);
+#endif
+	}
+
+	return 1;
+}
+
+#ifdef CONFIG_ETHER_LOOPBACK_TEST
+
+#define ELBT_BUFSZ	1024	/* must be multiple of 32 */
+
+#define ELBT_CRCSZ	4
+
+#define ELBT_NRXBD	4	/* must be at least 2 */
+#define ELBT_NTXBD	4
+
+#define ELBT_MAXRXERR	32
+#define ELBT_MAXTXERR	32
+
+#define ELBT_CLSWAIT	1000	/* msec to wait for further input frames */
+
+typedef
+	struct {
+		uint off;
+		char *lab;
+	}
+elbt_prdesc;
+
+typedef
+	struct {
+		uint _l, _f, m, bc, mc, lg, no, sh, cr, ov, cl;
+		uint badsrc, badtyp, badlen, badbit;
+	}
+elbt_rxeacc;
+
+static elbt_prdesc rxeacc_descs[] = {
+	{ offsetof(elbt_rxeacc, _l),		"Not Last in Frame"	},
+	{ offsetof(elbt_rxeacc, _f),		"Not First in Frame"	},
+	{ offsetof(elbt_rxeacc, m),		"Address Miss"		},
+	{ offsetof(elbt_rxeacc, bc),		"Broadcast Address"	},
+	{ offsetof(elbt_rxeacc, mc),		"Multicast Address"	},
+	{ offsetof(elbt_rxeacc, lg),		"Frame Length Violation"},
+	{ offsetof(elbt_rxeacc, no),		"Non-Octet Alignment"	},
+	{ offsetof(elbt_rxeacc, sh),		"Short Frame"		},
+	{ offsetof(elbt_rxeacc, cr),		"CRC Error"		},
+	{ offsetof(elbt_rxeacc, ov),		"Overrun"		},
+	{ offsetof(elbt_rxeacc, cl),		"Collision"		},
+	{ offsetof(elbt_rxeacc, badsrc),	"Bad Src Address"	},
+	{ offsetof(elbt_rxeacc, badtyp),	"Bad Frame Type"	},
+	{ offsetof(elbt_rxeacc, badlen),	"Bad Frame Length"	},
+	{ offsetof(elbt_rxeacc, badbit),	"Data Compare Errors"	},
+};
+static int rxeacc_ndesc = sizeof (rxeacc_descs) / sizeof (rxeacc_descs[0]);
+
+typedef
+	struct {
+		uint def, hb, lc, rl, rc, un, csl;
+	}
+elbt_txeacc;
+
+static elbt_prdesc txeacc_descs[] = {
+	{ offsetof(elbt_txeacc, def),		"Defer Indication"	},
+	{ offsetof(elbt_txeacc, hb),		"Heartbeat"		},
+	{ offsetof(elbt_txeacc, lc),		"Late Collision"	},
+	{ offsetof(elbt_txeacc, rl),		"Retransmission Limit"	},
+	{ offsetof(elbt_txeacc, rc),		"Retry Count"		},
+	{ offsetof(elbt_txeacc, un),		"Underrun"		},
+	{ offsetof(elbt_txeacc, csl),		"Carrier Sense Lost"	},
+};
+static int txeacc_ndesc = sizeof (txeacc_descs) / sizeof (txeacc_descs[0]);
+
+typedef
+	struct {
+		uchar rxbufs[ELBT_NRXBD][ELBT_BUFSZ];
+		uchar txbufs[ELBT_NTXBD][ELBT_BUFSZ];
+		cbd_t rxbd[ELBT_NRXBD];
+		cbd_t txbd[ELBT_NTXBD];
+		enum { Idle, Running, Closing, Closed } state;
+		int proff, page, sblock;
+		uint clstime, nsent, ntxerr, nrcvd, nrxerr;
+		ushort rxerrs[ELBT_MAXRXERR], txerrs[ELBT_MAXTXERR];
+		elbt_rxeacc rxeacc;
+		elbt_txeacc txeacc;
+	} __attribute__ ((aligned(8)))
+elbt_chan;
+
+static uchar patbytes[ELBT_NTXBD] = {
+	0xff, 0xaa, 0x55, 0x00
+};
+static uint patwords[ELBT_NTXBD] = {
+	0xffffffff, 0xaaaaaaaa, 0x55555555, 0x00000000
+};
+
+#ifdef __GNUC__
+static elbt_chan elbt_chans[3] __attribute__ ((aligned(8)));
+#else
+#error "elbt_chans must be 64-bit aligned"
+#endif
+
+#define CPM_CR_GRACEFUL_STOP_TX	((ushort)0x0005)
+
+static elbt_prdesc epram_descs[] = {
+	{ offsetof(fcc_enet_t, fen_crcec),	"CRC Errors"		},
+	{ offsetof(fcc_enet_t, fen_alec),	"Alignment Errors"	},
+	{ offsetof(fcc_enet_t, fen_disfc),	"Discarded Frames"	},
+	{ offsetof(fcc_enet_t, fen_octc),	"Octets"		},
+	{ offsetof(fcc_enet_t, fen_colc),	"Collisions"		},
+	{ offsetof(fcc_enet_t, fen_broc),	"Broadcast Frames"	},
+	{ offsetof(fcc_enet_t, fen_mulc),	"Multicast Frames"	},
+	{ offsetof(fcc_enet_t, fen_uspc),	"Undersize Frames"	},
+	{ offsetof(fcc_enet_t, fen_frgc),	"Fragments"		},
+	{ offsetof(fcc_enet_t, fen_ospc),	"Oversize Frames"	},
+	{ offsetof(fcc_enet_t, fen_jbrc),	"Jabbers"		},
+	{ offsetof(fcc_enet_t, fen_p64c),	"64 Octet Frames"	},
+	{ offsetof(fcc_enet_t, fen_p65c),	"65-127 Octet Frames"	},
+	{ offsetof(fcc_enet_t, fen_p128c),	"128-255 Octet Frames"	},
+	{ offsetof(fcc_enet_t, fen_p256c),	"256-511 Octet Frames"	},
+	{ offsetof(fcc_enet_t, fen_p512c),	"512-1023 Octet Frames"	},
+	{ offsetof(fcc_enet_t, fen_p1024c),	"1024-1518 Octet Frames"},
+};
+static int epram_ndesc = sizeof (epram_descs) / sizeof (epram_descs[0]);
+
+/*
+ * given an elbt_prdesc array and an array of base addresses, print
+ * each prdesc down the screen with the values fetched from each
+ * base address across the screen
+ */
+static void
+print_desc (elbt_prdesc descs[], int ndesc, uchar *bases[], int nbase)
+{
+	elbt_prdesc *dp = descs, *edp = dp + ndesc;
+	int i;
+
+	printf ("%32s", "");
+
+	for (i = 0; i < nbase; i++)
+		printf ("  Channel %d", i);
+
+	putc ('\n');
+
+	while (dp < edp) {
+
+		printf ("%-32s", dp->lab);
+
+		for (i = 0; i < nbase; i++) {
+			uint val = *(uint *)(bases[i] + dp->off);
+
+			printf (" %10u", val);
+		}
+
+		putc ('\n');
+
+		dp++;
+	}
+}
+
+/*
+ * return number of bits that are set in a value; value contains
+ * nbits (right-justified) bits.
+ */
+static uint __inline__
+nbs (uint value, uint nbits)
+{
+	uint cnt = 0;
+#if 1
+	uint pos = sizeof (uint) * 8;
+
+	__asm__ __volatile__ ("\
+	mtctr	%2\n\
+1:	rlwnm.	%2,%1,%4,31,31\n\
+	beq	2f\n\
+	addi	%0,%0,1\n\
+2:	subi	%4,%4,1\n\
+	bdnz	1b"
+	: "=r"(cnt)
+	: "r"(value), "r"(nbits), "r"(cnt), "r"(pos)
+	: "ctr", "cc" );
+#else
+	uint mask = 1;
+
+	do {
+		if (value & mask)
+			cnt++;
+		mask <<= 1;
+	} while (--nbits);
+#endif
+
+	return (cnt);
+}
+
+static ulong
+badbits (uchar *bp, int n, ulong pat)
+{
+	ulong *lp, cnt = 0;
+	int nl;
+
+	while (n > 0 && ((ulong)bp & (sizeof (ulong) - 1)) != 0) {
+		uchar diff;
+
+		diff = *bp++ ^ (uchar)pat;
+
+		if (diff)
+			cnt += nbs ((ulong)diff, 8);
+
+		n--;
+	}
+
+	lp = (ulong *)bp;
+	nl = n / sizeof (ulong);
+	n -= nl * sizeof (ulong);
+
+	while (nl > 0) {
+		ulong diff;
+
+		diff = *lp++ ^ pat;
+
+		if (diff)
+			cnt += nbs (diff, 32);
+
+		nl--;
+	}
+
+	bp = (uchar *)lp;
+
+	while (n > 0) {
+		uchar diff;
+
+		diff = *bp++ ^ (uchar)pat;
+
+		if (diff)
+			cnt += nbs ((ulong)diff, 8);
+
+		n--;
+	}
+
+	return (cnt);
+}
+
+static inline unsigned short
+swap16 (unsigned short x)
+{
+	return (((x & 0xff) << 8) | ((x & 0xff00) >> 8));
+}
+
+/* broadcast is not an error - we send them like that */
+#define BD_ENET_RX_ERRS	(BD_ENET_RX_STATS & ~BD_ENET_RX_BC)
+
+void
+eth_loopback_test (void)
+{
+	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	volatile cpm8260_t *cp = &(immr->im_cpm);
+	int c, nclosed;
+	ulong runtime, nmsec;
+	uchar *bases[3];
+
+	puts ("FCC Ethernet External loopback test\n");
+
+	eth_getenv_enetaddr("ethaddr", NetOurEther);
+
+	/*
+	 * global initialisations for all FCC channels
+	 */
+
+	/* 28.9 - (1-2): ioports have been set up already */
+
+#if defined(CONFIG_HYMOD)
+	/*
+	 * Attention: this is board-specific
+	 * 0, FCC1
+	 * 1, FCC2
+	 * 2, FCC3
+	 */
+#       define FCC_START_LOOP 0
+#       define FCC_END_LOOP   2
+
+	/*
+	 * Attention: this is board-specific
+	 * - FCC1 Rx-CLK is CLK10
+	 * - FCC1 Tx-CLK is CLK11
+	 * - FCC2 Rx-CLK is CLK13
+	 * - FCC2 Tx-CLK is CLK14
+	 * - FCC3 Rx-CLK is CLK15
+	 * - FCC3 Tx-CLK is CLK16
+	 */
+
+	/* 28.9 - (3): connect FCC's tx and rx clocks */
+	immr->im_cpmux.cmx_uar = 0;
+	immr->im_cpmux.cmx_fcr = CMXFCR_RF1CS_CLK10|CMXFCR_TF1CS_CLK11|\
+	    CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14|\
+	    CMXFCR_RF3CS_CLK15|CMXFCR_TF3CS_CLK16;
+#elif defined(CONFIG_SBC8260) || defined(CONFIG_SACSng)
+	/*
+	 * Attention: this is board-specific
+	 * 1, FCC2
+	 */
+#       define FCC_START_LOOP 1
+#       define FCC_END_LOOP   1
+
+	/*
+	 * Attention: this is board-specific
+	 * - FCC2 Rx-CLK is CLK13
+	 * - FCC2 Tx-CLK is CLK14
+	 */
+
+	/* 28.9 - (3): connect FCC's tx and rx clocks */
+	immr->im_cpmux.cmx_uar = 0;
+	immr->im_cpmux.cmx_fcr = CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14;
+#else
+#error "eth_loopback_test not supported on your board"
+#endif
+
+	puts ("Initialise FCC channels:");
+
+	for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) {
+		elbt_chan *ecp = &elbt_chans[c];
+		volatile fcc_t *fcp = &immr->im_fcc[c];
+		volatile fcc_enet_t *fpp;
+		int i;
+		ulong addr;
+
+		/*
+		 * initialise channel data
+		 */
+
+		printf (" %d", c);
+
+		memset ((void *)ecp, 0, sizeof (*ecp));
+
+		ecp->state = Idle;
+
+		switch (c) {
+
+		case 0: /* FCC1 */
+			ecp->proff = PROFF_FCC1;
+			ecp->page = CPM_CR_FCC1_PAGE;
+			ecp->sblock = CPM_CR_FCC1_SBLOCK;
+			break;
+
+		case 1: /* FCC2 */
+			ecp->proff = PROFF_FCC2;
+			ecp->page = CPM_CR_FCC2_PAGE;
+			ecp->sblock = CPM_CR_FCC2_SBLOCK;
+			break;
+
+		case 2: /* FCC3 */
+			ecp->proff = PROFF_FCC3;
+			ecp->page = CPM_CR_FCC3_PAGE;
+			ecp->sblock = CPM_CR_FCC3_SBLOCK;
+			break;
+		}
+
+		/*
+		 * set up tx buffers and bds
+		 */
+
+		for (i = 0; i < ELBT_NTXBD; i++) {
+			cbd_t *bdp = &ecp->txbd[i];
+			uchar *bp = &ecp->txbufs[i][0];
+
+			bdp->cbd_bufaddr = (uint)bp;
+			/* room for crc */
+			bdp->cbd_datlen = ELBT_BUFSZ - ELBT_CRCSZ;
+			bdp->cbd_sc = BD_ENET_TX_READY | BD_ENET_TX_PAD | \
+				BD_ENET_TX_LAST | BD_ENET_TX_TC;
+
+			memset ((void *)bp, patbytes[i], ELBT_BUFSZ);
+			NetSetEther (bp, NetBcastAddr, 0x8000);
+		}
+		ecp->txbd[ELBT_NTXBD - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+		/*
+		 * set up rx buffers and bds
+		 */
+
+		for (i = 0; i < ELBT_NRXBD; i++) {
+		    cbd_t *bdp = &ecp->rxbd[i];
+		    uchar *bp = &ecp->rxbufs[i][0];
+
+		    bdp->cbd_bufaddr = (uint)bp;
+		    bdp->cbd_datlen = 0;
+		    bdp->cbd_sc = BD_ENET_RX_EMPTY;
+
+		    memset ((void *)bp, 0, ELBT_BUFSZ);
+		}
+		ecp->rxbd[ELBT_NRXBD - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+		/*
+		 * set up the FCC channel hardware
+		 */
+
+		/* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, Mode Ethernet */
+		fcp->fcc_gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+
+		/* 28.9 - (5): FPSMR: fd, enet CRC, Promis, RMON, Rx SHort */
+		fcp->fcc_fpsmr = FCC_PSMR_FDE | FCC_PSMR_LPB | \
+			FCC_PSMR_ENCRC | FCC_PSMR_PRO | \
+			FCC_PSMR_MON | FCC_PSMR_RSH;
+
+		/* 28.9 - (6): FDSR: Ethernet Syn */
+		fcp->fcc_fdsr = 0xD555;
+
+		/* 29.9 - (7): initialise parameter ram */
+		fpp = (fcc_enet_t *)&(immr->im_dprambase[ecp->proff]);
+
+		/* clear whole struct to make sure all resv fields are zero */
+		memset ((void *)fpp, 0, sizeof (fcc_enet_t));
+
+		/*
+		 * common Parameter RAM area
+		 *
+		 * Allocate space in the reserved FCC area of DPRAM for the
+		 * internal buffers.  No one uses this space (yet), so we
+		 * can do this.  Later, we will add resource management for
+		 * this area.
+		 */
+		addr = CPM_FCC_SPECIAL_BASE + (c * 64);
+		fpp->fen_genfcc.fcc_riptr = addr;
+		fpp->fen_genfcc.fcc_tiptr = addr + 32;
+
+		/*
+		 * Set maximum bytes per receive buffer.
+		 * It must be a multiple of 32.
+		 * buffers are in 60x bus memory.
+		 */
+		fpp->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
+		fpp->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
+		fpp->fen_genfcc.fcc_rbase = (unsigned int)(&ecp->rxbd[0]);
+		fpp->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
+		fpp->fen_genfcc.fcc_tbase = (unsigned int)(&ecp->txbd[0]);
+
+		/* protocol-specific area */
+		fpp->fen_cmask = 0xdebb20e3;	/* CRC mask */
+		fpp->fen_cpres = 0xffffffff;	/* CRC preset */
+		fpp->fen_retlim = 15;		/* Retry limit threshold */
+		fpp->fen_mflr = PKT_MAXBUF_SIZE;/* max frame length register */
+
+		/*
+		 * Set Ethernet station address.
+		 *
+		 * This is supplied in the board information structure, so we
+		 * copy that into the controller.
+		 * So, far we have only been given one Ethernet address. We use
+		 * the same address for all channels
+		 */
+#define ea NetOurEther
+		fpp->fen_paddrh = (ea[5] << 8) + ea[4];
+		fpp->fen_paddrm = (ea[3] << 8) + ea[2];
+		fpp->fen_paddrl = (ea[1] << 8) + ea[0];
+#undef ea
+
+		fpp->fen_minflr = PKT_MINBUF_SIZE; /* min frame len register */
+		/*
+		 * pad pointer. use tiptr since we don't need
+		 * a specific padding char
+		 */
+		fpp->fen_padptr = fpp->fen_genfcc.fcc_tiptr;
+		fpp->fen_maxd1 = PKT_MAXDMA_SIZE;	/* max DMA1 length */
+		fpp->fen_maxd2 = PKT_MAXDMA_SIZE;	/* max DMA2 length */
+		fpp->fen_rfthr = 1;
+		fpp->fen_rfcnt = 1;
+
+		/* 28.9 - (8): clear out events in FCCE */
+		fcp->fcc_fcce = ~0x0;
+
+		/* 28.9 - (9): FCCM: mask all events */
+		fcp->fcc_fccm = 0;
+
+		/* 28.9 - (10-12): we don't use ethernet interrupts */
+
+		/* 28.9 - (13)
+		 *
+		 * Let's re-initialize the channel now.  We have to do it later
+		 * than the manual describes because we have just now finished
+		 * the BD initialization.
+		 */
+		cp->cp_cpcr = mk_cr_cmd (ecp->page, ecp->sblock, \
+			0x0c, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+		do {
+			__asm__ __volatile__ ("eieio");
+		} while (cp->cp_cpcr & CPM_CR_FLG);
+	}
+
+	puts (" done\nStarting test... (Ctrl-C to Finish)\n");
+
+	/*
+	 * Note: don't want serial output from here until the end of the
+	 * test - the delays would probably stuff things up.
+	 */
+
+	clear_ctrlc ();
+	runtime = get_timer (0);
+
+	do {
+		nclosed = 0;
+
+		for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) {
+			volatile fcc_t *fcp = &immr->im_fcc[c];
+			elbt_chan *ecp = &elbt_chans[c];
+			int i;
+
+			switch (ecp->state) {
+
+			case Idle:
+				/*
+				 * set the channel Running ...
+				 */
+
+				/* 28.9 - (14): enable tx/rx in gfmr */
+				fcp->fcc_gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+
+				ecp->state = Running;
+				break;
+
+			case Running:
+				/*
+				 * (while Running only) check for
+				 * termination of the test
+				 */
+
+				(void)ctrlc ();
+
+				if (had_ctrlc ()) {
+					/*
+					 * initiate a "graceful stop transmit"
+					 * on the channel
+					 */
+					cp->cp_cpcr = mk_cr_cmd (ecp->page, \
+						ecp->sblock, 0x0c, \
+						CPM_CR_GRACEFUL_STOP_TX) | \
+						CPM_CR_FLG;
+					do {
+						__asm__ __volatile__ ("eieio");
+					} while (cp->cp_cpcr & CPM_CR_FLG);
+
+					ecp->clstime = get_timer (0);
+					ecp->state = Closing;
+				}
+				/* fall through ... */
+
+			case Closing:
+				/*
+				 * (while Running or Closing) poll the channel:
+				 * - check for any non-READY tx buffers and
+				 *   make them ready
+				 * - check for any non-EMPTY rx buffers and
+				 *   check that they were received correctly,
+				 *   adjust counters etc, then make empty
+				 */
+
+				for (i = 0; i < ELBT_NTXBD; i++) {
+					cbd_t *bdp = &ecp->txbd[i];
+					ushort sc = bdp->cbd_sc;
+
+					if ((sc & BD_ENET_TX_READY) != 0)
+						continue;
+
+					/*
+					 * this frame has finished
+					 * transmitting
+					 */
+					ecp->nsent++;
+
+					if (sc & BD_ENET_TX_STATS) {
+						ulong n;
+
+						/*
+						 * we had an error on
+						 * the transmission
+						 */
+						n = ecp->ntxerr++;
+						if (n < ELBT_MAXTXERR)
+							ecp->txerrs[n] = sc;
+
+						if (sc & BD_ENET_TX_DEF)
+							ecp->txeacc.def++;
+						if (sc & BD_ENET_TX_HB)
+							ecp->txeacc.hb++;
+						if (sc & BD_ENET_TX_LC)
+							ecp->txeacc.lc++;
+						if (sc & BD_ENET_TX_RL)
+							ecp->txeacc.rl++;
+						if (sc & BD_ENET_TX_RCMASK)
+							ecp->txeacc.rc++;
+						if (sc & BD_ENET_TX_UN)
+							ecp->txeacc.un++;
+						if (sc & BD_ENET_TX_CSL)
+							ecp->txeacc.csl++;
+
+						bdp->cbd_sc &= \
+							~BD_ENET_TX_STATS;
+					}
+
+					if (ecp->state == Closing)
+						ecp->clstime = get_timer (0);
+
+					/* make it ready again */
+					bdp->cbd_sc |= BD_ENET_TX_READY;
+				}
+
+				for (i = 0; i < ELBT_NRXBD; i++) {
+					cbd_t *bdp = &ecp->rxbd[i];
+					ushort sc = bdp->cbd_sc, mask;
+
+					if ((sc & BD_ENET_RX_EMPTY) != 0)
+						continue;
+
+					/* we have a new frame in this buffer */
+					ecp->nrcvd++;
+
+					mask = BD_ENET_RX_LAST|BD_ENET_RX_FIRST;
+					if ((sc & mask) != mask) {
+						/* somethings wrong here ... */
+						if (!(sc & BD_ENET_RX_LAST))
+							ecp->rxeacc._l++;
+						if (!(sc & BD_ENET_RX_FIRST))
+							ecp->rxeacc._f++;
+					}
+
+					if (sc & BD_ENET_RX_ERRS) {
+						ulong n;
+
+						/*
+						 * we had some sort of error
+						 * on the frame
+						 */
+						n = ecp->nrxerr++;
+						if (n < ELBT_MAXRXERR)
+							ecp->rxerrs[n] = sc;
+
+						if (sc & BD_ENET_RX_MISS)
+							ecp->rxeacc.m++;
+						if (sc & BD_ENET_RX_BC)
+							ecp->rxeacc.bc++;
+						if (sc & BD_ENET_RX_MC)
+							ecp->rxeacc.mc++;
+						if (sc & BD_ENET_RX_LG)
+							ecp->rxeacc.lg++;
+						if (sc & BD_ENET_RX_NO)
+							ecp->rxeacc.no++;
+						if (sc & BD_ENET_RX_SH)
+							ecp->rxeacc.sh++;
+						if (sc & BD_ENET_RX_CR)
+							ecp->rxeacc.cr++;
+						if (sc & BD_ENET_RX_OV)
+							ecp->rxeacc.ov++;
+						if (sc & BD_ENET_RX_CL)
+							ecp->rxeacc.cl++;
+
+						bdp->cbd_sc &= \
+							~BD_ENET_RX_ERRS;
+					}
+					else {
+						ushort datlen = bdp->cbd_datlen;
+						Ethernet_t *ehp;
+						ushort prot;
+						int ours, tb, n, nbytes;
+
+						ehp = (Ethernet_t *) \
+							&ecp->rxbufs[i][0];
+
+						ours = memcmp (ehp->et_src, \
+							NetOurEther, 6);
+
+						prot = swap16 (ehp->et_protlen);
+						tb = prot & 0x8000;
+						n = prot & 0x7fff;
+
+						nbytes = ELBT_BUFSZ - \
+							offsetof (Ethernet_t, \
+								et_dsap) - \
+							ELBT_CRCSZ;
+
+						/* check the frame is correct */
+						if (datlen != ELBT_BUFSZ)
+							ecp->rxeacc.badlen++;
+						else if (!ours)
+							ecp->rxeacc.badsrc++;
+						else if (!tb || n >= ELBT_NTXBD)
+							ecp->rxeacc.badtyp++;
+						else {
+							ulong patword = \
+								patwords[n];
+							uint nbb;
+
+							nbb = badbits ( \
+								&ehp->et_dsap, \
+								nbytes, \
+								patword);
+
+							ecp->rxeacc.badbit += \
+								nbb;
+						}
+					}
+
+					if (ecp->state == Closing)
+					    ecp->clstime = get_timer (0);
+
+					/* make it empty again */
+					bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+				}
+
+				if (ecp->state != Closing)
+					break;
+
+				/*
+				 * (while Closing) check to see if
+				 * waited long enough
+				 */
+
+				if (get_timer (ecp->clstime) >= ELBT_CLSWAIT) {
+					/* write GFMR: disable tx/rx */
+					fcp->fcc_gfmr &= \
+						~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+					ecp->state = Closed;
+				}
+
+				break;
+
+			case Closed:
+				nclosed++;
+				break;
+			}
+		}
+
+	} while (nclosed < (FCC_END_LOOP - FCC_START_LOOP + 1));
+
+	runtime = get_timer (runtime);
+	if (runtime <= ELBT_CLSWAIT) {
+		printf ("Whoops! somehow elapsed time (%ld) is wrong (<= %d)\n",
+			runtime, ELBT_CLSWAIT);
+		return;
+	}
+	nmsec = runtime - ELBT_CLSWAIT;
+
+	printf ("Test Finished in %ldms (plus %dms close wait period)!\n\n",
+		nmsec, ELBT_CLSWAIT);
+
+	/*
+	 * now print stats
+	 */
+
+	for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) {
+		elbt_chan *ecp = &elbt_chans[c];
+		uint rxpps, txpps, nerr;
+
+		rxpps = (ecp->nrcvd * 1000) / nmsec;
+		txpps = (ecp->nsent * 1000) / nmsec;
+
+		printf ("Channel %d: %d rcvd (%d pps, %d rxerrs), "
+			"%d sent (%d pps, %d txerrs)\n\n", c,
+			ecp->nrcvd, rxpps, ecp->nrxerr,
+			ecp->nsent, txpps, ecp->ntxerr);
+
+		if ((nerr = ecp->nrxerr) > 0) {
+			ulong i;
+
+			printf ("\tFirst %d rx errs:", nerr);
+			for (i = 0; i < nerr; i++)
+				printf (" %04x", ecp->rxerrs[i]);
+			putc ('\n');
+		}
+
+		if ((nerr = ecp->ntxerr) > 0) {
+			ulong i;
+
+			printf ("\tFirst %d tx errs:", nerr);
+			for (i = 0; i < nerr; i++)
+				printf (" %04x", ecp->txerrs[i]);
+			putc ('\n');
+		}
+	}
+
+	puts ("Receive Error Counts:\n");
+	for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++)
+		bases[c] = (uchar *)&elbt_chans[c].rxeacc;
+	print_desc (rxeacc_descs, rxeacc_ndesc, bases, 3);
+
+	puts ("\nTransmit Error Counts:\n");
+	for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++)
+		bases[c] = (uchar *)&elbt_chans[c].txeacc;
+	print_desc (txeacc_descs, txeacc_ndesc, bases, 3);
+
+	puts ("\nRMON(-like) Counters:\n");
+	for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++)
+		bases[c] = (uchar *)&immr->im_dprambase[elbt_chans[c].proff];
+	print_desc (epram_descs, epram_ndesc, bases, 3);
+}
+
+#endif /* CONFIG_ETHER_LOOPBACK_TEST */
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8260/ether_scc.c b/arch/powerpc/cpu/mpc8260/ether_scc.c
new file mode 100644
index 0000000..432111d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/ether_scc.c
@@ -0,0 +1,387 @@
+/*
+ * MPC8260 SCC Ethernet
+ *
+ * Copyright (c) 2000 MontaVista Software, Inc.   Dan Malek (dmalek@jlc.net)
+ *
+ * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright (c) 2001
+ * Advent Networks, Inc. <http://www.adventnetworks.com>
+ * Jay Monkman <jtm@smoothsmoothie.com>
+ *
+ * Modified so that it plays nicely when more than one ETHERNET interface
+ * is in use a la ether_fcc.c.
+ * (C) Copyright 2008
+ * DENX Software Engineerin GmbH
+ * Gary Jennejohn <garyj@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/cpm_8260.h>
+#include <mpc8260.h>
+#include <malloc.h>
+#include <net.h>
+#include <command.h>
+#include <config.h>
+
+#ifndef CONFIG_NET_MULTI
+#error "CONFIG_NET_MULTI must be defined."
+#endif
+
+#if (CONFIG_ETHER_INDEX == 1)
+#  define PROFF_ENET            PROFF_SCC1
+#  define CPM_CR_ENET_PAGE      CPM_CR_SCC1_PAGE
+#  define CPM_CR_ENET_SBLOCK    CPM_CR_SCC1_SBLOCK
+#  define CMXSCR_MASK          (CMXSCR_SC1          |\
+				CMXSCR_RS1CS_MSK    |\
+				CMXSCR_TS1CS_MSK)
+
+#elif (CONFIG_ETHER_INDEX == 2)
+#  define PROFF_ENET            PROFF_SCC2
+#  define CPM_CR_ENET_PAGE      CPM_CR_SCC2_PAGE
+#  define CPM_CR_ENET_SBLOCK    CPM_CR_SCC2_SBLOCK
+#  define CMXSCR_MASK          (CMXSCR_SC2          |\
+				CMXSCR_RS2CS_MSK    |\
+				CMXSCR_TS2CS_MSK)
+
+#elif (CONFIG_ETHER_INDEX == 3)
+#  define PROFF_ENET            PROFF_SCC3
+#  define CPM_CR_ENET_PAGE      CPM_CR_SCC3_PAGE
+#  define CPM_CR_ENET_SBLOCK    CPM_CR_SCC3_SBLOCK
+#  define CMXSCR_MASK          (CMXSCR_SC3          |\
+				CMXSCR_RS3CS_MSK    |\
+				CMXSCR_TS3CS_MSK)
+#elif (CONFIG_ETHER_INDEX == 4)
+#  define PROFF_ENET            PROFF_SCC4
+#  define CPM_CR_ENET_PAGE      CPM_CR_SCC4_PAGE
+#  define CPM_CR_ENET_SBLOCK    CPM_CR_SCC4_SBLOCK
+#  define CMXSCR_MASK          (CMXSCR_SC4          |\
+				CMXSCR_RS4CS_MSK    |\
+				CMXSCR_TS4CS_MSK)
+
+#endif
+
+
+/* Ethernet Transmit and Receive Buffers */
+#define DBUF_LENGTH  1520
+
+#define TX_BUF_CNT 2
+
+#if !defined(CONFIG_SYS_SCC_TOUT_LOOP)
+  #define CONFIG_SYS_SCC_TOUT_LOOP 1000000
+#endif
+
+static char txbuf[TX_BUF_CNT][ DBUF_LENGTH ];
+
+static uint rxIdx;      /* index of the current RX buffer */
+static uint txIdx;      /* index of the current TX buffer */
+
+/*
+ * SCC Ethernet Tx and Rx buffer descriptors allocated at the
+ *  immr->udata_bd address on Dual-Port RAM
+ * Provide for Double Buffering
+ */
+
+typedef volatile struct CommonBufferDescriptor {
+    cbd_t rxbd[PKTBUFSRX];         /* Rx BD */
+    cbd_t txbd[TX_BUF_CNT];        /* Tx BD */
+} RTXBD;
+
+static RTXBD *rtx;
+
+
+static int sec_send(struct eth_device *dev, volatile void *packet, int length)
+{
+    int i;
+    int result = 0;
+
+    if (length <= 0) {
+	printf("scc: bad packet size: %d\n", length);
+	goto out;
+    }
+
+    for(i=0; rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+	if (i >= CONFIG_SYS_SCC_TOUT_LOOP) {
+	    puts ("scc: tx buffer not ready\n");
+	    goto out;
+	}
+    }
+
+    rtx->txbd[txIdx].cbd_bufaddr = (uint)packet;
+    rtx->txbd[txIdx].cbd_datlen = length;
+    rtx->txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST |
+				BD_ENET_TX_WRAP);
+
+    for(i=0; rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+	if (i >= CONFIG_SYS_SCC_TOUT_LOOP) {
+	    puts ("scc: tx error\n");
+	    goto out;
+	}
+    }
+
+    /* return only status bits */
+    result = rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS;
+
+ out:
+    return result;
+}
+
+
+static int sec_rx(struct eth_device *dev)
+{
+    int length;
+
+    for (;;)
+    {
+	if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+	    length = -1;
+	    break;     /* nothing received - leave for() loop */
+	}
+
+	length = rtx->rxbd[rxIdx].cbd_datlen;
+
+	if (rtx->rxbd[rxIdx].cbd_sc & 0x003f)
+	{
+	    printf("err: %x\n", rtx->rxbd[rxIdx].cbd_sc);
+	}
+	else
+	{
+	    /* Pass the packet up to the protocol layers. */
+	    NetReceive(NetRxPackets[rxIdx], length - 4);
+	}
+
+
+	/* Give the buffer back to the SCC. */
+	rtx->rxbd[rxIdx].cbd_datlen = 0;
+
+	/* wrap around buffer index when necessary */
+	if ((rxIdx + 1) >= PKTBUFSRX) {
+	    rtx->rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP |
+					       BD_ENET_RX_EMPTY);
+	    rxIdx = 0;
+	}
+	else {
+	    rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+	    rxIdx++;
+	}
+    }
+    return length;
+}
+
+/**************************************************************
+ *
+ * SCC Ethernet Initialization Routine
+ *
+ *************************************************************/
+
+static int sec_init(struct eth_device *dev, bd_t *bis)
+{
+    int i;
+    volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+    scc_enet_t *pram_ptr;
+    uint dpaddr;
+    uchar ea[6];
+
+    rxIdx = 0;
+    txIdx = 0;
+
+    /*
+     * Assign static pointer to BD area.
+     * Avoid exhausting DPRAM, which would cause a panic.
+     */
+    if (rtx == NULL) {
+	    dpaddr = m8260_cpm_dpalloc(sizeof(RTXBD) + 2, 16);
+	    rtx = (RTXBD *)&immr->im_dprambase[dpaddr];
+    }
+
+    /* 24.21 - (1-3): ioports have been set up already */
+
+    /* 24.21 - (4,5): connect SCC's tx and rx clocks, use NMSI for SCC */
+    immr->im_cpmux.cmx_uar = 0;
+    immr->im_cpmux.cmx_scr = ( (immr->im_cpmux.cmx_scr & ~CMXSCR_MASK) |
+			       CONFIG_SYS_CMXSCR_VALUE);
+
+
+    /* 24.21 (6) write RBASE and TBASE to parameter RAM */
+    pram_ptr = (scc_enet_t *)&(immr->im_dprambase[PROFF_ENET]);
+    pram_ptr->sen_genscc.scc_rbase = (unsigned int)(&rtx->rxbd[0]);
+    pram_ptr->sen_genscc.scc_tbase = (unsigned int)(&rtx->txbd[0]);
+
+    pram_ptr->sen_genscc.scc_rfcr = 0x18;  /* Nrml Ops and Mot byte ordering */
+    pram_ptr->sen_genscc.scc_tfcr = 0x18;  /* Mot byte ordering, Nrml access */
+
+    pram_ptr->sen_genscc.scc_mrblr = DBUF_LENGTH; /* max. package len 1520 */
+
+    pram_ptr->sen_cpres  = ~(0x0);        /* Preset CRC */
+    pram_ptr->sen_cmask  = 0xdebb20e3;    /* Constant Mask for CRC */
+
+
+    /* 24.21 - (7): Write INIT RX AND TX PARAMETERS to CPCR */
+    while(immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+    immr->im_cpm.cp_cpcr = mk_cr_cmd(CPM_CR_ENET_PAGE,
+				     CPM_CR_ENET_SBLOCK,
+				     0x0c,
+				     CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+    /* 24.21 - (8-18): Set up parameter RAM */
+    pram_ptr->sen_crcec  = 0x0;           /* Error Counter CRC (unused) */
+    pram_ptr->sen_alec   = 0x0;           /* Align Error Counter (unused) */
+    pram_ptr->sen_disfc  = 0x0;           /* Discard Frame Counter (unused) */
+
+    pram_ptr->sen_pads   = 0x8888;        /* Short Frame PAD Characters */
+
+    pram_ptr->sen_retlim = 15;            /* Retry Limit Threshold */
+
+    pram_ptr->sen_maxflr = 1518;  /* MAX Frame Length Register */
+    pram_ptr->sen_minflr = 64;            /* MIN Frame Length Register */
+
+    pram_ptr->sen_maxd1  = DBUF_LENGTH;   /* MAX DMA1 Length Register */
+    pram_ptr->sen_maxd2  = DBUF_LENGTH;   /* MAX DMA2 Length Register */
+
+    pram_ptr->sen_gaddr1 = 0x0;   /* Group Address Filter 1 (unused) */
+    pram_ptr->sen_gaddr2 = 0x0;   /* Group Address Filter 2 (unused) */
+    pram_ptr->sen_gaddr3 = 0x0;   /* Group Address Filter 3 (unused) */
+    pram_ptr->sen_gaddr4 = 0x0;   /* Group Address Filter 4 (unused) */
+
+    eth_getenv_enetaddr("ethaddr", ea);
+    pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
+    pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
+    pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
+
+    pram_ptr->sen_pper   = 0x0;   /* Persistence (unused) */
+
+    pram_ptr->sen_iaddr1 = 0x0;   /* Individual Address Filter 1 (unused) */
+    pram_ptr->sen_iaddr2 = 0x0;   /* Individual Address Filter 2 (unused) */
+    pram_ptr->sen_iaddr3 = 0x0;   /* Individual Address Filter 3 (unused) */
+    pram_ptr->sen_iaddr4 = 0x0;   /* Individual Address Filter 4 (unused) */
+
+    pram_ptr->sen_taddrh = 0x0;   /* Tmp Address (MSB) (unused) */
+    pram_ptr->sen_taddrm = 0x0;   /* Tmp Address (unused) */
+    pram_ptr->sen_taddrl = 0x0;   /* Tmp Address (LSB) (unused) */
+
+    /* 24.21 - (19): Initialize RxBD */
+    for (i = 0; i < PKTBUFSRX; i++)
+    {
+	rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+	rtx->rxbd[i].cbd_datlen = 0;                  /* Reset */
+	rtx->rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i];
+    }
+
+    rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+    /* 24.21 - (20): Initialize TxBD */
+    for (i = 0; i < TX_BUF_CNT; i++)
+    {
+	rtx->txbd[i].cbd_sc = (BD_ENET_TX_PAD  |
+			       BD_ENET_TX_LAST |
+			       BD_ENET_TX_TC);
+	rtx->txbd[i].cbd_datlen = 0;                  /* Reset */
+	rtx->txbd[i].cbd_bufaddr = (uint)&txbuf[i][0];
+    }
+
+    rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+    /* 24.21 - (21): Write 0xffff to SCCE */
+    immr->im_scc[CONFIG_ETHER_INDEX-1].scc_scce = ~(0x0);
+
+    /* 24.21 - (22): Write to SCCM to enable TXE, RXF, TXB events */
+    immr->im_scc[CONFIG_ETHER_INDEX-1].scc_sccm = (SCCE_ENET_TXE |
+						   SCCE_ENET_RXF |
+						   SCCE_ENET_TXB);
+
+    /* 24.21 - (23): we don't use ethernet interrupts */
+
+    /* 24.21 - (24): Clear GSMR_H to enable normal operations */
+    immr->im_scc[CONFIG_ETHER_INDEX-1].scc_gsmrh = 0;
+
+    /* 24.21 - (25): Clear GSMR_L to enable normal operations */
+    immr->im_scc[CONFIG_ETHER_INDEX-1].scc_gsmrl = (SCC_GSMRL_TCI        |
+						    SCC_GSMRL_TPL_48     |
+						    SCC_GSMRL_TPP_10     |
+						    SCC_GSMRL_MODE_ENET);
+
+    /* 24.21 - (26): Initialize DSR */
+    immr->im_scc[CONFIG_ETHER_INDEX-1].scc_dsr = 0xd555;
+
+    /* 24.21 - (27): Initialize PSMR2
+     *
+     * Settings:
+     *	CRC = 32-Bit CCITT
+     *	NIB = Begin searching for SFD 22 bits after RENA
+     *	FDE = Full Duplex Enable
+     *	BRO = Reject broadcast packets
+     *	PROMISCOUS = Catch all packets regardless of dest. MAC adress
+     */
+    immr->im_scc[CONFIG_ETHER_INDEX-1].scc_psmr   =	SCC_PSMR_ENCRC	|
+							SCC_PSMR_NIB22	|
+#if defined(CONFIG_SCC_ENET_FULL_DUPLEX)
+							SCC_PSMR_FDE	|
+#endif
+#if defined(CONFIG_SCC_ENET_NO_BROADCAST)
+							SCC_PSMR_BRO	|
+#endif
+#if defined(CONFIG_SCC_ENET_PROMISCOUS)
+							SCC_PSMR_PRO	|
+#endif
+							0;
+
+    /* 24.21 - (28): Write to GSMR_L to enable SCC */
+    immr->im_scc[CONFIG_ETHER_INDEX-1].scc_gsmrl |= (SCC_GSMRL_ENR |
+						     SCC_GSMRL_ENT);
+
+    return 0;
+}
+
+
+static void sec_halt(struct eth_device *dev)
+{
+    volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+    immr->im_scc[CONFIG_ETHER_INDEX-1].scc_gsmrl &= ~(SCC_GSMRL_ENR |
+						      SCC_GSMRL_ENT);
+}
+
+#if 0
+static void sec_restart(void)
+{
+    volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+    immr->im_cpm.cp_scc[CONFIG_ETHER_INDEX-1].scc_gsmrl |= (SCC_GSMRL_ENR |
+							    SCC_GSMRL_ENT);
+}
+#endif
+
+int mpc82xx_scc_enet_initialize(bd_t *bis)
+{
+	struct eth_device *dev;
+
+	dev = (struct eth_device *) malloc(sizeof *dev);
+	memset(dev, 0, sizeof *dev);
+
+	sprintf(dev->name, "SCC ETHERNET");
+	dev->init   = sec_init;
+	dev->halt   = sec_halt;
+	dev->send   = sec_send;
+	dev->recv   = sec_rx;
+
+	eth_register(dev);
+
+	return 1;
+}
diff --git a/arch/powerpc/cpu/mpc8260/i2c.c b/arch/powerpc/cpu/mpc8260/i2c.c
new file mode 100644
index 0000000..d2bdcc2
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/i2c.c
@@ -0,0 +1,785 @@
+/*
+ * (C) Copyright 2000
+ * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
+ *
+ * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_HARD_I2C)
+
+#include <asm/cpm_8260.h>
+#include <i2c.h>
+
+/* define to enable debug messages */
+#undef  DEBUG_I2C
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_I2C_MULTI_BUS)
+static unsigned int i2c_bus_num __attribute__ ((section (".data"))) = 0;
+#endif /* CONFIG_I2C_MULTI_BUS */
+
+/* uSec to wait between polls of the i2c */
+#define DELAY_US	100
+/* uSec to wait for the CPM to start processing the buffer */
+#define START_DELAY_US	1000
+
+/*
+ * tx/rx per-byte timeout: we delay DELAY_US uSec between polls so the
+ * timeout will be (tx_length + rx_length) * DELAY_US * TOUT_LOOP
+ */
+#define TOUT_LOOP 5
+
+/*-----------------------------------------------------------------------
+ * Set default values
+ */
+#ifndef	CONFIG_SYS_I2C_SPEED
+#define	CONFIG_SYS_I2C_SPEED	50000
+#endif
+
+/*-----------------------------------------------------------------------
+ */
+
+typedef void (*i2c_ecb_t)(int, int, void *);    /* error callback function */
+
+/* This structure keeps track of the bd and buffer space usage. */
+typedef struct i2c_state {
+	int		rx_idx;		/* index   to next free Rx BD */
+	int		tx_idx;		/* index   to next free Tx BD */
+	void		*rxbd;		/* pointer to next free Rx BD */
+	void		*txbd;		/* pointer to next free Tx BD */
+	int		tx_space;	/* number  of Tx bytes left   */
+	unsigned char	*tx_buf;	/* pointer to free Tx area    */
+	i2c_ecb_t	err_cb;		/* error callback function    */
+	void		*cb_data;	/* private data to be passed  */
+} i2c_state_t;
+
+/* flags for i2c_send() and i2c_receive() */
+#define	I2CF_ENABLE_SECONDARY	0x01	/* secondary_address is valid	*/
+#define	I2CF_START_COND		0x02	/* tx: generate start condition	*/
+#define I2CF_STOP_COND		0x04	/* tx: generate stop  condition	*/
+
+/* return codes */
+#define I2CERR_NO_BUFFERS	1	/* no more BDs or buffer space	*/
+#define I2CERR_MSG_TOO_LONG	2	/* tried to send/receive to much data   */
+#define I2CERR_TIMEOUT		3	/* timeout in i2c_doio()	*/
+#define I2CERR_QUEUE_EMPTY	4	/* i2c_doio called without send/receive */
+#define I2CERR_IO_ERROR		5	/* had an error during comms	*/
+
+/* error callback flags */
+#define I2CECB_RX_ERR		0x10	/* this is a receive error	*/
+#define     I2CECB_RX_OV	0x02	/* receive overrun error	*/
+#define     I2CECB_RX_MASK	0x0f	/* mask for error bits		*/
+#define I2CECB_TX_ERR		0x20	/* this is a transmit error	*/
+#define     I2CECB_TX_CL	0x01	/* transmit collision error	*/
+#define     I2CECB_TX_UN	0x02	/* transmit underflow error	*/
+#define     I2CECB_TX_NAK	0x04	/* transmit no ack error	*/
+#define     I2CECB_TX_MASK	0x0f	/* mask for error bits		*/
+#define I2CECB_TIMEOUT		0x40	/* this is a timeout error	*/
+
+#define ERROR_I2C_NONE		0
+#define ERROR_I2C_LENGTH	1
+
+#define I2C_WRITE_BIT		0x00
+#define I2C_READ_BIT		0x01
+
+#define I2C_RXTX_LEN	128	/* maximum tx/rx buffer length */
+
+
+#define NUM_RX_BDS 4
+#define NUM_TX_BDS 4
+#define MAX_TX_SPACE 256
+
+typedef struct I2C_BD
+{
+  unsigned short status;
+  unsigned short length;
+  unsigned char *addr;
+} I2C_BD;
+#define BD_I2C_TX_START 0x0400  /* special status for i2c: Start condition */
+
+#define BD_I2C_TX_CL	0x0001	/* collision error */
+#define BD_I2C_TX_UN	0x0002	/* underflow error */
+#define BD_I2C_TX_NAK	0x0004	/* no acknowledge error */
+#define BD_I2C_TX_ERR	(BD_I2C_TX_NAK|BD_I2C_TX_UN|BD_I2C_TX_CL)
+
+#define BD_I2C_RX_ERR	BD_SC_OV
+
+#ifdef DEBUG_I2C
+#define PRINTD(x) printf x
+#else
+#define PRINTD(x)
+#endif
+
+/*
+ * Returns the best value of I2BRG to meet desired clock speed of I2C with
+ * input parameters (clock speed, filter, and predivider value).
+ * It returns computer speed value and the difference between it and desired
+ * speed.
+ */
+static inline int
+i2c_roundrate(int hz, int speed, int filter, int modval,
+		int *brgval, int *totspeed)
+{
+    int moddiv = 1 << (5-(modval & 3)), brgdiv, div;
+
+    PRINTD(("\t[I2C] trying hz=%d, speed=%d, filter=%d, modval=%d\n",
+	hz, speed, filter, modval));
+
+    div = moddiv * speed;
+    brgdiv = (hz + div - 1) / div;
+
+    PRINTD(("\t\tmoddiv=%d, brgdiv=%d\n", moddiv, brgdiv));
+
+    *brgval = ((brgdiv + 1) / 2) - 3 - (2*filter);
+
+    if ((*brgval < 0) || (*brgval > 255)) {
+	  PRINTD(("\t\trejected brgval=%d\n", *brgval));
+	  return -1;
+    }
+
+    brgdiv = 2 * (*brgval + 3 + (2 * filter));
+    div = moddiv * brgdiv ;
+    *totspeed = hz / div;
+
+    PRINTD(("\t\taccepted brgval=%d, totspeed=%d\n", *brgval, *totspeed));
+
+    return  0;
+}
+
+/*
+ * Sets the I2C clock predivider and divider to meet required clock speed.
+ */
+static int i2c_setrate(int hz, int speed)
+{
+    immap_t	*immap = (immap_t *)CONFIG_SYS_IMMR ;
+    volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c;
+    int brgval,
+	  modval,	/* 0-3 */
+	  bestspeed_diff = speed,
+	  bestspeed_brgval=0,
+	  bestspeed_modval=0,
+	  bestspeed_filter=0,
+	  totspeed,
+	  filter = 0; /* Use this fixed value */
+
+	for (modval = 0; modval < 4; modval++)
+	{
+		if (i2c_roundrate (hz, speed, filter, modval, &brgval, &totspeed) == 0)
+		{
+			int diff = speed - totspeed ;
+
+			if ((diff >= 0) && (diff < bestspeed_diff))
+			{
+				bestspeed_diff	= diff ;
+				bestspeed_modval	= modval;
+				bestspeed_brgval	= brgval;
+				bestspeed_filter	= filter;
+			}
+		}
+	}
+
+    PRINTD(("[I2C] Best is:\n"));
+    PRINTD(("[I2C] CPU=%dhz RATE=%d F=%d I2MOD=%08x I2BRG=%08x DIFF=%dhz\n",
+		   hz, speed,
+		   bestspeed_filter, bestspeed_modval, bestspeed_brgval,
+		   bestspeed_diff));
+
+    i2c->i2c_i2mod |= ((bestspeed_modval & 3) << 1) | (bestspeed_filter << 3);
+    i2c->i2c_i2brg = bestspeed_brgval & 0xff;
+
+    PRINTD(("[I2C] i2mod=%08x i2brg=%08x\n", i2c->i2c_i2mod, i2c->i2c_i2brg));
+
+    return 1 ;
+}
+
+void i2c_init(int speed, int slaveadd)
+{
+	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR ;
+	volatile cpm8260_t *cp = (cpm8260_t *)&immap->im_cpm;
+	volatile i2c8260_t *i2c	= (i2c8260_t *)&immap->im_i2c;
+	volatile iic_t *iip;
+	ulong rbase, tbase;
+	volatile I2C_BD *rxbd, *txbd;
+	uint dpaddr;
+
+#ifdef CONFIG_SYS_I2C_INIT_BOARD
+	/* call board specific i2c bus reset routine before accessing the   */
+	/* environment, which might be in a chip on that bus. For details   */
+	/* about this problem see doc/I2C_Edge_Conditions.                  */
+	i2c_init_board();
+#endif
+
+	dpaddr = *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE]));
+	if (dpaddr == 0) {
+	    /* need to allocate dual port ram */
+	    dpaddr = m8260_cpm_dpalloc(64 +
+		(NUM_RX_BDS * sizeof(I2C_BD)) + (NUM_TX_BDS * sizeof(I2C_BD)) +
+		MAX_TX_SPACE, 64);
+	    *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE])) = dpaddr;
+	}
+
+	/*
+	 * initialise data in dual port ram:
+	 *
+	 *	  dpaddr -> parameter ram (64 bytes)
+	 *         rbase -> rx BD         (NUM_RX_BDS * sizeof(I2C_BD) bytes)
+	 *         tbase -> tx BD         (NUM_TX_BDS * sizeof(I2C_BD) bytes)
+	 *                  tx buffer     (MAX_TX_SPACE bytes)
+	 */
+
+	iip = (iic_t *)&immap->im_dprambase[dpaddr];
+	memset((void*)iip, 0, sizeof(iic_t));
+
+	rbase = dpaddr + 64;
+	tbase = rbase + NUM_RX_BDS * sizeof(I2C_BD);
+
+	/* Disable interrupts */
+	i2c->i2c_i2mod = 0x00;
+	i2c->i2c_i2cmr = 0x00;
+	i2c->i2c_i2cer = 0xff;
+	i2c->i2c_i2add = slaveadd;
+
+	/*
+	 * Set the I2C BRG Clock division factor from desired i2c rate
+	 * and current CPU rate (we assume sccr dfbgr field is 0;
+	 * divide BRGCLK by 1)
+	 */
+	PRINTD(("[I2C] Setting rate...\n"));
+	i2c_setrate (gd->brg_clk, CONFIG_SYS_I2C_SPEED) ;
+
+	/* Set I2C controller in master mode */
+	i2c->i2c_i2com = 0x01;
+
+	/* Initialize Tx/Rx parameters */
+	iip->iic_rbase = rbase;
+	iip->iic_tbase = tbase;
+	rxbd = (I2C_BD *)((unsigned char *)&immap->im_dprambase[iip->iic_rbase]);
+	txbd = (I2C_BD *)((unsigned char *)&immap->im_dprambase[iip->iic_tbase]);
+
+	PRINTD(("[I2C] rbase = %04x\n", iip->iic_rbase));
+	PRINTD(("[I2C] tbase = %04x\n", iip->iic_tbase));
+	PRINTD(("[I2C] rxbd = %08x\n", (int)rxbd));
+	PRINTD(("[I2C] txbd = %08x\n", (int)txbd));
+
+	/* Set big endian byte order */
+	iip->iic_tfcr = 0x10;
+	iip->iic_rfcr = 0x10;
+
+	/* Set maximum receive size. */
+	iip->iic_mrblr = I2C_RXTX_LEN;
+
+    cp->cp_cpcr = mk_cr_cmd(CPM_CR_I2C_PAGE,
+							CPM_CR_I2C_SBLOCK,
+							0x00,
+							CPM_CR_INIT_TRX) | CPM_CR_FLG;
+    do {
+		__asm__ __volatile__ ("eieio");
+    } while (cp->cp_cpcr & CPM_CR_FLG);
+
+	/* Clear events and interrupts */
+	i2c->i2c_i2cer = 0xff;
+	i2c->i2c_i2cmr = 0x00;
+}
+
+static
+void i2c_newio(i2c_state_t *state)
+{
+	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR ;
+	volatile iic_t *iip;
+	uint dpaddr;
+
+	PRINTD(("[I2C] i2c_newio\n"));
+
+	dpaddr = *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE]));
+	iip = (iic_t *)&immap->im_dprambase[dpaddr];
+	state->rx_idx = 0;
+	state->tx_idx = 0;
+	state->rxbd = (void*)&immap->im_dprambase[iip->iic_rbase];
+	state->txbd = (void*)&immap->im_dprambase[iip->iic_tbase];
+	state->tx_space = MAX_TX_SPACE;
+	state->tx_buf = (uchar*)state->txbd + NUM_TX_BDS * sizeof(I2C_BD);
+	state->err_cb = NULL;
+	state->cb_data = NULL;
+
+	PRINTD(("[I2C] rxbd = %08x\n", (int)state->rxbd));
+	PRINTD(("[I2C] txbd = %08x\n", (int)state->txbd));
+	PRINTD(("[I2C] tx_buf = %08x\n", (int)state->tx_buf));
+
+	/* clear the buffer memory */
+	memset((char *)state->tx_buf, 0, MAX_TX_SPACE);
+}
+
+static
+int i2c_send(i2c_state_t *state,
+			 unsigned char address,
+			 unsigned char secondary_address,
+			 unsigned int flags,
+			 unsigned short size,
+			 unsigned char *dataout)
+{
+	volatile I2C_BD *txbd;
+	int i,j;
+
+	PRINTD(("[I2C] i2c_send add=%02d sec=%02d flag=%02d size=%d\n",
+			address, secondary_address, flags, size));
+
+	/* trying to send message larger than BD */
+	if (size > I2C_RXTX_LEN)
+	  return I2CERR_MSG_TOO_LONG;
+
+	/* no more free bds */
+	if (state->tx_idx >= NUM_TX_BDS || state->tx_space < (2 + size))
+	  return I2CERR_NO_BUFFERS;
+
+	txbd = (I2C_BD *)state->txbd;
+	txbd->addr = state->tx_buf;
+
+	PRINTD(("[I2C] txbd = %08x\n", (int)txbd));
+
+    if (flags & I2CF_START_COND)
+    {
+	PRINTD(("[I2C] Formatting addresses...\n"));
+	if (flags & I2CF_ENABLE_SECONDARY)
+	{
+		txbd->length = size + 2;  /* Length of message plus dest addresses */
+		txbd->addr[0] = address << 1;
+		txbd->addr[1] = secondary_address;
+		i = 2;
+	}
+	else
+	{
+		txbd->length = size + 1;  /* Length of message plus dest address */
+		txbd->addr[0] = address << 1;  /* Write destination address to BD */
+		i = 1;
+	}
+    }
+    else
+    {
+	txbd->length = size;  /* Length of message */
+	i = 0;
+    }
+
+	/* set up txbd */
+	txbd->status = BD_SC_READY;
+	if (flags & I2CF_START_COND)
+	  txbd->status |= BD_I2C_TX_START;
+	if (flags & I2CF_STOP_COND)
+	  txbd->status |= BD_SC_LAST | BD_SC_WRAP;
+
+	/* Copy data to send into buffer */
+	PRINTD(("[I2C] copy data...\n"));
+	for(j = 0; j < size; i++, j++)
+	  txbd->addr[i] = dataout[j];
+
+	PRINTD(("[I2C] txbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+		   txbd->length,
+		   txbd->status,
+		   txbd->addr[0],
+		   txbd->addr[1]));
+
+	/* advance state */
+	state->tx_buf += txbd->length;
+	state->tx_space -= txbd->length;
+	state->tx_idx++;
+	state->txbd = (void*)(txbd + 1);
+
+	return 0;
+}
+
+static
+int i2c_receive(i2c_state_t *state,
+				unsigned char address,
+				unsigned char secondary_address,
+				unsigned int flags,
+				unsigned short size_to_expect,
+				unsigned char *datain)
+{
+	volatile I2C_BD *rxbd, *txbd;
+
+	PRINTD(("[I2C] i2c_receive %02d %02d %02d\n", address, secondary_address, flags));
+
+	/* Expected to receive too much */
+	if (size_to_expect > I2C_RXTX_LEN)
+	  return I2CERR_MSG_TOO_LONG;
+
+	/* no more free bds */
+	if (state->tx_idx >= NUM_TX_BDS || state->rx_idx >= NUM_RX_BDS
+		 || state->tx_space < 2)
+	  return I2CERR_NO_BUFFERS;
+
+	rxbd = (I2C_BD *)state->rxbd;
+	txbd = (I2C_BD *)state->txbd;
+
+	PRINTD(("[I2C] rxbd = %08x\n", (int)rxbd));
+	PRINTD(("[I2C] txbd = %08x\n", (int)txbd));
+
+	txbd->addr = state->tx_buf;
+
+	/* set up TXBD for destination address */
+	if (flags & I2CF_ENABLE_SECONDARY)
+	{
+		txbd->length = 2;
+		txbd->addr[0] = address << 1;   /* Write data */
+		txbd->addr[1] = secondary_address;  /* Internal address */
+		txbd->status = BD_SC_READY;
+	}
+	else
+	{
+		txbd->length = 1 + size_to_expect;
+		txbd->addr[0] = (address << 1) | 0x01;
+		txbd->status = BD_SC_READY;
+		memset(&txbd->addr[1], 0, txbd->length);
+	}
+
+	/* set up rxbd for reception */
+	rxbd->status = BD_SC_EMPTY;
+	rxbd->length = size_to_expect;
+	rxbd->addr = datain;
+
+	txbd->status |= BD_I2C_TX_START;
+	if (flags & I2CF_STOP_COND)
+	{
+		txbd->status |= BD_SC_LAST | BD_SC_WRAP;
+		rxbd->status |= BD_SC_WRAP;
+	}
+
+	PRINTD(("[I2C] txbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+		   txbd->length,
+		   txbd->status,
+		   txbd->addr[0],
+		   txbd->addr[1]));
+	PRINTD(("[I2C] rxbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+		   rxbd->length,
+		   rxbd->status,
+		   rxbd->addr[0],
+		   rxbd->addr[1]));
+
+	/* advance state */
+	state->tx_buf += txbd->length;
+	state->tx_space -= txbd->length;
+	state->tx_idx++;
+	state->txbd = (void*)(txbd + 1);
+	state->rx_idx++;
+	state->rxbd = (void*)(rxbd + 1);
+
+	return 0;
+}
+
+
+static
+int i2c_doio(i2c_state_t *state)
+{
+	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR ;
+	volatile iic_t *iip;
+	volatile i2c8260_t *i2c	= (i2c8260_t *)&immap->im_i2c;
+	volatile I2C_BD *txbd, *rxbd;
+	int  n, i, b, rxcnt = 0, rxtimeo = 0, txcnt = 0, txtimeo = 0, rc = 0;
+	uint dpaddr;
+
+	PRINTD(("[I2C] i2c_doio\n"));
+
+	if (state->tx_idx <= 0 && state->rx_idx <= 0) {
+		PRINTD(("[I2C] No I/O is queued\n"));
+		return I2CERR_QUEUE_EMPTY;
+	}
+
+	dpaddr = *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE]));
+	iip = (iic_t *)&immap->im_dprambase[dpaddr];
+	iip->iic_rbptr = iip->iic_rbase;
+	iip->iic_tbptr = iip->iic_tbase;
+
+	/* Enable I2C */
+	PRINTD(("[I2C] Enabling I2C...\n"));
+	i2c->i2c_i2mod |= 0x01;
+
+	/* Begin transmission */
+	i2c->i2c_i2com |= 0x80;
+
+	/* Loop until transmit & receive completed */
+
+	if ((n = state->tx_idx) > 0) {
+
+		txbd = ((I2C_BD*)state->txbd) - n;
+		for (i = 0; i < n; i++) {
+			txtimeo += TOUT_LOOP * txbd->length;
+			txbd++;
+		}
+
+		txbd--; /* wait until last in list is done */
+
+		PRINTD(("[I2C] Transmitting...(txbd=0x%08lx)\n", (ulong)txbd));
+
+		udelay(START_DELAY_US);	/* give it time to start */
+		while((txbd->status & BD_SC_READY) && (++txcnt < txtimeo)) {
+			udelay(DELAY_US);
+			if (ctrlc())
+				return (-1);
+			__asm__ __volatile__ ("eieio");
+		}
+	}
+
+	if (txcnt < txtimeo && (n = state->rx_idx) > 0) {
+
+		rxbd = ((I2C_BD*)state->rxbd) - n;
+		for (i = 0; i < n; i++) {
+			rxtimeo += TOUT_LOOP * rxbd->length;
+			rxbd++;
+		}
+
+		rxbd--; /* wait until last in list is done */
+
+		PRINTD(("[I2C] Receiving...(rxbd=0x%08lx)\n", (ulong)rxbd));
+
+		udelay(START_DELAY_US);	/* give it time to start */
+		while((rxbd->status & BD_SC_EMPTY) && (++rxcnt < rxtimeo)) {
+			udelay(DELAY_US);
+			if (ctrlc())
+				return (-1);
+			__asm__ __volatile__ ("eieio");
+		}
+	}
+
+	/* Turn off I2C */
+	i2c->i2c_i2mod &= ~0x01;
+
+	if ((n = state->tx_idx) > 0) {
+		for (i = 0; i < n; i++) {
+			txbd = ((I2C_BD*)state->txbd) - (n - i);
+			if ((b = txbd->status & BD_I2C_TX_ERR) != 0) {
+				if (state->err_cb != NULL)
+					(*state->err_cb)(I2CECB_TX_ERR|b, i,
+						state->cb_data);
+				if (rc == 0)
+					rc = I2CERR_IO_ERROR;
+			}
+		}
+	}
+
+	if ((n = state->rx_idx) > 0) {
+		for (i = 0; i < n; i++) {
+			rxbd = ((I2C_BD*)state->rxbd) - (n - i);
+			if ((b = rxbd->status & BD_I2C_RX_ERR) != 0) {
+				if (state->err_cb != NULL)
+					(*state->err_cb)(I2CECB_RX_ERR|b, i,
+						state->cb_data);
+				if (rc == 0)
+					rc = I2CERR_IO_ERROR;
+			}
+		}
+	}
+
+	if ((txtimeo > 0 && txcnt >= txtimeo) || \
+	    (rxtimeo > 0 && rxcnt >= rxtimeo)) {
+		if (state->err_cb != NULL)
+			(*state->err_cb)(I2CECB_TIMEOUT, -1, state->cb_data);
+		if (rc == 0)
+			rc = I2CERR_TIMEOUT;
+	}
+
+	return (rc);
+}
+
+static void
+i2c_probe_callback(int flags, int xnum, void *data)
+{
+	/*
+	 * the only acceptable errors are a transmit NAK or a receive
+	 * overrun - tx NAK means the device does not exist, rx OV
+	 * means the device must have responded to the slave address
+	 * even though the transfer failed
+	 */
+	if (flags == (I2CECB_TX_ERR|I2CECB_TX_NAK))
+		*(int *)data |= 1;
+	if (flags == (I2CECB_RX_ERR|I2CECB_RX_OV))
+		*(int *)data |= 2;
+}
+
+int
+i2c_probe(uchar chip)
+{
+	i2c_state_t state;
+	int rc, err_flag;
+	uchar buf[1];
+
+	i2c_newio(&state);
+
+	state.err_cb = i2c_probe_callback;
+	state.cb_data = (void *) &err_flag;
+	err_flag = 0;
+
+	rc = i2c_receive(&state, chip, 0, I2CF_START_COND|I2CF_STOP_COND, 1, buf);
+
+	if (rc != 0)
+		return (rc);	/* probe failed */
+
+	rc = i2c_doio(&state);
+
+	if (rc == 0)
+		return (0);	/* device exists - read succeeded */
+
+	if (rc == I2CERR_TIMEOUT)
+		return (-1);	/* device does not exist - timeout */
+
+	if (rc != I2CERR_IO_ERROR || err_flag == 0)
+		return (rc);	/* probe failed */
+
+	if (err_flag & 1)
+		return (-1);	/* device does not exist - had transmit NAK */
+
+	return (0);	/* device exists - had receive overrun */
+}
+
+
+int
+i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	i2c_state_t state;
+	uchar xaddr[4];
+	int rc;
+
+	xaddr[0] = (addr >> 24) & 0xFF;
+	xaddr[1] = (addr >> 16) & 0xFF;
+	xaddr[2] = (addr >>  8) & 0xFF;
+	xaddr[3] =  addr        & 0xFF;
+
+#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
+	 /*
+	  * EEPROM chips that implement "address overflow" are ones
+	  * like Catalyst 24WC04/08/16 which has 9/10/11 bits of address
+	  * and the extra bits end up in the "chip address" bit slots.
+	  * This makes a 24WC08 (1Kbyte) chip look like four 256 byte
+	  * chips.
+	  *
+	  * Note that we consider the length of the address field to still
+	  * be one byte because the extra address bits are hidden in the
+	  * chip address.
+	  */
+	chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
+#endif
+
+	i2c_newio(&state);
+
+	rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen, &xaddr[4-alen]);
+	if (rc != 0) {
+		printf("i2c_read: i2c_send failed (%d)\n", rc);
+		return 1;
+	}
+
+	rc = i2c_receive(&state, chip, 0, I2CF_STOP_COND, len, buffer);
+	if (rc != 0) {
+		printf("i2c_read: i2c_receive failed (%d)\n", rc);
+		return 1;
+	}
+
+	rc = i2c_doio(&state);
+	if (rc != 0) {
+		printf("i2c_read: i2c_doio failed (%d)\n", rc);
+		return 1;
+	}
+	return 0;
+}
+
+int
+i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	i2c_state_t state;
+	uchar xaddr[4];
+	int rc;
+
+	xaddr[0] = (addr >> 24) & 0xFF;
+	xaddr[1] = (addr >> 16) & 0xFF;
+	xaddr[2] = (addr >>  8) & 0xFF;
+	xaddr[3] =  addr        & 0xFF;
+
+#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
+	 /*
+	  * EEPROM chips that implement "address overflow" are ones
+	  * like Catalyst 24WC04/08/16 which has 9/10/11 bits of address
+	  * and the extra bits end up in the "chip address" bit slots.
+	  * This makes a 24WC08 (1Kbyte) chip look like four 256 byte
+	  * chips.
+	  *
+	  * Note that we consider the length of the address field to still
+	  * be one byte because the extra address bits are hidden in the
+	  * chip address.
+	  */
+	chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
+#endif
+
+	i2c_newio(&state);
+
+	rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen, &xaddr[4-alen]);
+	if (rc != 0) {
+		printf("i2c_write: first i2c_send failed (%d)\n", rc);
+		return 1;
+	}
+
+	rc = i2c_send(&state, 0, 0, I2CF_STOP_COND, len, buffer);
+	if (rc != 0) {
+		printf("i2c_write: second i2c_send failed (%d)\n", rc);
+		return 1;
+	}
+
+	rc = i2c_doio(&state);
+	if (rc != 0) {
+		printf("i2c_write: i2c_doio failed (%d)\n", rc);
+		return 1;
+	}
+	return 0;
+}
+
+#if defined(CONFIG_I2C_MULTI_BUS)
+/*
+ * Functions for multiple I2C bus handling
+ */
+unsigned int i2c_get_bus_num(void)
+{
+	return i2c_bus_num;
+}
+
+int i2c_set_bus_num(unsigned int bus)
+{
+#if defined(CONFIG_I2C_MUX)
+	if (bus < CONFIG_SYS_MAX_I2C_BUS) {
+		i2c_bus_num = bus;
+	} else {
+		int	ret;
+
+		ret = i2x_mux_select_mux(bus);
+		if (ret == 0)
+			i2c_bus_num = bus;
+		else
+			return ret;
+	}
+#else
+	if (bus >= CONFIG_SYS_MAX_I2C_BUS)
+		return -1;
+	i2c_bus_num = bus;
+#endif
+	return 0;
+}
+
+#endif	/* CONFIG_I2C_MULTI_BUS */
+#endif	/* CONFIG_HARD_I2C */
diff --git a/arch/powerpc/cpu/mpc8260/interrupts.c b/arch/powerpc/cpu/mpc8260/interrupts.c
new file mode 100644
index 0000000..2606c60
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/interrupts.c
@@ -0,0 +1,279 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 22-Oct-00
+ */
+
+#include <common.h>
+#include <command.h>
+#include <mpc8260.h>
+#include <mpc8260_irq.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/****************************************************************************/
+
+struct irq_action {
+	interrupt_handler_t *handler;
+	void *arg;
+	ulong count;
+};
+
+static struct irq_action irq_handlers[NR_IRQS];
+
+static ulong ppc_cached_irq_mask[NR_MASK_WORDS];
+
+/****************************************************************************/
+/* this section was ripped out of arch/powerpc/kernel/ppc8260_pic.c in the	    */
+/* Linux/PPC 2.4.x source. There was no copyright notice in that file.	    */
+
+/* The 8260 internal interrupt controller.  It is usually
+ * the only interrupt controller.
+ * There are two 32-bit registers (high/low) for up to 64
+ * possible interrupts.
+ *
+ * Now, the fun starts.....Interrupt Numbers DO NOT MAP
+ * in a simple arithmetic fashion to mask or pending registers.
+ * That is, interrupt 4 does not map to bit position 4.
+ * We create two tables, indexed by vector number, to indicate
+ * which register to use and which bit in the register to use.
+ */
+static u_char irq_to_siureg[] = {
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static u_char irq_to_siubit[] = {
+	31, 16, 17, 18, 19, 20, 21, 22,
+	23, 24, 25, 26, 27, 28, 29, 30,
+	29, 30, 16, 17, 18, 19, 20, 21,
+	22, 23, 24, 25, 26, 27, 28, 31,
+	0, 1, 2, 3, 4, 5, 6, 7,
+	8, 9, 10, 11, 12, 13, 14, 15,
+	15, 14, 13, 12, 11, 10, 9, 8,
+	7, 6, 5, 4, 3, 2, 1, 0
+};
+
+static void m8260_mask_irq (unsigned int irq_nr)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	int bit, word;
+	volatile uint *simr;
+
+	bit = irq_to_siubit[irq_nr];
+	word = irq_to_siureg[irq_nr];
+
+	simr = &(immr->im_intctl.ic_simrh);
+	ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+	simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void m8260_unmask_irq (unsigned int irq_nr)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	int bit, word;
+	volatile uint *simr;
+
+	bit = irq_to_siubit[irq_nr];
+	word = irq_to_siureg[irq_nr];
+
+	simr = &(immr->im_intctl.ic_simrh);
+	ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+	simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void m8260_mask_and_ack (unsigned int irq_nr)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	int bit, word;
+	volatile uint *simr, *sipnr;
+
+	bit = irq_to_siubit[irq_nr];
+	word = irq_to_siureg[irq_nr];
+
+	simr = &(immr->im_intctl.ic_simrh);
+	sipnr = &(immr->im_intctl.ic_sipnrh);
+	ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+	simr[word] = ppc_cached_irq_mask[word];
+	sipnr[word] = 1 << (31 - bit);
+}
+
+static int m8260_get_irq (struct pt_regs *regs)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	int irq;
+	unsigned long bits;
+
+	/* For MPC8260, read the SIVEC register and shift the bits down
+	 * to get the irq number.         */
+	bits = immr->im_intctl.ic_sivec;
+	irq = bits >> 26;
+	return irq;
+}
+
+/* end of code ripped out of arch/powerpc/kernel/ppc8260_pic.c		    */
+/****************************************************************************/
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+	*decrementer_count = (gd->bus_clk / 4) / CONFIG_SYS_HZ;
+
+	/* Initialize the default interrupt mapping priorities */
+	immr->im_intctl.ic_sicr = 0;
+	immr->im_intctl.ic_siprr = 0x05309770;
+	immr->im_intctl.ic_scprrh = 0x05309770;
+	immr->im_intctl.ic_scprrl = 0x05309770;
+
+	/* disable all interrupts and clear all pending bits */
+	immr->im_intctl.ic_simrh = ppc_cached_irq_mask[0] = 0;
+	immr->im_intctl.ic_simrl = ppc_cached_irq_mask[1] = 0;
+	immr->im_intctl.ic_sipnrh = 0xffffffff;
+	immr->im_intctl.ic_sipnrl = 0xffffffff;
+
+#ifdef CONFIG_HYMOD
+	/*
+	 * ensure all external interrupt sources default to trigger on
+	 * high-to-low transition (i.e. edge triggered active low)
+	 */
+	immr->im_intctl.ic_siexr = -1;
+#endif
+
+	return (0);
+}
+
+/****************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt (struct pt_regs *regs)
+{
+	int irq, unmask = 1;
+
+	irq = m8260_get_irq (regs);
+
+	m8260_mask_and_ack (irq);
+
+	enable_interrupts ();
+
+	if (irq_handlers[irq].handler != NULL)
+		(*irq_handlers[irq].handler) (irq_handlers[irq].arg);
+	else {
+		printf ("\nBogus External Interrupt IRQ %d\n", irq);
+		/*
+		 * turn off the bogus interrupt, otherwise it
+		 * might repeat forever
+		 */
+		unmask = 0;
+	}
+
+	if (unmask)
+		m8260_unmask_irq (irq);
+}
+
+/****************************************************************************/
+
+/*
+ * Install and free an interrupt handler.
+ */
+
+void
+irq_install_handler (int irq, interrupt_handler_t * handler, void *arg)
+{
+	if (irq < 0 || irq >= NR_IRQS) {
+		printf ("irq_install_handler: bad irq number %d\n", irq);
+		return;
+	}
+
+	if (irq_handlers[irq].handler != NULL)
+		printf ("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
+				(ulong) handler, (ulong) irq_handlers[irq].handler);
+
+	irq_handlers[irq].handler = handler;
+	irq_handlers[irq].arg = arg;
+
+	m8260_unmask_irq (irq);
+}
+
+void irq_free_handler (int irq)
+{
+	if (irq < 0 || irq >= NR_IRQS) {
+		printf ("irq_free_handler: bad irq number %d\n", irq);
+		return;
+	}
+
+	m8260_mask_irq (irq);
+
+	irq_handlers[irq].handler = NULL;
+	irq_handlers[irq].arg = NULL;
+}
+
+/****************************************************************************/
+
+void timer_interrupt_cpu (struct pt_regs *regs)
+{
+	/* nothing to do here */
+	return;
+}
+
+/****************************************************************************/
+
+#if defined(CONFIG_CMD_IRQ)
+
+/* ripped this out of ppc4xx/interrupts.c */
+
+/*******************************************************************************
+*
+* irqinfo - print information about PCI devices
+*
+*/
+void
+do_irqinfo (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
+{
+	int irq, re_enable;
+
+	re_enable = disable_interrupts ();
+
+	puts ("\nInterrupt-Information:\n"
+		"Nr  Routine   Arg       Count\n");
+
+	for (irq = 0; irq < 32; irq++)
+		if (irq_handlers[irq].handler != NULL)
+			printf ("%02d  %08lx  %08lx  %ld\n", irq,
+					(ulong) irq_handlers[irq].handler,
+					(ulong) irq_handlers[irq].arg,
+					irq_handlers[irq].count);
+
+	if (re_enable)
+		enable_interrupts ();
+}
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8260/kgdb.S b/arch/powerpc/cpu/mpc8260/kgdb.S
new file mode 100644
index 0000000..c5936c7
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/kgdb.S
@@ -0,0 +1,72 @@
+/*
+ *  Copyright (C) 2000	Murray Jensen <Murray.Jensen@cmst.csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <command.h>
+#include <mpc8260.h>
+#include <version.h>
+
+#define CONFIG_8260 1		/* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1	/* avoid reading Linux autoconf.h file	*/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#if defined(CONFIG_CMD_KGDB)
+
+ /*
+ * cache flushing routines for kgdb
+ */
+
+	.globl	kgdb_flush_cache_all
+kgdb_flush_cache_all:
+	mfspr	r3, HID0
+	ori	r3, r3, HID0_ICFI|HID0_DCI	/* Invalidate All */
+	SYNC
+	mtspr	HID0, r3
+	blr
+
+	.globl	kgdb_flush_cache_range
+kgdb_flush_cache_range:
+	li	r5,CONFIG_SYS_CACHELINE_SIZE-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,CONFIG_SYS_CACHELINE_SHIFT
+	beqlr
+	mtctr	r4
+	mr	r6,r3
+1:	dcbst	0,r3
+	addi	r3,r3,CONFIG_SYS_CACHELINE_SIZE
+	bdnz	1b
+	sync				/* wait for dcbst's to get to ram */
+	mtctr	r4
+2:	icbi	0,r6
+	addi	r6,r6,CONFIG_SYS_CACHELINE_SIZE
+	bdnz	2b
+	SYNC
+	blr
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8260/pci.c b/arch/powerpc/cpu/mpc8260/pci.c
new file mode 100644
index 0000000..6a14ba4
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/pci.c
@@ -0,0 +1,466 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (c) 2005 MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ * Added support for PCI bridge on MPC8272ADS
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_PCI
+
+#include <pci.h>
+#include <mpc8260.h>
+#include <asm/m8260_pci.h>
+#include <asm/io.h>
+#ifdef CONFIG_OF_LIBFDT
+#include <libfdt.h>
+#include <fdt_support.h>
+#endif
+
+#if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272 || defined CONFIG_PM826
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+/*
+ *   Local->PCI map (from CPU)				   controlled by
+ *   MPC826x master window
+ *
+ *   0x80000000 - 0xBFFFFFFF	CPU2PCI space		   PCIBR0
+ *   0xF4000000 - 0xF7FFFFFF	CPU2PCI space		   PCIBR1
+ *
+ *   0x80000000 - 0x9FFFFFFF	0x80000000 - 0x9FFFFFFF	  (Outbound ATU #1)
+ *				PCI Mem with prefetch
+ *
+ *   0xA0000000 - 0xBFFFFFFF	0xA0000000 - 0xBFFFFFFF	  (Outbound ATU #2)
+ *				PCI Mem w/o  prefetch
+ *
+ *   0xF4000000 - 0xF7FFFFFF	0x00000000 - 0x03FFFFFF	  (Outbound ATU #3)
+ *				32-bit PCI IO
+ *
+ *   PCI->Local map (from PCI)
+ *   MPC826x slave window				   controlled by
+ *
+ *   0x00000000 - 0x1FFFFFFF	0x00000000 - 0x1FFFFFFF	  (Inbound ATU #1)
+ *				MPC826x local memory
+ */
+
+/*
+ * Slave window that allows PCI masters to access MPC826x local memory.
+ * This window is set up using the first set of Inbound ATU registers
+ */
+
+#ifndef CONFIG_SYS_PCI_SLV_MEM_LOCAL
+#define PCI_SLV_MEM_LOCAL CONFIG_SYS_SDRAM_BASE	/* Local base */
+#else
+#define PCI_SLV_MEM_LOCAL CONFIG_SYS_PCI_SLV_MEM_LOCAL
+#endif
+
+#ifndef CONFIG_SYS_PCI_SLV_MEM_BUS
+#define PCI_SLV_MEM_BUS 0x00000000	/* PCI base */
+#else
+#define PCI_SLV_MEM_BUS CONFIG_SYS_PCI_SLV_MEM_BUS
+#endif
+
+#ifndef CONFIG_SYS_PICMR0_MASK_ATTRIB
+#define PICMR0_MASK_ATTRIB	(PICMR_MASK_512MB | PICMR_ENABLE | \
+				 PICMR_PREFETCH_EN)
+#else
+#define PICMR0_MASK_ATTRIB CONFIG_SYS_PICMR0_MASK_ATTRIB
+#endif
+
+/*
+ * These are the windows that allow the CPU to access PCI address space.
+ * All three PCI master windows, which allow the CPU to access PCI
+ * prefetch, non prefetch, and IO space (see below), must all fit within
+ * these windows.
+ */
+
+/* PCIBR0 */
+#ifndef CONFIG_SYS_PCI_MSTR0_LOCAL
+#define PCI_MSTR0_LOCAL		0x80000000	/* Local base */
+#else
+#define PCI_MSTR0_LOCAL CONFIG_SYS_PCI_MSTR0_LOCAL
+#endif
+
+#ifndef CONFIG_SYS_PCIMSK0_MASK
+#define PCIMSK0_MASK		PCIMSK_1GB	/* Size of window */
+#else
+#define PCIMSK0_MASK	CONFIG_SYS_PCIMSK0_MASK
+#endif
+
+/* PCIBR1 */
+#ifndef CONFIG_SYS_PCI_MSTR1_LOCAL
+#define PCI_MSTR1_LOCAL		0xF4000000	/* Local base */
+#else
+#define PCI_MSTR1_LOCAL		CONFIG_SYS_PCI_MSTR1_LOCAL
+#endif
+
+#ifndef CONFIG_SYS_PCIMSK1_MASK
+#define	 PCIMSK1_MASK		PCIMSK_64MB	/* Size of window */
+#else
+#define	 PCIMSK1_MASK		CONFIG_SYS_PCIMSK1_MASK
+#endif
+
+/*
+ * Master window that allows the CPU to access PCI Memory (prefetch).
+ * This window will be setup with the first set of Outbound ATU registers
+ * in the bridge.
+ */
+
+#ifndef CONFIG_SYS_PCI_MSTR_MEM_LOCAL
+#define PCI_MSTR_MEM_LOCAL 0x80000000	/* Local base */
+#else
+#define PCI_MSTR_MEM_LOCAL CONFIG_SYS_PCI_MSTR_MEM_LOCAL
+#endif
+
+#ifndef CONFIG_SYS_PCI_MSTR_MEM_BUS
+#define PCI_MSTR_MEM_BUS 0x80000000	/* PCI base   */
+#else
+#define PCI_MSTR_MEM_BUS CONFIG_SYS_PCI_MSTR_MEM_BUS
+#endif
+
+#ifndef CONFIG_SYS_CPU_PCI_MEM_START
+#define CPU_PCI_MEM_START PCI_MSTR_MEM_LOCAL
+#else
+#define CPU_PCI_MEM_START CONFIG_SYS_CPU_PCI_MEM_START
+#endif
+
+#ifndef CONFIG_SYS_PCI_MSTR_MEM_SIZE
+#define PCI_MSTR_MEM_SIZE 0x10000000	/* 256MB */
+#else
+#define PCI_MSTR_MEM_SIZE CONFIG_SYS_PCI_MSTR_MEM_SIZE
+#endif
+
+#ifndef CONFIG_SYS_POCMR0_MASK_ATTRIB
+#define POCMR0_MASK_ATTRIB	(POCMR_MASK_256MB | POCMR_ENABLE | POCMR_PREFETCH_EN)
+#else
+#define POCMR0_MASK_ATTRIB CONFIG_SYS_POCMR0_MASK_ATTRIB
+#endif
+
+/*
+ * Master window that allows the CPU to access PCI Memory (non-prefetch).
+ * This window will be setup with the second set of Outbound ATU registers
+ * in the bridge.
+ */
+
+#ifndef CONFIG_SYS_PCI_MSTR_MEMIO_LOCAL
+#define PCI_MSTR_MEMIO_LOCAL 0x90000000 /* Local base */
+#else
+#define PCI_MSTR_MEMIO_LOCAL CONFIG_SYS_PCI_MSTR_MEMIO_LOCAL
+#endif
+
+#ifndef CONFIG_SYS_PCI_MSTR_MEMIO_BUS
+#define PCI_MSTR_MEMIO_BUS 0x90000000	/* PCI base   */
+#else
+#define PCI_MSTR_MEMIO_BUS CONFIG_SYS_PCI_MSTR_MEMIO_BUS
+#endif
+
+#ifndef CONFIG_SYS_CPU_PCI_MEMIO_START
+#define CPU_PCI_MEMIO_START PCI_MSTR_MEMIO_LOCAL
+#else
+#define CPU_PCI_MEMIO_START CONFIG_SYS_CPU_PCI_MEMIO_START
+#endif
+
+#ifndef CONFIG_SYS_PCI_MSTR_MEMIO_SIZE
+#define PCI_MSTR_MEMIO_SIZE 0x10000000	/* 256 MB */
+#else
+#define PCI_MSTR_MEMIO_SIZE CONFIG_SYS_PCI_MSTR_MEMIO_SIZE
+#endif
+
+#ifndef CONFIG_SYS_POCMR1_MASK_ATTRIB
+#define POCMR1_MASK_ATTRIB	(POCMR_MASK_512MB | POCMR_ENABLE)
+#else
+#define POCMR1_MASK_ATTRIB CONFIG_SYS_POCMR1_MASK_ATTRIB
+#endif
+
+/*
+ * Master window that allows the CPU to access PCI IO space.
+ * This window will be setup with the third set of Outbound ATU registers
+ * in the bridge.
+ */
+
+#ifndef CONFIG_SYS_PCI_MSTR_IO_LOCAL
+#define PCI_MSTR_IO_LOCAL 0xA0000000	/* Local base */
+#else
+#define PCI_MSTR_IO_LOCAL CONFIG_SYS_PCI_MSTR_IO_LOCAL
+#endif
+
+#ifndef CONFIG_SYS_PCI_MSTR_IO_BUS
+#define PCI_MSTR_IO_BUS 0xA0000000	/* PCI base   */
+#else
+#define PCI_MSTR_IO_BUS CONFIG_SYS_PCI_MSTR_IO_BUS
+#endif
+
+#ifndef CONFIG_SYS_CPU_PCI_IO_START
+#define CPU_PCI_IO_START PCI_MSTR_IO_LOCAL
+#else
+#define CPU_PCI_IO_START CONFIG_SYS_CPU_PCI_IO_START
+#endif
+
+#ifndef CONFIG_SYS_PCI_MSTR_IO_SIZE
+#define PCI_MSTR_IO_SIZE 0x10000000	/* 256MB */
+#else
+#define PCI_MSTR_IO_SIZE CONFIG_SYS_PCI_MSTR_IO_SIZE
+#endif
+
+#ifndef CONFIG_SYS_POCMR2_MASK_ATTRIB
+#define POCMR2_MASK_ATTRIB	(POCMR_MASK_256MB | POCMR_ENABLE | POCMR_PCI_IO)
+#else
+#define POCMR2_MASK_ATTRIB CONFIG_SYS_POCMR2_MASK_ATTRIB
+#endif
+
+/* PCI bus configuration registers.
+ */
+
+#define PCI_CLASS_BRIDGE_CTLR	0x06
+
+
+static inline void pci_outl (u32 addr, u32 data)
+{
+	*(volatile u32 *) addr = cpu_to_le32 (data);
+}
+
+void pci_mpc8250_init (struct pci_controller *hose)
+{
+	u16 tempShort;
+
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	pci_dev_t host_devno = PCI_BDF (0, 0, 0);
+
+	pci_setup_indirect (hose, CONFIG_SYS_IMMR + PCI_CFG_ADDR_REG,
+			    CONFIG_SYS_IMMR + PCI_CFG_DATA_REG);
+
+	/*
+	 * Setting required to enable local bus for PCI (SIUMCR [LBPC]).
+	 */
+#ifdef CONFIG_MPC8266ADS
+	immap->im_siu_conf.sc_siumcr =
+		(immap->im_siu_conf.sc_siumcr & ~SIUMCR_LBPC11)
+		| SIUMCR_LBPC01;
+#elif defined(CONFIG_ADSTYPE) && CONFIG_ADSTYPE == CONFIG_SYS_PQ2FADS
+/* nothing to do for this board here */
+#elif defined CONFIG_MPC8272
+	immap->im_siu_conf.sc_siumcr = (immap->im_siu_conf.sc_siumcr &
+				  ~SIUMCR_BBD &
+				  ~SIUMCR_ESE &
+				  ~SIUMCR_PBSE &
+				  ~SIUMCR_CDIS &
+				  ~SIUMCR_DPPC11 &
+				  ~SIUMCR_L2CPC11 &
+				  ~SIUMCR_LBPC11 &
+				  ~SIUMCR_APPC11 &
+				  ~SIUMCR_CS10PC11 &
+				  ~SIUMCR_BCTLC11 &
+				  ~SIUMCR_MMR11)
+				  | SIUMCR_DPPC11
+				  | SIUMCR_L2CPC01
+				  | SIUMCR_LBPC00
+				  | SIUMCR_APPC10
+				  | SIUMCR_CS10PC00
+				  | SIUMCR_BCTLC00
+				  | SIUMCR_MMR11;
+#elif defined(CONFIG_TQM8272)
+/* nothing to do for this Board here */
+#else
+	/*
+	 * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]),
+	 * and local bus for PCI (SIUMCR [LBPC]).
+	 */
+	immap->im_siu_conf.sc_siumcr = (immap->im_siu_conf.sc_siumcr &
+						~SIUMCR_LBPC11 &
+						~SIUMCR_CS10PC11 &
+						~SIUMCR_LBPC11) |
+					SIUMCR_LBPC01 |
+					SIUMCR_CS10PC01 |
+					SIUMCR_APPC10;
+#endif
+
+	/* Make PCI lowest priority */
+	/* Each 4 bits is a device bus request	and the MS 4bits
+	   is highest priority */
+	/* Bus		     4bit value
+	   ---		     ----------
+	   CPM high	     0b0000
+	   CPM middle	     0b0001
+	   CPM low	     0b0010
+	   PCI reguest	     0b0011
+	   Reserved	     0b0100
+	   Reserved	     0b0101
+	   Internal Core     0b0110
+	   External Master 1 0b0111
+	   External Master 2 0b1000
+	   External Master 3 0b1001
+	   The rest are reserved */
+	immap->im_siu_conf.sc_ppc_alrh = 0x61207893;
+
+	/* Park bus on core while modifying PCI Bus accesses */
+	immap->im_siu_conf.sc_ppc_acr = 0x6;
+
+	/*
+	 * Set up master windows that allow the CPU to access PCI space. These
+	 * windows are set up using the two SIU PCIBR registers.
+	 */
+	immap->im_memctl.memc_pcimsk0 = PCIMSK0_MASK;
+	immap->im_memctl.memc_pcibr0 = PCI_MSTR0_LOCAL | PCIBR_ENABLE;
+
+#if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272
+	immap->im_memctl.memc_pcimsk1 = PCIMSK1_MASK;
+	immap->im_memctl.memc_pcibr1 = PCI_MSTR1_LOCAL | PCIBR_ENABLE;
+#endif
+
+	/* Release PCI RST (by default the PCI RST signal is held low)	*/
+	immap->im_pci.pci_gcr = cpu_to_le32 (PCIGCR_PCI_BUS_EN);
+
+	/* give it some time */
+	{
+#if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272
+		/* Give the PCI cards more time to initialize before query
+		   This might be good for other boards also
+		 */
+		int i;
+
+		for (i = 0; i < 1000; ++i)
+#endif
+			udelay (1000);
+	}
+
+	/*
+	 * Set up master window that allows the CPU to access PCI Memory (prefetch)
+	 * space. This window is set up using the first set of Outbound ATU registers.
+	 */
+	immap->im_pci.pci_potar0 = cpu_to_le32 (PCI_MSTR_MEM_BUS >> 12);	/* PCI base */
+	immap->im_pci.pci_pobar0 = cpu_to_le32 (PCI_MSTR_MEM_LOCAL >> 12);	/* Local base */
+	immap->im_pci.pci_pocmr0 = cpu_to_le32 (POCMR0_MASK_ATTRIB);	/* Size & attribute */
+
+	/*
+	 * Set up master window that allows the CPU to access PCI Memory (non-prefetch)
+	 * space. This window is set up using the second set of Outbound ATU registers.
+	 */
+	immap->im_pci.pci_potar1 = cpu_to_le32 (PCI_MSTR_MEMIO_BUS >> 12);	/* PCI base */
+	immap->im_pci.pci_pobar1 = cpu_to_le32 (PCI_MSTR_MEMIO_LOCAL >> 12);	/* Local base */
+	immap->im_pci.pci_pocmr1 = cpu_to_le32 (POCMR1_MASK_ATTRIB);	/* Size & attribute */
+
+	/*
+	 * Set up master window that allows the CPU to access PCI IO space. This window
+	 * is set up using the third set of Outbound ATU registers.
+	 */
+	immap->im_pci.pci_potar2 = cpu_to_le32 (PCI_MSTR_IO_BUS >> 12); /* PCI base */
+	immap->im_pci.pci_pobar2 = cpu_to_le32 (PCI_MSTR_IO_LOCAL >> 12);	/* Local base */
+	immap->im_pci.pci_pocmr2 = cpu_to_le32 (POCMR2_MASK_ATTRIB);	/* Size & attribute */
+
+	/*
+	 * Set up slave window that allows PCI masters to access MPC826x local memory.
+	 * This window is set up using the first set of Inbound ATU registers
+	 */
+	immap->im_pci.pci_pitar0 = cpu_to_le32 (PCI_SLV_MEM_LOCAL >> 12);	/* PCI base */
+	immap->im_pci.pci_pibar0 = cpu_to_le32 (PCI_SLV_MEM_BUS >> 12); /* Local base */
+	immap->im_pci.pci_picmr0 = cpu_to_le32 (PICMR0_MASK_ATTRIB);	/* Size & attribute */
+
+	/* See above for description - puts PCI request as highest priority */
+#ifdef CONFIG_MPC8272
+	immap->im_siu_conf.sc_ppc_alrh = 0x01236745;
+#else
+	immap->im_siu_conf.sc_ppc_alrh = 0x03124567;
+#endif
+
+	/* Park the bus on the PCI */
+	immap->im_siu_conf.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
+
+	/* Host mode - specify the bridge as a host-PCI bridge */
+
+	pci_hose_write_config_byte (hose, host_devno, PCI_CLASS_CODE,
+				    PCI_CLASS_BRIDGE_CTLR);
+
+	/* Enable the host bridge to be a master on the PCI bus, and to act as a PCI memory target */
+	pci_hose_read_config_word (hose, host_devno, PCI_COMMAND, &tempShort);
+	pci_hose_write_config_word (hose, host_devno, PCI_COMMAND,
+				    tempShort | PCI_COMMAND_MASTER |
+				    PCI_COMMAND_MEMORY);
+
+	/* do some bridge init, should be done on all 8260 based bridges */
+	pci_hose_write_config_byte (hose, host_devno, PCI_CACHE_LINE_SIZE,
+				    0x08);
+	pci_hose_write_config_byte (hose, host_devno, PCI_LATENCY_TIMER,
+				    0xF8);
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	/* System memory space */
+#if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272 || defined CONFIG_PM826
+	pci_set_region (hose->regions + 0,
+			PCI_SLV_MEM_BUS,
+			PCI_SLV_MEM_LOCAL,
+			gd->ram_size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+#else
+	pci_set_region (hose->regions + 0,
+			CONFIG_SYS_SDRAM_BASE,
+			CONFIG_SYS_SDRAM_BASE,
+			0x4000000, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+#endif
+
+	/* PCI memory space */
+#if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272
+	pci_set_region (hose->regions + 1,
+			PCI_MSTR_MEMIO_BUS,
+			PCI_MSTR_MEMIO_LOCAL,
+			PCI_MSTR_MEMIO_SIZE, PCI_REGION_MEM);
+#else
+	pci_set_region (hose->regions + 1,
+			PCI_MSTR_MEM_BUS,
+			PCI_MSTR_MEM_LOCAL,
+			PCI_MSTR_MEM_SIZE, PCI_REGION_MEM);
+#endif
+
+	/* PCI I/O space */
+	pci_set_region (hose->regions + 2,
+			PCI_MSTR_IO_BUS,
+			PCI_MSTR_IO_LOCAL, PCI_MSTR_IO_SIZE, PCI_REGION_IO);
+
+	hose->region_count = 3;
+
+	pci_register_hose (hose);
+	/* Mask off master abort machine checks */
+	immap->im_pci.pci_emr &= cpu_to_le32 (~PCI_ERROR_PCI_NO_RSP);
+	eieio ();
+
+	hose->last_busno = pci_hose_scan (hose);
+
+
+	/* clear the error in the error status register */
+	immap->im_pci.pci_esr = cpu_to_le32 (PCI_ERROR_PCI_NO_RSP);
+
+	/* unmask master abort machine checks */
+	immap->im_pci.pci_emr |= cpu_to_le32 (PCI_ERROR_PCI_NO_RSP);
+}
+
+#if defined(CONFIG_OF_LIBFDT)
+void ft_pci_setup(void *blob, bd_t *bd)
+{
+	do_fixup_by_prop_u32(blob, "device_type", "pci", 4,
+		"clock-frequency", gd->pci_clk, 1);
+}
+#endif
+
+#endif /* CONFIG_PCI */
diff --git a/arch/powerpc/cpu/mpc8260/serial_scc.c b/arch/powerpc/cpu/mpc8260/serial_scc.c
new file mode 100644
index 0000000..4ab6a28
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/serial_scc.c
@@ -0,0 +1,498 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
+ */
+
+/*
+ * Minimal serial functions needed to use one of the SCC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <mpc8260.h>
+#include <asm/cpm_8260.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CONS_ON_SCC)
+
+#if CONFIG_CONS_INDEX == 1	/* Console on SCC1 */
+
+#define SCC_INDEX		0
+#define PROFF_SCC		PROFF_SCC1
+#define CMXSCR_MASK		(CMXSCR_GR1|CMXSCR_SC1|\
+					CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
+#define CMXSCR_VALUE		(CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
+#define CPM_CR_SCC_PAGE		CPM_CR_SCC1_PAGE
+#define CPM_CR_SCC_SBLOCK	CPM_CR_SCC1_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 2	/* Console on SCC2 */
+
+#define SCC_INDEX		1
+#define PROFF_SCC		PROFF_SCC2
+#define CMXSCR_MASK		(CMXSCR_GR2|CMXSCR_SC2|\
+					CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
+#define CMXSCR_VALUE		(CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
+#define CPM_CR_SCC_PAGE		CPM_CR_SCC2_PAGE
+#define CPM_CR_SCC_SBLOCK	CPM_CR_SCC2_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 3	/* Console on SCC3 */
+
+#define SCC_INDEX		2
+#define PROFF_SCC		PROFF_SCC3
+#define CMXSCR_MASK		(CMXSCR_GR3|CMXSCR_SC3|\
+					CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
+#define CMXSCR_VALUE		(CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
+#define CPM_CR_SCC_PAGE		CPM_CR_SCC3_PAGE
+#define CPM_CR_SCC_SBLOCK	CPM_CR_SCC3_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 4	/* Console on SCC4 */
+
+#define SCC_INDEX		3
+#define PROFF_SCC		PROFF_SCC4
+#define CMXSCR_MASK		(CMXSCR_GR4|CMXSCR_SC4|\
+					CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
+#define CMXSCR_VALUE		(CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
+#define CPM_CR_SCC_PAGE		CPM_CR_SCC4_PAGE
+#define CPM_CR_SCC_SBLOCK	CPM_CR_SCC4_SBLOCK
+
+#else
+
+#error "console not correctly defined"
+
+#endif
+
+int serial_init (void)
+{
+	volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile scc_t *sp;
+	volatile scc_uart_t *up;
+	volatile cbd_t *tbdf, *rbdf;
+	volatile cpm8260_t *cp = &(im->im_cpm);
+	uint	dpaddr;
+
+	/* initialize pointers to SCC */
+
+	sp = (scc_t *) &(im->im_scc[SCC_INDEX]);
+	up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
+
+	/* Disable transmitter/receiver.
+	*/
+	sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	/* put the SCC channel into NMSI (non multiplexd serial interface)
+	 * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
+	 */
+	im->im_cpmux.cmx_scr = (im->im_cpmux.cmx_scr&~CMXSCR_MASK)|CMXSCR_VALUE;
+
+	/* Set up the baud rate generator.
+	*/
+	serial_setbrg ();
+
+	/* Allocate space for two buffer descriptors in the DP ram.
+	 * damm: allocating space after the two buffers for rx/tx data
+	 */
+
+	dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
+
+	/* Set the physical address of the host memory buffers in
+	 * the buffer descriptors.
+	 */
+	rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
+	rbdf->cbd_bufaddr = (uint) (rbdf+2);
+	rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+	tbdf = rbdf + 1;
+	tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+	tbdf->cbd_sc = BD_SC_WRAP;
+
+	/* Set up the uart parameters in the parameter ram.
+	*/
+	up->scc_genscc.scc_rbase = dpaddr;
+	up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
+	up->scc_genscc.scc_rfcr = CPMFCR_EB;
+	up->scc_genscc.scc_tfcr = CPMFCR_EB;
+	up->scc_genscc.scc_mrblr = 1;
+	up->scc_maxidl = 0;
+	up->scc_brkcr = 1;
+	up->scc_parec = 0;
+	up->scc_frmec = 0;
+	up->scc_nosec = 0;
+	up->scc_brkec = 0;
+	up->scc_uaddr1 = 0;
+	up->scc_uaddr2 = 0;
+	up->scc_toseq = 0;
+	up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
+	up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
+	up->scc_rccm = 0xc0ff;
+
+	/* Mask all interrupts and remove anything pending.
+	*/
+	sp->scc_sccm = 0;
+	sp->scc_scce = 0xffff;
+
+	/* Set 8 bit FIFO, 16 bit oversampling and UART mode.
+	*/
+	sp->scc_gsmrh = SCC_GSMRH_RFW;	/* 8 bit FIFO */
+	sp->scc_gsmrl = \
+		SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
+
+	/* Set CTS flow control, 1 stop bit, 8 bit character length,
+	 * normal async UART mode, no parity
+	 */
+	sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL;
+
+	/* execute the "Init Rx and Tx params" CP command.
+	*/
+
+	while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
+	  ;
+
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
+					0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+	while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
+	  ;
+
+	/* Enable transmitter/receiver.
+	*/
+	sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
+
+	return (0);
+}
+
+void
+serial_setbrg (void)
+{
+#if defined(CONFIG_CONS_USE_EXTC)
+	m8260_cpm_extcbrg(SCC_INDEX, gd->baudrate,
+		CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
+#else
+	m8260_cpm_setbrg(SCC_INDEX, gd->baudrate);
+#endif
+}
+
+void
+serial_putc(const char c)
+{
+	volatile scc_uart_t	*up;
+	volatile cbd_t		*tbdf;
+	volatile immap_t	*im;
+
+	if (c == '\n')
+		serial_putc ('\r');
+
+	im = (immap_t *)CONFIG_SYS_IMMR;
+	up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
+	tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase];
+
+	/* Wait for last character to go.
+	 */
+	while (tbdf->cbd_sc & BD_SC_READY)
+		;
+
+	/* Load the character into the transmit buffer.
+	 */
+	*(volatile char *)tbdf->cbd_bufaddr = c;
+	tbdf->cbd_datlen = 1;
+	tbdf->cbd_sc |= BD_SC_READY;
+}
+
+void
+serial_puts (const char *s)
+{
+	while (*s) {
+		serial_putc (*s++);
+	}
+}
+
+int
+serial_getc(void)
+{
+	volatile cbd_t		*rbdf;
+	volatile scc_uart_t	*up;
+	volatile immap_t	*im;
+	unsigned char		c;
+
+	im = (immap_t *)CONFIG_SYS_IMMR;
+	up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
+	rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
+
+	/* Wait for character to show up.
+	 */
+	while (rbdf->cbd_sc & BD_SC_EMPTY)
+		;
+
+	/* Grab the char and clear the buffer again.
+	 */
+	c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
+	rbdf->cbd_sc |= BD_SC_EMPTY;
+
+	return (c);
+}
+
+int
+serial_tstc()
+{
+	volatile cbd_t		*rbdf;
+	volatile scc_uart_t	*up;
+	volatile immap_t	*im;
+
+	im = (immap_t *)CONFIG_SYS_IMMR;
+	up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
+	rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
+
+	return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
+}
+
+#endif	/* CONFIG_CONS_ON_SCC */
+
+#if defined(CONFIG_KGDB_ON_SCC)
+
+#if defined(CONFIG_CONS_ON_SCC) && CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
+#error Whoops! serial console and kgdb are on the same scc serial port
+#endif
+
+#if CONFIG_KGDB_INDEX == 1	/* KGDB Port on SCC1 */
+
+#define KGDB_SCC_INDEX		0
+#define KGDB_PROFF_SCC		PROFF_SCC1
+#define KGDB_CMXSCR_MASK	(CMXSCR_GR1|CMXSCR_SC1|\
+					CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
+#define KGDB_CMXSCR_VALUE	(CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
+#define KGDB_CPM_CR_SCC_PAGE	CPM_CR_SCC1_PAGE
+#define KGDB_CPM_CR_SCC_SBLOCK	CPM_CR_SCC1_SBLOCK
+
+#elif CONFIG_KGDB_INDEX == 2	/* KGDB Port on SCC2 */
+
+#define KGDB_SCC_INDEX		1
+#define KGDB_PROFF_SCC		PROFF_SCC2
+#define KGDB_CMXSCR_MASK	(CMXSCR_GR2|CMXSCR_SC2|\
+					CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
+#define KGDB_CMXSCR_VALUE	(CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
+#define KGDB_CPM_CR_SCC_PAGE	CPM_CR_SCC2_PAGE
+#define KGDB_CPM_CR_SCC_SBLOCK	CPM_CR_SCC2_SBLOCK
+
+#elif CONFIG_KGDB_INDEX == 3	/* KGDB Port on SCC3 */
+
+#define KGDB_SCC_INDEX		2
+#define KGDB_PROFF_SCC		PROFF_SCC3
+#define KGDB_CMXSCR_MASK	(CMXSCR_GR3|CMXSCR_SC3|\
+					CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
+#define KGDB_CMXSCR_VALUE	(CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
+#define KGDB_CPM_CR_SCC_PAGE	CPM_CR_SCC3_PAGE
+#define KGDB_CPM_CR_SCC_SBLOCK	CPM_CR_SCC3_SBLOCK
+
+#elif CONFIG_KGDB_INDEX == 4	/* KGDB Port on SCC4 */
+
+#define KGDB_SCC_INDEX		3
+#define KGDB_PROFF_SCC		PROFF_SCC4
+#define KGDB_CMXSCR_MASK	(CMXSCR_GR4|CMXSCR_SC4|\
+					CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
+#define KGDB_CMXSCR_VALUE	(CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
+#define KGDB_CPM_CR_SCC_PAGE	CPM_CR_SCC4_PAGE
+#define KGDB_CPM_CR_SCC_SBLOCK	CPM_CR_SCC4_SBLOCK
+
+#else
+
+#error "kgdb serial port not correctly defined"
+
+#endif
+
+void
+kgdb_serial_init (void)
+{
+	volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile scc_t *sp;
+	volatile scc_uart_t *up;
+	volatile cbd_t *tbdf, *rbdf;
+	volatile cpm8260_t *cp = &(im->im_cpm);
+	uint dpaddr, speed = CONFIG_KGDB_BAUDRATE;
+	char *s, *e;
+
+	if ((s = getenv("kgdbrate")) != NULL && *s != '\0') {
+		ulong rate = simple_strtoul(s, &e, 10);
+		if (e > s && *e == '\0')
+			speed = rate;
+	}
+
+	/* initialize pointers to SCC */
+
+	sp = (scc_t *) &(im->im_scc[KGDB_SCC_INDEX]);
+	up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
+
+	/* Disable transmitter/receiver.
+	*/
+	sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	/* put the SCC channel into NMSI (non multiplexd serial interface)
+	 * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
+	 */
+	im->im_cpmux.cmx_scr = \
+		(im->im_cpmux.cmx_scr & ~KGDB_CMXSCR_MASK) | KGDB_CMXSCR_VALUE;
+
+	/* Set up the baud rate generator.
+	*/
+#if defined(CONFIG_KGDB_USE_EXTC)
+	m8260_cpm_extcbrg(KGDB_SCC_INDEX, speed,
+		CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
+#else
+	m8260_cpm_setbrg(KGDB_SCC_INDEX, speed);
+#endif
+
+	/* Allocate space for two buffer descriptors in the DP ram.
+	 * damm: allocating space after the two buffers for rx/tx data
+	 */
+
+	dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
+
+	/* Set the physical address of the host memory buffers in
+	 * the buffer descriptors.
+	 */
+	rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
+	rbdf->cbd_bufaddr = (uint) (rbdf+2);
+	rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+	tbdf = rbdf + 1;
+	tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+	tbdf->cbd_sc = BD_SC_WRAP;
+
+	/* Set up the uart parameters in the parameter ram.
+	*/
+	up->scc_genscc.scc_rbase = dpaddr;
+	up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
+	up->scc_genscc.scc_rfcr = CPMFCR_EB;
+	up->scc_genscc.scc_tfcr = CPMFCR_EB;
+	up->scc_genscc.scc_mrblr = 1;
+	up->scc_maxidl = 0;
+	up->scc_brkcr = 1;
+	up->scc_parec = 0;
+	up->scc_frmec = 0;
+	up->scc_nosec = 0;
+	up->scc_brkec = 0;
+	up->scc_uaddr1 = 0;
+	up->scc_uaddr2 = 0;
+	up->scc_toseq = 0;
+	up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
+	up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
+	up->scc_rccm = 0xc0ff;
+
+	/* Mask all interrupts and remove anything pending.
+	*/
+	sp->scc_sccm = 0;
+	sp->scc_scce = 0xffff;
+
+	/* Set 8 bit FIFO, 16 bit oversampling and UART mode.
+	*/
+	sp->scc_gsmrh = SCC_GSMRH_RFW;	/* 8 bit FIFO */
+	sp->scc_gsmrl = \
+		SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
+
+	/* Set CTS flow control, 1 stop bit, 8 bit character length,
+	 * normal async UART mode, no parity
+	 */
+	sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL;
+
+	/* execute the "Init Rx and Tx params" CP command.
+	*/
+
+	while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
+	  ;
+
+	cp->cp_cpcr = mk_cr_cmd(KGDB_CPM_CR_SCC_PAGE, KGDB_CPM_CR_SCC_SBLOCK,
+					0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+	while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
+	  ;
+
+	/* Enable transmitter/receiver.
+	*/
+	sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
+
+	printf("SCC%d at %dbps ", CONFIG_KGDB_INDEX, speed);
+}
+
+void
+putDebugChar(const char c)
+{
+	volatile scc_uart_t	*up;
+	volatile cbd_t		*tbdf;
+	volatile immap_t	*im;
+
+	if (c == '\n')
+		putDebugChar ('\r');
+
+	im = (immap_t *)CONFIG_SYS_IMMR;
+	up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
+	tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase];
+
+	/* Wait for last character to go.
+	 */
+	while (tbdf->cbd_sc & BD_SC_READY)
+		;
+
+	/* Load the character into the transmit buffer.
+	 */
+	*(volatile char *)tbdf->cbd_bufaddr = c;
+	tbdf->cbd_datlen = 1;
+	tbdf->cbd_sc |= BD_SC_READY;
+}
+
+void
+putDebugStr (const char *s)
+{
+	while (*s) {
+		putDebugChar (*s++);
+	}
+}
+
+int
+getDebugChar(void)
+{
+	volatile cbd_t		*rbdf;
+	volatile scc_uart_t	*up;
+	volatile immap_t	*im;
+	unsigned char		c;
+
+	im = (immap_t *)CONFIG_SYS_IMMR;
+	up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
+	rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
+
+	/* Wait for character to show up.
+	 */
+	while (rbdf->cbd_sc & BD_SC_EMPTY)
+		;
+
+	/* Grab the char and clear the buffer again.
+	 */
+	c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
+	rbdf->cbd_sc |= BD_SC_EMPTY;
+
+	return (c);
+}
+
+void
+kgdb_interruptible(int yes)
+{
+	return;
+}
+
+#endif	/* CONFIG_KGDB_ON_SCC */
diff --git a/arch/powerpc/cpu/mpc8260/serial_smc.c b/arch/powerpc/cpu/mpc8260/serial_smc.c
new file mode 100644
index 0000000..7b6eaba
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/serial_smc.c
@@ -0,0 +1,467 @@
+/*
+ * (C) Copyright 2000, 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00, with
+ * changes based on the file arch/powerpc/mbxboot/m8260_tty.c from the
+ * Linux/PPC sources (m8260_tty.c had no copyright info in it).
+ */
+
+/*
+ * Minimal serial functions needed to use one of the SMC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <mpc8260.h>
+#include <asm/cpm_8260.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CONS_ON_SMC)
+
+#if CONFIG_CONS_INDEX == 1	/* Console on SMC1 */
+
+#define SMC_INDEX		0
+#define PROFF_SMC_BASE		PROFF_SMC1_BASE
+#define PROFF_SMC		PROFF_SMC1
+#define CPM_CR_SMC_PAGE		CPM_CR_SMC1_PAGE
+#define CPM_CR_SMC_SBLOCK	CPM_CR_SMC1_SBLOCK
+#define CMXSMR_MASK		(CMXSMR_SMC1|CMXSMR_SMC1CS_MSK)
+#define CMXSMR_VALUE		CMXSMR_SMC1CS_BRG7
+
+#elif CONFIG_CONS_INDEX == 2	/* Console on SMC2 */
+
+#define SMC_INDEX		1
+#define PROFF_SMC_BASE		PROFF_SMC2_BASE
+#define PROFF_SMC		PROFF_SMC2
+#define CPM_CR_SMC_PAGE		CPM_CR_SMC2_PAGE
+#define CPM_CR_SMC_SBLOCK	CPM_CR_SMC2_SBLOCK
+#define CMXSMR_MASK		(CMXSMR_SMC2|CMXSMR_SMC2CS_MSK)
+#define CMXSMR_VALUE		CMXSMR_SMC2CS_BRG8
+
+#else
+
+#error "console not correctly defined"
+
+#endif
+
+#if !defined(CONFIG_SYS_SMC_RXBUFLEN)
+#define CONFIG_SYS_SMC_RXBUFLEN	1
+#define CONFIG_SYS_MAXIDLE	0
+#else
+#if !defined(CONFIG_SYS_MAXIDLE)
+#error "you must define CONFIG_SYS_MAXIDLE"
+#endif
+#endif
+
+typedef volatile struct serialbuffer {
+	cbd_t	rxbd;		/* Rx BD */
+	cbd_t	txbd;		/* Tx BD */
+	uint	rxindex;	/* index for next character to read */
+	volatile uchar	rxbuf[CONFIG_SYS_SMC_RXBUFLEN];/* rx buffers */
+	volatile uchar	txbuf;	/* tx buffers */
+} serialbuffer_t;
+
+/* map rs_table index to baud rate generator index */
+static unsigned char brg_map[] = {
+	6,	/* BRG7 for SMC1 */
+	7,	/* BRG8 for SMC2 */
+	0,	/* BRG1 for SCC1 */
+	1,	/* BRG1 for SCC2 */
+	2,	/* BRG1 for SCC3 */
+	3,	/* BRG1 for SCC4 */
+};
+
+int serial_init (void)
+{
+	volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile smc_t *sp;
+	volatile smc_uart_t *up;
+	volatile cpm8260_t *cp = &(im->im_cpm);
+	uint	dpaddr;
+	volatile serialbuffer_t *rtx;
+
+	/* initialize pointers to SMC */
+
+	sp = (smc_t *) &(im->im_smc[SMC_INDEX]);
+	*(ushort *)(&im->im_dprambase[PROFF_SMC_BASE]) = PROFF_SMC;
+	up = (smc_uart_t *)&im->im_dprambase[PROFF_SMC];
+
+	/* Disable transmitter/receiver. */
+	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+	/* NOTE: I/O port pins are set up via the iop_conf_tab[] table */
+
+	/* Allocate space for two buffer descriptors in the DP ram.
+	 * damm: allocating space after the two buffers for rx/tx data
+	 */
+
+	/* allocate size of struct serialbuffer with bd rx/tx,
+	 * buffer rx/tx and rx index
+	 */
+	dpaddr = m8260_cpm_dpalloc((sizeof(serialbuffer_t)), 16);
+
+	rtx = (serialbuffer_t *)&im->im_dprambase[dpaddr];
+
+	/* Set the physical address of the host memory buffers in
+	 * the buffer descriptors.
+	 */
+	rtx->rxbd.cbd_bufaddr = (uint) &rtx->rxbuf;
+	rtx->rxbd.cbd_sc      = 0;
+
+	rtx->txbd.cbd_bufaddr = (uint) &rtx->txbuf;
+	rtx->txbd.cbd_sc      = 0;
+
+	/* Set up the uart parameters in the parameter ram. */
+	up->smc_rbase = dpaddr;
+	up->smc_tbase = dpaddr+sizeof(cbd_t);
+	up->smc_rfcr = CPMFCR_EB;
+	up->smc_tfcr = CPMFCR_EB;
+	up->smc_brklen = 0;
+	up->smc_brkec = 0;
+	up->smc_brkcr = 0;
+
+	/* Set UART mode, 8 bit, no parity, one stop.
+	 * Enable receive and transmit.
+	 */
+	sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
+
+	/* Mask all interrupts and remove anything pending. */
+	sp->smc_smcm = 0;
+	sp->smc_smce = 0xff;
+
+	/* put the SMC channel into NMSI (non multiplexd serial interface)
+	 * mode and wire either BRG7 to SMC1 or BRG8 to SMC2 (15-17).
+	 */
+	im->im_cpmux.cmx_smr = (im->im_cpmux.cmx_smr&~CMXSMR_MASK)|CMXSMR_VALUE;
+
+	/* Set up the baud rate generator. */
+	serial_setbrg ();
+
+	/* Make the first buffer the only buffer. */
+	rtx->txbd.cbd_sc |= BD_SC_WRAP;
+	rtx->rxbd.cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+	/* single/multi character receive. */
+	up->smc_mrblr = CONFIG_SYS_SMC_RXBUFLEN;
+	up->smc_maxidl = CONFIG_SYS_MAXIDLE;
+	rtx->rxindex = 0;
+
+	/* Initialize Tx/Rx parameters. */
+
+	while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
+	  ;
+
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC_PAGE, CPM_CR_SMC_SBLOCK,
+					0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+	while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
+	  ;
+
+	/* Enable transmitter/receiver. */
+	sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+
+	return (0);
+}
+
+void
+serial_setbrg (void)
+{
+#if defined(CONFIG_CONS_USE_EXTC)
+	m8260_cpm_extcbrg(brg_map[SMC_INDEX], gd->baudrate,
+		CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
+#else
+	m8260_cpm_setbrg(brg_map[SMC_INDEX], gd->baudrate);
+#endif
+}
+
+void
+serial_putc(const char c)
+{
+	volatile smc_uart_t	*up;
+	volatile immap_t	*im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile serialbuffer_t	*rtx;
+
+	if (c == '\n')
+		serial_putc ('\r');
+
+	up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
+
+	rtx = (serialbuffer_t *)&im->im_dprambase[up->smc_rbase];
+
+	/* Wait for last character to go. */
+	while (rtx->txbd.cbd_sc & BD_SC_READY & BD_SC_READY)
+		;
+	rtx->txbuf = c;
+	rtx->txbd.cbd_datlen = 1;
+	rtx->txbd.cbd_sc |= BD_SC_READY;
+}
+
+void
+serial_puts (const char *s)
+{
+	while (*s) {
+		serial_putc (*s++);
+	}
+}
+
+int
+serial_getc(void)
+{
+	volatile smc_uart_t	*up;
+	volatile immap_t	*im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile serialbuffer_t	*rtx;
+	unsigned char  c;
+
+	up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
+
+	rtx = (serialbuffer_t *)&im->im_dprambase[up->smc_rbase];
+
+	/* Wait for character to show up. */
+	while (rtx->rxbd.cbd_sc & BD_SC_EMPTY)
+		;
+
+	/* the characters are read one by one,
+	 * use the rxindex to know the next char to deliver
+	 */
+	c = *(unsigned char *) (rtx->rxbd.cbd_bufaddr + rtx->rxindex);
+	rtx->rxindex++;
+
+	/* check if all char are readout, then make prepare for next receive */
+	if (rtx->rxindex >= rtx->rxbd.cbd_datlen) {
+		rtx->rxindex = 0;
+		rtx->rxbd.cbd_sc |= BD_SC_EMPTY;
+	}
+	return(c);
+}
+
+int
+serial_tstc()
+{
+	volatile smc_uart_t	*up;
+	volatile immap_t	*im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile serialbuffer_t	*rtx;
+
+	up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
+	rtx = (serialbuffer_t *)&im->im_dprambase[up->smc_rbase];
+
+	return !(rtx->rxbd.cbd_sc & BD_SC_EMPTY);
+}
+
+#endif	/* CONFIG_CONS_ON_SMC */
+
+#if defined(CONFIG_KGDB_ON_SMC)
+
+#if defined(CONFIG_CONS_ON_SMC) && CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
+#error Whoops! serial console and kgdb are on the same smc serial port
+#endif
+
+#if CONFIG_KGDB_INDEX == 1	/* KGDB Port on SMC1 */
+
+#define KGDB_SMC_INDEX		0
+#define KGDB_PROFF_SMC_BASE	PROFF_SMC1_BASE
+#define KGDB_PROFF_SMC		PROFF_SMC1
+#define KGDB_CPM_CR_SMC_PAGE	CPM_CR_SMC1_PAGE
+#define KGDB_CPM_CR_SMC_SBLOCK	CPM_CR_SMC1_SBLOCK
+#define KGDB_CMXSMR_MASK	(CMXSMR_SMC1|CMXSMR_SMC1CS_MSK)
+#define KGDB_CMXSMR_VALUE	CMXSMR_SMC1CS_BRG7
+
+#elif CONFIG_KGDB_INDEX == 2	/* KGDB Port on SMC2 */
+
+#define KGDB_SMC_INDEX		1
+#define KGDB_PROFF_SMC_BASE	PROFF_SMC2_BASE
+#define KGDB_PROFF_SMC		PROFF_SMC2
+#define KGDB_CPM_CR_SMC_PAGE	CPM_CR_SMC2_PAGE
+#define KGDB_CPM_CR_SMC_SBLOCK	CPM_CR_SMC2_SBLOCK
+#define KGDB_CMXSMR_MASK	(CMXSMR_SMC2|CMXSMR_SMC2CS_MSK)
+#define KGDB_CMXSMR_VALUE	CMXSMR_SMC2CS_BRG8
+
+#else
+
+#error "console not correctly defined"
+
+#endif
+
+void
+kgdb_serial_init (void)
+{
+	volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile smc_t *sp;
+	volatile smc_uart_t *up;
+	volatile cbd_t *tbdf, *rbdf;
+	volatile cpm8260_t *cp = &(im->im_cpm);
+	uint dpaddr, speed = CONFIG_KGDB_BAUDRATE;
+	char *s, *e;
+
+	if ((s = getenv("kgdbrate")) != NULL && *s != '\0') {
+		ulong rate = simple_strtoul(s, &e, 10);
+		if (e > s && *e == '\0')
+			speed = rate;
+	}
+
+	/* initialize pointers to SMC */
+
+	sp = (smc_t *) &(im->im_smc[KGDB_SMC_INDEX]);
+	*(ushort *)(&im->im_dprambase[KGDB_PROFF_SMC_BASE]) = KGDB_PROFF_SMC;
+	up = (smc_uart_t *)&im->im_dprambase[KGDB_PROFF_SMC];
+
+	/* Disable transmitter/receiver. */
+	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+	/* NOTE: I/O port pins are set up via the iop_conf_tab[] table */
+
+	/* Allocate space for two buffer descriptors in the DP ram.
+	 * damm: allocating space after the two buffers for rx/tx data
+	 */
+
+	dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
+
+	/* Set the physical address of the host memory buffers in
+	 * the buffer descriptors.
+	 */
+	rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
+	rbdf->cbd_bufaddr = (uint) (rbdf+2);
+	rbdf->cbd_sc = 0;
+	tbdf = rbdf + 1;
+	tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+	tbdf->cbd_sc = 0;
+
+	/* Set up the uart parameters in the parameter ram. */
+	up->smc_rbase = dpaddr;
+	up->smc_tbase = dpaddr+sizeof(cbd_t);
+	up->smc_rfcr = CPMFCR_EB;
+	up->smc_tfcr = CPMFCR_EB;
+	up->smc_brklen = 0;
+	up->smc_brkec = 0;
+	up->smc_brkcr = 0;
+
+	/* Set UART mode, 8 bit, no parity, one stop.
+	 * Enable receive and transmit.
+	 */
+	sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
+
+	/* Mask all interrupts and remove anything pending. */
+	sp->smc_smcm = 0;
+	sp->smc_smce = 0xff;
+
+	/* put the SMC channel into NMSI (non multiplexd serial interface)
+	 * mode and wire either BRG7 to SMC1 or BRG8 to SMC2 (15-17).
+	 */
+	im->im_cpmux.cmx_smr =
+		(im->im_cpmux.cmx_smr & ~KGDB_CMXSMR_MASK) | KGDB_CMXSMR_VALUE;
+
+	/* Set up the baud rate generator. */
+#if defined(CONFIG_KGDB_USE_EXTC)
+	m8260_cpm_extcbrg(brg_map[KGDB_SMC_INDEX], speed,
+		CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
+#else
+	m8260_cpm_setbrg(brg_map[KGDB_SMC_INDEX], speed);
+#endif
+
+	/* Make the first buffer the only buffer. */
+	tbdf->cbd_sc |= BD_SC_WRAP;
+	rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+	/* Single character receive. */
+	up->smc_mrblr = 1;
+	up->smc_maxidl = 0;
+
+	/* Initialize Tx/Rx parameters. */
+
+	while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
+	  ;
+
+	cp->cp_cpcr = mk_cr_cmd(KGDB_CPM_CR_SMC_PAGE, KGDB_CPM_CR_SMC_SBLOCK,
+					0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+	while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
+	  ;
+
+	/* Enable transmitter/receiver.	*/
+	sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+
+	printf("SMC%d at %dbps ", CONFIG_KGDB_INDEX, speed);
+}
+
+void
+putDebugChar(const char c)
+{
+	volatile cbd_t		*tbdf;
+	volatile char		*buf;
+	volatile smc_uart_t	*up;
+	volatile immap_t	*im = (immap_t *)CONFIG_SYS_IMMR;
+
+	if (c == '\n')
+		putDebugChar ('\r');
+
+	up = (smc_uart_t *)&(im->im_dprambase[KGDB_PROFF_SMC]);
+
+	tbdf = (cbd_t *)&im->im_dprambase[up->smc_tbase];
+
+	/* Wait for last character to go. */
+	buf = (char *)tbdf->cbd_bufaddr;
+	while (tbdf->cbd_sc & BD_SC_READY)
+		;
+
+	*buf = c;
+	tbdf->cbd_datlen = 1;
+	tbdf->cbd_sc |= BD_SC_READY;
+}
+
+void
+putDebugStr (const char *s)
+{
+	while (*s) {
+		putDebugChar (*s++);
+	}
+}
+
+int
+getDebugChar(void)
+{
+	volatile cbd_t		*rbdf;
+	volatile unsigned char	*buf;
+	volatile smc_uart_t	*up;
+	volatile immap_t	*im = (immap_t *)CONFIG_SYS_IMMR;
+	unsigned char		c;
+
+	up = (smc_uart_t *)&(im->im_dprambase[KGDB_PROFF_SMC]);
+
+	rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase];
+
+	/* Wait for character to show up. */
+	buf = (unsigned char *)rbdf->cbd_bufaddr;
+	while (rbdf->cbd_sc & BD_SC_EMPTY)
+		;
+	c = *buf;
+	rbdf->cbd_sc |= BD_SC_EMPTY;
+
+	return(c);
+}
+
+void
+kgdb_interruptible(int yes)
+{
+	return;
+}
+
+#endif	/* CONFIG_KGDB_ON_SMC */
diff --git a/arch/powerpc/cpu/mpc8260/speed.c b/arch/powerpc/cpu/mpc8260/speed.c
new file mode 100644
index 0000000..0e1c2b0
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/speed.c
@@ -0,0 +1,253 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8260.h>
+#include <asm/processor.h>
+
+#if defined(CONFIG_BOARD_GET_CPU_CLK_F)
+extern unsigned long board_get_cpu_clk_f (void);
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* ------------------------------------------------------------------------- */
+
+/* Bus-to-Core Multiplier */
+#define _1x	2
+#define _1_5x	3
+#define _2x	4
+#define _2_5x	5
+#define _3x	6
+#define _3_5x	7
+#define _4x	8
+#define _4_5x	9
+#define _5x	10
+#define _5_5x	11
+#define _6x	12
+#define _6_5x	13
+#define _7x	14
+#define _7_5x	15
+#define _8x	16
+#define _byp	-1
+#define _off	-2
+#define _unk	-3
+
+typedef struct {
+	int b2c_mult;
+	int vco_div;
+	char *freq_60x;
+	char *freq_core;
+} corecnf_t;
+
+/*
+ * this table based on "Errata to MPC8260 PowerQUICC II User's Manual",
+ * Rev. 1, 8/2000, page 10.
+ */
+corecnf_t corecnf_tab[] = {
+	{ _1_5x,  4, " 33-100", " 33-100" },	/* 0x00 */
+	{   _1x,  4, " 50-150", " 50-150" },	/* 0x01 */
+	{   _1x,  8, " 25-75 ", " 25-75 " },	/* 0x02 */
+	{  _byp, -1, "  ?-?  ", "  ?-?  " },	/* 0x03 */
+	{   _2x,  2, " 50-150", "100-300" },	/* 0x04 */
+	{   _2x,  4, " 25-75 ", " 50-150" },	/* 0x05 */
+	{ _2_5x,  2, " 40-120", "100-240" },	/* 0x06 */
+	{ _4_5x,  2, " 22-65 ", "100-300" },	/* 0x07 */
+	{   _3x,  2, " 33-100", "100-300" },	/* 0x08 */
+	{ _5_5x,  2, " 18-55 ", "100-300" },	/* 0x09 */
+	{   _4x,  2, " 25-75 ", "100-300" },	/* 0x0A */
+	{   _5x,  2, " 20-60 ", "100-300" },	/* 0x0B */
+	{ _1_5x,  8, " 16-50 ", " 16-50 " },	/* 0x0C */
+	{   _6x,  2, " 16-50 ", "100-300" },	/* 0x0D */
+	{ _3_5x,  2, " 30-85 ", "100-300" },	/* 0x0E */
+	{  _off, -1, "  ?-?  ", "  ?-?  " },	/* 0x0F */
+	{   _3x,  4, " 16-50 ", " 50-150" },	/* 0x10 */
+	{ _2_5x,  4, " 20-60 ", " 50-120" },	/* 0x11 */
+	{ _6_5x,  2, " 15-46 ", "100-300" },	/* 0x12 */
+	{  _byp, -1, "  ?-?  ", "  ?-?  " },	/* 0x13 */
+	{   _7x,  2, " 14-43 ", "100-300" },	/* 0x14 */
+	{   _2x,  4, " 25-75 ", " 50-150" },	/* 0x15 */
+	{ _7_5x,  2, " 13-40 ", "100-300" },	/* 0x16 */
+	{ _4_5x,  2, " 22-65 ", "100-300" },	/* 0x17 */
+	{  _unk, -1, "  ?-?  ", "  ?-?  " },	/* 0x18 */
+	{ _5_5x,  2, " 18-55 ", "100-300" },	/* 0x19 */
+	{   _4x,  2, " 25-75 ", "100-300" },	/* 0x1A */
+	{   _5x,  2, " 20-60 ", "100-300" },	/* 0x1B */
+	{   _8x,  2, " 12-38 ", "100-300" },	/* 0x1C */
+	{   _6x,  2, " 16-50 ", "100-300" },	/* 0x1D */
+	{ _3_5x,  2, " 30-85 ", "100-300" },	/* 0x1E */
+	{  _off, -1, "  ?-?  ", "  ?-?  " },	/* 0x1F */
+};
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ *
+ */
+
+int get_clocks (void)
+{
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	ulong clkin;
+	ulong sccr, dfbrg;
+	ulong scmr, corecnf, busdf, cpmdf, plldf, pllmf;
+	corecnf_t *cp;
+
+#if !defined(CONFIG_8260_CLKIN)
+#error clock measuring not implemented yet - define CONFIG_8260_CLKIN
+#else
+#if defined(CONFIG_BOARD_GET_CPU_CLK_F)
+	clkin = board_get_cpu_clk_f ();
+#else
+	clkin = CONFIG_8260_CLKIN;
+#endif
+#endif
+
+	sccr = immap->im_clkrst.car_sccr;
+	dfbrg = (sccr & SCCR_DFBRG_MSK) >> SCCR_DFBRG_SHIFT;
+
+	scmr = immap->im_clkrst.car_scmr;
+	corecnf = (scmr & SCMR_CORECNF_MSK) >> SCMR_CORECNF_SHIFT;
+	cp = &corecnf_tab[corecnf];
+
+	busdf = (scmr & SCMR_BUSDF_MSK) >> SCMR_BUSDF_SHIFT;
+	cpmdf = (scmr & SCMR_CPMDF_MSK) >> SCMR_CPMDF_SHIFT;
+
+	/* HiP7, HiP7 Rev01, HiP7 RevA */
+	if ((get_pvr () == PVR_8260_HIP7) ||
+	    (get_pvr () == PVR_8260_HIP7R1) ||
+	    (get_pvr () == PVR_8260_HIP7RA)) {
+		pllmf = (scmr & SCMR_PLLMF_MSKH7) >> SCMR_PLLMF_SHIFT;
+		gd->vco_out = clkin * (pllmf + 1);
+	} else {                        /* HiP3, HiP4 */
+		pllmf = (scmr & SCMR_PLLMF_MSK) >> SCMR_PLLMF_SHIFT;
+		plldf = (scmr & SCMR_PLLDF) ? 1 : 0;
+		gd->vco_out = (clkin * 2 * (pllmf + 1)) / (plldf + 1);
+	}
+#if 0
+	if (gd->vco_out / (busdf + 1) != clkin) {
+		/* aaarrrggghhh!!! */
+		return (1);
+	}
+#endif
+
+	gd->cpm_clk = gd->vco_out / 2;
+	gd->bus_clk = clkin;
+	gd->scc_clk = gd->vco_out / 4;
+	gd->brg_clk = gd->vco_out / (1 << (2 * (dfbrg + 1)));
+
+	if (cp->b2c_mult > 0) {
+		gd->cpu_clk = (clkin * cp->b2c_mult) / 2;
+	} else {
+		gd->cpu_clk = clkin;
+	}
+
+#ifdef CONFIG_PCI
+	gd->pci_clk = clkin;
+
+	if (sccr & SCCR_PCI_MODE) {
+		uint pci_div;
+		uint pcidf = (sccr & SCCR_PCIDF_MSK) >> SCCR_PCIDF_SHIFT;
+
+		if (sccr & SCCR_PCI_MODCK) {
+			pci_div = 2;
+			if (pcidf == 9) {
+				pci_div *= 5;
+			} else if (pcidf == 0xB) {
+				pci_div *= 6;
+			} else {
+				pci_div *= (pcidf + 1);
+			}
+		} else {
+			pci_div = pcidf + 1;
+		}
+
+		gd->pci_clk = (gd->cpm_clk * 2) / pci_div;
+	}
+#endif
+
+	return (0);
+}
+
+int prt_8260_clks (void)
+{
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	ulong sccr, dfbrg;
+	ulong scmr, corecnf, busdf, cpmdf, plldf, pllmf, pcidf;
+	corecnf_t *cp;
+
+	sccr = immap->im_clkrst.car_sccr;
+	dfbrg = (sccr & SCCR_DFBRG_MSK) >> SCCR_DFBRG_SHIFT;
+
+	scmr = immap->im_clkrst.car_scmr;
+	corecnf = (scmr & SCMR_CORECNF_MSK) >> SCMR_CORECNF_SHIFT;
+	busdf = (scmr & SCMR_BUSDF_MSK) >> SCMR_BUSDF_SHIFT;
+	cpmdf = (scmr & SCMR_CPMDF_MSK) >> SCMR_CPMDF_SHIFT;
+	plldf = (scmr & SCMR_PLLDF) ? 1 : 0;
+	pllmf = (scmr & SCMR_PLLMF_MSK) >> SCMR_PLLMF_SHIFT;
+	pcidf = (sccr & SCCR_PCIDF_MSK) >> SCCR_PCIDF_SHIFT;
+
+	cp = &corecnf_tab[corecnf];
+
+	puts (CPU_ID_STR " Clock Configuration\n - Bus-to-Core Mult ");
+
+	switch (cp->b2c_mult) {
+	case _byp:
+		puts ("BYPASS");
+		break;
+
+	case _off:
+		puts ("OFF");
+		break;
+
+	case _unk:
+		puts ("UNKNOWN");
+		break;
+
+	default:
+		printf ("%d%sx",
+			cp->b2c_mult / 2,
+			(cp->b2c_mult % 2) ? ".5" : "");
+		break;
+	}
+
+	printf (", VCO Div %d, 60x Bus Freq %s, Core Freq %s\n",
+			cp->vco_div, cp->freq_60x, cp->freq_core);
+
+	printf (" - dfbrg %ld, corecnf 0x%02lx, busdf %ld, cpmdf %ld, "
+		"plldf %ld, pllmf %ld, pcidf %ld\n",
+			dfbrg, corecnf, busdf, cpmdf,
+			plldf, pllmf, pcidf);
+
+	printf (" - vco_out %10ld, scc_clk %10ld, brg_clk %10ld\n",
+			gd->vco_out, gd->scc_clk, gd->brg_clk);
+
+	printf (" - cpu_clk %10ld, cpm_clk %10ld, bus_clk %10ld\n",
+			gd->cpu_clk, gd->cpm_clk, gd->bus_clk);
+#ifdef CONFIG_PCI
+	printf (" - pci_clk %10ld\n", gd->pci_clk);
+#endif
+	putc ('\n');
+
+	return (0);
+}
diff --git a/arch/powerpc/cpu/mpc8260/speed.h b/arch/powerpc/cpu/mpc8260/speed.h
new file mode 100644
index 0000000..3f32a14
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/speed.h
@@ -0,0 +1,54 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*-----------------------------------------------------------------------
+ * Timer value for timer 2, ICLK = 10
+ *
+ * SPEED_FCOUNT2 =  GCLK / (16 * (TIMER_TMR_PS + 1))
+ * SPEED_TMR3_PS = (GCLK / (16 * SPEED_FCOUNT3)) - 1
+ *
+ * SPEED_FCOUNT2	timer 2 counting frequency
+ * GCLK			CPU clock
+ * SPEED_TMR2_PS	prescaler
+ */
+#define SPEED_TMR2_PS	(250 - 1)	/* divide by 250	*/
+
+/*-----------------------------------------------------------------------
+ * Timer value for PIT
+ *
+ * PIT_TIME = SPEED_PITC / PITRTCLK
+ * PITRTCLK = 8192
+ */
+#define SPEED_PITC	(82 << 16)	/* start counting from 82	*/
+
+/*
+ * The new value for PTA is calculated from
+ *
+ *	PTA = (gclk * Trefresh) / (2 ^ (2 * DFBRG) * PTP * NCS)
+ *
+ * gclk		CPU clock (not bus clock !)
+ * Trefresh	Refresh cycle * 4 (four word bursts used)
+ * DFBRG	For normal mode (no clock reduction) always 0
+ * PTP		Prescaler (already adjusted for no. of banks and 4K / 8K refresh)
+ * NCS		Number of SDRAM banks (chip selects) on this UPM.
+ */
diff --git a/arch/powerpc/cpu/mpc8260/spi.c b/arch/powerpc/cpu/mpc8260/spi.c
new file mode 100644
index 0000000..f5d2ac3
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/spi.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2001 Navin Boppuri / Prashant Patel
+ *	<nboppuri@trinetcommunication.com>,
+ *	<pmpatel@trinetcommunication.com>
+ * Copyright (c) 2001 Gerd Mennchen <Gerd.Mennchen@icn.siemens.de>
+ * Copyright (c) 2001-2003 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * MPC8260 CPM SPI interface.
+ *
+ * Parts of this code are probably not portable and/or specific to
+ * the board which I used for the tests. Please send fixes/complaints
+ * to wd@denx.de
+ *
+ */
+
+#include <common.h>
+#include <asm/cpm_8260.h>
+#include <linux/ctype.h>
+#include <malloc.h>
+#include <post.h>
+#include <net.h>
+
+#if defined(CONFIG_SPI)
+
+/* Warning:
+ * You cannot enable DEBUG for early system initalization, i. e. when
+ * this driver is used to read environment parameters like "baudrate"
+ * from EEPROM which are used to initialize the serial port which is
+ * needed to print the debug messages...
+ */
+#undef	DEBUG
+
+#define SPI_EEPROM_WREN		0x06
+#define SPI_EEPROM_RDSR		0x05
+#define SPI_EEPROM_READ		0x03
+#define SPI_EEPROM_WRITE	0x02
+
+/* ---------------------------------------------------------------
+ * Offset for initial SPI buffers in DPRAM:
+ * We need a 520 byte scratch DPRAM area to use at an early stage.
+ * It is used between the two initialization calls (spi_init_f()
+ * and spi_init_r()).
+ * The value 0x2000 makes it far enough from the start of the data
+ * area (as well as from the stack pointer).
+ * --------------------------------------------------------------- */
+#ifndef	CONFIG_SYS_SPI_INIT_OFFSET
+#define	CONFIG_SYS_SPI_INIT_OFFSET	0x2000
+#endif
+
+#define CPM_SPI_BASE 0x100
+
+#ifdef	DEBUG
+
+#define	DPRINT(a)	printf a;
+/* -----------------------------------------------
+ * Helper functions to peek into tx and rx buffers
+ * ----------------------------------------------- */
+static const char * const hex_digit = "0123456789ABCDEF";
+
+static char quickhex (int i)
+{
+	return hex_digit[i];
+}
+
+static void memdump (void *pv, int num)
+{
+	int i;
+	unsigned char *pc = (unsigned char *) pv;
+
+	for (i = 0; i < num; i++)
+		printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f));
+	printf ("\t");
+	for (i = 0; i < num; i++)
+		printf ("%c", isprint (pc[i]) ? pc[i] : '.');
+	printf ("\n");
+}
+#else	/* !DEBUG */
+
+#define	DPRINT(a)
+
+#endif	/* DEBUG */
+
+/* -------------------
+ * Function prototypes
+ * ------------------- */
+void spi_init (void);
+
+ssize_t spi_read (uchar *, int, uchar *, int);
+ssize_t spi_write (uchar *, int, uchar *, int);
+ssize_t spi_xfer (size_t);
+
+/* -------------------
+ * Variables
+ * ------------------- */
+
+#define MAX_BUFFER	0x104
+
+/* ----------------------------------------------------------------------
+ * Initially we place the RX and TX buffers at a fixed location in DPRAM!
+ * ---------------------------------------------------------------------- */
+static uchar *rxbuf =
+  (uchar *)&((immap_t *)CONFIG_SYS_IMMR)->im_dprambase
+			[CONFIG_SYS_SPI_INIT_OFFSET];
+static uchar *txbuf =
+  (uchar *)&((immap_t *)CONFIG_SYS_IMMR)->im_dprambase
+			[CONFIG_SYS_SPI_INIT_OFFSET+MAX_BUFFER];
+
+/* **************************************************************************
+ *
+ *  Function:    spi_init_f
+ *
+ *  Description: Init SPI-Controller (ROM part)
+ *
+ *  return:      ---
+ *
+ * *********************************************************************** */
+void spi_init_f (void)
+{
+	unsigned int dpaddr;
+
+	volatile spi_t *spi;
+	volatile immap_t *immr;
+	volatile cpm8260_t *cp;
+	volatile cbd_t *tbdf, *rbdf;
+
+	immr = (immap_t *)  CONFIG_SYS_IMMR;
+	cp   = (cpm8260_t *) &immr->im_cpm;
+
+	*(ushort *)(&immr->im_dprambase[PROFF_SPI_BASE]) = PROFF_SPI;
+	spi  = (spi_t *)&immr->im_dprambase[PROFF_SPI];
+
+/* 1 */
+	/* ------------------------------------------------
+	 * Initialize Port D SPI pins
+	 * (we are only in Master Mode !)
+	 * ------------------------------------------------ */
+
+	/* --------------------------------------------
+	 * GPIO or per. Function
+	 * PPARD[16] = 1 [0x00008000] (SPIMISO)
+	 * PPARD[17] = 1 [0x00004000] (SPIMOSI)
+	 * PPARD[18] = 1 [0x00002000] (SPICLK)
+	 * PPARD[12] = 0 [0x00080000] -> GPIO: (CS for ATC EEPROM)
+	 * -------------------------------------------- */
+	immr->im_ioport.iop_ppard |=  0x0000E000;	/* set  bits	*/
+	immr->im_ioport.iop_ppard &= ~0x00080000;	/* reset bit	*/
+
+	/* ----------------------------------------------
+	 * In/Out or per. Function 0/1
+	 * PDIRD[16] = 0 [0x00008000] -> PERI1: SPIMISO
+	 * PDIRD[17] = 0 [0x00004000] -> PERI1: SPIMOSI
+	 * PDIRD[18] = 0 [0x00002000] -> PERI1: SPICLK
+	 * PDIRD[12] = 1 [0x00080000] -> GPIO OUT: CS for ATC EEPROM
+	 * ---------------------------------------------- */
+	immr->im_ioport.iop_pdird &= ~0x0000E000;
+	immr->im_ioport.iop_pdird |= 0x00080000;
+
+	/* ----------------------------------------------
+	 * special option reg.
+	 * PSORD[16] = 1 [0x00008000] -> SPIMISO
+	 * PSORD[17] = 1 [0x00004000] -> SPIMOSI
+	 * PSORD[18] = 1 [0x00002000] -> SPICLK
+	 * ---------------------------------------------- */
+	immr->im_ioport.iop_psord |= 0x0000E000;
+
+	/* Initialize the parameter ram.
+	 * We need to make sure many things are initialized to zero
+	 */
+	spi->spi_rstate	= 0;
+	spi->spi_rdp	= 0;
+	spi->spi_rbptr	= 0;
+	spi->spi_rbc	= 0;
+	spi->spi_rxtmp	= 0;
+	spi->spi_tstate	= 0;
+	spi->spi_tdp	= 0;
+	spi->spi_tbptr	= 0;
+	spi->spi_tbc	= 0;
+	spi->spi_txtmp	= 0;
+
+	/* Allocate space for one transmit and one receive buffer
+	 * descriptor in the DP ram
+	 */
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+	dpaddr = m8260_cpm_dpalloc (sizeof(cbd_t)*2, 8);
+#else
+	dpaddr = CPM_SPI_BASE;
+#endif
+
+/* 3 */
+	/* Set up the SPI parameters in the parameter ram */
+	spi->spi_rbase = dpaddr;
+	spi->spi_tbase = dpaddr + sizeof (cbd_t);
+
+	/***********IMPORTANT******************/
+
+	/*
+	 * Setting transmit and receive buffer descriptor pointers
+	 * initially to rbase and tbase. Only the microcode patches
+	 * documentation talks about initializing this pointer. This
+	 * is missing from the sample I2C driver. If you dont
+	 * initialize these pointers, the kernel hangs.
+	 */
+	spi->spi_rbptr = spi->spi_rbase;
+	spi->spi_tbptr = spi->spi_tbase;
+
+/* 4 */
+	/* Init SPI Tx + Rx Parameters */
+	while (cp->cp_cpcr & CPM_CR_FLG)
+		;
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK,
+							0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG)
+		;
+
+/* 6 */
+	/* Set to big endian. */
+	spi->spi_tfcr = CPMFCR_EB;
+	spi->spi_rfcr = CPMFCR_EB;
+
+/* 7 */
+	/* Set maximum receive size. */
+	spi->spi_mrblr = MAX_BUFFER;
+
+/* 8 + 9 */
+	/* tx and rx buffer descriptors */
+	tbdf = (cbd_t *) & immr->im_dprambase[spi->spi_tbase];
+	rbdf = (cbd_t *) & immr->im_dprambase[spi->spi_rbase];
+
+	tbdf->cbd_sc &= ~BD_SC_READY;
+	rbdf->cbd_sc &= ~BD_SC_EMPTY;
+
+	/* Set the bd's rx and tx buffer address pointers */
+	rbdf->cbd_bufaddr = (ulong) rxbuf;
+	tbdf->cbd_bufaddr = (ulong) txbuf;
+
+/* 10 + 11 */
+	immr->im_spi.spi_spie = SPI_EMASK;		/* Clear all SPI events	*/
+	immr->im_spi.spi_spim = 0x00;			/* Mask  all SPI events */
+
+
+	return;
+}
+
+/* **************************************************************************
+ *
+ *  Function:    spi_init_r
+ *
+ *  Description: Init SPI-Controller (RAM part) -
+ *		 The malloc engine is ready and we can move our buffers to
+ *		 normal RAM
+ *
+ *  return:      ---
+ *
+ * *********************************************************************** */
+void spi_init_r (void)
+{
+	volatile spi_t *spi;
+	volatile immap_t *immr;
+	volatile cpm8260_t *cp;
+	volatile cbd_t *tbdf, *rbdf;
+
+	immr = (immap_t *)  CONFIG_SYS_IMMR;
+	cp   = (cpm8260_t *) &immr->im_cpm;
+
+	spi  = (spi_t *)&immr->im_dprambase[PROFF_SPI];
+
+	/* tx and rx buffer descriptors */
+	tbdf = (cbd_t *) & immr->im_dprambase[spi->spi_tbase];
+	rbdf = (cbd_t *) & immr->im_dprambase[spi->spi_rbase];
+
+	/* Allocate memory for RX and TX buffers */
+	rxbuf = (uchar *) malloc (MAX_BUFFER);
+	txbuf = (uchar *) malloc (MAX_BUFFER);
+
+	rbdf->cbd_bufaddr = (ulong) rxbuf;
+	tbdf->cbd_bufaddr = (ulong) txbuf;
+
+	return;
+}
+
+/****************************************************************************
+ *  Function:    spi_write
+ **************************************************************************** */
+ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
+{
+	int i;
+
+	memset(rxbuf, 0, MAX_BUFFER);
+	memset(txbuf, 0, MAX_BUFFER);
+	*txbuf = SPI_EEPROM_WREN;		/* write enable		*/
+	spi_xfer(1);
+	memcpy(txbuf, addr, alen);
+	*txbuf = SPI_EEPROM_WRITE;		/* WRITE memory array	*/
+	memcpy(alen + txbuf, buffer, len);
+	spi_xfer(alen + len);
+						/* ignore received data	*/
+	for (i = 0; i < 1000; i++) {
+		*txbuf = SPI_EEPROM_RDSR;	/* read status		*/
+		txbuf[1] = 0;
+		spi_xfer(2);
+		if (!(rxbuf[1] & 1)) {
+			break;
+		}
+		udelay(1000);
+	}
+	if (i >= 1000) {
+		printf ("*** spi_write: Time out while writing!\n");
+	}
+
+	return len;
+}
+
+/****************************************************************************
+ *  Function:    spi_read
+ **************************************************************************** */
+ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len)
+{
+	memset(rxbuf, 0, MAX_BUFFER);
+	memset(txbuf, 0, MAX_BUFFER);
+	memcpy(txbuf, addr, alen);
+	*txbuf = SPI_EEPROM_READ;		/* READ memory array	*/
+
+	/*
+	 * There is a bug in 860T (?) that cuts the last byte of input
+	 * if we're reading into DPRAM. The solution we choose here is
+	 * to always read len+1 bytes (we have one extra byte at the
+	 * end of the buffer).
+	 */
+	spi_xfer(alen + len + 1);
+	memcpy(buffer, alen + rxbuf, len);
+
+	return len;
+}
+
+/****************************************************************************
+ *  Function:    spi_xfer
+ **************************************************************************** */
+ssize_t spi_xfer (size_t count)
+{
+	volatile immap_t *immr;
+	volatile cpm8260_t *cp;
+	volatile spi_t *spi;
+	cbd_t *tbdf, *rbdf;
+	int tm;
+
+	DPRINT (("*** spi_xfer entered ***\n"));
+
+	immr = (immap_t *) CONFIG_SYS_IMMR;
+	cp   = (cpm8260_t *) &immr->im_cpm;
+
+	spi  = (spi_t *)&immr->im_dprambase[PROFF_SPI];
+
+	tbdf = (cbd_t *) & immr->im_dprambase[spi->spi_tbase];
+	rbdf = (cbd_t *) & immr->im_dprambase[spi->spi_rbase];
+
+	/* Board-specific: Set CS for device (ATC EEPROM) */
+	immr->im_ioport.iop_pdatd &= ~0x00080000;
+
+	/* Setting tx bd status and data length */
+	tbdf->cbd_sc  = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP;
+	tbdf->cbd_datlen = count;
+
+	DPRINT (("*** spi_xfer: Bytes to be xferred: %d ***\n",
+							tbdf->cbd_datlen));
+
+	/* Setting rx bd status and data length */
+	rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+	rbdf->cbd_datlen = 0;	 /* rx length has no significance */
+
+	immr->im_spi.spi_spmode = SPMODE_REV	|
+			SPMODE_MSTR	|
+			SPMODE_EN	|
+			SPMODE_LEN(8)	|	/* 8 Bits per char */
+			SPMODE_PM(0x8) ;	/* medium speed */
+	immr->im_spi.spi_spie = SPI_EMASK;		/* Clear all SPI events	*/
+	immr->im_spi.spi_spim = 0x00;			/* Mask  all SPI events */
+
+	/* start spi transfer */
+	DPRINT (("*** spi_xfer: Performing transfer ...\n"));
+	immr->im_spi.spi_spcom |= SPI_STR;		/* Start transmit */
+
+	/* --------------------------------
+	 * Wait for SPI transmit to get out
+	 * or time out (1 second = 1000 ms)
+	 * -------------------------------- */
+	for (tm=0; tm<1000; ++tm) {
+		if (immr->im_spi.spi_spie & SPI_TXB) {	/* Tx Buffer Empty */
+			DPRINT (("*** spi_xfer: Tx buffer empty\n"));
+			break;
+		}
+		if ((tbdf->cbd_sc & BD_SC_READY) == 0) {
+			DPRINT (("*** spi_xfer: Tx BD done\n"));
+			break;
+		}
+		udelay (1000);
+	}
+	if (tm >= 1000) {
+		printf ("*** spi_xfer: Time out while xferring to/from SPI!\n");
+	}
+	DPRINT (("*** spi_xfer: ... transfer ended\n"));
+
+#ifdef	DEBUG
+	printf ("\nspi_xfer: txbuf after xfer\n");
+	memdump ((void *) txbuf, 16);	/* dump of txbuf before transmit */
+	printf ("spi_xfer: rxbuf after xfer\n");
+	memdump ((void *) rxbuf, 16);	/* dump of rxbuf after transmit */
+	printf ("\n");
+#endif
+
+	/* Clear CS for device */
+	immr->im_ioport.iop_pdatd |= 0x00080000;
+
+	return count;
+}
+#endif	/* CONFIG_SPI */
diff --git a/arch/powerpc/cpu/mpc8260/start.S b/arch/powerpc/cpu/mpc8260/start.S
new file mode 100644
index 0000000..a435042
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/start.S
@@ -0,0 +1,1023 @@
+/*
+ *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000, 2001,2002 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ *  U-Boot - Startup Code for MPC8260 PowerPC based Embedded Boards
+ */
+#include <config.h>
+#include <mpc8260.h>
+#include <timestamp.h>
+#include <version.h>
+
+#define CONFIG_8260 1		/* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1	/* avoid reading Linux autoconf.h file	*/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef  CONFIG_IDENT_STRING
+#define  CONFIG_IDENT_STRING ""
+#endif
+
+/* We don't want the  MMU yet.
+*/
+#undef	MSR_KERNEL
+/* Floating Point enable, Machine Check and Recoverable Interr. */
+#ifdef DEBUG
+#define MSR_KERNEL (MSR_FP|MSR_RI)
+#else
+#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
+#endif
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+	START_GOT
+	GOT_ENTRY(_GOT2_TABLE_)
+	GOT_ENTRY(_FIXUP_TABLE_)
+
+	GOT_ENTRY(_start)
+	GOT_ENTRY(_start_of_vectors)
+	GOT_ENTRY(_end_of_vectors)
+	GOT_ENTRY(transfer_to_handler)
+
+	GOT_ENTRY(__init_end)
+	GOT_ENTRY(_end)
+	GOT_ENTRY(__bss_start)
+#if defined(CONFIG_HYMOD)
+	GOT_ENTRY(environment)
+#endif
+	END_GOT
+
+/*
+ * Version string - must be in data segment because MPC8260 uses the first
+ * 256 bytes for the Hard Reset Configuration Word table (see below).
+ * Similarly, can't have the U-Boot Magic Number as the first thing in
+ * the image - don't know how this will affect the image tools, but I guess
+ * I'll find out soon
+ */
+	.data
+	.globl	version_string
+version_string:
+	.ascii U_BOOT_VERSION
+	.ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
+	.ascii CONFIG_IDENT_STRING, "\0"
+
+/*
+ *  Hard Reset Configuration Word (HRCW) table
+ *
+ *  The Hard Reset Configuration Word (HRCW) sets a number of useful things
+ *  such as whether there is an external memory controller, whether the
+ *  PowerPC core is disabled (i.e. only the communications processor is
+ *  active, accessed by another CPU on the bus), whether using external
+ *  arbitration, external bus mode, boot port size, core initial prefix,
+ *  internal space base, boot memory space, etc.
+ *
+ *  These things dictate where the processor begins execution, where the
+ *  boot ROM appears in memory, the memory controller setup when access
+ *  boot ROM, etc. The HRCW is *extremely* important.
+ *
+ *  The HRCW is read from the bus during reset. One CPU on the bus will
+ *  be a hard reset configuration master, any others will be hard reset
+ *  configuration slaves. The master reads eight HRCWs from flash during
+ *  reset - the first it uses for itself, the other 7 it communicates to
+ *  up to 7 configuration slaves by some complicated mechanism, which is
+ *  not really important here.
+ *
+ *  The configuration master performs 32 successive reads starting at address
+ *  0 and incrementing by 8 each read (i.e. on 64 bit boundaries) but only 8
+ *  bits is read, and always from byte lane D[0-7] (so that port size of the
+ *  boot device does not matter). The first four reads form the 32 bit HRCW
+ *  for the master itself. The second four reads form the HRCW for the first
+ *  slave, and so on, up to seven slaves. The 32 bit HRCW is formed by
+ *  concatenating the four bytes, with the first read placed in byte 0 (the
+ *  most significant byte), and so on with the fourth read placed in byte 3
+ *  (the least significant byte).
+ */
+#define _HRCW_TABLE_ENTRY(w)		\
+	.fill	8,1,(((w)>>24)&0xff);	\
+	.fill	8,1,(((w)>>16)&0xff);	\
+	.fill	8,1,(((w)>> 8)&0xff);	\
+	.fill	8,1,(((w)    )&0xff)
+	.text
+	.globl	_hrcw_table
+_hrcw_table:
+	_HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_MASTER)
+	_HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE1)
+	_HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE2)
+	_HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE3)
+	_HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE4)
+	_HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE5)
+	_HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE6)
+	_HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE7)
+/*
+ *  After configuration, a system reset exception is executed using the
+ *  vector at offset 0x100 relative to the base set by MSR[IP]. If MSR[IP]
+ *  is 0, the base address is 0x00000000. If MSR[IP] is 1, the base address
+ *  is 0xfff00000. In the case of a Power On Reset or Hard Reset, the value
+ *  of MSR[IP] is determined by the CIP field in the HRCW.
+ *
+ *  Other bits in the HRCW set up the Base Address and Port Size in BR0.
+ *  This determines the location of the boot ROM (flash or EPROM) in the
+ *  processor's address space at boot time. As long as the HRCW is set up
+ *  so that we eventually end up executing the code below when the processor
+ *  executes the reset exception, the actual values used should not matter.
+ *
+ *  Once we have got here, the address mask in OR0 is cleared so that the
+ *  bottom 32K of the boot ROM is effectively repeated all throughout the
+ *  processor's address space, after which we can jump to the absolute
+ *  address at which the boot ROM was linked at compile time, and proceed
+ *  to initialise the memory controller without worrying if the rug will be
+ *  pulled out from under us, so to speak (it will be fine as long as we
+ *  configure BR0 with the same boot ROM link address).
+ */
+	. = EXC_OFF_SYS_RESET
+
+	.globl	_start
+_start:
+	li	r21, BOOTFLAG_COLD	/* Normal Power-On: Boot from FLASH*/
+	nop
+	b	boot_cold
+
+	. = EXC_OFF_SYS_RESET + 0x10
+
+	.globl	_start_warm
+_start_warm:
+	li	r21, BOOTFLAG_WARM	/* Software reboot		*/
+	b	boot_warm
+
+boot_cold:
+#if defined(CONFIG_MPC8260ADS) && defined(CONFIG_SYS_DEFAULT_IMMR)
+	lis	r3, CONFIG_SYS_DEFAULT_IMMR@h
+	nop
+	lwz	r4, 0(r3)
+	nop
+	rlwinm	r4, r4, 0, 8, 5
+	nop
+	oris	r4, r4, 0x0200
+	nop
+	stw	r4, 0(r3)
+	nop
+#endif /* CONFIG_MPC8260ADS && CONFIG_SYS_DEFAULT_IMMR */
+boot_warm:
+	mfmsr	r5			/* save msr contents		*/
+
+#if defined(CONFIG_COGENT)
+	/* this is what the cogent EPROM does */
+	li	r0, 0
+	mtmsr	r0
+	isync
+	bl	cogent_init_8260
+#endif	/* CONFIG_COGENT */
+
+#if defined(CONFIG_SYS_DEFAULT_IMMR)
+	lis	r3, CONFIG_SYS_IMMR@h
+	ori	r3, r3, CONFIG_SYS_IMMR@l
+	lis	r4, CONFIG_SYS_DEFAULT_IMMR@h
+	stw	r3, 0x1A8(r4)
+#endif /* CONFIG_SYS_DEFAULT_IMMR */
+
+	/* Initialise the MPC8260 processor core			*/
+	/*--------------------------------------------------------------*/
+
+	bl	init_8260_core
+
+#ifndef CONFIG_SYS_RAMBOOT
+	/* When booting from ROM (Flash or EPROM), clear the		*/
+	/* Address Mask in OR0 so ROM appears everywhere		*/
+	/*--------------------------------------------------------------*/
+
+	lis	r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
+	lwz	r4, IM_OR0@l(r3)
+	li	r5, 0x7fff
+	and	r4, r4, r5
+	stw	r4, IM_OR0@l(r3)
+
+	/* Calculate absolute address in FLASH and jump there		*/
+	/*--------------------------------------------------------------*/
+
+	lis	r3, CONFIG_SYS_MONITOR_BASE@h
+	ori	r3, r3, CONFIG_SYS_MONITOR_BASE@l
+	addi	r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+	mtlr	r3
+	blr
+
+in_flash:
+#endif	/* CONFIG_SYS_RAMBOOT */
+
+	/* initialize some things that are hard to access from C	*/
+	/*--------------------------------------------------------------*/
+
+	lis	r3, CONFIG_SYS_IMMR@h		/* set up stack in internal DPRAM */
+	ori	r1, r3, CONFIG_SYS_INIT_SP_OFFSET
+	li	r0, 0			/* Make room for stack frame header and	*/
+	stwu	r0, -4(r1)		/* clear final stack frame so that	*/
+	stwu	r0, -4(r1)		/* stack backtraces terminate cleanly	*/
+
+	/* let the C-code set up the rest				*/
+	/*								*/
+	/* Be careful to keep code relocatable !			*/
+	/*--------------------------------------------------------------*/
+
+	GET_GOT			/* initialize GOT access		*/
+
+	/* r3: IMMR */
+	bl	cpu_init_f	/* run low-level CPU init code (in Flash)*/
+
+#ifdef DEBUG
+	bl	init_debug	/* set up debugging stuff		*/
+#endif
+
+	mr	r3, r21
+	/* r3: BOOTFLAG */
+	bl	board_init_f	/* run 1st part of board init code (in Flash)*/
+
+/*
+ * Vector Table
+ */
+
+	.globl	_start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+	STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+	STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+	STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+	. = 0x600
+Alignment:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	mfspr	r4,DAR
+	stw	r4,_DAR(r21)
+	mfspr	r5,DSISR
+	stw	r5,_DSISR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+	. = 0x700
+ProgramCheck:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+		MSR_KERNEL, COPY_EE)
+
+	STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+	/* I guess we could implement decrementer, and may have
+	 * to someday for timekeeping.
+	 */
+	STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+
+	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+	STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+	STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+	STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+	STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+	STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+	STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
+#ifdef DEBUG
+	. = 0x1300
+	/*
+	 * This exception occurs when the program counter matches the
+	 * Instruction Address Breakpoint Register (IABR).
+	 *
+	 * I want the cpu to halt if this occurs so I can hunt around
+	 * with the debugger and look at things.
+	 *
+	 * When DEBUG is defined, both machine check enable (in the MSR)
+	 * and checkstop reset enable (in the reset mode register) are
+	 * turned off and so a checkstop condition will result in the cpu
+	 * halting.
+	 *
+	 * I force the cpu into a checkstop condition by putting an illegal
+	 * instruction here (at least this is the theory).
+	 *
+	 * well - that didnt work, so just do an infinite loop!
+	 */
+1:	b	1b
+#else
+	STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
+#endif
+	STD_EXCEPTION(0x1400, SMI, UnknownException)
+
+	STD_EXCEPTION(0x1500, Trap_15, UnknownException)
+	STD_EXCEPTION(0x1600, Trap_16, UnknownException)
+	STD_EXCEPTION(0x1700, Trap_17, UnknownException)
+	STD_EXCEPTION(0x1800, Trap_18, UnknownException)
+	STD_EXCEPTION(0x1900, Trap_19, UnknownException)
+	STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
+	STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+	STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
+	STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
+	STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
+	STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
+	STD_EXCEPTION(0x2000, Trap_20, UnknownException)
+	STD_EXCEPTION(0x2100, Trap_21, UnknownException)
+	STD_EXCEPTION(0x2200, Trap_22, UnknownException)
+	STD_EXCEPTION(0x2300, Trap_23, UnknownException)
+	STD_EXCEPTION(0x2400, Trap_24, UnknownException)
+	STD_EXCEPTION(0x2500, Trap_25, UnknownException)
+	STD_EXCEPTION(0x2600, Trap_26, UnknownException)
+	STD_EXCEPTION(0x2700, Trap_27, UnknownException)
+	STD_EXCEPTION(0x2800, Trap_28, UnknownException)
+	STD_EXCEPTION(0x2900, Trap_29, UnknownException)
+	STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
+	STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
+	STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
+	STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
+	STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
+	STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
+
+
+	.globl	_end_of_vectors
+_end_of_vectors:
+
+	. = 0x3000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+	.globl	transfer_to_handler
+transfer_to_handler:
+	stw	r22,_NIP(r21)
+	lis	r22,MSR_POW@h
+	andc	r23,r23,r22
+	stw	r23,_MSR(r21)
+	SAVE_GPR(7, r21)
+	SAVE_4GPRS(8, r21)
+	SAVE_8GPRS(12, r21)
+	SAVE_8GPRS(24, r21)
+	mflr	r23
+	andi.	r24,r23,0x3f00		/* get vector offset */
+	stw	r24,TRAP(r21)
+	li	r22,0
+	stw	r22,RESULT(r21)
+	lwz	r24,0(r23)		/* virtual address of handler */
+	lwz	r23,4(r23)		/* where to go when done */
+	mtspr	SRR0,r24
+	mtspr	SRR1,r20
+	mtlr	r23
+	SYNC
+	rfi				/* jump to handler, enable MMU */
+
+int_return:
+	mfmsr	r28		/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC			/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SRR0,r2
+	mtspr	SRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfi
+
+#if defined(CONFIG_COGENT)
+
+/*
+ * This code initialises the MPC8260 processor core
+ * (conforms to PowerPC 603e spec)
+ */
+
+	.globl	cogent_init_8260
+cogent_init_8260:
+
+	/* Taken from page 14 of CMA282 manual				*/
+	/*--------------------------------------------------------------*/
+
+	lis	r4, (CONFIG_SYS_IMMR+IM_REGBASE)@h
+	lis	r3, CONFIG_SYS_IMMR@h
+	stw	r3, IM_IMMR@l(r4)
+	lwz	r3, IM_IMMR@l(r4)
+	stw	r3, 0(r0)
+	lis	r3, CONFIG_SYS_SYPCR@h
+	ori	r3, r3, CONFIG_SYS_SYPCR@l
+	stw	r3, IM_SYPCR@l(r4)
+	lwz	r3, IM_SYPCR@l(r4)
+	stw	r3, 4(r0)
+	lis	r3, CONFIG_SYS_SCCR@h
+	ori	r3, r3, CONFIG_SYS_SCCR@l
+	stw	r3, IM_SCCR@l(r4)
+	lwz	r3, IM_SCCR@l(r4)
+	stw	r3, 8(r0)
+
+	/* the rest of this was disassembled from the			*/
+	/* EPROM code that came with my CMA282 CPU module		*/
+	/*--------------------------------------------------------------*/
+
+	lis	r1, 0x1234
+	ori	r1, r1, 0x5678
+	stw	r1, 0x20(r0)
+	lwz	r1, 0x20(r0)
+	stw	r1, 0x24(r0)
+	lwz	r1, 0x24(r0)
+	lis	r3, 0x0e80
+	ori	r3, r3, 0
+	stw	r1, 4(r3)
+	lwz	r1, 4(r3)
+
+	/* Done!							*/
+	/*--------------------------------------------------------------*/
+
+	blr
+
+#endif	/* CONFIG_COGENT */
+
+/*
+ * This code initialises the MPC8260 processor core
+ * (conforms to PowerPC 603e spec)
+ * Note: expects original MSR contents to be in r5.
+ */
+
+	.globl	init_8260_core
+init_8260_core:
+
+	/* Initialize machine status; enable machine check interrupt	*/
+	/*--------------------------------------------------------------*/
+
+	li	r3, MSR_KERNEL		/* Set ME and RI flags */
+	rlwimi	r3, r5, 0, 25, 25	/* preserve IP bit set by HRCW */
+#ifdef DEBUG
+	rlwimi	r3, r5, 0, 21, 22	/* debugger might set SE & BE bits */
+#endif
+	SYNC				/* Some chip revs need this... */
+	mtmsr	r3
+	SYNC
+	mtspr	SRR1, r3		/* Make SRR1 match MSR */
+
+	/* Initialise the SYPCR early, and reset the watchdog (if req)	*/
+	/*--------------------------------------------------------------*/
+
+	lis	r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
+#if !defined(CONFIG_COGENT)
+	lis	r4, CONFIG_SYS_SYPCR@h
+	ori	r4, r4, CONFIG_SYS_SYPCR@l
+	stw	r4, IM_SYPCR@l(r3)
+#endif /* !CONFIG_COGENT */
+#if defined(CONFIG_WATCHDOG)
+	li	r4, 21868		/* = 0x556c */
+	sth	r4, IM_SWSR@l(r3)
+	li	r4, -21959		/* = 0xaa39 */
+	sth	r4, IM_SWSR@l(r3)
+#endif /* CONFIG_WATCHDOG */
+
+	/* Initialize the Hardware Implementation-dependent Registers	*/
+	/* HID0 also contains cache control				*/
+	/*--------------------------------------------------------------*/
+
+	lis	r3, CONFIG_SYS_HID0_INIT@h
+	ori	r3, r3, CONFIG_SYS_HID0_INIT@l
+	SYNC
+	mtspr	HID0, r3
+
+	lis	r3, CONFIG_SYS_HID0_FINAL@h
+	ori	r3, r3, CONFIG_SYS_HID0_FINAL@l
+	SYNC
+	mtspr	HID0, r3
+
+	lis	r3, CONFIG_SYS_HID2@h
+	ori	r3, r3, CONFIG_SYS_HID2@l
+	mtspr	HID2, r3
+
+	/* clear all BAT's						*/
+	/*--------------------------------------------------------------*/
+
+	li	r0, 0
+	mtspr	DBAT0U, r0
+	mtspr	DBAT0L, r0
+	mtspr	DBAT1U, r0
+	mtspr	DBAT1L, r0
+	mtspr	DBAT2U, r0
+	mtspr	DBAT2L, r0
+	mtspr	DBAT3U, r0
+	mtspr	DBAT3L, r0
+	mtspr	IBAT0U, r0
+	mtspr	IBAT0L, r0
+	mtspr	IBAT1U, r0
+	mtspr	IBAT1L, r0
+	mtspr	IBAT2U, r0
+	mtspr	IBAT2L, r0
+	mtspr	IBAT3U, r0
+	mtspr	IBAT3L, r0
+	SYNC
+
+	/* invalidate all tlb's						*/
+	/*								*/
+	/* From the 603e User Manual: "The 603e provides the ability to	*/
+	/* invalidate a TLB entry. The TLB Invalidate Entry (tlbie)	*/
+	/* instruction invalidates the TLB entry indexed by the EA, and	*/
+	/* operates on both the instruction and data TLBs simultaneously*/
+	/* invalidating four TLB entries (both sets in each TLB). The	*/
+	/* index corresponds to bits 15-19 of the EA. To invalidate all	*/
+	/* entries within both TLBs, 32 tlbie instructions should be	*/
+	/* issued, incrementing this field by one each time."		*/
+	/*								*/
+	/* "Note that the tlbia instruction is not implemented on the	*/
+	/* 603e."							*/
+	/*								*/
+	/* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000	*/
+	/* incrementing by 0x1000 each time. The code below is sort of	*/
+	/* based on code in "flush_tlbs" from arch/powerpc/kernel/head.S	*/
+	/*								*/
+	/*--------------------------------------------------------------*/
+
+	li	r3, 32
+	mtctr	r3
+	li	r3, 0
+1:	tlbie	r3
+	addi	r3, r3, 0x1000
+	bdnz	1b
+	SYNC
+
+	/* Done!							*/
+	/*--------------------------------------------------------------*/
+
+	blr
+
+#ifdef DEBUG
+
+/*
+ * initialise things related to debugging.
+ *
+ * must be called after the global offset table (GOT) is initialised
+ * (GET_GOT) and after cpu_init_f() has executed.
+ */
+
+	.globl	init_debug
+init_debug:
+
+	lis	r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
+
+	/* Quick and dirty hack to enable the RAM and copy the		*/
+	/* vectors so that we can take exceptions.			*/
+	/*--------------------------------------------------------------*/
+	/* write Memory Refresh Prescaler */
+	li	r4, CONFIG_SYS_MPTPR
+	sth	r4, IM_MPTPR@l(r3)
+	/* write 60x Refresh Timer */
+	li	r4, CONFIG_SYS_PSRT
+	stb	r4, IM_PSRT@l(r3)
+	/* init the 60x SDRAM Mode Register */
+	lis	r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM)@h
+	ori	r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM)@l
+	stw	r4, IM_PSDMR@l(r3)
+	/* write Precharge All Banks command */
+	lis	r4, (CONFIG_SYS_PSDMR|PSDMR_OP_PREA)@h
+	ori	r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_PREA)@l
+	stw	r4, IM_PSDMR@l(r3)
+	stb	r0, 0(0)
+	/* write eight CBR Refresh commands */
+	lis	r4, (CONFIG_SYS_PSDMR|PSDMR_OP_CBRR)@h
+	ori	r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_CBRR)@l
+	stw	r4, IM_PSDMR@l(r3)
+	stb	r0, 0(0)
+	stb	r0, 0(0)
+	stb	r0, 0(0)
+	stb	r0, 0(0)
+	stb	r0, 0(0)
+	stb	r0, 0(0)
+	stb	r0, 0(0)
+	stb	r0, 0(0)
+	/* write Mode Register Write command */
+	lis	r4, (CONFIG_SYS_PSDMR|PSDMR_OP_MRW)@h
+	ori	r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_MRW)@l
+	stw	r4, IM_PSDMR@l(r3)
+	stb	r0, 0(0)
+	/* write Normal Operation command and enable Refresh */
+	lis	r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM|PSDMR_RFEN)@h
+	ori	r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM|PSDMR_RFEN)@l
+	stw	r4, IM_PSDMR@l(r3)
+	stb	r0, 0(0)
+	/* RAM should now be operational */
+
+#define VEC_WRD_CNT	((_end_of_vectors - _start + EXC_OFF_SYS_RESET) / 4)
+	mflr	r3
+	GET_GOT
+	mtlr	r3
+	lwz	r3, GOT(_end_of_vectors)
+	rlwinm	r4, r3, 0, 18, 31	/* _end_of_vectors & 0x3FFF	*/
+	lis	r5, VEC_WRD_CNT@h
+	ori	r5, r5, VEC_WRD_CNT@l
+	mtctr	r5
+1:
+	lwzu	r5, -4(r3)
+	stwu	r5, -4(r4)
+	bdnz	1b
+
+	/* Load the Instruction Address Breakpoint Register (IABR).	*/
+	/*								*/
+	/* The address to load is stored in the first word of dual port	*/
+	/* ram and should be preserved while the power is on, so you	*/
+	/* can plug addresses into that location then reset the cpu and	*/
+	/* this code will load that address into the IABR after the	*/
+	/* reset.							*/
+	/*								*/
+	/* When the program counter matches the contents of the IABR,	*/
+	/* an exception is generated (before the instruction at that	*/
+	/* location completes). The vector for this exception is 0x1300 */
+	/*--------------------------------------------------------------*/
+	lis	r3, CONFIG_SYS_IMMR@h
+	lwz	r3, 0(r3)
+	mtspr	IABR, r3
+
+	/* Set the entire dual port RAM (where the initial stack	*/
+	/* resides) to a known value - makes it easier to see where	*/
+	/* the stack has been written					*/
+	/*--------------------------------------------------------------*/
+	lis	r3, (CONFIG_SYS_IMMR + CONFIG_SYS_INIT_SP_OFFSET)@h
+	ori	r3, r3, (CONFIG_SYS_IMMR + CONFIG_SYS_INIT_SP_OFFSET)@l
+	li	r4, ((CONFIG_SYS_INIT_SP_OFFSET - 4) / 4)
+	mtctr	r4
+	lis	r4, 0xdeadbeaf@h
+	ori	r4, r4, 0xdeadbeaf@l
+1:
+	stwu	r4, -4(r3)
+	bdnz	1b
+
+	/* Done!							*/
+	/*--------------------------------------------------------------*/
+
+	blr
+#endif
+
+/* Cache functions.
+ *
+ * Note: requires that all cache bits in
+ * HID0 are in the low half word.
+ */
+	.globl	icache_enable
+icache_enable:
+	mfspr	r3, HID0
+	ori	r3, r3, HID0_ICE
+	lis	r4, 0
+	ori	r4, r4, HID0_ILOCK
+	andc	r3, r3, r4
+	ori	r4, r3, HID0_ICFI
+	isync
+	mtspr	HID0, r4	/* sets enable and invalidate, clears lock */
+	isync
+	mtspr	HID0, r3	/* clears invalidate */
+	blr
+
+	.globl	icache_disable
+icache_disable:
+	mfspr	r3, HID0
+	lis	r4, 0
+	ori	r4, r4, HID0_ICE|HID0_ILOCK
+	andc	r3, r3, r4
+	ori	r4, r3, HID0_ICFI
+	isync
+	mtspr	HID0, r4	/* sets invalidate, clears enable and lock */
+	isync
+	mtspr	HID0, r3	/* clears invalidate */
+	blr
+
+	.globl	icache_status
+icache_status:
+	mfspr	r3, HID0
+	rlwinm	r3, r3, HID0_ICE_BITPOS + 1, 31, 31
+	blr
+
+	.globl	dcache_enable
+dcache_enable:
+	mfspr	r3, HID0
+	ori	r3, r3, HID0_DCE
+	lis	r4, 0
+	ori	r4, r4, HID0_DLOCK
+	andc	r3, r3, r4
+	ori	r4, r3, HID0_DCI
+	sync
+	mtspr	HID0, r4	/* sets enable and invalidate, clears lock */
+	sync
+	mtspr	HID0, r3	/* clears invalidate */
+	blr
+
+	.globl	dcache_disable
+dcache_disable:
+	mfspr	r3, HID0
+	lis	r4, 0
+	ori	r4, r4, HID0_DCE|HID0_DLOCK
+	andc	r3, r3, r4
+	ori	r4, r3, HID0_DCI
+	sync
+	mtspr	HID0, r4	/* sets invalidate, clears enable and lock */
+	sync
+	mtspr	HID0, r3	/* clears invalidate */
+	blr
+
+	.globl	dcache_status
+dcache_status:
+	mfspr	r3, HID0
+	rlwinm	r3, r3, HID0_DCE_BITPOS + 1, 31, 31
+	blr
+
+	.globl get_pvr
+get_pvr:
+	mfspr	r3, PVR
+	blr
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+	.globl	relocate_code
+relocate_code:
+	mr	r1,  r3		/* Set new stack pointer		*/
+	mr	r9,  r4		/* Save copy of Global Data pointer	*/
+	mr	r10, r5		/* Save copy of Destination Address	*/
+
+	GET_GOT
+	mr	r3,  r5				/* Destination Address	*/
+	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address	*/
+	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
+	lwz	r5, GOT(__init_end)
+	sub	r5, r5, r4
+	li	r6, CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size	*/
+
+	/*
+	 * Fix GOT pointer:
+	 *
+	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+	 *
+	 * Offset:
+	 */
+	sub	r15, r10, r4
+
+	/* First our own GOT */
+	add	r12, r12, r15
+	/* then the one used by the C code */
+	add	r30, r30, r15
+
+	/*
+	 * Now relocate code
+	 */
+
+	cmplw	cr1,r3,r4
+	addi	r0,r5,3
+	srwi.	r0,r0,2
+	beq	cr1,4f		/* In place copy is not necessary	*/
+	beq	7f		/* Protect against 0 count		*/
+	mtctr	r0
+	bge	cr1,2f
+
+	la	r8,-4(r4)
+	la	r7,-4(r3)
+1:	lwzu	r0,4(r8)
+	stwu	r0,4(r7)
+	bdnz	1b
+	b	4f
+
+2:	slwi	r0,r0,2
+	add	r8,r4,r0
+	add	r7,r3,r0
+3:	lwzu	r0,-4(r8)
+	stwu	r0,-4(r7)
+	bdnz	3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:	cmpwi	r6,0
+	add	r5,r3,r5
+	beq	7f		/* Always flush prefetch queue in any case */
+	subi	r0,r6,1
+	andc	r3,r3,r0
+	mfspr	r7,HID0		/* don't do dcbst if dcache is disabled */
+	rlwinm	r7,r7,HID0_DCE_BITPOS+1,31,31
+	cmpwi	r7,0
+	beq	9f
+	mr	r4,r3
+5:	dcbst	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	5b
+	sync			/* Wait for all dcbst to complete on bus */
+9:	mfspr	r7,HID0		/* don't do icbi if icache is disabled */
+	rlwinm	r7,r7,HID0_ICE_BITPOS+1,31,31
+	cmpwi	r7,0
+	beq	7f
+	mr	r4,r3
+6:	icbi	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	6b
+7:	sync			/* Wait for all icbi to complete on bus	*/
+	isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+	mtlr	r0
+	blr
+
+in_ram:
+
+	/*
+	 * Relocation Function, r12 point to got2+0x8000
+	 *
+	 * Adjust got2 pointers, no need to check for 0, this code
+	 * already puts a few entries in the table.
+	 */
+	li	r0,__got2_entries@sectoff@l
+	la	r3,GOT(_GOT2_TABLE_)
+	lwz	r11,GOT(_GOT2_TABLE_)
+	mtctr	r0
+	sub	r11,r3,r11
+	addi	r3,r3,-4
+1:	lwzu	r0,4(r3)
+	cmpwi	r0,0
+	beq-	2f
+	add	r0,r0,r11
+	stw	r0,0(r3)
+2:	bdnz	1b
+
+	/*
+	 * Now adjust the fixups and the pointers to the fixups
+	 * in case we need to move ourselves again.
+	 */
+	li	r0,__fixup_entries@sectoff@l
+	lwz	r3,GOT(_FIXUP_TABLE_)
+	cmpwi	r0,0
+	mtctr	r0
+	addi	r3,r3,-4
+	beq	4f
+3:	lwzu	r4,4(r3)
+	lwzux	r0,r4,r11
+	add	r0,r0,r11
+	stw	r10,0(r3)
+	stw	r0,0(r4)
+	bdnz	3b
+4:
+clear_bss:
+	/*
+	 * Now clear BSS segment
+	 */
+	lwz	r3,GOT(__bss_start)
+#if defined(CONFIG_HYMOD)
+	/*
+	 * For HYMOD - the environment is the very last item in flash.
+	 * The real .bss stops just before environment starts, so only
+	 * clear up to that point.
+	 *
+	 * taken from mods for FADS board
+	 */
+	lwz	r4,GOT(environment)
+#else
+	lwz	r4,GOT(_end)
+#endif
+
+	cmplw	0, r3, r4
+	beq	6f
+
+	li	r0, 0
+5:
+	stw	r0, 0(r3)
+	addi	r3, r3, 4
+	cmplw	0, r3, r4
+	bne	5b
+6:
+
+	mr	r3, r9		/* Global Data pointer		*/
+	mr	r4, r10		/* Destination Address		*/
+	bl	board_init_r
+
+	/*
+	 * Copy exception vector code to low memory
+	 *
+	 * r3: dest_addr
+	 * r7: source address, r8: end address, r9: target address
+	 */
+	.globl	trap_init
+trap_init:
+	mflr	r4			/* save link register		*/
+	GET_GOT
+	lwz	r7, GOT(_start)
+	lwz	r8, GOT(_end_of_vectors)
+
+	li	r9, 0x100		/* reset vector always at 0x100 */
+
+	cmplw	0, r7, r8
+	bgelr				/* return if r7>=r8 - just in case */
+1:
+	lwz	r0, 0(r7)
+	stw	r0, 0(r9)
+	addi	r7, r7, 4
+	addi	r9, r9, 4
+	cmplw	0, r7, r8
+	bne	1b
+
+	/*
+	 * relocate `hdlr' and `int_return' entries
+	 */
+	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+	li	r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	2b
+
+	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	3b
+
+	li	r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	4b
+
+	mfmsr	r3			/* now that the vectors have	*/
+	lis	r7, MSR_IP@h		/* relocated into low memory	*/
+	ori	r7, r7, MSR_IP@l	/* MSR[IP] can be turned off	*/
+	andc	r3, r3, r7		/* (if it was on)		*/
+	SYNC				/* Some chip revs need this... */
+	mtmsr	r3
+	SYNC
+
+	mtlr	r4			/* restore link register    */
+	blr
diff --git a/arch/powerpc/cpu/mpc8260/traps.c b/arch/powerpc/cpu/mpc8260/traps.c
new file mode 100644
index 0000000..c116cdf
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/traps.c
@@ -0,0 +1,273 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+#include <asm/m8260_pci.h>
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM	0x02000000
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace(unsigned long *sp)
+{
+	int cnt = 0;
+	unsigned long i;
+
+	puts ("Call backtrace: ");
+	while (sp) {
+		if ((uint)sp > END_OF_MEM)
+			break;
+
+		i = sp[1];
+		if (cnt++ % 7 == 0)
+			putc ('\n');
+		printf("%08lX ", i);
+		if (cnt > 32) break;
+		sp = (unsigned long *)*sp;
+	}
+	putc ('\n');
+}
+
+void show_regs(struct pt_regs * regs)
+{
+	int i;
+
+	printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+	       regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+	printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+	       regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+	       regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+	       regs->msr&MSR_IR ? 1 : 0,
+	       regs->msr&MSR_DR ? 1 : 0);
+
+	putc ('\n');
+	for (i = 0;  i < 32;  i++) {
+		if ((i % 8) == 0) {
+			printf("GPR%02d: ", i);
+		}
+
+		printf("%08lX ", regs->gpr[i]);
+		if ((i % 8) == 7) {
+			putc ('\n');
+		}
+	}
+}
+
+
+void
+_exception(int signr, struct pt_regs *regs)
+{
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+#ifdef CONFIG_PCI
+void dump_pci (void)
+{
+
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+
+	printf ("PCI: err status %x err mask %x err ctrl %x\n",
+		le32_to_cpu (immap->im_pci.pci_esr),
+		le32_to_cpu (immap->im_pci.pci_emr),
+		le32_to_cpu (immap->im_pci.pci_ecr));
+	printf ("     error address %x error data %x ctrl %x\n",
+		le32_to_cpu (immap->im_pci.pci_eacr),
+		le32_to_cpu (immap->im_pci.pci_edcr),
+		le32_to_cpu (immap->im_pci.pci_eccr));
+
+}
+#endif
+
+void
+MachineCheckException(struct pt_regs *regs)
+{
+	unsigned long fixup;
+
+	/* Probing PCI using config cycles cause this exception
+	 * when a device is not present.  Catch it and return to
+	 * the PCI exception handler.
+	 */
+#ifdef CONFIG_PCI
+	volatile immap_t *immap  = (immap_t *)CONFIG_SYS_IMMR;
+#ifdef DEBUG
+	dump_pci();
+#endif
+	/* clear the error in the error status register */
+	if(immap->im_pci.pci_esr & cpu_to_le32(PCI_ERROR_PCI_NO_RSP)) {
+		immap->im_pci.pci_esr = cpu_to_le32(PCI_ERROR_PCI_NO_RSP);
+		return;
+	}
+#endif
+	if ((fixup = search_exception_table(regs->nip)) != 0) {
+		regs->nip = fixup;
+		return;
+	}
+
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	puts ("Machine check in kernel mode.\n"
+		"Caused by (from msr): ");
+	printf("regs %p ",regs);
+	switch( regs->msr & 0x000F0000) {
+	case (0x80000000>>12):
+		puts ("Machine check signal - probably due to mm fault\n"
+			"with mmu off\n");
+		break;
+	case (0x80000000>>13):
+		puts ("Transfer error ack signal\n");
+		break;
+	case (0x80000000>>14):
+		puts ("Data parity signal\n");
+		break;
+	case (0x80000000>>15):
+		puts ("Address parity signal\n");
+		break;
+	default:
+		puts ("Unknown values in msr\n");
+	}
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+#ifdef CONFIG_PCI
+	dump_pci();
+#endif
+	panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Program Check Exception");
+}
+
+void
+SoftEmuException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Software Emulation Exception");
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+	       regs->nip, regs->msr, regs->trap);
+	_exception(0, regs);
+}
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+void
+DebugException(struct pt_regs *regs)
+{
+
+  printf("Debugger trap at @ %lx\n", regs->nip );
+  show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+  do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading.  If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+#if 0
+	int	retval;
+
+	__asm__ __volatile__(			\
+		"1:	lwz %0,0(%1)\n"		\
+		"	eieio\n"		\
+		"	li %0,0\n"		\
+		"2:\n"				\
+		".section .fixup,\"ax\"\n"	\
+		"3:	li %0,-1\n"		\
+		"	b 2b\n"			\
+		".section __ex_table,\"a\"\n"	\
+		"	.align 2\n"		\
+		"	.long 1b,3b\n"		\
+		".text"				\
+		: "=r" (retval) : "r"(addr));
+
+	return (retval);
+#endif
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8260/u-boot.lds b/arch/powerpc/cpu/mpc8260/u-boot.lds
new file mode 100644
index 0000000..b8681e7
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/u-boot.lds
@@ -0,0 +1,122 @@
+/*
+ * (C) Copyright 2001-2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text)	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data)	}
+  .rel.rodata    : { *(.rel.rodata)	}
+  .rela.rodata   : { *(.rela.rodata)	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	}
+  .plt : { *(.plt) }
+  .text      :
+  {
+    arch/powerpc/cpu/mpc8260/start.o		(.text)
+    *(.text)
+    *(.got1)
+    . = ALIGN(16);
+    *(.eh_frame)
+    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x0FFF) & 0xFFFFF000;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+  __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  . = .;
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+
+  . = .;
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(4096);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss (NOLOAD)       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+   . = ALIGN(4);
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc83xx/Makefile b/arch/powerpc/cpu/mpc83xx/Makefile
new file mode 100644
index 0000000..15e2c18
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/Makefile
@@ -0,0 +1,62 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# Copyright 2004 Freescale Semiconductor, Inc.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(CPU).a
+
+START	= start.o
+
+COBJS-y += traps.o
+COBJS-y += cpu.o
+COBJS-y += cpu_init.o
+COBJS-y += speed.o
+COBJS-y += interrupts.o
+COBJS-y += spd_sdram.o
+COBJS-y += ecc.o
+COBJS-$(CONFIG_QE) += qe_io.o
+COBJS-$(CONFIG_FSL_SERDES) += serdes.o
+COBJS-$(CONFIG_PCI) += pci.o
+COBJS-$(CONFIG_PCIE) += pcie.o
+COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
+
+COBJS	:= $(COBJS-y)
+SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc83xx/config.mk b/arch/powerpc/cpu/mpc83xx/config.mk
new file mode 100644
index 0000000..8a3a8c1
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/config.mk
@@ -0,0 +1,29 @@
+#
+# Copyright 2004 Freescale Semiconductor, Inc.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -fPIC -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_MPC83xx -DCONFIG_E300 \
+			-ffixed-r2 -msoft-float
+
+# Use default linker script.  Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/arch/powerpc/cpu/mpc83xx/u-boot.lds
diff --git a/arch/powerpc/cpu/mpc83xx/cpu.c b/arch/powerpc/cpu/mpc83xx/cpu.c
new file mode 100644
index 0000000..51180d6
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/cpu.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * CPU specific code for the MPC83xx family.
+ *
+ * Derived from the MPC8260 and MPC85xx.
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc83xx.h>
+#include <asm/processor.h>
+#include <libfdt.h>
+#include <tsec.h>
+#include <netdev.h>
+#include <fsl_esdhc.h>
+#ifdef CONFIG_BOOTCOUNT_LIMIT
+#include <asm/immap_qe.h>
+#include <asm/io.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int checkcpu(void)
+{
+	volatile immap_t *immr;
+	ulong clock = gd->cpu_clk;
+	u32 pvr = get_pvr();
+	u32 spridr;
+	char buf[32];
+	int i;
+
+	const struct cpu_type {
+		char name[15];
+		u32 partid;
+	} cpu_type_list [] = {
+		CPU_TYPE_ENTRY(8311),
+		CPU_TYPE_ENTRY(8313),
+		CPU_TYPE_ENTRY(8314),
+		CPU_TYPE_ENTRY(8315),
+		CPU_TYPE_ENTRY(8321),
+		CPU_TYPE_ENTRY(8323),
+		CPU_TYPE_ENTRY(8343),
+		CPU_TYPE_ENTRY(8347_TBGA_),
+		CPU_TYPE_ENTRY(8347_PBGA_),
+		CPU_TYPE_ENTRY(8349),
+		CPU_TYPE_ENTRY(8358_TBGA_),
+		CPU_TYPE_ENTRY(8358_PBGA_),
+		CPU_TYPE_ENTRY(8360),
+		CPU_TYPE_ENTRY(8377),
+		CPU_TYPE_ENTRY(8378),
+		CPU_TYPE_ENTRY(8379),
+	};
+
+	immr = (immap_t *)CONFIG_SYS_IMMR;
+
+	puts("CPU:   ");
+
+	switch (pvr & 0xffff0000) {
+		case PVR_E300C1:
+			printf("e300c1, ");
+			break;
+
+		case PVR_E300C2:
+			printf("e300c2, ");
+			break;
+
+		case PVR_E300C3:
+			printf("e300c3, ");
+			break;
+
+		case PVR_E300C4:
+			printf("e300c4, ");
+			break;
+
+		default:
+			printf("Unknown core, ");
+	}
+
+	spridr = immr->sysconf.spridr;
+
+	for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++)
+		if (cpu_type_list[i].partid == PARTID_NO_E(spridr)) {
+			puts("MPC");
+			puts(cpu_type_list[i].name);
+			if (IS_E_PROCESSOR(spridr))
+				puts("E");
+			if (REVID_MAJOR(spridr) >= 2)
+				puts("A");
+			printf(", Rev: %d.%d", REVID_MAJOR(spridr),
+			       REVID_MINOR(spridr));
+			break;
+		}
+
+	if (i == ARRAY_SIZE(cpu_type_list))
+		printf("(SPRIDR %08x unknown), ", spridr);
+
+	printf(" at %s MHz, ", strmhz(buf, clock));
+
+	printf("CSB: %s MHz\n", strmhz(buf, gd->csb_clk));
+
+	return 0;
+}
+
+
+/*
+ * Program a UPM with the code supplied in the table.
+ *
+ * The 'dummy' variable is used to increment the MAD. 'dummy' is
+ * supposed to be a pointer to the memory of the device being
+ * programmed by the UPM.  The data in the MDR is written into
+ * memory and the MAD is incremented every time there's a write
+ * to 'dummy'. Unfortunately, the current prototype for this
+ * function doesn't allow for passing the address of this
+ * device, and changing the prototype will break a number lots
+ * of other code, so we need to use a round-about way of finding
+ * the value for 'dummy'.
+ *
+ * The value can be extracted from the base address bits of the
+ * Base Register (BR) associated with the specific UPM.  To find
+ * that BR, we need to scan all 8 BRs until we find the one that
+ * has its MSEL bits matching the UPM we want.  Once we know the
+ * right BR, we can extract the base address bits from it.
+ *
+ * The MxMR and the BR and OR of the chosen bank should all be
+ * configured before calling this function.
+ *
+ * Parameters:
+ * upm: 0=UPMA, 1=UPMB, 2=UPMC
+ * table: Pointer to an array of values to program
+ * size: Number of elements in the array.  Must be 64 or less.
+ */
+void upmconfig (uint upm, uint *table, uint size)
+{
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	volatile fsl_lbus_t *lbus = &immap->lbus;
+	volatile uchar *dummy = NULL;
+	const u32 msel = (upm + 4) << BR_MSEL_SHIFT;	/* What the MSEL field in BRn should be */
+	volatile u32 *mxmr = &lbus->mamr + upm;	/* Pointer to mamr, mbmr, or mcmr */
+	uint i;
+
+	/* Scan all the banks to determine the base address of the device */
+	for (i = 0; i < 8; i++) {
+		if ((lbus->bank[i].br & BR_MSEL) == msel) {
+			dummy = (uchar *) (lbus->bank[i].br & BR_BA);
+			break;
+		}
+	}
+
+	if (!dummy) {
+		printf("Error: %s() could not find matching BR\n", __FUNCTION__);
+		hang();
+	}
+
+	/* Set the OP field in the MxMR to "write" and the MAD field to 000000 */
+	*mxmr = (*mxmr & 0xCFFFFFC0) | 0x10000000;
+
+	for (i = 0; i < size; i++) {
+		lbus->mdr = table[i];
+		__asm__ __volatile__ ("sync");
+		*dummy = 0;	/* Write the value to memory and increment MAD */
+		__asm__ __volatile__ ("sync");
+		while(((*mxmr & 0x3f) != ((i + 1) & 0x3f)));
+	}
+
+	/* Set the OP field in the MxMR to "normal" and the MAD field to 000000 */
+	*mxmr &= 0xCFFFFFC0;
+}
+
+
+int
+do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	ulong msr;
+#ifndef MPC83xx_RESET
+	ulong addr;
+#endif
+
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+
+	puts("Resetting the board.\n");
+
+#ifdef MPC83xx_RESET
+
+	/* Interrupts and MMU off */
+	__asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
+
+	msr &= ~( MSR_EE | MSR_IR | MSR_DR);
+	__asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
+
+	/* enable Reset Control Reg */
+	immap->reset.rpr = 0x52535445;
+	__asm__ __volatile__ ("sync");
+	__asm__ __volatile__ ("isync");
+
+	/* confirm Reset Control Reg is enabled */
+	while(!((immap->reset.rcer) & RCER_CRE));
+
+	udelay(200);
+
+	/* perform reset, only one bit */
+	immap->reset.rcr = RCR_SWHR;
+
+#else	/* ! MPC83xx_RESET */
+
+	immap->reset.rmr = RMR_CSRE;    /* Checkstop Reset enable */
+
+	/* Interrupts and MMU off */
+	__asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
+
+	msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
+	__asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
+
+	/*
+	 * Trying to execute the next instruction at a non-existing address
+	 * should cause a machine check, resulting in reset
+	 */
+	addr = CONFIG_SYS_RESET_ADDRESS;
+
+	((void (*)(void)) addr) ();
+#endif	/* MPC83xx_RESET */
+
+	return 1;
+}
+
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ */
+
+unsigned long get_tbclk(void)
+{
+	ulong tbclk;
+
+	tbclk = (gd->bus_clk + 3L) / 4L;
+
+	return tbclk;
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset (void)
+{
+	int re_enable = disable_interrupts();
+
+	/* Reset the 83xx watchdog */
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	immr->wdt.swsrr = 0x556c;
+	immr->wdt.swsrr = 0xaa39;
+
+	if (re_enable)
+		enable_interrupts ();
+}
+#endif
+
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_UEC_ETH)
+	uec_standard_init(bis);
+#endif
+
+#if defined(CONFIG_TSEC_ENET)
+	tsec_standard_init(bis);
+#endif
+	return 0;
+}
+
+/*
+ * Initializes on-chip MMC controllers.
+ * to override, implement board_mmc_init()
+ */
+int cpu_mmc_init(bd_t *bis)
+{
+#ifdef CONFIG_FSL_ESDHC
+	return fsl_esdhc_mmc_init(bis);
+#else
+	return 0;
+#endif
+}
+
+#ifdef CONFIG_BOOTCOUNT_LIMIT
+
+#if !defined(CONFIG_MPC8360)
+#error "CONFIG_BOOTCOUNT_LIMIT only for MPC8360 implemented"
+#endif
+
+#if !defined(CONFIG_BOOTCOUNT_ADDR)
+#define CONFIG_BOOTCOUNT_ADDR	(0x110000 + QE_MURAM_SIZE - 2 * sizeof(unsigned long))
+#endif
+
+#include <asm/io.h>
+
+void bootcount_store (ulong a)
+{
+	void *reg = (void *)(CONFIG_SYS_IMMR + CONFIG_BOOTCOUNT_ADDR);
+	out_be32 (reg, a);
+	out_be32 (reg + 4, BOOTCOUNT_MAGIC);
+}
+
+ulong bootcount_load (void)
+{
+	void *reg = (void *)(CONFIG_SYS_IMMR + CONFIG_BOOTCOUNT_ADDR);
+
+	if (in_be32 (reg + 4) != BOOTCOUNT_MAGIC)
+		return 0;
+	else
+		return in_be32 (reg);
+}
+#endif /* CONFIG_BOOTCOUNT_LIMIT */
diff --git a/arch/powerpc/cpu/mpc83xx/cpu_init.c b/arch/powerpc/cpu/mpc83xx/cpu_init.c
new file mode 100644
index 0000000..75b4522
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/cpu_init.c
@@ -0,0 +1,548 @@
+/*
+ * Copyright (C) 2004-2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc83xx.h>
+#include <ioports.h>
+#include <asm/io.h>
+#ifdef CONFIG_USB_EHCI_FSL
+#include <usb/ehci-fsl.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_QE
+extern qe_iop_conf_t qe_iop_conf_tab[];
+extern void qe_config_iopin(u8 port, u8 pin, int dir,
+			 int open_drain, int assign);
+extern void qe_init(uint qe_base);
+extern void qe_reset(void);
+
+static void config_qe_ioports(void)
+{
+	u8	port, pin;
+	int	dir, open_drain, assign;
+	int	i;
+
+	for (i = 0; qe_iop_conf_tab[i].assign != QE_IOP_TAB_END; i++) {
+		port		= qe_iop_conf_tab[i].port;
+		pin		= qe_iop_conf_tab[i].pin;
+		dir		= qe_iop_conf_tab[i].dir;
+		open_drain	= qe_iop_conf_tab[i].open_drain;
+		assign		= qe_iop_conf_tab[i].assign;
+		qe_config_iopin(port, pin, dir, open_drain, assign);
+	}
+}
+#endif
+
+/*
+ * Breathe some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ * initialize the UPM's
+ */
+void cpu_init_f (volatile immap_t * im)
+{
+	__be32 acr_mask =
+#ifdef CONFIG_SYS_ACR_PIPE_DEP /* Arbiter pipeline depth */
+		(ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_ACR_RPTCNT /* Arbiter repeat count */
+		(ACR_RPTCNT << ACR_RPTCNT_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_ACR_APARK	/* Arbiter address parking mode */
+		(ACR_APARK << ACR_APARK_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_ACR_PARKM	/* Arbiter parking master */
+		(ACR_PARKM << ACR_PARKM_SHIFT) |
+#endif
+		0;
+	__be32 acr_val =
+#ifdef CONFIG_SYS_ACR_PIPE_DEP /* Arbiter pipeline depth */
+		(CONFIG_SYS_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_ACR_RPTCNT /* Arbiter repeat count */
+		(CONFIG_SYS_ACR_RPTCNT << ACR_RPTCNT_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_ACR_APARK	/* Arbiter address parking mode */
+		(CONFIG_SYS_ACR_APARK << ACR_APARK_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_ACR_PARKM	/* Arbiter parking master */
+		(CONFIG_SYS_ACR_PARKM << ACR_PARKM_SHIFT) |
+#endif
+		0;
+	__be32 spcr_mask =
+#ifdef CONFIG_SYS_SPCR_OPT /* Optimize transactions between CSB and other dev */
+		(SPCR_OPT << SPCR_OPT_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SPCR_TSECEP /* all eTSEC's Emergency priority */
+		(SPCR_TSECEP << SPCR_TSECEP_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SPCR_TSEC1EP /* TSEC1 Emergency priority */
+		(SPCR_TSEC1EP << SPCR_TSEC1EP_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SPCR_TSEC2EP /* TSEC2 Emergency priority */
+		(SPCR_TSEC2EP << SPCR_TSEC2EP_SHIFT) |
+#endif
+		0;
+	__be32 spcr_val =
+#ifdef CONFIG_SYS_SPCR_OPT
+		(CONFIG_SYS_SPCR_OPT << SPCR_OPT_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SPCR_TSECEP /* all eTSEC's Emergency priority */
+		(CONFIG_SYS_SPCR_TSECEP << SPCR_TSECEP_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SPCR_TSEC1EP /* TSEC1 Emergency priority */
+		(CONFIG_SYS_SPCR_TSEC1EP << SPCR_TSEC1EP_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SPCR_TSEC2EP /* TSEC2 Emergency priority */
+		(CONFIG_SYS_SPCR_TSEC2EP << SPCR_TSEC2EP_SHIFT) |
+#endif
+		0;
+	__be32 sccr_mask =
+#ifdef CONFIG_SYS_SCCR_ENCCM /* Encryption clock mode */
+		(SCCR_ENCCM << SCCR_ENCCM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_PCICM /* PCI & DMA clock mode */
+		(SCCR_PCICM << SCCR_PCICM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSECCM /* all TSEC's clock mode */
+		(SCCR_TSECCM << SCCR_TSECCM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC1CM /* TSEC1 clock mode */
+		(SCCR_TSEC1CM << SCCR_TSEC1CM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC2CM /* TSEC2 clock mode */
+		(SCCR_TSEC2CM << SCCR_TSEC2CM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC1ON /* TSEC1 clock switch */
+		(SCCR_TSEC1ON << SCCR_TSEC1ON_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC2ON /* TSEC2 clock switch */
+		(SCCR_TSEC2ON << SCCR_TSEC2ON_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_USBMPHCM /* USB MPH clock mode */
+		(SCCR_USBMPHCM << SCCR_USBMPHCM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_USBDRCM /* USB DR clock mode */
+		(SCCR_USBDRCM << SCCR_USBDRCM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_SATACM /* SATA controller clock mode */
+		(SCCR_SATACM << SCCR_SATACM_SHIFT) |
+#endif
+		0;
+	__be32 sccr_val =
+#ifdef CONFIG_SYS_SCCR_ENCCM /* Encryption clock mode */
+		(CONFIG_SYS_SCCR_ENCCM << SCCR_ENCCM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_PCICM /* PCI & DMA clock mode */
+		(CONFIG_SYS_SCCR_PCICM << SCCR_PCICM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSECCM /* all TSEC's clock mode */
+		(CONFIG_SYS_SCCR_TSECCM << SCCR_TSECCM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC1CM /* TSEC1 clock mode */
+		(CONFIG_SYS_SCCR_TSEC1CM << SCCR_TSEC1CM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC2CM /* TSEC2 clock mode */
+		(CONFIG_SYS_SCCR_TSEC2CM << SCCR_TSEC2CM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC1ON /* TSEC1 clock switch */
+		(CONFIG_SYS_SCCR_TSEC1ON << SCCR_TSEC1ON_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC2ON /* TSEC2 clock switch */
+		(CONFIG_SYS_SCCR_TSEC2ON << SCCR_TSEC2ON_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_USBMPHCM /* USB MPH clock mode */
+		(CONFIG_SYS_SCCR_USBMPHCM << SCCR_USBMPHCM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_USBDRCM /* USB DR clock mode */
+		(CONFIG_SYS_SCCR_USBDRCM << SCCR_USBDRCM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_SATACM /* SATA controller clock mode */
+		(CONFIG_SYS_SCCR_SATACM << SCCR_SATACM_SHIFT) |
+#endif
+		0;
+	__be32 lcrr_mask =
+#ifdef CONFIG_SYS_LCRR_DBYP /* PLL bypass */
+		LCRR_DBYP |
+#endif
+#ifdef CONFIG_SYS_LCRR_EADC /* external address delay */
+		LCRR_EADC |
+#endif
+#ifdef CONFIG_SYS_LCRR_CLKDIV /* system clock divider */
+		LCRR_CLKDIV |
+#endif
+		0;
+	__be32 lcrr_val =
+#ifdef CONFIG_SYS_LCRR_DBYP /* PLL bypass */
+		CONFIG_SYS_LCRR_DBYP |
+#endif
+#ifdef CONFIG_SYS_LCRR_EADC
+		CONFIG_SYS_LCRR_EADC |
+#endif
+#ifdef CONFIG_SYS_LCRR_CLKDIV /* system clock divider */
+		CONFIG_SYS_LCRR_CLKDIV |
+#endif
+		0;
+
+	/* Pointer is writable since we allocated a register for it */
+	gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+	/* Clear initial global data */
+	memset ((void *) gd, 0, sizeof (gd_t));
+
+	/* system performance tweaking */
+	clrsetbits_be32(&im->arbiter.acr, acr_mask, acr_val);
+
+	clrsetbits_be32(&im->sysconf.spcr, spcr_mask, spcr_val);
+
+	clrsetbits_be32(&im->clk.sccr, sccr_mask, sccr_val);
+
+	/* RSR - Reset Status Register - clear all status (4.6.1.3) */
+	gd->reset_status = __raw_readl(&im->reset.rsr);
+	__raw_writel(~(RSR_RES), &im->reset.rsr);
+
+	/* AER - Arbiter Event Register - store status */
+	gd->arbiter_event_attributes = __raw_readl(&im->arbiter.aeatr);
+	gd->arbiter_event_address = __raw_readl(&im->arbiter.aeadr);
+
+	/*
+	 * RMR - Reset Mode Register
+	 * contains checkstop reset enable (4.6.1.4)
+	 */
+	__raw_writel(RMR_CSRE & (1<<RMR_CSRE_SHIFT), &im->reset.rmr);
+
+	/* LCRR - Clock Ratio Register (10.3.1.16)
+	 * write, read, and isync per MPC8379ERM rev.1 CLKDEV field description
+	 */
+	clrsetbits_be32(&im->lbus.lcrr, lcrr_mask, lcrr_val);
+	__raw_readl(&im->lbus.lcrr);
+	isync();
+
+	/* Enable Time Base & Decrementer ( so we will have udelay() )*/
+	setbits_be32(&im->sysconf.spcr, SPCR_TBEN);
+
+	/* System General Purpose Register */
+#ifdef CONFIG_SYS_SICRH
+#if defined(CONFIG_MPC834x) || defined(CONFIG_MPC8313)
+	/* regarding to MPC34x manual rev.1 bits 28..29 must be preserved */
+	__raw_writel((im->sysconf.sicrh & 0x0000000C) | CONFIG_SYS_SICRH,
+		     &im->sysconf.sicrh);
+#else
+	__raw_writel(CONFIG_SYS_SICRH, &im->sysconf.sicrh);
+#endif
+#endif
+#ifdef CONFIG_SYS_SICRL
+	__raw_writel(CONFIG_SYS_SICRL, &im->sysconf.sicrl);
+#endif
+#ifdef CONFIG_SYS_DDRCDR /* DDR control driver register */
+	__raw_writel(CONFIG_SYS_DDRCDR, &im->sysconf.ddrcdr);
+#endif
+#ifdef CONFIG_SYS_OBIR /* Output buffer impedance register */
+	__raw_writel(CONFIG_SYS_OBIR, &im->sysconf.obir);
+#endif
+
+#ifdef CONFIG_QE
+	/* Config QE ioports */
+	config_qe_ioports();
+#endif
+
+	/*
+	 * Memory Controller:
+	 */
+
+	/* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary
+	 * addresses - these have to be modified later when FLASH size
+	 * has been determined
+	 */
+
+#if defined(CONFIG_SYS_BR0_PRELIM)  \
+	&& defined(CONFIG_SYS_OR0_PRELIM) \
+	&& defined(CONFIG_SYS_LBLAWBAR0_PRELIM) \
+	&& defined(CONFIG_SYS_LBLAWAR0_PRELIM)
+	im->lbus.bank[0].br = CONFIG_SYS_BR0_PRELIM;
+	im->lbus.bank[0].or = CONFIG_SYS_OR0_PRELIM;
+	im->sysconf.lblaw[0].bar = CONFIG_SYS_LBLAWBAR0_PRELIM;
+	im->sysconf.lblaw[0].ar = CONFIG_SYS_LBLAWAR0_PRELIM;
+#else
+#error	CONFIG_SYS_BR0_PRELIM, CONFIG_SYS_OR0_PRELIM, CONFIG_SYS_LBLAWBAR0_PRELIM & CONFIG_SYS_LBLAWAR0_PRELIM must be defined
+#endif
+
+#if defined(CONFIG_SYS_BR1_PRELIM) && defined(CONFIG_SYS_OR1_PRELIM)
+	im->lbus.bank[1].br = CONFIG_SYS_BR1_PRELIM;
+	im->lbus.bank[1].or = CONFIG_SYS_OR1_PRELIM;
+#endif
+#if defined(CONFIG_SYS_LBLAWBAR1_PRELIM) && defined(CONFIG_SYS_LBLAWAR1_PRELIM)
+	im->sysconf.lblaw[1].bar = CONFIG_SYS_LBLAWBAR1_PRELIM;
+	im->sysconf.lblaw[1].ar = CONFIG_SYS_LBLAWAR1_PRELIM;
+#endif
+#if defined(CONFIG_SYS_BR2_PRELIM) && defined(CONFIG_SYS_OR2_PRELIM)
+	im->lbus.bank[2].br = CONFIG_SYS_BR2_PRELIM;
+	im->lbus.bank[2].or = CONFIG_SYS_OR2_PRELIM;
+#endif
+#if defined(CONFIG_SYS_LBLAWBAR2_PRELIM) && defined(CONFIG_SYS_LBLAWAR2_PRELIM)
+	im->sysconf.lblaw[2].bar = CONFIG_SYS_LBLAWBAR2_PRELIM;
+	im->sysconf.lblaw[2].ar = CONFIG_SYS_LBLAWAR2_PRELIM;
+#endif
+#if defined(CONFIG_SYS_BR3_PRELIM) && defined(CONFIG_SYS_OR3_PRELIM)
+	im->lbus.bank[3].br = CONFIG_SYS_BR3_PRELIM;
+	im->lbus.bank[3].or = CONFIG_SYS_OR3_PRELIM;
+#endif
+#if defined(CONFIG_SYS_LBLAWBAR3_PRELIM) && defined(CONFIG_SYS_LBLAWAR3_PRELIM)
+	im->sysconf.lblaw[3].bar = CONFIG_SYS_LBLAWBAR3_PRELIM;
+	im->sysconf.lblaw[3].ar = CONFIG_SYS_LBLAWAR3_PRELIM;
+#endif
+#if defined(CONFIG_SYS_BR4_PRELIM) && defined(CONFIG_SYS_OR4_PRELIM)
+	im->lbus.bank[4].br = CONFIG_SYS_BR4_PRELIM;
+	im->lbus.bank[4].or = CONFIG_SYS_OR4_PRELIM;
+#endif
+#if defined(CONFIG_SYS_LBLAWBAR4_PRELIM) && defined(CONFIG_SYS_LBLAWAR4_PRELIM)
+	im->sysconf.lblaw[4].bar = CONFIG_SYS_LBLAWBAR4_PRELIM;
+	im->sysconf.lblaw[4].ar = CONFIG_SYS_LBLAWAR4_PRELIM;
+#endif
+#if defined(CONFIG_SYS_BR5_PRELIM) && defined(CONFIG_SYS_OR5_PRELIM)
+	im->lbus.bank[5].br = CONFIG_SYS_BR5_PRELIM;
+	im->lbus.bank[5].or = CONFIG_SYS_OR5_PRELIM;
+#endif
+#if defined(CONFIG_SYS_LBLAWBAR5_PRELIM) && defined(CONFIG_SYS_LBLAWAR5_PRELIM)
+	im->sysconf.lblaw[5].bar = CONFIG_SYS_LBLAWBAR5_PRELIM;
+	im->sysconf.lblaw[5].ar = CONFIG_SYS_LBLAWAR5_PRELIM;
+#endif
+#if defined(CONFIG_SYS_BR6_PRELIM) && defined(CONFIG_SYS_OR6_PRELIM)
+	im->lbus.bank[6].br = CONFIG_SYS_BR6_PRELIM;
+	im->lbus.bank[6].or = CONFIG_SYS_OR6_PRELIM;
+#endif
+#if defined(CONFIG_SYS_LBLAWBAR6_PRELIM) && defined(CONFIG_SYS_LBLAWAR6_PRELIM)
+	im->sysconf.lblaw[6].bar = CONFIG_SYS_LBLAWBAR6_PRELIM;
+	im->sysconf.lblaw[6].ar = CONFIG_SYS_LBLAWAR6_PRELIM;
+#endif
+#if defined(CONFIG_SYS_BR7_PRELIM) && defined(CONFIG_SYS_OR7_PRELIM)
+	im->lbus.bank[7].br = CONFIG_SYS_BR7_PRELIM;
+	im->lbus.bank[7].or = CONFIG_SYS_OR7_PRELIM;
+#endif
+#if defined(CONFIG_SYS_LBLAWBAR7_PRELIM) && defined(CONFIG_SYS_LBLAWAR7_PRELIM)
+	im->sysconf.lblaw[7].bar = CONFIG_SYS_LBLAWBAR7_PRELIM;
+	im->sysconf.lblaw[7].ar = CONFIG_SYS_LBLAWAR7_PRELIM;
+#endif
+#ifdef CONFIG_SYS_GPIO1_PRELIM
+	im->gpio[0].dat = CONFIG_SYS_GPIO1_DAT;
+	im->gpio[0].dir = CONFIG_SYS_GPIO1_DIR;
+#endif
+#ifdef CONFIG_SYS_GPIO2_PRELIM
+	im->gpio[1].dat = CONFIG_SYS_GPIO2_DAT;
+	im->gpio[1].dir = CONFIG_SYS_GPIO2_DIR;
+#endif
+#ifdef CONFIG_USB_EHCI_FSL
+#ifndef CONFIG_MPC834x
+	uint32_t temp;
+	struct usb_ehci *ehci = (struct usb_ehci *)CONFIG_SYS_MPC8xxx_USB_ADDR;
+
+	/* Configure interface. */
+	setbits_be32(&ehci->control, REFSEL_16MHZ | UTMI_PHY_EN);
+
+	/* Wait for clock to stabilize */
+	do {
+		temp = __raw_readl(&ehci->control);
+		udelay(1000);
+	} while (!(temp & PHY_CLK_VALID));
+#endif
+#endif
+}
+
+int cpu_init_r (void)
+{
+#ifdef CONFIG_QE
+	uint qe_base = CONFIG_SYS_IMMR + 0x00100000; /* QE immr base */
+
+	qe_init(qe_base);
+	qe_reset();
+#endif
+	return 0;
+}
+
+/*
+ * Print out the bus arbiter event
+ */
+#if defined(CONFIG_DISPLAY_AER_FULL)
+static int print_83xx_arb_event(int force)
+{
+	static char* event[] = {
+		"Address Time Out",
+		"Data Time Out",
+		"Address Only Transfer Type",
+		"External Control Word Transfer Type",
+		"Reserved Transfer Type",
+		"Transfer Error",
+		"reserved",
+		"reserved"
+	};
+	static char* master[] = {
+		"e300 Core Data Transaction",
+		"reserved",
+		"e300 Core Instruction Fetch",
+		"reserved",
+		"TSEC1",
+		"TSEC2",
+		"USB MPH",
+		"USB DR",
+		"Encryption Core",
+		"I2C Boot Sequencer",
+		"JTAG",
+		"reserved",
+		"eSDHC",
+		"PCI1",
+		"PCI2",
+		"DMA",
+		"QUICC Engine 00",
+		"QUICC Engine 01",
+		"QUICC Engine 10",
+		"QUICC Engine 11",
+		"reserved",
+		"reserved",
+		"reserved",
+		"reserved",
+		"SATA1",
+		"SATA2",
+		"SATA3",
+		"SATA4",
+		"reserved",
+		"PCI Express 1",
+		"PCI Express 2",
+		"TDM-DMAC"
+	};
+	static char *transfer[] = {
+		"Address-only, Clean Block",
+		"Address-only, lwarx reservation set",
+		"Single-beat or Burst write",
+		"reserved",
+		"Address-only, Flush Block",
+		"reserved",
+		"Burst write",
+		"reserved",
+		"Address-only, sync",
+		"Address-only, tlbsync",
+		"Single-beat or Burst read",
+		"Single-beat or Burst read",
+		"Address-only, Kill Block",
+		"Address-only, icbi",
+		"Burst read",
+		"reserved",
+		"Address-only, eieio",
+		"reserved",
+		"Single-beat write",
+		"reserved",
+		"ecowx - Illegal single-beat write",
+		"reserved",
+		"reserved",
+		"reserved",
+		"Address-only, TLB Invalidate",
+		"reserved",
+		"Single-beat or Burst read",
+		"reserved",
+		"eciwx - Illegal single-beat read",
+		"reserved",
+		"Burst read",
+		"reserved"
+	};
+
+	int etype = (gd->arbiter_event_attributes & AEATR_EVENT)
+	            >> AEATR_EVENT_SHIFT;
+	int mstr_id = (gd->arbiter_event_attributes & AEATR_MSTR_ID)
+	              >> AEATR_MSTR_ID_SHIFT;
+	int tbst = (gd->arbiter_event_attributes & AEATR_TBST)
+	           >> AEATR_TBST_SHIFT;
+	int tsize = (gd->arbiter_event_attributes & AEATR_TSIZE)
+	            >> AEATR_TSIZE_SHIFT;
+	int ttype = (gd->arbiter_event_attributes & AEATR_TTYPE)
+	            >> AEATR_TTYPE_SHIFT;
+
+	if (!force && !gd->arbiter_event_address)
+		return 0;
+
+	puts("Arbiter Event Status:\n");
+	printf("       Event Address: 0x%08lX\n", gd->arbiter_event_address);
+	printf("       Event Type:    0x%1x  = %s\n", etype, event[etype]);
+	printf("       Master ID:     0x%02x = %s\n", mstr_id, master[mstr_id]);
+	printf("       Transfer Size: 0x%1x  = %d bytes\n", (tbst<<3) | tsize,
+				tbst ? (tsize ? tsize : 8) : 16 + 8 * tsize);
+	printf("       Transfer Type: 0x%02x = %s\n", ttype, transfer[ttype]);
+
+	return gd->arbiter_event_address;
+}
+
+#elif defined(CONFIG_DISPLAY_AER_BRIEF)
+
+static int print_83xx_arb_event(int force)
+{
+	if (!force && !gd->arbiter_event_address)
+		return 0;
+
+	printf("Arbiter Event Status: AEATR=0x%08lX, AEADR=0x%08lX\n",
+		gd->arbiter_event_attributes, gd->arbiter_event_address);
+
+	return gd->arbiter_event_address;
+}
+#endif /* CONFIG_DISPLAY_AER_xxxx */
+
+/*
+ * Figure out the cause of the reset
+ */
+int prt_83xx_rsr(void)
+{
+	static struct {
+		ulong mask;
+		char *desc;
+	} bits[] = {
+		{
+		RSR_SWSR, "Software Soft"}, {
+		RSR_SWHR, "Software Hard"}, {
+		RSR_JSRS, "JTAG Soft"}, {
+		RSR_CSHR, "Check Stop"}, {
+		RSR_SWRS, "Software Watchdog"}, {
+		RSR_BMRS, "Bus Monitor"}, {
+		RSR_SRS,  "External/Internal Soft"}, {
+		RSR_HRS,  "External/Internal Hard"}
+	};
+	static int n = sizeof bits / sizeof bits[0];
+	ulong rsr = gd->reset_status;
+	int i;
+	char *sep;
+
+	puts("Reset Status:");
+
+	sep = " ";
+	for (i = 0; i < n; i++)
+		if (rsr & bits[i].mask) {
+			printf("%s%s", sep, bits[i].desc);
+			sep = ", ";
+		}
+	puts("\n");
+
+#if defined(CONFIG_DISPLAY_AER_FULL) || defined(CONFIG_DISPLAY_AER_BRIEF)
+	print_83xx_arb_event(rsr & RSR_BMRS);
+#endif
+	puts("\n");
+
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc83xx/ecc.c b/arch/powerpc/cpu/mpc83xx/ecc.c
new file mode 100644
index 0000000..f3942b4
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/ecc.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2007 Freescale Semiconductor, Inc.
+ *
+ * Dave Liu <daveliu@freescale.com>
+ * based on the contribution of Marian Balakowicz <m8@semihalf.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <common.h>
+#include <mpc83xx.h>
+#include <command.h>
+
+#if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD)
+void ecc_print_status(void)
+{
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	volatile ddr83xx_t *ddr = &immap->ddr;
+
+	printf("\nECC mode: %s\n\n",
+	       (ddr->sdram_cfg & SDRAM_CFG_ECC_EN) ? "ON" : "OFF");
+
+	/* Interrupts */
+	printf("Memory Error Interrupt Enable:\n");
+	printf("  Multiple-Bit Error Interrupt Enable: %d\n",
+	       (ddr->err_int_en & ECC_ERR_INT_EN_MBEE) ? 1 : 0);
+	printf("  Single-Bit Error Interrupt Enable: %d\n",
+	       (ddr->err_int_en & ECC_ERR_INT_EN_SBEE) ? 1 : 0);
+	printf("  Memory Select Error Interrupt Enable: %d\n\n",
+	       (ddr->err_int_en & ECC_ERR_INT_EN_MSEE) ? 1 : 0);
+
+	/* Error disable */
+	printf("Memory Error Disable:\n");
+	printf("  Multiple-Bit Error Disable: %d\n",
+	       (ddr->err_disable & ECC_ERROR_DISABLE_MBED) ? 1 : 0);
+	printf("  Sinle-Bit Error Disable: %d\n",
+	       (ddr->err_disable & ECC_ERROR_DISABLE_SBED) ? 1 : 0);
+	printf("  Memory Select Error Disable: %d\n\n",
+	       (ddr->err_disable & ECC_ERROR_DISABLE_MSED) ? 1 : 0);
+
+	/* Error injection */
+	printf("Memory Data Path Error Injection Mask High/Low: %08x %08x\n",
+	       ddr->data_err_inject_hi, ddr->data_err_inject_lo);
+
+	printf("Memory Data Path Error Injection Mask ECC:\n");
+	printf("  ECC Mirror Byte: %d\n",
+	       (ddr->ecc_err_inject & ECC_ERR_INJECT_EMB) ? 1 : 0);
+	printf("  ECC Injection Enable: %d\n",
+	       (ddr->ecc_err_inject & ECC_ERR_INJECT_EIEN) ? 1 : 0);
+	printf("  ECC Error Injection Mask: 0x%02x\n\n",
+	       ddr->ecc_err_inject & ECC_ERR_INJECT_EEIM);
+
+	/* SBE counter/threshold */
+	printf("Memory Single-Bit Error Management (0..255):\n");
+	printf("  Single-Bit Error Threshold: %d\n",
+	       (ddr->err_sbe & ECC_ERROR_MAN_SBET) >> ECC_ERROR_MAN_SBET_SHIFT);
+	printf("  Single-Bit Error Counter: %d\n\n",
+	       (ddr->err_sbe & ECC_ERROR_MAN_SBEC) >> ECC_ERROR_MAN_SBEC_SHIFT);
+
+	/* Error detect */
+	printf("Memory Error Detect:\n");
+	printf("  Multiple Memory Errors: %d\n",
+	       (ddr->err_detect & ECC_ERROR_DETECT_MME) ? 1 : 0);
+	printf("  Multiple-Bit Error: %d\n",
+	       (ddr->err_detect & ECC_ERROR_DETECT_MBE) ? 1 : 0);
+	printf("  Single-Bit Error: %d\n",
+	       (ddr->err_detect & ECC_ERROR_DETECT_SBE) ? 1 : 0);
+	printf("  Memory Select Error: %d\n\n",
+	       (ddr->err_detect & ECC_ERROR_DETECT_MSE) ? 1 : 0);
+
+	/* Capture data */
+	printf("Memory Error Address Capture: 0x%08x\n", ddr->capture_address);
+	printf("Memory Data Path Read Capture High/Low: %08x %08x\n",
+	       ddr->capture_data_hi, ddr->capture_data_lo);
+	printf("Memory Data Path Read Capture ECC: 0x%02x\n\n",
+	       ddr->capture_ecc & CAPTURE_ECC_ECE);
+
+	printf("Memory Error Attributes Capture:\n");
+	printf(" Data Beat Number: %d\n",
+	       (ddr->capture_attributes & ECC_CAPT_ATTR_BNUM) >>
+	       ECC_CAPT_ATTR_BNUM_SHIFT);
+	printf("  Transaction Size: %d\n",
+	       (ddr->capture_attributes & ECC_CAPT_ATTR_TSIZ) >>
+	       ECC_CAPT_ATTR_TSIZ_SHIFT);
+	printf("  Transaction Source: %d\n",
+	       (ddr->capture_attributes & ECC_CAPT_ATTR_TSRC) >>
+	       ECC_CAPT_ATTR_TSRC_SHIFT);
+	printf("  Transaction Type: %d\n",
+	       (ddr->capture_attributes & ECC_CAPT_ATTR_TTYP) >>
+	       ECC_CAPT_ATTR_TTYP_SHIFT);
+	printf("  Error Information Valid: %d\n\n",
+	       ddr->capture_attributes & ECC_CAPT_ATTR_VLD);
+}
+
+int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	volatile ddr83xx_t *ddr = &immap->ddr;
+	volatile u32 val;
+	u64 *addr;
+	u32 count;
+	register u64 *i;
+	u32 ret[2];
+	u32 pattern[2];
+	u32 writeback[2];
+
+	/* The pattern is written into memory to generate error */
+	pattern[0] = 0xfedcba98UL;
+	pattern[1] = 0x76543210UL;
+
+	/* After injecting error, re-initialize the memory with the value */
+	writeback[0] = 0x01234567UL;
+	writeback[1] = 0x89abcdefUL;
+
+	if (argc > 4) {
+		cmd_usage(cmdtp);
+		return 1;
+	}
+
+	if (argc == 2) {
+		if (strcmp(argv[1], "status") == 0) {
+			ecc_print_status();
+			return 0;
+		} else if (strcmp(argv[1], "captureclear") == 0) {
+			ddr->capture_address = 0;
+			ddr->capture_data_hi = 0;
+			ddr->capture_data_lo = 0;
+			ddr->capture_ecc = 0;
+			ddr->capture_attributes = 0;
+			return 0;
+		}
+	}
+	if (argc == 3) {
+		if (strcmp(argv[1], "sbecnt") == 0) {
+			val = simple_strtoul(argv[2], NULL, 10);
+			if (val > 255) {
+				printf("Incorrect Counter value, "
+				       "should be 0..255\n");
+				return 1;
+			}
+
+			val = (val << ECC_ERROR_MAN_SBEC_SHIFT);
+			val |= (ddr->err_sbe & ECC_ERROR_MAN_SBET);
+
+			ddr->err_sbe = val;
+			return 0;
+		} else if (strcmp(argv[1], "sbethr") == 0) {
+			val = simple_strtoul(argv[2], NULL, 10);
+			if (val > 255) {
+				printf("Incorrect Counter value, "
+				       "should be 0..255\n");
+				return 1;
+			}
+
+			val = (val << ECC_ERROR_MAN_SBET_SHIFT);
+			val |= (ddr->err_sbe & ECC_ERROR_MAN_SBEC);
+
+			ddr->err_sbe = val;
+			return 0;
+		} else if (strcmp(argv[1], "errdisable") == 0) {
+			val = ddr->err_disable;
+
+			if (strcmp(argv[2], "+sbe") == 0) {
+				val |= ECC_ERROR_DISABLE_SBED;
+			} else if (strcmp(argv[2], "+mbe") == 0) {
+				val |= ECC_ERROR_DISABLE_MBED;
+			} else if (strcmp(argv[2], "+mse") == 0) {
+				val |= ECC_ERROR_DISABLE_MSED;
+			} else if (strcmp(argv[2], "+all") == 0) {
+				val |= (ECC_ERROR_DISABLE_SBED |
+					ECC_ERROR_DISABLE_MBED |
+					ECC_ERROR_DISABLE_MSED);
+			} else if (strcmp(argv[2], "-sbe") == 0) {
+				val &= ~ECC_ERROR_DISABLE_SBED;
+			} else if (strcmp(argv[2], "-mbe") == 0) {
+				val &= ~ECC_ERROR_DISABLE_MBED;
+			} else if (strcmp(argv[2], "-mse") == 0) {
+				val &= ~ECC_ERROR_DISABLE_MSED;
+			} else if (strcmp(argv[2], "-all") == 0) {
+				val &= ~(ECC_ERROR_DISABLE_SBED |
+					 ECC_ERROR_DISABLE_MBED |
+					 ECC_ERROR_DISABLE_MSED);
+			} else {
+				printf("Incorrect err_disable field\n");
+				return 1;
+			}
+
+			ddr->err_disable = val;
+			__asm__ __volatile__("sync");
+			__asm__ __volatile__("isync");
+			return 0;
+		} else if (strcmp(argv[1], "errdetectclr") == 0) {
+			val = ddr->err_detect;
+
+			if (strcmp(argv[2], "mme") == 0) {
+				val |= ECC_ERROR_DETECT_MME;
+			} else if (strcmp(argv[2], "sbe") == 0) {
+				val |= ECC_ERROR_DETECT_SBE;
+			} else if (strcmp(argv[2], "mbe") == 0) {
+				val |= ECC_ERROR_DETECT_MBE;
+			} else if (strcmp(argv[2], "mse") == 0) {
+				val |= ECC_ERROR_DETECT_MSE;
+			} else if (strcmp(argv[2], "all") == 0) {
+				val |= (ECC_ERROR_DETECT_MME |
+					ECC_ERROR_DETECT_MBE |
+					ECC_ERROR_DETECT_SBE |
+					ECC_ERROR_DETECT_MSE);
+			} else {
+				printf("Incorrect err_detect field\n");
+				return 1;
+			}
+
+			ddr->err_detect = val;
+			return 0;
+		} else if (strcmp(argv[1], "injectdatahi") == 0) {
+			val = simple_strtoul(argv[2], NULL, 16);
+
+			ddr->data_err_inject_hi = val;
+			return 0;
+		} else if (strcmp(argv[1], "injectdatalo") == 0) {
+			val = simple_strtoul(argv[2], NULL, 16);
+
+			ddr->data_err_inject_lo = val;
+			return 0;
+		} else if (strcmp(argv[1], "injectecc") == 0) {
+			val = simple_strtoul(argv[2], NULL, 16);
+			if (val > 0xff) {
+				printf("Incorrect ECC inject mask, "
+				       "should be 0x00..0xff\n");
+				return 1;
+			}
+			val |= (ddr->ecc_err_inject & ~ECC_ERR_INJECT_EEIM);
+
+			ddr->ecc_err_inject = val;
+			return 0;
+		} else if (strcmp(argv[1], "inject") == 0) {
+			val = ddr->ecc_err_inject;
+
+			if (strcmp(argv[2], "en") == 0)
+				val |= ECC_ERR_INJECT_EIEN;
+			else if (strcmp(argv[2], "dis") == 0)
+				val &= ~ECC_ERR_INJECT_EIEN;
+			else
+				printf("Incorrect command\n");
+
+			ddr->ecc_err_inject = val;
+			__asm__ __volatile__("sync");
+			__asm__ __volatile__("isync");
+			return 0;
+		} else if (strcmp(argv[1], "mirror") == 0) {
+			val = ddr->ecc_err_inject;
+
+			if (strcmp(argv[2], "en") == 0)
+				val |= ECC_ERR_INJECT_EMB;
+			else if (strcmp(argv[2], "dis") == 0)
+				val &= ~ECC_ERR_INJECT_EMB;
+			else
+				printf("Incorrect command\n");
+
+			ddr->ecc_err_inject = val;
+			return 0;
+		}
+	}
+	if (argc == 4) {
+		if (strcmp(argv[1], "testdw") == 0) {
+			addr = (u64 *) simple_strtoul(argv[2], NULL, 16);
+			count = simple_strtoul(argv[3], NULL, 16);
+
+			if ((u32) addr % 8) {
+				printf("Address not alligned on "
+				       "double word boundary\n");
+				return 1;
+			}
+			disable_interrupts();
+
+			for (i = addr; i < addr + count; i++) {
+
+				/* enable injects */
+				ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN;
+				__asm__ __volatile__("sync");
+				__asm__ __volatile__("isync");
+
+				/* write memory location injecting errors */
+				ppcDWstore((u32 *) i, pattern);
+				__asm__ __volatile__("sync");
+
+				/* disable injects */
+				ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN;
+				__asm__ __volatile__("sync");
+				__asm__ __volatile__("isync");
+
+				/* read data, this generates ECC error */
+				ppcDWload((u32 *) i, ret);
+				__asm__ __volatile__("sync");
+
+				/* re-initialize memory, double word write the location again,
+				 * generates new ECC code this time */
+				ppcDWstore((u32 *) i, writeback);
+				__asm__ __volatile__("sync");
+			}
+			enable_interrupts();
+			return 0;
+		}
+		if (strcmp(argv[1], "testword") == 0) {
+			addr = (u64 *) simple_strtoul(argv[2], NULL, 16);
+			count = simple_strtoul(argv[3], NULL, 16);
+
+			if ((u32) addr % 8) {
+				printf("Address not alligned on "
+				       "double word boundary\n");
+				return 1;
+			}
+			disable_interrupts();
+
+			for (i = addr; i < addr + count; i++) {
+
+				/* enable injects */
+				ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN;
+				__asm__ __volatile__("sync");
+				__asm__ __volatile__("isync");
+
+				/* write memory location injecting errors */
+				*(u32 *) i = 0xfedcba98UL;
+				__asm__ __volatile__("sync");
+
+				/* sub double word write,
+				 * bus will read-modify-write,
+				 * generates ECC error */
+				*((u32 *) i + 1) = 0x76543210UL;
+				__asm__ __volatile__("sync");
+
+				/* disable injects */
+				ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN;
+				__asm__ __volatile__("sync");
+				__asm__ __volatile__("isync");
+
+				/* re-initialize memory,
+				 * double word write the location again,
+				 * generates new ECC code this time */
+				ppcDWstore((u32 *) i, writeback);
+				__asm__ __volatile__("sync");
+			}
+			enable_interrupts();
+			return 0;
+		}
+	}
+	cmd_usage(cmdtp);
+	return 1;
+}
+
+U_BOOT_CMD(ecc, 4, 0, do_ecc,
+	   "support for DDR ECC features",
+	   "status              - print out status info\n"
+	   "ecc captureclear        - clear capture regs data\n"
+	   "ecc sbecnt <val>        - set Single-Bit Error counter\n"
+	   "ecc sbethr <val>        - set Single-Bit Threshold\n"
+	   "ecc errdisable <flag>   - clear/set disable Memory Error Disable, flag:\n"
+	   "  [-|+]sbe - Single-Bit Error\n"
+	   "  [-|+]mbe - Multiple-Bit Error\n"
+	   "  [-|+]mse - Memory Select Error\n"
+	   "  [-|+]all - all errors\n"
+	   "ecc errdetectclr <flag> - clear Memory Error Detect, flag:\n"
+	   "  mme - Multiple Memory Errors\n"
+	   "  sbe - Single-Bit Error\n"
+	   "  mbe - Multiple-Bit Error\n"
+	   "  mse - Memory Select Error\n"
+	   "  all - all errors\n"
+	   "ecc injectdatahi <hi>  - set Memory Data Path Error Injection Mask High\n"
+	   "ecc injectdatalo <lo>  - set Memory Data Path Error Injection Mask Low\n"
+	   "ecc injectecc <ecc>    - set ECC Error Injection Mask\n"
+	   "ecc inject <en|dis>    - enable/disable error injection\n"
+	   "ecc mirror <en|dis>    - enable/disable mirror byte\n"
+	   "ecc testdw <addr> <cnt>  - test mem region with double word access:\n"
+	   "  - enables injects\n"
+	   "  - writes pattern injecting errors with double word access\n"
+	   "  - disables injects\n"
+	   "  - reads pattern back with double word access, generates error\n"
+	   "  - re-inits memory\n"
+	   "ecc testword <addr> <cnt>  - test mem region with word access:\n"
+	   "  - enables injects\n"
+	   "  - writes pattern injecting errors with word access\n"
+	   "  - writes pattern with word access, generates error\n"
+	   "  - disables injects\n" "  - re-inits memory");
+#endif
diff --git a/arch/powerpc/cpu/mpc83xx/fdt.c b/arch/powerpc/cpu/mpc83xx/fdt.c
new file mode 100644
index 0000000..daf73a6
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/fdt.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2007 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <asm/processor.h>
+
+extern void ft_qe_setup(void *blob);
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_BOOTCOUNT_LIMIT) && defined(CONFIG_MPC8360)
+#include <asm/immap_qe.h>
+
+void fdt_fixup_muram (void *blob)
+{
+	ulong data[2];
+
+	data[0] = 0;
+	data[1] = QE_MURAM_SIZE - 2 * sizeof(unsigned long);
+	do_fixup_by_compat(blob, "fsl,qe-muram-data", "reg",
+			data, sizeof (data), 0);
+}
+#endif
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	int spridr = immr->sysconf.spridr;
+
+	/*
+	 * delete crypto node if not on an E-processor
+	 * initial revisions of the MPC834xE/6xE have the original SEC 2.0.
+	 * EA revisions got the SEC uprevved to 2.4 but since the default device
+	 * tree contains SEC 2.0 properties we uprev them here.
+	 */
+	if (!IS_E_PROCESSOR(spridr))
+		fdt_fixup_crypto_node(blob, 0);
+	else if (IS_E_PROCESSOR(spridr) &&
+		 (SPR_FAMILY(spridr) == SPR_834X_FAMILY ||
+		  SPR_FAMILY(spridr) == SPR_836X_FAMILY) &&
+		 REVID_MAJOR(spridr) >= 2)
+		fdt_fixup_crypto_node(blob, 0x0204);
+
+#if defined(CONFIG_HAS_ETH0) || defined(CONFIG_HAS_ETH1) ||\
+    defined(CONFIG_HAS_ETH2) || defined(CONFIG_HAS_ETH3) ||\
+    defined(CONFIG_HAS_ETH4) || defined(CONFIG_HAS_ETH5)
+	fdt_fixup_ethernet(blob);
+#ifdef CONFIG_MPC8313
+	/*
+	* mpc8313e erratum IPIC1 swapped TSEC interrupt ID numbers on rev. 1
+	* h/w (see AN3545).  The base device tree in use has rev. 1 ID numbers,
+	* so if on Rev. 2 (and higher) h/w, we fix them up here
+	*/
+	if (REVID_MAJOR(immr->sysconf.spridr) >= 2) {
+		int nodeoffset, path;
+		const char *prop;
+
+		nodeoffset = fdt_path_offset(blob, "/aliases");
+		if (nodeoffset >= 0) {
+#if defined(CONFIG_HAS_ETH0)
+			prop = fdt_getprop(blob, nodeoffset, "ethernet0", NULL);
+			if (prop) {
+				u32 tmp[] = { 32, 0x8, 33, 0x8, 34, 0x8 };
+
+				path = fdt_path_offset(blob, prop);
+				prop = fdt_getprop(blob, path, "interrupts", 0);
+				if (prop)
+					fdt_setprop(blob, path, "interrupts",
+						    &tmp, sizeof(tmp));
+			}
+#endif
+#if defined(CONFIG_HAS_ETH1)
+			prop = fdt_getprop(blob, nodeoffset, "ethernet1", NULL);
+			if (prop) {
+				u32 tmp[] = { 35, 0x8, 36, 0x8, 37, 0x8 };
+
+				path = fdt_path_offset(blob, prop);
+				prop = fdt_getprop(blob, path, "interrupts", 0);
+				if (prop)
+					fdt_setprop(blob, path, "interrupts",
+						    &tmp, sizeof(tmp));
+			}
+#endif
+		}
+	}
+#endif
+#endif
+
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+		"timebase-frequency", (bd->bi_busfreq / 4), 1);
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+		"bus-frequency", bd->bi_busfreq, 1);
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+		"clock-frequency", gd->core_clk, 1);
+	do_fixup_by_prop_u32(blob, "device_type", "soc", 4,
+		"bus-frequency", bd->bi_busfreq, 1);
+	do_fixup_by_compat_u32(blob, "fsl,soc",
+		"bus-frequency", bd->bi_busfreq, 1);
+	do_fixup_by_compat_u32(blob, "fsl,soc",
+		"clock-frequency", bd->bi_busfreq, 1);
+	do_fixup_by_compat_u32(blob, "fsl,immr",
+		"bus-frequency", bd->bi_busfreq, 1);
+	do_fixup_by_compat_u32(blob, "fsl,immr",
+		"clock-frequency", bd->bi_busfreq, 1);
+#ifdef CONFIG_QE
+	ft_qe_setup(blob);
+#endif
+
+#ifdef CONFIG_SYS_NS16550
+	do_fixup_by_compat_u32(blob, "ns16550",
+		"clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
+#endif
+
+	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+
+#if defined(CONFIG_BOOTCOUNT_LIMIT)
+	fdt_fixup_muram (blob);
+#endif
+}
diff --git a/arch/powerpc/cpu/mpc83xx/interrupts.c b/arch/powerpc/cpu/mpc83xx/interrupts.c
new file mode 100644
index 0000000..faffbaf
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/interrupts.c
@@ -0,0 +1,97 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <mpc83xx.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct irq_action {
+	interrupt_handler_t *handler;
+	void *arg;
+	ulong count;
+};
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+	*decrementer_count = (gd->bus_clk / 4) / CONFIG_SYS_HZ;
+
+	/* Enable e300 time base */
+
+	immr->sysconf.spcr |= 0x00400000;
+
+	return 0;
+}
+
+
+/*
+ * Handle external interrupts
+ */
+
+void external_interrupt (struct pt_regs *regs)
+{
+}
+
+
+/*
+ * Install and free an interrupt handler.
+ */
+
+void
+irq_install_handler (int irq, interrupt_handler_t * handler, void *arg)
+{
+}
+
+
+void irq_free_handler (int irq)
+{
+}
+
+
+void timer_interrupt_cpu (struct pt_regs *regs)
+{
+	/* nothing to do here */
+	return;
+}
+
+
+#if defined(CONFIG_CMD_IRQ)
+
+/* ripped this out of ppc4xx/interrupts.c */
+
+/*
+ * irqinfo - print information about PCI devices
+ */
+
+void
+do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+}
+
+#endif
diff --git a/arch/powerpc/cpu/mpc83xx/nand_init.c b/arch/powerpc/cpu/mpc83xx/nand_init.c
new file mode 100644
index 0000000..38e141a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/nand_init.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2004-2008 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc83xx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Breathe some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ * initialize the UPM's
+ */
+void cpu_init_f (volatile immap_t * im)
+{
+	int i;
+
+	/* Pointer is writable since we allocated a register for it */
+	gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+	/* Clear initial global data */
+	for (i = 0; i < sizeof(gd_t); i++)
+		((char *)gd)[i] = 0;
+
+	/* system performance tweaking */
+
+#ifdef CONFIG_SYS_ACR_PIPE_DEP
+	/* Arbiter pipeline depth */
+	im->arbiter.acr = (im->arbiter.acr & ~ACR_PIPE_DEP) |
+			  (CONFIG_SYS_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT);
+#endif
+
+#ifdef CONFIG_SYS_ACR_RPTCNT
+	/* Arbiter repeat count */
+	im->arbiter.acr = (im->arbiter.acr & ~(ACR_RPTCNT)) |
+			  (CONFIG_SYS_ACR_RPTCNT << ACR_RPTCNT_SHIFT);
+#endif
+
+#ifdef CONFIG_SYS_SPCR_OPT
+	/* Optimize transactions between CSB and other devices */
+	im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_OPT) |
+			   (CONFIG_SYS_SPCR_OPT << SPCR_OPT_SHIFT);
+#endif
+
+	/* Enable Time Base & Decrimenter (so we will have udelay()) */
+	im->sysconf.spcr |= SPCR_TBEN;
+
+	/* DDR control driver register */
+#ifdef CONFIG_SYS_DDRCDR
+	im->sysconf.ddrcdr = CONFIG_SYS_DDRCDR;
+#endif
+	/* Output buffer impedance register */
+#ifdef CONFIG_SYS_OBIR
+	im->sysconf.obir = CONFIG_SYS_OBIR;
+#endif
+
+	/*
+	 * Memory Controller:
+	 */
+
+	/* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary
+	 * addresses - these have to be modified later when FLASH size
+	 * has been determined
+	 */
+
+#if defined(CONFIG_SYS_NAND_BR_PRELIM)  \
+	&& defined(CONFIG_SYS_NAND_OR_PRELIM) \
+	&& defined(CONFIG_SYS_NAND_LBLAWBAR_PRELIM) \
+	&& defined(CONFIG_SYS_NAND_LBLAWAR_PRELIM)
+	im->lbus.bank[0].br = CONFIG_SYS_NAND_BR_PRELIM;
+	im->lbus.bank[0].or = CONFIG_SYS_NAND_OR_PRELIM;
+	im->sysconf.lblaw[0].bar = CONFIG_SYS_NAND_LBLAWBAR_PRELIM;
+	im->sysconf.lblaw[0].ar = CONFIG_SYS_NAND_LBLAWAR_PRELIM;
+#else
+#error CONFIG_SYS_NAND_BR_PRELIM, CONFIG_SYS_NAND_OR_PRELIM, CONFIG_SYS_NAND_LBLAWBAR_PRELIM & CONFIG_SYS_NAND_LBLAWAR_PRELIM must be defined
+#endif
+}
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ */
+unsigned long get_tbclk(void)
+{
+	return (gd->bus_clk + 3L) / 4L;
+}
+
+void puts(const char *str)
+{
+	while (*str)
+		putc(*str++);
+}
diff --git a/arch/powerpc/cpu/mpc83xx/pci.c b/arch/powerpc/cpu/mpc83xx/pci.c
new file mode 100644
index 0000000..a42b230
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/pci.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) Freescale Semiconductor, Inc. 2007
+ *
+ * Author: Scott Wood <scottwood@freescale.com>,
+ * with some bits from older board-specific PCI initialization.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <pci.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <fdt_support.h>
+#endif
+
+#include <asm/mpc8349_pci.h>
+
+#define MAX_BUSES 2
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static struct pci_controller pci_hose[MAX_BUSES];
+static int pci_num_buses;
+
+static void pci_init_bus(int bus, struct pci_region *reg)
+{
+	volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
+	volatile pot83xx_t *pot = immr->ios.pot;
+	volatile pcictrl83xx_t *pci_ctrl = &immr->pci_ctrl[bus];
+	struct pci_controller *hose = &pci_hose[bus];
+	u32 dev;
+	u16 reg16;
+	int i;
+
+	if (bus == 1)
+		pot += 3;
+
+	/* Setup outbound translation windows */
+	for (i = 0; i < 3; i++, reg++, pot++) {
+		if (reg->size == 0)
+			break;
+
+		hose->regions[i] = *reg;
+		hose->region_count++;
+
+		pot->potar = reg->bus_start >> 12;
+		pot->pobar = reg->phys_start >> 12;
+		pot->pocmr = ~(reg->size - 1) >> 12;
+
+		if (reg->flags & PCI_REGION_IO)
+			pot->pocmr |= POCMR_IO;
+#ifdef CONFIG_83XX_PCI_STREAMING
+		else if (reg->flags & PCI_REGION_PREFETCH)
+			pot->pocmr |= POCMR_SE;
+#endif
+
+		if (bus == 1)
+			pot->pocmr |= POCMR_DST;
+
+		pot->pocmr |= POCMR_EN;
+	}
+
+	/* Point inbound translation at RAM */
+	pci_ctrl->pitar1 = 0;
+	pci_ctrl->pibar1 = 0;
+	pci_ctrl->piebar1 = 0;
+	pci_ctrl->piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP |
+	                   PIWAR_WTT_SNOOP | (__ilog2(gd->ram_size - 1));
+
+	i = hose->region_count++;
+	hose->regions[i].bus_start = 0;
+	hose->regions[i].phys_start = 0;
+	hose->regions[i].size = gd->ram_size;
+	hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY;
+
+	hose->first_busno = pci_last_busno() + 1;
+	hose->last_busno = 0xff;
+
+	pci_setup_indirect(hose, CONFIG_SYS_IMMR + 0x8300 + bus * 0x80,
+	                         CONFIG_SYS_IMMR + 0x8304 + bus * 0x80);
+
+	pci_register_hose(hose);
+
+	/*
+	 * Write to Command register
+	 */
+	reg16 = 0xff;
+	dev = PCI_BDF(hose->first_busno, 0, 0);
+	pci_hose_read_config_word(hose, dev, PCI_COMMAND, &reg16);
+	reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
+
+	/*
+	 * Clear non-reserved bits in status register.
+	 */
+	pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
+	pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
+	pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);
+
+#ifdef CONFIG_PCI_SCAN_SHOW
+	printf("PCI:   Bus Dev VenId DevId Class Int\n");
+#endif
+#ifndef CONFIG_PCISLAVE
+	/*
+	 * Hose scan.
+	 */
+	hose->last_busno = pci_hose_scan(hose);
+#endif
+}
+
+/*
+ * The caller must have already set OCCR, and the PCI_LAW BARs
+ * must have been set to cover all of the requested regions.
+ *
+ * If fewer than three regions are requested, then the region
+ * list is terminated with a region of size 0.
+ */
+void mpc83xx_pci_init(int num_buses, struct pci_region **reg, int warmboot)
+{
+	volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
+	int i;
+
+	if (num_buses > MAX_BUSES) {
+		printf("%d PCI buses requsted, %d supported\n",
+		       num_buses, MAX_BUSES);
+
+		num_buses = MAX_BUSES;
+	}
+
+	pci_num_buses = num_buses;
+
+	/*
+	 * Release PCI RST Output signal.
+	 * Power on to RST high must be at least 100 ms as per PCI spec.
+	 * On warm boots only 1 ms is required.
+	 */
+	udelay(warmboot ? 1000 : 100000);
+
+	for (i = 0; i < num_buses; i++)
+		immr->pci_ctrl[i].gcr = 1;
+
+	/*
+	 * RST high to first config access must be at least 2^25 cycles
+	 * as per PCI spec.  This could be cut in half if we know we're
+	 * running at 66MHz.  This could be insufficiently long if we're
+	 * running the PCI bus at significantly less than 33MHz.
+	 */
+	udelay(1020000);
+
+	for (i = 0; i < num_buses; i++)
+		pci_init_bus(i, reg[i]);
+}
+
+#ifdef CONFIG_PCISLAVE
+
+#define PCI_FUNCTION_CONFIG	0x44
+#define PCI_FUNCTION_CFG_LOCK	0x20
+
+/*
+ * Unlock the configuration bit so that the host system can begin booting
+ *
+ * This should be used after you have:
+ * 1) Called mpc83xx_pci_init()
+ * 2) Set up your inbound translation windows to the appropriate size
+ */
+void mpc83xx_pcislave_unlock(int bus)
+{
+	struct pci_controller *hose = &pci_hose[bus];
+	u32 dev;
+	u16 reg16;
+
+	/* Unlock configuration lock in PCI function configuration register */
+	dev = PCI_BDF(hose->first_busno, 0, 0);
+	pci_hose_read_config_word (hose, dev, PCI_FUNCTION_CONFIG, &reg16);
+	reg16 &= ~(PCI_FUNCTION_CFG_LOCK);
+	pci_hose_write_config_word (hose, dev, PCI_FUNCTION_CONFIG, reg16);
+
+	/* The configuration bit is now unlocked, so we can scan the bus */
+	hose->last_busno = pci_hose_scan(hose);
+}
+#endif
+
+#if defined(CONFIG_OF_LIBFDT)
+void ft_pci_setup(void *blob, bd_t *bd)
+{
+	int nodeoffset;
+	int tmp[2];
+	const char *path;
+
+	if (pci_num_buses < 1)
+		return;
+
+	nodeoffset = fdt_path_offset(blob, "/aliases");
+	if (nodeoffset >= 0) {
+		path = fdt_getprop(blob, nodeoffset, "pci0", NULL);
+		if (path) {
+			tmp[0] = cpu_to_be32(pci_hose[0].first_busno);
+			tmp[1] = cpu_to_be32(pci_hose[0].last_busno);
+			do_fixup_by_path(blob, path, "bus-range",
+				&tmp, sizeof(tmp), 1);
+
+			tmp[0] = cpu_to_be32(gd->pci_clk);
+			do_fixup_by_path(blob, path, "clock-frequency",
+				&tmp, sizeof(tmp[0]), 1);
+		}
+
+		if (pci_num_buses < 2)
+			return;
+
+		path = fdt_getprop(blob, nodeoffset, "pci1", NULL);
+		if (path) {
+			tmp[0] = cpu_to_be32(pci_hose[1].first_busno);
+			tmp[1] = cpu_to_be32(pci_hose[1].last_busno);
+			do_fixup_by_path(blob, path, "bus-range",
+				&tmp, sizeof(tmp), 1);
+
+			tmp[0] = cpu_to_be32(gd->pci_clk);
+			do_fixup_by_path(blob, path, "clock-frequency",
+				&tmp, sizeof(tmp[0]), 1);
+		}
+	}
+}
+#endif /* CONFIG_OF_LIBFDT */
diff --git a/arch/powerpc/cpu/mpc83xx/pcie.c b/arch/powerpc/cpu/mpc83xx/pcie.c
new file mode 100644
index 0000000..77f8906
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/pcie.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2007-2009  Freescale Semiconductor, Inc.
+ * Copyright (C) 2008-2009  MontaVista Software, Inc.
+ *
+ * Authors: Tony Li <tony.li@freescale.com>
+ *          Anton Vorontsov <avorontsov@ru.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <mpc83xx.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define PCIE_MAX_BUSES 2
+
+#ifdef CONFIG_83XX_GENERIC_PCIE_REGISTER_HOSES
+
+static int mpc83xx_pcie_remap_cfg(struct pci_controller *hose, pci_dev_t dev)
+{
+	int bus = PCI_BUS(dev) - hose->first_busno;
+	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	pex83xx_t *pex = &immr->pciexp[bus];
+	struct pex_outbound_window *out_win = &pex->bridge.pex_outbound_win[0];
+	u8 devfn = PCI_DEV(dev) << 3 | PCI_FUNC(dev);
+	u32 dev_base = bus << 24 | devfn << 16;
+
+	if (hose->indirect_type == INDIRECT_TYPE_NO_PCIE_LINK)
+		return -1;
+	/*
+	 * Workaround for the HW bug: for Type 0 configure transactions the
+	 * PCI-E controller does not check the device number bits and just
+	 * assumes that the device number bits are 0.
+	 */
+	if (devfn & 0xf8)
+		return -1;
+
+	out_le32(&out_win->tarl, dev_base);
+	return 0;
+}
+
+#define cfg_read(val, addr, type, op) \
+	do { *val = op((type)(addr)); } while (0)
+#define cfg_write(val, addr, type, op) \
+	do { op((type *)(addr), (val)); } while (0)
+
+#define cfg_read_err(val) do { *val = -1; } while (0)
+#define cfg_write_err(val) do { } while (0)
+
+#define PCIE_OP(rw, size, type, op)					\
+static int pcie_##rw##_config_##size(struct pci_controller *hose,	\
+				     pci_dev_t dev, int offset,		\
+				     type val)				\
+{									\
+	int ret;							\
+									\
+	ret = mpc83xx_pcie_remap_cfg(hose, dev);			\
+	if (ret) {							\
+		cfg_##rw##_err(val); 					\
+		return ret; 						\
+	}								\
+	cfg_##rw(val, (void *)hose->cfg_addr + offset, type, op);	\
+	return 0;							\
+}
+
+PCIE_OP(read, byte, u8 *, in_8)
+PCIE_OP(read, word, u16 *, in_le16)
+PCIE_OP(read, dword, u32 *, in_le32)
+PCIE_OP(write, byte, u8, out_8)
+PCIE_OP(write, word, u16, out_le16)
+PCIE_OP(write, dword, u32, out_le32)
+
+static void mpc83xx_pcie_register_hose(int bus, struct pci_region *reg,
+				       u8 link)
+{
+	extern void disable_addr_trans(void); /* start.S */
+	static struct pci_controller pcie_hose[PCIE_MAX_BUSES];
+	struct pci_controller *hose = &pcie_hose[bus];
+	int i;
+
+	/*
+	 * There are no spare BATs to remap all PCI-E windows for U-Boot, so
+	 * disable translations. In general, this is not great solution, and
+	 * that's why we don't register PCI-E hoses by default.
+	 */
+	disable_addr_trans();
+
+	for (i = 0; i < 2; i++, reg++) {
+		if (reg->size == 0)
+			break;
+
+		hose->regions[i] = *reg;
+		hose->region_count++;
+	}
+
+	i = hose->region_count++;
+	hose->regions[i].bus_start = 0;
+	hose->regions[i].phys_start = 0;
+	hose->regions[i].size = gd->ram_size;
+	hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY;
+
+	i = hose->region_count++;
+	hose->regions[i].bus_start = CONFIG_SYS_IMMR;
+	hose->regions[i].phys_start = CONFIG_SYS_IMMR;
+	hose->regions[i].size = 0x100000;
+	hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY;
+
+	hose->first_busno = pci_last_busno() + 1;
+	hose->last_busno = 0xff;
+
+	if (bus == 0)
+		hose->cfg_addr = (unsigned int *)CONFIG_SYS_PCIE1_CFG_BASE;
+	else
+		hose->cfg_addr = (unsigned int *)CONFIG_SYS_PCIE2_CFG_BASE;
+
+	pci_set_ops(hose,
+			pcie_read_config_byte,
+			pcie_read_config_word,
+			pcie_read_config_dword,
+			pcie_write_config_byte,
+			pcie_write_config_word,
+			pcie_write_config_dword);
+
+	if (!link)
+		hose->indirect_type = INDIRECT_TYPE_NO_PCIE_LINK;
+
+	pci_register_hose(hose);
+
+#ifdef CONFIG_PCI_SCAN_SHOW
+	printf("PCI:   Bus Dev VenId DevId Class Int\n");
+#endif
+	/*
+	 * Hose scan.
+	 */
+	hose->last_busno = pci_hose_scan(hose);
+}
+
+#else
+
+static void mpc83xx_pcie_register_hose(int bus, struct pci_region *reg,
+				       u8 link) {}
+
+#endif /* CONFIG_83XX_GENERIC_PCIE_REGISTER_HOSES */
+
+static void mpc83xx_pcie_init_bus(int bus, struct pci_region *reg)
+{
+	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	pex83xx_t *pex = &immr->pciexp[bus];
+	struct pex_outbound_window *out_win;
+	struct pex_inbound_window *in_win;
+	void *hose_cfg_base;
+	unsigned int ram_sz;
+	unsigned int barl;
+	unsigned int tar;
+	u16 reg16;
+	int i;
+
+	/* Enable pex csb bridge inbound & outbound transactions */
+	out_le32(&pex->bridge.pex_csb_ctrl,
+		in_le32(&pex->bridge.pex_csb_ctrl) | PEX_CSB_CTRL_OBPIOE |
+		PEX_CSB_CTRL_IBPIOE);
+
+	/* Enable bridge outbound */
+	out_le32(&pex->bridge.pex_csb_obctrl, PEX_CSB_OBCTRL_PIOE |
+		PEX_CSB_OBCTRL_MEMWE | PEX_CSB_OBCTRL_IOWE |
+		PEX_CSB_OBCTRL_CFGWE);
+
+	out_win = &pex->bridge.pex_outbound_win[0];
+	if (bus) {
+		out_le32(&out_win->ar, PEX_OWAR_EN | PEX_OWAR_TYPE_CFG |
+			CONFIG_SYS_PCIE2_CFG_SIZE);
+		out_le32(&out_win->bar, CONFIG_SYS_PCIE2_CFG_BASE);
+	} else {
+		out_le32(&out_win->ar, PEX_OWAR_EN | PEX_OWAR_TYPE_CFG |
+			CONFIG_SYS_PCIE1_CFG_SIZE);
+		out_le32(&out_win->bar, CONFIG_SYS_PCIE1_CFG_BASE);
+	}
+	out_le32(&out_win->tarl, 0);
+	out_le32(&out_win->tarh, 0);
+
+	for (i = 0; i < 2; i++, reg++) {
+		u32 ar;
+
+		if (reg->size == 0)
+			break;
+
+		out_win = &pex->bridge.pex_outbound_win[i + 1];
+		out_le32(&out_win->bar, reg->phys_start);
+		out_le32(&out_win->tarl, reg->bus_start);
+		out_le32(&out_win->tarh, 0);
+		ar = PEX_OWAR_EN | (reg->size & PEX_OWAR_SIZE);
+		if (reg->flags & PCI_REGION_IO)
+			ar |= PEX_OWAR_TYPE_IO;
+		else
+			ar |= PEX_OWAR_TYPE_MEM;
+		out_le32(&out_win->ar, ar);
+	}
+
+	out_le32(&pex->bridge.pex_csb_ibctrl, PEX_CSB_IBCTRL_PIOE);
+
+	ram_sz = gd->ram_size;
+	barl = 0;
+	tar = 0;
+	i = 0;
+	while (ram_sz > 0) {
+		in_win = &pex->bridge.pex_inbound_win[i];
+		out_le32(&in_win->barl, barl);
+		out_le32(&in_win->barh, 0x0);
+		out_le32(&in_win->tar, tar);
+		if (ram_sz >= 0x10000000) {
+			/* The maxium windows size is 256M */
+			out_le32(&in_win->ar, PEX_IWAR_EN | PEX_IWAR_NSOV |
+				PEX_IWAR_TYPE_PF | 0x0FFFF000);
+			barl += 0x10000000;
+			tar += 0x10000000;
+			ram_sz -= 0x10000000;
+		} else {
+			/* The UM  is not clear here.
+			 * So, round up to even Mb boundary */
+
+			ram_sz = ram_sz >> (20 +
+					((ram_sz & 0xFFFFF) ? 1 : 0));
+			if (!(ram_sz % 2))
+				ram_sz -= 1;
+			out_le32(&in_win->ar, PEX_IWAR_EN | PEX_IWAR_NSOV |
+				PEX_IWAR_TYPE_PF | (ram_sz << 20) | 0xFF000);
+			ram_sz = 0;
+		}
+		i++;
+	}
+
+	in_win = &pex->bridge.pex_inbound_win[i];
+	out_le32(&in_win->barl, CONFIG_SYS_IMMR);
+	out_le32(&in_win->barh, 0);
+	out_le32(&in_win->tar, CONFIG_SYS_IMMR);
+	out_le32(&in_win->ar, PEX_IWAR_EN |
+		PEX_IWAR_TYPE_NO_PF | PEX_IWAR_SIZE_1M);
+
+	/* Enable the host virtual INTX interrupts */
+	out_le32(&pex->bridge.pex_int_axi_misc_enb,
+		in_le32(&pex->bridge.pex_int_axi_misc_enb) | 0x1E0);
+
+	/* Hose configure header is memory-mapped */
+	hose_cfg_base = (void *)pex;
+
+	get_clocks();
+	/* Configure the PCIE controller core clock ratio */
+	out_le32(hose_cfg_base + PEX_GCLK_RATIO,
+		(((bus ? gd->pciexp2_clk : gd->pciexp1_clk) / 1000000) * 16)
+		/ 333);
+	udelay(1000000);
+
+	/* Do Type 1 bridge configuration */
+	out_8(hose_cfg_base + PCI_PRIMARY_BUS, 0);
+	out_8(hose_cfg_base + PCI_SECONDARY_BUS, 1);
+	out_8(hose_cfg_base + PCI_SUBORDINATE_BUS, 255);
+
+	/*
+	 * Write to Command register
+	 */
+	reg16 = in_le16(hose_cfg_base + PCI_COMMAND);
+	reg16 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO |
+			PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
+	out_le16(hose_cfg_base + PCI_COMMAND, reg16);
+
+	/*
+	 * Clear non-reserved bits in status register.
+	 */
+	out_le16(hose_cfg_base + PCI_STATUS, 0xffff);
+	out_8(hose_cfg_base + PCI_LATENCY_TIMER, 0x80);
+	out_8(hose_cfg_base + PCI_CACHE_LINE_SIZE, 0x08);
+
+	printf("PCIE%d: ", bus);
+
+	reg16 = in_le16(hose_cfg_base + PCI_LTSSM);
+	if (reg16 >= PCI_LTSSM_L0)
+		printf("link\n");
+	else
+		printf("No link\n");
+
+	mpc83xx_pcie_register_hose(bus, reg, reg16 >= PCI_LTSSM_L0);
+}
+
+/*
+ * The caller must have already set SCCR, SERDES and the PCIE_LAW BARs
+ * must have been set to cover all of the requested regions.
+ */
+void mpc83xx_pcie_init(int num_buses, struct pci_region **reg, int warmboot)
+{
+	int i;
+
+	/*
+	 * Release PCI RST Output signal.
+	 * Power on to RST high must be at least 100 ms as per PCI spec.
+	 * On warm boots only 1 ms is required.
+	 */
+	udelay(warmboot ? 1000 : 100000);
+
+	for (i = 0; i < num_buses; i++)
+		mpc83xx_pcie_init_bus(i, reg[i]);
+}
diff --git a/arch/powerpc/cpu/mpc83xx/qe_io.c b/arch/powerpc/cpu/mpc83xx/qe_io.c
new file mode 100644
index 0000000..db94f00
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/qe_io.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2006 Freescale Semiconductor, Inc.
+ *
+ * Dave Liu <daveliu@freescale.com>
+ * based on source code of Shlomi Gridish
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "common.h"
+#include "asm/errno.h"
+#include "asm/io.h"
+#include "asm/immap_83xx.h"
+
+#define	NUM_OF_PINS	32
+void qe_config_iopin(u8 port, u8 pin, int dir, int open_drain, int assign)
+{
+	u32			pin_2bit_mask;
+	u32			pin_2bit_dir;
+	u32			pin_2bit_assign;
+	u32			pin_1bit_mask;
+	u32			tmp_val;
+	volatile immap_t	*im = (volatile immap_t *)CONFIG_SYS_IMMR;
+	volatile qepio83xx_t	*par_io = (volatile qepio83xx_t *)&im->qepio;
+
+	/* Caculate pin location and 2bit mask and dir */
+	pin_2bit_mask = (u32)(0x3 << (NUM_OF_PINS-(pin%(NUM_OF_PINS/2)+1)*2));
+	pin_2bit_dir = (u32)(dir << (NUM_OF_PINS-(pin%(NUM_OF_PINS/2)+1)*2));
+
+	/* Setup the direction */
+	tmp_val = (pin > (NUM_OF_PINS/2) - 1) ? \
+		in_be32(&par_io->ioport[port].dir2) :
+		in_be32(&par_io->ioport[port].dir1);
+
+	if (pin > (NUM_OF_PINS/2) -1) {
+		out_be32(&par_io->ioport[port].dir2, ~pin_2bit_mask & tmp_val);
+		out_be32(&par_io->ioport[port].dir2, pin_2bit_dir | tmp_val);
+	} else {
+		out_be32(&par_io->ioport[port].dir1, ~pin_2bit_mask & tmp_val);
+		out_be32(&par_io->ioport[port].dir1, pin_2bit_dir | tmp_val);
+	}
+
+	/* Calculate pin location for 1bit mask */
+	pin_1bit_mask = (u32)(1 << (NUM_OF_PINS - (pin+1)));
+
+	/* Setup the open drain */
+	tmp_val = in_be32(&par_io->ioport[port].podr);
+	if (open_drain) {
+		out_be32(&par_io->ioport[port].podr, pin_1bit_mask | tmp_val);
+	} else {
+		out_be32(&par_io->ioport[port].podr, ~pin_1bit_mask & tmp_val);
+	}
+
+	/* Setup the assignment */
+	tmp_val = (pin > (NUM_OF_PINS/2) - 1) ?
+		in_be32(&par_io->ioport[port].ppar2):
+		in_be32(&par_io->ioport[port].ppar1);
+	pin_2bit_assign = (u32)(assign
+				<< (NUM_OF_PINS - (pin%(NUM_OF_PINS/2)+1)*2));
+
+	/* Clear and set 2 bits mask */
+	if (pin > (NUM_OF_PINS/2) - 1) {
+		out_be32(&par_io->ioport[port].ppar2, ~pin_2bit_mask & tmp_val);
+		out_be32(&par_io->ioport[port].ppar2, pin_2bit_assign | tmp_val);
+	} else {
+		out_be32(&par_io->ioport[port].ppar1, ~pin_2bit_mask & tmp_val);
+		out_be32(&par_io->ioport[port].ppar1, pin_2bit_assign | tmp_val);
+	}
+}
diff --git a/arch/powerpc/cpu/mpc83xx/serdes.c b/arch/powerpc/cpu/mpc83xx/serdes.c
new file mode 100644
index 0000000..64033fe
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/serdes.c
@@ -0,0 +1,145 @@
+/*
+ * Freescale SerDes initialization routine
+ *
+ * Copyright (C) 2007 Freescale Semicondutor, Inc.
+ * Copyright (C) 2008 MontaVista Software, Inc.
+ *
+ * Author: Li Yang <leoli@freescale.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.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_serdes.h>
+
+/* SerDes registers */
+#define FSL_SRDSCR0_OFFS		0x0
+#define FSL_SRDSCR0_DPP_1V2		0x00008800
+#define FSL_SRDSCR1_OFFS		0x4
+#define FSL_SRDSCR1_PLLBW		0x00000040
+#define FSL_SRDSCR2_OFFS		0x8
+#define FSL_SRDSCR2_VDD_1V2		0x00800000
+#define FSL_SRDSCR2_SEIC_MASK		0x00001c1c
+#define FSL_SRDSCR2_SEIC_SATA		0x00001414
+#define FSL_SRDSCR2_SEIC_PEX		0x00001010
+#define FSL_SRDSCR2_SEIC_SGMII		0x00000101
+#define FSL_SRDSCR3_OFFS		0xc
+#define FSL_SRDSCR3_KFR_SATA		0x10100000
+#define FSL_SRDSCR3_KPH_SATA		0x04040000
+#define FSL_SRDSCR3_SDFM_SATA_PEX	0x01010000
+#define FSL_SRDSCR3_SDTXL_SATA		0x00000505
+#define FSL_SRDSCR4_OFFS		0x10
+#define FSL_SRDSCR4_PROT_SATA		0x00000808
+#define FSL_SRDSCR4_PROT_PEX		0x00000101
+#define FSL_SRDSCR4_PROT_SGMII		0x00000505
+#define FSL_SRDSCR4_PLANE_X2		0x01000000
+#define FSL_SRDSRSTCTL_OFFS		0x20
+#define FSL_SRDSRSTCTL_RST		0x80000000
+#define FSL_SRDSRSTCTL_SATA_RESET	0xf
+
+void fsl_setup_serdes(u32 offset, char proto, u32 rfcks, char vdd)
+{
+	void *regs = (void *)CONFIG_SYS_IMMR + offset;
+	u32 tmp;
+
+	/* 1.0V corevdd */
+	if (vdd) {
+		/* DPPE/DPPA = 0 */
+		tmp = in_be32(regs + FSL_SRDSCR0_OFFS);
+		tmp &= ~FSL_SRDSCR0_DPP_1V2;
+		out_be32(regs + FSL_SRDSCR0_OFFS, tmp);
+
+		/* VDD = 0 */
+		tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+		tmp &= ~FSL_SRDSCR2_VDD_1V2;
+		out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+	}
+
+	/* protocol specific configuration */
+	switch (proto) {
+	case FSL_SERDES_PROTO_SATA:
+		/* Set and clear reset bits */
+		tmp = in_be32(regs + FSL_SRDSRSTCTL_OFFS);
+		tmp |= FSL_SRDSRSTCTL_SATA_RESET;
+		out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp);
+		udelay(1000);
+		tmp &= ~FSL_SRDSRSTCTL_SATA_RESET;
+		out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp);
+
+		/* Configure SRDSCR1 */
+		tmp = in_be32(regs + FSL_SRDSCR1_OFFS);
+		tmp &= ~FSL_SRDSCR1_PLLBW;
+		out_be32(regs + FSL_SRDSCR1_OFFS, tmp);
+
+		/* Configure SRDSCR2 */
+		tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+		tmp &= ~FSL_SRDSCR2_SEIC_MASK;
+		tmp |= FSL_SRDSCR2_SEIC_SATA;
+		out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+
+		/* Configure SRDSCR3 */
+		tmp = FSL_SRDSCR3_KFR_SATA | FSL_SRDSCR3_KPH_SATA |
+			FSL_SRDSCR3_SDFM_SATA_PEX |
+			FSL_SRDSCR3_SDTXL_SATA;
+		out_be32(regs + FSL_SRDSCR3_OFFS, tmp);
+
+		/* Configure SRDSCR4 */
+		tmp = rfcks | FSL_SRDSCR4_PROT_SATA;
+		out_be32(regs + FSL_SRDSCR4_OFFS, tmp);
+		break;
+	case FSL_SERDES_PROTO_PEX:
+	case FSL_SERDES_PROTO_PEX_X2:
+		/* Configure SRDSCR1 */
+		tmp = in_be32(regs + FSL_SRDSCR1_OFFS);
+		tmp |= FSL_SRDSCR1_PLLBW;
+		out_be32(regs + FSL_SRDSCR1_OFFS, tmp);
+
+		/* Configure SRDSCR2 */
+		tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+		tmp &= ~FSL_SRDSCR2_SEIC_MASK;
+		tmp |= FSL_SRDSCR2_SEIC_PEX;
+		out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+
+		/* Configure SRDSCR3 */
+		tmp = FSL_SRDSCR3_SDFM_SATA_PEX;
+		out_be32(regs + FSL_SRDSCR3_OFFS, tmp);
+
+		/* Configure SRDSCR4 */
+		tmp = rfcks | FSL_SRDSCR4_PROT_PEX;
+		if (proto == FSL_SERDES_PROTO_PEX_X2)
+			tmp |= FSL_SRDSCR4_PLANE_X2;
+		out_be32(regs + FSL_SRDSCR4_OFFS, tmp);
+		break;
+	case FSL_SERDES_PROTO_SGMII:
+		/* Configure SRDSCR1 */
+		tmp = in_be32(regs + FSL_SRDSCR1_OFFS);
+		tmp &= ~FSL_SRDSCR1_PLLBW;
+		out_be32(regs + FSL_SRDSCR1_OFFS, tmp);
+
+		/* Configure SRDSCR2 */
+		tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+		tmp &= ~FSL_SRDSCR2_SEIC_MASK;
+		tmp |= FSL_SRDSCR2_SEIC_SGMII;
+		out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+
+		/* Configure SRDSCR3 */
+		out_be32(regs + FSL_SRDSCR3_OFFS, 0);
+
+		/* Configure SRDSCR4 */
+		tmp = rfcks | FSL_SRDSCR4_PROT_SGMII;
+		out_be32(regs + FSL_SRDSCR4_OFFS, tmp);
+		break;
+	default:
+		return;
+	}
+
+	/* Do a software reset */
+	tmp = in_be32(regs + FSL_SRDSRSTCTL_OFFS);
+	tmp |= FSL_SRDSRSTCTL_RST;
+	out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp);
+}
diff --git a/arch/powerpc/cpu/mpc83xx/spd_sdram.c b/arch/powerpc/cpu/mpc83xx/spd_sdram.c
new file mode 100644
index 0000000..44aaa9a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/spd_sdram.c
@@ -0,0 +1,918 @@
+/*
+ * (C) Copyright 2006-2007 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
+ * (C) Copyright 2003 Motorola Inc.
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <i2c.h>
+#include <spd.h>
+#include <asm/mmu.h>
+#include <spd_sdram.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void board_add_ram_info(int use_default)
+{
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	volatile ddr83xx_t *ddr = &immap->ddr;
+	char buf[32];
+
+	printf(" (DDR%d", ((ddr->sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK)
+			   >> SDRAM_CFG_SDRAM_TYPE_SHIFT) - 1);
+
+	if (ddr->sdram_cfg & SDRAM_CFG_32_BE)
+		puts(", 32-bit");
+	else
+		puts(", 64-bit");
+
+	if (ddr->sdram_cfg & SDRAM_CFG_ECC_EN)
+		puts(", ECC on");
+	else
+		puts(", ECC off");
+
+	printf(", %s MHz)", strmhz(buf, gd->mem_clk));
+
+#if defined(CONFIG_SYS_LB_SDRAM) && defined(CONFIG_SYS_LBC_SDRAM_SIZE)
+	puts("\nSDRAM: ");
+	print_size (CONFIG_SYS_LBC_SDRAM_SIZE * 1024 * 1024, " (local bus)");
+#endif
+}
+
+#ifdef CONFIG_SPD_EEPROM
+#ifndef	CONFIG_SYS_READ_SPD
+#define CONFIG_SYS_READ_SPD	i2c_read
+#endif
+
+/*
+ * Convert picoseconds into clock cycles (rounding up if needed).
+ */
+int
+picos_to_clk(int picos)
+{
+	unsigned int mem_bus_clk;
+	int clks;
+
+	mem_bus_clk = gd->mem_clk >> 1;
+	clks = picos / (1000000000 / (mem_bus_clk / 1000));
+	if (picos % (1000000000 / (mem_bus_clk / 1000)) != 0)
+		clks++;
+
+	return clks;
+}
+
+unsigned int banksize(unsigned char row_dens)
+{
+	return ((row_dens >> 2) | ((row_dens & 3) << 6)) << 24;
+}
+
+int read_spd(uint addr)
+{
+	return ((int) addr);
+}
+
+#undef SPD_DEBUG
+#ifdef SPD_DEBUG
+static void spd_debug(spd_eeprom_t *spd)
+{
+	printf ("\nDIMM type:       %-18.18s\n", spd->mpart);
+	printf ("SPD size:        %d\n", spd->info_size);
+	printf ("EEPROM size:     %d\n", 1 << spd->chip_size);
+	printf ("Memory type:     %d\n", spd->mem_type);
+	printf ("Row addr:        %d\n", spd->nrow_addr);
+	printf ("Column addr:     %d\n", spd->ncol_addr);
+	printf ("# of rows:       %d\n", spd->nrows);
+	printf ("Row density:     %d\n", spd->row_dens);
+	printf ("# of banks:      %d\n", spd->nbanks);
+	printf ("Data width:      %d\n",
+			256 * spd->dataw_msb + spd->dataw_lsb);
+	printf ("Chip width:      %d\n", spd->primw);
+	printf ("Refresh rate:    %02X\n", spd->refresh);
+	printf ("CAS latencies:   %02X\n", spd->cas_lat);
+	printf ("Write latencies: %02X\n", spd->write_lat);
+	printf ("tRP:             %d\n", spd->trp);
+	printf ("tRCD:            %d\n", spd->trcd);
+	printf ("\n");
+}
+#endif /* SPD_DEBUG */
+
+long int spd_sdram()
+{
+	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+	volatile ddr83xx_t *ddr = &immap->ddr;
+	volatile law83xx_t *ecm = &immap->sysconf.ddrlaw[0];
+	spd_eeprom_t spd;
+	unsigned int n_ranks;
+	unsigned int odt_rd_cfg, odt_wr_cfg;
+	unsigned char twr_clk, twtr_clk;
+	unsigned int sdram_type;
+	unsigned int memsize;
+	unsigned int law_size;
+	unsigned char caslat, caslat_ctrl;
+	unsigned int trfc, trfc_clk, trfc_low, trfc_high;
+	unsigned int trcd_clk, trtp_clk;
+	unsigned char cke_min_clk;
+	unsigned char add_lat, wr_lat;
+	unsigned char wr_data_delay;
+	unsigned char four_act;
+	unsigned char cpo;
+	unsigned char burstlen;
+	unsigned char odt_cfg, mode_odt_enable;
+	unsigned int max_bus_clk;
+	unsigned int max_data_rate, effective_data_rate;
+	unsigned int ddrc_clk;
+	unsigned int refresh_clk;
+	unsigned int sdram_cfg;
+	unsigned int ddrc_ecc_enable;
+	unsigned int pvr = get_pvr();
+
+	/*
+	 * First disable the memory controller (could be enabled
+	 * by the debugger)
+	 */
+	clrsetbits_be32(&ddr->sdram_cfg, SDRAM_CFG_MEM_EN, 0);
+	sync();
+	isync();
+
+	/* Read SPD parameters with I2C */
+	CONFIG_SYS_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) & spd, sizeof (spd));
+#ifdef SPD_DEBUG
+	spd_debug(&spd);
+#endif
+	/* Check the memory type */
+	if (spd.mem_type != SPD_MEMTYPE_DDR && spd.mem_type != SPD_MEMTYPE_DDR2) {
+		debug("DDR: Module mem type is %02X\n", spd.mem_type);
+		return 0;
+	}
+
+	/* Check the number of physical bank */
+	if (spd.mem_type == SPD_MEMTYPE_DDR) {
+		n_ranks = spd.nrows;
+	} else {
+		n_ranks = (spd.nrows & 0x7) + 1;
+	}
+
+	if (n_ranks > 2) {
+		printf("DDR: The number of physical bank is %02X\n", n_ranks);
+		return 0;
+	}
+
+	/* Check if the number of row of the module is in the range of DDRC */
+	if (spd.nrow_addr < 12 || spd.nrow_addr > 15) {
+		printf("DDR: Row number is out of range of DDRC, row=%02X\n",
+							 spd.nrow_addr);
+		return 0;
+	}
+
+	/* Check if the number of col of the module is in the range of DDRC */
+	if (spd.ncol_addr < 8 || spd.ncol_addr > 11) {
+		printf("DDR: Col number is out of range of DDRC, col=%02X\n",
+							 spd.ncol_addr);
+		return 0;
+	}
+
+#ifdef CONFIG_SYS_DDRCDR_VALUE
+	/*
+	 * Adjust DDR II IO voltage biasing.  It just makes it work.
+	 */
+	if(spd.mem_type == SPD_MEMTYPE_DDR2) {
+		immap->sysconf.ddrcdr = CONFIG_SYS_DDRCDR_VALUE;
+	}
+	udelay(50000);
+#endif
+
+	/*
+	 * ODT configuration recommendation from DDR Controller Chapter.
+	 */
+	odt_rd_cfg = 0;			/* Never assert ODT */
+	odt_wr_cfg = 0;			/* Never assert ODT */
+	if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+		odt_wr_cfg = 1;		/* Assert ODT on writes to CSn */
+	}
+
+	/* Setup DDR chip select register */
+#ifdef CONFIG_SYS_83XX_DDR_USES_CS0
+	ddr->csbnds[0].csbnds = (banksize(spd.row_dens) >> 24) - 1;
+	ddr->cs_config[0] = ( 1 << 31
+			    | (odt_rd_cfg << 20)
+			    | (odt_wr_cfg << 16)
+			    | ((spd.nbanks == 8 ? 1 : 0) << 14)
+			    | ((spd.nrow_addr - 12) << 8)
+			    | (spd.ncol_addr - 8) );
+	debug("\n");
+	debug("cs0_bnds = 0x%08x\n",ddr->csbnds[0].csbnds);
+	debug("cs0_config = 0x%08x\n",ddr->cs_config[0]);
+
+	if (n_ranks == 2) {
+		ddr->csbnds[1].csbnds = ( (banksize(spd.row_dens) >> 8)
+				  | ((banksize(spd.row_dens) >> 23) - 1) );
+		ddr->cs_config[1] = ( 1<<31
+				    | (odt_rd_cfg << 20)
+				    | (odt_wr_cfg << 16)
+				    | ((spd.nbanks == 8 ? 1 : 0) << 14)
+				    | ((spd.nrow_addr - 12) << 8)
+				    | (spd.ncol_addr - 8) );
+		debug("cs1_bnds = 0x%08x\n",ddr->csbnds[1].csbnds);
+		debug("cs1_config = 0x%08x\n",ddr->cs_config[1]);
+	}
+
+#else
+	ddr->csbnds[2].csbnds = (banksize(spd.row_dens) >> 24) - 1;
+	ddr->cs_config[2] = ( 1 << 31
+			    | (odt_rd_cfg << 20)
+			    | (odt_wr_cfg << 16)
+			    | ((spd.nbanks == 8 ? 1 : 0) << 14)
+			    | ((spd.nrow_addr - 12) << 8)
+			    | (spd.ncol_addr - 8) );
+	debug("\n");
+	debug("cs2_bnds = 0x%08x\n",ddr->csbnds[2].csbnds);
+	debug("cs2_config = 0x%08x\n",ddr->cs_config[2]);
+
+	if (n_ranks == 2) {
+		ddr->csbnds[3].csbnds = ( (banksize(spd.row_dens) >> 8)
+				  | ((banksize(spd.row_dens) >> 23) - 1) );
+		ddr->cs_config[3] = ( 1<<31
+				    | (odt_rd_cfg << 20)
+				    | (odt_wr_cfg << 16)
+				    | ((spd.nbanks == 8 ? 1 : 0) << 14)
+				    | ((spd.nrow_addr - 12) << 8)
+				    | (spd.ncol_addr - 8) );
+		debug("cs3_bnds = 0x%08x\n",ddr->csbnds[3].csbnds);
+		debug("cs3_config = 0x%08x\n",ddr->cs_config[3]);
+	}
+#endif
+
+	/*
+	 * Figure out memory size in Megabytes.
+	 */
+	memsize = n_ranks * banksize(spd.row_dens) / 0x100000;
+
+	/*
+	 * First supported LAW size is 16M, at LAWAR_SIZE_16M == 23.
+	 */
+	law_size = 19 + __ilog2(memsize);
+
+	/*
+	 * Set up LAWBAR for all of DDR.
+	 */
+	ecm->bar = CONFIG_SYS_DDR_SDRAM_BASE & 0xfffff000;
+	ecm->ar  = (LAWAR_EN | LAWAR_TRGT_IF_DDR | (LAWAR_SIZE & law_size));
+	debug("DDR:bar=0x%08x\n", ecm->bar);
+	debug("DDR:ar=0x%08x\n", ecm->ar);
+
+	/*
+	 * Find the largest CAS by locating the highest 1 bit
+	 * in the spd.cas_lat field.  Translate it to a DDR
+	 * controller field value:
+	 *
+	 *	CAS Lat	DDR I	DDR II	Ctrl
+	 *	Clocks	SPD Bit	SPD Bit	Value
+	 *	-------	-------	-------	-----
+	 *	1.0	0		0001
+	 *	1.5	1		0010
+	 *	2.0	2	2	0011
+	 *	2.5	3		0100
+	 *	3.0	4	3	0101
+	 *	3.5	5		0110
+	 *	4.0	6	4	0111
+	 *	4.5			1000
+	 *	5.0		5	1001
+	 */
+	caslat = __ilog2(spd.cas_lat);
+	if ((spd.mem_type == SPD_MEMTYPE_DDR)
+	    && (caslat > 6)) {
+		printf("DDR I: Invalid SPD CAS Latency: 0x%x.\n", spd.cas_lat);
+		return 0;
+	} else if (spd.mem_type == SPD_MEMTYPE_DDR2
+		   && (caslat < 2 || caslat > 5)) {
+		printf("DDR II: Invalid SPD CAS Latency: 0x%x.\n",
+		       spd.cas_lat);
+		return 0;
+	}
+	debug("DDR: caslat SPD bit is %d\n", caslat);
+
+	max_bus_clk = 1000 *10 / (((spd.clk_cycle & 0xF0) >> 4) * 10
+			+ (spd.clk_cycle & 0x0f));
+	max_data_rate = max_bus_clk * 2;
+
+	debug("DDR:Module maximum data rate is: %d MHz\n", max_data_rate);
+
+	ddrc_clk = gd->mem_clk / 1000000;
+	effective_data_rate = 0;
+
+	if (max_data_rate >= 460) { /* it is DDR2-800, 667, 533 */
+		if (spd.cas_lat & 0x08)
+			caslat = 3;
+		else
+			caslat = 4;
+		if (ddrc_clk <= 460 && ddrc_clk > 350)
+			effective_data_rate = 400;
+		else if (ddrc_clk <=350 && ddrc_clk > 280)
+			effective_data_rate = 333;
+		else if (ddrc_clk <= 280 && ddrc_clk > 230)
+			effective_data_rate = 266;
+		else
+			effective_data_rate = 200;
+	} else if (max_data_rate >= 390 && max_data_rate < 460) { /* it is DDR 400 */
+		if (ddrc_clk <= 460 && ddrc_clk > 350) {
+			/* DDR controller clk at 350~460 */
+			effective_data_rate = 400; /* 5ns */
+			caslat = caslat;
+		} else if (ddrc_clk <= 350 && ddrc_clk > 280) {
+			/* DDR controller clk at 280~350 */
+			effective_data_rate = 333; /* 6ns */
+			if (spd.clk_cycle2 == 0x60)
+				caslat = caslat - 1;
+			else
+				caslat = caslat;
+		} else if (ddrc_clk <= 280 && ddrc_clk > 230) {
+			/* DDR controller clk at 230~280 */
+			effective_data_rate = 266; /* 7.5ns */
+			if (spd.clk_cycle3 == 0x75)
+				caslat = caslat - 2;
+			else if (spd.clk_cycle2 == 0x75)
+				caslat = caslat - 1;
+			else
+				caslat = caslat;
+		} else if (ddrc_clk <= 230 && ddrc_clk > 90) {
+			/* DDR controller clk at 90~230 */
+			effective_data_rate = 200; /* 10ns */
+			if (spd.clk_cycle3 == 0xa0)
+				caslat = caslat - 2;
+			else if (spd.clk_cycle2 == 0xa0)
+				caslat = caslat - 1;
+			else
+				caslat = caslat;
+		}
+	} else if (max_data_rate >= 323) { /* it is DDR 333 */
+		if (ddrc_clk <= 350 && ddrc_clk > 280) {
+			/* DDR controller clk at 280~350 */
+			effective_data_rate = 333; /* 6ns */
+			caslat = caslat;
+		} else if (ddrc_clk <= 280 && ddrc_clk > 230) {
+			/* DDR controller clk at 230~280 */
+			effective_data_rate = 266; /* 7.5ns */
+			if (spd.clk_cycle2 == 0x75)
+				caslat = caslat - 1;
+			else
+				caslat = caslat;
+		} else if (ddrc_clk <= 230 && ddrc_clk > 90) {
+			/* DDR controller clk at 90~230 */
+			effective_data_rate = 200; /* 10ns */
+			if (spd.clk_cycle3 == 0xa0)
+				caslat = caslat - 2;
+			else if (spd.clk_cycle2 == 0xa0)
+				caslat = caslat - 1;
+			else
+				caslat = caslat;
+		}
+	} else if (max_data_rate >= 256) { /* it is DDR 266 */
+		if (ddrc_clk <= 350 && ddrc_clk > 280) {
+			/* DDR controller clk at 280~350 */
+			printf("DDR: DDR controller freq is more than "
+				"max data rate of the module\n");
+			return 0;
+		} else if (ddrc_clk <= 280 && ddrc_clk > 230) {
+			/* DDR controller clk at 230~280 */
+			effective_data_rate = 266; /* 7.5ns */
+			caslat = caslat;
+		} else if (ddrc_clk <= 230 && ddrc_clk > 90) {
+			/* DDR controller clk at 90~230 */
+			effective_data_rate = 200; /* 10ns */
+			if (spd.clk_cycle2 == 0xa0)
+				caslat = caslat - 1;
+		}
+	} else if (max_data_rate >= 190) { /* it is DDR 200 */
+		if (ddrc_clk <= 350 && ddrc_clk > 230) {
+			/* DDR controller clk at 230~350 */
+			printf("DDR: DDR controller freq is more than "
+				"max data rate of the module\n");
+			return 0;
+		} else if (ddrc_clk <= 230 && ddrc_clk > 90) {
+			/* DDR controller clk at 90~230 */
+			effective_data_rate = 200; /* 10ns */
+			caslat = caslat;
+		}
+	}
+
+	debug("DDR:Effective data rate is: %dMHz\n", effective_data_rate);
+	debug("DDR:The MSB 1 of CAS Latency is: %d\n", caslat);
+
+	/*
+	 * Errata DDR6 work around: input enable 2 cycles earlier.
+	 * including MPC834x Rev1.0/1.1 and MPC8360 Rev1.1/1.2.
+	 */
+	if(PVR_MAJ(pvr) <= 1 && spd.mem_type == SPD_MEMTYPE_DDR){
+		if (caslat == 2)
+			ddr->debug_reg = 0x201c0000; /* CL=2 */
+		else if (caslat == 3)
+			ddr->debug_reg = 0x202c0000; /* CL=2.5 */
+		else if (caslat == 4)
+			ddr->debug_reg = 0x202c0000; /* CL=3.0 */
+
+		__asm__ __volatile__ ("sync");
+
+		debug("Errata DDR6 (debug_reg=0x%08x)\n", ddr->debug_reg);
+	}
+
+	/*
+	 * Convert caslat clocks to DDR controller value.
+	 * Force caslat_ctrl to be DDR Controller field-sized.
+	 */
+	if (spd.mem_type == SPD_MEMTYPE_DDR) {
+		caslat_ctrl = (caslat + 1) & 0x07;
+	} else {
+		caslat_ctrl =  (2 * caslat - 1) & 0x0f;
+	}
+
+	debug("DDR: effective data rate is %d MHz\n", effective_data_rate);
+	debug("DDR: caslat SPD bit is %d, controller field is 0x%x\n",
+	      caslat, caslat_ctrl);
+
+	/*
+	 * Timing Config 0.
+	 * Avoid writing for DDR I.
+	 */
+	if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+		unsigned char taxpd_clk = 8;		/* By the book. */
+		unsigned char tmrd_clk = 2;		/* By the book. */
+		unsigned char act_pd_exit = 2;		/* Empirical? */
+		unsigned char pre_pd_exit = 6;		/* Empirical? */
+
+		ddr->timing_cfg_0 = (0
+			| ((act_pd_exit & 0x7) << 20)	/* ACT_PD_EXIT */
+			| ((pre_pd_exit & 0x7) << 16)	/* PRE_PD_EXIT */
+			| ((taxpd_clk & 0xf) << 8)	/* ODT_PD_EXIT */
+			| ((tmrd_clk & 0xf) << 0)	/* MRS_CYC */
+			);
+		debug("DDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);
+	}
+
+	/*
+	 * For DDR I, WRREC(Twr) and WRTORD(Twtr) are not in SPD,
+	 * use conservative value.
+	 * For DDR II, they are bytes 36 and 37, in quarter nanos.
+	 */
+
+	if (spd.mem_type == SPD_MEMTYPE_DDR) {
+		twr_clk = 3;	/* Clocks */
+		twtr_clk = 1;	/* Clocks */
+	} else {
+		twr_clk = picos_to_clk(spd.twr * 250);
+		twtr_clk = picos_to_clk(spd.twtr * 250);
+		if (twtr_clk < 2)
+			twtr_clk = 2;
+	}
+
+	/*
+	 * Calculate Trfc, in picos.
+	 * DDR I:  Byte 42 straight up in ns.
+	 * DDR II: Byte 40 and 42 swizzled some, in ns.
+	 */
+	if (spd.mem_type == SPD_MEMTYPE_DDR) {
+		trfc = spd.trfc * 1000;		/* up to ps */
+	} else {
+		unsigned int byte40_table_ps[8] = {
+			0,
+			250,
+			330,
+			500,
+			660,
+			750,
+			0,
+			0
+		};
+
+		trfc = (((spd.trctrfc_ext & 0x1) * 256) + spd.trfc) * 1000
+			+ byte40_table_ps[(spd.trctrfc_ext >> 1) & 0x7];
+	}
+	trfc_clk = picos_to_clk(trfc);
+
+	/*
+	 * Trcd, Byte 29, from quarter nanos to ps and clocks.
+	 */
+	trcd_clk = picos_to_clk(spd.trcd * 250) & 0x7;
+
+	/*
+	 * Convert trfc_clk to DDR controller fields.  DDR I should
+	 * fit in the REFREC field (16-19) of TIMING_CFG_1, but the
+	 * 83xx controller has an extended REFREC field of three bits.
+	 * The controller automatically adds 8 clocks to this value,
+	 * so preadjust it down 8 first before splitting it up.
+	 */
+	trfc_low = (trfc_clk - 8) & 0xf;
+	trfc_high = ((trfc_clk - 8) >> 4) & 0x3;
+
+	ddr->timing_cfg_1 =
+	    (((picos_to_clk(spd.trp * 250) & 0x07) << 28 ) |	/* PRETOACT */
+	     ((picos_to_clk(spd.tras * 1000) & 0x0f ) << 24 ) | /* ACTTOPRE */
+	     (trcd_clk << 20 ) |				/* ACTTORW */
+	     (caslat_ctrl << 16 ) |				/* CASLAT */
+	     (trfc_low << 12 ) |				/* REFEC */
+	     ((twr_clk & 0x07) << 8) |				/* WRRREC */
+	     ((picos_to_clk(spd.trrd * 250) & 0x07) << 4) |	/* ACTTOACT */
+	     ((twtr_clk & 0x07) << 0)				/* WRTORD */
+	    );
+
+	/*
+	 * Additive Latency
+	 * For DDR I, 0.
+	 * For DDR II, with ODT enabled, use "a value" less than ACTTORW,
+	 * which comes from Trcd, and also note that:
+	 *	add_lat + caslat must be >= 4
+	 */
+	add_lat = 0;
+	if (spd.mem_type == SPD_MEMTYPE_DDR2
+	    && (odt_wr_cfg || odt_rd_cfg)
+	    && (caslat < 4)) {
+		add_lat = 4 - caslat;
+		if ((add_lat + caslat) < 4) {
+			add_lat = 0;
+		}
+	}
+
+	/*
+	 * Write Data Delay
+	 * Historically 0x2 == 4/8 clock delay.
+	 * Empirically, 0x3 == 6/8 clock delay is suggested for DDR I 266.
+	 */
+	wr_data_delay = 2;
+
+	/*
+	 * Write Latency
+	 * Read to Precharge
+	 * Minimum CKE Pulse Width.
+	 * Four Activate Window
+	 */
+	if (spd.mem_type == SPD_MEMTYPE_DDR) {
+		/*
+		 * This is a lie.  It should really be 1, but if it is
+		 * set to 1, bits overlap into the old controller's
+		 * otherwise unused ACSM field.  If we leave it 0, then
+		 * the HW will magically treat it as 1 for DDR 1.  Oh Yea.
+		 */
+		wr_lat = 0;
+
+		trtp_clk = 2;		/* By the book. */
+		cke_min_clk = 1;	/* By the book. */
+		four_act = 1;		/* By the book. */
+
+	} else {
+		wr_lat = caslat - 1;
+
+		/* Convert SPD value from quarter nanos to picos. */
+		trtp_clk = picos_to_clk(spd.trtp * 250);
+		if (trtp_clk < 2)
+			trtp_clk = 2;
+		trtp_clk += add_lat;
+
+		cke_min_clk = 3;	/* By the book. */
+		four_act = picos_to_clk(37500);	/* By the book. 1k pages? */
+	}
+
+	/*
+	 * Empirically set ~MCAS-to-preamble override for DDR 2.
+	 * Your milage will vary.
+	 */
+	cpo = 0;
+	if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+		if (effective_data_rate == 266) {
+			cpo = 0x4;		/* READ_LAT + 1/2 */
+		} else if (effective_data_rate == 333) {
+			cpo = 0x6;		/* READ_LAT + 1 */
+		} else if (effective_data_rate == 400) {
+			cpo = 0x7;		/* READ_LAT + 5/4 */
+		} else {
+			/* Automatic calibration */
+			cpo = 0x1f;
+		}
+	}
+
+	ddr->timing_cfg_2 = (0
+		| ((add_lat & 0x7) << 28)		/* ADD_LAT */
+		| ((cpo & 0x1f) << 23)			/* CPO */
+		| ((wr_lat & 0x7) << 19)		/* WR_LAT */
+		| ((trtp_clk & 0x7) << 13)		/* RD_TO_PRE */
+		| ((wr_data_delay & 0x7) << 10)		/* WR_DATA_DELAY */
+		| ((cke_min_clk & 0x7) << 6)		/* CKE_PLS */
+		| ((four_act & 0x1f) << 0)		/* FOUR_ACT */
+		);
+
+	debug("DDR:timing_cfg_1=0x%08x\n", ddr->timing_cfg_1);
+	debug("DDR:timing_cfg_2=0x%08x\n", ddr->timing_cfg_2);
+
+	/* Check DIMM data bus width */
+	if (spd.dataw_lsb < 64) {
+		if (spd.mem_type == SPD_MEMTYPE_DDR)
+			burstlen = 0x03; /* 32 bit data bus, burst len is 8 */
+		else
+			burstlen = 0x02; /* 32 bit data bus, burst len is 4 */
+		debug("\n   DDR DIMM: data bus width is 32 bit");
+	} else {
+		burstlen = 0x02; /* Others act as 64 bit bus, burst len is 4 */
+		debug("\n   DDR DIMM: data bus width is 64 bit");
+	}
+
+	/* Is this an ECC DDR chip? */
+	if (spd.config == 0x02)
+		debug(" with ECC\n");
+	else
+		debug(" without ECC\n");
+
+	/* Burst length is always 4 for 64 bit data bus, 8 for 32 bit data bus,
+	   Burst type is sequential
+	 */
+	if (spd.mem_type == SPD_MEMTYPE_DDR) {
+		switch (caslat) {
+		case 1:
+			ddr->sdram_mode = 0x50 | burstlen; /* CL=1.5 */
+			break;
+		case 2:
+			ddr->sdram_mode = 0x20 | burstlen; /* CL=2.0 */
+			break;
+		case 3:
+			ddr->sdram_mode = 0x60 | burstlen; /* CL=2.5 */
+			break;
+		case 4:
+			ddr->sdram_mode = 0x30 | burstlen; /* CL=3.0 */
+			break;
+		default:
+			printf("DDR:only CL 1.5, 2.0, 2.5, 3.0 is supported\n");
+			return 0;
+		}
+	} else {
+		mode_odt_enable = 0x0;                  /* Default disabled */
+		if (odt_wr_cfg || odt_rd_cfg) {
+			/*
+			 * Bits 6 and 2 in Extended MRS(1)
+			 * Bit 2 == 0x04 == 75 Ohm, with 2 DIMM modules.
+			 * Bit 6 == 0x40 == 150 Ohm, with 1 DIMM module.
+			 */
+			mode_odt_enable = 0x40;         /* 150 Ohm */
+		}
+
+		ddr->sdram_mode =
+			(0
+			 | (1 << (16 + 10))             /* DQS Differential disable */
+			 | (add_lat << (16 + 3))        /* Additive Latency in EMRS1 */
+			 | (mode_odt_enable << 16)      /* ODT Enable in EMRS1 */
+			 | ((twr_clk - 1) << 9)         /* Write Recovery Autopre */
+			 | (caslat << 4)                /* caslat */
+			 | (burstlen << 0)              /* Burst length */
+			);
+	}
+	debug("DDR:sdram_mode=0x%08x\n", ddr->sdram_mode);
+
+	/*
+	 * Clear EMRS2 and EMRS3.
+	 */
+	ddr->sdram_mode2 = 0;
+	debug("DDR: sdram_mode2 = 0x%08x\n", ddr->sdram_mode2);
+
+	switch (spd.refresh) {
+		case 0x00:
+		case 0x80:
+			refresh_clk = picos_to_clk(15625000);
+			break;
+		case 0x01:
+		case 0x81:
+			refresh_clk = picos_to_clk(3900000);
+			break;
+		case 0x02:
+		case 0x82:
+			refresh_clk = picos_to_clk(7800000);
+			break;
+		case 0x03:
+		case 0x83:
+			refresh_clk = picos_to_clk(31300000);
+			break;
+		case 0x04:
+		case 0x84:
+			refresh_clk = picos_to_clk(62500000);
+			break;
+		case 0x05:
+		case 0x85:
+			refresh_clk = picos_to_clk(125000000);
+			break;
+		default:
+			refresh_clk = 0x512;
+			break;
+	}
+
+	/*
+	 * Set BSTOPRE to 0x100 for page mode
+	 * If auto-charge is used, set BSTOPRE = 0
+	 */
+	ddr->sdram_interval = ((refresh_clk & 0x3fff) << 16) | 0x100;
+	debug("DDR:sdram_interval=0x%08x\n", ddr->sdram_interval);
+
+	/*
+	 * SDRAM Cfg 2
+	 */
+	odt_cfg = 0;
+#ifndef CONFIG_NEVER_ASSERT_ODT_TO_CPU
+	if (odt_rd_cfg | odt_wr_cfg) {
+		odt_cfg = 0x2;		/* ODT to IOs during reads */
+	}
+#endif
+	if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+		ddr->sdram_cfg2 = (0
+			    | (0 << 26)	/* True DQS */
+			    | (odt_cfg << 21)	/* ODT only read */
+			    | (1 << 12)	/* 1 refresh at a time */
+			    );
+
+		debug("DDR: sdram_cfg2  = 0x%08x\n", ddr->sdram_cfg2);
+	}
+
+#ifdef CONFIG_SYS_DDR_SDRAM_CLK_CNTL	/* Optional platform specific value */
+	ddr->sdram_clk_cntl = CONFIG_SYS_DDR_SDRAM_CLK_CNTL;
+#endif
+	debug("DDR:sdram_clk_cntl=0x%08x\n", ddr->sdram_clk_cntl);
+
+	asm("sync;isync");
+
+	udelay(600);
+
+	/*
+	 * Figure out the settings for the sdram_cfg register. Build up
+	 * the value in 'sdram_cfg' before writing since the write into
+	 * the register will actually enable the memory controller, and all
+	 * settings must be done before enabling.
+	 *
+	 * sdram_cfg[0]   = 1 (ddr sdram logic enable)
+	 * sdram_cfg[1]   = 1 (self-refresh-enable)
+	 * sdram_cfg[5:7] = (SDRAM type = DDR SDRAM)
+	 *			010 DDR 1 SDRAM
+	 *			011 DDR 2 SDRAM
+	 * sdram_cfg[12] = 0 (32_BE =0 , 64 bit bus mode)
+	 * sdram_cfg[13] = 0 (8_BE =0, 4-beat bursts)
+	 */
+	if (spd.mem_type == SPD_MEMTYPE_DDR)
+		sdram_type = SDRAM_CFG_SDRAM_TYPE_DDR1;
+	else
+		sdram_type = SDRAM_CFG_SDRAM_TYPE_DDR2;
+
+	sdram_cfg = (0
+		     | SDRAM_CFG_MEM_EN		/* DDR enable */
+		     | SDRAM_CFG_SREN		/* Self refresh */
+		     | sdram_type		/* SDRAM type */
+		     );
+
+	/* sdram_cfg[3] = RD_EN - registered DIMM enable */
+	if (spd.mod_attr & 0x02)
+		sdram_cfg |= SDRAM_CFG_RD_EN;
+
+	/* The DIMM is 32bit width */
+	if (spd.dataw_lsb < 64) {
+		if (spd.mem_type == SPD_MEMTYPE_DDR)
+			sdram_cfg |= SDRAM_CFG_32_BE | SDRAM_CFG_8_BE;
+		if (spd.mem_type == SPD_MEMTYPE_DDR2)
+			sdram_cfg |= SDRAM_CFG_32_BE;
+	}
+
+	ddrc_ecc_enable = 0;
+
+#if defined(CONFIG_DDR_ECC)
+	/* Enable ECC with sdram_cfg[2] */
+	if (spd.config == 0x02) {
+		sdram_cfg |= 0x20000000;
+		ddrc_ecc_enable = 1;
+		/* disable error detection */
+		ddr->err_disable = ~ECC_ERROR_ENABLE;
+		/* set single bit error threshold to maximum value,
+		 * reset counter to zero */
+		ddr->err_sbe = (255 << ECC_ERROR_MAN_SBET_SHIFT) |
+				(0 << ECC_ERROR_MAN_SBEC_SHIFT);
+	}
+
+	debug("DDR:err_disable=0x%08x\n", ddr->err_disable);
+	debug("DDR:err_sbe=0x%08x\n", ddr->err_sbe);
+#endif
+	debug("   DDRC ECC mode: %s\n", ddrc_ecc_enable ? "ON":"OFF");
+
+#if defined(CONFIG_DDR_2T_TIMING)
+	/*
+	 * Enable 2T timing by setting sdram_cfg[16].
+	 */
+	sdram_cfg |= SDRAM_CFG_2T_EN;
+#endif
+	/* Enable controller, and GO! */
+	ddr->sdram_cfg = sdram_cfg;
+	asm("sync;isync");
+	udelay(500);
+
+	debug("DDR:sdram_cfg=0x%08x\n", ddr->sdram_cfg);
+	return memsize; /*in MBytes*/
+}
+#endif /* CONFIG_SPD_EEPROM */
+
+#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+/*
+ * Use timebase counter, get_timer() is not availabe
+ * at this point of initialization yet.
+ */
+static __inline__ unsigned long get_tbms (void)
+{
+	unsigned long tbl;
+	unsigned long tbu1, tbu2;
+	unsigned long ms;
+	unsigned long long tmp;
+
+	ulong tbclk = get_tbclk();
+
+	/* get the timebase ticks */
+	do {
+		asm volatile ("mftbu %0":"=r" (tbu1):);
+		asm volatile ("mftb %0":"=r" (tbl):);
+		asm volatile ("mftbu %0":"=r" (tbu2):);
+	} while (tbu1 != tbu2);
+
+	/* convert ticks to ms */
+	tmp = (unsigned long long)(tbu1);
+	tmp = (tmp << 32);
+	tmp += (unsigned long long)(tbl);
+	ms = tmp/(tbclk/1000);
+
+	return ms;
+}
+
+/*
+ * Initialize all of memory for ECC, then enable errors.
+ */
+void ddr_enable_ecc(unsigned int dram_size)
+{
+	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+	volatile ddr83xx_t *ddr= &immap->ddr;
+	unsigned long t_start, t_end;
+	register u64 *p;
+	register uint size;
+	unsigned int pattern[2];
+
+	icache_enable();
+	t_start = get_tbms();
+	pattern[0] = 0xdeadbeef;
+	pattern[1] = 0xdeadbeef;
+
+#if defined(CONFIG_DDR_ECC_INIT_VIA_DMA)
+	dma_meminit(pattern[0], dram_size);
+#else
+	debug("ddr init: CPU FP write method\n");
+	size = dram_size;
+	for (p = 0; p < (u64*)(size); p++) {
+		ppcDWstore((u32*)p, pattern);
+	}
+	__asm__ __volatile__ ("sync");
+#endif
+
+	t_end = get_tbms();
+	icache_disable();
+
+	debug("\nREADY!!\n");
+	debug("ddr init duration: %ld ms\n", t_end - t_start);
+
+	/* Clear All ECC Errors */
+	if ((ddr->err_detect & ECC_ERROR_DETECT_MME) == ECC_ERROR_DETECT_MME)
+		ddr->err_detect |= ECC_ERROR_DETECT_MME;
+	if ((ddr->err_detect & ECC_ERROR_DETECT_MBE) == ECC_ERROR_DETECT_MBE)
+		ddr->err_detect |= ECC_ERROR_DETECT_MBE;
+	if ((ddr->err_detect & ECC_ERROR_DETECT_SBE) == ECC_ERROR_DETECT_SBE)
+		ddr->err_detect |= ECC_ERROR_DETECT_SBE;
+	if ((ddr->err_detect & ECC_ERROR_DETECT_MSE) == ECC_ERROR_DETECT_MSE)
+		ddr->err_detect |= ECC_ERROR_DETECT_MSE;
+
+	/* Disable ECC-Interrupts */
+	ddr->err_int_en &= ECC_ERR_INT_DISABLE;
+
+	/* Enable errors for ECC */
+	ddr->err_disable &= ECC_ERROR_ENABLE;
+
+	__asm__ __volatile__ ("sync");
+	__asm__ __volatile__ ("isync");
+}
+#endif	/* CONFIG_DDR_ECC */
diff --git a/arch/powerpc/cpu/mpc83xx/speed.c b/arch/powerpc/cpu/mpc83xx/speed.c
new file mode 100644
index 0000000..bde7e92
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/speed.c
@@ -0,0 +1,549 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc83xx.h>
+#include <command.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* ----------------------------------------------------------------- */
+
+typedef enum {
+	_unk,
+	_off,
+	_byp,
+	_x8,
+	_x4,
+	_x2,
+	_x1,
+	_1x,
+	_1_5x,
+	_2x,
+	_2_5x,
+	_3x
+} mult_t;
+
+typedef struct {
+	mult_t core_csb_ratio;
+	mult_t vco_divider;
+} corecnf_t;
+
+corecnf_t corecnf_tab[] = {
+	{_byp, _byp},		/* 0x00 */
+	{_byp, _byp},		/* 0x01 */
+	{_byp, _byp},		/* 0x02 */
+	{_byp, _byp},		/* 0x03 */
+	{_byp, _byp},		/* 0x04 */
+	{_byp, _byp},		/* 0x05 */
+	{_byp, _byp},		/* 0x06 */
+	{_byp, _byp},		/* 0x07 */
+	{_1x, _x2},		/* 0x08 */
+	{_1x, _x4},		/* 0x09 */
+	{_1x, _x8},		/* 0x0A */
+	{_1x, _x8},		/* 0x0B */
+	{_1_5x, _x2},		/* 0x0C */
+	{_1_5x, _x4},		/* 0x0D */
+	{_1_5x, _x8},		/* 0x0E */
+	{_1_5x, _x8},		/* 0x0F */
+	{_2x, _x2},		/* 0x10 */
+	{_2x, _x4},		/* 0x11 */
+	{_2x, _x8},		/* 0x12 */
+	{_2x, _x8},		/* 0x13 */
+	{_2_5x, _x2},		/* 0x14 */
+	{_2_5x, _x4},		/* 0x15 */
+	{_2_5x, _x8},		/* 0x16 */
+	{_2_5x, _x8},		/* 0x17 */
+	{_3x, _x2},		/* 0x18 */
+	{_3x, _x4},		/* 0x19 */
+	{_3x, _x8},		/* 0x1A */
+	{_3x, _x8},		/* 0x1B */
+};
+
+/* ----------------------------------------------------------------- */
+
+/*
+ *
+ */
+int get_clocks(void)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	u32 pci_sync_in;
+	u8 spmf;
+	u8 clkin_div;
+	u32 sccr;
+	u32 corecnf_tab_index;
+	u8 corepll;
+	u32 lcrr;
+
+	u32 csb_clk;
+#if defined(CONFIG_MPC834x) || defined(CONFIG_MPC831x) || defined(CONFIG_MPC837x)
+	u32 tsec1_clk;
+	u32 tsec2_clk;
+	u32 usbdr_clk;
+#endif
+#ifdef CONFIG_MPC834x
+	u32 usbmph_clk;
+#endif
+	u32 core_clk;
+	u32 i2c1_clk;
+#if !defined(CONFIG_MPC832x)
+	u32 i2c2_clk;
+#endif
+#if defined(CONFIG_MPC8315)
+	u32 tdm_clk;
+#endif
+#if defined(CONFIG_MPC837x)
+	u32 sdhc_clk;
+#endif
+	u32 enc_clk;
+	u32 lbiu_clk;
+	u32 lclk_clk;
+	u32 mem_clk;
+#if defined(CONFIG_MPC8360)
+	u32 mem_sec_clk;
+#endif
+#if defined(CONFIG_MPC8360) || defined(CONFIG_MPC832x)
+	u32 qepmf;
+	u32 qepdf;
+	u32 qe_clk;
+	u32 brg_clk;
+#endif
+#if defined(CONFIG_MPC837x) || defined(CONFIG_MPC831x)
+	u32 pciexp1_clk;
+	u32 pciexp2_clk;
+#endif
+#if defined(CONFIG_MPC837x) || defined(CONFIG_MPC8315)
+	u32 sata_clk;
+#endif
+
+	if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im)
+		return -1;
+
+	clkin_div = ((im->clk.spmr & SPMR_CKID) >> SPMR_CKID_SHIFT);
+
+	if (im->reset.rcwh & HRCWH_PCI_HOST) {
+#if defined(CONFIG_83XX_CLKIN)
+		pci_sync_in = CONFIG_83XX_CLKIN / (1 + clkin_div);
+#else
+		pci_sync_in = 0xDEADBEEF;
+#endif
+	} else {
+#if defined(CONFIG_83XX_PCICLK)
+		pci_sync_in = CONFIG_83XX_PCICLK;
+#else
+		pci_sync_in = 0xDEADBEEF;
+#endif
+	}
+
+	spmf = ((im->reset.rcwl & HRCWL_SPMF) >> HRCWL_SPMF_SHIFT);
+	csb_clk = pci_sync_in * (1 + clkin_div) * spmf;
+
+	sccr = im->clk.sccr;
+
+#if defined(CONFIG_MPC834x) || defined(CONFIG_MPC831x) || defined(CONFIG_MPC837x)
+	switch ((sccr & SCCR_TSEC1CM) >> SCCR_TSEC1CM_SHIFT) {
+	case 0:
+		tsec1_clk = 0;
+		break;
+	case 1:
+		tsec1_clk = csb_clk;
+		break;
+	case 2:
+		tsec1_clk = csb_clk / 2;
+		break;
+	case 3:
+		tsec1_clk = csb_clk / 3;
+		break;
+	default:
+		/* unkown SCCR_TSEC1CM value */
+		return -2;
+	}
+
+	switch ((sccr & SCCR_USBDRCM) >> SCCR_USBDRCM_SHIFT) {
+	case 0:
+		usbdr_clk = 0;
+		break;
+	case 1:
+		usbdr_clk = csb_clk;
+		break;
+	case 2:
+		usbdr_clk = csb_clk / 2;
+		break;
+	case 3:
+		usbdr_clk = csb_clk / 3;
+		break;
+	default:
+		/* unkown SCCR_USBDRCM value */
+		return -3;
+	}
+#endif
+
+#if defined(CONFIG_MPC834x) || defined(CONFIG_MPC837x) || defined(CONFIG_MPC8315)
+	switch ((sccr & SCCR_TSEC2CM) >> SCCR_TSEC2CM_SHIFT) {
+	case 0:
+		tsec2_clk = 0;
+		break;
+	case 1:
+		tsec2_clk = csb_clk;
+		break;
+	case 2:
+		tsec2_clk = csb_clk / 2;
+		break;
+	case 3:
+		tsec2_clk = csb_clk / 3;
+		break;
+	default:
+		/* unkown SCCR_TSEC2CM value */
+		return -4;
+	}
+#elif defined(CONFIG_MPC8313)
+	tsec2_clk = tsec1_clk;
+
+	if (!(sccr & SCCR_TSEC1ON))
+		tsec1_clk = 0;
+	if (!(sccr & SCCR_TSEC2ON))
+		tsec2_clk = 0;
+#endif
+
+#if defined(CONFIG_MPC834x)
+	switch ((sccr & SCCR_USBMPHCM) >> SCCR_USBMPHCM_SHIFT) {
+	case 0:
+		usbmph_clk = 0;
+		break;
+	case 1:
+		usbmph_clk = csb_clk;
+		break;
+	case 2:
+		usbmph_clk = csb_clk / 2;
+		break;
+	case 3:
+		usbmph_clk = csb_clk / 3;
+		break;
+	default:
+		/* unkown SCCR_USBMPHCM value */
+		return -5;
+	}
+
+	if (usbmph_clk != 0 && usbdr_clk != 0 && usbmph_clk != usbdr_clk) {
+		/* if USB MPH clock is not disabled and
+		 * USB DR clock is not disabled then
+		 * USB MPH & USB DR must have the same rate
+		 */
+		return -6;
+	}
+#endif
+	switch ((sccr & SCCR_ENCCM) >> SCCR_ENCCM_SHIFT) {
+	case 0:
+		enc_clk = 0;
+		break;
+	case 1:
+		enc_clk = csb_clk;
+		break;
+	case 2:
+		enc_clk = csb_clk / 2;
+		break;
+	case 3:
+		enc_clk = csb_clk / 3;
+		break;
+	default:
+		/* unkown SCCR_ENCCM value */
+		return -7;
+	}
+
+#if defined(CONFIG_MPC837x)
+	switch ((sccr & SCCR_SDHCCM) >> SCCR_SDHCCM_SHIFT) {
+	case 0:
+		sdhc_clk = 0;
+		break;
+	case 1:
+		sdhc_clk = csb_clk;
+		break;
+	case 2:
+		sdhc_clk = csb_clk / 2;
+		break;
+	case 3:
+		sdhc_clk = csb_clk / 3;
+		break;
+	default:
+		/* unkown SCCR_SDHCCM value */
+		return -8;
+	}
+#endif
+#if defined(CONFIG_MPC8315)
+	switch ((sccr & SCCR_TDMCM) >> SCCR_TDMCM_SHIFT) {
+	case 0:
+		tdm_clk = 0;
+		break;
+	case 1:
+		tdm_clk = csb_clk;
+		break;
+	case 2:
+		tdm_clk = csb_clk / 2;
+		break;
+	case 3:
+		tdm_clk = csb_clk / 3;
+		break;
+	default:
+		/* unkown SCCR_TDMCM value */
+		return -8;
+	}
+#endif
+
+#if defined(CONFIG_MPC834x)
+	i2c1_clk = tsec2_clk;
+#elif defined(CONFIG_MPC8360)
+	i2c1_clk = csb_clk;
+#elif defined(CONFIG_MPC832x)
+	i2c1_clk = enc_clk;
+#elif defined(CONFIG_MPC831x)
+	i2c1_clk = enc_clk;
+#elif defined(CONFIG_MPC837x)
+	i2c1_clk = sdhc_clk;
+#endif
+#if !defined(CONFIG_MPC832x)
+	i2c2_clk = csb_clk; /* i2c-2 clk is equal to csb clk */
+#endif
+
+#if defined(CONFIG_MPC837x) || defined(CONFIG_MPC831x)
+	switch ((sccr & SCCR_PCIEXP1CM) >> SCCR_PCIEXP1CM_SHIFT) {
+	case 0:
+		pciexp1_clk = 0;
+		break;
+	case 1:
+		pciexp1_clk = csb_clk;
+		break;
+	case 2:
+		pciexp1_clk = csb_clk / 2;
+		break;
+	case 3:
+		pciexp1_clk = csb_clk / 3;
+		break;
+	default:
+		/* unkown SCCR_PCIEXP1CM value */
+		return -9;
+	}
+
+	switch ((sccr & SCCR_PCIEXP2CM) >> SCCR_PCIEXP2CM_SHIFT) {
+	case 0:
+		pciexp2_clk = 0;
+		break;
+	case 1:
+		pciexp2_clk = csb_clk;
+		break;
+	case 2:
+		pciexp2_clk = csb_clk / 2;
+		break;
+	case 3:
+		pciexp2_clk = csb_clk / 3;
+		break;
+	default:
+		/* unkown SCCR_PCIEXP2CM value */
+		return -10;
+	}
+#endif
+
+#if defined(CONFIG_MPC837x) || defined(CONFIG_MPC8315)
+	switch ((sccr & SCCR_SATA1CM) >> SCCR_SATA1CM_SHIFT) {
+	case 0:
+		sata_clk = 0;
+		break;
+	case 1:
+		sata_clk = csb_clk;
+		break;
+	case 2:
+		sata_clk = csb_clk / 2;
+		break;
+	case 3:
+		sata_clk = csb_clk / 3;
+		break;
+	default:
+		/* unkown SCCR_SATACM value */
+		return -11;
+	}
+#endif
+
+	lbiu_clk = csb_clk *
+	           (1 + ((im->reset.rcwl & HRCWL_LBIUCM) >> HRCWL_LBIUCM_SHIFT));
+	lcrr = (im->lbus.lcrr & LCRR_CLKDIV) >> LCRR_CLKDIV_SHIFT;
+	switch (lcrr) {
+	case 2:
+	case 4:
+	case 8:
+		lclk_clk = lbiu_clk / lcrr;
+		break;
+	default:
+		/* unknown lcrr */
+		return -12;
+	}
+
+	mem_clk = csb_clk *
+		  (1 + ((im->reset.rcwl & HRCWL_DDRCM) >> HRCWL_DDRCM_SHIFT));
+	corepll = (im->reset.rcwl & HRCWL_COREPLL) >> HRCWL_COREPLL_SHIFT;
+#if defined(CONFIG_MPC8360)
+	mem_sec_clk = csb_clk * (1 +
+		       ((im->reset.rcwl & HRCWL_LBIUCM) >> HRCWL_LBIUCM_SHIFT));
+#endif
+
+	corecnf_tab_index = ((corepll & 0x1F) << 2) | ((corepll & 0x60) >> 5);
+	if (corecnf_tab_index > (sizeof(corecnf_tab) / sizeof(corecnf_t))) {
+		/* corecnf_tab_index is too high, possibly worng value */
+		return -11;
+	}
+	switch (corecnf_tab[corecnf_tab_index].core_csb_ratio) {
+	case _byp:
+	case _x1:
+	case _1x:
+		core_clk = csb_clk;
+		break;
+	case _1_5x:
+		core_clk = (3 * csb_clk) / 2;
+		break;
+	case _2x:
+		core_clk = 2 * csb_clk;
+		break;
+	case _2_5x:
+		core_clk = (5 * csb_clk) / 2;
+		break;
+	case _3x:
+		core_clk = 3 * csb_clk;
+		break;
+	default:
+		/* unkown core to csb ratio */
+		return -13;
+	}
+
+#if defined(CONFIG_MPC8360) || defined(CONFIG_MPC832x)
+	qepmf = (im->reset.rcwl & HRCWL_CEPMF) >> HRCWL_CEPMF_SHIFT;
+	qepdf = (im->reset.rcwl & HRCWL_CEPDF) >> HRCWL_CEPDF_SHIFT;
+	qe_clk = (pci_sync_in * qepmf) / (1 + qepdf);
+	brg_clk = qe_clk / 2;
+#endif
+
+	gd->csb_clk = csb_clk;
+#if defined(CONFIG_MPC834x) || defined(CONFIG_MPC831x) || defined(CONFIG_MPC837x)
+	gd->tsec1_clk = tsec1_clk;
+	gd->tsec2_clk = tsec2_clk;
+	gd->usbdr_clk = usbdr_clk;
+#endif
+#if defined(CONFIG_MPC834x)
+	gd->usbmph_clk = usbmph_clk;
+#endif
+#if defined(CONFIG_MPC8315)
+	gd->tdm_clk = tdm_clk;
+#endif
+#if defined(CONFIG_MPC837x)
+	gd->sdhc_clk = sdhc_clk;
+#endif
+	gd->core_clk = core_clk;
+	gd->i2c1_clk = i2c1_clk;
+#if !defined(CONFIG_MPC832x)
+	gd->i2c2_clk = i2c2_clk;
+#endif
+	gd->enc_clk = enc_clk;
+	gd->lbiu_clk = lbiu_clk;
+	gd->lclk_clk = lclk_clk;
+	gd->mem_clk = mem_clk;
+#if defined(CONFIG_MPC8360)
+	gd->mem_sec_clk = mem_sec_clk;
+#endif
+#if defined(CONFIG_MPC8360) || defined(CONFIG_MPC832x)
+	gd->qe_clk = qe_clk;
+	gd->brg_clk = brg_clk;
+#endif
+#if defined(CONFIG_MPC837x)
+	gd->pciexp1_clk = pciexp1_clk;
+	gd->pciexp2_clk = pciexp2_clk;
+#endif
+#if defined(CONFIG_MPC837x) || defined(CONFIG_MPC8315)
+	gd->sata_clk = sata_clk;
+#endif
+	gd->pci_clk = pci_sync_in;
+	gd->cpu_clk = gd->core_clk;
+	gd->bus_clk = gd->csb_clk;
+	return 0;
+
+}
+
+/********************************************
+ * get_bus_freq
+ * return system bus freq in Hz
+ *********************************************/
+ulong get_bus_freq(ulong dummy)
+{
+	return gd->csb_clk;
+}
+
+int do_clocks (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	char buf[32];
+
+	printf("Clock configuration:\n");
+	printf("  Core:                %-4s MHz\n", strmhz(buf, gd->core_clk));
+	printf("  Coherent System Bus: %-4s MHz\n", strmhz(buf, gd->csb_clk));
+#if defined(CONFIG_MPC8360) || defined(CONFIG_MPC832x)
+	printf("  QE:                  %-4s MHz\n", strmhz(buf, gd->qe_clk));
+	printf("  BRG:                 %-4s MHz\n", strmhz(buf, gd->brg_clk));
+#endif
+	printf("  Local Bus Controller:%-4s MHz\n", strmhz(buf, gd->lbiu_clk));
+	printf("  Local Bus:           %-4s MHz\n", strmhz(buf, gd->lclk_clk));
+	printf("  DDR:                 %-4s MHz\n", strmhz(buf, gd->mem_clk));
+#if defined(CONFIG_MPC8360)
+	printf("  DDR Secondary:       %-4s MHz\n", strmhz(buf, gd->mem_sec_clk));
+#endif
+	printf("  SEC:                 %-4s MHz\n", strmhz(buf, gd->enc_clk));
+	printf("  I2C1:                %-4s MHz\n", strmhz(buf, gd->i2c1_clk));
+#if !defined(CONFIG_MPC832x)
+	printf("  I2C2:                %-4s MHz\n", strmhz(buf, gd->i2c2_clk));
+#endif
+#if defined(CONFIG_MPC8315)
+	printf("  TDM:                 %-4s MHz\n", strmhz(buf, gd->tdm_clk));
+#endif
+#if defined(CONFIG_MPC837x)
+	printf("  SDHC:                %-4s MHz\n", strmhz(buf, gd->sdhc_clk));
+#endif
+#if defined(CONFIG_MPC834x) || defined(CONFIG_MPC831x) || defined(CONFIG_MPC837x)
+	printf("  TSEC1:               %-4s MHz\n", strmhz(buf, gd->tsec1_clk));
+	printf("  TSEC2:               %-4s MHz\n", strmhz(buf, gd->tsec2_clk));
+	printf("  USB DR:              %-4s MHz\n", strmhz(buf, gd->usbdr_clk));
+#endif
+#if defined(CONFIG_MPC834x)
+	printf("  USB MPH:             %-4s MHz\n", strmhz(buf, gd->usbmph_clk));
+#endif
+#if defined(CONFIG_MPC837x)
+	printf("  PCIEXP1:             %-4s MHz\n", strmhz(buf, gd->pciexp1_clk));
+	printf("  PCIEXP2:             %-4s MHz\n", strmhz(buf, gd->pciexp2_clk));
+#endif
+#if defined(CONFIG_MPC837x) || defined(CONFIG_MPC8315)
+	printf("  SATA:                %-4s MHz\n", strmhz(buf, gd->sata_clk));
+#endif
+	return 0;
+}
+
+U_BOOT_CMD(clocks, 1, 0, do_clocks,
+	"print clock configuration",
+	"    clocks"
+);
diff --git a/arch/powerpc/cpu/mpc83xx/start.S b/arch/powerpc/cpu/mpc83xx/start.S
new file mode 100644
index 0000000..a7c8079
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/start.S
@@ -0,0 +1,1207 @@
+/*
+ * Copyright (C) 1998  Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000, 2001,2002 Wolfgang Denk <wd@denx.de>
+ * Copyright Freescale Semiconductor, Inc. 2004, 2006, 2008.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ *  U-Boot - Startup Code for MPC83xx PowerPC based Embedded Boards
+ */
+
+#include <config.h>
+#include <mpc83xx.h>
+#include <timestamp.h>
+#include <version.h>
+
+#define CONFIG_83XX	1		/* needed for Linux kernel header files*/
+#define _LINUX_CONFIG_H 1	/* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef  CONFIG_IDENT_STRING
+#define  CONFIG_IDENT_STRING "MPC83XX"
+#endif
+
+/* We don't want the  MMU yet.
+ */
+#undef	MSR_KERNEL
+
+/*
+ * Floating Point enable, Machine Check and Recoverable Interr.
+ */
+#ifdef DEBUG
+#define MSR_KERNEL (MSR_FP|MSR_RI)
+#else
+#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
+#endif
+
+#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_SYS_RAMBOOT)
+#define CONFIG_SYS_FLASHBOOT
+#endif
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+	START_GOT
+	GOT_ENTRY(_GOT2_TABLE_)
+	GOT_ENTRY(__bss_start)
+	GOT_ENTRY(_end)
+
+#ifndef CONFIG_NAND_SPL
+	GOT_ENTRY(_FIXUP_TABLE_)
+	GOT_ENTRY(_start)
+	GOT_ENTRY(_start_of_vectors)
+	GOT_ENTRY(_end_of_vectors)
+	GOT_ENTRY(transfer_to_handler)
+#endif
+	END_GOT
+
+/*
+ * The Hard Reset Configuration Word (HRCW) table is in the first 64
+ * (0x40) bytes of flash.  It has 8 bytes, but each byte is repeated 8
+ * times so the processor can fetch it out of flash whether the flash
+ * is 8, 16, 32, or 64 bits wide (hardware trickery).
+ */
+	.text
+#define _HRCW_TABLE_ENTRY(w)		\
+	.fill	8,1,(((w)>>24)&0xff);	\
+	.fill	8,1,(((w)>>16)&0xff);	\
+	.fill	8,1,(((w)>> 8)&0xff);	\
+	.fill	8,1,(((w)    )&0xff)
+
+	_HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_LOW)
+	_HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_HIGH)
+
+/*
+ * Magic number and version string - put it after the HRCW since it
+ * cannot be first in flash like it is in many other processors.
+ */
+	.long	0x27051956		/* U-Boot Magic Number */
+
+	.globl	version_string
+version_string:
+	.ascii U_BOOT_VERSION
+	.ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
+	.ascii " ", CONFIG_IDENT_STRING, "\0"
+
+	.align 2
+
+	.globl enable_addr_trans
+enable_addr_trans:
+	/* enable address translation */
+	mfmsr	r5
+	ori	r5, r5, (MSR_IR | MSR_DR)
+	mtmsr	r5
+	isync
+	blr
+
+	.globl disable_addr_trans
+disable_addr_trans:
+	/* disable address translation */
+	mflr	r4
+	mfmsr	r3
+	andi.	r0, r3, (MSR_IR | MSR_DR)
+	beqlr
+	andc	r3, r3, r0
+	mtspr	SRR0, r4
+	mtspr	SRR1, r3
+	rfi
+
+	.globl get_pvr
+get_pvr:
+	mfspr	r3, PVR
+	blr
+
+	.globl	ppcDWstore
+ppcDWstore:
+	lfd	1, 0(r4)
+	stfd	1, 0(r3)
+	blr
+
+	.globl	ppcDWload
+ppcDWload:
+	lfd	1, 0(r3)
+	stfd	1, 0(r4)
+	blr
+
+#ifndef CONFIG_DEFAULT_IMMR
+#error CONFIG_DEFAULT_IMMR must be defined
+#endif /* CONFIG_SYS_DEFAULT_IMMR */
+#ifndef CONFIG_SYS_IMMR
+#define CONFIG_SYS_IMMR CONFIG_DEFAULT_IMMR
+#endif /* CONFIG_SYS_IMMR */
+
+/*
+ * After configuration, a system reset exception is executed using the
+ * vector at offset 0x100 relative to the base set by MSR[IP]. If
+ * MSR[IP] is 0, the base address is 0x00000000. If MSR[IP] is 1, the
+ * base address is 0xfff00000. In the case of a Power On Reset or Hard
+ * Reset, the value of MSR[IP] is determined by the CIP field in the
+ * HRCW.
+ *
+ * Other bits in the HRCW set up the Base Address and Port Size in BR0.
+ * This determines the location of the boot ROM (flash or EPROM) in the
+ * processor's address space at boot time. As long as the HRCW is set up
+ * so that we eventually end up executing the code below when the
+ * processor executes the reset exception, the actual values used should
+ * not matter.
+ *
+ * Once we have got here, the address mask in OR0 is cleared so that the
+ * bottom 32K of the boot ROM is effectively repeated all throughout the
+ * processor's address space, after which we can jump to the absolute
+ * address at which the boot ROM was linked at compile time, and proceed
+ * to initialise the memory controller without worrying if the rug will
+ * be pulled out from under us, so to speak (it will be fine as long as
+ * we configure BR0 with the same boot ROM link address).
+ */
+	. = EXC_OFF_SYS_RESET
+
+	.globl	_start
+_start: /* time t 0 */
+	li	r21, BOOTFLAG_COLD  /* Normal Power-On: Boot from FLASH*/
+	nop
+	b	boot_cold
+
+	. = EXC_OFF_SYS_RESET + 0x10
+
+	.globl	_start_warm
+_start_warm:
+	li	r21, BOOTFLAG_WARM	/* Software reboot	*/
+	b	boot_warm
+
+
+boot_cold: /* time t 3 */
+	lis	r4, CONFIG_DEFAULT_IMMR@h
+	nop
+boot_warm: /* time t 5 */
+	mfmsr	r5			/* save msr contents	*/
+
+	/* 83xx manuals prescribe a specific sequence for updating IMMRBAR. */
+	bl	1f
+1:	mflr	r7
+
+	lis	r3, CONFIG_SYS_IMMR@h
+	ori	r3, r3, CONFIG_SYS_IMMR@l
+
+	lwz	r6, IMMRBAR(r4)
+	isync
+
+	stw	r3, IMMRBAR(r4)
+	lwz	r6, 0(r7)		/* Arbitrary external load */
+	isync
+
+	lwz	r6, IMMRBAR(r3)
+	isync
+
+	/* Initialise the E300 processor core		*/
+	/*------------------------------------------*/
+
+#ifdef CONFIG_NAND_SPL
+	/* The FCM begins execution after only the first page
+	 * is loaded.  Wait for the rest before branching
+	 * to another flash page.
+	 */
+1:	lwz	r6, 0x50b0(r3)
+	andi.	r6, r6, 1
+	beq	1b
+#endif
+
+	bl	init_e300_core
+
+#ifdef CONFIG_SYS_FLASHBOOT
+
+	/* Inflate flash location so it appears everywhere, calculate */
+	/* the absolute address in final location of the FLASH, jump  */
+	/* there and deflate the flash size back to minimal size      */
+	/*------------------------------------------------------------*/
+	bl map_flash_by_law1
+	lis r4, (CONFIG_SYS_MONITOR_BASE)@h
+	ori r4, r4, (CONFIG_SYS_MONITOR_BASE)@l
+	addi r5, r4, in_flash - _start + EXC_OFF_SYS_RESET
+	mtlr r5
+	blr
+in_flash:
+#if 1 /* Remapping flash with LAW0. */
+	bl remap_flash_by_law0
+#endif
+#endif	/* CONFIG_SYS_FLASHBOOT */
+
+	/* setup the bats */
+	bl	setup_bats
+	sync
+
+	/*
+	 * Cache must be enabled here for stack-in-cache trick.
+	 * This means we need to enable the BATS.
+	 * This means:
+	 *   1) for the EVB, original gt regs need to be mapped
+	 *   2) need to have an IBAT for the 0xf region,
+	 *      we are running there!
+	 * Cache should be turned on after BATs, since by default
+	 * everything is write-through.
+	 * The init-mem BAT can be reused after reloc. The old
+	 * gt-regs BAT can be reused after board_init_f calls
+	 * board_early_init_f (EVB only).
+	 */
+	/* enable address translation */
+	bl	enable_addr_trans
+	sync
+
+	/* enable the data cache */
+	bl	dcache_enable
+	sync
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+	bl	lock_ram_in_cache
+	sync
+#endif
+
+	/* set up the stack pointer in our newly created
+	 * cache-ram (r1) */
+	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
+	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
+
+	li	r0, 0		/* Make room for stack frame header and	*/
+	stwu	r0, -4(r1)	/* clear final stack frame so that	*/
+	stwu	r0, -4(r1)	/* stack backtraces terminate cleanly	*/
+
+
+	/* let the C-code set up the rest	                    */
+	/*				                            */
+	/* Be careful to keep code relocatable & stack humble   */
+	/*------------------------------------------------------*/
+
+	GET_GOT			/* initialize GOT access	*/
+
+	/* r3: IMMR */
+	lis	r3, CONFIG_SYS_IMMR@h
+	/* run low-level CPU init code (in Flash)*/
+	bl	cpu_init_f
+
+	/* r3: BOOTFLAG */
+	mr	r3, r21
+	/* run 1st part of board init code (in Flash)*/
+	bl	board_init_f
+
+#ifndef CONFIG_NAND_SPL
+/*
+ * Vector Table
+ */
+
+	.globl	_start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+	STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+	STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+#ifndef FIXME
+	STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+#endif
+
+/* Alignment exception. */
+	. = 0x600
+Alignment:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	mfspr	r4,DAR
+	stw	r4,_DAR(r21)
+	mfspr	r5,DSISR
+	stw	r5,_DSISR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+	. = 0x700
+ProgramCheck:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+		MSR_KERNEL, COPY_EE)
+
+	STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+	/* I guess we could implement decrementer, and may have
+	 * to someday for timekeeping.
+	 */
+	STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+
+	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+	STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+	STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+	STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+	STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+	STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+	STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
+#ifdef DEBUG
+	. = 0x1300
+	/*
+	 * This exception occurs when the program counter matches the
+	 * Instruction Address Breakpoint Register (IABR).
+	 *
+	 * I want the cpu to halt if this occurs so I can hunt around
+	 * with the debugger and look at things.
+	 *
+	 * When DEBUG is defined, both machine check enable (in the MSR)
+	 * and checkstop reset enable (in the reset mode register) are
+	 * turned off and so a checkstop condition will result in the cpu
+	 * halting.
+	 *
+	 * I force the cpu into a checkstop condition by putting an illegal
+	 * instruction here (at least this is the theory).
+	 *
+	 * well - that didnt work, so just do an infinite loop!
+	 */
+1:	b	1b
+#else
+	STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
+#endif
+	STD_EXCEPTION(0x1400, SMI, UnknownException)
+
+	STD_EXCEPTION(0x1500, Trap_15, UnknownException)
+	STD_EXCEPTION(0x1600, Trap_16, UnknownException)
+	STD_EXCEPTION(0x1700, Trap_17, UnknownException)
+	STD_EXCEPTION(0x1800, Trap_18, UnknownException)
+	STD_EXCEPTION(0x1900, Trap_19, UnknownException)
+	STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
+	STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+	STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
+	STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
+	STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
+	STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
+	STD_EXCEPTION(0x2000, Trap_20, UnknownException)
+	STD_EXCEPTION(0x2100, Trap_21, UnknownException)
+	STD_EXCEPTION(0x2200, Trap_22, UnknownException)
+	STD_EXCEPTION(0x2300, Trap_23, UnknownException)
+	STD_EXCEPTION(0x2400, Trap_24, UnknownException)
+	STD_EXCEPTION(0x2500, Trap_25, UnknownException)
+	STD_EXCEPTION(0x2600, Trap_26, UnknownException)
+	STD_EXCEPTION(0x2700, Trap_27, UnknownException)
+	STD_EXCEPTION(0x2800, Trap_28, UnknownException)
+	STD_EXCEPTION(0x2900, Trap_29, UnknownException)
+	STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
+	STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
+	STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
+	STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
+	STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
+	STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
+
+
+	.globl	_end_of_vectors
+_end_of_vectors:
+
+	. = 0x3000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+	.globl	transfer_to_handler
+transfer_to_handler:
+	stw	r22,_NIP(r21)
+	lis	r22,MSR_POW@h
+	andc	r23,r23,r22
+	stw	r23,_MSR(r21)
+	SAVE_GPR(7, r21)
+	SAVE_4GPRS(8, r21)
+	SAVE_8GPRS(12, r21)
+	SAVE_8GPRS(24, r21)
+	mflr	r23
+	andi.	r24,r23,0x3f00		/* get vector offset */
+	stw	r24,TRAP(r21)
+	li	r22,0
+	stw	r22,RESULT(r21)
+	lwz	r24,0(r23)		/* virtual address of handler */
+	lwz	r23,4(r23)		/* where to go when done */
+	mtspr	SRR0,r24
+	mtspr	SRR1,r20
+	mtlr	r23
+	SYNC
+	rfi				/* jump to handler, enable MMU */
+
+int_return:
+	mfmsr	r28		/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC			/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SRR0,r2
+	mtspr	SRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfi
+#endif /* !CONFIG_NAND_SPL */
+
+/*
+ * This code initialises the E300 processor core
+ * (conforms to PowerPC 603e spec)
+ * Note: expects original MSR contents to be in r5.
+ */
+	.globl	init_e300_core
+init_e300_core: /* time t 10 */
+	/* Initialize machine status; enable machine check interrupt */
+	/*-----------------------------------------------------------*/
+
+	li	r3, MSR_KERNEL			/* Set ME and RI flags */
+	rlwimi	r3, r5, 0, 25, 25	/* preserve IP bit set by HRCW */
+#ifdef DEBUG
+	rlwimi	r3, r5, 0, 21, 22   /* debugger might set SE & BE bits */
+#endif
+	SYNC						/* Some chip revs need this... */
+	mtmsr	r3
+	SYNC
+	mtspr	SRR1, r3			/* Make SRR1 match MSR */
+
+
+	lis	r3, CONFIG_SYS_IMMR@h
+#if defined(CONFIG_WATCHDOG)
+	/* Initialise the Wathcdog values and reset it (if req) */
+	/*------------------------------------------------------*/
+	lis r4, CONFIG_SYS_WATCHDOG_VALUE
+	ori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR)
+	stw r4, SWCRR(r3)
+
+	/* and reset it */
+
+	li	r4, 0x556C
+	sth	r4, SWSRR@l(r3)
+	li	r4, -0x55C7
+	sth	r4, SWSRR@l(r3)
+#else
+	/* Disable Wathcdog  */
+	/*-------------------*/
+	lwz r4, SWCRR(r3)
+	/* Check to see if its enabled for disabling
+	   once disabled by SW you can't re-enable */
+	andi. r4, r4, 0x4
+	beq 1f
+	xor r4, r4, r4
+	stw r4, SWCRR(r3)
+1:
+#endif /* CONFIG_WATCHDOG */
+
+#if defined(CONFIG_MASK_AER_AO)
+	/* Write the Arbiter Event Enable to mask Address Only traps. */
+	/* This prevents the dcbz instruction from being trapped when */
+	/* HID0_ABE Address Broadcast Enable is set and the MEMORY    */
+	/* COHERENCY bit is set in the WIMG bits, which is often      */
+	/* needed for PCI operation.                                  */
+	lwz	r4, 0x0808(r3)
+	rlwinm	r0, r4, 0, ~AER_AO
+	stw	r0, 0x0808(r3)
+#endif /* CONFIG_MASK_AER_AO */
+
+	/* Initialize the Hardware Implementation-dependent Registers */
+	/* HID0 also contains cache control			*/
+	/* - force invalidation of data and instruction caches  */
+	/*------------------------------------------------------*/
+
+	lis	r3, CONFIG_SYS_HID0_INIT@h
+	ori	r3, r3, (CONFIG_SYS_HID0_INIT | HID0_ICFI | HID0_DCFI)@l
+	SYNC
+	mtspr	HID0, r3
+
+	lis	r3, CONFIG_SYS_HID0_FINAL@h
+	ori	r3, r3, (CONFIG_SYS_HID0_FINAL & ~(HID0_ICFI | HID0_DCFI))@l
+	SYNC
+	mtspr	HID0, r3
+
+	lis	r3, CONFIG_SYS_HID2@h
+	ori	r3, r3, CONFIG_SYS_HID2@l
+	SYNC
+	mtspr	HID2, r3
+
+	/* Done!						*/
+	/*------------------------------*/
+	blr
+
+	/* setup_bats - set them up to some initial state */
+	.globl	setup_bats
+setup_bats:
+	addis	r0, r0, 0x0000
+
+	/* IBAT 0 */
+	addis	r4, r0, CONFIG_SYS_IBAT0L@h
+	ori	r4, r4, CONFIG_SYS_IBAT0L@l
+	addis	r3, r0, CONFIG_SYS_IBAT0U@h
+	ori	r3, r3, CONFIG_SYS_IBAT0U@l
+	mtspr	IBAT0L, r4
+	mtspr	IBAT0U, r3
+
+	/* DBAT 0 */
+	addis	r4, r0, CONFIG_SYS_DBAT0L@h
+	ori	r4, r4, CONFIG_SYS_DBAT0L@l
+	addis	r3, r0, CONFIG_SYS_DBAT0U@h
+	ori	r3, r3, CONFIG_SYS_DBAT0U@l
+	mtspr	DBAT0L, r4
+	mtspr	DBAT0U, r3
+
+	/* IBAT 1 */
+	addis	r4, r0, CONFIG_SYS_IBAT1L@h
+	ori	r4, r4, CONFIG_SYS_IBAT1L@l
+	addis	r3, r0, CONFIG_SYS_IBAT1U@h
+	ori	r3, r3, CONFIG_SYS_IBAT1U@l
+	mtspr	IBAT1L, r4
+	mtspr	IBAT1U, r3
+
+	/* DBAT 1 */
+	addis	r4, r0, CONFIG_SYS_DBAT1L@h
+	ori	r4, r4, CONFIG_SYS_DBAT1L@l
+	addis	r3, r0, CONFIG_SYS_DBAT1U@h
+	ori	r3, r3, CONFIG_SYS_DBAT1U@l
+	mtspr	DBAT1L, r4
+	mtspr	DBAT1U, r3
+
+	/* IBAT 2 */
+	addis	r4, r0, CONFIG_SYS_IBAT2L@h
+	ori	r4, r4, CONFIG_SYS_IBAT2L@l
+	addis	r3, r0, CONFIG_SYS_IBAT2U@h
+	ori	r3, r3, CONFIG_SYS_IBAT2U@l
+	mtspr	IBAT2L, r4
+	mtspr	IBAT2U, r3
+
+	/* DBAT 2 */
+	addis	r4, r0, CONFIG_SYS_DBAT2L@h
+	ori	r4, r4, CONFIG_SYS_DBAT2L@l
+	addis	r3, r0, CONFIG_SYS_DBAT2U@h
+	ori	r3, r3, CONFIG_SYS_DBAT2U@l
+	mtspr	DBAT2L, r4
+	mtspr	DBAT2U, r3
+
+	/* IBAT 3 */
+	addis	r4, r0, CONFIG_SYS_IBAT3L@h
+	ori	r4, r4, CONFIG_SYS_IBAT3L@l
+	addis	r3, r0, CONFIG_SYS_IBAT3U@h
+	ori	r3, r3, CONFIG_SYS_IBAT3U@l
+	mtspr	IBAT3L, r4
+	mtspr	IBAT3U, r3
+
+	/* DBAT 3 */
+	addis	r4, r0, CONFIG_SYS_DBAT3L@h
+	ori	r4, r4, CONFIG_SYS_DBAT3L@l
+	addis	r3, r0, CONFIG_SYS_DBAT3U@h
+	ori	r3, r3, CONFIG_SYS_DBAT3U@l
+	mtspr	DBAT3L, r4
+	mtspr	DBAT3U, r3
+
+#ifdef CONFIG_HIGH_BATS
+	/* IBAT 4 */
+	addis   r4, r0, CONFIG_SYS_IBAT4L@h
+	ori     r4, r4, CONFIG_SYS_IBAT4L@l
+	addis   r3, r0, CONFIG_SYS_IBAT4U@h
+	ori     r3, r3, CONFIG_SYS_IBAT4U@l
+	mtspr   IBAT4L, r4
+	mtspr   IBAT4U, r3
+
+	/* DBAT 4 */
+	addis   r4, r0, CONFIG_SYS_DBAT4L@h
+	ori     r4, r4, CONFIG_SYS_DBAT4L@l
+	addis   r3, r0, CONFIG_SYS_DBAT4U@h
+	ori     r3, r3, CONFIG_SYS_DBAT4U@l
+	mtspr   DBAT4L, r4
+	mtspr   DBAT4U, r3
+
+	/* IBAT 5 */
+	addis   r4, r0, CONFIG_SYS_IBAT5L@h
+	ori     r4, r4, CONFIG_SYS_IBAT5L@l
+	addis   r3, r0, CONFIG_SYS_IBAT5U@h
+	ori     r3, r3, CONFIG_SYS_IBAT5U@l
+	mtspr   IBAT5L, r4
+	mtspr   IBAT5U, r3
+
+	/* DBAT 5 */
+	addis   r4, r0, CONFIG_SYS_DBAT5L@h
+	ori     r4, r4, CONFIG_SYS_DBAT5L@l
+	addis   r3, r0, CONFIG_SYS_DBAT5U@h
+	ori     r3, r3, CONFIG_SYS_DBAT5U@l
+	mtspr   DBAT5L, r4
+	mtspr   DBAT5U, r3
+
+	/* IBAT 6 */
+	addis   r4, r0, CONFIG_SYS_IBAT6L@h
+	ori     r4, r4, CONFIG_SYS_IBAT6L@l
+	addis   r3, r0, CONFIG_SYS_IBAT6U@h
+	ori     r3, r3, CONFIG_SYS_IBAT6U@l
+	mtspr   IBAT6L, r4
+	mtspr   IBAT6U, r3
+
+	/* DBAT 6 */
+	addis   r4, r0, CONFIG_SYS_DBAT6L@h
+	ori     r4, r4, CONFIG_SYS_DBAT6L@l
+	addis   r3, r0, CONFIG_SYS_DBAT6U@h
+	ori     r3, r3, CONFIG_SYS_DBAT6U@l
+	mtspr   DBAT6L, r4
+	mtspr   DBAT6U, r3
+
+	/* IBAT 7 */
+	addis   r4, r0, CONFIG_SYS_IBAT7L@h
+	ori     r4, r4, CONFIG_SYS_IBAT7L@l
+	addis   r3, r0, CONFIG_SYS_IBAT7U@h
+	ori     r3, r3, CONFIG_SYS_IBAT7U@l
+	mtspr   IBAT7L, r4
+	mtspr   IBAT7U, r3
+
+	/* DBAT 7 */
+	addis   r4, r0, CONFIG_SYS_DBAT7L@h
+	ori     r4, r4, CONFIG_SYS_DBAT7L@l
+	addis   r3, r0, CONFIG_SYS_DBAT7U@h
+	ori     r3, r3, CONFIG_SYS_DBAT7U@l
+	mtspr   DBAT7L, r4
+	mtspr   DBAT7U, r3
+#endif
+
+	isync
+
+	/* invalidate all tlb's
+	 *
+	 * From the 603e User Manual: "The 603e provides the ability to
+	 * invalidate a TLB entry. The TLB Invalidate Entry (tlbie)
+	 * instruction invalidates the TLB entry indexed by the EA, and
+	 * operates on both the instruction and data TLBs simultaneously
+	 * invalidating four TLB entries (both sets in each TLB). The
+	 * index corresponds to bits 15-19 of the EA. To invalidate all
+	 * entries within both TLBs, 32 tlbie instructions should be
+	 * issued, incrementing this field by one each time."
+	 *
+	 * "Note that the tlbia instruction is not implemented on the
+	 * 603e."
+	 *
+	 * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000
+	 * incrementing by 0x1000 each time. The code below is sort of
+	 * based on code in "flush_tlbs" from arch/powerpc/kernel/head.S
+	 *
+	 */
+	lis	r3, 0
+	lis	r5, 2
+
+1:
+	tlbie	r3
+	addi	r3, r3, 0x1000
+	cmp	0, 0, r3, r5
+	blt	1b
+
+	blr
+
+/* Cache functions.
+ *
+ * Note: requires that all cache bits in
+ * HID0 are in the low half word.
+ */
+	.globl	icache_enable
+icache_enable:
+	mfspr	r3, HID0
+	ori	r3, r3, HID0_ICE
+	li	r4, HID0_ICFI|HID0_ILOCK
+	andc	r3, r3, r4
+	ori	r4, r3, HID0_ICFI
+	isync
+	mtspr	HID0, r4    /* sets enable and invalidate, clears lock */
+	isync
+	mtspr	HID0, r3	/* clears invalidate */
+	blr
+
+	.globl	icache_disable
+icache_disable:
+	mfspr	r3, HID0
+	lis	r4, 0
+	ori	r4, r4, HID0_ICE|HID0_ICFI|HID0_ILOCK
+	andc	r3, r3, r4
+	isync
+	mtspr	HID0, r3	/* clears invalidate, enable and lock */
+	blr
+
+	.globl	icache_status
+icache_status:
+	mfspr	r3, HID0
+	rlwinm	r3, r3, (31 - HID0_ICE_SHIFT + 1), 31, 31
+	blr
+
+	.globl	dcache_enable
+dcache_enable:
+	mfspr	r3, HID0
+	li	r5, HID0_DCFI|HID0_DLOCK
+	andc	r3, r3, r5
+	ori	r3, r3, HID0_DCE
+	sync
+	mtspr	HID0, r3		/* enable, no invalidate */
+	blr
+
+	.globl	dcache_disable
+dcache_disable:
+	mflr	r4
+	bl	flush_dcache		/* uses r3 and r5 */
+	mfspr	r3, HID0
+	li	r5, HID0_DCE|HID0_DLOCK
+	andc	r3, r3, r5
+	ori	r5, r3, HID0_DCFI
+	sync
+	mtspr	HID0, r5	/* sets invalidate, clears enable and lock */
+	sync
+	mtspr	HID0, r3	/* clears invalidate */
+	mtlr	r4
+	blr
+
+	.globl	dcache_status
+dcache_status:
+	mfspr	r3, HID0
+	rlwinm	r3, r3, (31 - HID0_DCE_SHIFT + 1), 31, 31
+	blr
+
+	.globl	flush_dcache
+flush_dcache:
+	lis	r3, 0
+	lis	r5, CONFIG_SYS_CACHELINE_SIZE
+1:	cmp	0, 1, r3, r5
+	bge	2f
+	lwz	r5, 0(r3)
+	lis	r5, CONFIG_SYS_CACHELINE_SIZE
+	addi	r3, r3, 0x4
+	b	1b
+2:	blr
+
+/*-------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+	.globl	relocate_code
+relocate_code:
+	mr	r1,  r3		/* Set new stack pointer	*/
+	mr	r9,  r4		/* Save copy of Global Data pointer */
+	mr	r10, r5		/* Save copy of Destination Address */
+
+	GET_GOT
+	mr	r3,  r5				/* Destination Address */
+	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address */
+	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
+	lwz	r5, GOT(__bss_start)
+	sub	r5, r5, r4
+	li	r6, CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size */
+
+	/*
+	 * Fix GOT pointer:
+	 *
+	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE)
+	 *		+ Destination Address
+	 *
+	 * Offset:
+	 */
+	sub	r15, r10, r4
+
+	/* First our own GOT */
+	add	r12, r12, r15
+	/* then the one used by the C code */
+	add	r30, r30, r15
+
+	/*
+	 * Now relocate code
+	 */
+
+	cmplw	cr1,r3,r4
+	addi	r0,r5,3
+	srwi.	r0,r0,2
+	beq	cr1,4f		/* In place copy is not necessary */
+	beq	7f		/* Protect against 0 count	  */
+	mtctr	r0
+	bge	cr1,2f
+	la	r8,-4(r4)
+	la	r7,-4(r3)
+
+	/* copy */
+1:	lwzu	r0,4(r8)
+	stwu	r0,4(r7)
+	bdnz	1b
+
+	addi	r0,r5,3
+	srwi.	r0,r0,2
+	mtctr	r0
+	la	r8,-4(r4)
+	la	r7,-4(r3)
+
+	/* and compare */
+20:	lwzu	r20,4(r8)
+	lwzu	r21,4(r7)
+	xor. r22, r20, r21
+	bne  30f
+	bdnz	20b
+	b 4f
+
+	/* compare failed */
+30:	li r3, 0
+	blr
+
+2:	slwi	r0,r0,2 /* re copy in reverse order ... y do we needed it? */
+	add	r8,r4,r0
+	add	r7,r3,r0
+3:	lwzu	r0,-4(r8)
+	stwu	r0,-4(r7)
+	bdnz	3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:	cmpwi	r6,0
+	add	r5,r3,r5
+	beq	7f		/* Always flush prefetch queue in any case */
+	subi	r0,r6,1
+	andc	r3,r3,r0
+	mr	r4,r3
+5:	dcbst	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	5b
+	sync			/* Wait for all dcbst to complete on bus */
+	mr	r4,r3
+6:	icbi	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	6b
+7:	sync			/* Wait for all icbi to complete on bus	*/
+	isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+	mtlr	r0
+	blr
+
+in_ram:
+
+	/*
+	 * Relocation Function, r12 point to got2+0x8000
+	 *
+	 * Adjust got2 pointers, no need to check for 0, this code
+	 * already puts a few entries in the table.
+	 */
+	li	r0,__got2_entries@sectoff@l
+	la	r3,GOT(_GOT2_TABLE_)
+	lwz	r11,GOT(_GOT2_TABLE_)
+	mtctr	r0
+	sub	r11,r3,r11
+	addi	r3,r3,-4
+1:	lwzu	r0,4(r3)
+	cmpwi	r0,0
+	beq-	2f
+	add	r0,r0,r11
+	stw	r0,0(r3)
+2:	bdnz	1b
+
+#ifndef CONFIG_NAND_SPL
+	/*
+	 * Now adjust the fixups and the pointers to the fixups
+	 * in case we need to move ourselves again.
+	 */
+	li	r0,__fixup_entries@sectoff@l
+	lwz	r3,GOT(_FIXUP_TABLE_)
+	cmpwi	r0,0
+	mtctr	r0
+	addi	r3,r3,-4
+	beq	4f
+3:	lwzu	r4,4(r3)
+	lwzux	r0,r4,r11
+	add	r0,r0,r11
+	stw	r10,0(r3)
+	stw	r0,0(r4)
+	bdnz	3b
+4:
+#endif
+
+clear_bss:
+	/*
+	 * Now clear BSS segment
+	 */
+	lwz	r3,GOT(__bss_start)
+#if defined(CONFIG_HYMOD)
+	/*
+	 * For HYMOD - the environment is the very last item in flash.
+	 * The real .bss stops just before environment starts, so only
+	 * clear up to that point.
+	 *
+	 * taken from mods for FADS board
+	 */
+	lwz	r4,GOT(environment)
+#else
+	lwz	r4,GOT(_end)
+#endif
+
+	cmplw	0, r3, r4
+	beq	6f
+
+	li	r0, 0
+5:
+	stw	r0, 0(r3)
+	addi	r3, r3, 4
+	cmplw	0, r3, r4
+	bne	5b
+6:
+
+	mr	r3, r9		/* Global Data pointer		*/
+	mr	r4, r10		/* Destination Address		*/
+	bl	board_init_r
+
+#ifndef CONFIG_NAND_SPL
+	/*
+	 * Copy exception vector code to low memory
+	 *
+	 * r3: dest_addr
+	 * r7: source address, r8: end address, r9: target address
+	 */
+	.globl	trap_init
+trap_init:
+	mflr	r4		/* save link register */
+	GET_GOT
+	lwz	r7, GOT(_start)
+	lwz	r8, GOT(_end_of_vectors)
+
+	li	r9, 0x100	/* reset vector always at 0x100 */
+
+	cmplw	0, r7, r8
+	bgelr			/* return if r7>=r8 - just in case */
+1:
+	lwz	r0, 0(r7)
+	stw	r0, 0(r9)
+	addi	r7, r7, 4
+	addi	r9, r9, 4
+	cmplw	0, r7, r8
+	bne	1b
+
+	/*
+	 * relocate `hdlr' and `int_return' entries
+	 */
+	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+	li	r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector */
+	cmplw	0, r7, r8
+	blt	2b
+
+	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector */
+	cmplw	0, r7, r8
+	blt	3b
+
+	li	r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector */
+	cmplw	0, r7, r8
+	blt	4b
+
+	mfmsr	r3			/* now that the vectors have */
+	lis	r7, MSR_IP@h		/* relocated into low memory */
+	ori	r7, r7, MSR_IP@l	/* MSR[IP] can be turned off */
+	andc	r3, r3, r7		/* (if it was on) */
+	SYNC				/* Some chip revs need this... */
+	mtmsr	r3
+	SYNC
+
+	mtlr	r4			/* restore link register    */
+	blr
+
+#endif /* !CONFIG_NAND_SPL */
+
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+lock_ram_in_cache:
+	/* Allocate Initial RAM in data cache.
+	 */
+	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
+	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
+	li	r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \
+		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
+	mtctr	r4
+1:
+	dcbz	r0, r3
+	addi	r3, r3, 32
+	bdnz	1b
+
+	/* Lock the data cache */
+	mfspr	r0, HID0
+	ori	r0, r0, HID0_DLOCK
+	sync
+	mtspr	HID0, r0
+	sync
+	blr
+
+#ifndef CONFIG_NAND_SPL
+.globl unlock_ram_in_cache
+unlock_ram_in_cache:
+	/* invalidate the INIT_RAM section */
+	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
+	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
+	li	r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \
+		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
+	mtctr	r4
+1:	icbi	r0, r3
+	dcbi	r0, r3
+	addi	r3, r3, 32
+	bdnz	1b
+	sync			/* Wait for all icbi to complete on bus	*/
+	isync
+
+	/* Unlock the data cache and invalidate it */
+	mfspr   r3, HID0
+	li	r5, HID0_DLOCK|HID0_DCFI
+	andc	r3, r3, r5		/* no invalidate, unlock */
+	ori	r5, r3, HID0_DCFI	/* invalidate, unlock */
+	sync
+	mtspr	HID0, r5		/* invalidate, unlock */
+	sync
+	mtspr	HID0, r3		/* no invalidate, unlock */
+	blr
+#endif /* !CONFIG_NAND_SPL */
+#endif /* CONFIG_SYS_INIT_RAM_LOCK */
+
+#ifdef CONFIG_SYS_FLASHBOOT
+map_flash_by_law1:
+	/* When booting from ROM (Flash or EPROM), clear the  */
+	/* Address Mask in OR0 so ROM appears everywhere      */
+	/*----------------------------------------------------*/
+	lis	r3, (CONFIG_SYS_IMMR)@h  /* r3 <= CONFIG_SYS_IMMR    */
+	lwz	r4, OR0@l(r3)
+	li	r5, 0x7fff        /* r5 <= 0x00007FFFF */
+	and	r4, r4, r5
+	stw	r4, OR0@l(r3)     /* OR0 <= OR0 & 0x00007FFFF */
+
+	/* As MPC8349E User's Manual presented, when RCW[BMS] is set to 0,
+	 * system will boot from 0x0000_0100, and the LBLAWBAR0[BASE_ADDR]
+	 * reset value is 0x00000; when RCW[BMS] is set to 1, system will boot
+	 * from 0xFFF0_0100, and the LBLAWBAR0[BASE_ADDR] reset value is
+	 * 0xFF800.  From the hard resetting to here, the processor fetched and
+	 * executed the instructions one by one.  There is not absolutely
+	 * jumping happened.  Laterly, the u-boot code has to do an absolutely
+	 * jumping to tell the CPU instruction fetching component what the
+	 * u-boot TEXT base address is.  Because the TEXT base resides in the
+	 * boot ROM memory space, to garantee the code can run smoothly after
+	 * that jumping, we must map in the entire boot ROM by Local Access
+	 * Window.  Sometimes, we desire an non-0x00000 or non-0xFF800 starting
+	 * address for boot ROM, such as 0xFE000000.  In this case, the default
+	 * LBIU Local Access Widow 0 will not cover this memory space.  So, we
+	 * need another window to map in it.
+	 */
+	lis r4, (CONFIG_SYS_FLASH_BASE)@h
+	ori r4, r4, (CONFIG_SYS_FLASH_BASE)@l
+	stw r4, LBLAWBAR1(r3) /* LBLAWBAR1 <= CONFIG_SYS_FLASH_BASE */
+
+	/* Store 0x80000012 + log2(CONFIG_SYS_FLASH_SIZE) into LBLAWAR1 */
+	lis r4, (0x80000012)@h
+	ori r4, r4, (0x80000012)@l
+	li r5, CONFIG_SYS_FLASH_SIZE
+1:	srawi. r5, r5, 1	/* r5 = r5 >> 1 */
+	addi r4, r4, 1
+	bne 1b
+
+	stw r4, LBLAWAR1(r3) /* LBLAWAR1 <= 8MB Flash Size */
+	blr
+
+	/* Though all the LBIU Local Access Windows and LBC Banks will be
+	 * initialized in the C code, we'd better configure boot ROM's
+	 * window 0 and bank 0 correctly at here.
+	 */
+remap_flash_by_law0:
+	/* Initialize the BR0 with the boot ROM starting address. */
+	lwz r4, BR0(r3)
+	li  r5, 0x7FFF
+	and r4, r4, r5
+	lis r5, (CONFIG_SYS_FLASH_BASE & 0xFFFF8000)@h
+	ori r5, r5, (CONFIG_SYS_FLASH_BASE & 0xFFFF8000)@l
+	or  r5, r5, r4
+	stw r5, BR0(r3) /* r5 <= (CONFIG_SYS_FLASH_BASE & 0xFFFF8000) | (BR0 & 0x00007FFF) */
+
+	lwz r4, OR0(r3)
+	lis r5, ~((CONFIG_SYS_FLASH_SIZE << 4) - 1)
+	or r4, r4, r5
+	stw r4, OR0(r3)
+
+	lis r4, (CONFIG_SYS_FLASH_BASE)@h
+	ori r4, r4, (CONFIG_SYS_FLASH_BASE)@l
+	stw r4, LBLAWBAR0(r3) /* LBLAWBAR0 <= CONFIG_SYS_FLASH_BASE */
+
+	/* Store 0x80000012 + log2(CONFIG_SYS_FLASH_SIZE) into LBLAWAR0 */
+	lis r4, (0x80000012)@h
+	ori r4, r4, (0x80000012)@l
+	li r5, CONFIG_SYS_FLASH_SIZE
+1:	srawi. r5, r5, 1 /* r5 = r5 >> 1 */
+	addi r4, r4, 1
+	bne 1b
+	stw r4, LBLAWAR0(r3) /* LBLAWAR0 <= Flash Size */
+
+
+	xor r4, r4, r4
+	stw r4, LBLAWBAR1(r3)
+	stw r4, LBLAWAR1(r3) /* Off LBIU LAW1 */
+	blr
+#endif /* CONFIG_SYS_FLASHBOOT */
diff --git a/arch/powerpc/cpu/mpc83xx/traps.c b/arch/powerpc/cpu/mpc83xx/traps.c
new file mode 100644
index 0000000..9d71b8b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/traps.c
@@ -0,0 +1,266 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware
+ * exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+#include <asm/mpc8349_pci.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+#define END_OF_MEM	(gd->bd->bi_memstart + gd->bd->bi_memsize)
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace(unsigned long *sp)
+{
+	int cnt = 0;
+	unsigned long i;
+
+	puts ("Call backtrace: ");
+	while (sp) {
+		if ((uint)sp > END_OF_MEM)
+			break;
+
+		i = sp[1];
+		if (cnt++ % 7 == 0)
+			putc ('\n');
+		printf("%08lX ", i);
+		if (cnt > 32) break;
+		sp = (unsigned long *)*sp;
+	}
+	putc ('\n');
+}
+
+void show_regs(struct pt_regs * regs)
+{
+	int i;
+
+	printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+	       regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+	printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+	       regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+	       regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+	       regs->msr&MSR_IR ? 1 : 0,
+	       regs->msr&MSR_DR ? 1 : 0);
+
+	putc ('\n');
+	for (i = 0;  i < 32;  i++) {
+		if ((i % 8) == 0) {
+			printf("GPR%02d: ", i);
+		}
+
+		printf("%08lX ", regs->gpr[i]);
+		if ((i % 8) == 7) {
+			putc ('\n');
+		}
+	}
+}
+
+
+void
+_exception(int signr, struct pt_regs *regs)
+{
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+#ifdef CONFIG_PCI
+void dump_pci (void)
+{
+/*
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	printf ("PCI: err status %x err mask %x err ctrl %x\n",
+		le32_to_cpu (immap->im_pci.pci_esr),
+		le32_to_cpu (immap->im_pci.pci_emr),
+		le32_to_cpu (immap->im_pci.pci_ecr));
+	printf ("     error address %x error data %x ctrl %x\n",
+		le32_to_cpu (immap->im_pci.pci_eacr),
+		le32_to_cpu (immap->im_pci.pci_edcr),
+		le32_to_cpu (immap->im_pci.pci_eccr));
+*/
+}
+#endif
+
+void
+MachineCheckException(struct pt_regs *regs)
+{
+	unsigned long fixup;
+
+	/* Probing PCI using config cycles cause this exception
+	 * when a device is not present.  Catch it and return to
+	 * the PCI exception handler.
+	 */
+#ifdef CONFIG_PCI
+#if 0
+	volatile immap_t *immap  = (immap_t *)CONFIG_SYS_IMMR;
+#ifdef DEBUG
+	dump_pci();
+#endif
+	/* clear the error in the error status register */
+	if(immap->im_pci.pci_esr & cpu_to_le32(PCI_ERROR_PCI_NO_RSP)) {
+		immap->im_pci.pci_esr = cpu_to_le32(PCI_ERROR_PCI_NO_RSP);
+		return;
+	}
+#endif
+#endif /* CONFIG_PCI */
+	if ((fixup = search_exception_table(regs->nip)) != 0) {
+		regs->nip = fixup;
+		return;
+	}
+
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	puts ("Machine check in kernel mode.\n"
+		"Caused by (from msr): ");
+	printf("regs %p ",regs);
+	switch( regs->msr & 0x000F0000) {
+	case (0x80000000>>12):
+		puts ("Machine check signal - probably due to mm fault\n"
+			"with mmu off\n");
+		break;
+	case (0x80000000>>13):
+		puts ("Transfer error ack signal\n");
+		break;
+	case (0x80000000>>14):
+		puts ("Data parity signal\n");
+		break;
+	case (0x80000000>>15):
+		puts ("Address parity signal\n");
+		break;
+	default:
+		puts ("Unknown values in msr\n");
+	}
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+#ifdef CONFIG_PCI
+	dump_pci();
+#endif
+	panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Program Check Exception");
+}
+
+void
+SoftEmuException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Software Emulation Exception");
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+	       regs->nip, regs->msr, regs->trap);
+	_exception(0, regs);
+}
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+void
+DebugException(struct pt_regs *regs)
+{
+	printf("Debugger trap at @ %lx\n", regs->nip );
+	show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+	do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading.  If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+#if 0
+	int	retval;
+
+	__asm__ __volatile__(			\
+		"1:	lwz %0,0(%1)\n"		\
+		"	eieio\n"		\
+		"	li %0,0\n"		\
+		"2:\n"				\
+		".section .fixup,\"ax\"\n"	\
+		"3:	li %0,-1\n"		\
+		"	b 2b\n"			\
+		".section __ex_table,\"a\"\n"	\
+		"	.align 2\n"		\
+		"	.long 1b,3b\n"		\
+		".text"				\
+		: "=r" (retval) : "r"(addr));
+
+	return (retval);
+#endif
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc83xx/u-boot.lds b/arch/powerpc/cpu/mpc83xx/u-boot.lds
new file mode 100644
index 0000000..0b74a13
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/u-boot.lds
@@ -0,0 +1,121 @@
+/*
+ * (C) Copyright 2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text)	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data)	}
+  .rel.rodata    : { *(.rel.rodata)	}
+  .rela.rodata   : { *(.rela.rodata)	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	}
+  .plt : { *(.plt) }
+  .text      :
+  {
+    arch/powerpc/cpu/mpc83xx/start.o	(.text)
+    *(.text)
+    *(.got1)
+    . = ALIGN(16);
+    *(.eh_frame)
+    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x0FFF) & 0xFFFFF000;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+  __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  . = .;
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+
+  . = .;
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(4096);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss (NOLOAD)       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+   . = ALIGN(4);
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}
+ENTRY(_start)
diff --git a/arch/powerpc/cpu/mpc85xx/Makefile b/arch/powerpc/cpu/mpc85xx/Makefile
new file mode 100644
index 0000000..f064fee
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/Makefile
@@ -0,0 +1,95 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2002,2003 Motorola Inc.
+# Xianghua Xiao,X.Xiao@motorola.com
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(CPU).a
+
+START	= start.o resetvec.o
+SOBJS-$(CONFIG_MP)	+= release.o
+SOBJS	= $(SOBJS-y)
+
+COBJS-$(CONFIG_CPM2)	+= commproc.o
+
+# supports ddr1
+COBJS-$(CONFIG_MPC8540) += ddr-gen1.o
+COBJS-$(CONFIG_MPC8560) += ddr-gen1.o
+COBJS-$(CONFIG_MPC8541) += ddr-gen1.o
+COBJS-$(CONFIG_MPC8555) += ddr-gen1.o
+
+# supports ddr1/2
+COBJS-$(CONFIG_MPC8548) += ddr-gen2.o
+COBJS-$(CONFIG_MPC8568) += ddr-gen2.o
+COBJS-$(CONFIG_MPC8544) += ddr-gen2.o
+
+# supports ddr1/2/3
+COBJS-$(CONFIG_MPC8572) += ddr-gen3.o
+COBJS-$(CONFIG_MPC8536) += ddr-gen3.o
+COBJS-$(CONFIG_MPC8569)	+= ddr-gen3.o
+COBJS-$(CONFIG_P1011)	+= ddr-gen3.o
+COBJS-$(CONFIG_P1012)	+= ddr-gen3.o
+COBJS-$(CONFIG_P1013)	+= ddr-gen3.o
+COBJS-$(CONFIG_P1020)	+= ddr-gen3.o
+COBJS-$(CONFIG_P1021)	+= ddr-gen3.o
+COBJS-$(CONFIG_P1022)	+= ddr-gen3.o
+COBJS-$(CONFIG_P2010)	+= ddr-gen3.o
+COBJS-$(CONFIG_P2020)	+= ddr-gen3.o
+COBJS-$(CONFIG_PPC_P4080)	+= ddr-gen3.o
+
+COBJS-$(CONFIG_CPM2)	+= ether_fcc.o
+COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
+COBJS-$(CONFIG_MP)	+= mp.o
+COBJS-$(CONFIG_MPC8536) += mpc8536_serdes.o
+COBJS-$(CONFIG_PCI)	+= pci.o
+COBJS-$(CONFIG_QE)	+= qe_io.o
+COBJS-$(CONFIG_CPM2)	+= serial_scc.o
+
+COBJS	= $(COBJS-y)
+COBJS	+= cpu.o
+COBJS	+= cpu_init.o
+COBJS	+= cpu_init_early.o
+COBJS	+= interrupts.o
+COBJS	+= speed.o
+COBJS	+= tlb.o
+COBJS	+= traps.o
+
+SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc85xx/commproc.c b/arch/powerpc/cpu/mpc85xx/commproc.c
new file mode 100644
index 0000000..f0fd1cb
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/commproc.c
@@ -0,0 +1,205 @@
+/*
+ * Adapted for Motorola MPC8560 chips
+ * Xianghua Xiao <x.xiao@motorola.com>
+ *
+ * This file is based on "arch/powerpc/8260_io/commproc.c" - here is it's
+ * copyright notice:
+ *
+ * General Purpose functions for the global management of the
+ * 8220 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
+ *	2.3.99 Updates
+ * Copyright (c) 2003 Motorola,Inc.
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space.  The allocator for that is here.  When the communication
+ * process is reset, we reclaim the memory available.  There is
+ * currently no deallocator for this memory.
+ */
+#include <common.h>
+#include <asm/cpm_85xx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * because we have stack and init data in dual port ram
+ * we must reduce the size
+ */
+#undef	CPM_DATAONLY_SIZE
+#define CPM_DATAONLY_SIZE	((uint)(8 * 1024) - CPM_DATAONLY_BASE)
+
+void
+m8560_cpm_reset(void)
+{
+	volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+	volatile ulong count;
+
+	gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+	/* Reclaim the DP memory for our use.
+	*/
+	gd->dp_alloc_base = CPM_DATAONLY_BASE;
+	gd->dp_alloc_top = gd->dp_alloc_base + CPM_DATAONLY_SIZE;
+
+	/*
+	 * Reset CPM
+	 */
+	cpm->im_cpm_cp.cpcr = CPM_CR_RST;
+	count = 0;
+	do {			/* Spin until command processed		*/
+		__asm__ __volatile__ ("eieio");
+	} while ((cpm->im_cpm_cp.cpcr & CPM_CR_FLG) && ++count < 1000000);
+}
+
+/* Allocate some memory from the dual ported ram.
+ * To help protocols with object alignment restrictions, we do that
+ * if they ask.
+ */
+uint
+m8560_cpm_dpalloc(uint size, uint align)
+{
+	volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+	uint	retloc;
+	uint	align_mask, off;
+	uint	savebase;
+
+	align_mask = align - 1;
+	savebase = gd->dp_alloc_base;
+
+	if ((off = (gd->dp_alloc_base & align_mask)) != 0)
+		gd->dp_alloc_base += (align - off);
+
+	if ((off = size & align_mask) != 0)
+		size += align - off;
+
+	if ((gd->dp_alloc_base + size) >= gd->dp_alloc_top) {
+		gd->dp_alloc_base = savebase;
+		panic("m8560_cpm_dpalloc: ran out of dual port ram!");
+	}
+
+	retloc = gd->dp_alloc_base;
+	gd->dp_alloc_base += size;
+
+	memset((void *)&(cpm->im_dprambase[retloc]), 0, size);
+
+	return(retloc);
+}
+
+/* We also own one page of host buffer space for the allocation of
+ * UART "fifos" and the like.
+ */
+uint
+m8560_cpm_hostalloc(uint size, uint align)
+{
+	/* the host might not even have RAM yet - just use dual port RAM */
+	return (m8560_cpm_dpalloc(size, align));
+}
+
+/* Set a baud rate generator.  This needs lots of work.  There are
+ * eight BRGs, which can be connected to the CPM channels or output
+ * as clocks.  The BRGs are in two different block of internal
+ * memory mapped space.
+ * The baud rate clock is the system clock divided by something.
+ * It was set up long ago during the initial boot phase and is
+ * is given to us.
+ * Baud rate clocks are zero-based in the driver code (as that maps
+ * to port numbers).  Documentation uses 1-based numbering.
+ */
+#define BRG_INT_CLK	gd->brg_clk
+#define BRG_UART_CLK	((BRG_INT_CLK + 15) / 16)
+
+/* This function is used by UARTS, or anything else that uses a 16x
+ * oversampled clock.
+ */
+void
+m8560_cpm_setbrg(uint brg, uint rate)
+{
+	volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+	volatile uint	*bp;
+
+	/* This is good enough to get SMCs running.....
+	*/
+	if (brg < 4) {
+		bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
+	}
+	else {
+		bp = (uint *)&(cpm->im_cpm_brg2.brgc5);
+		brg -= 4;
+	}
+	bp += brg;
+	*bp = (((((BRG_UART_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
+}
+
+/* This function is used to set high speed synchronous baud rate
+ * clocks.
+ */
+void
+m8560_cpm_fastbrg(uint brg, uint rate, int div16)
+{
+	volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+	volatile uint	*bp;
+
+	/* This is good enough to get SMCs running.....
+	*/
+	if (brg < 4) {
+		bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
+	}
+	else {
+		bp = (uint *)&(cpm->im_cpm_brg2.brgc5);
+		brg -= 4;
+	}
+	bp += brg;
+	*bp = (((((BRG_INT_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
+	if (div16)
+		*bp |= CPM_BRG_DIV16;
+}
+
+/* This function is used to set baud rate generators using an external
+ * clock source and 16x oversampling.
+ */
+
+void
+m8560_cpm_extcbrg(uint brg, uint rate, uint extclk, int pinsel)
+{
+	volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+	volatile uint	*bp;
+
+	if (brg < 4) {
+		bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
+	}
+	else {
+		bp = (uint *)&(cpm->im_cpm_brg2.brgc5);
+		brg -= 4;
+	}
+	bp += brg;
+	*bp = ((((((extclk/16)+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
+	if (pinsel == 0)
+		*bp |= CPM_BRG_EXTC_CLK3_9;
+	else
+		*bp |= CPM_BRG_EXTC_CLK5_15;
+}
+
+#ifdef CONFIG_POST
+
+void post_word_store (ulong a)
+{
+	volatile ulong *save_addr =
+		(volatile ulong *)(CONFIG_SYS_IMMR + CPM_POST_WORD_ADDR);
+
+	*save_addr = a;
+}
+
+ulong post_word_load (void)
+{
+	volatile ulong *save_addr =
+		(volatile ulong *)(CONFIG_SYS_IMMR + CPM_POST_WORD_ADDR);
+
+	return *save_addr;
+}
+
+#endif	/* CONFIG_POST */
diff --git a/arch/powerpc/cpu/mpc85xx/config.mk b/arch/powerpc/cpu/mpc85xx/config.mk
new file mode 100644
index 0000000..f07d920
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/config.mk
@@ -0,0 +1,35 @@
+#
+# (C) Copyright 2002,2003 Motorola Inc.
+# Xianghua Xiao, X.Xiao@motorola.com
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -fPIC -meabi
+
+PLATFORM_CPPFLAGS += -ffixed-r2 -Wa,-me500 -msoft-float -mno-string
+
+# -mspe=yes is needed to have -mno-spe accepted by a buggy GCC;
+# see "[PATCH,rs6000] make -mno-spe work as expected" on
+# http://gcc.gnu.org/ml/gcc-patches/2008-04/msg00311.html
+PLATFORM_CPPFLAGS +=$(call cc-option,-mspe=yes)
+PLATFORM_CPPFLAGS +=$(call cc-option,-mno-spe)
+
+# Use default linker script.  Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/arch/powerpc/cpu/mpc85xx/u-boot.lds
diff --git a/arch/powerpc/cpu/mpc85xx/cpu.c b/arch/powerpc/cpu/mpc85xx/cpu.c
new file mode 100644
index 0000000..0cc6e03
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/cpu.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2004,2007-2009 Freescale Semiconductor, Inc.
+ * (C) Copyright 2002, 2003 Motorola Inc.
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <fsl_esdhc.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int checkcpu (void)
+{
+	sys_info_t sysinfo;
+	uint pvr, svr;
+	uint fam;
+	uint ver;
+	uint major, minor;
+	struct cpu_type *cpu;
+	char buf1[32], buf2[32];
+#ifdef CONFIG_DDR_CLK_FREQ
+	volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+#ifdef CONFIG_FSL_CORENET
+	u32 ddr_sync = ((gur->rcwsr[5]) & FSL_CORENET_RCWSR5_DDR_SYNC)
+		>> FSL_CORENET_RCWSR5_DDR_SYNC_SHIFT;
+#else
+	u32 ddr_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_DDR_RATIO)
+		>> MPC85xx_PORPLLSR_DDR_RATIO_SHIFT;
+#endif
+#else
+#ifdef CONFIG_FSL_CORENET
+	u32 ddr_sync = 0;
+#else
+	u32 ddr_ratio = 0;
+#endif
+#endif /* CONFIG_DDR_CLK_FREQ */
+	int i;
+
+	svr = get_svr();
+	major = SVR_MAJ(svr);
+#ifdef CONFIG_MPC8536
+	major &= 0x7; /* the msb of this nibble is a mfg code */
+#endif
+	minor = SVR_MIN(svr);
+
+	if (cpu_numcores() > 1) {
+#ifndef CONFIG_MP
+		puts("Unicore software on multiprocessor system!!\n"
+		     "To enable mutlticore build define CONFIG_MP\n");
+#endif
+		volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
+		printf("CPU%d:  ", pic->whoami);
+	} else {
+		puts("CPU:   ");
+	}
+
+	cpu = gd->cpu;
+
+	puts(cpu->name);
+	if (IS_E_PROCESSOR(svr))
+		puts("E");
+
+	printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr);
+
+	pvr = get_pvr();
+	fam = PVR_FAM(pvr);
+	ver = PVR_VER(pvr);
+	major = PVR_MAJ(pvr);
+	minor = PVR_MIN(pvr);
+
+	printf("Core:  ");
+	switch (fam) {
+	case PVR_FAM(PVR_85xx):
+	    puts("E500");
+	    break;
+	default:
+	    puts("Unknown");
+	    break;
+	}
+
+	if (PVR_MEM(pvr) == 0x03)
+		puts("MC");
+
+	printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr);
+
+	get_sys_info(&sysinfo);
+
+	puts("Clock Configuration:");
+	for (i = 0; i < cpu_numcores(); i++) {
+		if (!(i & 3))
+			printf ("\n       ");
+		printf("CPU%d:%-4s MHz, ",
+				i,strmhz(buf1, sysinfo.freqProcessor[i]));
+	}
+	printf("\n       CCB:%-4s MHz,\n", strmhz(buf1, sysinfo.freqSystemBus));
+
+#ifdef CONFIG_FSL_CORENET
+	if (ddr_sync == 1) {
+		printf("       DDR:%-4s MHz (%s MT/s data rate) "
+			"(Synchronous), ",
+			strmhz(buf1, sysinfo.freqDDRBus/2),
+			strmhz(buf2, sysinfo.freqDDRBus));
+	} else {
+		printf("       DDR:%-4s MHz (%s MT/s data rate) "
+			"(Asynchronous), ",
+			strmhz(buf1, sysinfo.freqDDRBus/2),
+			strmhz(buf2, sysinfo.freqDDRBus));
+	}
+#else
+	switch (ddr_ratio) {
+	case 0x0:
+		printf("       DDR:%-4s MHz (%s MT/s data rate), ",
+			strmhz(buf1, sysinfo.freqDDRBus/2),
+			strmhz(buf2, sysinfo.freqDDRBus));
+		break;
+	case 0x7:
+		printf("       DDR:%-4s MHz (%s MT/s data rate) "
+			"(Synchronous), ",
+			strmhz(buf1, sysinfo.freqDDRBus/2),
+			strmhz(buf2, sysinfo.freqDDRBus));
+		break;
+	default:
+		printf("       DDR:%-4s MHz (%s MT/s data rate) "
+			"(Asynchronous), ",
+			strmhz(buf1, sysinfo.freqDDRBus/2),
+			strmhz(buf2, sysinfo.freqDDRBus));
+		break;
+	}
+#endif
+
+	if (sysinfo.freqLocalBus > LCRR_CLKDIV) {
+		printf("LBC:%-4s MHz\n", strmhz(buf1, sysinfo.freqLocalBus));
+	} else {
+		printf("LBC: unknown (LCRR[CLKDIV] = 0x%02lx)\n",
+		       sysinfo.freqLocalBus);
+	}
+
+#ifdef CONFIG_CPM2
+	printf("CPM:   %s MHz\n", strmhz(buf1, sysinfo.freqSystemBus));
+#endif
+
+#ifdef CONFIG_QE
+	printf("       QE:%-4s MHz\n", strmhz(buf1, sysinfo.freqQE));
+#endif
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+	for (i = 0; i < CONFIG_SYS_NUM_FMAN; i++) {
+		printf("       FMAN%d: %s MHz\n", i,
+			strmhz(buf1, sysinfo.freqFMan[i]));
+	}
+#endif
+
+#ifdef CONFIG_SYS_DPAA_PME
+	printf("       PME:   %s MHz\n", strmhz(buf1, sysinfo.freqPME));
+#endif
+
+	puts("L1:    D-cache 32 kB enabled\n       I-cache 32 kB enabled\n");
+
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+/* Everything after the first generation of PQ3 parts has RSTCR */
+#if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
+    defined(CONFIG_MPC8555) || defined(CONFIG_MPC8560)
+	unsigned long val, msr;
+
+	/*
+	 * Initiate hard reset in debug control register DBCR0
+	 * Make sure MSR[DE] = 1.  This only resets the core.
+	 */
+	msr = mfmsr ();
+	msr |= MSR_DE;
+	mtmsr (msr);
+
+	val = mfspr(DBCR0);
+	val |= 0x70000000;
+	mtspr(DBCR0,val);
+#else
+	volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	out_be32(&gur->rstcr, 0x2);	/* HRESET_REQ */
+	udelay(100);
+#endif
+
+	return 1;
+}
+
+
+/*
+ * Get timebase clock frequency
+ */
+unsigned long get_tbclk (void)
+{
+#ifdef CONFIG_FSL_CORENET
+	return (gd->bus_clk + 8) / 16;
+#else
+	return (gd->bus_clk + 4UL)/8UL;
+#endif
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void
+watchdog_reset(void)
+{
+	int re_enable = disable_interrupts();
+	reset_85xx_watchdog();
+	if (re_enable) enable_interrupts();
+}
+
+void
+reset_85xx_watchdog(void)
+{
+	/*
+	 * Clear TSR(WIS) bit by writing 1
+	 */
+	unsigned long val;
+	val = mfspr(SPRN_TSR);
+	val |= TSR_WIS;
+	mtspr(SPRN_TSR, val);
+}
+#endif	/* CONFIG_WATCHDOG */
+
+/*
+ * Configures a UPM. The function requires the respective MxMR to be set
+ * before calling this function. "size" is the number or entries, not a sizeof.
+ */
+void upmconfig (uint upm, uint * table, uint size)
+{
+	int i, mdr, mad, old_mad = 0;
+	volatile u32 *mxmr;
+	volatile ccsr_lbc_t *lbc = (void *)(CONFIG_SYS_MPC85xx_LBC_ADDR);
+	volatile u32 *brp,*orp;
+	volatile u8* dummy = NULL;
+	int upmmask;
+
+	switch (upm) {
+	case UPMA:
+		mxmr = &lbc->mamr;
+		upmmask = BR_MS_UPMA;
+		break;
+	case UPMB:
+		mxmr = &lbc->mbmr;
+		upmmask = BR_MS_UPMB;
+		break;
+	case UPMC:
+		mxmr = &lbc->mcmr;
+		upmmask = BR_MS_UPMC;
+		break;
+	default:
+		printf("%s: Bad UPM index %d to configure\n", __FUNCTION__, upm);
+		hang();
+	}
+
+	/* Find the address for the dummy write transaction */
+	for (brp = &lbc->br0, orp = &lbc->or0, i = 0; i < 8;
+		 i++, brp += 2, orp += 2) {
+
+		/* Look for a valid BR with selected UPM */
+		if ((in_be32(brp) & (BR_V | BR_MSEL)) == (BR_V | upmmask)) {
+			dummy = (volatile u8*)(in_be32(brp) & BR_BA);
+			break;
+		}
+	}
+
+	if (i == 8) {
+		printf("Error: %s() could not find matching BR\n", __FUNCTION__);
+		hang();
+	}
+
+	for (i = 0; i < size; i++) {
+		/* 1 */
+		out_be32(mxmr,  (in_be32(mxmr) & 0x4fffffc0) | MxMR_OP_WARR | i);
+		/* 2 */
+		out_be32(&lbc->mdr, table[i]);
+		/* 3 */
+		mdr = in_be32(&lbc->mdr);
+		/* 4 */
+		*(volatile u8 *)dummy = 0;
+		/* 5 */
+		do {
+			mad = in_be32(mxmr) & MxMR_MAD_MSK;
+		} while (mad <= old_mad && !(!mad && i == (size-1)));
+		old_mad = mad;
+	}
+	out_be32(mxmr, (in_be32(mxmr) & 0x4fffffc0) | MxMR_OP_NORM);
+}
+
+/*
+ * Initializes on-chip MMC controllers.
+ * to override, implement board_mmc_init()
+ */
+int cpu_mmc_init(bd_t *bis)
+{
+#ifdef CONFIG_FSL_ESDHC
+	return fsl_esdhc_mmc_init(bis);
+#else
+	return 0;
+#endif
+}
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c
new file mode 100644
index 0000000..e0126d3
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright 2007-2009 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2003 Motorola Inc.
+ * Modified by Xianghua Xiao, X.Xiao@motorola.com
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/processor.h>
+#include <ioports.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/fsl_law.h>
+#include "mp.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_MPC8536
+extern void fsl_serdes_init(void);
+#endif
+
+#ifdef CONFIG_QE
+extern qe_iop_conf_t qe_iop_conf_tab[];
+extern void qe_config_iopin(u8 port, u8 pin, int dir,
+				int open_drain, int assign);
+extern void qe_init(uint qe_base);
+extern void qe_reset(void);
+
+static void config_qe_ioports(void)
+{
+	u8      port, pin;
+	int     dir, open_drain, assign;
+	int     i;
+
+	for (i = 0; qe_iop_conf_tab[i].assign != QE_IOP_TAB_END; i++) {
+		port		= qe_iop_conf_tab[i].port;
+		pin		= qe_iop_conf_tab[i].pin;
+		dir		= qe_iop_conf_tab[i].dir;
+		open_drain	= qe_iop_conf_tab[i].open_drain;
+		assign		= qe_iop_conf_tab[i].assign;
+		qe_config_iopin(port, pin, dir, open_drain, assign);
+	}
+}
+#endif
+
+#ifdef CONFIG_CPM2
+void config_8560_ioports (volatile ccsr_cpm_t * cpm)
+{
+	int portnum;
+
+	for (portnum = 0; portnum < 4; portnum++) {
+		uint pmsk = 0,
+		     ppar = 0,
+		     psor = 0,
+		     pdir = 0,
+		     podr = 0,
+		     pdat = 0;
+		iop_conf_t *iopc = (iop_conf_t *) & iop_conf_tab[portnum][0];
+		iop_conf_t *eiopc = iopc + 32;
+		uint msk = 1;
+
+		/*
+		 * NOTE:
+		 * index 0 refers to pin 31,
+		 * index 31 refers to pin 0
+		 */
+		while (iopc < eiopc) {
+			if (iopc->conf) {
+				pmsk |= msk;
+				if (iopc->ppar)
+					ppar |= msk;
+				if (iopc->psor)
+					psor |= msk;
+				if (iopc->pdir)
+					pdir |= msk;
+				if (iopc->podr)
+					podr |= msk;
+				if (iopc->pdat)
+					pdat |= msk;
+			}
+
+			msk <<= 1;
+			iopc++;
+		}
+
+		if (pmsk != 0) {
+			volatile ioport_t *iop = ioport_addr (cpm, portnum);
+			uint tpmsk = ~pmsk;
+
+			/*
+			 * the (somewhat confused) paragraph at the
+			 * bottom of page 35-5 warns that there might
+			 * be "unknown behaviour" when programming
+			 * PSORx and PDIRx, if PPARx = 1, so I
+			 * decided this meant I had to disable the
+			 * dedicated function first, and enable it
+			 * last.
+			 */
+			iop->ppar &= tpmsk;
+			iop->psor = (iop->psor & tpmsk) | psor;
+			iop->podr = (iop->podr & tpmsk) | podr;
+			iop->pdat = (iop->pdat & tpmsk) | pdat;
+			iop->pdir = (iop->pdir & tpmsk) | pdir;
+			iop->ppar |= ppar;
+		}
+	}
+}
+#endif
+
+/*
+ * Breathe some life into the CPU...
+ *
+ * Set up the memory map
+ * initialize a bunch of registers
+ */
+
+#ifdef CONFIG_FSL_CORENET
+static void corenet_tb_init(void)
+{
+	volatile ccsr_rcpm_t *rcpm =
+		(void *)(CONFIG_SYS_FSL_CORENET_RCPM_ADDR);
+	volatile ccsr_pic_t *pic =
+		(void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
+	u32 whoami = in_be32(&pic->whoami);
+
+	/* Enable the timebase register for this core */
+	out_be32(&rcpm->ctbenrl, (1 << whoami));
+}
+#endif
+
+void cpu_init_f (void)
+{
+	volatile ccsr_lbc_t *memctl = (void *)(CONFIG_SYS_MPC85xx_LBC_ADDR);
+	extern void m8560_cpm_reset (void);
+#ifdef CONFIG_MPC8548
+	ccsr_local_ecm_t *ecm = (void *)(CONFIG_SYS_MPC85xx_ECM_ADDR);
+	uint svr = get_svr();
+
+	/*
+	 * CPU2 errata workaround: A core hang possible while executing
+	 * a msync instruction and a snoopable transaction from an I/O
+	 * master tagged to make quick forward progress is present.
+	 * Fixed in silicon rev 2.1.
+	 */
+	if ((SVR_MAJ(svr) == 1) || ((SVR_MAJ(svr) == 2 && SVR_MIN(svr) == 0x0)))
+		out_be32(&ecm->eebpcr, in_be32(&ecm->eebpcr) | (1 << 16));
+#endif
+
+	disable_tlb(14);
+	disable_tlb(15);
+
+#ifdef CONFIG_CPM2
+	config_8560_ioports((ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR);
+#endif
+
+	/* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary
+	 * addresses - these have to be modified later when FLASH size
+	 * has been determined
+	 */
+#if defined(CONFIG_SYS_OR0_REMAP)
+	memctl->or0 = CONFIG_SYS_OR0_REMAP;
+#endif
+#if defined(CONFIG_SYS_OR1_REMAP)
+	memctl->or1 = CONFIG_SYS_OR1_REMAP;
+#endif
+
+	/* now restrict to preliminary range */
+	/* if cs1 is already set via debugger, leave cs0/cs1 alone */
+	if (! memctl->br1 & 1) {
+#if defined(CONFIG_SYS_BR0_PRELIM) && defined(CONFIG_SYS_OR0_PRELIM)
+		memctl->br0 = CONFIG_SYS_BR0_PRELIM;
+		memctl->or0 = CONFIG_SYS_OR0_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR1_PRELIM) && defined(CONFIG_SYS_OR1_PRELIM)
+		memctl->or1 = CONFIG_SYS_OR1_PRELIM;
+		memctl->br1 = CONFIG_SYS_BR1_PRELIM;
+#endif
+	}
+
+#if defined(CONFIG_SYS_BR2_PRELIM) && defined(CONFIG_SYS_OR2_PRELIM)
+	memctl->or2 = CONFIG_SYS_OR2_PRELIM;
+	memctl->br2 = CONFIG_SYS_BR2_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR3_PRELIM) && defined(CONFIG_SYS_OR3_PRELIM)
+	memctl->or3 = CONFIG_SYS_OR3_PRELIM;
+	memctl->br3 = CONFIG_SYS_BR3_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR4_PRELIM) && defined(CONFIG_SYS_OR4_PRELIM)
+	memctl->or4 = CONFIG_SYS_OR4_PRELIM;
+	memctl->br4 = CONFIG_SYS_BR4_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR5_PRELIM) && defined(CONFIG_SYS_OR5_PRELIM)
+	memctl->or5 = CONFIG_SYS_OR5_PRELIM;
+	memctl->br5 = CONFIG_SYS_BR5_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR6_PRELIM) && defined(CONFIG_SYS_OR6_PRELIM)
+	memctl->or6 = CONFIG_SYS_OR6_PRELIM;
+	memctl->br6 = CONFIG_SYS_BR6_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR7_PRELIM) && defined(CONFIG_SYS_OR7_PRELIM)
+	memctl->or7 = CONFIG_SYS_OR7_PRELIM;
+	memctl->br7 = CONFIG_SYS_BR7_PRELIM;
+#endif
+
+#if defined(CONFIG_CPM2)
+	m8560_cpm_reset();
+#endif
+#ifdef CONFIG_QE
+	/* Config QE ioports */
+	config_qe_ioports();
+#endif
+#if defined(CONFIG_MPC8536)
+	fsl_serdes_init();
+#endif
+#if defined(CONFIG_FSL_DMA)
+	dma_init();
+#endif
+#ifdef CONFIG_FSL_CORENET
+	corenet_tb_init();
+#endif
+	init_used_tlb_cams();
+}
+
+
+/*
+ * Initialize L2 as cache.
+ *
+ * The newer 8548, etc, parts have twice as much cache, but
+ * use the same bit-encoding as the older 8555, etc, parts.
+ *
+ */
+
+int cpu_init_r(void)
+{
+	puts ("L2:    ");
+
+#if defined(CONFIG_L2_CACHE)
+	volatile ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR;
+	volatile uint cache_ctl;
+	uint svr, ver;
+	uint l2srbar;
+	u32 l2siz_field;
+
+	svr = get_svr();
+	ver = SVR_SOC_VER(svr);
+
+	asm("msync;isync");
+	cache_ctl = l2cache->l2ctl;
+
+#if defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SYS_INIT_L2_ADDR)
+	if (cache_ctl & MPC85xx_L2CTL_L2E) {
+		/* Clear L2 SRAM memory-mapped base address */
+		out_be32(&l2cache->l2srbar0, 0x0);
+		out_be32(&l2cache->l2srbar1, 0x0);
+
+		/* set MBECCDIS=0, SBECCDIS=0 */
+		clrbits_be32(&l2cache->l2errdis,
+				(MPC85xx_L2ERRDIS_MBECC |
+				 MPC85xx_L2ERRDIS_SBECC));
+
+		/* set L2E=0, L2SRAM=0 */
+		clrbits_be32(&l2cache->l2ctl,
+				(MPC85xx_L2CTL_L2E |
+				 MPC85xx_L2CTL_L2SRAM_ENTIRE));
+	}
+#endif
+
+	l2siz_field = (cache_ctl >> 28) & 0x3;
+
+	switch (l2siz_field) {
+	case 0x0:
+		printf(" unknown size (0x%08x)\n", cache_ctl);
+		return -1;
+		break;
+	case 0x1:
+		if (ver == SVR_8540 || ver == SVR_8560   ||
+		    ver == SVR_8541 || ver == SVR_8541_E ||
+		    ver == SVR_8555 || ver == SVR_8555_E) {
+			puts("128 KB ");
+			/* set L2E=1, L2I=1, & L2BLKSZ=1 (128 Kbyte) */
+			cache_ctl = 0xc4000000;
+		} else {
+			puts("256 KB ");
+			cache_ctl = 0xc0000000; /* set L2E=1, L2I=1, & L2SRAM=0 */
+		}
+		break;
+	case 0x2:
+		if (ver == SVR_8540 || ver == SVR_8560   ||
+		    ver == SVR_8541 || ver == SVR_8541_E ||
+		    ver == SVR_8555 || ver == SVR_8555_E) {
+			puts("256 KB ");
+			/* set L2E=1, L2I=1, & L2BLKSZ=2 (256 Kbyte) */
+			cache_ctl = 0xc8000000;
+		} else {
+			puts ("512 KB ");
+			/* set L2E=1, L2I=1, & L2SRAM=0 */
+			cache_ctl = 0xc0000000;
+		}
+		break;
+	case 0x3:
+		puts("1024 KB ");
+		/* set L2E=1, L2I=1, & L2SRAM=0 */
+		cache_ctl = 0xc0000000;
+		break;
+	}
+
+	if (l2cache->l2ctl & MPC85xx_L2CTL_L2E) {
+		puts("already enabled");
+		l2srbar = l2cache->l2srbar0;
+#ifdef CONFIG_SYS_INIT_L2_ADDR
+		if (l2cache->l2ctl & MPC85xx_L2CTL_L2SRAM_ENTIRE
+				&& l2srbar >= CONFIG_SYS_FLASH_BASE) {
+			l2srbar = CONFIG_SYS_INIT_L2_ADDR;
+			l2cache->l2srbar0 = l2srbar;
+			printf("moving to 0x%08x", CONFIG_SYS_INIT_L2_ADDR);
+		}
+#endif /* CONFIG_SYS_INIT_L2_ADDR */
+		puts("\n");
+	} else {
+		asm("msync;isync");
+		l2cache->l2ctl = cache_ctl; /* invalidate & enable */
+		asm("msync;isync");
+		puts("enabled\n");
+	}
+#elif defined(CONFIG_BACKSIDE_L2_CACHE)
+	u32 l2cfg0 = mfspr(SPRN_L2CFG0);
+
+	/* invalidate the L2 cache */
+	mtspr(SPRN_L2CSR0, (L2CSR0_L2FI|L2CSR0_L2LFC));
+	while (mfspr(SPRN_L2CSR0) & (L2CSR0_L2FI|L2CSR0_L2LFC))
+		;
+
+#ifdef CONFIG_SYS_CACHE_STASHING
+	/* set stash id to (coreID) * 2 + 32 + L2 (1) */
+	mtspr(SPRN_L2CSR1, (32 + 1));
+#endif
+
+	/* enable the cache */
+	mtspr(SPRN_L2CSR0, CONFIG_SYS_INIT_L2CSR0);
+
+	if (CONFIG_SYS_INIT_L2CSR0 & L2CSR0_L2E) {
+		while (!(mfspr(SPRN_L2CSR0) & L2CSR0_L2E))
+			;
+		printf("%d KB enabled\n", (l2cfg0 & 0x3fff) * 64);
+	}
+#else
+	puts("disabled\n");
+#endif
+#ifdef CONFIG_QE
+	uint qe_base = CONFIG_SYS_IMMR + 0x00080000; /* QE immr base */
+	qe_init(qe_base);
+	qe_reset();
+#endif
+
+#if defined(CONFIG_MP)
+	setup_mp();
+#endif
+	return 0;
+}
+
+extern void setup_ivors(void);
+
+void arch_preboot_os(void)
+{
+	u32 msr;
+
+	/*
+	 * We are changing interrupt offsets and are about to boot the OS so
+	 * we need to make sure we disable all async interrupts. EE is already
+	 * disabled by the time we get called.
+	 */
+	msr = mfmsr();
+	msr &= ~(MSR_ME|MSR_CE|MSR_DE);
+	mtmsr(msr);
+
+	setup_ivors();
+}
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init_early.c b/arch/powerpc/cpu/mpc85xx/cpu_init_early.c
new file mode 100644
index 0000000..32aa94b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init_early.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2009 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/fsl_law.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR_PHYS)
+#ifdef CONFIG_FSL_CORENET
+static void setup_ccsrbar(void)
+{
+	u32 temp;
+	volatile u32 *ccsr_virt = (volatile u32 *)(CONFIG_SYS_CCSRBAR + 0x1000);
+	volatile ccsr_local_t *ccm;
+
+	/*
+	 * We can't call set_law() because we haven't moved
+	 * CCSR yet.
+	 */
+	ccm = (void *)ccsr_virt;
+
+	out_be32(&ccm->law[0].lawbarh,
+		(u64)CONFIG_SYS_CCSRBAR_PHYS >> 32);
+	out_be32(&ccm->law[0].lawbarl, (u32)CONFIG_SYS_CCSRBAR_PHYS);
+	out_be32(&ccm->law[0].lawar,
+		LAW_EN | (0x1e << 20) | LAW_SIZE_4K);
+
+	in_be32((u32 *)(ccsr_virt + 0));
+	in_be32((u32 *)(ccsr_virt + 1));
+	isync();
+
+	ccm = (void *)CONFIG_SYS_CCSRBAR;
+	/* Now use the temporary LAW to move CCSR */
+	out_be32(&ccm->ccsrbarh, (u64)CONFIG_SYS_CCSRBAR_PHYS >> 32);
+	out_be32(&ccm->ccsrbarl, (u32)CONFIG_SYS_CCSRBAR_PHYS);
+	out_be32(&ccm->ccsrar, CCSRAR_C);
+	temp = in_be32(&ccm->ccsrar);
+	disable_law(0);
+}
+#else
+static void setup_ccsrbar(void)
+{
+	u32 temp;
+	volatile u32 *ccsr_virt = (volatile u32 *)(CONFIG_SYS_CCSRBAR + 0x1000);
+
+	temp = in_be32(ccsr_virt);
+	out_be32(ccsr_virt, CONFIG_SYS_CCSRBAR_PHYS >> 12);
+	temp = in_be32((volatile u32 *)CONFIG_SYS_CCSRBAR);
+}
+#endif
+#endif
+
+/* We run cpu_init_early_f in AS = 1 */
+void cpu_init_early_f(void)
+{
+	u32 mas0, mas1, mas2, mas3, mas7;
+	int i;
+
+	/* Pointer is writable since we allocated a register for it */
+	gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+	/*
+	 * Clear initial global data
+	 *   we don't use memset so we can share this code with NAND_SPL
+	 */
+	for (i = 0; i < sizeof(gd_t); i++)
+		((char *)gd)[i] = 0;
+
+	mas0 = MAS0_TLBSEL(0) | MAS0_ESEL(0);
+	mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_TSIZE(BOOKE_PAGESZ_4K);
+	mas2 = FSL_BOOKE_MAS2(CONFIG_SYS_CCSRBAR, MAS2_I|MAS2_G);
+	mas3 = FSL_BOOKE_MAS3(CONFIG_SYS_CCSRBAR_PHYS, 0, MAS3_SW|MAS3_SR);
+	mas7 = FSL_BOOKE_MAS7(CONFIG_SYS_CCSRBAR_PHYS);
+
+	write_tlb(mas0, mas1, mas2, mas3, mas7);
+
+	/* set up CCSR if we want it moved */
+#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR_PHYS)
+	mas0 = MAS0_TLBSEL(0) | MAS0_ESEL(1);
+	/* mas1 is the same as above */
+	mas2 = FSL_BOOKE_MAS2(CONFIG_SYS_CCSRBAR + 0x1000, MAS2_I|MAS2_G);
+	mas3 = FSL_BOOKE_MAS3(CONFIG_SYS_CCSRBAR_DEFAULT, 0, MAS3_SW|MAS3_SR);
+	mas7 = FSL_BOOKE_MAS7(CONFIG_SYS_CCSRBAR_DEFAULT);
+
+	write_tlb(mas0, mas1, mas2, mas3, mas7);
+
+	setup_ccsrbar();
+#endif
+
+	init_laws();
+	invalidate_tlb(0);
+	init_tlbs();
+}
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init_nand.c b/arch/powerpc/cpu/mpc85xx/cpu_init_nand.c
new file mode 100644
index 0000000..184cca4
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init_nand.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+void cpu_init_f(void)
+{
+	ccsr_lbc_t *lbc = (void *)(CONFIG_SYS_MPC85xx_LBC_ADDR);
+
+	/*
+	 * LCRR - Clock Ratio Register - set up local bus timing
+	 * when needed
+	 */
+	out_be32(&lbc->lcrr, LCRR_DBYP | LCRR_CLKDIV_8);
+
+#if defined(CONFIG_NAND_BR_PRELIM) && defined(CONFIG_NAND_OR_PRELIM)
+	out_be32(&lbc->br0, CONFIG_NAND_BR_PRELIM);
+	out_be32(&lbc->or0, CONFIG_NAND_OR_PRELIM);
+#else
+#error  CONFIG_NAND_BR_PRELIM, CONFIG_NAND_OR_PRELIM must be defined
+#endif
+
+#if defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SYS_INIT_L2_ADDR)
+	ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR;
+	char *l2srbar;
+	int i;
+
+	out_be32(&l2cache->l2srbar0, CONFIG_SYS_INIT_L2_ADDR);
+
+	/* set MBECCDIS=1, SBECCDIS=1 */
+	out_be32(&l2cache->l2errdis,
+		(MPC85xx_L2ERRDIS_MBECC | MPC85xx_L2ERRDIS_SBECC));
+
+	/* set L2E=1 & L2SRAM=001 */
+	out_be32(&l2cache->l2ctl,
+		(MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2SRAM_ENTIRE));
+
+	/* Initialize L2 SRAM to zero */
+	l2srbar = (char *)CONFIG_SYS_INIT_L2_ADDR;
+	for (i = 0; i < CONFIG_SYS_L2_SIZE; i++)
+		l2srbar[i] = 0;
+#endif
+}
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen1.c b/arch/powerpc/cpu/mpc85xx/ddr-gen1.c
new file mode 100644
index 0000000..54437dd
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen1.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2008 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+			     unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+
+	if (ctrl_num != 0) {
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		if (i == 0) {
+			out_be32(&ddr->cs0_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs0_config, regs->cs[i].config);
+
+		} else if (i == 1) {
+			out_be32(&ddr->cs1_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs1_config, regs->cs[i].config);
+
+		} else if (i == 2) {
+			out_be32(&ddr->cs2_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs2_config, regs->cs[i].config);
+
+		} else if (i == 3) {
+			out_be32(&ddr->cs3_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs3_config, regs->cs[i].config);
+		}
+	}
+
+	out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1);
+	out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+	out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
+	out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
+#if defined(CONFIG_MPC8555) || defined(CONFIG_MPC8541)
+	out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
+#endif
+
+	/*
+	 * 200 painful micro-seconds must elapse between
+	 * the DDR clock setup and the DDR config enable.
+	 */
+	udelay(200);
+	asm volatile("sync;isync");
+
+	out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg);
+
+	asm("sync;isync;msync");
+	udelay(500);
+}
+
+#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+/*
+ * Initialize all of memory for ECC, then enable errors.
+ */
+
+void
+ddr_enable_ecc(unsigned int dram_size)
+{
+	volatile ccsr_ddr_t *ddr= (void *)(CONFIG_SYS_MPC85xx_DDR_ADDR);
+
+	dma_meminit(CONFIG_MEM_INIT_VALUE, dram_size);
+
+	/*
+	 * Enable errors for ECC.
+	 */
+	debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable);
+	ddr->err_disable = 0x00000000;
+	asm("sync;isync;msync");
+	debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable);
+}
+
+#endif	/* CONFIG_DDR_ECC  && ! CONFIG_ECC_INIT_VIA_DDRCONTROLLER */
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen2.c b/arch/powerpc/cpu/mpc85xx/ddr-gen2.c
new file mode 100644
index 0000000..655f99c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen2.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+			     unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+
+	if (ctrl_num) {
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		if (i == 0) {
+			out_be32(&ddr->cs0_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs0_config, regs->cs[i].config);
+
+		} else if (i == 1) {
+			out_be32(&ddr->cs1_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs1_config, regs->cs[i].config);
+
+		} else if (i == 2) {
+			out_be32(&ddr->cs2_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs2_config, regs->cs[i].config);
+
+		} else if (i == 3) {
+			out_be32(&ddr->cs3_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs3_config, regs->cs[i].config);
+		}
+	}
+
+	out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3);
+	out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0);
+	out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1);
+	out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+	out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+	out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
+	out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
+	out_be32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl);
+	out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
+	out_be32(&ddr->sdram_data_init, regs->ddr_data_init);
+	out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
+	out_be32(&ddr->init_addr, regs->ddr_init_addr);
+	out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+
+	/*
+	 * 200 painful micro-seconds must elapse between
+	 * the DDR clock setup and the DDR config enable.
+	 */
+	udelay(200);
+	asm volatile("sync;isync");
+
+	out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg);
+
+	/* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done.  */
+	while (in_be32(&ddr->sdram_cfg_2) & 0x10) {
+		udelay(10000);		/* throttle polling rate */
+	}
+}
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
new file mode 100644
index 0000000..0691ca4
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2008 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+			     unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr;
+	u32 temp_sdram_cfg;
+
+	switch (ctrl_num) {
+	case 0:
+		ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+		break;
+	case 1:
+		ddr = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR;
+		break;
+	default:
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		if (i == 0) {
+			out_be32(&ddr->cs0_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs0_config, regs->cs[i].config);
+			out_be32(&ddr->cs0_config_2, regs->cs[i].config_2);
+
+		} else if (i == 1) {
+			out_be32(&ddr->cs1_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs1_config, regs->cs[i].config);
+			out_be32(&ddr->cs1_config_2, regs->cs[i].config_2);
+
+		} else if (i == 2) {
+			out_be32(&ddr->cs2_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs2_config, regs->cs[i].config);
+			out_be32(&ddr->cs2_config_2, regs->cs[i].config_2);
+
+		} else if (i == 3) {
+			out_be32(&ddr->cs3_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs3_config, regs->cs[i].config);
+			out_be32(&ddr->cs3_config_2, regs->cs[i].config_2);
+		}
+	}
+
+	out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3);
+	out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0);
+	out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1);
+	out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+	out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+	out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
+	out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
+	out_be32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl);
+	out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
+	out_be32(&ddr->sdram_data_init, regs->ddr_data_init);
+	out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
+	out_be32(&ddr->init_addr, regs->ddr_init_addr);
+	out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+
+	out_be32(&ddr->timing_cfg_4, regs->timing_cfg_4);
+	out_be32(&ddr->timing_cfg_5, regs->timing_cfg_5);
+	out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl);
+	out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl);
+	out_be32(&ddr->ddr_sr_cntr, regs->ddr_sr_cntr);
+	out_be32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1);
+	out_be32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2);
+
+	/* Set, but do not enable the memory */
+	temp_sdram_cfg = regs->ddr_sdram_cfg;
+	temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN);
+	out_be32(&ddr->sdram_cfg, temp_sdram_cfg);
+	/*
+	 * For 8572 DDR1 erratum - DDR controller may enter illegal state
+	 * when operatiing in 32-bit bus mode with 4-beat bursts,
+	 * This erratum does not affect DDR3 mode, only for DDR2 mode.
+	 */
+#ifdef CONFIG_MPC8572
+	if ((((in_be32(&ddr->sdram_cfg) >> 24) & 0x7) == SDRAM_TYPE_DDR2)
+	    && in_be32(&ddr->sdram_cfg) & 0x80000) {
+		/* set DEBUG_1[31] */
+		u32 temp = in_be32(&ddr->debug_1);
+		out_be32(&ddr->debug_1, temp | 1);
+	}
+#endif
+
+	/*
+	 * 500 painful micro-seconds must elapse between
+	 * the DDR clock setup and the DDR config enable.
+	 * DDR2 need 200 us, and DDR3 need 500 us from spec,
+	 * we choose the max, that is 500 us for all of case.
+	 */
+	udelay(500);
+	asm volatile("sync;isync");
+
+	/* Let the controller go */
+	temp_sdram_cfg = in_be32(&ddr->sdram_cfg);
+	out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
+
+	/* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done.  */
+	while (in_be32(&ddr->sdram_cfg_2) & 0x10) {
+		udelay(10000);		/* throttle polling rate */
+	}
+}
diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
new file mode 100644
index 0000000..5f1414d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
@@ -0,0 +1,469 @@
+/*
+ * MPC8560 FCC Fast Ethernet
+ * Copyright (c) 2003 Motorola,Inc.
+ * Xianghua Xiao, (X.Xiao@motorola.com)
+ *
+ * Copyright (c) 2000 MontaVista Software, Inc.   Dan Malek (dmalek@jlc.net)
+ *
+ * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * MPC8560 FCC Fast Ethernet
+ * Basic ET HW initialization and packet RX/TX routines
+ *
+ * This code will not perform the IO port configuration. This should be
+ * done in the iop_conf_t structure specific for the board.
+ *
+ * TODO:
+ * add a PHY driver to do the negotiation
+ * reflect negotiation results in FPSMR
+ * look for ways to configure the board specific stuff elsewhere, eg.
+ *    config_xxx.h or the board directory
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/cpm_85xx.h>
+#include <command.h>
+#include <config.h>
+#include <net.h>
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+#include <miiphy.h>
+#endif
+
+#if defined(CONFIG_ETHER_ON_FCC) && defined(CONFIG_CMD_NET) && \
+	defined(CONFIG_NET_MULTI)
+
+static struct ether_fcc_info_s
+{
+	int ether_index;
+	int proff_enet;
+	ulong cpm_cr_enet_sblock;
+	ulong cpm_cr_enet_page;
+	ulong cmxfcr_mask;
+	ulong cmxfcr_value;
+}
+	ether_fcc_info[] =
+{
+#ifdef CONFIG_ETHER_ON_FCC1
+{
+	0,
+	PROFF_FCC1,
+	CPM_CR_FCC1_SBLOCK,
+	CPM_CR_FCC1_PAGE,
+	CONFIG_SYS_CMXFCR_MASK1,
+	CONFIG_SYS_CMXFCR_VALUE1
+},
+#endif
+
+#ifdef CONFIG_ETHER_ON_FCC2
+{
+	1,
+	PROFF_FCC2,
+	CPM_CR_FCC2_SBLOCK,
+	CPM_CR_FCC2_PAGE,
+	CONFIG_SYS_CMXFCR_MASK2,
+	CONFIG_SYS_CMXFCR_VALUE2
+},
+#endif
+
+#ifdef CONFIG_ETHER_ON_FCC3
+{
+	2,
+	PROFF_FCC3,
+	CPM_CR_FCC3_SBLOCK,
+	CPM_CR_FCC3_PAGE,
+	CONFIG_SYS_CMXFCR_MASK3,
+	CONFIG_SYS_CMXFCR_VALUE3
+},
+#endif
+};
+
+/*---------------------------------------------------------------------*/
+
+/* Maximum input DMA size.  Must be a should(?) be a multiple of 4. */
+#define PKT_MAXDMA_SIZE         1520
+
+/* The FCC stores dest/src/type, data, and checksum for receive packets. */
+#define PKT_MAXBUF_SIZE         1518
+#define PKT_MINBUF_SIZE         64
+
+/* Maximum input buffer size.  Must be a multiple of 32. */
+#define PKT_MAXBLR_SIZE         1536
+
+#define TOUT_LOOP 1000000
+
+#define TX_BUF_CNT 2
+
+static uint rxIdx;	/* index of the current RX buffer */
+static uint txIdx;	/* index of the current TX buffer */
+
+/*
+ * FCC Ethernet Tx and Rx buffer descriptors.
+ * Provide for Double Buffering
+ * Note: PKTBUFSRX is defined in net.h
+ */
+
+typedef volatile struct rtxbd {
+    cbd_t rxbd[PKTBUFSRX];
+    cbd_t txbd[TX_BUF_CNT];
+} RTXBD;
+
+/*  Good news: the FCC supports external BDs! */
+#ifdef __GNUC__
+static RTXBD rtx __attribute__ ((aligned(8)));
+#else
+#error "rtx must be 64-bit aligned"
+#endif
+
+#undef ET_DEBUG
+
+static int fec_send(struct eth_device* dev, volatile void *packet, int length)
+{
+    int i = 0;
+    int result = 0;
+
+    if (length <= 0) {
+	printf("fec: bad packet size: %d\n", length);
+	goto out;
+    }
+
+    for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+	if (i >= TOUT_LOOP) {
+	    printf("fec: tx buffer not ready\n");
+	    goto out;
+	}
+    }
+
+    rtx.txbd[txIdx].cbd_bufaddr = (uint)packet;
+    rtx.txbd[txIdx].cbd_datlen = length;
+    rtx.txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST | \
+			       BD_ENET_TX_TC | BD_ENET_TX_PAD);
+
+    for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+	if (i >= TOUT_LOOP) {
+	    printf("fec: tx error\n");
+	    goto out;
+	}
+    }
+
+#ifdef ET_DEBUG
+    printf("cycles: 0x%x txIdx=0x%04x status: 0x%04x\n", i, txIdx,rtx.txbd[txIdx].cbd_sc);
+    printf("packets at 0x%08x, length_in_bytes=0x%x\n",(uint)packet,length);
+    for(i=0;i<(length/16 + 1);i++) {
+	 printf("%08x %08x %08x %08x\n",*((uint *)rtx.txbd[txIdx].cbd_bufaddr+i*4),\
+    *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 1),*((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 2), \
+    *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 3));
+    }
+#endif
+
+    /* return only status bits */
+    result = rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_STATS;
+    txIdx = (txIdx + 1) % TX_BUF_CNT;
+
+out:
+    return result;
+}
+
+static int fec_recv(struct eth_device* dev)
+{
+    int length;
+
+    for (;;)
+    {
+	if (rtx.rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+	    length = -1;
+	    break;     /* nothing received - leave for() loop */
+	}
+	length = rtx.rxbd[rxIdx].cbd_datlen;
+
+	if (rtx.rxbd[rxIdx].cbd_sc & 0x003f) {
+	    printf("fec: rx error %04x\n", rtx.rxbd[rxIdx].cbd_sc);
+	}
+	else {
+	    /* Pass the packet up to the protocol layers. */
+	    NetReceive(NetRxPackets[rxIdx], length - 4);
+	}
+
+
+	/* Give the buffer back to the FCC. */
+	rtx.rxbd[rxIdx].cbd_datlen = 0;
+
+	/* wrap around buffer index when necessary */
+	if ((rxIdx + 1) >= PKTBUFSRX) {
+	    rtx.rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
+	    rxIdx = 0;
+	}
+	else {
+	    rtx.rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+	    rxIdx++;
+	}
+    }
+    return length;
+}
+
+
+static int fec_init(struct eth_device* dev, bd_t *bis)
+{
+    struct ether_fcc_info_s * info = dev->priv;
+    int i;
+    volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+    volatile ccsr_cpm_cp_t *cp = &(cpm->im_cpm_cp);
+    fcc_enet_t *pram_ptr;
+    unsigned long mem_addr;
+
+#if 0
+    mii_discover_phy();
+#endif
+
+    /* 28.9 - (1-2): ioports have been set up already */
+
+    /* 28.9 - (3): connect FCC's tx and rx clocks */
+    cpm->im_cpm_mux.cmxuar = 0; /* ATM */
+    cpm->im_cpm_mux.cmxfcr = (cpm->im_cpm_mux.cmxfcr & ~info->cmxfcr_mask) |
+							info->cmxfcr_value;
+
+    /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, set Mode Ethernet */
+    if(info->ether_index == 0) {
+	cpm->im_cpm_fcc1.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+    } else if (info->ether_index == 1) {
+	cpm->im_cpm_fcc2.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+    } else if (info->ether_index == 2) {
+	cpm->im_cpm_fcc3.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+    }
+
+    /* 28.9 - (5): FPSMR: enable full duplex, select CCITT CRC for Ethernet,MII */
+    if(info->ether_index == 0) {
+	cpm->im_cpm_fcc1.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
+    } else if (info->ether_index == 1){
+	cpm->im_cpm_fcc2.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
+    } else if (info->ether_index == 2){
+	cpm->im_cpm_fcc3.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
+    }
+
+    /* 28.9 - (6): FDSR: Ethernet Syn */
+    if(info->ether_index == 0) {
+	cpm->im_cpm_fcc1.fdsr = 0xD555;
+    } else if (info->ether_index == 1) {
+	cpm->im_cpm_fcc2.fdsr = 0xD555;
+    } else if (info->ether_index == 2) {
+	cpm->im_cpm_fcc3.fdsr = 0xD555;
+    }
+
+    /* reset indeces to current rx/tx bd (see eth_send()/eth_rx()) */
+    rxIdx = 0;
+    txIdx = 0;
+
+    /* Setup Receiver Buffer Descriptors */
+    for (i = 0; i < PKTBUFSRX; i++)
+    {
+      rtx.rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+      rtx.rxbd[i].cbd_datlen = 0;
+      rtx.rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i];
+    }
+    rtx.rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+    /* Setup Ethernet Transmitter Buffer Descriptors */
+    for (i = 0; i < TX_BUF_CNT; i++)
+    {
+      rtx.txbd[i].cbd_sc = 0;
+      rtx.txbd[i].cbd_datlen = 0;
+      rtx.txbd[i].cbd_bufaddr = 0;
+    }
+    rtx.txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+    /* 28.9 - (7): initialize parameter ram */
+    pram_ptr = (fcc_enet_t *)&(cpm->im_dprambase[info->proff_enet]);
+
+    /* clear whole structure to make sure all reserved fields are zero */
+    memset((void*)pram_ptr, 0, sizeof(fcc_enet_t));
+
+    /*
+     * common Parameter RAM area
+     *
+     * Allocate space in the reserved FCC area of DPRAM for the
+     * internal buffers.  No one uses this space (yet), so we
+     * can do this.  Later, we will add resource management for
+     * this area.
+     * CPM_FCC_SPECIAL_BASE:	0xB000 for MPC8540, MPC8560
+     *				0x9000 for MPC8541, MPC8555
+     */
+    mem_addr = CPM_FCC_SPECIAL_BASE + ((info->ether_index) * 64);
+    pram_ptr->fen_genfcc.fcc_riptr = mem_addr;
+    pram_ptr->fen_genfcc.fcc_tiptr = mem_addr+32;
+    /*
+     * Set maximum bytes per receive buffer.
+     * It must be a multiple of 32.
+     */
+    pram_ptr->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE; /* 1536 */
+    /* localbus SDRAM should be preferred */
+    pram_ptr->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB |
+				       CONFIG_SYS_CPMFCR_RAMTYPE) << 24;
+    pram_ptr->fen_genfcc.fcc_rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
+    pram_ptr->fen_genfcc.fcc_rbdstat = 0;
+    pram_ptr->fen_genfcc.fcc_rbdlen = 0;
+    pram_ptr->fen_genfcc.fcc_rdptr = 0;
+    /* localbus SDRAM should be preferred */
+    pram_ptr->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB |
+				       CONFIG_SYS_CPMFCR_RAMTYPE) << 24;
+    pram_ptr->fen_genfcc.fcc_tbase = (unsigned int)(&rtx.txbd[txIdx]);
+    pram_ptr->fen_genfcc.fcc_tbdstat = 0;
+    pram_ptr->fen_genfcc.fcc_tbdlen = 0;
+    pram_ptr->fen_genfcc.fcc_tdptr = 0;
+
+    /* protocol-specific area */
+    pram_ptr->fen_statbuf = 0x0;
+    pram_ptr->fen_cmask = 0xdebb20e3;	/* CRC mask */
+    pram_ptr->fen_cpres = 0xffffffff;	/* CRC preset */
+    pram_ptr->fen_crcec = 0;
+    pram_ptr->fen_alec = 0;
+    pram_ptr->fen_disfc = 0;
+    pram_ptr->fen_retlim = 15;		/* Retry limit threshold */
+    pram_ptr->fen_retcnt = 0;
+    pram_ptr->fen_pper = 0;
+    pram_ptr->fen_boffcnt = 0;
+    pram_ptr->fen_gaddrh = 0;
+    pram_ptr->fen_gaddrl = 0;
+    pram_ptr->fen_mflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
+    /*
+     * Set Ethernet station address.
+     *
+     * This is supplied in the board information structure, so we
+     * copy that into the controller.
+     * So far we have only been given one Ethernet address. We make
+     * it unique by setting a few bits in the upper byte of the
+     * non-static part of the address.
+     */
+#define ea eth_get_dev()->enetaddr
+    pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
+    pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
+    pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
+#undef ea
+    pram_ptr->fen_ibdcount = 0;
+    pram_ptr->fen_ibdstart = 0;
+    pram_ptr->fen_ibdend = 0;
+    pram_ptr->fen_txlen = 0;
+    pram_ptr->fen_iaddrh = 0;  /* disable hash */
+    pram_ptr->fen_iaddrl = 0;
+    pram_ptr->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register: 64 */
+    /* pad pointer. use tiptr since we don't need a specific padding char */
+    pram_ptr->fen_padptr = pram_ptr->fen_genfcc.fcc_tiptr;
+    pram_ptr->fen_maxd1 = PKT_MAXDMA_SIZE;	/* maximum DMA1 length:1520 */
+    pram_ptr->fen_maxd2 = PKT_MAXDMA_SIZE;	/* maximum DMA2 length:1520 */
+
+#if defined(ET_DEBUG)
+    printf("parm_ptr(0xff788500) = %p\n",pram_ptr);
+    printf("pram_ptr->fen_genfcc.fcc_rbase %08x\n",
+	pram_ptr->fen_genfcc.fcc_rbase);
+    printf("pram_ptr->fen_genfcc.fcc_tbase %08x\n",
+	pram_ptr->fen_genfcc.fcc_tbase);
+#endif
+
+    /* 28.9 - (8)(9): clear out events in FCCE */
+    /* 28.9 - (9): FCCM: mask all events */
+    if(info->ether_index == 0) {
+	cpm->im_cpm_fcc1.fcce = ~0x0;
+	cpm->im_cpm_fcc1.fccm = 0;
+    } else if (info->ether_index == 1) {
+	cpm->im_cpm_fcc2.fcce = ~0x0;
+	cpm->im_cpm_fcc2.fccm = 0;
+    } else if (info->ether_index == 2) {
+	cpm->im_cpm_fcc3.fcce = ~0x0;
+	cpm->im_cpm_fcc3.fccm = 0;
+    }
+
+    /* 28.9 - (10-12): we don't use ethernet interrupts */
+
+    /* 28.9 - (13)
+     *
+     * Let's re-initialize the channel now.  We have to do it later
+     * than the manual describes because we have just now finished
+     * the BD initialization.
+     */
+    cp->cpcr = mk_cr_cmd(info->cpm_cr_enet_page,
+			    info->cpm_cr_enet_sblock,
+			    0x0c,
+			    CPM_CR_INIT_TRX) | CPM_CR_FLG;
+    do {
+	__asm__ __volatile__ ("eieio");
+    } while (cp->cpcr & CPM_CR_FLG);
+
+    /* 28.9 - (14): enable tx/rx in gfmr */
+    if(info->ether_index == 0) {
+	cpm->im_cpm_fcc1.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+    } else if (info->ether_index == 1) {
+	cpm->im_cpm_fcc2.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+    } else if (info->ether_index == 2) {
+	cpm->im_cpm_fcc3.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+    }
+
+    return 1;
+}
+
+static void fec_halt(struct eth_device* dev)
+{
+    struct ether_fcc_info_s * info = dev->priv;
+    volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+
+    /* write GFMR: disable tx/rx */
+    if(info->ether_index == 0) {
+	cpm->im_cpm_fcc1.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+    } else if(info->ether_index == 1) {
+	cpm->im_cpm_fcc2.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+    } else if(info->ether_index == 2) {
+	cpm->im_cpm_fcc3.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+    }
+}
+
+int fec_initialize(bd_t *bis)
+{
+	struct eth_device* dev;
+	int i;
+
+	for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
+	{
+		dev = (struct eth_device*) malloc(sizeof *dev);
+		memset(dev, 0, sizeof *dev);
+
+		sprintf(dev->name, "FCC%d ETHERNET",
+			ether_fcc_info[i].ether_index + 1);
+		dev->priv   = &ether_fcc_info[i];
+		dev->init   = fec_init;
+		dev->halt   = fec_halt;
+		dev->send   = fec_send;
+		dev->recv   = fec_recv;
+
+		eth_register(dev);
+
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
+		&& defined(CONFIG_BITBANGMII)
+		miiphy_register(dev->name,
+				bb_miiphy_read,	bb_miiphy_write);
+#endif
+	}
+
+	return 1;
+}
+
+#endif
diff --git a/arch/powerpc/cpu/mpc85xx/fdt.c b/arch/powerpc/cpu/mpc85xx/fdt.c
new file mode 100644
index 0000000..1d11ab4
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/fdt.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright 2007-2009 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <asm/processor.h>
+#include <linux/ctype.h>
+#ifdef CONFIG_FSL_ESDHC
+#include <fsl_esdhc.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern void ft_qe_setup(void *blob);
+extern void ft_fixup_num_cores(void *blob);
+
+#ifdef CONFIG_MP
+#include "mp.h"
+
+void ft_fixup_cpu(void *blob, u64 memory_limit)
+{
+	int off;
+	ulong spin_tbl_addr = get_spin_phys_addr();
+	u32 bootpg = determine_mp_bootpg();
+	u32 id = get_my_id();
+
+	off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+	while (off != -FDT_ERR_NOTFOUND) {
+		u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
+
+		if (reg) {
+			if (*reg == id) {
+				fdt_setprop_string(blob, off, "status", "okay");
+			} else {
+				u64 val = *reg * SIZE_BOOT_ENTRY + spin_tbl_addr;
+				val = cpu_to_fdt32(val);
+				fdt_setprop_string(blob, off, "status",
+								"disabled");
+				fdt_setprop_string(blob, off, "enable-method",
+								"spin-table");
+				fdt_setprop(blob, off, "cpu-release-addr",
+						&val, sizeof(val));
+			}
+		} else {
+			printf ("cpu NULL\n");
+		}
+		off = fdt_node_offset_by_prop_value(blob, off,
+				"device_type", "cpu", 4);
+	}
+
+	/* Reserve the boot page so OSes dont use it */
+	if ((u64)bootpg < memory_limit) {
+		off = fdt_add_mem_rsv(blob, bootpg, (u64)4096);
+		if (off < 0)
+			printf("%s: %s\n", __FUNCTION__, fdt_strerror(off));
+	}
+}
+#endif
+
+#define ft_fixup_l3cache(x, y)
+
+#if defined(CONFIG_L2_CACHE)
+/* return size in kilobytes */
+static inline u32 l2cache_size(void)
+{
+	volatile ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR;
+	volatile u32 l2siz_field = (l2cache->l2ctl >> 28) & 0x3;
+	u32 ver = SVR_SOC_VER(get_svr());
+
+	switch (l2siz_field) {
+	case 0x0:
+		break;
+	case 0x1:
+		if (ver == SVR_8540 || ver == SVR_8560   ||
+		    ver == SVR_8541 || ver == SVR_8541_E ||
+		    ver == SVR_8555 || ver == SVR_8555_E)
+			return 128;
+		else
+			return 256;
+		break;
+	case 0x2:
+		if (ver == SVR_8540 || ver == SVR_8560   ||
+		    ver == SVR_8541 || ver == SVR_8541_E ||
+		    ver == SVR_8555 || ver == SVR_8555_E)
+			return 256;
+		else
+			return 512;
+		break;
+	case 0x3:
+		return 1024;
+		break;
+	}
+
+	return 0;
+}
+
+static inline void ft_fixup_l2cache(void *blob)
+{
+	int len, off;
+	u32 *ph;
+	struct cpu_type *cpu = identify_cpu(SVR_SOC_VER(get_svr()));
+	char compat_buf[38];
+
+	const u32 line_size = 32;
+	const u32 num_ways = 8;
+	const u32 size = l2cache_size() * 1024;
+	const u32 num_sets = size / (line_size * num_ways);
+
+	off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+	if (off < 0) {
+		debug("no cpu node fount\n");
+		return;
+	}
+
+	ph = (u32 *)fdt_getprop(blob, off, "next-level-cache", 0);
+
+	if (ph == NULL) {
+		debug("no next-level-cache property\n");
+		return ;
+	}
+
+	off = fdt_node_offset_by_phandle(blob, *ph);
+	if (off < 0) {
+		printf("%s: %s\n", __func__, fdt_strerror(off));
+		return ;
+	}
+
+	if (cpu) {
+		if (isdigit(cpu->name[0]))
+			len = sprintf(compat_buf,
+				"fsl,mpc%s-l2-cache-controller", cpu->name);
+		else
+			len = sprintf(compat_buf,
+				"fsl,%c%s-l2-cache-controller",
+				tolower(cpu->name[0]), cpu->name + 1);
+
+		sprintf(&compat_buf[len + 1], "cache");
+	}
+	fdt_setprop(blob, off, "cache-unified", NULL, 0);
+	fdt_setprop_cell(blob, off, "cache-block-size", line_size);
+	fdt_setprop_cell(blob, off, "cache-size", size);
+	fdt_setprop_cell(blob, off, "cache-sets", num_sets);
+	fdt_setprop_cell(blob, off, "cache-level", 2);
+	fdt_setprop(blob, off, "compatible", compat_buf, sizeof(compat_buf));
+
+	/* we dont bother w/L3 since no platform of this type has one */
+}
+#elif defined(CONFIG_BACKSIDE_L2_CACHE)
+static inline void ft_fixup_l2cache(void *blob)
+{
+	int off, l2_off, l3_off = -1;
+	u32 *ph;
+	u32 l2cfg0 = mfspr(SPRN_L2CFG0);
+	u32 size, line_size, num_ways, num_sets;
+
+	size = (l2cfg0 & 0x3fff) * 64 * 1024;
+	num_ways = ((l2cfg0 >> 14) & 0x1f) + 1;
+	line_size = (((l2cfg0 >> 23) & 0x3) + 1) * 32;
+	num_sets = size / (line_size * num_ways);
+
+	off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+
+	while (off != -FDT_ERR_NOTFOUND) {
+		ph = (u32 *)fdt_getprop(blob, off, "next-level-cache", 0);
+
+		if (ph == NULL) {
+			debug("no next-level-cache property\n");
+			goto next;
+		}
+
+		l2_off = fdt_node_offset_by_phandle(blob, *ph);
+		if (l2_off < 0) {
+			printf("%s: %s\n", __func__, fdt_strerror(off));
+			goto next;
+		}
+
+#ifdef CONFIG_SYS_CACHE_STASHING
+		{
+			u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
+			if (reg)
+				fdt_setprop_cell(blob, l2_off, "cache-stash-id",
+					 (*reg * 2) + 32 + 1);
+		}
+#endif
+
+		fdt_setprop(blob, l2_off, "cache-unified", NULL, 0);
+		fdt_setprop_cell(blob, l2_off, "cache-block-size", line_size);
+		fdt_setprop_cell(blob, l2_off, "cache-size", size);
+		fdt_setprop_cell(blob, l2_off, "cache-sets", num_sets);
+		fdt_setprop_cell(blob, l2_off, "cache-level", 2);
+		fdt_setprop(blob, l2_off, "compatible", "cache", 6);
+
+		if (l3_off < 0) {
+			ph = (u32 *)fdt_getprop(blob, l2_off, "next-level-cache", 0);
+
+			if (ph == NULL) {
+				debug("no next-level-cache property\n");
+				goto next;
+			}
+			l3_off = *ph;
+		}
+next:
+		off = fdt_node_offset_by_prop_value(blob, off,
+				"device_type", "cpu", 4);
+	}
+	if (l3_off > 0) {
+		l3_off = fdt_node_offset_by_phandle(blob, l3_off);
+		if (l3_off < 0) {
+			printf("%s: %s\n", __func__, fdt_strerror(off));
+			return ;
+		}
+		ft_fixup_l3cache(blob, l3_off);
+	}
+}
+#else
+#define ft_fixup_l2cache(x)
+#endif
+
+static inline void ft_fixup_cache(void *blob)
+{
+	int off;
+
+	off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+
+	while (off != -FDT_ERR_NOTFOUND) {
+		u32 l1cfg0 = mfspr(SPRN_L1CFG0);
+		u32 l1cfg1 = mfspr(SPRN_L1CFG1);
+		u32 isize, iline_size, inum_sets, inum_ways;
+		u32 dsize, dline_size, dnum_sets, dnum_ways;
+
+		/* d-side config */
+		dsize = (l1cfg0 & 0x7ff) * 1024;
+		dnum_ways = ((l1cfg0 >> 11) & 0xff) + 1;
+		dline_size = (((l1cfg0 >> 23) & 0x3) + 1) * 32;
+		dnum_sets = dsize / (dline_size * dnum_ways);
+
+		fdt_setprop_cell(blob, off, "d-cache-block-size", dline_size);
+		fdt_setprop_cell(blob, off, "d-cache-size", dsize);
+		fdt_setprop_cell(blob, off, "d-cache-sets", dnum_sets);
+
+#ifdef CONFIG_SYS_CACHE_STASHING
+		{
+			u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
+			if (reg)
+				fdt_setprop_cell(blob, off, "cache-stash-id",
+					 (*reg * 2) + 32 + 0);
+		}
+#endif
+
+		/* i-side config */
+		isize = (l1cfg1 & 0x7ff) * 1024;
+		inum_ways = ((l1cfg1 >> 11) & 0xff) + 1;
+		iline_size = (((l1cfg1 >> 23) & 0x3) + 1) * 32;
+		inum_sets = isize / (iline_size * inum_ways);
+
+		fdt_setprop_cell(blob, off, "i-cache-block-size", iline_size);
+		fdt_setprop_cell(blob, off, "i-cache-size", isize);
+		fdt_setprop_cell(blob, off, "i-cache-sets", inum_sets);
+
+		off = fdt_node_offset_by_prop_value(blob, off,
+				"device_type", "cpu", 4);
+	}
+
+	ft_fixup_l2cache(blob);
+}
+
+
+void fdt_add_enet_stashing(void *fdt)
+{
+	do_fixup_by_compat(fdt, "gianfar", "bd-stash", NULL, 0, 1);
+
+	do_fixup_by_compat_u32(fdt, "gianfar", "rx-stash-len", 96, 1);
+
+	do_fixup_by_compat_u32(fdt, "gianfar", "rx-stash-idx", 0, 1);
+}
+
+#if defined(CONFIG_SYS_DPAA_FMAN) || defined(CONFIG_SYS_DPAA_PME)
+static void ft_fixup_clks(void *blob, const char *alias, unsigned long freq)
+{
+	const char *path = fdt_get_alias(blob, alias);
+
+	int off = fdt_path_offset(blob, path);
+
+	if (off >= 0) {
+		off = fdt_setprop_cell(blob, off, "clock-frequency", freq);
+		if (off > 0)
+			printf("WARNING enable to set clock-frequency "
+				"for %s: %s\n", alias, fdt_strerror(off));
+	}
+}
+
+static void ft_fixup_dpaa_clks(void *blob)
+{
+	sys_info_t sysinfo;
+
+	get_sys_info(&sysinfo);
+	ft_fixup_clks(blob, "fman0", sysinfo.freqFMan[0]);
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+	ft_fixup_clks(blob, "fman1", sysinfo.freqFMan[1]);
+#endif
+
+#ifdef CONFIG_SYS_DPAA_PME
+	ft_fixup_clks(blob, "pme", sysinfo.freqPME);
+#endif
+}
+#else
+#define ft_fixup_dpaa_clks(x)
+#endif
+
+#ifdef CONFIG_QE
+static void ft_fixup_qe_snum(void *blob)
+{
+	unsigned int svr;
+
+	svr = mfspr(SPRN_SVR);
+	if (SVR_SOC_VER(svr) == SVR_8569_E) {
+		if(IS_SVR_REV(svr, 1, 0))
+			do_fixup_by_compat_u32(blob, "fsl,qe",
+				"fsl,qe-num-snums", 46, 1);
+		else
+			do_fixup_by_compat_u32(blob, "fsl,qe",
+				"fsl,qe-num-snums", 76, 1);
+	}
+}
+#endif
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+	int off;
+	int val;
+	sys_info_t sysinfo;
+
+	/* delete crypto node if not on an E-processor */
+	if (!IS_E_PROCESSOR(get_svr()))
+		fdt_fixup_crypto_node(blob, 0);
+
+	fdt_fixup_ethernet(blob);
+
+	fdt_add_enet_stashing(blob);
+
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+		"timebase-frequency", get_tbclk(), 1);
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+		"bus-frequency", bd->bi_busfreq, 1);
+	get_sys_info(&sysinfo);
+	off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+	while (off != -FDT_ERR_NOTFOUND) {
+		u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
+		val = cpu_to_fdt32(sysinfo.freqProcessor[*reg]);
+		fdt_setprop(blob, off, "clock-frequency", &val, 4);
+		off = fdt_node_offset_by_prop_value(blob, off, "device_type",
+							"cpu", 4);
+	}
+	do_fixup_by_prop_u32(blob, "device_type", "soc", 4,
+		"bus-frequency", bd->bi_busfreq, 1);
+
+	do_fixup_by_compat_u32(blob, "fsl,pq3-localbus",
+		"bus-frequency", gd->lbc_clk, 1);
+	do_fixup_by_compat_u32(blob, "fsl,elbc",
+		"bus-frequency", gd->lbc_clk, 1);
+#ifdef CONFIG_QE
+	ft_qe_setup(blob);
+	ft_fixup_qe_snum(blob);
+#endif
+
+#ifdef CONFIG_SYS_NS16550
+	do_fixup_by_compat_u32(blob, "ns16550",
+		"clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
+#endif
+
+#ifdef CONFIG_CPM2
+	do_fixup_by_compat_u32(blob, "fsl,cpm2-scc-uart",
+		"current-speed", bd->bi_baudrate, 1);
+
+	do_fixup_by_compat_u32(blob, "fsl,cpm2-brg",
+		"clock-frequency", bd->bi_brgfreq, 1);
+#endif
+
+	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+
+#ifdef CONFIG_MP
+	ft_fixup_cpu(blob, (u64)bd->bi_memstart + (u64)bd->bi_memsize);
+#endif
+	ft_fixup_num_cores(blob);
+
+	ft_fixup_cache(blob);
+
+#if defined(CONFIG_FSL_ESDHC)
+	fdt_fixup_esdhc(blob, bd);
+#endif
+
+	ft_fixup_dpaa_clks(blob);
+}
diff --git a/arch/powerpc/cpu/mpc85xx/fixed_ivor.S b/arch/powerpc/cpu/mpc85xx/fixed_ivor.S
new file mode 100644
index 0000000..320cae3
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/fixed_ivor.S
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * Kumar Gala <kumar.gala@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* This file is intended to be included by other asm code since
+ * we will want to execute this on both the primary core when
+ * it does a bootm and the secondary core's that get released
+ * out of the spin table */
+
+#define SET_IVOR(vector_number, vector_offset)	\
+	li	r3,vector_offset@l; 		\
+	mtspr	SPRN_IVOR##vector_number,r3;
+
+#define SET_GIVOR(vector_number, vector_offset)	\
+	li	r3,vector_offset@l; 		\
+	mtspr	SPRN_GIVOR##vector_number,r3;
+
+	SET_IVOR(0, 0x020) /* Critical Input */
+	SET_IVOR(1, 0x000) /* Machine Check */
+	SET_IVOR(2, 0x060) /* Data Storage */
+	SET_IVOR(3, 0x080) /* Instruction Storage */
+	SET_IVOR(4, 0x0a0) /* External Input */
+	SET_IVOR(5, 0x0c0) /* Alignment */
+	SET_IVOR(6, 0x0e0) /* Program */
+	SET_IVOR(7, 0x100) /* FP Unavailable */
+	SET_IVOR(8, 0x120) /* System Call */
+	SET_IVOR(9, 0x140) /* Auxiliary Processor Unavailable */
+	SET_IVOR(10, 0x160) /* Decrementer */
+	SET_IVOR(11, 0x180) /* Fixed Interval Timer */
+	SET_IVOR(12, 0x1a0) /* Watchdog Timer */
+	SET_IVOR(13, 0x1c0) /* Data TLB Error */
+	SET_IVOR(14, 0x1e0) /* Instruction TLB Error */
+	SET_IVOR(15, 0x040) /* Debug */
+
+/* e500v1 & e500v2 only */
+#ifndef CONFIG_E500MC
+	SET_IVOR(32, 0x200) /* SPE Unavailable */
+	SET_IVOR(33, 0x220) /* Embedded FP Data */
+	SET_IVOR(34, 0x240) /* Embedded FP Round */
+#endif
+
+	SET_IVOR(35, 0x260) /* Performance monitor */
+
+/* e500mc only */
+#ifdef CONFIG_E500MC
+	SET_IVOR(36, 0x280) /* Processor doorbell */
+	SET_IVOR(37, 0x2a0) /* Processor doorbell critical */
+	SET_IVOR(38, 0x2c0) /* Guest Processor doorbell */
+	SET_IVOR(39, 0x2e0) /* Guest Processor critical & machine check */
+	SET_IVOR(40, 0x300) /* Hypervisor system call */
+	SET_IVOR(41, 0x320) /* Hypervisor Priviledge */
+
+	SET_GIVOR(2, 0x060) /* Guest Data Storage */
+	SET_GIVOR(3, 0x080) /* Guest Instruction Storage */
+	SET_GIVOR(4, 0x0a0) /* Guest External Input */
+	SET_GIVOR(8, 0x120) /* Guest System Call */
+	SET_GIVOR(13, 0x1c0) /* Guest Data TLB Error */
+	SET_GIVOR(14, 0x1e0) /* Guest Instruction TLB Error */
+#endif
diff --git a/arch/powerpc/cpu/mpc85xx/interrupts.c b/arch/powerpc/cpu/mpc85xx/interrupts.c
new file mode 100644
index 0000000..409367d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/interrupts.c
@@ -0,0 +1,110 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002 (440 port)
+ * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com
+ *
+ * (C) Copyright 2003 Motorola Inc. (MPC85xx port)
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+int interrupt_init_cpu(unsigned int *decrementer_count)
+{
+	ccsr_pic_t __iomem *pic = (void *)CONFIG_SYS_MPC85xx_PIC_ADDR;
+
+	out_be32(&pic->gcr, MPC85xx_PICGCR_RST);
+	while (in_be32(&pic->gcr) & MPC85xx_PICGCR_RST)
+		;
+	out_be32(&pic->gcr, MPC85xx_PICGCR_M);
+	in_be32(&pic->gcr);
+
+	*decrementer_count = get_tbclk() / CONFIG_SYS_HZ;
+
+	/* PIE is same as DIE, dec interrupt enable */
+	mtspr(SPRN_TCR, TCR_PIE);
+
+#ifdef CONFIG_INTERRUPTS
+	pic->iivpr1 = 0x810001;	/* 50220 enable ecm interrupts */
+	debug("iivpr1@%x = %x\n", (uint)&pic->iivpr1, pic->iivpr1);
+
+	pic->iivpr2 = 0x810002;	/* 50240 enable ddr interrupts */
+	debug("iivpr2@%x = %x\n", (uint)&pic->iivpr2, pic->iivpr2);
+
+	pic->iivpr3 = 0x810003;	/* 50260 enable lbc interrupts */
+	debug("iivpr3@%x = %x\n", (uint)&pic->iivpr3, pic->iivpr3);
+
+#ifdef CONFIG_PCI1
+	pic->iivpr8 = 0x810008;	/* enable pci1 interrupts */
+	debug("iivpr8@%x = %x\n", (uint)&pic->iivpr8, pic->iivpr8);
+#endif
+#if defined(CONFIG_PCI2) || defined(CONFIG_PCIE2)
+	pic->iivpr9 = 0x810009;	/* enable pci1 interrupts */
+	debug("iivpr9@%x = %x\n", (uint)&pic->iivpr9, pic->iivpr9);
+#endif
+#ifdef CONFIG_PCIE1
+	pic->iivpr10 = 0x81000a;	/* enable pcie1 interrupts */
+	debug("iivpr10@%x = %x\n", (uint)&pic->iivpr10, pic->iivpr10);
+#endif
+#ifdef CONFIG_PCIE3
+	pic->iivpr11 = 0x81000b;	/* enable pcie3 interrupts */
+	debug("iivpr11@%x = %x\n", (uint)&pic->iivpr11, pic->iivpr11);
+#endif
+
+	pic->ctpr=0;		/* 40080 clear current task priority register */
+#endif
+
+	return (0);
+}
+
+/* Install and free a interrupt handler. Not implemented yet. */
+
+void
+irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
+{
+	return;
+}
+
+void
+irq_free_handler(int vec)
+{
+	return;
+}
+
+void timer_interrupt_cpu(struct pt_regs *regs)
+{
+	/* PIS is same as DIS, dec interrupt status */
+	mtspr(SPRN_TSR, TSR_PIS);
+}
+
+#if defined(CONFIG_CMD_IRQ)
+/* irqinfo - print information about PCI devices,not implemented. */
+int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	return 0;
+}
+#endif
diff --git a/arch/powerpc/cpu/mpc85xx/mp.c b/arch/powerpc/cpu/mpc85xx/mp.c
new file mode 100644
index 0000000..826bf32
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/mp.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <ioports.h>
+#include <lmb.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/fsl_law.h>
+#include "mp.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+u32 get_my_id()
+{
+	return mfspr(SPRN_PIR);
+}
+
+int cpu_reset(int nr)
+{
+	volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
+	out_be32(&pic->pir, 1 << nr);
+	/* the dummy read works around an errata on early 85xx MP PICs */
+	(void)in_be32(&pic->pir);
+	out_be32(&pic->pir, 0x0);
+
+	return 0;
+}
+
+int cpu_status(int nr)
+{
+	u32 *table, id = get_my_id();
+
+	if (nr == id) {
+		table = (u32 *)get_spin_virt_addr();
+		printf("table base @ 0x%p\n", table);
+	} else {
+		table = (u32 *)get_spin_virt_addr() + nr * NUM_BOOT_ENTRY;
+		printf("Running on cpu %d\n", id);
+		printf("\n");
+		printf("table @ 0x%p\n", table);
+		printf("   addr - 0x%08x\n", table[BOOT_ENTRY_ADDR_LOWER]);
+		printf("   pir  - 0x%08x\n", table[BOOT_ENTRY_PIR]);
+		printf("   r3   - 0x%08x\n", table[BOOT_ENTRY_R3_LOWER]);
+		printf("   r6   - 0x%08x\n", table[BOOT_ENTRY_R6_LOWER]);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_FSL_CORENET
+int cpu_disable(int nr)
+{
+	volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+
+	setbits_be32(&gur->coredisrl, 1 << nr);
+
+	return 0;
+}
+#else
+int cpu_disable(int nr)
+{
+	volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+
+	switch (nr) {
+	case 0:
+		setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_CPU0);
+		break;
+	case 1:
+		setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_CPU1);
+		break;
+	default:
+		printf("Invalid cpu number for disable %d\n", nr);
+		return 1;
+	}
+
+	return 0;
+}
+#endif
+
+static u8 boot_entry_map[4] = {
+	0,
+	BOOT_ENTRY_PIR,
+	BOOT_ENTRY_R3_LOWER,
+	BOOT_ENTRY_R6_LOWER,
+};
+
+int cpu_release(int nr, int argc, char *argv[])
+{
+	u32 i, val, *table = (u32 *)get_spin_virt_addr() + nr * NUM_BOOT_ENTRY;
+	u64 boot_addr;
+
+	if (nr == get_my_id()) {
+		printf("Invalid to release the boot core.\n\n");
+		return 1;
+	}
+
+	if (argc != 4) {
+		printf("Invalid number of arguments to release.\n\n");
+		return 1;
+	}
+
+	boot_addr = simple_strtoull(argv[0], NULL, 16);
+
+	/* handle pir, r3, r6 */
+	for (i = 1; i < 4; i++) {
+		if (argv[i][0] != '-') {
+			u8 entry = boot_entry_map[i];
+			val = simple_strtoul(argv[i], NULL, 16);
+			table[entry] = val;
+		}
+	}
+
+	table[BOOT_ENTRY_ADDR_UPPER] = (u32)(boot_addr >> 32);
+
+	/* ensure all table updates complete before final address write */
+	eieio();
+
+	table[BOOT_ENTRY_ADDR_LOWER] = (u32)(boot_addr & 0xffffffff);
+
+	return 0;
+}
+
+u32 determine_mp_bootpg(void)
+{
+	/* if we have 4G or more of memory, put the boot page at 4Gb-4k */
+	if ((u64)gd->ram_size > 0xfffff000)
+		return (0xfffff000);
+
+	return (gd->ram_size - 4096);
+}
+
+ulong get_spin_phys_addr(void)
+{
+	extern ulong __secondary_start_page;
+	extern ulong __spin_table;
+
+	return (determine_mp_bootpg() +
+		(ulong)&__spin_table - (ulong)&__secondary_start_page);
+}
+
+ulong get_spin_virt_addr(void)
+{
+	extern ulong __secondary_start_page;
+	extern ulong __spin_table;
+
+	return (CONFIG_BPTR_VIRT_ADDR +
+		(ulong)&__spin_table - (ulong)&__secondary_start_page);
+}
+
+#ifdef CONFIG_FSL_CORENET
+static void plat_mp_up(unsigned long bootpg)
+{
+	u32 up, cpu_up_mask, whoami;
+	u32 *table = (u32 *)get_spin_virt_addr();
+	volatile ccsr_gur_t *gur;
+	volatile ccsr_local_t *ccm;
+	volatile ccsr_rcpm_t *rcpm;
+	volatile ccsr_pic_t *pic;
+	int timeout = 10;
+	u32 nr_cpus;
+	struct law_entry e;
+
+	gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	ccm = (void *)(CONFIG_SYS_FSL_CORENET_CCM_ADDR);
+	rcpm = (void *)(CONFIG_SYS_FSL_CORENET_RCPM_ADDR);
+	pic = (void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
+
+	nr_cpus = ((in_be32(&pic->frr) >> 8) & 0xff) + 1;
+
+	whoami = in_be32(&pic->whoami);
+	cpu_up_mask = 1 << whoami;
+	out_be32(&ccm->bstrl, bootpg);
+
+	e = find_law(bootpg);
+	out_be32(&ccm->bstrar, LAW_EN | e.trgt_id << 20 | LAW_SIZE_4K);
+
+	/* readback to sync write */
+	in_be32(&ccm->bstrar);
+
+	/* disable time base at the platform */
+	out_be32(&rcpm->ctbenrl, cpu_up_mask);
+
+	/* release the hounds */
+	up = ((1 << nr_cpus) - 1);
+	out_be32(&gur->brrl, up);
+
+	/* wait for everyone */
+	while (timeout) {
+		int i;
+		for (i = 0; i < nr_cpus; i++) {
+			if (table[i * NUM_BOOT_ENTRY + BOOT_ENTRY_ADDR_LOWER])
+				cpu_up_mask |= (1 << i);
+		};
+
+		if ((cpu_up_mask & up) == up)
+			break;
+
+		udelay(100);
+		timeout--;
+	}
+
+	if (timeout == 0)
+		printf("CPU up timeout. CPU up mask is %x should be %x\n",
+			cpu_up_mask, up);
+
+	/* enable time base at the platform */
+	out_be32(&rcpm->ctbenrl, 0);
+	mtspr(SPRN_TBWU, 0);
+	mtspr(SPRN_TBWL, 0);
+	out_be32(&rcpm->ctbenrl, (1 << nr_cpus) - 1);
+
+#ifdef CONFIG_MPC8xxx_DISABLE_BPTR
+	/*
+	 * Disabling Boot Page Translation allows the memory region 0xfffff000
+	 * to 0xffffffff to be used normally.  Leaving Boot Page Translation
+	 * enabled remaps 0xfffff000 to SDRAM which makes that memory region
+	 * unusable for normal operation but it does allow OSes to easily
+	 * reset a processor core to put it back into U-Boot's spinloop.
+	 */
+	clrbits_be32(&ecm->bptr, 0x80000000);
+#endif
+}
+#else
+static void plat_mp_up(unsigned long bootpg)
+{
+	u32 up, cpu_up_mask, whoami;
+	u32 *table = (u32 *)get_spin_virt_addr();
+	volatile u32 bpcr;
+	volatile ccsr_local_ecm_t *ecm = (void *)(CONFIG_SYS_MPC85xx_ECM_ADDR);
+	volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
+	u32 devdisr;
+	int timeout = 10;
+
+	whoami = in_be32(&pic->whoami);
+	out_be32(&ecm->bptr, 0x80000000 | (bootpg >> 12));
+
+	/* disable time base at the platform */
+	devdisr = in_be32(&gur->devdisr);
+	if (whoami)
+		devdisr |= MPC85xx_DEVDISR_TB0;
+	else
+		devdisr |= MPC85xx_DEVDISR_TB1;
+	out_be32(&gur->devdisr, devdisr);
+
+	/* release the hounds */
+	up = ((1 << cpu_numcores()) - 1);
+	bpcr = in_be32(&ecm->eebpcr);
+	bpcr |= (up << 24);
+	out_be32(&ecm->eebpcr, bpcr);
+	asm("sync; isync; msync");
+
+	cpu_up_mask = 1 << whoami;
+	/* wait for everyone */
+	while (timeout) {
+		int i;
+		for (i = 0; i < cpu_numcores(); i++) {
+			if (table[i * NUM_BOOT_ENTRY + BOOT_ENTRY_ADDR_LOWER])
+				cpu_up_mask |= (1 << i);
+		};
+
+		if ((cpu_up_mask & up) == up)
+			break;
+
+		udelay(100);
+		timeout--;
+	}
+
+	if (timeout == 0)
+		printf("CPU up timeout. CPU up mask is %x should be %x\n",
+			cpu_up_mask, up);
+
+	/* enable time base at the platform */
+	if (whoami)
+		devdisr |= MPC85xx_DEVDISR_TB1;
+	else
+		devdisr |= MPC85xx_DEVDISR_TB0;
+	out_be32(&gur->devdisr, devdisr);
+	mtspr(SPRN_TBWU, 0);
+	mtspr(SPRN_TBWL, 0);
+
+	devdisr &= ~(MPC85xx_DEVDISR_TB0 | MPC85xx_DEVDISR_TB1);
+	out_be32(&gur->devdisr, devdisr);
+
+#ifdef CONFIG_MPC8xxx_DISABLE_BPTR
+	/*
+	 * Disabling Boot Page Translation allows the memory region 0xfffff000
+	 * to 0xffffffff to be used normally.  Leaving Boot Page Translation
+	 * enabled remaps 0xfffff000 to SDRAM which makes that memory region
+	 * unusable for normal operation but it does allow OSes to easily
+	 * reset a processor core to put it back into U-Boot's spinloop.
+	 */
+	clrbits_be32(&ecm->bptr, 0x80000000);
+#endif
+}
+#endif
+
+void cpu_mp_lmb_reserve(struct lmb *lmb)
+{
+	u32 bootpg = determine_mp_bootpg();
+
+	lmb_reserve(lmb, bootpg, 4096);
+}
+
+void setup_mp(void)
+{
+	extern ulong __secondary_start_page;
+	extern ulong __bootpg_addr;
+	ulong fixup = (ulong)&__secondary_start_page;
+	u32 bootpg = determine_mp_bootpg();
+
+	/* Store the bootpg's SDRAM address for use by secondary CPU cores */
+	__bootpg_addr = bootpg;
+
+	/* look for the tlb covering the reset page, there better be one */
+	int i = find_tlb_idx((void *)CONFIG_BPTR_VIRT_ADDR, 1);
+
+	/* we found a match */
+	if (i != -1) {
+		/* map reset page to bootpg so we can copy code there */
+		disable_tlb(i);
+
+		set_tlb(1, CONFIG_BPTR_VIRT_ADDR, bootpg, /* tlb, epn, rpn */
+			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, /* perms, wimge */
+			0, i, BOOKE_PAGESZ_4K, 1); /* ts, esel, tsize, iprot */
+
+		memcpy((void *)CONFIG_BPTR_VIRT_ADDR, (void *)fixup, 4096);
+
+		plat_mp_up(bootpg);
+	} else {
+		puts("WARNING: No reset page TLB. "
+			"Skipping secondary core setup\n");
+	}
+}
diff --git a/arch/powerpc/cpu/mpc85xx/mp.h b/arch/powerpc/cpu/mpc85xx/mp.h
new file mode 100644
index 0000000..3422cc1
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/mp.h
@@ -0,0 +1,21 @@
+#ifndef __MPC85XX_MP_H_
+#define __MPC85XX_MP_H_
+
+#include <asm/mp.h>
+
+ulong get_spin_phys_addr(void);
+ulong get_spin_virt_addr(void);
+u32 get_my_id(void);
+
+#define BOOT_ENTRY_ADDR_UPPER	0
+#define BOOT_ENTRY_ADDR_LOWER	1
+#define BOOT_ENTRY_R3_UPPER	2
+#define BOOT_ENTRY_R3_LOWER	3
+#define BOOT_ENTRY_RESV		4
+#define BOOT_ENTRY_PIR		5
+#define BOOT_ENTRY_R6_UPPER	6
+#define BOOT_ENTRY_R6_LOWER	7
+#define NUM_BOOT_ENTRY		8
+#define SIZE_BOOT_ENTRY		(NUM_BOOT_ENTRY * sizeof(u32))
+
+#endif
diff --git a/arch/powerpc/cpu/mpc85xx/mpc8536_serdes.c b/arch/powerpc/cpu/mpc85xx/mpc8536_serdes.c
new file mode 100644
index 0000000..cb6a6f0
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/mpc8536_serdes.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2008 Freescale Semicondutor, Inc.
+ *	Dave Liu <daveliu@freescale.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.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+
+/* PORDEVSR register */
+#define GUTS_PORDEVSR_OFFS		0xc
+#define GUTS_PORDEVSR_SERDES2_IO_SEL	0x38000000
+#define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT	27
+
+/* SerDes CR0 register */
+#define	FSL_SRDSCR0_OFFS	0x0
+#define FSL_SRDSCR0_TXEQA_MASK	0x00007000
+#define FSL_SRDSCR0_TXEQA_SGMII	0x00004000
+#define FSL_SRDSCR0_TXEQA_SATA	0x00001000
+#define FSL_SRDSCR0_TXEQE_MASK	0x00000700
+#define FSL_SRDSCR0_TXEQE_SGMII	0x00000400
+#define FSL_SRDSCR0_TXEQE_SATA	0x00000100
+
+/* SerDes CR1 register */
+#define FSL_SRDSCR1_OFFS	0x4
+#define FSL_SRDSCR1_LANEA_MASK	0x80200000
+#define FSL_SRDSCR1_LANEA_OFF	0x80200000
+#define FSL_SRDSCR1_LANEE_MASK	0x08020000
+#define FSL_SRDSCR1_LANEE_OFF	0x08020000
+
+/* SerDes CR2 register */
+#define FSL_SRDSCR2_OFFS	0x8
+#define FSL_SRDSCR2_EICA_MASK	0x00001f00
+#define FSL_SRDSCR2_EICA_SGMII	0x00000400
+#define FSL_SRDSCR2_EICA_SATA	0x00001400
+#define FSL_SRDSCR2_EICE_MASK	0x0000001f
+#define FSL_SRDSCR2_EICE_SGMII	0x00000004
+#define FSL_SRDSCR2_EICE_SATA	0x00000014
+
+/* SerDes CR3 register */
+#define FSL_SRDSCR3_OFFS	0xc
+#define FSL_SRDSCR3_LANEA_MASK	0x3f000700
+#define FSL_SRDSCR3_LANEA_SGMII	0x00000000
+#define FSL_SRDSCR3_LANEA_SATA	0x15000500
+#define FSL_SRDSCR3_LANEE_MASK	0x003f0007
+#define FSL_SRDSCR3_LANEE_SGMII	0x00000000
+#define FSL_SRDSCR3_LANEE_SATA	0x00150005
+
+void fsl_serdes_init(void)
+{
+	void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR;
+	u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS);
+	u32 srds2_io_sel;
+	u32 tmp;
+
+	/* parse the SRDS2_IO_SEL of PORDEVSR */
+	srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL)
+		       >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT;
+
+	switch (srds2_io_sel) {
+	case 1:	/* Lane A - SATA1, Lane E - SATA2 */
+		/* CR 0 */
+		tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+		tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+		tmp |= FSL_SRDSCR0_TXEQA_SATA;
+		tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
+		tmp |= FSL_SRDSCR0_TXEQE_SATA;
+		out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+		/* CR 1 */
+		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+		tmp &= ~FSL_SRDSCR1_LANEA_MASK;
+		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+		/* CR 2 */
+		tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+		tmp &= ~FSL_SRDSCR2_EICA_MASK;
+		tmp |= FSL_SRDSCR2_EICA_SATA;
+		tmp &= ~FSL_SRDSCR2_EICE_MASK;
+		tmp |= FSL_SRDSCR2_EICE_SATA;
+		out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+		/* CR 3 */
+		tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+		tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+		tmp |= FSL_SRDSCR3_LANEA_SATA;
+		tmp &= ~FSL_SRDSCR3_LANEE_MASK;
+		tmp |= FSL_SRDSCR3_LANEE_SATA;
+		out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+		break;
+	case 3: /* Lane A - SATA1, Lane E - disabled */
+		/* CR 0 */
+		tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+		tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+		tmp |= FSL_SRDSCR0_TXEQA_SATA;
+		out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+		/* CR 1 */
+		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+		tmp |= FSL_SRDSCR1_LANEE_OFF;
+		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+		/* CR 2 */
+		tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+		tmp &= ~FSL_SRDSCR2_EICA_MASK;
+		tmp |= FSL_SRDSCR2_EICA_SATA;
+		out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+		/* CR 3 */
+		tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+		tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+		tmp |= FSL_SRDSCR3_LANEA_SATA;
+		out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+		break;
+	case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
+		/* CR 0 */
+		tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+		tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+		tmp |= FSL_SRDSCR0_TXEQA_SGMII;
+		tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
+		tmp |= FSL_SRDSCR0_TXEQE_SGMII;
+		out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+		/* CR 1 */
+		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+		tmp &= ~FSL_SRDSCR1_LANEA_MASK;
+		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+		/* CR 2 */
+		tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+		tmp &= ~FSL_SRDSCR2_EICA_MASK;
+		tmp |= FSL_SRDSCR2_EICA_SGMII;
+		tmp &= ~FSL_SRDSCR2_EICE_MASK;
+		tmp |= FSL_SRDSCR2_EICE_SGMII;
+		out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+		/* CR 3 */
+		tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+		tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+		tmp |= FSL_SRDSCR3_LANEA_SGMII;
+		tmp &= ~FSL_SRDSCR3_LANEE_MASK;
+		tmp |= FSL_SRDSCR3_LANEE_SGMII;
+		out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+		break;
+	case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
+		/* CR 0 */
+		tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+		tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+		tmp |= FSL_SRDSCR0_TXEQA_SGMII;
+		out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+		/* CR 1 */
+		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+		tmp |= FSL_SRDSCR1_LANEE_OFF;
+		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+		/* CR 2 */
+		tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+		tmp &= ~FSL_SRDSCR2_EICA_MASK;
+		tmp |= FSL_SRDSCR2_EICA_SGMII;
+		out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+		/* CR 3 */
+		tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+		tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+		tmp |= FSL_SRDSCR3_LANEA_SGMII;
+		out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+		break;
+	case 7: /* Lane A - disabled, Lane E - disabled */
+		/* CR 1 */
+		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+		tmp &= ~FSL_SRDSCR1_LANEA_MASK;
+		tmp |= FSL_SRDSCR1_LANEA_OFF;
+		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+		tmp |= FSL_SRDSCR1_LANEE_OFF;
+		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+		break;
+	default:
+		break;
+	}
+}
diff --git a/arch/powerpc/cpu/mpc85xx/pci.c b/arch/powerpc/cpu/mpc85xx/pci.c
new file mode 100644
index 0000000..75d2716
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/pci.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2004 Freescale Semiconductor.
+ * Copyright (C) 2003 Motorola Inc.
+ * Xianghua Xiao (x.xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * PCI Configuration space access support for MPC85xx PCI Bridge
+ */
+#include <common.h>
+#include <asm/cpm_85xx.h>
+#include <pci.h>
+
+#if !defined(CONFIG_FSL_PCI_INIT)
+
+#ifndef CONFIG_SYS_PCI1_MEM_BUS
+#define CONFIG_SYS_PCI1_MEM_BUS CONFIG_SYS_PCI1_MEM_BASE
+#endif
+
+#ifndef CONFIG_SYS_PCI1_IO_BUS
+#define CONFIG_SYS_PCI1_IO_BUS CONFIG_SYS_PCI1_IO_BASE
+#endif
+
+#ifndef CONFIG_SYS_PCI2_MEM_BUS
+#define CONFIG_SYS_PCI2_MEM_BUS CONFIG_SYS_PCI2_MEM_BASE
+#endif
+
+#ifndef CONFIG_SYS_PCI2_IO_BUS
+#define CONFIG_SYS_PCI2_IO_BUS CONFIG_SYS_PCI2_IO_BASE
+#endif
+
+static struct pci_controller *pci_hose;
+
+void
+pci_mpc85xx_init(struct pci_controller *board_hose)
+{
+	u16 reg16;
+	u32 dev;
+
+	volatile ccsr_pcix_t *pcix = (void *)(CONFIG_SYS_MPC85xx_PCIX_ADDR);
+#ifdef CONFIG_MPC85XX_PCI2
+	volatile ccsr_pcix_t *pcix2 = (void *)(CONFIG_SYS_MPC85xx_PCIX2_ADDR);
+#endif
+	volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	struct pci_controller * hose;
+
+	pci_hose = board_hose;
+
+	hose = &pci_hose[0];
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	pci_setup_indirect(hose,
+			   (CONFIG_SYS_IMMR+0x8000),
+			   (CONFIG_SYS_IMMR+0x8004));
+
+	/*
+	 * Hose scan.
+	 */
+	dev = PCI_BDF(hose->first_busno, 0, 0);
+	pci_hose_read_config_word (hose, dev, PCI_COMMAND, &reg16);
+	reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
+
+	/*
+	 * Clear non-reserved bits in status register.
+	 */
+	pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
+
+	if (!(gur->pordevsr & MPC85xx_PORDEVSR_PCI1)) {
+		/* PCI-X init */
+		if (CONFIG_SYS_CLK_FREQ < 66000000)
+			printf("PCI-X will only work at 66 MHz\n");
+
+		reg16 = PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ
+			| PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E;
+		pci_hose_write_config_word(hose, dev, PCIX_COMMAND, reg16);
+	}
+
+	pcix->potar1   = (CONFIG_SYS_PCI1_MEM_BUS >> 12) & 0x000fffff;
+	pcix->potear1  = 0x00000000;
+	pcix->powbar1  = (CONFIG_SYS_PCI1_MEM_PHYS >> 12) & 0x000fffff;
+	pcix->powbear1 = 0x00000000;
+	pcix->powar1 = (POWAR_EN | POWAR_MEM_READ |
+			POWAR_MEM_WRITE | (__ilog2(CONFIG_SYS_PCI1_MEM_SIZE) - 1));
+
+	pcix->potar2  = (CONFIG_SYS_PCI1_IO_BUS >> 12) & 0x000fffff;
+	pcix->potear2  = 0x00000000;
+	pcix->powbar2  = (CONFIG_SYS_PCI1_IO_PHYS >> 12) & 0x000fffff;
+	pcix->powbear2 = 0x00000000;
+	pcix->powar2 = (POWAR_EN | POWAR_IO_READ |
+			POWAR_IO_WRITE | (__ilog2(CONFIG_SYS_PCI1_IO_SIZE) - 1));
+
+	pcix->pitar1 = 0x00000000;
+	pcix->piwbar1 = 0x00000000;
+	pcix->piwar1 = (PIWAR_EN | PIWAR_PF | PIWAR_LOCAL |
+			PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_MEM_2G);
+
+	pcix->powar3 = 0;
+	pcix->powar4 = 0;
+	pcix->piwar2 = 0;
+	pcix->piwar3 = 0;
+
+	pci_set_region(hose->regions + 0,
+		       CONFIG_SYS_PCI1_MEM_BUS,
+		       CONFIG_SYS_PCI1_MEM_PHYS,
+		       CONFIG_SYS_PCI1_MEM_SIZE,
+		       PCI_REGION_MEM);
+
+	pci_set_region(hose->regions + 1,
+		       CONFIG_SYS_PCI1_IO_BUS,
+		       CONFIG_SYS_PCI1_IO_PHYS,
+		       CONFIG_SYS_PCI1_IO_SIZE,
+		       PCI_REGION_IO);
+
+	hose->region_count = 2;
+
+	pci_register_hose(hose);
+
+#if defined(CONFIG_MPC8555CDS) || defined(CONFIG_MPC8541CDS)
+	/*
+	 * This is a SW workaround for an apparent HW problem
+	 * in the PCI controller on the MPC85555/41 CDS boards.
+	 * The first config cycle must be to a valid, known
+	 * device on the PCI bus in order to trick the PCI
+	 * controller state machine into a known valid state.
+	 * Without this, the first config cycle has the chance
+	 * of hanging the controller permanently, just leaving
+	 * it in a semi-working state, or leaving it working.
+	 *
+	 * Pick on the Tundra, Device 17, to get it right.
+	 */
+	{
+		u8 header_type;
+
+		pci_hose_read_config_byte(hose,
+					  PCI_BDF(0,BRIDGE_ID,0),
+					  PCI_HEADER_TYPE,
+					  &header_type);
+	}
+#endif
+
+	hose->last_busno = pci_hose_scan(hose);
+
+#ifdef CONFIG_MPC85XX_PCI2
+	hose = &pci_hose[1];
+
+	hose->first_busno = pci_hose[0].last_busno + 1;
+	hose->last_busno = 0xff;
+
+	pci_setup_indirect(hose,
+			   (CONFIG_SYS_IMMR+0x9000),
+			   (CONFIG_SYS_IMMR+0x9004));
+
+	dev = PCI_BDF(hose->first_busno, 0, 0);
+	pci_hose_read_config_word (hose, dev, PCI_COMMAND, &reg16);
+	reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
+
+	/*
+	 * Clear non-reserved bits in status register.
+	 */
+	pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
+
+	pcix2->potar1   = (CONFIG_SYS_PCI2_MEM_BUS >> 12) & 0x000fffff;
+	pcix2->potear1  = 0x00000000;
+	pcix2->powbar1  = (CONFIG_SYS_PCI2_MEM_PHYS >> 12) & 0x000fffff;
+	pcix2->powbear1 = 0x00000000;
+	pcix2->powar1 = (POWAR_EN | POWAR_MEM_READ |
+			POWAR_MEM_WRITE | (__ilog2(CONFIG_SYS_PCI2_MEM_SIZE) - 1));
+
+	pcix2->potar2  = (CONFIG_SYS_PCI2_IO_BUS >> 12) & 0x000fffff;
+	pcix2->potear2  = 0x00000000;
+	pcix2->powbar2  = (CONFIG_SYS_PCI2_IO_PHYS >> 12) & 0x000fffff;
+	pcix2->powbear2 = 0x00000000;
+	pcix2->powar2 = (POWAR_EN | POWAR_IO_READ |
+			POWAR_IO_WRITE | (__ilog2(CONFIG_SYS_PCI2_IO_SIZE) - 1));
+
+	pcix2->pitar1 = 0x00000000;
+	pcix2->piwbar1 = 0x00000000;
+	pcix2->piwar1 = (PIWAR_EN | PIWAR_PF | PIWAR_LOCAL |
+			PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_MEM_2G);
+
+	pcix2->powar3 = 0;
+	pcix2->powar4 = 0;
+	pcix2->piwar2 = 0;
+	pcix2->piwar3 = 0;
+
+	pci_set_region(hose->regions + 0,
+		       CONFIG_SYS_PCI2_MEM_BUS,
+		       CONFIG_SYS_PCI2_MEM_PHYS,
+		       CONFIG_SYS_PCI2_MEM_SIZE,
+		       PCI_REGION_MEM);
+
+	pci_set_region(hose->regions + 1,
+		       CONFIG_SYS_PCI2_IO_BUS,
+		       CONFIG_SYS_PCI2_IO_PHYS,
+		       CONFIG_SYS_PCI2_IO_SIZE,
+		       PCI_REGION_IO);
+
+	hose->region_count = 2;
+
+	/*
+	 * Hose scan.
+	 */
+	pci_register_hose(hose);
+
+	hose->last_busno = pci_hose_scan(hose);
+#endif
+}
+#endif /* !CONFIG_FSL_PCI_INIT */
diff --git a/arch/powerpc/cpu/mpc85xx/qe_io.c b/arch/powerpc/cpu/mpc85xx/qe_io.c
new file mode 100644
index 0000000..72a29b7
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/qe_io.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006 Freescale Semiconductor, Inc.
+ *
+ * Dave Liu <daveliu@freescale.com>
+ * based on source code of Shlomi Gridish
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "common.h"
+#include "asm/errno.h"
+#include "asm/io.h"
+#include "asm/immap_85xx.h"
+
+#if defined(CONFIG_QE)
+#define	NUM_OF_PINS	32
+void qe_config_iopin(u8 port, u8 pin, int dir, int open_drain, int assign)
+{
+	u32			pin_2bit_mask;
+	u32			pin_2bit_dir;
+	u32			pin_2bit_assign;
+	u32			pin_1bit_mask;
+	u32			tmp_val;
+	volatile ccsr_gur_t	*gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+	volatile par_io_t	*par_io = (volatile par_io_t *)
+						&(gur->qe_par_io);
+
+	/* Caculate pin location and 2bit mask and dir */
+	pin_2bit_mask = (u32)(0x3 << (NUM_OF_PINS-(pin%(NUM_OF_PINS/2)+1)*2));
+	pin_2bit_dir = (u32)(dir << (NUM_OF_PINS-(pin%(NUM_OF_PINS/2)+1)*2));
+
+	/* Setup the direction */
+	tmp_val = (pin > (NUM_OF_PINS/2) - 1) ? \
+		in_be32(&par_io[port].cpdir2) :
+		in_be32(&par_io[port].cpdir1);
+
+	if (pin > (NUM_OF_PINS/2) -1) {
+		out_be32(&par_io[port].cpdir2, ~pin_2bit_mask & tmp_val);
+		out_be32(&par_io[port].cpdir2, pin_2bit_dir | tmp_val);
+	} else {
+		out_be32(&par_io[port].cpdir1, ~pin_2bit_mask & tmp_val);
+		out_be32(&par_io[port].cpdir1, pin_2bit_dir | tmp_val);
+	}
+
+	/* Calculate pin location for 1bit mask */
+	pin_1bit_mask = (u32)(1 << (NUM_OF_PINS - (pin+1)));
+
+	/* Setup the open drain */
+	tmp_val = in_be32(&par_io[port].cpodr);
+	if (open_drain)
+		out_be32(&par_io[port].cpodr, pin_1bit_mask | tmp_val);
+	else
+		out_be32(&par_io[port].cpodr, ~pin_1bit_mask & tmp_val);
+
+	/* Setup the assignment */
+	tmp_val = (pin > (NUM_OF_PINS/2) - 1) ?
+		in_be32(&par_io[port].cppar2):
+		in_be32(&par_io[port].cppar1);
+	pin_2bit_assign = (u32)(assign
+				<< (NUM_OF_PINS - (pin%(NUM_OF_PINS/2)+1)*2));
+
+	/* Clear and set 2 bits mask */
+	if (pin > (NUM_OF_PINS/2) - 1) {
+		out_be32(&par_io[port].cppar2, ~pin_2bit_mask & tmp_val);
+		out_be32(&par_io[port].cppar2, pin_2bit_assign | tmp_val);
+	} else {
+		out_be32(&par_io[port].cppar1, ~pin_2bit_mask & tmp_val);
+		out_be32(&par_io[port].cppar1, pin_2bit_assign | tmp_val);
+	}
+}
+
+#endif /* CONFIG_QE */
diff --git a/arch/powerpc/cpu/mpc85xx/release.S b/arch/powerpc/cpu/mpc85xx/release.S
new file mode 100644
index 0000000..0b5b9da
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/release.S
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Kumar Gala <kumar.gala@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <mpc85xx.h>
+#include <version.h>
+
+#define _LINUX_CONFIG_H 1	/* avoid reading Linux autoconf.h file	*/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+/* To boot secondary cpus, we need a place for them to start up.
+ * Normally, they start at 0xfffffffc, but that's usually the
+ * firmware, and we don't want to have to run the firmware again.
+ * Instead, the primary cpu will set the BPTR to point here to
+ * this page.  We then set up the core, and head to
+ * start_secondary.  Note that this means that the code below
+ * must never exceed 1023 instructions (the branch at the end
+ * would then be the 1024th).
+ */
+	.globl	__secondary_start_page
+	.align	12
+__secondary_start_page:
+/* First do some preliminary setup */
+	lis	r3, HID0_EMCP@h		/* enable machine check */
+#ifndef CONFIG_E500MC
+	ori	r3,r3,HID0_TBEN@l	/* enable Timebase */
+#endif
+#ifdef CONFIG_PHYS_64BIT
+	ori	r3,r3,HID0_ENMAS7@l	/* enable MAS7 updates */
+#endif
+	mtspr	SPRN_HID0,r3
+
+#ifndef CONFIG_E500MC
+	li	r3,(HID1_ASTME|HID1_ABE)@l	/* Addr streaming & broadcast */
+	mfspr   r0,PVR
+	andi.	r0,r0,0xff
+	cmpwi	r0,0x50@l	/* if we are rev 5.0 or greater set MBDD */
+	blt 1f
+	/* Set MBDD bit also */
+	ori r3, r3, HID1_MBDD@l
+1:
+	mtspr	SPRN_HID1,r3
+#endif
+
+	/* Enable branch prediction */
+	lis	r3,BUCSR_ENABLE@h
+	ori	r3,r3,BUCSR_ENABLE@l
+	mtspr	SPRN_BUCSR,r3
+
+	/* Ensure TB is 0 */
+	li	r3,0
+	mttbl	r3
+	mttbu	r3
+
+	/* Enable/invalidate the I-Cache */
+	lis	r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
+	ori	r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
+	mtspr	SPRN_L1CSR1,r2
+1:
+	mfspr	r3,SPRN_L1CSR1
+	and.	r1,r3,r2
+	bne	1b
+
+	lis	r3,(L1CSR1_CPE|L1CSR1_ICE)@h
+	ori	r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
+	mtspr	SPRN_L1CSR1,r3
+	isync
+2:
+	mfspr	r3,SPRN_L1CSR1
+	andi.	r1,r3,L1CSR1_ICE@l
+	beq	2b
+
+	/* Enable/invalidate the D-Cache */
+	lis	r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h
+	ori	r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l
+	mtspr	SPRN_L1CSR0,r2
+1:
+	mfspr	r3,SPRN_L1CSR0
+	and.	r1,r3,r2
+	bne	1b
+
+	lis	r3,(L1CSR0_CPE|L1CSR0_DCE)@h
+	ori	r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l
+	mtspr	SPRN_L1CSR0,r3
+	isync
+2:
+	mfspr	r3,SPRN_L1CSR0
+	andi.	r1,r3,L1CSR0_DCE@l
+	beq	2b
+
+#define toreset(x) (x - __secondary_start_page + 0xfffff000)
+
+	/* get our PIR to figure out our table entry */
+	lis	r3,toreset(__spin_table)@h
+	ori	r3,r3,toreset(__spin_table)@l
+
+	/* r10 has the base address for the entry */
+	mfspr	r0,SPRN_PIR
+#ifdef CONFIG_E500MC
+	rlwinm	r4,r0,27,27,31
+#else
+	mr	r4,r0
+#endif
+	slwi	r8,r4,5
+	add	r10,r3,r8
+
+#if defined(CONFIG_E500MC) && defined(CONFIG_SYS_CACHE_STASHING)
+	/* set stash id to (coreID) * 2 + 32 + L1 CT (0) */
+	slwi	r8,r4,1
+	addi	r8,r8,32
+	mtspr	L1CSR2,r8
+#endif
+
+#ifdef CONFIG_BACKSIDE_L2_CACHE
+	/* Enable/invalidate the L2 cache */
+	msync
+	lis	r2,(L2CSR0_L2FI|L2CSR0_L2LFC)@h
+	ori	r2,r2,(L2CSR0_L2FI|L2CSR0_L2LFC)@l
+	mtspr	SPRN_L2CSR0,r2
+1:
+	mfspr	r3,SPRN_L2CSR0
+	and.	r1,r3,r2
+	bne	1b
+
+#ifdef CONFIG_SYS_CACHE_STASHING
+	/* set stash id to (coreID) * 2 + 32 + L2 (1) */
+	addi	r3,r8,1
+	mtspr	SPRN_L2CSR1,r3
+#endif
+
+	lis	r3,CONFIG_SYS_INIT_L2CSR0@h
+	ori	r3,r3,CONFIG_SYS_INIT_L2CSR0@l
+	mtspr	SPRN_L2CSR0,r3
+	isync
+2:
+	mfspr	r3,SPRN_L2CSR0
+	andis.	r1,r3,L2CSR0_L2E@h
+	beq	2b
+#endif
+
+#define EPAPR_MAGIC		(0x45504150)
+#define ENTRY_ADDR_UPPER	0
+#define ENTRY_ADDR_LOWER	4
+#define ENTRY_R3_UPPER		8
+#define ENTRY_R3_LOWER		12
+#define ENTRY_RESV		16
+#define ENTRY_PIR		20
+#define ENTRY_R6_UPPER		24
+#define ENTRY_R6_LOWER		28
+#define ENTRY_SIZE		32
+
+	/* setup the entry */
+	li	r3,0
+	li	r8,1
+	stw	r0,ENTRY_PIR(r10)
+	stw	r3,ENTRY_ADDR_UPPER(r10)
+	stw	r8,ENTRY_ADDR_LOWER(r10)
+	stw	r3,ENTRY_R3_UPPER(r10)
+	stw	r4,ENTRY_R3_LOWER(r10)
+	stw	r3,ENTRY_R6_UPPER(r10)
+	stw	r3,ENTRY_R6_LOWER(r10)
+
+	/* load r13 with the address of the 'bootpg' in SDRAM */
+	lis	r13,toreset(__bootpg_addr)@h
+	ori	r13,r13,toreset(__bootpg_addr)@l
+	lwz	r13,0(r13)
+
+	/* setup mapping for AS = 1, and jump there */
+	lis	r11,(MAS0_TLBSEL(1)|MAS0_ESEL(1))@h
+	mtspr	SPRN_MAS0,r11
+	lis	r11,(MAS1_VALID|MAS1_IPROT)@h
+	ori	r11,r11,(MAS1_TS|MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
+	mtspr	SPRN_MAS1,r11
+	oris	r11,r13,(MAS2_I|MAS2_G)@h
+	ori	r11,r13,(MAS2_I|MAS2_G)@l
+	mtspr	SPRN_MAS2,r11
+	oris	r11,r13,(MAS3_SX|MAS3_SW|MAS3_SR)@h
+	ori	r11,r13,(MAS3_SX|MAS3_SW|MAS3_SR)@l
+	mtspr	SPRN_MAS3,r11
+	tlbwe
+
+	bl	1f
+1:	mflr	r11
+	/*
+	 * OR in 0xfff to create a mask of the bootpg SDRAM address.  We use
+	 * this mask to fixup the cpu spin table and the address that we want
+	 * to jump to, eg change them from 0xfffffxxx to 0x7ffffxxx if the
+	 * bootpg is at 0x7ffff000 in SDRAM.
+	 */
+	ori	r13,r13,0xfff
+	and	r11, r11, r13
+	and	r10, r10, r13
+
+	addi	r11,r11,(2f-1b)
+	mfmsr	r13
+	ori	r12,r13,MSR_IS|MSR_DS@l
+
+	mtspr	SPRN_SRR0,r11
+	mtspr	SPRN_SRR1,r12
+	rfi
+
+	/* spin waiting for addr */
+2:
+	lwz	r4,ENTRY_ADDR_LOWER(r10)
+	andi.	r11,r4,1
+	bne	2b
+	isync
+
+	/* setup IVORs to match fixed offsets */
+#include "fixed_ivor.S"
+
+	/* get the upper bits of the addr */
+	lwz	r11,ENTRY_ADDR_UPPER(r10)
+
+	/* setup branch addr */
+	mtspr	SPRN_SRR0,r4
+
+	/* mark the entry as released */
+	li	r8,3
+	stw	r8,ENTRY_ADDR_LOWER(r10)
+
+	/* mask by ~64M to setup our tlb we will jump to */
+	rlwinm	r12,r4,0,0,5
+
+	/* setup r3, r4, r5, r6, r7, r8, r9 */
+	lwz	r3,ENTRY_R3_LOWER(r10)
+	li	r4,0
+	li	r5,0
+	lwz	r6,ENTRY_R6_LOWER(r10)
+	lis	r7,(64*1024*1024)@h
+	li	r8,0
+	li	r9,0
+
+	/* load up the pir */
+	lwz	r0,ENTRY_PIR(r10)
+	mtspr	SPRN_PIR,r0
+	mfspr	r0,SPRN_PIR
+	stw	r0,ENTRY_PIR(r10)
+
+	mtspr	IVPR,r12
+/*
+ * Coming here, we know the cpu has one TLB mapping in TLB1[0]
+ * which maps 0xfffff000-0xffffffff one-to-one.  We set up a
+ * second mapping that maps addr 1:1 for 64M, and then we jump to
+ * addr
+ */
+	lis	r10,(MAS0_TLBSEL(1)|MAS0_ESEL(0))@h
+	mtspr	SPRN_MAS0,r10
+	lis	r10,(MAS1_VALID|MAS1_IPROT)@h
+	ori	r10,r10,(MAS1_TSIZE(BOOKE_PAGESZ_64M))@l
+	mtspr	SPRN_MAS1,r10
+	/* WIMGE = 0b00000 for now */
+	mtspr	SPRN_MAS2,r12
+	ori	r12,r12,(MAS3_SX|MAS3_SW|MAS3_SR)
+	mtspr	SPRN_MAS3,r12
+#ifdef CONFIG_ENABLE_36BIT_PHYS
+	mtspr	SPRN_MAS7,r11
+#endif
+	tlbwe
+
+/* Now we have another mapping for this page, so we jump to that
+ * mapping
+ */
+	mtspr	SPRN_SRR1,r13
+	rfi
+
+	/*
+	 * Allocate some space for the SDRAM address of the bootpg.
+	 * This variable has to be in the boot page so that it can
+	 * be accessed by secondary cores when they come out of reset.
+	 */
+	.globl __bootpg_addr
+__bootpg_addr:
+	.long	0
+
+	.align L1_CACHE_SHIFT
+	.globl __spin_table
+__spin_table:
+	.space CONFIG_MAX_CPUS*ENTRY_SIZE
+
+	/* Fill in the empty space.  The actual reset vector is
+	 * the last word of the page */
+__secondary_start_code_end:
+	.space 4092 - (__secondary_start_code_end - __secondary_start_page)
+__secondary_reset_vector:
+	b	__secondary_start_page
diff --git a/arch/powerpc/cpu/mpc85xx/resetvec.S b/arch/powerpc/cpu/mpc85xx/resetvec.S
new file mode 100644
index 0000000..29555d4
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/resetvec.S
@@ -0,0 +1,2 @@
+	.section .resetvec,"ax"
+	b _start_e500
diff --git a/arch/powerpc/cpu/mpc85xx/serial_scc.c b/arch/powerpc/cpu/mpc85xx/serial_scc.c
new file mode 100644
index 0000000..2dab212
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/serial_scc.c
@@ -0,0 +1,268 @@
+/*
+ * (C) Copyright 2003 Motorola Inc.
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ * Modified based on 8260 for 8560.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
+ */
+
+/*
+ * Minimal serial functions needed to use one of the SCC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <asm/cpm_85xx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CONS_ON_SCC)
+
+#if CONFIG_CONS_INDEX == 1	/* Console on SCC1 */
+
+#define SCC_INDEX		0
+#define PROFF_SCC		PROFF_SCC1
+#define CMXSCR_MASK		(CMXSCR_GR1|CMXSCR_SC1|\
+					CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
+#define CMXSCR_VALUE		(CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
+#define CPM_CR_SCC_PAGE		CPM_CR_SCC1_PAGE
+#define CPM_CR_SCC_SBLOCK	CPM_CR_SCC1_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 2	/* Console on SCC2 */
+
+#define SCC_INDEX		1
+#define PROFF_SCC		PROFF_SCC2
+#define CMXSCR_MASK		(CMXSCR_GR2|CMXSCR_SC2|\
+					CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
+#define CMXSCR_VALUE		(CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
+#define CPM_CR_SCC_PAGE		CPM_CR_SCC2_PAGE
+#define CPM_CR_SCC_SBLOCK	CPM_CR_SCC2_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 3	/* Console on SCC3 */
+
+#define SCC_INDEX		2
+#define PROFF_SCC		PROFF_SCC3
+#define CMXSCR_MASK		(CMXSCR_GR3|CMXSCR_SC3|\
+					CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
+#define CMXSCR_VALUE		(CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
+#define CPM_CR_SCC_PAGE		CPM_CR_SCC3_PAGE
+#define CPM_CR_SCC_SBLOCK	CPM_CR_SCC3_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 4	/* Console on SCC4 */
+
+#define SCC_INDEX		3
+#define PROFF_SCC		PROFF_SCC4
+#define CMXSCR_MASK		(CMXSCR_GR4|CMXSCR_SC4|\
+					CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
+#define CMXSCR_VALUE		(CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
+#define CPM_CR_SCC_PAGE		CPM_CR_SCC4_PAGE
+#define CPM_CR_SCC_SBLOCK	CPM_CR_SCC4_SBLOCK
+
+#else
+
+#error "console not correctly defined"
+
+#endif
+
+int serial_init (void)
+{
+	volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+	volatile ccsr_cpm_scc_t *sp;
+	volatile scc_uart_t *up;
+	volatile cbd_t *tbdf, *rbdf;
+	volatile ccsr_cpm_cp_t *cp = &(cpm->im_cpm_cp);
+	uint	dpaddr;
+
+	/* initialize pointers to SCC */
+
+	sp = (ccsr_cpm_scc_t *) &(cpm->im_cpm_scc[SCC_INDEX]);
+	up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
+
+	/* Disable transmitter/receiver.
+	*/
+	sp->gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	/* put the SCC channel into NMSI (non multiplexd serial interface)
+	 * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
+	 */
+	cpm->im_cpm_mux.cmxscr = \
+		(cpm->im_cpm_mux.cmxscr&~CMXSCR_MASK)|CMXSCR_VALUE;
+
+	/* Set up the baud rate generator.
+	*/
+	serial_setbrg ();
+
+	/* Allocate space for two buffer descriptors in the DP ram.
+	 * damm: allocating space after the two buffers for rx/tx data
+	 */
+
+	dpaddr = m8560_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
+
+	/* Set the physical address of the host memory buffers in
+	 * the buffer descriptors.
+	 */
+	rbdf = (cbd_t *)&(cpm->im_dprambase[dpaddr]);
+	rbdf->cbd_bufaddr = (uint) (rbdf+2);
+	rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+	tbdf = rbdf + 1;
+	tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+	tbdf->cbd_sc = BD_SC_WRAP;
+
+	/* Set up the uart parameters in the parameter ram.
+	*/
+	up->scc_genscc.scc_rbase = dpaddr;
+	up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
+	up->scc_genscc.scc_rfcr = CPMFCR_EB;
+	up->scc_genscc.scc_tfcr = CPMFCR_EB;
+	up->scc_genscc.scc_mrblr = 1;
+	up->scc_maxidl = 0;
+	up->scc_brkcr = 1;
+	up->scc_parec = 0;
+	up->scc_frmec = 0;
+	up->scc_nosec = 0;
+	up->scc_brkec = 0;
+	up->scc_uaddr1 = 0;
+	up->scc_uaddr2 = 0;
+	up->scc_toseq = 0;
+	up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
+	up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
+	up->scc_rccm = 0xc0ff;
+
+	/* Mask all interrupts and remove anything pending.
+	*/
+	sp->sccm = 0;
+	sp->scce = 0xffff;
+
+	/* Set 8 bit FIFO, 16 bit oversampling and UART mode.
+	*/
+	sp->gsmrh = SCC_GSMRH_RFW;	/* 8 bit FIFO */
+	sp->gsmrl = \
+		SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
+
+	/* Set CTS no flow control, 1 stop bit, 8 bit character length,
+	 * normal async UART mode, no parity
+	 */
+	sp->psmr = SCU_PSMR_CL;
+
+	/* execute the "Init Rx and Tx params" CP command.
+	*/
+
+	while (cp->cpcr & CPM_CR_FLG)  /* wait if cp is busy */
+	  ;
+
+	cp->cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
+					0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+	while (cp->cpcr & CPM_CR_FLG)  /* wait if cp is busy */
+	  ;
+
+	/* Enable transmitter/receiver.
+	*/
+	sp->gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
+
+	return (0);
+}
+
+void
+serial_setbrg (void)
+{
+#if defined(CONFIG_CONS_USE_EXTC)
+	m8560_cpm_extcbrg(SCC_INDEX, gd->baudrate,
+		CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
+#else
+	m8560_cpm_setbrg(SCC_INDEX, gd->baudrate);
+#endif
+}
+
+void
+serial_putc(const char c)
+{
+	volatile scc_uart_t	*up;
+	volatile cbd_t		*tbdf;
+	volatile ccsr_cpm_t	*cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+
+	if (c == '\n')
+		serial_putc ('\r');
+
+	up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
+	tbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_tbase]);
+
+	/* Wait for last character to go.
+	 */
+	while (tbdf->cbd_sc & BD_SC_READY)
+		;
+
+	/* Load the character into the transmit buffer.
+	 */
+	*(volatile char *)tbdf->cbd_bufaddr = c;
+	tbdf->cbd_datlen = 1;
+	tbdf->cbd_sc |= BD_SC_READY;
+}
+
+void
+serial_puts (const char *s)
+{
+	while (*s) {
+		serial_putc (*s++);
+	}
+}
+
+int
+serial_getc(void)
+{
+	volatile cbd_t		*rbdf;
+	volatile scc_uart_t	*up;
+	volatile ccsr_cpm_t	*cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+	unsigned char		c;
+
+	up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
+	rbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_rbase]);
+
+	/* Wait for character to show up.
+	 */
+	while (rbdf->cbd_sc & BD_SC_EMPTY)
+		;
+
+	/* Grab the char and clear the buffer again.
+	 */
+	c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
+	rbdf->cbd_sc |= BD_SC_EMPTY;
+
+	return (c);
+}
+
+int
+serial_tstc()
+{
+	volatile cbd_t		*rbdf;
+	volatile scc_uart_t	*up;
+	volatile ccsr_cpm_t	*cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+
+	up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
+	rbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_rbase]);
+
+	return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
+}
+
+#endif	/* CONFIG_CONS_ON_SCC */
diff --git a/arch/powerpc/cpu/mpc85xx/speed.c b/arch/powerpc/cpu/mpc85xx/speed.c
new file mode 100644
index 0000000..268edbc
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/speed.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2004, 2007-2009 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2003 Motorola Inc.
+ * Xianghua Xiao, (X.Xiao@motorola.com)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <ppc_asm.tmpl>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* --------------------------------------------------------------- */
+
+void get_sys_info (sys_info_t * sysInfo)
+{
+	volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+#ifdef CONFIG_FSL_CORENET
+	volatile ccsr_clk_t *clk = (void *)(CONFIG_SYS_FSL_CORENET_CLK_ADDR);
+
+	const u8 core_cplx_PLL[16] = {
+		[ 0] = 0,	/* CC1 PPL / 1 */
+		[ 1] = 0,	/* CC1 PPL / 2 */
+		[ 2] = 0,	/* CC1 PPL / 4 */
+		[ 4] = 1,	/* CC2 PPL / 1 */
+		[ 5] = 1,	/* CC2 PPL / 2 */
+		[ 6] = 1,	/* CC2 PPL / 4 */
+		[ 8] = 2,	/* CC3 PPL / 1 */
+		[ 9] = 2,	/* CC3 PPL / 2 */
+		[10] = 2,	/* CC3 PPL / 4 */
+		[12] = 3,	/* CC4 PPL / 1 */
+		[13] = 3,	/* CC4 PPL / 2 */
+		[14] = 3,	/* CC4 PPL / 4 */
+	};
+
+	const u8 core_cplx_PLL_div[16] = {
+		[ 0] = 1,	/* CC1 PPL / 1 */
+		[ 1] = 2,	/* CC1 PPL / 2 */
+		[ 2] = 4,	/* CC1 PPL / 4 */
+		[ 4] = 1,	/* CC2 PPL / 1 */
+		[ 5] = 2,	/* CC2 PPL / 2 */
+		[ 6] = 4,	/* CC2 PPL / 4 */
+		[ 8] = 1,	/* CC3 PPL / 1 */
+		[ 9] = 2,	/* CC3 PPL / 2 */
+		[10] = 4,	/* CC3 PPL / 4 */
+		[12] = 1,	/* CC4 PPL / 1 */
+		[13] = 2,	/* CC4 PPL / 2 */
+		[14] = 4,	/* CC4 PPL / 4 */
+	};
+	uint lcrr_div, i, freqCC_PLL[4], rcw_tmp;
+	unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
+
+	sysInfo->freqSystemBus = sysclk;
+	sysInfo->freqDDRBus = sysclk;
+	freqCC_PLL[0] = sysclk;
+	freqCC_PLL[1] = sysclk;
+	freqCC_PLL[2] = sysclk;
+	freqCC_PLL[3] = sysclk;
+
+	sysInfo->freqSystemBus *= (in_be32(&gur->rcwsr[0]) >> 25) & 0x1f;
+	sysInfo->freqDDRBus *= ((in_be32(&gur->rcwsr[0]) >> 17) & 0x1f);
+	freqCC_PLL[0] *= (in_be32(&clk->pllc1gsr) >> 1) & 0x3f;
+	freqCC_PLL[1] *= (in_be32(&clk->pllc2gsr) >> 1) & 0x3f;
+	freqCC_PLL[2] *= (in_be32(&clk->pllc3gsr) >> 1) & 0x3f;
+	freqCC_PLL[3] *= (in_be32(&clk->pllc4gsr) >> 1) & 0x3f;
+
+	rcw_tmp = in_be32(&gur->rcwsr[3]);
+	for (i = 0; i < cpu_numcores(); i++) {
+		u32 c_pll_sel = (in_be32(&clk->clkc0csr + i*8) >> 27) & 0xf;
+		u32 cplx_pll = core_cplx_PLL[c_pll_sel];
+
+		sysInfo->freqProcessor[i] =
+			 freqCC_PLL[cplx_pll] / core_cplx_PLL_div[c_pll_sel];
+	}
+
+#define PME_CLK_SEL	0x80000000
+#define FM1_CLK_SEL	0x40000000
+#define FM2_CLK_SEL	0x20000000
+	rcw_tmp = in_be32(&gur->rcwsr[7]);
+
+#ifdef CONFIG_SYS_DPAA_PME
+	if (rcw_tmp & PME_CLK_SEL)
+		sysInfo->freqPME = freqCC_PLL[2] / 2;
+	else
+		sysInfo->freqPME = sysInfo->freqSystemBus / 2;
+#endif
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+	if (rcw_tmp & FM1_CLK_SEL)
+		sysInfo->freqFMan[0] = freqCC_PLL[2] / 2;
+	else
+		sysInfo->freqFMan[0] = sysInfo->freqSystemBus / 2;
+#if (CONFIG_SYS_NUM_FMAN) == 2
+	if (rcw_tmp & FM2_CLK_SEL)
+		sysInfo->freqFMan[1] = freqCC_PLL[2] / 2;
+	else
+		sysInfo->freqFMan[1] = sysInfo->freqSystemBus / 2;
+#endif
+#endif
+
+#else
+	uint plat_ratio,e500_ratio,half_freqSystemBus;
+	uint lcrr_div;
+	int i;
+#ifdef CONFIG_QE
+	u32 qe_ratio;
+#endif
+
+	plat_ratio = (gur->porpllsr) & 0x0000003e;
+	plat_ratio >>= 1;
+	sysInfo->freqSystemBus = plat_ratio * CONFIG_SYS_CLK_FREQ;
+
+	/* Divide before multiply to avoid integer
+	 * overflow for processor speeds above 2GHz */
+	half_freqSystemBus = sysInfo->freqSystemBus/2;
+	for (i = 0; i < cpu_numcores(); i++) {
+		e500_ratio = ((gur->porpllsr) >> (i * 8 + 16)) & 0x3f;
+		sysInfo->freqProcessor[i] = e500_ratio * half_freqSystemBus;
+	}
+
+	/* Note: freqDDRBus is the MCLK frequency, not the data rate. */
+	sysInfo->freqDDRBus = sysInfo->freqSystemBus;
+
+#ifdef CONFIG_DDR_CLK_FREQ
+	{
+		u32 ddr_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_DDR_RATIO)
+			>> MPC85xx_PORPLLSR_DDR_RATIO_SHIFT;
+		if (ddr_ratio != 0x7)
+			sysInfo->freqDDRBus = ddr_ratio * CONFIG_DDR_CLK_FREQ;
+	}
+#endif
+#endif
+
+#ifdef CONFIG_QE
+	qe_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_QE_RATIO)
+			>> MPC85xx_PORPLLSR_QE_RATIO_SHIFT;
+	sysInfo->freqQE = qe_ratio * CONFIG_SYS_CLK_FREQ;
+#endif
+
+#if defined(CONFIG_SYS_LBC_LCRR)
+	/* We will program LCRR to this value later */
+	lcrr_div = CONFIG_SYS_LBC_LCRR & LCRR_CLKDIV;
+#else
+	{
+	    volatile ccsr_lbc_t *lbc = (void *)(CONFIG_SYS_MPC85xx_LBC_ADDR);
+	    lcrr_div = in_be32(&lbc->lcrr) & LCRR_CLKDIV;
+	}
+#endif
+	if (lcrr_div == 2 || lcrr_div == 4 || lcrr_div == 8) {
+#if defined(CONFIG_FSL_CORENET)
+		/* If this is corenet based SoC, bit-representation
+		 * for four times the clock divider values.
+		 */
+		lcrr_div *= 4;
+#elif !defined(CONFIG_MPC8540) && !defined(CONFIG_MPC8541) && \
+    !defined(CONFIG_MPC8555) && !defined(CONFIG_MPC8560)
+		/*
+		 * Yes, the entire PQ38 family use the same
+		 * bit-representation for twice the clock divider values.
+		 */
+		lcrr_div *= 2;
+#endif
+		sysInfo->freqLocalBus = sysInfo->freqSystemBus / lcrr_div;
+	} else {
+		/* In case anyone cares what the unknown value is */
+		sysInfo->freqLocalBus = lcrr_div;
+	}
+}
+
+
+int get_clocks (void)
+{
+	sys_info_t sys_info;
+#ifdef CONFIG_MPC8544
+	volatile ccsr_gur_t *gur = (void *) CONFIG_SYS_MPC85xx_GUTS_ADDR;
+#endif
+#if defined(CONFIG_CPM2)
+	volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+	uint sccr, dfbrg;
+
+	/* set VCO = 4 * BRG */
+	cpm->im_cpm_intctl.sccr &= 0xfffffffc;
+	sccr = cpm->im_cpm_intctl.sccr;
+	dfbrg = (sccr & SCCR_DFBRG_MSK) >> SCCR_DFBRG_SHIFT;
+#endif
+	get_sys_info (&sys_info);
+	gd->cpu_clk = sys_info.freqProcessor[0];
+	gd->bus_clk = sys_info.freqSystemBus;
+	gd->mem_clk = sys_info.freqDDRBus;
+	gd->lbc_clk = sys_info.freqLocalBus;
+
+#ifdef CONFIG_QE
+	gd->qe_clk = sys_info.freqQE;
+	gd->brg_clk = gd->qe_clk / 2;
+#endif
+	/*
+	 * The base clock for I2C depends on the actual SOC.  Unfortunately,
+	 * there is no pattern that can be used to determine the frequency, so
+	 * the only choice is to look up the actual SOC number and use the value
+	 * for that SOC. This information is taken from application note
+	 * AN2919.
+	 */
+#if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
+	defined(CONFIG_MPC8560) || defined(CONFIG_MPC8555)
+	gd->i2c1_clk = sys_info.freqSystemBus;
+#elif defined(CONFIG_MPC8544)
+	/*
+	 * On the 8544, the I2C clock is the same as the SEC clock.  This can be
+	 * either CCB/2 or CCB/3, depending on the value of cfg_sec_freq. See
+	 * 4.4.3.3 of the 8544 RM.  Note that this might actually work for all
+	 * 85xx, but only the 8544 has cfg_sec_freq, so it's unknown if the
+	 * PORDEVSR2_SEC_CFG bit is 0 on all 85xx boards that are not an 8544.
+	 */
+	if (gur->pordevsr2 & MPC85xx_PORDEVSR2_SEC_CFG)
+		gd->i2c1_clk = sys_info.freqSystemBus / 3;
+	else
+		gd->i2c1_clk = sys_info.freqSystemBus / 2;
+#else
+	/* Most 85xx SOCs use CCB/2, so this is the default behavior. */
+	gd->i2c1_clk = sys_info.freqSystemBus / 2;
+#endif
+	gd->i2c2_clk = gd->i2c1_clk;
+
+#if defined(CONFIG_FSL_ESDHC)
+#ifdef CONFIG_MPC8569
+	gd->sdhc_clk = gd->bus_clk;
+#else
+	gd->sdhc_clk = gd->bus_clk / 2;
+#endif
+#endif /* defined(CONFIG_FSL_ESDHC) */
+
+#if defined(CONFIG_CPM2)
+	gd->vco_out = 2*sys_info.freqSystemBus;
+	gd->cpm_clk = gd->vco_out / 2;
+	gd->scc_clk = gd->vco_out / 4;
+	gd->brg_clk = gd->vco_out / (1 << (2 * (dfbrg + 1)));
+#endif
+
+	if(gd->cpu_clk != 0) return (0);
+	else return (1);
+}
+
+
+/********************************************
+ * get_bus_freq
+ * return system bus freq in Hz
+ *********************************************/
+ulong get_bus_freq (ulong dummy)
+{
+	return gd->bus_clk;
+}
+
+/********************************************
+ * get_ddr_freq
+ * return ddr bus freq in Hz
+ *********************************************/
+ulong get_ddr_freq (ulong dummy)
+{
+	return gd->mem_clk;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/start.S b/arch/powerpc/cpu/mpc85xx/start.S
new file mode 100644
index 0000000..b3cb56a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/start.S
@@ -0,0 +1,1195 @@
+/*
+ * Copyright 2004, 2007-2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2003  Motorola,Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* U-Boot Startup Code for Motorola 85xx PowerPC based Embedded Boards
+ *
+ * The processor starts at 0xfffffffc and the code is first executed in the
+ * last 4K page(0xfffff000-0xffffffff) in flash/rom.
+ *
+ */
+
+#include <config.h>
+#include <mpc85xx.h>
+#include <timestamp.h>
+#include <version.h>
+
+#define _LINUX_CONFIG_H 1	/* avoid reading Linux autoconf.h file	*/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef	 CONFIG_IDENT_STRING
+#define	 CONFIG_IDENT_STRING ""
+#endif
+
+#undef	MSR_KERNEL
+#define MSR_KERNEL ( MSR_ME )	/* Machine Check */
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+	START_GOT
+	GOT_ENTRY(_GOT2_TABLE_)
+	GOT_ENTRY(_FIXUP_TABLE_)
+
+#ifndef CONFIG_NAND_SPL
+	GOT_ENTRY(_start)
+	GOT_ENTRY(_start_of_vectors)
+	GOT_ENTRY(_end_of_vectors)
+	GOT_ENTRY(transfer_to_handler)
+#endif
+
+	GOT_ENTRY(__init_end)
+	GOT_ENTRY(_end)
+	GOT_ENTRY(__bss_start)
+	END_GOT
+
+/*
+ * e500 Startup -- after reset only the last 4KB of the effective
+ * address space is mapped in the MMU L2 TLB1 Entry0. The .bootpg
+ * section is located at THIS LAST page and basically does three
+ * things: clear some registers, set up exception tables and
+ * add more TLB entries for 'larger spaces'(e.g. the boot rom) to
+ * continue the boot procedure.
+
+ * Once the boot rom is mapped by TLB entries we can proceed
+ * with normal startup.
+ *
+ */
+
+	.section .bootpg,"ax"
+	.globl _start_e500
+
+_start_e500:
+
+/* clear registers/arrays not reset by hardware */
+
+	/* L1 */
+	li	r0,2
+	mtspr	L1CSR0,r0	/* invalidate d-cache */
+	mtspr	L1CSR1,r0	/* invalidate i-cache */
+
+	mfspr	r1,DBSR
+	mtspr	DBSR,r1		/* Clear all valid bits */
+
+	/*
+	 *	Enable L1 Caches early
+	 *
+	 */
+
+#if defined(CONFIG_E500MC) && defined(CONFIG_SYS_CACHE_STASHING)
+	/* set stash id to (coreID) * 2 + 32 + L1 CT (0) */
+	li	r2,(32 + 0)
+	mtspr	L1CSR2,r2
+#endif
+
+	/* Enable/invalidate the I-Cache */
+	lis	r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
+	ori	r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
+	mtspr	SPRN_L1CSR1,r2
+1:
+	mfspr	r3,SPRN_L1CSR1
+	and.	r1,r3,r2
+	bne	1b
+
+	lis	r3,(L1CSR1_CPE|L1CSR1_ICE)@h
+	ori	r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
+	mtspr	SPRN_L1CSR1,r3
+	isync
+2:
+	mfspr	r3,SPRN_L1CSR1
+	andi.	r1,r3,L1CSR1_ICE@l
+	beq	2b
+
+	/* Enable/invalidate the D-Cache */
+	lis	r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h
+	ori	r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l
+	mtspr	SPRN_L1CSR0,r2
+1:
+	mfspr	r3,SPRN_L1CSR0
+	and.	r1,r3,r2
+	bne	1b
+
+	lis	r3,(L1CSR0_CPE|L1CSR0_DCE)@h
+	ori	r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l
+	mtspr	SPRN_L1CSR0,r3
+	isync
+2:
+	mfspr	r3,SPRN_L1CSR0
+	andi.	r1,r3,L1CSR0_DCE@l
+	beq	2b
+
+	/* Setup interrupt vectors */
+	lis	r1,TEXT_BASE@h
+	mtspr	IVPR,r1
+
+	li	r1,0x0100
+	mtspr	IVOR0,r1	/* 0: Critical input */
+	li	r1,0x0200
+	mtspr	IVOR1,r1	/* 1: Machine check */
+	li	r1,0x0300
+	mtspr	IVOR2,r1	/* 2: Data storage */
+	li	r1,0x0400
+	mtspr	IVOR3,r1	/* 3: Instruction storage */
+	li	r1,0x0500
+	mtspr	IVOR4,r1	/* 4: External interrupt */
+	li	r1,0x0600
+	mtspr	IVOR5,r1	/* 5: Alignment */
+	li	r1,0x0700
+	mtspr	IVOR6,r1	/* 6: Program check */
+	li	r1,0x0800
+	mtspr	IVOR7,r1	/* 7: floating point unavailable */
+	li	r1,0x0900
+	mtspr	IVOR8,r1	/* 8: System call */
+	/* 9: Auxiliary processor unavailable(unsupported) */
+	li	r1,0x0a00
+	mtspr	IVOR10,r1	/* 10: Decrementer */
+	li	r1,0x0b00
+	mtspr	IVOR11,r1	/* 11: Interval timer */
+	li	r1,0x0c00
+	mtspr	IVOR12,r1	/* 12: Watchdog timer */
+	li	r1,0x0d00
+	mtspr	IVOR13,r1	/* 13: Data TLB error */
+	li	r1,0x0e00
+	mtspr	IVOR14,r1	/* 14: Instruction TLB error */
+	li	r1,0x0f00
+	mtspr	IVOR15,r1	/* 15: Debug */
+
+	/* Clear and set up some registers. */
+	li      r0,0x0000
+	lis	r1,0xffff
+	mtspr	DEC,r0			/* prevent dec exceptions */
+	mttbl	r0			/* prevent fit & wdt exceptions */
+	mttbu	r0
+	mtspr	TSR,r1			/* clear all timer exception status */
+	mtspr	TCR,r0			/* disable all */
+	mtspr	ESR,r0			/* clear exception syndrome register */
+	mtspr	MCSR,r0			/* machine check syndrome register */
+	mtxer	r0			/* clear integer exception register */
+
+#ifdef CONFIG_SYS_BOOK3E_HV
+	mtspr	MAS8,r0			/* make sure MAS8 is clear */
+#endif
+
+	/* Enable Time Base and Select Time Base Clock */
+	lis	r0,HID0_EMCP@h		/* Enable machine check */
+#if defined(CONFIG_ENABLE_36BIT_PHYS)
+	ori	r0,r0,HID0_ENMAS7@l	/* Enable MAS7 */
+#endif
+#ifndef CONFIG_E500MC
+	ori	r0,r0,HID0_TBEN@l	/* Enable Timebase */
+#endif
+	mtspr	HID0,r0
+
+#ifndef CONFIG_E500MC
+	li	r0,(HID1_ASTME|HID1_ABE)@l	/* Addr streaming & broadcast */
+	mfspr	r3,PVR
+	andi.	r3,r3, 0xff
+	cmpwi	r3,0x50@l	/* if we are rev 5.0 or greater set MBDD */
+	blt 1f
+	/* Set MBDD bit also */
+	ori r0, r0, HID1_MBDD@l
+1:
+	mtspr	HID1,r0
+#endif
+
+	/* Enable Branch Prediction */
+#if defined(CONFIG_BTB)
+	lis	r0,BUCSR_ENABLE@h
+	ori	r0,r0,BUCSR_ENABLE@l
+	mtspr	SPRN_BUCSR,r0
+#endif
+
+#if defined(CONFIG_SYS_INIT_DBCR)
+	lis	r1,0xffff
+	ori	r1,r1,0xffff
+	mtspr	DBSR,r1			/* Clear all status bits */
+	lis	r0,CONFIG_SYS_INIT_DBCR@h	/* DBCR0[IDM] must be set */
+	ori	r0,r0,CONFIG_SYS_INIT_DBCR@l
+	mtspr	DBCR0,r0
+#endif
+
+#ifdef CONFIG_MPC8569
+#define CONFIG_SYS_LBC_ADDR (CONFIG_SYS_CCSRBAR_DEFAULT + 0x5000)
+#define CONFIG_SYS_LBCR_ADDR (CONFIG_SYS_LBC_ADDR + 0xd0)
+
+	/* MPC8569 Rev.0 silcon needs to set bit 13 of LBCR to allow elBC to
+	 * use address space which is more than 12bits, and it must be done in
+	 * the 4K boot page. So we set this bit here.
+	 */
+
+	/* create a temp mapping TLB0[0] for LBCR  */
+	lis     r6,FSL_BOOKE_MAS0(0, 0, 0)@h
+	ori     r6,r6,FSL_BOOKE_MAS0(0, 0, 0)@l
+
+	lis     r7,FSL_BOOKE_MAS1(1, 0, 0, 0, BOOKE_PAGESZ_4K)@h
+	ori     r7,r7,FSL_BOOKE_MAS1(1, 0, 0, 0, BOOKE_PAGESZ_4K)@l
+
+	lis     r8,FSL_BOOKE_MAS2(CONFIG_SYS_LBC_ADDR, MAS2_I|MAS2_G)@h
+	ori     r8,r8,FSL_BOOKE_MAS2(CONFIG_SYS_LBC_ADDR, MAS2_I|MAS2_G)@l
+
+	lis     r9,FSL_BOOKE_MAS3(CONFIG_SYS_LBC_ADDR, 0,
+						(MAS3_SX|MAS3_SW|MAS3_SR))@h
+	ori     r9,r9,FSL_BOOKE_MAS3(CONFIG_SYS_LBC_ADDR, 0,
+						(MAS3_SX|MAS3_SW|MAS3_SR))@l
+
+	mtspr   MAS0,r6
+	mtspr   MAS1,r7
+	mtspr   MAS2,r8
+	mtspr   MAS3,r9
+	isync
+	msync
+	tlbwe
+
+	/* Set LBCR register */
+	lis     r4,CONFIG_SYS_LBCR_ADDR@h
+	ori     r4,r4,CONFIG_SYS_LBCR_ADDR@l
+
+	lis     r5,CONFIG_SYS_LBC_LBCR@h
+	ori     r5,r5,CONFIG_SYS_LBC_LBCR@l
+	stw     r5,0(r4)
+	isync
+
+	/* invalidate this temp TLB */
+	lis	r4,CONFIG_SYS_LBC_ADDR@h
+	ori	r4,r4,CONFIG_SYS_LBC_ADDR@l
+	tlbivax	0,r4
+	isync
+
+#endif /* CONFIG_MPC8569 */
+
+	lis     r6,FSL_BOOKE_MAS0(1, 15, 0)@h
+	ori     r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l
+
+#ifndef CONFIG_SYS_RAMBOOT
+	/* create a temp mapping in AS=1 to the 4M boot window */
+	lis     r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@h
+	ori     r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@l
+
+	lis     r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@h
+	ori     r8,r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@l
+
+	/* The 85xx has the default boot window 0xff800000 - 0xffffffff */
+	lis     r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
+	ori     r9,r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
+#else
+	/*
+	 * create a temp mapping in AS=1 to the 1M TEXT_BASE space, the main
+	 * image has been relocated to TEXT_BASE on the second stage.
+	 */
+	lis     r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_1M)@h
+	ori     r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_1M)@l
+
+	lis     r8,FSL_BOOKE_MAS2(TEXT_BASE, (MAS2_I|MAS2_G))@h
+	ori     r8,r8,FSL_BOOKE_MAS2(TEXT_BASE, (MAS2_I|MAS2_G))@l
+
+	lis     r9,FSL_BOOKE_MAS3(TEXT_BASE, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
+	ori     r9,r9,FSL_BOOKE_MAS3(TEXT_BASE, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
+#endif
+
+	mtspr   MAS0,r6
+	mtspr   MAS1,r7
+	mtspr   MAS2,r8
+	mtspr   MAS3,r9
+	isync
+	msync
+	tlbwe
+
+	/* create a temp mapping in AS=1 to the stack */
+	lis     r6,FSL_BOOKE_MAS0(1, 14, 0)@h
+	ori     r6,r6,FSL_BOOKE_MAS0(1, 14, 0)@l
+
+	lis     r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16K)@h
+	ori     r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16K)@l
+
+	lis     r8,FSL_BOOKE_MAS2(CONFIG_SYS_INIT_RAM_ADDR, 0)@h
+	ori     r8,r8,FSL_BOOKE_MAS2(CONFIG_SYS_INIT_RAM_ADDR, 0)@l
+
+	lis     r9,FSL_BOOKE_MAS3(CONFIG_SYS_INIT_RAM_ADDR, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
+	ori     r9,r9,FSL_BOOKE_MAS3(CONFIG_SYS_INIT_RAM_ADDR, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
+
+	mtspr   MAS0,r6
+	mtspr   MAS1,r7
+	mtspr   MAS2,r8
+	mtspr   MAS3,r9
+	isync
+	msync
+	tlbwe
+
+	lis	r6,MSR_IS|MSR_DS@h
+	ori	r6,r6,MSR_IS|MSR_DS@l
+	lis	r7,switch_as@h
+	ori	r7,r7,switch_as@l
+
+	mtspr	SPRN_SRR0,r7
+	mtspr	SPRN_SRR1,r6
+	rfi
+
+switch_as:
+/* L1 DCache is used for initial RAM */
+
+	/* Allocate Initial RAM in data cache.
+	 */
+	lis	r3,CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
+	mfspr	r2, L1CFG0
+	andi.	r2, r2, 0x1ff
+	/* cache size * 1024 / (2 * L1 line size) */
+	slwi	r2, r2, (10 - 1 - L1_CACHE_SHIFT)
+	mtctr	r2
+	li	r0,0
+1:
+	dcbz	r0,r3
+	dcbtls	0,r0,r3
+	addi	r3,r3,CONFIG_SYS_CACHELINE_SIZE
+	bdnz	1b
+
+	/* Jump out the last 4K page and continue to 'normal' start */
+#ifdef CONFIG_SYS_RAMBOOT
+	b	_start_cont
+#else
+	/* Calculate absolute address in FLASH and jump there		*/
+	/*--------------------------------------------------------------*/
+	lis	r3,CONFIG_SYS_MONITOR_BASE@h
+	ori	r3,r3,CONFIG_SYS_MONITOR_BASE@l
+	addi	r3,r3,_start_cont - _start + _START_OFFSET
+	mtlr	r3
+	blr
+#endif
+
+	.text
+	.globl	_start
+_start:
+	.long	0x27051956		/* U-BOOT Magic Number */
+	.globl	version_string
+version_string:
+	.ascii U_BOOT_VERSION
+	.ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
+	.ascii CONFIG_IDENT_STRING, "\0"
+
+	.align	4
+	.globl	_start_cont
+_start_cont:
+	/* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
+	lis	r1,CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r1,r1,CONFIG_SYS_INIT_SP_OFFSET@l
+
+	li	r0,0
+	stwu	r0,-4(r1)
+	stwu	r0,-4(r1)		/* Terminate call chain */
+
+	stwu	r1,-8(r1)		/* Save back chain and move SP */
+	lis	r0,RESET_VECTOR@h	/* Address of reset vector */
+	ori	r0,r0,RESET_VECTOR@l
+	stwu	r1,-8(r1)		/* Save back chain and move SP */
+	stw	r0,+12(r1)		/* Save return addr (underflow vect) */
+
+	GET_GOT
+	bl	cpu_init_early_f
+
+	/* switch back to AS = 0 */
+	lis	r3,(MSR_CE|MSR_ME|MSR_DE)@h
+	ori	r3,r3,(MSR_CE|MSR_ME|MSR_DE)@l
+	mtmsr	r3
+	isync
+
+	bl	cpu_init_f
+	bl	board_init_f
+	isync
+
+#ifndef CONFIG_NAND_SPL
+	. = EXC_OFF_SYS_RESET
+	.globl	_start_of_vectors
+_start_of_vectors:
+
+/* Critical input. */
+	CRIT_EXCEPTION(0x0100, CriticalInput, CritcalInputException)
+
+/* Machine check */
+	MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+	STD_EXCEPTION(0x0300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+	STD_EXCEPTION(0x0400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+	STD_EXCEPTION(0x0500, ExtInterrupt, ExtIntException)
+
+/* Alignment exception. */
+	. = 0x0600
+Alignment:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	mfspr	r4,DAR
+	stw	r4,_DAR(r21)
+	mfspr	r5,DSISR
+	stw	r5,_DSISR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+	. = 0x0700
+ProgramCheck:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+		MSR_KERNEL, COPY_EE)
+
+	/* No FPU on MPC85xx.  This exception is not supposed to happen.
+	*/
+	STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
+
+	. = 0x0900
+/*
+ * r0 - SYSCALL number
+ * r3-... arguments
+ */
+SystemCall:
+	addis	r11,r0,0	/* get functions table addr */
+	ori	r11,r11,0	/* Note: this code is patched in trap_init */
+	addis	r12,r0,0	/* get number of functions */
+	ori	r12,r12,0
+
+	cmplw	0,r0,r12
+	bge	1f
+
+	rlwinm	r0,r0,2,0,31	/* fn_addr = fn_tbl[r0] */
+	add	r11,r11,r0
+	lwz	r11,0(r11)
+
+	li	r20,0xd00-4	/* Get stack pointer */
+	lwz	r12,0(r20)
+	subi	r12,r12,12	/* Adjust stack pointer */
+	li	r0,0xc00+_end_back-SystemCall
+	cmplw	0,r0,r12	/* Check stack overflow */
+	bgt	1f
+	stw	r12,0(r20)
+
+	mflr	r0
+	stw	r0,0(r12)
+	mfspr	r0,SRR0
+	stw	r0,4(r12)
+	mfspr	r0,SRR1
+	stw	r0,8(r12)
+
+	li	r12,0xc00+_back-SystemCall
+	mtlr	r12
+	mtspr	SRR0,r11
+
+1:	SYNC
+	rfi
+_back:
+
+	mfmsr	r11			/* Disable interrupts */
+	li	r12,0
+	ori	r12,r12,MSR_EE
+	andc	r11,r11,r12
+	SYNC				/* Some chip revs need this... */
+	mtmsr	r11
+	SYNC
+
+	li	r12,0xd00-4		/* restore regs */
+	lwz	r12,0(r12)
+
+	lwz	r11,0(r12)
+	mtlr	r11
+	lwz	r11,4(r12)
+	mtspr	SRR0,r11
+	lwz	r11,8(r12)
+	mtspr	SRR1,r11
+
+	addi	r12,r12,12		/* Adjust stack pointer */
+	li	r20,0xd00-4
+	stw	r12,0(r20)
+
+	SYNC
+	rfi
+_end_back:
+
+	STD_EXCEPTION(0x0a00, Decrementer, timer_interrupt)
+	STD_EXCEPTION(0x0b00, IntervalTimer, UnknownException)
+	STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException)
+
+	STD_EXCEPTION(0x0d00, DataTLBError, UnknownException)
+	STD_EXCEPTION(0x0e00, InstructionTLBError, UnknownException)
+
+	CRIT_EXCEPTION(0x0f00, DebugBreakpoint, DebugException )
+
+	.globl	_end_of_vectors
+_end_of_vectors:
+
+
+	. = . + (0x100 - ( . & 0xff ))	/* align for debug */
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+	.globl	transfer_to_handler
+transfer_to_handler:
+	stw	r22,_NIP(r21)
+	lis	r22,MSR_POW@h
+	andc	r23,r23,r22
+	stw	r23,_MSR(r21)
+	SAVE_GPR(7, r21)
+	SAVE_4GPRS(8, r21)
+	SAVE_8GPRS(12, r21)
+	SAVE_8GPRS(24, r21)
+
+	mflr	r23
+	andi.	r24,r23,0x3f00		/* get vector offset */
+	stw	r24,TRAP(r21)
+	li	r22,0
+	stw	r22,RESULT(r21)
+	mtspr	SPRG2,r22		/* r1 is now kernel sp */
+
+	lwz	r24,0(r23)		/* virtual address of handler */
+	lwz	r23,4(r23)		/* where to go when done */
+	mtspr	SRR0,r24
+	mtspr	SRR1,r20
+	mtlr	r23
+	SYNC
+	rfi				/* jump to handler, enable MMU */
+
+int_return:
+	mfmsr	r28		/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC			/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SRR0,r2
+	mtspr	SRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfi
+
+crit_return:
+	mfmsr	r28		/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC			/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SPRN_CSRR0,r2
+	mtspr	SPRN_CSRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfci
+
+mck_return:
+	mfmsr	r28		/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC			/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SPRN_MCSRR0,r2
+	mtspr	SPRN_MCSRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfmci
+
+/* Cache functions.
+*/
+.globl invalidate_icache
+invalidate_icache:
+	mfspr	r0,L1CSR1
+	ori	r0,r0,L1CSR1_ICFI
+	msync
+	isync
+	mtspr	L1CSR1,r0
+	isync
+	blr				/* entire I cache */
+
+.globl invalidate_dcache
+invalidate_dcache:
+	mfspr	r0,L1CSR0
+	ori	r0,r0,L1CSR0_DCFI
+	msync
+	isync
+	mtspr	L1CSR0,r0
+	isync
+	blr
+
+	.globl	icache_enable
+icache_enable:
+	mflr	r8
+	bl	invalidate_icache
+	mtlr	r8
+	isync
+	mfspr	r4,L1CSR1
+	ori	r4,r4,0x0001
+	oris	r4,r4,0x0001
+	mtspr	L1CSR1,r4
+	isync
+	blr
+
+	.globl	icache_disable
+icache_disable:
+	mfspr	r0,L1CSR1
+	lis	r3,0
+	ori	r3,r3,L1CSR1_ICE
+	andc	r0,r0,r3
+	mtspr	L1CSR1,r0
+	isync
+	blr
+
+	.globl	icache_status
+icache_status:
+	mfspr	r3,L1CSR1
+	andi.	r3,r3,L1CSR1_ICE
+	blr
+
+	.globl	dcache_enable
+dcache_enable:
+	mflr	r8
+	bl	invalidate_dcache
+	mtlr	r8
+	isync
+	mfspr	r0,L1CSR0
+	ori	r0,r0,0x0001
+	oris	r0,r0,0x0001
+	msync
+	isync
+	mtspr	L1CSR0,r0
+	isync
+	blr
+
+	.globl	dcache_disable
+dcache_disable:
+	mfspr	r3,L1CSR0
+	lis	r4,0
+	ori	r4,r4,L1CSR0_DCE
+	andc	r3,r3,r4
+	mtspr	L1CSR0,r0
+	isync
+	blr
+
+	.globl	dcache_status
+dcache_status:
+	mfspr	r3,L1CSR0
+	andi.	r3,r3,L1CSR0_DCE
+	blr
+
+	.globl get_pir
+get_pir:
+	mfspr	r3,PIR
+	blr
+
+	.globl get_pvr
+get_pvr:
+	mfspr	r3,PVR
+	blr
+
+	.globl get_svr
+get_svr:
+	mfspr	r3,SVR
+	blr
+
+	.globl wr_tcr
+wr_tcr:
+	mtspr	TCR,r3
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 in8 */
+/* Description:	 Input 8 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	in8
+in8:
+	lbz	r3,0x0000(r3)
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 out8 */
+/* Description:	 Output 8 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	out8
+out8:
+	stb	r4,0x0000(r3)
+	sync
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 out16 */
+/* Description:	 Output 16 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	out16
+out16:
+	sth	r4,0x0000(r3)
+	sync
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 out16r */
+/* Description:	 Byte reverse and output 16 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	out16r
+out16r:
+	sthbrx	r4,r0,r3
+	sync
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 out32 */
+/* Description:	 Output 32 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	out32
+out32:
+	stw	r4,0x0000(r3)
+	sync
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 out32r */
+/* Description:	 Byte reverse and output 32 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	out32r
+out32r:
+	stwbrx	r4,r0,r3
+	sync
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 in16 */
+/* Description:	 Input 16 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	in16
+in16:
+	lhz	r3,0x0000(r3)
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 in16r */
+/* Description:	 Input 16 bits and byte reverse */
+/*------------------------------------------------------------------------------- */
+	.globl	in16r
+in16r:
+	lhbrx	r3,r0,r3
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 in32 */
+/* Description:	 Input 32 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	in32
+in32:
+	lwz	3,0x0000(3)
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 in32r */
+/* Description:	 Input 32 bits and byte reverse */
+/*------------------------------------------------------------------------------- */
+	.globl	in32r
+in32r:
+	lwbrx	r3,r0,r3
+	blr
+#endif  /* !CONFIG_NAND_SPL */
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void write_tlb(mas0, mas1, mas2, mas3, mas7)
+ */
+	.globl	write_tlb
+write_tlb:
+	mtspr	MAS0,r3
+	mtspr	MAS1,r4
+	mtspr	MAS2,r5
+	mtspr	MAS3,r6
+#ifdef CONFIG_ENABLE_36BIT_PHYS
+	mtspr	MAS7,r7
+#endif
+	li	r3,0
+#ifdef CONFIG_SYS_BOOK3E_HV
+	mtspr	MAS8,r3
+#endif
+	isync
+	tlbwe
+	msync
+	isync
+	blr
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+	.globl	relocate_code
+relocate_code:
+	mr	r1,r3		/* Set new stack pointer		*/
+	mr	r9,r4		/* Save copy of Init Data pointer	*/
+	mr	r10,r5		/* Save copy of Destination Address	*/
+
+	GET_GOT
+	mr	r3,r5				/* Destination Address	*/
+	lis	r4,CONFIG_SYS_MONITOR_BASE@h		/* Source      Address	*/
+	ori	r4,r4,CONFIG_SYS_MONITOR_BASE@l
+	lwz	r5,GOT(__init_end)
+	sub	r5,r5,r4
+	li	r6,CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size	*/
+
+	/*
+	 * Fix GOT pointer:
+	 *
+	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+	 *
+	 * Offset:
+	 */
+	sub	r15,r10,r4
+
+	/* First our own GOT */
+	add	r12,r12,r15
+	/* the the one used by the C code */
+	add	r30,r30,r15
+
+	/*
+	 * Now relocate code
+	 */
+
+	cmplw	cr1,r3,r4
+	addi	r0,r5,3
+	srwi.	r0,r0,2
+	beq	cr1,4f		/* In place copy is not necessary	*/
+	beq	7f		/* Protect against 0 count		*/
+	mtctr	r0
+	bge	cr1,2f
+
+	la	r8,-4(r4)
+	la	r7,-4(r3)
+1:	lwzu	r0,4(r8)
+	stwu	r0,4(r7)
+	bdnz	1b
+	b	4f
+
+2:	slwi	r0,r0,2
+	add	r8,r4,r0
+	add	r7,r3,r0
+3:	lwzu	r0,-4(r8)
+	stwu	r0,-4(r7)
+	bdnz	3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:	cmpwi	r6,0
+	add	r5,r3,r5
+	beq	7f		/* Always flush prefetch queue in any case */
+	subi	r0,r6,1
+	andc	r3,r3,r0
+	mr	r4,r3
+5:	dcbst	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	5b
+	sync			/* Wait for all dcbst to complete on bus */
+	mr	r4,r3
+6:	icbi	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	6b
+7:	sync			/* Wait for all icbi to complete on bus */
+	isync
+
+	/*
+	 * Re-point the IVPR at RAM
+	 */
+	mtspr	IVPR,r10
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+	addi	r0,r10,in_ram - _start + _START_OFFSET
+	mtlr	r0
+	blr				/* NEVER RETURNS! */
+	.globl	in_ram
+in_ram:
+
+	/*
+	 * Relocation Function, r12 point to got2+0x8000
+	 *
+	 * Adjust got2 pointers, no need to check for 0, this code
+	 * already puts a few entries in the table.
+	 */
+	li	r0,__got2_entries@sectoff@l
+	la	r3,GOT(_GOT2_TABLE_)
+	lwz	r11,GOT(_GOT2_TABLE_)
+	mtctr	r0
+	sub	r11,r3,r11
+	addi	r3,r3,-4
+1:	lwzu	r0,4(r3)
+	cmpwi	r0,0
+	beq-	2f
+	add	r0,r0,r11
+	stw	r0,0(r3)
+2:	bdnz	1b
+
+	/*
+	 * Now adjust the fixups and the pointers to the fixups
+	 * in case we need to move ourselves again.
+	 */
+	li	r0,__fixup_entries@sectoff@l
+	lwz	r3,GOT(_FIXUP_TABLE_)
+	cmpwi	r0,0
+	mtctr	r0
+	addi	r3,r3,-4
+	beq	4f
+3:	lwzu	r4,4(r3)
+	lwzux	r0,r4,r11
+	add	r0,r0,r11
+	stw	r10,0(r3)
+	stw	r0,0(r4)
+	bdnz	3b
+4:
+clear_bss:
+	/*
+	 * Now clear BSS segment
+	 */
+	lwz	r3,GOT(__bss_start)
+	lwz	r4,GOT(_end)
+
+	cmplw	0,r3,r4
+	beq	6f
+
+	li	r0,0
+5:
+	stw	r0,0(r3)
+	addi	r3,r3,4
+	cmplw	0,r3,r4
+	bne	5b
+6:
+
+	mr	r3,r9		/* Init Data pointer		*/
+	mr	r4,r10		/* Destination Address		*/
+	bl	board_init_r
+
+#ifndef CONFIG_NAND_SPL
+	/*
+	 * Copy exception vector code to low memory
+	 *
+	 * r3: dest_addr
+	 * r7: source address, r8: end address, r9: target address
+	 */
+	.globl	trap_init
+trap_init:
+	mflr	r4			/* save link register		*/
+	GET_GOT
+	lwz	r7,GOT(_start_of_vectors)
+	lwz	r8,GOT(_end_of_vectors)
+
+	li	r9,0x100		/* reset vector always at 0x100 */
+
+	cmplw	0,r7,r8
+	bgelr				/* return if r7>=r8 - just in case */
+1:
+	lwz	r0,0(r7)
+	stw	r0,0(r9)
+	addi	r7,r7,4
+	addi	r9,r9,4
+	cmplw	0,r7,r8
+	bne	1b
+
+	/*
+	 * relocate `hdlr' and `int_return' entries
+	 */
+	li	r7,.L_CriticalInput - _start + _START_OFFSET
+	bl	trap_reloc
+	li	r7,.L_MachineCheck - _start + _START_OFFSET
+	bl	trap_reloc
+	li	r7,.L_DataStorage - _start + _START_OFFSET
+	bl	trap_reloc
+	li	r7,.L_InstStorage - _start + _START_OFFSET
+	bl	trap_reloc
+	li	r7,.L_ExtInterrupt - _start + _START_OFFSET
+	bl	trap_reloc
+	li	r7,.L_Alignment - _start + _START_OFFSET
+	bl	trap_reloc
+	li	r7,.L_ProgramCheck - _start + _START_OFFSET
+	bl	trap_reloc
+	li	r7,.L_FPUnavailable - _start + _START_OFFSET
+	bl	trap_reloc
+	li	r7,.L_Decrementer - _start + _START_OFFSET
+	bl	trap_reloc
+	li	r7,.L_IntervalTimer - _start + _START_OFFSET
+	li	r8,_end_of_vectors - _start + _START_OFFSET
+2:
+	bl	trap_reloc
+	addi	r7,r7,0x100		/* next exception vector	*/
+	cmplw	0,r7,r8
+	blt	2b
+
+	lis	r7,0x0
+	mtspr	IVPR,r7
+
+	mtlr	r4			/* restore link register	*/
+	blr
+
+.globl unlock_ram_in_cache
+unlock_ram_in_cache:
+	/* invalidate the INIT_RAM section */
+	lis	r3,(CONFIG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@h
+	ori	r3,r3,(CONFIG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@l
+	mfspr	r4,L1CFG0
+	andi.	r4,r4,0x1ff
+	slwi	r4,r4,(10 - 1 - L1_CACHE_SHIFT)
+	mtctr	r4
+1:	dcbi	r0,r3
+	addi	r3,r3,CONFIG_SYS_CACHELINE_SIZE
+	bdnz	1b
+	sync
+
+	/* Invalidate the TLB entries for the cache */
+	lis	r3,CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
+	tlbivax	0,r3
+	addi	r3,r3,0x1000
+	tlbivax	0,r3
+	addi	r3,r3,0x1000
+	tlbivax	0,r3
+	addi	r3,r3,0x1000
+	tlbivax	0,r3
+	isync
+	blr
+
+.globl flush_dcache
+flush_dcache:
+	mfspr	r3,SPRN_L1CFG0
+
+	rlwinm	r5,r3,9,3	/* Extract cache block size */
+	twlgti	r5,1		/* Only 32 and 64 byte cache blocks
+				 * are currently defined.
+				 */
+	li	r4,32
+	subfic	r6,r5,2		/* r6 = log2(1KiB / cache block size) -
+				 *      log2(number of ways)
+				 */
+	slw	r5,r4,r5	/* r5 = cache block size */
+
+	rlwinm	r7,r3,0,0xff	/* Extract number of KiB in the cache */
+	mulli	r7,r7,13	/* An 8-way cache will require 13
+				 * loads per set.
+				 */
+	slw	r7,r7,r6
+
+	/* save off HID0 and set DCFA */
+	mfspr	r8,SPRN_HID0
+	ori	r9,r8,HID0_DCFA@l
+	mtspr	SPRN_HID0,r9
+	isync
+
+	lis	r4,0
+	mtctr	r7
+
+1:	lwz	r3,0(r4)	/* Load... */
+	add	r4,r4,r5
+	bdnz	1b
+
+	msync
+	lis	r4,0
+	mtctr	r7
+
+1:	dcbf	0,r4		/* ...and flush. */
+	add	r4,r4,r5
+	bdnz	1b
+
+	/* restore HID0 */
+	mtspr	SPRN_HID0,r8
+	isync
+
+	blr
+
+.globl setup_ivors
+setup_ivors:
+
+#include "fixed_ivor.S"
+	blr
+#endif /* !CONFIG_NAND_SPL */
diff --git a/arch/powerpc/cpu/mpc85xx/tlb.c b/arch/powerpc/cpu/mpc85xx/tlb.c
new file mode 100644
index 0000000..b3037ac
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/tlb.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#ifdef CONFIG_ADDR_MAP
+#include <addr_map.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void invalidate_tlb(u8 tlb)
+{
+	if (tlb == 0)
+		mtspr(MMUCSR0, 0x4);
+	if (tlb == 1)
+		mtspr(MMUCSR0, 0x2);
+}
+
+void init_tlbs(void)
+{
+	int i;
+
+	for (i = 0; i < num_tlb_entries; i++) {
+		write_tlb(tlb_table[i].mas0,
+			  tlb_table[i].mas1,
+			  tlb_table[i].mas2,
+			  tlb_table[i].mas3,
+			  tlb_table[i].mas7);
+	}
+
+	return ;
+}
+
+#ifndef CONFIG_NAND_SPL
+static inline void use_tlb_cam(u8 idx)
+{
+	int i = idx / 32;
+	int bit = idx % 32;
+
+	gd->used_tlb_cams[i] |= (1 << bit);
+}
+
+static inline void free_tlb_cam(u8 idx)
+{
+	int i = idx / 32;
+	int bit = idx % 32;
+
+	gd->used_tlb_cams[i] &= ~(1 << bit);
+}
+
+void init_used_tlb_cams(void)
+{
+	int i;
+	unsigned int num_cam = mfspr(SPRN_TLB1CFG) & 0xfff;
+
+	for (i = 0; i < ((CONFIG_SYS_NUM_TLBCAMS+31)/32); i++)
+		gd->used_tlb_cams[i] = 0;
+
+	/* walk all the entries */
+	for (i = 0; i < num_cam; i++) {
+		u32 _mas1;
+
+		mtspr(MAS0, FSL_BOOKE_MAS0(1, i, 0));
+
+		asm volatile("tlbre;isync");
+		_mas1 = mfspr(MAS1);
+
+		/* if the entry isn't valid skip it */
+		if ((_mas1 & MAS1_VALID))
+			use_tlb_cam(i);
+	}
+}
+
+int find_free_tlbcam(void)
+{
+	int i;
+	u32 idx;
+
+	for (i = 0; i < ((CONFIG_SYS_NUM_TLBCAMS+31)/32); i++) {
+		idx = ffz(gd->used_tlb_cams[i]);
+
+		if (idx != 32)
+			break;
+	}
+
+	idx += i * 32;
+
+	if (idx >= CONFIG_SYS_NUM_TLBCAMS)
+		return -1;
+
+	return idx;
+}
+
+void set_tlb(u8 tlb, u32 epn, u64 rpn,
+	     u8 perms, u8 wimge,
+	     u8 ts, u8 esel, u8 tsize, u8 iprot)
+{
+	u32 _mas0, _mas1, _mas2, _mas3, _mas7;
+
+	if (tlb == 1)
+		use_tlb_cam(esel);
+
+	_mas0 = FSL_BOOKE_MAS0(tlb, esel, 0);
+	_mas1 = FSL_BOOKE_MAS1(1, iprot, 0, ts, tsize);
+	_mas2 = FSL_BOOKE_MAS2(epn, wimge);
+	_mas3 = FSL_BOOKE_MAS3(rpn, 0, perms);
+	_mas7 = FSL_BOOKE_MAS7(rpn);
+
+	write_tlb(_mas0, _mas1, _mas2, _mas3, _mas7);
+
+#ifdef CONFIG_ADDR_MAP
+	if ((tlb == 1) && (gd->flags & GD_FLG_RELOC))
+		addrmap_set_entry(epn, rpn, (1UL << ((tsize * 2) + 10)), esel);
+#endif
+}
+
+void disable_tlb(u8 esel)
+{
+	u32 _mas0, _mas1, _mas2, _mas3, _mas7;
+
+	free_tlb_cam(esel);
+
+	_mas0 = FSL_BOOKE_MAS0(1, esel, 0);
+	_mas1 = 0;
+	_mas2 = 0;
+	_mas3 = 0;
+	_mas7 = 0;
+
+	mtspr(MAS0, _mas0);
+	mtspr(MAS1, _mas1);
+	mtspr(MAS2, _mas2);
+	mtspr(MAS3, _mas3);
+#ifdef CONFIG_ENABLE_36BIT_PHYS
+	mtspr(MAS7, _mas7);
+#endif
+	asm volatile("isync;msync;tlbwe;isync");
+
+#ifdef CONFIG_ADDR_MAP
+	if (gd->flags & GD_FLG_RELOC)
+		addrmap_set_entry(0, 0, 0, esel);
+#endif
+}
+
+static void tlbsx (const volatile unsigned *addr)
+{
+	__asm__ __volatile__ ("tlbsx 0,%0" : : "r" (addr), "m" (*addr));
+}
+
+/* return -1 if we didn't find anything */
+int find_tlb_idx(void *addr, u8 tlbsel)
+{
+	u32 _mas0, _mas1;
+
+	/* zero out Search PID, AS */
+	mtspr(MAS6, 0);
+
+	tlbsx(addr);
+
+	_mas0 = mfspr(MAS0);
+	_mas1 = mfspr(MAS1);
+
+	/* we found something, and its in the TLB we expect */
+	if ((MAS1_VALID & _mas1) &&
+		(MAS0_TLBSEL(tlbsel) == (_mas0 & MAS0_TLBSEL_MSK))) {
+		return ((_mas0 & MAS0_ESEL_MSK) >> 16);
+	}
+
+	return -1;
+}
+
+#ifdef CONFIG_ADDR_MAP
+void init_addr_map(void)
+{
+	int i;
+	unsigned int num_cam = mfspr(SPRN_TLB1CFG) & 0xfff;
+
+	/* walk all the entries */
+	for (i = 0; i < num_cam; i++) {
+		unsigned long epn;
+		u32 tsize, _mas1;
+		phys_addr_t rpn;
+
+		mtspr(MAS0, FSL_BOOKE_MAS0(1, i, 0));
+
+		asm volatile("tlbre;isync");
+		_mas1 = mfspr(MAS1);
+
+		/* if the entry isn't valid skip it */
+		if (!(_mas1 & MAS1_VALID))
+			continue;
+
+		tsize = (_mas1 >> 8) & 0xf;
+		epn = mfspr(MAS2) & MAS2_EPN;
+		rpn = mfspr(MAS3) & MAS3_RPN;
+#ifdef CONFIG_ENABLE_36BIT_PHYS
+		rpn |= ((phys_addr_t)mfspr(MAS7)) << 32;
+#endif
+
+		addrmap_set_entry(epn, rpn, (1UL << ((tsize * 2) + 10)), i);
+	}
+
+	return ;
+}
+#endif
+
+unsigned int setup_ddr_tlbs(unsigned int memsize_in_meg)
+{
+	int i;
+	unsigned int tlb_size;
+	unsigned int ram_tlb_address = (unsigned int)CONFIG_SYS_DDR_SDRAM_BASE;
+	unsigned int max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf;
+	u64 size, memsize = (u64)memsize_in_meg << 20;
+
+	size = min(memsize, CONFIG_MAX_MEM_MAPPED);
+
+	/* Convert (4^max) kB to (2^max) bytes */
+	max_cam = max_cam * 2 + 10;
+
+	for (i = 0; size && i < 8; i++) {
+		int ram_tlb_index = find_free_tlbcam();
+		u32 camsize = __ilog2_u64(size) & ~1U;
+		u32 align = __ilog2(ram_tlb_address) & ~1U;
+
+		if (ram_tlb_index == -1)
+			break;
+
+		if (align == -2) align = max_cam;
+		if (camsize > align)
+			camsize = align;
+
+		if (camsize > max_cam)
+			camsize = max_cam;
+
+		tlb_size = (camsize - 10) / 2;
+
+		set_tlb(1, ram_tlb_address, ram_tlb_address,
+			MAS3_SX|MAS3_SW|MAS3_SR, 0,
+			0, ram_tlb_index, tlb_size, 1);
+
+		size -= 1ULL << camsize;
+		memsize -= 1ULL << camsize;
+		ram_tlb_address += 1UL << camsize;
+	}
+
+	if (memsize)
+		print_size(memsize, " left unmapped\n");
+
+	/*
+	 * Confirm that the requested amount of memory was mapped.
+	 */
+	return memsize_in_meg;
+}
+#endif /* !CONFIG_NAND_SPL */
diff --git a/arch/powerpc/cpu/mpc85xx/traps.c b/arch/powerpc/cpu/mpc85xx/traps.c
new file mode 100644
index 0000000..7e96664
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/traps.c
@@ -0,0 +1,325 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright 2007 Freescale Semiconductor.
+ * Copyright (C) 2003 Motorola
+ * Modified by Xianghua Xiao(x.xiao@motorola.com)
+ *
+ * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+/*
+ * End of addressable memory.  This may be less than the actual
+ * amount of memory on the system if we're unable to keep all
+ * the memory mapped in.
+ */
+extern ulong get_effective_memsize(void);
+#define END_OF_MEM (gd->bd->bi_memstart + get_effective_memsize())
+
+static __inline__ void set_tsr(unsigned long val)
+{
+	asm volatile("mtspr 0x150, %0" : : "r" (val));
+}
+
+static __inline__ unsigned long get_esr(void)
+{
+	unsigned long val;
+	asm volatile("mfspr %0, 0x03e" : "=r" (val) :);
+	return val;
+}
+
+#define ESR_MCI 0x80000000
+#define ESR_PIL 0x08000000
+#define ESR_PPR 0x04000000
+#define ESR_PTR 0x02000000
+#define ESR_DST 0x00800000
+#define ESR_DIZ 0x00400000
+#define ESR_U0F 0x00008000
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace(unsigned long *sp)
+{
+	int cnt = 0;
+	unsigned long i;
+
+	printf("Call backtrace: ");
+	while (sp) {
+		if ((uint)sp > END_OF_MEM)
+			break;
+
+		i = sp[1];
+		if (cnt++ % 7 == 0)
+			printf("\n");
+		printf("%08lX ", i);
+		if (cnt > 32) break;
+		sp = (unsigned long *)*sp;
+	}
+	printf("\n");
+}
+
+void show_regs(struct pt_regs * regs)
+{
+	int i;
+
+	printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+	       regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+	printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+	       regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+	       regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+	       regs->msr&MSR_IR ? 1 : 0,
+	       regs->msr&MSR_DR ? 1 : 0);
+
+	printf("\n");
+	for (i = 0;  i < 32;  i++) {
+		if ((i % 8) == 0)
+		{
+			printf("GPR%02d: ", i);
+		}
+
+		printf("%08lX ", regs->gpr[i]);
+		if ((i % 8) == 7)
+		{
+			printf("\n");
+		}
+	}
+}
+
+
+void
+_exception(int signr, struct pt_regs *regs)
+{
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+void
+CritcalInputException(struct pt_regs *regs)
+{
+	panic("Critical Input Exception");
+}
+
+int machinecheck_count = 0;
+int machinecheck_error = 0;
+void
+MachineCheckException(struct pt_regs *regs)
+{
+	unsigned long fixup;
+	unsigned int mcsr, mcsrr0, mcsrr1, mcar;
+
+	/* Probing PCI using config cycles cause this exception
+	 * when a device is not present.  Catch it and return to
+	 * the PCI exception handler.
+	 */
+	if ((fixup = search_exception_table(regs->nip)) != 0) {
+		regs->nip = fixup;
+		return;
+	}
+
+	mcsrr0 = mfspr(SPRN_MCSRR0);
+	mcsrr1 = mfspr(SPRN_MCSRR1);
+	mcsr = mfspr(SPRN_MCSR);
+	mcar = mfspr(SPRN_MCAR);
+
+	machinecheck_count++;
+	machinecheck_error=1;
+
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	printf("Machine check in kernel mode.\n");
+	printf("Caused by (from mcsr): ");
+	printf("mcsr = 0x%08x\n", mcsr);
+	if (mcsr & 0x80000000)
+		printf("Machine check input pin\n");
+	if (mcsr & 0x40000000)
+		printf("Instruction cache parity error\n");
+	if (mcsr & 0x20000000)
+		printf("Data cache push parity error\n");
+	if (mcsr & 0x10000000)
+		printf("Data cache parity error\n");
+	if (mcsr & 0x00000080)
+		printf("Bus instruction address error\n");
+	if (mcsr & 0x00000040)
+		printf("Bus Read address error\n");
+	if (mcsr & 0x00000020)
+		printf("Bus Write address error\n");
+	if (mcsr & 0x00000010)
+		printf("Bus Instruction data bus error\n");
+	if (mcsr & 0x00000008)
+		printf("Bus Read data bus error\n");
+	if (mcsr & 0x00000004)
+		printf("Bus Write bus error\n");
+	if (mcsr & 0x00000002)
+		printf("Bus Instruction parity error\n");
+	if (mcsr & 0x00000001)
+		printf("Bus Read parity error\n");
+
+	show_regs(regs);
+	printf("MCSR=0x%08x \tMCSRR0=0x%08x \nMCSRR1=0x%08x \tMCAR=0x%08x\n",
+	       mcsr, mcsrr0, mcsrr1, mcar);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	if (machinecheck_count > 10) {
+		panic("machine check count too high\n");
+	}
+
+	if (machinecheck_count > 1) {
+		regs->nip += 4; /* skip offending instruction */
+		printf("Skipping current instr, Returning to 0x%08lx\n",
+		       regs->nip);
+	} else {
+		printf("Returning back to 0x%08lx\n",regs->nip);
+	}
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+	long esr_val;
+
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	show_regs(regs);
+
+	esr_val = get_esr();
+	if( esr_val & ESR_PIL )
+		printf( "** Illegal Instruction **\n" );
+	else if( esr_val & ESR_PPR )
+		printf( "** Privileged Instruction **\n" );
+	else if( esr_val & ESR_PTR )
+		printf( "** Trap Instruction **\n" );
+
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Program Check Exception");
+}
+
+void
+PITException(struct pt_regs *regs)
+{
+	/*
+	 * Reset PIT interrupt
+	 */
+	set_tsr(0x0c000000);
+
+	/*
+	 * Call timer_interrupt routine in interrupts.c
+	 */
+	timer_interrupt(NULL);
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+	       regs->nip, regs->msr, regs->trap);
+	_exception(0, regs);
+}
+
+void
+ExtIntException(struct pt_regs *regs)
+{
+	volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC85xx_PIC_ADDR);
+
+	uint vect;
+
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	printf("External Interrupt Exception at PC: %lx, SR: %lx, vector=%lx",
+	       regs->nip, regs->msr, regs->trap);
+	vect = pic->iack0;
+	printf(" irq IACK0@%05x=%d\n",(int)&pic->iack0,vect);
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+}
+
+void
+DebugException(struct pt_regs *regs)
+{
+	printf("Debugger trap at @ %lx\n", regs->nip );
+	show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+	do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading.	 If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/u-boot-nand.lds b/arch/powerpc/cpu/mpc85xx/u-boot-nand.lds
new file mode 100644
index 0000000..5fd3e6c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/u-boot-nand.lds
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+PHDRS
+{
+  text PT_LOAD;
+  bss PT_LOAD;
+}
+
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text)	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data)	}
+  .rel.rodata    : { *(.rel.rodata)	}
+  .rela.rodata   : { *(.rela.rodata)	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	}
+  .plt : { *(.plt) }
+  .text      :
+  {
+    *(.text)
+    *(.got1)
+   } :text
+    _etext = .;
+    PROVIDE (etext = .);
+    .rodata    :
+   {
+    *(.eh_frame)
+    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+  } :text
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x00FF) & 0xFFFFFF00;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+  __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  . = .;
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+  . = .;
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(256);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(256);
+  __init_end = .;
+
+  .bootpg ADDR(.text) - 0x1000 :
+  {
+    arch/powerpc/cpu/mpc85xx/start.o	(.bootpg)
+  } :text = 0xffff
+
+  . = ADDR(.text) + 0x80000;
+
+  __bss_start = .;
+  .bss (NOLOAD)       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  } :bss
+
+  . = ALIGN(4);
+  _end = . ;
+  PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds b/arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds
new file mode 100644
index 0000000..7d9cee9
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds
@@ -0,0 +1,67 @@
+/*
+ * (C) Copyright 2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de
+ *
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SECTIONS
+{
+	. = 0xfff00000;
+	.text : {
+		*(.text)
+	}
+	_etext = .;
+
+	.reloc : {
+		_GOT2_TABLE_ = .;
+		*(.got2)
+		_FIXUP_TABLE_ = .;
+		*(.fixup)
+	}
+	__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+	__fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+	. = ALIGN(8);
+	.data : {
+		*(.rodata*)
+		*(.data*)
+		*(.sdata*)
+	}
+	_edata  =  .;
+
+	. = ALIGN(8);
+	__init_begin = .;
+	__init_end = .;
+
+	.resetvec ADDR(.text) + 0xffc : {
+		*(.resetvec)
+	} = 0xffff
+
+	__bss_start = .;
+	.bss : {
+		*(.sbss)
+		*(.bss)
+	}
+	_end = .;
+}
+ASSERT(__init_end <= 0xfff00ffc, "NAND bootstrap too big");
diff --git a/arch/powerpc/cpu/mpc85xx/u-boot.lds b/arch/powerpc/cpu/mpc85xx/u-boot.lds
new file mode 100644
index 0000000..c88b1f3
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/u-boot.lds
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2007-2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef RESET_VECTOR_ADDRESS
+#define RESET_VECTOR_ADDRESS	0xfffffffc
+#endif
+
+OUTPUT_ARCH(powerpc)
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+PHDRS
+{
+  text PT_LOAD;
+  bss PT_LOAD;
+}
+
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text)	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data)	}
+  .rel.rodata    : { *(.rel.rodata)	}
+  .rela.rodata   : { *(.rela.rodata)	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	}
+  .plt : { *(.plt) }
+  .text      :
+  {
+    *(.text)
+    *(.got1)
+   } :text
+    _etext = .;
+    PROVIDE (etext = .);
+    .rodata    :
+   {
+    *(.eh_frame)
+    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+  } :text
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x00FF) & 0xFFFFFF00;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+  __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  . = .;
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+  . = .;
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(256);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(256);
+  __init_end = .;
+
+  .bootpg RESET_VECTOR_ADDRESS - 0xffc :
+  {
+    arch/powerpc/cpu/mpc85xx/start.o	(.bootpg)
+  } :text = 0xffff
+
+  .resetvec RESET_VECTOR_ADDRESS :
+  {
+    *(.resetvec)
+  } :text = 0xffff
+
+  . = RESET_VECTOR_ADDRESS + 0x4;
+
+  /*
+   * Make sure that the bss segment isn't linked at 0x0, otherwise its
+   * address won't be updated during relocation fixups.  Note that
+   * this is a temporary fix.  Code to dynamically the fixup the bss
+   * location will be added in the future.  When the bss relocation
+   * fixup code is present this workaround should be removed.
+   */
+#if (RESET_VECTOR_ADDRESS == 0xfffffffc)
+  . |= 0x10;
+#endif
+
+  __bss_start = .;
+  .bss (NOLOAD)       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  } :bss
+
+  . = ALIGN(4);
+  _end = . ;
+  PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc86xx/Makefile b/arch/powerpc/cpu/mpc86xx/Makefile
new file mode 100644
index 0000000..daca79a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/Makefile
@@ -0,0 +1,63 @@
+#
+# Copyright 2007 Freescale Semiconductor, Inc.
+# (C) Copyright 2002,2003 Motorola Inc.
+# Xianghua Xiao,X.Xiao@motorola.com
+#
+# (C) Copyright 2004 Freescale Semiconductor. (MC86xx Port)
+# Jeff Brown
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(CPU).a
+
+START	= start.o
+
+SOBJS-y += cache.o
+SOBJS-$(CONFIG_MP) += release.o
+
+COBJS-y	+= cpu.o
+COBJS-y	+= cpu_init.o
+# 8610 & 8641 are identical w/regards to DDR
+COBJS-$(CONFIG_MPC8610) += ddr-8641.o
+COBJS-$(CONFIG_MPC8641) += ddr-8641.o
+COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
+COBJS-y	+= interrupts.o
+COBJS-$(CONFIG_MP) += mp.o
+COBJS-y	+= speed.o
+COBJS-y	+= traps.o
+
+SRCS	:= $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(ASOBJS) $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc86xx/cache.S b/arch/powerpc/cpu/mpc86xx/cache.S
new file mode 100644
index 0000000..0bb058b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/cache.S
@@ -0,0 +1,378 @@
+#include <config.h>
+#include <mpc86xx.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef CACHE_LINE_SIZE
+# define CACHE_LINE_SIZE L1_CACHE_BYTES
+#endif
+
+#if CACHE_LINE_SIZE == 128
+#define LG_CACHE_LINE_SIZE 7
+#elif CACHE_LINE_SIZE == 32
+#define LG_CACHE_LINE_SIZE 5
+#elif CACHE_LINE_SIZE == 16
+#define LG_CACHE_LINE_SIZE 4
+#elif CACHE_LINE_SIZE == 8
+#define LG_CACHE_LINE_SIZE 3
+#else
+# error "Invalid cache line size!"
+#endif
+
+/*
+ * Most of this code is taken from 74xx_7xx/cache.S
+ * and then cleaned up a bit
+ */
+
+/*
+ * Invalidate L1 instruction cache.
+ */
+_GLOBAL(invalidate_l1_instruction_cache)
+	/* use invalidate-all bit in HID0 */
+	mfspr	r3,HID0
+	ori	r3,r3,HID0_ICFI
+	mtspr	HID0,r3
+	isync
+	blr
+
+/*
+ * Invalidate L1 data cache.
+ */
+_GLOBAL(invalidate_l1_data_cache)
+	mfspr	r3,HID0
+	ori	r3,r3,HID0_DCFI
+	mtspr	HID0,r3
+	isync
+	blr
+
+/*
+ * Flush data cache.
+ */
+_GLOBAL(flush_dcache)
+	lis	r3,0
+	lis	r5,CACHE_LINE_SIZE
+flush:
+	cmp	0,1,r3,r5
+	bge	done
+	lwz	r5,0(r3)
+	lis	r5,CACHE_LINE_SIZE
+	addi	r3,r3,0x4
+	b	flush
+done:
+	blr
+/*
+ * Write any modified data cache blocks out to memory
+ * and invalidate the corresponding instruction cache blocks.
+ * This is a no-op on the 601.
+ *
+ * flush_icache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_icache_range)
+	li	r5,CACHE_LINE_SIZE-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,LG_CACHE_LINE_SIZE
+	beqlr
+	mtctr	r4
+	mr	r6,r3
+1:	dcbst	0,r3
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	1b
+	sync				/* wait for dcbst's to get to ram */
+	mtctr	r4
+2:	icbi	0,r6
+	addi	r6,r6,CACHE_LINE_SIZE
+	bdnz	2b
+	sync				/* additional sync needed on g4 */
+	isync
+	blr
+/*
+ * Write any modified data cache blocks out to memory.
+ * Does not invalidate the corresponding cache lines (especially for
+ * any corresponding instruction cache).
+ *
+ * clean_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(clean_dcache_range)
+	li	r5,CACHE_LINE_SIZE-1
+	andc	r3,r3,r5	/* align r3 down to cache line */
+	subf	r4,r3,r4	/* r4 = offset of stop from start of cache line */
+	add	r4,r4,r5	/* r4 += cache_line_size-1 */
+	srwi.	r4,r4,LG_CACHE_LINE_SIZE  /* r4 = number of cache lines to flush */
+	beqlr				  /* if r4 == 0 return */
+	mtctr	r4			  /* ctr = r4 */
+
+	sync
+1:	dcbst	0,r3
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	1b
+	sync				/* wait for dcbst's to get to ram */
+	blr
+
+/*
+ * Write any modified data cache blocks out to memory
+ * and invalidate the corresponding instruction cache blocks.
+ *
+ * flush_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_dcache_range)
+	li	r5,CACHE_LINE_SIZE-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,LG_CACHE_LINE_SIZE
+	beqlr
+	mtctr	r4
+
+	sync
+1:	dcbf	0,r3
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	1b
+	sync				/* wait for dcbf's to get to ram */
+	blr
+
+/*
+ * Like above, but invalidate the D-cache.  This is used by the 8xx
+ * to invalidate the cache so the PPC core doesn't get stale data
+ * from the CPM (no cache snooping here :-).
+ *
+ * invalidate_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(invalidate_dcache_range)
+	li	r5,CACHE_LINE_SIZE-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,LG_CACHE_LINE_SIZE
+	beqlr
+	mtctr	r4
+
+	sync
+1:	dcbi	0,r3
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	1b
+	sync				/* wait for dcbi's to get to ram */
+	blr
+
+/*
+ * Flush a particular page from the data cache to RAM.
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ *
+ *	void __flush_page_to_ram(void *page)
+ */
+_GLOBAL(__flush_page_to_ram)
+	rlwinm	r3,r3,0,0,19		/* Get page base address */
+	li	r4,4096/CACHE_LINE_SIZE	/* Number of lines in a page */
+	mtctr	r4
+	mr	r6,r3
+0:	dcbst	0,r3			/* Write line to ram */
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	0b
+	sync
+	mtctr	r4
+1:	icbi	0,r6
+	addi	r6,r6,CACHE_LINE_SIZE
+	bdnz	1b
+	sync
+	isync
+	blr
+
+/*
+ * Flush a particular page from the instruction cache.
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ *
+ *	void __flush_icache_page(void *page)
+ */
+_GLOBAL(__flush_icache_page)
+	li	r4,4096/CACHE_LINE_SIZE	/* Number of lines in a page */
+	mtctr	r4
+1:	icbi	0,r3
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	1b
+	sync
+	isync
+	blr
+
+/*
+ * Clear a page using the dcbz instruction, which doesn't cause any
+ * memory traffic (except to write out any cache lines which get
+ * displaced).  This only works on cacheable memory.
+ */
+_GLOBAL(clear_page)
+	li	r0,4096/CACHE_LINE_SIZE
+	mtctr	r0
+1:	dcbz	0,r3
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	1b
+	blr
+
+/*
+ * Enable L1 Instruction cache
+ */
+_GLOBAL(icache_enable)
+	mfspr	r3, HID0
+	li	r5, HID0_ICFI|HID0_ILOCK
+	andc	r3, r3, r5
+	ori	r3, r3, HID0_ICE
+	ori	r5, r3, HID0_ICFI
+	mtspr	HID0, r5
+	mtspr	HID0, r3
+	isync
+	blr
+
+/*
+ * Disable L1 Instruction cache
+ */
+_GLOBAL(icache_disable)
+	mflr	r4
+	bl	invalidate_l1_instruction_cache		/* uses r3 */
+	sync
+	mtlr	r4
+	mfspr	r3, HID0
+	li	r5, 0
+	ori	r5, r5, HID0_ICE
+	andc	r3, r3, r5
+	mtspr	HID0, r3
+	isync
+	blr
+
+/*
+ * Is instruction cache enabled?
+ */
+_GLOBAL(icache_status)
+	mfspr	r3, HID0
+	andi.	r3, r3, HID0_ICE
+	blr
+
+
+_GLOBAL(l1dcache_enable)
+	mfspr	r3, HID0
+	li	r5, HID0_DCFI|HID0_DLOCK
+	andc	r3, r3, r5
+	mtspr	HID0, r3		/* no invalidate, unlock */
+	ori	r3, r3, HID0_DCE
+	ori	r5, r3, HID0_DCFI
+	mtspr	HID0, r5		/* enable + invalidate */
+	mtspr	HID0, r3		/* enable */
+	sync
+	blr
+
+/*
+ * Enable data cache(s) - L1 and optionally L2
+ * Calls l2cache_enable. LR saved in r5
+ */
+_GLOBAL(dcache_enable)
+	mfspr	r3, HID0
+	li	r5, HID0_DCFI|HID0_DLOCK
+	andc	r3, r3, r5
+	mtspr	HID0, r3		/* no invalidate, unlock */
+	ori	r3, r3, HID0_DCE
+	ori	r5, r3, HID0_DCFI
+	mtspr	HID0, r5		/* enable + invalidate */
+	mtspr	HID0, r3		/* enable */
+	sync
+#ifdef CONFIG_SYS_L2
+	mflr	r5
+	bl	l2cache_enable		/* uses r3 and r4 */
+	sync
+	mtlr	r5
+#endif
+	blr
+
+
+/*
+ * Disable data cache(s) - L1 and optionally L2
+ * Calls flush_dcache and l2cache_disable_no_flush.
+ * LR saved in r4
+ */
+_GLOBAL(dcache_disable)
+	mflr	r4			/* save link register */
+	bl	flush_dcache	/* uses r3 and r5 */
+	sync
+	mfspr	r3, HID0
+	li	r5, HID0_DCFI|HID0_DLOCK
+	andc	r3, r3, r5
+	mtspr	HID0, r3		/* no invalidate, unlock */
+	li	r5, HID0_DCE|HID0_DCFI
+	andc	r3, r3, r5		/* no enable, no invalidate */
+	mtspr	HID0, r3
+	sync
+#ifdef CONFIG_SYS_L2
+	bl	l2cache_disable_no_flush /* uses r3 */
+#endif
+	mtlr	r4			/* restore link register */
+	blr
+
+/*
+ * Is data cache enabled?
+ */
+_GLOBAL(dcache_status)
+	mfspr	r3, HID0
+	andi.	r3, r3, HID0_DCE
+	blr
+
+/*
+ * Invalidate L2 cache using L2I, assume L2 is enabled
+ */
+_GLOBAL(l2cache_invalidate)
+	mfspr	r3, l2cr
+	rlwinm.	r3, r3, 0, 0, 0
+	beq	1f
+
+	mfspr	r3, l2cr
+	rlwinm	r3, r3, 0, 1, 31
+
+#ifdef	CONFIG_ALTIVEC
+	dssall
+#endif
+	sync
+	mtspr	l2cr, r3
+	sync
+1:	mfspr	r3, l2cr
+	oris	r3, r3, L2CR_L2I@h
+	mtspr	l2cr, r3
+
+invl2:
+	mfspr	r3, l2cr
+	andis.	r3, r3, L2CR_L2I@h
+	bne	invl2
+	blr
+
+/*
+ * Enable L2 cache
+ * Calls l2cache_invalidate. LR is saved in r4
+ */
+_GLOBAL(l2cache_enable)
+	mflr	r4			/* save link register */
+	bl	l2cache_invalidate	/* uses r3 */
+	sync
+	lis	r3, L2_ENABLE@h
+	ori	r3, r3, L2_ENABLE@l
+	mtspr	l2cr, r3
+	isync
+	mtlr	r4			/* restore link register */
+	blr
+
+/*
+ * Disable L2 cache
+ * Calls flush_dcache. LR is saved in r4
+ */
+_GLOBAL(l2cache_disable)
+	mflr	r4			/* save link register */
+	bl	flush_dcache		/* uses r3 and r5 */
+	sync
+	mtlr	r4			/* restore link register */
+l2cache_disable_no_flush:		/* provide way to disable L2 w/o flushing */
+	lis	r3, L2_INIT@h
+	ori	r3, r3, L2_INIT@l
+	mtspr	l2cr, r3
+	isync
+	blr
diff --git a/arch/powerpc/cpu/mpc86xx/config.mk b/arch/powerpc/cpu/mpc86xx/config.mk
new file mode 100644
index 0000000..ca2f837
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/config.mk
@@ -0,0 +1,27 @@
+#
+# (C) Copyright 2004 Freescale Semiconductor.
+# Jeff Brown
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -fPIC -meabi
+
+PLATFORM_CPPFLAGS += -ffixed-r2 -mstring
+PLATFORM_CPPFLAGS += -maltivec -mabi=altivec -msoft-float
diff --git a/arch/powerpc/cpu/mpc86xx/cpu.c b/arch/powerpc/cpu/mpc86xx/cpu.c
new file mode 100644
index 0000000..1887575
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/cpu.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2006,2009-2010 Freescale Semiconductor, Inc.
+ * Jeff Brown
+ * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <mpc86xx.h>
+#include <asm/fsl_law.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Default board reset function
+ */
+static void
+__board_reset(void)
+{
+	/* Do nothing */
+}
+void board_reset(void) __attribute__((weak, alias("__board_reset")));
+
+
+int
+checkcpu(void)
+{
+	sys_info_t sysinfo;
+	uint pvr, svr;
+	uint ver;
+	uint major, minor;
+	char buf1[32], buf2[32];
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	volatile ccsr_gur_t *gur = &immap->im_gur;
+	struct cpu_type *cpu;
+	uint msscr0 = mfspr(MSSCR0);
+
+	svr = get_svr();
+	ver = SVR_SOC_VER(svr);
+	major = SVR_MAJ(svr);
+	minor = SVR_MIN(svr);
+
+	if (cpu_numcores() > 1) {
+#ifndef CONFIG_MP
+		puts("Unicore software on multiprocessor system!!\n"
+		     "To enable mutlticore build define CONFIG_MP\n");
+#endif
+	}
+	puts("CPU:   ");
+
+	cpu = gd->cpu;
+
+	puts(cpu->name);
+
+	printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr);
+	puts("Core:  ");
+
+	pvr = get_pvr();
+	ver = PVR_E600_VER(pvr);
+	major = PVR_E600_MAJ(pvr);
+	minor = PVR_E600_MIN(pvr);
+
+	printf("E600 Core %d", (msscr0 & 0x20) ? 1 : 0 );
+	if (gur->pordevsr & MPC86xx_PORDEVSR_CORE1TE)
+		puts("\n    Core1Translation Enabled");
+	debug(" (MSSCR0=%x, PORDEVSR=%x)", msscr0, gur->pordevsr);
+
+	printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr);
+
+	get_sys_info(&sysinfo);
+
+	puts("Clock Configuration:\n");
+	printf("       CPU:%-4s MHz, ", strmhz(buf1, sysinfo.freqProcessor));
+	printf("MPX:%-4s MHz\n", strmhz(buf1, sysinfo.freqSystemBus));
+	printf("       DDR:%-4s MHz (%s MT/s data rate), ",
+		strmhz(buf1, sysinfo.freqSystemBus / 2),
+		strmhz(buf2, sysinfo.freqSystemBus));
+
+	if (sysinfo.freqLocalBus > LCRR_CLKDIV) {
+		printf("LBC:%-4s MHz\n", strmhz(buf1, sysinfo.freqLocalBus));
+	} else {
+		printf("LBC: unknown (LCRR[CLKDIV] = 0x%02lx)\n",
+		       sysinfo.freqLocalBus);
+	}
+
+	puts("L1:    D-cache 32 KB enabled\n");
+	puts("       I-cache 32 KB enabled\n");
+
+	puts("L2:    ");
+	if (get_l2cr() & 0x80000000) {
+#if defined(CONFIG_MPC8610)
+		puts("256");
+#elif defined(CONFIG_MPC8641)
+		puts("512");
+#endif
+		puts(" KB enabled\n");
+	} else {
+		puts("Disabled\n");
+	}
+
+	return 0;
+}
+
+
+void
+do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+	volatile ccsr_gur_t *gur = &immap->im_gur;
+
+	/* Attempt board-specific reset */
+	board_reset();
+
+	/* Next try asserting HRESET_REQ */
+	out_be32(&gur->rstcr, MPC86xx_RSTCR_HRST_REQ);
+
+	while (1)
+		;
+}
+
+
+/*
+ * Get timebase clock frequency
+ */
+unsigned long
+get_tbclk(void)
+{
+	sys_info_t sys_info;
+
+	get_sys_info(&sys_info);
+	return (sys_info.freqSystemBus + 3L) / 4L;
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void
+watchdog_reset(void)
+{
+#if defined(CONFIG_MPC8610)
+	/*
+	 * This actually feed the hard enabled watchdog.
+	 */
+	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+	volatile ccsr_wdt_t *wdt = &immap->im_wdt;
+	volatile ccsr_gur_t *gur = &immap->im_gur;
+	u32 tmp = gur->pordevsr;
+
+	if (tmp & 0x4000) {
+		wdt->swsrr = 0x556c;
+		wdt->swsrr = 0xaa39;
+	}
+#endif
+}
+#endif	/* CONFIG_WATCHDOG */
+
+/*
+ * Print out the state of various machine registers.
+ * Currently prints out LAWs, BR0/OR0, and BATs
+ */
+void mpc86xx_reginfo(void)
+{
+	immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+	ccsr_lbc_t *lbc = &immap->im_lbc;
+
+	print_bats();
+	print_laws();
+
+	printf ("Local Bus Controller Registers\n"
+		"\tBR0\t0x%08X\tOR0\t0x%08X \n", in_be32(&lbc->br0), in_be32(&lbc->or0));
+	printf("\tBR1\t0x%08X\tOR1\t0x%08X \n", in_be32(&lbc->br1), in_be32(&lbc->or1));
+	printf("\tBR2\t0x%08X\tOR2\t0x%08X \n", in_be32(&lbc->br2), in_be32(&lbc->or2));
+	printf("\tBR3\t0x%08X\tOR3\t0x%08X \n", in_be32(&lbc->br3), in_be32(&lbc->or3));
+	printf("\tBR4\t0x%08X\tOR4\t0x%08X \n", in_be32(&lbc->br4), in_be32(&lbc->or4));
+	printf("\tBR5\t0x%08X\tOR5\t0x%08X \n", in_be32(&lbc->br5), in_be32(&lbc->or5));
+	printf("\tBR6\t0x%08X\tOR6\t0x%08X \n", in_be32(&lbc->br6), in_be32(&lbc->or6));
+	printf("\tBR7\t0x%08X\tOR7\t0x%08X \n", in_be32(&lbc->br7), in_be32(&lbc->or7));
+
+}
+
+/*
+ * Set the DDR BATs to reflect the actual size of DDR.
+ *
+ * dram_size is the actual size of DDR, in bytes
+ *
+ * Note: we assume that CONFIG_MAX_MEM_MAPPED is 2G or smaller as we only
+ * are using a single BAT to cover DDR.
+ *
+ * If this is not true, (e.g. CONFIG_MAX_MEM_MAPPED is 2GB but HID0_XBSEN
+ * is not defined) then we might have a situation where U-Boot will attempt
+ * to relocated itself outside of the region mapped by DBAT0.
+ * This will cause a machine check.
+ *
+ * Currently we are limited to power of two sized DDR since we only use a
+ * single bat.  If a non-power of two size is used that is less than
+ * CONFIG_MAX_MEM_MAPPED u-boot will crash.
+ *
+ */
+void setup_ddr_bat(phys_addr_t dram_size)
+{
+	unsigned long batu, bl;
+
+	bl = TO_BATU_BL(min(dram_size, CONFIG_MAX_MEM_MAPPED));
+
+	if (BATU_SIZE(bl) != dram_size) {
+		u64 sz = (u64)dram_size - BATU_SIZE(bl);
+		print_size(sz, " left unmapped\n");
+	}
+
+	batu = bl | BATU_VS | BATU_VP;
+	write_bat(DBAT0, batu, CONFIG_SYS_DBAT0L);
+	write_bat(IBAT0, batu, CONFIG_SYS_IBAT0L);
+}
diff --git a/arch/powerpc/cpu/mpc86xx/cpu_init.c b/arch/powerpc/cpu/mpc86xx/cpu_init.c
new file mode 100644
index 0000000..b4f047d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/cpu_init.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2004,2009 Freescale Semiconductor, Inc.
+ * Jeff Brown
+ * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * cpu_init.c - low level cpu init
+ */
+
+#include <config.h>
+#include <common.h>
+#include <mpc86xx.h>
+#include <asm/mmu.h>
+#include <asm/fsl_law.h>
+#include <asm/mp.h>
+
+void setup_bats(void);
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Breathe some life into the CPU...
+ *
+ * Set up the memory map
+ * initialize a bunch of registers
+ */
+
+void cpu_init_f(void)
+{
+	volatile immap_t    *immap = (immap_t *)CONFIG_SYS_IMMR;
+	volatile ccsr_lbc_t *memctl = &immap->im_lbc;
+
+	/* Pointer is writable since we allocated a register for it */
+	gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+	/* Clear initial global data */
+	memset ((void *) gd, 0, sizeof (gd_t));
+
+#ifdef CONFIG_FSL_LAW
+	init_laws();
+#endif
+
+	setup_bats();
+
+	/* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary
+	 * addresses - these have to be modified later when FLASH size
+	 * has been determined
+	 */
+
+#if defined(CONFIG_SYS_OR0_REMAP)
+	memctl->or0 = CONFIG_SYS_OR0_REMAP;
+#endif
+#if defined(CONFIG_SYS_OR1_REMAP)
+	memctl->or1 = CONFIG_SYS_OR1_REMAP;
+#endif
+
+	/* now restrict to preliminary range */
+#if defined(CONFIG_SYS_BR0_PRELIM) && defined(CONFIG_SYS_OR0_PRELIM)
+	memctl->br0 = CONFIG_SYS_BR0_PRELIM;
+	memctl->or0 = CONFIG_SYS_OR0_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR1_PRELIM) && defined(CONFIG_SYS_OR1_PRELIM)
+	memctl->or1 = CONFIG_SYS_OR1_PRELIM;
+	memctl->br1 = CONFIG_SYS_BR1_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR2_PRELIM) && defined(CONFIG_SYS_OR2_PRELIM)
+	memctl->or2 = CONFIG_SYS_OR2_PRELIM;
+	memctl->br2 = CONFIG_SYS_BR2_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR3_PRELIM) && defined(CONFIG_SYS_OR3_PRELIM)
+	memctl->or3 = CONFIG_SYS_OR3_PRELIM;
+	memctl->br3 = CONFIG_SYS_BR3_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR4_PRELIM) && defined(CONFIG_SYS_OR4_PRELIM)
+	memctl->or4 = CONFIG_SYS_OR4_PRELIM;
+	memctl->br4 = CONFIG_SYS_BR4_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR5_PRELIM) && defined(CONFIG_SYS_OR5_PRELIM)
+	memctl->or5 = CONFIG_SYS_OR5_PRELIM;
+	memctl->br5 = CONFIG_SYS_BR5_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR6_PRELIM) && defined(CONFIG_SYS_OR6_PRELIM)
+	memctl->or6 = CONFIG_SYS_OR6_PRELIM;
+	memctl->br6 = CONFIG_SYS_BR6_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR7_PRELIM) && defined(CONFIG_SYS_OR7_PRELIM)
+	memctl->or7 = CONFIG_SYS_OR7_PRELIM;
+	memctl->br7 = CONFIG_SYS_BR7_PRELIM;
+#endif
+#if defined(CONFIG_FSL_DMA)
+	dma_init();
+#endif
+
+	/* enable the timebase bit in HID0 */
+	set_hid0(get_hid0() | 0x4000000);
+
+	/* enable EMCP, SYNCBE | ABE bits in HID1 */
+	set_hid1(get_hid1() | 0x80000C00);
+}
+
+/*
+ * initialize higher level parts of CPU like timers
+ */
+int cpu_init_r(void)
+{
+#if defined(CONFIG_MP)
+	setup_mp();
+#endif
+	return 0;
+}
+
+/* Set up BAT registers */
+void setup_bats(void)
+{
+#if defined(CONFIG_SYS_DBAT0U) && defined(CONFIG_SYS_DBAT0L)
+	write_bat(DBAT0, CONFIG_SYS_DBAT0U, CONFIG_SYS_DBAT0L);
+#endif
+#if defined(CONFIG_SYS_IBAT0U) && defined(CONFIG_SYS_IBAT0L)
+	write_bat(IBAT0, CONFIG_SYS_IBAT0U, CONFIG_SYS_IBAT0L);
+#endif
+	write_bat(DBAT1, CONFIG_SYS_DBAT1U, CONFIG_SYS_DBAT1L);
+	write_bat(IBAT1, CONFIG_SYS_IBAT1U, CONFIG_SYS_IBAT1L);
+	write_bat(DBAT2, CONFIG_SYS_DBAT2U, CONFIG_SYS_DBAT2L);
+	write_bat(IBAT2, CONFIG_SYS_IBAT2U, CONFIG_SYS_IBAT2L);
+	write_bat(DBAT3, CONFIG_SYS_DBAT3U, CONFIG_SYS_DBAT3L);
+	write_bat(IBAT3, CONFIG_SYS_IBAT3U, CONFIG_SYS_IBAT3L);
+	write_bat(DBAT4, CONFIG_SYS_DBAT4U, CONFIG_SYS_DBAT4L);
+	write_bat(IBAT4, CONFIG_SYS_IBAT4U, CONFIG_SYS_IBAT4L);
+	write_bat(DBAT5, CONFIG_SYS_DBAT5U, CONFIG_SYS_DBAT5L);
+	write_bat(IBAT5, CONFIG_SYS_IBAT5U, CONFIG_SYS_IBAT5L);
+	write_bat(DBAT6, CONFIG_SYS_DBAT6U, CONFIG_SYS_DBAT6L);
+	write_bat(IBAT6, CONFIG_SYS_IBAT6U, CONFIG_SYS_IBAT6L);
+	write_bat(DBAT7, CONFIG_SYS_DBAT7U, CONFIG_SYS_DBAT7L);
+	write_bat(IBAT7, CONFIG_SYS_IBAT7U, CONFIG_SYS_IBAT7L);
+
+	return;
+}
+
+#ifdef CONFIG_ADDR_MAP
+/* Initialize address mapping array */
+void init_addr_map(void)
+{
+	int i;
+	ppc_bat_t bat = DBAT0;
+	phys_size_t size;
+	unsigned long upper, lower;
+
+	for (i = 0; i < CONFIG_SYS_NUM_ADDR_MAP; i++, bat++) {
+		if (read_bat(bat, &upper, &lower) != -1) {
+			if (!BATU_VALID(upper))
+				size = 0;
+			else
+				size = BATU_SIZE(upper);
+			addrmap_set_entry(BATU_VADDR(upper), BATL_PADDR(lower),
+					  size, i);
+		}
+#ifdef CONFIG_HIGH_BATS
+		/* High bats are not contiguous with low BAT numbers */
+		if (bat == DBAT3)
+			bat = DBAT4 - 1;
+#endif
+	}
+}
+#endif
diff --git a/arch/powerpc/cpu/mpc86xx/ddr-8641.c b/arch/powerpc/cpu/mpc86xx/ddr-8641.c
new file mode 100644
index 0000000..b8f2c93
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/ddr-8641.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2008 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+			     unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr;
+
+	switch (ctrl_num) {
+	case 0:
+		ddr = (void *)CONFIG_SYS_MPC86xx_DDR_ADDR;
+		break;
+	case 1:
+		ddr = (void *)CONFIG_SYS_MPC86xx_DDR2_ADDR;
+		break;
+	default:
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		if (i == 0) {
+			out_be32(&ddr->cs0_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs0_config, regs->cs[i].config);
+
+		} else if (i == 1) {
+			out_be32(&ddr->cs1_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs1_config, regs->cs[i].config);
+
+		} else if (i == 2) {
+			out_be32(&ddr->cs2_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs2_config, regs->cs[i].config);
+
+		} else if (i == 3) {
+			out_be32(&ddr->cs3_bnds, regs->cs[i].bnds);
+			out_be32(&ddr->cs3_config, regs->cs[i].config);
+		}
+	}
+
+	out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3);
+	out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0);
+	out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1);
+	out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+	out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+	out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
+	out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
+	out_be32(&ddr->sdram_mode_cntl, regs->ddr_sdram_md_cntl);
+	out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
+	out_be32(&ddr->sdram_data_init, regs->ddr_data_init);
+	out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
+	out_be32(&ddr->init_addr, regs->ddr_init_addr);
+	out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+
+	debug("before go\n");
+
+	/*
+	 * 200 painful micro-seconds must elapse between
+	 * the DDR clock setup and the DDR config enable.
+	 */
+	udelay(200);
+	asm volatile("sync;isync");
+
+	out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg);
+
+	/*
+	 * Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done
+	 */
+	while (in_be32(&ddr->sdram_cfg_2) & 0x10) {
+		udelay(10000);		/* throttle polling rate */
+	}
+}
diff --git a/arch/powerpc/cpu/mpc86xx/fdt.c b/arch/powerpc/cpu/mpc86xx/fdt.c
new file mode 100644
index 0000000..51f3f4c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/fdt.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <asm/mp.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern void ft_fixup_num_cores(void *blob);
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+#ifdef CONFIG_MP
+	int off;
+	u32 bootpg = determine_mp_bootpg();
+#endif
+
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+			     "timebase-frequency", bd->bi_busfreq / 4, 1);
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+			     "bus-frequency", bd->bi_busfreq, 1);
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+			     "clock-frequency", bd->bi_intfreq, 1);
+	do_fixup_by_prop_u32(blob, "device_type", "soc", 4,
+			     "bus-frequency", bd->bi_busfreq, 1);
+
+#if defined(CONFIG_MPC8641)
+	do_fixup_by_compat_u32(blob, "fsl,mpc8641-localbus",
+			       "bus-frequency", gd->lbc_clk, 1);
+#endif
+	do_fixup_by_compat_u32(blob, "fsl,elbc",
+			       "bus-frequency", gd->lbc_clk, 1);
+
+	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+
+#if defined(CONFIG_HAS_ETH0) || defined(CONFIG_HAS_ETH1) \
+    || defined(CONFIG_HAS_ETH2) || defined(CONFIG_HAS_ETH3)
+	fdt_fixup_ethernet(blob);
+#endif
+
+#ifdef CONFIG_SYS_NS16550
+	do_fixup_by_compat_u32(blob, "ns16550",
+			       "clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
+#endif
+
+#ifdef CONFIG_MP
+	/* Reserve the boot page so OSes dont use it */
+	off = fdt_add_mem_rsv(blob, bootpg, (u64)4096);
+	if (off < 0)
+		printf("%s: %s\n", __FUNCTION__, fdt_strerror(off));
+#endif
+	ft_fixup_num_cores(blob);
+}
diff --git a/arch/powerpc/cpu/mpc86xx/interrupts.c b/arch/powerpc/cpu/mpc86xx/interrupts.c
new file mode 100644
index 0000000..c78fc72
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/interrupts.c
@@ -0,0 +1,115 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002 (440 port)
+ * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com
+ *
+ * (C) Copyright 2003 Motorola Inc. (MPC85xx port)
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ *
+ * (C) Copyright 2004, 2007 Freescale Semiconductor. (MPC86xx Port)
+ * Jeff Brown
+ * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc86xx.h>
+#include <command.h>
+#include <asm/processor.h>
+
+int interrupt_init_cpu(unsigned long *decrementer_count)
+{
+	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	volatile ccsr_pic_t *pic = &immr->im_pic;
+
+	pic->gcr = MPC86xx_PICGCR_RST;
+	while (pic->gcr & MPC86xx_PICGCR_RST)
+		;
+	pic->gcr = MPC86xx_PICGCR_MODE;
+
+	*decrementer_count = get_tbclk() / CONFIG_SYS_HZ;
+	debug("interrupt init: tbclk() = %d MHz, decrementer_count = %ld\n",
+	      (get_tbclk() / 1000000),
+	      *decrementer_count);
+
+#ifdef CONFIG_INTERRUPTS
+
+	pic->iivpr1 = 0x810001;	/* 50220 enable mcm interrupts */
+	debug("iivpr1@%x = %x\n", &pic->iivpr1, pic->iivpr1);
+
+	pic->iivpr2 = 0x810002;	/* 50240 enable ddr interrupts */
+	debug("iivpr2@%x = %x\n", &pic->iivpr2, pic->iivpr2);
+
+	pic->iivpr3 = 0x810003;	/* 50260 enable lbc interrupts */
+	debug("iivpr3@%x = %x\n", &pic->iivpr3, pic->iivpr3);
+
+#if defined(CONFIG_PCI1) || defined(CONFIG_PCIE1)
+	pic->iivpr8 = 0x810008;	/* enable pcie1 interrupts */
+	debug("iivpr8@%x = %x\n", &pic->iivpr8, pic->iivpr8);
+#endif
+#if defined(CONFIG_PCI2) || defined(CONFIG_PCIE2)
+	pic->iivpr9 = 0x810009;	/* enable pcie2 interrupts */
+	debug("iivpr9@%x = %x\n", &pic->iivpr9, pic->iivpr9);
+#endif
+
+	pic->ctpr = 0;	/* 40080 clear current task priority register */
+#endif
+
+	return 0;
+}
+
+/*
+ * timer_interrupt - gets called when the decrementer overflows,
+ * with interrupts disabled.
+ * Trivial implementation - no need to be really accurate.
+ */
+void timer_interrupt_cpu(struct pt_regs *regs)
+{
+	/* nothing to do here */
+}
+
+/*
+ * Install and free a interrupt handler. Not implemented yet.
+ */
+void irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
+{
+}
+
+void irq_free_handler(int vec)
+{
+}
+
+/*
+ * irqinfo - print information about PCI devices,not implemented.
+ */
+int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	return 0;
+}
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt(struct pt_regs *regs)
+{
+	puts("external_interrupt (oops!)\n");
+}
diff --git a/arch/powerpc/cpu/mpc86xx/mp.c b/arch/powerpc/cpu/mpc86xx/mp.c
new file mode 100644
index 0000000..b4a0faa
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/mp.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <ioports.h>
+#include <lmb.h>
+#include <asm/io.h>
+#include <asm/mp.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int cpu_reset(int nr)
+{
+	/* dummy function so common/cmd_mp.c will build
+	 * should be implemented in the future, when cpu_release()
+	 * is supported.  Be aware there may be a similiar bug
+	 * as exists on MPC85xx w/its PIC having a timing window
+	 * associated to resetting the core */
+	return 1;
+}
+
+int cpu_status(int nr)
+{
+	/* dummy function so common/cmd_mp.c will build */
+	return 0;
+}
+
+int cpu_disable(int nr)
+{
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_CCSRBAR;
+	volatile ccsr_gur_t *gur = &immap->im_gur;
+
+	switch (nr) {
+	case 0:
+		setbits_be32(&gur->devdisr, MPC86xx_DEVDISR_CPU0);
+		break;
+	case 1:
+		setbits_be32(&gur->devdisr, MPC86xx_DEVDISR_CPU1);
+		break;
+	default:
+		printf("Invalid cpu number for disable %d\n", nr);
+		return 1;
+	}
+
+	return 0;
+}
+
+int cpu_release(int nr, int argc, char *argv[])
+{
+	/* dummy function so common/cmd_mp.c will build
+	 * should be implemented in the future */
+	return 1;
+}
+
+u32 determine_mp_bootpg(void)
+{
+	/* if we have 4G or more of memory, put the boot page at 4Gb-1M */
+	if ((u64)gd->ram_size > 0xfffff000)
+		return (0xfff00000);
+
+	return (gd->ram_size - (1024 * 1024));
+}
+
+void cpu_mp_lmb_reserve(struct lmb *lmb)
+{
+	u32 bootpg = determine_mp_bootpg();
+
+	/* tell u-boot we stole a page */
+	lmb_reserve(lmb, bootpg, 4096);
+}
+
+/*
+ * Copy the code for other cpus to execute into an
+ * aligned location accessible via BPTR
+ */
+void setup_mp(void)
+{
+	extern ulong __secondary_start_page;
+	ulong fixup = (ulong)&__secondary_start_page;
+	u32 bootpg = determine_mp_bootpg();
+	u32 bootpg_va;
+
+	if (bootpg >= CONFIG_SYS_MAX_DDR_BAT_SIZE) {
+		/* We're not covered by the DDR mapping, set up BAT  */
+		write_bat(DBAT7, CONFIG_SYS_SCRATCH_VA | BATU_BL_128K |
+			  BATU_VS | BATU_VP,
+			  bootpg | BATL_PP_RW | BATL_MEMCOHERENCE);
+		bootpg_va = CONFIG_SYS_SCRATCH_VA;
+	} else {
+		bootpg_va = bootpg;
+	}
+
+	memcpy((void *)bootpg_va, (void *)fixup, 4096);
+	flush_cache(bootpg_va, 4096);
+
+	/* remove the temporary BAT mapping */
+	if (bootpg >= CONFIG_SYS_MAX_DDR_BAT_SIZE)
+		write_bat(DBAT7, 0, 0);
+
+	/* If the physical location of bootpg is not at fff00000, set BPTR */
+	if (bootpg != 0xfff00000)
+		out_be32((uint *)(CONFIG_SYS_CCSRBAR + 0x20), 0x80000000 |
+			 (bootpg >> 12));
+}
diff --git a/arch/powerpc/cpu/mpc86xx/release.S b/arch/powerpc/cpu/mpc86xx/release.S
new file mode 100644
index 0000000..67a6f2b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/release.S
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2004, 2007, 2008 Freescale Semiconductor.
+ * Srikanth Srinivasan <srikanth.srinivaan@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <config.h>
+#include <mpc86xx.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+/* If this is a multi-cpu system then we need to handle the
+ * 2nd cpu.  The assumption is that the 2nd cpu is being
+ * held in boot holdoff mode until the 1st cpu unlocks it
+ * from Linux.	We'll do some basic cpu init and then pass
+ * it to the Linux Reset Vector.
+ * Sri:	 Much of this initialization is not required. Linux
+ * rewrites the bats, and the sprs and also enables the L1 cache.
+ *
+ * Core 0 must copy this to a 1M aligned region and set BPTR
+ * to point to it.
+ */
+	.align 12
+.globl __secondary_start_page
+__secondary_start_page:
+	.space 0x100	/* space over to reset vector loc */
+	mfspr	r0, MSSCR0
+	andi.	r0, r0, 0x0020
+	rlwinm	r0,r0,27,31,31
+	mtspr	PIR, r0
+
+	/* Invalidate BATs */
+	li	r0, 0
+	mtspr	IBAT0U, r0
+	mtspr	IBAT1U, r0
+	mtspr	IBAT2U, r0
+	mtspr	IBAT3U, r0
+	mtspr	IBAT4U, r0
+	mtspr	IBAT5U, r0
+	mtspr	IBAT6U, r0
+	mtspr	IBAT7U, r0
+	isync
+	mtspr	DBAT0U, r0
+	mtspr	DBAT1U, r0
+	mtspr	DBAT2U, r0
+	mtspr	DBAT3U, r0
+	mtspr	DBAT4U, r0
+	mtspr	DBAT5U, r0
+	mtspr	DBAT6U, r0
+	mtspr	DBAT7U, r0
+	isync
+	sync
+
+	/* enable extended addressing */
+	mfspr	r0, HID0
+	lis	r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
+	ori	r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
+	mtspr	HID0, r0
+	sync
+	isync
+
+#ifdef CONFIG_SYS_L2
+	/* init the L2 cache */
+	addis	r3, r0, L2_INIT@h
+	ori	r3, r3, L2_INIT@l
+	sync
+	mtspr	l2cr, r3
+#ifdef CONFIG_ALTIVEC
+	dssall
+#endif
+	/* invalidate the L2 cache */
+	mfspr	r3, l2cr
+	rlwinm.	r3, r3, 0, 0, 0
+	beq	1f
+
+	mfspr	r3, l2cr
+	rlwinm	r3, r3, 0, 1, 31
+
+#ifdef	CONFIG_ALTIVEC
+	dssall
+#endif
+	sync
+	mtspr	l2cr, r3
+	sync
+1:	mfspr	r3, l2cr
+	oris	r3, r3, L2CR_L2I@h
+	mtspr	l2cr, r3
+
+invl2:
+	mfspr	r3, l2cr
+	andis.	r3, r3, L2CR_L2I@h
+	bne	invl2
+	sync
+#endif
+
+	/* enable and invalidate the data cache */
+	mfspr	r3, HID0
+	li	r5, HID0_DCFI|HID0_DLOCK
+	andc	r3, r3, r5
+	mtspr	HID0, r3		/* no invalidate, unlock */
+	ori	r3, r3, HID0_DCE
+	ori	r5, r3, HID0_DCFI
+	mtspr	HID0, r5		/* enable + invalidate */
+	mtspr	HID0, r3		/* enable */
+	sync
+#ifdef CONFIG_SYS_L2
+	sync
+	lis	r3, L2_ENABLE@h
+	ori	r3, r3, L2_ENABLE@l
+	mtspr	l2cr, r3
+	isync
+	sync
+#endif
+
+	/* enable and invalidate the instruction cache*/
+	mfspr	r3, HID0
+	li	r5, HID0_ICFI|HID0_ILOCK
+	andc	r3, r3, r5
+	ori	r3, r3, HID0_ICE
+	ori	r5, r3, HID0_ICFI
+	mtspr	HID0, r5
+	mtspr	HID0, r3
+	isync
+	sync
+
+	/* TBEN in HID0 */
+	mfspr	r4, HID0
+	oris	r4, r4, 0x0400
+	mtspr	HID0, r4
+	sync
+	isync
+
+	/* MCP|SYNCBE|ABE in HID1 */
+	mfspr	r4, HID1
+	oris	r4, r4, 0x8000
+	ori	r4, r4, 0x0C00
+	mtspr	HID1, r4
+	sync
+	isync
+
+	lis	r3, CONFIG_LINUX_RESET_VEC@h
+	ori	r3, r3, CONFIG_LINUX_RESET_VEC@l
+	mtlr	r3
+	blr
+
+	/* Never Returns, Running in Linux Now */
diff --git a/arch/powerpc/cpu/mpc86xx/speed.c b/arch/powerpc/cpu/mpc86xx/speed.c
new file mode 100644
index 0000000..64a3479
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/speed.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2004 Freescale Semiconductor.
+ * Jeff Brown
+ * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
+ *
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc86xx.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* used in some defintiions of CONFIG_SYS_CLK_FREQ */
+extern unsigned long get_board_sys_clk(unsigned long dummy);
+
+void get_sys_info(sys_info_t *sysInfo)
+{
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	volatile ccsr_gur_t *gur = &immap->im_gur;
+	uint plat_ratio, e600_ratio;
+	uint lcrr_div;
+
+	plat_ratio = (gur->porpllsr) & 0x0000003e;
+	plat_ratio >>= 1;
+
+	switch (plat_ratio) {
+	case 0x0:
+		sysInfo->freqSystemBus = 16 * CONFIG_SYS_CLK_FREQ;
+		break;
+	case 0x02:
+	case 0x03:
+	case 0x04:
+	case 0x05:
+	case 0x06:
+	case 0x08:
+	case 0x09:
+	case 0x0a:
+	case 0x0c:
+	case 0x10:
+		sysInfo->freqSystemBus = plat_ratio * CONFIG_SYS_CLK_FREQ;
+		break;
+	default:
+		sysInfo->freqSystemBus = 0;
+		break;
+	}
+
+	e600_ratio = (gur->porpllsr) & 0x003f0000;
+	e600_ratio >>= 16;
+
+	switch (e600_ratio) {
+	case 0x10:
+		sysInfo->freqProcessor = 2 * sysInfo->freqSystemBus;
+		break;
+	case 0x19:
+		sysInfo->freqProcessor = 5 * sysInfo->freqSystemBus / 2;
+		break;
+	case 0x20:
+		sysInfo->freqProcessor = 3 * sysInfo->freqSystemBus;
+		break;
+	case 0x39:
+		sysInfo->freqProcessor = 7 * sysInfo->freqSystemBus / 2;
+		break;
+	case 0x28:
+		sysInfo->freqProcessor = 4 * sysInfo->freqSystemBus;
+		break;
+	case 0x1d:
+		sysInfo->freqProcessor = 9 * sysInfo->freqSystemBus / 2;
+		break;
+	default:
+		sysInfo->freqProcessor = e600_ratio + sysInfo->freqSystemBus;
+		break;
+	}
+
+#if defined(CONFIG_SYS_LBC_LCRR)
+	/* We will program LCRR to this value later */
+	lcrr_div = CONFIG_SYS_LBC_LCRR & LCRR_CLKDIV;
+#else
+	{
+		volatile ccsr_lbc_t *lbc = &immap->im_lbc;
+		lcrr_div = in_be32(&lbc->lcrr) & LCRR_CLKDIV;
+	}
+#endif
+	if (lcrr_div == 2 || lcrr_div == 4 || lcrr_div == 8) {
+		sysInfo->freqLocalBus = sysInfo->freqSystemBus / (lcrr_div * 2);
+	} else {
+		/* In case anyone cares what the unknown value is */
+		sysInfo->freqLocalBus = lcrr_div;
+	}
+}
+
+
+/*
+ * Measure CPU clock speed (core clock GCLK1, GCLK2)
+ * (Approx. GCLK frequency in Hz)
+ */
+
+int get_clocks(void)
+{
+	sys_info_t sys_info;
+
+	get_sys_info(&sys_info);
+	gd->cpu_clk = sys_info.freqProcessor;
+	gd->bus_clk = sys_info.freqSystemBus;
+	gd->lbc_clk = sys_info.freqLocalBus;
+
+	/*
+	 * The base clock for I2C depends on the actual SOC.  Unfortunately,
+	 * there is no pattern that can be used to determine the frequency, so
+	 * the only choice is to look up the actual SOC number and use the value
+	 * for that SOC. This information is taken from application note
+	 * AN2919.
+	 */
+#ifdef CONFIG_MPC8610
+	gd->i2c1_clk = sys_info.freqSystemBus;
+#else
+	gd->i2c1_clk = sys_info.freqSystemBus / 2;
+#endif
+	gd->i2c2_clk = gd->i2c1_clk;
+
+	if (gd->cpu_clk != 0)
+		return 0;
+	else
+		return 1;
+}
+
+
+/*
+ * get_bus_freq
+ *	Return system bus freq in Hz
+ */
+
+ulong get_bus_freq(ulong dummy)
+{
+	ulong val;
+	sys_info_t sys_info;
+
+	get_sys_info(&sys_info);
+	val = sys_info.freqSystemBus;
+
+	return val;
+}
diff --git a/arch/powerpc/cpu/mpc86xx/start.S b/arch/powerpc/cpu/mpc86xx/start.S
new file mode 100644
index 0000000..ed1e4ca
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/start.S
@@ -0,0 +1,957 @@
+/*
+ * Copyright 2004, 2007 Freescale Semiconductor.
+ * Srikanth Srinivasan <srikanth.srinivaan@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*  U-Boot - Startup Code for 86xx PowerPC based Embedded Boards
+ *
+ *
+ *  The processor starts at 0xfff00100 and the code is executed
+ *  from flash. The code is organized to be at an other address
+ *  in memory, but as long we don't jump around before relocating.
+ *  board_init lies at a quite high address and when the cpu has
+ *  jumped there, everything is ok.
+ */
+#include <config.h>
+#include <mpc86xx.h>
+#include <timestamp.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef	CONFIG_IDENT_STRING
+#define CONFIG_IDENT_STRING ""
+#endif
+
+/*
+ * Need MSR_DR | MSR_IR enabled to access I/O (printf) in exceptions
+ */
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+	START_GOT
+	GOT_ENTRY(_GOT2_TABLE_)
+	GOT_ENTRY(_FIXUP_TABLE_)
+
+	GOT_ENTRY(_start)
+	GOT_ENTRY(_start_of_vectors)
+	GOT_ENTRY(_end_of_vectors)
+	GOT_ENTRY(transfer_to_handler)
+
+	GOT_ENTRY(__init_end)
+	GOT_ENTRY(_end)
+	GOT_ENTRY(__bss_start)
+	END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+	.text
+	.long	0x27051956		/* U-Boot Magic Number */
+	.globl	version_string
+version_string:
+	.ascii	U_BOOT_VERSION
+	.ascii	" (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
+	.ascii	CONFIG_IDENT_STRING, "\0"
+
+	. = EXC_OFF_SYS_RESET
+	.globl	_start
+_start:
+	li	r21, BOOTFLAG_COLD	/* Normal Power-On: Boot from FLASH */
+	b	boot_cold
+	sync
+
+	. = EXC_OFF_SYS_RESET + 0x10
+
+	.globl	_start_warm
+_start_warm:
+	li	r21, BOOTFLAG_WARM	/* Software reboot */
+	b	boot_warm
+	sync
+
+	/* the boot code is located below the exception table */
+
+	.globl	_start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+	STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+	STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+	STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+	. = 0x600
+Alignment:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	mfspr	r4,DAR
+	stw	r4,_DAR(r21)
+	mfspr	r5,DSISR
+	stw	r5,_DSISR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+	. = 0x700
+ProgramCheck:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+		MSR_KERNEL, COPY_EE)
+
+	STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+	/* I guess we could implement decrementer, and may have
+	 * to someday for timekeeping.
+	 */
+	STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+	STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+	STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+	STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+	STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+	STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+	STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
+	STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
+	STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
+	STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+	STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+	STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+	STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+	STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+	STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+	STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+	STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
+	STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
+	STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
+	STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
+
+	.globl	_end_of_vectors
+_end_of_vectors:
+
+	. = 0x2000
+
+boot_cold:
+boot_warm:
+	/*
+	 * NOTE: Only Cpu 0 will ever come here.  Other cores go to an
+	 * address specified by the BPTR
+	 */
+1:
+#ifdef CONFIG_SYS_RAMBOOT
+	/* disable everything */
+	li	r0, 0
+	mtspr	HID0, r0
+	sync
+	mtmsr	0
+#endif
+
+	/* Invalidate BATs */
+	bl	invalidate_bats
+	sync
+	/* Invalidate all of TLB before MMU turn on */
+	bl      clear_tlbs
+	sync
+
+#ifdef CONFIG_SYS_L2
+	/* init the L2 cache */
+	lis	r3, L2_INIT@h
+	ori	r3, r3, L2_INIT@l
+	mtspr	l2cr, r3
+	/* invalidate the L2 cache */
+	bl	l2cache_invalidate
+	sync
+#endif
+
+	/*
+	 * Calculate absolute address in FLASH and jump there
+	 *------------------------------------------------------*/
+	lis	r3, CONFIG_SYS_MONITOR_BASE_EARLY@h
+	ori	r3, r3, CONFIG_SYS_MONITOR_BASE_EARLY@l
+	addi	r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+	mtlr	r3
+	blr
+
+in_flash:
+	/* let the C-code set up the rest			*/
+	/*							*/
+	/* Be careful to keep code relocatable !		*/
+	/*------------------------------------------------------*/
+	/* perform low-level init */
+
+	/* enable extended addressing */
+	bl	enable_ext_addr
+
+	/* setup the bats */
+	bl	early_bats
+
+	/*
+	 * Cache must be enabled here for stack-in-cache trick.
+	 * This means we need to enable the BATS.
+	 * Cache should be turned on after BATs, since by default
+	 * everything is write-through.
+	 */
+
+	/* enable address translation */
+	mfmsr	r5
+	ori	r5, r5, (MSR_IR | MSR_DR)
+	lis	r3,addr_trans_enabled@h
+	ori	r3, r3, addr_trans_enabled@l
+	mtspr	SPRN_SRR0,r3
+	mtspr	SPRN_SRR1,r5
+	rfi
+
+addr_trans_enabled:
+	/* enable and invalidate the data cache */
+/*	bl	l1dcache_enable */
+	bl	dcache_enable
+	sync
+
+#if 1
+	bl	icache_enable
+#endif
+
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+	bl	lock_ram_in_cache
+	sync
+#endif
+
+#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
+	bl      setup_ccsrbar
+#endif
+
+	/* set up the stack pointer in our newly created
+	 * cache-ram (r1) */
+	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
+	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
+
+	li	r0, 0		/* Make room for stack frame header and */
+	stwu	r0, -4(r1)	/* clear final stack frame so that	*/
+	stwu	r0, -4(r1)	/* stack backtraces terminate cleanly	*/
+
+	GET_GOT			/* initialize GOT access	*/
+
+	/* run low-level CPU init code	   (from Flash) */
+	bl	cpu_init_f
+	sync
+
+#ifdef	RUN_DIAG
+
+	/* Load PX_AUX register address in r4 */
+	lis	r4, PIXIS_BASE@h
+	ori	r4, r4, 0x6
+	/* Load contents of PX_AUX in r3 bits 24 to 31*/
+	lbz	r3, 0(r4)
+
+	/* Mask and obtain the bit in r3 */
+	rlwinm. r3, r3, 0, 24, 24
+	/* If not zero, jump and continue with u-boot */
+	bne	diag_done
+
+	/* Load back contents of PX_AUX in r3 bits 24 to 31 */
+	lbz	r3, 0(r4)
+	/* Set the MSB of the register value */
+	ori	r3, r3, 0x80
+	/* Write value in r3 back to PX_AUX */
+	stb	r3, 0(r4)
+
+	/* Get the address to jump to in r3*/
+	lis	r3, CONFIG_SYS_DIAG_ADDR@h
+	ori	r3, r3, CONFIG_SYS_DIAG_ADDR@l
+
+	/* Load the LR with the branch address */
+	mtlr	r3
+
+	/* Branch to diagnostic */
+	blr
+
+diag_done:
+#endif
+
+/*	bl	l2cache_enable */
+	mr	r3, r21
+
+	/* r3: BOOTFLAG */
+	/* run 1st part of board init code (from Flash)	  */
+	bl	board_init_f
+	sync
+
+	/* NOTREACHED */
+
+	.globl	invalidate_bats
+invalidate_bats:
+
+	li	r0, 0
+	/* invalidate BATs */
+	mtspr	IBAT0U, r0
+	mtspr	IBAT1U, r0
+	mtspr	IBAT2U, r0
+	mtspr	IBAT3U, r0
+	mtspr	IBAT4U, r0
+	mtspr	IBAT5U, r0
+	mtspr	IBAT6U, r0
+	mtspr	IBAT7U, r0
+
+	isync
+	mtspr	DBAT0U, r0
+	mtspr	DBAT1U, r0
+	mtspr	DBAT2U, r0
+	mtspr	DBAT3U, r0
+	mtspr	DBAT4U, r0
+	mtspr	DBAT5U, r0
+	mtspr	DBAT6U, r0
+	mtspr	DBAT7U, r0
+
+	isync
+	sync
+	blr
+
+/*
+ * early_bats:
+ *
+ * Set up bats needed early on - this is usually the BAT for the
+ * stack-in-cache, the Flash, and CCSR space
+ */
+	.globl  early_bats
+early_bats:
+	/* IBAT 3 */
+	lis	r4, CONFIG_SYS_IBAT3L@h
+	ori     r4, r4, CONFIG_SYS_IBAT3L@l
+	lis	r3, CONFIG_SYS_IBAT3U@h
+	ori     r3, r3, CONFIG_SYS_IBAT3U@l
+	mtspr   IBAT3L, r4
+	mtspr   IBAT3U, r3
+	isync
+
+	/* DBAT 3 */
+	lis	r4, CONFIG_SYS_DBAT3L@h
+	ori     r4, r4, CONFIG_SYS_DBAT3L@l
+	lis	r3, CONFIG_SYS_DBAT3U@h
+	ori     r3, r3, CONFIG_SYS_DBAT3U@l
+	mtspr   DBAT3L, r4
+	mtspr   DBAT3U, r3
+	isync
+
+	/* IBAT 5 */
+	lis	r4, CONFIG_SYS_IBAT5L@h
+	ori     r4, r4, CONFIG_SYS_IBAT5L@l
+	lis	r3, CONFIG_SYS_IBAT5U@h
+	ori     r3, r3, CONFIG_SYS_IBAT5U@l
+	mtspr   IBAT5L, r4
+	mtspr   IBAT5U, r3
+	isync
+
+	/* DBAT 5 */
+	lis	r4, CONFIG_SYS_DBAT5L@h
+	ori     r4, r4, CONFIG_SYS_DBAT5L@l
+	lis	r3, CONFIG_SYS_DBAT5U@h
+	ori     r3, r3, CONFIG_SYS_DBAT5U@l
+	mtspr   DBAT5L, r4
+	mtspr   DBAT5U, r3
+	isync
+
+	/* IBAT 6 */
+	lis	r4, CONFIG_SYS_IBAT6L_EARLY@h
+	ori     r4, r4, CONFIG_SYS_IBAT6L_EARLY@l
+	lis	r3, CONFIG_SYS_IBAT6U_EARLY@h
+	ori     r3, r3, CONFIG_SYS_IBAT6U_EARLY@l
+	mtspr   IBAT6L, r4
+	mtspr   IBAT6U, r3
+	isync
+
+	/* DBAT 6 */
+	lis	r4, CONFIG_SYS_DBAT6L_EARLY@h
+	ori     r4, r4, CONFIG_SYS_DBAT6L_EARLY@l
+	lis	r3, CONFIG_SYS_DBAT6U_EARLY@h
+	ori     r3, r3, CONFIG_SYS_DBAT6U_EARLY@l
+	mtspr   DBAT6L, r4
+	mtspr   DBAT6U, r3
+	isync
+
+#if(CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
+	/* IBAT 7 */
+	lis	r4, CONFIG_SYS_CCSR_DEFAULT_IBATL@h
+	ori     r4, r4, CONFIG_SYS_CCSR_DEFAULT_IBATL@l
+	lis	r3, CONFIG_SYS_CCSR_DEFAULT_IBATU@h
+	ori     r3, r3, CONFIG_SYS_CCSR_DEFAULT_IBATU@l
+	mtspr   IBAT7L, r4
+	mtspr   IBAT7U, r3
+	isync
+
+	/* DBAT 7 */
+	lis	r4, CONFIG_SYS_CCSR_DEFAULT_DBATL@h
+	ori     r4, r4, CONFIG_SYS_CCSR_DEFAULT_DBATL@l
+	lis	r3, CONFIG_SYS_CCSR_DEFAULT_DBATU@h
+	ori     r3, r3, CONFIG_SYS_CCSR_DEFAULT_DBATU@l
+	mtspr   DBAT7L, r4
+	mtspr   DBAT7U, r3
+	isync
+#endif
+	blr
+
+	.globl clear_tlbs
+clear_tlbs:
+	addis   r3, 0, 0x0000
+	addis   r5, 0, 0x4
+	isync
+tlblp:
+	tlbie   r3
+	sync
+	addi    r3, r3, 0x1000
+	cmp     0, 0, r3, r5
+	blt tlblp
+	blr
+
+	.globl disable_addr_trans
+disable_addr_trans:
+	/* disable address translation */
+	mflr	r4
+	mfmsr	r3
+	andi.	r0, r3, (MSR_IR | MSR_DR)
+	beqlr
+	andc	r3, r3, r0
+	mtspr	SRR0, r4
+	mtspr	SRR1, r3
+	rfi
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+	.globl	transfer_to_handler
+transfer_to_handler:
+	stw	r22,_NIP(r21)
+	lis	r22,MSR_POW@h
+	andc	r23,r23,r22
+	stw	r23,_MSR(r21)
+	SAVE_GPR(7, r21)
+	SAVE_4GPRS(8, r21)
+	SAVE_8GPRS(12, r21)
+	SAVE_8GPRS(24, r21)
+	mflr	r23
+	andi.	r24,r23,0x3f00		/* get vector offset */
+	stw	r24,TRAP(r21)
+	li	r22,0
+	stw	r22,RESULT(r21)
+	mtspr	SPRG2,r22		/* r1 is now kernel sp */
+	lwz	r24,0(r23)		/* virtual address of handler */
+	lwz	r23,4(r23)		/* where to go when done */
+	mtspr	SRR0,r24
+	mtspr	SRR1,r20
+	mtlr	r23
+	SYNC
+	rfi				/* jump to handler, enable MMU */
+
+int_return:
+	mfmsr	r28		/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC			/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SRR0,r2
+	mtspr	SRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfi
+
+	.globl	dc_read
+dc_read:
+	blr
+
+	.globl get_pvr
+get_pvr:
+	mfspr	r3, PVR
+	blr
+
+	.globl get_svr
+get_svr:
+	mfspr	r3, SVR
+	blr
+
+
+/*
+ * Function:	in8
+ * Description:	Input 8 bits
+ */
+	.globl	in8
+in8:
+	lbz	r3,0x0000(r3)
+	blr
+
+/*
+ * Function:	out8
+ * Description:	Output 8 bits
+ */
+	.globl	out8
+out8:
+	stb	r4,0x0000(r3)
+	blr
+
+/*
+ * Function:	out16
+ * Description:	Output 16 bits
+ */
+	.globl	out16
+out16:
+	sth	r4,0x0000(r3)
+	blr
+
+/*
+ * Function:	out16r
+ * Description:	Byte reverse and output 16 bits
+ */
+	.globl	out16r
+out16r:
+	sthbrx	r4,r0,r3
+	blr
+
+/*
+ * Function:	out32
+ * Description:	Output 32 bits
+ */
+	.globl	out32
+out32:
+	stw	r4,0x0000(r3)
+	blr
+
+/*
+ * Function:	out32r
+ * Description:	Byte reverse and output 32 bits
+ */
+	.globl	out32r
+out32r:
+	stwbrx	r4,r0,r3
+	blr
+
+/*
+ * Function:	in16
+ * Description:	Input 16 bits
+ */
+	.globl	in16
+in16:
+	lhz	r3,0x0000(r3)
+	blr
+
+/*
+ * Function:	in16r
+ * Description:	Input 16 bits and byte reverse
+ */
+	.globl	in16r
+in16r:
+	lhbrx	r3,r0,r3
+	blr
+
+/*
+ * Function:	in32
+ * Description:	Input 32 bits
+ */
+	.globl	in32
+in32:
+	lwz	3,0x0000(3)
+	blr
+
+/*
+ * Function:	in32r
+ * Description:	Input 32 bits and byte reverse
+ */
+	.globl	in32r
+in32r:
+	lwbrx	r3,r0,r3
+	blr
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+	.globl	relocate_code
+relocate_code:
+
+	mr	r1,  r3		/* Set new stack pointer		*/
+	mr	r9,  r4		/* Save copy of Global Data pointer	*/
+	mr	r10, r5		/* Save copy of Destination Address	*/
+
+	GET_GOT
+	mr	r3,  r5				/* Destination Address	*/
+	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address	*/
+	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
+	lwz	r5, GOT(__init_end)
+	sub	r5, r5, r4
+	li	r6, CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size	*/
+
+	/*
+	 * Fix GOT pointer:
+	 *
+	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+	 *
+	 * Offset:
+	 */
+	sub	r15, r10, r4
+
+	/* First our own GOT */
+	add	r12, r12, r15
+	/* then the one used by the C code */
+	add	r30, r30, r15
+
+	/*
+	 * Now relocate code
+	 */
+	cmplw	cr1,r3,r4
+	addi	r0,r5,3
+	srwi.	r0,r0,2
+	beq	cr1,4f		/* In place copy is not necessary	*/
+	beq	7f		/* Protect against 0 count		*/
+	mtctr	r0
+	bge	cr1,2f
+
+	la	r8,-4(r4)
+	la	r7,-4(r3)
+1:	lwzu	r0,4(r8)
+	stwu	r0,4(r7)
+	bdnz	1b
+	b	4f
+
+2:	slwi	r0,r0,2
+	add	r8,r4,r0
+	add	r7,r3,r0
+3:	lwzu	r0,-4(r8)
+	stwu	r0,-4(r7)
+	bdnz	3b
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:	cmpwi	r6,0
+	add	r5,r3,r5
+	beq	7f		/* Always flush prefetch queue in any case */
+	subi	r0,r6,1
+	andc	r3,r3,r0
+	mr	r4,r3
+5:	dcbst	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	5b
+	sync			/* Wait for all dcbst to complete on bus */
+	mr	r4,r3
+6:	icbi	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	6b
+7:	sync			/* Wait for all icbi to complete on bus */
+	isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+	mtlr	r0
+	blr
+
+in_ram:
+	/*
+	 * Relocation Function, r12 point to got2+0x8000
+	 *
+	 * Adjust got2 pointers, no need to check for 0, this code
+	 * already puts a few entries in the table.
+	 */
+	li	r0,__got2_entries@sectoff@l
+	la	r3,GOT(_GOT2_TABLE_)
+	lwz	r11,GOT(_GOT2_TABLE_)
+	mtctr	r0
+	sub	r11,r3,r11
+	addi	r3,r3,-4
+1:	lwzu	r0,4(r3)
+	cmpwi	r0,0
+	beq-	2f
+	add	r0,r0,r11
+	stw	r0,0(r3)
+2:	bdnz	1b
+
+	/*
+	 * Now adjust the fixups and the pointers to the fixups
+	 * in case we need to move ourselves again.
+	 */
+	li	r0,__fixup_entries@sectoff@l
+	lwz	r3,GOT(_FIXUP_TABLE_)
+	cmpwi	r0,0
+	mtctr	r0
+	addi	r3,r3,-4
+	beq	4f
+3:	lwzu	r4,4(r3)
+	lwzux	r0,r4,r11
+	add	r0,r0,r11
+	stw	r10,0(r3)
+	stw	r0,0(r4)
+	bdnz	3b
+4:
+/* clear_bss: */
+	/*
+	 * Now clear BSS segment
+	 */
+	lwz	r3,GOT(__bss_start)
+	lwz	r4,GOT(_end)
+
+	cmplw	0, r3, r4
+	beq	6f
+
+	li	r0, 0
+5:
+	stw	r0, 0(r3)
+	addi	r3, r3, 4
+	cmplw	0, r3, r4
+	bne	5b
+6:
+	mr	r3, r9		/* Init Date pointer		*/
+	mr	r4, r10		/* Destination Address		*/
+	bl	board_init_r
+
+	/* not reached - end relocate_code */
+/*-----------------------------------------------------------------------*/
+
+	/*
+	 * Copy exception vector code to low memory
+	 *
+	 * r3: dest_addr
+	 * r7: source address, r8: end address, r9: target address
+	 */
+	.globl	trap_init
+trap_init:
+	mflr	r4			/* save link register		*/
+	GET_GOT
+	lwz	r7, GOT(_start)
+	lwz	r8, GOT(_end_of_vectors)
+
+	li	r9, 0x100		/* reset vector always at 0x100 */
+
+	cmplw	0, r7, r8
+	bgelr				/* return if r7>=r8 - just in case */
+1:
+	lwz	r0, 0(r7)
+	stw	r0, 0(r9)
+	addi	r7, r7, 4
+	addi	r9, r9, 4
+	cmplw	0, r7, r8
+	bne	1b
+
+	/*
+	 * relocate `hdlr' and `int_return' entries
+	 */
+	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+	li	r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	2b
+
+	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	3b
+
+	li	r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	4b
+
+	/* enable execptions from RAM vectors */
+	mfmsr	r7
+	li	r8,MSR_IP
+	andc	r7,r7,r8
+	ori	r7,r7,MSR_ME		/* Enable Machine Check */
+	mtmsr	r7
+
+	mtlr	r4			/* restore link register	*/
+	blr
+
+.globl enable_ext_addr
+enable_ext_addr:
+	mfspr	r0, HID0
+	lis	r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
+	ori	r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
+	mtspr	HID0, r0
+	sync
+	isync
+	blr
+
+#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
+.globl setup_ccsrbar
+setup_ccsrbar:
+	/* Special sequence needed to update CCSRBAR itself */
+	lis	r4, CONFIG_SYS_CCSRBAR_DEFAULT@h
+	ori	r4, r4, CONFIG_SYS_CCSRBAR_DEFAULT@l
+
+	lis	r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@h
+	ori	r5, r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@l
+	srwi	r5,r5,12
+	li	r6, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
+	rlwimi	r5,r6,20,8,11
+	stw	r5, 0(r4) /* Store physical value of CCSR */
+	isync
+
+	lis	r5, TEXT_BASE@h
+	ori	r5,r5,TEXT_BASE@l
+	lwz	r5, 0(r5)
+	isync
+
+	/* Use VA of CCSR to do read */
+	lis	r3, CONFIG_SYS_CCSRBAR@h
+	lwz	r5, CONFIG_SYS_CCSRBAR@l(r3)
+	isync
+
+	blr
+#endif
+
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+lock_ram_in_cache:
+	/* Allocate Initial RAM in data cache.
+	 */
+	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
+	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
+	li	r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \
+		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
+	mtctr	r4
+1:
+	dcbz	r0, r3
+	addi	r3, r3, 32
+	bdnz	1b
+#if 1
+/* Lock the data cache */
+	mfspr	r0, HID0
+	ori	r0, r0, 0x1000
+	sync
+	mtspr	HID0, r0
+	sync
+	blr
+#endif
+#if 0
+	/* Lock the first way of the data cache */
+	mfspr	r0, LDSTCR
+	ori	r0, r0, 0x0080
+#if defined(CONFIG_ALTIVEC)
+	dssall
+#endif
+	sync
+	mtspr	LDSTCR, r0
+	sync
+	isync
+	blr
+#endif
+
+.globl unlock_ram_in_cache
+unlock_ram_in_cache:
+	/* invalidate the INIT_RAM section */
+	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
+	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
+	li	r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \
+		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
+	mtctr	r4
+1:	icbi	r0, r3
+	addi	r3, r3, 32
+	bdnz	1b
+	sync			/* Wait for all icbi to complete on bus */
+	isync
+#if 1
+/* Unlock the data cache and invalidate it */
+	mfspr	r0, HID0
+	li	r3,0x1000
+	andc	r0,r0,r3
+	li	r3,0x0400
+	or	r0,r0,r3
+	sync
+	mtspr	HID0, r0
+	sync
+	blr
+#endif
+#if 0
+	/* Unlock the first way of the data cache */
+	mfspr	r0, LDSTCR
+	li	r3,0x0080
+	andc	r0,r0,r3
+#ifdef CONFIG_ALTIVEC
+	dssall
+#endif
+	sync
+	mtspr	LDSTCR, r0
+	sync
+	isync
+	li	r3,0x0400
+	or	r0,r0,r3
+	sync
+	mtspr	HID0, r0
+	sync
+	blr
+#endif
+#endif
diff --git a/arch/powerpc/cpu/mpc86xx/traps.c b/arch/powerpc/cpu/mpc86xx/traps.c
new file mode 100644
index 0000000..406403e
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/traps.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+/*
+ * End of addressable memory.  This may be less than the actual
+ * amount of memory on the system if we're unable to keep all
+ * the memory mapped in.
+ */
+extern ulong get_effective_memsize(void);
+#define END_OF_MEM (gd->bd->bi_memstart + get_effective_memsize())
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace(unsigned long *sp)
+{
+	int cnt = 0;
+	unsigned long i;
+
+	printf("Call backtrace: ");
+	while (sp) {
+		if ((uint) sp > END_OF_MEM)
+			break;
+
+		i = sp[1];
+		if (cnt++ % 7 == 0)
+			printf("\n");
+		printf("%08lX ", i);
+		if (cnt > 32)
+			break;
+		sp = (unsigned long *)*sp;
+	}
+	printf("\n");
+}
+
+void
+show_regs(struct pt_regs *regs)
+{
+	int i;
+
+	printf("NIP: %08lX XER: %08lX LR: %08lX REGS:"
+	       " %p TRAP: %04lx DAR: %08lX\n",
+	       regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+	printf("MSR: %08lx EE: %01x PR: %01x FP:"
+	       " %01x ME: %01x IR/DR: %01x%01x\n",
+	       regs->msr, regs->msr & MSR_EE ? 1 : 0,
+	       regs->msr & MSR_PR ? 1 : 0, regs->msr & MSR_FP ? 1 : 0,
+	       regs->msr & MSR_ME ? 1 : 0, regs->msr & MSR_IR ? 1 : 0,
+	       regs->msr & MSR_DR ? 1 : 0);
+
+	printf("\n");
+	for (i = 0; i < 32; i++) {
+		if ((i % 8) == 0) {
+			printf("GPR%02d: ", i);
+		}
+
+		printf("%08lX ", regs->gpr[i]);
+		if ((i % 8) == 7) {
+			printf("\n");
+		}
+	}
+}
+
+
+void
+_exception(int signr, struct pt_regs *regs)
+{
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Exception in kernel pc %lx signal %d", regs->nip, signr);
+}
+
+void
+MachineCheckException(struct pt_regs *regs)
+{
+	unsigned long fixup;
+
+	/* Probing PCI using config cycles cause this exception
+	 * when a device is not present.  Catch it and return to
+	 * the PCI exception handler.
+	 */
+	if ((fixup = search_exception_table(regs->nip)) != 0) {
+		regs->nip = fixup;
+		return;
+	}
+
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler) (regs))
+		return;
+#endif
+
+	printf("Machine check in kernel mode.\n");
+	printf("Caused by (from msr): ");
+	printf("regs %p ", regs);
+	switch ( regs->msr & 0x001F0000) {
+	case (0x80000000>>11):
+		printf("MSS error. MSSSR0: %08x\n", mfspr(SPRN_MSSSR0));
+		break;
+	case (0x80000000>>12):
+		printf("Machine check signal - probably due to mm fault\n"
+		       "with mmu off\n");
+		break;
+	case (0x80000000 >> 13):
+		printf("Transfer error ack signal\n");
+		break;
+	case (0x80000000 >> 14):
+		printf("Data parity signal\n");
+		break;
+	case (0x80000000 >> 15):
+		printf("Address parity signal\n");
+		break;
+	default:
+		printf("Unknown values in msr\n");
+	}
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler) (regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+	unsigned char *p = regs ? (unsigned char *)(regs->nip) : NULL;
+	int i, j;
+
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler) (regs))
+		return;
+#endif
+	show_regs(regs);
+
+	p = (unsigned char *)((unsigned long)p & 0xFFFFFFE0);
+	p -= 32;
+	for (i = 0; i < 256; i += 16) {
+		printf("%08x: ", (unsigned int)p + i);
+		for (j = 0; j < 16; j++) {
+			printf("%02x ", p[i + j]);
+		}
+		printf("\n");
+	}
+
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Program Check Exception");
+}
+
+void
+SoftEmuException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler) (regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Software Emulation Exception");
+}
+
+void
+UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler) (regs))
+		return;
+#endif
+	printf("UnknownException regs@%lx\n", (ulong)regs);
+	printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+	       regs->nip, regs->msr, regs->trap);
+	_exception(0, regs);
+}
+
+/*
+ * Probe an address by reading.
+ * If not present, return -1,
+ * otherwise return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xx/Makefile b/arch/powerpc/cpu/mpc8xx/Makefile
new file mode 100644
index 0000000..5f70459
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/Makefile
@@ -0,0 +1,66 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+# CFLAGS += -DET_DEBUG
+
+LIB	= $(obj)lib$(CPU).a
+
+START-y	+= start.o
+START-y	+= kgdb.o
+COBJS-y	+= bedbug_860.o
+COBJS-y	+= commproc.o
+COBJS-y	+= cpu.o
+COBJS-y	+= cpu_init.o
+COBJS-y	+= fec.o
+COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
+COBJS-y	+= i2c.o
+COBJS-y	+= interrupts.o
+COBJS-y	+= lcd.o
+COBJS-y	+= scc.o
+COBJS-y	+= serial.o
+COBJS-y	+= speed.o
+COBJS-y	+= spi.o
+COBJS-y	+= traps.o
+COBJS-y	+= upatch.o
+COBJS-y	+= video.o
+SOBJS-y	+= plprcr_write.o
+
+SRCS	:= $(START-y:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+START	:= $(addprefix $(obj),$(START-y))
+
+all:	$(obj).depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS) $(obj)kgdb.o
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc8xx/bedbug_860.c b/arch/powerpc/cpu/mpc8xx/bedbug_860.c
new file mode 100644
index 0000000..0308bbb
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/bedbug_860.c
@@ -0,0 +1,316 @@
+/*
+ * Bedbug Functions specific to the MPC860 chip
+ */
+
+#include <common.h>
+#include <command.h>
+#include <linux/ctype.h>
+#include <bedbug/bedbug.h>
+#include <bedbug/regs.h>
+#include <bedbug/ppc.h>
+#include <bedbug/type.h>
+
+#if defined(CONFIG_CMD_BEDBUG) && defined(CONFIG_8xx)
+
+#define MAX_BREAK_POINTS 2
+
+extern CPU_DEBUG_CTX bug_ctx;
+
+void bedbug860_init __P((void));
+void bedbug860_do_break __P((cmd_tbl_t*,int,int,char*[]));
+void bedbug860_break_isr __P((struct pt_regs*));
+int  bedbug860_find_empty __P((void));
+int  bedbug860_set __P((int,unsigned long));
+int  bedbug860_clear __P((int));
+
+
+/* ======================================================================
+ * Initialize the global bug_ctx structure for the MPC860.  Clear all
+ * of the breakpoints.
+ * ====================================================================== */
+
+void bedbug860_init( void )
+{
+  int	i;
+  /* -------------------------------------------------- */
+
+  bug_ctx.hw_debug_enabled = 0;
+  bug_ctx.stopped = 0;
+  bug_ctx.current_bp = 0;
+  bug_ctx.regs = NULL;
+
+  bug_ctx.do_break   = bedbug860_do_break;
+  bug_ctx.break_isr  = bedbug860_break_isr;
+  bug_ctx.find_empty = bedbug860_find_empty;
+  bug_ctx.set        = bedbug860_set;
+  bug_ctx.clear      = bedbug860_clear;
+
+  for( i = 1; i <= MAX_BREAK_POINTS; ++i )
+    (*bug_ctx.clear)( i );
+
+  puts ("BEDBUG:ready\n");
+  return;
+} /* bedbug_init_breakpoints */
+
+
+
+/* ======================================================================
+ * Set/clear/show one of the hardware breakpoints for the 860.  The "off"
+ * string will disable a specific breakpoint.  The "show" string will
+ * display the current breakpoints.  Otherwise an address will set a
+ * breakpoint at that address.  Setting a breakpoint uses the CPU-specific
+ * set routine which will assign a breakpoint number.
+ * ====================================================================== */
+
+void bedbug860_do_break (cmd_tbl_t *cmdtp, int flag, int argc,
+			 char *argv[])
+{
+  long		addr = 0;       /* Address to break at  */
+  int		which_bp;       /* Breakpoint number    */
+  /* -------------------------------------------------- */
+
+  if (argc < 2)
+  {
+    cmd_usage(cmdtp);
+    return;
+  }
+
+  /* Turn off a breakpoint */
+
+  if( strcmp( argv[ 1 ], "off" ) == 0 )
+  {
+    if( bug_ctx.hw_debug_enabled == 0 )
+    {
+      printf( "No breakpoints enabled\n" );
+      return;
+    }
+
+    which_bp = simple_strtoul( argv[ 2 ], NULL, 10 );
+
+    if( bug_ctx.clear )
+      (*bug_ctx.clear)( which_bp );
+
+    printf( "Breakpoint %d removed\n", which_bp );
+    return;
+  }
+
+  /* Show a list of breakpoints */
+
+  if( strcmp( argv[ 1 ], "show" ) == 0 )
+  {
+    for( which_bp = 1; which_bp <= MAX_BREAK_POINTS; ++which_bp )
+    {
+
+      switch( which_bp )
+      {
+      case 1: addr = GET_CMPA(); break;
+      case 2: addr = GET_CMPB(); break;
+      case 3: addr = GET_CMPC(); break;
+      case 4: addr = GET_CMPD(); break;
+      }
+
+      printf( "Breakpoint [%d]: ", which_bp );
+      if( addr == 0 )
+	printf( "NOT SET\n" );
+      else
+	disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
+    }
+    return;
+  }
+
+  /* Set a breakpoint at the address */
+
+  if( !isdigit( argv[ 1 ][ 0 ]))
+  {
+    cmd_usage(cmdtp);
+    return;
+  }
+
+  addr = simple_strtoul( argv[ 1 ], NULL, 16 ) & 0xfffffffc;
+
+  if(( bug_ctx.set ) && ( which_bp = (*bug_ctx.set)( 0, addr )) > 0 )
+  {
+    printf( "Breakpoint [%d]: ", which_bp );
+    disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
+  }
+
+  return;
+} /* bedbug860_do_break */
+
+
+
+/* ======================================================================
+ * Handle a breakpoint.  First determine which breakpoint was hit by
+ * looking at the DeBug Status Register (DBSR), clear the breakpoint
+ * and enter a mini main loop.  Stay in the loop until the stopped flag
+ * in the debug context is cleared.
+ * ====================================================================== */
+
+void bedbug860_break_isr( struct pt_regs *regs )
+{
+  unsigned long	addr;     /* Address stopped at   */
+  unsigned long	cause;     /* Address stopped at   */
+  /* -------------------------------------------------- */
+
+  cause = GET_ICR();
+
+  if( !(cause & 0x00000004)) {
+    printf( "Not an instruction breakpoint (ICR 0x%08lx)\n", cause );
+    return;
+  }
+
+  addr = regs->nip;
+
+  if( addr == GET_CMPA() )
+  {
+    bug_ctx.current_bp = 1;
+  }
+  else if( addr == GET_CMPB() )
+  {
+    bug_ctx.current_bp = 2;
+  }
+  else if( addr == GET_CMPC() )
+  {
+    bug_ctx.current_bp = 3;
+  }
+  else if( addr == GET_CMPD() )
+  {
+    bug_ctx.current_bp = 4;
+  }
+
+  bedbug_main_loop( addr, regs );
+  return;
+} /* bedbug860_break_isr */
+
+
+
+/* ======================================================================
+ * Look through all of the hardware breakpoints available to see if one
+ * is unused.
+ * ====================================================================== */
+
+int bedbug860_find_empty( void )
+{
+  /* -------------------------------------------------- */
+
+  if( GET_CMPA() == 0 )
+    return 1;
+
+  if( GET_CMPB() == 0 )
+    return 2;
+
+  if( GET_CMPC() == 0 )
+    return 3;
+
+  if( GET_CMPD() == 0 )
+    return 4;
+
+  return 0;
+} /* bedbug860_find_empty */
+
+
+
+/* ======================================================================
+ * Set a breakpoint.  If 'which_bp' is zero then find an unused breakpoint
+ * number, otherwise reassign the given breakpoint.  If hardware debugging
+ * is not enabled, then turn it on via the MSR and DBCR0.  Set the break
+ * address in the appropriate IACx register and enable proper address
+ * beakpoint in DBCR0.
+ * ====================================================================== */
+
+int bedbug860_set( int which_bp, unsigned long addr )
+{
+  /* -------------------------------------------------- */
+
+  /* Only look if which_bp == 0, else use which_bp */
+  if(( bug_ctx.find_empty ) && ( !which_bp ) &&
+     ( which_bp = (*bug_ctx.find_empty)()) == 0 )
+  {
+    printf( "All breakpoints in use\n" );
+    return 0;
+  }
+
+  if( which_bp < 1 || which_bp > MAX_BREAK_POINTS )
+  {
+    printf( "Invalid break point # %d\n", which_bp );
+    return 0;
+  }
+
+  if( ! bug_ctx.hw_debug_enabled )
+  {
+    bug_ctx.hw_debug_enabled = 1;
+    SET_DER( GET_DER() | 0x00000004 );
+  }
+
+  switch( which_bp )
+  {
+  case 1:
+    SET_CMPA( addr );
+    SET_ICTRL( GET_ICTRL() | 0x80080800 ); /* CTA=Equal,IW0=Match A,SIW0EN */
+    break;
+
+  case 2:
+    SET_CMPB( addr );
+    SET_ICTRL( GET_ICTRL() | 0x10020400 ); /* CTB=Equal,IW1=Match B,SIW1EN */
+    break;
+
+  case 3:
+    SET_CMPC( addr );
+    SET_ICTRL( GET_ICTRL() | 0x02008200 ); /* CTC=Equal,IW2=Match C,SIW2EN */
+    break;
+
+  case 4:
+    SET_CMPD( addr );
+    SET_ICTRL( GET_ICTRL() | 0x00404100 ); /* CTD=Equal,IW3=Match D,SIW3EN */
+    break;
+  }
+
+  return which_bp;
+} /* bedbug860_set */
+
+
+
+/* ======================================================================
+ * Disable a specific breakoint by setting the appropriate IACx register
+ * to zero and claring the instruction address breakpoint in DBCR0.
+ * ====================================================================== */
+
+int bedbug860_clear( int which_bp )
+{
+  /* -------------------------------------------------- */
+
+  if( which_bp < 1 || which_bp > MAX_BREAK_POINTS )
+  {
+    printf( "Invalid break point # (%d)\n", which_bp );
+    return -1;
+  }
+
+  switch( which_bp )
+  {
+  case 1:
+    SET_CMPA( 0 );
+    SET_ICTRL( GET_ICTRL() & ~0x80080800 ); /* CTA=Equal,IW0=Match A,SIW0EN */
+    break;
+
+  case 2:
+    SET_CMPB( 0 );
+    SET_ICTRL( GET_ICTRL() & ~0x10020400 ); /* CTB=Equal,IW1=Match B,SIW1EN */
+    break;
+
+  case 3:
+    SET_CMPC( 0 );
+    SET_ICTRL( GET_ICTRL() & ~0x02008200 ); /* CTC=Equal,IW2=Match C,SIW2EN */
+    break;
+
+  case 4:
+    SET_CMPD( 0 );
+    SET_ICTRL( GET_ICTRL() & ~0x00404100 ); /* CTD=Equal,IW3=Match D,SIW3EN */
+    break;
+  }
+
+  return 0;
+} /* bedbug860_clear */
+
+
+/* ====================================================================== */
+#endif
diff --git a/arch/powerpc/cpu/mpc8xx/commproc.c b/arch/powerpc/cpu/mpc8xx/commproc.c
new file mode 100644
index 0000000..a87a0dc
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/commproc.c
@@ -0,0 +1,131 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <commproc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+
+int dpram_init (void)
+{
+	/* Reclaim the DP memory for our use. */
+	gd->dp_alloc_base = CPM_DATAONLY_BASE;
+	gd->dp_alloc_top  = CPM_DATAONLY_BASE + CPM_DATAONLY_SIZE;
+
+	return (0);
+}
+
+/* Allocate some memory from the dual ported ram.  We may want to
+ * enforce alignment restrictions, but right now everyone is a good
+ * citizen.
+ */
+uint dpram_alloc (uint size)
+{
+	uint addr = gd->dp_alloc_base;
+
+	if ((gd->dp_alloc_base + size) >= gd->dp_alloc_top)
+		return (CPM_DP_NOSPACE);
+
+	gd->dp_alloc_base += size;
+
+	return addr;
+}
+
+uint dpram_base (void)
+{
+	return gd->dp_alloc_base;
+}
+
+/* Allocate some memory from the dual ported ram.  We may want to
+ * enforce alignment restrictions, but right now everyone is a good
+ * citizen.
+ */
+uint dpram_alloc_align (uint size, uint align)
+{
+	uint addr, mask = align - 1;
+
+	addr = (gd->dp_alloc_base + mask) & ~mask;
+
+	if ((addr + size) >= gd->dp_alloc_top)
+		return (CPM_DP_NOSPACE);
+
+	gd->dp_alloc_base = addr + size;
+
+	return addr;
+}
+
+uint dpram_base_align (uint align)
+{
+	uint mask = align - 1;
+
+	return (gd->dp_alloc_base + mask) & ~mask;
+}
+#endif	/* CONFIG_SYS_ALLOC_DPRAM */
+
+#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER)
+
+void post_word_store (ulong a)
+{
+	volatile void *save_addr =
+		((immap_t *) CONFIG_SYS_IMMR)->im_cpm.cp_dpmem + CPM_POST_WORD_ADDR;
+
+	*(volatile ulong *) save_addr = a;
+}
+
+ulong post_word_load (void)
+{
+	volatile void *save_addr =
+		((immap_t *) CONFIG_SYS_IMMR)->im_cpm.cp_dpmem + CPM_POST_WORD_ADDR;
+
+	return *(volatile ulong *) save_addr;
+}
+
+#endif	/* CONFIG_POST || CONFIG_LOGBUFFER*/
+
+#ifdef CONFIG_BOOTCOUNT_LIMIT
+
+void bootcount_store (ulong a)
+{
+	volatile ulong *save_addr =
+		(volatile ulong *)( ((immap_t *) CONFIG_SYS_IMMR)->im_cpm.cp_dpmem +
+		                    CPM_BOOTCOUNT_ADDR );
+
+	save_addr[0] = a;
+	save_addr[1] = BOOTCOUNT_MAGIC;
+}
+
+ulong bootcount_load (void)
+{
+	volatile ulong *save_addr =
+		(volatile ulong *)( ((immap_t *) CONFIG_SYS_IMMR)->im_cpm.cp_dpmem +
+		                    CPM_BOOTCOUNT_ADDR );
+
+	if (save_addr[1] != BOOTCOUNT_MAGIC)
+		return 0;
+	else
+		return save_addr[0];
+}
+
+#endif /* CONFIG_BOOTCOUNT_LIMIT */
diff --git a/arch/powerpc/cpu/mpc8xx/config.mk b/arch/powerpc/cpu/mpc8xx/config.mk
new file mode 100644
index 0000000..5540d65
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/config.mk
@@ -0,0 +1,26 @@
+#
+# (C) Copyright 2000
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -fPIC -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_8xx -ffixed-r2 -mstring -mcpu=860 -msoft-float
diff --git a/arch/powerpc/cpu/mpc8xx/cpu.c b/arch/powerpc/cpu/mpc8xx/cpu.c
new file mode 100644
index 0000000..2eb848b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/cpu.c
@@ -0,0 +1,654 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * m8xx.c
+ *
+ * CPU specific code
+ *
+ * written or collected and sometimes rewritten by
+ * Magnus Damm <damm@bitsmart.com>
+ *
+ * minor modifications by
+ * Wolfgang Denk <wd@denx.de>
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc8xx.h>
+#include <commproc.h>
+#include <netdev.h>
+#include <asm/cache.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <libfdt_env.h>
+#include <fdt_support.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static char *cpu_warning = "\n         " \
+	"*** Warning: CPU Core has Silicon Bugs -- Check the Errata ***";
+
+#if ((defined(CONFIG_MPC86x) || defined(CONFIG_MPC855)) && \
+     !defined(CONFIG_MPC862))
+
+static int check_CPU (long clock, uint pvr, uint immr)
+{
+	char *id_str =
+# if defined(CONFIG_MPC855)
+	"PC855";
+# elif defined(CONFIG_MPC860P)
+	"PC860P";
+# else
+	NULL;
+# endif
+	volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
+	uint k, m;
+	char buf[32];
+	char pre = 'X';
+	char *mid = "xx";
+	char *suf;
+
+	/* the highest 16 bits should be 0x0050 for a 860 */
+
+	if ((pvr >> 16) != 0x0050)
+		return -1;
+
+	k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]);
+	m = 0;
+	suf = "";
+
+	/*
+	 * Some boards use sockets so different CPUs can be used.
+	 * We have to check chip version in run time.
+	 */
+	switch (k) {
+	case 0x00020001: pre = 'P'; break;
+	case 0x00030001: break;
+	case 0x00120003: suf = "A"; break;
+	case 0x00130003: suf = "A3"; break;
+
+	case 0x00200004: suf = "B"; break;
+
+	case 0x00300004: suf = "C"; break;
+	case 0x00310004: suf = "C1"; m = 1; break;
+
+	case 0x00200064: mid = "SR"; suf = "B"; break;
+	case 0x00300065: mid = "SR"; suf = "C"; break;
+	case 0x00310065: mid = "SR"; suf = "C1"; m = 1; break;
+	case 0x05010000: suf = "D3"; m = 1; break;
+	case 0x05020000: suf = "D4"; m = 1; break;
+		/* this value is not documented anywhere */
+	case 0x40000000: pre = 'P'; suf = "D"; m = 1; break;
+		/* MPC866P/MPC866T/MPC859T/MPC859DSL/MPC852T */
+	case 0x08010004:		/* Rev. A.0 */
+		suf = "A";
+		/* fall through */
+	case 0x08000003:		/* Rev. 0.3 */
+		pre = 'M'; m = 1;
+		if (id_str == NULL)
+			id_str =
+# if defined(CONFIG_MPC852T)
+		"PC852T";
+# elif defined(CONFIG_MPC859T)
+		"PC859T";
+# elif defined(CONFIG_MPC859DSL)
+		"PC859DSL";
+# elif defined(CONFIG_MPC866T)
+		"PC866T";
+# else
+		"PC866x"; /* Unknown chip from MPC866 family */
+# endif
+		break;
+	case 0x09000000: pre = 'M'; mid = suf = ""; m = 1;
+		if (id_str == NULL)
+			id_str = "PC885"; /* 870/875/880/885 */
+		break;
+
+	default: suf = NULL; break;
+	}
+
+	if (id_str == NULL)
+		id_str = "PC86x";	/* Unknown 86x chip */
+	if (suf)
+		printf ("%c%s%sZPnn%s", pre, id_str, mid, suf);
+	else
+		printf ("unknown M%s (0x%08x)", id_str, k);
+
+
+#if defined(CONFIG_SYS_8xx_CPUCLK_MIN) && defined(CONFIG_SYS_8xx_CPUCLK_MAX)
+	printf (" at %s MHz [%d.%d...%d.%d MHz]\n       ",
+		strmhz (buf, clock),
+		CONFIG_SYS_8xx_CPUCLK_MIN / 1000000,
+		((CONFIG_SYS_8xx_CPUCLK_MIN % 1000000) + 50000) / 100000,
+		CONFIG_SYS_8xx_CPUCLK_MAX / 1000000,
+		((CONFIG_SYS_8xx_CPUCLK_MAX % 1000000) + 50000) / 100000
+	);
+#else
+	printf (" at %s MHz: ", strmhz (buf, clock));
+#endif
+	printf ("%u kB I-Cache %u kB D-Cache",
+		checkicache () >> 10,
+		checkdcache () >> 10
+	);
+
+	/* do we have a FEC (860T/P or 852/859/866/885)? */
+
+	immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
+	if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
+		printf (" FEC present");
+	}
+
+	if (!m) {
+		puts (cpu_warning);
+	}
+
+	putc ('\n');
+
+#ifdef DEBUG
+	if(clock != measure_gclk()) {
+	    printf ("clock %ldHz != %dHz\n", clock, measure_gclk());
+	}
+#endif
+
+	return 0;
+}
+
+#elif defined(CONFIG_MPC862)
+
+static int check_CPU (long clock, uint pvr, uint immr)
+{
+	volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
+	uint k, m;
+	char buf[32];
+	char pre = 'X';
+	char *mid = "xx";
+	char *suf;
+
+	/* the highest 16 bits should be 0x0050 for a 8xx */
+
+	if ((pvr >> 16) != 0x0050)
+		return -1;
+
+	k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]);
+	m = 0;
+
+	switch (k) {
+
+		/* this value is not documented anywhere */
+	case 0x06000000: mid = "P"; suf = "0"; break;
+	case 0x06010001: mid = "P"; suf = "A"; m = 1; break;
+	case 0x07000003: mid = "P"; suf = "B"; m = 1; break;
+	default: suf = NULL; break;
+	}
+
+#ifndef CONFIG_MPC857
+	if (suf)
+		printf ("%cPC862%sZPnn%s", pre, mid, suf);
+	else
+		printf ("unknown MPC862 (0x%08x)", k);
+#else
+	if (suf)
+		printf ("%cPC857TZPnn%s", pre, suf); /* only 857T tested right now! */
+	else
+		printf ("unknown MPC857 (0x%08x)", k);
+#endif
+
+	printf (" at %s MHz:", strmhz (buf, clock));
+
+	printf (" %u kB I-Cache", checkicache () >> 10);
+	printf (" %u kB D-Cache", checkdcache () >> 10);
+
+	/* lets check and see if we're running on a 862T (or P?) */
+
+	immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
+	if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
+		printf (" FEC present");
+	}
+
+	if (!m) {
+		puts (cpu_warning);
+	}
+
+	putc ('\n');
+
+	return 0;
+}
+
+#elif defined(CONFIG_MPC823)
+
+static int check_CPU (long clock, uint pvr, uint immr)
+{
+	volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
+	uint k, m;
+	char buf[32];
+	char *suf;
+
+	/* the highest 16 bits should be 0x0050 for a 8xx */
+
+	if ((pvr >> 16) != 0x0050)
+		return -1;
+
+	k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]);
+	m = 0;
+
+	switch (k) {
+		/* MPC823 */
+	case 0x20000000: suf = "0"; break;
+	case 0x20010000: suf = "0.1"; break;
+	case 0x20020000: suf = "Z2/3"; break;
+	case 0x20020001: suf = "Z3"; break;
+	case 0x21000000: suf = "A"; break;
+	case 0x21010000: suf = "B"; m = 1; break;
+	case 0x21010001: suf = "B2"; m = 1; break;
+		/* MPC823E */
+	case 0x24010000: suf = NULL;
+			puts ("PPC823EZTnnB2");
+			m = 1;
+			break;
+	default:
+			suf = NULL;
+			printf ("unknown MPC823 (0x%08x)", k);
+			break;
+	}
+	if (suf)
+		printf ("PPC823ZTnn%s", suf);
+
+	printf (" at %s MHz:", strmhz (buf, clock));
+
+	printf (" %u kB I-Cache", checkicache () >> 10);
+	printf (" %u kB D-Cache", checkdcache () >> 10);
+
+	/* lets check and see if we're running on a 860T (or P?) */
+
+	immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
+	if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
+		puts (" FEC present");
+	}
+
+	if (!m) {
+		puts (cpu_warning);
+	}
+
+	putc ('\n');
+
+	return 0;
+}
+
+#elif defined(CONFIG_MPC850)
+
+static int check_CPU (long clock, uint pvr, uint immr)
+{
+	volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
+	uint k, m;
+	char buf[32];
+
+	/* the highest 16 bits should be 0x0050 for a 8xx */
+
+	if ((pvr >> 16) != 0x0050)
+		return -1;
+
+	k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]);
+	m = 0;
+
+	switch (k) {
+	case 0x20020001:
+		printf ("XPC850xxZT");
+		break;
+	case 0x21000065:
+		printf ("XPC850xxZTA");
+		break;
+	case 0x21010067:
+		printf ("XPC850xxZTB");
+		m = 1;
+		break;
+	case 0x21020068:
+		printf ("XPC850xxZTC");
+		m = 1;
+		break;
+	default:
+		printf ("unknown MPC850 (0x%08x)", k);
+	}
+	printf (" at %s MHz:", strmhz (buf, clock));
+
+	printf (" %u kB I-Cache", checkicache () >> 10);
+	printf (" %u kB D-Cache", checkdcache () >> 10);
+
+	/* lets check and see if we're running on a 850T (or P?) */
+
+	immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
+	if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
+		printf (" FEC present");
+	}
+
+	if (!m) {
+		puts (cpu_warning);
+	}
+
+	putc ('\n');
+
+	return 0;
+}
+#else
+#error CPU undefined
+#endif
+/* ------------------------------------------------------------------------- */
+
+int checkcpu (void)
+{
+	ulong clock = gd->cpu_clk;
+	uint immr = get_immr (0);	/* Return full IMMR contents */
+	uint pvr = get_pvr ();
+
+	puts ("CPU:   ");
+
+	/* 850 has PARTNUM 20 */
+	/* 801 has PARTNUM 10 */
+	return check_CPU (clock, pvr, immr);
+}
+
+/* ------------------------------------------------------------------------- */
+/* L1 i-cache                                                                */
+/* the standard 860 has 128 sets of 16 bytes in 2 ways (= 4 kB)              */
+/* the 860 P (plus) has 256 sets of 16 bytes in 4 ways (= 16 kB)             */
+
+int checkicache (void)
+{
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	u32 cacheon = rd_ic_cst () & IDC_ENABLED;
+
+#ifdef CONFIG_IP86x
+	u32 k = memctl->memc_br1 & ~0x00007fff;	/* probe in flash memoryarea */
+#else
+	u32 k = memctl->memc_br0 & ~0x00007fff;	/* probe in flash memoryarea */
+#endif
+	u32 m;
+	u32 lines = -1;
+
+	wr_ic_cst (IDC_UNALL);
+	wr_ic_cst (IDC_INVALL);
+	wr_ic_cst (IDC_DISABLE);
+	__asm__ volatile ("isync");
+
+	while (!((m = rd_ic_cst ()) & IDC_CERR2)) {
+		wr_ic_adr (k);
+		wr_ic_cst (IDC_LDLCK);
+		__asm__ volatile ("isync");
+
+		lines++;
+		k += 0x10;				/* the number of bytes in a cacheline */
+	}
+
+	wr_ic_cst (IDC_UNALL);
+	wr_ic_cst (IDC_INVALL);
+
+	if (cacheon)
+		wr_ic_cst (IDC_ENABLE);
+	else
+		wr_ic_cst (IDC_DISABLE);
+
+	__asm__ volatile ("isync");
+
+	return lines << 4;
+};
+
+/* ------------------------------------------------------------------------- */
+/* L1 d-cache                                                                */
+/* the standard 860 has 128 sets of 16 bytes in 2 ways (= 4 kB)              */
+/* the 860 P (plus) has 256 sets of 16 bytes in 2 ways (= 8 kB)              */
+/* call with cache disabled                                                  */
+
+int checkdcache (void)
+{
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	u32 cacheon = rd_dc_cst () & IDC_ENABLED;
+
+#ifdef CONFIG_IP86x
+	u32 k = memctl->memc_br1 & ~0x00007fff;	/* probe in flash memoryarea */
+#else
+	u32 k = memctl->memc_br0 & ~0x00007fff;	/* probe in flash memoryarea */
+#endif
+	u32 m;
+	u32 lines = -1;
+
+	wr_dc_cst (IDC_UNALL);
+	wr_dc_cst (IDC_INVALL);
+	wr_dc_cst (IDC_DISABLE);
+
+	while (!((m = rd_dc_cst ()) & IDC_CERR2)) {
+		wr_dc_adr (k);
+		wr_dc_cst (IDC_LDLCK);
+		lines++;
+		k += 0x10;	/* the number of bytes in a cacheline */
+	}
+
+	wr_dc_cst (IDC_UNALL);
+	wr_dc_cst (IDC_INVALL);
+
+	if (cacheon)
+		wr_dc_cst (IDC_ENABLE);
+	else
+		wr_dc_cst (IDC_DISABLE);
+
+	return lines << 4;
+};
+
+/* ------------------------------------------------------------------------- */
+
+void upmconfig (uint upm, uint * table, uint size)
+{
+	uint i;
+	uint addr = 0;
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+
+	for (i = 0; i < size; i++) {
+		memctl->memc_mdr = table[i];	/* (16-15) */
+		memctl->memc_mcr = addr | upm;	/* (16-16) */
+		addr++;
+	}
+}
+
+/* ------------------------------------------------------------------------- */
+
+#ifndef CONFIG_LWMON
+
+int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	ulong msr, addr;
+
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+
+	immap->im_clkrst.car_plprcr |= PLPRCR_CSR;	/* Checkstop Reset enable */
+
+	/* Interrupts and MMU off */
+	__asm__ volatile ("mtspr    81, 0");
+	__asm__ volatile ("mfmsr    %0":"=r" (msr));
+
+	msr &= ~0x1030;
+	__asm__ volatile ("mtmsr    %0"::"r" (msr));
+
+	/*
+	 * Trying to execute the next instruction at a non-existing address
+	 * should cause a machine check, resulting in reset
+	 */
+#ifdef CONFIG_SYS_RESET_ADDRESS
+	addr = CONFIG_SYS_RESET_ADDRESS;
+#else
+	/*
+	 * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address, CONFIG_SYS_MONITOR_BASE
+	 * - sizeof (ulong) is usually a valid address. Better pick an address
+	 * known to be invalid on your system and assign it to CONFIG_SYS_RESET_ADDRESS.
+	 * "(ulong)-1" used to be a good choice for many systems...
+	 */
+	addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong);
+#endif
+	((void (*)(void)) addr) ();
+	return 1;
+}
+
+#else	/* CONFIG_LWMON */
+
+/*
+ * On the LWMON board, the MCLR reset input of the PIC's on the board
+ * uses a 47K/1n RC combination which has a 47us time  constant.  The
+ * low  signal on the HRESET pin of the CPU is only 512 clocks = 8 us
+ * and thus too short to reset the external hardware. So we  use  the
+ * watchdog to reset the board.
+ */
+int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	/* prevent triggering the watchdog */
+	disable_interrupts ();
+
+	/* make sure the watchdog is running */
+	reset_8xx_watchdog ((immap_t *) CONFIG_SYS_IMMR);
+
+	/* wait for watchdog reset */
+	while (1) {};
+
+	/* NOTREACHED */
+	return 1;
+}
+
+#endif	/* CONFIG_LWMON */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ *
+ * See sections 14.2 and 14.6 of the User's Manual
+ */
+unsigned long get_tbclk (void)
+{
+	uint immr = get_immr (0);	/* Return full IMMR contents */
+	volatile immap_t *immap = (volatile immap_t *)(immr & 0xFFFF0000);
+	ulong oscclk, factor, pll;
+
+	if (immap->im_clkrst.car_sccr & SCCR_TBS) {
+		return (gd->cpu_clk / 16);
+	}
+
+	pll = immap->im_clkrst.car_plprcr;
+
+#define PLPRCR_val(a) ((pll & PLPRCR_ ## a ## _MSK) >> PLPRCR_ ## a ## _SHIFT)
+
+	/*
+	 * For newer PQ1 chips (MPC866/87x/88x families), PLL multiplication
+	 * factor is calculated as follows:
+	 *
+	 *		     MFN
+	 *	     MFI + -------
+	 *		   MFD + 1
+	 * factor =  -----------------
+	 *	     (PDF + 1) * 2^S
+	 *
+	 * For older chips, it's just MF field of PLPRCR plus one.
+	 */
+	if ((immr & 0x0FFF) >= MPC8xx_NEW_CLK) { /* MPC866/87x/88x series */
+		factor = (PLPRCR_val(MFI) + PLPRCR_val(MFN)/(PLPRCR_val(MFD)+1))/
+			(PLPRCR_val(PDF)+1) / (1<<PLPRCR_val(S));
+	} else {
+		factor = PLPRCR_val(MF)+1;
+	}
+
+	oscclk = gd->cpu_clk / factor;
+
+	if ((immap->im_clkrst.car_sccr & SCCR_RTSEL) == 0 || factor > 2) {
+		return (oscclk / 4);
+	}
+	return (oscclk / 16);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset (void)
+{
+	int re_enable = disable_interrupts ();
+
+	reset_8xx_watchdog ((immap_t *) CONFIG_SYS_IMMR);
+	if (re_enable)
+		enable_interrupts ();
+}
+#endif /* CONFIG_WATCHDOG */
+
+#if defined(CONFIG_WATCHDOG) || defined(CONFIG_LWMON)
+
+void reset_8xx_watchdog (volatile immap_t * immr)
+{
+# if defined(CONFIG_LWMON)
+	/*
+	 * The LWMON board uses a MAX6301 Watchdog
+	 * with the trigger pin connected to port PA.7
+	 *
+	 * (The old board version used a MAX706TESA Watchdog, which
+	 * had to be handled exactly the same.)
+	 */
+# define WATCHDOG_BIT	0x0100
+	immr->im_ioport.iop_papar &= ~(WATCHDOG_BIT);	/* GPIO     */
+	immr->im_ioport.iop_padir |= WATCHDOG_BIT;	/* Output   */
+	immr->im_ioport.iop_paodr &= ~(WATCHDOG_BIT);	/* active output */
+
+	immr->im_ioport.iop_padat ^= WATCHDOG_BIT;	/* Toggle WDI   */
+# elif defined(CONFIG_KUP4K) || defined(CONFIG_KUP4X)
+	/*
+	 * The KUP4 boards uses a TPS3705 Watchdog
+	 * with the trigger pin connected to port PA.5
+	 */
+# define WATCHDOG_BIT	0x0400
+	immr->im_ioport.iop_papar &= ~(WATCHDOG_BIT);	/* GPIO     */
+	immr->im_ioport.iop_padir |= WATCHDOG_BIT;	/* Output   */
+	immr->im_ioport.iop_paodr &= ~(WATCHDOG_BIT);	/* active output */
+
+	immr->im_ioport.iop_padat ^= WATCHDOG_BIT;	/* Toggle WDI   */
+# else
+	/*
+	 * All other boards use the MPC8xx Internal Watchdog
+	 */
+	immr->im_siu_conf.sc_swsr = 0x556c;	/* write magic1 */
+	immr->im_siu_conf.sc_swsr = 0xaa39;	/* write magic2 */
+# endif /* CONFIG_LWMON */
+}
+#endif /* CONFIG_WATCHDOG */
+
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(SCC_ENET) && defined(CONFIG_CMD_NET)
+	scc_initialize(bis);
+#endif
+#if defined(FEC_ENET)
+	fec_initialize(bis);
+#endif
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xx/cpu_init.c b/arch/powerpc/cpu/mpc8xx/cpu_init.c
new file mode 100644
index 0000000..eb0091b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/cpu_init.c
@@ -0,0 +1,285 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+
+#include <mpc8xx.h>
+#include <commproc.h>
+
+#if defined(CONFIG_SYS_RTCSC) || defined(CONFIG_SYS_RMDS)
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+#if defined(CONFIG_SYS_I2C_UCODE_PATCH) || defined(CONFIG_SYS_SPI_UCODE_PATCH) || \
+    defined(CONFIG_SYS_SMC_UCODE_PATCH)
+void cpm_load_patch (volatile immap_t * immr);
+#endif
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ * initialize the UPM's
+ */
+void cpu_init_f (volatile immap_t * immr)
+{
+#ifndef CONFIG_MBX
+	volatile memctl8xx_t *memctl = &immr->im_memctl;
+# ifdef CONFIG_SYS_PLPRCR
+	ulong mfmask;
+# endif
+#endif
+	ulong reg;
+
+	/* SYPCR - contains watchdog control (11-9) */
+
+	immr->im_siu_conf.sc_sypcr = CONFIG_SYS_SYPCR;
+
+#if defined(CONFIG_WATCHDOG)
+	reset_8xx_watchdog (immr);
+#endif /* CONFIG_WATCHDOG */
+
+	/* SIUMCR - contains debug pin configuration (11-6) */
+#ifndef CONFIG_SVM_SC8xx
+	immr->im_siu_conf.sc_siumcr |= CONFIG_SYS_SIUMCR;
+#else
+	immr->im_siu_conf.sc_siumcr = CONFIG_SYS_SIUMCR;
+#endif
+	/* initialize timebase status and control register (11-26) */
+	/* unlock TBSCRK */
+
+	immr->im_sitk.sitk_tbscrk = KAPWR_KEY;
+	immr->im_sit.sit_tbscr = CONFIG_SYS_TBSCR;
+
+	/* initialize the PIT (11-31) */
+
+	immr->im_sitk.sitk_piscrk = KAPWR_KEY;
+	immr->im_sit.sit_piscr = CONFIG_SYS_PISCR;
+
+	/* System integration timers. Don't change EBDF! (15-27) */
+
+	immr->im_clkrstk.cark_sccrk = KAPWR_KEY;
+	reg = immr->im_clkrst.car_sccr;
+	reg &= SCCR_MASK;
+	reg |= CONFIG_SYS_SCCR;
+	immr->im_clkrst.car_sccr = reg;
+
+	/* PLL (CPU clock) settings (15-30) */
+
+	immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
+
+#ifndef CONFIG_MBX		/* MBX board does things different */
+
+	/* If CONFIG_SYS_PLPRCR (set in the various *_config.h files) tries to
+	 * set the MF field, then just copy CONFIG_SYS_PLPRCR over car_plprcr,
+	 * otherwise OR in CONFIG_SYS_PLPRCR so we do not change the current MF
+	 * field value.
+	 *
+	 * For newer (starting MPC866) chips PLPRCR layout is different.
+	 */
+#ifdef CONFIG_SYS_PLPRCR
+	if (get_immr(0xFFFF) >= MPC8xx_NEW_CLK)
+	   mfmask = PLPRCR_MFACT_MSK;
+	else
+	   mfmask = PLPRCR_MF_MSK;
+
+	if ((CONFIG_SYS_PLPRCR & mfmask) != 0)
+	   reg = CONFIG_SYS_PLPRCR;			/* reset control bits   */
+	else {
+	   reg = immr->im_clkrst.car_plprcr;
+	   reg &= mfmask;			/* isolate MF-related fields */
+	   reg |= CONFIG_SYS_PLPRCR;			/* reset control bits   */
+	}
+	immr->im_clkrst.car_plprcr = reg;
+#endif
+
+	/*
+	 * Memory Controller:
+	 */
+
+	/* perform BR0 reset that MPC850 Rev. A can't guarantee */
+	reg = memctl->memc_br0;
+	reg &= BR_PS_MSK;	/* Clear everything except Port Size bits */
+	reg |= BR_V;		/* then add just the "Bank Valid" bit     */
+	memctl->memc_br0 = reg;
+
+	/* Map banks 0 (and maybe 1) to the FLASH banks 0 (and 1) at
+	 * preliminary addresses - these have to be modified later
+	 * when FLASH size has been determined
+	 *
+	 * Depending on the size of the memory region defined by
+	 * CONFIG_SYS_OR0_REMAP some boards (wide address mask) allow to map the
+	 * CONFIG_SYS_MONITOR_BASE, while others (narrower address mask) can't
+	 * map CONFIG_SYS_MONITOR_BASE.
+	 *
+	 * For example, for CONFIG_IVMS8, the CONFIG_SYS_MONITOR_BASE is
+	 * 0xff000000, but CONFIG_SYS_OR0_REMAP's address mask is 0xfff80000.
+	 *
+	 * If BR0 wasn't loaded with address base 0xff000000, then BR0's
+	 * base address remains as 0x00000000. However, the address mask
+	 * have been narrowed to 512Kb, so CONFIG_SYS_MONITOR_BASE wasn't mapped
+	 * into the Bank0.
+	 *
+	 * This is why CONFIG_IVMS8 and similar boards must load BR0 with
+	 * CONFIG_SYS_BR0_PRELIM in advance.
+	 *
+	 * [Thanks to Michael Liao for this explanation.
+	 *  I owe him a free beer. - wd]
+	 */
+
+#if defined(CONFIG_GTH)	        || \
+    defined(CONFIG_HERMES)	|| \
+    defined(CONFIG_ICU862)	|| \
+    defined(CONFIG_IP860)	|| \
+    defined(CONFIG_IVML24)	|| \
+    defined(CONFIG_IVMS8)	|| \
+    defined(CONFIG_LWMON)	|| \
+    defined(CONFIG_MHPC)	|| \
+    defined(CONFIG_PCU_E)	|| \
+    defined(CONFIG_R360MPI)	|| \
+    defined(CONFIG_RMU)		|| \
+    defined(CONFIG_RPXCLASSIC)	|| \
+    defined(CONFIG_RPXLITE)	|| \
+    defined(CONFIG_SPC1920)	|| \
+    defined(CONFIG_SPD823TS)
+
+	memctl->memc_br0 = CONFIG_SYS_BR0_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR0_REMAP)
+	memctl->memc_or0 = CONFIG_SYS_OR0_REMAP;
+#endif
+#if defined(CONFIG_SYS_OR1_REMAP)
+	memctl->memc_or1 = CONFIG_SYS_OR1_REMAP;
+#endif
+#if defined(CONFIG_SYS_OR5_REMAP)
+	memctl->memc_or5 = CONFIG_SYS_OR5_REMAP;
+#endif
+
+	/* now restrict to preliminary range */
+	memctl->memc_br0 = CONFIG_SYS_BR0_PRELIM;
+	memctl->memc_or0 = CONFIG_SYS_OR0_PRELIM;
+
+#if (defined(CONFIG_SYS_OR1_PRELIM) && defined(CONFIG_SYS_BR1_PRELIM))
+	memctl->memc_or1 = CONFIG_SYS_OR1_PRELIM;
+	memctl->memc_br1 = CONFIG_SYS_BR1_PRELIM;
+#endif
+
+#if defined(CONFIG_IP860) /* disable CS0 now that Flash is mapped on CS1 */
+	memctl->memc_br0 = 0;
+#endif
+
+#if defined(CONFIG_SYS_OR2_PRELIM) && defined(CONFIG_SYS_BR2_PRELIM)
+	memctl->memc_or2 = CONFIG_SYS_OR2_PRELIM;
+	memctl->memc_br2 = CONFIG_SYS_BR2_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR3_PRELIM) && defined(CONFIG_SYS_BR3_PRELIM)
+	memctl->memc_or3 = CONFIG_SYS_OR3_PRELIM;
+	memctl->memc_br3 = CONFIG_SYS_BR3_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR4_PRELIM) && defined(CONFIG_SYS_BR4_PRELIM)
+	memctl->memc_or4 = CONFIG_SYS_OR4_PRELIM;
+	memctl->memc_br4 = CONFIG_SYS_BR4_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR5_PRELIM) && defined(CONFIG_SYS_BR5_PRELIM)
+	memctl->memc_or5 = CONFIG_SYS_OR5_PRELIM;
+	memctl->memc_br5 = CONFIG_SYS_BR5_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR6_PRELIM) && defined(CONFIG_SYS_BR6_PRELIM)
+	memctl->memc_or6 = CONFIG_SYS_OR6_PRELIM;
+	memctl->memc_br6 = CONFIG_SYS_BR6_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR7_PRELIM) && defined(CONFIG_SYS_BR7_PRELIM)
+	memctl->memc_or7 = CONFIG_SYS_OR7_PRELIM;
+	memctl->memc_br7 = CONFIG_SYS_BR7_PRELIM;
+#endif
+
+#endif /* ! CONFIG_MBX */
+
+	/*
+	 * Reset CPM
+	 */
+	immr->im_cpm.cp_cpcr = CPM_CR_RST | CPM_CR_FLG;
+	do {			/* Spin until command processed     */
+		__asm__ ("eieio");
+	} while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+
+#ifdef CONFIG_MBX
+	/*
+	 * on the MBX, things are a little bit different:
+	 * - we need to read the VPD to get board information
+	 * - the plprcr is set up dynamically
+	 * - the memory controller is set up dynamically
+	 */
+	mbx_init ();
+#endif /* CONFIG_MBX */
+
+#ifdef CONFIG_RPXCLASSIC
+	rpxclassic_init ();
+#endif
+
+#if defined(CONFIG_RPXLITE) && defined(CONFIG_ENV_IS_IN_NVRAM)
+	rpxlite_init ();
+#endif
+
+#ifdef CONFIG_SYS_RCCR			/* must be done before cpm_load_patch() */
+	/* write config value */
+	immr->im_cpm.cp_rccr = CONFIG_SYS_RCCR;
+#endif
+
+#if defined(CONFIG_SYS_I2C_UCODE_PATCH) || defined(CONFIG_SYS_SPI_UCODE_PATCH) || \
+    defined(CONFIG_SYS_SMC_UCODE_PATCH)
+	cpm_load_patch (immr);	/* load mpc8xx  microcode patch */
+#endif
+}
+
+/*
+ * initialize higher level parts of CPU like timers
+ */
+int cpu_init_r (void)
+{
+#if defined(CONFIG_SYS_RTCSC) || defined(CONFIG_SYS_RMDS)
+	bd_t *bd = gd->bd;
+	volatile immap_t *immr = (volatile immap_t *) (bd->bi_immr_base);
+#endif
+
+#ifdef CONFIG_SYS_RTCSC
+	/* Unlock RTSC register */
+	immr->im_sitk.sitk_rtcsck = KAPWR_KEY;
+	/* write config value */
+	immr->im_sit.sit_rtcsc = CONFIG_SYS_RTCSC;
+#endif
+
+#ifdef CONFIG_SYS_RMDS
+	/* write config value */
+	immr->im_cpm.cp_rmds = CONFIG_SYS_RMDS;
+#endif
+	return (0);
+}
diff --git a/arch/powerpc/cpu/mpc8xx/fdt.c b/arch/powerpc/cpu/mpc8xx/fdt.c
new file mode 100644
index 0000000..7130983
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/fdt.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2008 (C) Bryan O'Donoghue
+ *
+ * Code copied & edited from Freescale mpc85xx stuff.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+		"timebase-frequency", get_tbclk(), 1);
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+		"bus-frequency", bd->bi_busfreq, 1);
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+		"clock-frequency", bd->bi_intfreq, 1);
+	do_fixup_by_compat_u32(blob, "fsl,cpm-brg", "clock-frequency",
+		gd->brg_clk, 1);
+
+	/* Fixup ethernet MAC addresses */
+	fdt_fixup_ethernet(blob);
+
+	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+}
diff --git a/arch/powerpc/cpu/mpc8xx/fec.c b/arch/powerpc/cpu/mpc8xx/fec.c
new file mode 100644
index 0000000..89c1ff9
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/fec.c
@@ -0,0 +1,1026 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <commproc.h>
+#include <net.h>
+#include <command.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#undef	ET_DEBUG
+
+#if defined(CONFIG_CMD_NET) && \
+	(defined(FEC_ENET) || defined(CONFIG_ETHER_ON_FEC1) || defined(CONFIG_ETHER_ON_FEC2))
+
+/* compatibility test, if only FEC_ENET defined assume ETHER on FEC1 */
+#if defined(FEC_ENET) && !defined(CONFIG_ETHER_ON_FEC1) && !defined(CONFIG_ETHER_ON_FEC2)
+#define CONFIG_ETHER_ON_FEC1 1
+#endif
+
+/* define WANT_MII when MII support is required */
+#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_FEC1_PHY) || defined(CONFIG_FEC2_PHY)
+#define WANT_MII
+#else
+#undef WANT_MII
+#endif
+
+#if defined(WANT_MII)
+#include <miiphy.h>
+
+#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
+#error "CONFIG_MII has to be defined!"
+#endif
+
+#endif
+
+#if defined(CONFIG_RMII) && !defined(WANT_MII)
+#error RMII support is unusable without a working PHY.
+#endif
+
+#ifdef CONFIG_SYS_DISCOVER_PHY
+static int mii_discover_phy(struct eth_device *dev);
+#endif
+
+int fec8xx_miiphy_read(char *devname, unsigned char addr,
+		unsigned char  reg, unsigned short *value);
+int fec8xx_miiphy_write(char *devname, unsigned char  addr,
+		unsigned char  reg, unsigned short value);
+
+static struct ether_fcc_info_s
+{
+	int ether_index;
+	int fecp_offset;
+	int phy_addr;
+	int actual_phy_addr;
+	int initialized;
+}
+	ether_fcc_info[] = {
+#if defined(CONFIG_ETHER_ON_FEC1)
+	{
+		0,
+		offsetof(immap_t, im_cpm.cp_fec1),
+#if defined(CONFIG_FEC1_PHY)
+		CONFIG_FEC1_PHY,
+#else
+		-1,	/* discover */
+#endif
+		-1,
+		0,
+
+	},
+#endif
+#if defined(CONFIG_ETHER_ON_FEC2)
+	{
+		1,
+		offsetof(immap_t, im_cpm.cp_fec2),
+#if defined(CONFIG_FEC2_PHY)
+		CONFIG_FEC2_PHY,
+#else
+		-1,
+#endif
+		-1,
+		0,
+	},
+#endif
+};
+
+/* Ethernet Transmit and Receive Buffers */
+#define DBUF_LENGTH  1520
+
+#define TX_BUF_CNT 2
+
+#define TOUT_LOOP 100
+
+#define PKT_MAXBUF_SIZE		1518
+#define PKT_MINBUF_SIZE		64
+#define PKT_MAXBLR_SIZE		1520
+
+#ifdef __GNUC__
+static char txbuf[DBUF_LENGTH] __attribute__ ((aligned(8)));
+#else
+#error txbuf must be aligned.
+#endif
+
+static uint rxIdx;	/* index of the current RX buffer */
+static uint txIdx;	/* index of the current TX buffer */
+
+/*
+  * FEC Ethernet Tx and Rx buffer descriptors allocated at the
+  *  immr->udata_bd address on Dual-Port RAM
+  * Provide for Double Buffering
+  */
+
+typedef volatile struct CommonBufferDescriptor {
+    cbd_t rxbd[PKTBUFSRX];		/* Rx BD */
+    cbd_t txbd[TX_BUF_CNT];		/* Tx BD */
+} RTXBD;
+
+static RTXBD *rtx = NULL;
+
+static int fec_send(struct eth_device* dev, volatile void *packet, int length);
+static int fec_recv(struct eth_device* dev);
+static int fec_init(struct eth_device* dev, bd_t * bd);
+static void fec_halt(struct eth_device* dev);
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+static void __mii_init(void);
+#endif
+
+int fec_initialize(bd_t *bis)
+{
+	struct eth_device* dev;
+	struct ether_fcc_info_s *efis;
+	int             i;
+
+	for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++) {
+
+		dev = malloc(sizeof(*dev));
+		if (dev == NULL)
+			hang();
+
+		memset(dev, 0, sizeof(*dev));
+
+		/* for FEC1 make sure that the name of the interface is the same
+		   as the old one for compatibility reasons */
+		if (i == 0) {
+			sprintf (dev->name, "FEC ETHERNET");
+		} else {
+			sprintf (dev->name, "FEC%d ETHERNET",
+				ether_fcc_info[i].ether_index + 1);
+		}
+
+		efis = &ether_fcc_info[i];
+
+		/*
+		 * reset actual phy addr
+		 */
+		efis->actual_phy_addr = -1;
+
+		dev->priv = efis;
+		dev->init = fec_init;
+		dev->halt = fec_halt;
+		dev->send = fec_send;
+		dev->recv = fec_recv;
+
+		eth_register(dev);
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+		miiphy_register(dev->name,
+			fec8xx_miiphy_read, fec8xx_miiphy_write);
+#endif
+	}
+	return 1;
+}
+
+static int fec_send(struct eth_device* dev, volatile void *packet, int length)
+{
+	int j, rc;
+	struct ether_fcc_info_s *efis = dev->priv;
+	volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
+
+	/* section 16.9.23.3
+	 * Wait for ready
+	 */
+	j = 0;
+	while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
+		udelay(1);
+		j++;
+	}
+	if (j>=TOUT_LOOP) {
+		printf("TX not ready\n");
+	}
+
+	rtx->txbd[txIdx].cbd_bufaddr = (uint)packet;
+	rtx->txbd[txIdx].cbd_datlen  = length;
+	rtx->txbd[txIdx].cbd_sc |= BD_ENET_TX_READY | BD_ENET_TX_LAST;
+	__asm__ ("eieio");
+
+	/* Activate transmit Buffer Descriptor polling */
+	fecp->fec_x_des_active = 0x01000000;	/* Descriptor polling active	*/
+
+	j = 0;
+	while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
+#if defined(CONFIG_ICU862)
+		udelay(10);
+#else
+		udelay(1);
+#endif
+		j++;
+	}
+	if (j>=TOUT_LOOP) {
+		printf("TX timeout\n");
+	}
+#ifdef ET_DEBUG
+	printf("%s[%d] %s: cycles: %d    status: %x  retry cnt: %d\n",
+	__FILE__,__LINE__,__FUNCTION__,j,rtx->txbd[txIdx].cbd_sc,
+	(rtx->txbd[txIdx].cbd_sc & 0x003C)>>2);
+#endif
+	/* return only status bits */;
+	rc = (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS);
+
+	txIdx = (txIdx + 1) % TX_BUF_CNT;
+
+	return rc;
+}
+
+static int fec_recv (struct eth_device *dev)
+{
+	struct ether_fcc_info_s *efis = dev->priv;
+	volatile fec_t *fecp =
+		(volatile fec_t *) (CONFIG_SYS_IMMR + efis->fecp_offset);
+	int length;
+
+	for (;;) {
+		/* section 16.9.23.2 */
+		if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+			length = -1;
+			break;	/* nothing received - leave for() loop */
+		}
+
+		length = rtx->rxbd[rxIdx].cbd_datlen;
+
+		if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) {
+#ifdef ET_DEBUG
+			printf ("%s[%d] err: %x\n",
+				__FUNCTION__, __LINE__,
+				rtx->rxbd[rxIdx].cbd_sc);
+#endif
+		} else {
+			volatile uchar *rx = NetRxPackets[rxIdx];
+
+			length -= 4;
+
+#if defined(CONFIG_CMD_CDP)
+			if ((rx[0] & 1) != 0
+			    && memcmp ((uchar *) rx, NetBcastAddr, 6) != 0
+			    && memcmp ((uchar *) rx, NetCDPAddr, 6) != 0)
+				rx = NULL;
+#endif
+			/*
+			 * Pass the packet up to the protocol layers.
+			 */
+			if (rx != NULL)
+				NetReceive (rx, length);
+		}
+
+		/* Give the buffer back to the FEC. */
+		rtx->rxbd[rxIdx].cbd_datlen = 0;
+
+		/* wrap around buffer index when necessary */
+		if ((rxIdx + 1) >= PKTBUFSRX) {
+			rtx->rxbd[PKTBUFSRX - 1].cbd_sc =
+				(BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
+			rxIdx = 0;
+		} else {
+			rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+			rxIdx++;
+		}
+
+		__asm__ ("eieio");
+
+		/* Try to fill Buffer Descriptors */
+		fecp->fec_r_des_active = 0x01000000;	/* Descriptor polling active    */
+	}
+
+	return length;
+}
+
+/**************************************************************
+ *
+ * FEC Ethernet Initialization Routine
+ *
+ *************************************************************/
+
+#define	FEC_ECNTRL_PINMUX	0x00000004
+#define FEC_ECNTRL_ETHER_EN	0x00000002
+#define FEC_ECNTRL_RESET	0x00000001
+
+#define FEC_RCNTRL_BC_REJ	0x00000010
+#define FEC_RCNTRL_PROM		0x00000008
+#define FEC_RCNTRL_MII_MODE	0x00000004
+#define FEC_RCNTRL_DRT		0x00000002
+#define FEC_RCNTRL_LOOP		0x00000001
+
+#define FEC_TCNTRL_FDEN		0x00000004
+#define FEC_TCNTRL_HBC		0x00000002
+#define FEC_TCNTRL_GTS		0x00000001
+
+#define	FEC_RESET_DELAY		50
+
+#if defined(CONFIG_RMII)
+
+static inline void fec_10Mbps(struct eth_device *dev)
+{
+	struct ether_fcc_info_s *efis = dev->priv;
+	int fecidx = efis->ether_index;
+	uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
+
+	if ((unsigned int)fecidx >= 2)
+		hang();
+
+	((volatile immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_cptr |=  mask;
+}
+
+static inline void fec_100Mbps(struct eth_device *dev)
+{
+	struct ether_fcc_info_s *efis = dev->priv;
+	int fecidx = efis->ether_index;
+	uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
+
+	if ((unsigned int)fecidx >= 2)
+		hang();
+
+	((volatile immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_cptr &= ~mask;
+}
+
+#endif
+
+static inline void fec_full_duplex(struct eth_device *dev)
+{
+	struct ether_fcc_info_s *efis = dev->priv;
+	volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
+
+	fecp->fec_r_cntrl &= ~FEC_RCNTRL_DRT;
+	fecp->fec_x_cntrl |=  FEC_TCNTRL_FDEN;	/* FD enable */
+}
+
+static inline void fec_half_duplex(struct eth_device *dev)
+{
+	struct ether_fcc_info_s *efis = dev->priv;
+	volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
+
+	fecp->fec_r_cntrl |=  FEC_RCNTRL_DRT;
+	fecp->fec_x_cntrl &= ~FEC_TCNTRL_FDEN;	/* FD disable */
+}
+
+static void fec_pin_init(int fecidx)
+{
+	bd_t           *bd = gd->bd;
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	volatile fec_t *fecp;
+
+	/*
+	 * only two FECs please
+	 */
+	if ((unsigned int)fecidx >= 2)
+		hang();
+
+	if (fecidx == 0)
+		fecp = &immr->im_cpm.cp_fec1;
+	else
+		fecp = &immr->im_cpm.cp_fec2;
+
+	/*
+	 * Set MII speed to 2.5 MHz or slightly below.
+	 * * According to the MPC860T (Rev. D) Fast ethernet controller user
+	 * * manual (6.2.14),
+	 * * the MII management interface clock must be less than or equal
+	 * * to 2.5 MHz.
+	 * * This MDC frequency is equal to system clock / (2 * MII_SPEED).
+	 * * Then MII_SPEED = system_clock / 2 * 2,5 MHz.
+	 *
+	 * All MII configuration is done via FEC1 registers:
+	 */
+	immr->im_cpm.cp_fec1.fec_mii_speed = ((bd->bi_intfreq + 4999999) / 5000000) << 1;
+
+#if defined(CONFIG_NETTA) || defined(CONFIG_NETPHONE) || defined(CONFIG_NETTA2)
+	/* our PHYs are the limit at 2.5 MHz */
+	fecp->fec_mii_speed <<= 1;
+#endif
+
+#if defined(CONFIG_MPC885_FAMILY) && defined(WANT_MII)
+	/* use MDC for MII */
+	immr->im_ioport.iop_pdpar |=  0x0080;
+	immr->im_ioport.iop_pddir &= ~0x0080;
+#endif
+
+	if (fecidx == 0) {
+#if defined(CONFIG_ETHER_ON_FEC1)
+
+#if defined(CONFIG_MPC885_FAMILY) /* MPC87x/88x have got 2 FECs and different pinout */
+
+#if !defined(CONFIG_RMII)
+
+		immr->im_ioport.iop_papar |=  0xf830;
+		immr->im_ioport.iop_padir |=  0x0830;
+		immr->im_ioport.iop_padir &= ~0xf000;
+
+		immr->im_cpm.cp_pbpar     |=  0x00001001;
+		immr->im_cpm.cp_pbdir     &= ~0x00001001;
+
+		immr->im_ioport.iop_pcpar |=  0x000c;
+		immr->im_ioport.iop_pcdir &= ~0x000c;
+
+		immr->im_cpm.cp_pepar     |=  0x00000003;
+		immr->im_cpm.cp_pedir     |=  0x00000003;
+		immr->im_cpm.cp_peso      &= ~0x00000003;
+
+		immr->im_cpm.cp_cptr      &= ~0x00000100;
+
+#else
+
+#if !defined(CONFIG_FEC1_PHY_NORXERR)
+		immr->im_ioport.iop_papar |=  0x1000;
+		immr->im_ioport.iop_padir &= ~0x1000;
+#endif
+		immr->im_ioport.iop_papar |=  0xe810;
+		immr->im_ioport.iop_padir |=  0x0810;
+		immr->im_ioport.iop_padir &= ~0xe000;
+
+		immr->im_cpm.cp_pbpar     |=  0x00000001;
+		immr->im_cpm.cp_pbdir     &= ~0x00000001;
+
+		immr->im_cpm.cp_cptr      |=  0x00000100;
+		immr->im_cpm.cp_cptr      &= ~0x00000050;
+
+#endif /* !CONFIG_RMII */
+
+#elif !defined(CONFIG_ICU862) && !defined(CONFIG_IAD210)
+		/*
+		 * Configure all of port D for MII.
+		 */
+		immr->im_ioport.iop_pdpar = 0x1fff;
+
+		/*
+		 * Bits moved from Rev. D onward
+		 */
+		if ((get_immr(0) & 0xffff) < 0x0501)
+			immr->im_ioport.iop_pddir = 0x1c58;	/* Pre rev. D */
+		else
+			immr->im_ioport.iop_pddir = 0x1fff;	/* Rev. D and later */
+#else
+		/*
+		 * Configure port A for MII.
+		 */
+
+#if defined(CONFIG_ICU862) && defined(CONFIG_SYS_DISCOVER_PHY)
+
+		/*
+		 * On the ICU862 board the MII-MDC pin is routed to PD8 pin
+		 * * of CPU, so for this board we need to configure Utopia and
+		 * * enable PD8 to MII-MDC function
+		 */
+		immr->im_ioport.iop_pdpar |= 0x4080;
+#endif
+
+		/*
+		 * Has Utopia been configured?
+		 */
+		if (immr->im_ioport.iop_pdpar & (0x8000 >> 1)) {
+			/*
+			 * YES - Use MUXED mode for UTOPIA bus.
+			 * This frees Port A for use by MII (see 862UM table 41-6).
+			 */
+			immr->im_ioport.utmode &= ~0x80;
+		} else {
+			/*
+			 * NO - set SPLIT mode for UTOPIA bus.
+			 *
+			 * This doesn't really effect UTOPIA (which isn't
+			 * enabled anyway) but just tells the 862
+			 * to use port A for MII (see 862UM table 41-6).
+			 */
+			immr->im_ioport.utmode |= 0x80;
+		}
+#endif				/* !defined(CONFIG_ICU862) */
+
+#endif	/* CONFIG_ETHER_ON_FEC1 */
+	} else if (fecidx == 1) {
+
+#if defined(CONFIG_ETHER_ON_FEC2)
+
+#if defined(CONFIG_MPC885_FAMILY) /* MPC87x/88x have got 2 FECs and different pinout */
+
+#if !defined(CONFIG_RMII)
+		immr->im_cpm.cp_pepar     |=  0x0003fffc;
+		immr->im_cpm.cp_pedir     |=  0x0003fffc;
+		immr->im_cpm.cp_peso      &= ~0x000087fc;
+		immr->im_cpm.cp_peso      |=  0x00037800;
+
+		immr->im_cpm.cp_cptr      &= ~0x00000080;
+#else
+
+#if !defined(CONFIG_FEC2_PHY_NORXERR)
+		immr->im_cpm.cp_pepar     |=  0x00000010;
+		immr->im_cpm.cp_pedir     |=  0x00000010;
+		immr->im_cpm.cp_peso      &= ~0x00000010;
+#endif
+		immr->im_cpm.cp_pepar     |=  0x00039620;
+		immr->im_cpm.cp_pedir     |=  0x00039620;
+		immr->im_cpm.cp_peso      |=  0x00031000;
+		immr->im_cpm.cp_peso      &= ~0x00008620;
+
+		immr->im_cpm.cp_cptr      |=  0x00000080;
+		immr->im_cpm.cp_cptr      &= ~0x00000028;
+#endif /* CONFIG_RMII */
+
+#endif /* CONFIG_MPC885_FAMILY */
+
+#endif /* CONFIG_ETHER_ON_FEC2 */
+
+	}
+}
+
+static int fec_reset(volatile fec_t *fecp)
+{
+	int i;
+
+	/* Whack a reset.
+	 * A delay is required between a reset of the FEC block and
+	 * initialization of other FEC registers because the reset takes
+	 * some time to complete. If you don't delay, subsequent writes
+	 * to FEC registers might get killed by the reset routine which is
+	 * still in progress.
+	 */
+
+	fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
+	for (i = 0;
+	     (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
+	     ++i) {
+		udelay (1);
+	}
+	if (i == FEC_RESET_DELAY)
+		return -1;
+
+	return 0;
+}
+
+static int fec_init (struct eth_device *dev, bd_t * bd)
+{
+	struct ether_fcc_info_s *efis = dev->priv;
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	volatile fec_t *fecp =
+		(volatile fec_t *) (CONFIG_SYS_IMMR + efis->fecp_offset);
+	int i;
+
+	if (efis->ether_index == 0) {
+#if defined(CONFIG_FADS)	/* FADS family uses FPGA (BCSR) to control PHYs */
+#if defined(CONFIG_MPC885ADS)
+		*(vu_char *) BCSR5 &= ~(BCSR5_MII1_EN | BCSR5_MII1_RST);
+#else
+		/* configure FADS for fast (FEC) ethernet, half-duplex */
+		/* The LXT970 needs about 50ms to recover from reset, so
+		 * wait for it by discovering the PHY before leaving eth_init().
+		 */
+		{
+			volatile uint *bcsr4 = (volatile uint *) BCSR4;
+
+			*bcsr4 = (*bcsr4 & ~(BCSR4_FETH_EN | BCSR4_FETHCFG1))
+				| (BCSR4_FETHCFG0 | BCSR4_FETHFDE |
+				   BCSR4_FETHRST);
+
+			/* reset the LXT970 PHY */
+			*bcsr4 &= ~BCSR4_FETHRST;
+			udelay (10);
+			*bcsr4 |= BCSR4_FETHRST;
+			udelay (10);
+		}
+#endif /* CONFIG_MPC885ADS */
+#endif /* CONFIG_FADS */
+	}
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+	/* the MII interface is connected to FEC1
+	 * so for the miiphy_xxx function to work we must
+	 * call mii_init since fec_halt messes the thing up
+	 */
+	if (efis->ether_index != 0)
+		__mii_init();
+#endif
+
+	if (fec_reset(fecp) < 0)
+		printf ("FEC_RESET_DELAY timeout\n");
+
+	/* We use strictly polling mode only
+	 */
+	fecp->fec_imask = 0;
+
+	/* Clear any pending interrupt
+	 */
+	fecp->fec_ievent = 0xffc0;
+
+	/* No need to set the IVEC register */
+
+	/* Set station address
+	 */
+#define ea dev->enetaddr
+	fecp->fec_addr_low = (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
+	fecp->fec_addr_high = (ea[4] << 8) | (ea[5]);
+#undef ea
+
+#if defined(CONFIG_CMD_CDP)
+	/*
+	 * Turn on multicast address hash table
+	 */
+	fecp->fec_hash_table_high = 0xffffffff;
+	fecp->fec_hash_table_low = 0xffffffff;
+#else
+	/* Clear multicast address hash table
+	 */
+	fecp->fec_hash_table_high = 0;
+	fecp->fec_hash_table_low = 0;
+#endif
+
+	/* Set maximum receive buffer size.
+	 */
+	fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
+
+	/* Set maximum frame length
+	 */
+	fecp->fec_r_hash = PKT_MAXBUF_SIZE;
+
+	/*
+	 * Setup Buffers and Buffer Desriptors
+	 */
+	rxIdx = 0;
+	txIdx = 0;
+
+	if (!rtx) {
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+		rtx = (RTXBD *) (immr->im_cpm.cp_dpmem +
+				 dpram_alloc_align (sizeof (RTXBD), 8));
+#else
+		rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_FEC_BASE);
+#endif
+	}
+	/*
+	 * Setup Receiver Buffer Descriptors (13.14.24.18)
+	 * Settings:
+	 *     Empty, Wrap
+	 */
+	for (i = 0; i < PKTBUFSRX; i++) {
+		rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+		rtx->rxbd[i].cbd_datlen = 0;	/* Reset */
+		rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i];
+	}
+	rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+	/*
+	 * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
+	 * Settings:
+	 *    Last, Tx CRC
+	 */
+	for (i = 0; i < TX_BUF_CNT; i++) {
+		rtx->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC;
+		rtx->txbd[i].cbd_datlen = 0;	/* Reset */
+		rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]);
+	}
+	rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+	/* Set receive and transmit descriptor base
+	 */
+	fecp->fec_r_des_start = (unsigned int) (&rtx->rxbd[0]);
+	fecp->fec_x_des_start = (unsigned int) (&rtx->txbd[0]);
+
+	/* Enable MII mode
+	 */
+#if 0				/* Full duplex mode */
+	fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE;
+	fecp->fec_x_cntrl = FEC_TCNTRL_FDEN;
+#else  /* Half duplex mode */
+	fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT;
+	fecp->fec_x_cntrl = 0;
+#endif
+
+	/* Enable big endian and don't care about SDMA FC.
+	 */
+	fecp->fec_fun_code = 0x78000000;
+
+	/*
+	 * Setup the pin configuration of the FEC
+	 */
+	fec_pin_init (efis->ether_index);
+
+	rxIdx = 0;
+	txIdx = 0;
+
+	/*
+	 * Now enable the transmit and receive processing
+	 */
+	fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;
+
+	if (efis->phy_addr == -1) {
+#ifdef CONFIG_SYS_DISCOVER_PHY
+		/*
+		 * wait for the PHY to wake up after reset
+		 */
+		efis->actual_phy_addr = mii_discover_phy (dev);
+
+		if (efis->actual_phy_addr == -1) {
+			printf ("Unable to discover phy!\n");
+			return -1;
+		}
+#else
+		efis->actual_phy_addr = -1;
+#endif
+	} else {
+		efis->actual_phy_addr = efis->phy_addr;
+	}
+
+#if defined(CONFIG_MII) && defined(CONFIG_RMII)
+	/*
+	 * adapt the RMII speed to the speed of the phy
+	 */
+	if (miiphy_speed (dev->name, efis->actual_phy_addr) == _100BASET) {
+		fec_100Mbps (dev);
+	} else {
+		fec_10Mbps (dev);
+	}
+#endif
+
+#if defined(CONFIG_MII)
+	/*
+	 * adapt to the half/full speed settings
+	 */
+	if (miiphy_duplex (dev->name, efis->actual_phy_addr) == FULL) {
+		fec_full_duplex (dev);
+	} else {
+		fec_half_duplex (dev);
+	}
+#endif
+
+	/* And last, try to fill Rx Buffer Descriptors */
+	fecp->fec_r_des_active = 0x01000000;	/* Descriptor polling active    */
+
+	efis->initialized = 1;
+
+	return 0;
+}
+
+
+static void fec_halt(struct eth_device* dev)
+{
+	struct ether_fcc_info_s *efis = dev->priv;
+	volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
+	int i;
+
+	/* avoid halt if initialized; mii gets stuck otherwise */
+	if (!efis->initialized)
+		return;
+
+	/* Whack a reset.
+	 * A delay is required between a reset of the FEC block and
+	 * initialization of other FEC registers because the reset takes
+	 * some time to complete. If you don't delay, subsequent writes
+	 * to FEC registers might get killed by the reset routine which is
+	 * still in progress.
+	 */
+
+	fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
+	for (i = 0;
+	     (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
+	     ++i) {
+		udelay (1);
+	}
+	if (i == FEC_RESET_DELAY) {
+		printf ("FEC_RESET_DELAY timeout\n");
+		return;
+	}
+
+	efis->initialized = 0;
+}
+
+#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+
+/* Make MII read/write commands for the FEC.
+*/
+
+#define mk_mii_read(ADDR, REG)	(0x60020000 | ((ADDR << 23) | \
+						(REG & 0x1f) << 18))
+
+#define mk_mii_write(ADDR, REG, VAL)	(0x50020000 | ((ADDR << 23) | \
+						(REG & 0x1f) << 18) | \
+						(VAL & 0xffff))
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR	((uint)0x80000000)	/* Heartbeat error */
+#define FEC_ENET_BABR	((uint)0x40000000)	/* Babbling receiver */
+#define FEC_ENET_BABT	((uint)0x20000000)	/* Babbling transmitter */
+#define FEC_ENET_GRA	((uint)0x10000000)	/* Graceful stop complete */
+#define FEC_ENET_TXF	((uint)0x08000000)	/* Full frame transmitted */
+#define FEC_ENET_TXB	((uint)0x04000000)	/* A buffer was transmitted */
+#define FEC_ENET_RXF	((uint)0x02000000)	/* Full frame received */
+#define FEC_ENET_RXB	((uint)0x01000000)	/* A buffer was received */
+#define FEC_ENET_MII	((uint)0x00800000)	/* MII interrupt */
+#define FEC_ENET_EBERR	((uint)0x00400000)	/* SDMA bus error */
+
+/* PHY identification
+ */
+#define PHY_ID_LXT970		0x78100000	/* LXT970 */
+#define PHY_ID_LXT971		0x001378e0	/* LXT971 and 972 */
+#define PHY_ID_82555		0x02a80150	/* Intel 82555 */
+#define PHY_ID_QS6612		0x01814400	/* QS6612 */
+#define PHY_ID_AMD79C784	0x00225610	/* AMD 79C784 */
+#define PHY_ID_LSI80225		0x0016f870	/* LSI 80225 */
+#define PHY_ID_LSI80225B	0x0016f880	/* LSI 80225/B */
+#define PHY_ID_DM9161		0x0181B880	/* Davicom DM9161 */
+#define PHY_ID_KSM8995M		0x00221450	/* MICREL KS8995MA */
+
+/* send command to phy using mii, wait for result */
+static uint
+mii_send(uint mii_cmd)
+{
+	uint mii_reply;
+	volatile fec_t	*ep;
+	int cnt;
+
+	ep = &(((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_fec);
+
+	ep->fec_mii_data = mii_cmd;	/* command to phy */
+
+	/* wait for mii complete */
+	cnt = 0;
+	while (!(ep->fec_ievent & FEC_ENET_MII)) {
+		if (++cnt > 1000) {
+			printf("mii_send STUCK!\n");
+			break;
+		}
+	}
+	mii_reply = ep->fec_mii_data;		/* result from phy */
+	ep->fec_ievent = FEC_ENET_MII;		/* clear MII complete */
+#if 0
+	printf("%s[%d] %s: sent=0x%8.8x, reply=0x%8.8x\n",
+		__FILE__,__LINE__,__FUNCTION__,mii_cmd,mii_reply);
+#endif
+	return (mii_reply & 0xffff);		/* data read from phy */
+}
+#endif
+
+#if defined(CONFIG_SYS_DISCOVER_PHY)
+static int mii_discover_phy(struct eth_device *dev)
+{
+#define MAX_PHY_PASSES 11
+	uint phyno;
+	int  pass;
+	uint phytype;
+	int phyaddr;
+
+	phyaddr = -1;	/* didn't find a PHY yet */
+	for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) {
+		if (pass > 1) {
+			/* PHY may need more time to recover from reset.
+			 * The LXT970 needs 50ms typical, no maximum is
+			 * specified, so wait 10ms before try again.
+			 * With 11 passes this gives it 100ms to wake up.
+			 */
+			udelay(10000);	/* wait 10ms */
+		}
+		for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) {
+			phytype = mii_send(mk_mii_read(phyno, PHY_PHYIDR2));
+#ifdef ET_DEBUG
+			printf("PHY type 0x%x pass %d type ", phytype, pass);
+#endif
+			if (phytype != 0xffff) {
+				phyaddr = phyno;
+				phytype |= mii_send(mk_mii_read(phyno,
+								PHY_PHYIDR1)) << 16;
+
+#ifdef ET_DEBUG
+				printf("PHY @ 0x%x pass %d type ",phyno,pass);
+				switch (phytype & 0xfffffff0) {
+				case PHY_ID_LXT970:
+					printf("LXT970\n");
+					break;
+				case PHY_ID_LXT971:
+					printf("LXT971\n");
+					break;
+				case PHY_ID_82555:
+					printf("82555\n");
+					break;
+				case PHY_ID_QS6612:
+					printf("QS6612\n");
+					break;
+				case PHY_ID_AMD79C784:
+					printf("AMD79C784\n");
+					break;
+				case PHY_ID_LSI80225B:
+					printf("LSI L80225/B\n");
+					break;
+				case PHY_ID_DM9161:
+					printf("Davicom DM9161\n");
+					break;
+				case PHY_ID_KSM8995M:
+					printf("MICREL KS8995M\n");
+					break;
+				default:
+					printf("0x%08x\n", phytype);
+					break;
+				}
+#endif
+			}
+		}
+	}
+	if (phyaddr < 0) {
+		printf("No PHY device found.\n");
+	}
+	return phyaddr;
+}
+#endif	/* CONFIG_SYS_DISCOVER_PHY */
+
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && !defined(CONFIG_BITBANGMII)
+
+/****************************************************************************
+ * mii_init -- Initialize the MII via FEC 1 for MII command without ethernet
+ * This function is a subset of eth_init
+ ****************************************************************************
+ */
+static void __mii_init(void)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	volatile fec_t *fecp = &(immr->im_cpm.cp_fec);
+
+	if (fec_reset(fecp) < 0)
+		printf ("FEC_RESET_DELAY timeout\n");
+
+	/* We use strictly polling mode only
+	 */
+	fecp->fec_imask = 0;
+
+	/* Clear any pending interrupt
+	 */
+	fecp->fec_ievent = 0xffc0;
+
+	/* Now enable the transmit and receive processing
+	 */
+	fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;
+}
+
+void mii_init (void)
+{
+	int i;
+
+	__mii_init();
+
+	/* Setup the pin configuration of the FEC(s)
+	*/
+	for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
+		fec_pin_init(ether_fcc_info[i].ether_index);
+}
+
+/*****************************************************************************
+ * Read and write a MII PHY register, routines used by MII Utilities
+ *
+ * FIXME: These routines are expected to return 0 on success, but mii_send
+ *	  does _not_ return an error code. Maybe 0xFFFF means error, i.e.
+ *	  no PHY connected...
+ *	  For now always return 0.
+ * FIXME: These routines only work after calling eth_init() at least once!
+ *	  Otherwise they hang in mii_send() !!! Sorry!
+ *****************************************************************************/
+
+int fec8xx_miiphy_read(char *devname, unsigned char addr,
+		unsigned char  reg, unsigned short *value)
+{
+	short rdreg;    /* register working value */
+
+#ifdef MII_DEBUG
+	printf ("miiphy_read(0x%x) @ 0x%x = ", reg, addr);
+#endif
+	rdreg = mii_send(mk_mii_read(addr, reg));
+
+	*value = rdreg;
+#ifdef MII_DEBUG
+	printf ("0x%04x\n", *value);
+#endif
+	return 0;
+}
+
+int fec8xx_miiphy_write(char *devname, unsigned char  addr,
+		unsigned char  reg, unsigned short value)
+{
+	short rdreg;    /* register working value */
+#ifdef MII_DEBUG
+	printf ("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
+#endif
+	rdreg = mii_send(mk_mii_write(addr, reg, value));
+
+#ifdef MII_DEBUG
+	printf ("0x%04x\n", value);
+#endif
+	return 0;
+}
+#endif
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8xx/fec.h b/arch/powerpc/cpu/mpc8xx/fec.h
new file mode 100644
index 0000000..a49417c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/fec.h
@@ -0,0 +1,28 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef	_FEC_H_
+#define	_FEC_H_
+
+
+#endif	/* _FEC_H_ */
diff --git a/arch/powerpc/cpu/mpc8xx/i2c.c b/arch/powerpc/cpu/mpc8xx/i2c.c
new file mode 100644
index 0000000..338caba
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/i2c.c
@@ -0,0 +1,707 @@
+/*
+ * (C) Copyright 2000
+ * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
+ *
+ * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Back ported to the 8xx platform (from the 8260 platform) by
+ * Murray.Jensen@cmst.csiro.au, 27-Jan-01.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_HARD_I2C
+
+#include <commproc.h>
+#include <i2c.h>
+#ifdef CONFIG_LWMON
+#include <watchdog.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* define to enable debug messages */
+#undef	DEBUG_I2C
+
+/* tx/rx timeout (we need the i2c early, so we don't use get_timer()) */
+#define TOUT_LOOP 1000000
+
+#define NUM_RX_BDS 4
+#define NUM_TX_BDS 4
+#define MAX_TX_SPACE 256
+#define I2C_RXTX_LEN 128	/* maximum tx/rx buffer length */
+
+typedef struct I2C_BD
+{
+  unsigned short status;
+  unsigned short length;
+  unsigned char *addr;
+} I2C_BD;
+#define BD_I2C_TX_START 0x0400  /* special status for i2c: Start condition */
+
+#define BD_I2C_TX_CL	0x0001	/* collision error */
+#define BD_I2C_TX_UN	0x0002	/* underflow error */
+#define BD_I2C_TX_NAK	0x0004	/* no acknowledge error */
+#define BD_I2C_TX_ERR	(BD_I2C_TX_NAK|BD_I2C_TX_UN|BD_I2C_TX_CL)
+
+#define BD_I2C_RX_ERR	BD_SC_OV
+
+typedef void (*i2c_ecb_t)(int, int);	/* error callback function */
+
+/* This structure keeps track of the bd and buffer space usage. */
+typedef struct i2c_state {
+	int		rx_idx;		/* index   to next free Rx BD */
+	int		tx_idx;		/* index   to next free Tx BD */
+	void		*rxbd;		/* pointer to next free Rx BD */
+	void		*txbd;		/* pointer to next free Tx BD */
+	int		tx_space;	/* number  of Tx bytes left   */
+	unsigned char	*tx_buf;	/* pointer to free Tx area    */
+	i2c_ecb_t	err_cb;		/* error callback function    */
+} i2c_state_t;
+
+
+/* flags for i2c_send() and i2c_receive() */
+#define I2CF_ENABLE_SECONDARY	0x01	/* secondary_address is valid		*/
+#define I2CF_START_COND		0x02	/* tx: generate start condition		*/
+#define I2CF_STOP_COND		0x04	/* tx: generate stop  condition		*/
+
+/* return codes */
+#define I2CERR_NO_BUFFERS	0x01	/* no more BDs or buffer space		*/
+#define I2CERR_MSG_TOO_LONG	0x02	/* tried to send/receive to much data	*/
+#define I2CERR_TIMEOUT		0x03	/* timeout in i2c_doio()		*/
+#define I2CERR_QUEUE_EMPTY	0x04	/* i2c_doio called without send/receive */
+
+/* error callback flags */
+#define I2CECB_RX_ERR		0x10	/* this is a receive error		*/
+#define     I2CECB_RX_ERR_OV	0x02	/* receive overrun error		*/
+#define     I2CECB_RX_MASK	0x0f	/* mask for error bits			*/
+#define I2CECB_TX_ERR		0x20	/* this is a transmit error		*/
+#define     I2CECB_TX_CL	0x01	/* transmit collision error		*/
+#define     I2CECB_TX_UN	0x02	/* transmit underflow error		*/
+#define     I2CECB_TX_NAK	0x04	/* transmit no ack error		*/
+#define     I2CECB_TX_MASK	0x0f	/* mask for error bits			*/
+#define I2CECB_TIMEOUT		0x40	/* this is a timeout error		*/
+
+#ifdef DEBUG_I2C
+#define PRINTD(x) printf x
+#else
+#define PRINTD(x)
+#endif
+
+/*
+ * Returns the best value of I2BRG to meet desired clock speed of I2C with
+ * input parameters (clock speed, filter, and predivider value).
+ * It returns computer speed value and the difference between it and desired
+ * speed.
+ */
+static inline int
+i2c_roundrate(int hz, int speed, int filter, int modval,
+		int *brgval, int *totspeed)
+{
+    int moddiv = 1 << (5-(modval & 3)), brgdiv, div;
+
+    PRINTD(("\t[I2C] trying hz=%d, speed=%d, filter=%d, modval=%d\n",
+	hz, speed, filter, modval));
+
+    div = moddiv * speed;
+    brgdiv = (hz + div - 1) / div;
+
+    PRINTD(("\t\tmoddiv=%d, brgdiv=%d\n", moddiv, brgdiv));
+
+    *brgval = ((brgdiv + 1) / 2) - 3 - (2*filter);
+
+    if ((*brgval < 0) || (*brgval > 255)) {
+	  PRINTD(("\t\trejected brgval=%d\n", *brgval));
+	  return -1;
+    }
+
+    brgdiv = 2 * (*brgval + 3 + (2 * filter));
+    div = moddiv * brgdiv ;
+    *totspeed = hz / div;
+
+    PRINTD(("\t\taccepted brgval=%d, totspeed=%d\n", *brgval, *totspeed));
+
+    return  0;
+}
+
+/*
+ * Sets the I2C clock predivider and divider to meet required clock speed.
+ */
+static int
+i2c_setrate (int hz, int speed)
+{
+	immap_t		*immap = (immap_t *) CONFIG_SYS_IMMR;
+	volatile i2c8xx_t *i2c = (i2c8xx_t *) & immap->im_i2c;
+	int		brgval,
+			modval,		/* 0-3 */
+			bestspeed_diff = speed,
+			bestspeed_brgval = 0,
+			bestspeed_modval = 0,
+			bestspeed_filter = 0,
+			totspeed,
+			filter = 0;	/* Use this fixed value */
+
+	for (modval = 0; modval < 4; modval++) {
+		if (i2c_roundrate(hz,speed,filter,modval,&brgval,&totspeed) == 0) {
+			int diff = speed - totspeed;
+
+			if ((diff >= 0) && (diff < bestspeed_diff)) {
+				bestspeed_diff = diff;
+				bestspeed_modval = modval;
+				bestspeed_brgval = brgval;
+				bestspeed_filter = filter;
+			}
+		}
+	}
+
+	PRINTD (("[I2C] Best is:\n"));
+	PRINTD (("[I2C] CPU=%dhz RATE=%d F=%d I2MOD=%08x I2BRG=%08x DIFF=%dhz\n",
+		hz,
+		speed,
+		bestspeed_filter,
+		bestspeed_modval,
+		bestspeed_brgval,
+		bestspeed_diff));
+
+	i2c->i2c_i2mod |= ((bestspeed_modval & 3) << 1) | (bestspeed_filter << 3);
+	i2c->i2c_i2brg = bestspeed_brgval & 0xff;
+
+	PRINTD (("[I2C] i2mod=%08x i2brg=%08x\n", i2c->i2c_i2mod,
+			 i2c->i2c_i2brg));
+
+	return 1;
+}
+
+void
+i2c_init(int speed, int slaveaddr)
+{
+	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR ;
+	volatile cpm8xx_t *cp = (cpm8xx_t *)&immap->im_cpm;
+	volatile i2c8xx_t *i2c	= (i2c8xx_t *)&immap->im_i2c;
+	volatile iic_t *iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
+	ulong rbase, tbase;
+	volatile I2C_BD *rxbd, *txbd;
+	uint dpaddr;
+
+#ifdef CONFIG_SYS_I2C_INIT_BOARD
+	/* call board specific i2c bus reset routine before accessing the   */
+	/* environment, which might be in a chip on that bus. For details   */
+	/* about this problem see doc/I2C_Edge_Conditions.                  */
+	i2c_init_board();
+#endif
+
+#ifdef CONFIG_SYS_I2C_UCODE_PATCH
+	iip = (iic_t *)&cp->cp_dpmem[iip->iic_rpbase];
+#else
+	/* Disable relocation */
+	iip->iic_rpbase = 0;
+#endif
+
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+	dpaddr = iip->iic_rbase;
+	if (dpaddr == 0) {
+	    /* need to allocate dual port ram */
+	    dpaddr = dpram_alloc_align(
+		(NUM_RX_BDS * sizeof(I2C_BD)) + (NUM_TX_BDS * sizeof(I2C_BD)) +
+		MAX_TX_SPACE, 8);
+	}
+#else
+	dpaddr = CPM_I2C_BASE;
+#endif
+
+	/*
+	 * initialise data in dual port ram:
+	 *
+	 * dpaddr->rbase -> rx BD         (NUM_RX_BDS * sizeof(I2C_BD) bytes)
+	 *         tbase -> tx BD         (NUM_TX_BDS * sizeof(I2C_BD) bytes)
+	 *                  tx buffer     (MAX_TX_SPACE bytes)
+	 */
+
+	rbase = dpaddr;
+	tbase = rbase + NUM_RX_BDS * sizeof(I2C_BD);
+
+	/* Initialize Port B I2C pins. */
+	cp->cp_pbpar |= 0x00000030;
+	cp->cp_pbdir |= 0x00000030;
+	cp->cp_pbodr |= 0x00000030;
+
+	/* Disable interrupts */
+	i2c->i2c_i2mod = 0x00;
+	i2c->i2c_i2cmr = 0x00;
+	i2c->i2c_i2cer = 0xff;
+	i2c->i2c_i2add = slaveaddr;
+
+	/*
+	 * Set the I2C BRG Clock division factor from desired i2c rate
+	 * and current CPU rate (we assume sccr dfbgr field is 0;
+	 * divide BRGCLK by 1)
+	 */
+	PRINTD(("[I2C] Setting rate...\n"));
+	i2c_setrate (gd->cpu_clk, CONFIG_SYS_I2C_SPEED) ;
+
+	/* Set I2C controller in master mode */
+	i2c->i2c_i2com = 0x01;
+
+	/* Set SDMA bus arbitration level to 5 (SDCR) */
+	immap->im_siu_conf.sc_sdcr = 0x0001 ;
+
+	/* Initialize Tx/Rx parameters */
+	iip->iic_rbase = rbase;
+	iip->iic_tbase = tbase;
+	rxbd = (I2C_BD *)((unsigned char *)&cp->cp_dpmem[iip->iic_rbase]);
+	txbd = (I2C_BD *)((unsigned char *)&cp->cp_dpmem[iip->iic_tbase]);
+
+	PRINTD(("[I2C] rbase = %04x\n", iip->iic_rbase));
+	PRINTD(("[I2C] tbase = %04x\n", iip->iic_tbase));
+	PRINTD(("[I2C] rxbd = %08x\n", (int)rxbd));
+	PRINTD(("[I2C] txbd = %08x\n", (int)txbd));
+
+	/* Set big endian byte order */
+	iip->iic_tfcr = 0x10;
+	iip->iic_rfcr = 0x10;
+
+	/* Set maximum receive size. */
+	iip->iic_mrblr = I2C_RXTX_LEN;
+
+#ifdef CONFIG_SYS_I2C_UCODE_PATCH
+	/*
+	 *  Initialize required parameters if using microcode patch.
+	 */
+	iip->iic_rbptr  = iip->iic_rbase;
+	iip->iic_tbptr  = iip->iic_tbase;
+	iip->iic_rstate = 0;
+	iip->iic_tstate = 0;
+#else
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	do {
+		__asm__ __volatile__ ("eieio");
+	} while (cp->cp_cpcr & CPM_CR_FLG);
+#endif
+
+	/* Clear events and interrupts */
+	i2c->i2c_i2cer = 0xff;
+	i2c->i2c_i2cmr = 0x00;
+}
+
+static void
+i2c_newio(i2c_state_t *state)
+{
+	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR ;
+	volatile cpm8xx_t *cp = (cpm8xx_t *)&immap->im_cpm;
+	volatile iic_t *iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
+
+	PRINTD(("[I2C] i2c_newio\n"));
+
+#ifdef CONFIG_SYS_I2C_UCODE_PATCH
+	iip = (iic_t *)&cp->cp_dpmem[iip->iic_rpbase];
+#endif
+	state->rx_idx = 0;
+	state->tx_idx = 0;
+	state->rxbd = (void*)&cp->cp_dpmem[iip->iic_rbase];
+	state->txbd = (void*)&cp->cp_dpmem[iip->iic_tbase];
+	state->tx_space = MAX_TX_SPACE;
+	state->tx_buf = (uchar*)state->txbd + NUM_TX_BDS * sizeof(I2C_BD);
+	state->err_cb = NULL;
+
+	PRINTD(("[I2C] rxbd = %08x\n", (int)state->rxbd));
+	PRINTD(("[I2C] txbd = %08x\n", (int)state->txbd));
+	PRINTD(("[I2C] tx_buf = %08x\n", (int)state->tx_buf));
+
+	/* clear the buffer memory */
+	memset((char *)state->tx_buf, 0, MAX_TX_SPACE);
+}
+
+static int
+i2c_send(i2c_state_t *state,
+	 unsigned char address,
+	 unsigned char secondary_address,
+	 unsigned int flags,
+	 unsigned short size,
+	 unsigned char *dataout)
+{
+	volatile I2C_BD *txbd;
+	int i,j;
+
+	PRINTD(("[I2C] i2c_send add=%02d sec=%02d flag=%02d size=%d\n",
+			address, secondary_address, flags, size));
+
+	/* trying to send message larger than BD */
+	if (size > I2C_RXTX_LEN)
+	  return I2CERR_MSG_TOO_LONG;
+
+	/* no more free bds */
+	if (state->tx_idx >= NUM_TX_BDS || state->tx_space < (2 + size))
+	  return I2CERR_NO_BUFFERS;
+
+	txbd = (I2C_BD *)state->txbd;
+	txbd->addr = state->tx_buf;
+
+	PRINTD(("[I2C] txbd = %08x\n", (int)txbd));
+
+	if (flags & I2CF_START_COND) {
+		PRINTD(("[I2C] Formatting addresses...\n"));
+		if (flags & I2CF_ENABLE_SECONDARY) {
+			txbd->length = size + 2;  /* Length of msg + dest addr */
+			txbd->addr[0] = address << 1;
+			txbd->addr[1] = secondary_address;
+			i = 2;
+		} else {
+			txbd->length = size + 1;  /* Length of msg + dest addr */
+			txbd->addr[0] = address << 1;  /* Write dest addr to BD */
+			i = 1;
+		}
+	} else {
+		txbd->length = size;  /* Length of message */
+		i = 0;
+	}
+
+	/* set up txbd */
+	txbd->status = BD_SC_READY;
+	if (flags & I2CF_START_COND)
+	  txbd->status |= BD_I2C_TX_START;
+	if (flags & I2CF_STOP_COND)
+	  txbd->status |= BD_SC_LAST | BD_SC_WRAP;
+
+	/* Copy data to send into buffer */
+	PRINTD(("[I2C] copy data...\n"));
+	for(j = 0; j < size; i++, j++)
+	  txbd->addr[i] = dataout[j];
+
+	PRINTD(("[I2C] txbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+		   txbd->length,
+		   txbd->status,
+		   txbd->addr[0],
+		   txbd->addr[1]));
+
+	/* advance state */
+	state->tx_buf += txbd->length;
+	state->tx_space -= txbd->length;
+	state->tx_idx++;
+	state->txbd = (void*)(txbd + 1);
+
+	return 0;
+}
+
+static int
+i2c_receive(i2c_state_t *state,
+	    unsigned char address,
+	    unsigned char secondary_address,
+	    unsigned int flags,
+	    unsigned short size_to_expect,
+	    unsigned char *datain)
+{
+	volatile I2C_BD *rxbd, *txbd;
+
+	PRINTD(("[I2C] i2c_receive %02d %02d %02d\n", address, secondary_address, flags));
+
+	/* Expected to receive too much */
+	if (size_to_expect > I2C_RXTX_LEN)
+	  return I2CERR_MSG_TOO_LONG;
+
+	/* no more free bds */
+	if (state->tx_idx >= NUM_TX_BDS || state->rx_idx >= NUM_RX_BDS
+		 || state->tx_space < 2)
+	  return I2CERR_NO_BUFFERS;
+
+	rxbd = (I2C_BD *)state->rxbd;
+	txbd = (I2C_BD *)state->txbd;
+
+	PRINTD(("[I2C] rxbd = %08x\n", (int)rxbd));
+	PRINTD(("[I2C] txbd = %08x\n", (int)txbd));
+
+	txbd->addr = state->tx_buf;
+
+	/* set up TXBD for destination address */
+	if (flags & I2CF_ENABLE_SECONDARY) {
+		txbd->length = 2;
+		txbd->addr[0] = address << 1;   /* Write data */
+		txbd->addr[1] = secondary_address;  /* Internal address */
+		txbd->status = BD_SC_READY;
+	} else {
+		txbd->length = 1 + size_to_expect;
+		txbd->addr[0] = (address << 1) | 0x01;
+		txbd->status = BD_SC_READY;
+		memset(&txbd->addr[1], 0, txbd->length);
+	}
+
+	/* set up rxbd for reception */
+	rxbd->status = BD_SC_EMPTY;
+	rxbd->length = size_to_expect;
+	rxbd->addr = datain;
+
+	txbd->status |= BD_I2C_TX_START;
+	if (flags & I2CF_STOP_COND) {
+		txbd->status |= BD_SC_LAST | BD_SC_WRAP;
+		rxbd->status |= BD_SC_WRAP;
+	}
+
+	PRINTD(("[I2C] txbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+		   txbd->length,
+		   txbd->status,
+		   txbd->addr[0],
+		   txbd->addr[1]));
+	PRINTD(("[I2C] rxbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+		   rxbd->length,
+		   rxbd->status,
+		   rxbd->addr[0],
+		   rxbd->addr[1]));
+
+	/* advance state */
+	state->tx_buf += txbd->length;
+	state->tx_space -= txbd->length;
+	state->tx_idx++;
+	state->txbd = (void*)(txbd + 1);
+	state->rx_idx++;
+	state->rxbd = (void*)(rxbd + 1);
+
+	return 0;
+}
+
+
+static int i2c_doio(i2c_state_t *state)
+{
+	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR ;
+	volatile cpm8xx_t *cp = (cpm8xx_t *)&immap->im_cpm;
+	volatile i2c8xx_t *i2c	= (i2c8xx_t *)&immap->im_i2c;
+	volatile iic_t *iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
+	volatile I2C_BD *txbd, *rxbd;
+	volatile int j = 0;
+
+	PRINTD(("[I2C] i2c_doio\n"));
+
+#ifdef CONFIG_SYS_I2C_UCODE_PATCH
+	iip = (iic_t *)&cp->cp_dpmem[iip->iic_rpbase];
+#endif
+
+	if (state->tx_idx <= 0 && state->rx_idx <= 0) {
+		PRINTD(("[I2C] No I/O is queued\n"));
+		return I2CERR_QUEUE_EMPTY;
+	}
+
+	iip->iic_rbptr = iip->iic_rbase;
+	iip->iic_tbptr = iip->iic_tbase;
+
+	/* Enable I2C */
+	PRINTD(("[I2C] Enabling I2C...\n"));
+	i2c->i2c_i2mod |= 0x01;
+
+	/* Begin transmission */
+	i2c->i2c_i2com |= 0x80;
+
+	/* Loop until transmit & receive completed */
+
+	if (state->tx_idx > 0) {
+		txbd = ((I2C_BD*)state->txbd) - 1;
+		PRINTD(("[I2C] Transmitting...(txbd=0x%08lx)\n", (ulong)txbd));
+		while((txbd->status & BD_SC_READY) && (j++ < TOUT_LOOP)) {
+			if (ctrlc()) {
+				return (-1);
+			}
+			__asm__ __volatile__ ("eieio");
+		}
+	}
+
+	if ((state->rx_idx > 0) && (j < TOUT_LOOP)) {
+		rxbd = ((I2C_BD*)state->rxbd) - 1;
+		PRINTD(("[I2C] Receiving...(rxbd=0x%08lx)\n", (ulong)rxbd));
+		while((rxbd->status & BD_SC_EMPTY) && (j++ < TOUT_LOOP)) {
+			if (ctrlc()) {
+				return (-1);
+			}
+			__asm__ __volatile__ ("eieio");
+		}
+	}
+
+	/* Turn off I2C */
+	i2c->i2c_i2mod &= ~0x01;
+
+	if (state->err_cb != NULL) {
+		int n, i, b;
+
+		/*
+		 * if we have an error callback function, look at the
+		 * error bits in the bd status and pass them back
+		 */
+
+		if ((n = state->tx_idx) > 0) {
+			for (i = 0; i < n; i++) {
+				txbd = ((I2C_BD*)state->txbd) - (n - i);
+				if ((b = txbd->status & BD_I2C_TX_ERR) != 0)
+					(*state->err_cb)(I2CECB_TX_ERR|b, i);
+			}
+		}
+
+		if ((n = state->rx_idx) > 0) {
+			for (i = 0; i < n; i++) {
+				rxbd = ((I2C_BD*)state->rxbd) - (n - i);
+				if ((b = rxbd->status & BD_I2C_RX_ERR) != 0)
+					(*state->err_cb)(I2CECB_RX_ERR|b, i);
+			}
+		}
+
+		if (j >= TOUT_LOOP)
+			(*state->err_cb)(I2CECB_TIMEOUT, 0);
+	}
+
+	return (j >= TOUT_LOOP) ? I2CERR_TIMEOUT : 0;
+}
+
+static int had_tx_nak;
+
+static void
+i2c_test_callback(int flags, int xnum)
+{
+	if ((flags & I2CECB_TX_ERR) && (flags & I2CECB_TX_NAK))
+		had_tx_nak = 1;
+}
+
+int i2c_probe(uchar chip)
+{
+	i2c_state_t state;
+	int rc;
+	uchar buf[1];
+
+	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+	i2c_newio(&state);
+
+	state.err_cb = i2c_test_callback;
+	had_tx_nak = 0;
+
+	rc = i2c_receive(&state, chip, 0, I2CF_START_COND|I2CF_STOP_COND, 1, buf);
+
+	if (rc != 0)
+		return (rc);
+
+	rc = i2c_doio(&state);
+
+	if ((rc != 0) && (rc != I2CERR_TIMEOUT))
+		return (rc);
+
+	return (had_tx_nak);
+}
+
+int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	i2c_state_t state;
+	uchar xaddr[4];
+	int rc;
+
+#ifdef CONFIG_LWMON
+	WATCHDOG_RESET();
+#endif
+
+	xaddr[0] = (addr >> 24) & 0xFF;
+	xaddr[1] = (addr >> 16) & 0xFF;
+	xaddr[2] = (addr >>  8) & 0xFF;
+	xaddr[3] =  addr        & 0xFF;
+
+#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
+	/*
+	 * EEPROM chips that implement "address overflow" are ones like
+	 * Catalyst 24WC04/08/16 which has 9/10/11 bits of address and the
+	 * extra bits end up in the "chip address" bit slots.  This makes
+	 * a 24WC08 (1Kbyte) chip look like four 256 byte chips.
+	 *
+	 * Note that we consider the length of the address field to still
+	 * be one byte because the extra address bits are hidden in the
+	 * chip address.
+	 */
+	 chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
+#endif
+
+	i2c_newio(&state);
+
+	rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen, &xaddr[4-alen]);
+	if (rc != 0) {
+		if (gd->have_console)
+			printf("i2c_read: i2c_send failed (%d)\n", rc);
+		return 1;
+	}
+
+	rc = i2c_receive(&state, chip, 0, I2CF_STOP_COND, len, buffer);
+	if (rc != 0) {
+		if (gd->have_console)
+			printf("i2c_read: i2c_receive failed (%d)\n", rc);
+		return 1;
+	}
+
+	rc = i2c_doio(&state);
+	if (rc != 0) {
+		if (gd->have_console)
+			printf("i2c_read: i2c_doio failed (%d)\n", rc);
+		return 1;
+	}
+	return 0;
+}
+
+int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	i2c_state_t state;
+	uchar xaddr[4];
+	int rc;
+
+	xaddr[0] = (addr >> 24) & 0xFF;
+	xaddr[1] = (addr >> 16) & 0xFF;
+	xaddr[2] = (addr >>  8) & 0xFF;
+	xaddr[3] =  addr        & 0xFF;
+
+#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
+	/*
+	 * EEPROM chips that implement "address overflow" are ones like
+	 * Catalyst 24WC04/08/16 which has 9/10/11 bits of address and the
+	 * extra bits end up in the "chip address" bit slots.  This makes
+	 * a 24WC08 (1Kbyte) chip look like four 256 byte chips.
+	 *
+	 * Note that we consider the length of the address field to still
+	 * be one byte because the extra address bits are hidden in the
+	 * chip address.
+	 */
+	 chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
+#endif
+
+	i2c_newio(&state);
+
+	rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen, &xaddr[4-alen]);
+	if (rc != 0) {
+		if (gd->have_console)
+			printf("i2c_write: first i2c_send failed (%d)\n", rc);
+		return 1;
+	}
+
+	rc = i2c_send(&state, 0, 0, I2CF_STOP_COND, len, buffer);
+	if (rc != 0) {
+		if (gd->have_console)
+			printf("i2c_write: second i2c_send failed (%d)\n", rc);
+		return 1;
+	}
+
+	rc = i2c_doio(&state);
+	if (rc != 0) {
+		if (gd->have_console)
+			printf("i2c_write: i2c_doio failed (%d)\n", rc);
+		return 1;
+	}
+	return 0;
+}
+
+#endif	/* CONFIG_HARD_I2C */
diff --git a/arch/powerpc/cpu/mpc8xx/interrupts.c b/arch/powerpc/cpu/mpc8xx/interrupts.c
new file mode 100644
index 0000000..5daa6b2
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/interrupts.c
@@ -0,0 +1,294 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <mpc8xx_irq.h>
+#include <asm/processor.h>
+#include <commproc.h>
+
+/************************************************************************/
+
+/*
+ * CPM interrupt vector functions.
+ */
+struct interrupt_action {
+	interrupt_handler_t *handler;
+	void *arg;
+};
+
+static struct interrupt_action cpm_vecs[CPMVEC_NR];
+static struct interrupt_action irq_vecs[NR_IRQS];
+
+static void cpm_interrupt_init (void);
+static void cpm_interrupt (void *regs);
+
+/************************************************************************/
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+	*decrementer_count = get_tbclk () / CONFIG_SYS_HZ;
+
+	/* disable all interrupts */
+	immr->im_siu_conf.sc_simask = 0;
+
+	/* Configure CPM interrupts */
+	cpm_interrupt_init ();
+
+	return (0);
+}
+
+/************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt (struct pt_regs *regs)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	int irq;
+	ulong simask, newmask;
+	ulong vec, v_bit;
+
+	/*
+	 * read the SIVEC register and shift the bits down
+	 * to get the irq number
+	 */
+	vec = immr->im_siu_conf.sc_sivec;
+	irq = vec >> 26;
+	v_bit = 0x80000000UL >> irq;
+
+	/*
+	 * Read Interrupt Mask Register and Mask Interrupts
+	 */
+	simask = immr->im_siu_conf.sc_simask;
+	newmask = simask & (~(0xFFFF0000 >> irq));
+	immr->im_siu_conf.sc_simask = newmask;
+
+	if (!(irq & 0x1)) {		/* External Interrupt ?     */
+		ulong siel;
+
+		/*
+		 * Read Interrupt Edge/Level Register
+		 */
+		siel = immr->im_siu_conf.sc_siel;
+
+		if (siel & v_bit) {	/* edge triggered interrupt ?   */
+			/*
+			 * Rewrite SIPEND Register to clear interrupt
+			 */
+			immr->im_siu_conf.sc_sipend = v_bit;
+		}
+	}
+
+	if (irq_vecs[irq].handler != NULL) {
+		irq_vecs[irq].handler (irq_vecs[irq].arg);
+	} else {
+		printf ("\nBogus External Interrupt IRQ %d Vector %ld\n",
+				irq, vec);
+		/* turn off the bogus interrupt to avoid it from now */
+		simask &= ~v_bit;
+	}
+	/*
+	 * Re-Enable old Interrupt Mask
+	 */
+	immr->im_siu_conf.sc_simask = simask;
+}
+
+/************************************************************************/
+
+/*
+ * CPM interrupt handler
+ */
+static void cpm_interrupt (void *regs)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	uint vec;
+
+	/*
+	 * Get the vector by setting the ACK bit
+	 * and then reading the register.
+	 */
+	immr->im_cpic.cpic_civr = 1;
+	vec = immr->im_cpic.cpic_civr;
+	vec >>= 11;
+
+	if (cpm_vecs[vec].handler != NULL) {
+		(*cpm_vecs[vec].handler) (cpm_vecs[vec].arg);
+	} else {
+		immr->im_cpic.cpic_cimr &= ~(1 << vec);
+		printf ("Masking bogus CPM interrupt vector 0x%x\n", vec);
+	}
+	/*
+	 * After servicing the interrupt,
+	 * we have to remove the status indicator.
+	 */
+	immr->im_cpic.cpic_cisr |= (1 << vec);
+}
+
+/*
+ * The CPM can generate the error interrupt when there is a race
+ * condition between generating and masking interrupts. All we have
+ * to do is ACK it and return. This is a no-op function so we don't
+ * need any special tests in the interrupt handler.
+ */
+static void cpm_error_interrupt (void *dummy)
+{
+}
+
+/************************************************************************/
+/*
+ * Install and free an interrupt handler
+ */
+void irq_install_handler (int vec, interrupt_handler_t * handler,
+						  void *arg)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+	if ((vec & CPMVEC_OFFSET) != 0) {
+		/* CPM interrupt */
+		vec &= 0xffff;
+		if (cpm_vecs[vec].handler != NULL) {
+			printf ("CPM interrupt 0x%x replacing 0x%x\n",
+				(uint) handler,
+				(uint) cpm_vecs[vec].handler);
+		}
+		cpm_vecs[vec].handler = handler;
+		cpm_vecs[vec].arg = arg;
+		immr->im_cpic.cpic_cimr |= (1 << vec);
+#if 0
+		printf ("Install CPM interrupt for vector %d ==> %p\n",
+			vec, handler);
+#endif
+	} else {
+		/* SIU interrupt */
+		if (irq_vecs[vec].handler != NULL) {
+			printf ("SIU interrupt %d 0x%x replacing 0x%x\n",
+				vec,
+				(uint) handler,
+				(uint) cpm_vecs[vec].handler);
+		}
+		irq_vecs[vec].handler = handler;
+		irq_vecs[vec].arg = arg;
+		immr->im_siu_conf.sc_simask |= 1 << (31 - vec);
+#if 0
+		printf ("Install SIU interrupt for vector %d ==> %p\n",
+			vec, handler);
+#endif
+	}
+}
+
+void irq_free_handler (int vec)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+	if ((vec & CPMVEC_OFFSET) != 0) {
+		/* CPM interrupt */
+		vec &= 0xffff;
+#if 0
+		printf ("Free CPM interrupt for vector %d ==> %p\n",
+			vec, cpm_vecs[vec].handler);
+#endif
+		immr->im_cpic.cpic_cimr &= ~(1 << vec);
+		cpm_vecs[vec].handler = NULL;
+		cpm_vecs[vec].arg = NULL;
+	} else {
+		/* SIU interrupt */
+#if 0
+		printf ("Free CPM interrupt for vector %d ==> %p\n",
+			vec, cpm_vecs[vec].handler);
+#endif
+		immr->im_siu_conf.sc_simask &= ~(1 << (31 - vec));
+		irq_vecs[vec].handler = NULL;
+		irq_vecs[vec].arg = NULL;
+	}
+}
+
+/************************************************************************/
+
+static void cpm_interrupt_init (void)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+	/*
+	 * Initialize the CPM interrupt controller.
+	 */
+
+	immr->im_cpic.cpic_cicr =
+		(CICR_SCD_SCC4 |
+		 CICR_SCC_SCC3 |
+		 CICR_SCB_SCC2 |
+		 CICR_SCA_SCC1) | ((CPM_INTERRUPT / 2) << 13) | CICR_HP_MASK;
+
+	immr->im_cpic.cpic_cimr = 0;
+
+	/*
+	 * Install the error handler.
+	 */
+	irq_install_handler (CPMVEC_ERROR, cpm_error_interrupt, NULL);
+
+	immr->im_cpic.cpic_cicr |= CICR_IEN;
+
+	/*
+	 * Install the cpm interrupt handler
+	 */
+	irq_install_handler (CPM_INTERRUPT, cpm_interrupt, NULL);
+}
+
+/************************************************************************/
+
+/*
+ * timer_interrupt - gets called when the decrementer overflows,
+ * with interrupts disabled.
+ * Trivial implementation - no need to be really accurate.
+ */
+void timer_interrupt_cpu (struct pt_regs *regs)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+#if 0
+	printf ("*** Timer Interrupt *** ");
+#endif
+	/* Reset Timer Expired and Timers Interrupt Status */
+	immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
+	__asm__ ("nop");
+	/*
+	  Clear TEXPS (and TMIST on older chips). SPLSS (on older
+	  chips) is cleared too.
+
+	  Bitwise OR is a read-modify-write operation so ALL bits
+	  which are cleared by writing `1' would be cleared by
+	  operations like
+
+	  immr->im_clkrst.car_plprcr |= PLPRCR_TEXPS;
+
+	  The same can be achieved by simple writing of the PLPRCR
+	  to itself. If a bit value should be preserved, read the
+	  register, ZERO the bit and write, not OR, the result back.
+	*/
+	immr->im_clkrst.car_plprcr = immr->im_clkrst.car_plprcr;
+}
+
+/************************************************************************/
diff --git a/arch/powerpc/cpu/mpc8xx/kgdb.S b/arch/powerpc/cpu/mpc8xx/kgdb.S
new file mode 100644
index 0000000..2cc8fe6
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/kgdb.S
@@ -0,0 +1,74 @@
+/*
+ *  Copyright (C) 2000	Murray Jensen <Murray.Jensen@cmst.csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <command.h>
+#include <mpc8xx.h>
+#include <version.h>
+
+#define CONFIG_8xx 1		/* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1	/* avoid reading Linux autoconf.h file	*/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#if defined(CONFIG_CMD_KGDB)
+
+ /*
+ * cache flushing routines for kgdb
+ */
+
+	.globl	kgdb_flush_cache_all
+kgdb_flush_cache_all:
+	lis	r3, IDC_INVALL@h
+	mtspr	DC_CST, r3
+	sync
+	lis	r3, IDC_INVALL@h
+	mtspr	IC_CST, r3
+	SYNC
+	blr
+
+	.globl	kgdb_flush_cache_range
+kgdb_flush_cache_range:
+	li	r5,CONFIG_SYS_CACHELINE_SIZE-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,CONFIG_SYS_CACHELINE_SHIFT
+	beqlr
+	mtctr	r4
+	mr	r6,r3
+1:	dcbst	0,r3
+	addi	r3,r3,CONFIG_SYS_CACHELINE_SIZE
+	bdnz	1b
+	sync				/* wait for dcbst's to get to ram */
+	mtctr	r4
+2:	icbi	0,r6
+	addi	r6,r6,CONFIG_SYS_CACHELINE_SIZE
+	bdnz	2b
+	SYNC
+	blr
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8xx/lcd.c b/arch/powerpc/cpu/mpc8xx/lcd.c
new file mode 100644
index 0000000..4b88b21
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/lcd.c
@@ -0,0 +1,621 @@
+/*
+ * (C) Copyright 2001-2002
+ * Wolfgang Denk, DENX Software Engineering -- wd@denx.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/************************************************************************/
+/* ** HEADER FILES							*/
+/************************************************************************/
+
+/* #define DEBUG */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+#include <watchdog.h>
+#include <version.h>
+#include <stdarg.h>
+#include <lcdvideo.h>
+#include <linux/types.h>
+#include <stdio_dev.h>
+#if defined(CONFIG_POST)
+#include <post.h>
+#endif
+#include <lcd.h>
+
+#ifdef CONFIG_LCD
+
+/************************************************************************/
+/* ** CONFIG STUFF -- should be moved to board config file		*/
+/************************************************************************/
+#ifndef CONFIG_LCD_INFO
+#define CONFIG_LCD_INFO		/* Display Logo, (C) and system info	*/
+#endif
+
+#if defined(CONFIG_V37) || defined(CONFIG_EDT32F10)
+#undef CONFIG_LCD_LOGO
+#undef CONFIG_LCD_INFO
+#endif
+
+/*----------------------------------------------------------------------*/
+#ifdef CONFIG_KYOCERA_KCS057QV1AJ
+/*
+ *  Kyocera KCS057QV1AJ-G23. Passive, color, single scan.
+ */
+#define LCD_BPP	LCD_COLOR4
+
+vidinfo_t panel_info = {
+    640, 480, 132, 99, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH,
+    LCD_BPP, 1, 0, 1, 0,  5, 0, 0, 0
+		/* wbl, vpw, lcdac, wbf */
+};
+#endif /* CONFIG_KYOCERA_KCS057QV1AJ */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+#ifdef CONFIG_HITACHI_SP19X001_Z1A
+/*
+ *  Hitachi SP19X001-. Active, color, single scan.
+ */
+vidinfo_t panel_info = {
+    640, 480, 154, 116, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH,
+    LCD_COLOR8, 1, 0, 1, 0, 0, 0, 0, 0
+		/* wbl, vpw, lcdac, wbf */
+};
+#endif /* CONFIG_HITACHI_SP19X001_Z1A */
+/*----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+#ifdef CONFIG_NEC_NL6448AC33
+/*
+ *  NEC NL6448AC33-18. Active, color, single scan.
+ */
+vidinfo_t panel_info = {
+    640, 480, 132, 99, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_HIGH,
+    3, 0, 0, 1, 1, 144, 2, 0, 33
+		/* wbl, vpw, lcdac, wbf */
+};
+#endif /* CONFIG_NEC_NL6448AC33 */
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_NEC_NL6448BC20
+/*
+ *  NEC NL6448BC20-08.  6.5", 640x480. Active, color, single scan.
+ */
+vidinfo_t panel_info = {
+    640, 480, 132, 99, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_HIGH,
+    3, 0, 0, 1, 1, 144, 2, 0, 33
+		/* wbl, vpw, lcdac, wbf */
+};
+#endif /* CONFIG_NEC_NL6448BC20 */
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_NEC_NL6448BC33_54
+/*
+ *  NEC NL6448BC33-54. 10.4", 640x480. Active, color, single scan.
+ */
+vidinfo_t panel_info = {
+    640, 480, 212, 158, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_HIGH,
+    3, 0, 0, 1, 1, 144, 2, 0, 33
+		/* wbl, vpw, lcdac, wbf */
+};
+#endif /* CONFIG_NEC_NL6448BC33_54 */
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_SHARP_LQ104V7DS01
+/*
+ *  SHARP LQ104V7DS01. 6.5", 640x480. Active, color, single scan.
+ */
+vidinfo_t panel_info = {
+    640, 480, 132, 99, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_LOW,
+    3, 0, 0, 1, 1, 25, 1, 0, 33
+		/* wbl, vpw, lcdac, wbf */
+};
+#endif /* CONFIG_SHARP_LQ104V7DS01 */
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_SHARP_16x9
+/*
+ * Sharp 320x240. Active, color, single scan.  It isn't 16x9, and I am
+ * not sure what it is.......
+ */
+vidinfo_t panel_info = {
+    320, 240, 0, 0, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH,
+    3, 0, 0, 1, 1, 15, 4, 0, 3
+};
+#endif /* CONFIG_SHARP_16x9 */
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_SHARP_LQ057Q3DC02
+/*
+ * Sharp LQ057Q3DC02 display. Active, color, single scan.
+ */
+#undef LCD_DF
+#define LCD_DF 12
+
+vidinfo_t panel_info = {
+    320, 240, 0, 0, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_HIGH,
+    3, 0, 0, 1, 1, 15, 4, 0, 3
+		/* wbl, vpw, lcdac, wbf */
+};
+#define CONFIG_LCD_INFO_BELOW_LOGO
+#endif /* CONFIG_SHARP_LQ057Q3DC02 */
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_SHARP_LQ64D341
+/*
+ * Sharp LQ64D341 display, 640x480. Active, color, single scan.
+ */
+vidinfo_t panel_info = {
+    640, 480, 0, 0, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_HIGH,
+    3, 0, 0, 1, 1, 128, 16, 0, 32
+		/* wbl, vpw, lcdac, wbf */
+};
+#endif /* CONFIG_SHARP_LQ64D341 */
+
+#ifdef CONFIG_SHARP_LQ065T9DR51U
+/*
+ * Sharp LQ065T9DR51U display, 400x240. Active, color, single scan.
+ */
+vidinfo_t panel_info = {
+    400, 240, 143, 79, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH,
+    3, 0, 0, 1, 1, 248, 4, 0, 35
+		/* wbl, vpw, lcdac, wbf */
+};
+#define CONFIG_LCD_INFO_BELOW_LOGO
+#endif /* CONFIG_SHARP_LQ065T9DR51U */
+
+#ifdef CONFIG_SHARP_LQ084V1DG21
+/*
+ * Sharp LQ084V1DG21 display, 640x480. Active, color, single scan.
+ */
+vidinfo_t panel_info = {
+    640, 480, 171, 129, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_LOW,
+    3, 0, 0, 1, 1, 160, 3, 0, 48
+		/* wbl, vpw, lcdac, wbf */
+};
+#endif /* CONFIG_SHARP_LQ084V1DG21 */
+
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_HLD1045
+/*
+ * HLD1045 display, 640x480. Active, color, single scan.
+ */
+vidinfo_t panel_info = {
+    640, 480, 0, 0, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_HIGH,
+    3, 0, 0, 1, 1, 160, 3, 0, 48
+		/* wbl, vpw, lcdac, wbf */
+};
+#endif /* CONFIG_HLD1045 */
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_PRIMEVIEW_V16C6448AC
+/*
+ * Prime View V16C6448AC
+ */
+vidinfo_t panel_info = {
+    640, 480, 130, 98, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_HIGH,
+    3, 0, 0, 1, 1, 144, 2, 0, 35
+		/* wbl, vpw, lcdac, wbf */
+};
+#endif /* CONFIG_PRIMEVIEW_V16C6448AC */
+
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_OPTREX_BW
+/*
+ * Optrex   CBL50840-2 NF-FW 99 22 M5
+ * or
+ * Hitachi  LMG6912RPFC-00T
+ * or
+ * Hitachi  SP14Q002
+ *
+ * 320x240. Black & white.
+ */
+#define OPTREX_BPP	0	/* 0 - monochrome,     1 bpp */
+				/* 1 -  4 grey levels, 2 bpp */
+				/* 2 - 16 grey levels, 4 bpp */
+vidinfo_t panel_info = {
+    320, 240, 0, 0, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW,
+    OPTREX_BPP, 0, 0, 0, 0, 0, 0, 0, 0, 4
+};
+#endif /* CONFIG_OPTREX_BW */
+
+/*-----------------------------------------------------------------*/
+#ifdef CONFIG_EDT32F10
+/*
+ * Emerging Display Technologies 320x240. Passive, monochrome, single scan.
+ */
+#define LCD_BPP		LCD_MONOCHROME
+#define LCD_DF		10
+
+vidinfo_t panel_info = {
+    320, 240, 0, 0, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW,
+    LCD_BPP,  0, 0, 0, 0, 33, 0, 0, 0
+};
+#endif
+/*----------------------------------------------------------------------*/
+
+
+int lcd_line_length;
+
+int lcd_color_fg;
+int lcd_color_bg;
+
+/*
+ * Frame buffer memory information
+ */
+void *lcd_base;			/* Start of framebuffer memory	*/
+void *lcd_console_address;	/* Start of console buffer	*/
+
+short console_col;
+short console_row;
+
+/************************************************************************/
+
+void lcd_ctrl_init (void *lcdbase);
+void lcd_enable (void);
+#if LCD_BPP == LCD_COLOR8
+void lcd_setcolreg (ushort regno,
+				ushort red, ushort green, ushort blue);
+#endif
+#if LCD_BPP == LCD_MONOCHROME
+void lcd_initcolregs (void);
+#endif
+
+#if defined(CONFIG_RBC823)
+void lcd_disable (void);
+#endif
+
+/************************************************************************/
+
+/************************************************************************/
+/* ----------------- chipset specific functions ----------------------- */
+/************************************************************************/
+
+/*
+ * Calculate fb size for VIDEOLFB_ATAG.
+ */
+ulong calc_fbsize (void)
+{
+	ulong size;
+	int line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;
+
+	size = line_length * panel_info.vl_row;
+
+	return size;
+}
+
+void lcd_ctrl_init (void *lcdbase)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	volatile lcd823_t *lcdp = &immr->im_lcd;
+
+	uint lccrtmp;
+	uint lchcr_hpc_tmp;
+
+	/* Initialize the LCD control register according to the LCD
+	 * parameters defined.  We do everything here but enable
+	 * the controller.
+	 */
+
+#ifdef CONFIG_RPXLITE
+	/* This is special for RPXlite_DW Software Development Platform **[Sam]** */
+	panel_info.vl_dp = CONFIG_SYS_LOW;
+#endif
+
+	lccrtmp  = LCDBIT (LCCR_BNUM_BIT,
+		   (((panel_info.vl_row * panel_info.vl_col) * (1 << LCD_BPP)) / 128));
+
+	lccrtmp |= LCDBIT (LCCR_CLKP_BIT, panel_info.vl_clkp)	|
+		   LCDBIT (LCCR_OEP_BIT,  panel_info.vl_oep)	|
+		   LCDBIT (LCCR_HSP_BIT,  panel_info.vl_hsp)	|
+		   LCDBIT (LCCR_VSP_BIT,  panel_info.vl_vsp)	|
+		   LCDBIT (LCCR_DP_BIT,   panel_info.vl_dp)	|
+		   LCDBIT (LCCR_BPIX_BIT, panel_info.vl_bpix)	|
+		   LCDBIT (LCCR_LBW_BIT,  panel_info.vl_lbw)	|
+		   LCDBIT (LCCR_SPLT_BIT, panel_info.vl_splt)	|
+		   LCDBIT (LCCR_CLOR_BIT, panel_info.vl_clor)	|
+		   LCDBIT (LCCR_TFT_BIT,  panel_info.vl_tft);
+
+#if 0
+	lccrtmp |= ((SIU_LEVEL5 / 2) << 12);
+	lccrtmp |= LCCR_EIEN;
+#endif
+
+	lcdp->lcd_lccr = lccrtmp;
+	lcdp->lcd_lcsr = 0xFF;		/* Clear pending interrupts */
+
+	/* Initialize LCD controller bus priorities.
+	 */
+#ifdef CONFIG_RBC823
+	immr->im_siu_conf.sc_sdcr = (immr->im_siu_conf.sc_sdcr & ~0x0f) | 1;	/* RAID = 01, LAID = 00 */
+#else
+	immr->im_siu_conf.sc_sdcr &= ~0x0f;	/* RAID = LAID = 0 */
+
+	/* set SHFT/CLOCK division factor 4
+	 * This needs to be set based upon display type and processor
+	 * speed.  The TFT displays run about 20 to 30 MHz.
+	 * I was running 64 MHz processor speed.
+	 * The value for this divider must be chosen so the result is
+	 * an integer of the processor speed (i.e., divide by 3 with
+	 * 64 MHz would be bad).
+	 */
+	immr->im_clkrst.car_sccr &= ~0x1F;
+	immr->im_clkrst.car_sccr |= LCD_DF;	/* was 8 */
+
+#endif /* CONFIG_RBC823 */
+
+#if defined(CONFIG_RBC823)
+	/* Enable LCD on port D.
+	 */
+	immr->im_ioport.iop_pddat &= 0x0300;
+	immr->im_ioport.iop_pdpar |= 0x1CFF;
+	immr->im_ioport.iop_pddir |= 0x1CFF;
+
+	/* Configure LCD_ON, VEE_ON, CCFL_ON on port B.
+	 */
+	immr->im_cpm.cp_pbdat &= ~0x00005001;
+	immr->im_cpm.cp_pbpar &= ~0x00005001;
+	immr->im_cpm.cp_pbdir |=  0x00005001;
+#elif !defined(CONFIG_EDT32F10)
+	/* Enable LCD on port D.
+	 */
+	immr->im_ioport.iop_pdpar |= 0x1FFF;
+	immr->im_ioport.iop_pddir |= 0x1FFF;
+
+	/* Enable LCD_A/B/C on port B.
+	 */
+	immr->im_cpm.cp_pbpar |= 0x00005001;
+	immr->im_cpm.cp_pbdir |= 0x00005001;
+#else
+	/* Enable LCD on port D.
+	 */
+	immr->im_ioport.iop_pdpar |= 0x1DFF;
+	immr->im_ioport.iop_pdpar &= ~0x0200;
+	immr->im_ioport.iop_pddir |= 0x1FFF;
+	immr->im_ioport.iop_pddat |= 0x0200;
+#endif
+
+	/* Load the physical address of the linear frame buffer
+	 * into the LCD controller.
+	 * BIG NOTE:  This has to be modified to load A and B depending
+	 * upon the split mode of the LCD.
+	 */
+	lcdp->lcd_lcfaa = (ulong)lcd_base;
+	lcdp->lcd_lcfba = (ulong)lcd_base;
+
+	/* MORE HACKS...This must be updated according to 823 manual
+	 * for different panels.
+	 * Udi Finkelstein - done - see below:
+	 * Note: You better not try unsupported combinations such as
+	 * 4-bit wide passive dual scan LCD at 4/8 Bit color.
+	 */
+	lchcr_hpc_tmp =
+		(panel_info.vl_col *
+		 (panel_info.vl_tft ? 8 :
+			(((2 - panel_info.vl_lbw) << /* 4 bit=2, 8-bit = 1 */
+			 /* use << to mult by: single scan = 1, dual scan = 2 */
+			  panel_info.vl_splt) *
+			 (panel_info.vl_bpix | 1)))) >> 3; /* 2/4 BPP = 1, 8/16 BPP = 3 */
+
+	lcdp->lcd_lchcr = LCHCR_BO |
+			  LCDBIT (LCHCR_AT_BIT, 4) |
+			  LCDBIT (LCHCR_HPC_BIT, lchcr_hpc_tmp) |
+			  panel_info.vl_wbl;
+
+	lcdp->lcd_lcvcr = LCDBIT (LCVCR_VPW_BIT, panel_info.vl_vpw) |
+			  LCDBIT (LCVCR_LCD_AC_BIT, panel_info.vl_lcdac) |
+			  LCDBIT (LCVCR_VPC_BIT, panel_info.vl_row) |
+			  panel_info.vl_wbf;
+
+}
+
+/*----------------------------------------------------------------------*/
+
+#ifdef	NOT_USED_SO_FAR
+static void
+lcd_getcolreg (ushort regno, ushort *red, ushort *green, ushort *blue)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	volatile cpm8xx_t *cp = &(immr->im_cpm);
+	unsigned short colreg, *cmap_ptr;
+
+	cmap_ptr = (unsigned short *)&cp->lcd_cmap[regno * 2];
+
+	colreg = *cmap_ptr;
+#ifdef	CONFIG_SYS_INVERT_COLORS
+	colreg ^= 0x0FFF;
+#endif
+
+	*red   = (colreg >> 8) & 0x0F;
+	*green = (colreg >> 4) & 0x0F;
+	*blue  =  colreg       & 0x0F;
+}
+#endif	/* NOT_USED_SO_FAR */
+
+/*----------------------------------------------------------------------*/
+
+#if LCD_BPP == LCD_COLOR8
+void
+lcd_setcolreg (ushort regno, ushort red, ushort green, ushort blue)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	volatile cpm8xx_t *cp = &(immr->im_cpm);
+	unsigned short colreg, *cmap_ptr;
+
+	cmap_ptr = (unsigned short *)&cp->lcd_cmap[regno * 2];
+
+	colreg = ((red   & 0x0F) << 8) |
+		 ((green & 0x0F) << 4) |
+		  (blue  & 0x0F) ;
+#ifdef	CONFIG_SYS_INVERT_COLORS
+	colreg ^= 0x0FFF;
+#endif
+	*cmap_ptr = colreg;
+
+	debug ("setcolreg: reg %2d @ %p: R=%02X G=%02X B=%02X => %02X%02X\n",
+		regno, &(cp->lcd_cmap[regno * 2]),
+		red, green, blue,
+		cp->lcd_cmap[ regno * 2 ], cp->lcd_cmap[(regno * 2) + 1]);
+}
+#endif	/* LCD_COLOR8 */
+
+/*----------------------------------------------------------------------*/
+
+#if LCD_BPP == LCD_MONOCHROME
+static
+void lcd_initcolregs (void)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	volatile cpm8xx_t *cp = &(immr->im_cpm);
+	ushort regno;
+
+	for (regno = 0; regno < 16; regno++) {
+		cp->lcd_cmap[regno * 2] = 0;
+		cp->lcd_cmap[(regno * 2) + 1] = regno & 0x0f;
+	}
+}
+#endif
+
+/*----------------------------------------------------------------------*/
+
+void lcd_enable (void)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	volatile lcd823_t *lcdp = &immr->im_lcd;
+
+	/* Enable the LCD panel */
+#ifndef CONFIG_RBC823
+	immr->im_siu_conf.sc_sdcr |= (1 << (31 - 25));		/* LAM = 1 */
+#endif
+	lcdp->lcd_lccr |= LCCR_PON;
+
+#ifdef CONFIG_V37
+	/* Turn on display backlight */
+	immr->im_cpm.cp_pbpar |= 0x00008000;
+	immr->im_cpm.cp_pbdir |= 0x00008000;
+#elif defined(CONFIG_RBC823)
+	/* Turn on display backlight */
+	immr->im_cpm.cp_pbdat |= 0x00004000;
+#endif
+
+#if defined(CONFIG_LWMON)
+    {	uchar c = pic_read (0x60);
+#if defined(CONFIG_LCD) && defined(CONFIG_LWMON) && (CONFIG_POST & CONFIG_SYS_POST_SYSMON)
+	/* Enable LCD later in sysmon test, only if temperature is OK */
+#else
+	c |= 0x07;	/* Power on CCFL, Enable CCFL, Chip Enable LCD */
+#endif
+	pic_write (0x60, c);
+    }
+#endif /* CONFIG_LWMON */
+
+#if defined(CONFIG_R360MPI)
+    {
+	extern void r360_i2c_lcd_write (uchar data0, uchar data1);
+	unsigned long bgi, ctr;
+	char *p;
+
+	if ((p = getenv("lcdbgi")) != NULL) {
+		bgi = simple_strtoul (p, 0, 10) & 0xFFF;
+	} else {
+		bgi = 0xFFF;
+	}
+
+	if ((p = getenv("lcdctr")) != NULL) {
+		ctr = simple_strtoul (p, 0, 10) & 0xFFF;
+	} else {
+		ctr=0x7FF;
+	}
+
+	r360_i2c_lcd_write(0x10, 0x01);
+	r360_i2c_lcd_write(0x20, 0x01);
+	r360_i2c_lcd_write(0x30 | ((bgi>>8) & 0xF), bgi & 0xFF);
+	r360_i2c_lcd_write(0x40 | ((ctr>>8) & 0xF), ctr & 0xFF);
+    }
+#endif /* CONFIG_R360MPI */
+#ifdef CONFIG_RBC823
+	udelay(200000); /* wait 200ms */
+	/* Turn VEE_ON first */
+	immr->im_cpm.cp_pbdat |= 0x00000001;
+	udelay(200000); /* wait 200ms */
+	/* Now turn on LCD_ON */
+	immr->im_cpm.cp_pbdat |= 0x00001000;
+#endif
+#ifdef CONFIG_RRVISION
+	debug ("PC4->Output(1): enable LVDS\n");
+	debug ("PC5->Output(0): disable PAL clock\n");
+	immr->im_ioport.iop_pddir |=  0x1000;
+	immr->im_ioport.iop_pcpar &= ~(0x0C00);
+	immr->im_ioport.iop_pcdir |=   0x0C00 ;
+	immr->im_ioport.iop_pcdat |=   0x0800 ;
+	immr->im_ioport.iop_pcdat &= ~(0x0400);
+	debug ("PDPAR=0x%04X PDDIR=0x%04X PDDAT=0x%04X\n",
+	       immr->im_ioport.iop_pdpar,
+	       immr->im_ioport.iop_pddir,
+	       immr->im_ioport.iop_pddat);
+	debug ("PCPAR=0x%04X PCDIR=0x%04X PCDAT=0x%04X\n",
+	       immr->im_ioport.iop_pcpar,
+	       immr->im_ioport.iop_pcdir,
+	       immr->im_ioport.iop_pcdat);
+#endif
+}
+
+/*----------------------------------------------------------------------*/
+
+#if defined (CONFIG_RBC823)
+void lcd_disable (void)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	volatile lcd823_t *lcdp = &immr->im_lcd;
+
+#if defined(CONFIG_LWMON)
+    {	uchar c = pic_read (0x60);
+	c &= ~0x07;	/* Power off CCFL, Disable CCFL, Chip Disable LCD */
+	pic_write (0x60, c);
+    }
+#elif defined(CONFIG_R360MPI)
+    {
+	extern void r360_i2c_lcd_write (uchar data0, uchar data1);
+
+	r360_i2c_lcd_write(0x10, 0x00);
+	r360_i2c_lcd_write(0x20, 0x00);
+	r360_i2c_lcd_write(0x30, 0x00);
+	r360_i2c_lcd_write(0x40, 0x00);
+    }
+#endif /* CONFIG_LWMON */
+	/* Disable the LCD panel */
+	lcdp->lcd_lccr &= ~LCCR_PON;
+#ifdef CONFIG_RBC823
+	/* Turn off display backlight, VEE and LCD_ON */
+	immr->im_cpm.cp_pbdat &= ~0x00005001;
+#else
+	immr->im_siu_conf.sc_sdcr &= ~(1 << (31 - 25));	/* LAM = 0 */
+#endif /* CONFIG_RBC823 */
+}
+#endif	/* NOT_USED_SO_FAR || CONFIG_RBC823 */
+
+
+/************************************************************************/
+
+#endif /* CONFIG_LCD */
diff --git a/arch/powerpc/cpu/mpc8xx/plprcr_write.S b/arch/powerpc/cpu/mpc8xx/plprcr_write.S
new file mode 100644
index 0000000..e325671
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/plprcr_write.S
@@ -0,0 +1,135 @@
+/*
+ * (C) Copyright 2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <mpc8xx.h>
+#include <ppc_asm.tmpl>
+#include <asm/cache.h>
+
+#define CACHE_CMD_ENABLE	0x02000000
+#define CACHE_CMD_DISABLE	0x04000000
+#define CACHE_CMD_LOAD_LOCK	0x06000000
+#define CACHE_CMD_UNLOCK_LINE	0x08000000
+#define CACHE_CMD_UNLOCK_ALL	0x0A000000
+#define CACHE_CMD_INVALIDATE	0x0C000000
+#define SPEED_PLPRCR_WAIT_5CYC	150
+#define _CACHE_ALIGN_SIZE	16
+
+
+	.text
+	.align 2
+	.globl plprcr_write_866
+
+/*
+ * void plprcr_write_866 (long plprcr)
+ * Write PLPRCR, including workaround for device errata SIU4 and SIU9.
+ */
+
+plprcr_write_866:
+	mfspr	r10, LR		/* save the Link Register value */
+
+	/* turn instruction cache on (no MMU required for instructions)
+	 */
+	lis	r4, CACHE_CMD_ENABLE@h
+	ori	r4, r4, CACHE_CMD_ENABLE@l
+	mtspr	IC_CST, r4
+	isync
+
+	/* clear IC_CST error bits
+	 */
+	mfspr	r4, IC_CST
+
+	bl	plprcr_here
+
+plprcr_here:
+	mflr	r5
+
+	/* calculate relocation offset
+	 */
+	lis	r4, plprcr_here@h
+	ori	r4, r4, plprcr_here@l
+	sub	r5, r5, r4
+
+	/* calculate first address of this function
+	 */
+	lis	r6, plprcr_write_866@h
+	ori	r6, r6, plprcr_write_866@l
+	add	r6, r6, r5
+
+	/* calculate end address of this function
+	 */
+	lis	r7, plprcr_end@h
+	ori	r7, r7, plprcr_end@l
+	add	r7, r7, r5
+
+	/* load and lock code addresses
+	 */
+	mr	r5, r6
+
+plprcr_loop:
+	mtspr	IC_ADR, r5
+	addi	r5, r5, _CACHE_ALIGN_SIZE	/* increment by one line */
+
+	lis	r4, CACHE_CMD_LOAD_LOCK@h
+	ori	r4, r4, CACHE_CMD_LOAD_LOCK@l
+	mtspr	IC_CST, r4
+	isync
+
+	cmpw	r5, r7
+	blt	plprcr_loop
+
+	/* IC_CST error bits not evaluated
+	 */
+
+	/* switch PLPRCR
+	 */
+	mfspr	r4, IMMR		/* read IMMR */
+	rlwinm	r4, r4, 0, 0, 15	/* only high 16 bits count */
+
+	/* write sequence according to MPC866 Errata
+	 */
+	stw	r3, PLPRCR(r4)
+	isync
+
+	lis	r3, SPEED_PLPRCR_WAIT_5CYC@h
+	ori	r3, r3, SPEED_PLPRCR_WAIT_5CYC@l
+
+plprcr_wait:
+	cmpwi	r3, 0
+	beq	plprcr_wait_end
+	nop
+	subi	r3, r3, 1
+	b	plprcr_wait
+
+plprcr_wait_end:
+
+	/* unlock instruction cache but leave it enabled
+	 */
+	lis	r4, CACHE_CMD_UNLOCK_ALL@h
+	ori	r4, r4, CACHE_CMD_UNLOCK_ALL@l
+	mtspr	IC_CST, r4
+	isync
+
+	mtspr	LR, r10		/* restore original Link Register value */
+	blr
+
+plprcr_end:
diff --git a/arch/powerpc/cpu/mpc8xx/scc.c b/arch/powerpc/cpu/mpc8xx/scc.c
new file mode 100644
index 0000000..effb967
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/scc.c
@@ -0,0 +1,572 @@
+/*
+ * File:  scc.c
+ * Description:
+ *	Basic ET HW initialization and packet RX/TX routines
+ *
+ * NOTE  <<<IMPORTANT:  PLEASE READ>>>:
+ *     Do not cache Rx/Tx buffers!
+ */
+
+/*
+ * MPC823 <-> MC68160 Connections:
+ *
+ * Setup MPC823 to work with MC68160 Enhanced Ethernet
+ * Serial Tranceiver as follows:
+ *
+ * MPC823 Signal                MC68160  Comments
+ * ------ ------                -------  --------
+ * PA-12 ETHTX    -------->   TX       Eth. Port Transmit Data
+ * PB-18 E_TENA   -------->   TENA     Eth. Transmit Port Enable
+ * PA-5 ETHTCK    <--------   TCLK     Eth. Port Transmit Clock
+ * PA-13 ETHRX    <--------   RX       Eth. Port Receive Data
+ * PC-8 E_RENA    <--------   RENA     Eth. Receive Enable
+ * PA-6 ETHRCK    <--------   RCLK     Eth. Port Receive Clock
+ * PC-9 E_CLSN    <--------   CLSN     Eth. Port Collision Indication
+ *
+ * FADS Board Signal              MC68160  Comments
+ * -----------------              -------  --------
+ * (BCSR1) ETHEN*     -------->  CS2      Eth. Port Enable
+ * (BSCR4) TPSQEL*    -------->  TPSQEL   Twisted Pair Signal Quality Error Test Enable
+ * (BCSR4) TPFLDL*    -------->  TPFLDL   Twisted Pair Full-Duplex
+ * (BCSR4) ETHLOOP    -------->  LOOP     Eth. Port Diagnostic Loop-Back
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <commproc.h>
+#include <net.h>
+#include <command.h>
+
+#if defined(CONFIG_CMD_NET) && defined(SCC_ENET)
+
+/* Ethernet Transmit and Receive Buffers */
+#define DBUF_LENGTH  1520
+
+#define TX_BUF_CNT 2
+
+#define TOUT_LOOP 10000	/* 10 ms to have a packet sent */
+
+static char txbuf[DBUF_LENGTH];
+
+static uint rxIdx;	/* index of the current RX buffer */
+static uint txIdx;	/* index of the current TX buffer */
+
+/*
+  * SCC Ethernet Tx and Rx buffer descriptors allocated at the
+  *  immr->udata_bd address on Dual-Port RAM
+  * Provide for Double Buffering
+  */
+
+typedef volatile struct CommonBufferDescriptor {
+    cbd_t rxbd[PKTBUFSRX];	/* Rx BD */
+    cbd_t txbd[TX_BUF_CNT];	/* Tx BD */
+} RTXBD;
+
+static RTXBD *rtx;
+
+static int scc_send(struct eth_device* dev, volatile void *packet, int length);
+static int scc_recv(struct eth_device* dev);
+static int scc_init (struct eth_device* dev, bd_t * bd);
+static void scc_halt(struct eth_device* dev);
+
+int scc_initialize(bd_t *bis)
+{
+	struct eth_device* dev;
+
+	dev = (struct eth_device*) malloc(sizeof *dev);
+	memset(dev, 0, sizeof *dev);
+
+	sprintf(dev->name, "SCC ETHERNET");
+	dev->iobase = 0;
+	dev->priv   = 0;
+	dev->init   = scc_init;
+	dev->halt   = scc_halt;
+	dev->send   = scc_send;
+	dev->recv   = scc_recv;
+
+	eth_register(dev);
+
+	return 1;
+}
+
+static int scc_send(struct eth_device* dev, volatile void *packet, int length)
+{
+	int i, j=0;
+#if 0
+	volatile char *in, *out;
+#endif
+
+	/* section 16.9.23.3
+	 * Wait for ready
+	 */
+#if 0
+	while (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY);
+	out = (char *)(rtx->txbd[txIdx].cbd_bufaddr);
+	in = packet;
+	for(i = 0; i < length; i++) {
+		*out++ = *in++;
+	}
+	rtx->txbd[txIdx].cbd_datlen = length;
+	rtx->txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST);
+	while (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) j++;
+
+#ifdef ET_DEBUG
+	printf("cycles: %d    status: %x\n", j, rtx->txbd[txIdx].cbd_sc);
+#endif
+	i = (rtx->txbd[txIdx++].cbd_sc & BD_ENET_TX_STATS) /* return only status bits */;
+
+	/* wrap around buffer index when necessary */
+	if (txIdx >= TX_BUF_CNT) txIdx = 0;
+#endif
+
+	while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
+		udelay (1);	/* will also trigger Wd if needed */
+		j++;
+	}
+	if (j>=TOUT_LOOP) printf("TX not ready\n");
+	rtx->txbd[txIdx].cbd_bufaddr = (uint)packet;
+	rtx->txbd[txIdx].cbd_datlen = length;
+	rtx->txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST |BD_ENET_TX_WRAP);
+	while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
+		udelay (1);	/* will also trigger Wd if needed */
+		j++;
+	}
+	if (j>=TOUT_LOOP) printf("TX timeout\n");
+#ifdef ET_DEBUG
+	printf("cycles: %d    status: %x\n", j, rtx->txbd[txIdx].cbd_sc);
+#endif
+	i = (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS) /* return only status bits */;
+	return i;
+}
+
+static int scc_recv (struct eth_device *dev)
+{
+	int length;
+
+	for (;;) {
+		/* section 16.9.23.2 */
+		if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+			length = -1;
+			break;	/* nothing received - leave for() loop */
+		}
+
+		length = rtx->rxbd[rxIdx].cbd_datlen;
+
+		if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) {
+#ifdef ET_DEBUG
+			printf ("err: %x\n", rtx->rxbd[rxIdx].cbd_sc);
+#endif
+		} else {
+			/* Pass the packet up to the protocol layers. */
+			NetReceive (NetRxPackets[rxIdx], length - 4);
+		}
+
+
+		/* Give the buffer back to the SCC. */
+		rtx->rxbd[rxIdx].cbd_datlen = 0;
+
+		/* wrap around buffer index when necessary */
+		if ((rxIdx + 1) >= PKTBUFSRX) {
+			rtx->rxbd[PKTBUFSRX - 1].cbd_sc =
+				(BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
+			rxIdx = 0;
+		} else {
+			rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+			rxIdx++;
+		}
+	}
+	return length;
+}
+
+/**************************************************************
+  *
+  * SCC Ethernet Initialization Routine
+  *
+  *************************************************************/
+
+static int scc_init (struct eth_device *dev, bd_t * bis)
+{
+
+	int i;
+	scc_enet_t *pram_ptr;
+
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+#if defined(CONFIG_LWMON)
+	reset_phy();
+#endif
+
+#ifdef CONFIG_FADS
+#if defined(CONFIG_MPC86xADS) || defined(CONFIG_MPC860T)
+	/* The MPC86xADS/FADS860T don't use the MODEM_EN or DATA_VOICE signals. */
+	*((uint *) BCSR4) &= ~BCSR4_ETHLOOP;
+	*((uint *) BCSR4) |= BCSR4_TFPLDL | BCSR4_TPSQEL;
+	*((uint *) BCSR1) &= ~BCSR1_ETHEN;
+#else
+	*((uint *) BCSR4) &= ~(BCSR4_ETHLOOP | BCSR4_MODEM_EN);
+	*((uint *) BCSR4) |= BCSR4_TFPLDL | BCSR4_TPSQEL | BCSR4_DATA_VOICE;
+	*((uint *) BCSR1) &= ~BCSR1_ETHEN;
+#endif
+#endif
+
+	pram_ptr = (scc_enet_t *) & (immr->im_cpm.cp_dparam[PROFF_ENET]);
+
+	rxIdx = 0;
+	txIdx = 0;
+
+	if (!rtx) {
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+		rtx = (RTXBD *) (immr->im_cpm.cp_dpmem +
+				 dpram_alloc_align (sizeof (RTXBD), 8));
+#else
+		rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_SCC_BASE);
+#endif
+	}
+
+#if (defined(PA_ENET_RXD) && defined(PA_ENET_TXD))
+	/* Configure port A pins for Txd and Rxd.
+	 */
+	immr->im_ioport.iop_papar |= (PA_ENET_RXD | PA_ENET_TXD);
+	immr->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD);
+	immr->im_ioport.iop_paodr &= ~PA_ENET_TXD;
+#elif (defined(PB_ENET_RXD) && defined(PB_ENET_TXD))
+	/* Configure port B pins for Txd and Rxd.
+	 */
+	immr->im_cpm.cp_pbpar |= (PB_ENET_RXD | PB_ENET_TXD);
+	immr->im_cpm.cp_pbdir &= ~(PB_ENET_RXD | PB_ENET_TXD);
+	immr->im_cpm.cp_pbodr &= ~PB_ENET_TXD;
+#else
+#error Configuration Error: exactly ONE of PA_ENET_[RT]XD, PB_ENET_[RT]XD must be defined
+#endif
+
+#if defined(PC_ENET_LBK)
+	/* Configure port C pins to disable External Loopback
+	 */
+	immr->im_ioport.iop_pcpar &= ~PC_ENET_LBK;
+	immr->im_ioport.iop_pcdir |= PC_ENET_LBK;
+	immr->im_ioport.iop_pcso &= ~PC_ENET_LBK;
+	immr->im_ioport.iop_pcdat &= ~PC_ENET_LBK;	/* Disable Loopback */
+#endif /* PC_ENET_LBK */
+
+	/* Configure port C pins to enable CLSN and RENA.
+	 */
+	immr->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA);
+	immr->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA);
+	immr->im_ioport.iop_pcso |= (PC_ENET_CLSN | PC_ENET_RENA);
+
+	/* Configure port A for TCLK and RCLK.
+	 */
+	immr->im_ioport.iop_papar |= (PA_ENET_TCLK | PA_ENET_RCLK);
+	immr->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK);
+
+	/*
+	 * Configure Serial Interface clock routing -- see section 16.7.5.3
+	 * First, clear all SCC bits to zero, then set the ones we want.
+	 */
+
+	immr->im_cpm.cp_sicr &= ~SICR_ENET_MASK;
+	immr->im_cpm.cp_sicr |= SICR_ENET_CLKRT;
+
+
+	/*
+	 * Initialize SDCR -- see section 16.9.23.7
+	 * SDMA configuration register
+	 */
+	immr->im_siu_conf.sc_sdcr = 0x01;
+
+
+	/*
+	 * Setup SCC Ethernet Parameter RAM
+	 */
+
+	pram_ptr->sen_genscc.scc_rfcr = 0x18;	/* Normal Operation and Mot byte ordering */
+	pram_ptr->sen_genscc.scc_tfcr = 0x18;	/* Mot byte ordering, Normal access */
+
+	pram_ptr->sen_genscc.scc_mrblr = DBUF_LENGTH;	/* max. ET package len 1520 */
+
+	pram_ptr->sen_genscc.scc_rbase = (unsigned int) (&rtx->rxbd[0]);	/* Set RXBD tbl start at Dual Port */
+	pram_ptr->sen_genscc.scc_tbase = (unsigned int) (&rtx->txbd[0]);	/* Set TXBD tbl start at Dual Port */
+
+	/*
+	 * Setup Receiver Buffer Descriptors (13.14.24.18)
+	 * Settings:
+	 *     Empty, Wrap
+	 */
+
+	for (i = 0; i < PKTBUFSRX; i++) {
+		rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+		rtx->rxbd[i].cbd_datlen = 0;	/* Reset */
+		rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i];
+	}
+
+	rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+	/*
+	 * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
+	 * Settings:
+	 *    Add PADs to Short FRAMES, Wrap, Last, Tx CRC
+	 */
+
+	for (i = 0; i < TX_BUF_CNT; i++) {
+		rtx->txbd[i].cbd_sc =
+			(BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+		rtx->txbd[i].cbd_datlen = 0;	/* Reset */
+		rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]);
+	}
+
+	rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+	/*
+	 * Enter Command:  Initialize Rx Params for SCC
+	 */
+
+	do {			/* Spin until ready to issue command    */
+		__asm__ ("eieio");
+	} while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+	/* Issue command */
+	immr->im_cpm.cp_cpcr =
+		((CPM_CR_INIT_RX << 8) | (CPM_CR_ENET << 4) | CPM_CR_FLG);
+	do {			/* Spin until command processed         */
+		__asm__ ("eieio");
+	} while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+
+	/*
+	 * Ethernet Specific Parameter RAM
+	 *     see table 13-16, pg. 660,
+	 *     pg. 681 (example with suggested settings)
+	 */
+
+	pram_ptr->sen_cpres = ~(0x0);	/* Preset CRC */
+	pram_ptr->sen_cmask = 0xdebb20e3;	/* Constant Mask for CRC */
+	pram_ptr->sen_crcec = 0x0;	/* Error Counter CRC (unused) */
+	pram_ptr->sen_alec = 0x0;	/* Alignment Error Counter (unused) */
+	pram_ptr->sen_disfc = 0x0;	/* Discard Frame Counter (unused) */
+	pram_ptr->sen_pads = 0x8888;	/* Short Frame PAD Characters */
+
+	pram_ptr->sen_retlim = 15;	/* Retry Limit Threshold */
+	pram_ptr->sen_maxflr = 1518;	/* MAX Frame Length Register */
+	pram_ptr->sen_minflr = 64;	/* MIN Frame Length Register */
+
+	pram_ptr->sen_maxd1 = DBUF_LENGTH;	/* MAX DMA1 Length Register */
+	pram_ptr->sen_maxd2 = DBUF_LENGTH;	/* MAX DMA2 Length Register */
+
+	pram_ptr->sen_gaddr1 = 0x0;	/* Group Address Filter 1 (unused) */
+	pram_ptr->sen_gaddr2 = 0x0;	/* Group Address Filter 2 (unused) */
+	pram_ptr->sen_gaddr3 = 0x0;	/* Group Address Filter 3 (unused) */
+	pram_ptr->sen_gaddr4 = 0x0;	/* Group Address Filter 4 (unused) */
+
+#define ea eth_get_dev()->enetaddr
+	pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
+	pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
+	pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
+#undef ea
+
+	pram_ptr->sen_pper = 0x0;	/* Persistence (unused) */
+	pram_ptr->sen_iaddr1 = 0x0;	/* Individual Address Filter 1 (unused) */
+	pram_ptr->sen_iaddr2 = 0x0;	/* Individual Address Filter 2 (unused) */
+	pram_ptr->sen_iaddr3 = 0x0;	/* Individual Address Filter 3 (unused) */
+	pram_ptr->sen_iaddr4 = 0x0;	/* Individual Address Filter 4 (unused) */
+	pram_ptr->sen_taddrh = 0x0;	/* Tmp Address (MSB) (unused) */
+	pram_ptr->sen_taddrm = 0x0;	/* Tmp Address (unused) */
+	pram_ptr->sen_taddrl = 0x0;	/* Tmp Address (LSB) (unused) */
+
+	/*
+	 * Enter Command:  Initialize Tx Params for SCC
+	 */
+
+	do {			/* Spin until ready to issue command    */
+		__asm__ ("eieio");
+	} while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+	/* Issue command */
+	immr->im_cpm.cp_cpcr =
+		((CPM_CR_INIT_TX << 8) | (CPM_CR_ENET << 4) | CPM_CR_FLG);
+	do {			/* Spin until command processed         */
+		__asm__ ("eieio");
+	} while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+
+	/*
+	 * Mask all Events in SCCM - we use polling mode
+	 */
+	immr->im_cpm.cp_scc[SCC_ENET].scc_sccm = 0;
+
+	/*
+	 * Clear Events in SCCE -- Clear bits by writing 1's
+	 */
+
+	immr->im_cpm.cp_scc[SCC_ENET].scc_scce = ~(0x0);
+
+
+	/*
+	 * Initialize GSMR High 32-Bits
+	 * Settings:  Normal Mode
+	 */
+
+	immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrh = 0;
+
+	/*
+	 * Initialize GSMR Low 32-Bits, but do not Enable Transmit/Receive
+	 * Settings:
+	 *     TCI = Invert
+	 *     TPL =  48 bits
+	 *     TPP = Repeating 10's
+	 *     MODE = Ethernet
+	 */
+
+	immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl = (SCC_GSMRL_TCI |
+						   SCC_GSMRL_TPL_48 |
+						   SCC_GSMRL_TPP_10 |
+						   SCC_GSMRL_MODE_ENET);
+
+	/*
+	 * Initialize the DSR -- see section 13.14.4 (pg. 513) v0.4
+	 */
+
+	immr->im_cpm.cp_scc[SCC_ENET].scc_dsr = 0xd555;
+
+	/*
+	 * Initialize the PSMR
+	 * Settings:
+	 *  CRC = 32-Bit CCITT
+	 *  NIB = Begin searching for SFD 22 bits after RENA
+	 *  FDE = Full Duplex Enable
+	 *  LPB = Loopback Enable (Needed when FDE is set)
+	 *  BRO = Reject broadcast packets
+	 *  PROMISCOUS = Catch all packets regardless of dest. MAC adress
+	 */
+	immr->im_cpm.cp_scc[SCC_ENET].scc_psmr = SCC_PSMR_ENCRC |
+		SCC_PSMR_NIB22 |
+#if defined(CONFIG_SCC_ENET_FULL_DUPLEX)
+		SCC_PSMR_FDE | SCC_PSMR_LPB |
+#endif
+#if defined(CONFIG_SCC_ENET_NO_BROADCAST)
+		SCC_PSMR_BRO |
+#endif
+#if defined(CONFIG_SCC_ENET_PROMISCOUS)
+		SCC_PSMR_PRO |
+#endif
+		0;
+
+	/*
+	 * Configure Ethernet TENA Signal
+	 */
+
+#if (defined(PC_ENET_TENA) && !defined(PB_ENET_TENA))
+	immr->im_ioport.iop_pcpar |= PC_ENET_TENA;
+	immr->im_ioport.iop_pcdir &= ~PC_ENET_TENA;
+#elif (defined(PB_ENET_TENA) && !defined(PC_ENET_TENA))
+	immr->im_cpm.cp_pbpar |= PB_ENET_TENA;
+	immr->im_cpm.cp_pbdir |= PB_ENET_TENA;
+#else
+#error Configuration Error: exactly ONE of PB_ENET_TENA, PC_ENET_TENA must be defined
+#endif
+
+#if defined(CONFIG_ADS) && defined(CONFIG_MPC860)
+	/*
+	 * Port C is used to control the PHY,MC68160.
+	 */
+	immr->im_ioport.iop_pcdir |=
+		(PC_ENET_ETHLOOP | PC_ENET_TPFLDL | PC_ENET_TPSQEL);
+
+	immr->im_ioport.iop_pcdat |= PC_ENET_TPFLDL;
+	immr->im_ioport.iop_pcdat &= ~(PC_ENET_ETHLOOP | PC_ENET_TPSQEL);
+	*((uint *) BCSR1) &= ~BCSR1_ETHEN;
+#endif /* MPC860ADS */
+
+#if defined(CONFIG_AMX860)
+	/*
+	 * Port B is used to control the PHY,MC68160.
+	 */
+	immr->im_cpm.cp_pbdir |=
+		(PB_ENET_ETHLOOP | PB_ENET_TPFLDL | PB_ENET_TPSQEL);
+
+	immr->im_cpm.cp_pbdat |= PB_ENET_TPFLDL;
+	immr->im_cpm.cp_pbdat &= ~(PB_ENET_ETHLOOP | PB_ENET_TPSQEL);
+
+	immr->im_ioport.iop_pddir |= PD_ENET_ETH_EN;
+	immr->im_ioport.iop_pddat &= ~PD_ENET_ETH_EN;
+#endif /* AMX860 */
+
+#ifdef CONFIG_RPXCLASSIC
+	*((uchar *) BCSR0) &= ~BCSR0_ETHLPBK;
+	*((uchar *) BCSR0) |= (BCSR0_ETHEN | BCSR0_COLTEST | BCSR0_FULLDPLX);
+#endif
+
+#ifdef CONFIG_RPXLITE
+	*((uchar *) BCSR0) |= BCSR0_ETHEN;
+#endif
+
+#if defined(CONFIG_QS860T)
+	/*
+	 * PB27=FDE-, set output low for full duplex
+	 * PB26=Link Test Enable, normally high output
+	 */
+	immr->im_cpm.cp_pbdir |= 0x00000030;
+	immr->im_cpm.cp_pbdat |= 0x00000020;
+	immr->im_cpm.cp_pbdat &= ~0x00000010;
+#endif /* QS860T */
+
+#ifdef CONFIG_MBX
+	board_ether_init ();
+#endif
+
+#if defined(CONFIG_NETVIA)
+#if defined(PA_ENET_PDN)
+	immr->im_ioport.iop_papar &= ~PA_ENET_PDN;
+	immr->im_ioport.iop_padir |= PA_ENET_PDN;
+	immr->im_ioport.iop_padat |= PA_ENET_PDN;
+#elif defined(PB_ENET_PDN)
+	immr->im_cpm.cp_pbpar &= ~PB_ENET_PDN;
+	immr->im_cpm.cp_pbdir |= PB_ENET_PDN;
+	immr->im_cpm.cp_pbdat |= PB_ENET_PDN;
+#elif defined(PC_ENET_PDN)
+	immr->im_ioport.iop_pcpar &= ~PC_ENET_PDN;
+	immr->im_ioport.iop_pcdir |= PC_ENET_PDN;
+	immr->im_ioport.iop_pcdat |= PC_ENET_PDN;
+#elif defined(PD_ENET_PDN)
+	immr->im_ioport.iop_pdpar &= ~PD_ENET_PDN;
+	immr->im_ioport.iop_pddir |= PD_ENET_PDN;
+	immr->im_ioport.iop_pddat |= PD_ENET_PDN;
+#endif
+#endif
+
+	/*
+	 * Set the ENT/ENR bits in the GSMR Low -- Enable Transmit/Receive
+	 */
+
+	immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl |=
+		(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	/*
+	 * Work around transmit problem with first eth packet
+	 */
+#if defined (CONFIG_FADS)
+	udelay (10000);		/* wait 10 ms */
+#elif defined (CONFIG_AMX860) || defined(CONFIG_RPXCLASSIC)
+	udelay (100000);	/* wait 100 ms */
+#endif
+
+	return 1;
+}
+
+
+static void scc_halt (struct eth_device *dev)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+	immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl &=
+		~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	immr->im_ioport.iop_pcso  &=  ~(PC_ENET_CLSN | PC_ENET_RENA);
+}
+
+#if 0
+void restart (void)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+	immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl |=
+		(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+}
+#endif
+#endif
diff --git a/arch/powerpc/cpu/mpc8xx/serial.c b/arch/powerpc/cpu/mpc8xx/serial.c
new file mode 100644
index 0000000..664db65
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/serial.c
@@ -0,0 +1,745 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <commproc.h>
+#include <command.h>
+#include <serial.h>
+#include <watchdog.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if !defined(CONFIG_8xx_CONS_NONE)	/* No Console at all */
+
+#if defined(CONFIG_8xx_CONS_SMC1)	/* Console on SMC1 */
+#define	SMC_INDEX	0
+#define PROFF_SMC	PROFF_SMC1
+#define CPM_CR_CH_SMC	CPM_CR_CH_SMC1
+
+#elif defined(CONFIG_8xx_CONS_SMC2)	/* Console on SMC2 */
+#define SMC_INDEX	1
+#define PROFF_SMC	PROFF_SMC2
+#define CPM_CR_CH_SMC	CPM_CR_CH_SMC2
+
+#endif /* CONFIG_8xx_CONS_SMCx */
+
+#if defined(CONFIG_8xx_CONS_SCC1)	/* Console on SCC1 */
+#define SCC_INDEX	0
+#define PROFF_SCC	PROFF_SCC1
+#define CPM_CR_CH_SCC	CPM_CR_CH_SCC1
+
+#elif defined(CONFIG_8xx_CONS_SCC2)	/* Console on SCC2 */
+#define SCC_INDEX	1
+#define PROFF_SCC	PROFF_SCC2
+#define CPM_CR_CH_SCC	CPM_CR_CH_SCC2
+
+#elif defined(CONFIG_8xx_CONS_SCC3)	/* Console on SCC3 */
+#define SCC_INDEX	2
+#define PROFF_SCC	PROFF_SCC3
+#define CPM_CR_CH_SCC	CPM_CR_CH_SCC3
+
+#elif defined(CONFIG_8xx_CONS_SCC4)	/* Console on SCC4 */
+#define SCC_INDEX	3
+#define PROFF_SCC	PROFF_SCC4
+#define CPM_CR_CH_SCC	CPM_CR_CH_SCC4
+
+#endif /* CONFIG_8xx_CONS_SCCx */
+
+#if !defined(CONFIG_SYS_SMC_RXBUFLEN)
+#define CONFIG_SYS_SMC_RXBUFLEN	1
+#define CONFIG_SYS_MAXIDLE	0
+#else
+#if !defined(CONFIG_SYS_MAXIDLE)
+#error "you must define CONFIG_SYS_MAXIDLE"
+#endif
+#endif
+
+typedef volatile struct serialbuffer {
+	cbd_t	rxbd;		/* Rx BD */
+	cbd_t	txbd;		/* Tx BD */
+	uint	rxindex;	/* index for next character to read */
+	volatile uchar	rxbuf[CONFIG_SYS_SMC_RXBUFLEN];/* rx buffers */
+	volatile uchar	txbuf;	/* tx buffers */
+} serialbuffer_t;
+
+static void serial_setdivisor(volatile cpm8xx_t *cp)
+{
+	int divisor=(gd->cpu_clk + 8*gd->baudrate)/16/gd->baudrate;
+
+	if(divisor/16>0x1000) {
+		/* bad divisor, assume 50MHz clock and 9600 baud */
+		divisor=(50*1000*1000 + 8*9600)/16/9600;
+	}
+
+#ifdef CONFIG_SYS_BRGCLK_PRESCALE
+	divisor /= CONFIG_SYS_BRGCLK_PRESCALE;
+#endif
+
+	if(divisor<=0x1000) {
+		cp->cp_brgc1=((divisor-1)<<1) | CPM_BRG_EN;
+	} else {
+		cp->cp_brgc1=((divisor/16-1)<<1) | CPM_BRG_EN | CPM_BRG_DIV16;
+	}
+}
+
+#if (defined (CONFIG_8xx_CONS_SMC1) || defined (CONFIG_8xx_CONS_SMC2))
+
+/*
+ * Minimal serial functions needed to use one of the SMC ports
+ * as serial console interface.
+ */
+
+static void smc_setbrg (void)
+{
+	volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile cpm8xx_t *cp = &(im->im_cpm);
+
+	/* Set up the baud rate generator.
+	 * See 8xx_io/commproc.c for details.
+	 *
+	 * Wire BRG1 to SMCx
+	 */
+
+	cp->cp_simode = 0x00000000;
+
+	serial_setdivisor(cp);
+}
+
+static int smc_init (void)
+{
+	volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile smc_t *sp;
+	volatile smc_uart_t *up;
+	volatile cpm8xx_t *cp = &(im->im_cpm);
+#if (!defined(CONFIG_8xx_CONS_SMC1)) && (defined(CONFIG_MPC823) || defined(CONFIG_MPC850))
+	volatile iop8xx_t *ip = (iop8xx_t *)&(im->im_ioport);
+#endif
+	uint	dpaddr;
+	volatile serialbuffer_t *rtx;
+
+	/* initialize pointers to SMC */
+
+	sp = (smc_t *) &(cp->cp_smc[SMC_INDEX]);
+	up = (smc_uart_t *) &cp->cp_dparam[PROFF_SMC];
+#ifdef CONFIG_SYS_SMC_UCODE_PATCH
+	up = (smc_uart_t *) &cp->cp_dpmem[up->smc_rpbase];
+#else
+	/* Disable relocation */
+	up->smc_rpbase = 0;
+#endif
+
+	/* Disable transmitter/receiver. */
+	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+	/* Enable SDMA. */
+	im->im_siu_conf.sc_sdcr = 1;
+
+	/* clear error conditions */
+#ifdef	CONFIG_SYS_SDSR
+	im->im_sdma.sdma_sdsr = CONFIG_SYS_SDSR;
+#else
+	im->im_sdma.sdma_sdsr = 0x83;
+#endif
+
+	/* clear SDMA interrupt mask */
+#ifdef	CONFIG_SYS_SDMR
+	im->im_sdma.sdma_sdmr = CONFIG_SYS_SDMR;
+#else
+	im->im_sdma.sdma_sdmr = 0x00;
+#endif
+
+#if defined(CONFIG_8xx_CONS_SMC1)
+	/* Use Port B for SMC1 instead of other functions. */
+	cp->cp_pbpar |=  0x000000c0;
+	cp->cp_pbdir &= ~0x000000c0;
+	cp->cp_pbodr &= ~0x000000c0;
+#else	/* CONFIG_8xx_CONS_SMC2 */
+# if defined(CONFIG_MPC823) || defined(CONFIG_MPC850)
+	/* Use Port A for SMC2 instead of other functions. */
+	ip->iop_papar |=  0x00c0;
+	ip->iop_padir &= ~0x00c0;
+	ip->iop_paodr &= ~0x00c0;
+# else	/* must be a 860 then */
+	/* Use Port B for SMC2 instead of other functions.
+	 */
+	cp->cp_pbpar |=  0x00000c00;
+	cp->cp_pbdir &= ~0x00000c00;
+	cp->cp_pbodr &= ~0x00000c00;
+# endif
+#endif
+
+#if defined(CONFIG_FADS) || defined(CONFIG_ADS)
+	/* Enable RS232 */
+#if defined(CONFIG_8xx_CONS_SMC1)
+	*((uint *) BCSR1) &= ~BCSR1_RS232EN_1;
+#else
+	*((uint *) BCSR1) &= ~BCSR1_RS232EN_2;
+#endif
+#endif	/* CONFIG_FADS */
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+	/* Enable Monitor Port Transceiver */
+	*((uchar *) BCSR0) |= BCSR0_ENMONXCVR ;
+#endif /* CONFIG_RPXLITE */
+
+	/* Set the physical address of the host memory buffers in
+	 * the buffer descriptors.
+	 */
+
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+	/* allocate
+	 * size of struct serialbuffer with bd rx/tx, buffer rx/tx and rx index
+	 */
+	dpaddr = dpram_alloc_align((sizeof(serialbuffer_t)), 8);
+#else
+	dpaddr = CPM_SERIAL_BASE ;
+#endif
+
+	rtx = (serialbuffer_t *)&cp->cp_dpmem[dpaddr];
+	/* Allocate space for two buffer descriptors in the DP ram.
+	 * For now, this address seems OK, but it may have to
+	 * change with newer versions of the firmware.
+	 * damm: allocating space after the two buffers for rx/tx data
+	 */
+
+	rtx->rxbd.cbd_bufaddr = (uint) &rtx->rxbuf;
+	rtx->rxbd.cbd_sc      = 0;
+
+	rtx->txbd.cbd_bufaddr = (uint) &rtx->txbuf;
+	rtx->txbd.cbd_sc      = 0;
+
+	/* Set up the uart parameters in the parameter ram. */
+	up->smc_rbase = dpaddr;
+	up->smc_tbase = dpaddr+sizeof(cbd_t);
+	up->smc_rfcr = SMC_EB;
+	up->smc_tfcr = SMC_EB;
+#if defined (CONFIG_SYS_SMC_UCODE_PATCH)
+	up->smc_rbptr = up->smc_rbase;
+	up->smc_tbptr = up->smc_tbase;
+	up->smc_rstate = 0;
+	up->smc_tstate = 0;
+#endif
+
+#if defined(CONFIG_MBX)
+	board_serial_init();
+#endif	/* CONFIG_MBX */
+
+	/* Set UART mode, 8 bit, no parity, one stop.
+	 * Enable receive and transmit.
+	 */
+	sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
+
+	/* Mask all interrupts and remove anything pending.
+	*/
+	sp->smc_smcm = 0;
+	sp->smc_smce = 0xff;
+
+#ifdef CONFIG_SYS_SPC1920_SMC1_CLK4
+	/* clock source is PLD */
+
+	/* set freq to 19200 Baud */
+	*((volatile uchar *) CONFIG_SYS_SPC1920_PLD_BASE+6) = 0x3;
+	/* configure clk4 as input */
+	im->im_ioport.iop_pdpar |= 0x800;
+	im->im_ioport.iop_pddir &= ~0x800;
+
+	cp->cp_simode = ((cp->cp_simode & ~0xf000) | 0x7000);
+#else
+	/* Set up the baud rate generator */
+	smc_setbrg ();
+#endif
+
+	/* Make the first buffer the only buffer. */
+	rtx->txbd.cbd_sc |= BD_SC_WRAP;
+	rtx->rxbd.cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+	/* single/multi character receive. */
+	up->smc_mrblr = CONFIG_SYS_SMC_RXBUFLEN;
+	up->smc_maxidl = CONFIG_SYS_MAXIDLE;
+	rtx->rxindex = 0;
+
+	/* Initialize Tx/Rx parameters.	*/
+	while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
+	  ;
+
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+	while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
+	  ;
+
+	/* Enable transmitter/receiver.	*/
+	sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+
+	return (0);
+}
+
+static void
+smc_putc(const char c)
+{
+	volatile smc_uart_t	*up;
+	volatile immap_t	*im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile cpm8xx_t	*cpmp = &(im->im_cpm);
+	volatile serialbuffer_t	*rtx;
+
+#ifdef CONFIG_MODEM_SUPPORT
+	if (gd->be_quiet)
+		return;
+#endif
+
+	if (c == '\n')
+		smc_putc ('\r');
+
+	up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
+#ifdef CONFIG_SYS_SMC_UCODE_PATCH
+	up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase];
+#endif
+
+	rtx = (serialbuffer_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+	/* Wait for last character to go. */
+	rtx->txbuf = c;
+	rtx->txbd.cbd_datlen = 1;
+	rtx->txbd.cbd_sc |= BD_SC_READY;
+	__asm__("eieio");
+
+	while (rtx->txbd.cbd_sc & BD_SC_READY) {
+		WATCHDOG_RESET ();
+		__asm__("eieio");
+	}
+}
+
+static void
+smc_puts (const char *s)
+{
+	while (*s) {
+		smc_putc (*s++);
+	}
+}
+
+static int
+smc_getc(void)
+{
+	volatile smc_uart_t	*up;
+	volatile immap_t	*im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile cpm8xx_t	*cpmp = &(im->im_cpm);
+	volatile serialbuffer_t	*rtx;
+	unsigned char  c;
+
+	up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
+#ifdef CONFIG_SYS_SMC_UCODE_PATCH
+	up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase];
+#endif
+	rtx = (serialbuffer_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+	/* Wait for character to show up. */
+	while (rtx->rxbd.cbd_sc & BD_SC_EMPTY)
+		WATCHDOG_RESET ();
+
+	/* the characters are read one by one,
+	 * use the rxindex to know the next char to deliver
+	 */
+	c = *(unsigned char *) (rtx->rxbd.cbd_bufaddr+rtx->rxindex);
+	rtx->rxindex++;
+
+	/* check if all char are readout, then make prepare for next receive */
+	if (rtx->rxindex >= rtx->rxbd.cbd_datlen) {
+		rtx->rxindex = 0;
+		rtx->rxbd.cbd_sc |= BD_SC_EMPTY;
+	}
+	return(c);
+}
+
+static int
+smc_tstc(void)
+{
+	volatile smc_uart_t	*up;
+	volatile immap_t	*im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile cpm8xx_t	*cpmp = &(im->im_cpm);
+	volatile serialbuffer_t	*rtx;
+
+	up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
+#ifdef CONFIG_SYS_SMC_UCODE_PATCH
+	up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase];
+#endif
+
+	rtx = (serialbuffer_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+	return !(rtx->rxbd.cbd_sc & BD_SC_EMPTY);
+}
+
+struct serial_device serial_smc_device =
+{
+	"serial_smc",
+	"SMC",
+	smc_init,
+	smc_setbrg,
+	smc_getc,
+	smc_tstc,
+	smc_putc,
+	smc_puts,
+};
+
+#endif /* CONFIG_8xx_CONS_SMC1 || CONFIG_8xx_CONS_SMC2 */
+
+#if defined(CONFIG_8xx_CONS_SCC1) || defined(CONFIG_8xx_CONS_SCC2) || \
+    defined(CONFIG_8xx_CONS_SCC3) || defined(CONFIG_8xx_CONS_SCC4)
+
+static void
+scc_setbrg (void)
+{
+	volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile cpm8xx_t *cp = &(im->im_cpm);
+
+	/* Set up the baud rate generator.
+	 * See 8xx_io/commproc.c for details.
+	 *
+	 * Wire BRG1 to SCCx
+	 */
+
+	cp->cp_sicr &= ~(0x000000FF << (8 * SCC_INDEX));
+
+	serial_setdivisor(cp);
+}
+
+static int scc_init (void)
+{
+	volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile scc_t *sp;
+	volatile scc_uart_t *up;
+	volatile cbd_t *tbdf, *rbdf;
+	volatile cpm8xx_t *cp = &(im->im_cpm);
+	uint	 dpaddr;
+#if (SCC_INDEX != 2) || !defined(CONFIG_MPC850)
+	volatile iop8xx_t *ip = (iop8xx_t *)&(im->im_ioport);
+#endif
+
+	/* initialize pointers to SCC */
+
+	sp = (scc_t *) &(cp->cp_scc[SCC_INDEX]);
+	up = (scc_uart_t *) &cp->cp_dparam[PROFF_SCC];
+
+#if defined(CONFIG_LWMON) && defined(CONFIG_8xx_CONS_SCC2)
+    {	/* Disable Ethernet, enable Serial */
+	uchar c;
+
+	c = pic_read  (0x61);
+	c &= ~0x40;	/* enable COM3 */
+	c |=  0x80;	/* disable Ethernet */
+	pic_write (0x61, c);
+
+	/* enable RTS2 */
+	cp->cp_pbpar |=  0x2000;
+	cp->cp_pbdat |=  0x2000;
+	cp->cp_pbdir |=  0x2000;
+    }
+#endif	/* CONFIG_LWMON */
+
+	/* Disable transmitter/receiver. */
+	sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+#if (SCC_INDEX == 2) && defined(CONFIG_MPC850)
+	/*
+	 * The MPC850 has SCC3 on Port B
+	 */
+	cp->cp_pbpar |=  0x06;
+	cp->cp_pbdir &= ~0x06;
+	cp->cp_pbodr &= ~0x06;
+
+#elif (SCC_INDEX < 2) || !defined(CONFIG_IP860)
+	/*
+	 * Standard configuration for SCC's is on Part A
+	 */
+	ip->iop_papar |=  ((3 << (2 * SCC_INDEX)));
+	ip->iop_padir &= ~((3 << (2 * SCC_INDEX)));
+	ip->iop_paodr &= ~((3 << (2 * SCC_INDEX)));
+#else
+	/*
+	 * The IP860 has SCC3 and SCC4 on Port D
+	 */
+	ip->iop_pdpar |=  ((3 << (2 * SCC_INDEX)));
+#endif
+
+	/* Allocate space for two buffer descriptors in the DP ram. */
+
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+	dpaddr = dpram_alloc_align (sizeof(cbd_t)*2 + 2, 8) ;
+#else
+	dpaddr = CPM_SERIAL2_BASE ;
+#endif
+
+	/* Enable SDMA.	*/
+	im->im_siu_conf.sc_sdcr = 0x0001;
+
+	/* Set the physical address of the host memory buffers in
+	 * the buffer descriptors.
+	 */
+
+	rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
+	rbdf->cbd_bufaddr = (uint) (rbdf+2);
+	rbdf->cbd_sc = 0;
+	tbdf = rbdf + 1;
+	tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+	tbdf->cbd_sc = 0;
+
+	/* Set up the baud rate generator. */
+	scc_setbrg ();
+
+	/* Set up the uart parameters in the parameter ram. */
+	up->scc_genscc.scc_rbase = dpaddr;
+	up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
+
+	/* Initialize Tx/Rx parameters. */
+	while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
+		;
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+	while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
+		;
+
+	up->scc_genscc.scc_rfcr  = SCC_EB | 0x05;
+	up->scc_genscc.scc_tfcr  = SCC_EB | 0x05;
+
+	up->scc_genscc.scc_mrblr = 1;	/* Single character receive */
+	up->scc_maxidl = 0;		/* disable max idle */
+	up->scc_brkcr  = 1;		/* send one break character on stop TX */
+	up->scc_parec  = 0;
+	up->scc_frmec  = 0;
+	up->scc_nosec  = 0;
+	up->scc_brkec  = 0;
+	up->scc_uaddr1 = 0;
+	up->scc_uaddr2 = 0;
+	up->scc_toseq  = 0;
+	up->scc_char1  = 0x8000;
+	up->scc_char2  = 0x8000;
+	up->scc_char3  = 0x8000;
+	up->scc_char4  = 0x8000;
+	up->scc_char5  = 0x8000;
+	up->scc_char6  = 0x8000;
+	up->scc_char7  = 0x8000;
+	up->scc_char8  = 0x8000;
+	up->scc_rccm   = 0xc0ff;
+
+	/* Set low latency / small fifo. */
+	sp->scc_gsmrh = SCC_GSMRH_RFW;
+
+	/* Set SCC(x) clock mode to 16x
+	 * See 8xx_io/commproc.c for details.
+	 *
+	 * Wire BRG1 to SCCn
+	 */
+
+	/* Set UART mode, clock divider 16 on Tx and Rx */
+	sp->scc_gsmrl &= ~0xF;
+	sp->scc_gsmrl |=
+		(SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+	sp->scc_psmr  = 0;
+	sp->scc_psmr  |= SCU_PSMR_CL;
+
+	/* Mask all interrupts and remove anything pending. */
+	sp->scc_sccm = 0;
+	sp->scc_scce = 0xffff;
+	sp->scc_dsr  = 0x7e7e;
+	sp->scc_psmr = 0x3000;
+
+	/* Make the first buffer the only buffer. */
+	tbdf->cbd_sc |= BD_SC_WRAP;
+	rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+	/* Enable transmitter/receiver.	*/
+	sp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	return (0);
+}
+
+static void
+scc_putc(const char c)
+{
+	volatile cbd_t		*tbdf;
+	volatile char		*buf;
+	volatile scc_uart_t	*up;
+	volatile immap_t	*im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile cpm8xx_t	*cpmp = &(im->im_cpm);
+
+#ifdef CONFIG_MODEM_SUPPORT
+	if (gd->be_quiet)
+		return;
+#endif
+
+	if (c == '\n')
+		scc_putc ('\r');
+
+	up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
+
+	tbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_tbase];
+
+	/* Wait for last character to go. */
+
+	buf = (char *)tbdf->cbd_bufaddr;
+
+	*buf = c;
+	tbdf->cbd_datlen = 1;
+	tbdf->cbd_sc |= BD_SC_READY;
+	__asm__("eieio");
+
+	while (tbdf->cbd_sc & BD_SC_READY) {
+		__asm__("eieio");
+		WATCHDOG_RESET ();
+	}
+}
+
+static void
+scc_puts (const char *s)
+{
+	while (*s) {
+		scc_putc (*s++);
+	}
+}
+
+static int
+scc_getc(void)
+{
+	volatile cbd_t		*rbdf;
+	volatile unsigned char	*buf;
+	volatile scc_uart_t	*up;
+	volatile immap_t	*im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile cpm8xx_t	*cpmp = &(im->im_cpm);
+	unsigned char		c;
+
+	up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
+
+	rbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
+
+	/* Wait for character to show up. */
+	buf = (unsigned char *)rbdf->cbd_bufaddr;
+
+	while (rbdf->cbd_sc & BD_SC_EMPTY)
+		WATCHDOG_RESET ();
+
+	c = *buf;
+	rbdf->cbd_sc |= BD_SC_EMPTY;
+
+	return(c);
+}
+
+static int
+scc_tstc(void)
+{
+	volatile cbd_t		*rbdf;
+	volatile scc_uart_t	*up;
+	volatile immap_t	*im = (immap_t *)CONFIG_SYS_IMMR;
+	volatile cpm8xx_t	*cpmp = &(im->im_cpm);
+
+	up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
+
+	rbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
+
+	return(!(rbdf->cbd_sc & BD_SC_EMPTY));
+}
+
+struct serial_device serial_scc_device =
+{
+	"serial_scc",
+	"SCC",
+	scc_init,
+	scc_setbrg,
+	scc_getc,
+	scc_tstc,
+	scc_putc,
+	scc_puts,
+};
+
+#endif	/* CONFIG_8xx_CONS_SCCx */
+
+#ifdef CONFIG_MODEM_SUPPORT
+void disable_putc(void)
+{
+	gd->be_quiet = 1;
+}
+
+void enable_putc(void)
+{
+	gd->be_quiet = 0;
+}
+#endif
+
+#if defined(CONFIG_CMD_KGDB)
+
+void
+kgdb_serial_init(void)
+{
+	int i = -1;
+
+	if (strcmp(default_serial_console()->ctlr, "SMC") == 0)
+	{
+#if defined(CONFIG_8xx_CONS_SMC1)
+		i = 1;
+#elif defined(CONFIG_8xx_CONS_SMC2)
+		i = 2;
+#endif
+	}
+	else if (strcmp(default_serial_console()->ctlr, "SMC") == 0)
+	{
+#if defined(CONFIG_8xx_CONS_SCC1)
+		i = 1;
+#elif defined(CONFIG_8xx_CONS_SCC2)
+		i = 2;
+#elif defined(CONFIG_8xx_CONS_SCC3)
+		i = 3;
+#elif defined(CONFIG_8xx_CONS_SCC4)
+		i = 4;
+#endif
+	}
+
+	if (i >= 0)
+	{
+		serial_printf("[on %s%d] ", default_serial_console()->ctlr, i);
+	}
+}
+
+void
+putDebugChar (int c)
+{
+	serial_putc (c);
+}
+
+void
+putDebugStr (const char *str)
+{
+	serial_puts (str);
+}
+
+int
+getDebugChar (void)
+{
+	return serial_getc();
+}
+
+void
+kgdb_interruptible (int yes)
+{
+	return;
+}
+#endif
+
+#endif	/* CONFIG_8xx_CONS_NONE */
diff --git a/arch/powerpc/cpu/mpc8xx/speed.c b/arch/powerpc/cpu/mpc8xx/speed.c
new file mode 100644
index 0000000..f309f29
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/speed.c
@@ -0,0 +1,416 @@
+/*
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if !defined(CONFIG_8xx_CPUCLK_DEFAULT) || defined(CONFIG_SYS_MEASURE_CPUCLK) || defined(DEBUG)
+
+#define PITC_SHIFT 16
+#define PITR_SHIFT 16
+/* pitc values to time for 58/8192 seconds (about 70.8 milliseconds) */
+#define SPEED_PIT_COUNTS 58
+#define SPEED_PITC	 ((SPEED_PIT_COUNTS - 1) << PITC_SHIFT)
+#define SPEED_PITC_INIT	 ((SPEED_PIT_COUNTS + 1) << PITC_SHIFT)
+
+/* Access functions for the Machine State Register */
+static __inline__ unsigned long get_msr(void)
+{
+	unsigned long msr;
+
+	asm volatile("mfmsr %0" : "=r" (msr) :);
+	return msr;
+}
+
+static __inline__ void set_msr(unsigned long msr)
+{
+	asm volatile("mtmsr %0" : : "r" (msr));
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Measure CPU clock speed (core clock GCLK1, GCLK2),
+ * also determine bus clock speed (checking bus divider factor)
+ *
+ * (Approx. GCLK frequency in Hz)
+ *
+ * Initializes timer 2 and PIT, but disables them before return.
+ * [Use timer 2, because MPC823 CPUs mask 0.x do not have timers 3 and 4]
+ *
+ * When measuring the CPU clock against the PIT, we count cpu clocks
+ * for 58/8192 seconds with a prescale divide by 177 for the cpu clock.
+ * These strange values for the timing interval and prescaling are used
+ * because the formula for the CPU clock is:
+ *
+ *    CPU clock = count * (177 * (8192 / 58))
+ *
+ *		= count * 24999.7241
+ *
+ *    which is very close to
+ *
+ *		= count * 25000
+ *
+ * Since the count gives the CPU clock divided by 25000, we can get
+ * the CPU clock rounded to the nearest 0.1 MHz by
+ *
+ *    CPU clock = ((count + 2) / 4) * 100000;
+ *
+ * The rounding is important since the measurement is sometimes going
+ * to be high or low by 0.025 MHz, depending on exactly how the clocks
+ * and counters interact. By rounding we get the exact answer for any
+ * CPU clock that is an even multiple of 0.1 MHz.
+ */
+
+unsigned long measure_gclk(void)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	volatile cpmtimer8xx_t *timerp = &immr->im_cpmtimer;
+	ulong timer2_val;
+	ulong msr_val;
+
+#ifdef CONFIG_SYS_8XX_XIN
+	/* dont use OSCM, only use EXTCLK/512 */
+	immr->im_clkrst.car_sccr |= SCCR_RTSEL | SCCR_RTDIV;
+#else
+	immr->im_clkrst.car_sccr &= ~(SCCR_RTSEL | SCCR_RTDIV);
+#endif
+
+	/* Reset + Stop Timer 2, no cascading
+	 */
+	timerp->cpmt_tgcr &= ~(TGCR_CAS2 | TGCR_RST2);
+
+	/* Keep stopped, halt in debug mode
+	 */
+	timerp->cpmt_tgcr |= (TGCR_FRZ2 | TGCR_STP2);
+
+	/* Timer 2 setup:
+	 * Output ref. interrupt disable, int. clock
+	 * Prescale by 177. Note that prescaler divides by value + 1
+	 * so we must subtract 1 here.
+	 */
+	timerp->cpmt_tmr2 = ((177 - 1) << TMR_PS_SHIFT) | TMR_ICLK_IN_GEN;
+
+	timerp->cpmt_tcn2 = 0;		/* reset state		*/
+	timerp->cpmt_tgcr |= TGCR_RST2;	/* enable timer 2	*/
+
+	/*
+	 * PIT setup:
+	 *
+	 * We want to time for SPEED_PITC_COUNTS counts (of 8192 Hz),
+	 * so the count value would be SPEED_PITC_COUNTS - 1.
+	 * But there would be an uncertainty in the start time of 1/4
+	 * count since when we enable the PIT the count is not
+	 * synchronized to the 32768 Hz oscillator. The trick here is
+	 * to start the count higher and wait until the PIT count
+	 * changes to the required value before starting timer 2.
+	 *
+	 * One count high should be enough, but occasionally the start
+	 * is off by 1 or 2 counts of 32768 Hz. With the start value
+	 * set two counts high it seems very reliable.
+	 */
+
+	immr->im_sitk.sitk_pitck = KAPWR_KEY;	/* PIT initialization */
+	immr->im_sit.sit_pitc = SPEED_PITC_INIT;
+
+	immr->im_sitk.sitk_piscrk = KAPWR_KEY;
+	immr->im_sit.sit_piscr = CONFIG_SYS_PISCR;
+
+	/*
+	 * Start measurement - disable interrupts, just in case
+	 */
+	msr_val = get_msr ();
+	set_msr (msr_val & ~MSR_EE);
+
+	immr->im_sit.sit_piscr |= PISCR_PTE;
+
+	/* spin until get exact count when we want to start */
+	while (immr->im_sit.sit_pitr > SPEED_PITC);
+
+	timerp->cpmt_tgcr &= ~TGCR_STP2;	/* Start Timer 2	*/
+	while ((immr->im_sit.sit_piscr & PISCR_PS) == 0);
+	timerp->cpmt_tgcr |= TGCR_STP2;		/* Stop  Timer 2	*/
+
+	/* re-enable external interrupts if they were on */
+	set_msr (msr_val);
+
+	/* Disable timer and PIT
+	 */
+	timer2_val = timerp->cpmt_tcn2;		/* save before reset timer */
+
+	timerp->cpmt_tgcr &= ~(TGCR_RST2 | TGCR_FRZ2 | TGCR_STP2);
+	immr->im_sit.sit_piscr &= ~PISCR_PTE;
+
+#if defined(CONFIG_SYS_8XX_XIN)
+	/* not using OSCM, using XIN, so scale appropriately */
+	return (((timer2_val + 2) / 4) * (CONFIG_SYS_8XX_XIN/512))/8192 * 100000L;
+#else
+	return ((timer2_val + 2) / 4) * 100000L;	/* convert to Hz	*/
+#endif
+}
+
+#endif
+
+void get_brgclk(uint sccr)
+{
+	uint divider = 0;
+
+	switch((sccr&SCCR_DFBRG11)>>11){
+		case 0:
+			divider = 1;
+			break;
+		case 1:
+			divider = 4;
+			break;
+		case 2:
+			divider = 16;
+			break;
+		case 3:
+			divider = 64;
+			break;
+	}
+	gd->brg_clk = gd->cpu_clk/divider;
+}
+
+#if !defined(CONFIG_8xx_CPUCLK_DEFAULT)
+
+/*
+ * get_clocks() fills in gd->cpu_clock depending on CONFIG_8xx_GCLK_FREQ
+ * or (if it is not defined) measure_gclk() (which uses the ref clock)
+ * from above.
+ */
+int get_clocks (void)
+{
+	uint immr = get_immr (0);	/* Return full IMMR contents */
+	volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
+	uint sccr = immap->im_clkrst.car_sccr;
+	/*
+	 * If for some reason measuring the gclk frequency won't
+	 * work, we return the hardwired value.
+	 * (For example, the cogent CMA286-60 CPU module has no
+	 * separate oscillator for PITRTCLK)
+	 */
+#if defined(CONFIG_8xx_GCLK_FREQ)
+	gd->cpu_clk = CONFIG_8xx_GCLK_FREQ;
+#elif defined(CONFIG_8xx_OSCLK)
+#define PLPRCR_val(a) ((pll & PLPRCR_ ## a ## _MSK) >> PLPRCR_ ## a ## _SHIFT)
+	uint pll = immap->im_clkrst.car_plprcr;
+	uint clk;
+
+	if ((immr & 0x0FFF) >= MPC8xx_NEW_CLK) { /* MPC866/87x/88x series */
+		clk = ((CONFIG_8xx_OSCLK / (PLPRCR_val(PDF)+1)) *
+		       (PLPRCR_val(MFI) + PLPRCR_val(MFN) / (PLPRCR_val(MFD)+1))) /
+			(1<<PLPRCR_val(S));
+	} else {
+		clk = CONFIG_8xx_OSCLK * (PLPRCR_val(MF)+1);
+	}
+	if (pll & PLPRCR_CSRC) {	/* Low frequency division factor is used  */
+		gd->cpu_clk = clk / (2 << ((sccr >> 8) & 7));
+	} else {			/* High frequency division factor is used */
+		gd->cpu_clk = clk / (1 << ((sccr >> 5) & 7));
+	}
+#else
+	gd->cpu_clk = measure_gclk();
+#endif /* CONFIG_8xx_GCLK_FREQ */
+
+	if ((sccr & SCCR_EBDF11) == 0) {
+		/* No Bus Divider active */
+		gd->bus_clk = gd->cpu_clk;
+	} else {
+		/* The MPC8xx has only one BDF: half clock speed */
+		gd->bus_clk = gd->cpu_clk / 2;
+	}
+
+	get_brgclk(sccr);
+
+	return (0);
+}
+
+#else /* CONFIG_8xx_CPUCLK_DEFAULT defined, use dynamic clock setting */
+
+static long init_pll_866 (long clk);
+
+/* This function sets up PLL (init_pll_866() is called) and
+ * fills gd->cpu_clk and gd->bus_clk according to the environment
+ * variable 'cpuclk' or to CONFIG_8xx_CPUCLK_DEFAULT (if 'cpuclk'
+ * contains invalid value).
+ * This functions requires an MPC866 or newer series CPU.
+ */
+int get_clocks_866 (void)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	char		  tmp[64];
+	long		  cpuclk = 0;
+	long		  sccr_reg;
+
+	if (getenv_r ("cpuclk", tmp, sizeof (tmp)) > 0)
+		cpuclk = simple_strtoul (tmp, NULL, 10) * 1000000;
+
+	if ((CONFIG_SYS_8xx_CPUCLK_MIN > cpuclk) || (CONFIG_SYS_8xx_CPUCLK_MAX < cpuclk))
+		cpuclk = CONFIG_8xx_CPUCLK_DEFAULT;
+
+	gd->cpu_clk = init_pll_866 (cpuclk);
+#if defined(CONFIG_SYS_MEASURE_CPUCLK)
+	gd->cpu_clk = measure_gclk ();
+#endif
+
+	get_brgclk(immr->im_clkrst.car_sccr);
+
+	/* if cpu clock <= 66 MHz then set bus division factor to 1,
+	 * otherwise set it to 2
+	 */
+	sccr_reg = immr->im_clkrst.car_sccr;
+	sccr_reg &= ~SCCR_EBDF11;
+
+	if (gd->cpu_clk <= 66000000) {
+		sccr_reg |= SCCR_EBDF00;	/* bus division factor = 1 */
+		gd->bus_clk = gd->cpu_clk;
+	} else {
+		sccr_reg |= SCCR_EBDF01;	/* bus division factor = 2 */
+		gd->bus_clk = gd->cpu_clk / 2;
+	}
+	immr->im_clkrst.car_sccr = sccr_reg;
+
+	return (0);
+}
+
+/* Adjust sdram refresh rate to actual CPU clock.
+ */
+int sdram_adjust_866 (void)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	long		  mamr;
+
+	mamr = immr->im_memctl.memc_mamr;
+	mamr &= ~MAMR_PTA_MSK;
+	mamr |= ((gd->cpu_clk / CONFIG_SYS_PTA_PER_CLK) << MAMR_PTA_SHIFT);
+	immr->im_memctl.memc_mamr = mamr;
+
+	return (0);
+}
+
+/* Configure PLL for MPC866/859/885 CPU series
+ * PLL multiplication factor is set to the value nearest to the desired clk,
+ * assuming a oscclk of 10 MHz.
+ */
+static long init_pll_866 (long clk)
+{
+	extern void plprcr_write_866 (long);
+
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	long		  n, plprcr;
+	char		  mfi, mfn, mfd, s, pdf;
+	long		  step_mfi, step_mfn;
+
+	if (clk < 20000000) {
+		clk *= 2;
+		pdf = 1;
+	} else {
+		pdf = 0;
+	}
+
+	if (clk < 40000000) {
+		s = 2;
+		step_mfi = CONFIG_8xx_OSCLK / 4;
+		mfd = 7;
+		step_mfn = CONFIG_8xx_OSCLK / 30;
+	} else if (clk < 80000000) {
+		s = 1;
+		step_mfi = CONFIG_8xx_OSCLK / 2;
+		mfd = 14;
+		step_mfn = CONFIG_8xx_OSCLK / 30;
+	} else {
+		s = 0;
+		step_mfi = CONFIG_8xx_OSCLK;
+		mfd = 29;
+		step_mfn = CONFIG_8xx_OSCLK / 30;
+	}
+
+	/* Calculate integer part of multiplication factor
+	 */
+	n = clk / step_mfi;
+	mfi = (char)n;
+
+	/* Calculate numerator of fractional part of multiplication factor
+	 */
+	n = clk - (n * step_mfi);
+	mfn = (char)(n / step_mfn);
+
+	/* Calculate effective clk
+	 */
+	n = ((mfi * step_mfi) + (mfn * step_mfn)) / (pdf + 1);
+
+	immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
+
+	plprcr = (immr->im_clkrst.car_plprcr & ~(PLPRCR_MFN_MSK
+			| PLPRCR_MFD_MSK | PLPRCR_S_MSK
+			| PLPRCR_MFI_MSK | PLPRCR_DBRMO
+			| PLPRCR_PDF_MSK))
+			| (mfn << PLPRCR_MFN_SHIFT)
+			| (mfd << PLPRCR_MFD_SHIFT)
+			| (s << PLPRCR_S_SHIFT)
+			| (mfi << PLPRCR_MFI_SHIFT)
+			| (pdf << PLPRCR_PDF_SHIFT);
+
+	if( (mfn > 0) && ((mfd / mfn) > 10) )
+		plprcr |= PLPRCR_DBRMO;
+
+	plprcr_write_866 (plprcr);		/* set value using SIU4/9 workaround */
+	immr->im_clkrstk.cark_plprcrk = 0x00000000;
+
+	return (n);
+}
+
+#endif /* CONFIG_8xx_CPUCLK_DEFAULT */
+
+#if defined(CONFIG_TQM8xxL) && !defined(CONFIG_TQM866M) \
+    && !defined(CONFIG_TQM885D)
+/*
+ * Adjust sdram refresh rate to actual CPU clock
+ * and set timebase source according to actual CPU clock
+ */
+int adjust_sdram_tbs_8xx (void)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	long		  mamr;
+	long              sccr;
+
+	mamr = immr->im_memctl.memc_mamr;
+	mamr &= ~MAMR_PTA_MSK;
+	mamr |= ((gd->cpu_clk / CONFIG_SYS_PTA_PER_CLK) << MAMR_PTA_SHIFT);
+	immr->im_memctl.memc_mamr = mamr;
+
+	if (gd->cpu_clk < 67000000) {
+		sccr = immr->im_clkrst.car_sccr;
+		sccr |= SCCR_TBS;
+		immr->im_clkrst.car_sccr = sccr;
+	}
+
+	return (0);
+}
+#endif /* CONFIG_TQM8xxL/M, !TQM866M, !TQM885D */
+
+/* ------------------------------------------------------------------------- */
diff --git a/arch/powerpc/cpu/mpc8xx/spi.c b/arch/powerpc/cpu/mpc8xx/spi.c
new file mode 100644
index 0000000..b2ac23e
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/spi.c
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 2001 Navin Boppuri / Prashant Patel
+ *	<nboppuri@trinetcommunication.com>,
+ *	<pmpatel@trinetcommunication.com>
+ * Copyright (c) 2001 Gerd Mennchen <Gerd.Mennchen@icn.siemens.de>
+ * Copyright (c) 2001 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * MPC8xx CPM SPI interface.
+ *
+ * Parts of this code are probably not portable and/or specific to
+ * the board which I used for the tests. Please send fixes/complaints
+ * to wd@denx.de
+ *
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <commproc.h>
+#include <linux/ctype.h>
+#include <malloc.h>
+#include <post.h>
+#include <serial.h>
+
+#if (defined(CONFIG_SPI)) || (CONFIG_POST & CONFIG_SYS_POST_SPI)
+
+/* Warning:
+ * You cannot enable DEBUG for early system initalization, i. e. when
+ * this driver is used to read environment parameters like "baudrate"
+ * from EEPROM which are used to initialize the serial port which is
+ * needed to print the debug messages...
+ */
+#undef	DEBUG
+
+#define SPI_EEPROM_WREN		0x06
+#define SPI_EEPROM_RDSR		0x05
+#define SPI_EEPROM_READ		0x03
+#define SPI_EEPROM_WRITE	0x02
+
+/* ---------------------------------------------------------------
+ * Offset for initial SPI buffers in DPRAM:
+ * We need a 520 byte scratch DPRAM area to use at an early stage.
+ * It is used between the two initialization calls (spi_init_f()
+ * and spi_init_r()).
+ * The value 0xb00 makes it far enough from the start of the data
+ * area (as well as from the stack pointer).
+ * --------------------------------------------------------------- */
+#ifndef	CONFIG_SYS_SPI_INIT_OFFSET
+#define	CONFIG_SYS_SPI_INIT_OFFSET	0xB00
+#endif
+
+#ifdef	DEBUG
+
+#define	DPRINT(a)	printf a;
+/* -----------------------------------------------
+ * Helper functions to peek into tx and rx buffers
+ * ----------------------------------------------- */
+static const char * const hex_digit = "0123456789ABCDEF";
+
+static char quickhex (int i)
+{
+	return hex_digit[i];
+}
+
+static void memdump (void *pv, int num)
+{
+	int i;
+	unsigned char *pc = (unsigned char *) pv;
+
+	for (i = 0; i < num; i++)
+		printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f));
+	printf ("\t");
+	for (i = 0; i < num; i++)
+		printf ("%c", isprint (pc[i]) ? pc[i] : '.');
+	printf ("\n");
+}
+#else	/* !DEBUG */
+
+#define	DPRINT(a)
+
+#endif	/* DEBUG */
+
+/* -------------------
+ * Function prototypes
+ * ------------------- */
+void spi_init (void);
+
+ssize_t spi_read (uchar *, int, uchar *, int);
+ssize_t spi_write (uchar *, int, uchar *, int);
+ssize_t spi_xfer (size_t);
+
+/* -------------------
+ * Variables
+ * ------------------- */
+
+#define MAX_BUFFER	0x104
+
+/* ----------------------------------------------------------------------
+ * Initially we place the RX and TX buffers at a fixed location in DPRAM!
+ * ---------------------------------------------------------------------- */
+static uchar *rxbuf =
+  (uchar *)&((cpm8xx_t *)&((immap_t *)CONFIG_SYS_IMMR)->im_cpm)->cp_dpmem
+			[CONFIG_SYS_SPI_INIT_OFFSET];
+static uchar *txbuf =
+  (uchar *)&((cpm8xx_t *)&((immap_t *)CONFIG_SYS_IMMR)->im_cpm)->cp_dpmem
+			[CONFIG_SYS_SPI_INIT_OFFSET+MAX_BUFFER];
+
+/* **************************************************************************
+ *
+ *  Function:    spi_init_f
+ *
+ *  Description: Init SPI-Controller (ROM part)
+ *
+ *  return:      ---
+ *
+ * *********************************************************************** */
+void spi_init_f (void)
+{
+	unsigned int dpaddr;
+
+	volatile spi_t *spi;
+	volatile immap_t *immr;
+	volatile cpic8xx_t *cpi;
+	volatile cpm8xx_t *cp;
+	volatile iop8xx_t *iop;
+	volatile cbd_t *tbdf, *rbdf;
+
+	immr = (immap_t *)  CONFIG_SYS_IMMR;
+	cpi  = (cpic8xx_t *)&immr->im_cpic;
+	iop  = (iop8xx_t *) &immr->im_ioport;
+	cp   = (cpm8xx_t *) &immr->im_cpm;
+
+#ifdef CONFIG_SYS_SPI_UCODE_PATCH
+	spi  = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase];
+#else
+	spi  = (spi_t *)&cp->cp_dparam[PROFF_SPI];
+	/* Disable relocation */
+	spi->spi_rpbase = 0;
+#endif
+
+/* 1 */
+	/* ------------------------------------------------
+	 * Initialize Port B SPI pins -> page 34-8 MPC860UM
+	 * (we are only in Master Mode !)
+	 * ------------------------------------------------ */
+
+	/* --------------------------------------------
+	 * GPIO or per. Function
+	 * PBPAR[28] = 1 [0x00000008] -> PERI: (SPIMISO)
+	 * PBPAR[29] = 1 [0x00000004] -> PERI: (SPIMOSI)
+	 * PBPAR[30] = 1 [0x00000002] -> PERI: (SPICLK)
+	 * PBPAR[31] = 0 [0x00000001] -> GPIO: (CS for PCUE/CCM-EEPROM)
+	 * -------------------------------------------- */
+	cp->cp_pbpar |=  0x0000000E;	/* set  bits	*/
+	cp->cp_pbpar &= ~0x00000001;	/* reset bit	*/
+
+	/* ----------------------------------------------
+	 * In/Out or per. Function 0/1
+	 * PBDIR[28] = 1 [0x00000008] -> PERI1: SPIMISO
+	 * PBDIR[29] = 1 [0x00000004] -> PERI1: SPIMOSI
+	 * PBDIR[30] = 1 [0x00000002] -> PERI1: SPICLK
+	 * PBDIR[31] = 1 [0x00000001] -> GPIO OUT: CS for PCUE/CCM-EEPROM
+	 * ---------------------------------------------- */
+	cp->cp_pbdir |= 0x0000000F;
+
+	/* ----------------------------------------------
+	 * open drain or active output
+	 * PBODR[28] = 1 [0x00000008] -> open drain: SPIMISO
+	 * PBODR[29] = 0 [0x00000004] -> active output SPIMOSI
+	 * PBODR[30] = 0 [0x00000002] -> active output: SPICLK
+	 * PBODR[31] = 0 [0x00000001] -> active output: GPIO OUT: CS for PCUE/CCM
+	 * ---------------------------------------------- */
+
+	cp->cp_pbodr |=  0x00000008;
+	cp->cp_pbodr &= ~0x00000007;
+
+	/* Initialize the parameter ram.
+	 * We need to make sure many things are initialized to zero
+	 */
+	spi->spi_rstate	= 0;
+	spi->spi_rdp	= 0;
+	spi->spi_rbptr	= 0;
+	spi->spi_rbc	= 0;
+	spi->spi_rxtmp	= 0;
+	spi->spi_tstate	= 0;
+	spi->spi_tdp	= 0;
+	spi->spi_tbptr	= 0;
+	spi->spi_tbc	= 0;
+	spi->spi_txtmp	= 0;
+
+	/* Allocate space for one transmit and one receive buffer
+	 * descriptor in the DP ram
+	 */
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+	dpaddr = dpram_alloc_align (sizeof(cbd_t)*2, 8);
+#else
+	dpaddr = CPM_SPI_BASE;
+#endif
+
+/* 3 */
+	/* Set up the SPI parameters in the parameter ram */
+	spi->spi_rbase = dpaddr;
+	spi->spi_tbase = dpaddr + sizeof (cbd_t);
+
+	/***********IMPORTANT******************/
+
+	/*
+	 * Setting transmit and receive buffer descriptor pointers
+	 * initially to rbase and tbase. Only the microcode patches
+	 * documentation talks about initializing this pointer. This
+	 * is missing from the sample I2C driver. If you dont
+	 * initialize these pointers, the kernel hangs.
+	 */
+	spi->spi_rbptr = spi->spi_rbase;
+	spi->spi_tbptr = spi->spi_tbase;
+
+/* 4 */
+#ifdef CONFIG_SYS_SPI_UCODE_PATCH
+	/*
+	 *  Initialize required parameters if using microcode patch.
+	 */
+	spi->spi_rstate = 0;
+	spi->spi_tstate = 0;
+#else
+	/* Init SPI Tx + Rx Parameters */
+	while (cp->cp_cpcr & CPM_CR_FLG)
+		;
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SPI, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG)
+		;
+#endif	/* CONFIG_SYS_SPI_UCODE_PATCH */
+
+/* 5 */
+	/* Set SDMA configuration register */
+	immr->im_siu_conf.sc_sdcr = 0x0001;
+
+/* 6 */
+	/* Set to big endian. */
+	spi->spi_tfcr = SMC_EB;
+	spi->spi_rfcr = SMC_EB;
+
+/* 7 */
+	/* Set maximum receive size. */
+	spi->spi_mrblr = MAX_BUFFER;
+
+/* 8 + 9 */
+	/* tx and rx buffer descriptors */
+	tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase];
+	rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase];
+
+	tbdf->cbd_sc &= ~BD_SC_READY;
+	rbdf->cbd_sc &= ~BD_SC_EMPTY;
+
+	/* Set the bd's rx and tx buffer address pointers */
+	rbdf->cbd_bufaddr = (ulong) rxbuf;
+	tbdf->cbd_bufaddr = (ulong) txbuf;
+
+/* 10 + 11 */
+	cp->cp_spim = 0;			/* Mask  all SPI events */
+	cp->cp_spie = SPI_EMASK;		/* Clear all SPI events	*/
+
+	return;
+}
+
+/* **************************************************************************
+ *
+ *  Function:    spi_init_r
+ *
+ *  Description: Init SPI-Controller (RAM part) -
+ *		 The malloc engine is ready and we can move our buffers to
+ *		 normal RAM
+ *
+ *  return:      ---
+ *
+ * *********************************************************************** */
+void spi_init_r (void)
+{
+	volatile cpm8xx_t *cp;
+	volatile spi_t *spi;
+	volatile immap_t *immr;
+	volatile cbd_t *tbdf, *rbdf;
+
+	immr = (immap_t *)  CONFIG_SYS_IMMR;
+	cp   = (cpm8xx_t *) &immr->im_cpm;
+
+#ifdef CONFIG_SYS_SPI_UCODE_PATCH
+	spi  = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase];
+#else
+	spi  = (spi_t *)&cp->cp_dparam[PROFF_SPI];
+	/* Disable relocation */
+	spi->spi_rpbase = 0;
+#endif
+
+	/* tx and rx buffer descriptors */
+	tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase];
+	rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase];
+
+	/* Allocate memory for RX and TX buffers */
+	rxbuf = (uchar *) malloc (MAX_BUFFER);
+	txbuf = (uchar *) malloc (MAX_BUFFER);
+
+	rbdf->cbd_bufaddr = (ulong) rxbuf;
+	tbdf->cbd_bufaddr = (ulong) txbuf;
+
+	return;
+}
+
+/****************************************************************************
+ *  Function:    spi_write
+ **************************************************************************** */
+ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
+{
+	int i;
+
+	memset(rxbuf, 0, MAX_BUFFER);
+	memset(txbuf, 0, MAX_BUFFER);
+	*txbuf = SPI_EEPROM_WREN;		/* write enable		*/
+	spi_xfer(1);
+	memcpy(txbuf, addr, alen);
+	*txbuf = SPI_EEPROM_WRITE;		/* WRITE memory array	*/
+	memcpy(alen + txbuf, buffer, len);
+	spi_xfer(alen + len);
+						/* ignore received data	*/
+	for (i = 0; i < 1000; i++) {
+		*txbuf = SPI_EEPROM_RDSR;	/* read status		*/
+		txbuf[1] = 0;
+		spi_xfer(2);
+		if (!(rxbuf[1] & 1)) {
+			break;
+		}
+		udelay(1000);
+	}
+	if (i >= 1000) {
+		printf ("*** spi_write: Time out while writing!\n");
+	}
+
+	return len;
+}
+
+/****************************************************************************
+ *  Function:    spi_read
+ **************************************************************************** */
+ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len)
+{
+	memset(rxbuf, 0, MAX_BUFFER);
+	memset(txbuf, 0, MAX_BUFFER);
+	memcpy(txbuf, addr, alen);
+	*txbuf = SPI_EEPROM_READ;		/* READ memory array	*/
+
+	/*
+	 * There is a bug in 860T (?) that cuts the last byte of input
+	 * if we're reading into DPRAM. The solution we choose here is
+	 * to always read len+1 bytes (we have one extra byte at the
+	 * end of the buffer).
+	 */
+	spi_xfer(alen + len + 1);
+	memcpy(buffer, alen + rxbuf, len);
+
+	return len;
+}
+
+/****************************************************************************
+ *  Function:    spi_xfer
+ **************************************************************************** */
+ssize_t spi_xfer (size_t count)
+{
+	volatile immap_t *immr;
+	volatile cpm8xx_t *cp;
+	volatile spi_t *spi;
+	cbd_t *tbdf, *rbdf;
+	ushort loop;
+	int tm;
+
+	DPRINT (("*** spi_xfer entered ***\n"));
+
+	immr = (immap_t *) CONFIG_SYS_IMMR;
+	cp   = (cpm8xx_t *) &immr->im_cpm;
+
+#ifdef CONFIG_SYS_SPI_UCODE_PATCH
+	spi  = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase];
+#else
+	spi  = (spi_t *)&cp->cp_dparam[PROFF_SPI];
+	/* Disable relocation */
+	spi->spi_rpbase = 0;
+#endif
+
+	tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase];
+	rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase];
+
+	/* Set CS for device */
+	cp->cp_pbdat &= ~0x0001;
+
+	/* Setting tx bd status and data length */
+	tbdf->cbd_sc  = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP;
+	tbdf->cbd_datlen = count;
+
+	DPRINT (("*** spi_xfer: Bytes to be xferred: %d ***\n",
+							tbdf->cbd_datlen));
+
+	/* Setting rx bd status and data length */
+	rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+	rbdf->cbd_datlen = 0;	 /* rx length has no significance */
+
+	loop = cp->cp_spmode & SPMODE_LOOP;
+	cp->cp_spmode = /*SPMODE_DIV16	|*/	/* BRG/16 mode not used here */
+			loop		|
+			SPMODE_REV	|
+			SPMODE_MSTR	|
+			SPMODE_EN	|
+			SPMODE_LEN(8)	|	/* 8 Bits per char */
+			SPMODE_PM(0x8) ;	/* medium speed */
+	cp->cp_spim = 0;			/* Mask  all SPI events */
+	cp->cp_spie = SPI_EMASK;		/* Clear all SPI events	*/
+
+	/* start spi transfer */
+	DPRINT (("*** spi_xfer: Performing transfer ...\n"));
+	cp->cp_spcom |= SPI_STR;		/* Start transmit */
+
+	/* --------------------------------
+	 * Wait for SPI transmit to get out
+	 * or time out (1 second = 1000 ms)
+	 * -------------------------------- */
+	for (tm=0; tm<1000; ++tm) {
+		if (cp->cp_spie & SPI_TXB) {	/* Tx Buffer Empty */
+			DPRINT (("*** spi_xfer: Tx buffer empty\n"));
+			break;
+		}
+		if ((tbdf->cbd_sc & BD_SC_READY) == 0) {
+			DPRINT (("*** spi_xfer: Tx BD done\n"));
+			break;
+		}
+		udelay (1000);
+	}
+	if (tm >= 1000) {
+		printf ("*** spi_xfer: Time out while xferring to/from SPI!\n");
+	}
+	DPRINT (("*** spi_xfer: ... transfer ended\n"));
+
+#ifdef	DEBUG
+	printf ("\nspi_xfer: txbuf after xfer\n");
+	memdump ((void *) txbuf, 16);	/* dump of txbuf before transmit */
+	printf ("spi_xfer: rxbuf after xfer\n");
+	memdump ((void *) rxbuf, 16);	/* dump of rxbuf after transmit */
+	printf ("\n");
+#endif
+
+	/* Clear CS for device */
+	cp->cp_pbdat |= 0x0001;
+
+	return count;
+}
+#endif	/* CONFIG_SPI || (CONFIG_POST & CONFIG_SYS_POST_SPI) */
+
+/*
+ * SPI test
+ *
+ * The Serial Peripheral Interface (SPI) is tested in the local loopback mode.
+ * The interface is configured accordingly and several packets
+ * are transfered. The configurable test parameters are:
+ *   TEST_MIN_LENGTH - minimum size of packet to transfer
+ *   TEST_MAX_LENGTH - maximum size of packet to transfer
+ *   TEST_NUM - number of tests
+ */
+
+#if CONFIG_POST & CONFIG_SYS_POST_SPI
+
+#define TEST_MIN_LENGTH		1
+#define TEST_MAX_LENGTH		MAX_BUFFER
+#define TEST_NUM		1
+
+static void packet_fill (char * packet, int length)
+{
+	char c = (char) length;
+	int i;
+
+	for (i = 0; i < length; i++)
+	{
+	    packet[i] = c++;
+	}
+}
+
+static int packet_check (char * packet, int length)
+{
+	char c = (char) length;
+	int i;
+
+	for (i = 0; i < length; i++) {
+	    if (packet[i] != c++) return -1;
+	}
+
+	return 0;
+}
+
+int spi_post_test (int flags)
+{
+	int res = -1;
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+	volatile cpm8xx_t *cp = (cpm8xx_t *) & immr->im_cpm;
+	int i;
+	int l;
+
+	spi_init_f ();
+	spi_init_r ();
+
+	cp->cp_spmode |= SPMODE_LOOP;
+
+	for (i = 0; i < TEST_NUM; i++) {
+		for (l = TEST_MIN_LENGTH; l <= TEST_MAX_LENGTH; l += 8) {
+			packet_fill ((char *)txbuf, l);
+
+			spi_xfer (l);
+
+			if (packet_check ((char *)rxbuf, l) < 0) {
+				goto Done;
+			}
+		}
+	}
+
+	res = 0;
+
+      Done:
+
+	cp->cp_spmode &= ~SPMODE_LOOP;
+
+	/*
+	 * SCC2 parameter RAM space overlaps
+	 * the SPI parameter RAM space. So we need to restore
+	 * the SCC2 configuration if it is used by UART.
+	 */
+
+#if !defined(CONFIG_8xx_CONS_NONE)
+	serial_reinit_all ();
+#endif
+
+	if (res != 0) {
+		post_log ("SPI test failed\n");
+	}
+
+	return res;
+}
+#endif	/* CONFIG_POST & CONFIG_SYS_POST_SPI */
diff --git a/arch/powerpc/cpu/mpc8xx/start.S b/arch/powerpc/cpu/mpc8xx/start.S
new file mode 100644
index 0000000..7cf602f
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/start.S
@@ -0,0 +1,684 @@
+/*
+ *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*  U-Boot - Startup Code for PowerPC based Embedded Boards
+ *
+ *
+ *  The processor starts at 0x00000100 and the code is executed
+ *  from flash. The code is organized to be at an other address
+ *  in memory, but as long we don't jump around before relocating,
+ *  board_init lies at a quite high address and when the cpu has
+ *  jumped there, everything is ok.
+ *  This works because the cpu gives the FLASH (CS0) the whole
+ *  address space at startup, and board_init lies as a echo of
+ *  the flash somewhere up there in the memory map.
+ *
+ *  board_init will change CS0 to be positioned at the correct
+ *  address and (s)dram will be positioned at address 0
+ */
+#include <config.h>
+#include <mpc8xx.h>
+#include <timestamp.h>
+#include <version.h>
+
+#define CONFIG_8xx 1		/* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1	/* avoid reading Linux autoconf.h file	*/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef  CONFIG_IDENT_STRING
+#define  CONFIG_IDENT_STRING ""
+#endif
+
+/* We don't want the  MMU yet.
+*/
+#undef	MSR_KERNEL
+#define MSR_KERNEL ( MSR_ME | MSR_RI )	/* Machine Check and Recoverable Interr. */
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+	START_GOT
+	GOT_ENTRY(_GOT2_TABLE_)
+	GOT_ENTRY(_FIXUP_TABLE_)
+
+	GOT_ENTRY(_start)
+	GOT_ENTRY(_start_of_vectors)
+	GOT_ENTRY(_end_of_vectors)
+	GOT_ENTRY(transfer_to_handler)
+
+	GOT_ENTRY(__init_end)
+	GOT_ENTRY(_end)
+	GOT_ENTRY(__bss_start)
+	END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+	.text
+	.long	0x27051956		/* U-Boot Magic Number			*/
+	.globl	version_string
+version_string:
+	.ascii U_BOOT_VERSION
+	.ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
+	.ascii CONFIG_IDENT_STRING, "\0"
+
+	. = EXC_OFF_SYS_RESET
+	.globl	_start
+_start:
+	lis	r3, CONFIG_SYS_IMMR@h		/* position IMMR */
+	mtspr	638, r3
+	li	r21, BOOTFLAG_COLD	/* Normal Power-On: Boot from FLASH	*/
+	b	boot_cold
+
+	. = EXC_OFF_SYS_RESET + 0x10
+
+	.globl	_start_warm
+_start_warm:
+	li	r21, BOOTFLAG_WARM	/* Software reboot			*/
+	b	boot_warm
+
+boot_cold:
+boot_warm:
+
+	/* Initialize machine status; enable machine check interrupt		*/
+	/*----------------------------------------------------------------------*/
+	li	r3, MSR_KERNEL		/* Set ME, RI flags */
+	mtmsr	r3
+	mtspr	SRR1, r3		/* Make SRR1 match MSR */
+
+	mfspr	r3, ICR			/* clear Interrupt Cause Register */
+
+	/* Initialize debug port registers					*/
+	/*----------------------------------------------------------------------*/
+	xor	r0, r0, r0		/* Clear R0 */
+	mtspr	LCTRL1, r0		/* Initialize debug port regs */
+	mtspr	LCTRL2, r0
+	mtspr	COUNTA, r0
+	mtspr	COUNTB, r0
+
+	/* Reset the caches							*/
+	/*----------------------------------------------------------------------*/
+
+	mfspr	r3, IC_CST		/* Clear error bits */
+	mfspr	r3, DC_CST
+
+	lis	r3, IDC_UNALL@h		/* Unlock all */
+	mtspr	IC_CST, r3
+	mtspr	DC_CST, r3
+
+	lis	r3, IDC_INVALL@h	/* Invalidate all */
+	mtspr	IC_CST, r3
+	mtspr	DC_CST, r3
+
+	lis	r3, IDC_DISABLE@h	/* Disable data cache */
+	mtspr	DC_CST, r3
+
+#if !defined(CONFIG_SYS_DELAYED_ICACHE)
+					/* On IP860 and PCU E,
+					 * we cannot enable IC yet
+					 */
+	lis	r3, IDC_ENABLE@h	/* Enable instruction cache */
+#endif
+	mtspr	IC_CST, r3
+
+	/* invalidate all tlb's							*/
+	/*----------------------------------------------------------------------*/
+
+	tlbia
+	isync
+
+	/*
+	 * Calculate absolute address in FLASH and jump there
+	 *----------------------------------------------------------------------*/
+
+	lis	r3, CONFIG_SYS_MONITOR_BASE@h
+	ori	r3, r3, CONFIG_SYS_MONITOR_BASE@l
+	addi	r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+	mtlr	r3
+	blr
+
+in_flash:
+
+	/* initialize some SPRs that are hard to access from C			*/
+	/*----------------------------------------------------------------------*/
+
+	lis	r3, CONFIG_SYS_IMMR@h		/* pass IMMR as arg1 to C routine */
+	ori	r1, r3, CONFIG_SYS_INIT_SP_OFFSET /* set up the stack in internal DPRAM */
+	/* Note: R0 is still 0 here */
+	stwu	r0, -4(r1)		/* clear final stack frame so that	*/
+	stwu	r0, -4(r1)		/* stack backtraces terminate cleanly	*/
+
+	/*
+	 * Disable serialized ifetch and show cycles
+	 * (i.e. set processor to normal mode).
+	 * This is also a silicon bug workaround, see errata
+	 */
+
+	li	r2, 0x0007
+	mtspr	ICTRL, r2
+
+	/* Set up debug mode entry */
+
+	lis	r2, CONFIG_SYS_DER@h
+	ori	r2, r2, CONFIG_SYS_DER@l
+	mtspr	DER, r2
+
+	/* let the C-code set up the rest					*/
+	/*									*/
+	/* Be careful to keep code relocatable !				*/
+	/*----------------------------------------------------------------------*/
+
+	GET_GOT			/* initialize GOT access			*/
+
+	/* r3: IMMR */
+	bl	cpu_init_f	/* run low-level CPU init code     (from Flash)	*/
+
+	mr	r3, r21
+	/* r3: BOOTFLAG */
+	bl	board_init_f	/* run 1st part of board init code (from Flash) */
+
+
+	.globl	_start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception.  "Never" generated on the 860. */
+	STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception.  "Never" generated on the 860. */
+	STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+	STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+	. = 0x600
+Alignment:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	mfspr	r4,DAR
+	stw	r4,_DAR(r21)
+	mfspr	r5,DSISR
+	stw	r5,_DSISR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+	. = 0x700
+ProgramCheck:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+		MSR_KERNEL, COPY_EE)
+
+	/* No FPU on MPC8xx.  This exception is not supposed to happen.
+	*/
+	STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+	/* I guess we could implement decrementer, and may have
+	 * to someday for timekeeping.
+	 */
+	STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+	STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+	STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+	STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+	STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+	STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+	/* On the MPC8xx, this is a software emulation interrupt.  It occurs
+	 * for all unimplemented and illegal instructions.
+	 */
+	STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
+
+	STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
+	STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
+
+	STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+	STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+	STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+	STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+	STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+	STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+	STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+
+	STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
+	STD_EXCEPTION(0x1d00, InstructionBreakpoint, DebugException)
+	STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
+	STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
+
+
+	.globl	_end_of_vectors
+_end_of_vectors:
+
+
+	. = 0x2000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+	.globl	transfer_to_handler
+transfer_to_handler:
+	stw	r22,_NIP(r21)
+	lis	r22,MSR_POW@h
+	andc	r23,r23,r22
+	stw	r23,_MSR(r21)
+	SAVE_GPR(7, r21)
+	SAVE_4GPRS(8, r21)
+	SAVE_8GPRS(12, r21)
+	SAVE_8GPRS(24, r21)
+	mflr	r23
+	andi.	r24,r23,0x3f00		/* get vector offset */
+	stw	r24,TRAP(r21)
+	li	r22,0
+	stw	r22,RESULT(r21)
+	mtspr	SPRG2,r22		/* r1 is now kernel sp */
+	lwz	r24,0(r23)		/* virtual address of handler */
+	lwz	r23,4(r23)		/* where to go when done */
+	mtspr	SRR0,r24
+	mtspr	SRR1,r20
+	mtlr	r23
+	SYNC
+	rfi				/* jump to handler, enable MMU */
+
+int_return:
+	mfmsr	r28			/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC				/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)		/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SRR0,r2
+	mtspr	SRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfi
+
+/* Cache functions.
+*/
+	.globl	icache_enable
+icache_enable:
+	SYNC
+	lis	r3, IDC_INVALL@h
+	mtspr	IC_CST, r3
+	lis	r3, IDC_ENABLE@h
+	mtspr	IC_CST, r3
+	blr
+
+	.globl	icache_disable
+icache_disable:
+	SYNC
+	lis	r3, IDC_DISABLE@h
+	mtspr	IC_CST, r3
+	blr
+
+	.globl	icache_status
+icache_status:
+	mfspr	r3, IC_CST
+	srwi	r3, r3, 31	/* >>31 => select bit 0 */
+	blr
+
+	.globl	dcache_enable
+dcache_enable:
+#if 0
+	SYNC
+#endif
+#if 1
+	lis	r3, 0x0400		/* Set cache mode with MMU off */
+	mtspr	MD_CTR, r3
+#endif
+
+	lis	r3, IDC_INVALL@h
+	mtspr	DC_CST, r3
+#if 0
+	lis	r3, DC_SFWT@h
+	mtspr	DC_CST, r3
+#endif
+	lis	r3, IDC_ENABLE@h
+	mtspr	DC_CST, r3
+	blr
+
+	.globl	dcache_disable
+dcache_disable:
+	SYNC
+	lis	r3, IDC_DISABLE@h
+	mtspr	DC_CST, r3
+	lis	r3, IDC_INVALL@h
+	mtspr	DC_CST, r3
+	blr
+
+	.globl	dcache_status
+dcache_status:
+	mfspr	r3, DC_CST
+	srwi	r3, r3, 31	/* >>31 => select bit 0 */
+	blr
+
+	.globl	dc_read
+dc_read:
+	mtspr	DC_ADR, r3
+	mfspr	r3, DC_DAT
+	blr
+
+/*
+ * unsigned int get_immr (unsigned int mask)
+ *
+ * return (mask ? (IMMR & mask) : IMMR);
+ */
+	.globl	get_immr
+get_immr:
+	mr	r4,r3		/* save mask */
+	mfspr	r3, IMMR	/* IMMR */
+	cmpwi	0,r4,0		/* mask != 0 ? */
+	beq	4f
+	and	r3,r3,r4	/* IMMR & mask */
+4:
+	blr
+
+	.globl get_pvr
+get_pvr:
+	mfspr	r3, PVR
+	blr
+
+
+	.globl wr_ic_cst
+wr_ic_cst:
+	mtspr	IC_CST, r3
+	blr
+
+	.globl rd_ic_cst
+rd_ic_cst:
+	mfspr	r3, IC_CST
+	blr
+
+	.globl wr_ic_adr
+wr_ic_adr:
+	mtspr	IC_ADR, r3
+	blr
+
+
+	.globl wr_dc_cst
+wr_dc_cst:
+	mtspr	DC_CST, r3
+	blr
+
+	.globl rd_dc_cst
+rd_dc_cst:
+	mfspr	r3, DC_CST
+	blr
+
+	.globl wr_dc_adr
+wr_dc_adr:
+	mtspr	DC_ADR, r3
+	blr
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+	.globl	relocate_code
+relocate_code:
+	mr	r1,  r3		/* Set new stack pointer		*/
+	mr	r9,  r4		/* Save copy of Global Data pointer	*/
+	mr	r10, r5		/* Save copy of Destination Address	*/
+
+	GET_GOT
+	mr	r3,  r5				/* Destination Address	*/
+	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address	*/
+	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
+	lwz	r5, GOT(__init_end)
+	sub	r5, r5, r4
+	li	r6, CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size	*/
+
+	/*
+	 * Fix GOT pointer:
+	 *
+	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+	 *
+	 * Offset:
+	 */
+	sub	r15, r10, r4
+
+	/* First our own GOT */
+	add	r12, r12, r15
+	/* then the one used by the C code */
+	add	r30, r30, r15
+
+	/*
+	 * Now relocate code
+	 */
+
+	cmplw	cr1,r3,r4
+	addi	r0,r5,3
+	srwi.	r0,r0,2
+	beq	cr1,4f		/* In place copy is not necessary	*/
+	beq	7f		/* Protect against 0 count		*/
+	mtctr	r0
+	bge	cr1,2f
+
+	la	r8,-4(r4)
+	la	r7,-4(r3)
+1:	lwzu	r0,4(r8)
+	stwu	r0,4(r7)
+	bdnz	1b
+	b	4f
+
+2:	slwi	r0,r0,2
+	add	r8,r4,r0
+	add	r7,r3,r0
+3:	lwzu	r0,-4(r8)
+	stwu	r0,-4(r7)
+	bdnz	3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:	cmpwi	r6,0
+	add	r5,r3,r5
+	beq	7f		/* Always flush prefetch queue in any case */
+	subi	r0,r6,1
+	andc	r3,r3,r0
+	mr	r4,r3
+5:	dcbst	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	5b
+	sync			/* Wait for all dcbst to complete on bus */
+	mr	r4,r3
+6:	icbi	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	6b
+7:	sync			/* Wait for all icbi to complete on bus	*/
+	isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+	mtlr	r0
+	blr
+
+in_ram:
+
+	/*
+	 * Relocation Function, r12 point to got2+0x8000
+	 *
+	 * Adjust got2 pointers, no need to check for 0, this code
+	 * already puts a few entries in the table.
+	 */
+	li	r0,__got2_entries@sectoff@l
+	la	r3,GOT(_GOT2_TABLE_)
+	lwz	r11,GOT(_GOT2_TABLE_)
+	mtctr	r0
+	sub	r11,r3,r11
+	addi	r3,r3,-4
+1:	lwzu	r0,4(r3)
+	cmpwi	r0,0
+	beq-	2f
+	add	r0,r0,r11
+	stw	r0,0(r3)
+2:	bdnz	1b
+
+	/*
+	 * Now adjust the fixups and the pointers to the fixups
+	 * in case we need to move ourselves again.
+	 */
+	li	r0,__fixup_entries@sectoff@l
+	lwz	r3,GOT(_FIXUP_TABLE_)
+	cmpwi	r0,0
+	mtctr	r0
+	addi	r3,r3,-4
+	beq	4f
+3:	lwzu	r4,4(r3)
+	lwzux	r0,r4,r11
+	add	r0,r0,r11
+	stw	r10,0(r3)
+	stw	r0,0(r4)
+	bdnz	3b
+4:
+clear_bss:
+	/*
+	 * Now clear BSS segment
+	 */
+	lwz	r3,GOT(__bss_start)
+	lwz	r4,GOT(_end)
+
+	cmplw	0, r3, r4
+	beq	6f
+
+	li	r0, 0
+5:
+	stw	r0, 0(r3)
+	addi	r3, r3, 4
+	cmplw	0, r3, r4
+	bne	5b
+6:
+
+	mr	r3, r9		/* Global Data pointer		*/
+	mr	r4, r10		/* Destination Address		*/
+	bl	board_init_r
+
+	/*
+	 * Copy exception vector code to low memory
+	 *
+	 * r3: dest_addr
+	 * r7: source address, r8: end address, r9: target address
+	 */
+	.globl	trap_init
+trap_init:
+	mflr	r4			/* save link register		*/
+	GET_GOT
+	lwz	r7, GOT(_start)
+	lwz	r8, GOT(_end_of_vectors)
+
+	li	r9, 0x100		/* reset vector always at 0x100 */
+
+	cmplw	0, r7, r8
+	bgelr				/* return if r7>=r8 - just in case */
+1:
+	lwz	r0, 0(r7)
+	stw	r0, 0(r9)
+	addi	r7, r7, 4
+	addi	r9, r9, 4
+	cmplw	0, r7, r8
+	bne	1b
+
+	/*
+	 * relocate `hdlr' and `int_return' entries
+	 */
+	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+	li	r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	2b
+
+	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+	bl	trap_reloc
+
+	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	3b
+
+	li	r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector	*/
+	cmplw	0, r7, r8
+	blt	4b
+
+	mtlr	r4			/* restore link register	*/
+	blr
diff --git a/arch/powerpc/cpu/mpc8xx/traps.c b/arch/powerpc/cpu/mpc8xx/traps.c
new file mode 100644
index 0000000..343dced
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/traps.c
@@ -0,0 +1,241 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM	0x02000000
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace(unsigned long *sp)
+{
+	int cnt = 0;
+	unsigned long i;
+
+	printf("Call backtrace: ");
+	while (sp) {
+		if ((uint)sp > END_OF_MEM)
+			break;
+
+		i = sp[1];
+		if (cnt++ % 7 == 0)
+			printf("\n");
+		printf("%08lX ", i);
+		if (cnt > 32) break;
+		sp = (unsigned long *)*sp;
+	}
+	printf("\n");
+}
+
+void show_regs(struct pt_regs * regs)
+{
+	int i;
+
+	printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+	       regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+	printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+	       regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+	       regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+	       regs->msr&MSR_IR ? 1 : 0,
+	       regs->msr&MSR_DR ? 1 : 0);
+
+	printf("\n");
+	for (i = 0;  i < 32;  i++) {
+		if ((i % 8) == 0)
+		{
+			printf("GPR%02d: ", i);
+		}
+
+		printf("%08lX ", regs->gpr[i]);
+		if ((i % 8) == 7)
+		{
+			printf("\n");
+		}
+	}
+}
+
+
+void
+_exception(int signr, struct pt_regs *regs)
+{
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+void
+MachineCheckException(struct pt_regs *regs)
+{
+	unsigned long fixup;
+
+	/* Probing PCI using config cycles cause this exception
+	 * when a device is not present.  Catch it and return to
+	 * the PCI exception handler.
+	 */
+	if ((fixup = search_exception_table(regs->nip)) != 0) {
+		regs->nip = fixup;
+		return;
+	}
+
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	printf("Machine check in kernel mode.\n");
+	printf("Caused by (from msr): ");
+	printf("regs %p ",regs);
+	switch( regs->msr & 0x000F0000) {
+	case (0x80000000>>12):
+		printf("Machine check signal - probably due to mm fault\n"
+			"with mmu off\n");
+		break;
+	case (0x80000000>>13):
+		printf("Transfer error ack signal\n");
+		break;
+	case (0x80000000>>14):
+		printf("Data parity signal\n");
+		break;
+	case (0x80000000>>15):
+		printf("Address parity signal\n");
+		break;
+	default:
+		printf("Unknown values in msr\n");
+	}
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Program Check Exception");
+}
+
+void
+SoftEmuException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Software Emulation Exception");
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+	printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+	       regs->nip, regs->msr, regs->trap);
+	_exception(0, regs);
+}
+
+void
+DebugException(struct pt_regs *regs)
+{
+  printf("Debugger trap at @ %lx\n", regs->nip );
+  show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+  do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading.  If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+#if 0
+	int	retval;
+
+	__asm__ __volatile__(			\
+		"1:	lwz %0,0(%1)\n"		\
+		"	eieio\n"		\
+		"	li %0,0\n"		\
+		"2:\n"				\
+		".section .fixup,\"ax\"\n"	\
+		"3:	li %0,-1\n"		\
+		"	b 2b\n"			\
+		".section __ex_table,\"a\"\n"	\
+		"	.align 2\n"		\
+		"	.long 1b,3b\n"		\
+		".text"				\
+		: "=r" (retval) : "r"(addr));
+
+	return (retval);
+#endif
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xx/upatch.c b/arch/powerpc/cpu/mpc8xx/upatch.c
new file mode 100644
index 0000000..a8cb735
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/upatch.c
@@ -0,0 +1,194 @@
+#include <common.h>
+#include <commproc.h>
+
+#if defined(CONFIG_SYS_I2C_UCODE_PATCH) || defined(CONFIG_SYS_SPI_UCODE_PATCH) || \
+    defined(CONFIG_SYS_SMC_UCODE_PATCH)
+
+static void UcodeCopy (volatile cpm8xx_t *cpm);
+
+void cpm_load_patch (volatile immap_t *immr)
+{
+	immr->im_cpm.cp_rccr &= ~0x0003;	/* Disable microcode program area */
+
+	UcodeCopy ((cpm8xx_t *)&immr->im_cpm);	/* Copy ucode patch to DPRAM   */
+#ifdef CONFIG_SYS_SPI_UCODE_PATCH
+    {
+	volatile spi_t *spi = (spi_t *) & immr->im_cpm.cp_dparam[PROFF_SPI];
+	/* Activate the microcode per the instructions in the microcode manual */
+	/* NOTE:  We're only relocating the SPI parameters (not I2C).          */
+	immr->im_cpm.cp_cpmcr1 = 0x802a;	/* Write Trap register 1 value */
+	immr->im_cpm.cp_cpmcr2 = 0x8028;	/* Write Trap register 2 value */
+	spi->spi_rpbase = CONFIG_SYS_SPI_DPMEM_OFFSET;	/* Where to relocte SPI params */
+    }
+#endif
+
+#ifdef CONFIG_SYS_I2C_UCODE_PATCH
+    {
+	volatile iic_t *iip = (iic_t *) & immr->im_cpm.cp_dparam[PROFF_IIC];
+	/* Activate the microcode per the instructions in the microcode manual */
+	/* NOTE:  We're only relocating the I2C parameters (not SPI).          */
+	immr->im_cpm.cp_cpmcr3 = 0x802e;	/* Write Trap register 3 value */
+	immr->im_cpm.cp_cpmcr4 = 0x802c;	/* Write Trap register 4 value */
+	iip->iic_rpbase = CONFIG_SYS_I2C_DPMEM_OFFSET;	/* Where to relocte I2C params */
+    }
+#endif
+
+#ifdef CONFIG_SYS_SMC_UCODE_PATCH
+    {
+	volatile smc_uart_t *up = (smc_uart_t *) & immr->im_cpm.cp_dparam[PROFF_SMC1];
+	/* Activate the microcode per the instructions in the microcode manual */
+	/* NOTE:  We're only relocating the SMC parameters.                    */
+	immr->im_cpm.cp_cpmcr1 = 0x8080;	/* Write Trap register 1 value */
+	immr->im_cpm.cp_cpmcr2 = 0x8088;	/* Write Trap register 2 value */
+	up->smc_rpbase = CONFIG_SYS_SMC_DPMEM_OFFSET;	/* Where to relocte SMC params */
+    }
+#endif
+
+	/*
+	 * Enable DPRAM microcode to execute from the first 512 bytes
+	 * and a 256 byte extension of DPRAM.
+	 */
+#ifdef CONFIG_SYS_SMC_UCODE_PATCH
+	immr->im_cpm.cp_rccr |= 0x0002;
+#else
+	immr->im_cpm.cp_rccr |= 0x0001;
+#endif
+}
+
+#if defined(CONFIG_SYS_I2C_UCODE_PATCH) || defined(CONFIG_SYS_SPI_UCODE_PATCh)
+static ulong patch_2000[] = {
+	0x7FFFEFD9, 0x3FFD0000, 0x7FFB49F7, 0x7FF90000,
+	0x5FEFADF7, 0x5F88ADF7, 0x5FEFAFF7, 0x5F88AFF7,
+	0x3A9CFBC8, 0x77CAE1BB, 0xF4DE7FAD, 0xABAE9330,
+	0x4E08FDCF, 0x6E0FAFF8, 0x7CCF76CF, 0xFDAFF9CF,
+	0xABF88DC8, 0xAB5879F7, 0xB0927383, 0xDFD079F7,
+	0xB090E6BB, 0xE5BBE74F, 0xB3FA6F0F, 0x6FFB76CE,
+	0xEE0CF9CF, 0x2BFBEFEF, 0xCFEEF9CF, 0x76CEAD23,
+	0x90B3DF99, 0x7FDDD0C1, 0x4BF847FD, 0x7CCF76CE,
+	0xCFEF77CA, 0x7EAF7FAD, 0x7DFDF0B7, 0xEF7A7FCA,
+	0x77CAFBC8, 0x6079E722, 0xFBC85FFF, 0xDFFF5FB3,
+	0xFFFBFBC8, 0xF3C894A5, 0xE7C9EDF9, 0x7F9A7FAD,
+	0x5F36AFE8, 0x5F5BFFDF, 0xDF95CB9E, 0xAF7D5FC3,
+	0xAFED8C1B, 0x5FC3AFDD, 0x5FC5DF99, 0x7EFDB0B3,
+	0x5FB3FFFE, 0xABAE5FB3, 0xFFFE5FD0, 0x600BE6BB,
+	0x600B5FD0, 0xDFC827FB, 0xEFDF5FCA, 0xCFDE3A9C,
+	0xE7C9EDF9, 0xF3C87F9E, 0x54CA7FED, 0x2D3A3637,
+	0x756F7E9A, 0xF1CE37EF, 0x2E677FEE, 0x10EBADF8,
+	0xEFDECFEA, 0xE52F7D9F, 0xE12BF1CE, 0x5F647E9A,
+	0x4DF8CFEA, 0x5F717D9B, 0xEFEECFEA, 0x5F73E522,
+	0xEFDE5F73, 0xCFDA0B61, 0x7385DF61, 0xE7C9EDF9,
+	0x7E9A30D5, 0x1458BFFF, 0xF3C85FFF, 0xDFFFA7F8,
+	0x5F5BBFFE, 0x7F7D10D0, 0x144D5F33, 0xBFFFAF78,
+	0x5F5BBFFD, 0xA7F85F33, 0xBFFE77FD, 0x30BD4E08,
+	0xFDCFE5FF, 0x6E0FAFF8, 0x7EEF7E9F, 0xFDEFF1CF,
+	0x5F17ABF8, 0x0D5B5F5B, 0xFFEF79F7, 0x309EAFDD,
+	0x5F3147F8, 0x5F31AFED, 0x7FDD50AF, 0x497847FD,
+	0x7F9E7FED, 0x7DFD70A9, 0xEF7E7ECE, 0x6BA07F9E,
+	0x2D227EFD, 0x30DB5F5B, 0xFFFD5F5B, 0xFFEF5F5B,
+	0xFFDF0C9C, 0xAFED0A9A, 0xAFDD0C37, 0x5F37AFBD,
+	0x7FBDB081, 0x5F8147F8,
+};
+
+static ulong patch_2F00[] = {
+	0x3E303430, 0x34343737, 0xABBF9B99, 0x4B4FBDBD,
+	0x59949334, 0x9FFF37FB, 0x9B177DD9, 0x936956BB,
+	0xFBDD697B, 0xDD2FD113, 0x1DB9F7BB, 0x36313963,
+	0x79373369, 0x3193137F, 0x7331737A, 0xF7BB9B99,
+	0x9BB19795, 0x77FDFD3D, 0x573B773F, 0x737933F7,
+	0xB991D115, 0x31699315, 0x31531694, 0xBF4FBDBD,
+	0x35931497, 0x35376956, 0xBD697B9D, 0x96931313,
+	0x19797937, 0x69350000,
+};
+#else
+
+static ulong patch_2000[] = {
+	0x3fff0000, 0x3ffd0000, 0x3ffb0000, 0x3ff90000,
+	0x5fefeff8, 0x5f91eff8, 0x3ff30000, 0x3ff10000,
+	0x3a11e710, 0xedf0ccb9, 0xf318ed66, 0x7f0e5fe2,
+	0x7fedbb38, 0x3afe7468, 0x7fedf4d8, 0x8ffbb92d,
+	0xb83b77fd, 0xb0bb5eb9, 0xdfda7fed, 0x90bde74d,
+	0x6f0dcbd3, 0xe7decfed, 0xcb50cfed, 0xcfeddf6d,
+	0x914d4f74, 0x5eaedfcb, 0x9ee0e7df, 0xefbb6ffb,
+	0xe7ef7f0e, 0x9ee57fed, 0xebb7effa, 0xeb30affb,
+	0x7fea90b3, 0x7e0cf09f, 0xbffff318, 0x5fffdfff,
+	0xac35efea, 0x7fce1fc1, 0xe2ff5fbd, 0xaffbe2ff,
+	0x5fbfaffb, 0xf9a87d0f, 0xaef8770f, 0x7d0fb0a2,
+	0xeffbbfff, 0xcfef5fba, 0x7d0fbfff, 0x5fba4cf8,
+	0x7fddd09b, 0x49f847fd, 0x7efdf097, 0x7fedfffd,
+	0x7dfdf093, 0xef7e7e1e, 0x5fba7f0e, 0x3a11e710,
+	0xedf0cc87, 0xfb18ad0a, 0x1f85bbb8, 0x74283b7e,
+	0x7375e4bb, 0x2ab64fb8, 0x5c7de4bb, 0x32fdffbf,
+	0x5f0843f8, 0x7ce3e1bb, 0xe74f7ded, 0x6f0f4fe8,
+	0xc7ba32be, 0x73f2efeb, 0x600b4f78, 0xe5bb760b,
+	0x5388aef8, 0x4ef80b6a, 0xcfef9ee5, 0xabf8751f,
+	0xefef5b88, 0x741f4fe8, 0x751e760d, 0x7fdb70dd,
+	0x741cafce, 0xefcc7fce, 0x751e7088, 0x741ce7bb,
+	0x334ecfed, 0xafdbefeb, 0xe5bb760b, 0x53ceaef8,
+	0xafe8e7eb, 0x4bf8771e, 0x7e007fed, 0x4fcbe2cc,
+	0x7fbc3085, 0x7b0f7a0f, 0x34b177fd, 0xb0e75e93,
+	0xdf313e3b, 0xaf78741f, 0x741f30cc, 0xcfef5f08,
+	0x741f3e88, 0xafb8771e, 0x5f437fed, 0x0bafe2cc,
+	0x741ccfec, 0xe5ca53a9, 0x6fcb4f74, 0x5e89df27,
+	0x2a923d14, 0x4b8fdf0c, 0x751f741c, 0x6c1eeffa,
+	0xefea7fce, 0x6ffc309a, 0xefec3fca, 0x308fdf0a,
+	0xadf85e7a, 0xaf7daefd, 0x5e7adf0a, 0x5e7aafdd,
+	0x761f1088, 0x1e7c7efd, 0x3089fffe, 0x4908fb18,
+	0x5fffdfff, 0xafbbf0f7, 0x4ef85f43, 0xadf81489,
+	0x7a0f7089, 0xcfef5089, 0x7a0fdf0c, 0x5e7cafed,
+	0xbc6e780f, 0xefef780f, 0xefef790f, 0xa7f85eeb,
+	0xffef790f, 0xefef790f, 0x1489df0a, 0x5e7aadfd,
+	0x5f09fffb, 0xe79aded9, 0xeff96079, 0x607ae79a,
+	0xded8eff9, 0x60795edb, 0x607acfef, 0xefefefdf,
+	0xefbfef7f, 0xeeffedff, 0xebffe7ff, 0xafefafdf,
+	0xafbfaf7f, 0xaeffadff, 0xabffa7ff, 0x6fef6fdf,
+	0x6fbf6f7f, 0x6eff6dff, 0x6bff67ff, 0x2fef2fdf,
+	0x2fbf2f7f, 0x2eff2dff, 0x2bff27ff, 0x4e08fd1f,
+	0xe5ff6e0f, 0xaff87eef, 0x7e0ffdef, 0xf11f6079,
+	0xabf8f51e, 0x7e0af11c, 0x37cfae16, 0x7fec909a,
+	0xadf8efdc, 0xcfeae52f, 0x7d0fe12b, 0xf11c6079,
+	0x7e0a4df8, 0xcfea5ea0, 0x7d0befec, 0xcfea5ea2,
+	0xe522efdc, 0x5ea2cfda, 0x4e08fd1f, 0x6e0faff8,
+	0x7c1f761f, 0xfdeff91f, 0x6079abf8, 0x761cee00,
+	0xf91f2bfb, 0xefefcfec, 0xf91f6079, 0x761c27fb,
+	0xefdf5e83, 0xcfdc7fdd, 0x50f84bf8, 0x47fd7c1f,
+	0x761ccfcf, 0x7eef7fed, 0x7dfd70ef, 0xef7e7f1e,
+	0x771efb18, 0x6079e722, 0xe6bbe5bb, 0x2e66e5bb,
+	0x600b2ee1, 0xe2bbe2bb, 0xe2bbe2bb, 0x2f5ee2bb,
+	0xe2bb2ff9, 0x6079e2bb,
+};
+
+static ulong patch_2F00[] = {
+	0x30303030, 0x3e3e3030, 0xaf79b9b3, 0xbaa3b979,
+	0x9693369f, 0x79f79777, 0x97333fff, 0xfb3b9e9f,
+	0x79b91d11, 0x9e13f3ff, 0x3f9b6bd9, 0xe173d136,
+	0x695669d1, 0x697b3daf, 0x79b93a3a, 0x3f979f91,
+	0x379ff976, 0xf99777fd, 0x9779737d, 0xe9d6bbf9,
+	0xbfffd9df, 0x97f7fd97, 0x6f7b9bff, 0xf9bd9683,
+	0x397db973, 0xd97b3b9f, 0xd7f9f733, 0x9993bb9e,
+	0xe1f9ef93, 0x73773337, 0xb936917d, 0x11f87379,
+	0xb979d336, 0x8b7ded73, 0x1b7d9337, 0x31f3f22f,
+	0x3f2327ee, 0xeeeeeeee, 0xeeeeeeee, 0xeeeeeeee,
+	0xeeeeee4b, 0xf4fbdbd2, 0x58bb1878, 0x577fdfd2,
+	0xd573b773, 0xf7374b4f, 0xbdbd25b8, 0xb177d2d1,
+	0x7376856b, 0xbfdd687b, 0xdd2fff8f, 0x78ffff8f,
+	0xf22f0000,
+};
+#endif
+
+static void UcodeCopy (volatile cpm8xx_t *cpm)
+{
+	vu_long *p;
+	int i;
+
+	p = (vu_long *)&(cpm->cp_dpmem[0x0000]);
+	for (i=0; i < sizeof(patch_2000)/4; ++i) {
+		p[i] = patch_2000[i];
+	}
+
+	p = (vu_long *)&(cpm->cp_dpmem[0x0F00]);
+	for (i=0; i < sizeof(patch_2F00)/4; ++i) {
+		p[i] = patch_2F00[i];
+	}
+}
+
+#endif	/* CONFIG_SYS_I2C_UCODE_PATCH, CONFIG_SYS_SPI_UCODE_PATCH */
diff --git a/arch/powerpc/cpu/mpc8xx/video.c b/arch/powerpc/cpu/mpc8xx/video.c
new file mode 100644
index 0000000..c79c499
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/video.c
@@ -0,0 +1,1331 @@
+/*
+ * (C) Copyright 2000
+ * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
+ * (C) Copyright 2002
+ * Wolfgang Denk, wd@denx.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* #define DEBUG */
+
+/************************************************************************/
+/* ** HEADER FILES							*/
+/************************************************************************/
+
+#include <stdarg.h>
+#include <common.h>
+#include <config.h>
+#include <version.h>
+#include <timestamp.h>
+#include <i2c.h>
+#include <linux/types.h>
+#include <stdio_dev.h>
+
+#ifdef CONFIG_VIDEO
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/************************************************************************/
+/* ** DEBUG SETTINGS							*/
+/************************************************************************/
+
+#if 0
+#define VIDEO_DEBUG_COLORBARS	/* Force colorbars output */
+#endif
+
+/************************************************************************/
+/* ** VIDEO MODE SETTINGS						*/
+/************************************************************************/
+
+#if 0
+#define VIDEO_MODE_EXTENDED		/* Allow screen size bigger than visible area */
+#define VIDEO_MODE_NTSC
+#endif
+
+#define VIDEO_MODE_PAL
+
+#if 0
+#define VIDEO_BLINK			/* This enables cursor blinking (under construction) */
+#endif
+
+#define VIDEO_INFO			/* Show U-Boot information */
+#define VIDEO_INFO_X		VIDEO_LOGO_WIDTH+8
+#define VIDEO_INFO_Y		16
+
+/************************************************************************/
+/* ** VIDEO ENCODER CONSTANTS						*/
+/************************************************************************/
+
+#ifdef CONFIG_VIDEO_ENCODER_AD7176
+
+#include <video_ad7176.h>	/* Sets encoder data, mode, and visible and active area */
+
+#define VIDEO_I2C		1
+#define VIDEO_I2C_ADDR		CONFIG_VIDEO_ENCODER_AD7176_ADDR
+#endif
+
+#ifdef CONFIG_VIDEO_ENCODER_AD7177
+
+#include <video_ad7177.h>	/* Sets encoder data, mode, and visible and active area */
+
+#define VIDEO_I2C		1
+#define VIDEO_I2C_ADDR		CONFIG_VIDEO_ENCODER_AD7177_ADDR
+#endif
+
+#ifdef CONFIG_VIDEO_ENCODER_AD7179
+
+#include <video_ad7179.h>	/* Sets encoder data, mode, and visible and active area */
+
+#define VIDEO_I2C		1
+#define VIDEO_I2C_ADDR		CONFIG_VIDEO_ENCODER_AD7179_ADDR
+#endif
+
+/************************************************************************/
+/* ** VIDEO MODE CONSTANTS						*/
+/************************************************************************/
+
+#ifdef VIDEO_MODE_EXTENDED
+#define VIDEO_COLS	VIDEO_ACTIVE_COLS
+#define VIDEO_ROWS	VIDEO_ACTIVE_ROWS
+#else
+#define VIDEO_COLS	VIDEO_VISIBLE_COLS
+#define VIDEO_ROWS	VIDEO_VISIBLE_ROWS
+#endif
+
+#define VIDEO_PIXEL_SIZE	(VIDEO_MODE_BPP/8)
+#define VIDEO_SIZE		(VIDEO_ROWS*VIDEO_COLS*VIDEO_PIXEL_SIZE)	/* Total size of buffer */
+#define VIDEO_PIX_BLOCKS	(VIDEO_SIZE >> 2)	/* Number of ints */
+#define VIDEO_LINE_LEN		(VIDEO_COLS*VIDEO_PIXEL_SIZE)	/* Number of bytes per line */
+#define VIDEO_BURST_LEN		(VIDEO_COLS/8)
+
+#ifdef VIDEO_MODE_YUYV
+#define VIDEO_BG_COL	0x80D880D8	/* Background color in YUYV format */
+#else
+#define VIDEO_BG_COL	0xF8F8F8F8	/* Background color in RGB format */
+#endif
+
+/************************************************************************/
+/* ** FONT AND LOGO DATA						*/
+/************************************************************************/
+
+#include <video_font.h>			/* Get font data, width and height */
+
+#ifdef CONFIG_VIDEO_LOGO
+#include <video_logo.h>			/* Get logo data, width and height */
+
+#define VIDEO_LOGO_WIDTH	DEF_U_BOOT_LOGO_WIDTH
+#define VIDEO_LOGO_HEIGHT	DEF_U_BOOT_LOGO_HEIGHT
+#define VIDEO_LOGO_ADDR		&u_boot_logo
+#endif
+
+/************************************************************************/
+/* ** VIDEO CONTROLLER CONSTANTS					*/
+/************************************************************************/
+
+/* VCCR - VIDEO CONTROLLER CONFIGURATION REGISTER */
+
+#define VIDEO_VCCR_VON	0		/* Video controller ON */
+#define VIDEO_VCCR_CSRC	1		/* Clock source */
+#define VIDEO_VCCR_PDF	13		/* Pixel display format */
+#define VIDEO_VCCR_IEN	11		/* Interrupt enable */
+
+/* VSR - VIDEO STATUS REGISTER */
+
+#define VIDEO_VSR_CAS	6		/* Active set */
+#define VIDEO_VSR_EOF	0		/* End of frame */
+
+/* VCMR - VIDEO COMMAND REGISTER */
+
+#define VIDEO_VCMR_BD	0		/* Blank display */
+#define VIDEO_VCMR_ASEL	1		/* Active set selection */
+
+/* VBCB - VIDEO BACKGROUND COLOR BUFFER REGISTER */
+
+#define VIDEO_BCSR4_RESET_BIT	21	/* BCSR4 - Extern video encoder reset */
+#define VIDEO_BCSR4_EXTCLK_BIT	22	/* BCSR4 - Extern clock enable */
+#define VIDEO_BCSR4_VIDLED_BIT	23	/* BCSR4 - Video led disable */
+
+/************************************************************************/
+/* ** CONSOLE CONSTANTS							*/
+/************************************************************************/
+
+#ifdef	CONFIG_VIDEO_LOGO
+#define CONSOLE_ROWS		((VIDEO_ROWS - VIDEO_LOGO_HEIGHT) / VIDEO_FONT_HEIGHT)
+#define VIDEO_LOGO_SKIP		(VIDEO_COLS - VIDEO_LOGO_WIDTH)
+#else
+#define CONSOLE_ROWS		(VIDEO_ROWS / VIDEO_FONT_HEIGHT)
+#endif
+
+#define CONSOLE_COLS		(VIDEO_COLS / VIDEO_FONT_WIDTH)
+#define CONSOLE_ROW_SIZE	(VIDEO_FONT_HEIGHT * VIDEO_LINE_LEN)
+#define CONSOLE_ROW_FIRST	(video_console_address)
+#define CONSOLE_ROW_SECOND	(video_console_address + CONSOLE_ROW_SIZE)
+#define CONSOLE_ROW_LAST	(video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE)
+#define CONSOLE_SIZE		(CONSOLE_ROW_SIZE * CONSOLE_ROWS)
+#define CONSOLE_SCROLL_SIZE	(CONSOLE_SIZE - CONSOLE_ROW_SIZE)
+
+/*
+ * Simple color definitions
+ */
+#define CONSOLE_COLOR_BLACK	 0
+#define CONSOLE_COLOR_RED	 1
+#define CONSOLE_COLOR_GREEN	 2
+#define CONSOLE_COLOR_YELLOW	 3
+#define CONSOLE_COLOR_BLUE	 4
+#define CONSOLE_COLOR_MAGENTA	 5
+#define CONSOLE_COLOR_CYAN	 6
+#define CONSOLE_COLOR_GREY	13
+#define CONSOLE_COLOR_GREY2	14
+#define CONSOLE_COLOR_WHITE	15	/* Must remain last / highest */
+
+/************************************************************************/
+/* ** BITOPS MACROS							*/
+/************************************************************************/
+
+#define HISHORT(i)	((i >> 16)&0xffff)
+#define LOSHORT(i)	(i & 0xffff)
+#define HICHAR(s)	((i >> 8)&0xff)
+#define LOCHAR(s)	(i & 0xff)
+#define HI(c)		((c >> 4)&0xf)
+#define LO(c)		(c & 0xf)
+#define SWAPINT(i)	(HISHORT(i) | (LOSHORT(i) << 16))
+#define SWAPSHORT(s)	(HICHAR(s) | (LOCHAR(s) << 8))
+#define SWAPCHAR(c)	(HI(c) | (LO(c) << 4))
+#define BITMASK(b)	(1 << (b))
+#define GETBIT(v,b)	(((v) & BITMASK(b)) > 0)
+#define SETBIT(v,b,d)	(v = (((d)>0) ? (v) | BITMASK(b): (v) & ~BITMASK(b)))
+
+/************************************************************************/
+/* ** STRUCTURES							*/
+/************************************************************************/
+
+typedef struct {
+	unsigned char V, Y1, U, Y2;
+} tYUYV;
+
+/* This structure is based on the Video Ram in the MPC823. */
+typedef struct VRAM {
+	unsigned	hx:2,		/* Horizontal sync */
+			vx:2,		/* Vertical sync */
+			fx:2,		/* Frame */
+			bx:2,		/* Blank */
+			res1:6,		/* Reserved */
+			vds:2,		/* Video Data Select */
+			inter:1,	/* Interrupt */
+			res2:2,		/* Reserved */
+			lcyc:11,	/* Loop/video cycles */
+			lp:1,		/* Loop start/end */
+			lst:1;		/* Last entry */
+} VRAM;
+
+/************************************************************************/
+/* ** VARIABLES								*/
+/************************************************************************/
+
+static int
+	video_panning_range_x = 0,	/* Video mode invisible pixels x range */
+	video_panning_range_y = 0,	/* Video mode invisible pixels y range */
+	video_panning_value_x = 0,	/* Video mode x panning value (absolute) */
+	video_panning_value_y = 0,	/* Video mode y panning value (absolute) */
+	video_panning_factor_x = 0,	/* Video mode x panning value (-127 +127) */
+	video_panning_factor_y = 0,	/* Video mode y panning value (-127 +127) */
+	console_col = 0,		/* Cursor col */
+	console_row = 0,		/* Cursor row */
+	video_palette[16];		/* Our palette */
+
+static const int video_font_draw_table[] =
+	{ 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff };
+
+static char
+	video_color_fg = 0,		/* Current fg color index (0-15) */
+	video_color_bg = 0,		/* Current bg color index (0-15) */
+	video_enable = 0;		/* Video has been initialized? */
+
+static void
+	*video_fb_address,		/* Frame buffer address */
+	*video_console_address;		/* Console frame buffer start address */
+
+/************************************************************************/
+/* ** MEMORY FUNCTIONS (32bit)						*/
+/************************************************************************/
+
+static void memsetl (int *p, int c, int v)
+{
+	while (c--)
+		*(p++) = v;
+}
+
+static void memcpyl (int *d, int *s, int c)
+{
+	while (c--)
+		*(d++) = *(s++);
+}
+
+/************************************************************************/
+/* ** VIDEO DRAWING AND COLOR FUNCTIONS					*/
+/************************************************************************/
+
+static int video_maprgb (int r, int g, int b)
+{
+#ifdef VIDEO_MODE_YUYV
+	unsigned int pR, pG, pB;
+	tYUYV YUYV;
+	unsigned int *ret = (unsigned int *) &YUYV;
+
+	/* Transform (0-255) components to (0-100) */
+
+	pR = r * 100 / 255;
+	pG = g * 100 / 255;
+	pB = b * 100 / 255;
+
+	/* Calculate YUV values (0-255) from RGB beetween 0-100 */
+
+	YUYV.Y1 = YUYV.Y2 = 209 * (pR + pG + pB) / 300 + 16;
+	YUYV.U	= pR - (pG * 3 / 4) - (pB / 4) + 128;
+	YUYV.V	= pB - (pR / 4) - (pG * 3 / 4) + 128;
+	return *ret;
+#endif
+#ifdef VIDEO_MODE_RGB
+	return ((r >> 3) << 11) | ((g > 2) << 6) | (b >> 3);
+#endif
+}
+
+static void video_setpalette (int color, int r, int g, int b)
+{
+	color &= 0xf;
+
+	video_palette[color] = video_maprgb (r, g, b);
+
+	/* Swap values if our panning offset is odd */
+	if (video_panning_value_x & 1)
+		video_palette[color] = SWAPINT (video_palette[color]);
+}
+
+static void video_fill (int color)
+{
+	memsetl (video_fb_address, VIDEO_PIX_BLOCKS, color);
+}
+
+static void video_setfgcolor (int i)
+{
+	video_color_fg = i & 0xf;
+}
+
+static void video_setbgcolor (int i)
+{
+	video_color_bg = i & 0xf;
+}
+
+static int video_pickcolor (int i)
+{
+	return video_palette[i & 0xf];
+}
+
+/* Absolute console plotting functions */
+
+#ifdef VIDEO_BLINK
+static void video_revchar (int xx, int yy)
+{
+	int rows;
+	u8 *dest;
+
+	dest = video_fb_address + yy * VIDEO_LINE_LEN + xx * 2;
+
+	for (rows = VIDEO_FONT_HEIGHT; rows--; dest += VIDEO_LINE_LEN) {
+		switch (VIDEO_FONT_WIDTH) {
+		case 16:
+			((u32 *) dest)[6] ^= 0xffffffff;
+			((u32 *) dest)[7] ^= 0xffffffff;
+			/* FALL THROUGH */
+		case 12:
+			((u32 *) dest)[4] ^= 0xffffffff;
+			((u32 *) dest)[5] ^= 0xffffffff;
+			/* FALL THROUGH */
+		case 8:
+			((u32 *) dest)[2] ^= 0xffffffff;
+			((u32 *) dest)[3] ^= 0xffffffff;
+			/* FALL THROUGH */
+		case 4:
+			((u32 *) dest)[0] ^= 0xffffffff;
+			((u32 *) dest)[1] ^= 0xffffffff;
+		}
+	}
+}
+#endif
+
+static void video_drawchars (int xx, int yy, unsigned char *s, int count)
+{
+	u8 *cdat, *dest, *dest0;
+	int rows, offset, c;
+	u32 eorx, fgx, bgx;
+
+	offset = yy * VIDEO_LINE_LEN + xx * 2;
+	dest0 = video_fb_address + offset;
+
+	fgx = video_pickcolor (video_color_fg);
+	bgx = video_pickcolor (video_color_bg);
+
+	if (xx & 1) {
+		fgx = SWAPINT (fgx);
+		bgx = SWAPINT (bgx);
+	}
+
+	eorx = fgx ^ bgx;
+
+	switch (VIDEO_FONT_WIDTH) {
+	case 4:
+	case 8:
+		while (count--) {
+			c = *s;
+			cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+			for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
+			     rows--;
+			     dest += VIDEO_LINE_LEN) {
+				u8 bits = *cdat++;
+
+				((u32 *) dest)[0] =
+					(video_font_draw_table[bits >> 6] & eorx) ^ bgx;
+				((u32 *) dest)[1] =
+					(video_font_draw_table[bits >> 4 & 3] & eorx) ^ bgx;
+				if (VIDEO_FONT_WIDTH == 8) {
+					((u32 *) dest)[2] =
+						(video_font_draw_table[bits >> 2 & 3] & eorx) ^ bgx;
+					((u32 *) dest)[3] =
+						(video_font_draw_table[bits & 3] & eorx) ^ bgx;
+				}
+			}
+			dest0 += VIDEO_FONT_WIDTH * 2;
+			s++;
+		}
+		break;
+	case 12:
+	case 16:
+		while (count--) {
+			cdat = video_fontdata + (*s) * (VIDEO_FONT_HEIGHT << 1);
+			for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--;
+				 dest += VIDEO_LINE_LEN) {
+				u8 bits = *cdat++;
+
+				((u32 *) dest)[0] =
+					(video_font_draw_table[bits >> 6] & eorx) ^ bgx;
+				((u32 *) dest)[1] =
+					(video_font_draw_table[bits >> 4 & 3] & eorx) ^ bgx;
+				((u32 *) dest)[2] =
+					(video_font_draw_table[bits >> 2 & 3] & eorx) ^ bgx;
+				((u32 *) dest)[3] =
+					(video_font_draw_table[bits & 3] & eorx) ^ bgx;
+				bits = *cdat++;
+				((u32 *) dest)[4] =
+					(video_font_draw_table[bits >> 6] & eorx) ^ bgx;
+				((u32 *) dest)[5] =
+					(video_font_draw_table[bits >> 4 & 3] & eorx) ^ bgx;
+				if (VIDEO_FONT_WIDTH == 16) {
+					((u32 *) dest)[6] =
+						(video_font_draw_table[bits >> 2 & 3] & eorx) ^ bgx;
+					((u32 *) dest)[7] =
+						(video_font_draw_table[bits & 3] & eorx) ^ bgx;
+				}
+			}
+			s++;
+			dest0 += VIDEO_FONT_WIDTH * 2;
+		}
+		break;
+	}
+}
+
+static inline void video_drawstring (int xx, int yy, char *s)
+{
+	video_drawchars (xx, yy, (unsigned char *)s, strlen (s));
+}
+
+/* Relative to console plotting functions */
+
+static void video_putchars (int xx, int yy, unsigned char *s, int count)
+{
+#ifdef CONFIG_VIDEO_LOGO
+	video_drawchars (xx, yy + VIDEO_LOGO_HEIGHT, s, count);
+#else
+	video_drawchars (xx, yy, s, count);
+#endif
+}
+
+static void video_putchar (int xx, int yy, unsigned char c)
+{
+#ifdef CONFIG_VIDEO_LOGO
+	video_drawchars (xx, yy + VIDEO_LOGO_HEIGHT, &c, 1);
+#else
+	video_drawchars (xx, yy, &c, 1);
+#endif
+}
+
+static inline void video_putstring (int xx, int yy, unsigned char *s)
+{
+	video_putchars (xx, yy, (unsigned char *)s, strlen ((char *)s));
+}
+
+/************************************************************************/
+/* ** VIDEO CONTROLLER LOW-LEVEL FUNCTIONS				*/
+/************************************************************************/
+
+#if !defined(CONFIG_RRVISION)
+static void video_mode_dupefield (VRAM * source, VRAM * dest, int entries)
+{
+	int i;
+
+	for (i = 0; i < entries; i++) {
+		dest[i] = source[i];	/* Copy the entire record */
+		dest[i].fx = (!dest[i].fx) * 3;	/* Negate field bit */
+	}
+
+	dest[0].lcyc++;			/* Add a cycle to the first entry */
+	dest[entries - 1].lst = 1;	/* Set end of ram entries */
+}
+#endif
+
+static void inline video_mode_addentry (VRAM * vr,
+	int Hx, int Vx, int Fx, int Bx,
+	int VDS, int INT, int LCYC, int LP, int LST)
+{
+	vr->hx = Hx;
+	vr->vx = Vx;
+	vr->fx = Fx;
+	vr->bx = Bx;
+	vr->vds = VDS;
+	vr->inter = INT;
+	vr->lcyc = LCYC;
+	vr->lp = LP;
+	vr->lst = LST;
+}
+
+#define ADDENTRY(a,b,c,d,e,f,g,h,i)	video_mode_addentry(&vr[entry++],a,b,c,d,e,f,g,h,i)
+
+static int video_mode_generate (void)
+{
+	immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+	VRAM *vr = (VRAM *) (((void *) immap) + 0xb00);	/* Pointer to the VRAM table */
+	int DX, X1, X2, DY, Y1, Y2, entry = 0, fifo;
+
+	/* CHECKING PARAMETERS */
+
+	if (video_panning_factor_y < -128)
+		video_panning_factor_y = -128;
+
+	if (video_panning_factor_y > 128)
+		video_panning_factor_y = 128;
+
+	if (video_panning_factor_x < -128)
+		video_panning_factor_x = -128;
+
+	if (video_panning_factor_x > 128)
+		video_panning_factor_x = 128;
+
+	/* Setting panning */
+
+	DX = video_panning_range_x = (VIDEO_ACTIVE_COLS - VIDEO_COLS) * 2;
+	DY = video_panning_range_y = (VIDEO_ACTIVE_ROWS - VIDEO_ROWS) / 2;
+
+	video_panning_value_x = (video_panning_factor_x + 128) * DX / 256;
+	video_panning_value_y = (video_panning_factor_y + 128) * DY / 256;
+
+	/* We assume these are burst units (multiplied by 2, we need it pari) */
+	X1 = video_panning_value_x & 0xfffe;
+	X2 = DX - X1;
+
+	/* We assume these are field line units (divided by 2, we need it pari) */
+	Y1 = video_panning_value_y & 0xfffe;
+	Y2 = DY - Y1;
+
+	debug("X1=%d, X2=%d, Y1=%d, Y2=%d, DX=%d, DY=%d VIDEO_COLS=%d \n",
+	      X1, X2, Y1, Y2, DX, DY, VIDEO_COLS);
+
+#ifdef VIDEO_MODE_NTSC
+/*
+ *	     Hx Vx Fx Bx VDS INT LCYC LP LST
+ *
+ * Retrace blanking
+ */
+	ADDENTRY (0, 0, 3, 0, 1, 0, 3, 1, 0);
+	ADDENTRY (3, 0, 3, 0, 1, 0, 243, 0, 0);
+	ADDENTRY (3, 0, 3, 0, 1, 0, 1440, 0, 0);
+	ADDENTRY (3, 0, 3, 0, 1, 0, 32, 1, 0);
+/*
+ * Vertical blanking
+ */
+	ADDENTRY (0, 0, 0, 0, 1, 0, 18, 1, 0);
+	ADDENTRY (3, 0, 0, 0, 1, 0, 243, 0, 0);
+	ADDENTRY (3, 0, 0, 0, 1, 0, 1440, 0, 0);
+	ADDENTRY (3, 0, 0, 0, 1, 0, 32, 1, 0);
+/*
+ * Odd field active area (TOP)
+ */
+	if (Y1 > 0) {
+		ADDENTRY (0, 0, 0, 0, 1, 0, Y1, 1, 0);
+		ADDENTRY (3, 0, 0, 0, 1, 0, 235, 0, 0);
+		ADDENTRY (3, 0, 0, 3, 1, 0, 1448, 0, 0);
+		ADDENTRY (3, 0, 0, 0, 1, 0, 32, 1, 0);
+	}
+/*
+ * Odd field active area
+ */
+	ADDENTRY (0, 0, 0, 0, 1, 0, 240 - DY, 1, 0);
+	ADDENTRY (3, 0, 0, 0, 1, 0, 235, 0, 0);
+	ADDENTRY (3, 0, 0, 3, 1, 0, 8 + X1, 0, 0);
+	ADDENTRY (3, 0, 0, 3, 0, 0, VIDEO_COLS * 2, 0, 0);
+
+	if (X2 > 0)
+		ADDENTRY (3, 0, 0, 3, 1, 0, X2, 0, 0);
+
+	ADDENTRY (3, 0, 0, 0, 1, 0, 32, 1, 0);
+
+/*
+ * Odd field active area (BOTTOM)
+ */
+	if (Y1 > 0) {
+		ADDENTRY (0, 0, 0, 0, 1, 0, Y2, 1, 0);
+		ADDENTRY (3, 0, 0, 0, 1, 0, 235, 0, 0);
+		ADDENTRY (3, 0, 0, 3, 1, 0, 1448, 0, 0);
+		ADDENTRY (3, 0, 0, 0, 1, 0, 32, 1, 0);
+	}
+/*
+ * Vertical blanking
+ */
+	ADDENTRY (0, 0, 0, 0, 1, 0, 4, 1, 0);
+	ADDENTRY (3, 0, 0, 0, 1, 0, 243, 0, 0);
+	ADDENTRY (3, 0, 0, 0, 1, 0, 1440, 0, 0);
+	ADDENTRY (3, 0, 0, 0, 1, 0, 32, 1, 0);
+/*
+ * Vertical blanking
+ */
+	ADDENTRY (0, 0, 3, 0, 1, 0, 19, 1, 0);
+	ADDENTRY (3, 0, 3, 0, 1, 0, 243, 0, 0);
+	ADDENTRY (3, 0, 3, 0, 1, 0, 1440, 0, 0);
+	ADDENTRY (3, 0, 3, 0, 1, 0, 32, 1, 0);
+/*
+ * Even field active area (TOP)
+ */
+	if (Y1 > 0) {
+		ADDENTRY (0, 0, 3, 0, 1, 0, Y1, 1, 0);
+		ADDENTRY (3, 0, 3, 0, 1, 0, 235, 0, 0);
+		ADDENTRY (3, 0, 3, 3, 1, 0, 1448, 0, 0);
+		ADDENTRY (3, 0, 3, 0, 1, 0, 32, 1, 0);
+	}
+/*
+ * Even field active area (CENTER)
+ */
+	ADDENTRY (0, 0, 3, 0, 1, 0, 240 - DY, 1, 0);
+	ADDENTRY (3, 0, 3, 0, 1, 0, 235, 0, 0);
+	ADDENTRY (3, 0, 3, 3, 1, 0, 8 + X1, 0, 0);
+	ADDENTRY (3, 0, 3, 3, 0, 0, VIDEO_COLS * 2, 0, 0);
+
+	if (X2 > 0)
+		ADDENTRY (3, 0, 3, 3, 1, 0, X2, 0, 0);
+
+	ADDENTRY (3, 0, 3, 0, 1, 0, 32, 1, 0);
+/*
+ * Even field active area (BOTTOM)
+ */
+	if (Y1 > 0) {
+		ADDENTRY (0, 0, 3, 0, 1, 0, Y2, 1, 0);
+		ADDENTRY (3, 0, 3, 0, 1, 0, 235, 0, 0);
+		ADDENTRY (3, 0, 3, 3, 1, 0, 1448, 0, 0);
+		ADDENTRY (3, 0, 3, 0, 1, 0, 32, 1, 0);
+	}
+/*
+ * Vertical blanking
+ */
+	ADDENTRY (0, 0, 3, 0, 1, 0, 1, 1, 0);
+	ADDENTRY (3, 0, 3, 0, 1, 0, 243, 0, 0);
+	ADDENTRY (3, 0, 3, 0, 1, 0, 1440, 0, 0);
+	ADDENTRY (3, 0, 3, 0, 1, 1, 32, 1, 1);
+#endif
+
+#ifdef VIDEO_MODE_PAL
+
+#if defined(CONFIG_RRVISION)
+
+#define HPW   160  /* horizontal pulse width (was 139)	*/
+#define VPW	2  /* vertical pulse width		*/
+#define HBP   104  /* horizontal back porch (was 112)	*/
+#define VBP    19  /* vertical back porch (was 19)	*/
+#define VID_R 240  /* number of rows			*/
+
+	debug ("[VIDEO CTRL] Starting to add controller entries...");
+/*
+ * Even field
+ */
+	ADDENTRY (0, 3, 0, 3, 1, 0, 2, 0, 0);
+	ADDENTRY (0, 0, 0, 3, 1, 0, HPW, 0, 0);
+	ADDENTRY (3, 0, 0, 3, 1, 0, HBP + (VIDEO_COLS * 2) + 72, 0, 0);
+
+	ADDENTRY (0, 0, 0, 3, 1, 0, VPW, 1, 0);
+	ADDENTRY (0, 0, 0, 3, 1, 0, HPW-1, 0, 0);
+	ADDENTRY (3, 0, 0, 3, 1, 0, HBP + (VIDEO_COLS * 2) + 72, 1, 0);
+
+	ADDENTRY (0, 3, 0, 3, 1, 0, VBP, 1, 0);
+	ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
+	ADDENTRY (3, 3, 0, 3, 1, 0, HBP + (VIDEO_COLS * 2) + 72, 1, 0);
+/*
+ * Active area
+ */
+	ADDENTRY (0, 3, 0, 3, 1, 0, VID_R , 1, 0);
+	ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
+	ADDENTRY (3, 3, 0, 3, 1, 0, HBP, 0, 0);
+	ADDENTRY (3, 3, 0, 3, 0, 0, VIDEO_COLS*2, 0, 0);
+	ADDENTRY (3, 3, 0, 3, 1, 0, 72, 1, 1);
+
+	ADDENTRY (0, 3, 0, 3, 1, 0, 51, 1, 0);
+	ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
+	ADDENTRY (3, 3, 0, 3, 1, 0, HBP +(VIDEO_COLS * 2) + 72 , 1, 0);
+/*
+ * Odd field
+ */
+	ADDENTRY (0, 3, 0, 3, 1, 0, 2, 0, 0);
+	ADDENTRY (0, 0, 0, 3, 1, 0, HPW, 0, 0);
+	ADDENTRY (3, 0, 0, 3, 1, 0, HBP + (VIDEO_COLS * 2) + 72, 0, 0);
+
+	ADDENTRY (0, 0, 0, 3, 1, 0, VPW+1, 1, 0);
+	ADDENTRY (0, 0, 0, 3, 1, 0, HPW-1, 0, 0);
+	ADDENTRY (3, 0, 0, 3, 1, 0, HBP + (VIDEO_COLS * 2) + 72, 1, 0);
+
+	ADDENTRY (0, 3, 0, 3, 1, 0, VBP, 1, 0);
+	ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
+	ADDENTRY (3, 3, 0, 3, 1, 0, HBP + (VIDEO_COLS * 2) + 72, 1, 0);
+/*
+ * Active area
+ */
+	ADDENTRY (0, 3, 0, 3, 1, 0, VID_R , 1, 0);
+	ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
+	ADDENTRY (3, 3, 0, 3, 1, 0, HBP, 0, 0);
+	ADDENTRY (3, 3, 0, 3, 0, 0, VIDEO_COLS*2, 0, 0);
+	ADDENTRY (3, 3, 0, 3, 1, 0, 72, 1, 1);
+
+	ADDENTRY (0, 3, 0, 3, 1, 0, 51, 1, 0);
+	ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
+	ADDENTRY (3, 3, 0, 3, 1, 0, HBP +(VIDEO_COLS * 2) + 72 , 1, 0);
+
+	debug ("done\n");
+
+#else  /* !CONFIG_RRVISION */
+
+/*
+ *	Hx Vx Fx Bx VDS INT LCYC LP LST
+ *
+ * vertical; blanking
+ */
+	ADDENTRY (0, 0, 0, 0, 1, 0, 22, 1, 0);
+	ADDENTRY (3, 0, 0, 0, 1, 0, 263, 0, 0);
+	ADDENTRY (3, 0, 0, 0, 1, 0, 1440, 0, 0);
+	ADDENTRY (3, 0, 0, 0, 1, 0, 24, 1, 0);
+/*
+ * active area (TOP)
+ */
+	if (Y1 > 0) {
+		ADDENTRY (0, 0, 0, 0, 1, 0, Y1, 1, 0);	/* 11? */
+		ADDENTRY (3, 0, 0, 0, 1, 0, 255, 0, 0);
+		ADDENTRY (3, 0, 0, 3, 1, 0, 1448, 0, 0);
+		ADDENTRY (3, 0, 0, 0, 1, 0, 24, 1, 0);
+	}
+/*
+ * field active area (CENTER)
+ */
+	ADDENTRY (0, 0, 0, 0, 1, 0, 288 - DY, 1, 0);	/* 265? */
+	ADDENTRY (3, 0, 0, 0, 1, 0, 255, 0, 0);
+	ADDENTRY (3, 0, 0, 3, 1, 0, 8 + X1, 0, 0);
+	ADDENTRY (3, 0, 0, 3, 0, 0, VIDEO_COLS * 2, 0, 0);
+
+	if (X2 > 0)
+		ADDENTRY (3, 0, 0, 1, 1, 0, X2, 0, 0);
+
+	ADDENTRY (3, 0, 0, 0, 1, 0, 24, 1, 0);
+/*
+ * field active area (BOTTOM)
+ */
+	if (Y2 > 0) {
+		ADDENTRY (0, 0, 0, 0, 1, 0, Y2, 1, 0);	/* 12? */
+		ADDENTRY (3, 0, 0, 0, 1, 0, 255, 0, 0);
+		ADDENTRY (3, 0, 0, 3, 1, 0, 1448, 0, 0);
+		ADDENTRY (3, 0, 0, 0, 1, 0, 24, 1, 0);
+	}
+/*
+ * field vertical; blanking
+ */
+	ADDENTRY (0, 0, 0, 0, 1, 0, 2, 1, 0);
+	ADDENTRY (3, 0, 0, 0, 1, 0, 263, 0, 0);
+	ADDENTRY (3, 0, 0, 0, 1, 0, 1440, 0, 0);
+	ADDENTRY (3, 0, 0, 0, 1, 0, 24, 1, 0);
+/*
+ * Create the other field (like this, but whit other field selected,
+ * one more cycle loop and a last identifier)
+ */
+	video_mode_dupefield (vr, &vr[entry], entry);
+#endif /* CONFIG_RRVISION */
+
+#endif /* VIDEO_MODE_PAL */
+
+	/* See what FIFO are we using */
+	fifo = GETBIT (immap->im_vid.vid_vsr, VIDEO_VSR_CAS);
+
+	/* Set number of lines and burst (only one frame for now) */
+	if (fifo) {
+		immap->im_vid.vid_vfcr0 = VIDEO_BURST_LEN |
+			(VIDEO_BURST_LEN << 8) | ((VIDEO_ROWS / 2) << 19);
+	} else {
+		immap->im_vid.vid_vfcr1 = VIDEO_BURST_LEN |
+			(VIDEO_BURST_LEN << 8) | ((VIDEO_ROWS / 2) << 19);
+	}
+
+	SETBIT (immap->im_vid.vid_vcmr, VIDEO_VCMR_ASEL, !fifo);
+
+/*
+ * Wait until changes are applied (not done)
+ * while (GETBIT(immap->im_vid.vid_vsr, VIDEO_VSR_CAS) == fifo) ;
+ */
+
+	/* Return number of VRAM entries */
+	return entry * 2;
+}
+
+static void video_encoder_init (void)
+{
+#ifdef VIDEO_I2C
+	int rc;
+
+	/* Initialize the I2C */
+	debug ("[VIDEO ENCODER] Initializing I2C bus...\n");
+	i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+#ifdef CONFIG_FADS
+	/* Reset ADV7176 chip */
+	debug ("[VIDEO ENCODER] Resetting encoder...\n");
+	(*(int *) BCSR4) &= ~(1 << 21);
+
+	/* Wait for 5 ms inside the reset */
+	debug ("[VIDEO ENCODER] Waiting for encoder reset...\n");
+	udelay (5000);
+
+	/* Take ADV7176 out of reset */
+	(*(int *) BCSR4) |= 1 << 21;
+
+	/* Wait for 5 ms after the reset */
+	udelay (5000);
+#endif	/* CONFIG_FADS */
+
+	/* Send configuration */
+#ifdef DEBUG
+	{
+		int i;
+
+		puts ("[VIDEO ENCODER] Configuring the encoder...\n");
+
+		printf ("Sending %zu bytes (@ %08lX) to I2C 0x%lX:\n   ",
+			sizeof(video_encoder_data),
+			(ulong)video_encoder_data,
+			(ulong)VIDEO_I2C_ADDR);
+		for (i=0; i<sizeof(video_encoder_data); ++i) {
+			printf(" %02X", video_encoder_data[i]);
+		}
+		putc ('\n');
+	}
+#endif	/* DEBUG */
+
+	if ((rc = i2c_write (VIDEO_I2C_ADDR, 0, 1,
+			 video_encoder_data,
+			 sizeof(video_encoder_data))) != 0) {
+		printf ("i2c_send error: rc=%d\n", rc);
+		return;
+	}
+#endif	/* VIDEO_I2C */
+	return;
+}
+
+static void video_ctrl_init (void *memptr)
+{
+	immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+
+	video_fb_address = memptr;
+
+	/* Set background */
+	debug ("[VIDEO CTRL] Setting background color...\n");
+	immap->im_vid.vid_vbcb = VIDEO_BG_COL;
+
+	/* Show the background */
+	debug ("[VIDEO CTRL] Forcing background...\n");
+	SETBIT (immap->im_vid.vid_vcmr, VIDEO_VCMR_BD, 1);
+
+	/* Turn off video controller */
+	debug ("[VIDEO CTRL] Turning off video controller...\n");
+	SETBIT (immap->im_vid.vid_vccr, VIDEO_VCCR_VON, 0);
+
+#ifdef CONFIG_FADS
+	/* Turn on Video Port LED */
+	debug ("[VIDEO CTRL] Turning off video port led...\n");
+	SETBIT (*(int *) BCSR4, VIDEO_BCSR4_VIDLED_BIT, 1);
+
+	/* Disable internal clock */
+	debug ("[VIDEO CTRL] Disabling internal clock...\n");
+	SETBIT (*(int *) BCSR4, VIDEO_BCSR4_EXTCLK_BIT, 0);
+#endif
+
+	/* Generate and make active a new video mode */
+	debug ("[VIDEO CTRL] Generating video mode...\n");
+	video_mode_generate ();
+
+	/* Start of frame buffer (even and odd frame, to make it working with */
+	/* any selected active set) */
+	debug ("[VIDEO CTRL] Setting frame buffer address...\n");
+	immap->im_vid.vid_vfaa1 =
+		immap->im_vid.vid_vfaa0 = (u32) video_fb_address;
+	immap->im_vid.vid_vfba1 =
+	immap->im_vid.vid_vfba0 =
+		(u32) video_fb_address + VIDEO_LINE_LEN;
+
+	/* YUV, Big endian, SHIFT/CLK/CLK input (BEFORE ENABLING 27MHZ EXT CLOCK) */
+	debug ("[VIDEO CTRL] Setting pixel mode and clocks...\n");
+	immap->im_vid.vid_vccr = 0x2042;
+
+	/* Configure port pins */
+	debug ("[VIDEO CTRL] Configuring input/output pins...\n");
+	immap->im_ioport.iop_pdpar = 0x1fff;
+	immap->im_ioport.iop_pddir = 0x0000;
+
+#ifdef CONFIG_FADS
+	/* Turn on Video Port Clock - ONLY AFTER SET VCCR TO ENABLE EXTERNAL CLOCK */
+	debug ("[VIDEO CTRL] Turning on video clock...\n");
+	SETBIT (*(int *) BCSR4, VIDEO_BCSR4_EXTCLK_BIT, 1);
+
+	/* Turn on Video Port LED */
+	debug ("[VIDEO CTRL] Turning on video port led...\n");
+	SETBIT (*(int *) BCSR4, VIDEO_BCSR4_VIDLED_BIT, 0);
+#endif
+#ifdef CONFIG_RRVISION
+	debug ("PC5->Output(1): enable PAL clock");
+	immap->im_ioport.iop_pcpar &= ~(0x0400);
+	immap->im_ioport.iop_pcdir |=   0x0400 ;
+	immap->im_ioport.iop_pcdat |=   0x0400 ;
+	debug ("PDPAR=0x%04X PDDIR=0x%04X PDDAT=0x%04X\n",
+	       immap->im_ioport.iop_pdpar,
+	       immap->im_ioport.iop_pddir,
+	       immap->im_ioport.iop_pddat);
+	debug ("PCPAR=0x%04X PCDIR=0x%04X PCDAT=0x%04X\n",
+	       immap->im_ioport.iop_pcpar,
+	       immap->im_ioport.iop_pcdir,
+	       immap->im_ioport.iop_pcdat);
+#endif	/* CONFIG_RRVISION */
+
+	/* Blanking the screen. */
+	debug ("[VIDEO CTRL] Blanking the screen...\n");
+	video_fill (VIDEO_BG_COL);
+
+	/*
+	 * Turns on Aggressive Mode. Normally, turning on the caches
+	 * will cause the screen to flicker when the caches try to
+	 * fill. This gives the FIFO's for the Video Controller
+	 * higher priority and prevents flickering because of
+	 * underrun. This may still be an issue when using FLASH,
+	 * since accessing data from Flash is so slow.
+	 */
+	debug ("[VIDEO CTRL] Turning on aggressive mode...\n");
+	immap->im_siu_conf.sc_sdcr = 0x40;
+
+	/* Turn on video controller */
+	debug ("[VIDEO CTRL] Turning on video controller...\n");
+	SETBIT (immap->im_vid.vid_vccr, VIDEO_VCCR_VON, 1);
+
+	/* Show the display */
+	debug ("[VIDEO CTRL] Enabling the video...\n");
+	SETBIT (immap->im_vid.vid_vcmr, VIDEO_VCMR_BD, 0);
+}
+
+/************************************************************************/
+/* ** CONSOLE FUNCTIONS							*/
+/************************************************************************/
+
+static void console_scrollup (void)
+{
+	/* Copy up rows ignoring the first one */
+	memcpyl (CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND, CONSOLE_SCROLL_SIZE >> 2);
+
+	/* Clear the last one */
+	memsetl (CONSOLE_ROW_LAST, CONSOLE_ROW_SIZE >> 2, VIDEO_BG_COL);
+}
+
+static inline void console_back (void)
+{
+	console_col--;
+
+	if (console_col < 0) {
+		console_col = CONSOLE_COLS - 1;
+		console_row--;
+		if (console_row < 0)
+			console_row = 0;
+	}
+
+	video_putchar ( console_col * VIDEO_FONT_WIDTH,
+			console_row * VIDEO_FONT_HEIGHT, ' ');
+}
+
+static inline void console_newline (void)
+{
+	console_row++;
+	console_col = 0;
+
+	/* Check if we need to scroll the terminal */
+	if (console_row >= CONSOLE_ROWS) {
+		/* Scroll everything up */
+		console_scrollup ();
+
+		/* Decrement row number */
+		console_row--;
+	}
+}
+
+void video_putc (const char c)
+{
+	if (!video_enable) {
+		serial_putc (c);
+		return;
+	}
+
+	switch (c) {
+	case 13:			/* Simply ignore this */
+		break;
+
+	case '\n':			/* Next line, please */
+		console_newline ();
+		break;
+
+	case 9:				/* Tab (8 chars alignment) */
+		console_col |= 0x0008;	/* Next 8 chars boundary */
+		console_col &= ~0x0007;	/* Set this bit to zero */
+
+		if (console_col >= CONSOLE_COLS)
+			console_newline ();
+		break;
+
+	case 8:				/* Eat last character */
+		console_back ();
+		break;
+
+	default:			/* Add to the console */
+		video_putchar ( console_col * VIDEO_FONT_WIDTH,
+				console_row * VIDEO_FONT_HEIGHT, c);
+		console_col++;
+		/* Check if we need to go to next row */
+		if (console_col >= CONSOLE_COLS)
+			console_newline ();
+	}
+}
+
+void video_puts (const char *s)
+{
+	int count = strlen (s);
+
+	if (!video_enable)
+		while (count--)
+			serial_putc (*s++);
+	else
+		while (count--)
+			video_putc (*s++);
+}
+
+/************************************************************************/
+/* ** CURSOR BLINKING FUNCTIONS						*/
+/************************************************************************/
+
+#ifdef VIDEO_BLINK
+
+#define BLINK_TIMER_ID		0
+#define BLINK_TIMER_HZ		2
+
+static unsigned char blink_enabled = 0;
+static timer_t blink_timer;
+
+static void blink_update (void)
+{
+	static int blink_row = -1, blink_col = -1, blink_old = 0;
+
+	/* Check if we have a new position to invert */
+	if ((console_row != blink_row) || (console_col != blink_col)) {
+		/* Check if we need to reverse last character */
+		if (blink_old)
+			video_revchar ( blink_col * VIDEO_FONT_WIDTH,
+					(blink_row
+#ifdef CONFIG_VIDEO_LOGO
+					 + VIDEO_LOGO_HEIGHT
+#endif
+					) * VIDEO_FONT_HEIGHT);
+
+		/* Update values */
+		blink_row = console_row;
+		blink_col = console_col;
+		blink_old = 0;
+	}
+
+/* Reverse this character */
+	blink_old = !blink_old;
+	video_revchar ( console_col * VIDEO_FONT_WIDTH,
+			(console_row
+#ifdef CONFIG_VIDEO_LOGO
+			+ VIDEO_LOGO_HEIGHT
+#endif
+			) * VIDEO_FONT_HEIGHT);
+
+}
+
+/*
+ * Handler for blinking cursor
+ */
+static void blink_handler (void *arg)
+{
+/* Blink */
+	blink_update ();
+/* Ack the timer */
+	timer_ack (&blink_timer);
+}
+
+int blink_set (int blink)
+{
+	int ret = blink_enabled;
+
+	if (blink)
+		timer_enable (&blink_timer);
+	else
+		timer_disable (&blink_timer);
+
+	blink_enabled = blink;
+
+	return ret;
+}
+
+static inline void blink_close (void)
+{
+	timer_close (&blink_timer);
+}
+
+static inline void blink_init (void)
+{
+	timer_init (&blink_timer,
+			BLINK_TIMER_ID, BLINK_TIMER_HZ,
+			blink_handler);
+}
+#endif
+
+/************************************************************************/
+/* ** LOGO PLOTTING FUNCTIONS						*/
+/************************************************************************/
+
+#ifdef CONFIG_VIDEO_LOGO
+void easylogo_plot (fastimage_t * image, void *screen, int width, int x,
+					int y)
+{
+	int skip = width - image->width, xcount, ycount = image->height;
+
+#ifdef VIDEO_MODE_YUYV
+	ushort *source = (ushort *) image->data;
+	ushort *dest   = (ushort *) screen + y * width + x;
+
+	while (ycount--) {
+		xcount = image->width;
+		while (xcount--)
+			*dest++ = *source++;
+		dest += skip;
+	}
+#endif
+#ifdef VIDEO_MODE_RGB
+	unsigned char
+	*source = (unsigned short *) image->data,
+			*dest = (unsigned short *) screen + ((y * width) + x) * 3;
+
+	while (ycount--) {
+		xcount = image->width * 3;
+		memcpy (dest, source, xcount);
+		source += xcount;
+		dest += ycount;
+	}
+#endif
+}
+
+static void *video_logo (void)
+{
+	u16 *screen = video_fb_address, width = VIDEO_COLS;
+#ifdef VIDEO_INFO
+# ifndef CONFIG_FADS
+	char temp[32];
+# endif
+	char info[80];
+#endif /* VIDEO_INFO */
+
+	easylogo_plot (VIDEO_LOGO_ADDR, screen, width, 0, 0);
+
+#ifdef VIDEO_INFO
+	sprintf (info, "%s (%s - %s) ",
+		 U_BOOT_VERSION, U_BOOT_DATE, U_BOOT_TIME);
+	video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y, info);
+
+	sprintf (info, "(C) 2002 DENX Software Engineering");
+	video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y + VIDEO_FONT_HEIGHT,
+					info);
+
+	sprintf (info, "    Wolfgang DENK, wd@denx.de");
+	video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y + VIDEO_FONT_HEIGHT * 2,
+					info);
+#ifndef CONFIG_FADS		/* all normal boards */
+	/* leave one blank line */
+
+	sprintf (info, "MPC823 CPU at %s MHz, %ld MB RAM, %ld MB Flash",
+		strmhz(temp, gd->cpu_clk),
+		gd->ram_size >> 20,
+		gd->bd->bi_flashsize >> 20 );
+	video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y + VIDEO_FONT_HEIGHT * 4,
+					info);
+#else				/* FADS :-( */
+	sprintf (info, "MPC823 CPU at 50 MHz on FADS823 board");
+	video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y + VIDEO_FONT_HEIGHT,
+					  info);
+
+	sprintf (info, "2MB FLASH - 8MB DRAM - 4MB SRAM");
+	video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y + VIDEO_FONT_HEIGHT * 2,
+					  info);
+#endif
+#endif
+
+	return video_fb_address + VIDEO_LOGO_HEIGHT * VIDEO_LINE_LEN;
+}
+#endif
+
+/************************************************************************/
+/* ** VIDEO HIGH-LEVEL FUNCTIONS					*/
+/************************************************************************/
+
+static int video_init (void *videobase)
+{
+	/* Initialize the encoder */
+	debug ("[VIDEO] Initializing video encoder...\n");
+	video_encoder_init ();
+
+	/* Initialize the video controller */
+	debug ("[VIDEO] Initializing video controller at %08x...\n",
+		   (int) videobase);
+	video_ctrl_init (videobase);
+
+	/* Setting the palette */
+	video_setpalette  (CONSOLE_COLOR_BLACK,	     0,	   0,	 0);
+	video_setpalette  (CONSOLE_COLOR_RED,	  0xFF,	   0,	 0);
+	video_setpalette  (CONSOLE_COLOR_GREEN,	     0, 0xFF,	 0);
+	video_setpalette  (CONSOLE_COLOR_YELLOW,  0xFF, 0xFF,	 0);
+	video_setpalette  (CONSOLE_COLOR_BLUE,	     0,	   0, 0xFF);
+	video_setpalette  (CONSOLE_COLOR_MAGENTA, 0xFF,	   0, 0xFF);
+	video_setpalette  (CONSOLE_COLOR_CYAN,	     0, 0xFF, 0xFF);
+	video_setpalette  (CONSOLE_COLOR_GREY,	  0xAA, 0xAA, 0xAA);
+	video_setpalette  (CONSOLE_COLOR_GREY2,	  0xF8, 0xF8, 0xF8);
+	video_setpalette  (CONSOLE_COLOR_WHITE,	  0xFF, 0xFF, 0xFF);
+
+#ifndef CONFIG_SYS_WHITE_ON_BLACK
+	video_setfgcolor (CONSOLE_COLOR_BLACK);
+	video_setbgcolor (CONSOLE_COLOR_GREY2);
+#else
+	video_setfgcolor (CONSOLE_COLOR_GREY2);
+	video_setbgcolor (CONSOLE_COLOR_BLACK);
+#endif	/* CONFIG_SYS_WHITE_ON_BLACK */
+
+#ifdef CONFIG_VIDEO_LOGO
+	/* Paint the logo and retrieve tv base address */
+	debug ("[VIDEO] Drawing the logo...\n");
+	video_console_address = video_logo ();
+#else
+	video_console_address = video_fb_address;
+#endif
+
+#ifdef VIDEO_BLINK
+	/* Enable the blinking (under construction) */
+	blink_init ();
+	blink_set (0);				/* To Fix! */
+#endif
+
+	/* Initialize the console */
+	console_col = 0;
+	console_row = 0;
+	video_enable = 1;
+
+#ifdef VIDEO_MODE_PAL
+# define VIDEO_MODE_TMP1	"PAL"
+#endif
+#ifdef VIDEO_MODE_NTSC
+# define VIDEO_MODE_TMP1	"NTSC"
+#endif
+#ifdef VIDEO_MODE_YUYV
+# define VIDEO_MODE_TMP2	"YCbYCr"
+#endif
+#ifdef VIDEO_MODE_RGB
+# define VIDEO_MODE_TMP2	"RGB"
+#endif
+	debug ( VIDEO_MODE_TMP1
+		" %dx%dx%d (" VIDEO_MODE_TMP2 ") on %s - console %dx%d\n",
+			VIDEO_COLS, VIDEO_ROWS, VIDEO_MODE_BPP,
+			VIDEO_ENCODER_NAME, CONSOLE_COLS, CONSOLE_ROWS);
+	return 0;
+}
+
+int drv_video_init (void)
+{
+	int error, devices = 1;
+
+	struct stdio_dev videodev;
+
+	video_init ((void *)(gd->fb_base));	/* Video initialization */
+
+/* Device initialization */
+
+	memset (&videodev, 0, sizeof (videodev));
+
+	strcpy (videodev.name, "video");
+	videodev.ext = DEV_EXT_VIDEO;	/* Video extensions */
+	videodev.flags = DEV_FLAGS_OUTPUT;	/* Output only */
+	videodev.putc = video_putc;	/* 'putc' function */
+	videodev.puts = video_puts;	/* 'puts' function */
+
+	error = stdio_register (&videodev);
+
+	return (error == 0) ? devices : error;
+}
+
+/************************************************************************/
+/* ** ROM capable initialization part - needed to reserve FB memory	*/
+/************************************************************************/
+
+/*
+ * This is called early in the system initialization to grab memory
+ * for the video controller.
+ * Returns new address for monitor, after reserving video buffer memory
+ *
+ * Note that this is running from ROM, so no write access to global data.
+ */
+ulong video_setmem (ulong addr)
+{
+	/* Allocate pages for the frame buffer. */
+	addr -= VIDEO_SIZE;
+
+	debug ("Reserving %dk for Video Framebuffer at: %08lx\n",
+		VIDEO_SIZE>>10, addr);
+
+	return (addr);
+}
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8xx/wlkbd.c b/arch/powerpc/cpu/mpc8xx/wlkbd.c
new file mode 100644
index 0000000..13009e2
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/wlkbd.c
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2000
+ * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+
+#ifdef CONFIG_WL_4PPM_KEYBOARD
+
+/* WIP: Wireless keyboard on SMC
+ */
+int	drv_wlkbd_init (void)
+{
+    return 0 ;
+}
+
+#endif	/* CONFIG_WL_4PPM_KEYBOARD */
diff --git a/arch/powerpc/cpu/mpc8xxx/Makefile b/arch/powerpc/cpu/mpc8xxx/Makefile
new file mode 100644
index 0000000..481f9e5
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/Makefile
@@ -0,0 +1,27 @@
+#
+# Copyright 2009 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
+# Version 2 as published by the Free Software Foundation.
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib8xxx.a
+
+COBJS-y	+= cpu.o
+COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
+COBJS-$(CONFIG_PCI)	+= pci_cfg.o
+
+SRCS	:= $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
diff --git a/arch/powerpc/cpu/mpc8xxx/cpu.c b/arch/powerpc/cpu/mpc8xxx/cpu.c
new file mode 100644
index 0000000..22f3423
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/cpu.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * This file is derived from arch/powerpc/cpu/mpc85xx/cpu.c and
+ * arch/powerpc/cpu/mpc86xx/cpu.c. Basically this file contains
+ * cpu specific common code for 85xx/86xx processors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+#include <tsec.h>
+#include <netdev.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct cpu_type cpu_type_list [] = {
+#if defined(CONFIG_MPC85xx)
+	CPU_TYPE_ENTRY(8533, 8533, 1),
+	CPU_TYPE_ENTRY(8533, 8533_E, 1),
+	CPU_TYPE_ENTRY(8535, 8535, 1),
+	CPU_TYPE_ENTRY(8535, 8535_E, 1),
+	CPU_TYPE_ENTRY(8536, 8536, 1),
+	CPU_TYPE_ENTRY(8536, 8536_E, 1),
+	CPU_TYPE_ENTRY(8540, 8540, 1),
+	CPU_TYPE_ENTRY(8541, 8541, 1),
+	CPU_TYPE_ENTRY(8541, 8541_E, 1),
+	CPU_TYPE_ENTRY(8543, 8543, 1),
+	CPU_TYPE_ENTRY(8543, 8543_E, 1),
+	CPU_TYPE_ENTRY(8544, 8544, 1),
+	CPU_TYPE_ENTRY(8544, 8544_E, 1),
+	CPU_TYPE_ENTRY(8545, 8545, 1),
+	CPU_TYPE_ENTRY(8545, 8545_E, 1),
+	CPU_TYPE_ENTRY(8547, 8547_E, 1),
+	CPU_TYPE_ENTRY(8548, 8548, 1),
+	CPU_TYPE_ENTRY(8548, 8548_E, 1),
+	CPU_TYPE_ENTRY(8555, 8555, 1),
+	CPU_TYPE_ENTRY(8555, 8555_E, 1),
+	CPU_TYPE_ENTRY(8560, 8560, 1),
+	CPU_TYPE_ENTRY(8567, 8567, 1),
+	CPU_TYPE_ENTRY(8567, 8567_E, 1),
+	CPU_TYPE_ENTRY(8568, 8568, 1),
+	CPU_TYPE_ENTRY(8568, 8568_E, 1),
+	CPU_TYPE_ENTRY(8569, 8569, 1),
+	CPU_TYPE_ENTRY(8569, 8569_E, 1),
+	CPU_TYPE_ENTRY(8572, 8572, 2),
+	CPU_TYPE_ENTRY(8572, 8572_E, 2),
+	CPU_TYPE_ENTRY(P1011, P1011, 1),
+	CPU_TYPE_ENTRY(P1011, P1011_E, 1),
+	CPU_TYPE_ENTRY(P1012, P1012, 1),
+	CPU_TYPE_ENTRY(P1012, P1012_E, 1),
+	CPU_TYPE_ENTRY(P1013, P1013, 1),
+	CPU_TYPE_ENTRY(P1013, P1013_E, 1),
+	CPU_TYPE_ENTRY(P1020, P1020, 2),
+	CPU_TYPE_ENTRY(P1020, P1020_E, 2),
+	CPU_TYPE_ENTRY(P1021, P1021, 2),
+	CPU_TYPE_ENTRY(P1021, P1021_E, 2),
+	CPU_TYPE_ENTRY(P1022, P1022, 2),
+	CPU_TYPE_ENTRY(P1022, P1022_E, 2),
+	CPU_TYPE_ENTRY(P2010, P2010, 1),
+	CPU_TYPE_ENTRY(P2010, P2010_E, 1),
+	CPU_TYPE_ENTRY(P2020, P2020, 2),
+	CPU_TYPE_ENTRY(P2020, P2020_E, 2),
+	CPU_TYPE_ENTRY(P4040, P4040, 4),
+	CPU_TYPE_ENTRY(P4040, P4040_E, 4),
+	CPU_TYPE_ENTRY(P4080, P4080, 8),
+	CPU_TYPE_ENTRY(P4080, P4080_E, 8),
+#elif defined(CONFIG_MPC86xx)
+	CPU_TYPE_ENTRY(8610, 8610, 1),
+	CPU_TYPE_ENTRY(8641, 8641, 2),
+	CPU_TYPE_ENTRY(8641D, 8641D, 2),
+#endif
+};
+
+struct cpu_type cpu_type_unknown = CPU_TYPE_ENTRY(Unknown, Unknown, 1);
+
+struct cpu_type *identify_cpu(u32 ver)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++) {
+		if (cpu_type_list[i].soc_ver == ver)
+			return &cpu_type_list[i];
+	}
+	return &cpu_type_unknown;
+}
+
+int cpu_numcores() {
+	struct cpu_type *cpu;
+	cpu = gd->cpu;
+	return cpu->num_cores;
+}
+
+int probecpu (void)
+{
+	uint svr;
+	uint ver;
+
+	svr = get_svr();
+	ver = SVR_SOC_VER(svr);
+
+	gd->cpu = identify_cpu(ver);
+
+	return 0;
+}
+
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_ETHER_ON_FCC)
+	fec_initialize(bis);
+#endif
+
+#if defined(CONFIG_UEC_ETH)
+	uec_standard_init(bis);
+#endif
+
+#if defined(CONFIG_TSEC_ENET) || defined(CONFIG_MPC85XX_FEC)
+	tsec_standard_init(bis);
+#endif
+
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/Makefile b/arch/powerpc/cpu/mpc8xxx/ddr/Makefile
new file mode 100644
index 0000000..cb7f856
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/Makefile
@@ -0,0 +1,35 @@
+#
+# Copyright 2008 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
+# Version 2 as published by the Free Software Foundation.
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)libddr.a
+
+COBJS-$(CONFIG_FSL_DDR1)	+= main.o util.o ctrl_regs.o options.o \
+				   lc_common_dimm_params.o
+COBJS-$(CONFIG_FSL_DDR1)	+= ddr1_dimm_params.o
+
+COBJS-$(CONFIG_FSL_DDR2)	+= main.o util.o ctrl_regs.o options.o \
+				   lc_common_dimm_params.o
+COBJS-$(CONFIG_FSL_DDR2)	+= ddr2_dimm_params.o
+
+COBJS-$(CONFIG_FSL_DDR3)	+= main.o util.o ctrl_regs.o options.o \
+				   lc_common_dimm_params.o
+COBJS-$(CONFIG_FSL_DDR3)	+= ddr3_dimm_params.o
+
+SRCS	:= $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h b/arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h
new file mode 100644
index 0000000..5aea517
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2008 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef COMMON_TIMING_PARAMS_H
+#define COMMON_TIMING_PARAMS_H
+
+typedef struct {
+	/* parameters to constrict */
+
+	unsigned int tCKmin_X_ps;
+	unsigned int tCKmax_ps;
+	unsigned int tCKmax_max_ps;
+	unsigned int tRCD_ps;
+	unsigned int tRP_ps;
+	unsigned int tRAS_ps;
+
+	unsigned int tWR_ps;	/* maximum = 63750 ps */
+	unsigned int tWTR_ps;	/* maximum = 63750 ps */
+	unsigned int tRFC_ps;	/* maximum = 255 ns + 256 ns + .75 ns
+					   = 511750 ps */
+
+	unsigned int tRRD_ps;	/* maximum = 63750 ps */
+	unsigned int tRC_ps;	/* maximum = 254 ns + .75 ns = 254750 ps */
+
+	unsigned int refresh_rate_ps;
+
+	unsigned int tIS_ps;	/* byte 32, spd->ca_setup */
+	unsigned int tIH_ps;	/* byte 33, spd->ca_hold */
+	unsigned int tDS_ps;	/* byte 34, spd->data_setup */
+	unsigned int tDH_ps;	/* byte 35, spd->data_hold */
+	unsigned int tRTP_ps;	/* byte 38, spd->trtp */
+	unsigned int tDQSQ_max_ps;	/* byte 44, spd->tdqsq */
+	unsigned int tQHS_ps;	/* byte 45, spd->tqhs */
+
+	unsigned int ndimms_present;
+	unsigned int lowest_common_SPD_caslat;
+	unsigned int highest_common_derated_caslat;
+	unsigned int additive_latency;
+	unsigned int all_DIMMs_burst_lengths_bitmask;
+	unsigned int all_DIMMs_registered;
+	unsigned int all_DIMMs_unbuffered;
+	unsigned int all_DIMMs_ECC_capable;
+
+	unsigned long long total_mem;
+	unsigned long long base_address;
+} common_timing_params_t;
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
new file mode 100644
index 0000000..03f9c43
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
@@ -0,0 +1,1366 @@
+/*
+ * Copyright 2008-2010 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.
+ */
+
+/*
+ * Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
+ * Based on code from spd_sdram.c
+ * Author: James Yang [at freescale.com]
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+
+extern unsigned int picos_to_mclk(unsigned int picos);
+/*
+ * Determine Rtt value.
+ *
+ * This should likely be either board or controller specific.
+ *
+ * Rtt(nominal) - DDR2:
+ *	0 = Rtt disabled
+ *	1 = 75 ohm
+ *	2 = 150 ohm
+ *	3 = 50 ohm
+ * Rtt(nominal) - DDR3:
+ *	0 = Rtt disabled
+ *	1 = 60 ohm
+ *	2 = 120 ohm
+ *	3 = 40 ohm
+ *	4 = 20 ohm
+ *	5 = 30 ohm
+ *
+ * FIXME: Apparently 8641 needs a value of 2
+ * FIXME: Old code seys if 667 MHz or higher, use 3 on 8572
+ *
+ * FIXME: There was some effort down this line earlier:
+ *
+ *	unsigned int i;
+ *	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL/2; i++) {
+ *		if (popts->dimmslot[i].num_valid_cs
+ *		    && (popts->cs_local_opts[2*i].odt_rd_cfg
+ *			|| popts->cs_local_opts[2*i].odt_wr_cfg)) {
+ *			rtt = 2;
+ *			break;
+ *		}
+ *	}
+ */
+static inline int fsl_ddr_get_rtt(void)
+{
+	int rtt;
+
+#if defined(CONFIG_FSL_DDR1)
+	rtt = 0;
+#elif defined(CONFIG_FSL_DDR2)
+	rtt = 3;
+#else
+	rtt = 0;
+#endif
+
+	return rtt;
+}
+
+/*
+ * compute the CAS write latency according to DDR3 spec
+ * CWL = 5 if tCK >= 2.5ns
+ *       6 if 2.5ns > tCK >= 1.875ns
+ *       7 if 1.875ns > tCK >= 1.5ns
+ *       8 if 1.5ns > tCK >= 1.25ns
+ */
+static inline unsigned int compute_cas_write_latency(void)
+{
+	unsigned int cwl;
+	const unsigned int mclk_ps = get_memory_clk_period_ps();
+
+	if (mclk_ps >= 2500)
+		cwl = 5;
+	else if (mclk_ps >= 1875)
+		cwl = 6;
+	else if (mclk_ps >= 1500)
+		cwl = 7;
+	else if (mclk_ps >= 1250)
+		cwl = 8;
+	else
+		cwl = 8;
+	return cwl;
+}
+
+/* Chip Select Configuration (CSn_CONFIG) */
+static void set_csn_config(int i, fsl_ddr_cfg_regs_t *ddr,
+			       const memctl_options_t *popts,
+			       const dimm_params_t *dimm_params)
+{
+	unsigned int cs_n_en = 0; /* Chip Select enable */
+	unsigned int intlv_en = 0; /* Memory controller interleave enable */
+	unsigned int intlv_ctl = 0; /* Interleaving control */
+	unsigned int ap_n_en = 0; /* Chip select n auto-precharge enable */
+	unsigned int odt_rd_cfg = 0; /* ODT for reads configuration */
+	unsigned int odt_wr_cfg = 0; /* ODT for writes configuration */
+	unsigned int ba_bits_cs_n = 0; /* Num of bank bits for SDRAM on CSn */
+	unsigned int row_bits_cs_n = 0; /* Num of row bits for SDRAM on CSn */
+	unsigned int col_bits_cs_n = 0; /* Num of ocl bits for SDRAM on CSn */
+
+	/* Compute CS_CONFIG only for existing ranks of each DIMM.  */
+	if ((((i&1) == 0)
+	    && (dimm_params[i/2].n_ranks == 1))
+	    || (dimm_params[i/2].n_ranks == 2)) {
+		unsigned int n_banks_per_sdram_device;
+		cs_n_en = 1;
+		if (i == 0) {
+			/* These fields only available in CS0_CONFIG */
+			intlv_en = popts->memctl_interleaving;
+			intlv_ctl = popts->memctl_interleaving_mode;
+		}
+		ap_n_en = popts->cs_local_opts[i].auto_precharge;
+		odt_rd_cfg = popts->cs_local_opts[i].odt_rd_cfg;
+		odt_wr_cfg = popts->cs_local_opts[i].odt_wr_cfg;
+		n_banks_per_sdram_device
+			= dimm_params[i/2].n_banks_per_sdram_device;
+		ba_bits_cs_n = __ilog2(n_banks_per_sdram_device) - 2;
+		row_bits_cs_n = dimm_params[i/2].n_row_addr - 12;
+		col_bits_cs_n = dimm_params[i/2].n_col_addr - 8;
+	}
+
+	ddr->cs[i].config = (0
+		| ((cs_n_en & 0x1) << 31)
+		| ((intlv_en & 0x3) << 29)
+		| ((intlv_ctl & 0xf) << 24)
+		| ((ap_n_en & 0x1) << 23)
+
+		/* XXX: some implementation only have 1 bit starting at left */
+		| ((odt_rd_cfg & 0x7) << 20)
+
+		/* XXX: Some implementation only have 1 bit starting at left */
+		| ((odt_wr_cfg & 0x7) << 16)
+
+		| ((ba_bits_cs_n & 0x3) << 14)
+		| ((row_bits_cs_n & 0x7) << 8)
+		| ((col_bits_cs_n & 0x7) << 0)
+		);
+	debug("FSLDDR: cs[%d]_config = 0x%08x\n", i,ddr->cs[i].config);
+}
+
+/* Chip Select Configuration 2 (CSn_CONFIG_2) */
+/* FIXME: 8572 */
+static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr)
+{
+	unsigned int pasr_cfg = 0;	/* Partial array self refresh config */
+
+	ddr->cs[i].config_2 = ((pasr_cfg & 7) << 24);
+	debug("FSLDDR: cs[%d]_config_2 = 0x%08x\n", i, ddr->cs[i].config_2);
+}
+
+/* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */
+
+#if !defined(CONFIG_FSL_DDR1)
+/*
+ * DDR SDRAM Timing Configuration 0 (TIMING_CFG_0)
+ *
+ * Avoid writing for DDR I.  The new PQ38 DDR controller
+ * dreams up non-zero default values to be backwards compatible.
+ */
+static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr)
+{
+	unsigned char trwt_mclk = 0;   /* Read-to-write turnaround */
+	unsigned char twrt_mclk = 0;   /* Write-to-read turnaround */
+	/* 7.5 ns on -3E; 0 means WL - CL + BL/2 + 1 */
+	unsigned char trrt_mclk = 0;   /* Read-to-read turnaround */
+	unsigned char twwt_mclk = 0;   /* Write-to-write turnaround */
+
+	/* Active powerdown exit timing (tXARD and tXARDS). */
+	unsigned char act_pd_exit_mclk;
+	/* Precharge powerdown exit timing (tXP). */
+	unsigned char pre_pd_exit_mclk;
+	/* Precharge powerdown exit timing (tAXPD). */
+	unsigned char taxpd_mclk;
+	/* Mode register set cycle time (tMRD). */
+	unsigned char tmrd_mclk;
+
+#if defined(CONFIG_FSL_DDR3)
+	/*
+	 * (tXARD and tXARDS). Empirical?
+	 * The DDR3 spec has not tXARD,
+	 * we use the tXP instead of it.
+	 * tXP=max(3nCK, 7.5ns) for DDR3.
+	 * spec has not the tAXPD, we use
+	 * tAXPD=8, need design to confirm.
+	 */
+	int tXP = max((get_memory_clk_period_ps() * 3), 7500); /* unit=ps */
+	act_pd_exit_mclk = picos_to_mclk(tXP);
+	/* Mode register MR0[A12] is '1' - fast exit */
+	pre_pd_exit_mclk = act_pd_exit_mclk;
+	taxpd_mclk = 8;
+	tmrd_mclk = 4;
+#else /* CONFIG_FSL_DDR2 */
+	/*
+	 * (tXARD and tXARDS). Empirical?
+	 * tXARD = 2 for DDR2
+	 * tXP=2
+	 * tAXPD=8
+	 */
+	act_pd_exit_mclk = 2;
+	pre_pd_exit_mclk = 2;
+	taxpd_mclk = 8;
+	tmrd_mclk = 2;
+#endif
+
+	ddr->timing_cfg_0 = (0
+		| ((trwt_mclk & 0x3) << 30)	/* RWT */
+		| ((twrt_mclk & 0x3) << 28)	/* WRT */
+		| ((trrt_mclk & 0x3) << 26)	/* RRT */
+		| ((twwt_mclk & 0x3) << 24)	/* WWT */
+		| ((act_pd_exit_mclk & 0x7) << 20)  /* ACT_PD_EXIT */
+		| ((pre_pd_exit_mclk & 0xF) << 16)  /* PRE_PD_EXIT */
+		| ((taxpd_mclk & 0xf) << 8)	/* ODT_PD_EXIT */
+		| ((tmrd_mclk & 0xf) << 0)	/* MRS_CYC */
+		);
+	debug("FSLDDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);
+}
+#endif	/* defined(CONFIG_FSL_DDR2) */
+
+/* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */
+static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr,
+			       const common_timing_params_t *common_dimm,
+			       unsigned int cas_latency)
+{
+	/* Extended Activate to precharge interval (tRAS) */
+	unsigned int ext_acttopre = 0;
+	unsigned int ext_refrec; /* Extended refresh recovery time (tRFC) */
+	unsigned int ext_caslat = 0; /* Extended MCAS latency from READ cmd */
+	unsigned int cntl_adj = 0; /* Control Adjust */
+
+	/* If the tRAS > 19 MCLK, we use the ext mode */
+	if (picos_to_mclk(common_dimm->tRAS_ps) > 0x13)
+		ext_acttopre = 1;
+
+	ext_refrec = (picos_to_mclk(common_dimm->tRFC_ps) - 8) >> 4;
+
+	/* If the CAS latency more than 8, use the ext mode */
+	if (cas_latency > 8)
+		ext_caslat = 1;
+
+	ddr->timing_cfg_3 = (0
+		| ((ext_acttopre & 0x1) << 24)
+		| ((ext_refrec & 0xF) << 16)
+		| ((ext_caslat & 0x1) << 12)
+		| ((cntl_adj & 0x7) << 0)
+		);
+	debug("FSLDDR: timing_cfg_3 = 0x%08x\n", ddr->timing_cfg_3);
+}
+
+/* DDR SDRAM Timing Configuration 1 (TIMING_CFG_1) */
+static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr,
+			       const memctl_options_t *popts,
+			       const common_timing_params_t *common_dimm,
+			       unsigned int cas_latency)
+{
+	/* Precharge-to-activate interval (tRP) */
+	unsigned char pretoact_mclk;
+	/* Activate to precharge interval (tRAS) */
+	unsigned char acttopre_mclk;
+	/*  Activate to read/write interval (tRCD) */
+	unsigned char acttorw_mclk;
+	/* CASLAT */
+	unsigned char caslat_ctrl;
+	/*  Refresh recovery time (tRFC) ; trfc_low */
+	unsigned char refrec_ctrl;
+	/* Last data to precharge minimum interval (tWR) */
+	unsigned char wrrec_mclk;
+	/* Activate-to-activate interval (tRRD) */
+	unsigned char acttoact_mclk;
+	/* Last write data pair to read command issue interval (tWTR) */
+	unsigned char wrtord_mclk;
+
+	pretoact_mclk = picos_to_mclk(common_dimm->tRP_ps);
+	acttopre_mclk = picos_to_mclk(common_dimm->tRAS_ps);
+	acttorw_mclk = picos_to_mclk(common_dimm->tRCD_ps);
+
+	/*
+	 * Translate CAS Latency to a DDR controller field value:
+	 *
+	 *      CAS Lat DDR I   DDR II  Ctrl
+	 *      Clocks  SPD Bit SPD Bit Value
+	 *      ------- ------- ------- -----
+	 *      1.0     0               0001
+	 *      1.5     1               0010
+	 *      2.0     2       2       0011
+	 *      2.5     3               0100
+	 *      3.0     4       3       0101
+	 *      3.5     5               0110
+	 *      4.0             4       0111
+	 *      4.5                     1000
+	 *      5.0             5       1001
+	 */
+#if defined(CONFIG_FSL_DDR1)
+	caslat_ctrl = (cas_latency + 1) & 0x07;
+#elif defined(CONFIG_FSL_DDR2)
+	caslat_ctrl = 2 * cas_latency - 1;
+#else
+	/*
+	 * if the CAS latency more than 8 cycle,
+	 * we need set extend bit for it at
+	 * TIMING_CFG_3[EXT_CASLAT]
+	 */
+	if (cas_latency > 8)
+		cas_latency -= 8;
+	caslat_ctrl = 2 * cas_latency - 1;
+#endif
+
+	refrec_ctrl = picos_to_mclk(common_dimm->tRFC_ps) - 8;
+	wrrec_mclk = picos_to_mclk(common_dimm->tWR_ps);
+	if (popts->OTF_burst_chop_en)
+		wrrec_mclk += 2;
+
+	acttoact_mclk = picos_to_mclk(common_dimm->tRRD_ps);
+	/*
+	 * JEDEC has min requirement for tRRD
+	 */
+#if defined(CONFIG_FSL_DDR3)
+	if (acttoact_mclk < 4)
+		acttoact_mclk = 4;
+#endif
+	wrtord_mclk = picos_to_mclk(common_dimm->tWTR_ps);
+	/*
+	 * JEDEC has some min requirements for tWTR
+	 */
+#if defined(CONFIG_FSL_DDR2)
+	if (wrtord_mclk < 2)
+		wrtord_mclk = 2;
+#elif defined(CONFIG_FSL_DDR3)
+	if (wrtord_mclk < 4)
+		wrtord_mclk = 4;
+#endif
+	if (popts->OTF_burst_chop_en)
+		wrtord_mclk += 2;
+
+	ddr->timing_cfg_1 = (0
+		| ((pretoact_mclk & 0x0F) << 28)
+		| ((acttopre_mclk & 0x0F) << 24)
+		| ((acttorw_mclk & 0xF) << 20)
+		| ((caslat_ctrl & 0xF) << 16)
+		| ((refrec_ctrl & 0xF) << 12)
+		| ((wrrec_mclk & 0x0F) << 8)
+		| ((acttoact_mclk & 0x07) << 4)
+		| ((wrtord_mclk & 0x07) << 0)
+		);
+	debug("FSLDDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1);
+}
+
+/* DDR SDRAM Timing Configuration 2 (TIMING_CFG_2) */
+static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr,
+			       const memctl_options_t *popts,
+			       const common_timing_params_t *common_dimm,
+			       unsigned int cas_latency,
+			       unsigned int additive_latency)
+{
+	/* Additive latency */
+	unsigned char add_lat_mclk;
+	/* CAS-to-preamble override */
+	unsigned short cpo;
+	/* Write latency */
+	unsigned char wr_lat;
+	/*  Read to precharge (tRTP) */
+	unsigned char rd_to_pre;
+	/* Write command to write data strobe timing adjustment */
+	unsigned char wr_data_delay;
+	/* Minimum CKE pulse width (tCKE) */
+	unsigned char cke_pls;
+	/* Window for four activates (tFAW) */
+	unsigned short four_act;
+
+	/* FIXME add check that this must be less than acttorw_mclk */
+	add_lat_mclk = additive_latency;
+	cpo = popts->cpo_override;
+
+#if defined(CONFIG_FSL_DDR1)
+	/*
+	 * This is a lie.  It should really be 1, but if it is
+	 * set to 1, bits overlap into the old controller's
+	 * otherwise unused ACSM field.  If we leave it 0, then
+	 * the HW will magically treat it as 1 for DDR 1.  Oh Yea.
+	 */
+	wr_lat = 0;
+#elif defined(CONFIG_FSL_DDR2)
+	wr_lat = cas_latency - 1;
+#else
+	wr_lat = compute_cas_write_latency();
+#endif
+
+	rd_to_pre = picos_to_mclk(common_dimm->tRTP_ps);
+	/*
+	 * JEDEC has some min requirements for tRTP
+	 */
+#if defined(CONFIG_FSL_DDR2)
+	if (rd_to_pre  < 2)
+		rd_to_pre  = 2;
+#elif defined(CONFIG_FSL_DDR3)
+	if (rd_to_pre < 4)
+		rd_to_pre = 4;
+#endif
+	if (additive_latency)
+		rd_to_pre += additive_latency;
+	if (popts->OTF_burst_chop_en)
+		rd_to_pre += 2; /* according to UM */
+
+	wr_data_delay = popts->write_data_delay;
+	cke_pls = picos_to_mclk(popts->tCKE_clock_pulse_width_ps);
+	four_act = picos_to_mclk(popts->tFAW_window_four_activates_ps);
+
+	ddr->timing_cfg_2 = (0
+		| ((add_lat_mclk & 0xf) << 28)
+		| ((cpo & 0x1f) << 23)
+		| ((wr_lat & 0xf) << 19)
+		| ((rd_to_pre & RD_TO_PRE_MASK) << RD_TO_PRE_SHIFT)
+		| ((wr_data_delay & WR_DATA_DELAY_MASK) << WR_DATA_DELAY_SHIFT)
+		| ((cke_pls & 0x7) << 6)
+		| ((four_act & 0x3f) << 0)
+		);
+	debug("FSLDDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2);
+}
+
+/* DDR SDRAM control configuration (DDR_SDRAM_CFG) */
+static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr,
+			       const memctl_options_t *popts,
+			       const common_timing_params_t *common_dimm)
+{
+	unsigned int mem_en;		/* DDR SDRAM interface logic enable */
+	unsigned int sren;		/* Self refresh enable (during sleep) */
+	unsigned int ecc_en;		/* ECC enable. */
+	unsigned int rd_en;		/* Registered DIMM enable */
+	unsigned int sdram_type;	/* Type of SDRAM */
+	unsigned int dyn_pwr;		/* Dynamic power management mode */
+	unsigned int dbw;		/* DRAM dta bus width */
+	unsigned int eight_be = 0;	/* 8-beat burst enable, DDR2 is zero */
+	unsigned int ncap = 0;		/* Non-concurrent auto-precharge */
+	unsigned int threeT_en;		/* Enable 3T timing */
+	unsigned int twoT_en;		/* Enable 2T timing */
+	unsigned int ba_intlv_ctl;	/* Bank (CS) interleaving control */
+	unsigned int x32_en = 0;	/* x32 enable */
+	unsigned int pchb8 = 0;		/* precharge bit 8 enable */
+	unsigned int hse;		/* Global half strength override */
+	unsigned int mem_halt = 0;	/* memory controller halt */
+	unsigned int bi = 0;		/* Bypass initialization */
+
+	mem_en = 1;
+	sren = popts->self_refresh_in_sleep;
+	if (common_dimm->all_DIMMs_ECC_capable) {
+		/* Allow setting of ECC only if all DIMMs are ECC. */
+		ecc_en = popts->ECC_mode;
+	} else {
+		ecc_en = 0;
+	}
+
+	rd_en = (common_dimm->all_DIMMs_registered
+		 && !common_dimm->all_DIMMs_unbuffered);
+
+	sdram_type = CONFIG_FSL_SDRAM_TYPE;
+
+	dyn_pwr = popts->dynamic_power;
+	dbw = popts->data_bus_width;
+	/* 8-beat burst enable DDR-III case
+	 * we must clear it when use the on-the-fly mode,
+	 * must set it when use the 32-bits bus mode.
+	 */
+	if (sdram_type == SDRAM_TYPE_DDR3) {
+		if (popts->burst_length == DDR_BL8)
+			eight_be = 1;
+		if (popts->burst_length == DDR_OTF)
+			eight_be = 0;
+		if (dbw == 0x1)
+			eight_be = 1;
+	}
+
+	threeT_en = popts->threeT_en;
+	twoT_en = popts->twoT_en;
+	ba_intlv_ctl = popts->ba_intlv_ctl;
+	hse = popts->half_strength_driver_enable;
+
+	ddr->ddr_sdram_cfg = (0
+			| ((mem_en & 0x1) << 31)
+			| ((sren & 0x1) << 30)
+			| ((ecc_en & 0x1) << 29)
+			| ((rd_en & 0x1) << 28)
+			| ((sdram_type & 0x7) << 24)
+			| ((dyn_pwr & 0x1) << 21)
+			| ((dbw & 0x3) << 19)
+			| ((eight_be & 0x1) << 18)
+			| ((ncap & 0x1) << 17)
+			| ((threeT_en & 0x1) << 16)
+			| ((twoT_en & 0x1) << 15)
+			| ((ba_intlv_ctl & 0x7F) << 8)
+			| ((x32_en & 0x1) << 5)
+			| ((pchb8 & 0x1) << 4)
+			| ((hse & 0x1) << 3)
+			| ((mem_halt & 0x1) << 1)
+			| ((bi & 0x1) << 0)
+			);
+	debug("FSLDDR: ddr_sdram_cfg = 0x%08x\n", ddr->ddr_sdram_cfg);
+}
+
+/* DDR SDRAM control configuration 2 (DDR_SDRAM_CFG_2) */
+static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
+			       const memctl_options_t *popts)
+{
+	unsigned int frc_sr = 0;	/* Force self refresh */
+	unsigned int sr_ie = 0;		/* Self-refresh interrupt enable */
+	unsigned int dll_rst_dis;	/* DLL reset disable */
+	unsigned int dqs_cfg;		/* DQS configuration */
+	unsigned int odt_cfg;		/* ODT configuration */
+	unsigned int num_pr;		/* Number of posted refreshes */
+	unsigned int obc_cfg;		/* On-The-Fly Burst Chop Cfg */
+	unsigned int ap_en;		/* Address Parity Enable */
+	unsigned int d_init;		/* DRAM data initialization */
+	unsigned int rcw_en = 0;	/* Register Control Word Enable */
+	unsigned int md_en = 0;		/* Mirrored DIMM Enable */
+
+	dll_rst_dis = 1;	/* Make this configurable */
+	dqs_cfg = popts->DQS_config;
+	if (popts->cs_local_opts[0].odt_rd_cfg
+	    || popts->cs_local_opts[0].odt_wr_cfg) {
+		/* FIXME */
+		odt_cfg = 2;
+	} else {
+		odt_cfg = 0;
+	}
+
+	num_pr = 1;	/* Make this configurable */
+
+	/*
+	 * 8572 manual says
+	 *     {TIMING_CFG_1[PRETOACT]
+	 *      + [DDR_SDRAM_CFG_2[NUM_PR]
+	 *        * ({EXT_REFREC || REFREC} + 8 + 2)]}
+	 *      << DDR_SDRAM_INTERVAL[REFINT]
+	 */
+#if defined(CONFIG_FSL_DDR3)
+	obc_cfg = popts->OTF_burst_chop_en;
+#else
+	obc_cfg = 0;
+#endif
+
+	ap_en = 0;	/* Make this configurable? */
+
+#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+	/* Use the DDR controller to auto initialize memory. */
+	d_init = 1;
+	ddr->ddr_data_init = CONFIG_MEM_INIT_VALUE;
+	debug("DDR: ddr_data_init = 0x%08x\n", ddr->ddr_data_init);
+#else
+	/* Memory will be initialized via DMA, or not at all. */
+	d_init = 0;
+#endif
+
+#if defined(CONFIG_FSL_DDR3)
+	md_en = popts->mirrored_dimm;
+#endif
+	ddr->ddr_sdram_cfg_2 = (0
+		| ((frc_sr & 0x1) << 31)
+		| ((sr_ie & 0x1) << 30)
+		| ((dll_rst_dis & 0x1) << 29)
+		| ((dqs_cfg & 0x3) << 26)
+		| ((odt_cfg & 0x3) << 21)
+		| ((num_pr & 0xf) << 12)
+		| ((obc_cfg & 0x1) << 6)
+		| ((ap_en & 0x1) << 5)
+		| ((d_init & 0x1) << 4)
+		| ((rcw_en & 0x1) << 2)
+		| ((md_en & 0x1) << 0)
+		);
+	debug("FSLDDR: ddr_sdram_cfg_2 = 0x%08x\n", ddr->ddr_sdram_cfg_2);
+}
+
+/* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
+static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
+				const memctl_options_t *popts)
+{
+	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
+	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
+
+#if defined(CONFIG_FSL_DDR3)
+	unsigned int rtt_wr = 0;	/* Rtt_WR - dynamic ODT off */
+	unsigned int srt = 0;	/* self-refresh temerature, normal range */
+	unsigned int asr = 0;	/* auto self-refresh disable */
+	unsigned int cwl = compute_cas_write_latency() - 5;
+	unsigned int pasr = 0;	/* partial array self refresh disable */
+
+	if (popts->rtt_override)
+		rtt_wr = popts->rtt_wr_override_value;
+
+	esdmode2 = (0
+		| ((rtt_wr & 0x3) << 9)
+		| ((srt & 0x1) << 7)
+		| ((asr & 0x1) << 6)
+		| ((cwl & 0x7) << 3)
+		| ((pasr & 0x7) << 0));
+#endif
+	ddr->ddr_sdram_mode_2 = (0
+				 | ((esdmode2 & 0xFFFF) << 16)
+				 | ((esdmode3 & 0xFFFF) << 0)
+				 );
+	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
+}
+
+/* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */
+static void set_ddr_sdram_interval(fsl_ddr_cfg_regs_t *ddr,
+			       const memctl_options_t *popts,
+			       const common_timing_params_t *common_dimm)
+{
+	unsigned int refint;	/* Refresh interval */
+	unsigned int bstopre;	/* Precharge interval */
+
+	refint = picos_to_mclk(common_dimm->refresh_rate_ps);
+
+	bstopre = popts->bstopre;
+
+	/* refint field used 0x3FFF in earlier controllers */
+	ddr->ddr_sdram_interval = (0
+				   | ((refint & 0xFFFF) << 16)
+				   | ((bstopre & 0x3FFF) << 0)
+				   );
+	debug("FSLDDR: ddr_sdram_interval = 0x%08x\n", ddr->ddr_sdram_interval);
+}
+
+#if defined(CONFIG_FSL_DDR3)
+/* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
+static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
+			       const memctl_options_t *popts,
+			       const common_timing_params_t *common_dimm,
+			       unsigned int cas_latency,
+			       unsigned int additive_latency)
+{
+	unsigned short esdmode;		/* Extended SDRAM mode */
+	unsigned short sdmode;		/* SDRAM mode */
+
+	/* Mode Register - MR1 */
+	unsigned int qoff = 0;		/* Output buffer enable 0=yes, 1=no */
+	unsigned int tdqs_en = 0;	/* TDQS Enable: 0=no, 1=yes */
+	unsigned int rtt;
+	unsigned int wrlvl_en = 0;	/* Write level enable: 0=no, 1=yes */
+	unsigned int al = 0;		/* Posted CAS# additive latency (AL) */
+	unsigned int dic = 1;		/* Output driver impedance, 34ohm */
+	unsigned int dll_en = 0;	/* DLL Enable  0=Enable (Normal),
+						       1=Disable (Test/Debug) */
+
+	/* Mode Register - MR0 */
+	unsigned int dll_on;	/* DLL control for precharge PD, 0=off, 1=on */
+	unsigned int wr;	/* Write Recovery */
+	unsigned int dll_rst;	/* DLL Reset */
+	unsigned int mode;	/* Normal=0 or Test=1 */
+	unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
+	/* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
+	unsigned int bt;
+	unsigned int bl;	/* BL: Burst Length */
+
+	unsigned int wr_mclk;
+
+	const unsigned int mclk_ps = get_memory_clk_period_ps();
+
+	rtt = fsl_ddr_get_rtt();
+	if (popts->rtt_override)
+		rtt = popts->rtt_override_value;
+
+	if (additive_latency == (cas_latency - 1))
+		al = 1;
+	if (additive_latency == (cas_latency - 2))
+		al = 2;
+
+	/*
+	 * The esdmode value will also be used for writing
+	 * MR1 during write leveling for DDR3, although the
+	 * bits specifically related to the write leveling
+	 * scheme will be handled automatically by the DDR
+	 * controller. so we set the wrlvl_en = 0 here.
+	 */
+	esdmode = (0
+		| ((qoff & 0x1) << 12)
+		| ((tdqs_en & 0x1) << 11)
+		| ((rtt & 0x4) << 7)   /* rtt field is split */
+		| ((wrlvl_en & 0x1) << 7)
+		| ((rtt & 0x2) << 5)   /* rtt field is split */
+		| ((dic & 0x2) << 4)   /* DIC field is split */
+		| ((al & 0x3) << 3)
+		| ((rtt & 0x1) << 2)  /* rtt field is split */
+		| ((dic & 0x1) << 1)   /* DIC field is split */
+		| ((dll_en & 0x1) << 0)
+		);
+
+	/*
+	 * DLL control for precharge PD
+	 * 0=slow exit DLL off (tXPDLL)
+	 * 1=fast exit DLL on (tXP)
+	 */
+	dll_on = 1;
+	wr_mclk = (common_dimm->tWR_ps + mclk_ps - 1) / mclk_ps;
+	if (wr_mclk >= 12)
+		wr = 6;
+	else if (wr_mclk >= 9)
+		wr = 5;
+	else
+		wr = wr_mclk - 4;
+	dll_rst = 0;	/* dll no reset */
+	mode = 0;	/* normal mode */
+
+	/* look up table to get the cas latency bits */
+	if (cas_latency >= 5 && cas_latency <= 11) {
+		unsigned char cas_latency_table[7] = {
+			0x2,	/* 5 clocks */
+			0x4,	/* 6 clocks */
+			0x6,	/* 7 clocks */
+			0x8,	/* 8 clocks */
+			0xa,	/* 9 clocks */
+			0xc,	/* 10 clocks */
+			0xe	/* 11 clocks */
+		};
+		caslat = cas_latency_table[cas_latency - 5];
+	}
+	bt = 0;	/* Nibble sequential */
+
+	switch (popts->burst_length) {
+	case DDR_BL8:
+		bl = 0;
+		break;
+	case DDR_OTF:
+		bl = 1;
+		break;
+	case DDR_BC4:
+		bl = 2;
+		break;
+	default:
+		printf("Error: invalid burst length of %u specified. "
+			" Defaulting to on-the-fly BC4 or BL8 beats.\n",
+			popts->burst_length);
+		bl = 1;
+		break;
+	}
+
+	sdmode = (0
+		  | ((dll_on & 0x1) << 12)
+		  | ((wr & 0x7) << 9)
+		  | ((dll_rst & 0x1) << 8)
+		  | ((mode & 0x1) << 7)
+		  | (((caslat >> 1) & 0x7) << 4)
+		  | ((bt & 0x1) << 3)
+		  | ((bl & 0x3) << 0)
+		  );
+
+	ddr->ddr_sdram_mode = (0
+			       | ((esdmode & 0xFFFF) << 16)
+			       | ((sdmode & 0xFFFF) << 0)
+			       );
+
+	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
+}
+
+#else /* !CONFIG_FSL_DDR3 */
+
+/* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
+static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
+			       const memctl_options_t *popts,
+			       const common_timing_params_t *common_dimm,
+			       unsigned int cas_latency,
+			       unsigned int additive_latency)
+{
+	unsigned short esdmode;		/* Extended SDRAM mode */
+	unsigned short sdmode;		/* SDRAM mode */
+
+	/*
+	 * FIXME: This ought to be pre-calculated in a
+	 * technology-specific routine,
+	 * e.g. compute_DDR2_mode_register(), and then the
+	 * sdmode and esdmode passed in as part of common_dimm.
+	 */
+
+	/* Extended Mode Register */
+	unsigned int mrs = 0;		/* Mode Register Set */
+	unsigned int outputs = 0;	/* 0=Enabled, 1=Disabled */
+	unsigned int rdqs_en = 0;	/* RDQS Enable: 0=no, 1=yes */
+	unsigned int dqs_en = 0;	/* DQS# Enable: 0=enable, 1=disable */
+	unsigned int ocd = 0;		/* 0x0=OCD not supported,
+					   0x7=OCD default state */
+	unsigned int rtt;
+	unsigned int al;		/* Posted CAS# additive latency (AL) */
+	unsigned int ods = 0;		/* Output Drive Strength:
+						0 = Full strength (18ohm)
+						1 = Reduced strength (4ohm) */
+	unsigned int dll_en = 0;	/* DLL Enable  0=Enable (Normal),
+						       1=Disable (Test/Debug) */
+
+	/* Mode Register (MR) */
+	unsigned int mr;	/* Mode Register Definition */
+	unsigned int pd;	/* Power-Down Mode */
+	unsigned int wr;	/* Write Recovery */
+	unsigned int dll_res;	/* DLL Reset */
+	unsigned int mode;	/* Normal=0 or Test=1 */
+	unsigned int caslat = 0;/* CAS# latency */
+	/* BT: Burst Type (0=Sequential, 1=Interleaved) */
+	unsigned int bt;
+	unsigned int bl;	/* BL: Burst Length */
+
+#if defined(CONFIG_FSL_DDR2)
+	const unsigned int mclk_ps = get_memory_clk_period_ps();
+#endif
+
+	rtt = fsl_ddr_get_rtt();
+
+	al = additive_latency;
+
+	esdmode = (0
+		| ((mrs & 0x3) << 14)
+		| ((outputs & 0x1) << 12)
+		| ((rdqs_en & 0x1) << 11)
+		| ((dqs_en & 0x1) << 10)
+		| ((ocd & 0x7) << 7)
+		| ((rtt & 0x2) << 5)   /* rtt field is split */
+		| ((al & 0x7) << 3)
+		| ((rtt & 0x1) << 2)   /* rtt field is split */
+		| ((ods & 0x1) << 1)
+		| ((dll_en & 0x1) << 0)
+		);
+
+	mr = 0;		 /* FIXME: CHECKME */
+
+	/*
+	 * 0 = Fast Exit (Normal)
+	 * 1 = Slow Exit (Low Power)
+	 */
+	pd = 0;
+
+#if defined(CONFIG_FSL_DDR1)
+	wr = 0;       /* Historical */
+#elif defined(CONFIG_FSL_DDR2)
+	wr = (common_dimm->tWR_ps + mclk_ps - 1) / mclk_ps - 1;
+#endif
+	dll_res = 0;
+	mode = 0;
+
+#if defined(CONFIG_FSL_DDR1)
+	if (1 <= cas_latency && cas_latency <= 4) {
+		unsigned char mode_caslat_table[4] = {
+			0x5,	/* 1.5 clocks */
+			0x2,	/* 2.0 clocks */
+			0x6,	/* 2.5 clocks */
+			0x3	/* 3.0 clocks */
+		};
+		caslat = mode_caslat_table[cas_latency - 1];
+	} else {
+		printf("Warning: unknown cas_latency %d\n", cas_latency);
+	}
+#elif defined(CONFIG_FSL_DDR2)
+	caslat = cas_latency;
+#endif
+	bt = 0;
+
+	switch (popts->burst_length) {
+	case DDR_BL4:
+		bl = 2;
+		break;
+	case DDR_BL8:
+		bl = 3;
+		break;
+	default:
+		printf("Error: invalid burst length of %u specified. "
+			" Defaulting to 4 beats.\n",
+			popts->burst_length);
+		bl = 2;
+		break;
+	}
+
+	sdmode = (0
+		  | ((mr & 0x3) << 14)
+		  | ((pd & 0x1) << 12)
+		  | ((wr & 0x7) << 9)
+		  | ((dll_res & 0x1) << 8)
+		  | ((mode & 0x1) << 7)
+		  | ((caslat & 0x7) << 4)
+		  | ((bt & 0x1) << 3)
+		  | ((bl & 0x7) << 0)
+		  );
+
+	ddr->ddr_sdram_mode = (0
+			       | ((esdmode & 0xFFFF) << 16)
+			       | ((sdmode & 0xFFFF) << 0)
+			       );
+	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
+}
+#endif
+
+/* DDR SDRAM Data Initialization (DDR_DATA_INIT) */
+static void set_ddr_data_init(fsl_ddr_cfg_regs_t *ddr)
+{
+	unsigned int init_value;	/* Initialization value */
+
+	init_value = 0xDEADBEEF;
+	ddr->ddr_data_init = init_value;
+}
+
+/*
+ * DDR SDRAM Clock Control (DDR_SDRAM_CLK_CNTL)
+ * The old controller on the 8540/60 doesn't have this register.
+ * Hope it's OK to set it (to 0) anyway.
+ */
+static void set_ddr_sdram_clk_cntl(fsl_ddr_cfg_regs_t *ddr,
+					 const memctl_options_t *popts)
+{
+	unsigned int clk_adjust;	/* Clock adjust */
+
+	clk_adjust = popts->clk_adjust;
+	ddr->ddr_sdram_clk_cntl = (clk_adjust & 0xF) << 23;
+}
+
+/* DDR Initialization Address (DDR_INIT_ADDR) */
+static void set_ddr_init_addr(fsl_ddr_cfg_regs_t *ddr)
+{
+	unsigned int init_addr = 0;	/* Initialization address */
+
+	ddr->ddr_init_addr = init_addr;
+}
+
+/* DDR Initialization Address (DDR_INIT_EXT_ADDR) */
+static void set_ddr_init_ext_addr(fsl_ddr_cfg_regs_t *ddr)
+{
+	unsigned int uia = 0;	/* Use initialization address */
+	unsigned int init_ext_addr = 0;	/* Initialization address */
+
+	ddr->ddr_init_ext_addr = (0
+				  | ((uia & 0x1) << 31)
+				  | (init_ext_addr & 0xF)
+				  );
+}
+
+/* DDR SDRAM Timing Configuration 4 (TIMING_CFG_4) */
+static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr,
+				const memctl_options_t *popts)
+{
+	unsigned int rwt = 0; /* Read-to-write turnaround for same CS */
+	unsigned int wrt = 0; /* Write-to-read turnaround for same CS */
+	unsigned int rrt = 0; /* Read-to-read turnaround for same CS */
+	unsigned int wwt = 0; /* Write-to-write turnaround for same CS */
+	unsigned int dll_lock = 0; /* DDR SDRAM DLL Lock Time */
+
+#if defined(CONFIG_FSL_DDR3)
+	if (popts->burst_length == DDR_BL8) {
+		/* We set BL/2 for fixed BL8 */
+		rrt = 0;	/* BL/2 clocks */
+		wwt = 0;	/* BL/2 clocks */
+	} else {
+		/* We need to set BL/2 + 2 to BC4 and OTF */
+		rrt = 2;	/* BL/2 + 2 clocks */
+		wwt = 2;	/* BL/2 + 2 clocks */
+	}
+	dll_lock = 1;	/* tDLLK = 512 clocks from spec */
+#endif
+	ddr->timing_cfg_4 = (0
+			     | ((rwt & 0xf) << 28)
+			     | ((wrt & 0xf) << 24)
+			     | ((rrt & 0xf) << 20)
+			     | ((wwt & 0xf) << 16)
+			     | (dll_lock & 0x3)
+			     );
+	debug("FSLDDR: timing_cfg_4 = 0x%08x\n", ddr->timing_cfg_4);
+}
+
+/* DDR SDRAM Timing Configuration 5 (TIMING_CFG_5) */
+static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr)
+{
+	unsigned int rodt_on = 0;	/* Read to ODT on */
+	unsigned int rodt_off = 0;	/* Read to ODT off */
+	unsigned int wodt_on = 0;	/* Write to ODT on */
+	unsigned int wodt_off = 0;	/* Write to ODT off */
+
+#if defined(CONFIG_FSL_DDR3)
+	rodt_on = 3;	/*  2 clocks */
+	rodt_off = 4;	/*  4 clocks */
+	wodt_on = 2;	/*  1 clocks */
+	wodt_off = 4;	/*  4 clocks */
+#endif
+
+	ddr->timing_cfg_5 = (0
+			     | ((rodt_on & 0x1f) << 24)
+			     | ((rodt_off & 0x7) << 20)
+			     | ((wodt_on & 0x1f) << 12)
+			     | ((wodt_off & 0x7) << 8)
+			     );
+	debug("FSLDDR: timing_cfg_5 = 0x%08x\n", ddr->timing_cfg_5);
+}
+
+/* DDR ZQ Calibration Control (DDR_ZQ_CNTL) */
+static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en)
+{
+	unsigned int zqinit = 0;/* POR ZQ Calibration Time (tZQinit) */
+	/* Normal Operation Full Calibration Time (tZQoper) */
+	unsigned int zqoper = 0;
+	/* Normal Operation Short Calibration Time (tZQCS) */
+	unsigned int zqcs = 0;
+
+	if (zq_en) {
+		zqinit = 9;	/* 512 clocks */
+		zqoper = 8;	/* 256 clocks */
+		zqcs = 6;	/* 64 clocks */
+	}
+
+	ddr->ddr_zq_cntl = (0
+			    | ((zq_en & 0x1) << 31)
+			    | ((zqinit & 0xF) << 24)
+			    | ((zqoper & 0xF) << 16)
+			    | ((zqcs & 0xF) << 8)
+			    );
+}
+
+/* DDR Write Leveling Control (DDR_WRLVL_CNTL) */
+static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int wrlvl_en,
+				const memctl_options_t *popts)
+{
+	/*
+	 * First DQS pulse rising edge after margining mode
+	 * is programmed (tWL_MRD)
+	 */
+	unsigned int wrlvl_mrd = 0;
+	/* ODT delay after margining mode is programmed (tWL_ODTEN) */
+	unsigned int wrlvl_odten = 0;
+	/* DQS/DQS_ delay after margining mode is programmed (tWL_DQSEN) */
+	unsigned int wrlvl_dqsen = 0;
+	/* WRLVL_SMPL: Write leveling sample time */
+	unsigned int wrlvl_smpl = 0;
+	/* WRLVL_WLR: Write leveling repeition time */
+	unsigned int wrlvl_wlr = 0;
+	/* WRLVL_START: Write leveling start time */
+	unsigned int wrlvl_start = 0;
+
+	/* suggest enable write leveling for DDR3 due to fly-by topology */
+	if (wrlvl_en) {
+		/* tWL_MRD min = 40 nCK, we set it 64 */
+		wrlvl_mrd = 0x6;
+		/* tWL_ODTEN 128 */
+		wrlvl_odten = 0x7;
+		/* tWL_DQSEN min = 25 nCK, we set it 32 */
+		wrlvl_dqsen = 0x5;
+		/*
+		 * Write leveling sample time at least need 6 clocks
+		 * higher than tWLO to allow enough time for progagation
+		 * delay and sampling the prime data bits.
+		 */
+		wrlvl_smpl = 0xf;
+		/*
+		 * Write leveling repetition time
+		 * at least tWLO + 6 clocks clocks
+		 * we set it 32
+		 */
+		wrlvl_wlr = 0x5;
+		/*
+		 * Write leveling start time
+		 * The value use for the DQS_ADJUST for the first sample
+		 * when write leveling is enabled.
+		 */
+		wrlvl_start = 0x8;
+		/*
+		 * Override the write leveling sample and start time
+		 * according to specific board
+		 */
+		if (popts->wrlvl_override) {
+			wrlvl_smpl = popts->wrlvl_sample;
+			wrlvl_start = popts->wrlvl_start;
+		}
+	}
+
+	ddr->ddr_wrlvl_cntl = (0
+			       | ((wrlvl_en & 0x1) << 31)
+			       | ((wrlvl_mrd & 0x7) << 24)
+			       | ((wrlvl_odten & 0x7) << 20)
+			       | ((wrlvl_dqsen & 0x7) << 16)
+			       | ((wrlvl_smpl & 0xf) << 12)
+			       | ((wrlvl_wlr & 0x7) << 8)
+			       | ((wrlvl_start & 0x1F) << 0)
+			       );
+}
+
+/* DDR Self Refresh Counter (DDR_SR_CNTR) */
+static void set_ddr_sr_cntr(fsl_ddr_cfg_regs_t *ddr, unsigned int sr_it)
+{
+	/* Self Refresh Idle Threshold */
+	ddr->ddr_sr_cntr = (sr_it & 0xF) << 16;
+}
+
+/* DDR SDRAM Register Control Word 1 (DDR_SDRAM_RCW_1) */
+static void set_ddr_sdram_rcw_1(fsl_ddr_cfg_regs_t *ddr)
+{
+	unsigned int rcw0 = 0;	/* RCW0: Register Control Word 0 */
+	unsigned int rcw1 = 0;	/* RCW1: Register Control Word 1 */
+	unsigned int rcw2 = 0;	/* RCW2: Register Control Word 2 */
+	unsigned int rcw3 = 0;	/* RCW3: Register Control Word 3 */
+	unsigned int rcw4 = 0;	/* RCW4: Register Control Word 4 */
+	unsigned int rcw5 = 0;	/* RCW5: Register Control Word 5 */
+	unsigned int rcw6 = 0;	/* RCW6: Register Control Word 6 */
+	unsigned int rcw7 = 0;	/* RCW7: Register Control Word 7 */
+
+	ddr->ddr_sdram_rcw_1 = (0
+				| ((rcw0 & 0xF) << 28)
+				| ((rcw1 & 0xF) << 24)
+				| ((rcw2 & 0xF) << 20)
+				| ((rcw3 & 0xF) << 16)
+				| ((rcw4 & 0xF) << 12)
+				| ((rcw5 & 0xF) << 8)
+				| ((rcw6 & 0xF) << 4)
+				| ((rcw7 & 0xF) << 0)
+				);
+}
+
+/* DDR SDRAM Register Control Word 2 (DDR_SDRAM_RCW_2) */
+static void set_ddr_sdram_rcw_2(fsl_ddr_cfg_regs_t *ddr)
+{
+	unsigned int rcw8 = 0;	/* RCW0: Register Control Word 8 */
+	unsigned int rcw9 = 0;	/* RCW1: Register Control Word 9 */
+	unsigned int rcw10 = 0;	/* RCW2: Register Control Word 10 */
+	unsigned int rcw11 = 0;	/* RCW3: Register Control Word 11 */
+	unsigned int rcw12 = 0;	/* RCW4: Register Control Word 12 */
+	unsigned int rcw13 = 0;	/* RCW5: Register Control Word 13 */
+	unsigned int rcw14 = 0;	/* RCW6: Register Control Word 14 */
+	unsigned int rcw15 = 0;	/* RCW7: Register Control Word 15 */
+
+	ddr->ddr_sdram_rcw_2 = (0
+				| ((rcw8 & 0xF) << 28)
+				| ((rcw9 & 0xF) << 24)
+				| ((rcw10 & 0xF) << 20)
+				| ((rcw11 & 0xF) << 16)
+				| ((rcw12 & 0xF) << 12)
+				| ((rcw13 & 0xF) << 8)
+				| ((rcw14 & 0xF) << 4)
+				| ((rcw15 & 0xF) << 0)
+				);
+}
+
+unsigned int
+check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
+{
+	unsigned int res = 0;
+
+	/*
+	 * Check that DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] are
+	 * not set at the same time.
+	 */
+	if (ddr->ddr_sdram_cfg & 0x10000000
+	    && ddr->ddr_sdram_cfg & 0x00008000) {
+		printf("Error: DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] "
+				" should not be set at the same time.\n");
+		res++;
+	}
+
+	return res;
+}
+
+unsigned int
+compute_fsl_memctl_config_regs(const memctl_options_t *popts,
+			       fsl_ddr_cfg_regs_t *ddr,
+			       const common_timing_params_t *common_dimm,
+			       const dimm_params_t *dimm_params,
+			       unsigned int dbw_cap_adj)
+{
+	unsigned int i;
+	unsigned int cas_latency;
+	unsigned int additive_latency;
+	unsigned int sr_it;
+	unsigned int zq_en;
+	unsigned int wrlvl_en;
+
+	memset(ddr, 0, sizeof(fsl_ddr_cfg_regs_t));
+
+	if (common_dimm == NULL) {
+		printf("Error: subset DIMM params struct null pointer\n");
+		return 1;
+	}
+
+	/*
+	 * Process overrides first.
+	 *
+	 * FIXME: somehow add dereated caslat to this
+	 */
+	cas_latency = (popts->cas_latency_override)
+		? popts->cas_latency_override_value
+		: common_dimm->lowest_common_SPD_caslat;
+
+	additive_latency = (popts->additive_latency_override)
+		? popts->additive_latency_override_value
+		: common_dimm->additive_latency;
+
+	sr_it = (popts->auto_self_refresh_en)
+		? popts->sr_it
+		: 0;
+	/* ZQ calibration */
+	zq_en = (popts->zq_en) ? 1 : 0;
+	/* write leveling */
+	wrlvl_en = (popts->wrlvl_en) ? 1 : 0;
+
+	/* Chip Select Memory Bounds (CSn_BNDS) */
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		unsigned long long ea = 0, sa = 0;
+
+		if (popts->ba_intlv_ctl && (i > 0) &&
+			((popts->ba_intlv_ctl & 0x60) != FSL_DDR_CS2_CS3 )) {
+			/* Don't set up boundaries for other CS
+			 * other than CS0, if bank interleaving
+			 * is enabled and not CS2+CS3 interleaved.
+			 * But we need to set the ODT_RD_CFG and
+			 * ODT_WR_CFG for CS1_CONFIG here.
+			 */
+			set_csn_config(i, ddr, popts, dimm_params);
+			break;
+		}
+
+		if (dimm_params[i/2].n_ranks == 0) {
+			debug("Skipping setup of CS%u "
+				"because n_ranks on DIMM %u is 0\n", i, i/2);
+			continue;
+		}
+		if (popts->memctl_interleaving && popts->ba_intlv_ctl) {
+			/*
+			 * This works superbank 2CS
+			 * There are 2 memory controllers configured
+			 * identically, memory is interleaved between them,
+			 * and each controller uses rank interleaving within
+			 * itself. Therefore the starting and ending address
+			 * on each controller is twice the amount present on
+			 * each controller.
+			 */
+			unsigned long long rank_density
+					= dimm_params[0].capacity;
+			ea = (2 * (rank_density >> dbw_cap_adj)) - 1;
+		}
+		else if (!popts->memctl_interleaving && popts->ba_intlv_ctl) {
+			/*
+			 * If memory interleaving between controllers is NOT
+			 * enabled, the starting address for each memory
+			 * controller is distinct.  However, because rank
+			 * interleaving is enabled, the starting and ending
+			 * addresses of the total memory on that memory
+			 * controller needs to be programmed into its
+			 * respective CS0_BNDS.
+			 */
+			unsigned long long rank_density
+						= dimm_params[i/2].rank_density;
+			switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
+			case FSL_DDR_CS0_CS1_CS2_CS3:
+				/* CS0+CS1+CS2+CS3 interleaving, only CS0_CNDS
+				 * needs to be set.
+				 */
+				sa = common_dimm->base_address;
+				ea = sa + (4 * (rank_density >> dbw_cap_adj))-1;
+				break;
+			case FSL_DDR_CS0_CS1_AND_CS2_CS3:
+				/* CS0+CS1 and CS2+CS3 interleaving, CS0_CNDS
+				 * and CS2_CNDS need to be set.
+				 */
+				if (!(i&1)) {
+					sa = dimm_params[i/2].base_address;
+					ea = sa + (i * (rank_density >>
+						dbw_cap_adj)) - 1;
+				}
+				break;
+			case FSL_DDR_CS0_CS1:
+				/* CS0+CS1 interleaving, CS0_CNDS needs
+				 * to be set
+				 */
+				sa = common_dimm->base_address;
+				ea = sa + (2 * (rank_density >> dbw_cap_adj))-1;
+				break;
+			case FSL_DDR_CS2_CS3:
+				/* CS2+CS3 interleaving*/
+				if (i == 2) {
+					sa = dimm_params[i/2].base_address;
+					ea = sa + (2 * (rank_density >>
+						dbw_cap_adj)) - 1;
+				}
+				break;
+			default:  /* No bank(chip-select) interleaving */
+				break;
+			}
+		}
+		else if (popts->memctl_interleaving && !popts->ba_intlv_ctl) {
+			/*
+			 * Only the rank on CS0 of each memory controller may
+			 * be used if memory controller interleaving is used
+			 * without rank interleaving within each memory
+			 * controller.  However, the ending address programmed
+			 * into each CS0 must be the sum of the amount of
+			 * memory in the two CS0 ranks.
+			 */
+			if (i == 0) {
+				unsigned long long rank_density
+						= dimm_params[0].rank_density;
+				ea = (2 * (rank_density >> dbw_cap_adj)) - 1;
+			}
+
+		}
+		else if (!popts->memctl_interleaving && !popts->ba_intlv_ctl) {
+			/*
+			 * No rank interleaving and no memory controller
+			 * interleaving.
+			 */
+			unsigned long long rank_density
+						= dimm_params[i/2].rank_density;
+			sa = dimm_params[i/2].base_address;
+			ea = sa + (rank_density >> dbw_cap_adj) - 1;
+			if (i&1) {
+				if ((dimm_params[i/2].n_ranks == 1)) {
+					/* Odd chip select, single-rank dimm */
+					sa = 0;
+					ea = 0;
+				} else {
+					/* Odd chip select, dual-rank DIMM */
+					sa += rank_density >> dbw_cap_adj;
+					ea += rank_density >> dbw_cap_adj;
+				}
+			}
+		}
+
+		sa >>= 24;
+		ea >>= 24;
+
+		ddr->cs[i].bnds = (0
+			| ((sa & 0xFFF) << 16)	/* starting address MSB */
+			| ((ea & 0xFFF) << 0)	/* ending address MSB */
+			);
+
+		debug("FSLDDR: cs[%d]_bnds = 0x%08x\n", i, ddr->cs[i].bnds);
+		set_csn_config(i, ddr, popts, dimm_params);
+		set_csn_config_2(i, ddr);
+	}
+
+#if !defined(CONFIG_FSL_DDR1)
+	set_timing_cfg_0(ddr);
+#endif
+
+	set_timing_cfg_3(ddr, common_dimm, cas_latency);
+	set_timing_cfg_1(ddr, popts, common_dimm, cas_latency);
+	set_timing_cfg_2(ddr, popts, common_dimm,
+				cas_latency, additive_latency);
+
+	set_ddr_sdram_cfg(ddr, popts, common_dimm);
+
+	set_ddr_sdram_cfg_2(ddr, popts);
+	set_ddr_sdram_mode(ddr, popts, common_dimm,
+				cas_latency, additive_latency);
+	set_ddr_sdram_mode_2(ddr, popts);
+	set_ddr_sdram_interval(ddr, popts, common_dimm);
+	set_ddr_data_init(ddr);
+	set_ddr_sdram_clk_cntl(ddr, popts);
+	set_ddr_init_addr(ddr);
+	set_ddr_init_ext_addr(ddr);
+	set_timing_cfg_4(ddr, popts);
+	set_timing_cfg_5(ddr);
+
+	set_ddr_zq_cntl(ddr, zq_en);
+	set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts);
+
+	set_ddr_sr_cntr(ddr, sr_it);
+
+	set_ddr_sdram_rcw_1(ddr);
+	set_ddr_sdram_rcw_2(ddr);
+
+	return check_fsl_memctl_config_regs(ddr);
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr.h b/arch/powerpc/cpu/mpc8xxx/ddr/ddr.h
new file mode 100644
index 0000000..f122075
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ddr.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2008 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef FSL_DDR_MAIN_H
+#define FSL_DDR_MAIN_H
+
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_ddr_dimm_params.h>
+
+#include "common_timing_params.h"
+
+/*
+ * Bind the main DDR setup driver's generic names
+ * to this specific DDR technology.
+ */
+static __inline__ int
+compute_dimm_parameters(const generic_spd_eeprom_t *spd,
+			dimm_params_t *pdimm,
+			unsigned int dimm_number)
+{
+	return ddr_compute_dimm_parameters(spd, pdimm, dimm_number);
+}
+
+/*
+ * Data Structures
+ *
+ * All data structures have to be on the stack
+ */
+#define CONFIG_SYS_NUM_DDR_CTLRS CONFIG_NUM_DDR_CONTROLLERS
+#define CONFIG_SYS_DIMM_SLOTS_PER_CTLR CONFIG_DIMM_SLOTS_PER_CTLR
+
+typedef struct {
+	generic_spd_eeprom_t
+	   spd_installed_dimms[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_SYS_DIMM_SLOTS_PER_CTLR];
+	struct dimm_params_s
+	   dimm_params[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_SYS_DIMM_SLOTS_PER_CTLR];
+	memctl_options_t memctl_opts[CONFIG_SYS_NUM_DDR_CTLRS];
+	common_timing_params_t common_timing_params[CONFIG_SYS_NUM_DDR_CTLRS];
+	fsl_ddr_cfg_regs_t fsl_ddr_config_reg[CONFIG_SYS_NUM_DDR_CTLRS];
+} fsl_ddr_info_t;
+
+/* Compute steps */
+#define STEP_GET_SPD                 (1 << 0)
+#define STEP_COMPUTE_DIMM_PARMS      (1 << 1)
+#define STEP_COMPUTE_COMMON_PARMS    (1 << 2)
+#define STEP_GATHER_OPTS             (1 << 3)
+#define STEP_ASSIGN_ADDRESSES        (1 << 4)
+#define STEP_COMPUTE_REGS            (1 << 5)
+#define STEP_PROGRAM_REGS            (1 << 6)
+#define STEP_ALL                     0xFFF
+
+extern unsigned long long
+fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step);
+
+extern const char * step_to_string(unsigned int step);
+
+extern unsigned int
+compute_fsl_memctl_config_regs(const memctl_options_t *popts,
+			       fsl_ddr_cfg_regs_t *ddr,
+			       const common_timing_params_t *common_dimm,
+			       const dimm_params_t *dimm_parameters,
+			       unsigned int dbw_capacity_adjust);
+extern unsigned int
+compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
+				      common_timing_params_t *outpdimm,
+				      unsigned int number_of_dimms);
+extern unsigned int populate_memctl_options(int all_DIMMs_registered,
+				memctl_options_t *popts,
+				dimm_params_t *pdimm,
+				unsigned int ctrl_num);
+
+extern unsigned int mclk_to_picos(unsigned int mclk);
+extern unsigned int get_memory_clk_period_ps(void);
+extern unsigned int picos_to_mclk(unsigned int picos);
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr1_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/ddr1_dimm_params.c
new file mode 100644
index 0000000..9184764
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ddr1_dimm_params.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2008 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * Study these table from Byte 31 of JEDEC SPD Spec.
+ *
+ *		DDR I	DDR II
+ *	Bit	Size	Size
+ *	---	-----	------
+ *	7 high	512MB	512MB
+ *	6	256MB	256MB
+ *	5	128MB	128MB
+ *	4	 64MB	 16GB
+ *	3	 32MB	  8GB
+ *	2	 16MB	  4GB
+ *	1	  2GB	  2GB
+ *	0 low	  1GB	  1GB
+ *
+ * Reorder Table to be linear by stripping the bottom
+ * 2 or 5 bits off and shifting them up to the top.
+ */
+
+static unsigned long long
+compute_ranksize(unsigned int mem_type, unsigned char row_dens)
+{
+	unsigned long long bsize;
+
+	/* Bottom 2 bits up to the top. */
+	bsize = ((row_dens >> 2) | ((row_dens & 3) << 6));
+	bsize <<= 24ULL;
+	debug("DDR: DDR I rank density = 0x%08x\n", bsize);
+
+	return bsize;
+}
+
+/*
+ * Convert a two-nibble BCD value into a cycle time.
+ * While the spec calls for nano-seconds, picos are returned.
+ *
+ * This implements the tables for bytes 9, 23 and 25 for both
+ * DDR I and II.  No allowance for distinguishing the invalid
+ * fields absent for DDR I yet present in DDR II is made.
+ * (That is, cycle times of .25, .33, .66 and .75 ns are
+ * allowed for both DDR II and I.)
+ */
+static unsigned int
+convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val)
+{
+	/* Table look up the lower nibble, allow DDR I & II. */
+	unsigned int tenths_ps[16] = {
+		0,
+		100,
+		200,
+		300,
+		400,
+		500,
+		600,
+		700,
+		800,
+		900,
+		250,	/* This and the next 3 entries valid ... */
+		330,	/* ...  only for tCK calculations. */
+		660,
+		750,
+		0,	/* undefined */
+		0	/* undefined */
+	};
+
+	unsigned int whole_ns = (spd_val & 0xF0) >> 4;
+	unsigned int tenth_ns = spd_val & 0x0F;
+	unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns];
+
+	return ps;
+}
+
+static unsigned int
+convert_bcd_hundredths_to_cycle_time_ps(unsigned int spd_val)
+{
+	unsigned int tenth_ns = (spd_val & 0xF0) >> 4;
+	unsigned int hundredth_ns = spd_val & 0x0F;
+	unsigned int ps = tenth_ns * 100 + hundredth_ns * 10;
+
+	return ps;
+}
+
+static unsigned int byte40_table_ps[8] = {
+	0,
+	250,
+	330,
+	500,
+	660,
+	750,
+	0,	/* supposed to be RFC, but not sure what that means */
+	0	/* Undefined */
+};
+
+static unsigned int
+compute_trfc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trfc)
+{
+	unsigned int trfc_ps;
+
+	trfc_ps = (((trctrfc_ext & 0x1) * 256) + trfc) * 1000
+		+ byte40_table_ps[(trctrfc_ext >> 1) & 0x7];
+
+	return trfc_ps;
+}
+
+static unsigned int
+compute_trc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trc)
+{
+	unsigned int trc_ps;
+
+	trc_ps = trc * 1000 + byte40_table_ps[(trctrfc_ext >> 4) & 0x7];
+
+	return trc_ps;
+}
+
+/*
+ * tCKmax from DDR I SPD Byte 43
+ *
+ * Bits 7:2 == whole ns
+ * Bits 1:0 == quarter ns
+ *    00    == 0.00 ns
+ *    01    == 0.25 ns
+ *    10    == 0.50 ns
+ *    11    == 0.75 ns
+ *
+ * Returns picoseconds.
+ */
+static unsigned int
+compute_tckmax_from_spd_ps(unsigned int byte43)
+{
+	return (byte43 >> 2) * 1000 + (byte43 & 0x3) * 250;
+}
+
+/*
+ * Determine Refresh Rate.  Ignore self refresh bit on DDR I.
+ * Table from SPD Spec, Byte 12, converted to picoseconds and
+ * filled in with "default" normal values.
+ */
+static unsigned int
+determine_refresh_rate_ps(const unsigned int spd_refresh)
+{
+	unsigned int refresh_time_ps[8] = {
+		15625000,	/* 0 Normal    1.00x */
+		3900000,	/* 1 Reduced    .25x */
+		7800000,	/* 2 Extended   .50x */
+		31300000,	/* 3 Extended  2.00x */
+		62500000,	/* 4 Extended  4.00x */
+		125000000,	/* 5 Extended  8.00x */
+		15625000,	/* 6 Normal    1.00x  filler */
+		15625000,	/* 7 Normal    1.00x  filler */
+	};
+
+	return refresh_time_ps[spd_refresh & 0x7];
+}
+
+/*
+ * The purpose of this function is to compute a suitable
+ * CAS latency given the DRAM clock period.  The SPD only
+ * defines at most 3 CAS latencies.  Typically the slower in
+ * frequency the DIMM runs at, the shorter its CAS latency can be.
+ * If the DIMM is operating at a sufficiently low frequency,
+ * it may be able to run at a CAS latency shorter than the
+ * shortest SPD-defined CAS latency.
+ *
+ * If a CAS latency is not found, 0 is returned.
+ *
+ * Do this by finding in the standard speed bin table the longest
+ * tCKmin that doesn't exceed the value of mclk_ps (tCK).
+ *
+ * An assumption made is that the SDRAM device allows the
+ * CL to be programmed for a value that is lower than those
+ * advertised by the SPD.  This is not always the case,
+ * as those modes not defined in the SPD are optional.
+ *
+ * CAS latency de-rating based upon values JEDEC Standard No. 79-E
+ * Table 11.
+ *
+ * ordinal 2, ddr1_speed_bins[1] contains tCK for CL=2
+ */
+				  /*   CL2.0 CL2.5 CL3.0  */
+unsigned short ddr1_speed_bins[] = {0, 7500, 6000, 5000 };
+
+unsigned int
+compute_derated_DDR1_CAS_latency(unsigned int mclk_ps)
+{
+	const unsigned int num_speed_bins = ARRAY_SIZE(ddr1_speed_bins);
+	unsigned int lowest_tCKmin_found = 0;
+	unsigned int lowest_tCKmin_CL = 0;
+	unsigned int i;
+
+	debug("mclk_ps = %u\n", mclk_ps);
+
+	for (i = 0; i < num_speed_bins; i++) {
+		unsigned int x = ddr1_speed_bins[i];
+		debug("i=%u, x = %u, lowest_tCKmin_found = %u\n",
+		      i, x, lowest_tCKmin_found);
+		if (x && lowest_tCKmin_found <= x && x <= mclk_ps) {
+			lowest_tCKmin_found = x;
+			lowest_tCKmin_CL = i + 1;
+		}
+	}
+
+	debug("lowest_tCKmin_CL = %u\n", lowest_tCKmin_CL);
+
+	return lowest_tCKmin_CL;
+}
+
+/*
+ * ddr_compute_dimm_parameters for DDR1 SPD
+ *
+ * Compute DIMM parameters based upon the SPD information in spd.
+ * Writes the results to the dimm_params_t structure pointed by pdimm.
+ *
+ * FIXME: use #define for the retvals
+ */
+unsigned int
+ddr_compute_dimm_parameters(const ddr1_spd_eeprom_t *spd,
+			     dimm_params_t *pdimm,
+			     unsigned int dimm_number)
+{
+	unsigned int retval;
+
+	if (spd->mem_type) {
+		if (spd->mem_type != SPD_MEMTYPE_DDR) {
+			printf("DIMM %u: is not a DDR1 SPD.\n", dimm_number);
+			return 1;
+		}
+	} else {
+		memset(pdimm, 0, sizeof(dimm_params_t));
+		return 1;
+	}
+
+	retval = ddr1_spd_check(spd);
+	if (retval) {
+		printf("DIMM %u: failed checksum\n", dimm_number);
+		return 2;
+	}
+
+	/*
+	 * The part name in ASCII in the SPD EEPROM is not null terminated.
+	 * Guarantee null termination here by presetting all bytes to 0
+	 * and copying the part name in ASCII from the SPD onto it
+	 */
+	memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+	memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+
+	/* DIMM organization parameters */
+	pdimm->n_ranks = spd->nrows;
+	pdimm->rank_density = compute_ranksize(spd->mem_type, spd->bank_dens);
+	pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+	pdimm->data_width = spd->dataw_lsb;
+	pdimm->primary_sdram_width = spd->primw;
+	pdimm->ec_sdram_width = spd->ecw;
+
+	/*
+	 * FIXME: Need to determine registered_dimm status.
+	 *     1 == register buffered
+	 *     0 == unbuffered
+	 */
+	pdimm->registered_dimm = 0;	/* unbuffered */
+
+	/* SDRAM device parameters */
+	pdimm->n_row_addr = spd->nrow_addr;
+	pdimm->n_col_addr = spd->ncol_addr;
+	pdimm->n_banks_per_sdram_device = spd->nbanks;
+	pdimm->edc_config = spd->config;
+	pdimm->burst_lengths_bitmask = spd->burstl;
+	pdimm->row_density = spd->bank_dens;
+
+	/*
+	 * Calculate the Maximum Data Rate based on the Minimum Cycle time.
+	 * The SPD clk_cycle field (tCKmin) is measured in tenths of
+	 * nanoseconds and represented as BCD.
+	 */
+	pdimm->tCKmin_X_ps
+		= convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle);
+	pdimm->tCKmin_X_minus_1_ps
+		= convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle2);
+	pdimm->tCKmin_X_minus_2_ps
+		= convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle3);
+
+	pdimm->tCKmax_ps = compute_tckmax_from_spd_ps(spd->tckmax);
+
+	/*
+	 * Compute CAS latencies defined by SPD
+	 * The SPD caslat_X should have at least 1 and at most 3 bits set.
+	 *
+	 * If cas_lat after masking is 0, the __ilog2 function returns
+	 * 255 into the variable.   This behavior is abused once.
+	 */
+	pdimm->caslat_X  = __ilog2(spd->cas_lat);
+	pdimm->caslat_X_minus_1 = __ilog2(spd->cas_lat
+					  & ~(1 << pdimm->caslat_X));
+	pdimm->caslat_X_minus_2 = __ilog2(spd->cas_lat
+					  & ~(1 << pdimm->caslat_X)
+					  & ~(1 << pdimm->caslat_X_minus_1));
+
+	/* Compute CAS latencies below that defined by SPD */
+	pdimm->caslat_lowest_derated
+		= compute_derated_DDR1_CAS_latency(get_memory_clk_period_ps());
+
+	/* Compute timing parameters */
+	pdimm->tRCD_ps = spd->trcd * 250;
+	pdimm->tRP_ps = spd->trp * 250;
+	pdimm->tRAS_ps = spd->tras * 1000;
+
+	pdimm->tWR_ps = mclk_to_picos(3);
+	pdimm->tWTR_ps = mclk_to_picos(1);
+	pdimm->tRFC_ps = compute_trfc_ps_from_spd(0, spd->trfc);
+
+	pdimm->tRRD_ps = spd->trrd * 250;
+	pdimm->tRC_ps = compute_trc_ps_from_spd(0, spd->trc);
+
+	pdimm->refresh_rate_ps = determine_refresh_rate_ps(spd->refresh);
+
+	pdimm->tIS_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_setup);
+	pdimm->tIH_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_hold);
+	pdimm->tDS_ps
+		= convert_bcd_hundredths_to_cycle_time_ps(spd->data_setup);
+	pdimm->tDH_ps
+		= convert_bcd_hundredths_to_cycle_time_ps(spd->data_hold);
+
+	pdimm->tRTP_ps = mclk_to_picos(2);	/* By the book. */
+	pdimm->tDQSQ_max_ps = spd->tdqsq * 10;
+	pdimm->tQHS_ps = spd->tqhs * 10;
+
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr2_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/ddr2_dimm_params.c
new file mode 100644
index 0000000..d9d0fa7
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ddr2_dimm_params.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright 2008 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * Study these table from Byte 31 of JEDEC SPD Spec.
+ *
+ *		DDR I	DDR II
+ *	Bit	Size	Size
+ *	---	-----	------
+ *	7 high	512MB	512MB
+ *	6	256MB	256MB
+ *	5	128MB	128MB
+ *	4	 64MB	 16GB
+ *	3	 32MB	  8GB
+ *	2	 16MB	  4GB
+ *	1	  2GB	  2GB
+ *	0 low	  1GB	  1GB
+ *
+ * Reorder Table to be linear by stripping the bottom
+ * 2 or 5 bits off and shifting them up to the top.
+ *
+ */
+static unsigned long long
+compute_ranksize(unsigned int mem_type, unsigned char row_dens)
+{
+	unsigned long long bsize;
+
+	/* Bottom 5 bits up to the top. */
+	bsize = ((row_dens >> 5) | ((row_dens & 31) << 3));
+	bsize <<= 27ULL;
+	debug("DDR: DDR II rank density = 0x%08x\n", bsize);
+
+	return bsize;
+}
+
+/*
+ * Convert a two-nibble BCD value into a cycle time.
+ * While the spec calls for nano-seconds, picos are returned.
+ *
+ * This implements the tables for bytes 9, 23 and 25 for both
+ * DDR I and II.  No allowance for distinguishing the invalid
+ * fields absent for DDR I yet present in DDR II is made.
+ * (That is, cycle times of .25, .33, .66 and .75 ns are
+ * allowed for both DDR II and I.)
+ */
+static unsigned int
+convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val)
+{
+	/* Table look up the lower nibble, allow DDR I & II. */
+	unsigned int tenths_ps[16] = {
+		0,
+		100,
+		200,
+		300,
+		400,
+		500,
+		600,
+		700,
+		800,
+		900,
+		250,	/* This and the next 3 entries valid ... */
+		330,	/* ...  only for tCK calculations. */
+		660,
+		750,
+		0,	/* undefined */
+		0	/* undefined */
+	};
+
+	unsigned int whole_ns = (spd_val & 0xF0) >> 4;
+	unsigned int tenth_ns = spd_val & 0x0F;
+	unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns];
+
+	return ps;
+}
+
+static unsigned int
+convert_bcd_hundredths_to_cycle_time_ps(unsigned int spd_val)
+{
+	unsigned int tenth_ns = (spd_val & 0xF0) >> 4;
+	unsigned int hundredth_ns = spd_val & 0x0F;
+	unsigned int ps = tenth_ns * 100 + hundredth_ns * 10;
+
+	return ps;
+}
+
+static unsigned int byte40_table_ps[8] = {
+	0,
+	250,
+	330,
+	500,
+	660,
+	750,
+	0,	/* supposed to be RFC, but not sure what that means */
+	0	/* Undefined */
+};
+
+static unsigned int
+compute_trfc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trfc)
+{
+	unsigned int trfc_ps;
+
+	trfc_ps = (((trctrfc_ext & 0x1) * 256) + trfc) * 1000
+		+ byte40_table_ps[(trctrfc_ext >> 1) & 0x7];
+
+	return trfc_ps;
+}
+
+static unsigned int
+compute_trc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trc)
+{
+	unsigned int trc_ps;
+
+	trc_ps = trc * 1000 + byte40_table_ps[(trctrfc_ext >> 4) & 0x7];
+
+	return trc_ps;
+}
+
+/*
+ * Determine Refresh Rate.  Ignore self refresh bit on DDR I.
+ * Table from SPD Spec, Byte 12, converted to picoseconds and
+ * filled in with "default" normal values.
+ */
+static unsigned int
+determine_refresh_rate_ps(const unsigned int spd_refresh)
+{
+	unsigned int refresh_time_ps[8] = {
+		15625000,	/* 0 Normal    1.00x */
+		3900000,	/* 1 Reduced    .25x */
+		7800000,	/* 2 Extended   .50x */
+		31300000,	/* 3 Extended  2.00x */
+		62500000,	/* 4 Extended  4.00x */
+		125000000,	/* 5 Extended  8.00x */
+		15625000,	/* 6 Normal    1.00x  filler */
+		15625000,	/* 7 Normal    1.00x  filler */
+	};
+
+	return refresh_time_ps[spd_refresh & 0x7];
+}
+
+/*
+ * The purpose of this function is to compute a suitable
+ * CAS latency given the DRAM clock period.  The SPD only
+ * defines at most 3 CAS latencies.  Typically the slower in
+ * frequency the DIMM runs at, the shorter its CAS latency can.
+ * be.  If the DIMM is operating at a sufficiently low frequency,
+ * it may be able to run at a CAS latency shorter than the
+ * shortest SPD-defined CAS latency.
+ *
+ * If a CAS latency is not found, 0 is returned.
+ *
+ * Do this by finding in the standard speed bin table the longest
+ * tCKmin that doesn't exceed the value of mclk_ps (tCK).
+ *
+ * An assumption made is that the SDRAM device allows the
+ * CL to be programmed for a value that is lower than those
+ * advertised by the SPD.  This is not always the case,
+ * as those modes not defined in the SPD are optional.
+ *
+ * CAS latency de-rating based upon values JEDEC Standard No. 79-2C
+ * Table 40, "DDR2 SDRAM stanadard speed bins and tCK, tRCD, tRP, tRAS,
+ * and tRC for corresponding bin"
+ *
+ * ordinal 2, ddr2_speed_bins[1] contains tCK for CL=3
+ * Not certain if any good value exists for CL=2
+ */
+				 /* CL2   CL3   CL4   CL5   CL6 */
+unsigned short ddr2_speed_bins[] = {   0, 5000, 3750, 3000, 2500 };
+
+unsigned int
+compute_derated_DDR2_CAS_latency(unsigned int mclk_ps)
+{
+	const unsigned int num_speed_bins = ARRAY_SIZE(ddr2_speed_bins);
+	unsigned int lowest_tCKmin_found = 0;
+	unsigned int lowest_tCKmin_CL = 0;
+	unsigned int i;
+
+	debug("mclk_ps = %u\n", mclk_ps);
+
+	for (i = 0; i < num_speed_bins; i++) {
+		unsigned int x = ddr2_speed_bins[i];
+		debug("i=%u, x = %u, lowest_tCKmin_found = %u\n",
+		      i, x, lowest_tCKmin_found);
+		if (x && x <= mclk_ps && x >= lowest_tCKmin_found ) {
+			lowest_tCKmin_found = x;
+			lowest_tCKmin_CL = i + 2;
+		}
+	}
+
+	debug("lowest_tCKmin_CL = %u\n", lowest_tCKmin_CL);
+
+	return lowest_tCKmin_CL;
+}
+
+/*
+ * ddr_compute_dimm_parameters for DDR2 SPD
+ *
+ * Compute DIMM parameters based upon the SPD information in spd.
+ * Writes the results to the dimm_params_t structure pointed by pdimm.
+ *
+ * FIXME: use #define for the retvals
+ */
+unsigned int
+ddr_compute_dimm_parameters(const ddr2_spd_eeprom_t *spd,
+			     dimm_params_t *pdimm,
+			     unsigned int dimm_number)
+{
+	unsigned int retval;
+
+	if (spd->mem_type) {
+		if (spd->mem_type != SPD_MEMTYPE_DDR2) {
+			printf("DIMM %u: is not a DDR2 SPD.\n", dimm_number);
+			return 1;
+		}
+	} else {
+		memset(pdimm, 0, sizeof(dimm_params_t));
+		return 1;
+	}
+
+	retval = ddr2_spd_check(spd);
+	if (retval) {
+		printf("DIMM %u: failed checksum\n", dimm_number);
+		return 2;
+	}
+
+	/*
+	 * The part name in ASCII in the SPD EEPROM is not null terminated.
+	 * Guarantee null termination here by presetting all bytes to 0
+	 * and copying the part name in ASCII from the SPD onto it
+	 */
+	memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+	memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+
+	/* DIMM organization parameters */
+	pdimm->n_ranks = (spd->mod_ranks & 0x7) + 1;
+	pdimm->rank_density = compute_ranksize(spd->mem_type, spd->rank_dens);
+	pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+	pdimm->data_width = spd->dataw;
+	pdimm->primary_sdram_width = spd->primw;
+	pdimm->ec_sdram_width = spd->ecw;
+
+	/* FIXME: what about registered SO-DIMM? */
+	switch (spd->dimm_type) {
+	case 0x01:	/* RDIMM */
+	case 0x10:	/* Mini-RDIMM */
+		pdimm->registered_dimm = 1; /* register buffered */
+		break;
+
+	case 0x02:	/* UDIMM */
+	case 0x04:	/* SO-DIMM */
+	case 0x08:	/* Micro-DIMM */
+	case 0x20:	/* Mini-UDIMM */
+		pdimm->registered_dimm = 0;	/* unbuffered */
+		break;
+
+	default:
+		printf("unknown dimm_type 0x%02X\n", spd->dimm_type);
+		return 1;
+		break;
+	}
+
+	/* SDRAM device parameters */
+	pdimm->n_row_addr = spd->nrow_addr;
+	pdimm->n_col_addr = spd->ncol_addr;
+	pdimm->n_banks_per_sdram_device = spd->nbanks;
+	pdimm->edc_config = spd->config;
+	pdimm->burst_lengths_bitmask = spd->burstl;
+	pdimm->row_density = spd->rank_dens;
+
+	/*
+	 * Calculate the Maximum Data Rate based on the Minimum Cycle time.
+	 * The SPD clk_cycle field (tCKmin) is measured in tenths of
+	 * nanoseconds and represented as BCD.
+	 */
+	pdimm->tCKmin_X_ps
+		= convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle);
+	pdimm->tCKmin_X_minus_1_ps
+		= convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle2);
+	pdimm->tCKmin_X_minus_2_ps
+		= convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle3);
+
+	pdimm->tCKmax_ps = convert_bcd_tenths_to_cycle_time_ps(spd->tckmax);
+
+	/*
+	 * Compute CAS latencies defined by SPD
+	 * The SPD caslat_X should have at least 1 and at most 3 bits set.
+	 *
+	 * If cas_lat after masking is 0, the __ilog2 function returns
+	 * 255 into the variable.   This behavior is abused once.
+	 */
+	pdimm->caslat_X  = __ilog2(spd->cas_lat);
+	pdimm->caslat_X_minus_1 = __ilog2(spd->cas_lat
+					  & ~(1 << pdimm->caslat_X));
+	pdimm->caslat_X_minus_2 = __ilog2(spd->cas_lat
+					  & ~(1 << pdimm->caslat_X)
+					  & ~(1 << pdimm->caslat_X_minus_1));
+
+	/* Compute CAS latencies below that defined by SPD */
+	pdimm->caslat_lowest_derated
+		= compute_derated_DDR2_CAS_latency(get_memory_clk_period_ps());
+
+	/* Compute timing parameters */
+	pdimm->tRCD_ps = spd->trcd * 250;
+	pdimm->tRP_ps = spd->trp * 250;
+	pdimm->tRAS_ps = spd->tras * 1000;
+
+	pdimm->tWR_ps = spd->twr * 250;
+	pdimm->tWTR_ps = spd->twtr * 250;
+	pdimm->tRFC_ps = compute_trfc_ps_from_spd(spd->trctrfc_ext, spd->trfc);
+
+	pdimm->tRRD_ps = spd->trrd * 250;
+	pdimm->tRC_ps = compute_trc_ps_from_spd(spd->trctrfc_ext, spd->trc);
+
+	pdimm->refresh_rate_ps = determine_refresh_rate_ps(spd->refresh);
+
+	pdimm->tIS_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_setup);
+	pdimm->tIH_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_hold);
+	pdimm->tDS_ps
+		= convert_bcd_hundredths_to_cycle_time_ps(spd->data_setup);
+	pdimm->tDH_ps
+		= convert_bcd_hundredths_to_cycle_time_ps(spd->data_hold);
+
+	pdimm->tRTP_ps = spd->trtp * 250;
+	pdimm->tDQSQ_max_ps = spd->tdqsq * 10;
+	pdimm->tQHS_ps = spd->tqhs * 10;
+
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c
new file mode 100644
index 0000000..d4199ba
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc.
+ *	Dave Liu <daveliu@freescale.com>
+ *
+ * calculate the organization and timing parameter
+ * from ddr3 spd, please refer to the spec
+ * JEDEC standard No.21-C 4_01_02_11R18.pdf
+ *
+ * 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 <common.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * each rank size =
+ * sdram capacity(bit) / 8 * primary bus width / sdram width
+ *
+ * where: sdram capacity  = spd byte4[3:0]
+ *        primary bus width = spd byte8[2:0]
+ *        sdram width = spd byte7[2:0]
+ *
+ * SPD byte4 - sdram density and banks
+ *	bit[3:0]	size(bit)	size(byte)
+ *	0000		256Mb		32MB
+ *	0001		512Mb		64MB
+ *	0010		1Gb		128MB
+ *	0011		2Gb		256MB
+ *	0100		4Gb		512MB
+ *	0101		8Gb		1GB
+ *	0110		16Gb		2GB
+ *
+ * SPD byte8 - module memory bus width
+ * 	bit[2:0]	primary bus width
+ *	000		8bits
+ * 	001		16bits
+ * 	010		32bits
+ * 	011		64bits
+ *
+ * SPD byte7 - module organiztion
+ * 	bit[2:0]	sdram device width
+ * 	000		4bits
+ * 	001		8bits
+ * 	010		16bits
+ * 	011		32bits
+ *
+ */
+static unsigned long long
+compute_ranksize(const ddr3_spd_eeprom_t *spd)
+{
+	unsigned long long bsize;
+
+	int nbit_sdram_cap_bsize = 0;
+	int nbit_primary_bus_width = 0;
+	int nbit_sdram_width = 0;
+
+	if ((spd->density_banks & 0xf) < 7)
+		nbit_sdram_cap_bsize = (spd->density_banks & 0xf) + 28;
+	if ((spd->bus_width & 0x7) < 4)
+		nbit_primary_bus_width = (spd->bus_width & 0x7) + 3;
+	if ((spd->organization & 0x7) < 4)
+		nbit_sdram_width = (spd->organization & 0x7) + 2;
+
+	bsize = 1ULL << (nbit_sdram_cap_bsize - 3
+		    + nbit_primary_bus_width - nbit_sdram_width);
+
+	debug("DDR: DDR III rank density = 0x%16lx\n", bsize);
+
+	return bsize;
+}
+
+/*
+ * ddr_compute_dimm_parameters for DDR3 SPD
+ *
+ * Compute DIMM parameters based upon the SPD information in spd.
+ * Writes the results to the dimm_params_t structure pointed by pdimm.
+ *
+ */
+unsigned int
+ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd,
+			     dimm_params_t *pdimm,
+			     unsigned int dimm_number)
+{
+	unsigned int retval;
+	unsigned int mtb_ps;
+
+	if (spd->mem_type) {
+		if (spd->mem_type != SPD_MEMTYPE_DDR3) {
+			printf("DIMM %u: is not a DDR3 SPD.\n", dimm_number);
+			return 1;
+		}
+	} else {
+		memset(pdimm, 0, sizeof(dimm_params_t));
+		return 1;
+	}
+
+	retval = ddr3_spd_check(spd);
+	if (retval) {
+		printf("DIMM %u: failed checksum\n", dimm_number);
+		return 2;
+	}
+
+	/*
+	 * The part name in ASCII in the SPD EEPROM is not null terminated.
+	 * Guarantee null termination here by presetting all bytes to 0
+	 * and copying the part name in ASCII from the SPD onto it
+	 */
+	memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+	memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+
+	/* DIMM organization parameters */
+	pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1;
+	pdimm->rank_density = compute_ranksize(spd);
+	pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+	pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7));
+	if ((spd->bus_width >> 3) & 0x3)
+		pdimm->ec_sdram_width = 8;
+	else
+		pdimm->ec_sdram_width = 0;
+	pdimm->data_width = pdimm->primary_sdram_width
+			  + pdimm->ec_sdram_width;
+
+	switch (spd->module_type & 0xf) {
+	case 0x01:	/* RDIMM */
+	case 0x05:	/* Mini-RDIMM */
+		pdimm->registered_dimm = 1; /* register buffered */
+		break;
+
+	case 0x02:	/* UDIMM */
+	case 0x03:	/* SO-DIMM */
+	case 0x04:	/* Micro-DIMM */
+	case 0x06:	/* Mini-UDIMM */
+		pdimm->registered_dimm = 0;	/* unbuffered */
+		break;
+
+	default:
+		printf("unknown dimm_type 0x%02X\n", spd->module_type);
+		return 1;
+	}
+
+	/* SDRAM device parameters */
+	pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12;
+	pdimm->n_col_addr = (spd->addressing & 0x7) + 9;
+	pdimm->n_banks_per_sdram_device = 8 << ((spd->density_banks >> 4) & 0x7);
+
+	/*
+	 * The SPD spec has not the ECC bit,
+	 * We consider the DIMM as ECC capability
+	 * when the extension bus exist
+	 */
+	if (pdimm->ec_sdram_width)
+		pdimm->edc_config = 0x02;
+	else
+		pdimm->edc_config = 0x00;
+
+	/*
+	 * The SPD spec has not the burst length byte
+	 * but DDR3 spec has nature BL8 and BC4,
+	 * BL8 -bit3, BC4 -bit2
+	 */
+	pdimm->burst_lengths_bitmask = 0x0c;
+	pdimm->row_density = __ilog2(pdimm->rank_density);
+
+	/* MTB - medium timebase
+	 * The unit in the SPD spec is ns,
+	 * We convert it to ps.
+	 * eg: MTB = 0.125ns (125ps)
+	 */
+	mtb_ps = (spd->mtb_dividend * 1000) /spd->mtb_divisor;
+	pdimm->mtb_ps = mtb_ps;
+
+	/*
+	 * sdram minimum cycle time
+	 * we assume the MTB is 0.125ns
+	 * eg:
+	 * tCK_min=15 MTB (1.875ns) ->DDR3-1066
+	 *        =12 MTB (1.5ns) ->DDR3-1333
+	 *        =10 MTB (1.25ns) ->DDR3-1600
+	 */
+	pdimm->tCKmin_X_ps = spd->tCK_min * mtb_ps;
+
+	/*
+	 * CAS latency supported
+	 * bit4 - CL4
+	 * bit5 - CL5
+	 * bit18 - CL18
+	 */
+	pdimm->caslat_X  = ((spd->caslat_msb << 8) | spd->caslat_lsb) << 4;
+
+	/*
+	 * min CAS latency time
+	 * eg: tAA_min =
+	 * DDR3-800D	100 MTB (12.5ns)
+	 * DDR3-1066F	105 MTB (13.125ns)
+	 * DDR3-1333H	108 MTB (13.5ns)
+	 * DDR3-1600H	90 MTB (11.25ns)
+	 */
+	pdimm->tAA_ps = spd->tAA_min * mtb_ps;
+
+	/*
+	 * min write recovery time
+	 * eg:
+	 * tWR_min = 120 MTB (15ns) -> all speed grades.
+	 */
+	pdimm->tWR_ps = spd->tWR_min * mtb_ps;
+
+	/*
+	 * min RAS to CAS delay time
+	 * eg: tRCD_min =
+	 * DDR3-800	100 MTB (12.5ns)
+	 * DDR3-1066F	105 MTB (13.125ns)
+	 * DDR3-1333H	108 MTB (13.5ns)
+	 * DDR3-1600H	90 MTB (11.25)
+	 */
+	pdimm->tRCD_ps = spd->tRCD_min * mtb_ps;
+
+	/*
+	 * min row active to row active delay time
+	 * eg: tRRD_min =
+	 * DDR3-800(1KB page)	80 MTB (10ns)
+	 * DDR3-1333(1KB page)	48 MTB (6ns)
+	 */
+	pdimm->tRRD_ps = spd->tRRD_min * mtb_ps;
+
+	/*
+	 * min row precharge delay time
+	 * eg: tRP_min =
+	 * DDR3-800D	100 MTB (12.5ns)
+	 * DDR3-1066F	105 MTB (13.125ns)
+	 * DDR3-1333H	108 MTB (13.5ns)
+	 * DDR3-1600H	90 MTB (11.25ns)
+	 */
+	pdimm->tRP_ps = spd->tRP_min * mtb_ps;
+
+	/* min active to precharge delay time
+	 * eg: tRAS_min =
+	 * DDR3-800D	300 MTB (37.5ns)
+	 * DDR3-1066F	300 MTB (37.5ns)
+	 * DDR3-1333H	288 MTB (36ns)
+	 * DDR3-1600H	280 MTB (35ns)
+	 */
+	pdimm->tRAS_ps = (((spd->tRAS_tRC_ext & 0xf) << 8) | spd->tRAS_min_lsb)
+			* mtb_ps;
+	/*
+	 * min active to actice/refresh delay time
+	 * eg: tRC_min =
+	 * DDR3-800D	400 MTB (50ns)
+	 * DDR3-1066F	405 MTB (50.625ns)
+	 * DDR3-1333H	396 MTB (49.5ns)
+	 * DDR3-1600H	370 MTB (46.25ns)
+	 */
+	pdimm->tRC_ps = (((spd->tRAS_tRC_ext & 0xf0) << 4) | spd->tRC_min_lsb)
+			* mtb_ps;
+	/*
+	 * min refresh recovery delay time
+	 * eg: tRFC_min =
+	 * 512Mb	720 MTB (90ns)
+	 * 1Gb		880 MTB (110ns)
+	 * 2Gb		1280 MTB (160ns)
+	 */
+	pdimm->tRFC_ps = ((spd->tRFC_min_msb << 8) | spd->tRFC_min_lsb)
+			* mtb_ps;
+	/*
+	 * min internal write to read command delay time
+	 * eg: tWTR_min = 40 MTB (7.5ns) - all speed bins.
+	 * tWRT is at least 4 mclk independent of operating freq.
+	 */
+	pdimm->tWTR_ps = spd->tWTR_min * mtb_ps;
+
+	/*
+	 * min internal read to precharge command delay time
+	 * eg: tRTP_min = 40 MTB (7.5ns) - all speed bins.
+	 * tRTP is at least 4 mclk independent of operating freq.
+	 */
+	pdimm->tRTP_ps = spd->tRTP_min * mtb_ps;
+
+	/*
+	 * Average periodic refresh interval
+	 * tREFI = 7.8 us at normal temperature range
+	 *       = 3.9 us at ext temperature range
+	 */
+	pdimm->refresh_rate_ps = 7800000;
+
+	/*
+	 * min four active window delay time
+	 * eg: tFAW_min =
+	 * DDR3-800(1KB page)	320 MTB (40ns)
+	 * DDR3-1066(1KB page)	300 MTB (37.5ns)
+	 * DDR3-1333(1KB page)	240 MTB (30ns)
+	 * DDR3-1600(1KB page)	240 MTB (30ns)
+	 */
+	pdimm->tFAW_ps = (((spd->tFAW_msb & 0xf) << 8) | spd->tFAW_min)
+			* mtb_ps;
+
+	/*
+	 * We need check the address mirror for unbuffered DIMM
+	 * If SPD indicate the address map mirror, The DDR controller
+	 * need care it.
+	 */
+	if ((spd->module_type == SPD_MODULETYPE_UDIMM) ||
+	    (spd->module_type == SPD_MODULETYPE_SODIMM) ||
+	    (spd->module_type == SPD_MODULETYPE_MICRODIMM) ||
+	    (spd->module_type == SPD_MODULETYPE_MINIUDIMM))
+		pdimm->mirrored_dimm = spd->mod_section.unbuffered.addr_mapping & 0x1;
+
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
new file mode 100644
index 0000000..e888e3e
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
@@ -0,0 +1,468 @@
+/*
+ * Copyright 2008 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+
+unsigned int
+compute_cas_latency_ddr3(const dimm_params_t *dimm_params,
+			 common_timing_params_t *outpdimm,
+			 unsigned int number_of_dimms)
+{
+	unsigned int i;
+	unsigned int tAAmin_ps = 0;
+	unsigned int tCKmin_X_ps = 0;
+	unsigned int common_caslat;
+	unsigned int caslat_actual;
+	unsigned int retry = 16;
+	unsigned int tmp;
+	const unsigned int mclk_ps = get_memory_clk_period_ps();
+
+	/* compute the common CAS latency supported between slots */
+	tmp = dimm_params[0].caslat_X;
+	for (i = 1; i < number_of_dimms; i++)
+		 tmp &= dimm_params[i].caslat_X;
+	common_caslat = tmp;
+
+	/* compute the max tAAmin tCKmin between slots */
+	for (i = 0; i < number_of_dimms; i++) {
+		tAAmin_ps = max(tAAmin_ps, dimm_params[i].tAA_ps);
+		tCKmin_X_ps = max(tCKmin_X_ps, dimm_params[i].tCKmin_X_ps);
+	}
+	/* validate if the memory clk is in the range of dimms */
+	if (mclk_ps < tCKmin_X_ps) {
+		printf("The DIMM max tCKmin is %d ps,"
+			"doesn't support the MCLK cycle %d ps\n",
+			tCKmin_X_ps, mclk_ps);
+		return 1;
+	}
+	/* determine the acutal cas latency */
+	caslat_actual = (tAAmin_ps + mclk_ps - 1) / mclk_ps;
+	/* check if the dimms support the CAS latency */
+	while (!(common_caslat & (1 << caslat_actual)) && retry > 0) {
+		caslat_actual++;
+		retry--;
+	}
+	/* once the caculation of caslat_actual is completed
+	 * we must verify that this CAS latency value does not
+	 * exceed tAAmax, which is 20 ns for all DDR3 speed grades
+	 */
+	if (caslat_actual * mclk_ps > 20000) {
+		printf("The choosen cas latency %d is too large\n",
+			caslat_actual);
+		return 1;
+	}
+	outpdimm->lowest_common_SPD_caslat = caslat_actual;
+
+	return 0;
+}
+
+/*
+ * compute_lowest_common_dimm_parameters()
+ *
+ * Determine the worst-case DIMM timing parameters from the set of DIMMs
+ * whose parameters have been computed into the array pointed to
+ * by dimm_params.
+ */
+unsigned int
+compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
+				      common_timing_params_t *outpdimm,
+				      unsigned int number_of_dimms)
+{
+	unsigned int i;
+
+	unsigned int tCKmin_X_ps = 0;
+	unsigned int tCKmax_ps = 0xFFFFFFFF;
+	unsigned int tCKmax_max_ps = 0;
+	unsigned int tRCD_ps = 0;
+	unsigned int tRP_ps = 0;
+	unsigned int tRAS_ps = 0;
+	unsigned int tWR_ps = 0;
+	unsigned int tWTR_ps = 0;
+	unsigned int tRFC_ps = 0;
+	unsigned int tRRD_ps = 0;
+	unsigned int tRC_ps = 0;
+	unsigned int refresh_rate_ps = 0;
+	unsigned int tIS_ps = 0;
+	unsigned int tIH_ps = 0;
+	unsigned int tDS_ps = 0;
+	unsigned int tDH_ps = 0;
+	unsigned int tRTP_ps = 0;
+	unsigned int tDQSQ_max_ps = 0;
+	unsigned int tQHS_ps = 0;
+
+	unsigned int temp1, temp2;
+	unsigned int additive_latency = 0;
+#if !defined(CONFIG_FSL_DDR3)
+	const unsigned int mclk_ps = get_memory_clk_period_ps();
+	unsigned int lowest_good_caslat;
+	unsigned int not_ok;
+
+	debug("using mclk_ps = %u\n", mclk_ps);
+#endif
+
+	temp1 = 0;
+	for (i = 0; i < number_of_dimms; i++) {
+		/*
+		 * If there are no ranks on this DIMM,
+		 * it probably doesn't exist, so skip it.
+		 */
+		if (dimm_params[i].n_ranks == 0) {
+			temp1++;
+			continue;
+		}
+
+		/*
+		 * Find minimum tCKmax_ps to find fastest slow speed,
+		 * i.e., this is the slowest the whole system can go.
+		 */
+		tCKmax_ps = min(tCKmax_ps, dimm_params[i].tCKmax_ps);
+
+		/* Either find maximum value to determine slowest
+		 * speed, delay, time, period, etc */
+		tCKmin_X_ps = max(tCKmin_X_ps, dimm_params[i].tCKmin_X_ps);
+		tCKmax_max_ps = max(tCKmax_max_ps, dimm_params[i].tCKmax_ps);
+		tRCD_ps = max(tRCD_ps, dimm_params[i].tRCD_ps);
+		tRP_ps = max(tRP_ps, dimm_params[i].tRP_ps);
+		tRAS_ps = max(tRAS_ps, dimm_params[i].tRAS_ps);
+		tWR_ps = max(tWR_ps, dimm_params[i].tWR_ps);
+		tWTR_ps = max(tWTR_ps, dimm_params[i].tWTR_ps);
+		tRFC_ps = max(tRFC_ps, dimm_params[i].tRFC_ps);
+		tRRD_ps = max(tRRD_ps, dimm_params[i].tRRD_ps);
+		tRC_ps = max(tRC_ps, dimm_params[i].tRC_ps);
+		tIS_ps = max(tIS_ps, dimm_params[i].tIS_ps);
+		tIH_ps = max(tIH_ps, dimm_params[i].tIH_ps);
+		tDS_ps = max(tDS_ps, dimm_params[i].tDS_ps);
+		tDH_ps = max(tDH_ps, dimm_params[i].tDH_ps);
+		tRTP_ps = max(tRTP_ps, dimm_params[i].tRTP_ps);
+		tQHS_ps = max(tQHS_ps, dimm_params[i].tQHS_ps);
+		refresh_rate_ps = max(refresh_rate_ps,
+				      dimm_params[i].refresh_rate_ps);
+
+		/*
+		 * Find maximum tDQSQ_max_ps to find slowest.
+		 *
+		 * FIXME: is finding the slowest value the correct
+		 * strategy for this parameter?
+		 */
+		tDQSQ_max_ps = max(tDQSQ_max_ps, dimm_params[i].tDQSQ_max_ps);
+	}
+
+	outpdimm->ndimms_present = number_of_dimms - temp1;
+
+	if (temp1 == number_of_dimms) {
+		debug("no dimms this memory controller\n");
+		return 0;
+	}
+
+	outpdimm->tCKmin_X_ps = tCKmin_X_ps;
+	outpdimm->tCKmax_ps = tCKmax_ps;
+	outpdimm->tCKmax_max_ps = tCKmax_max_ps;
+	outpdimm->tRCD_ps = tRCD_ps;
+	outpdimm->tRP_ps = tRP_ps;
+	outpdimm->tRAS_ps = tRAS_ps;
+	outpdimm->tWR_ps = tWR_ps;
+	outpdimm->tWTR_ps = tWTR_ps;
+	outpdimm->tRFC_ps = tRFC_ps;
+	outpdimm->tRRD_ps = tRRD_ps;
+	outpdimm->tRC_ps = tRC_ps;
+	outpdimm->refresh_rate_ps = refresh_rate_ps;
+	outpdimm->tIS_ps = tIS_ps;
+	outpdimm->tIH_ps = tIH_ps;
+	outpdimm->tDS_ps = tDS_ps;
+	outpdimm->tDH_ps = tDH_ps;
+	outpdimm->tRTP_ps = tRTP_ps;
+	outpdimm->tDQSQ_max_ps = tDQSQ_max_ps;
+	outpdimm->tQHS_ps = tQHS_ps;
+
+	/* Determine common burst length for all DIMMs. */
+	temp1 = 0xff;
+	for (i = 0; i < number_of_dimms; i++) {
+		if (dimm_params[i].n_ranks) {
+			temp1 &= dimm_params[i].burst_lengths_bitmask;
+		}
+	}
+	outpdimm->all_DIMMs_burst_lengths_bitmask = temp1;
+
+	/* Determine if all DIMMs registered buffered. */
+	temp1 = temp2 = 0;
+	for (i = 0; i < number_of_dimms; i++) {
+		if (dimm_params[i].n_ranks) {
+			if (dimm_params[i].registered_dimm)
+				temp1 = 1;
+			if (!dimm_params[i].registered_dimm)
+				temp2 = 1;
+		}
+	}
+
+	outpdimm->all_DIMMs_registered = 0;
+	if (temp1 && !temp2) {
+		outpdimm->all_DIMMs_registered = 1;
+	}
+
+	outpdimm->all_DIMMs_unbuffered = 0;
+	if (!temp1 && temp2) {
+		outpdimm->all_DIMMs_unbuffered = 1;
+	}
+
+	/* CHECKME: */
+	if (!outpdimm->all_DIMMs_registered
+	    && !outpdimm->all_DIMMs_unbuffered) {
+		printf("ERROR:  Mix of registered buffered and unbuffered "
+				"DIMMs detected!\n");
+	}
+
+#if defined(CONFIG_FSL_DDR3)
+	if (compute_cas_latency_ddr3(dimm_params, outpdimm, number_of_dimms))
+		return 1;
+#else
+	/*
+	 * Compute a CAS latency suitable for all DIMMs
+	 *
+	 * Strategy for SPD-defined latencies: compute only
+	 * CAS latency defined by all DIMMs.
+	 */
+
+	/*
+	 * Step 1: find CAS latency common to all DIMMs using bitwise
+	 * operation.
+	 */
+	temp1 = 0xFF;
+	for (i = 0; i < number_of_dimms; i++) {
+		if (dimm_params[i].n_ranks) {
+			temp2 = 0;
+			temp2 |= 1 << dimm_params[i].caslat_X;
+			temp2 |= 1 << dimm_params[i].caslat_X_minus_1;
+			temp2 |= 1 << dimm_params[i].caslat_X_minus_2;
+			/*
+			 * FIXME: If there was no entry for X-2 (X-1) in
+			 * the SPD, then caslat_X_minus_2
+			 * (caslat_X_minus_1) contains either 255 or
+			 * 0xFFFFFFFF because that's what the glorious
+			 * __ilog2 function returns for an input of 0.
+			 * On 32-bit PowerPC, left shift counts with bit
+			 * 26 set (that the value of 255 or 0xFFFFFFFF
+			 * will have), cause the destination register to
+			 * be 0.  That is why this works.
+			 */
+			temp1 &= temp2;
+		}
+	}
+
+	/*
+	 * Step 2: check each common CAS latency against tCK of each
+	 * DIMM's SPD.
+	 */
+	lowest_good_caslat = 0;
+	temp2 = 0;
+	while (temp1) {
+		not_ok = 0;
+		temp2 =  __ilog2(temp1);
+		debug("checking common caslat = %u\n", temp2);
+
+		/* Check if this CAS latency will work on all DIMMs at tCK. */
+		for (i = 0; i < number_of_dimms; i++) {
+			if (!dimm_params[i].n_ranks) {
+				continue;
+			}
+			if (dimm_params[i].caslat_X == temp2) {
+				if (mclk_ps >= dimm_params[i].tCKmin_X_ps) {
+					debug("CL = %u ok on DIMM %u at tCK=%u"
+					    " ps with its tCKmin_X_ps of %u\n",
+					       temp2, i, mclk_ps,
+					       dimm_params[i].tCKmin_X_ps);
+					continue;
+				} else {
+					not_ok++;
+				}
+			}
+
+			if (dimm_params[i].caslat_X_minus_1 == temp2) {
+				unsigned int tCKmin_X_minus_1_ps
+					= dimm_params[i].tCKmin_X_minus_1_ps;
+				if (mclk_ps >= tCKmin_X_minus_1_ps) {
+					debug("CL = %u ok on DIMM %u at "
+						"tCK=%u ps with its "
+						"tCKmin_X_minus_1_ps of %u\n",
+					       temp2, i, mclk_ps,
+					       tCKmin_X_minus_1_ps);
+					continue;
+				} else {
+					not_ok++;
+				}
+			}
+
+			if (dimm_params[i].caslat_X_minus_2 == temp2) {
+				unsigned int tCKmin_X_minus_2_ps
+					= dimm_params[i].tCKmin_X_minus_2_ps;
+				if (mclk_ps >= tCKmin_X_minus_2_ps) {
+					debug("CL = %u ok on DIMM %u at "
+						"tCK=%u ps with its "
+						"tCKmin_X_minus_2_ps of %u\n",
+					       temp2, i, mclk_ps,
+					       tCKmin_X_minus_2_ps);
+					continue;
+				} else {
+					not_ok++;
+				}
+			}
+		}
+
+		if (!not_ok) {
+			lowest_good_caslat = temp2;
+		}
+
+		temp1 &= ~(1 << temp2);
+	}
+
+	debug("lowest common SPD-defined CAS latency = %u\n",
+	       lowest_good_caslat);
+	outpdimm->lowest_common_SPD_caslat = lowest_good_caslat;
+
+
+	/*
+	 * Compute a common 'de-rated' CAS latency.
+	 *
+	 * The strategy here is to find the *highest* dereated cas latency
+	 * with the assumption that all of the DIMMs will support a dereated
+	 * CAS latency higher than or equal to their lowest dereated value.
+	 */
+	temp1 = 0;
+	for (i = 0; i < number_of_dimms; i++) {
+		temp1 = max(temp1, dimm_params[i].caslat_lowest_derated);
+	}
+	outpdimm->highest_common_derated_caslat = temp1;
+	debug("highest common dereated CAS latency = %u\n", temp1);
+#endif /* #if defined(CONFIG_FSL_DDR3) */
+
+	/* Determine if all DIMMs ECC capable. */
+	temp1 = 1;
+	for (i = 0; i < number_of_dimms; i++) {
+		if (dimm_params[i].n_ranks && dimm_params[i].edc_config != 2) {
+			temp1 = 0;
+			break;
+		}
+	}
+	if (temp1) {
+		debug("all DIMMs ECC capable\n");
+	} else {
+		debug("Warning: not all DIMMs ECC capable, cant enable ECC\n");
+	}
+	outpdimm->all_DIMMs_ECC_capable = temp1;
+
+#ifndef CONFIG_FSL_DDR3
+	/* FIXME: move to somewhere else to validate. */
+	if (mclk_ps > tCKmax_max_ps) {
+		printf("Warning: some of the installed DIMMs "
+				"can not operate this slowly.\n");
+		return 1;
+	}
+#endif
+	/*
+	 * Compute additive latency.
+	 *
+	 * For DDR1, additive latency should be 0.
+	 *
+	 * For DDR2, with ODT enabled, use "a value" less than ACTTORW,
+	 *	which comes from Trcd, and also note that:
+	 *	    add_lat + caslat must be >= 4
+	 *
+	 * For DDR3, we use the AL=0
+	 *
+	 * When to use additive latency for DDR2:
+	 *
+	 * I. Because you are using CL=3 and need to do ODT on writes and
+	 *    want functionality.
+	 *    1. Are you going to use ODT? (Does your board not have
+	 *      additional termination circuitry for DQ, DQS, DQS_,
+	 *      DM, RDQS, RDQS_ for x4/x8 configs?)
+	 *    2. If so, is your lowest supported CL going to be 3?
+	 *    3. If so, then you must set AL=1 because
+	 *
+	 *       WL >= 3 for ODT on writes
+	 *       RL = AL + CL
+	 *       WL = RL - 1
+	 *       ->
+	 *       WL = AL + CL - 1
+	 *       AL + CL - 1 >= 3
+	 *       AL + CL >= 4
+	 *  QED
+	 *
+	 *  RL >= 3 for ODT on reads
+	 *  RL = AL + CL
+	 *
+	 *  Since CL aren't usually less than 2, AL=0 is a minimum,
+	 *  so the WL-derived AL should be the  -- FIXME?
+	 *
+	 * II. Because you are using auto-precharge globally and want to
+	 *     use additive latency (posted CAS) to get more bandwidth.
+	 *     1. Are you going to use auto-precharge mode globally?
+	 *
+	 *        Use addtivie latency and compute AL to be 1 cycle less than
+	 *        tRCD, i.e. the READ or WRITE command is in the cycle
+	 *        immediately following the ACTIVATE command..
+	 *
+	 * III. Because you feel like it or want to do some sort of
+	 *      degraded-performance experiment.
+	 *     1.  Do you just want to use additive latency because you feel
+	 *         like it?
+	 *
+	 * Validation:  AL is less than tRCD, and within the other
+	 * read-to-precharge constraints.
+	 */
+
+	additive_latency = 0;
+
+#if defined(CONFIG_FSL_DDR2)
+	if (lowest_good_caslat < 4) {
+		additive_latency = picos_to_mclk(tRCD_ps) - lowest_good_caslat;
+		if (mclk_to_picos(additive_latency) > tRCD_ps) {
+			additive_latency = picos_to_mclk(tRCD_ps);
+			debug("setting additive_latency to %u because it was "
+				" greater than tRCD_ps\n", additive_latency);
+		}
+	}
+
+#elif defined(CONFIG_FSL_DDR3)
+	/*
+	 * The system will not use the global auto-precharge mode.
+	 * However, it uses the page mode, so we set AL=0
+	 */
+	additive_latency = 0;
+#endif
+
+	/*
+	 * Validate additive latency
+	 * FIXME: move to somewhere else to validate
+	 *
+	 * AL <= tRCD(min)
+	 */
+	if (mclk_to_picos(additive_latency) > tRCD_ps) {
+		printf("Error: invalid additive latency exceeds tRCD(min).\n");
+		return 1;
+	}
+
+	/*
+	 * RL = CL + AL;  RL >= 3 for ODT_RD_CFG to be enabled
+	 * WL = RL - 1;  WL >= 3 for ODT_WL_CFG to be enabled
+	 * ADD_LAT (the register) must be set to a value less
+	 * than ACTTORW if WL = 1, then AL must be set to 1
+	 * RD_TO_PRE (the register) must be set to a minimum
+	 * tRTP + AL if AL is nonzero
+	 */
+
+	/*
+	 * Additive latency will be applied only if the memctl option to
+	 * use it.
+	 */
+	outpdimm->additive_latency = additive_latency;
+
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/main.c b/arch/powerpc/cpu/mpc8xxx/ddr/main.c
new file mode 100644
index 0000000..faa1af9
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/main.c
@@ -0,0 +1,479 @@
+/*
+ * Copyright 2008 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+/*
+ * Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
+ * Based on code from spd_sdram.c
+ * Author: James Yang [at freescale.com]
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+
+extern void fsl_ddr_set_lawbar(
+		const common_timing_params_t *memctl_common_params,
+		unsigned int memctl_interleaved,
+		unsigned int ctrl_num);
+
+/* processor specific function */
+extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+				   unsigned int ctrl_num);
+
+/* Board-specific functions defined in each board's ddr.c */
+extern void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd,
+			   unsigned int ctrl_num);
+
+/*
+ * ASSUMPTIONS:
+ *    - Same number of CONFIG_DIMM_SLOTS_PER_CTLR on each controller
+ *    - Same memory data bus width on all controllers
+ *
+ * NOTES:
+ *
+ * The memory controller and associated documentation use confusing
+ * terminology when referring to the orgranization of DRAM.
+ *
+ * Here is a terminology translation table:
+ *
+ * memory controller/documention  |industry   |this code  |signals
+ * -------------------------------|-----------|-----------|-----------------
+ * physical bank/bank		  |rank       |rank	  |chip select (CS)
+ * logical bank/sub-bank	  |bank       |bank	  |bank address (BA)
+ * page/row			  |row	      |page	  |row address
+ * ???				  |column     |column	  |column address
+ *
+ * The naming confusion is further exacerbated by the descriptions of the
+ * memory controller interleaving feature, where accesses are interleaved
+ * _BETWEEN_ two seperate memory controllers.  This is configured only in
+ * CS0_CONFIG[INTLV_CTL] of each memory controller.
+ *
+ * memory controller documentation | number of chip selects
+ *				   | per memory controller supported
+ * --------------------------------|-----------------------------------------
+ * cache line interleaving	   | 1 (CS0 only)
+ * page interleaving		   | 1 (CS0 only)
+ * bank interleaving		   | 1 (CS0 only)
+ * superbank interleraving	   | depends on bank (chip select)
+ *				   |   interleraving [rank interleaving]
+ *				   |   mode used on every memory controller
+ *
+ * Even further confusing is the existence of the interleaving feature
+ * _WITHIN_ each memory controller.  The feature is referred to in
+ * documentation as chip select interleaving or bank interleaving,
+ * although it is configured in the DDR_SDRAM_CFG field.
+ *
+ * Name of field		| documentation name	| this code
+ * -----------------------------|-----------------------|------------------
+ * DDR_SDRAM_CFG[BA_INTLV_CTL]	| Bank (chip select)	| rank interleaving
+ *				|  interleaving
+ */
+
+#ifdef DEBUG
+const char *step_string_tbl[] = {
+	"STEP_GET_SPD",
+	"STEP_COMPUTE_DIMM_PARMS",
+	"STEP_COMPUTE_COMMON_PARMS",
+	"STEP_GATHER_OPTS",
+	"STEP_ASSIGN_ADDRESSES",
+	"STEP_COMPUTE_REGS",
+	"STEP_PROGRAM_REGS",
+	"STEP_ALL"
+};
+
+const char * step_to_string(unsigned int step) {
+
+	unsigned int s = __ilog2(step);
+
+	if ((1 << s) != step)
+		return step_string_tbl[7];
+
+	return step_string_tbl[s];
+}
+#endif
+
+int step_assign_addresses(fsl_ddr_info_t *pinfo,
+			  unsigned int dbw_cap_adj[],
+			  unsigned int *memctl_interleaving,
+			  unsigned int *rank_interleaving)
+{
+	int i, j;
+
+	/*
+	 * If a reduced data width is requested, but the SPD
+	 * specifies a physically wider device, adjust the
+	 * computed dimm capacities accordingly before
+	 * assigning addresses.
+	 */
+	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+		unsigned int found = 0;
+
+		switch (pinfo->memctl_opts[i].data_bus_width) {
+		case 2:
+			/* 16-bit */
+			printf("can't handle 16-bit mode yet\n");
+			break;
+
+		case 1:
+			/* 32-bit */
+			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+				unsigned int dw;
+				dw = pinfo->dimm_params[i][j].data_width;
+				if (pinfo->dimm_params[i][j].n_ranks
+				    && (dw == 72 || dw == 64)) {
+					/*
+					 * FIXME: can't really do it
+					 * like this because this just
+					 * further reduces the memory
+					 */
+					found = 1;
+					break;
+				}
+			}
+			if (found) {
+				dbw_cap_adj[i] = 1;
+			}
+			break;
+
+		case 0:
+			/* 64-bit */
+			break;
+
+		default:
+			printf("unexpected data bus width "
+				"specified controller %u\n", i);
+			return 1;
+		}
+	}
+
+	/*
+	 * Check if all controllers are configured for memory
+	 * controller interleaving.
+	 */
+	j = 0;
+	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+		if (pinfo->memctl_opts[i].memctl_interleaving) {
+			j++;
+		}
+	}
+	if (j == 2)
+		*memctl_interleaving = 1;
+
+	/* Check that all controllers are rank interleaving. */
+	j = 0;
+	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+		if (pinfo->memctl_opts[i].ba_intlv_ctl) {
+			j++;
+		}
+	}
+	if (j == 2)
+		*rank_interleaving = 1;
+
+	if (*memctl_interleaving) {
+		unsigned long long addr, total_mem_per_ctlr = 0;
+		/*
+		 * If interleaving between memory controllers,
+		 * make each controller start at a base address
+		 * of 0.
+		 *
+		 * Also, if bank interleaving (chip select
+		 * interleaving) is enabled on each memory
+		 * controller, CS0 needs to be programmed to
+		 * cover the entire memory range on that memory
+		 * controller
+		 *
+		 * Bank interleaving also implies that each
+		 * addressed chip select is identical in size.
+		 */
+
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			addr = 0;
+			pinfo->common_timing_params[i].base_address = 0ull;
+			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+				unsigned long long cap
+					= pinfo->dimm_params[i][j].capacity;
+
+				pinfo->dimm_params[i][j].base_address = addr;
+				addr += cap >> dbw_cap_adj[i];
+				total_mem_per_ctlr += cap >> dbw_cap_adj[i];
+			}
+		}
+		pinfo->common_timing_params[0].total_mem = total_mem_per_ctlr;
+	} else {
+		/*
+		 * Simple linear assignment if memory
+		 * controllers are not interleaved.
+		 */
+		unsigned long long cur_memsize = 0;
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			u64 total_mem_per_ctlr = 0;
+			pinfo->common_timing_params[i].base_address =
+						cur_memsize;
+			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+				/* Compute DIMM base addresses. */
+				unsigned long long cap =
+					pinfo->dimm_params[i][j].capacity;
+				pinfo->dimm_params[i][j].base_address =
+					cur_memsize;
+				cur_memsize += cap >> dbw_cap_adj[i];
+				total_mem_per_ctlr += cap >> dbw_cap_adj[i];
+			}
+			pinfo->common_timing_params[i].total_mem =
+							total_mem_per_ctlr;
+		}
+	}
+
+	return 0;
+}
+
+unsigned long long
+fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step)
+{
+	unsigned int i, j;
+	unsigned int all_controllers_memctl_interleaving = 0;
+	unsigned int all_controllers_rank_interleaving = 0;
+	unsigned long long total_mem = 0;
+
+	fsl_ddr_cfg_regs_t *ddr_reg = pinfo->fsl_ddr_config_reg;
+	common_timing_params_t *timing_params = pinfo->common_timing_params;
+
+	/* data bus width capacity adjust shift amount */
+	unsigned int dbw_capacity_adjust[CONFIG_NUM_DDR_CONTROLLERS];
+
+	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+		dbw_capacity_adjust[i] = 0;
+	}
+
+	debug("starting at step %u (%s)\n",
+	      start_step, step_to_string(start_step));
+
+	switch (start_step) {
+	case STEP_GET_SPD:
+		/* STEP 1:  Gather all DIMM SPD data */
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			fsl_ddr_get_spd(pinfo->spd_installed_dimms[i], i);
+		}
+
+	case STEP_COMPUTE_DIMM_PARMS:
+		/* STEP 2:  Compute DIMM parameters from SPD data */
+
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+				unsigned int retval;
+				generic_spd_eeprom_t *spd =
+					&(pinfo->spd_installed_dimms[i][j]);
+				dimm_params_t *pdimm =
+					&(pinfo->dimm_params[i][j]);
+
+				retval = compute_dimm_parameters(spd, pdimm, i);
+				if (retval == 2) {
+					printf("Error: compute_dimm_parameters"
+					" non-zero returned FATAL value "
+					"for memctl=%u dimm=%u\n", i, j);
+					return 0;
+				}
+				if (retval) {
+					debug("Warning: compute_dimm_parameters"
+					" non-zero return value for memctl=%u "
+					"dimm=%u\n", i, j);
+				}
+			}
+		}
+
+	case STEP_COMPUTE_COMMON_PARMS:
+		/*
+		 * STEP 3: Compute a common set of timing parameters
+		 * suitable for all of the DIMMs on each memory controller
+		 */
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			debug("Computing lowest common DIMM"
+				" parameters for memctl=%u\n", i);
+			compute_lowest_common_dimm_parameters(
+				pinfo->dimm_params[i],
+				&timing_params[i],
+				CONFIG_DIMM_SLOTS_PER_CTLR);
+		}
+
+	case STEP_GATHER_OPTS:
+		/* STEP 4:  Gather configuration requirements from user */
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			debug("Reloading memory controller "
+				"configuration options for memctl=%u\n", i);
+			/*
+			 * This "reloads" the memory controller options
+			 * to defaults.  If the user "edits" an option,
+			 * next_step points to the step after this,
+			 * which is currently STEP_ASSIGN_ADDRESSES.
+			 */
+			populate_memctl_options(
+					timing_params[i].all_DIMMs_registered,
+					&pinfo->memctl_opts[i],
+					pinfo->dimm_params[i], i);
+		}
+
+	case STEP_ASSIGN_ADDRESSES:
+		/* STEP 5:  Assign addresses to chip selects */
+		step_assign_addresses(pinfo,
+				dbw_capacity_adjust,
+				&all_controllers_memctl_interleaving,
+				&all_controllers_rank_interleaving);
+
+	case STEP_COMPUTE_REGS:
+		/* STEP 6:  compute controller register values */
+		debug("FSL Memory ctrl cg register computation\n");
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			if (timing_params[i].ndimms_present == 0) {
+				memset(&ddr_reg[i], 0,
+					sizeof(fsl_ddr_cfg_regs_t));
+				continue;
+			}
+
+			compute_fsl_memctl_config_regs(
+					&pinfo->memctl_opts[i],
+					&ddr_reg[i], &timing_params[i],
+					pinfo->dimm_params[i],
+					dbw_capacity_adjust[i]);
+		}
+
+	default:
+		break;
+	}
+
+	/* Compute the total amount of memory. */
+
+	/*
+	 * If bank interleaving but NOT memory controller interleaving
+	 * CS_BNDS describe the quantity of memory on each memory
+	 * controller, so the total is the sum across.
+	 */
+	if (!all_controllers_memctl_interleaving
+	    && all_controllers_rank_interleaving) {
+		total_mem = 0;
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			total_mem += timing_params[i].total_mem;
+		}
+
+	} else {
+		/*
+		 * Compute the amount of memory available just by
+		 * looking for the highest valid CSn_BNDS value.
+		 * This allows us to also experiment with using
+		 * only CS0 when using dual-rank DIMMs.
+		 */
+		unsigned int max_end = 0;
+
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			for (j = 0; j < CONFIG_CHIP_SELECTS_PER_CTRL; j++) {
+				fsl_ddr_cfg_regs_t *reg = &ddr_reg[i];
+				if (reg->cs[j].config & 0x80000000) {
+					unsigned int end;
+					end = reg->cs[j].bnds & 0xFFF;
+					if (end > max_end) {
+						max_end = end;
+					}
+				}
+			}
+		}
+
+		total_mem = 1 + (((unsigned long long)max_end << 24ULL)
+				    | 0xFFFFFFULL);
+	}
+
+	return total_mem;
+}
+
+/*
+ * fsl_ddr_sdram() -- this is the main function to be called by
+ *	initdram() in the board file.
+ *
+ * It returns amount of memory configured in bytes.
+ */
+phys_size_t fsl_ddr_sdram(void)
+{
+	unsigned int i;
+	unsigned int memctl_interleaved;
+	unsigned long long total_memory;
+	fsl_ddr_info_t info;
+
+	/* Reset info structure. */
+	memset(&info, 0, sizeof(fsl_ddr_info_t));
+
+	/* Compute it once normally. */
+	total_memory = fsl_ddr_compute(&info, STEP_GET_SPD);
+
+	/* Check for memory controller interleaving. */
+	memctl_interleaved = 0;
+	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+		memctl_interleaved +=
+			info.memctl_opts[i].memctl_interleaving;
+	}
+
+	if (memctl_interleaved) {
+		if (memctl_interleaved == CONFIG_NUM_DDR_CONTROLLERS) {
+			debug("memctl interleaving\n");
+			/*
+			 * Change the meaning of memctl_interleaved
+			 * to be "boolean".
+			 */
+			memctl_interleaved = 1;
+		} else {
+			printf("Warning: memctl interleaving not "
+				"properly configured on all controllers\n");
+			memctl_interleaved = 0;
+			for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
+				info.memctl_opts[i].memctl_interleaving = 0;
+			debug("Recomputing with memctl_interleaving off.\n");
+			total_memory = fsl_ddr_compute(&info,
+						       STEP_ASSIGN_ADDRESSES);
+		}
+	}
+
+	/* Program configuration registers. */
+	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+		debug("Programming controller %u\n", i);
+		if (info.common_timing_params[i].ndimms_present == 0) {
+			debug("No dimms present on controller %u; "
+					"skipping programming\n", i);
+			continue;
+		}
+
+		fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), i);
+	}
+
+	if (memctl_interleaved) {
+		const unsigned int ctrl_num = 0;
+
+		/* Only set LAWBAR1 if memory controller interleaving is on. */
+		fsl_ddr_set_lawbar(&info.common_timing_params[0],
+					 memctl_interleaved, ctrl_num);
+	} else {
+		/*
+		 * Memory controller interleaving is NOT on;
+		 * set each lawbar individually.
+		 */
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			fsl_ddr_set_lawbar(&info.common_timing_params[i],
+						 0, i);
+		}
+	}
+
+	debug("total_memory = %llu\n", total_memory);
+
+#if !defined(CONFIG_PHYS_64BIT)
+	/* Check for 4G or more.  Bad. */
+	if (total_memory >= (1ull << 32)) {
+		printf("Detected %lld MB of memory\n", total_memory >> 20);
+		printf("This U-Boot only supports < 4G of DDR\n");
+		printf("You could rebuild it with CONFIG_PHYS_64BIT\n");
+		total_memory = CONFIG_MAX_MEM_MAPPED;
+	}
+#endif
+
+	return total_memory;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/options.c b/arch/powerpc/cpu/mpc8xxx/ddr/options.c
new file mode 100644
index 0000000..46731c8
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/options.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2008, 2010 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 <common.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+
+/* Board-specific functions defined in each board's ddr.c */
+extern void fsl_ddr_board_options(memctl_options_t *popts,
+		dimm_params_t *pdimm,
+		unsigned int ctrl_num);
+
+unsigned int populate_memctl_options(int all_DIMMs_registered,
+			memctl_options_t *popts,
+			dimm_params_t *pdimm,
+			unsigned int ctrl_num)
+{
+	unsigned int i;
+	const char *p;
+
+	/* Chip select options. */
+
+	/* Pick chip-select local options. */
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		/* If not DDR2, odt_rd_cfg and odt_wr_cfg need to be 0. */
+
+		/* only for single CS? */
+		popts->cs_local_opts[i].odt_rd_cfg = 0;
+
+		popts->cs_local_opts[i].odt_wr_cfg = 1;
+		popts->cs_local_opts[i].auto_precharge = 0;
+	}
+
+	/* Pick interleaving mode. */
+
+	/*
+	 * 0 = no interleaving
+	 * 1 = interleaving between 2 controllers
+	 */
+	popts->memctl_interleaving = 0;
+
+	/*
+	 * 0 = cacheline
+	 * 1 = page
+	 * 2 = (logical) bank
+	 * 3 = superbank (only if CS interleaving is enabled)
+	 */
+	popts->memctl_interleaving_mode = 0;
+
+	/*
+	 * 0: cacheline: bit 30 of the 36-bit physical addr selects the memctl
+	 * 1: page:      bit to the left of the column bits selects the memctl
+	 * 2: bank:      bit to the left of the bank bits selects the memctl
+	 * 3: superbank: bit to the left of the chip select selects the memctl
+	 *
+	 * NOTE: ba_intlv (rank interleaving) is independent of memory
+	 * controller interleaving; it is only within a memory controller.
+	 * Must use superbank interleaving if rank interleaving is used and
+	 * memory controller interleaving is enabled.
+	 */
+
+	/*
+	 * 0 = no
+	 * 0x40 = CS0,CS1
+	 * 0x20 = CS2,CS3
+	 * 0x60 = CS0,CS1 + CS2,CS3
+	 * 0x04 = CS0,CS1,CS2,CS3
+	 */
+	popts->ba_intlv_ctl = 0;
+
+	/* Memory Organization Parameters */
+	popts->registered_dimm_en = all_DIMMs_registered;
+
+	/* Operational Mode Paramters */
+
+	/* Pick ECC modes */
+#ifdef CONFIG_DDR_ECC
+	popts->ECC_mode = 1;		  /* 0 = disabled, 1 = enabled */
+#else
+	popts->ECC_mode = 0;		  /* 0 = disabled, 1 = enabled */
+#endif
+	popts->ECC_init_using_memctl = 1; /* 0 = use DMA, 1 = use memctl */
+
+	/*
+	 * Choose DQS config
+	 * 0 for DDR1
+	 * 1 for DDR2
+	 */
+#if defined(CONFIG_FSL_DDR1)
+	popts->DQS_config = 0;
+#elif defined(CONFIG_FSL_DDR2) || defined(CONFIG_FSL_DDR3)
+	popts->DQS_config = 1;
+#endif
+
+	/* Choose self-refresh during sleep. */
+	popts->self_refresh_in_sleep = 1;
+
+	/* Choose dynamic power management mode. */
+	popts->dynamic_power = 0;
+
+	/* 0 = 64-bit, 1 = 32-bit, 2 = 16-bit */
+	popts->data_bus_width = 0;
+
+	/* Choose burst length. */
+#if defined(CONFIG_FSL_DDR3)
+#if defined(CONFIG_E500MC)
+	popts->OTF_burst_chop_en = 0;	/* on-the-fly burst chop disable */
+	popts->burst_length = DDR_BL8;	/* Fixed 8-beat burst len */
+#else
+	popts->OTF_burst_chop_en = 1;	/* on-the-fly burst chop */
+	popts->burst_length = DDR_OTF;	/* on-the-fly BC4 and BL8 */
+#endif
+#else
+	popts->burst_length = DDR_BL4;	/* has to be 4 for DDR2 */
+#endif
+
+	/* Choose ddr controller address mirror mode */
+#if defined(CONFIG_FSL_DDR3)
+	popts->mirrored_dimm = pdimm[0].mirrored_dimm;
+#endif
+
+	/* Global Timing Parameters. */
+	debug("mclk_ps = %u ps\n", get_memory_clk_period_ps());
+
+	/* Pick a caslat override. */
+	popts->cas_latency_override = 0;
+	popts->cas_latency_override_value = 3;
+	if (popts->cas_latency_override) {
+		debug("using caslat override value = %u\n",
+		       popts->cas_latency_override_value);
+	}
+
+	/* Decide whether to use the computed derated latency */
+	popts->use_derated_caslat = 0;
+
+	/* Choose an additive latency. */
+	popts->additive_latency_override = 0;
+	popts->additive_latency_override_value = 3;
+	if (popts->additive_latency_override) {
+		debug("using additive latency override value = %u\n",
+		       popts->additive_latency_override_value);
+	}
+
+	/*
+	 * 2T_EN setting
+	 *
+	 * Factors to consider for 2T_EN:
+	 *	- number of DIMMs installed
+	 *	- number of components, number of active ranks
+	 *	- how much time you want to spend playing around
+	 */
+	popts->twoT_en = 0;
+	popts->threeT_en = 0;
+
+	/*
+	 * BSTTOPRE precharge interval
+	 *
+	 * Set this to 0 for global auto precharge
+	 *
+	 * FIXME: Should this be configured in picoseconds?
+	 * Why it should be in ps:  better understanding of this
+	 * relative to actual DRAM timing parameters such as tRAS.
+	 * e.g. tRAS(min) = 40 ns
+	 */
+	popts->bstopre = 0x100;
+
+	/* Minimum CKE pulse width -- tCKE(MIN) */
+	popts->tCKE_clock_pulse_width_ps
+		= mclk_to_picos(FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR);
+
+	/*
+	 * Window for four activates -- tFAW
+	 *
+	 * FIXME: UM: applies only to DDR2/DDR3 with eight logical banks only
+	 * FIXME: varies depending upon number of column addresses or data
+	 * FIXME: width, was considering looking at pdimm->primary_sdram_width
+	 */
+#if defined(CONFIG_FSL_DDR1)
+	popts->tFAW_window_four_activates_ps = mclk_to_picos(1);
+
+#elif defined(CONFIG_FSL_DDR2)
+	/*
+	 * x4/x8;  some datasheets have 35000
+	 * x16 wide columns only?  Use 50000?
+	 */
+	popts->tFAW_window_four_activates_ps = 37500;
+
+#elif defined(CONFIG_FSL_DDR3)
+	popts->tFAW_window_four_activates_ps = pdimm[0].tFAW_ps;
+#endif
+	popts->zq_en = 0;
+	popts->wrlvl_en = 0;
+#if defined(CONFIG_FSL_DDR3)
+	/*
+	 * due to ddr3 dimm is fly-by topology
+	 * we suggest to enable write leveling to
+	 * meet the tQDSS under different loading.
+	 */
+	popts->wrlvl_en = 1;
+	popts->wrlvl_override = 0;
+#endif
+
+	/*
+	 * Check interleaving configuration from environment.
+	 * Please refer to doc/README.fsl-ddr for the detail.
+	 *
+	 * If memory controller interleaving is enabled, then the data
+	 * bus widths must be programmed identically for the 2 memory
+	 * controllers.
+	 *
+	 * XXX: Attempt to set both controllers to the same chip select
+	 * interleaving mode. It will do a best effort to get the
+	 * requested ranks interleaved together such that the result
+	 * should be a subset of the requested configuration.
+	 */
+#if (CONFIG_NUM_DDR_CONTROLLERS > 1)
+	if ((p = getenv("memctl_intlv_ctl")) != NULL) {
+		if (pdimm[0].n_ranks == 0) {
+			printf("There is no rank on CS0. Because only rank on "
+				"CS0 and ranks chip-select interleaved with CS0"
+				" are controller interleaved, force non memory "
+				"controller interleaving\n");
+			popts->memctl_interleaving = 0;
+		} else {
+			popts->memctl_interleaving = 1;
+			if (strcmp(p, "cacheline") == 0)
+				popts->memctl_interleaving_mode =
+					FSL_DDR_CACHE_LINE_INTERLEAVING;
+			else if (strcmp(p, "page") == 0)
+				popts->memctl_interleaving_mode =
+					FSL_DDR_PAGE_INTERLEAVING;
+			else if (strcmp(p, "bank") == 0)
+				popts->memctl_interleaving_mode =
+					FSL_DDR_BANK_INTERLEAVING;
+			else if (strcmp(p, "superbank") == 0)
+				popts->memctl_interleaving_mode =
+					FSL_DDR_SUPERBANK_INTERLEAVING;
+			else
+				popts->memctl_interleaving_mode =
+						simple_strtoul(p, NULL, 0);
+		}
+	}
+#endif
+
+	if( ((p = getenv("ba_intlv_ctl")) != NULL) &&
+		(CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
+		if (strcmp(p, "cs0_cs1") == 0)
+			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1;
+		else if (strcmp(p, "cs2_cs3") == 0)
+			popts->ba_intlv_ctl = FSL_DDR_CS2_CS3;
+		else if (strcmp(p, "cs0_cs1_and_cs2_cs3") == 0)
+			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_AND_CS2_CS3;
+		else if (strcmp(p, "cs0_cs1_cs2_cs3") == 0)
+			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_CS2_CS3;
+		else
+			popts->ba_intlv_ctl = simple_strtoul(p, NULL, 0);
+
+		switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
+		case FSL_DDR_CS0_CS1_CS2_CS3:
+		case FSL_DDR_CS0_CS1:
+			if (pdimm[0].n_ranks != 2) {
+				popts->ba_intlv_ctl = 0;
+				printf("Not enough bank(chip-select) for "
+					"CS0+CS1, force non-interleaving!\n");
+			}
+			break;
+		case FSL_DDR_CS2_CS3:
+			if (pdimm[1].n_ranks !=2){
+				popts->ba_intlv_ctl = 0;
+				printf("Not enough bank(CS) for CS2+CS3, "
+					"force non-interleaving!\n");
+			}
+			break;
+		case FSL_DDR_CS0_CS1_AND_CS2_CS3:
+			if ((pdimm[0].n_ranks != 2)||(pdimm[1].n_ranks != 2)) {
+				popts->ba_intlv_ctl = 0;
+				printf("Not enough bank(CS) for CS0+CS1 or "
+					"CS2+CS3, force non-interleaving!\n");
+			}
+			break;
+		default:
+			popts->ba_intlv_ctl = 0;
+			break;
+		}
+	}
+
+	fsl_ddr_board_options(popts, pdimm, ctrl_num);
+
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/util.c b/arch/powerpc/cpu/mpc8xxx/ddr/util.c
new file mode 100644
index 0000000..1e2d921
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/util.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2008 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/fsl_law.h>
+
+#include "ddr.h"
+
+unsigned int fsl_ddr_get_mem_data_rate(void);
+
+/*
+ * Round mclk_ps to nearest 10 ps in memory controller code.
+ *
+ * If an imprecise data rate is too high due to rounding error
+ * propagation, compute a suitably rounded mclk_ps to compute
+ * a working memory controller configuration.
+ */
+unsigned int get_memory_clk_period_ps(void)
+{
+	unsigned int mclk_ps;
+
+	mclk_ps = 2000000000000ULL / fsl_ddr_get_mem_data_rate();
+	/* round to nearest 10 ps */
+	return 10 * ((mclk_ps + 5) / 10);
+}
+
+/* Convert picoseconds into DRAM clock cycles (rounding up if needed). */
+unsigned int picos_to_mclk(unsigned int picos)
+{
+	const unsigned long long ULL_2e12 = 2000000000000ULL;
+	const unsigned long long ULL_8Fs = 0xFFFFFFFFULL;
+	unsigned long long clks;
+	unsigned long long clks_temp;
+
+	if (!picos)
+		return 0;
+
+	clks = fsl_ddr_get_mem_data_rate() * (unsigned long long) picos;
+	clks_temp = clks;
+	clks = clks / ULL_2e12;
+	if (clks_temp % ULL_2e12) {
+		clks++;
+	}
+
+	if (clks > ULL_8Fs) {
+		clks = ULL_8Fs;
+	}
+
+	return (unsigned int) clks;
+}
+
+unsigned int mclk_to_picos(unsigned int mclk)
+{
+	return get_memory_clk_period_ps() * mclk;
+}
+
+void
+__fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params,
+			   unsigned int memctl_interleaved,
+			   unsigned int ctrl_num)
+{
+	unsigned long long base = memctl_common_params->base_address;
+	unsigned long long size = memctl_common_params->total_mem;
+
+	/*
+	 * If no DIMMs on this controller, do not proceed any further.
+	 */
+	if (!memctl_common_params->ndimms_present) {
+		return;
+	}
+
+#if !defined(CONFIG_PHYS_64BIT)
+	if (base >= CONFIG_MAX_MEM_MAPPED)
+		return;
+	if ((base + size) >= CONFIG_MAX_MEM_MAPPED)
+		size = CONFIG_MAX_MEM_MAPPED - base;
+#endif
+
+	if (ctrl_num == 0) {
+		/*
+		 * Set up LAW for DDR controller 1 space.
+		 */
+		unsigned int lawbar1_target_id = memctl_interleaved
+			? LAW_TRGT_IF_DDR_INTRLV : LAW_TRGT_IF_DDR_1;
+
+		if (set_ddr_laws(base, size, lawbar1_target_id) < 0) {
+			printf("%s: ERROR (ctrl #0, intrlv=%d)\n", __func__,
+				memctl_interleaved);
+			return ;
+		}
+	} else if (ctrl_num == 1) {
+		if (set_ddr_laws(base, size, LAW_TRGT_IF_DDR_2) < 0) {
+			printf("%s: ERROR (ctrl #1)\n", __func__);
+			return ;
+		}
+	} else {
+		printf("%s: unexpected DDR controller number (%u)\n", __func__,
+			ctrl_num);
+	}
+}
+
+__attribute__((weak, alias("__fsl_ddr_set_lawbar"))) void
+fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params,
+			 unsigned int memctl_interleaved,
+			 unsigned int ctrl_num);
+
+void board_add_ram_info(int use_default)
+{
+#if defined(CONFIG_MPC85xx)
+	volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC85xx_DDR_ADDR);
+#elif defined(CONFIG_MPC86xx)
+	volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC86xx_DDR_ADDR);
+#endif
+#if (CONFIG_NUM_DDR_CONTROLLERS > 1)
+	uint32_t cs0_config = in_be32(&ddr->cs0_config);
+#endif
+	uint32_t sdram_cfg = in_be32(&ddr->sdram_cfg);
+	int cas_lat;
+
+	puts(" (DDR");
+	switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >>
+		SDRAM_CFG_SDRAM_TYPE_SHIFT) {
+	case SDRAM_TYPE_DDR1:
+		puts("1");
+		break;
+	case SDRAM_TYPE_DDR2:
+		puts("2");
+		break;
+	case SDRAM_TYPE_DDR3:
+		puts("3");
+		break;
+	default:
+		puts("?");
+		break;
+	}
+
+	if (sdram_cfg & SDRAM_CFG_32_BE)
+		puts(", 32-bit");
+	else
+		puts(", 64-bit");
+
+	/* Calculate CAS latency based on timing cfg values */
+	cas_lat = ((in_be32(&ddr->timing_cfg_1) >> 16) & 0xf) + 1;
+	if ((in_be32(&ddr->timing_cfg_3) >> 12) & 1)
+		cas_lat += (8 << 1);
+	printf(", CL=%d", cas_lat >> 1);
+	if (cas_lat & 0x1)
+		puts(".5");
+
+	if (sdram_cfg & SDRAM_CFG_ECC_EN)
+		puts(", ECC on)");
+	else
+		puts(", ECC off)");
+
+#if (CONFIG_NUM_DDR_CONTROLLERS > 1)
+	if (cs0_config & 0x20000000) {
+		puts("\n");
+		puts("       DDR Controller Interleaving Mode: ");
+
+		switch ((cs0_config >> 24) & 0xf) {
+		case FSL_DDR_CACHE_LINE_INTERLEAVING:
+			puts("cache line");
+			break;
+		case FSL_DDR_PAGE_INTERLEAVING:
+			puts("page");
+			break;
+		case FSL_DDR_BANK_INTERLEAVING:
+			puts("bank");
+			break;
+		case FSL_DDR_SUPERBANK_INTERLEAVING:
+			puts("super-bank");
+			break;
+		default:
+			puts("invalid");
+			break;
+		}
+	}
+#endif
+
+	if ((sdram_cfg >> 8) & 0x7f) {
+		puts("\n");
+		puts("       DDR Chip-Select Interleaving Mode: ");
+		switch(sdram_cfg >> 8 & 0x7f) {
+		case FSL_DDR_CS0_CS1_CS2_CS3:
+			puts("CS0+CS1+CS2+CS3");
+			break;
+		case FSL_DDR_CS0_CS1:
+			puts("CS0+CS1");
+			break;
+		case FSL_DDR_CS2_CS3:
+			puts("CS2+CS3");
+			break;
+		case FSL_DDR_CS0_CS1_AND_CS2_CS3:
+			puts("CS0+CS1 and CS2+CS3");
+			break;
+		default:
+			puts("invalid");
+			break;
+		}
+	}
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/fdt.c b/arch/powerpc/cpu/mpc8xxx/fdt.c
new file mode 100644
index 0000000..ccefaf5
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/fdt.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * This file is derived from arch/powerpc/cpu/mpc85xx/cpu.c and
+ * arch/powerpc/cpu/mpc86xx/cpu.c. Basically this file contains
+ * cpu specific common code for 85xx/86xx processors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+
+void ft_fixup_num_cores(void *blob) {
+	int off, num_cores, del_cores;
+
+	del_cores = 0;
+	num_cores = cpu_numcores();
+
+	off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+	while (off != -FDT_ERR_NOTFOUND) {
+		u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
+
+		/* if we find a cpu node outside of what we expect delete it
+		 * and reset the offset back to the start since we can't
+		 * trust the offsets anymore
+		 */
+		if (*reg > num_cores-1) {
+			fdt_del_node(blob, off);
+			del_cores++;
+			off = -1;
+		}
+		off = fdt_node_offset_by_prop_value(blob, off,
+				"device_type", "cpu", 4);
+	}
+	debug ("%x core system found\n", num_cores);
+	debug ("deleted %d extra core entry entries from device tree\n",
+								del_cores);
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/pci_cfg.c b/arch/powerpc/cpu/mpc8xxx/pci_cfg.c
new file mode 100644
index 0000000..9b7181d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/pci_cfg.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_law.h>
+#include <pci.h>
+
+struct pci_info {
+	u32	cfg;
+};
+
+/* The cfg field is a bit mask in which each bit represents the value of
+ * cfg_IO_ports[] signal and the bit is set if the interface would be
+ * enabled based on the value of cfg_IO_ports[] signal
+ *
+ * On MPC86xx/PQ3 based systems:
+ *   we extract cfg_IO_ports from GUTS register PORDEVSR
+ *
+ * cfg_IO_ports only exist on systems w/PCIe (we set cfg 0 for systems
+ * without PCIe)
+ */
+
+#if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8560)
+static struct pci_info pci_config_info[] =
+{
+	[LAW_TRGT_IF_PCI] = {
+		.cfg =   0,
+	},
+};
+#elif defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
+static struct pci_info pci_config_info[] =
+{
+	[LAW_TRGT_IF_PCI] = {
+		.cfg =   0,
+	},
+};
+#elif defined(CONFIG_MPC8536)
+static struct pci_info pci_config_info[] =
+{
+	[LAW_TRGT_IF_PCI] = {
+		.cfg =   0,
+	},
+	[LAW_TRGT_IF_PCIE_1] = {
+		.cfg =   (1 << 2) | (1 << 3) | (1 << 5) | (1 << 7),
+	},
+	[LAW_TRGT_IF_PCIE_2] = {
+		.cfg =   (1 << 5) | (1 << 7),
+	},
+	[LAW_TRGT_IF_PCIE_3] = {
+		.cfg =   (1 << 7),
+	},
+};
+#elif defined(CONFIG_MPC8544)
+static struct pci_info pci_config_info[] =
+{
+	[LAW_TRGT_IF_PCI] = {
+		.cfg =   0,
+	},
+	[LAW_TRGT_IF_PCIE_1] = {
+		.cfg =   (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) |
+			 (1 << 6) | (1 << 7),
+	},
+	[LAW_TRGT_IF_PCIE_2] = {
+		.cfg =   (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7),
+	},
+	[LAW_TRGT_IF_PCIE_3] = {
+		.cfg =   (1 << 6) | (1 << 7),
+	},
+};
+#elif defined(CONFIG_MPC8548)
+static struct pci_info pci_config_info[] =
+{
+	[LAW_TRGT_IF_PCI_1] = {
+		.cfg =   0,
+	},
+	[LAW_TRGT_IF_PCI_2] = {
+		.cfg =   0,
+	},
+	/* PCI_2 is always host and we dont use iosel to determine enable/disable */
+	[LAW_TRGT_IF_PCIE_1] = {
+		.cfg =   (1 << 3) | (1 << 4) | (1 << 7),
+	},
+};
+#elif defined(CONFIG_MPC8568)
+static struct pci_info pci_config_info[] =
+{
+	[LAW_TRGT_IF_PCI] = {
+		.cfg =   0,
+	},
+	[LAW_TRGT_IF_PCIE_1] = {
+		.cfg =   (1 << 3) | (1 << 4) | (1 << 7),
+	},
+};
+#elif defined(CONFIG_MPC8569)
+static struct pci_info pci_config_info[] =
+{
+	[LAW_TRGT_IF_PCIE_1] = {
+		.cfg =   (1 << 0) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) |
+			 (1 << 8) | (1 << 0xc) | (1 << 0xf),
+	},
+};
+#elif defined(CONFIG_MPC8572)
+static struct pci_info pci_config_info[] =
+{
+	[LAW_TRGT_IF_PCIE_1] = {
+		.cfg =   (1 << 2) | (1 << 3) | (1 << 7) |
+			 (1 << 0xb) | (1 << 0xc) | (1 << 0xf),
+	},
+	[LAW_TRGT_IF_PCIE_2] = {
+		.cfg =   (1 << 3) | (1 << 7),
+	},
+	[LAW_TRGT_IF_PCIE_3] = {
+		.cfg =   (1 << 7),
+	},
+};
+#elif defined(CONFIG_MPC8610)
+static struct pci_info pci_config_info[] =
+{
+	[LAW_TRGT_IF_PCI_1] = {
+		.cfg =   0,
+	},
+	[LAW_TRGT_IF_PCIE_1] = {
+		.cfg =   (1 << 1) | (1 << 4),
+	},
+	[LAW_TRGT_IF_PCIE_2] = {
+		.cfg =   (1 << 0) | (1 << 4),
+	},
+};
+#elif defined(CONFIG_MPC8641)
+static struct pci_info pci_config_info[] =
+{
+	[LAW_TRGT_IF_PCIE_1] = {
+		.cfg =   (1 << 2) | (1 << 3) | (1 << 5) | (1 << 6) |
+			 (1 << 7) | (1 << 0xe) | (1 << 0xf),
+	},
+};
+#elif defined(CONFIG_P1011) || defined(CONFIG_P1020) || \
+      defined(CONFIG_P1012) || defined(CONFIG_P1021)
+static struct pci_info pci_config_info[] =
+{
+	[LAW_TRGT_IF_PCIE_1] = {
+		.cfg =   (1 << 0) | (1 << 6) | (1 << 0xe) | (1 << 0xf),
+	},
+	[LAW_TRGT_IF_PCIE_2] = {
+		.cfg =   (1 << 0xe),
+	},
+};
+#elif defined(CONFIG_P1013) || defined(CONFIG_P1022)
+static struct pci_info pci_config_info[] =
+{
+	[LAW_TRGT_IF_PCIE_1] = {
+		.cfg =   (1 << 6) | (1 << 7) | (1 << 9) | (1 << 0xa) |
+			 (1 << 0xb) | (1 << 0xd) | (1 << 0xe) |
+			 (1 << 0xf) | (1 << 0x15) | (1 << 0x16) |
+			 (1 << 0x17) | (1 << 0x18) | (1 << 0x19) |
+			 (1 << 0x1a) | (1 << 0x1b) | (1 << 0x1c) |
+			 (1 << 0x1d) | (1 << 0x1e) | (1 << 0x1f),
+	},
+	[LAW_TRGT_IF_PCIE_2] = {
+		.cfg =   (1 << 0) | (1 << 1) | (1 << 6) | (1 << 7) |
+			 (1 << 9) | (1 << 0xa) | (1 << 0xb) | (1 << 0xd) |
+			 (1 << 0x15) | (1 << 0x16) | (1 << 0x17) |
+			 (1 << 0x18) | (1 << 0x1c),
+	},
+	[LAW_TRGT_IF_PCIE_3] = {
+		.cfg =   (1 << 6) | (1 << 7) | (1 << 9) | (1 << 0xd) |
+			 (1 << 0x15) | (1 << 0x16) | (1 << 0x17) | (1 << 0x18) |
+			 (1 << 0x19) | (1 << 0x1a) | (1 << 0x1b),
+	},
+};
+#elif defined(CONFIG_P2010) || defined(CONFIG_P2020)
+static struct pci_info pci_config_info[] =
+{
+	[LAW_TRGT_IF_PCIE_1] = {
+		.cfg =   (1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) |
+			 (1 << 0xd) | (1 << 0xe) | (1 << 0xf),
+	},
+	[LAW_TRGT_IF_PCIE_2] = {
+		.cfg =   (1 << 2) | (1 << 0xe),
+	},
+	[LAW_TRGT_IF_PCIE_3] = {
+		.cfg =   (1 << 2) | (1 << 4),
+	},
+};
+#elif defined(CONFIG_FSL_CORENET)
+#else
+#error Need to define pci_config_info for processor
+#endif
+
+#ifndef CONFIG_FSL_CORENET
+int is_fsl_pci_cfg(enum law_trgt_if trgt, u32 io_sel)
+{
+	return ((1 << io_sel) & pci_config_info[trgt].cfg);
+}
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/40x_spd_sdram.c b/arch/powerpc/cpu/ppc4xx/40x_spd_sdram.c
new file mode 100644
index 0000000..f65cd88
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/40x_spd_sdram.c
@@ -0,0 +1,464 @@
+/*
+ * arch/powerpc/cpu/ppc4xx/40x_spd_sdram.c
+ * This SPD SDRAM detection code supports IBM/AMCC PPC44x cpu with a
+ * SDRAM controller. Those are all current 405 PPC's.
+ *
+ * (C) Copyright 2001
+ * Bill Hunter, Wave 7 Optics, williamhunter@attbi.com
+ *
+ * Based on code by:
+ *
+ * Kenneth Johansson ,Ericsson AB.
+ * kenneth.johansson@etx.ericsson.se
+ *
+ * hacked up by bill hunter. fixed so we could run before
+ * serial_init and console_init. previous version avoided this by
+ * running out of cache memory during serial/console init, then running
+ * this code later.
+ *
+ * (C) Copyright 2002
+ * Jun Gu, Artesyn Technology, jung@artesyncp.com
+ * Support for AMCC 440 based on OpenBIOS draminit.c from IBM.
+ *
+ * (C) Copyright 2005
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <i2c.h>
+#include <ppc4xx.h>
+
+#if defined(CONFIG_SPD_EEPROM) && !defined(CONFIG_440)
+
+/*
+ * Set default values
+ */
+#ifndef CONFIG_SYS_I2C_SPEED
+#define CONFIG_SYS_I2C_SPEED	50000
+#endif
+
+#define ONE_BILLION	1000000000
+
+#define	 SDRAM0_CFG_DCE		0x80000000
+#define	 SDRAM0_CFG_SRE		0x40000000
+#define	 SDRAM0_CFG_PME		0x20000000
+#define	 SDRAM0_CFG_MEMCHK	0x10000000
+#define	 SDRAM0_CFG_REGEN	0x08000000
+#define	 SDRAM0_CFG_ECCDD	0x00400000
+#define	 SDRAM0_CFG_EMDULR	0x00200000
+#define	 SDRAM0_CFG_DRW_SHIFT	(31-6)
+#define	 SDRAM0_CFG_BRPF_SHIFT	(31-8)
+
+#define	 SDRAM0_TR_CASL_SHIFT	(31-8)
+#define	 SDRAM0_TR_PTA_SHIFT	(31-13)
+#define	 SDRAM0_TR_CTP_SHIFT	(31-15)
+#define	 SDRAM0_TR_LDF_SHIFT	(31-17)
+#define	 SDRAM0_TR_RFTA_SHIFT	(31-29)
+#define	 SDRAM0_TR_RCD_SHIFT	(31-31)
+
+#define	 SDRAM0_RTR_SHIFT	(31-15)
+#define	 SDRAM0_ECCCFG_SHIFT	(31-11)
+
+/* SDRAM0_CFG enable macro  */
+#define SDRAM0_CFG_BRPF(x) ( ( x & 0x3)<< SDRAM0_CFG_BRPF_SHIFT )
+
+#define SDRAM0_BXCR_SZ_MASK	0x000e0000
+#define SDRAM0_BXCR_AM_MASK	0x0000e000
+
+#define SDRAM0_BXCR_SZ_SHIFT	(31-14)
+#define SDRAM0_BXCR_AM_SHIFT	(31-18)
+
+#define SDRAM0_BXCR_SZ(x)	( (( x << SDRAM0_BXCR_SZ_SHIFT) & SDRAM0_BXCR_SZ_MASK) )
+#define SDRAM0_BXCR_AM(x)	( (( x << SDRAM0_BXCR_AM_SHIFT) & SDRAM0_BXCR_AM_MASK) )
+
+#ifdef CONFIG_SPDDRAM_SILENT
+# define SPD_ERR(x) do { return 0; } while (0)
+#else
+# define SPD_ERR(x) do { printf(x); return(0); } while (0)
+#endif
+
+#define sdram_HZ_to_ns(hertz) (1000000000/(hertz))
+
+/* function prototypes */
+int spd_read(uint addr);
+
+
+/*
+ * This function is reading data from the DIMM module EEPROM over the SPD bus
+ * and uses that to program the sdram controller.
+ *
+ * This works on boards that has the same schematics that the AMCC walnut has.
+ *
+ * Input: null for default I2C spd functions or a pointer to a custom function
+ * returning spd_data.
+ */
+
+long int spd_sdram(int(read_spd)(uint addr))
+{
+	int tmp,row,col;
+	int total_size,bank_size,bank_code;
+	int ecc_on;
+	int mode;
+	int bank_cnt;
+
+	int sdram0_pmit=0x07c00000;
+#ifndef CONFIG_405EP /* not on PPC405EP */
+	int sdram0_besr0 = -1;
+	int sdram0_besr1 = -1;
+	int sdram0_eccesr = -1;
+#endif
+	int sdram0_ecccfg;
+
+	int sdram0_rtr=0;
+	int sdram0_tr=0;
+
+	int sdram0_b0cr;
+	int sdram0_b1cr;
+	int sdram0_b2cr;
+	int sdram0_b3cr;
+
+	int sdram0_cfg=0;
+
+	int t_rp;
+	int t_rcd;
+	int t_ras;
+	int t_rc;
+	int min_cas;
+
+	PPC4xx_SYS_INFO sys_info;
+	unsigned long bus_period_x_10;
+
+	/*
+	 * get the board info
+	 */
+	get_sys_info(&sys_info);
+	bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10);
+
+	if (read_spd == 0){
+		read_spd=spd_read;
+		/*
+		 * Make sure I2C controller is initialized
+		 * before continuing.
+		 */
+		i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+	}
+
+	/* Make shure we are using SDRAM */
+	if (read_spd(2) != 0x04) {
+		SPD_ERR("SDRAM - non SDRAM memory module found\n");
+	}
+
+	/* ------------------------------------------------------------------
+	 * configure memory timing register
+	 *
+	 * data from DIMM:
+	 * 27	IN Row Precharge Time ( t RP)
+	 * 29	MIN RAS to CAS Delay ( t RCD)
+	 * 127	 Component and Clock Detail ,clk0-clk3, junction temp, CAS
+	 * -------------------------------------------------------------------*/
+
+	/*
+	 * first figure out which cas latency mode to use
+	 * use the min supported mode
+	 */
+
+	tmp = read_spd(127) & 0x6;
+	if (tmp == 0x02) {		/* only cas = 2 supported */
+		min_cas = 2;
+/*		t_ck = read_spd(9); */
+/*		t_ac = read_spd(10); */
+	} else if (tmp == 0x04) {	/* only cas = 3 supported */
+		min_cas = 3;
+/*		t_ck = read_spd(9); */
+/*		t_ac = read_spd(10); */
+	} else if (tmp == 0x06) {	/* 2,3 supported, so use 2 */
+		min_cas = 2;
+/*		t_ck = read_spd(23); */
+/*		t_ac = read_spd(24); */
+	} else {
+		SPD_ERR("SDRAM - unsupported CAS latency \n");
+	}
+
+	/* get some timing values, t_rp,t_rcd,t_ras,t_rc
+	 */
+	t_rp = read_spd(27);
+	t_rcd = read_spd(29);
+	t_ras = read_spd(30);
+	t_rc = t_ras + t_rp;
+
+	/* The following timing calcs subtract 1 before deviding.
+	 * this has effect of using ceiling instead of floor rounding,
+	 * and also subtracting 1 to convert number to reg value
+	 */
+	/* set up CASL */
+	sdram0_tr = (min_cas - 1) << SDRAM0_TR_CASL_SHIFT;
+	/* set up PTA */
+	sdram0_tr |= ((((t_rp - 1) * 10)/bus_period_x_10) & 0x3) << SDRAM0_TR_PTA_SHIFT;
+	/* set up CTP */
+	tmp = (((t_rc - t_rcd - t_rp -1) * 10) / bus_period_x_10) & 0x3;
+	if (tmp < 1)
+		tmp = 1;
+	sdram0_tr |= tmp << SDRAM0_TR_CTP_SHIFT;
+	/* set LDF	= 2 cycles, reg value = 1 */
+	sdram0_tr |= 1 << SDRAM0_TR_LDF_SHIFT;
+	/* set RFTA = t_rfc/bus_period, use t_rfc = t_rc */
+	tmp = (((t_rc - 1) * 10) / bus_period_x_10) - 3;
+	if (tmp < 0)
+		tmp = 0;
+	if (tmp > 6)
+		tmp = 6;
+	sdram0_tr |= tmp << SDRAM0_TR_RFTA_SHIFT;
+	/* set RCD = t_rcd/bus_period*/
+	sdram0_tr |= ((((t_rcd - 1) * 10) / bus_period_x_10) &0x3) << SDRAM0_TR_RCD_SHIFT ;
+
+
+	/*------------------------------------------------------------------
+	 * configure RTR register
+	 * -------------------------------------------------------------------*/
+	row = read_spd(3);
+	col = read_spd(4);
+	tmp = read_spd(12) & 0x7f ; /* refresh type less self refresh bit */
+	switch (tmp) {
+	case 0x00:
+		tmp = 15625;
+		break;
+	case 0x01:
+		tmp = 15625 / 4;
+		break;
+	case 0x02:
+		tmp = 15625 / 2;
+		break;
+	case 0x03:
+		tmp = 15625 * 2;
+		break;
+	case 0x04:
+		tmp = 15625 * 4;
+		break;
+	case 0x05:
+		tmp = 15625 * 8;
+		break;
+	default:
+		SPD_ERR("SDRAM - Bad refresh period \n");
+	}
+	/* convert from nsec to bus cycles */
+	tmp = (tmp * 10) / bus_period_x_10;
+	sdram0_rtr = (tmp & 0x3ff8) <<	SDRAM0_RTR_SHIFT;
+
+	/*------------------------------------------------------------------
+	 * determine the number of banks used
+	 * -------------------------------------------------------------------*/
+	/* byte 7:6 is module data width */
+	if (read_spd(7) != 0)
+		SPD_ERR("SDRAM - unsupported module width\n");
+	tmp = read_spd(6);
+	if (tmp < 32)
+		SPD_ERR("SDRAM - unsupported module width\n");
+	else if (tmp < 64)
+		bank_cnt = 1;		/* one bank per sdram side */
+	else if (tmp < 73)
+		bank_cnt = 2;	/* need two banks per side */
+	else if (tmp < 161)
+		bank_cnt = 4;	/* need four banks per side */
+	else
+		SPD_ERR("SDRAM - unsupported module width\n");
+
+	/* byte 5 is the module row count (refered to as dimm "sides") */
+	tmp = read_spd(5);
+	if (tmp == 1)
+		;
+	else if (tmp==2)
+		bank_cnt *= 2;
+	else if (tmp==4)
+		bank_cnt *= 4;
+	else
+		bank_cnt = 8;		/* 8 is an error code */
+
+	if (bank_cnt > 4)	/* we only have 4 banks to work with */
+		SPD_ERR("SDRAM - unsupported module rows for this width\n");
+
+	/* now check for ECC ability of module. We only support ECC
+	 *   on 32 bit wide devices with 8 bit ECC.
+	 */
+	if ((read_spd(11)==2) && (read_spd(6)==40) && (read_spd(14)==8)) {
+		sdram0_ecccfg = 0xf << SDRAM0_ECCCFG_SHIFT;
+		ecc_on = 1;
+	} else {
+		sdram0_ecccfg = 0;
+		ecc_on = 0;
+	}
+
+	/*------------------------------------------------------------------
+	 * calculate total size
+	 * -------------------------------------------------------------------*/
+	/* calculate total size and do sanity check */
+	tmp = read_spd(31);
+	total_size = 1 << 22;	/* total_size = 4MB */
+	/* now multiply 4M by the smallest device row density */
+	/* note that we don't support asymetric rows */
+	while (((tmp & 0x0001) == 0) && (tmp != 0)) {
+		total_size = total_size << 1;
+		tmp = tmp >> 1;
+	}
+	total_size *= read_spd(5);	/* mult by module rows (dimm sides) */
+
+	/*------------------------------------------------------------------
+	 * map	rows * cols * banks to a mode
+	 * -------------------------------------------------------------------*/
+
+	switch (row) {
+	case 11:
+		switch (col) {
+		case 8:
+			mode=4; /* mode 5 */
+			break;
+		case 9:
+		case 10:
+			mode=0; /* mode 1 */
+			break;
+		default:
+			SPD_ERR("SDRAM - unsupported mode\n");
+		}
+		break;
+	case 12:
+		switch (col) {
+		case 8:
+			mode=3; /* mode 4 */
+			break;
+		case 9:
+		case 10:
+			mode=1; /* mode 2 */
+			break;
+		default:
+			SPD_ERR("SDRAM - unsupported mode\n");
+		}
+		break;
+	case 13:
+		switch (col) {
+		case 8:
+			mode=5; /* mode 6 */
+			break;
+		case 9:
+		case 10:
+			if (read_spd(17) == 2)
+				mode = 6; /* mode 7 */
+			else
+				mode = 2; /* mode 3 */
+			break;
+		case 11:
+			mode = 2; /* mode 3 */
+			break;
+		default:
+			SPD_ERR("SDRAM - unsupported mode\n");
+		}
+		break;
+	default:
+		SPD_ERR("SDRAM - unsupported mode\n");
+	}
+
+	/*------------------------------------------------------------------
+	 * using the calculated values, compute the bank
+	 * config register values.
+	 * -------------------------------------------------------------------*/
+	sdram0_b1cr = 0;
+	sdram0_b2cr = 0;
+	sdram0_b3cr = 0;
+
+	/* compute the size of each bank */
+	bank_size = total_size / bank_cnt;
+	/* convert bank size to bank size code for ppc4xx
+	   by takeing log2(bank_size) - 22 */
+	tmp = bank_size;		/* start with tmp = bank_size */
+	bank_code = 0;			/* and bank_code = 0 */
+	while (tmp > 1) {		/* this takes log2 of tmp */
+		bank_code++;		/* and stores result in bank_code */
+		tmp = tmp >> 1;
+	}				/* bank_code is now log2(bank_size) */
+	bank_code -= 22;		/* subtract 22 to get the code */
+
+	tmp = SDRAM0_BXCR_SZ(bank_code) | SDRAM0_BXCR_AM(mode) | 1;
+	sdram0_b0cr = (bank_size * 0) | tmp;
+#ifndef CONFIG_405EP /* not on PPC405EP */
+	if (bank_cnt > 1)
+		sdram0_b2cr = (bank_size * 1) | tmp;
+	if (bank_cnt > 2)
+		sdram0_b1cr = (bank_size * 2) | tmp;
+	if (bank_cnt > 3)
+		sdram0_b3cr = (bank_size * 3) | tmp;
+#else
+	/* PPC405EP chip only supports two SDRAM banks */
+	if (bank_cnt > 1)
+		sdram0_b1cr = (bank_size * 1) | tmp;
+	if (bank_cnt > 2)
+		total_size = 2 * bank_size;
+#endif
+
+	/*
+	 *   enable sdram controller DCE=1
+	 *  enable burst read prefetch to 32 bytes BRPF=2
+	 *  leave other functions off
+	 */
+
+	/*------------------------------------------------------------------
+	 * now that we've done our calculations, we are ready to
+	 * program all the registers.
+	 * -------------------------------------------------------------------*/
+
+	/* disable memcontroller so updates work */
+	mtsdram(SDRAM0_CFG, 0);
+
+#ifndef CONFIG_405EP /* not on PPC405EP */
+	mtsdram(SDRAM0_BESR0, sdram0_besr0);
+	mtsdram(SDRAM0_BESR1, sdram0_besr1);
+	mtsdram(SDRAM0_ECCCFG, sdram0_ecccfg);
+	mtsdram(SDRAM0_ECCESR, sdram0_eccesr);
+#endif
+	mtsdram(SDRAM0_RTR, sdram0_rtr);
+	mtsdram(SDRAM0_PMIT, sdram0_pmit);
+	mtsdram(SDRAM0_B0CR, sdram0_b0cr);
+	mtsdram(SDRAM0_B1CR, sdram0_b1cr);
+#ifndef CONFIG_405EP /* not on PPC405EP */
+	mtsdram(SDRAM0_B2CR, sdram0_b2cr);
+	mtsdram(SDRAM0_B3CR, sdram0_b3cr);
+#endif
+	mtsdram(SDRAM0_TR, sdram0_tr);
+
+	/* SDRAM have a power on delay,	 500 micro should do */
+	udelay(500);
+	sdram0_cfg = SDRAM0_CFG_DCE | SDRAM0_CFG_BRPF(1) | SDRAM0_CFG_ECCDD | SDRAM0_CFG_EMDULR;
+	if (ecc_on)
+		sdram0_cfg |= SDRAM0_CFG_MEMCHK;
+	mtsdram(SDRAM0_CFG, sdram0_cfg);
+
+	return (total_size);
+}
+
+int spd_read(uint addr)
+{
+	uchar data[2];
+
+	if (i2c_read(SPD_EEPROM_ADDRESS, addr, 1, data, 1) == 0)
+		return (int)data[0];
+	else
+		return 0;
+}
+
+#endif /* CONFIG_SPD_EEPROM */
diff --git a/arch/powerpc/cpu/ppc4xx/44x_spd_ddr.c b/arch/powerpc/cpu/ppc4xx/44x_spd_ddr.c
new file mode 100644
index 0000000..005315b
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/44x_spd_ddr.c
@@ -0,0 +1,1248 @@
+/*
+ * arch/powerpc/cpu/ppc4xx/44x_spd_ddr.c
+ * This SPD DDR detection code supports IBM/AMCC PPC44x cpu with a
+ * DDR controller. Those are 440GP/GX/EP/GR.
+ *
+ * (C) Copyright 2001
+ * Bill Hunter, Wave 7 Optics, williamhunter@attbi.com
+ *
+ * Based on code by:
+ *
+ * Kenneth Johansson ,Ericsson AB.
+ * kenneth.johansson@etx.ericsson.se
+ *
+ * hacked up by bill hunter. fixed so we could run before
+ * serial_init and console_init. previous version avoided this by
+ * running out of cache memory during serial/console init, then running
+ * this code later.
+ *
+ * (C) Copyright 2002
+ * Jun Gu, Artesyn Technology, jung@artesyncp.com
+ * Support for AMCC 440 based on OpenBIOS draminit.c from IBM.
+ *
+ * (C) Copyright 2005-2007
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#if 0
+#define DEBUG
+#endif
+
+#include <common.h>
+#include <asm/processor.h>
+#include <i2c.h>
+#include <ppc4xx.h>
+#include <asm/mmu.h>
+
+#include "ecc.h"
+
+#if defined(CONFIG_SPD_EEPROM) &&					\
+	(defined(CONFIG_440GP) || defined(CONFIG_440GX) ||		\
+	 defined(CONFIG_440EP) || defined(CONFIG_440GR))
+
+/*
+ * Set default values
+ */
+#ifndef CONFIG_SYS_I2C_SPEED
+#define CONFIG_SYS_I2C_SPEED	50000
+#endif
+
+#define ONE_BILLION	1000000000
+
+/*
+ * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed
+ */
+void __spd_ddr_init_hang (void)
+{
+	hang ();
+}
+void spd_ddr_init_hang (void) __attribute__((weak, alias("__spd_ddr_init_hang")));
+
+/*-----------------------------------------------------------------------------+
+  |  General Definition
+  +-----------------------------------------------------------------------------*/
+#define DEFAULT_SPD_ADDR1	0x53
+#define DEFAULT_SPD_ADDR2	0x52
+#define MAXBANKS		4		/* at most 4 dimm banks */
+#define MAX_SPD_BYTES		256
+#define NUMHALFCYCLES		4
+#define NUMMEMTESTS		8
+#define NUMMEMWORDS		8
+#define MAXBXCR			4
+#define TRUE			1
+#define FALSE			0
+
+/*
+ * This DDR2 setup code can dynamically setup the TLB entries for the DDR2 memory
+ * region. Right now the cache should still be disabled in U-Boot because of the
+ * EMAC driver, that need it's buffer descriptor to be located in non cached
+ * memory.
+ *
+ * If at some time this restriction doesn't apply anymore, just define
+ * CONFIG_4xx_DCACHE in the board config file and this code should setup
+ * everything correctly.
+ */
+#ifdef CONFIG_4xx_DCACHE
+#define MY_TLB_WORD2_I_ENABLE	0			/* enable caching on SDRAM */
+#else
+#define MY_TLB_WORD2_I_ENABLE	TLB_WORD2_I_ENABLE	/* disable caching on SDRAM */
+#endif
+
+/* bank_parms is used to sort the bank sizes by descending order */
+struct bank_param {
+	unsigned long cr;
+	unsigned long bank_size_bytes;
+};
+
+typedef struct bank_param BANKPARMS;
+
+#ifdef CONFIG_SYS_SIMULATE_SPD_EEPROM
+extern const unsigned char cfg_simulate_spd_eeprom[128];
+#endif
+
+static unsigned char spd_read(uchar chip, uint addr);
+static void get_spd_info(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long num_dimm_banks);
+static void check_mem_type(unsigned long *dimm_populated,
+			   unsigned char *iic0_dimm_addr,
+			   unsigned long num_dimm_banks);
+static void check_volt_type(unsigned long *dimm_populated,
+			    unsigned char *iic0_dimm_addr,
+			    unsigned long num_dimm_banks);
+static void program_cfg0(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long  num_dimm_banks);
+static void program_cfg1(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long num_dimm_banks);
+static void program_rtr(unsigned long *dimm_populated,
+			unsigned char *iic0_dimm_addr,
+			unsigned long num_dimm_banks);
+static void program_tr0(unsigned long *dimm_populated,
+			unsigned char *iic0_dimm_addr,
+			unsigned long num_dimm_banks);
+static void program_tr1(void);
+
+static unsigned long program_bxcr(unsigned long *dimm_populated,
+				  unsigned char *iic0_dimm_addr,
+				  unsigned long num_dimm_banks);
+
+/*
+ * This function is reading data from the DIMM module EEPROM over the SPD bus
+ * and uses that to program the sdram controller.
+ *
+ * This works on boards that has the same schematics that the AMCC walnut has.
+ *
+ * BUG: Don't handle ECC memory
+ * BUG: A few values in the TR register is currently hardcoded
+ */
+long int spd_sdram(void) {
+	unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS;
+	unsigned long dimm_populated[sizeof(iic0_dimm_addr)];
+	unsigned long total_size;
+	unsigned long cfg0;
+	unsigned long mcsts;
+	unsigned long num_dimm_banks;		    /* on board dimm banks */
+
+	num_dimm_banks = sizeof(iic0_dimm_addr);
+
+	/*
+	 * Make sure I2C controller is initialized
+	 * before continuing.
+	 */
+	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+	/*
+	 * Read the SPD information using I2C interface. Check to see if the
+	 * DIMM slots are populated.
+	 */
+	get_spd_info(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*
+	 * Check the memory type for the dimms plugged.
+	 */
+	check_mem_type(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*
+	 * Check the voltage type for the dimms plugged.
+	 */
+	check_volt_type(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
+	/*
+	 * Soft-reset SDRAM controller.
+	 */
+	mtsdr(SDR0_SRST, SDR0_SRST_DMC);
+	mtsdr(SDR0_SRST, 0x00000000);
+#endif
+
+	/*
+	 * program 440GP SDRAM controller options (SDRAM0_CFG0)
+	 */
+	program_cfg0(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*
+	 * program 440GP SDRAM controller options (SDRAM0_CFG1)
+	 */
+	program_cfg1(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*
+	 * program SDRAM refresh register (SDRAM0_RTR)
+	 */
+	program_rtr(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*
+	 * program SDRAM Timing Register 0 (SDRAM0_TR0)
+	 */
+	program_tr0(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*
+	 * program the BxCR registers to find out total sdram installed
+	 */
+	total_size = program_bxcr(dimm_populated, iic0_dimm_addr,
+				  num_dimm_banks);
+
+#ifdef CONFIG_PROG_SDRAM_TLB /* this define should eventually be removed */
+	/* and program tlb entries for this size (dynamic) */
+	program_tlb(0, 0, total_size, MY_TLB_WORD2_I_ENABLE);
+#endif
+
+	/*
+	 * program SDRAM Clock Timing Register (SDRAM0_CLKTR)
+	 */
+	mtsdram(SDRAM0_CLKTR, 0x40000000);
+
+	/*
+	 * delay to ensure 200 usec has elapsed
+	 */
+	udelay(400);
+
+	/*
+	 * enable the memory controller
+	 */
+	mfsdram(SDRAM0_CFG0, cfg0);
+	mtsdram(SDRAM0_CFG0, cfg0 | SDRAM_CFG0_DCEN);
+
+	/*
+	 * wait for SDRAM_CFG0_DC_EN to complete
+	 */
+	while (1) {
+		mfsdram(SDRAM0_MCSTS, mcsts);
+		if ((mcsts & SDRAM_MCSTS_MRSC) != 0)
+			break;
+	}
+
+	/*
+	 * program SDRAM Timing Register 1, adding some delays
+	 */
+	program_tr1();
+
+#ifdef CONFIG_DDR_ECC
+	/*
+	 * If ecc is enabled, initialize the parity bits.
+	 */
+	ecc_init(CONFIG_SYS_SDRAM_BASE, total_size);
+#endif
+
+	return total_size;
+}
+
+static unsigned char spd_read(uchar chip, uint addr)
+{
+	unsigned char data[2];
+
+#ifdef CONFIG_SYS_SIMULATE_SPD_EEPROM
+	if (chip == CONFIG_SYS_SIMULATE_SPD_EEPROM) {
+		/*
+		 * Onboard spd eeprom requested -> simulate values
+		 */
+		return cfg_simulate_spd_eeprom[addr];
+	}
+#endif /* CONFIG_SYS_SIMULATE_SPD_EEPROM */
+
+	if (i2c_probe(chip) == 0) {
+		if (i2c_read(chip, addr, 1, data, 1) == 0) {
+			return data[0];
+		}
+	}
+
+	return 0;
+}
+
+static void get_spd_info(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long dimm_found;
+	unsigned char num_of_bytes;
+	unsigned char total_size;
+
+	dimm_found = FALSE;
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		num_of_bytes = 0;
+		total_size = 0;
+
+		num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0);
+		total_size = spd_read(iic0_dimm_addr[dimm_num], 1);
+
+		if ((num_of_bytes != 0) && (total_size != 0)) {
+			dimm_populated[dimm_num] = TRUE;
+			dimm_found = TRUE;
+			debug("DIMM slot %lu: populated\n", dimm_num);
+		} else {
+			dimm_populated[dimm_num] = FALSE;
+			debug("DIMM slot %lu: Not populated\n", dimm_num);
+		}
+	}
+
+	if (dimm_found == FALSE) {
+		printf("ERROR - No memory installed. Install a DDR-SDRAM DIMM.\n\n");
+		spd_ddr_init_hang ();
+	}
+}
+
+static void check_mem_type(unsigned long *dimm_populated,
+			   unsigned char *iic0_dimm_addr,
+			   unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned char dimm_type;
+
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] == TRUE) {
+			dimm_type = spd_read(iic0_dimm_addr[dimm_num], 2);
+			switch (dimm_type) {
+			case 7:
+				debug("DIMM slot %lu: DDR SDRAM detected\n", dimm_num);
+				break;
+			default:
+				printf("ERROR: Unsupported DIMM detected in slot %lu.\n",
+				       dimm_num);
+				printf("Only DDR SDRAM DIMMs are supported.\n");
+				printf("Replace the DIMM module with a supported DIMM.\n\n");
+				spd_ddr_init_hang ();
+				break;
+			}
+		}
+	}
+}
+
+static void check_volt_type(unsigned long *dimm_populated,
+			    unsigned char *iic0_dimm_addr,
+			    unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long voltage_type;
+
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] == TRUE) {
+			voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8);
+			if (voltage_type != 0x04) {
+				printf("ERROR: DIMM %lu with unsupported voltage level.\n",
+				       dimm_num);
+				spd_ddr_init_hang ();
+			} else {
+				debug("DIMM %lu voltage level supported.\n", dimm_num);
+			}
+			break;
+		}
+	}
+}
+
+static void program_cfg0(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long cfg0;
+	unsigned long ecc_enabled;
+	unsigned char ecc;
+	unsigned char attributes;
+	unsigned long data_width;
+	unsigned long dimm_32bit;
+	unsigned long dimm_64bit;
+
+	/*
+	 * get Memory Controller Options 0 data
+	 */
+	mfsdram(SDRAM0_CFG0, cfg0);
+
+	/*
+	 * clear bits
+	 */
+	cfg0 &= ~(SDRAM_CFG0_DCEN | SDRAM_CFG0_MCHK_MASK |
+		  SDRAM_CFG0_RDEN | SDRAM_CFG0_PMUD |
+		  SDRAM_CFG0_DMWD_MASK |
+		  SDRAM_CFG0_UIOS_MASK | SDRAM_CFG0_PDP);
+
+
+	/*
+	 * FIXME: assume the DDR SDRAMs in both banks are the same
+	 */
+	ecc_enabled = TRUE;
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] == TRUE) {
+			ecc = spd_read(iic0_dimm_addr[dimm_num], 11);
+			if (ecc != 0x02) {
+				ecc_enabled = FALSE;
+			}
+
+			/*
+			 * program Registered DIMM Enable
+			 */
+			attributes = spd_read(iic0_dimm_addr[dimm_num], 21);
+			if ((attributes & 0x02) != 0x00) {
+				cfg0 |= SDRAM_CFG0_RDEN;
+			}
+
+			/*
+			 * program DDR SDRAM Data Width
+			 */
+			data_width =
+				(unsigned long)spd_read(iic0_dimm_addr[dimm_num],6) +
+				(((unsigned long)spd_read(iic0_dimm_addr[dimm_num],7)) << 8);
+			if (data_width == 64 || data_width == 72) {
+				dimm_64bit = TRUE;
+				cfg0 |= SDRAM_CFG0_DMWD_64;
+			} else if (data_width == 32 || data_width == 40) {
+				dimm_32bit = TRUE;
+				cfg0 |= SDRAM_CFG0_DMWD_32;
+			} else {
+				printf("WARNING: DIMM with datawidth of %lu bits.\n",
+				       data_width);
+				printf("Only DIMMs with 32 or 64 bit datawidths supported.\n");
+				spd_ddr_init_hang ();
+			}
+			break;
+		}
+	}
+
+	/*
+	 * program Memory Data Error Checking
+	 */
+	if (ecc_enabled == TRUE) {
+		cfg0 |= SDRAM_CFG0_MCHK_GEN;
+	} else {
+		cfg0 |= SDRAM_CFG0_MCHK_NON;
+	}
+
+	/*
+	 * program Page Management Unit (0 == enabled)
+	 */
+	cfg0 &= ~SDRAM_CFG0_PMUD;
+
+	/*
+	 * program Memory Controller Options 0
+	 * Note: DCEN must be enabled after all DDR SDRAM controller
+	 * configuration registers get initialized.
+	 */
+	mtsdram(SDRAM0_CFG0, cfg0);
+}
+
+static void program_cfg1(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long num_dimm_banks)
+{
+	unsigned long cfg1;
+	mfsdram(SDRAM0_CFG1, cfg1);
+
+	/*
+	 * Self-refresh exit, disable PM
+	 */
+	cfg1 &= ~(SDRAM_CFG1_SRE | SDRAM_CFG1_PMEN);
+
+	/*
+	 * program Memory Controller Options 1
+	 */
+	mtsdram(SDRAM0_CFG1, cfg1);
+}
+
+static void program_rtr(unsigned long *dimm_populated,
+			unsigned char *iic0_dimm_addr,
+			unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long bus_period_x_10;
+	unsigned long refresh_rate = 0;
+	unsigned char refresh_rate_type;
+	unsigned long refresh_interval;
+	unsigned long sdram_rtr;
+	PPC4xx_SYS_INFO sys_info;
+
+	/*
+	 * get the board info
+	 */
+	get_sys_info(&sys_info);
+	bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10);
+
+	for (dimm_num = 0;  dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] == TRUE) {
+			refresh_rate_type = 0x7F & spd_read(iic0_dimm_addr[dimm_num], 12);
+			switch (refresh_rate_type) {
+			case 0x00:
+				refresh_rate = 15625;
+				break;
+			case 0x01:
+				refresh_rate = 15625/4;
+				break;
+			case 0x02:
+				refresh_rate = 15625/2;
+				break;
+			case 0x03:
+				refresh_rate = 15626*2;
+				break;
+			case 0x04:
+				refresh_rate = 15625*4;
+				break;
+			case 0x05:
+				refresh_rate = 15625*8;
+				break;
+			default:
+				printf("ERROR: DIMM %lu, unsupported refresh rate/type.\n",
+				       dimm_num);
+				printf("Replace the DIMM module with a supported DIMM.\n");
+				break;
+			}
+
+			break;
+		}
+	}
+
+	refresh_interval = refresh_rate * 10 / bus_period_x_10;
+	sdram_rtr = (refresh_interval & 0x3ff8) <<  16;
+
+	/*
+	 * program Refresh Timer Register (SDRAM0_RTR)
+	 */
+	mtsdram(SDRAM0_RTR, sdram_rtr);
+}
+
+static void program_tr0(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long tr0;
+	unsigned char wcsbc;
+	unsigned char t_rp_ns;
+	unsigned char t_rcd_ns;
+	unsigned char t_ras_ns;
+	unsigned long t_rp_clk;
+	unsigned long t_ras_rcd_clk;
+	unsigned long t_rcd_clk;
+	unsigned long t_rfc_clk;
+	unsigned long plb_check;
+	unsigned char cas_bit;
+	unsigned long cas_index;
+	unsigned char cas_2_0_available;
+	unsigned char cas_2_5_available;
+	unsigned char cas_3_0_available;
+	unsigned long cycle_time_ns_x_10[3];
+	unsigned long tcyc_3_0_ns_x_10;
+	unsigned long tcyc_2_5_ns_x_10;
+	unsigned long tcyc_2_0_ns_x_10;
+	unsigned long tcyc_reg;
+	unsigned long bus_period_x_10;
+	PPC4xx_SYS_INFO sys_info;
+	unsigned long residue;
+
+	/*
+	 * get the board info
+	 */
+	get_sys_info(&sys_info);
+	bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10);
+
+	/*
+	 * get SDRAM Timing Register 0 (SDRAM_TR0) and clear bits
+	 */
+	mfsdram(SDRAM0_TR0, tr0);
+	tr0 &= ~(SDRAM_TR0_SDWR_MASK | SDRAM_TR0_SDWD_MASK |
+		 SDRAM_TR0_SDCL_MASK | SDRAM_TR0_SDPA_MASK |
+		 SDRAM_TR0_SDCP_MASK | SDRAM_TR0_SDLD_MASK |
+		 SDRAM_TR0_SDRA_MASK | SDRAM_TR0_SDRD_MASK);
+
+	/*
+	 * initialization
+	 */
+	wcsbc = 0;
+	t_rp_ns = 0;
+	t_rcd_ns = 0;
+	t_ras_ns = 0;
+	cas_2_0_available = TRUE;
+	cas_2_5_available = TRUE;
+	cas_3_0_available = TRUE;
+	tcyc_2_0_ns_x_10 = 0;
+	tcyc_2_5_ns_x_10 = 0;
+	tcyc_3_0_ns_x_10 = 0;
+
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] == TRUE) {
+			wcsbc = spd_read(iic0_dimm_addr[dimm_num], 15);
+			t_rp_ns	 = spd_read(iic0_dimm_addr[dimm_num], 27) >> 2;
+			t_rcd_ns = spd_read(iic0_dimm_addr[dimm_num], 29) >> 2;
+			t_ras_ns = spd_read(iic0_dimm_addr[dimm_num], 30);
+			cas_bit = spd_read(iic0_dimm_addr[dimm_num], 18);
+
+			for (cas_index = 0; cas_index < 3; cas_index++) {
+				switch (cas_index) {
+				case 0:
+					tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9);
+					break;
+				case 1:
+					tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 23);
+					break;
+				default:
+					tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 25);
+					break;
+				}
+
+				if ((tcyc_reg & 0x0F) >= 10) {
+					printf("ERROR: Tcyc incorrect for DIMM in slot %lu\n",
+					       dimm_num);
+					spd_ddr_init_hang ();
+				}
+
+				cycle_time_ns_x_10[cas_index] =
+					(((tcyc_reg & 0xF0) >> 4) * 10) + (tcyc_reg & 0x0F);
+			}
+
+			cas_index = 0;
+
+			if ((cas_bit & 0x80) != 0) {
+				cas_index += 3;
+			} else if ((cas_bit & 0x40) != 0) {
+				cas_index += 2;
+			} else if ((cas_bit & 0x20) != 0) {
+				cas_index += 1;
+			}
+
+			if (((cas_bit & 0x10) != 0) && (cas_index < 3)) {
+				tcyc_3_0_ns_x_10 = cycle_time_ns_x_10[cas_index];
+				cas_index++;
+			} else {
+				if (cas_index != 0) {
+					cas_index++;
+				}
+				cas_3_0_available = FALSE;
+			}
+
+			if (((cas_bit & 0x08) != 0) || (cas_index < 3)) {
+				tcyc_2_5_ns_x_10 = cycle_time_ns_x_10[cas_index];
+				cas_index++;
+			} else {
+				if (cas_index != 0) {
+					cas_index++;
+				}
+				cas_2_5_available = FALSE;
+			}
+
+			if (((cas_bit & 0x04) != 0) || (cas_index < 3)) {
+				tcyc_2_0_ns_x_10 = cycle_time_ns_x_10[cas_index];
+				cas_index++;
+			} else {
+				if (cas_index != 0) {
+					cas_index++;
+				}
+				cas_2_0_available = FALSE;
+			}
+
+			break;
+		}
+	}
+
+	/*
+	 * Program SD_WR and SD_WCSBC fields
+	 */
+	tr0 |= SDRAM_TR0_SDWR_2_CLK;		    /* Write Recovery: 2 CLK */
+	switch (wcsbc) {
+	case 0:
+		tr0 |= SDRAM_TR0_SDWD_0_CLK;
+		break;
+	default:
+		tr0 |= SDRAM_TR0_SDWD_1_CLK;
+		break;
+	}
+
+	/*
+	 * Program SD_CASL field
+	 */
+	if ((cas_2_0_available == TRUE) &&
+	    (bus_period_x_10 >= tcyc_2_0_ns_x_10)) {
+		tr0 |= SDRAM_TR0_SDCL_2_0_CLK;
+	} else if ((cas_2_5_available == TRUE) &&
+		 (bus_period_x_10 >= tcyc_2_5_ns_x_10)) {
+		tr0 |= SDRAM_TR0_SDCL_2_5_CLK;
+	} else if ((cas_3_0_available == TRUE) &&
+		 (bus_period_x_10 >= tcyc_3_0_ns_x_10)) {
+		tr0 |= SDRAM_TR0_SDCL_3_0_CLK;
+	} else {
+		printf("ERROR: No supported CAS latency with the installed DIMMs.\n");
+		printf("Only CAS latencies of 2.0, 2.5, and 3.0 are supported.\n");
+		printf("Make sure the PLB speed is within the supported range.\n");
+		spd_ddr_init_hang ();
+	}
+
+	/*
+	 * Calculate Trp in clock cycles and round up if necessary
+	 * Program SD_PTA field
+	 */
+	t_rp_clk = sys_info.freqPLB * t_rp_ns / ONE_BILLION;
+	plb_check = ONE_BILLION * t_rp_clk / t_rp_ns;
+	if (sys_info.freqPLB != plb_check) {
+		t_rp_clk++;
+	}
+	switch ((unsigned long)t_rp_clk) {
+	case 0:
+	case 1:
+	case 2:
+		tr0 |= SDRAM_TR0_SDPA_2_CLK;
+		break;
+	case 3:
+		tr0 |= SDRAM_TR0_SDPA_3_CLK;
+		break;
+	default:
+		tr0 |= SDRAM_TR0_SDPA_4_CLK;
+		break;
+	}
+
+	/*
+	 * Program SD_CTP field
+	 */
+	t_ras_rcd_clk = sys_info.freqPLB * (t_ras_ns - t_rcd_ns) / ONE_BILLION;
+	plb_check = ONE_BILLION * t_ras_rcd_clk / (t_ras_ns - t_rcd_ns);
+	if (sys_info.freqPLB != plb_check) {
+		t_ras_rcd_clk++;
+	}
+	switch (t_ras_rcd_clk) {
+	case 0:
+	case 1:
+	case 2:
+		tr0 |= SDRAM_TR0_SDCP_2_CLK;
+		break;
+	case 3:
+		tr0 |= SDRAM_TR0_SDCP_3_CLK;
+		break;
+	case 4:
+		tr0 |= SDRAM_TR0_SDCP_4_CLK;
+		break;
+	default:
+		tr0 |= SDRAM_TR0_SDCP_5_CLK;
+		break;
+	}
+
+	/*
+	 * Program SD_LDF field
+	 */
+	tr0 |= SDRAM_TR0_SDLD_2_CLK;
+
+	/*
+	 * Program SD_RFTA field
+	 * FIXME tRFC hardcoded as 75 nanoseconds
+	 */
+	t_rfc_clk = sys_info.freqPLB / (ONE_BILLION / 75);
+	residue = sys_info.freqPLB % (ONE_BILLION / 75);
+	if (residue >= (ONE_BILLION / 150)) {
+		t_rfc_clk++;
+	}
+	switch (t_rfc_clk) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+		tr0 |= SDRAM_TR0_SDRA_6_CLK;
+		break;
+	case 7:
+		tr0 |= SDRAM_TR0_SDRA_7_CLK;
+		break;
+	case 8:
+		tr0 |= SDRAM_TR0_SDRA_8_CLK;
+		break;
+	case 9:
+		tr0 |= SDRAM_TR0_SDRA_9_CLK;
+		break;
+	case 10:
+		tr0 |= SDRAM_TR0_SDRA_10_CLK;
+		break;
+	case 11:
+		tr0 |= SDRAM_TR0_SDRA_11_CLK;
+		break;
+	case 12:
+		tr0 |= SDRAM_TR0_SDRA_12_CLK;
+		break;
+	default:
+		tr0 |= SDRAM_TR0_SDRA_13_CLK;
+		break;
+	}
+
+	/*
+	 * Program SD_RCD field
+	 */
+	t_rcd_clk = sys_info.freqPLB * t_rcd_ns / ONE_BILLION;
+	plb_check = ONE_BILLION * t_rcd_clk / t_rcd_ns;
+	if (sys_info.freqPLB != plb_check) {
+		t_rcd_clk++;
+	}
+	switch (t_rcd_clk) {
+	case 0:
+	case 1:
+	case 2:
+		tr0 |= SDRAM_TR0_SDRD_2_CLK;
+		break;
+	case 3:
+		tr0 |= SDRAM_TR0_SDRD_3_CLK;
+		break;
+	default:
+		tr0 |= SDRAM_TR0_SDRD_4_CLK;
+		break;
+	}
+
+	debug("tr0: %x\n", tr0);
+	mtsdram(SDRAM0_TR0, tr0);
+}
+
+static int short_mem_test(void)
+{
+	unsigned long i, j;
+	unsigned long bxcr_num;
+	unsigned long *membase;
+	const unsigned long test[NUMMEMTESTS][NUMMEMWORDS] = {
+		{0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF},
+		{0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},
+		{0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+		 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555},
+		{0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+		 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA},
+		{0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+		 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A},
+		{0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+		 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5},
+		{0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+		 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
+		{0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+		 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55}};
+
+	for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) {
+		mtdcr(SDRAM0_CFGADDR, SDRAM0_B0CR + (bxcr_num << 2));
+		if ((mfdcr(SDRAM0_CFGDATA) & SDRAM_BXCR_SDBE) == SDRAM_BXCR_SDBE) {
+			/* Bank is enabled */
+			membase = (unsigned long*)
+				(mfdcr(SDRAM0_CFGDATA) & SDRAM_BXCR_SDBA_MASK);
+
+			/*
+			 * Run the short memory test
+			 */
+			for (i = 0; i < NUMMEMTESTS; i++) {
+				for (j = 0; j < NUMMEMWORDS; j++) {
+					/* printf("bank enabled base:%x\n", &membase[j]); */
+					membase[j] = test[i][j];
+					ppcDcbf((unsigned long)&(membase[j]));
+				}
+
+				for (j = 0; j < NUMMEMWORDS; j++) {
+					if (membase[j] != test[i][j]) {
+						ppcDcbf((unsigned long)&(membase[j]));
+						return 0;
+					}
+					ppcDcbf((unsigned long)&(membase[j]));
+				}
+
+				if (j < NUMMEMWORDS)
+					return 0;
+			}
+
+			/*
+			 * see if the rdclt value passed
+			 */
+			if (i < NUMMEMTESTS)
+				return 0;
+		}
+	}
+
+	return 1;
+}
+
+static void program_tr1(void)
+{
+	unsigned long tr0;
+	unsigned long tr1;
+	unsigned long cfg0;
+	unsigned long ecc_temp;
+	unsigned long dlycal;
+	unsigned long dly_val;
+	unsigned long k;
+	unsigned long max_pass_length;
+	unsigned long current_pass_length;
+	unsigned long current_fail_length;
+	unsigned long current_start;
+	unsigned long rdclt;
+	unsigned long rdclt_offset;
+	long max_start;
+	long max_end;
+	long rdclt_average;
+	unsigned char window_found;
+	unsigned char fail_found;
+	unsigned char pass_found;
+	PPC4xx_SYS_INFO sys_info;
+
+	/*
+	 * get the board info
+	 */
+	get_sys_info(&sys_info);
+
+	/*
+	 * get SDRAM Timing Register 0 (SDRAM_TR0) and clear bits
+	 */
+	mfsdram(SDRAM0_TR1, tr1);
+	tr1 &= ~(SDRAM_TR1_RDSS_MASK | SDRAM_TR1_RDSL_MASK |
+		 SDRAM_TR1_RDCD_MASK | SDRAM_TR1_RDCT_MASK);
+
+	mfsdram(SDRAM0_TR0, tr0);
+	if (((tr0 & SDRAM_TR0_SDCL_MASK) == SDRAM_TR0_SDCL_2_5_CLK) &&
+	    (sys_info.freqPLB > 100000000)) {
+		tr1 |= SDRAM_TR1_RDSS_TR2;
+		tr1 |= SDRAM_TR1_RDSL_STAGE3;
+		tr1 |= SDRAM_TR1_RDCD_RCD_1_2;
+	} else {
+		tr1 |= SDRAM_TR1_RDSS_TR1;
+		tr1 |= SDRAM_TR1_RDSL_STAGE2;
+		tr1 |= SDRAM_TR1_RDCD_RCD_0_0;
+	}
+
+	/*
+	 * save CFG0 ECC setting to a temporary variable and turn ECC off
+	 */
+	mfsdram(SDRAM0_CFG0, cfg0);
+	ecc_temp = cfg0 & SDRAM_CFG0_MCHK_MASK;
+	mtsdram(SDRAM0_CFG0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | SDRAM_CFG0_MCHK_NON);
+
+	/*
+	 * get the delay line calibration register value
+	 */
+	mfsdram(SDRAM0_DLYCAL, dlycal);
+	dly_val = SDRAM_DLYCAL_DLCV_DECODE(dlycal) << 2;
+
+	max_pass_length = 0;
+	max_start = 0;
+	max_end = 0;
+	current_pass_length = 0;
+	current_fail_length = 0;
+	current_start = 0;
+	rdclt_offset = 0;
+	window_found = FALSE;
+	fail_found = FALSE;
+	pass_found = FALSE;
+	debug("Starting memory test ");
+
+	for (k = 0; k < NUMHALFCYCLES; k++) {
+		for (rdclt = 0; rdclt < dly_val; rdclt++) {
+			/*
+			 * Set the timing reg for the test.
+			 */
+			mtsdram(SDRAM0_TR1, (tr1 | SDRAM_TR1_RDCT_ENCODE(rdclt)));
+
+			if (short_mem_test()) {
+				if (fail_found == TRUE) {
+					pass_found = TRUE;
+					if (current_pass_length == 0) {
+						current_start = rdclt_offset + rdclt;
+					}
+
+					current_fail_length = 0;
+					current_pass_length++;
+
+					if (current_pass_length > max_pass_length) {
+						max_pass_length = current_pass_length;
+						max_start = current_start;
+						max_end = rdclt_offset + rdclt;
+					}
+				}
+			} else {
+				current_pass_length = 0;
+				current_fail_length++;
+
+				if (current_fail_length >= (dly_val>>2)) {
+					if (fail_found == FALSE) {
+						fail_found = TRUE;
+					} else if (pass_found == TRUE) {
+						window_found = TRUE;
+						break;
+					}
+				}
+			}
+		}
+		debug(".");
+
+		if (window_found == TRUE) {
+			break;
+		}
+
+		tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK;
+		rdclt_offset += dly_val;
+	}
+	debug("\n");
+
+	/*
+	 * make sure we find the window
+	 */
+	if (window_found == FALSE) {
+		printf("ERROR: Cannot determine a common read delay.\n");
+		spd_ddr_init_hang ();
+	}
+
+	/*
+	 * restore the orignal ECC setting
+	 */
+	mtsdram(SDRAM0_CFG0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | ecc_temp);
+
+	/*
+	 * set the SDRAM TR1 RDCD value
+	 */
+	tr1 &= ~SDRAM_TR1_RDCD_MASK;
+	if ((tr0 & SDRAM_TR0_SDCL_MASK) == SDRAM_TR0_SDCL_2_5_CLK) {
+		tr1 |= SDRAM_TR1_RDCD_RCD_1_2;
+	} else {
+		tr1 |= SDRAM_TR1_RDCD_RCD_0_0;
+	}
+
+	/*
+	 * set the SDRAM TR1 RDCLT value
+	 */
+	tr1 &= ~SDRAM_TR1_RDCT_MASK;
+	while (max_end >= (dly_val << 1)) {
+		max_end -= (dly_val << 1);
+		max_start -= (dly_val << 1);
+	}
+
+	rdclt_average = ((max_start + max_end) >> 1);
+
+	if (rdclt_average < 0) {
+		rdclt_average = 0;
+	}
+
+	if (rdclt_average >= dly_val) {
+		rdclt_average -= dly_val;
+		tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK;
+	}
+	tr1 |= SDRAM_TR1_RDCT_ENCODE(rdclt_average);
+
+	debug("tr1: %x\n", tr1);
+
+	/*
+	 * program SDRAM Timing Register 1 TR1
+	 */
+	mtsdram(SDRAM0_TR1, tr1);
+}
+
+static unsigned long program_bxcr(unsigned long *dimm_populated,
+				  unsigned char *iic0_dimm_addr,
+				  unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long bank_base_addr;
+	unsigned long cr;
+	unsigned long i;
+	unsigned long j;
+	unsigned long temp;
+	unsigned char num_row_addr;
+	unsigned char num_col_addr;
+	unsigned char num_banks;
+	unsigned char bank_size_id;
+	unsigned long ctrl_bank_num[MAXBANKS];
+	unsigned long bx_cr_num;
+	unsigned long largest_size_index;
+	unsigned long largest_size;
+	unsigned long current_size_index;
+	BANKPARMS bank_parms[MAXBXCR];
+	unsigned long sorted_bank_num[MAXBXCR]; /* DDR Controller bank number table (sorted by size) */
+	unsigned long sorted_bank_size[MAXBXCR]; /* DDR Controller bank size table (sorted by size)*/
+
+	/*
+	 * Set the BxCR regs.  First, wipe out the bank config registers.
+	 */
+	for (bx_cr_num = 0; bx_cr_num < MAXBXCR; bx_cr_num++) {
+		mtdcr(SDRAM0_CFGADDR, SDRAM0_B0CR + (bx_cr_num << 2));
+		mtdcr(SDRAM0_CFGDATA, 0x00000000);
+		bank_parms[bx_cr_num].bank_size_bytes = 0;
+	}
+
+#ifdef CONFIG_BAMBOO
+	/*
+	 * This next section is hardware dependent and must be programmed
+	 * to match the hardware.  For bamboo, the following holds...
+	 * 1. SDRAM0_B0CR: Bank 0 of dimm 0 ctrl_bank_num : 0 (soldered onboard)
+	 * 2. SDRAM0_B1CR: Bank 0 of dimm 1 ctrl_bank_num : 1
+	 * 3. SDRAM0_B2CR: Bank 1 of dimm 1 ctrl_bank_num : 1
+	 * 4. SDRAM0_B3CR: Bank 0 of dimm 2 ctrl_bank_num : 3
+	 * ctrl_bank_num corresponds to the first usable DDR controller bank number by DIMM
+	 */
+	ctrl_bank_num[0] = 0;
+	ctrl_bank_num[1] = 1;
+	ctrl_bank_num[2] = 3;
+#else
+	/*
+	 * Ocotea, Ebony and the other IBM/AMCC eval boards have
+	 * 2 DIMM slots with each max 2 banks
+	 */
+	ctrl_bank_num[0] = 0;
+	ctrl_bank_num[1] = 2;
+#endif
+
+	/*
+	 * reset the bank_base address
+	 */
+	bank_base_addr = CONFIG_SYS_SDRAM_BASE;
+
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] == TRUE) {
+			num_row_addr = spd_read(iic0_dimm_addr[dimm_num], 3);
+			num_col_addr = spd_read(iic0_dimm_addr[dimm_num], 4);
+			num_banks    = spd_read(iic0_dimm_addr[dimm_num], 5);
+			bank_size_id = spd_read(iic0_dimm_addr[dimm_num], 31);
+			debug("DIMM%d: row=%d col=%d banks=%d\n", dimm_num,
+			      num_row_addr, num_col_addr, num_banks);
+
+			/*
+			 * Set the SDRAM0_BxCR regs
+			 */
+			cr = 0;
+			switch (bank_size_id) {
+			case 0x02:
+				cr |= SDRAM_BXCR_SDSZ_8;
+				break;
+			case 0x04:
+				cr |= SDRAM_BXCR_SDSZ_16;
+				break;
+			case 0x08:
+				cr |= SDRAM_BXCR_SDSZ_32;
+				break;
+			case 0x10:
+				cr |= SDRAM_BXCR_SDSZ_64;
+				break;
+			case 0x20:
+				cr |= SDRAM_BXCR_SDSZ_128;
+				break;
+			case 0x40:
+				cr |= SDRAM_BXCR_SDSZ_256;
+				break;
+			case 0x80:
+				cr |= SDRAM_BXCR_SDSZ_512;
+				break;
+			default:
+				printf("DDR-SDRAM: DIMM %lu BxCR configuration.\n",
+				       dimm_num);
+				printf("ERROR: Unsupported value for the banksize: %d.\n",
+				       bank_size_id);
+				printf("Replace the DIMM module with a supported DIMM.\n\n");
+				spd_ddr_init_hang ();
+			}
+
+			switch (num_col_addr) {
+			case 0x08:
+				cr |= SDRAM_BXCR_SDAM_1;
+				break;
+			case 0x09:
+				cr |= SDRAM_BXCR_SDAM_2;
+				break;
+			case 0x0A:
+				cr |= SDRAM_BXCR_SDAM_3;
+				break;
+			case 0x0B:
+				cr |= SDRAM_BXCR_SDAM_4;
+				break;
+			default:
+				printf("DDR-SDRAM: DIMM %lu BxCR configuration.\n",
+				       dimm_num);
+				printf("ERROR: Unsupported value for number of "
+				       "column addresses: %d.\n", num_col_addr);
+				printf("Replace the DIMM module with a supported DIMM.\n\n");
+				spd_ddr_init_hang ();
+			}
+
+			/*
+			 * enable the bank
+			 */
+			cr |= SDRAM_BXCR_SDBE;
+
+			for (i = 0; i < num_banks; i++) {
+				bank_parms[ctrl_bank_num[dimm_num]+i].bank_size_bytes =
+					(4 << 20) * bank_size_id;
+				bank_parms[ctrl_bank_num[dimm_num]+i].cr = cr;
+				debug("DIMM%d-bank %d (SDRAM0_B%dCR): bank_size_bytes=%d\n",
+				      dimm_num, i, ctrl_bank_num[dimm_num]+i,
+				      bank_parms[ctrl_bank_num[dimm_num]+i].bank_size_bytes);
+			}
+		}
+	}
+
+	/* Initialize sort tables */
+	for (i = 0; i < MAXBXCR; i++) {
+		sorted_bank_num[i] = i;
+		sorted_bank_size[i] = bank_parms[i].bank_size_bytes;
+	}
+
+	for (i = 0; i < MAXBXCR-1; i++) {
+		largest_size = sorted_bank_size[i];
+		largest_size_index = 255;
+
+		/* Find the largest remaining value */
+		for (j = i + 1; j < MAXBXCR; j++) {
+			if (sorted_bank_size[j] > largest_size) {
+				/* Save largest remaining value and its index */
+				largest_size = sorted_bank_size[j];
+				largest_size_index = j;
+			}
+		}
+
+		if (largest_size_index != 255) {
+			/* Swap the current and largest values */
+			current_size_index = sorted_bank_num[largest_size_index];
+			sorted_bank_size[largest_size_index] = sorted_bank_size[i];
+			sorted_bank_size[i] = largest_size;
+			sorted_bank_num[largest_size_index] = sorted_bank_num[i];
+			sorted_bank_num[i] = current_size_index;
+		}
+	}
+
+	/* Set the SDRAM0_BxCR regs thanks to sort tables */
+	for (bx_cr_num = 0, bank_base_addr = 0; bx_cr_num < MAXBXCR; bx_cr_num++) {
+		if (bank_parms[sorted_bank_num[bx_cr_num]].bank_size_bytes) {
+			mtdcr(SDRAM0_CFGADDR, SDRAM0_B0CR + (sorted_bank_num[bx_cr_num] << 2));
+			temp = mfdcr(SDRAM0_CFGDATA) & ~(SDRAM_BXCR_SDBA_MASK | SDRAM_BXCR_SDSZ_MASK |
+						  SDRAM_BXCR_SDAM_MASK | SDRAM_BXCR_SDBE);
+			temp = temp | (bank_base_addr & SDRAM_BXCR_SDBA_MASK) |
+				bank_parms[sorted_bank_num[bx_cr_num]].cr;
+			mtdcr(SDRAM0_CFGDATA, temp);
+			bank_base_addr += bank_parms[sorted_bank_num[bx_cr_num]].bank_size_bytes;
+			debug("SDRAM0_B%dCR=0x%08lx\n", sorted_bank_num[bx_cr_num], temp);
+		}
+	}
+
+	return(bank_base_addr);
+}
+#endif /* CONFIG_SPD_EEPROM */
diff --git a/arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c b/arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c
new file mode 100644
index 0000000..faddee9
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c
@@ -0,0 +1,3174 @@
+/*
+ * arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c
+ * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a
+ * DDR2 controller (non Denali Core). Those currently are:
+ *
+ * 405:		405EX(r)
+ * 440/460:	440SP/440SPe/460EX/460GT
+ *
+ * Copyright (c) 2008 Nuovation System Designs, LLC
+ *   Grant Erickson <gerickson@nuovations.com>
+
+ * (C) Copyright 2007-2009
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * COPYRIGHT   AMCC   CORPORATION 2004
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#if 0
+#define DEBUG
+#endif
+
+#include <common.h>
+#include <command.h>
+#include <ppc4xx.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/cache.h>
+
+#include "ecc.h"
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
+
+#define PPC4xx_IBM_DDR2_DUMP_REGISTER(mnemonic)				\
+	do {								\
+		u32 data;						\
+		mfsdram(SDRAM_##mnemonic, data);			\
+		printf("%20s[%02x] = 0x%08X\n",				\
+		       "SDRAM_" #mnemonic, SDRAM_##mnemonic, data);	\
+	} while (0)
+
+#define PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(mnemonic)			\
+	do {								\
+		u32 data;						\
+		data = mfdcr(SDRAM_##mnemonic);				\
+		printf("%20s[%02x] = 0x%08X\n",				\
+		       "SDRAM_" #mnemonic, SDRAM_##mnemonic, data);	\
+	} while (0)
+
+#if defined(CONFIG_440)
+/*
+ * This DDR2 setup code can dynamically setup the TLB entries for the DDR2
+ * memory region. Right now the cache should still be disabled in U-Boot
+ * because of the EMAC driver, that need its buffer descriptor to be located
+ * in non cached memory.
+ *
+ * If at some time this restriction doesn't apply anymore, just define
+ * CONFIG_4xx_DCACHE in the board config file and this code should setup
+ * everything correctly.
+ */
+#ifdef CONFIG_4xx_DCACHE
+/* enable caching on SDRAM */
+#define MY_TLB_WORD2_I_ENABLE		0
+#else
+/* disable caching on SDRAM */
+#define MY_TLB_WORD2_I_ENABLE		TLB_WORD2_I_ENABLE
+#endif /* CONFIG_4xx_DCACHE */
+
+void dcbz_area(u32 start_address, u32 num_bytes);
+#endif /* CONFIG_440 */
+
+#define MAXRANKS	4
+#define MAXBXCF		4
+
+#define MULDIV64(m1, m2, d)	(u32)(((u64)(m1) * (u64)(m2)) / (u64)(d))
+
+#if !defined(CONFIG_NAND_SPL)
+/*-----------------------------------------------------------------------------+
+ * sdram_memsize
+ *-----------------------------------------------------------------------------*/
+phys_size_t sdram_memsize(void)
+{
+	phys_size_t mem_size;
+	unsigned long mcopt2;
+	unsigned long mcstat;
+	unsigned long mb0cf;
+	unsigned long sdsz;
+	unsigned long i;
+
+	mem_size = 0;
+
+	mfsdram(SDRAM_MCOPT2, mcopt2);
+	mfsdram(SDRAM_MCSTAT, mcstat);
+
+	/* DDR controller must be enabled and not in self-refresh. */
+	/* Otherwise memsize is zero. */
+	if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE)
+	    && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT)
+	    && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK))
+		== (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) {
+		for (i = 0; i < MAXBXCF; i++) {
+			mfsdram(SDRAM_MB0CF + (i << 2), mb0cf);
+			/* Banks enabled */
+			if ((mb0cf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) {
+#if defined(CONFIG_440)
+				sdsz = mfdcr_any(SDRAM_R0BAS + i) & SDRAM_RXBAS_SDSZ_MASK;
+#else
+				sdsz = mb0cf & SDRAM_RXBAS_SDSZ_MASK;
+#endif
+				switch(sdsz) {
+				case SDRAM_RXBAS_SDSZ_8:
+					mem_size+=8;
+					break;
+				case SDRAM_RXBAS_SDSZ_16:
+					mem_size+=16;
+					break;
+				case SDRAM_RXBAS_SDSZ_32:
+					mem_size+=32;
+					break;
+				case SDRAM_RXBAS_SDSZ_64:
+					mem_size+=64;
+					break;
+				case SDRAM_RXBAS_SDSZ_128:
+					mem_size+=128;
+					break;
+				case SDRAM_RXBAS_SDSZ_256:
+					mem_size+=256;
+					break;
+				case SDRAM_RXBAS_SDSZ_512:
+					mem_size+=512;
+					break;
+				case SDRAM_RXBAS_SDSZ_1024:
+					mem_size+=1024;
+					break;
+				case SDRAM_RXBAS_SDSZ_2048:
+					mem_size+=2048;
+					break;
+				case SDRAM_RXBAS_SDSZ_4096:
+					mem_size+=4096;
+					break;
+				default:
+					printf("WARNING: Unsupported bank size (SDSZ=0x%lx)!\n"
+					       , sdsz);
+					mem_size=0;
+					break;
+				}
+			}
+		}
+	}
+
+	return mem_size << 20;
+}
+
+/*-----------------------------------------------------------------------------+
+ * is_ecc_enabled
+ *-----------------------------------------------------------------------------*/
+static unsigned long is_ecc_enabled(void)
+{
+	unsigned long val;
+
+	mfsdram(SDRAM_MCOPT1, val);
+
+	return SDRAM_MCOPT1_MCHK_CHK_DECODE(val);
+}
+
+/*-----------------------------------------------------------------------------+
+ * board_add_ram_info
+ *-----------------------------------------------------------------------------*/
+void board_add_ram_info(int use_default)
+{
+	PPC4xx_SYS_INFO board_cfg;
+	u32 val;
+
+	if (is_ecc_enabled())
+		puts(" (ECC");
+	else
+		puts(" (ECC not");
+
+	get_sys_info(&board_cfg);
+
+#if defined(CONFIG_405EX)
+	val = board_cfg.freqPLB;
+#else
+	mfsdr(SDR0_DDR0, val);
+	val = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(val), 1);
+#endif
+	printf(" enabled, %d MHz", (val * 2) / 1000000);
+
+	mfsdram(SDRAM_MMODE, val);
+	val = (val & SDRAM_MMODE_DCL_MASK) >> 4;
+	printf(", CL%d)", val);
+}
+#endif /* !CONFIG_NAND_SPL */
+
+#if defined(CONFIG_SPD_EEPROM)
+
+/*-----------------------------------------------------------------------------+
+ * Defines
+ *-----------------------------------------------------------------------------*/
+#ifndef	TRUE
+#define TRUE		1
+#endif
+#ifndef FALSE
+#define FALSE		0
+#endif
+
+#define SDRAM_DDR1	1
+#define SDRAM_DDR2	2
+#define SDRAM_NONE	0
+
+#define MAXDIMMS	2
+#define MAX_SPD_BYTES	256   /* Max number of bytes on the DIMM's SPD EEPROM */
+
+#define ONE_BILLION	1000000000
+
+#define CMD_NOP		(7 << 19)
+#define CMD_PRECHARGE	(2 << 19)
+#define CMD_REFRESH	(1 << 19)
+#define CMD_EMR		(0 << 19)
+#define CMD_READ	(5 << 19)
+#define CMD_WRITE	(4 << 19)
+
+#define SELECT_MR	(0 << 16)
+#define SELECT_EMR	(1 << 16)
+#define SELECT_EMR2	(2 << 16)
+#define SELECT_EMR3	(3 << 16)
+
+/* MR */
+#define DLL_RESET	0x00000100
+
+#define WRITE_RECOV_2	(1 << 9)
+#define WRITE_RECOV_3	(2 << 9)
+#define WRITE_RECOV_4	(3 << 9)
+#define WRITE_RECOV_5	(4 << 9)
+#define WRITE_RECOV_6	(5 << 9)
+
+#define BURST_LEN_4	0x00000002
+
+/* EMR */
+#define ODT_0_OHM	0x00000000
+#define ODT_50_OHM	0x00000044
+#define ODT_75_OHM	0x00000004
+#define ODT_150_OHM	0x00000040
+
+#define ODS_FULL	0x00000000
+#define ODS_REDUCED	0x00000002
+#define OCD_CALIB_DEF	0x00000380
+
+/* defines for ODT (On Die Termination) of the 440SP(e) DDR2 controller */
+#define ODT_EB0R	(0x80000000 >> 8)
+#define ODT_EB0W	(0x80000000 >> 7)
+#define CALC_ODT_R(n)	(ODT_EB0R << (n << 1))
+#define CALC_ODT_W(n)	(ODT_EB0W << (n << 1))
+#define CALC_ODT_RW(n)	(CALC_ODT_R(n) | CALC_ODT_W(n))
+
+/* Defines for the Read Cycle Delay test */
+#define NUMMEMTESTS	8
+#define NUMMEMWORDS	8
+#define NUMLOOPS	64		/* memory test loops */
+
+/*
+ * Newer PPC's like 440SPe, 460EX/GT can be equipped with more than 2GB of SDRAM.
+ * To support such configurations, we "only" map the first 2GB via the TLB's. We
+ * need some free virtual address space for the remaining peripherals like, SoC
+ * devices, FLASH etc.
+ *
+ * Note that ECC is currently not supported on configurations with more than 2GB
+ * SDRAM. This is because we only map the first 2GB on such systems, and therefore
+ * the ECC parity byte of the remaining area can't be written.
+ */
+
+/*
+ * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed
+ */
+void __spd_ddr_init_hang (void)
+{
+	hang ();
+}
+void spd_ddr_init_hang (void) __attribute__((weak, alias("__spd_ddr_init_hang")));
+
+/*
+ * To provide an interface for board specific config values in this common
+ * DDR setup code, we implement he "weak" default functions here. They return
+ * the default value back to the caller.
+ *
+ * Please see include/configs/yucca.h for an example fora board specific
+ * implementation.
+ */
+u32 __ddr_wrdtr(u32 default_val)
+{
+	return default_val;
+}
+u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr")));
+
+u32 __ddr_clktr(u32 default_val)
+{
+	return default_val;
+}
+u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr")));
+
+
+/* Private Structure Definitions */
+
+/* enum only to ease code for cas latency setting */
+typedef enum ddr_cas_id {
+	DDR_CAS_2      = 20,
+	DDR_CAS_2_5    = 25,
+	DDR_CAS_3      = 30,
+	DDR_CAS_4      = 40,
+	DDR_CAS_5      = 50
+} ddr_cas_id_t;
+
+/*-----------------------------------------------------------------------------+
+ * Prototypes
+ *-----------------------------------------------------------------------------*/
+static void get_spd_info(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long num_dimm_banks);
+static void check_mem_type(unsigned long *dimm_populated,
+			   unsigned char *iic0_dimm_addr,
+			   unsigned long num_dimm_banks);
+static void check_frequency(unsigned long *dimm_populated,
+			    unsigned char *iic0_dimm_addr,
+			    unsigned long num_dimm_banks);
+static void check_rank_number(unsigned long *dimm_populated,
+			      unsigned char *iic0_dimm_addr,
+			      unsigned long num_dimm_banks);
+static void check_voltage_type(unsigned long *dimm_populated,
+			       unsigned char *iic0_dimm_addr,
+			       unsigned long num_dimm_banks);
+static void program_memory_queue(unsigned long *dimm_populated,
+				 unsigned char *iic0_dimm_addr,
+				 unsigned long num_dimm_banks);
+static void program_codt(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long num_dimm_banks);
+static void program_mode(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long num_dimm_banks,
+			 ddr_cas_id_t *selected_cas,
+			 int *write_recovery);
+static void program_tr(unsigned long *dimm_populated,
+		       unsigned char *iic0_dimm_addr,
+		       unsigned long num_dimm_banks);
+static void program_rtr(unsigned long *dimm_populated,
+			unsigned char *iic0_dimm_addr,
+			unsigned long num_dimm_banks);
+static void program_bxcf(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long num_dimm_banks);
+static void program_copt1(unsigned long *dimm_populated,
+			  unsigned char *iic0_dimm_addr,
+			  unsigned long num_dimm_banks);
+static void program_initplr(unsigned long *dimm_populated,
+			    unsigned char *iic0_dimm_addr,
+			    unsigned long num_dimm_banks,
+			    ddr_cas_id_t selected_cas,
+			    int write_recovery);
+#ifdef CONFIG_DDR_ECC
+static void program_ecc(unsigned long *dimm_populated,
+			unsigned char *iic0_dimm_addr,
+			unsigned long num_dimm_banks,
+			unsigned long tlb_word2_i_value);
+#endif
+#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+static void program_DQS_calibration(unsigned long *dimm_populated,
+				unsigned char *iic0_dimm_addr,
+				unsigned long num_dimm_banks);
+#ifdef HARD_CODED_DQS /* calibration test with hardvalues */
+static void	test(void);
+#else
+static void	DQS_calibration_process(void);
+#endif
+#endif
+int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+
+static unsigned char spd_read(uchar chip, uint addr)
+{
+	unsigned char data[2];
+
+	if (i2c_probe(chip) == 0)
+		if (i2c_read(chip, addr, 1, data, 1) == 0)
+			return data[0];
+
+	return 0;
+}
+
+/*-----------------------------------------------------------------------------+
+ * initdram.  Initializes the 440SP Memory Queue and DDR SDRAM controller.
+ * Note: This routine runs from flash with a stack set up in the chip's
+ * sram space.  It is important that the routine does not require .sbss, .bss or
+ * .data sections.  It also cannot call routines that require these sections.
+ *-----------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------
+ * Function:	 initdram
+ * Description:  Configures SDRAM memory banks for DDR operation.
+ *		 Auto Memory Configuration option reads the DDR SDRAM EEPROMs
+ *		 via the IIC bus and then configures the DDR SDRAM memory
+ *		 banks appropriately. If Auto Memory Configuration is
+ *		 not used, it is assumed that no DIMM is plugged
+ *-----------------------------------------------------------------------------*/
+phys_size_t initdram(int board_type)
+{
+	unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS;
+	unsigned char spd0[MAX_SPD_BYTES];
+	unsigned char spd1[MAX_SPD_BYTES];
+	unsigned char *dimm_spd[MAXDIMMS];
+	unsigned long dimm_populated[MAXDIMMS] = {SDRAM_NONE, SDRAM_NONE};
+	unsigned long num_dimm_banks;		/* on board dimm banks */
+	unsigned long val;
+	ddr_cas_id_t selected_cas = DDR_CAS_5;	/* preset to silence compiler */
+	int write_recovery;
+	phys_size_t dram_size = 0;
+
+	num_dimm_banks = sizeof(iic0_dimm_addr);
+
+	/*------------------------------------------------------------------
+	 * Set up an array of SPD matrixes.
+	 *-----------------------------------------------------------------*/
+	dimm_spd[0] = spd0;
+	dimm_spd[1] = spd1;
+
+	/*------------------------------------------------------------------
+	 * Reset the DDR-SDRAM controller.
+	 *-----------------------------------------------------------------*/
+	mtsdr(SDR0_SRST, (0x80000000 >> 10));
+	mtsdr(SDR0_SRST, 0x00000000);
+
+	/*
+	 * Make sure I2C controller is initialized
+	 * before continuing.
+	 */
+
+	/* switch to correct I2C bus */
+	I2C_SET_BUS(CONFIG_SYS_SPD_BUS_NUM);
+	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+	/*------------------------------------------------------------------
+	 * Clear out the serial presence detect buffers.
+	 * Perform IIC reads from the dimm.  Fill in the spds.
+	 * Check to see if the dimm slots are populated
+	 *-----------------------------------------------------------------*/
+	get_spd_info(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*------------------------------------------------------------------
+	 * Check the memory type for the dimms plugged.
+	 *-----------------------------------------------------------------*/
+	check_mem_type(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*------------------------------------------------------------------
+	 * Check the frequency supported for the dimms plugged.
+	 *-----------------------------------------------------------------*/
+	check_frequency(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*------------------------------------------------------------------
+	 * Check the total rank number.
+	 *-----------------------------------------------------------------*/
+	check_rank_number(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*------------------------------------------------------------------
+	 * Check the voltage type for the dimms plugged.
+	 *-----------------------------------------------------------------*/
+	check_voltage_type(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*------------------------------------------------------------------
+	 * Program SDRAM controller options 2 register
+	 * Except Enabling of the memory controller.
+	 *-----------------------------------------------------------------*/
+	mfsdram(SDRAM_MCOPT2, val);
+	mtsdram(SDRAM_MCOPT2,
+		(val &
+		 ~(SDRAM_MCOPT2_SREN_MASK | SDRAM_MCOPT2_PMEN_MASK |
+		   SDRAM_MCOPT2_IPTR_MASK | SDRAM_MCOPT2_XSRP_MASK |
+		   SDRAM_MCOPT2_ISIE_MASK))
+		| (SDRAM_MCOPT2_SREN_ENTER | SDRAM_MCOPT2_PMEN_DISABLE |
+		   SDRAM_MCOPT2_IPTR_IDLE | SDRAM_MCOPT2_XSRP_ALLOW |
+		   SDRAM_MCOPT2_ISIE_ENABLE));
+
+	/*------------------------------------------------------------------
+	 * Program SDRAM controller options 1 register
+	 * Note: Does not enable the memory controller.
+	 *-----------------------------------------------------------------*/
+	program_copt1(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*------------------------------------------------------------------
+	 * Set the SDRAM Controller On Die Termination Register
+	 *-----------------------------------------------------------------*/
+	program_codt(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*------------------------------------------------------------------
+	 * Program SDRAM refresh register.
+	 *-----------------------------------------------------------------*/
+	program_rtr(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*------------------------------------------------------------------
+	 * Program SDRAM mode register.
+	 *-----------------------------------------------------------------*/
+	program_mode(dimm_populated, iic0_dimm_addr, num_dimm_banks,
+		     &selected_cas, &write_recovery);
+
+	/*------------------------------------------------------------------
+	 * Set the SDRAM Write Data/DM/DQS Clock Timing Reg
+	 *-----------------------------------------------------------------*/
+	mfsdram(SDRAM_WRDTR, val);
+	mtsdram(SDRAM_WRDTR, (val & ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) |
+		ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | SDRAM_WRDTR_WTR_90_DEG_ADV));
+
+	/*------------------------------------------------------------------
+	 * Set the SDRAM Clock Timing Register
+	 *-----------------------------------------------------------------*/
+	mfsdram(SDRAM_CLKTR, val);
+	mtsdram(SDRAM_CLKTR, (val & ~SDRAM_CLKTR_CLKP_MASK) |
+		ddr_clktr(SDRAM_CLKTR_CLKP_0_DEG));
+
+	/*------------------------------------------------------------------
+	 * Program the BxCF registers.
+	 *-----------------------------------------------------------------*/
+	program_bxcf(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*------------------------------------------------------------------
+	 * Program SDRAM timing registers.
+	 *-----------------------------------------------------------------*/
+	program_tr(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*------------------------------------------------------------------
+	 * Set the Extended Mode register
+	 *-----------------------------------------------------------------*/
+	mfsdram(SDRAM_MEMODE, val);
+	mtsdram(SDRAM_MEMODE,
+		(val & ~(SDRAM_MEMODE_DIC_MASK  | SDRAM_MEMODE_DLL_MASK |
+			 SDRAM_MEMODE_RTT_MASK | SDRAM_MEMODE_DQS_MASK)) |
+		(SDRAM_MEMODE_DIC_NORMAL | SDRAM_MEMODE_DLL_ENABLE
+		 | SDRAM_MEMODE_RTT_150OHM | SDRAM_MEMODE_DQS_ENABLE));
+
+	/*------------------------------------------------------------------
+	 * Program Initialization preload registers.
+	 *-----------------------------------------------------------------*/
+	program_initplr(dimm_populated, iic0_dimm_addr, num_dimm_banks,
+			selected_cas, write_recovery);
+
+	/*------------------------------------------------------------------
+	 * Delay to ensure 200usec have elapsed since reset.
+	 *-----------------------------------------------------------------*/
+	udelay(400);
+
+	/*------------------------------------------------------------------
+	 * Set the memory queue core base addr.
+	 *-----------------------------------------------------------------*/
+	program_memory_queue(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+	/*------------------------------------------------------------------
+	 * Program SDRAM controller options 2 register
+	 * Enable the memory controller.
+	 *-----------------------------------------------------------------*/
+	mfsdram(SDRAM_MCOPT2, val);
+	mtsdram(SDRAM_MCOPT2,
+		(val & ~(SDRAM_MCOPT2_SREN_MASK | SDRAM_MCOPT2_DCEN_MASK |
+			 SDRAM_MCOPT2_IPTR_MASK | SDRAM_MCOPT2_ISIE_MASK)) |
+			 SDRAM_MCOPT2_IPTR_EXECUTE);
+
+	/*------------------------------------------------------------------
+	 * Wait for IPTR_EXECUTE init sequence to complete.
+	 *-----------------------------------------------------------------*/
+	do {
+		mfsdram(SDRAM_MCSTAT, val);
+	} while ((val & SDRAM_MCSTAT_MIC_MASK) == SDRAM_MCSTAT_MIC_NOTCOMP);
+
+	/* enable the controller only after init sequence completes */
+	mfsdram(SDRAM_MCOPT2, val);
+	mtsdram(SDRAM_MCOPT2, (val | SDRAM_MCOPT2_DCEN_ENABLE));
+
+	/* Make sure delay-line calibration is done before proceeding */
+	do {
+		mfsdram(SDRAM_DLCR, val);
+	} while (!(val & SDRAM_DLCR_DLCS_COMPLETE));
+
+	/* get installed memory size */
+	dram_size = sdram_memsize();
+
+	/*
+	 * Limit size to 2GB
+	 */
+	if (dram_size > CONFIG_MAX_MEM_MAPPED)
+		dram_size = CONFIG_MAX_MEM_MAPPED;
+
+	/* and program tlb entries for this size (dynamic) */
+
+	/*
+	 * Program TLB entries with caches enabled, for best performace
+	 * while auto-calibrating and ECC generation
+	 */
+	program_tlb(0, 0, dram_size, 0);
+
+	/*------------------------------------------------------------------
+	 * DQS calibration.
+	 *-----------------------------------------------------------------*/
+#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+	DQS_autocalibration();
+#else
+	program_DQS_calibration(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+#endif
+
+#ifdef CONFIG_DDR_ECC
+	/*------------------------------------------------------------------
+	 * If ecc is enabled, initialize the parity bits.
+	 *-----------------------------------------------------------------*/
+	program_ecc(dimm_populated, iic0_dimm_addr, num_dimm_banks, 0);
+#endif
+
+	/*
+	 * Now after initialization (auto-calibration and ECC generation)
+	 * remove the TLB entries with caches enabled and program again with
+	 * desired cache functionality
+	 */
+	remove_tlb(0, dram_size);
+	program_tlb(0, 0, dram_size, MY_TLB_WORD2_I_ENABLE);
+
+	ppc4xx_ibm_ddr2_register_dump();
+
+	/*
+	 * Clear potential errors resulting from auto-calibration.
+	 * If not done, then we could get an interrupt later on when
+	 * exceptions are enabled.
+	 */
+	set_mcsr(get_mcsr());
+
+	return sdram_memsize();
+}
+
+static void get_spd_info(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long dimm_found;
+	unsigned char num_of_bytes;
+	unsigned char total_size;
+
+	dimm_found = FALSE;
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		num_of_bytes = 0;
+		total_size = 0;
+
+		num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0);
+		debug("\nspd_read(0x%x) returned %d\n",
+		      iic0_dimm_addr[dimm_num], num_of_bytes);
+		total_size = spd_read(iic0_dimm_addr[dimm_num], 1);
+		debug("spd_read(0x%x) returned %d\n",
+		      iic0_dimm_addr[dimm_num], total_size);
+
+		if ((num_of_bytes != 0) && (total_size != 0)) {
+			dimm_populated[dimm_num] = TRUE;
+			dimm_found = TRUE;
+			debug("DIMM slot %lu: populated\n", dimm_num);
+		} else {
+			dimm_populated[dimm_num] = FALSE;
+			debug("DIMM slot %lu: Not populated\n", dimm_num);
+		}
+	}
+
+	if (dimm_found == FALSE) {
+		printf("ERROR - No memory installed. Install a DDR-SDRAM DIMM.\n\n");
+		spd_ddr_init_hang ();
+	}
+}
+
+
+/*------------------------------------------------------------------
+ * For the memory DIMMs installed, this routine verifies that they
+ * really are DDR specific DIMMs.
+ *-----------------------------------------------------------------*/
+static void check_mem_type(unsigned long *dimm_populated,
+			   unsigned char *iic0_dimm_addr,
+			   unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long dimm_type;
+
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] == TRUE) {
+			dimm_type = spd_read(iic0_dimm_addr[dimm_num], 2);
+			switch (dimm_type) {
+			case 1:
+				printf("ERROR: Standard Fast Page Mode DRAM DIMM detected in "
+				       "slot %d.\n", (unsigned int)dimm_num);
+				printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n");
+				printf("Replace the DIMM module with a supported DIMM.\n\n");
+				spd_ddr_init_hang ();
+				break;
+			case 2:
+				printf("ERROR: EDO DIMM detected in slot %d.\n",
+				       (unsigned int)dimm_num);
+				printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n");
+				printf("Replace the DIMM module with a supported DIMM.\n\n");
+				spd_ddr_init_hang ();
+				break;
+			case 3:
+				printf("ERROR: Pipelined Nibble DIMM detected in slot %d.\n",
+				       (unsigned int)dimm_num);
+				printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n");
+				printf("Replace the DIMM module with a supported DIMM.\n\n");
+				spd_ddr_init_hang ();
+				break;
+			case 4:
+				printf("ERROR: SDRAM DIMM detected in slot %d.\n",
+				       (unsigned int)dimm_num);
+				printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n");
+				printf("Replace the DIMM module with a supported DIMM.\n\n");
+				spd_ddr_init_hang ();
+				break;
+			case 5:
+				printf("ERROR: Multiplexed ROM DIMM detected in slot %d.\n",
+				       (unsigned int)dimm_num);
+				printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n");
+				printf("Replace the DIMM module with a supported DIMM.\n\n");
+				spd_ddr_init_hang ();
+				break;
+			case 6:
+				printf("ERROR: SGRAM DIMM detected in slot %d.\n",
+				       (unsigned int)dimm_num);
+				printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n");
+				printf("Replace the DIMM module with a supported DIMM.\n\n");
+				spd_ddr_init_hang ();
+				break;
+			case 7:
+				debug("DIMM slot %lu: DDR1 SDRAM detected\n", dimm_num);
+				dimm_populated[dimm_num] = SDRAM_DDR1;
+				break;
+			case 8:
+				debug("DIMM slot %lu: DDR2 SDRAM detected\n", dimm_num);
+				dimm_populated[dimm_num] = SDRAM_DDR2;
+				break;
+			default:
+				printf("ERROR: Unknown DIMM detected in slot %d.\n",
+				       (unsigned int)dimm_num);
+				printf("Only DDR1 and DDR2 SDRAM DIMMs are supported.\n");
+				printf("Replace the DIMM module with a supported DIMM.\n\n");
+				spd_ddr_init_hang ();
+				break;
+			}
+		}
+	}
+	for (dimm_num = 1; dimm_num < num_dimm_banks; dimm_num++) {
+		if ((dimm_populated[dimm_num-1] != SDRAM_NONE)
+		    && (dimm_populated[dimm_num]   != SDRAM_NONE)
+		    && (dimm_populated[dimm_num-1] != dimm_populated[dimm_num])) {
+			printf("ERROR: DIMM's DDR1 and DDR2 type can not be mixed.\n");
+			spd_ddr_init_hang ();
+		}
+	}
+}
+
+/*------------------------------------------------------------------
+ * For the memory DIMMs installed, this routine verifies that
+ * frequency previously calculated is supported.
+ *-----------------------------------------------------------------*/
+static void check_frequency(unsigned long *dimm_populated,
+			    unsigned char *iic0_dimm_addr,
+			    unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long tcyc_reg;
+	unsigned long cycle_time;
+	unsigned long calc_cycle_time;
+	unsigned long sdram_freq;
+	unsigned long sdr_ddrpll;
+	PPC4xx_SYS_INFO board_cfg;
+
+	/*------------------------------------------------------------------
+	 * Get the board configuration info.
+	 *-----------------------------------------------------------------*/
+	get_sys_info(&board_cfg);
+
+	mfsdr(SDR0_DDR0, sdr_ddrpll);
+	sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll));
+
+	/*
+	 * calc_cycle_time is calculated from DDR frequency set by board/chip
+	 * and is expressed in multiple of 10 picoseconds
+	 * to match the way DIMM cycle time is calculated below.
+	 */
+	calc_cycle_time = MULDIV64(ONE_BILLION, 100, sdram_freq);
+
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] != SDRAM_NONE) {
+			tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9);
+			/*
+			 * Byte 9, Cycle time for CAS Latency=X, is split into two nibbles:
+			 * the higher order nibble (bits 4-7) designates the cycle time
+			 * to a granularity of 1ns;
+			 * the value presented by the lower order nibble (bits 0-3)
+			 * has a granularity of .1ns and is added to the value designated
+			 * by the higher nibble. In addition, four lines of the lower order
+			 * nibble are assigned to support +.25,+.33, +.66 and +.75.
+			 */
+			 /* Convert from hex to decimal */
+			if ((tcyc_reg & 0x0F) == 0x0D)
+				cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 75;
+			else if ((tcyc_reg & 0x0F) == 0x0C)
+				cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 66;
+			else if ((tcyc_reg & 0x0F) == 0x0B)
+				cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 33;
+			else if ((tcyc_reg & 0x0F) == 0x0A)
+				cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 25;
+			else
+				cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) +
+					((tcyc_reg & 0x0F)*10);
+			debug("cycle_time=%lu [10 picoseconds]\n", cycle_time);
+
+			if  (cycle_time > (calc_cycle_time + 10)) {
+				/*
+				 * the provided sdram cycle_time is too small
+				 * for the available DIMM cycle_time.
+				 * The additionnal 100ps is here to accept a small incertainty.
+				 */
+				printf("ERROR: DRAM DIMM detected with cycle_time %d ps in "
+				       "slot %d \n while calculated cycle time is %d ps.\n",
+				       (unsigned int)(cycle_time*10),
+				       (unsigned int)dimm_num,
+				       (unsigned int)(calc_cycle_time*10));
+				printf("Replace the DIMM, or change DDR frequency via "
+				       "strapping bits.\n\n");
+				spd_ddr_init_hang ();
+			}
+		}
+	}
+}
+
+/*------------------------------------------------------------------
+ * For the memory DIMMs installed, this routine verifies two
+ * ranks/banks maximum are availables.
+ *-----------------------------------------------------------------*/
+static void check_rank_number(unsigned long *dimm_populated,
+			      unsigned char *iic0_dimm_addr,
+			      unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long dimm_rank;
+	unsigned long total_rank = 0;
+
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] != SDRAM_NONE) {
+			dimm_rank = spd_read(iic0_dimm_addr[dimm_num], 5);
+			if (((unsigned long)spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08)
+				dimm_rank = (dimm_rank & 0x0F) +1;
+			else
+				dimm_rank = dimm_rank & 0x0F;
+
+
+			if (dimm_rank > MAXRANKS) {
+				printf("ERROR: DRAM DIMM detected with %lu ranks in "
+				       "slot %lu is not supported.\n", dimm_rank, dimm_num);
+				printf("Only %d ranks are supported for all DIMM.\n", MAXRANKS);
+				printf("Replace the DIMM module with a supported DIMM.\n\n");
+				spd_ddr_init_hang ();
+			} else
+				total_rank += dimm_rank;
+		}
+		if (total_rank > MAXRANKS) {
+			printf("ERROR: DRAM DIMM detected with a total of %d ranks "
+			       "for all slots.\n", (unsigned int)total_rank);
+			printf("Only %d ranks are supported for all DIMM.\n", MAXRANKS);
+			printf("Remove one of the DIMM modules.\n\n");
+			spd_ddr_init_hang ();
+		}
+	}
+}
+
+/*------------------------------------------------------------------
+ * only support 2.5V modules.
+ * This routine verifies this.
+ *-----------------------------------------------------------------*/
+static void check_voltage_type(unsigned long *dimm_populated,
+			       unsigned char *iic0_dimm_addr,
+			       unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long voltage_type;
+
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] != SDRAM_NONE) {
+			voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8);
+			switch (voltage_type) {
+			case 0x00:
+				printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n");
+				printf("This DIMM is 5.0 Volt/TTL.\n");
+				printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n",
+				       (unsigned int)dimm_num);
+				spd_ddr_init_hang ();
+				break;
+			case 0x01:
+				printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n");
+				printf("This DIMM is LVTTL.\n");
+				printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n",
+				       (unsigned int)dimm_num);
+				spd_ddr_init_hang ();
+				break;
+			case 0x02:
+				printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n");
+				printf("This DIMM is 1.5 Volt.\n");
+				printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n",
+				       (unsigned int)dimm_num);
+				spd_ddr_init_hang ();
+				break;
+			case 0x03:
+				printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n");
+				printf("This DIMM is 3.3 Volt/TTL.\n");
+				printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n",
+				       (unsigned int)dimm_num);
+				spd_ddr_init_hang ();
+				break;
+			case 0x04:
+				/* 2.5 Voltage only for DDR1 */
+				break;
+			case 0x05:
+				/* 1.8 Voltage only for DDR2 */
+				break;
+			default:
+				printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n");
+				printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n",
+				       (unsigned int)dimm_num);
+				spd_ddr_init_hang ();
+				break;
+			}
+		}
+	}
+}
+
+/*-----------------------------------------------------------------------------+
+ * program_copt1.
+ *-----------------------------------------------------------------------------*/
+static void program_copt1(unsigned long *dimm_populated,
+			  unsigned char *iic0_dimm_addr,
+			  unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long mcopt1;
+	unsigned long ecc_enabled;
+	unsigned long ecc = 0;
+	unsigned long data_width = 0;
+	unsigned long dimm_32bit;
+	unsigned long dimm_64bit;
+	unsigned long registered = 0;
+	unsigned long attribute = 0;
+	unsigned long buf0, buf1; /* TODO: code to be changed for IOP1.6 to support 4 DIMMs */
+	unsigned long bankcount;
+	unsigned long ddrtype;
+	unsigned long val;
+
+#ifdef CONFIG_DDR_ECC
+	ecc_enabled = TRUE;
+#else
+	ecc_enabled = FALSE;
+#endif
+	dimm_32bit = FALSE;
+	dimm_64bit = FALSE;
+	buf0 = FALSE;
+	buf1 = FALSE;
+
+	/*------------------------------------------------------------------
+	 * Set memory controller options reg 1, SDRAM_MCOPT1.
+	 *-----------------------------------------------------------------*/
+	mfsdram(SDRAM_MCOPT1, val);
+	mcopt1 = val & ~(SDRAM_MCOPT1_MCHK_MASK | SDRAM_MCOPT1_RDEN_MASK |
+			 SDRAM_MCOPT1_PMU_MASK  | SDRAM_MCOPT1_DMWD_MASK |
+			 SDRAM_MCOPT1_UIOS_MASK | SDRAM_MCOPT1_BCNT_MASK |
+			 SDRAM_MCOPT1_DDR_TYPE_MASK | SDRAM_MCOPT1_RWOO_MASK |
+			 SDRAM_MCOPT1_WOOO_MASK | SDRAM_MCOPT1_DCOO_MASK |
+			 SDRAM_MCOPT1_DREF_MASK);
+
+	mcopt1 |= SDRAM_MCOPT1_QDEP;
+	mcopt1 |= SDRAM_MCOPT1_PMU_OPEN;
+	mcopt1 |= SDRAM_MCOPT1_RWOO_DISABLED;
+	mcopt1 |= SDRAM_MCOPT1_WOOO_DISABLED;
+	mcopt1 |= SDRAM_MCOPT1_DCOO_DISABLED;
+	mcopt1 |= SDRAM_MCOPT1_DREF_NORMAL;
+
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] != SDRAM_NONE) {
+			/* test ecc support */
+			ecc = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 11);
+			if (ecc != 0x02) /* ecc not supported */
+				ecc_enabled = FALSE;
+
+			/* test bank count */
+			bankcount = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 17);
+			if (bankcount == 0x04) /* bank count = 4 */
+				mcopt1 |= SDRAM_MCOPT1_4_BANKS;
+			else /* bank count = 8 */
+				mcopt1 |= SDRAM_MCOPT1_8_BANKS;
+
+			/* test DDR type */
+			ddrtype = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 2);
+			/* test for buffered/unbuffered, registered, differential clocks */
+			registered = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 20);
+			attribute = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 21);
+
+			/* TODO: code to be changed for IOP1.6 to support 4 DIMMs */
+			if (dimm_num == 0) {
+				if (dimm_populated[dimm_num] == SDRAM_DDR1) /* DDR1 type */
+					mcopt1 |= SDRAM_MCOPT1_DDR1_TYPE;
+				if (dimm_populated[dimm_num] == SDRAM_DDR2) /* DDR2 type */
+					mcopt1 |= SDRAM_MCOPT1_DDR2_TYPE;
+				if (registered == 1) { /* DDR2 always buffered */
+					/* TODO: what about above  comments ? */
+					mcopt1 |= SDRAM_MCOPT1_RDEN;
+					buf0 = TRUE;
+				} else {
+					/* TODO: the mask 0x02 doesn't match Samsung def for byte 21. */
+					if ((attribute & 0x02) == 0x00) {
+						/* buffered not supported */
+						buf0 = FALSE;
+					} else {
+						mcopt1 |= SDRAM_MCOPT1_RDEN;
+						buf0 = TRUE;
+					}
+				}
+			}
+			else if (dimm_num == 1) {
+				if (dimm_populated[dimm_num] == SDRAM_DDR1) /* DDR1 type */
+					mcopt1 |= SDRAM_MCOPT1_DDR1_TYPE;
+				if (dimm_populated[dimm_num] == SDRAM_DDR2) /* DDR2 type */
+					mcopt1 |= SDRAM_MCOPT1_DDR2_TYPE;
+				if (registered == 1) {
+					/* DDR2 always buffered */
+					mcopt1 |= SDRAM_MCOPT1_RDEN;
+					buf1 = TRUE;
+				} else {
+					if ((attribute & 0x02) == 0x00) {
+						/* buffered not supported */
+						buf1 = FALSE;
+					} else {
+						mcopt1 |= SDRAM_MCOPT1_RDEN;
+						buf1 = TRUE;
+					}
+				}
+			}
+
+			/* Note that for DDR2 the byte 7 is reserved, but OK to keep code as is. */
+			data_width = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 6) +
+				(((unsigned long)spd_read(iic0_dimm_addr[dimm_num], 7)) << 8);
+
+			switch (data_width) {
+			case 72:
+			case 64:
+				dimm_64bit = TRUE;
+				break;
+			case 40:
+			case 32:
+				dimm_32bit = TRUE;
+				break;
+			default:
+				printf("WARNING: Detected a DIMM with a data width of %lu bits.\n",
+				       data_width);
+				printf("Only DIMMs with 32 or 64 bit DDR-SDRAM widths are supported.\n");
+				break;
+			}
+		}
+	}
+
+	/* verify matching properties */
+	if ((dimm_populated[0] != SDRAM_NONE) && (dimm_populated[1] != SDRAM_NONE)) {
+		if (buf0 != buf1) {
+			printf("ERROR: DIMM's buffered/unbuffered, registered, clocking don't match.\n");
+			spd_ddr_init_hang ();
+		}
+	}
+
+	if ((dimm_64bit == TRUE) && (dimm_32bit == TRUE)) {
+		printf("ERROR: Cannot mix 32 bit and 64 bit DDR-SDRAM DIMMs together.\n");
+		spd_ddr_init_hang ();
+	}
+	else if ((dimm_64bit == TRUE) && (dimm_32bit == FALSE)) {
+		mcopt1 |= SDRAM_MCOPT1_DMWD_64;
+	} else if ((dimm_64bit == FALSE) && (dimm_32bit == TRUE)) {
+		mcopt1 |= SDRAM_MCOPT1_DMWD_32;
+	} else {
+		printf("ERROR: Please install only 32 or 64 bit DDR-SDRAM DIMMs.\n\n");
+		spd_ddr_init_hang ();
+	}
+
+	if (ecc_enabled == TRUE)
+		mcopt1 |= SDRAM_MCOPT1_MCHK_GEN;
+	else
+		mcopt1 |= SDRAM_MCOPT1_MCHK_NON;
+
+	mtsdram(SDRAM_MCOPT1, mcopt1);
+}
+
+/*-----------------------------------------------------------------------------+
+ * program_codt.
+ *-----------------------------------------------------------------------------*/
+static void program_codt(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long num_dimm_banks)
+{
+	unsigned long codt;
+	unsigned long modt0 = 0;
+	unsigned long modt1 = 0;
+	unsigned long modt2 = 0;
+	unsigned long modt3 = 0;
+	unsigned char dimm_num;
+	unsigned char dimm_rank;
+	unsigned char total_rank = 0;
+	unsigned char total_dimm = 0;
+	unsigned char dimm_type = 0;
+	unsigned char firstSlot = 0;
+
+	/*------------------------------------------------------------------
+	 * Set the SDRAM Controller On Die Termination Register
+	 *-----------------------------------------------------------------*/
+	mfsdram(SDRAM_CODT, codt);
+	codt &= ~(SDRAM_CODT_DQS_SINGLE_END | SDRAM_CODT_CKSE_SINGLE_END);
+	codt |= SDRAM_CODT_IO_NMODE;
+
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] != SDRAM_NONE) {
+			dimm_rank = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 5);
+			if (((unsigned long)spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08) {
+				dimm_rank = (dimm_rank & 0x0F) + 1;
+				dimm_type = SDRAM_DDR2;
+			} else {
+				dimm_rank = dimm_rank & 0x0F;
+				dimm_type = SDRAM_DDR1;
+			}
+
+			total_rank += dimm_rank;
+			total_dimm++;
+			if ((dimm_num == 0) && (total_dimm == 1))
+				firstSlot = TRUE;
+			else
+				firstSlot = FALSE;
+		}
+	}
+	if (dimm_type == SDRAM_DDR2) {
+		codt |= SDRAM_CODT_DQS_1_8_V_DDR2;
+		if ((total_dimm == 1) && (firstSlot == TRUE)) {
+			if (total_rank == 1) {	/* PUUU */
+				codt |= CALC_ODT_R(0);
+				modt0 = CALC_ODT_W(0);
+				modt1 = 0x00000000;
+				modt2 = 0x00000000;
+				modt3 = 0x00000000;
+			}
+			if (total_rank == 2) {	/* PPUU */
+				codt |= CALC_ODT_R(0) | CALC_ODT_R(1);
+				modt0 = CALC_ODT_W(0) | CALC_ODT_W(1);
+				modt1 = 0x00000000;
+				modt2 = 0x00000000;
+				modt3 = 0x00000000;
+			}
+		} else if ((total_dimm == 1) && (firstSlot != TRUE)) {
+			if (total_rank == 1) {	/* UUPU */
+				codt |= CALC_ODT_R(2);
+				modt0 = 0x00000000;
+				modt1 = 0x00000000;
+				modt2 = CALC_ODT_W(2);
+				modt3 = 0x00000000;
+			}
+			if (total_rank == 2) {	/* UUPP */
+				codt |= CALC_ODT_R(2) | CALC_ODT_R(3);
+				modt0 = 0x00000000;
+				modt1 = 0x00000000;
+				modt2 = CALC_ODT_W(2) | CALC_ODT_W(3);
+				modt3 = 0x00000000;
+			}
+		}
+		if (total_dimm == 2) {
+			if (total_rank == 2) {	/* PUPU */
+				codt |= CALC_ODT_R(0) | CALC_ODT_R(2);
+				modt0 = CALC_ODT_RW(2);
+				modt1 = 0x00000000;
+				modt2 = CALC_ODT_RW(0);
+				modt3 = 0x00000000;
+			}
+			if (total_rank == 4) {	/* PPPP */
+				codt |= CALC_ODT_R(0) | CALC_ODT_R(1) |
+					CALC_ODT_R(2) | CALC_ODT_R(3);
+				modt0 = CALC_ODT_RW(2) | CALC_ODT_RW(3);
+				modt1 = 0x00000000;
+				modt2 = CALC_ODT_RW(0) | CALC_ODT_RW(1);
+				modt3 = 0x00000000;
+			}
+		}
+	} else {
+		codt |= SDRAM_CODT_DQS_2_5_V_DDR1;
+		modt0 = 0x00000000;
+		modt1 = 0x00000000;
+		modt2 = 0x00000000;
+		modt3 = 0x00000000;
+
+		if (total_dimm == 1) {
+			if (total_rank == 1)
+				codt |= 0x00800000;
+			if (total_rank == 2)
+				codt |= 0x02800000;
+		}
+		if (total_dimm == 2) {
+			if (total_rank == 2)
+				codt |= 0x08800000;
+			if (total_rank == 4)
+				codt |= 0x2a800000;
+		}
+	}
+
+	debug("nb of dimm %d\n", total_dimm);
+	debug("nb of rank %d\n", total_rank);
+	if (total_dimm == 1)
+		debug("dimm in slot %d\n", firstSlot);
+
+	mtsdram(SDRAM_CODT, codt);
+	mtsdram(SDRAM_MODT0, modt0);
+	mtsdram(SDRAM_MODT1, modt1);
+	mtsdram(SDRAM_MODT2, modt2);
+	mtsdram(SDRAM_MODT3, modt3);
+}
+
+/*-----------------------------------------------------------------------------+
+ * program_initplr.
+ *-----------------------------------------------------------------------------*/
+static void program_initplr(unsigned long *dimm_populated,
+			    unsigned char *iic0_dimm_addr,
+			    unsigned long num_dimm_banks,
+			    ddr_cas_id_t selected_cas,
+			    int write_recovery)
+{
+	u32 cas = 0;
+	u32 odt = 0;
+	u32 ods = 0;
+	u32 mr;
+	u32 wr;
+	u32 emr;
+	u32 emr2;
+	u32 emr3;
+	int dimm_num;
+	int total_dimm = 0;
+
+	/******************************************************
+	 ** Assumption: if more than one DIMM, all DIMMs are the same
+	 **		as already checked in check_memory_type
+	 ******************************************************/
+
+	if ((dimm_populated[0] == SDRAM_DDR1) || (dimm_populated[1] == SDRAM_DDR1)) {
+		mtsdram(SDRAM_INITPLR0, 0x81B80000);
+		mtsdram(SDRAM_INITPLR1, 0x81900400);
+		mtsdram(SDRAM_INITPLR2, 0x81810000);
+		mtsdram(SDRAM_INITPLR3, 0xff800162);
+		mtsdram(SDRAM_INITPLR4, 0x81900400);
+		mtsdram(SDRAM_INITPLR5, 0x86080000);
+		mtsdram(SDRAM_INITPLR6, 0x86080000);
+		mtsdram(SDRAM_INITPLR7, 0x81000062);
+	} else if ((dimm_populated[0] == SDRAM_DDR2) || (dimm_populated[1] == SDRAM_DDR2)) {
+		switch (selected_cas) {
+		case DDR_CAS_3:
+			cas = 3 << 4;
+			break;
+		case DDR_CAS_4:
+			cas = 4 << 4;
+			break;
+		case DDR_CAS_5:
+			cas = 5 << 4;
+			break;
+		default:
+			printf("ERROR: ucode error on selected_cas value %d", selected_cas);
+			spd_ddr_init_hang ();
+			break;
+		}
+
+#if 0
+		/*
+		 * ToDo - Still a problem with the write recovery:
+		 * On the Corsair CM2X512-5400C4 module, setting write recovery
+		 * in the INITPLR reg to the value calculated in program_mode()
+		 * results in not correctly working DDR2 memory (crash after
+		 * relocation).
+		 *
+		 * So for now, set the write recovery to 3. This seems to work
+		 * on the Corair module too.
+		 *
+		 * 2007-03-01, sr
+		 */
+		switch (write_recovery) {
+		case 3:
+			wr = WRITE_RECOV_3;
+			break;
+		case 4:
+			wr = WRITE_RECOV_4;
+			break;
+		case 5:
+			wr = WRITE_RECOV_5;
+			break;
+		case 6:
+			wr = WRITE_RECOV_6;
+			break;
+		default:
+			printf("ERROR: write recovery not support (%d)", write_recovery);
+			spd_ddr_init_hang ();
+			break;
+		}
+#else
+		wr = WRITE_RECOV_3; /* test-only, see description above */
+#endif
+
+		for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++)
+			if (dimm_populated[dimm_num] != SDRAM_NONE)
+				total_dimm++;
+		if (total_dimm == 1) {
+			odt = ODT_150_OHM;
+			ods = ODS_FULL;
+		} else if (total_dimm == 2) {
+			odt = ODT_75_OHM;
+			ods = ODS_REDUCED;
+		} else {
+			printf("ERROR: Unsupported number of DIMM's (%d)", total_dimm);
+			spd_ddr_init_hang ();
+		}
+
+		mr = CMD_EMR | SELECT_MR | BURST_LEN_4 | wr | cas;
+		emr = CMD_EMR | SELECT_EMR | odt | ods;
+		emr2 = CMD_EMR | SELECT_EMR2;
+		emr3 = CMD_EMR | SELECT_EMR3;
+		/* NOP - Wait 106 MemClk cycles */
+		mtsdram(SDRAM_INITPLR0, SDRAM_INITPLR_ENABLE | CMD_NOP |
+					SDRAM_INITPLR_IMWT_ENCODE(106));
+		udelay(1000);
+		/* precharge 4 MemClk cycles */
+		mtsdram(SDRAM_INITPLR1, SDRAM_INITPLR_ENABLE | CMD_PRECHARGE |
+					SDRAM_INITPLR_IMWT_ENCODE(4));
+		/* EMR2 - Wait tMRD (2 MemClk cycles) */
+		mtsdram(SDRAM_INITPLR2, SDRAM_INITPLR_ENABLE | emr2 |
+					SDRAM_INITPLR_IMWT_ENCODE(2));
+		/* EMR3 - Wait tMRD (2 MemClk cycles) */
+		mtsdram(SDRAM_INITPLR3, SDRAM_INITPLR_ENABLE | emr3 |
+					SDRAM_INITPLR_IMWT_ENCODE(2));
+		/* EMR DLL ENABLE - Wait tMRD (2 MemClk cycles) */
+		mtsdram(SDRAM_INITPLR4, SDRAM_INITPLR_ENABLE | emr |
+					SDRAM_INITPLR_IMWT_ENCODE(2));
+		/* MR w/ DLL reset - 200 cycle wait for DLL reset */
+		mtsdram(SDRAM_INITPLR5, SDRAM_INITPLR_ENABLE | mr | DLL_RESET |
+					SDRAM_INITPLR_IMWT_ENCODE(200));
+		udelay(1000);
+		/* precharge 4 MemClk cycles */
+		mtsdram(SDRAM_INITPLR6, SDRAM_INITPLR_ENABLE | CMD_PRECHARGE |
+					SDRAM_INITPLR_IMWT_ENCODE(4));
+		/* Refresh 25 MemClk cycles */
+		mtsdram(SDRAM_INITPLR7, SDRAM_INITPLR_ENABLE | CMD_REFRESH |
+					SDRAM_INITPLR_IMWT_ENCODE(25));
+		/* Refresh 25 MemClk cycles */
+		mtsdram(SDRAM_INITPLR8, SDRAM_INITPLR_ENABLE | CMD_REFRESH |
+					SDRAM_INITPLR_IMWT_ENCODE(25));
+		/* Refresh 25 MemClk cycles */
+		mtsdram(SDRAM_INITPLR9, SDRAM_INITPLR_ENABLE | CMD_REFRESH |
+					SDRAM_INITPLR_IMWT_ENCODE(25));
+		/* Refresh 25 MemClk cycles */
+		mtsdram(SDRAM_INITPLR10, SDRAM_INITPLR_ENABLE | CMD_REFRESH |
+					 SDRAM_INITPLR_IMWT_ENCODE(25));
+		/* MR w/o DLL reset - Wait tMRD (2 MemClk cycles) */
+		mtsdram(SDRAM_INITPLR11, SDRAM_INITPLR_ENABLE | mr |
+					 SDRAM_INITPLR_IMWT_ENCODE(2));
+		/* EMR OCD Default - Wait tMRD (2 MemClk cycles) */
+		mtsdram(SDRAM_INITPLR12, SDRAM_INITPLR_ENABLE | OCD_CALIB_DEF |
+					 SDRAM_INITPLR_IMWT_ENCODE(2) | emr);
+		/* EMR OCD Exit */
+		mtsdram(SDRAM_INITPLR13, SDRAM_INITPLR_ENABLE | emr |
+					 SDRAM_INITPLR_IMWT_ENCODE(2));
+	} else {
+		printf("ERROR: ucode error as unknown DDR type in program_initplr");
+		spd_ddr_init_hang ();
+	}
+}
+
+/*------------------------------------------------------------------
+ * This routine programs the SDRAM_MMODE register.
+ * the selected_cas is an output parameter, that will be passed
+ * by caller to call the above program_initplr( )
+ *-----------------------------------------------------------------*/
+static void program_mode(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long num_dimm_banks,
+			 ddr_cas_id_t *selected_cas,
+			 int *write_recovery)
+{
+	unsigned long dimm_num;
+	unsigned long sdram_ddr1;
+	unsigned long t_wr_ns;
+	unsigned long t_wr_clk;
+	unsigned long cas_bit;
+	unsigned long cas_index;
+	unsigned long sdram_freq;
+	unsigned long ddr_check;
+	unsigned long mmode;
+	unsigned long tcyc_reg;
+	unsigned long cycle_2_0_clk;
+	unsigned long cycle_2_5_clk;
+	unsigned long cycle_3_0_clk;
+	unsigned long cycle_4_0_clk;
+	unsigned long cycle_5_0_clk;
+	unsigned long max_2_0_tcyc_ns_x_100;
+	unsigned long max_2_5_tcyc_ns_x_100;
+	unsigned long max_3_0_tcyc_ns_x_100;
+	unsigned long max_4_0_tcyc_ns_x_100;
+	unsigned long max_5_0_tcyc_ns_x_100;
+	unsigned long cycle_time_ns_x_100[3];
+	PPC4xx_SYS_INFO board_cfg;
+	unsigned char cas_2_0_available;
+	unsigned char cas_2_5_available;
+	unsigned char cas_3_0_available;
+	unsigned char cas_4_0_available;
+	unsigned char cas_5_0_available;
+	unsigned long sdr_ddrpll;
+
+	/*------------------------------------------------------------------
+	 * Get the board configuration info.
+	 *-----------------------------------------------------------------*/
+	get_sys_info(&board_cfg);
+
+	mfsdr(SDR0_DDR0, sdr_ddrpll);
+	sdram_freq = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(sdr_ddrpll), 1);
+	debug("sdram_freq=%lu\n", sdram_freq);
+
+	/*------------------------------------------------------------------
+	 * Handle the timing.  We need to find the worst case timing of all
+	 * the dimm modules installed.
+	 *-----------------------------------------------------------------*/
+	t_wr_ns = 0;
+	cas_2_0_available = TRUE;
+	cas_2_5_available = TRUE;
+	cas_3_0_available = TRUE;
+	cas_4_0_available = TRUE;
+	cas_5_0_available = TRUE;
+	max_2_0_tcyc_ns_x_100 = 10;
+	max_2_5_tcyc_ns_x_100 = 10;
+	max_3_0_tcyc_ns_x_100 = 10;
+	max_4_0_tcyc_ns_x_100 = 10;
+	max_5_0_tcyc_ns_x_100 = 10;
+	sdram_ddr1 = TRUE;
+
+	/* loop through all the DIMM slots on the board */
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		/* If a dimm is installed in a particular slot ... */
+		if (dimm_populated[dimm_num] != SDRAM_NONE) {
+			if (dimm_populated[dimm_num] == SDRAM_DDR1)
+				sdram_ddr1 = TRUE;
+			else
+				sdram_ddr1 = FALSE;
+
+			/* t_wr_ns = max(t_wr_ns, (unsigned long)dimm_spd[dimm_num][36] >> 2); */ /*  not used in this loop. */
+			cas_bit = spd_read(iic0_dimm_addr[dimm_num], 18);
+			debug("cas_bit[SPD byte 18]=%02lx\n", cas_bit);
+
+			/* For a particular DIMM, grab the three CAS values it supports */
+			for (cas_index = 0; cas_index < 3; cas_index++) {
+				switch (cas_index) {
+				case 0:
+					tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9);
+					break;
+				case 1:
+					tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 23);
+					break;
+				default:
+					tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 25);
+					break;
+				}
+
+				if ((tcyc_reg & 0x0F) >= 10) {
+					if ((tcyc_reg & 0x0F) == 0x0D) {
+						/* Convert from hex to decimal */
+						cycle_time_ns_x_100[cas_index] =
+							(((tcyc_reg & 0xF0) >> 4) * 100) + 75;
+					} else {
+						printf("ERROR: SPD reported Tcyc is incorrect for DIMM "
+						       "in slot %d\n", (unsigned int)dimm_num);
+						spd_ddr_init_hang ();
+					}
+				} else {
+					/* Convert from hex to decimal */
+					cycle_time_ns_x_100[cas_index] =
+						(((tcyc_reg & 0xF0) >> 4) * 100) +
+						((tcyc_reg & 0x0F)*10);
+				}
+				debug("cas_index=%lu: cycle_time_ns_x_100=%lu\n", cas_index,
+				      cycle_time_ns_x_100[cas_index]);
+			}
+
+			/* The rest of this routine determines if CAS 2.0, 2.5, 3.0, 4.0 and 5.0 are */
+			/* supported for a particular DIMM. */
+			cas_index = 0;
+
+			if (sdram_ddr1) {
+				/*
+				 * DDR devices use the following bitmask for CAS latency:
+				 *  Bit   7    6    5    4    3    2    1    0
+				 *       TBD  4.0  3.5  3.0  2.5  2.0  1.5  1.0
+				 */
+				if (((cas_bit & 0x40) == 0x40) && (cas_index < 3) &&
+				    (cycle_time_ns_x_100[cas_index] != 0)) {
+					max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100,
+								    cycle_time_ns_x_100[cas_index]);
+					cas_index++;
+				} else {
+					if (cas_index != 0)
+						cas_index++;
+					cas_4_0_available = FALSE;
+				}
+
+				if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) &&
+				    (cycle_time_ns_x_100[cas_index] != 0)) {
+					max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100,
+								    cycle_time_ns_x_100[cas_index]);
+					cas_index++;
+				} else {
+					if (cas_index != 0)
+						cas_index++;
+					cas_3_0_available = FALSE;
+				}
+
+				if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) &&
+				    (cycle_time_ns_x_100[cas_index] != 0)) {
+					max_2_5_tcyc_ns_x_100 = max(max_2_5_tcyc_ns_x_100,
+								    cycle_time_ns_x_100[cas_index]);
+					cas_index++;
+				} else {
+					if (cas_index != 0)
+						cas_index++;
+					cas_2_5_available = FALSE;
+				}
+
+				if (((cas_bit & 0x04) == 0x04) && (cas_index < 3) &&
+				    (cycle_time_ns_x_100[cas_index] != 0)) {
+					max_2_0_tcyc_ns_x_100 = max(max_2_0_tcyc_ns_x_100,
+								    cycle_time_ns_x_100[cas_index]);
+					cas_index++;
+				} else {
+					if (cas_index != 0)
+						cas_index++;
+					cas_2_0_available = FALSE;
+				}
+			} else {
+				/*
+				 * DDR2 devices use the following bitmask for CAS latency:
+				 *  Bit   7    6    5    4    3    2    1    0
+				 *       TBD  6.0  5.0  4.0  3.0  2.0  TBD  TBD
+				 */
+				if (((cas_bit & 0x20) == 0x20) && (cas_index < 3) &&
+				    (cycle_time_ns_x_100[cas_index] != 0)) {
+					max_5_0_tcyc_ns_x_100 = max(max_5_0_tcyc_ns_x_100,
+								    cycle_time_ns_x_100[cas_index]);
+					cas_index++;
+				} else {
+					if (cas_index != 0)
+						cas_index++;
+					cas_5_0_available = FALSE;
+				}
+
+				if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) &&
+				    (cycle_time_ns_x_100[cas_index] != 0)) {
+					max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100,
+								    cycle_time_ns_x_100[cas_index]);
+					cas_index++;
+				} else {
+					if (cas_index != 0)
+						cas_index++;
+					cas_4_0_available = FALSE;
+				}
+
+				if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) &&
+				    (cycle_time_ns_x_100[cas_index] != 0)) {
+					max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100,
+								    cycle_time_ns_x_100[cas_index]);
+					cas_index++;
+				} else {
+					if (cas_index != 0)
+						cas_index++;
+					cas_3_0_available = FALSE;
+				}
+			}
+		}
+	}
+
+	/*------------------------------------------------------------------
+	 * Set the SDRAM mode, SDRAM_MMODE
+	 *-----------------------------------------------------------------*/
+	mfsdram(SDRAM_MMODE, mmode);
+	mmode = mmode & ~(SDRAM_MMODE_WR_MASK | SDRAM_MMODE_DCL_MASK);
+
+	/* add 10 here because of rounding problems */
+	cycle_2_0_clk = MULDIV64(ONE_BILLION, 100, max_2_0_tcyc_ns_x_100) + 10;
+	cycle_2_5_clk = MULDIV64(ONE_BILLION, 100, max_2_5_tcyc_ns_x_100) + 10;
+	cycle_3_0_clk = MULDIV64(ONE_BILLION, 100, max_3_0_tcyc_ns_x_100) + 10;
+	cycle_4_0_clk = MULDIV64(ONE_BILLION, 100, max_4_0_tcyc_ns_x_100) + 10;
+	cycle_5_0_clk = MULDIV64(ONE_BILLION, 100, max_5_0_tcyc_ns_x_100) + 10;
+	debug("cycle_3_0_clk=%lu\n", cycle_3_0_clk);
+	debug("cycle_4_0_clk=%lu\n", cycle_4_0_clk);
+	debug("cycle_5_0_clk=%lu\n", cycle_5_0_clk);
+
+	if (sdram_ddr1 == TRUE) { /* DDR1 */
+		if ((cas_2_0_available == TRUE) && (sdram_freq <= cycle_2_0_clk)) {
+			mmode |= SDRAM_MMODE_DCL_DDR1_2_0_CLK;
+			*selected_cas = DDR_CAS_2;
+		} else if ((cas_2_5_available == TRUE) && (sdram_freq <= cycle_2_5_clk)) {
+			mmode |= SDRAM_MMODE_DCL_DDR1_2_5_CLK;
+			*selected_cas = DDR_CAS_2_5;
+		} else if ((cas_3_0_available == TRUE) && (sdram_freq <= cycle_3_0_clk)) {
+			mmode |= SDRAM_MMODE_DCL_DDR1_3_0_CLK;
+			*selected_cas = DDR_CAS_3;
+		} else {
+			printf("ERROR: Cannot find a supported CAS latency with the installed DIMMs.\n");
+			printf("Only DIMMs DDR1 with CAS latencies of 2.0, 2.5, and 3.0 are supported.\n");
+			printf("Make sure the PLB speed is within the supported range of the DIMMs.\n\n");
+			spd_ddr_init_hang ();
+		}
+	} else { /* DDR2 */
+		debug("cas_3_0_available=%d\n", cas_3_0_available);
+		debug("cas_4_0_available=%d\n", cas_4_0_available);
+		debug("cas_5_0_available=%d\n", cas_5_0_available);
+		if ((cas_3_0_available == TRUE) && (sdram_freq <= cycle_3_0_clk)) {
+			mmode |= SDRAM_MMODE_DCL_DDR2_3_0_CLK;
+			*selected_cas = DDR_CAS_3;
+		} else if ((cas_4_0_available == TRUE) && (sdram_freq <= cycle_4_0_clk)) {
+			mmode |= SDRAM_MMODE_DCL_DDR2_4_0_CLK;
+			*selected_cas = DDR_CAS_4;
+		} else if ((cas_5_0_available == TRUE) && (sdram_freq <= cycle_5_0_clk)) {
+			mmode |= SDRAM_MMODE_DCL_DDR2_5_0_CLK;
+			*selected_cas = DDR_CAS_5;
+		} else {
+			printf("ERROR: Cannot find a supported CAS latency with the installed DIMMs.\n");
+			printf("Only DIMMs DDR2 with CAS latencies of 3.0, 4.0, and 5.0 are supported.\n");
+			printf("Make sure the PLB speed is within the supported range of the DIMMs.\n");
+			printf("cas3=%d cas4=%d cas5=%d\n",
+			       cas_3_0_available, cas_4_0_available, cas_5_0_available);
+			printf("sdram_freq=%lu cycle3=%lu cycle4=%lu cycle5=%lu\n\n",
+			       sdram_freq, cycle_3_0_clk, cycle_4_0_clk, cycle_5_0_clk);
+			spd_ddr_init_hang ();
+		}
+	}
+
+	if (sdram_ddr1 == TRUE)
+		mmode |= SDRAM_MMODE_WR_DDR1;
+	else {
+
+		/* loop through all the DIMM slots on the board */
+		for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+			/* If a dimm is installed in a particular slot ... */
+			if (dimm_populated[dimm_num] != SDRAM_NONE)
+				t_wr_ns = max(t_wr_ns,
+					      spd_read(iic0_dimm_addr[dimm_num], 36) >> 2);
+		}
+
+		/*
+		 * convert from nanoseconds to ddr clocks
+		 * round up if necessary
+		 */
+		t_wr_clk = MULDIV64(sdram_freq, t_wr_ns, ONE_BILLION);
+		ddr_check = MULDIV64(ONE_BILLION, t_wr_clk, t_wr_ns);
+		if (sdram_freq != ddr_check)
+			t_wr_clk++;
+
+		switch (t_wr_clk) {
+		case 0:
+		case 1:
+		case 2:
+		case 3:
+			mmode |= SDRAM_MMODE_WR_DDR2_3_CYC;
+			break;
+		case 4:
+			mmode |= SDRAM_MMODE_WR_DDR2_4_CYC;
+			break;
+		case 5:
+			mmode |= SDRAM_MMODE_WR_DDR2_5_CYC;
+			break;
+		default:
+			mmode |= SDRAM_MMODE_WR_DDR2_6_CYC;
+			break;
+		}
+		*write_recovery = t_wr_clk;
+	}
+
+	debug("CAS latency = %d\n", *selected_cas);
+	debug("Write recovery = %d\n", *write_recovery);
+
+	mtsdram(SDRAM_MMODE, mmode);
+}
+
+/*-----------------------------------------------------------------------------+
+ * program_rtr.
+ *-----------------------------------------------------------------------------*/
+static void program_rtr(unsigned long *dimm_populated,
+			unsigned char *iic0_dimm_addr,
+			unsigned long num_dimm_banks)
+{
+	PPC4xx_SYS_INFO board_cfg;
+	unsigned long max_refresh_rate;
+	unsigned long dimm_num;
+	unsigned long refresh_rate_type;
+	unsigned long refresh_rate;
+	unsigned long rint;
+	unsigned long sdram_freq;
+	unsigned long sdr_ddrpll;
+	unsigned long val;
+
+	/*------------------------------------------------------------------
+	 * Get the board configuration info.
+	 *-----------------------------------------------------------------*/
+	get_sys_info(&board_cfg);
+
+	/*------------------------------------------------------------------
+	 * Set the SDRAM Refresh Timing Register, SDRAM_RTR
+	 *-----------------------------------------------------------------*/
+	mfsdr(SDR0_DDR0, sdr_ddrpll);
+	sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll));
+
+	max_refresh_rate = 0;
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] != SDRAM_NONE) {
+
+			refresh_rate_type = spd_read(iic0_dimm_addr[dimm_num], 12);
+			refresh_rate_type &= 0x7F;
+			switch (refresh_rate_type) {
+			case 0:
+				refresh_rate =  15625;
+				break;
+			case 1:
+				refresh_rate =   3906;
+				break;
+			case 2:
+				refresh_rate =   7812;
+				break;
+			case 3:
+				refresh_rate =  31250;
+				break;
+			case 4:
+				refresh_rate =  62500;
+				break;
+			case 5:
+				refresh_rate = 125000;
+				break;
+			default:
+				refresh_rate = 0;
+				printf("ERROR: DIMM %d unsupported refresh rate/type.\n",
+				       (unsigned int)dimm_num);
+				printf("Replace the DIMM module with a supported DIMM.\n\n");
+				spd_ddr_init_hang ();
+				break;
+			}
+
+			max_refresh_rate = max(max_refresh_rate, refresh_rate);
+		}
+	}
+
+	rint = MULDIV64(sdram_freq, max_refresh_rate, ONE_BILLION);
+	mfsdram(SDRAM_RTR, val);
+	mtsdram(SDRAM_RTR, (val & ~SDRAM_RTR_RINT_MASK) |
+		(SDRAM_RTR_RINT_ENCODE(rint)));
+}
+
+/*------------------------------------------------------------------
+ * This routine programs the SDRAM_TRx registers.
+ *-----------------------------------------------------------------*/
+static void program_tr(unsigned long *dimm_populated,
+		       unsigned char *iic0_dimm_addr,
+		       unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long sdram_ddr1;
+	unsigned long t_rp_ns;
+	unsigned long t_rcd_ns;
+	unsigned long t_rrd_ns;
+	unsigned long t_ras_ns;
+	unsigned long t_rc_ns;
+	unsigned long t_rfc_ns;
+	unsigned long t_wpc_ns;
+	unsigned long t_wtr_ns;
+	unsigned long t_rpc_ns;
+	unsigned long t_rp_clk;
+	unsigned long t_rcd_clk;
+	unsigned long t_rrd_clk;
+	unsigned long t_ras_clk;
+	unsigned long t_rc_clk;
+	unsigned long t_rfc_clk;
+	unsigned long t_wpc_clk;
+	unsigned long t_wtr_clk;
+	unsigned long t_rpc_clk;
+	unsigned long sdtr1, sdtr2, sdtr3;
+	unsigned long ddr_check;
+	unsigned long sdram_freq;
+	unsigned long sdr_ddrpll;
+
+	PPC4xx_SYS_INFO board_cfg;
+
+	/*------------------------------------------------------------------
+	 * Get the board configuration info.
+	 *-----------------------------------------------------------------*/
+	get_sys_info(&board_cfg);
+
+	mfsdr(SDR0_DDR0, sdr_ddrpll);
+	sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll));
+
+	/*------------------------------------------------------------------
+	 * Handle the timing.  We need to find the worst case timing of all
+	 * the dimm modules installed.
+	 *-----------------------------------------------------------------*/
+	t_rp_ns = 0;
+	t_rrd_ns = 0;
+	t_rcd_ns = 0;
+	t_ras_ns = 0;
+	t_rc_ns = 0;
+	t_rfc_ns = 0;
+	t_wpc_ns = 0;
+	t_wtr_ns = 0;
+	t_rpc_ns = 0;
+	sdram_ddr1 = TRUE;
+
+	/* loop through all the DIMM slots on the board */
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		/* If a dimm is installed in a particular slot ... */
+		if (dimm_populated[dimm_num] != SDRAM_NONE) {
+			if (dimm_populated[dimm_num] == SDRAM_DDR2)
+				sdram_ddr1 = TRUE;
+			else
+				sdram_ddr1 = FALSE;
+
+			t_rcd_ns = max(t_rcd_ns, spd_read(iic0_dimm_addr[dimm_num], 29) >> 2);
+			t_rrd_ns = max(t_rrd_ns, spd_read(iic0_dimm_addr[dimm_num], 28) >> 2);
+			t_rp_ns  = max(t_rp_ns,  spd_read(iic0_dimm_addr[dimm_num], 27) >> 2);
+			t_ras_ns = max(t_ras_ns, spd_read(iic0_dimm_addr[dimm_num], 30));
+			t_rc_ns  = max(t_rc_ns,  spd_read(iic0_dimm_addr[dimm_num], 41));
+			t_rfc_ns = max(t_rfc_ns, spd_read(iic0_dimm_addr[dimm_num], 42));
+		}
+	}
+
+	/*------------------------------------------------------------------
+	 * Set the SDRAM Timing Reg 1, SDRAM_TR1
+	 *-----------------------------------------------------------------*/
+	mfsdram(SDRAM_SDTR1, sdtr1);
+	sdtr1 &= ~(SDRAM_SDTR1_LDOF_MASK | SDRAM_SDTR1_RTW_MASK |
+		   SDRAM_SDTR1_WTWO_MASK | SDRAM_SDTR1_RTRO_MASK);
+
+	/* default values */
+	sdtr1 |= SDRAM_SDTR1_LDOF_2_CLK;
+	sdtr1 |= SDRAM_SDTR1_RTW_2_CLK;
+
+	/* normal operations */
+	sdtr1 |= SDRAM_SDTR1_WTWO_0_CLK;
+	sdtr1 |= SDRAM_SDTR1_RTRO_1_CLK;
+
+	mtsdram(SDRAM_SDTR1, sdtr1);
+
+	/*------------------------------------------------------------------
+	 * Set the SDRAM Timing Reg 2, SDRAM_TR2
+	 *-----------------------------------------------------------------*/
+	mfsdram(SDRAM_SDTR2, sdtr2);
+	sdtr2 &= ~(SDRAM_SDTR2_RCD_MASK  | SDRAM_SDTR2_WTR_MASK |
+		   SDRAM_SDTR2_XSNR_MASK | SDRAM_SDTR2_WPC_MASK |
+		   SDRAM_SDTR2_RPC_MASK  | SDRAM_SDTR2_RP_MASK  |
+		   SDRAM_SDTR2_RRD_MASK);
+
+	/*
+	 * convert t_rcd from nanoseconds to ddr clocks
+	 * round up if necessary
+	 */
+	t_rcd_clk = MULDIV64(sdram_freq, t_rcd_ns, ONE_BILLION);
+	ddr_check = MULDIV64(ONE_BILLION, t_rcd_clk, t_rcd_ns);
+	if (sdram_freq != ddr_check)
+		t_rcd_clk++;
+
+	switch (t_rcd_clk) {
+	case 0:
+	case 1:
+		sdtr2 |= SDRAM_SDTR2_RCD_1_CLK;
+		break;
+	case 2:
+		sdtr2 |= SDRAM_SDTR2_RCD_2_CLK;
+		break;
+	case 3:
+		sdtr2 |= SDRAM_SDTR2_RCD_3_CLK;
+		break;
+	case 4:
+		sdtr2 |= SDRAM_SDTR2_RCD_4_CLK;
+		break;
+	default:
+		sdtr2 |= SDRAM_SDTR2_RCD_5_CLK;
+		break;
+	}
+
+	if (sdram_ddr1 == TRUE) { /* DDR1 */
+		if (sdram_freq < 200000000) {
+			sdtr2 |= SDRAM_SDTR2_WTR_1_CLK;
+			sdtr2 |= SDRAM_SDTR2_WPC_2_CLK;
+			sdtr2 |= SDRAM_SDTR2_RPC_2_CLK;
+		} else {
+			sdtr2 |= SDRAM_SDTR2_WTR_2_CLK;
+			sdtr2 |= SDRAM_SDTR2_WPC_3_CLK;
+			sdtr2 |= SDRAM_SDTR2_RPC_2_CLK;
+		}
+	} else { /* DDR2 */
+		/* loop through all the DIMM slots on the board */
+		for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+			/* If a dimm is installed in a particular slot ... */
+			if (dimm_populated[dimm_num] != SDRAM_NONE) {
+				t_wpc_ns = max(t_wtr_ns, spd_read(iic0_dimm_addr[dimm_num], 36) >> 2);
+				t_wtr_ns = max(t_wtr_ns, spd_read(iic0_dimm_addr[dimm_num], 37) >> 2);
+				t_rpc_ns = max(t_rpc_ns, spd_read(iic0_dimm_addr[dimm_num], 38) >> 2);
+			}
+		}
+
+		/*
+		 * convert from nanoseconds to ddr clocks
+		 * round up if necessary
+		 */
+		t_wpc_clk = MULDIV64(sdram_freq, t_wpc_ns, ONE_BILLION);
+		ddr_check = MULDIV64(ONE_BILLION, t_wpc_clk, t_wpc_ns);
+		if (sdram_freq != ddr_check)
+			t_wpc_clk++;
+
+		switch (t_wpc_clk) {
+		case 0:
+		case 1:
+		case 2:
+			sdtr2 |= SDRAM_SDTR2_WPC_2_CLK;
+			break;
+		case 3:
+			sdtr2 |= SDRAM_SDTR2_WPC_3_CLK;
+			break;
+		case 4:
+			sdtr2 |= SDRAM_SDTR2_WPC_4_CLK;
+			break;
+		case 5:
+			sdtr2 |= SDRAM_SDTR2_WPC_5_CLK;
+			break;
+		default:
+			sdtr2 |= SDRAM_SDTR2_WPC_6_CLK;
+			break;
+		}
+
+		/*
+		 * convert from nanoseconds to ddr clocks
+		 * round up if necessary
+		 */
+		t_wtr_clk = MULDIV64(sdram_freq, t_wtr_ns, ONE_BILLION);
+		ddr_check = MULDIV64(ONE_BILLION, t_wtr_clk, t_wtr_ns);
+		if (sdram_freq != ddr_check)
+			t_wtr_clk++;
+
+		switch (t_wtr_clk) {
+		case 0:
+		case 1:
+			sdtr2 |= SDRAM_SDTR2_WTR_1_CLK;
+			break;
+		case 2:
+			sdtr2 |= SDRAM_SDTR2_WTR_2_CLK;
+			break;
+		case 3:
+			sdtr2 |= SDRAM_SDTR2_WTR_3_CLK;
+			break;
+		default:
+			sdtr2 |= SDRAM_SDTR2_WTR_4_CLK;
+			break;
+		}
+
+		/*
+		 * convert from nanoseconds to ddr clocks
+		 * round up if necessary
+		 */
+		t_rpc_clk = MULDIV64(sdram_freq, t_rpc_ns, ONE_BILLION);
+		ddr_check = MULDIV64(ONE_BILLION, t_rpc_clk, t_rpc_ns);
+		if (sdram_freq != ddr_check)
+			t_rpc_clk++;
+
+		switch (t_rpc_clk) {
+		case 0:
+		case 1:
+		case 2:
+			sdtr2 |= SDRAM_SDTR2_RPC_2_CLK;
+			break;
+		case 3:
+			sdtr2 |= SDRAM_SDTR2_RPC_3_CLK;
+			break;
+		default:
+			sdtr2 |= SDRAM_SDTR2_RPC_4_CLK;
+			break;
+		}
+	}
+
+	/* default value */
+	sdtr2 |= SDRAM_SDTR2_XSNR_16_CLK;
+
+	/*
+	 * convert t_rrd from nanoseconds to ddr clocks
+	 * round up if necessary
+	 */
+	t_rrd_clk = MULDIV64(sdram_freq, t_rrd_ns, ONE_BILLION);
+	ddr_check = MULDIV64(ONE_BILLION, t_rrd_clk, t_rrd_ns);
+	if (sdram_freq != ddr_check)
+		t_rrd_clk++;
+
+	if (t_rrd_clk == 3)
+		sdtr2 |= SDRAM_SDTR2_RRD_3_CLK;
+	else
+		sdtr2 |= SDRAM_SDTR2_RRD_2_CLK;
+
+	/*
+	 * convert t_rp from nanoseconds to ddr clocks
+	 * round up if necessary
+	 */
+	t_rp_clk = MULDIV64(sdram_freq, t_rp_ns, ONE_BILLION);
+	ddr_check = MULDIV64(ONE_BILLION, t_rp_clk, t_rp_ns);
+	if (sdram_freq != ddr_check)
+		t_rp_clk++;
+
+	switch (t_rp_clk) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+		sdtr2 |= SDRAM_SDTR2_RP_3_CLK;
+		break;
+	case 4:
+		sdtr2 |= SDRAM_SDTR2_RP_4_CLK;
+		break;
+	case 5:
+		sdtr2 |= SDRAM_SDTR2_RP_5_CLK;
+		break;
+	case 6:
+		sdtr2 |= SDRAM_SDTR2_RP_6_CLK;
+		break;
+	default:
+		sdtr2 |= SDRAM_SDTR2_RP_7_CLK;
+		break;
+	}
+
+	mtsdram(SDRAM_SDTR2, sdtr2);
+
+	/*------------------------------------------------------------------
+	 * Set the SDRAM Timing Reg 3, SDRAM_TR3
+	 *-----------------------------------------------------------------*/
+	mfsdram(SDRAM_SDTR3, sdtr3);
+	sdtr3 &= ~(SDRAM_SDTR3_RAS_MASK  | SDRAM_SDTR3_RC_MASK |
+		   SDRAM_SDTR3_XCS_MASK | SDRAM_SDTR3_RFC_MASK);
+
+	/*
+	 * convert t_ras from nanoseconds to ddr clocks
+	 * round up if necessary
+	 */
+	t_ras_clk = MULDIV64(sdram_freq, t_ras_ns, ONE_BILLION);
+	ddr_check = MULDIV64(ONE_BILLION, t_ras_clk, t_ras_ns);
+	if (sdram_freq != ddr_check)
+		t_ras_clk++;
+
+	sdtr3 |= SDRAM_SDTR3_RAS_ENCODE(t_ras_clk);
+
+	/*
+	 * convert t_rc from nanoseconds to ddr clocks
+	 * round up if necessary
+	 */
+	t_rc_clk = MULDIV64(sdram_freq, t_rc_ns, ONE_BILLION);
+	ddr_check = MULDIV64(ONE_BILLION, t_rc_clk, t_rc_ns);
+	if (sdram_freq != ddr_check)
+		t_rc_clk++;
+
+	sdtr3 |= SDRAM_SDTR3_RC_ENCODE(t_rc_clk);
+
+	/* default xcs value */
+	sdtr3 |= SDRAM_SDTR3_XCS;
+
+	/*
+	 * convert t_rfc from nanoseconds to ddr clocks
+	 * round up if necessary
+	 */
+	t_rfc_clk = MULDIV64(sdram_freq, t_rfc_ns, ONE_BILLION);
+	ddr_check = MULDIV64(ONE_BILLION, t_rfc_clk, t_rfc_ns);
+	if (sdram_freq != ddr_check)
+		t_rfc_clk++;
+
+	sdtr3 |= SDRAM_SDTR3_RFC_ENCODE(t_rfc_clk);
+
+	mtsdram(SDRAM_SDTR3, sdtr3);
+}
+
+/*-----------------------------------------------------------------------------+
+ * program_bxcf.
+ *-----------------------------------------------------------------------------*/
+static void program_bxcf(unsigned long *dimm_populated,
+			 unsigned char *iic0_dimm_addr,
+			 unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long num_col_addr;
+	unsigned long num_ranks;
+	unsigned long num_banks;
+	unsigned long mode;
+	unsigned long ind_rank;
+	unsigned long ind;
+	unsigned long ind_bank;
+	unsigned long bank_0_populated;
+
+	/*------------------------------------------------------------------
+	 * Set the BxCF regs.  First, wipe out the bank config registers.
+	 *-----------------------------------------------------------------*/
+	mtsdram(SDRAM_MB0CF, 0x00000000);
+	mtsdram(SDRAM_MB1CF, 0x00000000);
+	mtsdram(SDRAM_MB2CF, 0x00000000);
+	mtsdram(SDRAM_MB3CF, 0x00000000);
+
+	mode = SDRAM_BXCF_M_BE_ENABLE;
+
+	bank_0_populated = 0;
+
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] != SDRAM_NONE) {
+			num_col_addr = spd_read(iic0_dimm_addr[dimm_num], 4);
+			num_ranks = spd_read(iic0_dimm_addr[dimm_num], 5);
+			if ((spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08)
+				num_ranks = (num_ranks & 0x0F) +1;
+			else
+				num_ranks = num_ranks & 0x0F;
+
+			num_banks = spd_read(iic0_dimm_addr[dimm_num], 17);
+
+			for (ind_bank = 0; ind_bank < 2; ind_bank++) {
+				if (num_banks == 4)
+					ind = 0;
+				else
+					ind = 5 << 8;
+				switch (num_col_addr) {
+				case 0x08:
+					mode |= (SDRAM_BXCF_M_AM_0 + ind);
+					break;
+				case 0x09:
+					mode |= (SDRAM_BXCF_M_AM_1 + ind);
+					break;
+				case 0x0A:
+					mode |= (SDRAM_BXCF_M_AM_2 + ind);
+					break;
+				case 0x0B:
+					mode |= (SDRAM_BXCF_M_AM_3 + ind);
+					break;
+				case 0x0C:
+					mode |= (SDRAM_BXCF_M_AM_4 + ind);
+					break;
+				default:
+					printf("DDR-SDRAM: DIMM %d BxCF configuration.\n",
+					       (unsigned int)dimm_num);
+					printf("ERROR: Unsupported value for number of "
+					       "column addresses: %d.\n", (unsigned int)num_col_addr);
+					printf("Replace the DIMM module with a supported DIMM.\n\n");
+					spd_ddr_init_hang ();
+				}
+			}
+
+			if ((dimm_populated[dimm_num] != SDRAM_NONE)&& (dimm_num ==1))
+				bank_0_populated = 1;
+
+			for (ind_rank = 0; ind_rank < num_ranks; ind_rank++) {
+				mtsdram(SDRAM_MB0CF +
+					((dimm_num + bank_0_populated + ind_rank) << 2),
+					mode);
+			}
+		}
+	}
+}
+
+/*------------------------------------------------------------------
+ * program memory queue.
+ *-----------------------------------------------------------------*/
+static void program_memory_queue(unsigned long *dimm_populated,
+				 unsigned char *iic0_dimm_addr,
+				 unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	phys_size_t rank_base_addr;
+	unsigned long rank_reg;
+	phys_size_t rank_size_bytes;
+	unsigned long rank_size_id;
+	unsigned long num_ranks;
+	unsigned long baseadd_size;
+	unsigned long i;
+	unsigned long bank_0_populated = 0;
+	phys_size_t total_size = 0;
+
+	/*------------------------------------------------------------------
+	 * Reset the rank_base_address.
+	 *-----------------------------------------------------------------*/
+	rank_reg   = SDRAM_R0BAS;
+
+	rank_base_addr = 0x00000000;
+
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_populated[dimm_num] != SDRAM_NONE) {
+			num_ranks = spd_read(iic0_dimm_addr[dimm_num], 5);
+			if ((spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08)
+				num_ranks = (num_ranks & 0x0F) + 1;
+			else
+				num_ranks = num_ranks & 0x0F;
+
+			rank_size_id = spd_read(iic0_dimm_addr[dimm_num], 31);
+
+			/*------------------------------------------------------------------
+			 * Set the sizes
+			 *-----------------------------------------------------------------*/
+			baseadd_size = 0;
+			switch (rank_size_id) {
+			case 0x01:
+				baseadd_size |= SDRAM_RXBAS_SDSZ_1024;
+				total_size = 1024;
+				break;
+			case 0x02:
+				baseadd_size |= SDRAM_RXBAS_SDSZ_2048;
+				total_size = 2048;
+				break;
+			case 0x04:
+				baseadd_size |= SDRAM_RXBAS_SDSZ_4096;
+				total_size = 4096;
+				break;
+			case 0x08:
+				baseadd_size |= SDRAM_RXBAS_SDSZ_32;
+				total_size = 32;
+				break;
+			case 0x10:
+				baseadd_size |= SDRAM_RXBAS_SDSZ_64;
+				total_size = 64;
+				break;
+			case 0x20:
+				baseadd_size |= SDRAM_RXBAS_SDSZ_128;
+				total_size = 128;
+				break;
+			case 0x40:
+				baseadd_size |= SDRAM_RXBAS_SDSZ_256;
+				total_size = 256;
+				break;
+			case 0x80:
+				baseadd_size |= SDRAM_RXBAS_SDSZ_512;
+				total_size = 512;
+				break;
+			default:
+				printf("DDR-SDRAM: DIMM %d memory queue configuration.\n",
+				       (unsigned int)dimm_num);
+				printf("ERROR: Unsupported value for the banksize: %d.\n",
+				       (unsigned int)rank_size_id);
+				printf("Replace the DIMM module with a supported DIMM.\n\n");
+				spd_ddr_init_hang ();
+			}
+			rank_size_bytes = total_size << 20;
+
+			if ((dimm_populated[dimm_num] != SDRAM_NONE) && (dimm_num == 1))
+				bank_0_populated = 1;
+
+			for (i = 0; i < num_ranks; i++)	{
+				mtdcr_any(rank_reg+i+dimm_num+bank_0_populated,
+					  (SDRAM_RXBAS_SDBA_ENCODE(rank_base_addr) |
+					   baseadd_size));
+				rank_base_addr += rank_size_bytes;
+			}
+		}
+	}
+
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+    defined(CONFIG_460SX)
+	/*
+	 * Enable high bandwidth access
+	 * This is currently not used, but with this setup
+	 * it is possible to use it later on in e.g. the Linux
+	 * EMAC driver for performance gain.
+	 */
+	mtdcr(SDRAM_PLBADDULL, 0x00000000); /* MQ0_BAUL */
+	mtdcr(SDRAM_PLBADDUHB, 0x00000008); /* MQ0_BAUH */
+
+	/*
+	 * Set optimal value for Memory Queue HB/LL Configuration registers
+	 */
+	mtdcr(SDRAM_CONF1HB, (mfdcr(SDRAM_CONF1HB) & ~SDRAM_CONF1HB_MASK) |
+	      SDRAM_CONF1HB_AAFR | SDRAM_CONF1HB_RPEN | SDRAM_CONF1HB_RFTE |
+	      SDRAM_CONF1HB_RPLM | SDRAM_CONF1HB_WRCL);
+	mtdcr(SDRAM_CONF1LL, (mfdcr(SDRAM_CONF1LL) & ~SDRAM_CONF1LL_MASK) |
+	      SDRAM_CONF1LL_AAFR | SDRAM_CONF1LL_RPEN | SDRAM_CONF1LL_RFTE |
+	      SDRAM_CONF1LL_RPLM);
+	mtdcr(SDRAM_CONFPATHB, mfdcr(SDRAM_CONFPATHB) | SDRAM_CONFPATHB_TPEN);
+#endif
+}
+
+#ifdef CONFIG_DDR_ECC
+/*-----------------------------------------------------------------------------+
+ * program_ecc.
+ *-----------------------------------------------------------------------------*/
+static void program_ecc(unsigned long *dimm_populated,
+			unsigned char *iic0_dimm_addr,
+			unsigned long num_dimm_banks,
+			unsigned long tlb_word2_i_value)
+{
+	unsigned long dimm_num;
+	unsigned long ecc;
+
+	ecc = 0;
+	/* loop through all the DIMM slots on the board */
+	for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) {
+		/* If a dimm is installed in a particular slot ... */
+		if (dimm_populated[dimm_num] != SDRAM_NONE)
+			ecc = max(ecc, spd_read(iic0_dimm_addr[dimm_num], 11));
+	}
+	if (ecc == 0)
+		return;
+
+	do_program_ecc(tlb_word2_i_value);
+}
+#endif
+
+#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+/*-----------------------------------------------------------------------------+
+ * program_DQS_calibration.
+ *-----------------------------------------------------------------------------*/
+static void program_DQS_calibration(unsigned long *dimm_populated,
+				    unsigned char *iic0_dimm_addr,
+				    unsigned long num_dimm_banks)
+{
+	unsigned long val;
+
+#ifdef HARD_CODED_DQS /* calibration test with hardvalues */
+	mtsdram(SDRAM_RQDC, 0x80000037);
+	mtsdram(SDRAM_RDCC, 0x40000000);
+	mtsdram(SDRAM_RFDC, 0x000001DF);
+
+	test();
+#else
+	/*------------------------------------------------------------------
+	 * Program RDCC register
+	 * Read sample cycle auto-update enable
+	 *-----------------------------------------------------------------*/
+
+	mfsdram(SDRAM_RDCC, val);
+	mtsdram(SDRAM_RDCC,
+		(val & ~(SDRAM_RDCC_RDSS_MASK | SDRAM_RDCC_RSAE_MASK))
+		| SDRAM_RDCC_RSAE_ENABLE);
+
+	/*------------------------------------------------------------------
+	 * Program RQDC register
+	 * Internal DQS delay mechanism enable
+	 *-----------------------------------------------------------------*/
+	mtsdram(SDRAM_RQDC, (SDRAM_RQDC_RQDE_ENABLE|SDRAM_RQDC_RQFD_ENCODE(0x38)));
+
+	/*------------------------------------------------------------------
+	 * Program RFDC register
+	 * Set Feedback Fractional Oversample
+	 * Auto-detect read sample cycle enable
+	 * Set RFOS to 1/4 of memclk cycle (0x3f)
+	 *-----------------------------------------------------------------*/
+	mfsdram(SDRAM_RFDC, val);
+	mtsdram(SDRAM_RFDC,
+		(val & ~(SDRAM_RFDC_ARSE_MASK | SDRAM_RFDC_RFOS_MASK |
+			 SDRAM_RFDC_RFFD_MASK))
+		| (SDRAM_RFDC_ARSE_ENABLE | SDRAM_RFDC_RFOS_ENCODE(0x3f) |
+		   SDRAM_RFDC_RFFD_ENCODE(0)));
+
+	DQS_calibration_process();
+#endif
+}
+
+static int short_mem_test(void)
+{
+	u32 *membase;
+	u32 bxcr_num;
+	u32 bxcf;
+	int i;
+	int j;
+	phys_size_t base_addr;
+	u32 test[NUMMEMTESTS][NUMMEMWORDS] = {
+		{0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF},
+		{0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},
+		{0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+		 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555},
+		{0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+		 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA},
+		{0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+		 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A},
+		{0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+		 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5},
+		{0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+		 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
+		{0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+		 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55} };
+	int l;
+
+	for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
+		mfsdram(SDRAM_MB0CF + (bxcr_num << 2), bxcf);
+
+		/* Banks enabled */
+		if ((bxcf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) {
+			/* Bank is enabled */
+
+			/*
+			 * Only run test on accessable memory (below 2GB)
+			 */
+			base_addr = SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num));
+			if (base_addr >= CONFIG_MAX_MEM_MAPPED)
+				continue;
+
+			/*------------------------------------------------------------------
+			 * Run the short memory test.
+			 *-----------------------------------------------------------------*/
+			membase = (u32 *)(u32)base_addr;
+
+			for (i = 0; i < NUMMEMTESTS; i++) {
+				for (j = 0; j < NUMMEMWORDS; j++) {
+					membase[j] = test[i][j];
+					ppcDcbf((u32)&(membase[j]));
+				}
+				sync();
+				for (l=0; l<NUMLOOPS; l++) {
+					for (j = 0; j < NUMMEMWORDS; j++) {
+						if (membase[j] != test[i][j]) {
+							ppcDcbf((u32)&(membase[j]));
+							return 0;
+						}
+						ppcDcbf((u32)&(membase[j]));
+					}
+					sync();
+				}
+			}
+		}	/* if bank enabled */
+	}		/* for bxcf_num */
+
+	return 1;
+}
+
+#ifndef HARD_CODED_DQS
+/*-----------------------------------------------------------------------------+
+ * DQS_calibration_process.
+ *-----------------------------------------------------------------------------*/
+static void DQS_calibration_process(void)
+{
+	unsigned long rfdc_reg;
+	unsigned long rffd;
+	unsigned long val;
+	long rffd_average;
+	long max_start;
+	long min_end;
+	unsigned long begin_rqfd[MAXRANKS];
+	unsigned long begin_rffd[MAXRANKS];
+	unsigned long end_rqfd[MAXRANKS];
+	unsigned long end_rffd[MAXRANKS];
+	char window_found;
+	unsigned long dlycal;
+	unsigned long dly_val;
+	unsigned long max_pass_length;
+	unsigned long current_pass_length;
+	unsigned long current_fail_length;
+	unsigned long current_start;
+	long max_end;
+	unsigned char fail_found;
+	unsigned char pass_found;
+#if !defined(CONFIG_DDR_RQDC_FIXED)
+	u32 rqdc_reg;
+	u32 rqfd;
+	u32 rqfd_start;
+	u32 rqfd_average;
+	int loopi = 0;
+	char str[] = "Auto calibration -";
+	char slash[] = "\\|/-\\|/-";
+
+	/*------------------------------------------------------------------
+	 * Test to determine the best read clock delay tuning bits.
+	 *
+	 * Before the DDR controller can be used, the read clock delay needs to be
+	 * set.  This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD].
+	 * This value cannot be hardcoded into the program because it changes
+	 * depending on the board's setup and environment.
+	 * To do this, all delay values are tested to see if they
+	 * work or not.  By doing this, you get groups of fails with groups of
+	 * passing values.  The idea is to find the start and end of a passing
+	 * window and take the center of it to use as the read clock delay.
+	 *
+	 * A failure has to be seen first so that when we hit a pass, we know
+	 * that it is truely the start of the window.  If we get passing values
+	 * to start off with, we don't know if we are at the start of the window.
+	 *
+	 * The code assumes that a failure will always be found.
+	 * If a failure is not found, there is no easy way to get the middle
+	 * of the passing window.  I guess we can pretty much pick any value
+	 * but some values will be better than others.  Since the lowest speed
+	 * we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed),
+	 * from experimentation it is safe to say you will always have a failure.
+	 *-----------------------------------------------------------------*/
+
+	/* first fix RQDC[RQFD] to an average of 80 degre phase shift to find RFDC[RFFD] */
+	rqfd_start = 64; /* test-only: don't know if this is the _best_ start value */
+
+	puts(str);
+
+calibration_loop:
+	mfsdram(SDRAM_RQDC, rqdc_reg);
+	mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
+		SDRAM_RQDC_RQFD_ENCODE(rqfd_start));
+#else /* CONFIG_DDR_RQDC_FIXED */
+	/*
+	 * On Katmai the complete auto-calibration somehow doesn't seem to
+	 * produce the best results, meaning optimal values for RQFD/RFFD.
+	 * This was discovered by GDA using a high bandwidth scope,
+	 * analyzing the DDR2 signals. GDA provided a fixed value for RQFD,
+	 * so now on Katmai "only" RFFD is auto-calibrated.
+	 */
+	mtsdram(SDRAM_RQDC, CONFIG_DDR_RQDC_FIXED);
+#endif /* CONFIG_DDR_RQDC_FIXED */
+
+	max_start = 0;
+	min_end = 0;
+	begin_rqfd[0] = 0;
+	begin_rffd[0] = 0;
+	begin_rqfd[1] = 0;
+	begin_rffd[1] = 0;
+	end_rqfd[0] = 0;
+	end_rffd[0] = 0;
+	end_rqfd[1] = 0;
+	end_rffd[1] = 0;
+	window_found = FALSE;
+
+	max_pass_length = 0;
+	max_start = 0;
+	max_end = 0;
+	current_pass_length = 0;
+	current_fail_length = 0;
+	current_start = 0;
+	window_found = FALSE;
+	fail_found = FALSE;
+	pass_found = FALSE;
+
+	/*
+	 * get the delay line calibration register value
+	 */
+	mfsdram(SDRAM_DLCR, dlycal);
+	dly_val = SDRAM_DLYCAL_DLCV_DECODE(dlycal) << 2;
+
+	for (rffd = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
+		mfsdram(SDRAM_RFDC, rfdc_reg);
+		rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
+
+		/*------------------------------------------------------------------
+		 * Set the timing reg for the test.
+		 *-----------------------------------------------------------------*/
+		mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
+
+		/*------------------------------------------------------------------
+		 * See if the rffd value passed.
+		 *-----------------------------------------------------------------*/
+		if (short_mem_test()) {
+			if (fail_found == TRUE) {
+				pass_found = TRUE;
+				if (current_pass_length == 0)
+					current_start = rffd;
+
+				current_fail_length = 0;
+				current_pass_length++;
+
+				if (current_pass_length > max_pass_length) {
+					max_pass_length = current_pass_length;
+					max_start = current_start;
+					max_end = rffd;
+				}
+			}
+		} else {
+			current_pass_length = 0;
+			current_fail_length++;
+
+			if (current_fail_length >= (dly_val >> 2)) {
+				if (fail_found == FALSE) {
+					fail_found = TRUE;
+				} else if (pass_found == TRUE) {
+					window_found = TRUE;
+					break;
+				}
+			}
+		}
+	}		/* for rffd */
+
+	/*------------------------------------------------------------------
+	 * Set the average RFFD value
+	 *-----------------------------------------------------------------*/
+	rffd_average = ((max_start + max_end) >> 1);
+
+	if (rffd_average < 0)
+		rffd_average = 0;
+
+	if (rffd_average > SDRAM_RFDC_RFFD_MAX)
+		rffd_average = SDRAM_RFDC_RFFD_MAX;
+	/* now fix RFDC[RFFD] found and find RQDC[RQFD] */
+	mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
+
+#if !defined(CONFIG_DDR_RQDC_FIXED)
+	max_pass_length = 0;
+	max_start = 0;
+	max_end = 0;
+	current_pass_length = 0;
+	current_fail_length = 0;
+	current_start = 0;
+	window_found = FALSE;
+	fail_found = FALSE;
+	pass_found = FALSE;
+
+	for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
+		mfsdram(SDRAM_RQDC, rqdc_reg);
+		rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
+
+		/*------------------------------------------------------------------
+		 * Set the timing reg for the test.
+		 *-----------------------------------------------------------------*/
+		mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
+
+		/*------------------------------------------------------------------
+		 * See if the rffd value passed.
+		 *-----------------------------------------------------------------*/
+		if (short_mem_test()) {
+			if (fail_found == TRUE) {
+				pass_found = TRUE;
+				if (current_pass_length == 0)
+					current_start = rqfd;
+
+				current_fail_length = 0;
+				current_pass_length++;
+
+				if (current_pass_length > max_pass_length) {
+					max_pass_length = current_pass_length;
+					max_start = current_start;
+					max_end = rqfd;
+				}
+			}
+		} else {
+			current_pass_length = 0;
+			current_fail_length++;
+
+			if (fail_found == FALSE) {
+				fail_found = TRUE;
+			} else if (pass_found == TRUE) {
+				window_found = TRUE;
+				break;
+			}
+		}
+	}
+
+	rqfd_average = ((max_start + max_end) >> 1);
+
+	/*------------------------------------------------------------------
+	 * Make sure we found the valid read passing window.  Halt if not
+	 *-----------------------------------------------------------------*/
+	if (window_found == FALSE) {
+		if (rqfd_start < SDRAM_RQDC_RQFD_MAX) {
+			putc('\b');
+			putc(slash[loopi++ % 8]);
+
+			/* try again from with a different RQFD start value */
+			rqfd_start++;
+			goto calibration_loop;
+		}
+
+		printf("\nERROR: Cannot determine a common read delay for the "
+		       "DIMM(s) installed.\n");
+		debug("%s[%d] ERROR : \n", __FUNCTION__,__LINE__);
+		ppc4xx_ibm_ddr2_register_dump();
+		spd_ddr_init_hang ();
+	}
+
+	if (rqfd_average < 0)
+		rqfd_average = 0;
+
+	if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
+		rqfd_average = SDRAM_RQDC_RQFD_MAX;
+
+	mtsdram(SDRAM_RQDC,
+		(rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
+		SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
+
+	blank_string(strlen(str));
+#endif /* CONFIG_DDR_RQDC_FIXED */
+
+	/*
+	 * Now complete RDSS configuration as mentioned on page 7 of the AMCC
+	 * PowerPC440SP/SPe DDR2 application note:
+	 * "DDR1/DDR2 Initialization Sequence and Dynamic Tuning"
+	 */
+	mfsdram(SDRAM_RTSR, val);
+	if ((val & SDRAM_RTSR_TRK1SM_MASK) == SDRAM_RTSR_TRK1SM_ATPLS1) {
+		mfsdram(SDRAM_RDCC, val);
+		if ((val & SDRAM_RDCC_RDSS_MASK) != SDRAM_RDCC_RDSS_T4) {
+			val += 0x40000000;
+			mtsdram(SDRAM_RDCC, val);
+		}
+	}
+
+	mfsdram(SDRAM_DLCR, val);
+	debug("%s[%d] DLCR: 0x%08lX\n", __FUNCTION__, __LINE__, val);
+	mfsdram(SDRAM_RQDC, val);
+	debug("%s[%d] RQDC: 0x%08lX\n", __FUNCTION__, __LINE__, val);
+	mfsdram(SDRAM_RFDC, val);
+	debug("%s[%d] RFDC: 0x%08lX\n", __FUNCTION__, __LINE__, val);
+	mfsdram(SDRAM_RDCC, val);
+	debug("%s[%d] RDCC: 0x%08lX\n", __FUNCTION__, __LINE__, val);
+}
+#else /* calibration test with hardvalues */
+/*-----------------------------------------------------------------------------+
+ * DQS_calibration_process.
+ *-----------------------------------------------------------------------------*/
+static void test(void)
+{
+	unsigned long dimm_num;
+	unsigned long ecc_temp;
+	unsigned long i, j;
+	unsigned long *membase;
+	unsigned long bxcf[MAXRANKS];
+	unsigned long val;
+	char window_found;
+	char begin_found[MAXDIMMS];
+	char end_found[MAXDIMMS];
+	char search_end[MAXDIMMS];
+	unsigned long test[NUMMEMTESTS][NUMMEMWORDS] = {
+		{0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF},
+		{0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},
+		{0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+		 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555},
+		{0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+		 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA},
+		{0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+		 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A},
+		{0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+		 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5},
+		{0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+		 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
+		{0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+		 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55} };
+
+	/*------------------------------------------------------------------
+	 * Test to determine the best read clock delay tuning bits.
+	 *
+	 * Before the DDR controller can be used, the read clock delay needs to be
+	 * set.  This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD].
+	 * This value cannot be hardcoded into the program because it changes
+	 * depending on the board's setup and environment.
+	 * To do this, all delay values are tested to see if they
+	 * work or not.  By doing this, you get groups of fails with groups of
+	 * passing values.  The idea is to find the start and end of a passing
+	 * window and take the center of it to use as the read clock delay.
+	 *
+	 * A failure has to be seen first so that when we hit a pass, we know
+	 * that it is truely the start of the window.  If we get passing values
+	 * to start off with, we don't know if we are at the start of the window.
+	 *
+	 * The code assumes that a failure will always be found.
+	 * If a failure is not found, there is no easy way to get the middle
+	 * of the passing window.  I guess we can pretty much pick any value
+	 * but some values will be better than others.  Since the lowest speed
+	 * we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed),
+	 * from experimentation it is safe to say you will always have a failure.
+	 *-----------------------------------------------------------------*/
+	mfsdram(SDRAM_MCOPT1, ecc_temp);
+	ecc_temp &= SDRAM_MCOPT1_MCHK_MASK;
+	mfsdram(SDRAM_MCOPT1, val);
+	mtsdram(SDRAM_MCOPT1, (val & ~SDRAM_MCOPT1_MCHK_MASK) |
+		SDRAM_MCOPT1_MCHK_NON);
+
+	window_found = FALSE;
+	begin_found[0] = FALSE;
+	end_found[0] = FALSE;
+	search_end[0] = FALSE;
+	begin_found[1] = FALSE;
+	end_found[1] = FALSE;
+	search_end[1] = FALSE;
+
+	for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) {
+		mfsdram(SDRAM_MB0CF + (bxcr_num << 2), bxcf[bxcr_num]);
+
+		/* Banks enabled */
+		if ((bxcf[dimm_num] & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) {
+
+			/* Bank is enabled */
+			membase =
+				(unsigned long*)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+dimm_num)));
+
+			/*------------------------------------------------------------------
+			 * Run the short memory test.
+			 *-----------------------------------------------------------------*/
+			for (i = 0; i < NUMMEMTESTS; i++) {
+				for (j = 0; j < NUMMEMWORDS; j++) {
+					membase[j] = test[i][j];
+					ppcDcbf((u32)&(membase[j]));
+				}
+				sync();
+				for (j = 0; j < NUMMEMWORDS; j++) {
+					if (membase[j] != test[i][j]) {
+						ppcDcbf((u32)&(membase[j]));
+						break;
+					}
+					ppcDcbf((u32)&(membase[j]));
+				}
+				sync();
+				if (j < NUMMEMWORDS)
+					break;
+			}
+
+			/*------------------------------------------------------------------
+			 * See if the rffd value passed.
+			 *-----------------------------------------------------------------*/
+			if (i < NUMMEMTESTS) {
+				if ((end_found[dimm_num] == FALSE) &&
+				    (search_end[dimm_num] == TRUE)) {
+					end_found[dimm_num] = TRUE;
+				}
+				if ((end_found[0] == TRUE) &&
+				    (end_found[1] == TRUE))
+					break;
+			} else {
+				if (begin_found[dimm_num] == FALSE) {
+					begin_found[dimm_num] = TRUE;
+					search_end[dimm_num] = TRUE;
+				}
+			}
+		} else {
+			begin_found[dimm_num] = TRUE;
+			end_found[dimm_num] = TRUE;
+		}
+	}
+
+	if ((begin_found[0] == TRUE) && (begin_found[1] == TRUE))
+		window_found = TRUE;
+
+	/*------------------------------------------------------------------
+	 * Make sure we found the valid read passing window.  Halt if not
+	 *-----------------------------------------------------------------*/
+	if (window_found == FALSE) {
+		printf("ERROR: Cannot determine a common read delay for the "
+		       "DIMM(s) installed.\n");
+		spd_ddr_init_hang ();
+	}
+
+	/*------------------------------------------------------------------
+	 * Restore the ECC variable to what it originally was
+	 *-----------------------------------------------------------------*/
+	mtsdram(SDRAM_MCOPT1,
+		(ppcMfdcr_sdram(SDRAM_MCOPT1) & ~SDRAM_MCOPT1_MCHK_MASK)
+		| ecc_temp);
+}
+#endif /* !HARD_CODED_DQS */
+#endif /* !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) */
+
+#else /* CONFIG_SPD_EEPROM */
+
+/*-----------------------------------------------------------------------------
+ * Function:	initdram
+ * Description: Configures the PPC4xx IBM DDR1/DDR2 SDRAM memory controller.
+ * 		The configuration is performed using static, compile-
+ *		time parameters.
+ * 		Configures the PPC405EX(r) and PPC460EX/GT
+ *---------------------------------------------------------------------------*/
+phys_size_t initdram(int board_type)
+{
+	/*
+	 * Only run this SDRAM init code once. For NAND booting
+	 * targets like Kilauea, we call initdram() early from the
+	 * 4k NAND booting image (CONFIG_NAND_SPL) from nand_boot().
+	 * Later on the NAND U-Boot image runs (CONFIG_NAND_U_BOOT)
+	 * which calls initdram() again. This time the controller
+	 * mustn't be reconfigured again since we're already running
+	 * from SDRAM.
+	 */
+#if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL)
+	unsigned long val;
+
+#if defined(CONFIG_440)
+	mtdcr(SDRAM_R0BAS,	CONFIG_SYS_SDRAM_R0BAS);
+	mtdcr(SDRAM_R1BAS,	CONFIG_SYS_SDRAM_R1BAS);
+	mtdcr(SDRAM_R2BAS,	CONFIG_SYS_SDRAM_R2BAS);
+	mtdcr(SDRAM_R3BAS,	CONFIG_SYS_SDRAM_R3BAS);
+	mtdcr(SDRAM_PLBADDULL,	CONFIG_SYS_SDRAM_PLBADDULL);	/* MQ0_BAUL */
+	mtdcr(SDRAM_PLBADDUHB,	CONFIG_SYS_SDRAM_PLBADDUHB);	/* MQ0_BAUH */
+	mtdcr(SDRAM_CONF1LL,	CONFIG_SYS_SDRAM_CONF1LL);
+	mtdcr(SDRAM_CONF1HB,	CONFIG_SYS_SDRAM_CONF1HB);
+	mtdcr(SDRAM_CONFPATHB,	CONFIG_SYS_SDRAM_CONFPATHB);
+#endif
+
+	/* Set Memory Bank Configuration Registers */
+
+	mtsdram(SDRAM_MB0CF, CONFIG_SYS_SDRAM0_MB0CF);
+	mtsdram(SDRAM_MB1CF, CONFIG_SYS_SDRAM0_MB1CF);
+	mtsdram(SDRAM_MB2CF, CONFIG_SYS_SDRAM0_MB2CF);
+	mtsdram(SDRAM_MB3CF, CONFIG_SYS_SDRAM0_MB3CF);
+
+	/* Set Memory Clock Timing Register */
+
+	mtsdram(SDRAM_CLKTR, CONFIG_SYS_SDRAM0_CLKTR);
+
+	/* Set Refresh Time Register */
+
+	mtsdram(SDRAM_RTR, CONFIG_SYS_SDRAM0_RTR);
+
+	/* Set SDRAM Timing Registers */
+
+	mtsdram(SDRAM_SDTR1, CONFIG_SYS_SDRAM0_SDTR1);
+	mtsdram(SDRAM_SDTR2, CONFIG_SYS_SDRAM0_SDTR2);
+	mtsdram(SDRAM_SDTR3, CONFIG_SYS_SDRAM0_SDTR3);
+
+	/* Set Mode and Extended Mode Registers */
+
+	mtsdram(SDRAM_MMODE, CONFIG_SYS_SDRAM0_MMODE);
+	mtsdram(SDRAM_MEMODE, CONFIG_SYS_SDRAM0_MEMODE);
+
+	/* Set Memory Controller Options 1 Register */
+
+	mtsdram(SDRAM_MCOPT1, CONFIG_SYS_SDRAM0_MCOPT1);
+
+	/* Set Manual Initialization Control Registers */
+
+	mtsdram(SDRAM_INITPLR0, CONFIG_SYS_SDRAM0_INITPLR0);
+	mtsdram(SDRAM_INITPLR1, CONFIG_SYS_SDRAM0_INITPLR1);
+	mtsdram(SDRAM_INITPLR2, CONFIG_SYS_SDRAM0_INITPLR2);
+	mtsdram(SDRAM_INITPLR3, CONFIG_SYS_SDRAM0_INITPLR3);
+	mtsdram(SDRAM_INITPLR4, CONFIG_SYS_SDRAM0_INITPLR4);
+	mtsdram(SDRAM_INITPLR5, CONFIG_SYS_SDRAM0_INITPLR5);
+	mtsdram(SDRAM_INITPLR6, CONFIG_SYS_SDRAM0_INITPLR6);
+	mtsdram(SDRAM_INITPLR7, CONFIG_SYS_SDRAM0_INITPLR7);
+	mtsdram(SDRAM_INITPLR8, CONFIG_SYS_SDRAM0_INITPLR8);
+	mtsdram(SDRAM_INITPLR9, CONFIG_SYS_SDRAM0_INITPLR9);
+	mtsdram(SDRAM_INITPLR10, CONFIG_SYS_SDRAM0_INITPLR10);
+	mtsdram(SDRAM_INITPLR11, CONFIG_SYS_SDRAM0_INITPLR11);
+	mtsdram(SDRAM_INITPLR12, CONFIG_SYS_SDRAM0_INITPLR12);
+	mtsdram(SDRAM_INITPLR13, CONFIG_SYS_SDRAM0_INITPLR13);
+	mtsdram(SDRAM_INITPLR14, CONFIG_SYS_SDRAM0_INITPLR14);
+	mtsdram(SDRAM_INITPLR15, CONFIG_SYS_SDRAM0_INITPLR15);
+
+	/* Set On-Die Termination Registers */
+
+	mtsdram(SDRAM_CODT, CONFIG_SYS_SDRAM0_CODT);
+	mtsdram(SDRAM_MODT0, CONFIG_SYS_SDRAM0_MODT0);
+	mtsdram(SDRAM_MODT1, CONFIG_SYS_SDRAM0_MODT1);
+
+	/* Set Write Timing Register */
+
+	mtsdram(SDRAM_WRDTR, CONFIG_SYS_SDRAM0_WRDTR);
+
+	/*
+	 * Start Initialization by SDRAM0_MCOPT2[SREN] = 0 and
+	 * SDRAM0_MCOPT2[IPTR] = 1
+	 */
+
+	mtsdram(SDRAM_MCOPT2, (SDRAM_MCOPT2_SREN_EXIT |
+			       SDRAM_MCOPT2_IPTR_EXECUTE));
+
+	/*
+	 * Poll SDRAM0_MCSTAT[MIC] for assertion to indicate the
+	 * completion of initialization.
+	 */
+
+	do {
+		mfsdram(SDRAM_MCSTAT, val);
+	} while ((val & SDRAM_MCSTAT_MIC_MASK) != SDRAM_MCSTAT_MIC_COMP);
+
+	/* Set Delay Control Registers */
+
+	mtsdram(SDRAM_DLCR, CONFIG_SYS_SDRAM0_DLCR);
+
+#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+	mtsdram(SDRAM_RDCC, CONFIG_SYS_SDRAM0_RDCC);
+	mtsdram(SDRAM_RQDC, CONFIG_SYS_SDRAM0_RQDC);
+	mtsdram(SDRAM_RFDC, CONFIG_SYS_SDRAM0_RFDC);
+#endif /* !CONFIG_PPC4xx_DDR_AUTOCALIBRATION */
+
+	/*
+	 * Enable Controller by SDRAM0_MCOPT2[DCEN] = 1:
+	 */
+
+	mfsdram(SDRAM_MCOPT2, val);
+	mtsdram(SDRAM_MCOPT2, val | SDRAM_MCOPT2_DCEN_ENABLE);
+
+#if defined(CONFIG_440)
+	/*
+	 * Program TLB entries with caches enabled, for best performace
+	 * while auto-calibrating and ECC generation
+	 */
+	program_tlb(0, 0, (CONFIG_SYS_MBYTES_SDRAM << 20), 0);
+#endif
+
+#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+	/*------------------------------------------------------------------
+	 | DQS calibration.
+	 +-----------------------------------------------------------------*/
+	DQS_autocalibration();
+#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */
+#endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */
+
+#if defined(CONFIG_DDR_ECC)
+	do_program_ecc(0);
+#endif /* defined(CONFIG_DDR_ECC) */
+
+#if defined(CONFIG_440)
+	/*
+	 * Now after initialization (auto-calibration and ECC generation)
+	 * remove the TLB entries with caches enabled and program again with
+	 * desired cache functionality
+	 */
+	remove_tlb(0, (CONFIG_SYS_MBYTES_SDRAM << 20));
+	program_tlb(0, 0, (CONFIG_SYS_MBYTES_SDRAM << 20), MY_TLB_WORD2_I_ENABLE);
+#endif
+
+	ppc4xx_ibm_ddr2_register_dump();
+
+#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+	/*
+	 * Clear potential errors resulting from auto-calibration.
+	 * If not done, then we could get an interrupt later on when
+	 * exceptions are enabled.
+	 */
+	set_mcsr(get_mcsr());
+#endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */
+
+#endif /* !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */
+
+	return (CONFIG_SYS_MBYTES_SDRAM << 20);
+}
+#endif /* CONFIG_SPD_EEPROM */
+
+#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+#if defined(CONFIG_440)
+u32 mfdcr_any(u32 dcr)
+{
+	u32 val;
+
+	switch (dcr) {
+	case SDRAM_R0BAS + 0:
+		val = mfdcr(SDRAM_R0BAS + 0);
+		break;
+	case SDRAM_R0BAS + 1:
+		val = mfdcr(SDRAM_R0BAS + 1);
+		break;
+	case SDRAM_R0BAS + 2:
+		val = mfdcr(SDRAM_R0BAS + 2);
+		break;
+	case SDRAM_R0BAS + 3:
+		val = mfdcr(SDRAM_R0BAS + 3);
+		break;
+	default:
+		printf("DCR %d not defined in case statement!!!\n", dcr);
+		val = 0; /* just to satisfy the compiler */
+	}
+
+	return val;
+}
+
+void mtdcr_any(u32 dcr, u32 val)
+{
+	switch (dcr) {
+	case SDRAM_R0BAS + 0:
+		mtdcr(SDRAM_R0BAS + 0, val);
+		break;
+	case SDRAM_R0BAS + 1:
+		mtdcr(SDRAM_R0BAS + 1, val);
+		break;
+	case SDRAM_R0BAS + 2:
+		mtdcr(SDRAM_R0BAS + 2, val);
+		break;
+	case SDRAM_R0BAS + 3:
+		mtdcr(SDRAM_R0BAS + 3, val);
+		break;
+	default:
+		printf("DCR %d not defined in case statement!!!\n", dcr);
+	}
+}
+#endif /* defined(CONFIG_440) */
+#endif /* !defined(CONFIG_NAND_U_BOOT) &&  !defined(CONFIG_NAND_SPL) */
+
+inline void ppc4xx_ibm_ddr2_register_dump(void)
+{
+#if defined(DEBUG)
+	printf("\nPPC4xx IBM DDR2 Register Dump:\n");
+
+#if (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+     defined(CONFIG_460EX) || defined(CONFIG_460GT))
+	PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(R0BAS);
+	PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(R1BAS);
+	PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(R2BAS);
+	PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(R3BAS);
+#endif /* (defined(CONFIG_440SP) || ... */
+#if defined(CONFIG_405EX)
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(BESR);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(BEARL);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(BEARH);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(WMIRQ);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(PLBOPT);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(PUABA);
+#endif /* defined(CONFIG_405EX) */
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(MB0CF);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(MB1CF);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(MB2CF);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(MB3CF);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(MCSTAT);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(MCOPT1);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(MCOPT2);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT0);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT1);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT2);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT3);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(CODT);
+#if (defined(CONFIG_440SP) || defined(CONFIG_440SPE) ||	\
+     defined(CONFIG_460EX) || defined(CONFIG_460GT))
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(VVPR);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(OPARS);
+	/*
+	 * OPART is only used as a trigger register.
+	 *
+	 * No data is contained in this register, and reading or writing
+	 * to is can cause bad things to happen (hangs). Just skip it and
+	 * report "N/A".
+	 */
+	printf("%20s = N/A\n", "SDRAM_OPART");
+#endif /* defined(CONFIG_440SP) || ... */
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(RTR);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR0);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR1);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR2);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR3);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR4);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR5);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR6);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR7);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR8);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR9);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR10);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR11);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR12);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR13);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR14);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR15);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(RQDC);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(RFDC);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(RDCC);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(DLCR);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(CLKTR);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(WRDTR);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(SDTR1);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(SDTR2);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(SDTR3);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(MMODE);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(MEMODE);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(ECCES);
+#if (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+     defined(CONFIG_460EX) || defined(CONFIG_460GT))
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(CID);
+#endif /* defined(CONFIG_440SP) || ... */
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(RID);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(FCSR);
+	PPC4xx_IBM_DDR2_DUMP_REGISTER(RTSR);
+#endif /* defined(DEBUG) */
+}
+
+#endif /* CONFIG_SDRAM_PPC4xx_IBM_DDR2 */
diff --git a/arch/powerpc/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c b/arch/powerpc/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
new file mode 100644
index 0000000..aed0ed7
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
@@ -0,0 +1,1251 @@
+/*
+ * arch/powerpc/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
+ * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a
+ * DDR2 controller (non Denali Core). Those currently are:
+ *
+ * 405:		405EX
+ * 440/460:	440SP/440SPe/460EX/460GT/460SX
+ *
+ * (C) Copyright 2008 Applied Micro Circuits Corporation
+ * Adam Graham  <agraham@amcc.com>
+ *
+ * (C) Copyright 2007-2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * COPYRIGHT   AMCC   CORPORATION 2004
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#undef DEBUG
+
+#include <common.h>
+#include <ppc4xx.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+#include "ecc.h"
+
+#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+
+/*
+ * Only compile the DDR auto-calibration code for NOR boot and
+ * not for NAND boot (NAND SPL and NAND U-Boot - NUB)
+ */
+#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+
+#define MAXBXCF			4
+#define SDRAM_RXBAS_SHIFT_1M	20
+
+#if defined(CONFIG_SYS_DECREMENT_PATTERNS)
+#define NUMMEMTESTS		24
+#else
+#define NUMMEMTESTS		8
+#endif /* CONFIG_SYS_DECREMENT_PATTERNS */
+#define NUMLOOPS		1	/* configure as you deem approporiate */
+#define NUMMEMWORDS		16
+
+#define SDRAM_RDCC_RDSS_VAL(n)	SDRAM_RDCC_RDSS_DECODE(ddr_rdss_opt(n))
+
+/* Private Structure Definitions */
+
+struct autocal_regs {
+	u32 rffd;
+	u32 rqfd;
+};
+
+struct ddrautocal {
+	u32 rffd;
+	u32 rffd_min;
+	u32 rffd_max;
+	u32 rffd_size;
+	u32 rqfd;
+	u32 rqfd_size;
+	u32 rdcc;
+	u32 flags;
+};
+
+struct sdram_timing {
+	u32 wrdtr;
+	u32 clktr;
+};
+
+struct sdram_timing_clks {
+	u32 wrdtr;
+	u32 clktr;
+	u32 rdcc;
+	u32 flags;
+};
+
+struct autocal_clks {
+	struct sdram_timing_clks clocks;
+	struct ddrautocal	 autocal;
+};
+
+/*--------------------------------------------------------------------------+
+ * Prototypes
+ *--------------------------------------------------------------------------*/
+#if defined(CONFIG_PPC4xx_DDR_METHOD_A)
+static u32 DQS_calibration_methodA(struct ddrautocal *);
+static u32 program_DQS_calibration_methodA(struct ddrautocal *);
+#else
+static u32 DQS_calibration_methodB(struct ddrautocal *);
+static u32 program_DQS_calibration_methodB(struct ddrautocal *);
+#endif
+static int short_mem_test(u32 *);
+
+/*
+ * To provide an interface for board specific config values in this common
+ * DDR setup code, we implement he "weak" default functions here. They return
+ * the default value back to the caller.
+ *
+ * Please see include/configs/yucca.h for an example fora board specific
+ * implementation.
+ */
+
+#if !defined(CONFIG_SPD_EEPROM)
+u32 __ddr_wrdtr(u32 default_val)
+{
+	return default_val;
+}
+u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr")));
+
+u32 __ddr_clktr(u32 default_val)
+{
+	return default_val;
+}
+u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr")));
+
+/*
+ * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed
+ */
+void __spd_ddr_init_hang(void)
+{
+	hang();
+}
+void
+spd_ddr_init_hang(void) __attribute__((weak, alias("__spd_ddr_init_hang")));
+#endif /* defined(CONFIG_SPD_EEPROM) */
+
+ulong __ddr_scan_option(ulong default_val)
+{
+	return default_val;
+}
+ulong ddr_scan_option(ulong) __attribute__((weak, alias("__ddr_scan_option")));
+
+u32 __ddr_rdss_opt(u32 default_val)
+{
+	return default_val;
+}
+u32 ddr_rdss_opt(ulong) __attribute__((weak, alias("__ddr_rdss_opt")));
+
+
+static u32 *get_membase(int bxcr_num)
+{
+	ulong bxcf;
+	u32 *membase;
+
+#if defined(SDRAM_R0BAS)
+	/* BAS from Memory Queue rank reg. */
+	membase =
+	    (u32 *)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num)));
+	bxcf = 0;	/* just to satisfy the compiler */
+#else
+	/* BAS from SDRAM_MBxCF mem rank reg. */
+	mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
+	membase = (u32 *)((bxcf & 0xfff80000) << 3);
+#endif
+
+	return membase;
+}
+
+static inline void ecc_clear_status_reg(void)
+{
+	mtsdram(SDRAM_ECCES, 0xffffffff);
+#if defined(SDRAM_R0BAS)
+	mtdcr(SDRAM_ERRSTATLL, 0xffffffff);
+#endif
+}
+
+/*
+ * Reset and relock memory DLL after SDRAM_CLKTR change
+ */
+static inline void relock_memory_DLL(void)
+{
+	u32 reg;
+
+	mtsdram(SDRAM_MCOPT2, SDRAM_MCOPT2_IPTR_EXECUTE);
+
+	do {
+		mfsdram(SDRAM_MCSTAT, reg);
+	} while (!(reg & SDRAM_MCSTAT_MIC_COMP));
+
+	mfsdram(SDRAM_MCOPT2, reg);
+	mtsdram(SDRAM_MCOPT2, reg | SDRAM_MCOPT2_DCEN_ENABLE);
+}
+
+static int ecc_check_status_reg(void)
+{
+	u32 ecc_status;
+
+	/*
+	 * Compare suceeded, now check
+	 * if got ecc error. If got an
+	 * ecc error, then don't count
+	 * this as a passing value
+	 */
+	mfsdram(SDRAM_ECCES, ecc_status);
+	if (ecc_status != 0x00000000) {
+		/* clear on error */
+		ecc_clear_status_reg();
+		/* ecc check failure */
+		return 0;
+	}
+	ecc_clear_status_reg();
+	sync();
+
+	return 1;
+}
+
+/* return 1 if passes, 0 if fail */
+static int short_mem_test(u32 *base_address)
+{
+	int i, j, l;
+	u32 ecc_mode = 0;
+
+	ulong test[NUMMEMTESTS][NUMMEMWORDS] = {
+	/* 0 */	{0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF},
+	/* 1 */	{0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},
+	/* 2 */	{0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+		 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+		 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+		 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555},
+	/* 3 */	{0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+		 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+		 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+		 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA},
+	/* 4 */	{0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+		 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+		 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+		 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A},
+	/* 5 */	{0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+		 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+		 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+		 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5},
+	/* 6 */	{0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+		 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+		 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+		 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
+	/* 7 */	{0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+		 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+		 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+		 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55},
+
+#if defined(CONFIG_SYS_DECREMENT_PATTERNS)
+	/* 8 */	{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+		 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+		 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+		 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff},
+	/* 9 */	{0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
+		 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
+		 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
+		 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe},
+	/* 10 */{0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
+		 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
+		 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
+		 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd},
+	/* 11 */{0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
+		 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
+		 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
+		 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc},
+	/* 12 */{0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
+		 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
+		 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
+		 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb},
+	/* 13 */{0xfffafffa, 0xfffafffa, 0xfffffffa, 0xfffafffa,
+		 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa,
+		 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa,
+		 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa},
+	/* 14 */{0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
+		 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
+		 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
+		 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9},
+	/* 15 */{0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
+		 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
+		 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
+		 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8},
+	/* 16 */{0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
+		 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
+		 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
+		 0xfff7ffff, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7},
+	/* 17 */{0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
+		 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
+		 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
+		 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7},
+	/* 18 */{0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
+		 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
+		 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
+		 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5},
+	/* 19 */{0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
+		 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
+		 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
+		 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4},
+	/* 20 */{0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
+		 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
+		 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
+		 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3},
+	/* 21 */{0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
+		 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
+		 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
+		 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2},
+	/* 22 */{0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
+		 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
+		 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
+		 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1},
+	/* 23 */{0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
+		 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
+		 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
+		 0xfff0fff0, 0xfff0fffe, 0xfff0fff0, 0xfff0fff0},
+#endif /* CONFIG_SYS_DECREMENT_PATTERNS */
+								 };
+
+	mfsdram(SDRAM_MCOPT1, ecc_mode);
+	if ((ecc_mode & SDRAM_MCOPT1_MCHK_CHK_REP) ==
+						SDRAM_MCOPT1_MCHK_CHK_REP) {
+		ecc_clear_status_reg();
+		sync();
+		ecc_mode = 1;
+	} else {
+		ecc_mode = 0;
+	}
+
+	/*
+	 * Run the short memory test.
+	 */
+	for (i = 0; i < NUMMEMTESTS; i++) {
+		for (j = 0; j < NUMMEMWORDS; j++) {
+			base_address[j] = test[i][j];
+			ppcDcbf((ulong)&(base_address[j]));
+		}
+		sync();
+		iobarrier_rw();
+		for (l = 0; l < NUMLOOPS; l++) {
+			for (j = 0; j < NUMMEMWORDS; j++) {
+				if (base_address[j] != test[i][j]) {
+					ppcDcbf((u32)&(base_address[j]));
+					return 0;
+				} else {
+					if (ecc_mode) {
+						if (!ecc_check_status_reg())
+							return 0;
+					}
+				}
+				ppcDcbf((u32)&(base_address[j]));
+			} /* for (j = 0; j < NUMMEMWORDS; j++) */
+			sync();
+			iobarrier_rw();
+		} /* for (l=0; l<NUMLOOPS; l++) */
+	}
+
+	return 1;
+}
+
+#if defined(CONFIG_PPC4xx_DDR_METHOD_A)
+/*-----------------------------------------------------------------------------+
+| program_DQS_calibration_methodA.
++-----------------------------------------------------------------------------*/
+static u32 program_DQS_calibration_methodA(struct ddrautocal *ddrcal)
+{
+	u32 pass_result = 0;
+
+#ifdef DEBUG
+	ulong temp;
+
+	mfsdram(SDRAM_RDCC, temp);
+	debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);
+#endif
+
+	pass_result = DQS_calibration_methodA(ddrcal);
+
+	return pass_result;
+}
+
+/*
+ * DQS_calibration_methodA()
+ *
+ * Autocalibration Method A
+ *
+ *  ARRAY [Entire DQS Range] DQS_Valid_Window ;    initialized to all zeros
+ *  ARRAY [Entire FDBK Range] FDBK_Valid_Window;   initialized to all zeros
+ *  MEMWRITE(addr, expected_data);
+ *  for (i = 0; i < Entire DQS Range; i++) {       RQDC.RQFD
+ *      for (j = 0; j < Entire FDBK Range; j++) {  RFDC.RFFD
+ *         MEMREAD(addr, actual_data);
+ *         if (actual_data == expected_data) {
+ *             DQS_Valid_Window[i] = 1;            RQDC.RQFD
+ *             FDBK_Valid_Window[i][j] = 1;        RFDC.RFFD
+ *         }
+ *      }
+ *  }
+ */
+static u32 DQS_calibration_methodA(struct ddrautocal *cal)
+{
+	ulong rfdc_reg;
+	ulong rffd;
+
+	ulong rqdc_reg;
+	ulong rqfd;
+
+	u32 *membase;
+	ulong bxcf;
+	int rqfd_average;
+	int bxcr_num;
+	int rffd_average;
+	int pass;
+	u32 passed = 0;
+
+	int in_window;
+	struct autocal_regs curr_win_min;
+	struct autocal_regs curr_win_max;
+	struct autocal_regs best_win_min;
+	struct autocal_regs best_win_max;
+	struct autocal_regs loop_win_min;
+	struct autocal_regs loop_win_max;
+
+#ifdef DEBUG
+	ulong temp;
+#endif
+	ulong rdcc;
+
+	char slash[] = "\\|/-\\|/-";
+	int loopi = 0;
+
+	/* start */
+	in_window = 0;
+
+	memset(&curr_win_min, 0, sizeof(curr_win_min));
+	memset(&curr_win_max, 0, sizeof(curr_win_max));
+	memset(&best_win_min, 0, sizeof(best_win_min));
+	memset(&best_win_max, 0, sizeof(best_win_max));
+	memset(&loop_win_min, 0, sizeof(loop_win_min));
+	memset(&loop_win_max, 0, sizeof(loop_win_max));
+
+	rdcc = 0;
+
+	/*
+	 * Program RDCC register
+	 * Read sample cycle auto-update enable
+	 */
+	mtsdram(SDRAM_RDCC,
+		ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) | SDRAM_RDCC_RSAE_ENABLE);
+
+#ifdef DEBUG
+	mfsdram(SDRAM_RDCC, temp);
+	debug("<%s>SDRAM_RDCC=0x%x\n", __func__, temp);
+	mfsdram(SDRAM_RTSR, temp);
+	debug("<%s>SDRAM_RTSR=0x%x\n", __func__, temp);
+	mfsdram(SDRAM_FCSR, temp);
+	debug("<%s>SDRAM_FCSR=0x%x\n", __func__, temp);
+#endif
+
+	/*
+	 * Program RQDC register
+	 * Internal DQS delay mechanism enable
+	 */
+	mtsdram(SDRAM_RQDC,
+		SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x00));
+
+#ifdef DEBUG
+	mfsdram(SDRAM_RQDC, temp);
+	debug("<%s>SDRAM_RQDC=0x%x\n", __func__, temp);
+#endif
+
+	/*
+	 * Program RFDC register
+	 * Set Feedback Fractional Oversample
+	 * Auto-detect read sample cycle enable
+	 */
+	mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE |
+		SDRAM_RFDC_RFOS_ENCODE(0) | SDRAM_RFDC_RFFD_ENCODE(0));
+
+#ifdef DEBUG
+	mfsdram(SDRAM_RFDC, temp);
+	debug("<%s>SDRAM_RFDC=0x%x\n", __func__, temp);
+#endif
+
+	putc(' ');
+	for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
+
+		mfsdram(SDRAM_RQDC, rqdc_reg);
+		rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
+		mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
+
+		putc('\b');
+		putc(slash[loopi++ % 8]);
+
+		curr_win_min.rffd = 0;
+		curr_win_max.rffd = 0;
+		in_window = 0;
+
+		for (rffd = 0, pass = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
+			mfsdram(SDRAM_RFDC, rfdc_reg);
+			rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
+			mtsdram(SDRAM_RFDC,
+				    rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
+
+			for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
+				mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
+
+				/* Banks enabled */
+				if (bxcf & SDRAM_BXCF_M_BE_MASK) {
+					/* Bank is enabled */
+					membase = get_membase(bxcr_num);
+					pass = short_mem_test(membase);
+				} /* if bank enabled */
+			} /* for bxcr_num */
+
+			/* If this value passed update RFFD windows */
+			if (pass && !in_window) { /* at the start of window */
+				in_window = 1;
+				curr_win_min.rffd = curr_win_max.rffd = rffd;
+				curr_win_min.rqfd = curr_win_max.rqfd = rqfd;
+				mfsdram(SDRAM_RDCC, rdcc); /*record this value*/
+			} else if (!pass && in_window) { /* at end of window */
+				in_window = 0;
+			} else if (pass && in_window) { /* within the window */
+				curr_win_max.rffd = rffd;
+				curr_win_max.rqfd = rqfd;
+			}
+			/* else if (!pass && !in_window)
+				skip - no pass, not currently in a window */
+
+			if (in_window) {
+				if ((curr_win_max.rffd - curr_win_min.rffd) >
+				    (best_win_max.rffd - best_win_min.rffd)) {
+					best_win_min.rffd = curr_win_min.rffd;
+					best_win_max.rffd = curr_win_max.rffd;
+
+					best_win_min.rqfd = curr_win_min.rqfd;
+					best_win_max.rqfd = curr_win_max.rqfd;
+					cal->rdcc	  = rdcc;
+				}
+				passed = 1;
+			}
+		} /* RFDC.RFFD */
+
+		/*
+		 * save-off the best window results of the RFDC.RFFD
+		 * for this RQDC.RQFD setting
+		 */
+		/*
+		 * if (just ended RFDC.RFDC loop pass window) >
+		 *	(prior RFDC.RFFD loop pass window)
+		 */
+		if ((best_win_max.rffd - best_win_min.rffd) >
+		    (loop_win_max.rffd - loop_win_min.rffd)) {
+			loop_win_min.rffd = best_win_min.rffd;
+			loop_win_max.rffd = best_win_max.rffd;
+			loop_win_min.rqfd = rqfd;
+			loop_win_max.rqfd = rqfd;
+			debug("RQFD.min 0x%08x, RQFD.max 0x%08x, "
+			      "RFFD.min 0x%08x, RFFD.max 0x%08x\n",
+					loop_win_min.rqfd, loop_win_max.rqfd,
+					loop_win_min.rffd, loop_win_max.rffd);
+		}
+	} /* RQDC.RQFD */
+
+	putc('\b');
+
+	debug("\n");
+
+	if ((loop_win_min.rffd == 0) && (loop_win_max.rffd == 0) &&
+	    (best_win_min.rffd == 0) && (best_win_max.rffd == 0) &&
+	    (best_win_min.rqfd == 0) && (best_win_max.rqfd == 0)) {
+		passed = 0;
+	}
+
+	/*
+	 * Need to program RQDC before RFDC.
+	 */
+	debug("<%s> RQFD Min: 0x%x\n", __func__, loop_win_min.rqfd);
+	debug("<%s> RQFD Max: 0x%x\n", __func__, loop_win_max.rqfd);
+	rqfd_average = loop_win_max.rqfd;
+
+	if (rqfd_average < 0)
+		rqfd_average = 0;
+
+	if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
+		rqfd_average = SDRAM_RQDC_RQFD_MAX;
+
+	debug("<%s> RFFD average: 0x%08x\n", __func__, rqfd_average);
+	mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
+				SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
+
+	debug("<%s> RFFD Min: 0x%08x\n", __func__, loop_win_min.rffd);
+	debug("<%s> RFFD Max: 0x%08x\n", __func__, loop_win_max.rffd);
+	rffd_average = ((loop_win_min.rffd + loop_win_max.rffd) / 2);
+
+	if (rffd_average < 0)
+		rffd_average = 0;
+
+	if (rffd_average > SDRAM_RFDC_RFFD_MAX)
+		rffd_average = SDRAM_RFDC_RFFD_MAX;
+
+	debug("<%s> RFFD average: 0x%08x\n", __func__, rffd_average);
+	mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
+
+	/* if something passed, then return the size of the largest window */
+	if (passed != 0) {
+		passed		= loop_win_max.rffd - loop_win_min.rffd;
+		cal->rqfd	= rqfd_average;
+		cal->rffd	= rffd_average;
+		cal->rffd_min	= loop_win_min.rffd;
+		cal->rffd_max	= loop_win_max.rffd;
+	}
+
+	return (u32)passed;
+}
+
+#else	/* !defined(CONFIG_PPC4xx_DDR_METHOD_A) */
+
+/*-----------------------------------------------------------------------------+
+| program_DQS_calibration_methodB.
++-----------------------------------------------------------------------------*/
+static u32 program_DQS_calibration_methodB(struct ddrautocal *ddrcal)
+{
+	u32 pass_result = 0;
+
+#ifdef DEBUG
+	ulong temp;
+#endif
+
+	/*
+	 * Program RDCC register
+	 * Read sample cycle auto-update enable
+	 */
+	mtsdram(SDRAM_RDCC,
+		ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) | SDRAM_RDCC_RSAE_ENABLE);
+
+#ifdef DEBUG
+	mfsdram(SDRAM_RDCC, temp);
+	debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);
+#endif
+
+	/*
+	 * Program RQDC register
+	 * Internal DQS delay mechanism enable
+	 */
+	mtsdram(SDRAM_RQDC,
+#if defined(CONFIG_DDR_RQDC_START_VAL)
+			SDRAM_RQDC_RQDE_ENABLE |
+			    SDRAM_RQDC_RQFD_ENCODE(CONFIG_DDR_RQDC_START_VAL));
+#else
+			SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x38));
+#endif
+
+#ifdef DEBUG
+	mfsdram(SDRAM_RQDC, temp);
+	debug("<%s>SDRAM_RQDC=0x%08x\n", __func__, temp);
+#endif
+
+	/*
+	 * Program RFDC register
+	 * Set Feedback Fractional Oversample
+	 * Auto-detect read sample cycle enable
+	 */
+	mtsdram(SDRAM_RFDC,	SDRAM_RFDC_ARSE_ENABLE |
+				SDRAM_RFDC_RFOS_ENCODE(0) |
+				SDRAM_RFDC_RFFD_ENCODE(0));
+
+#ifdef DEBUG
+	mfsdram(SDRAM_RFDC, temp);
+	debug("<%s>SDRAM_RFDC=0x%08x\n", __func__, temp);
+#endif
+
+	pass_result = DQS_calibration_methodB(ddrcal);
+
+	return pass_result;
+}
+
+/*
+ * DQS_calibration_methodB()
+ *
+ * Autocalibration Method B
+ *
+ * ARRAY [Entire DQS Range] DQS_Valid_Window ;       initialized to all zeros
+ * ARRAY [Entire Feedback Range] FDBK_Valid_Window;  initialized to all zeros
+ * MEMWRITE(addr, expected_data);
+ * Initialialize the DQS delay to 80 degrees (MCIF0_RRQDC[RQFD]=0x38).
+ *
+ *  for (j = 0; j < Entire Feedback Range; j++) {
+ *      MEMREAD(addr, actual_data);
+ *       if (actual_data == expected_data) {
+ *           FDBK_Valid_Window[j] = 1;
+ *       }
+ * }
+ *
+ * Set MCIF0_RFDC[RFFD] to the middle of the FDBK_Valid_Window.
+ *
+ * for (i = 0; i < Entire DQS Range; i++) {
+ *     MEMREAD(addr, actual_data);
+ *     if (actual_data == expected_data) {
+ *         DQS_Valid_Window[i] = 1;
+ *      }
+ * }
+ *
+ * Set MCIF0_RRQDC[RQFD] to the middle of the DQS_Valid_Window.
+ */
+/*-----------------------------------------------------------------------------+
+| DQS_calibration_methodB.
++-----------------------------------------------------------------------------*/
+static u32 DQS_calibration_methodB(struct ddrautocal *cal)
+{
+	ulong rfdc_reg;
+	ulong rffd;
+
+	ulong rqdc_reg;
+	ulong rqfd;
+
+	ulong rdcc;
+
+	u32 *membase;
+	ulong bxcf;
+	int rqfd_average;
+	int bxcr_num;
+	int rffd_average;
+	int pass;
+	uint passed = 0;
+
+	int in_window;
+	u32 curr_win_min, curr_win_max;
+	u32 best_win_min, best_win_max;
+	u32 size = 0;
+
+	/*------------------------------------------------------------------
+	 | Test to determine the best read clock delay tuning bits.
+	 |
+	 | Before the DDR controller can be used, the read clock delay needs to
+	 | be set.  This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD].
+	 | This value cannot be hardcoded into the program because it changes
+	 | depending on the board's setup and environment.
+	 | To do this, all delay values are tested to see if they
+	 | work or not.  By doing this, you get groups of fails with groups of
+	 | passing values.  The idea is to find the start and end of a passing
+	 | window and take the center of it to use as the read clock delay.
+	 |
+	 | A failure has to be seen first so that when we hit a pass, we know
+	 | that it is truely the start of the window.  If we get passing values
+	 | to start off with, we don't know if we are at the start of the window
+	 |
+	 | The code assumes that a failure will always be found.
+	 | If a failure is not found, there is no easy way to get the middle
+	 | of the passing window.  I guess we can pretty much pick any value
+	 | but some values will be better than others.  Since the lowest speed
+	 | we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed),
+	 | from experimentation it is safe to say you will always have a failure
+	 +-----------------------------------------------------------------*/
+
+	debug("\n\n");
+
+	in_window = 0;
+	rdcc = 0;
+
+	curr_win_min = curr_win_max = 0;
+	best_win_min = best_win_max = 0;
+	for (rffd = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
+		mfsdram(SDRAM_RFDC, rfdc_reg);
+		rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
+		mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
+
+		pass = 1;
+		for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
+			mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
+
+			/* Banks enabled */
+			if (bxcf & SDRAM_BXCF_M_BE_MASK) {
+				/* Bank is enabled */
+				membase = get_membase(bxcr_num);
+				pass &= short_mem_test(membase);
+			} /* if bank enabled */
+		} /* for bxcf_num */
+
+		/* If this value passed */
+		if (pass && !in_window) {	/* start of passing window */
+			in_window = 1;
+			curr_win_min = curr_win_max = rffd;
+			mfsdram(SDRAM_RDCC, rdcc);	/* record this value */
+		} else if (!pass && in_window) {	/* end passing window */
+			in_window = 0;
+		} else if (pass && in_window) {	/* within the passing window */
+			curr_win_max = rffd;
+		}
+
+		if (in_window) {
+			if ((curr_win_max - curr_win_min) >
+			    (best_win_max - best_win_min)) {
+				best_win_min = curr_win_min;
+				best_win_max = curr_win_max;
+				cal->rdcc    = rdcc;
+			}
+			passed = 1;
+		}
+	} /* for rffd */
+
+	if ((best_win_min == 0) && (best_win_max == 0))
+		passed = 0;
+	else
+		size = best_win_max - best_win_min;
+
+	debug("RFFD Min: 0x%x\n", best_win_min);
+	debug("RFFD Max: 0x%x\n", best_win_max);
+	rffd_average = ((best_win_min + best_win_max) / 2);
+
+	cal->rffd_min = best_win_min;
+	cal->rffd_max = best_win_max;
+
+	if (rffd_average < 0)
+		rffd_average = 0;
+
+	if (rffd_average > SDRAM_RFDC_RFFD_MAX)
+		rffd_average = SDRAM_RFDC_RFFD_MAX;
+
+	mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
+
+	rffd = rffd_average;
+	in_window = 0;
+
+	curr_win_min = curr_win_max = 0;
+	best_win_min = best_win_max = 0;
+	for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
+		mfsdram(SDRAM_RQDC, rqdc_reg);
+		rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
+		mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
+
+		pass = 1;
+		for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
+
+			mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
+
+			/* Banks enabled */
+			if (bxcf & SDRAM_BXCF_M_BE_MASK) {
+				/* Bank is enabled */
+				membase = get_membase(bxcr_num);
+				pass &= short_mem_test(membase);
+			} /* if bank enabled */
+		} /* for bxcf_num */
+
+		/* If this value passed */
+		if (pass && !in_window) {
+			in_window = 1;
+			curr_win_min = curr_win_max = rqfd;
+		} else if (!pass && in_window) {
+			in_window = 0;
+		} else if (pass && in_window) {
+			curr_win_max = rqfd;
+		}
+
+		if (in_window) {
+			if ((curr_win_max - curr_win_min) >
+			    (best_win_max - best_win_min)) {
+				best_win_min = curr_win_min;
+				best_win_max = curr_win_max;
+			}
+			passed = 1;
+		}
+	} /* for rqfd */
+
+	if ((best_win_min == 0) && (best_win_max == 0))
+		passed = 0;
+
+	debug("RQFD Min: 0x%x\n", best_win_min);
+	debug("RQFD Max: 0x%x\n", best_win_max);
+	rqfd_average = ((best_win_min + best_win_max) / 2);
+
+	if (rqfd_average < 0)
+		rqfd_average = 0;
+
+	if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
+		rqfd_average = SDRAM_RQDC_RQFD_MAX;
+
+	mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
+					SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
+
+	mfsdram(SDRAM_RQDC, rqdc_reg);
+	mfsdram(SDRAM_RFDC, rfdc_reg);
+
+	/*
+	 * Need to program RQDC before RFDC. The value is read above.
+	 * That is the reason why auto cal not work.
+	 * See, comments below.
+	 */
+	mtsdram(SDRAM_RQDC, rqdc_reg);
+	mtsdram(SDRAM_RFDC, rfdc_reg);
+
+	debug("RQDC: 0x%08X\n", rqdc_reg);
+	debug("RFDC: 0x%08X\n", rfdc_reg);
+
+	/* if something passed, then return the size of the largest window */
+	if (passed != 0) {
+		passed		= size;
+		cal->rqfd	= rqfd_average;
+		cal->rffd	= rffd_average;
+	}
+
+	return (uint)passed;
+}
+#endif /* defined(CONFIG_PPC4xx_DDR_METHOD_A) */
+
+/*
+ * Default table for DDR auto-calibration of all
+ * possible WRDTR and CLKTR values.
+ * Table format is:
+ *	 {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]}
+ *
+ * Table is terminated with {-1, -1} value pair.
+ *
+ * Board vendors can specify their own board specific subset of
+ * known working {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]} value
+ * pairs via a board defined ddr_scan_option() function.
+ */
+struct sdram_timing full_scan_options[] = {
+	{0, 0}, {0, 1}, {0, 2}, {0, 3},
+	{1, 0}, {1, 1}, {1, 2}, {1, 3},
+	{2, 0}, {2, 1}, {2, 2}, {2, 3},
+	{3, 0}, {3, 1}, {3, 2}, {3, 3},
+	{4, 0}, {4, 1}, {4, 2}, {4, 3},
+	{5, 0}, {5, 1}, {5, 2}, {5, 3},
+	{6, 0}, {6, 1}, {6, 2}, {6, 3},
+	{-1, -1}
+};
+
+/*---------------------------------------------------------------------------+
+| DQS_calibration.
++----------------------------------------------------------------------------*/
+u32 DQS_autocalibration(void)
+{
+	u32 wdtr;
+	u32 clkp;
+	u32 result = 0;
+	u32 best_result = 0;
+	u32 best_rdcc;
+	struct ddrautocal ddrcal;
+	struct autocal_clks tcal;
+	ulong rfdc_reg;
+	ulong rqdc_reg;
+	u32 val;
+	int verbose_lvl = 0;
+	char *str;
+	char slash[] = "\\|/-\\|/-";
+	int loopi = 0;
+	struct sdram_timing *scan_list;
+
+#if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION)
+	int i;
+	char tmp[64];	/* long enough for environment variables */
+#endif
+
+	memset(&tcal, 0, sizeof(tcal));
+
+	ddr_scan_option((ulong)full_scan_options);
+
+	scan_list =
+	      (struct sdram_timing *)ddr_scan_option((ulong)full_scan_options);
+
+	mfsdram(SDRAM_MCOPT1, val);
+	if ((val & SDRAM_MCOPT1_MCHK_CHK_REP) == SDRAM_MCOPT1_MCHK_CHK_REP)
+		str = "ECC Auto calibration -";
+	else
+		str = "Auto calibration -";
+
+	puts(str);
+
+#if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION)
+	i = getenv_r("autocalib", tmp, sizeof(tmp));
+	if (i < 0)
+		strcpy(tmp, CONFIG_AUTOCALIB);
+
+	if (strcmp(tmp, "final") == 0) {
+		/* display the final autocalibration results only */
+		verbose_lvl = 1;
+	} else if (strcmp(tmp, "loop") == 0) {
+		/* display summary autocalibration info per iteration */
+		verbose_lvl = 2;
+	} else if (strcmp(tmp, "display") == 0) {
+		/* display full debug autocalibration window info. */
+		verbose_lvl = 3;
+	}
+#endif /* (DEBUG_PPC4xx_DDR_AUTOCALIBRATION) */
+
+	best_rdcc = (SDRAM_RDCC_RDSS_T4 >> 30);
+
+	while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) {
+		wdtr = scan_list->wrdtr;
+		clkp = scan_list->clktr;
+
+		mfsdram(SDRAM_WRDTR, val);
+		val &= ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK);
+		mtsdram(SDRAM_WRDTR, (val |
+			ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | (wdtr << 25))));
+
+		mtsdram(SDRAM_CLKTR, clkp << 30);
+
+		relock_memory_DLL();
+
+		putc('\b');
+		putc(slash[loopi++ % 8]);
+
+#ifdef DEBUG
+		debug("\n");
+		debug("*** --------------\n");
+		mfsdram(SDRAM_WRDTR, val);
+		debug("*** SDRAM_WRDTR set to 0x%08x\n", val);
+		mfsdram(SDRAM_CLKTR, val);
+		debug("*** SDRAM_CLKTR set to 0x%08x\n", val);
+#endif
+
+		debug("\n");
+		if (verbose_lvl > 2) {
+			printf("*** SDRAM_WRDTR (wdtr) set to %d\n", wdtr);
+			printf("*** SDRAM_CLKTR (clkp) set to %d\n", clkp);
+		}
+
+		memset(&ddrcal, 0, sizeof(ddrcal));
+
+		/*
+		 * DQS calibration.
+		 */
+		/*
+		 * program_DQS_calibration_method[A|B]() returns 0 if no
+		 * passing RFDC.[RFFD] window is found or returns the size
+		 * of the best passing window; in the case of a found passing
+		 * window, the ddrcal will contain the values of the best
+		 * window RQDC.[RQFD] and RFDC.[RFFD].
+		 */
+
+		/*
+		 * Call PPC4xx SDRAM DDR autocalibration methodA or methodB.
+		 * Default is methodB.
+		 * Defined the autocalibration method in the board specific
+		 * header file.
+		 * Please see include/configs/kilauea.h for an example for
+		 * a board specific implementation.
+		 */
+#if defined(CONFIG_PPC4xx_DDR_METHOD_A)
+		result = program_DQS_calibration_methodA(&ddrcal);
+#else
+		result = program_DQS_calibration_methodB(&ddrcal);
+#endif
+
+		sync();
+
+		/*
+		 * Clear potential errors resulting from auto-calibration.
+		 * If not done, then we could get an interrupt later on when
+		 * exceptions are enabled.
+		 */
+		set_mcsr(get_mcsr());
+
+		val = ddrcal.rdcc;	/* RDCC from the best passing window */
+
+		udelay(100);
+
+		if (verbose_lvl > 1) {
+			char *tstr;
+			switch ((val >> 30)) {
+			case 0:
+				if (result != 0)
+					tstr = "T1";
+				else
+					tstr = "N/A";
+				break;
+			case 1:
+				tstr = "T2";
+				break;
+			case 2:
+				tstr = "T3";
+				break;
+			case 3:
+				tstr = "T4";
+				break;
+			default:
+				tstr = "unknown";
+				break;
+			}
+			printf("** WRDTR(%d) CLKTR(%d), Wind (%d), best (%d), "
+			       "max-min(0x%04x)(0x%04x), RDCC: %s\n",
+				wdtr, clkp, result, best_result,
+				ddrcal.rffd_min, ddrcal.rffd_max, tstr);
+		}
+
+		/*
+		 * The DQS calibration "result" is either "0"
+		 * if no passing window was found, or is the
+		 * size of the RFFD passing window.
+		 */
+		/*
+		 * want the lowest Read Sample Cycle Select
+		 */
+		val = SDRAM_RDCC_RDSS_DECODE(val);
+		debug("*** (%d) (%d) current_rdcc, best_rdcc\n",
+			val, best_rdcc);
+
+		if ((result != 0) &&
+		    (val >= SDRAM_RDCC_RDSS_VAL(SDRAM_RDCC_RDSS_T2))) {
+			if (((result == best_result) && (val < best_rdcc)) ||
+			    ((result > best_result) && (val <= best_rdcc))) {
+				tcal.autocal.flags = 1;
+				debug("*** (%d)(%d) result passed window "
+					"size: 0x%08x, rqfd = 0x%08x, "
+					"rffd = 0x%08x, rdcc = 0x%08x\n",
+					wdtr, clkp, result, ddrcal.rqfd,
+					ddrcal.rffd, ddrcal.rdcc);
+
+				/*
+				 * Save the SDRAM_WRDTR and SDRAM_CLKTR
+				 * settings for the largest returned
+				 * RFFD passing window size.
+				 */
+				best_rdcc = val;
+				tcal.clocks.wrdtr = wdtr;
+				tcal.clocks.clktr = clkp;
+				tcal.clocks.rdcc = SDRAM_RDCC_RDSS_ENCODE(val);
+				tcal.autocal.rqfd = ddrcal.rqfd;
+				tcal.autocal.rffd = ddrcal.rffd;
+				best_result = result;
+
+					if (verbose_lvl > 2) {
+						printf("** (%d)(%d)  "
+						       "best result: 0x%04x\n",
+							wdtr, clkp,
+							best_result);
+						printf("** (%d)(%d)  "
+						       "best WRDTR: 0x%04x\n",
+							wdtr, clkp,
+							tcal.clocks.wrdtr);
+						printf("** (%d)(%d)  "
+						       "best CLKTR: 0x%04x\n",
+							wdtr, clkp,
+							tcal.clocks.clktr);
+						printf("** (%d)(%d)  "
+						       "best RQDC: 0x%04x\n",
+							wdtr, clkp,
+							tcal.autocal.rqfd);
+						printf("** (%d)(%d)  "
+						       "best RFDC: 0x%04x\n",
+							wdtr, clkp,
+							tcal.autocal.rffd);
+						printf("** (%d)(%d)  "
+						       "best RDCC: 0x%08x\n",
+							wdtr, clkp,
+							(u32)tcal.clocks.rdcc);
+						mfsdram(SDRAM_RTSR, val);
+						printf("** (%d)(%d)  best "
+						       "loop RTSR: 0x%08x\n",
+							wdtr, clkp, val);
+						mfsdram(SDRAM_FCSR, val);
+						printf("** (%d)(%d)  best "
+						       "loop FCSR: 0x%08x\n",
+							wdtr, clkp, val);
+					}
+			}
+		} /* if ((result != 0) && (val >= (ddr_rdss_opt()))) */
+		scan_list++;
+	} /* while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) */
+
+	if (tcal.autocal.flags == 1) {
+		if (verbose_lvl > 0) {
+			printf("*** --------------\n");
+			printf("*** best_result window size: %d\n",
+							best_result);
+			printf("*** best_result WRDTR: 0x%04x\n",
+							tcal.clocks.wrdtr);
+			printf("*** best_result CLKTR: 0x%04x\n",
+							tcal.clocks.clktr);
+			printf("*** best_result RQFD: 0x%04x\n",
+							tcal.autocal.rqfd);
+			printf("*** best_result RFFD: 0x%04x\n",
+							tcal.autocal.rffd);
+			printf("*** best_result RDCC: 0x%04x\n",
+							tcal.clocks.rdcc);
+			printf("*** --------------\n");
+			printf("\n");
+		}
+
+		/*
+		 * if got best passing result window, then lock in the
+		 * best CLKTR, WRDTR, RQFD, and RFFD values
+		 */
+		mfsdram(SDRAM_WRDTR, val);
+		mtsdram(SDRAM_WRDTR, (val &
+		    ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) |
+		    ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC |
+					(tcal.clocks.wrdtr << 25)));
+
+		mtsdram(SDRAM_CLKTR, tcal.clocks.clktr << 30);
+
+		relock_memory_DLL();
+
+		mfsdram(SDRAM_RQDC, rqdc_reg);
+		rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
+		mtsdram(SDRAM_RQDC, rqdc_reg |
+				SDRAM_RQDC_RQFD_ENCODE(tcal.autocal.rqfd));
+
+		mfsdram(SDRAM_RQDC, rqdc_reg);
+		debug("*** best_result: read value SDRAM_RQDC 0x%08x\n",
+				rqdc_reg);
+
+		mfsdram(SDRAM_RFDC, rfdc_reg);
+		rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
+		mtsdram(SDRAM_RFDC, rfdc_reg |
+				SDRAM_RFDC_RFFD_ENCODE(tcal.autocal.rffd));
+
+		mfsdram(SDRAM_RFDC, rfdc_reg);
+		debug("*** best_result: read value SDRAM_RFDC 0x%08x\n",
+				rfdc_reg);
+		mfsdram(SDRAM_RDCC, val);
+		debug("***  SDRAM_RDCC 0x%08x\n", val);
+	} else {
+		/*
+		 * no valid windows were found
+		 */
+		printf("DQS memory calibration window can not be determined, "
+		       "terminating u-boot.\n");
+		ppc4xx_ibm_ddr2_register_dump();
+		spd_ddr_init_hang();
+	}
+
+	blank_string(strlen(str));
+
+	return 0;
+}
+#else /* defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */
+u32 DQS_autocalibration(void)
+{
+	return 0;
+}
+#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */
+#endif /* defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) */
diff --git a/arch/powerpc/cpu/ppc4xx/4xx_pci.c b/arch/powerpc/cpu/ppc4xx/4xx_pci.c
new file mode 100644
index 0000000..eed4534
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/4xx_pci.c
@@ -0,0 +1,873 @@
+/*-----------------------------------------------------------------------------+
+ *       This source code is dual-licensed.  You may use it under the terms of
+ *       the GNU General Public license version 2, or under the license below.
+ *
+ *       This source code has been made available to you by IBM on an AS-IS
+ *       basis.  Anyone receiving this source is licensed under IBM
+ *       copyrights to use it in any way he or she deems fit, including
+ *       copying it, modifying it, compiling it, and redistributing it either
+ *       with or without modifications.  No license under IBM patents or
+ *       patent applications is to be implied by the copyright license.
+ *
+ *       Any user of this software should understand that IBM cannot provide
+ *       technical support for this software and will not be responsible for
+ *       any consequences resulting from the use of this software.
+ *
+ *       Any person who transfers this source code or any derivative work
+ *       must include the IBM copyright notice, this paragraph, and the
+ *       preceding two paragraphs in the transferred software.
+ *
+ *       COPYRIGHT   I B M   CORPORATION 1995
+ *       LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
+ *-----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------+
+ *
+ *  File Name:   405gp_pci.c
+ *
+ *  Function:    Initialization code for the 405GP PCI Configuration regs.
+ *
+ *  Author:      Mark Game
+ *
+ *  Change Activity-
+ *
+ *  Date        Description of Change                                       BY
+ *  ---------   ---------------------                                       ---
+ *  09-Sep-98   Created                                                     MCG
+ *  02-Nov-98   Removed External arbiter selected message                   JWB
+ *  27-Nov-98   Zero out PTMBAR2 and disable in PTM2MS                      JWB
+ *  04-Jan-99   Zero out other unused PMM and PTM regs. Change bus scan     MCG
+ *              from (0 to n) to (1 to n).
+ *  17-May-99   Port to Walnut                                              JWB
+ *  17-Jun-99   Updated for VGA support                                     JWB
+ *  21-Jun-99   Updated to allow SRAM region to be a target from PCI bus    JWB
+ *  19-Jul-99   Updated for 405GP pass 1 errata #26 (Low PCI subsequent     MCG
+ *              target latency timer values are not supported).
+ *              Should be fixed in pass 2.
+ *  09-Sep-99   Removed use of PTM2 since the SRAM region no longer needs   JWB
+ *              to be a PCI target. Zero out PTMBAR2 and disable in PTM2MS.
+ *  10-Dec-99   Updated PCI_Write_CFG_Reg for pass2 errata #6               JWB
+ *  11-Jan-00   Ensure PMMxMAs disabled before setting PMMxLAs. This is not
+ *              really required after a reset since PMMxMAs are already
+ *	        disabled but is a good practice nonetheless.                JWB
+ *  12-Jun-01   stefan.roese@esd-electronics.com
+ *              - PCI host/adapter handling reworked
+ *  09-Jul-01   stefan.roese@esd-electronics.com
+ *              - PCI host now configures from device 0 (not 1) to max_dev,
+ *                (host configures itself)
+ *              - On CPCI-405 pci base address and size is generated from
+ *                SDRAM and FLASH size (CFG regs not used anymore)
+ *              - Some minor changes for CPCI-405-A (adapter version)
+ *  14-Sep-01   stefan.roese@esd-electronics.com
+ *              - CONFIG_PCI_SCAN_SHOW added to print pci devices upon startup
+ *  28-Sep-01   stefan.roese@esd-electronics.com
+ *              - Changed pci master configuration for linux compatibility
+ *                (no need for bios_fixup() anymore)
+ *  26-Feb-02   stefan.roese@esd-electronics.com
+ *              - Bug fixed in pci configuration (Andrew May)
+ *              - Removed pci class code init for CPCI405 board
+ *  15-May-02   stefan.roese@esd-electronics.com
+ *              - New vga device handling
+ *  29-May-02   stefan.roese@esd-electronics.com
+ *              - PCI class code init added (if defined)
+ *----------------------------------------------------------------------------*/
+
+#include <common.h>
+#include <command.h>
+#include <asm/4xx_pci.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <pci.h>
+
+#ifdef CONFIG_PCI
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405EP)
+
+#if defined(CONFIG_PMC405)
+ushort pmc405_pci_subsys_deviceid(void);
+#endif
+
+/*#define DEBUG*/
+
+/*
+ * Board-specific pci initialization
+ * Platform code can reimplement pci_pre_init() if needed
+ */
+int __pci_pre_init(struct pci_controller *hose)
+{
+#if defined(CONFIG_405EP)
+	/*
+	 * Enable the internal PCI arbiter by default.
+	 *
+	 * On 405EP CPUs the internal arbiter can be controlled
+	 * by the I2C strapping EEPROM. If you want to do so
+	 * or if you want to disable the arbiter pci_pre_init()
+	 * must be reimplemented without enabling the arbiter.
+	 * The arbiter is enabled in this place because of
+	 * compatibility reasons.
+	 */
+	mtdcr(CPC0_PCI, mfdcr(CPC0_PCI) | CPC0_PCI_ARBIT_EN);
+#endif /* CONFIG_405EP */
+
+	return 1;
+}
+int pci_pre_init(struct pci_controller *hose)
+	__attribute__((weak, alias("__pci_pre_init")));
+
+int __is_pci_host(struct pci_controller *hose)
+{
+#if defined(CONFIG_405GP)
+	if (mfdcr(CPC0_PSR) & PSR_PCI_ARBIT_EN)
+		return 1;
+#elif defined (CONFIG_405EP)
+	if (mfdcr(CPC0_PCI) & CPC0_PCI_ARBIT_EN)
+		return 1;
+#endif
+	return 0;
+}
+int is_pci_host(struct pci_controller *hose) __attribute__((weak, alias("__is_pci_host")));
+
+/*-----------------------------------------------------------------------------+
+ * pci_init.  Initializes the 405GP PCI Configuration regs.
+ *-----------------------------------------------------------------------------*/
+void pci_405gp_init(struct pci_controller *hose)
+{
+	int i, reg_num = 0;
+	bd_t *bd = gd->bd;
+
+	unsigned short temp_short;
+	unsigned long ptmpcila[2] = {CONFIG_SYS_PCI_PTM1PCI, CONFIG_SYS_PCI_PTM2PCI};
+#if defined(CONFIG_PCI_4xx_PTM_OVERWRITE)
+	char *ptmla_str, *ptmms_str;
+#endif
+	unsigned long ptmla[2]    = {CONFIG_SYS_PCI_PTM1LA, CONFIG_SYS_PCI_PTM2LA};
+	unsigned long ptmms[2]    = {CONFIG_SYS_PCI_PTM1MS, CONFIG_SYS_PCI_PTM2MS};
+#if defined(CONFIG_PIP405) || defined (CONFIG_MIP405)
+	unsigned long pmmla[3]    = {0x80000000, 0xA0000000, 0};
+	unsigned long pmmma[3]    = {0xE0000001, 0xE0000001, 0};
+	unsigned long pmmpcila[3] = {0x80000000, 0x00000000, 0};
+	unsigned long pmmpciha[3] = {0x00000000, 0x00000000, 0};
+#else
+	unsigned long pmmla[3]    = {0x80000000, 0,0};
+	unsigned long pmmma[3]    = {0xC0000001, 0,0};
+	unsigned long pmmpcila[3] = {0x80000000, 0,0};
+	unsigned long pmmpciha[3] = {0x00000000, 0,0};
+#endif
+#ifdef CONFIG_PCI_PNP
+#if (CONFIG_PCI_HOST == PCI_HOST_AUTO)
+	char *s;
+#endif
+#endif
+
+#if defined(CONFIG_PCI_4xx_PTM_OVERWRITE)
+	ptmla_str = getenv("ptm1la");
+	ptmms_str = getenv("ptm1ms");
+	if(NULL != ptmla_str && NULL != ptmms_str ) {
+	        ptmla[0] = simple_strtoul (ptmla_str, NULL, 16);
+		ptmms[0] = simple_strtoul (ptmms_str, NULL, 16);
+	}
+
+	ptmla_str = getenv("ptm2la");
+	ptmms_str = getenv("ptm2ms");
+	if(NULL != ptmla_str && NULL != ptmms_str ) {
+	        ptmla[1] = simple_strtoul (ptmla_str, NULL, 16);
+		ptmms[1] = simple_strtoul (ptmms_str, NULL, 16);
+	}
+#endif
+
+	/*
+	 * Register the hose
+	 */
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	/* ISA/PCI I/O space */
+	pci_set_region(hose->regions + reg_num++,
+		       MIN_PCI_PCI_IOADDR,
+		       MIN_PLB_PCI_IOADDR,
+		       0x10000,
+		       PCI_REGION_IO);
+
+	/* PCI I/O space */
+	pci_set_region(hose->regions + reg_num++,
+		       0x00800000,
+		       0xe8800000,
+		       0x03800000,
+		       PCI_REGION_IO);
+
+	reg_num = 2;
+
+	/* Memory spaces */
+	for (i=0; i<2; i++)
+		if (ptmms[i] & 1)
+		{
+			if (!i) hose->pci_fb = hose->regions + reg_num;
+
+			pci_set_region(hose->regions + reg_num++,
+				       ptmpcila[i], ptmla[i],
+				       ~(ptmms[i] & 0xfffff000) + 1,
+				       PCI_REGION_MEM |
+				       PCI_REGION_SYS_MEMORY);
+		}
+
+	/* PCI memory spaces */
+	for (i=0; i<3; i++)
+		if (pmmma[i] & 1)
+		{
+			pci_set_region(hose->regions + reg_num++,
+				       pmmpcila[i], pmmla[i],
+				       ~(pmmma[i] & 0xfffff000) + 1,
+				       PCI_REGION_MEM);
+		}
+
+	hose->region_count = reg_num;
+
+	pci_setup_indirect(hose,
+			   PCICFGADR,
+			   PCICFGDATA);
+
+	if (hose->pci_fb)
+		pciauto_region_init(hose->pci_fb);
+
+	/* Let board change/modify hose & do initial checks */
+	if (pci_pre_init(hose) == 0) {
+		printf("PCI: Board-specific initialization failed.\n");
+		printf("PCI: Configuration aborted.\n");
+		return;
+	}
+
+	pci_register_hose(hose);
+
+	/*--------------------------------------------------------------------------+
+	 * 405GP PCI Master configuration.
+	 * Map one 512 MB range of PLB/processor addresses to PCI memory space.
+	 * PLB address 0x80000000-0xBFFFFFFF ==> PCI address 0x80000000-0xBFFFFFFF
+	 * Use byte reversed out routines to handle endianess.
+	 *--------------------------------------------------------------------------*/
+	out32r(PMM0MA,    (pmmma[0]&~0x1)); /* disable, configure PMMxLA, PMMxPCILA first */
+	out32r(PMM0LA,    pmmla[0]);
+	out32r(PMM0PCILA, pmmpcila[0]);
+	out32r(PMM0PCIHA, pmmpciha[0]);
+	out32r(PMM0MA,    pmmma[0]);
+
+	/*--------------------------------------------------------------------------+
+	 * PMM1 is not used.  Initialize them to zero.
+	 *--------------------------------------------------------------------------*/
+	out32r(PMM1MA,    (pmmma[1]&~0x1));
+	out32r(PMM1LA,    pmmla[1]);
+	out32r(PMM1PCILA, pmmpcila[1]);
+	out32r(PMM1PCIHA, pmmpciha[1]);
+	out32r(PMM1MA,    pmmma[1]);
+
+	/*--------------------------------------------------------------------------+
+	 * PMM2 is not used.  Initialize them to zero.
+	 *--------------------------------------------------------------------------*/
+	out32r(PMM2MA,    (pmmma[2]&~0x1));
+	out32r(PMM2LA,    pmmla[2]);
+	out32r(PMM2PCILA, pmmpcila[2]);
+	out32r(PMM2PCIHA, pmmpciha[2]);
+	out32r(PMM2MA,    pmmma[2]);
+
+	/*--------------------------------------------------------------------------+
+	 * 405GP PCI Target configuration.  (PTM1)
+	 * Note: PTM1MS is hardwire enabled but we set the enable bit anyway.
+	 *--------------------------------------------------------------------------*/
+	out32r(PTM1LA,    ptmla[0]);         /* insert address                     */
+	out32r(PTM1MS,    ptmms[0]);         /* insert size, enable bit is 1       */
+	pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_1, ptmpcila[0]);
+
+	/*--------------------------------------------------------------------------+
+	 * 405GP PCI Target configuration.  (PTM2)
+	 *--------------------------------------------------------------------------*/
+	out32r(PTM2LA, ptmla[1]);            /* insert address                     */
+	pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_2, ptmpcila[1]);
+
+	if (ptmms[1] == 0)
+	{
+		out32r(PTM2MS,    0x00000001);   /* set enable bit                     */
+		pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_2, 0x00000000);
+		out32r(PTM2MS,    0x00000000);   /* disable                            */
+	}
+	else
+	{
+		out32r(PTM2MS, ptmms[1]);        /* insert size, enable bit is 1       */
+	}
+
+	/*
+	 * Insert Subsystem Vendor and Device ID
+	 */
+	pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_VENDOR_ID, CONFIG_SYS_PCI_SUBSYS_VENDORID);
+#ifdef CONFIG_CPCI405
+	if (is_pci_host(hose))
+		pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_DEVICEID);
+	else
+		pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_DEVICEID2);
+#else
+	pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_DEVICEID);
+#endif
+
+	/*
+	 * Insert Class-code
+	 */
+#ifdef CONFIG_SYS_PCI_CLASSCODE
+	pci_write_config_word(PCIDEVID_405GP, PCI_CLASS_SUB_CODE, CONFIG_SYS_PCI_CLASSCODE);
+#endif /* CONFIG_SYS_PCI_CLASSCODE */
+
+	/*--------------------------------------------------------------------------+
+	 * If PCI speed = 66MHz, set 66MHz capable bit.
+	 *--------------------------------------------------------------------------*/
+	if (bd->bi_pci_busfreq >= 66000000) {
+		pci_read_config_word(PCIDEVID_405GP, PCI_STATUS, &temp_short);
+		pci_write_config_word(PCIDEVID_405GP,PCI_STATUS,(temp_short|PCI_STATUS_66MHZ));
+	}
+
+#if (CONFIG_PCI_HOST != PCI_HOST_ADAPTER)
+#if (CONFIG_PCI_HOST == PCI_HOST_AUTO)
+	if (is_pci_host(hose) ||
+	    (((s = getenv("pciscan")) != NULL) && (strcmp(s, "yes") == 0)))
+#endif
+	{
+		/*--------------------------------------------------------------------------+
+		 * Write the 405GP PCI Configuration regs.
+		 * Enable 405GP to be a master on the PCI bus (PMM).
+		 * Enable 405GP to act as a PCI memory target (PTM).
+		 *--------------------------------------------------------------------------*/
+		pci_read_config_word(PCIDEVID_405GP, PCI_COMMAND, &temp_short);
+		pci_write_config_word(PCIDEVID_405GP, PCI_COMMAND, temp_short |
+				      PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+	}
+#endif
+
+#if defined(CONFIG_405EP)
+	/*
+	 * on ppc405ep vendor/device id is not set
+	 * The user manual says 0x1014 (IBM) / 0x0156 (405GP!)
+	 * are the correct values.
+	 */
+	pci_write_config_word(PCIDEVID_405GP, PCI_VENDOR_ID, PCI_VENDOR_ID_IBM);
+	pci_write_config_word(PCIDEVID_405GP,
+			      PCI_DEVICE_ID, PCI_DEVICE_ID_IBM_405GP);
+#endif
+
+	/*
+	 * Set HCE bit (Host Configuration Enabled)
+	 */
+	pci_read_config_word(PCIDEVID_405GP, PCIBRDGOPT2, &temp_short);
+	pci_write_config_word(PCIDEVID_405GP, PCIBRDGOPT2, (temp_short | 0x0001));
+
+#ifdef CONFIG_PCI_PNP
+	/*--------------------------------------------------------------------------+
+	 * Scan the PCI bus and configure devices found.
+	 *--------------------------------------------------------------------------*/
+#if (CONFIG_PCI_HOST == PCI_HOST_AUTO)
+	if (is_pci_host(hose) ||
+	    (((s = getenv("pciscan")) != NULL) && (strcmp(s, "yes") == 0)))
+#endif
+	{
+#ifdef CONFIG_PCI_SCAN_SHOW
+		printf("PCI:   Bus Dev VenId DevId Class Int\n");
+#endif
+		hose->last_busno = pci_hose_scan(hose);
+	}
+#endif  /* CONFIG_PCI_PNP */
+
+}
+
+/*
+ * drivers/pci/pci.c skips every host bridge but the 405GP since it could
+ * be set as an Adapter.
+ *
+ * I (Andrew May) don't know what we should do here, but I don't want
+ * the auto setup of a PCI device disabling what is done pci_405gp_init
+ * as has happened before.
+ */
+void pci_405gp_setup_bridge(struct pci_controller *hose, pci_dev_t dev,
+			    struct pci_config_table *entry)
+{
+#ifdef DEBUG
+	printf("405gp_setup_bridge\n");
+#endif
+}
+
+/*
+ *
+ */
+
+void pci_405gp_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
+{
+	unsigned char int_line = 0xff;
+
+	/*
+	 * Write pci interrupt line register (cpci405 specific)
+	 */
+	switch (PCI_DEV(dev) & 0x03)
+	{
+	case 0:
+		int_line = 27 + 2;
+		break;
+	case 1:
+		int_line = 27 + 3;
+		break;
+	case 2:
+		int_line = 27 + 0;
+		break;
+	case 3:
+		int_line = 27 + 1;
+		break;
+	}
+
+	pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, int_line);
+}
+
+void pci_405gp_setup_vga(struct pci_controller *hose, pci_dev_t dev,
+			 struct pci_config_table *entry)
+{
+	unsigned int cmdstat = 0;
+
+	pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_prefetch, hose->pci_io);
+
+	/* always enable io space on vga boards */
+	pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat);
+	cmdstat |= PCI_COMMAND_IO;
+	pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat);
+}
+
+#if !(defined(CONFIG_PIP405) || defined (CONFIG_MIP405)) && !(defined (CONFIG_SC3))
+
+/*
+ *As is these functs get called out of flash Not a horrible
+ *thing, but something to keep in mind. (no statics?)
+ */
+static struct pci_config_table pci_405gp_config_table[] = {
+/*if VendID is 0 it terminates the table search (ie Walnut)*/
+#ifdef CONFIG_SYS_PCI_SUBSYS_VENDORID
+	{CONFIG_SYS_PCI_SUBSYS_VENDORID, PCI_ANY_ID, PCI_CLASS_BRIDGE_HOST,
+	 PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_405gp_setup_bridge},
+#endif
+	{PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA,
+	 PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_405gp_setup_vga},
+
+	{PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NOT_DEFINED_VGA,
+	 PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_405gp_setup_vga},
+
+	{ }
+};
+
+static struct pci_controller hose = {
+	fixup_irq: pci_405gp_fixup_irq,
+	config_table: pci_405gp_config_table,
+};
+
+void pci_init_board(void)
+{
+	/*we want the ptrs to RAM not flash (ie don't use init list)*/
+	hose.fixup_irq    = pci_405gp_fixup_irq;
+	hose.config_table = pci_405gp_config_table;
+	pci_405gp_init(&hose);
+}
+
+#endif
+
+#endif /* CONFIG_405GP */
+
+/*-----------------------------------------------------------------------------+
+ * CONFIG_440
+ *-----------------------------------------------------------------------------*/
+#if defined(CONFIG_440)
+
+static struct pci_controller ppc440_hose = {0};
+
+/*
+ * This routine is called to determine if a pci scan should be
+ * performed. With various hardware environments (especially cPCI and
+ * PPMC) it's insufficient to depend on the state of the arbiter enable
+ * bit in the strap register, or generic host/adapter assumptions.
+ *
+ * Rather than hard-code a bad assumption in the general 440 code, the
+ * 440 pci code requires the board to decide at runtime.
+ *
+ * Return 0 for adapter mode, non-zero for host (monarch) mode.
+ *
+ * Weak default implementation: "Normal" boards implement the PCI
+ * host functionality. This can be overridden for PCI adapter boards.
+ */
+int __is_pci_host(struct pci_controller *hose)
+{
+	return 1;
+}
+int is_pci_host(struct pci_controller *hose)
+	__attribute__((weak, alias("__is_pci_host")));
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \
+    defined(CONFIG_440GR) || defined(CONFIG_440GRX)
+
+#if defined(CONFIG_SYS_PCI_TARGET_INIT)
+/*
+ * pci_target_init
+ *
+ * The bootstrap configuration provides default settings for the pci
+ * inbound map (PIM). But the bootstrap config choices are limited and
+ * may not be sufficient for a given board.
+ */
+void __pci_target_init(struct pci_controller *hose)
+{
+	/*
+	 * Set up Direct MMIO registers
+	 */
+
+	/*
+	 * PowerPC440 EP PCI Master configuration.
+	 * Map one 1Gig range of PLB/processor addresses to PCI memory space.
+	 * PLB address 0xA0000000-0xDFFFFFFF ==> PCI address 0xA0000000-0xDFFFFFFF
+	 * Use byte reversed out routines to handle endianess.
+	 * Make this region non-prefetchable.
+	 */
+	/* PMM0 Mask/Attribute - disabled b4 setting */
+	out_le32((void *)PCIL0_PMM0MA, 0x00000000);
+	/* PMM0 Local Address */
+	out_le32((void *)PCIL0_PMM0LA, CONFIG_SYS_PCI_MEMBASE);
+	/* PMM0 PCI Low Address */
+	out_le32((void *)PCIL0_PMM0PCILA, CONFIG_SYS_PCI_MEMBASE);
+	/* PMM0 PCI High Address */
+	out_le32((void *)PCIL0_PMM0PCIHA, 0x00000000);
+	/* 512M + No prefetching, and enable region */
+	out_le32((void *)PCIL0_PMM0MA, 0xE0000001);
+
+	/* PMM1 Mask/Attribute - disabled b4 setting */
+	out_le32((void *)PCIL0_PMM1MA, 0x00000000);
+	/* PMM1 Local Address */
+	out_le32((void *)PCIL0_PMM1LA, CONFIG_SYS_PCI_MEMBASE2);
+	/* PMM1 PCI Low Address */
+	out_le32((void *)PCIL0_PMM1PCILA, CONFIG_SYS_PCI_MEMBASE2);
+	/* PMM1 PCI High Address */
+	out_le32((void *)PCIL0_PMM1PCIHA, 0x00000000);
+	/* 512M + No prefetching, and enable region */
+	out_le32((void *)PCIL0_PMM1MA, 0xE0000001);
+
+	out_le32((void *)PCIL0_PTM1MS, 0x00000001); /* Memory Size/Attribute */
+	out_le32((void *)PCIL0_PTM1LA, 0);	/* Local Addr. Reg */
+	out_le32((void *)PCIL0_PTM2MS, 0);	/* Memory Size/Attribute */
+	out_le32((void *)PCIL0_PTM2LA, 0);	/* Local Addr. Reg */
+
+	/*
+	 * Set up Configuration registers
+	 */
+
+	/* Program the board's subsystem id/vendor id */
+	pci_write_config_word(0, PCI_SUBSYSTEM_VENDOR_ID,
+			      CONFIG_SYS_PCI_SUBSYS_VENDORID);
+	pci_write_config_word(0, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_ID);
+
+	/* Configure command register as bus master */
+	pci_write_config_word(0, PCI_COMMAND, PCI_COMMAND_MASTER);
+
+	/* 240nS PCI clock */
+	pci_write_config_word(0, PCI_LATENCY_TIMER, 1);
+
+	/* No error reporting */
+	pci_write_config_word(0, PCI_ERREN, 0);
+
+	pci_write_config_dword(0, PCI_BRDGOPT2, 0x00000101);
+}
+#endif /* CONFIG_SYS_PCI_TARGET_INIT */
+
+/*
+ * pci_pre_init
+ *
+ * This routine is called just prior to registering the hose and gives
+ * the board the opportunity to check things. Returning a value of zero
+ * indicates that things are bad & PCI initialization should be aborted.
+ *
+ * Different boards may wish to customize the pci controller structure
+ * (add regions, override default access routines, etc) or perform
+ * certain pre-initialization actions.
+ *
+ */
+int __pci_pre_init(struct pci_controller *hose)
+{
+	u32 reg;
+
+	/*
+	 * Set priority for all PLB3 devices to 0.
+	 * Set PLB3 arbiter to fair mode.
+	 */
+	mfsdr(SD0_AMP1, reg);
+	mtsdr(SD0_AMP1, (reg & 0x000000FF) | 0x0000FF00);
+	reg = mfdcr(PLB3_ACR);
+	mtdcr(PLB3_ACR, reg | 0x80000000);
+
+	/*
+	 * Set priority for all PLB4 devices to 0.
+	 */
+	mfsdr(SD0_AMP0, reg);
+	mtsdr(SD0_AMP0, (reg & 0x000000FF) | 0x0000FF00);
+	reg = mfdcr(PLB4_ACR) | 0xa0000000;
+	mtdcr(PLB4_ACR, reg);
+
+	/*
+	 * Set Nebula PLB4 arbiter to fair mode.
+	 */
+	/* Segment0 */
+	reg = (mfdcr(PLB0_ACR) & ~PLB0_ACR_PPM_MASK) | PLB0_ACR_PPM_FAIR;
+	reg = (reg & ~PLB0_ACR_HBU_MASK) | PLB0_ACR_HBU_ENABLED;
+	reg = (reg & ~PLB0_ACR_RDP_MASK) | PLB0_ACR_RDP_4DEEP;
+	reg = (reg & ~PLB0_ACR_WRP_MASK) | PLB0_ACR_WRP_2DEEP;
+	mtdcr(PLB0_ACR, reg);
+
+	/* Segment1 */
+	reg = (mfdcr(PLB1_ACR) & ~PLB1_ACR_PPM_MASK) | PLB1_ACR_PPM_FAIR;
+	reg = (reg & ~PLB1_ACR_HBU_MASK) | PLB1_ACR_HBU_ENABLED;
+	reg = (reg & ~PLB1_ACR_RDP_MASK) | PLB1_ACR_RDP_4DEEP;
+	reg = (reg & ~PLB1_ACR_WRP_MASK) | PLB1_ACR_WRP_2DEEP;
+	mtdcr(PLB1_ACR, reg);
+
+#if defined(CONFIG_SYS_PCI_BOARD_FIXUP_IRQ)
+	hose->fixup_irq = board_pci_fixup_irq;
+#endif
+
+	return 1;
+}
+
+#else /* defined(CONFIG_440EP) ... */
+
+#if defined(CONFIG_SYS_PCI_TARGET_INIT)
+void __pci_target_init(struct pci_controller * hose)
+{
+	/*
+	 * Disable everything
+	 */
+	out_le32((void *)PCIL0_PIM0SA, 0); /* disable */
+	out_le32((void *)PCIL0_PIM1SA, 0); /* disable */
+	out_le32((void *)PCIL0_PIM2SA, 0); /* disable */
+	out_le32((void *)PCIL0_EROMBA, 0); /* disable expansion rom */
+
+	/*
+	 * Map all of SDRAM to PCI address 0x0000_0000. Note that the 440
+	 * strapping options do not support sizes such as 128/256 MB.
+	 */
+	out_le32((void *)PCIL0_PIM0LAL, CONFIG_SYS_SDRAM_BASE);
+	out_le32((void *)PCIL0_PIM0LAH, 0);
+	out_le32((void *)PCIL0_PIM0SA, ~(gd->ram_size - 1) | 1);
+	out_le32((void *)PCIL0_BAR0, 0);
+
+	/*
+	 * Program the board's subsystem id/vendor id
+	 */
+	out_le16((void *)PCIL0_SBSYSVID, CONFIG_SYS_PCI_SUBSYS_VENDORID);
+	out_le16((void *)PCIL0_SBSYSID, CONFIG_SYS_PCI_SUBSYS_DEVICEID);
+
+	out_le16((void *)PCIL0_CMD, in_le16((void *)PCIL0_CMD) |
+		 PCI_COMMAND_MEMORY);
+}
+#endif /* CONFIG_SYS_PCI_TARGET_INIT */
+
+int __pci_pre_init(struct pci_controller *hose)
+{
+	/*
+	 * This board is always configured as the host & requires the
+	 * PCI arbiter to be enabled.
+	 */
+	if (!pci_arbiter_enabled()) {
+		printf("PCI: PCI Arbiter disabled!\n");
+		return 0;
+	}
+
+	return 1;
+}
+
+#endif /* defined(CONFIG_440EP) ... */
+
+#if defined(CONFIG_SYS_PCI_TARGET_INIT)
+void pci_target_init(struct pci_controller * hose)
+	__attribute__((weak, alias("__pci_target_init")));
+#endif /* CONFIG_SYS_PCI_TARGET_INIT */
+
+int pci_pre_init(struct pci_controller *hose)
+	__attribute__((weak, alias("__pci_pre_init")));
+
+#if defined(CONFIG_SYS_PCI_MASTER_INIT)
+void __pci_master_init(struct pci_controller *hose)
+{
+	u16 reg;
+
+	/*
+	 * Write the PowerPC440 EP PCI Configuration regs.
+	 * Enable PowerPC440 EP to be a master on the PCI bus (PMM).
+	 * Enable PowerPC440 EP to act as a PCI memory target (PTM).
+	 */
+	pci_read_config_word(0, PCI_COMMAND, &reg);
+	pci_write_config_word(0, PCI_COMMAND, reg |
+			      PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+}
+void pci_master_init(struct pci_controller *hose)
+	__attribute__((weak, alias("__pci_master_init")));
+#endif /* CONFIG_SYS_PCI_MASTER_INIT */
+
+int pci_440_init (struct pci_controller *hose)
+{
+	int reg_num = 0;
+
+#ifndef CONFIG_DISABLE_PISE_TEST
+	/*--------------------------------------------------------------------------+
+	 * The PCI initialization sequence enable bit must be set ... if not abort
+	 * pci setup since updating the bit requires chip reset.
+	 *--------------------------------------------------------------------------*/
+#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+	unsigned long strap;
+
+	mfsdr(SDR0_SDSTP1,strap);
+	if ((strap & SDR0_SDSTP1_PISE_MASK) == 0) {
+		printf("PCI: SDR0_STRP1[PISE] not set.\n");
+		printf("PCI: Configuration aborted.\n");
+		return -1;
+	}
+#elif defined(CONFIG_440GP)
+	unsigned long strap;
+
+	strap = mfdcr(CPC0_STRP1);
+	if ((strap & CPC0_STRP1_PISE_MASK) == 0) {
+		printf("PCI: CPC0_STRP1[PISE] not set.\n");
+		printf("PCI: Configuration aborted.\n");
+		return -1;
+	}
+#endif
+#endif /* CONFIG_DISABLE_PISE_TEST */
+
+	/*--------------------------------------------------------------------------+
+	 * PCI controller init
+	 *--------------------------------------------------------------------------*/
+	hose->first_busno = 0;
+	hose->last_busno = 0;
+
+	/* PCI I/O space */
+	pci_set_region(hose->regions + reg_num++,
+		       0x00000000,
+		       PCIL0_IOBASE,
+		       0x10000,
+		       PCI_REGION_IO);
+
+	/* PCI memory space */
+	pci_set_region(hose->regions + reg_num++,
+		       CONFIG_SYS_PCI_TARGBASE,
+		       CONFIG_SYS_PCI_MEMBASE,
+#ifdef CONFIG_SYS_PCI_MEMSIZE
+		       CONFIG_SYS_PCI_MEMSIZE,
+#else
+		       0x10000000,
+#endif
+		       PCI_REGION_MEM );
+
+#if defined(CONFIG_PCI_SYS_MEM_BUS) && defined(CONFIG_PCI_SYS_MEM_PHYS) && \
+	defined(CONFIG_PCI_SYS_MEM_SIZE)
+	/* System memory space */
+	pci_set_region(hose->regions + reg_num++,
+		       CONFIG_PCI_SYS_MEM_BUS,
+		       CONFIG_PCI_SYS_MEM_PHYS,
+		       CONFIG_PCI_SYS_MEM_SIZE,
+		       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY );
+#endif
+
+	hose->region_count = reg_num;
+
+	pci_setup_indirect(hose, PCIL0_CFGADR, PCIL0_CFGDATA);
+
+	/* Let board change/modify hose & do initial checks */
+	if (pci_pre_init(hose) == 0) {
+		printf("PCI: Board-specific initialization failed.\n");
+		printf("PCI: Configuration aborted.\n");
+		return -1;
+	}
+
+	pci_register_hose( hose );
+
+	/*--------------------------------------------------------------------------+
+	 * PCI target init
+	 *--------------------------------------------------------------------------*/
+#if defined(CONFIG_SYS_PCI_TARGET_INIT)
+	pci_target_init(hose);                /* Let board setup pci target */
+#else
+	out16r( PCIL0_SBSYSVID, CONFIG_SYS_PCI_SUBSYS_VENDORID );
+	out16r( PCIL0_SBSYSID, CONFIG_SYS_PCI_SUBSYS_ID );
+	out16r( PCIL0_CLS, 0x00060000 ); /* Bridge, host bridge */
+#endif
+
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	out32r( PCIL0_BRDGOPT1, 0x04000060 );               /* PLB Rq pri highest   */
+	out32r( PCIL0_BRDGOPT2, in32(PCIL0_BRDGOPT2) | 0x83 ); /* Enable host config, clear Timeout, ensure int src1  */
+#elif defined(PCIL0_BRDGOPT1)
+	out32r( PCIL0_BRDGOPT1, 0x10000060 );               /* PLB Rq pri highest   */
+	out32r( PCIL0_BRDGOPT2, in32(PCIL0_BRDGOPT2) | 1 ); /* Enable host config   */
+#endif
+
+	/*--------------------------------------------------------------------------+
+	 * PCI master init: default is one 256MB region for PCI memory:
+	 * 0x3_00000000 - 0x3_0FFFFFFF  ==> CONFIG_SYS_PCI_MEMBASE
+	 *--------------------------------------------------------------------------*/
+#if defined(CONFIG_SYS_PCI_MASTER_INIT)
+	pci_master_init(hose);          /* Let board setup pci master */
+#else
+	out32r( PCIL0_POM0SA, 0 ); /* disable */
+	out32r( PCIL0_POM1SA, 0 ); /* disable */
+	out32r( PCIL0_POM2SA, 0 ); /* disable */
+#if defined(CONFIG_440SPE)
+	out32r( PCIL0_POM0LAL, 0x10000000 );
+	out32r( PCIL0_POM0LAH, 0x0000000c );
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	out32r( PCIL0_POM0LAL, 0x20000000 );
+	out32r( PCIL0_POM0LAH, 0x0000000c );
+#else
+	out32r( PCIL0_POM0LAL, 0x00000000 );
+	out32r( PCIL0_POM0LAH, 0x00000003 );
+#endif
+	out32r( PCIL0_POM0PCIAL, CONFIG_SYS_PCI_MEMBASE );
+	out32r( PCIL0_POM0PCIAH, 0x00000000 );
+	out32r( PCIL0_POM0SA, 0xf0000001 ); /* 256MB, enabled */
+	out32r( PCIL0_STS, in32r( PCIL0_STS ) & ~0x0000fff8 );
+#endif
+
+	/*--------------------------------------------------------------------------+
+	 * PCI host configuration -- we don't make any assumptions here ... the
+	 * _board_must_indicate_ what to do -- there's just too many runtime
+	 * scenarios in environments like cPCI, PPMC, etc. to make a determination
+	 * based on hard-coded values or state of arbiter enable.
+	 *--------------------------------------------------------------------------*/
+	if (is_pci_host(hose)) {
+#ifdef CONFIG_PCI_SCAN_SHOW
+		printf("PCI:   Bus Dev VenId DevId Class Int\n");
+#endif
+#if !defined(CONFIG_440EP) && !defined(CONFIG_440GR) && \
+    !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX)
+		out16r( PCIL0_CMD, in16r( PCIL0_CMD ) | PCI_COMMAND_MASTER);
+#endif
+		hose->last_busno = pci_hose_scan(hose);
+	}
+	return hose->last_busno;
+}
+
+void pci_init_board(void)
+{
+	int busno;
+
+	busno = pci_440_init (&ppc440_hose);
+#if (defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)) && \
+    !defined(CONFIG_PCI_DISABLE_PCIE)
+	pcie_setup_hoses(busno + 1);
+#endif
+}
+
+#endif /* CONFIG_440 */
+
+#if defined(CONFIG_405EX)
+void pci_init_board(void)
+{
+#ifdef CONFIG_PCI_SCAN_SHOW
+	printf("PCI:   Bus Dev VenId DevId Class Int\n");
+#endif
+	pcie_setup_hoses(0);
+}
+#endif /* CONFIG_405EX */
+
+#endif /* CONFIG_PCI */
diff --git a/arch/powerpc/cpu/ppc4xx/4xx_pcie.c b/arch/powerpc/cpu/ppc4xx/4xx_pcie.c
new file mode 100644
index 0000000..10b58b7
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/4xx_pcie.c
@@ -0,0 +1,1298 @@
+/*
+ * (C) Copyright 2006 - 2008
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Roland Dreier <rolandd@cisco.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#if 0
+#define DEBUG
+#endif
+
+#include <common.h>
+#include <pci.h>
+#include <ppc4xx.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+#if (defined(CONFIG_440SPE) || defined(CONFIG_405EX) ||	\
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)) && \
+    defined(CONFIG_PCI) && !defined(CONFIG_PCI_DISABLE_PCIE)
+
+#include <asm/4xx_pcie.h>
+
+enum {
+	PTYPE_ENDPOINT		= 0x0,
+	PTYPE_LEGACY_ENDPOINT	= 0x1,
+	PTYPE_ROOT_PORT		= 0x4,
+
+	LNKW_X1			= 0x1,
+	LNKW_X4			= 0x4,
+	LNKW_X8			= 0x8
+};
+
+static struct pci_controller pcie_hose[CONFIG_SYS_PCIE_NR_PORTS];
+
+/*
+ * Per default, all cards are present, so we need to check if the
+ * link comes up.
+ */
+int __board_pcie_card_present(int port)
+{
+	return 1;
+}
+int board_pcie_card_present(int port)
+	__attribute__((weak, alias("__board_pcie_card_present")));
+
+/*
+ * Some boards have runtime detection of the first and last PCIe
+ * slot used, so let's provide weak default functions for the
+ * common version.
+ */
+int __board_pcie_first(void)
+{
+	return 0;
+}
+int board_pcie_first(void)
+	__attribute__((weak, alias("__board_pcie_first")));
+
+int __board_pcie_last(void)
+{
+	return CONFIG_SYS_PCIE_NR_PORTS - 1;
+}
+int board_pcie_last(void)
+	__attribute__((weak, alias("__board_pcie_last")));
+
+void __board_pcie_setup_port(int port, int rootpoint)
+{
+	/* noting in this weak default implementation */
+}
+void board_pcie_setup_port(int port, int rootpoint)
+	__attribute__((weak, alias("__board_pcie_setup_port")));
+
+void pcie_setup_hoses(int busno)
+{
+	struct pci_controller *hose;
+	int i, bus;
+	int ret = 0;
+	char *env;
+	unsigned int delay;
+	int first = board_pcie_first();
+	int last = board_pcie_last();
+
+	/*
+	 * Assume we're called after the PCI(X) hose(s) are initialized,
+	 * which takes bus ID 0... and therefore start numbering PCIe's
+	 * from the next number.
+	 */
+	bus = busno;
+
+	for (i = first; i <= last; i++) {
+		/*
+		 * Some boards (e.g. Katmai) can detects via hardware
+		 * if a PCIe card is plugged, so let's check this.
+		 */
+		if (!board_pcie_card_present(i))
+			continue;
+
+		if (is_end_point(i)) {
+			board_pcie_setup_port(i, 0);
+			ret = ppc4xx_init_pcie_endport(i);
+		} else {
+			board_pcie_setup_port(i, 1);
+			ret = ppc4xx_init_pcie_rootport(i);
+		}
+		if (ret == -ENODEV)
+			continue;
+		if (ret) {
+			printf("PCIE%d: initialization as %s failed\n", i,
+			       is_end_point(i) ? "endpoint" : "root-complex");
+			continue;
+		}
+
+		hose = &pcie_hose[i];
+		hose->first_busno = bus;
+		hose->last_busno = bus;
+		hose->current_busno = bus;
+
+		/* setup mem resource */
+		pci_set_region(hose->regions + 0,
+			       CONFIG_SYS_PCIE_MEMBASE + i * CONFIG_SYS_PCIE_MEMSIZE,
+			       CONFIG_SYS_PCIE_MEMBASE + i * CONFIG_SYS_PCIE_MEMSIZE,
+			       CONFIG_SYS_PCIE_MEMSIZE,
+			       PCI_REGION_MEM);
+		hose->region_count = 1;
+		pci_register_hose(hose);
+
+		if (is_end_point(i)) {
+			ppc4xx_setup_pcie_endpoint(hose, i);
+			/*
+			 * Reson for no scanning is endpoint can not generate
+			 * upstream configuration accesses.
+			 */
+		} else {
+			ppc4xx_setup_pcie_rootpoint(hose, i);
+			env = getenv ("pciscandelay");
+			if (env != NULL) {
+				delay = simple_strtoul(env, NULL, 10);
+				if (delay > 5)
+					printf("Warning, expect noticable delay before "
+					       "PCIe scan due to 'pciscandelay' value!\n");
+				mdelay(delay * 1000);
+			}
+
+			/*
+			 * Config access can only go down stream
+			 */
+			hose->last_busno = pci_hose_scan(hose);
+			bus = hose->last_busno + 1;
+		}
+	}
+}
+
+static int validate_endpoint(struct pci_controller *hose)
+{
+	if (hose->cfg_data == (u8 *)CONFIG_SYS_PCIE0_CFGBASE)
+		return (is_end_point(0));
+	else if (hose->cfg_data == (u8 *)CONFIG_SYS_PCIE1_CFGBASE)
+		return (is_end_point(1));
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+	else if (hose->cfg_data == (u8 *)CONFIG_SYS_PCIE2_CFGBASE)
+		return (is_end_point(2));
+#endif
+
+	return 0;
+}
+
+static u8* pcie_get_base(struct pci_controller *hose, unsigned int devfn)
+{
+	u8 *base = (u8*)hose->cfg_data;
+
+	/* use local configuration space for the first bus */
+	if (PCI_BUS(devfn) == 0) {
+		if (hose->cfg_data == (u8*)CONFIG_SYS_PCIE0_CFGBASE)
+			base = (u8*)CONFIG_SYS_PCIE0_XCFGBASE;
+		if (hose->cfg_data == (u8*)CONFIG_SYS_PCIE1_CFGBASE)
+			base = (u8*)CONFIG_SYS_PCIE1_XCFGBASE;
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+		if (hose->cfg_data == (u8*)CONFIG_SYS_PCIE2_CFGBASE)
+			base = (u8*)CONFIG_SYS_PCIE2_XCFGBASE;
+#endif
+	}
+
+	return base;
+}
+
+static void pcie_dmer_disable(void)
+{
+	mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE),
+		mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE)) | GPL_DMER_MASK_DISA);
+	mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE),
+		mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE)) | GPL_DMER_MASK_DISA);
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+	mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE),
+		mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE)) | GPL_DMER_MASK_DISA);
+#endif
+}
+
+static void pcie_dmer_enable(void)
+{
+	mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE0_BASE),
+		mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE)) & ~GPL_DMER_MASK_DISA);
+	mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE1_BASE),
+		mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE)) & ~GPL_DMER_MASK_DISA);
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+	mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE2_BASE),
+		mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE)) & ~GPL_DMER_MASK_DISA);
+#endif
+}
+
+static int pcie_read_config(struct pci_controller *hose, unsigned int devfn,
+	int offset, int len, u32 *val) {
+
+	u8 *address;
+	*val = 0;
+
+	if (validate_endpoint(hose))
+		return 0;		/* No upstream config access */
+
+	/*
+	 * Bus numbers are relative to hose->first_busno
+	 */
+	devfn -= PCI_BDF(hose->first_busno, 0, 0);
+
+	/*
+	 * NOTICE: configuration space ranges are currenlty mapped only for
+	 * the first 16 buses, so such limit must be imposed. In case more
+	 * buses are required the TLB settings in board/amcc/<board>/init.S
+	 * need to be altered accordingly (one bus takes 1 MB of memory space).
+	 */
+	if (PCI_BUS(devfn) >= 16)
+		return 0;
+
+	/*
+	 * Only single device/single function is supported for the primary and
+	 * secondary buses of the 440SPe host bridge.
+	 */
+	if ((!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 0))) &&
+		((PCI_BUS(devfn) == 0) || (PCI_BUS(devfn) == 1)))
+		return 0;
+
+	address = pcie_get_base(hose, devfn);
+	offset += devfn << 4;
+
+	/*
+	 * Reading from configuration space of non-existing device can
+	 * generate transaction errors. For the read duration we suppress
+	 * assertion of machine check exceptions to avoid those.
+	 */
+	pcie_dmer_disable ();
+
+	debug("%s: cfg_data=%08x offset=%08x\n", __func__, hose->cfg_data, offset);
+	switch (len) {
+	case 1:
+		*val = in_8(hose->cfg_data + offset);
+		break;
+	case 2:
+		*val = in_le16((u16 *)(hose->cfg_data + offset));
+		break;
+	default:
+		*val = in_le32((u32*)(hose->cfg_data + offset));
+		break;
+	}
+
+	pcie_dmer_enable ();
+
+	return 0;
+}
+
+static int pcie_write_config(struct pci_controller *hose, unsigned int devfn,
+	int offset, int len, u32 val) {
+
+	u8 *address;
+
+	if (validate_endpoint(hose))
+		return 0;		/* No upstream config access */
+
+	/*
+	 * Bus numbers are relative to hose->first_busno
+	 */
+	devfn -= PCI_BDF(hose->first_busno, 0, 0);
+
+	/*
+	 * Same constraints as in pcie_read_config().
+	 */
+	if (PCI_BUS(devfn) >= 16)
+		return 0;
+
+	if ((!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 0))) &&
+		((PCI_BUS(devfn) == 0) || (PCI_BUS(devfn) == 1)))
+		return 0;
+
+	address = pcie_get_base(hose, devfn);
+	offset += devfn << 4;
+
+	/*
+	 * Suppress MCK exceptions, similar to pcie_read_config()
+	 */
+	pcie_dmer_disable ();
+
+	switch (len) {
+	case 1:
+		out_8(hose->cfg_data + offset, val);
+		break;
+	case 2:
+		out_le16((u16 *)(hose->cfg_data + offset), val);
+		break;
+	default:
+		out_le32((u32 *)(hose->cfg_data + offset), val);
+		break;
+	}
+
+	pcie_dmer_enable ();
+
+	return 0;
+}
+
+int pcie_read_config_byte(struct pci_controller *hose,pci_dev_t dev,int offset,u8 *val)
+{
+	u32 v;
+	int rv;
+
+	rv = pcie_read_config(hose, dev, offset, 1, &v);
+	*val = (u8)v;
+	return rv;
+}
+
+int pcie_read_config_word(struct pci_controller *hose,pci_dev_t dev,int offset,u16 *val)
+{
+	u32 v;
+	int rv;
+
+	rv = pcie_read_config(hose, dev, offset, 2, &v);
+	*val = (u16)v;
+	return rv;
+}
+
+int pcie_read_config_dword(struct pci_controller *hose,pci_dev_t dev,int offset,u32 *val)
+{
+	u32 v;
+	int rv;
+
+	rv = pcie_read_config(hose, dev, offset, 3, &v);
+	*val = (u32)v;
+	return rv;
+}
+
+int pcie_write_config_byte(struct pci_controller *hose,pci_dev_t dev,int offset,u8 val)
+{
+	return pcie_write_config(hose,(u32)dev,offset,1,val);
+}
+
+int pcie_write_config_word(struct pci_controller *hose,pci_dev_t dev,int offset,u16 val)
+{
+	return pcie_write_config(hose,(u32)dev,offset,2,(u32 )val);
+}
+
+int pcie_write_config_dword(struct pci_controller *hose,pci_dev_t dev,int offset,u32 val)
+{
+	return pcie_write_config(hose,(u32)dev,offset,3,(u32 )val);
+}
+
+#if defined(CONFIG_440SPE)
+static void ppc4xx_setup_utl(u32 port) {
+
+	volatile void *utl_base = NULL;
+
+	/*
+	 * Map UTL registers
+	 */
+	switch (port) {
+	case 0:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x20000000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800);
+		break;
+
+	case 1:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x20001000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800);
+		break;
+
+	case 2:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x20002000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800);
+		break;
+	}
+	utl_base = (unsigned int *)(CONFIG_SYS_PCIE_BASE + 0x1000 * port);
+
+	/*
+	 * Set buffer allocations and then assert VRB and TXE.
+	 */
+	out_be32(utl_base + PEUTL_OUTTR,   0x08000000);
+	out_be32(utl_base + PEUTL_INTR,    0x02000000);
+	out_be32(utl_base + PEUTL_OPDBSZ,  0x10000000);
+	out_be32(utl_base + PEUTL_PBBSZ,   0x53000000);
+	out_be32(utl_base + PEUTL_IPHBSZ,  0x08000000);
+	out_be32(utl_base + PEUTL_IPDBSZ,  0x10000000);
+	out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
+	out_be32(utl_base + PEUTL_PCTL,    0x80800066);
+}
+
+static int check_error(void)
+{
+	u32 valPE0, valPE1, valPE2;
+	int err = 0;
+
+	/* SDR0_PEGPLLLCT1 reset */
+	if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000))
+		printf("PCIE: SDR0_PEGPLLLCT1 reset error 0x%x\n", valPE0);
+
+	valPE0 = SDR_READ(PESDR0_RCSSET);
+	valPE1 = SDR_READ(PESDR1_RCSSET);
+	valPE2 = SDR_READ(PESDR2_RCSSET);
+
+	/* SDR0_PExRCSSET rstgu */
+	if (!(valPE0 & 0x01000000) ||
+	    !(valPE1 & 0x01000000) ||
+	    !(valPE2 & 0x01000000)) {
+		printf("PCIE:  SDR0_PExRCSSET rstgu error\n");
+		err = -1;
+	}
+
+	/* SDR0_PExRCSSET rstdl */
+	if (!(valPE0 & 0x00010000) ||
+	    !(valPE1 & 0x00010000) ||
+	    !(valPE2 & 0x00010000)) {
+		printf("PCIE:  SDR0_PExRCSSET rstdl error\n");
+		err = -1;
+	}
+
+	/* SDR0_PExRCSSET rstpyn */
+	if ((valPE0 & 0x00001000) ||
+	    (valPE1 & 0x00001000) ||
+	    (valPE2 & 0x00001000)) {
+		printf("PCIE:  SDR0_PExRCSSET rstpyn error\n");
+		err = -1;
+	}
+
+	/* SDR0_PExRCSSET hldplb */
+	if ((valPE0 & 0x10000000) ||
+	    (valPE1 & 0x10000000) ||
+	    (valPE2 & 0x10000000)) {
+		printf("PCIE:  SDR0_PExRCSSET hldplb error\n");
+		err = -1;
+	}
+
+	/* SDR0_PExRCSSET rdy */
+	if ((valPE0 & 0x00100000) ||
+	    (valPE1 & 0x00100000) ||
+	    (valPE2 & 0x00100000)) {
+		printf("PCIE:  SDR0_PExRCSSET rdy error\n");
+		err = -1;
+	}
+
+	/* SDR0_PExRCSSET shutdown */
+	if ((valPE0 & 0x00000100) ||
+	    (valPE1 & 0x00000100) ||
+	    (valPE2 & 0x00000100)) {
+		printf("PCIE:  SDR0_PExRCSSET shutdown error\n");
+		err = -1;
+	}
+	return err;
+}
+
+/*
+ * Initialize PCI Express core
+ */
+int ppc4xx_init_pcie(void)
+{
+	int time_out = 20;
+
+	/* Set PLL clock receiver to LVPECL */
+	SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) | 1 << 28);
+
+	if (check_error()) {
+		printf("ERROR: failed to set PCIe reference clock receiver --"
+			"PESDR0_PLLLCT1 = 0x%08x\n", SDR_READ(PESDR0_PLLLCT1));
+
+		return -1;
+	}
+
+	/* Did resistance calibration work? */
+	if (!(SDR_READ(PESDR0_PLLLCT2) & 0x10000)) {
+		printf("ERROR: PCIe resistance calibration failed --"
+			"PESDR0_PLLLCT2 = 0x%08x\n", SDR_READ(PESDR0_PLLLCT2));
+
+		return -1;
+	}
+	/* De-assert reset of PCIe PLL, wait for lock */
+	SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24));
+	udelay(300);	/* 300 uS is maximum time lock should take */
+
+	while (time_out) {
+		if (!(SDR_READ(PESDR0_PLLLCT3) & 0x10000000)) {
+			time_out--;
+			udelay(20);	/* Wait 20 uS more if needed */
+		} else
+			break;
+	}
+	if (!time_out) {
+		printf("ERROR: PCIe PLL VCO output not locked to ref clock --"
+			"PESDR0_PLLLCTS=0x%08x\n", SDR_READ(PESDR0_PLLLCT3));
+
+		return -1;
+	}
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+static void ppc4xx_setup_utl(u32 port)
+{
+	volatile void *utl_base = NULL;
+
+	/*
+	 * Map UTL registers at 0x0801_n000 (4K 0xfff mask) PEGPLn_REGMSK
+	 */
+	switch (port) {
+	case 0:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE0), U64_TO_U32_HIGH(CONFIG_SYS_PCIE0_UTLBASE));
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE0), U64_TO_U32_LOW(CONFIG_SYS_PCIE0_UTLBASE));
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001);	/* BAM 11100000=4KB */
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0);
+		break;
+
+	case 1:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE1), U64_TO_U32_HIGH(CONFIG_SYS_PCIE0_UTLBASE));
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE1), U64_TO_U32_LOW(CONFIG_SYS_PCIE0_UTLBASE)
+			+ 0x1000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001);	/* BAM 11100000=4KB */
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0);
+		break;
+	}
+	utl_base = (unsigned int *)(CONFIG_SYS_PCIE_BASE + 0x1000 * port);
+
+	/*
+	 * Set buffer allocations and then assert VRB and TXE.
+	 */
+	out_be32(utl_base + PEUTL_PBCTL, 0x0800000c);	/* PLBME, CRRE */
+	out_be32(utl_base + PEUTL_OUTTR, 0x08000000);
+	out_be32(utl_base + PEUTL_INTR, 0x02000000);
+	out_be32(utl_base + PEUTL_OPDBSZ, 0x04000000);	/* OPD = 512 Bytes */
+	out_be32(utl_base + PEUTL_PBBSZ, 0x00000000);	/* Max 512 Bytes */
+	out_be32(utl_base + PEUTL_IPHBSZ, 0x02000000);
+	out_be32(utl_base + PEUTL_IPDBSZ, 0x04000000);	/* IPD = 512 Bytes */
+	out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
+	out_be32(utl_base + PEUTL_PCTL, 0x80800066);	/* VRB,TXE,timeout=default */
+}
+
+/*
+ * TODO: double check PCI express SDR based on the latest user manual
+ *		 Some registers specified here no longer exist.. has to be
+ *		 updated based on the final EAS spec.
+ */
+static int check_error(void)
+{
+	u32 valPE0, valPE1;
+	int err = 0;
+
+	valPE0 = SDR_READ(SDRN_PESDR_RCSSET(0));
+	valPE1 = SDR_READ(SDRN_PESDR_RCSSET(1));
+
+	/* SDR0_PExRCSSET rstgu */
+	if (!(valPE0 & PESDRx_RCSSET_RSTGU) || !(valPE1 & PESDRx_RCSSET_RSTGU)) {
+		printf("PCIE:  SDR0_PExRCSSET rstgu error\n");
+		err = -1;
+	}
+
+	/* SDR0_PExRCSSET rstdl */
+	if (!(valPE0 & PESDRx_RCSSET_RSTDL) || !(valPE1 & PESDRx_RCSSET_RSTDL)) {
+		printf("PCIE:  SDR0_PExRCSSET rstdl error\n");
+		err = -1;
+	}
+
+	/* SDR0_PExRCSSET rstpyn */
+	if ((valPE0 & PESDRx_RCSSET_RSTPYN) || (valPE1 & PESDRx_RCSSET_RSTPYN)) {
+		printf("PCIE:  SDR0_PExRCSSET rstpyn error\n");
+		err = -1;
+	}
+
+	/* SDR0_PExRCSSET hldplb */
+	if ((valPE0 & PESDRx_RCSSET_HLDPLB) || (valPE1 & PESDRx_RCSSET_HLDPLB)) {
+		printf("PCIE:  SDR0_PExRCSSET hldplb error\n");
+		err = -1;
+	}
+
+	/* SDR0_PExRCSSET rdy */
+	if ((valPE0 & PESDRx_RCSSET_RDY) || (valPE1 & PESDRx_RCSSET_RDY)) {
+		printf("PCIE:  SDR0_PExRCSSET rdy error\n");
+		err = -1;
+	}
+
+	return err;
+}
+
+/*
+ * Initialize PCI Express core as described in User Manual
+ * TODO: double check PE SDR PLL Register with the updated user manual.
+ */
+int ppc4xx_init_pcie(void)
+{
+	if (check_error())
+		return -1;
+
+	return 0;
+}
+#endif /* CONFIG_460EX */
+
+#if defined(CONFIG_405EX)
+static void ppc4xx_setup_utl(u32 port)
+{
+	u32 utl_base;
+
+	/*
+	 * Map UTL registers at 0xef4f_n000 (4K 0xfff mask) PEGPLn_REGMSK
+	 */
+	switch (port) {
+	case 0:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x00000000);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE0), CONFIG_SYS_PCIE0_UTLBASE);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); /* 4k region, valid */
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0);
+		break;
+
+	case 1:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x00000000);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE1), CONFIG_SYS_PCIE1_UTLBASE);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); /* 4k region, valid */
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0);
+
+		break;
+	}
+	utl_base = (port==0) ? CONFIG_SYS_PCIE0_UTLBASE : CONFIG_SYS_PCIE1_UTLBASE;
+
+	/*
+	 * Set buffer allocations and then assert VRB and TXE.
+	 */
+	out_be32((u32 *)(utl_base + PEUTL_OUTTR),   0x02000000);
+	out_be32((u32 *)(utl_base + PEUTL_INTR),    0x02000000);
+	out_be32((u32 *)(utl_base + PEUTL_OPDBSZ),  0x04000000);
+	out_be32((u32 *)(utl_base + PEUTL_PBBSZ),   0x21000000);
+	out_be32((u32 *)(utl_base + PEUTL_IPHBSZ),  0x02000000);
+	out_be32((u32 *)(utl_base + PEUTL_IPDBSZ),  0x04000000);
+	out_be32((u32 *)(utl_base + PEUTL_RCIRQEN), 0x00f00000);
+	out_be32((u32 *)(utl_base + PEUTL_PCTL),    0x80800066);
+
+	out_be32((u32 *)(utl_base + PEUTL_PBCTL),   0x0800000c);
+	out_be32((u32 *)(utl_base + PEUTL_RCSTA),
+		 in_be32((u32 *)(utl_base + PEUTL_RCSTA)) | 0x000040000);
+}
+
+int ppc4xx_init_pcie(void)
+{
+	/*
+	 * Nothing to do on 405EX
+	 */
+	return 0;
+}
+#endif /* CONFIG_405EX */
+
+/*
+ * Board-specific pcie initialization
+ * Platform code can reimplement ppc4xx_init_pcie_port_hw() if needed
+ */
+
+/*
+ * Initialize various parts of the PCI Express core for our port:
+ *
+ * - Set as a root port and enable max width
+ *   (PXIE0 -> X8, PCIE1 and PCIE2 -> X4).
+ * - Set up UTL configuration.
+ * - Increase SERDES drive strength to levels suggested by AMCC.
+ * - De-assert RSTPYN, RSTDL and RSTGU.
+ *
+ * NOTICE for 440SPE revB chip: PESDRn_UTLSET2 is not set - we leave it
+ * with default setting 0x11310000. The register has new fields,
+ * PESDRn_UTLSET2[LKINE] in particular: clearing it leads to PCIE core
+ * hang.
+ */
+#if defined(CONFIG_440SPE)
+int __ppc4xx_init_pcie_port_hw(int port, int rootport)
+{
+	u32 val = 1 << 24;
+	u32 utlset1;
+
+	if (rootport) {
+		val = PTYPE_ROOT_PORT << 20;
+		utlset1 = 0x21222222;
+	} else {
+		val = PTYPE_LEGACY_ENDPOINT << 20;
+		utlset1 = 0x20222222;
+	}
+
+	if (port == 0)
+		val |= LNKW_X8 << 12;
+	else
+		val |= LNKW_X4 << 12;
+
+	SDR_WRITE(SDRN_PESDR_DLPSET(port), val);
+	SDR_WRITE(SDRN_PESDR_UTLSET1(port), utlset1);
+	if (!ppc440spe_revB())
+		SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x11000000);
+	SDR_WRITE(SDRN_PESDR_HSSL0SET1(port), 0x35000000);
+	SDR_WRITE(SDRN_PESDR_HSSL1SET1(port), 0x35000000);
+	SDR_WRITE(SDRN_PESDR_HSSL2SET1(port), 0x35000000);
+	SDR_WRITE(SDRN_PESDR_HSSL3SET1(port), 0x35000000);
+	if (port == 0) {
+		SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000);
+	}
+	SDR_WRITE(SDRN_PESDR_RCSSET(port), (SDR_READ(SDRN_PESDR_RCSSET(port)) &
+					    ~(1 << 24 | 1 << 16)) | 1 << 12);
+
+	return 0;
+}
+#endif /* CONFIG_440SPE */
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+int __ppc4xx_init_pcie_port_hw(int port, int rootport)
+{
+	u32 val;
+	u32 utlset1;
+
+	if (rootport)
+		val = PTYPE_ROOT_PORT << 20;
+	else
+		val = PTYPE_LEGACY_ENDPOINT << 20;
+
+	if (port == 0) {
+		val |= LNKW_X1 << 12;
+		utlset1 = 0x20000000;
+	} else {
+		val |= LNKW_X4 << 12;
+		utlset1 = 0x20101101;
+	}
+
+	SDR_WRITE(SDRN_PESDR_DLPSET(port), val);
+	SDR_WRITE(SDRN_PESDR_UTLSET1(port), utlset1);
+	SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x01210000);
+
+	switch (port) {
+	case 0:
+		SDR_WRITE(PESDR0_L0CDRCTL, 0x00003230);
+		SDR_WRITE(PESDR0_L0DRV, 0x00000130);
+		SDR_WRITE(PESDR0_L0CLK, 0x00000006);
+
+		SDR_WRITE(PESDR0_PHY_CTL_RST,0x10000000);
+		break;
+
+	case 1:
+		SDR_WRITE(PESDR1_L0CDRCTL, 0x00003230);
+		SDR_WRITE(PESDR1_L1CDRCTL, 0x00003230);
+		SDR_WRITE(PESDR1_L2CDRCTL, 0x00003230);
+		SDR_WRITE(PESDR1_L3CDRCTL, 0x00003230);
+		SDR_WRITE(PESDR1_L0DRV, 0x00000130);
+		SDR_WRITE(PESDR1_L1DRV, 0x00000130);
+		SDR_WRITE(PESDR1_L2DRV, 0x00000130);
+		SDR_WRITE(PESDR1_L3DRV, 0x00000130);
+		SDR_WRITE(PESDR1_L0CLK, 0x00000006);
+		SDR_WRITE(PESDR1_L1CLK, 0x00000006);
+		SDR_WRITE(PESDR1_L2CLK, 0x00000006);
+		SDR_WRITE(PESDR1_L3CLK, 0x00000006);
+
+		SDR_WRITE(PESDR1_PHY_CTL_RST,0x10000000);
+		break;
+	}
+
+	SDR_WRITE(SDRN_PESDR_RCSSET(port), SDR_READ(SDRN_PESDR_RCSSET(port)) |
+		  (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN));
+
+	/* Poll for PHY reset */
+	switch (port) {
+	case 0:
+		while (!(SDR_READ(PESDR0_RSTSTA) & 0x1))
+			udelay(10);
+		break;
+	case 1:
+		while (!(SDR_READ(PESDR1_RSTSTA) & 0x1))
+			udelay(10);
+		break;
+	}
+
+	SDR_WRITE(SDRN_PESDR_RCSSET(port),
+		  (SDR_READ(SDRN_PESDR_RCSSET(port)) &
+		   ~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) |
+		  PESDRx_RCSSET_RSTPYN);
+
+	return 0;
+}
+#endif /* CONFIG_440SPE */
+
+#if defined(CONFIG_405EX)
+int __ppc4xx_init_pcie_port_hw(int port, int rootport)
+{
+	u32 val;
+
+	if (rootport)
+		val = 0x00401000;
+	else
+		val = 0x00101000;
+
+	SDR_WRITE(SDRN_PESDR_DLPSET(port), val);
+	SDR_WRITE(SDRN_PESDR_UTLSET1(port), 0x00000000);
+	SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x01010000);
+	SDR_WRITE(SDRN_PESDR_PHYSET1(port), 0x720F0000);
+	SDR_WRITE(SDRN_PESDR_PHYSET2(port), 0x70600003);
+
+	/* Assert the PE0_PHY reset */
+	SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01010000);
+	udelay(1000);
+
+	/* deassert the PE0_hotreset */
+	if (is_end_point(port))
+		SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01111000);
+	else
+		SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01101000);
+
+	/* poll for phy !reset */
+	while (!(SDR_READ(SDRN_PESDR_PHYSTA(port)) & 0x00001000))
+		;
+
+	/* deassert the PE0_gpl_utl_reset */
+	SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x00101000);
+
+	if (port == 0)
+		mtdcr(DCRN_PEGPL_CFG(PCIE0), 0x10000000);  /* guarded on */
+	else
+		mtdcr(DCRN_PEGPL_CFG(PCIE1), 0x10000000);  /* guarded on */
+
+	return 0;
+}
+#endif /* CONFIG_405EX */
+
+int ppc4xx_init_pcie_port_hw(int port, int rootport)
+__attribute__((weak, alias("__ppc4xx_init_pcie_port_hw")));
+
+/*
+ * We map PCI Express configuration access into the 512MB regions
+ *
+ * NOTICE: revB is very strict about PLB real addressess and ranges to
+ * be mapped for config space; it seems to only work with d_nnnn_nnnn
+ * range (hangs the core upon config transaction attempts when set
+ * otherwise) while revA uses c_nnnn_nnnn.
+ *
+ * For 440SPe revA:
+ *     PCIE0: 0xc_4000_0000
+ *     PCIE1: 0xc_8000_0000
+ *     PCIE2: 0xc_c000_0000
+ *
+ * For 440SPe revB:
+ *     PCIE0: 0xd_0000_0000
+ *     PCIE1: 0xd_2000_0000
+ *     PCIE2: 0xd_4000_0000
+ *
+ * For 405EX:
+ *     PCIE0: 0xa000_0000
+ *     PCIE1: 0xc000_0000
+ *
+ * For 460EX/GT:
+ *     PCIE0: 0xd_0000_0000
+ *     PCIE1: 0xd_2000_0000
+ */
+static inline u64 ppc4xx_get_cfgaddr(int port)
+{
+#if defined(CONFIG_405EX)
+	if (port == 0)
+		return (u64)CONFIG_SYS_PCIE0_CFGBASE;
+	else
+		return (u64)CONFIG_SYS_PCIE1_CFGBASE;
+#endif
+#if defined(CONFIG_440SPE)
+	if (ppc440spe_revB()) {
+		switch (port) {
+		default:	/* to satisfy compiler */
+		case 0:
+			return 0x0000000d00000000ULL;
+		case 1:
+			return 0x0000000d20000000ULL;
+		case 2:
+			return 0x0000000d40000000ULL;
+		}
+	} else {
+		switch (port) {
+		default:	/* to satisfy compiler */
+		case 0:
+			return 0x0000000c40000000ULL;
+		case 1:
+			return 0x0000000c80000000ULL;
+		case 2:
+			return 0x0000000cc0000000ULL;
+		}
+	}
+#endif
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	if (port == 0)
+		return 0x0000000d00000000ULL;
+	else
+		return 0x0000000d20000000ULL;
+#endif
+}
+
+/*
+ *  4xx boards as endpoint and root point setup
+ *                    and
+ *    testing inbound and out bound windows
+ *
+ *  4xx boards can be plugged into another 4xx boards or you can get PCI-E
+ *  cable which can be used to setup loop back from one port to another port.
+ *  Please rememeber that unless there is a endpoint plugged in to root port it
+ *  will not initialize. It is the same in case of endpoint , unless there is
+ *  root port attached it will not initialize.
+ *
+ *  In this release of software all the PCI-E ports are configured as either
+ *  endpoint or rootpoint.In future we will have support for selective ports
+ *  setup as endpoint and root point in single board.
+ *
+ *  Once your board came up as root point , you can verify by reading
+ *  /proc/bus/pci/devices. Where you can see the configuration registers
+ *  of endpoint device attached to the port.
+ *
+ *  Enpoint cofiguration can be verified by connecting 4xx board to any
+ *  host or another 4xx board. Then try to scan the device. In case of
+ *  linux use "lspci" or appripriate os command.
+ *
+ *  How do I verify the inbound and out bound windows ? (4xx to 4xx)
+ *  in this configuration inbound and outbound windows are setup to access
+ *  sram memroy area. SRAM is at 0x4 0000 0000 , on PLB bus. This address
+ *  is mapped at 0x90000000. From u-boot prompt write data 0xb000 0000,
+ *  This is waere your POM(PLB out bound memory window) mapped. then
+ *  read the data from other 4xx board's u-boot prompt at address
+ *  0x9000 0000(SRAM). Data should match.
+ *  In case of inbound , write data to u-boot command prompt at 0xb000 0000
+ *  which is mapped to 0x4 0000 0000. Now on rootpoint yucca u-boot prompt check
+ *  data at 0x9000 0000(SRAM).Data should match.
+ */
+int ppc4xx_init_pcie_port(int port, int rootport)
+{
+	static int core_init;
+	volatile u32 val = 0;
+	int attempts;
+	u64 addr;
+	u32 low, high;
+
+	if (!core_init) {
+		if (ppc4xx_init_pcie())
+			return -1;
+		++core_init;
+	}
+
+	/*
+	 * Initialize various parts of the PCI Express core for our port
+	 */
+	ppc4xx_init_pcie_port_hw(port, rootport);
+
+	/*
+	 * Notice: the following delay has critical impact on device
+	 * initialization - if too short (<50ms) the link doesn't get up.
+	 */
+	mdelay(100);
+
+	val = SDR_READ(SDRN_PESDR_RCSSTS(port));
+	if (val & (1 << 20)) {
+		printf("PCIE%d: PGRST failed %08x\n", port, val);
+		return -1;
+	}
+
+	/*
+	 * Verify link is up
+	 */
+	val = SDR_READ(SDRN_PESDR_LOOP(port));
+	if (!(val & 0x00001000)) {
+		printf("PCIE%d: link is not up.\n", port);
+		return -ENODEV;
+	}
+
+	/*
+	 * Setup UTL registers - but only on revA!
+	 * We use default settings for revB chip.
+	 */
+	if (!ppc440spe_revB())
+		ppc4xx_setup_utl(port);
+
+	/*
+	 * We map PCI Express configuration access into the 512MB regions
+	 */
+	addr = ppc4xx_get_cfgaddr(port);
+	low = U64_TO_U32_LOW(addr);
+	high = U64_TO_U32_HIGH(addr);
+
+	switch (port) {
+	case 0:
+		mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), high);
+		mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), low);
+		mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */
+		break;
+	case 1:
+		mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), high);
+		mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), low);
+		mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */
+		break;
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+	case 2:
+		mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), high);
+		mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), low);
+		mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */
+		break;
+#endif
+	}
+
+	/*
+	 * Check for VC0 active and assert RDY.
+	 */
+	attempts = 10;
+	while(!(SDR_READ(SDRN_PESDR_RCSSTS(port)) & (1 << 16))) {
+		if (!(attempts--)) {
+			printf("PCIE%d: VC0 not active\n", port);
+			return -1;
+		}
+		mdelay(1000);
+	}
+	SDR_WRITE(SDRN_PESDR_RCSSET(port),
+		  SDR_READ(SDRN_PESDR_RCSSET(port)) | 1 << 20);
+	mdelay(100);
+
+	return 0;
+}
+
+int ppc4xx_init_pcie_rootport(int port)
+{
+	return ppc4xx_init_pcie_port(port, 1);
+}
+
+int ppc4xx_init_pcie_endport(int port)
+{
+	return ppc4xx_init_pcie_port(port, 0);
+}
+
+void ppc4xx_setup_pcie_rootpoint(struct pci_controller *hose, int port)
+{
+	volatile void *mbase = NULL;
+	volatile void *rmbase = NULL;
+
+	pci_set_ops(hose,
+		    pcie_read_config_byte,
+		    pcie_read_config_word,
+		    pcie_read_config_dword,
+		    pcie_write_config_byte,
+		    pcie_write_config_word,
+		    pcie_write_config_dword);
+
+	switch (port) {
+	case 0:
+		mbase = (u32 *)CONFIG_SYS_PCIE0_XCFGBASE;
+		rmbase = (u32 *)CONFIG_SYS_PCIE0_CFGBASE;
+		hose->cfg_data = (u8 *)CONFIG_SYS_PCIE0_CFGBASE;
+		break;
+	case 1:
+		mbase = (u32 *)CONFIG_SYS_PCIE1_XCFGBASE;
+		rmbase = (u32 *)CONFIG_SYS_PCIE1_CFGBASE;
+		hose->cfg_data = (u8 *)CONFIG_SYS_PCIE1_CFGBASE;
+		break;
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+	case 2:
+		mbase = (u32 *)CONFIG_SYS_PCIE2_XCFGBASE;
+		rmbase = (u32 *)CONFIG_SYS_PCIE2_CFGBASE;
+		hose->cfg_data = (u8 *)CONFIG_SYS_PCIE2_CFGBASE;
+		break;
+#endif
+	}
+
+	/*
+	 * Set bus numbers on our root port
+	 */
+	out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0);
+	out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1);
+	out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1);
+
+	/*
+	 * Set up outbound translation to hose->mem_space from PLB
+	 * addresses at an offset of 0xd_0000_0000.  We set the low
+	 * bits of the mask to 11 to turn off splitting into 8
+	 * subregions and to enable the outbound translation.
+	 */
+	out_le32(mbase + PECFG_POM0LAH, 0x00000000);
+	out_le32(mbase + PECFG_POM0LAL, CONFIG_SYS_PCIE_MEMBASE +
+		 port * CONFIG_SYS_PCIE_MEMSIZE);
+	debug("PECFG_POM0LA=%08x.%08x\n", in_le32(mbase + PECFG_POM0LAH),
+	      in_le32(mbase + PECFG_POM0LAL));
+
+	switch (port) {
+	case 0:
+		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), CONFIG_SYS_PCIE_ADDR_HIGH);
+		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CONFIG_SYS_PCIE_MEMBASE +
+		      port * CONFIG_SYS_PCIE_MEMSIZE);
+		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff);
+		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0),
+		      ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3);
+		debug("0:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n",
+		      mfdcr(DCRN_PEGPL_OMR1BAH(PCIE0)),
+		      mfdcr(DCRN_PEGPL_OMR1BAL(PCIE0)),
+		      mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE0)),
+		      mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE0)));
+		break;
+	case 1:
+		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), CONFIG_SYS_PCIE_ADDR_HIGH);
+		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), CONFIG_SYS_PCIE_MEMBASE +
+		      port * CONFIG_SYS_PCIE_MEMSIZE);
+		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff);
+		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1),
+		      ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3);
+		debug("1:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n",
+		      mfdcr(DCRN_PEGPL_OMR1BAH(PCIE1)),
+		      mfdcr(DCRN_PEGPL_OMR1BAL(PCIE1)),
+		      mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE1)),
+		      mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE1)));
+		break;
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+	case 2:
+		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), CONFIG_SYS_PCIE_ADDR_HIGH);
+		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), CONFIG_SYS_PCIE_MEMBASE +
+		      port * CONFIG_SYS_PCIE_MEMSIZE);
+		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff);
+		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2),
+		      ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3);
+		debug("2:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n",
+		      mfdcr(DCRN_PEGPL_OMR1BAH(PCIE2)),
+		      mfdcr(DCRN_PEGPL_OMR1BAL(PCIE2)),
+		      mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE2)),
+		      mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE2)));
+		break;
+#endif
+	}
+
+	/* Set up 4GB inbound memory window at 0 */
+	out_le32(mbase + PCI_BASE_ADDRESS_0, 0);
+	out_le32(mbase + PCI_BASE_ADDRESS_1, 0);
+	out_le32(mbase + PECFG_BAR0HMPA, 0x7ffffff);
+	out_le32(mbase + PECFG_BAR0LMPA, 0);
+
+	out_le32(mbase + PECFG_PIM01SAH, 0xffff0000);
+	out_le32(mbase + PECFG_PIM01SAL, 0x00000000);
+	out_le32(mbase + PECFG_PIM0LAL, 0);
+	out_le32(mbase + PECFG_PIM0LAH, 0);
+	out_le32(mbase + PECFG_PIM1LAL, 0x00000000);
+	out_le32(mbase + PECFG_PIM1LAH, 0x00000004);
+	out_le32(mbase + PECFG_PIMEN, 0x1);
+
+	/* Enable I/O, Mem, and Busmaster cycles */
+	out_le16((u16 *)(mbase + PCI_COMMAND),
+		 in_le16((u16 *)(mbase + PCI_COMMAND)) |
+		 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+	/* Set Device and Vendor Id */
+	out_le16(mbase + 0x200, 0xaaa0 + port);
+	out_le16(mbase + 0x202, 0xbed0 + port);
+
+	/* Set Class Code to PCI-PCI bridge and Revision Id to 1 */
+	out_le32(mbase + 0x208, 0x06040001);
+
+	printf("PCIE%d: successfully set as root-complex\n", port);
+}
+
+int ppc4xx_setup_pcie_endpoint(struct pci_controller *hose, int port)
+{
+	volatile void *mbase = NULL;
+	int attempts = 0;
+
+	pci_set_ops(hose,
+		    pcie_read_config_byte,
+		    pcie_read_config_word,
+		    pcie_read_config_dword,
+		    pcie_write_config_byte,
+		    pcie_write_config_word,
+		    pcie_write_config_dword);
+
+	switch (port) {
+	case 0:
+		mbase = (u32 *)CONFIG_SYS_PCIE0_XCFGBASE;
+		hose->cfg_data = (u8 *)CONFIG_SYS_PCIE0_CFGBASE;
+		break;
+	case 1:
+		mbase = (u32 *)CONFIG_SYS_PCIE1_XCFGBASE;
+		hose->cfg_data = (u8 *)CONFIG_SYS_PCIE1_CFGBASE;
+		break;
+#if defined(CONFIG_SYS_PCIE2_CFGBASE)
+	case 2:
+		mbase = (u32 *)CONFIG_SYS_PCIE2_XCFGBASE;
+		hose->cfg_data = (u8 *)CONFIG_SYS_PCIE2_CFGBASE;
+		break;
+#endif
+	}
+
+	/*
+	 * Set up outbound translation to hose->mem_space from PLB
+	 * addresses at an offset of 0xd_0000_0000.  We set the low
+	 * bits of the mask to 11 to turn off splitting into 8
+	 * subregions and to enable the outbound translation.
+	 */
+	out_le32(mbase + PECFG_POM0LAH, 0x00001ff8);
+	out_le32(mbase + PECFG_POM0LAL, 0x00001000);
+
+	switch (port) {
+	case 0:
+		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), CONFIG_SYS_PCIE_ADDR_HIGH);
+		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CONFIG_SYS_PCIE_MEMBASE +
+		      port * CONFIG_SYS_PCIE_MEMSIZE);
+		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff);
+		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0),
+		      ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3);
+		break;
+	case 1:
+		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), CONFIG_SYS_PCIE_ADDR_HIGH);
+		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), CONFIG_SYS_PCIE_MEMBASE +
+		      port * CONFIG_SYS_PCIE_MEMSIZE);
+		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff);
+		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1),
+		      ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3);
+		break;
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+	case 2:
+		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), CONFIG_SYS_PCIE_ADDR_HIGH);
+		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), CONFIG_SYS_PCIE_MEMBASE +
+		      port * CONFIG_SYS_PCIE_MEMSIZE);
+		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff);
+		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2),
+		      ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3);
+		break;
+#endif
+	}
+
+	/* Set up 64MB inbound memory window at 0 */
+	out_le32(mbase + PCI_BASE_ADDRESS_0, 0);
+	out_le32(mbase + PCI_BASE_ADDRESS_1, 0);
+
+	out_le32(mbase + PECFG_PIM01SAH, 0xffffffff);
+	out_le32(mbase + PECFG_PIM01SAL, 0xfc000000);
+
+	/* Setup BAR0 */
+	out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffff);
+	out_le32(mbase + PECFG_BAR0LMPA, 0xfc000000 | PCI_BASE_ADDRESS_MEM_TYPE_64);
+
+	/* Disable BAR1 & BAR2 */
+	out_le32(mbase + PECFG_BAR1MPA, 0);
+	out_le32(mbase + PECFG_BAR2HMPA, 0);
+	out_le32(mbase + PECFG_BAR2LMPA, 0);
+
+	out_le32(mbase + PECFG_PIM0LAL, U64_TO_U32_LOW(CONFIG_SYS_PCIE_INBOUND_BASE));
+	out_le32(mbase + PECFG_PIM0LAH, U64_TO_U32_HIGH(CONFIG_SYS_PCIE_INBOUND_BASE));
+	out_le32(mbase + PECFG_PIMEN, 0x1);
+
+	/* Enable I/O, Mem, and Busmaster cycles */
+	out_le16((u16 *)(mbase + PCI_COMMAND),
+		 in_le16((u16 *)(mbase + PCI_COMMAND)) |
+		 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+	out_le16(mbase + 0x200, 0xcaad);		/* Setting vendor ID */
+	out_le16(mbase + 0x202, 0xfeed);		/* Setting device ID */
+
+	/* Set Class Code to Processor/PPC */
+	out_le32(mbase + 0x208, 0x0b200001);
+
+	attempts = 10;
+	while(!(SDR_READ(SDRN_PESDR_RCSSTS(port)) & (1 << 8))) {
+		if (!(attempts--)) {
+			printf("PCIE%d: BME not active\n", port);
+			return -1;
+		}
+		mdelay(1000);
+	}
+
+	printf("PCIE%d: successfully set as endpoint\n", port);
+
+	return 0;
+}
+#endif /* CONFIG_440SPE && CONFIG_PCI */
diff --git a/arch/powerpc/cpu/ppc4xx/4xx_uart.c b/arch/powerpc/cpu/ppc4xx/4xx_uart.c
new file mode 100644
index 0000000..8de6542
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/4xx_uart.c
@@ -0,0 +1,878 @@
+/*
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This source code is dual-licensed.  You may use it under the terms of the
+ * GNU General Public License version 2, or under the license below.
+ *
+ * This source code has been made available to you by IBM on an AS-IS
+ * basis.  Anyone receiving this source is licensed under IBM
+ * copyrights to use it in any way he or she deems fit, including
+ * copying it, modifying it, compiling it, and redistributing it either
+ * with or without modifications.  No license under IBM patents or
+ * patent applications is to be implied by the copyright license.
+ *
+ * Any user of this software should understand that IBM cannot provide
+ * technical support for this software and will not be responsible for
+ * any consequences resulting from the use of this software.
+ *
+ * Any person who transfers this source code or any derivative work
+ * must include the IBM copyright notice, this paragraph, and the
+ * preceding two paragraphs in the transferred software.
+ *
+ * COPYRIGHT   I B M   CORPORATION 1995
+ * LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
+ */
+
+#include <common.h>
+#include <commproc.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <watchdog.h>
+#include <ppc4xx.h>
+
+#ifdef CONFIG_SERIAL_MULTI
+#include <serial.h>
+#endif
+
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
+#include <malloc.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
+    defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
+    defined(CONFIG_405EX) || defined(CONFIG_440)
+
+#if defined(CONFIG_440)
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UART0_BASE	(CONFIG_SYS_PERIPHERAL_BASE + 0x00000300)
+#define UART1_BASE	(CONFIG_SYS_PERIPHERAL_BASE + 0x00000400)
+#else
+#define UART0_BASE	(CONFIG_SYS_PERIPHERAL_BASE + 0x00000200)
+#define UART1_BASE	(CONFIG_SYS_PERIPHERAL_BASE + 0x00000300)
+#endif
+
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+#define UART2_BASE	(CONFIG_SYS_PERIPHERAL_BASE + 0x00000600)
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UART2_BASE	(CONFIG_SYS_PERIPHERAL_BASE + 0x00000500)
+#define UART3_BASE	(CONFIG_SYS_PERIPHERAL_BASE + 0x00000600)
+#endif
+
+#if defined(CONFIG_440GP)
+#define CR0_MASK        0x3fff0000
+#define CR0_EXTCLK_ENA  0x00600000
+#define CR0_UDIV_POS    16
+#define UDIV_SUBTRACT	1
+#define UART0_SDR	CPC0_CR0
+#define MFREG(a, d)	d = mfdcr(a)
+#define MTREG(a, d)	mtdcr(a, d)
+#else /* #if defined(CONFIG_440GP) */
+/* all other 440 PPC's access clock divider via sdr register */
+#define CR0_MASK        0xdfffffff
+#define CR0_EXTCLK_ENA  0x00800000
+#define CR0_UDIV_POS    0
+#define UDIV_SUBTRACT	0
+#define UART0_SDR	SDR0_UART0
+#define UART1_SDR	SDR0_UART1
+#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \
+    defined(CONFIG_440GR) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UART2_SDR	SDR0_UART2
+#endif
+#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \
+    defined(CONFIG_440GR) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UART3_SDR	SDR0_UART3
+#endif
+#define MFREG(a, d)	mfsdr(a, d)
+#define MTREG(a, d)	mtsdr(a, d)
+#endif /* #if defined(CONFIG_440GP) */
+#elif defined(CONFIG_405EP) || defined(CONFIG_405EZ)
+#define UART0_BASE      0xef600300
+#define UART1_BASE      0xef600400
+#define UCR0_MASK       0x0000007f
+#define UCR1_MASK       0x00007f00
+#define UCR0_UDIV_POS   0
+#define UCR1_UDIV_POS   8
+#define UDIV_MAX        127
+#elif defined(CONFIG_405EX)
+#define UART0_BASE	0xef600200
+#define UART1_BASE	0xef600300
+#define CR0_MASK	0x000000ff
+#define CR0_EXTCLK_ENA	0x00800000
+#define CR0_UDIV_POS	0
+#define UDIV_SUBTRACT	0
+#define UART0_SDR	SDR0_UART0
+#define UART1_SDR	SDR0_UART1
+#else /* CONFIG_405GP || CONFIG_405CR */
+#define UART0_BASE      0xef600300
+#define UART1_BASE      0xef600400
+#define CR0_MASK        0x00001fff
+#define CR0_EXTCLK_ENA  0x000000c0
+#define CR0_UDIV_POS    1
+#define UDIV_MAX        32
+#endif
+
+/* using serial port 0 or 1 as U-Boot console ? */
+#if defined(CONFIG_UART1_CONSOLE)
+#define ACTING_UART0_BASE	UART1_BASE
+#define ACTING_UART1_BASE	UART0_BASE
+#else
+#define ACTING_UART0_BASE	UART0_BASE
+#define ACTING_UART1_BASE	UART1_BASE
+#endif
+
+#if defined(CONFIG_405EP) && defined(CONFIG_SYS_EXT_SERIAL_CLOCK)
+#error "External serial clock not supported on AMCC PPC405EP!"
+#endif
+
+#define UART_RBR    0x00
+#define UART_THR    0x00
+#define UART_IER    0x01
+#define UART_IIR    0x02
+#define UART_FCR    0x02
+#define UART_LCR    0x03
+#define UART_MCR    0x04
+#define UART_LSR    0x05
+#define UART_MSR    0x06
+#define UART_SCR    0x07
+#define UART_DLL    0x00
+#define UART_DLM    0x01
+
+/*-----------------------------------------------------------------------------+
+  | Line Status Register.
+  +-----------------------------------------------------------------------------*/
+#define asyncLSRDataReady1            0x01
+#define asyncLSROverrunError1         0x02
+#define asyncLSRParityError1          0x04
+#define asyncLSRFramingError1         0x08
+#define asyncLSRBreakInterrupt1       0x10
+#define asyncLSRTxHoldEmpty1          0x20
+#define asyncLSRTxShiftEmpty1         0x40
+#define asyncLSRRxFifoError1          0x80
+
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
+/*-----------------------------------------------------------------------------+
+  | Fifo
+  +-----------------------------------------------------------------------------*/
+typedef struct {
+	char *rx_buffer;
+	ulong rx_put;
+	ulong rx_get;
+} serial_buffer_t;
+
+volatile static serial_buffer_t buf_info;
+#endif
+
+static void serial_init_common(u32 base, u32 udiv, u16 bdiv)
+{
+	PPC4xx_SYS_INFO sys_info;
+	u8 val;
+
+	get_sys_info(&sys_info);
+
+	/* Correct UART frequency in bd-info struct now that
+	 * the UART divisor is available
+	 */
+#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK
+	gd->uart_clk = CONFIG_SYS_EXT_SERIAL_CLOCK;
+#else
+	gd->uart_clk = sys_info.freqUART / udiv;
+#endif
+
+	out_8((u8 *)base + UART_LCR, 0x80);	/* set DLAB bit */
+	out_8((u8 *)base + UART_DLL, bdiv);	/* set baudrate divisor */
+	out_8((u8 *)base + UART_DLM, bdiv >> 8); /* set baudrate divisor */
+	out_8((u8 *)base + UART_LCR, 0x03);	/* clear DLAB; set 8 bits, no parity */
+	out_8((u8 *)base + UART_FCR, 0x00);	/* disable FIFO */
+	out_8((u8 *)base + UART_MCR, 0x00);	/* no modem control DTR RTS */
+	val = in_8((u8 *)base + UART_LSR);	/* clear line status */
+	val = in_8((u8 *)base + UART_RBR);	/* read receive buffer */
+	out_8((u8 *)base + UART_SCR, 0x00);	/* set scratchpad */
+	out_8((u8 *)base + UART_IER, 0x00);	/* set interrupt enable reg */
+}
+
+#if (defined(CONFIG_440) || defined(CONFIG_405EX)) &&	\
+    !defined(CONFIG_SYS_EXT_SERIAL_CLOCK)
+static void serial_divs (int baudrate, unsigned long *pudiv,
+			 unsigned short *pbdiv)
+{
+	sys_info_t sysinfo;
+	unsigned long div;		/* total divisor udiv * bdiv */
+	unsigned long umin;		/* minimum udiv	*/
+	unsigned short diff;		/* smallest diff */
+	unsigned long udiv;		/* best udiv */
+	unsigned short idiff;		/* current diff */
+	unsigned short ibdiv;		/* current bdiv */
+	unsigned long i;
+	unsigned long est;		/* current estimate */
+
+	get_sys_info(&sysinfo);
+
+	udiv = 32;			/* Assume lowest possible serial clk */
+	div = sysinfo.freqPLB / (16 * baudrate); /* total divisor */
+	umin = sysinfo.pllOpbDiv << 1;	/* 2 x OPB divisor */
+	diff = 32;			/* highest possible */
+
+	/* i is the test udiv value -- start with the largest
+	 * possible (32) to minimize serial clock and constrain
+	 * search to umin.
+	 */
+	for (i = 32; i > umin; i--) {
+		ibdiv = div / i;
+		est = i * ibdiv;
+		idiff = (est > div) ? (est-div) : (div-est);
+		if (idiff == 0) {
+			udiv = i;
+			break;      /* can't do better */
+		} else if (idiff < diff) {
+			udiv = i;       /* best so far */
+			diff = idiff;   /* update lowest diff*/
+		}
+	}
+
+	*pudiv = udiv;
+	*pbdiv = div / udiv;
+}
+
+#elif defined(CONFIG_405EZ)
+
+static void serial_divs (int baudrate, unsigned long *pudiv,
+			 unsigned short *pbdiv)
+{
+	sys_info_t sysinfo;
+	unsigned long div;		/* total divisor udiv * bdiv */
+	unsigned long umin;		/* minimum udiv	*/
+	unsigned short diff;		/* smallest diff */
+	unsigned long udiv;		/* best udiv */
+	unsigned short idiff;		/* current diff */
+	unsigned short ibdiv;		/* current bdiv */
+	unsigned long i;
+	unsigned long est;		/* current estimate */
+	unsigned long plloutb;
+	unsigned long cpr_pllc;
+	u32 reg;
+
+	/* check the pll feedback source */
+	mfcpr(CPR0_PLLC, cpr_pllc);
+
+	get_sys_info(&sysinfo);
+
+	plloutb = ((CONFIG_SYS_CLK_FREQ * ((cpr_pllc & PLLC_SRC_MASK) ?
+					   sysinfo.pllFwdDivB : sysinfo.pllFwdDiv) *
+		    sysinfo.pllFbkDiv) / sysinfo.pllFwdDivB);
+	udiv = 256;			/* Assume lowest possible serial clk */
+	div = plloutb / (16 * baudrate); /* total divisor */
+	umin = (plloutb / get_OPB_freq()) << 1;	/* 2 x OPB divisor */
+	diff = 256;			/* highest possible */
+
+	/* i is the test udiv value -- start with the largest
+	 * possible (256) to minimize serial clock and constrain
+	 * search to umin.
+	 */
+	for (i = 256; i > umin; i--) {
+		ibdiv = div / i;
+		est = i * ibdiv;
+		idiff = (est > div) ? (est-div) : (div-est);
+		if (idiff == 0) {
+			udiv = i;
+			break;      /* can't do better */
+		} else if (idiff < diff) {
+			udiv = i;       /* best so far */
+			diff = idiff;   /* update lowest diff*/
+		}
+	}
+
+	*pudiv = udiv;
+	mfcpr(CPC0_PERD0, reg);
+	reg &= ~0x0000ffff;
+	reg |= ((udiv - 0) << 8) | (udiv - 0);
+	mtcpr(CPC0_PERD0, reg);
+	*pbdiv = div / udiv;
+}
+#endif /* defined(CONFIG_440) && !defined(CONFIG_SYS_EXT_SERIAL_CLK) */
+
+/*
+ * Minimal serial functions needed to use one of the SMC ports
+ * as serial console interface.
+ */
+
+#if defined(CONFIG_440)
+int serial_init_dev(unsigned long base)
+{
+	unsigned long reg;
+	unsigned long udiv;
+	unsigned short bdiv;
+#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK
+	unsigned long tmp;
+#endif
+
+	MFREG(UART0_SDR, reg);
+	reg &= ~CR0_MASK;
+
+#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK
+	reg |= CR0_EXTCLK_ENA;
+	udiv = 1;
+	tmp  = gd->baudrate * 16;
+	bdiv = (CONFIG_SYS_EXT_SERIAL_CLOCK + tmp / 2) / tmp;
+#else
+	/* For 440, the cpu clock is on divider chain A, UART on divider
+	 * chain B ... so cpu clock is irrelevant. Get the "optimized"
+	 * values that are subject to the 1/2 opb clock constraint
+	 */
+	serial_divs (gd->baudrate, &udiv, &bdiv);
+#endif
+
+	reg |= (udiv - UDIV_SUBTRACT) << CR0_UDIV_POS;	/* set the UART divisor */
+
+	/*
+	 * Configure input clock to baudrate generator for all
+	 * available serial ports here
+	 */
+	MTREG(UART0_SDR, reg);
+#if defined(UART1_SDR)
+	MTREG(UART1_SDR, reg);
+#endif
+#if defined(UART2_SDR)
+	MTREG(UART2_SDR, reg);
+#endif
+#if defined(UART3_SDR)
+	MTREG(UART3_SDR, reg);
+#endif
+
+	serial_init_common(base, udiv, bdiv);
+
+	return (0);
+}
+
+#else /* !defined(CONFIG_440) */
+
+int serial_init_dev (unsigned long base)
+{
+	unsigned long reg;
+	unsigned long tmp;
+	unsigned long clk;
+	unsigned long udiv;
+	unsigned short bdiv;
+
+#ifdef CONFIG_405EX
+	clk = tmp = 0;
+	mfsdr(UART0_SDR, reg);
+	reg &= ~CR0_MASK;
+#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK
+	reg |= CR0_EXTCLK_ENA;
+	udiv = 1;
+	tmp  = gd->baudrate * 16;
+	bdiv = (CONFIG_SYS_EXT_SERIAL_CLOCK + tmp / 2) / tmp;
+#else
+	serial_divs(gd->baudrate, &udiv, &bdiv);
+#endif
+	reg |= (udiv - UDIV_SUBTRACT) << CR0_UDIV_POS;  /* set the UART divisor */
+
+	/*
+	 * Configure input clock to baudrate generator for all
+	 * available serial ports here
+	 */
+	mtsdr(UART0_SDR, reg);
+
+#if defined(UART1_SDR)
+	mtsdr(UART1_SDR, reg);
+#endif
+
+#elif defined(CONFIG_405EZ)
+	serial_divs(gd->baudrate, &udiv, &bdiv);
+	clk = tmp = reg = 0;
+#else
+#ifdef CONFIG_405EP
+	reg = mfdcr(CPC0_UCR) & ~(UCR0_MASK | UCR1_MASK);
+	clk = gd->cpu_clk;
+	tmp = CONFIG_SYS_BASE_BAUD * 16;
+	udiv = (clk + tmp / 2) / tmp;
+	if (udiv > UDIV_MAX)                    /* max. n bits for udiv */
+		udiv = UDIV_MAX;
+	reg |= (udiv) << UCR0_UDIV_POS;	        /* set the UART divisor */
+	reg |= (udiv) << UCR1_UDIV_POS;	        /* set the UART divisor */
+	mtdcr (CPC0_UCR, reg);
+#else /* CONFIG_405EP */
+	reg = mfdcr(CPC0_CR0) & ~CR0_MASK;
+#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK
+	clk = CONFIG_SYS_EXT_SERIAL_CLOCK;
+	udiv = 1;
+	reg |= CR0_EXTCLK_ENA;
+#else
+	clk = gd->cpu_clk;
+#ifdef CONFIG_SYS_405_UART_ERRATA_59
+	udiv = 31;			/* Errata 59: stuck at 31 */
+#else
+	tmp = CONFIG_SYS_BASE_BAUD * 16;
+	udiv = (clk + tmp / 2) / tmp;
+	if (udiv > UDIV_MAX)                    /* max. n bits for udiv */
+		udiv = UDIV_MAX;
+#endif
+#endif
+	reg |= (udiv - 1) << CR0_UDIV_POS;	/* set the UART divisor */
+	mtdcr (CPC0_CR0, reg);
+#endif /* CONFIG_405EP */
+	tmp = gd->baudrate * udiv * 16;
+	bdiv = (clk + tmp / 2) / tmp;
+#endif /* CONFIG_405EX */
+
+	serial_init_common(base, udiv, bdiv);
+
+	return (0);
+}
+
+#endif /* if defined(CONFIG_440) */
+
+void serial_setbrg_dev(unsigned long base)
+{
+	serial_init_dev(base);
+}
+
+void serial_putc_dev(unsigned long base, const char c)
+{
+	int i;
+
+	if (c == '\n')
+		serial_putc_dev(base, '\r');
+
+	/* check THRE bit, wait for transmiter available */
+	for (i = 1; i < 3500; i++) {
+		if ((in_8((u8 *)base + UART_LSR) & 0x20) == 0x20)
+			break;
+		udelay (100);
+	}
+
+	out_8((u8 *)base + UART_THR, c);	/* put character out */
+}
+
+void serial_puts_dev (unsigned long base, const char *s)
+{
+	while (*s)
+		serial_putc_dev (base, *s++);
+}
+
+int serial_getc_dev (unsigned long base)
+{
+	unsigned char status = 0;
+
+	while (1) {
+#if defined(CONFIG_HW_WATCHDOG)
+		WATCHDOG_RESET ();	/* Reset HW Watchdog, if needed */
+#endif	/* CONFIG_HW_WATCHDOG */
+
+		status = in_8((u8 *)base + UART_LSR);
+		if ((status & asyncLSRDataReady1) != 0x0)
+			break;
+
+		if ((status & ( asyncLSRFramingError1 |
+				asyncLSROverrunError1 |
+				asyncLSRParityError1  |
+				asyncLSRBreakInterrupt1 )) != 0) {
+			out_8((u8 *)base + UART_LSR,
+			      asyncLSRFramingError1 |
+			      asyncLSROverrunError1 |
+			      asyncLSRParityError1  |
+			      asyncLSRBreakInterrupt1);
+		}
+	}
+
+	return (0x000000ff & (int) in_8((u8 *)base));
+}
+
+int serial_tstc_dev (unsigned long base)
+{
+	unsigned char status;
+
+	status = in_8((u8 *)base + UART_LSR);
+	if ((status & asyncLSRDataReady1) != 0x0)
+		return (1);
+
+	if ((status & ( asyncLSRFramingError1 |
+			asyncLSROverrunError1 |
+			asyncLSRParityError1  |
+			asyncLSRBreakInterrupt1 )) != 0) {
+		out_8((u8 *)base + UART_LSR,
+		      asyncLSRFramingError1 |
+		      asyncLSROverrunError1 |
+		      asyncLSRParityError1  |
+		      asyncLSRBreakInterrupt1);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
+
+void serial_isr (void *arg)
+{
+	int space;
+	int c;
+	const int rx_get = buf_info.rx_get;
+	int rx_put = buf_info.rx_put;
+
+	if (rx_get <= rx_put)
+		space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get);
+	else
+		space = rx_get - rx_put;
+
+	while (serial_tstc_dev (ACTING_UART0_BASE)) {
+		c = serial_getc_dev (ACTING_UART0_BASE);
+		if (space) {
+			buf_info.rx_buffer[rx_put++] = c;
+			space--;
+		}
+		if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO)
+			rx_put = 0;
+		if (space < CONFIG_SERIAL_SOFTWARE_FIFO / 4) {
+			/* Stop flow by setting RTS inactive */
+			out_8((u8 *)ACTING_UART0_BASE + UART_MCR,
+			      in_8((u8 *)ACTING_UART0_BASE + UART_MCR) &
+			      (0xFF ^ 0x02));
+		}
+	}
+	buf_info.rx_put = rx_put;
+}
+
+void serial_buffered_init (void)
+{
+	serial_puts ("Switching to interrupt driven serial input mode.\n");
+	buf_info.rx_buffer = malloc (CONFIG_SERIAL_SOFTWARE_FIFO);
+	buf_info.rx_put = 0;
+	buf_info.rx_get = 0;
+
+	if (in_8((u8 *)ACTING_UART0_BASE + UART_MSR) & 0x10)
+		serial_puts ("Check CTS signal present on serial port: OK.\n");
+	else
+		serial_puts ("WARNING: CTS signal not present on serial port.\n");
+
+	irq_install_handler ( VECNUM_U0 /*UART0 */ /*int vec */ ,
+			      serial_isr /*interrupt_handler_t *handler */ ,
+			      (void *) &buf_info /*void *arg */ );
+
+	/* Enable "RX Data Available" Interrupt on UART */
+	out_8(ACTING_UART0_BASE + UART_IER, 0x01);
+	/* Set DTR active */
+	out_8(ACTING_UART0_BASE + UART_MCR,
+	      in_8((u8 *)ACTING_UART0_BASE + UART_MCR) | 0x01);
+	/* Start flow by setting RTS active */
+	out_8(ACTING_UART0_BASE + UART_MCR,
+	      in_8((u8 *)ACTING_UART0_BASE + UART_MCR) | 0x02);
+	/* Setup UART FIFO: RX trigger level: 4 byte, Enable FIFO */
+	out_8(ACTING_UART0_BASE + UART_FCR, (1 << 6) | 1);
+}
+
+void serial_buffered_putc (const char c)
+{
+	/* Wait for CTS */
+#if defined(CONFIG_HW_WATCHDOG)
+	while (!(in_8((u8 *)ACTING_UART0_BASE + UART_MSR) & 0x10))
+		WATCHDOG_RESET ();
+#else
+	while (!(in_8((u8 *)ACTING_UART0_BASE + UART_MSR) & 0x10));
+#endif
+	serial_putc (c);
+}
+
+void serial_buffered_puts (const char *s)
+{
+	serial_puts (s);
+}
+
+int serial_buffered_getc (void)
+{
+	int space;
+	int c;
+	int rx_get = buf_info.rx_get;
+	int rx_put;
+
+#if defined(CONFIG_HW_WATCHDOG)
+	while (rx_get == buf_info.rx_put)
+		WATCHDOG_RESET ();
+#else
+	while (rx_get == buf_info.rx_put);
+#endif
+	c = buf_info.rx_buffer[rx_get++];
+	if (rx_get == CONFIG_SERIAL_SOFTWARE_FIFO)
+		rx_get = 0;
+	buf_info.rx_get = rx_get;
+
+	rx_put = buf_info.rx_put;
+	if (rx_get <= rx_put)
+		space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get);
+	else
+		space = rx_get - rx_put;
+
+	if (space > CONFIG_SERIAL_SOFTWARE_FIFO / 2) {
+		/* Start flow by setting RTS active */
+		out_8(ACTING_UART0_BASE + UART_MCR,
+		      in_8((u8 *)ACTING_UART0_BASE + UART_MCR) | 0x02);
+	}
+
+	return c;
+}
+
+int serial_buffered_tstc (void)
+{
+	return (buf_info.rx_get != buf_info.rx_put) ? 1 : 0;
+}
+
+#endif	/* CONFIG_SERIAL_SOFTWARE_FIFO */
+
+#if defined(CONFIG_CMD_KGDB)
+/*
+  AS HARNOIS : according to CONFIG_KGDB_SER_INDEX kgdb uses serial port
+  number 0 or number 1
+  - if CONFIG_KGDB_SER_INDEX = 1 => serial port number 0 :
+  configuration has been already done
+  - if CONFIG_KGDB_SER_INDEX = 2 => serial port number 1 :
+  configure port 1 for serial I/O with rate = CONFIG_KGDB_BAUDRATE
+*/
+#if (CONFIG_KGDB_SER_INDEX & 2)
+void kgdb_serial_init (void)
+{
+	u8 val;
+	u16 br_reg;
+
+	get_clocks ();
+	br_reg = (((((gd->cpu_clk / 16) / 18) * 10) / CONFIG_KGDB_BAUDRATE) +
+		  5) / 10;
+	/*
+	 * Init onboard 16550 UART
+	 */
+	out_8((u8 *)ACTING_UART1_BASE + UART_LCR, 0x80);	/* set DLAB bit */
+	out_8((u8 *)ACTING_UART1_BASE + UART_DLL, (br_reg & 0x00ff)); /* set divisor for 9600 baud */
+	out_8((u8 *)ACTING_UART1_BASE + UART_DLM, ((br_reg & 0xff00) >> 8)); /* set divisor for 9600 baud */
+	out_8((u8 *)ACTING_UART1_BASE + UART_LCR, 0x03);	/* line control 8 bits no parity */
+	out_8((u8 *)ACTING_UART1_BASE + UART_FCR, 0x00);	/* disable FIFO */
+	out_8((u8 *)ACTING_UART1_BASE + UART_MCR, 0x00);	/* no modem control DTR RTS */
+	val = in_8((u8 *)ACTING_UART1_BASE + UART_LSR);		/* clear line status */
+	val = in_8((u8 *)ACTING_UART1_BASE + UART_RBR);		/* read receive buffer */
+	out_8((u8 *)ACTING_UART1_BASE + UART_SCR, 0x00);	/* set scratchpad */
+	out_8((u8 *)ACTING_UART1_BASE + UART_IER, 0x00);	/* set interrupt enable reg */
+}
+
+void putDebugChar (const char c)
+{
+	if (c == '\n')
+		serial_putc ('\r');
+
+	out_8((u8 *)ACTING_UART1_BASE + UART_THR, c);	/* put character out */
+
+	/* check THRE bit, wait for transfer done */
+	while ((in_8((u8 *)ACTING_UART1_BASE + UART_LSR) & 0x20) != 0x20);
+}
+
+void putDebugStr (const char *s)
+{
+	while (*s)
+		serial_putc (*s++);
+}
+
+int getDebugChar (void)
+{
+	unsigned char status = 0;
+
+	while (1) {
+		status = in_8((u8 *)ACTING_UART1_BASE + UART_LSR);
+		if ((status & asyncLSRDataReady1) != 0x0)
+			break;
+
+		if ((status & (asyncLSRFramingError1 |
+			       asyncLSROverrunError1 |
+			       asyncLSRParityError1  |
+			       asyncLSRBreakInterrupt1 )) != 0) {
+			out_8((u8 *)ACTING_UART1_BASE + UART_LSR,
+			      asyncLSRFramingError1 |
+			      asyncLSROverrunError1 |
+			      asyncLSRParityError1  |
+			      asyncLSRBreakInterrupt1);
+		}
+	}
+
+	return (0x000000ff & (int) in_8((u8 *)ACTING_UART1_BASE));
+}
+
+void kgdb_interruptible (int yes)
+{
+	return;
+}
+
+#else	/* ! (CONFIG_KGDB_SER_INDEX & 2) */
+
+void kgdb_serial_init (void)
+{
+	serial_printf ("[on serial] ");
+}
+
+void putDebugChar (int c)
+{
+	serial_putc (c);
+}
+
+void putDebugStr (const char *str)
+{
+	serial_puts (str);
+}
+
+int getDebugChar (void)
+{
+	return serial_getc ();
+}
+
+void kgdb_interruptible (int yes)
+{
+	return;
+}
+#endif	/* (CONFIG_KGDB_SER_INDEX & 2) */
+#endif
+
+
+#if defined(CONFIG_SERIAL_MULTI)
+int serial0_init(void)
+{
+	return (serial_init_dev(UART0_BASE));
+}
+
+int serial1_init(void)
+{
+	return (serial_init_dev(UART1_BASE));
+}
+
+void serial0_setbrg (void)
+{
+	serial_setbrg_dev(UART0_BASE);
+}
+
+void serial1_setbrg (void)
+{
+	serial_setbrg_dev(UART1_BASE);
+}
+
+void serial0_putc(const char c)
+{
+	serial_putc_dev(UART0_BASE,c);
+}
+
+void serial1_putc(const char c)
+{
+	serial_putc_dev(UART1_BASE, c);
+}
+
+void serial0_puts(const char *s)
+{
+	serial_puts_dev(UART0_BASE, s);
+}
+
+void serial1_puts(const char *s)
+{
+	serial_puts_dev(UART1_BASE, s);
+}
+
+int serial0_getc(void)
+{
+	return(serial_getc_dev(UART0_BASE));
+}
+
+int serial1_getc(void)
+{
+	return(serial_getc_dev(UART1_BASE));
+}
+
+int serial0_tstc(void)
+{
+	return (serial_tstc_dev(UART0_BASE));
+}
+
+int serial1_tstc(void)
+{
+	return (serial_tstc_dev(UART1_BASE));
+}
+
+struct serial_device serial0_device =
+{
+	"serial0",
+	"UART0",
+	serial0_init,
+	serial0_setbrg,
+	serial0_getc,
+	serial0_tstc,
+	serial0_putc,
+	serial0_puts,
+};
+
+struct serial_device serial1_device =
+{
+	"serial1",
+	"UART1",
+	serial1_init,
+	serial1_setbrg,
+	serial1_getc,
+	serial1_tstc,
+	serial1_putc,
+	serial1_puts,
+};
+#else
+/*
+ * Wrapper functions
+ */
+int serial_init(void)
+{
+	return serial_init_dev(ACTING_UART0_BASE);
+}
+
+void serial_setbrg(void)
+{
+	serial_setbrg_dev(ACTING_UART0_BASE);
+}
+
+void serial_putc(const char c)
+{
+	serial_putc_dev(ACTING_UART0_BASE, c);
+}
+
+void serial_puts(const char *s)
+{
+	serial_puts_dev(ACTING_UART0_BASE, s);
+}
+
+int serial_getc(void)
+{
+	return serial_getc_dev(ACTING_UART0_BASE);
+}
+
+int serial_tstc(void)
+{
+	return serial_tstc_dev(ACTING_UART0_BASE);
+}
+#endif /* CONFIG_SERIAL_MULTI */
+
+#endif	/* CONFIG_405GP || CONFIG_405CR */
diff --git a/arch/powerpc/cpu/ppc4xx/Makefile b/arch/powerpc/cpu/ppc4xx/Makefile
new file mode 100644
index 0000000..88d53fb
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/Makefile
@@ -0,0 +1,92 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(CPU).a
+
+START	:= resetvec.o
+START	+= start.o
+
+SOBJS	:= cache.o
+SOBJS	+= dcr.o
+SOBJS	+= kgdb.o
+
+COBJS	:= 40x_spd_sdram.o
+
+COBJS	+= 44x_spd_ddr.o
+COBJS	+= 44x_spd_ddr2.o
+ifdef CONFIG_PPC4xx_DDR_AUTOCALIBRATION
+COBJS	+= 4xx_ibm_ddr2_autocalib.o
+endif
+COBJS	+= 4xx_pci.o
+COBJS	+= 4xx_pcie.o
+COBJS	+= bedbug_405.o
+ifdef CONFIG_CMD_CHIP_CONFIG
+COBJS	+= cmd_chip_config.o
+endif
+COBJS	+= commproc.o
+COBJS	+= cpu.o
+COBJS	+= cpu_init.o
+COBJS	+= denali_data_eye.o
+COBJS	+= denali_spd_ddr2.o
+COBJS	+= ecc.o
+COBJS	+= fdt.o
+COBJS	+= interrupts.o
+COBJS	+= iop480_uart.o
+ifdef CONFIG_CMD_REGINFO
+COBJS	+= reginfo.o
+endif
+COBJS	+= sdram.o
+COBJS	+= speed.o
+COBJS	+= tlb.o
+COBJS	+= traps.o
+COBJS	+= usb.o
+COBJS	+= usb_ohci.o
+COBJS	+= usbdev.o
+ifndef CONFIG_XILINX_440
+COBJS	+= 4xx_uart.o
+COBJS	+= gpio.o
+COBJS	+= miiphy.o
+COBJS	+= uic.o
+else
+COBJS	+= xilinx_irq.o
+endif
+
+SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/ppc4xx/bedbug_405.c b/arch/powerpc/cpu/ppc4xx/bedbug_405.c
new file mode 100644
index 0000000..ef11cb6
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/bedbug_405.c
@@ -0,0 +1,308 @@
+/*
+ * Bedbug Functions specific to the PPC405 chip
+ */
+
+#include <common.h>
+#include <command.h>
+#include <linux/ctype.h>
+#include <bedbug/type.h>
+#include <bedbug/bedbug.h>
+#include <bedbug/regs.h>
+#include <bedbug/ppc.h>
+
+#if defined(CONFIG_CMD_BEDBUG) && defined(CONFIG_4xx)
+
+#define MAX_BREAK_POINTS 4
+
+extern CPU_DEBUG_CTX bug_ctx;
+
+void bedbug405_init __P ((void));
+void bedbug405_do_break __P ((cmd_tbl_t *, int, int, char *[]));
+void bedbug405_break_isr __P ((struct pt_regs *));
+int bedbug405_find_empty __P ((void));
+int bedbug405_set __P ((int, unsigned long));
+int bedbug405_clear __P ((int));
+
+
+/* ======================================================================
+ * Initialize the global bug_ctx structure for the AMCC PPC405.	Clear all
+ * of the breakpoints.
+ * ====================================================================== */
+
+void bedbug405_init (void)
+{
+	int i;
+
+	/* -------------------------------------------------- */
+
+	bug_ctx.hw_debug_enabled = 0;
+	bug_ctx.stopped = 0;
+	bug_ctx.current_bp = 0;
+	bug_ctx.regs = NULL;
+
+	bug_ctx.do_break = bedbug405_do_break;
+	bug_ctx.break_isr = bedbug405_break_isr;
+	bug_ctx.find_empty = bedbug405_find_empty;
+	bug_ctx.set = bedbug405_set;
+	bug_ctx.clear = bedbug405_clear;
+
+	for (i = 1; i <= MAX_BREAK_POINTS; ++i)
+		(*bug_ctx.clear) (i);
+
+	puts ("BEDBUG:ready\n");
+	return;
+}	/* bedbug_init_breakpoints */
+
+
+
+/* ======================================================================
+ * Set/clear/show one of the hardware breakpoints for the 405.	The "off"
+ * string will disable a specific breakpoint.  The "show" string will
+ * display the current breakpoints.  Otherwise an address will set a
+ * breakpoint at that address.	Setting a breakpoint uses the CPU-specific
+ * set routine which will assign a breakpoint number.
+ * ====================================================================== */
+
+void bedbug405_do_break (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	long addr = 0;		/* Address to break at  */
+	int which_bp;		/* Breakpoint number    */
+
+	/* -------------------------------------------------- */
+
+	if (argc < 2) {
+		cmd_usage(cmdtp);
+		return;
+	}
+
+	/* Turn off a breakpoint */
+
+	if (strcmp (argv[1], "off") == 0) {
+		if (bug_ctx.hw_debug_enabled == 0) {
+			printf ("No breakpoints enabled\n");
+			return;
+		}
+
+		which_bp = simple_strtoul (argv[2], NULL, 10);
+
+		if (bug_ctx.clear)
+			(*bug_ctx.clear) (which_bp);
+
+		printf ("Breakpoint %d removed\n", which_bp);
+		return;
+	}
+
+	/* Show a list of breakpoints */
+
+	if (strcmp (argv[1], "show") == 0) {
+		for (which_bp = 1; which_bp <= MAX_BREAK_POINTS; ++which_bp) {
+
+			switch (which_bp) {
+			case 1:
+				addr = GET_IAC1 ();
+				break;
+			case 2:
+				addr = GET_IAC2 ();
+				break;
+			case 3:
+				addr = GET_IAC3 ();
+				break;
+			case 4:
+				addr = GET_IAC4 ();
+				break;
+			}
+
+			printf ("Breakpoint [%d]: ", which_bp);
+			if (addr == 0)
+				printf ("NOT SET\n");
+			else
+				disppc ((unsigned char *) addr, 0, 1, bedbug_puts,
+						F_RADHEX);
+		}
+		return;
+	}
+
+	/* Set a breakpoint at the address */
+
+	if (!isdigit (argv[1][0])) {
+		cmd_usage(cmdtp);
+		return;
+	}
+
+	addr = simple_strtoul (argv[1], NULL, 16) & 0xfffffffc;
+
+	if ((bug_ctx.set) && (which_bp = (*bug_ctx.set) (0, addr)) > 0) {
+		printf ("Breakpoint [%d]: ", which_bp);
+		disppc ((unsigned char *) addr, 0, 1, bedbug_puts, F_RADHEX);
+	}
+
+	return;
+}	/* bedbug405_do_break */
+
+
+
+/* ======================================================================
+ * Handle a breakpoint.	 First determine which breakpoint was hit by
+ * looking at the DeBug Status Register (DBSR), clear the breakpoint
+ * and enter a mini main loop.	Stay in the loop until the stopped flag
+ * in the debug context is cleared.
+ * ====================================================================== */
+
+void bedbug405_break_isr (struct pt_regs *regs)
+{
+	unsigned long dbsr_val;		/* Value of the DBSR    */
+	unsigned long addr = 0;		/* Address stopped at   */
+
+	/* -------------------------------------------------- */
+
+	dbsr_val = GET_DBSR ();
+
+	if (dbsr_val & DBSR_IA1) {
+		bug_ctx.current_bp = 1;
+		addr = GET_IAC1 ();
+		SET_DBSR (DBSR_IA1);	/* Write a 1 to clear */
+	} else if (dbsr_val & DBSR_IA2) {
+		bug_ctx.current_bp = 2;
+		addr = GET_IAC2 ();
+		SET_DBSR (DBSR_IA2);	/* Write a 1 to clear */
+	} else if (dbsr_val & DBSR_IA3) {
+		bug_ctx.current_bp = 3;
+		addr = GET_IAC3 ();
+		SET_DBSR (DBSR_IA3);	/* Write a 1 to clear */
+	} else if (dbsr_val & DBSR_IA4) {
+		bug_ctx.current_bp = 4;
+		addr = GET_IAC4 ();
+		SET_DBSR (DBSR_IA4);	/* Write a 1 to clear */
+	}
+
+	bedbug_main_loop (addr, regs);
+	return;
+}	/* bedbug405_break_isr */
+
+
+
+/* ======================================================================
+ * Look through all of the hardware breakpoints available to see if one
+ * is unused.
+ * ====================================================================== */
+
+int bedbug405_find_empty (void)
+{
+	/* -------------------------------------------------- */
+
+	if (GET_IAC1 () == 0)
+		return 1;
+
+	if (GET_IAC2 () == 0)
+		return 2;
+
+	if (GET_IAC3 () == 0)
+		return 3;
+
+	if (GET_IAC4 () == 0)
+		return 4;
+
+	return 0;
+}	/* bedbug405_find_empty */
+
+
+
+/* ======================================================================
+ * Set a breakpoint.  If 'which_bp' is zero then find an unused breakpoint
+ * number, otherwise reassign the given breakpoint.  If hardware debugging
+ * is not enabled, then turn it on via the MSR and DBCR0.  Set the break
+ * address in the appropriate IACx register and enable proper address
+ * beakpoint in DBCR0.
+ * ====================================================================== */
+
+int bedbug405_set (int which_bp, unsigned long addr)
+{
+	/* -------------------------------------------------- */
+
+	/* Only look if which_bp == 0, else use which_bp */
+	if ((bug_ctx.find_empty) && (!which_bp) &&
+		(which_bp = (*bug_ctx.find_empty) ()) == 0) {
+		printf ("All breakpoints in use\n");
+		return 0;
+	}
+
+	if (which_bp < 1 || which_bp > MAX_BREAK_POINTS) {
+		printf ("Invalid break point # %d\n", which_bp);
+		return 0;
+	}
+
+	if (!bug_ctx.hw_debug_enabled) {
+		SET_MSR (GET_MSR () | 0x200);	/* set MSR[ DE ] */
+		SET_DBCR0 (GET_DBCR0 () | DBCR0_IDM);
+		bug_ctx.hw_debug_enabled = 1;
+	}
+
+	switch (which_bp) {
+	case 1:
+		SET_IAC1 (addr);
+		SET_DBCR0 (GET_DBCR0 () | DBCR0_IA1);
+		break;
+
+	case 2:
+		SET_IAC2 (addr);
+		SET_DBCR0 (GET_DBCR0 () | DBCR0_IA2);
+		break;
+
+	case 3:
+		SET_IAC3 (addr);
+		SET_DBCR0 (GET_DBCR0 () | DBCR0_IA3);
+		break;
+
+	case 4:
+		SET_IAC4 (addr);
+		SET_DBCR0 (GET_DBCR0 () | DBCR0_IA4);
+		break;
+	}
+
+	return which_bp;
+}	/* bedbug405_set */
+
+
+
+/* ======================================================================
+ * Disable a specific breakoint by setting the appropriate IACx register
+ * to zero and claring the instruction address breakpoint in DBCR0.
+ * ====================================================================== */
+
+int bedbug405_clear (int which_bp)
+{
+	/* -------------------------------------------------- */
+
+	if (which_bp < 1 || which_bp > MAX_BREAK_POINTS) {
+		printf ("Invalid break point # (%d)\n", which_bp);
+		return -1;
+	}
+
+	switch (which_bp) {
+	case 1:
+		SET_IAC1 (0);
+		SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA1);
+		break;
+
+	case 2:
+		SET_IAC2 (0);
+		SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA2);
+		break;
+
+	case 3:
+		SET_IAC3 (0);
+		SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA3);
+		break;
+
+	case 4:
+		SET_IAC4 (0);
+		SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA4);
+		break;
+	}
+
+	return 0;
+}	/* bedbug405_clear */
+
+
+/* ====================================================================== */
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/cache.S b/arch/powerpc/cpu/ppc4xx/cache.S
new file mode 100644
index 0000000..269716f
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/cache.S
@@ -0,0 +1,235 @@
+/*
+ * This file contains miscellaneous low-level functions.
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras.
+ *
+ * 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 <config.h>
+#include <config.h>
+#include <ppc4xx.h>
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+/*
+ * Flush instruction cache.
+ */
+_GLOBAL(invalidate_icache)
+	iccci	r0,r0
+	isync
+	blr
+
+/*
+ * Write any modified data cache blocks out to memory
+ * and invalidate the corresponding instruction cache blocks.
+ *
+ * flush_icache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_icache_range)
+	li	r5,L1_CACHE_BYTES-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,L1_CACHE_SHIFT
+	beqlr
+	mtctr	r4
+	mr	r6,r3
+1:	dcbst	0,r3
+	addi	r3,r3,L1_CACHE_BYTES
+	bdnz	1b
+	sync				/* wait for dcbst's to get to ram */
+	mtctr	r4
+2:	icbi	0,r6
+	addi	r6,r6,L1_CACHE_BYTES
+	bdnz	2b
+	sync				/* additional sync needed on g4 */
+	isync
+	blr
+
+/*
+ * Write any modified data cache blocks out to memory.
+ * Does not invalidate the corresponding cache lines (especially for
+ * any corresponding instruction cache).
+ *
+ * clean_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(clean_dcache_range)
+	li	r5,L1_CACHE_BYTES-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,L1_CACHE_SHIFT
+	beqlr
+	mtctr	r4
+
+1:	dcbst	0,r3
+	addi	r3,r3,L1_CACHE_BYTES
+	bdnz	1b
+	sync				/* wait for dcbst's to get to ram */
+	blr
+
+/*
+ * Write any modified data cache blocks out to memory and invalidate them.
+ * Does not invalidate the corresponding instruction cache blocks.
+ *
+ * flush_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_dcache_range)
+	li	r5,L1_CACHE_BYTES-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,L1_CACHE_SHIFT
+	beqlr
+	mtctr	r4
+
+1:	dcbf	0,r3
+	addi	r3,r3,L1_CACHE_BYTES
+	bdnz	1b
+	sync				/* wait for dcbst's to get to ram */
+	blr
+
+/*
+ * Like above, but invalidate the D-cache.  This is used by the 8xx
+ * to invalidate the cache so the PPC core doesn't get stale data
+ * from the CPM (no cache snooping here :-).
+ *
+ * invalidate_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(invalidate_dcache_range)
+	li	r5,L1_CACHE_BYTES-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,L1_CACHE_SHIFT
+	beqlr
+	mtctr	r4
+
+1:	dcbi	0,r3
+	addi	r3,r3,L1_CACHE_BYTES
+	bdnz	1b
+	sync				/* wait for dcbi's to get to ram */
+	blr
+
+/*
+ * 40x cores have 8K or 16K dcache and 32 byte line size.
+ * 44x has a 32K dcache and 32 byte line size.
+ * 8xx has 1, 2, 4, 8K variants.
+ * For now, cover the worst case of the 44x.
+ * Must be called with external interrupts disabled.
+ */
+#define CACHE_NWAYS     64
+#define CACHE_NLINES    32
+
+_GLOBAL(flush_dcache)
+	li	r4,(2 * CACHE_NWAYS * CACHE_NLINES)
+	mtctr	r4
+	lis	r5,0
+1:	lwz	r3,0(r5)		/* Load one word from every line */
+	addi	r5,r5,L1_CACHE_BYTES
+	bdnz	1b
+	sync
+	blr
+
+_GLOBAL(invalidate_dcache)
+	addi	r6,0,0x0000		/* clear GPR 6 */
+	/* Do loop for # of dcache congruence classes. */
+	lis	r7,(CONFIG_SYS_DCACHE_SIZE / L1_CACHE_BYTES / 2)@ha	/* TBS for large sized cache */
+	ori	r7,r7,(CONFIG_SYS_DCACHE_SIZE / L1_CACHE_BYTES / 2)@l
+					/* NOTE: dccci invalidates both */
+	mtctr	r7			/* ways in the D cache */
+..dcloop:
+	dccci	0,r6			/* invalidate line */
+	addi	r6,r6,L1_CACHE_BYTES	/* bump to next line */
+	bdnz	..dcloop
+	sync
+	blr
+
+/*
+ * Cache functions.
+ *
+ * NOTE: currently the 440s run with dcache _disabled_ once relocated to DRAM,
+ * although for some cache-ralated calls stubs have to be provided to satisfy
+ * symbols resolution.
+ * Icache-related functions are used in POST framework.
+ *
+ */
+#ifdef CONFIG_440
+
+       .globl  dcache_disable
+       .globl  dcache_enable
+       .globl  icache_disable
+       .globl  icache_enable
+dcache_disable:
+dcache_enable:
+icache_disable:
+icache_enable:
+	blr
+
+	.globl	dcache_status
+	.globl	icache_status
+dcache_status:
+icache_status:
+	mr	r3,  0
+	blr
+
+#else /* CONFIG_440 */
+
+	.globl	icache_enable
+icache_enable:
+	mflr	r8
+	bl	invalidate_icache
+	mtlr	r8
+	isync
+	addis	r3,r0, 0xc000	      /* set bit 0 */
+	mticcr	r3
+	blr
+
+	.globl	icache_disable
+icache_disable:
+	addis	r3,r0, 0x0000	      /* clear bit 0 */
+	mticcr	r3
+	isync
+	blr
+
+	.globl	icache_status
+icache_status:
+	mficcr	r3
+	srwi	r3, r3, 31	/* >>31 => select bit 0 */
+	blr
+
+	.globl	dcache_enable
+dcache_enable:
+	mflr	r8
+	bl	invalidate_dcache
+	mtlr	r8
+	isync
+	addis	r3,r0, 0x8000	      /* set bit 0 */
+	mtdccr	r3
+	blr
+
+	.globl	dcache_disable
+dcache_disable:
+	mflr	r8
+	bl	flush_dcache
+	mtlr	r8
+	addis	r3,r0, 0x0000	      /* clear bit 0 */
+	mtdccr	r3
+	blr
+
+	.globl	dcache_status
+dcache_status:
+	mfdccr	r3
+	srwi	r3, r3, 31	/* >>31 => select bit 0 */
+	blr
+
+#endif /* CONFIG_440 */
diff --git a/arch/powerpc/cpu/ppc4xx/cmd_chip_config.c b/arch/powerpc/cpu/ppc4xx/cmd_chip_config.c
new file mode 100644
index 0000000..ba57211
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/cmd_chip_config.c
@@ -0,0 +1,148 @@
+/*
+ * (C) Copyright 2008-2009
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * (C) Copyright 2009
+ * Dirk Eibach,  Guntermann & Drunck GmbH, eibach@gdsys.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <i2c.h>
+#include <asm/ppc4xx_config.h>
+#include <asm/io.h>
+
+static void print_configs(int cur_config_nr)
+{
+	int i;
+
+	for (i = 0; i < ppc4xx_config_count; i++) {
+		printf("%-16s - %s", ppc4xx_config_val[i].label,
+		       ppc4xx_config_val[i].description);
+		if (i == cur_config_nr)
+			printf(" ***");
+		printf("\n");
+	}
+
+}
+
+static int do_chip_config(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	int i;
+	int ret;
+	int cur_config_nr = -1;
+	u8 cur_config[CONFIG_4xx_CONFIG_BLOCKSIZE];
+
+	/*
+	 * First switch to correct I2C bus. This is I2C bus 0
+	 * for all currently available 4xx derivats.
+	 */
+	I2C_SET_BUS(0);
+
+#ifdef CONFIG_CMD_EEPROM
+	ret = eeprom_read(CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR,
+			  CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET,
+			  cur_config, CONFIG_4xx_CONFIG_BLOCKSIZE);
+#else
+	ret = i2c_read(CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR,
+		       CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET,
+		       1, cur_config, CONFIG_4xx_CONFIG_BLOCKSIZE);
+#endif
+	if (ret) {
+		printf("Error reading EEPROM at addr 0x%x\n",
+		       CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR);
+		return -1;
+	}
+
+	/*
+	 * Search the current configuration
+	 */
+	for (i = 0; i < ppc4xx_config_count; i++) {
+		if (memcmp(cur_config, ppc4xx_config_val[i].val,
+			   CONFIG_4xx_CONFIG_BLOCKSIZE) == 0)
+			cur_config_nr = i;
+	}
+
+	if (cur_config_nr == -1) {
+		printf("Warning: The I2C bootstrap values don't match any"
+		       " of the available options!\n");
+		printf("I2C bootstrap EEPROM values are (I2C address 0x%02x):\n",
+			CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR);
+		for (i = 0; i < CONFIG_4xx_CONFIG_BLOCKSIZE; i++) {
+			printf("%02x ", cur_config[i]);
+		}
+		printf("\n");
+	}
+
+	if (argc < 2) {
+		printf("Available configurations (I2C address 0x%02x):\n",
+		       CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR);
+		print_configs(cur_config_nr);
+		return 0;
+	}
+
+	for (i = 0; i < ppc4xx_config_count; i++) {
+		/*
+		 * Search for configuration name/label
+		 */
+		if (strcmp(argv[1], ppc4xx_config_val[i].label) == 0) {
+			printf("Using configuration:\n%-16s - %s\n",
+			       ppc4xx_config_val[i].label,
+			       ppc4xx_config_val[i].description);
+
+#ifdef CONFIG_CMD_EEPROM
+			ret = eeprom_write(CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR,
+					   CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET,
+					   ppc4xx_config_val[i].val,
+					   CONFIG_4xx_CONFIG_BLOCKSIZE);
+#else
+			ret = i2c_write(CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR,
+					CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET,
+					1, ppc4xx_config_val[i].val,
+					CONFIG_4xx_CONFIG_BLOCKSIZE);
+#endif
+			udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
+			if (ret) {
+				printf("Error updating EEPROM at addr 0x%x\n",
+				       CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR);
+				return -1;
+			}
+
+			printf("done (dump via 'i2c md %x 0.1 %x')\n",
+			       CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR,
+			       CONFIG_4xx_CONFIG_BLOCKSIZE);
+			printf("Reset the board for the changes to"
+			       " take effect\n");
+			return 0;
+		}
+	}
+
+	printf("Configuration %s not found!\n", argv[1]);
+	print_configs(cur_config_nr);
+	return -1;
+}
+
+U_BOOT_CMD(
+	chip_config,	2,	0,	do_chip_config,
+	"program the I2C bootstrap EEPROM",
+	"[config-label]"
+);
diff --git a/arch/powerpc/cpu/ppc4xx/commproc.c b/arch/powerpc/cpu/ppc4xx/commproc.c
new file mode 100644
index 0000000..a1696d3
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/commproc.c
@@ -0,0 +1,77 @@
+/*
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Atapted for ppc4XX by Denis Peter
+ */
+
+#include <common.h>
+#include <commproc.h>
+#include <asm/io.h>
+
+#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER)
+
+#if defined(CONFIG_SYS_POST_WORD_ADDR)
+# define _POST_ADDR	((CONFIG_SYS_OCM_DATA_ADDR) + (CONFIG_SYS_POST_WORD_ADDR))
+#elif defined(CONFIG_SYS_POST_ALT_WORD_ADDR)
+# define _POST_ADDR	(CONFIG_SYS_POST_ALT_WORD_ADDR)
+#endif
+
+void post_word_store (ulong a)
+{
+	volatile void *save_addr = (volatile void *)(_POST_ADDR);
+
+	out_be32(save_addr, a);
+}
+
+ulong post_word_load (void)
+{
+	volatile void *save_addr = (volatile void *)(_POST_ADDR);
+
+	return in_be32(save_addr);
+}
+
+#endif	/* CONFIG_POST || CONFIG_LOGBUFFER*/
+
+#ifdef CONFIG_BOOTCOUNT_LIMIT
+
+void bootcount_store (ulong a)
+{
+	volatile ulong *save_addr =
+		(volatile ulong *)(CONFIG_SYS_OCM_DATA_ADDR + CONFIG_SYS_BOOTCOUNT_ADDR);
+
+	save_addr[0] = a;
+	save_addr[1] = BOOTCOUNT_MAGIC;
+}
+
+ulong bootcount_load (void)
+{
+	volatile ulong *save_addr =
+		(volatile ulong *)(CONFIG_SYS_OCM_DATA_ADDR + CONFIG_SYS_BOOTCOUNT_ADDR);
+
+	if (save_addr[1] != BOOTCOUNT_MAGIC)
+		return 0;
+	else
+		return save_addr[0];
+}
+
+#endif /* CONFIG_BOOTCOUNT_LIMIT */
diff --git a/arch/powerpc/cpu/ppc4xx/config.mk b/arch/powerpc/cpu/ppc4xx/config.mk
new file mode 100644
index 0000000..5bda710
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/config.mk
@@ -0,0 +1,37 @@
+#
+# (C) Copyright 2000
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -fPIC -meabi
+PLATFORM_CPPFLAGS += -DCONFIG_4xx -ffixed-r2 -mstring -msoft-float
+
+cfg=$(shell grep configs $(OBJTREE)/include/config.h | sed 's/.*<\(configs.*\)>/\1/')
+is440:=$(shell grep CONFIG_440 $(TOPDIR)/include/$(cfg))
+
+ifneq (,$(findstring CONFIG_440,$(is440)))
+PLATFORM_CPPFLAGS += -Wa,-m440 -mcpu=440
+else
+PLATFORM_CPPFLAGS += -Wa,-m405 -mcpu=405
+endif
+
+# Use default linker script.  Board port can override in board/*/config.mk
+LDSCRIPT := $(SRCTREE)/arch/powerpc/cpu/ppc4xx/u-boot.lds
diff --git a/arch/powerpc/cpu/ppc4xx/cpu.c b/arch/powerpc/cpu/ppc4xx/cpu.c
new file mode 100644
index 0000000..e1a023b
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/cpu.c
@@ -0,0 +1,754 @@
+/*
+ * (C) Copyright 2000-2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * CPU specific code
+ *
+ * written or collected and sometimes rewritten by
+ * Magnus Damm <damm@bitsmart.com>
+ *
+ * minor modifications by
+ * Wolfgang Denk <wd@denx.de>
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/cache.h>
+#include <ppc4xx.h>
+#include <netdev.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void board_reset(void);
+
+/*
+ * To provide an interface to detect CPU number for boards that support
+ * more then one CPU, we implement the "weak" default functions here.
+ *
+ * Returns CPU number
+ */
+int __get_cpu_num(void)
+{
+	return NA_OR_UNKNOWN_CPU;
+}
+int get_cpu_num(void) __attribute__((weak, alias("__get_cpu_num")));
+
+#if defined(CONFIG_PCI)
+#if defined(CONFIG_405GP) || \
+    defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+
+#define PCI_ASYNC
+
+static int pci_async_enabled(void)
+{
+#if defined(CONFIG_405GP)
+	return (mfdcr(CPC0_PSR) & PSR_PCI_ASYNC_EN);
+#endif
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	unsigned long val;
+
+	mfsdr(SDR0_SDSTP1, val);
+	return (val & SDR0_SDSTP1_PAME_MASK);
+#endif
+}
+#endif
+#endif /* CONFIG_PCI */
+
+#if defined(CONFIG_PCI) && !defined(CONFIG_IOP480) && \
+    !defined(CONFIG_405) && !defined(CONFIG_405EX)
+int pci_arbiter_enabled(void)
+{
+#if defined(CONFIG_405GP)
+	return (mfdcr(CPC0_PSR) & PSR_PCI_ARBIT_EN);
+#endif
+
+#if defined(CONFIG_405EP)
+	return (mfdcr(CPC0_PCI) & CPC0_PCI_ARBIT_EN);
+#endif
+
+#if defined(CONFIG_440GP)
+	return (mfdcr(CPC0_STRP1) & CPC0_STRP1_PAE_MASK);
+#endif
+
+#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+	unsigned long val;
+
+	mfsdr(SDR0_XCR, val);
+	return (val & 0x80000000);
+#endif
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	unsigned long val;
+
+	mfsdr(SDR0_PCI0, val);
+	return (val & 0x80000000);
+#endif
+}
+#endif
+
+#if defined(CONFIG_405EP)
+#define I2C_BOOTROM
+
+static int i2c_bootrom_enabled(void)
+{
+#if defined(CONFIG_405EP)
+	return (mfdcr(CPC0_BOOT) & CPC0_BOOT_SEP);
+#else
+	unsigned long val;
+
+	mfsdr(SDR0_SDCS0, val);
+	return (val & SDR0_SDCS_SDD);
+#endif
+}
+#endif
+
+#if defined(CONFIG_440GX)
+#define SDR0_PINSTP_SHIFT	29
+static char *bootstrap_str[] = {
+	"EBC (16 bits)",
+	"EBC (8 bits)",
+	"EBC (32 bits)",
+	"EBC (8 bits)",
+	"PCI",
+	"I2C (Addr 0x54)",
+	"Reserved",
+	"I2C (Addr 0x50)",
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'B', 'D', 'E', 'x', 'F' };
+#endif
+
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+#define SDR0_PINSTP_SHIFT	30
+static char *bootstrap_str[] = {
+	"EBC (8 bits)",
+	"PCI",
+	"I2C (Addr 0x54)",
+	"I2C (Addr 0x50)",
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D'};
+#endif
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+#define SDR0_PINSTP_SHIFT	29
+static char *bootstrap_str[] = {
+	"EBC (8 bits)",
+	"PCI",
+	"NAND (8 bits)",
+	"EBC (16 bits)",
+	"EBC (16 bits)",
+	"I2C (Addr 0x54)",
+	"PCI",
+	"I2C (Addr 0x52)",
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G', 'F', 'H' };
+#endif
+
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#define SDR0_PINSTP_SHIFT	29
+static char *bootstrap_str[] = {
+	"EBC (8 bits)",
+	"EBC (16 bits)",
+	"EBC (16 bits)",
+	"NAND (8 bits)",
+	"PCI",
+	"I2C (Addr 0x54)",
+	"PCI",
+	"I2C (Addr 0x52)",
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G', 'F', 'H' };
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define SDR0_PINSTP_SHIFT	29
+static char *bootstrap_str[] = {
+	"EBC (8 bits)",
+	"EBC (16 bits)",
+	"PCI",
+	"PCI",
+	"EBC (16 bits)",
+	"NAND (8 bits)",
+	"I2C (Addr 0x54)",	/* A8 */
+	"I2C (Addr 0x52)",	/* A4 */
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' };
+#endif
+
+#if defined(CONFIG_460SX)
+#define SDR0_PINSTP_SHIFT	29
+static char *bootstrap_str[] = {
+	"EBC (8 bits)",
+	"EBC (16 bits)",
+	"EBC (32 bits)",
+	"NAND (8 bits)",
+	"I2C (Addr 0x54)",      /* A8 */
+	"I2C (Addr 0x52)",      /* A4 */
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G' };
+#endif
+
+#if defined(CONFIG_405EZ)
+#define SDR0_PINSTP_SHIFT	28
+static char *bootstrap_str[] = {
+	"EBC (8 bits)",
+	"SPI (fast)",
+	"NAND (512 page, 4 addr cycle)",
+	"I2C (Addr 0x50)",
+	"EBC (32 bits)",
+	"I2C (Addr 0x50)",
+	"NAND (2K page, 5 addr cycle)",
+	"I2C (Addr 0x50)",
+	"EBC (16 bits)",
+	"Reserved",
+	"NAND (2K page, 4 addr cycle)",
+	"I2C (Addr 0x50)",
+	"NAND (512 page, 3 addr cycle)",
+	"I2C (Addr 0x50)",
+	"SPI (slow)",
+	"I2C (Addr 0x50)",
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', \
+				 'I', 'x', 'K', 'L', 'M', 'N', 'O', 'P' };
+#endif
+
+#if defined(CONFIG_405EX)
+#define SDR0_PINSTP_SHIFT	29
+static char *bootstrap_str[] = {
+	"EBC (8 bits)",
+	"EBC (16 bits)",
+	"EBC (16 bits)",
+	"NAND (8 bits)",
+	"NAND (8 bits)",
+	"I2C (Addr 0x54)",
+	"EBC (8 bits)",
+	"I2C (Addr 0x52)",
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G', 'F', 'H' };
+#endif
+
+#if defined(SDR0_PINSTP_SHIFT)
+static int bootstrap_option(void)
+{
+	unsigned long val;
+
+	mfsdr(SDR0_PINSTP, val);
+	return ((val & 0xf0000000) >> SDR0_PINSTP_SHIFT);
+}
+#endif /* SDR0_PINSTP_SHIFT */
+
+
+#if defined(CONFIG_440)
+static int do_chip_reset (unsigned long sys0, unsigned long sys1)
+{
+	/* Changes to CPC0_SYS0 and CPC0_SYS1 require chip
+	 * reset.
+	 */
+	mtdcr (CPC0_CR0, mfdcr (CPC0_CR0) | 0x80000000);	/* Set SWE */
+	mtdcr (CPC0_SYS0, sys0);
+	mtdcr (CPC0_SYS1, sys1);
+	mtdcr (CPC0_CR0, mfdcr (CPC0_CR0) & ~0x80000000);	/* Clr SWE */
+	mtspr (SPRN_DBCR0, 0x20000000);	/* Reset the chip */
+
+	return 1;
+}
+#endif
+
+
+int checkcpu (void)
+{
+#if !defined(CONFIG_405)	/* not used on Xilinx 405 FPGA implementations */
+	uint pvr = get_pvr();
+	ulong clock = gd->cpu_clk;
+	char buf[32];
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	u32 reg;
+#endif
+
+#if !defined(CONFIG_IOP480)
+	char addstr[64] = "";
+	sys_info_t sys_info;
+	int cpu_num;
+
+	cpu_num = get_cpu_num();
+	if (cpu_num >= 0)
+		printf("CPU%d:  ", cpu_num);
+	else
+		puts("CPU:   ");
+
+	get_sys_info(&sys_info);
+
+#if defined(CONFIG_XILINX_440)
+	puts("IBM PowerPC 4");
+#else
+	puts("AMCC PowerPC 4");
+#endif
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
+    defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
+    defined(CONFIG_405EX)
+	puts("05");
+#endif
+#if defined(CONFIG_440)
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	puts("60");
+#else
+	puts("40");
+#endif
+#endif
+
+	switch (pvr) {
+	case PVR_405GP_RB:
+		puts("GP Rev. B");
+		break;
+
+	case PVR_405GP_RC:
+		puts("GP Rev. C");
+		break;
+
+	case PVR_405GP_RD:
+		puts("GP Rev. D");
+		break;
+
+#ifdef CONFIG_405GP
+	case PVR_405GP_RE: /* 405GP rev E and 405CR rev C have same PVR */
+		puts("GP Rev. E");
+		break;
+#endif
+
+	case PVR_405CR_RA:
+		puts("CR Rev. A");
+		break;
+
+	case PVR_405CR_RB:
+		puts("CR Rev. B");
+		break;
+
+#ifdef CONFIG_405CR
+	case PVR_405CR_RC: /* 405GP rev E and 405CR rev C have same PVR */
+		puts("CR Rev. C");
+		break;
+#endif
+
+	case PVR_405GPR_RB:
+		puts("GPr Rev. B");
+		break;
+
+	case PVR_405EP_RB:
+		puts("EP Rev. B");
+		break;
+
+	case PVR_405EZ_RA:
+		puts("EZ Rev. A");
+		break;
+
+	case PVR_405EX1_RA:
+		puts("EX Rev. A");
+		strcpy(addstr, "Security support");
+		break;
+
+	case PVR_405EXR2_RA:
+		puts("EXr Rev. A");
+		strcpy(addstr, "No Security support");
+		break;
+
+	case PVR_405EX1_RC:
+		puts("EX Rev. C");
+		strcpy(addstr, "Security support");
+		break;
+
+	case PVR_405EX2_RC:
+		puts("EX Rev. C");
+		strcpy(addstr, "No Security support");
+		break;
+
+	case PVR_405EXR1_RC:
+		puts("EXr Rev. C");
+		strcpy(addstr, "Security support");
+		break;
+
+	case PVR_405EXR2_RC:
+		puts("EXr Rev. C");
+		strcpy(addstr, "No Security support");
+		break;
+
+	case PVR_405EX1_RD:
+		puts("EX Rev. D");
+		strcpy(addstr, "Security support");
+		break;
+
+	case PVR_405EX2_RD:
+		puts("EX Rev. D");
+		strcpy(addstr, "No Security support");
+		break;
+
+	case PVR_405EXR1_RD:
+		puts("EXr Rev. D");
+		strcpy(addstr, "Security support");
+		break;
+
+	case PVR_405EXR2_RD:
+		puts("EXr Rev. D");
+		strcpy(addstr, "No Security support");
+		break;
+
+#if defined(CONFIG_440)
+	case PVR_440GP_RB:
+		puts("GP Rev. B");
+		/* See errata 1.12: CHIP_4 */
+		if ((mfdcr(CPC0_SYS0) != mfdcr(CPC0_STRP0)) ||
+		    (mfdcr(CPC0_SYS1) != mfdcr(CPC0_STRP1)) ){
+			puts (  "\n\t CPC0_SYSx DCRs corrupted. "
+				"Resetting chip ...\n");
+			udelay( 1000 * 1000 ); /* Give time for serial buf to clear */
+			do_chip_reset ( mfdcr(CPC0_STRP0),
+					mfdcr(CPC0_STRP1) );
+		}
+		break;
+
+	case PVR_440GP_RC:
+		puts("GP Rev. C");
+		break;
+
+	case PVR_440GX_RA:
+		puts("GX Rev. A");
+		break;
+
+	case PVR_440GX_RB:
+		puts("GX Rev. B");
+		break;
+
+	case PVR_440GX_RC:
+		puts("GX Rev. C");
+		break;
+
+	case PVR_440GX_RF:
+		puts("GX Rev. F");
+		break;
+
+	case PVR_440EP_RA:
+		puts("EP Rev. A");
+		break;
+
+#ifdef CONFIG_440EP
+	case PVR_440EP_RB: /* 440EP rev B and 440GR rev A have same PVR */
+		puts("EP Rev. B");
+		break;
+
+	case PVR_440EP_RC: /* 440EP rev C and 440GR rev B have same PVR */
+		puts("EP Rev. C");
+		break;
+#endif /*  CONFIG_440EP */
+
+#ifdef CONFIG_440GR
+	case PVR_440GR_RA: /* 440EP rev B and 440GR rev A have same PVR */
+		puts("GR Rev. A");
+		break;
+
+	case PVR_440GR_RB: /* 440EP rev C and 440GR rev B have same PVR */
+		puts("GR Rev. B");
+		break;
+#endif /* CONFIG_440GR */
+#endif /* CONFIG_440 */
+
+#ifdef CONFIG_440EPX
+	case PVR_440EPX1_RA: /* 440EPx rev A and 440GRx rev A have same PVR */
+		puts("EPx Rev. A");
+		strcpy(addstr, "Security/Kasumi support");
+		break;
+
+	case PVR_440EPX2_RA: /* 440EPx rev A and 440GRx rev A have same PVR */
+		puts("EPx Rev. A");
+		strcpy(addstr, "No Security/Kasumi support");
+		break;
+#endif /* CONFIG_440EPX */
+
+#ifdef CONFIG_440GRX
+	case PVR_440GRX1_RA: /* 440EPx rev A and 440GRx rev A have same PVR */
+		puts("GRx Rev. A");
+		strcpy(addstr, "Security/Kasumi support");
+		break;
+
+	case PVR_440GRX2_RA: /* 440EPx rev A and 440GRx rev A have same PVR */
+		puts("GRx Rev. A");
+		strcpy(addstr, "No Security/Kasumi support");
+		break;
+#endif /* CONFIG_440GRX */
+
+	case PVR_440SP_6_RAB:
+		puts("SP Rev. A/B");
+		strcpy(addstr, "RAID 6 support");
+		break;
+
+	case PVR_440SP_RAB:
+		puts("SP Rev. A/B");
+		strcpy(addstr, "No RAID 6 support");
+		break;
+
+	case PVR_440SP_6_RC:
+		puts("SP Rev. C");
+		strcpy(addstr, "RAID 6 support");
+		break;
+
+	case PVR_440SP_RC:
+		puts("SP Rev. C");
+		strcpy(addstr, "No RAID 6 support");
+		break;
+
+	case PVR_440SPe_6_RA:
+		puts("SPe Rev. A");
+		strcpy(addstr, "RAID 6 support");
+		break;
+
+	case PVR_440SPe_RA:
+		puts("SPe Rev. A");
+		strcpy(addstr, "No RAID 6 support");
+		break;
+
+	case PVR_440SPe_6_RB:
+		puts("SPe Rev. B");
+		strcpy(addstr, "RAID 6 support");
+		break;
+
+	case PVR_440SPe_RB:
+		puts("SPe Rev. B");
+		strcpy(addstr, "No RAID 6 support");
+		break;
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	case PVR_460EX_RA:
+		puts("EX Rev. A");
+		strcpy(addstr, "No Security/Kasumi support");
+		break;
+
+	case PVR_460EX_SE_RA:
+		puts("EX Rev. A");
+		strcpy(addstr, "Security/Kasumi support");
+		break;
+
+	case PVR_460EX_RB:
+		puts("EX Rev. B");
+		mfsdr(SDR0_ECID3, reg);
+		if (reg & 0x00100000)
+			strcpy(addstr, "No Security/Kasumi support");
+		else
+			strcpy(addstr, "Security/Kasumi support");
+		break;
+
+	case PVR_460GT_RA:
+		puts("GT Rev. A");
+		strcpy(addstr, "No Security/Kasumi support");
+		break;
+
+	case PVR_460GT_SE_RA:
+		puts("GT Rev. A");
+		strcpy(addstr, "Security/Kasumi support");
+		break;
+
+	case PVR_460GT_RB:
+		puts("GT Rev. B");
+		mfsdr(SDR0_ECID3, reg);
+		if (reg & 0x00100000)
+			strcpy(addstr, "No Security/Kasumi support");
+		else
+			strcpy(addstr, "Security/Kasumi support");
+		break;
+#endif
+
+	case PVR_460SX_RA:
+		puts("SX Rev. A");
+		strcpy(addstr, "Security support");
+		break;
+
+	case PVR_460SX_RA_V1:
+		puts("SX Rev. A");
+		strcpy(addstr, "No Security support");
+		break;
+
+	case PVR_460GX_RA:
+		puts("GX Rev. A");
+		strcpy(addstr, "Security support");
+		break;
+
+	case PVR_460GX_RA_V1:
+		puts("GX Rev. A");
+		strcpy(addstr, "No Security support");
+		break;
+
+	case PVR_VIRTEX5:
+		puts("x5 VIRTEX5");
+		break;
+
+	default:
+		printf (" UNKNOWN (PVR=%08x)", pvr);
+		break;
+	}
+
+	printf (" at %s MHz (PLB=%lu OPB=%lu EBC=%lu",
+		strmhz(buf, clock),
+		sys_info.freqPLB / 1000000,
+		get_OPB_freq() / 1000000,
+		sys_info.freqEBC / 1000000);
+#if defined(CONFIG_PCI) && \
+	(defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \
+	 defined(CONFIG_440GR) || defined(CONFIG_440GRX))
+	printf(" PCI=%lu MHz", sys_info.freqPCI / 1000000);
+#endif
+	printf(")\n");
+
+	if (addstr[0] != 0)
+		printf("       %s\n", addstr);
+
+#if defined(I2C_BOOTROM)
+	printf ("       I2C boot EEPROM %sabled\n", i2c_bootrom_enabled() ? "en" : "dis");
+#endif	/* I2C_BOOTROM */
+#if defined(SDR0_PINSTP_SHIFT)
+	printf ("       Bootstrap Option %c - ", bootstrap_char[bootstrap_option()]);
+	printf ("Boot ROM Location %s", bootstrap_str[bootstrap_option()]);
+#ifdef CONFIG_NAND_U_BOOT
+	puts(", booting from NAND");
+#endif /* CONFIG_NAND_U_BOOT */
+	putc('\n');
+#endif	/* SDR0_PINSTP_SHIFT */
+
+#if defined(CONFIG_PCI) && !defined(CONFIG_405EX)
+	printf ("       Internal PCI arbiter %sabled", pci_arbiter_enabled() ? "en" : "dis");
+#endif
+
+#if defined(CONFIG_PCI) && defined(PCI_ASYNC)
+	if (pci_async_enabled()) {
+		printf (", PCI async ext clock used");
+	} else {
+		printf (", PCI sync clock at %lu MHz",
+		       sys_info.freqPLB / sys_info.pllPciDiv / 1000000);
+	}
+#endif
+
+#if defined(CONFIG_PCI) && !defined(CONFIG_405EX)
+	putc('\n');
+#endif
+
+#if defined(CONFIG_405EP) || defined(CONFIG_405EZ) || defined(CONFIG_405EX)
+	printf ("       16 kB I-Cache 16 kB D-Cache");
+#elif defined(CONFIG_440)
+	printf ("       32 kB I-Cache 32 kB D-Cache");
+#else
+	printf ("       16 kB I-Cache %d kB D-Cache",
+		((pvr | 0x00000001) == PVR_405GPR_RB) ? 16 : 8);
+#endif
+#endif /* !defined(CONFIG_IOP480) */
+
+#if defined(CONFIG_IOP480)
+	printf ("PLX IOP480 (PVR=%08x)", pvr);
+	printf (" at %s MHz:", strmhz(buf, clock));
+	printf (" %u kB I-Cache", 4);
+	printf (" %u kB D-Cache", 2);
+#endif
+
+#endif /* !defined(CONFIG_405) */
+
+	putc ('\n');
+
+	return 0;
+}
+
+int ppc440spe_revB() {
+	unsigned int pvr;
+
+	pvr = get_pvr();
+	if ((pvr == PVR_440SPe_6_RB) || (pvr == PVR_440SPe_RB))
+		return 1;
+	else
+		return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+#if defined(CONFIG_BOARD_RESET)
+	board_reset();
+#else
+#if defined(CONFIG_SYS_4xx_RESET_TYPE)
+	mtspr(SPRN_DBCR0, CONFIG_SYS_4xx_RESET_TYPE << 28);
+#else
+	/*
+	 * Initiate system reset in debug control register DBCR
+	 */
+	mtspr(SPRN_DBCR0, 0x30000000);
+#endif /* defined(CONFIG_SYS_4xx_RESET_TYPE) */
+#endif /* defined(CONFIG_BOARD_RESET) */
+
+	return 1;
+}
+
+
+/*
+ * Get timebase clock frequency
+ */
+unsigned long get_tbclk (void)
+{
+#if !defined(CONFIG_IOP480)
+	sys_info_t  sys_info;
+
+	get_sys_info(&sys_info);
+	return (sys_info.freqProcessor);
+#else
+	return (66000000);
+#endif
+
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset(void)
+{
+	int re_enable = disable_interrupts();
+	reset_4xx_watchdog();
+	if (re_enable) enable_interrupts();
+}
+
+void reset_4xx_watchdog(void)
+{
+	/*
+	 * Clear TSR(WIS) bit
+	 */
+	mtspr(SPRN_TSR, 0x40000000);
+}
+#endif	/* CONFIG_WATCHDOG */
+
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_PPC4xx_EMAC)
+	ppc_4xx_eth_initialize(bis);
+#endif
+	return 0;
+}
diff --git a/arch/powerpc/cpu/ppc4xx/cpu_init.c b/arch/powerpc/cpu/ppc4xx/cpu_init.c
new file mode 100644
index 0000000..8a6e545
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/cpu_init.c
@@ -0,0 +1,456 @@
+/*
+ * (C) Copyright 2000-2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <ppc4xx_enet.h>
+#include <asm/processor.h>
+#include <asm/gpio.h>
+#include <ppc4xx.h>
+
+#if defined(CONFIG_405GP)  || defined(CONFIG_405EP)
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+#ifndef CONFIG_SYS_PLL_RECONFIG
+#define CONFIG_SYS_PLL_RECONFIG	0
+#endif
+
+void reconfigure_pll(u32 new_cpu_freq)
+{
+#if defined(CONFIG_440EPX)
+	int	reset_needed = 0;
+	u32	reg, temp;
+	u32	prbdv0, target_prbdv0,				/* CLK_PRIMBD */
+		fwdva, target_fwdva, fwdvb, target_fwdvb,	/* CLK_PLLD */
+		fbdv, target_fbdv, lfbdv, target_lfbdv,
+		perdv0,	target_perdv0,				/* CLK_PERD */
+		spcid0,	target_spcid0;				/* CLK_SPCID */
+
+	/* Reconfigure clocks if necessary.
+	 * See PPC440EPx User's Manual, sections 8.2 and 14 */
+	if (new_cpu_freq == 667) {
+		target_prbdv0 = 2;
+		target_fwdva = 2;
+		target_fwdvb = 4;
+		target_fbdv = 20;
+		target_lfbdv = 1;
+		target_perdv0 = 4;
+		target_spcid0 = 4;
+
+		mfcpr(CPR0_PRIMBD0, reg);
+		temp = (reg & PRBDV_MASK) >> 24;
+		prbdv0 = temp ? temp : 8;
+		if (prbdv0 != target_prbdv0) {
+			reg &= ~PRBDV_MASK;
+			reg |= ((target_prbdv0 == 8 ? 0 : target_prbdv0) << 24);
+			mtcpr(CPR0_PRIMBD0, reg);
+			reset_needed = 1;
+		}
+
+		mfcpr(CPR0_PLLD, reg);
+
+		temp = (reg & PLLD_FWDVA_MASK) >> 16;
+		fwdva = temp ? temp : 16;
+
+		temp = (reg & PLLD_FWDVB_MASK) >> 8;
+		fwdvb = temp ? temp : 8;
+
+		temp = (reg & PLLD_FBDV_MASK) >> 24;
+		fbdv = temp ? temp : 32;
+
+		temp = (reg & PLLD_LFBDV_MASK);
+		lfbdv = temp ? temp : 64;
+
+		if (fwdva != target_fwdva || fbdv != target_fbdv || lfbdv != target_lfbdv) {
+			reg &= ~(PLLD_FWDVA_MASK | PLLD_FWDVB_MASK |
+				 PLLD_FBDV_MASK | PLLD_LFBDV_MASK);
+			reg |= ((target_fwdva == 16 ? 0 : target_fwdva) << 16) |
+				((target_fwdvb == 8 ? 0 : target_fwdvb) << 8) |
+				((target_fbdv == 32 ? 0 : target_fbdv) << 24) |
+				(target_lfbdv == 64 ? 0 : target_lfbdv);
+			mtcpr(CPR0_PLLD, reg);
+			reset_needed = 1;
+		}
+
+		mfcpr(CPR0_PERD, reg);
+		perdv0 = (reg & CPR0_PERD_PERDV0_MASK) >> 24;
+		if (perdv0 != target_perdv0) {
+			reg &= ~CPR0_PERD_PERDV0_MASK;
+			reg |= (target_perdv0 << 24);
+			mtcpr(CPR0_PERD, reg);
+			reset_needed = 1;
+		}
+
+		mfcpr(CPR0_SPCID, reg);
+		temp = (reg & CPR0_SPCID_SPCIDV0_MASK) >> 24;
+		spcid0 = temp ? temp : 4;
+		if (spcid0 != target_spcid0) {
+			reg &= ~CPR0_SPCID_SPCIDV0_MASK;
+			reg |= ((target_spcid0 == 4 ? 0 : target_spcid0) << 24);
+			mtcpr(CPR0_SPCID, reg);
+			reset_needed = 1;
+		}
+	}
+
+	/* Get current value of FWDVA.*/
+	mfcpr(CPR0_PLLD, reg);
+	temp = (reg & PLLD_FWDVA_MASK) >> 16;
+
+	/*
+	 * Check to see if FWDVA has been set to value of 1. if it has we must
+	 * modify it.
+	 */
+	if (temp == 1) {
+		mfcpr(CPR0_PLLD, reg);
+		/* Get current value of fbdv.  */
+		temp = (reg & PLLD_FBDV_MASK) >> 24;
+		fbdv = temp ? temp : 32;
+		/* Get current value of lfbdv. */
+		temp = (reg & PLLD_LFBDV_MASK);
+		lfbdv = temp ? temp : 64;
+		/*
+		 * Load register that contains current boot strapping option.
+		 */
+		mfcpr(CPR0_ICFG, reg);
+		/* Shift strapping option into low 3 bits.*/
+		reg = (reg >> 28);
+
+		if ((reg == BOOT_STRAP_OPTION_A) || (reg == BOOT_STRAP_OPTION_B) ||
+		    (reg == BOOT_STRAP_OPTION_D) || (reg == BOOT_STRAP_OPTION_E)) {
+			/*
+			 * Get current value of FWDVA. Assign current FWDVA to
+			 * new FWDVB.
+			 */
+			mfcpr(CPR0_PLLD, reg);
+			target_fwdvb = (reg & PLLD_FWDVA_MASK) >> 16;
+			fwdvb = target_fwdvb ? target_fwdvb : 8;
+			/*
+			 * Get current value of FWDVB. Assign current FWDVB to
+			 * new FWDVA.
+			 */
+			target_fwdva = (reg & PLLD_FWDVB_MASK) >> 8;
+			fwdva = target_fwdva ? target_fwdva : 16;
+			/*
+			 * Update CPR0_PLLD with switched FWDVA and FWDVB.
+			 */
+			reg &= ~(PLLD_FWDVA_MASK | PLLD_FWDVB_MASK |
+				PLLD_FBDV_MASK | PLLD_LFBDV_MASK);
+			reg |= ((fwdva == 16 ? 0 : fwdva) << 16) |
+				((fwdvb == 8 ? 0 : fwdvb) << 8) |
+				((fbdv == 32 ? 0 : fbdv) << 24) |
+				(lfbdv == 64 ? 0 : lfbdv);
+			mtcpr(CPR0_PLLD, reg);
+			/* Acknowledge that a reset is required. */
+			reset_needed = 1;
+		}
+	}
+
+	if (reset_needed) {
+		/*
+		 * Set reload inhibit so configuration will persist across
+		 * processor resets
+		 */
+		mfcpr(CPR0_ICFG, reg);
+		reg &= ~CPR0_ICFG_RLI_MASK;
+		reg |= 1 << 31;
+		mtcpr(CPR0_ICFG, reg);
+
+		/* Reset processor if configuration changed */
+		__asm__ __volatile__ ("sync; isync");
+		mtspr(SPRN_DBCR0, 0x20000000);
+	}
+#endif
+}
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Reconfigure PLL if necessary,
+ * set up the memory map,
+ * initialize a bunch of registers
+ */
+void
+cpu_init_f (void)
+{
+#if defined(CONFIG_WATCHDOG) || defined(CONFIG_440GX) || defined(CONFIG_460EX)
+	u32 val;
+#endif
+
+	reconfigure_pll(CONFIG_SYS_PLL_RECONFIG);
+
+#if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && !defined(CONFIG_SYS_4xx_GPIO_TABLE)
+	/*
+	 * GPIO0 setup (select GPIO or alternate function)
+	 */
+#if defined(CONFIG_SYS_GPIO0_OR)
+	out32(GPIO0_OR, CONFIG_SYS_GPIO0_OR);		/* set initial state of output pins	*/
+#endif
+#if defined(CONFIG_SYS_GPIO0_ODR)
+	out32(GPIO0_ODR, CONFIG_SYS_GPIO0_ODR);	/* open-drain select			*/
+#endif
+	out32(GPIO0_OSRH, CONFIG_SYS_GPIO0_OSRH);	/* output select			*/
+	out32(GPIO0_OSRL, CONFIG_SYS_GPIO0_OSRL);
+	out32(GPIO0_ISR1H, CONFIG_SYS_GPIO0_ISR1H);	/* input select				*/
+	out32(GPIO0_ISR1L, CONFIG_SYS_GPIO0_ISR1L);
+	out32(GPIO0_TSRH, CONFIG_SYS_GPIO0_TSRH);	/* three-state select			*/
+	out32(GPIO0_TSRL, CONFIG_SYS_GPIO0_TSRL);
+#if defined(CONFIG_SYS_GPIO0_ISR2H)
+	out32(GPIO0_ISR2H, CONFIG_SYS_GPIO0_ISR2H);
+	out32(GPIO0_ISR2L, CONFIG_SYS_GPIO0_ISR2L);
+#endif
+#if defined (CONFIG_SYS_GPIO0_TCR)
+	out32(GPIO0_TCR, CONFIG_SYS_GPIO0_TCR);	/* enable output driver for outputs	*/
+#endif
+#endif /* CONFIG_405EP ... && !CONFIG_SYS_4xx_GPIO_TABLE */
+
+#if defined (CONFIG_405EP)
+	/*
+	 * Set EMAC noise filter bits
+	 */
+	mtdcr(CPC0_EPCTL, CPC0_EPRCSR_E0NFE | CPC0_EPRCSR_E1NFE);
+#endif /* CONFIG_405EP */
+
+#if defined(CONFIG_SYS_4xx_GPIO_TABLE)
+	gpio_set_chip_configuration();
+#endif /* CONFIG_SYS_4xx_GPIO_TABLE */
+
+	/*
+	 * External Bus Controller (EBC) Setup
+	 */
+#if (defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR))
+#if (defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
+     defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
+     defined(CONFIG_405EX) || defined(CONFIG_405))
+	/*
+	 * Move the next instructions into icache, since these modify the flash
+	 * we are running from!
+	 */
+	asm volatile("	bl	0f"		::: "lr");
+	asm volatile("0:	mflr	3"		::: "r3");
+	asm volatile("	addi	4, 0, 14"	::: "r4");
+	asm volatile("	mtctr	4"		::: "ctr");
+	asm volatile("1:	icbt	0, 3");
+	asm volatile("	addi	3, 3, 32"	::: "r3");
+	asm volatile("	bdnz	1b"		::: "ctr", "cr0");
+	asm volatile("	addis	3, 0, 0x0"	::: "r3");
+	asm volatile("	ori	3, 3, 0xA000"	::: "r3");
+	asm volatile("	mtctr	3"		::: "ctr");
+	asm volatile("2:	bdnz	2b"		::: "ctr", "cr0");
+#endif
+
+	mtebc(PB0AP, CONFIG_SYS_EBC_PB0AP);
+	mtebc(PB0CR, CONFIG_SYS_EBC_PB0CR);
+#endif
+
+#if (defined(CONFIG_SYS_EBC_PB1AP) && defined(CONFIG_SYS_EBC_PB1CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 1))
+	mtebc(PB1AP, CONFIG_SYS_EBC_PB1AP);
+	mtebc(PB1CR, CONFIG_SYS_EBC_PB1CR);
+#endif
+
+#if (defined(CONFIG_SYS_EBC_PB2AP) && defined(CONFIG_SYS_EBC_PB2CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 2))
+	mtebc(PB2AP, CONFIG_SYS_EBC_PB2AP);
+	mtebc(PB2CR, CONFIG_SYS_EBC_PB2CR);
+#endif
+
+#if (defined(CONFIG_SYS_EBC_PB3AP) && defined(CONFIG_SYS_EBC_PB3CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 3))
+	mtebc(PB3AP, CONFIG_SYS_EBC_PB3AP);
+	mtebc(PB3CR, CONFIG_SYS_EBC_PB3CR);
+#endif
+
+#if (defined(CONFIG_SYS_EBC_PB4AP) && defined(CONFIG_SYS_EBC_PB4CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 4))
+	mtebc(PB4AP, CONFIG_SYS_EBC_PB4AP);
+	mtebc(PB4CR, CONFIG_SYS_EBC_PB4CR);
+#endif
+
+#if (defined(CONFIG_SYS_EBC_PB5AP) && defined(CONFIG_SYS_EBC_PB5CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 5))
+	mtebc(PB5AP, CONFIG_SYS_EBC_PB5AP);
+	mtebc(PB5CR, CONFIG_SYS_EBC_PB5CR);
+#endif
+
+#if (defined(CONFIG_SYS_EBC_PB6AP) && defined(CONFIG_SYS_EBC_PB6CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 6))
+	mtebc(PB6AP, CONFIG_SYS_EBC_PB6AP);
+	mtebc(PB6CR, CONFIG_SYS_EBC_PB6CR);
+#endif
+
+#if (defined(CONFIG_SYS_EBC_PB7AP) && defined(CONFIG_SYS_EBC_PB7CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 7))
+	mtebc(PB7AP, CONFIG_SYS_EBC_PB7AP);
+	mtebc(PB7CR, CONFIG_SYS_EBC_PB7CR);
+#endif
+
+#if defined (CONFIG_SYS_EBC_CFG)
+	mtebc(EBC0_CFG, CONFIG_SYS_EBC_CFG);
+#endif
+
+#if defined(CONFIG_WATCHDOG)
+	val = mfspr(tcr);
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+	val |= 0xb8000000;      /* generate system reset after 1.34 seconds */
+#elif defined(CONFIG_440EPX)
+	val |= 0xb0000000;      /* generate system reset after 1.34 seconds */
+#else
+	val |= 0xf0000000;      /* generate system reset after 2.684 seconds */
+#endif
+#if defined(CONFIG_SYS_4xx_RESET_TYPE)
+	val &= ~0x30000000;			/* clear WRC bits */
+	val |= CONFIG_SYS_4xx_RESET_TYPE << 28;	/* set board specific WRC type */
+#endif
+	mtspr(tcr, val);
+
+	val = mfspr(tsr);
+	val |= 0x80000000;      /* enable watchdog timer */
+	mtspr(tsr, val);
+
+	reset_4xx_watchdog();
+#endif /* CONFIG_WATCHDOG */
+
+#if defined(CONFIG_440GX)
+	/* Take the GX out of compatibility mode
+	 * Travis Sawyer, 9 Mar 2004
+	 * NOTE: 440gx user manual inconsistency here
+	 *       Compatibility mode and Ethernet Clock select are not
+	 *       correct in the manual
+	 */
+	mfsdr(SDR0_MFR, val);
+	val &= ~0x10000000;
+	mtsdr(SDR0_MFR,val);
+#endif /* CONFIG_440GX */
+
+#if defined(CONFIG_460EX)
+	/*
+	 * Set SDR0_AHB_CFG[A2P_INCR4] (bit 24) and
+	 * clear SDR0_AHB_CFG[A2P_PROT2] (bit 25) for a new 460EX errata
+	 * regarding concurrent use of AHB USB OTG, USB 2.0 host and SATA
+	 */
+	mfsdr(SDR0_AHB_CFG, val);
+	val |= 0x80;
+	val &= ~0x40;
+	mtsdr(SDR0_AHB_CFG, val);
+	mfsdr(SDR0_USB2HOST_CFG, val);
+	val &= ~0xf00;
+	val |= 0x400;
+	mtsdr(SDR0_USB2HOST_CFG, val);
+#endif /* CONFIG_460EX */
+
+#if defined(CONFIG_405EX) || \
+    defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)  || \
+    defined(CONFIG_460SX)
+	/*
+	 * Set PLB4 arbiter (Segment 0 and 1) to 4 deep pipeline read
+	 */
+	mtdcr(PLB0_ACR, (mfdcr(PLB0_ACR) & ~PLB0_ACR_RDP_MASK) |
+	      PLB0_ACR_RDP_4DEEP);
+	mtdcr(PLB1_ACR, (mfdcr(PLB1_ACR) & ~PLB1_ACR_RDP_MASK) |
+	      PLB1_ACR_RDP_4DEEP);
+#endif /* CONFIG_440SP/SPE || CONFIG_460EX/GT || CONFIG_405EX */
+}
+
+/*
+ * initialize higher level parts of CPU like time base and timers
+ */
+int cpu_init_r (void)
+{
+#if defined(CONFIG_405GP)
+	uint pvr = get_pvr();
+
+	/*
+	 * Set edge conditioning circuitry on PPC405GPr
+	 * for compatibility to existing PPC405GP designs.
+	 */
+	if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) {
+		mtdcr(CPC0_ECR, 0x60606000);
+	}
+#endif  /* defined(CONFIG_405GP) */
+
+	return 0;
+}
+
+#if defined(CONFIG_PCI) && \
+	(defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \
+	 defined(CONFIG_440GR) || defined(CONFIG_440GRX))
+/*
+ * 440EP(x)/GR(x) PCI async/sync clocking restriction:
+ *
+ * In asynchronous PCI mode, the synchronous PCI clock must meet
+ * certain requirements. The following equation describes the
+ * relationship that must be maintained between the asynchronous PCI
+ * clock and synchronous PCI clock. Select an appropriate PCI:PLB
+ * ratio to maintain the relationship:
+ *
+ * AsyncPCIClk - 1MHz <= SyncPCIclock <= (2 * AsyncPCIClk) - 1MHz
+ */
+static int ppc4xx_pci_sync_clock_ok(u32 sync, u32 async)
+{
+	if (((async - 1000000) > sync) || (sync > ((2 * async) - 1000000)))
+		return 0;
+	else
+		return 1;
+}
+
+int ppc4xx_pci_sync_clock_config(u32 async)
+{
+	sys_info_t sys_info;
+	u32 sync;
+	int div;
+	u32 reg;
+	u32 spcid_val[] = {
+		CPR0_SPCID_SPCIDV0_DIV1, CPR0_SPCID_SPCIDV0_DIV2,
+		CPR0_SPCID_SPCIDV0_DIV3, CPR0_SPCID_SPCIDV0_DIV4 };
+
+	get_sys_info(&sys_info);
+	sync = sys_info.freqPCI;
+
+	/*
+	 * First check if the equation above is met
+	 */
+	if (!ppc4xx_pci_sync_clock_ok(sync, async)) {
+		/*
+		 * Reconfigure PCI sync clock to meet the equation.
+		 * Start with highest possible PCI sync frequency
+		 * (divider 1).
+		 */
+		for (div = 1; div <= 4; div++) {
+			sync = sys_info.freqPLB / div;
+			if (ppc4xx_pci_sync_clock_ok(sync, async))
+			    break;
+		}
+
+		if (div <= 4) {
+			mtcpr(CPR0_SPCID, spcid_val[div]);
+
+			mfcpr(CPR0_ICFG, reg);
+			reg |= CPR0_ICFG_RLI_MASK;
+			mtcpr(CPR0_ICFG, reg);
+
+			/* do chip reset */
+			mtspr(SPRN_DBCR0, 0x20000000);
+		} else {
+			/* Impossible to configure the PCI sync clock */
+			return -1;
+		}
+	}
+
+	return 0;
+}
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/dcr.S b/arch/powerpc/cpu/ppc4xx/dcr.S
new file mode 100644
index 0000000..93465a3
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/dcr.S
@@ -0,0 +1,198 @@
+/*
+ * (C) Copyright 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <config.h>
+
+#if defined(CONFIG_4xx) && defined(CONFIG_CMD_SETGETDCR)
+
+#include <ppc4xx.h>
+
+#define _LINUX_CONFIG_H 1       /* avoid reading Linux autoconf.h file  */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#define _ASMLANGUAGE
+
+/*****************************************************************************
+ *
+ *  XXX - DANGER
+ *        These routines make use of self modifying code.  DO NOT CALL THEM
+ *	  UNTIL THEY ARE RELOCATED TO RAM.  Additionally, I do not
+ *	  recommend them for use in anything other than an interactive
+ *        debugging environment.  This is mainly due to performance reasons.
+ *
+ ****************************************************************************/
+
+/*
+ * static void _create_MFDCR(unsigned short dcrn)
+ *
+ * Builds a 'mfdcr' instruction for get_dcr
+ * function.
+ */
+		.section ".text"
+		.align 2
+		.type	 _create_MFDCR,@function
+_create_MFDCR:
+		/*
+		 * Build up a 'mfdcr' instruction formatted as follows:
+		 *
+		 *  OPCD |   RT   |    DCRF      |     XO       | CR |
+		 * ---------------|--------------|--------------|----|
+		 * 0   5 | 6   10 | 11        20 | 21        30 | 31 |
+		 *       |        |    DCRN      |              |    |
+		 *   31  |  %r3   | (5..9|0..4)  |      323     |  0 |
+		 *
+		 * Where:
+		 *	OPCD = opcode - 31
+		 *	RT   = destination register - %r3 return register
+		 *	DCRF = DCRN # with upper and lower halves swapped
+		 *	XO   = extended opcode - 323
+		 *	CR   = CR[CR0] NOT undefined - 0
+		 */
+		rlwinm	r0, r3, 27, 27, 31	/* OPCD = 31 */
+		rlwinm	r3, r3, 5, 22, 26
+		or	r3, r3, r0
+		slwi	r3, r3, 10
+		oris	r3, r3, 0x3e30		/* RT = %r3 */
+		ori	r3, r3, 323		/* XO = 323 */
+		slwi	r3, r3, 1		/* CR = 0 */
+
+		mflr	r4
+		stw	r3, 0(r4)		/* Store instr in get_dcr() */
+		dcbst	r0, r4			/* Make sure val is written out */
+		sync				/* Wait for write to complete */
+		icbi	r0, r4			/* Make sure old instr is dumped */
+		isync				/* Wait for icbi to complete */
+
+		blr
+.Lfe1:		.size	 _create_MFDCR,.Lfe1-_create_MFDCR
+/* end _create_MFDCR() */
+
+/*
+ * static void _create_MTDCR(unsigned short dcrn, unsigned long value)
+ *
+ * Builds a 'mtdcr' instruction for set_dcr
+ * function.
+ */
+		.section ".text"
+		.align 2
+		.type	 _create_MTDCR,@function
+_create_MTDCR:
+		/*
+		 * Build up a 'mtdcr' instruction formatted as follows:
+		 *
+		 *  OPCD |   RS   |    DCRF      |     XO       | CR |
+		 * ---------------|--------------|--------------|----|
+		 * 0   5 | 6   10 | 11        20 | 21        30 | 31 |
+		 *       |        |    DCRN      |              |    |
+		 *   31  |  %r3   | (5..9|0..4)  |      451     |  0 |
+		 *
+		 * Where:
+		 *	OPCD = opcode - 31
+		 *	RS   = source register - %r4
+		 *	DCRF = dest. DCRN # with upper and lower halves swapped
+		 *	XO   = extended opcode - 451
+		 *	CR   = CR[CR0] NOT undefined - 0
+		 */
+		rlwinm	r0, r3, 27, 27, 31	/* OPCD = 31 */
+		rlwinm	r3, r3, 5, 22, 26
+		or	r3, r3, r0
+		slwi	r3, r3, 10
+		oris	r3, r3, 0x3e40		/* RS = %r4 */
+		ori	r3, r3, 451		/* XO = 451 */
+		slwi	r3, r3, 1		/* CR = 0 */
+
+		mflr	r5
+		stw	r3, 0(r5)		/* Store instr in set_dcr() */
+		dcbst	r0, r5			/* Make sure val is written out */
+		sync				/* Wait for write to complete */
+		icbi	r0, r5			/* Make sure old instr is dumped */
+		isync				/* Wait for icbi to complete */
+
+		blr
+.Lfe2:		.size	 _create_MTDCR,.Lfe2-_create_MTDCR
+/* end _create_MTDCR() */
+
+
+/*
+ * unsigned long get_dcr(unsigned short dcrn)
+ *
+ * Return a given DCR's value.
+ */
+		/* */
+		/* XXX - This is self modifying code, hence */
+		/* it is in the data section. */
+		/* */
+		.section ".data"
+		.align	2
+		.globl	get_dcr
+		.type	get_dcr,@function
+get_dcr:
+		mflr	r0			/* Get link register */
+		stwu	r1, -32(r1)		/* Save back chain and move SP */
+		stw	r0, +36(r1)		/* Save link register */
+
+		bl	_create_MFDCR		/* Build following instruction */
+		/* XXX - we build this instuction up on the fly. */
+		.long	0			/* Get DCR's value */
+
+		lwz	r0, +36(r1)		/* Get saved link register */
+		mtlr	r0			/* Restore link register */
+		addi	r1, r1, +32		/* Remove frame from stack */
+		blr				/* Return to calling function */
+.Lfe3:		.size	get_dcr,.Lfe3-get_dcr
+/* end get_dcr() */
+
+
+/*
+ * unsigned void set_dcr(unsigned short dcrn, unsigned long value)
+ *
+ * Return a given DCR's value.
+ */
+		/*
+		 * XXX - This is self modifying code, hence
+		 * it is in the data section.
+		 */
+		.section ".data"
+		.align	2
+		.globl	set_dcr
+		.type	set_dcr,@function
+set_dcr:
+		mflr	r0			/* Get link register */
+		stwu	r1, -32(r1)		/* Save back chain and move SP */
+		stw	r0, +36(r1)		/* Save link register */
+
+		bl	_create_MTDCR		/* Build following instruction */
+		/* XXX - we build this instuction up on the fly. */
+		.long	0			/* Set DCR's value */
+
+		lwz	r0, +36(r1)		/* Get saved link register */
+		mtlr	r0			/* Restore link register */
+		addi	r1, r1, +32		/* Remove frame from stack */
+		blr				/* Return to calling function */
+.Lfe4:		.size	set_dcr,.Lfe4-set_dcr
+/* end set_dcr() */
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/denali_data_eye.c b/arch/powerpc/cpu/ppc4xx/denali_data_eye.c
new file mode 100644
index 0000000..03b8d3c
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/denali_data_eye.c
@@ -0,0 +1,389 @@
+/*
+ * arch/powerpc/cpu/ppc4xx/denali_data_eye.c
+ * Extracted from board/amcc/sequoia/sdram.c by Larry Johnson <lrj@acm.org>.
+ *
+ * (C) Copyright 2006
+ * Sylvie Gohl,             AMCC/IBM, gohl.sylvie@fr.ibm.com
+ * Jacqueline Pira-Ferriol, AMCC/IBM, jpira-ferriol@fr.ibm.com
+ * Thierry Roman,           AMCC/IBM, thierry_roman@fr.ibm.com
+ * Alain Saurel,            AMCC/IBM, alain.saurel@fr.ibm.com
+ * Robert Snyder,           AMCC/IBM, rob.snyder@fr.ibm.com
+ *
+ * (C) Copyright 2006-2007
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#if 0
+#define DEBUG
+#endif
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <ppc4xx.h>
+
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+/*-----------------------------------------------------------------------------+
+ * denali_wait_for_dlllock.
+ +----------------------------------------------------------------------------*/
+int denali_wait_for_dlllock(void)
+{
+	u32 val;
+	int wait;
+
+	/* -----------------------------------------------------------+
+	 * Wait for the DCC master delay line to finish calibration
+	 * ----------------------------------------------------------*/
+	for (wait = 0; wait != 0xffff; ++wait) {
+		mfsdram(DDR0_17, val);
+		if (DDR0_17_DLLLOCKREG_DECODE(val)) {
+			/* dlllockreg bit on */
+			return 0;
+		}
+	}
+	debug("0x%04x: DDR0_17 Value (dlllockreg bit): 0x%08x\n", wait, val);
+	debug("Waiting for dlllockreg bit to raise\n");
+	return -1;
+}
+
+#if defined(CONFIG_DDR_DATA_EYE)
+#define DDR_DCR_BASE 0x10
+#define ddrcfga  (DDR_DCR_BASE+0x0)	/* DDR configuration address reg */
+#define ddrcfgd  (DDR_DCR_BASE+0x1)	/* DDR configuration data reg    */
+
+/*-----------------------------------------------------------------------------+
+ * wait_for_dram_init_complete.
+ +----------------------------------------------------------------------------*/
+static int wait_for_dram_init_complete(void)
+{
+	unsigned long val;
+	int wait = 0;
+
+	/* --------------------------------------------------------------+
+	 * Wait for 'DRAM initialization complete' bit in status register
+	 * -------------------------------------------------------------*/
+	mtdcr(ddrcfga, DDR0_00);
+
+	while (wait != 0xffff) {
+		val = mfdcr(ddrcfgd);
+		if ((val & DDR0_00_INT_STATUS_BIT6) == DDR0_00_INT_STATUS_BIT6)
+			/* 'DRAM initialization complete' bit */
+			return 0;
+		else
+			wait++;
+	}
+	debug("DRAM initialization complete bit in status register did not "
+	      "rise\n");
+	return -1;
+}
+
+#define NUM_TRIES 64
+#define NUM_READS 10
+
+/*-----------------------------------------------------------------------------+
+ * denali_core_search_data_eye.
+ +----------------------------------------------------------------------------*/
+void denali_core_search_data_eye(void)
+{
+	int k, j;
+	u32 val;
+	u32 wr_dqs_shift, dqs_out_shift, dll_dqs_delay_X;
+	u32 max_passing_cases = 0, wr_dqs_shift_with_max_passing_cases = 0;
+	u32 passing_cases = 0, dll_dqs_delay_X_sw_val = 0;
+	u32 dll_dqs_delay_X_start_window = 0, dll_dqs_delay_X_end_window = 0;
+	volatile u32 *ram_pointer;
+	u32 test[NUM_TRIES] = {
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+		0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+		0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+		0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+		0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+		0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+		0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+		0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+		0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+		0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+		0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+		0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55
+	};
+
+	ram_pointer = (volatile u32 *)(CONFIG_SYS_SDRAM_BASE);
+
+	for (wr_dqs_shift = 64; wr_dqs_shift < 96; wr_dqs_shift++) {
+		/* for (wr_dqs_shift=1; wr_dqs_shift<96; wr_dqs_shift++) { */
+
+		/* -----------------------------------------------------------+
+		 * De-assert 'start' parameter.
+		 * ----------------------------------------------------------*/
+		mtdcr(ddrcfga, DDR0_02);
+		val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
+		    DDR0_02_START_OFF;
+		mtdcr(ddrcfgd, val);
+
+		/* -----------------------------------------------------------+
+		 * Set 'wr_dqs_shift'
+		 * ----------------------------------------------------------*/
+		mtdcr(ddrcfga, DDR0_09);
+		val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK) |
+		    DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift);
+		mtdcr(ddrcfgd, val);
+
+		/* -----------------------------------------------------------+
+		 * Set 'dqs_out_shift' = wr_dqs_shift + 32
+		 * ----------------------------------------------------------*/
+		dqs_out_shift = wr_dqs_shift + 32;
+		mtdcr(ddrcfga, DDR0_22);
+		val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK) |
+		    DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift);
+		mtdcr(ddrcfgd, val);
+
+		passing_cases = 0;
+
+		for (dll_dqs_delay_X = 1; dll_dqs_delay_X < 64;
+		     dll_dqs_delay_X++) {
+			/* for (dll_dqs_delay_X=1; dll_dqs_delay_X<128;
+			   dll_dqs_delay_X++) { */
+			/* -----------------------------------------------------------+
+			 * Set 'dll_dqs_delay_X'.
+			 * ----------------------------------------------------------*/
+			/* dll_dqs_delay_0 */
+			mtdcr(ddrcfga, DDR0_17);
+			val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK)
+			    | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X);
+			mtdcr(ddrcfgd, val);
+			/* dll_dqs_delay_1 to dll_dqs_delay_4 */
+			mtdcr(ddrcfga, DDR0_18);
+			val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK)
+			    | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X)
+			    | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X)
+			    | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X)
+			    | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X);
+			mtdcr(ddrcfgd, val);
+			/* dll_dqs_delay_5 to dll_dqs_delay_8 */
+			mtdcr(ddrcfga, DDR0_19);
+			val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK)
+			    | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X)
+			    | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X)
+			    | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X)
+			    | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X);
+			mtdcr(ddrcfgd, val);
+			/* clear any ECC errors */
+			mtdcr(ddrcfga, DDR0_00);
+			mtdcr(ddrcfgd,
+			      mfdcr(ddrcfgd) | DDR0_00_INT_ACK_ENCODE(0x3C));
+
+			sync();
+			eieio();
+
+			/* -----------------------------------------------------------+
+			 * Assert 'start' parameter.
+			 * ----------------------------------------------------------*/
+			mtdcr(ddrcfga, DDR0_02);
+			val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
+			    DDR0_02_START_ON;
+			mtdcr(ddrcfgd, val);
+
+			sync();
+			eieio();
+
+			/* -----------------------------------------------------------+
+			 * Wait for the DCC master delay line to finish calibration
+			 * ----------------------------------------------------------*/
+			if (denali_wait_for_dlllock() != 0) {
+				printf("dll lock did not occur !!!\n");
+				printf("denali_core_search_data_eye!!!\n");
+				printf("wr_dqs_shift = %d - dll_dqs_delay_X = "
+				       "%d\n", wr_dqs_shift, dll_dqs_delay_X);
+				hang();
+			}
+			sync();
+			eieio();
+
+			if (wait_for_dram_init_complete() != 0) {
+				printf("dram init complete did not occur!!!\n");
+				printf("denali_core_search_data_eye!!!\n");
+				printf("wr_dqs_shift = %d - dll_dqs_delay_X = "
+				       "%d\n", wr_dqs_shift, dll_dqs_delay_X);
+				hang();
+			}
+			udelay(100); /* wait 100us to ensure init is really completed !!! */
+
+			/* write values */
+			for (j = 0; j < NUM_TRIES; j++) {
+				ram_pointer[j] = test[j];
+
+				/* clear any cache at ram location */
+			      __asm__("dcbf 0,%0": :"r"(&ram_pointer[j]));
+			}
+
+			/* read values back */
+			for (j = 0; j < NUM_TRIES; j++) {
+				for (k = 0; k < NUM_READS; k++) {
+					/* clear any cache at ram location */
+				      __asm__("dcbf 0,%0": :"r"(&ram_pointer
+					    [j]));
+
+					if (ram_pointer[j] != test[j])
+						break;
+				}
+
+				/* read error */
+				if (k != NUM_READS)
+					break;
+			}
+
+			/* See if the dll_dqs_delay_X value passed. */
+			mtdcr(ddrcfga, DDR0_00);
+			if (j < NUM_TRIES
+			    || (DDR0_00_INT_STATUS_DECODE(mfdcr(ddrcfgd)) &
+				0x3F)) {
+				/* Failed */
+				passing_cases = 0;
+				/* break; */
+			} else {
+				/* Passed */
+				if (passing_cases == 0)
+					dll_dqs_delay_X_sw_val =
+					    dll_dqs_delay_X;
+				passing_cases++;
+				if (passing_cases >= max_passing_cases) {
+					max_passing_cases = passing_cases;
+					wr_dqs_shift_with_max_passing_cases =
+					    wr_dqs_shift;
+					dll_dqs_delay_X_start_window =
+					    dll_dqs_delay_X_sw_val;
+					dll_dqs_delay_X_end_window =
+					    dll_dqs_delay_X;
+				}
+			}
+
+			/* -----------------------------------------------------------+
+			 * De-assert 'start' parameter.
+			 * ----------------------------------------------------------*/
+			mtdcr(ddrcfga, DDR0_02);
+			val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
+			    DDR0_02_START_OFF;
+			mtdcr(ddrcfgd, val);
+		} /* for (dll_dqs_delay_X=0; dll_dqs_delay_X<128; dll_dqs_delay_X++) */
+	} /* for (wr_dqs_shift=0; wr_dqs_shift<96; wr_dqs_shift++) */
+
+	/* -----------------------------------------------------------+
+	 * Largest passing window is now detected.
+	 * ----------------------------------------------------------*/
+
+	/* Compute dll_dqs_delay_X value */
+	dll_dqs_delay_X = (dll_dqs_delay_X_end_window +
+			   dll_dqs_delay_X_start_window) / 2;
+	wr_dqs_shift = wr_dqs_shift_with_max_passing_cases;
+
+	debug("DQS calibration - Window detected:\n");
+	debug("max_passing_cases = %d\n", max_passing_cases);
+	debug("wr_dqs_shift      = %d\n", wr_dqs_shift);
+	debug("dll_dqs_delay_X   = %d\n", dll_dqs_delay_X);
+	debug("dll_dqs_delay_X window = %d - %d\n",
+	      dll_dqs_delay_X_start_window, dll_dqs_delay_X_end_window);
+
+	/* -----------------------------------------------------------+
+	 * De-assert 'start' parameter.
+	 * ----------------------------------------------------------*/
+	mtdcr(ddrcfga, DDR0_02);
+	val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF;
+	mtdcr(ddrcfgd, val);
+
+	/* -----------------------------------------------------------+
+	 * Set 'wr_dqs_shift'
+	 * ----------------------------------------------------------*/
+	mtdcr(ddrcfga, DDR0_09);
+	val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK)
+	    | DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift);
+	mtdcr(ddrcfgd, val);
+	debug("DDR0_09=0x%08lx\n", val);
+
+	/* -----------------------------------------------------------+
+	 * Set 'dqs_out_shift' = wr_dqs_shift + 32
+	 * ----------------------------------------------------------*/
+	dqs_out_shift = wr_dqs_shift + 32;
+	mtdcr(ddrcfga, DDR0_22);
+	val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK)
+	    | DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift);
+	mtdcr(ddrcfgd, val);
+	debug("DDR0_22=0x%08lx\n", val);
+
+	/* -----------------------------------------------------------+
+	 * Set 'dll_dqs_delay_X'.
+	 * ----------------------------------------------------------*/
+	/* dll_dqs_delay_0 */
+	mtdcr(ddrcfga, DDR0_17);
+	val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK)
+	    | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X);
+	mtdcr(ddrcfgd, val);
+	debug("DDR0_17=0x%08lx\n", val);
+
+	/* dll_dqs_delay_1 to dll_dqs_delay_4 */
+	mtdcr(ddrcfga, DDR0_18);
+	val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK)
+	    | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X)
+	    | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X)
+	    | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X)
+	    | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X);
+	mtdcr(ddrcfgd, val);
+	debug("DDR0_18=0x%08lx\n", val);
+
+	/* dll_dqs_delay_5 to dll_dqs_delay_8 */
+	mtdcr(ddrcfga, DDR0_19);
+	val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK)
+	    | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X)
+	    | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X)
+	    | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X)
+	    | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X);
+	mtdcr(ddrcfgd, val);
+	debug("DDR0_19=0x%08lx\n", val);
+
+	/* -----------------------------------------------------------+
+	 * Assert 'start' parameter.
+	 * ----------------------------------------------------------*/
+	mtdcr(ddrcfga, DDR0_02);
+	val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_ON;
+	mtdcr(ddrcfgd, val);
+
+	sync();
+	eieio();
+
+	/* -----------------------------------------------------------+
+	 * Wait for the DCC master delay line to finish calibration
+	 * ----------------------------------------------------------*/
+	if (denali_wait_for_dlllock() != 0) {
+		printf("dll lock did not occur !!!\n");
+		hang();
+	}
+	sync();
+	eieio();
+
+	if (wait_for_dram_init_complete() != 0) {
+		printf("dram init complete did not occur !!!\n");
+		hang();
+	}
+	udelay(100); /* wait 100us to ensure init is really completed !!! */
+}
+#endif /* defined(CONFIG_DDR_DATA_EYE) */
+#endif /* defined(CONFIG_440EPX) || defined(CONFIG_440GRX) */
diff --git a/arch/powerpc/cpu/ppc4xx/denali_spd_ddr2.c b/arch/powerpc/cpu/ppc4xx/denali_spd_ddr2.c
new file mode 100644
index 0000000..080ea0a
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/denali_spd_ddr2.c
@@ -0,0 +1,1256 @@
+/*
+ * arch/powerpc/cpu/ppc4xx/denali_spd_ddr2.c
+ * This SPD SDRAM detection code supports AMCC PPC44x CPUs with a Denali-core
+ * DDR2 controller, specifically the 440EPx/GRx.
+ *
+ * (C) Copyright 2007-2008
+ * Larry Johnson, lrj@acm.org.
+ *
+ * Based primarily on arch/powerpc/cpu/ppc4xx/4xx_spd_ddr2.c, which is...
+ *
+ * (C) Copyright 2007
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * COPYRIGHT   AMCC   CORPORATION 2004
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#if 0
+#define DEBUG
+#endif
+
+#include <common.h>
+#include <command.h>
+#include <ppc4xx.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/cache.h>
+
+#if defined(CONFIG_SPD_EEPROM) &&				\
+	(defined(CONFIG_440EPX) || defined(CONFIG_440GRX))
+
+/*-----------------------------------------------------------------------------+
+ * Defines
+ *-----------------------------------------------------------------------------*/
+#ifndef	TRUE
+#define TRUE		1
+#endif
+#ifndef FALSE
+#define FALSE		0
+#endif
+
+#define MAXDIMMS	2
+#define MAXRANKS	2
+
+#define ONE_BILLION	1000000000
+
+#define MULDIV64(m1, m2, d)	(u32)(((u64)(m1) * (u64)(m2)) / (u64)(d))
+
+#define DLL_DQS_DELAY	0x19
+#define DLL_DQS_BYPASS	0x0B
+#define DQS_OUT_SHIFT	0x7F
+
+/*
+ * This DDR2 setup code can dynamically setup the TLB entries for the DDR2 memory
+ * region. Right now the cache should still be disabled in U-Boot because of the
+ * EMAC driver, that need it's buffer descriptor to be located in non cached
+ * memory.
+ *
+ * If at some time this restriction doesn't apply anymore, just define
+ * CONFIG_4xx_DCACHE in the board config file and this code should setup
+ * everything correctly.
+ */
+#if defined(CONFIG_4xx_DCACHE)
+#define MY_TLB_WORD2_I_ENABLE	0			/* enable caching on SDRAM */
+#else
+#define MY_TLB_WORD2_I_ENABLE	TLB_WORD2_I_ENABLE	/* disable caching on SDRAM */
+#endif
+
+/*-----------------------------------------------------------------------------+
+ * Prototypes
+ *-----------------------------------------------------------------------------*/
+extern int denali_wait_for_dlllock(void);
+extern void denali_core_search_data_eye(void);
+extern void dcbz_area(u32 start_address, u32 num_bytes);
+
+/*
+ * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed
+ */
+void __spd_ddr_init_hang(void)
+{
+	hang();
+}
+void spd_ddr_init_hang(void)
+    __attribute__ ((weak, alias("__spd_ddr_init_hang")));
+
+#if defined(DEBUG)
+static void print_mcsr(void)
+{
+	printf("MCSR = 0x%08X\n", mfspr(SPRN_MCSR));
+}
+
+static void denali_sdram_register_dump(void)
+{
+	unsigned int sdram_data;
+
+	printf("\n  Register Dump:\n");
+	mfsdram(DDR0_00, sdram_data);
+	printf("        DDR0_00 = 0x%08X", sdram_data);
+	mfsdram(DDR0_01, sdram_data);
+	printf("        DDR0_01 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_02, sdram_data);
+	printf("        DDR0_02 = 0x%08X", sdram_data);
+	mfsdram(DDR0_03, sdram_data);
+	printf("        DDR0_03 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_04, sdram_data);
+	printf("        DDR0_04 = 0x%08X", sdram_data);
+	mfsdram(DDR0_05, sdram_data);
+	printf("        DDR0_05 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_06, sdram_data);
+	printf("        DDR0_06 = 0x%08X", sdram_data);
+	mfsdram(DDR0_07, sdram_data);
+	printf("        DDR0_07 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_08, sdram_data);
+	printf("        DDR0_08 = 0x%08X", sdram_data);
+	mfsdram(DDR0_09, sdram_data);
+	printf("        DDR0_09 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_10, sdram_data);
+	printf("        DDR0_10 = 0x%08X", sdram_data);
+	mfsdram(DDR0_11, sdram_data);
+	printf("        DDR0_11 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_12, sdram_data);
+	printf("        DDR0_12 = 0x%08X", sdram_data);
+	mfsdram(DDR0_14, sdram_data);
+	printf("        DDR0_14 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_17, sdram_data);
+	printf("        DDR0_17 = 0x%08X", sdram_data);
+	mfsdram(DDR0_18, sdram_data);
+	printf("        DDR0_18 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_19, sdram_data);
+	printf("        DDR0_19 = 0x%08X", sdram_data);
+	mfsdram(DDR0_20, sdram_data);
+	printf("        DDR0_20 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_21, sdram_data);
+	printf("        DDR0_21 = 0x%08X", sdram_data);
+	mfsdram(DDR0_22, sdram_data);
+	printf("        DDR0_22 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_23, sdram_data);
+	printf("        DDR0_23 = 0x%08X", sdram_data);
+	mfsdram(DDR0_24, sdram_data);
+	printf("        DDR0_24 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_25, sdram_data);
+	printf("        DDR0_25 = 0x%08X", sdram_data);
+	mfsdram(DDR0_26, sdram_data);
+	printf("        DDR0_26 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_27, sdram_data);
+	printf("        DDR0_27 = 0x%08X", sdram_data);
+	mfsdram(DDR0_28, sdram_data);
+	printf("        DDR0_28 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_31, sdram_data);
+	printf("        DDR0_31 = 0x%08X", sdram_data);
+	mfsdram(DDR0_32, sdram_data);
+	printf("        DDR0_32 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_33, sdram_data);
+	printf("        DDR0_33 = 0x%08X", sdram_data);
+	mfsdram(DDR0_34, sdram_data);
+	printf("        DDR0_34 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_35, sdram_data);
+	printf("        DDR0_35 = 0x%08X", sdram_data);
+	mfsdram(DDR0_36, sdram_data);
+	printf("        DDR0_36 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_37, sdram_data);
+	printf("        DDR0_37 = 0x%08X", sdram_data);
+	mfsdram(DDR0_38, sdram_data);
+	printf("        DDR0_38 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_39, sdram_data);
+	printf("        DDR0_39 = 0x%08X", sdram_data);
+	mfsdram(DDR0_40, sdram_data);
+	printf("        DDR0_40 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_41, sdram_data);
+	printf("        DDR0_41 = 0x%08X", sdram_data);
+	mfsdram(DDR0_42, sdram_data);
+	printf("        DDR0_42 = 0x%08X\n", sdram_data);
+	mfsdram(DDR0_43, sdram_data);
+	printf("        DDR0_43 = 0x%08X", sdram_data);
+	mfsdram(DDR0_44, sdram_data);
+	printf("        DDR0_44 = 0x%08X\n", sdram_data);
+}
+#else
+static inline void denali_sdram_register_dump(void)
+{
+}
+
+inline static void print_mcsr(void)
+{
+}
+#endif /* defined(DEBUG) */
+
+static int is_ecc_enabled(void)
+{
+	u32 val;
+
+	mfsdram(DDR0_22, val);
+	return 0x3 == DDR0_22_CTRL_RAW_DECODE(val);
+}
+
+static unsigned char spd_read(u8 chip, unsigned int addr)
+{
+	u8 data[2];
+
+	if (0 != i2c_probe(chip) || 0 != i2c_read(chip, addr, 1, data, 1)) {
+		debug("spd_read(0x%02X, 0x%02X) failed\n", chip, addr);
+		return 0;
+	}
+	debug("spd_read(0x%02X, 0x%02X) returned 0x%02X\n",
+	      chip, addr, data[0]);
+	return data[0];
+}
+
+static unsigned long get_tcyc(unsigned char reg)
+{
+	/*
+	 * Byte 9, et al: Cycle time for CAS Latency=X, is split into two
+	 * nibbles: the higher order nibble (bits 4-7) designates the cycle time
+	 * to a granularity of 1ns; the value presented by the lower order
+	 * nibble (bits 0-3) has a granularity of .1ns and is added to the value
+	 * designated by the higher nibble. In addition, four lines of the lower
+	 * order nibble are assigned to support +.25, +.33, +.66, and +.75.
+	 */
+
+	unsigned char subfield_b = reg & 0x0F;
+
+	switch (subfield_b & 0x0F) {
+	case 0x0:
+	case 0x1:
+	case 0x2:
+	case 0x3:
+	case 0x4:
+	case 0x5:
+	case 0x6:
+	case 0x7:
+	case 0x8:
+	case 0x9:
+		return 1000 * (reg >> 4) + 100 * subfield_b;
+	case 0xA:
+		return 1000 * (reg >> 4) + 250;
+	case 0xB:
+		return 1000 * (reg >> 4) + 333;
+	case 0xC:
+		return 1000 * (reg >> 4) + 667;
+	case 0xD:
+		return 1000 * (reg >> 4) + 750;
+	}
+	return 0;
+}
+
+/*------------------------------------------------------------------
+ * Find the installed DIMMs, make sure that the are DDR2, and fill
+ * in the dimm_ranks array.  Then dimm_ranks[dimm_num] > 0 iff the
+ * DIMM and dimm_num is present.
+ * Note: Because there are only two chip-select lines, it is assumed
+ * that a board with a single socket can support two ranks on that
+ * socket, while a board with two sockets can support only one rank
+ * on each socket.
+ *-----------------------------------------------------------------*/
+static void get_spd_info(unsigned long dimm_ranks[],
+			 unsigned long *ranks,
+			 unsigned char const iic0_dimm_addr[],
+			 unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long dimm_found = FALSE;
+	unsigned long const max_ranks_per_dimm = (1 == num_dimm_banks) ? 2 : 1;
+	unsigned char num_of_bytes;
+	unsigned char total_size;
+
+	*ranks = 0;
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		num_of_bytes = 0;
+		total_size = 0;
+
+		num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0);
+		total_size = spd_read(iic0_dimm_addr[dimm_num], 1);
+		if ((num_of_bytes != 0) && (total_size != 0)) {
+			unsigned char const dimm_type =
+			    spd_read(iic0_dimm_addr[dimm_num], 2);
+
+			unsigned long ranks_on_dimm =
+			    (spd_read(iic0_dimm_addr[dimm_num], 5) & 0x07) + 1;
+
+			if (8 != dimm_type) {
+				switch (dimm_type) {
+				case 1:
+					printf("ERROR: Standard Fast Page Mode "
+					       "DRAM DIMM");
+					break;
+				case 2:
+					printf("ERROR: EDO DIMM");
+					break;
+				case 3:
+					printf("ERROR: Pipelined Nibble DIMM");
+					break;
+				case 4:
+					printf("ERROR: SDRAM DIMM");
+					break;
+				case 5:
+					printf("ERROR: Multiplexed ROM DIMM");
+					break;
+				case 6:
+					printf("ERROR: SGRAM DIMM");
+					break;
+				case 7:
+					printf("ERROR: DDR1 DIMM");
+					break;
+				default:
+					printf("ERROR: Unknown DIMM (type %d)",
+					       (unsigned int)dimm_type);
+					break;
+				}
+				printf(" detected in slot %lu.\n", dimm_num);
+				printf("Only DDR2 SDRAM DIMMs are supported."
+				       "\n");
+				printf("Replace the module with a DDR2 DIMM."
+				       "\n\n");
+				spd_ddr_init_hang();
+			}
+			dimm_found = TRUE;
+			debug("DIMM slot %lu: populated with %lu-rank DDR2 DIMM"
+			      "\n", dimm_num, ranks_on_dimm);
+			if (ranks_on_dimm > max_ranks_per_dimm) {
+				printf("WARNING: DRAM DIMM in slot %lu has %lu "
+				       "ranks.\n", dimm_num, ranks_on_dimm);
+				if (1 == max_ranks_per_dimm) {
+					printf("Only one rank will be used.\n");
+				} else {
+					printf
+					    ("Only two ranks will be used.\n");
+				}
+				ranks_on_dimm = max_ranks_per_dimm;
+			}
+			dimm_ranks[dimm_num] = ranks_on_dimm;
+			*ranks += ranks_on_dimm;
+		} else {
+			dimm_ranks[dimm_num] = 0;
+			debug("DIMM slot %lu: Not populated\n", dimm_num);
+		}
+	}
+	if (dimm_found == FALSE) {
+		printf("ERROR: No memory installed.\n");
+		printf("Install at least one DDR2 DIMM.\n\n");
+		spd_ddr_init_hang();
+	}
+	debug("Total number of ranks = %d\n", *ranks);
+}
+
+/*------------------------------------------------------------------
+ * For the memory DIMMs installed, this routine verifies that
+ * frequency previously calculated is supported.
+ *-----------------------------------------------------------------*/
+static void check_frequency(unsigned long *dimm_ranks,
+			    unsigned char const iic0_dimm_addr[],
+			    unsigned long num_dimm_banks,
+			    unsigned long sdram_freq)
+{
+	unsigned long dimm_num;
+	unsigned long cycle_time;
+	unsigned long calc_cycle_time;
+
+	/*
+	 * calc_cycle_time is calculated from DDR frequency set by board/chip
+	 * and is expressed in picoseconds to match the way DIMM cycle time is
+	 * calculated below.
+	 */
+	calc_cycle_time = MULDIV64(ONE_BILLION, 1000, sdram_freq);
+
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_ranks[dimm_num]) {
+			cycle_time =
+			    get_tcyc(spd_read(iic0_dimm_addr[dimm_num], 9));
+			debug("cycle_time=%d ps\n", cycle_time);
+
+			if (cycle_time > (calc_cycle_time + 10)) {
+				/*
+				 * the provided sdram cycle_time is too small
+				 * for the available DIMM cycle_time. The
+				 * additionnal 10ps is here to accept a small
+				 * incertainty.
+				 */
+				printf
+				    ("ERROR: DRAM DIMM detected with cycle_time %d ps in "
+				     "slot %d \n while calculated cycle time is %d ps.\n",
+				     (unsigned int)cycle_time,
+				     (unsigned int)dimm_num,
+				     (unsigned int)calc_cycle_time);
+				printf
+				    ("Replace the DIMM, or change DDR frequency via "
+				     "strapping bits.\n\n");
+				spd_ddr_init_hang();
+			}
+		}
+	}
+}
+
+/*------------------------------------------------------------------
+ * This routine gets size information for the installed memory
+ * DIMMs.
+ *-----------------------------------------------------------------*/
+static void get_dimm_size(unsigned long dimm_ranks[],
+			  unsigned char const iic0_dimm_addr[],
+			  unsigned long num_dimm_banks,
+			  unsigned long *const rows,
+			  unsigned long *const banks,
+			  unsigned long *const cols, unsigned long *const width)
+{
+	unsigned long dimm_num;
+
+	*rows = 0;
+	*banks = 0;
+	*cols = 0;
+	*width = 0;
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_ranks[dimm_num]) {
+			unsigned long t;
+
+			/* Rows */
+			t = spd_read(iic0_dimm_addr[dimm_num], 3);
+			if (0 == *rows) {
+				*rows = t;
+			} else if (t != *rows) {
+				printf("ERROR: DRAM DIMM modules do not all "
+				       "have the same number of rows.\n\n");
+				spd_ddr_init_hang();
+			}
+			/* Banks */
+			t = spd_read(iic0_dimm_addr[dimm_num], 17);
+			if (0 == *banks) {
+				*banks = t;
+			} else if (t != *banks) {
+				printf("ERROR: DRAM DIMM modules do not all "
+				       "have the same number of banks.\n\n");
+				spd_ddr_init_hang();
+			}
+			/* Columns */
+			t = spd_read(iic0_dimm_addr[dimm_num], 4);
+			if (0 == *cols) {
+				*cols = t;
+			} else if (t != *cols) {
+				printf("ERROR: DRAM DIMM modules do not all "
+				       "have the same number of columns.\n\n");
+				spd_ddr_init_hang();
+			}
+			/* Data width */
+			t = spd_read(iic0_dimm_addr[dimm_num], 6);
+			if (0 == *width) {
+				*width = t;
+			} else if (t != *width) {
+				printf("ERROR: DRAM DIMM modules do not all "
+				       "have the same data width.\n\n");
+				spd_ddr_init_hang();
+			}
+		}
+	}
+	debug("Number of rows = %d\n", *rows);
+	debug("Number of columns = %d\n", *cols);
+	debug("Number of banks = %d\n", *banks);
+	debug("Data width = %d\n", *width);
+	if (*rows > 14) {
+		printf("ERROR: DRAM DIMM modules have %lu address rows.\n",
+		       *rows);
+		printf("Only modules with 14 or fewer rows are supported.\n\n");
+		spd_ddr_init_hang();
+	}
+	if (4 != *banks && 8 != *banks) {
+		printf("ERROR: DRAM DIMM modules have %lu banks.\n", *banks);
+		printf("Only modules with 4 or 8 banks are supported.\n\n");
+		spd_ddr_init_hang();
+	}
+	if (*cols > 12) {
+		printf("ERROR: DRAM DIMM modules have %lu address columns.\n",
+		       *cols);
+		printf("Only modules with 12 or fewer columns are "
+		       "supported.\n\n");
+		spd_ddr_init_hang();
+	}
+	if (32 != *width && 40 != *width && 64 != *width && 72 != *width) {
+		printf("ERROR: DRAM DIMM modules have a width of %lu bit.\n",
+		       *width);
+		printf("Only modules with widths of 32, 40, 64, and 72 bits "
+		       "are supported.\n\n");
+		spd_ddr_init_hang();
+	}
+}
+
+/*------------------------------------------------------------------
+ * Only 1.8V modules are supported.  This routine verifies this.
+ *-----------------------------------------------------------------*/
+static void check_voltage_type(unsigned long dimm_ranks[],
+			       unsigned char const iic0_dimm_addr[],
+			       unsigned long num_dimm_banks)
+{
+	unsigned long dimm_num;
+	unsigned long voltage_type;
+
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		if (dimm_ranks[dimm_num]) {
+			voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8);
+			if (0x05 != voltage_type) {	/* 1.8V for DDR2 */
+				printf("ERROR: Slot %lu provides 1.8V for DDR2 "
+				       "DIMMs.\n", dimm_num);
+				switch (voltage_type) {
+				case 0x00:
+					printf("This DIMM is 5.0 Volt/TTL.\n");
+					break;
+				case 0x01:
+					printf("This DIMM is LVTTL.\n");
+					break;
+				case 0x02:
+					printf("This DIMM is 1.5 Volt.\n");
+					break;
+				case 0x03:
+					printf("This DIMM is 3.3 Volt/TTL.\n");
+					break;
+				case 0x04:
+					printf("This DIMM is 2.5 Volt.\n");
+					break;
+				default:
+					printf("This DIMM is an unknown "
+					       "voltage.\n");
+					break;
+				}
+				printf("Replace it with a 1.8V DDR2 DIMM.\n\n");
+				spd_ddr_init_hang();
+			}
+		}
+	}
+}
+
+static void program_ddr0_03(unsigned long dimm_ranks[],
+			    unsigned char const iic0_dimm_addr[],
+			    unsigned long num_dimm_banks,
+			    unsigned long sdram_freq,
+			    unsigned long rows, unsigned long *cas_latency)
+{
+	unsigned long dimm_num;
+	unsigned long cas_index;
+	unsigned long cycle_2_0_clk;
+	unsigned long cycle_3_0_clk;
+	unsigned long cycle_4_0_clk;
+	unsigned long cycle_5_0_clk;
+	unsigned long max_2_0_tcyc_ps = 100;
+	unsigned long max_3_0_tcyc_ps = 100;
+	unsigned long max_4_0_tcyc_ps = 100;
+	unsigned long max_5_0_tcyc_ps = 100;
+	unsigned char cas_available = 0x3C;	/* value for DDR2 */
+	u32 ddr0_03 = DDR0_03_BSTLEN_ENCODE(0x2) | DDR0_03_INITAREF_ENCODE(0x2);
+	unsigned int const tcyc_addr[3] = { 9, 23, 25 };
+
+	/*------------------------------------------------------------------
+	 * Get the board configuration info.
+	 *-----------------------------------------------------------------*/
+	debug("sdram_freq = %d\n", sdram_freq);
+
+	/*------------------------------------------------------------------
+	 * Handle the timing.  We need to find the worst case timing of all
+	 * the dimm modules installed.
+	 *-----------------------------------------------------------------*/
+	/* loop through all the DIMM slots on the board */
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		/* If a dimm is installed in a particular slot ... */
+		if (dimm_ranks[dimm_num]) {
+			unsigned char const cas_bit =
+			    spd_read(iic0_dimm_addr[dimm_num], 18);
+			unsigned char cas_mask;
+
+			cas_available &= cas_bit;
+			for (cas_mask = 0x80; cas_mask; cas_mask >>= 1) {
+				if (cas_bit & cas_mask)
+					break;
+			}
+			debug("cas_bit (SPD byte 18) = %02X, cas_mask = %02X\n",
+			      cas_bit, cas_mask);
+
+			for (cas_index = 0; cas_index < 3;
+			     cas_mask >>= 1, cas_index++) {
+				unsigned long cycle_time_ps;
+
+				if (!(cas_available & cas_mask)) {
+					continue;
+				}
+				cycle_time_ps =
+				    get_tcyc(spd_read(iic0_dimm_addr[dimm_num],
+						      tcyc_addr[cas_index]));
+
+				debug("cas_index = %d: cycle_time_ps = %d\n",
+				      cas_index, cycle_time_ps);
+				/*
+				 * DDR2 devices use the following bitmask for CAS latency:
+				 *  Bit   7    6    5    4    3    2    1    0
+				 *       TBD  6.0  5.0  4.0  3.0  2.0  TBD  TBD
+				 */
+				switch (cas_mask) {
+				case 0x20:
+					max_5_0_tcyc_ps =
+					    max(max_5_0_tcyc_ps, cycle_time_ps);
+					break;
+				case 0x10:
+					max_4_0_tcyc_ps =
+					    max(max_4_0_tcyc_ps, cycle_time_ps);
+					break;
+				case 0x08:
+					max_3_0_tcyc_ps =
+					    max(max_3_0_tcyc_ps, cycle_time_ps);
+					break;
+				case 0x04:
+					max_2_0_tcyc_ps =
+					    max(max_2_0_tcyc_ps, cycle_time_ps);
+					break;
+				}
+			}
+		}
+	}
+	debug("cas_available (bit map) = 0x%02X\n", cas_available);
+
+	/*------------------------------------------------------------------
+	 * Set the SDRAM mode, SDRAM_MMODE
+	 *-----------------------------------------------------------------*/
+
+	/* add 10 here because of rounding problems */
+	cycle_2_0_clk = MULDIV64(ONE_BILLION, 1000, max_2_0_tcyc_ps) + 10;
+	cycle_3_0_clk = MULDIV64(ONE_BILLION, 1000, max_3_0_tcyc_ps) + 10;
+	cycle_4_0_clk = MULDIV64(ONE_BILLION, 1000, max_4_0_tcyc_ps) + 10;
+	cycle_5_0_clk = MULDIV64(ONE_BILLION, 1000, max_5_0_tcyc_ps) + 10;
+	debug("cycle_2_0_clk = %d\n", cycle_2_0_clk);
+	debug("cycle_3_0_clk = %d\n", cycle_3_0_clk);
+	debug("cycle_4_0_clk = %d\n", cycle_4_0_clk);
+	debug("cycle_5_0_clk = %d\n", cycle_5_0_clk);
+
+	if ((cas_available & 0x04) && (sdram_freq <= cycle_2_0_clk)) {
+		*cas_latency = 2;
+		ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x2) |
+		    DDR0_03_CASLAT_LIN_ENCODE(0x4);
+	} else if ((cas_available & 0x08) && (sdram_freq <= cycle_3_0_clk)) {
+		*cas_latency = 3;
+		ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x3) |
+		    DDR0_03_CASLAT_LIN_ENCODE(0x6);
+	} else if ((cas_available & 0x10) && (sdram_freq <= cycle_4_0_clk)) {
+		*cas_latency = 4;
+		ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x4) |
+		    DDR0_03_CASLAT_LIN_ENCODE(0x8);
+	} else if ((cas_available & 0x20) && (sdram_freq <= cycle_5_0_clk)) {
+		*cas_latency = 5;
+		ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x5) |
+		    DDR0_03_CASLAT_LIN_ENCODE(0xA);
+	} else {
+		printf("ERROR: Cannot find a supported CAS latency with the "
+		       "installed DIMMs.\n");
+		printf("Only DDR2 DIMMs with CAS latencies of 2.0, 3.0, 4.0, "
+		       "and 5.0 are supported.\n");
+		printf("Make sure the PLB speed is within the supported range "
+		       "of the DIMMs.\n");
+		printf("sdram_freq=%ld cycle2=%ld cycle3=%ld cycle4=%ld "
+		       "cycle5=%ld\n\n", sdram_freq, cycle_2_0_clk,
+		       cycle_3_0_clk, cycle_4_0_clk, cycle_5_0_clk);
+		spd_ddr_init_hang();
+	}
+	debug("CAS latency = %d\n", *cas_latency);
+	mtsdram(DDR0_03, ddr0_03);
+}
+
+static void program_ddr0_04(unsigned long dimm_ranks[],
+			    unsigned char const iic0_dimm_addr[],
+			    unsigned long num_dimm_banks,
+			    unsigned long sdram_freq)
+{
+	unsigned long dimm_num;
+	unsigned long t_rc_ps = 0;
+	unsigned long t_rrd_ps = 0;
+	unsigned long t_rtp_ps = 0;
+	unsigned long t_rc_clk;
+	unsigned long t_rrd_clk;
+	unsigned long t_rtp_clk;
+
+	/*------------------------------------------------------------------
+	 * Handle the timing.  We need to find the worst case timing of all
+	 * the dimm modules installed.
+	 *-----------------------------------------------------------------*/
+	/* loop through all the DIMM slots on the board */
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		/* If a dimm is installed in a particular slot ... */
+		if (dimm_ranks[dimm_num]) {
+			unsigned long ps;
+
+			/* tRC */
+			ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 41);
+			switch (spd_read(iic0_dimm_addr[dimm_num], 40) >> 4) {
+			case 0x1:
+				ps += 250;
+				break;
+			case 0x2:
+				ps += 333;
+				break;
+			case 0x3:
+				ps += 500;
+				break;
+			case 0x4:
+				ps += 667;
+				break;
+			case 0x5:
+				ps += 750;
+				break;
+			}
+			t_rc_ps = max(t_rc_ps, ps);
+			/* tRRD */
+			ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 28);
+			t_rrd_ps = max(t_rrd_ps, ps);
+			/* tRTP */
+			ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 38);
+			t_rtp_ps = max(t_rtp_ps, ps);
+		}
+	}
+	debug("t_rc_ps  = %d\n", t_rc_ps);
+	t_rc_clk = (MULDIV64(sdram_freq, t_rc_ps, ONE_BILLION) + 999) / 1000;
+	debug("t_rrd_ps = %d\n", t_rrd_ps);
+	t_rrd_clk = (MULDIV64(sdram_freq, t_rrd_ps, ONE_BILLION) + 999) / 1000;
+	debug("t_rtp_ps = %d\n", t_rtp_ps);
+	t_rtp_clk = (MULDIV64(sdram_freq, t_rtp_ps, ONE_BILLION) + 999) / 1000;
+	mtsdram(DDR0_04, DDR0_04_TRC_ENCODE(t_rc_clk) |
+		DDR0_04_TRRD_ENCODE(t_rrd_clk) |
+		DDR0_04_TRTP_ENCODE(t_rtp_clk));
+}
+
+static void program_ddr0_05(unsigned long dimm_ranks[],
+			    unsigned char const iic0_dimm_addr[],
+			    unsigned long num_dimm_banks,
+			    unsigned long sdram_freq)
+{
+	unsigned long dimm_num;
+	unsigned long t_rp_ps = 0;
+	unsigned long t_ras_ps = 0;
+	unsigned long t_rp_clk;
+	unsigned long t_ras_clk;
+	u32 ddr0_05 = DDR0_05_TMRD_ENCODE(0x2) | DDR0_05_TEMRS_ENCODE(0x2);
+
+	/*------------------------------------------------------------------
+	 * Handle the timing.  We need to find the worst case timing of all
+	 * the dimm modules installed.
+	 *-----------------------------------------------------------------*/
+	/* loop through all the DIMM slots on the board */
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		/* If a dimm is installed in a particular slot ... */
+		if (dimm_ranks[dimm_num]) {
+			unsigned long ps;
+
+			/* tRP */
+			ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 27);
+			t_rp_ps = max(t_rp_ps, ps);
+			/* tRAS */
+			ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 30);
+			t_ras_ps = max(t_ras_ps, ps);
+		}
+	}
+	debug("t_rp_ps  = %d\n", t_rp_ps);
+	t_rp_clk = (MULDIV64(sdram_freq, t_rp_ps, ONE_BILLION) + 999) / 1000;
+	debug("t_ras_ps = %d\n", t_ras_ps);
+	t_ras_clk = (MULDIV64(sdram_freq, t_ras_ps, ONE_BILLION) + 999) / 1000;
+	mtsdram(DDR0_05, ddr0_05 | DDR0_05_TRP_ENCODE(t_rp_clk) |
+		DDR0_05_TRAS_MIN_ENCODE(t_ras_clk));
+}
+
+static void program_ddr0_06(unsigned long dimm_ranks[],
+			    unsigned char const iic0_dimm_addr[],
+			    unsigned long num_dimm_banks,
+			    unsigned long sdram_freq)
+{
+	unsigned long dimm_num;
+	unsigned char spd_40;
+	unsigned long t_wtr_ps = 0;
+	unsigned long t_rfc_ps = 0;
+	unsigned long t_wtr_clk;
+	unsigned long t_rfc_clk;
+	u32 ddr0_06 =
+	    DDR0_06_WRITEINTERP_ENCODE(0x1) | DDR0_06_TDLL_ENCODE(200);
+
+	/*------------------------------------------------------------------
+	 * Handle the timing.  We need to find the worst case timing of all
+	 * the dimm modules installed.
+	 *-----------------------------------------------------------------*/
+	/* loop through all the DIMM slots on the board */
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		/* If a dimm is installed in a particular slot ... */
+		if (dimm_ranks[dimm_num]) {
+			unsigned long ps;
+
+			/* tWTR */
+			ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 37);
+			t_wtr_ps = max(t_wtr_ps, ps);
+			/* tRFC */
+			ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 42);
+			spd_40 = spd_read(iic0_dimm_addr[dimm_num], 40);
+			ps += 256000 * (spd_40 & 0x01);
+			switch ((spd_40 & 0x0E) >> 1) {
+			case 0x1:
+				ps += 250;
+				break;
+			case 0x2:
+				ps += 333;
+				break;
+			case 0x3:
+				ps += 500;
+				break;
+			case 0x4:
+				ps += 667;
+				break;
+			case 0x5:
+				ps += 750;
+				break;
+			}
+			t_rfc_ps = max(t_rfc_ps, ps);
+		}
+	}
+	debug("t_wtr_ps = %d\n", t_wtr_ps);
+	t_wtr_clk = (MULDIV64(sdram_freq, t_wtr_ps, ONE_BILLION) + 999) / 1000;
+	debug("t_rfc_ps = %d\n", t_rfc_ps);
+	t_rfc_clk = (MULDIV64(sdram_freq, t_rfc_ps, ONE_BILLION) + 999) / 1000;
+	mtsdram(DDR0_06, ddr0_06 | DDR0_06_TWTR_ENCODE(t_wtr_clk) |
+		DDR0_06_TRFC_ENCODE(t_rfc_clk));
+}
+
+static void program_ddr0_10(unsigned long dimm_ranks[], unsigned long ranks)
+{
+	unsigned long csmap;
+
+	if (2 == ranks) {
+		/* Both chip selects in use */
+		csmap = 0x03;
+	} else {
+		/* One chip select in use */
+		csmap = (1 == dimm_ranks[0]) ? 0x1 : 0x2;
+	}
+	mtsdram(DDR0_10, DDR0_10_WRITE_MODEREG_ENCODE(0x0) |
+		DDR0_10_CS_MAP_ENCODE(csmap) |
+		DDR0_10_OCD_ADJUST_PUP_CS_0_ENCODE(0));
+}
+
+static void program_ddr0_11(unsigned long sdram_freq)
+{
+	unsigned long const t_xsnr_ps = 200000;	/* 200 ns */
+	unsigned long t_xsnr_clk;
+
+	debug("t_xsnr_ps = %d\n", t_xsnr_ps);
+	t_xsnr_clk =
+	    (MULDIV64(sdram_freq, t_xsnr_ps, ONE_BILLION) + 999) / 1000;
+	mtsdram(DDR0_11, DDR0_11_SREFRESH_ENCODE(0) |
+		DDR0_11_TXSNR_ENCODE(t_xsnr_clk) | DDR0_11_TXSR_ENCODE(200));
+}
+
+static void program_ddr0_22(unsigned long dimm_ranks[],
+			    unsigned char const iic0_dimm_addr[],
+			    unsigned long num_dimm_banks, unsigned long width)
+{
+#if defined(CONFIG_DDR_ECC)
+	unsigned long dimm_num;
+	unsigned long ecc_available = width >= 64;
+	u32 ddr0_22 = DDR0_22_DQS_OUT_SHIFT_BYPASS_ENCODE(0x26) |
+	    DDR0_22_DQS_OUT_SHIFT_ENCODE(DQS_OUT_SHIFT) |
+	    DDR0_22_DLL_DQS_BYPASS_8_ENCODE(DLL_DQS_BYPASS);
+
+	/* loop through all the DIMM slots on the board */
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		/* If a dimm is installed in a particular slot ... */
+		if (dimm_ranks[dimm_num]) {
+			/* Check for ECC */
+			if (0 == (spd_read(iic0_dimm_addr[dimm_num], 11) &
+				  0x02)) {
+				ecc_available = FALSE;
+			}
+		}
+	}
+	if (ecc_available) {
+		debug("ECC found on all DIMMs present\n");
+		mtsdram(DDR0_22, ddr0_22 | DDR0_22_CTRL_RAW_ENCODE(0x3));
+	} else {
+		debug("ECC not found on some or all DIMMs present\n");
+		mtsdram(DDR0_22, ddr0_22 | DDR0_22_CTRL_RAW_ENCODE(0x0));
+	}
+#else
+	mtsdram(DDR0_22, DDR0_22_CTRL_RAW_ENCODE(0x0) |
+		DDR0_22_DQS_OUT_SHIFT_BYPASS_ENCODE(0x26) |
+		DDR0_22_DQS_OUT_SHIFT_ENCODE(DQS_OUT_SHIFT) |
+		DDR0_22_DLL_DQS_BYPASS_8_ENCODE(DLL_DQS_BYPASS));
+#endif /* defined(CONFIG_DDR_ECC) */
+}
+
+static void program_ddr0_24(unsigned long ranks)
+{
+	u32 ddr0_24 = DDR0_24_RTT_PAD_TERMINATION_ENCODE(0x1) |	/* 75 ohm */
+	    DDR0_24_ODT_RD_MAP_CS1_ENCODE(0x0);
+
+	if (2 == ranks) {
+		/* Both chip selects in use */
+		ddr0_24 |= DDR0_24_ODT_WR_MAP_CS1_ENCODE(0x1) |
+		    DDR0_24_ODT_WR_MAP_CS0_ENCODE(0x2);
+	} else {
+		/* One chip select in use */
+		/* One of the two fields added to ddr0_24 is a "don't care" */
+		ddr0_24 |= DDR0_24_ODT_WR_MAP_CS1_ENCODE(0x2) |
+		    DDR0_24_ODT_WR_MAP_CS0_ENCODE(0x1);
+	}
+	mtsdram(DDR0_24, ddr0_24);
+}
+
+static void program_ddr0_26(unsigned long sdram_freq)
+{
+	unsigned long const t_ref_ps = 7800000;	/* 7.8 us. refresh */
+	/* TODO: check definition of tRAS_MAX */
+	unsigned long const t_ras_max_ps = 9 * t_ref_ps;
+	unsigned long t_ras_max_clk;
+	unsigned long t_ref_clk;
+
+	/* Round down t_ras_max_clk and t_ref_clk */
+	debug("t_ras_max_ps = %d\n", t_ras_max_ps);
+	t_ras_max_clk = MULDIV64(sdram_freq, t_ras_max_ps, ONE_BILLION) / 1000;
+	debug("t_ref_ps     = %d\n", t_ref_ps);
+	t_ref_clk = MULDIV64(sdram_freq, t_ref_ps, ONE_BILLION) / 1000;
+	mtsdram(DDR0_26, DDR0_26_TRAS_MAX_ENCODE(t_ras_max_clk) |
+		DDR0_26_TREF_ENCODE(t_ref_clk));
+}
+
+static void program_ddr0_27(unsigned long sdram_freq)
+{
+	unsigned long const t_init_ps = 200000000;	/* 200 us. init */
+	unsigned long t_init_clk;
+
+	debug("t_init_ps = %d\n", t_init_ps);
+	t_init_clk =
+	    (MULDIV64(sdram_freq, t_init_ps, ONE_BILLION) + 999) / 1000;
+	mtsdram(DDR0_27, DDR0_27_EMRS_DATA_ENCODE(0x0000) |
+		DDR0_27_TINIT_ENCODE(t_init_clk));
+}
+
+static void program_ddr0_43(unsigned long dimm_ranks[],
+			    unsigned char const iic0_dimm_addr[],
+			    unsigned long num_dimm_banks,
+			    unsigned long sdram_freq,
+			    unsigned long cols, unsigned long banks)
+{
+	unsigned long dimm_num;
+	unsigned long t_wr_ps = 0;
+	unsigned long t_wr_clk;
+	u32 ddr0_43 = DDR0_43_APREBIT_ENCODE(10) |
+	    DDR0_43_COLUMN_SIZE_ENCODE(12 - cols) |
+	    DDR0_43_EIGHT_BANK_MODE_ENCODE(8 == banks ? 1 : 0);
+
+	/*------------------------------------------------------------------
+	 * Handle the timing.  We need to find the worst case timing of all
+	 * the dimm modules installed.
+	 *-----------------------------------------------------------------*/
+	/* loop through all the DIMM slots on the board */
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		/* If a dimm is installed in a particular slot ... */
+		if (dimm_ranks[dimm_num]) {
+			unsigned long ps;
+
+			ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 36);
+			t_wr_ps = max(t_wr_ps, ps);
+		}
+	}
+	debug("t_wr_ps = %d\n", t_wr_ps);
+	t_wr_clk = (MULDIV64(sdram_freq, t_wr_ps, ONE_BILLION) + 999) / 1000;
+	mtsdram(DDR0_43, ddr0_43 | DDR0_43_TWR_ENCODE(t_wr_clk));
+}
+
+static void program_ddr0_44(unsigned long dimm_ranks[],
+			    unsigned char const iic0_dimm_addr[],
+			    unsigned long num_dimm_banks,
+			    unsigned long sdram_freq)
+{
+	unsigned long dimm_num;
+	unsigned long t_rcd_ps = 0;
+	unsigned long t_rcd_clk;
+
+	/*------------------------------------------------------------------
+	 * Handle the timing.  We need to find the worst case timing of all
+	 * the dimm modules installed.
+	 *-----------------------------------------------------------------*/
+	/* loop through all the DIMM slots on the board */
+	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+		/* If a dimm is installed in a particular slot ... */
+		if (dimm_ranks[dimm_num]) {
+			unsigned long ps;
+
+			ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 29);
+			t_rcd_ps = max(t_rcd_ps, ps);
+		}
+	}
+	debug("t_rcd_ps = %d\n", t_rcd_ps);
+	t_rcd_clk = (MULDIV64(sdram_freq, t_rcd_ps, ONE_BILLION) + 999) / 1000;
+	mtsdram(DDR0_44, DDR0_44_TRCD_ENCODE(t_rcd_clk));
+}
+
+/*-----------------------------------------------------------------------------+
+ * initdram.  Initializes the 440EPx/GPx DDR SDRAM controller.
+ * Note: This routine runs from flash with a stack set up in the chip's
+ * sram space.  It is important that the routine does not require .sbss, .bss or
+ * .data sections.  It also cannot call routines that require these sections.
+ *-----------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------
+ * Function:	 initdram
+ * Description:  Configures SDRAM memory banks for DDR operation.
+ *		 Auto Memory Configuration option reads the DDR SDRAM EEPROMs
+ *		 via the IIC bus and then configures the DDR SDRAM memory
+ *		 banks appropriately. If Auto Memory Configuration is
+ *		 not used, it is assumed that no DIMM is plugged
+ *-----------------------------------------------------------------------------*/
+phys_size_t initdram(int board_type)
+{
+	unsigned char const iic0_dimm_addr[] = SPD_EEPROM_ADDRESS;
+	unsigned long dimm_ranks[MAXDIMMS];
+	unsigned long ranks;
+	unsigned long rows;
+	unsigned long banks;
+	unsigned long cols;
+	unsigned long width;
+	unsigned long const sdram_freq = get_bus_freq(0);
+	unsigned long const num_dimm_banks = sizeof(iic0_dimm_addr);	/* on board dimm banks */
+	unsigned long cas_latency = 0;	/* to quiet initialization warning */
+	unsigned long dram_size;
+
+	debug("\nEntering initdram()\n");
+
+	/*------------------------------------------------------------------
+	 * Stop the DDR-SDRAM controller.
+	 *-----------------------------------------------------------------*/
+	mtsdram(DDR0_02, DDR0_02_START_ENCODE(0));
+
+	/*
+	 * Make sure I2C controller is initialized
+	 * before continuing.
+	 */
+	/* switch to correct I2C bus */
+	I2C_SET_BUS(CONFIG_SYS_SPD_BUS_NUM);
+	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+	/*------------------------------------------------------------------
+	 * Clear out the serial presence detect buffers.
+	 * Perform IIC reads from the dimm.  Fill in the spds.
+	 * Check to see if the dimm slots are populated
+	 *-----------------------------------------------------------------*/
+	get_spd_info(dimm_ranks, &ranks, iic0_dimm_addr, num_dimm_banks);
+
+	/*------------------------------------------------------------------
+	 * Check the frequency supported for the dimms plugged.
+	 *-----------------------------------------------------------------*/
+	check_frequency(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq);
+
+	/*------------------------------------------------------------------
+	 * Check and get size information.
+	 *-----------------------------------------------------------------*/
+	get_dimm_size(dimm_ranks, iic0_dimm_addr, num_dimm_banks, &rows, &banks,
+		      &cols, &width);
+
+	/*------------------------------------------------------------------
+	 * Check the voltage type for the dimms plugged.
+	 *-----------------------------------------------------------------*/
+	check_voltage_type(dimm_ranks, iic0_dimm_addr, num_dimm_banks);
+
+	/*------------------------------------------------------------------
+	 * Program registers for SDRAM controller.
+	 *-----------------------------------------------------------------*/
+	mtsdram(DDR0_00, DDR0_00_DLL_INCREMENT_ENCODE(0x19) |
+		DDR0_00_DLL_START_POINT_DECODE(0x0A));
+
+	mtsdram(DDR0_01, DDR0_01_PLB0_DB_CS_LOWER_ENCODE(0x01) |
+		DDR0_01_PLB0_DB_CS_UPPER_ENCODE(0x00) |
+		DDR0_01_INT_MASK_ENCODE(0xFF));
+
+	program_ddr0_03(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq,
+			rows, &cas_latency);
+
+	program_ddr0_04(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq);
+
+	program_ddr0_05(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq);
+
+	program_ddr0_06(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq);
+
+	/*
+	 * TODO: tFAW not found in SPD.  Value of 13 taken from Sequoia
+	 * board SDRAM, but may be overly conservative.
+	 */
+	mtsdram(DDR0_07, DDR0_07_NO_CMD_INIT_ENCODE(0) |
+		DDR0_07_TFAW_ENCODE(13) |
+		DDR0_07_AUTO_REFRESH_MODE_ENCODE(1) |
+		DDR0_07_AREFRESH_ENCODE(0));
+
+	mtsdram(DDR0_08, DDR0_08_WRLAT_ENCODE(cas_latency - 1) |
+		DDR0_08_TCPD_ENCODE(200) | DDR0_08_DQS_N_EN_ENCODE(0) |
+		DDR0_08_DDRII_ENCODE(1));
+
+	mtsdram(DDR0_09, DDR0_09_OCD_ADJUST_PDN_CS_0_ENCODE(0x00) |
+		DDR0_09_RTT_0_ENCODE(0x1) |
+		DDR0_09_WR_DQS_SHIFT_BYPASS_ENCODE(0x1D) |
+		DDR0_09_WR_DQS_SHIFT_ENCODE(DQS_OUT_SHIFT - 0x20));
+
+	program_ddr0_10(dimm_ranks, ranks);
+
+	program_ddr0_11(sdram_freq);
+
+	mtsdram(DDR0_12, DDR0_12_TCKE_ENCODE(3));
+
+	mtsdram(DDR0_14, DDR0_14_DLL_BYPASS_MODE_ENCODE(0) |
+		DDR0_14_REDUC_ENCODE(width <= 40 ? 1 : 0) |
+		DDR0_14_REG_DIMM_ENABLE_ENCODE(0));
+
+	mtsdram(DDR0_17, DDR0_17_DLL_DQS_DELAY_0_ENCODE(DLL_DQS_DELAY));
+
+	mtsdram(DDR0_18, DDR0_18_DLL_DQS_DELAY_4_ENCODE(DLL_DQS_DELAY) |
+		DDR0_18_DLL_DQS_DELAY_3_ENCODE(DLL_DQS_DELAY) |
+		DDR0_18_DLL_DQS_DELAY_2_ENCODE(DLL_DQS_DELAY) |
+		DDR0_18_DLL_DQS_DELAY_1_ENCODE(DLL_DQS_DELAY));
+
+	mtsdram(DDR0_19, DDR0_19_DLL_DQS_DELAY_8_ENCODE(DLL_DQS_DELAY) |
+		DDR0_19_DLL_DQS_DELAY_7_ENCODE(DLL_DQS_DELAY) |
+		DDR0_19_DLL_DQS_DELAY_6_ENCODE(DLL_DQS_DELAY) |
+		DDR0_19_DLL_DQS_DELAY_5_ENCODE(DLL_DQS_DELAY));
+
+	mtsdram(DDR0_20, DDR0_20_DLL_DQS_BYPASS_3_ENCODE(DLL_DQS_BYPASS) |
+		DDR0_20_DLL_DQS_BYPASS_2_ENCODE(DLL_DQS_BYPASS) |
+		DDR0_20_DLL_DQS_BYPASS_1_ENCODE(DLL_DQS_BYPASS) |
+		DDR0_20_DLL_DQS_BYPASS_0_ENCODE(DLL_DQS_BYPASS));
+
+	mtsdram(DDR0_21, DDR0_21_DLL_DQS_BYPASS_7_ENCODE(DLL_DQS_BYPASS) |
+		DDR0_21_DLL_DQS_BYPASS_6_ENCODE(DLL_DQS_BYPASS) |
+		DDR0_21_DLL_DQS_BYPASS_5_ENCODE(DLL_DQS_BYPASS) |
+		DDR0_21_DLL_DQS_BYPASS_4_ENCODE(DLL_DQS_BYPASS));
+
+	program_ddr0_22(dimm_ranks, iic0_dimm_addr, num_dimm_banks, width);
+
+	mtsdram(DDR0_23, DDR0_23_ODT_RD_MAP_CS0_ENCODE(0x0) |
+		DDR0_23_FWC_ENCODE(0));
+
+	program_ddr0_24(ranks);
+
+	program_ddr0_26(sdram_freq);
+
+	program_ddr0_27(sdram_freq);
+
+	mtsdram(DDR0_28, DDR0_28_EMRS3_DATA_ENCODE(0x0000) |
+		DDR0_28_EMRS2_DATA_ENCODE(0x0000));
+
+	mtsdram(DDR0_31, DDR0_31_XOR_CHECK_BITS_ENCODE(0x0000));
+
+	mtsdram(DDR0_42, DDR0_42_ADDR_PINS_ENCODE(14 - rows) |
+		DDR0_42_CASLAT_LIN_GATE_ENCODE(2 * cas_latency));
+
+	program_ddr0_43(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq,
+			cols, banks);
+
+	program_ddr0_44(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq);
+
+	denali_sdram_register_dump();
+
+	dram_size = (width >= 64) ? 8 : 4;
+	dram_size *= 1 << cols;
+	dram_size *= banks;
+	dram_size *= 1 << rows;
+	dram_size *= ranks;
+	debug("dram_size = %lu\n", dram_size);
+
+	/* Start the SDRAM controler */
+	mtsdram(DDR0_02, DDR0_02_START_ENCODE(1));
+	denali_wait_for_dlllock();
+
+#if defined(CONFIG_DDR_DATA_EYE)
+	/*
+	 * Map the first 1 MiB of memory in the TLB, and perform the data eye
+	 * search.
+	 */
+	program_tlb(0, CONFIG_SYS_SDRAM_BASE, TLB_1MB_SIZE, TLB_WORD2_I_ENABLE);
+	denali_core_search_data_eye();
+	denali_sdram_register_dump();
+	remove_tlb(CONFIG_SYS_SDRAM_BASE, TLB_1MB_SIZE);
+#endif
+
+#if defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC)
+	program_tlb(0, CONFIG_SYS_SDRAM_BASE, dram_size, 0);
+	sync();
+	/* Zero the memory */
+	debug("Zeroing SDRAM...");
+#if defined(CONFIG_SYS_MEM_TOP_HIDE)
+	dcbz_area(CONFIG_SYS_SDRAM_BASE, dram_size - CONFIG_SYS_MEM_TOP_HIDE);
+#else
+#error Please define CONFIG_SYS_MEM_TOP_HIDE (see README) in your board config file
+#endif
+	/* Write modified dcache lines back to memory */
+	clean_dcache_range(CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_SDRAM_BASE + dram_size - CONFIG_SYS_MEM_TOP_HIDE);
+	debug("Completed\n");
+	sync();
+	remove_tlb(CONFIG_SYS_SDRAM_BASE, dram_size);
+
+#if defined(CONFIG_DDR_ECC)
+	/*
+	 * If ECC is enabled, clear and enable interrupts
+	 */
+	if (is_ecc_enabled()) {
+		u32 val;
+
+		sync();
+		/* Clear error status */
+		mfsdram(DDR0_00, val);
+		mtsdram(DDR0_00, val | DDR0_00_INT_ACK_ALL);
+		/* Set 'int_mask' parameter to functionnal value */
+		mfsdram(DDR0_01, val);
+		mtsdram(DDR0_01, (val & ~DDR0_01_INT_MASK_MASK) |
+			DDR0_01_INT_MASK_ALL_OFF);
+#if defined(CONFIG_DDR_DATA_EYE)
+		/*
+		 * Running denali_core_search_data_eye() when ECC is enabled
+		 * causes non-ECC machine checks.  This clears them.
+		 */
+		print_mcsr();
+		mtspr(SPRN_MCSR, mfspr(SPRN_MCSR));
+		print_mcsr();
+#endif
+		sync();
+	}
+#endif /* defined(CONFIG_DDR_ECC) */
+#endif /* defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC) */
+
+	program_tlb(0, CONFIG_SYS_SDRAM_BASE, dram_size, MY_TLB_WORD2_I_ENABLE);
+	return dram_size;
+}
+
+void board_add_ram_info(int use_default)
+{
+	u32 val;
+
+	printf(" (ECC");
+	if (!is_ecc_enabled()) {
+		printf(" not");
+	}
+	printf(" enabled, %ld MHz", (2 * get_bus_freq(0)) / 1000000);
+
+	mfsdram(DDR0_03, val);
+	printf(", CL%d)", DDR0_03_CASLAT_LIN_DECODE(val) >> 1);
+}
+#endif /* CONFIG_SPD_EEPROM */
diff --git a/arch/powerpc/cpu/ppc4xx/ecc.c b/arch/powerpc/cpu/ppc4xx/ecc.c
new file mode 100644
index 0000000..f105605
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/ecc.c
@@ -0,0 +1,185 @@
+/*
+ *    Copyright (c) 2008 Nuovation System Designs, LLC
+ *      Grant Erickson <gerickson@nuovations.com>
+ *
+ *    (C) Copyright 2005-2009
+ *    Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ *    (C) Copyright 2002
+ *    Jun Gu, Artesyn Technology, jung@artesyncp.com
+ *
+ *    (C) Copyright 2001
+ *    Bill Hunter, Wave 7 Optics, williamhunter@attbi.com
+ *
+ *    See file CREDITS for list of people who contributed to this
+ *    project.
+ *
+ *    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 program is distributed in the hope that it will abe useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *    GNU General Public License for more details.
+ *
+ *    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., 59 Temple Place, Suite 330, Boston,
+ *    MA 02111-1307 USA
+ *
+ *    Description:
+ *	This file implements generic DRAM ECC initialization for
+ *	PowerPC processors using a SDRAM DDR/DDR2 controller,
+ *	including the 405EX(r), 440GP/GX/EP/GR, 440SP(E), and
+ *	460EX/GT.
+ */
+
+#include <common.h>
+#include <ppc4xx.h>
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/cache.h>
+
+#include "ecc.h"
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR) || \
+    defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
+#if defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC)
+
+#if defined(CONFIG_405EX)
+/*
+ * Currently only 405EX uses 16bit data bus width as an alternative
+ * option to 32bit data width (SDRAM0_MCOPT1_WDTH)
+ */
+#define SDRAM_DATA_ALT_WIDTH	2
+#else
+#define SDRAM_DATA_ALT_WIDTH	8
+#endif
+
+static void wait_ddr_idle(void)
+{
+	u32 val;
+
+	do {
+		mfsdram(SDRAM_MCSTAT, val);
+	} while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT);
+}
+
+static void program_ecc_addr(unsigned long start_address,
+			     unsigned long num_bytes,
+			     unsigned long tlb_word2_i_value)
+{
+	unsigned long current_address;
+	unsigned long end_address;
+	unsigned long address_increment;
+	unsigned long mcopt1;
+	char str[] = "ECC generation -";
+	char slash[] = "\\|/-\\|/-";
+	int loop = 0;
+	int loopi = 0;
+
+	current_address = start_address;
+	mfsdram(SDRAM_MCOPT1, mcopt1);
+	if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) {
+		mtsdram(SDRAM_MCOPT1,
+			(mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_GEN);
+		sync();
+		eieio();
+		wait_ddr_idle();
+
+		puts(str);
+
+#ifdef CONFIG_440
+		if (tlb_word2_i_value == TLB_WORD2_I_ENABLE) {
+#endif
+			/* ECC bit set method for non-cached memory */
+			if ((mcopt1 & SDRAM_MCOPT1_DMWD_MASK) == SDRAM_MCOPT1_DMWD_32)
+				address_increment = 4;
+			else
+				address_increment = SDRAM_DATA_ALT_WIDTH;
+			end_address = current_address + num_bytes;
+
+			while (current_address < end_address) {
+				*((unsigned long *)current_address) = 0;
+				current_address += address_increment;
+
+				if ((loop++ % (2 << 20)) == 0) {
+					putc('\b');
+					putc(slash[loopi++ % 8]);
+				}
+			}
+#ifdef CONFIG_440
+		} else {
+			/* ECC bit set method for cached memory */
+			dcbz_area(start_address, num_bytes);
+			/* Write modified dcache lines back to memory */
+			clean_dcache_range(start_address, start_address + num_bytes);
+		}
+#endif /* CONFIG_440 */
+
+		blank_string(strlen(str));
+
+		sync();
+		eieio();
+		wait_ddr_idle();
+
+		/* clear ECC error repoting registers */
+		mtsdram(SDRAM_ECCES, 0xffffffff);
+		mtdcr(0x4c, 0xffffffff);
+
+		mtsdram(SDRAM_MCOPT1,
+			(mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_CHK_REP);
+		sync();
+		eieio();
+		wait_ddr_idle();
+	}
+}
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)
+void ecc_init(unsigned long * const start, unsigned long size)
+{
+	/*
+	 * Init ECC with cache disabled (on PPC's with IBM DDR
+	 * controller (non DDR2), not tested with cache enabled yet
+	 */
+	program_ecc_addr((u32)start, size, TLB_WORD2_I_ENABLE);
+}
+#endif
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
+void do_program_ecc(unsigned long tlb_word2_i_value)
+{
+	unsigned long mcopt1;
+	unsigned long mcopt2;
+	unsigned long mcstat;
+	phys_size_t memsize = sdram_memsize();
+
+	if (memsize > CONFIG_MAX_MEM_MAPPED) {
+		printf("\nWarning: Can't enable ECC on systems with more than 2GB of SDRAM!\n");
+		return;
+	}
+
+	mfsdram(SDRAM_MCOPT1, mcopt1);
+	mfsdram(SDRAM_MCOPT2, mcopt2);
+
+	if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) {
+		/* DDR controller must be enabled and not in self-refresh. */
+		mfsdram(SDRAM_MCSTAT, mcstat);
+		if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE)
+		    && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT)
+		    && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK))
+			== (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) {
+
+			program_ecc_addr(0, memsize, tlb_word2_i_value);
+		}
+	}
+}
+#endif
+
+#endif /* defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC) */
+#endif /* defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)... */
diff --git a/arch/powerpc/cpu/ppc4xx/ecc.h b/arch/powerpc/cpu/ppc4xx/ecc.h
new file mode 100644
index 0000000..b258891
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/ecc.h
@@ -0,0 +1,75 @@
+/*
+ *    Copyright (c) 2008 Nuovation System Designs, LLC
+ *	Grant Erickson <gerickson@nuovations.com>
+ *
+ *    Copyright (c) 2007-2009 DENX Software Engineering, GmbH
+ *	Stefan Roese <sr@denx.de>
+ *
+ *    See file CREDITS for list of people who contributed to this
+ *    project.
+ *
+ *    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 program is distributed in the hope that it will abe useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *    GNU General Public License for more details.
+ *
+ *    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., 59 Temple Place, Suite 330, Boston,
+ *    MA 02111-1307 USA
+ *
+ *    Description:
+ *	This file implements ECC initialization for PowerPC processors
+ *	using the IBM SDRAM DDR1 & DDR2 controller.
+ *
+ */
+
+#ifndef _ECC_H_
+#define _ECC_H_
+
+/*
+ * Since the IBM DDR controller used on 440GP/GX/EP/GR is not register
+ * compatible to the IBM DDR/2 controller used on 405EX/440SP/SPe/460EX/GT
+ * we need to make some processor dependant defines used later on by the
+ * driver.
+ */
+
+/* For 440GP/GX/EP/GR */
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)
+#define SDRAM_MCOPT1		SDRAM_CFG0
+#define SDRAM_MCOPT1_MCHK_MASK	SDRAM_CFG0_MCHK_MASK
+#define SDRAM_MCOPT1_MCHK_NON	SDRAM_CFG0_MCHK_NON
+#define SDRAM_MCOPT1_MCHK_GEN	SDRAM_CFG0_MCHK_GEN
+#define SDRAM_MCOPT1_MCHK_CHK	SDRAM_CFG0_MCHK_CHK
+#define SDRAM_MCOPT1_MCHK_CHK_REP SDRAM_CFG0_MCHK_CHK
+#define SDRAM_MCOPT1_DMWD_MASK	SDRAM_CFG0_DMWD_MASK
+#define SDRAM_MCOPT1_DMWD_32	SDRAM_CFG0_DMWD_32
+
+#define SDRAM_MCSTAT		SDRAM0_MCSTS
+#define SDRAM_MCSTAT_IDLE_MASK	SDRAM_MCSTS_CIS
+#define SDRAM_MCSTAT_IDLE_NOT	SDRAM_MCSTS_IDLE_NOT
+
+#define SDRAM_ECCES		SDRAM0_ECCESR
+#endif
+
+void ecc_init(unsigned long * const start, unsigned long size);
+void do_program_ecc(unsigned long tlb_word2_i_value);
+
+static void inline blank_string(int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		putc('\b');
+	for (i = 0; i < size; i++)
+		putc(' ');
+	for (i = 0; i < size; i++)
+		putc('\b');
+}
+
+#endif /* _ECC_H_ */
diff --git a/arch/powerpc/cpu/ppc4xx/fdt.c b/arch/powerpc/cpu/ppc4xx/fdt.c
new file mode 100644
index 0000000..15a184b
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/fdt.c
@@ -0,0 +1,177 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/cache.h>
+#include <ppc4xx.h>
+
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
+#include <libfdt.h>
+#include <libfdt_env.h>
+#include <fdt_support.h>
+#include <asm/4xx_pcie.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void __ft_board_setup(void *blob, bd_t *bd)
+{
+	int rc;
+	int i;
+	u32 bxcr;
+	u32 ranges[EBC_NUM_BANKS * 4];
+	u32 *p = ranges;
+	char ebc_path[] = "/plb/opb/ebc";
+
+	ft_cpu_setup(blob, bd);
+
+	/*
+	 * Read 4xx EBC bus bridge registers to get mappings of the
+	 * peripheral banks into the OPB/PLB address space
+	 */
+	for (i = 0; i < EBC_NUM_BANKS; i++) {
+		mtdcr(EBC0_CFGADDR, EBC_BXCR(i));
+		bxcr = mfdcr(EBC0_CFGDATA);
+
+		if ((bxcr & EBC_BXCR_BU_MASK) != EBC_BXCR_BU_NONE) {
+			*p++ = i;
+			*p++ = 0;
+			*p++ = bxcr & EBC_BXCR_BAS_MASK;
+			*p++ = EBC_BXCR_BANK_SIZE(bxcr);
+
+#ifdef CONFIG_FDT_FIXUP_NOR_FLASH_SIZE
+			/* Try to update reg property in nor flash node too */
+			fdt_fixup_nor_flash_size(blob, i,
+						 EBC_BXCR_BANK_SIZE(bxcr));
+#endif
+		}
+	}
+
+	/* Some 405 PPC's have EBC as direct PLB child in the dts */
+	if (fdt_path_offset(blob, ebc_path) < 0)
+		strcpy(ebc_path, "/plb/ebc");
+	rc = fdt_find_and_setprop(blob, ebc_path, "ranges", ranges,
+				  (p - ranges) * sizeof(u32), 1);
+	if (rc) {
+		printf("Unable to update property EBC mappings, err=%s\n",
+		       fdt_strerror(rc));
+	}
+}
+void ft_board_setup(void *blob, bd_t *bd) __attribute__((weak, alias("__ft_board_setup")));
+
+/*
+ * Fixup all PCIe nodes by setting the device_type property
+ * to "pci-endpoint" instead is "pci" for endpoint ports.
+ * This property will get checked later by the Linux driver
+ * to properly configure the PCIe port in Linux (again).
+ */
+void fdt_pcie_setup(void *blob)
+{
+	const char *compat = "ibm,plb-pciex";
+	const char *prop = "device_type";
+	const char *prop_val = "pci-endpoint";
+	const u32 *port;
+	int no;
+	int rc;
+
+	/* Search first PCIe node */
+	no = fdt_node_offset_by_compatible(blob, -1, compat);
+	while (no != -FDT_ERR_NOTFOUND) {
+		port = fdt_getprop(blob, no, "port", NULL);
+		if (port == NULL) {
+			printf("WARNING: could not find port property\n");
+		} else {
+			if (is_end_point(*port)) {
+				rc = fdt_setprop(blob, no, prop, prop_val,
+						 strlen(prop_val) + 1);
+				if (rc < 0)
+					printf("WARNING: could not set %s for %s: %s.\n",
+					       prop, compat, fdt_strerror(rc));
+			}
+		}
+
+		/* Jump to next PCIe node */
+		no = fdt_node_offset_by_compatible(blob, no, compat);
+	}
+}
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+	sys_info_t sys_info;
+	int off, ndepth = 0;
+
+	get_sys_info(&sys_info);
+
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, "timebase-frequency",
+			     bd->bi_intfreq, 1);
+	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, "clock-frequency",
+			     bd->bi_intfreq, 1);
+	do_fixup_by_path_u32(blob, "/plb", "clock-frequency", sys_info.freqPLB, 1);
+	do_fixup_by_path_u32(blob, "/plb/opb", "clock-frequency", sys_info.freqOPB, 1);
+
+	if (fdt_path_offset(blob, "/plb/opb/ebc") >= 0)
+		do_fixup_by_path_u32(blob, "/plb/opb/ebc", "clock-frequency",
+			sys_info.freqEBC, 1);
+	else
+		do_fixup_by_path_u32(blob, "/plb/ebc", "clock-frequency",
+			sys_info.freqEBC, 1);
+
+	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+
+	/*
+	 * Fixup all UART clocks for CPU internal UARTs
+	 * (only these UARTs are definitely clocked by gd->uart_clk)
+	 *
+	 * These UARTs are direct childs of /plb/opb. This code
+	 * does not touch any UARTs that are connected to the ebc.
+	 */
+	off = fdt_path_offset(blob, "/plb/opb");
+	while ((off = fdt_next_node(blob, off, &ndepth)) >= 0) {
+		/*
+		 * process all sub nodes and stop when we are back
+		 * at the starting depth
+		 */
+		if (ndepth <= 0)
+			break;
+
+		/* only update direct childs */
+		if ((ndepth == 1) &&
+		    (fdt_node_check_compatible(blob, off, "ns16550") == 0))
+			fdt_setprop(blob, off,
+				    "clock-frequency",
+				    (void*)&(gd->uart_clk), 4);
+	}
+
+	/*
+	 * Fixup all ethernet nodes
+	 * Note: aliases in the dts are required for this
+	 */
+	fdt_fixup_ethernet(blob);
+
+	/*
+	 * Fixup all available PCIe nodes by setting the device_type property
+	 */
+	fdt_pcie_setup(blob);
+}
+#endif /* CONFIG_OF_LIBFDT && CONFIG_OF_BOARD_SETUP */
diff --git a/arch/powerpc/cpu/ppc4xx/gpio.c b/arch/powerpc/cpu/ppc4xx/gpio.c
new file mode 100644
index 0000000..c0d351a
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/gpio.c
@@ -0,0 +1,255 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+#if defined(CONFIG_SYS_4xx_GPIO_TABLE)
+gpio_param_s const gpio_tab[GPIO_GROUP_MAX][GPIO_MAX] = CONFIG_SYS_4xx_GPIO_TABLE;
+#endif
+
+#if defined(GPIO0_OSRL)
+/* Only some 4xx variants support alternate funtions on the GPIO's */
+void gpio_config(int pin, int in_out, int gpio_alt, int out_val)
+{
+	u32 mask;
+	u32 mask2;
+	u32 val;
+	u32 offs = 0;
+	u32 offs2 = 0;
+	int pin2 = pin << 1;
+
+	if (pin >= GPIO_MAX) {
+		offs = 0x100;
+		pin -= GPIO_MAX;
+	}
+
+	if (pin >= GPIO_MAX/2) {
+		offs2 = 0x4;
+		pin2 = (pin - GPIO_MAX/2) << 1;
+	}
+
+	mask = 0x80000000 >> pin;
+	mask2 = 0xc0000000 >> pin2;
+
+	/* first set TCR to 0 */
+	out_be32((void *)GPIO0_TCR + offs, in_be32((void *)GPIO0_TCR + offs) & ~mask);
+
+	if (in_out == GPIO_OUT) {
+		val = in_be32((void *)GPIO0_OSRL + offs + offs2) & ~mask2;
+		switch (gpio_alt) {
+		case GPIO_ALT1:
+			val |= GPIO_ALT1_SEL >> pin2;
+			break;
+		case GPIO_ALT2:
+			val |= GPIO_ALT2_SEL >> pin2;
+			break;
+		case GPIO_ALT3:
+			val |= GPIO_ALT3_SEL >> pin2;
+			break;
+		}
+		out_be32((void *)GPIO0_OSRL + offs + offs2, val);
+
+		/* setup requested output value */
+		if (out_val == GPIO_OUT_0)
+			out_be32((void *)GPIO0_OR + offs,
+				 in_be32((void *)GPIO0_OR + offs) & ~mask);
+		else if (out_val == GPIO_OUT_1)
+			out_be32((void *)GPIO0_OR + offs,
+				 in_be32((void *)GPIO0_OR + offs) | mask);
+
+		/* now configure TCR to drive output if selected */
+		out_be32((void *)GPIO0_TCR + offs,
+			 in_be32((void *)GPIO0_TCR + offs) | mask);
+	} else {
+		val = in_be32((void *)GPIO0_ISR1L + offs + offs2) & ~mask2;
+		val |= GPIO_IN_SEL >> pin2;
+		out_be32((void *)GPIO0_ISR1L + offs + offs2, val);
+	}
+}
+#endif /* GPIO_OSRL */
+
+void gpio_write_bit(int pin, int val)
+{
+	u32 offs = 0;
+
+	if (pin >= GPIO_MAX) {
+		offs = 0x100;
+		pin -= GPIO_MAX;
+	}
+
+	if (val)
+		out_be32((void *)GPIO0_OR + offs,
+			 in_be32((void *)GPIO0_OR + offs) | GPIO_VAL(pin));
+	else
+		out_be32((void *)GPIO0_OR + offs,
+			 in_be32((void *)GPIO0_OR + offs) & ~GPIO_VAL(pin));
+}
+
+int gpio_read_out_bit(int pin)
+{
+	u32 offs = 0;
+
+	if (pin >= GPIO_MAX) {
+		offs = 0x100;
+		pin -= GPIO_MAX;
+	}
+
+	return (in_be32((void *)GPIO0_OR + offs) & GPIO_VAL(pin) ? 1 : 0);
+}
+
+int gpio_read_in_bit(int pin)
+{
+	u32 offs = 0;
+
+	if (pin >= GPIO_MAX) {
+		offs = 0x100;
+		pin -= GPIO_MAX;
+	}
+
+	return (in_be32((void *)GPIO0_IR + offs) & GPIO_VAL(pin) ? 1 : 0);
+}
+
+#if defined(CONFIG_SYS_4xx_GPIO_TABLE)
+void gpio_set_chip_configuration(void)
+{
+	unsigned char i=0, j=0, offs=0, gpio_core;
+	unsigned long reg, core_add;
+
+	for (gpio_core=0; gpio_core<GPIO_GROUP_MAX; gpio_core++) {
+		j = 0;
+		offs = 0;
+		/* GPIO config of the GPIOs 0 to 31 */
+		for (i=0; i<GPIO_MAX; i++, j++) {
+			if (i == GPIO_MAX/2) {
+				offs = 4;
+				j = i-16;
+			}
+
+			core_add = gpio_tab[gpio_core][i].add;
+
+			if ((gpio_tab[gpio_core][i].in_out == GPIO_IN) ||
+			    (gpio_tab[gpio_core][i].in_out == GPIO_BI)) {
+
+				switch (gpio_tab[gpio_core][i].alt_nb) {
+				case GPIO_SEL:
+					break;
+
+				case GPIO_ALT1:
+					reg = in_be32((void *)GPIO_IS1(core_add+offs))
+						& ~(GPIO_MASK >> (j*2));
+					reg = reg | (GPIO_IN_SEL >> (j*2));
+					out_be32((void *)GPIO_IS1(core_add+offs), reg);
+					break;
+
+				case GPIO_ALT2:
+					reg = in_be32((void *)GPIO_IS2(core_add+offs))
+						& ~(GPIO_MASK >> (j*2));
+					reg = reg | (GPIO_IN_SEL >> (j*2));
+					out_be32((void *)GPIO_IS2(core_add+offs), reg);
+					break;
+
+				case GPIO_ALT3:
+					reg = in_be32((void *)GPIO_IS3(core_add+offs))
+						& ~(GPIO_MASK >> (j*2));
+					reg = reg | (GPIO_IN_SEL >> (j*2));
+					out_be32((void *)GPIO_IS3(core_add+offs), reg);
+					break;
+				}
+			}
+
+			if ((gpio_tab[gpio_core][i].in_out == GPIO_OUT) ||
+			    (gpio_tab[gpio_core][i].in_out == GPIO_BI)) {
+
+				u32 gpio_alt_sel = 0;
+
+				switch (gpio_tab[gpio_core][i].alt_nb) {
+				case GPIO_SEL:
+					/*
+					 * Setup output value
+					 * 1 -> high level
+					 * 0 -> low level
+					 * else -> don't touch
+					 */
+					reg = in_be32((void *)GPIO_OR(core_add));
+					if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1)
+						reg |= (0x80000000 >> (i));
+					else if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_0)
+						reg &= ~(0x80000000 >> (i));
+					out_be32((void *)GPIO_OR(core_add), reg);
+
+					reg = in_be32((void *)GPIO_TCR(core_add)) |
+						(0x80000000 >> (i));
+					out_be32((void *)GPIO_TCR(core_add), reg);
+
+					reg = in_be32((void *)GPIO_OS(core_add+offs))
+						& ~(GPIO_MASK >> (j*2));
+					out_be32((void *)GPIO_OS(core_add+offs), reg);
+					reg = in_be32((void *)GPIO_TS(core_add+offs))
+						& ~(GPIO_MASK >> (j*2));
+					out_be32((void *)GPIO_TS(core_add+offs), reg);
+					break;
+
+				case GPIO_ALT1:
+					gpio_alt_sel = GPIO_ALT1_SEL;
+					break;
+
+				case GPIO_ALT2:
+					gpio_alt_sel = GPIO_ALT2_SEL;
+					break;
+
+				case GPIO_ALT3:
+					gpio_alt_sel = GPIO_ALT3_SEL;
+					break;
+				}
+
+				if (0 != gpio_alt_sel) {
+					reg = in_be32((void *)GPIO_OS(core_add+offs))
+						& ~(GPIO_MASK >> (j*2));
+					reg = reg | (gpio_alt_sel >> (j*2));
+					out_be32((void *)GPIO_OS(core_add+offs), reg);
+
+					if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1) {
+						reg = in_be32((void *)GPIO_TCR(core_add))
+							| (0x80000000 >> (i));
+						out_be32((void *)GPIO_TCR(core_add), reg);
+						reg = in_be32((void *)GPIO_TS(core_add+offs))
+							& ~(GPIO_MASK >> (j*2));
+						out_be32((void *)GPIO_TS(core_add+offs), reg);
+					} else {
+						reg = in_be32((void *)GPIO_TCR(core_add))
+							& ~(0x80000000 >> (i));
+						out_be32((void *)GPIO_TCR(core_add), reg);
+						reg = in_be32((void *)GPIO_TS(core_add+offs))
+							& ~(GPIO_MASK >> (j*2));
+						reg = reg | (gpio_alt_sel >> (j*2));
+						out_be32((void *)GPIO_TS(core_add+offs), reg);
+					}
+				}
+			}
+		}
+	}
+}
+#endif /* CONFIG_SYS_4xx_GPIO_TABLE */
diff --git a/arch/powerpc/cpu/ppc4xx/interrupts.c b/arch/powerpc/cpu/ppc4xx/interrupts.c
new file mode 100644
index 0000000..6db8421
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/interrupts.c
@@ -0,0 +1,216 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002 (440 port)
+ * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com
+ *
+ * (C) Copyright 2003 (440GX port)
+ * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com
+ *
+ * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX)
+ * Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * Work supported by Qtechnology (htpp://qtec.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/interrupt.h>
+#include <ppc4xx.h>
+#include <ppc_asm.tmpl>
+#include <commproc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * CPM interrupt vector functions.
+ */
+struct	irq_action {
+	interrupt_handler_t *handler;
+	void *arg;
+	int count;
+};
+static struct irq_action irq_vecs[IRQ_MAX];
+
+#if defined(CONFIG_440)
+
+/* SPRN changed in 440 */
+static __inline__ void set_evpr(unsigned long val)
+{
+	asm volatile("mtspr 0x03f,%0" : : "r" (val));
+}
+
+#else /* !defined(CONFIG_440) */
+
+static __inline__ void set_pit(unsigned long val)
+{
+	asm volatile("mtpit %0" : : "r" (val));
+}
+
+
+static __inline__ void set_tcr(unsigned long val)
+{
+	asm volatile("mttcr %0" : : "r" (val));
+}
+
+
+static __inline__ void set_evpr(unsigned long val)
+{
+	asm volatile("mtevpr %0" : : "r" (val));
+}
+#endif /* defined(CONFIG_440 */
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+	int vec;
+	unsigned long val;
+
+	/* decrementer is automatically reloaded */
+	*decrementer_count = 0;
+
+	/*
+	 * Mark all irqs as free
+	 */
+	for (vec = 0; vec < IRQ_MAX; vec++) {
+		irq_vecs[vec].handler = NULL;
+		irq_vecs[vec].arg = NULL;
+		irq_vecs[vec].count = 0;
+	}
+
+#ifdef CONFIG_4xx
+	/*
+	 * Init PIT
+	 */
+#if defined(CONFIG_440)
+	val = mfspr( SPRN_TCR );
+	val &= (~0x04400000);		/* clear DIS & ARE */
+	mtspr( SPRN_TCR, val );
+	mtspr( SPRN_DEC, 0 );		/* Prevent exception after TSR clear*/
+	mtspr( SPRN_DECAR, 0 );		/* clear reload */
+	mtspr( SPRN_TSR, 0x08000000 );	/* clear DEC status */
+	val = gd->bd->bi_intfreq/1000;	/* 1 msec */
+	mtspr( SPRN_DECAR, val );		/* Set auto-reload value */
+	mtspr( SPRN_DEC, val );		/* Set inital val */
+#else
+	set_pit(gd->bd->bi_intfreq / 1000);
+#endif
+#endif  /* CONFIG_4xx */
+
+#ifdef CONFIG_ADCIOP
+	/*
+	 * Init PIT
+	 */
+	set_pit(66000);
+#endif
+
+	/*
+	 * Enable PIT
+	 */
+	val = mfspr(SPRN_TCR);
+	val |= 0x04400000;
+	mtspr(SPRN_TCR, val);
+
+	/*
+	 * Set EVPR to 0
+	 */
+	set_evpr(0x00000000);
+
+	/*
+	 * Call uic or xilinx_irq pic_enable
+	 */
+	pic_enable();
+
+	return (0);
+}
+
+void timer_interrupt_cpu(struct pt_regs *regs)
+{
+	/* nothing to do here */
+	return;
+}
+
+void interrupt_run_handler(int vec)
+{
+	irq_vecs[vec].count++;
+
+	if (irq_vecs[vec].handler != NULL) {
+		/* call isr */
+		(*irq_vecs[vec].handler) (irq_vecs[vec].arg);
+	} else {
+		pic_irq_disable(vec);
+		printf("Masking bogus interrupt vector %d\n", vec);
+	}
+
+	pic_irq_ack(vec);
+	return;
+}
+
+void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
+{
+	/*
+	 * Print warning when replacing with a different irq vector
+	 */
+	if ((irq_vecs[vec].handler != NULL) && (irq_vecs[vec].handler != handler)) {
+		printf("Interrupt vector %d: handler 0x%x replacing 0x%x\n",
+		       vec, (uint) handler, (uint) irq_vecs[vec].handler);
+	}
+	irq_vecs[vec].handler = handler;
+	irq_vecs[vec].arg = arg;
+
+	pic_irq_enable(vec);
+	return;
+}
+
+void irq_free_handler(int vec)
+{
+	debug("Free interrupt for vector %d ==> %p\n",
+	      vec, irq_vecs[vec].handler);
+
+	pic_irq_disable(vec);
+
+	irq_vecs[vec].handler = NULL;
+	irq_vecs[vec].arg = NULL;
+	return;
+}
+
+#if defined(CONFIG_CMD_IRQ)
+int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	int vec;
+
+	printf ("Interrupt-Information:\n");
+	printf ("Nr  Routine   Arg       Count\n");
+
+	for (vec = 0; vec < IRQ_MAX; vec++) {
+		if (irq_vecs[vec].handler != NULL) {
+			printf ("%02d  %08lx  %08lx  %d\n",
+				vec,
+				(ulong)irq_vecs[vec].handler,
+				(ulong)irq_vecs[vec].arg,
+				irq_vecs[vec].count);
+		}
+	}
+
+	return 0;
+}
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/iop480_uart.c b/arch/powerpc/cpu/ppc4xx/iop480_uart.c
new file mode 100644
index 0000000..0e3423f
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/iop480_uart.c
@@ -0,0 +1,237 @@
+/*
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <commproc.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <watchdog.h>
+
+#ifdef CONFIG_SERIAL_MULTI
+#include <serial.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_IOP480
+
+#define SPU_BASE         0x40000000
+
+#define spu_LineStat_rc  0x00	/* Line Status Register (Read/Clear) */
+#define spu_LineStat_w   0x04	/* Line Status Register (Set) */
+#define spu_Handshk_rc   0x08	/* Handshake Status Register (Read/Clear) */
+#define spu_Handshk_w    0x0c	/* Handshake Status Register (Set) */
+#define spu_BRateDivh    0x10	/* Baud rate divisor high */
+#define spu_BRateDivl    0x14	/* Baud rate divisor low */
+#define spu_CtlReg       0x18	/* Control Register */
+#define spu_RxCmd        0x1c	/* Rx Command Register */
+#define spu_TxCmd        0x20	/* Tx Command Register */
+#define spu_RxBuff       0x24	/* Rx data buffer */
+#define spu_TxBuff       0x24	/* Tx data buffer */
+
+/*-----------------------------------------------------------------------------+
+  | Line Status Register.
+  +-----------------------------------------------------------------------------*/
+#define asyncLSRport1           0x40000000
+#define asyncLSRport1set        0x40000004
+#define asyncLSRDataReady             0x80
+#define asyncLSRFramingError          0x40
+#define asyncLSROverrunError          0x20
+#define asyncLSRParityError           0x10
+#define asyncLSRBreakInterrupt        0x08
+#define asyncLSRTxHoldEmpty           0x04
+#define asyncLSRTxShiftEmpty          0x02
+
+/*-----------------------------------------------------------------------------+
+  | Handshake Status Register.
+  +-----------------------------------------------------------------------------*/
+#define asyncHSRport1           0x40000008
+#define asyncHSRport1set        0x4000000c
+#define asyncHSRDsr                   0x80
+#define asyncLSRCts                   0x40
+
+/*-----------------------------------------------------------------------------+
+  | Control Register.
+  +-----------------------------------------------------------------------------*/
+#define asyncCRport1            0x40000018
+#define asyncCRNormal                 0x00
+#define asyncCRLoopback               0x40
+#define asyncCRAutoEcho               0x80
+#define asyncCRDtr                    0x20
+#define asyncCRRts                    0x10
+#define asyncCRWordLength7            0x00
+#define asyncCRWordLength8            0x08
+#define asyncCRParityDisable          0x00
+#define asyncCRParityEnable           0x04
+#define asyncCREvenParity             0x00
+#define asyncCROddParity              0x02
+#define asyncCRStopBitsOne            0x00
+#define asyncCRStopBitsTwo            0x01
+#define asyncCRDisableDtrRts          0x00
+
+/*-----------------------------------------------------------------------------+
+  | Receiver Command Register.
+  +-----------------------------------------------------------------------------*/
+#define asyncRCRport1           0x4000001c
+#define asyncRCRDisable               0x00
+#define asyncRCREnable                0x80
+#define asyncRCRIntDisable            0x00
+#define asyncRCRIntEnabled            0x20
+#define asyncRCRDMACh2                0x40
+#define asyncRCRDMACh3                0x60
+#define asyncRCRErrorInt              0x10
+#define asyncRCRPauseEnable           0x08
+
+/*-----------------------------------------------------------------------------+
+  | Transmitter Command Register.
+  +-----------------------------------------------------------------------------*/
+#define asyncTCRport1           0x40000020
+#define asyncTCRDisable               0x00
+#define asyncTCREnable                0x80
+#define asyncTCRIntDisable            0x00
+#define asyncTCRIntEnabled            0x20
+#define asyncTCRDMACh2                0x40
+#define asyncTCRDMACh3                0x60
+#define asyncTCRTxEmpty               0x10
+#define asyncTCRErrorInt              0x08
+#define asyncTCRStopPause             0x04
+#define asyncTCRBreakGen              0x02
+
+/*-----------------------------------------------------------------------------+
+  | Miscellanies defines.
+  +-----------------------------------------------------------------------------*/
+#define asyncTxBufferport1      0x40000024
+#define asyncRxBufferport1      0x40000024
+#define asyncDLABLsbport1       0x40000014
+#define asyncDLABMsbport1       0x40000010
+#define asyncXOFFchar                 0x13
+#define asyncXONchar                  0x11
+
+/*
+ * Minimal serial functions needed to use one of the SMC ports
+ * as serial console interface.
+ */
+
+int serial_init (void)
+{
+	volatile char val;
+	unsigned short br_reg;
+
+	br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1);
+
+	/*
+	 * Init onboard UART
+	 */
+	out_8((u8 *)SPU_BASE + spu_LineStat_rc, 0x78); /* Clear all bits in Line Status Reg */
+	out_8((u8 *)SPU_BASE + spu_BRateDivl, (br_reg & 0x00ff)); /* Set baud rate divisor... */
+	out_8((u8 *)SPU_BASE + spu_BRateDivh, ((br_reg & 0xff00) >> 8)); /* ... */
+	out_8((u8 *)SPU_BASE + spu_CtlReg, 0x08);	/* Set 8 bits, no parity and 1 stop bit */
+	out_8((u8 *)SPU_BASE + spu_RxCmd, 0xb0);	/* Enable Rx */
+	out_8((u8 *)SPU_BASE + spu_TxCmd, 0x9c);	/* Enable Tx */
+	out_8((u8 *)SPU_BASE + spu_Handshk_rc, 0xff);	/* Clear Handshake */
+	val = in_8((u8 *)SPU_BASE + spu_RxBuff);	/* Dummy read, to clear receiver */
+
+	return (0);
+}
+
+void serial_setbrg (void)
+{
+	unsigned short br_reg;
+
+	br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1);
+
+	out_8((u8 *)SPU_BASE + spu_BRateDivl,
+	      (br_reg & 0x00ff)); /* Set baud rate divisor... */
+	out_8((u8 *)SPU_BASE + spu_BRateDivh,
+	      ((br_reg & 0xff00) >> 8)); /* ... */
+}
+
+void serial_putc (const char c)
+{
+	if (c == '\n')
+		serial_putc ('\r');
+
+	/* load status from handshake register */
+	if (in_8((u8 *)SPU_BASE + spu_Handshk_rc) != 00)
+		out_8((u8 *)SPU_BASE + spu_Handshk_rc, 0xff);	/* Clear Handshake */
+
+	out_8((u8 *)SPU_BASE + spu_TxBuff, c);	/* Put char */
+
+	while ((in_8((u8 *)SPU_BASE + spu_LineStat_rc) & 04) != 04) {
+		if (in_8((u8 *)SPU_BASE + spu_Handshk_rc) != 00)
+			out_8((u8 *)SPU_BASE + spu_Handshk_rc, 0xff);	/* Clear Handshake */
+	}
+}
+
+void serial_puts (const char *s)
+{
+	while (*s) {
+		serial_putc (*s++);
+	}
+}
+
+int serial_getc ()
+{
+	unsigned char status = 0;
+
+	while (1) {
+		status = in_8((u8 *)asyncLSRport1);
+		if ((status & asyncLSRDataReady) != 0x0) {
+			break;
+		}
+		if ((status & ( asyncLSRFramingError |
+				asyncLSROverrunError |
+				asyncLSRParityError  |
+				asyncLSRBreakInterrupt )) != 0) {
+			(void) out_8((u8 *)asyncLSRport1,
+				     asyncLSRFramingError |
+				     asyncLSROverrunError |
+				     asyncLSRParityError  |
+				     asyncLSRBreakInterrupt );
+		}
+	}
+	return (0x000000ff & (int) in_8((u8 *)asyncRxBufferport1));
+}
+
+int serial_tstc ()
+{
+	unsigned char status;
+
+	status = in_8((u8 *)asyncLSRport1);
+	if ((status & asyncLSRDataReady) != 0x0) {
+		return (1);
+	}
+	if ((status & ( asyncLSRFramingError |
+			asyncLSROverrunError |
+			asyncLSRParityError  |
+			asyncLSRBreakInterrupt )) != 0) {
+		(void) out_8((u8 *)asyncLSRport1,
+			     asyncLSRFramingError |
+			     asyncLSROverrunError |
+			     asyncLSRParityError  |
+			     asyncLSRBreakInterrupt);
+	}
+	return 0;
+}
+
+#endif	/* CONFIG_IOP480 */
diff --git a/arch/powerpc/cpu/ppc4xx/kgdb.S b/arch/powerpc/cpu/ppc4xx/kgdb.S
new file mode 100644
index 0000000..4227a4c
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/kgdb.S
@@ -0,0 +1,78 @@
+/*
+ *  Copyright (C) 2000	Murray Jensen <Murray.Jensen@cmst.csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <command.h>
+#include <ppc4xx.h>
+#include <version.h>
+
+#define CONFIG_405GP 1		/* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1	/* avoid reading Linux autoconf.h file	*/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#if defined(CONFIG_CMD_KGDB)
+ /*
+ * cache flushing routines for kgdb
+ */
+
+	.globl	kgdb_flush_cache_all
+kgdb_flush_cache_all:
+	/* icache */
+	iccci   r0,r0		/* iccci invalidates the entire I cache */
+	/* dcache */
+	addi    r6,0,0x0000     /* clear GPR 6 */
+	addi    r7,r0, 128	/* do loop for # of dcache lines */
+				/* NOTE: dccci invalidates both */
+	mtctr   r7              /* ways in the D cache */
+..dcloop:
+	dccci   0,r6            /* invalidate line */
+	addi    r6,r6, 32	/* bump to next line */
+	bdnz    ..dcloop
+	blr
+
+	.globl	kgdb_flush_cache_range
+kgdb_flush_cache_range:
+	li	r5,L1_CACHE_BYTES-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,L1_CACHE_SHIFT
+	beqlr
+	mtctr	r4
+	mr	r6,r3
+1:	dcbst	0,r3
+	addi	r3,r3,L1_CACHE_BYTES
+	bdnz	1b
+	sync			/* wait for dcbst's to get to ram */
+	mtctr	r4
+2:	icbi	0,r6
+	addi	r6,r6,L1_CACHE_BYTES
+	bdnz	2b
+	SYNC
+	blr
+
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/miiphy.c b/arch/powerpc/cpu/ppc4xx/miiphy.c
new file mode 100644
index 0000000..22ed5c2
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/miiphy.c
@@ -0,0 +1,366 @@
+/*-----------------------------------------------------------------------------+
+  |   This source code is dual-licensed.  You may use it under the terms of the
+  |   GNU General Public License version 2, or under the license below.
+  |
+  |	  This source code has been made available to you by IBM on an AS-IS
+  |	  basis.  Anyone receiving this source is licensed under IBM
+  |	  copyrights to use it in any way he or she deems fit, including
+  |	  copying it, modifying it, compiling it, and redistributing it either
+  |	  with or without modifications.  No license under IBM patents or
+  |	  patent applications is to be implied by the copyright license.
+  |
+  |	  Any user of this software should understand that IBM cannot provide
+  |	  technical support for this software and will not be responsible for
+  |	  any consequences resulting from the use of this software.
+  |
+  |	  Any person who transfers this source code or any derivative work
+  |	  must include the IBM copyright notice, this paragraph, and the
+  |	  preceding two paragraphs in the transferred software.
+  |
+  |	  COPYRIGHT   I B M   CORPORATION 1995
+  |	  LICENSED MATERIAL  -	PROGRAM PROPERTY OF I B M
+  +-----------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------+
+  |
+  |  File Name:	 miiphy.c
+  |
+  |  Function:	 This module has utilities for accessing the MII PHY through
+  |	       the EMAC3 macro.
+  |
+  |  Author:	 Mark Wisner
+  |
+  +-----------------------------------------------------------------------------*/
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#if 0
+#define DEBUG
+#endif
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <ppc_asm.tmpl>
+#include <commproc.h>
+#include <ppc4xx_enet.h>
+#include <405_mal.h>
+#include <miiphy.h>
+
+#if !defined(CONFIG_PHY_CLK_FREQ)
+#define CONFIG_PHY_CLK_FREQ	0
+#endif
+
+/***********************************************************/
+/* Dump out to the screen PHY regs			   */
+/***********************************************************/
+
+void miiphy_dump (char *devname, unsigned char addr)
+{
+	unsigned long i;
+	unsigned short data;
+
+	for (i = 0; i < 0x1A; i++) {
+		if (miiphy_read (devname, addr, i, &data)) {
+			printf ("read error for reg %lx\n", i);
+			return;
+		}
+		printf ("Phy reg %lx ==> %4x\n", i, data);
+
+		/* jump to the next set of regs */
+		if (i == 0x07)
+			i = 0x0f;
+
+	}			/* end for loop */
+}				/* end dump */
+
+/***********************************************************/
+/* (Re)start autonegotiation				   */
+/***********************************************************/
+int phy_setup_aneg (char *devname, unsigned char addr)
+{
+	u16 bmcr;
+
+#if defined(CONFIG_PHY_DYNAMIC_ANEG)
+	/*
+	 * Set up advertisement based on capablilities reported by the PHY.
+	 * This should work for both copper and fiber.
+	 */
+	u16 bmsr;
+#if defined(CONFIG_PHY_GIGE)
+	u16 exsr = 0x0000;
+#endif
+
+	miiphy_read (devname, addr, PHY_BMSR, &bmsr);
+
+#if defined(CONFIG_PHY_GIGE)
+	if (bmsr & PHY_BMSR_EXT_STAT)
+		miiphy_read (devname, addr, PHY_EXSR, &exsr);
+
+	if (exsr & (PHY_EXSR_1000XF | PHY_EXSR_1000XH)) {
+		/* 1000BASE-X */
+		u16 anar = 0x0000;
+
+		if (exsr & PHY_EXSR_1000XF)
+			anar |= PHY_X_ANLPAR_FD;
+
+		if (exsr & PHY_EXSR_1000XH)
+			anar |= PHY_X_ANLPAR_HD;
+
+		miiphy_write (devname, addr, PHY_ANAR, anar);
+	} else
+#endif
+	{
+		u16 anar, btcr;
+
+		miiphy_read (devname, addr, PHY_ANAR, &anar);
+		anar &= ~(0x5000 | PHY_ANLPAR_T4 | PHY_ANLPAR_TXFD |
+			  PHY_ANLPAR_TX | PHY_ANLPAR_10FD | PHY_ANLPAR_10);
+
+		miiphy_read (devname, addr, PHY_1000BTCR, &btcr);
+		btcr &= ~(0x00FF | PHY_1000BTCR_1000FD | PHY_1000BTCR_1000HD);
+
+		if (bmsr & PHY_BMSR_100T4)
+			anar |= PHY_ANLPAR_T4;
+
+		if (bmsr & PHY_BMSR_100TXF)
+			anar |= PHY_ANLPAR_TXFD;
+
+		if (bmsr & PHY_BMSR_100TXH)
+			anar |= PHY_ANLPAR_TX;
+
+		if (bmsr & PHY_BMSR_10TF)
+			anar |= PHY_ANLPAR_10FD;
+
+		if (bmsr & PHY_BMSR_10TH)
+			anar |= PHY_ANLPAR_10;
+
+		miiphy_write (devname, addr, PHY_ANAR, anar);
+
+#if defined(CONFIG_PHY_GIGE)
+		if (exsr & PHY_EXSR_1000TF)
+			btcr |= PHY_1000BTCR_1000FD;
+
+		if (exsr & PHY_EXSR_1000TH)
+			btcr |= PHY_1000BTCR_1000HD;
+
+		miiphy_write (devname, addr, PHY_1000BTCR, btcr);
+#endif
+	}
+
+#else /* defined(CONFIG_PHY_DYNAMIC_ANEG) */
+	/*
+	 * Set up standard advertisement
+	 */
+	u16 adv;
+
+	miiphy_read (devname, addr, PHY_ANAR, &adv);
+	adv |= (PHY_ANLPAR_ACK  | PHY_ANLPAR_TXFD | PHY_ANLPAR_TX |
+		PHY_ANLPAR_10FD | PHY_ANLPAR_10);
+	miiphy_write (devname, addr, PHY_ANAR, adv);
+
+	miiphy_read (devname, addr, PHY_1000BTCR, &adv);
+	adv |= (0x0300);
+	miiphy_write (devname, addr, PHY_1000BTCR, adv);
+
+#endif /* defined(CONFIG_PHY_DYNAMIC_ANEG) */
+
+	/* Start/Restart aneg */
+	miiphy_read (devname, addr, PHY_BMCR, &bmcr);
+	bmcr |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
+	miiphy_write (devname, addr, PHY_BMCR, bmcr);
+
+	return 0;
+}
+
+/***********************************************************/
+/* read a phy reg and return the value with a rc	   */
+/***********************************************************/
+/* AMCC_TODO:
+ * Find out of the choice for the emac for MDIO is from the bridges,
+ * i.e. ZMII or RGMII as approporiate.  If the bridges are not used
+ * to determine the emac for MDIO, then is the SDR0_ETH_CFG[MDIO_SEL]
+ * used?  If so, then this routine below does not apply to the 460EX/GT.
+ *
+ * sr: Currently on 460EX only EMAC0 works with MDIO, so we always
+ * return EMAC0 offset here
+ * vg: For 460EX/460GT if internal GPCS PHY address is specified
+ * return appropriate EMAC offset
+ */
+unsigned int miiphy_getemac_offset(u8 addr)
+{
+#if (defined(CONFIG_440) && \
+    !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
+    !defined(CONFIG_460EX) && !defined(CONFIG_460GT)) && \
+    defined(CONFIG_NET_MULTI)
+	unsigned long zmii;
+	unsigned long eoffset;
+
+	/* Need to find out which mdi port we're using */
+	zmii = in_be32((void *)ZMII0_FER);
+
+	if (zmii & (ZMII_FER_MDI << ZMII_FER_V (0)))
+		/* using port 0 */
+		eoffset = 0;
+
+	else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (1)))
+		/* using port 1 */
+		eoffset = 0x100;
+
+	else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (2)))
+		/* using port 2 */
+		eoffset = 0x400;
+
+	else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (3)))
+		/* using port 3 */
+		eoffset = 0x600;
+
+	else {
+		/* None of the mdi ports are enabled! */
+		/* enable port 0 */
+		zmii |= ZMII_FER_MDI << ZMII_FER_V (0);
+		out_be32((void *)ZMII0_FER, zmii);
+		eoffset = 0;
+		/* need to soft reset port 0 */
+		zmii = in_be32((void *)EMAC0_MR0);
+		zmii |= EMAC_MR0_SRST;
+		out_be32((void *)EMAC0_MR0, zmii);
+	}
+
+	return (eoffset);
+#else
+
+#if defined(CONFIG_NET_MULTI) && defined(CONFIG_405EX)
+	unsigned long rgmii;
+	int devnum = 1;
+
+	rgmii = in_be32((void *)RGMII_FER);
+	if (rgmii & (1 << (19 - devnum)))
+		return 0x100;
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	u32 eoffset = 0;
+
+	switch (addr) {
+#if defined(CONFIG_HAS_ETH1) && defined(CONFIG_GPCS_PHY1_ADDR)
+	case CONFIG_GPCS_PHY1_ADDR:
+		if (addr == EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1 + 0x100)))
+			eoffset = 0x100;
+		break;
+#endif
+#if defined(CONFIG_HAS_ETH2) && defined(CONFIG_GPCS_PHY2_ADDR)
+	case CONFIG_GPCS_PHY2_ADDR:
+		if (addr == EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1 + 0x300)))
+			eoffset = 0x300;
+		break;
+#endif
+#if defined(CONFIG_HAS_ETH3) && defined(CONFIG_GPCS_PHY3_ADDR)
+	case CONFIG_GPCS_PHY3_ADDR:
+		if (addr == EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1 + 0x400)))
+			eoffset = 0x400;
+		break;
+#endif
+	default:
+		eoffset = 0;
+		break;
+	}
+	return eoffset;
+#endif
+
+	return 0;
+#endif
+}
+
+static int emac_miiphy_wait(u32 emac_reg)
+{
+	u32 sta_reg;
+	int i;
+
+	/* wait for completion */
+	i = 0;
+	do {
+		sta_reg = in_be32((void *)EMAC0_STACR + emac_reg);
+		if (i++ > 5) {
+			debug("%s [%d]: Timeout! EMAC0_STACR=0x%0x\n", __func__,
+			      __LINE__, sta_reg);
+			return -1;
+		}
+		udelay(10);
+	} while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK);
+
+	return 0;
+}
+
+static int emac_miiphy_command(u8 addr, u8 reg, int cmd, u16 value)
+{
+	u32 emac_reg;
+	u32 sta_reg;
+
+	emac_reg = miiphy_getemac_offset(addr);
+
+	/* wait for completion */
+	if (emac_miiphy_wait(emac_reg) != 0)
+		return -1;
+
+	sta_reg = reg;		/* reg address */
+
+	/* set clock (50MHz) and read flags */
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+    defined(CONFIG_405EX)
+#if defined(CONFIG_IBM_EMAC4_V4)	/* EMAC4 V4 changed bit setting */
+	sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | cmd;
+#else
+	sta_reg |= cmd;
+#endif
+#else
+	sta_reg = (sta_reg | cmd) & ~EMAC_STACR_CLK_100MHZ;
+#endif
+
+	/* Some boards (mainly 405EP based) define the PHY clock freqency fixed */
+	sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ;
+	sta_reg = sta_reg | ((u32)addr << 5);	/* Phy address */
+	sta_reg = sta_reg | EMAC_STACR_OC_MASK;	/* new IBM emac v4 */
+	if (cmd == EMAC_STACR_WRITE)
+		memcpy(&sta_reg, &value, 2);	/* put in data */
+
+	out_be32((void *)EMAC0_STACR + emac_reg, sta_reg);
+	debug("%s [%d]: sta_reg=%08x\n", __func__, __LINE__, sta_reg);
+
+	/* wait for completion */
+	if (emac_miiphy_wait(emac_reg) != 0)
+		return -1;
+
+	debug("%s [%d]: sta_reg=%08x\n", __func__, __LINE__, sta_reg);
+	if ((sta_reg & EMAC_STACR_PHYE) != 0)
+		return -1;
+
+	return 0;
+}
+
+int emac4xx_miiphy_read (char *devname, unsigned char addr, unsigned char reg,
+			 unsigned short *value)
+{
+	unsigned long sta_reg;
+	unsigned long emac_reg;
+
+	emac_reg = miiphy_getemac_offset(addr);
+
+	if (emac_miiphy_command(addr, reg, EMAC_STACR_READ, 0) != 0)
+		return -1;
+
+	sta_reg = in_be32((void *)EMAC0_STACR + emac_reg);
+	*value = sta_reg >> 16;
+
+	return 0;
+}
+
+/***********************************************************/
+/* write a phy reg and return the value with a rc	    */
+/***********************************************************/
+
+int emac4xx_miiphy_write (char *devname, unsigned char addr, unsigned char reg,
+			  unsigned short value)
+{
+	return emac_miiphy_command(addr, reg, EMAC_STACR_WRITE, value);
+}
diff --git a/arch/powerpc/cpu/ppc4xx/reginfo.c b/arch/powerpc/cpu/ppc4xx/reginfo.c
new file mode 100644
index 0000000..a975667
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/reginfo.c
@@ -0,0 +1,370 @@
+/*
+ *(C) Copyright 2005-2009 Netstal Maschinen AG
+ *    Bruno Hars (Bruno.Hars@netstal.com)
+ *    Niklaus Giger (Niklaus.Giger@netstal.com)
+ *
+ *    This source code is free software; you can redistribute it
+ *    and/or modify it in source code form 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 program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/*
+ * reginfo.c - register dump of HW-configuratin register for PPC4xx based board
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/ppc4xx-uic.h>
+#include <ppc4xx_enet.h>
+
+enum REGISTER_TYPE {
+	IDCR1,	/* Indirectly Accessed DCR via SDRAM0_CFGADDR/SDRAM0_CFGDATA */
+	IDCR2,	/* Indirectly Accessed DCR via EBC0_CFGADDR/EBC0_CFGDATA */
+	IDCR3,	/* Indirectly Accessed DCR via EBM0_CFGADDR/EBM0_CFGDATA */
+	IDCR4,	/* Indirectly Accessed DCR via PPM0_CFGADDR/PPM0_CFGDATA */
+	IDCR5,	/* Indirectly Accessed DCR via CPR0_CFGADDR/CPR0_CFGDATA */
+	IDCR6,	/* Indirectly Accessed DCR via SDR0_CFGADDR/SDR0_CFGDATA */
+	MM	/* Directly Accessed MMIO Register */
+};
+
+struct cpu_register {
+	char *name;
+	enum REGISTER_TYPE type;
+	u32 address;
+};
+
+/*
+ * PPC440EPx registers ordered for output
+ * name           type    addr            size
+ * -------------------------------------------
+ */
+
+const struct cpu_register ppc4xx_reg[] = {
+	{"PB0CR",		IDCR2,	PB0CR},
+	{"PB0AP",		IDCR2,	PB0AP},
+	{"PB1CR",		IDCR2,	PB1CR},
+	{"PB1AP",		IDCR2,	PB1AP},
+	{"PB2CR",		IDCR2,	PB2CR},
+	{"PB2AP",		IDCR2,	PB2AP},
+	{"PB3CR",		IDCR2,	PB3CR},
+	{"PB3AP",		IDCR2,	PB3AP},
+
+	{"PB4CR",		IDCR2,	PB4CR},
+	{"PB4AP",		IDCR2,	PB4AP},
+#if !defined(CONFIG_405EP)
+	{"PB5CR",		IDCR2,	PB5CR},
+	{"PB5AP",		IDCR2,	PB5AP},
+	{"PB6CR",		IDCR2,	PB6CR},
+	{"PB6AP",		IDCR2,	PB6AP},
+	{"PB7CR",		IDCR2,	PB7CR},
+	{"PB7AP",		IDCR2,	PB7AP},
+#endif
+
+	{"PBEAR",		IDCR2,	PBEAR},
+#if defined(CONFIG_405EP) || defined (CONFIG_405GP)
+	{"PBESR0",		IDCR2,	PBESR0},
+	{"PBESR1",		IDCR2,	PBESR1},
+#endif
+	{"EBC0_CFG",		IDCR2,	EBC0_CFG},
+
+#ifdef CONFIG_405GP
+	{"SDRAM0_BESR0",	IDCR1,	SDRAM0_BESR0},
+	{"SDRAM0_BESRS0",	IDCR1,	SDRAM0_BESRS0},
+	{"SDRAM0_BESR1",	IDCR1,	SDRAM0_BESR1},
+	{"SDRAM0_BESRS1",	IDCR1,	SDRAM0_BESRS1},
+	{"SDRAM0_BEAR",		IDCR1,	SDRAM0_BEAR},
+	{"SDRAM0_CFG",		IDCR1,	SDRAM0_CFG},
+	{"SDRAM0_RTR",		IDCR1,	SDRAM0_RTR},
+	{"SDRAM0_PMIT",		IDCR1,	SDRAM0_PMIT},
+
+	{"SDRAM0_B0CR",		IDCR1,	SDRAM0_B0CR},
+	{"SDRAM0_B1CR",		IDCR1,	SDRAM0_B1CR},
+	{"SDRAM0_B2CR",		IDCR1,	SDRAM0_B2CR},
+	{"SDRAM0_B3CR",		IDCR1,	SDRAM0_B1CR},
+	{"SDRAM0_TR",		IDCR1,	SDRAM0_TR},
+	{"SDRAM0_ECCCFG",	IDCR1,	SDRAM0_B1CR},
+	{"SDRAM0_ECCESR",	IDCR1,	SDRAM0_ECCESR},
+
+
+#endif
+
+#ifdef CONFIG_440EPX
+	{"SDR0_SDSTP0",		IDCR6,	SDR0_SDSTP0},
+	{"SDR0_SDSTP1",		IDCR6,	SDR0_SDSTP1},
+	{"SDR0_SDSTP2",		IDCR6,	SDR0_SDSTP2},
+	{"SDR0_SDSTP3",		IDCR6,	SDR0_SDSTP3},
+	{"SDR0_CUST0",		IDCR6,	SDR0_CUST0},
+	{"SDR0_CUST1",		IDCR6,	SDR0_CUST1},
+	{"SDR0_EBC0",		IDCR6,	SDR0_EBC0},
+	{"SDR0_AMP0",		IDCR6,	SD0_AMP0},
+	{"SDR0_AMP1",		IDCR6,	SD0_AMP1},
+	{"SDR0_CP440",		IDCR6,	SDR0_CP440},
+	{"SDR0_CRYP0",		IDCR6,	SDR0_CRYP0},
+	{"SDR0_DDRCFG",		IDCR6,	SDR0_DDRCFG},
+	{"SDR0_EMAC0RXST",	IDCR6,	SDR0_EMAC0RXST},
+	{"SDR0_EMAC0TXST",	IDCR6,	SDR0_EMAC0TXST},
+	{"SDR0_MFR",		IDCR6,	SDR0_MFR},
+	{"SDR0_PCI0",		IDCR6,	SDR0_PCI0},
+	{"SDR0_PFC0",		IDCR6,	SDR0_PFC0},
+	{"SDR0_PFC1",		IDCR6,	SDR0_PFC1},
+	{"SDR0_PFC2",		IDCR6,	SDR0_PFC2},
+	{"SDR0_PFC4",		IDCR6,	SDR0_PFC4},
+	{"SDR0_UART0",		IDCR6,	SDR0_UART0},
+	{"SDR0_UART1",		IDCR6,	SDR0_UART1},
+	{"SDR0_UART2",		IDCR6,	SDR0_UART2},
+	{"SDR0_UART3",		IDCR6,	SDR0_UART3},
+	{"DDR0_02",		IDCR1,	DDR0_02},
+	{"DDR0_00",		IDCR1,	DDR0_00},
+	{"DDR0_01",		IDCR1,	DDR0_01},
+	{"DDR0_03",		IDCR1,	DDR0_03},
+	{"DDR0_04",		IDCR1,	DDR0_04},
+	{"DDR0_05",		IDCR1,	DDR0_05},
+	{"DDR0_06",		IDCR1,	DDR0_06},
+	{"DDR0_07",		IDCR1,	DDR0_07},
+	{"DDR0_08",		IDCR1,	DDR0_08},
+	{"DDR0_09",		IDCR1,	DDR0_09},
+	{"DDR0_10",		IDCR1,	DDR0_10},
+	{"DDR0_11",		IDCR1,	DDR0_11},
+	{"DDR0_12",		IDCR1,	DDR0_12},
+	{"DDR0_14",		IDCR1,	DDR0_14},
+	{"DDR0_17",		IDCR1,	DDR0_17},
+	{"DDR0_18",		IDCR1,	DDR0_18},
+	{"DDR0_19",		IDCR1,	DDR0_19},
+	{"DDR0_20",		IDCR1,	DDR0_20},
+	{"DDR0_21",		IDCR1,	DDR0_21},
+	{"DDR0_22",		IDCR1,	DDR0_22},
+	{"DDR0_23",		IDCR1,	DDR0_23},
+	{"DDR0_24",		IDCR1,	DDR0_24},
+	{"DDR0_25",		IDCR1,	DDR0_25},
+	{"DDR0_26",		IDCR1,	DDR0_26},
+	{"DDR0_27",		IDCR1,	DDR0_27},
+	{"DDR0_28",		IDCR1,	DDR0_28},
+	{"DDR0_31",		IDCR1,	DDR0_31},
+	{"DDR0_32",		IDCR1,	DDR0_32},
+	{"DDR0_33",		IDCR1,	DDR0_33},
+	{"DDR0_34",		IDCR1,	DDR0_34},
+	{"DDR0_35",		IDCR1,	DDR0_35},
+	{"DDR0_36",		IDCR1,	DDR0_36},
+	{"DDR0_37",		IDCR1,	DDR0_37},
+	{"DDR0_38",		IDCR1,	DDR0_38},
+	{"DDR0_39",		IDCR1,	DDR0_39},
+	{"DDR0_40",		IDCR1,	DDR0_40},
+	{"DDR0_41",		IDCR1,	DDR0_41},
+	{"DDR0_42",		IDCR1,	DDR0_42},
+	{"DDR0_43",		IDCR1,	DDR0_43},
+	{"DDR0_44",		IDCR1,	DDR0_44},
+	{"CPR0_ICFG",		IDCR5,	CPR0_ICFG},
+	{"CPR0_MALD",		IDCR5,	CPR0_MALD},
+	{"CPR0_OPBD00",		IDCR5,	CPR0_OPBD0},
+	{"CPR0_PERD0",		IDCR5,	CPR0_PERD},
+	{"CPR0_PLLC0",		IDCR5,	CPR0_PLLC},
+	{"CPR0_PLLD0",		IDCR5,	CPR0_PLLD},
+	{"CPR0_PRIMAD0",	IDCR5,	CPR0_PRIMAD0},
+	{"CPR0_PRIMBD0",	IDCR5,	CPR0_PRIMBD0},
+	{"CPR0_SPCID",		IDCR5,	CPR0_SPCID},
+	{"SPI0_MODE",		MM,	SPI0_MODE},
+	{"IIC0_CLKDIV",		MM,	PCIL0_PMM1MA},
+	{"PCIL0_PMM0MA",	MM,	PCIL0_PMM0MA},
+	{"PCIL0_PMM1MA",	MM,	PCIL0_PMM1MA},
+	{"PCIL0_PTM1LA",	MM,	PCIL0_PMM1MA},
+	{"PCIL0_PTM1MS",	MM,	PCIL0_PTM1MS},
+	{"PCIL0_PTM2LA",	MM,	PCIL0_PMM1MA},
+	{"PCIL0_PTM2MS",	MM,	PCIL0_PTM2MS},
+	{"ZMII0_FER",		MM,	ZMII0_FER},
+	{"ZMII0_SSR",		MM,	ZMII0_SSR},
+	{"EMAC0_IPGVR",		MM,	EMAC0_IPGVR},
+	{"EMAC0_MR1",		MM,	EMAC0_MR1},
+	{"EMAC0_PTR",		MM,	EMAC0_PTR},
+	{"EMAC0_RWMR",		MM,	EMAC0_RWMR},
+	{"EMAC0_STACR",		MM,	EMAC0_STACR},
+	{"EMAC0_TMR0",		MM,	EMAC0_TMR0},
+	{"EMAC0_TMR1",		MM,	EMAC0_TMR1},
+	{"EMAC0_TRTR",		MM,	EMAC0_TRTR},
+	{"EMAC1_MR1",		MM,	EMAC1_MR1},
+	{"GPIO0_OR",		MM,	GPIO0_OR},
+	{"GPIO1_OR",		MM,	GPIO1_OR},
+	{"GPIO0_TCR",		MM,	GPIO0_TCR},
+	{"GPIO1_TCR",		MM,	GPIO1_TCR},
+	{"GPIO0_ODR",		MM,	GPIO0_ODR},
+	{"GPIO1_ODR",		MM,	GPIO1_ODR},
+	{"GPIO0_OSRL",		MM,	GPIO0_OSRL},
+	{"GPIO0_OSRH",		MM,	GPIO0_OSRH},
+	{"GPIO1_OSRL",		MM,	GPIO1_OSRL},
+	{"GPIO1_OSRH",		MM,	GPIO1_OSRH},
+	{"GPIO0_TSRL",		MM,	GPIO0_TSRL},
+	{"GPIO0_TSRH",		MM,	GPIO0_TSRH},
+	{"GPIO1_TSRL",		MM,	GPIO1_TSRL},
+	{"GPIO1_TSRH",		MM,	GPIO1_TSRH},
+	{"GPIO0_IR",		MM,	GPIO0_IR},
+	{"GPIO1_IR",		MM,	GPIO1_IR},
+	{"GPIO0_ISR1L",		MM,	GPIO0_ISR1L},
+	{"GPIO0_ISR1H",		MM,	GPIO0_ISR1H},
+	{"GPIO1_ISR1L",		MM,	GPIO1_ISR1L},
+	{"GPIO1_ISR1H",		MM,	GPIO1_ISR1H},
+	{"GPIO0_ISR2L",		MM,	GPIO0_ISR2L},
+	{"GPIO0_ISR2H",		MM,	GPIO0_ISR2H},
+	{"GPIO1_ISR2L",		MM,	GPIO1_ISR2L},
+	{"GPIO1_ISR2H",		MM,	GPIO1_ISR2H},
+	{"GPIO0_ISR3L",		MM,	GPIO0_ISR3L},
+	{"GPIO0_ISR3H",		MM,	GPIO0_ISR3H},
+	{"GPIO1_ISR3L",		MM,	GPIO1_ISR3L},
+	{"GPIO1_ISR3H",		MM,	GPIO1_ISR3H},
+	{"SDR0_USB2PHY0CR",	IDCR6,	SDR0_USB2PHY0CR},
+	{"SDR0_USB2H0CR",	IDCR6,	SDR0_USB2H0CR},
+	{"SDR0_USB2D0CR",	IDCR6,	SDR0_USB2D0CR},
+#endif
+};
+
+/*
+ * CPU Register dump of PPC4xx HW configuration registers
+ * Output: first all DCR-registers, then in order of struct ppc4xx_reg
+ */
+#define PRINT_DCR(dcr) 	printf("0x%08x %-16s: 0x%08x\n", dcr,#dcr, mfdcr(dcr));
+
+void ppc4xx_reginfo(void)
+{
+	unsigned int i;
+	unsigned int n;
+	u32 value;
+	enum REGISTER_TYPE type;
+#if defined (CONFIG_405EP)
+	printf("Dump PPC405EP HW configuration registers\n\n");
+#elif CONFIG_405GP
+	printf ("Dump 405GP HW configuration registers\n\n");
+#elif CONFIG_440EPX
+	printf("Dump PPC440EPx HW configuration registers\n\n");
+#endif
+	printf("MSR: 0x%08x\n", mfmsr());
+
+	printf ("\nUniversal Interrupt Controller Regs\n");
+	PRINT_DCR(UIC0SR);
+	PRINT_DCR(UIC0ER);
+	PRINT_DCR(UIC0CR);
+	PRINT_DCR(UIC0PR);
+	PRINT_DCR(UIC0TR);
+	PRINT_DCR(UIC0MSR);
+	PRINT_DCR(UIC0VR);
+	PRINT_DCR(UIC0VCR);
+
+#if (UIC_MAX > 1)
+	PRINT_DCR(UIC2SR);
+	PRINT_DCR(UIC2ER);
+	PRINT_DCR(UIC2CR);
+	PRINT_DCR(UIC2PR);
+	PRINT_DCR(UIC2TR);
+	PRINT_DCR(UIC2MSR);
+	PRINT_DCR(UIC2VR);
+	PRINT_DCR(UIC2VCR);
+#endif
+
+#if (UIC_MAX > 2)
+	PRINT_DCR(UIC2SR);
+	PRINT_DCR(UIC2ER);
+	PRINT_DCR(UIC2CR);
+	PRINT_DCR(UIC2PR);
+	PRINT_DCR(UIC2TR);
+	PRINT_DCR(UIC2MSR);
+	PRINT_DCR(UIC2VR);
+	PRINT_DCR(UIC2VCR);
+#endif
+
+#if (UIC_MAX > 3)
+	PRINT_DCR(UIC3SR);
+	PRINT_DCR(UIC3ER);
+	PRINT_DCR(UIC3CR);
+	PRINT_DCR(UIC3PR);
+	PRINT_DCR(UIC3TR);
+	PRINT_DCR(UIC3MSR);
+	PRINT_DCR(UIC3VR);
+	PRINT_DCR(UIC3VCR);
+#endif
+
+#if defined (CONFIG_405EP) || defined (CONFIG_405GP)
+	printf ("\n\nDMA Channels\n");
+	PRINT_DCR(DMASR);
+	PRINT_DCR(DMASGC);
+	PRINT_DCR(DMAADR);
+
+	PRINT_DCR(DMACR0);
+	PRINT_DCR(DMACT0);
+	PRINT_DCR(DMADA0);
+	PRINT_DCR(DMASA0);
+	PRINT_DCR(DMASB0);
+
+	PRINT_DCR(DMACR1);
+	PRINT_DCR(DMACT1);
+	PRINT_DCR(DMADA1);
+	PRINT_DCR(DMASA1);
+	PRINT_DCR(DMASB1);
+
+	PRINT_DCR(DMACR2);
+	PRINT_DCR(DMACT2);
+	PRINT_DCR(DMADA2);
+	PRINT_DCR(DMASA2);
+	PRINT_DCR(DMASB2);
+
+	PRINT_DCR(DMACR3);
+	PRINT_DCR(DMACT3);
+	PRINT_DCR(DMADA3);
+	PRINT_DCR(DMASA3);
+	PRINT_DCR(DMASB3);
+#endif
+
+	printf ("\n\nVarious HW-Configuration registers\n");
+#if defined (CONFIG_440EPX)
+	PRINT_DCR(MAL0_CFG);
+	PRINT_DCR(CPM0_ER);
+	PRINT_DCR(CPM1_ER);
+	PRINT_DCR(PLB4A0_ACR);
+	PRINT_DCR(PLB4A1_ACR);
+	PRINT_DCR(PLB3A0_ACR);
+	PRINT_DCR(OPB2PLB40_BCTRL);
+	PRINT_DCR(P4P3BO0_CFG);
+#endif
+	n = sizeof(ppc4xx_reg) / sizeof(ppc4xx_reg[0]);
+	for (i = 0; i < n; i++) {
+		value = 0;
+		type = ppc4xx_reg[i].type;
+		switch (type) {
+		case IDCR1:	/* Indirect via SDRAM0_CFGADDR/DDR0_CFGDATA */
+			mtdcr(SDRAM0_CFGADDR, ppc4xx_reg[i].address);
+			value = mfdcr(SDRAM0_CFGDATA);
+			break;
+		case IDCR2:	/* Indirect via EBC0_CFGADDR/EBC0_CFGDATA */
+			mtdcr(EBC0_CFGADDR, ppc4xx_reg[i].address);
+			value = mfdcr(EBC0_CFGDATA);
+			break;
+		case IDCR5:	/* Indirect via CPR0_CFGADDR/CPR0_CFGDATA */
+			mtdcr(CPR0_CFGADDR, ppc4xx_reg[i].address);
+			value = mfdcr(CPR0_CFGDATA);
+			break;
+		case IDCR6:	/* Indirect via SDR0_CFGADDR/SDR0_CFGDATA */
+			mtdcr(SDR0_CFGADDR, ppc4xx_reg[i].address);
+			value = mfdcr(SDR0_CFGDATA);
+			break;
+		case MM:	/* Directly Accessed MMIO Register */
+			value = in_be32((const volatile unsigned __iomem *)
+				ppc4xx_reg[i].address);
+			break;
+		default:
+			printf("\nERROR: struct entry %d: unknown register"
+				"type\n", i);
+			break;
+		}
+		printf("0x%08x %-16s: 0x%08x\n",ppc4xx_reg[i].address,
+			ppc4xx_reg[i].name, value);
+	}
+}
diff --git a/arch/powerpc/cpu/ppc4xx/resetvec.S b/arch/powerpc/cpu/ppc4xx/resetvec.S
new file mode 100644
index 0000000..b3308bd
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/resetvec.S
@@ -0,0 +1,12 @@
+/* Copyright MontaVista Software Incorporated, 2000 */
+#include <config.h>
+	.section .resetvec,"ax"
+#if defined(CONFIG_440)
+	b _start_440
+#else
+#if defined(CONFIG_BOOT_PCI) && defined(CONFIG_MIP405)
+	b _start_pci
+#else
+	b _start
+#endif
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/sdram.c b/arch/powerpc/cpu/ppc4xx/sdram.c
new file mode 100644
index 0000000..30c6e0e
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/sdram.c
@@ -0,0 +1,468 @@
+/*
+ * (C) Copyright 2005-2007
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * (C) Copyright 2006
+ * DAVE Srl <www.dave-tech.it>
+ *
+ * (C) Copyright 2002-2004
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <ppc4xx.h>
+#include <asm/processor.h>
+#include "sdram.h"
+#include "ecc.h"
+
+#ifdef CONFIG_SDRAM_BANK0
+
+#ifndef CONFIG_440
+
+#ifndef CONFIG_SYS_SDRAM_TABLE
+sdram_conf_t mb0cf[] = {
+	{(128 << 20), 13, 0x000A4001},	    /* (0-128MB) Address Mode 3, 13x10(4) */
+	{(64 << 20),  13, 0x00084001},	    /* (0-64MB) Address Mode 3, 13x9(4)	  */
+	{(32 << 20),  12, 0x00062001},	    /* (0-32MB) Address Mode 2, 12x9(4)	  */
+	{(16 << 20),  12, 0x00046001},	    /* (0-16MB) Address Mode 4, 12x8(4)	  */
+	{(4 << 20),   11, 0x00008001},	    /* (0-4MB) Address Mode 5, 11x8(2)	  */
+};
+#else
+sdram_conf_t mb0cf[] = CONFIG_SYS_SDRAM_TABLE;
+#endif
+
+#define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0]))
+
+#ifdef CONFIG_SYS_SDRAM_CASL
+static ulong ns2clks(ulong ns)
+{
+	ulong bus_period_x_10 = ONE_BILLION / (get_bus_freq(0) / 10);
+
+	return ((ns * 10) + bus_period_x_10) / bus_period_x_10;
+}
+#endif /* CONFIG_SYS_SDRAM_CASL */
+
+static ulong compute_sdtr1(ulong speed)
+{
+#ifdef CONFIG_SYS_SDRAM_CASL
+	ulong tmp;
+	ulong sdtr1 = 0;
+
+	/* CASL */
+	if (CONFIG_SYS_SDRAM_CASL < 2)
+		sdtr1 |= (1 << SDRAM0_TR_CASL);
+	else
+		if (CONFIG_SYS_SDRAM_CASL > 4)
+			sdtr1 |= (3 << SDRAM0_TR_CASL);
+		else
+			sdtr1 |= ((CONFIG_SYS_SDRAM_CASL-1) << SDRAM0_TR_CASL);
+
+	/* PTA */
+	tmp = ns2clks(CONFIG_SYS_SDRAM_PTA);
+	if ((tmp >= 2) && (tmp <= 4))
+		sdtr1 |= ((tmp-1) << SDRAM0_TR_PTA);
+	else
+		sdtr1 |= ((4-1) << SDRAM0_TR_PTA);
+
+	/* CTP */
+	tmp = ns2clks(CONFIG_SYS_SDRAM_CTP);
+	if ((tmp >= 2) && (tmp <= 4))
+		sdtr1 |= ((tmp-1) << SDRAM0_TR_CTP);
+	else
+		sdtr1 |= ((4-1) << SDRAM0_TR_CTP);
+
+	/* LDF */
+	tmp = ns2clks(CONFIG_SYS_SDRAM_LDF);
+	if ((tmp >= 2) && (tmp <= 4))
+		sdtr1 |= ((tmp-1) << SDRAM0_TR_LDF);
+	else
+		sdtr1 |= ((2-1) << SDRAM0_TR_LDF);
+
+	/* RFTA */
+	tmp = ns2clks(CONFIG_SYS_SDRAM_RFTA);
+	if ((tmp >= 4) && (tmp <= 10))
+		sdtr1 |= ((tmp-4) << SDRAM0_TR_RFTA);
+	else
+		sdtr1 |= ((10-4) << SDRAM0_TR_RFTA);
+
+	/* RCD */
+	tmp = ns2clks(CONFIG_SYS_SDRAM_RCD);
+	if ((tmp >= 2) && (tmp <= 4))
+		sdtr1 |= ((tmp-1) << SDRAM0_TR_RCD);
+	else
+		sdtr1 |= ((4-1) << SDRAM0_TR_RCD);
+
+	return sdtr1;
+#else /* CONFIG_SYS_SDRAM_CASL */
+	/*
+	 * If no values are configured in the board config file
+	 * use the default values, which seem to be ok for most
+	 * boards.
+	 *
+	 * REMARK:
+	 * For new board ports we strongly recommend to define the
+	 * correct values for the used SDRAM chips in your board
+	 * config file (see PPChameleonEVB.h)
+	 */
+	if (speed > 100000000) {
+		/*
+		 * 133 MHz SDRAM
+		 */
+		return 0x01074015;
+	} else {
+		/*
+		 * default: 100 MHz SDRAM
+		 */
+		return 0x0086400d;
+	}
+#endif /* CONFIG_SYS_SDRAM_CASL */
+}
+
+/* refresh is expressed in ms */
+static ulong compute_rtr(ulong speed, ulong rows, ulong refresh)
+{
+#ifdef CONFIG_SYS_SDRAM_CASL
+	ulong tmp;
+
+	tmp = ((refresh*1000*1000) / (1 << rows)) * (speed / 1000);
+	tmp /= 1000000;
+
+	return ((tmp & 0x00003FF8) << 16);
+#else /* CONFIG_SYS_SDRAM_CASL */
+	if (speed > 100000000) {
+		/*
+		 * 133 MHz SDRAM
+		 */
+		return 0x07f00000;
+	} else {
+		/*
+		 * default: 100 MHz SDRAM
+		 */
+		return 0x05f00000;
+	}
+#endif /* CONFIG_SYS_SDRAM_CASL */
+}
+
+/*
+ * Autodetect onboard SDRAM on 405 platforms
+ */
+phys_size_t initdram(int board_type)
+{
+	ulong speed;
+	ulong sdtr1;
+	int i;
+
+	/*
+	 * Determine SDRAM speed
+	 */
+	speed = get_bus_freq(0); /* parameter not used on ppc4xx */
+
+	/*
+	 * sdtr1 (register SDRAM0_TR) must take into account timings listed
+	 * in SDRAM chip datasheet. rtr (register SDRAM0_RTR) must take into
+	 * account actual SDRAM size. So we can set up sdtr1 according to what
+	 * is specified in board configuration file while rtr dependds on SDRAM
+	 * size we are assuming before detection.
+	 */
+	sdtr1 = compute_sdtr1(speed);
+
+	for (i=0; i<N_MB0CF; i++) {
+		/*
+		 * Disable memory controller.
+		 */
+		mtsdram(SDRAM0_CFG, 0x00000000);
+
+		/*
+		 * Set MB0CF for bank 0.
+		 */
+		mtsdram(SDRAM0_B0CR, mb0cf[i].reg);
+		mtsdram(SDRAM0_TR, sdtr1);
+		mtsdram(SDRAM0_RTR, compute_rtr(speed, mb0cf[i].rows, 64));
+
+		udelay(200);
+
+		/*
+		 * Set memory controller options reg, MCOPT1.
+		 * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst
+		 * read/prefetch.
+		 */
+		mtsdram(SDRAM0_CFG, 0x80800000);
+
+		udelay(10000);
+
+		if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
+			phys_size_t size = mb0cf[i].size;
+
+			/*
+			 * OK, size detected.  Enable second bank if
+			 * defined (assumes same type as bank 0)
+			 */
+#ifdef CONFIG_SDRAM_BANK1
+			mtsdram(SDRAM0_CFG, 0x00000000);
+			mtsdram(SDRAM0_B1CR, mb0cf[i].size | mb0cf[i].reg);
+			mtsdram(SDRAM0_CFG, 0x80800000);
+			udelay(10000);
+
+			/*
+			 * Check if 2nd bank is really available.
+			 * If the size not equal to the size of the first
+			 * bank, then disable the 2nd bank completely.
+			 */
+			if (get_ram_size((long *)mb0cf[i].size, mb0cf[i].size) !=
+			    mb0cf[i].size) {
+				mtsdram(SDRAM0_B1CR, 0);
+				mtsdram(SDRAM0_CFG, 0);
+			} else {
+				/*
+				 * We have two identical banks, so the size
+				 * is twice the bank size
+				 */
+				size = 2 * size;
+			}
+#endif
+
+			/*
+			 * OK, size detected -> all done
+			 */
+			return size;
+		}
+	}
+
+	return 0;
+}
+
+#else /* CONFIG_440 */
+
+/*
+ * Define some default values. Those can be overwritten in the
+ * board config file.
+ */
+
+#ifndef CONFIG_SYS_SDRAM_TABLE
+sdram_conf_t mb0cf[] = {
+	{(256 << 20), 13, 0x000C4001},	/* 256MB mode 3, 13x10(4)	*/
+	{(128 << 20), 13, 0x000A4001},	/* 128MB mode 3, 13x10(4)	*/
+	{(64 << 20),  12, 0x00082001}	/* 64MB mode 2, 12x9(4)		*/
+};
+#else
+sdram_conf_t mb0cf[] = CONFIG_SYS_SDRAM_TABLE;
+#endif
+
+#ifndef CONFIG_SYS_SDRAM0_TR0
+#define	CONFIG_SYS_SDRAM0_TR0		0x41094012
+#endif
+
+#ifndef CONFIG_SYS_SDRAM0_WDDCTR
+#define CONFIG_SYS_SDRAM0_WDDCTR	0x00000000  /* wrcp=0 dcd=0	*/
+#endif
+
+#ifndef CONFIG_SYS_SDRAM0_RTR
+#define CONFIG_SYS_SDRAM0_RTR 		0x04100000 /* 7.8us @ 133MHz PLB */
+#endif
+
+#ifndef CONFIG_SYS_SDRAM0_CFG0
+#define CONFIG_SYS_SDRAM0_CFG0		0x82000000 /* DCEN=1, PMUD=0, 64-bit */
+#endif
+
+#define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0]))
+
+#define NUM_TRIES 64
+#define NUM_READS 10
+
+static void sdram_tr1_set(int ram_address, int* tr1_value)
+{
+	int i;
+	int j, k;
+	volatile unsigned int* ram_pointer = (unsigned int *)ram_address;
+	int first_good = -1, last_bad = 0x1ff;
+
+	unsigned long test[NUM_TRIES] = {
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+		0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+		0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+		0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+		0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+		0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+		0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+		0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+		0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+		0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+		0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+		0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 };
+
+	/* go through all possible SDRAM0_TR1[RDCT] values */
+	for (i=0; i<=0x1ff; i++) {
+		/* set the current value for TR1 */
+		mtsdram(SDRAM0_TR1, (0x80800800 | i));
+
+		/* write values */
+		for (j=0; j<NUM_TRIES; j++) {
+			ram_pointer[j] = test[j];
+
+			/* clear any cache at ram location */
+			__asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
+		}
+
+		/* read values back */
+		for (j=0; j<NUM_TRIES; j++) {
+			for (k=0; k<NUM_READS; k++) {
+				/* clear any cache at ram location */
+				__asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
+
+				if (ram_pointer[j] != test[j])
+					break;
+			}
+
+			/* read error */
+			if (k != NUM_READS)
+				break;
+		}
+
+		/* we have a SDRAM0_TR1[RDCT] that is part of the window */
+		if (j == NUM_TRIES) {
+			if (first_good == -1)
+				first_good = i;		/* found beginning of window */
+		} else { /* bad read */
+			/* if we have not had a good read then don't care */
+			if (first_good != -1) {
+				/* first failure after a good read */
+				last_bad = i-1;
+				break;
+			}
+		}
+	}
+
+	/* return the current value for TR1 */
+	*tr1_value = (first_good + last_bad) / 2;
+}
+
+/*
+ * Autodetect onboard DDR SDRAM on 440 platforms
+ *
+ * NOTE: Some of the hardcoded values are hardware dependant,
+ *	 so this should be extended for other future boards
+ *	 using this routine!
+ */
+phys_size_t initdram(int board_type)
+{
+	int i;
+	int tr1_bank1;
+
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \
+    defined(CONFIG_440GR) || defined(CONFIG_440SP)
+	/*
+	 * Soft-reset SDRAM controller.
+	 */
+	mtsdr(SDR0_SRST, SDR0_SRST_DMC);
+	mtsdr(SDR0_SRST, 0x00000000);
+#endif
+
+	for (i=0; i<N_MB0CF; i++) {
+		/*
+		 * Disable memory controller.
+		 */
+		mtsdram(SDRAM0_CFG0, 0x00000000);
+
+		/*
+		 * Setup some default
+		 */
+		mtsdram(SDRAM0_UABBA, 0x00000000); /* ubba=0 (default)		*/
+		mtsdram(SDRAM0_SLIO, 0x00000000);	/* rdre=0 wrre=0 rarw=0		*/
+		mtsdram(SDRAM0_DEVOPT, 0x00000000); /* dll=0 ds=0 (normal)		*/
+		mtsdram(SDRAM0_WDDCTR, CONFIG_SYS_SDRAM0_WDDCTR);
+		mtsdram(SDRAM0_CLKTR, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0	*/
+
+		/*
+		 * Following for CAS Latency = 2.5 @ 133 MHz PLB
+		 */
+		mtsdram(SDRAM0_B0CR, mb0cf[i].reg);
+		mtsdram(SDRAM0_TR0, CONFIG_SYS_SDRAM0_TR0);
+		mtsdram(SDRAM0_TR1, 0x80800800);	/* SS=T2 SL=STAGE 3 CD=1 CT=0x00*/
+		mtsdram(SDRAM0_RTR, CONFIG_SYS_SDRAM0_RTR);
+		mtsdram(SDRAM0_CFG1, 0x00000000);	/* Self-refresh exit, disable PM*/
+		udelay(400);			/* Delay 200 usecs (min)	*/
+
+		/*
+		 * Enable the controller, then wait for DCEN to complete
+		 */
+		mtsdram(SDRAM0_CFG0, CONFIG_SYS_SDRAM0_CFG0);
+		udelay(10000);
+
+		if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
+			phys_size_t size = mb0cf[i].size;
+			/*
+			 * Optimize TR1 to current hardware environment
+			 */
+			sdram_tr1_set(0x00000000, &tr1_bank1);
+			mtsdram(SDRAM0_TR1, (tr1_bank1 | 0x80800800));
+
+
+			/*
+			 * OK, size detected.  Enable second bank if
+			 * defined (assumes same type as bank 0)
+			 */
+#ifdef CONFIG_SDRAM_BANK1
+			mtsdram(SDRAM0_CFG0, 0);
+			mtsdram(SDRAM0_B1CR, mb0cf[i].size | mb0cf[i].reg);
+			mtsdram(SDRAM0_CFG0, CONFIG_SYS_SDRAM0_CFG0);
+			udelay(10000);
+
+			/*
+			 * Check if 2nd bank is really available.
+			 * If the size not equal to the size of the first
+			 * bank, then disable the 2nd bank completely.
+			 */
+			if (get_ram_size((long *)mb0cf[i].size, mb0cf[i].size)
+			    != mb0cf[i].size) {
+				mtsdram(SDRAM0_CFG0, 0);
+				mtsdram(SDRAM0_B1CR, 0);
+				mtsdram(SDRAM0_CFG0, CONFIG_SYS_SDRAM0_CFG0);
+				udelay(10000);
+			} else {
+				/*
+				 * We have two identical banks, so the size
+				 * is twice the bank size
+				 */
+				size = 2 * size;
+			}
+#endif
+
+#ifdef CONFIG_SDRAM_ECC
+			ecc_init(0, size);
+#endif
+
+			/*
+			 * OK, size detected -> all done
+			 */
+			return size;
+		}
+	}
+
+	return 0;				/* nothing found !		*/
+}
+
+#endif /* CONFIG_440 */
+
+#endif /* CONFIG_SDRAM_BANK0 */
diff --git a/arch/powerpc/cpu/ppc4xx/sdram.h b/arch/powerpc/cpu/ppc4xx/sdram.h
new file mode 100644
index 0000000..bea3376
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/sdram.h
@@ -0,0 +1,76 @@
+/*
+ * (C) Copyright 2006
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * (C) Copyright 2006
+ * DAVE Srl <www.dave-tech.it>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _SDRAM_H_
+#define _SDRAM_H_
+
+#include <config.h>
+
+#define ONE_BILLION	1000000000
+
+struct sdram_conf_s {
+	unsigned long size;
+	int rows;
+	unsigned long reg;
+};
+
+typedef struct sdram_conf_s sdram_conf_t;
+
+/* Bitfields offsets */
+#define SDRAM0_TR_CASL		(31 - 8)
+#define SDRAM0_TR_PTA		(31 - 13)
+#define SDRAM0_TR_CTP		(31 - 15)
+#define SDRAM0_TR_LDF		(31 - 17)
+#define SDRAM0_TR_RFTA		(31 - 29)
+#define SDRAM0_TR_RCD		(31 - 31)
+
+#ifdef CONFIG_SYS_SDRAM_CL
+/* SDRAM timings [ns] according to AMCC/IBM names (see SDRAM_faq.doc) */
+#define CONFIG_SYS_SDRAM_CASL		CONFIG_SYS_SDRAM_CL
+#define CONFIG_SYS_SDRAM_PTA		CONFIG_SYS_SDRAM_tRP
+#define CONFIG_SYS_SDRAM_CTP		(CONFIG_SYS_SDRAM_tRC - CONFIG_SYS_SDRAM_tRCD - CONFIG_SYS_SDRAM_tRP)
+#define CONFIG_SYS_SDRAM_LDF		0
+#ifdef CONFIG_SYS_SDRAM_tRFC
+#define CONFIG_SYS_SDRAM_RFTA		CONFIG_SYS_SDRAM_tRFC
+#else
+#define CONFIG_SYS_SDRAM_RFTA		CONFIG_SYS_SDRAM_tRC
+#endif
+#define CONFIG_SYS_SDRAM_RCD		CONFIG_SYS_SDRAM_tRCD
+#endif /* #ifdef CONFIG_SYS_SDRAM_CL */
+
+/*
+ * Some defines for the 440 DDR controller
+ */
+#define SDRAM_CFG0_DC_EN	0x80000000	/* SDRAM Controller Enable	*/
+#define SDRAM_CFG0_MEMCHK	0x30000000	/* Memory data error checking mask*/
+#define SDRAM_CFG0_MEMCHK_NON	0x00000000	/* No ECC generation		*/
+#define SDRAM_CFG0_MEMCHK_GEN	0x20000000	/* ECC generation		*/
+#define SDRAM_CFG0_MEMCHK_CHK	0x30000000	/* ECC generation and checking	*/
+#define SDRAM_CFG0_DRAMWDTH	0x02000000	/* DRAM width mask		*/
+#define SDRAM_CFG0_DRAMWDTH_32	0x00000000	/* 32 bits			*/
+#define SDRAM_CFG0_DRAMWDTH_64	0x02000000	/* 64 bits			*/
+
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/speed.c b/arch/powerpc/cpu/ppc4xx/speed.c
new file mode 100644
index 0000000..906face
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/speed.c
@@ -0,0 +1,1177 @@
+/*
+ * (C) Copyright 2000-2008
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <ppc_asm.tmpl>
+#include <ppc4xx.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ONE_BILLION        1000000000
+#ifdef DEBUG
+#define DEBUGF(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGF(fmt,args...)
+#endif
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR)
+
+void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
+{
+	unsigned long pllmr;
+	unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
+	uint pvr = get_pvr();
+	unsigned long psr;
+	unsigned long m;
+
+	/*
+	 * Read PLL Mode register
+	 */
+	pllmr = mfdcr (CPC0_PLLMR);
+
+	/*
+	 * Read Pin Strapping register
+	 */
+	psr = mfdcr (CPC0_PSR);
+
+	/*
+	 * Determine FWD_DIV.
+	 */
+	sysInfo->pllFwdDiv = 8 - ((pllmr & PLLMR_FWD_DIV_MASK) >> 29);
+
+	/*
+	 * Determine FBK_DIV.
+	 */
+	sysInfo->pllFbkDiv = ((pllmr & PLLMR_FB_DIV_MASK) >> 25);
+	if (sysInfo->pllFbkDiv == 0) {
+		sysInfo->pllFbkDiv = 16;
+	}
+
+	/*
+	 * Determine PLB_DIV.
+	 */
+	sysInfo->pllPlbDiv = ((pllmr & PLLMR_CPU_TO_PLB_MASK) >> 17) + 1;
+
+	/*
+	 * Determine PCI_DIV.
+	 */
+	sysInfo->pllPciDiv = ((pllmr & PLLMR_PCI_TO_PLB_MASK) >> 13) + 1;
+
+	/*
+	 * Determine EXTBUS_DIV.
+	 */
+	sysInfo->pllExtBusDiv = ((pllmr & PLLMR_EXB_TO_PLB_MASK) >> 11) + 2;
+
+	/*
+	 * Determine OPB_DIV.
+	 */
+	sysInfo->pllOpbDiv = ((pllmr & PLLMR_OPB_TO_PLB_MASK) >> 15) + 1;
+
+	/*
+	 * Check if PPC405GPr used (mask minor revision field)
+	 */
+	if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) {
+		/*
+		 * Determine FWD_DIV B (only PPC405GPr with new mode strapping).
+		 */
+		sysInfo->pllFwdDivB = 8 - (pllmr & PLLMR_FWDB_DIV_MASK);
+
+		/*
+		 * Determine factor m depending on PLL feedback clock source
+		 */
+		if (!(psr & PSR_PCI_ASYNC_EN)) {
+			if (psr & PSR_NEW_MODE_EN) {
+				/*
+				 * sync pci clock used as feedback (new mode)
+				 */
+				m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllPciDiv;
+			} else {
+				/*
+				 * sync pci clock used as feedback (legacy mode)
+				 */
+				m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllPciDiv;
+			}
+		} else if (psr & PSR_NEW_MODE_EN) {
+			if (psr & PSR_PERCLK_SYNC_MODE_EN) {
+				/*
+				 * PerClk used as feedback (new mode)
+				 */
+				m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllExtBusDiv;
+			} else {
+				/*
+				 * CPU clock used as feedback (new mode)
+				 */
+				m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
+			}
+		} else if (sysInfo->pllExtBusDiv == sysInfo->pllFbkDiv) {
+			/*
+			 * PerClk used as feedback (legacy mode)
+			 */
+			m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllExtBusDiv;
+		} else {
+			/*
+			 * PLB clock used as feedback (legacy mode)
+			 */
+			m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv;
+		}
+
+		sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
+			(unsigned long long)sysClkPeriodPs;
+		sysInfo->freqProcessor = sysInfo->freqVCOHz / sysInfo->pllFwdDiv;
+		sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDivB * sysInfo->pllPlbDiv);
+	} else {
+		/*
+		 * Check pllFwdDiv to see if running in bypass mode where the CPU speed
+		 * is equal to the 405GP SYS_CLK_FREQ. If not in bypass mode, check VCO
+		 * to make sure it is within the proper range.
+		 *    spec:    VCO = SYS_CLOCK x FBKDIV x PLBDIV x FWDDIV
+		 * Note freqVCO is calculated in MHz to avoid errors introduced by rounding.
+		 */
+		if (sysInfo->pllFwdDiv == 1) {
+			sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ;
+			sysInfo->freqPLB = CONFIG_SYS_CLK_FREQ / sysInfo->pllPlbDiv;
+		} else {
+			sysInfo->freqVCOHz = ( 1000000000000LL *
+					       (unsigned long long)sysInfo->pllFwdDiv *
+					       (unsigned long long)sysInfo->pllFbkDiv *
+					       (unsigned long long)sysInfo->pllPlbDiv
+				) / (unsigned long long)sysClkPeriodPs;
+			sysInfo->freqPLB = (ONE_BILLION / ((sysClkPeriodPs * 10) /
+							   sysInfo->pllFbkDiv)) * 10000;
+			sysInfo->freqProcessor = sysInfo->freqPLB * sysInfo->pllPlbDiv;
+		}
+	}
+
+	sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
+	sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv;
+	sysInfo->freqUART = sysInfo->freqProcessor;
+}
+
+
+/********************************************
+ * get_PCI_freq
+ * return PCI bus freq in Hz
+ *********************************************/
+ulong get_PCI_freq (void)
+{
+	ulong val;
+	PPC4xx_SYS_INFO sys_info;
+
+	get_sys_info (&sys_info);
+	val = sys_info.freqPLB / sys_info.pllPciDiv;
+	return val;
+}
+
+
+#elif defined(CONFIG_440)
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+    defined(CONFIG_460SX)
+static u8 pll_fwdv_multi_bits[] = {
+	/* values for:  1 - 16 */
+	0x00, 0x01, 0x0f, 0x04, 0x09, 0x0a, 0x0d, 0x0e, 0x03, 0x0c,
+	0x05, 0x08, 0x07, 0x02, 0x0b, 0x06
+};
+
+u32 get_cpr0_fwdv(unsigned long cpr_reg_fwdv)
+{
+	u32 index;
+
+	for (index = 0; index < ARRAY_SIZE(pll_fwdv_multi_bits); index++)
+		if (cpr_reg_fwdv == (u32)pll_fwdv_multi_bits[index])
+			return index + 1;
+
+	return 0;
+}
+
+static u8 pll_fbdv_multi_bits[] = {
+	/* values for:  1 - 100 */
+	0x00, 0xff, 0x7e, 0xfd, 0x7a, 0xf5, 0x6a, 0xd5, 0x2a, 0xd4,
+	0x29, 0xd3, 0x26, 0xcc, 0x19, 0xb3, 0x67, 0xce, 0x1d, 0xbb,
+	0x77, 0xee, 0x5d, 0xba, 0x74, 0xe9, 0x52, 0xa5, 0x4b, 0x96,
+	0x2c, 0xd8, 0x31, 0xe3, 0x46, 0x8d, 0x1b, 0xb7, 0x6f, 0xde,
+	0x3d, 0xfb, 0x76, 0xed, 0x5a, 0xb5, 0x6b, 0xd6, 0x2d, 0xdb,
+	0x36, 0xec, 0x59, 0xb2, 0x64, 0xc9, 0x12, 0xa4, 0x48, 0x91,
+	0x23, 0xc7, 0x0e, 0x9c, 0x38, 0xf0, 0x61, 0xc2, 0x05, 0x8b,
+	0x17, 0xaf, 0x5f, 0xbe, 0x7c, 0xf9, 0x72, 0xe5, 0x4a, 0x95,
+	0x2b, 0xd7, 0x2e, 0xdc, 0x39, 0xf3, 0x66, 0xcd, 0x1a, 0xb4,
+	0x68, 0xd1, 0x22, 0xc4, 0x09, 0x93, 0x27, 0xcf, 0x1e, 0xbc,
+	/* values for:  101 - 200 */
+	0x78, 0xf1, 0x62, 0xc5, 0x0a, 0x94, 0x28, 0xd0, 0x21, 0xc3,
+	0x06, 0x8c, 0x18, 0xb0, 0x60, 0xc1, 0x02, 0x84, 0x08, 0x90,
+	0x20, 0xc0, 0x01, 0x83, 0x07, 0x8f, 0x1f, 0xbf, 0x7f, 0xfe,
+	0x7d, 0xfa, 0x75, 0xea, 0x55, 0xaa, 0x54, 0xa9, 0x53, 0xa6,
+	0x4c, 0x99, 0x33, 0xe7, 0x4e, 0x9d, 0x3b, 0xf7, 0x6e, 0xdd,
+	0x3a, 0xf4, 0x69, 0xd2, 0x25, 0xcb, 0x16, 0xac, 0x58, 0xb1,
+	0x63, 0xc6, 0x0d, 0x9b, 0x37, 0xef, 0x5e, 0xbd, 0x7b, 0xf6,
+	0x6d, 0xda, 0x35, 0xeb, 0x56, 0xad, 0x5b, 0xb6, 0x6c, 0xd9,
+	0x32, 0xe4, 0x49, 0x92, 0x24, 0xc8, 0x11, 0xa3, 0x47, 0x8e,
+	0x1c, 0xb8, 0x70, 0xe1, 0x42, 0x85, 0x0b, 0x97, 0x2f, 0xdf,
+	/* values for:  201 - 255 */
+	0x3e, 0xfc, 0x79, 0xf2, 0x65, 0xca, 0x15, 0xab, 0x57, 0xae,
+	0x5c, 0xb9, 0x73, 0xe6, 0x4d, 0x9a, 0x34, 0xe8, 0x51, 0xa2,
+	0x44, 0x89, 0x13, 0xa7, 0x4f, 0x9e, 0x3c, 0xf8, 0x71, 0xe2,
+	0x45, 0x8a, 0x14, 0xa8, 0x50, 0xa1, 0x43, 0x86, 0x0c, 0x98,
+	0x30, 0xe0, 0x41, 0x82, 0x04, 0x88, 0x10, 0xa0, 0x40, 0x81,
+	0x03, 0x87, 0x0f, 0x9f, 0x3f  /* END */
+};
+
+u32 get_cpr0_fbdv(unsigned long cpr_reg_fbdv)
+{
+	u32 index;
+
+	for (index = 0; index < ARRAY_SIZE(pll_fbdv_multi_bits); index++)
+		if (cpr_reg_fbdv == (u32)pll_fbdv_multi_bits[index])
+			return index + 1;
+
+	return 0;
+}
+
+/*
+ * AMCC_TODO: verify this routine against latest EAS, cause stuff changed
+ *            with latest EAS
+ */
+void get_sys_info (sys_info_t * sysInfo)
+{
+	unsigned long strp0;
+	unsigned long strp1;
+	unsigned long temp;
+	unsigned long m;
+	unsigned long plbedv0;
+
+	/* Extract configured divisors */
+	mfsdr(SDR0_SDSTP0, strp0);
+	mfsdr(SDR0_SDSTP1, strp1);
+
+	temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 4);
+	sysInfo->pllFwdDivA = get_cpr0_fwdv(temp);
+
+	temp = (strp0 & PLLSYS0_FWD_DIV_B_MASK);
+	sysInfo->pllFwdDivB = get_cpr0_fwdv(temp);
+
+	temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 8;
+	sysInfo->pllFbkDiv = get_cpr0_fbdv(temp);
+
+	temp = (strp1 & PLLSYS0_OPB_DIV_MASK) >> 26;
+	sysInfo->pllOpbDiv = temp ? temp : 4;
+
+	/* AMCC_TODO: verify the SDR0_SDSTP1.PERDV0 value sysInfo->pllExtBusDiv */
+	temp = (strp1 & PLLSYS0_PERCLK_DIV_MASK) >> 24;
+	sysInfo->pllExtBusDiv = temp ? temp : 4;
+
+	temp = (strp1 & PLLSYS0_PLBEDV0_DIV_MASK) >> 29;
+	plbedv0 = temp ? temp: 8;
+
+	/* Calculate 'M' based on feedback source */
+	temp = (strp0 & PLLSYS0_SEL_MASK) >> 27;
+	if (temp == 0) {
+		/* PLL internal feedback */
+		m = sysInfo->pllFbkDiv;
+	} else {
+		/* PLL PerClk feedback */
+		m = sysInfo->pllFwdDivA * plbedv0 * sysInfo->pllOpbDiv *
+			sysInfo->pllExtBusDiv;
+	}
+
+	/* Now calculate the individual clocks */
+	sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1);
+	sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
+	sysInfo->freqPLB = sysInfo->freqVCOMhz / sysInfo->pllFwdDivA / plbedv0;
+	sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
+	sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
+	sysInfo->freqDDR = sysInfo->freqPLB;
+	sysInfo->freqUART = sysInfo->freqPLB;
+
+	return;
+}
+
+#elif defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+void get_sys_info (sys_info_t *sysInfo)
+{
+	unsigned long temp;
+	unsigned long reg;
+	unsigned long lfdiv;
+	unsigned long m;
+	unsigned long prbdv0;
+	/*
+	  WARNING: ASSUMES the following:
+	  ENG=1
+	  PRADV0=1
+	  PRBDV0=1
+	*/
+
+	/* Decode CPR0_PLLD0 for divisors */
+	mfcpr(CPR0_PLLD, reg);
+	temp = (reg & PLLD_FWDVA_MASK) >> 16;
+	sysInfo->pllFwdDivA = temp ? temp : 16;
+	temp = (reg & PLLD_FWDVB_MASK) >> 8;
+	sysInfo->pllFwdDivB = temp ? temp: 8 ;
+	temp = (reg & PLLD_FBDV_MASK) >> 24;
+	sysInfo->pllFbkDiv = temp ? temp : 32;
+	lfdiv = reg & PLLD_LFBDV_MASK;
+
+	mfcpr(CPR0_OPBD0, reg);
+	temp = (reg & OPBDDV_MASK) >> 24;
+	sysInfo->pllOpbDiv = temp ? temp : 4;
+
+	mfcpr(CPR0_PERD, reg);
+	temp = (reg & PERDV_MASK) >> 24;
+	sysInfo->pllExtBusDiv = temp ? temp : 8;
+
+	mfcpr(CPR0_PRIMBD0, reg);
+	temp = (reg & PRBDV_MASK) >> 24;
+	prbdv0 = temp ? temp : 8;
+
+	mfcpr(CPR0_SPCID, reg);
+	temp = (reg & SPCID_MASK) >> 24;
+	sysInfo->pllPciDiv = temp ? temp : 4;
+
+	/* Calculate 'M' based on feedback source */
+	mfsdr(SDR0_SDSTP0, reg);
+	temp = (reg & PLLSYS0_SEL_MASK) >> 27;
+	if (temp == 0) { /* PLL output */
+		/* Figure which pll to use */
+		mfcpr(CPR0_PLLC, reg);
+		temp = (reg & PLLC_SRC_MASK) >> 29;
+		if (!temp) /* PLLOUTA */
+			m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
+		else       /* PLLOUTB */
+			m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
+	}
+	else if (temp == 1) /* CPU output */
+		m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
+	else /* PerClk */
+		m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
+
+	/* Now calculate the individual clocks */
+	sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
+	sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
+	sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
+	sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
+	sysInfo->freqEBC = sysInfo->freqPLB/sysInfo->pllExtBusDiv;
+	sysInfo->freqPCI = sysInfo->freqPLB/sysInfo->pllPciDiv;
+	sysInfo->freqUART = sysInfo->freqPLB;
+
+	/* Figure which timer source to use */
+	if (mfspr(SPRN_CCR1) & 0x0080) {
+		/* External Clock, assume same as SYS_CLK */
+		temp = sysInfo->freqProcessor / 2;  /* Max extern clock speed */
+		if (CONFIG_SYS_CLK_FREQ > temp)
+			sysInfo->freqTmrClk = temp;
+		else
+			sysInfo->freqTmrClk = CONFIG_SYS_CLK_FREQ;
+	}
+	else  /* Internal clock */
+		sysInfo->freqTmrClk = sysInfo->freqProcessor;
+}
+
+/********************************************
+ * get_PCI_freq
+ * return PCI bus freq in Hz
+ *********************************************/
+ulong get_PCI_freq (void)
+{
+	sys_info_t sys_info;
+	get_sys_info (&sys_info);
+	return sys_info.freqPCI;
+}
+
+#elif !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) \
+	&& !defined(CONFIG_XILINX_440)
+void get_sys_info (sys_info_t * sysInfo)
+{
+	unsigned long strp0;
+	unsigned long temp;
+	unsigned long m;
+
+	/* Extract configured divisors */
+	strp0 = mfdcr( CPC0_STRP0 );
+	sysInfo->pllFwdDivA = 8 - ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 15);
+	sysInfo->pllFwdDivB = 8 - ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 12);
+	temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 18;
+	sysInfo->pllFbkDiv = temp ? temp : 16;
+	sysInfo->pllOpbDiv = 1 + ((strp0 & PLLSYS0_OPB_DIV_MASK) >> 10);
+	sysInfo->pllExtBusDiv = 1 + ((strp0 & PLLSYS0_EPB_DIV_MASK) >> 8);
+
+	/* Calculate 'M' based on feedback source */
+	if( strp0 & PLLSYS0_EXTSL_MASK )
+		m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
+	else
+		m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
+
+	/* Now calculate the individual clocks */
+	sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
+	sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
+	sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB;
+	if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */
+		sysInfo->freqPLB >>= 1;
+	sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
+	sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
+	sysInfo->freqUART = sysInfo->freqPLB;
+}
+#else
+
+#if !defined(CONFIG_XILINX_440)
+void get_sys_info (sys_info_t * sysInfo)
+{
+	unsigned long strp0;
+	unsigned long strp1;
+	unsigned long temp;
+	unsigned long temp1;
+	unsigned long lfdiv;
+	unsigned long m;
+	unsigned long prbdv0;
+
+#if defined(CONFIG_YUCCA)
+	unsigned long sys_freq;
+	unsigned long sys_per=0;
+	unsigned long msr;
+	unsigned long pci_clock_per;
+	unsigned long sdr_ddrpll;
+
+	/*-------------------------------------------------------------------------+
+	 | Get the system clock period.
+	 +-------------------------------------------------------------------------*/
+	sys_per = determine_sysper();
+
+	msr = (mfmsr () & ~(MSR_EE));	/* disable interrupts */
+
+	/*-------------------------------------------------------------------------+
+	 | Calculate the system clock speed from the period.
+	 +-------------------------------------------------------------------------*/
+	sys_freq = (ONE_BILLION / sys_per) * 1000;
+#endif
+
+	/* Extract configured divisors */
+	mfsdr( SDR0_SDSTP0,strp0 );
+	mfsdr( SDR0_SDSTP1,strp1 );
+
+	temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 8);
+	sysInfo->pllFwdDivA = temp ? temp : 16 ;
+	temp = ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 5);
+	sysInfo->pllFwdDivB = temp ? temp: 8 ;
+	temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 12;
+	sysInfo->pllFbkDiv = temp ? temp : 32;
+	temp = (strp0 & PLLSYS0_OPB_DIV_MASK);
+	sysInfo->pllOpbDiv = temp ? temp : 4;
+	temp = (strp1 & PLLSYS1_PERCLK_DIV_MASK) >> 24;
+	sysInfo->pllExtBusDiv = temp ? temp : 4;
+	prbdv0 = (strp0 >> 2) & 0x7;
+
+	/* Calculate 'M' based on feedback source */
+	temp = (strp0 & PLLSYS0_SEL_MASK) >> 27;
+	temp1 = (strp1 & PLLSYS1_LF_DIV_MASK) >> 26;
+	lfdiv = temp1 ? temp1 : 64;
+	if (temp == 0) { /* PLL output */
+		/* Figure which pll to use */
+		temp = (strp0 & PLLSYS0_SRC_MASK) >> 30;
+		if (!temp)
+			m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
+		else
+			m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
+	}
+	else if (temp == 1) /* CPU output */
+		m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
+	else /* PerClk */
+		m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
+
+	/* Now calculate the individual clocks */
+#if defined(CONFIG_YUCCA)
+	sysInfo->freqVCOMhz = (m * sys_freq) ;
+#else
+	sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1);
+#endif
+	sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
+	sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
+	sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
+	sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
+
+#if defined(CONFIG_YUCCA)
+	/* Determine PCI Clock Period */
+	pci_clock_per = determine_pci_clock_per();
+	sysInfo->freqPCI = (ONE_BILLION/pci_clock_per) * 1000;
+	mfsdr(SDR0_DDR0, sdr_ddrpll);
+	sysInfo->freqDDR = ((sysInfo->freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll));
+#endif
+
+	sysInfo->freqUART = sysInfo->freqPLB;
+}
+
+#endif
+#endif /* CONFIG_XILINX_440 */
+
+#if defined(CONFIG_YUCCA)
+unsigned long determine_sysper(void)
+{
+	unsigned int fpga_clocking_reg;
+	unsigned int master_clock_selection;
+	unsigned long master_clock_per = 0;
+	unsigned long fb_div_selection;
+	unsigned int vco_div_reg_value;
+	unsigned long vco_div_selection;
+	unsigned long sys_per = 0;
+	int extClkVal;
+
+	/*-------------------------------------------------------------------------+
+	 | Read FPGA reg 0 and reg 1 to get FPGA reg information
+	 +-------------------------------------------------------------------------*/
+	fpga_clocking_reg = in16(FPGA_REG16);
+
+
+	/* Determine Master Clock Source Selection */
+	master_clock_selection = fpga_clocking_reg & FPGA_REG16_MASTER_CLK_MASK;
+
+	switch(master_clock_selection) {
+		case FPGA_REG16_MASTER_CLK_66_66:
+			master_clock_per = PERIOD_66_66MHZ;
+			break;
+		case FPGA_REG16_MASTER_CLK_50:
+			master_clock_per = PERIOD_50_00MHZ;
+			break;
+		case FPGA_REG16_MASTER_CLK_33_33:
+			master_clock_per = PERIOD_33_33MHZ;
+			break;
+		case FPGA_REG16_MASTER_CLK_25:
+			master_clock_per = PERIOD_25_00MHZ;
+			break;
+		case FPGA_REG16_MASTER_CLK_EXT:
+			if ((extClkVal==EXTCLK_33_33)
+					&& (extClkVal==EXTCLK_50)
+					&& (extClkVal==EXTCLK_66_66)
+					&& (extClkVal==EXTCLK_83)) {
+				/* calculate master clock period from external clock value */
+				master_clock_per=(ONE_BILLION/extClkVal) * 1000;
+			} else {
+				/* Unsupported */
+				DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
+				hang();
+			}
+			break;
+		default:
+			/* Unsupported */
+			DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
+			hang();
+			break;
+	}
+
+	/* Determine FB divisors values */
+	if ((fpga_clocking_reg & FPGA_REG16_FB1_DIV_MASK) == FPGA_REG16_FB1_DIV_LOW) {
+		if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
+			fb_div_selection = FPGA_FB_DIV_6;
+		else
+			fb_div_selection = FPGA_FB_DIV_12;
+	} else {
+		if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
+			fb_div_selection = FPGA_FB_DIV_10;
+		else
+			fb_div_selection = FPGA_FB_DIV_20;
+	}
+
+	/* Determine VCO divisors values */
+	vco_div_reg_value = fpga_clocking_reg & FPGA_REG16_VCO_DIV_MASK;
+
+	switch(vco_div_reg_value) {
+		case FPGA_REG16_VCO_DIV_4:
+			vco_div_selection = FPGA_VCO_DIV_4;
+			break;
+		case FPGA_REG16_VCO_DIV_6:
+			vco_div_selection = FPGA_VCO_DIV_6;
+			break;
+		case FPGA_REG16_VCO_DIV_8:
+			vco_div_selection = FPGA_VCO_DIV_8;
+			break;
+		case FPGA_REG16_VCO_DIV_10:
+		default:
+			vco_div_selection = FPGA_VCO_DIV_10;
+			break;
+	}
+
+	if (master_clock_selection == FPGA_REG16_MASTER_CLK_EXT) {
+		switch(master_clock_per) {
+			case PERIOD_25_00MHZ:
+				if (fb_div_selection == FPGA_FB_DIV_12) {
+					if (vco_div_selection == FPGA_VCO_DIV_4)
+						sys_per = PERIOD_75_00MHZ;
+					if (vco_div_selection == FPGA_VCO_DIV_6)
+						sys_per = PERIOD_50_00MHZ;
+				}
+				break;
+			case PERIOD_33_33MHZ:
+				if (fb_div_selection == FPGA_FB_DIV_6) {
+					if (vco_div_selection == FPGA_VCO_DIV_4)
+						sys_per = PERIOD_50_00MHZ;
+					if (vco_div_selection == FPGA_VCO_DIV_6)
+						sys_per = PERIOD_33_33MHZ;
+				}
+				if (fb_div_selection == FPGA_FB_DIV_10) {
+					if (vco_div_selection == FPGA_VCO_DIV_4)
+						sys_per = PERIOD_83_33MHZ;
+					if (vco_div_selection == FPGA_VCO_DIV_10)
+						sys_per = PERIOD_33_33MHZ;
+				}
+				if (fb_div_selection == FPGA_FB_DIV_12) {
+					if (vco_div_selection == FPGA_VCO_DIV_4)
+						sys_per = PERIOD_100_00MHZ;
+					if (vco_div_selection == FPGA_VCO_DIV_6)
+						sys_per = PERIOD_66_66MHZ;
+					if (vco_div_selection == FPGA_VCO_DIV_8)
+						sys_per = PERIOD_50_00MHZ;
+				}
+				break;
+			case PERIOD_50_00MHZ:
+				if (fb_div_selection == FPGA_FB_DIV_6) {
+					if (vco_div_selection == FPGA_VCO_DIV_4)
+						sys_per = PERIOD_75_00MHZ;
+					if (vco_div_selection == FPGA_VCO_DIV_6)
+						sys_per = PERIOD_50_00MHZ;
+				}
+				if (fb_div_selection == FPGA_FB_DIV_10) {
+					if (vco_div_selection == FPGA_VCO_DIV_6)
+						sys_per = PERIOD_83_33MHZ;
+					if (vco_div_selection == FPGA_VCO_DIV_10)
+						sys_per = PERIOD_50_00MHZ;
+				}
+				if (fb_div_selection == FPGA_FB_DIV_12) {
+					if (vco_div_selection == FPGA_VCO_DIV_6)
+						sys_per = PERIOD_100_00MHZ;
+					if (vco_div_selection == FPGA_VCO_DIV_8)
+						sys_per = PERIOD_75_00MHZ;
+				}
+				break;
+			case PERIOD_66_66MHZ:
+				if (fb_div_selection == FPGA_FB_DIV_6) {
+					if (vco_div_selection == FPGA_VCO_DIV_4)
+						sys_per = PERIOD_100_00MHZ;
+					if (vco_div_selection == FPGA_VCO_DIV_6)
+						sys_per = PERIOD_66_66MHZ;
+					if (vco_div_selection == FPGA_VCO_DIV_8)
+						sys_per = PERIOD_50_00MHZ;
+				}
+				if (fb_div_selection == FPGA_FB_DIV_10) {
+					if (vco_div_selection == FPGA_VCO_DIV_8)
+						sys_per = PERIOD_83_33MHZ;
+					if (vco_div_selection == FPGA_VCO_DIV_10)
+						sys_per = PERIOD_66_66MHZ;
+				}
+				if (fb_div_selection == FPGA_FB_DIV_12) {
+					if (vco_div_selection == FPGA_VCO_DIV_8)
+						sys_per = PERIOD_100_00MHZ;
+				}
+				break;
+			default:
+				break;
+		}
+
+		if (sys_per == 0) {
+			/* Other combinations are not supported */
+			DEBUGF ("%s[%d] *** sys period compute failed ***\n", __FUNCTION__,__LINE__);
+			hang();
+		}
+	} else {
+		/* calcul system clock without cheking */
+		/* if engineering option clock no check is selected */
+		/* sys_per = master_clock_per * vco_div_selection / fb_div_selection */
+		sys_per = (master_clock_per/fb_div_selection) * vco_div_selection;
+	}
+
+	return(sys_per);
+}
+
+/*-------------------------------------------------------------------------+
+| determine_pci_clock_per.
++-------------------------------------------------------------------------*/
+unsigned long determine_pci_clock_per(void)
+{
+	unsigned long pci_clock_selection,  pci_period;
+
+	/*-------------------------------------------------------------------------+
+	 | Read FPGA reg 6 to get PCI 0 FPGA reg information
+	 +-------------------------------------------------------------------------*/
+	pci_clock_selection = in16(FPGA_REG16);	/* was reg6 averifier */
+
+
+	pci_clock_selection = pci_clock_selection & FPGA_REG16_PCI0_CLK_MASK;
+
+	switch (pci_clock_selection) {
+		case FPGA_REG16_PCI0_CLK_133_33:
+			pci_period = PERIOD_133_33MHZ;
+			break;
+		case FPGA_REG16_PCI0_CLK_100:
+			pci_period = PERIOD_100_00MHZ;
+			break;
+		case FPGA_REG16_PCI0_CLK_66_66:
+			pci_period = PERIOD_66_66MHZ;
+			break;
+		default:
+			pci_period = PERIOD_33_33MHZ;;
+			break;
+	}
+
+	return(pci_period);
+}
+#endif
+
+#elif defined(CONFIG_XILINX_405)
+extern void get_sys_info (sys_info_t * sysInfo);
+extern ulong get_PCI_freq (void);
+
+#elif defined(CONFIG_AP1000)
+void get_sys_info (sys_info_t * sysInfo)
+{
+	sysInfo->freqProcessor = 240 * 1000 * 1000;
+	sysInfo->freqPLB = 80 * 1000 * 1000;
+	sysInfo->freqPCI = 33 * 1000 * 1000;
+}
+
+#elif defined(CONFIG_405)
+
+void get_sys_info (sys_info_t * sysInfo)
+{
+	sysInfo->freqVCOMhz=3125000;
+	sysInfo->freqProcessor=12*1000*1000;
+	sysInfo->freqPLB=50*1000*1000;
+	sysInfo->freqPCI=66*1000*1000;
+}
+
+#elif defined(CONFIG_405EP)
+void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
+{
+	unsigned long pllmr0;
+	unsigned long pllmr1;
+	unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
+	unsigned long m;
+	unsigned long pllmr0_ccdv;
+
+	/*
+	 * Read PLL Mode registers
+	 */
+	pllmr0 = mfdcr (CPC0_PLLMR0);
+	pllmr1 = mfdcr (CPC0_PLLMR1);
+
+	/*
+	 * Determine forward divider A
+	 */
+	sysInfo->pllFwdDiv = 8 - ((pllmr1 & PLLMR1_FWDVA_MASK) >> 16);
+
+	/*
+	 * Determine forward divider B (should be equal to A)
+	 */
+	sysInfo->pllFwdDivB = 8 - ((pllmr1 & PLLMR1_FWDVB_MASK) >> 12);
+
+	/*
+	 * Determine FBK_DIV.
+	 */
+	sysInfo->pllFbkDiv = ((pllmr1 & PLLMR1_FBMUL_MASK) >> 20);
+	if (sysInfo->pllFbkDiv == 0)
+		sysInfo->pllFbkDiv = 16;
+
+	/*
+	 * Determine PLB_DIV.
+	 */
+	sysInfo->pllPlbDiv = ((pllmr0 & PLLMR0_CPU_TO_PLB_MASK) >> 16) + 1;
+
+	/*
+	 * Determine PCI_DIV.
+	 */
+	sysInfo->pllPciDiv = (pllmr0 & PLLMR0_PCI_TO_PLB_MASK) + 1;
+
+	/*
+	 * Determine EXTBUS_DIV.
+	 */
+	sysInfo->pllExtBusDiv = ((pllmr0 & PLLMR0_EXB_TO_PLB_MASK) >> 8) + 2;
+
+	/*
+	 * Determine OPB_DIV.
+	 */
+	sysInfo->pllOpbDiv = ((pllmr0 & PLLMR0_OPB_TO_PLB_MASK) >> 12) + 1;
+
+	/*
+	 * Determine the M factor
+	 */
+	m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
+
+	/*
+	 * Determine VCO clock frequency
+	 */
+	sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
+		(unsigned long long)sysClkPeriodPs;
+
+	/*
+	 * Determine CPU clock frequency
+	 */
+	pllmr0_ccdv = ((pllmr0 & PLLMR0_CPU_DIV_MASK) >> 20) + 1;
+	if (pllmr1 & PLLMR1_SSCS_MASK) {
+		/*
+		 * This is true if FWDVA == FWDVB:
+		 * sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv)
+		 *	/ pllmr0_ccdv;
+		 */
+		sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv * sysInfo->pllFwdDivB)
+			/ sysInfo->pllFwdDiv / pllmr0_ccdv;
+	} else {
+		sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ / pllmr0_ccdv;
+	}
+
+	/*
+	 * Determine PLB clock frequency
+	 */
+	sysInfo->freqPLB = sysInfo->freqProcessor / sysInfo->pllPlbDiv;
+
+	sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv;
+
+	sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
+
+	sysInfo->freqUART = sysInfo->freqProcessor * pllmr0_ccdv;
+}
+
+
+/********************************************
+ * get_PCI_freq
+ * return PCI bus freq in Hz
+ *********************************************/
+ulong get_PCI_freq (void)
+{
+	ulong val;
+	PPC4xx_SYS_INFO sys_info;
+
+	get_sys_info (&sys_info);
+	val = sys_info.freqPLB / sys_info.pllPciDiv;
+	return val;
+}
+
+#elif defined(CONFIG_405EZ)
+void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
+{
+	unsigned long cpr_plld;
+	unsigned long cpr_pllc;
+	unsigned long cpr_primad;
+	unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ/1000);
+	unsigned long primad_cpudv;
+	unsigned long m;
+	unsigned long plloutb;
+
+	/*
+	 * Read PLL Mode registers
+	 */
+	mfcpr(CPR0_PLLD, cpr_plld);
+	mfcpr(CPR0_PLLC, cpr_pllc);
+
+	/*
+	 * Determine forward divider A
+	 */
+	sysInfo->pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16);
+
+	/*
+	 * Determine forward divider B
+	 */
+	sysInfo->pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8);
+	if (sysInfo->pllFwdDivB == 0)
+		sysInfo->pllFwdDivB = 8;
+
+	/*
+	 * Determine FBK_DIV.
+	 */
+	sysInfo->pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24);
+	if (sysInfo->pllFbkDiv == 0)
+		sysInfo->pllFbkDiv = 256;
+
+	/*
+	 * Read CPR_PRIMAD register
+	 */
+	mfcpr(CPC0_PRIMAD, cpr_primad);
+
+	/*
+	 * Determine PLB_DIV.
+	 */
+	sysInfo->pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16);
+	if (sysInfo->pllPlbDiv == 0)
+		sysInfo->pllPlbDiv = 16;
+
+	/*
+	 * Determine EXTBUS_DIV.
+	 */
+	sysInfo->pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK);
+	if (sysInfo->pllExtBusDiv == 0)
+		sysInfo->pllExtBusDiv = 16;
+
+	/*
+	 * Determine OPB_DIV.
+	 */
+	sysInfo->pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8);
+	if (sysInfo->pllOpbDiv == 0)
+		sysInfo->pllOpbDiv = 16;
+
+	/*
+	 * Determine the M factor
+	 */
+	if (cpr_pllc & PLLC_SRC_MASK)
+		m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
+	else
+		m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
+
+	/*
+	 * Determine VCO clock frequency
+	 */
+	sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
+		(unsigned long long)sysClkPeriodPs;
+
+	/*
+	 * Determine CPU clock frequency
+	 */
+	primad_cpudv = ((cpr_primad & PRIMAD_CPUDV_MASK) >> 24);
+	if (primad_cpudv == 0)
+		primad_cpudv = 16;
+
+	sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * m) /
+		sysInfo->pllFwdDiv / primad_cpudv;
+
+	/*
+	 * Determine PLB clock frequency
+	 */
+	sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * m) /
+		sysInfo->pllFwdDiv / sysInfo->pllPlbDiv;
+
+	sysInfo->freqOPB = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) /
+		sysInfo->pllOpbDiv;
+
+	sysInfo->freqEBC = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) /
+		sysInfo->pllExtBusDiv;
+
+	plloutb = ((CONFIG_SYS_CLK_FREQ * ((cpr_pllc & PLLC_SRC_MASK) ?
+		sysInfo->pllFwdDivB : sysInfo->pllFwdDiv) * sysInfo->pllFbkDiv) /
+		sysInfo->pllFwdDivB);
+	sysInfo->freqUART = plloutb;
+}
+
+#elif defined(CONFIG_405EX)
+
+/*
+ * TODO: We need to get the CPR registers and calculate these values correctly!!!!
+ *   We need the specs!!!!
+ */
+static unsigned char get_fbdv(unsigned char index)
+{
+	unsigned char ret = 0;
+	/* This is table should be 256 bytes.
+	 * Only take first 52 values.
+	 */
+	unsigned char fbdv_tb[] = {
+		0x00, 0xff, 0x7f, 0xfd,
+		0x7a, 0xf5, 0x6a, 0xd5,
+		0x2a, 0xd4, 0x29, 0xd3,
+		0x26, 0xcc, 0x19, 0xb3,
+		0x67, 0xce, 0x1d, 0xbb,
+		0x77, 0xee, 0x5d, 0xba,
+		0x74, 0xe9, 0x52, 0xa5,
+		0x4b, 0x96, 0x2c, 0xd8,
+		0x31, 0xe3, 0x46, 0x8d,
+		0x1b, 0xb7, 0x6f, 0xde,
+		0x3d, 0xfb, 0x76, 0xed,
+		0x5a, 0xb5, 0x6b, 0xd6,
+		0x2d, 0xdb, 0x36, 0xec,
+
+	};
+
+	if ((index & 0x7f) == 0)
+		return 1;
+	while (ret < sizeof (fbdv_tb)) {
+		if (fbdv_tb[ret] == index)
+			break;
+		ret++;
+	}
+	ret++;
+
+	return ret;
+}
+
+#define PLL_FBK_PLL_LOCAL	0
+#define PLL_FBK_CPU		1
+#define PLL_FBK_PERCLK		5
+
+void get_sys_info (sys_info_t * sysInfo)
+{
+	unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
+	unsigned long m = 1;
+	unsigned int  tmp;
+	unsigned char fwdva[16] = {
+		1, 2, 14, 9, 4, 11, 16, 13,
+		12, 5, 6, 15, 10, 7, 8, 3,
+	};
+	unsigned char sel, cpudv0, plb2xDiv;
+
+	mfcpr(CPR0_PLLD, tmp);
+
+	/*
+	 * Determine forward divider A
+	 */
+	sysInfo->pllFwdDiv = fwdva[((tmp >> 16) & 0x0f)];	/* FWDVA */
+
+	/*
+	 * Determine FBK_DIV.
+	 */
+	sysInfo->pllFbkDiv = get_fbdv(((tmp >> 24) & 0x0ff)); /* FBDV */
+
+	/*
+	 * Determine PLBDV0
+	 */
+	sysInfo->pllPlbDiv = 2;
+
+	/*
+	 * Determine PERDV0
+	 */
+	mfcpr(CPR0_PERD, tmp);
+	tmp = (tmp >> 24) & 0x03;
+	sysInfo->pllExtBusDiv = (tmp == 0) ? 4 : tmp;
+
+	/*
+	 * Determine OPBDV0
+	 */
+	mfcpr(CPR0_OPBD0, tmp);
+	tmp = (tmp >> 24) & 0x03;
+	sysInfo->pllOpbDiv = (tmp == 0) ? 4 : tmp;
+
+	/* Determine PLB2XDV0 */
+	mfcpr(CPR0_PLBD, tmp);
+	tmp = (tmp >> 16) & 0x07;
+	plb2xDiv = (tmp == 0) ? 8 : tmp;
+
+	/* Determine CPUDV0 */
+	mfcpr(CPR0_CPUD, tmp);
+	tmp = (tmp >> 24) & 0x07;
+	cpudv0 = (tmp == 0) ? 8 : tmp;
+
+	/* Determine SEL(5:7) in CPR0_PLLC */
+	mfcpr(CPR0_PLLC, tmp);
+	sel = (tmp >> 24) & 0x07;
+
+	/*
+	 * Determine the M factor
+	 * PLL local: M = FBDV
+	 * CPU clock: M = FBDV * FWDVA * CPUDV0
+	 * PerClk	: M = FBDV * FWDVA * PLB2XDV0 * PLBDV0(2) * OPBDV0 * PERDV0
+	 *
+	 */
+	switch (sel) {
+	case PLL_FBK_CPU:
+		m = sysInfo->pllFwdDiv * cpudv0;
+		break;
+	case PLL_FBK_PERCLK:
+		m = sysInfo->pllFwdDiv * plb2xDiv * 2
+			* sysInfo->pllOpbDiv * sysInfo->pllExtBusDiv;
+		break;
+	case PLL_FBK_PLL_LOCAL:
+		break;
+	default:
+		printf("%s unknown m\n", __FUNCTION__);
+		return;
+
+	}
+	m *= sysInfo->pllFbkDiv;
+
+	/*
+	 * Determine VCO clock frequency
+	 */
+	sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
+		(unsigned long long)sysClkPeriodPs;
+
+	/*
+	 * Determine CPU clock frequency
+	 */
+	sysInfo->freqProcessor = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * cpudv0);
+
+	/*
+	 * Determine PLB clock frequency, ddr1x should be the same
+	 */
+	sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * plb2xDiv * 2);
+	sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
+	sysInfo->freqDDR = sysInfo->freqPLB;
+	sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
+	sysInfo->freqUART = sysInfo->freqPLB;
+}
+
+#endif
+
+int get_clocks (void)
+{
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
+    defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
+    defined(CONFIG_405EX) || defined(CONFIG_405) || \
+    defined(CONFIG_440)
+	sys_info_t sys_info;
+
+	get_sys_info (&sys_info);
+	gd->cpu_clk = sys_info.freqProcessor;
+	gd->bus_clk = sys_info.freqPLB;
+
+#endif	/* defined(CONFIG_405GP) || defined(CONFIG_405CR) */
+
+#ifdef CONFIG_IOP480
+	gd->cpu_clk = 66000000;
+	gd->bus_clk = 66000000;
+#endif
+	return (0);
+}
+
+
+/********************************************
+ * get_bus_freq
+ * return PLB bus freq in Hz
+ *********************************************/
+ulong get_bus_freq (ulong dummy)
+{
+	ulong val;
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
+    defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
+    defined(CONFIG_405EX) || defined(CONFIG_405) || \
+    defined(CONFIG_440)
+	sys_info_t sys_info;
+
+	get_sys_info (&sys_info);
+	val = sys_info.freqPLB;
+
+#elif defined(CONFIG_IOP480)
+
+	val = 66;
+
+#else
+# error get_bus_freq() not implemented
+#endif
+
+	return val;
+}
+
+#if !defined(CONFIG_IOP480)
+ulong get_OPB_freq (void)
+{
+	PPC4xx_SYS_INFO sys_info;
+
+	get_sys_info (&sys_info);
+
+	return sys_info.freqOPB;
+}
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/start.S b/arch/powerpc/cpu/ppc4xx/start.S
new file mode 100644
index 0000000..c739deb
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/start.S
@@ -0,0 +1,2170 @@
+/*
+ *  Copyright (C) 1998	Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
+ *  Copyright (C) 2007 Stefan Roese <sr@denx.de>, DENX Software Engineering
+ *  Copyright (c) 2008 Nuovation System Designs, LLC
+ *    Grant Erickson <gerickson@nuovations.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+/*------------------------------------------------------------------------------+
+ *   This source code is dual-licensed.  You may use it under the terms of the
+ *   GNU General Public License version 2, or under the license below.
+ *
+ *	 This source code has been made available to you by IBM on an AS-IS
+ *	 basis.	 Anyone receiving this source is licensed under IBM
+ *	 copyrights to use it in any way he or she deems fit, including
+ *	 copying it, modifying it, compiling it, and redistributing it either
+ *	 with or without modifications.	 No license under IBM patents or
+ *	 patent applications is to be implied by the copyright license.
+ *
+ *	 Any user of this software should understand that IBM cannot provide
+ *	 technical support for this software and will not be responsible for
+ *	 any consequences resulting from the use of this software.
+ *
+ *	 Any person who transfers this source code or any derivative work
+ *	 must include the IBM copyright notice, this paragraph, and the
+ *	 preceding two paragraphs in the transferred software.
+ *
+ *	 COPYRIGHT   I B M   CORPORATION 1995
+ *	 LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
+ *-------------------------------------------------------------------------------
+ */
+
+/*  U-Boot - Startup Code for AMCC 4xx PowerPC based Embedded Boards
+ *
+ *
+ *  The processor starts at 0xfffffffc and the code is executed
+ *  from flash/rom.
+ *  in memory, but as long we don't jump around before relocating.
+ *  board_init lies at a quite high address and when the cpu has
+ *  jumped there, everything is ok.
+ *  This works because the cpu gives the FLASH (CS0) the whole
+ *  address space at startup, and board_init lies as a echo of
+ *  the flash somewhere up there in the memorymap.
+ *
+ *  board_init will change CS0 to be positioned at the correct
+ *  address and (s)dram will be positioned at address 0
+ */
+#include <config.h>
+#include <ppc4xx.h>
+#include <timestamp.h>
+#include <version.h>
+
+#define _LINUX_CONFIG_H 1	/* avoid reading Linux autoconf.h file	*/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <asm/ppc4xx-isram.h>
+
+#ifndef	 CONFIG_IDENT_STRING
+#define	 CONFIG_IDENT_STRING ""
+#endif
+
+#ifdef CONFIG_SYS_INIT_DCACHE_CS
+# if (CONFIG_SYS_INIT_DCACHE_CS == 0)
+#  define PBxAP PB1AP
+#  define PBxCR PB0CR
+#  if (defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR))
+#   define PBxAP_VAL CONFIG_SYS_EBC_PB0AP
+#   define PBxCR_VAL CONFIG_SYS_EBC_PB0CR
+#  endif
+# endif
+# if (CONFIG_SYS_INIT_DCACHE_CS == 1)
+#  define PBxAP PB1AP
+#  define PBxCR PB1CR
+#  if (defined(CONFIG_SYS_EBC_PB1AP) && defined(CONFIG_SYS_EBC_PB1CR))
+#   define PBxAP_VAL CONFIG_SYS_EBC_PB1AP
+#   define PBxCR_VAL CONFIG_SYS_EBC_PB1CR
+#  endif
+# endif
+# if (CONFIG_SYS_INIT_DCACHE_CS == 2)
+#  define PBxAP PB2AP
+#  define PBxCR PB2CR
+#  if (defined(CONFIG_SYS_EBC_PB2AP) && defined(CONFIG_SYS_EBC_PB2CR))
+#   define PBxAP_VAL CONFIG_SYS_EBC_PB2AP
+#   define PBxCR_VAL CONFIG_SYS_EBC_PB2CR
+#  endif
+# endif
+# if (CONFIG_SYS_INIT_DCACHE_CS == 3)
+#  define PBxAP PB3AP
+#  define PBxCR PB3CR
+#  if (defined(CONFIG_SYS_EBC_PB3AP) && defined(CONFIG_SYS_EBC_PB3CR))
+#   define PBxAP_VAL CONFIG_SYS_EBC_PB3AP
+#   define PBxCR_VAL CONFIG_SYS_EBC_PB3CR
+#  endif
+# endif
+# if (CONFIG_SYS_INIT_DCACHE_CS == 4)
+#  define PBxAP PB4AP
+#  define PBxCR PB4CR
+#  if (defined(CONFIG_SYS_EBC_PB4AP) && defined(CONFIG_SYS_EBC_PB4CR))
+#   define PBxAP_VAL CONFIG_SYS_EBC_PB4AP
+#   define PBxCR_VAL CONFIG_SYS_EBC_PB4CR
+#  endif
+# endif
+# if (CONFIG_SYS_INIT_DCACHE_CS == 5)
+#  define PBxAP PB5AP
+#  define PBxCR PB5CR
+#  if (defined(CONFIG_SYS_EBC_PB5AP) && defined(CONFIG_SYS_EBC_PB5CR))
+#   define PBxAP_VAL CONFIG_SYS_EBC_PB5AP
+#   define PBxCR_VAL CONFIG_SYS_EBC_PB5CR
+#  endif
+# endif
+# if (CONFIG_SYS_INIT_DCACHE_CS == 6)
+#  define PBxAP PB6AP
+#  define PBxCR PB6CR
+#  if (defined(CONFIG_SYS_EBC_PB6AP) && defined(CONFIG_SYS_EBC_PB6CR))
+#   define PBxAP_VAL CONFIG_SYS_EBC_PB6AP
+#   define PBxCR_VAL CONFIG_SYS_EBC_PB6CR
+#  endif
+# endif
+# if (CONFIG_SYS_INIT_DCACHE_CS == 7)
+#  define PBxAP PB7AP
+#  define PBxCR PB7CR
+#  if (defined(CONFIG_SYS_EBC_PB7AP) && defined(CONFIG_SYS_EBC_PB7CR))
+#   define PBxAP_VAL CONFIG_SYS_EBC_PB7AP
+#   define PBxCR_VAL CONFIG_SYS_EBC_PB7CR
+#  endif
+# endif
+# ifndef PBxAP_VAL
+#  define PBxAP_VAL	0
+# endif
+# ifndef PBxCR_VAL
+#  define PBxCR_VAL	0
+# endif
+/*
+ * Memory Bank x (nothingness) initialization CONFIG_SYS_INIT_RAM_ADDR + 64 MiB
+ * used as temporary stack pointer for the primordial stack
+ */
+# ifndef CONFIG_SYS_INIT_DCACHE_PBxAR
+#  define CONFIG_SYS_INIT_DCACHE_PBxAR	(EBC_BXAP_BME_DISABLED			| \
+				 EBC_BXAP_TWT_ENCODE(7)			| \
+				 EBC_BXAP_BCE_DISABLE			| \
+				 EBC_BXAP_BCT_2TRANS			| \
+				 EBC_BXAP_CSN_ENCODE(0)			| \
+				 EBC_BXAP_OEN_ENCODE(0)			| \
+				 EBC_BXAP_WBN_ENCODE(0)			| \
+				 EBC_BXAP_WBF_ENCODE(0)			| \
+				 EBC_BXAP_TH_ENCODE(2)			| \
+				 EBC_BXAP_RE_DISABLED			| \
+				 EBC_BXAP_SOR_NONDELAYED		| \
+				 EBC_BXAP_BEM_WRITEONLY			| \
+				 EBC_BXAP_PEN_DISABLED)
+# endif /* CONFIG_SYS_INIT_DCACHE_PBxAR */
+# ifndef CONFIG_SYS_INIT_DCACHE_PBxCR
+#  define CONFIG_SYS_INIT_DCACHE_PBxCR	(EBC_BXCR_BAS_ENCODE(CONFIG_SYS_INIT_RAM_ADDR)	| \
+				 EBC_BXCR_BS_64MB			| \
+				 EBC_BXCR_BU_RW				| \
+				 EBC_BXCR_BW_16BIT)
+# endif /* CONFIG_SYS_INIT_DCACHE_PBxCR */
+# ifndef CONFIG_SYS_INIT_RAM_PATTERN
+#  define CONFIG_SYS_INIT_RAM_PATTERN	0xDEADDEAD
+# endif
+#endif /* CONFIG_SYS_INIT_DCACHE_CS */
+
+#if (defined(CONFIG_SYS_INIT_RAM_DCACHE) && (CONFIG_SYS_INIT_RAM_END > (4 << 10)))
+#error Only 4k of init-ram is supported - please adjust CONFIG_SYS_INIT_RAM_END!
+#endif
+
+/*
+ * Unless otherwise overriden, enable two 128MB cachable instruction regions
+ * at CONFIG_SYS_SDRAM_BASE and another 128MB cacheable instruction region covering
+ * NOR flash at CONFIG_SYS_FLASH_BASE. Disable all cacheable data regions.
+ */
+#if !defined(CONFIG_SYS_FLASH_BASE)
+/* If not already defined, set it to the "last" 128MByte region */
+# define CONFIG_SYS_FLASH_BASE		0xf8000000
+#endif
+#if !defined(CONFIG_SYS_ICACHE_SACR_VALUE)
+# define CONFIG_SYS_ICACHE_SACR_VALUE		\
+		(PPC_128MB_SACR_VALUE(CONFIG_SYS_SDRAM_BASE + (  0 << 20)) | \
+		 PPC_128MB_SACR_VALUE(CONFIG_SYS_SDRAM_BASE + (128 << 20)) | \
+		 PPC_128MB_SACR_VALUE(CONFIG_SYS_FLASH_BASE))
+#endif /* !defined(CONFIG_SYS_ICACHE_SACR_VALUE) */
+
+#if !defined(CONFIG_SYS_DCACHE_SACR_VALUE)
+# define CONFIG_SYS_DCACHE_SACR_VALUE		\
+		(0x00000000)
+#endif /* !defined(CONFIG_SYS_DCACHE_SACR_VALUE) */
+
+#define function_prolog(func_name)	.text; \
+					.align 2; \
+					.globl func_name; \
+					func_name:
+#define function_epilog(func_name)	.type func_name,@function; \
+					.size func_name,.-func_name
+
+/* We don't want the  MMU yet.
+*/
+#undef	MSR_KERNEL
+#define MSR_KERNEL ( MSR_ME  )	/* Machine Check */
+
+
+	.extern ext_bus_cntlr_init
+#ifdef CONFIG_NAND_U_BOOT
+	.extern reconfig_tlb0
+#endif
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+#if !defined(CONFIG_NAND_SPL)
+	START_GOT
+	GOT_ENTRY(_GOT2_TABLE_)
+	GOT_ENTRY(_FIXUP_TABLE_)
+
+	GOT_ENTRY(_start)
+	GOT_ENTRY(_start_of_vectors)
+	GOT_ENTRY(_end_of_vectors)
+	GOT_ENTRY(transfer_to_handler)
+
+	GOT_ENTRY(__init_end)
+	GOT_ENTRY(_end)
+	GOT_ENTRY(__bss_start)
+	END_GOT
+#endif /* CONFIG_NAND_SPL */
+
+#if defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+	/*
+	 * NAND U-Boot image is started from offset 0
+	 */
+	.text
+#if defined(CONFIG_440)
+	bl	reconfig_tlb0
+#endif
+	GET_GOT
+	bl	cpu_init_f	/* run low-level CPU init code	   (from Flash) */
+	bl	board_init_f
+#endif
+
+#if defined(CONFIG_SYS_RAMBOOT)
+	/*
+	 * 4xx RAM-booting U-Boot image is started from offset 0
+	 */
+	.text
+	bl	_start_440
+#endif
+
+/*
+ * 440 Startup -- on reset only the top 4k of the effective
+ * address space is mapped in by an entry in the instruction
+ * and data shadow TLB. The .bootpg section is located in the
+ * top 4k & does only what's necessary to map in the the rest
+ * of the boot rom. Once the boot rom is mapped in we can
+ * proceed with normal startup.
+ *
+ * NOTE: CS0 only covers the top 2MB of the effective address
+ * space after reset.
+ */
+
+#if defined(CONFIG_440)
+#if !defined(CONFIG_NAND_SPL)
+    .section .bootpg,"ax"
+#endif
+    .globl _start_440
+
+/**************************************************************************/
+_start_440:
+	/*--------------------------------------------------------------------+
+	| 440EPX BUP Change - Hardware team request
+	+--------------------------------------------------------------------*/
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+	sync
+	nop
+	nop
+#endif
+	/*----------------------------------------------------------------+
+	| Core bug fix.  Clear the esr
+	+-----------------------------------------------------------------*/
+	li	r0,0
+	mtspr	SPRN_ESR,r0
+	/*----------------------------------------------------------------*/
+	/* Clear and set up some registers. */
+	/*----------------------------------------------------------------*/
+	iccci	r0,r0		/* NOTE: operands not used for 440 */
+	dccci	r0,r0		/* NOTE: operands not used for 440 */
+	sync
+	li	r0,0
+	mtspr	SPRN_SRR0,r0
+	mtspr	SPRN_SRR1,r0
+	mtspr	SPRN_CSRR0,r0
+	mtspr	SPRN_CSRR1,r0
+	/* NOTE: 440GX adds machine check status regs */
+#if defined(CONFIG_440) && !defined(CONFIG_440GP)
+	mtspr	SPRN_MCSRR0,r0
+	mtspr	SPRN_MCSRR1,r0
+	mfspr	r1,SPRN_MCSR
+	mtspr	SPRN_MCSR,r1
+#endif
+
+	/*----------------------------------------------------------------*/
+	/* CCR0 init */
+	/*----------------------------------------------------------------*/
+	/* Disable store gathering & broadcast, guarantee inst/data
+	* cache block touch, force load/store alignment
+	* (see errata 1.12: 440_33)
+	*/
+	lis	r1,0x0030	/* store gathering & broadcast disable */
+	ori	r1,r1,0x6000	/* cache touch */
+	mtspr	SPRN_CCR0,r1
+
+	/*----------------------------------------------------------------*/
+	/* Initialize debug */
+	/*----------------------------------------------------------------*/
+	mfspr	r1,SPRN_DBCR0
+	andis.	r1, r1, 0x8000	/* test DBCR0[EDM] bit			*/
+	bne	skip_debug_init	/* if set, don't clear debug register	*/
+	mtspr	SPRN_DBCR0,r0
+	mtspr	SPRN_DBCR1,r0
+	mtspr	SPRN_DBCR2,r0
+	mtspr	SPRN_IAC1,r0
+	mtspr	SPRN_IAC2,r0
+	mtspr	SPRN_IAC3,r0
+	mtspr	SPRN_DAC1,r0
+	mtspr	SPRN_DAC2,r0
+	mtspr	SPRN_DVC1,r0
+	mtspr	SPRN_DVC2,r0
+
+	mfspr	r1,SPRN_DBSR
+	mtspr	SPRN_DBSR,r1	/* Clear all valid bits */
+skip_debug_init:
+
+#if defined (CONFIG_440SPE)
+	/*----------------------------------------------------------------+
+	| Initialize Core Configuration Reg1.
+	| a. ICDPEI: Record even parity. Normal operation.
+	| b. ICTPEI: Record even parity. Normal operation.
+	| c. DCTPEI: Record even parity. Normal operation.
+	| d. DCDPEI: Record even parity. Normal operation.
+	| e. DCUPEI: Record even parity. Normal operation.
+	| f. DCMPEI: Record even parity. Normal operation.
+	| g. FCOM:   Normal operation
+	| h. MMUPEI: Record even parity. Normal operation.
+	| i. FFF:    Flush only as much data as necessary.
+	| j. TCS:    Timebase increments from CPU clock.
+	+-----------------------------------------------------------------*/
+	li	r0,0
+	mtspr	SPRN_CCR1, r0
+
+	/*----------------------------------------------------------------+
+	| Reset the timebase.
+	| The previous write to CCR1 sets the timebase source.
+	+-----------------------------------------------------------------*/
+	mtspr	SPRN_TBWL, r0
+	mtspr	SPRN_TBWU, r0
+#endif
+
+	/*----------------------------------------------------------------*/
+	/* Setup interrupt vectors */
+	/*----------------------------------------------------------------*/
+	mtspr	SPRN_IVPR,r0		/* Vectors start at 0x0000_0000 */
+	li	r1,0x0100
+	mtspr	SPRN_IVOR0,r1	/* Critical input */
+	li	r1,0x0200
+	mtspr	SPRN_IVOR1,r1	/* Machine check */
+	li	r1,0x0300
+	mtspr	SPRN_IVOR2,r1	/* Data storage */
+	li	r1,0x0400
+	mtspr	SPRN_IVOR3,r1	/* Instruction storage */
+	li	r1,0x0500
+	mtspr	SPRN_IVOR4,r1	/* External interrupt */
+	li	r1,0x0600
+	mtspr	SPRN_IVOR5,r1	/* Alignment */
+	li	r1,0x0700
+	mtspr	SPRN_IVOR6,r1	/* Program check */
+	li	r1,0x0800
+	mtspr	SPRN_IVOR7,r1	/* Floating point unavailable */
+	li	r1,0x0c00
+	mtspr	SPRN_IVOR8,r1	/* System call */
+	li	r1,0x0a00
+	mtspr	SPRN_IVOR9,r1	/* Auxiliary Processor unavailable */
+	li	r1,0x0900
+	mtspr	SPRN_IVOR10,r1	/* Decrementer */
+	li	r1,0x1300
+	mtspr	SPRN_IVOR13,r1	/* Data TLB error */
+	li	r1,0x1400
+	mtspr	SPRN_IVOR14,r1	/* Instr TLB error */
+	li	r1,0x2000
+	mtspr	SPRN_IVOR15,r1	/* Debug */
+
+	/*----------------------------------------------------------------*/
+	/* Configure cache regions  */
+	/*----------------------------------------------------------------*/
+	mtspr	SPRN_INV0,r0
+	mtspr	SPRN_INV1,r0
+	mtspr	SPRN_INV2,r0
+	mtspr	SPRN_INV3,r0
+	mtspr	SPRN_DNV0,r0
+	mtspr	SPRN_DNV1,r0
+	mtspr	SPRN_DNV2,r0
+	mtspr	SPRN_DNV3,r0
+	mtspr	SPRN_ITV0,r0
+	mtspr	SPRN_ITV1,r0
+	mtspr	SPRN_ITV2,r0
+	mtspr	SPRN_ITV3,r0
+	mtspr	SPRN_DTV0,r0
+	mtspr	SPRN_DTV1,r0
+	mtspr	SPRN_DTV2,r0
+	mtspr	SPRN_DTV3,r0
+
+	/*----------------------------------------------------------------*/
+	/* Cache victim limits */
+	/*----------------------------------------------------------------*/
+	/* floors 0, ceiling max to use the entire cache -- nothing locked
+	*/
+	lis	r1,0x0001
+	ori	r1,r1,0xf800
+	mtspr	SPRN_IVLIM,r1
+	mtspr	SPRN_DVLIM,r1
+
+	/*----------------------------------------------------------------+
+	|Initialize MMUCR[STID] = 0.
+	+-----------------------------------------------------------------*/
+	mfspr	r0,SPRN_MMUCR
+	addis	r1,0,0xFFFF
+	ori	r1,r1,0xFF00
+	and	r0,r0,r1
+	mtspr	SPRN_MMUCR,r0
+
+	/*----------------------------------------------------------------*/
+	/* Clear all TLB entries -- TID = 0, TS = 0 */
+	/*----------------------------------------------------------------*/
+	addis	r0,0,0x0000
+#ifdef CONFIG_SYS_RAMBOOT
+	li	r4,0		/* Start with TLB #0 */
+#else
+	li	r4,1		/* Start with TLB #1 */
+#endif
+	li	r1,64		/* 64 TLB entries */
+	sub	r1,r1,r4	/* calculate last TLB # */
+	mtctr	r1
+rsttlb:
+#ifdef CONFIG_SYS_RAMBOOT
+	tlbre	r3,r4,0		/* Read contents from TLB word #0 to get EPN */
+	rlwinm.	r3,r3,0,0xfffffc00	/* Mask EPN */
+	beq	tlbnxt		/* Skip EPN=0 TLB, this is the SDRAM TLB */
+#endif
+	tlbwe	r0,r4,0		/* Invalidate all entries (V=0)*/
+	tlbwe	r0,r4,1
+	tlbwe	r0,r4,2
+tlbnxt:	addi	r4,r4,1		/* Next TLB */
+	bdnz	rsttlb
+
+	/*----------------------------------------------------------------*/
+	/* TLB entry setup -- step thru tlbtab */
+	/*----------------------------------------------------------------*/
+#if defined(CONFIG_440SPE_REVA)
+	/*----------------------------------------------------------------*/
+	/* We have different TLB tables for revA and rev B of 440SPe */
+	/*----------------------------------------------------------------*/
+	mfspr	r1, PVR
+	lis	r0,0x5342
+	ori	r0,r0,0x1891
+	cmpw	r7,r1,r0
+	bne	r7,..revA
+	bl	tlbtabB
+	b	..goon
+..revA:
+	bl	tlbtabA
+..goon:
+#else
+	bl	tlbtab		/* Get tlbtab pointer */
+#endif
+	mr	r5,r0
+	li	r1,0x003f	/* 64 TLB entries max */
+	mtctr	r1
+	li	r4,0		/* TLB # */
+
+	addi	r5,r5,-4
+1:
+#ifdef CONFIG_SYS_RAMBOOT
+	tlbre	r3,r4,0		/* Read contents from TLB word #0 */
+	rlwinm.	r3,r3,0,0x00000200	/* Mask V (valid) bit */
+	bne	tlbnx2		/* Skip V=1 TLB, this is the SDRAM TLB */
+#endif
+	lwzu	r0,4(r5)
+	cmpwi	r0,0
+	beq	2f		/* 0 marks end */
+	lwzu	r1,4(r5)
+	lwzu	r2,4(r5)
+	tlbwe	r0,r4,0		/* TLB Word 0 */
+	tlbwe	r1,r4,1		/* TLB Word 1 */
+	tlbwe	r2,r4,2		/* TLB Word 2 */
+tlbnx2:	addi	r4,r4,1		/* Next TLB */
+	bdnz	1b
+
+	/*----------------------------------------------------------------*/
+	/* Continue from 'normal' start */
+	/*----------------------------------------------------------------*/
+2:
+	bl	3f
+	b	_start
+
+3:	li	r0,0
+	mtspr	SPRN_SRR1,r0		/* Keep things disabled for now */
+	mflr	r1
+	mtspr	SPRN_SRR0,r1
+	rfi
+#endif /* CONFIG_440 */
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+#ifndef CONFIG_NAND_SPL
+	.text
+	.long	0x27051956		/* U-Boot Magic Number			*/
+	.globl	version_string
+version_string:
+	.ascii U_BOOT_VERSION
+	.ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
+	.ascii CONFIG_IDENT_STRING, "\0"
+
+	. = EXC_OFF_SYS_RESET
+	.globl	_start_of_vectors
+_start_of_vectors:
+
+/* Critical input. */
+	CRIT_EXCEPTION(0x100, CritcalInput, UnknownException)
+
+#ifdef CONFIG_440
+/* Machine check */
+	MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+#else
+	CRIT_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+#endif /* CONFIG_440 */
+
+/* Data Storage exception. */
+	STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+	STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+	STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+	. = 0x600
+Alignment:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	mfspr	r4,DAR
+	stw	r4,_DAR(r21)
+	mfspr	r5,DSISR
+	stw	r5,_DSISR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+	. = 0x700
+ProgramCheck:
+	EXCEPTION_PROLOG(SRR0, SRR1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+		MSR_KERNEL, COPY_EE)
+
+#ifdef CONFIG_440
+	STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+	STD_EXCEPTION(0x900, Decrementer, DecrementerPITException)
+	STD_EXCEPTION(0xa00, APU, UnknownException)
+#endif
+	STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+
+#ifdef CONFIG_440
+	STD_EXCEPTION(0x1300, DataTLBError, UnknownException)
+	STD_EXCEPTION(0x1400, InstructionTLBError, UnknownException)
+#else
+	STD_EXCEPTION(0x1000, PIT, DecrementerPITException)
+	STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+	STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+#endif
+	CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException )
+
+	.globl	_end_of_vectors
+_end_of_vectors:
+	. = _START_OFFSET
+#endif
+	.globl	_start
+_start:
+
+/*****************************************************************************/
+#if defined(CONFIG_440)
+
+	/*----------------------------------------------------------------*/
+	/* Clear and set up some registers. */
+	/*----------------------------------------------------------------*/
+	li	r0,0x0000
+	lis	r1,0xffff
+	mtspr	SPRN_DEC,r0			/* prevent dec exceptions */
+	mtspr	SPRN_TBWL,r0			/* prevent fit & wdt exceptions */
+	mtspr	SPRN_TBWU,r0
+	mtspr	SPRN_TSR,r1			/* clear all timer exception status */
+	mtspr	SPRN_TCR,r0			/* disable all */
+	mtspr	SPRN_ESR,r0			/* clear exception syndrome register */
+	mtxer	r0			/* clear integer exception register */
+
+	/*----------------------------------------------------------------*/
+	/* Debug setup -- some (not very good) ice's need an event*/
+	/* to establish control :-( Define CONFIG_SYS_INIT_DBCR to the dbsr */
+	/* value you need in this case 0x8cff 0000 should do the trick */
+	/*----------------------------------------------------------------*/
+#if defined(CONFIG_SYS_INIT_DBCR)
+	lis	r1,0xffff
+	ori	r1,r1,0xffff
+	mtspr	SPRN_DBSR,r1			/* Clear all status bits */
+	lis	r0,CONFIG_SYS_INIT_DBCR@h
+	ori	r0,r0,CONFIG_SYS_INIT_DBCR@l
+	mtspr	SPRN_DBCR0,r0
+	isync
+#endif
+
+	/*----------------------------------------------------------------*/
+	/* Setup the internal SRAM */
+	/*----------------------------------------------------------------*/
+	li	r0,0
+
+#ifdef CONFIG_SYS_INIT_RAM_DCACHE
+	/* Clear Dcache to use as RAM */
+	addis	r3,r0,CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
+	addis	r4,r0,CONFIG_SYS_INIT_RAM_END@h
+	ori	r4,r4,CONFIG_SYS_INIT_RAM_END@l
+	rlwinm. r5,r4,0,27,31
+	rlwinm	r5,r4,27,5,31
+	beq	..d_ran
+	addi	r5,r5,0x0001
+..d_ran:
+	mtctr	r5
+..d_ag:
+	dcbz	r0,r3
+	addi	r3,r3,32
+	bdnz	..d_ag
+
+	/*
+	 * Lock the init-ram/stack in d-cache, so that other regions
+	 * may use d-cache as well
+	 * Note, that this current implementation locks exactly 4k
+	 * of d-cache, so please make sure that you don't define a
+	 * bigger init-ram area. Take a look at the lwmon5 440EPx
+	 * implementation as a reference.
+	 */
+	msync
+	isync
+	/* 8. set TFLOOR/NFLOOR to 8 (-> 8*16*32 bytes locked -> 4k) */
+	lis	r1,0x0201
+	ori	r1,r1,0xf808
+	mtspr	SPRN_DVLIM,r1
+	lis	r1,0x0808
+	ori	r1,r1,0x0808
+	mtspr	SPRN_DNV0,r1
+	mtspr	SPRN_DNV1,r1
+	mtspr	SPRN_DNV2,r1
+	mtspr	SPRN_DNV3,r1
+	mtspr	SPRN_DTV0,r1
+	mtspr	SPRN_DTV1,r1
+	mtspr	SPRN_DTV2,r1
+	mtspr	SPRN_DTV3,r1
+	msync
+	isync
+#endif /* CONFIG_SYS_INIT_RAM_DCACHE */
+
+	/* 440EP & 440GR are only 440er PPC's without internal SRAM */
+#if !defined(CONFIG_440EP) && !defined(CONFIG_440GR)
+	/* not all PPC's have internal SRAM usable as L2-cache */
+#if defined(CONFIG_440GX) || \
+    defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460SX)
+	mtdcr	L2_CACHE_CFG,r0		/* Ensure L2 Cache is off */
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	lis	r1, 0x0000
+	ori	r1,r1,0x0008		/* Set L2_CACHE_CFG[RDBW]=1 */
+	mtdcr	L2_CACHE_CFG,r1
+#endif
+
+	lis	r2,0x7fff
+	ori	r2,r2,0xffff
+	mfdcr	r1,ISRAM0_DPC
+	and	r1,r1,r2		/* Disable parity check */
+	mtdcr	ISRAM0_DPC,r1
+	mfdcr	r1,ISRAM0_PMEG
+	and	r1,r1,r2		/* Disable pwr mgmt */
+	mtdcr	ISRAM0_PMEG,r1
+
+	lis	r1,0x8000		/* BAS = 8000_0000 */
+#if defined(CONFIG_440GX) || defined(CONFIG_440SP)
+	ori	r1,r1,0x0980		/* first 64k */
+	mtdcr	ISRAM0_SB0CR,r1
+	lis	r1,0x8001
+	ori	r1,r1,0x0980		/* second 64k */
+	mtdcr	ISRAM0_SB1CR,r1
+	lis	r1, 0x8002
+	ori	r1,r1, 0x0980		/* third 64k */
+	mtdcr	ISRAM0_SB2CR,r1
+	lis	r1, 0x8003
+	ori	r1,r1, 0x0980		/* fourth 64k */
+	mtdcr	ISRAM0_SB3CR,r1
+#elif defined(CONFIG_440SPE) || defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	lis	r1,0x0000		/* BAS = X_0000_0000 */
+	ori	r1,r1,0x0984		/* first 64k */
+	mtdcr	ISRAM0_SB0CR,r1
+	lis	r1,0x0001
+	ori	r1,r1,0x0984		/* second 64k */
+	mtdcr	ISRAM0_SB1CR,r1
+	lis	r1, 0x0002
+	ori	r1,r1, 0x0984		/* third 64k */
+	mtdcr	ISRAM0_SB2CR,r1
+	lis	r1, 0x0003
+	ori	r1,r1, 0x0984		/* fourth 64k */
+	mtdcr	ISRAM0_SB3CR,r1
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	lis	r2,0x7fff
+	ori	r2,r2,0xffff
+	mfdcr	r1,ISRAM1_DPC
+	and	r1,r1,r2		/* Disable parity check */
+	mtdcr	ISRAM1_DPC,r1
+	mfdcr	r1,ISRAM1_PMEG
+	and	r1,r1,r2		/* Disable pwr mgmt */
+	mtdcr	ISRAM1_PMEG,r1
+
+	lis	r1,0x0004		/* BAS = 4_0004_0000 */
+	ori	r1,r1,0x0984		/* 64k */
+	mtdcr	ISRAM1_SB0CR,r1
+#endif
+#elif defined(CONFIG_460SX)
+	lis     r1,0x0000               /* BAS = 0000_0000 */
+	ori     r1,r1,0x0B84            /* first 128k */
+	mtdcr   ISRAM0_SB0CR,r1
+	lis     r1,0x0001
+	ori     r1,r1,0x0B84            /* second 128k */
+	mtdcr   ISRAM0_SB1CR,r1
+	lis     r1, 0x0002
+	ori     r1,r1, 0x0B84           /* third 128k */
+	mtdcr   ISRAM0_SB2CR,r1
+	lis     r1, 0x0003
+	ori     r1,r1, 0x0B84           /* fourth 128k */
+	mtdcr   ISRAM0_SB3CR,r1
+#elif defined(CONFIG_440GP)
+	ori	r1,r1,0x0380		/* 8k rw */
+	mtdcr	ISRAM0_SB0CR,r1
+	mtdcr	ISRAM0_SB1CR,r0		/* Disable bank 1 */
+#endif
+#endif /* #if !defined(CONFIG_440EP) && !defined(CONFIG_440GR) */
+
+	/*----------------------------------------------------------------*/
+	/* Setup the stack in internal SRAM */
+	/*----------------------------------------------------------------*/
+	lis	r1,CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r1,r1,CONFIG_SYS_INIT_SP_OFFSET@l
+	li	r0,0
+	stwu	r0,-4(r1)
+	stwu	r0,-4(r1)		/* Terminate call chain */
+
+	stwu	r1,-8(r1)		/* Save back chain and move SP */
+	lis	r0,RESET_VECTOR@h	/* Address of reset vector */
+	ori	r0,r0, RESET_VECTOR@l
+	stwu	r1,-8(r1)		/* Save back chain and move SP */
+	stw	r0,+12(r1)		/* Save return addr (underflow vect) */
+
+#ifdef CONFIG_NAND_SPL
+	bl	nand_boot_common	/* will not return */
+#else
+	GET_GOT
+
+	bl	cpu_init_f	/* run low-level CPU init code	   (from Flash) */
+	bl	board_init_f
+#endif
+
+#endif /* CONFIG_440 */
+
+/*****************************************************************************/
+#ifdef CONFIG_IOP480
+	/*----------------------------------------------------------------------- */
+	/* Set up some machine state registers. */
+	/*----------------------------------------------------------------------- */
+	addi	r0,r0,0x0000		/* initialize r0 to zero */
+	mtspr	SPRN_ESR,r0		/* clear Exception Syndrome Reg */
+	mttcr	r0			/* timer control register */
+	mtexier r0			/* disable all interrupts */
+	addis	r4,r0,0xFFFF		/* set r4 to 0xFFFFFFFF (status in the */
+	ori	r4,r4,0xFFFF		/* dbsr is cleared by setting bits to 1) */
+	mtdbsr	r4			/* clear/reset the dbsr */
+	mtexisr r4			/* clear all pending interrupts */
+	addis	r4,r0,0x8000
+	mtexier r4			/* enable critical exceptions */
+	addis	r4,r0,0x0000		/* assume 403GCX - enable core clk */
+	ori	r4,r4,0x4020		/* dbling (no harm done on GA and GC */
+	mtiocr	r4			/* since bit not used) & DRC to latch */
+					/* data bus on rising edge of CAS */
+	/*----------------------------------------------------------------------- */
+	/* Clear XER. */
+	/*----------------------------------------------------------------------- */
+	mtxer	r0
+	/*----------------------------------------------------------------------- */
+	/* Invalidate i-cache and d-cache TAG arrays. */
+	/*----------------------------------------------------------------------- */
+	addi	r3,0,1024		/* 1/4 of I-cache size, half of D-cache */
+	addi	r4,0,1024		/* 1/4 of I-cache */
+..cloop:
+	iccci	0,r3
+	iccci	r4,r3
+	dccci	0,r3
+	addic.	r3,r3,-16		/* move back one cache line */
+	bne	..cloop			/* loop back to do rest until r3 = 0 */
+
+	/* */
+	/* initialize IOP480 so it can read 1 MB code area for SRAM spaces */
+	/* this requires enabling MA[17..0], by default only MA[12..0] are enabled. */
+	/* */
+
+	/* first copy IOP480 register base address into r3 */
+	addis	r3,0,0x5000		/* IOP480 register base address hi */
+/*	ori	r3,r3,0x0000		/  IOP480 register base address lo */
+
+#ifdef CONFIG_ADCIOP
+	/* use r4 as the working variable */
+	/* turn on CS3 (LOCCTL.7) */
+	lwz	r4,0x84(r3)		/* LOCTL is at offset 0x84 */
+	andi.	r4,r4,0xff7f		/* make bit 7 = 0 -- CS3 mode */
+	stw	r4,0x84(r3)		/* LOCTL is at offset 0x84 */
+#endif
+
+#ifdef CONFIG_DASA_SIM
+	/* use r4 as the working variable */
+	/* turn on MA17 (LOCCTL.7) */
+	lwz	r4,0x84(r3)		/* LOCTL is at offset 0x84 */
+	ori	r4,r4,0x80		/* make bit 7 = 1 -- MA17 mode */
+	stw	r4,0x84(r3)		/* LOCTL is at offset 0x84 */
+#endif
+
+	/* turn on MA16..13 (LCS0BRD.12 = 0) */
+	lwz	r4,0x100(r3)		/* LCS0BRD is at offset 0x100 */
+	andi.	r4,r4,0xefff		/* make bit 12 = 0 */
+	stw	r4,0x100(r3)		/* LCS0BRD is at offset 0x100 */
+
+	/* make sure above stores all comlete before going on */
+	sync
+
+	/* last thing, set local init status done bit (DEVINIT.31) */
+	lwz	r4,0x80(r3)		/* DEVINIT is at offset 0x80 */
+	oris	r4,r4,0x8000		/* make bit 31 = 1 */
+	stw	r4,0x80(r3)		/* DEVINIT is at offset 0x80 */
+
+	/* clear all pending interrupts and disable all interrupts */
+	li	r4,-1			/* set p1 to 0xffffffff */
+	stw	r4,0x1b0(r3)		/* clear all pending interrupts */
+	stw	r4,0x1b8(r3)		/* clear all pending interrupts */
+	li	r4,0			/* set r4 to 0 */
+	stw	r4,0x1b4(r3)		/* disable all interrupts */
+	stw	r4,0x1bc(r3)		/* disable all interrupts */
+
+	/* make sure above stores all comlete before going on */
+	sync
+
+	/* Set-up icache cacheability. */
+	lis	r1, CONFIG_SYS_ICACHE_SACR_VALUE@h
+	ori	r1, r1, CONFIG_SYS_ICACHE_SACR_VALUE@l
+	mticcr	r1
+	isync
+
+	/* Set-up dcache cacheability. */
+	lis	r1, CONFIG_SYS_DCACHE_SACR_VALUE@h
+	ori	r1, r1, CONFIG_SYS_DCACHE_SACR_VALUE@l
+	mtdccr	r1
+
+	addis	r1,r0,CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r1,r1,CONFIG_SYS_INIT_SP_OFFSET /* set up the stack to SDRAM */
+	li	r0, 0			/* Make room for stack frame header and */
+	stwu	r0, -4(r1)		/* clear final stack frame so that	*/
+	stwu	r0, -4(r1)		/* stack backtraces terminate cleanly	*/
+
+	GET_GOT			/* initialize GOT access			*/
+
+	bl	board_init_f	/* run first part of init code (from Flash)	*/
+
+#endif	/* CONFIG_IOP480 */
+
+/*****************************************************************************/
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
+    defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
+    defined(CONFIG_405EX) || defined(CONFIG_405)
+	/*----------------------------------------------------------------------- */
+	/* Clear and set up some registers. */
+	/*----------------------------------------------------------------------- */
+	addi	r4,r0,0x0000
+#if !defined(CONFIG_405EX)
+	mtspr	SPRN_SGR,r4
+#else
+	/*
+	 * On 405EX, completely clearing the SGR leads to PPC hangup
+	 * upon PCIe configuration access. The PCIe memory regions
+	 * need to be guarded!
+	 */
+	lis	r3,0x0000
+	ori	r3,r3,0x7FFC
+	mtspr	SPRN_SGR,r3
+#endif
+	mtspr	SPRN_DCWR,r4
+	mtesr	r4			/* clear Exception Syndrome Reg */
+	mttcr	r4			/* clear Timer Control Reg */
+	mtxer	r4			/* clear Fixed-Point Exception Reg */
+	mtevpr	r4			/* clear Exception Vector Prefix Reg */
+	addi	r4,r0,(0xFFFF-0x10000)		/* set r4 to 0xFFFFFFFF (status in the */
+					/* dbsr is cleared by setting bits to 1) */
+	mtdbsr	r4			/* clear/reset the dbsr */
+
+	/* Invalidate the i- and d-caches. */
+	bl	invalidate_icache
+	bl	invalidate_dcache
+
+	/* Set-up icache cacheability. */
+	lis	r4, CONFIG_SYS_ICACHE_SACR_VALUE@h
+	ori	r4, r4, CONFIG_SYS_ICACHE_SACR_VALUE@l
+	mticcr	r4
+	isync
+
+	/* Set-up dcache cacheability. */
+	lis	r4, CONFIG_SYS_DCACHE_SACR_VALUE@h
+	ori	r4, r4, CONFIG_SYS_DCACHE_SACR_VALUE@l
+	mtdccr	r4
+
+#if !(defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR))\
+				&& !defined (CONFIG_XILINX_405)
+	/*----------------------------------------------------------------------- */
+	/* Tune the speed and size for flash CS0  */
+	/*----------------------------------------------------------------------- */
+	bl	ext_bus_cntlr_init
+#endif
+
+#if !(defined(CONFIG_SYS_INIT_DCACHE_CS) || defined(CONFIG_SYS_TEMP_STACK_OCM))
+	/*
+	 * For boards that don't have OCM and can't use the data cache
+	 * for their primordial stack, setup stack here directly after the
+	 * SDRAM is initialized in ext_bus_cntlr_init.
+	 */
+	lis	r1, CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r1,r1,CONFIG_SYS_INIT_SP_OFFSET /* set up the stack in SDRAM */
+
+	li	r0, 0			/* Make room for stack frame header and */
+	stwu	r0, -4(r1)		/* clear final stack frame so that	*/
+	stwu	r0, -4(r1)		/* stack backtraces terminate cleanly	*/
+	/*
+	 * Set up a dummy frame to store reset vector as return address.
+	 * this causes stack underflow to reset board.
+	 */
+	stwu	r1, -8(r1)		/* Save back chain and move SP */
+	lis	r0, RESET_VECTOR@h	/* Address of reset vector */
+	ori	r0, r0, RESET_VECTOR@l
+	stwu	r1, -8(r1)		/* Save back chain and move SP */
+	stw	r0, +12(r1)		/* Save return addr (underflow vect) */
+#endif /* !(CONFIG_SYS_INIT_DCACHE_CS	|| !CONFIG_SYS_TEM_STACK_OCM) */
+
+#if defined(CONFIG_405EP)
+	/*----------------------------------------------------------------------- */
+	/* DMA Status, clear to come up clean */
+	/*----------------------------------------------------------------------- */
+	addis	r3,r0, 0xFFFF		/* Clear all existing DMA status */
+	ori	r3,r3, 0xFFFF
+	mtdcr	DMASR, r3
+
+	bl	ppc405ep_init		/* do ppc405ep specific init */
+#endif /* CONFIG_405EP */
+
+#if defined(CONFIG_SYS_OCM_DATA_ADDR) && defined(CONFIG_SYS_OCM_DATA_SIZE)
+#if defined(CONFIG_405EZ)
+	/********************************************************************
+	 * Setup OCM - On Chip Memory - PPC405EZ uses OCM Controller V2
+	 *******************************************************************/
+	/*
+	 * We can map the OCM on the PLB3, so map it at
+	 * CONFIG_SYS_OCM_DATA_ADDR + 0x8000
+	 */
+	lis	r3,CONFIG_SYS_OCM_DATA_ADDR@h	/* OCM location */
+	ori	r3,r3,CONFIG_SYS_OCM_DATA_ADDR@l
+	ori	r3,r3,0x0270		/* 16K for Bank 1, R/W/Enable */
+	mtdcr	OCM0_PLBCR1,r3		/* Set PLB Access */
+	ori	r3,r3,0x4000		/* Add 0x4000 for bank 2 */
+	mtdcr	OCM0_PLBCR2,r3		/* Set PLB Access */
+	isync
+
+	lis	r3,CONFIG_SYS_OCM_DATA_ADDR@h	/* OCM location */
+	ori	r3,r3,CONFIG_SYS_OCM_DATA_ADDR@l
+	ori	r3,r3,0x0270		/* 16K for Bank 1, R/W/Enable */
+	mtdcr	OCM0_DSRC1, r3		/* Set Data Side */
+	mtdcr	OCM0_ISRC1, r3		/* Set Instruction Side */
+	ori	r3,r3,0x4000		/* Add 0x4000 for bank 2 */
+	mtdcr	OCM0_DSRC2, r3		/* Set Data Side */
+	mtdcr	OCM0_ISRC2, r3		/* Set Instruction Side */
+	addis	r3,0,0x0800		/* OCM Data Parity Disable - 1 Wait State */
+	mtdcr	OCM0_DISDPC,r3
+
+	isync
+#else /* CONFIG_405EZ */
+	/********************************************************************
+	 * Setup OCM - On Chip Memory
+	 *******************************************************************/
+	/* Setup OCM */
+	lis	r0, 0x7FFF
+	ori	r0, r0, 0xFFFF
+	mfdcr	r3, OCM0_ISCNTL		/* get instr-side IRAM config */
+	mfdcr	r4, OCM0_DSCNTL		/* get data-side IRAM config */
+	and	r3, r3, r0		/* disable data-side IRAM */
+	and	r4, r4, r0		/* disable data-side IRAM */
+	mtdcr	OCM0_ISCNTL, r3		/* set instr-side IRAM config */
+	mtdcr	OCM0_DSCNTL, r4		/* set data-side IRAM config */
+	isync
+
+	lis	r3,CONFIG_SYS_OCM_DATA_ADDR@h	/* OCM location */
+	ori	r3,r3,CONFIG_SYS_OCM_DATA_ADDR@l
+	mtdcr	OCM0_DSARC, r3
+	addis	r4, 0, 0xC000		/* OCM data area enabled */
+	mtdcr	OCM0_DSCNTL, r4
+	isync
+#endif /* CONFIG_405EZ */
+#endif
+
+	/*----------------------------------------------------------------------- */
+	/* Setup temporary stack in DCACHE or OCM if needed for SDRAM SPD. */
+	/*----------------------------------------------------------------------- */
+#ifdef CONFIG_SYS_INIT_DCACHE_CS
+	li	r4, PBxAP
+	mtdcr	EBC0_CFGADDR, r4
+	lis	r4, CONFIG_SYS_INIT_DCACHE_PBxAR@h
+	ori	r4, r4, CONFIG_SYS_INIT_DCACHE_PBxAR@l
+	mtdcr	EBC0_CFGDATA, r4
+
+	addi	r4, 0, PBxCR
+	mtdcr	EBC0_CFGADDR, r4
+	lis	r4, CONFIG_SYS_INIT_DCACHE_PBxCR@h
+	ori	r4, r4, CONFIG_SYS_INIT_DCACHE_PBxCR@l
+	mtdcr	EBC0_CFGDATA, r4
+
+	/*
+	 * Enable the data cache for the 128MB storage access control region
+	 * at CONFIG_SYS_INIT_RAM_ADDR.
+	 */
+	mfdccr	r4
+	oris	r4, r4, PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@h
+	ori	r4, r4, PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@l
+	mtdccr	r4
+
+	/*
+	 * Preallocate data cache lines to be used to avoid a subsequent
+	 * cache miss and an ensuing machine check exception when exceptions
+	 * are enabled.
+	 */
+	li	r0, 0
+
+	lis	r3, CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l
+
+	lis	r4, CONFIG_SYS_INIT_RAM_END@h
+	ori	r4, r4, CONFIG_SYS_INIT_RAM_END@l
+
+	/*
+	 * Convert the size, in bytes, to the number of cache lines/blocks
+	 * to preallocate.
+	 */
+	clrlwi. r5, r4, (32 - L1_CACHE_SHIFT)
+	srwi	r5, r4, L1_CACHE_SHIFT
+	beq	..load_counter
+	addi	r5, r5, 0x0001
+..load_counter:
+	mtctr	r5
+
+	/* Preallocate the computed number of cache blocks. */
+..alloc_dcache_block:
+	dcba	r0, r3
+	addi	r3, r3, L1_CACHE_BYTES
+	bdnz	..alloc_dcache_block
+	sync
+
+	/*
+	 * Load the initial stack pointer and data area and convert the size,
+	 * in bytes, to the number of words to initialize to a known value.
+	 */
+	lis	r1, CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r1, r1, CONFIG_SYS_INIT_SP_OFFSET@l
+
+	lis	r4, (CONFIG_SYS_INIT_RAM_END >> 2)@h
+	ori	r4, r4, (CONFIG_SYS_INIT_RAM_END >> 2)@l
+	mtctr	r4
+
+	lis	r2, CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r2, r2, CONFIG_SYS_INIT_RAM_END@l
+
+	lis	r4, CONFIG_SYS_INIT_RAM_PATTERN@h
+	ori	r4, r4, CONFIG_SYS_INIT_RAM_PATTERN@l
+
+..stackloop:
+	stwu	r4, -4(r2)
+	bdnz	..stackloop
+
+	/*
+	 * Make room for stack frame header and clear final stack frame so
+	 * that stack backtraces terminate cleanly.
+	 */
+	stwu	r0, -4(r1)
+	stwu	r0, -4(r1)
+
+	/*
+	 * Set up a dummy frame to store reset vector as return address.
+	 * this causes stack underflow to reset board.
+	 */
+	stwu	r1, -8(r1)		/* Save back chain and move SP */
+	addis	r0, 0, RESET_VECTOR@h	/* Address of reset vector */
+	ori	r0, r0, RESET_VECTOR@l
+	stwu	r1, -8(r1)		/* Save back chain and move SP */
+	stw	r0, +12(r1)		/* Save return addr (underflow vect) */
+
+#elif defined(CONFIG_SYS_TEMP_STACK_OCM) && \
+	(defined(CONFIG_SYS_OCM_DATA_ADDR) && defined(CONFIG_SYS_OCM_DATA_SIZE))
+	/*
+	 * Stack in OCM.
+	 */
+
+	/* Set up Stack at top of OCM */
+	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)@h
+	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)@l
+
+	/* Set up a zeroized stack frame so that backtrace works right */
+	li	r0, 0
+	stwu	r0, -4(r1)
+	stwu	r0, -4(r1)
+
+	/*
+	 * Set up a dummy frame to store reset vector as return address.
+	 * this causes stack underflow to reset board.
+	 */
+	stwu	r1, -8(r1)		/* Save back chain and move SP */
+	lis	r0, RESET_VECTOR@h	/* Address of reset vector */
+	ori	r0, r0, RESET_VECTOR@l
+	stwu	r1, -8(r1)		/* Save back chain and move SP */
+	stw	r0, +12(r1)		/* Save return addr (underflow vect) */
+#endif /* CONFIG_SYS_INIT_DCACHE_CS */
+
+#ifdef CONFIG_NAND_SPL
+	bl	nand_boot_common	/* will not return */
+#else
+	GET_GOT			/* initialize GOT access			*/
+
+	bl	cpu_init_f	/* run low-level CPU init code	   (from Flash) */
+
+	/* NEVER RETURNS! */
+	bl	board_init_f	/* run first part of init code (from Flash)	*/
+#endif /* CONFIG_NAND_SPL */
+
+#endif	/* CONFIG_405GP || CONFIG_405CR || CONFIG_405 || CONFIG_405EP */
+	/*----------------------------------------------------------------------- */
+
+
+#ifndef CONFIG_NAND_SPL
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+	.globl	transfer_to_handler
+transfer_to_handler:
+	stw	r22,_NIP(r21)
+	lis	r22,MSR_POW@h
+	andc	r23,r23,r22
+	stw	r23,_MSR(r21)
+	SAVE_GPR(7, r21)
+	SAVE_4GPRS(8, r21)
+	SAVE_8GPRS(12, r21)
+	SAVE_8GPRS(24, r21)
+	mflr	r23
+	andi.	r24,r23,0x3f00		/* get vector offset */
+	stw	r24,TRAP(r21)
+	li	r22,0
+	stw	r22,RESULT(r21)
+	mtspr	SPRG2,r22		/* r1 is now kernel sp */
+	lwz	r24,0(r23)		/* virtual address of handler */
+	lwz	r23,4(r23)		/* where to go when done */
+	mtspr	SRR0,r24
+	mtspr	SRR1,r20
+	mtlr	r23
+	SYNC
+	rfi				/* jump to handler, enable MMU */
+
+int_return:
+	mfmsr	r28		/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC			/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SRR0,r2
+	mtspr	SRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfi
+
+crit_return:
+	mfmsr	r28		/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC			/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SPRN_CSRR0,r2
+	mtspr	SPRN_CSRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfci
+
+#ifdef CONFIG_440
+mck_return:
+	mfmsr	r28		/* Disable interrupts */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r28,r28,r4
+	SYNC			/* Some chip revs need this... */
+	mtmsr	r28
+	SYNC
+	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SPRN_MCSRR0,r2
+	mtspr	SPRN_MCSRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfmci
+#endif /* CONFIG_440 */
+
+
+	.globl get_pvr
+get_pvr:
+	mfspr	r3, PVR
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 out16 */
+/* Description:	 Output 16 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	out16
+out16:
+	sth	r4,0x0000(r3)
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 out16r */
+/* Description:	 Byte reverse and output 16 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	out16r
+out16r:
+	sthbrx	r4,r0,r3
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 out32r */
+/* Description:	 Byte reverse and output 32 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	out32r
+out32r:
+	stwbrx	r4,r0,r3
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 in16 */
+/* Description:	 Input 16 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	in16
+in16:
+	lhz	r3,0x0000(r3)
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 in16r */
+/* Description:	 Input 16 bits and byte reverse */
+/*------------------------------------------------------------------------------- */
+	.globl	in16r
+in16r:
+	lhbrx	r3,r0,r3
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 in32r */
+/* Description:	 Input 32 bits and byte reverse */
+/*------------------------------------------------------------------------------- */
+	.globl	in32r
+in32r:
+	lwbrx	r3,r0,r3
+	blr
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = Relocated stack pointer
+ * r4 = Relocated global data pointer
+ * r5 = Relocated text pointer
+ */
+	.globl	relocate_code
+relocate_code:
+#if defined(CONFIG_4xx_DCACHE) || defined(CONFIG_SYS_INIT_DCACHE_CS)
+	/*
+	 * We need to flush the initial global data (gd_t) before the dcache
+	 * will be invalidated.
+	 */
+
+	/* Save registers */
+	mr	r9, r3
+	mr	r10, r4
+	mr	r11, r5
+
+	/* Flush initial global data range */
+	mr	r3, r4
+	addi	r4, r4, CONFIG_SYS_GBL_DATA_SIZE@l
+	bl	flush_dcache_range
+
+#if defined(CONFIG_SYS_INIT_DCACHE_CS)
+	/*
+	 * Undo the earlier data cache set-up for the primordial stack and
+	 * data area. First, invalidate the data cache and then disable data
+	 * cacheability for that area. Finally, restore the EBC values, if
+	 * any.
+	 */
+
+	/* Invalidate the primordial stack and data area in cache */
+	lis	r3, CONFIG_SYS_INIT_RAM_ADDR@h
+	ori	r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l
+
+	lis	r4, CONFIG_SYS_INIT_RAM_END@h
+	ori	r4, r4, CONFIG_SYS_INIT_RAM_END@l
+	add	r4, r4, r3
+
+	bl	invalidate_dcache_range
+
+	/* Disable cacheability for the region */
+	mfdccr	r3
+	lis     r4, ~PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@h
+	ori     r4, r4, ~PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@l
+	and     r3, r3, r4
+	mtdccr  r3
+
+	/* Restore the EBC parameters */
+	li	r3, PBxAP
+	mtdcr	EBC0_CFGADDR, r3
+	lis	r3, PBxAP_VAL@h
+	ori	r3, r3, PBxAP_VAL@l
+	mtdcr	EBC0_CFGDATA, r3
+
+	li	r3, PBxCR
+	mtdcr	EBC0_CFGADDR, r3
+	lis	r3, PBxCR_VAL@h
+	ori	r3, r3, PBxCR_VAL@l
+	mtdcr	EBC0_CFGDATA, r3
+#endif /* defined(CONFIG_SYS_INIT_DCACHE_CS) */
+
+	/* Restore registers */
+	mr	r3, r9
+	mr	r4, r10
+	mr	r5, r11
+#endif /* defined(CONFIG_4xx_DCACHE) || defined(CONFIG_SYS_INIT_DCACHE_CS) */
+
+#ifdef CONFIG_SYS_INIT_RAM_DCACHE
+	/*
+	 * Unlock the previously locked d-cache
+	 */
+	msync
+	isync
+	/* set TFLOOR/NFLOOR to 0 again */
+	lis	r6,0x0001
+	ori	r6,r6,0xf800
+	mtspr	SPRN_DVLIM,r6
+	lis	r6,0x0000
+	ori	r6,r6,0x0000
+	mtspr	SPRN_DNV0,r6
+	mtspr	SPRN_DNV1,r6
+	mtspr	SPRN_DNV2,r6
+	mtspr	SPRN_DNV3,r6
+	mtspr	SPRN_DTV0,r6
+	mtspr	SPRN_DTV1,r6
+	mtspr	SPRN_DTV2,r6
+	mtspr	SPRN_DTV3,r6
+	msync
+	isync
+#endif /* CONFIG_SYS_INIT_RAM_DCACHE */
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+    defined(CONFIG_460SX)
+	/*
+	 * On some 440er platforms the cache is enabled in the first TLB (Boot-CS)
+	 * to speed up the boot process. Now this cache needs to be disabled.
+	 */
+	iccci	0,0			/* Invalidate inst cache */
+	dccci	0,0			/* Invalidate data cache, now no longer our stack */
+	sync
+	isync
+
+	/* Clear all potential pending exceptions */
+	mfspr	r1,SPRN_MCSR
+	mtspr	SPRN_MCSR,r1
+#ifdef CONFIG_SYS_TLB_FOR_BOOT_FLASH
+	addi	r1,r0,CONFIG_SYS_TLB_FOR_BOOT_FLASH	/* Use defined TLB */
+#else
+	addi	r1,r0,0x0000		/* Default TLB entry is #0 */
+#endif /* CONFIG_SYS_TLB_FOR_BOOT_FLASH */
+	tlbre	r0,r1,0x0002		/* Read contents */
+	ori	r0,r0,0x0c00		/* Or in the inhibit, write through bit */
+	tlbwe	r0,r1,0x0002		/* Save it out */
+	sync
+	isync
+#endif /* defined(CONFIG_440EP) || ... || defined(CONFIG_460GT) */
+	mr	r1,  r3		/* Set new stack pointer		*/
+	mr	r9,  r4		/* Save copy of Init Data pointer	*/
+	mr	r10, r5		/* Save copy of Destination Address	*/
+
+	GET_GOT
+	mr	r3,  r5				/* Destination Address	*/
+	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address	*/
+	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
+	lwz	r5, GOT(__init_end)
+	sub	r5, r5, r4
+	li	r6, L1_CACHE_BYTES		/* Cache Line Size	*/
+
+	/*
+	 * Fix GOT pointer:
+	 *
+	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+	 *
+	 * Offset:
+	 */
+	sub	r15, r10, r4
+
+	/* First our own GOT */
+	add	r12, r12, r15
+	/* then the one used by the C code */
+	add	r30, r30, r15
+
+	/*
+	 * Now relocate code
+	 */
+
+	cmplw	cr1,r3,r4
+	addi	r0,r5,3
+	srwi.	r0,r0,2
+	beq	cr1,4f		/* In place copy is not necessary	*/
+	beq	7f		/* Protect against 0 count		*/
+	mtctr	r0
+	bge	cr1,2f
+
+	la	r8,-4(r4)
+	la	r7,-4(r3)
+1:	lwzu	r0,4(r8)
+	stwu	r0,4(r7)
+	bdnz	1b
+	b	4f
+
+2:	slwi	r0,r0,2
+	add	r8,r4,r0
+	add	r7,r3,r0
+3:	lwzu	r0,-4(r8)
+	stwu	r0,-4(r7)
+	bdnz	3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:	cmpwi	r6,0
+	add	r5,r3,r5
+	beq	7f		/* Always flush prefetch queue in any case */
+	subi	r0,r6,1
+	andc	r3,r3,r0
+	mr	r4,r3
+5:	dcbst	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	5b
+	sync			/* Wait for all dcbst to complete on bus */
+	mr	r4,r3
+6:	icbi	0,r4
+	add	r4,r4,r6
+	cmplw	r4,r5
+	blt	6b
+7:	sync			/* Wait for all icbi to complete on bus */
+	isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+	addi	r0, r10, in_ram - _start + _START_OFFSET
+	mtlr	r0
+	blr				/* NEVER RETURNS! */
+
+in_ram:
+
+	/*
+	 * Relocation Function, r12 point to got2+0x8000
+	 *
+	 * Adjust got2 pointers, no need to check for 0, this code
+	 * already puts a few entries in the table.
+	 */
+	li	r0,__got2_entries@sectoff@l
+	la	r3,GOT(_GOT2_TABLE_)
+	lwz	r11,GOT(_GOT2_TABLE_)
+	mtctr	r0
+	sub	r11,r3,r11
+	addi	r3,r3,-4
+1:	lwzu	r0,4(r3)
+	cmpwi	r0,0
+	beq-	2f
+	add	r0,r0,r11
+	stw	r0,0(r3)
+2:	bdnz	1b
+
+	/*
+	 * Now adjust the fixups and the pointers to the fixups
+	 * in case we need to move ourselves again.
+	 */
+	li	r0,__fixup_entries@sectoff@l
+	lwz	r3,GOT(_FIXUP_TABLE_)
+	cmpwi	r0,0
+	mtctr	r0
+	addi	r3,r3,-4
+	beq	4f
+3:	lwzu	r4,4(r3)
+	lwzux	r0,r4,r11
+	add	r0,r0,r11
+	stw	r10,0(r3)
+	stw	r0,0(r4)
+	bdnz	3b
+4:
+clear_bss:
+	/*
+	 * Now clear BSS segment
+	 */
+	lwz	r3,GOT(__bss_start)
+	lwz	r4,GOT(_end)
+
+	cmplw	0, r3, r4
+	beq	7f
+
+	li	r0, 0
+
+	andi.	r5, r4, 3
+	beq	6f
+	sub	r4, r4, r5
+	mtctr	r5
+	mr	r5, r4
+5:	stb	r0, 0(r5)
+	addi	r5, r5, 1
+	bdnz	5b
+6:
+	stw	r0, 0(r3)
+	addi	r3, r3, 4
+	cmplw	0, r3, r4
+	bne	6b
+
+7:
+	mr	r3, r9		/* Init Data pointer		*/
+	mr	r4, r10		/* Destination Address		*/
+	bl	board_init_r
+
+	/*
+	 * Copy exception vector code to low memory
+	 *
+	 * r3: dest_addr
+	 * r7: source address, r8: end address, r9: target address
+	 */
+	.globl	trap_init
+trap_init:
+	mflr	r4			/* save link register		*/
+	GET_GOT
+	lwz	r7, GOT(_start_of_vectors)
+	lwz	r8, GOT(_end_of_vectors)
+
+	li	r9, 0x100		/* reset vector always at 0x100 */
+
+	cmplw	0, r7, r8
+	bgelr				/* return if r7>=r8 - just in case */
+1:
+	lwz	r0, 0(r7)
+	stw	r0, 0(r9)
+	addi	r7, r7, 4
+	addi	r9, r9, 4
+	cmplw	0, r7, r8
+	bne	1b
+
+	/*
+	 * relocate `hdlr' and `int_return' entries
+	 */
+	li	r7, .L_MachineCheck - _start + _START_OFFSET
+	li	r8, Alignment - _start + _START_OFFSET
+2:
+	bl	trap_reloc
+	addi	r7, r7, 0x100		/* next exception vector */
+	cmplw	0, r7, r8
+	blt	2b
+
+	li	r7, .L_Alignment - _start + _START_OFFSET
+	bl	trap_reloc
+
+	li	r7, .L_ProgramCheck - _start + _START_OFFSET
+	bl	trap_reloc
+
+#ifdef CONFIG_440
+	li	r7, .L_FPUnavailable - _start + _START_OFFSET
+	bl	trap_reloc
+
+	li	r7, .L_Decrementer - _start + _START_OFFSET
+	bl	trap_reloc
+
+	li	r7, .L_APU - _start + _START_OFFSET
+	bl	trap_reloc
+
+	li	r7, .L_InstructionTLBError - _start + _START_OFFSET
+	bl	trap_reloc
+
+	li	r7, .L_DataTLBError - _start + _START_OFFSET
+	bl	trap_reloc
+#else /* CONFIG_440 */
+	li	r7, .L_PIT - _start + _START_OFFSET
+	bl	trap_reloc
+
+	li	r7, .L_InstructionTLBMiss - _start + _START_OFFSET
+	bl	trap_reloc
+
+	li	r7, .L_DataTLBMiss - _start + _START_OFFSET
+	bl	trap_reloc
+#endif /* CONFIG_440 */
+
+	li	r7, .L_DebugBreakpoint - _start + _START_OFFSET
+	bl	trap_reloc
+
+#if !defined(CONFIG_440)
+	addi	r7,r0,0x1000		/* set ME bit (Machine Exceptions) */
+	oris	r7,r7,0x0002		/* set CE bit (Critical Exceptions) */
+	mtmsr	r7			/* change MSR */
+#else
+	bl	__440_msr_set
+	b	__440_msr_continue
+
+__440_msr_set:
+	addi	r7,r0,0x1000		/* set ME bit (Machine Exceptions) */
+	oris	r7,r7,0x0002		/* set CE bit (Critical Exceptions) */
+	mtspr	SPRN_SRR1,r7
+	mflr	r7
+	mtspr	SPRN_SRR0,r7
+	rfi
+__440_msr_continue:
+#endif
+
+	mtlr	r4			/* restore link register	*/
+	blr
+
+#if defined(CONFIG_440)
+/*----------------------------------------------------------------------------+
+| dcbz_area.
++----------------------------------------------------------------------------*/
+	function_prolog(dcbz_area)
+	rlwinm. r5,r4,0,27,31
+	rlwinm	r5,r4,27,5,31
+	beq	..d_ra2
+	addi	r5,r5,0x0001
+..d_ra2:mtctr	r5
+..d_ag2:dcbz	r0,r3
+	addi	r3,r3,32
+	bdnz	..d_ag2
+	sync
+	blr
+	function_epilog(dcbz_area)
+#endif /* CONFIG_440 */
+#endif /* CONFIG_NAND_SPL */
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 in8 */
+/* Description:	 Input 8 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	in8
+in8:
+	lbz	r3,0x0000(r3)
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 out8 */
+/* Description:	 Output 8 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	out8
+out8:
+	stb	r4,0x0000(r3)
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 out32 */
+/* Description:	 Output 32 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	out32
+out32:
+	stw	r4,0x0000(r3)
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 in32 */
+/* Description:	 Input 32 bits */
+/*------------------------------------------------------------------------------- */
+	.globl	in32
+in32:
+	lwz	3,0x0000(3)
+	blr
+
+/**************************************************************************/
+/* PPC405EP specific stuff						  */
+/**************************************************************************/
+#ifdef CONFIG_405EP
+ppc405ep_init:
+
+#ifdef CONFIG_BUBINGA
+	/*
+	 * Initialize EBC chip selects 1 & 4 and GPIO pins (for alternate
+	 * function) to support FPGA and NVRAM accesses below.
+	 */
+
+	lis	r3,GPIO0_OSRH@h		/* config GPIO output select */
+	ori	r3,r3,GPIO0_OSRH@l
+	lis	r4,CONFIG_SYS_GPIO0_OSRH@h
+	ori	r4,r4,CONFIG_SYS_GPIO0_OSRH@l
+	stw	r4,0(r3)
+	lis	r3,GPIO0_OSRL@h
+	ori	r3,r3,GPIO0_OSRL@l
+	lis	r4,CONFIG_SYS_GPIO0_OSRL@h
+	ori	r4,r4,CONFIG_SYS_GPIO0_OSRL@l
+	stw	r4,0(r3)
+
+	lis	r3,GPIO0_ISR1H@h	/* config GPIO input select */
+	ori	r3,r3,GPIO0_ISR1H@l
+	lis	r4,CONFIG_SYS_GPIO0_ISR1H@h
+	ori	r4,r4,CONFIG_SYS_GPIO0_ISR1H@l
+	stw	r4,0(r3)
+	lis	r3,GPIO0_ISR1L@h
+	ori	r3,r3,GPIO0_ISR1L@l
+	lis	r4,CONFIG_SYS_GPIO0_ISR1L@h
+	ori	r4,r4,CONFIG_SYS_GPIO0_ISR1L@l
+	stw	r4,0(r3)
+
+	lis	r3,GPIO0_TSRH@h		/* config GPIO three-state select */
+	ori	r3,r3,GPIO0_TSRH@l
+	lis	r4,CONFIG_SYS_GPIO0_TSRH@h
+	ori	r4,r4,CONFIG_SYS_GPIO0_TSRH@l
+	stw	r4,0(r3)
+	lis	r3,GPIO0_TSRL@h
+	ori	r3,r3,GPIO0_TSRL@l
+	lis	r4,CONFIG_SYS_GPIO0_TSRL@h
+	ori	r4,r4,CONFIG_SYS_GPIO0_TSRL@l
+	stw	r4,0(r3)
+
+	lis	r3,GPIO0_TCR@h		/* config GPIO driver output enables */
+	ori	r3,r3,GPIO0_TCR@l
+	lis	r4,CONFIG_SYS_GPIO0_TCR@h
+	ori	r4,r4,CONFIG_SYS_GPIO0_TCR@l
+	stw	r4,0(r3)
+
+	li	r3,PB1AP		/* program EBC bank 1 for RTC access */
+	mtdcr	EBC0_CFGADDR,r3
+	lis	r3,CONFIG_SYS_EBC_PB1AP@h
+	ori	r3,r3,CONFIG_SYS_EBC_PB1AP@l
+	mtdcr	EBC0_CFGDATA,r3
+	li	r3,PB1CR
+	mtdcr	EBC0_CFGADDR,r3
+	lis	r3,CONFIG_SYS_EBC_PB1CR@h
+	ori	r3,r3,CONFIG_SYS_EBC_PB1CR@l
+	mtdcr	EBC0_CFGDATA,r3
+
+	li	r3,PB1AP		/* program EBC bank 1 for RTC access */
+	mtdcr	EBC0_CFGADDR,r3
+	lis	r3,CONFIG_SYS_EBC_PB1AP@h
+	ori	r3,r3,CONFIG_SYS_EBC_PB1AP@l
+	mtdcr	EBC0_CFGDATA,r3
+	li	r3,PB1CR
+	mtdcr	EBC0_CFGADDR,r3
+	lis	r3,CONFIG_SYS_EBC_PB1CR@h
+	ori	r3,r3,CONFIG_SYS_EBC_PB1CR@l
+	mtdcr	EBC0_CFGDATA,r3
+
+	li	r3,PB4AP		/* program EBC bank 4 for FPGA access */
+	mtdcr	EBC0_CFGADDR,r3
+	lis	r3,CONFIG_SYS_EBC_PB4AP@h
+	ori	r3,r3,CONFIG_SYS_EBC_PB4AP@l
+	mtdcr	EBC0_CFGDATA,r3
+	li	r3,PB4CR
+	mtdcr	EBC0_CFGADDR,r3
+	lis	r3,CONFIG_SYS_EBC_PB4CR@h
+	ori	r3,r3,CONFIG_SYS_EBC_PB4CR@l
+	mtdcr	EBC0_CFGDATA,r3
+#endif
+
+	/*
+	!-----------------------------------------------------------------------
+	! Check to see if chip is in bypass mode.
+	! If so, write stored CPC0_PLLMR0 and CPC0_PLLMR1 values and perform a
+	! CPU reset   Otherwise, skip this step and keep going.
+	! Note:	 Running BIOS in bypass mode is not supported since PLB speed
+	!	 will not be fast enough for the SDRAM (min 66MHz)
+	!-----------------------------------------------------------------------
+	*/
+	mfdcr	r5, CPC0_PLLMR1
+	rlwinm	r4,r5,1,0x1		/* get system clock source (SSCS) */
+	cmpi	cr0,0,r4,0x1
+
+	beq    pll_done			/* if SSCS =b'1' then PLL has */
+					/* already been set */
+					/* and CPU has been reset */
+					/* so skip to next section */
+
+#ifdef CONFIG_BUBINGA
+	/*
+	!-----------------------------------------------------------------------
+	! Read NVRAM to get value to write in PLLMR.
+	! If value has not been correctly saved, write default value
+	! Default config values (assuming on-board 33MHz SYS_CLK) are above.
+	! See CPU_DEFAULT_200 and CPU_DEFAULT_266 above.
+	!
+	! WARNING:  This code assumes the first three words in the nvram_t
+	!	    structure in openbios.h.  Changing the beginning of
+	!	    the structure will break this code.
+	!
+	!-----------------------------------------------------------------------
+	*/
+	addis	r3,0,NVRAM_BASE@h
+	addi	r3,r3,NVRAM_BASE@l
+
+	lwz	r4, 0(r3)
+	addis	r5,0,NVRVFY1@h
+	addi	r5,r5,NVRVFY1@l
+	cmp	cr0,0,r4,r5		/* Compare 1st NVRAM Magic number*/
+	bne	..no_pllset
+	addi	r3,r3,4
+	lwz	r4, 0(r3)
+	addis	r5,0,NVRVFY2@h
+	addi	r5,r5,NVRVFY2@l
+	cmp	cr0,0,r4,r5		/* Compare 2 NVRAM Magic number */
+	bne	..no_pllset
+	addi	r3,r3,8			/* Skip over conf_size */
+	lwz	r4, 4(r3)		/* Load PLLMR1 value from NVRAM */
+	lwz	r3, 0(r3)		/* Load PLLMR0 value from NVRAM */
+	rlwinm	r5,r4,1,0x1		/* get system clock source (SSCS) */
+	cmpi	 cr0,0,r5,1		/* See if PLL is locked */
+	beq	pll_write
+..no_pllset:
+#endif /* CONFIG_BUBINGA */
+
+#ifdef CONFIG_TAIHU
+	mfdcr	r4, CPC0_BOOT
+	andi.	r5, r4, CPC0_BOOT_SEP@l
+	bne	strap_1			/* serial eeprom present */
+	addis	r5,0,CPLD_REG0_ADDR@h
+	ori	r5,r5,CPLD_REG0_ADDR@l
+	andi.	r5, r5, 0x10
+	bne	_pci_66mhz
+#endif /* CONFIG_TAIHU */
+
+#if defined(CONFIG_ZEUS)
+	mfdcr	r4, CPC0_BOOT
+	andi.	r5, r4, CPC0_BOOT_SEP@l
+	bne	strap_1			/* serial eeprom present */
+	lis	r3,0x0000
+	addi	r3,r3,0x3030
+	lis	r4,0x8042
+	addi	r4,r4,0x223e
+	b	1f
+strap_1:
+	mfdcr	r3, CPC0_PLLMR0
+	mfdcr	r4, CPC0_PLLMR1
+	b	1f
+#endif
+
+	addis	r3,0,PLLMR0_DEFAULT@h	/* PLLMR0 default value */
+	ori	r3,r3,PLLMR0_DEFAULT@l	/* */
+	addis	r4,0,PLLMR1_DEFAULT@h	/* PLLMR1 default value */
+	ori	r4,r4,PLLMR1_DEFAULT@l	/* */
+
+#ifdef CONFIG_TAIHU
+	b	1f
+_pci_66mhz:
+	addis	r3,0,PLLMR0_DEFAULT_PCI66@h
+	ori	r3,r3,PLLMR0_DEFAULT_PCI66@l
+	addis	r4,0,PLLMR1_DEFAULT_PCI66@h
+	ori	r4,r4,PLLMR1_DEFAULT_PCI66@l
+	b	1f
+strap_1:
+	mfdcr	r3, CPC0_PLLMR0
+	mfdcr	r4, CPC0_PLLMR1
+#endif /* CONFIG_TAIHU */
+
+1:
+	b	pll_write		/* Write the CPC0_PLLMR with new value */
+
+pll_done:
+	/*
+	!-----------------------------------------------------------------------
+	! Clear Soft Reset Register
+	! This is needed to enable PCI if not booting from serial EPROM
+	!-----------------------------------------------------------------------
+		*/
+	addi	r3, 0, 0x0
+	mtdcr	CPC0_SRR, r3
+
+	addis	 r3,0,0x0010
+	mtctr	r3
+pci_wait:
+	bdnz	pci_wait
+
+	blr				/* return to main code */
+
+/*
+!-----------------------------------------------------------------------------
+! Function:	pll_write
+! Description:	Updates the value of the CPC0_PLLMR according to CMOS27E documentation
+!		That is:
+!			  1.  Pll is first disabled (de-activated by putting in bypass mode)
+!			  2.  PLL is reset
+!			  3.  Clock dividers are set while PLL is held in reset and bypassed
+!			  4.  PLL Reset is cleared
+!			  5.  Wait 100us for PLL to lock
+!			  6.  A core reset is performed
+! Input: r3 = Value to write to CPC0_PLLMR0
+! Input: r4 = Value to write to CPC0_PLLMR1
+! Output r3 = none
+!-----------------------------------------------------------------------------
+*/
+	.globl	pll_write
+pll_write:
+	mfdcr  r5, CPC0_UCR
+	andis. r5,r5,0xFFFF
+	ori    r5,r5,0x0101		/* Stop the UART clocks */
+	mtdcr  CPC0_UCR,r5		/* Before changing PLL */
+
+	mfdcr  r5, CPC0_PLLMR1
+	rlwinm r5,r5,0,0x7FFFFFFF	/* Disable PLL */
+	mtdcr	CPC0_PLLMR1,r5
+	oris   r5,r5,0x4000		/* Set PLL Reset */
+	mtdcr	CPC0_PLLMR1,r5
+
+	mtdcr	CPC0_PLLMR0,r3		/* Set clock dividers */
+	rlwinm r5,r4,0,0x3FFFFFFF	/* Reset & Bypass new PLL dividers */
+	oris   r5,r5,0x4000		/* Set PLL Reset */
+	mtdcr	CPC0_PLLMR1,r5		/* Set clock dividers */
+	rlwinm r5,r5,0,0xBFFFFFFF	/* Clear PLL Reset */
+	mtdcr	CPC0_PLLMR1,r5
+
+		/*
+	! Wait min of 100us for PLL to lock.
+	! See CMOS 27E databook for more info.
+	! At 200MHz, that means waiting 20,000 instructions
+		 */
+	addi	r3,0,20000		/* 2000 = 0x4e20 */
+	mtctr	r3
+pll_wait:
+	bdnz	pll_wait
+
+	oris   r5,r5,0x8000		/* Enable PLL */
+	mtdcr	CPC0_PLLMR1,r5		/* Engage */
+
+	/*
+	 * Reset CPU to guarantee timings are OK
+	 * Not sure if this is needed...
+	 */
+	addis r3,0,0x1000
+	mtspr SPRN_DBCR0,r3		/* This will cause a CPU core reset, and */
+					/* execution will continue from the poweron */
+					/* vector of 0xfffffffc */
+#endif /* CONFIG_405EP */
+
+#if defined(CONFIG_440)
+/*----------------------------------------------------------------------------+
+| mttlb3.
++----------------------------------------------------------------------------*/
+	function_prolog(mttlb3)
+	TLBWE(4,3,2)
+	blr
+	function_epilog(mttlb3)
+
+/*----------------------------------------------------------------------------+
+| mftlb3.
++----------------------------------------------------------------------------*/
+	function_prolog(mftlb3)
+	TLBRE(3,3,2)
+	blr
+	function_epilog(mftlb3)
+
+/*----------------------------------------------------------------------------+
+| mttlb2.
++----------------------------------------------------------------------------*/
+	function_prolog(mttlb2)
+	TLBWE(4,3,1)
+	blr
+	function_epilog(mttlb2)
+
+/*----------------------------------------------------------------------------+
+| mftlb2.
++----------------------------------------------------------------------------*/
+	function_prolog(mftlb2)
+	TLBRE(3,3,1)
+	blr
+	function_epilog(mftlb2)
+
+/*----------------------------------------------------------------------------+
+| mttlb1.
++----------------------------------------------------------------------------*/
+	function_prolog(mttlb1)
+	TLBWE(4,3,0)
+	blr
+	function_epilog(mttlb1)
+
+/*----------------------------------------------------------------------------+
+| mftlb1.
++----------------------------------------------------------------------------*/
+	function_prolog(mftlb1)
+	TLBRE(3,3,0)
+	blr
+	function_epilog(mftlb1)
+#endif /* CONFIG_440 */
+
+#if defined(CONFIG_NAND_SPL)
+/*
+ * void nand_boot_relocate(dst, src, bytes)
+ *
+ * r3 = Destination address to copy code to (in SDRAM)
+ * r4 = Source address to copy code from
+ * r5 = size to copy in bytes
+ */
+nand_boot_relocate:
+	mr	r6,r3
+	mr	r7,r4
+	mflr	r8
+
+	/*
+	 * Copy SPL from icache into SDRAM
+	 */
+	subi	r3,r3,4
+	subi	r4,r4,4
+	srwi	r5,r5,2
+	mtctr	r5
+..spl_loop:
+	lwzu	r0,4(r4)
+	stwu	r0,4(r3)
+	bdnz	..spl_loop
+
+	/*
+	 * Calculate "corrected" link register, so that we "continue"
+	 * in execution in destination range
+	 */
+	sub	r3,r7,r6	/* r3 = src - dst */
+	sub	r8,r8,r3	/* r8 = link-reg - (src - dst) */
+	mtlr	r8
+	blr
+
+nand_boot_common:
+	/*
+	 * First initialize SDRAM. It has to be available *before* calling
+	 * nand_boot().
+	 */
+	lis	r3,CONFIG_SYS_SDRAM_BASE@h
+	ori	r3,r3,CONFIG_SYS_SDRAM_BASE@l
+	bl	initdram
+
+	/*
+	 * Now copy the 4k SPL code into SDRAM and continue execution
+	 * from there.
+	 */
+	lis	r3,CONFIG_SYS_NAND_BOOT_SPL_DST@h
+	ori	r3,r3,CONFIG_SYS_NAND_BOOT_SPL_DST@l
+	lis	r4,CONFIG_SYS_NAND_BOOT_SPL_SRC@h
+	ori	r4,r4,CONFIG_SYS_NAND_BOOT_SPL_SRC@l
+	lis	r5,CONFIG_SYS_NAND_BOOT_SPL_SIZE@h
+	ori	r5,r5,CONFIG_SYS_NAND_BOOT_SPL_SIZE@l
+	bl	nand_boot_relocate
+
+	/*
+	 * We're running from SDRAM now!!!
+	 *
+	 * It is necessary for 4xx systems to relocate from running at
+	 * the original location (0xfffffxxx) to somewhere else (SDRAM
+	 * preferably). This is because CS0 needs to be reconfigured for
+	 * NAND access. And we can't reconfigure this CS when currently
+	 * "running" from it.
+	 */
+
+	/*
+	 * Finally call nand_boot() to load main NAND U-Boot image from
+	 * NAND and jump to it.
+	 */
+	bl	nand_boot		/* will not return */
+#endif /* CONFIG_NAND_SPL */
diff --git a/arch/powerpc/cpu/ppc4xx/tlb.c b/arch/powerpc/cpu/ppc4xx/tlb.c
new file mode 100644
index 0000000..24a9a9c
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/tlb.c
@@ -0,0 +1,352 @@
+/*
+ * (C) Copyright 2007
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_440)
+
+#include <ppc440.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+
+typedef struct region {
+	u64 base;
+	u32 size;
+	u32 tlb_word2_i_value;
+} region_t;
+
+void remove_tlb(u32 vaddr, u32 size)
+{
+	int i;
+	u32 tlb_word0_value;
+	u32 tlb_vaddr;
+	u32 tlb_size = 0;
+
+	for (i=0; i<PPC4XX_TLB_SIZE; i++) {
+		tlb_word0_value = mftlb1(i);
+		tlb_vaddr = TLB_WORD0_EPN_DECODE(tlb_word0_value);
+		if (((tlb_word0_value & TLB_WORD0_V_MASK) == TLB_WORD0_V_ENABLE) &&
+		    (tlb_vaddr >= vaddr)) {
+			/*
+			 * TLB is enabled and start address is lower or equal
+			 * than the area we are looking for. Now we only have
+			 * to check the size/end address for a match.
+			 */
+			switch (tlb_word0_value & TLB_WORD0_SIZE_MASK) {
+			case TLB_WORD0_SIZE_1KB:
+				tlb_size = 1 << 10;
+				break;
+			case TLB_WORD0_SIZE_4KB:
+				tlb_size = 4 << 10;
+				break;
+			case TLB_WORD0_SIZE_16KB:
+				tlb_size = 16 << 10;
+				break;
+			case TLB_WORD0_SIZE_64KB:
+				tlb_size = 64 << 10;
+				break;
+			case TLB_WORD0_SIZE_256KB:
+				tlb_size = 256 << 10;
+				break;
+			case TLB_WORD0_SIZE_1MB:
+				tlb_size = 1 << 20;
+				break;
+			case TLB_WORD0_SIZE_16MB:
+				tlb_size = 16 << 20;
+				break;
+			case TLB_WORD0_SIZE_256MB:
+				tlb_size = 256 << 20;
+				break;
+			}
+
+			/*
+			 * Now check the end-address if it's in the range
+			 */
+			if ((tlb_vaddr + tlb_size - 1) <= (vaddr + size - 1))
+				/*
+				 * Found a TLB in the range.
+				 * Disable it by writing 0 to tlb0 word.
+				 */
+				mttlb1(i, 0);
+		}
+	}
+
+	/* Execute an ISYNC instruction so that the new TLB entry takes effect */
+	asm("isync");
+}
+
+/*
+ * Change the I attribute (cache inhibited) of a TLB or multiple TLB's.
+ * This function is used to either turn cache on or off in a specific
+ * memory area.
+ */
+void change_tlb(u32 vaddr, u32 size, u32 tlb_word2_i_value)
+{
+	int i;
+	u32 tlb_word0_value;
+	u32 tlb_word2_value;
+	u32 tlb_vaddr;
+	u32 tlb_size = 0;
+
+	for (i=0; i<PPC4XX_TLB_SIZE; i++) {
+		tlb_word0_value = mftlb1(i);
+		tlb_vaddr = TLB_WORD0_EPN_DECODE(tlb_word0_value);
+		if (((tlb_word0_value & TLB_WORD0_V_MASK) == TLB_WORD0_V_ENABLE) &&
+		    (tlb_vaddr >= vaddr)) {
+			/*
+			 * TLB is enabled and start address is lower or equal
+			 * than the area we are looking for. Now we only have
+			 * to check the size/end address for a match.
+			 */
+			switch (tlb_word0_value & TLB_WORD0_SIZE_MASK) {
+			case TLB_WORD0_SIZE_1KB:
+				tlb_size = 1 << 10;
+				break;
+			case TLB_WORD0_SIZE_4KB:
+				tlb_size = 4 << 10;
+				break;
+			case TLB_WORD0_SIZE_16KB:
+				tlb_size = 16 << 10;
+				break;
+			case TLB_WORD0_SIZE_64KB:
+				tlb_size = 64 << 10;
+				break;
+			case TLB_WORD0_SIZE_256KB:
+				tlb_size = 256 << 10;
+				break;
+			case TLB_WORD0_SIZE_1MB:
+				tlb_size = 1 << 20;
+				break;
+			case TLB_WORD0_SIZE_16MB:
+				tlb_size = 16 << 20;
+				break;
+			case TLB_WORD0_SIZE_256MB:
+				tlb_size = 256 << 20;
+				break;
+			}
+
+			/*
+			 * Now check the end-address if it's in the range
+			 */
+			if (((tlb_vaddr + tlb_size - 1) <= (vaddr + size - 1)) ||
+			    ((tlb_vaddr < (vaddr + size - 1)) &&
+			     ((tlb_vaddr + tlb_size - 1) > (vaddr + size - 1)))) {
+				/*
+				 * Found a TLB in the range.
+				 * Change cache attribute in tlb2 word.
+				 */
+				tlb_word2_value =
+					TLB_WORD2_U0_DISABLE | TLB_WORD2_U1_DISABLE |
+					TLB_WORD2_U2_DISABLE | TLB_WORD2_U3_DISABLE |
+					TLB_WORD2_W_DISABLE | tlb_word2_i_value |
+					TLB_WORD2_M_DISABLE | TLB_WORD2_G_DISABLE |
+					TLB_WORD2_E_DISABLE | TLB_WORD2_UX_ENABLE |
+					TLB_WORD2_UW_ENABLE | TLB_WORD2_UR_ENABLE |
+					TLB_WORD2_SX_ENABLE | TLB_WORD2_SW_ENABLE |
+					TLB_WORD2_SR_ENABLE;
+
+				/*
+				 * Now either flush or invalidate the dcache
+				 */
+				if (tlb_word2_i_value)
+					flush_dcache();
+				else
+					invalidate_dcache();
+
+				mttlb3(i, tlb_word2_value);
+				asm("iccci 0,0");
+			}
+		}
+	}
+
+	/* Execute an ISYNC instruction so that the new TLB entry takes effect */
+	asm("isync");
+}
+
+static int add_tlb_entry(u64 phys_addr,
+			 u32 virt_addr,
+			 u32 tlb_word0_size_value,
+			 u32 tlb_word2_i_value)
+{
+	int i;
+	unsigned long tlb_word0_value;
+	unsigned long tlb_word1_value;
+	unsigned long tlb_word2_value;
+
+	/* First, find the index of a TLB entry not being used */
+	for (i=0; i<PPC4XX_TLB_SIZE; i++) {
+		tlb_word0_value = mftlb1(i);
+		if ((tlb_word0_value & TLB_WORD0_V_MASK) == TLB_WORD0_V_DISABLE)
+			break;
+	}
+	if (i >= PPC4XX_TLB_SIZE)
+		return -1;
+
+	/* Second, create the TLB entry */
+	tlb_word0_value = TLB_WORD0_EPN_ENCODE(virt_addr) | TLB_WORD0_V_ENABLE |
+		TLB_WORD0_TS_0 | tlb_word0_size_value;
+	tlb_word1_value = TLB_WORD1_RPN_ENCODE((u32)phys_addr) |
+		TLB_WORD1_ERPN_ENCODE(phys_addr >> 32);
+	tlb_word2_value = TLB_WORD2_U0_DISABLE | TLB_WORD2_U1_DISABLE |
+		TLB_WORD2_U2_DISABLE | TLB_WORD2_U3_DISABLE |
+		TLB_WORD2_W_DISABLE | tlb_word2_i_value |
+		TLB_WORD2_M_DISABLE | TLB_WORD2_G_DISABLE |
+		TLB_WORD2_E_DISABLE | TLB_WORD2_UX_ENABLE |
+		TLB_WORD2_UW_ENABLE | TLB_WORD2_UR_ENABLE |
+		TLB_WORD2_SX_ENABLE | TLB_WORD2_SW_ENABLE |
+		TLB_WORD2_SR_ENABLE;
+
+	/* Wait for all memory accesses to complete */
+	sync();
+
+	/* Third, add the TLB entries */
+	mttlb1(i, tlb_word0_value);
+	mttlb2(i, tlb_word1_value);
+	mttlb3(i, tlb_word2_value);
+
+	/* Execute an ISYNC instruction so that the new TLB entry takes effect */
+	asm("isync");
+
+	return 0;
+}
+
+static void program_tlb_addr(u64 phys_addr,
+			     u32 virt_addr,
+			     u32 mem_size,
+			     u32 tlb_word2_i_value)
+{
+	int rc;
+	int tlb_i;
+
+	tlb_i = tlb_word2_i_value;
+	while (mem_size != 0) {
+		rc = 0;
+		/* Add the TLB entries in to map the region. */
+		if (((phys_addr & TLB_256MB_ALIGN_MASK) == phys_addr) &&
+		    (mem_size >= TLB_256MB_SIZE)) {
+			/* Add a 256MB TLB entry */
+			if ((rc = add_tlb_entry(phys_addr, virt_addr,
+						TLB_WORD0_SIZE_256MB, tlb_i)) == 0) {
+				mem_size -= TLB_256MB_SIZE;
+				phys_addr += TLB_256MB_SIZE;
+				virt_addr += TLB_256MB_SIZE;
+			}
+		} else if (((phys_addr & TLB_16MB_ALIGN_MASK) == phys_addr) &&
+			   (mem_size >= TLB_16MB_SIZE)) {
+			/* Add a 16MB TLB entry */
+			if ((rc = add_tlb_entry(phys_addr, virt_addr,
+						TLB_WORD0_SIZE_16MB, tlb_i)) == 0) {
+				mem_size -= TLB_16MB_SIZE;
+				phys_addr += TLB_16MB_SIZE;
+				virt_addr += TLB_16MB_SIZE;
+			}
+		} else if (((phys_addr & TLB_1MB_ALIGN_MASK) == phys_addr) &&
+			   (mem_size >= TLB_1MB_SIZE)) {
+			/* Add a 1MB TLB entry */
+			if ((rc = add_tlb_entry(phys_addr, virt_addr,
+						TLB_WORD0_SIZE_1MB, tlb_i)) == 0) {
+				mem_size -= TLB_1MB_SIZE;
+				phys_addr += TLB_1MB_SIZE;
+				virt_addr += TLB_1MB_SIZE;
+			}
+		} else if (((phys_addr & TLB_256KB_ALIGN_MASK) == phys_addr) &&
+			   (mem_size >= TLB_256KB_SIZE)) {
+			/* Add a 256KB TLB entry */
+			if ((rc = add_tlb_entry(phys_addr, virt_addr,
+						TLB_WORD0_SIZE_256KB, tlb_i)) == 0) {
+				mem_size -= TLB_256KB_SIZE;
+				phys_addr += TLB_256KB_SIZE;
+				virt_addr += TLB_256KB_SIZE;
+			}
+		} else if (((phys_addr & TLB_64KB_ALIGN_MASK) == phys_addr) &&
+			   (mem_size >= TLB_64KB_SIZE)) {
+			/* Add a 64KB TLB entry */
+			if ((rc = add_tlb_entry(phys_addr, virt_addr,
+						TLB_WORD0_SIZE_64KB, tlb_i)) == 0) {
+				mem_size -= TLB_64KB_SIZE;
+				phys_addr += TLB_64KB_SIZE;
+				virt_addr += TLB_64KB_SIZE;
+			}
+		} else if (((phys_addr & TLB_16KB_ALIGN_MASK) == phys_addr) &&
+			   (mem_size >= TLB_16KB_SIZE)) {
+			/* Add a 16KB TLB entry */
+			if ((rc = add_tlb_entry(phys_addr, virt_addr,
+						TLB_WORD0_SIZE_16KB, tlb_i)) == 0) {
+				mem_size -= TLB_16KB_SIZE;
+				phys_addr += TLB_16KB_SIZE;
+				virt_addr += TLB_16KB_SIZE;
+			}
+		} else if (((phys_addr & TLB_4KB_ALIGN_MASK) == phys_addr) &&
+			   (mem_size >= TLB_4KB_SIZE)) {
+			/* Add a 4KB TLB entry */
+			if ((rc = add_tlb_entry(phys_addr, virt_addr,
+						TLB_WORD0_SIZE_4KB, tlb_i)) == 0) {
+				mem_size -= TLB_4KB_SIZE;
+				phys_addr += TLB_4KB_SIZE;
+				virt_addr += TLB_4KB_SIZE;
+			}
+		} else if (((phys_addr & TLB_1KB_ALIGN_MASK) == phys_addr) &&
+			   (mem_size >= TLB_1KB_SIZE)) {
+			/* Add a 1KB TLB entry */
+			if ((rc = add_tlb_entry(phys_addr, virt_addr,
+						TLB_WORD0_SIZE_1KB, tlb_i)) == 0) {
+				mem_size -= TLB_1KB_SIZE;
+				phys_addr += TLB_1KB_SIZE;
+				virt_addr += TLB_1KB_SIZE;
+			}
+		} else {
+			printf("ERROR: no TLB size exists for the base address 0x%llx.\n",
+				phys_addr);
+		}
+
+		if (rc != 0)
+			printf("ERROR: no TLB entries available for the base addr 0x%llx.\n",
+				phys_addr);
+	}
+
+	return;
+}
+
+/*
+ * Program one (or multiple) TLB entries for one memory region
+ *
+ * Common usage for boards with SDRAM DIMM modules to dynamically
+ * configure the TLB's for the SDRAM
+ */
+void program_tlb(u64 phys_addr, u32 virt_addr, u32 size, u32 tlb_word2_i_value)
+{
+	region_t region_array;
+
+	region_array.base = phys_addr;
+	region_array.size = size;
+	region_array.tlb_word2_i_value = tlb_word2_i_value;	/* en-/disable cache */
+
+	/* Call the routine to add in the tlb entries for the memory regions */
+	program_tlb_addr(region_array.base, virt_addr, region_array.size,
+			 region_array.tlb_word2_i_value);
+
+	return;
+}
+
+#endif /* CONFIG_440 */
diff --git a/arch/powerpc/cpu/ppc4xx/traps.c b/arch/powerpc/cpu/ppc4xx/traps.c
new file mode 100644
index 0000000..1616772
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/traps.c
@@ -0,0 +1,409 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+ */
+#define END_OF_MEM	(gd->bd->bi_memstart + gd->bd->bi_memsize)
+
+static __inline__ void set_tsr(unsigned long val)
+{
+#if defined(CONFIG_440)
+	asm volatile("mtspr 0x150, %0" : : "r" (val));
+#else
+	asm volatile("mttsr %0" : : "r" (val));
+#endif
+}
+
+static __inline__ unsigned long get_esr(void)
+{
+	unsigned long val;
+
+#if defined(CONFIG_440)
+	asm volatile("mfspr %0, 0x03e" : "=r" (val) :);
+#else
+	asm volatile("mfesr %0" : "=r" (val) :);
+#endif
+	return val;
+}
+
+#define ESR_MCI 0x80000000
+#define ESR_PIL 0x08000000
+#define ESR_PPR 0x04000000
+#define ESR_PTR 0x02000000
+#define ESR_DST 0x00800000
+#define ESR_DIZ 0x00400000
+#define ESR_U0F 0x00008000
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace(unsigned long *sp)
+{
+	int cnt = 0;
+	unsigned long i;
+
+	printf("Call backtrace: ");
+	while (sp) {
+		if ((uint)sp > END_OF_MEM)
+			break;
+
+		i = sp[1];
+		if (cnt++ % 7 == 0)
+			printf("\n");
+		printf("%08lX ", i);
+		if (cnt > 32) break;
+		sp = (unsigned long *)*sp;
+	}
+	printf("\n");
+}
+
+void show_regs(struct pt_regs * regs)
+{
+	int i;
+
+	printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DEAR: %08lX\n",
+	       regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+	printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+	       regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+	       regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+	       regs->msr&MSR_IR ? 1 : 0,
+	       regs->msr&MSR_DR ? 1 : 0);
+
+	printf("\n");
+	for (i = 0;  i < 32;  i++) {
+		if ((i % 8) == 0) {
+			printf("GPR%02d: ", i);
+		}
+
+		printf("%08lX ", regs->gpr[i]);
+		if ((i % 8) == 7) {
+			printf("\n");
+		}
+	}
+}
+
+
+void
+_exception(int signr, struct pt_regs *regs)
+{
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Exception");
+}
+
+void
+MachineCheckException(struct pt_regs *regs)
+{
+	unsigned long fixup, val;
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+	u32 value2;
+	int corr_ecc = 0;
+	int uncorr_ecc = 0;
+#endif
+
+	if ((fixup = search_exception_table(regs->nip)) != 0) {
+		regs->nip = fixup;
+		val = mfspr(MCSR);
+		/* Clear MCSR */
+		mtspr(SPRN_MCSR, val);
+		return;
+	}
+
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	printf("Machine Check Exception.\n");
+	printf("Caused by (from msr): ");
+	printf("regs %p ", regs);
+
+	val = get_esr();
+
+#if !defined(CONFIG_440) && !defined(CONFIG_405EX)
+	if (val& ESR_IMCP) {
+		printf("Instruction");
+		mtspr(ESR, val & ~ESR_IMCP);
+	} else {
+		printf("Data");
+	}
+	printf(" machine check.\n");
+
+#elif defined(CONFIG_440) || defined(CONFIG_405EX)
+	if (val& ESR_IMCP){
+		printf("Instruction Synchronous Machine Check exception\n");
+		mtspr(SPRN_ESR, val & ~ESR_IMCP);
+	} else {
+		val = mfspr(MCSR);
+		if (val & MCSR_IB)
+			printf("Instruction Read PLB Error\n");
+#if defined(CONFIG_440)
+		if (val & MCSR_DRB)
+			printf("Data Read PLB Error\n");
+		if (val & MCSR_DWB)
+			printf("Data Write PLB Error\n");
+#else
+		if (val & MCSR_DB)
+			printf("Data PLB Error\n");
+#endif
+		if (val & MCSR_TLBP)
+			printf("TLB Parity Error\n");
+		if (val & MCSR_ICP){
+			/*flush_instruction_cache(); */
+			printf("I-Cache Parity Error\n");
+		}
+		if (val & MCSR_DCSP)
+			printf("D-Cache Search Parity Error\n");
+		if (val & MCSR_DCFP)
+			printf("D-Cache Flush Parity Error\n");
+		if (val & MCSR_IMPE)
+			printf("Machine Check exception is imprecise\n");
+
+		/* Clear MCSR */
+		mtspr(SPRN_MCSR, val);
+	}
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+	mfsdram(DDR0_00, val) ;
+	printf("DDR0: DDR0_00 %lx\n", val);
+	val = (val >> 16) & 0xff;
+	if (val & 0x80)
+		printf("DDR0: At least one interrupt active\n");
+	if (val & 0x40)
+		printf("DDR0: DRAM initialization complete.\n");
+	if (val & 0x20) {
+		printf("DDR0: Multiple uncorrectable ECC events.\n");
+		uncorr_ecc = 1;
+	}
+	if (val & 0x10) {
+		printf("DDR0: Single uncorrectable ECC event.\n");
+		uncorr_ecc = 1;
+	}
+	if (val & 0x08) {
+		printf("DDR0: Multiple correctable ECC events.\n");
+		corr_ecc = 1;
+	}
+	if (val & 0x04) {
+		printf("DDR0: Single correctable ECC event.\n");
+		corr_ecc = 1;
+	}
+	if (val & 0x02)
+		printf("Multiple accesses outside the defined"
+		       " physical memory space detected\n");
+	if (val & 0x01)
+		printf("DDR0: Single access outside the defined"
+		       " physical memory space detected.\n");
+
+	mfsdram(DDR0_01, val);
+	val = (val >> 8) & 0x7;
+	switch (val ) {
+	case 0:
+		printf("DDR0: Write Out-of-Range command\n");
+		break;
+	case 1:
+		printf("DDR0: Read Out-of-Range command\n");
+		break;
+	case 2:
+		printf("DDR0: Masked write Out-of-Range command\n");
+		break;
+	case 4:
+		printf("DDR0: Wrap write Out-of-Range command\n");
+		break;
+	case 5:
+		printf("DDR0: Wrap read Out-of-Range command\n");
+		break;
+	default:
+		mfsdram(DDR0_01, value2);
+		printf("DDR0: No DDR0 error know 0x%lx %x\n", val, value2);
+	}
+	mfsdram(DDR0_23, val);
+	if (((val >> 16) & 0xff) && corr_ecc)
+		printf("DDR0: Syndrome for correctable ECC event 0x%lx\n",
+		       (val >> 16) & 0xff);
+	mfsdram(DDR0_23, val);
+	if (((val >> 8) & 0xff) && uncorr_ecc)
+		printf("DDR0: Syndrome for uncorrectable ECC event 0x%lx\n",
+		       (val >> 8) & 0xff);
+	mfsdram(DDR0_33, val);
+	if (val)
+		printf("DDR0: Address of command that caused an "
+		       "Out-of-Range interrupt %lx\n", val);
+	mfsdram(DDR0_34, val);
+	if (val && uncorr_ecc)
+		printf("DDR0: Address of uncorrectable ECC event %lx\n", val);
+	mfsdram(DDR0_35, val);
+	if (val && uncorr_ecc)
+		printf("DDR0: Address of uncorrectable ECC event %lx\n", val);
+	mfsdram(DDR0_36, val);
+	if (val && uncorr_ecc)
+		printf("DDR0: Data of uncorrectable ECC event 0x%08lx\n", val);
+	mfsdram(DDR0_37, val);
+	if (val && uncorr_ecc)
+		printf("DDR0: Data of uncorrectable ECC event 0x%08lx\n", val);
+	mfsdram(DDR0_38, val);
+	if (val && corr_ecc)
+		printf("DDR0: Address of correctable ECC event %lx\n", val);
+	mfsdram(DDR0_39, val);
+	if (val && corr_ecc)
+		printf("DDR0: Address of correctable ECC event %lx\n", val);
+	mfsdram(DDR0_40, val);
+	if (val && corr_ecc)
+		printf("DDR0: Data of correctable ECC event 0x%08lx\n", val);
+	mfsdram(DDR0_41, val);
+	if (val && corr_ecc)
+		printf("DDR0: Data of correctable ECC event 0x%08lx\n", val);
+#endif /* CONFIG_440EPX */
+#endif /* CONFIG_440 */
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+	long esr_val;
+
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	show_regs(regs);
+
+	esr_val = get_esr();
+	if( esr_val & ESR_PIL )
+		printf( "** Illegal Instruction **\n" );
+	else if( esr_val & ESR_PPR )
+		printf( "** Privileged Instruction **\n" );
+	else if( esr_val & ESR_PTR )
+		printf( "** Trap Instruction **\n" );
+
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("Program Check Exception");
+}
+
+void
+DecrementerPITException(struct pt_regs *regs)
+{
+	/*
+	 * Reset PIT interrupt
+	 */
+	set_tsr(0x08000000);
+
+	/*
+	 * Call timer_interrupt routine in interrupts.c
+	 */
+	timer_interrupt(NULL);
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+	if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+		return;
+#endif
+
+	printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+	       regs->nip, regs->msr, regs->trap);
+	_exception(0, regs);
+}
+
+void
+DebugException(struct pt_regs *regs)
+{
+	printf("Debugger trap at @ %lx\n", regs->nip );
+	show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+	do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading.  If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+#if 0
+	int	retval;
+
+	__asm__ __volatile__(			\
+		"1:	lwz %0,0(%1)\n"		\
+		"	eieio\n"		\
+		"	li %0,0\n"		\
+		"2:\n"				\
+		".section .fixup,\"ax\"\n"	\
+		"3:	li %0,-1\n"		\
+		"	b 2b\n"			\
+		".section __ex_table,\"a\"\n"	\
+		"	.align 2\n"		\
+		"	.long 1b,3b\n"		\
+		".text"				\
+		: "=r" (retval) : "r"(addr));
+
+	return (retval);
+#endif
+	return 0;
+}
diff --git a/arch/powerpc/cpu/ppc4xx/u-boot.lds b/arch/powerpc/cpu/ppc4xx/u-boot.lds
new file mode 100644
index 0000000..eca1f9d
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/u-boot.lds
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2007-2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "config.h"	/* CONFIG_BOARDDIR */
+
+#ifndef RESET_VECTOR_ADDRESS
+#define RESET_VECTOR_ADDRESS	0xfffffffc
+#endif
+
+OUTPUT_ARCH(powerpc)
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+PHDRS
+{
+  text PT_LOAD;
+  bss PT_LOAD;
+}
+
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text)	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data)	}
+  .rel.rodata    : { *(.rel.rodata)	}
+  .rela.rodata   : { *(.rela.rodata)	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	}
+  .plt : { *(.plt) }
+  .text      :
+  {
+    *(.text)
+    *(.got1)
+   } :text
+    _etext = .;
+    PROVIDE (etext = .);
+    .rodata    :
+   {
+    *(.eh_frame)
+    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+  } :text
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x00FF) & 0xFFFFFF00;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+  __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  . = .;
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+  . = .;
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(256);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(256);
+  __init_end = .;
+
+#ifdef CONFIG_440
+  .bootpg RESET_VECTOR_ADDRESS - 0xffc :
+  {
+    arch/powerpc/cpu/ppc4xx/start.o	(.bootpg)
+
+    /*
+     * PPC440 board need a board specific object with the
+     * TLB definitions. This needs to get included right after
+     * start.o, since the first shadow TLB only covers 4k
+     * of address space.
+     */
+    CONFIG_BOARDDIR/init.o	(.bootpg)
+  } :text = 0xffff
+#endif
+
+  .resetvec RESET_VECTOR_ADDRESS :
+  {
+    *(.resetvec)
+  } :text = 0xffff
+
+  . = RESET_VECTOR_ADDRESS + 0x4;
+
+  /*
+   * Make sure that the bss segment isn't linked at 0x0, otherwise its
+   * address won't be updated during relocation fixups.  Note that
+   * this is a temporary fix.  Code to dynamically the fixup the bss
+   * location will be added in the future.  When the bss relocation
+   * fixup code is present this workaround should be removed.
+   */
+#if (RESET_VECTOR_ADDRESS == 0xfffffffc)
+  . |= 0x10;
+#endif
+
+  __bss_start = .;
+  .bss (NOLOAD)       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  } :bss
+
+  . = ALIGN(4);
+  _end = . ;
+  PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/ppc4xx/uic.c b/arch/powerpc/cpu/ppc4xx/uic.c
new file mode 100644
index 0000000..8b1b259
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/uic.c
@@ -0,0 +1,180 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002 (440 port)
+ * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com
+ *
+ * (C) Copyright 2003 (440GX port)
+ * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com
+ *
+ * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX)
+ * Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * Work supported by Qtechnology (htpp://qtec.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/interrupt.h>
+#include <ppc4xx.h>
+#include <ppc_asm.tmpl>
+#include <commproc.h>
+
+#if (UIC_MAX > 3)
+#define UICB0_ALL	(UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI) | \
+			 UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI) | \
+			 UIC_MASK(VECNUM_UIC3CI) | UIC_MASK(VECNUM_UIC3NCI))
+#elif (UIC_MAX > 2)
+#define UICB0_ALL	(UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI) | \
+			 UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI))
+#elif (UIC_MAX > 1)
+#define UICB0_ALL	(UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI))
+#else
+#define UICB0_ALL	0
+#endif
+
+u32 get_dcr(u16);
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void pic_enable(void)
+{
+#if (UIC_MAX > 1)
+	/* Install the UIC1 handlers */
+	irq_install_handler(VECNUM_UIC1NCI, (void *)(void *)external_interrupt, 0);
+	irq_install_handler(VECNUM_UIC1CI, (void *)(void *)external_interrupt, 0);
+#endif
+#if (UIC_MAX > 2)
+	irq_install_handler(VECNUM_UIC2NCI, (void *)(void *)external_interrupt, 0);
+	irq_install_handler(VECNUM_UIC2CI, (void *)(void *)external_interrupt, 0);
+#endif
+#if (UIC_MAX > 3)
+	irq_install_handler(VECNUM_UIC3NCI, (void *)(void *)external_interrupt, 0);
+	irq_install_handler(VECNUM_UIC3CI, (void *)(void *)external_interrupt, 0);
+#endif
+}
+
+/* Handler for UIC interrupt */
+static void uic_interrupt(u32 uic_base, int vec_base)
+{
+	u32 uic_msr;
+	u32 msr_shift;
+	int vec;
+
+	/*
+	 * Read masked interrupt status register to determine interrupt source
+	 */
+	uic_msr = get_dcr(uic_base + UIC_MSR);
+	msr_shift = uic_msr;
+	vec = vec_base;
+
+	while (msr_shift != 0) {
+		if (msr_shift & 0x80000000)
+			interrupt_run_handler(vec);
+		/*
+		 * Shift msr to next position and increment vector
+		 */
+		msr_shift <<= 1;
+		vec++;
+	}
+}
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt(struct pt_regs *regs)
+{
+	u32 uic_msr;
+
+	/*
+	 * Read masked interrupt status register to determine interrupt source
+	 */
+	uic_msr = mfdcr(UIC0MSR);
+
+#if (UIC_MAX > 1)
+	if ((UIC_MASK(VECNUM_UIC1CI) & uic_msr) ||
+	    (UIC_MASK(VECNUM_UIC1NCI) & uic_msr))
+		uic_interrupt(UIC1_DCR_BASE, 32);
+#endif
+
+#if (UIC_MAX > 2)
+	if ((UIC_MASK(VECNUM_UIC2CI) & uic_msr) ||
+	    (UIC_MASK(VECNUM_UIC2NCI) & uic_msr))
+		uic_interrupt(UIC2_DCR_BASE, 64);
+#endif
+
+#if (UIC_MAX > 3)
+	if ((UIC_MASK(VECNUM_UIC3CI) & uic_msr) ||
+	    (UIC_MASK(VECNUM_UIC3NCI) & uic_msr))
+		uic_interrupt(UIC3_DCR_BASE, 96);
+#endif
+
+	mtdcr(UIC0SR, (uic_msr & UICB0_ALL));
+
+	if (uic_msr & ~(UICB0_ALL))
+		uic_interrupt(UIC0_DCR_BASE, 0);
+
+	return;
+}
+
+void pic_irq_ack(unsigned int vec)
+{
+	if ((vec >= 0) && (vec < 32))
+		mtdcr(UIC0SR, UIC_MASK(vec));
+	else if ((vec >= 32) && (vec < 64))
+		mtdcr(UIC1SR, UIC_MASK(vec));
+	else if ((vec >= 64) && (vec < 96))
+		mtdcr(UIC2SR, UIC_MASK(vec));
+	else if (vec >= 96)
+		mtdcr(UIC3SR, UIC_MASK(vec));
+}
+
+/*
+ * Install and free a interrupt handler.
+ */
+void pic_irq_enable(unsigned int vec)
+{
+
+	if ((vec >= 0) && (vec < 32))
+		mtdcr(UIC0ER, mfdcr(UIC0ER) | UIC_MASK(vec));
+	else if ((vec >= 32) && (vec < 64))
+		mtdcr(UIC1ER, mfdcr(UIC1ER) | UIC_MASK(vec));
+	else if ((vec >= 64) && (vec < 96))
+		mtdcr(UIC2ER, mfdcr(UIC2ER) | UIC_MASK(vec));
+	else if (vec >= 96)
+		mtdcr(UIC3ER, mfdcr(UIC3ER) | UIC_MASK(vec));
+
+	debug("Install interrupt vector %d\n", vec);
+}
+
+void pic_irq_disable(unsigned int vec)
+{
+	if ((vec >= 0) && (vec < 32))
+		mtdcr(UIC0ER, mfdcr(UIC0ER) & ~UIC_MASK(vec));
+	else if ((vec >= 32) && (vec < 64))
+		mtdcr(UIC1ER, mfdcr(UIC1ER) & ~UIC_MASK(vec));
+	else if ((vec >= 64) && (vec < 96))
+		mtdcr(UIC2ER, mfdcr(UIC2ER) & ~UIC_MASK(vec));
+	else if (vec >= 96)
+		mtdcr(UIC3ER, mfdcr(UIC3ER) & ~UIC_MASK(vec));
+}
diff --git a/arch/powerpc/cpu/ppc4xx/usb.c b/arch/powerpc/cpu/ppc4xx/usb.c
new file mode 100644
index 0000000..592efe7
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/usb.c
@@ -0,0 +1,66 @@
+/*
+ * (C) Copyright 2007
+ * Markus Klotzbuecher, DENX Software Engineering <mk@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT)
+
+#ifdef CONFIG_4xx_DCACHE
+#include <asm/mmu.h>
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+#include "usbdev.h"
+
+int usb_cpu_init(void)
+{
+#ifdef CONFIG_4xx_DCACHE
+	/* disable cache */
+	change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, TLB_WORD2_I_ENABLE);
+#endif
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440EPX)
+	usb_dev_init();
+#endif
+	return 0;
+}
+
+int usb_cpu_stop(void)
+{
+#ifdef CONFIG_4xx_DCACHE
+	/* enable cache */
+	change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, 0);
+#endif
+	return 0;
+}
+
+int usb_cpu_init_fail(void)
+{
+#ifdef CONFIG_4xx_DCACHE
+	/* enable cache */
+	change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, 0);
+#endif
+	return 0;
+}
+
+#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) */
diff --git a/arch/powerpc/cpu/ppc4xx/usb_ohci.c b/arch/powerpc/cpu/ppc4xx/usb_ohci.c
new file mode 100644
index 0000000..a9edacd
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/usb_ohci.c
@@ -0,0 +1,1648 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB on the PPC440EP.
+ *
+ * (C) Copyright 2003-2004
+ * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
+ *
+ * (C) Copyright 2004
+ * Pierre Aubert, Staubli Faverges <p.aubert@staubli.com>
+ *
+ * Note: Much of this code has been derived from Linux 2.4
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+/*
+ * IMPORTANT NOTES
+ * 1 - this driver is intended for use with USB Mass Storage Devices
+ *     (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes!
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_USB_OHCI
+
+#include <malloc.h>
+#include <usb.h>
+#include "usb_ohci.h"
+
+#include "usbdev.h"
+
+#define OHCI_USE_NPS		/* force NoPowerSwitching mode */
+#undef OHCI_VERBOSE_DEBUG	/* not always helpful */
+#undef DEBUG
+#undef SHOW_INFO
+#undef OHCI_FILL_TRACE
+
+/* For initializing controller (mask in an HCFS mode too) */
+#define OHCI_CONTROL_INIT \
+	(OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
+
+#define readl(a) (*((volatile u32 *)(a)))
+#define writel(a, b) (*((volatile u32 *)(b)) = ((volatile u32)a))
+
+#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+
+#ifdef DEBUG
+#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg)
+#else
+#define dbg(format, arg...) do {} while(0)
+#endif /* DEBUG */
+#define err(format, arg...) printf("ERROR: " format "\n", ## arg)
+#ifdef SHOW_INFO
+#define info(format, arg...) printf("INFO: " format "\n", ## arg)
+#else
+#define info(format, arg...) do {} while(0)
+#endif
+
+#define m16_swap(x) swap_16(x)
+#define m32_swap(x) swap_32(x)
+
+#if defined(CONFIG_405EZ) || defined(CONFIG_440EP) || defined(CONFIG_440EPX)
+#define ohci_cpu_to_le16(x) (x)
+#define ohci_cpu_to_le32(x) (x)
+#else
+#define ohci_cpu_to_le16(x) swap_16(x)
+#define ohci_cpu_to_le32(x) swap_32(x)
+#endif
+
+/* global ohci_t */
+static ohci_t gohci;
+/* this must be aligned to a 256 byte boundary */
+struct ohci_hcca ghcca[1];
+/* a pointer to the aligned storage */
+struct ohci_hcca *phcca;
+/* this allocates EDs for all possible endpoints */
+struct ohci_device ohci_dev;
+/* urb_priv */
+urb_priv_t urb_priv;
+/* RHSC flag */
+int got_rhsc;
+/* device which was disconnected */
+struct usb_device *devgone;
+/* flag guarding URB transation */
+int urb_finished = 0;
+
+/*-------------------------------------------------------------------------*/
+
+/* AMD-756 (D2 rev) reports corrupt register contents in some cases.
+ * The erratum (#4) description is incorrect.  AMD's workaround waits
+ * till some bits (mostly reserved) are clear; ok for all revs.
+ */
+#define OHCI_QUIRK_AMD756 0xabcd
+#define read_roothub(hc, register, mask) ({ \
+	u32 temp = readl (&hc->regs->roothub.register); \
+	if (hc->flags & OHCI_QUIRK_AMD756) \
+		while (temp & mask) \
+			temp = readl (&hc->regs->roothub.register); \
+	temp; })
+
+static u32 roothub_a (struct ohci *hc)
+	{ return read_roothub (hc, a, 0xfc0fe000); }
+static inline u32 roothub_b (struct ohci *hc)
+	{ return readl (&hc->regs->roothub.b); }
+static inline u32 roothub_status (struct ohci *hc)
+	{ return readl (&hc->regs->roothub.status); }
+static u32 roothub_portstatus (struct ohci *hc, int i)
+	{ return read_roothub (hc, portstatus [i], 0xffe0fce0); }
+
+
+/* forward declaration */
+static int hc_interrupt (void);
+static void
+td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer,
+	int transfer_len, struct devrequest * setup, urb_priv_t * urb, int interval);
+
+/*-------------------------------------------------------------------------*
+ * URB support functions
+ *-------------------------------------------------------------------------*/
+
+/* free HCD-private data associated with this URB */
+
+static void urb_free_priv (urb_priv_t * urb)
+{
+	int		i;
+	int		last;
+	struct td	* td;
+
+	last = urb->length - 1;
+	if (last >= 0) {
+		for (i = 0; i <= last; i++) {
+			td = urb->td[i];
+			if (td) {
+				td->usb_dev = NULL;
+				urb->td[i] = NULL;
+			}
+		}
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+static int sohci_get_current_frame_number (struct usb_device * dev);
+
+/* debug| print the main components of an URB
+ * small: 0) header + data packets 1) just header */
+
+static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffer,
+	int transfer_len, struct devrequest * setup, char * str, int small)
+{
+	urb_priv_t * purb = &urb_priv;
+
+	dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx",
+			str,
+			sohci_get_current_frame_number (dev),
+			usb_pipedevice (pipe),
+			usb_pipeendpoint (pipe),
+			usb_pipeout (pipe)? 'O': 'I',
+			usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"):
+				(usb_pipecontrol (pipe)? "CTRL": "BULK"),
+			purb->actual_length,
+			transfer_len, dev->status);
+#ifdef	OHCI_VERBOSE_DEBUG
+	if (!small) {
+		int i, len;
+
+		if (usb_pipecontrol (pipe)) {
+			printf (__FILE__ ": cmd(8):");
+			for (i = 0; i < 8 ; i++)
+				printf (" %02x", ((__u8 *) setup) [i]);
+			printf ("\n");
+		}
+		if (transfer_len > 0 && buffer) {
+			printf (__FILE__ ": data(%d/%d):",
+				purb->actual_length,
+				transfer_len);
+			len = usb_pipeout (pipe)?
+					transfer_len: purb->actual_length;
+			for (i = 0; i < 16 && i < len; i++)
+				printf (" %02x", ((__u8 *) buffer) [i]);
+			printf ("%s\n", i < len? "...": "");
+		}
+	}
+#endif
+}
+
+/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/
+void ep_print_int_eds (ohci_t *ohci, char * str) {
+	int i, j;
+	 __u32 * ed_p;
+	for (i= 0; i < 32; i++) {
+		j = 5;
+		ed_p = &(ohci->hcca->int_table [i]);
+		if (*ed_p == 0)
+		    continue;
+		printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i);
+		while (*ed_p != 0 && j--) {
+			ed_t *ed = (ed_t *)ohci_cpu_to_le32(ed_p);
+			printf (" ed: %4x;", ed->hwINFO);
+			ed_p = &ed->hwNextED;
+		}
+		printf ("\n");
+	}
+}
+
+static void ohci_dump_intr_mask (char *label, __u32 mask)
+{
+	dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s",
+		label,
+		mask,
+		(mask & OHCI_INTR_MIE) ? " MIE" : "",
+		(mask & OHCI_INTR_OC) ? " OC" : "",
+		(mask & OHCI_INTR_RHSC) ? " RHSC" : "",
+		(mask & OHCI_INTR_FNO) ? " FNO" : "",
+		(mask & OHCI_INTR_UE) ? " UE" : "",
+		(mask & OHCI_INTR_RD) ? " RD" : "",
+		(mask & OHCI_INTR_SF) ? " SF" : "",
+		(mask & OHCI_INTR_WDH) ? " WDH" : "",
+		(mask & OHCI_INTR_SO) ? " SO" : ""
+		);
+}
+
+static void maybe_print_eds (char *label, __u32 value)
+{
+	ed_t *edp = (ed_t *)value;
+
+	if (value) {
+		dbg ("%s %08x", label, value);
+		dbg ("%08x", edp->hwINFO);
+		dbg ("%08x", edp->hwTailP);
+		dbg ("%08x", edp->hwHeadP);
+		dbg ("%08x", edp->hwNextED);
+	}
+}
+
+static char * hcfs2string (int state)
+{
+	switch (state) {
+		case OHCI_USB_RESET:	return "reset";
+		case OHCI_USB_RESUME:	return "resume";
+		case OHCI_USB_OPER:	return "operational";
+		case OHCI_USB_SUSPEND:	return "suspend";
+	}
+	return "?";
+}
+
+/* dump control and status registers */
+static void ohci_dump_status (ohci_t *controller)
+{
+	struct ohci_regs	*regs = controller->regs;
+	__u32			temp;
+
+	temp = readl (&regs->revision) & 0xff;
+	if (temp != 0x10)
+		dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f));
+
+	temp = readl (&regs->control);
+	dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp,
+		(temp & OHCI_CTRL_RWE) ? " RWE" : "",
+		(temp & OHCI_CTRL_RWC) ? " RWC" : "",
+		(temp & OHCI_CTRL_IR) ? " IR" : "",
+		hcfs2string (temp & OHCI_CTRL_HCFS),
+		(temp & OHCI_CTRL_BLE) ? " BLE" : "",
+		(temp & OHCI_CTRL_CLE) ? " CLE" : "",
+		(temp & OHCI_CTRL_IE) ? " IE" : "",
+		(temp & OHCI_CTRL_PLE) ? " PLE" : "",
+		temp & OHCI_CTRL_CBSR
+		);
+
+	temp = readl (&regs->cmdstatus);
+	dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp,
+		(temp & OHCI_SOC) >> 16,
+		(temp & OHCI_OCR) ? " OCR" : "",
+		(temp & OHCI_BLF) ? " BLF" : "",
+		(temp & OHCI_CLF) ? " CLF" : "",
+		(temp & OHCI_HCR) ? " HCR" : ""
+		);
+
+	ohci_dump_intr_mask ("intrstatus", readl (&regs->intrstatus));
+	ohci_dump_intr_mask ("intrenable", readl (&regs->intrenable));
+
+	maybe_print_eds ("ed_periodcurrent", readl (&regs->ed_periodcurrent));
+
+	maybe_print_eds ("ed_controlhead", readl (&regs->ed_controlhead));
+	maybe_print_eds ("ed_controlcurrent", readl (&regs->ed_controlcurrent));
+
+	maybe_print_eds ("ed_bulkhead", readl (&regs->ed_bulkhead));
+	maybe_print_eds ("ed_bulkcurrent", readl (&regs->ed_bulkcurrent));
+
+	maybe_print_eds ("donehead", readl (&regs->donehead));
+}
+
+static void ohci_dump_roothub (ohci_t *controller, int verbose)
+{
+	__u32			temp, ndp, i;
+
+	temp = roothub_a (controller);
+	ndp = (temp & RH_A_NDP);
+
+	if (verbose) {
+		dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp,
+			((temp & RH_A_POTPGT) >> 24) & 0xff,
+			(temp & RH_A_NOCP) ? " NOCP" : "",
+			(temp & RH_A_OCPM) ? " OCPM" : "",
+			(temp & RH_A_DT) ? " DT" : "",
+			(temp & RH_A_NPS) ? " NPS" : "",
+			(temp & RH_A_PSM) ? " PSM" : "",
+			ndp
+			);
+		temp = roothub_b (controller);
+		dbg ("roothub.b: %08x PPCM=%04x DR=%04x",
+			temp,
+			(temp & RH_B_PPCM) >> 16,
+			(temp & RH_B_DR)
+			);
+		temp = roothub_status (controller);
+		dbg ("roothub.status: %08x%s%s%s%s%s%s",
+			temp,
+			(temp & RH_HS_CRWE) ? " CRWE" : "",
+			(temp & RH_HS_OCIC) ? " OCIC" : "",
+			(temp & RH_HS_LPSC) ? " LPSC" : "",
+			(temp & RH_HS_DRWE) ? " DRWE" : "",
+			(temp & RH_HS_OCI) ? " OCI" : "",
+			(temp & RH_HS_LPS) ? " LPS" : ""
+			);
+	}
+
+	for (i = 0; i < ndp; i++) {
+		temp = roothub_portstatus (controller, i);
+		dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s",
+			i,
+			temp,
+			(temp & RH_PS_PRSC) ? " PRSC" : "",
+			(temp & RH_PS_OCIC) ? " OCIC" : "",
+			(temp & RH_PS_PSSC) ? " PSSC" : "",
+			(temp & RH_PS_PESC) ? " PESC" : "",
+			(temp & RH_PS_CSC) ? " CSC" : "",
+
+			(temp & RH_PS_LSDA) ? " LSDA" : "",
+			(temp & RH_PS_PPS) ? " PPS" : "",
+			(temp & RH_PS_PRS) ? " PRS" : "",
+			(temp & RH_PS_POCI) ? " POCI" : "",
+			(temp & RH_PS_PSS) ? " PSS" : "",
+
+			(temp & RH_PS_PES) ? " PES" : "",
+			(temp & RH_PS_CCS) ? " CCS" : ""
+			);
+	}
+}
+
+static void ohci_dump (ohci_t *controller, int verbose)
+{
+	dbg ("OHCI controller usb-%s state", controller->slot_name);
+
+	/* dumps some of the state we know about */
+	ohci_dump_status (controller);
+	if (verbose)
+		ep_print_int_eds (controller, "hcca");
+	dbg ("hcca frame #%04x", controller->hcca->frame_no);
+	ohci_dump_roothub (controller, 1);
+}
+
+
+#endif /* DEBUG */
+
+/*-------------------------------------------------------------------------*
+ * Interface functions (URB)
+ *-------------------------------------------------------------------------*/
+
+/* get a transfer request */
+
+int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer,
+		int transfer_len, struct devrequest *setup, int interval)
+{
+	ohci_t *ohci;
+	ed_t * ed;
+	urb_priv_t *purb_priv;
+	int i, size = 0;
+
+	ohci = &gohci;
+
+	/* when controller's hung, permit only roothub cleanup attempts
+	 * such as powering down ports */
+	if (ohci->disabled) {
+		err("sohci_submit_job: EPIPE");
+		return -1;
+	}
+
+	/* if we have an unfinished URB from previous transaction let's
+	 * fail and scream as quickly as possible so as not to corrupt
+	 * further communication */
+	if (!urb_finished) {
+		err("sohci_submit_job: URB NOT FINISHED");
+		return -1;
+	}
+	/* we're about to begin a new transaction here so mark the URB unfinished */
+	urb_finished = 0;
+
+	/* every endpoint has a ed, locate and fill it */
+	if (!(ed = ep_add_ed (dev, pipe))) {
+		err("sohci_submit_job: ENOMEM");
+		return -1;
+	}
+
+	/* for the private part of the URB we need the number of TDs (size) */
+	switch (usb_pipetype (pipe)) {
+		case PIPE_BULK: /* one TD for every 4096 Byte */
+			size = (transfer_len - 1) / 4096 + 1;
+			break;
+		case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */
+			size = (transfer_len == 0)? 2:
+						(transfer_len - 1) / 4096 + 3;
+			break;
+	}
+
+	if (size >= (N_URB_TD - 1)) {
+		err("need %d TDs, only have %d", size, N_URB_TD);
+		return -1;
+	}
+	purb_priv = &urb_priv;
+	purb_priv->pipe = pipe;
+
+	/* fill the private part of the URB */
+	purb_priv->length = size;
+	purb_priv->ed = ed;
+	purb_priv->actual_length = 0;
+
+	/* allocate the TDs */
+	/* note that td[0] was allocated in ep_add_ed */
+	for (i = 0; i < size; i++) {
+		purb_priv->td[i] = td_alloc (dev);
+		if (!purb_priv->td[i]) {
+			purb_priv->length = i;
+			urb_free_priv (purb_priv);
+			err("sohci_submit_job: ENOMEM");
+			return -1;
+		}
+	}
+
+	if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
+		urb_free_priv (purb_priv);
+		err("sohci_submit_job: EINVAL");
+		return -1;
+	}
+
+	/* link the ed into a chain if is not already */
+	if (ed->state != ED_OPER)
+		ep_link (ohci, ed);
+
+	/* fill the TDs and link it to the ed */
+	td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, interval);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+/* tell us the current USB frame number */
+
+static int sohci_get_current_frame_number (struct usb_device *usb_dev)
+{
+	ohci_t *ohci = &gohci;
+
+	return ohci_cpu_to_le16 (ohci->hcca->frame_no);
+}
+#endif
+
+/*-------------------------------------------------------------------------*
+ * ED handling functions
+ *-------------------------------------------------------------------------*/
+
+/* link an ed into one of the HC chains */
+
+static int ep_link (ohci_t *ohci, ed_t *edi)
+{
+	volatile ed_t *ed = edi;
+
+	ed->state = ED_OPER;
+
+	switch (ed->type) {
+	case PIPE_CONTROL:
+		ed->hwNextED = 0;
+		if (ohci->ed_controltail == NULL) {
+			writel (ed, &ohci->regs->ed_controlhead);
+		} else {
+			ohci->ed_controltail->hwNextED = ohci_cpu_to_le32 ((unsigned long)ed);
+		}
+		ed->ed_prev = ohci->ed_controltail;
+		if (!ohci->ed_controltail && !ohci->ed_rm_list[0] &&
+			!ohci->ed_rm_list[1] && !ohci->sleeping) {
+			ohci->hc_control |= OHCI_CTRL_CLE;
+			writel (ohci->hc_control, &ohci->regs->control);
+		}
+		ohci->ed_controltail = edi;
+		break;
+
+	case PIPE_BULK:
+		ed->hwNextED = 0;
+		if (ohci->ed_bulktail == NULL) {
+			writel (ed, &ohci->regs->ed_bulkhead);
+		} else {
+			ohci->ed_bulktail->hwNextED = ohci_cpu_to_le32 ((unsigned long)ed);
+		}
+		ed->ed_prev = ohci->ed_bulktail;
+		if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] &&
+			!ohci->ed_rm_list[1] && !ohci->sleeping) {
+			ohci->hc_control |= OHCI_CTRL_BLE;
+			writel (ohci->hc_control, &ohci->regs->control);
+		}
+		ohci->ed_bulktail = edi;
+		break;
+	}
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* unlink an ed from one of the HC chains.
+ * just the link to the ed is unlinked.
+ * the link from the ed still points to another operational ed or 0
+ * so the HC can eventually finish the processing of the unlinked ed */
+
+static int ep_unlink (ohci_t *ohci, ed_t *edi)
+{
+	volatile ed_t *ed = edi;
+
+	ed->hwINFO |= ohci_cpu_to_le32 (OHCI_ED_SKIP);
+
+	switch (ed->type) {
+	case PIPE_CONTROL:
+		if (ed->ed_prev == NULL) {
+			if (!ed->hwNextED) {
+				ohci->hc_control &= ~OHCI_CTRL_CLE;
+				writel (ohci->hc_control, &ohci->regs->control);
+			}
+			writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_controlhead);
+		} else {
+			ed->ed_prev->hwNextED = ed->hwNextED;
+		}
+		if (ohci->ed_controltail == ed) {
+			ohci->ed_controltail = ed->ed_prev;
+		} else {
+			((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
+		}
+		break;
+
+	case PIPE_BULK:
+		if (ed->ed_prev == NULL) {
+			if (!ed->hwNextED) {
+				ohci->hc_control &= ~OHCI_CTRL_BLE;
+				writel (ohci->hc_control, &ohci->regs->control);
+			}
+			writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_bulkhead);
+		} else {
+			ed->ed_prev->hwNextED = ed->hwNextED;
+		}
+		if (ohci->ed_bulktail == ed) {
+			ohci->ed_bulktail = ed->ed_prev;
+		} else {
+			((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
+		}
+		break;
+	}
+	ed->state = ED_UNLINK;
+	return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/* add/reinit an endpoint; this should be done once at the usb_set_configuration command,
+ * but the USB stack is a little bit stateless	so we do it at every transaction
+ * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK
+ * in all other cases the state is left unchanged
+ * the ed info fields are setted anyway even though most of them should not change */
+
+static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe)
+{
+	td_t *td;
+	ed_t *ed_ret;
+	volatile ed_t *ed;
+
+	ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint (pipe) << 1) |
+			(usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))];
+
+	if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) {
+		err("ep_add_ed: pending delete");
+		/* pending delete request */
+		return NULL;
+	}
+
+	if (ed->state == ED_NEW) {
+		ed->hwINFO = ohci_cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */
+		/* dummy td; end of td list for ed */
+		td = td_alloc (usb_dev);
+		ed->hwTailP = ohci_cpu_to_le32 ((unsigned long)td);
+		ed->hwHeadP = ed->hwTailP;
+		ed->state = ED_UNLINK;
+		ed->type = usb_pipetype (pipe);
+		ohci_dev.ed_cnt++;
+	}
+
+	ed->hwINFO = ohci_cpu_to_le32 (usb_pipedevice (pipe)
+			| usb_pipeendpoint (pipe) << 7
+			| (usb_pipeisoc (pipe)? 0x8000: 0)
+			| (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000))
+			| usb_pipeslow (pipe) << 13
+			| usb_maxpacket (usb_dev, pipe) << 16);
+
+	return ed_ret;
+}
+
+/*-------------------------------------------------------------------------*
+ * TD handling functions
+ *-------------------------------------------------------------------------*/
+
+/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
+
+static void td_fill (ohci_t *ohci, unsigned int info,
+	void *data, int len,
+	struct usb_device *dev, int index, urb_priv_t *urb_priv)
+{
+	volatile td_t  *td, *td_pt;
+#ifdef OHCI_FILL_TRACE
+	int i;
+#endif
+
+	if (index > urb_priv->length) {
+		err("index > length");
+		return;
+	}
+	/* use this td as the next dummy */
+	td_pt = urb_priv->td [index];
+	td_pt->hwNextTD = 0;
+
+	/* fill the old dummy TD */
+	td = urb_priv->td [index] = (td_t *)(ohci_cpu_to_le32 (urb_priv->ed->hwTailP) & ~0xf);
+
+	td->ed = urb_priv->ed;
+	td->next_dl_td = NULL;
+	td->index = index;
+	td->data = (__u32)data;
+#ifdef OHCI_FILL_TRACE
+	if (usb_pipebulk(urb_priv->pipe) && usb_pipeout(urb_priv->pipe)) {
+		for (i = 0; i < len; i++)
+		printf("td->data[%d] %#2x ",i, ((unsigned char *)td->data)[i]);
+		printf("\n");
+	}
+#endif
+	if (!len)
+		data = 0;
+
+	td->hwINFO = ohci_cpu_to_le32 (info);
+	td->hwCBP = ohci_cpu_to_le32 ((unsigned long)data);
+	if (data)
+		td->hwBE = ohci_cpu_to_le32 ((unsigned long)(data + len - 1));
+	else
+		td->hwBE = 0;
+	td->hwNextTD = ohci_cpu_to_le32 ((unsigned long)td_pt);
+
+	/* append to queue */
+	td->ed->hwTailP = td->hwNextTD;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* prepare all TDs of a transfer */
+static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer,
+	int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval)
+{
+	ohci_t *ohci = &gohci;
+	int data_len = transfer_len;
+	void *data;
+	int cnt = 0;
+	__u32 info = 0;
+	unsigned int toggle = 0;
+
+	/* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */
+	if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) {
+		toggle = TD_T_TOGGLE;
+	} else {
+		toggle = TD_T_DATA0;
+		usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1);
+	}
+	urb->td_cnt = 0;
+	if (data_len)
+		data = buffer;
+	else
+		data = 0;
+
+	switch (usb_pipetype (pipe)) {
+	case PIPE_BULK:
+		info = usb_pipeout (pipe)?
+			TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ;
+		while(data_len > 4096) {
+			td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, dev, cnt, urb);
+			data += 4096; data_len -= 4096; cnt++;
+		}
+		info = usb_pipeout (pipe)?
+			TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
+		td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, dev, cnt, urb);
+		cnt++;
+
+		if (!ohci->sleeping)
+			writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
+		break;
+
+	case PIPE_CONTROL:
+		info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
+		td_fill (ohci, info, setup, 8, dev, cnt++, urb);
+		if (data_len > 0) {
+			info = usb_pipeout (pipe)?
+				TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1;
+			/* NOTE:  mishandles transfers >8K, some >4K */
+			td_fill (ohci, info, data, data_len, dev, cnt++, urb);
+		}
+		info = usb_pipeout (pipe)?
+			TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1;
+		td_fill (ohci, info, data, 0, dev, cnt++, urb);
+		if (!ohci->sleeping)
+			writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
+		break;
+	}
+	if (urb->length != cnt)
+		dbg("TD LENGTH %d != CNT %d", urb->length, cnt);
+}
+
+/*-------------------------------------------------------------------------*
+ * Done List handling functions
+ *-------------------------------------------------------------------------*/
+
+
+/* calculate the transfer length and update the urb */
+
+static void dl_transfer_length(td_t * td)
+{
+	__u32 tdINFO, tdBE, tdCBP;
+	urb_priv_t *lurb_priv = &urb_priv;
+
+	tdINFO = ohci_cpu_to_le32 (td->hwINFO);
+	tdBE   = ohci_cpu_to_le32 (td->hwBE);
+	tdCBP  = ohci_cpu_to_le32 (td->hwCBP);
+
+
+	if (!(usb_pipecontrol(lurb_priv->pipe) &&
+	    ((td->index == 0) || (td->index == lurb_priv->length - 1)))) {
+		if (tdBE != 0) {
+			if (td->hwCBP == 0)
+				lurb_priv->actual_length += tdBE - td->data + 1;
+			else
+				lurb_priv->actual_length += tdCBP - td->data;
+		}
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* replies to the request have to be on a FIFO basis so
+ * we reverse the reversed done-list */
+
+static td_t * dl_reverse_done_list (ohci_t *ohci)
+{
+	__u32 td_list_hc;
+	td_t *td_rev = NULL;
+	td_t *td_list = NULL;
+	urb_priv_t *lurb_priv = NULL;
+
+	td_list_hc = ohci_cpu_to_le32 (ohci->hcca->done_head) & 0xfffffff0;
+	ohci->hcca->done_head = 0;
+
+	while (td_list_hc) {
+		td_list = (td_t *)td_list_hc;
+
+		if (TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO))) {
+			lurb_priv = &urb_priv;
+			dbg(" USB-error/status: %x : %p",
+					TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO)), td_list);
+			if (td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x1)) {
+				if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) {
+					td_list->ed->hwHeadP =
+						(lurb_priv->td[lurb_priv->length - 1]->hwNextTD & ohci_cpu_to_le32 (0xfffffff0)) |
+									(td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x2));
+					lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1;
+				} else
+					td_list->ed->hwHeadP &= ohci_cpu_to_le32 (0xfffffff2);
+			}
+#ifdef CONFIG_MPC5200
+			td_list->hwNextTD = 0;
+#endif
+		}
+
+		td_list->next_dl_td = td_rev;
+		td_rev = td_list;
+		td_list_hc = ohci_cpu_to_le32 (td_list->hwNextTD) & 0xfffffff0;
+	}
+	return td_list;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* td done list */
+static int dl_done_list (ohci_t *ohci, td_t *td_list)
+{
+	td_t *td_list_next = NULL;
+	ed_t *ed;
+	int cc = 0;
+	int stat = 0;
+	/* urb_t *urb; */
+	urb_priv_t *lurb_priv;
+	__u32 tdINFO, edHeadP, edTailP;
+
+	while (td_list) {
+		td_list_next = td_list->next_dl_td;
+
+		lurb_priv = &urb_priv;
+		tdINFO = ohci_cpu_to_le32 (td_list->hwINFO);
+
+		ed = td_list->ed;
+
+		dl_transfer_length(td_list);
+
+		/* error code of transfer */
+		cc = TD_CC_GET (tdINFO);
+		if (++(lurb_priv->td_cnt) == lurb_priv->length) {
+			if ((ed->state & (ED_OPER | ED_UNLINK))
+					&& (lurb_priv->state != URB_DEL)) {
+				dbg("ConditionCode %#x", cc);
+				stat = cc_to_error[cc];
+				urb_finished = 1;
+			}
+		}
+
+		if (ed->state != ED_NEW) {
+			edHeadP = ohci_cpu_to_le32 (ed->hwHeadP) & 0xfffffff0;
+			edTailP = ohci_cpu_to_le32 (ed->hwTailP);
+
+			/* unlink eds if they are not busy */
+			if ((edHeadP == edTailP) && (ed->state == ED_OPER))
+				ep_unlink (ohci, ed);
+		}
+
+		td_list = td_list_next;
+	}
+	return stat;
+}
+
+/*-------------------------------------------------------------------------*
+ * Virtual Root Hub
+ *-------------------------------------------------------------------------*/
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] =
+{
+	0x12,	    /*	__u8  bLength; */
+	0x01,	    /*	__u8  bDescriptorType; Device */
+	0x10,	    /*	__u16 bcdUSB; v1.1 */
+	0x01,
+	0x09,	    /*	__u8  bDeviceClass; HUB_CLASSCODE */
+	0x00,	    /*	__u8  bDeviceSubClass; */
+	0x00,	    /*	__u8  bDeviceProtocol; */
+	0x08,	    /*	__u8  bMaxPacketSize0; 8 Bytes */
+	0x00,	    /*	__u16 idVendor; */
+	0x00,
+	0x00,	    /*	__u16 idProduct; */
+	0x00,
+	0x00,	    /*	__u16 bcdDevice; */
+	0x00,
+	0x00,	    /*	__u8  iManufacturer; */
+	0x01,	    /*	__u8  iProduct; */
+	0x00,	    /*	__u8  iSerialNumber; */
+	0x01	    /*	__u8  bNumConfigurations; */
+};
+
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+	0x09,	    /*	__u8  bLength; */
+	0x02,	    /*	__u8  bDescriptorType; Configuration */
+	0x19,	    /*	__u16 wTotalLength; */
+	0x00,
+	0x01,	    /*	__u8  bNumInterfaces; */
+	0x01,	    /*	__u8  bConfigurationValue; */
+	0x00,	    /*	__u8  iConfiguration; */
+	0x40,	    /*	__u8  bmAttributes;
+		 Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+	0x00,	    /*	__u8  MaxPower; */
+
+	/* interface */
+	0x09,	    /*	__u8  if_bLength; */
+	0x04,	    /*	__u8  if_bDescriptorType; Interface */
+	0x00,	    /*	__u8  if_bInterfaceNumber; */
+	0x00,	    /*	__u8  if_bAlternateSetting; */
+	0x01,	    /*	__u8  if_bNumEndpoints; */
+	0x09,	    /*	__u8  if_bInterfaceClass; HUB_CLASSCODE */
+	0x00,	    /*	__u8  if_bInterfaceSubClass; */
+	0x00,	    /*	__u8  if_bInterfaceProtocol; */
+	0x00,	    /*	__u8  if_iInterface; */
+
+	/* endpoint */
+	0x07,	    /*	__u8  ep_bLength; */
+	0x05,	    /*	__u8  ep_bDescriptorType; Endpoint */
+	0x81,	    /*	__u8  ep_bEndpointAddress; IN Endpoint 1 */
+	0x03,	    /*	__u8  ep_bmAttributes; Interrupt */
+	0x02,	    /*	__u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+	0x00,
+	0xff	    /*	__u8  ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] =
+{
+	0x04,			/*  __u8  bLength; */
+	0x03,			/*  __u8  bDescriptorType; String-descriptor */
+	0x09,			/*  __u8  lang ID */
+	0x04,			/*  __u8  lang ID */
+};
+
+static unsigned char root_hub_str_index1[] =
+{
+	28,			/*  __u8  bLength; */
+	0x03,			/*  __u8  bDescriptorType; String-descriptor */
+	'O',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'H',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'C',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'I',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	' ',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'R',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'o',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'o',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	't',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	' ',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'H',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'u',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'b',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+};
+
+/* Hub class-specific descriptor is constructed dynamically */
+
+
+/*-------------------------------------------------------------------------*/
+
+#define OK(x)			len = (x); break
+#ifdef DEBUG
+#define WR_RH_STAT(x)		{info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);}
+#define WR_RH_PORTSTAT(x)	{info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);}
+#else
+#define WR_RH_STAT(x)		writel((x), &gohci.regs->roothub.status)
+#define WR_RH_PORTSTAT(x)	writel((x), &gohci.regs->roothub.portstatus[wIndex-1])
+#endif
+#define RD_RH_STAT		roothub_status(&gohci)
+#define RD_RH_PORTSTAT		roothub_portstatus(&gohci,wIndex-1)
+
+/* request to virtual root hub */
+
+int rh_check_port_status(ohci_t *controller)
+{
+	__u32 temp, ndp, i;
+	int res;
+
+	res = -1;
+	temp = roothub_a (controller);
+	ndp = (temp & RH_A_NDP);
+	for (i = 0; i < ndp; i++) {
+		temp = roothub_portstatus (controller, i);
+		/* check for a device disconnect */
+		if (((temp & (RH_PS_PESC | RH_PS_CSC)) ==
+			(RH_PS_PESC | RH_PS_CSC)) &&
+			((temp & RH_PS_CCS) == 0)) {
+			res = i;
+			break;
+		}
+	}
+	return res;
+}
+
+static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+		void *buffer, int transfer_len, struct devrequest *cmd)
+{
+	void * data = buffer;
+	int leni = transfer_len;
+	int len = 0;
+	int stat = 0;
+	__u32 datab[4];
+	__u8 *data_buf = (__u8 *)datab;
+	__u16 bmRType_bReq;
+	__u16 wValue;
+	__u16 wIndex;
+	__u16 wLength;
+
+#ifdef DEBUG
+urb_priv.actual_length = 0;
+pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));
+#endif
+	if (usb_pipeint(pipe)) {
+		info("Root-Hub submit IRQ: NOT implemented");
+		return 0;
+	}
+
+	bmRType_bReq  = cmd->requesttype | (cmd->request << 8);
+	wValue	      = m16_swap (cmd->value);
+	wIndex	      = m16_swap (cmd->index);
+	wLength	      = m16_swap (cmd->length);
+
+	info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x",
+		dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
+
+	switch (bmRType_bReq) {
+	/* Request Destination:
+	   without flags: Device,
+	   RH_INTERFACE: interface,
+	   RH_ENDPOINT: endpoint,
+	   RH_CLASS means HUB here,
+	   RH_OTHER | RH_CLASS	almost ever means HUB_PORT here
+	*/
+
+	case RH_GET_STATUS:
+			*(__u16 *) data_buf = m16_swap (1); OK (2);
+	case RH_GET_STATUS | RH_INTERFACE:
+			*(__u16 *) data_buf = m16_swap (0); OK (2);
+	case RH_GET_STATUS | RH_ENDPOINT:
+			*(__u16 *) data_buf = m16_swap (0); OK (2);
+	case RH_GET_STATUS | RH_CLASS:
+			*(__u32 *) data_buf = m32_swap (
+				RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));
+			OK (4);
+	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+			*(__u32 *) data_buf = m32_swap (RD_RH_PORTSTAT); OK (4);
+
+	case RH_CLEAR_FEATURE | RH_ENDPOINT:
+		switch (wValue) {
+			case (RH_ENDPOINT_STALL): OK (0);
+		}
+		break;
+
+	case RH_CLEAR_FEATURE | RH_CLASS:
+		switch (wValue) {
+			case RH_C_HUB_LOCAL_POWER:
+				OK(0);
+			case (RH_C_HUB_OVER_CURRENT):
+					WR_RH_STAT(RH_HS_OCIC); OK (0);
+		}
+		break;
+
+	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+		switch (wValue) {
+			case (RH_PORT_ENABLE):
+					WR_RH_PORTSTAT (RH_PS_CCS ); OK (0);
+			case (RH_PORT_SUSPEND):
+					WR_RH_PORTSTAT (RH_PS_POCI); OK (0);
+			case (RH_PORT_POWER):
+					WR_RH_PORTSTAT (RH_PS_LSDA); OK (0);
+			case (RH_C_PORT_CONNECTION):
+					WR_RH_PORTSTAT (RH_PS_CSC ); OK (0);
+			case (RH_C_PORT_ENABLE):
+					WR_RH_PORTSTAT (RH_PS_PESC); OK (0);
+			case (RH_C_PORT_SUSPEND):
+					WR_RH_PORTSTAT (RH_PS_PSSC); OK (0);
+			case (RH_C_PORT_OVER_CURRENT):
+					WR_RH_PORTSTAT (RH_PS_OCIC); OK (0);
+			case (RH_C_PORT_RESET):
+					WR_RH_PORTSTAT (RH_PS_PRSC); OK (0);
+		}
+		break;
+
+	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+		switch (wValue) {
+			case (RH_PORT_SUSPEND):
+					WR_RH_PORTSTAT (RH_PS_PSS ); OK (0);
+			case (RH_PORT_RESET): /* BUG IN HUP CODE *********/
+					if (RD_RH_PORTSTAT & RH_PS_CCS)
+					    WR_RH_PORTSTAT (RH_PS_PRS);
+					OK (0);
+			case (RH_PORT_POWER):
+					WR_RH_PORTSTAT (RH_PS_PPS ); OK (0);
+			case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/
+					if (RD_RH_PORTSTAT & RH_PS_CCS)
+					    WR_RH_PORTSTAT (RH_PS_PES );
+					OK (0);
+		}
+		break;
+
+	case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0);
+
+	case RH_GET_DESCRIPTOR:
+		switch ((wValue & 0xff00) >> 8) {
+			case (0x01): /* device descriptor */
+				len = min_t(unsigned int,
+					  leni,
+					  min_t(unsigned int,
+					      sizeof (root_hub_dev_des),
+					      wLength));
+				data_buf = root_hub_dev_des; OK(len);
+			case (0x02): /* configuration descriptor */
+				len = min_t(unsigned int,
+					  leni,
+					  min_t(unsigned int,
+					      sizeof (root_hub_config_des),
+					      wLength));
+				data_buf = root_hub_config_des; OK(len);
+			case (0x03): /* string descriptors */
+				if(wValue==0x0300) {
+					len = min_t(unsigned int,
+						  leni,
+						  min_t(unsigned int,
+						      sizeof (root_hub_str_index0),
+						      wLength));
+					data_buf = root_hub_str_index0;
+					OK(len);
+				}
+				if(wValue==0x0301) {
+					len = min_t(unsigned int,
+						  leni,
+						  min_t(unsigned int,
+						      sizeof (root_hub_str_index1),
+						      wLength));
+					data_buf = root_hub_str_index1;
+					OK(len);
+			}
+			default:
+				stat = USB_ST_STALLED;
+		}
+		break;
+
+	case RH_GET_DESCRIPTOR | RH_CLASS:
+	    {
+		    __u32 temp = roothub_a (&gohci);
+
+		    data_buf [0] = 9;		/* min length; */
+		    data_buf [1] = 0x29;
+		    data_buf [2] = temp & RH_A_NDP;
+		    data_buf [3] = 0;
+		    if (temp & RH_A_PSM)	/* per-port power switching? */
+			data_buf [3] |= 0x1;
+		    if (temp & RH_A_NOCP)	/* no overcurrent reporting? */
+			data_buf [3] |= 0x10;
+		    else if (temp & RH_A_OCPM)	/* per-port overcurrent reporting? */
+			data_buf [3] |= 0x8;
+
+		    /* corresponds to data_buf[4-7] */
+		    datab [1] = 0;
+		    data_buf [5] = (temp & RH_A_POTPGT) >> 24;
+		    temp = roothub_b (&gohci);
+		    data_buf [7] = temp & RH_B_DR;
+		    if (data_buf [2] < 7) {
+			data_buf [8] = 0xff;
+		    } else {
+			data_buf [0] += 2;
+			data_buf [8] = (temp & RH_B_DR) >> 8;
+			data_buf [10] = data_buf [9] = 0xff;
+		    }
+
+		    len = min_t(unsigned int, leni,
+			      min_t(unsigned int, data_buf [0], wLength));
+		    OK (len);
+		}
+
+	case RH_GET_CONFIGURATION:	*(__u8 *) data_buf = 0x01; OK (1);
+
+	case RH_SET_CONFIGURATION:	WR_RH_STAT (0x10000); OK (0);
+
+	default:
+		dbg ("unsupported root hub command");
+		stat = USB_ST_STALLED;
+	}
+
+#ifdef	DEBUG
+	ohci_dump_roothub (&gohci, 1);
+#endif
+
+	len = min_t(int, len, leni);
+	if (data != data_buf)
+	    memcpy (data, data_buf, len);
+	dev->act_len = len;
+	dev->status = stat;
+
+#ifdef DEBUG
+	if (transfer_len)
+		urb_priv.actual_length = transfer_len;
+	pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/);
+#endif
+
+	return stat;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* common code for handling submit messages - used for all but root hub */
+/* accesses. */
+int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		int transfer_len, struct devrequest *setup, int interval)
+{
+	int stat = 0;
+	int maxsize = usb_maxpacket(dev, pipe);
+	int timeout;
+
+	/* device pulled? Shortcut the action. */
+	if (devgone == dev) {
+		dev->status = USB_ST_CRC_ERR;
+		return 0;
+	}
+
+#ifdef DEBUG
+	urb_priv.actual_length = 0;
+	pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
+#endif
+	if (!maxsize) {
+		err("submit_common_message: pipesize for pipe %lx is zero",
+			pipe);
+		return -1;
+	}
+
+	if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < 0) {
+		err("sohci_submit_job failed");
+		return -1;
+	}
+
+	/* allow more time for a BULK device to react - some are slow */
+#define BULK_TO	 5000	/* timeout in milliseconds */
+	if (usb_pipebulk(pipe))
+		timeout = BULK_TO;
+	else
+		timeout = 100;
+
+	/* wait for it to complete */
+	for (;;) {
+		/* check whether the controller is done */
+		stat = hc_interrupt();
+		if (stat < 0) {
+			stat = USB_ST_CRC_ERR;
+			break;
+		}
+
+		/* NOTE: since we are not interrupt driven in U-Boot and always
+		 * handle only one URB at a time, we cannot assume the
+		 * transaction finished on the first successful return from
+		 * hc_interrupt().. unless the flag for current URB is set,
+		 * meaning that all TD's to/from device got actually
+		 * transferred and processed. If the current URB is not
+		 * finished we need to re-iterate this loop so as
+		 * hc_interrupt() gets called again as there needs to be some
+		 * more TD's to process still */
+		if ((stat >= 0) && (stat != 0xff) && (urb_finished)) {
+			/* 0xff is returned for an SF-interrupt */
+			break;
+		}
+
+		if (--timeout) {
+			wait_ms(1);
+			if (!urb_finished)
+				dbg("\%");
+
+		} else {
+			err("CTL:TIMEOUT ");
+			dbg("submit_common_msg: TO status %x\n", stat);
+			stat = USB_ST_CRC_ERR;
+			urb_finished = 1;
+			break;
+		}
+	}
+#if 0
+	/* we got an Root Hub Status Change interrupt */
+	if (got_rhsc) {
+#ifdef DEBUG
+		ohci_dump_roothub (&gohci, 1);
+#endif
+		got_rhsc = 0;
+		/* abuse timeout */
+		timeout = rh_check_port_status(&gohci);
+		if (timeout >= 0) {
+#if 0 /* this does nothing useful, but leave it here in case that changes */
+			/* the called routine adds 1 to the passed value */
+			usb_hub_port_connect_change(gohci.rh.dev, timeout - 1);
+#endif
+			/*
+			 * XXX
+			 * This is potentially dangerous because it assumes
+			 * that only one device is ever plugged in!
+			 */
+			devgone = dev;
+		}
+	}
+#endif
+
+	dev->status = stat;
+	dev->act_len = transfer_len;
+
+#ifdef DEBUG
+	pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe));
+#endif
+
+	/* free TDs in urb_priv */
+	urb_free_priv (&urb_priv);
+	return 0;
+}
+
+/* submit routines called from usb.c */
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		int transfer_len)
+{
+	info("submit_bulk_msg");
+	return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0);
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		int transfer_len, struct devrequest *setup)
+{
+	int maxsize = usb_maxpacket(dev, pipe);
+
+	info("submit_control_msg");
+#ifdef DEBUG
+	urb_priv.actual_length = 0;
+	pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
+#endif
+	if (!maxsize) {
+		err("submit_control_message: pipesize for pipe %lx is zero",
+			pipe);
+		return -1;
+	}
+	if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) {
+		gohci.rh.dev = dev;
+		/* root hub - redirect */
+		return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len,
+			setup);
+	}
+
+	return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0);
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		int transfer_len, int interval)
+{
+	info("submit_int_msg");
+	return -1;
+}
+
+/*-------------------------------------------------------------------------*
+ * HC functions
+ *-------------------------------------------------------------------------*/
+
+/* reset the HC and BUS */
+
+static int hc_reset (ohci_t *ohci)
+{
+	int timeout = 30;
+	int smm_timeout = 50; /* 0,5 sec */
+
+	if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */
+		writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */
+		info("USB HC TakeOver from SMM");
+		while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
+			wait_ms (10);
+			if (--smm_timeout == 0) {
+				err("USB HC TakeOver failed!");
+				return -1;
+			}
+		}
+	}
+
+	/* Disable HC interrupts */
+	writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
+
+	dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;",
+		ohci->slot_name,
+		readl (&ohci->regs->control));
+
+	/* Reset USB (needed by some controllers) */
+	ohci->hc_control = 0;
+	writel (ohci->hc_control, &ohci->regs->control);
+
+	/* HC Reset requires max 10 us delay */
+	writel (OHCI_HCR,  &ohci->regs->cmdstatus);
+	while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
+		if (--timeout == 0) {
+			err("USB HC reset timed out!");
+			return -1;
+		}
+		udelay (1);
+	}
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Start an OHCI controller, set the BUS operational
+ * enable interrupts
+ * connect the virtual root hub */
+
+static int hc_start (ohci_t * ohci)
+{
+	__u32 mask;
+	unsigned int fminterval;
+
+	ohci->disabled = 1;
+
+	/* Tell the controller where the control and bulk lists are
+	 * The lists are empty now. */
+
+	writel (0, &ohci->regs->ed_controlhead);
+	writel (0, &ohci->regs->ed_bulkhead);
+
+	writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */
+
+	fminterval = 0x2edf;
+	writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);
+	fminterval |= ((((fminterval - 210) * 6) / 7) << 16);
+	writel (fminterval, &ohci->regs->fminterval);
+	writel (0x628, &ohci->regs->lsthresh);
+
+	/* start controller operations */
+	ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+	ohci->disabled = 0;
+	writel (ohci->hc_control, &ohci->regs->control);
+
+	/* disable all interrupts */
+	mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD |
+			OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC |
+			OHCI_INTR_OC | OHCI_INTR_MIE);
+	writel (mask, &ohci->regs->intrdisable);
+	/* clear all interrupts */
+	mask &= ~OHCI_INTR_MIE;
+	writel (mask, &ohci->regs->intrstatus);
+	/* Choose the interrupts we care about now  - but w/o MIE */
+	mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO;
+	writel (mask, &ohci->regs->intrenable);
+
+#ifdef	OHCI_USE_NPS
+	/* required for AMD-756 and some Mac platforms */
+	writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM,
+		&ohci->regs->roothub.a);
+	writel (RH_HS_LPSC, &ohci->regs->roothub.status);
+#endif	/* OHCI_USE_NPS */
+
+#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);})
+	/* POTPGT delay is bits 24-31, in 2 ms units. */
+	mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
+
+	/* connect the virtual root hub */
+	ohci->rh.devnum = 0;
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* an interrupt happens */
+
+static int
+hc_interrupt (void)
+{
+	ohci_t *ohci = &gohci;
+	struct ohci_regs *regs = ohci->regs;
+	int ints;
+	int stat = -1;
+
+	if ((ohci->hcca->done_head != 0) &&
+	     !(ohci_cpu_to_le32(ohci->hcca->done_head) & 0x01)) {
+
+		ints =  OHCI_INTR_WDH;
+
+	} else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
+		ohci->disabled++;
+		err ("%s device removed!", ohci->slot_name);
+		return -1;
+
+	} else if ((ints &= readl (&regs->intrenable)) == 0) {
+		dbg("hc_interrupt: returning..\n");
+		return 0xff;
+	}
+
+	/* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */
+
+	if (ints & OHCI_INTR_RHSC) {
+		got_rhsc = 1;
+		stat = 0xff;
+	}
+
+	if (ints & OHCI_INTR_UE) {
+		ohci->disabled++;
+		err ("OHCI Unrecoverable Error, controller usb-%s disabled",
+			ohci->slot_name);
+		/* e.g. due to PCI Master/Target Abort */
+
+#ifdef	DEBUG
+		ohci_dump (ohci, 1);
+#endif
+		/* FIXME: be optimistic, hope that bug won't repeat often. */
+		/* Make some non-interrupt context restart the controller. */
+		/* Count and limit the retries though; either hardware or */
+		/* software errors can go forever... */
+		hc_reset (ohci);
+		return -1;
+	}
+
+	if (ints & OHCI_INTR_WDH) {
+		writel (OHCI_INTR_WDH, &regs->intrdisable);
+		stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci));
+		writel (OHCI_INTR_WDH, &regs->intrenable);
+	}
+
+	if (ints & OHCI_INTR_SO) {
+		dbg("USB Schedule overrun\n");
+		writel (OHCI_INTR_SO, &regs->intrenable);
+		stat = -1;
+	}
+
+	/* FIXME:  this assumes SOF (1/ms) interrupts don't get lost... */
+	if (ints & OHCI_INTR_SF) {
+		unsigned int frame = ohci_cpu_to_le16 (ohci->hcca->frame_no) & 1;
+		wait_ms(1);
+		writel (OHCI_INTR_SF, &regs->intrdisable);
+		if (ohci->ed_rm_list[frame] != NULL)
+			writel (OHCI_INTR_SF, &regs->intrenable);
+		stat = 0xff;
+	}
+
+	writel (ints, &regs->intrstatus);
+	return stat;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+
+/* De-allocate all resources.. */
+
+static void hc_release_ohci (ohci_t *ohci)
+{
+	dbg ("USB HC release ohci usb-%s", ohci->slot_name);
+
+	if (!ohci->disabled)
+		hc_reset (ohci);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * low level initalisation routine, called from usb.c
+ */
+static char ohci_inited = 0;
+
+int usb_lowlevel_init(void)
+{
+	memset (&gohci, 0, sizeof (ohci_t));
+	memset (&urb_priv, 0, sizeof (urb_priv_t));
+
+	/* align the storage */
+	if ((__u32)&ghcca[0] & 0xff) {
+		err("HCCA not aligned!!");
+		return -1;
+	}
+	phcca = &ghcca[0];
+	info("aligned ghcca %p", phcca);
+	memset(&ohci_dev, 0, sizeof(struct ohci_device));
+	if ((__u32)&ohci_dev.ed[0] & 0x7) {
+		err("EDs not aligned!!");
+		return -1;
+	}
+	memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1));
+	if ((__u32)gtd & 0x7) {
+		err("TDs not aligned!!");
+		return -1;
+	}
+	ptd = gtd;
+	gohci.hcca = phcca;
+	memset (phcca, 0, sizeof (struct ohci_hcca));
+
+	gohci.disabled = 1;
+	gohci.sleeping = 0;
+	gohci.irq = -1;
+#if defined(CONFIG_440EP)
+	gohci.regs = (struct ohci_regs *)(CONFIG_SYS_PERIPHERAL_BASE | 0x1000);
+#elif defined(CONFIG_440EPX) || defined(CONFIG_SYS_USB_HOST)
+	gohci.regs = (struct ohci_regs *)(CONFIG_SYS_USB_HOST);
+#endif
+
+	gohci.flags = 0;
+	gohci.slot_name = "ppc440";
+
+	if (hc_reset (&gohci) < 0) {
+		hc_release_ohci (&gohci);
+		return -1;
+	}
+
+	if (hc_start (&gohci) < 0) {
+		err ("can't start usb-%s", gohci.slot_name);
+		hc_release_ohci (&gohci);
+		return -1;
+	}
+
+#ifdef	DEBUG
+	ohci_dump (&gohci, 1);
+#endif
+	ohci_inited = 1;
+	urb_finished = 1;
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440EPX)
+	/* init the device driver */
+	usb_dev_init();
+#endif
+
+	return 0;
+}
+
+int usb_lowlevel_stop(void)
+{
+	/* this gets called really early - before the controller has */
+	/* even been initialized! */
+	if (!ohci_inited)
+		return 0;
+	/* TODO release any interrupts, etc. */
+	/* call hc_release_ohci() here ? */
+	hc_reset (&gohci);
+	return 0;
+}
+
+#endif /* CONFIG_USB_OHCI */
diff --git a/arch/powerpc/cpu/ppc4xx/usb_ohci.h b/arch/powerpc/cpu/ppc4xx/usb_ohci.h
new file mode 100644
index 0000000..2c3dc4f
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/usb_ohci.h
@@ -0,0 +1,410 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ *
+ * usb-ohci.h
+ */
+
+static int cc_to_error[16] = {
+
+/* mapping of the OHCI CC status to error codes */
+	/* No  Error  */ 0,
+	/* CRC Error  */ USB_ST_CRC_ERR,
+	/* Bit Stuff  */ USB_ST_BIT_ERR,
+	/* Data Togg  */ USB_ST_CRC_ERR,
+	/* Stall      */ USB_ST_STALLED,
+	/* DevNotResp */ -1,
+	/* PIDCheck   */ USB_ST_BIT_ERR,
+	/* UnExpPID   */ USB_ST_BIT_ERR,
+	/* DataOver   */ USB_ST_BUF_ERR,
+	/* DataUnder  */ USB_ST_BUF_ERR,
+	/* reservd    */ -1,
+	/* reservd    */ -1,
+	/* BufferOver */ USB_ST_BUF_ERR,
+	/* BuffUnder  */ USB_ST_BUF_ERR,
+	/* Not Access */ -1,
+	/* Not Access */ -1
+};
+
+/* ED States */
+
+#define ED_NEW		0x00
+#define ED_UNLINK	0x01
+#define ED_OPER		0x02
+#define ED_DEL		0x04
+#define ED_URB_DEL	0x08
+
+/* usb_ohci_ed */
+struct ed {
+	__u32 hwINFO;
+	__u32 hwTailP;
+	__u32 hwHeadP;
+	__u32 hwNextED;
+
+	struct ed *ed_prev;
+	__u8 int_period;
+	__u8 int_branch;
+	__u8 int_load;
+	__u8 int_interval;
+	__u8 state;
+	__u8 type;
+	__u16 last_iso;
+	struct ed *ed_rm_list;
+
+	struct usb_device *usb_dev;
+	__u32 unused[3];
+} __attribute__((aligned(16)));
+typedef struct ed ed_t;
+
+/* TD info field */
+#define TD_CC	    0xf0000000
+#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
+#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
+#define TD_EC	    0x0C000000
+#define TD_T	    0x03000000
+#define TD_T_DATA0  0x02000000
+#define TD_T_DATA1  0x03000000
+#define TD_T_TOGGLE 0x00000000
+#define TD_R	    0x00040000
+#define TD_DI	    0x00E00000
+#define TD_DI_SET(X) (((X) & 0x07)<< 21)
+#define TD_DP	    0x00180000
+#define TD_DP_SETUP 0x00000000
+#define TD_DP_IN    0x00100000
+#define TD_DP_OUT   0x00080000
+
+#define TD_ISO	    0x00010000
+#define TD_DEL	    0x00020000
+
+/* CC Codes */
+#define TD_CC_NOERROR	   0x00
+#define TD_CC_CRC	   0x01
+#define TD_CC_BITSTUFFING  0x02
+#define TD_CC_DATATOGGLEM  0x03
+#define TD_CC_STALL	   0x04
+#define TD_DEVNOTRESP	   0x05
+#define TD_PIDCHECKFAIL	   0x06
+#define TD_UNEXPECTEDPID   0x07
+#define TD_DATAOVERRUN	   0x08
+#define TD_DATAUNDERRUN	   0x09
+#define TD_BUFFEROVERRUN   0x0C
+#define TD_BUFFERUNDERRUN  0x0D
+#define TD_NOTACCESSED	   0x0F
+
+#define MAXPSW 1
+
+struct td {
+	__u32 hwINFO;
+	__u32 hwCBP;		/* Current Buffer Pointer */
+	__u32 hwNextTD;		/* Next TD Pointer */
+	__u32 hwBE;		/* Memory Buffer End Pointer */
+
+	__u16 hwPSW[MAXPSW];
+	__u8 unused;
+	__u8 index;
+	struct ed *ed;
+	struct td *next_dl_td;
+	struct usb_device *usb_dev;
+	int transfer_len;
+	__u32 data;
+
+	__u32 unused2[2];
+} __attribute__((aligned(32)));
+typedef struct td td_t;
+
+#define OHCI_ED_SKIP	(1 << 14)
+
+/*
+ * The HCCA (Host Controller Communications Area) is a 256 byte
+ * structure defined in the OHCI spec. that the host controller is
+ * told the base address of.  It must be 256-byte aligned.
+ */
+
+#define NUM_INTS 32		/* part of the OHCI standard */
+struct ohci_hcca {
+	__u32 int_table[NUM_INTS];	/* Interrupt ED table */
+#if defined(CONFIG_MPC5200)
+	__u16 pad1;		/* set to 0 on each frame_no change */
+	__u16 frame_no;		/* current frame number */
+#else
+	__u16 frame_no;		/* current frame number */
+	__u16 pad1;		/* set to 0 on each frame_no change */
+#endif
+	__u32 done_head;	/* info returned for an interrupt */
+	u8 reserved_for_hc[116];
+} __attribute__((aligned(256)));
+
+/*
+ * Maximum number of root hub ports.
+ */
+#define MAX_ROOT_PORTS	15	/* maximum OHCI root hub ports */
+
+/*
+ * This is the structure of the OHCI controller's memory mapped I/O
+ * region.  This is Memory Mapped I/O.	You must use the readl() and
+ * writel() macros defined in asm/io.h to access these!!
+ */
+struct ohci_regs {
+	/* control and status registers */
+	__u32 revision;
+	__u32 control;
+	__u32 cmdstatus;
+	__u32 intrstatus;
+	__u32 intrenable;
+	__u32 intrdisable;
+	/* memory pointers */
+	__u32 hcca;
+	__u32 ed_periodcurrent;
+	__u32 ed_controlhead;
+	__u32 ed_controlcurrent;
+	__u32 ed_bulkhead;
+	__u32 ed_bulkcurrent;
+	__u32 donehead;
+	/* frame counters */
+	__u32 fminterval;
+	__u32 fmremaining;
+	__u32 fmnumber;
+	__u32 periodicstart;
+	__u32 lsthresh;
+	/* Root hub ports */
+	struct ohci_roothub_regs {
+		__u32 a;
+		__u32 b;
+		__u32 status;
+		__u32 portstatus[MAX_ROOT_PORTS];
+	} roothub;
+} __attribute__((aligned(32)));
+
+/* OHCI CONTROL AND STATUS REGISTER MASKS */
+
+/*
+ * HcControl (control) register masks
+ */
+#define OHCI_CTRL_CBSR	(3 << 0)	/* control/bulk service ratio */
+#define OHCI_CTRL_PLE	(1 << 2)	/* periodic list enable */
+#define OHCI_CTRL_IE	(1 << 3)	/* isochronous enable */
+#define OHCI_CTRL_CLE	(1 << 4)	/* control list enable */
+#define OHCI_CTRL_BLE	(1 << 5)	/* bulk list enable */
+#define OHCI_CTRL_HCFS	(3 << 6)	/* host controller functional state */
+#define OHCI_CTRL_IR	(1 << 8)	/* interrupt routing */
+#define OHCI_CTRL_RWC	(1 << 9)	/* remote wakeup connected */
+#define OHCI_CTRL_RWE	(1 << 10)	/* remote wakeup enable */
+
+/* pre-shifted values for HCFS */
+#	define OHCI_USB_RESET	(0 << 6)
+#	define OHCI_USB_RESUME	(1 << 6)
+#	define OHCI_USB_OPER	(2 << 6)
+#	define OHCI_USB_SUSPEND (3 << 6)
+
+/*
+ * HcCommandStatus (cmdstatus) register masks
+ */
+#define OHCI_HCR	(1 << 0)	/* host controller reset */
+#define OHCI_CLF	(1 << 1)	/* control list filled */
+#define OHCI_BLF	(1 << 2)	/* bulk list filled */
+#define OHCI_OCR	(1 << 3)	/* ownership change request */
+#define OHCI_SOC	(3 << 16)	/* scheduling overrun count */
+
+/*
+ * masks used with interrupt registers:
+ * HcInterruptStatus (intrstatus)
+ * HcInterruptEnable (intrenable)
+ * HcInterruptDisable (intrdisable)
+ */
+#define OHCI_INTR_SO	(1 << 0)	/* scheduling overrun */
+#define OHCI_INTR_WDH	(1 << 1)	/* writeback of done_head */
+#define OHCI_INTR_SF	(1 << 2)	/* start frame */
+#define OHCI_INTR_RD	(1 << 3)	/* resume detect */
+#define OHCI_INTR_UE	(1 << 4)	/* unrecoverable error */
+#define OHCI_INTR_FNO	(1 << 5)	/* frame number overflow */
+#define OHCI_INTR_RHSC	(1 << 6)	/* root hub status change */
+#define OHCI_INTR_OC	(1 << 30)	/* ownership change */
+#define OHCI_INTR_MIE	(1 << 31)	/* master interrupt enable */
+
+/* Virtual Root HUB */
+struct virt_root_hub {
+	int devnum;		/* Address of Root Hub endpoint */
+	void *dev;		/* was urb */
+	void *int_addr;
+	int send;
+	int interval;
+};
+
+/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
+
+/* destination of request */
+#define RH_INTERFACE		   0x01
+#define RH_ENDPOINT		   0x02
+#define RH_OTHER		   0x03
+
+#define RH_CLASS		   0x20
+#define RH_VENDOR		   0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS		0x0080
+#define RH_CLEAR_FEATURE	0x0100
+#define RH_SET_FEATURE		0x0300
+#define RH_SET_ADDRESS		0x0500
+#define RH_GET_DESCRIPTOR	0x0680
+#define RH_SET_DESCRIPTOR	0x0700
+#define RH_GET_CONFIGURATION	0x0880
+#define RH_SET_CONFIGURATION	0x0900
+#define RH_GET_STATE		0x0280
+#define RH_GET_INTERFACE	0x0A80
+#define RH_SET_INTERFACE	0x0B00
+#define RH_SYNC_FRAME		0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP		0x2000
+
+/* Hub port features */
+#define RH_PORT_CONNECTION	   0x00
+#define RH_PORT_ENABLE		   0x01
+#define RH_PORT_SUSPEND		   0x02
+#define RH_PORT_OVER_CURRENT	   0x03
+#define RH_PORT_RESET		   0x04
+#define RH_PORT_POWER		   0x08
+#define RH_PORT_LOW_SPEED	   0x09
+
+#define RH_C_PORT_CONNECTION	   0x10
+#define RH_C_PORT_ENABLE	   0x11
+#define RH_C_PORT_SUSPEND	   0x12
+#define RH_C_PORT_OVER_CURRENT	   0x13
+#define RH_C_PORT_RESET		   0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER	   0x00
+#define RH_C_HUB_OVER_CURRENT	   0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP	   0x00
+#define RH_ENDPOINT_STALL	   0x01
+
+#define RH_ACK			   0x01
+#define RH_REQ_ERR		   -1
+#define RH_NACK			   0x00
+
+/* OHCI ROOT HUB REGISTER MASKS */
+
+/* roothub.portstatus [i] bits */
+#define RH_PS_CCS	     0x00000001	/* current connect status */
+#define RH_PS_PES	     0x00000002	/* port enable status */
+#define RH_PS_PSS	     0x00000004	/* port suspend status */
+#define RH_PS_POCI	     0x00000008	/* port over current indicator */
+#define RH_PS_PRS	     0x00000010	/* port reset status */
+#define RH_PS_PPS	     0x00000100	/* port power status */
+#define RH_PS_LSDA	     0x00000200	/* low speed device attached */
+#define RH_PS_CSC	     0x00010000	/* connect status change */
+#define RH_PS_PESC	     0x00020000	/* port enable status change */
+#define RH_PS_PSSC	     0x00040000	/* port suspend status change */
+#define RH_PS_OCIC	     0x00080000	/* over current indicator change */
+#define RH_PS_PRSC	     0x00100000	/* port reset status change */
+
+/* roothub.status bits */
+#define RH_HS_LPS	     0x00000001	/* local power status */
+#define RH_HS_OCI	     0x00000002	/* over current indicator */
+#define RH_HS_DRWE	     0x00008000	/* device remote wakeup enable */
+#define RH_HS_LPSC	     0x00010000	/* local power status change */
+#define RH_HS_OCIC	     0x00020000	/* over current indicator change */
+#define RH_HS_CRWE	     0x80000000	/* clear remote wakeup enable */
+
+/* roothub.b masks */
+#define RH_B_DR		0x0000ffff	/* device removable flags */
+#define RH_B_PPCM	0xffff0000	/* port power control mask */
+
+/* roothub.a masks */
+#define RH_A_NDP	(0xff << 0)	/* number of downstream ports */
+#define RH_A_PSM	(1 << 8)	/* power switching mode */
+#define RH_A_NPS	(1 << 9)	/* no power switching */
+#define RH_A_DT		(1 << 10)	/* device type (mbz) */
+#define RH_A_OCPM	(1 << 11)	/* over current protection mode */
+#define RH_A_NOCP	(1 << 12)	/* no over current protection */
+#define RH_A_POTPGT	(0xff << 24)	/* power on to power good time */
+
+/* urb */
+#define N_URB_TD 48
+typedef struct {
+	ed_t *ed;
+	__u16 length;		/* number of tds associated with this request */
+	__u16 td_cnt;		/* number of tds already serviced */
+	int state;
+	unsigned long pipe;
+	int actual_length;
+	td_t *td[N_URB_TD];	/* list pointer to all corresponding TDs associated with this request */
+} urb_priv_t;
+#define URB_DEL 1
+
+/*
+ * This is the full ohci controller description
+ *
+ * Note how the "proper" USB information is just
+ * a subset of what the full implementation needs. (Linus)
+ */
+
+typedef struct ohci {
+	struct ohci_hcca *hcca;	/* hcca */
+	/*dma_addr_t hcca_dma; */
+
+	int irq;
+	int disabled;		/* e.g. got a UE, we're hung */
+	int sleeping;
+	unsigned long flags;	/* for HC bugs */
+
+	struct ohci_regs *regs;	/* OHCI controller's memory */
+
+	ed_t *ed_rm_list[2];	/* lists of all endpoints to be removed */
+	ed_t *ed_bulktail;	/* last endpoint of bulk list */
+	ed_t *ed_controltail;	/* last endpoint of control list */
+	int intrstatus;
+	__u32 hc_control;	/* copy of the hc control reg */
+	struct usb_device *dev[32];
+	struct virt_root_hub rh;
+
+	const char *slot_name;
+} ohci_t;
+
+#define NUM_EDS 8		/* num of preallocated endpoint descriptors */
+
+struct ohci_device {
+	ed_t ed[NUM_EDS];
+	int ed_cnt;
+};
+
+/* hcd */
+/* endpoint */
+static int ep_link(ohci_t * ohci, ed_t * ed);
+static int ep_unlink(ohci_t * ohci, ed_t * ed);
+static ed_t *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe);
+
+/*-------------------------------------------------------------------------*/
+
+/* we need more TDs than EDs */
+#define NUM_TD 64
+
+/* +1 so we can align the storage */
+td_t gtd[NUM_TD + 1];
+/* pointers to aligned storage */
+td_t *ptd;
+
+/* TDs ... */
+static inline struct td *td_alloc(struct usb_device *usb_dev)
+{
+	int i;
+	struct td *td;
+
+	td = NULL;
+	for (i = 0; i < NUM_TD; i++) {
+		if (ptd[i].usb_dev == NULL) {
+			td = &ptd[i];
+			td->usb_dev = usb_dev;
+			break;
+		}
+	}
+
+	return td;
+}
+
+static inline void ed_free(struct ed *ed)
+{
+	ed->usb_dev = NULL;
+}
diff --git a/arch/powerpc/cpu/ppc4xx/usbdev.c b/arch/powerpc/cpu/ppc4xx/usbdev.c
new file mode 100644
index 0000000..fe398af
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/usbdev.c
@@ -0,0 +1,230 @@
+/*USB 1.1,2.0 device*/
+
+#include <common.h>
+#include <asm/processor.h>
+
+#if (defined(CONFIG_440EP) || defined(CONFIG_440EPX)) && defined(CONFIG_CMD_USB)
+
+#include <usb.h>
+#include <asm/ppc4xx-uic.h>
+#include "usbdev.h"
+
+#define USB_DT_DEVICE        0x01
+#define USB_DT_CONFIG        0x02
+#define USB_DT_STRING        0x03
+#define USB_DT_INTERFACE     0x04
+#define USB_DT_ENDPOINT      0x05
+
+int set_value = -1;
+
+void process_endpoints(unsigned short usb2d0_intrin)
+{
+	/*will hold the packet received */
+	struct usb_device_descriptor usb_device_packet;
+	struct usb_configuration_descriptor usb_config_packet;
+	struct usb_string_descriptor usb_string_packet;
+	struct devrequest setup_packet;
+	unsigned int *setup_packet_pt;
+	unsigned char *packet_pt = NULL;
+	int temp, temp1;
+
+	int i;
+
+	/*printf("{USB device} - endpoint 0x%X \n", usb2d0_intrin); */
+
+	/*set usb address, seems to not work unless it is done in the next
+	   interrupt, so that is why it is done this way */
+	if (set_value != -1)
+		*(unsigned char *)USB2D0_FADDR_8 = (unsigned char)set_value;
+
+	/*endpoint 1 */
+	if (usb2d0_intrin & 0x01) {
+		setup_packet_pt = (unsigned int *)&setup_packet;
+
+		/*copy packet */
+		setup_packet_pt[0] = *(unsigned int *)USB2D0_FIFO_0;
+		setup_packet_pt[1] = *(unsigned int *)USB2D0_FIFO_0;
+		temp = *(unsigned int *)USB2D0_FIFO_0;
+		temp1 = *(unsigned int *)USB2D0_FIFO_0;
+
+		/*do some swapping */
+		setup_packet.value = swap_16(setup_packet.value);
+		setup_packet.index = swap_16(setup_packet.index);
+		setup_packet.length = swap_16(setup_packet.length);
+
+		/*clear rx packet */
+		*(unsigned short *)USB2D0_INCSR0_8 = 0x48;
+
+		/*printf("0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n", setup_packet.requesttype,
+		   setup_packet.request, setup_packet.value,
+		   setup_packet.index, setup_packet.length, temp, temp1 ); */
+
+		switch (setup_packet.request) {
+		case USB_REQ_GET_DESCRIPTOR:
+
+			switch (setup_packet.value >> 8) {
+			case USB_DT_DEVICE:
+				/*create packet */
+				usb_device_packet.bLength = 18;
+				usb_device_packet.bDescriptorType =
+				    USB_DT_DEVICE;
+#ifdef USB_2_0_DEVICE
+				usb_device_packet.bcdUSB = swap_16(0x200);
+#else
+				usb_device_packet.bcdUSB = swap_16(0x110);
+#endif
+				usb_device_packet.bDeviceClass = 0xff;
+				usb_device_packet.bDeviceSubClass = 0;
+				usb_device_packet.bDeviceProtocol = 0;
+				usb_device_packet.bMaxPacketSize0 = 32;
+				usb_device_packet.idVendor = swap_16(1);
+				usb_device_packet.idProduct = swap_16(2);
+				usb_device_packet.bcdDevice = swap_16(0x300);
+				usb_device_packet.iManufacturer = 1;
+				usb_device_packet.iProduct = 1;
+				usb_device_packet.iSerialNumber = 1;
+				usb_device_packet.bNumConfigurations = 1;
+
+				/*put packet in fifo */
+				packet_pt = (unsigned char *)&usb_device_packet;
+				break;
+
+			case USB_DT_CONFIG:
+				/*create packet */
+				usb_config_packet.bLength = 9;
+				usb_config_packet.bDescriptorType =
+				    USB_DT_CONFIG;
+				usb_config_packet.wTotalLength = swap_16(25);
+				usb_config_packet.bNumInterfaces = 1;
+				usb_config_packet.bConfigurationValue = 1;
+				usb_config_packet.iConfiguration = 0;
+				usb_config_packet.bmAttributes = 0x40;
+				usb_config_packet.bMaxPower = 0;
+
+				/*put packet in fifo */
+				packet_pt = (unsigned char *)&usb_config_packet;
+				break;
+
+			case USB_DT_STRING:
+				/*create packet */
+				usb_string_packet.bLength = 2;
+				usb_string_packet.bDescriptorType =
+				    USB_DT_STRING;
+				usb_string_packet.wData[0] = 0x0094;
+
+				/*put packet in fifo */
+				packet_pt = (unsigned char *)&usb_string_packet;
+				break;
+			}
+
+			/*put packet in fifo */
+			for (i = 0; i < (setup_packet.length); i++) {
+				*(unsigned char *)USB2D0_FIFO_0 = packet_pt[i];
+			}
+
+			/*give tx command */
+			*(unsigned short *)USB2D0_INCSR0_8 = 0x0a;
+
+			break;
+
+		case USB_REQ_SET_ADDRESS:
+
+			/*copy usb address */
+			set_value = setup_packet.value;
+
+			break;
+		}
+
+	}
+}
+
+void process_other(unsigned char usb2d0_intrusb)
+{
+
+	/*check for sof */
+	if (usb2d0_intrusb & 0x08) {
+		/*printf("{USB device} - sof detected\n"); */
+	}
+
+	/*check for reset */
+	if (usb2d0_intrusb & 0x04) {
+		/*printf("{USB device} - reset detected\n"); */
+
+		/*copy usb address of zero, need to do this when usb reset */
+		set_value = 0;
+	}
+
+	if (usb2d0_intrusb & 0x02) {
+		/*printf("{USB device} - resume detected\n"); */
+	}
+
+	if (usb2d0_intrusb & 0x01) {
+		/*printf("{USB device} - suspend detected\n"); */
+	}
+}
+
+int usbInt(void)
+{
+	/*Must read these 2 registers and use values to clear interrupts.  If you
+	   do not read them then the interrupt will not be cleared.  If you do not
+	   use the variable the optimizer will not do a read. */
+	volatile unsigned short usb2d0_intrin =
+	    *(unsigned short *)USB2D0_INTRIN_16;
+	volatile unsigned char usb2d0_intrusb =
+	    *(unsigned char *)USB2D0_INTRUSB_8;
+
+	/*check if there was an endpoint interrupt */
+	if (usb2d0_intrin != 0) {
+		process_endpoints(usb2d0_intrin);
+	}
+
+	/*check for other interrupts */
+	if (usb2d0_intrusb != 0) {
+		process_other(usb2d0_intrusb);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_440EPX)
+void usb_dev_init()
+{
+	printf("USB 2.0 Device init\n");
+
+	/*usb dev init */
+	*(unsigned char *)USB2D0_POWER_8 = 0xa1;	/* 2.0 */
+
+	/*enable interrupts */
+	*(unsigned char *)USB2D0_INTRUSBE_8 = 0x0f;
+
+	irq_install_handler(VECNUM_USBDEV, (interrupt_handler_t *) usbInt,
+			    NULL);
+}
+#else
+void usb_dev_init()
+{
+#ifdef USB_2_0_DEVICE
+	printf("USB 2.0 Device init\n");
+	/*select 2.0 device */
+	mtsdr(SDR0_USB0, 0x0);	/* 2.0 */
+
+	/*usb dev init */
+	*(unsigned char *)USB2D0_POWER_8 = 0xa1;	/* 2.0 */
+#else
+	printf("USB 1.1 Device init\n");
+	/*select 1.1 device */
+	mtsdr(SDR0_USB0, 0x2);	/* 1.1 */
+
+	/*usb dev init */
+	*(unsigned char *)USB2D0_POWER_8 = 0xc0;	/* 1.1 */
+#endif
+
+	/*enable interrupts */
+	*(unsigned char *)USB2D0_INTRUSBE_8 = 0x0f;
+
+	irq_install_handler(VECNUM_USBDEV, (interrupt_handler_t *) usbInt,
+			    NULL);
+}
+#endif
+
+#endif /* CONFIG_440EP || CONFIG_440EPX */
diff --git a/arch/powerpc/cpu/ppc4xx/usbdev.h b/arch/powerpc/cpu/ppc4xx/usbdev.h
new file mode 100644
index 0000000..ef6a2da
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/usbdev.h
@@ -0,0 +1,31 @@
+#include <config.h>
+
+/*Common Registers*/
+#define USB2D0_INTRIN_16   (CONFIG_SYS_USB_DEVICE | 0x100)
+#define USB2D0_POWER_8     (CONFIG_SYS_USB_DEVICE | 0x102)
+#define USB2D0_FADDR_8     (CONFIG_SYS_USB_DEVICE | 0x103)
+#define USB2D0_INTRINE_16  (CONFIG_SYS_USB_DEVICE | 0x104)
+#define USB2D0_INTROUT_16  (CONFIG_SYS_USB_DEVICE | 0x106)
+#define USB2D0_INTRUSBE_8  (CONFIG_SYS_USB_DEVICE | 0x108)
+#define USB2D0_INTRUSB_8   (CONFIG_SYS_USB_DEVICE | 0x109)
+#define USB2D0_INTROUTE_16 (CONFIG_SYS_USB_DEVICE | 0x10a)
+#define USB2D0_TSTMODE_8   (CONFIG_SYS_USB_DEVICE | 0x10c)
+#define USB2D0_INDEX_8     (CONFIG_SYS_USB_DEVICE | 0x10d)
+#define USB2D0_FRAME_16    (CONFIG_SYS_USB_DEVICE | 0x10e)
+
+/*Indexed Registers*/
+#define USB2D0_INCSR0_8    (CONFIG_SYS_USB_DEVICE | 0x110)
+#define USB2D0_INCSR_16    (CONFIG_SYS_USB_DEVICE | 0x110)
+#define USB2D0_INMAXP_16   (CONFIG_SYS_USB_DEVICE | 0x112)
+#define USB2D0_OUTCSR_16   (CONFIG_SYS_USB_DEVICE | 0x114)
+#define USB2D0_OUTMAXP_16  (CONFIG_SYS_USB_DEVICE | 0x116)
+#define USB2D0_OUTCOUNT0_8 (CONFIG_SYS_USB_DEVICE | 0x11a)
+#define USB2D0_OUTCOUNT_16 (CONFIG_SYS_USB_DEVICE | 0x11a)
+
+/*FIFOs*/
+#define USB2D0_FIFO_0 (CONFIG_SYS_USB_DEVICE | 0x120)
+#define USB2D0_FIFO_1 (CONFIG_SYS_USB_DEVICE | 0x124)
+#define USB2D0_FIFO_2 (CONFIG_SYS_USB_DEVICE | 0x128)
+#define USB2D0_FIFO_3 (CONFIG_SYS_USB_DEVICE | 0x12c)
+
+void usb_dev_init(void);
diff --git a/arch/powerpc/cpu/ppc4xx/xilinx_irq.c b/arch/powerpc/cpu/ppc4xx/xilinx_irq.c
new file mode 100644
index 0000000..7108777
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/xilinx_irq.c
@@ -0,0 +1,100 @@
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * This work has been supported by: QTechnology  http://qtec.com/
+ * Based on interrupts.c Wolfgang Denk-DENX Software Engineering-wd@denx.de
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/interrupt.h>
+#include <ppc4xx.h>
+#include <ppc_asm.tmpl>
+#include <commproc.h>
+#include <asm/io.h>
+#include <asm/xilinx_irq.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void pic_enable(void)
+{
+	debug("Xilinx PIC at 0x%8x\n", intc);
+
+	/*
+	 * Disable all external interrupts until they are
+	 * explicitly requested.
+	 */
+	out_be32((u32 *) IER, 0);
+
+	/* Acknowledge any pending interrupts just in case. */
+	out_be32((u32 *) IAR, 0xffffffff);
+
+	/* Turn on the Master Enable. */
+	out_be32((u32 *) MER, 0x3UL);
+
+	return;
+}
+
+int xilinx_pic_irq_get(void)
+{
+	u32 irq;
+	irq = in_be32((u32 *) IVR);
+
+	/* If no interrupt is pending then all bits of the IVR are set to 1. As
+	 * the IVR is as many bits wide as numbers of inputs are available.
+	 * Therefore, if all bits of the IVR are set to one, its content will
+	 * be bigger than XPAR_INTC_MAX_NUM_INTR_INPUTS.
+	 */
+	if (irq >= XPAR_INTC_MAX_NUM_INTR_INPUTS)
+		irq = -1;	/* report no pending interrupt. */
+
+	debug("get_irq: %d\n", irq);
+	return (irq);
+}
+
+void pic_irq_enable(unsigned int irq)
+{
+	u32 mask = IRQ_MASK(irq);
+	debug("enable: %d\n", irq);
+	out_be32((u32 *) SIE, mask);
+}
+
+void pic_irq_disable(unsigned int irq)
+{
+	u32 mask = IRQ_MASK(irq);
+	debug("disable: %d\n", irq);
+	out_be32((u32 *) CIE, mask);
+}
+
+void pic_irq_ack(unsigned int irq)
+{
+	u32 mask = IRQ_MASK(irq);
+	debug("ack: %d\n", irq);
+	out_be32((u32 *) IAR, mask);
+}
+
+void external_interrupt(struct pt_regs *regs)
+{
+	int irq;
+
+	irq = xilinx_pic_irq_get();
+	if (irq < 0)
+		return;
+
+	interrupt_run_handler(irq);
+
+	return;
+}
diff --git a/arch/powerpc/include/asm/4xx_pci.h b/arch/powerpc/include/asm/4xx_pci.h
new file mode 100644
index 0000000..f686e7c
--- /dev/null
+++ b/arch/powerpc/include/asm/4xx_pci.h
@@ -0,0 +1,60 @@
+#ifndef _405GP_PCI_H
+#define _405GP_PCI_H
+
+#include <pci.h>
+
+/*----------------------------------------------------------------------------+
+| 405GP PCI core memory map defines.
++----------------------------------------------------------------------------*/
+#define MIN_PCI_MEMADDR1    0x80000000
+#define MIN_PCI_MEMADDR2    0x00000000
+#define MIN_PLB_PCI_IOADDR  0xE8000000  /* PLB side of PCI I/O address space */
+#define MIN_PCI_PCI_IOADDR  0x00000000  /* PCI side of PCI I/O address space */
+#define MAX_PCI_DEVICES     32
+
+/*----------------------------------------------------------------------------+
+| Defines for the 405GP PCI Config address and data registers followed by
+| defines for the standard PCI device configuration header.
++----------------------------------------------------------------------------*/
+#define PCICFGADR       0xEEC00000
+#define PCICFGDATA      0xEEC00004
+
+#define PCIBUSNUM       0x40        /* 405GP specific parameters */
+#define PCISUBBUSNUM    0x41
+#define PCIDISCOUNT     0x42
+#define PCIBRDGOPT1     0x4A
+#define PCIBRDGOPT2     0x60
+
+/*----------------------------------------------------------------------------+
+| Defines for 405GP PCI Master local configuration regs.
++----------------------------------------------------------------------------*/
+#define PMM0LA          0xEF400000
+#define PMM0MA          0xEF400004
+#define PMM0PCILA       0xEF400008
+#define PMM0PCIHA       0xEF40000C
+#define PMM1LA          0xEF400010
+#define PMM1MA          0xEF400014
+#define PMM1PCILA       0xEF400018
+#define PMM1PCIHA       0xEF40001C
+#define PMM2LA          0xEF400020
+#define PMM2MA          0xEF400024
+#define PMM2PCILA       0xEF400028
+#define PMM2PCIHA       0xEF40002C
+
+/*----------------------------------------------------------------------------+
+| Defines for 405GP PCI Target local configuration regs.
++----------------------------------------------------------------------------*/
+#define PTM1MS          0xEF400030
+#define PTM1LA          0xEF400034
+#define PTM2MS          0xEF400038
+#define PTM2LA          0xEF40003C
+
+#define PCIDEVID_405GP	0x0
+
+void board_pci_fixup_irq(struct pci_controller *hose, pci_dev_t dev);
+int pci_arbiter_enabled(void);
+int __pci_pre_init(struct pci_controller *hose);
+void __pci_target_init(struct pci_controller *hose);
+void __pci_master_init(struct pci_controller *hose);
+
+#endif
diff --git a/arch/powerpc/include/asm/4xx_pcie.h b/arch/powerpc/include/asm/4xx_pcie.h
new file mode 100644
index 0000000..a0e88de
--- /dev/null
+++ b/arch/powerpc/include/asm/4xx_pcie.h
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Roland Dreier <rolandd@cisco.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.
+ */
+
+#ifndef __4XX_PCIE_H
+#define __4XX_PCIE_H
+
+#include <ppc4xx.h>
+#include <pci.h>
+
+#define DCRN_SDR0_CFGADDR	0x00e
+#define DCRN_SDR0_CFGDATA	0x00f
+
+#if defined(CONFIG_440SPE)
+#define CONFIG_SYS_PCIE_NR_PORTS	3
+
+#define CONFIG_SYS_PCIE_ADDR_HIGH	0x0000000d
+
+#define DCRN_PCIE0_BASE		0x100
+#define DCRN_PCIE1_BASE		0x120
+#define DCRN_PCIE2_BASE		0x140
+
+#define PCIE0_SDR		0x300
+#define PCIE1_SDR		0x340
+#define PCIE2_SDR		0x370
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define CONFIG_SYS_PCIE_NR_PORTS	2
+
+#define CONFIG_SYS_PCIE_ADDR_HIGH	0x0000000d
+
+#define DCRN_PCIE0_BASE		0x100
+#define DCRN_PCIE1_BASE		0x120
+
+#define PCIE0_SDR		0x300
+#define PCIE1_SDR		0x340
+#endif
+
+#if defined(CONFIG_405EX)
+#define CONFIG_SYS_PCIE_NR_PORTS	2
+
+#define CONFIG_SYS_PCIE_ADDR_HIGH	0x00000000
+
+#define	DCRN_PCIE0_BASE		0x040
+#define	DCRN_PCIE1_BASE		0x060
+
+#define PCIE0_SDR		0x400
+#define PCIE1_SDR		0x440
+#endif
+
+#define PCIE0			DCRN_PCIE0_BASE
+#define PCIE1			DCRN_PCIE1_BASE
+#define PCIE2			DCRN_PCIE2_BASE
+
+#define DCRN_PEGPL_CFGBAH(base)		(base + 0x00)
+#define DCRN_PEGPL_CFGBAL(base)		(base + 0x01)
+#define DCRN_PEGPL_CFGMSK(base)		(base + 0x02)
+#define DCRN_PEGPL_MSGBAH(base)		(base + 0x03)
+#define DCRN_PEGPL_MSGBAL(base)		(base + 0x04)
+#define DCRN_PEGPL_MSGMSK(base)		(base + 0x05)
+#define DCRN_PEGPL_OMR1BAH(base)	(base + 0x06)
+#define DCRN_PEGPL_OMR1BAL(base)	(base + 0x07)
+#define DCRN_PEGPL_OMR1MSKH(base)	(base + 0x08)
+#define DCRN_PEGPL_OMR1MSKL(base)	(base + 0x09)
+#define DCRN_PEGPL_REGBAH(base)		(base + 0x12)
+#define DCRN_PEGPL_REGBAL(base)		(base + 0x13)
+#define DCRN_PEGPL_REGMSK(base)		(base + 0x14)
+#define DCRN_PEGPL_SPECIAL(base)	(base + 0x15)
+#define DCRN_PEGPL_CFG(base)		(base + 0x16)
+
+/*
+ * System DCRs (SDRs)
+ */
+#define PESDR0_PLLLCT1		0x03a0
+#define PESDR0_PLLLCT2		0x03a1
+#define PESDR0_PLLLCT3		0x03a2
+
+/* common regs, at for all 4xx with PCIe core */
+#define SDRN_PESDR_UTLSET1(n)		(sdr_base(n) + 0x00)
+#define SDRN_PESDR_UTLSET2(n)		(sdr_base(n) + 0x01)
+#define SDRN_PESDR_DLPSET(n)		(sdr_base(n) + 0x02)
+#define SDRN_PESDR_LOOP(n)		(sdr_base(n) + 0x03)
+#define SDRN_PESDR_RCSSET(n)		(sdr_base(n) + 0x04)
+#define SDRN_PESDR_RCSSTS(n)		(sdr_base(n) + 0x05)
+
+#if defined(CONFIG_440SPE)
+#define SDRN_PESDR_HSSL0SET1(n)		(sdr_base(n) + 0x06)
+#define SDRN_PESDR_HSSL0SET2(n)		(sdr_base(n) + 0x07)
+#define SDRN_PESDR_HSSL0STS(n)		(sdr_base(n) + 0x08)
+#define SDRN_PESDR_HSSL1SET1(n)		(sdr_base(n) + 0x09)
+#define SDRN_PESDR_HSSL1SET2(n)		(sdr_base(n) + 0x0a)
+#define SDRN_PESDR_HSSL1STS(n)		(sdr_base(n) + 0x0b)
+#define SDRN_PESDR_HSSL2SET1(n)		(sdr_base(n) + 0x0c)
+#define SDRN_PESDR_HSSL2SET2(n)		(sdr_base(n) + 0x0d)
+#define SDRN_PESDR_HSSL2STS(n)		(sdr_base(n) + 0x0e)
+#define SDRN_PESDR_HSSL3SET1(n)		(sdr_base(n) + 0x0f)
+#define SDRN_PESDR_HSSL3SET2(n)		(sdr_base(n) + 0x10)
+#define SDRN_PESDR_HSSL3STS(n)		(sdr_base(n) + 0x11)
+
+#define PESDR0_UTLSET1		0x0300
+#define PESDR0_UTLSET2		0x0301
+#define PESDR0_DLPSET		0x0302
+#define PESDR0_LOOP		0x0303
+#define PESDR0_RCSSET		0x0304
+#define PESDR0_RCSSTS		0x0305
+#define PESDR0_HSSL0SET1	0x0306
+#define PESDR0_HSSL0SET2	0x0307
+#define PESDR0_HSSL0STS		0x0308
+#define PESDR0_HSSL1SET1	0x0309
+#define PESDR0_HSSL1SET2	0x030a
+#define PESDR0_HSSL1STS		0x030b
+#define PESDR0_HSSL2SET1	0x030c
+#define PESDR0_HSSL2SET2	0x030d
+#define PESDR0_HSSL2STS		0x030e
+#define PESDR0_HSSL3SET1	0x030f
+#define PESDR0_HSSL3SET2	0x0310
+#define PESDR0_HSSL3STS		0x0311
+#define PESDR0_HSSL4SET1	0x0312
+#define PESDR0_HSSL4SET2	0x0313
+#define PESDR0_HSSL4STS		0x0314
+#define PESDR0_HSSL5SET1	0x0315
+#define PESDR0_HSSL5SET2	0x0316
+#define PESDR0_HSSL5STS		0x0317
+#define PESDR0_HSSL6SET1	0x0318
+#define PESDR0_HSSL6SET2	0x0319
+#define PESDR0_HSSL6STS		0x031a
+#define PESDR0_HSSL7SET1	0x031b
+#define PESDR0_HSSL7SET2	0x031c
+#define PESDR0_HSSL7STS		0x031d
+#define PESDR0_HSSCTLSET	0x031e
+#define PESDR0_LANE_ABCD	0x031f
+#define PESDR0_LANE_EFGH	0x0320
+
+#define PESDR1_UTLSET1		0x0340
+#define PESDR1_UTLSET2		0x0341
+#define PESDR1_DLPSET		0x0342
+#define PESDR1_LOOP		0x0343
+#define PESDR1_RCSSET		0x0344
+#define PESDR1_RCSSTS		0x0345
+#define PESDR1_HSSL0SET1	0x0346
+#define PESDR1_HSSL0SET2	0x0347
+#define PESDR1_HSSL0STS		0x0348
+#define PESDR1_HSSL1SET1	0x0349
+#define PESDR1_HSSL1SET2	0x034a
+#define PESDR1_HSSL1STS		0x034b
+#define PESDR1_HSSL2SET1	0x034c
+#define PESDR1_HSSL2SET2	0x034d
+#define PESDR1_HSSL2STS		0x034e
+#define PESDR1_HSSL3SET1	0x034f
+#define PESDR1_HSSL3SET2	0x0350
+#define PESDR1_HSSL3STS		0x0351
+#define PESDR1_HSSCTLSET	0x0352
+#define PESDR1_LANE_ABCD	0x0353
+
+#define PESDR2_UTLSET1		0x0370
+#define PESDR2_UTLSET2		0x0371
+#define PESDR2_DLPSET		0x0372
+#define PESDR2_LOOP		0x0373
+#define PESDR2_RCSSET		0x0374
+#define PESDR2_RCSSTS		0x0375
+#define PESDR2_HSSL0SET1	0x0376
+#define PESDR2_HSSL0SET2	0x0377
+#define PESDR2_HSSL0STS		0x0378
+#define PESDR2_HSSL1SET1	0x0379
+#define PESDR2_HSSL1SET2	0x037a
+#define PESDR2_HSSL1STS		0x037b
+#define PESDR2_HSSL2SET1	0x037c
+#define PESDR2_HSSL2SET2	0x037d
+#define PESDR2_HSSL2STS		0x037e
+#define PESDR2_HSSL3SET1	0x037f
+#define PESDR2_HSSL3SET2	0x0380
+#define PESDR2_HSSL3STS		0x0381
+#define PESDR2_HSSCTLSET	0x0382
+#define PESDR2_LANE_ABCD	0x0383
+
+#elif defined(CONFIG_405EX)
+
+#define SDRN_PESDR_PHYSET1(n)		(sdr_base(n) + 0x06)
+#define SDRN_PESDR_PHYSET2(n)		(sdr_base(n) + 0x07)
+#define SDRN_PESDR_BIST(n)		(sdr_base(n) + 0x08)
+#define SDRN_PESDR_LPB(n)		(sdr_base(n) + 0x0b)
+#define SDRN_PESDR_PHYSTA(n)		(sdr_base(n) + 0x0c)
+
+#define PESDR0_UTLSET1		0x0400
+#define PESDR0_UTLSET2		0x0401
+#define PESDR0_DLPSET		0x0402
+#define PESDR0_LOOP		0x0403
+#define PESDR0_RCSSET		0x0404
+#define PESDR0_RCSSTS		0x0405
+#define PESDR0_PHYSET1		0x0406
+#define PESDR0_PHYSET2		0x0407
+#define PESDR0_BIST		0x0408
+#define PESDR0_LPB		0x040B
+#define PESDR0_PHYSTA		0x040C
+
+#define PESDR1_UTLSET1		0x0440
+#define PESDR1_UTLSET2		0x0441
+#define PESDR1_DLPSET		0x0442
+#define PESDR1_LOOP		0x0443
+#define PESDR1_RCSSET		0x0444
+#define PESDR1_RCSSTS		0x0445
+#define PESDR1_PHYSET1		0x0446
+#define PESDR1_PHYSET2		0x0447
+#define PESDR1_BIST		0x0448
+#define PESDR1_LPB		0x044B
+#define PESDR1_PHYSTA		0x044C
+
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+
+#define PESDR0_L0BIST		0x0308	/* PE0 L0 built in self test */
+#define PESDR0_L0BISTSTS	0x0309	/* PE0 L0 built in self test status */
+#define PESDR0_L0CDRCTL		0x030A	/* PE0 L0 CDR control */
+#define PESDR0_L0DRV		0x030B	/* PE0 L0 drive */
+#define PESDR0_L0REC		0x030C	/* PE0 L0 receiver */
+#define PESDR0_L0LPB		0x030D	/* PE0 L0 loopback */
+#define PESDR0_L0CLK		0x030E	/* PE0 L0 clocking */
+#define PESDR0_PHY_CTL_RST	0x030F	/* PE0 PHY control reset */
+#define PESDR0_RSTSTA		0x0310	/* PE0 reset status */
+#define PESDR0_OBS		0x0311	/* PE0 observation register */
+#define PESDR0_L0ERRC		0x0320	/* PE0 L0 error counter */
+
+#define PESDR1_L0BIST		0x0348	/* PE1 L0 built in self test */
+#define PESDR1_L1BIST		0x0349	/* PE1 L1 built in self test */
+#define PESDR1_L2BIST		0x034A	/* PE1 L2 built in self test */
+#define PESDR1_L3BIST		0x034B	/* PE1 L3 built in self test */
+#define PESDR1_L0BISTSTS	0x034C	/* PE1 L0 built in self test status */
+#define PESDR1_L1BISTSTS	0x034D	/* PE1 L1 built in self test status */
+#define PESDR1_L2BISTSTS	0x034E	/* PE1 L2 built in self test status */
+#define PESDR1_L3BISTSTS	0x034F	/* PE1 L3 built in self test status */
+#define PESDR1_L0CDRCTL		0x0350	/* PE1 L0 CDR control */
+#define PESDR1_L1CDRCTL		0x0351	/* PE1 L1 CDR control */
+#define PESDR1_L2CDRCTL		0x0352	/* PE1 L2 CDR control */
+#define PESDR1_L3CDRCTL		0x0353	/* PE1 L3 CDR control */
+#define PESDR1_L0DRV		0x0354	/* PE1 L0 drive */
+#define PESDR1_L1DRV		0x0355	/* PE1 L1 drive */
+#define PESDR1_L2DRV		0x0356	/* PE1 L2 drive */
+#define PESDR1_L3DRV		0x0357	/* PE1 L3 drive */
+#define PESDR1_L0REC		0x0358	/* PE1 L0 receiver */
+#define PESDR1_L1REC		0x0359	/* PE1 L1 receiver */
+#define PESDR1_L2REC		0x035A	/* PE1 L2 receiver */
+#define PESDR1_L3REC		0x035B	/* PE1 L3 receiver */
+#define PESDR1_L0LPB		0x035C	/* PE1 L0 loopback */
+#define PESDR1_L1LPB		0x035D	/* PE1 L1 loopback */
+#define PESDR1_L2LPB		0x035E	/* PE1 L2 loopback */
+#define PESDR1_L3LPB		0x035F	/* PE1 L3 loopback */
+#define PESDR1_L0CLK		0x0360	/* PE1 L0 clocking */
+#define PESDR1_L1CLK		0x0361	/* PE1 L1 clocking */
+#define PESDR1_L2CLK		0x0362	/* PE1 L2 clocking */
+#define PESDR1_L3CLK		0x0363	/* PE1 L3 clocking */
+#define PESDR1_PHY_CTL_RST	0x0364	/* PE1 PHY control reset */
+#define PESDR1_RSTSTA		0x0365	/* PE1 reset status */
+#define PESDR1_OBS		0x0366	/* PE1 observation register */
+#define PESDR1_L0ERRC		0x0368	/* PE1 L0 error counter */
+#define PESDR1_L1ERRC		0x0369	/* PE1 L1 error counter */
+#define PESDR1_L2ERRC		0x036A	/* PE1 L2 error counter */
+#define PESDR1_L3ERRC		0x036B	/* PE1 L3 error counter */
+#define PESDR0_IHS1		0x036C	/* PE interrupt handler interfact setting 1 */
+#define PESDR0_IHS2		0x036D	/* PE interrupt handler interfact setting 2 */
+
+#endif
+
+/* SDR Bit Mappings */
+#define PESDRx_RCSSET_HLDPLB	0x10000000
+#define PESDRx_RCSSET_RSTGU	0x01000000
+#define PESDRx_RCSSET_RDY       0x00100000
+#define PESDRx_RCSSET_RSTDL     0x00010000
+#define PESDRx_RCSSET_RSTPYN    0x00001000
+
+#define PESDRx_RCSSTS_PLBIDL	0x10000000
+#define PESDRx_RCSSTS_HRSTRQ	0x01000000
+#define PESDRx_RCSSTS_PGRST	0x00100000
+#define PESDRx_RCSSTS_VC0ACT	0x00010000
+#define PESDRx_RCSSTS_BMEN	0x00000100
+
+/*
+ * UTL register offsets
+ */
+#define	PEUTL_PBCTL		0x00
+#define PEUTL_PBBSZ		0x20
+#define PEUTL_OPDBSZ		0x68
+#define PEUTL_IPHBSZ		0x70
+#define PEUTL_IPDBSZ		0x78
+#define PEUTL_OUTTR		0x90
+#define PEUTL_INTR		0x98
+#define PEUTL_PCTL		0xa0
+#define	PEUTL_RCSTA		0xb0
+#define PEUTL_RCIRQEN		0xb8
+
+/*
+ * Config space register offsets
+ */
+#define PECFG_BAR0LMPA		0x210
+#define PECFG_BAR0HMPA		0x214
+#define PECFG_BAR1MPA		0x218
+#define PECFG_BAR2LMPA		0x220
+#define PECFG_BAR2HMPA		0x224
+
+#define PECFG_PIMEN		0x33c
+#define PECFG_PIM0LAL		0x340
+#define PECFG_PIM0LAH		0x344
+#define PECFG_PIM1LAL		0x348
+#define PECFG_PIM1LAH		0x34c
+#define PECFG_PIM01SAL		0x350
+#define PECFG_PIM01SAH		0x354
+
+#define PECFG_POM0LAL		0x380
+#define PECFG_POM0LAH		0x384
+
+#define SDR_READ(offset) ({\
+	mtdcr(DCRN_SDR0_CFGADDR, offset); \
+	mfdcr(DCRN_SDR0_CFGDATA);})
+
+#define SDR_WRITE(offset, data) ({\
+	mtdcr(DCRN_SDR0_CFGADDR, offset); \
+	mtdcr(DCRN_SDR0_CFGDATA,data);})
+
+#define GPL_DMER_MASK_DISA	0x02000000
+
+#define U64_TO_U32_LOW(val)	((u32)((val) & 0x00000000ffffffffULL))
+#define U64_TO_U32_HIGH(val)	((u32)((val) >> 32))
+
+/*
+ * Prototypes
+ */
+int ppc4xx_init_pcie(void);
+int ppc4xx_init_pcie_rootport(int port);
+int ppc4xx_init_pcie_endport(int port);
+void ppc4xx_setup_pcie_rootpoint(struct pci_controller *hose, int port);
+int ppc4xx_setup_pcie_endpoint(struct pci_controller *hose, int port);
+int pcie_hose_scan(struct pci_controller *hose, int bus);
+
+/*
+ * Function to determine root port or endport from env variable.
+ */
+static inline int is_end_point(int port)
+{
+	char s[10], *tk;
+	char *pcie_mode = getenv("pcie_mode");
+
+	if (pcie_mode == NULL)
+		return 0;
+
+	strcpy(s, pcie_mode);
+	tk = strtok(s, ":");
+
+	switch (port) {
+	case 0:
+		if (tk != NULL) {
+			if (!(strcmp(tk, "ep") && strcmp(tk, "EP")))
+				return 1;
+			else
+				return 0;
+		}
+		else
+			return 0;
+
+	case 1:
+		tk = strtok(NULL, ":");
+		if (tk != NULL) {
+			if (!(strcmp(tk, "ep") && strcmp(tk, "EP")))
+				return 1;
+			else
+				return 0;
+		}
+		else
+			return 0;
+
+	case 2:
+		tk = strtok(NULL, ":");
+		if (tk != NULL)
+			tk = strtok(NULL, ":");
+		if (tk != NULL) {
+			if (!(strcmp(tk, "ep") && strcmp(tk, "EP")))
+				return 1;
+			else
+				return 0;
+		}
+		else
+			return 0;
+	}
+
+	return 0;
+}
+
+static inline void mdelay(int n)
+{
+	u32 ms = n;
+
+	while (ms--)
+		udelay(1000);
+}
+
+#if defined(PCIE0_SDR)
+static inline u32 sdr_base(int port)
+{
+	switch (port) {
+	default:	/* to satisfy compiler */
+	case 0:
+		return PCIE0_SDR;
+	case 1:
+		return PCIE1_SDR;
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+	case 2:
+		return PCIE2_SDR;
+#endif
+	}
+}
+#endif /* defined(PCIE0_SDR) */
+
+#endif /* __4XX_PCIE_H */
diff --git a/arch/powerpc/include/asm/5xx_immap.h b/arch/powerpc/include/asm/5xx_immap.h
new file mode 100644
index 0000000..72cbab4
--- /dev/null
+++ b/arch/powerpc/include/asm/5xx_immap.h
@@ -0,0 +1,439 @@
+/*
+ * (C) Copyright 2003
+ * Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,
+ */
+
+/*
+ * File:		5xx_immap.h
+ *
+ * Discription:		MPC555 Internal Memory Map
+ *
+ */
+
+#ifndef __IMMAP_5XX__
+#define __IMMAP_5XX__
+
+/* System Configuration Registers.
+*/
+typedef	struct sys_conf {
+	uint sc_siumcr;
+	uint sc_sypcr;
+	char res1[6];
+	ushort sc_swsr;
+	uint sc_sipend;
+	uint sc_simask;
+	uint sc_siel;
+	uint sc_sivec;
+	uint sc_tesr;
+	uint sc_sgpiodt1;
+	uint sc_sgpiodt2;
+	uint sc_sgpiocr;
+	uint sc_emcr;
+	uint sc_res1aa;
+	uint sc_res1ab;
+	uint sc_pdmcr;
+	char res3[192];
+} sysconf5xx_t;
+
+
+/* Memory Controller Registers.
+*/
+typedef struct	mem_ctlr {
+	uint memc_br0;
+	uint memc_or0;
+	uint memc_br1;
+	uint memc_or1;
+	uint memc_br2;
+	uint memc_or2;
+	uint memc_br3;
+	uint memc_or3;
+	char res1[32];
+	uint memc_dmbr;
+	uint memc_dmor;
+	char res2[48];
+	ushort memc_mstat;
+	ushort memc_res4a;
+	char res3[132];
+} memctl5xx_t;
+
+/* System Integration Timers.
+*/
+typedef struct	sys_int_timers {
+	ushort sit_tbscr;
+	char res1[2];
+	uint sit_tbref0;
+	uint sit_tbref1;
+	char res2[20];
+	ushort sit_rtcsc;
+	char res3[2];
+	uint sit_rtc;
+	uint sit_rtsec;
+	uint sit_rtcal;
+	char res4[16];
+	ushort sit_piscr;
+	char res5[2];
+	uint sit_pitc;
+	uint sit_pitr;
+	char res6[52];
+} sit5xx_t;
+
+/* Clocks and Reset
+*/
+typedef struct clk_and_reset {
+	uint car_sccr;
+	uint car_plprcr;
+	ushort car_rsr;
+	ushort car_res7a;
+	ushort car_colir;
+	ushort car_res7b;
+	ushort car_vsrmcr;
+	ushort car_res7c;
+	char res1[108];
+
+} car5xx_t;
+
+#define TBSCR_TBE		((ushort)0x0001)
+
+/* System Integration Timer Keys
+*/
+typedef struct sitk {
+	uint sitk_tbscrk;
+	uint sitk_tbref0k;
+	uint sitk_tbref1k;
+	uint sitk_tbk;
+	char res1[16];
+	uint sitk_rtcsck;
+	uint sitk_rtck;
+	uint sitk_rtseck;
+	uint sitk_rtcalk;
+	char res2[16];
+	uint sitk_piscrk;
+	uint sitk_pitck;
+	char res3[56];
+} sitk5xx_t;
+
+/* Clocks and Reset Keys.
+*/
+typedef struct cark {
+	uint	cark_sccrk;
+	uint	cark_plprcrk;
+	uint	cark_rsrk;
+	char	res1[1140];
+} cark8xx_t;
+
+/* The key to unlock registers maintained by keep-alive power.
+*/
+#define KAPWR_KEY	((unsigned int)0x55ccaa33)
+
+/* Flash Configuration
+*/
+typedef struct fl {
+	uint fl_cmfmcr;
+	uint fl_cmftst;
+	uint fl_cmfctl;
+	char res1[52];
+} fl5xx_t;
+
+/* Dpram Control
+*/
+typedef struct dprc {
+	ushort dprc_dptmcr;
+	ushort dprc_ramtst;
+	ushort dprc_rambar;
+	ushort dprc_misrh;
+	ushort dprc_misrl;
+	ushort dprc_miscnt;
+} dprc5xx_t;
+
+/* Time Processor Unit
+*/
+typedef struct tpu {
+	ushort tpu_tpumcr;
+	ushort tpu_tcr;
+	ushort tpu_dscr;
+	ushort tpu_dssr;
+	ushort tpu_ticr;
+	ushort tpu_cier;
+	ushort tpu_cfsr0;
+	ushort tpu_cfsr1;
+	ushort tpu_cfsr2;
+	ushort tpu_cfsr3;
+	ushort tpu_hsqr0;
+	ushort tpu_hsqr1;
+	ushort tpu_hsrr0;
+	ushort tpu_hsrr1;
+	ushort tpu_cpr0;
+	ushort tpu_cpr1;
+	ushort tpu_cisr;
+	ushort tpu_lr;
+	ushort tpu_sglr;
+	ushort tpu_dcnr;
+	ushort tpu_tpumcr2;
+	ushort tpu_tpumcr3;
+	ushort tpu_isdr;
+	ushort tpu_iscr;
+	char   res1[208];
+	char   tpu[16][16];
+	char   res2[512];
+} tpu5xx_t;
+
+/* QADC
+*/
+typedef struct qadc {
+	ushort qadc_64mcr;
+	ushort qadc_64test;
+	ushort qadc_64int;
+	u_char  qadc_portqa;
+	u_char  qadc_portqb;
+	ushort qadc_ddrqa;
+	ushort qadc_qacr0;
+	ushort qadc_qacr1;
+	ushort qadc_qacr2;
+	ushort qadc_qasr0;
+	ushort qadc_qasr1;
+	char   res1[492];
+       /* command convertion word table */
+	ushort qadc_ccw[64];
+       /* result word table, unsigned right justified */
+	ushort qadc_rjurr[64];
+       /* result word table, signed left justified */
+	ushort qadc_ljsrr[64];
+       /* result word table, unsigned left justified */
+	ushort qadc_ljurr[64];
+} qadc5xx_t;
+
+/* QSMCM
+*/
+typedef struct qsmcm {
+	ushort qsmcm_qsmcr;
+	ushort qsmcm_qtest;
+	ushort qsmcm_qdsci_il;
+	ushort qsmcm_qspi_il;
+	ushort qsmcm_scc1r0;
+	ushort qsmcm_scc1r1;
+	ushort qsmcm_sc1sr;
+	ushort qsmcm_sc1dr;
+	char   res1[2];
+	char   res2[2];
+	ushort qsmcm_portqs;
+	u_char qsmcm_pqspar;
+	u_char qsmcm_ddrqs;
+	ushort qsmcm_spcr0;
+	ushort qsmcm_spcr1;
+	ushort qsmcm_spcr2;
+	u_char qsmcm_spcr3;
+	u_char qsmcm_spsr;
+	ushort qsmcm_scc2r0;
+	ushort qsmcm_scc2r1;
+	ushort qsmcm_sc2sr;
+	ushort qsmcm_sc2dr;
+	ushort qsmcm_qsci1cr;
+	ushort qsmcm_qsci1sr;
+	ushort qsmcm_sctq[16];
+	ushort qsmcm_scrq[16];
+	char   res3[212];
+	ushort qsmcm_recram[32];
+	ushort qsmcm_tranram[32];
+	u_char qsmcm_comdram[32];
+	char   res[3616];
+} qsmcm5xx_t;
+
+
+/* MIOS
+*/
+
+typedef struct mios {
+	ushort mios_mpwmsm0perr;                 /* mpwmsm0 */
+	ushort mios_mpwmsm0pulr;
+	ushort mios_mpwmsm0cntr;
+	ushort mios_mpwmsm0scr;
+	ushort mios_mpwmsm1perr;                 /* mpwmsm1 */
+	ushort mios_mpwmsm1pulr;
+	ushort mios_mpwmsm1cntr;
+	ushort mios_mpwmsm1scr;
+	ushort mios_mpwmsm2perr;                 /* mpwmsm2 */
+	ushort mios_mpwmsm2pulr;
+	ushort mios_mpwmsm2cntr;
+	ushort mios_mpwmsm2scr;
+	ushort mios_mpwmsm3perr;                 /* mpwmsm3 */
+	ushort mios_mpwmsm3pulr;
+	ushort mios_mpwmsm3cntr;
+	ushort mios_mpwmsm3scr;
+	char res1[16];
+	ushort mios_mmcsm6cnt;                   /* mmcsm6 */
+	ushort mios_mmcsm6mlr;
+	ushort mios_mmcsm6scrd, mmcsm6scr;
+	char res2[32];
+	ushort mios_mdasm11ar;                   /* mdasm11 */
+	ushort mios_mdasm11br;
+	ushort mios_mdasm11scrd, mdasm11scr;
+	ushort mios_mdasm12ar;                   /* mdasm12 */
+	ushort mios_mdasm12br;
+	ushort mios_mdasm12scrd, mdasm12scr;
+	ushort mios_mdasm13ar;                   /* mdasm13 */
+	ushort mios_mdasm13br;
+	ushort mios_mdasm13scrd, mdasm13scr;
+	ushort mios_mdasm14ar;                   /* mdasm14 */
+	ushort mios_mdasm14br;
+	ushort mios_mdasm14scrd, mdasm14scr;
+	ushort mios_mdasm15ar;                   /* mdasm15 */
+	ushort mios_mdasm15br;
+	ushort mios_mdasm15scrd, mdasm15scr;
+	ushort mios_mpwmsm16perr;                /* mpwmsm16 */
+	ushort mios_mpwmsm16pulr;
+	ushort mios_mpwmsm16cntr;
+	ushort mios_mpwmsm16scr;
+	ushort mios_mpwmsm17perr;                /* mpwmsm17 */
+	ushort mios_mpwmsm17pulr;
+	ushort mios_mpwmsm17cntr;
+	ushort mios_mpwmsm17scr;
+	ushort mios_mpwmsm18perr;                /* mpwmsm18 */
+	ushort mios_mpwmsm18pulr;
+	ushort mios_mpwmsm18cntr;
+	ushort mios_mpwmsm18scr;
+	ushort mios_mpwmsm19perr;                /* mpwmsm19 */
+	ushort mios_mpwmsm19pulr;
+	ushort mios_mpwmsm19cntr;
+	ushort mios_mpwmsm19scr;
+	char res3[16];
+	ushort mios_mmcsm22cnt;                  /* mmcsm22 */
+	ushort mios_mmcsm22mlr;
+	ushort mios_mmcsm22scrd, mmcsm22scr;
+	char res4[32];
+	ushort mios_mdasm27ar;                   /* mdasm27 */
+	ushort mios_mdasm27br;
+	ushort mios_mdasm27scrd, mdasm27scr;
+	ushort mios_mdasm28ar;                   /*mdasm28 */
+	ushort mios_mdasm28br;
+	ushort mios_mdasm28scrd, mdasm28scr;
+	ushort mios_mdasm29ar;                   /* mdasm29 */
+	ushort mios_mdasm29br;
+	ushort mios_mdasm29scrd, mdasm29scr;
+	ushort mios_mdasm30ar;                   /* mdasm30 */
+	ushort mios_mdasm30br;
+	ushort mios_mdasm30scrd, mdasm30scr;
+	ushort mios_mdasm31ar;                   /* mdasm31 */
+	ushort mios_mdasm31br;
+	ushort mios_mdasm31scrd, mdasm31scr;
+	ushort mios_mpiosm32dr;
+	ushort mios_mpiosm32ddr;
+	char res5[1788];
+	ushort mios_mios1tpcr;
+	char mios_res13[2];
+	ushort mios_mios1vnr;
+	ushort mios_mios1mcr;
+	char res6[12];
+	ushort mios_res42z;
+	ushort mios_mcpsmscr;
+	char res7[1000];
+	ushort mios_mios1sr0;
+	char res12[2];
+	ushort mios_mios1er0;
+	ushort mios_mios1rpr0;
+	char res8[40];
+	ushort mios_mios1lvl0;
+	char res9[14];
+	ushort mios_mios1sr1;
+	char res10[2];
+	ushort mios_mios1er1;
+	ushort mios_mios1rpr1;
+	char res11[40];
+	ushort mios_mios1lvl1;
+	char res13[1038];
+} mios5xx_t;
+
+/* Toucan Module
+*/
+typedef struct tcan {
+	ushort tcan_tcnmcr;
+	ushort tcan_cantcr;
+	ushort tcan_canicr;
+	u_char tcan_canctrl0;
+	u_char tcan_canctrl1;
+	u_char tcan_presdiv;
+	u_char tcan_canctrl2;
+	ushort tcan_timer;
+	char res1[4];
+	ushort tcan_rxgmskhi;
+	ushort tcan_rxgmsklo;
+	ushort tcan_rx14mskhi;
+	ushort tcan_rx14msklo;
+	ushort tcan_rx15mskhi;
+	ushort tcan_rx15msklo;
+	char res2[4];
+	ushort tcan_estat;
+	ushort tcan_imask;
+	ushort tcan_iflag;
+	u_char tcan_rxectr;
+	u_char tcan_txectr;
+	char res3[88];
+	struct {
+	       ushort scr;
+	       ushort id_high;
+	       ushort id_low;
+	       u_char data[8];
+		   char res4[2];
+	    } tcan_mbuff[16];
+	    char res5[640];
+} tcan5xx_t;
+
+/* UIMB
+*/
+typedef struct uimb {
+	uint uimb_umcr;
+	char res1[12];
+	uint uimb_utstcreg;
+	char res2[12];
+	uint uimb_uipend;
+} uimb5xx_t;
+
+
+/* Internal Memory Map MPC555
+*/
+typedef struct immap {
+	char               res1[262144];	/* CMF Flash A 256 Kbytes */
+	char               res2[196608];	/* CMF Flash B 192 Kbytes */
+	char               res3[2670592];	/* Reserved for Flash */
+	sysconf5xx_t       im_siu_conf;		/* SIU Configuration */
+	memctl5xx_t	   im_memctl;		/* Memory Controller */
+	sit5xx_t           im_sit;		/* System Integration Timers */
+	car5xx_t	   im_clkrst;		/* Clocks and Reset */
+	sitk5xx_t          im_sitk;		/* System Integration Timer Keys*/
+	cark8xx_t          im_clkrstk;		/* Clocks and Resert Keys */
+	fl5xx_t	           im_fla;	        /* Flash Module A */
+	fl5xx_t	           im_flb;	        /* Flash Module B */
+	char               res4[14208];		/* Reserved for SIU */
+	dprc5xx_t	   im_dprc;		/* Dpram Control Register */
+	char               res5[8180];		/* Reserved */
+	char               dptram[6144];	/* Dptram */
+	char               res6[2048];		/* Reserved */
+	tpu5xx_t	   im_tpua;		/* Time Proessing Unit A */
+	tpu5xx_t	   im_tpub;		/* Time Processing Unit B */
+	qadc5xx_t	   im_qadca;		/* QADC A */
+	qadc5xx_t	   im_qadcb;		/* QADC B */
+	qsmcm5xx_t	   im_qsmcm;		/* SCI and SPI */
+	mios5xx_t	   im_mios;		/* MIOS */
+	tcan5xx_t          im_tcana;		/* Toucan A */
+	tcan5xx_t          im_tcanb;		/* Toucan B */
+	char               res7[1792];		/* Reserved */
+	uimb5xx_t          im_uimb;	        /* UIMB */
+} immap_t;
+
+#endif /* __IMMAP_5XX__ */
diff --git a/arch/powerpc/include/asm/8xx_immap.h b/arch/powerpc/include/asm/8xx_immap.h
new file mode 100644
index 0000000..40679cb
--- /dev/null
+++ b/arch/powerpc/include/asm/8xx_immap.h
@@ -0,0 +1,511 @@
+
+/*
+ * MPC8xx Internal Memory Map
+ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ *
+ * The I/O on the MPC860 is comprised of blocks of special registers
+ * and the dual port ram for the Communication Processor Module.
+ * Within this space are functional units such as the SIU, memory
+ * controller, system timers, and other control functions.  It is
+ * a combination that I found difficult to separate into logical
+ * functional files.....but anyone else is welcome to try.  -- Dan
+ */
+#ifndef __IMMAP_8XX__
+#define __IMMAP_8XX__
+
+/* System configuration registers.
+*/
+typedef	struct sys_conf {
+	uint	sc_siumcr;
+	uint	sc_sypcr;
+	uint	sc_swt;
+	char	res1[2];
+	ushort	sc_swsr;
+	uint	sc_sipend;
+	uint	sc_simask;
+	uint	sc_siel;
+	uint	sc_sivec;
+	uint	sc_tesr;
+	char	res2[0xc];
+	uint	sc_sdcr;
+	char	res3[0x4c];
+} sysconf8xx_t;
+
+/* PCMCIA configuration registers.
+*/
+typedef struct pcmcia_conf {
+	uint	pcmc_pbr0;
+	uint	pcmc_por0;
+	uint	pcmc_pbr1;
+	uint	pcmc_por1;
+	uint	pcmc_pbr2;
+	uint	pcmc_por2;
+	uint	pcmc_pbr3;
+	uint	pcmc_por3;
+	uint	pcmc_pbr4;
+	uint	pcmc_por4;
+	uint	pcmc_pbr5;
+	uint	pcmc_por5;
+	uint	pcmc_pbr6;
+	uint	pcmc_por6;
+	uint	pcmc_pbr7;
+	uint	pcmc_por7;
+	char	res1[0x20];
+	uint	pcmc_pgcra;
+	uint	pcmc_pgcrb;
+	uint	pcmc_pscr;
+	char	res2[4];
+	uint	pcmc_pipr;
+	char	res3[4];
+	uint	pcmc_per;
+	char	res4[4];
+} pcmconf8xx_t;
+
+/* Memory controller registers.
+*/
+typedef struct	mem_ctlr {
+	uint	memc_br0;
+	uint	memc_or0;
+	uint	memc_br1;
+	uint	memc_or1;
+	uint	memc_br2;
+	uint	memc_or2;
+	uint	memc_br3;
+	uint	memc_or3;
+	uint	memc_br4;
+	uint	memc_or4;
+	uint	memc_br5;
+	uint	memc_or5;
+	uint	memc_br6;
+	uint	memc_or6;
+	uint	memc_br7;
+	uint	memc_or7;
+	char	res1[0x24];
+	uint	memc_mar;
+	uint	memc_mcr;
+	char	res2[4];
+	uint	memc_mamr;
+	uint	memc_mbmr;
+	ushort	memc_mstat;
+	ushort	memc_mptpr;
+	uint	memc_mdr;
+	char	res3[0x80];
+} memctl8xx_t;
+
+/* System Integration Timers.
+*/
+typedef struct	sys_int_timers {
+	ushort	sit_tbscr;
+	char	res0[0x02];
+	uint	sit_tbreff0;
+	uint	sit_tbreff1;
+	char	res1[0x14];
+	ushort	sit_rtcsc;
+	char	res2[0x02];
+	uint	sit_rtc;
+	uint	sit_rtsec;
+	uint	sit_rtcal;
+	char	res3[0x10];
+	ushort	sit_piscr;
+	char	res4[2];
+	uint	sit_pitc;
+	uint	sit_pitr;
+	char	res5[0x34];
+} sit8xx_t;
+
+#define TBSCR_TBIRQ_MASK	((ushort)0xff00)
+#define TBSCR_REFA		((ushort)0x0080)
+#define TBSCR_REFB		((ushort)0x0040)
+#define TBSCR_REFAE		((ushort)0x0008)
+#define TBSCR_REFBE		((ushort)0x0004)
+#define TBSCR_TBF		((ushort)0x0002)
+#define TBSCR_TBE		((ushort)0x0001)
+
+#define RTCSC_RTCIRQ_MASK	((ushort)0xff00)
+#define RTCSC_SEC		((ushort)0x0080)
+#define RTCSC_ALR		((ushort)0x0040)
+#define RTCSC_38K		((ushort)0x0010)
+#define RTCSC_SIE		((ushort)0x0008)
+#define RTCSC_ALE		((ushort)0x0004)
+#define RTCSC_RTF		((ushort)0x0002)
+#define RTCSC_RTE		((ushort)0x0001)
+
+#define PISCR_PIRQ_MASK		((ushort)0xff00)
+#define PISCR_PS		((ushort)0x0080)
+#define PISCR_PIE		((ushort)0x0004)
+#define PISCR_PTF		((ushort)0x0002)
+#define PISCR_PTE		((ushort)0x0001)
+
+/* Clocks and Reset.
+*/
+typedef struct clk_and_reset {
+	uint	car_sccr;
+	uint	car_plprcr;
+	uint	car_rsr;
+	char	res[0x74];        /* Reserved area                  */
+} car8xx_t;
+
+/* System Integration Timers keys.
+*/
+typedef struct sitk {
+	uint	sitk_tbscrk;
+	uint	sitk_tbreff0k;
+	uint	sitk_tbreff1k;
+	uint	sitk_tbk;
+	char	res1[0x10];
+	uint	sitk_rtcsck;
+	uint	sitk_rtck;
+	uint	sitk_rtseck;
+	uint	sitk_rtcalk;
+	char	res2[0x10];
+	uint	sitk_piscrk;
+	uint	sitk_pitck;
+	char	res3[0x38];
+} sitk8xx_t;
+
+/* Clocks and reset keys.
+*/
+typedef struct cark {
+	uint	cark_sccrk;
+	uint	cark_plprcrk;
+	uint	cark_rsrk;
+	char	res[0x474];
+} cark8xx_t;
+
+/* The key to unlock registers maintained by keep-alive power.
+*/
+#define KAPWR_KEY	((unsigned int)0x55ccaa33)
+
+/* Video interface.  MPC823 Only.
+*/
+typedef struct vid823 {
+	ushort	vid_vccr;
+	ushort	res1;
+	u_char	vid_vsr;
+	u_char	res2;
+	u_char	vid_vcmr;
+	u_char	res3;
+	uint	vid_vbcb;
+	uint	res4;
+	uint	vid_vfcr0;
+	uint	vid_vfaa0;
+	uint	vid_vfba0;
+	uint	vid_vfcr1;
+	uint	vid_vfaa1;
+	uint	vid_vfba1;
+	u_char	res5[0x18];
+} vid823_t;
+
+/* LCD interface.  823 Only.
+*/
+typedef struct lcd {
+	uint	lcd_lccr;
+	uint	lcd_lchcr;
+	uint	lcd_lcvcr;
+	char	res1[4];
+	uint	lcd_lcfaa;
+	uint	lcd_lcfba;
+	char	lcd_lcsr;
+	char	res2[0x7];
+} lcd823_t;
+
+/* I2C
+*/
+typedef struct i2c {
+	u_char	i2c_i2mod;
+	char	res1[3];
+	u_char	i2c_i2add;
+	char	res2[3];
+	u_char	i2c_i2brg;
+	char	res3[3];
+	u_char	i2c_i2com;
+	char	res4[3];
+	u_char	i2c_i2cer;
+	char	res5[3];
+	u_char	i2c_i2cmr;
+	char	res6[0x8b];
+} i2c8xx_t;
+
+/* DMA control/status registers.
+*/
+typedef struct sdma_csr {
+	char	res1[4];
+	uint	sdma_sdar;
+	u_char	sdma_sdsr;
+	char	res3[3];
+	u_char	sdma_sdmr;
+	char	res4[3];
+	u_char	sdma_idsr1;
+	char	res5[3];
+	u_char	sdma_idmr1;
+	char	res6[3];
+	u_char	sdma_idsr2;
+	char	res7[3];
+	u_char	sdma_idmr2;
+	char	res8[0x13];
+} sdma8xx_t;
+
+/* Communication Processor Module Interrupt Controller.
+*/
+typedef struct cpm_ic {
+	ushort	cpic_civr;
+	char	res[0xe];
+	uint	cpic_cicr;
+	uint	cpic_cipr;
+	uint	cpic_cimr;
+	uint	cpic_cisr;
+} cpic8xx_t;
+
+/* Input/Output Port control/status registers.
+*/
+typedef struct io_port {
+	ushort	iop_padir;
+	ushort	iop_papar;
+	ushort	iop_paodr;
+	ushort	iop_padat;
+	char	res1[8];
+	ushort	iop_pcdir;
+	ushort	iop_pcpar;
+	ushort	iop_pcso;
+	ushort	iop_pcdat;
+	ushort	iop_pcint;
+	char	res2[6];
+	ushort	iop_pddir;
+	ushort	iop_pdpar;
+	char	res3[2];
+	ushort	iop_pddat;
+	uint	utmode;
+	char	res4[4];
+} iop8xx_t;
+
+/* Communication Processor Module Timers
+*/
+typedef struct cpm_timers {
+	ushort	cpmt_tgcr;
+	char	res1[0xe];
+	ushort	cpmt_tmr1;
+	ushort	cpmt_tmr2;
+	ushort	cpmt_trr1;
+	ushort	cpmt_trr2;
+	ushort	cpmt_tcr1;
+	ushort	cpmt_tcr2;
+	ushort	cpmt_tcn1;
+	ushort	cpmt_tcn2;
+	ushort	cpmt_tmr3;
+	ushort	cpmt_tmr4;
+	ushort	cpmt_trr3;
+	ushort	cpmt_trr4;
+	ushort	cpmt_tcr3;
+	ushort	cpmt_tcr4;
+	ushort	cpmt_tcn3;
+	ushort	cpmt_tcn4;
+	ushort	cpmt_ter1;
+	ushort	cpmt_ter2;
+	ushort	cpmt_ter3;
+	ushort	cpmt_ter4;
+	char	res2[8];
+} cpmtimer8xx_t;
+
+/* Finally, the Communication Processor stuff.....
+*/
+typedef struct scc {		/* Serial communication channels */
+	uint	scc_gsmrl;
+	uint	scc_gsmrh;
+	ushort	scc_psmr;
+	char	res1[2];
+	ushort	scc_todr;
+	ushort	scc_dsr;
+	ushort	scc_scce;
+	char	res2[2];
+	ushort	scc_sccm;
+	char	res3;
+	u_char	scc_sccs;
+	char	res4[8];
+} scc_t;
+
+typedef struct smc {		/* Serial management channels */
+	char	res1[2];
+	ushort	smc_smcmr;
+	char	res2[2];
+	u_char	smc_smce;
+	char	res3[3];
+	u_char	smc_smcm;
+	char	res4[5];
+} smc_t;
+
+/* MPC860T Fast Ethernet Controller.  It isn't part of the CPM, but
+ * it fits within the address space.
+ */
+
+typedef struct fec {
+	uint	fec_addr_low;		/* lower 32 bits of station address	*/
+	ushort	fec_addr_high;		/* upper 16 bits of station address	*/
+	ushort	res1;			/* reserved				*/
+	uint	fec_hash_table_high;	/* upper 32-bits of hash table		*/
+	uint	fec_hash_table_low;	/* lower 32-bits of hash table		*/
+	uint	fec_r_des_start;	/* beginning of Rx descriptor ring	*/
+	uint	fec_x_des_start;	/* beginning of Tx descriptor ring	*/
+	uint	fec_r_buff_size;	/* Rx buffer size			*/
+	uint	res2[9];		/* reserved				*/
+	uint	fec_ecntrl;		/* ethernet control register		*/
+	uint	fec_ievent;		/* interrupt event register		*/
+	uint	fec_imask;		/* interrupt mask register		*/
+	uint	fec_ivec;		/* interrupt level and vector status	*/
+	uint	fec_r_des_active;	/* Rx ring updated flag			*/
+	uint	fec_x_des_active;	/* Tx ring updated flag			*/
+	uint	res3[10];		/* reserved				*/
+	uint	fec_mii_data;		/* MII data register			*/
+	uint	fec_mii_speed;		/* MII speed control register		*/
+	uint	res4[17];		/* reserved				*/
+	uint	fec_r_bound;		/* end of RAM (read-only)		*/
+	uint	fec_r_fstart;		/* Rx FIFO start address		*/
+	uint	res5[6];		/* reserved				*/
+	uint	fec_x_fstart;		/* Tx FIFO start address		*/
+	uint	res6[17];		/* reserved				*/
+	uint	fec_fun_code;		/* fec SDMA function code		*/
+	uint	res7[3];		/* reserved				*/
+	uint	fec_r_cntrl;		/* Rx control register			*/
+	uint	fec_r_hash;		/* Rx hash register			*/
+	uint	res8[14];		/* reserved				*/
+	uint	fec_x_cntrl;		/* Tx control register			*/
+	uint	res9[0x1e];		/* reserved				*/
+} fec_t;
+
+/* The FEC and LCD color map share the same address space....
+ * I guess we will never see an 823T :-).
+ */
+union fec_lcd {
+	fec_t	fl_un_fec;
+	u_char	fl_un_cmap[0x200];
+};
+
+typedef struct comm_proc {
+	/* General control and status registers.
+	*/
+	ushort	cp_cpcr;
+	u_char	res1[2];
+	ushort	cp_rccr;
+	u_char	res2;
+	u_char	cp_rmds;
+	u_char	res3[4];
+	ushort	cp_cpmcr1;
+	ushort	cp_cpmcr2;
+	ushort	cp_cpmcr3;
+	ushort	cp_cpmcr4;
+	u_char	res4[2];
+	ushort	cp_rter;
+	u_char	res5[2];
+	ushort	cp_rtmr;
+	u_char	res6[0x14];
+
+	/* Baud rate generators.
+	*/
+	uint	cp_brgc1;
+	uint	cp_brgc2;
+	uint	cp_brgc3;
+	uint	cp_brgc4;
+
+	/* Serial Communication Channels.
+	*/
+	scc_t	cp_scc[4];
+
+	/* Serial Management Channels.
+	*/
+	smc_t	cp_smc[2];
+
+	/* Serial Peripheral Interface.
+	*/
+	ushort	cp_spmode;
+	u_char	res7[4];
+	u_char	cp_spie;
+	u_char	res8[3];
+	u_char	cp_spim;
+	u_char	res9[2];
+	u_char	cp_spcom;
+	u_char	res10[2];
+
+	/* Parallel Interface Port.
+	*/
+	u_char	res11[2];
+	ushort	cp_pipc;
+	u_char	res12[2];
+	ushort	cp_ptpr;
+	uint	cp_pbdir;
+	uint	cp_pbpar;
+	u_char	res13[2];
+	ushort	cp_pbodr;
+	uint	cp_pbdat;
+
+	/* Port E - MPC87x/88x only.
+	 */
+	uint	cp_pedir;
+	uint	cp_pepar;
+	uint	cp_peso;
+	uint	cp_peodr;
+	uint	cp_pedat;
+
+	/* Communications Processor Timing Register -
+	   Contains RMII Timing for the FECs on MPC87x/88x only.
+	*/
+	uint	cp_cptr;
+
+	/* Serial Interface and Time Slot Assignment.
+	*/
+	uint	cp_simode;
+	u_char	cp_sigmr;
+	u_char	res15;
+	u_char	cp_sistr;
+	u_char	cp_sicmr;
+	u_char	res16[4];
+	uint	cp_sicr;
+	uint	cp_sirp;
+	u_char	res17[0xc];
+
+	/* 256 bytes of MPC823 video controller RAM array.
+	*/
+	u_char	cp_vcram[0x100];
+	u_char	cp_siram[0x200];
+
+	/* The fast ethernet controller is not really part of the CPM,
+	 * but it resides in the address space.
+	 * The LCD color map is also here.
+	 */
+	union	fec_lcd	fl_un;
+#define cp_fec		fl_un.fl_un_fec
+#define lcd_cmap	fl_un.fl_un_cmap
+	char	res18[0xE00];
+
+	/* The MPC885 family has a second FEC here */
+	fec_t	cp_fec2;
+#define cp_fec1	cp_fec	/* consistency macro */
+
+	/* Dual Ported RAM follows.
+	 * There are many different formats for this memory area
+	 * depending upon the devices used and options chosen.
+	 * Some processors don't have all of it populated.
+	 */
+	u_char	cp_dpmem[0x1C00];	/* BD / Data / ucode */
+	u_char	cp_dparam[0x400];	/* Parameter RAM */
+} cpm8xx_t;
+
+/* Internal memory map.
+*/
+typedef struct immap {
+	sysconf8xx_t	im_siu_conf;	/* SIU Configuration */
+	pcmconf8xx_t	im_pcmcia;	/* PCMCIA Configuration */
+	memctl8xx_t	im_memctl;	/* Memory Controller */
+	sit8xx_t	im_sit;		/* System integration timers */
+	car8xx_t	im_clkrst;	/* Clocks and reset */
+	sitk8xx_t	im_sitk;	/* Sys int timer keys */
+	cark8xx_t	im_clkrstk;	/* Clocks and reset keys */
+	vid823_t	im_vid;		/* Video (823 only) */
+	lcd823_t	im_lcd;		/* LCD (823 only) */
+	i2c8xx_t	im_i2c;		/* I2C control/status */
+	sdma8xx_t	im_sdma;	/* SDMA control/status */
+	cpic8xx_t	im_cpic;	/* CPM Interrupt Controller */
+	iop8xx_t	im_ioport;	/* IO Port control/status */
+	cpmtimer8xx_t	im_cpmtimer;	/* CPM timers */
+	cpm8xx_t	im_cpm;		/* Communication processor */
+} immap_t;
+
+#endif /* __IMMAP_8XX__ */
diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
new file mode 100644
index 0000000..23f22df
--- /dev/null
+++ b/arch/powerpc/include/asm/atomic.h
@@ -0,0 +1,95 @@
+/*
+ * PowerPC atomic operations
+ */
+
+#ifndef _ASM_PPC_ATOMIC_H_
+#define _ASM_PPC_ATOMIC_H_
+
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
+typedef struct { volatile int counter; } atomic_t;
+#else
+typedef struct { int counter; } atomic_t;
+#endif
+
+#define ATOMIC_INIT(i)	{ (i) }
+
+#define atomic_read(v)		((v)->counter)
+#define atomic_set(v,i)		(((v)->counter) = (i))
+
+extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
+extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
+
+extern __inline__ int atomic_add_return(int a, atomic_t *v)
+{
+	int t;
+
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%3\n\
+	add	%0,%2,%0\n\
+	stwcx.	%0,0,%3\n\
+	bne-	1b"
+	: "=&r" (t), "=m" (*v)
+	: "r" (a), "r" (v), "m" (*v)
+	: "cc");
+
+	return t;
+}
+
+extern __inline__ int atomic_sub_return(int a, atomic_t *v)
+{
+	int t;
+
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%3\n\
+	subf	%0,%2,%0\n\
+	stwcx.	%0,0,%3\n\
+	bne-	1b"
+	: "=&r" (t), "=m" (*v)
+	: "r" (a), "r" (v), "m" (*v)
+	: "cc");
+
+	return t;
+}
+
+extern __inline__ int atomic_inc_return(atomic_t *v)
+{
+	int t;
+
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%2\n\
+	addic	%0,%0,1\n\
+	stwcx.	%0,0,%2\n\
+	bne-	1b"
+	: "=&r" (t), "=m" (*v)
+	: "r" (v), "m" (*v)
+	: "cc");
+
+	return t;
+}
+
+extern __inline__ int atomic_dec_return(atomic_t *v)
+{
+	int t;
+
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%2\n\
+	addic	%0,%0,-1\n\
+	stwcx.	%0,0,%2\n\
+	bne	1b"
+	: "=&r" (t), "=m" (*v)
+	: "r" (v), "m" (*v)
+	: "cc");
+
+	return t;
+}
+
+#define atomic_add(a, v)		((void) atomic_add_return((a), (v)))
+#define atomic_sub(a, v)		((void) atomic_sub_return((a), (v)))
+#define atomic_sub_and_test(a, v)	(atomic_sub_return((a), (v)) == 0)
+#define atomic_inc(v)			((void) atomic_inc_return((v)))
+#define atomic_dec(v)			((void) atomic_dec_return((v)))
+#define atomic_dec_and_test(v)		(atomic_dec_return((v)) == 0)
+
+#endif /* _ASM_PPC_ATOMIC_H_ */
diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
new file mode 100644
index 0000000..adaf091
--- /dev/null
+++ b/arch/powerpc/include/asm/bitops.h
@@ -0,0 +1,387 @@
+/*
+ * bitops.h: Bit string operations on the ppc
+ */
+
+#ifndef _PPC_BITOPS_H
+#define _PPC_BITOPS_H
+
+#include <linux/config.h>
+#include <asm/byteorder.h>
+
+extern void set_bit(int nr, volatile void *addr);
+extern void clear_bit(int nr, volatile void *addr);
+extern void change_bit(int nr, volatile void *addr);
+extern int test_and_set_bit(int nr, volatile void *addr);
+extern int test_and_clear_bit(int nr, volatile void *addr);
+extern int test_and_change_bit(int nr, volatile void *addr);
+
+/*
+ * Arguably these bit operations don't imply any memory barrier or
+ * SMP ordering, but in fact a lot of drivers expect them to imply
+ * both, since they do on x86 cpus.
+ */
+#ifdef CONFIG_SMP
+#define SMP_WMB		"eieio\n"
+#define SMP_MB		"\nsync"
+#else
+#define SMP_WMB
+#define SMP_MB
+#endif /* CONFIG_SMP */
+
+#define __INLINE_BITOPS	1
+
+#if __INLINE_BITOPS
+/*
+ * These used to be if'd out here because using : "cc" as a constraint
+ * resulted in errors from egcs.  Things may be OK with gcc-2.95.
+ */
+extern __inline__ void set_bit(int nr, volatile void * addr)
+{
+	unsigned long old;
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+	__asm__ __volatile__(SMP_WMB "\
+1:	lwarx	%0,0,%3\n\
+	or	%0,%0,%2\n\
+	stwcx.	%0,0,%3\n\
+	bne	1b"
+	SMP_MB
+	: "=&r" (old), "=m" (*p)
+	: "r" (mask), "r" (p), "m" (*p)
+	: "cc" );
+}
+
+extern __inline__ void clear_bit(int nr, volatile void *addr)
+{
+	unsigned long old;
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+	__asm__ __volatile__(SMP_WMB "\
+1:	lwarx	%0,0,%3\n\
+	andc	%0,%0,%2\n\
+	stwcx.	%0,0,%3\n\
+	bne	1b"
+	SMP_MB
+	: "=&r" (old), "=m" (*p)
+	: "r" (mask), "r" (p), "m" (*p)
+	: "cc");
+}
+
+extern __inline__ void change_bit(int nr, volatile void *addr)
+{
+	unsigned long old;
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+	__asm__ __volatile__(SMP_WMB "\
+1:	lwarx	%0,0,%3\n\
+	xor	%0,%0,%2\n\
+	stwcx.	%0,0,%3\n\
+	bne	1b"
+	SMP_MB
+	: "=&r" (old), "=m" (*p)
+	: "r" (mask), "r" (p), "m" (*p)
+	: "cc");
+}
+
+extern __inline__ int test_and_set_bit(int nr, volatile void *addr)
+{
+	unsigned int old, t;
+	unsigned int mask = 1 << (nr & 0x1f);
+	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+	__asm__ __volatile__(SMP_WMB "\
+1:	lwarx	%0,0,%4\n\
+	or	%1,%0,%3\n\
+	stwcx.	%1,0,%4\n\
+	bne	1b"
+	SMP_MB
+	: "=&r" (old), "=&r" (t), "=m" (*p)
+	: "r" (mask), "r" (p), "m" (*p)
+	: "cc");
+
+	return (old & mask) != 0;
+}
+
+extern __inline__ int test_and_clear_bit(int nr, volatile void *addr)
+{
+	unsigned int old, t;
+	unsigned int mask = 1 << (nr & 0x1f);
+	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+	__asm__ __volatile__(SMP_WMB "\
+1:	lwarx	%0,0,%4\n\
+	andc	%1,%0,%3\n\
+	stwcx.	%1,0,%4\n\
+	bne	1b"
+	SMP_MB
+	: "=&r" (old), "=&r" (t), "=m" (*p)
+	: "r" (mask), "r" (p), "m" (*p)
+	: "cc");
+
+	return (old & mask) != 0;
+}
+
+extern __inline__ int test_and_change_bit(int nr, volatile void *addr)
+{
+	unsigned int old, t;
+	unsigned int mask = 1 << (nr & 0x1f);
+	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+	__asm__ __volatile__(SMP_WMB "\
+1:	lwarx	%0,0,%4\n\
+	xor	%1,%0,%3\n\
+	stwcx.	%1,0,%4\n\
+	bne	1b"
+	SMP_MB
+	: "=&r" (old), "=&r" (t), "=m" (*p)
+	: "r" (mask), "r" (p), "m" (*p)
+	: "cc");
+
+	return (old & mask) != 0;
+}
+#endif /* __INLINE_BITOPS */
+
+extern __inline__ int test_bit(int nr, __const__ volatile void *addr)
+{
+	__const__ unsigned int *p = (__const__ unsigned int *) addr;
+
+	return ((p[nr >> 5] >> (nr & 0x1f)) & 1) != 0;
+}
+
+/* Return the bit position of the most significant 1 bit in a word */
+/* - the result is undefined when x == 0 */
+extern __inline__ int __ilog2(unsigned int x)
+{
+	int lz;
+
+	asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x));
+	return 31 - lz;
+}
+
+extern __inline__ int ffz(unsigned int x)
+{
+	if ((x = ~x) == 0)
+		return 32;
+	return __ilog2(x & -x);
+}
+
+/*
+ * fls: find last (most-significant) bit set.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ *
+ * On powerpc, __ilog2(0) returns -1, but this is not safe in general
+ */
+static __inline__ int fls(unsigned int x)
+{
+	return __ilog2(x) + 1;
+}
+#define PLATFORM_FLS
+
+/**
+ * fls64 - find last set bit in a 64-bit word
+ * @x: the word to search
+ *
+ * This is defined in a similar way as the libc and compiler builtin
+ * ffsll, but returns the position of the most significant set bit.
+ *
+ * fls64(value) returns 0 if value is 0 or the position of the last
+ * set bit if value is nonzero. The last (most significant) bit is
+ * at position 64.
+ */
+#if BITS_PER_LONG == 32
+static inline int fls64(__u64 x)
+{
+	__u32 h = x >> 32;
+	if (h)
+		return fls(h) + 32;
+	return fls(x);
+}
+#elif BITS_PER_LONG == 64
+static inline int fls64(__u64 x)
+{
+	if (x == 0)
+		return 0;
+	return __ilog2(x) + 1;
+}
+#else
+#error BITS_PER_LONG not 32 or 64
+#endif
+
+static inline int __ilog2_u64(u64 n)
+{
+	return fls64(n) - 1;
+}
+
+static inline int ffs64(u64 x)
+{
+	return __ilog2_u64(x & -x) + 1ull;
+}
+
+#ifdef __KERNEL__
+
+/*
+ * ffs: find first bit set. This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+extern __inline__ int ffs(int x)
+{
+	return __ilog2(x & -x) + 1;
+}
+#define PLATFORM_FFS
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+
+#define hweight32(x) generic_hweight32(x)
+#define hweight16(x) generic_hweight16(x)
+#define hweight8(x) generic_hweight8(x)
+
+#endif /* __KERNEL__ */
+
+/*
+ * This implementation of find_{first,next}_zero_bit was stolen from
+ * Linus' asm-alpha/bitops.h.
+ */
+#define find_first_zero_bit(addr, size) \
+	find_next_zero_bit((addr), (size), 0)
+
+extern __inline__ unsigned long find_next_zero_bit(void * addr,
+	unsigned long size, unsigned long offset)
+{
+	unsigned int * p = ((unsigned int *) addr) + (offset >> 5);
+	unsigned int result = offset & ~31UL;
+	unsigned int tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if (offset) {
+		tmp = *p++;
+		tmp |= ~0UL >> (32-offset);
+		if (size < 32)
+			goto found_first;
+		if (tmp != ~0U)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while (size >= 32) {
+		if ((tmp = *p++) != ~0U)
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if (!size)
+		return result;
+	tmp = *p;
+found_first:
+	tmp |= ~0UL << size;
+found_middle:
+	return result + ffz(tmp);
+}
+
+
+#define _EXT2_HAVE_ASM_BITOPS_
+
+#ifdef __KERNEL__
+/*
+ * test_and_{set,clear}_bit guarantee atomicity without
+ * disabling interrupts.
+ */
+#define ext2_set_bit(nr, addr)		test_and_set_bit((nr) ^ 0x18, addr)
+#define ext2_clear_bit(nr, addr)	test_and_clear_bit((nr) ^ 0x18, addr)
+
+#else
+extern __inline__ int ext2_set_bit(int nr, void * addr)
+{
+	int		mask;
+	unsigned char	*ADDR = (unsigned char *) addr;
+	int oldbit;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	oldbit = (*ADDR & mask) ? 1 : 0;
+	*ADDR |= mask;
+	return oldbit;
+}
+
+extern __inline__ int ext2_clear_bit(int nr, void * addr)
+{
+	int		mask;
+	unsigned char	*ADDR = (unsigned char *) addr;
+	int oldbit;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	oldbit = (*ADDR & mask) ? 1 : 0;
+	*ADDR = *ADDR & ~mask;
+	return oldbit;
+}
+#endif	/* __KERNEL__ */
+
+extern __inline__ int ext2_test_bit(int nr, __const__ void * addr)
+{
+	__const__ unsigned char	*ADDR = (__const__ unsigned char *) addr;
+
+	return (ADDR[nr >> 3] >> (nr & 7)) & 1;
+}
+
+/*
+ * This implementation of ext2_find_{first,next}_zero_bit was stolen from
+ * Linus' asm-alpha/bitops.h and modified for a big-endian machine.
+ */
+
+#define ext2_find_first_zero_bit(addr, size) \
+	ext2_find_next_zero_bit((addr), (size), 0)
+
+static __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
+	unsigned long size, unsigned long offset)
+{
+	unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
+	unsigned int result = offset & ~31UL;
+	unsigned int tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if (offset) {
+		tmp = cpu_to_le32p(p++);
+		tmp |= ~0UL >> (32-offset);
+		if (size < 32)
+			goto found_first;
+		if (tmp != ~0U)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while (size >= 32) {
+		if ((tmp = cpu_to_le32p(p++)) != ~0U)
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if (!size)
+		return result;
+	tmp = cpu_to_le32p(p);
+found_first:
+	tmp |= ~0U << size;
+found_middle:
+	return result + ffz(tmp);
+}
+
+/* Bitmap functions for the minix filesystem.  */
+#define minix_test_and_set_bit(nr,addr) ext2_set_bit(nr,addr)
+#define minix_set_bit(nr,addr) ((void)ext2_set_bit(nr,addr))
+#define minix_test_and_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) ext2_test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size)
+
+#endif /* _PPC_BITOPS_H */
diff --git a/arch/powerpc/include/asm/byteorder.h b/arch/powerpc/include/asm/byteorder.h
new file mode 100644
index 0000000..3f5bcf6
--- /dev/null
+++ b/arch/powerpc/include/asm/byteorder.h
@@ -0,0 +1,84 @@
+#ifndef _PPC_BYTEORDER_H
+#define _PPC_BYTEORDER_H
+
+#include <asm/types.h>
+
+#ifdef __GNUC__
+
+extern __inline__ unsigned ld_le16(const volatile unsigned short *addr)
+{
+	unsigned val;
+
+	__asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
+	return val;
+}
+
+extern __inline__ void st_le16(volatile unsigned short *addr, const unsigned val)
+{
+	__asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+extern __inline__ unsigned ld_le32(const volatile unsigned *addr)
+{
+	unsigned val;
+
+	__asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
+	return val;
+}
+
+extern __inline__ void st_le32(volatile unsigned *addr, const unsigned val)
+{
+	__asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+/* alas, egcs sounds like it has a bug in this code that doesn't use the
+   inline asm correctly, and can cause file corruption. Until I hear that
+   it's fixed, I can live without the extra speed. I hope. */
+#if !(__GNUC__ >= 2 && __GNUC_MINOR__ >= 90)
+#if 0
+#  define __arch_swab16(x) ld_le16(&x)
+#  define __arch_swab32(x) ld_le32(&x)
+#else
+static __inline__ __attribute__((const)) __u16 ___arch__swab16(__u16 value)
+{
+	__u16 result;
+
+	__asm__("rlwimi %0,%1,8,16,23"
+	    : "=r" (result)
+	    : "r" (value), "0" (value >> 8));
+	return result;
+}
+
+static __inline__ __attribute__((const)) __u32 ___arch__swab32(__u32 value)
+{
+	__u32 result;
+
+	__asm__("rlwimi %0,%1,24,16,23\n\t"
+	    "rlwimi %0,%1,8,8,15\n\t"
+	    "rlwimi %0,%1,24,0,7"
+	    : "=r" (result)
+	    : "r" (value), "0" (value >> 24));
+	return result;
+}
+#define __arch__swab32(x) ___arch__swab32(x)
+#define __arch__swab16(x) ___arch__swab16(x)
+#endif /* 0 */
+
+#endif
+
+/* The same, but returns converted value from the location pointer by addr. */
+#define __arch__swab16p(addr) ld_le16(addr)
+#define __arch__swab32p(addr) ld_le32(addr)
+
+/* The same, but do the conversion in situ, ie. put the value back to addr. */
+#define __arch__swab16s(addr) st_le16(addr,*addr)
+#define __arch__swab32s(addr) st_le32(addr,*addr)
+
+#endif /* __GNUC__ */
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+#define __BYTEORDER_HAS_U64__
+#endif
+#include <linux/byteorder/big_endian.h>
+
+#endif /* _PPC_BYTEORDER_H */
diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h
new file mode 100644
index 0000000..53e8d05
--- /dev/null
+++ b/arch/powerpc/include/asm/cache.h
@@ -0,0 +1,101 @@
+/*
+ * include/asm-ppc/cache.h
+ */
+#ifndef __ARCH_PPC_CACHE_H
+#define __ARCH_PPC_CACHE_H
+
+#include <linux/config.h>
+#include <asm/processor.h>
+
+/* bytes per L1 cache line */
+#if defined(CONFIG_8xx) || defined(CONFIG_IOP480)
+#define	L1_CACHE_SHIFT	4
+#elif defined(CONFIG_PPC64BRIDGE)
+#define L1_CACHE_SHIFT	7
+#elif defined(CONFIG_E500MC)
+#define L1_CACHE_SHIFT	6
+#else
+#define	L1_CACHE_SHIFT	5
+#endif
+
+#define L1_CACHE_BYTES          (1 << L1_CACHE_SHIFT)
+
+/*
+ * For compatibility reasons support the CONFIG_SYS_CACHELINE_SIZE too
+ */
+#ifndef CONFIG_SYS_CACHELINE_SIZE
+#define CONFIG_SYS_CACHELINE_SIZE	L1_CACHE_BYTES
+#endif
+
+#define	L1_CACHE_ALIGN(x)       (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
+#define	L1_CACHE_PAGES		8
+
+#define	SMP_CACHE_BYTES L1_CACHE_BYTES
+
+#ifdef MODULE
+#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES)))
+#else
+#define __cacheline_aligned					\
+  __attribute__((__aligned__(L1_CACHE_BYTES),			\
+		 __section__(".data.cacheline_aligned")))
+#endif
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+extern void flush_dcache_range(unsigned long start, unsigned long stop);
+extern void clean_dcache_range(unsigned long start, unsigned long stop);
+extern void invalidate_dcache_range(unsigned long start, unsigned long stop);
+extern void flush_dcache(void);
+extern void invalidate_dcache(void);
+extern void invalidate_icache(void);
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+extern void unlock_ram_in_cache(void);
+#endif /* CONFIG_SYS_INIT_RAM_LOCK */
+#endif /* __ASSEMBLY__ */
+
+/* prep registers for L2 */
+#define CACHECRBA       0x80000823      /* Cache configuration register address */
+#define L2CACHE_MASK	0x03	/* Mask for 2 L2 Cache bits */
+#define L2CACHE_512KB	0x00	/* 512KB */
+#define L2CACHE_256KB	0x01	/* 256KB */
+#define L2CACHE_1MB	0x02	/* 1MB */
+#define L2CACHE_NONE	0x03	/* NONE */
+#define L2CACHE_PARITY  0x08    /* Mask for L2 Cache Parity Protected bit */
+
+#ifdef CONFIG_8xx
+/* Cache control on the MPC8xx is provided through some additional
+ * special purpose registers.
+ */
+#define IC_CST		560	/* Instruction cache control/status */
+#define IC_ADR		561	/* Address needed for some commands */
+#define IC_DAT		562	/* Read-only data register */
+#define DC_CST		568	/* Data cache control/status */
+#define DC_ADR		569	/* Address needed for some commands */
+#define DC_DAT		570	/* Read-only data register */
+
+/* Commands.  Only the first few are available to the instruction cache.
+*/
+#define	IDC_ENABLE	0x02000000	/* Cache enable */
+#define IDC_DISABLE	0x04000000	/* Cache disable */
+#define IDC_LDLCK	0x06000000	/* Load and lock */
+#define IDC_UNLINE	0x08000000	/* Unlock line */
+#define IDC_UNALL	0x0a000000	/* Unlock all */
+#define IDC_INVALL	0x0c000000	/* Invalidate all */
+
+#define DC_FLINE	0x0e000000	/* Flush data cache line */
+#define DC_SFWT		0x01000000	/* Set forced writethrough mode */
+#define DC_CFWT		0x03000000	/* Clear forced writethrough mode */
+#define DC_SLES		0x05000000	/* Set little endian swap mode */
+#define DC_CLES		0x07000000	/* Clear little endian swap mode */
+
+/* Status.
+*/
+#define IDC_ENABLED	0x80000000	/* Cache is enabled */
+#define IDC_CERR1	0x00200000	/* Cache error 1 */
+#define IDC_CERR2	0x00100000	/* Cache error 2 */
+#define IDC_CERR3	0x00080000	/* Cache error 3 */
+
+#define DC_DFWT		0x40000000	/* Data cache is forced write through */
+#define DC_LES		0x20000000	/* Caches are little endian mode */
+#endif /* CONFIG_8xx */
+
+#endif
diff --git a/arch/powerpc/include/asm/config.h b/arch/powerpc/include/asm/config.h
new file mode 100644
index 0000000..fc3facb
--- /dev/null
+++ b/arch/powerpc/include/asm/config.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2009-2010 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef _ASM_CONFIG_H_
+#define _ASM_CONFIG_H_
+
+#define CONFIG_LMB
+
+#ifndef CONFIG_MAX_MEM_MAPPED
+#if defined(CONFIG_4xx) || defined(CONFIG_E500) || defined(CONFIG_MPC86xx)
+#define CONFIG_MAX_MEM_MAPPED	((phys_size_t)2 << 30)
+#else
+#define CONFIG_MAX_MEM_MAPPED	(256 << 20)
+#endif
+#endif
+
+/* Check if boards need to enable FSL DMA engine for SDRAM init */
+#if !defined(CONFIG_FSL_DMA) && defined(CONFIG_DDR_ECC)
+#if (defined(CONFIG_MPC83xx) && defined(CONFIG_DDR_ECC_INIT_VIA_DMA)) || \
+	((defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)) && \
+	!defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER))
+#define CONFIG_FSL_DMA
+#endif
+#endif
+
+#if defined(CONFIG_MPC8572) || defined(CONFIG_P1020) || \
+	defined(CONFIG_P1021) || defined(CONFIG_P1022) || \
+	defined(CONFIG_P2020) || defined(CONFIG_MPC8641)
+#define CONFIG_MAX_CPUS		2
+#elif defined(CONFIG_PPC_P4080)
+#define CONFIG_MAX_CPUS		8
+#else
+#define CONFIG_MAX_CPUS		1
+#endif
+
+/*
+ * Provide a default boot page translation virtual address that lines up with
+ * Freescale's default e500 reset page.
+ */
+#if (defined(CONFIG_E500) && defined(CONFIG_MP))
+#ifndef CONFIG_BPTR_VIRT_ADDR
+#define CONFIG_BPTR_VIRT_ADDR	0xfffff000
+#endif
+#endif
+
+/* Enable TSEC2.0 for the platforms that have it if we are using TSEC */
+#if defined(CONFIG_TSEC_ENET) && \
+    (defined(CONFIG_P1020) || defined(CONFIG_P1011))
+#define CONFIG_TSECV2
+#endif
+
+/* Number of TLB CAM entries we have on FSL Book-E chips */
+#if defined(CONFIG_E500MC)
+#define CONFIG_SYS_NUM_TLBCAMS	64
+#elif defined(CONFIG_E500)
+#define CONFIG_SYS_NUM_TLBCAMS	16
+#endif
+
+/* Relocation to SDRAM works on all PPC boards */
+#define CONFIG_RELOC_FIXUP_WORKS
+
+#endif /* _ASM_CONFIG_H_ */
diff --git a/arch/powerpc/include/asm/cpm_8260.h b/arch/powerpc/include/asm/cpm_8260.h
new file mode 100644
index 0000000..8302404
--- /dev/null
+++ b/arch/powerpc/include/asm/cpm_8260.h
@@ -0,0 +1,796 @@
+
+/*
+ * MPC8260 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ *
+ * This file contains structures and information for the communication
+ * processor channels found in the dual port RAM or parameter RAM.
+ * All CPM control and status is available through the MPC8260 internal
+ * memory map.  See immap.h for details.
+ */
+#ifndef __CPM_82XX__
+#define __CPM_82XX__
+
+#include <asm/immap_8260.h>
+
+/* CPM Command register.
+*/
+#define CPM_CR_RST	((uint)0x80000000)
+#define CPM_CR_PAGE	((uint)0x7c000000)
+#define CPM_CR_SBLOCK	((uint)0x03e00000)
+#define CPM_CR_FLG	((uint)0x00010000)
+#define CPM_CR_MCN	((uint)0x00003fc0)
+#define CPM_CR_OPCODE	((uint)0x0000000f)
+
+/* Device sub-block and page codes.
+*/
+#define CPM_CR_SCC1_SBLOCK	(0x04)
+#define CPM_CR_SCC2_SBLOCK	(0x05)
+#define CPM_CR_SCC3_SBLOCK	(0x06)
+#define CPM_CR_SCC4_SBLOCK	(0x07)
+#define CPM_CR_SMC1_SBLOCK	(0x08)
+#define CPM_CR_SMC2_SBLOCK	(0x09)
+#define CPM_CR_SPI_SBLOCK	(0x0a)
+#define CPM_CR_I2C_SBLOCK	(0x0b)
+#define CPM_CR_TIMER_SBLOCK	(0x0f)
+#define CPM_CR_RAND_SBLOCK	(0x0e)
+#define CPM_CR_FCC1_SBLOCK	(0x10)
+#define CPM_CR_FCC2_SBLOCK	(0x11)
+#define CPM_CR_FCC3_SBLOCK	(0x12)
+#define CPM_CR_IDMA1_SBLOCK	(0x14)
+#define CPM_CR_IDMA2_SBLOCK	(0x15)
+#define CPM_CR_IDMA3_SBLOCK	(0x16)
+#define CPM_CR_IDMA4_SBLOCK	(0x17)
+#define CPM_CR_MCC1_SBLOCK	(0x1c)
+
+#define CPM_CR_SCC1_PAGE	(0x00)
+#define CPM_CR_SCC2_PAGE	(0x01)
+#define CPM_CR_SCC3_PAGE	(0x02)
+#define CPM_CR_SCC4_PAGE	(0x03)
+#define CPM_CR_SMC1_PAGE	(0x07)
+#define CPM_CR_SMC2_PAGE	(0x08)
+#define CPM_CR_SPI_PAGE		(0x09)
+#define CPM_CR_I2C_PAGE		(0x0a)
+#define CPM_CR_TIMER_PAGE	(0x0a)
+#define CPM_CR_RAND_PAGE	(0x0a)
+#define CPM_CR_FCC1_PAGE	(0x04)
+#define CPM_CR_FCC2_PAGE	(0x05)
+#define CPM_CR_FCC3_PAGE	(0x06)
+#define CPM_CR_IDMA1_PAGE	(0x07)
+#define CPM_CR_IDMA2_PAGE	(0x08)
+#define CPM_CR_IDMA3_PAGE	(0x09)
+#define CPM_CR_IDMA4_PAGE	(0x0a)
+#define CPM_CR_MCC1_PAGE	(0x07)
+#define CPM_CR_MCC2_PAGE	(0x08)
+
+/* Some opcodes (there are more...later)
+*/
+#define CPM_CR_INIT_TRX		((ushort)0x0000)
+#define CPM_CR_INIT_RX		((ushort)0x0001)
+#define CPM_CR_INIT_TX		((ushort)0x0002)
+#define CPM_CR_HUNT_MODE	((ushort)0x0003)
+#define CPM_CR_STOP_TX		((ushort)0x0004)
+#define CPM_CR_RESTART_TX	((ushort)0x0006)
+#define CPM_CR_SET_GADDR	((ushort)0x0008)
+
+#define mk_cr_cmd(PG, SBC, MCN, OP) \
+	((PG << 26) | (SBC << 21) | (MCN << 6) | OP)
+
+/* Dual Port RAM addresses.  The first 16K is available for almost
+ * any CPM use, so we put the BDs there.  The first 128 bytes are
+ * used for SMC1 and SMC2 parameter RAM, so we start allocating
+ * BDs above that.  All of this must change when we start
+ * downloading RAM microcode.
+ */
+#define CPM_DATAONLY_BASE	((uint)128)
+#define CPM_DP_NOSPACE		((uint)0x7fffffff)
+#ifndef CONFIG_MPC8272_FAMILY
+#define CPM_DATAONLY_SIZE	((uint)(8 * 1024) - CPM_DATAONLY_BASE)
+#define CPM_FCC_SPECIAL_BASE	((uint)0x0000b000)
+#else  /* 8247/48/71/72 */
+#define CPM_DATAONLY_SIZE	((uint)(4 * 1024) - CPM_DATAONLY_BASE)
+#define CPM_FCC_SPECIAL_BASE	((uint)0x00009000)
+#endif /* !CONFIG_MPC8272_FAMILY */
+
+/* The number of pages of host memory we allocate for CPM.  This is
+ * done early in kernel initialization to get physically contiguous
+ * pages.
+ */
+#define NUM_CPM_HOST_PAGES	2
+
+
+/* Export the base address of the communication processor registers
+ * and dual port ram.
+ */
+extern	cpm8260_t	*cpmp;		/* Pointer to comm processor */
+uint		m8260_cpm_dpalloc(uint size, uint align);
+uint		m8260_cpm_hostalloc(uint size, uint align);
+void		m8260_cpm_setbrg(uint brg, uint rate);
+void		m8260_cpm_fastbrg(uint brg, uint rate, int div16);
+void		m8260_cpm_extcbrg(uint brg, uint rate, uint extclk, int pinsel);
+
+/* Buffer descriptors used by many of the CPM protocols.
+*/
+typedef struct cpm_buf_desc {
+	ushort	cbd_sc;		/* Status and Control */
+	ushort	cbd_datlen;	/* Data length in buffer */
+	uint	cbd_bufaddr;	/* Buffer address in host memory */
+} cbd_t;
+
+#define BD_SC_EMPTY	((ushort)0x8000)	/* Recieve is empty */
+#define BD_SC_READY	((ushort)0x8000)	/* Transmit is ready */
+#define BD_SC_WRAP	((ushort)0x2000)	/* Last buffer descriptor */
+#define BD_SC_INTRPT	((ushort)0x1000)	/* Interrupt on change */
+#define BD_SC_LAST	((ushort)0x0800)	/* Last buffer in frame */
+#define BD_SC_CM	((ushort)0x0200)	/* Continous mode */
+#define BD_SC_ID	((ushort)0x0100)	/* Rec'd too many idles */
+#define BD_SC_P		((ushort)0x0100)	/* xmt preamble */
+#define BD_SC_BR	((ushort)0x0020)	/* Break received */
+#define BD_SC_FR	((ushort)0x0010)	/* Framing error */
+#define BD_SC_PR	((ushort)0x0008)	/* Parity error */
+#define BD_SC_OV	((ushort)0x0002)	/* Overrun */
+#define BD_SC_CD	((ushort)0x0001)	/* ?? */
+
+/* Function code bits, usually generic to devices.
+*/
+#define CPMFCR_GBL	((u_char)0x20)	/* Set memory snooping */
+#define CPMFCR_EB	((u_char)0x10)	/* Set big endian byte order */
+#define CPMFCR_TC2	((u_char)0x04)	/* Transfer code 2 value */
+#define CPMFCR_DTB	((u_char)0x02)	/* Use local bus for data when set */
+#define CPMFCR_BDB	((u_char)0x01)	/* Use local bus for BD when set */
+
+/* Parameter RAM offsets from the base.
+*/
+#ifndef CONFIG_SYS_CPM_POST_WORD_ADDR
+#define CPM_POST_WORD_ADDR      0x80FC	/* steal a long at the end of SCC1 */
+#else
+#define CPM_POST_WORD_ADDR	CONFIG_SYS_CPM_POST_WORD_ADDR
+#endif
+
+#ifndef CONFIG_SYS_CPM_BOOTCOUNT_ADDR
+#define CPM_BOOTCOUNT_ADDR	(CPM_POST_WORD_ADDR - 2*sizeof(ulong))
+#else
+#define CPM_BOOTCOUNT_ADDR	CONFIG_SYS_CPM_BOOTCOUNT_ADDR
+#endif
+
+#define PROFF_SCC1		((uint)0x8000)
+#define PROFF_SCC2		((uint)0x8100)
+#define PROFF_SCC3		((uint)0x8200)
+#define PROFF_SCC4		((uint)0x8300)
+#define PROFF_FCC1		((uint)0x8400)
+#define PROFF_FCC2		((uint)0x8500)
+#define PROFF_FCC3		((uint)0x8600)
+#define PROFF_MCC1		((uint)0x8700)
+#define PROFF_SMC1_BASE		((uint)0x87fc)
+#define PROFF_IDMA1_BASE	((uint)0x87fe)
+#define PROFF_MCC2		((uint)0x8800)
+#define PROFF_SMC2_BASE		((uint)0x88fc)
+#define PROFF_IDMA2_BASE	((uint)0x88fe)
+#define PROFF_SPI_BASE		((uint)0x89fc)
+#define PROFF_IDMA3_BASE	((uint)0x89fe)
+#define PROFF_TIMERS		((uint)0x8ae0)
+#define PROFF_REVNUM		((uint)0x8af0)
+#define PROFF_RAND		((uint)0x8af8)
+#define PROFF_I2C_BASE		((uint)0x8afc)
+#define PROFF_IDMA4_BASE	((uint)0x8afe)
+
+/* The SMCs are relocated to any of the first eight DPRAM pages.
+ * We will fix these at the first locations of DPRAM, until we
+ * get some microcode patches :-).
+ * The parameter ram space for the SMCs is fifty-some bytes, and
+ * they are required to start on a 64 byte boundary.
+ */
+#define PROFF_SMC1	(0)
+#define PROFF_SMC2	(64)
+#define PROFF_SPI	((16*1024) - 128)
+
+/* Define enough so I can at least use the serial port as a UART.
+ */
+typedef struct smc_uart {
+	ushort	smc_rbase;	/* Rx Buffer descriptor base address */
+	ushort	smc_tbase;	/* Tx Buffer descriptor base address */
+	u_char	smc_rfcr;	/* Rx function code */
+	u_char	smc_tfcr;	/* Tx function code */
+	ushort	smc_mrblr;	/* Max receive buffer length */
+	uint	smc_rstate;	/* Internal */
+	uint	smc_idp;	/* Internal */
+	ushort	smc_rbptr;	/* Internal */
+	ushort	smc_ibc;	/* Internal */
+	uint	smc_rxtmp;	/* Internal */
+	uint	smc_tstate;	/* Internal */
+	uint	smc_tdp;	/* Internal */
+	ushort	smc_tbptr;	/* Internal */
+	ushort	smc_tbc;	/* Internal */
+	uint	smc_txtmp;	/* Internal */
+	ushort	smc_maxidl;	/* Maximum idle characters */
+	ushort	smc_tmpidl;	/* Temporary idle counter */
+	ushort	smc_brklen;	/* Last received break length */
+	ushort	smc_brkec;	/* rcv'd break condition counter */
+	ushort	smc_brkcr;	/* xmt break count register */
+	ushort	smc_rmask;	/* Temporary bit mask */
+	uint	smc_stmp;	/* SDMA Temp */
+} smc_uart_t;
+
+/* SMC uart mode register (Internal memory map).
+*/
+#define	SMCMR_REN	((ushort)0x0001)
+#define SMCMR_TEN	((ushort)0x0002)
+#define SMCMR_DM	((ushort)0x000c)
+#define SMCMR_SM_GCI	((ushort)0x0000)
+#define SMCMR_SM_UART	((ushort)0x0020)
+#define SMCMR_SM_TRANS	((ushort)0x0030)
+#define SMCMR_SM_MASK	((ushort)0x0030)
+#define SMCMR_PM_EVEN	((ushort)0x0100)	/* Even parity, else odd */
+#define SMCMR_REVD	SMCMR_PM_EVEN
+#define SMCMR_PEN	((ushort)0x0200)	/* Parity enable */
+#define SMCMR_BS	SMCMR_PEN
+#define SMCMR_SL	((ushort)0x0400)	/* Two stops, else one */
+#define SMCR_CLEN_MASK	((ushort)0x7800)	/* Character length */
+#define smcr_mk_clen(C)	(((C) << 11) & SMCR_CLEN_MASK)
+
+/* SMC Event and Mask register.
+*/
+#define	SMCM_TXE	((unsigned char)0x10)
+#define	SMCM_BSY	((unsigned char)0x04)
+#define	SMCM_TX		((unsigned char)0x02)
+#define	SMCM_RX		((unsigned char)0x01)
+
+/* Baud rate generators.
+*/
+#define CPM_BRG_RST		((uint)0x00020000)
+#define CPM_BRG_EN		((uint)0x00010000)
+#define CPM_BRG_EXTC_INT	((uint)0x00000000)
+#define CPM_BRG_EXTC_CLK3_9	((uint)0x00004000)
+#define CPM_BRG_EXTC_CLK5_15	((uint)0x00008000)
+#define CPM_BRG_ATB		((uint)0x00002000)
+#define CPM_BRG_CD_MASK		((uint)0x00001ffe)
+#define CPM_BRG_DIV16		((uint)0x00000001)
+
+/* SCCs.
+*/
+#define SCC_GSMRH_IRP		((uint)0x00040000)
+#define SCC_GSMRH_GDE		((uint)0x00010000)
+#define SCC_GSMRH_TCRC_CCITT	((uint)0x00008000)
+#define SCC_GSMRH_TCRC_BISYNC	((uint)0x00004000)
+#define SCC_GSMRH_TCRC_HDLC	((uint)0x00000000)
+#define SCC_GSMRH_REVD		((uint)0x00002000)
+#define SCC_GSMRH_TRX		((uint)0x00001000)
+#define SCC_GSMRH_TTX		((uint)0x00000800)
+#define SCC_GSMRH_CDP		((uint)0x00000400)
+#define SCC_GSMRH_CTSP		((uint)0x00000200)
+#define SCC_GSMRH_CDS		((uint)0x00000100)
+#define SCC_GSMRH_CTSS		((uint)0x00000080)
+#define SCC_GSMRH_TFL		((uint)0x00000040)
+#define SCC_GSMRH_RFW		((uint)0x00000020)
+#define SCC_GSMRH_TXSY		((uint)0x00000010)
+#define SCC_GSMRH_SYNL16	((uint)0x0000000c)
+#define SCC_GSMRH_SYNL8		((uint)0x00000008)
+#define SCC_GSMRH_SYNL4		((uint)0x00000004)
+#define SCC_GSMRH_RTSM		((uint)0x00000002)
+#define SCC_GSMRH_RSYN		((uint)0x00000001)
+
+#define SCC_GSMRL_SIR		((uint)0x80000000)	/* SCC2 only */
+#define SCC_GSMRL_EDGE_NONE	((uint)0x60000000)
+#define SCC_GSMRL_EDGE_NEG	((uint)0x40000000)
+#define SCC_GSMRL_EDGE_POS	((uint)0x20000000)
+#define SCC_GSMRL_EDGE_BOTH	((uint)0x00000000)
+#define SCC_GSMRL_TCI		((uint)0x10000000)
+#define SCC_GSMRL_TSNC_3	((uint)0x0c000000)
+#define SCC_GSMRL_TSNC_4	((uint)0x08000000)
+#define SCC_GSMRL_TSNC_14	((uint)0x04000000)
+#define SCC_GSMRL_TSNC_INF	((uint)0x00000000)
+#define SCC_GSMRL_RINV		((uint)0x02000000)
+#define SCC_GSMRL_TINV		((uint)0x01000000)
+#define SCC_GSMRL_TPL_128	((uint)0x00c00000)
+#define SCC_GSMRL_TPL_64	((uint)0x00a00000)
+#define SCC_GSMRL_TPL_48	((uint)0x00800000)
+#define SCC_GSMRL_TPL_32	((uint)0x00600000)
+#define SCC_GSMRL_TPL_16	((uint)0x00400000)
+#define SCC_GSMRL_TPL_8		((uint)0x00200000)
+#define SCC_GSMRL_TPL_NONE	((uint)0x00000000)
+#define SCC_GSMRL_TPP_ALL1	((uint)0x00180000)
+#define SCC_GSMRL_TPP_01	((uint)0x00100000)
+#define SCC_GSMRL_TPP_10	((uint)0x00080000)
+#define SCC_GSMRL_TPP_ZEROS	((uint)0x00000000)
+#define SCC_GSMRL_TEND		((uint)0x00040000)
+#define SCC_GSMRL_TDCR_32	((uint)0x00030000)
+#define SCC_GSMRL_TDCR_16	((uint)0x00020000)
+#define SCC_GSMRL_TDCR_8	((uint)0x00010000)
+#define SCC_GSMRL_TDCR_1	((uint)0x00000000)
+#define SCC_GSMRL_RDCR_32	((uint)0x0000c000)
+#define SCC_GSMRL_RDCR_16	((uint)0x00008000)
+#define SCC_GSMRL_RDCR_8	((uint)0x00004000)
+#define SCC_GSMRL_RDCR_1	((uint)0x00000000)
+#define SCC_GSMRL_RENC_DFMAN	((uint)0x00003000)
+#define SCC_GSMRL_RENC_MANCH	((uint)0x00002000)
+#define SCC_GSMRL_RENC_FM0	((uint)0x00001000)
+#define SCC_GSMRL_RENC_NRZI	((uint)0x00000800)
+#define SCC_GSMRL_RENC_NRZ	((uint)0x00000000)
+#define SCC_GSMRL_TENC_DFMAN	((uint)0x00000600)
+#define SCC_GSMRL_TENC_MANCH	((uint)0x00000400)
+#define SCC_GSMRL_TENC_FM0	((uint)0x00000200)
+#define SCC_GSMRL_TENC_NRZI	((uint)0x00000100)
+#define SCC_GSMRL_TENC_NRZ	((uint)0x00000000)
+#define SCC_GSMRL_DIAG_LE	((uint)0x000000c0)	/* Loop and echo */
+#define SCC_GSMRL_DIAG_ECHO	((uint)0x00000080)
+#define SCC_GSMRL_DIAG_LOOP	((uint)0x00000040)
+#define SCC_GSMRL_DIAG_NORM	((uint)0x00000000)
+#define SCC_GSMRL_ENR		((uint)0x00000020)
+#define SCC_GSMRL_ENT		((uint)0x00000010)
+#define SCC_GSMRL_MODE_ENET	((uint)0x0000000c)
+#define SCC_GSMRL_MODE_DDCMP	((uint)0x00000009)
+#define SCC_GSMRL_MODE_BISYNC	((uint)0x00000008)
+#define SCC_GSMRL_MODE_V14	((uint)0x00000007)
+#define SCC_GSMRL_MODE_AHDLC	((uint)0x00000006)
+#define SCC_GSMRL_MODE_PROFIBUS	((uint)0x00000005)
+#define SCC_GSMRL_MODE_UART	((uint)0x00000004)
+#define SCC_GSMRL_MODE_SS7	((uint)0x00000003)
+#define SCC_GSMRL_MODE_ATALK	((uint)0x00000002)
+#define SCC_GSMRL_MODE_HDLC	((uint)0x00000000)
+
+#define SCC_TODR_TOD		((ushort)0x8000)
+
+/* SCC Event and Mask register.
+*/
+#define	SCCM_TXE	((unsigned char)0x10)
+#define	SCCM_BSY	((unsigned char)0x04)
+#define	SCCM_TX		((unsigned char)0x02)
+#define	SCCM_RX		((unsigned char)0x01)
+
+typedef struct scc_param {
+	ushort	scc_rbase;	/* Rx Buffer descriptor base address */
+	ushort	scc_tbase;	/* Tx Buffer descriptor base address */
+	u_char	scc_rfcr;	/* Rx function code */
+	u_char	scc_tfcr;	/* Tx function code */
+	ushort	scc_mrblr;	/* Max receive buffer length */
+	uint	scc_rstate;	/* Internal */
+	uint	scc_idp;	/* Internal */
+	ushort	scc_rbptr;	/* Internal */
+	ushort	scc_ibc;	/* Internal */
+	uint	scc_rxtmp;	/* Internal */
+	uint	scc_tstate;	/* Internal */
+	uint	scc_tdp;	/* Internal */
+	ushort	scc_tbptr;	/* Internal */
+	ushort	scc_tbc;	/* Internal */
+	uint	scc_txtmp;	/* Internal */
+	uint	scc_rcrc;	/* Internal */
+	uint	scc_tcrc;	/* Internal */
+} sccp_t;
+
+/* CPM Ethernet through SCC1.
+ */
+typedef struct scc_enet {
+	sccp_t	sen_genscc;
+	uint	sen_cpres;	/* Preset CRC */
+	uint	sen_cmask;	/* Constant mask for CRC */
+	uint	sen_crcec;	/* CRC Error counter */
+	uint	sen_alec;	/* alignment error counter */
+	uint	sen_disfc;	/* discard frame counter */
+	ushort	sen_pads;	/* Tx short frame pad character */
+	ushort	sen_retlim;	/* Retry limit threshold */
+	ushort	sen_retcnt;	/* Retry limit counter */
+	ushort	sen_maxflr;	/* maximum frame length register */
+	ushort	sen_minflr;	/* minimum frame length register */
+	ushort	sen_maxd1;	/* maximum DMA1 length */
+	ushort	sen_maxd2;	/* maximum DMA2 length */
+	ushort	sen_maxd;	/* Rx max DMA */
+	ushort	sen_dmacnt;	/* Rx DMA counter */
+	ushort	sen_maxb;	/* Max BD byte count */
+	ushort	sen_gaddr1;	/* Group address filter */
+	ushort	sen_gaddr2;
+	ushort	sen_gaddr3;
+	ushort	sen_gaddr4;
+	uint	sen_tbuf0data0;	/* Save area 0 - current frame */
+	uint	sen_tbuf0data1;	/* Save area 1 - current frame */
+	uint	sen_tbuf0rba;	/* Internal */
+	uint	sen_tbuf0crc;	/* Internal */
+	ushort	sen_tbuf0bcnt;	/* Internal */
+	ushort	sen_paddrh;	/* physical address (MSB) */
+	ushort	sen_paddrm;
+	ushort	sen_paddrl;	/* physical address (LSB) */
+	ushort	sen_pper;	/* persistence */
+	ushort	sen_rfbdptr;	/* Rx first BD pointer */
+	ushort	sen_tfbdptr;	/* Tx first BD pointer */
+	ushort	sen_tlbdptr;	/* Tx last BD pointer */
+	uint	sen_tbuf1data0;	/* Save area 0 - current frame */
+	uint	sen_tbuf1data1;	/* Save area 1 - current frame */
+	uint	sen_tbuf1rba;	/* Internal */
+	uint	sen_tbuf1crc;	/* Internal */
+	ushort	sen_tbuf1bcnt;	/* Internal */
+	ushort	sen_txlen;	/* Tx Frame length counter */
+	ushort	sen_iaddr1;	/* Individual address filter */
+	ushort	sen_iaddr2;
+	ushort	sen_iaddr3;
+	ushort	sen_iaddr4;
+	ushort	sen_boffcnt;	/* Backoff counter */
+
+	/* NOTE: Some versions of the manual have the following items
+	 * incorrectly documented.  Below is the proper order.
+	 */
+	ushort	sen_taddrh;	/* temp address (MSB) */
+	ushort	sen_taddrm;
+	ushort	sen_taddrl;	/* temp address (LSB) */
+} scc_enet_t;
+
+
+/* SCC Event register as used by Ethernet.
+*/
+#define SCCE_ENET_GRA	((ushort)0x0080)	/* Graceful stop complete */
+#define SCCE_ENET_TXE	((ushort)0x0010)	/* Transmit Error */
+#define SCCE_ENET_RXF	((ushort)0x0008)	/* Full frame received */
+#define SCCE_ENET_BSY	((ushort)0x0004)	/* All incoming buffers full */
+#define SCCE_ENET_TXB	((ushort)0x0002)	/* A buffer was transmitted */
+#define SCCE_ENET_RXB	((ushort)0x0001)	/* A buffer was received */
+
+/* SCC Mode Register (PSMR) as used by Ethernet.
+*/
+#define SCC_PSMR_HBC	((ushort)0x8000)	/* Enable heartbeat */
+#define SCC_PSMR_FC	((ushort)0x4000)	/* Force collision */
+#define SCC_PSMR_RSH	((ushort)0x2000)	/* Receive short frames */
+#define SCC_PSMR_IAM	((ushort)0x1000)	/* Check individual hash */
+#define SCC_PSMR_ENCRC	((ushort)0x0800)	/* Ethernet CRC mode */
+#define SCC_PSMR_PRO	((ushort)0x0200)	/* Promiscuous mode */
+#define SCC_PSMR_BRO	((ushort)0x0100)	/* Catch broadcast pkts */
+#define SCC_PSMR_SBT	((ushort)0x0080)	/* Special backoff timer */
+#define SCC_PSMR_LPB	((ushort)0x0040)	/* Set Loopback mode */
+#define SCC_PSMR_SIP	((ushort)0x0020)	/* Sample Input Pins */
+#define SCC_PSMR_LCW	((ushort)0x0010)	/* Late collision window */
+#define SCC_PSMR_NIB22	((ushort)0x000a)	/* Start frame search */
+#define SCC_PSMR_FDE	((ushort)0x0001)	/* Full duplex enable */
+
+/* Buffer descriptor control/status used by Ethernet receive.
+ * Common to SCC and FCC.
+ */
+#define BD_ENET_RX_EMPTY	((ushort)0x8000)
+#define BD_ENET_RX_WRAP		((ushort)0x2000)
+#define BD_ENET_RX_INTR		((ushort)0x1000)
+#define BD_ENET_RX_LAST		((ushort)0x0800)
+#define BD_ENET_RX_FIRST	((ushort)0x0400)
+#define BD_ENET_RX_MISS		((ushort)0x0100)
+#define BD_ENET_RX_BC		((ushort)0x0080)	/* FCC Only */
+#define BD_ENET_RX_MC		((ushort)0x0040)	/* FCC Only */
+#define BD_ENET_RX_LG		((ushort)0x0020)
+#define BD_ENET_RX_NO		((ushort)0x0010)
+#define BD_ENET_RX_SH		((ushort)0x0008)
+#define BD_ENET_RX_CR		((ushort)0x0004)
+#define BD_ENET_RX_OV		((ushort)0x0002)
+#define BD_ENET_RX_CL		((ushort)0x0001)
+#define BD_ENET_RX_STATS	((ushort)0x01ff)	/* All status bits */
+
+/* Buffer descriptor control/status used by Ethernet transmit.
+ * Common to SCC and FCC.
+ */
+#define BD_ENET_TX_READY	((ushort)0x8000)
+#define BD_ENET_TX_PAD		((ushort)0x4000)
+#define BD_ENET_TX_WRAP		((ushort)0x2000)
+#define BD_ENET_TX_INTR		((ushort)0x1000)
+#define BD_ENET_TX_LAST		((ushort)0x0800)
+#define BD_ENET_TX_TC		((ushort)0x0400)
+#define BD_ENET_TX_DEF		((ushort)0x0200)
+#define BD_ENET_TX_HB		((ushort)0x0100)
+#define BD_ENET_TX_LC		((ushort)0x0080)
+#define BD_ENET_TX_RL		((ushort)0x0040)
+#define BD_ENET_TX_RCMASK	((ushort)0x003c)
+#define BD_ENET_TX_UN		((ushort)0x0002)
+#define BD_ENET_TX_CSL		((ushort)0x0001)
+#define BD_ENET_TX_STATS	((ushort)0x03ff)	/* All status bits */
+
+/* SCC as UART
+*/
+typedef struct scc_uart {
+	sccp_t	scc_genscc;
+	uint	scc_res1;	/* Reserved */
+	uint	scc_res2;	/* Reserved */
+	ushort	scc_maxidl;	/* Maximum idle chars */
+	ushort	scc_idlc;	/* temp idle counter */
+	ushort	scc_brkcr;	/* Break count register */
+	ushort	scc_parec;	/* receive parity error counter */
+	ushort	scc_frmec;	/* receive framing error counter */
+	ushort	scc_nosec;	/* receive noise counter */
+	ushort	scc_brkec;	/* receive break condition counter */
+	ushort	scc_brkln;	/* last received break length */
+	ushort	scc_uaddr1;	/* UART address character 1 */
+	ushort	scc_uaddr2;	/* UART address character 2 */
+	ushort	scc_rtemp;	/* Temp storage */
+	ushort	scc_toseq;	/* Transmit out of sequence char */
+	ushort	scc_char1;	/* control character 1 */
+	ushort	scc_char2;	/* control character 2 */
+	ushort	scc_char3;	/* control character 3 */
+	ushort	scc_char4;	/* control character 4 */
+	ushort	scc_char5;	/* control character 5 */
+	ushort	scc_char6;	/* control character 6 */
+	ushort	scc_char7;	/* control character 7 */
+	ushort	scc_char8;	/* control character 8 */
+	ushort	scc_rccm;	/* receive control character mask */
+	ushort	scc_rccr;	/* receive control character register */
+	ushort	scc_rlbc;	/* receive last break character */
+} scc_uart_t;
+
+/* SCC Event and Mask registers when it is used as a UART.
+*/
+#define UART_SCCM_GLR		((ushort)0x1000)
+#define UART_SCCM_GLT		((ushort)0x0800)
+#define UART_SCCM_AB		((ushort)0x0200)
+#define UART_SCCM_IDL		((ushort)0x0100)
+#define UART_SCCM_GRA		((ushort)0x0080)
+#define UART_SCCM_BRKE		((ushort)0x0040)
+#define UART_SCCM_BRKS		((ushort)0x0020)
+#define UART_SCCM_CCR		((ushort)0x0008)
+#define UART_SCCM_BSY		((ushort)0x0004)
+#define UART_SCCM_TX		((ushort)0x0002)
+#define UART_SCCM_RX		((ushort)0x0001)
+
+/* The SCC PSMR when used as a UART.
+*/
+#define SCU_PSMR_FLC		((ushort)0x8000)
+#define SCU_PSMR_SL		((ushort)0x4000)
+#define SCU_PSMR_CL		((ushort)0x3000)
+#define SCU_PSMR_UM		((ushort)0x0c00)
+#define SCU_PSMR_FRZ		((ushort)0x0200)
+#define SCU_PSMR_RZS		((ushort)0x0100)
+#define SCU_PSMR_SYN		((ushort)0x0080)
+#define SCU_PSMR_DRT		((ushort)0x0040)
+#define SCU_PSMR_PEN		((ushort)0x0010)
+#define SCU_PSMR_RPM		((ushort)0x000c)
+#define SCU_PSMR_REVP		((ushort)0x0008)
+#define SCU_PSMR_TPM		((ushort)0x0003)
+#define SCU_PSMR_TEVP		((ushort)0x0003)
+
+/* CPM Transparent mode SCC.
+ */
+typedef struct scc_trans {
+	sccp_t	st_genscc;
+	uint	st_cpres;	/* Preset CRC */
+	uint	st_cmask;	/* Constant mask for CRC */
+} scc_trans_t;
+
+#define BD_SCC_TX_LAST		((ushort)0x0800)
+
+/*  SCC as HDLC controller - taken from commproc.h
+ */
+typedef struct scc_hdlc {
+	sccp_t  sh_genscc;
+	/*
+	* HDLC specific parameter RAM
+	*/
+	uchar   res[4];         /* reserved */
+	ulong   sh_cmask;       /* CRC constant */
+	ulong   sh_cpres;       /* CRC preset */
+	ushort  sh_disfc;       /* discarded frame counter */
+	ushort  sh_crcec;       /* CRC error counter */
+	ushort  sh_abtsc;       /* abort sequence counter */
+	ushort  sh_nmarc;       /* nonmatching address rx cnt */
+	ushort  sh_retrc;       /* frame retransmission cnt */
+	ushort  sh_mflr;        /* maximum frame length reg */
+	ushort  sh_maxcnt;      /* maximum length counter */
+	ushort  sh_rfthr;       /* received frames threshold */
+	ushort  sh_rfcnt;       /* received frames count */
+	ushort  sh_hmask;       /* user defined frm addr mask */
+	ushort  sh_haddr1;      /* user defined frm address 1 */
+	ushort  sh_haddr2;      /* user defined frm address 2 */
+	ushort  sh_haddr3;      /* user defined frm address 3 */
+	ushort  sh_haddr4;      /* user defined frm address 4 */
+	ushort  tmp;            /* temp */
+	ushort  tmp_mb;         /* temp */
+} scc_hdlc_t;
+
+/* How about some FCCs.....
+*/
+#define FCC_GFMR_DIAG_NORM	((uint)0x00000000)
+#define FCC_GFMR_DIAG_LE	((uint)0x40000000)
+#define FCC_GFMR_DIAG_AE	((uint)0x80000000)
+#define FCC_GFMR_DIAG_ALE	((uint)0xc0000000)
+#define FCC_GFMR_TCI		((uint)0x20000000)
+#define FCC_GFMR_TRX		((uint)0x10000000)
+#define FCC_GFMR_TTX		((uint)0x08000000)
+#define FCC_GFMR_TTX		((uint)0x08000000)
+#define FCC_GFMR_CDP		((uint)0x04000000)
+#define FCC_GFMR_CTSP		((uint)0x02000000)
+#define FCC_GFMR_CDS		((uint)0x01000000)
+#define FCC_GFMR_CTSS		((uint)0x00800000)
+#define FCC_GFMR_SYNL_NONE	((uint)0x00000000)
+#define FCC_GFMR_SYNL_AUTO	((uint)0x00004000)
+#define FCC_GFMR_SYNL_8		((uint)0x00008000)
+#define FCC_GFMR_SYNL_16	((uint)0x0000c000)
+#define FCC_GFMR_RTSM		((uint)0x00002000)
+#define FCC_GFMR_RENC_NRZ	((uint)0x00000000)
+#define FCC_GFMR_RENC_NRZI	((uint)0x00000800)
+#define FCC_GFMR_REVD		((uint)0x00000400)
+#define FCC_GFMR_TENC_NRZ	((uint)0x00000000)
+#define FCC_GFMR_TENC_NRZI	((uint)0x00000100)
+#define FCC_GFMR_TCRC_16	((uint)0x00000000)
+#define FCC_GFMR_TCRC_32	((uint)0x00000080)
+#define FCC_GFMR_ENR		((uint)0x00000020)
+#define FCC_GFMR_ENT		((uint)0x00000010)
+#define FCC_GFMR_MODE_ENET	((uint)0x0000000c)
+#define FCC_GFMR_MODE_ATM	((uint)0x0000000a)
+#define FCC_GFMR_MODE_HDLC	((uint)0x00000000)
+
+/* Generic FCC parameter ram.
+*/
+typedef struct fcc_param {
+	ushort	fcc_riptr;	/* Rx Internal temp pointer */
+	ushort	fcc_tiptr;	/* Tx Internal temp pointer */
+	ushort	fcc_res1;
+	ushort	fcc_mrblr;	/* Max receive buffer length, mod 32 bytes */
+	uint	fcc_rstate;	/* Upper byte is Func code, must be set */
+	uint	fcc_rbase;	/* Receive BD base */
+	ushort	fcc_rbdstat;	/* RxBD status */
+	ushort	fcc_rbdlen;	/* RxBD down counter */
+	uint	fcc_rdptr;	/* RxBD internal data pointer */
+	uint	fcc_tstate;	/* Upper byte is Func code, must be set */
+	uint	fcc_tbase;	/* Transmit BD base */
+	ushort	fcc_tbdstat;	/* TxBD status */
+	ushort	fcc_tbdlen;	/* TxBD down counter */
+	uint	fcc_tdptr;	/* TxBD internal data pointer */
+	uint	fcc_rbptr;	/* Rx BD Internal buf pointer */
+	uint	fcc_tbptr;	/* Tx BD Internal buf pointer */
+	uint	fcc_rcrc;	/* Rx temp CRC */
+	uint	fcc_res2;
+	uint	fcc_tcrc;	/* Tx temp CRC */
+} fccp_t;
+
+
+/* Ethernet controller through FCC.
+*/
+typedef struct fcc_enet {
+	fccp_t	fen_genfcc;
+	uint	fen_statbuf;	/* Internal status buffer */
+	uint	fen_camptr;	/* CAM address */
+	uint	fen_cmask;	/* Constant mask for CRC */
+	uint	fen_cpres;	/* Preset CRC */
+	uint	fen_crcec;	/* CRC Error counter */
+	uint	fen_alec;	/* alignment error counter */
+	uint	fen_disfc;	/* discard frame counter */
+	ushort	fen_retlim;	/* Retry limit */
+	ushort	fen_retcnt;	/* Retry counter */
+	ushort	fen_pper;	/* Persistence */
+	ushort	fen_boffcnt;	/* backoff counter */
+	uint	fen_gaddrh;	/* Group address filter, high 32-bits */
+	uint	fen_gaddrl;	/* Group address filter, low 32-bits */
+	ushort	fen_tfcstat;	/* out of sequence TxBD */
+	ushort	fen_tfclen;
+	uint	fen_tfcptr;
+	ushort	fen_mflr;	/* Maximum frame length (1518) */
+	ushort	fen_paddrh;	/* MAC address */
+	ushort	fen_paddrm;
+	ushort	fen_paddrl;
+	ushort	fen_ibdcount;	/* Internal BD counter */
+	ushort	fen_idbstart;	/* Internal BD start pointer */
+	ushort	fen_ibdend;	/* Internal BD end pointer */
+	ushort	fen_txlen;	/* Internal Tx frame length counter */
+	uint	fen_ibdbase[8]; /* Internal use */
+	uint	fen_iaddrh;	/* Individual address filter */
+	uint	fen_iaddrl;
+	ushort	fen_minflr;	/* Minimum frame length (64) */
+	ushort	fen_taddrh;	/* Filter transfer MAC address */
+	ushort	fen_taddrm;
+	ushort	fen_taddrl;
+	ushort	fen_padptr;	/* Pointer to pad byte buffer */
+	ushort	fen_cftype;	/* control frame type */
+	ushort	fen_cfrange;	/* control frame range */
+	ushort	fen_maxb;	/* maximum BD count */
+	ushort	fen_maxd1;	/* Max DMA1 length (1520) */
+	ushort	fen_maxd2;	/* Max DMA2 length (1520) */
+	ushort	fen_maxd;	/* internal max DMA count */
+	ushort	fen_dmacnt;	/* internal DMA counter */
+	uint	fen_octc;	/* Total octect counter */
+	uint	fen_colc;	/* Total collision counter */
+	uint	fen_broc;	/* Total broadcast packet counter */
+	uint	fen_mulc;	/* Total multicast packet count */
+	uint	fen_uspc;	/* Total packets < 64 bytes */
+	uint	fen_frgc;	/* Total packets < 64 bytes with errors */
+	uint	fen_ospc;	/* Total packets > 1518 */
+	uint	fen_jbrc;	/* Total packets > 1518 with errors */
+	uint	fen_p64c;	/* Total packets == 64 bytes */
+	uint	fen_p65c;	/* Total packets 64 < bytes <= 127 */
+	uint	fen_p128c;	/* Total packets 127 < bytes <= 255 */
+	uint	fen_p256c;	/* Total packets 256 < bytes <= 511 */
+	uint	fen_p512c;	/* Total packets 512 < bytes <= 1023 */
+	uint	fen_p1024c;	/* Total packets 1024 < bytes <= 1518 */
+	uint	fen_cambuf;	/* Internal CAM buffer poiner */
+	ushort	fen_rfthr;	/* Received frames threshold */
+	ushort	fen_rfcnt;	/* Received frames count */
+} fcc_enet_t;
+
+/* FCC Event/Mask register as used by Ethernet.
+*/
+#define FCC_ENET_GRA	((ushort)0x0080)	/* Graceful stop complete */
+#define FCC_ENET_RXC	((ushort)0x0040)	/* Control Frame Received */
+#define FCC_ENET_TXC	((ushort)0x0020)	/* Out of seq. Tx sent */
+#define FCC_ENET_TXE	((ushort)0x0010)	/* Transmit Error */
+#define FCC_ENET_RXF	((ushort)0x0008)	/* Full frame received */
+#define FCC_ENET_BSY	((ushort)0x0004)	/* Busy.  Rx Frame dropped */
+#define FCC_ENET_TXB	((ushort)0x0002)	/* A buffer was transmitted */
+#define FCC_ENET_RXB	((ushort)0x0001)	/* A buffer was received */
+
+/* FCC Mode Register (FPSMR) as used by Ethernet.
+*/
+#define FCC_PSMR_HBC	((uint)0x80000000)	/* Enable heartbeat */
+#define FCC_PSMR_FC	((uint)0x40000000)	/* Force Collision */
+#define FCC_PSMR_SBT	((uint)0x20000000)	/* Stop backoff timer */
+#define FCC_PSMR_LPB	((uint)0x10000000)	/* Local protect. 1 = FDX */
+#define FCC_PSMR_LCW	((uint)0x08000000)	/* Late collision select */
+#define FCC_PSMR_FDE	((uint)0x04000000)	/* Full Duplex Enable */
+#define FCC_PSMR_MON	((uint)0x02000000)	/* RMON Enable */
+#define FCC_PSMR_PRO	((uint)0x00400000)	/* Promiscuous Enable */
+#define FCC_PSMR_FCE	((uint)0x00200000)	/* Flow Control Enable */
+#define FCC_PSMR_RSH	((uint)0x00100000)	/* Receive Short Frames */
+#define FCC_PSMR_RMII	((uint)0x00020000)	/* Use RMII interface */
+#define FCC_PSMR_CAM	((uint)0x00000400)	/* CAM enable */
+#define FCC_PSMR_BRO	((uint)0x00000200)	/* Broadcast pkt discard */
+#define FCC_PSMR_ENCRC	((uint)0x00000080)	/* Use 32-bit CRC */
+
+/* IIC parameter RAM.
+*/
+typedef struct iic {
+	ushort	iic_rbase;	/* Rx Buffer descriptor base address */
+	ushort	iic_tbase;	/* Tx Buffer descriptor base address */
+	u_char	iic_rfcr;	/* Rx function code */
+	u_char	iic_tfcr;	/* Tx function code */
+	ushort	iic_mrblr;	/* Max receive buffer length */
+	uint	iic_rstate;	/* Internal */
+	uint	iic_rdp;	/* Internal */
+	ushort	iic_rbptr;	/* Internal */
+	ushort	iic_rbc;	/* Internal */
+	uint	iic_rxtmp;	/* Internal */
+	uint	iic_tstate;	/* Internal */
+	uint	iic_tdp;	/* Internal */
+	ushort	iic_tbptr;	/* Internal */
+	ushort	iic_tbc;	/* Internal */
+	uint	iic_txtmp;	/* Internal */
+} iic_t;
+
+/* SPI parameter RAM.
+*/
+typedef struct spi {
+	ushort	spi_rbase;	/* Rx Buffer descriptor base address */
+	ushort	spi_tbase;	/* Tx Buffer descriptor base address */
+	u_char	spi_rfcr;	/* Rx function code */
+	u_char	spi_tfcr;	/* Tx function code */
+	ushort	spi_mrblr;	/* Max receive buffer length */
+	uint	spi_rstate;	/* Internal */
+	uint	spi_rdp;	/* Internal */
+	ushort	spi_rbptr;	/* Internal */
+	ushort	spi_rbc;	/* Internal */
+	uint	spi_rxtmp;	/* Internal */
+	uint	spi_tstate;	/* Internal */
+	uint	spi_tdp;	/* Internal */
+	ushort	spi_tbptr;	/* Internal */
+	ushort	spi_tbc;	/* Internal */
+	uint	spi_txtmp;	/* Internal */
+	uint	spi_res;	/* Tx temp. */
+	uint	spi_res1[4];	/* SDMA temp. */
+} spi_t;
+
+/* SPI Mode register.
+*/
+#define SPMODE_LOOP	((ushort)0x4000)	/* Loopback */
+#define SPMODE_CI	((ushort)0x2000)	/* Clock Invert */
+#define SPMODE_CP	((ushort)0x1000)	/* Clock Phase */
+#define SPMODE_DIV16	((ushort)0x0800)	/* BRG/16 mode */
+#define SPMODE_REV	((ushort)0x0400)	/* Reversed Data */
+#define SPMODE_MSTR	((ushort)0x0200)	/* SPI Master */
+#define SPMODE_EN	((ushort)0x0100)	/* Enable */
+#define SPMODE_LENMSK	((ushort)0x00f0)	/* character length */
+#define SPMODE_PMMSK	((ushort)0x000f)	/* prescale modulus */
+
+#define SPMODE_LEN(x)	((((x)-1)&0xF)<<4)
+#define SPMODE_PM(x)	((x) &0xF)
+
+/* SPI Event/Mask register.
+*/
+#define SPI_EMASK		0x37	/* Event Mask				*/
+#define SPI_MME			0x20	/* Multi-Master Error			*/
+#define SPI_TXE			0x10	/* Transmit Error			*/
+#define SPI_BSY			0x04	/* Busy					*/
+#define SPI_TXB			0x02	/* Tx Buffer Empty			*/
+#define SPI_RXB			0x01	/* RX Buffer full/closed		*/
+
+#define SPI_STR			0x80	/* SPCOM: Start transmit		*/
+
+#define SPI_EB		((u_char)0x10)		/* big endian byte order */
+
+#define BD_IIC_START		((ushort)0x0400)
+
+#endif /* __CPM_82XX__ */
diff --git a/arch/powerpc/include/asm/cpm_85xx.h b/arch/powerpc/include/asm/cpm_85xx.h
new file mode 100644
index 0000000..a74a3a1
--- /dev/null
+++ b/arch/powerpc/include/asm/cpm_85xx.h
@@ -0,0 +1,830 @@
+
+/*
+ * MPC85xx Communication Processor Module
+ * Copyright (c) 2003,Motorola Inc.
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ *
+ * MPC8260 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ *
+ * This file contains structures and information for the communication
+ * processor channels found in the dual port RAM or parameter RAM.
+ * All CPM control and status is available through the MPC8260 internal
+ * memory map.  See immap.h for details.
+ */
+#ifndef __CPM_85XX__
+#define __CPM_85XX__
+
+#include <asm/immap_85xx.h>
+
+/* CPM Command register.
+*/
+#define CPM_CR_RST	((uint)0x80000000)
+#define CPM_CR_PAGE	((uint)0x7c000000)
+#define CPM_CR_SBLOCK	((uint)0x03e00000)
+#define CPM_CR_FLG	((uint)0x00010000)
+#define CPM_CR_MCN	((uint)0x00003fc0)
+#define CPM_CR_OPCODE	((uint)0x0000000f)
+
+/* Device sub-block and page codes.
+*/
+#define CPM_CR_SCC1_SBLOCK	(0x04)
+#define CPM_CR_SCC2_SBLOCK	(0x05)
+#define CPM_CR_SCC3_SBLOCK	(0x06)
+#define CPM_CR_SCC4_SBLOCK	(0x07)
+#define CPM_CR_SMC1_SBLOCK	(0x08)
+#define CPM_CR_SMC2_SBLOCK	(0x09)
+#define CPM_CR_SPI_SBLOCK	(0x0a)
+#define CPM_CR_I2C_SBLOCK	(0x0b)
+#define CPM_CR_TIMER_SBLOCK	(0x0f)
+#define CPM_CR_RAND_SBLOCK	(0x0e)
+#define CPM_CR_FCC1_SBLOCK	(0x10)
+#define CPM_CR_FCC2_SBLOCK	(0x11)
+#define CPM_CR_FCC3_SBLOCK	(0x12)
+#define CPM_CR_MCC1_SBLOCK	(0x1c)
+
+#define CPM_CR_SCC1_PAGE	(0x00)
+#define CPM_CR_SCC2_PAGE	(0x01)
+#define CPM_CR_SCC3_PAGE	(0x02)
+#define CPM_CR_SCC4_PAGE	(0x03)
+#define CPM_CR_SPI_PAGE		(0x09)
+#define CPM_CR_I2C_PAGE		(0x0a)
+#define CPM_CR_TIMER_PAGE	(0x0a)
+#define CPM_CR_RAND_PAGE	(0x0a)
+#define CPM_CR_FCC1_PAGE	(0x04)
+#define CPM_CR_FCC2_PAGE	(0x05)
+#define CPM_CR_FCC3_PAGE	(0x06)
+#define CPM_CR_MCC1_PAGE	(0x07)
+#define CPM_CR_MCC2_PAGE	(0x08)
+
+/* Some opcodes (there are more...later)
+*/
+#define CPM_CR_INIT_TRX		((ushort)0x0000)
+#define CPM_CR_INIT_RX		((ushort)0x0001)
+#define CPM_CR_INIT_TX		((ushort)0x0002)
+#define CPM_CR_HUNT_MODE	((ushort)0x0003)
+#define CPM_CR_STOP_TX		((ushort)0x0004)
+#define CPM_CR_RESTART_TX	((ushort)0x0006)
+#define CPM_CR_SET_GADDR	((ushort)0x0008)
+
+#define mk_cr_cmd(PG, SBC, MCN, OP) \
+	((PG << 26) | (SBC << 21) | (MCN << 6) | OP)
+
+/* Dual Port RAM addresses.  The first 16K is available for almost
+ * any CPM use, so we put the BDs there.  The first 128 bytes are
+ * used for SMC1 and SMC2 parameter RAM, so we start allocating
+ * BDs above that.  All of this must change when we start
+ * downloading RAM microcode.
+ */
+#define CPM_DATAONLY_BASE	((uint)128)
+#define CPM_DP_NOSPACE		((uint)0x7FFFFFFF)
+#if defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
+#define CPM_FCC_SPECIAL_BASE	((uint)0x00009000)
+#define CPM_DATAONLY_SIZE	((uint)(8 * 1024) - CPM_DATAONLY_BASE)
+#else	/* MPC8540, MPC8560 */
+#define CPM_FCC_SPECIAL_BASE	((uint)0x0000B000)
+#define CPM_DATAONLY_SIZE	((uint)(16 * 1024) - CPM_DATAONLY_BASE)
+#endif
+
+/* The number of pages of host memory we allocate for CPM.  This is
+ * done early in kernel initialization to get physically contiguous
+ * pages.
+ */
+#define NUM_CPM_HOST_PAGES	2
+
+/* Export the base address of the communication processor registers
+ * and dual port ram.
+ */
+/*extern	cpm8560_t	*cpmp;	 Pointer to comm processor */
+uint		m8560_cpm_dpalloc(uint size, uint align);
+uint		m8560_cpm_hostalloc(uint size, uint align);
+void		m8560_cpm_setbrg(uint brg, uint rate);
+void		m8560_cpm_fastbrg(uint brg, uint rate, int div16);
+void		m8560_cpm_extcbrg(uint brg, uint rate, uint extclk, int pinsel);
+
+/* Buffer descriptors used by many of the CPM protocols.
+*/
+typedef struct cpm_buf_desc {
+	ushort	cbd_sc;		/* Status and Control */
+	ushort	cbd_datlen;	/* Data length in buffer */
+	uint	cbd_bufaddr;	/* Buffer address in host memory */
+} cbd_t;
+
+#define BD_SC_EMPTY	((ushort)0x8000)	/* Recieve is empty */
+#define BD_SC_READY	((ushort)0x8000)	/* Transmit is ready */
+#define BD_SC_WRAP	((ushort)0x2000)	/* Last buffer descriptor */
+#define BD_SC_INTRPT	((ushort)0x1000)	/* Interrupt on change */
+#define BD_SC_LAST	((ushort)0x0800)	/* Last buffer in frame */
+#define BD_SC_CM	((ushort)0x0200)	/* Continous mode */
+#define BD_SC_ID	((ushort)0x0100)	/* Rec'd too many idles */
+#define BD_SC_P		((ushort)0x0100)	/* xmt preamble */
+#define BD_SC_BR	((ushort)0x0020)	/* Break received */
+#define BD_SC_FR	((ushort)0x0010)	/* Framing error */
+#define BD_SC_PR	((ushort)0x0008)	/* Parity error */
+#define BD_SC_OV	((ushort)0x0002)	/* Overrun */
+#define BD_SC_CD	((ushort)0x0001)	/* ?? */
+
+/* Function code bits, usually generic to devices.
+*/
+#define CPMFCR_GBL	((u_char)0x20)	/* Set memory snooping */
+#define CPMFCR_EB	((u_char)0x10)	/* Set big endian byte order */
+#define CPMFCR_TC2	((u_char)0x04)	/* Transfer code 2 value */
+#define CPMFCR_DTB	((u_char)0x02)	/* Use local bus for data when set */
+#define CPMFCR_BDB	((u_char)0x01)	/* Use local bus for BD when set */
+
+/* Parameter RAM offsets from the base.
+*/
+#define CPM_POST_WORD_ADDR      0x80FC	/* steal a long at the end of SCC1 */
+#define PROFF_SCC1		((uint)0x8000)
+#define PROFF_SCC2		((uint)0x8100)
+#define PROFF_SCC3		((uint)0x8200)
+#define PROFF_SCC4		((uint)0x8300)
+#define PROFF_FCC1		((uint)0x8400)
+#define PROFF_FCC2		((uint)0x8500)
+#define PROFF_FCC3		((uint)0x8600)
+#define PROFF_MCC1		((uint)0x8700)
+#define PROFF_MCC2		((uint)0x8800)
+#define PROFF_SPI_BASE		((uint)0x89fc)
+#define PROFF_TIMERS		((uint)0x8ae0)
+#define PROFF_REVNUM		((uint)0x8af0)
+#define PROFF_RAND		((uint)0x8af8)
+#define PROFF_I2C_BASE		((uint)0x8afc)
+
+/* Baud rate generators.
+*/
+#define CPM_BRG_RST		((uint)0x00020000)
+#define CPM_BRG_EN		((uint)0x00010000)
+#define CPM_BRG_EXTC_INT	((uint)0x00000000)
+#define CPM_BRG_EXTC_CLK3_9	((uint)0x00004000)
+#define CPM_BRG_EXTC_CLK5_15	((uint)0x00008000)
+#define CPM_BRG_ATB		((uint)0x00002000)
+#define CPM_BRG_CD_MASK		((uint)0x00001ffe)
+#define CPM_BRG_DIV16		((uint)0x00000001)
+
+/* SCCs.
+*/
+#define SCC_GSMRH_IRP		((uint)0x00040000)
+#define SCC_GSMRH_GDE		((uint)0x00010000)
+#define SCC_GSMRH_TCRC_CCITT	((uint)0x00008000)
+#define SCC_GSMRH_TCRC_BISYNC	((uint)0x00004000)
+#define SCC_GSMRH_TCRC_HDLC	((uint)0x00000000)
+#define SCC_GSMRH_REVD		((uint)0x00002000)
+#define SCC_GSMRH_TRX		((uint)0x00001000)
+#define SCC_GSMRH_TTX		((uint)0x00000800)
+#define SCC_GSMRH_CDP		((uint)0x00000400)
+#define SCC_GSMRH_CTSP		((uint)0x00000200)
+#define SCC_GSMRH_CDS		((uint)0x00000100)
+#define SCC_GSMRH_CTSS		((uint)0x00000080)
+#define SCC_GSMRH_TFL		((uint)0x00000040)
+#define SCC_GSMRH_RFW		((uint)0x00000020)
+#define SCC_GSMRH_TXSY		((uint)0x00000010)
+#define SCC_GSMRH_SYNL16	((uint)0x0000000c)
+#define SCC_GSMRH_SYNL8		((uint)0x00000008)
+#define SCC_GSMRH_SYNL4		((uint)0x00000004)
+#define SCC_GSMRH_RTSM		((uint)0x00000002)
+#define SCC_GSMRH_RSYN		((uint)0x00000001)
+
+#define SCC_GSMRL_SIR		((uint)0x80000000)	/* SCC2 only */
+#define SCC_GSMRL_EDGE_NONE	((uint)0x60000000)
+#define SCC_GSMRL_EDGE_NEG	((uint)0x40000000)
+#define SCC_GSMRL_EDGE_POS	((uint)0x20000000)
+#define SCC_GSMRL_EDGE_BOTH	((uint)0x00000000)
+#define SCC_GSMRL_TCI		((uint)0x10000000)
+#define SCC_GSMRL_TSNC_3	((uint)0x0c000000)
+#define SCC_GSMRL_TSNC_4	((uint)0x08000000)
+#define SCC_GSMRL_TSNC_14	((uint)0x04000000)
+#define SCC_GSMRL_TSNC_INF	((uint)0x00000000)
+#define SCC_GSMRL_RINV		((uint)0x02000000)
+#define SCC_GSMRL_TINV		((uint)0x01000000)
+#define SCC_GSMRL_TPL_128	((uint)0x00c00000)
+#define SCC_GSMRL_TPL_64	((uint)0x00a00000)
+#define SCC_GSMRL_TPL_48	((uint)0x00800000)
+#define SCC_GSMRL_TPL_32	((uint)0x00600000)
+#define SCC_GSMRL_TPL_16	((uint)0x00400000)
+#define SCC_GSMRL_TPL_8		((uint)0x00200000)
+#define SCC_GSMRL_TPL_NONE	((uint)0x00000000)
+#define SCC_GSMRL_TPP_ALL1	((uint)0x00180000)
+#define SCC_GSMRL_TPP_01	((uint)0x00100000)
+#define SCC_GSMRL_TPP_10	((uint)0x00080000)
+#define SCC_GSMRL_TPP_ZEROS	((uint)0x00000000)
+#define SCC_GSMRL_TEND		((uint)0x00040000)
+#define SCC_GSMRL_TDCR_32	((uint)0x00030000)
+#define SCC_GSMRL_TDCR_16	((uint)0x00020000)
+#define SCC_GSMRL_TDCR_8	((uint)0x00010000)
+#define SCC_GSMRL_TDCR_1	((uint)0x00000000)
+#define SCC_GSMRL_RDCR_32	((uint)0x0000c000)
+#define SCC_GSMRL_RDCR_16	((uint)0x00008000)
+#define SCC_GSMRL_RDCR_8	((uint)0x00004000)
+#define SCC_GSMRL_RDCR_1	((uint)0x00000000)
+#define SCC_GSMRL_RENC_DFMAN	((uint)0x00003000)
+#define SCC_GSMRL_RENC_MANCH	((uint)0x00002000)
+#define SCC_GSMRL_RENC_FM0	((uint)0x00001000)
+#define SCC_GSMRL_RENC_NRZI	((uint)0x00000800)
+#define SCC_GSMRL_RENC_NRZ	((uint)0x00000000)
+#define SCC_GSMRL_TENC_DFMAN	((uint)0x00000600)
+#define SCC_GSMRL_TENC_MANCH	((uint)0x00000400)
+#define SCC_GSMRL_TENC_FM0	((uint)0x00000200)
+#define SCC_GSMRL_TENC_NRZI	((uint)0x00000100)
+#define SCC_GSMRL_TENC_NRZ	((uint)0x00000000)
+#define SCC_GSMRL_DIAG_LE	((uint)0x000000c0)	/* Loop and echo */
+#define SCC_GSMRL_DIAG_ECHO	((uint)0x00000080)
+#define SCC_GSMRL_DIAG_LOOP	((uint)0x00000040)
+#define SCC_GSMRL_DIAG_NORM	((uint)0x00000000)
+#define SCC_GSMRL_ENR		((uint)0x00000020)
+#define SCC_GSMRL_ENT		((uint)0x00000010)
+#define SCC_GSMRL_MODE_ENET	((uint)0x0000000c)
+#define SCC_GSMRL_MODE_DDCMP	((uint)0x00000009)
+#define SCC_GSMRL_MODE_BISYNC	((uint)0x00000008)
+#define SCC_GSMRL_MODE_V14	((uint)0x00000007)
+#define SCC_GSMRL_MODE_AHDLC	((uint)0x00000006)
+#define SCC_GSMRL_MODE_PROFIBUS	((uint)0x00000005)
+#define SCC_GSMRL_MODE_UART	((uint)0x00000004)
+#define SCC_GSMRL_MODE_SS7	((uint)0x00000003)
+#define SCC_GSMRL_MODE_ATALK	((uint)0x00000002)
+#define SCC_GSMRL_MODE_HDLC	((uint)0x00000000)
+
+#define SCC_TODR_TOD		((ushort)0x8000)
+
+/* SCC Event and Mask register.
+*/
+#define	SCCM_TXE	((unsigned char)0x10)
+#define	SCCM_BSY	((unsigned char)0x04)
+#define	SCCM_TX		((unsigned char)0x02)
+#define	SCCM_RX		((unsigned char)0x01)
+
+typedef struct scc_param {
+	ushort	scc_rbase;	/* Rx Buffer descriptor base address */
+	ushort	scc_tbase;	/* Tx Buffer descriptor base address */
+	u_char	scc_rfcr;	/* Rx function code */
+	u_char	scc_tfcr;	/* Tx function code */
+	ushort	scc_mrblr;	/* Max receive buffer length */
+	uint	scc_rstate;	/* Internal */
+	uint	scc_idp;	/* Internal */
+	ushort	scc_rbptr;	/* Internal */
+	ushort	scc_ibc;	/* Internal */
+	uint	scc_rxtmp;	/* Internal */
+	uint	scc_tstate;	/* Internal */
+	uint	scc_tdp;	/* Internal */
+	ushort	scc_tbptr;	/* Internal */
+	ushort	scc_tbc;	/* Internal */
+	uint	scc_txtmp;	/* Internal */
+	uint	scc_rcrc;	/* Internal */
+	uint	scc_tcrc;	/* Internal */
+} sccp_t;
+
+/* CPM Ethernet through SCC1.
+ */
+typedef struct scc_enet {
+	sccp_t	sen_genscc;
+	uint	sen_cpres;	/* Preset CRC */
+	uint	sen_cmask;	/* Constant mask for CRC */
+	uint	sen_crcec;	/* CRC Error counter */
+	uint	sen_alec;	/* alignment error counter */
+	uint	sen_disfc;	/* discard frame counter */
+	ushort	sen_pads;	/* Tx short frame pad character */
+	ushort	sen_retlim;	/* Retry limit threshold */
+	ushort	sen_retcnt;	/* Retry limit counter */
+	ushort	sen_maxflr;	/* maximum frame length register */
+	ushort	sen_minflr;	/* minimum frame length register */
+	ushort	sen_maxd1;	/* maximum DMA1 length */
+	ushort	sen_maxd2;	/* maximum DMA2 length */
+	ushort	sen_maxd;	/* Rx max DMA */
+	ushort	sen_dmacnt;	/* Rx DMA counter */
+	ushort	sen_maxb;	/* Max BD byte count */
+	ushort	sen_gaddr1;	/* Group address filter */
+	ushort	sen_gaddr2;
+	ushort	sen_gaddr3;
+	ushort	sen_gaddr4;
+	uint	sen_tbuf0data0;	/* Save area 0 - current frame */
+	uint	sen_tbuf0data1;	/* Save area 1 - current frame */
+	uint	sen_tbuf0rba;	/* Internal */
+	uint	sen_tbuf0crc;	/* Internal */
+	ushort	sen_tbuf0bcnt;	/* Internal */
+	ushort	sen_paddrh;	/* physical address (MSB) */
+	ushort	sen_paddrm;
+	ushort	sen_paddrl;	/* physical address (LSB) */
+	ushort	sen_pper;	/* persistence */
+	ushort	sen_rfbdptr;	/* Rx first BD pointer */
+	ushort	sen_tfbdptr;	/* Tx first BD pointer */
+	ushort	sen_tlbdptr;	/* Tx last BD pointer */
+	uint	sen_tbuf1data0;	/* Save area 0 - current frame */
+	uint	sen_tbuf1data1;	/* Save area 1 - current frame */
+	uint	sen_tbuf1rba;	/* Internal */
+	uint	sen_tbuf1crc;	/* Internal */
+	ushort	sen_tbuf1bcnt;	/* Internal */
+	ushort	sen_txlen;	/* Tx Frame length counter */
+	ushort	sen_iaddr1;	/* Individual address filter */
+	ushort	sen_iaddr2;
+	ushort	sen_iaddr3;
+	ushort	sen_iaddr4;
+	ushort	sen_boffcnt;	/* Backoff counter */
+
+	/* NOTE: Some versions of the manual have the following items
+	 * incorrectly documented.  Below is the proper order.
+	 */
+	ushort	sen_taddrh;	/* temp address (MSB) */
+	ushort	sen_taddrm;
+	ushort	sen_taddrl;	/* temp address (LSB) */
+} scc_enet_t;
+
+
+/* SCC Event register as used by Ethernet.
+*/
+#define SCCE_ENET_GRA	((ushort)0x0080)	/* Graceful stop complete */
+#define SCCE_ENET_TXE	((ushort)0x0010)	/* Transmit Error */
+#define SCCE_ENET_RXF	((ushort)0x0008)	/* Full frame received */
+#define SCCE_ENET_BSY	((ushort)0x0004)	/* All incoming buffers full */
+#define SCCE_ENET_TXB	((ushort)0x0002)	/* A buffer was transmitted */
+#define SCCE_ENET_RXB	((ushort)0x0001)	/* A buffer was received */
+
+/* SCC Mode Register (PSMR) as used by Ethernet.
+*/
+#define SCC_PSMR_HBC	((ushort)0x8000)	/* Enable heartbeat */
+#define SCC_PSMR_FC	((ushort)0x4000)	/* Force collision */
+#define SCC_PSMR_RSH	((ushort)0x2000)	/* Receive short frames */
+#define SCC_PSMR_IAM	((ushort)0x1000)	/* Check individual hash */
+#define SCC_PSMR_ENCRC	((ushort)0x0800)	/* Ethernet CRC mode */
+#define SCC_PSMR_PRO	((ushort)0x0200)	/* Promiscuous mode */
+#define SCC_PSMR_BRO	((ushort)0x0100)	/* Catch broadcast pkts */
+#define SCC_PSMR_SBT	((ushort)0x0080)	/* Special backoff timer */
+#define SCC_PSMR_LPB	((ushort)0x0040)	/* Set Loopback mode */
+#define SCC_PSMR_SIP	((ushort)0x0020)	/* Sample Input Pins */
+#define SCC_PSMR_LCW	((ushort)0x0010)	/* Late collision window */
+#define SCC_PSMR_NIB22	((ushort)0x000a)	/* Start frame search */
+#define SCC_PSMR_FDE	((ushort)0x0001)	/* Full duplex enable */
+
+/* Buffer descriptor control/status used by Ethernet receive.
+ * Common to SCC and FCC.
+ */
+#define BD_ENET_RX_EMPTY	((ushort)0x8000)
+#define BD_ENET_RX_WRAP		((ushort)0x2000)
+#define BD_ENET_RX_INTR		((ushort)0x1000)
+#define BD_ENET_RX_LAST		((ushort)0x0800)
+#define BD_ENET_RX_FIRST	((ushort)0x0400)
+#define BD_ENET_RX_MISS		((ushort)0x0100)
+#define BD_ENET_RX_BC		((ushort)0x0080)	/* FCC Only */
+#define BD_ENET_RX_MC		((ushort)0x0040)	/* FCC Only */
+#define BD_ENET_RX_LG		((ushort)0x0020)
+#define BD_ENET_RX_NO		((ushort)0x0010)
+#define BD_ENET_RX_SH		((ushort)0x0008)
+#define BD_ENET_RX_CR		((ushort)0x0004)
+#define BD_ENET_RX_OV		((ushort)0x0002)
+#define BD_ENET_RX_CL		((ushort)0x0001)
+#define BD_ENET_RX_STATS	((ushort)0x01ff)	/* All status bits */
+
+/* Buffer descriptor control/status used by Ethernet transmit.
+ * Common to SCC and FCC.
+ */
+#define BD_ENET_TX_READY	((ushort)0x8000)
+#define BD_ENET_TX_PAD		((ushort)0x4000)
+#define BD_ENET_TX_WRAP		((ushort)0x2000)
+#define BD_ENET_TX_INTR		((ushort)0x1000)
+#define BD_ENET_TX_LAST		((ushort)0x0800)
+#define BD_ENET_TX_TC		((ushort)0x0400)
+#define BD_ENET_TX_DEF		((ushort)0x0200)
+#define BD_ENET_TX_HB		((ushort)0x0100)
+#define BD_ENET_TX_LC		((ushort)0x0080)
+#define BD_ENET_TX_RL		((ushort)0x0040)
+#define BD_ENET_TX_RCMASK	((ushort)0x003c)
+#define BD_ENET_TX_UN		((ushort)0x0002)
+#define BD_ENET_TX_CSL		((ushort)0x0001)
+#define BD_ENET_TX_STATS	((ushort)0x03ff)	/* All status bits */
+
+/* SCC as UART
+*/
+typedef struct scc_uart {
+	sccp_t	scc_genscc;
+	uint	scc_res1;	/* Reserved */
+	uint	scc_res2;	/* Reserved */
+	ushort	scc_maxidl;	/* Maximum idle chars */
+	ushort	scc_idlc;	/* temp idle counter */
+	ushort	scc_brkcr;	/* Break count register */
+	ushort	scc_parec;	/* receive parity error counter */
+	ushort	scc_frmec;	/* receive framing error counter */
+	ushort	scc_nosec;	/* receive noise counter */
+	ushort	scc_brkec;	/* receive break condition counter */
+	ushort	scc_brkln;	/* last received break length */
+	ushort	scc_uaddr1;	/* UART address character 1 */
+	ushort	scc_uaddr2;	/* UART address character 2 */
+	ushort	scc_rtemp;	/* Temp storage */
+	ushort	scc_toseq;	/* Transmit out of sequence char */
+	ushort	scc_char1;	/* control character 1 */
+	ushort	scc_char2;	/* control character 2 */
+	ushort	scc_char3;	/* control character 3 */
+	ushort	scc_char4;	/* control character 4 */
+	ushort	scc_char5;	/* control character 5 */
+	ushort	scc_char6;	/* control character 6 */
+	ushort	scc_char7;	/* control character 7 */
+	ushort	scc_char8;	/* control character 8 */
+	ushort	scc_rccm;	/* receive control character mask */
+	ushort	scc_rccr;	/* receive control character register */
+	ushort	scc_rlbc;	/* receive last break character */
+} scc_uart_t;
+
+/* SCC Event and Mask registers when it is used as a UART.
+*/
+#define UART_SCCM_GLR		((ushort)0x1000)
+#define UART_SCCM_GLT		((ushort)0x0800)
+#define UART_SCCM_AB		((ushort)0x0200)
+#define UART_SCCM_IDL		((ushort)0x0100)
+#define UART_SCCM_GRA		((ushort)0x0080)
+#define UART_SCCM_BRKE		((ushort)0x0040)
+#define UART_SCCM_BRKS		((ushort)0x0020)
+#define UART_SCCM_CCR		((ushort)0x0008)
+#define UART_SCCM_BSY		((ushort)0x0004)
+#define UART_SCCM_TX		((ushort)0x0002)
+#define UART_SCCM_RX		((ushort)0x0001)
+
+/* The SCC PSMR when used as a UART.
+*/
+#define SCU_PSMR_FLC		((ushort)0x8000)
+#define SCU_PSMR_SL		((ushort)0x4000)
+#define SCU_PSMR_CL		((ushort)0x3000)
+#define SCU_PSMR_UM		((ushort)0x0c00)
+#define SCU_PSMR_FRZ		((ushort)0x0200)
+#define SCU_PSMR_RZS		((ushort)0x0100)
+#define SCU_PSMR_SYN		((ushort)0x0080)
+#define SCU_PSMR_DRT		((ushort)0x0040)
+#define SCU_PSMR_PEN		((ushort)0x0010)
+#define SCU_PSMR_RPM		((ushort)0x000c)
+#define SCU_PSMR_REVP		((ushort)0x0008)
+#define SCU_PSMR_TPM		((ushort)0x0003)
+#define SCU_PSMR_TEVP		((ushort)0x0003)
+
+/* CPM Transparent mode SCC.
+ */
+typedef struct scc_trans {
+	sccp_t	st_genscc;
+	uint	st_cpres;	/* Preset CRC */
+	uint	st_cmask;	/* Constant mask for CRC */
+} scc_trans_t;
+
+#define BD_SCC_TX_LAST		((ushort)0x0800)
+
+/* How about some FCCs.....
+*/
+#define FCC_GFMR_DIAG_NORM	((uint)0x00000000)
+#define FCC_GFMR_DIAG_LE	((uint)0x40000000)
+#define FCC_GFMR_DIAG_AE	((uint)0x80000000)
+#define FCC_GFMR_DIAG_ALE	((uint)0xc0000000)
+#define FCC_GFMR_TCI		((uint)0x20000000)
+#define FCC_GFMR_TRX		((uint)0x10000000)
+#define FCC_GFMR_TTX		((uint)0x08000000)
+#define FCC_GFMR_TTX		((uint)0x08000000)
+#define FCC_GFMR_CDP		((uint)0x04000000)
+#define FCC_GFMR_CTSP		((uint)0x02000000)
+#define FCC_GFMR_CDS		((uint)0x01000000)
+#define FCC_GFMR_CTSS		((uint)0x00800000)
+#define FCC_GFMR_SYNL_NONE	((uint)0x00000000)
+#define FCC_GFMR_SYNL_AUTO	((uint)0x00004000)
+#define FCC_GFMR_SYNL_8		((uint)0x00008000)
+#define FCC_GFMR_SYNL_16	((uint)0x0000c000)
+#define FCC_GFMR_RTSM		((uint)0x00002000)
+#define FCC_GFMR_RENC_NRZ	((uint)0x00000000)
+#define FCC_GFMR_RENC_NRZI	((uint)0x00000800)
+#define FCC_GFMR_REVD		((uint)0x00000400)
+#define FCC_GFMR_TENC_NRZ	((uint)0x00000000)
+#define FCC_GFMR_TENC_NRZI	((uint)0x00000100)
+#define FCC_GFMR_TCRC_16	((uint)0x00000000)
+#define FCC_GFMR_TCRC_32	((uint)0x00000080)
+#define FCC_GFMR_ENR		((uint)0x00000020)
+#define FCC_GFMR_ENT		((uint)0x00000010)
+#define FCC_GFMR_MODE_ENET	((uint)0x0000000c)
+#define FCC_GFMR_MODE_ATM	((uint)0x0000000a)
+#define FCC_GFMR_MODE_HDLC	((uint)0x00000000)
+
+/* Generic FCC parameter ram.
+*/
+typedef struct fcc_param {
+	ushort	fcc_riptr;	/* Rx Internal temp pointer */
+	ushort	fcc_tiptr;	/* Tx Internal temp pointer */
+	ushort	fcc_res1;
+	ushort	fcc_mrblr;	/* Max receive buffer length, mod 32 bytes */
+	uint	fcc_rstate;	/* Upper byte is Func code, must be set */
+	uint	fcc_rbase;	/* Receive BD base */
+	ushort	fcc_rbdstat;	/* RxBD status */
+	ushort	fcc_rbdlen;	/* RxBD down counter */
+	uint	fcc_rdptr;	/* RxBD internal data pointer */
+	uint	fcc_tstate;	/* Upper byte is Func code, must be set */
+	uint	fcc_tbase;	/* Transmit BD base */
+	ushort	fcc_tbdstat;	/* TxBD status */
+	ushort	fcc_tbdlen;	/* TxBD down counter */
+	uint	fcc_tdptr;	/* TxBD internal data pointer */
+	uint	fcc_rbptr;	/* Rx BD Internal buf pointer */
+	uint	fcc_tbptr;	/* Tx BD Internal buf pointer */
+	uint	fcc_rcrc;	/* Rx temp CRC */
+	uint	fcc_res2;
+	uint	fcc_tcrc;	/* Tx temp CRC */
+} fccp_t;
+
+
+/* Ethernet controller through FCC.
+*/
+typedef struct fcc_enet {
+	fccp_t	fen_genfcc;
+	uint	fen_statbuf;	/* Internal status buffer */
+	uint	fen_camptr;	/* CAM address */
+	uint	fen_cmask;	/* Constant mask for CRC */
+	uint	fen_cpres;	/* Preset CRC */
+	uint	fen_crcec;	/* CRC Error counter */
+	uint	fen_alec;	/* alignment error counter */
+	uint	fen_disfc;	/* discard frame counter */
+	ushort	fen_retlim;	/* Retry limit */
+	ushort	fen_retcnt;	/* Retry counter */
+	ushort	fen_pper;	/* Persistence */
+	ushort	fen_boffcnt;	/* backoff counter */
+	uint	fen_gaddrh;	/* Group address filter, high 32-bits */
+	uint	fen_gaddrl;	/* Group address filter, low 32-bits */
+	ushort	fen_tfcstat;	/* out of sequence TxBD */
+	ushort	fen_tfclen;
+	uint	fen_tfcptr;
+	ushort	fen_mflr;	/* Maximum frame length (1518) */
+	ushort	fen_paddrh;	/* MAC address */
+	ushort	fen_paddrm;
+	ushort	fen_paddrl;
+	ushort	fen_ibdcount;	/* Internal BD counter */
+	ushort	fen_ibdstart;	/* Internal BD start pointer */
+	ushort	fen_ibdend;	/* Internal BD end pointer */
+	ushort	fen_txlen;	/* Internal Tx frame length counter */
+	uint	fen_ibdbase[8]; /* Internal use */
+	uint	fen_iaddrh;	/* Individual address filter */
+	uint	fen_iaddrl;
+	ushort	fen_minflr;	/* Minimum frame length (64) */
+	ushort	fen_taddrh;	/* Filter transfer MAC address */
+	ushort	fen_taddrm;
+	ushort	fen_taddrl;
+	ushort	fen_padptr;	/* Pointer to pad byte buffer */
+	ushort	fen_cftype;	/* control frame type */
+	ushort	fen_cfrange;	/* control frame range */
+	ushort	fen_maxb;	/* maximum BD count */
+	ushort	fen_maxd1;	/* Max DMA1 length (1520) */
+	ushort	fen_maxd2;	/* Max DMA2 length (1520) */
+	ushort	fen_maxd;	/* internal max DMA count */
+	ushort	fen_dmacnt;	/* internal DMA counter */
+	uint	fen_octc;	/* Total octect counter */
+	uint	fen_colc;	/* Total collision counter */
+	uint	fen_broc;	/* Total broadcast packet counter */
+	uint	fen_mulc;	/* Total multicast packet count */
+	uint	fen_uspc;	/* Total packets < 64 bytes */
+	uint	fen_frgc;	/* Total packets < 64 bytes with errors */
+	uint	fen_ospc;	/* Total packets > 1518 */
+	uint	fen_jbrc;	/* Total packets > 1518 with errors */
+	uint	fen_p64c;	/* Total packets == 64 bytes */
+	uint	fen_p65c;	/* Total packets 64 < bytes <= 127 */
+	uint	fen_p128c;	/* Total packets 127 < bytes <= 255 */
+	uint	fen_p256c;	/* Total packets 256 < bytes <= 511 */
+	uint	fen_p512c;	/* Total packets 512 < bytes <= 1023 */
+	uint	fen_p1024c;	/* Total packets 1024 < bytes <= 1518 */
+	uint	fen_cambuf;	/* Internal CAM buffer poiner */
+	ushort	fen_rfthr;	/* Received frames threshold */
+	ushort	fen_rfcnt;	/* Received frames count */
+} fcc_enet_t;
+
+/* FCC Event/Mask register as used by Ethernet.
+*/
+#define FCC_ENET_GRA	((ushort)0x0080)	/* Graceful stop complete */
+#define FCC_ENET_RXC	((ushort)0x0040)	/* Control Frame Received */
+#define FCC_ENET_TXC	((ushort)0x0020)	/* Out of seq. Tx sent */
+#define FCC_ENET_TXE	((ushort)0x0010)	/* Transmit Error */
+#define FCC_ENET_RXF	((ushort)0x0008)	/* Full frame received */
+#define FCC_ENET_BSY	((ushort)0x0004)	/* Busy.  Rx Frame dropped */
+#define FCC_ENET_TXB	((ushort)0x0002)	/* A buffer was transmitted */
+#define FCC_ENET_RXB	((ushort)0x0001)	/* A buffer was received */
+
+/* FCC Mode Register (FPSMR) as used by Ethernet.
+*/
+#define FCC_PSMR_HBC	((uint)0x80000000)	/* Enable heartbeat */
+#define FCC_PSMR_FC	((uint)0x40000000)	/* Force Collision */
+#define FCC_PSMR_SBT	((uint)0x20000000)	/* Stop backoff timer */
+#define FCC_PSMR_LPB	((uint)0x10000000)	/* Local protect. 1 = FDX */
+#define FCC_PSMR_LCW	((uint)0x08000000)	/* Late collision select */
+#define FCC_PSMR_FDE	((uint)0x04000000)	/* Full Duplex Enable */
+#define FCC_PSMR_MON	((uint)0x02000000)	/* RMON Enable */
+#define FCC_PSMR_PRO	((uint)0x00400000)	/* Promiscuous Enable */
+#define FCC_PSMR_FCE	((uint)0x00200000)	/* Flow Control Enable */
+#define FCC_PSMR_RSH	((uint)0x00100000)	/* Receive Short Frames */
+#define FCC_PSMR_CAM	((uint)0x00000400)	/* CAM enable */
+#define FCC_PSMR_BRO	((uint)0x00000200)	/* Broadcast pkt discard */
+#define FCC_PSMR_ENCRC	((uint)0x00000080)	/* Use 32-bit CRC */
+
+/* IIC parameter RAM.
+*/
+typedef struct iic {
+	ushort	iic_rbase;	/* Rx Buffer descriptor base address */
+	ushort	iic_tbase;	/* Tx Buffer descriptor base address */
+	u_char	iic_rfcr;	/* Rx function code */
+	u_char	iic_tfcr;	/* Tx function code */
+	ushort	iic_mrblr;	/* Max receive buffer length */
+	uint	iic_rstate;	/* Internal */
+	uint	iic_rdp;	/* Internal */
+	ushort	iic_rbptr;	/* Internal */
+	ushort	iic_rbc;	/* Internal */
+	uint	iic_rxtmp;	/* Internal */
+	uint	iic_tstate;	/* Internal */
+	uint	iic_tdp;	/* Internal */
+	ushort	iic_tbptr;	/* Internal */
+	ushort	iic_tbc;	/* Internal */
+	uint	iic_txtmp;	/* Internal */
+} iic_t;
+
+/* SPI parameter RAM.
+*/
+typedef struct spi {
+	ushort	spi_rbase;	/* Rx Buffer descriptor base address */
+	ushort	spi_tbase;	/* Tx Buffer descriptor base address */
+	u_char	spi_rfcr;	/* Rx function code */
+	u_char	spi_tfcr;	/* Tx function code */
+	ushort	spi_mrblr;	/* Max receive buffer length */
+	uint	spi_rstate;	/* Internal */
+	uint	spi_rdp;	/* Internal */
+	ushort	spi_rbptr;	/* Internal */
+	ushort	spi_rbc;	/* Internal */
+	uint	spi_rxtmp;	/* Internal */
+	uint	spi_tstate;	/* Internal */
+	uint	spi_tdp;	/* Internal */
+	ushort	spi_tbptr;	/* Internal */
+	ushort	spi_tbc;	/* Internal */
+	uint	spi_txtmp;	/* Internal */
+	uint	spi_res;	/* Tx temp. */
+	uint	spi_res1[4];	/* SDMA temp. */
+} spi_t;
+
+/* SPI Mode register.
+*/
+#define SPMODE_LOOP	((ushort)0x4000)	/* Loopback */
+#define SPMODE_CI	((ushort)0x2000)	/* Clock Invert */
+#define SPMODE_CP	((ushort)0x1000)	/* Clock Phase */
+#define SPMODE_DIV16	((ushort)0x0800)	/* BRG/16 mode */
+#define SPMODE_REV	((ushort)0x0400)	/* Reversed Data */
+#define SPMODE_MSTR	((ushort)0x0200)	/* SPI Master */
+#define SPMODE_EN	((ushort)0x0100)	/* Enable */
+#define SPMODE_LENMSK	((ushort)0x00f0)	/* character length */
+#define SPMODE_PMMSK	((ushort)0x000f)	/* prescale modulus */
+
+#define SPMODE_LEN(x)	((((x)-1)&0xF)<<4)
+#define SPMODE_PM(x)	((x) &0xF)
+
+#define SPI_EB		((u_char)0x10)		/* big endian byte order */
+
+#define BD_IIC_START	((ushort)0x0400)
+
+/*-----------------------------------------------------------------------
+ * CMXFCR - CMX FCC Clock Route Register                                15-12
+ */
+#define CMXFCR_FC1         0x40000000   /* FCC1 connection              */
+#define CMXFCR_RF1CS_MSK   0x38000000   /* Receive FCC1 Clock Source Mask */
+#define CMXFCR_TF1CS_MSK   0x07000000   /* Transmit FCC1 Clock Source Mask */
+#define CMXFCR_FC2         0x00400000   /* FCC2 connection              */
+#define CMXFCR_RF2CS_MSK   0x00380000   /* Receive FCC2 Clock Source Mask */
+#define CMXFCR_TF2CS_MSK   0x00070000   /* Transmit FCC2 Clock Source Mask */
+#define CMXFCR_FC3         0x00004000   /* FCC3 connection              */
+#define CMXFCR_RF3CS_MSK   0x00003800   /* Receive FCC3 Clock Source Mask */
+#define CMXFCR_TF3CS_MSK   0x00000700   /* Transmit FCC3 Clock Source Mask */
+
+#define CMXFCR_RF1CS_BRG5  0x00000000   /* Receive FCC1 Clock Source is BRG5 */
+#define CMXFCR_RF1CS_BRG6  0x08000000   /* Receive FCC1 Clock Source is BRG6 */
+#define CMXFCR_RF1CS_BRG7  0x10000000   /* Receive FCC1 Clock Source is BRG7 */
+#define CMXFCR_RF1CS_BRG8  0x18000000   /* Receive FCC1 Clock Source is BRG8 */
+#define CMXFCR_RF1CS_CLK9  0x20000000   /* Receive FCC1 Clock Source is CLK9 */
+#define CMXFCR_RF1CS_CLK10 0x28000000   /* Receive FCC1 Clock Source is CLK10 */
+#define CMXFCR_RF1CS_CLK11 0x30000000   /* Receive FCC1 Clock Source is CLK11 */
+#define CMXFCR_RF1CS_CLK12 0x38000000   /* Receive FCC1 Clock Source is CLK12 */
+
+#define CMXFCR_TF1CS_BRG5  0x00000000   /* Transmit FCC1 Clock Source is BRG5 */
+#define CMXFCR_TF1CS_BRG6  0x01000000   /* Transmit FCC1 Clock Source is BRG6 */
+#define CMXFCR_TF1CS_BRG7  0x02000000   /* Transmit FCC1 Clock Source is BRG7 */
+#define CMXFCR_TF1CS_BRG8  0x03000000   /* Transmit FCC1 Clock Source is BRG8 */
+#define CMXFCR_TF1CS_CLK9  0x04000000   /* Transmit FCC1 Clock Source is CLK9 */
+#define CMXFCR_TF1CS_CLK10 0x05000000   /* Transmit FCC1 Clock Source is CLK10 */
+#define CMXFCR_TF1CS_CLK11 0x06000000   /* Transmit FCC1 Clock Source is CLK11 */
+#define CMXFCR_TF1CS_CLK12 0x07000000   /* Transmit FCC1 Clock Source is CLK12 */
+
+#define CMXFCR_RF2CS_BRG5  0x00000000   /* Receive FCC2 Clock Source is BRG5 */
+#define CMXFCR_RF2CS_BRG6  0x00080000   /* Receive FCC2 Clock Source is BRG6 */
+#define CMXFCR_RF2CS_BRG7  0x00100000   /* Receive FCC2 Clock Source is BRG7 */
+#define CMXFCR_RF2CS_BRG8  0x00180000   /* Receive FCC2 Clock Source is BRG8 */
+#define CMXFCR_RF2CS_CLK13 0x00200000   /* Receive FCC2 Clock Source is CLK13 */
+#define CMXFCR_RF2CS_CLK14 0x00280000   /* Receive FCC2 Clock Source is CLK14 */
+#define CMXFCR_RF2CS_CLK15 0x00300000   /* Receive FCC2 Clock Source is CLK15 */
+#define CMXFCR_RF2CS_CLK16 0x00380000   /* Receive FCC2 Clock Source is CLK16 */
+
+#define CMXFCR_TF2CS_BRG5  0x00000000   /* Transmit FCC2 Clock Source is BRG5 */
+#define CMXFCR_TF2CS_BRG6  0x00010000   /* Transmit FCC2 Clock Source is BRG6 */
+#define CMXFCR_TF2CS_BRG7  0x00020000   /* Transmit FCC2 Clock Source is BRG7 */
+#define CMXFCR_TF2CS_BRG8  0x00030000   /* Transmit FCC2 Clock Source is BRG8 */
+#define CMXFCR_TF2CS_CLK13 0x00040000   /* Transmit FCC2 Clock Source is CLK13 */
+#define CMXFCR_TF2CS_CLK14 0x00050000   /* Transmit FCC2 Clock Source is CLK14 */
+#define CMXFCR_TF2CS_CLK15 0x00060000   /* Transmit FCC2 Clock Source is CLK15 */
+#define CMXFCR_TF2CS_CLK16 0x00070000   /* Transmit FCC2 Clock Source is CLK16 */
+
+#define CMXFCR_RF3CS_BRG5  0x00000000   /* Receive FCC3 Clock Source is BRG5 */
+#define CMXFCR_RF3CS_BRG6  0x00000800   /* Receive FCC3 Clock Source is BRG6 */
+#define CMXFCR_RF3CS_BRG7  0x00001000   /* Receive FCC3 Clock Source is BRG7 */
+#define CMXFCR_RF3CS_BRG8  0x00001800   /* Receive FCC3 Clock Source is BRG8 */
+#define CMXFCR_RF3CS_CLK13 0x00002000   /* Receive FCC3 Clock Source is CLK13 */
+#define CMXFCR_RF3CS_CLK14 0x00002800   /* Receive FCC3 Clock Source is CLK14 */
+#define CMXFCR_RF3CS_CLK15 0x00003000   /* Receive FCC3 Clock Source is CLK15 */
+#define CMXFCR_RF3CS_CLK16 0x00003800   /* Receive FCC3 Clock Source is CLK16 */
+
+#define CMXFCR_TF3CS_BRG5  0x00000000   /* Transmit FCC3 Clock Source is BRG5 */
+#define CMXFCR_TF3CS_BRG6  0x00000100   /* Transmit FCC3 Clock Source is BRG6 */
+#define CMXFCR_TF3CS_BRG7  0x00000200   /* Transmit FCC3 Clock Source is BRG7 */
+#define CMXFCR_TF3CS_BRG8  0x00000300   /* Transmit FCC3 Clock Source is BRG8 */
+#define CMXFCR_TF3CS_CLK13 0x00000400   /* Transmit FCC3 Clock Source is CLK13 */
+#define CMXFCR_TF3CS_CLK14 0x00000500   /* Transmit FCC3 Clock Source is CLK14 */
+#define CMXFCR_TF3CS_CLK15 0x00000600   /* Transmit FCC3 Clock Source is CLK15 */
+#define CMXFCR_TF3CS_CLK16 0x00000700   /* Transmit FCC3 Clock Source is CLK16 */
+
+/*-----------------------------------------------------------------------
+ * CMXSCR - CMX SCC Clock Route Register                                15-14
+ */
+#define CMXSCR_GR1         0x80000000   /* Grant Support of SCC1        */
+#define CMXSCR_SC1         0x40000000   /* SCC1 connection              */
+#define CMXSCR_RS1CS_MSK   0x38000000   /* Receive SCC1 Clock Source Mask */
+#define CMXSCR_TS1CS_MSK   0x07000000   /* Transmit SCC1 Clock Source Mask */
+#define CMXSCR_GR2         0x00800000   /* Grant Support of SCC2        */
+#define CMXSCR_SC2         0x00400000   /* SCC2 connection              */
+#define CMXSCR_RS2CS_MSK   0x00380000   /* Receive SCC2 Clock Source Mask */
+#define CMXSCR_TS2CS_MSK   0x00070000   /* Transmit SCC2 Clock Source Mask */
+#define CMXSCR_GR3         0x00008000   /* Grant Support of SCC3        */
+#define CMXSCR_SC3         0x00004000   /* SCC3 connection              */
+#define CMXSCR_RS3CS_MSK   0x00003800   /* Receive SCC3 Clock Source Mask */
+#define CMXSCR_TS3CS_MSK   0x00000700   /* Transmit SCC3 Clock Source Mask */
+#define CMXSCR_GR4         0x00000080   /* Grant Support of SCC4        */
+#define CMXSCR_SC4         0x00000040   /* SCC4 connection              */
+#define CMXSCR_RS4CS_MSK   0x00000038   /* Receive SCC4 Clock Source Mask */
+#define CMXSCR_TS4CS_MSK   0x00000007   /* Transmit SCC4 Clock Source Mask */
+
+#define CMXSCR_RS1CS_BRG1  0x00000000   /* SCC1 Rx Clock Source is BRG1 */
+#define CMXSCR_RS1CS_BRG2  0x08000000   /* SCC1 Rx Clock Source is BRG2 */
+#define CMXSCR_RS1CS_BRG3  0x10000000   /* SCC1 Rx Clock Source is BRG3 */
+#define CMXSCR_RS1CS_BRG4  0x18000000   /* SCC1 Rx Clock Source is BRG4 */
+#define CMXSCR_RS1CS_CLK11 0x20000000   /* SCC1 Rx Clock Source is CLK11 */
+#define CMXSCR_RS1CS_CLK12 0x28000000   /* SCC1 Rx Clock Source is CLK12 */
+#define CMXSCR_RS1CS_CLK3  0x30000000   /* SCC1 Rx Clock Source is CLK3 */
+#define CMXSCR_RS1CS_CLK4  0x38000000   /* SCC1 Rx Clock Source is CLK4 */
+
+#define CMXSCR_TS1CS_BRG1  0x00000000   /* SCC1 Tx Clock Source is BRG1 */
+#define CMXSCR_TS1CS_BRG2  0x01000000   /* SCC1 Tx Clock Source is BRG2 */
+#define CMXSCR_TS1CS_BRG3  0x02000000   /* SCC1 Tx Clock Source is BRG3 */
+#define CMXSCR_TS1CS_BRG4  0x03000000   /* SCC1 Tx Clock Source is BRG4 */
+#define CMXSCR_TS1CS_CLK11 0x04000000   /* SCC1 Tx Clock Source is CLK11 */
+#define CMXSCR_TS1CS_CLK12 0x05000000   /* SCC1 Tx Clock Source is CLK12 */
+#define CMXSCR_TS1CS_CLK3  0x06000000   /* SCC1 Tx Clock Source is CLK3 */
+#define CMXSCR_TS1CS_CLK4  0x07000000   /* SCC1 Tx Clock Source is CLK4 */
+
+#define CMXSCR_RS2CS_BRG1  0x00000000   /* SCC2 Rx Clock Source is BRG1 */
+#define CMXSCR_RS2CS_BRG2  0x00080000   /* SCC2 Rx Clock Source is BRG2 */
+#define CMXSCR_RS2CS_BRG3  0x00100000   /* SCC2 Rx Clock Source is BRG3 */
+#define CMXSCR_RS2CS_BRG4  0x00180000   /* SCC2 Rx Clock Source is BRG4 */
+#define CMXSCR_RS2CS_CLK11 0x00200000   /* SCC2 Rx Clock Source is CLK11 */
+#define CMXSCR_RS2CS_CLK12 0x00280000   /* SCC2 Rx Clock Source is CLK12 */
+#define CMXSCR_RS2CS_CLK3  0x00300000   /* SCC2 Rx Clock Source is CLK3 */
+#define CMXSCR_RS2CS_CLK4  0x00380000   /* SCC2 Rx Clock Source is CLK4 */
+
+#define CMXSCR_TS2CS_BRG1  0x00000000   /* SCC2 Tx Clock Source is BRG1 */
+#define CMXSCR_TS2CS_BRG2  0x00010000   /* SCC2 Tx Clock Source is BRG2 */
+#define CMXSCR_TS2CS_BRG3  0x00020000   /* SCC2 Tx Clock Source is BRG3 */
+#define CMXSCR_TS2CS_BRG4  0x00030000   /* SCC2 Tx Clock Source is BRG4 */
+#define CMXSCR_TS2CS_CLK11 0x00040000   /* SCC2 Tx Clock Source is CLK11 */
+#define CMXSCR_TS2CS_CLK12 0x00050000   /* SCC2 Tx Clock Source is CLK12 */
+#define CMXSCR_TS2CS_CLK3  0x00060000   /* SCC2 Tx Clock Source is CLK3 */
+#define CMXSCR_TS2CS_CLK4  0x00070000   /* SCC2 Tx Clock Source is CLK4 */
+
+#define CMXSCR_RS3CS_BRG1  0x00000000   /* SCC3 Rx Clock Source is BRG1 */
+#define CMXSCR_RS3CS_BRG2  0x00000800   /* SCC3 Rx Clock Source is BRG2 */
+#define CMXSCR_RS3CS_BRG3  0x00001000   /* SCC3 Rx Clock Source is BRG3 */
+#define CMXSCR_RS3CS_BRG4  0x00001800   /* SCC3 Rx Clock Source is BRG4 */
+#define CMXSCR_RS3CS_CLK5  0x00002000   /* SCC3 Rx Clock Source is CLK5 */
+#define CMXSCR_RS3CS_CLK6  0x00002800   /* SCC3 Rx Clock Source is CLK6 */
+#define CMXSCR_RS3CS_CLK7  0x00003000   /* SCC3 Rx Clock Source is CLK7 */
+#define CMXSCR_RS3CS_CLK8  0x00003800   /* SCC3 Rx Clock Source is CLK8 */
+
+#define CMXSCR_TS3CS_BRG1  0x00000000   /* SCC3 Tx Clock Source is BRG1 */
+#define CMXSCR_TS3CS_BRG2  0x00000100   /* SCC3 Tx Clock Source is BRG2 */
+#define CMXSCR_TS3CS_BRG3  0x00000200   /* SCC3 Tx Clock Source is BRG3 */
+#define CMXSCR_TS3CS_BRG4  0x00000300   /* SCC3 Tx Clock Source is BRG4 */
+#define CMXSCR_TS3CS_CLK5  0x00000400   /* SCC3 Tx Clock Source is CLK5 */
+#define CMXSCR_TS3CS_CLK6  0x00000500   /* SCC3 Tx Clock Source is CLK6 */
+#define CMXSCR_TS3CS_CLK7  0x00000600   /* SCC3 Tx Clock Source is CLK7 */
+#define CMXSCR_TS3CS_CLK8  0x00000700   /* SCC3 Tx Clock Source is CLK8 */
+
+#define CMXSCR_RS4CS_BRG1  0x00000000   /* SCC4 Rx Clock Source is BRG1 */
+#define CMXSCR_RS4CS_BRG2  0x00000008   /* SCC4 Rx Clock Source is BRG2 */
+#define CMXSCR_RS4CS_BRG3  0x00000010   /* SCC4 Rx Clock Source is BRG3 */
+#define CMXSCR_RS4CS_BRG4  0x00000018   /* SCC4 Rx Clock Source is BRG4 */
+#define CMXSCR_RS4CS_CLK5  0x00000020   /* SCC4 Rx Clock Source is CLK5 */
+#define CMXSCR_RS4CS_CLK6  0x00000028   /* SCC4 Rx Clock Source is CLK6 */
+#define CMXSCR_RS4CS_CLK7  0x00000030   /* SCC4 Rx Clock Source is CLK7 */
+#define CMXSCR_RS4CS_CLK8  0x00000038   /* SCC4 Rx Clock Source is CLK8 */
+
+#define CMXSCR_TS4CS_BRG1  0x00000000   /* SCC4 Tx Clock Source is BRG1 */
+#define CMXSCR_TS4CS_BRG2  0x00000001   /* SCC4 Tx Clock Source is BRG2 */
+#define CMXSCR_TS4CS_BRG3  0x00000002   /* SCC4 Tx Clock Source is BRG3 */
+#define CMXSCR_TS4CS_BRG4  0x00000003   /* SCC4 Tx Clock Source is BRG4 */
+#define CMXSCR_TS4CS_CLK5  0x00000004   /* SCC4 Tx Clock Source is CLK5 */
+#define CMXSCR_TS4CS_CLK6  0x00000005   /* SCC4 Tx Clock Source is CLK6 */
+#define CMXSCR_TS4CS_CLK7  0x00000006   /* SCC4 Tx Clock Source is CLK7 */
+#define CMXSCR_TS4CS_CLK8  0x00000007   /* SCC4 Tx Clock Source is CLK8 */
+
+#endif /* __CPM_85XX__ */
diff --git a/arch/powerpc/include/asm/e300.h b/arch/powerpc/include/asm/e300.h
new file mode 100644
index 0000000..bfef4df
--- /dev/null
+++ b/arch/powerpc/include/asm/e300.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2004 Freescale Semiconductor, Inc.
+ * Liberty Eran (liberty@freescale.com)
+ */
+
+#ifndef	__E300_H__
+#define __E300_H__
+
+#define PVR_E300C1	0x80830000
+#define PVR_E300C2	0x80840000
+#define PVR_E300C3	0x80850000
+#define PVR_E300C4	0x80860000
+
+/*
+ * Hardware Implementation-Dependent Register 0 (HID0)
+ */
+
+/* #define HID0 1008 already defined in processor.h */
+#define HID0_MASK_MACHINE_CHECK		     0x00000000
+#define HID0_ENABLE_MACHINE_CHECK	     0x80000000
+
+#define HID0_DISABLE_CACHE_PARITY	     0x00000000
+#define HID0_ENABLE_CACHE_PARITY	     0x40000000
+
+#define HID0_DISABLE_ADDRESS_PARITY	     0x00000000 /* on mpc8349ads must be disabled */
+#define HID0_ENABLE_ADDRESS_PARITY	     0x20000000
+
+#define HID0_DISABLE_DATA_PARITY	     0x00000000 /* on mpc8349ads must be disabled */
+#define HID0_ENABLE_DATE_PARITY		     0x10000000
+
+#define HID0_CORE_CLK_OUT		     0x00000000
+#define HID0_CORE_CLK_OUT_DIV_2		     0x08000000
+
+#define HID0_ENABLE_ARTRY_OUT_PRECHARGE      0x00000000 /* on mpc8349ads must be enabled */
+#define HID0_DISABLE_ARTRY_OUT_PRECHARGE     0x01000000
+
+#define HID0_DISABLE_DOSE_MODE		     0x00000000
+#define HID0_ENABLE_DOSE_MODE		     0x00800000
+
+#define HID0_DISABLE_NAP_MODE		     0x00000000
+#define HID0_ENABLE_NAP_MODE		     0x00400000
+
+#define HID0_DISABLE_SLEEP_MODE		     0x00000000
+#define HID0_ENABLE_SLEEP_MODE		     0x00200000
+
+#define HID0_DISABLE_DYNAMIC_POWER_MANAGMENT 0x00000000
+#define HID0_ENABLE_DYNAMIC_POWER_MANAGMENT  0x00100000
+
+#define HID0_SOFT_RESET			     0x00010000
+
+#define HID0_DISABLE_INSTRUCTION_CACHE	     0x00000000
+#define HID0_ENABLE_INSTRUCTION_CACHE	     0x00008000
+
+#define HID0_DISABLE_DATA_CACHE		     0x00000000
+#define HID0_ENABLE_DATA_CACHE		     0x00004000
+
+#define HID0_LOCK_INSTRUCTION_CACHE	     0x00002000
+
+#define HID0_LOCK_DATA_CACHE		     0x00001000
+
+#define HID0_INVALIDATE_INSTRUCTION_CACHE    0x00000800
+
+#define HID0_INVALIDATE_DATA_CACHE	     0x00000400
+
+#define HID0_DISABLE_M_BIT		     0x00000000
+#define HID0_ENABLE_M_BIT		     0x00000080
+
+#define HID0_FBIOB			     0x00000010
+
+#define HID0_DISABLE_ADDRESS_BROADCAST	     0x00000000
+#define HID0_ENABLE_ADDRESS_BROADCAST	     0x00000008
+
+#define HID0_ENABLE_NOOP_DCACHE_INSTRUCTION  0x00000000
+#define HID0_DISABLE_NOOP_DCACHE_INSTRUCTION 0x00000001
+
+/*
+ * Hardware Implementation-Dependent Register 2 (HID2)
+ */
+#define HID2		1011
+
+#define HID2_LET       0x08000000
+#define HID2_HBE       0x00040000
+#define HID2_IWLCK_000 0x00000000 /* no ways locked */
+#define HID2_IWLCK_001 0x00002000 /* way 0 locked */
+#define HID2_IWLCK_010 0x00004000 /* way 0 through way 1 locked */
+#define HID2_IWLCK_011 0x00006000 /* way 0 through way 2 locked */
+#define HID2_IWLCK_100 0x00008000 /* way 0 through way 3 locked */
+#define HID2_IWLCK_101 0x0000A000 /* way 0 through way 4 locked */
+#define HID2_IWLCK_110 0x0000C000 /* way 0 through way 5 locked */
+
+#endif	/* __E300_H__ */
diff --git a/arch/powerpc/include/asm/errno.h b/arch/powerpc/include/asm/errno.h
new file mode 100644
index 0000000..4c82b50
--- /dev/null
+++ b/arch/powerpc/include/asm/errno.h
@@ -0,0 +1 @@
+#include <asm-generic/errno.h>
diff --git a/arch/powerpc/include/asm/fsl_ddr_dimm_params.h b/arch/powerpc/include/asm/fsl_ddr_dimm_params.h
new file mode 100644
index 0000000..55923e0
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_ddr_dimm_params.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2008 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef DDR2_DIMM_PARAMS_H
+#define DDR2_DIMM_PARAMS_H
+
+/* Parameters for a DDR2 dimm computed from the SPD */
+typedef struct dimm_params_s {
+
+	/* DIMM organization parameters */
+	char mpart[19];		/* guaranteed null terminated */
+
+	unsigned int n_ranks;
+	unsigned long long rank_density;
+	unsigned long long capacity;
+	unsigned int data_width;
+	unsigned int primary_sdram_width;
+	unsigned int ec_sdram_width;
+	unsigned int registered_dimm;
+
+	/* SDRAM device parameters */
+	unsigned int n_row_addr;
+	unsigned int n_col_addr;
+	unsigned int edc_config;	/* 0 = none, 1 = parity, 2 = ECC */
+	unsigned int n_banks_per_sdram_device;
+	unsigned int burst_lengths_bitmask;	/* BL=4 bit 2, BL=8 = bit 3 */
+	unsigned int row_density;
+
+	/* used in computing base address of DIMMs */
+	unsigned long long base_address;
+	/* mirrored DIMMs */
+	unsigned int mirrored_dimm;	/* only for ddr3 */
+
+	/* DIMM timing parameters */
+
+	unsigned int mtb_ps;	/* medium timebase ps, only for ddr3 */
+	unsigned int tAA_ps;	/* minimum CAS latency time, only for ddr3 */
+	unsigned int tFAW_ps;	/* four active window delay, only for ddr3 */
+
+	/*
+	 * SDRAM clock periods
+	 * The range for these are 1000-10000 so a short should be sufficient
+	 */
+	unsigned int tCKmin_X_ps;
+	unsigned int tCKmin_X_minus_1_ps;
+	unsigned int tCKmin_X_minus_2_ps;
+	unsigned int tCKmax_ps;
+
+	/* SPD-defined CAS latencies */
+	unsigned int caslat_X;
+	unsigned int caslat_X_minus_1;
+	unsigned int caslat_X_minus_2;
+
+	unsigned int caslat_lowest_derated;	/* Derated CAS latency */
+
+	/* basic timing parameters */
+	unsigned int tRCD_ps;
+	unsigned int tRP_ps;
+	unsigned int tRAS_ps;
+
+	unsigned int tWR_ps;	/* maximum = 63750 ps */
+	unsigned int tWTR_ps;	/* maximum = 63750 ps */
+	unsigned int tRFC_ps;   /* max = 255 ns + 256 ns + .75 ns
+				       = 511750 ps */
+
+	unsigned int tRRD_ps;	/* maximum = 63750 ps */
+	unsigned int tRC_ps;	/* maximum = 254 ns + .75 ns = 254750 ps */
+
+	unsigned int refresh_rate_ps;
+
+	/* DDR3 doesn't need these as below */
+	unsigned int tIS_ps;	/* byte 32, spd->ca_setup */
+	unsigned int tIH_ps;	/* byte 33, spd->ca_hold */
+	unsigned int tDS_ps;	/* byte 34, spd->data_setup */
+	unsigned int tDH_ps;	/* byte 35, spd->data_hold */
+	unsigned int tRTP_ps;	/* byte 38, spd->trtp */
+	unsigned int tDQSQ_max_ps;	/* byte 44, spd->tdqsq */
+	unsigned int tQHS_ps;	/* byte 45, spd->tqhs */
+} dimm_params_t;
+
+extern unsigned int ddr_compute_dimm_parameters(
+					 const generic_spd_eeprom_t *spd,
+					 dimm_params_t *pdimm,
+					 unsigned int dimm_number);
+
+#endif
diff --git a/arch/powerpc/include/asm/fsl_ddr_sdram.h b/arch/powerpc/include/asm/fsl_ddr_sdram.h
new file mode 100644
index 0000000..3216a50
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_ddr_sdram.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2008-2009 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef FSL_DDR_MEMCTL_H
+#define FSL_DDR_MEMCTL_H
+
+/*
+ * Pick a basic DDR Technology.
+ */
+#include <ddr_spd.h>
+
+#define SDRAM_TYPE_DDR1    2
+#define SDRAM_TYPE_DDR2    3
+#define SDRAM_TYPE_LPDDR1  6
+#define SDRAM_TYPE_DDR3    7
+
+#define DDR_BL4		4	/* burst length 4 */
+#define DDR_BC4		DDR_BL4	/* burst chop for ddr3 */
+#define DDR_OTF		6	/* on-the-fly BC4 and BL8 */
+#define DDR_BL8		8	/* burst length 8 */
+
+#if defined(CONFIG_FSL_DDR1)
+#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR	(1)
+typedef ddr1_spd_eeprom_t generic_spd_eeprom_t;
+#ifndef CONFIG_FSL_SDRAM_TYPE
+#define CONFIG_FSL_SDRAM_TYPE	SDRAM_TYPE_DDR1
+#endif
+#elif defined(CONFIG_FSL_DDR2)
+#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR	(3)
+typedef ddr2_spd_eeprom_t generic_spd_eeprom_t;
+#ifndef CONFIG_FSL_SDRAM_TYPE
+#define CONFIG_FSL_SDRAM_TYPE	SDRAM_TYPE_DDR2
+#endif
+#elif defined(CONFIG_FSL_DDR3)
+#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR	(3)	/* FIXME */
+typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
+#ifndef CONFIG_FSL_SDRAM_TYPE
+#define CONFIG_FSL_SDRAM_TYPE	SDRAM_TYPE_DDR3
+#endif
+#endif	/* #if defined(CONFIG_FSL_DDR1) */
+
+/* define bank(chip select) interleaving mode */
+#define FSL_DDR_CS0_CS1			0x40
+#define FSL_DDR_CS2_CS3			0x20
+#define FSL_DDR_CS0_CS1_AND_CS2_CS3	(FSL_DDR_CS0_CS1 | FSL_DDR_CS2_CS3)
+#define FSL_DDR_CS0_CS1_CS2_CS3		(FSL_DDR_CS0_CS1_AND_CS2_CS3 | 0x04)
+
+/* define memory controller interleaving mode */
+#define FSL_DDR_CACHE_LINE_INTERLEAVING	0x0
+#define FSL_DDR_PAGE_INTERLEAVING	0x1
+#define FSL_DDR_BANK_INTERLEAVING	0x2
+#define FSL_DDR_SUPERBANK_INTERLEAVING	0x3
+
+/* DDR_SDRAM_CFG - DDR SDRAM Control Configuration
+ */
+#define SDRAM_CFG_MEM_EN		0x80000000
+#define SDRAM_CFG_SREN			0x40000000
+#define SDRAM_CFG_ECC_EN		0x20000000
+#define SDRAM_CFG_RD_EN			0x10000000
+#define SDRAM_CFG_SDRAM_TYPE_DDR1	0x02000000
+#define SDRAM_CFG_SDRAM_TYPE_DDR2	0x03000000
+#define SDRAM_CFG_SDRAM_TYPE_MASK	0x07000000
+#define SDRAM_CFG_SDRAM_TYPE_SHIFT	24
+#define SDRAM_CFG_DYN_PWR		0x00200000
+#define SDRAM_CFG_32_BE			0x00080000
+#define SDRAM_CFG_8_BE			0x00040000
+#define SDRAM_CFG_NCAP			0x00020000
+#define SDRAM_CFG_2T_EN			0x00008000
+#define SDRAM_CFG_BI			0x00000001
+
+#if defined(CONFIG_P4080)
+#define RD_TO_PRE_MASK		0xf
+#define RD_TO_PRE_SHIFT		13
+#define WR_DATA_DELAY_MASK	0xf
+#define WR_DATA_DELAY_SHIFT	9
+#else
+#define RD_TO_PRE_MASK		0x7
+#define RD_TO_PRE_SHIFT		13
+#define WR_DATA_DELAY_MASK	0x7
+#define WR_DATA_DELAY_SHIFT	10
+#endif
+
+/* Record of register values computed */
+typedef struct fsl_ddr_cfg_regs_s {
+	struct {
+		unsigned int bnds;
+		unsigned int config;
+		unsigned int config_2;
+	} cs[CONFIG_CHIP_SELECTS_PER_CTRL];
+	unsigned int timing_cfg_3;
+	unsigned int timing_cfg_0;
+	unsigned int timing_cfg_1;
+	unsigned int timing_cfg_2;
+	unsigned int ddr_sdram_cfg;
+	unsigned int ddr_sdram_cfg_2;
+	unsigned int ddr_sdram_mode;
+	unsigned int ddr_sdram_mode_2;
+	unsigned int ddr_sdram_md_cntl;
+	unsigned int ddr_sdram_interval;
+	unsigned int ddr_data_init;
+	unsigned int ddr_sdram_clk_cntl;
+	unsigned int ddr_init_addr;
+	unsigned int ddr_init_ext_addr;
+	unsigned int timing_cfg_4;
+	unsigned int timing_cfg_5;
+	unsigned int ddr_zq_cntl;
+	unsigned int ddr_wrlvl_cntl;
+	unsigned int ddr_sr_cntr;
+	unsigned int ddr_sdram_rcw_1;
+	unsigned int ddr_sdram_rcw_2;
+} fsl_ddr_cfg_regs_t;
+
+typedef struct memctl_options_partial_s {
+	unsigned int all_DIMMs_ECC_capable;
+	unsigned int all_DIMMs_tCKmax_ps;
+	unsigned int all_DIMMs_burst_lengths_bitmask;
+	unsigned int all_DIMMs_registered;
+	unsigned int all_DIMMs_unbuffered;
+	/*	unsigned int lowest_common_SPD_caslat; */
+	unsigned int all_DIMMs_minimum_tRCD_ps;
+} memctl_options_partial_t;
+
+/*
+ * Generalized parameters for memory controller configuration,
+ * might be a little specific to the FSL memory controller
+ */
+typedef struct memctl_options_s {
+	/*
+	 * Memory organization parameters
+	 *
+	 * if DIMM is present in the system
+	 * where DIMMs are with respect to chip select
+	 * where chip selects are with respect to memory boundaries
+	 */
+	unsigned int registered_dimm_en;    /* use registered DIMM support */
+
+	/* Options local to a Chip Select */
+	struct cs_local_opts_s {
+		unsigned int auto_precharge;
+		unsigned int odt_rd_cfg;
+		unsigned int odt_wr_cfg;
+	} cs_local_opts[CONFIG_CHIP_SELECTS_PER_CTRL];
+
+	/* Special configurations for chip select */
+	unsigned int memctl_interleaving;
+	unsigned int memctl_interleaving_mode;
+	unsigned int ba_intlv_ctl;
+
+	/* Operational mode parameters */
+	unsigned int ECC_mode;	 /* Use ECC? */
+	/* Initialize ECC using memory controller? */
+	unsigned int ECC_init_using_memctl;
+	unsigned int DQS_config;	/* Use DQS? maybe only with DDR2? */
+	/* SREN - self-refresh during sleep */
+	unsigned int self_refresh_in_sleep;
+	unsigned int dynamic_power;	/* DYN_PWR */
+	/* memory data width to use (16-bit, 32-bit, 64-bit) */
+	unsigned int data_bus_width;
+	unsigned int burst_length;	/* BL4, OTF and BL8 */
+	/* On-The-Fly Burst Chop enable */
+	unsigned int OTF_burst_chop_en;
+	/* mirrior DIMMs for DDR3 */
+	unsigned int mirrored_dimm;
+
+	/* Global Timing Parameters */
+	unsigned int cas_latency_override;
+	unsigned int cas_latency_override_value;
+	unsigned int use_derated_caslat;
+	unsigned int additive_latency_override;
+	unsigned int additive_latency_override_value;
+
+	unsigned int clk_adjust;		/* */
+	unsigned int cpo_override;
+	unsigned int write_data_delay;		/* DQS adjust */
+
+	unsigned int wrlvl_override;
+	unsigned int wrlvl_sample;		/* Write leveling */
+	unsigned int wrlvl_start;
+
+	unsigned int half_strength_driver_enable;
+	unsigned int twoT_en;
+	unsigned int threeT_en;
+	unsigned int bstopre;
+	unsigned int tCKE_clock_pulse_width_ps;	/* tCKE */
+	unsigned int tFAW_window_four_activates_ps;	/* tFAW --  FOUR_ACT */
+
+	/* Rtt impedance */
+	unsigned int rtt_override;		/* rtt_override enable */
+	unsigned int rtt_override_value;	/* that is Rtt_Nom for DDR3 */
+	unsigned int rtt_wr_override_value;	/* this is Rtt_WR for DDR3 */
+
+	/* Automatic self refresh */
+	unsigned int auto_self_refresh_en;
+	unsigned int sr_it;
+	/* ZQ calibration */
+	unsigned int zq_en;
+	/* Write leveling */
+	unsigned int wrlvl_en;
+} memctl_options_t;
+
+extern phys_size_t fsl_ddr_sdram(void);
+#endif
diff --git a/arch/powerpc/include/asm/fsl_dma.h b/arch/powerpc/include/asm/fsl_dma.h
new file mode 100644
index 0000000..1164191
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_dma.h
@@ -0,0 +1,141 @@
+/*
+ * Freescale DMA Controller
+ *
+ * Copyright 2006 Freescale Semiconductor, Inc.
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _ASM_FSL_DMA_H_
+#define _ASM_FSL_DMA_H_
+
+#include <asm/types.h>
+
+#ifdef CONFIG_MPC83xx
+typedef struct fsl_dma {
+	uint	mr;		/* DMA mode register */
+#define FSL_DMA_MR_CS		0x00000001	/* Channel start */
+#define FSL_DMA_MR_CC		0x00000002	/* Channel continue */
+#define FSL_DMA_MR_CTM		0x00000004	/* Channel xfer mode */
+#define FSL_DMA_MR_CTM_DIRECT	0x00000004	/* Direct channel xfer mode */
+#define FSL_DMA_MR_EOTIE	0x00000080	/* End-of-transfer interrupt en */
+#define FSL_DMA_MR_PRC_MASK	0x00000c00	/* PCI read command */
+#define FSL_DMA_MR_SAHE		0x00001000	/* Source addr hold enable */
+#define FSL_DMA_MR_DAHE		0x00002000	/* Dest addr hold enable */
+#define FSL_DMA_MR_SAHTS_MASK	0x0000c000	/* Source addr hold xfer size */
+#define FSL_DMA_MR_DAHTS_MASK	0x00030000	/* Dest addr hold xfer size */
+#define FSL_DMA_MR_EMS_EN	0x00040000	/* Ext master start en */
+#define FSL_DMA_MR_IRQS		0x00080000	/* Interrupt steer */
+#define FSL_DMA_MR_DMSEN	0x00100000	/* Direct mode snooping en */
+#define FSL_DMA_MR_BWC_MASK	0x00e00000	/* Bandwidth/pause ctl */
+#define FSL_DMA_MR_DRCNT	0x0f000000	/* DMA request count */
+	uint	sr;		/* DMA status register */
+#define FSL_DMA_SR_EOCDI	0x00000001	/* End-of-chain/direct interrupt */
+#define FSL_DMA_SR_EOSI		0x00000002	/* End-of-segment interrupt */
+#define FSL_DMA_SR_CB		0x00000004	/* Channel busy */
+#define FSL_DMA_SR_TE		0x00000080	/* Transfer error */
+	uint	cdar;		/* DMA current descriptor address register */
+	char	res0[4];
+	uint	sar;		/* DMA source address register */
+	char	res1[4];
+	uint	dar;		/* DMA destination address register */
+	char	res2[4];
+	uint	bcr;		/* DMA byte count register */
+	uint	ndar;		/* DMA next descriptor address register */
+	uint	gsr;		/* DMA general status register (DMA3 ONLY!) */
+	char	res3[84];
+} fsl_dma_t;
+#else
+typedef struct fsl_dma {
+	uint	mr;		/* DMA mode register */
+#define FSL_DMA_MR_CS		0x00000001	/* Channel start */
+#define FSL_DMA_MR_CC		0x00000002	/* Channel continue */
+#define FSL_DMA_MR_CTM		0x00000004	/* Channel xfer mode */
+#define FSL_DMA_MR_CTM_DIRECT	0x00000004	/* Direct channel xfer mode */
+#define FSL_DMA_MR_CA		0x00000008	/* Channel abort */
+#define FSL_DMA_MR_CDSM		0x00000010
+#define FSL_DMA_MR_XFE		0x00000020	/* Extended features en */
+#define FSL_DMA_MR_EIE		0x00000040	/* Error interrupt en */
+#define FSL_DMA_MR_EOLSIE	0x00000080	/* End-of-lists interrupt en */
+#define FSL_DMA_MR_EOLNIE	0x00000100	/* End-of-links interrupt en */
+#define FSL_DMA_MR_EOSIE	0x00000200	/* End-of-seg interrupt en */
+#define FSL_DMA_MR_SRW		0x00000400	/* Single register write */
+#define FSL_DMA_MR_SAHE		0x00001000	/* Source addr hold enable */
+#define FSL_DMA_MR_DAHE		0x00002000	/* Dest addr hold enable */
+#define FSL_DMA_MR_SAHTS_MASK	0x0000c000	/* Source addr hold xfer size */
+#define FSL_DMA_MR_DAHTS_MASK	0x00030000	/* Dest addr hold xfer size */
+#define FSL_DMA_MR_EMS_EN	0x00040000	/* Ext master start en */
+#define FSL_DMA_MR_EMP_EN	0x00200000	/* Ext master pause en */
+#define FSL_DMA_MR_BWC_MASK	0x0f000000	/* Bandwidth/pause ctl */
+#define FSL_DMA_MR_BWC_DIS	0x0f000000	/* Bandwidth/pause ctl disable */
+	uint	sr;		/* DMA status register */
+#define FSL_DMA_SR_EOLSI	0x00000001	/* End-of-list interrupt */
+#define FSL_DMA_SR_EOSI		0x00000002	/* End-of-segment interrupt */
+#define FSL_DMA_SR_CB		0x00000004	/* Channel busy */
+#define FSL_DMA_SR_EOLNI	0x00000008	/* End-of-links interrupt */
+#define FSL_DMA_SR_PE		0x00000010	/* Programming error */
+#define FSL_DMA_SR_CH		0x00000020	/* Channel halted */
+#define FSL_DMA_SR_TE		0x00000080	/* Transfer error */
+	char	res0[4];
+	uint	clndar;		/* DMA current link descriptor address register */
+	uint	satr;		/* DMA source attributes register */
+#define FSL_DMA_SATR_ESAD_MASK		0x000001ff	/* Extended source addr */
+#define FSL_DMA_SATR_SREAD_NO_SNOOP	0x00040000	/* Read, don't snoop */
+#define FSL_DMA_SATR_SREAD_SNOOP	0x00050000	/* Read, snoop */
+#define FSL_DMA_SATR_SREAD_UNLOCK	0x00070000	/* Read, unlock l2 */
+#define FSL_DMA_SATR_STRAN_MASK		0x00f00000	/* Source interface  */
+#define FSL_DMA_SATR_SSME		0x01000000	/* Source stride en */
+#define FSL_DMA_SATR_SPCIORDER		0x02000000	/* PCI transaction order */
+#define FSL_DMA_SATR_STFLOWLVL_MASK	0x0c000000	/* RIO flow level */
+#define FSL_DMA_SATR_SBPATRMU		0x20000000	/* Bypass ATMU */
+	uint	sar;		/* DMA source address register */
+	uint	datr;		/* DMA destination attributes register */
+#define FSL_DMA_DATR_EDAD_MASK		0x000001ff	/* Extended dest addr */
+#define FSL_DMA_DATR_DWRITE_NO_SNOOP	0x00040000	/* Write, don't snoop */
+#define FSL_DMA_DATR_DWRITE_SNOOP	0x00050000	/* Write, snoop */
+#define FSL_DMA_DATR_DWRITE_ALLOC	0x00060000	/* Write, alloc l2 */
+#define FSL_DMA_DATR_DWRITE_LOCK	0x00070000	/* Write, lock l2 */
+#define FSL_DMA_DATR_DTRAN_MASK		0x00f00000	/* Dest interface  */
+#define FSL_DMA_DATR_DSME		0x01000000	/* Dest stride en */
+#define FSL_DMA_DATR_DPCIORDER		0x02000000	/* PCI transaction order */
+#define FSL_DMA_DATR_DTFLOWLVL_MASK	0x0c000000	/* RIO flow level */
+#define FSL_DMA_DATR_DBPATRMU		0x20000000	/* Bypass ATMU */
+	uint	dar;		/* DMA destination address register */
+	uint	bcr;		/* DMA byte count register */
+	char	res1[4];
+	uint	nlndar;		/* DMA next link descriptor address register */
+	char	res2[8];
+	uint	clabdar;	/* DMA current List - alternate base descriptor address Register */
+	char	res3[4];
+	uint	nlsdar;		/* DMA next list descriptor address register */
+	uint	ssr;		/* DMA source stride register */
+	uint	dsr;		/* DMA destination stride register */
+	char	res4[56];
+} fsl_dma_t;
+#endif /* !CONFIG_MPC83xx */
+
+#ifdef CONFIG_FSL_DMA
+void dma_init(void);
+int dmacpy(phys_addr_t dest, phys_addr_t src, phys_size_t n);
+#if (defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER))
+void dma_meminit(uint val, uint size);
+#endif
+#endif
+
+#endif	/* _ASM_DMA_H_ */
diff --git a/arch/powerpc/include/asm/fsl_i2c.h b/arch/powerpc/include/asm/fsl_i2c.h
new file mode 100644
index 0000000..4f71341
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_i2c.h
@@ -0,0 +1,86 @@
+/*
+ * Freescale I2C Controller
+ *
+ * Copyright 2006 Freescale Semiconductor, Inc.
+ *
+ * Based on earlier versions by Gleb Natapov <gnatapov@mrv.com>,
+ * Xianghua Xiao <x.xiao@motorola.com>, Eran Liberty (liberty@freescale.com),
+ * and Jeff Brown.
+ * Some bits are taken from linux driver writen by adrian@humboldt.co.uk.
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _ASM_FSL_I2C_H_
+#define _ASM_FSL_I2C_H_
+
+#include <asm/types.h>
+
+typedef struct fsl_i2c {
+
+	u8 adr;		/* I2C slave address */
+	u8 res0[3];
+#define I2C_ADR		0xFE
+#define I2C_ADR_SHIFT	1
+#define I2C_ADR_RES	~(I2C_ADR)
+
+	u8 fdr;		/* I2C frequency divider register */
+	u8 res1[3];
+#define IC2_FDR		0x3F
+#define IC2_FDR_SHIFT	0
+#define IC2_FDR_RES	~(IC2_FDR)
+
+	u8 cr;		/* I2C control redister	*/
+	u8 res2[3];
+#define I2C_CR_MEN	0x80
+#define I2C_CR_MIEN	0x40
+#define I2C_CR_MSTA	0x20
+#define I2C_CR_MTX	0x10
+#define I2C_CR_TXAK	0x08
+#define I2C_CR_RSTA	0x04
+#define I2C_CR_BCST	0x01
+
+	u8 sr;		/* I2C status register */
+	u8 res3[3];
+#define I2C_SR_MCF	0x80
+#define I2C_SR_MAAS	0x40
+#define I2C_SR_MBB	0x20
+#define I2C_SR_MAL	0x10
+#define I2C_SR_BCSTM	0x08
+#define I2C_SR_SRW	0x04
+#define I2C_SR_MIF	0x02
+#define I2C_SR_RXAK	0x01
+
+	u8 dr;		/* I2C data register */
+	u8 res4[3];
+#define I2C_DR		0xFF
+#define I2C_DR_SHIFT	0
+#define I2C_DR_RES	~(I2C_DR)
+
+	u8 dfsrr;	/* I2C digital filter sampling rate register */
+	u8 res5[3];
+#define I2C_DFSRR	0x3F
+#define I2C_DFSRR_SHIFT	0
+#define I2C_DFSRR_RES	~(I2C_DR)
+
+	/* Fill out the reserved block */
+	u8 res6[0xE8];
+} fsl_i2c_t;
+
+#endif	/* _ASM_I2C_H_ */
diff --git a/arch/powerpc/include/asm/fsl_law.h b/arch/powerpc/include/asm/fsl_law.h
new file mode 100644
index 0000000..34c56a2
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_law.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2008-2009 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
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef _FSL_LAW_H_
+#define _FSL_LAW_H_
+
+#include <asm/io.h>
+
+#define LAW_EN	0x80000000
+
+#define SET_LAW_ENTRY(idx, a, sz, trgt) \
+	{ .index = idx, .addr = a, .size = sz, .trgt_id = trgt }
+
+#define SET_LAW(a, sz, trgt) \
+	{ .index = -1, .addr = a, .size = sz, .trgt_id = trgt }
+
+enum law_size {
+	LAW_SIZE_4K = 0xb,
+	LAW_SIZE_8K,
+	LAW_SIZE_16K,
+	LAW_SIZE_32K,
+	LAW_SIZE_64K,
+	LAW_SIZE_128K,
+	LAW_SIZE_256K,
+	LAW_SIZE_512K,
+	LAW_SIZE_1M,
+	LAW_SIZE_2M,
+	LAW_SIZE_4M,
+	LAW_SIZE_8M,
+	LAW_SIZE_16M,
+	LAW_SIZE_32M,
+	LAW_SIZE_64M,
+	LAW_SIZE_128M,
+	LAW_SIZE_256M,
+	LAW_SIZE_512M,
+	LAW_SIZE_1G,
+	LAW_SIZE_2G,
+	LAW_SIZE_4G,
+	LAW_SIZE_8G,
+	LAW_SIZE_16G,
+	LAW_SIZE_32G,
+};
+
+#define law_size_bits(sz)	(__ilog2_u64(sz) - 1)
+
+#ifdef CONFIG_FSL_CORENET
+enum law_trgt_if {
+	LAW_TRGT_IF_PCIE_1 = 0x00,
+	LAW_TRGT_IF_PCIE_2 = 0x01,
+	LAW_TRGT_IF_PCIE_3 = 0x02,
+	LAW_TRGT_IF_RIO_1 = 0x08,
+	LAW_TRGT_IF_RIO_2 = 0x09,
+
+	LAW_TRGT_IF_DDR_1 = 0x10,
+	LAW_TRGT_IF_DDR_2 = 0x11,	/* 2nd controller */
+	LAW_TRGT_IF_DDR_INTRLV = 0x14,
+
+	LAW_TRGT_IF_BMAN = 0x18,
+	LAW_TRGT_IF_DCSR = 0x1d,
+	LAW_TRGT_IF_LBC = 0x1f,
+	LAW_TRGT_IF_QMAN = 0x3c,
+};
+#define LAW_TRGT_IF_DDR		LAW_TRGT_IF_DDR_1
+#else
+enum law_trgt_if {
+	LAW_TRGT_IF_PCI = 0x00,
+	LAW_TRGT_IF_PCI_2 = 0x01,
+#ifndef CONFIG_MPC8641
+	LAW_TRGT_IF_PCIE_1 = 0x02,
+#endif
+#if !defined(CONFIG_MPC8572) && !defined(CONFIG_P2020)
+	LAW_TRGT_IF_PCIE_3 = 0x03,
+#endif
+	LAW_TRGT_IF_LBC = 0x04,
+	LAW_TRGT_IF_CCSR = 0x08,
+	LAW_TRGT_IF_DDR_INTRLV = 0x0b,
+	LAW_TRGT_IF_RIO = 0x0c,
+	LAW_TRGT_IF_RIO_2 = 0x0d,
+	LAW_TRGT_IF_DDR = 0x0f,
+	LAW_TRGT_IF_DDR_2 = 0x16,	/* 2nd controller */
+};
+#define LAW_TRGT_IF_DDR_1	LAW_TRGT_IF_DDR
+#define LAW_TRGT_IF_PCI_1	LAW_TRGT_IF_PCI
+#define LAW_TRGT_IF_PCIX	LAW_TRGT_IF_PCI
+#define LAW_TRGT_IF_PCIE_2	LAW_TRGT_IF_PCI_2
+
+#ifdef CONFIG_MPC8641
+#define LAW_TRGT_IF_PCIE_1	LAW_TRGT_IF_PCI
+#endif
+
+#if defined(CONFIG_MPC8572) || defined(CONFIG_P2020)
+#define LAW_TRGT_IF_PCIE_3	LAW_TRGT_IF_PCI
+#endif
+#endif /* CONFIG_FSL_CORENET */
+
+struct law_entry {
+	int index;
+	phys_addr_t addr;
+	enum law_size size;
+	enum law_trgt_if trgt_id;
+};
+
+extern void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id);
+extern int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id);
+extern int set_last_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id);
+extern int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id);
+extern struct law_entry find_law(phys_addr_t addr);
+extern void disable_law(u8 idx);
+extern void init_laws(void);
+extern void print_laws(void);
+
+/* define in board code */
+extern struct law_entry law_table[];
+extern int num_law_entries;
+#endif
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
new file mode 100644
index 0000000..5723de6
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -0,0 +1,496 @@
+/*
+ * Copyright (C) 2004-2008 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 __ASM_PPC_FSL_LBC_H
+#define __ASM_PPC_FSL_LBC_H
+
+#include <config.h>
+
+/* BR - Base Registers
+ */
+#define BR0				0x5000		/* Register offset to immr */
+#define BR1				0x5008
+#define BR2				0x5010
+#define BR3				0x5018
+#define BR4				0x5020
+#define BR5				0x5028
+#define BR6				0x5030
+#define BR7				0x5038
+
+#define BR_BA				0xFFFF8000
+#define BR_BA_SHIFT			15
+#define BR_XBA				0x00006000
+#define BR_XBA_SHIFT			13
+#define BR_PS				0x00001800
+#define BR_PS_SHIFT			11
+#define BR_PS_8				0x00000800	/* Port Size 8 bit */
+#define BR_PS_16			0x00001000	/* Port Size 16 bit */
+#define BR_PS_32			0x00001800	/* Port Size 32 bit */
+#define BR_DECC				0x00000600
+#define BR_DECC_SHIFT			9
+#define BR_DECC_OFF			0x00000000
+#define BR_DECC_CHK			0x00000200
+#define BR_DECC_CHK_GEN			0x00000400
+#define BR_WP				0x00000100
+#define BR_WP_SHIFT			8
+#define BR_MSEL				0x000000E0
+#define BR_MSEL_SHIFT			5
+#define BR_MS_GPCM			0x00000000	/* GPCM */
+#define BR_MS_FCM			0x00000020	/* FCM */
+#ifdef CONFIG_MPC83xx
+#define BR_MS_SDRAM			0x00000060	/* SDRAM */
+#elif defined(CONFIG_MPC85xx)
+#define BR_MS_SDRAM			0x00000000	/* SDRAM */
+#endif
+#define BR_MS_UPMA			0x00000080	/* UPMA */
+#define BR_MS_UPMB			0x000000A0	/* UPMB */
+#define BR_MS_UPMC			0x000000C0	/* UPMC */
+#if !defined(CONFIG_MPC834x)
+#define BR_ATOM				0x0000000C
+#define BR_ATOM_SHIFT			2
+#endif
+#define BR_V				0x00000001
+#define BR_V_SHIFT			0
+
+#define UPMA			0
+#define UPMB			1
+#define UPMC			2
+
+#if defined(CONFIG_MPC834x)
+#define BR_RES				~(BR_BA | BR_PS | BR_DECC | BR_WP | BR_MSEL | BR_V)
+#else
+#define BR_RES				~(BR_BA | BR_PS | BR_DECC | BR_WP | BR_MSEL | BR_ATOM | BR_V)
+#endif
+
+/* Convert an address into the right format for the BR registers */
+#if defined(CONFIG_PHYS_64BIT) && !defined(CONFIG_FSL_ELBC)
+#define BR_PHYS_ADDR(x)	((unsigned long)((x & 0x0ffff8000ULL) | \
+					 ((x & 0x300000000ULL) >> 19)))
+#else
+#define BR_PHYS_ADDR(x) (x & 0xffff8000)
+#endif
+
+/* OR - Option Registers
+ */
+#define OR0				0x5004		/* Register offset to immr */
+#define OR1				0x500C
+#define OR2				0x5014
+#define OR3				0x501C
+#define OR4				0x5024
+#define OR5				0x502C
+#define OR6				0x5034
+#define OR7				0x503C
+
+#define OR_GPCM_AM			0xFFFF8000
+#define OR_GPCM_AM_SHIFT		15
+#define OR_GPCM_XAM			0x00006000
+#define OR_GPCM_XAM_SHIFT		13
+#define OR_GPCM_BCTLD			0x00001000
+#define OR_GPCM_BCTLD_SHIFT		12
+#define OR_GPCM_CSNT			0x00000800
+#define OR_GPCM_CSNT_SHIFT		11
+#define OR_GPCM_ACS			0x00000600
+#define OR_GPCM_ACS_SHIFT		9
+#define OR_GPCM_ACS_DIV2		0x00000600
+#define OR_GPCM_ACS_DIV4		0x00000400
+#define OR_GPCM_XACS			0x00000100
+#define OR_GPCM_XACS_SHIFT		8
+#define OR_GPCM_SCY			0x000000F0
+#define OR_GPCM_SCY_SHIFT		4
+#define OR_GPCM_SCY_1			0x00000010
+#define OR_GPCM_SCY_2			0x00000020
+#define OR_GPCM_SCY_3			0x00000030
+#define OR_GPCM_SCY_4			0x00000040
+#define OR_GPCM_SCY_5			0x00000050
+#define OR_GPCM_SCY_6			0x00000060
+#define OR_GPCM_SCY_7			0x00000070
+#define OR_GPCM_SCY_8			0x00000080
+#define OR_GPCM_SCY_9			0x00000090
+#define OR_GPCM_SCY_10			0x000000a0
+#define OR_GPCM_SCY_11			0x000000b0
+#define OR_GPCM_SCY_12			0x000000c0
+#define OR_GPCM_SCY_13			0x000000d0
+#define OR_GPCM_SCY_14			0x000000e0
+#define OR_GPCM_SCY_15			0x000000f0
+#define OR_GPCM_SETA			0x00000008
+#define OR_GPCM_SETA_SHIFT		3
+#define OR_GPCM_TRLX			0x00000004
+#define OR_GPCM_TRLX_SHIFT		2
+#define OR_GPCM_EHTR			0x00000002
+#define OR_GPCM_EHTR_SHIFT		1
+#define OR_GPCM_EAD			0x00000001
+#define OR_GPCM_EAD_SHIFT		0
+
+/* helpers to convert values into an OR address mask (GPCM mode) */
+#define P2SZ_TO_AM(s)	((~((s) - 1)) & 0xffff8000)	/* must be pow of 2 */
+#define MEG_TO_AM(m)	P2SZ_TO_AM((m) << 20)
+
+#define OR_FCM_AM			0xFFFF8000
+#define OR_FCM_AM_SHIFT				15
+#define OR_FCM_XAM			0x00006000
+#define OR_FCM_XAM_SHIFT		13
+#define OR_FCM_BCTLD			0x00001000
+#define OR_FCM_BCTLD_SHIFT			12
+#define OR_FCM_PGS			0x00000400
+#define OR_FCM_PGS_SHIFT			10
+#define OR_FCM_CSCT			0x00000200
+#define OR_FCM_CSCT_SHIFT			 9
+#define OR_FCM_CST			0x00000100
+#define OR_FCM_CST_SHIFT			 8
+#define OR_FCM_CHT			0x00000080
+#define OR_FCM_CHT_SHIFT			 7
+#define OR_FCM_SCY			0x00000070
+#define OR_FCM_SCY_SHIFT			 4
+#define OR_FCM_SCY_1			0x00000010
+#define OR_FCM_SCY_2			0x00000020
+#define OR_FCM_SCY_3			0x00000030
+#define OR_FCM_SCY_4			0x00000040
+#define OR_FCM_SCY_5			0x00000050
+#define OR_FCM_SCY_6			0x00000060
+#define OR_FCM_SCY_7			0x00000070
+#define OR_FCM_RST			0x00000008
+#define OR_FCM_RST_SHIFT			 3
+#define OR_FCM_TRLX			0x00000004
+#define OR_FCM_TRLX_SHIFT			 2
+#define OR_FCM_EHTR			0x00000002
+#define OR_FCM_EHTR_SHIFT			 1
+
+#define OR_UPM_AM			0xFFFF8000
+#define OR_UPM_AM_SHIFT			15
+#define OR_UPM_XAM			0x00006000
+#define OR_UPM_XAM_SHIFT		13
+#define OR_UPM_BCTLD			0x00001000
+#define OR_UPM_BCTLD_SHIFT		12
+#define OR_UPM_BI			0x00000100
+#define OR_UPM_BI_SHIFT			8
+#define OR_UPM_TRLX			0x00000004
+#define OR_UPM_TRLX_SHIFT		2
+#define OR_UPM_EHTR			0x00000002
+#define OR_UPM_EHTR_SHIFT		1
+#define OR_UPM_EAD			0x00000001
+#define OR_UPM_EAD_SHIFT		0
+
+#define OR_SDRAM_AM			0xFFFF8000
+#define OR_SDRAM_AM_SHIFT		15
+#define OR_SDRAM_XAM			0x00006000
+#define OR_SDRAM_XAM_SHIFT		13
+#define OR_SDRAM_COLS			0x00001C00
+#define OR_SDRAM_COLS_SHIFT		10
+#define OR_SDRAM_ROWS			0x000001C0
+#define OR_SDRAM_ROWS_SHIFT		6
+#define OR_SDRAM_PMSEL			0x00000020
+#define OR_SDRAM_PMSEL_SHIFT		5
+#define OR_SDRAM_EAD			0x00000001
+#define OR_SDRAM_EAD_SHIFT		0
+
+#define OR_AM_32KB			0xFFFF8000
+#define OR_AM_64KB			0xFFFF0000
+#define OR_AM_128KB			0xFFFE0000
+#define OR_AM_256KB			0xFFFC0000
+#define OR_AM_512KB			0xFFF80000
+#define OR_AM_1MB			0xFFF00000
+#define OR_AM_2MB			0xFFE00000
+#define OR_AM_4MB			0xFFC00000
+#define OR_AM_8MB			0xFF800000
+#define OR_AM_16MB			0xFF000000
+#define OR_AM_32MB			0xFE000000
+#define OR_AM_64MB			0xFC000000
+#define OR_AM_128MB			0xF8000000
+#define OR_AM_256MB			0xF0000000
+#define OR_AM_512MB			0xE0000000
+#define OR_AM_1GB			0xC0000000
+#define OR_AM_2GB			0x80000000
+#define OR_AM_4GB			0x00000000
+
+/* MxMR - UPM Machine A/B/C Mode Registers
+ */
+#define MxMR_MAD_MSK		0x0000003f /* Machine Address Mask	   */
+#define MxMR_TLFx_MSK		0x000003c0 /* Refresh Loop Field Mask	   */
+#define MxMR_WLFx_MSK		0x00003c00 /* Write Loop Field Mask	   */
+#define MxMR_WLFx_1X		0x00000400 /*	executed 1 time		   */
+#define MxMR_WLFx_2X		0x00000800 /*	executed 2 times	   */
+#define MxMR_WLFx_3X		0x00000c00 /*	executed 3 times	   */
+#define MxMR_WLFx_4X		0x00001000 /*	executed 4 times	   */
+#define MxMR_WLFx_5X		0x00001400 /*	executed 5 times	   */
+#define MxMR_WLFx_6X		0x00001800 /*	executed 6 times	   */
+#define MxMR_WLFx_7X		0x00001c00 /*	executed 7 times	   */
+#define MxMR_WLFx_8X		0x00002000 /*	executed 8 times	   */
+#define MxMR_WLFx_9X		0x00002400 /*	executed 9 times	   */
+#define MxMR_WLFx_10X		0x00002800 /*	executed 10 times	   */
+#define MxMR_WLFx_11X		0x00002c00 /*	executed 11 times	   */
+#define MxMR_WLFx_12X		0x00003000 /*	executed 12 times	   */
+#define MxMR_WLFx_13X		0x00003400 /*	executed 13 times	   */
+#define MxMR_WLFx_14X		0x00003800 /*	executed 14 times	   */
+#define MxMR_WLFx_15X		0x00003c00 /*	executed 15 times	   */
+#define MxMR_WLFx_16X		0x00000000 /*	executed 16 times	   */
+#define MxMR_RLFx_MSK		0x0003c000 /* Read Loop Field Mask	   */
+#define MxMR_GPL_x4DIS		0x00040000 /* GPL_A4 Ouput Line Disable	   */
+#define MxMR_G0CLx_MSK		0x00380000 /* General Line 0 Control Mask  */
+#define MxMR_DSx_1_CYCL		0x00000000 /* 1 cycle Disable Period	   */
+#define MxMR_DSx_2_CYCL		0x00400000 /* 2 cycle Disable Period	   */
+#define MxMR_DSx_3_CYCL		0x00800000 /* 3 cycle Disable Period	   */
+#define MxMR_DSx_4_CYCL		0x00c00000 /* 4 cycle Disable Period	   */
+#define MxMR_DSx_MSK		0x00c00000 /* Disable Timer Period Mask	   */
+#define MxMR_AMx_MSK		0x07000000 /* Addess Multiplex Size Mask   */
+#define MxMR_OP_NORM		0x00000000 /* Normal Operation		   */
+#define MxMR_OP_WARR		0x10000000 /* Write to Array		   */
+#define MxMR_OP_RARR		0x20000000 /* Read from Array		   */
+#define MxMR_OP_RUNP		0x30000000 /* Run Pattern		   */
+#define MxMR_OP_MSK		0x30000000 /* Command Opcode Mask	   */
+#define MxMR_RFEN		0x40000000 /* Refresh Enable		   */
+#define MxMR_BSEL		0x80000000 /* Bus Select		   */
+
+#define LBLAWAR_EN			0x80000000
+#define LBLAWAR_4KB			0x0000000B
+#define LBLAWAR_8KB			0x0000000C
+#define LBLAWAR_16KB			0x0000000D
+#define LBLAWAR_32KB			0x0000000E
+#define LBLAWAR_64KB			0x0000000F
+#define LBLAWAR_128KB			0x00000010
+#define LBLAWAR_256KB			0x00000011
+#define LBLAWAR_512KB			0x00000012
+#define LBLAWAR_1MB			0x00000013
+#define LBLAWAR_2MB			0x00000014
+#define LBLAWAR_4MB			0x00000015
+#define LBLAWAR_8MB			0x00000016
+#define LBLAWAR_16MB			0x00000017
+#define LBLAWAR_32MB			0x00000018
+#define LBLAWAR_64MB			0x00000019
+#define LBLAWAR_128MB			0x0000001A
+#define LBLAWAR_256MB			0x0000001B
+#define LBLAWAR_512MB			0x0000001C
+#define LBLAWAR_1GB			0x0000001D
+#define LBLAWAR_2GB			0x0000001E
+
+/* LBCR - Local Bus Configuration Register
+ */
+#define LBCR_LDIS			0x80000000
+#define LBCR_LDIS_SHIFT			31
+#define LBCR_BCTLC			0x00C00000
+#define LBCR_BCTLC_SHIFT		22
+#define LBCR_LPBSE			0x00020000
+#define LBCR_LPBSE_SHIFT		17
+#define LBCR_EPAR			0x00010000
+#define LBCR_EPAR_SHIFT			16
+#define LBCR_BMT			0x0000FF00
+#define LBCR_BMT_SHIFT			8
+
+/* LCRR - Clock Ratio Register
+ */
+#define LCRR_DBYP			0x80000000
+#define LCRR_DBYP_SHIFT			31
+#define LCRR_BUFCMDC			0x30000000
+#define LCRR_BUFCMDC_SHIFT		28
+#define LCRR_BUFCMDC_1			0x10000000
+#define LCRR_BUFCMDC_2			0x20000000
+#define LCRR_BUFCMDC_3			0x30000000
+#define LCRR_BUFCMDC_4			0x00000000
+#define LCRR_ECL			0x03000000
+#define LCRR_ECL_SHIFT			24
+#define LCRR_ECL_4			0x00000000
+#define LCRR_ECL_5			0x01000000
+#define LCRR_ECL_6			0x02000000
+#define LCRR_ECL_7			0x03000000
+#define LCRR_EADC			0x00030000
+#define LCRR_EADC_SHIFT			16
+#define LCRR_EADC_1			0x00010000
+#define LCRR_EADC_2			0x00020000
+#define LCRR_EADC_3			0x00030000
+#define LCRR_EADC_4			0x00000000
+/* CLKDIV is five bits only on 8536, 8572, and 8610, so far, but the fifth bit
+ * should always be zero on older parts that have a four bit CLKDIV.
+ */
+#define LCRR_CLKDIV			0x0000001F
+#define LCRR_CLKDIV_SHIFT		0
+#if defined(CONFIG_MPC83xx) || defined (CONFIG_MPC8540) || \
+    defined(CONFIG_MPC8541) || defined (CONFIG_MPC8555) || \
+    defined(CONFIG_MPC8560)
+#define LCRR_CLKDIV_2			0x00000002
+#define LCRR_CLKDIV_4			0x00000004
+#define LCRR_CLKDIV_8			0x00000008
+#elif defined(CONFIG_FSL_CORENET)
+#define LCRR_CLKDIV_8			0x00000002
+#define LCRR_CLKDIV_16			0x00000004
+#define LCRR_CLKDIV_32			0x00000008
+#else
+#define LCRR_CLKDIV_4			0x00000002
+#define LCRR_CLKDIV_8			0x00000004
+#define LCRR_CLKDIV_16			0x00000008
+#endif
+
+/* LTEDR - Transfer Error Check Disable Register
+ */
+#define LTEDR_BMD	0x80000000 /* Bus monitor disable				*/
+#define LTEDR_PARD	0x20000000 /* Parity error checking disabled			*/
+#define LTEDR_WPD	0x04000000 /* Write protect error checking diable		*/
+#define LTEDR_WARA	0x00800000 /* Write-after-read-atomic error checking diable	*/
+#define LTEDR_RAWA	0x00400000 /* Read-after-write-atomic error checking disable	*/
+#define LTEDR_CSD	0x00080000 /* Chip select error checking disable		*/
+
+/* FMR - Flash Mode Register
+ */
+#define FMR_CWTO               0x0000F000
+#define FMR_CWTO_SHIFT         12
+#define FMR_BOOT               0x00000800
+#define FMR_ECCM               0x00000100
+#define FMR_AL                 0x00000030
+#define FMR_AL_SHIFT           4
+#define FMR_OP                 0x00000003
+#define FMR_OP_SHIFT           0
+
+/* FIR - Flash Instruction Register
+ */
+#define FIR_OP0                        0xF0000000
+#define FIR_OP0_SHIFT          28
+#define FIR_OP1                        0x0F000000
+#define FIR_OP1_SHIFT          24
+#define FIR_OP2                        0x00F00000
+#define FIR_OP2_SHIFT          20
+#define FIR_OP3                        0x000F0000
+#define FIR_OP3_SHIFT          16
+#define FIR_OP4                        0x0000F000
+#define FIR_OP4_SHIFT          12
+#define FIR_OP5                        0x00000F00
+#define FIR_OP5_SHIFT          8
+#define FIR_OP6                        0x000000F0
+#define FIR_OP6_SHIFT          4
+#define FIR_OP7                        0x0000000F
+#define FIR_OP7_SHIFT          0
+#define FIR_OP_NOP             0x0 /* No operation and end of sequence */
+#define FIR_OP_CA              0x1 /* Issue current column address */
+#define FIR_OP_PA              0x2 /* Issue current block+page address */
+#define FIR_OP_UA              0x3 /* Issue user defined address */
+#define FIR_OP_CM0             0x4 /* Issue command from FCR[CMD0] */
+#define FIR_OP_CM1             0x5 /* Issue command from FCR[CMD1] */
+#define FIR_OP_CM2             0x6 /* Issue command from FCR[CMD2] */
+#define FIR_OP_CM3             0x7 /* Issue command from FCR[CMD3] */
+#define FIR_OP_WB              0x8 /* Write FBCR bytes from FCM buffer */
+#define FIR_OP_WS              0x9 /* Write 1 or 2 bytes from MDR[AS] */
+#define FIR_OP_RB              0xA /* Read FBCR bytes to FCM buffer */
+#define FIR_OP_RS              0xB /* Read 1 or 2 bytes to MDR[AS] */
+#define FIR_OP_CW0             0xC /* Wait then issue FCR[CMD0] */
+#define FIR_OP_CW1             0xD /* Wait then issue FCR[CMD1] */
+#define FIR_OP_RBW             0xE /* Wait then read FBCR bytes */
+#define FIR_OP_RSW             0xF /* Wait then read 1 or 2 bytes */
+
+/* FCR - Flash Command Register
+ */
+#define FCR_CMD0               0xFF000000
+#define FCR_CMD0_SHIFT         24
+#define FCR_CMD1               0x00FF0000
+#define FCR_CMD1_SHIFT         16
+#define FCR_CMD2               0x0000FF00
+#define FCR_CMD2_SHIFT         8
+#define FCR_CMD3               0x000000FF
+#define FCR_CMD3_SHIFT         0
+/* FBAR - Flash Block Address Register
+ */
+#define FBAR_BLK               0x00FFFFFF
+
+/* FPAR - Flash Page Address Register
+ */
+#define FPAR_SP_PI             0x00007C00
+#define FPAR_SP_PI_SHIFT       10
+#define FPAR_SP_MS             0x00000200
+#define FPAR_SP_CI             0x000001FF
+#define FPAR_SP_CI_SHIFT       0
+#define FPAR_LP_PI             0x0003F000
+#define FPAR_LP_PI_SHIFT       12
+#define FPAR_LP_MS             0x00000800
+#define FPAR_LP_CI             0x000007FF
+#define FPAR_LP_CI_SHIFT       0
+
+/* LSDMR - SDRAM Machine Mode Register
+ */
+#define LSDMR_RFEN	(1 << (31 -  1))
+#define LSDMR_BSMA1516	(3 << (31 - 10))
+#define LSDMR_BSMA1617	(4 << (31 - 10))
+#define LSDMR_RFCR5	(3 << (31 - 16))
+#define LSDMR_RFCR16	(7 << (31 - 16))
+#define LSDMR_PRETOACT3 (3 << (31 - 19))
+#define LSDMR_PRETOACT7	(7 << (31 - 19))
+#define LSDMR_ACTTORW3	(3 << (31 - 22))
+#define LSDMR_ACTTORW7	(7 << (31 - 22))
+#define LSDMR_ACTTORW6	(6 << (31 - 22))
+#define LSDMR_BL8	(1 << (31 - 23))
+#define LSDMR_WRC2	(2 << (31 - 27))
+#define LSDMR_WRC4	(0 << (31 - 27))
+#define LSDMR_BUFCMD	(1 << (31 - 29))
+#define LSDMR_CL3	(3 << (31 - 31))
+
+#define LSDMR_OP_NORMAL	(0 << (31 - 4))
+#define LSDMR_OP_ARFRSH	(1 << (31 - 4))
+#define LSDMR_OP_SRFRSH	(2 << (31 - 4))
+#define LSDMR_OP_MRW	(3 << (31 - 4))
+#define LSDMR_OP_PRECH	(4 << (31 - 4))
+#define LSDMR_OP_PCHALL	(5 << (31 - 4))
+#define LSDMR_OP_ACTBNK	(6 << (31 - 4))
+#define LSDMR_OP_RWINV	(7 << (31 - 4))
+
+/* LTESR - Transfer Error Status Register
+ */
+#define LTESR_BM               0x80000000
+#define LTESR_FCT              0x40000000
+#define LTESR_PAR              0x20000000
+#define LTESR_WP               0x04000000
+#define LTESR_ATMW             0x00800000
+#define LTESR_ATMR             0x00400000
+#define LTESR_CS               0x00080000
+#define LTESR_CC               0x00000001
+
+#ifndef __ASSEMBLY__
+/*
+ * Local Bus Controller Registers.
+ */
+typedef struct lbus_bank {
+	u32 br;                 /* Base Register */
+	u32 or;                 /* Option Register */
+} lbus_bank_t;
+
+typedef struct fsl_lbus {
+	lbus_bank_t bank[8];
+	u8 res0[0x28];
+	u32 mar;                /* UPM Address Register */
+	u8 res1[0x4];
+	u32 mamr;               /* UPMA Mode Register */
+	u32 mbmr;               /* UPMB Mode Register */
+	u32 mcmr;               /* UPMC Mode Register */
+	u8 res2[0x8];
+	u32 mrtpr;              /* Memory Refresh Timer Prescaler Register */
+	u32 mdr;                /* UPM Data Register */
+	u8 res3[0x4];
+	u32 lsor;               /* Special Operation Initiation Register */
+	u32 lsdmr;              /* SDRAM Mode Register */
+	u8 res4[0x8];
+	u32 lurt;               /* UPM Refresh Timer */
+	u32 lsrt;               /* SDRAM Refresh Timer */
+	u8 res5[0x8];
+	u32 ltesr;              /* Transfer Error Status Register */
+	u32 ltedr;              /* Transfer Error Disable Register */
+	u32 lteir;              /* Transfer Error Interrupt Register */
+	u32 lteatr;             /* Transfer Error Attributes Register */
+	u32 ltear;               /* Transfer Error Address Register */
+	u8 res6[0xC];
+	u32 lbcr;               /* Configuration Register */
+	u32 lcrr;               /* Clock Ratio Register */
+	u8 res7[0x8];
+	u32 fmr;                /* Flash Mode Register */
+	u32 fir;                /* Flash Instruction Register */
+	u32 fcr;                /* Flash Command Register */
+	u32 fbar;               /* Flash Block Addr Register */
+	u32 fpar;               /* Flash Page Addr Register */
+	u32 fbcr;               /* Flash Byte Count Register */
+	u8 res8[0xF08];
+} fsl_lbus_t;
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_PPC_FSL_LBC_H */
diff --git a/arch/powerpc/include/asm/fsl_pci.h b/arch/powerpc/include/asm/fsl_pci.h
new file mode 100644
index 0000000..db61e7e
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_pci.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2007,2009 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef __FSL_PCI_H_
+#define __FSL_PCI_H_
+
+#include <asm/fsl_law.h>
+
+int is_fsl_pci_cfg(enum law_trgt_if trgt, u32 io_sel);
+
+int fsl_setup_hose(struct pci_controller *hose, unsigned long addr);
+int fsl_is_pci_agent(struct pci_controller *hose);
+void fsl_pci_init(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data);
+void fsl_pci_config_unlock(struct pci_controller *hose);
+void ft_fsl_pci_setup(void *blob, const char *pci_alias,
+			struct pci_controller *hose);
+
+/*
+ * Common PCI/PCIE Register structure for mpc85xx and mpc86xx
+ */
+
+/*
+ * PCI Translation Registers
+ */
+typedef struct pci_outbound_window {
+	u32	potar;		/* 0x00 - Address */
+	u32	potear;		/* 0x04 - Address Extended */
+	u32	powbar;		/* 0x08 - Window Base Address */
+	u32	res1;
+	u32	powar;		/* 0x10 - Window Attributes */
+#define POWAR_EN	0x80000000
+#define POWAR_IO_READ	0x00080000
+#define POWAR_MEM_READ	0x00040000
+#define POWAR_IO_WRITE	0x00008000
+#define POWAR_MEM_WRITE	0x00004000
+	u32	res2[3];
+} pot_t;
+
+typedef struct pci_inbound_window {
+	u32	pitar;		/* 0x00 - Address */
+	u32	res1;
+	u32	piwbar;		/* 0x08 - Window Base Address */
+	u32	piwbear;	/* 0x0c - Window Base Address Extended */
+	u32	piwar;		/* 0x10 - Window Attributes */
+#define PIWAR_EN		0x80000000
+#define PIWAR_PF		0x20000000
+#define PIWAR_LOCAL		0x00f00000
+#define PIWAR_READ_SNOOP	0x00050000
+#define PIWAR_WRITE_SNOOP	0x00005000
+	u32	res2[3];
+} pit_t;
+
+/* PCI/PCI Express Registers */
+typedef struct ccsr_pci {
+	u32	cfg_addr;	/* 0x000 - PCI Configuration Address Register */
+	u32	cfg_data;	/* 0x004 - PCI Configuration Data Register */
+	u32	int_ack;	/* 0x008 - PCI Interrupt Acknowledge Register */
+	u32	out_comp_to;	/* 0x00C - PCI Outbound Completion Timeout Register */
+	u32	out_conf_to;	/* 0x010 - PCI Configuration Timeout Register */
+	u32	config;		/* 0x014 - PCIE CONFIG Register */
+	char	res2[8];
+	u32	pme_msg_det;	/* 0x020 - PCIE PME & message detect register */
+	u32	pme_msg_dis;	/* 0x024 - PCIE PME & message disable register */
+	u32	pme_msg_int_en;	/* 0x028 - PCIE PME & message interrupt enable register */
+	u32	pm_command;	/* 0x02c - PCIE PM Command register */
+	char	res4[3016];	/*     (- #xbf8	 #x30)3016 */
+	u32	block_rev1;	/* 0xbf8 - PCIE Block Revision register 1 */
+	u32	block_rev2;	/* 0xbfc - PCIE Block Revision register 2 */
+
+	pot_t	pot[5];		/* 0xc00 - 0xc9f Outbound ATMU's 0, 1, 2, 3, and 4 */
+	u32	res5[64];
+	pit_t	pit[3];		/* 0xda0 - 0xdff Inbound ATMU's 3, 2, and 1 */
+#define PIT3 0
+#define PIT2 1
+#define PIT1 2
+
+#if 0
+	u32	potar0;		/* 0xc00 - PCI Outbound Transaction Address Register 0 */
+	u32	potear0;	/* 0xc04 - PCI Outbound Translation Extended Address Register 0 */
+	char	res5[8];
+	u32	powar0;		/* 0xc10 - PCI Outbound Window Attributes Register 0 */
+	char	res6[12];
+	u32	potar1;		/* 0xc20 - PCI Outbound Transaction Address Register 1 */
+	u32	potear1;	/* 0xc24 - PCI Outbound Translation Extended Address Register 1 */
+	u32	powbar1;	/* 0xc28 - PCI Outbound Window Base Address Register 1 */
+	char	res7[4];
+	u32	powar1;		/* 0xc30 - PCI Outbound Window Attributes Register 1 */
+	char	res8[12];
+	u32	potar2;		/* 0xc40 - PCI Outbound Transaction Address Register 2 */
+	u32	potear2;	/* 0xc44 - PCI Outbound Translation Extended Address Register 2 */
+	u32	powbar2;	/* 0xc48 - PCI Outbound Window Base Address Register 2 */
+	char	res9[4];
+	u32	powar2;		/* 0xc50 - PCI Outbound Window Attributes Register 2 */
+	char	res10[12];
+	u32	potar3;		/* 0xc60 - PCI Outbound Transaction Address Register 3 */
+	u32	potear3;	/* 0xc64 - PCI Outbound Translation Extended Address Register 3 */
+	u32	powbar3;	/* 0xc68 - PCI Outbound Window Base Address Register 3 */
+	char	res11[4];
+	u32	powar3;		/* 0xc70 - PCI Outbound Window Attributes Register 3 */
+	char	res12[12];
+	u32	potar4;		/* 0xc80 - PCI Outbound Transaction Address Register 4 */
+	u32	potear4;	/* 0xc84 - PCI Outbound Translation Extended Address Register 4 */
+	u32	powbar4;	/* 0xc88 - PCI Outbound Window Base Address Register 4 */
+	char	res13[4];
+	u32	powar4;		/* 0xc90 - PCI Outbound Window Attributes Register 4 */
+	char	res14[268];
+	u32	pitar3;		/* 0xda0 - PCI Inbound Translation Address Register 3 */
+	char	res15[4];
+	u32	piwbar3;	/* 0xda8 - PCI Inbound Window Base Address Register 3 */
+	u32	piwbear3;	/* 0xdac - PCI Inbound Window Base Extended Address Register 3 */
+	u32	piwar3;		/* 0xdb0 - PCI Inbound Window Attributes Register 3 */
+	char	res16[12];
+	u32	pitar2;		/* 0xdc0 - PCI Inbound Translation Address Register 2 */
+	char	res17[4];
+	u32	piwbar2;	/* 0xdc8 - PCI Inbound Window Base Address Register 2 */
+	u32	piwbear2;	/* 0xdcc - PCI Inbound Window Base Extended Address Register 2 */
+	u32	piwar2;		/* 0xdd0 - PCI Inbound Window Attributes Register 2 */
+	char	res18[12];
+	u32	pitar1;		/* 0xde0 - PCI Inbound Translation Address Register 1 */
+	char	res19[4];
+	u32	piwbar1;	/* 0xde8 - PCI Inbound Window Base Address Register 1 */
+	char	res20[4];
+	u32	piwar1;		/* 0xdf0 - PCI Inbound Window Attributes Register 1 */
+	char	res21[12];
+#endif
+	u32	pedr;		/* 0xe00 - PCI Error Detect Register */
+	u32	pecdr;		/* 0xe04 - PCI Error Capture Disable Register */
+	u32	peer;		/* 0xe08 - PCI Error Interrupt Enable Register */
+	u32	peattrcr;	/* 0xe0c - PCI Error Attributes Capture Register */
+	u32	peaddrcr;	/* 0xe10 - PCI Error Address Capture Register */
+/*	u32	perr_disr	 * 0xe10 - PCIE Erorr Disable Register */
+	u32	peextaddrcr;	/* 0xe14 - PCI	Error Extended Address Capture Register */
+	u32	pedlcr;		/* 0xe18 - PCI Error Data Low Capture Register */
+	u32	pedhcr;		/* 0xe1c - PCI Error Error Data High Capture Register */
+	u32	gas_timr;	/* 0xe20 - PCI Gasket Timer Register */
+/*	u32	perr_cap_stat;	 * 0xe20 - PCIE Error Capture Status Register */
+	char	res22[4];
+	u32	perr_cap0;	/* 0xe28 - PCIE Error Capture Register 0 */
+	u32	perr_cap1;	/* 0xe2c - PCIE Error Capture Register 1 */
+	u32	perr_cap2;	/* 0xe30 - PCIE Error Capture Register 2 */
+	u32	perr_cap3;	/* 0xe34 - PCIE Error Capture Register 3 */
+	char	res23[200];
+	u32	pdb_stat;	/* 0xf00 - PCIE Debug Status */
+	char	res24[252];
+} ccsr_fsl_pci_t;
+
+struct fsl_pci_info {
+	unsigned long	regs;
+	pci_addr_t	mem_bus;
+	phys_size_t	mem_phys;
+	pci_size_t	mem_size;
+	pci_addr_t	io_bus;
+	phys_size_t	io_phys;
+	pci_size_t	io_size;
+	int		pci_num;
+};
+
+int fsl_pci_init_port(struct fsl_pci_info *pci_info,
+				struct pci_controller *hose, int busno);
+
+#define SET_STD_PCI_INFO(x, num) \
+{			\
+	x.regs = CONFIG_SYS_PCI##num##_ADDR;	\
+	x.mem_bus = CONFIG_SYS_PCI##num##_MEM_BUS; \
+	x.mem_phys = CONFIG_SYS_PCI##num##_MEM_PHYS; \
+	x.mem_size = CONFIG_SYS_PCI##num##_MEM_SIZE; \
+	x.io_bus = CONFIG_SYS_PCI##num##_IO_BUS; \
+	x.io_phys = CONFIG_SYS_PCI##num##_IO_PHYS; \
+	x.io_size = CONFIG_SYS_PCI##num##_IO_SIZE; \
+	x.pci_num = num; \
+}
+
+#define SET_STD_PCIE_INFO(x, num) \
+{			\
+	x.regs = CONFIG_SYS_PCIE##num##_ADDR;	\
+	x.mem_bus = CONFIG_SYS_PCIE##num##_MEM_BUS; \
+	x.mem_phys = CONFIG_SYS_PCIE##num##_MEM_PHYS; \
+	x.mem_size = CONFIG_SYS_PCIE##num##_MEM_SIZE; \
+	x.io_bus = CONFIG_SYS_PCIE##num##_IO_BUS; \
+	x.io_phys = CONFIG_SYS_PCIE##num##_IO_PHYS; \
+	x.io_size = CONFIG_SYS_PCIE##num##_IO_SIZE; \
+	x.pci_num = num; \
+}
+
+#endif
diff --git a/arch/powerpc/include/asm/fsl_serdes.h b/arch/powerpc/include/asm/fsl_serdes.h
new file mode 100644
index 0000000..6da4b6f
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_serdes.h
@@ -0,0 +1,21 @@
+#ifndef __FSL_SERDES_H
+#define __FSL_SERDES_H
+
+#include <config.h>
+
+#define FSL_SERDES_CLK_100		(0 << 28)
+#define FSL_SERDES_CLK_125		(1 << 28)
+#define FSL_SERDES_CLK_150		(3 << 28)
+#define FSL_SERDES_PROTO_SATA		0
+#define FSL_SERDES_PROTO_PEX		1
+#define FSL_SERDES_PROTO_PEX_X2		2
+#define FSL_SERDES_PROTO_SGMII		3
+#define FSL_SERDES_VDD_1V		1
+
+#ifdef CONFIG_FSL_SERDES
+extern void fsl_setup_serdes(u32 offset, char proto, u32 rfcks, char vdd);
+#else
+static void fsl_setup_serdes(u32 offset, char proto, u32 rfcks, char vdd) {}
+#endif /* CONFIG_FSL_SERDES */
+
+#endif /* __FSL_SERDES_H */
diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
new file mode 100644
index 0000000..d3dd44e
--- /dev/null
+++ b/arch/powerpc/include/asm/global_data.h
@@ -0,0 +1,198 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef	__ASM_GBL_DATA_H
+#define __ASM_GBL_DATA_H
+
+#include "config.h"
+#include "asm/types.h"
+
+/*
+ * The following data structure is placed in some memory wich is
+ * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
+ * some locked parts of the data cache) to allow for a minimum set of
+ * global variables during system initialization (until we have set
+ * up the memory controller so that we can use RAM).
+ *
+ * Keep it *SMALL* and remember to set CONFIG_SYS_GBL_DATA_SIZE > sizeof(gd_t)
+ */
+
+typedef	struct	global_data {
+	bd_t		*bd;
+	unsigned long	flags;
+	unsigned long	baudrate;
+	unsigned long	cpu_clk;	/* CPU clock in Hz! */
+	unsigned long	bus_clk;
+#if defined(CONFIG_8xx)
+	unsigned long	brg_clk;
+#endif
+#if defined(CONFIG_CPM2)
+	/* There are many clocks on the MPC8260 - see page 9-5 */
+	unsigned long	vco_out;
+	unsigned long	cpm_clk;
+	unsigned long	scc_clk;
+	unsigned long	brg_clk;
+#ifdef CONFIG_PCI
+	unsigned long	pci_clk;
+#endif
+#endif
+	unsigned long   mem_clk;
+#if defined(CONFIG_MPC83xx)
+	/* There are other clocks in the MPC83XX */
+	u32 csb_clk;
+#if defined(CONFIG_MPC834x) || defined(CONFIG_MPC831x) || defined(CONFIG_MPC837x)
+	u32 tsec1_clk;
+	u32 tsec2_clk;
+	u32 usbdr_clk;
+#endif
+#if defined (CONFIG_MPC834x)
+	u32 usbmph_clk;
+#endif /* CONFIG_MPC834x */
+#if defined(CONFIG_MPC8315)
+	u32 tdm_clk;
+#endif
+	u32 core_clk;
+	u32 enc_clk;
+	u32 lbiu_clk;
+	u32 lclk_clk;
+	u32 pci_clk;
+#if defined(CONFIG_MPC837x) || defined(CONFIG_MPC831x)
+	u32 pciexp1_clk;
+	u32 pciexp2_clk;
+#endif
+#if defined(CONFIG_MPC837x) || defined(CONFIG_MPC8315)
+	u32 sata_clk;
+#endif
+#if defined(CONFIG_MPC8360)
+	u32  mem_sec_clk;
+#endif /* CONFIG_MPC8360 */
+#endif
+#if defined(CONFIG_FSL_ESDHC)
+	u32 sdhc_clk;
+#endif
+#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
+	u32 lbc_clk;
+	void *cpu;
+#endif /* CONFIG_MPC85xx || CONFIG_MPC86xx */
+#if defined(CONFIG_MPC83xx) || defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
+	u32 i2c1_clk;
+	u32 i2c2_clk;
+#endif
+#if defined(CONFIG_QE)
+	u32 qe_clk;
+	u32 brg_clk;
+	uint mp_alloc_base;
+	uint mp_alloc_top;
+#endif /* CONFIG_QE */
+#if defined(CONFIG_FSL_LAW)
+	u32 used_laws;
+#endif
+#if defined(CONFIG_E500)
+	u32 used_tlb_cams[(CONFIG_SYS_NUM_TLBCAMS+31)/32];
+#endif
+#if defined(CONFIG_MPC5xxx)
+	unsigned long	ipb_clk;
+	unsigned long	pci_clk;
+#endif
+#if defined(CONFIG_MPC512X)
+	u32 ips_clk;
+	u32 csb_clk;
+	u32 pci_clk;
+#endif /* CONFIG_MPC512X */
+#if defined(CONFIG_MPC8220)
+	unsigned long   bExtUart;
+	unsigned long   inp_clk;
+	unsigned long   pci_clk;
+	unsigned long   vco_clk;
+	unsigned long   pev_clk;
+	unsigned long   flb_clk;
+#endif
+	phys_size_t	ram_size;	/* RAM size */
+	unsigned long	reset_status;	/* reset status register at boot	*/
+#if defined(CONFIG_MPC83xx)
+	unsigned long	arbiter_event_attributes;
+	unsigned long	arbiter_event_address;
+#endif
+	unsigned long	env_addr;	/* Address  of Environment struct	*/
+	unsigned long	env_valid;	/* Checksum of Environment valid?	*/
+	unsigned long	have_console;	/* serial_init() was called		*/
+#if defined(CONFIG_SYS_ALLOC_DPRAM) || defined(CONFIG_CPM2)
+	unsigned int	dp_alloc_base;
+	unsigned int	dp_alloc_top;
+#endif
+#if defined(CONFIG_4xx)
+	u32  uart_clk;
+#endif /* CONFIG_4xx */
+#if defined(CONFIG_SYS_GT_6426x)
+	unsigned int	mirror_hack[16];
+#endif
+#if defined(CONFIG_A3000)	|| \
+    defined(CONFIG_HIDDEN_DRAGON)  || \
+    defined(CONFIG_MUSENKI)	||  \
+    defined(CONFIG_SANDPOINT)
+	void *		console_addr;
+#endif
+	unsigned long	relocaddr;	/* Start address of U-Boot in RAM */
+#if defined(CONFIG_LCD) || defined(CONFIG_VIDEO)
+	unsigned long	fb_base;	/* Base address of framebuffer memory	*/
+#endif
+#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER)
+	unsigned long	post_log_word;  /* Record POST activities */
+	unsigned long	post_init_f_time;  /* When post_init_f started */
+#endif
+#ifdef CONFIG_BOARD_TYPES
+	unsigned long	board_type;
+#endif
+#ifdef CONFIG_MODEM_SUPPORT
+	unsigned long do_mdm_init;
+	unsigned long be_quiet;
+#endif
+#if defined(CONFIG_LWMON) || defined(CONFIG_LWMON5)
+	unsigned long kbd_status;
+#endif
+#if defined(CONFIG_WD_MAX_RATE)
+	unsigned long long wdt_last;	/* trace watch-dog triggering rate */
+#endif
+	void		**jt;		/* jump table */
+} gd_t;
+
+/*
+ * Global Data Flags
+ */
+#define	GD_FLG_RELOC	0x00001		/* Code was relocated to RAM		*/
+#define	GD_FLG_DEVINIT	0x00002		/* Devices have been initialized	*/
+#define	GD_FLG_SILENT	0x00004		/* Silent mode				*/
+#define	GD_FLG_POSTFAIL	0x00008		/* Critical POST test failed		*/
+#define	GD_FLG_POSTSTOP	0x00010		/* POST seqeunce aborted		*/
+#define	GD_FLG_LOGINIT	0x00020		/* Log Buffer has been initialized	*/
+#define GD_FLG_DISABLE_CONSOLE	0x00040		/* Disable console (in & out)	 */
+
+#if 1
+#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r2")
+#else /* We could use plain global data, but the resulting code is bigger */
+#define XTRN_DECLARE_GLOBAL_DATA_PTR	extern
+#define DECLARE_GLOBAL_DATA_PTR     XTRN_DECLARE_GLOBAL_DATA_PTR \
+				    gd_t *gd
+#endif
+
+#endif /* __ASM_GBL_DATA_H */
diff --git a/arch/powerpc/include/asm/gpio.h b/arch/powerpc/include/asm/gpio.h
new file mode 100644
index 0000000..23e29b1
--- /dev/null
+++ b/arch/powerpc/include/asm/gpio.h
@@ -0,0 +1,119 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __ASM_PPC_GPIO_H
+#define __ASM_PPC_GPIO_H
+
+#include <asm/types.h>
+
+/* 4xx PPC's have 2 GPIO controllers */
+#if defined(CONFIG_405EZ) ||					\
+	defined(CONFIG_440EP) || defined(CONFIG_440GR) ||	\
+	defined(CONFIG_440EPX) || defined(CONFIG_440GRX) ||	\
+	defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define GPIO_GROUP_MAX	2
+#else
+#define GPIO_GROUP_MAX	1
+#endif
+
+/* GPIO controller */
+struct ppc4xx_gpio {
+	u32 or;		/* Output Control */
+	u32 tcr;	/* Tri-State Control */
+	u32 osl;	/* Output Select 16..31 */
+	u32 osh;	/* Output Select 0..15 */
+	u32 tsl;	/* Tri-State Select 16..31 */
+	u32 tsh;	/* Tri-State Select 0..15 */
+	u32 odr;	/* Open Drain */
+	u32 ir;		/* Input */
+	u32 rr1;	/* Receive Register 1 */
+	u32 rr2;	/* Receive Register 2 */
+	u32 rr3;	/* Receive Register 3 */
+	u32 reserved;
+	u32 is1l;	/* Input Select 1 16..31 */
+	u32 is1h;	/* Input Select 1 0..15 */
+	u32 is2l;	/* Input Select 2 16..31 */
+	u32 is2h;	/* Input Select 2 0..15 */
+	u32 is3l;	/* Input Select 3 16..31 */
+	u32 is3h;	/* Input Select 3 0..15 */
+};
+
+/* Offsets */
+#define GPIOx_OR	0x00		/* GPIO Output Register */
+#define GPIOx_TCR	0x04		/* GPIO Three-State Control Register */
+#define GPIOx_OSL	0x08		/* GPIO Output Select Register (Bits 0-31) */
+#define GPIOx_OSH	0x0C		/* GPIO Ouput Select Register (Bits 32-63) */
+#define GPIOx_TSL	0x10		/* GPIO Three-State Select Register (Bits 0-31) */
+#define GPIOx_TSH	0x14		/* GPIO Three-State Select Register  (Bits 32-63) */
+#define GPIOx_ODR	0x18		/* GPIO Open drain Register */
+#define GPIOx_IR	0x1C		/* GPIO Input Register */
+#define GPIOx_RR1	0x20		/* GPIO Receive Register 1 */
+#define GPIOx_RR2	0x24		/* GPIO Receive Register 2 */
+#define GPIOx_RR3	0x28		/* GPIO Receive Register 3 */
+#define GPIOx_IS1L	0x30		/* GPIO Input Select Register 1 (Bits 0-31) */
+#define GPIOx_IS1H	0x34		/* GPIO Input Select Register 1 (Bits 32-63) */
+#define GPIOx_IS2L	0x38		/* GPIO Input Select Register 2 (Bits 0-31) */
+#define GPIOx_IS2H	0x3C		/* GPIO Input Select Register 2 (Bits 32-63) */
+#define GPIOx_IS3L	0x40		/* GPIO Input Select Register 3 (Bits 0-31) */
+#define GPIOx_IS3H	0x44		/* GPIO Input Select Register 3 (Bits 32-63) */
+
+#define GPIO_OR(x)	(x+GPIOx_OR)	/* GPIO Output Register */
+#define GPIO_TCR(x)	(x+GPIOx_TCR)	/* GPIO Three-State Control Register */
+#define GPIO_OS(x)	(x+GPIOx_OSL)	/* GPIO Output Select Register High or Low */
+#define GPIO_TS(x)	(x+GPIOx_TSL)	/* GPIO Three-state Control Reg High or Low */
+#define GPIO_IS1(x)	(x+GPIOx_IS1L)	/* GPIO Input register1 High or Low */
+#define GPIO_IS2(x)	(x+GPIOx_IS2L)	/* GPIO Input register2 High or Low */
+#define GPIO_IS3(x)	(x+GPIOx_IS3L)	/* GPIO Input register3 High or Low */
+
+#define GPIO0		0
+#define GPIO1		1
+
+#define GPIO_MAX	32
+#define GPIO_ALT1_SEL	0x40000000
+#define GPIO_ALT2_SEL	0x80000000
+#define GPIO_ALT3_SEL	0xc0000000
+#define GPIO_IN_SEL	0x40000000
+#define GPIO_MASK	0xc0000000
+
+#define GPIO_VAL(gpio)	(0x80000000 >> (gpio))
+
+#ifndef __ASSEMBLY__
+typedef enum gpio_select { GPIO_SEL, GPIO_ALT1, GPIO_ALT2, GPIO_ALT3 } gpio_select_t;
+typedef enum gpio_driver { GPIO_DIS, GPIO_IN, GPIO_OUT, GPIO_BI } gpio_driver_t;
+typedef enum gpio_out	 { GPIO_OUT_0, GPIO_OUT_1, GPIO_OUT_NO_CHG } gpio_out_t;
+
+typedef struct {
+	unsigned long	add;	/* gpio core base address	*/
+	gpio_driver_t	in_out;	/* Driver Setting		*/
+	gpio_select_t	alt_nb;	/* Selected Alternate		*/
+	gpio_out_t	out_val;/* Default Output Value		*/
+} gpio_param_s;
+#endif
+
+void gpio_config(int pin, int in_out, int gpio_alt, int out_val);
+void gpio_write_bit(int pin, int val);
+int gpio_read_out_bit(int pin);
+int gpio_read_in_bit(int pin);
+void gpio_set_chip_configuration(void);
+
+#endif /* __ASM_PPC_GPIO_H */
diff --git a/arch/powerpc/include/asm/immap_512x.h b/arch/powerpc/include/asm/immap_512x.h
new file mode 100644
index 0000000..95350fd
--- /dev/null
+++ b/arch/powerpc/include/asm/immap_512x.h
@@ -0,0 +1,1246 @@
+/*
+ * (C) Copyright 2007-2009 DENX Software Engineering
+ *
+ * MPC512x Internal Memory Map
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Based on the MPC83xx header.
+ */
+
+#ifndef __IMMAP_512x__
+#define __IMMAP_512x__
+
+#include <asm/types.h>
+#if defined(CONFIG_E300)
+#include <asm/e300.h>
+#endif
+
+/*
+ * System reset offset (PowerPC standard)
+ */
+#define EXC_OFF_SYS_RESET	0x0100
+#define	_START_OFFSET		EXC_OFF_SYS_RESET
+
+#define SPR_5121E		0x80180000
+
+/*
+ * IMMRBAR - Internal Memory Register Base Address
+ */
+#define CONFIG_DEFAULT_IMMR	0xFF400000	/* Default IMMR base address */
+#define IMMRBAR			0x0000		/* Register offset to immr */
+#define IMMRBAR_BASE_ADDR	0xFFF00000	/* Base address mask */
+#define IMMRBAR_RES		~(IMMRBAR_BASE_ADDR)
+
+
+#ifndef __ASSEMBLY__
+typedef struct law512x {
+	u32 bar;	/* Base Addr Register */
+	u32 ar;		/* Attributes Register */
+} law512x_t;
+
+/*
+ * System configuration registers
+ */
+typedef struct sysconf512x {
+	u32 immrbar;		/* Internal memory map base address register */
+	u8 res0[0x1c];
+	u32 lpbaw;		/* LP Boot Access Window */
+	u32 lpcs0aw;		/* LP CS0 Access Window */
+	u32 lpcs1aw;		/* LP CS1 Access Window */
+	u32 lpcs2aw;		/* LP CS2 Access Window */
+	u32 lpcs3aw;		/* LP CS3 Access Window */
+	u32 lpcs4aw;		/* LP CS4 Access Window */
+	u32 lpcs5aw;		/* LP CS5 Access Window */
+	u32 lpcs6aw;		/* LP CS6 Access Window */
+	u32 lpcs7aw;		/* LP CS7 Access Window */
+	u8 res1[0x1c];
+	law512x_t pcilaw[3];	/* PCI Local Access Window 0-2 Registers */
+	u8 res2[0x28];
+	law512x_t ddrlaw;	/* DDR Local Access Window */
+	u8 res3[0x18];
+	u32 mbxbar;		/* MBX Base Address */
+	u32 srambar;		/* SRAM Base Address */
+	u32 nfcbar;		/* NFC Base Address */
+	u8 res4[0x34];
+	u32 spridr;		/* System Part and Revision ID Register */
+	u32 spcr;		/* System Priority Configuration Register */
+	u8 res5[0xf8];
+} sysconf512x_t;
+
+#define LAWBAR_BAR	0xFFFFF000	/* Base address mask */
+
+/*
+ * Watch Dog Timer (WDT) Registers
+ */
+typedef struct wdt512x {
+	u8 res0[4];
+	u32 swcrr;		/* System watchdog control register */
+	u32 swcnr;		/* System watchdog count register */
+	u8 res1[2];
+	u16 swsrr;		/* System watchdog service register */
+	u8 res2[0xF0];
+} wdt512x_t;
+
+/*
+ * RTC Module Registers
+ */
+typedef struct rtclk512x {
+	u8 fixme[0x100];
+} rtclk512x_t;
+
+/*
+ * General Purpose Timer
+ */
+typedef struct gpt512x {
+	u8 fixme[0x100];
+} gpt512x_t;
+
+/*
+ * Integrated Programmable Interrupt Controller
+ */
+typedef struct ipic512x {
+	u8 fixme[0x100];
+} ipic512x_t;
+
+/*
+ * System Arbiter Registers
+ */
+typedef struct arbiter512x {
+	u32 acr;		/* Arbiter Configuration Register */
+	u32 atr;		/* Arbiter Timers Register */
+	u32 ater;		/* Arbiter Transfer Error Register */
+	u32 aer;		/* Arbiter Event Register */
+	u32 aidr;		/* Arbiter Interrupt Definition Register */
+	u32 amr;		/* Arbiter Mask Register */
+	u32 aeatr;		/* Arbiter Event Attributes Register */
+	u32 aeadr;		/* Arbiter Event Address Register */
+	u32 aerr;		/* Arbiter Event Response Register */
+	u8 res1[0xDC];
+} arbiter512x_t;
+
+/*
+ * Reset Module
+ */
+typedef struct reset512x {
+	u32 rcwl;		/* Reset Configuration Word Low Register */
+	u32 rcwh;		/* Reset Configuration Word High Register */
+	u8 res0[8];
+	u32 rsr;		/* Reset Status Register */
+	u32 rmr;		/* Reset Mode Register */
+	u32 rpr;		/* Reset protection Register */
+	u32 rcr;		/* Reset Control Register */
+	u32 rcer;		/* Reset Control Enable Register */
+	u8 res1[0xDC];
+} reset512x_t;
+
+/* RSR - Reset Status Register */
+#define RSR_SWSR	0x00002000	/* software soft reset */
+#define RSR_SWHR	0x00001000	/* software hard reset */
+#define RSR_JHRS	0x00000200	/* jtag hreset */
+#define RSR_JSRS	0x00000100	/* jtag sreset status */
+#define RSR_CSHR	0x00000010	/* checkstop reset status */
+#define RSR_SWRS	0x00000008	/* software watchdog reset status */
+#define RSR_BMRS	0x00000004	/* bus monitop reset status */
+#define RSR_SRS		0x00000002	/* soft reset status */
+#define RSR_HRS		0x00000001	/* hard reset status */
+#define RSR_RES		~(RSR_SWSR | RSR_SWHR |\
+			 RSR_JHRS | RSR_JSRS | RSR_CSHR | RSR_SWRS |\
+			 RSR_BMRS | RSR_SRS | RSR_HRS)
+
+/* RMR - Reset Mode Register */
+#define RMR_CSRE	0x00000001	/* checkstop reset enable */
+#define RMR_CSRE_SHIFT	0
+#define RMR_RES		(~(RMR_CSRE))
+
+/* RCR - Reset Control Register */
+#define RCR_SWHR	0x00000002	/* software hard reset */
+#define RCR_SWSR	0x00000001	/* software soft reset */
+#define RCR_RES		(~(RCR_SWHR | RCR_SWSR))
+
+/* RCER - Reset Control Enable Register */
+#define RCER_CRE	0x00000001	/* software hard reset */
+#define RCER_RES	(~(RCER_CRE))
+
+/*
+ * Clock Module
+ */
+typedef struct clk512x {
+	u32 spmr;		/* System PLL Mode Register */
+	u32 sccr[2];		/* System Clock Control Registers */
+	u32 scfr[2];		/* System Clock Frequency Registers */
+	u8 res0[4];
+	u32 bcr;		/* Bread Crumb Register */
+	u32 pscccr[12];		/* PSC0-11 Clock Control Registers */
+	u32 spccr;		/* SPDIF Clock Control Register */
+	u32 cccr;		/* CFM Clock Control Register */
+	u32 dccr;		/* DIU Clock Control Register */
+	u32 msccr[4];		/* MSCAN1-4 Clock Control Registers */
+	u8 res1[0x98];
+} clk512x_t;
+
+/* SPMR - System PLL Mode Register */
+#define SPMR_SPMF		0x0F000000
+#define SPMR_SPMF_SHIFT		24
+#define SPMR_CPMF		0x000F0000
+#define SPMR_CPMF_SHIFT		16
+
+/* System Clock Control Register 1 commands */
+#define CLOCK_SCCR1_CFG_EN		0x80000000
+#define CLOCK_SCCR1_LPC_EN		0x40000000
+#define CLOCK_SCCR1_NFC_EN		0x20000000
+#define CLOCK_SCCR1_PATA_EN		0x10000000
+#define CLOCK_SCCR1_PSC_EN(cn)		(0x08000000 >> (cn))
+#define CLOCK_SCCR1_PSCFIFO_EN		0x00008000
+#define CLOCK_SCCR1_SATA_EN		0x00004000
+#define CLOCK_SCCR1_FEC_EN		0x00002000
+#define CLOCK_SCCR1_TPR_EN		0x00001000
+#define CLOCK_SCCR1_PCI_EN		0x00000800
+#define CLOCK_SCCR1_DDR_EN		0x00000400
+
+/* System Clock Control Register 2 commands */
+#define CLOCK_SCCR2_DIU_EN		0x80000000
+#define CLOCK_SCCR2_AXE_EN		0x40000000
+#define CLOCK_SCCR2_MEM_EN		0x20000000
+#define CLOCK_SCCR2_USB1_EN		0x10000000
+#define CLOCK_SCCR2_USB2_EN		0x08000000
+#define CLOCK_SCCR2_I2C_EN		0x04000000
+#define CLOCK_SCCR2_BDLC_EN		0x02000000
+#define CLOCK_SCCR2_SDHC_EN		0x01000000
+#define CLOCK_SCCR2_SPDIF_EN		0x00800000
+#define CLOCK_SCCR2_MBX_BUS_EN		0x00400000
+#define CLOCK_SCCR2_MBX_EN		0x00200000
+#define CLOCK_SCCR2_MBX_3D_EN		0x00100000
+#define CLOCK_SCCR2_IIM_EN		0x00080000
+
+/* SCFR1 System Clock Frequency Register 1 */
+#define SCFR1_IPS_DIV		0x3
+#define SCFR1_IPS_DIV_MASK	0x03800000
+#define SCFR1_IPS_DIV_SHIFT	23
+
+#define SCFR1_PCI_DIV		0x6
+#define SCFR1_PCI_DIV_MASK	0x00700000
+#define SCFR1_PCI_DIV_SHIFT	20
+
+#define SCFR1_LPC_DIV_MASK	0x00003800
+#define SCFR1_LPC_DIV_SHIFT	11
+
+/* SCFR2 System Clock Frequency Register 2 */
+#define SCFR2_SYS_DIV		0xFC000000
+#define SCFR2_SYS_DIV_SHIFT	26
+
+/* SPCR - System Priority Configuration Register */
+#define SPCR_TBEN	0x00400000	/* E300 core time base unit enable */
+
+/*
+ * Power Management Control Module
+ */
+typedef struct pmc512x {
+	u8 fixme[0x100];
+} pmc512x_t;
+
+/*
+ * General purpose I/O module
+ */
+typedef struct gpio512x {
+	u32 gpdir;
+	u32 gpodr;
+	u32 gpdat;
+	u32 gpier;
+	u32 gpimr;
+	u32 gpicr1;
+	u32 gpicr2;
+	u8 res0[0xE4];
+} gpio512x_t;
+
+/*
+ * DDR Memory Controller Memory Map
+ */
+typedef struct ddr512x {
+	u32 ddr_sys_config;	/* System Configuration Register */
+	u32 ddr_time_config0;	/* Timing Configuration Register */
+	u32 ddr_time_config1;	/* Timing Configuration Register */
+	u32 ddr_time_config2;	/* Timing Configuration Register */
+	u32 ddr_command;	/* Command Register */
+	u32 ddr_compact_command;	/* Compact Command Register */
+	u32 self_refresh_cmd_0;	/* Enter/Exit Self Refresh Registers */
+	u32 self_refresh_cmd_1;	/* Enter/Exit Self Refresh Registers */
+	u32 self_refresh_cmd_2;	/* Enter/Exit Self Refresh Registers */
+	u32 self_refresh_cmd_3;	/* Enter/Exit Self Refresh Registers */
+	u32 self_refresh_cmd_4;	/* Enter/Exit Self Refresh Registers */
+	u32 self_refresh_cmd_5;	/* Enter/Exit Self Refresh Registers */
+	u32 self_refresh_cmd_6;	/* Enter/Exit Self Refresh Registers */
+	u32 self_refresh_cmd_7;	/* Enter/Exit Self Refresh Registers */
+	u32 DQS_config_offset_count;	/* DQS Config Offset Count */
+	u32 DQS_config_offset_time;	/* DQS Config Offset Time */
+	u32 DQS_delay_status;	/* DQS Delay Status */
+	u32 res0[0xF];
+	u32 prioman_config1;	/* Priority Manager Configuration */
+	u32 prioman_config2;	/* Priority Manager Configuration */
+	u32 hiprio_config;	/* High Priority Configuration */
+	u32 lut_table0_main_upper;	/* LUT0 Main Upper */
+	u32 lut_table1_main_upper;	/* LUT1 Main Upper */
+	u32 lut_table2_main_upper;	/* LUT2 Main Upper */
+	u32 lut_table3_main_upper;	/* LUT3 Main Upper */
+	u32 lut_table4_main_upper;	/* LUT4 Main Upper */
+	u32 lut_table0_main_lower;	/* LUT0 Main Lower */
+	u32 lut_table1_main_lower;	/* LUT1 Main Lower */
+	u32 lut_table2_main_lower;	/* LUT2 Main Lower */
+	u32 lut_table3_main_lower;	/* LUT3 Main Lower */
+	u32 lut_table4_main_lower;	/* LUT4 Main Lower */
+	u32 lut_table0_alternate_upper;	/* LUT0 Alternate Upper */
+	u32 lut_table1_alternate_upper; /* LUT1 Alternate Upper */
+	u32 lut_table2_alternate_upper; /* LUT2 Alternate Upper */
+	u32 lut_table3_alternate_upper; /* LUT3 Alternate Upper */
+	u32 lut_table4_alternate_upper; /* LUT4 Alternate Upper */
+	u32 lut_table0_alternate_lower; /* LUT0 Alternate Lower */
+	u32 lut_table1_alternate_lower; /* LUT1 Alternate Lower */
+	u32 lut_table2_alternate_lower; /* LUT2 Alternate Lower */
+	u32 lut_table3_alternate_lower; /* LUT3 Alternate Lower */
+	u32 lut_table4_alternate_lower; /* LUT4 Alternate Lower */
+	u32 performance_monitor_config;
+	u32 event_time_counter;
+	u32 event_time_preset;
+	u32 performance_monitor1_address_low;
+	u32 performance_monitor2_address_low;
+	u32 performance_monitor1_address_hi;
+	u32 performance_monitor2_address_hi;
+	u32 res1[2];
+	u32 performance_monitor1_read_counter;
+	u32 performance_monitor2_read_counter;
+	u32 performance_monitor1_write_counter;
+	u32 performance_monitor2_write_counter;
+	u32 granted_ack_counter0;
+	u32 granted_ack_counter1;
+	u32 granted_ack_counter2;
+	u32 granted_ack_counter3;
+	u32 granted_ack_counter4;
+	u32 cumulative_wait_counter0;
+	u32 cumulative_wait_counter1;
+	u32 cumulative_wait_counter2;
+	u32 cumulative_wait_counter3;
+	u32 cumulative_wait_counter4;
+	u32 summed_priority_counter0;
+	u32 summed_priority_counter1;
+	u32 summed_priority_counter2;
+	u32 summed_priority_counter3;
+	u32 summed_priority_counter4;
+	u32 res2[0x3AD];
+} ddr512x_t;
+
+/* MDDRC SYS CFG and Timing CFG0 Registers */
+#define MDDRC_SYS_CFG_EN	0xF0000000
+#define MDDRC_SYS_CFG_CMD_MASK	0x10000000
+#define MDDRC_REFRESH_ZERO_MASK	0x0000FFFF
+
+/*
+ * DDR Memory Controller Configuration settings
+ */
+typedef struct ddr512x_config {
+	u32 ddr_sys_config;	/* System Configuration Register */
+	u32 ddr_time_config0;	/* Timing Configuration Register */
+	u32 ddr_time_config1;	/* Timing Configuration Register */
+	u32 ddr_time_config2;	/* Timing Configuration Register */
+} ddr512x_config_t;
+
+/*
+ * DMA/Messaging Unit
+ */
+typedef struct dma512x {
+	u8 fixme[0x1800];
+} dma512x_t;
+
+/*
+ * PCI Software Configuration Registers
+ */
+typedef struct pciconf512x {
+	u32 config_address;
+	u32 config_data;
+	u32 int_ack;
+	u8 res[116];
+} pciconf512x_t;
+
+/*
+ * PCI Outbound Translation Register
+ */
+typedef struct pci_outbound_window {
+	u32 potar;
+	u8 res0[4];
+	u32 pobar;
+	u8 res1[4];
+	u32 pocmr;
+	u8 res2[4];
+} pot512x_t;
+
+/* POTAR - PCI Outbound Translation Address Register */
+#define POTAR_TA_MASK	0x000fffff
+
+/* POBAR - PCI Outbound Base Address Register */
+#define POBAR_BA_MASK	0x000fffff
+
+/* POCMR - PCI Outbound Comparision Mask Register */
+#define POCMR_EN	0x80000000
+#define POCMR_IO	0x40000000	/* 0-memory space 1-I/O space */
+#define POCMR_PRE	0x20000000	/* prefetch enable */
+#define POCMR_SBS	0x00100000	/* special byte swap enable */
+#define POCMR_CM_MASK	0x000fffff
+#define POCMR_CM_4G	0x00000000
+#define POCMR_CM_2G	0x00080000
+#define POCMR_CM_1G	0x000C0000
+#define POCMR_CM_512M	0x000E0000
+#define POCMR_CM_256M	0x000F0000
+#define POCMR_CM_128M	0x000F8000
+#define POCMR_CM_64M	0x000FC000
+#define POCMR_CM_32M	0x000FE000
+#define POCMR_CM_16M	0x000FF000
+#define POCMR_CM_8M	0x000FF800
+#define POCMR_CM_4M	0x000FFC00
+#define POCMR_CM_2M	0x000FFE00
+#define POCMR_CM_1M	0x000FFF00
+#define POCMR_CM_512K	0x000FFF80
+#define POCMR_CM_256K	0x000FFFC0
+#define POCMR_CM_128K	0x000FFFE0
+#define POCMR_CM_64K	0x000FFFF0
+#define POCMR_CM_32K	0x000FFFF8
+#define POCMR_CM_16K	0x000FFFFC
+#define POCMR_CM_8K	0x000FFFFE
+#define POCMR_CM_4K	0x000FFFFF
+
+/*
+ * Sequencer
+ */
+typedef struct ios512x {
+	pot512x_t pot[6];
+	u8 res0[0x60];
+	u32 pmcr;
+	u8 res1[4];
+	u32 dtcr;
+	u8 res2[4];
+} ios512x_t;
+
+/*
+ * PCI Controller
+ */
+typedef struct pcictrl512x {
+	u32 esr;
+	u32 ecdr;
+	u32 eer;
+	u32 eatcr;
+	u32 eacr;
+	u32 eeacr;
+	u32 edlcr;
+	u32 edhcr;
+	u32 gcr;
+	u32 ecr;
+	u32 gsr;
+	u8 res0[12];
+	u32 pitar2;
+	u8 res1[4];
+	u32 pibar2;
+	u32 piebar2;
+	u32 piwar2;
+	u8 res2[4];
+	u32 pitar1;
+	u8 res3[4];
+	u32 pibar1;
+	u32 piebar1;
+	u32 piwar1;
+	u8 res4[4];
+	u32 pitar0;
+	u8 res5[4];
+	u32 pibar0;
+	u8 res6[4];
+	u32 piwar0;
+	u8 res7[132];
+} pcictrl512x_t;
+
+
+/* PITAR - PCI Inbound Translation Address Register
+ */
+#define PITAR_TA_MASK	0x000fffff
+
+/* PIBAR - PCI Inbound Base/Extended Address Register
+ */
+#define PIBAR_MASK	0xffffffff
+#define PIEBAR_EBA_MASK	0x000fffff
+
+/* PIWAR - PCI Inbound Windows Attributes Register
+ */
+#define PIWAR_EN	0x80000000
+#define PIWAR_SBS	0x40000000
+#define PIWAR_PF	0x20000000
+#define PIWAR_RTT_MASK	0x000f0000
+#define PIWAR_RTT_NO_SNOOP 0x00040000
+#define PIWAR_RTT_SNOOP	0x00050000
+#define PIWAR_WTT_MASK	0x0000f000
+#define PIWAR_WTT_NO_SNOOP 0x00004000
+#define PIWAR_WTT_SNOOP	0x00005000
+
+/*
+ * MSCAN
+ */
+typedef struct mscan512x {
+	u8 fixme[0x100];
+} mscan512x_t;
+
+/*
+ * BDLC
+ */
+typedef struct bdlc512x {
+	u8 fixme[0x100];
+} bdlc512x_t;
+
+/*
+ * SDHC
+ */
+typedef struct sdhc512x {
+	u8 fixme[0x100];
+} sdhc512x_t;
+
+/*
+ * SPDIF
+ */
+typedef struct spdif512x {
+	u8 fixme[0x100];
+} spdif512x_t;
+
+/*
+ * I2C
+ */
+typedef struct i2c512x_dev {
+	volatile u32 madr;		/* I2Cn + 0x00 */
+	volatile u32 mfdr;		/* I2Cn + 0x04 */
+	volatile u32 mcr;		/* I2Cn + 0x08 */
+	volatile u32 msr;		/* I2Cn + 0x0C */
+	volatile u32 mdr;		/* I2Cn + 0x10 */
+	u8 res0[0x0C];
+} i2c512x_dev_t;
+
+/* Number of I2C buses */
+#define I2C_BUS_CNT	3
+
+typedef struct i2c512x {
+	i2c512x_dev_t dev[I2C_BUS_CNT];
+	volatile u32 icr;
+	volatile u32 mifr;
+	u8 res0[0x98];
+} i2c512x_t;
+
+/* I2Cn control register bits */
+#define I2C_EN		0x80
+#define I2C_IEN		0x40
+#define I2C_STA		0x20
+#define I2C_TX		0x10
+#define I2C_TXAK	0x08
+#define I2C_RSTA	0x04
+#define I2C_INIT_MASK	(I2C_EN | I2C_STA | I2C_TX | I2C_RSTA)
+
+/* I2Cn status register bits */
+#define I2C_CF		0x80
+#define I2C_AAS		0x40
+#define I2C_BB		0x20
+#define I2C_AL		0x10
+#define I2C_SRW		0x04
+#define I2C_IF		0x02
+#define I2C_RXAK	0x01
+
+/*
+ * AXE
+ */
+typedef struct axe512x {
+	u8 fixme[0x100];
+} axe512x_t;
+
+/*
+ * DIU
+ */
+typedef struct diu512x {
+	u8 fixme[0x100];
+} diu512x_t;
+
+/*
+ * CFM
+ */
+typedef struct cfm512x {
+	u8 fixme[0x100];
+} cfm512x_t;
+
+/*
+ * FEC
+ */
+typedef struct fec512x {
+	u32	fec_id;		/* FEC_ID register */
+	u32	ievent;		/* Interrupt event register */
+	u32	imask;		/* Interrupt mask register */
+	u32	reserved_01;
+	u32	r_des_active;	/* Receive ring updated flag */
+	u32	x_des_active;	/* Transmit ring updated flag */
+	u32	reserved_02[3];
+	u32	ecntrl;		/* Ethernet control register */
+	u32	reserved_03[6];
+	u32	mii_data;	/* MII data register */
+	u32	mii_speed;	/* MII speed register */
+	u32	reserved_04[7];
+	u32	mib_control;	/* MIB control/status register */
+	u32	reserved_05[7];
+	u32	r_cntrl;	/* Receive control register */
+	u32	r_hash;		/* Receive hash */
+	u32	reserved_06[14];
+	u32	x_cntrl;	/* Transmit control register */
+	u32	reserved_07[7];
+	u32	paddr1;		/* Physical address low */
+	u32	paddr2;		/* Physical address high + type field */
+	u32	op_pause;	/* Opcode + pause duration */
+	u32	reserved_08[10];
+	u32	iaddr1;		/* Upper 32 bits of individual hash table */
+	u32	iaddr2;		/* Lower 32 bits of individual hash table */
+	u32	gaddr1;		/* Upper 32 bits of group hash table */
+	u32	gaddr2;		/* Lower 32 bits of group hash table */
+	u32	reserved_09[7];
+	u32	x_wmrk;		/* Transmit FIFO watermark */
+	u32	reserved_10;
+	u32	r_bound;	/* End of RAM */
+	u32	r_fstart;	/* Receive FIFO start address */
+	u32	reserved_11[11];
+	u32	r_des_start;	/* Beginning of receive descriptor ring */
+	u32	x_des_start;	/* Pointer to beginning of transmit descriptor ring */
+	u32	r_buff_size;	/* Receive buffer size */
+	u32	reserved_12[26];
+	u32	dma_control;	/* DMA control for IP bus, AMBA IF + DMA revision */
+	u32	reserved_13[2];
+
+	u32	mib[128];	/* MIB Block Counters */
+
+	u32	fifo[256];	/*  used by FEC, can only be accessed by DMA */
+} fec512x_t;
+
+/*
+ * ULPI
+ */
+typedef struct ulpi512x {
+	u8 fixme[0x600];
+} ulpi512x_t;
+
+/*
+ * UTMI
+ */
+typedef struct utmi512x {
+	u8 fixme[0x3000];
+} utmi512x_t;
+
+/*
+ * PCI DMA
+ */
+typedef struct pcidma512x {
+	u8 fixme[0x300];
+} pcidma512x_t;
+
+/*
+ * IO Control
+ */
+typedef struct ioctrl512x {
+	u32	io_control_mem;			/* MEM pad ctrl reg */
+	u32	io_control_gp;			/* GP pad ctrl reg */
+	u32	io_control_lpc_clk;		/* LPC_CLK pad ctrl reg */
+	u32	io_control_lpc_oe;		/* LPC_OE pad ctrl reg */
+	u32	io_control_lpc_rw;		/* LPC_R/W pad ctrl reg */
+	u32	io_control_lpc_ack;		/* LPC_ACK pad ctrl reg */
+	u32	io_control_lpc_cs0;		/* LPC_CS0 pad ctrl reg */
+	u32	io_control_nfc_ce0;		/* NFC_CE0 pad ctrl reg */
+	u32	io_control_lpc_cs1;		/* LPC_CS1 pad ctrl reg */
+	u32	io_control_lpc_cs2;		/* LPC_CS2 pad ctrl reg */
+	u32	io_control_lpc_ax03;		/* LPC_AX03 pad ctrl reg */
+	u32	io_control_emb_ax02;		/* EMB_AX02 pad ctrl reg */
+	u32	io_control_emb_ax01;		/* EMB_AX01 pad ctrl reg */
+	u32	io_control_emb_ax00;		/* EMB_AX00 pad ctrl reg */
+	u32	io_control_emb_ad31;		/* EMB_AD31 pad ctrl reg */
+	u32	io_control_emb_ad30;		/* EMB_AD30 pad ctrl reg */
+	u32	io_control_emb_ad29;		/* EMB_AD29 pad ctrl reg */
+	u32	io_control_emb_ad28;		/* EMB_AD28 pad ctrl reg */
+	u32	io_control_emb_ad27;		/* EMB_AD27 pad ctrl reg */
+	u32	io_control_emb_ad26;		/* EMB_AD26 pad ctrl reg */
+	u32	io_control_emb_ad25;		/* EMB_AD25 pad ctrl reg */
+	u32	io_control_emb_ad24;		/* EMB_AD24 pad ctrl reg */
+	u32	io_control_emb_ad23;		/* EMB_AD23 pad ctrl reg */
+	u32	io_control_emb_ad22;		/* EMB_AD22 pad ctrl reg */
+	u32	io_control_emb_ad21;		/* EMB_AD21 pad ctrl reg */
+	u32	io_control_emb_ad20;		/* EMB_AD20 pad ctrl reg */
+	u32	io_control_emb_ad19;		/* EMB_AD19 pad ctrl reg */
+	u32	io_control_emb_ad18;		/* EMB_AD18 pad ctrl reg */
+	u32	io_control_emb_ad17;		/* EMB_AD17 pad ctrl reg */
+	u32	io_control_emb_ad16;		/* EMB_AD16 pad ctrl reg */
+	u32	io_control_emb_ad15;		/* EMB_AD15 pad ctrl reg */
+	u32	io_control_emb_ad14;		/* EMB_AD14 pad ctrl reg */
+	u32	io_control_emb_ad13;		/* EMB_AD13 pad ctrl reg */
+	u32	io_control_emb_ad12;		/* EMB_AD12 pad ctrl reg */
+	u32	io_control_emb_ad11;		/* EMB_AD11 pad ctrl reg */
+	u32	io_control_emb_ad10;		/* EMB_AD10 pad ctrl reg */
+	u32	io_control_emb_ad09;		/* EMB_AD09 pad ctrl reg */
+	u32	io_control_emb_ad08;		/* EMB_AD08 pad ctrl reg */
+	u32	io_control_emb_ad07;		/* EMB_AD07 pad ctrl reg */
+	u32	io_control_emb_ad06;		/* EMB_AD06 pad ctrl reg */
+	u32	io_control_emb_ad05;		/* EMB_AD05 pad ctrl reg */
+	u32	io_control_emb_ad04;		/* EMB_AD04 pad ctrl reg */
+	u32	io_control_emb_ad03;		/* EMB_AD03 pad ctrl reg */
+	u32	io_control_emb_ad02;		/* EMB_AD02 pad ctrl reg */
+	u32	io_control_emb_ad01;		/* EMB_AD01 pad ctrl reg */
+	u32	io_control_emb_ad00;		/* EMB_AD00 pad ctrl reg */
+	u32	io_control_pata_ce1;		/* PATA_CE1 pad ctrl reg */
+	u32	io_control_pata_ce2;		/* PATA_CE2 pad ctrl reg */
+	u32	io_control_pata_isolate;	/* PATA_ISOLATE pad ctrl reg */
+	u32	io_control_pata_ior;		/* PATA_IOR pad ctrl reg */
+	u32	io_control_pata_iow;		/* PATA_IOW pad ctrl reg */
+	u32	io_control_pata_iochrdy;	/* PATA_IOCHRDY pad ctrl reg */
+	u32	io_control_pata_intrq;		/* PATA_INTRQ pad ctrl reg */
+	u32	io_control_pata_drq;		/* PATA_DRQ pad ctrl reg */
+	u32	io_control_pata_dack;		/* PATA_DACK pad ctrl reg */
+	u32	io_control_nfc_wp;		/* NFC_WP pad ctrl reg */
+	u32	io_control_nfc_rb;		/* NFC_RB pad ctrl reg */
+	u32	io_control_nfc_ale;		/* NFC_ALE pad ctrl reg */
+	u32	io_control_nfc_cle;		/* NFC_CLE pad ctrl reg */
+	u32	io_control_nfc_we;		/* NFC_WE pad ctrl reg */
+	u32	io_control_nfc_re;		/* NFC_RE pad ctrl reg */
+	u32	io_control_pci_ad31;		/* PCI_AD31 pad ctrl reg */
+	u32	io_control_pci_ad30;		/* PCI_AD30 pad ctrl reg */
+	u32	io_control_pci_ad29;		/* PCI_AD29 pad ctrl reg */
+	u32	io_control_pci_ad28;		/* PCI_AD28 pad ctrl reg */
+	u32	io_control_pci_ad27;		/* PCI_AD27 pad ctrl reg */
+	u32	io_control_pci_ad26;		/* PCI_AD26 pad ctrl reg */
+	u32	io_control_pci_ad25;		/* PCI_AD25 pad ctrl reg */
+	u32	io_control_pci_ad24;		/* PCI_AD24 pad ctrl reg */
+	u32	io_control_pci_ad23;		/* PCI_AD23 pad ctrl reg */
+	u32	io_control_pci_ad22;		/* PCI_AD22 pad ctrl reg */
+	u32	io_control_pci_ad21;		/* PCI_AD21 pad ctrl reg */
+	u32	io_control_pci_ad20;		/* PCI_AD20 pad ctrl reg */
+	u32	io_control_pci_ad19;		/* PCI_AD19 pad ctrl reg */
+	u32	io_control_pci_ad18;		/* PCI_AD18 pad ctrl reg */
+	u32	io_control_pci_ad17;		/* PCI_AD17 pad ctrl reg */
+	u32	io_control_pci_ad16;		/* PCI_AD16 pad ctrl reg */
+	u32	io_control_pci_ad15;		/* PCI_AD15 pad ctrl reg */
+	u32	io_control_pci_ad14;		/* PCI_AD14 pad ctrl reg */
+	u32	io_control_pci_ad13;		/* PCI_AD13 pad ctrl reg */
+	u32	io_control_pci_ad12;		/* PCI_AD12 pad ctrl reg */
+	u32	io_control_pci_ad11;		/* PCI_AD11 pad ctrl reg */
+	u32	io_control_pci_ad10;		/* PCI_AD10 pad ctrl reg */
+	u32	io_control_pci_ad09;		/* PCI_AD09 pad ctrl reg */
+	u32	io_control_pci_ad08;		/* PCI_AD08 pad ctrl reg */
+	u32	io_control_pci_ad07;		/* PCI_AD07 pad ctrl reg */
+	u32	io_control_pci_ad06;		/* PCI_AD06 pad ctrl reg */
+	u32	io_control_pci_ad05;		/* PCI_AD05 pad ctrl reg */
+	u32	io_control_pci_ad04;		/* PCI_AD04 pad ctrl reg */
+	u32	io_control_pci_ad03;		/* PCI_AD03 pad ctrl reg */
+	u32	io_control_pci_ad02;		/* PCI_AD02 pad ctrl reg */
+	u32	io_control_pci_ad01;		/* PCI_AD01 pad ctrl reg */
+	u32	io_control_pci_ad00;		/* PCI_AD00 pad ctrl reg */
+	u32	io_control_pci_cbe0;		/* PCI_CBE0 pad ctrl reg */
+	u32	io_control_pci_cbe1;		/* PCI_CBE1 pad ctrl reg */
+	u32	io_control_pci_cbe2;		/* PCI_CBE2 pad ctrl reg */
+	u32	io_control_pci_cbe3;		/* PCI_CBE3 pad ctrl reg */
+	u32	io_control_pci_grant2;		/* PCI_GRANT2 pad ctrl reg */
+	u32	io_control_pci_req2;		/* PCI_REQ2 pad ctrl reg */
+	u32	io_control_pci_grant1;		/* PCI_GRANT1 pad ctrl reg */
+	u32	io_control_pci_req1;		/* PCI_REQ1 pad ctrl reg */
+	u32	io_control_pci_grant0;		/* PCI_GRANT0 pad ctrl reg */
+	u32	io_control_pci_req0;		/* PCI_REQ0 pad ctrl reg */
+	u32	io_control_pci_inta;		/* PCI_INTA pad ctrl reg */
+	u32	io_control_pci_clk;		/* PCI_CLK pad ctrl reg */
+	u32	io_control_pci_rst;		/* PCI_RST- pad ctrl reg */
+	u32	io_control_pci_frame;		/* PCI_FRAME pad ctrl reg */
+	u32	io_control_pci_idsel;		/* PCI_IDSEL pad ctrl reg */
+	u32	io_control_pci_devsel;		/* PCI_DEVSEL pad ctrl reg */
+	u32	io_control_pci_irdy;		/* PCI_IRDY pad ctrl reg */
+	u32	io_control_pci_trdy;		/* PCI_TRDY pad ctrl reg */
+	u32	io_control_pci_stop;		/* PCI_STOP pad ctrl reg */
+	u32	io_control_pci_par;		/* PCI_PAR pad ctrl reg */
+	u32	io_control_pci_perr;		/* PCI_PERR pad ctrl reg */
+	u32	io_control_pci_serr;		/* PCI_SERR pad ctrl reg */
+	u32	io_control_spdif_txclk;		/* SPDIF_TXCLK pad ctrl reg */
+	u32	io_control_spdif_tx;		/* SPDIF_TX pad ctrl reg */
+	u32	io_control_spdif_rx;		/* SPDIF_RX pad ctrl reg */
+	u32	io_control_i2c0_scl;		/* I2C0_SCL pad ctrl reg */
+	u32	io_control_i2c0_sda;		/* I2C0_SDA pad ctrl reg */
+	u32	io_control_i2c1_scl;		/* I2C1_SCL pad ctrl reg */
+	u32	io_control_i2c1_sda;		/* I2C1_SDA pad ctrl reg */
+	u32	io_control_i2c2_scl;		/* I2C2_SCL pad ctrl reg */
+	u32	io_control_i2c2_sda;		/* I2C2_SDA pad ctrl reg */
+	u32	io_control_irq0;		/* IRQ0 pad ctrl reg */
+	u32	io_control_irq1;		/* IRQ1 pad ctrl reg */
+	u32	io_control_can1_tx;		/* CAN1_TX pad ctrl reg */
+	u32	io_control_can2_tx;		/* CAN2_TX pad ctrl reg */
+	u32	io_control_j1850_tx;		/* J1850_TX pad ctrl reg */
+	u32	io_control_j1850_rx;		/* J1850_RX pad ctrl reg */
+	u32	io_control_psc_mclk_in;		/* PSC_MCLK_IN pad ctrl reg */
+	u32	io_control_psc0_0;		/* PSC0_0 pad ctrl reg */
+	u32	io_control_psc0_1;		/* PSC0_1 pad ctrl reg */
+	u32	io_control_psc0_2;		/* PSC0_2 pad ctrl reg */
+	u32	io_control_psc0_3;		/* PSC0_3 pad ctrl reg */
+	u32	io_control_psc0_4;		/* PSC0_4 pad ctrl reg */
+	u32	io_control_psc1_0;		/* PSC1_0 pad ctrl reg */
+	u32	io_control_psc1_1;		/* PSC1_1 pad ctrl reg */
+	u32	io_control_psc1_2;		/* PSC1_2 pad ctrl reg */
+	u32	io_control_psc1_3;		/* PSC1_3 pad ctrl reg */
+	u32	io_control_psc1_4;		/* PSC1_4 pad ctrl reg */
+	u32	io_control_psc2_0;		/* PSC2_0 pad ctrl reg */
+	u32	io_control_psc2_1;		/* PSC2_1 pad ctrl reg */
+	u32	io_control_psc2_2;		/* PSC2_2 pad ctrl reg */
+	u32	io_control_psc2_3;		/* PSC2_3 pad ctrl reg */
+	u32	io_control_psc2_4;		/* PSC2_4 pad ctrl reg */
+	u32	io_control_psc3_0;		/* PSC3_0 pad ctrl reg */
+	u32	io_control_psc3_1;		/* PSC3_1 pad ctrl reg */
+	u32	io_control_psc3_2;		/* PSC3_2 pad ctrl reg */
+	u32	io_control_psc3_3;		/* PSC3_3 pad ctrl reg */
+	u32	io_control_psc3_4;		/* PSC3_4 pad ctrl reg */
+	u32	io_control_psc4_0;		/* PSC4_0 pad ctrl reg */
+	u32	io_control_psc4_1;		/* PSC4_1 pad ctrl reg */
+	u32	io_control_psc4_2;		/* PSC4_2 pad ctrl reg */
+	u32	io_control_psc4_3;		/* PSC4_3 pad ctrl reg */
+	u32	io_control_psc4_4;		/* PSC4_4 pad ctrl reg */
+	u32	io_control_psc5_0;		/* PSC5_0 pad ctrl reg */
+	u32	io_control_psc5_1;		/* PSC5_1 pad ctrl reg */
+	u32	io_control_psc5_2;		/* PSC5_2 pad ctrl reg */
+	u32	io_control_psc5_3;		/* PSC5_3 pad ctrl reg */
+	u32	io_control_psc5_4;		/* PSC5_4 pad ctrl reg */
+	u32	io_control_psc6_0;		/* PSC6_0 pad ctrl reg */
+	u32	io_control_psc6_1;		/* PSC6_1 pad ctrl reg */
+	u32	io_control_psc6_2;		/* PSC6_2 pad ctrl reg */
+	u32	io_control_psc6_3;		/* PSC6_3 pad ctrl reg */
+	u32	io_control_psc6_4;		/* PSC6_4 pad ctrl reg */
+	u32	io_control_psc7_0;		/* PSC7_0 pad ctrl reg */
+	u32	io_control_psc7_1;		/* PSC7_1 pad ctrl reg */
+	u32	io_control_psc7_2;		/* PSC7_2 pad ctrl reg */
+	u32	io_control_psc7_3;		/* PSC7_3 pad ctrl reg */
+	u32	io_control_psc7_4;		/* PSC7_4 pad ctrl reg */
+	u32	io_control_psc8_0;		/* PSC8_0 pad ctrl reg */
+	u32	io_control_psc8_1;		/* PSC8_1 pad ctrl reg */
+	u32	io_control_psc8_2;		/* PSC8_2 pad ctrl reg */
+	u32	io_control_psc8_3;		/* PSC8_3 pad ctrl reg */
+	u32	io_control_psc8_4;		/* PSC8_4 pad ctrl reg */
+	u32	io_control_psc9_0;		/* PSC9_0 pad ctrl reg */
+	u32	io_control_psc9_1;		/* PSC9_1 pad ctrl reg */
+	u32	io_control_psc9_2;		/* PSC9_2 pad ctrl reg */
+	u32	io_control_psc9_3;		/* PSC9_3 pad ctrl reg */
+	u32	io_control_psc9_4;		/* PSC9_4 pad ctrl reg */
+	u32	io_control_psc10_0;		/* PSC10_0 pad ctrl reg */
+	u32	io_control_psc10_1;		/* PSC10_1 pad ctrl reg */
+	u32	io_control_psc10_2;		/* PSC10_2 pad ctrl reg */
+	u32	io_control_psc10_3;		/* PSC10_3 pad ctrl reg */
+	u32	io_control_psc10_4;		/* PSC10_4 pad ctrl reg */
+	u32	io_control_psc11_0;		/* PSC11_0 pad ctrl reg */
+	u32	io_control_psc11_1;		/* PSC11_1 pad ctrl reg */
+	u32	io_control_psc11_2;		/* PSC11_2 pad ctrl reg */
+	u32	io_control_psc11_3;		/* PSC11_3 pad ctrl reg */
+	u32	io_control_psc11_4;		/* PSC11_4 pad ctrl reg */
+	u32	io_control_ckstp_out;		/* CKSTP_OUT pad ctrl reg */
+	u32	io_control_usb_phy_drvvbus;	/* USB2_DRVVBUS pad ctrl reg */
+	u8	reserved[0x0cfc];		/* fill to 4096 bytes size */
+} ioctrl512x_t;
+
+/* Indexes in regs array */
+/* Set for DDR */
+#define IOCTRL_MUX_DDR		0x00000036
+
+/* IO pin fields */
+#define IO_PIN_FMUX(v)	((v) << 7)	/* pin function */
+#define IO_PIN_HOLD(v)	((v) << 5)	/* hold time, pci only */
+#define IO_PIN_PUD(v)	((v) << 4)	/* if PUE, 0=pull-down, 1=pull-up */
+#define IO_PIN_PUE(v)	((v) << 3)	/* pull up/down enable */
+#define IO_PIN_ST(v)	((v) << 2)	/* schmitt trigger */
+#define IO_PIN_DS(v)	((v))		/* slew rate */
+
+typedef struct iopin_t {
+	int p_offset;		/* offset from IOCTL_MEM_OFFSET */
+	int nr_pins;		/* number of pins to set this way */
+	int bit_or;		/* or in the value instead of overwrite */
+	u_long val;		/* value to write or or */
+}iopin_t;
+
+void iopin_initialize(iopin_t *,int);
+
+/*
+ * IIM
+ */
+typedef struct iim512x {
+	u32 stat;		/* IIM status register */
+	u32 statm;		/* IIM status IRQ mask */
+	u32 err;		/* IIM errors register */
+	u32 emask;		/* IIM error IRQ mask  */
+	u32 fctl;		/* IIM fuse control register */
+	u32 ua;			/* IIM upper address register */
+	u32 la;			/* IIM lower address register */
+	u32 sdat;		/* IIM explicit sense data */
+	u8 res0[0x08];
+	u32 prg_p;		/* IIM program protection register */
+	u8 res1[0x10];
+	u32 divide;		/* IIM divide factor register */
+	u8 res2[0x7c0];
+	u32 fbac0;		/* IIM fuse bank 0 prot (for Freescale use) */
+	u32 fb0w0[0x1f];	/* IIM fuse bank 0 data (for Freescale use) */
+	u8 res3[0x380];
+	u32 fbac1;		/* IIM fuse bank 1 protection */
+	u32 fb1w1[0x01f];	/* IIM fuse bank 1 data */
+	u8 res4[0x380];
+} iim512x_t;
+
+/*
+ * LPC
+ */
+typedef struct lpc512x {
+	u32	cs_cfg[8];	/* Chip Select N Configuration Registers
+				   No dedicated entry for CS Boot as == CS0 */
+	u32	cs_cr;		/* Chip Select Control Register */
+	u32	cs_sr;		/* Chip Select Status Register */
+	u32	cs_bcr;		/* Chip Select Burst Control Register */
+	u32	cs_dccr;	/* Chip Select Deadcycle Control Register */
+	u32	cs_hccr;	/* Chip Select Holdcycle Control Register */
+	u32	altr;		/* Address Latch Timing Register */
+	u8	res0[0xc8];
+	u32	sclpc_psr;	/* SCLPC Packet Size Register */
+	u32	sclpc_sar;	/* SCLPC Start Address Register */
+	u32	sclpc_cr;	/* SCLPC Control Register */
+	u32	sclpc_er;	/* SCLPC Enable Register */
+	u32	sclpc_nar;	/* SCLPC NextAddress Register */
+	u32	sclpc_sr;	/* SCLPC Status Register */
+	u32	sclpc_bdr;	/* SCLPC Bytes Done Register */
+	u32	emb_scr;	/* EMB Share Counter Register */
+	u32	emb_pcr;	/* EMB Pause Control Register */
+	u8	res1[0x1c];
+	u32	lpc_fdwr;	/* LPC RX/TX FIFO Data Word Register */
+	u32	lpc_fsr;	/* LPC RX/TX FIFO Status Register */
+	u32	lpc_cr;		/* LPC RX/TX FIFO Control Register */
+	u32	lpc_ar;		/* LPC RX/TX FIFO Alarm Register */
+	u8	res2[0xb0];
+} lpc512x_t;
+
+/*
+ * PATA
+ */
+typedef struct pata512x {
+	/* LOCAL Registers */
+	u32 pata_time1;		/* Time register 1: PIO and tx timing parameter */
+	u32 pata_time2;		/* Time register 2: PIO timing parameter */
+	u32 pata_time3;		/* Time register 3: PIO and MDMA timing parameter */
+	u32 pata_time4;		/* Time register 4: MDMA and UDMA timing parameter */
+	u32 pata_time5;		/* Time register 5: UDMA timing parameter */
+	u32 pata_time6;		/* Time register 6: UDMA timing parameter */
+	u32 pata_fifo_data32;   /* 32bit wide dataport to/from FIFO */
+	u32 pata_fifo_data16;   /* 16bit wide dataport to/from FIFO */
+	u32 pata_fifo_fill;	/* FIFO filling in halfwords (READONLY)*/
+	u32 pata_ata_control;   /* ATA Interface control register */
+	u32 pata_irq_pending;   /* Interrupt pending register (READONLY) */
+	u32 pata_irq_enable;	/* Interrupt enable register */
+	u32 pata_irq_clear;	/* Interrupt clear register (WRITEONLY)*/
+	u32 pata_fifo_alarm;	/* fifo alarm threshold */
+	u32 res1[0x1A];
+	/* DRIVE Registers */
+	u32 pata_drive_data;	/* drive data register*/
+	u32 pata_drive_features;/* drive features register */
+	u32 pata_drive_sectcnt; /* drive sector count register */
+	u32 pata_drive_sectnum; /* drive sector number register */
+	u32 pata_drive_cyllow;  /* drive cylinder low register */
+	u32 pata_drive_cylhigh; /* drive cylinder high register */
+	u32 pata_drive_dev_head;/* drive device head register */
+	u32 pata_drive_command; /* write = drive command, read = drive status reg */
+	u32 res2[0x06];
+	u32 pata_drive_alt_stat;/* write = drive control, read = drive alt status reg */
+	u32 res3[0x09];
+} pata512x_t;
+
+/*
+ * PSC
+ */
+typedef struct psc512x {
+	volatile u8	mode;		/* PSC + 0x00 */
+	volatile u8	res0[3];
+	union {				/* PSC + 0x04 */
+		volatile u16	status;
+		volatile u16	clock_select;
+	} sr_csr;
+#define psc_status	sr_csr.status
+#define psc_clock_select sr_csr.clock_select
+	volatile u16	res1;
+	volatile u8	command;	/* PSC + 0x08 */
+	volatile u8	res2[3];
+	union {				/* PSC + 0x0c */
+		volatile u8	buffer_8;
+		volatile u16	buffer_16;
+		volatile u32	buffer_32;
+	} buffer;
+#define psc_buffer_8	buffer.buffer_8
+#define psc_buffer_16	buffer.buffer_16
+#define psc_buffer_32	buffer.buffer_32
+	union {				/* PSC + 0x10 */
+		volatile u8	ipcr;
+		volatile u8	acr;
+	} ipcr_acr;
+#define psc_ipcr	ipcr_acr.ipcr
+#define psc_acr		ipcr_acr.acr
+	volatile u8	res3[3];
+	union {				/* PSC + 0x14 */
+		volatile u16	isr;
+		volatile u16	imr;
+	} isr_imr;
+#define psc_isr		isr_imr.isr
+#define psc_imr		isr_imr.imr
+	volatile u16	res4;
+	volatile u8	ctur;		/* PSC + 0x18 */
+	volatile u8	res5[3];
+	volatile u8	ctlr;		/* PSC + 0x1c */
+	volatile u8	res6[3];
+	volatile u32	ccr;		/* PSC + 0x20 */
+	volatile u8	res7[12];
+	volatile u8	ivr;		/* PSC + 0x30 */
+	volatile u8	res8[3];
+	volatile u8	ip;		/* PSC + 0x34 */
+	volatile u8	res9[3];
+	volatile u8	op1;		/* PSC + 0x38 */
+	volatile u8	res10[3];
+	volatile u8	op0;		/* PSC + 0x3c */
+	volatile u8	res11[3];
+	volatile u32	sicr;		/* PSC + 0x40 */
+	volatile u8	res12[60];
+	volatile u32	tfcmd;		/* PSC + 0x80 */
+	volatile u32	tfalarm;	/* PSC + 0x84 */
+	volatile u32	tfstat;		/* PSC + 0x88 */
+	volatile u32	tfintstat;	/* PSC + 0x8C */
+	volatile u32	tfintmask;	/* PSC + 0x90 */
+	volatile u32	tfcount;	/* PSC + 0x94 */
+	volatile u16	tfwptr;		/* PSC + 0x98 */
+	volatile u16	tfrptr;		/* PSC + 0x9A */
+	volatile u32	tfsize;		/* PSC + 0x9C */
+	volatile u8	res13[28];
+	union {				/* PSC + 0xBC */
+		volatile u8	buffer_8;
+		volatile u16	buffer_16;
+		volatile u32	buffer_32;
+	} tfdata_buffer;
+#define tfdata_8	tfdata_buffer.buffer_8
+#define tfdata_16	tfdata_buffer.buffer_16
+#define tfdata_32	tfdata_buffer.buffer_32
+
+	volatile u32	rfcmd;		/* PSC + 0xC0 */
+	volatile u32	rfalarm;	/* PSC + 0xC4 */
+	volatile u32	rfstat;		/* PSC + 0xC8 */
+	volatile u32	rfintstat;	/* PSC + 0xCC */
+	volatile u32	rfintmask;	/* PSC + 0xD0 */
+	volatile u32	rfcount;	/* PSC + 0xD4 */
+	volatile u16	rfwptr;		/* PSC + 0xD8 */
+	volatile u16	rfrptr;		/* PSC + 0xDA */
+	volatile u32	rfsize;		/* PSC + 0xDC */
+	volatile u8	res18[28];
+	union {				/* PSC + 0xFC */
+		volatile u8	buffer_8;
+		volatile u16	buffer_16;
+		volatile u32	buffer_32;
+	} rfdata_buffer;
+#define rfdata_8	rfdata_buffer.buffer_8
+#define rfdata_16	rfdata_buffer.buffer_16
+#define rfdata_32	rfdata_buffer.buffer_32
+} psc512x_t;
+
+/* PSC FIFO Command values */
+#define PSC_FIFO_RESET_SLICE		0x80
+#define PSC_FIFO_ENABLE_SLICE		0x01
+
+/* PSC FIFO Controller Command values */
+#define FIFOC_ENABLE_CLOCK_GATE		0x01
+#define FIFOC_DISABLE_CLOCK_GATE	0x00
+
+/* PSC FIFO status */
+#define PSC_FIFO_EMPTY			0x01
+
+/* PSC Command values */
+#define PSC_RX_ENABLE		0x01
+#define PSC_RX_DISABLE		0x02
+#define PSC_TX_ENABLE		0x04
+#define PSC_TX_DISABLE		0x08
+#define PSC_SEL_MODE_REG_1	0x10
+#define PSC_RST_RX		0x20
+#define PSC_RST_TX		0x30
+#define PSC_RST_ERR_STAT	0x40
+#define PSC_RST_BRK_CHG_INT	0x50
+#define PSC_START_BRK		0x60
+#define PSC_STOP_BRK		0x70
+
+/* PSC status register bits */
+#define PSC_SR_CDE		0x0080
+#define PSC_SR_TXEMP		0x0800
+#define PSC_SR_OE		0x1000
+#define PSC_SR_PE		0x2000
+#define PSC_SR_FE		0x4000
+#define PSC_SR_RB		0x8000
+
+/* PSC mode fields */
+#define PSC_MODE_5_BITS		0x00
+#define PSC_MODE_6_BITS		0x01
+#define PSC_MODE_7_BITS		0x02
+#define PSC_MODE_8_BITS		0x03
+#define PSC_MODE_PAREVEN	0x00
+#define PSC_MODE_PARODD		0x04
+#define PSC_MODE_PARFORCE	0x08
+#define PSC_MODE_PARNONE	0x10
+#define PSC_MODE_ENTIMEOUT	0x20
+#define PSC_MODE_RXRTS		0x80
+#define PSC_MODE_1_STOPBIT	0x07
+
+/*
+ * FIFOC
+ */
+typedef struct fifoc512x {
+	u32 fifoc_cmd;
+	u32 fifoc_int;
+	u32 fifoc_dma;
+	u32 fifoc_axe;
+	u32 fifoc_debug;
+	u8 fixme[0xEC];
+} fifoc512x_t;
+
+/*
+ * Centralized FIFO Controller has internal memory for all 12 PSCs FIFOs
+ *
+ * NOTE: individual PSC units are free to use whatever area (and size) of the
+ * FIFOC internal memory, so make sure memory areas for FIFO slices used by
+ * different PSCs do not overlap!
+ *
+ * Overall size of FIFOC memory is not documented in the MPC5121e RM, but
+ * tests indicate that it is 1024 words total.
+ */
+#define FIFOC_PSC0_TX_SIZE	0x0	/* number of 4-byte words for FIFO slice */
+#define FIFOC_PSC0_TX_ADDR	0x0
+#define FIFOC_PSC0_RX_SIZE	0x0
+#define FIFOC_PSC0_RX_ADDR	0x0
+
+#define FIFOC_PSC1_TX_SIZE	0x0
+#define FIFOC_PSC1_TX_ADDR	0x0
+#define FIFOC_PSC1_RX_SIZE	0x0
+#define FIFOC_PSC1_RX_ADDR	0x0
+
+#define FIFOC_PSC2_TX_SIZE	0x0
+#define FIFOC_PSC2_TX_ADDR	0x0
+#define FIFOC_PSC2_RX_SIZE	0x0
+#define FIFOC_PSC2_RX_ADDR	0x0
+
+#define FIFOC_PSC3_TX_SIZE	0x04
+#define FIFOC_PSC3_TX_ADDR	0x0
+#define FIFOC_PSC3_RX_SIZE	0x04
+#define FIFOC_PSC3_RX_ADDR	0x10
+
+#define FIFOC_PSC4_TX_SIZE	0x0
+#define FIFOC_PSC4_TX_ADDR	0x0
+#define FIFOC_PSC4_RX_SIZE	0x0
+#define FIFOC_PSC4_RX_ADDR	0x0
+
+#define FIFOC_PSC5_TX_SIZE	0x0
+#define FIFOC_PSC5_TX_ADDR	0x0
+#define FIFOC_PSC5_RX_SIZE	0x0
+#define FIFOC_PSC5_RX_ADDR	0x0
+
+#define FIFOC_PSC6_TX_SIZE	0x0
+#define FIFOC_PSC6_TX_ADDR	0x0
+#define FIFOC_PSC6_RX_SIZE	0x0
+#define FIFOC_PSC6_RX_ADDR	0x0
+
+#define FIFOC_PSC7_TX_SIZE	0x0
+#define FIFOC_PSC7_TX_ADDR	0x0
+#define FIFOC_PSC7_RX_SIZE	0x0
+#define FIFOC_PSC7_RX_ADDR	0x0
+
+#define FIFOC_PSC8_TX_SIZE	0x0
+#define FIFOC_PSC8_TX_ADDR	0x0
+#define FIFOC_PSC8_RX_SIZE	0x0
+#define FIFOC_PSC8_RX_ADDR	0x0
+
+#define FIFOC_PSC9_TX_SIZE	0x0
+#define FIFOC_PSC9_TX_ADDR	0x0
+#define FIFOC_PSC9_RX_SIZE	0x0
+#define FIFOC_PSC9_RX_ADDR	0x0
+
+#define FIFOC_PSC10_TX_SIZE	0x0
+#define FIFOC_PSC10_TX_ADDR	0x0
+#define FIFOC_PSC10_RX_SIZE	0x0
+#define FIFOC_PSC10_RX_ADDR	0x0
+
+#define FIFOC_PSC11_TX_SIZE	0x0
+#define FIFOC_PSC11_TX_ADDR	0x0
+#define FIFOC_PSC11_RX_SIZE	0x0
+#define FIFOC_PSC11_RX_ADDR	0x0
+
+/*
+ * SATA
+ */
+typedef struct sata512x {
+	u8 fixme[0x2000];
+} sata512x_t;
+
+typedef struct immap {
+	sysconf512x_t		sysconf;	/* System configuration */
+	u8			res0[0x700];
+	wdt512x_t		wdt;		/* Watch Dog Timer (WDT) */
+	rtclk512x_t		rtc;		/* Real Time Clock Module */
+	gpt512x_t		gpt;		/* General Purpose Timer */
+	ipic512x_t		ipic;		/* Integrated Programmable Interrupt Controller */
+	arbiter512x_t		arbiter;	/* CSB Arbiter */
+	reset512x_t		reset;		/* Reset Module */
+	clk512x_t		clk;		/* Clock Module */
+	pmc512x_t		pmc;		/* Power Management Control Module */
+	gpio512x_t		gpio;		/* General purpose I/O module */
+	u8			res1[0x100];
+	mscan512x_t		mscan;		/* MSCAN */
+	bdlc512x_t		bdlc;		/* BDLC */
+	sdhc512x_t		sdhc;		/* SDHC */
+	spdif512x_t		spdif;		/* SPDIF */
+	i2c512x_t		i2c;		/* I2C Controllers */
+	u8			res2[0x800];
+	axe512x_t		axe;		/* AXE */
+	diu512x_t		diu;		/* Display Interface Unit */
+	cfm512x_t		cfm;		/* Clock Frequency Measurement */
+	u8			res3[0x500];
+	fec512x_t		fec;		/* Fast Ethernet Controller */
+	ulpi512x_t		ulpi;		/* USB ULPI */
+	u8			res4[0xa00];
+	utmi512x_t		utmi;		/* USB UTMI */
+	u8			res5[0x1000];
+	pcidma512x_t		pci_dma;	/* PCI DMA */
+	pciconf512x_t		pci_conf;	/* PCI Configuration */
+	u8			res6[0x80];
+	ios512x_t		ios;		/* PCI Sequencer */
+	pcictrl512x_t		pci_ctrl;	/* PCI Controller Control and Status */
+	u8			res7[0xa00];
+	ddr512x_t		mddrc;		/* Multi-port DDR Memory Controller */
+	ioctrl512x_t		io_ctrl;	/* IO Control */
+	iim512x_t		iim;		/* IC Identification module */
+	u8			res8[0x4000];
+	lpc512x_t		lpc;		/* LocalPlus Controller */
+	pata512x_t		pata;		/* Parallel ATA */
+	u8			res9[0xd00];
+	psc512x_t		psc[12];	/* PSCs */
+	u8			res10[0x300];
+	fifoc512x_t		fifoc;		/* FIFO Controller */
+	u8			res11[0x2000];
+	dma512x_t		dma;		/* DMA */
+	u8			res12[0xa800];
+	sata512x_t		sata;		/* Serial ATA */
+	u8			res13[0xde000];
+} immap_t;
+
+/* provide interface to get PATA base address */
+static inline u32 get_pata_base (void)
+{
+	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+	return (u32)(&im->pata);
+}
+#endif	/* __ASSEMBLY__ */
+
+#endif /* __IMMAP_512x__ */
diff --git a/arch/powerpc/include/asm/immap_8220.h b/arch/powerpc/include/asm/immap_8220.h
new file mode 100644
index 0000000..f9595f4
--- /dev/null
+++ b/arch/powerpc/include/asm/immap_8220.h
@@ -0,0 +1,246 @@
+/*
+ * MPC8220 Internal Memory Map
+ * Copyright (c) 2004 TsiChung Liew (Tsi-Chung.Liew@freescale.com)
+ *
+ * The Internal Memory Map of the 8220.
+ *
+ */
+#ifndef __IMMAP_MPC8220__
+#define __IMMAP_MPC8220__
+
+/*
+ * System configuration registers.
+ */
+typedef struct sys_conf {
+    u16     mbar;       /* 0x00 */
+    u16     res1;
+
+    u16     res2;       /* 0x04 */
+    u16     sdramds;
+
+    u32     res3[6];    /* 0x08 */
+
+    u32     cscfg[6];   /* 0x20 */
+
+    u32     res4[2];    /* 0x38 */
+
+    u8      res5[3];    /* 0x40 */
+    u8      rstctrl;
+
+    u8      res6[3];    /* 0x44 */
+    u8      rststat;
+
+    u32     res7[2];    /* 0x48 */
+
+    u32     jtagid;     /* 0x50 */
+} sysconf8220_t;
+
+
+/*
+ * Memory controller registers.
+ */
+typedef struct mem_ctlr {
+    ushort  mode;           /* 0x100 */
+    ushort  res1;
+    u32     ctrl;           /* 0x104 */
+    u32     cfg1;           /* 0x108 */
+    u32     cfg2;           /* 0x10c */
+} memctl8220_t;
+
+/*
+ * XLB Arbitration registers
+ */
+typedef struct xlb_arb
+{
+    uint    res1[16];       /* 0x200 */
+    uint    config;         /* 0x240 */
+    uint    version;        /* 0x244 */
+    uint    status;         /* 0x248 */
+    uint    intEnable;      /* 0x24c */
+    uint    addrCap;        /* 0x250 */
+    uint    busSigCap;      /* 0x254 */
+    uint    addrTenTimeOut; /* 0x258 */
+    uint    dataTenTimeOut; /* 0x25c */
+    uint    busActTimeOut;  /* 0x260 */
+    uint    mastPriEn;      /* 0x264 */
+    uint    mastPriority;   /* 0x268 */
+    uint    baseAddr;       /* 0x26c */
+} xlbarb8220_t;
+
+/*
+ * Flexbus registers
+ */
+typedef struct flexbus
+{
+    ushort  csar0;          /* 0x00 */
+    ushort  res1;
+    uint    csmr0;          /* 0x04 */
+    uint    cscr0;          /* 0x08 */
+
+    ushort  csar1;          /* 0x0c */
+    ushort  res2;
+    uint    csmr1;          /* 0x10 */
+    uint    cscr1;          /* 0x14 */
+
+    ushort  csar2;          /* 0x18 */
+    ushort  res3;
+    uint    csmr2;          /* 0x1c */
+    uint    cscr2;          /* 0x20 */
+
+    ushort  csar3;          /* 0x24 */
+    ushort  res4;
+    uint    csmr3;          /* 0x28 */
+    uint    cscr3;          /* 0x2c */
+
+    ushort  csar4;          /* 0x30 */
+    ushort  res5;
+    uint    csmr4;          /* 0x34 */
+    uint    cscr4;          /* 0x38 */
+
+    ushort  csar5;          /* 0x3c */
+    ushort  res6;
+    uint    csmr5;          /* 0x40 */
+    uint    cscr5;          /* 0x44 */
+} flexbus8220_t;
+
+/*
+ * GPIO registers
+ */
+typedef struct gpio
+{
+    u32     out;        /* 0x00 */
+    u32     obs;        /* 0x04 */
+    u32     obc;        /* 0x08 */
+    u32     obt;        /* 0x0c */
+    u32     en;         /* 0x10 */
+    u32     ebs;        /* 0x14 */
+    u32     ebc;        /* 0x18 */
+    u32     ebt;        /* 0x1c */
+    u32     mc;         /* 0x20 */
+    u32     st;         /* 0x24 */
+    u32     intr;       /* 0x28 */
+} gpio8220_t;
+
+/*
+ * General Purpose Timer registers
+ */
+typedef struct gptimer
+{
+    u8  OCPW;
+    u8  OctIct;
+    u8  Control;
+    u8  Mode;
+
+    u16 Prescl;  /* Prescale */
+    u16 Count;   /* Count */
+
+    u16 PwmWid;  /* PWM Width */
+    u8  PwmOp;   /* Output Polarity */
+    u8  PwmLd;   /* Immediate Update */
+
+    u16 Capture; /* Capture internal counter */
+    u8  OvfPin;  /* Ovf and Pin */
+    u8  Int;     /* Interrupts */
+} gptmr8220_t;
+
+/*
+ * PSC registers
+ */
+typedef struct psc
+{
+    u32 mr1_2;             /* 0x00 Mode reg 1 & 2 */
+    u32 sr_csr;            /* 0x04 Status/Clock Select reg */
+    u32 cr;                /* 0x08 Command reg */
+    u8  xmitbuf[4];        /* 0x0c Receive/Transmit Buffer */
+    u32 ipcr_acr;          /* 0x10 Input Port Change/Auxiliary Control reg */
+    u32 isr_imr;           /* 0x14 Interrupt Status/Mask reg */
+    u32 ctur;              /* 0x18 Counter Timer Upper reg */
+    u32 ctlr;              /* 0x1c Counter Timer Lower reg */
+    u32 rsvd1[4];          /* 0x20 ... 0x2c */
+    u32 ivr;               /* 0x30 Interrupt Vector reg */
+    u32 ipr;               /* 0x34 Input Port reg */
+    u32 opsetr;            /* 0x38 Output Port Set reg */
+    u32 opresetr;          /* 0x3c Output Port Reset reg */
+    u32 sicr;              /* 0x40 PSC/IrDA control reg */
+    u32 ircr1;             /* 0x44 IrDA control reg 1*/
+    u32 ircr2;             /* 0x48 IrDA control reg 2*/
+    u32 irsdr;             /* 0x4c IrDA SIR Divide reg */
+    u32 irmdr;             /* 0x50 IrDA MIR Divide reg */
+    u32 irfdr;             /* 0x54 PSC IrDA FIR Divide reg */
+    u32 rfnum;             /* 0x58 RX-FIFO counter */
+    u32 txnum;             /* 0x5c TX-FIFO counter */
+    u32 rfdata;            /* 0x60 RX-FIFO data */
+    u32 rfstat;            /* 0x64 RX-FIFO status */
+    u32 rfcntl;            /* 0x68 RX-FIFO control */
+    u32 rfalarm;           /* 0x6c RX-FIFO alarm */
+    u32 rfrptr;            /* 0x70 RX-FIFO read pointer */
+    u32 rfwptr;            /* 0x74 RX-FIFO write pointer */
+    u32 rflfrptr;          /* 0x78 RX-FIFO last read frame pointer */
+    u32 rflfwptr;          /* 0x7c RX-FIFO last write frame pointer */
+
+    u32 tfdata;            /* 0x80 TX-FIFO data */
+    u32 tfstat;            /* 0x84 TX-FIFO status */
+    u32 tfcntl;            /* 0x88 TX-FIFO control */
+    u32 tfalarm;           /* 0x8c TX-FIFO alarm */
+    u32 tfrptr;            /* 0x90 TX-FIFO read pointer */
+    u32 tfwptr;            /* 0x94 TX-FIFO write pointer */
+    u32 tflfrptr;          /* 0x98 TX-FIFO last read frame pointer */
+    u32 tflfwptr;          /* 0x9c TX-FIFO last write frame pointer */
+} psc8220_t;
+
+/*
+ * Interrupt Controller registers
+ */
+typedef struct interrupt_controller {
+} intctl8220_t;
+
+
+/* Fast controllers
+*/
+
+/*
+ * I2C registers
+ */
+typedef struct i2c
+{
+    u8   adr;            /* 0x00 */
+    u8   res1[3];
+    u8   fdr;            /* 0x04 */
+    u8   res2[3];
+    u8   cr;             /* 0x08 */
+    u8   res3[3];
+    u8   sr;             /* 0x0C */
+    u8   res4[3];
+    u8   dr;             /* 0x10 */
+    u8   res5[3];
+    u32  reserved0;      /* 0x14 */
+    u32  reserved1;      /* 0x18 */
+    u32  reserved2;      /* 0x1c */
+    u8   icr;            /* 0x20 */
+    u8   res6[3];
+} i2c8220_t;
+
+/*
+ * Port Configuration Registers
+ */
+typedef struct pcfg
+{
+    uint    pcfg0;          /* 0x00 */
+    uint    pcfg1;          /* 0x04 */
+    uint    pcfg2;          /* 0x08 */
+    uint    pcfg3;          /* 0x0c */
+} pcfg8220_t;
+
+/* ...and the whole thing wrapped up....
+*/
+typedef struct immap {
+    sysconf8220_t   im_sysconf; /* System Configuration */
+    memctl8220_t    im_memctl;  /* Memory Controller */
+    xlbarb8220_t    im_xlbarb;  /* XLB Arbitration */
+    psc8220_t       im_psc;     /* PSC controller */
+    flexbus8220_t   im_fb;      /* FlexBus Controller */
+    i2c8220_t       im_i2c;     /* I2C control/status */
+    pcfg8220_t      im_pcfg;    /* Port configuration */
+} immap_t;
+
+#endif /* __IMMAP_MPC8220__ */
diff --git a/arch/powerpc/include/asm/immap_8260.h b/arch/powerpc/include/asm/immap_8260.h
new file mode 100644
index 0000000..4974ae5
--- /dev/null
+++ b/arch/powerpc/include/asm/immap_8260.h
@@ -0,0 +1,599 @@
+/*
+ * MPC8260 Internal Memory Map
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ *
+ * The Internal Memory Map of the 8260.	 I don't know how generic
+ * this will be, as I don't have any knowledge of the subsequent
+ * parts at this time.	I copied this from the 8xx_immap.h.
+ */
+#ifndef __IMMAP_82XX__
+#define __IMMAP_82XX__
+
+/* System configuration registers.
+*/
+typedef struct sys_conf {
+	uint	sc_siumcr;
+	uint	sc_sypcr;
+	char	res1[6];
+	ushort	sc_swsr;
+	char	res2[20];
+	uint	sc_bcr;
+	u_char	sc_ppc_acr;
+	char	res3[3];
+	uint	sc_ppc_alrh;
+	uint	sc_ppc_alrl;
+	u_char	sc_lcl_acr;
+	char	res4[3];
+	uint	sc_lcl_alrh;
+	uint	sc_lcl_alrl;
+	uint	sc_tescr1;
+	uint	sc_tescr2;
+	uint	sc_ltescr1;
+	uint	sc_ltescr2;
+	uint	sc_pdtea;
+	u_char	sc_pdtem;
+	char	res5[3];
+	uint	sc_ldtea;
+	u_char	sc_ldtem;
+	char	res6[163];
+} sysconf8260_t;
+
+
+/* Memory controller registers.
+*/
+typedef struct	mem_ctlr {
+	uint	memc_br0;
+	uint	memc_or0;
+	uint	memc_br1;
+	uint	memc_or1;
+	uint	memc_br2;
+	uint	memc_or2;
+	uint	memc_br3;
+	uint	memc_or3;
+	uint	memc_br4;
+	uint	memc_or4;
+	uint	memc_br5;
+	uint	memc_or5;
+	uint	memc_br6;
+	uint	memc_or6;
+	uint	memc_br7;
+	uint	memc_or7;
+	uint	memc_br8;
+	uint	memc_or8;
+	uint	memc_br9;
+	uint	memc_or9;
+	uint	memc_br10;
+	uint	memc_or10;
+	uint	memc_br11;
+	uint	memc_or11;
+	char	res1[8];
+	uint	memc_mar;
+	char	res2[4];
+	uint	memc_mamr;
+	uint	memc_mbmr;
+	uint	memc_mcmr;
+	char	res3[8];
+	ushort	memc_mptpr;
+	char	res4[2];
+	uint	memc_mdr;
+	char	res5[4];
+	uint	memc_psdmr;
+	uint	memc_lsdmr;
+	u_char	memc_purt;
+	char	res6[3];
+	u_char	memc_psrt;
+	char	res7[3];
+	u_char	memc_lurt;
+	char	res8[3];
+	u_char	memc_lsrt;
+	char	res9[3];
+	uint	memc_immr;
+	uint	memc_pcibr0;
+	uint	memc_pcibr1;
+	char	res10[16];
+	uint	memc_pcimsk0;
+	uint	memc_pcimsk1;
+	char	res11[52];
+} memctl8260_t;
+
+/* System Integration Timers.
+*/
+typedef struct	sys_int_timers {
+	char	res1[32];
+	ushort	sit_tmcntsc;
+	char	res2[2];
+	uint	sit_tmcnt;
+	char	res3[4];
+	uint	sit_tmcntal;
+	char	res4[16];
+	ushort	sit_piscr;
+	char	res5[2];
+	uint	sit_pitc;
+	uint	sit_pitr;
+	char	res6[94];
+	char	res7[390];
+} sit8260_t;
+
+/* PCI
+ */
+typedef struct pci_config {
+	uint	pci_omisr;
+	uint	pci_ominr;
+	char	res1[8];
+	uint	pci_ifqpr;
+	uint	pci_ofqpr;
+	char	res2[8];
+	uint	pci_imr0;
+	uint	pci_imr1;
+	uint	pci_omr0;
+	uint	pci_omr1;
+	uint	pci_odr;
+	char	res3[4];
+	uint	pci_idr;
+	char	res4[20];
+	uint	pci_imisr;
+	uint	pci_imimr;
+	char	res5[24];
+	uint	pci_ifhpr;
+	char	res5_2[4];
+	uint	pci_iftpr;
+	char	res6[4];
+	uint	pci_iphpr;
+	char	res6_2[4];
+	uint	pci_iptpr;
+	char	res7[4];
+	uint	pci_ofhpr;
+	char	res7_2[4];
+	uint	pci_oftpr;
+	char	res8[4];
+	uint	pci_ophpr;
+	char	res8_2[4];
+	uint	pci_optpr;
+	char	res9[8];
+	uint	pci_mucr;
+	char	res10[8];
+	uint	pci_qbar;
+	char	res11[12];
+	uint	pci_dmamr0;
+	uint	pci_dmasr0;
+	uint	pci_dmacdar0;
+	char	res12[4];
+	uint	pci_dmasar0;
+	char	res13[4];
+	uint	pci_dmadar0;
+	char	res14[4];
+	uint	pci_dmabcr0;
+	uint	pci_dmandar0;
+	char	res15[88];
+	uint	pci_dmamr1;
+	uint	pci_dmasr1;
+	uint	pci_dmacdar1;
+	char	res16[4];
+	uint	pci_dmasar1;
+	char	res17[4];
+	uint	pci_dmadar1;
+	char	res18[4];
+	uint	pci_dmabcr1;
+	uint	pci_dmandar1;
+	char	res19[88];
+	uint	pci_dmamr2;
+	uint	pci_dmasr2;
+	uint	pci_dmacdar2;
+	char	res20[4];
+	uint	pci_dmasar2;
+	char	res21[4];
+	uint	pci_dmadar2;
+	char	res22[4];
+	uint	pci_dmabcr2;
+	uint	pci_dmandar2;
+	char	res23[88];
+	uint	pci_dmamr3;
+	uint	pci_dmasr3;
+	uint	pci_dmacdar3;
+	char	res24[4];
+	uint	pci_dmasar3;
+	char	res25[4];
+	uint	pci_dmadar3;
+	char	res26[4];
+	uint	pci_dmabcr3;
+	uint	pci_dmandar3;
+	char	res27[344];
+	uint	pci_potar0;
+	char	res28[4];
+	uint	pci_pobar0;
+	char	res29[4];
+	uint	pci_pocmr0;
+	char	res30[4];
+	uint	pci_potar1;
+	char	res31[4];
+	uint	pci_pobar1;
+	char	res32[4];
+	uint	pci_pocmr1;
+	char	res33[4];
+	uint	pci_potar2;
+	char	res34[4];
+	uint	pci_pobar2;
+	char	res35[4];
+	uint	pci_pocmr2;
+	char	res36[52];
+	uint	pci_ptcr;
+	uint	pci_gpcr;
+	uint	pci_gcr;
+	uint	pci_esr;
+	uint	pci_emr;
+	uint	pci_ecr;
+	uint	pci_eacr;
+	char	res37[4];
+	uint	pci_edcr;
+	char	res38[4];
+	uint	pci_eccr;
+	char	res39[44];
+	uint	pci_pitar1;
+	char	res40[4];
+	uint	pci_pibar1;
+	char	res41[4];
+	uint	pci_picmr1;
+	char	res42[4];
+	uint	pci_pitar0;
+	char	res43[4];
+	uint	pci_pibar0;
+	char	res44[4];
+	uint	pci_picmr0;
+	char	res45[4];
+	uint	pci_cfg_addr;
+	uint	pci_cfg_data;
+	uint	pci_int_ack;
+	char	res46[756];
+}pci8260_t;
+#define PISCR_PIRQ_MASK		((ushort)0xff00)
+#define PISCR_PS		((ushort)0x0080)
+#define PISCR_PIE		((ushort)0x0004)
+#define PISCR_PTF		((ushort)0x0002)
+#define PISCR_PTE		((ushort)0x0001)
+
+/* Interrupt Controller.
+*/
+typedef struct interrupt_controller {
+	ushort	ic_sicr;
+	char	res1[2];
+	uint	ic_sivec;
+	uint	ic_sipnrh;
+	uint	ic_sipnrl;
+	uint	ic_siprr;
+	uint	ic_scprrh;
+	uint	ic_scprrl;
+	uint	ic_simrh;
+	uint	ic_simrl;
+	uint	ic_siexr;
+	char	res2[88];
+} intctl8260_t;
+
+/* Clocks and Reset.
+*/
+typedef struct clk_and_reset {
+	uint	car_sccr;
+	char	res1[4];
+	uint	car_scmr;
+	char	res2[4];
+	uint	car_rsr;
+	uint	car_rmr;
+	char	res[104];
+} car8260_t;
+
+/* Input/Output Port control/status registers.
+ * Names consistent with processor manual, although they are different
+ * from the original 8xx names.......
+ */
+typedef struct io_port {
+	uint	iop_pdira;
+	uint	iop_ppara;
+	uint	iop_psora;
+	uint	iop_podra;
+	uint	iop_pdata;
+	char	res1[12];
+	uint	iop_pdirb;
+	uint	iop_pparb;
+	uint	iop_psorb;
+	uint	iop_podrb;
+	uint	iop_pdatb;
+	char	res2[12];
+	uint	iop_pdirc;
+	uint	iop_pparc;
+	uint	iop_psorc;
+	uint	iop_podrc;
+	uint	iop_pdatc;
+	char	res3[12];
+	uint	iop_pdird;
+	uint	iop_ppard;
+	uint	iop_psord;
+	uint	iop_podrd;
+	uint	iop_pdatd;
+	char	res4[12];
+} iop8260_t;
+
+/* Communication Processor Module Timers
+*/
+typedef struct cpm_timers {
+	u_char	cpmt_tgcr1;
+	char	res1[3];
+	u_char	cpmt_tgcr2;
+	char	res2[11];
+	ushort	cpmt_tmr1;
+	ushort	cpmt_tmr2;
+	ushort	cpmt_trr1;
+	ushort	cpmt_trr2;
+	ushort	cpmt_tcr1;
+	ushort	cpmt_tcr2;
+	ushort	cpmt_tcn1;
+	ushort	cpmt_tcn2;
+	ushort	cpmt_tmr3;
+	ushort	cpmt_tmr4;
+	ushort	cpmt_trr3;
+	ushort	cpmt_trr4;
+	ushort	cpmt_tcr3;
+	ushort	cpmt_tcr4;
+	ushort	cpmt_tcn3;
+	ushort	cpmt_tcn4;
+	ushort	cpmt_ter1;
+	ushort	cpmt_ter2;
+	ushort	cpmt_ter3;
+	ushort	cpmt_ter4;
+	char	res3[584];
+} cpmtimer8260_t;
+
+/* DMA control/status registers.
+*/
+typedef struct sdma_csr {
+	char	res0[24];
+	u_char	sdma_sdsr;
+	char	res1[3];
+	u_char	sdma_sdmr;
+	char	res2[3];
+	u_char	sdma_idsr1;
+	char	res3[3];
+	u_char	sdma_idmr1;
+	char	res4[3];
+	u_char	sdma_idsr2;
+	char	res5[3];
+	u_char	sdma_idmr2;
+	char	res6[3];
+	u_char	sdma_idsr3;
+	char	res7[3];
+	u_char	sdma_idmr3;
+	char	res8[3];
+	u_char	sdma_idsr4;
+	char	res9[3];
+	u_char	sdma_idmr4;
+	char	res10[707];
+} sdma8260_t;
+
+/* Fast controllers
+*/
+typedef struct fcc {
+	uint	fcc_gfmr;
+	uint	fcc_fpsmr;
+	ushort	fcc_ftodr;
+	char	res1[2];
+	ushort	fcc_fdsr;
+	char	res2[2];
+	ushort	fcc_fcce;
+	char	res3[2];
+	ushort	fcc_fccm;
+	char	res4[2];
+	u_char	fcc_fccs;
+	char	res5[3];
+	u_char	fcc_ftirr_phy[4];
+} fcc_t;
+
+/* Fast controllers continued
+ */
+typedef struct fcc_c {
+	uint	fcc_firper;
+	uint	fcc_firer;
+	uint	fcc_firsr_hi;
+	uint	fcc_firsr_lo;
+	u_char	fcc_gfemr;
+	char	res1[15];
+} fcc_c_t;
+
+/* TC Layer
+ */
+typedef struct tclayer {
+	ushort	tc_tcmode;
+	ushort	tc_cdsmr;
+	ushort	tc_tcer;
+	ushort	tc_rcc;
+	ushort	tc_tcmr;
+	ushort	tc_fcc;
+	ushort	tc_ccc;
+	ushort	tc_icc;
+	ushort	tc_tcc;
+	ushort	tc_ecc;
+	char	res1[12];
+} tclayer_t;
+
+/* I2C
+*/
+typedef struct i2c {
+	u_char	i2c_i2mod;
+	char	res1[3];
+	u_char	i2c_i2add;
+	char	res2[3];
+	u_char	i2c_i2brg;
+	char	res3[3];
+	u_char	i2c_i2com;
+	char	res4[3];
+	u_char	i2c_i2cer;
+	char	res5[3];
+	u_char	i2c_i2cmr;
+	char	res6[331];
+} i2c8260_t;
+
+typedef struct scc {		/* Serial communication channels */
+	uint	scc_gsmrl;
+	uint	scc_gsmrh;
+	ushort	scc_psmr;
+	char	res1[2];
+	ushort	scc_todr;
+	ushort	scc_dsr;
+	ushort	scc_scce;
+	char	res2[2];
+	ushort	scc_sccm;
+	char	res3;
+	u_char	scc_sccs;
+	char	res4[8];
+} scc_t;
+
+typedef struct smc {		/* Serial management channels */
+	char	res1[2];
+	ushort	smc_smcmr;
+	char	res2[2];
+	u_char	smc_smce;
+	char	res3[3];
+	u_char	smc_smcm;
+	char	res4[5];
+} smc_t;
+
+/* Serial Peripheral Interface.
+*/
+typedef struct im_spi {
+	ushort	spi_spmode;
+	char	res1[4];
+	u_char	spi_spie;
+	char	res2[3];
+	u_char	spi_spim;
+	char	res3[2];
+	u_char	spi_spcom;
+	char	res4[82];
+} im_spi_t;
+
+/* CPM Mux.
+*/
+typedef struct cpmux {
+	u_char	cmx_si1cr;
+	char	res1;
+	u_char	cmx_si2cr;
+	char	res2;
+	uint	cmx_fcr;
+	uint	cmx_scr;
+	u_char	cmx_smr;
+	char	res3;
+	ushort	cmx_uar;
+	char	res4[16];
+} cpmux_t;
+
+/* SIRAM control
+*/
+typedef struct siram {
+	ushort	si_amr;
+	ushort	si_bmr;
+	ushort	si_cmr;
+	ushort	si_dmr;
+	u_char	si_gmr;
+	char	res1;
+	u_char	si_cmdr;
+	char	res2;
+	u_char	si_str;
+	char	res3;
+	ushort	si_rsr;
+} siramctl_t;
+
+typedef struct mcc {
+	ushort	mcc_mcce;
+	char	res1[2];
+	ushort	mcc_mccm;
+	char	res2[2];
+	u_char	mcc_mccf;
+	char	res3[7];
+} mcc_t;
+
+typedef struct comm_proc {
+	uint	cp_cpcr;
+	uint	cp_rccr;
+	char	res1[14];
+	ushort	cp_rter;
+	char	res2[2];
+	ushort	cp_rtmr;
+	ushort	cp_rtscr;
+	char	res3[2];
+	uint	cp_rtsr;
+	char	res4[12];
+} cpm8260_t;
+
+/* ...and the whole thing wrapped up....
+*/
+typedef struct immap {
+	/* Some references are into the unique and known dpram spaces,
+	 * others are from the generic base.
+	 */
+#define im_dprambase	im_dpram1
+	u_char		im_dpram1[16*1024];
+	char		res1[16*1024];
+	u_char		im_dpram2[4*1024];
+	char		res2[8*1024];
+	u_char		im_dpram3[4*1024];
+	char		res3[16*1024];
+
+	sysconf8260_t	im_siu_conf;	/* SIU Configuration */
+	memctl8260_t	im_memctl;	/* Memory Controller */
+	sit8260_t	im_sit;		/* System Integration Timers */
+	pci8260_t	im_pci;		/* PCI Configuration */
+	intctl8260_t	im_intctl;	/* Interrupt Controller */
+	car8260_t	im_clkrst;	/* Clocks and reset */
+	iop8260_t	im_ioport;	/* IO Port control/status */
+	cpmtimer8260_t	im_cpmtimer;	/* CPM timers */
+	sdma8260_t	im_sdma;	/* SDMA control/status */
+
+	fcc_t		im_fcc[3];	/* Three FCCs */
+
+	char		res4[32];
+	fcc_c_t		im_fcc_c[3];	/* Continued FCCs */
+	char		res4a[32];
+
+	tclayer_t	im_tclayer[8];	/* Eight TCLayers */
+	ushort		tc_tcgsr;
+	ushort		tc_tcger;
+
+	/* First set of baud rate generators.
+	*/
+	char		res4b[236];
+	uint		im_brgc5;
+	uint		im_brgc6;
+	uint		im_brgc7;
+	uint		im_brgc8;
+
+	char		res5[608];
+
+	i2c8260_t	im_i2c;		/* I2C control/status */
+	cpm8260_t	im_cpm;		/* Communication processor */
+
+	/* Second set of baud rate generators.
+	*/
+	uint		im_brgc1;
+	uint		im_brgc2;
+	uint		im_brgc3;
+	uint		im_brgc4;
+
+	scc_t		im_scc[4];	/* Four SCCs */
+	smc_t		im_smc[2];	/* Couple of SMCs */
+	im_spi_t	im_spi;		/* A SPI */
+	cpmux_t		im_cpmux;	/* CPM clock route mux */
+	siramctl_t	im_siramctl1;	/* First SI RAM Control */
+	mcc_t		im_mcc1;	/* First MCC */
+	siramctl_t	im_siramctl2;	/* Second SI RAM Control */
+	mcc_t		im_mcc2;	/* Second MCC */
+
+	char		res6[1184];
+
+	ushort		im_si1txram[256];
+	char		res7[512];
+	ushort		im_si1rxram[256];
+	char		res8[512];
+	ushort		im_si2txram[256];
+	char		res9[512];
+	ushort		im_si2rxram[256];
+	char		res10[512];
+	char		res11[4096];
+} immap_t;
+
+#endif /* __IMMAP_82XX__ */
diff --git a/arch/powerpc/include/asm/immap_83xx.h b/arch/powerpc/include/asm/immap_83xx.h
new file mode 100644
index 0000000..6b42a73
--- /dev/null
+++ b/arch/powerpc/include/asm/immap_83xx.h
@@ -0,0 +1,877 @@
+/*
+ * Copyright 2004-2009 Freescale Semiconductor, Inc.
+ *
+ * MPC83xx Internal Memory Map
+ *
+ * Contributors:
+ *	Dave Liu <daveliu@freescale.com>
+ *	Tanya Jiang <tanya.jiang@freescale.com>
+ *	Mandy Lavi <mandy.lavi@freescale.com>
+ *	Eran Liberty <liberty@freescale.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+#ifndef __IMMAP_83xx__
+#define __IMMAP_83xx__
+
+#include <asm/types.h>
+#include <asm/fsl_i2c.h>
+#include <asm/mpc8xxx_spi.h>
+#include <asm/fsl_lbc.h>
+#include <asm/fsl_dma.h>
+
+/*
+ * Local Access Window
+ */
+typedef struct law83xx {
+	u32 bar;		/* LBIU local access window base address register */
+	u32 ar;			/* LBIU local access window attribute register */
+} law83xx_t;
+
+/*
+ * System configuration registers
+ */
+typedef struct sysconf83xx {
+	u32 immrbar;		/* Internal memory map base address register */
+	u8 res0[0x04];
+	u32 altcbar;		/* Alternate configuration base address register */
+	u8 res1[0x14];
+	law83xx_t lblaw[4];	/* LBIU local access window */
+	u8 res2[0x20];
+	law83xx_t pcilaw[2];	/* PCI local access window */
+	u8 res3[0x10];
+	law83xx_t pcielaw[2];	/* PCI Express local access window */
+	u8 res4[0x10];
+	law83xx_t ddrlaw[2];	/* DDR local access window */
+	u8 res5[0x50];
+	u32 sgprl;		/* System General Purpose Register Low */
+	u32 sgprh;		/* System General Purpose Register High */
+	u32 spridr;		/* System Part and Revision ID Register */
+	u8 res6[0x04];
+	u32 spcr;		/* System Priority Configuration Register */
+	u32 sicrl;		/* System I/O Configuration Register Low */
+	u32 sicrh;		/* System I/O Configuration Register High */
+	u8 res7[0x04];
+	u32 sidcr0;		/* System I/O Delay Configuration Register 0 */
+	u32 sidcr1;		/* System I/O Delay Configuration Register 1 */
+	u32 ddrcdr;		/* DDR Control Driver Register */
+	u32 ddrdsr;		/* DDR Debug Status Register */
+	u32 obir;		/* Output Buffer Impedance Register */
+	u8 res8[0xC];
+	u32 pecr1;		/* PCI Express control register 1 */
+	u32 pecr2;		/* PCI Express control register 2 */
+	u8 res9[0xB8];
+} sysconf83xx_t;
+
+/*
+ * Watch Dog Timer (WDT) Registers
+ */
+typedef struct wdt83xx {
+	u8 res0[4];
+	u32 swcrr;		/* System watchdog control register */
+	u32 swcnr;		/* System watchdog count register */
+	u8 res1[2];
+	u16 swsrr;		/* System watchdog service register */
+	u8 res2[0xF0];
+} wdt83xx_t;
+
+/*
+ * RTC/PIT Module Registers
+ */
+typedef struct rtclk83xx {
+	u32 cnr;		/* control register */
+	u32 ldr;		/* load register */
+	u32 psr;		/* prescale register */
+	u32 ctr;		/* counter value field register */
+	u32 evr;		/* event register */
+	u32 alr;		/* alarm register */
+	u8 res0[0xE8];
+} rtclk83xx_t;
+
+/*
+ * Global timer module
+ */
+typedef struct gtm83xx {
+	u8 cfr1;		/* Timer1/2 Configuration */
+	u8 res0[3];
+	u8 cfr2;		/* Timer3/4 Configuration */
+	u8 res1[10];
+	u16 mdr1;		/* Timer1 Mode Register */
+	u16 mdr2;		/* Timer2 Mode Register */
+	u16 rfr1;		/* Timer1 Reference Register */
+	u16 rfr2;		/* Timer2 Reference Register */
+	u16 cpr1;		/* Timer1 Capture Register */
+	u16 cpr2;		/* Timer2 Capture Register */
+	u16 cnr1;		/* Timer1 Counter Register */
+	u16 cnr2;		/* Timer2 Counter Register */
+	u16 mdr3;		/* Timer3 Mode Register */
+	u16 mdr4;		/* Timer4 Mode Register */
+	u16 rfr3;		/* Timer3 Reference Register */
+	u16 rfr4;		/* Timer4 Reference Register */
+	u16 cpr3;		/* Timer3 Capture Register */
+	u16 cpr4;		/* Timer4 Capture Register */
+	u16 cnr3;		/* Timer3 Counter Register */
+	u16 cnr4;		/* Timer4 Counter Register */
+	u16 evr1;		/* Timer1 Event Register */
+	u16 evr2;		/* Timer2 Event Register */
+	u16 evr3;		/* Timer3 Event Register */
+	u16 evr4;		/* Timer4 Event Register */
+	u16 psr1;		/* Timer1 Prescaler Register */
+	u16 psr2;		/* Timer2 Prescaler Register */
+	u16 psr3;		/* Timer3 Prescaler Register */
+	u16 psr4;		/* Timer4 Prescaler Register */
+	u8 res[0xC0];
+} gtm83xx_t;
+
+/*
+ * Integrated Programmable Interrupt Controller
+ */
+typedef struct ipic83xx {
+	u32 sicfr;		/* System Global Interrupt Configuration Register */
+	u32 sivcr;		/* System Global Interrupt Vector Register */
+	u32 sipnr_h;		/* System Internal Interrupt Pending Register - High */
+	u32 sipnr_l;		/* System Internal Interrupt Pending Register - Low */
+	u32 siprr_a;		/* System Internal Interrupt Group A Priority Register */
+	u8 res0[8];
+	u32 siprr_d;		/* System Internal Interrupt Group D Priority Register */
+	u32 simsr_h;		/* System Internal Interrupt Mask Register - High */
+	u32 simsr_l;		/* System Internal Interrupt Mask Register - Low */
+	u8 res1[4];
+	u32 sepnr;		/* System External Interrupt Pending Register */
+	u32 smprr_a;		/* System Mixed Interrupt Group A Priority Register */
+	u32 smprr_b;		/* System Mixed Interrupt Group B Priority Register */
+	u32 semsr;		/* System External Interrupt Mask Register */
+	u32 secnr;		/* System External Interrupt Control Register */
+	u32 sersr;		/* System Error Status Register */
+	u32 sermr;		/* System Error Mask Register */
+	u32 sercr;		/* System Error Control Register */
+	u8 res2[4];
+	u32 sifcr_h;		/* System Internal Interrupt Force Register - High */
+	u32 sifcr_l;		/* System Internal Interrupt Force Register - Low */
+	u32 sefcr;		/* System External Interrupt Force Register */
+	u32 serfr;		/* System Error Force Register */
+	u32 scvcr;		/* System Critical Interrupt Vector Register */
+	u32 smvcr;		/* System Management Interrupt Vector Register */
+	u8 res3[0x98];
+} ipic83xx_t;
+
+/*
+ * System Arbiter Registers
+ */
+typedef struct arbiter83xx {
+	u32 acr;		/* Arbiter Configuration Register */
+	u32 atr;		/* Arbiter Timers Register */
+	u8 res[4];
+	u32 aer;		/* Arbiter Event Register */
+	u32 aidr;		/* Arbiter Interrupt Definition Register */
+	u32 amr;		/* Arbiter Mask Register */
+	u32 aeatr;		/* Arbiter Event Attributes Register */
+	u32 aeadr;		/* Arbiter Event Address Register */
+	u32 aerr;		/* Arbiter Event Response Register */
+	u8 res1[0xDC];
+} arbiter83xx_t;
+
+/*
+ * Reset Module
+ */
+typedef struct reset83xx {
+	u32 rcwl;		/* Reset Configuration Word Low Register */
+	u32 rcwh;		/* Reset Configuration Word High Register */
+	u8 res0[8];
+	u32 rsr;		/* Reset Status Register */
+	u32 rmr;		/* Reset Mode Register */
+	u32 rpr;		/* Reset protection Register */
+	u32 rcr;		/* Reset Control Register */
+	u32 rcer;		/* Reset Control Enable Register */
+	u8 res1[0xDC];
+} reset83xx_t;
+
+/*
+ * Clock Module
+ */
+typedef struct clk83xx {
+	u32 spmr;		/* system PLL mode Register */
+	u32 occr;		/* output clock control Register */
+	u32 sccr;		/* system clock control Register */
+	u8 res0[0xF4];
+} clk83xx_t;
+
+/*
+ * Power Management Control Module
+ */
+typedef struct pmc83xx {
+	u32 pmccr;		/* PMC Configuration Register */
+	u32 pmcer;		/* PMC Event Register */
+	u32 pmcmr;		/* PMC Mask Register */
+	u32 pmccr1;		/* PMC Configuration Register 1 */
+	u32 pmccr2;		/* PMC Configuration Register 2 */
+	u8 res0[0xEC];
+} pmc83xx_t;
+
+/*
+ * General purpose I/O module
+ */
+typedef struct gpio83xx {
+	u32 dir;		/* direction register */
+	u32 odr;		/* open drain register */
+	u32 dat;		/* data register */
+	u32 ier;		/* interrupt event register */
+	u32 imr;		/* interrupt mask register */
+	u32 icr;		/* external interrupt control register */
+	u8 res0[0xE8];
+} gpio83xx_t;
+
+/*
+ * QE Ports Interrupts Registers
+ */
+typedef struct qepi83xx {
+	u8 res0[0xC];
+	u32 qepier;		/* QE Ports Interrupt Event Register */
+	u32 qepimr;		/* QE Ports Interrupt Mask Register */
+	u32 qepicr;		/* QE Ports Interrupt Control Register */
+	u8 res1[0xE8];
+} qepi83xx_t;
+
+/*
+ * QE Parallel I/O Ports
+ */
+typedef struct gpio_n {
+	u32 podr;		/* Open Drain Register */
+	u32 pdat;		/* Data Register */
+	u32 dir1;		/* direction register 1 */
+	u32 dir2;		/* direction register 2 */
+	u32 ppar1;		/* Pin Assignment Register 1 */
+	u32 ppar2;		/* Pin Assignment Register 2 */
+} gpio_n_t;
+
+typedef struct qegpio83xx {
+	gpio_n_t ioport[0x7];
+	u8 res0[0x358];
+} qepio83xx_t;
+
+/*
+ * QE Secondary Bus Access Windows
+ */
+typedef struct qesba83xx {
+	u32 lbmcsar;		/* Local bus memory controller start address */
+	u32 sdmcsar;		/* Secondary DDR memory controller start address */
+	u8 res0[0x38];
+	u32 lbmcear;		/* Local bus memory controller end address */
+	u32 sdmcear;		/* Secondary DDR memory controller end address */
+	u8 res1[0x38];
+	u32 lbmcar;		/* Local bus memory controller attributes */
+	u32 sdmcar;		/* Secondary DDR memory controller attributes */
+	u8 res2[0x378];
+} qesba83xx_t;
+
+/*
+ * DDR Memory Controller Memory Map
+ */
+typedef struct ddr_cs_bnds {
+	u32 csbnds;
+	u8 res0[4];
+} ddr_cs_bnds_t;
+
+typedef struct ddr83xx {
+	ddr_cs_bnds_t csbnds[4];/* Chip Select x Memory Bounds */
+	u8 res0[0x60];
+	u32 cs_config[4];	/* Chip Select x Configuration */
+	u8 res1[0x70];
+	u32 timing_cfg_3;	/* SDRAM Timing Configuration 3 */
+	u32 timing_cfg_0;	/* SDRAM Timing Configuration 0 */
+	u32 timing_cfg_1;	/* SDRAM Timing Configuration 1 */
+	u32 timing_cfg_2;	/* SDRAM Timing Configuration 2 */
+	u32 sdram_cfg;		/* SDRAM Control Configuration */
+	u32 sdram_cfg2;		/* SDRAM Control Configuration 2 */
+	u32 sdram_mode;		/* SDRAM Mode Configuration */
+	u32 sdram_mode2;	/* SDRAM Mode Configuration 2 */
+	u32 sdram_md_cntl;	/* SDRAM Mode Control */
+	u32 sdram_interval;	/* SDRAM Interval Configuration */
+	u32 ddr_data_init;	/* SDRAM Data Initialization */
+	u8 res2[4];
+	u32 sdram_clk_cntl;	/* SDRAM Clock Control */
+	u8 res3[0x14];
+	u32 ddr_init_addr;	/* DDR training initialization address */
+	u32 ddr_init_ext_addr;	/* DDR training initialization extended address */
+	u8 res4[0xAA8];
+	u32 ddr_ip_rev1;	/* DDR IP block revision 1 */
+	u32 ddr_ip_rev2;	/* DDR IP block revision 2 */
+	u8 res5[0x200];
+	u32 data_err_inject_hi;	/* Memory Data Path Error Injection Mask High */
+	u32 data_err_inject_lo;	/* Memory Data Path Error Injection Mask Low */
+	u32 ecc_err_inject;	/* Memory Data Path Error Injection Mask ECC */
+	u8 res6[0x14];
+	u32 capture_data_hi;	/* Memory Data Path Read Capture High */
+	u32 capture_data_lo;	/* Memory Data Path Read Capture Low */
+	u32 capture_ecc;	/* Memory Data Path Read Capture ECC */
+	u8 res7[0x14];
+	u32 err_detect;		/* Memory Error Detect */
+	u32 err_disable;	/* Memory Error Disable */
+	u32 err_int_en;		/* Memory Error Interrupt Enable */
+	u32 capture_attributes;	/* Memory Error Attributes Capture */
+	u32 capture_address;	/* Memory Error Address Capture */
+	u32 capture_ext_address;/* Memory Error Extended Address Capture */
+	u32 err_sbe;		/* Memory Single-Bit ECC Error Management */
+	u8 res8[0xA4];
+	u32 debug_reg;
+	u8 res9[0xFC];
+} ddr83xx_t;
+
+/*
+ * DUART
+ */
+typedef struct duart83xx {
+	u8 urbr_ulcr_udlb;	/* combined register for URBR, UTHR and UDLB */
+	u8 uier_udmb;		/* combined register for UIER and UDMB */
+	u8 uiir_ufcr_uafr;	/* combined register for UIIR, UFCR and UAFR */
+	u8 ulcr;		/* line control register */
+	u8 umcr;		/* MODEM control register */
+	u8 ulsr;		/* line status register */
+	u8 umsr;		/* MODEM status register */
+	u8 uscr;		/* scratch register */
+	u8 res0[8];
+	u8 udsr;		/* DMA status register */
+	u8 res1[3];
+	u8 res2[0xEC];
+} duart83xx_t;
+
+/*
+ * DMA/Messaging Unit
+ */
+typedef struct dma83xx {
+	u32 res0[0xC];		/* 0x0-0x29 reseverd */
+	u32 omisr;		/* 0x30 Outbound message interrupt status register */
+	u32 omimr;		/* 0x34 Outbound message interrupt mask register */
+	u32 res1[0x6];		/* 0x38-0x49 reserved */
+	u32 imr0;		/* 0x50 Inbound message register 0 */
+	u32 imr1;		/* 0x54 Inbound message register 1 */
+	u32 omr0;		/* 0x58 Outbound message register 0 */
+	u32 omr1;		/* 0x5C Outbound message register 1 */
+	u32 odr;		/* 0x60 Outbound doorbell register */
+	u32 res2;		/* 0x64-0x67 reserved */
+	u32 idr;		/* 0x68 Inbound doorbell register */
+	u32 res3[0x5];		/* 0x6C-0x79 reserved */
+	u32 imisr;		/* 0x80 Inbound message interrupt status register */
+	u32 imimr;		/* 0x84 Inbound message interrupt mask register */
+	u32 res4[0x1E];		/* 0x88-0x99 reserved */
+	struct fsl_dma dma[4];
+} dma83xx_t;
+
+/*
+ * PCI Software Configuration Registers
+ */
+typedef struct pciconf83xx {
+	u32 config_address;
+	u32 config_data;
+	u32 int_ack;
+	u8 res[116];
+} pciconf83xx_t;
+
+/*
+ * PCI Outbound Translation Register
+ */
+typedef struct pci_outbound_window {
+	u32 potar;
+	u8 res0[4];
+	u32 pobar;
+	u8 res1[4];
+	u32 pocmr;
+	u8 res2[4];
+} pot83xx_t;
+
+/*
+ * Sequencer
+ */
+typedef struct ios83xx {
+	pot83xx_t pot[6];
+	u8 res0[0x60];
+	u32 pmcr;
+	u8 res1[4];
+	u32 dtcr;
+	u8 res2[4];
+} ios83xx_t;
+
+/*
+ * PCI Controller Control and Status Registers
+ */
+typedef struct pcictrl83xx {
+	u32 esr;
+	u32 ecdr;
+	u32 eer;
+	u32 eatcr;
+	u32 eacr;
+	u32 eeacr;
+	u32 edlcr;
+	u32 edhcr;
+	u32 gcr;
+	u32 ecr;
+	u32 gsr;
+	u8 res0[12];
+	u32 pitar2;
+	u8 res1[4];
+	u32 pibar2;
+	u32 piebar2;
+	u32 piwar2;
+	u8 res2[4];
+	u32 pitar1;
+	u8 res3[4];
+	u32 pibar1;
+	u32 piebar1;
+	u32 piwar1;
+	u8 res4[4];
+	u32 pitar0;
+	u8 res5[4];
+	u32 pibar0;
+	u8 res6[4];
+	u32 piwar0;
+	u8 res7[132];
+} pcictrl83xx_t;
+
+/*
+ * USB
+ */
+typedef struct usb83xx {
+	u8 fixme[0x1000];
+} usb83xx_t;
+
+/*
+ * TSEC
+ */
+typedef struct tsec83xx {
+	u8 fixme[0x1000];
+} tsec83xx_t;
+
+/*
+ * Security
+ */
+typedef struct security83xx {
+	u8 fixme[0x10000];
+} security83xx_t;
+
+/*
+ *  PCI Express
+ */
+struct pex_inbound_window {
+	u32 ar;
+	u32 tar;
+	u32 barl;
+	u32 barh;
+};
+
+struct pex_outbound_window {
+	u32 ar;
+	u32 bar;
+	u32 tarl;
+	u32 tarh;
+};
+
+struct pex_csb_bridge {
+	u32 pex_csb_ver;
+	u32 pex_csb_cab;
+	u32 pex_csb_ctrl;
+	u8 res0[8];
+	u32 pex_dms_dstmr;
+	u8 res1[4];
+	u32 pex_cbs_stat;
+	u8 res2[0x20];
+	u32 pex_csb_obctrl;
+	u32 pex_csb_obstat;
+	u8 res3[0x98];
+	u32 pex_csb_ibctrl;
+	u32 pex_csb_ibstat;
+	u8 res4[0xb8];
+	u32 pex_wdma_ctrl;
+	u32 pex_wdma_addr;
+	u32 pex_wdma_stat;
+	u8 res5[0x94];
+	u32 pex_rdma_ctrl;
+	u32 pex_rdma_addr;
+	u32 pex_rdma_stat;
+	u8 res6[0xd4];
+	u32 pex_ombcr;
+	u32 pex_ombdr;
+	u8 res7[0x38];
+	u32 pex_imbcr;
+	u32 pex_imbdr;
+	u8 res8[0x38];
+	u32 pex_int_enb;
+	u32 pex_int_stat;
+	u32 pex_int_apio_vec1;
+	u32 pex_int_apio_vec2;
+	u8 res9[0x10];
+	u32 pex_int_ppio_vec1;
+	u32 pex_int_ppio_vec2;
+	u32 pex_int_wdma_vec1;
+	u32 pex_int_wdma_vec2;
+	u32 pex_int_rdma_vec1;
+	u32 pex_int_rdma_vec2;
+	u32 pex_int_misc_vec;
+	u8 res10[4];
+	u32 pex_int_axi_pio_enb;
+	u32 pex_int_axi_wdma_enb;
+	u32 pex_int_axi_rdma_enb;
+	u32 pex_int_axi_misc_enb;
+	u32 pex_int_axi_pio_stat;
+	u32 pex_int_axi_wdma_stat;
+	u32 pex_int_axi_rdma_stat;
+	u32 pex_int_axi_misc_stat;
+	u8 res11[0xa0];
+	struct pex_outbound_window pex_outbound_win[4];
+	u8 res12[0x100];
+	u32 pex_epiwtar0;
+	u32 pex_epiwtar1;
+	u32 pex_epiwtar2;
+	u32 pex_epiwtar3;
+	u8 res13[0x70];
+	struct pex_inbound_window pex_inbound_win[4];
+};
+
+typedef struct pex83xx {
+	u8 pex_cfg_header[0x404];
+	u32 pex_ltssm_stat;
+	u8 res0[0x30];
+	u32 pex_ack_replay_timeout;
+	u8 res1[4];
+	u32 pex_gclk_ratio;
+	u8 res2[0xc];
+	u32 pex_pm_timer;
+	u32 pex_pme_timeout;
+	u8 res3[4];
+	u32 pex_aspm_req_timer;
+	u8 res4[0x18];
+	u32 pex_ssvid_update;
+	u8 res5[0x34];
+	u32 pex_cfg_ready;
+	u8 res6[0x24];
+	u32 pex_bar_sizel;
+	u8 res7[4];
+	u32 pex_bar_sel;
+	u8 res8[0x20];
+	u32 pex_bar_pf;
+	u8 res9[0x88];
+	u32 pex_pme_to_ack_tor;
+	u8 res10[0xc];
+	u32 pex_ss_intr_mask;
+	u8 res11[0x25c];
+	struct pex_csb_bridge bridge;
+	u8 res12[0x160];
+} pex83xx_t;
+
+/*
+ * SATA
+ */
+typedef struct sata83xx {
+	u8 fixme[0x1000];
+} sata83xx_t;
+
+/*
+ * eSDHC
+ */
+typedef struct sdhc83xx {
+	u8 fixme[0x1000];
+} sdhc83xx_t;
+
+/*
+ * SerDes
+ */
+typedef struct serdes83xx {
+	u8 fixme[0x100];
+} serdes83xx_t;
+
+/*
+ * On Chip ROM
+ */
+typedef struct rom83xx {
+	u8 mem[0x10000];
+} rom83xx_t;
+
+/*
+ * TDM
+ */
+typedef struct tdm83xx {
+	u8 fixme[0x200];
+} tdm83xx_t;
+
+/*
+ * TDM DMAC
+ */
+typedef struct tdmdmac83xx {
+	u8 fixme[0x2000];
+} tdmdmac83xx_t;
+
+#if defined(CONFIG_MPC834x)
+typedef struct immap {
+	sysconf83xx_t		sysconf;	/* System configuration */
+	wdt83xx_t		wdt;		/* Watch Dog Timer (WDT) Registers */
+	rtclk83xx_t		rtc;		/* Real Time Clock Module Registers */
+	rtclk83xx_t		pit;		/* Periodic Interval Timer */
+	gtm83xx_t		gtm[2];		/* Global Timers Module */
+	ipic83xx_t		ipic;		/* Integrated Programmable Interrupt Controller */
+	arbiter83xx_t		arbiter;	/* System Arbiter Registers */
+	reset83xx_t		reset;		/* Reset Module */
+	clk83xx_t		clk;		/* System Clock Module */
+	pmc83xx_t		pmc;		/* Power Management Control Module */
+	gpio83xx_t		gpio[2];	/* General purpose I/O module */
+	u8			res0[0x200];
+	u8			dll_ddr[0x100];
+	u8			dll_lbc[0x100];
+	u8			res1[0xE00];
+	ddr83xx_t		ddr;		/* DDR Memory Controller Memory */
+	fsl_i2c_t		i2c[2];		/* I2C Controllers */
+	u8			res2[0x1300];
+	duart83xx_t		duart[2];	/* DUART */
+	u8			res3[0x900];
+	fsl_lbus_t		lbus;	/* Local Bus Controller Registers */
+	u8			res4[0x1000];
+	spi8xxx_t		spi;		/* Serial Peripheral Interface */
+	dma83xx_t		dma;		/* DMA */
+	pciconf83xx_t		pci_conf[2];	/* PCI Software Configuration Registers */
+	ios83xx_t		ios;		/* Sequencer */
+	pcictrl83xx_t		pci_ctrl[2];	/* PCI Controller Control and Status Registers */
+	u8			res5[0x19900];
+	usb83xx_t		usb[2];
+	tsec83xx_t		tsec[2];
+	u8			res6[0xA000];
+	security83xx_t		security;
+	u8			res7[0xC0000];
+} immap_t;
+
+#ifdef CONFIG_HAS_FSL_MPH_USB
+#define CONFIG_SYS_MPC83xx_USB_OFFSET  0x22000	/* use the MPH controller */
+#else
+#define CONFIG_SYS_MPC83xx_USB_OFFSET  0x23000	/* use the DR controller */
+#endif
+
+#elif defined(CONFIG_MPC8313)
+typedef struct immap {
+	sysconf83xx_t		sysconf;	/* System configuration */
+	wdt83xx_t		wdt;		/* Watch Dog Timer (WDT) Registers */
+	rtclk83xx_t		rtc;		/* Real Time Clock Module Registers */
+	rtclk83xx_t		pit;		/* Periodic Interval Timer */
+	gtm83xx_t		gtm[2];		/* Global Timers Module */
+	ipic83xx_t		ipic;		/* Integrated Programmable Interrupt Controller */
+	arbiter83xx_t		arbiter;	/* System Arbiter Registers */
+	reset83xx_t		reset;		/* Reset Module */
+	clk83xx_t		clk;		/* System Clock Module */
+	pmc83xx_t		pmc;		/* Power Management Control Module */
+	gpio83xx_t		gpio[1];	/* General purpose I/O module */
+	u8			res0[0x1300];
+	ddr83xx_t		ddr;		/* DDR Memory Controller Memory */
+	fsl_i2c_t		i2c[2];		/* I2C Controllers */
+	u8			res1[0x1300];
+	duart83xx_t		duart[2];	/* DUART */
+	u8			res2[0x900];
+	fsl_lbus_t		lbus;	/* Local Bus Controller Registers */
+	u8			res3[0x1000];
+	spi8xxx_t		spi;		/* Serial Peripheral Interface */
+	dma83xx_t		dma;		/* DMA */
+	pciconf83xx_t		pci_conf[1];	/* PCI Software Configuration Registers */
+	u8			res4[0x80];
+	ios83xx_t		ios;		/* Sequencer */
+	pcictrl83xx_t		pci_ctrl[1];	/* PCI Controller Control and Status Registers */
+	u8			res5[0x1aa00];
+	usb83xx_t		usb[1];
+	tsec83xx_t		tsec[2];
+	u8			res6[0xA000];
+	security83xx_t		security;
+	u8			res7[0xC0000];
+} immap_t;
+
+#elif defined(CONFIG_MPC8315)
+typedef struct immap {
+	sysconf83xx_t		sysconf;	/* System configuration */
+	wdt83xx_t		wdt;		/* Watch Dog Timer (WDT) Registers */
+	rtclk83xx_t		rtc;		/* Real Time Clock Module Registers */
+	rtclk83xx_t		pit;		/* Periodic Interval Timer */
+	gtm83xx_t		gtm[2];		/* Global Timers Module */
+	ipic83xx_t		ipic;		/* Integrated Programmable Interrupt Controller */
+	arbiter83xx_t		arbiter;	/* System Arbiter Registers */
+	reset83xx_t		reset;		/* Reset Module */
+	clk83xx_t		clk;		/* System Clock Module */
+	pmc83xx_t		pmc;		/* Power Management Control Module */
+	gpio83xx_t		gpio[1];	/* General purpose I/O module */
+	u8			res0[0x1300];
+	ddr83xx_t		ddr;		/* DDR Memory Controller Memory */
+	fsl_i2c_t		i2c[2];		/* I2C Controllers */
+	u8			res1[0x1300];
+	duart83xx_t		duart[2];	/* DUART */
+	u8			res2[0x900];
+	fsl_lbus_t		lbus;	/* Local Bus Controller Registers */
+	u8			res3[0x1000];
+	spi8xxx_t		spi;		/* Serial Peripheral Interface */
+	dma83xx_t		dma;		/* DMA */
+	pciconf83xx_t		pci_conf[1];	/* PCI Software Configuration Registers */
+	u8			res4[0x80];
+	ios83xx_t		ios;		/* Sequencer */
+	pcictrl83xx_t		pci_ctrl[1];	/* PCI Controller Control and Status Registers */
+	u8			res5[0xa00];
+	pex83xx_t		pciexp[2];	/* PCI Express Controller */
+	u8			res6[0xb000];
+	tdm83xx_t		tdm;		/* TDM Controller */
+	u8			res7[0x1e00];
+	sata83xx_t		sata[2];	/* SATA Controller */
+	u8			res8[0x9000];
+	usb83xx_t		usb[1];		/* USB DR Controller */
+	tsec83xx_t		tsec[2];
+	u8			res9[0x6000];
+	tdmdmac83xx_t		tdmdmac;	/* TDM DMAC */
+	u8			res10[0x2000];
+	security83xx_t		security;
+	u8			res11[0xA3000];
+	serdes83xx_t		serdes[1];	/* SerDes Registers */
+	u8			res12[0x1CF00];
+} immap_t;
+
+#elif defined(CONFIG_MPC837x)
+typedef struct immap {
+	sysconf83xx_t		sysconf;	/* System configuration */
+	wdt83xx_t		wdt;		/* Watch Dog Timer (WDT) Registers */
+	rtclk83xx_t		rtc;		/* Real Time Clock Module Registers */
+	rtclk83xx_t		pit;		/* Periodic Interval Timer */
+	gtm83xx_t		gtm[2];		/* Global Timers Module */
+	ipic83xx_t		ipic;		/* Integrated Programmable Interrupt Controller */
+	arbiter83xx_t		arbiter;	/* System Arbiter Registers */
+	reset83xx_t		reset;		/* Reset Module */
+	clk83xx_t		clk;		/* System Clock Module */
+	pmc83xx_t		pmc;		/* Power Management Control Module */
+	gpio83xx_t		gpio[2];	/* General purpose I/O module */
+	u8			res0[0x1200];
+	ddr83xx_t		ddr;		/* DDR Memory Controller Memory */
+	fsl_i2c_t		i2c[2];		/* I2C Controllers */
+	u8			res1[0x1300];
+	duart83xx_t		duart[2];	/* DUART */
+	u8			res2[0x900];
+	fsl_lbus_t		lbus;	/* Local Bus Controller Registers */
+	u8			res3[0x1000];
+	spi8xxx_t		spi;		/* Serial Peripheral Interface */
+	dma83xx_t		dma;		/* DMA */
+	pciconf83xx_t		pci_conf[1];	/* PCI Software Configuration Registers */
+	u8			res4[0x80];
+	ios83xx_t		ios;		/* Sequencer */
+	pcictrl83xx_t		pci_ctrl[1];	/* PCI Controller Control and Status Registers */
+	u8			res5[0xa00];
+	pex83xx_t		pciexp[2];	/* PCI Express Controller */
+	u8			res6[0xd000];
+	sata83xx_t		sata[4];	/* SATA Controller */
+	u8			res7[0x7000];
+	usb83xx_t		usb[1];		/* USB DR Controller */
+	tsec83xx_t		tsec[2];
+	u8			res8[0x8000];
+	sdhc83xx_t		sdhc;		/* SDHC Controller */
+	u8			res9[0x1000];
+	security83xx_t		security;
+	u8			res10[0xA3000];
+	serdes83xx_t		serdes[2];	/* SerDes Registers */
+	u8			res11[0xCE00];
+	rom83xx_t		rom;		/* On Chip ROM */
+} immap_t;
+
+#elif defined(CONFIG_MPC8360)
+typedef struct immap {
+	sysconf83xx_t		sysconf;	/* System configuration */
+	wdt83xx_t		wdt;		/* Watch Dog Timer (WDT) Registers */
+	rtclk83xx_t		rtc;		/* Real Time Clock Module Registers */
+	rtclk83xx_t		pit;		/* Periodic Interval Timer */
+	u8			res0[0x200];
+	ipic83xx_t		ipic;		/* Integrated Programmable Interrupt Controller */
+	arbiter83xx_t		arbiter;	/* System Arbiter Registers */
+	reset83xx_t		reset;		/* Reset Module */
+	clk83xx_t		clk;		/* System Clock Module */
+	pmc83xx_t		pmc;		/* Power Management Control Module */
+	qepi83xx_t		qepi;		/* QE Ports Interrupts Registers */
+	u8			res1[0x300];
+	u8			dll_ddr[0x100];
+	u8			dll_lbc[0x100];
+	u8			res2[0x200];
+	qepio83xx_t		qepio;		/* QE Parallel I/O ports */
+	qesba83xx_t		qesba;		/* QE Secondary Bus Access Windows */
+	u8			res3[0x400];
+	ddr83xx_t		ddr;		/* DDR Memory Controller Memory */
+	fsl_i2c_t		i2c[2];		/* I2C Controllers */
+	u8			res4[0x1300];
+	duart83xx_t		duart[2];	/* DUART */
+	u8			res5[0x900];
+	fsl_lbus_t		lbus;	/* Local Bus Controller Registers */
+	u8			res6[0x2000];
+	dma83xx_t		dma;		/* DMA */
+	pciconf83xx_t		pci_conf[1];	/* PCI Software Configuration Registers */
+	u8			res7[128];
+	ios83xx_t		ios;		/* Sequencer (IOS) */
+	pcictrl83xx_t		pci_ctrl[1];	/* PCI Controller Control and Status Registers */
+	u8			res8[0x4A00];
+	ddr83xx_t		ddr_secondary;	/* Secondary DDR Memory Controller Memory Map */
+	u8			res9[0x22000];
+	security83xx_t		security;
+	u8			res10[0xC0000];
+	u8			qe[0x100000];	/* QE block */
+} immap_t;
+
+#elif defined(CONFIG_MPC832x)
+typedef struct immap {
+	sysconf83xx_t		sysconf;	/* System configuration */
+	wdt83xx_t		wdt;		/* Watch Dog Timer (WDT) Registers */
+	rtclk83xx_t		rtc;		/* Real Time Clock Module Registers */
+	rtclk83xx_t		pit;		/* Periodic Interval Timer */
+	gtm83xx_t		gtm[2];		/* Global Timers Module */
+	ipic83xx_t		ipic;		/* Integrated Programmable Interrupt Controller */
+	arbiter83xx_t		arbiter;	/* System Arbiter Registers */
+	reset83xx_t		reset;		/* Reset Module */
+	clk83xx_t		clk;		/* System Clock Module */
+	pmc83xx_t		pmc;		/* Power Management Control Module */
+	qepi83xx_t		qepi;		/* QE Ports Interrupts Registers */
+	u8			res0[0x300];
+	u8			dll_ddr[0x100];
+	u8			dll_lbc[0x100];
+	u8			res1[0x200];
+	qepio83xx_t		qepio;		/* QE Parallel I/O ports */
+	u8			res2[0x800];
+	ddr83xx_t		ddr;		/* DDR Memory Controller Memory */
+	fsl_i2c_t		i2c[2];		/* I2C Controllers */
+	u8			res3[0x1300];
+	duart83xx_t		duart[2];	/* DUART */
+	u8			res4[0x900];
+	fsl_lbus_t		lbus;	/* Local Bus Controller Registers */
+	u8			res5[0x2000];
+	dma83xx_t		dma;		/* DMA */
+	pciconf83xx_t		pci_conf[1];	/* PCI Software Configuration Registers */
+	u8			res6[128];
+	ios83xx_t		ios;		/* Sequencer (IOS) */
+	pcictrl83xx_t		pci_ctrl[1];	/* PCI Controller Control and Status Registers */
+	u8			res7[0x27A00];
+	security83xx_t		security;
+	u8			res8[0xC0000];
+	u8			qe[0x100000];	/* QE block */
+} immap_t;
+#endif
+
+#define CONFIG_SYS_MPC83xx_DMA_OFFSET	(0x8000)
+#define CONFIG_SYS_MPC83xx_DMA_ADDR	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC83xx_DMA_OFFSET)
+#define CONFIG_SYS_MPC83xx_ESDHC_OFFSET	(0x2e000)
+#define CONFIG_SYS_MPC83xx_ESDHC_ADDR	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC83xx_ESDHC_OFFSET)
+
+#ifndef CONFIG_SYS_MPC83xx_USB_OFFSET
+#define CONFIG_SYS_MPC83xx_USB_OFFSET  0x23000
+#endif
+#define CONFIG_SYS_MPC83xx_USB_ADDR \
+			(CONFIG_SYS_IMMR + CONFIG_SYS_MPC83xx_USB_OFFSET)
+
+#define CONFIG_SYS_TSEC1_OFFSET		0x24000
+#define CONFIG_SYS_MDIO1_OFFSET		0x24000
+
+#define TSEC_BASE_ADDR		(CONFIG_SYS_IMMR + CONFIG_SYS_TSEC1_OFFSET)
+#define MDIO_BASE_ADDR		(CONFIG_SYS_IMMR + CONFIG_SYS_MDIO1_OFFSET)
+#endif				/* __IMMAP_83xx__ */
diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h
new file mode 100644
index 0000000..957ad76
--- /dev/null
+++ b/arch/powerpc/include/asm/immap_85xx.h
@@ -0,0 +1,2106 @@
+/*
+ * MPC85xx Internal Memory Map
+ *
+ * Copyright 2007-2009 Freescale Semiconductor, Inc.
+ *
+ * Copyright(c) 2002,2003 Motorola Inc.
+ * Xianghua Xiao (x.xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __IMMAP_85xx__
+#define __IMMAP_85xx__
+
+#include <asm/types.h>
+#include <asm/fsl_dma.h>
+#include <asm/fsl_i2c.h>
+#include <asm/fsl_lbc.h>
+
+typedef struct ccsr_local {
+	u32	ccsrbarh;	/* CCSR Base Addr High */
+	u32	ccsrbarl;	/* CCSR Base Addr Low */
+	u32	ccsrar;		/* CCSR Attr */
+#define CCSRAR_C	0x80000000	/* Commit */
+	u8	res1[4];
+	u32	altcbarh;	/* Alternate Configuration Base Addr High */
+	u32	altcbarl;	/* Alternate Configuration Base Addr Low */
+	u32	altcar;		/* Alternate Configuration Attr */
+	u8	res2[4];
+	u32	bstrh;		/* Boot space translation high */
+	u32	bstrl;		/* Boot space translation Low */
+	u32	bstrar;		/* Boot space translation attributes */
+	u8	res3[0xbd4];
+	struct {
+		u32	lawbarh;	/* LAWn base addr high */
+		u32	lawbarl;	/* LAWn base addr low */
+		u32	lawar;		/* LAWn attributes */
+		u8	res4[4];
+	} law[32];
+	u8	res35[0x204];
+} ccsr_local_t;
+
+/* Local-Access Registers & ECM Registers */
+typedef struct ccsr_local_ecm {
+	u32	ccsrbar;	/* CCSR Base Addr */
+	u8	res1[4];
+	u32	altcbar;	/* Alternate Configuration Base Addr */
+	u8	res2[4];
+	u32	altcar;		/* Alternate Configuration Attr */
+	u8	res3[12];
+	u32	bptr;		/* Boot Page Translation */
+	u8	res4[3044];
+	u32	lawbar0;	/* Local Access Window 0 Base Addr */
+	u8	res5[4];
+	u32	lawar0;		/* Local Access Window 0 Attrs */
+	u8	res6[20];
+	u32	lawbar1;	/* Local Access Window 1 Base Addr */
+	u8	res7[4];
+	u32	lawar1;		/* Local Access Window 1 Attrs */
+	u8	res8[20];
+	u32	lawbar2;	/* Local Access Window 2 Base Addr */
+	u8	res9[4];
+	u32	lawar2;		/* Local Access Window 2 Attrs */
+	u8	res10[20];
+	u32	lawbar3;	/* Local Access Window 3 Base Addr */
+	u8	res11[4];
+	u32	lawar3;		/* Local Access Window 3 Attrs */
+	u8	res12[20];
+	u32	lawbar4;	/* Local Access Window 4 Base Addr */
+	u8	res13[4];
+	u32	lawar4;		/* Local Access Window 4 Attrs */
+	u8	res14[20];
+	u32	lawbar5;	/* Local Access Window 5 Base Addr */
+	u8	res15[4];
+	u32	lawar5;		/* Local Access Window 5 Attrs */
+	u8	res16[20];
+	u32	lawbar6;	/* Local Access Window 6 Base Addr */
+	u8	res17[4];
+	u32	lawar6;		/* Local Access Window 6 Attrs */
+	u8	res18[20];
+	u32	lawbar7;	/* Local Access Window 7 Base Addr */
+	u8	res19[4];
+	u32	lawar7;		/* Local Access Window 7 Attrs */
+	u8	res19_8a[20];
+	u32	lawbar8;	/* Local Access Window 8 Base Addr */
+	u8	res19_8b[4];
+	u32	lawar8;		/* Local Access Window 8 Attrs */
+	u8	res19_9a[20];
+	u32	lawbar9;	/* Local Access Window 9 Base Addr */
+	u8	res19_9b[4];
+	u32	lawar9;		/* Local Access Window 9 Attrs */
+	u8	res19_10a[20];
+	u32	lawbar10;	/* Local Access Window 10 Base Addr */
+	u8	res19_10b[4];
+	u32	lawar10;	/* Local Access Window 10 Attrs */
+	u8	res19_11a[20];
+	u32	lawbar11;	/* Local Access Window 11 Base Addr */
+	u8	res19_11b[4];
+	u32	lawar11;	/* Local Access Window 11 Attrs */
+	u8	res20[652];
+	u32	eebacr;		/* ECM CCB Addr Configuration */
+	u8	res21[12];
+	u32	eebpcr;		/* ECM CCB Port Configuration */
+	u8	res22[3564];
+	u32	eedr;		/* ECM Error Detect */
+	u8	res23[4];
+	u32	eeer;		/* ECM Error Enable */
+	u32	eeatr;		/* ECM Error Attrs Capture */
+	u32	eeadr;		/* ECM Error Addr Capture */
+	u8	res24[492];
+} ccsr_local_ecm_t;
+
+/* DDR memory controller registers */
+typedef struct ccsr_ddr {
+	u32	cs0_bnds;		/* Chip Select 0 Memory Bounds */
+	u8	res1[4];
+	u32	cs1_bnds;		/* Chip Select 1 Memory Bounds */
+	u8	res2[4];
+	u32	cs2_bnds;		/* Chip Select 2 Memory Bounds */
+	u8	res3[4];
+	u32	cs3_bnds;		/* Chip Select 3 Memory Bounds */
+	u8	res4[100];
+	u32	cs0_config;		/* Chip Select Configuration */
+	u32	cs1_config;		/* Chip Select Configuration */
+	u32	cs2_config;		/* Chip Select Configuration */
+	u32	cs3_config;		/* Chip Select Configuration */
+	u8	res4a[48];
+	u32	cs0_config_2;		/* Chip Select Configuration 2 */
+	u32	cs1_config_2;		/* Chip Select Configuration 2 */
+	u32	cs2_config_2;		/* Chip Select Configuration 2 */
+	u32	cs3_config_2;		/* Chip Select Configuration 2 */
+	u8	res5[48];
+	u32	timing_cfg_3;		/* SDRAM Timing Configuration 3 */
+	u32	timing_cfg_0;		/* SDRAM Timing Configuration 0 */
+	u32	timing_cfg_1;		/* SDRAM Timing Configuration 1 */
+	u32	timing_cfg_2;		/* SDRAM Timing Configuration 2 */
+	u32	sdram_cfg;		/* SDRAM Control Configuration */
+	u32	sdram_cfg_2;		/* SDRAM Control Configuration 2 */
+	u32	sdram_mode;		/* SDRAM Mode Configuration */
+	u32	sdram_mode_2;		/* SDRAM Mode Configuration 2 */
+	u32	sdram_md_cntl;		/* SDRAM Mode Control */
+	u32	sdram_interval;		/* SDRAM Interval Configuration */
+	u32	sdram_data_init;	/* SDRAM Data initialization */
+	u8	res6[4];
+	u32	sdram_clk_cntl;		/* SDRAM Clock Control */
+	u8	res7[20];
+	u32	init_addr;		/* training init addr */
+	u32	init_ext_addr;		/* training init extended addr */
+	u8	res8_1[16];
+	u32	timing_cfg_4;		/* SDRAM Timing Configuration 4 */
+	u32	timing_cfg_5;		/* SDRAM Timing Configuration 5 */
+	u8	reg8_1a[8];
+	u32	ddr_zq_cntl;		/* ZQ calibration control*/
+	u32	ddr_wrlvl_cntl;		/* write leveling control*/
+	u8	reg8_1aa[4];
+	u32	ddr_sr_cntr;		/* self refresh counter */
+	u32	ddr_sdram_rcw_1;	/* Control Words 1 */
+	u32	ddr_sdram_rcw_2;	/* Control Words 2 */
+	u8	res8_1b[2456];
+	u32	ddr_dsr1;		/* Debug Status 1 */
+	u32	ddr_dsr2;		/* Debug Status 2 */
+	u32	ddr_cdr1;		/* Control Driver 1 */
+	u32	ddr_cdr2;		/* Control Driver 2 */
+	u8	res8_1c[200];
+	u32	ip_rev1;		/* IP Block Revision 1 */
+	u32	ip_rev2;		/* IP Block Revision 2 */
+	u8	res8_2[512];
+	u32	data_err_inject_hi;	/* Data Path Err Injection Mask High */
+	u32	data_err_inject_lo;	/* Data Path Err Injection Mask Low */
+	u32	ecc_err_inject;		/* Data Path Err Injection Mask ECC */
+	u8	res9[20];
+	u32	capture_data_hi;	/* Data Path Read Capture High */
+	u32	capture_data_lo;	/* Data Path Read Capture Low */
+	u32	capture_ecc;		/* Data Path Read Capture ECC */
+	u8	res10[20];
+	u32	err_detect;		/* Error Detect */
+	u32	err_disable;		/* Error Disable */
+	u32	err_int_en;
+	u32	capture_attributes;	/* Error Attrs Capture */
+	u32	capture_address;	/* Error Addr Capture */
+	u32	capture_ext_address;	/* Error Extended Addr Capture */
+	u32	err_sbe;		/* Single-Bit ECC Error Management */
+	u8	res11[164];
+	u32	debug_1;
+	u32	debug_2;
+	u32	debug_3;
+	u32	debug_4;
+	u32	debug_5;
+	u32	debug_6;
+	u32	debug_7;
+	u32	debug_8;
+	u32	debug_9;
+	u32	debug_10;
+	u32	debug_11;
+	u32	debug_12;
+	u32	debug_13;
+	u32	debug_14;
+	u32	debug_15;
+	u32	debug_16;
+	u32	debug_17;
+	u32	debug_18;
+	u8	res12[184];
+} ccsr_ddr_t;
+
+/* I2C Registers */
+typedef struct ccsr_i2c {
+	struct fsl_i2c	i2c[1];
+	u8	res[4096 - 1 * sizeof(struct fsl_i2c)];
+} ccsr_i2c_t;
+
+#if defined(CONFIG_MPC8540) \
+	|| defined(CONFIG_MPC8541) \
+	|| defined(CONFIG_MPC8548) \
+	|| defined(CONFIG_MPC8555)
+/* DUART Registers */
+typedef struct ccsr_duart {
+	u8	res1[1280];
+/* URBR1, UTHR1, UDLB1 with the same addr */
+	u8	urbr1_uthr1_udlb1;
+/* UIER1, UDMB1 with the same addr01 */
+	u8	uier1_udmb1;
+/* UIIR1, UFCR1, UAFR1 with the same addr */
+	u8	uiir1_ufcr1_uafr1;
+	u8	ulcr1;		/* UART1 Line Control */
+	u8	umcr1;		/* UART1 Modem Control */
+	u8	ulsr1;		/* UART1 Line Status */
+	u8	umsr1;		/* UART1 Modem Status */
+	u8	uscr1;		/* UART1 Scratch */
+	u8	res2[8];
+	u8	udsr1;		/* UART1 DMA Status */
+	u8	res3[239];
+/* URBR2, UTHR2, UDLB2 with the same addr */
+	u8	urbr2_uthr2_udlb2;
+/* UIER2, UDMB2 with the same addr */
+	u8	uier2_udmb2;
+/* UIIR2, UFCR2, UAFR2 with the same addr */
+	u8	uiir2_ufcr2_uafr2;
+	u8	ulcr2;		/* UART2 Line Control */
+	u8	umcr2;		/* UART2 Modem Control */
+	u8	ulsr2;		/* UART2 Line Status */
+	u8	umsr2;		/* UART2 Modem Status */
+	u8	uscr2;		/* UART2 Scratch */
+	u8	res4[8];
+	u8	udsr2;		/* UART2 DMA Status */
+	u8	res5[2543];
+} ccsr_duart_t;
+#else /* MPC8560 uses UART on its CPM */
+typedef struct ccsr_duart {
+	u8 res[4096];
+} ccsr_duart_t;
+#endif
+
+/* Local Bus Controller Registers */
+typedef struct ccsr_lbc {
+	u32	br0;		/* LBC Base 0 */
+	u32	or0;		/* LBC Options 0 */
+	u32	br1;		/* LBC Base 1 */
+	u32	or1;		/* LBC Options 1 */
+	u32	br2;		/* LBC Base 2 */
+	u32	or2;		/* LBC Options 2 */
+	u32	br3;		/* LBC Base 3 */
+	u32	or3;		/* LBC Options 3 */
+	u32	br4;		/* LBC Base 4 */
+	u32	or4;		/* LBC Options 4 */
+	u32	br5;		/* LBC Base 5 */
+	u32	or5;		/* LBC Options 5 */
+	u32	br6;		/* LBC Base 6 */
+	u32	or6;		/* LBC Options 6 */
+	u32	br7;		/* LBC Base 7 */
+	u32	or7;		/* LBC Options 7 */
+	u8	res1[40];
+	u32	mar;		/* LBC UPM Addr */
+	u8	res2[4];
+	u32	mamr;		/* LBC UPMA Mode */
+	u32	mbmr;		/* LBC UPMB Mode */
+	u32	mcmr;		/* LBC UPMC Mode */
+	u8	res3[8];
+	u32	mrtpr;		/* LBC Memory Refresh Timer Prescaler */
+	u32	mdr;		/* LBC UPM Data */
+	u8	res4[8];
+	u32	lsdmr;		/* LBC SDRAM Mode */
+	u8	res5[8];
+	u32	lurt;		/* LBC UPM Refresh Timer */
+	u32	lsrt;		/* LBC SDRAM Refresh Timer */
+	u8	res6[8];
+	u32	ltesr;		/* LBC Transfer Error Status */
+	u32	ltedr;		/* LBC Transfer Error Disable */
+	u32	lteir;		/* LBC Transfer Error IRQ */
+	u32	lteatr;		/* LBC Transfer Error Attrs */
+	u32	ltear;		/* LBC Transfer Error Addr */
+	u8	res7[12];
+	u32	lbcr;		/* LBC Configuration */
+	u32	lcrr;		/* LBC Clock Ratio */
+	u8	res8[3880];
+} ccsr_lbc_t;
+
+/* eSPI Registers */
+typedef struct ccsr_espi {
+	u32	mode;		/* eSPI mode */
+	u32	event;		/* eSPI event */
+	u32	mask;		/* eSPI mask */
+	u32	com;		/* eSPI command */
+	u32	tx;		/* eSPI transmit FIFO access */
+	u32	rx;		/* eSPI receive FIFO access */
+	u8	res1[8];	/* reserved */
+	u32	csmode[4];	/* 0x2c: sSPI CS0/1/2/3 mode */
+	u8	res2[4048];	/* fill up to 0x1000 */
+} ccsr_espi_t;
+
+/* PCI Registers */
+typedef struct ccsr_pcix {
+	u32	cfg_addr;	/* PCIX Configuration Addr */
+	u32	cfg_data;	/* PCIX Configuration Data */
+	u32	int_ack;	/* PCIX IRQ Acknowledge */
+	u8	res1[3060];
+	u32	potar0;		/* PCIX Outbound Transaction Addr 0 */
+	u32	potear0;	/* PCIX Outbound Translation Extended Addr 0 */
+	u32	powbar0;	/* PCIX Outbound Window Base Addr 0 */
+	u32	powbear0;	/* PCIX Outbound Window Base Extended Addr 0 */
+	u32	powar0;		/* PCIX Outbound Window Attrs 0 */
+	u8	res2[12];
+	u32	potar1;		/* PCIX Outbound Transaction Addr 1 */
+	u32	potear1;	/* PCIX Outbound Translation Extended Addr 1 */
+	u32	powbar1;	/* PCIX Outbound Window Base Addr 1 */
+	u32	powbear1;	/* PCIX Outbound Window Base Extended Addr 1 */
+	u32	powar1;		/* PCIX Outbound Window Attrs 1 */
+	u8	res3[12];
+	u32	potar2;		/* PCIX Outbound Transaction Addr 2 */
+	u32	potear2;	/* PCIX Outbound Translation Extended Addr 2 */
+	u32	powbar2;	/* PCIX Outbound Window Base Addr 2 */
+	u32	powbear2;	/* PCIX Outbound Window Base Extended Addr 2 */
+	u32	powar2;		/* PCIX Outbound Window Attrs 2 */
+	u8	res4[12];
+	u32	potar3;		/* PCIX Outbound Transaction Addr 3 */
+	u32	potear3;	/* PCIX Outbound Translation Extended Addr 3 */
+	u32	powbar3;	/* PCIX Outbound Window Base Addr 3 */
+	u32	powbear3;	/* PCIX Outbound Window Base Extended Addr 3 */
+	u32	powar3;		/* PCIX Outbound Window Attrs 3 */
+	u8	res5[12];
+	u32	potar4;		/* PCIX Outbound Transaction Addr 4 */
+	u32	potear4;	/* PCIX Outbound Translation Extended Addr 4 */
+	u32	powbar4;	/* PCIX Outbound Window Base Addr 4 */
+	u32	powbear4;	/* PCIX Outbound Window Base Extended Addr 4 */
+	u32	powar4;		/* PCIX Outbound Window Attrs 4 */
+	u8	res6[268];
+	u32	pitar3;		/* PCIX Inbound Translation Addr 3 */
+	u32	pitear3;	/* PCIX Inbound Translation Extended Addr 3 */
+	u32	piwbar3;	/* PCIX Inbound Window Base Addr 3 */
+	u32	piwbear3;	/* PCIX Inbound Window Base Extended Addr 3 */
+	u32	piwar3;		/* PCIX Inbound Window Attrs 3 */
+	u8	res7[12];
+	u32	pitar2;		/* PCIX Inbound Translation Addr 2 */
+	u32	pitear2;	/* PCIX Inbound Translation Extended Addr 2 */
+	u32	piwbar2;	/* PCIX Inbound Window Base Addr 2 */
+	u32	piwbear2;	/* PCIX Inbound Window Base Extended Addr 2 */
+	u32	piwar2;		/* PCIX Inbound Window Attrs 2 */
+	u8	res8[12];
+	u32	pitar1;		/* PCIX Inbound Translation Addr 1 */
+	u32	pitear1;	/* PCIX Inbound Translation Extended Addr 1 */
+	u32	piwbar1;	/* PCIX Inbound Window Base Addr 1 */
+	u8	res9[4];
+	u32	piwar1;		/* PCIX Inbound Window Attrs 1 */
+	u8	res10[12];
+	u32	pedr;		/* PCIX Error Detect */
+	u32	pecdr;		/* PCIX Error Capture Disable */
+	u32	peer;		/* PCIX Error Enable */
+	u32	peattrcr;	/* PCIX Error Attrs Capture */
+	u32	peaddrcr;	/* PCIX Error Addr Capture */
+	u32	peextaddrcr;	/* PCIX Error Extended Addr Capture */
+	u32	pedlcr;		/* PCIX Error Data Low Capture */
+	u32	pedhcr;		/* PCIX Error Error Data High Capture */
+	u32	gas_timr;	/* PCIX Gasket Timer */
+	u8	res11[476];
+} ccsr_pcix_t;
+
+#define PCIX_COMMAND	0x62
+#define POWAR_EN	0x80000000
+#define POWAR_IO_READ	0x00080000
+#define POWAR_MEM_READ	0x00040000
+#define POWAR_IO_WRITE	0x00008000
+#define POWAR_MEM_WRITE	0x00004000
+#define POWAR_MEM_512M	0x0000001c
+#define POWAR_IO_1M	0x00000013
+
+#define PIWAR_EN	0x80000000
+#define PIWAR_PF	0x20000000
+#define PIWAR_LOCAL	0x00f00000
+#define PIWAR_READ_SNOOP	0x00050000
+#define PIWAR_WRITE_SNOOP	0x00005000
+#define PIWAR_MEM_2G		0x0000001e
+
+typedef struct ccsr_gpio {
+	u32	gpdir;
+	u32	gpodr;
+	u32	gpdat;
+	u32	gpier;
+	u32	gpimr;
+	u32	gpicr;
+} ccsr_gpio_t;
+
+/* L2 Cache Registers */
+typedef struct ccsr_l2cache {
+	u32	l2ctl;		/* L2 configuration 0 */
+	u8	res1[12];
+	u32	l2cewar0;	/* L2 cache external write addr 0 */
+	u8	res2[4];
+	u32	l2cewcr0;	/* L2 cache external write control 0 */
+	u8	res3[4];
+	u32	l2cewar1;	/* L2 cache external write addr 1 */
+	u8	res4[4];
+	u32	l2cewcr1;	/* L2 cache external write control 1 */
+	u8	res5[4];
+	u32	l2cewar2;	/* L2 cache external write addr 2 */
+	u8	res6[4];
+	u32	l2cewcr2;	/* L2 cache external write control 2 */
+	u8	res7[4];
+	u32	l2cewar3;	/* L2 cache external write addr 3 */
+	u8	res8[4];
+	u32	l2cewcr3;	/* L2 cache external write control 3 */
+	u8	res9[180];
+	u32	l2srbar0;	/* L2 memory-mapped SRAM base addr 0 */
+	u8	res10[4];
+	u32	l2srbar1;	/* L2 memory-mapped SRAM base addr 1 */
+	u8	res11[3316];
+	u32	l2errinjhi;	/* L2 error injection mask high */
+	u32	l2errinjlo;	/* L2 error injection mask low */
+	u32	l2errinjctl;	/* L2 error injection tag/ECC control */
+	u8	res12[20];
+	u32	l2captdatahi;	/* L2 error data high capture */
+	u32	l2captdatalo;	/* L2 error data low capture */
+	u32	l2captecc;	/* L2 error ECC capture */
+	u8	res13[20];
+	u32	l2errdet;	/* L2 error detect */
+	u32	l2errdis;	/* L2 error disable */
+	u32	l2errinten;	/* L2 error interrupt enable */
+	u32	l2errattr;	/* L2 error attributes capture */
+	u32	l2erraddr;	/* L2 error addr capture */
+	u8	res14[4];
+	u32	l2errctl;	/* L2 error control */
+	u8	res15[420];
+} ccsr_l2cache_t;
+
+#define MPC85xx_L2CTL_L2E			0x80000000
+#define MPC85xx_L2CTL_L2SRAM_ENTIRE		0x00010000
+#define MPC85xx_L2ERRDIS_MBECC			0x00000008
+#define MPC85xx_L2ERRDIS_SBECC			0x00000004
+
+/* DMA Registers */
+typedef struct ccsr_dma {
+	u8	res1[256];
+	struct fsl_dma dma[4];
+	u32	dgsr;		/* DMA General Status */
+	u8	res2[11516];
+} ccsr_dma_t;
+
+/* tsec */
+typedef struct ccsr_tsec {
+	u8	res1[16];
+	u32	ievent;		/* IRQ Event */
+	u32	imask;		/* IRQ Mask */
+	u32	edis;		/* Error Disabled */
+	u8	res2[4];
+	u32	ecntrl;		/* Ethernet Control */
+	u32	minflr;		/* Minimum Frame Len */
+	u32	ptv;		/* Pause Time Value */
+	u32	dmactrl;	/* DMA Control */
+	u32	tbipa;		/* TBI PHY Addr */
+	u8	res3[88];
+	u32	fifo_tx_thr;		/* FIFO transmit threshold */
+	u8	res4[8];
+	u32	fifo_tx_starve;		/* FIFO transmit starve */
+	u32	fifo_tx_starve_shutoff;	/* FIFO transmit starve shutoff */
+	u8	res5[96];
+	u32	tctrl;		/* TX Control */
+	u32	tstat;		/* TX Status */
+	u8	res6[4];
+	u32	tbdlen;		/* TX Buffer Desc Data Len */
+	u8	res7[16];
+	u32	ctbptrh;	/* Current TX Buffer Desc Ptr High */
+	u32	ctbptr;		/* Current TX Buffer Desc Ptr */
+	u8	res8[88];
+	u32	tbptrh;		/* TX Buffer Desc Ptr High */
+	u32	tbptr;		/* TX Buffer Desc Ptr Low */
+	u8	res9[120];
+	u32	tbaseh;		/* TX Desc Base Addr High */
+	u32	tbase;		/* TX Desc Base Addr */
+	u8	res10[168];
+	u32	ostbd;		/* Out-of-Sequence(OOS) TX Buffer Desc */
+	u32	ostbdp;		/* OOS TX Data Buffer Ptr */
+	u32	os32tbdp;	/* OOS 32 Bytes TX Data Buffer Ptr Low */
+	u32	os32iptrh;	/* OOS 32 Bytes TX Insert Ptr High */
+	u32	os32iptrl;	/* OOS 32 Bytes TX Insert Ptr Low */
+	u32	os32tbdr;	/* OOS 32 Bytes TX Reserved */
+	u32	os32iil;	/* OOS 32 Bytes TX Insert Idx/Len */
+	u8	res11[52];
+	u32	rctrl;		/* RX Control */
+	u32	rstat;		/* RX Status */
+	u8	res12[4];
+	u32	rbdlen;		/* RxBD Data Len */
+	u8	res13[16];
+	u32	crbptrh;	/* Current RX Buffer Desc Ptr High */
+	u32	crbptr;		/* Current RX Buffer Desc Ptr */
+	u8	res14[24];
+	u32	mrblr;		/* Maximum RX Buffer Len */
+	u32	mrblr2r3;	/* Maximum RX Buffer Len R2R3 */
+	u8	res15[56];
+	u32	rbptrh;		/* RX Buffer Desc Ptr High 0 */
+	u32	rbptr;		/* RX Buffer Desc Ptr */
+	u32	rbptrh1;	/* RX Buffer Desc Ptr High 1 */
+	u32	rbptrl1;	/* RX Buffer Desc Ptr Low 1 */
+	u32	rbptrh2;	/* RX Buffer Desc Ptr High 2 */
+	u32	rbptrl2;	/* RX Buffer Desc Ptr Low 2 */
+	u32	rbptrh3;	/* RX Buffer Desc Ptr High 3 */
+	u32	rbptrl3;	/* RX Buffer Desc Ptr Low 3 */
+	u8	res16[96];
+	u32	rbaseh;		/* RX Desc Base Addr High 0 */
+	u32	rbase;		/* RX Desc Base Addr */
+	u32	rbaseh1;	/* RX Desc Base Addr High 1 */
+	u32	rbasel1;	/* RX Desc Base Addr Low 1 */
+	u32	rbaseh2;	/* RX Desc Base Addr High 2 */
+	u32	rbasel2;	/* RX Desc Base Addr Low 2 */
+	u32	rbaseh3;	/* RX Desc Base Addr High 3 */
+	u32	rbasel3;	/* RX Desc Base Addr Low 3 */
+	u8	res17[224];
+	u32	maccfg1;	/* MAC Configuration 1 */
+	u32	maccfg2;	/* MAC Configuration 2 */
+	u32	ipgifg;		/* Inter Packet Gap/Inter Frame Gap */
+	u32	hafdup;		/* Half Duplex */
+	u32	maxfrm;		/* Maximum Frame Len */
+	u8	res18[12];
+	u32	miimcfg;	/* MII Management Configuration */
+	u32	miimcom;	/* MII Management Cmd */
+	u32	miimadd;	/* MII Management Addr */
+	u32	miimcon;	/* MII Management Control */
+	u32	miimstat;	/* MII Management Status */
+	u32	miimind;	/* MII Management Indicator */
+	u8	res19[4];
+	u32	ifstat;		/* Interface Status */
+	u32	macstnaddr1;	/* Station Addr Part 1 */
+	u32	macstnaddr2;	/* Station Addr Part 2 */
+	u8	res20[312];
+	u32	tr64;		/* TX & RX 64-byte Frame Counter */
+	u32	tr127;		/* TX & RX 65-127 byte Frame Counter */
+	u32	tr255;		/* TX & RX 128-255 byte Frame Counter */
+	u32	tr511;		/* TX & RX 256-511 byte Frame Counter */
+	u32	tr1k;		/* TX & RX 512-1023 byte Frame Counter */
+	u32	trmax;		/* TX & RX 1024-1518 byte Frame Counter */
+	u32	trmgv;		/* TX & RX 1519-1522 byte Good VLAN Frame */
+	u32	rbyt;		/* RX Byte Counter */
+	u32	rpkt;		/* RX Packet Counter */
+	u32	rfcs;		/* RX FCS Error Counter */
+	u32	rmca;		/* RX Multicast Packet Counter */
+	u32	rbca;		/* RX Broadcast Packet Counter */
+	u32	rxcf;		/* RX Control Frame Packet Counter */
+	u32	rxpf;		/* RX Pause Frame Packet Counter */
+	u32	rxuo;		/* RX Unknown OP Code Counter */
+	u32	raln;		/* RX Alignment Error Counter */
+	u32	rflr;		/* RX Frame Len Error Counter */
+	u32	rcde;		/* RX Code Error Counter */
+	u32	rcse;		/* RX Carrier Sense Error Counter */
+	u32	rund;		/* RX Undersize Packet Counter */
+	u32	rovr;		/* RX Oversize Packet Counter */
+	u32	rfrg;		/* RX Fragments Counter */
+	u32	rjbr;		/* RX Jabber Counter */
+	u32	rdrp;		/* RX Drop Counter */
+	u32	tbyt;		/* TX Byte Counter Counter */
+	u32	tpkt;		/* TX Packet Counter */
+	u32	tmca;		/* TX Multicast Packet Counter */
+	u32	tbca;		/* TX Broadcast Packet Counter */
+	u32	txpf;		/* TX Pause Control Frame Counter */
+	u32	tdfr;		/* TX Deferral Packet Counter */
+	u32	tedf;		/* TX Excessive Deferral Packet Counter */
+	u32	tscl;		/* TX Single Collision Packet Counter */
+	u32	tmcl;		/* TX Multiple Collision Packet Counter */
+	u32	tlcl;		/* TX Late Collision Packet Counter */
+	u32	txcl;		/* TX Excessive Collision Packet Counter */
+	u32	tncl;		/* TX Total Collision Counter */
+	u8	res21[4];
+	u32	tdrp;		/* TX Drop Frame Counter */
+	u32	tjbr;		/* TX Jabber Frame Counter */
+	u32	tfcs;		/* TX FCS Error Counter */
+	u32	txcf;		/* TX Control Frame Counter */
+	u32	tovr;		/* TX Oversize Frame Counter */
+	u32	tund;		/* TX Undersize Frame Counter */
+	u32	tfrg;		/* TX Fragments Frame Counter */
+	u32	car1;		/* Carry One */
+	u32	car2;		/* Carry Two */
+	u32	cam1;		/* Carry Mask One */
+	u32	cam2;		/* Carry Mask Two */
+	u8	res22[192];
+	u32	iaddr0;		/* Indivdual addr 0 */
+	u32	iaddr1;		/* Indivdual addr 1 */
+	u32	iaddr2;		/* Indivdual addr 2 */
+	u32	iaddr3;		/* Indivdual addr 3 */
+	u32	iaddr4;		/* Indivdual addr 4 */
+	u32	iaddr5;		/* Indivdual addr 5 */
+	u32	iaddr6;		/* Indivdual addr 6 */
+	u32	iaddr7;		/* Indivdual addr 7 */
+	u8	res23[96];
+	u32	gaddr0;		/* Global addr 0 */
+	u32	gaddr1;		/* Global addr 1 */
+	u32	gaddr2;		/* Global addr 2 */
+	u32	gaddr3;		/* Global addr 3 */
+	u32	gaddr4;		/* Global addr 4 */
+	u32	gaddr5;		/* Global addr 5 */
+	u32	gaddr6;		/* Global addr 6 */
+	u32	gaddr7;		/* Global addr 7 */
+	u8	res24[96];
+	u32	pmd0;		/* Pattern Match Data */
+	u8	res25[4];
+	u32	pmask0;		/* Pattern Mask */
+	u8	res26[4];
+	u32	pcntrl0;	/* Pattern Match Control */
+	u8	res27[4];
+	u32	pattrb0;	/* Pattern Match Attrs */
+	u32	pattrbeli0;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd1;		/* Pattern Match Data */
+	u8	res28[4];
+	u32	pmask1;		/* Pattern Mask */
+	u8	res29[4];
+	u32	pcntrl1;	/* Pattern Match Control */
+	u8	res30[4];
+	u32	pattrb1;	/* Pattern Match Attrs */
+	u32	pattrbeli1;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd2;		/* Pattern Match Data */
+	u8	res31[4];
+	u32	pmask2;		/* Pattern Mask */
+	u8	res32[4];
+	u32	pcntrl2;	/* Pattern Match Control */
+	u8	res33[4];
+	u32	pattrb2;	/* Pattern Match Attrs */
+	u32	pattrbeli2;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd3;		/* Pattern Match Data */
+	u8	res34[4];
+	u32	pmask3;		/* Pattern Mask */
+	u8	res35[4];
+	u32	pcntrl3;	/* Pattern Match Control */
+	u8	res36[4];
+	u32	pattrb3;	/* Pattern Match Attrs */
+	u32	pattrbeli3;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd4;		/* Pattern Match Data */
+	u8	res37[4];
+	u32	pmask4;		/* Pattern Mask */
+	u8	res38[4];
+	u32	pcntrl4;	/* Pattern Match Control */
+	u8	res39[4];
+	u32	pattrb4;	/* Pattern Match Attrs */
+	u32	pattrbeli4;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd5;		/* Pattern Match Data */
+	u8	res40[4];
+	u32	pmask5;		/* Pattern Mask */
+	u8	res41[4];
+	u32	pcntrl5;	/* Pattern Match Control */
+	u8	res42[4];
+	u32	pattrb5;	/* Pattern Match Attrs */
+	u32	pattrbeli5;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd6;		/* Pattern Match Data */
+	u8	res43[4];
+	u32	pmask6;		/* Pattern Mask */
+	u8	res44[4];
+	u32	pcntrl6;	/* Pattern Match Control */
+	u8	res45[4];
+	u32	pattrb6;	/* Pattern Match Attrs */
+	u32	pattrbeli6;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd7;		/* Pattern Match Data */
+	u8	res46[4];
+	u32	pmask7;		/* Pattern Mask */
+	u8	res47[4];
+	u32	pcntrl7;	/* Pattern Match Control */
+	u8	res48[4];
+	u32	pattrb7;	/* Pattern Match Attrs */
+	u32	pattrbeli7;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd8;		/* Pattern Match Data */
+	u8	res49[4];
+	u32	pmask8;		/* Pattern Mask */
+	u8	res50[4];
+	u32	pcntrl8;	/* Pattern Match Control */
+	u8	res51[4];
+	u32	pattrb8;	/* Pattern Match Attrs */
+	u32	pattrbeli8;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd9;		/* Pattern Match Data */
+	u8	res52[4];
+	u32	pmask9;		/* Pattern Mask */
+	u8	res53[4];
+	u32	pcntrl9;	/* Pattern Match Control */
+	u8	res54[4];
+	u32	pattrb9;	/* Pattern Match Attrs */
+	u32	pattrbeli9;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd10;		/* Pattern Match Data */
+	u8	res55[4];
+	u32	pmask10;	/* Pattern Mask */
+	u8	res56[4];
+	u32	pcntrl10;	/* Pattern Match Control */
+	u8	res57[4];
+	u32	pattrb10;	/* Pattern Match Attrs */
+	u32	pattrbeli10;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd11;		/* Pattern Match Data */
+	u8	res58[4];
+	u32	pmask11;	/* Pattern Mask */
+	u8	res59[4];
+	u32	pcntrl11;	/* Pattern Match Control */
+	u8	res60[4];
+	u32	pattrb11;	/* Pattern Match Attrs */
+	u32	pattrbeli11;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd12;		/* Pattern Match Data */
+	u8	res61[4];
+	u32	pmask12;	/* Pattern Mask */
+	u8	res62[4];
+	u32	pcntrl12;	/* Pattern Match Control */
+	u8	res63[4];
+	u32	pattrb12;	/* Pattern Match Attrs */
+	u32	pattrbeli12;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd13;		/* Pattern Match Data */
+	u8	res64[4];
+	u32	pmask13;	/* Pattern Mask */
+	u8	res65[4];
+	u32	pcntrl13;	/* Pattern Match Control */
+	u8	res66[4];
+	u32	pattrb13;	/* Pattern Match Attrs */
+	u32	pattrbeli13;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd14;		/* Pattern Match Data */
+	u8	res67[4];
+	u32	pmask14;	/* Pattern Mask */
+	u8	res68[4];
+	u32	pcntrl14;	/* Pattern Match Control */
+	u8	res69[4];
+	u32	pattrb14;	/* Pattern Match Attrs */
+	u32	pattrbeli14;	/* Pattern Match Attrs Extract Len & Idx */
+	u32	pmd15;		/* Pattern Match Data */
+	u8	res70[4];
+	u32	pmask15;	/* Pattern Mask */
+	u8	res71[4];
+	u32	pcntrl15;	/* Pattern Match Control */
+	u8	res72[4];
+	u32	pattrb15;	/* Pattern Match Attrs */
+	u32	pattrbeli15;	/* Pattern Match Attrs Extract Len & Idx */
+	u8	res73[248];
+	u32	attr;		/* Attrs */
+	u32	attreli;	/* Attrs Extract Len & Idx */
+	u8	res74[1024];
+} ccsr_tsec_t;
+
+/* PIC Registers */
+typedef struct ccsr_pic {
+	u8	res1[64];
+	u32	ipidr0;		/* Interprocessor IRQ Dispatch 0 */
+	u8	res2[12];
+	u32	ipidr1;		/* Interprocessor IRQ Dispatch 1 */
+	u8	res3[12];
+	u32	ipidr2;		/* Interprocessor IRQ Dispatch 2 */
+	u8	res4[12];
+	u32	ipidr3;		/* Interprocessor IRQ Dispatch 3 */
+	u8	res5[12];
+	u32	ctpr;		/* Current Task Priority */
+	u8	res6[12];
+	u32	whoami;		/* Who Am I */
+	u8	res7[12];
+	u32	iack;		/* IRQ Acknowledge */
+	u8	res8[12];
+	u32	eoi;		/* End Of IRQ */
+	u8	res9[3916];
+	u32	frr;		/* Feature Reporting */
+	u8	res10[28];
+	u32	gcr;		/* Global Configuration */
+#define MPC85xx_PICGCR_RST	0x80000000
+#define MPC85xx_PICGCR_M	0x20000000
+	u8	res11[92];
+	u32	vir;		/* Vendor Identification */
+	u8	res12[12];
+	u32	pir;		/* Processor Initialization */
+	u8	res13[12];
+	u32	ipivpr0;	/* IPI Vector/Priority 0 */
+	u8	res14[12];
+	u32	ipivpr1;	/* IPI Vector/Priority 1 */
+	u8	res15[12];
+	u32	ipivpr2;	/* IPI Vector/Priority 2 */
+	u8	res16[12];
+	u32	ipivpr3;	/* IPI Vector/Priority 3 */
+	u8	res17[12];
+	u32	svr;		/* Spurious Vector */
+	u8	res18[12];
+	u32	tfrr;		/* Timer Frequency Reporting */
+	u8	res19[12];
+	u32	gtccr0;		/* Global Timer Current Count 0 */
+	u8	res20[12];
+	u32	gtbcr0;		/* Global Timer Base Count 0 */
+	u8	res21[12];
+	u32	gtvpr0;		/* Global Timer Vector/Priority 0 */
+	u8	res22[12];
+	u32	gtdr0;		/* Global Timer Destination 0 */
+	u8	res23[12];
+	u32	gtccr1;		/* Global Timer Current Count 1 */
+	u8	res24[12];
+	u32	gtbcr1;		/* Global Timer Base Count 1 */
+	u8	res25[12];
+	u32	gtvpr1;		/* Global Timer Vector/Priority 1 */
+	u8	res26[12];
+	u32	gtdr1;		/* Global Timer Destination 1 */
+	u8	res27[12];
+	u32	gtccr2;		/* Global Timer Current Count 2 */
+	u8	res28[12];
+	u32	gtbcr2;		/* Global Timer Base Count 2 */
+	u8	res29[12];
+	u32	gtvpr2;		/* Global Timer Vector/Priority 2 */
+	u8	res30[12];
+	u32	gtdr2;		/* Global Timer Destination 2 */
+	u8	res31[12];
+	u32	gtccr3;		/* Global Timer Current Count 3 */
+	u8	res32[12];
+	u32	gtbcr3;		/* Global Timer Base Count 3 */
+	u8	res33[12];
+	u32	gtvpr3;		/* Global Timer Vector/Priority 3 */
+	u8	res34[12];
+	u32	gtdr3;		/* Global Timer Destination 3 */
+	u8	res35[268];
+	u32	tcr;		/* Timer Control */
+	u8	res36[12];
+	u32	irqsr0;		/* IRQ_OUT Summary 0 */
+	u8	res37[12];
+	u32	irqsr1;		/* IRQ_OUT Summary 1 */
+	u8	res38[12];
+	u32	cisr0;		/* Critical IRQ Summary 0 */
+	u8	res39[12];
+	u32	cisr1;		/* Critical IRQ Summary 1 */
+	u8	res40[188];
+	u32	msgr0;		/* Message 0 */
+	u8	res41[12];
+	u32	msgr1;		/* Message 1 */
+	u8	res42[12];
+	u32	msgr2;		/* Message 2 */
+	u8	res43[12];
+	u32	msgr3;		/* Message 3 */
+	u8	res44[204];
+	u32	mer;		/* Message Enable */
+	u8	res45[12];
+	u32	msr;		/* Message Status */
+	u8	res46[60140];
+	u32	eivpr0;		/* External IRQ Vector/Priority 0 */
+	u8	res47[12];
+	u32	eidr0;		/* External IRQ Destination 0 */
+	u8	res48[12];
+	u32	eivpr1;		/* External IRQ Vector/Priority 1 */
+	u8	res49[12];
+	u32	eidr1;		/* External IRQ Destination 1 */
+	u8	res50[12];
+	u32	eivpr2;		/* External IRQ Vector/Priority 2 */
+	u8	res51[12];
+	u32	eidr2;		/* External IRQ Destination 2 */
+	u8	res52[12];
+	u32	eivpr3;		/* External IRQ Vector/Priority 3 */
+	u8	res53[12];
+	u32	eidr3;		/* External IRQ Destination 3 */
+	u8	res54[12];
+	u32	eivpr4;		/* External IRQ Vector/Priority 4 */
+	u8	res55[12];
+	u32	eidr4;		/* External IRQ Destination 4 */
+	u8	res56[12];
+	u32	eivpr5;		/* External IRQ Vector/Priority 5 */
+	u8	res57[12];
+	u32	eidr5;		/* External IRQ Destination 5 */
+	u8	res58[12];
+	u32	eivpr6;		/* External IRQ Vector/Priority 6 */
+	u8	res59[12];
+	u32	eidr6;		/* External IRQ Destination 6 */
+	u8	res60[12];
+	u32	eivpr7;		/* External IRQ Vector/Priority 7 */
+	u8	res61[12];
+	u32	eidr7;		/* External IRQ Destination 7 */
+	u8	res62[12];
+	u32	eivpr8;		/* External IRQ Vector/Priority 8 */
+	u8	res63[12];
+	u32	eidr8;		/* External IRQ Destination 8 */
+	u8	res64[12];
+	u32	eivpr9;		/* External IRQ Vector/Priority 9 */
+	u8	res65[12];
+	u32	eidr9;		/* External IRQ Destination 9 */
+	u8	res66[12];
+	u32	eivpr10;	/* External IRQ Vector/Priority 10 */
+	u8	res67[12];
+	u32	eidr10;		/* External IRQ Destination 10 */
+	u8	res68[12];
+	u32	eivpr11;	/* External IRQ Vector/Priority 11 */
+	u8	res69[12];
+	u32	eidr11;		/* External IRQ Destination 11 */
+	u8	res70[140];
+	u32	iivpr0;		/* Internal IRQ Vector/Priority 0 */
+	u8	res71[12];
+	u32	iidr0;		/* Internal IRQ Destination 0 */
+	u8	res72[12];
+	u32	iivpr1;		/* Internal IRQ Vector/Priority 1 */
+	u8	res73[12];
+	u32	iidr1;		/* Internal IRQ Destination 1 */
+	u8	res74[12];
+	u32	iivpr2;		/* Internal IRQ Vector/Priority 2 */
+	u8	res75[12];
+	u32	iidr2;		/* Internal IRQ Destination 2 */
+	u8	res76[12];
+	u32	iivpr3;		/* Internal IRQ Vector/Priority 3 */
+	u8	res77[12];
+	u32	iidr3;		/* Internal IRQ Destination 3 */
+	u8	res78[12];
+	u32	iivpr4;		/* Internal IRQ Vector/Priority 4 */
+	u8	res79[12];
+	u32	iidr4;		/* Internal IRQ Destination 4 */
+	u8	res80[12];
+	u32	iivpr5;		/* Internal IRQ Vector/Priority 5 */
+	u8	res81[12];
+	u32	iidr5;		/* Internal IRQ Destination 5 */
+	u8	res82[12];
+	u32	iivpr6;		/* Internal IRQ Vector/Priority 6 */
+	u8	res83[12];
+	u32	iidr6;		/* Internal IRQ Destination 6 */
+	u8	res84[12];
+	u32	iivpr7;		/* Internal IRQ Vector/Priority 7 */
+	u8	res85[12];
+	u32	iidr7;		/* Internal IRQ Destination 7 */
+	u8	res86[12];
+	u32	iivpr8;		/* Internal IRQ Vector/Priority 8 */
+	u8	res87[12];
+	u32	iidr8;		/* Internal IRQ Destination 8 */
+	u8	res88[12];
+	u32	iivpr9;		/* Internal IRQ Vector/Priority 9 */
+	u8	res89[12];
+	u32	iidr9;		/* Internal IRQ Destination 9 */
+	u8	res90[12];
+	u32	iivpr10;	/* Internal IRQ Vector/Priority 10 */
+	u8	res91[12];
+	u32	iidr10;		/* Internal IRQ Destination 10 */
+	u8	res92[12];
+	u32	iivpr11;	/* Internal IRQ Vector/Priority 11 */
+	u8	res93[12];
+	u32	iidr11;		/* Internal IRQ Destination 11 */
+	u8	res94[12];
+	u32	iivpr12;	/* Internal IRQ Vector/Priority 12 */
+	u8	res95[12];
+	u32	iidr12;		/* Internal IRQ Destination 12 */
+	u8	res96[12];
+	u32	iivpr13;	/* Internal IRQ Vector/Priority 13 */
+	u8	res97[12];
+	u32	iidr13;		/* Internal IRQ Destination 13 */
+	u8	res98[12];
+	u32	iivpr14;	/* Internal IRQ Vector/Priority 14 */
+	u8	res99[12];
+	u32	iidr14;		/* Internal IRQ Destination 14 */
+	u8	res100[12];
+	u32	iivpr15;	/* Internal IRQ Vector/Priority 15 */
+	u8	res101[12];
+	u32	iidr15;		/* Internal IRQ Destination 15 */
+	u8	res102[12];
+	u32	iivpr16;	/* Internal IRQ Vector/Priority 16 */
+	u8	res103[12];
+	u32	iidr16;		/* Internal IRQ Destination 16 */
+	u8	res104[12];
+	u32	iivpr17;	/* Internal IRQ Vector/Priority 17 */
+	u8	res105[12];
+	u32	iidr17;		/* Internal IRQ Destination 17 */
+	u8	res106[12];
+	u32	iivpr18;	/* Internal IRQ Vector/Priority 18 */
+	u8	res107[12];
+	u32	iidr18;		/* Internal IRQ Destination 18 */
+	u8	res108[12];
+	u32	iivpr19;	/* Internal IRQ Vector/Priority 19 */
+	u8	res109[12];
+	u32	iidr19;		/* Internal IRQ Destination 19 */
+	u8	res110[12];
+	u32	iivpr20;	/* Internal IRQ Vector/Priority 20 */
+	u8	res111[12];
+	u32	iidr20;		/* Internal IRQ Destination 20 */
+	u8	res112[12];
+	u32	iivpr21;	/* Internal IRQ Vector/Priority 21 */
+	u8	res113[12];
+	u32	iidr21;		/* Internal IRQ Destination 21 */
+	u8	res114[12];
+	u32	iivpr22;	/* Internal IRQ Vector/Priority 22 */
+	u8	res115[12];
+	u32	iidr22;		/* Internal IRQ Destination 22 */
+	u8	res116[12];
+	u32	iivpr23;	/* Internal IRQ Vector/Priority 23 */
+	u8	res117[12];
+	u32	iidr23;		/* Internal IRQ Destination 23 */
+	u8	res118[12];
+	u32	iivpr24;	/* Internal IRQ Vector/Priority 24 */
+	u8	res119[12];
+	u32	iidr24;		/* Internal IRQ Destination 24 */
+	u8	res120[12];
+	u32	iivpr25;	/* Internal IRQ Vector/Priority 25 */
+	u8	res121[12];
+	u32	iidr25;		/* Internal IRQ Destination 25 */
+	u8	res122[12];
+	u32	iivpr26;	/* Internal IRQ Vector/Priority 26 */
+	u8	res123[12];
+	u32	iidr26;		/* Internal IRQ Destination 26 */
+	u8	res124[12];
+	u32	iivpr27;	/* Internal IRQ Vector/Priority 27 */
+	u8	res125[12];
+	u32	iidr27;		/* Internal IRQ Destination 27 */
+	u8	res126[12];
+	u32	iivpr28;	/* Internal IRQ Vector/Priority 28 */
+	u8	res127[12];
+	u32	iidr28;		/* Internal IRQ Destination 28 */
+	u8	res128[12];
+	u32	iivpr29;	/* Internal IRQ Vector/Priority 29 */
+	u8	res129[12];
+	u32	iidr29;		/* Internal IRQ Destination 29 */
+	u8	res130[12];
+	u32	iivpr30;	/* Internal IRQ Vector/Priority 30 */
+	u8	res131[12];
+	u32	iidr30;		/* Internal IRQ Destination 30 */
+	u8	res132[12];
+	u32	iivpr31;	/* Internal IRQ Vector/Priority 31 */
+	u8	res133[12];
+	u32	iidr31;		/* Internal IRQ Destination 31 */
+	u8	res134[4108];
+	u32	mivpr0;		/* Messaging IRQ Vector/Priority 0 */
+	u8	res135[12];
+	u32	midr0;		/* Messaging IRQ Destination 0 */
+	u8	res136[12];
+	u32	mivpr1;		/* Messaging IRQ Vector/Priority 1 */
+	u8	res137[12];
+	u32	midr1;		/* Messaging IRQ Destination 1 */
+	u8	res138[12];
+	u32	mivpr2;		/* Messaging IRQ Vector/Priority 2 */
+	u8	res139[12];
+	u32	midr2;		/* Messaging IRQ Destination 2 */
+	u8	res140[12];
+	u32	mivpr3;		/* Messaging IRQ Vector/Priority 3 */
+	u8	res141[12];
+	u32	midr3;		/* Messaging IRQ Destination 3 */
+	u8	res142[59852];
+	u32	ipi0dr0;	/* Processor 0 Interprocessor IRQ Dispatch 0 */
+	u8	res143[12];
+	u32	ipi0dr1;	/* Processor 0 Interprocessor IRQ Dispatch 1 */
+	u8	res144[12];
+	u32	ipi0dr2;	/* Processor 0 Interprocessor IRQ Dispatch 2 */
+	u8	res145[12];
+	u32	ipi0dr3;	/* Processor 0 Interprocessor IRQ Dispatch 3 */
+	u8	res146[12];
+	u32	ctpr0;		/* Current Task Priority for Processor 0 */
+	u8	res147[12];
+	u32	whoami0;	/* Who Am I for Processor 0 */
+	u8	res148[12];
+	u32	iack0;		/* IRQ Acknowledge for Processor 0 */
+	u8	res149[12];
+	u32	eoi0;		/* End Of IRQ for Processor 0 */
+	u8	res150[130892];
+} ccsr_pic_t;
+
+/* CPM Block */
+#ifndef CONFIG_CPM2
+typedef struct ccsr_cpm {
+	u8 res[262144];
+} ccsr_cpm_t;
+#else
+/*
+ * DPARM
+ * General SIU
+ */
+typedef struct ccsr_cpm_siu {
+	u8	res1[80];
+	u32	smaer;
+	u32	smser;
+	u32	smevr;
+	u8	res2[4];
+	u32	lmaer;
+	u32	lmser;
+	u32	lmevr;
+	u8	res3[2964];
+} ccsr_cpm_siu_t;
+
+/* IRQ Controller */
+typedef struct ccsr_cpm_intctl {
+	u16	sicr;
+	u8	res1[2];
+	u32	sivec;
+	u32	sipnrh;
+	u32	sipnrl;
+	u32	siprr;
+	u32	scprrh;
+	u32	scprrl;
+	u32	simrh;
+	u32	simrl;
+	u32	siexr;
+	u8	res2[88];
+	u32	sccr;
+	u8	res3[124];
+} ccsr_cpm_intctl_t;
+
+/* input/output port */
+typedef struct ccsr_cpm_iop {
+	u32	pdira;
+	u32	ppara;
+	u32	psora;
+	u32	podra;
+	u32	pdata;
+	u8	res1[12];
+	u32	pdirb;
+	u32	pparb;
+	u32	psorb;
+	u32	podrb;
+	u32	pdatb;
+	u8	res2[12];
+	u32	pdirc;
+	u32	pparc;
+	u32	psorc;
+	u32	podrc;
+	u32	pdatc;
+	u8	res3[12];
+	u32	pdird;
+	u32	ppard;
+	u32	psord;
+	u32	podrd;
+	u32	pdatd;
+	u8	res4[12];
+} ccsr_cpm_iop_t;
+
+/* CPM timers */
+typedef struct ccsr_cpm_timer {
+	u8	tgcr1;
+	u8	res1[3];
+	u8	tgcr2;
+	u8	res2[11];
+	u16	tmr1;
+	u16	tmr2;
+	u16	trr1;
+	u16	trr2;
+	u16	tcr1;
+	u16	tcr2;
+	u16	tcn1;
+	u16	tcn2;
+	u16	tmr3;
+	u16	tmr4;
+	u16	trr3;
+	u16	trr4;
+	u16	tcr3;
+	u16	tcr4;
+	u16	tcn3;
+	u16	tcn4;
+	u16	ter1;
+	u16	ter2;
+	u16	ter3;
+	u16	ter4;
+	u8	res3[608];
+} ccsr_cpm_timer_t;
+
+/* SDMA */
+typedef struct ccsr_cpm_sdma {
+	u8	sdsr;
+	u8	res1[3];
+	u8	sdmr;
+	u8	res2[739];
+} ccsr_cpm_sdma_t;
+
+/* FCC1 */
+typedef struct ccsr_cpm_fcc1 {
+	u32	gfmr;
+	u32	fpsmr;
+	u16	ftodr;
+	u8	res1[2];
+	u16	fdsr;
+	u8	res2[2];
+	u16	fcce;
+	u8	res3[2];
+	u16	fccm;
+	u8	res4[2];
+	u8	fccs;
+	u8	res5[3];
+	u8	ftirr_phy[4];
+} ccsr_cpm_fcc1_t;
+
+/* FCC2 */
+typedef struct ccsr_cpm_fcc2 {
+	u32	gfmr;
+	u32	fpsmr;
+	u16	ftodr;
+	u8	res1[2];
+	u16	fdsr;
+	u8	res2[2];
+	u16	fcce;
+	u8	res3[2];
+	u16	fccm;
+	u8	res4[2];
+	u8	fccs;
+	u8	res5[3];
+	u8	ftirr_phy[4];
+} ccsr_cpm_fcc2_t;
+
+/* FCC3 */
+typedef struct ccsr_cpm_fcc3 {
+	u32	gfmr;
+	u32	fpsmr;
+	u16	ftodr;
+	u8	res1[2];
+	u16	fdsr;
+	u8	res2[2];
+	u16	fcce;
+	u8	res3[2];
+	u16	fccm;
+	u8	res4[2];
+	u8	fccs;
+	u8	res5[3];
+	u8	res[36];
+} ccsr_cpm_fcc3_t;
+
+/* FCC1 extended */
+typedef struct ccsr_cpm_fcc1_ext {
+	u32	firper;
+	u32	firer;
+	u32	firsr_h;
+	u32	firsr_l;
+	u8	gfemr;
+	u8	res[15];
+
+} ccsr_cpm_fcc1_ext_t;
+
+/* FCC2 extended */
+typedef struct ccsr_cpm_fcc2_ext {
+	u32	firper;
+	u32	firer;
+	u32	firsr_h;
+	u32	firsr_l;
+	u8	gfemr;
+	u8	res[31];
+} ccsr_cpm_fcc2_ext_t;
+
+/* FCC3 extended */
+typedef struct ccsr_cpm_fcc3_ext {
+	u8	gfemr;
+	u8	res[47];
+} ccsr_cpm_fcc3_ext_t;
+
+/* TC layers */
+typedef struct ccsr_cpm_tmp1 {
+	u8	res[496];
+} ccsr_cpm_tmp1_t;
+
+/* BRGs:5,6,7,8 */
+typedef struct ccsr_cpm_brg2 {
+	u32	brgc5;
+	u32	brgc6;
+	u32	brgc7;
+	u32	brgc8;
+	u8	res[608];
+} ccsr_cpm_brg2_t;
+
+/* I2C */
+typedef struct ccsr_cpm_i2c {
+	u8	i2mod;
+	u8	res1[3];
+	u8	i2add;
+	u8	res2[3];
+	u8	i2brg;
+	u8	res3[3];
+	u8	i2com;
+	u8	res4[3];
+	u8	i2cer;
+	u8	res5[3];
+	u8	i2cmr;
+	u8	res6[331];
+} ccsr_cpm_i2c_t;
+
+/* CPM core */
+typedef struct ccsr_cpm_cp {
+	u32	cpcr;
+	u32	rccr;
+	u8	res1[14];
+	u16	rter;
+	u8	res2[2];
+	u16	rtmr;
+	u16	rtscr;
+	u8	res3[2];
+	u32	rtsr;
+	u8	res4[12];
+} ccsr_cpm_cp_t;
+
+/* BRGs:1,2,3,4 */
+typedef struct ccsr_cpm_brg1 {
+	u32	brgc1;
+	u32	brgc2;
+	u32	brgc3;
+	u32	brgc4;
+} ccsr_cpm_brg1_t;
+
+/* SCC1-SCC4 */
+typedef struct ccsr_cpm_scc {
+	u32	gsmrl;
+	u32	gsmrh;
+	u16	psmr;
+	u8	res1[2];
+	u16	todr;
+	u16	dsr;
+	u16	scce;
+	u8	res2[2];
+	u16	sccm;
+	u8	res3;
+	u8	sccs;
+	u8	res4[8];
+} ccsr_cpm_scc_t;
+
+typedef struct ccsr_cpm_tmp2 {
+	u8	res[32];
+} ccsr_cpm_tmp2_t;
+
+/* SPI */
+typedef struct ccsr_cpm_spi {
+	u16	spmode;
+	u8	res1[4];
+	u8	spie;
+	u8	res2[3];
+	u8	spim;
+	u8	res3[2];
+	u8	spcom;
+	u8	res4[82];
+} ccsr_cpm_spi_t;
+
+/* CPM MUX */
+typedef struct ccsr_cpm_mux {
+	u8	cmxsi1cr;
+	u8	res1;
+	u8	cmxsi2cr;
+	u8	res2;
+	u32	cmxfcr;
+	u32	cmxscr;
+	u8	res3[2];
+	u16	cmxuar;
+	u8	res4[16];
+} ccsr_cpm_mux_t;
+
+/* SI,MCC,etc */
+typedef struct ccsr_cpm_tmp3 {
+	u8 res[58592];
+} ccsr_cpm_tmp3_t;
+
+typedef struct ccsr_cpm_iram {
+	u32	iram[8192];
+	u8	res[98304];
+} ccsr_cpm_iram_t;
+
+typedef struct ccsr_cpm {
+	/* Some references are into the unique & known dpram spaces,
+	 * others are from the generic base.
+	 */
+#define im_dprambase		im_dpram1
+	u8			im_dpram1[16*1024];
+	u8			res1[16*1024];
+	u8			im_dpram2[16*1024];
+	u8			res2[16*1024];
+	ccsr_cpm_siu_t		im_cpm_siu; /* SIU Configuration */
+	ccsr_cpm_intctl_t	im_cpm_intctl; /* IRQ Controller */
+	ccsr_cpm_iop_t		im_cpm_iop; /* IO Port control/status */
+	ccsr_cpm_timer_t	im_cpm_timer; /* CPM timers */
+	ccsr_cpm_sdma_t		im_cpm_sdma; /* SDMA control/status */
+	ccsr_cpm_fcc1_t		im_cpm_fcc1;
+	ccsr_cpm_fcc2_t		im_cpm_fcc2;
+	ccsr_cpm_fcc3_t		im_cpm_fcc3;
+	ccsr_cpm_fcc1_ext_t	im_cpm_fcc1_ext;
+	ccsr_cpm_fcc2_ext_t	im_cpm_fcc2_ext;
+	ccsr_cpm_fcc3_ext_t	im_cpm_fcc3_ext;
+	ccsr_cpm_tmp1_t		im_cpm_tmp1;
+	ccsr_cpm_brg2_t		im_cpm_brg2;
+	ccsr_cpm_i2c_t		im_cpm_i2c;
+	ccsr_cpm_cp_t		im_cpm_cp;
+	ccsr_cpm_brg1_t		im_cpm_brg1;
+	ccsr_cpm_scc_t		im_cpm_scc[4];
+	ccsr_cpm_tmp2_t		im_cpm_tmp2;
+	ccsr_cpm_spi_t		im_cpm_spi;
+	ccsr_cpm_mux_t		im_cpm_mux;
+	ccsr_cpm_tmp3_t		im_cpm_tmp3;
+	ccsr_cpm_iram_t		im_cpm_iram;
+} ccsr_cpm_t;
+#endif
+
+/* RapidIO Registers */
+typedef struct ccsr_rio {
+	u32	didcar;		/* Device Identity Capability */
+	u32	dicar;		/* Device Information Capability */
+	u32	aidcar;		/* Assembly Identity Capability */
+	u32	aicar;		/* Assembly Information Capability */
+	u32	pefcar;		/* Processing Element Features Capability */
+	u32	spicar;		/* Switch Port Information Capability */
+	u32	socar;		/* Source Operations Capability */
+	u32	docar;		/* Destination Operations Capability */
+	u8	res1[32];
+	u32	msr;		/* Mailbox Cmd And Status */
+	u32	pwdcsr;		/* Port-Write & Doorbell Cmd And Status */
+	u8	res2[4];
+	u32	pellccsr;	/* Processing Element Logic Layer CCSR */
+	u8	res3[12];
+	u32	lcsbacsr;	/* Local Cfg Space Base Addr Cmd & Status */
+	u32	bdidcsr;	/* Base Device ID Cmd & Status */
+	u8	res4[4];
+	u32	hbdidlcsr;	/* Host Base Device ID Lock Cmd & Status */
+	u32	ctcsr;		/* Component Tag Cmd & Status */
+	u8	res5[144];
+	u32	pmbh0csr;	/* Port Maint. Block Hdr 0 Cmd & Status */
+	u8	res6[28];
+	u32	pltoccsr;	/* Port Link Time-out Ctrl Cmd & Status */
+	u32	prtoccsr;	/* Port Response Time-out Ctrl Cmd & Status */
+	u8	res7[20];
+	u32	pgccsr;		/* Port General Cmd & Status */
+	u32	plmreqcsr;	/* Port Link Maint. Request Cmd & Status */
+	u32	plmrespcsr;	/* Port Link Maint. Response Cmd & Status */
+	u32	plascsr;	/* Port Local Ackid Status Cmd & Status */
+	u8	res8[12];
+	u32	pescsr;		/* Port Error & Status Cmd & Status */
+	u32	pccsr;		/* Port Control Cmd & Status */
+	u8	res9[65184];
+	u32	cr;		/* Port Control Cmd & Status */
+	u8	res10[12];
+	u32	pcr;		/* Port Configuration */
+	u32	peir;		/* Port Error Injection */
+	u8	res11[3048];
+	u32	rowtar0;	/* RIO Outbound Window Translation Addr 0 */
+	u8	res12[12];
+	u32	rowar0;		/* RIO Outbound Attrs 0 */
+	u8	res13[12];
+	u32	rowtar1;	/* RIO Outbound Window Translation Addr 1 */
+	u8	res14[4];
+	u32	rowbar1;	/* RIO Outbound Window Base Addr 1 */
+	u8	res15[4];
+	u32	rowar1;		/* RIO Outbound Attrs 1 */
+	u8	res16[12];
+	u32	rowtar2;	/* RIO Outbound Window Translation Addr 2 */
+	u8	res17[4];
+	u32	rowbar2;	/* RIO Outbound Window Base Addr 2 */
+	u8	res18[4];
+	u32	rowar2;		/* RIO Outbound Attrs 2 */
+	u8	res19[12];
+	u32	rowtar3;	/* RIO Outbound Window Translation Addr 3 */
+	u8	res20[4];
+	u32	rowbar3;	/* RIO Outbound Window Base Addr 3 */
+	u8	res21[4];
+	u32	rowar3;		/* RIO Outbound Attrs 3 */
+	u8	res22[12];
+	u32	rowtar4;	/* RIO Outbound Window Translation Addr 4 */
+	u8	res23[4];
+	u32	rowbar4;	/* RIO Outbound Window Base Addr 4 */
+	u8	res24[4];
+	u32	rowar4;		/* RIO Outbound Attrs 4 */
+	u8	res25[12];
+	u32	rowtar5;	/* RIO Outbound Window Translation Addr 5 */
+	u8	res26[4];
+	u32	rowbar5;	/* RIO Outbound Window Base Addr 5 */
+	u8	res27[4];
+	u32	rowar5;		/* RIO Outbound Attrs 5 */
+	u8	res28[12];
+	u32	rowtar6;	/* RIO Outbound Window Translation Addr 6 */
+	u8	res29[4];
+	u32	rowbar6;	/* RIO Outbound Window Base Addr 6 */
+	u8	res30[4];
+	u32	rowar6;		/* RIO Outbound Attrs 6 */
+	u8	res31[12];
+	u32	rowtar7;	/* RIO Outbound Window Translation Addr 7 */
+	u8	res32[4];
+	u32	rowbar7;	/* RIO Outbound Window Base Addr 7 */
+	u8	res33[4];
+	u32	rowar7;		/* RIO Outbound Attrs 7 */
+	u8	res34[12];
+	u32	rowtar8;	/* RIO Outbound Window Translation Addr 8 */
+	u8	res35[4];
+	u32	rowbar8;	/* RIO Outbound Window Base Addr 8 */
+	u8	res36[4];
+	u32	rowar8;		/* RIO Outbound Attrs 8 */
+	u8	res37[76];
+	u32	riwtar4;	/* RIO Inbound Window Translation Addr 4 */
+	u8	res38[4];
+	u32	riwbar4;	/* RIO Inbound Window Base Addr 4 */
+	u8	res39[4];
+	u32	riwar4;		/* RIO Inbound Attrs 4 */
+	u8	res40[12];
+	u32	riwtar3;	/* RIO Inbound Window Translation Addr 3 */
+	u8	res41[4];
+	u32	riwbar3;	/* RIO Inbound Window Base Addr 3 */
+	u8	res42[4];
+	u32	riwar3;		/* RIO Inbound Attrs 3 */
+	u8	res43[12];
+	u32	riwtar2;	/* RIO Inbound Window Translation Addr 2 */
+	u8	res44[4];
+	u32	riwbar2;	/* RIO Inbound Window Base Addr 2 */
+	u8	res45[4];
+	u32	riwar2;		/* RIO Inbound Attrs 2 */
+	u8	res46[12];
+	u32	riwtar1;	/* RIO Inbound Window Translation Addr 1 */
+	u8	res47[4];
+	u32	riwbar1;	/* RIO Inbound Window Base Addr 1 */
+	u8	res48[4];
+	u32	riwar1;		/* RIO Inbound Attrs 1 */
+	u8	res49[12];
+	u32	riwtar0;	/* RIO Inbound Window Translation Addr 0 */
+	u8	res50[12];
+	u32	riwar0;		/* RIO Inbound Attrs 0 */
+	u8	res51[12];
+	u32	pnfedr;		/* Port Notification/Fatal Error Detect */
+	u32	pnfedir;	/* Port Notification/Fatal Error Detect */
+	u32	pnfeier;	/* Port Notification/Fatal Error IRQ Enable */
+	u32	pecr;		/* Port Error Control */
+	u32	pepcsr0;	/* Port Error Packet/Control Symbol 0 */
+	u32	pepr1;		/* Port Error Packet 1 */
+	u32	pepr2;		/* Port Error Packet 2 */
+	u8	res52[4];
+	u32	predr;		/* Port Recoverable Error Detect */
+	u8	res53[4];
+	u32	pertr;		/* Port Error Recovery Threshold */
+	u32	prtr;		/* Port Retry Threshold */
+	u8	res54[464];
+	u32	omr;		/* Outbound Mode */
+	u32	osr;		/* Outbound Status */
+	u32	eodqtpar;	/* Extended Outbound Desc Queue Tail Ptr Addr */
+	u32	odqtpar;	/* Outbound Desc Queue Tail Ptr Addr */
+	u32	eosar;		/* Extended Outbound Unit Source Addr */
+	u32	osar;		/* Outbound Unit Source Addr */
+	u32	odpr;		/* Outbound Destination Port */
+	u32	odatr;		/* Outbound Destination Attrs */
+	u32	odcr;		/* Outbound Doubleword Count */
+	u32	eodqhpar;	/* Extended Outbound Desc Queue Head Ptr Addr */
+	u32	odqhpar;	/* Outbound Desc Queue Head Ptr Addr */
+	u8	res55[52];
+	u32	imr;		/* Outbound Mode */
+	u32	isr;		/* Inbound Status */
+	u32	eidqtpar;	/* Extended Inbound Desc Queue Tail Ptr Addr */
+	u32	idqtpar;	/* Inbound Desc Queue Tail Ptr Addr */
+	u32	eifqhpar;	/* Extended Inbound Frame Queue Head Ptr Addr */
+	u32	ifqhpar;	/* Inbound Frame Queue Head Ptr Addr */
+	u8	res56[1000];
+	u32	dmr;		/* Doorbell Mode */
+	u32	dsr;		/* Doorbell Status */
+	u32	edqtpar;	/* Extended Doorbell Queue Tail Ptr Addr */
+	u32	dqtpar;		/* Doorbell Queue Tail Ptr Addr */
+	u32	edqhpar;	/* Extended Doorbell Queue Head Ptr Addr */
+	u32	dqhpar;		/* Doorbell Queue Head Ptr Addr */
+	u8	res57[104];
+	u32	pwmr;		/* Port-Write Mode */
+	u32	pwsr;		/* Port-Write Status */
+	u32	epwqbar;	/* Extended Port-Write Queue Base Addr */
+	u32	pwqbar;		/* Port-Write Queue Base Addr */
+	u8	res58[60176];
+} ccsr_rio_t;
+
+/* Quick Engine Block Pin Muxing Registers */
+typedef struct par_io {
+	u32	cpodr;
+	u32	cpdat;
+	u32	cpdir1;
+	u32	cpdir2;
+	u32	cppar1;
+	u32	cppar2;
+	u8	res[8];
+} par_io_t;
+
+#ifdef CONFIG_SYS_FSL_CPC
+/*
+ * Define a single offset that is the start of all the CPC register
+ * blocks - if there is more than one CPC, we expect these to be
+ * contiguous 4k regions
+ */
+
+typedef struct cpc_corenet {
+	u32 	cpccsr0;	/* Config/status reg */
+	u32	res1;
+	u32	cpccfg0;	/* Configuration register */
+	u32	res2;
+	u32	cpcewcr0;	/* External Write reg 0 */
+	u32	cpcewabr0;	/* External write base reg 0 */
+	u32	res3[2];
+	u32	cpcewcr1;	/* External Write reg 1 */
+	u32	cpcewabr1;	/* External write base reg 1 */
+	u32	res4[54];
+	u32	cpcsrcr1;	/* SRAM control reg 1 */
+	u32	cpcsrcr0;	/* SRAM control reg 0 */
+	u32	res5[62];
+	struct {
+		u32	id;	/* partition ID */
+		u32	res;
+		u32	alloc;	/* partition allocation */
+		u32	way;	/* partition way */
+	} partition_regs[16];
+	u32	res6[704];
+	u32	cpcerrinjhi;	/* Error injection high */
+	u32	cpcerrinjlo;	/* Error injection lo */
+	u32	cpcerrinjctl;	/* Error injection control */
+	u32	res7[5];
+	u32	cpccaptdatahi;	/* capture data high */
+	u32	cpccaptdatalo;	/* capture data low */
+	u32	cpcaptecc;	/* capture ECC */
+	u32	res8[5];
+	u32	cpcerrdet;	/* error detect */
+	u32	cpcerrdis;	/* error disable */
+	u32	cpcerrinten;	/* errir interrupt enable */
+	u32	cpcerrattr;	/* error attribute */
+	u32	cpcerreaddr;	/* error extended address */
+	u32	cpcerraddr;	/* error address */
+	u32	cpcerrctl;	/* error control */
+	u32	res9[105];	/* pad out to 4k */
+} cpc_corenet_t;
+
+#define CPC_CSR0_CE	0x80000000	/* Cache Enable */
+#define CPC_CSR0_PE	0x40000000	/* Enable ECC */
+#define CPC_CSR0_FI	0x00200000	/* Cache Flash Invalidate */
+#define CPC_CSR0_WT	0x00080000	/* Write-through mode */
+#define CPC_CSR0_FL	0x00000800	/* Hardware cache flush */
+#define CPC_CSR0_LFC	0x00000400	/* Cache Lock Flash Clear */
+#define CPC_CFG0_SZ_MASK	0x00003fff
+#define CPC_CFG0_SZ_K(x)	((x & CPC_CFG0_SZ_MASK) << 6)
+#define CPC_CFG0_NUM_WAYS(x)	(((x >> 14) & 0x1f) + 1)
+#define CPC_CFG0_LINE_SZ(x)	((((x >> 23) & 0x3) + 1) * 32)
+#define CPC_SRCR1_SRBARU_MASK	0x0000ffff
+#define CPC_SRCR1_SRBARU(x)	(((unsigned long long)x >> 32) \
+				 & CPC_SRCR1_SRBARU_MASK)
+#define	CPC_SRCR0_SRBARL_MASK	0xffff8000
+#define CPC_SRCR0_SRBARL(x)	(x & CPC_SRCR0_SRBARL_MASK)
+#define CPC_SRCR0_INTLVEN	0x00000100
+#define CPC_SRCR0_SRAMSZ_1_WAY	0x00000000
+#define CPC_SRCR0_SRAMSZ_2_WAY	0x00000002
+#define CPC_SRCR0_SRAMSZ_4_WAY	0x00000004
+#define CPC_SRCR0_SRAMSZ_8_WAY	0x00000006
+#define CPC_SRCR0_SRAMSZ_16_WAY	0x00000008
+#define CPC_SRCR0_SRAMSZ_32_WAY	0x0000000a
+#define CPC_SRCR0_SRAMEN	0x00000001
+#define	CPC_ERRDIS_TMHITDIS  	0x00000080	/* multi-way hit disable */
+#endif /* CONFIG_SYS_FSL_CPC */
+
+/* Global Utilities Block */
+#ifdef CONFIG_FSL_CORENET
+typedef struct ccsr_gur {
+	u32	porsr1;		/* POR status */
+	u8	res1[28];
+	u32	gpporcr1;	/* General-purpose POR configuration */
+	u8	res2[12];
+	u32	gpiocr;		/* GPIO control */
+	u8	res3[12];
+	u32	gpoutdr;	/* General-purpose output data */
+	u8	res4[12];
+	u32	gpindr;		/* General-purpose input data */
+	u8	res5[12];
+	u32	pmuxcr;		/* Alt function signal multiplex control */
+	u8	res6[12];
+	u32	devdisr;	/* Device disable control */
+#define FSL_CORENET_DEVDISR_PCIE1	0x80000000
+#define FSL_CORENET_DEVDISR_PCIE2	0x40000000
+#define FSL_CORENET_DEVDISR_PCIE3	0x20000000
+#define FSL_CORENET_DEVDISR_RMU		0x08000000
+#define FSL_CORENET_DEVDISR_SRIO1	0x04000000
+#define FSL_CORENET_DEVDISR_SRIO2	0x02000000
+#define FSL_CORENET_DEVDISR_DMA1	0x00400000
+#define FSL_CORENET_DEVDISR_DMA2	0x00200000
+#define FSL_CORENET_DEVDISR_DDR1	0x00100000
+#define FSL_CORENET_DEVDISR_DDR2	0x00080000
+#define FSL_CORENET_DEVDISR_DBG		0x00010000
+#define FSL_CORENET_DEVDISR_NAL		0x00008000
+#define FSL_CORENET_DEVDISR_ELBC	0x00001000
+#define FSL_CORENET_DEVDISR_USB1	0x00000800
+#define FSL_CORENET_DEVDISR_USB2	0x00000400
+#define FSL_CORENET_DEVDISR_ESDHC	0x00000100
+#define FSL_CORENET_DEVDISR_GPIO	0x00000080
+#define FSL_CORENET_DEVDISR_ESPI	0x00000040
+#define FSL_CORENET_DEVDISR_I2C1	0x00000020
+#define FSL_CORENET_DEVDISR_I2C2	0x00000010
+#define FSL_CORENET_DEVDISR_DUART1	0x00000002
+#define FSL_CORENET_DEVDISR_DUART2	0x00000001
+	u8	res7[12];
+	u32	powmgtcsr;	/* Power management status & control */
+	u8	res8[12];
+	u32	coredisru;	/* uppper portion for support of 64 cores */
+	u32	coredisrl;	/* lower portion for support of 64 cores */
+	u8	res9[8];
+	u32	pvr;		/* Processor version */
+	u32	svr;		/* System version */
+	u8	res10[8];
+	u32	rstcr;		/* Reset control */
+	u32	rstrqpblsr;	/* Reset request preboot loader status */
+	u8	res11[8];
+	u32	rstrqmr1;	/* Reset request mask */
+	u8	res12[4];
+	u32	rstrqsr1;	/* Reset request status */
+	u8	res13[4];
+	u8	res14[4];
+	u32	rstrqwdtmrl;	/* Reset request WDT mask */
+	u8	res15[4];
+	u32	rstrqwdtsrl;	/* Reset request WDT status */
+	u8	res16[4];
+	u32	brrl;		/* Boot release */
+	u8	res17[24];
+	u32	rcwsr[16];	/* Reset control word status */
+#define FSL_CORENET_RCWSR4_SRDS_PRTCL		0xfc000000
+#define FSL_CORENET_RCWSR5_DDR_SYNC		0x00008000
+#define FSL_CORENET_RCWSR5_DDR_SYNC_SHIFT		15
+#define FSL_CORENET_RCWSR7_MCK_TO_PLAT_RAT	0x00400000
+#define FSL_CORENET_RCWSR8_HOST_AGT_B1		0x00e00000
+#define FSL_CORENET_RCWSR8_HOST_AGT_B2		0x00100000
+	u8	res18[192];
+	u32	scratchrw[4];	/* Scratch Read/Write */
+	u8	res19[240];
+	u32	scratchw1r[4];	/* Scratch Read (Write once) */
+	u8	res20[240];
+	u32	scrtsr[8];	/* Core reset status */
+	u8	res21[224];
+	u32	pex1liodnr;	/* PCI Express 1 LIODN */
+	u32	pex2liodnr;	/* PCI Express 2 LIODN */
+	u32	pex3liodnr;	/* PCI Express 3 LIODN */
+	u32	pex4liodnr;	/* PCI Express 4 LIODN */
+	u32	rio1liodnr;	/* RIO 1 LIODN */
+	u32	rio2liodnr;	/* RIO 2 LIODN */
+	u32	rio3liodnr;	/* RIO 3 LIODN */
+	u32	rio4liodnr;	/* RIO 4 LIODN */
+	u32	usb1liodnr;	/* USB 1 LIODN */
+	u32	usb2liodnr;	/* USB 2 LIODN */
+	u32	usb3liodnr;	/* USB 3 LIODN */
+	u32	usb4liodnr;	/* USB 4 LIODN */
+	u32	sdmmc1liodnr;	/* SD/MMC 1 LIODN */
+	u32	sdmmc2liodnr;	/* SD/MMC 2 LIODN */
+	u32	sdmmc3liodnr;	/* SD/MMC 3 LIODN */
+	u32	sdmmc4liodnr;	/* SD/MMC 4 LIODN */
+	u32	rmuliodnr;	/* RIO Message Unit LIODN */
+	u32	rduliodnr;	/* RIO Doorbell Unit LIODN */
+	u32	rpwuliodnr;	/* RIO Port Write Unit LIODN */
+	u8	res22[52];
+	u32	dma1liodnr;	/* DMA 1 LIODN */
+	u32	dma2liodnr;	/* DMA 2 LIODN */
+	u32	dma3liodnr;	/* DMA 3 LIODN */
+	u32	dma4liodnr;	/* DMA 4 LIODN */
+	u8	res23[48];
+	u8	res24[64];
+	u32	pblsr;		/* Preboot loader status */
+	u32	pamubypenr;	/* PAMU bypass enable */
+	u32	dmacr1;		/* DMA control */
+	u8	res25[4];
+	u32	gensr1;		/* General status */
+	u8	res26[12];
+	u32	gencr1;		/* General control */
+	u8	res27[12];
+	u8	res28[4];
+	u32	cgensrl;	/* Core general status */
+	u8	res29[8];
+	u8	res30[4];
+	u32	cgencrl;	/* Core general control */
+	u8	res31[184];
+	u32	sriopstecr;	/* SRIO prescaler timer enable control */
+	u8	res32[2300];
+} ccsr_gur_t;
+
+typedef struct ccsr_clk {
+	u32	clkc0csr;	/* Core 0 Clock control/status */
+	u8	res1[0x1c];
+	u32	clkc1csr;	/* Core 1 Clock control/status */
+	u8	res2[0x1c];
+	u32	clkc2csr;	/* Core 2 Clock control/status */
+	u8	res3[0x1c];
+	u32	clkc3csr;	/* Core 3 Clock control/status */
+	u8	res4[0x1c];
+	u32	clkc4csr;	/* Core 4 Clock control/status */
+	u8	res5[0x1c];
+	u32	clkc5csr;	/* Core 5 Clock control/status */
+	u8	res6[0x1c];
+	u32	clkc6csr;	/* Core 6 Clock control/status */
+	u8	res7[0x1c];
+	u32	clkc7csr;	/* Core 7 Clock control/status */
+	u8	res8[0x71c];
+	u32	pllc1gsr;	/* Cluster PLL 1 General Status */
+	u8	res10[0x1c];
+	u32	pllc2gsr;	/* Cluster PLL 2 General Status */
+	u8	res11[0x1c];
+	u32	pllc3gsr;	/* Cluster PLL 3 General Status */
+	u8	res12[0x1c];
+	u32	pllc4gsr;	/* Cluster PLL 4 General Status */
+	u8	res13[0x39c];
+	u32	pllpgsr;	/* Platform PLL General Status */
+	u8	res14[0x1c];
+	u32	plldgsr;	/* DDR PLL General Status */
+	u8	res15[0x3dc];
+} ccsr_clk_t;
+
+typedef struct ccsr_rcpm {
+	u8	res1[4];
+	u32	cdozsrl;	/* Core Doze Status */
+	u8	res2[4];
+	u32	cdozcrl;	/* Core Doze Control */
+	u8	res3[4];
+	u32	cnapsrl;	/* Core Nap Status */
+	u8	res4[4];
+	u32	cnapcrl;	/* Core Nap Control */
+	u8	res5[4];
+	u32	cdozpsrl;	/* Core Doze Previous Status */
+	u8	res6[4];
+	u32	cdozpcrl;	/* Core Doze Previous Control */
+	u8	res7[4];
+	u32	cwaitsrl;	/* Core Wait Status */
+	u8	res8[8];
+	u32	powmgtcsr;	/* Power Mangement Control & Status */
+	u8	res9[12];
+	u32	ippdexpcr0;	/* IP Powerdown Exception Control 0 */
+	u8	res10[12];
+	u8	res11[4];
+	u32	cpmimrl;	/* Core PM IRQ Masking */
+	u8	res12[4];
+	u32	cpmcimrl;	/* Core PM Critical IRQ Masking */
+	u8	res13[4];
+	u32	cpmmcimrl;	/* Core PM Machine Check IRQ Masking */
+	u8	res14[4];
+	u32	cpmnmimrl;	/* Core PM NMI Masking */
+	u8	res15[4];
+	u32	ctbenrl;	/* Core Time Base Enable */
+	u8	res16[4];
+	u32	ctbclkselrl;	/* Core Time Base Clock Select */
+	u8	res17[4];
+	u32	ctbhltcrl;	/* Core Time Base Halt Control */
+	u8	res18[0xf68];
+} ccsr_rcpm_t;
+
+#else
+typedef struct ccsr_gur {
+	u32	porpllsr;	/* POR PLL ratio status */
+#ifdef CONFIG_MPC8536
+#define MPC85xx_PORPLLSR_DDR_RATIO	0x3e000000
+#define MPC85xx_PORPLLSR_DDR_RATIO_SHIFT	25
+#else
+#define MPC85xx_PORPLLSR_DDR_RATIO	0x00003e00
+#define MPC85xx_PORPLLSR_DDR_RATIO_SHIFT	9
+#endif
+#define MPC85xx_PORPLLSR_QE_RATIO	0x3e000000
+#define MPC85xx_PORPLLSR_QE_RATIO_SHIFT		25
+#define MPC85xx_PORPLLSR_PLAT_RATIO	0x0000003e
+#define MPC85xx_PORPLLSR_PLAT_RATIO_SHIFT	1
+	u32	porbmsr;	/* POR boot mode status */
+#define MPC85xx_PORBMSR_HA		0x00070000
+#define MPC85xx_PORBMSR_HA_SHIFT	16
+	u32	porimpscr;	/* POR I/O impedance status & control */
+	u32	pordevsr;	/* POR I/O device status regsiter */
+#define MPC85xx_PORDEVSR_SGMII1_DIS	0x20000000
+#define MPC85xx_PORDEVSR_SGMII2_DIS	0x10000000
+#define MPC85xx_PORDEVSR_SGMII3_DIS	0x08000000
+#define MPC85xx_PORDEVSR_SGMII4_DIS	0x04000000
+#define MPC85xx_PORDEVSR_SRDS2_IO_SEL	0x38000000
+#define MPC85xx_PORDEVSR_PCI1		0x00800000
+#define MPC85xx_PORDEVSR_IO_SEL		0x00780000
+#define MPC85xx_PORDEVSR_IO_SEL_SHIFT	19
+#define MPC85xx_PORDEVSR_PCI2_ARB	0x00040000
+#define MPC85xx_PORDEVSR_PCI1_ARB	0x00020000
+#define MPC85xx_PORDEVSR_PCI1_PCI32	0x00010000
+#define MPC85xx_PORDEVSR_PCI1_SPD	0x00008000
+#define MPC85xx_PORDEVSR_PCI2_SPD	0x00004000
+#define MPC85xx_PORDEVSR_DRAM_RTYPE	0x00000060
+#define MPC85xx_PORDEVSR_RIO_CTLS	0x00000008
+#define MPC85xx_PORDEVSR_RIO_DEV_ID	0x00000007
+	u32	pordbgmsr;	/* POR debug mode status */
+	u32	pordevsr2;	/* POR I/O device status 2 */
+/* The 8544 RM says this is bit 26, but it's really bit 24 */
+#define MPC85xx_PORDEVSR2_SEC_CFG	0x00000080
+	u8	res1[8];
+	u32	gpporcr;	/* General-purpose POR configuration */
+	u8	res2[12];
+	u32	gpiocr;		/* GPIO control */
+	u8	res3[12];
+#if defined(CONFIG_MPC8569)
+	u32	plppar1;	/* Platform port pin assignment 1 */
+	u32	plppar2;	/* Platform port pin assignment 2 */
+	u32	plpdir1;	/* Platform port pin direction 1 */
+	u32	plpdir2;	/* Platform port pin direction 2 */
+#else
+	u32	gpoutdr;	/* General-purpose output data */
+	u8	res4[12];
+#endif
+	u32	gpindr;		/* General-purpose input data */
+	u8	res5[12];
+	u32	pmuxcr;		/* Alt. function signal multiplex control */
+#define MPC85xx_PMUXCR_SD_DATA		0x80000000
+#define MPC85xx_PMUXCR_SDHC_CD		0x40000000
+#define MPC85xx_PMUXCR_SDHC_WP		0x20000000
+	u8	res6[12];
+	u32	devdisr;	/* Device disable control */
+#define MPC85xx_DEVDISR_PCI1		0x80000000
+#define MPC85xx_DEVDISR_PCI2		0x40000000
+#define MPC85xx_DEVDISR_PCIE		0x20000000
+#define MPC85xx_DEVDISR_LBC		0x08000000
+#define MPC85xx_DEVDISR_PCIE2		0x04000000
+#define MPC85xx_DEVDISR_PCIE3		0x02000000
+#define MPC85xx_DEVDISR_SEC		0x01000000
+#define MPC85xx_DEVDISR_SRIO		0x00080000
+#define MPC85xx_DEVDISR_RMSG		0x00040000
+#define MPC85xx_DEVDISR_DDR		0x00010000
+#define MPC85xx_DEVDISR_CPU		0x00008000
+#define MPC85xx_DEVDISR_CPU0		MPC85xx_DEVDISR_CPU
+#define MPC85xx_DEVDISR_TB		0x00004000
+#define MPC85xx_DEVDISR_TB0		MPC85xx_DEVDISR_TB
+#define MPC85xx_DEVDISR_CPU1		0x00002000
+#define MPC85xx_DEVDISR_TB1		0x00001000
+#define MPC85xx_DEVDISR_DMA		0x00000400
+#define MPC85xx_DEVDISR_TSEC1		0x00000080
+#define MPC85xx_DEVDISR_TSEC2		0x00000040
+#define MPC85xx_DEVDISR_TSEC3		0x00000020
+#define MPC85xx_DEVDISR_TSEC4		0x00000010
+#define MPC85xx_DEVDISR_I2C		0x00000004
+#define MPC85xx_DEVDISR_DUART		0x00000002
+	u8	res7[12];
+	u32	powmgtcsr;	/* Power management status & control */
+	u8	res8[12];
+	u32	mcpsumr;	/* Machine check summary */
+	u8	res9[12];
+	u32	pvr;		/* Processor version */
+	u32	svr;		/* System version */
+	u8	res10a[8];
+	u32	rstcr;		/* Reset control */
+#if defined(CONFIG_MPC8568)||defined(CONFIG_MPC8569)
+	u8	res10b[76];
+	par_io_t qe_par_io[7];
+	u8	res10c[3136];
+#else
+	u8	res10b[3404];
+#endif
+	u32	clkocr;		/* Clock out select */
+	u8	res11[12];
+	u32	ddrdllcr;	/* DDR DLL control */
+	u8	res12[12];
+	u32	lbcdllcr;	/* LBC DLL control */
+	u8	res13[248];
+	u32	lbiuiplldcr0;	/* LBIU PLL Debug Reg 0 */
+	u32	lbiuiplldcr1;	/* LBIU PLL Debug Reg 1 */
+	u32	ddrioovcr;	/* DDR IO Override Control */
+	u32	tsec12ioovcr;	/* eTSEC 1/2 IO override control */
+	u32	tsec34ioovcr;	/* eTSEC 3/4 IO override control */
+	u8	res15[61648];
+} ccsr_gur_t;
+#endif
+
+typedef struct serdes_corenet {
+	struct {
+		u32	rstctl;	/* Reset Control Register */
+#define SRDS_RSTCTL_RST		0x80000000
+#define SRDS_RSTCTL_RSTDONE	0x40000000
+#define SRDS_RSTCTL_RSTERR	0x20000000
+		u32	pllcr0; /* PLL Control Register 0 */
+		u32	pllcr1; /* PLL Control Register 1 */
+#define SRDS_PLLCR1_PLL_BWSEL	0x08000000
+		u32	res[5];
+	} bank[3];
+	u32	res1[12];
+	u32	srdstcalcr;	/* TX Calibration Control */
+	u32	res2[3];
+	u32	srdsrcalcr;	/* RX Calibration Control */
+	u32	res3[3];
+	u32	srdsgr0;	/* General Register 0 */
+	u32	res4[11];
+	u32	srdspccr0;	/* Protocol Converter Config 0 */
+	u32	srdspccr1;	/* Protocol Converter Config 1 */
+	u32	srdspccr2;	/* Protocol Converter Config 2 */
+#define SRDS_PCCR2_RST_XGMII1		0x00800000
+#define SRDS_PCCR2_RST_XGMII2		0x00400000
+	u32	res5[197];
+	struct {
+		u32	gcr0;	/* General Control Register 0 */
+#define SRDS_GCR0_RRST			0x00400000
+#define SRDS_GCR0_1STLANE		0x00010000
+		u32	gcr1;	/* General Control Register 1 */
+#define SRDS_GCR1_REIDL_CTL_MASK	0x001f0000
+#define SRDS_GCR1_REIDL_CTL_PCIE	0x00100000
+#define SRDS_GCR1_REIDL_CTL_SRIO	0x00000000
+#define SRDS_GCR1_REIDL_CTL_SGMII	0x00040000
+#define SRDS_GCR1_OPAD_CTL		0x04000000
+		u32	res1[4];
+		u32	tecr0;	/* TX Equalization Control Reg 0 */
+#define SRDS_TECR0_TEQ_TYPE_MASK	0x30000000
+#define SRDS_TECR0_TEQ_TYPE_2LVL	0x10000000
+		u32	res3;
+		u32	ttlcr0;	/* Transition Tracking Loop Ctrl 0 */
+		u32	res4[7];
+	} lane[24];
+	u32 res6[384];
+} serdes_corenet_t;
+
+enum {
+	FSL_SRDS_B1_LANE_A = 0,
+	FSL_SRDS_B1_LANE_B = 1,
+	FSL_SRDS_B1_LANE_C = 2,
+	FSL_SRDS_B1_LANE_D = 3,
+	FSL_SRDS_B1_LANE_E = 4,
+	FSL_SRDS_B1_LANE_F = 5,
+	FSL_SRDS_B1_LANE_G = 6,
+	FSL_SRDS_B1_LANE_H = 7,
+	FSL_SRDS_B1_LANE_I = 8,
+	FSL_SRDS_B1_LANE_J = 9,
+	FSL_SRDS_B2_LANE_A = 16,
+	FSL_SRDS_B2_LANE_B = 17,
+	FSL_SRDS_B2_LANE_C = 18,
+	FSL_SRDS_B2_LANE_D = 19,
+	FSL_SRDS_B3_LANE_A = 20,
+	FSL_SRDS_B3_LANE_B = 21,
+	FSL_SRDS_B3_LANE_C = 22,
+	FSL_SRDS_B3_LANE_D = 23,
+};
+
+#ifdef CONFIG_FSL_CORENET
+#define CONFIG_SYS_FSL_CORENET_CCM_OFFSET	0x0000
+#define CONFIG_SYS_MPC85xx_DDR_OFFSET		0x8000
+#define CONFIG_SYS_MPC85xx_DDR2_OFFSET		0x9000
+#define CONFIG_SYS_FSL_CORENET_CLK_OFFSET	0xE1000
+#define CONFIG_SYS_FSL_CORENET_RCPM_OFFSET	0xE2000
+#define CONFIG_SYS_FSL_CORENET_SERDES_OFFSET	0xEA000
+#define CONFIG_SYS_FSL_CPC_OFFSET		0x10000
+#define CONFIG_SYS_MPC85xx_DMA_OFFSET		0x100000
+#define CONFIG_SYS_MPC85xx_ESPI_OFFSET		0x110000
+#define CONFIG_SYS_MPC85xx_ESDHC_OFFSET		0x114000
+#define CONFIG_SYS_MPC85xx_LBC_OFFSET		0x124000
+#define CONFIG_SYS_MPC85xx_GPIO_OFFSET		0x130000
+#define CONFIG_SYS_MPC85xx_USB_OFFSET		0x210000
+#define CONFIG_SYS_FSL_CORENET_QMAN_OFFSET	0x318000
+#define CONFIG_SYS_FSL_CORENET_BMAN_OFFSET	0x31a000
+#else
+#define CONFIG_SYS_MPC85xx_ECM_OFFSET		0x0000
+#define CONFIG_SYS_MPC85xx_DDR_OFFSET		0x2000
+#define CONFIG_SYS_MPC85xx_LBC_OFFSET		0x5000
+#define CONFIG_SYS_MPC85xx_DDR2_OFFSET		0x6000
+#define CONFIG_SYS_MPC85xx_ESPI_OFFSET		0x7000
+#define CONFIG_SYS_MPC85xx_PCIX_OFFSET		0x8000
+#define CONFIG_SYS_MPC85xx_PCIX2_OFFSET		0x9000
+#define CONFIG_SYS_MPC85xx_GPIO_OFFSET		0xF000
+#define CONFIG_SYS_MPC85xx_SATA1_OFFSET		0x18000
+#define CONFIG_SYS_MPC85xx_SATA2_OFFSET		0x19000
+#define CONFIG_SYS_MPC85xx_L2_OFFSET		0x20000
+#define CONFIG_SYS_MPC85xx_DMA_OFFSET		0x21000
+#define CONFIG_SYS_MPC85xx_USB_OFFSET		0x22000
+#ifdef CONFIG_TSECV2
+#define CONFIG_SYS_TSEC1_OFFSET			0xB0000
+#else
+#define CONFIG_SYS_TSEC1_OFFSET			0x24000
+#endif
+#define CONFIG_SYS_MDIO1_OFFSET			0x24000
+#define CONFIG_SYS_MPC85xx_ESDHC_OFFSET		0x2e000
+#define CONFIG_SYS_MPC85xx_SERDES2_OFFSET	0xE3100
+#define CONFIG_SYS_MPC85xx_SERDES1_OFFSET	0xE3000
+#define CONFIG_SYS_MPC85xx_CPM_OFFSET		0x80000
+#endif
+
+#define CONFIG_SYS_MPC85xx_PIC_OFFSET		0x40000
+#define CONFIG_SYS_MPC85xx_GUTS_OFFSET		0xE0000
+
+#define CONFIG_SYS_FSL_CPC_ADDR	\
+	(CONFIG_SYS_CCSRBAR + CONFIG_SYS_FSL_CPC_OFFSET)
+#define CONFIG_SYS_FSL_CORENET_QMAN_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_QMAN_OFFSET)
+#define CONFIG_SYS_FSL_CORENET_BMAN_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_BMAN_OFFSET)
+#define CONFIG_SYS_MPC85xx_GUTS_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_GUTS_OFFSET)
+#define CONFIG_SYS_FSL_CORENET_CCM_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_CCM_OFFSET)
+#define CONFIG_SYS_FSL_CORENET_CLK_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_CLK_OFFSET)
+#define CONFIG_SYS_FSL_CORENET_RCPM_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_RCPM_OFFSET)
+#define CONFIG_SYS_MPC85xx_ECM_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_ECM_OFFSET)
+#define CONFIG_SYS_MPC85xx_DDR_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DDR_OFFSET)
+#define CONFIG_SYS_MPC85xx_DDR2_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DDR2_OFFSET)
+#define CONFIG_SYS_MPC85xx_LBC_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_LBC_OFFSET)
+#define CONFIG_SYS_MPC85xx_ESPI_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_ESPI_OFFSET)
+#define CONFIG_SYS_MPC85xx_PCIX_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_PCIX_OFFSET)
+#define CONFIG_SYS_MPC85xx_PCIX2_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_PCIX2_OFFSET)
+#define CONFIG_SYS_MPC85xx_GPIO_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_GPIO_OFFSET)
+#define CONFIG_SYS_MPC85xx_SATA1_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_SATA1_OFFSET)
+#define CONFIG_SYS_MPC85xx_SATA2_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_SATA2_OFFSET)
+#define CONFIG_SYS_MPC85xx_L2_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_L2_OFFSET)
+#define CONFIG_SYS_MPC85xx_DMA_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DMA_OFFSET)
+#define CONFIG_SYS_MPC85xx_ESDHC_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_ESDHC_OFFSET)
+#define CONFIG_SYS_MPC85xx_PIC_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_PIC_OFFSET)
+#define CONFIG_SYS_MPC85xx_CPM_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_CPM_OFFSET)
+#define CONFIG_SYS_MPC85xx_SERDES1_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_SERDES2_OFFSET)
+#define CONFIG_SYS_MPC85xx_SERDES2_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_SERDES2_OFFSET)
+#define CONFIG_SYS_FSL_CORENET_SERDES_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_SERDES_OFFSET)
+#define CONFIG_SYS_MPC85xx_USB_ADDR \
+	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_USB_OFFSET)
+
+#define TSEC_BASE_ADDR		(CONFIG_SYS_IMMR + CONFIG_SYS_TSEC1_OFFSET)
+#define MDIO_BASE_ADDR		(CONFIG_SYS_IMMR + CONFIG_SYS_MDIO1_OFFSET)
+
+#endif /*__IMMAP_85xx__*/
diff --git a/arch/powerpc/include/asm/immap_86xx.h b/arch/powerpc/include/asm/immap_86xx.h
new file mode 100644
index 0000000..fd7acdb
--- /dev/null
+++ b/arch/powerpc/include/asm/immap_86xx.h
@@ -0,0 +1,1310 @@
+/*
+ * MPC86xx Internal Memory Map
+ *
+ * Copyright 2004 Freescale Semiconductor
+ * Jeff Brown (Jeffrey@freescale.com)
+ * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
+ *
+ */
+
+#ifndef __IMMAP_86xx__
+#define __IMMAP_86xx__
+
+#include <asm/types.h>
+#include <asm/fsl_dma.h>
+#include <asm/fsl_i2c.h>
+
+/* Local-Access Registers and MCM Registers(0x0000-0x2000) */
+typedef struct ccsr_local_mcm {
+	uint	ccsrbar;	/* 0x0 - Control Configuration Status Registers Base Address Register */
+	char	res1[4];
+	uint	altcbar;	/* 0x8 - Alternate Configuration Base Address Register */
+	char	res2[4];
+	uint	altcar;		/* 0x10 - Alternate Configuration Attribute Register */
+	char	res3[12];
+	uint	bptr;		/* 0x20 - Boot Page Translation Register */
+	char	res4[3044];
+	uint	lawbar0;	/* 0xc08 - Local Access Window 0 Base Address Register */
+	char	res5[4];
+	uint	lawar0;		/* 0xc10 - Local Access Window 0 Attributes Register */
+	char	res6[20];
+	uint	lawbar1;	/* 0xc28 - Local Access Window 1 Base Address Register */
+	char	res7[4];
+	uint	lawar1;		/* 0xc30 - Local Access Window 1 Attributes Register */
+	char	res8[20];
+	uint	lawbar2;	/* 0xc48 - Local Access Window 2 Base Address Register */
+	char	res9[4];
+	uint	lawar2;		/* 0xc50 - Local Access Window 2 Attributes Register */
+	char	res10[20];
+	uint	lawbar3;	/* 0xc68 - Local Access Window 3 Base Address Register */
+	char	res11[4];
+	uint	lawar3;		/* 0xc70 - Local Access Window 3 Attributes Register */
+	char	res12[20];
+	uint	lawbar4;	/* 0xc88 - Local Access Window 4 Base Address Register */
+	char	res13[4];
+	uint	lawar4;		/* 0xc90 - Local Access Window 4 Attributes Register */
+	char	res14[20];
+	uint	lawbar5;	/* 0xca8 - Local Access Window 5 Base Address Register */
+	char	res15[4];
+	uint	lawar5;		/* 0xcb0 - Local Access Window 5 Attributes Register */
+	char	res16[20];
+	uint	lawbar6;	/* 0xcc8 - Local Access Window 6 Base Address Register */
+	char	res17[4];
+	uint	lawar6;		/* 0xcd0 - Local Access Window 6 Attributes Register */
+	char	res18[20];
+	uint	lawbar7;	/* 0xce8 - Local Access Window 7 Base Address Register */
+	char	res19[4];
+	uint	lawar7;		/* 0xcf0 - Local Access Window 7 Attributes Register */
+	char	res20[20];
+	uint	lawbar8;	/* 0xd08 - Local Access Window 8 Base Address Register */
+	char	res21[4];
+	uint	lawar8;		/* 0xd10 - Local Access Window 8 Attributes Register */
+	char	res22[20];
+	uint	lawbar9;	/* 0xd28 - Local Access Window 9 Base Address Register */
+	char	res23[4];
+	uint	lawar9;		/* 0xd30 - Local Access Window 9 Attributes Register */
+	char	res24[716];
+	uint	abcr;		/* 0x1000 - MCM CCB Address Configuration Register */
+	char	res25[4];
+	uint    dbcr;           /* 0x1008 - MCM MPX data bus Configuration Register */
+	char	res26[4];
+	uint	pcr;		/* 0x1010 - MCM CCB Port Configuration Register */
+	char	res27[44];
+	uint	hpmr0;		/* 0x1040 - MCM HPM Threshold Count Register 0 */
+	uint	hpmr1;		/* 0x1044 - MCM HPM Threshold Count Register 1 */
+	uint	hpmr2;		/* 0x1048 - MCM HPM Threshold Count Register 2 */
+	uint	hpmr3;		/* 0x104c - MCM HPM Threshold Count Register 3 */
+	char	res28[16];
+	uint	hpmr4;		/* 0x1060 - MCM HPM Threshold Count Register 4 */
+	uint	hpmr5;		/* 0x1064 - MCM HPM Threshold Count Register 5 */
+	uint	hpmccr;		/* 0x1068 - MCM HPM Cycle Count Register */
+	char	res29[3476];
+	uint	edr;		/* 0x1e00 - MCM Error Detect Register */
+	char	res30[4];
+	uint	eer;		/* 0x1e08 - MCM Error Enable Register */
+	uint	eatr;		/* 0x1e0c - MCM Error Attributes Capture Register */
+	uint	eladr;		/* 0x1e10 - MCM Error Low Address Capture Register */
+	uint	ehadr;		/* 0x1e14 - MCM Error High Address Capture Register */
+	char	res31[488];
+} ccsr_local_mcm_t;
+
+/* DDR memory controller registers(0x2000-0x3000) and (0x6000-0x7000) */
+
+typedef struct ccsr_ddr {
+	uint	cs0_bnds;		/* 0x2000 - DDR Chip Select 0 Memory Bounds */
+	char	res1[4];
+	uint	cs1_bnds;		/* 0x2008 - DDR Chip Select 1 Memory Bounds */
+	char	res2[4];
+	uint	cs2_bnds;		/* 0x2010 - DDR Chip Select 2 Memory Bounds */
+	char	res3[4];
+	uint	cs3_bnds;		/* 0x2018 - DDR Chip Select 3 Memory Bounds */
+	char	res4[4];
+	uint	cs4_bnds;		/* 0x2020 - DDR Chip Select 4 Memory Bounds */
+	char	res5[4];
+	uint	cs5_bnds;		/* 0x2028 - DDR Chip Select 5 Memory Bounds */
+	char	res6[84];
+	uint	cs0_config;		/* 0x2080 - DDR Chip Select Configuration */
+	uint	cs1_config;		/* 0x2084 - DDR Chip Select Configuration */
+	uint	cs2_config;		/* 0x2088 - DDR Chip Select Configuration */
+	uint	cs3_config;		/* 0x208c - DDR Chip Select Configuration */
+	uint	cs4_config;		/* 0x2090 - DDR Chip Select Configuration */
+	uint	cs5_config;		/* 0x2094 - DDR Chip Select Configuration */
+	char	res7[104];
+	uint	timing_cfg_3;		/* 0x2100 - DDR SDRAM Timing Configuration Register 3 */
+	uint	timing_cfg_0;		/* 0x2104 - DDR SDRAM Timing Configuration Register 0 */
+	uint	timing_cfg_1;		/* 0x2108 - DDR SDRAM Timing Configuration Register 1 */
+	uint	timing_cfg_2;		/* 0x210c - DDR SDRAM Timing Configuration Register 2 */
+	uint	sdram_cfg;		/* 0x2110 - DDR SDRAM Control Configuration 1 */
+	uint    sdram_cfg_2;            /* 0x2114 - DDR SDRAM Control Configuration 2 */
+	uint	sdram_mode;		/* 0x2118 - DDR SDRAM Mode Configuration 1 */
+	uint    sdram_mode_2;		/* 0x211c - DDR SDRAM Mode Configuration 2 */
+	uint    sdram_mode_cntl;        /* 0x2120 - DDR SDRAM Mode Control */
+	uint	sdram_interval;		/* 0x2124 - DDR SDRAM Interval Configuration */
+	uint    sdram_data_init;	/* 0x2128 - DDR SDRAM Data Initialization */
+	char	res8[4];
+	uint	sdram_clk_cntl;		/* 0x2130 - DDR SDRAM Clock Control */
+	char    res9[12];
+	uint    sdram_ocd_cntl;		/* 0x2140 - DDR SDRAM OCD Control */
+	uint    sdram_ocd_status;	/* 0x2144 - DDR SDRAM OCD Status */
+	uint    init_addr;		/* 0x2148 - DDR training initialzation address */
+	uint    init_ext_addr;		/* 0x214C - DDR training initialzation extended address */
+	char    res10[2728];
+	uint    ip_rev1;		/* 0x2BF8 - DDR IP Block Revision 1 */
+	uint    ip_rev2;		/* 0x2BFC - DDR IP Block Revision 2 */
+	char	res11[512];
+	uint	data_err_inject_hi;	/* 0x2e00 - DDR Memory Data Path Error Injection Mask High */
+	uint	data_err_inject_lo;	/* 0x2e04 - DDR Memory Data Path Error Injection Mask Low */
+	uint	ecc_err_inject;		/* 0x2e08 - DDR Memory Data Path Error Injection Mask ECC */
+	char	res12[20];
+	uint	capture_data_hi;	/* 0x2e20 - DDR Memory Data Path Read Capture High */
+	uint	capture_data_lo;	/* 0x2e24 - DDR Memory Data Path Read Capture Low */
+	uint	capture_ecc;		/* 0x2e28 - DDR Memory Data Path Read Capture ECC */
+	char	res13[20];
+	uint	err_detect;		/* 0x2e40 - DDR Memory Error Detect */
+	uint	err_disable;		/* 0x2e44 - DDR Memory Error Disable */
+	uint	err_int_en;		/* 0x2e48 - DDR Memory Error Interrupt Enable */
+	uint	capture_attributes;	/* 0x2e4c - DDR Memory Error Attributes Capture */
+	uint	capture_address;	/* 0x2e50 - DDR Memory Error Address Capture */
+	uint	capture_ext_address;	/* 0x2e54 - DDR Memory Error Extended Address Capture */
+	uint	err_sbe;		/* 0x2e58 - DDR Memory Single-Bit ECC Error Management */
+	char	res14[164];
+	uint	debug_1;		/* 0x2f00 */
+	uint	debug_2;
+	uint	debug_3;
+	uint	debug_4;
+	uint	debug_5;
+	char	res15[236];
+} ccsr_ddr_t;
+
+
+/* Daul I2C Registers(0x3000-0x4000) */
+typedef struct ccsr_i2c {
+	struct fsl_i2c	i2c[2];
+	u8	res[4096 - 2 * sizeof(struct fsl_i2c)];
+} ccsr_i2c_t;
+
+/* DUART Registers(0x4000-0x5000) */
+typedef struct ccsr_duart {
+	char	res1[1280];
+	u_char	urbr1_uthr1_udlb1;/* 0x4500 - URBR1, UTHR1, UDLB1 with the same address offset of 0x04500 */
+	u_char	uier1_udmb1;	/* 0x4501 - UIER1, UDMB1 with the same address offset of 0x04501 */
+	u_char	uiir1_ufcr1_uafr1;/* 0x4502 - UIIR1, UFCR1, UAFR1 with the same address offset of 0x04502 */
+	u_char	ulcr1;		/* 0x4503 - UART1 Line Control Register */
+	u_char	umcr1;		/* 0x4504 - UART1 Modem Control Register */
+	u_char	ulsr1;		/* 0x4505 - UART1 Line Status Register */
+	u_char	umsr1;		/* 0x4506 - UART1 Modem Status Register */
+	u_char	uscr1;		/* 0x4507 - UART1 Scratch Register */
+	char	res2[8];
+	u_char	udsr1;		/* 0x4510 - UART1 DMA Status Register */
+	char	res3[239];
+	u_char	urbr2_uthr2_udlb2;/* 0x4600 - URBR2, UTHR2, UDLB2 with the same address offset of 0x04600 */
+	u_char	uier2_udmb2;	/* 0x4601 - UIER2, UDMB2 with the same address offset of 0x04601 */
+	u_char	uiir2_ufcr2_uafr2;/* 0x4602 - UIIR2, UFCR2, UAFR2 with the same address offset of 0x04602 */
+	u_char	ulcr2;		/* 0x4603 - UART2 Line Control Register */
+	u_char	umcr2;		/* 0x4604 - UART2 Modem Control Register */
+	u_char	ulsr2;		/* 0x4605 - UART2 Line Status Register */
+	u_char	umsr2;		/* 0x4606 - UART2 Modem Status Register */
+	u_char	uscr2;		/* 0x4607 - UART2 Scratch Register */
+	char	res4[8];
+	u_char	udsr2;		/* 0x4610 - UART2 DMA Status Register */
+	char	res5[2543];
+} ccsr_duart_t;
+
+
+/* Local Bus Controller Registers(0x5000-0x6000) */
+typedef struct ccsr_lbc {
+	uint	br0;		/* 0x5000 - LBC Base Register 0 */
+	uint	or0;		/* 0x5004 - LBC Options Register 0 */
+	uint	br1;		/* 0x5008 - LBC Base Register 1 */
+	uint	or1;		/* 0x500c - LBC Options Register 1 */
+	uint	br2;		/* 0x5010 - LBC Base Register 2 */
+	uint	or2;		/* 0x5014 - LBC Options Register 2 */
+	uint	br3;		/* 0x5018 - LBC Base Register 3 */
+	uint	or3;		/* 0x501c - LBC Options Register 3 */
+	uint	br4;		/* 0x5020 - LBC Base Register 4 */
+	uint	or4;		/* 0x5024 - LBC Options Register 4 */
+	uint	br5;		/* 0x5028 - LBC Base Register 5 */
+	uint	or5;		/* 0x502c - LBC Options Register 5 */
+	uint	br6;		/* 0x5030 - LBC Base Register 6 */
+	uint	or6;		/* 0x5034 - LBC Options Register 6 */
+	uint	br7;		/* 0x5038 - LBC Base Register 7 */
+	uint	or7;		/* 0x503c - LBC Options Register 7 */
+	char	res1[40];
+	uint	mar;		/* 0x5068 - LBC UPM Address Register */
+	char	res2[4];
+	uint	mamr;		/* 0x5070 - LBC UPMA Mode Register */
+	uint	mbmr;		/* 0x5074 - LBC UPMB Mode Register */
+	uint	mcmr;		/* 0x5078 - LBC UPMC Mode Register */
+	char	res3[8];
+	uint	mrtpr;		/* 0x5084 - LBC Memory Refresh Timer Prescaler Register */
+	uint	mdr;		/* 0x5088 - LBC UPM Data Register */
+	char	res4[8];
+	uint	lsdmr;		/* 0x5094 - LBC SDRAM Mode Register */
+	char	res5[8];
+	uint	lurt;		/* 0x50a0 - LBC UPM Refresh Timer */
+	uint	lsrt;		/* 0x50a4 - LBC SDRAM Refresh Timer */
+	char	res6[8];
+	uint	ltesr;		/* 0x50b0 - LBC Transfer Error Status Register */
+	uint	ltedr;		/* 0x50b4 - LBC Transfer Error Disable Register */
+	uint	lteir;		/* 0x50b8 - LBC Transfer Error Interrupt Register */
+	uint	lteatr;		/* 0x50bc - LBC Transfer Error Attributes Register */
+	uint	ltear;		/* 0x50c0 - LBC Transfer Error Address Register */
+	char	res7[12];
+	uint	lbcr;		/* 0x50d0 - LBC Configuration Register */
+	uint	lcrr;		/* 0x50d4 - LBC Clock Ratio Register */
+	char	res8[3880];
+} ccsr_lbc_t;
+
+/* PCI Express Registers(0x8000-0x9000) and (0x9000-0xA000) */
+typedef struct ccsr_pex {
+	uint	cfg_addr;	/* 0x8000 - PEX Configuration Address Register */
+	uint	cfg_data;	/* 0x8004 - PEX Configuration Data Register */
+	char	res1[4];
+	uint	out_comp_to;	/* 0x800C - PEX Outbound Completion Timeout Register */
+	char	res2[16];
+	uint	pme_msg_det;	/* 0x8020 - PEX PME & message detect register */
+	uint    pme_msg_int_en;	/* 0x8024 - PEX PME & message interrupt enable register */
+	uint    pme_msg_dis;	/* 0x8028 - PEX PME & message disable register */
+	uint    pm_command;	/* 0x802c - PEX PM Command register */
+	char	res3[3016];
+	uint    block_rev1;	/* 0x8bf8 - PEX Block Revision register 1 */
+	uint    block_rev2;	/* 0x8bfc - PEX Block Revision register 2 */
+	uint	potar0;	        /* 0x8c00 - PEX Outbound Transaction Address Register 0 */
+	uint	potear0;	/* 0x8c04 - PEX Outbound Translation Extended Address Register 0 */
+	char	res4[8];
+	uint	powar0;	        /* 0x8c10 - PEX Outbound Window Attributes Register 0 */
+	char	res5[12];
+	uint	potar1;	        /* 0x8c20 - PEX Outbound Transaction Address Register 1 */
+	uint	potear1;	/* 0x8c24 - PEX Outbound Translation Extended Address Register 1 */
+	uint	powbar1;	/* 0x8c28 - PEX Outbound Window Base Address Register 1 */
+	char	res6[4];
+	uint	powar1;	        /* 0x8c30 - PEX Outbound Window Attributes Register 1 */
+	char	res7[12];
+	uint	potar2;	        /* 0x8c40 - PEX Outbound Transaction Address Register 2 */
+	uint	potear2;	/* 0x8c44 - PEX Outbound Translation Extended Address Register 2 */
+	uint	powbar2;	/* 0x8c48 - PEX Outbound Window Base Address Register 2 */
+	char	res8[4];
+	uint	powar2;	        /* 0x8c50 - PEX Outbound Window Attributes Register 2 */
+	char	res9[12];
+	uint	potar3;	        /* 0x8c60 - PEX Outbound Transaction Address Register 3 */
+	uint	potear3;	/* 0x8c64 - PEX Outbound Translation Extended Address Register 3 */
+	uint	powbar3;	/* 0x8c68 - PEX Outbound Window Base Address Register 3 */
+	char	res10[4];
+	uint	powar3;	        /* 0x8c70 - PEX Outbound Window Attributes Register 3 */
+	char	res11[12];
+	uint	potar4;	        /* 0x8c80 - PEX Outbound Transaction Address Register 4 */
+	uint	potear4;	/* 0x8c84 - PEX Outbound Translation Extended Address Register 4 */
+	uint	powbar4;	/* 0x8c88 - PEX Outbound Window Base Address Register 4 */
+	char	res12[4];
+	uint	powar4;	        /* 0x8c90 - PEX Outbound Window Attributes Register 4 */
+	char	res13[12];
+	char	res14[256];
+	uint	pitar3;	        /* 0x8da0 - PEX Inbound Translation Address Register 3  */
+	char	res15[4];
+	uint	piwbar3;	/* 0x8da8 - PEX Inbound Window Base Address Register 3 */
+	uint	piwbear3;	/* 0x8dac - PEX Inbound Window Base Extended Address Register 3 */
+	uint	piwar3;	        /* 0x8db0 - PEX Inbound Window Attributes Register 3 */
+	char	res16[12];
+	uint	pitar2;	        /* 0x8dc0 - PEX Inbound Translation Address Register 2  */
+	char	res17[4];
+	uint	piwbar2;	/* 0x8dc8 - PEX Inbound Window Base Address Register 2 */
+	uint	piwbear2;	/* 0x8dcc - PEX Inbound Window Base Extended Address Register 2 */
+	uint	piwar2;	        /* 0x8dd0 - PEX Inbound Window Attributes Register 2 */
+	char	res18[12];
+	uint	pitar1;	        /* 0x8de0 - PEX Inbound Translation Address Register 1  */
+	char	res19[4];
+	uint	piwbar1;	/* 0x8de8 - PEX Inbound Window Base Address Register 1 */
+	uint	piwbear1;
+	uint	piwar1;	        /* 0x8df0 - PEX Inbound Window Attributes Register 1 */
+	char	res20[12];
+	uint	pedr;		/* 0x8e00 - PEX Error Detect Register */
+	char    res21[4];
+	uint	peer;		/* 0x8e08 - PEX Error Interrupt Enable Register */
+	char    res22[4];
+	uint	pecdr;		/* 0x8e10 - PEX Error Disable Register */
+	char    res23[12];
+	uint	peer_stat;	/* 0x8e20 - PEX Error Capture Status Register */
+	char    res24[4];
+	uint	perr_cap0;	/* 0x8e28 - PEX Error Capture Register 0 */
+	uint	perr_cap1;	/* 0x8e2c - PEX Error Capture Register 1 */
+	uint	perr_cap2;	/* 0x8e30 - PEX Error Capture Register 2 */
+	uint	perr_cap3;	/* 0x8e34 - PEX Error Capture Register 3 */
+	char	res25[452];
+	char    res26[4];
+} ccsr_pex_t;
+
+/* Hyper Transport Register Block (0xA000-0xB000) */
+typedef struct ccsr_ht {
+	uint    hcfg_addr;      /* 0xa000 - HT Configuration Address register */
+	uint    hcfg_data;      /* 0xa004 - HT Configuration Data register */
+	char	res1[3064];
+	uint    howtar0;        /* 0xac00 - HT Outbound Window 0 Translation register */
+	char	res2[12];
+	uint    howar0;         /* 0xac10 - HT Outbound Window 0 Attributes register */
+	char	res3[12];
+	uint    howtar1;        /* 0xac20 - HT Outbound Window 1 Translation register */
+	char	res4[4];
+	uint    howbar1;        /* 0xac28 - HT Outbound Window 1 Base Address register */
+	char	res5[4];
+	uint    howar1;         /* 0xac30 - HT Outbound Window 1 Attributes register */
+	char	res6[12];
+	uint    howtar2;        /* 0xac40 - HT Outbound Window 2 Translation register */
+	char	res7[4];
+	uint    howbar2;        /* 0xac48 - HT Outbound Window 2 Base Address register */
+	char	res8[4];
+	uint    howar2;         /* 0xac50 - HT Outbound Window 2 Attributes register */
+	char	res9[12];
+	uint    howtar3;        /* 0xac60 - HT Outbound Window 3 Translation register */
+	char	res10[4];
+	uint    howbar3;        /* 0xac68 - HT Outbound Window 3 Base Address register */
+	char	res11[4];
+	uint    howar3;         /* 0xac70 - HT Outbound Window 3 Attributes  register */
+	char	res12[12];
+	uint    howtar4;        /* 0xac80 - HT Outbound Window 4 Translation register */
+	char	res13[4];
+	uint    howbar4;        /* 0xac88 - HT Outbound Window 4 Base Address register */
+	char	res14[4];
+	uint    howar4;         /* 0xac90 - HT Outbound Window 4 Attributes register */
+	char	res15[236];
+	uint    hiwtar4;        /* 0xad80 - HT Inbound Window 4 Translation register */
+	char	res16[4];
+	uint    hiwbar4;        /* 0xad88 - HT Inbound Window 4 Base Address register */
+	char	res17[4];
+	uint    hiwar4;         /* 0xad90 - HT Inbound Window 4 Attributes register */
+	char	res18[12];
+	uint    hiwtar3;        /* 0xada0 - HT Inbound Window 3 Translation register */
+	char	res19[4];
+	uint    hiwbar3;        /* 0xada8 - HT Inbound Window 3 Base Address register */
+	char	res20[4];
+	uint    hiwar3;         /* 0xadb0 - HT Inbound Window 3 Attributes register */
+	char	res21[12];
+	uint    hiwtar2;        /* 0xadc0 - HT Inbound Window 2 Translation register */
+	char	res22[4];
+	uint    hiwbar2;        /* 0xadc8 - HT Inbound Window 2 Base Address register */
+	char	res23[4];
+	uint    hiwar2;         /* 0xadd0 - HT Inbound Window 2 Attributes register */
+	char	res24[12];
+	uint    hiwtar1;        /* 0xade0 - HT Inbound Window 1 Translation register */
+	char	res25[4];
+	uint    hiwbar1;        /* 0xade8 - HT Inbound Window 1 Base Address register */
+	char	res26[4];
+	uint    hiwar1;         /* 0xadf0 - HT Inbound Window 1 Attributes register */
+	char	res27[12];
+	uint    hedr;           /* 0xae00 - HT Error Detect register */
+	char	res28[4];
+	uint    heier;          /* 0xae08 - HT Error Interrupt Enable register */
+	char	res29[4];
+	uint    hecdr;          /* 0xae10 - HT Error Capture Disbale register */
+	char	res30[12];
+	uint    hecsr;          /* 0xae20 - HT Error Capture Status register */
+	char	res31[4];
+	uint    hec0;           /* 0xae28 - HT Error Capture 0 register */
+	uint    hec1;           /* 0xae2c - HT Error Capture 1 register */
+	uint    hec2;           /* 0xae30 - HT Error Capture 2 register */
+	char    res32[460];
+} ccsr_ht_t;
+
+/* DMA Registers(0x2_1000-0x2_2000) */
+typedef struct ccsr_dma {
+	char	res1[256];
+	struct fsl_dma dma[4];
+	uint	dgsr;		/* 0x21300 - DMA General Status Register */
+	char	res2[3324];
+} ccsr_dma_t;
+
+/* tsec1-4: 24000-28000 */
+typedef struct ccsr_tsec {
+	uint    id;		/* 0x24000 - Controller ID Register */
+	char	res1[12];
+	uint	ievent;		/* 0x24010 - Interrupt Event Register */
+	uint	imask;		/* 0x24014 - Interrupt Mask Register */
+	uint	edis;		/* 0x24018 - Error Disabled Register */
+	char	res2[4];
+	uint	ecntrl;		/* 0x24020 - Ethernet Control Register */
+	char    res2_1[4];
+	uint	ptv;		/* 0x24028 - Pause Time Value Register */
+	uint	dmactrl;	/* 0x2402c - DMA Control Register */
+	uint	tbipa;		/* 0x24030 - TBI PHY Address Register */
+	char	res3[88];
+	uint	fifo_tx_thr;	/* 0x2408c - FIFO transmit threshold register */
+	char	res4[8];
+	uint	fifo_tx_starve;	/* 0x24098 - FIFO transmit starve register */
+	uint	fifo_tx_starve_shutoff;/* 0x2409c - FIFO transmit starve shutoff register */
+	char    res4_1[4];
+	uint    fifo_rx_pause;  /* 0x240a4 - FIFO receive pause threshold register */
+	uint    fifo_rx_alarm;  /* 0x240a8 - FIFO receive alarm threshold register */
+	char	res5[84];
+	uint	tctrl;		/* 0x24100 - Transmit Control Register */
+	uint	tstat;		/* 0x24104 - Transmit Status Register */
+	uint    dfvlan;		/* 0x24108 - Default VLAN control word */
+	char    res6[4];
+	uint    txic;		/* 0x24110 - Transmit interrupt coalescing Register */
+	uint    tqueue;         /* 0x24114 - Transmit Queue Control Register */
+	char	res7[40];
+	uint    tr03wt;         /* 0x24140 - TxBD Rings 0-3 round-robin weightings */
+	uint    tw47wt;         /* 0x24144 - TxBD Rings 4-7 round-robin weightings */
+	char    res8[52];
+	uint	tbdbph;	        /* 0x2417c - Transmit Data Buffer Pointer High Register */
+	char    res9[4];
+	uint    tbptr0;         /* 0x24184 - Transmit Buffer Descriptor Pointer for Ring 0 */
+	char    res10[4];
+	uint    tbptr1;         /* 0x2418C - Transmit Buffer Descriptor Pointer for Ring 1 */
+	char    res11[4];
+	uint    tbptr2;         /* 0x24194 - Transmit Buffer Descriptor Pointer for Ring 2 */
+	char    res12[4];
+	uint    tbptr3;         /* 0x2419C - Transmit Buffer Descriptor Pointer for Ring 3 */
+	char    res13[4];
+	uint    tbptr4;         /* 0x241A4 - Transmit Buffer Descriptor Pointer for Ring 4 */
+	char    res14[4];
+	uint    tbptr5;         /* 0x241AC - Transmit Buffer Descriptor Pointer for Ring 5 */
+	char    res15[4];
+	uint    tbptr6;         /* 0x241B4 - Transmit Buffer Descriptor Pointer for Ring 6 */
+	char    res16[4];
+	uint    tbptr7;         /* 0x241BC - Transmit Buffer Descriptor Pointer for Ring 7 */
+	char    res17[64];
+	uint	tbaseh;		/* 0x24200 - Transmit Descriptor Base Address High Register */
+	uint	tbase0;		/* 0x24204 - Transmit Descriptor Base Address Register of Ring 0 */
+	char    res18[4];
+	uint    tbase1;         /* 0x2420C - Transmit Descriptor base address of Ring 1 */
+	char    res19[4];
+	uint    tbase2;         /* 0x24214 - Transmit Descriptor base address of Ring 2 */
+	char    res20[4];
+	uint    tbase3;         /* 0x2421C - Transmit Descriptor base address of Ring 3 */
+	char    res21[4];
+	uint    tbase4;         /* 0x24224 - Transmit Descriptor base address of Ring 4 */
+	char    res22[4];
+	uint    tbase5;         /* 0x2422C - Transmit Descriptor base address of Ring 5 */
+	char    res23[4];
+	uint    tbase6;         /* 0x24234 - Transmit Descriptor base address of Ring 6 */
+	char    res24[4];
+	uint    tbase7;         /* 0x2423C - Transmit Descriptor base address of Ring 7 */
+	char    res25[192];
+	uint	rctrl;		/* 0x24300 - Receive Control Register */
+	uint	rstat;		/* 0x24304 - Receive Status Register */
+	char	res26[8];
+	uint    rxic;           /* 0x24310 - Receive Interrupt Coalecing Register */
+	uint    rqueue;         /* 0x24314 - Receive queue control register */
+	char	res27[24];
+	uint    rbifx;		/* 0x24330 - Receive bit field extract control Register */
+	uint    rqfar;		/* 0x24334 - Receive queue filing table address Register */
+	uint    rqfcr;		/* 0x24338 - Receive queue filing table control Register */
+	uint    rqfpr;		/* 0x2433c - Receive queue filing table property Register */
+	uint	mrblr;		/* 0x24340 - Maximum Receive Buffer Length Register */
+	char	res28[56];
+	uint    rbdbph;		/* 0x2437C - Receive Data Buffer Pointer High */
+	char    res29[4];
+	uint	rbptr0;		/* 0x24384 - Receive Buffer Descriptor Pointer for Ring 0 */
+	char    res30[4];
+	uint	rbptr1;		/* 0x2438C - Receive Buffer Descriptor Pointer for Ring 1 */
+	char    res31[4];
+	uint	rbptr2;		/* 0x24394 - Receive Buffer Descriptor Pointer for Ring 2 */
+	char    res32[4];
+	uint	rbptr3;		/* 0x2439C - Receive Buffer Descriptor Pointer for Ring 3 */
+	char    res33[4];
+	uint	rbptr4;		/* 0x243A4 - Receive Buffer Descriptor Pointer for Ring 4 */
+	char    res34[4];
+	uint	rbptr5;		/* 0x243AC - Receive Buffer Descriptor Pointer for Ring 5 */
+	char    res35[4];
+	uint	rbptr6;		/* 0x243B4 - Receive Buffer Descriptor Pointer for Ring 6 */
+	char    res36[4];
+	uint	rbptr7;		/* 0x243BC - Receive Buffer Descriptor Pointer for Ring 7 */
+	char    res37[64];
+	uint	rbaseh;		/* 0x24400 - Receive Descriptor Base Address High 0 */
+	uint	rbase0;		/* 0x24404 - Receive Descriptor Base Address of Ring 0 */
+	char    res38[4];
+	uint	rbase1;		/* 0x2440C - Receive Descriptor Base Address of Ring 1 */
+	char    res39[4];
+	uint	rbase2;		/* 0x24414 - Receive Descriptor Base Address of Ring 2 */
+	char    res40[4];
+	uint	rbase3;		/* 0x2441C - Receive Descriptor Base Address of Ring 3 */
+	char    res41[4];
+	uint	rbase4;		/* 0x24424 - Receive Descriptor Base Address of Ring 4 */
+	char    res42[4];
+	uint	rbase5;		/* 0x2442C - Receive Descriptor Base Address of Ring 5 */
+	char    res43[4];
+	uint	rbase6;		/* 0x24434 - Receive Descriptor Base Address of Ring 6 */
+	char    res44[4];
+	uint	rbase7;		/* 0x2443C - Receive Descriptor Base Address of Ring 7 */
+	char    res45[192];
+	uint	maccfg1;	/* 0x24500 - MAC Configuration 1 Register */
+	uint	maccfg2;	/* 0x24504 - MAC Configuration 2 Register */
+	uint	ipgifg;		/* 0x24508 - Inter Packet Gap/Inter Frame Gap Register */
+	uint	hafdup;		/* 0x2450c - Half Duplex Register */
+	uint	maxfrm;		/* 0x24510 - Maximum Frame Length Register */
+	char	res46[12];
+	uint	miimcfg;	/* 0x24520 - MII Management Configuration Register */
+	uint	miimcom;	/* 0x24524 - MII Management Command Register */
+	uint	miimadd;	/* 0x24528 - MII Management Address Register */
+	uint	miimcon;	/* 0x2452c - MII Management Control Register */
+	uint	miimstat;	/* 0x24530 - MII Management Status Register */
+	uint	miimind;	/* 0x24534 - MII Management Indicator Register */
+	uint    ifctrl;		/* 0x24538 - Interface Contrl Register */
+	uint	ifstat;		/* 0x2453c - Interface Status Register */
+	uint	macstnaddr1;	/* 0x24540 - Station Address Part 1 Register */
+	uint	macstnaddr2;	/* 0x24544 - Station Address Part 2 Register */
+	uint    mac01addr1;     /* 0x24548 - MAC exact match address 1, part 1 */
+	uint    mac01addr2;     /* 0x2454C - MAC exact match address 1, part 2 */
+	uint    mac02addr1;     /* 0x24550 - MAC exact match address 2, part 1 */
+	uint    mac02addr2;     /* 0x24554 - MAC exact match address 2, part 2 */
+	uint    mac03addr1;     /* 0x24558 - MAC exact match address 3, part 1 */
+	uint    mac03addr2;     /* 0x2455C - MAC exact match address 3, part 2 */
+	uint    mac04addr1;     /* 0x24560 - MAC exact match address 4, part 1 */
+	uint    mac04addr2;     /* 0x24564 - MAC exact match address 4, part 2 */
+	uint    mac05addr1;     /* 0x24568 - MAC exact match address 5, part 1 */
+	uint    mac05addr2;     /* 0x2456C - MAC exact match address 5, part 2 */
+	uint    mac06addr1;     /* 0x24570 - MAC exact match address 6, part 1 */
+	uint    mac06addr2;     /* 0x24574 - MAC exact match address 6, part 2 */
+	uint    mac07addr1;     /* 0x24578 - MAC exact match address 7, part 1 */
+	uint    mac07addr2;     /* 0x2457C - MAC exact match address 7, part 2 */
+	uint    mac08addr1;     /* 0x24580 - MAC exact match address 8, part 1 */
+	uint    mac08addr2;     /* 0x24584 - MAC exact match address 8, part 2 */
+	uint    mac09addr1;     /* 0x24588 - MAC exact match address 9, part 1 */
+	uint    mac09addr2;     /* 0x2458C - MAC exact match address 9, part 2 */
+	uint    mac10addr1;     /* 0x24590 - MAC exact match address 10, part 1 */
+	uint    mac10addr2;     /* 0x24594 - MAC exact match address 10, part 2 */
+	uint    mac11addr1;     /* 0x24598 - MAC exact match address 11, part 1 */
+	uint    mac11addr2;     /* 0x2459C - MAC exact match address 11, part 2 */
+	uint    mac12addr1;     /* 0x245A0 - MAC exact match address 12, part 1 */
+	uint    mac12addr2;     /* 0x245A4 - MAC exact match address 12, part 2 */
+	uint    mac13addr1;     /* 0x245A8 - MAC exact match address 13, part 1 */
+	uint    mac13addr2;     /* 0x245AC - MAC exact match address 13, part 2 */
+	uint    mac14addr1;     /* 0x245B0 - MAC exact match address 14, part 1 */
+	uint    mac14addr2;     /* 0x245B4 - MAC exact match address 14, part 2 */
+	uint    mac15addr1;     /* 0x245B8 - MAC exact match address 15, part 1 */
+	uint    mac15addr2;     /* 0x245BC - MAC exact match address 15, part 2 */
+	char	res48[192];
+	uint	tr64;		/* 0x24680 - Transmit and Receive 64-byte Frame Counter */
+	uint	tr127;		/* 0x24684 - Transmit and Receive 65-127 byte Frame Counter */
+	uint	tr255;		/* 0x24688 - Transmit and Receive 128-255 byte Frame Counter */
+	uint	tr511;		/* 0x2468c - Transmit and Receive 256-511 byte Frame Counter */
+	uint	tr1k;		/* 0x24690 - Transmit and Receive 512-1023 byte Frame Counter */
+	uint	trmax;		/* 0x24694 - Transmit and Receive 1024-1518 byte Frame Counter */
+	uint	trmgv;		/* 0x24698 - Transmit and Receive 1519-1522 byte Good VLAN Frame */
+	uint	rbyt;		/* 0x2469c - Receive Byte Counter */
+	uint	rpkt;		/* 0x246a0 - Receive Packet Counter */
+	uint	rfcs;		/* 0x246a4 - Receive FCS Error Counter */
+	uint	rmca;		/* 0x246a8 - Receive Multicast Packet Counter */
+	uint	rbca;		/* 0x246ac - Receive Broadcast Packet Counter */
+	uint	rxcf;		/* 0x246b0 - Receive Control Frame Packet Counter */
+	uint	rxpf;		/* 0x246b4 - Receive Pause Frame Packet Counter */
+	uint	rxuo;		/* 0x246b8 - Receive Unknown OP Code Counter */
+	uint	raln;		/* 0x246bc - Receive Alignment Error Counter */
+	uint	rflr;		/* 0x246c0 - Receive Frame Length Error Counter */
+	uint	rcde;		/* 0x246c4 - Receive Code Error Counter */
+	uint	rcse;		/* 0x246c8 - Receive Carrier Sense Error Counter */
+	uint	rund;		/* 0x246cc - Receive Undersize Packet Counter */
+	uint	rovr;		/* 0x246d0 - Receive Oversize Packet Counter */
+	uint	rfrg;		/* 0x246d4 - Receive Fragments Counter */
+	uint	rjbr;		/* 0x246d8 - Receive Jabber Counter */
+	uint	rdrp;		/* 0x246dc - Receive Drop Counter */
+	uint	tbyt;		/* 0x246e0 - Transmit Byte Counter Counter */
+	uint	tpkt;		/* 0x246e4 - Transmit Packet Counter */
+	uint	tmca;		/* 0x246e8 - Transmit Multicast Packet Counter */
+	uint	tbca;		/* 0x246ec - Transmit Broadcast Packet Counter */
+	uint	txpf;		/* 0x246f0 - Transmit Pause Control Frame Counter */
+	uint	tdfr;		/* 0x246f4 - Transmit Deferral Packet Counter */
+	uint	tedf;		/* 0x246f8 - Transmit Excessive Deferral Packet Counter */
+	uint	tscl;		/* 0x246fc - Transmit Single Collision Packet Counter */
+	uint	tmcl;		/* 0x24700 - Transmit Multiple Collision Packet Counter */
+	uint	tlcl;		/* 0x24704 - Transmit Late Collision Packet Counter */
+	uint	txcl;		/* 0x24708 - Transmit Excessive Collision Packet Counter */
+	uint	tncl;		/* 0x2470c - Transmit Total Collision Counter */
+	char	res49[4];
+	uint	tdrp;		/* 0x24714 - Transmit Drop Frame Counter */
+	uint	tjbr;		/* 0x24718 - Transmit Jabber Frame Counter */
+	uint	tfcs;		/* 0x2471c - Transmit FCS Error Counter */
+	uint	txcf;		/* 0x24720 - Transmit Control Frame Counter */
+	uint	tovr;		/* 0x24724 - Transmit Oversize Frame Counter */
+	uint	tund;		/* 0x24728 - Transmit Undersize Frame Counter */
+	uint	tfrg;		/* 0x2472c - Transmit Fragments Frame Counter */
+	uint	car1;		/* 0x24730 - Carry Register One */
+	uint	car2;		/* 0x24734 - Carry Register Two */
+	uint	cam1;		/* 0x24738 - Carry Mask Register One */
+	uint	cam2;		/* 0x2473c - Carry Mask Register Two */
+	uint    rrej;	        /* 0x24740 - Receive filer rejected packet counter */
+	char	res50[188];
+	uint	iaddr0;		/* 0x24800 - Indivdual address register 0 */
+	uint	iaddr1;		/* 0x24804 - Indivdual address register 1 */
+	uint	iaddr2;		/* 0x24808 - Indivdual address register 2 */
+	uint	iaddr3;		/* 0x2480c - Indivdual address register 3 */
+	uint	iaddr4;		/* 0x24810 - Indivdual address register 4 */
+	uint	iaddr5;		/* 0x24814 - Indivdual address register 5 */
+	uint	iaddr6;		/* 0x24818 - Indivdual address register 6 */
+	uint	iaddr7;		/* 0x2481c - Indivdual address register 7 */
+	char	res51[96];
+	uint	gaddr0;		/* 0x24880 - Global address register 0 */
+	uint	gaddr1;		/* 0x24884 - Global address register 1 */
+	uint	gaddr2;		/* 0x24888 - Global address register 2 */
+	uint	gaddr3;		/* 0x2488c - Global address register 3 */
+	uint	gaddr4;		/* 0x24890 - Global address register 4 */
+	uint	gaddr5;		/* 0x24894 - Global address register 5 */
+	uint	gaddr6;		/* 0x24898 - Global address register 6 */
+	uint	gaddr7;		/* 0x2489c - Global address register 7 */
+	char	res52[352];
+	uint    fifocfg;        /* 0x24A00 - FIFO interface configuration register */
+	char    res53[500];
+	uint    attr;           /* 0x24BF8 - DMA Attribute register */
+	uint    attreli;        /* 0x24BFC - DMA Attribute extract length and index register */
+	char    res54[1024];
+} ccsr_tsec_t;
+
+/* PIC Registers(0x4_0000-0x6_1000) */
+
+typedef struct ccsr_pic {
+	char	res1[64];
+	uint	ipidr0;		/* 0x40040 - Interprocessor Interrupt Dispatch Register 0 */
+	char	res2[12];
+	uint	ipidr1;		/* 0x40050 - Interprocessor Interrupt Dispatch Register 1 */
+	char	res3[12];
+	uint	ipidr2;		/* 0x40060 - Interprocessor Interrupt Dispatch Register 2 */
+	char	res4[12];
+	uint	ipidr3;		/* 0x40070 - Interprocessor Interrupt Dispatch Register 3 */
+	char	res5[12];
+	uint	ctpr;		/* 0x40080 - Current Task Priority Register */
+	char	res6[12];
+	uint	whoami;		/* 0x40090 - Who Am I Register */
+	char	res7[12];
+	uint	iack;		/* 0x400a0 - Interrupt Acknowledge Register */
+	char	res8[12];
+	uint	eoi;		/* 0x400b0 - End Of Interrupt Register */
+	char	res9[3916];
+	uint	frr;		/* 0x41000 - Feature Reporting Register */
+	char	res10[28];
+	uint	gcr;		/* 0x41020 - Global Configuration Register */
+#define MPC86xx_PICGCR_RST	0x80000000
+#define MPC86xx_PICGCR_MODE	0x20000000
+	char	res11[92];
+	uint	vir;		/* 0x41080 - Vendor Identification Register */
+	char	res12[12];
+	uint	pir;		/* 0x41090 - Processor Initialization Register */
+	char	res13[12];
+	uint	ipivpr0;	/* 0x410a0 - IPI Vector/Priority Register 0 */
+	char	res14[12];
+	uint	ipivpr1;	/* 0x410b0 - IPI Vector/Priority Register 1 */
+	char	res15[12];
+	uint	ipivpr2;	/* 0x410c0 - IPI Vector/Priority Register 2 */
+	char	res16[12];
+	uint	ipivpr3;	/* 0x410d0 - IPI Vector/Priority Register 3 */
+	char	res17[12];
+	uint	svr;		/* 0x410e0 - Spurious Vector Register */
+	char	res18[12];
+	uint	tfrr;		/* 0x410f0 - Timer Frequency Reporting Register */
+	char	res19[12];
+	uint	gtccr0;		/* 0x41100 - Global Timer Current Count Register 0 */
+	char	res20[12];
+	uint	gtbcr0;		/* 0x41110 - Global Timer Base Count Register 0 */
+	char	res21[12];
+	uint	gtvpr0;		/* 0x41120 - Global Timer Vector/Priority Register 0 */
+	char	res22[12];
+	uint	gtdr0;		/* 0x41130 - Global Timer Destination Register 0 */
+	char	res23[12];
+	uint	gtccr1;		/* 0x41140 - Global Timer Current Count Register 1 */
+	char	res24[12];
+	uint	gtbcr1;		/* 0x41150 - Global Timer Base Count Register 1 */
+	char	res25[12];
+	uint	gtvpr1;		/* 0x41160 - Global Timer Vector/Priority Register 1 */
+	char	res26[12];
+	uint	gtdr1;		/* 0x41170 - Global Timer Destination Register 1 */
+	char	res27[12];
+	uint	gtccr2;		/* 0x41180 - Global Timer Current Count Register 2 */
+	char	res28[12];
+	uint	gtbcr2;		/* 0x41190 - Global Timer Base Count Register 2 */
+	char	res29[12];
+	uint	gtvpr2;		/* 0x411a0 - Global Timer Vector/Priority Register 2 */
+	char	res30[12];
+	uint	gtdr2;		/* 0x411b0 - Global Timer Destination Register 2 */
+	char	res31[12];
+	uint	gtccr3;		/* 0x411c0 - Global Timer Current Count Register 3 */
+	char	res32[12];
+	uint	gtbcr3;		/* 0x411d0 - Global Timer Base Count Register 3 */
+	char	res33[12];
+	uint	gtvpr3;		/* 0x411e0 - Global Timer Vector/Priority Register 3 */
+	char	res34[12];
+	uint	gtdr3;		/* 0x411f0 - Global Timer Destination Register 3 */
+	char	res35[268];
+	uint	tcr;		/* 0x41300 - Timer Control Register */
+	char	res36[12];
+	uint	irqsr0;		/* 0x41310 - IRQ_OUT Summary Register 0 */
+	char	res37[12];
+	uint	irqsr1;		/* 0x41320 - IRQ_OUT Summary Register 1 */
+	char	res38[12];
+	uint	cisr0;		/* 0x41330 - Critical Interrupt Summary Register 0 */
+	char	res39[12];
+	uint	cisr1;		/* 0x41340 - Critical Interrupt Summary Register 1 */
+	char	res40[12];
+	uint	pm0mr0;		/* 0x41350 - Performance monitor 0 mask register 0  */
+	char	res41[12];
+	uint	pm0mr1;		/* 0x41360 - Performance monitor 0 mask register 1  */
+	char	res42[12];
+	uint	pm1mr0;		/* 0x41370 - Performance monitor 1 mask register 0  */
+	char	res43[12];
+	uint	pm1mr1;		/* 0x41380 - Performance monitor 1 mask register 1  */
+	char	res44[12];
+	uint	pm2mr0;		/* 0x41390 - Performance monitor 2 mask register 0  */
+	char	res45[12];
+	uint	pm2mr1;		/* 0x413A0 - Performance monitor 2 mask register 1  */
+	char	res46[12];
+	uint	pm3mr0;		/* 0x413B0 - Performance monitor 3 mask register 0  */
+	char	res47[12];
+	uint	pm3mr1;		/* 0x413C0 - Performance monitor 3 mask register 1  */
+	char	res48[60];
+	uint	msgr0;		/* 0x41400 - Message Register 0 */
+	char	res49[12];
+	uint	msgr1;		/* 0x41410 - Message Register 1 */
+	char	res50[12];
+	uint	msgr2;		/* 0x41420 - Message Register 2 */
+	char	res51[12];
+	uint	msgr3;		/* 0x41430 - Message Register 3 */
+	char	res52[204];
+	uint	mer;		/* 0x41500 - Message Enable Register */
+	char	res53[12];
+	uint	msr;		/* 0x41510 - Message Status Register */
+	char	res54[60140];
+	uint	eivpr0;		/* 0x50000 - External Interrupt Vector/Priority Register 0 */
+	char	res55[12];
+	uint	eidr0;		/* 0x50010 - External Interrupt Destination Register 0 */
+	char	res56[12];
+	uint	eivpr1;		/* 0x50020 - External Interrupt Vector/Priority Register 1 */
+	char	res57[12];
+	uint	eidr1;		/* 0x50030 - External Interrupt Destination Register 1 */
+	char	res58[12];
+	uint	eivpr2;		/* 0x50040 - External Interrupt Vector/Priority Register 2 */
+	char	res59[12];
+	uint	eidr2;		/* 0x50050 - External Interrupt Destination Register 2 */
+	char	res60[12];
+	uint	eivpr3;		/* 0x50060 - External Interrupt Vector/Priority Register 3 */
+	char	res61[12];
+	uint	eidr3;		/* 0x50070 - External Interrupt Destination Register 3 */
+	char	res62[12];
+	uint	eivpr4;		/* 0x50080 - External Interrupt Vector/Priority Register 4 */
+	char	res63[12];
+	uint	eidr4;		/* 0x50090 - External Interrupt Destination Register 4 */
+	char	res64[12];
+	uint	eivpr5;		/* 0x500a0 - External Interrupt Vector/Priority Register 5 */
+	char	res65[12];
+	uint	eidr5;		/* 0x500b0 - External Interrupt Destination Register 5 */
+	char	res66[12];
+	uint	eivpr6;		/* 0x500c0 - External Interrupt Vector/Priority Register 6 */
+	char	res67[12];
+	uint	eidr6;		/* 0x500d0 - External Interrupt Destination Register 6 */
+	char	res68[12];
+	uint	eivpr7;		/* 0x500e0 - External Interrupt Vector/Priority Register 7 */
+	char	res69[12];
+	uint	eidr7;		/* 0x500f0 - External Interrupt Destination Register 7 */
+	char	res70[12];
+	uint	eivpr8;		/* 0x50100 - External Interrupt Vector/Priority Register 8 */
+	char	res71[12];
+	uint	eidr8;		/* 0x50110 - External Interrupt Destination Register 8 */
+	char	res72[12];
+	uint	eivpr9;		/* 0x50120 - External Interrupt Vector/Priority Register 9 */
+	char	res73[12];
+	uint	eidr9;		/* 0x50130 - External Interrupt Destination Register 9 */
+	char	res74[12];
+	uint	eivpr10;	/* 0x50140 - External Interrupt Vector/Priority Register 10 */
+	char	res75[12];
+	uint	eidr10;		/* 0x50150 - External Interrupt Destination Register 10 */
+	char	res76[12];
+	uint	eivpr11;	/* 0x50160 - External Interrupt Vector/Priority Register 11 */
+	char	res77[12];
+	uint	eidr11;		/* 0x50170 - External Interrupt Destination Register 11 */
+	char	res78[140];
+	uint	iivpr0;		/* 0x50200 - Internal Interrupt Vector/Priority Register 0 */
+	char	res79[12];
+	uint	iidr0;		/* 0x50210 - Internal Interrupt Destination Register 0 */
+	char	res80[12];
+	uint	iivpr1;		/* 0x50220 - Internal Interrupt Vector/Priority Register 1 */
+	char	res81[12];
+	uint	iidr1;		/* 0x50230 - Internal Interrupt Destination Register 1 */
+	char	res82[12];
+	uint	iivpr2;		/* 0x50240 - Internal Interrupt Vector/Priority Register 2 */
+	char	res83[12];
+	uint	iidr2;		/* 0x50250 - Internal Interrupt Destination Register 2 */
+	char	res84[12];
+	uint	iivpr3;		/* 0x50260 - Internal Interrupt Vector/Priority Register 3 */
+	char	res85[12];
+	uint	iidr3;		/* 0x50270 - Internal Interrupt Destination Register 3 */
+	char	res86[12];
+	uint	iivpr4;		/* 0x50280 - Internal Interrupt Vector/Priority Register 4 */
+	char	res87[12];
+	uint	iidr4;		/* 0x50290 - Internal Interrupt Destination Register 4 */
+	char	res88[12];
+	uint	iivpr5;		/* 0x502a0 - Internal Interrupt Vector/Priority Register 5 */
+	char	res89[12];
+	uint	iidr5;		/* 0x502b0 - Internal Interrupt Destination Register 5 */
+	char	res90[12];
+	uint	iivpr6;		/* 0x502c0 - Internal Interrupt Vector/Priority Register 6 */
+	char	res91[12];
+	uint	iidr6;		/* 0x502d0 - Internal Interrupt Destination Register 6 */
+	char	res92[12];
+	uint	iivpr7;		/* 0x502e0 - Internal Interrupt Vector/Priority Register 7 */
+	char	res93[12];
+	uint	iidr7;		/* 0x502f0 - Internal Interrupt Destination Register 7 */
+	char	res94[12];
+	uint	iivpr8;		/* 0x50300 - Internal Interrupt Vector/Priority Register 8 */
+	char	res95[12];
+	uint	iidr8;		/* 0x50310 - Internal Interrupt Destination Register 8 */
+	char	res96[12];
+	uint	iivpr9;		/* 0x50320 - Internal Interrupt Vector/Priority Register 9 */
+	char	res97[12];
+	uint	iidr9;		/* 0x50330 - Internal Interrupt Destination Register 9 */
+	char	res98[12];
+	uint	iivpr10;	/* 0x50340 - Internal Interrupt Vector/Priority Register 10 */
+	char	res99[12];
+	uint	iidr10;		/* 0x50350 - Internal Interrupt Destination Register 10 */
+	char	res100[12];
+	uint	iivpr11;	/* 0x50360 - Internal Interrupt Vector/Priority Register 11 */
+	char	res101[12];
+	uint	iidr11;		/* 0x50370 - Internal Interrupt Destination Register 11 */
+	char	res102[12];
+	uint	iivpr12;	/* 0x50380 - Internal Interrupt Vector/Priority Register 12 */
+	char	res103[12];
+	uint	iidr12;		/* 0x50390 - Internal Interrupt Destination Register 12 */
+	char	res104[12];
+	uint	iivpr13;	/* 0x503a0 - Internal Interrupt Vector/Priority Register 13 */
+	char	res105[12];
+	uint	iidr13;		/* 0x503b0 - Internal Interrupt Destination Register 13 */
+	char	res106[12];
+	uint	iivpr14;	/* 0x503c0 - Internal Interrupt Vector/Priority Register 14 */
+	char	res107[12];
+	uint	iidr14;		/* 0x503d0 - Internal Interrupt Destination Register 14 */
+	char	res108[12];
+	uint	iivpr15;	/* 0x503e0 - Internal Interrupt Vector/Priority Register 15 */
+	char	res109[12];
+	uint	iidr15;		/* 0x503f0 - Internal Interrupt Destination Register 15 */
+	char	res110[12];
+	uint	iivpr16;	/* 0x50400 - Internal Interrupt Vector/Priority Register 16 */
+	char	res111[12];
+	uint	iidr16;		/* 0x50410 - Internal Interrupt Destination Register 16 */
+	char	res112[12];
+	uint	iivpr17;	/* 0x50420 - Internal Interrupt Vector/Priority Register 17 */
+	char	res113[12];
+	uint	iidr17;		/* 0x50430 - Internal Interrupt Destination Register 17 */
+	char	res114[12];
+	uint	iivpr18;	/* 0x50440 - Internal Interrupt Vector/Priority Register 18 */
+	char	res115[12];
+	uint	iidr18;		/* 0x50450 - Internal Interrupt Destination Register 18 */
+	char	res116[12];
+	uint	iivpr19;	/* 0x50460 - Internal Interrupt Vector/Priority Register 19 */
+	char	res117[12];
+	uint	iidr19;		/* 0x50470 - Internal Interrupt Destination Register 19 */
+	char	res118[12];
+	uint	iivpr20;	/* 0x50480 - Internal Interrupt Vector/Priority Register 20 */
+	char	res119[12];
+	uint	iidr20;		/* 0x50490 - Internal Interrupt Destination Register 20 */
+	char	res120[12];
+	uint	iivpr21;	/* 0x504a0 - Internal Interrupt Vector/Priority Register 21 */
+	char	res121[12];
+	uint	iidr21;		/* 0x504b0 - Internal Interrupt Destination Register 21 */
+	char	res122[12];
+	uint	iivpr22;	/* 0x504c0 - Internal Interrupt Vector/Priority Register 22 */
+	char	res123[12];
+	uint	iidr22;		/* 0x504d0 - Internal Interrupt Destination Register 22 */
+	char	res124[12];
+	uint	iivpr23;	/* 0x504e0 - Internal Interrupt Vector/Priority Register 23 */
+	char	res125[12];
+	uint	iidr23;		/* 0x504f0 - Internal Interrupt Destination Register 23 */
+	char	res126[12];
+	uint	iivpr24;	/* 0x50500 - Internal Interrupt Vector/Priority Register 24 */
+	char	res127[12];
+	uint	iidr24;		/* 0x50510 - Internal Interrupt Destination Register 24 */
+	char	res128[12];
+	uint	iivpr25;	/* 0x50520 - Internal Interrupt Vector/Priority Register 25 */
+	char	res129[12];
+	uint	iidr25;		/* 0x50530 - Internal Interrupt Destination Register 25 */
+	char	res130[12];
+	uint	iivpr26;	/* 0x50540 - Internal Interrupt Vector/Priority Register 26 */
+	char	res131[12];
+	uint	iidr26;		/* 0x50550 - Internal Interrupt Destination Register 26 */
+	char	res132[12];
+	uint	iivpr27;	/* 0x50560 - Internal Interrupt Vector/Priority Register 27 */
+	char	res133[12];
+	uint	iidr27;		/* 0x50570 - Internal Interrupt Destination Register 27 */
+	char	res134[12];
+	uint	iivpr28;	/* 0x50580 - Internal Interrupt Vector/Priority Register 28 */
+	char	res135[12];
+	uint	iidr28;		/* 0x50590 - Internal Interrupt Destination Register 28 */
+	char	res136[12];
+	uint	iivpr29;	/* 0x505a0 - Internal Interrupt Vector/Priority Register 29 */
+	char	res137[12];
+	uint	iidr29;		/* 0x505b0 - Internal Interrupt Destination Register 29 */
+	char	res138[12];
+	uint	iivpr30;	/* 0x505c0 - Internal Interrupt Vector/Priority Register 30 */
+	char	res139[12];
+	uint	iidr30;		/* 0x505d0 - Internal Interrupt Destination Register 30 */
+	char	res140[12];
+	uint	iivpr31;	/* 0x505e0 - Internal Interrupt Vector/Priority Register 31 */
+	char	res141[12];
+	uint	iidr31;		/* 0x505f0 - Internal Interrupt Destination Register 31 */
+	char	res142[4108];
+	uint	mivpr0;		/* 0x51600 - Messaging Interrupt Vector/Priority Register 0 */
+	char	res143[12];
+	uint	midr0;		/* 0x51610 - Messaging Interrupt Destination Register 0 */
+	char	res144[12];
+	uint	mivpr1;		/* 0x51620 - Messaging Interrupt Vector/Priority Register 1 */
+	char	res145[12];
+	uint	midr1;		/* 0x51630 - Messaging Interrupt Destination Register 1 */
+	char	res146[12];
+	uint	mivpr2;		/* 0x51640 - Messaging Interrupt Vector/Priority Register 2 */
+	char	res147[12];
+	uint	midr2;		/* 0x51650 - Messaging Interrupt Destination Register 2 */
+	char	res148[12];
+	uint	mivpr3;		/* 0x51660 - Messaging Interrupt Vector/Priority Register 3 */
+	char	res149[12];
+	uint	midr3;		/* 0x51670 - Messaging Interrupt Destination Register 3 */
+	char	res150[59852];
+	uint	ipi0dr0;	/* 0x60040 - Processor 0 Interprocessor Interrupt Dispatch Register 0 */
+	char	res151[12];
+	uint	ipi0dr1;	/* 0x60050 - Processor 0 Interprocessor Interrupt Dispatch Register 1 */
+	char	res152[12];
+	uint	ipi0dr2;	/* 0x60060 - Processor 0 Interprocessor Interrupt Dispatch Register 2 */
+	char	res153[12];
+	uint	ipi0dr3;	/* 0x60070 - Processor 0 Interprocessor Interrupt Dispatch Register 3 */
+	char	res154[12];
+	uint	ctpr0;		/* 0x60080 - Current Task Priority Register for Processor 0 */
+	char	res155[12];
+	uint	whoami0;	/* 0x60090 - Who Am I Register for Processor 0 */
+	char	res156[12];
+	uint	iack0;		/* 0x600a0 - Interrupt Acknowledge Register for Processor 0 */
+	char	res157[12];
+	uint	eoi0;		/* 0x600b0 - End Of Interrupt Register for Processor 0 */
+	char	res158[3916];
+} ccsr_pic_t;
+
+/* RapidIO Registers(0xc_0000-0xe_0000) */
+
+typedef struct ccsr_rio {
+	uint	didcar;		/* 0xc0000 - Device Identity Capability Register */
+	uint	dicar;		/* 0xc0004 - Device Information Capability Register */
+	uint	aidcar;		/* 0xc0008 - Assembly Identity Capability Register */
+	uint	aicar;		/* 0xc000c - Assembly Information Capability Register */
+	uint	pefcar;		/* 0xc0010 - Processing Element Features Capability Register */
+	uint	spicar;		/* 0xc0014 - Switch Port Information Capability Register */
+	uint	socar;		/* 0xc0018 - Source Operations Capability Register */
+	uint	docar;		/* 0xc001c - Destination Operations Capability Register */
+	char	res1[32];
+	uint	msr;		/* 0xc0040 - Mailbox Command And Status Register */
+	uint	pwdcsr;		/* 0xc0044 - Port-Write and Doorbell Command And Status Register */
+	char	res2[4];
+	uint	pellccsr;	/* 0xc004c - Processing Element Logic Layer Control Command and Status Register */
+	char	res3[12];
+	uint	lcsbacsr;	/* 0xc005c - Local Configuration Space Base Address Command and Status Register */
+	uint	bdidcsr;	/* 0xc0060 - Base Device ID Command and Status Register */
+	char	res4[4];
+	uint	hbdidlcsr;	/* 0xc0068 - Host Base Device ID Lock Command and Status Register */
+	uint	ctcsr;		/* 0xc006c - Component Tag Command and Status Register */
+	char	res5[144];
+	uint	pmbh0csr;	/* 0xc0100 - 8/16 LP-LVDS Port Maintenance Block Header 0 Command and Status Register */
+	char	res6[28];
+	uint	pltoccsr;	/* 0xc0120 - Port Link Time-out Control Command and Status Register */
+	uint	prtoccsr;	/* 0xc0124 - Port Response Time-out Control Command and Status Register */
+	char	res7[20];
+	uint	pgccsr;		/* 0xc013c - Port General Command and Status Register */
+	uint	plmreqcsr;	/* 0xc0140 - Port Link Maintenance Request Command and Status Register */
+	uint	plmrespcsr;	/* 0xc0144 - Port Link Maintenance Response Command and Status Register */
+	uint	plascsr;	/* 0xc0148 - Port Local Ackid Status Command and Status Register */
+	char	res8[12];
+	uint	pescsr;		/* 0xc0158 - Port Error and Status Command and Status Register */
+	uint	pccsr;		/* 0xc015c - Port Control Command and Status Register */
+	char	res9[1184];
+	uint	erbh;		/* 0xc0600 - Error Reporting Block Header Register */
+	char	res10[4];
+	uint	ltledcsr;	/* 0xc0608 - Logical/Transport layer error detect status register */
+	uint	ltleecsr;	/* 0xc060c - Logical/Transport layer error enable register */
+	char	res11[4];
+	uint	ltlaccsr;	/* 0xc0614 - Logical/Transport layer addresss capture register */
+	uint	ltldidccsr;	/* 0xc0618 - Logical/Transport layer device ID capture register */
+	uint	ltlcccsr;	/* 0xc061c - Logical/Transport layer control capture register */
+	char	res12[32];
+	uint	edcsr;	        /* 0xc0640 - Port 0 error detect status register */
+	uint	erecsr;	        /* 0xc0644 - Port 0 error rate enable status register */
+	uint	ecacsr;	        /* 0xc0648 - Port 0 error capture attributes register */
+	uint	pcseccsr0;	/* 0xc064c - Port 0 packet/control symbol error capture register 0 */
+	uint	peccsr1;	/* 0xc0650 - Port 0 error capture command and status register 1 */
+	uint	peccsr2;	/* 0xc0654 - Port 0 error capture command and status register 2 */
+	uint	peccsr3;	/* 0xc0658 - Port 0 error capture command and status register 3 */
+	char	res13[12];
+	uint	ercsr;	        /* 0xc0668 - Port 0 error rate command and status register */
+	uint	ertcsr;	        /* 0xc066C - Port 0 error rate threshold status register*/
+	char	res14[63892];
+	uint	llcr;		/* 0xd0004 - Logical Layer Configuration Register */
+	char	res15[12];
+	uint	epwisr;		/* 0xd0010 - Error / Port-Write Interrupt Status Register */
+	char	res16[12];
+	uint	lretcr;		/* 0xd0020 - Logical Retry Error Threshold Configuration Register */
+	char	res17[92];
+	uint	pretcr;		/* 0xd0080 - Physical Retry Erorr Threshold Configuration Register */
+	char	res18[124];
+	uint	adidcsr;	/* 0xd0100 - Port 0 Alt. Device ID Command and Status Register */
+	char	res19[28];
+	uint	ptaacr;	        /* 0xd0120 - Port 0 Pass-Through/Accept-All Configuration Register */
+	char	res20[12];
+	uint	iecsr;	        /* 0xd0130 - Port 0 Implementation Error Status Register */
+	char	res21[12];
+	uint	pcr;		/* 0xd0140 - Port 0 Phsyical Configuration RegisterRegister */
+	char	res22[20];
+	uint	slcsr;	        /* 0xd0158 - Port 0 Serial Link Command and Status Register */
+	char	res23[4];
+	uint	sleir;	        /* 0xd0160 - Port 0 Serial Link Error Injection Register */
+	char	res24[2716];
+	uint	rowtar0;	/* 0xd0c00 - RapidIO Outbound Window Translation Address Register 0 */
+	uint	rowtear0;	/* 0xd0c04 - RapidIO Outbound Window Translation Ext. Address Register 0 */
+	char	res25[8];
+	uint	rowar0;		/* 0xd0c10 - RapidIO Outbound Attributes Register 0 */
+	char	res26[12];
+	uint	rowtar1;	/* 0xd0c20 - RapidIO Outbound Window Translation Address Register 1 */
+	uint	rowtear1;	/* 0xd0c24 - RapidIO Outbound Window Translation Ext. Address Register 1 */
+	uint	rowbar1;	/* 0xd0c28 - RapidIO Outbound Window Base Address Register 1 */
+	char	res27[4];
+	uint	rowar1;		/* 0xd0c30 - RapidIO Outbound Attributes Register 1 */
+	uint	rows1r1;	/* 0xd0c34 - RapidIO Outbound Window Segment 1 Register 1 */
+	uint	rows2r1;	/* 0xd0c38 - RapidIO Outbound Window Segment 2 Register 1 */
+	uint	rows3r1;	/* 0xd0c3c - RapidIO Outbound Window Segment 3 Register 1 */
+	uint	rowtar2;	/* 0xd0c40 - RapidIO Outbound Window Translation Address Register 2 */
+	uint	rowtear2;	/* 0xd0c44 - RapidIO Outbound Window Translation Ext. Address Register 2 */
+	uint	rowbar2;	/* 0xd0c48 - RapidIO Outbound Window Base Address Register 2 */
+	char	res28[4];
+	uint	rowar2;		/* 0xd0c50 - RapidIO Outbound Attributes Register 2 */
+	uint	rows1r2;	/* 0xd0c54 - RapidIO Outbound Window Segment 1 Register 2 */
+	uint	rows2r2;	/* 0xd0c58 - RapidIO Outbound Window Segment 2 Register 2 */
+	uint	rows3r2;	/* 0xd0c5c - RapidIO Outbound Window Segment 3 Register 2 */
+	uint	rowtar3;	/* 0xd0c60 - RapidIO Outbound Window Translation Address Register 3 */
+	uint	rowtear3;	/* 0xd0c64 - RapidIO Outbound Window Translation Ext. Address Register 3 */
+	uint	rowbar3;	/* 0xd0c68 - RapidIO Outbound Window Base Address Register 3 */
+	char	res29[4];
+	uint	rowar3;		/* 0xd0c70 - RapidIO Outbound Attributes Register 3 */
+	uint	rows1r3;	/* 0xd0c74 - RapidIO Outbound Window Segment 1 Register 3 */
+	uint	rows2r3;	/* 0xd0c78 - RapidIO Outbound Window Segment 2 Register 3 */
+	uint	rows3r3;	/* 0xd0c7c - RapidIO Outbound Window Segment 3 Register 3 */
+	uint	rowtar4;	/* 0xd0c80 - RapidIO Outbound Window Translation Address Register 4 */
+	uint	rowtear4;	/* 0xd0c84 - RapidIO Outbound Window Translation Ext. Address Register 4 */
+	uint	rowbar4;	/* 0xd0c88 - RapidIO Outbound Window Base Address Register 4 */
+	char	res30[4];
+	uint	rowar4;		/* 0xd0c90 - RapidIO Outbound Attributes Register 4 */
+	uint	rows1r4;	/* 0xd0c94 - RapidIO Outbound Window Segment 1 Register 4 */
+	uint	rows2r4;	/* 0xd0c98 - RapidIO Outbound Window Segment 2 Register 4 */
+	uint	rows3r4;	/* 0xd0c9c - RapidIO Outbound Window Segment 3 Register 4 */
+	uint	rowtar5;	/* 0xd0ca0 - RapidIO Outbound Window Translation Address Register 5 */
+	uint	rowtear5;	/* 0xd0ca4 - RapidIO Outbound Window Translation Ext. Address Register 5 */
+	uint	rowbar5;	/* 0xd0ca8 - RapidIO Outbound Window Base Address Register 5 */
+	char	res31[4];
+	uint	rowar5;		/* 0xd0cb0 - RapidIO Outbound Attributes Register 5 */
+	uint	rows1r5;	/* 0xd0cb4 - RapidIO Outbound Window Segment 1 Register 5 */
+	uint	rows2r5;	/* 0xd0cb8 - RapidIO Outbound Window Segment 2 Register 5 */
+	uint	rows3r5;	/* 0xd0cbc - RapidIO Outbound Window Segment 3 Register 5 */
+	uint	rowtar6;	/* 0xd0cc0 - RapidIO Outbound Window Translation Address Register 6 */
+	uint	rowtear6;	/* 0xd0cc4 - RapidIO Outbound Window Translation Ext. Address Register 6 */
+	uint	rowbar6;	/* 0xd0cc8 - RapidIO Outbound Window Base Address Register 6 */
+	char	res32[4];
+	uint	rowar6;		/* 0xd0cd0 - RapidIO Outbound Attributes Register 6 */
+	uint	rows1r6;	/* 0xd0cd4 - RapidIO Outbound Window Segment 1 Register 6 */
+	uint	rows2r6;	/* 0xd0cd8 - RapidIO Outbound Window Segment 2 Register 6 */
+	uint	rows3r6;	/* 0xd0cdc - RapidIO Outbound Window Segment 3 Register 6 */
+	uint	rowtar7;	/* 0xd0ce0 - RapidIO Outbound Window Translation Address Register 7 */
+	uint	rowtear7;	/* 0xd0ce4 - RapidIO Outbound Window Translation Ext. Address Register 7 */
+	uint	rowbar7;	/* 0xd0ce8 - RapidIO Outbound Window Base Address Register 7 */
+	char	res33[4];
+	uint	rowar7;		/* 0xd0cf0 - RapidIO Outbound Attributes Register 7 */
+	uint	rows1r7;	/* 0xd0cf4 - RapidIO Outbound Window Segment 1 Register 7 */
+	uint	rows2r7;	/* 0xd0cf8 - RapidIO Outbound Window Segment 2 Register 7 */
+	uint	rows3r7;	/* 0xd0cfc - RapidIO Outbound Window Segment 3 Register 7 */
+	uint	rowtar8;	/* 0xd0d00 - RapidIO Outbound Window Translation Address Register 8 */
+	uint	rowtear8;	/* 0xd0d04 - RapidIO Outbound Window Translation Ext. Address Register 8 */
+	uint	rowbar8;	/* 0xd0d08 - RapidIO Outbound Window Base Address Register 8 */
+	char	res34[4];
+	uint	rowar8;		/* 0xd0d10 - RapidIO Outbound Attributes Register 8 */
+	uint	rows1r8;	/* 0xd0d14 - RapidIO Outbound Window Segment 1 Register 8 */
+	uint	rows2r8;	/* 0xd0d18 - RapidIO Outbound Window Segment 2 Register 8 */
+	uint	rows3r8;	/* 0xd0d1c - RapidIO Outbound Window Segment 3 Register 8 */
+	char	res35[64];
+	uint	riwtar4;	/* 0xd0d60 - RapidIO Inbound Window Translation Address Register 4 */
+	uint	riwbar4;	/* 0xd0d68 - RapidIO Inbound Window Base Address Register 4 */
+	char	res36[4];
+	uint	riwar4;		/* 0xd0d70 - RapidIO Inbound Attributes Register 4 */
+	char	res37[12];
+	uint	riwtar3;	/* 0xd0d80 - RapidIO Inbound Window Translation Address Register 3 */
+	char	res38[4];
+	uint	riwbar3;	/* 0xd0d88 - RapidIO Inbound Window Base Address Register 3 */
+	char	res39[4];
+	uint	riwar3;		/* 0xd0d90 - RapidIO Inbound Attributes Register 3 */
+	char	res40[12];
+	uint	riwtar2;	/* 0xd0da0 - RapidIO Inbound Window Translation Address Register 2 */
+	char	res41[4];
+	uint	riwbar2;	/* 0xd0da8 - RapidIO Inbound Window Base Address Register 2 */
+	char	res42[4];
+	uint	riwar2;		/* 0xd0db0 - RapidIO Inbound Attributes Register 2 */
+	char	res43[12];
+	uint	riwtar1;	/* 0xd0dc0 - RapidIO Inbound Window Translation Address Register 1 */
+	char	res44[4];
+	uint	riwbar1;	/* 0xd0dc8 - RapidIO Inbound Window Base Address Register 1 */
+	char	res45[4];
+	uint	riwar1;		/* 0xd0dd0 - RapidIO Inbound Attributes Register 1 */
+	char	res46[12];
+	uint	riwtar0;	/* 0xd0de0 - RapidIO Inbound Window Translation Address Register 0 */
+	char	res47[12];
+	uint	riwar0;		/* 0xd0df0 - RapidIO Inbound Attributes Register 0 */
+	char	res48[12];
+	uint	pnfedr;		/* 0xd0e00 - Port Notification/Fatal Error Detect Register */
+	uint	pnfedir;	/* 0xd0e04 - Port Notification/Fatal Error Detect Register */
+	uint	pnfeier;	/* 0xd0e08 - Port Notification/Fatal Error Interrupt Enable Register */
+	uint	pecr;		/* 0xd0e0c - Port Error Control Register */
+	uint	pepcsr0;	/* 0xd0e10 - Port Error Packet/Control Symbol Register 0 */
+	uint	pepr1;		/* 0xd0e14 - Port Error Packet Register 1 */
+	uint	pepr2;		/* 0xd0e18 - Port Error Packet Register 2 */
+	char	res49[4];
+	uint	predr;		/* 0xd0e20 - Port Recoverable Error Detect Register */
+	char	res50[4];
+	uint	pertr;		/* 0xd0e28 - Port Error Recovery Threshold Register */
+	uint	prtr;		/* 0xd0e2c - Port Retry Threshold Register */
+	char	res51[8656];
+	uint	omr;		/* 0xd3000 - Outbound Mode Register */
+	uint	osr;		/* 0xd3004 - Outbound Status Register */
+	uint	eodqtpar;	/* 0xd3008 - Extended Outbound Descriptor Queue Tail Pointer Address Register */
+	uint	odqtpar;	/* 0xd300c - Outbound Descriptor Queue Tail Pointer Address Register */
+	uint	eosar;		/* 0xd3010 - Extended Outbound Unit Source Address Register */
+	uint	osar;		/* 0xd3014 - Outbound Unit Source Address Register */
+	uint	odpr;		/* 0xd3018 - Outbound Destination Port Register */
+	uint	odatr;		/* 0xd301c - Outbound Destination Attributes Register */
+	uint	odcr;		/* 0xd3020 - Outbound Doubleword Count Register */
+	uint	eodqhpar;	/* 0xd3024 - Extended Outbound Descriptor Queue Head Pointer Address Register */
+	uint	odqhpar;	/* 0xd3028 - Outbound Descriptor Queue Head Pointer Address Register */
+	uint	oretr;	        /* 0xd302C - Outbound Retry Error Threshold Register */
+	uint	omgr;	        /* 0xd3030 - Outbound Multicast Group Register */
+	uint	omlr;	        /* 0xd3034 - Outbound Multicast List Register */
+	char	res52[40];
+	uint	imr;		/* 0xd3060 - Outbound Mode Register */
+	uint	isr;		/* 0xd3064 - Inbound Status Register */
+	uint	eidqtpar;	/* 0xd3068 - Extended Inbound Descriptor Queue Tail Pointer Address Register */
+	uint	idqtpar;	/* 0xd306c - Inbound Descriptor Queue Tail Pointer Address Register */
+	uint	eifqhpar;	/* 0xd3070 - Extended Inbound Frame Queue Head Pointer Address Register */
+	uint	ifqhpar;	/* 0xd3074 - Inbound Frame Queue Head Pointer Address Register */
+	uint	imirir;	        /* 0xd3078 - Inbound Maximum Interrutp Report Interval Register */
+	char	res53[900];
+	uint	oddmr;		/* 0xd3400 - Outbound Doorbell Mode Register */
+	uint	oddsr;		/* 0xd3404 - Outbound Doorbell Status Register */
+	char	res54[16];
+	uint	oddpr;		/* 0xd3418 - Outbound Doorbell Destination Port Register */
+	uint	oddatr;		/* 0xd341C - Outbound Doorbell Destination Attributes Register */
+	char	res55[12];
+	uint	oddretr;	/* 0xd342C - Outbound Doorbell Retry Threshold Configuration Register */
+	char	res56[48];
+	uint	idmr;		/* 0xd3460 - Inbound Doorbell Mode Register */
+	uint	idsr;		/* 0xd3464 - Inbound Doorbell Status Register */
+	uint	iedqtpar;	/* 0xd3468 - Extended Inbound Doorbell Queue Tail Pointer Address Register */
+	uint	iqtpar;	        /* 0xd346c - Inbound Doorbell Queue Tail Pointer Address Register */
+	uint	iedqhpar;	/* 0xd3470 - Extended Inbound Doorbell Queue Head Pointer Address Register */
+	uint	idqhpar;	/* 0xd3474 - Inbound Doorbell Queue Head Pointer Address Register */
+	uint	idmirir;	/* 0xd3478 - Inbound Doorbell Max Interrupt Report Interval Register */
+	char	res57[100];
+	uint	pwmr;		/* 0xd34e0 - Port-Write Mode Register */
+	uint	pwsr;		/* 0xd34e4 - Port-Write Status Register */
+	uint	epwqbar;	/* 0xd34e8 - Extended Port-Write Queue Base Address Register */
+	uint	pwqbar;		/* 0xd34ec - Port-Write Queue Base Address Register */
+	char	res58[51984];
+} ccsr_rio_t;
+
+/* Global Utilities Register Block(0xe_0000-0xf_ffff) */
+typedef struct ccsr_gur {
+	uint	porpllsr;	/* 0xe0000 - POR PLL ratio status register */
+	uint	porbmsr;	/* 0xe0004 - POR boot mode status register */
+	uint	porimpscr;	/* 0xe0008 - POR I/O impedance status and control register */
+	uint	pordevsr;	/* 0xe000c - POR I/O device status regsiter */
+	uint	pordbgmsr;	/* 0xe0010 - POR debug mode status register */
+	char	res1[12];
+	uint	gpporcr;	/* 0xe0020 - General-purpose POR configuration register */
+	char	res2[12];
+	uint	gpiocr;		/* 0xe0030 - GPIO control register */
+	char	res3[12];
+	uint	gpoutdr;	/* 0xe0040 - General-purpose output data register */
+	char	res4[12];
+	uint	gpindr;		/* 0xe0050 - General-purpose input data register */
+	char	res5[12];
+	uint	pmuxcr;		/* 0xe0060 - Alternate function signal multiplex control */
+	char	res6[12];
+	uint	devdisr;	/* 0xe0070 - Device disable control */
+	char	res7[12];
+	uint	powmgtcsr;	/* 0xe0080 - Power management status and control register */
+	char	res8[12];
+	uint	mcpsumr;	/* 0xe0090 - Machine check summary register */
+	uint	rstrscr;	/* 0xe0094 - Reset request status and control register */
+	char	res9[8];
+	uint	pvr;		/* 0xe00a0 - Processor version register */
+	uint	svr;		/* 0xe00a4 - System version register */
+	char	res10a[8];
+	uint	rstcr;		/* 0xe00b0 - Reset control register */
+	char	res10b[1868];
+	uint	clkdvdr;	/* 0xe0800 - Clock Divide register */
+	char	res10c[796];
+	uint	ddr1clkdr;	/* 0xe0b20 - DDRC1 Clock Disable register */
+	char	res10d[4];
+	uint	ddr2clkdr;	/* 0xe0b28 - DDRC2 Clock Disable register */
+	char	res10e[724];
+	uint	clkocr;		/* 0xe0e00 - Clock out select register */
+	char	res11[12];
+	uint	ddrdllcr;	/* 0xe0e10 - DDR DLL control register */
+	char	res12[12];
+	uint	lbcdllcr;	/* 0xe0e20 - LBC DLL control register */
+	char	res13a[224];
+	uint	srds1cr0;	/* 0xe0f04 - SerDes1 control register 0 */
+	char	res13b[4];
+	uint	srds1cr1;	/* 0xe0f08 - SerDes1 control register 1 */
+	char	res14[24];
+	uint	ddrioovcr;	/* 0xe0f24 - DDR IO Overdrive Control register */
+	char	res15a[24];
+	uint	srds2cr0;	/* 0xe0f40 - SerDes2 control register 0 */
+	uint	srds2cr1;	/* 0xe0f44 - SerDes2 control register 1 */
+	char	res16[184];
+} ccsr_gur_t;
+
+#define MPC8610_PORBMSR_HA      0x00070000
+#define MPC8610_PORBMSR_HA_SHIFT	16
+#define MPC8641_PORBMSR_HA      0x00060000
+#define MPC8641_PORBMSR_HA_SHIFT	17
+#define MPC8610_PORDEVSR_IO_SEL		0x00380000
+#define MPC8610_PORDEVSR_IO_SEL_SHIFT		19
+#define MPC8641_PORDEVSR_IO_SEL		0x000F0000
+#define MPC8641_PORDEVSR_IO_SEL_SHIFT		16
+#define MPC86xx_PORDEVSR_CORE1TE	0x00000080 /* ASMP (Core1 addr trans) */
+#define MPC86xx_DEVDISR_PCIEX1	0x80000000
+#define MPC86xx_DEVDISR_PCIEX2	0x40000000
+#define MPC86xx_DEVDISR_PCI1	0x80000000
+#define MPC86xx_DEVDISR_PCIE1	0x40000000
+#define MPC86xx_DEVDISR_PCIE2	0x20000000
+#define MPC86xx_DEVDISR_CPU0	0x00008000
+#define MPC86xx_DEVDISR_CPU1	0x00004000
+#define MPC86xx_RSTCR_HRST_REQ	0x00000002
+
+/*
+ * Watchdog register block(0xe_4000-0xe_4fff)
+ */
+typedef struct ccsr_wdt {
+	uint	res0;
+	uint	swcrr; /* System watchdog control register */
+	uint	swcnr; /* System watchdog count register */
+	char	res1[2];
+	ushort	swsrr; /* System watchdog service register */
+	char	res2[4080];
+} ccsr_wdt_t;
+
+typedef struct immap {
+	ccsr_local_mcm_t	im_local_mcm;
+	ccsr_ddr_t		im_ddr1;
+	ccsr_i2c_t		im_i2c;
+	ccsr_duart_t		im_duart;
+	ccsr_lbc_t		im_lbc;
+	ccsr_ddr_t		im_ddr2;
+	char                    res1[4096];
+	ccsr_pex_t		im_pex1;
+	ccsr_pex_t		im_pex2;
+	ccsr_ht_t               im_ht;
+	char                    res2[90112];
+	ccsr_dma_t		im_dma;
+	char                    res3[8192];
+	ccsr_tsec_t		im_tsec1;
+	ccsr_tsec_t		im_tsec2;
+	ccsr_tsec_t             im_tsec3;
+	ccsr_tsec_t             im_tsec4;
+	char                    res4[98304];
+	ccsr_pic_t		im_pic;
+	char                    res5[389120];
+	ccsr_rio_t		im_rio;
+	ccsr_gur_t		im_gur;
+	char			res6[12288];
+	ccsr_wdt_t		im_wdt;
+} immap_t;
+
+extern immap_t  *immr;
+
+#define CONFIG_SYS_MPC86xx_DDR_OFFSET	(0x2000)
+#define CONFIG_SYS_MPC86xx_DDR_ADDR	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC86xx_DDR_OFFSET)
+#define CONFIG_SYS_MPC86xx_DDR2_OFFSET	(0x6000)
+#define CONFIG_SYS_MPC86xx_DDR2_ADDR	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC86xx_DDR2_OFFSET)
+#define CONFIG_SYS_MPC86xx_DMA_OFFSET	(0x21000)
+#define CONFIG_SYS_MPC86xx_DMA_ADDR	(CONFIG_SYS_IMMR + CONFIG_SYS_MPC86xx_DMA_OFFSET)
+
+#define CONFIG_SYS_TSEC1_OFFSET		0x24000
+#define CONFIG_SYS_MDIO1_OFFSET		0x24000
+
+#define TSEC_BASE_ADDR		(CONFIG_SYS_IMMR + CONFIG_SYS_TSEC1_OFFSET)
+#define MDIO_BASE_ADDR		(CONFIG_SYS_IMMR + CONFIG_SYS_MDIO1_OFFSET)
+
+#endif /*__IMMAP_86xx__*/
diff --git a/arch/powerpc/include/asm/immap_qe.h b/arch/powerpc/include/asm/immap_qe.h
new file mode 100644
index 0000000..531cfc8
--- /dev/null
+++ b/arch/powerpc/include/asm/immap_qe.h
@@ -0,0 +1,621 @@
+/*
+ * QUICC Engine (QE) Internal Memory Map.
+ * The Internal Memory Map for devices with QE on them. This
+ * is the superset of all QE devices (8360, etc.).
+ *
+ * Copyright (c) 2006-2009 Freescale Semiconductor, Inc.
+ * Author: Shlomi Gridih <gridish@freescale.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.
+ */
+
+#ifndef __IMMAP_QE_H__
+#define __IMMAP_QE_H__
+
+/* QE I-RAM
+*/
+typedef struct qe_iram {
+	u32 iadd;		/* I-RAM Address Register */
+	u32 idata;		/* I-RAM Data Register    */
+	u8 res0[0x4];
+	u32 iready;
+	u8 res1[0x70];
+} __attribute__ ((packed)) qe_iram_t;
+
+/* QE Interrupt Controller
+*/
+typedef struct qe_ic {
+	u32 qicr;
+	u32 qivec;
+	u32 qripnr;
+	u32 qipnr;
+	u32 qipxcc;
+	u32 qipycc;
+	u32 qipwcc;
+	u32 qipzcc;
+	u32 qimr;
+	u32 qrimr;
+	u32 qicnr;
+	u8 res0[0x4];
+	u32 qiprta;
+	u32 qiprtb;
+	u8 res1[0x4];
+	u32 qricr;
+	u8 res2[0x20];
+	u32 qhivec;
+	u8 res3[0x1C];
+} __attribute__ ((packed)) qe_ic_t;
+
+/* Communications Processor
+*/
+typedef struct cp_qe {
+	u32 cecr;		/* QE command register */
+	u32 ceccr;		/* QE controller configuration register */
+	u32 cecdr;		/* QE command data register */
+	u8 res0[0xA];
+	u16 ceter;		/* QE timer event register */
+	u8 res1[0x2];
+	u16 cetmr;		/* QE timers mask register */
+	u32 cetscr;		/* QE time-stamp timer control register */
+	u32 cetsr1;		/* QE time-stamp register 1 */
+	u32 cetsr2;		/* QE time-stamp register 2 */
+	u8 res2[0x8];
+	u32 cevter;		/* QE virtual tasks event register */
+	u32 cevtmr;		/* QE virtual tasks mask register */
+	u16 cercr;		/* QE RAM control register */
+	u8 res3[0x2];
+	u8 res4[0x24];
+	u16 ceexe1;		/* QE external request 1 event register */
+	u8 res5[0x2];
+	u16 ceexm1;		/* QE external request 1 mask register */
+	u8 res6[0x2];
+	u16 ceexe2;		/* QE external request 2 event register */
+	u8 res7[0x2];
+	u16 ceexm2;		/* QE external request 2 mask register */
+	u8 res8[0x2];
+	u16 ceexe3;		/* QE external request 3 event register */
+	u8 res9[0x2];
+	u16 ceexm3;		/* QE external request 3 mask register */
+	u8 res10[0x2];
+	u16 ceexe4;		/* QE external request 4 event register */
+	u8 res11[0x2];
+	u16 ceexm4;		/* QE external request 4 mask register */
+	u8 res12[0x2];
+	u8 res13[0x280];
+} __attribute__ ((packed)) cp_qe_t;
+
+/* QE Multiplexer
+*/
+typedef struct qe_mux {
+	u32 cmxgcr;		/* CMX general clock route register    */
+	u32 cmxsi1cr_l;		/* CMX SI1 clock route low register    */
+	u32 cmxsi1cr_h;		/* CMX SI1 clock route high register   */
+	u32 cmxsi1syr;		/* CMX SI1 SYNC route register         */
+	u32 cmxucr1;		/* CMX UCC1, UCC3 clock route register */
+	u32 cmxucr2;		/* CMX UCC5, UCC7 clock route register */
+	u32 cmxucr3;		/* CMX UCC2, UCC4 clock route register */
+	u32 cmxucr4;		/* CMX UCC6, UCC8 clock route register */
+	u32 cmxupcr;		/* CMX UPC clock route register        */
+	u8 res0[0x1C];
+} __attribute__ ((packed)) qe_mux_t;
+
+/* QE Timers
+*/
+typedef struct qe_timers {
+	u8 gtcfr1;		/* Timer 1 2 global configuration register */
+	u8 res0[0x3];
+	u8 gtcfr2;		/* Timer 3 4 global configuration register */
+	u8 res1[0xB];
+	u16 gtmdr1;		/* Timer 1 mode register */
+	u16 gtmdr2;		/* Timer 2 mode register */
+	u16 gtrfr1;		/* Timer 1 reference register */
+	u16 gtrfr2;		/* Timer 2 reference register */
+	u16 gtcpr1;		/* Timer 1 capture register */
+	u16 gtcpr2;		/* Timer 2 capture register */
+	u16 gtcnr1;		/* Timer 1 counter */
+	u16 gtcnr2;		/* Timer 2 counter */
+	u16 gtmdr3;		/* Timer 3 mode register */
+	u16 gtmdr4;		/* Timer 4 mode register */
+	u16 gtrfr3;		/* Timer 3 reference register */
+	u16 gtrfr4;		/* Timer 4 reference register */
+	u16 gtcpr3;		/* Timer 3 capture register */
+	u16 gtcpr4;		/* Timer 4 capture register */
+	u16 gtcnr3;		/* Timer 3 counter */
+	u16 gtcnr4;		/* Timer 4 counter */
+	u16 gtevr1;		/* Timer 1 event register */
+	u16 gtevr2;		/* Timer 2 event register */
+	u16 gtevr3;		/* Timer 3 event register */
+	u16 gtevr4;		/* Timer 4 event register */
+	u16 gtps;		/* Timer 1 prescale register */
+	u8 res2[0x46];
+} __attribute__ ((packed)) qe_timers_t;
+
+/* BRG
+*/
+typedef struct qe_brg {
+	u32 brgc1;		/* BRG1 configuration register  */
+	u32 brgc2;		/* BRG2 configuration register  */
+	u32 brgc3;		/* BRG3 configuration register  */
+	u32 brgc4;		/* BRG4 configuration register  */
+	u32 brgc5;		/* BRG5 configuration register  */
+	u32 brgc6;		/* BRG6 configuration register  */
+	u32 brgc7;		/* BRG7 configuration register  */
+	u32 brgc8;		/* BRG8 configuration register  */
+	u32 brgc9;		/* BRG9 configuration register  */
+	u32 brgc10;		/* BRG10 configuration register */
+	u32 brgc11;		/* BRG11 configuration register */
+	u32 brgc12;		/* BRG12 configuration register */
+	u32 brgc13;		/* BRG13 configuration register */
+	u32 brgc14;		/* BRG14 configuration register */
+	u32 brgc15;		/* BRG15 configuration register */
+	u32 brgc16;		/* BRG16 configuration register */
+	u8 res0[0x40];
+} __attribute__ ((packed)) qe_brg_t;
+
+/* SPI
+*/
+typedef struct spi {
+	u8 res0[0x20];
+	u32 spmode;		/* SPI mode register */
+	u8 res1[0x2];
+	u8 spie;		/* SPI event register */
+	u8 res2[0x1];
+	u8 res3[0x2];
+	u8 spim;		/* SPI mask register */
+	u8 res4[0x1];
+	u8 res5[0x1];
+	u8 spcom;		/* SPI command register  */
+	u8 res6[0x2];
+	u32 spitd;		/* SPI transmit data register (cpu mode) */
+	u32 spird;		/* SPI receive data register (cpu mode) */
+	u8 res7[0x8];
+} __attribute__ ((packed)) spi_t;
+
+/* SI
+*/
+typedef struct si1 {
+	u16 siamr1;		/* SI1 TDMA mode register */
+	u16 sibmr1;		/* SI1 TDMB mode register */
+	u16 sicmr1;		/* SI1 TDMC mode register */
+	u16 sidmr1;		/* SI1 TDMD mode register */
+	u8 siglmr1_h;		/* SI1 global mode register high */
+	u8 res0[0x1];
+	u8 sicmdr1_h;		/* SI1 command register high */
+	u8 res2[0x1];
+	u8 sistr1_h;		/* SI1 status register high */
+	u8 res3[0x1];
+	u16 sirsr1_h;		/* SI1 RAM shadow address register high */
+	u8 sitarc1;		/* SI1 RAM counter Tx TDMA */
+	u8 sitbrc1;		/* SI1 RAM counter Tx TDMB */
+	u8 sitcrc1;		/* SI1 RAM counter Tx TDMC */
+	u8 sitdrc1;		/* SI1 RAM counter Tx TDMD */
+	u8 sirarc1;		/* SI1 RAM counter Rx TDMA */
+	u8 sirbrc1;		/* SI1 RAM counter Rx TDMB */
+	u8 sircrc1;		/* SI1 RAM counter Rx TDMC */
+	u8 sirdrc1;		/* SI1 RAM counter Rx TDMD */
+	u8 res4[0x8];
+	u16 siemr1;		/* SI1 TDME mode register 16 bits */
+	u16 sifmr1;		/* SI1 TDMF mode register 16 bits */
+	u16 sigmr1;		/* SI1 TDMG mode register 16 bits */
+	u16 sihmr1;		/* SI1 TDMH mode register 16 bits */
+	u8 siglmg1_l;		/* SI1 global mode register low 8 bits */
+	u8 res5[0x1];
+	u8 sicmdr1_l;		/* SI1 command register low 8 bits */
+	u8 res6[0x1];
+	u8 sistr1_l;		/* SI1 status register low 8 bits */
+	u8 res7[0x1];
+	u16 sirsr1_l;		/* SI1 RAM shadow address register low 16 bits */
+	u8 siterc1;		/* SI1 RAM counter Tx TDME 8 bits */
+	u8 sitfrc1;		/* SI1 RAM counter Tx TDMF 8 bits */
+	u8 sitgrc1;		/* SI1 RAM counter Tx TDMG 8 bits */
+	u8 sithrc1;		/* SI1 RAM counter Tx TDMH 8 bits */
+	u8 sirerc1;		/* SI1 RAM counter Rx TDME 8 bits */
+	u8 sirfrc1;		/* SI1 RAM counter Rx TDMF 8 bits */
+	u8 sirgrc1;		/* SI1 RAM counter Rx TDMG 8 bits */
+	u8 sirhrc1;		/* SI1 RAM counter Rx TDMH 8 bits */
+	u8 res8[0x8];
+	u32 siml1;		/* SI1 multiframe limit register */
+	u8 siedm1;		/* SI1 extended diagnostic mode register */
+	u8 res9[0xBB];
+} __attribute__ ((packed)) si1_t;
+
+/* SI Routing Tables
+*/
+typedef struct sir {
+	u8 tx[0x400];
+	u8 rx[0x400];
+	u8 res0[0x800];
+} __attribute__ ((packed)) sir_t;
+
+/* USB Controller.
+*/
+typedef struct usb_ctlr {
+	u8 usb_usmod;
+	u8 usb_usadr;
+	u8 usb_uscom;
+	u8 res1[1];
+	u16 usb_usep1;
+	u16 usb_usep2;
+	u16 usb_usep3;
+	u16 usb_usep4;
+	u8 res2[4];
+	u16 usb_usber;
+	u8 res3[2];
+	u16 usb_usbmr;
+	u8 res4[1];
+	u8 usb_usbs;
+	u16 usb_ussft;
+	u8 res5[2];
+	u16 usb_usfrn;
+	u8 res6[0x22];
+} __attribute__ ((packed)) usb_t;
+
+/* MCC
+*/
+typedef struct mcc {
+	u32 mcce;		/* MCC event register */
+	u32 mccm;		/* MCC mask register */
+	u32 mccf;		/* MCC configuration register */
+	u32 merl;		/* MCC emergency request level register */
+	u8 res0[0xF0];
+} __attribute__ ((packed)) mcc_t;
+
+/* QE UCC Slow
+*/
+typedef struct ucc_slow {
+	u32 gumr_l;		/* UCCx general mode register (low) */
+	u32 gumr_h;		/* UCCx general mode register (high) */
+	u16 upsmr;		/* UCCx protocol-specific mode register */
+	u8 res0[0x2];
+	u16 utodr;		/* UCCx transmit on demand register */
+	u16 udsr;		/* UCCx data synchronization register */
+	u16 ucce;		/* UCCx event register */
+	u8 res1[0x2];
+	u16 uccm;		/* UCCx mask register */
+	u8 res2[0x1];
+	u8 uccs;		/* UCCx status register */
+	u8 res3[0x24];
+	u16 utpt;
+	u8 guemr;		/* UCC general extended mode register */
+	u8 res4[0x200 - 0x091];
+} __attribute__ ((packed)) ucc_slow_t;
+
+typedef struct ucc_mii_mng {
+	u32 miimcfg;		/* MII management configuration reg    */
+	u32 miimcom;		/* MII management command reg          */
+	u32 miimadd;		/* MII management address reg          */
+	u32 miimcon;		/* MII management control reg          */
+	u32 miimstat;		/* MII management status reg           */
+	u32 miimind;		/* MII management indication reg       */
+	u32 ifctl;		/* interface control reg               */
+	u32 ifstat;		/* interface statux reg                */
+} __attribute__ ((packed))uec_mii_t;
+
+typedef struct ucc_ethernet {
+	u32 maccfg1;		/* mac configuration reg. 1            */
+	u32 maccfg2;		/* mac configuration reg. 2            */
+	u32 ipgifg;		/* interframe gap reg.                 */
+	u32 hafdup;		/* half-duplex reg.                    */
+	u8 res1[0x10];
+	u32 miimcfg;		/* MII management configuration reg    */
+	u32 miimcom;		/* MII management command reg          */
+	u32 miimadd;		/* MII management address reg          */
+	u32 miimcon;		/* MII management control reg          */
+	u32 miimstat;		/* MII management status reg           */
+	u32 miimind;		/* MII management indication reg       */
+	u32 ifctl;		/* interface control reg               */
+	u32 ifstat;		/* interface statux reg                */
+	u32 macstnaddr1;	/* mac station address part 1 reg      */
+	u32 macstnaddr2;	/* mac station address part 2 reg      */
+	u8 res2[0x8];
+	u32 uempr;		/* UCC Ethernet Mac parameter reg      */
+	u32 utbipar;		/* UCC tbi address reg                 */
+	u16 uescr;		/* UCC Ethernet statistics control reg */
+	u8 res3[0x180 - 0x15A];
+	u32 tx64;		/* Total number of frames (including bad
+				 * frames) transmitted that were exactly
+				 * of the minimal length (64 for un tagged,
+				 * 68 for tagged, or with length exactly
+				 * equal to the parameter MINLength */
+	u32 tx127;		/* Total number of frames (including bad
+				 * frames) transmitted that were between
+				 * MINLength (Including FCS length==4)
+				 * and 127 octets */
+	u32 tx255;		/* Total number of frames (including bad
+				 * frames) transmitted that were between
+				 * 128 (Including FCS length==4) and 255
+				 * octets */
+	u32 rx64;		/* Total number of frames received including
+				 * bad frames that were exactly of the
+				 * mninimal length (64 bytes) */
+	u32 rx127;		/* Total number of frames (including bad
+				 * frames) received that were between
+				 * MINLength (Including FCS length==4)
+				 * and 127 octets */
+	u32 rx255;		/* Total number of frames (including
+				 * bad frames) received that were between
+				 * 128 (Including FCS length==4) and 255
+				 * octets */
+	u32 txok;		/* Total number of octets residing in frames
+				 * that where involved in succesfull
+				 * transmission */
+	u16 txcf;		/* Total number of PAUSE control frames
+				 *  transmitted by this MAC */
+	u8 res4[0x2];
+	u32 tmca;		/* Total number of frames that were transmitted
+				 * succesfully with the group address bit set
+				 * that are not broadcast frames */
+	u32 tbca;		/* Total number of frames transmitted
+				 * succesfully that had destination address
+				 * field equal to the broadcast address */
+	u32 rxfok;		/* Total number of frames received OK */
+	u32 rxbok;		/* Total number of octets received OK */
+	u32 rbyt;		/* Total number of octets received including
+				 * octets in bad frames. Must be implemented
+				 * in HW because it includes octets in frames
+				 * that never even reach the UCC */
+	u32 rmca;		/* Total number of frames that were received
+				 * succesfully with the group address bit set
+				 * that are not broadcast frames */
+	u32 rbca;		/* Total number of frames received succesfully
+				 * that had destination address equal to the
+				 * broadcast address */
+	u32 scar;		/* Statistics carry register */
+	u32 scam;		/* Statistics caryy mask register */
+	u8 res5[0x200 - 0x1c4];
+} __attribute__ ((packed)) uec_t;
+
+/* QE UCC Fast
+*/
+typedef struct ucc_fast {
+	u32 gumr;		/* UCCx general mode register */
+	u32 upsmr;		/* UCCx protocol-specific mode register  */
+	u16 utodr;		/* UCCx transmit on demand register  */
+	u8 res0[0x2];
+	u16 udsr;		/* UCCx data synchronization register  */
+	u8 res1[0x2];
+	u32 ucce;		/* UCCx event register */
+	u32 uccm;		/* UCCx mask register.  */
+	u8 uccs;		/* UCCx status register */
+	u8 res2[0x7];
+	u32 urfb;		/* UCC receive FIFO base */
+	u16 urfs;		/* UCC receive FIFO size */
+	u8 res3[0x2];
+	u16 urfet;		/* UCC receive FIFO emergency threshold */
+	u16 urfset;		/* UCC receive FIFO special emergency
+				 * threshold */
+	u32 utfb;		/* UCC transmit FIFO base */
+	u16 utfs;		/* UCC transmit FIFO size */
+	u8 res4[0x2];
+	u16 utfet;		/* UCC transmit FIFO emergency threshold */
+	u8 res5[0x2];
+	u16 utftt;		/* UCC transmit FIFO transmit threshold */
+	u8 res6[0x2];
+	u16 utpt;		/* UCC transmit polling timer */
+	u8 res7[0x2];
+	u32 urtry;		/* UCC retry counter register */
+	u8 res8[0x4C];
+	u8 guemr;		/* UCC general extended mode register */
+	u8 res9[0x100 - 0x091];
+	uec_t ucc_eth;
+} __attribute__ ((packed)) ucc_fast_t;
+
+/* QE UCC
+*/
+typedef struct ucc_common {
+	u8 res1[0x90];
+	u8 guemr;
+	u8 res2[0x200 - 0x091];
+} __attribute__ ((packed)) ucc_common_t;
+
+typedef struct ucc {
+	union {
+		ucc_slow_t slow;
+		ucc_fast_t fast;
+		ucc_common_t common;
+	};
+} __attribute__ ((packed)) ucc_t;
+
+/* MultiPHY UTOPIA POS Controllers (UPC)
+*/
+typedef struct upc {
+	u32 upgcr;		/* UTOPIA/POS general configuration register */
+	u32 uplpa;		/* UTOPIA/POS last PHY address */
+	u32 uphec;		/* ATM HEC register */
+	u32 upuc;		/* UTOPIA/POS UCC configuration */
+	u32 updc1;		/* UTOPIA/POS device 1 configuration */
+	u32 updc2;		/* UTOPIA/POS device 2 configuration  */
+	u32 updc3;		/* UTOPIA/POS device 3 configuration */
+	u32 updc4;		/* UTOPIA/POS device 4 configuration  */
+	u32 upstpa;		/* UTOPIA/POS STPA threshold  */
+	u8 res0[0xC];
+	u32 updrs1_h;		/* UTOPIA/POS device 1 rate select  */
+	u32 updrs1_l;		/* UTOPIA/POS device 1 rate select  */
+	u32 updrs2_h;		/* UTOPIA/POS device 2 rate select  */
+	u32 updrs2_l;		/* UTOPIA/POS device 2 rate select */
+	u32 updrs3_h;		/* UTOPIA/POS device 3 rate select */
+	u32 updrs3_l;		/* UTOPIA/POS device 3 rate select */
+	u32 updrs4_h;		/* UTOPIA/POS device 4 rate select */
+	u32 updrs4_l;		/* UTOPIA/POS device 4 rate select */
+	u32 updrp1;		/* UTOPIA/POS device 1 receive priority low  */
+	u32 updrp2;		/* UTOPIA/POS device 2 receive priority low  */
+	u32 updrp3;		/* UTOPIA/POS device 3 receive priority low  */
+	u32 updrp4;		/* UTOPIA/POS device 4 receive priority low  */
+	u32 upde1;		/* UTOPIA/POS device 1 event */
+	u32 upde2;		/* UTOPIA/POS device 2 event */
+	u32 upde3;		/* UTOPIA/POS device 3 event */
+	u32 upde4;		/* UTOPIA/POS device 4 event */
+	u16 uprp1;
+	u16 uprp2;
+	u16 uprp3;
+	u16 uprp4;
+	u8 res1[0x8];
+	u16 uptirr1_0;		/* Device 1 transmit internal rate 0 */
+	u16 uptirr1_1;		/* Device 1 transmit internal rate 1 */
+	u16 uptirr1_2;		/* Device 1 transmit internal rate 2 */
+	u16 uptirr1_3;		/* Device 1 transmit internal rate 3 */
+	u16 uptirr2_0;		/* Device 2 transmit internal rate 0 */
+	u16 uptirr2_1;		/* Device 2 transmit internal rate 1 */
+	u16 uptirr2_2;		/* Device 2 transmit internal rate 2 */
+	u16 uptirr2_3;		/* Device 2 transmit internal rate 3 */
+	u16 uptirr3_0;		/* Device 3 transmit internal rate 0 */
+	u16 uptirr3_1;		/* Device 3 transmit internal rate 1 */
+	u16 uptirr3_2;		/* Device 3 transmit internal rate 2 */
+	u16 uptirr3_3;		/* Device 3 transmit internal rate 3 */
+	u16 uptirr4_0;		/* Device 4 transmit internal rate 0 */
+	u16 uptirr4_1;		/* Device 4 transmit internal rate 1 */
+	u16 uptirr4_2;		/* Device 4 transmit internal rate 2 */
+	u16 uptirr4_3;		/* Device 4 transmit internal rate 3 */
+	u32 uper1;		/* Device 1 port enable register */
+	u32 uper2;		/* Device 2 port enable register */
+	u32 uper3;		/* Device 3 port enable register */
+	u32 uper4;		/* Device 4 port enable register */
+	u8 res2[0x150];
+} __attribute__ ((packed)) upc_t;
+
+/* SDMA
+*/
+typedef struct sdma {
+	u32 sdsr;		/* Serial DMA status register */
+	u32 sdmr;		/* Serial DMA mode register */
+	u32 sdtr1;		/* SDMA system bus threshold register */
+	u32 sdtr2;		/* SDMA secondary bus threshold register */
+	u32 sdhy1;		/* SDMA system bus hysteresis register */
+	u32 sdhy2;		/* SDMA secondary bus hysteresis register */
+	u32 sdta1;		/* SDMA system bus address register */
+	u32 sdta2;		/* SDMA secondary bus address register */
+	u32 sdtm1;		/* SDMA system bus MSNUM register */
+	u32 sdtm2;		/* SDMA secondary bus MSNUM register */
+	u8 res0[0x10];
+	u32 sdaqr;		/* SDMA address bus qualify register */
+	u32 sdaqmr;		/* SDMA address bus qualify mask register */
+	u8 res1[0x4];
+	u32 sdwbcr;		/* SDMA CAM entries base register */
+	u8 res2[0x38];
+} __attribute__ ((packed)) sdma_t;
+
+/* Debug Space
+*/
+typedef struct dbg {
+	u32 bpdcr;		/* Breakpoint debug command register */
+	u32 bpdsr;		/* Breakpoint debug status register */
+	u32 bpdmr;		/* Breakpoint debug mask register */
+	u32 bprmrr0;		/* Breakpoint request mode risc register 0 */
+	u32 bprmrr1;		/* Breakpoint request mode risc register 1 */
+	u8 res0[0x8];
+	u32 bprmtr0;		/* Breakpoint request mode trb register 0 */
+	u32 bprmtr1;		/* Breakpoint request mode trb register 1 */
+	u8 res1[0x8];
+	u32 bprmir;		/* Breakpoint request mode immediate register */
+	u32 bprmsr;		/* Breakpoint request mode serial register */
+	u32 bpemr;		/* Breakpoint exit mode register */
+	u8 res2[0x48];
+} __attribute__ ((packed)) dbg_t;
+
+/*
+ * RISC Special Registers (Trap and Breakpoint).  These are described in
+ * the QE Developer's Handbook.
+*/
+typedef struct rsp {
+	u32 tibcr[16];	/* Trap/instruction breakpoint control regs */
+	u8 res0[64];
+	u32 ibcr0;
+	u32 ibs0;
+	u32 ibcnr0;
+	u8 res1[4];
+	u32 ibcr1;
+	u32 ibs1;
+	u32 ibcnr1;
+	u32 npcr;
+	u32 dbcr;
+	u32 dbar;
+	u32 dbamr;
+	u32 dbsr;
+	u32 dbcnr;
+	u8 res2[12];
+	u32 dbdr_h;
+	u32 dbdr_l;
+	u32 dbdmr_h;
+	u32 dbdmr_l;
+	u32 bsr;
+	u32 bor;
+	u32 bior;
+	u8 res3[4];
+	u32 iatr[4];
+	u32 eccr;		/* Exception control configuration register */
+	u32 eicr;
+	u8 res4[0x100-0xf8];
+} __attribute__ ((packed)) rsp_t;
+
+typedef struct qe_immap {
+	qe_iram_t iram;		/* I-RAM */
+	qe_ic_t ic;		/* Interrupt Controller */
+	cp_qe_t cp;		/* Communications Processor */
+	qe_mux_t qmx;		/* QE Multiplexer */
+	qe_timers_t qet;	/* QE Timers */
+	spi_t spi[0x2];		/* spi  */
+	mcc_t mcc;		/* mcc */
+	qe_brg_t brg;		/* brg */
+	usb_t usb;		/* USB */
+	si1_t si1;		/* SI */
+	u8 res11[0x800];
+	sir_t sir;		/* SI Routing Tables  */
+	ucc_t ucc1;		/* ucc1 */
+	ucc_t ucc3;		/* ucc3 */
+	ucc_t ucc5;		/* ucc5 */
+	ucc_t ucc7;		/* ucc7 */
+	u8 res12[0x600];
+	upc_t upc1;		/* MultiPHY UTOPIA POS Controller 1 */
+	ucc_t ucc2;		/* ucc2 */
+	ucc_t ucc4;		/* ucc4 */
+	ucc_t ucc6;		/* ucc6 */
+	ucc_t ucc8;		/* ucc8 */
+	u8 res13[0x600];
+	upc_t upc2;		/* MultiPHY UTOPIA POS Controller 2 */
+	sdma_t sdma;		/* SDMA */
+	dbg_t dbg;		/* Debug Space */
+	rsp_t rsp[0x2];		/* RISC Special Registers
+				 * (Trap and Breakpoint) */
+	u8 res14[0x300];
+	u8 res15[0x3A00];
+	u8 res16[0x8000];	/* 0x108000 -  0x110000 */
+#if defined(CONFIG_MPC8568)
+	u8 muram[0x10000];	/* 0x1_0000 -  0x2_0000 Multi-user RAM */
+	u8 res17[0x20000];	/* 0x2_0000 -  0x4_0000 */
+#elif defined(CONFIG_MPC8569)
+	u8 muram[0x20000];	/* 0x1_0000 -  0x3_0000 Multi-user RAM */
+	u8 res17[0x10000];	/* 0x3_0000 -  0x4_0000 */
+#else
+	u8 muram[0xC000];	/* 0x110000 -  0x11C000 Multi-user RAM */
+	u8 res17[0x24000];	/* 0x11C000 -  0x140000 */
+	u8 res18[0xC0000];	/* 0x140000 -  0x200000 */
+#endif
+} __attribute__ ((packed)) qe_map_t;
+
+extern qe_map_t *qe_immr;
+
+#if defined(CONFIG_MPC8568)
+#define QE_MURAM_SIZE		0x10000UL
+#elif defined(CONFIG_MPC8569)
+#define QE_MURAM_SIZE		0x20000UL
+#elif defined(CONFIG_MPC8360)
+#define QE_MURAM_SIZE		0xc000UL
+#elif defined(CONFIG_MPC832x)
+#define QE_MURAM_SIZE		0x4000UL
+#endif
+
+#if defined(CONFIG_MPC8323)
+#define MAX_QE_RISC     1
+#define QE_NUM_OF_SNUM	28
+#elif defined(CONFIG_MPC8569)
+#define MAX_QE_RISC     4
+#define QE_NUM_OF_SNUM	46
+#else
+#define MAX_QE_RISC	2
+#define QE_NUM_OF_SNUM	28
+#endif
+
+#endif				/* __IMMAP_QE_H__ */
diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h
new file mode 100644
index 0000000..792836b
--- /dev/null
+++ b/arch/powerpc/include/asm/interrupt.h
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * This work has been supported by: QTechnology  http://qtec.com/
+ * Based on interrupts.c Wolfgang Denk-DENX Software Engineering-wd@denx.de
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef INTERRUPT_H
+#define INTERRUPT_H
+
+#if defined(CONFIG_XILINX_440)
+#include <asm/xilinx_irq.h>
+#else
+#include <asm/ppc4xx-uic.h>
+#endif
+
+void pic_enable(void);
+void pic_irq_enable(unsigned int irq);
+void pic_irq_disable(unsigned int irq);
+void pic_irq_ack(unsigned int irq);
+void external_interrupt(struct pt_regs *regs);
+void interrupt_run_handler(int vec);
+
+#endif
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
new file mode 100644
index 0000000..4ddad26
--- /dev/null
+++ b/arch/powerpc/include/asm/io.h
@@ -0,0 +1,318 @@
+/* originally from linux source.
+ * removed the dependencies on CONFIG_ values
+ * removed virt_to_phys stuff (and in fact everything surrounded by #if __KERNEL__)
+ * Modified By Rob Taylor, Flying Pig Systems, 2000
+ */
+
+#ifndef _PPC_IO_H
+#define _PPC_IO_H
+
+#include <linux/config.h>
+#include <asm/byteorder.h>
+
+#ifdef CONFIG_ADDR_MAP
+#include <addr_map.h>
+#endif
+
+#define SIO_CONFIG_RA   0x398
+#define SIO_CONFIG_RD   0x399
+
+#ifndef _IO_BASE
+#define _IO_BASE 0
+#endif
+
+#define readb(addr) in_8((volatile u8 *)(addr))
+#define writeb(b,addr) out_8((volatile u8 *)(addr), (b))
+#if !defined(__BIG_ENDIAN)
+#define readw(addr) (*(volatile u16 *) (addr))
+#define readl(addr) (*(volatile u32 *) (addr))
+#define writew(b,addr) ((*(volatile u16 *) (addr)) = (b))
+#define writel(b,addr) ((*(volatile u32 *) (addr)) = (b))
+#else
+#define readw(addr) in_le16((volatile u16 *)(addr))
+#define readl(addr) in_le32((volatile u32 *)(addr))
+#define writew(b,addr) out_le16((volatile u16 *)(addr),(b))
+#define writel(b,addr) out_le32((volatile u32 *)(addr),(b))
+#endif
+
+/*
+ * The insw/outsw/insl/outsl macros don't do byte-swapping.
+ * They are only used in practice for transferring buffers which
+ * are arrays of bytes, and byte-swapping is not appropriate in
+ * that case.  - paulus
+ */
+#define insb(port, buf, ns) _insb((u8 *)((port)+_IO_BASE), (buf), (ns))
+#define outsb(port, buf, ns)    _outsb((u8 *)((port)+_IO_BASE), (buf), (ns))
+#define insw(port, buf, ns) _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define outsw(port, buf, ns)    _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define insl(port, buf, nl) _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+#define outsl(port, buf, nl)    _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+
+#define inb(port)       in_8((u8 *)((port)+_IO_BASE))
+#define outb(val, port)     out_8((u8 *)((port)+_IO_BASE), (val))
+#if !defined(__BIG_ENDIAN)
+#define inw(port)       in_be16((u16 *)((port)+_IO_BASE))
+#define outw(val, port)     out_be16((u16 *)((port)+_IO_BASE), (val))
+#define inl(port)       in_be32((u32 *)((port)+_IO_BASE))
+#define outl(val, port)     out_be32((u32 *)((port)+_IO_BASE), (val))
+#else
+#define inw(port)       in_le16((u16 *)((port)+_IO_BASE))
+#define outw(val, port)     out_le16((u16 *)((port)+_IO_BASE), (val))
+#define inl(port)       in_le32((u32 *)((port)+_IO_BASE))
+#define outl(val, port)     out_le32((u32 *)((port)+_IO_BASE), (val))
+#endif
+
+#define inb_p(port)     in_8((u8 *)((port)+_IO_BASE))
+#define outb_p(val, port)   out_8((u8 *)((port)+_IO_BASE), (val))
+#define inw_p(port)     in_le16((u16 *)((port)+_IO_BASE))
+#define outw_p(val, port)   out_le16((u16 *)((port)+_IO_BASE), (val))
+#define inl_p(port)     in_le32((u32 *)((port)+_IO_BASE))
+#define outl_p(val, port)   out_le32((u32 *)((port)+_IO_BASE), (val))
+
+extern void _insb(volatile u8 *port, void *buf, int ns);
+extern void _outsb(volatile u8 *port, const void *buf, int ns);
+extern void _insw(volatile u16 *port, void *buf, int ns);
+extern void _outsw(volatile u16 *port, const void *buf, int ns);
+extern void _insl(volatile u32 *port, void *buf, int nl);
+extern void _outsl(volatile u32 *port, const void *buf, int nl);
+extern void _insw_ns(volatile u16 *port, void *buf, int ns);
+extern void _outsw_ns(volatile u16 *port, const void *buf, int ns);
+extern void _insl_ns(volatile u32 *port, void *buf, int nl);
+extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
+
+/*
+ * The *_ns versions below don't do byte-swapping.
+ * Neither do the standard versions now, these are just here
+ * for older code.
+ */
+#define insw_ns(port, buf, ns)  _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define outsw_ns(port, buf, ns) _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define insl_ns(port, buf, nl)  _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+#define outsl_ns(port, buf, nl) _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+
+
+#define IO_SPACE_LIMIT ~0
+
+#define memset_io(a,b,c)       memset((void *)(a),(b),(c))
+#define memcpy_fromio(a,b,c)   memcpy((a),(void *)(b),(c))
+#define memcpy_toio(a,b,c)  memcpy((void *)(a),(b),(c))
+
+/*
+ * Enforce In-order Execution of I/O:
+ * Acts as a barrier to ensure all previous I/O accesses have
+ * completed before any further ones are issued.
+ */
+static inline void eieio(void)
+{
+	__asm__ __volatile__ ("eieio" : : : "memory");
+}
+
+static inline void sync(void)
+{
+	__asm__ __volatile__ ("sync" : : : "memory");
+}
+
+static inline void isync(void)
+{
+	__asm__ __volatile__ ("isync" : : : "memory");
+}
+
+/* Enforce in-order execution of data I/O.
+ * No distinction between read/write on PPC; use eieio for all three.
+ */
+#define iobarrier_rw() eieio()
+#define iobarrier_r()  eieio()
+#define iobarrier_w()  eieio()
+
+/*
+ * Non ordered and non-swapping "raw" accessors
+ */
+#define __iomem
+#define PCI_FIX_ADDR(addr)	(addr)
+
+static inline unsigned char __raw_readb(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned char *)PCI_FIX_ADDR(addr);
+}
+static inline unsigned short __raw_readw(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned short *)PCI_FIX_ADDR(addr);
+}
+static inline unsigned int __raw_readl(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned int *)PCI_FIX_ADDR(addr);
+}
+static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr)
+{
+	*(volatile unsigned char *)PCI_FIX_ADDR(addr) = v;
+}
+static inline void __raw_writew(unsigned short v, volatile void __iomem *addr)
+{
+	*(volatile unsigned short *)PCI_FIX_ADDR(addr) = v;
+}
+static inline void __raw_writel(unsigned int v, volatile void __iomem *addr)
+{
+	*(volatile unsigned int *)PCI_FIX_ADDR(addr) = v;
+}
+
+/*
+ * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
+ *
+ * Read operations have additional twi & isync to make sure the read
+ * is actually performed (i.e. the data has come back) before we start
+ * executing any following instructions.
+ */
+extern inline int in_8(const volatile unsigned char __iomem *addr)
+{
+	int ret;
+
+	__asm__ __volatile__(
+		"sync; lbz%U1%X1 %0,%1;\n"
+		"twi 0,%0,0;\n"
+		"isync" : "=r" (ret) : "m" (*addr));
+	return ret;
+}
+
+extern inline void out_8(volatile unsigned char __iomem *addr, int val)
+{
+	__asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
+}
+
+extern inline int in_le16(const volatile unsigned short __iomem *addr)
+{
+	int ret;
+
+	__asm__ __volatile__("sync; lhbrx %0,0,%1;\n"
+			     "twi 0,%0,0;\n"
+			     "isync" : "=r" (ret) :
+			      "r" (addr), "m" (*addr));
+	return ret;
+}
+
+extern inline int in_be16(const volatile unsigned short __iomem *addr)
+{
+	int ret;
+
+	__asm__ __volatile__("sync; lhz%U1%X1 %0,%1;\n"
+			     "twi 0,%0,0;\n"
+			     "isync" : "=r" (ret) : "m" (*addr));
+	return ret;
+}
+
+extern inline void out_le16(volatile unsigned short __iomem *addr, int val)
+{
+	__asm__ __volatile__("sync; sthbrx %1,0,%2" : "=m" (*addr) :
+			      "r" (val), "r" (addr));
+}
+
+extern inline void out_be16(volatile unsigned short __iomem *addr, int val)
+{
+	__asm__ __volatile__("sync; sth%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
+}
+
+extern inline unsigned in_le32(const volatile unsigned __iomem *addr)
+{
+	unsigned ret;
+
+	__asm__ __volatile__("sync; lwbrx %0,0,%1;\n"
+			     "twi 0,%0,0;\n"
+			     "isync" : "=r" (ret) :
+			     "r" (addr), "m" (*addr));
+	return ret;
+}
+
+extern inline unsigned in_be32(const volatile unsigned __iomem *addr)
+{
+	unsigned ret;
+
+	__asm__ __volatile__("sync; lwz%U1%X1 %0,%1;\n"
+			     "twi 0,%0,0;\n"
+			     "isync" : "=r" (ret) : "m" (*addr));
+	return ret;
+}
+
+extern inline void out_le32(volatile unsigned __iomem *addr, int val)
+{
+	__asm__ __volatile__("sync; stwbrx %1,0,%2" : "=m" (*addr) :
+			     "r" (val), "r" (addr));
+}
+
+extern inline void out_be32(volatile unsigned __iomem *addr, int val)
+{
+	__asm__ __volatile__("sync; stw%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
+}
+
+/* Clear and set bits in one shot. These macros can be used to clear and
+ * set multiple bits in a register using a single call. These macros can
+ * also be used to set a multiple-bit bit pattern using a mask, by
+ * specifying the mask in the 'clear' parameter and the new bit pattern
+ * in the 'set' parameter.
+ */
+
+#define clrbits(type, addr, clear) \
+	out_##type((addr), in_##type(addr) & ~(clear))
+
+#define setbits(type, addr, set) \
+	out_##type((addr), in_##type(addr) | (set))
+
+#define clrsetbits(type, addr, clear, set) \
+	out_##type((addr), (in_##type(addr) & ~(clear)) | (set))
+
+#define clrbits_be32(addr, clear) clrbits(be32, addr, clear)
+#define setbits_be32(addr, set) setbits(be32, addr, set)
+#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set)
+
+#define clrbits_le32(addr, clear) clrbits(le32, addr, clear)
+#define setbits_le32(addr, set) setbits(le32, addr, set)
+#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set)
+
+#define clrbits_be16(addr, clear) clrbits(be16, addr, clear)
+#define setbits_be16(addr, set) setbits(be16, addr, set)
+#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set)
+
+#define clrbits_le16(addr, clear) clrbits(le16, addr, clear)
+#define setbits_le16(addr, set) setbits(le16, addr, set)
+#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set)
+
+#define clrbits_8(addr, clear) clrbits(8, addr, clear)
+#define setbits_8(addr, set) setbits(8, addr, set)
+#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
+
+/*
+ * Given a physical address and a length, return a virtual address
+ * that can be used to access the memory range with the caching
+ * properties specified by "flags".
+ */
+#define MAP_NOCACHE	(0)
+#define MAP_WRCOMBINE	(0)
+#define MAP_WRBACK	(0)
+#define MAP_WRTHROUGH	(0)
+
+static inline void *
+map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
+{
+#ifdef CONFIG_ADDR_MAP
+	return (void *)(addrmap_phys_to_virt(paddr));
+#else
+	return (void *)((unsigned long)paddr);
+#endif
+}
+
+/*
+ * Take down a mapping set up by map_physmem().
+ */
+static inline void unmap_physmem(void *vaddr, unsigned long flags)
+{
+
+}
+
+static inline phys_addr_t virt_to_phys(void * vaddr)
+{
+#ifdef CONFIG_ADDR_MAP
+	return addrmap_virt_to_phys(vaddr);
+#else
+	return (phys_addr_t)((unsigned long)vaddr);
+#endif
+}
+
+#endif
diff --git a/arch/powerpc/include/asm/iopin_8260.h b/arch/powerpc/include/asm/iopin_8260.h
new file mode 100644
index 0000000..619f3a8
--- /dev/null
+++ b/arch/powerpc/include/asm/iopin_8260.h
@@ -0,0 +1,168 @@
+/*
+ * MPC8260 I/O port pin manipulation functions
+ */
+
+#ifndef _ASM_IOPIN_8260_H_
+#define _ASM_IOPIN_8260_H_
+
+#include <linux/types.h>
+#include <asm/immap_8260.h>
+
+#ifdef __KERNEL__
+
+typedef
+    struct {
+	u_char port:2;	/* port number (A=0, B=1, C=2, D=3) */
+	u_char pin:5;	/* port pin (0-31) */
+	u_char flag:1;	/* for whatever */
+    }
+iopin_t;
+
+#define IOPIN_PORTA	0
+#define IOPIN_PORTB	1
+#define IOPIN_PORTC	2
+#define IOPIN_PORTD	3
+
+extern __inline__ void
+iopin_set_high(iopin_t *iopin)
+{
+    volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdata;
+    datp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void
+iopin_set_low(iopin_t *iopin)
+{
+    volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdata;
+    datp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint
+iopin_is_high(iopin_t *iopin)
+{
+    volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdata;
+    return (datp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint
+iopin_is_low(iopin_t *iopin)
+{
+    volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdata;
+    return ((datp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void
+iopin_set_out(iopin_t *iopin)
+{
+    volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdira;
+    dirp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void
+iopin_set_in(iopin_t *iopin)
+{
+    volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdira;
+    dirp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint
+iopin_is_out(iopin_t *iopin)
+{
+    volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdira;
+    return (dirp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint
+iopin_is_in(iopin_t *iopin)
+{
+    volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdira;
+    return ((dirp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void
+iopin_set_odr(iopin_t *iopin)
+{
+    volatile uint *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_podra;
+    odrp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void
+iopin_set_act(iopin_t *iopin)
+{
+    volatile uint *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_podra;
+    odrp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint
+iopin_is_odr(iopin_t *iopin)
+{
+    volatile uint *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_podra;
+    return (odrp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint
+iopin_is_act(iopin_t *iopin)
+{
+    volatile uint *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_podra;
+    return ((odrp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void
+iopin_set_ded(iopin_t *iopin)
+{
+    volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_ppara;
+    parp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void
+iopin_set_gen(iopin_t *iopin)
+{
+    volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_ppara;
+    parp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint
+iopin_is_ded(iopin_t *iopin)
+{
+    volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_ppara;
+    return (parp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint
+iopin_is_gen(iopin_t *iopin)
+{
+    volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_ppara;
+    return ((parp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void
+iopin_set_opt2(iopin_t *iopin)
+{
+    volatile uint *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_psora;
+    sorp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void
+iopin_set_opt1(iopin_t *iopin)
+{
+    volatile uint *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_psora;
+    sorp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint
+iopin_is_opt2(iopin_t *iopin)
+{
+    volatile uint *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_psora;
+    return (sorp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint
+iopin_is_opt1(iopin_t *iopin)
+{
+    volatile uint *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_psora;
+    return ((sorp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_IOPIN_8260_H_ */
diff --git a/arch/powerpc/include/asm/iopin_85xx.h b/arch/powerpc/include/asm/iopin_85xx.h
new file mode 100644
index 0000000..0f07ba3
--- /dev/null
+++ b/arch/powerpc/include/asm/iopin_85xx.h
@@ -0,0 +1,146 @@
+/*
+ * MPC85xx I/O port pin manipulation functions
+ */
+
+#ifndef _ASM_IOPIN_85xx_H_
+#define _ASM_IOPIN_85xx_H_
+
+#include <linux/types.h>
+#include <asm/immap_85xx.h>
+
+#ifdef __KERNEL__
+
+typedef struct {
+	u_char port:2;		/* port number (A=0, B=1, C=2, D=3) */
+	u_char pin:5;		/* port pin (0-31) */
+	u_char flag:1;		/* for whatever */
+} iopin_t;
+
+#define IOPIN_PORTA	0
+#define IOPIN_PORTB	1
+#define IOPIN_PORTC	2
+#define IOPIN_PORTD	3
+
+extern __inline__ void iopin_set_high (iopin_t * iopin)
+{
+	volatile uint *datp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdata;
+	datp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void iopin_set_low (iopin_t * iopin)
+{
+	volatile uint *datp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdata;
+	datp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint iopin_is_high (iopin_t * iopin)
+{
+	volatile uint *datp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdata;
+	return (datp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint iopin_is_low (iopin_t * iopin)
+{
+	volatile uint *datp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdata;
+	return ((datp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void iopin_set_out (iopin_t * iopin)
+{
+	volatile uint *dirp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdira;
+	dirp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void iopin_set_in (iopin_t * iopin)
+{
+	volatile uint *dirp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdira;
+	dirp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint iopin_is_out (iopin_t * iopin)
+{
+	volatile uint *dirp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdira;
+	return (dirp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint iopin_is_in (iopin_t * iopin)
+{
+	volatile uint *dirp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdira;
+	return ((dirp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void iopin_set_odr (iopin_t * iopin)
+{
+	volatile uint *odrp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.podra;
+	odrp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void iopin_set_act (iopin_t * iopin)
+{
+	volatile uint *odrp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.podra;
+	odrp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint iopin_is_odr (iopin_t * iopin)
+{
+	volatile uint *odrp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.podra;
+	return (odrp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint iopin_is_act (iopin_t * iopin)
+{
+	volatile uint *odrp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.podra;
+	return ((odrp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void iopin_set_ded (iopin_t * iopin)
+{
+	volatile uint *parp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.ppara;
+	parp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void iopin_set_gen (iopin_t * iopin)
+{
+	volatile uint *parp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.ppara;
+	parp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint iopin_is_ded (iopin_t * iopin)
+{
+	volatile uint *parp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.ppara;
+	return (parp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint iopin_is_gen (iopin_t * iopin)
+{
+	volatile uint *parp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.ppara;
+	return ((parp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void iopin_set_opt2 (iopin_t * iopin)
+{
+	volatile uint *sorp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.psora;
+	sorp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void iopin_set_opt1 (iopin_t * iopin)
+{
+	volatile uint *sorp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.psora;
+	sorp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint iopin_is_opt2 (iopin_t * iopin)
+{
+	volatile uint *sorp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.psora;
+	return (sorp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint iopin_is_opt1 (iopin_t * iopin)
+{
+	volatile uint *sorp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.psora;
+	return ((sorp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_IOPIN_85xx_H_ */
diff --git a/arch/powerpc/include/asm/iopin_8xx.h b/arch/powerpc/include/asm/iopin_8xx.h
new file mode 100644
index 0000000..3a2a682
--- /dev/null
+++ b/arch/powerpc/include/asm/iopin_8xx.h
@@ -0,0 +1,395 @@
+/*
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * MPC8xx I/O port pin manipulation functions
+ * Roughly based on iopin_8260.h
+ */
+
+#ifndef _ASM_IOPIN_8XX_H_
+#define _ASM_IOPIN_8XX_H_
+
+#include <linux/types.h>
+#include <asm/8xx_immap.h>
+
+#ifdef __KERNEL__
+
+typedef struct {
+	u_char port:2;	/* port number (A=0, B=1, C=2, D=3) */
+	u_char pin:5;	/* port pin (0-31) */
+	u_char flag:1;	/* for whatever */
+} iopin_t;
+
+#define IOPIN_PORTA	0
+#define IOPIN_PORTB	1
+#define IOPIN_PORTC	2
+#define IOPIN_PORTD	3
+
+extern __inline__ void
+iopin_set_high(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padat;
+		*datp |= (1 << (15 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdat;
+		*datp |= (1 << (31 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdat;
+		*datp |= (1 << (15 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTD) {
+		volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddat;
+		*datp |= (1 << (15 - iopin->pin));
+	}
+}
+
+extern __inline__ void
+iopin_set_low(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padat;
+		*datp &= ~(1 << (15 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdat;
+		*datp &= ~(1 << (31 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdat;
+		*datp &= ~(1 << (15 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTD) {
+		volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddat;
+		*datp &= ~(1 << (15 - iopin->pin));
+	}
+}
+
+extern __inline__ uint
+iopin_is_high(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padat;
+		return (*datp >> (15 - iopin->pin)) & 1;
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdat;
+		return (*datp >> (31 - iopin->pin)) & 1;
+	} else if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdat;
+		return (*datp >> (15 - iopin->pin)) & 1;
+	} else if (iopin->port == IOPIN_PORTD) {
+		volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddat;
+		return (*datp >> (15 - iopin->pin)) & 1;
+	}
+	return 0;
+}
+
+extern __inline__ uint
+iopin_is_low(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padat;
+		return ((*datp >> (15 - iopin->pin)) & 1) ^ 1;
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdat;
+		return ((*datp >> (31 - iopin->pin)) & 1) ^ 1;
+	} else if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdat;
+		return ((*datp >> (15 - iopin->pin)) & 1) ^ 1;
+	} else if (iopin->port == IOPIN_PORTD) {
+		volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddat;
+		return ((*datp >> (15 - iopin->pin)) & 1) ^ 1;
+	}
+	return 0;
+}
+
+extern __inline__ void
+iopin_set_out(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padir;
+		*dirp |= (1 << (15 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdir;
+		*dirp |= (1 << (31 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdir;
+		*dirp |= (1 << (15 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTD) {
+		volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddir;
+		*dirp |= (1 << (15 - iopin->pin));
+	}
+}
+
+extern __inline__ void
+iopin_set_in(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padir;
+		*dirp &= ~(1 << (15 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdir;
+		*dirp &= ~(1 << (31 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdir;
+		*dirp &= ~(1 << (15 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTD) {
+		volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddir;
+		*dirp &= ~(1 << (15 - iopin->pin));
+	}
+}
+
+extern __inline__ uint
+iopin_is_out(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padir;
+		return (*dirp >> (15 - iopin->pin)) & 1;
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdir;
+		return (*dirp >> (31 - iopin->pin)) & 1;
+	} else if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdir;
+		return (*dirp >> (15 - iopin->pin)) & 1;
+	} else if (iopin->port == IOPIN_PORTD) {
+		volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddir;
+		return (*dirp >> (15 - iopin->pin)) & 1;
+	}
+	return 0;
+}
+
+extern __inline__ uint
+iopin_is_in(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padir;
+		return ((*dirp >> (15 - iopin->pin)) & 1) ^ 1;
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdir;
+		return ((*dirp >> (31 - iopin->pin)) & 1) ^ 1;
+	} else if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdir;
+		return ((*dirp >> (15 - iopin->pin)) & 1) ^ 1;
+	} else if (iopin->port == IOPIN_PORTD) {
+		volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddir;
+		return ((*dirp >> (15 - iopin->pin)) & 1) ^ 1;
+	}
+	return 0;
+}
+
+extern __inline__ void
+iopin_set_odr(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_paodr;
+		*odrp |= (1 << (15 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbodr;
+		*odrp |= (1 << (31 - iopin->pin));
+	}
+}
+
+extern __inline__ void
+iopin_set_act(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_paodr;
+		*odrp &= ~(1 << (15 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbodr;
+		*odrp &= ~(1 << (31 - iopin->pin));
+	}
+}
+
+extern __inline__ uint
+iopin_is_odr(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_paodr;
+		return (*odrp >> (15 - iopin->pin)) & 1;
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbodr;
+		return (*odrp >> (31 - iopin->pin)) & 1;
+	}
+	return 0;
+}
+
+extern __inline__ uint
+iopin_is_act(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_paodr;
+		return ((*odrp >> (15 - iopin->pin)) & 1) ^ 1;
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbodr;
+		return ((*odrp >> (31 - iopin->pin)) & 1) ^ 1;
+	}
+	return 0;
+}
+
+extern __inline__ void
+iopin_set_ded(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_papar;
+		*parp |= (1 << (15 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbpar;
+		*parp |= (1 << (31 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcpar;
+		*parp |= (1 << (15 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTD) {
+		volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdpar;
+		*parp |= (1 << (15 - iopin->pin));
+	}
+}
+
+extern __inline__ void
+iopin_set_gen(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_papar;
+		*parp &= ~(1 << (15 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbpar;
+		*parp &= ~(1 << (31 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcpar;
+		*parp &= ~(1 << (15 - iopin->pin));
+	} else if (iopin->port == IOPIN_PORTD) {
+		volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdpar;
+		*parp &= ~(1 << (15 - iopin->pin));
+	}
+}
+
+extern __inline__ uint
+iopin_is_ded(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_papar;
+		return (*parp >> (15 - iopin->pin)) & 1;
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbpar;
+		return (*parp >> (31 - iopin->pin)) & 1;
+	} else if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcpar;
+		return (*parp >> (15 - iopin->pin)) & 1;
+	} else if (iopin->port == IOPIN_PORTD) {
+		volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdpar;
+		return (*parp >> (15 - iopin->pin)) & 1;
+	}
+	return 0;
+}
+
+extern __inline__ uint
+iopin_is_gen(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTA) {
+		volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_papar;
+		return ((*parp >> (15 - iopin->pin)) & 1) ^ 1;
+	} else if (iopin->port == IOPIN_PORTB) {
+		volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbpar;
+		return ((*parp >> (31 - iopin->pin)) & 1) ^ 1;
+	} else if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcpar;
+		return ((*parp >> (15 - iopin->pin)) & 1) ^ 1;
+	} else if (iopin->port == IOPIN_PORTD) {
+		volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdpar;
+		return ((*parp >> (15 - iopin->pin)) & 1) ^ 1;
+	}
+	return 0;
+}
+
+extern __inline__ void
+iopin_set_opt2(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcso;
+		*sorp |= (1 << (15 - iopin->pin));
+	}
+}
+
+extern __inline__ void
+iopin_set_opt1(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcso;
+		*sorp &= ~(1 << (15 - iopin->pin));
+	}
+}
+
+extern __inline__ uint
+iopin_is_opt2(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcso;
+		return (*sorp >> (15 - iopin->pin)) & 1;
+	}
+	return 0;
+}
+
+extern __inline__ uint
+iopin_is_opt1(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcso;
+		return ((*sorp >> (15 - iopin->pin)) & 1) ^ 1;
+	}
+	return 0;
+}
+
+extern __inline__ void
+iopin_set_falledge(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *intp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcint;
+		*intp |= (1 << (15 - iopin->pin));
+	}
+}
+
+extern __inline__ void
+iopin_set_anyedge(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *intp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcint;
+		*intp &= ~(1 << (15 - iopin->pin));
+	}
+}
+
+extern __inline__ uint
+iopin_is_falledge(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *intp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcint;
+		return (*intp >> (15 - iopin->pin)) & 1;
+	}
+	return 0;
+}
+
+extern __inline__ uint
+iopin_is_anyedge(iopin_t *iopin)
+{
+	if (iopin->port == IOPIN_PORTC) {
+		volatile ushort *intp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcint;
+		return ((*intp >> (15 - iopin->pin)) & 1) ^ 1;
+	}
+	return 0;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_IOPIN_8XX_H_ */
diff --git a/arch/powerpc/include/asm/m8260_pci.h b/arch/powerpc/include/asm/m8260_pci.h
new file mode 100644
index 0000000..45f01de
--- /dev/null
+++ b/arch/powerpc/include/asm/m8260_pci.h
@@ -0,0 +1,166 @@
+
+#ifndef _PPC_KERNEL_M8260_PCI_H
+#define _PPC_KERNEL_M8260_PCI_H
+
+#define M8265_PCIBR0	0x101ac
+#define M8265_PCIBR1	0x101b0
+#define M8265_PCIMSK0	0x101c4
+#define M8265_PCIMSK1	0x101c8
+
+/* Bit definitions for PCIBR registers */
+
+#define PCIBR_ENABLE        0x00000001
+
+/* Bit definitions for PCIMSK registers */
+
+#define PCIMSK_32KB         0xFFFF8000  /* Size of window, smallest */
+#define PCIMSK_64KB         0xFFFF0000
+#define PCIMSK_128KB        0xFFFE0000
+#define PCIMSK_256KB        0xFFFC0000
+#define PCIMSK_512KB        0xFFF80000
+#define PCIMSK_1MB          0xFFF00000
+#define PCIMSK_2MB          0xFFE00000
+#define PCIMSK_4MB          0xFFC00000
+#define PCIMSK_8MB          0xFF800000
+#define PCIMSK_16MB         0xFF000000
+#define PCIMSK_32MB         0xFE000000
+#define PCIMSK_64MB         0xFC000000
+#define PCIMSK_128MB        0xF8000000
+#define PCIMSK_256MB        0xF0000000
+#define PCIMSK_512MB        0xE0000000
+#define PCIMSK_1GB          0xC0000000  /* Size of window, largest */
+
+
+#define M826X_SCCR_PCI_MODE_EN 0x100
+
+
+/*
+ * Outbound ATU registers (3 sets). These registers control how 60x bus (local)
+ * addresses are translated to PCI addresses when the MPC826x is a PCI bus
+ * master (initiator).
+ */
+
+#define POTAR_REG0          0x10800     /* PCI Outbound Translation Addr registers */
+#define POTAR_REG1          0x10818
+#define POTAR_REG2          0x10830
+
+#define POBAR_REG0          0x10808     /* PCI Outbound Base Addr registers */
+#define POBAR_REG1          0x10820
+#define POBAR_REG2          0x10838
+
+#define POCMR_REG0          0x10810     /* PCI Outbound Comparison Mask registers */
+#define POCMR_REG1          0x10828
+#define POCMR_REG2          0x10840
+
+/* Bit definitions for POMCR registers */
+
+#define POCMR_MASK_4KB      0x000FFFFF
+#define POCMR_MASK_8KB      0x000FFFFE
+#define POCMR_MASK_16KB     0x000FFFFC
+#define POCMR_MASK_32KB     0x000FFFF8
+#define POCMR_MASK_64KB     0x000FFFF0
+#define POCMR_MASK_128KB    0x000FFFE0
+#define POCMR_MASK_256KB    0x000FFFC0
+#define POCMR_MASK_512KB    0x000FFF80
+#define POCMR_MASK_1MB      0x000FFF00
+#define POCMR_MASK_2MB      0x000FFE00
+#define POCMR_MASK_4MB      0x000FFC00
+#define POCMR_MASK_8MB      0x000FF800
+#define POCMR_MASK_16MB     0x000FF000
+#define POCMR_MASK_32MB     0x000FE000
+#define POCMR_MASK_64MB     0x000FC000
+#define POCMR_MASK_128MB    0x000F8000
+#define POCMR_MASK_256MB    0x000F0000
+#define POCMR_MASK_512MB    0x000E0000
+#define POCMR_MASK_1GB      0x000C0000
+
+#define POCMR_ENABLE        0x80000000
+#define POCMR_PCI_IO        0x40000000
+#define POCMR_PREFETCH_EN   0x20000000
+
+/* Soft PCI reset */
+
+#define PCI_GCR_REG         0x10880
+
+/* Bit definitions for PCI_GCR registers */
+
+#define PCIGCR_PCI_BUS_EN   0x1
+
+/*
+ * Inbound ATU registers (2 sets). These registers control how PCI addresses
+ * are translated to 60x bus (local) addresses when the MPC826x is a PCI bus target.
+ */
+
+#define PITAR_REG1          0x108D0
+#define PIBAR_REG1          0x108D8
+#define PICMR_REG1          0x108E0
+#define PITAR_REG0          0x108E8
+#define PIBAR_REG0          0x108F0
+#define PICMR_REG0          0x108F8
+
+/* Bit definitions for PCI Inbound Comparison Mask registers */
+
+#define PICMR_MASK_4KB       0x000FFFFF
+#define PICMR_MASK_8KB       0x000FFFFE
+#define PICMR_MASK_16KB      0x000FFFFC
+#define PICMR_MASK_32KB      0x000FFFF8
+#define PICMR_MASK_64KB      0x000FFFF0
+#define PICMR_MASK_128KB     0x000FFFE0
+#define PICMR_MASK_256KB     0x000FFFC0
+#define PICMR_MASK_512KB     0x000FFF80
+#define PICMR_MASK_1MB       0x000FFF00
+#define PICMR_MASK_2MB       0x000FFE00
+#define PICMR_MASK_4MB       0x000FFC00
+#define PICMR_MASK_8MB       0x000FF800
+#define PICMR_MASK_16MB      0x000FF000
+#define PICMR_MASK_32MB      0x000FE000
+#define PICMR_MASK_64MB      0x000FC000
+#define PICMR_MASK_128MB     0x000F8000
+#define PICMR_MASK_256MB     0x000F0000
+#define PICMR_MASK_512MB     0x000E0000
+#define PICMR_MASK_1GB       0x000C0000
+
+#define PICMR_ENABLE         0x80000000
+#define PICMR_NO_SNOOP_EN    0x40000000
+#define PICMR_PREFETCH_EN    0x20000000
+
+/* PCI error Registers */
+
+#define	PCI_ERROR_STATUS_REG		0x10884
+#define	PCI_ERROR_MASK_REG		0x10888
+#define	PCI_ERROR_CONTROL_REG		0x1088C
+#define PCI_ERROR_ADRS_CAPTURE_REG      0x10890
+#define PCI_ERROR_DATA_CAPTURE_REG      0x10898
+#define PCI_ERROR_CTRL_CAPTURE_REG      0x108A0
+
+/* PCI error Register bit defines */
+
+#define	PCI_ERROR_PCI_ADDR_PAR			0x00000001
+#define	PCI_ERROR_PCI_DATA_PAR_WR		0x00000002
+#define	PCI_ERROR_PCI_DATA_PAR_RD		0x00000004
+#define	PCI_ERROR_PCI_NO_RSP			0x00000008
+#define	PCI_ERROR_PCI_TAR_ABT			0x00000010
+#define	PCI_ERROR_PCI_SERR			0x00000020
+#define	PCI_ERROR_PCI_PERR_RD			0x00000040
+#define	PCI_ERROR_PCI_PERR_WR			0x00000080
+#define	PCI_ERROR_I2O_OFQO			0x00000100
+#define	PCI_ERROR_I2O_IPQO			0x00000200
+#define	PCI_ERROR_IRA				0x00000400
+#define	PCI_ERROR_NMI				0x00000800
+#define	PCI_ERROR_I2O_DBMC			0x00001000
+
+/*
+ * Register pair used to generate configuration cycles on the PCI bus
+ * and access the MPC826x's own PCI configuration registers.
+ */
+
+#define PCI_CFG_ADDR_REG     0x10900
+#define PCI_CFG_DATA_REG     0x10904
+
+/* Bus parking decides where the bus control sits when idle */
+/* If modifying memory controllers for PCI park on the core */
+
+#define PPC_ACR_BUS_PARK_CORE 0x6
+#define PPC_ACR_BUS_PARK_PCI  0x3
+
+#endif /* _PPC_KERNEL_M8260_PCI_H */
diff --git a/arch/powerpc/include/asm/mc146818rtc.h b/arch/powerpc/include/asm/mc146818rtc.h
new file mode 100644
index 0000000..5f806c4
--- /dev/null
+++ b/arch/powerpc/include/asm/mc146818rtc.h
@@ -0,0 +1,27 @@
+/*
+ * Machine dependent access functions for RTC registers.
+ */
+#ifndef __ASM_PPC_MC146818RTC_H
+#define __ASM_PPC_MC146818RTC_H
+
+#include <asm/io.h>
+
+#ifndef RTC_PORT
+#define RTC_PORT(x) (0x70 + (x))
+#define RTC_ALWAYS_BCD  1   /* RTC operates in binary mode */
+#endif
+
+/*
+ * The yet supported machines all access the RTC index register via
+ * an ISA port access but the way to access the date register differs ...
+ */
+#define CMOS_READ(addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+inb_p(RTC_PORT(1)); \
+})
+#define CMOS_WRITE(val, addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+outb_p((val),RTC_PORT(1)); \
+})
+
+#endif /* __ASM_PPC_MC146818RTC_H */
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
new file mode 100644
index 0000000..ce7f081
--- /dev/null
+++ b/arch/powerpc/include/asm/mmu.h
@@ -0,0 +1,763 @@
+/*
+ * PowerPC memory management structures
+ */
+
+#ifndef _PPC_MMU_H_
+#define _PPC_MMU_H_
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/* Hardware Page Table Entry */
+typedef struct _PTE {
+#ifdef CONFIG_PPC64BRIDGE
+	unsigned long long vsid:52;
+	unsigned long api:5;
+	unsigned long :5;
+	unsigned long h:1;
+	unsigned long v:1;
+	unsigned long long rpn:52;
+#else /* CONFIG_PPC64BRIDGE */
+	unsigned long v:1;	/* Entry is valid */
+	unsigned long vsid:24;	/* Virtual segment identifier */
+	unsigned long h:1;	/* Hash algorithm indicator */
+	unsigned long api:6;	/* Abbreviated page index */
+	unsigned long rpn:20;	/* Real (physical) page number */
+#endif /* CONFIG_PPC64BRIDGE */
+	unsigned long    :3;	/* Unused */
+	unsigned long r:1;	/* Referenced */
+	unsigned long c:1;	/* Changed */
+	unsigned long w:1;	/* Write-thru cache mode */
+	unsigned long i:1;	/* Cache inhibited */
+	unsigned long m:1;	/* Memory coherence */
+	unsigned long g:1;	/* Guarded */
+	unsigned long  :1;	/* Unused */
+	unsigned long pp:2;	/* Page protection */
+} PTE;
+
+/* Values for PP (assumes Ks=0, Kp=1) */
+#define PP_RWXX	0	/* Supervisor read/write, User none */
+#define PP_RWRX 1	/* Supervisor read/write, User read */
+#define PP_RWRW 2	/* Supervisor read/write, User read/write */
+#define PP_RXRX 3	/* Supervisor read,       User read */
+
+/* Segment Register */
+typedef struct _SEGREG {
+	unsigned long t:1;	/* Normal or I/O  type */
+	unsigned long ks:1;	/* Supervisor 'key' (normally 0) */
+	unsigned long kp:1;	/* User 'key' (normally 1) */
+	unsigned long n:1;	/* No-execute */
+	unsigned long :4;	/* Unused */
+	unsigned long vsid:24;	/* Virtual Segment Identifier */
+} SEGREG;
+
+/* Block Address Translation (BAT) Registers */
+typedef struct _P601_BATU {	/* Upper part of BAT for 601 processor */
+	unsigned long bepi:15;	/* Effective page index (virtual address) */
+	unsigned long :8;	/* unused */
+	unsigned long w:1;
+	unsigned long i:1;	/* Cache inhibit */
+	unsigned long m:1;	/* Memory coherence */
+	unsigned long ks:1;	/* Supervisor key (normally 0) */
+	unsigned long kp:1;	/* User key (normally 1) */
+	unsigned long pp:2;	/* Page access protections */
+} P601_BATU;
+
+typedef struct _BATU {		/* Upper part of BAT (all except 601) */
+#ifdef CONFIG_PPC64BRIDGE
+	unsigned long long bepi:47;
+#else /* CONFIG_PPC64BRIDGE */
+	unsigned long bepi:15;	/* Effective page index (virtual address) */
+#endif /* CONFIG_PPC64BRIDGE */
+	unsigned long :4;	/* Unused */
+	unsigned long bl:11;	/* Block size mask */
+	unsigned long vs:1;	/* Supervisor valid */
+	unsigned long vp:1;	/* User valid */
+} BATU;
+
+typedef struct _P601_BATL {	/* Lower part of BAT for 601 processor */
+	unsigned long brpn:15;	/* Real page index (physical address) */
+	unsigned long :10;	/* Unused */
+	unsigned long v:1;	/* Valid bit */
+	unsigned long bl:6;	/* Block size mask */
+} P601_BATL;
+
+typedef struct _BATL {		/* Lower part of BAT (all except 601) */
+#ifdef CONFIG_PPC64BRIDGE
+	unsigned long long brpn:47;
+#else /* CONFIG_PPC64BRIDGE */
+	unsigned long brpn:15;	/* Real page index (physical address) */
+#endif /* CONFIG_PPC64BRIDGE */
+	unsigned long :10;	/* Unused */
+	unsigned long w:1;	/* Write-thru cache */
+	unsigned long i:1;	/* Cache inhibit */
+	unsigned long m:1;	/* Memory coherence */
+	unsigned long g:1;	/* Guarded (MBZ in IBAT) */
+	unsigned long :1;	/* Unused */
+	unsigned long pp:2;	/* Page access protections */
+} BATL;
+
+typedef struct _BAT {
+	BATU batu;		/* Upper register */
+	BATL batl;		/* Lower register */
+} BAT;
+
+typedef struct _P601_BAT {
+	P601_BATU batu;		/* Upper register */
+	P601_BATL batl;		/* Lower register */
+} P601_BAT;
+
+/*
+ * Simulated two-level MMU.  This structure is used by the kernel
+ * to keep track of MMU mappings and is used to update/maintain
+ * the hardware HASH table which is really a cache of mappings.
+ *
+ * The simulated structures mimic the hardware available on other
+ * platforms, notably the 80x86 and 680x0.
+ */
+
+typedef struct _pte {
+	unsigned long page_num:20;
+	unsigned long flags:12;		/* Page flags (some unused bits) */
+} pte;
+
+#define PD_SHIFT (10+12)		/* Page directory */
+#define PD_MASK  0x02FF
+#define PT_SHIFT (12)			/* Page Table */
+#define PT_MASK  0x02FF
+#define PG_SHIFT (12)			/* Page Entry */
+
+
+/* MMU context */
+
+typedef struct _MMU_context {
+	SEGREG	segs[16];	/* Segment registers */
+	pte	**pmap;		/* Two-level page-map structure */
+} MMU_context;
+
+extern void _tlbie(unsigned long va);	/* invalidate a TLB entry */
+extern void _tlbia(void);		/* invalidate all TLB entries */
+
+#ifdef CONFIG_ADDR_MAP
+extern void init_addr_map(void);
+#endif
+
+typedef enum {
+	IBAT0 = 0, IBAT1, IBAT2, IBAT3,
+	DBAT0, DBAT1, DBAT2, DBAT3,
+#ifdef CONFIG_HIGH_BATS
+	IBAT4, IBAT5, IBAT6, IBAT7,
+	DBAT4, DBAT5, DBAT6, DBAT7
+#endif
+} ppc_bat_t;
+
+extern int read_bat(ppc_bat_t bat, unsigned long *upper, unsigned long *lower);
+extern int write_bat(ppc_bat_t bat, unsigned long upper, unsigned long lower);
+extern void print_bats(void);
+
+#endif /* __ASSEMBLY__ */
+
+#define BATU_VS                 0x00000002
+#define BATU_VP                 0x00000001
+#define BATU_INVALID            0x00000000
+
+#define BATL_WRITETHROUGH       0x00000040
+#define BATL_CACHEINHIBIT       0x00000020
+#define BATL_MEMCOHERENCE	0x00000010
+#define BATL_GUARDEDSTORAGE     0x00000008
+#define BATL_NO_ACCESS		0x00000000
+
+#define BATL_PP_MSK		0x00000003
+#define BATL_PP_00		0x00000000 /* No access */
+#define BATL_PP_01		0x00000001 /* Read-only */
+#define BATL_PP_10		0x00000002 /* Read-write */
+#define BATL_PP_11		0x00000003
+
+#define BATL_PP_NO_ACCESS	BATL_PP_00
+#define BATL_PP_RO		BATL_PP_01
+#define BATL_PP_RW		BATL_PP_10
+
+/* BAT Block size values */
+#define BATU_BL_128K            0x00000000
+#define BATU_BL_256K            0x00000004
+#define BATU_BL_512K            0x0000000c
+#define BATU_BL_1M              0x0000001c
+#define BATU_BL_2M              0x0000003c
+#define BATU_BL_4M              0x0000007c
+#define BATU_BL_8M              0x000000fc
+#define BATU_BL_16M             0x000001fc
+#define BATU_BL_32M             0x000003fc
+#define BATU_BL_64M             0x000007fc
+#define BATU_BL_128M            0x00000ffc
+#define BATU_BL_256M            0x00001ffc
+
+/* Block lengths for processors that support extended block length */
+#ifdef HID0_XBSEN
+#define BATU_BL_512M            0x00003ffc
+#define BATU_BL_1G              0x00007ffc
+#define BATU_BL_2G              0x0000fffc
+#define BATU_BL_4G              0x0001fffc
+#define BATU_BL_MAX		BATU_BL_4G
+#else
+#define BATU_BL_MAX		BATU_BL_256M
+#endif
+
+/* BAT Access Protection */
+#define BPP_XX	0x00		/* No access */
+#define BPP_RX	0x01		/* Read only */
+#define BPP_RW	0x02		/* Read/write */
+
+/* Macros to get values from BATs, once data is in the BAT register format */
+#define BATU_VALID(x) (x & 0x3)
+#define BATU_VADDR(x) (x & 0xfffe0000)
+#define BATL_PADDR(x) ((phys_addr_t)((x & 0xfffe0000)		\
+				     | ((x & 0x0e00ULL) << 24)	\
+				     | ((x & 0x04ULL) << 30)))
+#define BATU_SIZE(x) (1ULL << (fls((x & BATU_BL_MAX) >> 2) + 17))
+
+/* bytes into BATU_BL */
+#define TO_BATU_BL(x) \
+	(u32)((((1ull << __ilog2_u64((u64)x)) / (128 * 1024)) - 1) * 4)
+
+/* Used to set up SDR1 register */
+#define HASH_TABLE_SIZE_64K	0x00010000
+#define HASH_TABLE_SIZE_128K	0x00020000
+#define HASH_TABLE_SIZE_256K	0x00040000
+#define HASH_TABLE_SIZE_512K	0x00080000
+#define HASH_TABLE_SIZE_1M	0x00100000
+#define HASH_TABLE_SIZE_2M	0x00200000
+#define HASH_TABLE_SIZE_4M	0x00400000
+#define HASH_TABLE_MASK_64K	0x000
+#define HASH_TABLE_MASK_128K	0x001
+#define HASH_TABLE_MASK_256K	0x003
+#define HASH_TABLE_MASK_512K	0x007
+#define HASH_TABLE_MASK_1M	0x00F
+#define HASH_TABLE_MASK_2M	0x01F
+#define HASH_TABLE_MASK_4M	0x03F
+
+/* Control/status registers for the MPC8xx.
+ * A write operation to these registers causes serialized access.
+ * During software tablewalk, the registers used perform mask/shift-add
+ * operations when written/read.  A TLB entry is created when the Mx_RPN
+ * is written, and the contents of several registers are used to
+ * create the entry.
+ */
+#define MI_CTR		784	/* Instruction TLB control register */
+#define MI_GPM		0x80000000	/* Set domain manager mode */
+#define MI_PPM		0x40000000	/* Set subpage protection */
+#define MI_CIDEF	0x20000000	/* Set cache inhibit when MMU dis */
+#define MI_RSV4I	0x08000000	/* Reserve 4 TLB entries */
+#define MI_PPCS		0x02000000	/* Use MI_RPN prob/priv state */
+#define MI_IDXMASK	0x00001f00	/* TLB index to be loaded */
+#define MI_RESETVAL	0x00000000	/* Value of register at reset */
+
+/* These are the Ks and Kp from the PowerPC books.  For proper operation,
+ * Ks = 0, Kp = 1.
+ */
+#define MI_AP		786
+#define MI_Ks		0x80000000	/* Should not be set */
+#define MI_Kp		0x40000000	/* Should always be set */
+
+/* The effective page number register.  When read, contains the information
+ * about the last instruction TLB miss.  When MI_RPN is written, bits in
+ * this register are used to create the TLB entry.
+ */
+#define MI_EPN		787
+#define MI_EPNMASK	0xfffff000	/* Effective page number for entry */
+#define MI_EVALID	0x00000200	/* Entry is valid */
+#define MI_ASIDMASK	0x0000000f	/* ASID match value */
+					/* Reset value is undefined */
+
+/* A "level 1" or "segment" or whatever you want to call it register.
+ * For the instruction TLB, it contains bits that get loaded into the
+ * TLB entry when the MI_RPN is written.
+ */
+#define MI_TWC		789
+#define MI_APG		0x000001e0	/* Access protection group (0) */
+#define MI_GUARDED	0x00000010	/* Guarded storage */
+#define MI_PSMASK	0x0000000c	/* Mask of page size bits */
+#define MI_PS8MEG	0x0000000c	/* 8M page size */
+#define MI_PS512K	0x00000004	/* 512K page size */
+#define MI_PS4K_16K	0x00000000	/* 4K or 16K page size */
+#define MI_SVALID	0x00000001	/* Segment entry is valid */
+					/* Reset value is undefined */
+
+/* Real page number.  Defined by the pte.  Writing this register
+ * causes a TLB entry to be created for the instruction TLB, using
+ * additional information from the MI_EPN, and MI_TWC registers.
+ */
+#define MI_RPN		790
+
+/* Define an RPN value for mapping kernel memory to large virtual
+ * pages for boot initialization.  This has real page number of 0,
+ * large page size, shared page, cache enabled, and valid.
+ * Also mark all subpages valid and write access.
+ */
+#define MI_BOOTINIT	0x000001fd
+
+#define MD_CTR		792	/* Data TLB control register */
+#define MD_GPM		0x80000000	/* Set domain manager mode */
+#define MD_PPM		0x40000000	/* Set subpage protection */
+#define MD_CIDEF	0x20000000	/* Set cache inhibit when MMU dis */
+#define MD_WTDEF	0x10000000	/* Set writethrough when MMU dis */
+#define MD_RSV4I	0x08000000	/* Reserve 4 TLB entries */
+#define MD_TWAM		0x04000000	/* Use 4K page hardware assist */
+#define MD_PPCS		0x02000000	/* Use MI_RPN prob/priv state */
+#define MD_IDXMASK	0x00001f00	/* TLB index to be loaded */
+#define MD_RESETVAL	0x04000000	/* Value of register at reset */
+
+#define M_CASID		793	/* Address space ID (context) to match */
+#define MC_ASIDMASK	0x0000000f	/* Bits used for ASID value */
+
+
+/* These are the Ks and Kp from the PowerPC books.  For proper operation,
+ * Ks = 0, Kp = 1.
+ */
+#define MD_AP		794
+#define MD_Ks		0x80000000	/* Should not be set */
+#define MD_Kp		0x40000000	/* Should always be set */
+
+/* The effective page number register.  When read, contains the information
+ * about the last instruction TLB miss.  When MD_RPN is written, bits in
+ * this register are used to create the TLB entry.
+ */
+#define MD_EPN		795
+#define MD_EPNMASK	0xfffff000	/* Effective page number for entry */
+#define MD_EVALID	0x00000200	/* Entry is valid */
+#define MD_ASIDMASK	0x0000000f	/* ASID match value */
+					/* Reset value is undefined */
+
+/* The pointer to the base address of the first level page table.
+ * During a software tablewalk, reading this register provides the address
+ * of the entry associated with MD_EPN.
+ */
+#define M_TWB		796
+#define	M_L1TB		0xfffff000	/* Level 1 table base address */
+#define M_L1INDX	0x00000ffc	/* Level 1 index, when read */
+					/* Reset value is undefined */
+
+/* A "level 1" or "segment" or whatever you want to call it register.
+ * For the data TLB, it contains bits that get loaded into the TLB entry
+ * when the MD_RPN is written.  It is also provides the hardware assist
+ * for finding the PTE address during software tablewalk.
+ */
+#define MD_TWC		797
+#define MD_L2TB		0xfffff000	/* Level 2 table base address */
+#define MD_L2INDX	0xfffffe00	/* Level 2 index (*pte), when read */
+#define MD_APG		0x000001e0	/* Access protection group (0) */
+#define MD_GUARDED	0x00000010	/* Guarded storage */
+#define MD_PSMASK	0x0000000c	/* Mask of page size bits */
+#define MD_PS8MEG	0x0000000c	/* 8M page size */
+#define MD_PS512K	0x00000004	/* 512K page size */
+#define MD_PS4K_16K	0x00000000	/* 4K or 16K page size */
+#define MD_WT		0x00000002	/* Use writethrough page attribute */
+#define MD_SVALID	0x00000001	/* Segment entry is valid */
+					/* Reset value is undefined */
+
+
+/* Real page number.  Defined by the pte.  Writing this register
+ * causes a TLB entry to be created for the data TLB, using
+ * additional information from the MD_EPN, and MD_TWC registers.
+ */
+#define MD_RPN		798
+
+/* This is a temporary storage register that could be used to save
+ * a processor working register during a tablewalk.
+ */
+#define M_TW		799
+
+/*
+ * At present, all PowerPC 400-class processors share a similar TLB
+ * architecture. The instruction and data sides share a unified,
+ * 64-entry, fully-associative TLB which is maintained totally under
+ * software control. In addition, the instruction side has a
+ * hardware-managed, 4-entry, fully- associative TLB which serves as a
+ * first level to the shared TLB. These two TLBs are known as the UTLB
+ * and ITLB, respectively.
+ */
+
+#define        PPC4XX_TLB_SIZE 64
+
+/*
+ * TLB entries are defined by a "high" tag portion and a "low" data
+ * portion.  On all architectures, the data portion is 32-bits.
+ *
+ * TLB entries are managed entirely under software control by reading,
+ * writing, and searchoing using the 4xx-specific tlbre, tlbwr, and tlbsx
+ * instructions.
+ */
+
+/*
+ * FSL Book-E support
+ */
+
+#define MAS0_TLBSEL_MSK	0x30000000
+#define MAS0_TLBSEL(x)	((x << 28) & MAS0_TLBSEL_MSK)
+#define MAS0_ESEL_MSK	0x0FFF0000
+#define MAS0_ESEL(x)	((x << 16) & MAS0_ESEL_MSK)
+#define MAS0_NV(x)	((x) & 0x00000FFF)
+
+#define MAS1_VALID	0x80000000
+#define MAS1_IPROT	0x40000000
+#define MAS1_TID(x)	((x << 16) & 0x3FFF0000)
+#define MAS1_TS		0x00001000
+#define MAS1_TSIZE(x)	((x << 8) & 0x00000F00)
+
+#define MAS2_EPN	0xFFFFF000
+#define MAS2_X0		0x00000040
+#define MAS2_X1		0x00000020
+#define MAS2_W		0x00000010
+#define MAS2_I		0x00000008
+#define MAS2_M		0x00000004
+#define MAS2_G		0x00000002
+#define MAS2_E		0x00000001
+
+#define MAS3_RPN	0xFFFFF000
+#define MAS3_U0		0x00000200
+#define MAS3_U1		0x00000100
+#define MAS3_U2		0x00000080
+#define MAS3_U3		0x00000040
+#define MAS3_UX		0x00000020
+#define MAS3_SX		0x00000010
+#define MAS3_UW		0x00000008
+#define MAS3_SW		0x00000004
+#define MAS3_UR		0x00000002
+#define MAS3_SR		0x00000001
+
+#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
+#define MAS4_TIDDSEL	0x000F0000
+#define MAS4_TSIZED(x)	MAS1_TSIZE(x)
+#define MAS4_X0D	0x00000040
+#define MAS4_X1D	0x00000020
+#define MAS4_WD		0x00000010
+#define MAS4_ID		0x00000008
+#define MAS4_MD		0x00000004
+#define MAS4_GD		0x00000002
+#define MAS4_ED		0x00000001
+
+#define MAS6_SPID0	0x3FFF0000
+#define MAS6_SPID1	0x00007FFE
+#define MAS6_SAS	0x00000001
+#define MAS6_SPID	MAS6_SPID0
+
+#define MAS7_RPN	0xFFFFFFFF
+
+#define FSL_BOOKE_MAS0(tlbsel,esel,nv) \
+		(MAS0_TLBSEL(tlbsel) | MAS0_ESEL(esel) | MAS0_NV(nv))
+#define FSL_BOOKE_MAS1(v,iprot,tid,ts,tsize) \
+		((((v) << 31) & MAS1_VALID)             |\
+		(((iprot) << 30) & MAS1_IPROT)          |\
+		(MAS1_TID(tid))				|\
+		(((ts) << 12) & MAS1_TS)                |\
+		(MAS1_TSIZE(tsize)))
+#define FSL_BOOKE_MAS2(epn, wimge) \
+		(((epn) & MAS3_RPN) | (wimge))
+#define FSL_BOOKE_MAS3(rpn, user, perms) \
+		(((rpn) & MAS3_RPN) | (user) | (perms))
+#define FSL_BOOKE_MAS7(rpn) \
+		(((u64)(rpn)) >> 32)
+
+#define BOOKE_PAGESZ_1K         0
+#define BOOKE_PAGESZ_4K         1
+#define BOOKE_PAGESZ_16K        2
+#define BOOKE_PAGESZ_64K        3
+#define BOOKE_PAGESZ_256K       4
+#define BOOKE_PAGESZ_1M         5
+#define BOOKE_PAGESZ_4M         6
+#define BOOKE_PAGESZ_16M        7
+#define BOOKE_PAGESZ_64M        8
+#define BOOKE_PAGESZ_256M       9
+#define BOOKE_PAGESZ_1G		10
+#define BOOKE_PAGESZ_4G		11
+#define BOOKE_PAGESZ_16GB	12
+#define BOOKE_PAGESZ_64GB	13
+#define BOOKE_PAGESZ_256GB	14
+#define BOOKE_PAGESZ_1TB	15
+
+#ifdef CONFIG_E500
+#ifndef __ASSEMBLY__
+extern void set_tlb(u8 tlb, u32 epn, u64 rpn,
+		    u8 perms, u8 wimge,
+		    u8 ts, u8 esel, u8 tsize, u8 iprot);
+extern void disable_tlb(u8 esel);
+extern void invalidate_tlb(u8 tlb);
+extern void init_tlbs(void);
+extern int find_tlb_idx(void *addr, u8 tlbsel);
+extern void init_used_tlb_cams(void);
+extern int find_free_tlbcam(void);
+
+extern unsigned int setup_ddr_tlbs(unsigned int memsize_in_meg);
+
+extern void write_tlb(u32 _mas0, u32 _mas1, u32 _mas2, u32 _mas3, u32 _mas7);
+
+#define SET_TLB_ENTRY(_tlb, _epn, _rpn, _perms, _wimge, _ts, _esel, _sz, _iprot) \
+	{ .mas0 = FSL_BOOKE_MAS0(_tlb, _esel, 0), \
+	  .mas1 = FSL_BOOKE_MAS1(1, _iprot, 0, _ts, _sz), \
+	  .mas2 = FSL_BOOKE_MAS2(_epn, _wimge), \
+	  .mas3 = FSL_BOOKE_MAS3(_rpn, 0, _perms), \
+	  .mas7 = FSL_BOOKE_MAS7(_rpn), }
+
+struct fsl_e_tlb_entry {
+	u32	mas0;
+	u32	mas1;
+	u32	mas2;
+	u32	mas3;
+	u32	mas7;
+};
+
+extern struct fsl_e_tlb_entry tlb_table[];
+extern int num_tlb_entries;
+#endif
+#endif
+
+#ifdef CONFIG_E300
+#define LAWAR_EN		0x80000000
+#define LAWAR_SIZE		0x0000003F
+
+#define LAWAR_TRGT_IF_PCI	0x00000000
+#define LAWAR_TRGT_IF_PCI1	0x00000000
+#define LAWAR_TRGT_IF_PCIX	0x00000000
+#define LAWAR_TRGT_IF_PCI2	0x00100000
+#define LAWAR_TRGT_IF_PCIE1	0x00200000
+#define LAWAR_TRGT_IF_PCIE2	0x00100000
+#define LAWAR_TRGT_IF_PCIE3	0x00300000
+#define LAWAR_TRGT_IF_LBC	0x00400000
+#define LAWAR_TRGT_IF_CCSR	0x00800000
+#define LAWAR_TRGT_IF_DDR_INTERLEAVED 0x00B00000
+#define LAWAR_TRGT_IF_RIO	0x00c00000
+#define LAWAR_TRGT_IF_DDR	0x00f00000
+#define LAWAR_TRGT_IF_DDR1	0x00f00000
+#define LAWAR_TRGT_IF_DDR2	0x01600000
+
+#define LAWAR_SIZE_BASE		0xa
+#define LAWAR_SIZE_4K		(LAWAR_SIZE_BASE+1)
+#define LAWAR_SIZE_8K		(LAWAR_SIZE_BASE+2)
+#define LAWAR_SIZE_16K		(LAWAR_SIZE_BASE+3)
+#define LAWAR_SIZE_32K		(LAWAR_SIZE_BASE+4)
+#define LAWAR_SIZE_64K		(LAWAR_SIZE_BASE+5)
+#define LAWAR_SIZE_128K		(LAWAR_SIZE_BASE+6)
+#define LAWAR_SIZE_256K		(LAWAR_SIZE_BASE+7)
+#define LAWAR_SIZE_512K		(LAWAR_SIZE_BASE+8)
+#define LAWAR_SIZE_1M		(LAWAR_SIZE_BASE+9)
+#define LAWAR_SIZE_2M		(LAWAR_SIZE_BASE+10)
+#define LAWAR_SIZE_4M		(LAWAR_SIZE_BASE+11)
+#define LAWAR_SIZE_8M		(LAWAR_SIZE_BASE+12)
+#define LAWAR_SIZE_16M		(LAWAR_SIZE_BASE+13)
+#define LAWAR_SIZE_32M		(LAWAR_SIZE_BASE+14)
+#define LAWAR_SIZE_64M		(LAWAR_SIZE_BASE+15)
+#define LAWAR_SIZE_128M		(LAWAR_SIZE_BASE+16)
+#define LAWAR_SIZE_256M		(LAWAR_SIZE_BASE+17)
+#define LAWAR_SIZE_512M		(LAWAR_SIZE_BASE+18)
+#define LAWAR_SIZE_1G		(LAWAR_SIZE_BASE+19)
+#define LAWAR_SIZE_2G		(LAWAR_SIZE_BASE+20)
+#define LAWAR_SIZE_4G		(LAWAR_SIZE_BASE+21)
+#define LAWAR_SIZE_8G		(LAWAR_SIZE_BASE+22)
+#define LAWAR_SIZE_16G		(LAWAR_SIZE_BASE+23)
+#define LAWAR_SIZE_32G		(LAWAR_SIZE_BASE+24)
+#endif
+
+#ifdef CONFIG_440
+/* General */
+#define TLB_VALID   0x00000200
+
+/* Supported page sizes */
+
+#define SZ_1K	0x00000000
+#define SZ_4K	0x00000010
+#define SZ_16K	0x00000020
+#define SZ_64K	0x00000030
+#define SZ_256K	0x00000040
+#define SZ_1M	0x00000050
+#define SZ_16M	0x00000070
+#define SZ_256M	0x00000090
+
+/* Storage attributes */
+#define SA_W	0x00000800	/* Write-through */
+#define SA_I	0x00000400	/* Caching inhibited */
+#define SA_M	0x00000200	/* Memory coherence */
+#define SA_G	0x00000100	/* Guarded */
+#define SA_E	0x00000080	/* Endian */
+
+/* Access control */
+#define AC_X	0x00000024	/* Execute */
+#define AC_W	0x00000012	/* Write */
+#define AC_R	0x00000009	/* Read */
+
+/* Some handy macros */
+
+#define EPN(e)		((e) & 0xfffffc00)
+#define TLB0(epn,sz)	((EPN((epn)) | (sz) | TLB_VALID ))
+#define TLB1(rpn,erpn)	(((rpn) & 0xfffffc00) | (erpn))
+#define TLB2(a)		((a) & 0x00000fbf)
+
+#define tlbtab_start\
+	mflr	r1	;\
+	bl	0f	;
+
+#define tlbtab_end\
+	.long 0, 0, 0	;\
+0:	mflr	r0	;\
+	mtlr	r1	;\
+	blr		;
+
+#define tlbentry(epn,sz,rpn,erpn,attr)\
+	.long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr)
+
+/*----------------------------------------------------------------------------+
+| TLB specific defines.
++----------------------------------------------------------------------------*/
+#define TLB_256MB_ALIGN_MASK 0xFF0000000ULL
+#define TLB_16MB_ALIGN_MASK  0xFFF000000ULL
+#define TLB_1MB_ALIGN_MASK   0xFFFF00000ULL
+#define TLB_256KB_ALIGN_MASK 0xFFFFC0000ULL
+#define TLB_64KB_ALIGN_MASK  0xFFFFF0000ULL
+#define TLB_16KB_ALIGN_MASK  0xFFFFFC000ULL
+#define TLB_4KB_ALIGN_MASK   0xFFFFFF000ULL
+#define TLB_1KB_ALIGN_MASK   0xFFFFFFC00ULL
+#define TLB_256MB_SIZE       0x10000000
+#define TLB_16MB_SIZE        0x01000000
+#define TLB_1MB_SIZE         0x00100000
+#define TLB_256KB_SIZE       0x00040000
+#define TLB_64KB_SIZE        0x00010000
+#define TLB_16KB_SIZE        0x00004000
+#define TLB_4KB_SIZE         0x00001000
+#define TLB_1KB_SIZE         0x00000400
+
+#define TLB_WORD0_EPN_MASK   0xFFFFFC00
+#define TLB_WORD0_EPN_ENCODE(n) (((unsigned long)(n))&0xFFFFFC00)
+#define TLB_WORD0_EPN_DECODE(n) (((unsigned long)(n))&0xFFFFFC00)
+#define TLB_WORD0_V_MASK     0x00000200
+#define TLB_WORD0_V_ENABLE   0x00000200
+#define TLB_WORD0_V_DISABLE  0x00000000
+#define TLB_WORD0_TS_MASK    0x00000100
+#define TLB_WORD0_TS_1       0x00000100
+#define TLB_WORD0_TS_0       0x00000000
+#define TLB_WORD0_SIZE_MASK  0x000000F0
+#define TLB_WORD0_SIZE_1KB   0x00000000
+#define TLB_WORD0_SIZE_4KB   0x00000010
+#define TLB_WORD0_SIZE_16KB  0x00000020
+#define TLB_WORD0_SIZE_64KB  0x00000030
+#define TLB_WORD0_SIZE_256KB 0x00000040
+#define TLB_WORD0_SIZE_1MB   0x00000050
+#define TLB_WORD0_SIZE_16MB  0x00000070
+#define TLB_WORD0_SIZE_256MB 0x00000090
+#define TLB_WORD0_TPAR_MASK  0x0000000F
+#define TLB_WORD0_TPAR_ENCODE(n) ((((unsigned long)(n))&0x0F)<<0)
+#define TLB_WORD0_TPAR_DECODE(n) ((((unsigned long)(n))>>0)&0x0F)
+
+#define TLB_WORD1_RPN_MASK   0xFFFFFC00
+#define TLB_WORD1_RPN_ENCODE(n) (((unsigned long)(n))&0xFFFFFC00)
+#define TLB_WORD1_RPN_DECODE(n) (((unsigned long)(n))&0xFFFFFC00)
+#define TLB_WORD1_PAR1_MASK  0x00000300
+#define TLB_WORD1_PAR1_ENCODE(n) ((((unsigned long)(n))&0x03)<<8)
+#define TLB_WORD1_PAR1_DECODE(n) ((((unsigned long)(n))>>8)&0x03)
+#define TLB_WORD1_PAR1_0     0x00000000
+#define TLB_WORD1_PAR1_1     0x00000100
+#define TLB_WORD1_PAR1_2     0x00000200
+#define TLB_WORD1_PAR1_3     0x00000300
+#define TLB_WORD1_ERPN_MASK  0x0000000F
+#define TLB_WORD1_ERPN_ENCODE(n) ((((unsigned long)(n))&0x0F)<<0)
+#define TLB_WORD1_ERPN_DECODE(n) ((((unsigned long)(n))>>0)&0x0F)
+
+#define TLB_WORD2_PAR2_MASK  0xC0000000
+#define TLB_WORD2_PAR2_ENCODE(n) ((((unsigned long)(n))&0x03)<<30)
+#define TLB_WORD2_PAR2_DECODE(n) ((((unsigned long)(n))>>30)&0x03)
+#define TLB_WORD2_PAR2_0     0x00000000
+#define TLB_WORD2_PAR2_1     0x40000000
+#define TLB_WORD2_PAR2_2     0x80000000
+#define TLB_WORD2_PAR2_3     0xC0000000
+#define TLB_WORD2_U0_MASK    0x00008000
+#define TLB_WORD2_U0_ENABLE  0x00008000
+#define TLB_WORD2_U0_DISABLE 0x00000000
+#define TLB_WORD2_U1_MASK    0x00004000
+#define TLB_WORD2_U1_ENABLE  0x00004000
+#define TLB_WORD2_U1_DISABLE 0x00000000
+#define TLB_WORD2_U2_MASK    0x00002000
+#define TLB_WORD2_U2_ENABLE  0x00002000
+#define TLB_WORD2_U2_DISABLE 0x00000000
+#define TLB_WORD2_U3_MASK    0x00001000
+#define TLB_WORD2_U3_ENABLE  0x00001000
+#define TLB_WORD2_U3_DISABLE 0x00000000
+#define TLB_WORD2_W_MASK     0x00000800
+#define TLB_WORD2_W_ENABLE   0x00000800
+#define TLB_WORD2_W_DISABLE  0x00000000
+#define TLB_WORD2_I_MASK     0x00000400
+#define TLB_WORD2_I_ENABLE   0x00000400
+#define TLB_WORD2_I_DISABLE  0x00000000
+#define TLB_WORD2_M_MASK     0x00000200
+#define TLB_WORD2_M_ENABLE   0x00000200
+#define TLB_WORD2_M_DISABLE  0x00000000
+#define TLB_WORD2_G_MASK     0x00000100
+#define TLB_WORD2_G_ENABLE   0x00000100
+#define TLB_WORD2_G_DISABLE  0x00000000
+#define TLB_WORD2_E_MASK     0x00000080
+#define TLB_WORD2_E_ENABLE   0x00000080
+#define TLB_WORD2_E_DISABLE  0x00000000
+#define TLB_WORD2_UX_MASK    0x00000020
+#define TLB_WORD2_UX_ENABLE  0x00000020
+#define TLB_WORD2_UX_DISABLE 0x00000000
+#define TLB_WORD2_UW_MASK    0x00000010
+#define TLB_WORD2_UW_ENABLE  0x00000010
+#define TLB_WORD2_UW_DISABLE 0x00000000
+#define TLB_WORD2_UR_MASK    0x00000008
+#define TLB_WORD2_UR_ENABLE  0x00000008
+#define TLB_WORD2_UR_DISABLE 0x00000000
+#define TLB_WORD2_SX_MASK    0x00000004
+#define TLB_WORD2_SX_ENABLE  0x00000004
+#define TLB_WORD2_SX_DISABLE 0x00000000
+#define TLB_WORD2_SW_MASK    0x00000002
+#define TLB_WORD2_SW_ENABLE  0x00000002
+#define TLB_WORD2_SW_DISABLE 0x00000000
+#define TLB_WORD2_SR_MASK    0x00000001
+#define TLB_WORD2_SR_ENABLE  0x00000001
+#define TLB_WORD2_SR_DISABLE 0x00000000
+
+/*----------------------------------------------------------------------------+
+| Following instructions are not available in Book E mode of the GNU assembler.
++----------------------------------------------------------------------------*/
+#define DCCCI(ra,rb)			.long 0x7c000000|\
+					(ra<<16)|(rb<<11)|(454<<1)
+
+#define ICCCI(ra,rb)			.long 0x7c000000|\
+					(ra<<16)|(rb<<11)|(966<<1)
+
+#define DCREAD(rt,ra,rb)		.long 0x7c000000|\
+					(rt<<21)|(ra<<16)|(rb<<11)|(486<<1)
+
+#define ICREAD(ra,rb)			.long 0x7c000000|\
+					(ra<<16)|(rb<<11)|(998<<1)
+
+#define TLBSX(rt,ra,rb)			.long 0x7c000000|\
+					(rt<<21)|(ra<<16)|(rb<<11)|(914<<1)
+
+#define TLBWE(rs,ra,ws)			.long 0x7c000000|\
+					(rs<<21)|(ra<<16)|(ws<<11)|(978<<1)
+
+#define TLBRE(rt,ra,ws)			.long 0x7c000000|\
+					(rt<<21)|(ra<<16)|(ws<<11)|(946<<1)
+
+#define TLBSXDOT(rt,ra,rb)		.long 0x7c000001|\
+					(rt<<21)|(ra<<16)|(rb<<11)|(914<<1)
+
+#define MSYNC				.long 0x7c000000|\
+					(598<<1)
+
+#define MBAR_INST				.long 0x7c000000|\
+					(854<<1)
+
+#ifndef __ASSEMBLY__
+/* Prototypes */
+void mttlb1(unsigned long index, unsigned long value);
+void mttlb2(unsigned long index, unsigned long value);
+void mttlb3(unsigned long index, unsigned long value);
+unsigned long mftlb1(unsigned long index);
+unsigned long mftlb2(unsigned long index);
+unsigned long mftlb3(unsigned long index);
+
+void program_tlb(u64 phys_addr, u32 virt_addr, u32 size, u32 tlb_word2_i_value);
+void remove_tlb(u32 vaddr, u32 size);
+void change_tlb(u32 vaddr, u32 size, u32 tlb_word2_i_value);
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_440 */
+#endif /* _PPC_MMU_H_ */
diff --git a/arch/powerpc/include/asm/mp.h b/arch/powerpc/include/asm/mp.h
new file mode 100644
index 0000000..5388c95
--- /dev/null
+++ b/arch/powerpc/include/asm/mp.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2009 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef _ASM_MP_H_
+#define _ASM_MP_H_
+
+#include <lmb.h>
+
+void setup_mp(void);
+void cpu_mp_lmb_reserve(struct lmb *lmb);
+u32 determine_mp_bootpg(void);
+
+#endif
diff --git a/arch/powerpc/include/asm/mpc512x.h b/arch/powerpc/include/asm/mpc512x.h
new file mode 100644
index 0000000..960e229
--- /dev/null
+++ b/arch/powerpc/include/asm/mpc512x.h
@@ -0,0 +1,58 @@
+/*
+ * include/asm-ppc/mpc512x.h
+ *
+ * Prototypes, etc. for the Freescale MPC512x embedded cpu chips
+ *
+ * 2009 (C) Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __ASMPPC_MPC512X_H
+#define __ASMPPC_MPC512X_H
+
+/*
+ * macros for manipulating CSx_START/STOP
+ */
+#define CSAW_START(start)	((start) & 0xFFFF0000)
+#define CSAW_STOP(start, size)	(((start) + (size) - 1) >> 16)
+
+/*
+ * Inlines
+ */
+
+/*
+ * According to MPC5121e RM, configuring local access windows should
+ * be followed by a dummy read of the config register that was
+ * modified last and an isync.
+ */
+static inline void sync_law(volatile void *addr)
+{
+	in_be32(addr);
+	__asm__ __volatile__ ("isync");
+}
+
+/*
+ * Prototypes
+ */
+extern long int fixed_sdram(ddr512x_config_t *mddrc_config,
+				u32 *dram_init_seq, int seq_sz);
+extern int mpc5121_diu_init(void);
+extern void ide_set_reset(int idereset);
+
+#endif /* __ASMPPC_MPC512X_H */
diff --git a/arch/powerpc/include/asm/mpc8349_pci.h b/arch/powerpc/include/asm/mpc8349_pci.h
new file mode 100644
index 0000000..7a1adba
--- /dev/null
+++ b/arch/powerpc/include/asm/mpc8349_pci.h
@@ -0,0 +1,168 @@
+#ifndef _PPC_KERNEL_MPC8349_PCI_H
+#define _PPC_KERNEL_MPC8349_PCI_H
+
+
+#define M8265_PCIBR0	0x101ac
+#define M8265_PCIBR1	0x101b0
+#define M8265_PCIMSK0	0x101c4
+#define M8265_PCIMSK1	0x101c8
+
+/* Bit definitions for PCIBR registers */
+
+#define PCIBR_ENABLE        0x00000001
+
+/* Bit definitions for PCIMSK registers */
+
+#define PCIMSK_32KB         0xFFFF8000  /* Size of window, smallest */
+#define PCIMSK_64KB         0xFFFF0000
+#define PCIMSK_128KB        0xFFFE0000
+#define PCIMSK_256KB        0xFFFC0000
+#define PCIMSK_512KB        0xFFF80000
+#define PCIMSK_1MB          0xFFF00000
+#define PCIMSK_2MB          0xFFE00000
+#define PCIMSK_4MB          0xFFC00000
+#define PCIMSK_8MB          0xFF800000
+#define PCIMSK_16MB         0xFF000000
+#define PCIMSK_32MB         0xFE000000
+#define PCIMSK_64MB         0xFC000000
+#define PCIMSK_128MB        0xF8000000
+#define PCIMSK_256MB        0xF0000000
+#define PCIMSK_512MB        0xE0000000
+#define PCIMSK_1GB          0xC0000000  /* Size of window, largest */
+
+
+#define M826X_SCCR_PCI_MODE_EN 0x100
+
+
+/*
+ * Outbound ATU registers (3 sets). These registers control how 60x bus
+ * (local) addresses are translated to PCI addresses when the MPC826x is
+ * a PCI bus master (initiator).
+ */
+
+#define POTAR_REG0          0x10800     /* PCI Outbound Translation Addr registers */
+#define POTAR_REG1          0x10818
+#define POTAR_REG2          0x10830
+
+#define POBAR_REG0          0x10808     /* PCI Outbound Base Addr registers */
+#define POBAR_REG1          0x10820
+#define POBAR_REG2          0x10838
+
+#define POCMR_REG0          0x10810     /* PCI Outbound Comparison Mask registers */
+#define POCMR_REG1          0x10828
+#define POCMR_REG2          0x10840
+
+/* Bit definitions for POMCR registers */
+
+#define POCMR_MASK_4KB      0x000FFFFF
+#define POCMR_MASK_8KB      0x000FFFFE
+#define POCMR_MASK_16KB     0x000FFFFC
+#define POCMR_MASK_32KB     0x000FFFF8
+#define POCMR_MASK_64KB     0x000FFFF0
+#define POCMR_MASK_128KB    0x000FFFE0
+#define POCMR_MASK_256KB    0x000FFFC0
+#define POCMR_MASK_512KB    0x000FFF80
+#define POCMR_MASK_1MB      0x000FFF00
+#define POCMR_MASK_2MB      0x000FFE00
+#define POCMR_MASK_4MB      0x000FFC00
+#define POCMR_MASK_8MB      0x000FF800
+#define POCMR_MASK_16MB     0x000FF000
+#define POCMR_MASK_32MB     0x000FE000
+#define POCMR_MASK_64MB     0x000FC000
+#define POCMR_MASK_128MB    0x000F8000
+#define POCMR_MASK_256MB    0x000F0000
+#define POCMR_MASK_512MB    0x000E0000
+#define POCMR_MASK_1GB      0x000C0000
+
+#define POCMR_ENABLE        0x80000000
+#define POCMR_PCI_IO        0x40000000
+#define POCMR_PREFETCH_EN   0x20000000
+#define POCMR_PCI2          0x10000000
+
+/* Soft PCI reset */
+
+#define PCI_GCR_REG         0x10880
+
+/* Bit definitions for PCI_GCR registers */
+
+#define PCIGCR_PCI_BUS_EN   0x1
+
+/*
+ * Inbound ATU registers (2 sets). These registers control how PCI
+ * addresses are translated to 60x bus (local) addresses when the
+ * MPC826x is a PCI bus target.
+ */
+
+#define PITAR_REG1          0x108D0
+#define PIBAR_REG1          0x108D8
+#define PICMR_REG1          0x108E0
+#define PITAR_REG0          0x108E8
+#define PIBAR_REG0          0x108F0
+#define PICMR_REG0          0x108F8
+
+/* Bit definitions for PCI Inbound Comparison Mask registers */
+
+#define PICMR_MASK_4KB       0x000FFFFF
+#define PICMR_MASK_8KB       0x000FFFFE
+#define PICMR_MASK_16KB      0x000FFFFC
+#define PICMR_MASK_32KB      0x000FFFF8
+#define PICMR_MASK_64KB      0x000FFFF0
+#define PICMR_MASK_128KB     0x000FFFE0
+#define PICMR_MASK_256KB     0x000FFFC0
+#define PICMR_MASK_512KB     0x000FFF80
+#define PICMR_MASK_1MB       0x000FFF00
+#define PICMR_MASK_2MB       0x000FFE00
+#define PICMR_MASK_4MB       0x000FFC00
+#define PICMR_MASK_8MB       0x000FF800
+#define PICMR_MASK_16MB      0x000FF000
+#define PICMR_MASK_32MB      0x000FE000
+#define PICMR_MASK_64MB      0x000FC000
+#define PICMR_MASK_128MB     0x000F8000
+#define PICMR_MASK_256MB     0x000F0000
+#define PICMR_MASK_512MB     0x000E0000
+#define PICMR_MASK_1GB       0x000C0000
+
+#define PICMR_ENABLE         0x80000000
+#define PICMR_NO_SNOOP_EN    0x40000000
+#define PICMR_PREFETCH_EN    0x20000000
+
+/* PCI error Registers */
+
+#define	PCI_ERROR_STATUS_REG		0x10884
+#define	PCI_ERROR_MASK_REG		0x10888
+#define	PCI_ERROR_CONTROL_REG		0x1088C
+#define PCI_ERROR_ADRS_CAPTURE_REG      0x10890
+#define PCI_ERROR_DATA_CAPTURE_REG      0x10898
+#define PCI_ERROR_CTRL_CAPTURE_REG      0x108A0
+
+/* PCI error Register bit defines */
+
+#define	PCI_ERROR_PCI_ADDR_PAR			0x00000001
+#define	PCI_ERROR_PCI_DATA_PAR_WR		0x00000002
+#define	PCI_ERROR_PCI_DATA_PAR_RD		0x00000004
+#define	PCI_ERROR_PCI_NO_RSP			0x00000008
+#define	PCI_ERROR_PCI_TAR_ABT			0x00000010
+#define	PCI_ERROR_PCI_SERR			0x00000020
+#define	PCI_ERROR_PCI_PERR_RD			0x00000040
+#define	PCI_ERROR_PCI_PERR_WR			0x00000080
+#define	PCI_ERROR_I2O_OFQO			0x00000100
+#define	PCI_ERROR_I2O_IPQO			0x00000200
+#define	PCI_ERROR_IRA				0x00000400
+#define	PCI_ERROR_NMI				0x00000800
+#define	PCI_ERROR_I2O_DBMC			0x00001000
+
+/*
+ * Register pair used to generate configuration cycles on the PCI bus
+ * and access the MPC826x's own PCI configuration registers.
+ */
+
+#define PCI_CFG_ADDR_REG     0x10900
+#define PCI_CFG_DATA_REG     0x10904
+
+/* Bus parking decides where the bus control sits when idle */
+/* If modifying memory controllers for PCI park on the core */
+
+#define PPC_ACR_BUS_PARK_CORE 0x6
+#define PPC_ACR_BUS_PARK_PCI  0x3
+
+#endif /* _PPC_KERNEL_M8260_PCI_H */
diff --git a/arch/powerpc/include/asm/mpc8xxx_spi.h b/arch/powerpc/include/asm/mpc8xxx_spi.h
new file mode 100644
index 0000000..41737d3
--- /dev/null
+++ b/arch/powerpc/include/asm/mpc8xxx_spi.h
@@ -0,0 +1,48 @@
+/*
+ * Freescale non-CPM SPI Controller
+ *
+ * Copyright 2008 Qstreams Networks, Inc.
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _ASM_MPC8XXX_SPI_H_
+#define _ASM_MPC8XXX_SPI_H_
+
+#include <asm/types.h>
+
+#if defined(CONFIG_MPC834x) || \
+	defined(CONFIG_MPC8313) || \
+	defined(CONFIG_MPC8315) || \
+	defined(CONFIG_MPC837x)
+
+typedef struct spi8xxx {
+	u8 res0[0x20];	/* 0x0-0x01f reserved */
+	u32 mode;	/* mode register  */
+	u32 event;	/* event register */
+	u32 mask;	/* mask register  */
+	u32 com;	/* command register */
+	u32 tx;		/* transmit register */
+	u32 rx;		/* receive register */
+	u8 res1[0xFC8];	/* fill up to 0x1000 */
+} spi8xxx_t;
+
+#endif
+
+#endif	/* _ASM_MPC8XXX_SPI_H_ */
diff --git a/arch/powerpc/include/asm/pci_io.h b/arch/powerpc/include/asm/pci_io.h
new file mode 100644
index 0000000..9b738c3
--- /dev/null
+++ b/arch/powerpc/include/asm/pci_io.h
@@ -0,0 +1,43 @@
+/* originally from linux source (asm-ppc/io.h).
+ * Sanity added by Rob Taylor, Flying Pig Systems, 2000
+ */
+#ifndef _PCI_IO_H_
+#define _PCI_IO_H_
+
+#include "io.h"
+
+
+#define pci_read_le16(addr, dest) \
+    __asm__ __volatile__("lhbrx %0,0,%1" : "=r" (dest) : \
+		  "r" (addr), "m" (*addr));
+
+#define pci_write_le16(addr, val) \
+    __asm__ __volatile__("sthbrx %1,0,%2" : "=m" (*addr) : \
+		  "r" (val), "r" (addr));
+
+
+#define pci_read_le32(addr, dest) \
+    __asm__ __volatile__("lwbrx %0,0,%1" : "=r" (dest) : \
+		 "r" (addr), "m" (*addr));
+
+#define pci_write_le32(addr, val) \
+__asm__ __volatile__("stwbrx %1,0,%2" : "=m" (*addr) : \
+		 "r" (val), "r" (addr));
+
+#define pci_readb(addr,b) ((b) = *(volatile u8 *) (addr))
+#define pci_writeb(b,addr) ((*(volatile u8 *) (addr)) = (b))
+
+#if !defined(__BIG_ENDIAN)
+#define pci_readw(addr,b) ((b) = *(volatile u16 *) (addr))
+#define pci_readl(addr,b) ((b) = *(volatile u32 *) (addr))
+#define pci_writew(b,addr) ((*(volatile u16 *) (addr)) = (b))
+#define pci_writel(b,addr) ((*(volatile u32 *) (addr)) = (b))
+#else
+#define pci_readw(addr,b) pci_read_le16((volatile u16 *)(addr),(b))
+#define pci_readl(addr,b) pci_read_le32((volatile u32 *)(addr),(b))
+#define pci_writew(b,addr) pci_write_le16((volatile u16 *)(addr),(b))
+#define pci_writel(b,addr) pci_write_le32((volatile u32 *)(addr),(b))
+#endif
+
+
+#endif /* _PCI_IO_H_ */
diff --git a/arch/powerpc/include/asm/pnp.h b/arch/powerpc/include/asm/pnp.h
new file mode 100644
index 0000000..22ceba2
--- /dev/null
+++ b/arch/powerpc/include/asm/pnp.h
@@ -0,0 +1,643 @@
+/* 11/02/95                                                                   */
+/*----------------------------------------------------------------------------*/
+/*      Plug and Play header definitions                                      */
+/*----------------------------------------------------------------------------*/
+
+/* Structure map for PnP on PowerPC Reference Platform                        */
+/* See Plug and Play ISA Specification, Version 1.0, May 28, 1993.  It        */
+/* (or later versions) is available on Compuserve in the PLUGPLAY area.       */
+/* This code has extensions to that specification, namely new short and       */
+/* long tag types for platform dependent information                          */
+
+/* Warning: LE notation used throughout this file                             */
+
+/* For enum's: if given in hex then they are bit significant, i.e.            */
+/* only one bit is on for each enum                                           */
+
+#ifndef _PNP_
+#define _PNP_
+
+#ifndef __ASSEMBLY__
+#define MAX_MEM_REGISTERS 9
+#define MAX_IO_PORTS 20
+#define MAX_IRQS 7
+/*#define MAX_DMA_CHANNELS 7*/
+
+/* Interrupt controllers */
+
+#define PNPinterrupt0 "PNP0000"      /* AT Interrupt Controller               */
+#define PNPinterrupt1 "PNP0001"      /* EISA Interrupt Controller             */
+#define PNPinterrupt2 "PNP0002"      /* MCA Interrupt Controller              */
+#define PNPinterrupt3 "PNP0003"      /* APIC                                  */
+#define PNPExtInt     "IBM000D"      /* PowerPC Extended Interrupt Controller */
+
+/* Timers */
+
+#define PNPtimer0     "PNP0100"      /* AT Timer                              */
+#define PNPtimer1     "PNP0101"      /* EISA Timer                            */
+#define PNPtimer2     "PNP0102"      /* MCA Timer                             */
+
+/* DMA controllers */
+
+#define PNPdma0       "PNP0200"      /* AT DMA Controller                     */
+#define PNPdma1       "PNP0201"      /* EISA DMA Controller                   */
+#define PNPdma2       "PNP0202"      /* MCA DMA Controller                    */
+
+/* start of August 15, 1994 additions */
+/* CMOS */
+#define PNPCMOS       "IBM0009"      /* CMOS                                  */
+
+/* L2 Cache */
+#define PNPL2         "IBM0007"      /* L2 Cache                              */
+
+/* NVRAM */
+#define PNPNVRAM      "IBM0008"      /* NVRAM                                 */
+
+/* Power Management */
+#define PNPPM         "IBM0005"      /* Power Management                      */
+/* end of August 15, 1994 additions */
+
+/* Keyboards */
+
+#define PNPkeyboard0  "PNP0300"      /* IBM PC/XT KB Cntlr (83 key, no mouse) */
+#define PNPkeyboard1  "PNP0301"      /* Olivetti ICO (102 key)                */
+#define PNPkeyboard2  "PNP0302"      /* IBM PC/AT KB Cntlr (84 key)           */
+#define PNPkeyboard3  "PNP0303"      /* IBM Enhanced (101/2 key, PS/2 mouse)  */
+#define PNPkeyboard4  "PNP0304"      /* Nokia 1050 KB Cntlr                   */
+#define PNPkeyboard5  "PNP0305"      /* Nokia 9140 KB Cntlr                   */
+#define PNPkeyboard6  "PNP0306"      /* Standard Japanese KB Cntlr            */
+#define PNPkeyboard7  "PNP0307"      /* Microsoft Windows (R) KB Cntlr        */
+
+/* Parallel port controllers */
+
+#define PNPparallel0 "PNP0400"       /* Standard LPT Parallel Port            */
+#define PNPparallel1 "PNP0401"       /* ECP Parallel Port                     */
+#define PNPepp       "IBM001C"       /* EPP Parallel Port                     */
+
+/* Serial port controllers */
+
+#define PNPserial0   "PNP0500"       /* Standard PC Serial port               */
+#define PNPSerial1   "PNP0501"       /* 16550A Compatible Serial port         */
+
+/* Disk controllers */
+
+#define PNPdisk0     "PNP0600"       /* Generic ESDI/IDE/ATA Compat HD Cntlr  */
+#define PNPdisk1     "PNP0601"       /* Plus Hardcard II                      */
+#define PNPdisk2     "PNP0602"       /* Plus Hardcard IIXL/EZ                 */
+
+/* Diskette controllers */
+
+#define PNPdiskette0 "PNP0700"       /* PC Standard Floppy Disk Controller    */
+
+/* Display controllers */
+
+#define PNPdisplay0  "PNP0900"       /* VGA Compatible                        */
+#define PNPdisplay1  "PNP0901"       /* Video Seven VGA                       */
+#define PNPdisplay2  "PNP0902"       /* 8514/A Compatible                     */
+#define PNPdisplay3  "PNP0903"       /* Trident VGA                           */
+#define PNPdisplay4  "PNP0904"       /* Cirrus Logic Laptop VGA               */
+#define PNPdisplay5  "PNP0905"       /* Cirrus Logic VGA                      */
+#define PNPdisplay6  "PNP0906"       /* Tseng ET4000 or ET4000/W32            */
+#define PNPdisplay7  "PNP0907"       /* Western Digital VGA                   */
+#define PNPdisplay8  "PNP0908"       /* Western Digital Laptop VGA            */
+#define PNPdisplay9  "PNP0909"       /* S3                                    */
+#define PNPdisplayA  "PNP090A"       /* ATI Ultra Pro/Plus (Mach 32)          */
+#define PNPdisplayB  "PNP090B"       /* ATI Ultra (Mach 8)                    */
+#define PNPdisplayC  "PNP090C"       /* XGA Compatible                        */
+#define PNPdisplayD  "PNP090D"       /* ATI VGA Wonder                        */
+#define PNPdisplayE  "PNP090E"       /* Weitek P9000 Graphics Adapter         */
+#define PNPdisplayF  "PNP090F"       /* Oak Technology VGA                    */
+
+/* Peripheral busses */
+
+#define PNPbuses0    "PNP0A00"       /* ISA Bus                               */
+#define PNPbuses1    "PNP0A01"       /* EISA Bus                              */
+#define PNPbuses2    "PNP0A02"       /* MCA Bus                               */
+#define PNPbuses3    "PNP0A03"       /* PCI Bus                               */
+#define PNPbuses4    "PNP0A04"       /* VESA/VL Bus                           */
+
+/* RTC, BIOS, planar devices */
+
+#define PNPspeaker0  "PNP0800"       /* AT Style Speaker Sound                */
+#define PNPrtc0      "PNP0B00"       /* AT RTC                                */
+#define PNPpnpbios0  "PNP0C00"       /* PNP BIOS (only created by root enum)  */
+#define PNPpnpbios1  "PNP0C01"       /* System Board Memory Device            */
+#define PNPpnpbios2  "PNP0C02"       /* Math Coprocessor                      */
+#define PNPpnpbios3  "PNP0C03"       /* PNP BIOS Event Notification Interrupt */
+
+/* PCMCIA controller */
+
+#define PNPpcmcia0   "PNP0E00"       /* Intel 82365 Compatible PCMCIA Cntlr   */
+
+/* Mice */
+
+#define PNPmouse0    "PNP0F00"       /* Microsoft Bus Mouse                   */
+#define PNPmouse1    "PNP0F01"       /* Microsoft Serial Mouse                */
+#define PNPmouse2    "PNP0F02"       /* Microsoft Inport Mouse                */
+#define PNPmouse3    "PNP0F03"       /* Microsoft PS/2 Mouse                  */
+#define PNPmouse4    "PNP0F04"       /* Mousesystems Mouse                    */
+#define PNPmouse5    "PNP0F05"       /* Mousesystems 3 Button Mouse - COM2    */
+#define PNPmouse6    "PNP0F06"       /* Genius Mouse - COM1                   */
+#define PNPmouse7    "PNP0F07"       /* Genius Mouse - COM2                   */
+#define PNPmouse8    "PNP0F08"       /* Logitech Serial Mouse                 */
+#define PNPmouse9    "PNP0F09"       /* Microsoft Ballpoint Serial Mouse      */
+#define PNPmouseA    "PNP0F0A"       /* Microsoft PNP Mouse                   */
+#define PNPmouseB    "PNP0F0B"       /* Microsoft PNP Ballpoint Mouse         */
+
+/* Modems */
+
+#define PNPmodem0    "PNP9000"       /* Specific IDs TBD                      */
+
+/* Network controllers */
+
+#define PNPnetworkC9 "PNP80C9"       /* IBM Token Ring                        */
+#define PNPnetworkCA "PNP80CA"       /* IBM Token Ring II                     */
+#define PNPnetworkCB "PNP80CB"       /* IBM Token Ring II/Short               */
+#define PNPnetworkCC "PNP80CC"       /* IBM Token Ring 4/16Mbs                */
+#define PNPnetwork27 "PNP8327"       /* IBM Token Ring (All types)            */
+#define PNPnetworket "IBM0010"       /* IBM Ethernet used by Power PC         */
+#define PNPneteisaet "IBM2001"       /* IBM Ethernet EISA adapter             */
+#define PNPAMD79C970 "IBM0016"       /* AMD 79C970 (PCI Ethernet)             */
+
+/* SCSI controllers */
+
+#define PNPscsi0     "PNPA000"       /* Adaptec 154x Compatible SCSI Cntlr    */
+#define PNPscsi1     "PNPA001"       /* Adaptec 174x Compatible SCSI Cntlr    */
+#define PNPscsi2     "PNPA002"       /* Future Domain 16-700 Compat SCSI Cntlr*/
+#define PNPscsi3     "PNPA003"       /* Panasonic CDROM Adapter (SBPro/SB16)  */
+#define PNPscsiF     "IBM000F"       /* NCR 810 SCSI Controller               */
+#define PNPscsi825   "IBM001B"       /* NCR 825 SCSI Controller               */
+#define PNPscsi875   "IBM0018"       /* NCR 875 SCSI Controller               */
+
+/* Sound/Video, Multimedia */
+
+#define PNPmm0       "PNPB000"       /* Sound Blaster Compatible Sound Device */
+#define PNPmm1       "PNPB001"       /* MS Windows Sound System Compat Device */
+#define PNPmmF       "IBM000E"       /* Crystal CS4231 Audio Device           */
+#define PNPv7310     "IBM0015"       /* ASCII V7310 Video Capture Device      */
+#define PNPmm4232    "IBM0017"       /* Crystal CS4232 Audio Device           */
+#define PNPpmsyn     "IBM001D"       /* YMF 289B chip (Yamaha)                */
+#define PNPgp4232    "IBM0012"       /* Crystal CS4232 Game Port              */
+#define PNPmidi4232  "IBM0013"       /* Crystal CS4232 MIDI                   */
+
+/* Operator Panel */
+#define PNPopctl     "IBM000B"       /* Operator's panel                      */
+
+/* Service Processor */
+#define PNPsp        "IBM0011"       /* IBM Service Processor                 */
+#define PNPLTsp      "IBM001E"       /* Lightning/Terlingua Support Processor */
+#define PNPLTmsp     "IBM001F"       /* Lightning/Terlingua Mini-SP           */
+
+/* Memory Controller */
+#define PNPmemctl    "IBM000A"       /* Memory controller                     */
+
+/* Graphics Assist */
+#define PNPg_assist  "IBM0014"       /* Graphics Assist                       */
+
+/* Miscellaneous Device Controllers */
+#define PNPtablet    "IBM0019"       /* IBM Tablet Controller                 */
+
+/* PNP Packet Handles */
+
+#define S1_Packet                0x0A   /* Version resource                   */
+#define S2_Packet                0x15   /* Logical DEVID (without flags)      */
+#define S2_Packet_flags          0x16   /* Logical DEVID (with flags)         */
+#define S3_Packet                0x1C   /* Compatible device ID               */
+#define S4_Packet                0x22   /* IRQ resource (without flags)       */
+#define S4_Packet_flags          0x23   /* IRQ resource (with flags)          */
+#define S5_Packet                0x2A   /* DMA resource                       */
+#define S6_Packet                0x30   /* Depend funct start (w/o priority)  */
+#define S6_Packet_priority       0x31   /* Depend funct start (w/ priority)   */
+#define S7_Packet                0x38   /* Depend funct end                   */
+#define S8_Packet                0x47   /* I/O port resource (w/o fixed loc)  */
+#define S9_Packet_fixed          0x4B   /* I/O port resource (w/ fixed loc)   */
+#define S14_Packet               0x71   /* Vendor defined                     */
+#define S15_Packet               0x78   /* End of resource (w/o checksum)     */
+#define S15_Packet_checksum      0x79   /* End of resource (w/ checksum)      */
+#define L1_Packet                0x81   /* Memory range                       */
+#define L1_Shadow                0x20   /* Memory is shadowable               */
+#define L1_32bit_mem             0x18   /* 32-bit memory only                 */
+#define L1_8_16bit_mem           0x10   /* 8- and 16-bit supported            */
+#define L1_Decode_Hi             0x04   /* decode supports high address       */
+#define L1_Cache                 0x02   /* read cacheable, write-through      */
+#define L1_Writeable             0x01   /* Memory is writeable                */
+#define L2_Packet                0x82   /* ANSI ID string                     */
+#define L3_Packet                0x83   /* Unicode ID string                  */
+#define L4_Packet                0x84   /* Vendor defined                     */
+#define L5_Packet                0x85   /* Large I/O                          */
+#define L6_Packet                0x86   /* 32-bit Fixed Loc Mem Range Desc    */
+#define END_TAG                  0x78   /* End of resource                    */
+#define DF_START_TAG             0x30   /* Dependent function start           */
+#define DF_START_TAG_priority    0x31   /* Dependent function start           */
+#define DF_END_TAG               0x38   /* Dependent function end             */
+#define SUBOPTIMAL_CONFIGURATION 0x2    /* Priority byte sub optimal config   */
+
+/* Device Base Type Codes */
+
+typedef enum _PnP_BASE_TYPE {
+  Reserved = 0,
+  MassStorageDevice = 1,
+  NetworkInterfaceController = 2,
+  DisplayController = 3,
+  MultimediaController = 4,
+  MemoryController = 5,
+  BridgeController = 6,
+  CommunicationsDevice = 7,
+  SystemPeripheral = 8,
+  InputDevice = 9,
+  ServiceProcessor = 0x0A,              /* 11/2/95                            */
+  } PnP_BASE_TYPE;
+
+/* Device Sub Type Codes */
+
+typedef enum _PnP_SUB_TYPE {
+  SCSIController = 0,
+  IDEController = 1,
+  FloppyController = 2,
+  IPIController = 3,
+  OtherMassStorageController = 0x80,
+
+  EthernetController = 0,
+  TokenRingController = 1,
+  FDDIController = 2,
+  OtherNetworkController = 0x80,
+
+  VGAController= 0,
+  SVGAController= 1,
+  XGAController= 2,
+  OtherDisplayController = 0x80,
+
+  VideoController = 0,
+  AudioController = 1,
+  OtherMultimediaController = 0x80,
+
+  RAM = 0,
+  FLASH = 1,
+  OtherMemoryDevice = 0x80,
+
+  HostProcessorBridge = 0,
+  ISABridge = 1,
+  EISABridge = 2,
+  MicroChannelBridge = 3,
+  PCIBridge = 4,
+  PCMCIABridge = 5,
+  VMEBridge = 6,
+  OtherBridgeDevice = 0x80,
+
+  RS232Device = 0,
+  ATCompatibleParallelPort = 1,
+  OtherCommunicationsDevice = 0x80,
+
+  ProgrammableInterruptController = 0,
+  DMAController = 1,
+  SystemTimer = 2,
+  RealTimeClock = 3,
+  L2Cache = 4,
+  NVRAM = 5,
+  PowerManagement = 6,
+  CMOS = 7,
+  OperatorPanel = 8,
+  ServiceProcessorClass1 = 9,
+  ServiceProcessorClass2 = 0xA,
+  ServiceProcessorClass3 = 0xB,
+  GraphicAssist = 0xC,
+  SystemPlanar = 0xF,                   /* 10/5/95                            */
+  OtherSystemPeripheral = 0x80,
+
+  KeyboardController = 0,
+  Digitizer = 1,
+  MouseController = 2,
+  TabletController = 3,                 /* 10/27/95                           */
+  OtherInputController = 0x80,
+
+  GeneralMemoryController = 0,
+  } PnP_SUB_TYPE;
+
+/* Device Interface Type Codes */
+
+typedef enum _PnP_INTERFACE {
+  General = 0,
+  GeneralSCSI = 0,
+  GeneralIDE = 0,
+  ATACompatible = 1,
+
+  GeneralFloppy = 0,
+  Compatible765 = 1,
+  NS398_Floppy = 2,                     /* NS Super I/O wired to use index
+					   register at port 398 and data
+					   register at port 399               */
+  NS26E_Floppy = 3,                     /* Ports 26E and 26F                  */
+  NS15C_Floppy = 4,                     /* Ports 15C and 15D                  */
+  NS2E_Floppy = 5,                      /* Ports 2E and 2F                    */
+  CHRP_Floppy = 6,                      /* CHRP Floppy in PR*P system         */
+
+  GeneralIPI = 0,
+
+  GeneralEther = 0,
+  GeneralToken = 0,
+  GeneralFDDI = 0,
+
+  GeneralVGA = 0,
+  GeneralSVGA = 0,
+  GeneralXGA = 0,
+
+  GeneralVideo = 0,
+  GeneralAudio = 0,
+  CS4232Audio = 1,                      /* CS 4232 Plug 'n Play Configured    */
+
+  GeneralRAM = 0,
+  GeneralFLASH = 0,
+  PCIMemoryController = 0,              /* PCI Config Method                  */
+  RS6KMemoryController = 1,             /* RS6K Config Method                 */
+
+  GeneralHostBridge = 0,
+  GeneralISABridge = 0,
+  GeneralEISABridge = 0,
+  GeneralMCABridge = 0,
+  GeneralPCIBridge = 0,
+  PCIBridgeDirect = 0,
+  PCIBridgeIndirect = 1,
+  PCIBridgeRS6K = 2,
+  GeneralPCMCIABridge = 0,
+  GeneralVMEBridge = 0,
+
+  GeneralRS232 = 0,
+  COMx = 1,
+  Compatible16450 = 2,
+  Compatible16550 = 3,
+  NS398SerPort = 4,                     /* NS Super I/O wired to use index
+					   register at port 398 and data
+					   register at port 399               */
+  NS26ESerPort = 5,                     /* Ports 26E and 26F                  */
+  NS15CSerPort = 6,                     /* Ports 15C and 15D                  */
+  NS2ESerPort = 7,                      /* Ports 2E and 2F                    */
+
+  GeneralParPort = 0,
+  LPTx = 1,
+  NS398ParPort = 2,                     /* NS Super I/O wired to use index
+					   register at port 398 and data
+					   register at port 399               */
+  NS26EParPort = 3,                     /* Ports 26E and 26F                  */
+  NS15CParPort = 4,                     /* Ports 15C and 15D                  */
+  NS2EParPort = 5,                      /* Ports 2E and 2F                    */
+
+  GeneralPIC = 0,
+  ISA_PIC = 1,
+  EISA_PIC = 2,
+  MPIC = 3,
+  RS6K_PIC = 4,
+
+  GeneralDMA = 0,
+  ISA_DMA = 1,
+  EISA_DMA = 2,
+
+  GeneralTimer = 0,
+  ISA_Timer = 1,
+  EISA_Timer = 2,
+  GeneralRTC = 0,
+  ISA_RTC = 1,
+
+  StoreThruOnly = 1,
+  StoreInEnabled = 2,
+  RS6KL2Cache = 3,
+
+  IndirectNVRAM = 0,                    /* Indirectly addressed               */
+  DirectNVRAM = 1,                      /* Memory Mapped                      */
+  IndirectNVRAM24 = 2,                  /* Indirectly addressed - 24 bit      */
+
+  GeneralPowerManagement = 0,
+  EPOWPowerManagement = 1,
+  PowerControl = 2,                    /* d1378 */
+
+  GeneralCMOS = 0,
+
+  GeneralOPPanel = 0,
+  HarddiskLight = 1,
+  CDROMLight = 2,
+  PowerLight = 3,
+  KeyLock = 4,
+  ANDisplay = 5,                        /* AlphaNumeric Display               */
+  SystemStatusLED = 6,                  /* 3 digit 7 segment LED              */
+  CHRP_SystemStatusLED = 7,             /* CHRP LEDs in PR*P system           */
+
+  GeneralServiceProcessor = 0,
+
+  TransferData = 1,
+  IGMC32 = 2,
+  IGMC64 = 3,
+
+  GeneralSystemPlanar = 0,              /* 10/5/95                            */
+
+  } PnP_INTERFACE;
+
+/* PnP resources */
+
+/* Compressed ASCII is 5 bits per char; 00001=A ... 11010=Z */
+
+typedef struct _SERIAL_ID {
+  unsigned char VendorID0;              /*    Bit(7)=0                        */
+					/*    Bits(6:2)=1st character in      */
+					/*       compressed ASCII             */
+					/*    Bits(1:0)=2nd character in      */
+					/*       compressed ASCII bits(4:3)   */
+  unsigned char VendorID1;              /*    Bits(7:5)=2nd character in      */
+					/*       compressed ASCII bits(2:0)   */
+					/*    Bits(4:0)=3rd character in      */
+					/*       compressed ASCII             */
+  unsigned char VendorID2;              /* Product number - vendor assigned   */
+  unsigned char VendorID3;              /* Product number - vendor assigned   */
+
+/* Serial number is to provide uniqueness if more than one board of same      */
+/* type is in system.  Must be "FFFFFFFF" if feature not supported.           */
+
+  unsigned char Serial0;                /* Unique serial number bits (7:0)    */
+  unsigned char Serial1;                /* Unique serial number bits (15:8)   */
+  unsigned char Serial2;                /* Unique serial number bits (23:16)  */
+  unsigned char Serial3;                /* Unique serial number bits (31:24)  */
+  unsigned char Checksum;
+  } SERIAL_ID;
+
+typedef enum _PnPItemName {
+  Unused = 0,
+  PnPVersion = 1,
+  LogicalDevice = 2,
+  CompatibleDevice = 3,
+  IRQFormat = 4,
+  DMAFormat = 5,
+  StartDepFunc = 6,
+  EndDepFunc = 7,
+  IOPort = 8,
+  FixedIOPort = 9,
+  Res1 = 10,
+  Res2 = 11,
+  Res3 = 12,
+  SmallVendorItem = 14,
+  EndTag = 15,
+  MemoryRange = 1,
+  ANSIIdentifier = 2,
+  UnicodeIdentifier = 3,
+  LargeVendorItem = 4,
+  MemoryRange32 = 5,
+  MemoryRangeFixed32 = 6,
+  } PnPItemName;
+
+/* Define a bunch of access functions for the bits in the tag field */
+
+/* Tag type - 0 = small; 1 = large */
+#define tag_type(t) (((t) & 0x80)>>7)
+#define set_tag_type(t,v) (t = (t & 0x7f) | ((v)<<7))
+
+/* Small item name is 4 bits - one of PnPItemName enum above */
+#define tag_small_item_name(t) (((t) & 0x78)>>3)
+#define set_tag_small_item_name(t,v) (t = (t & 0x07) | ((v)<<3))
+
+/* Small item count is 3 bits - count of further bytes in packet */
+#define tag_small_count(t) ((t) & 0x07)
+#define set_tag_count(t,v) (t = (t & 0x78) | (v))
+
+/* Large item name is 7 bits - one of PnPItemName enum above */
+#define tag_large_item_name(t) ((t) & 0x7f)
+#define set_tag_large_item_name(t,v) (t = (t | 0x80) | (v))
+
+/* a PnP resource is a bunch of contiguous TAG packets ending with an end tag */
+
+typedef union _PnP_TAG_PACKET {
+  struct _S1_Pack{                      /* VERSION PACKET                     */
+    unsigned char Tag;                  /* small tag = 0x0a                   */
+    unsigned char Version[2];           /* PnP version, Vendor version        */
+    } S1_Pack;
+
+  struct _S2_Pack{                      /* LOGICAL DEVICE ID PACKET           */
+    unsigned char Tag;                  /* small tag = 0x15 or 0x16           */
+    unsigned char DevId[4];             /* Logical device id                  */
+    unsigned char Flags[2];             /* bit(0) boot device;                */
+					/* bit(7:1) cmd in range x31-x37      */
+					/* bit(7:0) cmd in range x28-x3f (opt)*/
+    } S2_Pack;
+
+  struct _S3_Pack{                      /* COMPATIBLE DEVICE ID PACKET        */
+    unsigned char Tag;                  /* small tag = 0x1c                   */
+    unsigned char CompatId[4];          /* Compatible device id               */
+    } S3_Pack;
+
+  struct _S4_Pack{                      /* IRQ PACKET                         */
+    unsigned char Tag;                  /* small tag = 0x22 or 0x23           */
+    unsigned char IRQMask[2];           /* bit(0) is IRQ0, ...;               */
+					/* bit(0) is IRQ8 ...                 */
+    unsigned char IRQInfo;              /* optional; assume bit(0)=1; else    */
+					/*  bit(0) - high true edge sensitive */
+					/*  bit(1) - low true edge sensitive  */
+					/*  bit(2) - high true level sensitive*/
+					/*  bit(3) - low true level sensitive */
+					/*  bit(7:4) - must be 0              */
+    } S4_Pack;
+
+  struct _S5_Pack{                      /* DMA PACKET                         */
+    unsigned char Tag;                  /* small tag = 0x2a                   */
+    unsigned char DMAMask;              /* bit(0) is channel 0 ...            */
+    unsigned char DMAInfo;
+    } S5_Pack;
+
+  struct _S6_Pack{                      /* START DEPENDENT FUNCTION PACKET    */
+    unsigned char Tag;                  /* small tag = 0x30 or 0x31           */
+    unsigned char Priority;             /* Optional; if missing then x01; else*/
+					/*  x00 = best possible               */
+					/*  x01 = acceptible                  */
+					/*  x02 = sub-optimal but functional  */
+    } S6_Pack;
+
+  struct _S7_Pack{                      /* END DEPENDENT FUNCTION PACKET      */
+    unsigned char Tag;                  /* small tag = 0x38                   */
+    } S7_Pack;
+
+  struct _S8_Pack{                      /* VARIABLE I/O PORT PACKET           */
+    unsigned char Tag;                  /* small tag x47                      */
+    unsigned char IOInfo;               /* x0  = decode only bits(9:0);       */
+#define  ISAAddr16bit         0x01      /* x01 = decode bits(15:0)            */
+    unsigned char RangeMin[2];          /* Min base address                   */
+    unsigned char RangeMax[2];          /* Max base address                   */
+    unsigned char IOAlign;              /* base alignmt, incr in 1B blocks    */
+    unsigned char IONum;                /* number of contiguous I/O ports     */
+    } S8_Pack;
+
+  struct _S9_Pack{                      /* FIXED I/O PORT PACKET              */
+    unsigned char Tag;                  /* small tag = 0x4b                   */
+    unsigned char Range[2];             /* base address 10 bits               */
+    unsigned char IONum;                /* number of contiguous I/O ports     */
+    } S9_Pack;
+
+  struct _S14_Pack{                     /* VENDOR DEFINED PACKET              */
+    unsigned char Tag;                  /* small tag = 0x7m m = 1-7           */
+    union _S14_Data{
+      unsigned char Data[7];            /* Vendor defined                     */
+      struct _S14_PPCPack{              /* Pr*p s14 pack                      */
+	 unsigned char Type;            /* 00=non-IBM                         */
+	 unsigned char PPCData[6];      /* Vendor defined                     */
+	} S14_PPCPack;
+      } S14_Data;
+    } S14_Pack;
+
+  struct _S15_Pack{                     /* END PACKET                         */
+    unsigned char Tag;                  /* small tag = 0x78 or 0x79           */
+    unsigned char Check;                /* optional - checksum                */
+    } S15_Pack;
+
+  struct _L1_Pack{                      /* MEMORY RANGE PACKET                */
+    unsigned char Tag;                  /* large tag = 0x81                   */
+    unsigned char Count0;               /* x09                                */
+    unsigned char Count1;               /* x00                                */
+    unsigned char Data[9];              /* a variable array of bytes,         */
+					/* count in tag                       */
+    } L1_Pack;
+
+  struct _L2_Pack{                      /* ANSI ID STRING PACKET              */
+    unsigned char Tag;                  /* large tag = 0x82                   */
+    unsigned char Count0;               /* Length of string                   */
+    unsigned char Count1;
+    unsigned char Identifier[1];        /* a variable array of bytes,         */
+					/* count in tag                       */
+    } L2_Pack;
+
+  struct _L3_Pack{                      /* UNICODE ID STRING PACKET           */
+    unsigned char Tag;                  /* large tag = 0x83                   */
+    unsigned char Count0;               /* Length + 2 of string               */
+    unsigned char Count1;
+    unsigned char Country0;             /* TBD                                */
+    unsigned char Country1;             /* TBD                                */
+    unsigned char Identifier[1];        /* a variable array of bytes,         */
+					/* count in tag                       */
+    } L3_Pack;
+
+  struct _L4_Pack{                      /* VENDOR DEFINED PACKET              */
+    unsigned char Tag;                  /* large tag = 0x84                   */
+    unsigned char Count0;
+    unsigned char Count1;
+    union _L4_Data{
+      unsigned char Data[1];            /* a variable array of bytes,         */
+					/* count in tag                       */
+      struct _L4_PPCPack{               /* Pr*p L4 packet                     */
+	 unsigned char Type;            /* 00=non-IBM                         */
+	 unsigned char PPCData[1];      /* a variable array of bytes,         */
+					/* count in tag                       */
+	} L4_PPCPack;
+      } L4_Data;
+    } L4_Pack;
+
+  struct _L5_Pack{
+    unsigned char Tag;                  /* large tag = 0x85                   */
+    unsigned char Count0;               /* Count = 17                         */
+    unsigned char Count1;
+    unsigned char Data[17];
+    } L5_Pack;
+
+  struct _L6_Pack{
+    unsigned char Tag;                  /* large tag = 0x86                   */
+    unsigned char Count0;               /* Count = 9                          */
+    unsigned char Count1;
+    unsigned char Data[9];
+    } L6_Pack;
+
+  } PnP_TAG_PACKET;
+
+#endif /* __ASSEMBLY__ */
+#endif  /* ndef _PNP_ */
diff --git a/arch/powerpc/include/asm/posix_types.h b/arch/powerpc/include/asm/posix_types.h
new file mode 100644
index 0000000..9170728
--- /dev/null
+++ b/arch/powerpc/include/asm/posix_types.h
@@ -0,0 +1,109 @@
+#ifndef _PPC_POSIX_TYPES_H
+#define _PPC_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned int	__kernel_dev_t;
+typedef unsigned int	__kernel_ino_t;
+typedef unsigned int	__kernel_mode_t;
+typedef unsigned short	__kernel_nlink_t;
+typedef long		__kernel_off_t;
+typedef int		__kernel_pid_t;
+typedef unsigned int	__kernel_uid_t;
+typedef unsigned int	__kernel_gid_t;
+typedef unsigned int	__kernel_size_t;
+typedef int		__kernel_ssize_t;
+typedef long		__kernel_ptrdiff_t;
+typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
+typedef long		__kernel_clock_t;
+typedef int		__kernel_daddr_t;
+typedef char *		__kernel_caddr_t;
+typedef short             __kernel_ipc_pid_t;
+typedef unsigned short	__kernel_uid16_t;
+typedef unsigned short	__kernel_gid16_t;
+typedef unsigned int	__kernel_uid32_t;
+typedef unsigned int	__kernel_gid32_t;
+
+typedef unsigned int	__kernel_old_uid_t;
+typedef unsigned int	__kernel_old_gid_t;
+
+#ifdef __GNUC__
+typedef long long	__kernel_loff_t;
+#endif
+
+typedef struct {
+	int	val[2];
+} __kernel_fsid_t;
+
+#ifndef __GNUC__
+
+#define	__FD_SET(d, set)	((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
+#define	__FD_CLR(d, set)	((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
+#define	__FD_ISSET(d, set)	((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define	__FD_ZERO(set)	\
+  ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+
+#else /* __GNUC__ */
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \
+    || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
+/* With GNU C, use inline functions instead so args are evaluated only once: */
+
+#undef __FD_SET
+static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+}
+
+#undef __FD_CLR
+static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+}
+
+#undef __FD_ISSET
+static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant case (8 ints,
+ * for a 256-bit fd_set)
+ */
+#undef __FD_ZERO
+static __inline__ void __FD_ZERO(__kernel_fd_set *p)
+{
+	unsigned int *tmp = (unsigned int *)p->fds_bits;
+	int i;
+
+	if (__builtin_constant_p(__FDSET_LONGS)) {
+		switch (__FDSET_LONGS) {
+			case 8:
+				tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
+				tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
+				return;
+		}
+	}
+	i = __FDSET_LONGS;
+	while (i) {
+		i--;
+		*tmp = 0;
+		tmp++;
+	}
+}
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+#endif /* __GNUC__ */
+#endif /* _PPC_POSIX_TYPES_H */
diff --git a/arch/powerpc/include/asm/ppc4xx-ebc.h b/arch/powerpc/include/asm/ppc4xx-ebc.h
new file mode 100644
index 0000000..9c17e46
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx-ebc.h
@@ -0,0 +1,199 @@
+/*
+ * (C) Copyright 2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC4xx_EBC_H_
+#define _PPC4xx_EBC_H_
+
+/*
+ * Currently there are two register layout versions for the IBM EBC core
+ * used on 4xx PPC's. The following grouping lists the first layout.
+ * Within this group there is a slight variation concerning the bit field
+ * position of the EMPL and EMPH fields:
+ */
+#if defined(CONFIG_405CR) || defined(CONFIG_405GP) || \
+    defined(CONFIG_405EP) || \
+    defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#define CONFIG_EBC_PPC4xx_IBM_VER1
+#if defined(CONFIG_405CR) || defined(CONFIG_405GP) || \
+    defined(CONFIG_405EP)
+#define EBC_CFG_EMPH_POS	8
+#define EBC_CFG_EMPL_POS	6
+#else
+#define EBC_CFG_EMPH_POS	6
+#define EBC_CFG_EMPL_POS	8
+#endif
+#endif
+
+/*
+ * Define the max number of EBC banks (chip selects)
+ */
+#if defined(CONFIG_405CR) || defined(CONFIG_405GP) || \
+    defined(CONFIG_405EZ) || \
+    defined(CONFIG_440GP) || defined(CONFIG_440GX)
+#define EBC_NUM_BANKS	8
+#endif
+
+#if defined(CONFIG_405EP)
+#define EBC_NUM_BANKS	5
+#endif
+
+#if defined(CONFIG_405EX) || \
+    defined(CONFIG_460SX)
+#define EBC_NUM_BANKS	4
+#endif
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define EBC_NUM_BANKS	6
+#endif
+
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+#define EBC_NUM_BANKS	3
+#endif
+
+/* Bank Configuration Register */
+#define EBC_BXCR(n)		(n)
+#define EBC_BXCR_BANK_SIZE(n)	(0x100000 << (((n) & EBC_BXCR_BS_MASK) >> 17))
+
+#define	EBC_BXCR_BAS_MASK	PPC_REG_VAL(11, 0xFFF)
+#define EBC_BXCR_BAS_ENCODE(n)	(((static_cast(u32, n)) & EBC_BXCR_BAS_MASK))
+#define EBC_BXCR_BS_MASK	PPC_REG_VAL(14, 0x7)
+#define EBC_BXCR_BS_1MB		PPC_REG_VAL(14, 0x0)
+#define EBC_BXCR_BS_2MB		PPC_REG_VAL(14, 0x1)
+#define EBC_BXCR_BS_4MB		PPC_REG_VAL(14, 0x2)
+#define EBC_BXCR_BS_8MB		PPC_REG_VAL(14, 0x3)
+#define EBC_BXCR_BS_16MB	PPC_REG_VAL(14, 0x4)
+#define EBC_BXCR_BS_32MB	PPC_REG_VAL(14, 0x5)
+#define EBC_BXCR_BS_64MB	PPC_REG_VAL(14, 0x6)
+#define EBC_BXCR_BS_128MB	PPC_REG_VAL(14, 0x7)
+#define EBC_BXCR_BU_MASK	PPC_REG_VAL(16, 0x3)
+#define	EBC_BXCR_BU_NONE	PPC_REG_VAL(16, 0x0)
+#define EBC_BXCR_BU_R		PPC_REG_VAL(16, 0x1)
+#define EBC_BXCR_BU_W		PPC_REG_VAL(16, 0x2)
+#define EBC_BXCR_BU_RW		PPC_REG_VAL(16, 0x3)
+#define EBC_BXCR_BW_MASK	PPC_REG_VAL(18, 0x3)
+#define EBC_BXCR_BW_8BIT	PPC_REG_VAL(18, 0x0)
+#define EBC_BXCR_BW_16BIT	PPC_REG_VAL(18, 0x1)
+#if defined(CONFIG_EBC_PPC4xx_IBM_VER1)
+#define EBC_BXCR_BW_32BIT	PPC_REG_VAL(18, 0x2)
+#else
+#define EBC_BXCR_BW_32BIT	PPC_REG_VAL(18, 0x3)
+#endif
+
+/* Bank Access Parameter Register */
+#define EBC_BXAP_BME_ENABLED	PPC_REG_VAL(0, 0x1)
+#define EBC_BXAP_BME_DISABLED	PPC_REG_VAL(0, 0x0)
+#define EBC_BXAP_TWT_ENCODE(n)	PPC_REG_VAL(8, (static_cast(u32, n)) & 0xFF)
+#define	EBC_BXAP_FWT_ENCODE(n)	PPC_REG_VAL(5, (static_cast(u32, n)) & 0x1F)
+#define	EBC_BXAP_BWT_ENCODE(n)	PPC_REG_VAL(8, (static_cast(u32, n)) & 0x7)
+#define EBC_BXAP_BCE_DISABLE	PPC_REG_VAL(9, 0x0)
+#define EBC_BXAP_BCE_ENABLE	PPC_REG_VAL(9, 0x1)
+#define EBC_BXAP_BCT_MASK	PPC_REG_VAL(11, 0x3)
+#define EBC_BXAP_BCT_2TRANS	PPC_REG_VAL(11, 0x0)
+#define EBC_BXAP_BCT_4TRANS	PPC_REG_VAL(11, 0x1)
+#define EBC_BXAP_BCT_8TRANS	PPC_REG_VAL(11, 0x2)
+#define EBC_BXAP_BCT_16TRANS	PPC_REG_VAL(11, 0x3)
+#define EBC_BXAP_CSN_ENCODE(n)	PPC_REG_VAL(13, (static_cast(u32, n)) & 0x3)
+#define EBC_BXAP_OEN_ENCODE(n)	PPC_REG_VAL(15, (static_cast(u32, n)) & 0x3)
+#define EBC_BXAP_WBN_ENCODE(n)	PPC_REG_VAL(17, (static_cast(u32, n)) & 0x3)
+#define EBC_BXAP_WBF_ENCODE(n)	PPC_REG_VAL(19, (static_cast(u32, n)) & 0x3)
+#define EBC_BXAP_TH_ENCODE(n)	PPC_REG_VAL(22, (static_cast(u32, n)) & 0x7)
+#define EBC_BXAP_RE_ENABLED	PPC_REG_VAL(23, 0x1)
+#define EBC_BXAP_RE_DISABLED	PPC_REG_VAL(23, 0x0)
+#define EBC_BXAP_SOR_DELAYED	PPC_REG_VAL(24, 0x0)
+#define EBC_BXAP_SOR_NONDELAYED	PPC_REG_VAL(24, 0x1)
+#define EBC_BXAP_BEM_WRITEONLY	PPC_REG_VAL(25, 0x0)
+#define EBC_BXAP_BEM_RW		PPC_REG_VAL(25, 0x1)
+#define EBC_BXAP_PEN_DISABLED	PPC_REG_VAL(26, 0x0)
+#define EBC_BXAP_PEN_ENABLED	PPC_REG_VAL(26, 0x1)
+
+/* Common fields in EBC0_CFG register */
+#define EBC_CFG_PTD_MASK	PPC_REG_VAL(1, 0x1)
+#define EBC_CFG_PTD_ENABLE	PPC_REG_VAL(1, 0x0)
+#define EBC_CFG_PTD_DISABLE	PPC_REG_VAL(1, 0x1)
+#define EBC_CFG_RTC_MASK	PPC_REG_VAL(4, 0x7)
+#define EBC_CFG_RTC_16PERCLK	PPC_REG_VAL(4, 0x0)
+#define EBC_CFG_RTC_32PERCLK	PPC_REG_VAL(4, 0x1)
+#define EBC_CFG_RTC_64PERCLK	PPC_REG_VAL(4, 0x2)
+#define EBC_CFG_RTC_128PERCLK	PPC_REG_VAL(4, 0x3)
+#define EBC_CFG_RTC_256PERCLK	PPC_REG_VAL(4, 0x4)
+#define EBC_CFG_RTC_512PERCLK	PPC_REG_VAL(4, 0x5)
+#define EBC_CFG_RTC_1024PERCLK	PPC_REG_VAL(4, 0x6)
+#define EBC_CFG_RTC_2048PERCLK	PPC_REG_VAL(4, 0x7)
+#define EBC_CFG_PME_MASK	PPC_REG_VAL(14, 0x1)
+#define EBC_CFG_PME_DISABLE	PPC_REG_VAL(14, 0x0)
+#define EBC_CFG_PME_ENABLE	PPC_REG_VAL(14, 0x1)
+#define EBC_CFG_PMT_MASK	PPC_REG_VAL(19, 0x1F)
+#define EBC_CFG_PMT_ENCODE(n)	PPC_REG_VAL(19, (static_cast(u32, n)) & 0x1F)
+
+/* Now the two versions of the other bits */
+#if defined(CONFIG_EBC_PPC4xx_IBM_VER1)
+#define EBC_CFG_EBTC_MASK	PPC_REG_VAL(0, 0x1)
+#define EBC_CFG_EBTC_HI		PPC_REG_VAL(0, 0x0)
+#define EBC_CFG_EBTC_DRIVEN	PPC_REG_VAL(0, 0x1)
+#define EBC_CFG_EMPH_MASK	PPC_REG_VAL(EBC_CFG_EMPH_POS, 0x3)
+#define EBC_CFG_EMPH_ENCODE(n)	PPC_REG_VAL(EBC_CFG_EMPH_POS, \
+						(static_cast(u32, n)) & 0x3)
+#define EBC_CFG_EMPL_MASK	PPC_REG_VAL(EBC_CFG_EMPL_POS, 0x3)
+#define EBC_CFG_EMPL_ENCODE(n)	PPC_REG_VAL(EBC_CFG_EMPH_POS, \
+						(static_cast(u32, n)) & 0x3)
+#define EBC_CFG_CSTC_MASK	PPC_REG_VAL(9, 0x1)
+#define EBC_CFG_CSTC_HI		PPC_REG_VAL(9, 0x0)
+#define EBC_CFG_CSTC_DRIVEN	PPC_REG_VAL(9, 0x1)
+#define EBC_CFG_BPR_MASK	PPC_REG_VAL(11, 0x3)
+#define EBC_CFG_BPR_1DW		PPC_REG_VAL(11, 0x0)
+#define EBC_CFG_BPR_2DW		PPC_REG_VAL(11, 0x1)
+#define EBC_CFG_BPR_4DW		PPC_REG_VAL(11, 0x2)
+#define EBC_CFG_EMS_MASK	PPC_REG_VAL(13, 0x3)
+#define EBC_CFG_EMS_8BIT	PPC_REG_VAL(13, 0x0)
+#define EBC_CFG_EMS_16BIT	PPC_REG_VAL(13, 0x1)
+#define EBC_CFG_EMS_32BIT	PPC_REG_VAL(13, 0x2)
+#else
+#define EBC_CFG_LE_MASK		PPC_REG_VAL(0, 0x1)
+#define EBC_CFG_LE_UNLOCK	PPC_REG_VAL(0, 0x0)
+#define EBC_CFG_LE_LOCK		PPC_REG_VAL(0, 0x1)
+#define EBC_CFG_ATC_MASK	PPC_REG_VAL(5, 0x1)
+#define EBC_CFG_ATC_HI		PPC_REG_VAL(5, 0x0)
+#define EBC_CFG_ATC_PREVIOUS	PPC_REG_VAL(5, 0x1)
+#define EBC_CFG_DTC_MASK	PPC_REG_VAL(6, 0x1)
+#define EBC_CFG_DTC_HI		PPC_REG_VAL(6, 0x0)
+#define EBC_CFG_DTC_PREVIOUS	PPC_REG_VAL(6, 0x1)
+#define EBC_CFG_CTC_MASK	PPC_REG_VAL(7, 0x1)
+#define EBC_CFG_CTC_HI		PPC_REG_VAL(7, 0x0)
+#define EBC_CFG_CTC_PREVIOUS	PPC_REG_VAL(7, 0x1)
+#define EBC_CFG_OEO_MASK	PPC_REG_VAL(8, 0x1)
+#define EBC_CFG_OEO_HI		PPC_REG_VAL(8, 0x0)
+#define EBC_CFG_OEO_PREVIOUS	PPC_REG_VAL(8, 0x1)
+#define EBC_CFG_EMC_MASK	PPC_REG_VAL(9, 0x1)
+#define EBC_CFG_EMC_NONDEFAULT	PPC_REG_VAL(9, 0x0)
+#define EBC_CFG_EMC_DEFAULT	PPC_REG_VAL(9, 0x1)
+#define EBC_CFG_PR_MASK		PPC_REG_VAL(21, 0x3)
+#define EBC_CFG_PR_16		PPC_REG_VAL(21, 0x0)
+#define EBC_CFG_PR_32		PPC_REG_VAL(21, 0x1)
+#define EBC_CFG_PR_64		PPC_REG_VAL(21, 0x2)
+#define EBC_CFG_PR_128		PPC_REG_VAL(21, 0x3)
+#endif
+
+#endif /* _PPC4xx_EBC_H_ */
diff --git a/arch/powerpc/include/asm/ppc4xx-isram.h b/arch/powerpc/include/asm/ppc4xx-isram.h
new file mode 100644
index 0000000..d6d17ac
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx-isram.h
@@ -0,0 +1,75 @@
+
+/*
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC4xx_ISRAM_H_
+#define _PPC4xx_ISRAM_H_
+
+/*
+ * Internal SRAM
+ */
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#define ISRAM0_DCR_BASE 0x380
+#else
+#define ISRAM0_DCR_BASE 0x020
+#endif
+#define ISRAM0_SB0CR	(ISRAM0_DCR_BASE+0x00)	/* SRAM bank config 0*/
+#define ISRAM0_SB1CR	(ISRAM0_DCR_BASE+0x01)	/* SRAM bank config 1*/
+#define ISRAM0_SB2CR	(ISRAM0_DCR_BASE+0x02)	/* SRAM bank config 2*/
+#define ISRAM0_SB3CR	(ISRAM0_DCR_BASE+0x03)	/* SRAM bank config 3*/
+#define ISRAM0_BEAR	(ISRAM0_DCR_BASE+0x04)	/* SRAM bus error addr reg */
+#define ISRAM0_BESR0	(ISRAM0_DCR_BASE+0x05)	/* SRAM bus error status reg 0 */
+#define ISRAM0_BESR1	(ISRAM0_DCR_BASE+0x06)	/* SRAM bus error status reg 1 */
+#define ISRAM0_PMEG	(ISRAM0_DCR_BASE+0x07)	/* SRAM power management */
+#define ISRAM0_CID	(ISRAM0_DCR_BASE+0x08)	/* SRAM bus core id reg */
+#define ISRAM0_REVID	(ISRAM0_DCR_BASE+0x09)	/* SRAM bus revision id reg */
+#define ISRAM0_DPC	(ISRAM0_DCR_BASE+0x0a)	/* SRAM data parity check reg */
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define ISRAM1_DCR_BASE 0x0B0
+#define ISRAM1_SB0CR	(ISRAM1_DCR_BASE+0x00)	/* SRAM1 bank config 0*/
+#define ISRAM1_BEAR	(ISRAM1_DCR_BASE+0x04)	/* SRAM1 bus error addr reg */
+#define ISRAM1_BESR0	(ISRAM1_DCR_BASE+0x05)	/* SRAM1 bus error status reg 0 */
+#define ISRAM1_BESR1	(ISRAM1_DCR_BASE+0x06)	/* SRAM1 bus error status reg 1 */
+#define ISRAM1_PMEG	(ISRAM1_DCR_BASE+0x07)	/* SRAM1 power management */
+#define ISRAM1_CID	(ISRAM1_DCR_BASE+0x08)	/* SRAM1 bus core id reg */
+#define ISRAM1_REVID	(ISRAM1_DCR_BASE+0x09)	/* SRAM1 bus revision id reg */
+#define ISRAM1_DPC	(ISRAM1_DCR_BASE+0x0a)	/* SRAM1 data parity check reg */
+#endif /* CONFIG_460EX || CONFIG_460GT */
+
+/*
+ * L2 Cache
+ */
+#if defined (CONFIG_440GX) || \
+    defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+    defined(CONFIG_460SX)
+#define L2_CACHE_BASE	0x030
+#define L2_CACHE_CFG	(L2_CACHE_BASE+0x00)	/* L2 Cache Config      */
+#define L2_CACHE_CMD	(L2_CACHE_BASE+0x01)	/* L2 Cache Command     */
+#define L2_CACHE_ADDR	(L2_CACHE_BASE+0x02)	/* L2 Cache Address     */
+#define L2_CACHE_DATA	(L2_CACHE_BASE+0x03)	/* L2 Cache Data        */
+#define L2_CACHE_STAT	(L2_CACHE_BASE+0x04)	/* L2 Cache Status      */
+#define L2_CACHE_CVER	(L2_CACHE_BASE+0x05)	/* L2 Cache Revision ID */
+#define L2_CACHE_SNP0	(L2_CACHE_BASE+0x06)	/* L2 Cache Snoop reg 0 */
+#define L2_CACHE_SNP1	(L2_CACHE_BASE+0x07)	/* L2 Cache Snoop reg 1 */
+#endif /* CONFIG_440GX */
+
+#endif /* _PPC4xx_ISRAM_H_ */
diff --git a/arch/powerpc/include/asm/ppc4xx-sdram.h b/arch/powerpc/include/asm/ppc4xx-sdram.h
new file mode 100644
index 0000000..92be514
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx-sdram.h
@@ -0,0 +1,1411 @@
+/*
+ * (C) Copyright 2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC4xx_SDRAM_H_
+#define _PPC4xx_SDRAM_H_
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_SDRAM)
+
+/*
+ * SDRAM Controller
+ */
+
+#ifndef CONFIG_405EP
+#define SDRAM0_BESR0	0x00	/* bus error syndrome reg a		*/
+#define SDRAM0_BESRS0	0x04	/* bus error syndrome reg set a		*/
+#define SDRAM0_BESR1	0x08	/* bus error syndrome reg b		*/
+#define SDRAM0_BESRS1	0x0c	/* bus error syndrome reg set b		*/
+#define SDRAM0_BEAR	0x10	/* bus error address reg		*/
+#endif
+#define SDRAM0_CFG	0x20	/* memory controller options 1		*/
+#define SDRAM0_STATUS	0x24	/* memory status			*/
+#define SDRAM0_RTR	0x30	/* refresh timer reg			*/
+#define SDRAM0_PMIT	0x34	/* power management idle timer		*/
+#define SDRAM0_B0CR	0x40	/* memory bank 0 configuration		*/
+#define SDRAM0_B1CR	0x44	/* memory bank 1 configuration		*/
+#ifndef CONFIG_405EP
+#define SDRAM0_B2CR	0x48	/* memory bank 2 configuration		*/
+#define SDRAM0_B3CR	0x4c	/* memory bank 3 configuration		*/
+#endif
+#define SDRAM0_TR	0x80	/* timing reg 1				*/
+#ifndef CONFIG_405EP
+#define SDRAM0_ECCCFG	0x94	/* ECC configuration			*/
+#define SDRAM0_ECCESR	0x98	/* ECC error status			*/
+#endif
+
+#endif /* CONFIG_SDRAM_PPC4xx_IBM_SDRAM */
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)
+
+/*
+ * Memory controller registers
+ */
+#define SDRAM_CFG0	0x20	/* memory controller options 0		*/
+#define SDRAM_CFG1	0x21	/* memory controller options 1		*/
+
+#define SDRAM0_BEAR	0x0010	/* bus error address reg		*/
+#define SDRAM0_SLIO	0x0018	/* ddr sdram slave interface options	*/
+#define SDRAM0_CFG0	0x0020	/* ddr sdram options 0			*/
+#define SDRAM0_CFG1	0x0021	/* ddr sdram options 1			*/
+#define SDRAM0_DEVOPT	0x0022	/* ddr sdram device options		*/
+#define SDRAM0_MCSTS	0x0024	/* memory controller status		*/
+#define SDRAM0_RTR	0x0030	/* refresh timer register		*/
+#define SDRAM0_PMIT	0x0034	/* power management idle timer		*/
+#define SDRAM0_UABBA	0x0038	/* plb UABus base address		*/
+#define SDRAM0_B0CR	0x0040	/* ddr sdram bank 0 configuration	*/
+#define SDRAM0_B1CR	0x0044	/* ddr sdram bank 1 configuration	*/
+#define SDRAM0_B2CR	0x0048	/* ddr sdram bank 2 configuration	*/
+#define SDRAM0_B3CR	0x004c	/* ddr sdram bank 3 configuration	*/
+#define SDRAM0_TR0	0x0080	/* sdram timing register 0		*/
+#define SDRAM0_TR1	0x0081	/* sdram timing register 1		*/
+#define SDRAM0_CLKTR	0x0082	/* ddr clock timing register		*/
+#define SDRAM0_WDDCTR	0x0083	/* write data/dm/dqs clock timing reg	*/
+#define SDRAM0_DLYCAL	0x0084	/* delay line calibration register	*/
+#define SDRAM0_ECCESR	0x0098	/* ECC error status			*/
+
+/*
+ * Memory Controller Options 0
+ */
+#define SDRAM_CFG0_DCEN		0x80000000	/* SDRAM Controller Enable	*/
+#define SDRAM_CFG0_MCHK_MASK	0x30000000	/* Memory data errchecking mask */
+#define SDRAM_CFG0_MCHK_NON	0x00000000	/* No ECC generation		*/
+#define SDRAM_CFG0_MCHK_GEN	0x20000000	/* ECC generation		*/
+#define SDRAM_CFG0_MCHK_CHK	0x30000000	/* ECC generation and checking	*/
+#define SDRAM_CFG0_RDEN		0x08000000	/* Registered DIMM enable	*/
+#define SDRAM_CFG0_PMUD		0x04000000	/* Page management unit		*/
+#define SDRAM_CFG0_DMWD_MASK	0x02000000	/* DRAM width mask		*/
+#define SDRAM_CFG0_DMWD_32	0x00000000	/* 32 bits			*/
+#define SDRAM_CFG0_DMWD_64	0x02000000	/* 64 bits			*/
+#define SDRAM_CFG0_UIOS_MASK	0x00C00000	/* Unused IO State		*/
+#define SDRAM_CFG0_PDP		0x00200000	/* Page deallocation policy	*/
+
+/*
+ * Memory Controller Options 1
+ */
+#define SDRAM_CFG1_SRE		0x80000000	/* Self-Refresh Entry		*/
+#define SDRAM_CFG1_PMEN		0x40000000	/* Power Management Enable	*/
+
+/*
+ * SDRAM DEVPOT Options
+ */
+#define SDRAM_DEVOPT_DLL	0x80000000
+#define SDRAM_DEVOPT_DS		0x40000000
+
+/*
+ * SDRAM MCSTS Options
+ */
+#define SDRAM_MCSTS_MRSC	0x80000000
+#define SDRAM_MCSTS_SRMS	0x40000000
+#define SDRAM_MCSTS_CIS		0x20000000
+#define SDRAM_MCSTS_IDLE_NOT	0x00000000	/* Mem contr not idle		*/
+
+/*
+ * SDRAM Refresh Timer Register
+ */
+#define SDRAM_RTR_RINT_MASK	  0xFFFF0000
+#define SDRAM_RTR_RINT_ENCODE(n)  (((n) << 16) & SDRAM_RTR_RINT_MASK)
+
+/*
+ * SDRAM UABus Base Address Reg
+ */
+#define SDRAM_UABBA_UBBA_MASK	0x0000000F
+
+/*
+ * Memory Bank 0-7 configuration
+ */
+#define SDRAM_BXCR_SDBA_MASK	0xff800000	  /* Base address	      */
+#define SDRAM_BXCR_SDSZ_MASK	0x000e0000	  /* Size		      */
+#define SDRAM_BXCR_SDSZ_8	0x00020000	  /*   8M		      */
+#define SDRAM_BXCR_SDSZ_16	0x00040000	  /*  16M		      */
+#define SDRAM_BXCR_SDSZ_32	0x00060000	  /*  32M		      */
+#define SDRAM_BXCR_SDSZ_64	0x00080000	  /*  64M		      */
+#define SDRAM_BXCR_SDSZ_128	0x000a0000	  /* 128M		      */
+#define SDRAM_BXCR_SDSZ_256	0x000c0000	  /* 256M		      */
+#define SDRAM_BXCR_SDSZ_512	0x000e0000	  /* 512M		      */
+#define SDRAM_BXCR_SDAM_MASK	0x0000e000	  /* Addressing mode	      */
+#define SDRAM_BXCR_SDAM_1	0x00000000	  /*   Mode 1		      */
+#define SDRAM_BXCR_SDAM_2	0x00002000	  /*   Mode 2		      */
+#define SDRAM_BXCR_SDAM_3	0x00004000	  /*   Mode 3		      */
+#define SDRAM_BXCR_SDAM_4	0x00006000	  /*   Mode 4		      */
+#define SDRAM_BXCR_SDBE		0x00000001	  /* Memory Bank Enable	      */
+
+/*
+ * SDRAM TR0 Options
+ */
+#define SDRAM_TR0_SDWR_MASK	0x80000000
+#define	 SDRAM_TR0_SDWR_2_CLK	0x00000000
+#define	 SDRAM_TR0_SDWR_3_CLK	0x80000000
+#define SDRAM_TR0_SDWD_MASK	0x40000000
+#define	 SDRAM_TR0_SDWD_0_CLK	0x00000000
+#define	 SDRAM_TR0_SDWD_1_CLK	0x40000000
+#define SDRAM_TR0_SDCL_MASK	0x01800000
+#define	 SDRAM_TR0_SDCL_2_0_CLK 0x00800000
+#define	 SDRAM_TR0_SDCL_2_5_CLK 0x01000000
+#define	 SDRAM_TR0_SDCL_3_0_CLK 0x01800000
+#define SDRAM_TR0_SDPA_MASK	0x000C0000
+#define	 SDRAM_TR0_SDPA_2_CLK	0x00040000
+#define	 SDRAM_TR0_SDPA_3_CLK	0x00080000
+#define	 SDRAM_TR0_SDPA_4_CLK	0x000C0000
+#define SDRAM_TR0_SDCP_MASK	0x00030000
+#define	 SDRAM_TR0_SDCP_2_CLK	0x00000000
+#define	 SDRAM_TR0_SDCP_3_CLK	0x00010000
+#define	 SDRAM_TR0_SDCP_4_CLK	0x00020000
+#define	 SDRAM_TR0_SDCP_5_CLK	0x00030000
+#define SDRAM_TR0_SDLD_MASK	0x0000C000
+#define	 SDRAM_TR0_SDLD_1_CLK	0x00000000
+#define	 SDRAM_TR0_SDLD_2_CLK	0x00004000
+#define SDRAM_TR0_SDRA_MASK	0x0000001C
+#define	 SDRAM_TR0_SDRA_6_CLK	0x00000000
+#define	 SDRAM_TR0_SDRA_7_CLK	0x00000004
+#define	 SDRAM_TR0_SDRA_8_CLK	0x00000008
+#define	 SDRAM_TR0_SDRA_9_CLK	0x0000000C
+#define	 SDRAM_TR0_SDRA_10_CLK	0x00000010
+#define	 SDRAM_TR0_SDRA_11_CLK	0x00000014
+#define	 SDRAM_TR0_SDRA_12_CLK	0x00000018
+#define	 SDRAM_TR0_SDRA_13_CLK	0x0000001C
+#define SDRAM_TR0_SDRD_MASK	0x00000003
+#define	 SDRAM_TR0_SDRD_2_CLK	0x00000001
+#define	 SDRAM_TR0_SDRD_3_CLK	0x00000002
+#define	 SDRAM_TR0_SDRD_4_CLK	0x00000003
+
+/*
+ * SDRAM TR1 Options
+ */
+#define SDRAM_TR1_RDSS_MASK	0xC0000000
+#define	 SDRAM_TR1_RDSS_TR0	0x00000000
+#define	 SDRAM_TR1_RDSS_TR1	0x40000000
+#define	 SDRAM_TR1_RDSS_TR2	0x80000000
+#define	 SDRAM_TR1_RDSS_TR3	0xC0000000
+#define SDRAM_TR1_RDSL_MASK	0x00C00000
+#define	 SDRAM_TR1_RDSL_STAGE1	0x00000000
+#define	 SDRAM_TR1_RDSL_STAGE2	0x00400000
+#define	 SDRAM_TR1_RDSL_STAGE3	0x00800000
+#define SDRAM_TR1_RDCD_MASK	0x00000800
+#define	 SDRAM_TR1_RDCD_RCD_0_0 0x00000000
+#define	 SDRAM_TR1_RDCD_RCD_1_2 0x00000800
+#define SDRAM_TR1_RDCT_MASK	0x000001FF
+#define	 SDRAM_TR1_RDCT_ENCODE(x)  (((x) << 0) & SDRAM_TR1_RDCT_MASK)
+#define	 SDRAM_TR1_RDCT_DECODE(x)  (((x) & SDRAM_TR1_RDCT_MASK) >> 0)
+#define	 SDRAM_TR1_RDCT_MIN	0x00000000
+#define	 SDRAM_TR1_RDCT_MAX	0x000001FF
+
+/*
+ * SDRAM WDDCTR Options
+ */
+#define SDRAM_WDDCTR_WRCP_MASK	0xC0000000
+#define	 SDRAM_WDDCTR_WRCP_0DEG	  0x00000000
+#define	 SDRAM_WDDCTR_WRCP_90DEG  0x40000000
+#define	 SDRAM_WDDCTR_WRCP_180DEG 0x80000000
+#define SDRAM_WDDCTR_DCD_MASK	0x000001FF
+
+/*
+ * SDRAM CLKTR Options
+ */
+#define SDRAM_CLKTR_CLKP_MASK	0xC0000000
+#define	 SDRAM_CLKTR_CLKP_0DEG	  0x00000000
+#define	 SDRAM_CLKTR_CLKP_90DEG	  0x40000000
+#define	 SDRAM_CLKTR_CLKP_180DEG  0x80000000
+#define SDRAM_CLKTR_DCDT_MASK	0x000001FF
+
+/*
+ * SDRAM DLYCAL Options
+ */
+#define SDRAM_DLYCAL_DLCV_MASK	0x000003FC
+#define	 SDRAM_DLYCAL_DLCV_ENCODE(x) (((x)<<2) & SDRAM_DLYCAL_DLCV_MASK)
+#define	 SDRAM_DLYCAL_DLCV_DECODE(x) (((x) & SDRAM_DLYCAL_DLCV_MASK)>>2)
+
+#endif /* CONFIG_SDRAM_PPC4xx_IBM_DDR */
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
+
+#define SDRAM_DLYCAL_DLCV_MASK		0x000003FC
+#define SDRAM_DLYCAL_DLCV_ENCODE(x)	(((x)<<2) & SDRAM_DLYCAL_DLCV_MASK)
+#define SDRAM_DLYCAL_DLCV_DECODE(x)	(((x) & SDRAM_DLYCAL_DLCV_MASK)>>2)
+
+#if !defined(CONFIG_405EX)
+/*
+ * Memory queue defines
+ */
+#define SDRAMQ_DCR_BASE 0x040
+
+#define SDRAM_R0BAS		(SDRAMQ_DCR_BASE+0x0)	/* rank 0 base address & size  */
+#define SDRAM_R1BAS		(SDRAMQ_DCR_BASE+0x1)	/* rank 1 base address & size  */
+#define SDRAM_R2BAS		(SDRAMQ_DCR_BASE+0x2)	/* rank 2 base address & size  */
+#define SDRAM_R3BAS		(SDRAMQ_DCR_BASE+0x3)	/* rank 3 base address & size  */
+#define SDRAM_CONF1HB		(SDRAMQ_DCR_BASE+0x5)	/* configuration 1 HB          */
+#define SDRAM_CONF1HB_AAFR	0x80000000	/* Address Ack on First Request - Bit 0 */
+#define SDRAM_CONF1HB_PRPD	0x00080000	/* PLB Read pipeline Disable - Bit 12 */
+#define SDRAM_CONF1HB_PWPD	0x00040000	/* PLB Write pipeline Disable - Bit 13 */
+#define SDRAM_CONF1HB_PRW	0x00020000	/* PLB Read Wait - Bit 14 */
+#define SDRAM_CONF1HB_RPLM	0x00001000	/* Read Passing Limit 1 - Bits 16..19 */
+#define SDRAM_CONF1HB_RPEN	0x00000800	/* Read Passing Enable - Bit 20 */
+#define SDRAM_CONF1HB_RFTE	0x00000400	/* Read Flow Through Enable - Bit 21 */
+#define SDRAM_CONF1HB_WRCL	0x00000080	/* MCIF Cycle Limit 1 - Bits 22..24 */
+#define SDRAM_CONF1HB_MASK	0x0000F380	/* RPLM & WRCL mask */
+
+#define SDRAM_ERRSTATHB		(SDRAMQ_DCR_BASE+0x7)	/* error status HB             */
+#define SDRAM_ERRADDUHB		(SDRAMQ_DCR_BASE+0x8)	/* error address upper 32 HB   */
+#define SDRAM_ERRADDLHB		(SDRAMQ_DCR_BASE+0x9)	/* error address lower 32 HB   */
+#define SDRAM_PLBADDULL		(SDRAMQ_DCR_BASE+0xA)	/* PLB base address upper 32 LL */
+#define SDRAM_CONF1LL		(SDRAMQ_DCR_BASE+0xB)	/* configuration 1 LL          */
+#define SDRAM_CONF1LL_AAFR	0x80000000		/* Address Ack on First Request - Bit 0 */
+#define SDRAM_CONF1LL_PRPD	0x00080000		/* PLB Read pipeline Disable - Bit 12 */
+#define SDRAM_CONF1LL_PWPD	0x00040000		/* PLB Write pipeline Disable - Bit 13 */
+#define SDRAM_CONF1LL_PRW	0x00020000		/* PLB Read Wait - Bit 14 */
+#define SDRAM_CONF1LL_RPLM	0x00001000		/* Read Passing Limit 1 - Bits 16..19 */
+#define SDRAM_CONF1LL_RPEN	0x00000800		/* Read Passing Enable - Bit 20 */
+#define SDRAM_CONF1LL_RFTE	0x00000400		/* Read Flow Through Enable - Bit 21 */
+#define SDRAM_CONF1LL_MASK	0x0000F000		/* RPLM mask */
+
+#define SDRAM_ERRSTATLL		(SDRAMQ_DCR_BASE+0xC)	/* error status LL             */
+#define SDRAM_ERRADDULL		(SDRAMQ_DCR_BASE+0xD)	/* error address upper 32 LL   */
+#define SDRAM_ERRADDLLL		(SDRAMQ_DCR_BASE+0xE)	/* error address lower 32 LL   */
+#define SDRAM_CONFPATHB		(SDRAMQ_DCR_BASE+0xF)	/* configuration between paths */
+#define SDRAM_CONFPATHB_TPEN	0x08000000		/* Transaction Passing Enable - Bit 4 */
+
+#define SDRAM_PLBADDUHB		(SDRAMQ_DCR_BASE+0x10)  /* PLB base address upper 32 LL */
+
+/*
+ * Memory Bank 0-7 configuration
+ */
+#if defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+    defined(CONFIG_460SX)
+#define SDRAM_RXBAS_SDBA_MASK		0xFFE00000	/* Base address	*/
+#define SDRAM_RXBAS_SDBA_ENCODE(n)	((u32)(((phys_size_t)(n) >> 2) & 0xFFE00000))
+#define SDRAM_RXBAS_SDBA_DECODE(n)	((((phys_size_t)(n)) & 0xFFE00000) << 2)
+#endif /* CONFIG_440SPE */
+#if defined(CONFIG_440SP)
+#define SDRAM_RXBAS_SDBA_MASK		0xFF800000	/* Base address	*/
+#define SDRAM_RXBAS_SDBA_ENCODE(n)	((((u32)(n))&0xFF800000))
+#define SDRAM_RXBAS_SDBA_DECODE(n)	((((u32)(n))&0xFF800000))
+#endif /* CONFIG_440SP */
+#define SDRAM_RXBAS_SDSZ_MASK		0x0000FFC0	/* Size		*/
+#define SDRAM_RXBAS_SDSZ_ENCODE(n)	((((u32)(n))&0x3FF)<<6)
+#define SDRAM_RXBAS_SDSZ_DECODE(n)	((((u32)(n))>>6)&0x3FF)
+#define SDRAM_RXBAS_SDSZ_0		0x00000000	/*   0M		*/
+#define SDRAM_RXBAS_SDSZ_8		0x0000FFC0	/*   8M		*/
+#define SDRAM_RXBAS_SDSZ_16		0x0000FF80	/*  16M		*/
+#define SDRAM_RXBAS_SDSZ_32		0x0000FF00	/*  32M		*/
+#define SDRAM_RXBAS_SDSZ_64		0x0000FE00	/*  64M		*/
+#define SDRAM_RXBAS_SDSZ_128		0x0000FC00	/* 128M		*/
+#define SDRAM_RXBAS_SDSZ_256		0x0000F800	/* 256M		*/
+#define SDRAM_RXBAS_SDSZ_512		0x0000F000	/* 512M		*/
+#define SDRAM_RXBAS_SDSZ_1024		0x0000E000	/* 1024M	*/
+#define SDRAM_RXBAS_SDSZ_2048		0x0000C000	/* 2048M	*/
+#define SDRAM_RXBAS_SDSZ_4096		0x00008000	/* 4096M	*/
+#else /* CONFIG_405EX */
+/*
+ * XXX - ToDo:
+ * Revisit this file to check if all these 405EX defines are correct and
+ * can be used in the common 44x_spd_ddr2 code as well. sr, 2008-06-02
+ */
+#define SDRAM_RXBAS_SDSZ_MASK		PPC_REG_VAL(19, 0xF)
+#define SDRAM_RXBAS_SDSZ_4MB	   	PPC_REG_VAL(19, 0x0)
+#define SDRAM_RXBAS_SDSZ_8MB	   	PPC_REG_VAL(19, 0x1)
+#define SDRAM_RXBAS_SDSZ_16MB	   	PPC_REG_VAL(19, 0x2)
+#define SDRAM_RXBAS_SDSZ_32MB	   	PPC_REG_VAL(19, 0x3)
+#define SDRAM_RXBAS_SDSZ_64MB	   	PPC_REG_VAL(19, 0x4)
+#define SDRAM_RXBAS_SDSZ_128MB	   	PPC_REG_VAL(19, 0x5)
+#define SDRAM_RXBAS_SDSZ_256MB	   	PPC_REG_VAL(19, 0x6)
+#define SDRAM_RXBAS_SDSZ_512MB	   	PPC_REG_VAL(19, 0x7)
+#define SDRAM_RXBAS_SDSZ_1024MB	   	PPC_REG_VAL(19, 0x8)
+#define SDRAM_RXBAS_SDSZ_2048MB	   	PPC_REG_VAL(19, 0x9)
+#define SDRAM_RXBAS_SDSZ_4096MB		PPC_REG_VAL(19, 0xA)
+#define SDRAM_RXBAS_SDSZ_8192MB		PPC_REG_VAL(19, 0xB)
+#define SDRAM_RXBAS_SDSZ_8      	SDRAM_RXBAS_SDSZ_8MB
+#define SDRAM_RXBAS_SDSZ_16     	SDRAM_RXBAS_SDSZ_16MB
+#define SDRAM_RXBAS_SDSZ_32     	SDRAM_RXBAS_SDSZ_32MB
+#define SDRAM_RXBAS_SDSZ_64     	SDRAM_RXBAS_SDSZ_64MB
+#define SDRAM_RXBAS_SDSZ_128    	SDRAM_RXBAS_SDSZ_128MB
+#define SDRAM_RXBAS_SDSZ_256    	SDRAM_RXBAS_SDSZ_256MB
+#define SDRAM_RXBAS_SDSZ_512    	SDRAM_RXBAS_SDSZ_512MB
+#define SDRAM_RXBAS_SDSZ_1024		SDRAM_RXBAS_SDSZ_1024MB
+#define SDRAM_RXBAS_SDSZ_2048		SDRAM_RXBAS_SDSZ_2048MB
+#define SDRAM_RXBAS_SDSZ_4096		SDRAM_RXBAS_SDSZ_4096MB
+#define SDRAM_RXBAS_SDSZ_8192		SDRAM_RXBAS_SDSZ_8192MB
+#define SDRAM_RXBAS_SDAM_MODE0		PPC_REG_VAL(23, 0x0)
+#define SDRAM_RXBAS_SDAM_MODE1		PPC_REG_VAL(23, 0x1)
+#define SDRAM_RXBAS_SDAM_MODE2		PPC_REG_VAL(23, 0x2)
+#define SDRAM_RXBAS_SDAM_MODE3		PPC_REG_VAL(23, 0x3)
+#define SDRAM_RXBAS_SDAM_MODE4		PPC_REG_VAL(23, 0x4)
+#define SDRAM_RXBAS_SDAM_MODE5		PPC_REG_VAL(23, 0x5)
+#define SDRAM_RXBAS_SDAM_MODE6		PPC_REG_VAL(23, 0x6)
+#define SDRAM_RXBAS_SDAM_MODE7		PPC_REG_VAL(23, 0x7)
+#define SDRAM_RXBAS_SDAM_MODE8		PPC_REG_VAL(23, 0x8)
+#define SDRAM_RXBAS_SDAM_MODE9		PPC_REG_VAL(23, 0x9)
+#define SDRAM_RXBAS_SDBE_DISABLE	PPC_REG_VAL(31, 0x0)
+#define SDRAM_RXBAS_SDBE_ENABLE		PPC_REG_VAL(31, 0x1)
+#endif /* CONFIG_405EX */
+
+/*
+ * Memory controller registers
+ */
+#define SDRAM_BESR	0x00	/* PLB bus error status (read/clear)         */
+#define SDRAM_BESRT	0x01	/* PLB bus error status (test/set)           */
+#define SDRAM_BEARL	0x02	/* PLB bus error address low                 */
+#define SDRAM_BEARH	0x03	/* PLB bus error address high                */
+#define SDRAM_WMIRQ	0x06	/* PLB write master interrupt (read/clear)   */
+#define SDRAM_WMIRQT	0x07	/* PLB write master interrupt (test/set)     */
+#define SDRAM_PLBOPT	0x08	/* PLB slave options                         */
+#define SDRAM_PUABA	0x09	/* PLB upper address base                    */
+#ifndef CONFIG_405EX
+#define SDRAM_MCSTAT	0x14	/* memory controller status                  */
+#else
+#define SDRAM_MCSTAT	0x1F	/* memory controller status                  */
+#endif
+#define SDRAM_MCOPT1	0x20	/* memory controller options 1               */
+#define SDRAM_MCOPT2	0x21	/* memory controller options 2               */
+#define SDRAM_MODT0	0x22	/* on die termination for bank 0             */
+#define SDRAM_MODT1	0x23	/* on die termination for bank 1             */
+#define SDRAM_MODT2	0x24	/* on die termination for bank 2             */
+#define SDRAM_MODT3	0x25	/* on die termination for bank 3             */
+#define SDRAM_CODT	0x26	/* on die termination for controller         */
+#define SDRAM_VVPR	0x27	/* variable VRef programmming                */
+#define SDRAM_OPARS	0x28	/* on chip driver control setup              */
+#define SDRAM_OPART	0x29	/* on chip driver control trigger            */
+#define SDRAM_RTR	0x30	/* refresh timer                             */
+#define SDRAM_PMIT	0x34	/* power management idle timer               */
+#define SDRAM_MB0CF	0x40	/* memory bank 0 configuration               */
+#define SDRAM_MB1CF	0x44	/* memory bank 1 configuration               */
+#define SDRAM_MB2CF	0x48
+#define SDRAM_MB3CF	0x4C
+#define SDRAM_INITPLR0	0x50	/* manual initialization control             */
+#define SDRAM_INITPLR1	0x51	/* manual initialization control             */
+#define SDRAM_INITPLR2	0x52	/* manual initialization control             */
+#define SDRAM_INITPLR3	0x53	/* manual initialization control             */
+#define SDRAM_INITPLR4	0x54	/* manual initialization control             */
+#define SDRAM_INITPLR5	0x55	/* manual initialization control             */
+#define SDRAM_INITPLR6	0x56	/* manual initialization control             */
+#define SDRAM_INITPLR7	0x57	/* manual initialization control             */
+#define SDRAM_INITPLR8	0x58	/* manual initialization control             */
+#define SDRAM_INITPLR9	0x59	/* manual initialization control             */
+#define SDRAM_INITPLR10	0x5a	/* manual initialization control             */
+#define SDRAM_INITPLR11	0x5b	/* manual initialization control             */
+#define SDRAM_INITPLR12	0x5c	/* manual initialization control             */
+#define SDRAM_INITPLR13	0x5d	/* manual initialization control             */
+#define SDRAM_INITPLR14	0x5e	/* manual initialization control             */
+#define SDRAM_INITPLR15	0x5f	/* manual initialization control             */
+#define SDRAM_RQDC	0x70	/* read DQS delay control                    */
+#define SDRAM_RFDC	0x74	/* read feedback delay control               */
+#define SDRAM_RDCC	0x78	/* read data capture control                 */
+#define SDRAM_DLCR	0x7A	/* delay line calibration                    */
+#define SDRAM_CLKTR	0x80	/* DDR clock timing                          */
+#define SDRAM_WRDTR	0x81	/* write data, DQS, DM clock, timing         */
+#define SDRAM_SDTR1	0x85	/* DDR SDRAM timing 1                        */
+#define SDRAM_SDTR2	0x86	/* DDR SDRAM timing 2                        */
+#define SDRAM_SDTR3	0x87	/* DDR SDRAM timing 3                        */
+#define SDRAM_MMODE	0x88	/* memory mode                               */
+#define SDRAM_MEMODE	0x89	/* memory extended mode                      */
+#define SDRAM_ECCES	0x98	/* ECC error status                          */
+#define SDRAM_CID	0xA4	/* core ID                                   */
+#ifndef CONFIG_405EX
+#define SDRAM_RID	0xA8	/* revision ID                               */
+#endif
+#define SDRAM_FCSR	0xB0	/* feedback calibration status               */
+#define SDRAM_RTSR	0xB1	/* run time status tracking                  */
+#ifdef CONFIG_405EX
+#define SDRAM_RID	0xF8	/* revision ID                               */
+#endif
+
+/*
+ * Memory Controller Bus Error Status
+ */
+#define SDRAM_BESR_MASK			PPC_REG_VAL(7, 0xFF)
+#define SDRAM_BESR_M0ID_MASK		PPC_REG_VAL(3, 0xF)
+#define SDRAM_BESR_M0ID_ICU		PPC_REG_VAL(3, 0x0)
+#define SDRAM_BESR_M0ID_PCIE0		PPC_REG_VAL(3, 0x1)
+#define SDRAM_BESR_M0ID_PCIE1		PPC_REG_VAL(3, 0x2)
+#define SDRAM_BESR_M0ID_DMA		PPC_REG_VAL(3, 0x3)
+#define SDRAM_BESR_M0ID_DCU		PPC_REG_VAL(3, 0x4)
+#define SDRAM_BESR_M0ID_OPB		PPC_REG_VAL(3, 0x5)
+#define SDRAM_BESR_M0ID_MAL		PPC_REG_VAL(3, 0x6)
+#define SDRAM_BESR_M0ID_SEC		PPC_REG_VAL(3, 0x7)
+#define SDRAM_BESR_M0ET_MASK		PPC_REG_VAL(6, 0x7)
+#define SDRAM_BESR_M0ET_NONE		PPC_REG_VAL(6, 0x0)
+#define SDRAM_BESR_M0ET_ECC		PPC_REG_VAL(6, 0x1)
+#define SDRAM_BESR_M0RW_WRITE		PPC_REG_VAL(7, 0)
+#define SDRAM_BESR_M0RW_READ		PPC_REG_VAL(8, 1)
+
+/*
+ * Memory Controller Status
+ */
+#define SDRAM_MCSTAT_MIC_MASK		0x80000000	/* Memory init status mask	*/
+#define SDRAM_MCSTAT_MIC_NOTCOMP	0x00000000	/* Mem init not complete	*/
+#define SDRAM_MCSTAT_MIC_COMP		0x80000000	/* Mem init complete		*/
+#define SDRAM_MCSTAT_SRMS_MASK		0x40000000	/* Mem self refresh stat mask	*/
+#define SDRAM_MCSTAT_SRMS_NOT_SF	0x00000000	/* Mem not in self refresh	*/
+#define SDRAM_MCSTAT_SRMS_SF		0x40000000	/* Mem in self refresh		*/
+#define SDRAM_MCSTAT_IDLE_MASK		0x20000000	/* Mem self refresh stat mask	*/
+#define SDRAM_MCSTAT_IDLE_NOT		0x00000000	/* Mem contr not idle		*/
+#define SDRAM_MCSTAT_IDLE		0x20000000	/* Mem contr idle		*/
+
+/*
+ * Memory Controller Options 1
+ */
+#define SDRAM_MCOPT1_MCHK_MASK		0x30000000 /* Memory data err check mask*/
+#define SDRAM_MCOPT1_MCHK_NON		0x00000000 /* No ECC generation		*/
+#define SDRAM_MCOPT1_MCHK_GEN		0x20000000 /* ECC generation		*/
+#define SDRAM_MCOPT1_MCHK_CHK		0x10000000 /* ECC generation and check	*/
+#define SDRAM_MCOPT1_MCHK_CHK_REP	0x30000000 /* ECC generation, chk, report*/
+#define SDRAM_MCOPT1_MCHK_CHK_DECODE(n)	((((u32)(n))>>28)&0x3)
+#define SDRAM_MCOPT1_RDEN_MASK		0x08000000 /* Registered DIMM mask	*/
+#define SDRAM_MCOPT1_RDEN		0x08000000 /* Registered DIMM enable	*/
+#define SDRAM_MCOPT1_PMU_MASK		0x06000000 /* Page management unit mask	*/
+#define SDRAM_MCOPT1_PMU_CLOSE		0x00000000 /* PMU Close			*/
+#define SDRAM_MCOPT1_PMU_OPEN		0x04000000 /* PMU Open			*/
+#define SDRAM_MCOPT1_PMU_AUTOCLOSE	0x02000000 /* PMU AutoClose		*/
+#define SDRAM_MCOPT1_DMWD_MASK		0x01000000 /* DRAM width mask		*/
+#define SDRAM_MCOPT1_DMWD_32		0x00000000 /* 32 bits			*/
+#define SDRAM_MCOPT1_DMWD_64		0x01000000 /* 64 bits			*/
+#define SDRAM_MCOPT1_UIOS_MASK		0x00C00000 /* Unused IO State		*/
+#define SDRAM_MCOPT1_BCNT_MASK		0x00200000 /* Bank count		*/
+#define SDRAM_MCOPT1_4_BANKS		0x00000000 /* 4 Banks			*/
+#define SDRAM_MCOPT1_8_BANKS		0x00200000 /* 8 Banks			*/
+#define SDRAM_MCOPT1_DDR_TYPE_MASK	0x00100000 /* DDR Memory Type mask	*/
+#define SDRAM_MCOPT1_DDR1_TYPE		0x00000000 /* DDR1 Memory Type		*/
+#define SDRAM_MCOPT1_DDR2_TYPE		0x00100000 /* DDR2 Memory Type		*/
+#define SDRAM_MCOPT1_QDEP		0x00020000 /* 4 commands deep		*/
+#define SDRAM_MCOPT1_RWOO_MASK		0x00008000 /* Out of Order Read mask	*/
+#define SDRAM_MCOPT1_RWOO_DISABLED	0x00000000 /* disabled			*/
+#define SDRAM_MCOPT1_RWOO_ENABLED	0x00008000 /* enabled			*/
+#define SDRAM_MCOPT1_WOOO_MASK		0x00004000 /* Out of Order Write mask	*/
+#define SDRAM_MCOPT1_WOOO_DISABLED	0x00000000 /* disabled			*/
+#define SDRAM_MCOPT1_WOOO_ENABLED	0x00004000 /* enabled			*/
+#define SDRAM_MCOPT1_DCOO_MASK		0x00002000 /* All Out of Order mask	*/
+#define SDRAM_MCOPT1_DCOO_DISABLED	0x00002000 /* disabled			*/
+#define SDRAM_MCOPT1_DCOO_ENABLED	0x00000000 /* enabled			*/
+#define SDRAM_MCOPT1_DREF_MASK		0x00001000 /* Deferred refresh mask	*/
+#define SDRAM_MCOPT1_DREF_NORMAL	0x00000000 /* normal refresh		*/
+#define SDRAM_MCOPT1_DREF_DEFER_4	0x00001000 /* defer up to 4 refresh cmd	*/
+
+/*
+ * Memory Controller Options 2
+ */
+#define SDRAM_MCOPT2_SREN_MASK		0x80000000 /* Self Test mask		*/
+#define SDRAM_MCOPT2_SREN_EXIT		0x00000000 /* Self Test exit		*/
+#define SDRAM_MCOPT2_SREN_ENTER		0x80000000 /* Self Test enter		*/
+#define SDRAM_MCOPT2_PMEN_MASK		0x40000000 /* Power Management mask	*/
+#define SDRAM_MCOPT2_PMEN_DISABLE	0x00000000 /* disable			*/
+#define SDRAM_MCOPT2_PMEN_ENABLE	0x40000000 /* enable			*/
+#define SDRAM_MCOPT2_IPTR_MASK		0x20000000 /* Init Trigger Reg mask	*/
+#define SDRAM_MCOPT2_IPTR_IDLE		0x00000000 /* idle			*/
+#define SDRAM_MCOPT2_IPTR_EXECUTE	0x20000000 /* execute preloaded init	*/
+#define SDRAM_MCOPT2_XSRP_MASK		0x10000000 /* Exit Self Refresh Prevent	*/
+#define SDRAM_MCOPT2_XSRP_ALLOW		0x00000000 /* allow self refresh exit	*/
+#define SDRAM_MCOPT2_XSRP_PREVENT	0x10000000 /* prevent self refresh exit	*/
+#define SDRAM_MCOPT2_DCEN_MASK		0x08000000 /* SDRAM Controller Enable	*/
+#define SDRAM_MCOPT2_DCEN_DISABLE	0x00000000 /* SDRAM Controller Enable	*/
+#define SDRAM_MCOPT2_DCEN_ENABLE	0x08000000 /* SDRAM Controller Enable	*/
+#define SDRAM_MCOPT2_ISIE_MASK		0x04000000 /* Init Seq Interruptable mas*/
+#define SDRAM_MCOPT2_ISIE_DISABLE	0x00000000 /* disable			*/
+#define SDRAM_MCOPT2_ISIE_ENABLE	0x04000000 /* enable			*/
+
+/*
+ * SDRAM Refresh Timer Register
+ */
+#define SDRAM_RTR_RINT_MASK		0xFFF80000
+#define SDRAM_RTR_RINT_ENCODE(n)	((((u32)(n))&0xFFF8)<<16)
+#define SDRAM_RTR_RINT_DECODE(n)	((((u32)(n))>>16)&0xFFF8)
+
+/*
+ * SDRAM Read DQS Delay Control Register
+ */
+#define SDRAM_RQDC_RQDE_MASK		0x80000000
+#define SDRAM_RQDC_RQDE_DISABLE		0x00000000
+#define SDRAM_RQDC_RQDE_ENABLE		0x80000000
+#define SDRAM_RQDC_RQFD_MASK		0x000001FF
+#define SDRAM_RQDC_RQFD_ENCODE(n)	((((u32)(n))&0x1FF)<<0)
+
+#define SDRAM_RQDC_RQFD_MAX		0x1FF
+
+/*
+ * SDRAM Read Data Capture Control Register
+ */
+#define SDRAM_RDCC_RDSS_MASK		0xC0000000
+#define SDRAM_RDCC_RDSS_T1		0x00000000
+#define SDRAM_RDCC_RDSS_T2		0x40000000
+#define SDRAM_RDCC_RDSS_T3		0x80000000
+#define SDRAM_RDCC_RDSS_T4		0xC0000000
+#define SDRAM_RDCC_RSAE_MASK		0x00000001
+#define SDRAM_RDCC_RSAE_DISABLE		0x00000001
+#define SDRAM_RDCC_RSAE_ENABLE		0x00000000
+#define SDRAM_RDCC_RDSS_ENCODE(n)	((((u32)(n))&0x03)<<30)
+#define SDRAM_RDCC_RDSS_DECODE(n)	((((u32)(n))>>30)&0x03)
+
+/*
+ * SDRAM Read Feedback Delay Control Register
+ */
+#define SDRAM_RFDC_ARSE_MASK		0x80000000
+#define SDRAM_RFDC_ARSE_DISABLE		0x80000000
+#define SDRAM_RFDC_ARSE_ENABLE		0x00000000
+#define SDRAM_RFDC_RFOS_MASK		0x007F0000
+#define SDRAM_RFDC_RFOS_ENCODE(n)	((((u32)(n))&0x7F)<<16)
+#define SDRAM_RFDC_RFFD_MASK		0x000007FF
+#define SDRAM_RFDC_RFFD_ENCODE(n)	((((u32)(n))&0x7FF)<<0)
+
+#define SDRAM_RFDC_RFFD_MAX		0x7FF
+
+/*
+ * SDRAM Delay Line Calibration Register
+ */
+#define SDRAM_DLCR_DCLM_MASK		0x80000000
+#define SDRAM_DLCR_DCLM_MANUAL		0x80000000
+#define SDRAM_DLCR_DCLM_AUTO		0x00000000
+#define SDRAM_DLCR_DLCR_MASK		0x08000000
+#define SDRAM_DLCR_DLCR_CALIBRATE	0x08000000
+#define SDRAM_DLCR_DLCR_IDLE		0x00000000
+#define SDRAM_DLCR_DLCS_MASK		0x07000000
+#define SDRAM_DLCR_DLCS_NOT_RUN		0x00000000
+#define SDRAM_DLCR_DLCS_IN_PROGRESS	0x01000000
+#define SDRAM_DLCR_DLCS_COMPLETE	0x02000000
+#define SDRAM_DLCR_DLCS_CONT_DONE	0x03000000
+#define SDRAM_DLCR_DLCS_ERROR		0x04000000
+#define SDRAM_DLCR_DLCV_MASK		0x000001FF
+#define SDRAM_DLCR_DLCV_ENCODE(n)	((((u32)(n))&0x1FF)<<0)
+#define SDRAM_DLCR_DLCV_DECODE(n)	((((u32)(n))>>0)&0x1FF)
+
+/*
+ * SDRAM Memory On Die Terimination Control Register
+ */
+#define SDRAM_MODT_ODTON_DISABLE		PPC_REG_VAL(0, 0)
+#define SDRAM_MODT_ODTON_ENABLE			PPC_REG_VAL(0, 1)
+#define SDRAM_MODT_EB1W_DISABLE			PPC_REG_VAL(1, 0)
+#define SDRAM_MODT_EB1W_ENABLE			PPC_REG_VAL(1, 1)
+#define SDRAM_MODT_EB1R_DISABLE			PPC_REG_VAL(2, 0)
+#define SDRAM_MODT_EB1R_ENABLE			PPC_REG_VAL(2, 1)
+#define SDRAM_MODT_EB0W_DISABLE			PPC_REG_VAL(7, 0)
+#define SDRAM_MODT_EB0W_ENABLE			PPC_REG_VAL(7, 1)
+#define SDRAM_MODT_EB0R_DISABLE			PPC_REG_VAL(8, 0)
+#define SDRAM_MODT_EB0R_ENABLE			PPC_REG_VAL(8, 1)
+
+/*
+ * SDRAM Controller On Die Termination Register
+ */
+#define SDRAM_CODT_ODT_ON			PPC_REG_VAL(0, 1)
+#define SDRAM_CODT_ODT_OFF			PPC_REG_VAL(0, 0)
+#define SDRAM_CODT_RK1W_ON			PPC_REG_VAL(1, 1)
+#define SDRAM_CODT_RK1W_OFF			PPC_REG_VAL(1, 0)
+#define SDRAM_CODT_RK1R_ON			PPC_REG_VAL(2, 1)
+#define SDRAM_CODT_RK1R_OFF			PPC_REG_VAL(2, 0)
+#define SDRAM_CODT_RK0W_ON			PPC_REG_VAL(7, 1)
+#define SDRAM_CODT_RK0W_OFF			PPC_REG_VAL(7, 0)
+#define SDRAM_CODT_RK0R_ON			PPC_REG_VAL(8, 1)
+#define SDRAM_CODT_RK0R_OFF			PPC_REG_VAL(8, 0)
+#define SDRAM_CODT_ODTSH_NORMAL			PPC_REG_VAL(10, 0)
+#define SDRAM_CODT_ODTSH_REMOVE_ONE_AT_END	PPC_REG_VAL(10, 1)
+#define SDRAM_CODT_ODTSH_ADD_ONE_AT_START	PPC_REG_VAL(10, 2)
+#define SDRAM_CODT_ODTSH_SHIFT_ONE_EARLIER	PPC_REG_VAL(10, 3)
+#define SDRAM_CODT_CODTZ_75OHM			PPC_REG_VAL(11, 0)
+#define SDRAM_CODT_CKEG_ON			PPC_REG_VAL(12, 1)
+#define SDRAM_CODT_CKEG_OFF			PPC_REG_VAL(12, 0)
+#define SDRAM_CODT_CTLG_ON			PPC_REG_VAL(13, 1)
+#define SDRAM_CODT_CTLG_OFF			PPC_REG_VAL(13, 0)
+#define SDRAM_CODT_FBDG_ON			PPC_REG_VAL(14, 1)
+#define SDRAM_CODT_FBDG_OFF			PPC_REG_VAL(14, 0)
+#define SDRAM_CODT_FBRG_ON			PPC_REG_VAL(15, 1)
+#define SDRAM_CODT_FBRG_OFF			PPC_REG_VAL(15, 0)
+#define SDRAM_CODT_CKLZ_36OHM			PPC_REG_VAL(18, 1)
+#define SDRAM_CODT_CKLZ_18OHM			PPC_REG_VAL(18, 0)
+#define SDRAM_CODT_DQS_VOLTAGE_DDR_MASK		PPC_REG_VAL(26, 1)
+#define SDRAM_CODT_DQS_2_5_V_DDR1		PPC_REG_VAL(26, 0)
+#define SDRAM_CODT_DQS_1_8_V_DDR2		PPC_REG_VAL(26, 1)
+#define SDRAM_CODT_DQS_MASK			PPC_REG_VAL(27, 1)
+#define SDRAM_CODT_DQS_DIFFERENTIAL		PPC_REG_VAL(27, 0)
+#define SDRAM_CODT_DQS_SINGLE_END		PPC_REG_VAL(27, 1)
+#define SDRAM_CODT_CKSE_DIFFERENTIAL		PPC_REG_VAL(28, 0)
+#define SDRAM_CODT_CKSE_SINGLE_END		PPC_REG_VAL(28, 1)
+#define SDRAM_CODT_FEEBBACK_RCV_SINGLE_END	PPC_REG_VAL(29, 1)
+#define SDRAM_CODT_FEEBBACK_DRV_SINGLE_END	PPC_REG_VAL(30, 1)
+#define SDRAM_CODT_IO_HIZ			PPC_REG_VAL(31, 0)
+#define SDRAM_CODT_IO_NMODE			PPC_REG_VAL(31, 1)
+
+/*
+ * SDRAM Initialization Preload Register
+ */
+#define SDRAM_INITPLR_ENABLE			PPC_REG_VAL(0, 1)
+#define SDRAM_INITPLR_DISABLE			PPC_REG_VAL(0, 0)
+#define SDRAM_INITPLR_IMWT_MASK			PPC_REG_VAL(8, 0xFF)
+#define SDRAM_INITPLR_IMWT_ENCODE(n)		PPC_REG_VAL(8, \
+							    (static_cast(u32, \
+									 n)) \
+							    & 0xFF)
+#define SDRAM_INITPLR_ICMD_MASK			PPC_REG_VAL(12, 0x7)
+#define SDRAM_INITPLR_ICMD_ENCODE(n)		PPC_REG_VAL(12, \
+							    (static_cast(u32, \
+									 n)) \
+							    & 0x7)
+#define SDRAM_INITPLR_IBA_MASK			PPC_REG_VAL(15, 0x7)
+#define SDRAM_INITPLR_IBA_ENCODE(n)		PPC_REG_VAL(15, \
+							    (static_cast(u32, \
+									 n)) \
+							    & 0x7)
+#define SDRAM_INITPLR_IMA_MASK			PPC_REG_VAL(31, 0x7FFF)
+#define SDRAM_INITPLR_IMA_ENCODE(n)		PPC_REG_VAL(31, \
+							    (static_cast(u32, \
+									 n)) \
+							    & 0x7FFF)
+
+/*
+ * JEDEC DDR Initialization Commands
+ */
+#define JEDEC_CMD_NOP				7
+#define JEDEC_CMD_PRECHARGE			2
+#define JEDEC_CMD_REFRESH			1
+#define JEDEC_CMD_EMR				0
+#define JEDEC_CMD_READ				5
+#define JEDEC_CMD_WRITE				4
+
+/*
+ * JEDEC Precharge Command Memory Address Arguments
+ */
+#define JEDEC_MA_PRECHARGE_ONE			(0 << 10)
+#define JEDEC_MA_PRECHARGE_ALL			(1 << 10)
+
+/*
+ * JEDEC DDR EMR Command Bank Address Arguments
+ */
+#define JEDEC_BA_MR				0
+#define JEDEC_BA_EMR				1
+#define JEDEC_BA_EMR2				2
+#define JEDEC_BA_EMR3				3
+
+/*
+ * JEDEC DDR Mode Register
+ */
+#define JEDEC_MA_MR_PDMODE_FAST_EXIT		(0 << 12)
+#define JEDEC_MA_MR_PDMODE_SLOW_EXIT		(1 << 12)
+#define JEDEC_MA_MR_WR_MASK			(0x7 << 9)
+#define JEDEC_MA_MR_WR_DDR1			(0x0 << 9)
+#define JEDEC_MA_MR_WR_DDR2_2_CYC		(0x1 << 9)
+#define JEDEC_MA_MR_WR_DDR2_3_CYC		(0x2 << 9)
+#define JEDEC_MA_MR_WR_DDR2_4_CYC		(0x3 << 9)
+#define JEDEC_MA_MR_WR_DDR2_5_CYC		(0x4 << 9)
+#define JEDEC_MA_MR_WR_DDR2_6_CYC		(0x5 << 9)
+#define JEDEC_MA_MR_DLL_RESET			(1 << 8)
+#define JEDEC_MA_MR_MODE_NORMAL			(0 << 8)
+#define JEDEC_MA_MR_MODE_TEST			(1 << 8)
+#define JEDEC_MA_MR_CL_MASK			(0x7 << 4)
+#define JEDEC_MA_MR_CL_DDR1_2_0_CLK		(0x2 << 4)
+#define JEDEC_MA_MR_CL_DDR1_2_5_CLK		(0x6 << 4)
+#define JEDEC_MA_MR_CL_DDR1_3_0_CLK		(0x3 << 4)
+#define JEDEC_MA_MR_CL_DDR2_2_0_CLK		(0x2 << 4)
+#define JEDEC_MA_MR_CL_DDR2_3_0_CLK		(0x3 << 4)
+#define JEDEC_MA_MR_CL_DDR2_4_0_CLK		(0x4 << 4)
+#define JEDEC_MA_MR_CL_DDR2_5_0_CLK		(0x5 << 4)
+#define JEDEC_MA_MR_CL_DDR2_6_0_CLK		(0x6 << 4)
+#define JEDEC_MA_MR_CL_DDR2_7_0_CLK		(0x7 << 4)
+#define JEDEC_MA_MR_BTYP_SEQUENTIAL		(0 << 3)
+#define JEDEC_MA_MR_BTYP_INTERLEAVED		(1 << 3)
+#define JEDEC_MA_MR_BLEN_MASK			(0x7 << 0)
+#define JEDEC_MA_MR_BLEN_4			(2 << 0)
+#define JEDEC_MA_MR_BLEN_8			(3 << 0)
+
+/*
+ * JEDEC DDR Extended Mode Register
+ */
+#define JEDEC_MA_EMR_OUTPUT_MASK		(1 << 12)
+#define JEDEC_MA_EMR_OUTPUT_ENABLE		(0 << 12)
+#define JEDEC_MA_EMR_OUTPUT_DISABLE		(1 << 12)
+#define JEDEC_MA_EMR_RQDS_MASK			(1 << 11)
+#define JEDEC_MA_EMR_RDQS_DISABLE		(0 << 11)
+#define JEDEC_MA_EMR_RDQS_ENABLE		(1 << 11)
+#define JEDEC_MA_EMR_DQS_MASK			(1 << 10)
+#define JEDEC_MA_EMR_DQS_DISABLE		(1 << 10)
+#define JEDEC_MA_EMR_DQS_ENABLE			(0 << 10)
+#define JEDEC_MA_EMR_OCD_MASK			(0x7 << 7)
+#define JEDEC_MA_EMR_OCD_EXIT			(0 << 7)
+#define JEDEC_MA_EMR_OCD_ENTER			(7 << 7)
+#define JEDEC_MA_EMR_AL_DDR1_0_CYC		(0 << 3)
+#define JEDEC_MA_EMR_AL_DDR2_1_CYC		(1 << 3)
+#define JEDEC_MA_EMR_AL_DDR2_2_CYC		(2 << 3)
+#define JEDEC_MA_EMR_AL_DDR2_3_CYC		(3 << 3)
+#define JEDEC_MA_EMR_AL_DDR2_4_CYC		(4 << 3)
+#define JEDEC_MA_EMR_RTT_MASK			(0x11 << 2)
+#define JEDEC_MA_EMR_RTT_DISABLED		(0x00 << 2)
+#define JEDEC_MA_EMR_RTT_75OHM			(0x01 << 2)
+#define JEDEC_MA_EMR_RTT_150OHM			(0x10 << 2)
+#define JEDEC_MA_EMR_RTT_50OHM			(0x11 << 2)
+#define JEDEC_MA_EMR_ODS_MASK			(1 << 1)
+#define JEDEC_MA_EMR_ODS_NORMAL			(0 << 1)
+#define JEDEC_MA_EMR_ODS_WEAK			(1 << 1)
+#define JEDEC_MA_EMR_DLL_MASK			(1 << 0)
+#define JEDEC_MA_EMR_DLL_ENABLE			(0 << 0)
+#define JEDEC_MA_EMR_DLL_DISABLE		(1 << 0)
+
+/*
+ * JEDEC DDR Extended Mode Register 2
+ */
+#define JEDEC_MA_EMR2_TEMP_COMMERCIAL		(0 << 7)
+#define JEDEC_MA_EMR2_TEMP_INDUSTRIAL		(1 << 7)
+
+/*
+ * SDRAM Mode Register (Corresponds 1:1 w/ JEDEC Mode Register)
+ */
+#define SDRAM_MMODE_WR_MASK			JEDEC_MA_MR_WR_MASK
+#define SDRAM_MMODE_WR_DDR1			JEDEC_MA_MR_WR_DDR1
+#define SDRAM_MMODE_WR_DDR2_2_CYC		JEDEC_MA_MR_WR_DDR2_2_CYC
+#define SDRAM_MMODE_WR_DDR2_3_CYC		JEDEC_MA_MR_WR_DDR2_3_CYC
+#define SDRAM_MMODE_WR_DDR2_4_CYC		JEDEC_MA_MR_WR_DDR2_4_CYC
+#define SDRAM_MMODE_WR_DDR2_5_CYC		JEDEC_MA_MR_WR_DDR2_5_CYC
+#define SDRAM_MMODE_WR_DDR2_6_CYC		JEDEC_MA_MR_WR_DDR2_6_CYC
+#define SDRAM_MMODE_DCL_MASK			JEDEC_MA_MR_CL_MASK
+#define SDRAM_MMODE_DCL_DDR1_2_0_CLK		JEDEC_MA_MR_CL_DDR1_2_0_CLK
+#define SDRAM_MMODE_DCL_DDR1_2_5_CLK		JEDEC_MA_MR_CL_DDR1_2_5_CLK
+#define SDRAM_MMODE_DCL_DDR1_3_0_CLK		JEDEC_MA_MR_CL_DDR1_3_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_2_0_CLK		JEDEC_MA_MR_CL_DDR2_2_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_3_0_CLK		JEDEC_MA_MR_CL_DDR2_3_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_4_0_CLK		JEDEC_MA_MR_CL_DDR2_4_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_5_0_CLK		JEDEC_MA_MR_CL_DDR2_5_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_6_0_CLK		JEDEC_MA_MR_CL_DDR2_6_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_7_0_CLK		JEDEC_MA_MR_CL_DDR2_7_0_CLK
+#define SDRAM_MMODE_BTYP_SEQUENTIAL		JEDEC_MA_MR_BTYP_SEQUENTIAL
+#define SDRAM_MMODE_BTYP_INTERLEAVED		JEDEC_MA_MR_BTYP_INTERLEAVED
+#define SDRAM_MMODE_BLEN_MASK			JEDEC_MA_MR_BLEN_MASK
+#define SDRAM_MMODE_BLEN_4			JEDEC_MA_MR_BLEN_4
+#define SDRAM_MMODE_BLEN_8			JEDEC_MA_MR_BLEN_8
+
+/*
+ * SDRAM Extended Mode Register (Corresponds 1:1 w/ JEDEC Extended
+ * Mode Register)
+ */
+#define SDRAM_MEMODE_QOFF_MASK			JEDEC_MA_EMR_OUTPUT_MASK
+#define SDRAM_MEMODE_QOFF_DISABLE		JEDEC_MA_EMR_OUTPUT_DISABLE
+#define SDRAM_MEMODE_QOFF_ENABLE		JEDEC_MA_EMR_OUTPUT_ENABLE
+#define SDRAM_MEMODE_RDQS_MASK			JEDEC_MA_EMR_RQDS_MASK
+#define SDRAM_MEMODE_RDQS_DISABLE		JEDEC_MA_EMR_RDQS_DISABLE
+#define SDRAM_MEMODE_RDQS_ENABLE		JEDEC_MA_EMR_RDQS_ENABLE
+#define SDRAM_MEMODE_DQS_MASK			JEDEC_MA_EMR_DQS_MASK
+#define SDRAM_MEMODE_DQS_DISABLE		JEDEC_MA_EMR_DQS_DISABLE
+#define SDRAM_MEMODE_DQS_ENABLE			JEDEC_MA_EMR_DQS_ENABLE
+#define SDRAM_MEMODE_AL_DDR1_0_CYC		JEDEC_MA_EMR_AL_DDR1_0_CYC
+#define SDRAM_MEMODE_AL_DDR2_1_CYC		JEDEC_MA_EMR_AL_DDR2_1_CYC
+#define SDRAM_MEMODE_AL_DDR2_2_CYC		JEDEC_MA_EMR_AL_DDR2_2_CYC
+#define SDRAM_MEMODE_AL_DDR2_3_CYC		JEDEC_MA_EMR_AL_DDR2_3_CYC
+#define SDRAM_MEMODE_AL_DDR2_4_CYC		JEDEC_MA_EMR_AL_DDR2_4_CYC
+#define SDRAM_MEMODE_RTT_MASK			JEDEC_MA_EMR_RTT_MASK
+#define SDRAM_MEMODE_RTT_DISABLED		JEDEC_MA_EMR_RTT_DISABLED
+#define SDRAM_MEMODE_RTT_75OHM			JEDEC_MA_EMR_RTT_75OHM
+#define SDRAM_MEMODE_RTT_150OHM			JEDEC_MA_EMR_RTT_150OHM
+#define SDRAM_MEMODE_RTT_50OHM			JEDEC_MA_EMR_RTT_50OHM
+#define SDRAM_MEMODE_DIC_MASK			JEDEC_MA_EMR_ODS_MASK
+#define SDRAM_MEMODE_DIC_NORMAL			JEDEC_MA_EMR_ODS_NORMAL
+#define SDRAM_MEMODE_DIC_WEAK			JEDEC_MA_EMR_ODS_WEAK
+#define SDRAM_MEMODE_DLL_MASK			JEDEC_MA_EMR_DLL_MASK
+#define SDRAM_MEMODE_DLL_DISABLE		JEDEC_MA_EMR_DLL_DISABLE
+#define SDRAM_MEMODE_DLL_ENABLE			JEDEC_MA_EMR_DLL_ENABLE
+
+/*
+ * SDRAM Clock Timing Register
+ */
+#define SDRAM_CLKTR_CLKP_MASK		0xC0000000
+#define SDRAM_CLKTR_CLKP_0_DEG		0x00000000
+#define SDRAM_CLKTR_CLKP_180_DEG_ADV	0x80000000
+#define SDRAM_CLKTR_CLKP_90_DEG_ADV	0x40000000
+#define SDRAM_CLKTR_CLKP_270_DEG_ADV	0xC0000000
+
+/*
+ * SDRAM Write Timing Register
+ */
+#define SDRAM_WRDTR_LLWP_MASK		0x10000000
+#define SDRAM_WRDTR_LLWP_DIS		0x10000000
+#define SDRAM_WRDTR_LLWP_1_CYC		0x00000000
+#define SDRAM_WRDTR_WTR_MASK		0x0E000000
+#define SDRAM_WRDTR_WTR_0_DEG		0x06000000
+#define SDRAM_WRDTR_WTR_90_DEG_ADV	0x04000000
+#define SDRAM_WRDTR_WTR_180_DEG_ADV	0x02000000
+#define SDRAM_WRDTR_WTR_270_DEG_ADV	0x00000000
+
+/*
+ * SDRAM SDTR1 Options
+ */
+#define SDRAM_SDTR1_LDOF_MASK		0x80000000
+#define SDRAM_SDTR1_LDOF_1_CLK		0x00000000
+#define SDRAM_SDTR1_LDOF_2_CLK		0x80000000
+#define SDRAM_SDTR1_RTW_MASK		0x00F00000
+#define SDRAM_SDTR1_RTW_2_CLK		0x00200000
+#define SDRAM_SDTR1_RTW_3_CLK		0x00300000
+#define SDRAM_SDTR1_WTWO_MASK		0x000F0000
+#define SDRAM_SDTR1_WTWO_0_CLK		0x00000000
+#define SDRAM_SDTR1_WTWO_1_CLK		0x00010000
+#define SDRAM_SDTR1_RTRO_MASK		0x0000F000
+#define SDRAM_SDTR1_RTRO_1_CLK		0x00001000
+#define SDRAM_SDTR1_RTRO_2_CLK		0x00002000
+
+/*
+ * SDRAM SDTR2 Options
+ */
+#define SDRAM_SDTR2_RCD_MASK		0xF0000000
+#define SDRAM_SDTR2_RCD_1_CLK		0x10000000
+#define SDRAM_SDTR2_RCD_2_CLK		0x20000000
+#define SDRAM_SDTR2_RCD_3_CLK		0x30000000
+#define SDRAM_SDTR2_RCD_4_CLK		0x40000000
+#define SDRAM_SDTR2_RCD_5_CLK		0x50000000
+#define SDRAM_SDTR2_WTR_MASK		0x0F000000
+#define SDRAM_SDTR2_WTR_1_CLK		0x01000000
+#define SDRAM_SDTR2_WTR_2_CLK		0x02000000
+#define SDRAM_SDTR2_WTR_3_CLK		0x03000000
+#define SDRAM_SDTR2_WTR_4_CLK		0x04000000
+#define SDRAM_SDTR3_WTR_ENCODE(n)	((((u32)(n))&0xF)<<24)
+#define SDRAM_SDTR2_XSNR_MASK		0x00FF0000
+#define SDRAM_SDTR2_XSNR_8_CLK		0x00080000
+#define SDRAM_SDTR2_XSNR_16_CLK		0x00100000
+#define SDRAM_SDTR2_XSNR_32_CLK		0x00200000
+#define SDRAM_SDTR2_XSNR_64_CLK		0x00400000
+#define SDRAM_SDTR2_WPC_MASK		0x0000F000
+#define SDRAM_SDTR2_WPC_2_CLK		0x00002000
+#define SDRAM_SDTR2_WPC_3_CLK		0x00003000
+#define SDRAM_SDTR2_WPC_4_CLK		0x00004000
+#define SDRAM_SDTR2_WPC_5_CLK		0x00005000
+#define SDRAM_SDTR2_WPC_6_CLK		0x00006000
+#define SDRAM_SDTR3_WPC_ENCODE(n)	((((u32)(n))&0xF)<<12)
+#define SDRAM_SDTR2_RPC_MASK		0x00000F00
+#define SDRAM_SDTR2_RPC_2_CLK		0x00000200
+#define SDRAM_SDTR2_RPC_3_CLK		0x00000300
+#define SDRAM_SDTR2_RPC_4_CLK		0x00000400
+#define SDRAM_SDTR2_RP_MASK		0x000000F0
+#define SDRAM_SDTR2_RP_3_CLK		0x00000030
+#define SDRAM_SDTR2_RP_4_CLK		0x00000040
+#define SDRAM_SDTR2_RP_5_CLK		0x00000050
+#define SDRAM_SDTR2_RP_6_CLK		0x00000060
+#define SDRAM_SDTR2_RP_7_CLK		0x00000070
+#define SDRAM_SDTR2_RRD_MASK		0x0000000F
+#define SDRAM_SDTR2_RRD_2_CLK		0x00000002
+#define SDRAM_SDTR2_RRD_3_CLK		0x00000003
+
+/*
+ * SDRAM SDTR3 Options
+ */
+#define SDRAM_SDTR3_RAS_MASK		0x1F000000
+#define SDRAM_SDTR3_RAS_ENCODE(n)	((((u32)(n))&0x1F)<<24)
+#define SDRAM_SDTR3_RC_MASK		0x001F0000
+#define SDRAM_SDTR3_RC_ENCODE(n)	((((u32)(n))&0x1F)<<16)
+#define SDRAM_SDTR3_XCS_MASK		0x00001F00
+#define SDRAM_SDTR3_XCS			0x00000D00
+#define SDRAM_SDTR3_RFC_MASK		0x0000003F
+#define SDRAM_SDTR3_RFC_ENCODE(n)	((((u32)(n))&0x3F)<<0)
+
+/*
+ * ECC Error Status
+ */
+#define SDRAM_ECCES_MASK		 PPC_REG_VAL(21, 0x3FFFFF)
+#define SDRAM_ECCES_BNCE_MASK		 PPC_REG_VAL(15, 0xFFFF)
+#define SDRAM_ECCES_BNCE_ENCODE(lane)	 PPC_REG_VAL(((lane) & 0xF), 1)
+#define SDRAM_ECCES_CKBER_MASK		 PPC_REG_VAL(17, 0x3)
+#define SDRAM_ECCES_CKBER_NONE		 PPC_REG_VAL(17, 0)
+#define SDRAM_ECCES_CKBER_16_ECC_0_3	 PPC_REG_VAL(17, 2)
+#define SDRAM_ECCES_CKBER_32_ECC_0_3	 PPC_REG_VAL(17, 1)
+#define SDRAM_ECCES_CKBER_32_ECC_4_8	 PPC_REG_VAL(17, 2)
+#define SDRAM_ECCES_CKBER_32_ECC_0_8	 PPC_REG_VAL(17, 3)
+#define SDRAM_ECCES_CE			 PPC_REG_VAL(18, 1)
+#define SDRAM_ECCES_UE			 PPC_REG_VAL(19, 1)
+#define SDRAM_ECCES_BKNER_MASK		 PPC_REG_VAL(21, 0x3)
+#define SDRAM_ECCES_BK0ER		 PPC_REG_VAL(20, 1)
+#define SDRAM_ECCES_BK1ER		 PPC_REG_VAL(21, 1)
+
+/*
+ * Memory Bank 0-1 configuration
+ */
+#define SDRAM_BXCF_M_AM_MASK		0x00000F00	/* Addressing mode	*/
+#define SDRAM_BXCF_M_AM_0		0x00000000	/*   Mode 0		*/
+#define SDRAM_BXCF_M_AM_1		0x00000100	/*   Mode 1		*/
+#define SDRAM_BXCF_M_AM_2		0x00000200	/*   Mode 2		*/
+#define SDRAM_BXCF_M_AM_3		0x00000300	/*   Mode 3		*/
+#define SDRAM_BXCF_M_AM_4		0x00000400	/*   Mode 4		*/
+#define SDRAM_BXCF_M_AM_5		0x00000500	/*   Mode 5		*/
+#define SDRAM_BXCF_M_AM_6		0x00000600	/*   Mode 6		*/
+#define SDRAM_BXCF_M_AM_7		0x00000700	/*   Mode 7		*/
+#define SDRAM_BXCF_M_AM_8		0x00000800	/*   Mode 8		*/
+#define SDRAM_BXCF_M_AM_9		0x00000900	/*   Mode 9		*/
+#define SDRAM_BXCF_M_BE_MASK		0x00000001	/* Memory Bank Enable	*/
+#define SDRAM_BXCF_M_BE_DISABLE		0x00000000	/* Memory Bank Enable	*/
+#define SDRAM_BXCF_M_BE_ENABLE		0x00000001	/* Memory Bank Enable	*/
+
+#define SDRAM_RTSR_TRK1SM_MASK		0xC0000000	/* Tracking State Mach 1*/
+#define SDRAM_RTSR_TRK1SM_ATBASE	0x00000000	/* atbase state		*/
+#define SDRAM_RTSR_TRK1SM_MISSED	0x40000000	/* missed state		*/
+#define SDRAM_RTSR_TRK1SM_ATPLS1	0x80000000	/* atpls1 state		*/
+#define SDRAM_RTSR_TRK1SM_RESET		0xC0000000	/* reset  state		*/
+
+#define SDR0_MFR_FIXD			0x10000000	/* Workaround for PCI/DMA */
+
+#endif /* CONFIG_SDRAM_PPC4xx_IBM_DDR2 */
+
+#if defined(CONFIG_SDRAM_PPC4xx_DENALI_DDR2)
+/*
+ * SDRAM Controller
+ */
+#define DDR0_00				0x00
+#define DDR0_00_INT_ACK_MASK		0x7F000000	/* Write only */
+#define DDR0_00_INT_ACK_ALL		0x7F000000
+#define DDR0_00_INT_ACK_ENCODE(n)	((((u32)(n))&0x7F)<<24)
+#define DDR0_00_INT_ACK_DECODE(n)	((((u32)(n))>>24)&0x7F)
+/* Status */
+#define DDR0_00_INT_STATUS_MASK		0x00FF0000	/* Read only */
+/* Bit0. A single access outside the defined PHYSICAL memory space detected. */
+#define DDR0_00_INT_STATUS_BIT0		0x00010000
+/* Bit1. Multiple accesses outside the defined PHYSICAL memory space detected. */
+#define DDR0_00_INT_STATUS_BIT1		0x00020000
+/* Bit2. Single correctable ECC event detected */
+#define DDR0_00_INT_STATUS_BIT2		0x00040000
+/* Bit3. Multiple correctable ECC events detected. */
+#define DDR0_00_INT_STATUS_BIT3		0x00080000
+/* Bit4. Single uncorrectable ECC event detected. */
+#define DDR0_00_INT_STATUS_BIT4		0x00100000
+/* Bit5. Multiple uncorrectable ECC events detected. */
+#define DDR0_00_INT_STATUS_BIT5		0x00200000
+/* Bit6. DRAM initialization complete. */
+#define DDR0_00_INT_STATUS_BIT6		0x00400000
+/* Bit7. Logical OR of all lower bits. */
+#define DDR0_00_INT_STATUS_BIT7		0x00800000
+
+#define DDR0_00_INT_STATUS_ENCODE(n)	((((u32)(n))&0xFF)<<16)
+#define DDR0_00_INT_STATUS_DECODE(n)	((((u32)(n))>>16)&0xFF)
+#define DDR0_00_DLL_INCREMENT_MASK	0x00007F00
+#define DDR0_00_DLL_INCREMENT_ENCODE(n)	((((u32)(n))&0x7F)<<8)
+#define DDR0_00_DLL_INCREMENT_DECODE(n)	((((u32)(n))>>8)&0x7F)
+#define DDR0_00_DLL_START_POINT_MASK	0x0000007F
+#define DDR0_00_DLL_START_POINT_ENCODE(n) ((((u32)(n))&0x7F)<<0)
+#define DDR0_00_DLL_START_POINT_DECODE(n) ((((u32)(n))>>0)&0x7F)
+
+#define DDR0_01				0x01
+#define DDR0_01_PLB0_DB_CS_LOWER_MASK	0x1F000000
+#define DDR0_01_PLB0_DB_CS_LOWER_ENCODE(n) ((((u32)(n))&0x1F)<<24)
+#define DDR0_01_PLB0_DB_CS_LOWER_DECODE(n) ((((u32)(n))>>24)&0x1F)
+#define DDR0_01_PLB0_DB_CS_UPPER_MASK	0x001F0000
+#define DDR0_01_PLB0_DB_CS_UPPER_ENCODE(n) ((((u32)(n))&0x1F)<<16)
+#define DDR0_01_PLB0_DB_CS_UPPER_DECODE(n) ((((u32)(n))>>16)&0x1F)
+#define DDR0_01_OUT_OF_RANGE_TYPE_MASK	0x00000700	/* Read only */
+#define DDR0_01_OUT_OF_RANGE_TYPE_ENCODE(n) ((((u32)(n))&0x7)<<8)
+#define DDR0_01_OUT_OF_RANGE_TYPE_DECODE(n) ((((u32)(n))>>8)&0x7)
+#define DDR0_01_INT_MASK_MASK		0x000000FF
+#define DDR0_01_INT_MASK_ENCODE(n)	((((u32)(n))&0xFF)<<0)
+#define DDR0_01_INT_MASK_DECODE(n)	((((u32)(n))>>0)&0xFF)
+#define DDR0_01_INT_MASK_ALL_ON		0x000000FF
+#define DDR0_01_INT_MASK_ALL_OFF	0x00000000
+
+#define DDR0_02				0x02
+#define DDR0_02_MAX_CS_REG_MASK		0x02000000	/* Read only */
+#define DDR0_02_MAX_CS_REG_ENCODE(n)	((((u32)(n))&0x2)<<24)
+#define DDR0_02_MAX_CS_REG_DECODE(n)	((((u32)(n))>>24)&0x2)
+#define DDR0_02_MAX_COL_REG_MASK	0x000F0000	/* Read only */
+#define DDR0_02_MAX_COL_REG_ENCODE(n)	((((u32)(n))&0xF)<<16)
+#define DDR0_02_MAX_COL_REG_DECODE(n)	((((u32)(n))>>16)&0xF)
+#define DDR0_02_MAX_ROW_REG_MASK	0x00000F00	/* Read only */
+#define DDR0_02_MAX_ROW_REG_ENCODE(n)	((((u32)(n))&0xF)<<8)
+#define DDR0_02_MAX_ROW_REG_DECODE(n)	((((u32)(n))>>8)&0xF)
+#define DDR0_02_START_MASK		0x00000001
+#define DDR0_02_START_ENCODE(n)		((((u32)(n))&0x1)<<0)
+#define DDR0_02_START_DECODE(n)		((((u32)(n))>>0)&0x1)
+#define DDR0_02_START_OFF		0x00000000
+#define DDR0_02_START_ON		0x00000001
+
+#define DDR0_03				0x03
+#define DDR0_03_BSTLEN_MASK		0x07000000
+#define DDR0_03_BSTLEN_ENCODE(n)	((((u32)(n))&0x7)<<24)
+#define DDR0_03_BSTLEN_DECODE(n)	((((u32)(n))>>24)&0x7)
+#define DDR0_03_CASLAT_MASK		0x00070000
+#define DDR0_03_CASLAT_ENCODE(n)	((((u32)(n))&0x7)<<16)
+#define DDR0_03_CASLAT_DECODE(n)	((((u32)(n))>>16)&0x7)
+#define DDR0_03_CASLAT_LIN_MASK		0x00000F00
+#define DDR0_03_CASLAT_LIN_ENCODE(n)	((((u32)(n))&0xF)<<8)
+#define DDR0_03_CASLAT_LIN_DECODE(n)	((((u32)(n))>>8)&0xF)
+#define DDR0_03_INITAREF_MASK		0x0000000F
+#define DDR0_03_INITAREF_ENCODE(n)	((((u32)(n))&0xF)<<0)
+#define DDR0_03_INITAREF_DECODE(n)	((((u32)(n))>>0)&0xF)
+
+#define DDR0_04				0x04
+#define DDR0_04_TRC_MASK		0x1F000000
+#define DDR0_04_TRC_ENCODE(n)		((((u32)(n))&0x1F)<<24)
+#define DDR0_04_TRC_DECODE(n)		((((u32)(n))>>24)&0x1F)
+#define DDR0_04_TRRD_MASK		0x00070000
+#define DDR0_04_TRRD_ENCODE(n)		((((u32)(n))&0x7)<<16)
+#define DDR0_04_TRRD_DECODE(n)		((((u32)(n))>>16)&0x7)
+#define DDR0_04_TRTP_MASK		0x00000700
+#define DDR0_04_TRTP_ENCODE(n)		((((u32)(n))&0x7)<<8)
+#define DDR0_04_TRTP_DECODE(n)		((((u32)(n))>>8)&0x7)
+
+#define DDR0_05				0x05
+#define DDR0_05_TMRD_MASK		0x1F000000
+#define DDR0_05_TMRD_ENCODE(n)		((((u32)(n))&0x1F)<<24)
+#define DDR0_05_TMRD_DECODE(n)		((((u32)(n))>>24)&0x1F)
+#define DDR0_05_TEMRS_MASK		0x00070000
+#define DDR0_05_TEMRS_ENCODE(n)		((((u32)(n))&0x7)<<16)
+#define DDR0_05_TEMRS_DECODE(n)		((((u32)(n))>>16)&0x7)
+#define DDR0_05_TRP_MASK		0x00000F00
+#define DDR0_05_TRP_ENCODE(n)		((((u32)(n))&0xF)<<8)
+#define DDR0_05_TRP_DECODE(n)		((((u32)(n))>>8)&0xF)
+#define DDR0_05_TRAS_MIN_MASK		0x000000FF
+#define DDR0_05_TRAS_MIN_ENCODE(n)	((((u32)(n))&0xFF)<<0)
+#define DDR0_05_TRAS_MIN_DECODE(n)	((((u32)(n))>>0)&0xFF)
+
+#define DDR0_06				0x06
+#define DDR0_06_WRITEINTERP_MASK	0x01000000
+#define DDR0_06_WRITEINTERP_ENCODE(n)	((((u32)(n))&0x1)<<24)
+#define DDR0_06_WRITEINTERP_DECODE(n)	((((u32)(n))>>24)&0x1)
+#define DDR0_06_TWTR_MASK		0x00070000
+#define DDR0_06_TWTR_ENCODE(n)		((((u32)(n))&0x7)<<16)
+#define DDR0_06_TWTR_DECODE(n)		((((u32)(n))>>16)&0x7)
+#define DDR0_06_TDLL_MASK		0x0000FF00
+#define DDR0_06_TDLL_ENCODE(n)		((((u32)(n))&0xFF)<<8)
+#define DDR0_06_TDLL_DECODE(n)		((((u32)(n))>>8)&0xFF)
+#define DDR0_06_TRFC_MASK		0x0000007F
+#define DDR0_06_TRFC_ENCODE(n)		((((u32)(n))&0x7F)<<0)
+#define DDR0_06_TRFC_DECODE(n)		((((u32)(n))>>0)&0x7F)
+
+#define DDR0_07				0x07
+#define DDR0_07_NO_CMD_INIT_MASK	0x01000000
+#define DDR0_07_NO_CMD_INIT_ENCODE(n)	((((u32)(n))&0x1)<<24)
+#define DDR0_07_NO_CMD_INIT_DECODE(n)	((((u32)(n))>>24)&0x1)
+#define DDR0_07_TFAW_MASK		0x001F0000
+#define DDR0_07_TFAW_ENCODE(n)		((((u32)(n))&0x1F)<<16)
+#define DDR0_07_TFAW_DECODE(n)		((((u32)(n))>>16)&0x1F)
+#define DDR0_07_AUTO_REFRESH_MODE_MASK	0x00000100
+#define DDR0_07_AUTO_REFRESH_MODE_ENCODE(n) ((((u32)(n))&0x1)<<8)
+#define DDR0_07_AUTO_REFRESH_MODE_DECODE(n) ((((u32)(n))>>8)&0x1)
+#define DDR0_07_AREFRESH_MASK		0x00000001
+#define DDR0_07_AREFRESH_ENCODE(n)	((((u32)(n))&0x1)<<0)
+#define DDR0_07_AREFRESH_DECODE(n)	((((u32)(n))>>0)&0x1)
+
+#define DDR0_08				0x08
+#define DDR0_08_WRLAT_MASK		0x07000000
+#define DDR0_08_WRLAT_ENCODE(n)		((((u32)(n))&0x7)<<24)
+#define DDR0_08_WRLAT_DECODE(n)		((((u32)(n))>>24)&0x7)
+#define DDR0_08_TCPD_MASK		0x00FF0000
+#define DDR0_08_TCPD_ENCODE(n)		((((u32)(n))&0xFF)<<16)
+#define DDR0_08_TCPD_DECODE(n)		((((u32)(n))>>16)&0xFF)
+#define DDR0_08_DQS_N_EN_MASK		0x00000100
+#define DDR0_08_DQS_N_EN_ENCODE(n)	((((u32)(n))&0x1)<<8)
+#define DDR0_08_DQS_N_EN_DECODE(n)	((((u32)(n))>>8)&0x1)
+#define DDR0_08_DDRII_SDRAM_MODE_MASK	0x00000001
+#define DDR0_08_DDRII_ENCODE(n)		((((u32)(n))&0x1)<<0)
+#define DDR0_08_DDRII_DECODE(n)		((((u32)(n))>>0)&0x1)
+
+#define DDR0_09				0x09
+#define DDR0_09_OCD_ADJUST_PDN_CS_0_MASK 0x1F000000
+#define DDR0_09_OCD_ADJUST_PDN_CS_0_ENCODE(n) ((((u32)(n))&0x1F)<<24)
+#define DDR0_09_OCD_ADJUST_PDN_CS_0_DECODE(n) ((((u32)(n))>>24)&0x1F)
+#define DDR0_09_RTT_0_MASK		0x00030000
+#define DDR0_09_RTT_0_ENCODE(n)		((((u32)(n))&0x3)<<16)
+#define DDR0_09_RTT_0_DECODE(n)		((((u32)(n))>>16)&0x3)
+#define DDR0_09_WR_DQS_SHIFT_BYPASS_MASK  0x00007F00
+#define DDR0_09_WR_DQS_SHIFT_BYPASS_ENCODE(n) ((((u32)(n))&0x7F)<<8)
+#define DDR0_09_WR_DQS_SHIFT_BYPASS_DECODE(n) ((((u32)(n))>>8)&0x7F)
+#define DDR0_09_WR_DQS_SHIFT_MASK	0x0000007F
+#define DDR0_09_WR_DQS_SHIFT_ENCODE(n)	((((u32)(n))&0x7F)<<0)
+#define DDR0_09_WR_DQS_SHIFT_DECODE(n)	((((u32)(n))>>0)&0x7F)
+
+#define DDR0_10				0x0A
+#define DDR0_10_WRITE_MODEREG_MASK	0x00010000	/* Write only */
+#define DDR0_10_WRITE_MODEREG_ENCODE(n)	((((u32)(n))&0x1)<<16)
+#define DDR0_10_WRITE_MODEREG_DECODE(n)	((((u32)(n))>>16)&0x1)
+#define DDR0_10_CS_MAP_MASK		0x00000300
+#define DDR0_10_CS_MAP_NO_MEM		0x00000000
+#define DDR0_10_CS_MAP_RANK0_INSTALLED	0x00000100
+#define DDR0_10_CS_MAP_RANK1_INSTALLED	0x00000200
+#define DDR0_10_CS_MAP_ENCODE(n)	((((u32)(n))&0x3)<<8)
+#define DDR0_10_CS_MAP_DECODE(n)	((((u32)(n))>>8)&0x3)
+#define DDR0_10_OCD_ADJUST_PUP_CS_0_MASK  0x0000001F
+#define DDR0_10_OCD_ADJUST_PUP_CS_0_ENCODE(n) ((((u32)(n))&0x1F)<<0)
+#define DDR0_10_OCD_ADJUST_PUP_CS_0_DECODE(n) ((((u32)(n))>>0)&0x1F)
+
+#define DDR0_11				0x0B
+#define DDR0_11_SREFRESH_MASK		0x01000000
+#define DDR0_11_SREFRESH_ENCODE(n)	((((u32)(n))&0x1)<<24)
+#define DDR0_11_SREFRESH_DECODE(n)	((((u32)(n))>>24)&0x1F)
+#define DDR0_11_TXSNR_MASK		0x00FF0000
+#define DDR0_11_TXSNR_ENCODE(n)		((((u32)(n))&0xFF)<<16)
+#define DDR0_11_TXSNR_DECODE(n)		((((u32)(n))>>16)&0xFF)
+#define DDR0_11_TXSR_MASK		0x0000FF00
+#define DDR0_11_TXSR_ENCODE(n)		((((u32)(n))&0xFF)<<8)
+#define DDR0_11_TXSR_DECODE(n)		((((u32)(n))>>8)&0xFF)
+
+#define DDR0_12				0x0C
+#define DDR0_12_TCKE_MASK		0x0000007
+#define DDR0_12_TCKE_ENCODE(n)		((((u32)(n))&0x7)<<0)
+#define DDR0_12_TCKE_DECODE(n)		((((u32)(n))>>0)&0x7)
+
+#define DDR0_14				0x0E
+#define DDR0_14_DLL_BYPASS_MODE_MASK	0x01000000
+#define DDR0_14_DLL_BYPASS_MODE_ENCODE(n) ((((u32)(n))&0x1)<<24)
+#define DDR0_14_DLL_BYPASS_MODE_DECODE(n) ((((u32)(n))>>24)&0x1)
+#define DDR0_14_REDUC_MASK		0x00010000
+#define DDR0_14_REDUC_64BITS		0x00000000
+#define DDR0_14_REDUC_32BITS		0x00010000
+#define DDR0_14_REDUC_ENCODE(n)		((((u32)(n))&0x1)<<16)
+#define DDR0_14_REDUC_DECODE(n)		((((u32)(n))>>16)&0x1)
+#define DDR0_14_REG_DIMM_ENABLE_MASK	0x00000100
+#define DDR0_14_REG_DIMM_ENABLE_ENCODE(n) ((((u32)(n))&0x1)<<8)
+#define DDR0_14_REG_DIMM_ENABLE_DECODE(n) ((((u32)(n))>>8)&0x1)
+
+#define DDR0_17				0x11
+#define DDR0_17_DLL_DQS_DELAY_0_MASK	0x7F000000
+#define DDR0_17_DLL_DQS_DELAY_0_ENCODE(n) ((((u32)(n))&0x7F)<<24)
+#define DDR0_17_DLL_DQS_DELAY_0_DECODE(n) ((((u32)(n))>>24)&0x7F)
+#define DDR0_17_DLLLOCKREG_MASK		0x00010000	/* Read only */
+#define DDR0_17_DLLLOCKREG_LOCKED	0x00010000
+#define DDR0_17_DLLLOCKREG_UNLOCKED	0x00000000
+#define DDR0_17_DLLLOCKREG_ENCODE(n)	((((u32)(n))&0x1)<<16)
+#define DDR0_17_DLLLOCKREG_DECODE(n)	((((u32)(n))>>16)&0x1)
+#define DDR0_17_DLL_LOCK_MASK		0x00007F00	/* Read only */
+#define DDR0_17_DLL_LOCK_ENCODE(n)	((((u32)(n))&0x7F)<<8)
+#define DDR0_17_DLL_LOCK_DECODE(n)	((((u32)(n))>>8)&0x7F)
+
+#define DDR0_18				0x12
+#define DDR0_18_DLL_DQS_DELAY_X_MASK	0x7F7F7F7F
+#define DDR0_18_DLL_DQS_DELAY_4_MASK	0x7F000000
+#define DDR0_18_DLL_DQS_DELAY_4_ENCODE(n) ((((u32)(n))&0x7F)<<24)
+#define DDR0_18_DLL_DQS_DELAY_4_DECODE(n) ((((u32)(n))>>24)&0x7F)
+#define DDR0_18_DLL_DQS_DELAY_3_MASK	0x007F0000
+#define DDR0_18_DLL_DQS_DELAY_3_ENCODE(n) ((((u32)(n))&0x7F)<<16)
+#define DDR0_18_DLL_DQS_DELAY_3_DECODE(n) ((((u32)(n))>>16)&0x7F)
+#define DDR0_18_DLL_DQS_DELAY_2_MASK	0x00007F00
+#define DDR0_18_DLL_DQS_DELAY_2_ENCODE(n) ((((u32)(n))&0x7F)<<8)
+#define DDR0_18_DLL_DQS_DELAY_2_DECODE(n) ((((u32)(n))>>8)&0x7F)
+#define DDR0_18_DLL_DQS_DELAY_1_MASK	0x0000007F
+#define DDR0_18_DLL_DQS_DELAY_1_ENCODE(n) ((((u32)(n))&0x7F)<<0)
+#define DDR0_18_DLL_DQS_DELAY_1_DECODE(n) ((((u32)(n))>>0)&0x7F)
+
+#define DDR0_19				0x13
+#define DDR0_19_DLL_DQS_DELAY_X_MASK	0x7F7F7F7F
+#define DDR0_19_DLL_DQS_DELAY_8_MASK	0x7F000000
+#define DDR0_19_DLL_DQS_DELAY_8_ENCODE(n) ((((u32)(n))&0x7F)<<24)
+#define DDR0_19_DLL_DQS_DELAY_8_DECODE(n) ((((u32)(n))>>24)&0x7F)
+#define DDR0_19_DLL_DQS_DELAY_7_MASK	0x007F0000
+#define DDR0_19_DLL_DQS_DELAY_7_ENCODE(n) ((((u32)(n))&0x7F)<<16)
+#define DDR0_19_DLL_DQS_DELAY_7_DECODE(n) ((((u32)(n))>>16)&0x7F)
+#define DDR0_19_DLL_DQS_DELAY_6_MASK	0x00007F00
+#define DDR0_19_DLL_DQS_DELAY_6_ENCODE(n) ((((u32)(n))&0x7F)<<8)
+#define DDR0_19_DLL_DQS_DELAY_6_DECODE(n) ((((u32)(n))>>8)&0x7F)
+#define DDR0_19_DLL_DQS_DELAY_5_MASK	0x0000007F
+#define DDR0_19_DLL_DQS_DELAY_5_ENCODE(n) ((((u32)(n))&0x7F)<<0)
+#define DDR0_19_DLL_DQS_DELAY_5_DECODE(n) ((((u32)(n))>>0)&0x7F)
+
+#define DDR0_20				0x14
+#define DDR0_20_DLL_DQS_BYPASS_3_MASK	0x7F000000
+#define DDR0_20_DLL_DQS_BYPASS_3_ENCODE(n) ((((u32)(n))&0x7F)<<24)
+#define DDR0_20_DLL_DQS_BYPASS_3_DECODE(n) ((((u32)(n))>>24)&0x7F)
+#define DDR0_20_DLL_DQS_BYPASS_2_MASK	0x007F0000
+#define DDR0_20_DLL_DQS_BYPASS_2_ENCODE(n) ((((u32)(n))&0x7F)<<16)
+#define DDR0_20_DLL_DQS_BYPASS_2_DECODE(n) ((((u32)(n))>>16)&0x7F)
+#define DDR0_20_DLL_DQS_BYPASS_1_MASK	0x00007F00
+#define DDR0_20_DLL_DQS_BYPASS_1_ENCODE(n) ((((u32)(n))&0x7F)<<8)
+#define DDR0_20_DLL_DQS_BYPASS_1_DECODE(n) ((((u32)(n))>>8)&0x7F)
+#define DDR0_20_DLL_DQS_BYPASS_0_MASK	0x0000007F
+#define DDR0_20_DLL_DQS_BYPASS_0_ENCODE(n) ((((u32)(n))&0x7F)<<0)
+#define DDR0_20_DLL_DQS_BYPASS_0_DECODE(n) ((((u32)(n))>>0)&0x7F)
+
+#define DDR0_21				0x15
+#define DDR0_21_DLL_DQS_BYPASS_7_MASK	0x7F000000
+#define DDR0_21_DLL_DQS_BYPASS_7_ENCODE(n) ((((u32)(n))&0x7F)<<24)
+#define DDR0_21_DLL_DQS_BYPASS_7_DECODE(n) ((((u32)(n))>>24)&0x7F)
+#define DDR0_21_DLL_DQS_BYPASS_6_MASK	0x007F0000
+#define DDR0_21_DLL_DQS_BYPASS_6_ENCODE(n) ((((u32)(n))&0x7F)<<16)
+#define DDR0_21_DLL_DQS_BYPASS_6_DECODE(n) ((((u32)(n))>>16)&0x7F)
+#define DDR0_21_DLL_DQS_BYPASS_5_MASK	0x00007F00
+#define DDR0_21_DLL_DQS_BYPASS_5_ENCODE(n) ((((u32)(n))&0x7F)<<8)
+#define DDR0_21_DLL_DQS_BYPASS_5_DECODE(n) ((((u32)(n))>>8)&0x7F)
+#define DDR0_21_DLL_DQS_BYPASS_4_MASK	0x0000007F
+#define DDR0_21_DLL_DQS_BYPASS_4_ENCODE(n) ((((u32)(n))&0x7F)<<0)
+#define DDR0_21_DLL_DQS_BYPASS_4_DECODE(n) ((((u32)(n))>>0)&0x7F)
+
+#define DDR0_22				0x16
+#define DDR0_22_CTRL_RAW_MASK		0x03000000
+#define DDR0_22_CTRL_RAW_ECC_DISABLE	0x00000000
+#define DDR0_22_CTRL_RAW_ECC_CHECK_ONLY	0x01000000
+#define DDR0_22_CTRL_RAW_NO_ECC_RAM	0x02000000
+#define DDR0_22_CTRL_RAW_ECC_ENABLE	0x03000000
+#define DDR0_22_CTRL_RAW_ENCODE(n)	((((u32)(n))&0x3)<<24)
+#define DDR0_22_CTRL_RAW_DECODE(n)	((((u32)(n))>>24)&0x3)
+#define DDR0_22_DQS_OUT_SHIFT_BYPASS_MASK 0x007F0000
+#define DDR0_22_DQS_OUT_SHIFT_BYPASS_ENCODE(n) ((((u32)(n))&0x7F)<<16)
+#define DDR0_22_DQS_OUT_SHIFT_BYPASS_DECODE(n) ((((u32)(n))>>16)&0x7F)
+#define DDR0_22_DQS_OUT_SHIFT_MASK	0x00007F00
+#define DDR0_22_DQS_OUT_SHIFT_ENCODE(n)	((((u32)(n))&0x7F)<<8)
+#define DDR0_22_DQS_OUT_SHIFT_DECODE(n)	((((u32)(n))>>8)&0x7F)
+#define DDR0_22_DLL_DQS_BYPASS_8_MASK	0x0000007F
+#define DDR0_22_DLL_DQS_BYPASS_8_ENCODE(n) ((((u32)(n))&0x7F)<<0)
+#define DDR0_22_DLL_DQS_BYPASS_8_DECODE(n) ((((u32)(n))>>0)&0x7F)
+
+#define DDR0_23				0x17
+#define DDR0_23_ODT_RD_MAP_CS0_MASK	0x03000000
+#define DDR0_23_ODT_RD_MAP_CS0_ENCODE(n) ((((u32)(n))&0x3)<<24)
+#define DDR0_23_ODT_RD_MAP_CS0_DECODE(n) ((((u32)(n))>>24)&0x3)
+#define DDR0_23_ECC_C_SYND_MASK		0x00FF0000	/* Read only */
+#define DDR0_23_ECC_C_SYND_ENCODE(n)	((((u32)(n))&0xFF)<<16)
+#define DDR0_23_ECC_C_SYND_DECODE(n)	((((u32)(n))>>16)&0xFF)
+#define DDR0_23_ECC_U_SYND_MASK		0x0000FF00	/* Read only */
+#define DDR0_23_ECC_U_SYND_ENCODE(n)	((((u32)(n))&0xFF)<<8)
+#define DDR0_23_ECC_U_SYND_DECODE(n)	((((u32)(n))>>8)&0xFF)
+#define DDR0_23_FWC_MASK		0x00000001	/* Write only */
+#define DDR0_23_FWC_ENCODE(n)		((((u32)(n))&0x1)<<0)
+#define DDR0_23_FWC_DECODE(n)		((((u32)(n))>>0)&0x1)
+
+#define DDR0_24				0x18
+#define DDR0_24_RTT_PAD_TERMINATION_MASK 0x03000000
+#define DDR0_24_RTT_PAD_TERMINATION_ENCODE(n) ((((u32)(n))&0x3)<<24)
+#define DDR0_24_RTT_PAD_TERMINATION_DECODE(n) ((((u32)(n))>>24)&0x3)
+#define DDR0_24_ODT_WR_MAP_CS1_MASK	0x00030000
+#define DDR0_24_ODT_WR_MAP_CS1_ENCODE(n) ((((u32)(n))&0x3)<<16)
+#define DDR0_24_ODT_WR_MAP_CS1_DECODE(n) ((((u32)(n))>>16)&0x3)
+#define DDR0_24_ODT_RD_MAP_CS1_MASK	0x00000300
+#define DDR0_24_ODT_RD_MAP_CS1_ENCODE(n) ((((u32)(n))&0x3)<<8)
+#define DDR0_24_ODT_RD_MAP_CS1_DECODE(n) ((((u32)(n))>>8)&0x3)
+#define DDR0_24_ODT_WR_MAP_CS0_MASK	0x00000003
+#define DDR0_24_ODT_WR_MAP_CS0_ENCODE(n) ((((u32)(n))&0x3)<<0)
+#define DDR0_24_ODT_WR_MAP_CS0_DECODE(n) ((((u32)(n))>>0)&0x3)
+
+#define DDR0_25				0x19
+#define DDR0_25_VERSION_MASK		0xFFFF0000	/* Read only */
+#define DDR0_25_VERSION_ENCODE(n)	((((u32)(n))&0xFFFF)<<16)
+#define DDR0_25_VERSION_DECODE(n)	((((u32)(n))>>16)&0xFFFF)
+#define DDR0_25_OUT_OF_RANGE_LENGTH_MASK  0x000003FF	/* Read only */
+#define DDR0_25_OUT_OF_RANGE_LENGTH_ENCODE(n) ((((u32)(n))&0x3FF)<<0)
+#define DDR0_25_OUT_OF_RANGE_LENGTH_DECODE(n) ((((u32)(n))>>0)&0x3FF)
+
+#define DDR0_26				0x1A
+#define DDR0_26_TRAS_MAX_MASK		0xFFFF0000
+#define DDR0_26_TRAS_MAX_ENCODE(n)	((((u32)(n))&0xFFFF)<<16)
+#define DDR0_26_TRAS_MAX_DECODE(n)	((((u32)(n))>>16)&0xFFFF)
+#define DDR0_26_TREF_MASK		0x00003FFF
+#define DDR0_26_TREF_ENCODE(n)		((((u32)(n))&0x3FFF)<<0)
+#define DDR0_26_TREF_DECODE(n)		((((u32)(n))>>0)&0x3FFF)
+
+#define DDR0_27				0x1B
+#define DDR0_27_EMRS_DATA_MASK		0x3FFF0000
+#define DDR0_27_EMRS_DATA_ENCODE(n)	((((u32)(n))&0x3FFF)<<16)
+#define DDR0_27_EMRS_DATA_DECODE(n)	((((u32)(n))>>16)&0x3FFF)
+#define DDR0_27_TINIT_MASK		0x0000FFFF
+#define DDR0_27_TINIT_ENCODE(n)		((((u32)(n))&0xFFFF)<<0)
+#define DDR0_27_TINIT_DECODE(n)		((((u32)(n))>>0)&0xFFFF)
+
+#define DDR0_28				0x1C
+#define DDR0_28_EMRS3_DATA_MASK		0x3FFF0000
+#define DDR0_28_EMRS3_DATA_ENCODE(n)	((((u32)(n))&0x3FFF)<<16)
+#define DDR0_28_EMRS3_DATA_DECODE(n)	((((u32)(n))>>16)&0x3FFF)
+#define DDR0_28_EMRS2_DATA_MASK		0x00003FFF
+#define DDR0_28_EMRS2_DATA_ENCODE(n)	((((u32)(n))&0x3FFF)<<0)
+#define DDR0_28_EMRS2_DATA_DECODE(n)	((((u32)(n))>>0)&0x3FFF)
+
+#define DDR0_31				0x1F
+#define DDR0_31_XOR_CHECK_BITS_MASK	0x0000FFFF
+#define DDR0_31_XOR_CHECK_BITS_ENCODE(n) ((((u32)(n))&0xFFFF)<<0)
+#define DDR0_31_XOR_CHECK_BITS_DECODE(n) ((((u32)(n))>>0)&0xFFFF)
+
+#define DDR0_32				0x20
+#define DDR0_32_OUT_OF_RANGE_ADDR_MASK	0xFFFFFFFF	/* Read only */
+#define DDR0_32_OUT_OF_RANGE_ADDR_ENCODE(n) ((((u32)(n))&0xFFFFFFFF)<<0)
+#define DDR0_32_OUT_OF_RANGE_ADDR_DECODE(n) ((((u32)(n))>>0)&0xFFFFFFFF)
+
+#define DDR0_33				0x21
+#define DDR0_33_OUT_OF_RANGE_ADDR_MASK	0x00000001	/* Read only */
+#define DDR0_33_OUT_OF_RANGE_ADDR_ENCODE(n) ((((u32)(n))&0x1)<<0)
+#define DDR0_33_OUT_OF_RANGE_ADDR_DECODE(n) ((((u32)(n))>>0)&0x1)
+
+#define DDR0_34				0x22
+#define DDR0_34_ECC_U_ADDR_MASK		0xFFFFFFFF	/* Read only */
+#define DDR0_34_ECC_U_ADDR_ENCODE(n)	((((u32)(n))&0xFFFFFFFF)<<0)
+#define DDR0_34_ECC_U_ADDR_DECODE(n)	((((u32)(n))>>0)&0xFFFFFFFF)
+
+#define DDR0_35				0x23
+#define DDR0_35_ECC_U_ADDR_MASK		0x00000001	/* Read only */
+#define DDR0_35_ECC_U_ADDR_ENCODE(n)	((((u32)(n))&0x1)<<0)
+#define DDR0_35_ECC_U_ADDR_DECODE(n)	((((u32)(n))>>0)&0x1)
+
+#define DDR0_36				0x24
+#define DDR0_36_ECC_U_DATA_MASK		0xFFFFFFFF	/* Read only */
+#define DDR0_36_ECC_U_DATA_ENCODE(n)	((((u32)(n))&0xFFFFFFFF)<<0)
+#define DDR0_36_ECC_U_DATA_DECODE(n)	((((u32)(n))>>0)&0xFFFFFFFF)
+
+#define DDR0_37				0x25
+#define DDR0_37_ECC_U_DATA_MASK		0xFFFFFFFF	/* Read only */
+#define DDR0_37_ECC_U_DATA_ENCODE(n)	((((u32)(n))&0xFFFFFFFF)<<0)
+#define DDR0_37_ECC_U_DATA_DECODE(n)	((((u32)(n))>>0)&0xFFFFFFFF)
+
+#define DDR0_38				0x26
+#define DDR0_38_ECC_C_ADDR_MASK		0xFFFFFFFF	/* Read only */
+#define DDR0_38_ECC_C_ADDR_ENCODE(n)	((((u32)(n))&0xFFFFFFFF)<<0)
+#define DDR0_38_ECC_C_ADDR_DECODE(n)	((((u32)(n))>>0)&0xFFFFFFFF)
+
+#define DDR0_39				0x27
+#define DDR0_39_ECC_C_ADDR_MASK		0x00000001	/* Read only */
+#define DDR0_39_ECC_C_ADDR_ENCODE(n)	((((u32)(n))&0x1)<<0)
+#define DDR0_39_ECC_C_ADDR_DECODE(n)	((((u32)(n))>>0)&0x1)
+
+#define DDR0_40				0x28
+#define DDR0_40_ECC_C_DATA_MASK		0xFFFFFFFF	/* Read only */
+#define DDR0_40_ECC_C_DATA_ENCODE(n)	((((u32)(n))&0xFFFFFFFF)<<0)
+#define DDR0_40_ECC_C_DATA_DECODE(n)	((((u32)(n))>>0)&0xFFFFFFFF)
+
+#define DDR0_41				0x29
+#define DDR0_41_ECC_C_DATA_MASK		0xFFFFFFFF	/* Read only */
+#define DDR0_41_ECC_C_DATA_ENCODE(n)	((((u32)(n))&0xFFFFFFFF)<<0)
+#define DDR0_41_ECC_C_DATA_DECODE(n)	((((u32)(n))>>0)&0xFFFFFFFF)
+
+#define DDR0_42				0x2A
+#define DDR0_42_ADDR_PINS_MASK		0x07000000
+#define DDR0_42_ADDR_PINS_ENCODE(n)	((((u32)(n))&0x7)<<24)
+#define DDR0_42_ADDR_PINS_DECODE(n)	((((u32)(n))>>24)&0x7)
+#define DDR0_42_CASLAT_LIN_GATE_MASK	0x0000000F
+#define DDR0_42_CASLAT_LIN_GATE_ENCODE(n) ((((u32)(n))&0xF)<<0)
+#define DDR0_42_CASLAT_LIN_GATE_DECODE(n) ((((u32)(n))>>0)&0xF)
+
+#define DDR0_43				0x2B
+#define DDR0_43_TWR_MASK		0x07000000
+#define DDR0_43_TWR_ENCODE(n)		((((u32)(n))&0x7)<<24)
+#define DDR0_43_TWR_DECODE(n)		((((u32)(n))>>24)&0x7)
+#define DDR0_43_APREBIT_MASK		0x000F0000
+#define DDR0_43_APREBIT_ENCODE(n)	((((u32)(n))&0xF)<<16)
+#define DDR0_43_APREBIT_DECODE(n)	((((u32)(n))>>16)&0xF)
+#define DDR0_43_COLUMN_SIZE_MASK	0x00000700
+#define DDR0_43_COLUMN_SIZE_ENCODE(n)	((((u32)(n))&0x7)<<8)
+#define DDR0_43_COLUMN_SIZE_DECODE(n)	((((u32)(n))>>8)&0x7)
+#define DDR0_43_EIGHT_BANK_MODE_MASK	0x00000001
+#define DDR0_43_EIGHT_BANK_MODE_8_BANKS	0x00000001
+#define DDR0_43_EIGHT_BANK_MODE_4_BANKS	0x00000000
+#define DDR0_43_EIGHT_BANK_MODE_ENCODE(n) ((((u32)(n))&0x1)<<0)
+#define DDR0_43_EIGHT_BANK_MODE_DECODE(n) ((((u32)(n))>>0)&0x1)
+
+#define DDR0_44				0x2C
+#define DDR0_44_TRCD_MASK		0x000000FF
+#define DDR0_44_TRCD_ENCODE(n)		((((u32)(n))&0xFF)<<0)
+#define DDR0_44_TRCD_DECODE(n)		((((u32)(n))>>0)&0xFF)
+
+#endif /* CONFIG_SDRAM_PPC4xx_DENALI_DDR2 */
+
+#ifndef __ASSEMBLY__
+/*
+ * Prototypes
+ */
+inline void ppc4xx_ibm_ddr2_register_dump(void);
+u32 mfdcr_any(u32);
+void mtdcr_any(u32, u32);
+u32 ddr_wrdtr(u32);
+u32 ddr_clktr(u32);
+void spd_ddr_init_hang(void);
+u32 DQS_autocalibration(void);
+phys_size_t sdram_memsize(void);
+void dcbz_area(u32 start_address, u32 num_bytes);
+#endif /* __ASSEMBLY__ */
+
+#endif /* _PPC4xx_SDRAM_H_ */
diff --git a/arch/powerpc/include/asm/ppc4xx-uic.h b/arch/powerpc/include/asm/ppc4xx-uic.h
new file mode 100644
index 0000000..782d045
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx-uic.h
@@ -0,0 +1,304 @@
+/*
+ *  Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.com>
+ *
+ * (C) Copyright 2008-2009
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC4xx_UIC_H_
+#define _PPC4xx_UIC_H_
+
+/*
+ * Define the number of UIC's
+ */
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+    defined(CONFIG_460SX)
+#define UIC_MAX		4
+#elif defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_405EX)
+#define UIC_MAX		3
+#elif defined(CONFIG_440GP) || defined(CONFIG_440SP) || \
+    defined(CONFIG_440EP) || defined(CONFIG_440GR)
+#define UIC_MAX		2
+#else
+#define UIC_MAX		1
+#endif
+
+#define IRQ_MAX		(UIC_MAX * 32)
+
+/*
+ * UIC register
+ */
+#define UIC_SR	0x0			/* UIC status			*/
+#define UIC_ER	0x2			/* UIC enable			*/
+#define UIC_CR	0x3			/* UIC critical			*/
+#define UIC_PR	0x4			/* UIC polarity			*/
+#define UIC_TR	0x5			/* UIC triggering		*/
+#define UIC_MSR 0x6			/* UIC masked status		*/
+#define UIC_VR	0x7			/* UIC vector			*/
+#define UIC_VCR 0x8			/* UIC vector configuration	*/
+
+/*
+ * On 440GX we use the UICB0 as UIC0. Its the root UIC where all other UIC's
+ * are cascaded on. With this trick we can use the common UIC code for 440GX
+ * too.
+ */
+#if defined(CONFIG_440GX)
+#define UIC0_DCR_BASE 0x200
+#define UIC1_DCR_BASE 0xc0
+#define UIC2_DCR_BASE 0xd0
+#define UIC3_DCR_BASE 0x210
+#else
+#define UIC0_DCR_BASE 0xc0
+#define UIC1_DCR_BASE 0xd0
+#define UIC2_DCR_BASE 0xe0
+#define UIC3_DCR_BASE 0xf0
+#endif
+
+#define UIC0SR	(UIC0_DCR_BASE+0x0)	/* UIC0 status			*/
+#define UIC0ER	(UIC0_DCR_BASE+0x2)	/* UIC0 enable			*/
+#define UIC0CR	(UIC0_DCR_BASE+0x3)	/* UIC0 critical		*/
+#define UIC0PR	(UIC0_DCR_BASE+0x4)	/* UIC0 polarity		*/
+#define UIC0TR	(UIC0_DCR_BASE+0x5)	/* UIC0 triggering		*/
+#define UIC0MSR (UIC0_DCR_BASE+0x6)	/* UIC0 masked status		*/
+#define UIC0VR	(UIC0_DCR_BASE+0x7)	/* UIC0 vector			*/
+#define UIC0VCR (UIC0_DCR_BASE+0x8)	/* UIC0 vector configuration	*/
+
+#define UIC1SR	(UIC1_DCR_BASE+0x0)	/* UIC1 status			*/
+#define UIC1ER	(UIC1_DCR_BASE+0x2)	/* UIC1 enable			*/
+#define UIC1CR	(UIC1_DCR_BASE+0x3)	/* UIC1 critical		*/
+#define UIC1PR	(UIC1_DCR_BASE+0x4)	/* UIC1 polarity		*/
+#define UIC1TR	(UIC1_DCR_BASE+0x5)	/* UIC1 triggering		*/
+#define UIC1MSR (UIC1_DCR_BASE+0x6)	/* UIC1 masked status		*/
+#define UIC1VR	(UIC1_DCR_BASE+0x7)	/* UIC1 vector			*/
+#define UIC1VCR (UIC1_DCR_BASE+0x8)	/* UIC1 vector configuration	*/
+
+#define UIC2SR	(UIC2_DCR_BASE+0x0)	/* UIC2 status-Read Clear	*/
+#define UIC2ER	(UIC2_DCR_BASE+0x2)	/* UIC2 enable			*/
+#define UIC2CR	(UIC2_DCR_BASE+0x3)	/* UIC2 critical		*/
+#define UIC2PR	(UIC2_DCR_BASE+0x4)	/* UIC2 polarity		*/
+#define UIC2TR	(UIC2_DCR_BASE+0x5)	/* UIC2 triggering		*/
+#define UIC2MSR (UIC2_DCR_BASE+0x6)	/* UIC2 masked status		*/
+#define UIC2VR	(UIC2_DCR_BASE+0x7)	/* UIC2 vector			*/
+#define UIC2VCR (UIC2_DCR_BASE+0x8)	/* UIC2 vector configuration	*/
+
+#define UIC3SR	(UIC3_DCR_BASE+0x0)	/* UIC3 status-Read Clear	*/
+#define UIC3ER	(UIC3_DCR_BASE+0x2)	/* UIC3 enable			*/
+#define UIC3CR	(UIC3_DCR_BASE+0x3)	/* UIC3 critical		*/
+#define UIC3PR	(UIC3_DCR_BASE+0x4)	/* UIC3 polarity		*/
+#define UIC3TR	(UIC3_DCR_BASE+0x5)	/* UIC3 triggering		*/
+#define UIC3MSR (UIC3_DCR_BASE+0x6)	/* UIC3 masked status		*/
+#define UIC3VR	(UIC3_DCR_BASE+0x7)	/* UIC3 vector			*/
+#define UIC3VCR (UIC3_DCR_BASE+0x8)	/* UIC3 vector configuration	*/
+
+/*
+ * Now the interrupt vector definitions. They are different for most of
+ * the 4xx variants, so we need some more #ifdef's here. No mask
+ * definitions anymore here. For this please use the UIC_MASK macro below.
+ *
+ * Note: Please only define the interrupts really used in U-Boot here.
+ * Those are the cascading and EMAC/MAL related interrupt.
+ */
+
+#if defined(CONFIG_405EP) || defined(CONFIG_405GP)
+#define VECNUM_MAL_SERR		10
+#define VECNUM_MAL_TXEOB	11
+#define VECNUM_MAL_RXEOB	12
+#define VECNUM_MAL_TXDE		13
+#define VECNUM_MAL_RXDE		14
+#define VECNUM_ETH0		15
+#define VECNUM_ETH1_OFFS	2
+#define VECNUM_EIRQ6		29
+#endif /* defined(CONFIG_405EP) */
+
+#if defined(CONFIG_405EZ)
+#define VECNUM_USBDEV		15
+#define VECNUM_ETH0		16
+#define VECNUM_MAL_SERR		18
+#define VECNUM_MAL_TXDE		18
+#define VECNUM_MAL_RXDE		18
+#define VECNUM_MAL_TXEOB	19
+#define VECNUM_MAL_RXEOB	21
+#endif /* CONFIG_405EX */
+
+#if defined(CONFIG_405EX)
+/* UIC 0 */
+#define VECNUM_MAL_TXEOB	10
+#define VECNUM_MAL_RXEOB	11
+#define VECNUM_ETH0		24
+#define VECNUM_ETH1_OFFS	1
+#define VECNUM_UIC2NCI		28
+#define VECNUM_UIC2CI		29
+#define VECNUM_UIC1NCI		30
+#define VECNUM_UIC1CI		31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR		(32 + 0)
+#define VECNUM_MAL_TXDE		(32 + 1)
+#define VECNUM_MAL_RXDE		(32 + 2)
+#endif /* CONFIG_405EX */
+
+#if defined(CONFIG_440GP) || \
+    defined(CONFIG_440EP) || defined(CONFIG_440GR)
+/* UIC 0 */
+#define VECNUM_MAL_TXEOB	10
+#define VECNUM_MAL_RXEOB	11
+#define VECNUM_UIC1NCI		30
+#define VECNUM_UIC1CI		31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR		(32 + 0)
+#define VECNUM_MAL_TXDE		(32 + 1)
+#define VECNUM_MAL_RXDE		(32 + 2)
+#define VECNUM_USBDEV		(32 + 23)
+#define VECNUM_ETH0		(32 + 28)
+#define VECNUM_ETH1_OFFS	2
+#endif /* CONFIG_440GP */
+
+#if defined(CONFIG_440GX)
+/* UICB 0 (440GX only) */
+/*
+ * All those defines below are off-by-one, so that the common UIC code
+ * can be used. So VECNUM_UIC1CI refers to VECNUM_UIC0CI etc.
+ */
+#define VECNUM_UIC1CI		0
+#define VECNUM_UIC1NCI		1
+#define VECNUM_UIC2CI		2
+#define VECNUM_UIC2NCI		3
+#define VECNUM_UIC3CI		4
+#define VECNUM_UIC3NCI		5
+
+/* UIC 0, used as UIC1 on 440GX because of UICB0 */
+#define VECNUM_MAL_TXEOB	(32 + 10)
+#define VECNUM_MAL_RXEOB	(32 + 11)
+
+/* UIC 1, used as UIC2 on 440GX because of UICB0 */
+#define VECNUM_MAL_SERR		(64 + 0)
+#define VECNUM_MAL_TXDE		(64 + 1)
+#define VECNUM_MAL_RXDE		(64 + 2)
+#define VECNUM_ETH0		(64 + 28)
+#define VECNUM_ETH1_OFFS	2
+#endif /* CONFIG_440GX */
+
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+/* UIC 0 */
+#define VECNUM_MAL_TXEOB	10
+#define VECNUM_MAL_RXEOB	11
+#define VECNUM_USBDEV		20
+#define VECNUM_ETH0		24
+#define VECNUM_ETH1_OFFS	1
+#define VECNUM_UIC2NCI		28
+#define VECNUM_UIC2CI		29
+#define VECNUM_UIC1NCI		30
+#define VECNUM_UIC1CI		31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR		(32 + 0)
+#define VECNUM_MAL_TXDE		(32 + 1)
+#define VECNUM_MAL_RXDE		(32 + 2)
+
+/* UIC 2 */
+#define VECNUM_EIRQ2		(64 + 3)
+#endif /* CONFIG_440EPX */
+
+#if defined(CONFIG_440SP)
+/* UIC 0 */
+#define VECNUM_UIC1NCI		30
+#define VECNUM_UIC1CI		31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR		(32 + 1)
+#define VECNUM_MAL_TXDE		(32 + 2)
+#define VECNUM_MAL_RXDE		(32 + 3)
+#define VECNUM_MAL_TXEOB	(32 + 6)
+#define VECNUM_MAL_RXEOB	(32 + 7)
+#define VECNUM_ETH0		(32 + 28)
+#endif /* CONFIG_440SP */
+
+#if defined(CONFIG_440SPE)
+/* UIC 0 */
+#define VECNUM_UIC2NCI		10
+#define VECNUM_UIC2CI		11
+#define VECNUM_UIC3NCI		16
+#define VECNUM_UIC3CI		17
+#define VECNUM_UIC1NCI		30
+#define VECNUM_UIC1CI		31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR		(32 + 1)
+#define VECNUM_MAL_TXDE		(32 + 2)
+#define VECNUM_MAL_RXDE		(32 + 3)
+#define VECNUM_MAL_TXEOB	(32 + 6)
+#define VECNUM_MAL_RXEOB	(32 + 7)
+#define VECNUM_ETH0		(32 + 28)
+#endif /* CONFIG_440SPE */
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+/* UIC 0 */
+#define VECNUM_UIC2NCI		10
+#define VECNUM_UIC2CI		11
+#define VECNUM_UIC3NCI		16
+#define VECNUM_UIC3CI		17
+#define VECNUM_UIC1NCI		30
+#define VECNUM_UIC1CI		31
+
+/* UIC 2 */
+#define VECNUM_MAL_SERR		(64 + 3)
+#define	VECNUM_MAL_TXDE		(64 + 4)
+#define	VECNUM_MAL_RXDE		(64 + 5)
+#define VECNUM_MAL_TXEOB	(64 + 6)
+#define	VECNUM_MAL_RXEOB	(64 + 7)
+#define	VECNUM_ETH0		(64 + 16)
+#define VECNUM_ETH1_OFFS	1
+#endif /* CONFIG_460EX */
+
+#if defined(CONFIG_460SX)
+/* UIC 0 */
+#define VECNUM_UIC2NCI		10
+#define VECNUM_UIC2CI		11
+#define VECNUM_UIC3NCI		16
+#define VECNUM_UIC3CI		17
+#define	VECNUM_ETH0		19
+#define VECNUM_ETH1_OFFS	1
+#define VECNUM_UIC1NCI		30
+#define VECNUM_UIC1CI		31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR		(32 + 1)
+#define	VECNUM_MAL_TXDE		(32 + 2)
+#define	VECNUM_MAL_RXDE		(32 + 3)
+#define VECNUM_MAL_TXEOB	(32 + 6)
+#define	VECNUM_MAL_RXEOB	(32 + 7)
+#endif /* CONFIG_460EX */
+
+#if !defined(VECNUM_ETH1_OFFS)
+#define VECNUM_ETH1_OFFS	1
+#endif
+
+/*
+ * Mask definitions (used for example in 4xx_enet.c)
+ */
+#define UIC_MASK(vec)		(0x80000000 >> ((vec) & 0x1f))
+/* UIC_NR won't work for 440GX because of its specific UIC DCR addresses */
+#define UIC_NR(vec)		((vec) >> 5)
+
+#endif /* _PPC4xx_UIC_H_ */
diff --git a/arch/powerpc/include/asm/ppc4xx_config.h b/arch/powerpc/include/asm/ppc4xx_config.h
new file mode 100644
index 0000000..49acb60
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx_config.h
@@ -0,0 +1,42 @@
+/*
+ * (C) Copyright 2008-2009
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * (C) Copyright 2009
+ * Dirk Eibach,  Guntermann & Drunck GmbH, eibach@gdsys.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef __PPC4xx_CONFIG_H
+#define __PPC4xx_CONFIG_H
+
+#include <common.h>
+
+struct ppc4xx_config {
+	char label[16];
+	char description[64];
+	u8 val[CONFIG_4xx_CONFIG_BLOCKSIZE];
+};
+
+extern struct ppc4xx_config ppc4xx_config_val[];
+extern int ppc4xx_config_count;
+
+#endif /* __PPC4xx_CONFIG_H */
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
new file mode 100644
index 0000000..9ec319a
--- /dev/null
+++ b/arch/powerpc/include/asm/processor.h
@@ -0,0 +1,1285 @@
+#ifndef __ASM_PPC_PROCESSOR_H
+#define __ASM_PPC_PROCESSOR_H
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
+#include <linux/config.h>
+
+#include <asm/ptrace.h>
+#include <asm/types.h>
+
+/* Machine State Register (MSR) Fields */
+
+#ifdef CONFIG_PPC64BRIDGE
+#define MSR_SF		(1<<63)
+#define MSR_ISF		(1<<61)
+#endif /* CONFIG_PPC64BRIDGE */
+#define MSR_UCLE	(1<<26)		/* User-mode cache lock enable (e500) */
+#define MSR_VEC		(1<<25)		/* Enable AltiVec(74xx) */
+#define MSR_SPE		(1<<25)		/* Enable SPE(e500) */
+#define MSR_POW		(1<<18)		/* Enable Power Management */
+#define MSR_WE		(1<<18)		/* Wait State Enable */
+#define MSR_TGPR	(1<<17)		/* TLB Update registers in use */
+#define MSR_CE		(1<<17)		/* Critical Interrupt Enable */
+#define MSR_ILE		(1<<16)		/* Interrupt Little Endian */
+#define MSR_EE		(1<<15)		/* External Interrupt Enable */
+#define MSR_PR		(1<<14)		/* Problem State / Privilege Level */
+#define MSR_FP		(1<<13)		/* Floating Point enable */
+#define MSR_ME		(1<<12)		/* Machine Check Enable */
+#define MSR_FE0		(1<<11)		/* Floating Exception mode 0 */
+#define MSR_SE		(1<<10)		/* Single Step */
+#define MSR_DWE		(1<<10)		/* Debug Wait Enable (4xx) */
+#define MSR_UBLE	(1<<10)		/* BTB lock enable (e500) */
+#define MSR_BE		(1<<9)		/* Branch Trace */
+#define MSR_DE		(1<<9)		/* Debug Exception Enable */
+#define MSR_FE1		(1<<8)		/* Floating Exception mode 1 */
+#define MSR_IP		(1<<6)		/* Exception prefix 0x000/0xFFF */
+#define MSR_IR		(1<<5)		/* Instruction Relocate */
+#define MSR_IS		(1<<5)		/* Book E Instruction space */
+#define MSR_DR		(1<<4)		/* Data Relocate */
+#define MSR_DS		(1<<4)		/* Book E Data space */
+#define MSR_PE		(1<<3)		/* Protection Enable */
+#define MSR_PX		(1<<2)		/* Protection Exclusive Mode */
+#define MSR_PMM		(1<<2)		/* Performance monitor mark bit (e500) */
+#define MSR_RI		(1<<1)		/* Recoverable Exception */
+#define MSR_LE		(1<<0)		/* Little Endian */
+
+#ifdef CONFIG_APUS_FAST_EXCEPT
+#define MSR_		MSR_ME|MSR_IP|MSR_RI
+#else
+#define MSR_		MSR_ME|MSR_RI
+#endif
+#ifndef CONFIG_E500
+#define MSR_KERNEL	MSR_|MSR_IR|MSR_DR
+#else
+#define MSR_KERNEL	MSR_ME
+#endif
+
+/* Floating Point Status and Control Register (FPSCR) Fields */
+
+#define FPSCR_FX	0x80000000	/* FPU exception summary */
+#define FPSCR_FEX	0x40000000	/* FPU enabled exception summary */
+#define FPSCR_VX	0x20000000	/* Invalid operation summary */
+#define FPSCR_OX	0x10000000	/* Overflow exception summary */
+#define FPSCR_UX	0x08000000	/* Underflow exception summary */
+#define FPSCR_ZX	0x04000000	/* Zero-devide exception summary */
+#define FPSCR_XX	0x02000000	/* Inexact exception summary */
+#define FPSCR_VXSNAN	0x01000000	/* Invalid op for SNaN */
+#define FPSCR_VXISI	0x00800000	/* Invalid op for Inv - Inv */
+#define FPSCR_VXIDI	0x00400000	/* Invalid op for Inv / Inv */
+#define FPSCR_VXZDZ	0x00200000	/* Invalid op for Zero / Zero */
+#define FPSCR_VXIMZ	0x00100000	/* Invalid op for Inv * Zero */
+#define FPSCR_VXVC	0x00080000	/* Invalid op for Compare */
+#define FPSCR_FR	0x00040000	/* Fraction rounded */
+#define FPSCR_FI	0x00020000	/* Fraction inexact */
+#define FPSCR_FPRF	0x0001f000	/* FPU Result Flags */
+#define FPSCR_FPCC	0x0000f000	/* FPU Condition Codes */
+#define FPSCR_VXSOFT	0x00000400	/* Invalid op for software request */
+#define FPSCR_VXSQRT	0x00000200	/* Invalid op for square root */
+#define FPSCR_VXCVI	0x00000100	/* Invalid op for integer convert */
+#define FPSCR_VE	0x00000080	/* Invalid op exception enable */
+#define FPSCR_OE	0x00000040	/* IEEE overflow exception enable */
+#define FPSCR_UE	0x00000020	/* IEEE underflow exception enable */
+#define FPSCR_ZE	0x00000010	/* IEEE zero divide exception enable */
+#define FPSCR_XE	0x00000008	/* FP inexact exception enable */
+#define FPSCR_NI	0x00000004	/* FPU non IEEE-Mode */
+#define FPSCR_RN	0x00000003	/* FPU rounding control */
+
+/* Special Purpose Registers (SPRNs)*/
+
+/* PPC440 Architecture is BOOK-E */
+#ifdef CONFIG_440
+#define CONFIG_BOOKE
+#endif
+
+#define SPRN_CCR0	0x3B3	/* Core Configuration Register 0 */
+#ifdef CONFIG_BOOKE
+#define SPRN_CCR1	0x378	/* Core Configuration Register for 440 only */
+#endif
+#define SPRN_CDBCR	0x3D7	/* Cache Debug Control Register */
+#define SPRN_CTR	0x009	/* Count Register */
+#define SPRN_DABR	0x3F5	/* Data Address Breakpoint Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_DAC1	0x3F6	/* Data Address Compare 1 */
+#define SPRN_DAC2	0x3F7	/* Data Address Compare 2 */
+#else
+#define SPRN_DAC1	0x13C	/* Book E Data Address Compare 1 */
+#define SPRN_DAC2	0x13D	/* Book E Data Address Compare 2 */
+#endif	/* CONFIG_BOOKE */
+#define SPRN_DAR	0x013	/* Data Address Register */
+#define SPRN_DBAT0L	0x219	/* Data BAT 0 Lower Register */
+#define SPRN_DBAT0U	0x218	/* Data BAT 0 Upper Register */
+#define SPRN_DBAT1L	0x21B	/* Data BAT 1 Lower Register */
+#define SPRN_DBAT1U	0x21A	/* Data BAT 1 Upper Register */
+#define SPRN_DBAT2L	0x21D	/* Data BAT 2 Lower Register */
+#define SPRN_DBAT2U	0x21C	/* Data BAT 2 Upper Register */
+#define SPRN_DBAT3L	0x21F	/* Data BAT 3 Lower Register */
+#define SPRN_DBAT3U	0x21E	/* Data BAT 3 Upper Register */
+#define SPRN_DBAT4L	0x239	/* Data BAT 4 Lower Register */
+#define SPRN_DBAT4U	0x238	/* Data BAT 4 Upper Register */
+#define SPRN_DBAT5L	0x23B	/* Data BAT 5 Lower Register */
+#define SPRN_DBAT5U	0x23A	/* Data BAT 5 Upper Register */
+#define SPRN_DBAT6L	0x23D	/* Data BAT 6 Lower Register */
+#define SPRN_DBAT6U	0x23C	/* Data BAT 6 Upper Register */
+#define SPRN_DBAT7L	0x23F	/* Data BAT 7 Lower Register */
+#define SPRN_DBAT7U	0x23E	/* Data BAT 7 Lower Register */
+#define SPRN_DBCR	0x3F2	/* Debug Control Regsiter */
+#define   DBCR_EDM	0x80000000
+#define   DBCR_IDM	0x40000000
+#define   DBCR_RST(x)	(((x) & 0x3) << 28)
+#define     DBCR_RST_NONE		0
+#define     DBCR_RST_CORE		1
+#define     DBCR_RST_CHIP		2
+#define     DBCR_RST_SYSTEM		3
+#define   DBCR_IC	0x08000000	/* Instruction Completion Debug Evnt */
+#define   DBCR_BT	0x04000000	/* Branch Taken Debug Event */
+#define   DBCR_EDE	0x02000000	/* Exception Debug Event */
+#define   DBCR_TDE	0x01000000	/* TRAP Debug Event */
+#define   DBCR_FER	0x00F80000	/* First Events Remaining Mask */
+#define   DBCR_FT	0x00040000	/* Freeze Timers on Debug Event */
+#define   DBCR_IA1	0x00020000	/* Instr. Addr. Compare 1 Enable */
+#define   DBCR_IA2	0x00010000	/* Instr. Addr. Compare 2 Enable */
+#define   DBCR_D1R	0x00008000	/* Data Addr. Compare 1 Read Enable */
+#define   DBCR_D1W	0x00004000	/* Data Addr. Compare 1 Write Enable */
+#define   DBCR_D1S(x)	(((x) & 0x3) << 12)	/* Data Adrr. Compare 1 Size */
+#define     DAC_BYTE	0
+#define     DAC_HALF	1
+#define     DAC_WORD	2
+#define     DAC_QUAD	3
+#define   DBCR_D2R	0x00000800	/* Data Addr. Compare 2 Read Enable */
+#define   DBCR_D2W	0x00000400	/* Data Addr. Compare 2 Write Enable */
+#define   DBCR_D2S(x)	(((x) & 0x3) << 8)	/* Data Addr. Compare 2 Size */
+#define   DBCR_SBT	0x00000040	/* Second Branch Taken Debug Event */
+#define   DBCR_SED	0x00000020	/* Second Exception Debug Event */
+#define   DBCR_STD	0x00000010	/* Second Trap Debug Event */
+#define   DBCR_SIA	0x00000008	/* Second IAC Enable */
+#define   DBCR_SDA	0x00000004	/* Second DAC Enable */
+#define   DBCR_JOI	0x00000002	/* JTAG Serial Outbound Int. Enable */
+#define   DBCR_JII	0x00000001	/* JTAG Serial Inbound Int. Enable */
+#ifndef CONFIG_BOOKE
+#define SPRN_DBCR0	0x3F2		/* Debug Control Register 0 */
+#else
+#define SPRN_DBCR0	0x134		/* Book E Debug Control Register 0 */
+#endif /* CONFIG_BOOKE */
+#ifndef CONFIG_BOOKE
+#define SPRN_DBCR1	0x3BD	/* Debug Control Register 1 */
+#define SPRN_DBSR	0x3F0	/* Debug Status Register */
+#else
+#define SPRN_DBCR1	0x135		/* Book E Debug Control Register 1 */
+#ifdef CONFIG_BOOKE
+#define	SPRN_DBDR	0x3f3		/* Debug Data Register */
+#endif
+#define SPRN_DBSR	0x130		/* Book E Debug Status Register */
+#define   DBSR_IC	    0x08000000	/* Book E Instruction Completion  */
+#define   DBSR_TIE	    0x01000000	/* Book E Trap Instruction Event */
+#endif /* CONFIG_BOOKE */
+#define SPRN_DCCR	0x3FA	/* Data Cache Cacheability Register */
+#define   DCCR_NOCACHE		0	/* Noncacheable */
+#define   DCCR_CACHE		1	/* Cacheable */
+#ifndef CONFIG_BOOKE
+#define	SPRN_DCDBTRL	0x39c	/* Data Cache Debug Tag Register Low */
+#define	SPRN_DCDBTRH	0x39d	/* Data Cache Debug Tag Register High */
+#endif
+#define SPRN_DCMP	0x3D1	/* Data TLB Compare Register */
+#define SPRN_DCWR	0x3BA	/* Data Cache Write-thru Register */
+#define   DCWR_COPY		0	/* Copy-back */
+#define   DCWR_WRITE		1	/* Write-through */
+#ifndef CONFIG_BOOKE
+#define SPRN_DEAR	0x3D5	/* Data Error Address Register */
+#else
+#define SPRN_DEAR	0x03D	/* Book E Data Error Address Register */
+#endif /* CONFIG_BOOKE */
+#define SPRN_DEC	0x016	/* Decrement Register */
+#define SPRN_DMISS	0x3D0	/* Data TLB Miss Register */
+#ifdef CONFIG_BOOKE
+#define	SPRN_DNV0	0x390	/* Data Cache Normal Victim 0 */
+#define	SPRN_DNV1	0x391	/* Data Cache Normal Victim 1 */
+#define	SPRN_DNV2	0x392	/* Data Cache Normal Victim 2 */
+#define	SPRN_DNV3	0x393	/* Data Cache Normal Victim 3 */
+#endif
+#define SPRN_DSISR	0x012	/* Data Storage Interrupt Status Register */
+#ifdef CONFIG_BOOKE
+#define	SPRN_DTV0	0x394	/* Data Cache Transient Victim 0 */
+#define	SPRN_DTV1	0x395	/* Data Cache Transient Victim 1 */
+#define	SPRN_DTV2	0x396	/* Data Cache Transient Victim 2 */
+#define	SPRN_DTV3	0x397	/* Data Cache Transient Victim 3 */
+#define	SPRN_DVLIM	0x398	/* Data Cache Victim Limit */
+#endif
+#define SPRN_EAR	0x11A	/* External Address Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_ESR	0x3D4	/* Exception Syndrome Register */
+#else
+#define SPRN_ESR	0x03E		/* Book E Exception Syndrome Register */
+#endif /* CONFIG_BOOKE */
+#define   ESR_IMCP	0x80000000	/* Instr. Machine Check - Protection */
+#define   ESR_IMCN	0x40000000	/* Instr. Machine Check - Non-config */
+#define   ESR_IMCB	0x20000000	/* Instr. Machine Check - Bus error */
+#define   ESR_IMCT	0x10000000	/* Instr. Machine Check - Timeout */
+#define   ESR_PIL	0x08000000	/* Program Exception - Illegal */
+#define   ESR_PPR	0x04000000	/* Program Exception - Priveleged */
+#define   ESR_PTR	0x02000000	/* Program Exception - Trap */
+#define   ESR_DST	0x00800000	/* Storage Exception - Data miss */
+#define   ESR_DIZ	0x00400000	/* Storage Exception - Zone fault */
+#define SPRN_EVPR	0x3D6	/* Exception Vector Prefix Register */
+#define SPRN_HASH1	0x3D2	/* Primary Hash Address Register */
+#define SPRN_HASH2	0x3D3	/* Secondary Hash Address Resgister */
+#define SPRN_HID0	0x3F0	/* Hardware Implementation Register 0 */
+
+#define HID0_ICE_SHIFT		15
+#define HID0_DCE_SHIFT		14
+#define HID0_DLOCK_SHIFT	12
+
+#define   HID0_EMCP	(1<<31)		/* Enable Machine Check pin */
+#define   HID0_EBA	(1<<29)		/* Enable Bus Address Parity */
+#define   HID0_EBD	(1<<28)		/* Enable Bus Data Parity */
+#define   HID0_SBCLK	(1<<27)
+#define   HID0_EICE	(1<<26)
+#define   HID0_ECLK	(1<<25)
+#define   HID0_PAR	(1<<24)
+#define   HID0_DOZE	(1<<23)
+#define   HID0_NAP	(1<<22)
+#define   HID0_SLEEP	(1<<21)
+#define   HID0_DPM	(1<<20)
+#define   HID0_ICE	(1<<HID0_ICE_SHIFT)	/* Instruction Cache Enable */
+#define   HID0_DCE	(1<<HID0_DCE_SHIFT)	/* Data Cache Enable */
+#define   HID0_TBEN	(1<<14)		/* Time Base Enable */
+#define   HID0_ILOCK	(1<<13)		/* Instruction Cache Lock */
+#define   HID0_DLOCK	(1<<HID0_DLOCK_SHIFT)	/* Data Cache Lock */
+#define   HID0_ICFI	(1<<11)		/* Instr. Cache Flash Invalidate */
+#define   HID0_DCFI	(1<<10)		/* Data Cache Flash Invalidate */
+#define   HID0_DCI	HID0_DCFI
+#define   HID0_SPD	(1<<9)		/* Speculative disable */
+#define   HID0_ENMAS7	(1<<7)		/* Enable MAS7 Update for 36-bit phys */
+#define   HID0_SGE	(1<<7)		/* Store Gathering Enable */
+#define   HID0_SIED	HID_SGE		/* Serial Instr. Execution [Disable] */
+#define   HID0_DCFA	(1<<6)		/* Data Cache Flush Assist */
+#define   HID0_BTIC	(1<<5)		/* Branch Target Instruction Cache Enable */
+#define   HID0_ABE	(1<<3)		/* Address Broadcast Enable */
+#define   HID0_BHTE	(1<<2)		/* Branch History Table Enable */
+#define   HID0_BTCD	(1<<1)		/* Branch target cache disable */
+#define SPRN_HID1	0x3F1	/* Hardware Implementation Register 1 */
+#define	  HID1_RFXE	(1<<17)		/* Read Fault Exception Enable */
+#define	  HID1_ASTME	(1<<13)		/* Address bus streaming mode */
+#define	  HID1_ABE	(1<<12)		/* Address broadcast enable */
+#define	  HID1_MBDD	(1<<6)		/* optimized sync instruction */
+#define SPRN_IABR	0x3F2	/* Instruction Address Breakpoint Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_IAC1	0x3F4	/* Instruction Address Compare 1 */
+#define SPRN_IAC2	0x3F5	/* Instruction Address Compare 2 */
+#else
+#define SPRN_IAC1	0x138	/* Book E Instruction Address Compare 1 */
+#define SPRN_IAC2	0x139	/* Book E Instruction Address Compare 2 */
+#endif /* CONFIG_BOOKE */
+#define SPRN_IBAT0L	0x211	/* Instruction BAT 0 Lower Register */
+#define SPRN_IBAT0U	0x210	/* Instruction BAT 0 Upper Register */
+#define SPRN_IBAT1L	0x213	/* Instruction BAT 1 Lower Register */
+#define SPRN_IBAT1U	0x212	/* Instruction BAT 1 Upper Register */
+#define SPRN_IBAT2L	0x215	/* Instruction BAT 2 Lower Register */
+#define SPRN_IBAT2U	0x214	/* Instruction BAT 2 Upper Register */
+#define SPRN_IBAT3L	0x217	/* Instruction BAT 3 Lower Register */
+#define SPRN_IBAT3U	0x216	/* Instruction BAT 3 Upper Register */
+#define SPRN_IBAT4L	0x231	/* Instruction BAT 4 Lower Register */
+#define SPRN_IBAT4U	0x230	/* Instruction BAT 4 Upper Register */
+#define SPRN_IBAT5L	0x233	/* Instruction BAT 5 Lower Register */
+#define SPRN_IBAT5U	0x232	/* Instruction BAT 5 Upper Register */
+#define SPRN_IBAT6L	0x235	/* Instruction BAT 6 Lower Register */
+#define SPRN_IBAT6U	0x234	/* Instruction BAT 6 Upper Register */
+#define SPRN_IBAT7L	0x237	/* Instruction BAT 7 Lower Register */
+#define SPRN_IBAT7U	0x236	/* Instruction BAT 7 Upper Register */
+#define SPRN_ICCR	0x3FB	/* Instruction Cache Cacheability Register */
+#define   ICCR_NOCACHE		0	/* Noncacheable */
+#define   ICCR_CACHE		1	/* Cacheable */
+#define SPRN_ICDBDR	0x3D3	/* Instruction Cache Debug Data Register */
+#ifdef CONFIG_BOOKE
+#define SPRN_ICDBTRL	0x39e	/* instruction cache debug tag register low */
+#define	SPRN_ICDBTRH	0x39f	/* instruction cache debug tag register high */
+#endif
+#define SPRN_ICMP	0x3D5	/* Instruction TLB Compare Register */
+#define SPRN_ICTC	0x3FB	/* Instruction Cache Throttling Control Reg */
+#define SPRN_IMISS	0x3D4	/* Instruction TLB Miss Register */
+#define SPRN_IMMR	0x27E	/* Internal Memory Map Register */
+#ifdef CONFIG_BOOKE
+#define	SPRN_INV0	0x370	/* Instruction Cache Normal Victim 0 */
+#define	SPRN_INV1	0x371	/* Instruction Cache Normal Victim 1 */
+#define	SPRN_INV2	0x372	/* Instruction Cache Normal Victim 2 */
+#define	SPRN_INV3	0x373	/* Instruction Cache Normal Victim 3 */
+#define	SPRN_ITV0	0x374	/* Instruction Cache Transient Victim 0 */
+#define	SPRN_ITV1	0x375	/* Instruction Cache Transient Victim 1 */
+#define	SPRN_ITV2	0x376	/* Instruction Cache Transient Victim 2 */
+#define	SPRN_ITV3	0x377	/* Instruction Cache Transient Victim 3 */
+#define	SPRN_IVLIM	0x399	/* Instruction Cache Victim Limit */
+#endif
+#define SPRN_LDSTCR	0x3F8	/* Load/Store Control Register */
+#define SPRN_L2CR	0x3F9	/* Level 2 Cache Control Regsiter */
+#define SPRN_LR		0x008	/* Link Register */
+#define SPRN_MBAR	0x137	/* System memory base address */
+#define SPRN_MMCR0	0x3B8	/* Monitor Mode Control Register 0 */
+#define SPRN_MMCR1	0x3BC	/* Monitor Mode Control Register 1 */
+#ifdef CONFIG_BOOKE
+#define	SPRN_MMUCR	0x3b2	/* MMU Control Register */
+#endif
+#define SPRN_PBL1	0x3FC	/* Protection Bound Lower 1 */
+#define SPRN_PBL2	0x3FE	/* Protection Bound Lower 2 */
+#define SPRN_PBU1	0x3FD	/* Protection Bound Upper 1 */
+#define SPRN_PBU2	0x3FF	/* Protection Bound Upper 2 */
+#ifndef CONFIG_BOOKE
+#define SPRN_PID	0x3B1	/* Process ID */
+#define SPRN_PIR	0x3FF	/* Processor Identification Register */
+#else
+#define SPRN_PID	0x030	/* Book E Process ID */
+#define SPRN_PIR	0x11E	/* Book E Processor Identification Register */
+#endif /* CONFIG_BOOKE */
+#define SPRN_PIT	0x3DB	/* Programmable Interval Timer */
+#define SPRN_PMC1	0x3B9	/* Performance Counter Register 1 */
+#define SPRN_PMC2	0x3BA	/* Performance Counter Register 2 */
+#define SPRN_PMC3	0x3BD	/* Performance Counter Register 3 */
+#define SPRN_PMC4	0x3BE	/* Performance Counter Register 4 */
+#define SPRN_PVR	0x11F	/* Processor Version Register */
+#define SPRN_RPA	0x3D6	/* Required Physical Address Register */
+#ifdef CONFIG_BOOKE
+#define	SPRN_RSTCFG	0x39b	/* Reset Configuration */
+#endif
+#define SPRN_SDA	0x3BF	/* Sampled Data Address Register */
+#define SPRN_SDR1	0x019	/* MMU Hash Base Register */
+#define SPRN_SGR	0x3B9	/* Storage Guarded Register */
+#define   SGR_NORMAL		0
+#define   SGR_GUARDED		1
+#define SPRN_SIA	0x3BB	/* Sampled Instruction Address Register */
+#define SPRN_SPRG0	0x110	/* Special Purpose Register General 0 */
+#define SPRN_SPRG1	0x111	/* Special Purpose Register General 1 */
+#define SPRN_SPRG2	0x112	/* Special Purpose Register General 2 */
+#define SPRN_SPRG3	0x113	/* Special Purpose Register General 3 */
+#define SPRN_SPRG4	0x114	/* Special Purpose Register General 4 */
+#define SPRN_SPRG5	0x115	/* Special Purpose Register General 5 */
+#define SPRN_SPRG6	0x116	/* Special Purpose Register General 6 */
+#define SPRN_SPRG7	0x117	/* Special Purpose Register General 7 */
+#define SPRN_SRR0	0x01A	/* Save/Restore Register 0 */
+#define SPRN_SRR1	0x01B	/* Save/Restore Register 1 */
+#define SPRN_SRR2	0x3DE	/* Save/Restore Register 2 */
+#define SPRN_SRR3	0x3DF	/* Save/Restore Register 3 */
+
+#ifdef CONFIG_BOOKE
+#define SPRN_SVR	0x3FF	/* System Version Register */
+#else
+#define SPRN_SVR	0x11E	/* System Version Register */
+#endif
+#define SPRN_TBHI	0x3DC	/* Time Base High */
+#define SPRN_TBHU	0x3CC	/* Time Base High User-mode */
+#define SPRN_TBLO	0x3DD	/* Time Base Low */
+#define SPRN_TBLU	0x3CD	/* Time Base Low User-mode */
+#define SPRN_TBRL	0x10C	/* Time Base Read Lower Register */
+#define SPRN_TBRU	0x10D	/* Time Base Read Upper Register */
+#define SPRN_TBWL	0x11C	/* Time Base Write Lower Register */
+#define SPRN_TBWU	0x11D	/* Time Base Write Upper Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_TCR	0x3DA	/* Timer Control Register */
+#else
+#define SPRN_TCR	0x154	/* Book E Timer Control Register */
+#endif /* CONFIG_BOOKE */
+#define   TCR_WP(x)		(((x)&0x3)<<30)	/* WDT Period */
+#define     WP_2_17		0		/* 2^17 clocks */
+#define     WP_2_21		1		/* 2^21 clocks */
+#define     WP_2_25		2		/* 2^25 clocks */
+#define     WP_2_29		3		/* 2^29 clocks */
+#define   TCR_WRC(x)		(((x)&0x3)<<28)	/* WDT Reset Control */
+#define     WRC_NONE		0		/* No reset will occur */
+#define     WRC_CORE		1		/* Core reset will occur */
+#define     WRC_CHIP		2		/* Chip reset will occur */
+#define     WRC_SYSTEM		3		/* System reset will occur */
+#define   TCR_WIE		0x08000000	/* WDT Interrupt Enable */
+#define   TCR_PIE		0x04000000	/* PIT Interrupt Enable */
+#define   TCR_FP(x)		(((x)&0x3)<<24)	/* FIT Period */
+#define     FP_2_9		0		/* 2^9 clocks */
+#define     FP_2_13		1		/* 2^13 clocks */
+#define     FP_2_17		2		/* 2^17 clocks */
+#define     FP_2_21		3		/* 2^21 clocks */
+#define   TCR_FIE		0x00800000	/* FIT Interrupt Enable */
+#define   TCR_ARE		0x00400000	/* Auto Reload Enable */
+#define SPRN_THRM1	0x3FC	/* Thermal Management Register 1 */
+#define   THRM1_TIN		(1<<0)
+#define   THRM1_TIV		(1<<1)
+#define   THRM1_THRES		(0x7f<<2)
+#define   THRM1_TID		(1<<29)
+#define   THRM1_TIE		(1<<30)
+#define   THRM1_V		(1<<31)
+#define SPRN_THRM2	0x3FD	/* Thermal Management Register 2 */
+#define SPRN_THRM3	0x3FE	/* Thermal Management Register 3 */
+#define   THRM3_E		(1<<31)
+#define SPRN_TLBMISS	0x3D4	/* 980 7450 TLB Miss Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_TSR	0x3D8	/* Timer Status Register */
+#else
+#define SPRN_TSR	0x150	/* Book E Timer Status Register */
+#endif /* CONFIG_BOOKE */
+#define   TSR_ENW		0x80000000	/* Enable Next Watchdog */
+#define   TSR_WIS		0x40000000	/* WDT Interrupt Status */
+#define   TSR_WRS(x)		(((x)&0x3)<<28)	/* WDT Reset Status */
+#define     WRS_NONE		0		/* No WDT reset occurred */
+#define     WRS_CORE		1		/* WDT forced core reset */
+#define     WRS_CHIP		2		/* WDT forced chip reset */
+#define     WRS_SYSTEM		3		/* WDT forced system reset */
+#define   TSR_PIS		0x08000000	/* PIT Interrupt Status */
+#define   TSR_FIS		0x04000000	/* FIT Interrupt Status */
+#define SPRN_UMMCR0	0x3A8	/* User Monitor Mode Control Register 0 */
+#define SPRN_UMMCR1	0x3AC	/* User Monitor Mode Control Register 0 */
+#define SPRN_UPMC1	0x3A9	/* User Performance Counter Register 1 */
+#define SPRN_UPMC2	0x3AA	/* User Performance Counter Register 2 */
+#define SPRN_UPMC3	0x3AD	/* User Performance Counter Register 3 */
+#define SPRN_UPMC4	0x3AE	/* User Performance Counter Register 4 */
+#define SPRN_USIA	0x3AB	/* User Sampled Instruction Address Register */
+#define SPRN_XER	0x001	/* Fixed Point Exception Register */
+#define SPRN_ZPR	0x3B0	/* Zone Protection Register */
+
+/* Book E definitions */
+#define SPRN_DECAR	0x036	/* Decrementer Auto Reload Register */
+#define SPRN_CSRR0	0x03A	/* Critical SRR0 */
+#define SPRN_CSRR1	0x03B	/* Critical SRR0 */
+#define SPRN_IVPR	0x03F	/* Interrupt Vector Prefix Register */
+#define SPRN_USPRG0	0x100	/* User Special Purpose Register General 0 */
+#define SPRN_SPRG4R	0x104	/* Special Purpose Register General 4 Read */
+#define SPRN_SPRG5R	0x105	/* Special Purpose Register General 5 Read */
+#define SPRN_SPRG6R	0x106	/* Special Purpose Register General 6 Read */
+#define SPRN_SPRG7R	0x107	/* Special Purpose Register General 7 Read */
+#define SPRN_SPRG4W	0x114	/* Special Purpose Register General 4 Write */
+#define SPRN_SPRG5W	0x115	/* Special Purpose Register General 5 Write */
+#define SPRN_SPRG6W	0x116	/* Special Purpose Register General 6 Write */
+#define SPRN_SPRG7W	0x117	/* Special Purpose Register General 7 Write */
+#define SPRN_DBCR2	0x136	/* Debug Control Register 2 */
+#define SPRN_IAC3	0x13A	/* Instruction Address Compare 3 */
+#define SPRN_IAC4	0x13B	/* Instruction Address Compare 4 */
+#define SPRN_DVC1	0x13E	/* Data Value Compare Register 1 */
+#define SPRN_DVC2	0x13F	/* Data Value Compare Register 2 */
+#define SPRN_IVOR0	0x190	/* Interrupt Vector Offset Register 0 */
+#define SPRN_IVOR1	0x191	/* Interrupt Vector Offset Register 1 */
+#define SPRN_IVOR2	0x192	/* Interrupt Vector Offset Register 2 */
+#define SPRN_IVOR3	0x193	/* Interrupt Vector Offset Register 3 */
+#define SPRN_IVOR4	0x194	/* Interrupt Vector Offset Register 4 */
+#define SPRN_IVOR5	0x195	/* Interrupt Vector Offset Register 5 */
+#define SPRN_IVOR6	0x196	/* Interrupt Vector Offset Register 6 */
+#define SPRN_IVOR7	0x197	/* Interrupt Vector Offset Register 7 */
+#define SPRN_IVOR8	0x198	/* Interrupt Vector Offset Register 8 */
+#define SPRN_IVOR9	0x199	/* Interrupt Vector Offset Register 9 */
+#define SPRN_IVOR10	0x19a	/* Interrupt Vector Offset Register 10 */
+#define SPRN_IVOR11	0x19b	/* Interrupt Vector Offset Register 11 */
+#define SPRN_IVOR12	0x19c	/* Interrupt Vector Offset Register 12 */
+#define SPRN_IVOR13	0x19d	/* Interrupt Vector Offset Register 13 */
+#define SPRN_IVOR14	0x19e	/* Interrupt Vector Offset Register 14 */
+#define SPRN_IVOR15	0x19f	/* Interrupt Vector Offset Register 15 */
+#define SPRN_IVOR38	0x1b0	/* Interrupt Vector Offset Register 38 */
+#define SPRN_IVOR39	0x1b1	/* Interrupt Vector Offset Register 39 */
+#define SPRN_IVOR40	0x1b2	/* Interrupt Vector Offset Register 40 */
+#define SPRN_IVOR41	0x1b3	/* Interrupt Vector Offset Register 41 */
+#define SPRN_GIVOR2	0x1b8	/* Guest Interrupt Vector Offset Register 2 */
+#define SPRN_GIVOR3	0x1b9	/* Guest Interrupt Vector Offset Register 3 */
+#define SPRN_GIVOR4	0x1ba	/* Guest Interrupt Vector Offset Register 4 */
+#define SPRN_GIVOR8	0x1bb	/* Guest Interrupt Vector Offset Register 8 */
+#define SPRN_GIVOR13	0x1bc	/* Guest Interrupt Vector Offset Register 13 */
+#define SPRN_GIVOR14	0x1bd	/* Guest Interrupt Vector Offset Register 14 */
+
+/* e500 definitions */
+#define SPRN_L1CFG0	0x203	/* L1 Cache Configuration Register 0 */
+#define SPRN_L1CFG1	0x204	/* L1 Cache Configuration Register 1 */
+#define SPRN_L2CFG0	0x207	/* L2 Cache Configuration Register 0 */
+#define SPRN_L1CSR0	0x3f2	/* L1 Data Cache Control and Status Register 0 */
+#define   L1CSR0_CPE		0x00010000	/* Data Cache Parity Enable */
+#define   L1CSR0_DCLFR		0x00000100	/* D-Cache Lock Flash Reset */
+#define   L1CSR0_DCFI		0x00000002	/* Data Cache Flash Invalidate */
+#define   L1CSR0_DCE		0x00000001	/* Data Cache Enable */
+#define SPRN_L1CSR1	0x3f3	/* L1 Instruction Cache Control and Status Register 1 */
+#define   L1CSR1_CPE		0x00010000	/* Instruction Cache Parity Enable */
+#define   L1CSR1_ICLFR		0x00000100	/* I-Cache Lock Flash Reset */
+#define   L1CSR1_ICFI		0x00000002	/* Instruction Cache Flash Invalidate */
+#define   L1CSR1_ICE		0x00000001	/* Instruction Cache Enable */
+#define SPRN_L1CSR2	0x25e	/* L1 Data Cache Control and Status Register 2 */
+#define SPRN_L2CSR0	0x3f9	/* L2 Data Cache Control and Status Register 0 */
+#define   L2CSR0_L2E		0x80000000	/* L2 Cache Enable */
+#define   L2CSR0_L2PE		0x40000000	/* L2 Cache Parity/ECC Enable */
+#define   L2CSR0_L2WP		0x1c000000	/* L2 I/D Way Partioning */
+#define   L2CSR0_L2CM		0x03000000	/* L2 Cache Coherency Mode */
+#define   L2CSR0_L2FI		0x00200000	/* L2 Cache Flash Invalidate */
+#define   L2CSR0_L2IO		0x00100000	/* L2 Cache Instruction Only */
+#define   L2CSR0_L2DO		0x00010000	/* L2 Cache Data Only */
+#define   L2CSR0_L2REP		0x00003000	/* L2 Line Replacement Algo */
+#define   L2CSR0_L2FL		0x00000800	/* L2 Cache Flush */
+#define   L2CSR0_L2LFC		0x00000400	/* L2 Cache Lock Flash Clear */
+#define   L2CSR0_L2LOA		0x00000080	/* L2 Cache Lock Overflow Allocate */
+#define   L2CSR0_L2LO		0x00000020	/* L2 Cache Lock Overflow */
+#define SPRN_L2CSR1	0x3fa	/* L2 Data Cache Control and Status Register 1 */
+
+#define SPRN_TLB0CFG	0x2B0	/* TLB 0 Config Register */
+#define SPRN_TLB1CFG	0x2B1	/* TLB 1 Config Register */
+#define SPRN_MMUCSR0	0x3f4	/* MMU control and status register 0 */
+#define SPRN_MAS0	0x270	/* MMU Assist Register 0 */
+#define SPRN_MAS1	0x271	/* MMU Assist Register 1 */
+#define SPRN_MAS2	0x272	/* MMU Assist Register 2 */
+#define SPRN_MAS3	0x273	/* MMU Assist Register 3 */
+#define SPRN_MAS4	0x274	/* MMU Assist Register 4 */
+#define SPRN_MAS5	0x275	/* MMU Assist Register 5 */
+#define SPRN_MAS6	0x276	/* MMU Assist Register 6 */
+#define SPRN_MAS7	0x3B0	/* MMU Assist Register 7 */
+#define SPRN_MAS8	0x155	/* MMU Assist Register 8 */
+
+#define SPRN_IVOR32	0x210	/* Interrupt Vector Offset Register 32 */
+#define SPRN_IVOR33	0x211	/* Interrupt Vector Offset Register 33 */
+#define SPRN_IVOR34	0x212	/* Interrupt Vector Offset Register 34 */
+#define SPRN_IVOR35	0x213	/* Interrupt Vector Offset Register 35 */
+#define SPRN_IVOR36	0x214	/* Interrupt Vector Offset Register 36 */
+#define SPRN_IVOR37	0x215	/* Interrupt Vector Offset Register 37 */
+#define SPRN_SPEFSCR	0x200	/* SPE & Embedded FP Status & Control */
+
+#define SPRN_MCSRR0	0x23a	/* Machine Check Save and Restore Register 0 */
+#define SPRN_MCSRR1	0x23b	/* Machine Check Save and Restore Register 1 */
+#define SPRN_BUCSR	0x3f5	/* Branch Control and Status Register */
+#define	  BUCSR_BBFI	0x00000200	/* Branch buffer flash invalidate */
+#define	  BUCSR_BPEN	0x00000001	/* Branch prediction enable */
+#define   BUCSR_ENABLE (BUCSR_BBFI|BUCSR_BPEN)
+#define SPRN_BBEAR	0x201	/* Branch Buffer Entry Address Register */
+#define SPRN_BBTAR	0x202	/* Branch Buffer Target Address Register */
+#define SPRN_PID1	0x279	/* Process ID Register 1 */
+#define SPRN_PID2	0x27a	/* Process ID Register 2 */
+#define SPRN_MCSR	0x23c	/* Machine Check Syndrome register */
+#define SPRN_MCAR	0x23d	/* Machine Check Address register */
+#define MCSR_MCS	0x80000000	/* Machine Check Summary */
+#define MCSR_IB		0x40000000	/* Instruction PLB Error */
+#if defined(CONFIG_440)
+#define MCSR_DRB	0x20000000	/* Data Read PLB Error */
+#define MCSR_DWB	0x10000000	/* Data Write PLB Error */
+#else
+#define MCSR_DB		0x20000000	/* Data PLB Error */
+#endif /* defined(CONFIG_440) */
+#define MCSR_TLBP	0x08000000	/* TLB Parity Error */
+#define MCSR_ICP	0x04000000	/* I-Cache Parity Error */
+#define MCSR_DCSP	0x02000000	/* D-Cache Search Parity Error */
+#define MCSR_DCFP	0x01000000	/* D-Cache Flush Parity Error */
+#define MCSR_IMPE	0x00800000	/* Imprecise Machine Check Exception */
+#define ESR_ST		0x00800000	/* Store Operation */
+
+#if defined(CONFIG_MPC86xx)
+#define SPRN_MSSCR0	0x3f6
+#define SPRN_MSSSR0	0x3f7
+#endif
+
+/* Short-hand versions for a number of the above SPRNs */
+
+#define CTR	SPRN_CTR	/* Counter Register */
+#define DAR	SPRN_DAR	/* Data Address Register */
+#define DABR	SPRN_DABR	/* Data Address Breakpoint Register */
+#define DAC1	SPRN_DAC1	/* Data Address Register 1 */
+#define DAC2	SPRN_DAC2	/* Data Address Register 2 */
+#define DBAT0L	SPRN_DBAT0L	/* Data BAT 0 Lower Register */
+#define DBAT0U	SPRN_DBAT0U	/* Data BAT 0 Upper Register */
+#define DBAT1L	SPRN_DBAT1L	/* Data BAT 1 Lower Register */
+#define DBAT1U	SPRN_DBAT1U	/* Data BAT 1 Upper Register */
+#define DBAT2L	SPRN_DBAT2L	/* Data BAT 2 Lower Register */
+#define DBAT2U	SPRN_DBAT2U	/* Data BAT 2 Upper Register */
+#define DBAT3L	SPRN_DBAT3L	/* Data BAT 3 Lower Register */
+#define DBAT3U	SPRN_DBAT3U	/* Data BAT 3 Upper Register */
+#define DBAT4L	SPRN_DBAT4L	/* Data BAT 4 Lower Register */
+#define DBAT4U	SPRN_DBAT4U	/* Data BAT 4 Upper Register */
+#define DBAT5L	SPRN_DBAT5L	/* Data BAT 5 Lower Register */
+#define DBAT5U	SPRN_DBAT5U	/* Data BAT 5 Upper Register */
+#define DBAT6L	SPRN_DBAT6L	/* Data BAT 6 Lower Register */
+#define DBAT6U	SPRN_DBAT6U	/* Data BAT 6 Upper Register */
+#define DBAT7L	SPRN_DBAT7L	/* Data BAT 7 Lower Register */
+#define DBAT7U	SPRN_DBAT7U	/* Data BAT 7 Upper Register */
+#define DBCR0	SPRN_DBCR0	/* Debug Control Register 0 */
+#define DBCR1	SPRN_DBCR1	/* Debug Control Register 1 */
+#define DBSR	SPRN_DBSR	/* Debug Status Register */
+#define DCMP	SPRN_DCMP	/* Data TLB Compare Register */
+#define DEC	SPRN_DEC	/* Decrement Register */
+#define DMISS	SPRN_DMISS	/* Data TLB Miss Register */
+#define DSISR	SPRN_DSISR	/* Data Storage Interrupt Status Register */
+#define EAR	SPRN_EAR	/* External Address Register */
+#define ESR	SPRN_ESR	/* Exception Syndrome Register */
+#define HASH1	SPRN_HASH1	/* Primary Hash Address Register */
+#define HASH2	SPRN_HASH2	/* Secondary Hash Address Register */
+#define HID0	SPRN_HID0	/* Hardware Implementation Register 0 */
+#define HID1	SPRN_HID1	/* Hardware Implementation Register 1 */
+#define IABR	SPRN_IABR	/* Instruction Address Breakpoint Register */
+#define IAC1	SPRN_IAC1	/* Instruction Address Register 1 */
+#define IAC2	SPRN_IAC2	/* Instruction Address Register 2 */
+#define IBAT0L	SPRN_IBAT0L	/* Instruction BAT 0 Lower Register */
+#define IBAT0U	SPRN_IBAT0U	/* Instruction BAT 0 Upper Register */
+#define IBAT1L	SPRN_IBAT1L	/* Instruction BAT 1 Lower Register */
+#define IBAT1U	SPRN_IBAT1U	/* Instruction BAT 1 Upper Register */
+#define IBAT2L	SPRN_IBAT2L	/* Instruction BAT 2 Lower Register */
+#define IBAT2U	SPRN_IBAT2U	/* Instruction BAT 2 Upper Register */
+#define IBAT3L	SPRN_IBAT3L	/* Instruction BAT 3 Lower Register */
+#define IBAT3U	SPRN_IBAT3U	/* Instruction BAT 3 Upper Register */
+#define IBAT4L	SPRN_IBAT4L	/* Instruction BAT 4 Lower Register */
+#define IBAT4U	SPRN_IBAT4U	/* Instruction BAT 4 Upper Register */
+#define IBAT5L	SPRN_IBAT5L	/* Instruction BAT 5 Lower Register */
+#define IBAT5U	SPRN_IBAT5U	/* Instruction BAT 5 Upper Register */
+#define IBAT6L	SPRN_IBAT6L	/* Instruction BAT 6 Lower Register */
+#define IBAT6U	SPRN_IBAT6U	/* Instruction BAT 6 Upper Register */
+#define IBAT7L	SPRN_IBAT7L	/* Instruction BAT 7 Lower Register */
+#define IBAT7U	SPRN_IBAT7U	/* Instruction BAT 7 Lower Register */
+#define ICMP	SPRN_ICMP	/* Instruction TLB Compare Register */
+#define IMISS	SPRN_IMISS	/* Instruction TLB Miss Register */
+#define IMMR	SPRN_IMMR	/* PPC 860/821 Internal Memory Map Register */
+#define LDSTCR	SPRN_LDSTCR	/* Load/Store Control Register */
+#define L2CR	SPRN_L2CR	/* PPC 750 L2 control register */
+#define LR	SPRN_LR
+#define MBAR	SPRN_MBAR	/* System memory base address */
+#if defined(CONFIG_MPC86xx)
+#define MSSCR0	SPRN_MSSCR0
+#endif
+#if defined(CONFIG_E500) || defined(CONFIG_MPC86xx)
+#define PIR	SPRN_PIR
+#endif
+#define SVR	SPRN_SVR	/* System-On-Chip Version Register */
+#define PVR	SPRN_PVR	/* Processor Version */
+#define RPA	SPRN_RPA	/* Required Physical Address Register */
+#define SDR1	SPRN_SDR1	/* MMU hash base register */
+#define SPR0	SPRN_SPRG0	/* Supervisor Private Registers */
+#define SPR1	SPRN_SPRG1
+#define SPR2	SPRN_SPRG2
+#define SPR3	SPRN_SPRG3
+#define SPRG0	SPRN_SPRG0
+#define SPRG1	SPRN_SPRG1
+#define SPRG2	SPRN_SPRG2
+#define SPRG3	SPRN_SPRG3
+#define SPRG4	SPRN_SPRG4
+#define SPRG5	SPRN_SPRG5
+#define SPRG6	SPRN_SPRG6
+#define SPRG7	SPRN_SPRG7
+#define SRR0	SPRN_SRR0	/* Save and Restore Register 0 */
+#define SRR1	SPRN_SRR1	/* Save and Restore Register 1 */
+#define SRR2	SPRN_SRR2	/* Save and Restore Register 2 */
+#define SRR3	SPRN_SRR3	/* Save and Restore Register 3 */
+#define SVR	SPRN_SVR	/* System Version Register */
+#define TBRL	SPRN_TBRL	/* Time Base Read Lower Register */
+#define TBRU	SPRN_TBRU	/* Time Base Read Upper Register */
+#define TBWL	SPRN_TBWL	/* Time Base Write Lower Register */
+#define TBWU	SPRN_TBWU	/* Time Base Write Upper Register */
+#define TCR	SPRN_TCR	/* Timer Control Register */
+#define TSR	SPRN_TSR	/* Timer Status Register */
+#define ICTC	1019
+#define THRM1	SPRN_THRM1	/* Thermal Management Register 1 */
+#define THRM2	SPRN_THRM2	/* Thermal Management Register 2 */
+#define THRM3	SPRN_THRM3	/* Thermal Management Register 3 */
+#define XER	SPRN_XER
+
+#define DECAR	SPRN_DECAR
+#define CSRR0	SPRN_CSRR0
+#define CSRR1	SPRN_CSRR1
+#define IVPR	SPRN_IVPR
+#define USPRG0	SPRN_USPRG
+#define SPRG4R	SPRN_SPRG4R
+#define SPRG5R	SPRN_SPRG5R
+#define SPRG6R	SPRN_SPRG6R
+#define SPRG7R	SPRN_SPRG7R
+#define SPRG4W	SPRN_SPRG4W
+#define SPRG5W	SPRN_SPRG5W
+#define SPRG6W	SPRN_SPRG6W
+#define SPRG7W	SPRN_SPRG7W
+#define DEAR	SPRN_DEAR
+#define DBCR2	SPRN_DBCR2
+#define IAC3	SPRN_IAC3
+#define IAC4	SPRN_IAC4
+#define DVC1	SPRN_DVC1
+#define DVC2	SPRN_DVC2
+#define IVOR0	SPRN_IVOR0
+#define IVOR1	SPRN_IVOR1
+#define IVOR2	SPRN_IVOR2
+#define IVOR3	SPRN_IVOR3
+#define IVOR4	SPRN_IVOR4
+#define IVOR5	SPRN_IVOR5
+#define IVOR6	SPRN_IVOR6
+#define IVOR7	SPRN_IVOR7
+#define IVOR8	SPRN_IVOR8
+#define IVOR9	SPRN_IVOR9
+#define IVOR10	SPRN_IVOR10
+#define IVOR11	SPRN_IVOR11
+#define IVOR12	SPRN_IVOR12
+#define IVOR13	SPRN_IVOR13
+#define IVOR14	SPRN_IVOR14
+#define IVOR15	SPRN_IVOR15
+#define IVOR32	SPRN_IVOR32
+#define IVOR33	SPRN_IVOR33
+#define IVOR34	SPRN_IVOR34
+#define IVOR35	SPRN_IVOR35
+#define MCSRR0	SPRN_MCSRR0
+#define MCSRR1	SPRN_MCSRR1
+#define L1CSR0	SPRN_L1CSR0
+#define L1CSR1	SPRN_L1CSR1
+#define L1CSR2	SPRN_L1CSR2
+#define L1CFG0	SPRN_L1CFG0
+#define L1CFG1	SPRN_L1CFG1
+#define L2CFG0	SPRN_L2CFG0
+#define L2CSR0	SPRN_L2CSR0
+#define L2CSR1	SPRN_L2CSR1
+#define MCSR	SPRN_MCSR
+#define MMUCSR0	SPRN_MMUCSR0
+#define BUCSR	SPRN_BUCSR
+#define PID0	SPRN_PID
+#define PID1	SPRN_PID1
+#define PID2	SPRN_PID2
+#define MAS0	SPRN_MAS0
+#define MAS1	SPRN_MAS1
+#define MAS2	SPRN_MAS2
+#define MAS3	SPRN_MAS3
+#define MAS4	SPRN_MAS4
+#define MAS5	SPRN_MAS5
+#define MAS6	SPRN_MAS6
+#define MAS7	SPRN_MAS7
+#define MAS8 	SPRN_MAS8
+
+#if defined(CONFIG_4xx) || defined(CONFIG_44x) || defined(CONFIG_MPC85xx)
+#define DAR_DEAR DEAR
+#else
+#define DAR_DEAR DAR
+#endif
+
+/* Device Control Registers */
+
+#define DCRN_BEAR	0x090	/* Bus Error Address Register */
+#define DCRN_BESR	0x091	/* Bus Error Syndrome Register */
+#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 DCRN_DMACC0	0x0C4	/* DMA Chained Count Register 0 */
+#define DCRN_DMACC1	0x0CC	/* DMA Chained Count Register 1 */
+#define DCRN_DMACC2	0x0D4	/* DMA Chained Count Register 2 */
+#define DCRN_DMACC3	0x0DC	 /* DMA Chained Count Register 3 */
+#define DCRN_DMACR0	0x0C0	 /* DMA Channel Control Register 0 */
+#define DCRN_DMACR1	0x0C8	 /* DMA Channel Control Register 1 */
+#define DCRN_DMACR2	0x0D0	 /* DMA Channel Control Register 2 */
+#define DCRN_DMACR3	0x0D8	 /* DMA Channel Control Register 3 */
+#define DCRN_DMACT0	0x0C1	 /* DMA Count Register 0 */
+#define DCRN_DMACT1	0x0C9	 /* DMA Count Register 1 */
+#define DCRN_DMACT2	0x0D1	 /* DMA Count Register 2 */
+#define DCRN_DMACT3	0x0D9	 /* DMA Count Register 3 */
+#define DCRN_DMADA0	0x0C2	 /* DMA Destination Address Register 0 */
+#define DCRN_DMADA1	0x0CA	 /* DMA Destination Address Register 1 */
+#define DCRN_DMADA2	0x0D2	 /* DMA Destination Address Register 2 */
+#define DCRN_DMADA3	0x0DA	 /* DMA Destination Address Register 3 */
+#define DCRN_DMASA0	0x0C3	 /* DMA Source Address Register 0 */
+#define DCRN_DMASA1	0x0CB	 /* DMA Source Address Register 1 */
+#define DCRN_DMASA2	0x0D3	 /* DMA Source Address Register 2 */
+#define DCRN_DMASA3	0x0DB	 /* DMA Source Address Register 3 */
+#define DCRN_DMASR	0x0E0	 /* DMA Status Register */
+#define DCRN_EXIER	0x042	 /* External Interrupt Enable Register */
+#define   EXIER_CIE	0x80000000	/* Critical Interrupt Enable */
+#define   EXIER_SRIE	0x08000000	/* Serial Port Rx Int. Enable */
+#define   EXIER_STIE	0x04000000	/* Serial Port Tx Int. Enable */
+#define   EXIER_JRIE	0x02000000	/* JTAG Serial Port Rx Int. Enable */
+#define   EXIER_JTIE	0x01000000	/* JTAG Serial Port Tx Int. Enable */
+#define   EXIER_D0IE	0x00800000	/* DMA Channel 0 Interrupt Enable */
+#define   EXIER_D1IE	0x00400000	/* DMA Channel 1 Interrupt Enable */
+#define   EXIER_D2IE	0x00200000	/* DMA Channel 2 Interrupt Enable */
+#define   EXIER_D3IE	0x00100000	/* DMA Channel 3 Interrupt Enable */
+#define   EXIER_E0IE	0x00000010	/* External Interrupt 0 Enable */
+#define   EXIER_E1IE	0x00000008	/* External Interrupt 1 Enable */
+#define   EXIER_E2IE	0x00000004	/* External Interrupt 2 Enable */
+#define   EXIER_E3IE	0x00000002	/* External Interrupt 3 Enable */
+#define   EXIER_E4IE	0x00000001	/* External Interrupt 4 Enable */
+#define DCRN_EXISR	0x040	 /* External Interrupt Status Register */
+#define DCRN_IOCR	0x0A0	 /* Input/Output Configuration Register */
+#define   IOCR_E0TE	0x80000000
+#define   IOCR_E0LP	0x40000000
+#define   IOCR_E1TE	0x20000000
+#define   IOCR_E1LP	0x10000000
+#define   IOCR_E2TE	0x08000000
+#define   IOCR_E2LP	0x04000000
+#define   IOCR_E3TE	0x02000000
+#define   IOCR_E3LP	0x01000000
+#define   IOCR_E4TE	0x00800000
+#define   IOCR_E4LP	0x00400000
+#define   IOCR_EDT	0x00080000
+#define   IOCR_SOR	0x00040000
+#define   IOCR_EDO	0x00008000
+#define   IOCR_2XC	0x00004000
+#define   IOCR_ATC	0x00002000
+#define   IOCR_SPD	0x00001000
+#define   IOCR_BEM	0x00000800
+#define   IOCR_PTD	0x00000400
+#define   IOCR_ARE	0x00000080
+#define   IOCR_DRC	0x00000020
+#define   IOCR_RDM(x)	(((x) & 0x3) << 3)
+#define   IOCR_TCS	0x00000004
+#define   IOCR_SCS	0x00000002
+#define   IOCR_SPC	0x00000001
+
+/* System-On-Chip Version Register */
+
+/* System-On-Chip Version Register (SVR) field extraction */
+
+#define SVR_VER(svr)	(((svr) >> 16) & 0xFFFF) /* Version field */
+#define SVR_REV(svr)	(((svr) >>  0) & 0xFFFF) /* Revision field */
+
+#define SVR_CID(svr)	(((svr) >> 28) & 0x0F)	 /* Company or manufacturer ID */
+#define SVR_SOCOP(svr)	(((svr) >> 22) & 0x3F)	 /* SOC integration options */
+#define SVR_SID(svr)	(((svr) >> 16) & 0x3F)	 /* SOC ID */
+#define SVR_PROC(svr)	(((svr) >> 12) & 0x0F)	 /* Process revision field */
+#define SVR_MFG(svr)	(((svr) >>  8) & 0x0F)	 /* Manufacturing revision */
+#define SVR_MJREV(svr)	(((svr) >>  4) & 0x0F)	 /* Major SOC design revision indicator */
+#define SVR_MNREV(svr)	(((svr) >>  0) & 0x0F)	 /* Minor SOC design revision indicator */
+
+/* Processor Version Register */
+
+/* Processor Version Register (PVR) field extraction */
+
+#define PVR_VER(pvr)  (((pvr) >>  16) & 0xFFFF)	/* Version field */
+#define PVR_REV(pvr)  (((pvr) >>   0) & 0xFFFF)	/* Revison field */
+
+/*
+ * AMCC has further subdivided the standard PowerPC 16-bit version and
+ * revision subfields of the PVR for the PowerPC 403s into the following:
+ */
+
+#define PVR_FAM(pvr)	(((pvr) >> 20) & 0xFFF)	/* Family field */
+#define PVR_MEM(pvr)	(((pvr) >> 16) & 0xF)	/* Member field */
+#define PVR_CORE(pvr)	(((pvr) >> 12) & 0xF)	/* Core field */
+#define PVR_CFG(pvr)	(((pvr) >>  8) & 0xF)	/* Configuration field */
+#define PVR_MAJ(pvr)	(((pvr) >>  4) & 0xF)	/* Major revision field */
+#define PVR_MIN(pvr)	(((pvr) >>  0) & 0xF)	/* Minor revision field */
+
+/* e600 core PVR fields */
+
+#define PVR_E600_VER(pvr)	(((pvr) >> 15) & 0xFFFF) /* Version/type */
+#define PVR_E600_TECH(pvr)	(((pvr) >> 12) & 0xF)	 /* Technology */
+#define PVR_E600_MAJ(pvr)	(((pvr) >> 8) & 0xF)	 /* Major revision */
+#define PVR_E600_MIN(pvr)	(((pvr) >> 0) & 0xFF)	 /* Minor revision */
+
+/* Processor Version Numbers */
+
+#define PVR_403GA	0x00200000
+#define PVR_403GB	0x00200100
+#define PVR_403GC	0x00200200
+#define PVR_403GCX	0x00201400
+#define PVR_405GP	0x40110000
+#define PVR_405GP_RB	0x40110040
+#define PVR_405GP_RC	0x40110082
+#define PVR_405GP_RD	0x401100C4
+#define PVR_405GP_RE	0x40110145  /* same as pc405cr rev c */
+#define PVR_405CR_RA	0x40110041
+#define PVR_405CR_RB	0x401100C5
+#define PVR_405CR_RC	0x40110145  /* same as pc405gp rev e */
+#define PVR_405EP_RA	0x51210950
+#define PVR_405GPR_RB	0x50910951
+#define PVR_405EZ_RA	0x41511460
+#define PVR_405EXR2_RA	0x12911471 /* 405EXr rev A/B without Security */
+#define PVR_405EX1_RA	0x12911477 /* 405EX rev A/B with Security */
+#define PVR_405EXR1_RC	0x1291147B /* 405EXr rev C with Security */
+#define PVR_405EXR2_RC	0x12911479 /* 405EXr rev C without Security */
+#define PVR_405EX1_RC	0x1291147F /* 405EX rev C with Security */
+#define PVR_405EX2_RC	0x1291147D /* 405EX rev C without Security */
+#define PVR_405EXR1_RD	0x12911472 /* 405EXr rev D with Security */
+#define PVR_405EXR2_RD	0x12911470 /* 405EXr rev D without Security */
+#define PVR_405EX1_RD	0x12911475 /* 405EX rev D with Security */
+#define PVR_405EX2_RD	0x12911473 /* 405EX rev D without Security */
+#define PVR_440GP_RB	0x40120440
+#define PVR_440GP_RC	0x40120481
+#define PVR_440EP_RA	0x42221850
+#define PVR_440EP_RB	0x422218D3 /* 440EP rev B and 440GR rev A have same PVR */
+#define PVR_440EP_RC	0x422218D4 /* 440EP rev C and 440GR rev B have same PVR */
+#define PVR_440GR_RA	0x422218D3 /* 440EP rev B and 440GR rev A have same PVR */
+#define PVR_440GR_RB	0x422218D4 /* 440EP rev C and 440GR rev B have same PVR */
+#define PVR_440EPX1_RA	0x216218D0 /* 440EPX rev A with Security / Kasumi */
+#define PVR_440EPX2_RA	0x216218D4 /* 440EPX rev A without Security / Kasumi */
+#define PVR_440GRX1_RA	0x216218D0 /* 440GRX rev A with Security / Kasumi */
+#define PVR_440GRX2_RA	0x216218D4 /* 440GRX rev A without Security / Kasumi */
+#define PVR_440GX_RA	0x51B21850
+#define PVR_440GX_RB	0x51B21851
+#define PVR_440GX_RC	0x51B21892
+#define PVR_440GX_RF	0x51B21894
+#define PVR_405EP_RB	0x51210950
+#define PVR_440SP_6_RAB	0x53221850 /* 440SP rev A&B with RAID 6 support enabled	*/
+#define PVR_440SP_RAB	0x53321850 /* 440SP rev A&B without RAID 6 support	*/
+#define PVR_440SP_6_RC	0x53221891 /* 440SP rev C with RAID 6 support enabled	*/
+#define PVR_440SP_RC	0x53321891 /* 440SP rev C without RAID 6 support	*/
+#define PVR_440SPe_6_RA	0x53421890 /* 440SPe rev A with RAID 6 support enabled	*/
+#define PVR_440SPe_RA	0x53521890 /* 440SPe rev A without RAID 6 support	*/
+#define PVR_440SPe_6_RB	0x53421891 /* 440SPe rev B with RAID 6 support enabled	*/
+#define PVR_440SPe_RB	0x53521891 /* 440SPe rev B without RAID 6 support	*/
+#define PVR_460EX_SE_RA	0x130218A2 /* 460EX rev A with Security Engine	  */
+#define PVR_460EX_RA	0x130218A3 /* 460EX rev A without Security Engine */
+#define PVR_460EX_RB	0x130218A4 /* 460EX rev B with and without Sec Eng*/
+#define PVR_460GT_SE_RA	0x130218A0 /* 460GT rev A with Security Engine	  */
+#define PVR_460GT_RA	0x130218A1 /* 460GT rev A without Security Engine */
+#define PVR_460GT_RB	0x130218A5 /* 460GT rev B with and without Sec Eng*/
+#define PVR_460SX_RA    0x13541800 /* 460SX rev A                   */
+#define PVR_460SX_RA_V1 0x13541801 /* 460SX rev A Variant 1 Security disabled */
+#define PVR_460GX_RA    0x13541802 /* 460GX rev A                   */
+#define PVR_460GX_RA_V1 0x13541803 /* 460GX rev A Variant 1 Security disabled */
+#define PVR_601		0x00010000
+#define PVR_602		0x00050000
+#define PVR_603		0x00030000
+#define PVR_603e	0x00060000
+#define PVR_603ev	0x00070000
+#define PVR_603r	0x00071000
+#define PVR_604		0x00040000
+#define PVR_604e	0x00090000
+#define PVR_604r	0x000A0000
+#define PVR_620		0x00140000
+#define PVR_740		0x00080000
+#define PVR_750		PVR_740
+#define PVR_740P	0x10080000
+#define PVR_750P	PVR_740P
+#define PVR_7400	0x000C0000
+#define PVR_7410	0x800C0000
+#define PVR_7450	0x80000000
+
+#define PVR_85xx	0x80200000
+#define PVR_85xx_REV1	(PVR_85xx | 0x0010)
+#define PVR_85xx_REV2	(PVR_85xx | 0x0020)
+
+#define PVR_86xx	0x80040000
+
+#define PVR_VIRTEX5     0x7ff21912
+
+/*
+ * For the 8xx processors, all of them report the same PVR family for
+ * the PowerPC core. The various versions of these processors must be
+ * differentiated by the version number in the Communication Processor
+ * Module (CPM).
+ */
+#define PVR_821		0x00500000
+#define PVR_823		PVR_821
+#define PVR_850		PVR_821
+#define PVR_860		PVR_821
+#define PVR_7400	0x000C0000
+#define PVR_8240	0x00810100
+
+/*
+ * PowerQUICC II family processors report different PVR values depending
+ * on silicon process (HiP3, HiP4, HiP7, etc.)
+ */
+#define PVR_8260	PVR_8240
+#define PVR_8260_HIP3	0x00810101
+#define PVR_8260_HIP4	0x80811014
+#define PVR_8260_HIP7	0x80822011
+#define PVR_8260_HIP7R1 0x80822013
+#define PVR_8260_HIP7RA	0x80822014
+
+/*
+ * MPC 52xx
+ */
+#define PVR_5200	0x80822011
+#define PVR_5200B	0x80822014
+
+/*
+ * System Version Register
+ */
+
+/* System Version Register (SVR) field extraction */
+
+#define SVR_VER(svr)	(((svr) >>  16) & 0xFFFF)	/* Version field */
+#define SVR_REV(svr)	(((svr) >>   0) & 0xFFFF)	/* Revison field */
+
+#define SVR_SUBVER(svr)	(((svr) >>  8) & 0xFF)	/* Process/MFG sub-version */
+
+#define SVR_FAM(svr)	(((svr) >> 20) & 0xFFF)	/* Family field */
+#define SVR_MEM(svr)	(((svr) >> 16) & 0xF)	/* Member field */
+
+#define SVR_MAJ(svr)	(((svr) >>  4) & 0xF)	/* Major revision field*/
+#define SVR_MIN(svr)	(((svr) >>  0) & 0xF)	/* Minor revision field*/
+
+/* Some parts define SVR[0:23] as the SOC version */
+#define SVR_SOC_VER(svr) (((svr) >> 8) & 0xFFFFFF)	/* SOC Version fields */
+
+/* whether MPC8xxxE (i.e. has SEC) */
+#if defined(CONFIG_MPC85xx)
+#define IS_E_PROCESSOR(svr)	(svr & 0x80000)
+#else
+#if defined(CONFIG_MPC83xx)
+#define IS_E_PROCESSOR(spridr)	(!(spridr & 0x00010000))
+#endif
+#endif
+
+#define IS_SVR_REV(svr, maj, min) \
+	((SVR_MAJ(svr) == maj) && (SVR_MIN(svr) == min))
+
+/*
+ * SVR_SOC_VER() Version Values
+ */
+
+#define SVR_8533	0x803400
+#define SVR_8533_E	0x803C00
+#define SVR_8535	0x803701
+#define SVR_8535_E	0x803F01
+#define SVR_8536	0x803700
+#define SVR_8536_E	0x803F00
+#define SVR_8540	0x803000
+#define SVR_8541	0x807200
+#define SVR_8541_E	0x807A00
+#define SVR_8543	0x803200
+#define SVR_8543_E	0x803A00
+#define SVR_8544	0x803401
+#define SVR_8544_E	0x803C01
+#define SVR_8545	0x803102
+#define SVR_8545_E	0x803902
+#define SVR_8547_E	0x803901
+#define SVR_8548	0x803100
+#define SVR_8548_E	0x803900
+#define SVR_8555	0x807100
+#define SVR_8555_E	0x807900
+#define SVR_8560	0x807000
+#define SVR_8567	0x807600
+#define SVR_8567_E	0x807E00
+#define SVR_8568	0x807500
+#define SVR_8568_E	0x807D00
+#define SVR_8569	0x808000
+#define SVR_8569_E	0x808800
+#define SVR_8572	0x80E000
+#define SVR_8572_E	0x80E800
+#define SVR_P1011	0x80E500
+#define SVR_P1011_E	0x80ED00
+#define SVR_P1012	0x80E501
+#define SVR_P1012_E	0x80ED01
+#define SVR_P1013	0x80E700
+#define SVR_P1013_E	0x80EF00
+#define SVR_P1020	0x80E400
+#define SVR_P1020_E	0x80EC00
+#define SVR_P1021	0x80E401
+#define SVR_P1021_E	0x80EC01
+#define SVR_P1022	0x80E600
+#define SVR_P1022_E	0x80EE00
+#define SVR_P2010	0x80E300
+#define SVR_P2010_E	0x80EB00
+#define SVR_P2020	0x80E200
+#define SVR_P2020_E	0x80EA00
+#define SVR_P4040	0x820100
+#define SVR_P4040_E	0x820900
+#define SVR_P4080	0x820000
+#define SVR_P4080_E	0x820800
+
+#define SVR_8610	0x80A000
+#define SVR_8641	0x809000
+#define SVR_8641D	0x809001
+
+#define SVR_Unknown	0xFFFFFF
+
+#define _GLOBAL(n)\
+	.globl n;\
+n:
+
+/* Macros for setting and retrieving special purpose registers */
+
+#define stringify(s)	tostring(s)
+#define tostring(s)	#s
+
+#define mfdcr(rn)	({unsigned int rval; \
+			asm volatile("mfdcr %0," stringify(rn) \
+				     : "=r" (rval)); rval;})
+#define mtdcr(rn, v)	asm volatile("mtdcr " stringify(rn) ",%0" : : "r" (v))
+
+#define mfmsr()		({unsigned int rval; \
+			asm volatile("mfmsr %0" : "=r" (rval)); rval;})
+#define mtmsr(v)	asm volatile("mtmsr %0" : : "r" (v))
+
+#define mfspr(rn)	({unsigned int rval; \
+			asm volatile("mfspr %0," stringify(rn) \
+				     : "=r" (rval)); rval;})
+#define mtspr(rn, v)	asm volatile("mtspr " stringify(rn) ",%0" : : "r" (v))
+
+#define tlbie(v)	asm volatile("tlbie %0 \n sync" : : "r" (v))
+
+/* Segment Registers */
+
+#define SR0	0
+#define SR1	1
+#define SR2	2
+#define SR3	3
+#define SR4	4
+#define SR5	5
+#define SR6	6
+#define SR7	7
+#define SR8	8
+#define SR9	9
+#define SR10	10
+#define SR11	11
+#define SR12	12
+#define SR13	13
+#define SR14	14
+#define SR15	15
+
+#ifndef __ASSEMBLY__
+
+struct cpu_type {
+	char name[15];
+	u32 soc_ver;
+	u32 num_cores;
+};
+
+struct cpu_type *identify_cpu(u32 ver);
+
+#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
+#define CPU_TYPE_ENTRY(n, v, nc) \
+	{ .name = #n, .soc_ver = SVR_##v, .num_cores = (nc), }
+#else
+#if defined(CONFIG_MPC83xx)
+#define CPU_TYPE_ENTRY(x) {#x, SPR_##x}
+#endif
+#endif
+
+
+#ifndef CONFIG_MACH_SPECIFIC
+extern int _machine;
+extern int have_of;
+#endif /* CONFIG_MACH_SPECIFIC */
+
+/* what kind of prep workstation we are */
+extern int _prep_type;
+/*
+ * This is used to identify the board type from a given PReP board
+ * vendor. Board revision is also made available.
+ */
+extern unsigned char ucSystemType;
+extern unsigned char ucBoardRev;
+extern unsigned char ucBoardRevMaj, ucBoardRevMin;
+
+struct task_struct;
+void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
+void release_thread(struct task_struct *);
+
+/*
+ * Create a new kernel thread.
+ */
+extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+
+/*
+ * Bus types
+ */
+#define EISA_bus 0
+#define EISA_bus__is_a_macro /* for versions in ksyms.c */
+#define MCA_bus 0
+#define MCA_bus__is_a_macro /* for versions in ksyms.c */
+
+/* Lazy FPU handling on uni-processor */
+extern struct task_struct *last_task_used_math;
+extern struct task_struct *last_task_used_altivec;
+
+/*
+ * this is the minimum allowable io space due to the location
+ * of the io areas on prep (first one at 0x80000000) but
+ * as soon as I get around to remapping the io areas with the BATs
+ * to match the mac we can raise this. -- Cort
+ */
+#define TASK_SIZE	(0x80000000UL)
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE	(TASK_SIZE / 8 * 3)
+
+typedef struct {
+	unsigned long seg;
+} mm_segment_t;
+
+struct thread_struct {
+	unsigned long	ksp;		/* Kernel stack pointer */
+	unsigned long	wchan;		/* Event task is sleeping on */
+	struct pt_regs	*regs;		/* Pointer to saved register state */
+	mm_segment_t	fs;		/* for get_fs() validation */
+	void		*pgdir;		/* root of page-table tree */
+	signed long	last_syscall;
+	double		fpr[32];	/* Complete floating point set */
+	unsigned long	fpscr_pad;	/* fpr ... fpscr must be contiguous */
+	unsigned long	fpscr;		/* Floating point status */
+#ifdef CONFIG_ALTIVEC
+	vector128	vr[32];		/* Complete AltiVec set */
+	vector128	vscr;		/* AltiVec status */
+	unsigned long	vrsave;
+#endif /* CONFIG_ALTIVEC */
+};
+
+#define INIT_SP		(sizeof(init_stack) + (unsigned long) &init_stack)
+
+#define INIT_THREAD  { \
+	INIT_SP, /* ksp */ \
+	0, /* wchan */ \
+	(struct pt_regs *)INIT_SP - 1, /* regs */ \
+	KERNEL_DS, /*fs*/ \
+	swapper_pg_dir, /* pgdir */ \
+	0, /* last_syscall */ \
+	{0}, 0, 0 \
+}
+
+/*
+ * Note: the vm_start and vm_end fields here should *not*
+ * be in kernel space.	(Could vm_end == vm_start perhaps?)
+ */
+#define INIT_MMAP { &init_mm, 0, 0x1000, NULL, \
+		    PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, \
+		    1, NULL, NULL }
+
+/*
+ * Return saved PC of a blocked thread. For now, this is the "user" PC
+ */
+static inline unsigned long thread_saved_pc(struct thread_struct *t)
+{
+	return (t->regs) ? t->regs->nip : 0;
+}
+
+#define copy_segments(tsk, mm)		do { } while (0)
+#define release_segments(mm)		do { } while (0)
+#define forget_segments()		do { } while (0)
+
+unsigned long get_wchan(struct task_struct *p);
+
+#define KSTK_EIP(tsk)  ((tsk)->thread.regs->nip)
+#define KSTK_ESP(tsk)  ((tsk)->thread.regs->gpr[1])
+
+/*
+ * NOTE! The task struct and the stack go together
+ */
+#define THREAD_SIZE (2*PAGE_SIZE)
+#define alloc_task_struct() \
+	((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
+#define free_task_struct(p)	free_pages((unsigned long)(p),1)
+#define get_task_struct(tsk)	  atomic_inc(&mem_map[MAP_NR(tsk)].count)
+
+/* in process.c - for early bootup debug -- Cort */
+int ll_printk(const char *, ...);
+void ll_puts(const char *);
+
+#define init_task	(init_task_union.task)
+#define init_stack	(init_task_union.stack)
+
+/* In misc.c */
+void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
+
+#endif /* ndef ASSEMBLY*/
+
+#ifdef CONFIG_MACH_SPECIFIC
+#if defined(CONFIG_8xx)
+#define _machine _MACH_8xx
+#define have_of 0
+#elif defined(CONFIG_OAK)
+#define _machine _MACH_oak
+#define have_of	0
+#elif defined(CONFIG_WALNUT)
+#define _machine _MACH_walnut
+#define have_of 0
+#elif defined(CONFIG_APUS)
+#define _machine _MACH_apus
+#define have_of 0
+#elif defined(CONFIG_GEMINI)
+#define _machine _MACH_gemini
+#define have_of 0
+#elif defined(CONFIG_8260)
+#define _machine _MACH_8260
+#define have_of 0
+#elif defined(CONFIG_SANDPOINT)
+#define _machine _MACH_sandpoint
+#elif defined(CONFIG_HIDDEN_DRAGON)
+#define _machine _MACH_hidden_dragon
+#define have_of 0
+#else
+#error "Machine not defined correctly"
+#endif
+#endif /* CONFIG_MACH_SPECIFIC */
+
+#endif /* __ASM_PPC_PROCESSOR_H */
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
new file mode 100644
index 0000000..cf09edf
--- /dev/null
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -0,0 +1,107 @@
+#ifndef _PPC_PTRACE_H
+#define _PPC_PTRACE_H
+
+/*
+ * This struct defines the way the registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ *
+ * this should only contain volatile regs
+ * since we can keep non-volatile in the thread_struct
+ * should set this up when only volatiles are saved
+ * by intr code.
+ *
+ * Since this is going on the stack, *CARE MUST BE TAKEN* to insure
+ * that the overall structure is a multiple of 16 bytes in length.
+ *
+ * Note that the offsets of the fields in this struct correspond with
+ * the PT_* values below.  This simplifies arch/powerpc/kernel/ptrace.c.
+ */
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_PPC64BRIDGE
+#define PPC_REG unsigned long /*long*/
+#else
+#define PPC_REG unsigned long
+#endif
+struct pt_regs {
+	PPC_REG gpr[32];
+	PPC_REG nip;
+	PPC_REG msr;
+	PPC_REG orig_gpr3;	/* Used for restarting system calls */
+	PPC_REG ctr;
+	PPC_REG link;
+	PPC_REG xer;
+	PPC_REG ccr;
+	PPC_REG mq;		/* 601 only (not used at present) */
+				/* Used on APUS to hold IPL value. */
+	PPC_REG trap;		/* Reason for being here */
+	PPC_REG dar;		/* Fault registers */
+	PPC_REG dsisr;
+	PPC_REG result;		/* Result of a system call */
+};
+#endif
+
+#define STACK_FRAME_OVERHEAD	16	/* size of minimum stack frame */
+
+/* Size of stack frame allocated when calling signal handler. */
+#define __SIGNAL_FRAMESIZE	64
+
+#define instruction_pointer(regs) ((regs)->nip)
+#define user_mode(regs) (((regs)->msr & MSR_PR) != 0)
+
+/*
+ * Offsets used by 'ptrace' system call interface.
+ * These can't be changed without breaking binary compatibility
+ * with MkLinux, etc.
+ */
+#define PT_R0	0
+#define PT_R1	1
+#define PT_R2	2
+#define PT_R3	3
+#define PT_R4	4
+#define PT_R5	5
+#define PT_R6	6
+#define PT_R7	7
+#define PT_R8	8
+#define PT_R9	9
+#define PT_R10	10
+#define PT_R11	11
+#define PT_R12	12
+#define PT_R13	13
+#define PT_R14	14
+#define PT_R15	15
+#define PT_R16	16
+#define PT_R17	17
+#define PT_R18	18
+#define PT_R19	19
+#define PT_R20	20
+#define PT_R21	21
+#define PT_R22	22
+#define PT_R23	23
+#define PT_R24	24
+#define PT_R25	25
+#define PT_R26	26
+#define PT_R27	27
+#define PT_R28	28
+#define PT_R29	29
+#define PT_R30	30
+#define PT_R31	31
+
+#define PT_NIP	32
+#define PT_MSR	33
+#ifdef __KERNEL__
+#define PT_ORIG_R3 34
+#endif
+#define PT_CTR	35
+#define PT_LNK	36
+#define PT_XER	37
+#define PT_CCR	38
+#define PT_MQ	39
+
+#define PT_FPR0	48	/* each FP reg occupies 2 slots in this space */
+#define PT_FPR31 (PT_FPR0 + 2*31)
+#define PT_FPSCR (PT_FPR0 + 2*32 + 1)
+
+#endif
diff --git a/arch/powerpc/include/asm/residual.h b/arch/powerpc/include/asm/residual.h
new file mode 100644
index 0000000..dc85edb
--- /dev/null
+++ b/arch/powerpc/include/asm/residual.h
@@ -0,0 +1,331 @@
+/* 7/18/95                                                                    */
+/*----------------------------------------------------------------------------*/
+/*      Residual Data header definitions and prototypes                       */
+/*----------------------------------------------------------------------------*/
+
+/* Structure map for RESIDUAL on PowerPC Reference Platform                   */
+/* residual.h - Residual data structure passed in r3.                         */
+/*              Load point passed in r4 to boot image.                        */
+/* For enum's: if given in hex then they are bit significant,                 */
+/*             i.e. only one bit is on for each enum                          */
+/* Reserved fields must be filled with zeros.                                */
+
+#ifndef _RESIDUAL_
+#define _RESIDUAL_
+
+#ifndef __ASSEMBLY__
+
+#define MAX_CPUS 32                     /* These should be set to the maximum */
+#define MAX_MEMS 64                     /* number possible for this system.   */
+#define MAX_DEVICES 256                 /* Changing these will change the     */
+#define AVE_PNP_SIZE 32                 /* structure, hence the version of    */
+#define MAX_MEM_SEGS 64                 /* this header file.                  */
+
+/*----------------------------------------------------------------------------*/
+/*               Public structures...                                         */
+/*----------------------------------------------------------------------------*/
+
+#include "pnp.h"
+
+typedef enum _L1CACHE_TYPE {
+  NoneCAC = 0,
+  SplitCAC = 1,
+  CombinedCAC = 2
+  } L1CACHE_TYPE;
+
+typedef enum _TLB_TYPE {
+  NoneTLB = 0,
+  SplitTLB = 1,
+  CombinedTLB = 2
+  } TLB_TYPE;
+
+typedef enum _FIRMWARE_SUPPORT {
+  Conventional = 0x01,
+  OpenFirmware = 0x02,
+  Diagnostics = 0x04,
+  LowDebug = 0x08,
+  Multiboot = 0x10,
+  LowClient = 0x20,
+  Hex41 = 0x40,
+  FAT = 0x80,
+  ISO9660 = 0x0100,
+  SCSI_InitiatorID_Override = 0x0200,
+  Tape_Boot = 0x0400,
+  FW_Boot_Path = 0x0800
+  } FIRMWARE_SUPPORT;
+
+typedef enum _FIRMWARE_SUPPLIERS {
+  IBMFirmware = 0x00,
+  MotoFirmware = 0x01,                  /* 7/18/95                            */
+  FirmWorks = 0x02,                     /* 10/5/95                            */
+  Bull = 0x03,                          /* 04/03/96                           */
+  } FIRMWARE_SUPPLIERS;
+
+typedef enum _ENDIAN_SWITCH_METHODS {
+  UsePort92 = 0x01,
+  UsePCIConfigA8 = 0x02,
+  UseFF001030 = 0x03,
+  } ENDIAN_SWITCH_METHODS;
+
+typedef enum _SPREAD_IO_METHODS {
+  UsePort850 = 0x00,
+/*UsePCIConfigA8 = 0x02,*/
+  } SPREAD_IO_METHODS;
+
+typedef struct _VPD {
+
+  /* Box dependent stuff */
+  unsigned char PrintableModel[32];     /* Null terminated string.
+					   Must be of the form:
+					   vvv,<20h>,<model designation>,<0x0>
+					   where vvv is the vendor ID
+					   e.g. IBM PPS MODEL 6015<0x0>       */
+  unsigned char Serial[16];             /* 12/94:
+					   Serial Number; must be of the form:
+					   vvv<serial number> where vvv is the
+					   vendor ID.
+					   e.g. IBM60151234567<20h><20h>      */
+  unsigned char Reserved[48];
+  unsigned long FirmwareSupplier;       /* See FirmwareSuppliers enum         */
+  unsigned long FirmwareSupports;       /* See FirmwareSupport enum           */
+  unsigned long NvramSize;              /* Size of nvram in bytes             */
+  unsigned long NumSIMMSlots;
+  unsigned short EndianSwitchMethod;    /* See EndianSwitchMethods enum       */
+  unsigned short SpreadIOMethod;        /* See SpreadIOMethods enum           */
+  unsigned long SmpIar;
+  unsigned long RAMErrLogOffset;        /* Heap offset to error log           */
+  unsigned long Reserved5;
+  unsigned long Reserved6;
+  unsigned long ProcessorHz;            /* Processor clock frequency in Hertz */
+  unsigned long ProcessorBusHz;         /* Processor bus clock frequency      */
+  unsigned long Reserved7;
+  unsigned long TimeBaseDivisor;        /* (Bus clocks per timebase tic)*1000 */
+  unsigned long WordWidth;              /* Word width in bits                 */
+  unsigned long PageSize;               /* Page size in bytes                 */
+  unsigned long CoherenceBlockSize;     /* Unit of transfer in/out of cache
+					   for which coherency is maintained;
+					   normally <= CacheLineSize.         */
+  unsigned long GranuleSize;            /* Unit of lock allocation to avoid   */
+					/*   false sharing of locks.          */
+
+  /* L1 Cache variables */
+  unsigned long CacheSize;              /* L1 Cache size in KB. This is the   */
+					/*   total size of the L1, whether    */
+					/*   combined or split                */
+  unsigned long CacheAttrib;            /* L1CACHE_TYPE                       */
+  unsigned long CacheAssoc;             /* L1 Cache associativity. Use this
+					   for combined cache. If split, put
+					   zeros here.                        */
+  unsigned long CacheLineSize;          /* L1 Cache line size in bytes. Use
+					   for combined cache. If split, put
+					   zeros here.                        */
+  /* For split L1 Cache: (= combined if combined cache) */
+  unsigned long I_CacheSize;
+  unsigned long I_CacheAssoc;
+  unsigned long I_CacheLineSize;
+  unsigned long D_CacheSize;
+  unsigned long D_CacheAssoc;
+  unsigned long D_CacheLineSize;
+
+  /* Translation Lookaside Buffer variables */
+  unsigned long TLBSize;                /* Total number of TLBs on the system */
+  unsigned long TLBAttrib;              /* Combined I+D or split TLB          */
+  unsigned long TLBAssoc;               /* TLB Associativity. Use this for
+					   combined TLB. If split, put zeros
+					   here.                              */
+  /* For split TLB: (= combined if combined TLB) */
+  unsigned long I_TLBSize;
+  unsigned long I_TLBAssoc;
+  unsigned long D_TLBSize;
+  unsigned long D_TLBAssoc;
+
+  unsigned long ExtendedVPD;            /* Offset to extended VPD area;
+					   null if unused                     */
+  } VPD;
+
+typedef enum _DEVICE_FLAGS {
+  Enabled = 0x4000,                     /* 1 - PCI device is enabled          */
+  Integrated = 0x2000,
+  Failed = 0x1000,                      /* 1 - device failed POST code tests  */
+  Static = 0x0800,                      /* 0 - dynamically configurable
+					   1 - static                         */
+  Dock = 0x0400,                        /* 0 - not a docking station device
+					   1 - is a docking station device    */
+  Boot = 0x0200,                        /* 0 - device cannot be used for BOOT
+					   1 - can be a BOOT device           */
+  Configurable = 0x0100,                /* 1 - device is configurable         */
+  Disableable = 0x80,                   /* 1 - device can be disabled         */
+  PowerManaged = 0x40,                  /* 0 - not managed; 1 - managed       */
+  ReadOnly = 0x20,                      /* 1 - device is read only            */
+  Removable = 0x10,                     /* 1 - device is removable            */
+  ConsoleIn = 0x08,
+  ConsoleOut = 0x04,
+  Input = 0x02,
+  Output = 0x01
+  } DEVICE_FLAGS;
+
+typedef enum _BUS_ID {
+  ISADEVICE = 0x01,
+  EISADEVICE = 0x02,
+  PCIDEVICE = 0x04,
+  PCMCIADEVICE = 0x08,
+  PNPISADEVICE = 0x10,
+  MCADEVICE = 0x20,
+  MXDEVICE = 0x40,                      /* Devices on mezzanine bus           */
+  PROCESSORDEVICE = 0x80,               /* Devices on processor bus           */
+  VMEDEVICE = 0x100,
+  } BUS_ID;
+
+typedef struct _DEVICE_ID {
+  unsigned long BusId;                  /* See BUS_ID enum above              */
+  unsigned long DevId;                  /* Big Endian format                  */
+  unsigned long SerialNum;              /* For multiple usage of a single
+					   DevId                              */
+  unsigned long Flags;                  /* See DEVICE_FLAGS enum above        */
+  unsigned char BaseType;               /* See pnp.h for bit definitions      */
+  unsigned char SubType;                /* See pnp.h for bit definitions      */
+  unsigned char Interface;              /* See pnp.h for bit definitions      */
+  unsigned char Spare;
+  } DEVICE_ID;
+
+typedef union _BUS_ACCESS {
+  struct _PnPAccess{
+    unsigned char CSN;
+    unsigned char LogicalDevNumber;
+    unsigned short ReadDataPort;
+    } PnPAccess;
+  struct _ISAAccess{
+    unsigned char SlotNumber;           /* ISA Slot Number generally not
+					   available; 0 if unknown            */
+    unsigned char LogicalDevNumber;
+    unsigned short ISAReserved;
+    } ISAAccess;
+  struct _MCAAccess{
+    unsigned char SlotNumber;
+    unsigned char LogicalDevNumber;
+    unsigned short MCAReserved;
+    } MCAAccess;
+  struct _PCMCIAAccess{
+    unsigned char SlotNumber;
+    unsigned char LogicalDevNumber;
+    unsigned short PCMCIAReserved;
+    } PCMCIAAccess;
+  struct _EISAAccess{
+    unsigned char SlotNumber;
+    unsigned char FunctionNumber;
+    unsigned short EISAReserved;
+    } EISAAccess;
+  struct _PCIAccess{
+    unsigned char BusNumber;
+    unsigned char DevFuncNumber;
+    unsigned short PCIReserved;
+    } PCIAccess;
+  struct _ProcBusAccess{
+    unsigned char BusNumber;
+    unsigned char BUID;
+    unsigned short ProcBusReserved;
+    } ProcBusAccess;
+  } BUS_ACCESS;
+
+/* Per logical device information */
+typedef struct _PPC_DEVICE {
+  DEVICE_ID DeviceId;
+  BUS_ACCESS BusAccess;
+
+  /* The following three are offsets into the DevicePnPHeap */
+  /* All are in PnP compressed format                       */
+  unsigned long AllocatedOffset;        /* Allocated resource description     */
+  unsigned long PossibleOffset;         /* Possible resource description      */
+  unsigned long CompatibleOffset;       /* Compatible device identifiers      */
+  } PPC_DEVICE;
+
+typedef enum _CPU_STATE {
+  CPU_GOOD = 0,                         /* CPU is present, and active         */
+  CPU_GOOD_FW = 1,                      /* CPU is present, and in firmware    */
+  CPU_OFF = 2,                          /* CPU is present, but inactive       */
+  CPU_FAILED = 3,                       /* CPU is present, but failed POST    */
+  CPU_NOT_PRESENT = 255                 /* CPU not present                    */
+  } CPU_STATE;
+
+typedef struct _PPC_CPU {
+  unsigned long CpuType;                /* Result of mfspr from Processor
+					   Version Register (PVR).
+					   PVR(0-15) = Version (e.g. 601)
+					   PVR(16-31 = EC Level               */
+  unsigned char CpuNumber;              /* CPU Number for this processor      */
+  unsigned char CpuState;               /* CPU State, see CPU_STATE enum      */
+  unsigned short Reserved;
+  } PPC_CPU;
+
+typedef struct _PPC_MEM {
+  unsigned long SIMMSize;               /* 0 - absent or bad
+					   8M, 32M (in MB)                    */
+  } PPC_MEM;
+
+typedef enum _MEM_USAGE {
+  Other = 0x8000,
+  ResumeBlock = 0x4000,                 /* for use by power management        */
+  SystemROM = 0x2000,                   /* Flash memory (populated)           */
+  UnPopSystemROM = 0x1000,              /* Unpopulated part of SystemROM area */
+  IOMemory = 0x0800,
+  SystemIO = 0x0400,
+  SystemRegs = 0x0200,
+  PCIAddr = 0x0100,
+  PCIConfig = 0x80,
+  ISAAddr = 0x40,
+  Unpopulated = 0x20,                   /* Unpopulated part of System Memory  */
+  Free = 0x10,                          /* Free part of System Memory         */
+  BootImage = 0x08,                     /* BootImage part of System Memory    */
+  FirmwareCode = 0x04,                  /* FirmwareCode part of System Memory */
+  FirmwareHeap = 0x02,                  /* FirmwareHeap part of System Memory */
+  FirmwareStack = 0x01                  /* FirmwareStack part of System Memory*/
+  } MEM_USAGE;
+
+typedef struct _MEM_MAP {
+  unsigned long Usage;                  /* See MEM_USAGE above                */
+  unsigned long BasePage;               /* Page number measured in 4KB pages  */
+  unsigned long PageCount;              /* Page count measured in 4KB pages   */
+  } MEM_MAP;
+
+typedef struct _RESIDUAL {
+  unsigned long ResidualLength;         /* Length of Residual                 */
+  unsigned char Version;                /* of this data structure             */
+  unsigned char Revision;               /* of this data structure             */
+  unsigned short EC;                    /* of this data structure             */
+  /* VPD */
+  VPD VitalProductData;
+  /* CPU */
+  unsigned short MaxNumCpus;            /* Max CPUs in this system            */
+  unsigned short ActualNumCpus;         /* ActualNumCpus < MaxNumCpus means   */
+					/* that there are unpopulated or      */
+					/* otherwise unusable cpu locations   */
+  PPC_CPU Cpus[MAX_CPUS];
+  /* Memory */
+  unsigned long TotalMemory;            /* Total amount of memory installed   */
+  unsigned long GoodMemory;             /* Total amount of good memory        */
+  unsigned long ActualNumMemSegs;
+  MEM_MAP Segs[MAX_MEM_SEGS];
+  unsigned long ActualNumMemories;
+  PPC_MEM Memories[MAX_MEMS];
+  /* Devices */
+  unsigned long ActualNumDevices;
+  PPC_DEVICE Devices[MAX_DEVICES];
+  unsigned char DevicePnPHeap[2*MAX_DEVICES*AVE_PNP_SIZE];
+  } RESIDUAL;
+
+
+extern RESIDUAL *res;
+extern void print_residual_device_info(void);
+extern PPC_DEVICE *residual_find_device(unsigned long BusMask,
+					unsigned char * DevID, int BaseType,
+					int SubType, int Interface, int n);
+extern PnP_TAG_PACKET *PnP_find_packet(unsigned char *p, unsigned packet_tag,
+				       int n);
+extern PnP_TAG_PACKET *PnP_find_small_vendor_packet(unsigned char *p,
+						    unsigned packet_type,
+						    int n);
+extern PnP_TAG_PACKET *PnP_find_large_vendor_packet(unsigned char *p,
+						    unsigned packet_type,
+						    int n);
+#endif /* __ASSEMBLY__ */
+#endif  /* ndef _RESIDUAL_ */
diff --git a/arch/powerpc/include/asm/sigcontext.h b/arch/powerpc/include/asm/sigcontext.h
new file mode 100644
index 0000000..715c868
--- /dev/null
+++ b/arch/powerpc/include/asm/sigcontext.h
@@ -0,0 +1,15 @@
+#ifndef _ASM_PPC_SIGCONTEXT_H
+#define _ASM_PPC_SIGCONTEXT_H
+
+#include <asm/ptrace.h>
+
+
+struct sigcontext_struct {
+	unsigned long	_unused[4];
+	int		signal;
+	unsigned long	handler;
+	unsigned long	oldmask;
+	struct pt_regs	*regs;
+};
+
+#endif
diff --git a/arch/powerpc/include/asm/signal.h b/arch/powerpc/include/asm/signal.h
new file mode 100644
index 0000000..b11a28e
--- /dev/null
+++ b/arch/powerpc/include/asm/signal.h
@@ -0,0 +1,154 @@
+#ifndef _ASMPPC_SIGNAL_H
+#define _ASMPPC_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+
+#define _NSIG		64
+#define _NSIG_BPW	32
+#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
+
+typedef unsigned long old_sigset_t;		/* at least 32 bits */
+
+typedef struct {
+	unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#define SIGHUP		 1
+#define SIGINT		 2
+#define SIGQUIT		 3
+#define SIGILL		 4
+#define SIGTRAP		 5
+#define SIGABRT		 6
+#define SIGIOT		 6
+#define SIGBUS		 7
+#define SIGFPE		 8
+#define SIGKILL		 9
+#define SIGUSR1		10
+#define SIGSEGV		11
+#define SIGUSR2		12
+#define SIGPIPE		13
+#define SIGALRM		14
+#define SIGTERM		15
+#define SIGSTKFLT	16
+#define SIGCHLD		17
+#define SIGCONT		18
+#define SIGSTOP		19
+#define SIGTSTP		20
+#define SIGTTIN		21
+#define SIGTTOU		22
+#define SIGURG		23
+#define SIGXCPU		24
+#define SIGXFSZ		25
+#define SIGVTALRM	26
+#define SIGPROF		27
+#define SIGWINCH	28
+#define SIGIO		29
+#define SIGPOLL		SIGIO
+/*
+#define SIGLOST		29
+*/
+#define SIGPWR		30
+#define SIGSYS		31
+#define	SIGUNUSED	31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN	32
+#define SIGRTMAX	(_NSIG-1)
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK is not currently supported, but will allow sigaltstack(2).
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP	0x00000001
+#define SA_NOCLDWAIT	0x00000002 /* not supported yet */
+#define SA_SIGINFO	0x00000004
+#define SA_ONSTACK	0x08000000
+#define SA_RESTART	0x10000000
+#define SA_NODEFER	0x40000000
+#define SA_RESETHAND	0x80000000
+
+#define SA_NOMASK	SA_NODEFER
+#define SA_ONESHOT	SA_RESETHAND
+#define SA_INTERRUPT	0x20000000 /* dummy -- ignored */
+
+#define SA_RESTORER	0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK	1
+#define SS_DISABLE	2
+
+#define MINSIGSTKSZ	2048
+#define SIGSTKSZ	8192
+#ifdef __KERNEL__
+
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ */
+#define SA_PROBE		SA_ONESHOT
+#define SA_SAMPLE_RANDOM	SA_RESTART
+#define SA_SHIRQ		0x04000000
+#endif
+
+#define SIG_BLOCK          0	/* for blocking signals */
+#define SIG_UNBLOCK        1	/* for unblocking signals */
+#define SIG_SETMASK        2	/* for setting the signal mask */
+
+/* Type of a signal handler.  */
+typedef void (*__sighandler_t)(int);
+
+#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
+#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
+#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+
+struct old_sigaction {
+	__sighandler_t sa_handler;
+	old_sigset_t sa_mask;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+};
+
+struct sigaction {
+	__sighandler_t sa_handler;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+	sigset_t sa_mask;		/* mask last for extensibility */
+};
+
+struct k_sigaction {
+	struct sigaction sa;
+};
+
+typedef struct sigaltstack {
+	void *ss_sp;
+	int ss_flags;
+	size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+#include <asm/sigcontext.h>
+
+#endif
+
+#endif
diff --git a/arch/powerpc/include/asm/status_led.h b/arch/powerpc/include/asm/status_led.h
new file mode 100644
index 0000000..0375709
--- /dev/null
+++ b/arch/powerpc/include/asm/status_led.h
@@ -0,0 +1,77 @@
+/*
+ * asm/status_led.h
+ *
+ * MPC8xx/MPC8260/MPC5xx based status led support functions
+ */
+
+#ifndef __ASM_STATUS_LED_H__
+#define __ASM_STATUS_LED_H__
+
+/* if not overriden */
+#ifndef CONFIG_BOARD_SPECIFIC_LED
+# if defined(CONFIG_8xx)
+#  include <mpc8xx.h>
+# elif defined(CONFIG_8260)
+#  include <mpc8260.h>
+# elif defined(CONFIG_5xx)
+#  include <mpc5xx.h>
+# else
+#  error CPU specific Status LED header file missing.
+#endif
+
+/* led_id_t is unsigned long mask */
+typedef unsigned long led_id_t;
+
+static inline void __led_init (led_id_t mask, int state)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+#ifdef STATUS_LED_PAR
+	immr->STATUS_LED_PAR &= ~mask;
+#endif
+#ifdef STATUS_LED_ODR
+	immr->STATUS_LED_ODR &= ~mask;
+#endif
+
+#if (STATUS_LED_ACTIVE == 0)
+	if (state == STATUS_LED_ON)
+		immr->STATUS_LED_DAT &= ~mask;
+	else
+		immr->STATUS_LED_DAT |= mask;
+#else
+	if (state == STATUS_LED_ON)
+		immr->STATUS_LED_DAT |= mask;
+	else
+		immr->STATUS_LED_DAT &= ~mask;
+#endif
+#ifdef STATUS_LED_DIR
+	immr->STATUS_LED_DIR |= mask;
+#endif
+}
+
+static inline void __led_toggle (led_id_t mask)
+{
+	((immap_t *) CONFIG_SYS_IMMR)->STATUS_LED_DAT ^= mask;
+}
+
+static inline void __led_set (led_id_t mask, int state)
+{
+	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+#if (STATUS_LED_ACTIVE == 0)
+	if (state == STATUS_LED_ON)
+		immr->STATUS_LED_DAT &= ~mask;
+	else
+		immr->STATUS_LED_DAT |= mask;
+#else
+	if (state == STATUS_LED_ON)
+		immr->STATUS_LED_DAT |= mask;
+	else
+		immr->STATUS_LED_DAT &= ~mask;
+#endif
+
+}
+
+#endif
+
+#endif	/* __ASM_STATUS_LED_H__ */
diff --git a/arch/powerpc/include/asm/string.h b/arch/powerpc/include/asm/string.h
new file mode 100644
index 0000000..d912a6b
--- /dev/null
+++ b/arch/powerpc/include/asm/string.h
@@ -0,0 +1,29 @@
+#ifndef _PPC_STRING_H_
+#define _PPC_STRING_H_
+
+#define __HAVE_ARCH_STRCPY
+#define __HAVE_ARCH_STRNCPY
+#define __HAVE_ARCH_STRLEN
+#define __HAVE_ARCH_STRCMP
+#define __HAVE_ARCH_STRCAT
+#define __HAVE_ARCH_MEMSET
+#define __HAVE_ARCH_BCOPY
+#define __HAVE_ARCH_MEMCPY
+#define __HAVE_ARCH_MEMMOVE
+#define __HAVE_ARCH_MEMCMP
+#define __HAVE_ARCH_MEMCHR
+
+extern int strcasecmp(const char *, const char *);
+extern int strncasecmp(const char *, const char *, int);
+extern char * strcpy(char *,const char *);
+extern char * strncpy(char *,const char *, __kernel_size_t);
+extern __kernel_size_t strlen(const char *);
+extern int strcmp(const char *,const char *);
+extern char * strcat(char *, const char *);
+extern void * memset(void *,int,__kernel_size_t);
+extern void * memcpy(void *,const void *,__kernel_size_t);
+extern void * memmove(void *,const void *,__kernel_size_t);
+extern int memcmp(const void *,const void *,__kernel_size_t);
+extern void * memchr(const void *,int,__kernel_size_t);
+
+#endif
diff --git a/arch/powerpc/include/asm/types.h b/arch/powerpc/include/asm/types.h
new file mode 100644
index 0000000..b27a6b7
--- /dev/null
+++ b/arch/powerpc/include/asm/types.h
@@ -0,0 +1,58 @@
+#ifndef _PPC_TYPES_H
+#define _PPC_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned short umode_t;
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
+#endif
+
+typedef struct {
+	__u32 u[4];
+} __attribute__((aligned(16))) vector128;
+
+#ifdef __KERNEL__
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#define BITS_PER_LONG 32
+
+/* DMA addresses are 32-bits wide */
+typedef u32 dma_addr_t;
+
+#ifdef CONFIG_PHYS_64BIT
+typedef unsigned long long phys_addr_t;
+typedef unsigned long long phys_size_t;
+#else
+typedef unsigned long phys_addr_t;
+typedef unsigned long phys_size_t;
+#endif
+
+#endif /* __KERNEL__ */
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/arch/powerpc/include/asm/u-boot.h b/arch/powerpc/include/asm/u-boot.h
new file mode 100644
index 0000000..ea2d22d
--- /dev/null
+++ b/arch/powerpc/include/asm/u-boot.h
@@ -0,0 +1,146 @@
+/*
+ * (C) Copyright 2000 - 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************
+ * NOTE: This header file defines an interface to U-Boot. Including
+ * this (unmodified) header file in another file is considered normal
+ * use of U-Boot, and does *not* fall under the heading of "derived
+ * work".
+ ********************************************************************
+ */
+
+#ifndef __U_BOOT_H__
+#define __U_BOOT_H__
+
+/*
+ * Board information passed to Linux kernel from U-Boot
+ *
+ * include/asm-ppc/u-boot.h
+ */
+
+#ifndef __ASSEMBLY__
+
+typedef struct bd_info {
+	unsigned long	bi_memstart;	/* start of DRAM memory */
+	phys_size_t	bi_memsize;	/* size	 of DRAM memory in bytes */
+	unsigned long	bi_flashstart;	/* start of FLASH memory */
+	unsigned long	bi_flashsize;	/* size	 of FLASH memory */
+	unsigned long	bi_flashoffset; /* reserved area for startup monitor */
+	unsigned long	bi_sramstart;	/* start of SRAM memory */
+	unsigned long	bi_sramsize;	/* size	 of SRAM memory */
+#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \
+	|| defined(CONFIG_E500) || defined(CONFIG_MPC86xx)
+	unsigned long	bi_immr_base;	/* base of IMMR register */
+#endif
+#if defined(CONFIG_MPC5xxx)
+	unsigned long	bi_mbar_base;	/* base of internal registers */
+#endif
+#if defined(CONFIG_MPC83xx)
+	unsigned long	bi_immrbar;
+#endif
+#if defined(CONFIG_MPC8220)
+	unsigned long	bi_mbar_base;	/* base of internal registers */
+	unsigned long   bi_inpfreq;     /* Input Freq, In MHz */
+	unsigned long   bi_pcifreq;     /* PCI Freq, in MHz */
+	unsigned long   bi_pevfreq;     /* PEV Freq, in MHz */
+	unsigned long   bi_flbfreq;     /* Flexbus Freq, in MHz */
+	unsigned long   bi_vcofreq;     /* VCO Freq, in MHz */
+#endif
+	unsigned long	bi_bootflags;	/* boot / reboot flag (for LynxOS) */
+	unsigned long	bi_ip_addr;	/* IP Address */
+	unsigned char	bi_enetaddr[6];	/* OLD: see README.enetaddr */
+	unsigned short	bi_ethspeed;	/* Ethernet speed in Mbps */
+	unsigned long	bi_intfreq;	/* Internal Freq, in MHz */
+	unsigned long	bi_busfreq;	/* Bus Freq, in MHz */
+#if defined(CONFIG_CPM2)
+	unsigned long	bi_cpmfreq;	/* CPM_CLK Freq, in MHz */
+	unsigned long	bi_brgfreq;	/* BRG_CLK Freq, in MHz */
+	unsigned long	bi_sccfreq;	/* SCC_CLK Freq, in MHz */
+	unsigned long	bi_vco;		/* VCO Out from PLL, in MHz */
+#endif
+#if defined(CONFIG_MPC512X)
+	unsigned long	bi_ipsfreq;	/* IPS Bus Freq, in MHz */
+#endif /* CONFIG_MPC512X */
+#if defined(CONFIG_MPC5xxx)
+	unsigned long	bi_ipbfreq;	/* IPB Bus Freq, in MHz */
+	unsigned long	bi_pcifreq;	/* PCI Bus Freq, in MHz */
+#endif
+	unsigned long	bi_baudrate;	/* Console Baudrate */
+#if defined(CONFIG_405)   || \
+    defined(CONFIG_405GP) || \
+    defined(CONFIG_405CR) || \
+    defined(CONFIG_405EP) || \
+    defined(CONFIG_405EZ) || \
+    defined(CONFIG_405EX) || \
+    defined(CONFIG_440)
+	unsigned char	bi_s_version[4];	/* Version of this structure */
+	unsigned char	bi_r_version[32];	/* Version of the ROM (AMCC) */
+	unsigned int	bi_procfreq;	/* CPU (Internal) Freq, in Hz */
+	unsigned int	bi_plb_busfreq;	/* PLB Bus speed, in Hz */
+	unsigned int	bi_pci_busfreq;	/* PCI Bus speed, in Hz */
+	unsigned char	bi_pci_enetaddr[6];	/* PCI Ethernet MAC address */
+#endif
+#if defined(CONFIG_HYMOD)
+	hymod_conf_t	bi_hymod_conf;	/* hymod configuration information */
+#endif
+
+#ifdef CONFIG_HAS_ETH1
+	unsigned char   bi_enet1addr[6];	/* OLD: see README.enetaddr */
+#endif
+#ifdef CONFIG_HAS_ETH2
+	unsigned char	bi_enet2addr[6];	/* OLD: see README.enetaddr */
+#endif
+#ifdef CONFIG_HAS_ETH3
+	unsigned char   bi_enet3addr[6];	/* OLD: see README.enetaddr */
+#endif
+#ifdef CONFIG_HAS_ETH4
+	unsigned char   bi_enet4addr[6];	/* OLD: see README.enetaddr */
+#endif
+#ifdef CONFIG_HAS_ETH5
+	unsigned char   bi_enet5addr[6];	/* OLD: see README.enetaddr */
+#endif
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405EP) || \
+    defined(CONFIG_405EZ) || defined(CONFIG_440GX) || \
+    defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	unsigned int	bi_opbfreq;		/* OPB clock in Hz */
+	int		bi_iic_fast[2];		/* Use fast i2c mode */
+#endif
+#if defined(CONFIG_NX823)
+	unsigned char	bi_sernum[8];
+#endif
+#if defined(CONFIG_4xx)
+#if defined(CONFIG_440GX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	int		bi_phynum[4];           /* Determines phy mapping */
+	int		bi_phymode[4];          /* Determines phy mode */
+#elif defined(CONFIG_405EP) || defined(CONFIG_440)
+	int		bi_phynum[2];           /* Determines phy mapping */
+	int		bi_phymode[2];          /* Determines phy mode */
+#else
+	int		bi_phynum[1];           /* Determines phy mapping */
+	int		bi_phymode[1];          /* Determines phy mode */
+#endif
+#endif /* defined(CONFIG_4xx) */
+} bd_t;
+
+#endif /* __ASSEMBLY__ */
+#endif	/* __U_BOOT_H__ */
diff --git a/arch/powerpc/include/asm/unaligned.h b/arch/powerpc/include/asm/unaligned.h
new file mode 100644
index 0000000..5f1b1e3
--- /dev/null
+++ b/arch/powerpc/include/asm/unaligned.h
@@ -0,0 +1,16 @@
+#ifndef _ASM_POWERPC_UNALIGNED_H
+#define _ASM_POWERPC_UNALIGNED_H
+
+#ifdef __KERNEL__
+
+/*
+ * The PowerPC can do unaligned accesses itself in big endian mode.
+ */
+#include <linux/unaligned/access_ok.h>
+#include <linux/unaligned/generic.h>
+
+#define get_unaligned	__get_unaligned_be
+#define put_unaligned	__put_unaligned_be
+
+#endif	/* __KERNEL__ */
+#endif	/* _ASM_POWERPC_UNALIGNED_H */
diff --git a/arch/powerpc/include/asm/xilinx_irq.h b/arch/powerpc/include/asm/xilinx_irq.h
new file mode 100644
index 0000000..61171c2
--- /dev/null
+++ b/arch/powerpc/include/asm/xilinx_irq.h
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * This work has been supported by: QTechnology  http://qtec.com/
+ * Based on interrupts.c Wolfgang Denk-DENX Software Engineering-wd@denx.de
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef XILINX_IRQ_H
+#define XILINX_IRQ_H
+
+#define intc	XPAR_INTC_0_BASEADDR
+#define ISR	(intc + (0 * 4))	/* Interrupt Status Register */
+#define IPR	(intc + (1 * 4))	/* Interrupt Pending Register */
+#define IER	(intc + (2 * 4))	/* Interrupt Enable Register */
+#define IAR	(intc + (3 * 4))	/* Interrupt Acknowledge Register */
+#define SIE	(intc + (4 * 4))	/* Set Interrupt Enable bits */
+#define CIE	(intc + (5 * 4))	/* Clear Interrupt Enable bits */
+#define IVR	(intc + (6 * 4))	/* Interrupt Vector Register */
+#define MER	(intc + (7 * 4))	/* Master Enable Register */
+
+#define IRQ_MASK(irq)	(1 << (irq & 0x1f))
+
+#define IRQ_MAX		XPAR_INTC_MAX_NUM_INTR_INPUTS
+
+#endif
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
new file mode 100644
index 0000000..334e457
--- /dev/null
+++ b/arch/powerpc/lib/Makefile
@@ -0,0 +1,61 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(ARCH).a
+
+SOBJS-y	+= ppccache.o
+SOBJS-y	+= ppcstring.o
+SOBJS-y	+= ticks.o
+SOBJS-y	+= reloc.o
+
+COBJS-y	+= bat_rw.o
+COBJS-y	+= board.o
+COBJS-y	+= bootm.o
+COBJS-y	+= cache.o
+COBJS-y	+= extable.o
+COBJS-y	+= interrupts.o
+COBJS-$(CONFIG_CMD_KGDB) += kgdb.o
+COBJS-y	+= time.o
+
+SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+$(LIB):	$(obj).depend $(OBJS)
+	@if ! $(CROSS_COMPILE)readelf -S $(OBJS) | grep -q '\.fixup.*PROGBITS';\
+	then \
+		echo "ERROR: Your compiler doesn't generate .fixup sections!";\
+		echo "       Upgrade to a recent toolchain."; \
+		exit 1; \
+	fi;
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/lib/bat_rw.c b/arch/powerpc/lib/bat_rw.c
new file mode 100644
index 0000000..c48c240
--- /dev/null
+++ b/arch/powerpc/lib/bat_rw.c
@@ -0,0 +1,260 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_ADDR_MAP
+#include <addr_map.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int write_bat (ppc_bat_t bat, unsigned long upper, unsigned long lower)
+{
+	int batn = -1;
+
+	sync();
+
+	switch (bat) {
+	case DBAT0:
+		mtspr (DBAT0L, lower);
+		mtspr (DBAT0U, upper);
+		batn = 0;
+		break;
+	case IBAT0:
+		mtspr (IBAT0L, lower);
+		mtspr (IBAT0U, upper);
+		break;
+	case DBAT1:
+		mtspr (DBAT1L, lower);
+		mtspr (DBAT1U, upper);
+		batn = 1;
+		break;
+	case IBAT1:
+		mtspr (IBAT1L, lower);
+		mtspr (IBAT1U, upper);
+		break;
+	case DBAT2:
+		mtspr (DBAT2L, lower);
+		mtspr (DBAT2U, upper);
+		batn = 2;
+		break;
+	case IBAT2:
+		mtspr (IBAT2L, lower);
+		mtspr (IBAT2U, upper);
+		break;
+	case DBAT3:
+		mtspr (DBAT3L, lower);
+		mtspr (DBAT3U, upper);
+		batn = 3;
+		break;
+	case IBAT3:
+		mtspr (IBAT3L, lower);
+		mtspr (IBAT3U, upper);
+		break;
+#ifdef CONFIG_HIGH_BATS
+	case DBAT4:
+		mtspr (DBAT4L, lower);
+		mtspr (DBAT4U, upper);
+		batn = 4;
+		break;
+	case IBAT4:
+		mtspr (IBAT4L, lower);
+		mtspr (IBAT4U, upper);
+		break;
+	case DBAT5:
+		mtspr (DBAT5L, lower);
+		mtspr (DBAT5U, upper);
+		batn = 5;
+		break;
+	case IBAT5:
+		mtspr (IBAT5L, lower);
+		mtspr (IBAT5U, upper);
+		break;
+	case DBAT6:
+		mtspr (DBAT6L, lower);
+		mtspr (DBAT6U, upper);
+		batn = 6;
+		break;
+	case IBAT6:
+		mtspr (IBAT6L, lower);
+		mtspr (IBAT6U, upper);
+		break;
+	case DBAT7:
+		mtspr (DBAT7L, lower);
+		mtspr (DBAT7U, upper);
+		batn = 7;
+		break;
+	case IBAT7:
+		mtspr (IBAT7L, lower);
+		mtspr (IBAT7U, upper);
+		break;
+#endif
+	default:
+		return (-1);
+	}
+
+#ifdef CONFIG_ADDR_MAP
+	if ((gd->flags & GD_FLG_RELOC) && (batn >= 0)) {
+		phys_size_t size;
+		if (!BATU_VALID(upper))
+			size = 0;
+		else
+			size = BATU_SIZE(upper);
+		addrmap_set_entry(BATU_VADDR(upper), BATL_PADDR(lower),
+				  size, batn);
+	}
+#endif
+
+	sync();
+	isync();
+
+	return (0);
+}
+
+int read_bat (ppc_bat_t bat, unsigned long *upper, unsigned long *lower)
+{
+	unsigned long register u;
+	unsigned long register l;
+
+	switch (bat) {
+	case DBAT0:
+		l = mfspr (DBAT0L);
+		u = mfspr (DBAT0U);
+		break;
+	case IBAT0:
+		l = mfspr (IBAT0L);
+		u = mfspr (IBAT0U);
+		break;
+	case DBAT1:
+		l = mfspr (DBAT1L);
+		u = mfspr (DBAT1U);
+		break;
+	case IBAT1:
+		l = mfspr (IBAT1L);
+		u = mfspr (IBAT1U);
+		break;
+	case DBAT2:
+		l = mfspr (DBAT2L);
+		u = mfspr (DBAT2U);
+		break;
+	case IBAT2:
+		l = mfspr (IBAT2L);
+		u = mfspr (IBAT2U);
+		break;
+	case DBAT3:
+		l = mfspr (DBAT3L);
+		u = mfspr (DBAT3U);
+		break;
+	case IBAT3:
+		l = mfspr (IBAT3L);
+		u = mfspr (IBAT3U);
+		break;
+#ifdef CONFIG_HIGH_BATS
+	case DBAT4:
+		l = mfspr (DBAT4L);
+		u = mfspr (DBAT4U);
+		break;
+	case IBAT4:
+		l = mfspr (IBAT4L);
+		u = mfspr (IBAT4U);
+		break;
+	case DBAT5:
+		l = mfspr (DBAT5L);
+		u = mfspr (DBAT5U);
+		break;
+	case IBAT5:
+		l = mfspr (IBAT5L);
+		u = mfspr (IBAT5U);
+		break;
+	case DBAT6:
+		l = mfspr (DBAT6L);
+		u = mfspr (DBAT6U);
+		break;
+	case IBAT6:
+		l = mfspr (IBAT6L);
+		u = mfspr (IBAT6U);
+		break;
+	case DBAT7:
+		l = mfspr (DBAT7L);
+		u = mfspr (DBAT7U);
+		break;
+	case IBAT7:
+		l = mfspr (IBAT7L);
+		u = mfspr (IBAT7U);
+		break;
+#endif
+	default:
+		return (-1);
+	}
+
+	*upper = u;
+	*lower = l;
+
+	return (0);
+}
+
+void print_bats(void)
+{
+	printf("BAT registers:\n");
+
+	printf ("\tIBAT0L = 0x%08X ", mfspr (IBAT0L));
+	printf ("\tIBAT0U = 0x%08X\n", mfspr (IBAT0U));
+	printf ("\tDBAT0L = 0x%08X ", mfspr (DBAT0L));
+	printf ("\tDBAT0U = 0x%08X\n", mfspr (DBAT0U));
+	printf ("\tIBAT1L = 0x%08X ", mfspr (IBAT1L));
+	printf ("\tIBAT1U = 0x%08X\n", mfspr (IBAT1U));
+	printf ("\tDBAT1L = 0x%08X ", mfspr (DBAT1L));
+	printf ("\tDBAT1U = 0x%08X\n", mfspr (DBAT1U));
+	printf ("\tIBAT2L = 0x%08X ", mfspr (IBAT2L));
+	printf ("\tIBAT2U = 0x%08X\n", mfspr (IBAT2U));
+	printf ("\tDBAT2L = 0x%08X ", mfspr (DBAT2L));
+	printf ("\tDBAT2U = 0x%08X\n", mfspr (DBAT2U));
+	printf ("\tIBAT3L = 0x%08X ", mfspr (IBAT3L));
+	printf ("\tIBAT3U = 0x%08X\n", mfspr (IBAT3U));
+	printf ("\tDBAT3L = 0x%08X ", mfspr (DBAT3L));
+	printf ("\tDBAT3U = 0x%08X\n", mfspr (DBAT3U));
+
+#ifdef CONFIG_HIGH_BATS
+	printf ("\tIBAT4L = 0x%08X ", mfspr (IBAT4L));
+	printf ("\tIBAT4U = 0x%08X\n", mfspr (IBAT4U));
+	printf ("\tDBAT4L = 0x%08X ", mfspr (DBAT4L));
+	printf ("\tDBAT4U = 0x%08X\n", mfspr (DBAT4U));
+	printf ("\tIBAT5L = 0x%08X ", mfspr (IBAT5L));
+	printf ("\tIBAT5U = 0x%08X\n", mfspr (IBAT5U));
+	printf ("\tDBAT5L = 0x%08X ", mfspr (DBAT5L));
+	printf ("\tDBAT5U = 0x%08X\n", mfspr (DBAT5U));
+	printf ("\tIBAT6L = 0x%08X ", mfspr (IBAT6L));
+	printf ("\tIBAT6U = 0x%08X\n", mfspr (IBAT6U));
+	printf ("\tDBAT6L = 0x%08X ", mfspr (DBAT6L));
+	printf ("\tDBAT6U = 0x%08X\n", mfspr (DBAT6U));
+	printf ("\tIBAT7L = 0x%08X ", mfspr (IBAT7L));
+	printf ("\tIBAT7U = 0x%08X\n", mfspr (IBAT7U));
+	printf ("\tDBAT7L = 0x%08X ", mfspr (DBAT7L));
+	printf ("\tDBAT7U = 0x%08X\n", mfspr (DBAT7U));
+#endif
+}
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
new file mode 100644
index 0000000..a30acee
--- /dev/null
+++ b/arch/powerpc/lib/board.c
@@ -0,0 +1,1084 @@
+/*
+ * (C) Copyright 2000-2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <malloc.h>
+#include <stdio_dev.h>
+#ifdef CONFIG_8xx
+#include <mpc8xx.h>
+#endif
+#ifdef CONFIG_5xx
+#include <mpc5xx.h>
+#endif
+#ifdef CONFIG_MPC5xxx
+#include <mpc5xxx.h>
+#endif
+#if defined(CONFIG_CMD_IDE)
+#include <ide.h>
+#endif
+#if defined(CONFIG_CMD_SCSI)
+#include <scsi.h>
+#endif
+#if defined(CONFIG_CMD_KGDB)
+#include <kgdb.h>
+#endif
+#ifdef CONFIG_STATUS_LED
+#include <status_led.h>
+#endif
+#include <net.h>
+#ifdef CONFIG_GENERIC_MMC
+#include <mmc.h>
+#endif
+#include <serial.h>
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+#if !defined(CONFIG_CPM2)
+#include <commproc.h>
+#endif
+#endif
+#include <version.h>
+#if defined(CONFIG_BAB7xx)
+#include <w83c553f.h>
+#endif
+#include <dtt.h>
+#if defined(CONFIG_POST)
+#include <post.h>
+#endif
+#if defined(CONFIG_LOGBUFFER)
+#include <logbuff.h>
+#endif
+#if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500)
+#include <asm/cache.h>
+#endif
+#ifdef CONFIG_PS2KBD
+#include <keyboard.h>
+#endif
+
+#ifdef CONFIG_ADDR_MAP
+#include <asm/mmu.h>
+#endif
+
+#ifdef CONFIG_MP
+#include <asm/mp.h>
+#endif
+
+#ifdef CONFIG_BITBANGMII
+#include <miiphy.h>
+#endif
+
+#ifdef CONFIG_SYS_UPDATE_FLASH_SIZE
+extern int update_flash_size (int flash_size);
+#endif
+
+#if defined(CONFIG_SC3)
+extern void sc3_read_eeprom(void);
+#endif
+
+#if defined(CONFIG_CMD_DOC)
+void doc_init (void);
+#endif
+#if defined(CONFIG_HARD_I2C) || \
+    defined(CONFIG_SOFT_I2C)
+#include <i2c.h>
+#endif
+#include <spi.h>
+#include <nand.h>
+
+static char *failed = "*** failed ***\n";
+
+#if defined(CONFIG_OXC) || defined(CONFIG_PCU_E) || defined(CONFIG_RMU)
+extern flash_info_t flash_info[];
+#endif
+
+#if defined(CONFIG_START_IDE)
+extern int board_start_ide(void);
+#endif
+#include <environment.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_ENV_IS_EMBEDDED)
+#define TOTAL_MALLOC_LEN	CONFIG_SYS_MALLOC_LEN
+#elif ( ((CONFIG_ENV_ADDR+CONFIG_ENV_SIZE) < CONFIG_SYS_MONITOR_BASE) || \
+	(CONFIG_ENV_ADDR >= (CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN)) ) || \
+      defined(CONFIG_ENV_IS_IN_NVRAM)
+#define	TOTAL_MALLOC_LEN	(CONFIG_SYS_MALLOC_LEN + CONFIG_ENV_SIZE)
+#else
+#define	TOTAL_MALLOC_LEN	CONFIG_SYS_MALLOC_LEN
+#endif
+
+#if !defined(CONFIG_SYS_MEM_TOP_HIDE)
+#define CONFIG_SYS_MEM_TOP_HIDE	0
+#endif
+
+extern ulong __init_end;
+extern ulong _end;
+ulong monitor_flash_len;
+
+#if defined(CONFIG_CMD_BEDBUG)
+#include <bedbug/type.h>
+#endif
+
+/************************************************************************
+ * Utilities								*
+ ************************************************************************
+ */
+
+/*
+ * All attempts to come up with a "common" initialization sequence
+ * that works for all boards and architectures failed: some of the
+ * requirements are just _too_ different. To get rid of the resulting
+ * mess of board dependend #ifdef'ed code we now make the whole
+ * initialization sequence configurable to the user.
+ *
+ * The requirements for any new initalization function is simple: it
+ * receives a pointer to the "global data" structure as it's only
+ * argument, and returns an integer return code, where 0 means
+ * "continue" and != 0 means "fatal error, hang the system".
+ */
+typedef int (init_fnc_t) (void);
+
+/************************************************************************
+ * Init Utilities							*
+ ************************************************************************
+ * Some of this code should be moved into the core functions,
+ * but let's get it working (again) first...
+ */
+
+static int init_baudrate (void)
+{
+	char tmp[64];	/* long enough for environment variables */
+	int i = getenv_r ("baudrate", tmp, sizeof (tmp));
+
+	gd->baudrate = (i > 0)
+			? (int) simple_strtoul (tmp, NULL, 10)
+			: CONFIG_BAUDRATE;
+	return (0);
+}
+
+/***********************************************************************/
+
+void __board_add_ram_info(int use_default)
+{
+	/* please define platform specific board_add_ram_info() */
+}
+void board_add_ram_info(int) __attribute__((weak, alias("__board_add_ram_info")));
+
+
+static int init_func_ram (void)
+{
+#ifdef	CONFIG_BOARD_TYPES
+	int board_type = gd->board_type;
+#else
+	int board_type = 0;	/* use dummy arg */
+#endif
+	puts ("DRAM:  ");
+
+	if ((gd->ram_size = initdram (board_type)) > 0) {
+		print_size (gd->ram_size, "");
+		board_add_ram_info(0);
+		putc('\n');
+		return (0);
+	}
+	puts (failed);
+	return (1);
+}
+
+/***********************************************************************/
+
+#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
+static int init_func_i2c (void)
+{
+	puts ("I2C:   ");
+	i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+	puts ("ready\n");
+	return (0);
+}
+#endif
+
+#if defined(CONFIG_HARD_SPI)
+static int init_func_spi (void)
+{
+	puts ("SPI:   ");
+	spi_init ();
+	puts ("ready\n");
+	return (0);
+}
+#endif
+
+/***********************************************************************/
+
+#if defined(CONFIG_WATCHDOG)
+static int init_func_watchdog_init (void)
+{
+	puts ("       Watchdog enabled\n");
+	WATCHDOG_RESET ();
+	return (0);
+}
+# define INIT_FUNC_WATCHDOG_INIT	init_func_watchdog_init,
+
+static int init_func_watchdog_reset (void)
+{
+	WATCHDOG_RESET ();
+	return (0);
+}
+# define INIT_FUNC_WATCHDOG_RESET	init_func_watchdog_reset,
+#else
+# define INIT_FUNC_WATCHDOG_INIT	/* undef */
+# define INIT_FUNC_WATCHDOG_RESET	/* undef */
+#endif /* CONFIG_WATCHDOG */
+
+/************************************************************************
+ * Initialization sequence						*
+ ************************************************************************
+ */
+
+init_fnc_t *init_sequence[] = {
+#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
+	probecpu,
+#endif
+#if defined(CONFIG_BOARD_EARLY_INIT_F)
+	board_early_init_f,
+#endif
+#if !defined(CONFIG_8xx_CPUCLK_DEFAULT)
+	get_clocks,		/* get CPU and bus clocks (etc.) */
+#if defined(CONFIG_TQM8xxL) && !defined(CONFIG_TQM866M) \
+    && !defined(CONFIG_TQM885D)
+	adjust_sdram_tbs_8xx,
+#endif
+	init_timebase,
+#endif
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+#if !defined(CONFIG_CPM2)
+	dpram_init,
+#endif
+#endif
+#if defined(CONFIG_BOARD_POSTCLK_INIT)
+	board_postclk_init,
+#endif
+	env_init,
+#if defined(CONFIG_8xx_CPUCLK_DEFAULT)
+	get_clocks_866,		/* get CPU and bus clocks according to the environment variable */
+	sdram_adjust_866,	/* adjust sdram refresh rate according to the new clock */
+	init_timebase,
+#endif
+	init_baudrate,
+	serial_init,
+	console_init_f,
+	display_options,
+#if defined(CONFIG_8260)
+	prt_8260_rsr,
+	prt_8260_clks,
+#endif /* CONFIG_8260 */
+#if defined(CONFIG_MPC83xx)
+	prt_83xx_rsr,
+#endif
+	checkcpu,
+#if defined(CONFIG_MPC5xxx)
+	prt_mpc5xxx_clks,
+#endif /* CONFIG_MPC5xxx */
+#if defined(CONFIG_MPC8220)
+	prt_mpc8220_clks,
+#endif
+	checkboard,
+	INIT_FUNC_WATCHDOG_INIT
+#if defined(CONFIG_MISC_INIT_F)
+	misc_init_f,
+#endif
+	INIT_FUNC_WATCHDOG_RESET
+#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
+	init_func_i2c,
+#endif
+#if defined(CONFIG_HARD_SPI)
+	init_func_spi,
+#endif
+#ifdef CONFIG_POST
+	post_init_f,
+#endif
+	INIT_FUNC_WATCHDOG_RESET
+	init_func_ram,
+#if defined(CONFIG_SYS_DRAM_TEST)
+	testdram,
+#endif /* CONFIG_SYS_DRAM_TEST */
+	INIT_FUNC_WATCHDOG_RESET
+
+	NULL,			/* Terminate this list */
+};
+
+ulong get_effective_memsize(void)
+{
+#ifndef	CONFIG_VERY_BIG_RAM
+	return gd->ram_size;
+#else
+	/* limit stack to what we can reasonable map */
+	return ((gd->ram_size > CONFIG_MAX_MEM_MAPPED) ?
+		 CONFIG_MAX_MEM_MAPPED : gd->ram_size);
+#endif
+}
+
+/************************************************************************
+ *
+ * This is the first part of the initialization sequence that is
+ * implemented in C, but still running from ROM.
+ *
+ * The main purpose is to provide a (serial) console interface as
+ * soon as possible (so we can see any error messages), and to
+ * initialize the RAM so that we can relocate the monitor code to
+ * RAM.
+ *
+ * Be aware of the restrictions: global data is read-only, BSS is not
+ * initialized, and stack space is limited to a few kB.
+ *
+ ************************************************************************
+ */
+
+#ifdef CONFIG_LOGBUFFER
+unsigned long logbuffer_base(void)
+{
+	return CONFIG_SYS_SDRAM_BASE + get_effective_memsize() - LOGBUFF_LEN;
+}
+#endif
+
+void board_init_f (ulong bootflag)
+{
+	bd_t *bd;
+	ulong len, addr, addr_sp;
+	ulong *s;
+	gd_t *id;
+	init_fnc_t **init_fnc_ptr;
+#ifdef CONFIG_PRAM
+	int i;
+	ulong reg;
+	uchar tmp[64];		/* long enough for environment variables */
+#endif
+
+	/* Pointer is writable since we allocated a register for it */
+	gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+	/* compiler optimization barrier needed for GCC >= 3.4 */
+	__asm__ __volatile__("": : :"memory");
+
+#if !defined(CONFIG_CPM2) && !defined(CONFIG_MPC512X) && \
+    !defined(CONFIG_MPC83xx) && !defined(CONFIG_MPC85xx) && \
+    !defined(CONFIG_MPC86xx)
+	/* Clear initial global data */
+	memset ((void *) gd, 0, sizeof (gd_t));
+#endif
+
+	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
+		if ((*init_fnc_ptr) () != 0) {
+			hang ();
+		}
+	}
+
+	/*
+	 * Now that we have DRAM mapped and working, we can
+	 * relocate the code and continue running from DRAM.
+	 *
+	 * Reserve memory at end of RAM for (top down in that order):
+	 *  - area that won't get touched by U-Boot and Linux (optional)
+	 *  - kernel log buffer
+	 *  - protected RAM
+	 *  - LCD framebuffer
+	 *  - monitor code
+	 *  - board info struct
+	 */
+	len = (ulong)&_end - CONFIG_SYS_MONITOR_BASE;
+
+	/*
+	 * Subtract specified amount of memory to hide so that it won't
+	 * get "touched" at all by U-Boot. By fixing up gd->ram_size
+	 * the Linux kernel should now get passed the now "corrected"
+	 * memory size and won't touch it either. This should work
+	 * for arch/ppc and arch/powerpc. Only Linux board ports in
+	 * arch/powerpc with bootwrapper support, that recalculate the
+	 * memory size from the SDRAM controller setup will have to
+	 * get fixed.
+	 */
+	gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE;
+
+	addr = CONFIG_SYS_SDRAM_BASE + get_effective_memsize();
+
+#if defined(CONFIG_MP) && (defined(CONFIG_MPC86xx) || defined(CONFIG_E500))
+	/*
+	 * We need to make sure the location we intend to put secondary core
+	 * boot code is reserved and not used by any part of u-boot
+	 */
+	if (addr > determine_mp_bootpg()) {
+		addr = determine_mp_bootpg();
+		debug ("Reserving MP boot page to %08lx\n", addr);
+	}
+#endif
+
+#ifdef CONFIG_LOGBUFFER
+#ifndef CONFIG_ALT_LB_ADDR
+	/* reserve kernel log buffer */
+	addr -= (LOGBUFF_RESERVE);
+	debug ("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, addr);
+#endif
+#endif
+
+#ifdef CONFIG_PRAM
+	/*
+	 * reserve protected RAM
+	 */
+	i = getenv_r ("pram", (char *)tmp, sizeof (tmp));
+	reg = (i > 0) ? simple_strtoul ((const char *)tmp, NULL, 10) : CONFIG_PRAM;
+	addr -= (reg << 10);		/* size is in kB */
+	debug ("Reserving %ldk for protected RAM at %08lx\n", reg, addr);
+#endif /* CONFIG_PRAM */
+
+	/* round down to next 4 kB limit */
+	addr &= ~(4096 - 1);
+	debug ("Top of RAM usable for U-Boot at: %08lx\n", addr);
+
+#ifdef CONFIG_LCD
+	/* reserve memory for LCD display (always full pages) */
+	addr = lcd_setmem (addr);
+	gd->fb_base = addr;
+#endif /* CONFIG_LCD */
+
+#if defined(CONFIG_VIDEO) && defined(CONFIG_8xx)
+	/* reserve memory for video display (always full pages) */
+	addr = video_setmem (addr);
+	gd->fb_base = addr;
+#endif /* CONFIG_VIDEO  */
+
+	/*
+	 * reserve memory for U-Boot code, data & bss
+	 * round down to next 4 kB limit
+	 */
+	addr -= len;
+	addr &= ~(4096 - 1);
+#ifdef CONFIG_E500
+	/* round down to next 64 kB limit so that IVPR stays aligned */
+	addr &= ~(65536 - 1);
+#endif
+
+	debug ("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
+
+	/*
+	 * reserve memory for malloc() arena
+	 */
+	addr_sp = addr - TOTAL_MALLOC_LEN;
+	debug ("Reserving %dk for malloc() at: %08lx\n",
+			TOTAL_MALLOC_LEN >> 10, addr_sp);
+
+	/*
+	 * (permanently) allocate a Board Info struct
+	 * and a permanent copy of the "global" data
+	 */
+	addr_sp -= sizeof (bd_t);
+	bd = (bd_t *) addr_sp;
+	gd->bd = bd;
+	debug ("Reserving %zu Bytes for Board Info at: %08lx\n",
+			sizeof (bd_t), addr_sp);
+	addr_sp -= sizeof (gd_t);
+	id = (gd_t *) addr_sp;
+	debug ("Reserving %zu Bytes for Global Data at: %08lx\n",
+			sizeof (gd_t), addr_sp);
+
+	/*
+	 * Finally, we set up a new (bigger) stack.
+	 *
+	 * Leave some safety gap for SP, force alignment on 16 byte boundary
+	 * Clear initial stack frame
+	 */
+	addr_sp -= 16;
+	addr_sp &= ~0xF;
+	s = (ulong *)addr_sp;
+	*s-- = 0;
+	*s-- = 0;
+	addr_sp = (ulong)s;
+	debug ("Stack Pointer at: %08lx\n", addr_sp);
+
+	/*
+	 * Save local variables to board info struct
+	 */
+
+	bd->bi_memstart  = CONFIG_SYS_SDRAM_BASE;	/* start of  DRAM memory	*/
+	bd->bi_memsize   = gd->ram_size;	/* size  of  DRAM memory in bytes */
+
+#ifdef CONFIG_IP860
+	bd->bi_sramstart = SRAM_BASE;	/* start of  SRAM memory	*/
+	bd->bi_sramsize  = SRAM_SIZE;	/* size  of  SRAM memory	*/
+#elif defined CONFIG_MPC8220
+	bd->bi_sramstart = CONFIG_SYS_SRAM_BASE;	/* start of  SRAM memory	*/
+	bd->bi_sramsize  = CONFIG_SYS_SRAM_SIZE;	/* size  of  SRAM memory	*/
+#else
+	bd->bi_sramstart = 0;		/* FIXME */ /* start of  SRAM memory	*/
+	bd->bi_sramsize  = 0;		/* FIXME */ /* size  of  SRAM memory	*/
+#endif
+
+#if defined(CONFIG_8xx) || defined(CONFIG_8260) || defined(CONFIG_5xx) || \
+    defined(CONFIG_E500) || defined(CONFIG_MPC86xx)
+	bd->bi_immr_base = CONFIG_SYS_IMMR;	/* base  of IMMR register     */
+#endif
+#if defined(CONFIG_MPC5xxx)
+	bd->bi_mbar_base = CONFIG_SYS_MBAR;	/* base of internal registers */
+#endif
+#if defined(CONFIG_MPC83xx)
+	bd->bi_immrbar = CONFIG_SYS_IMMR;
+#endif
+#if defined(CONFIG_MPC8220)
+	bd->bi_mbar_base = CONFIG_SYS_MBAR;	/* base of internal registers */
+	bd->bi_inpfreq   = gd->inp_clk;
+	bd->bi_pcifreq   = gd->pci_clk;
+	bd->bi_vcofreq   = gd->vco_clk;
+	bd->bi_pevfreq   = gd->pev_clk;
+	bd->bi_flbfreq   = gd->flb_clk;
+
+	/* store bootparam to sram (backward compatible), here? */
+	{
+		u32 *sram = (u32 *)CONFIG_SYS_SRAM_BASE;
+		*sram++ = gd->ram_size;
+		*sram++ = gd->bus_clk;
+		*sram++ = gd->inp_clk;
+		*sram++ = gd->cpu_clk;
+		*sram++ = gd->vco_clk;
+		*sram++ = gd->flb_clk;
+		*sram++ = 0xb8c3ba11;  /* boot signature */
+	}
+#endif
+
+	bd->bi_bootflags = bootflag;	/* boot / reboot flag (for LynxOS)    */
+
+	WATCHDOG_RESET ();
+	bd->bi_intfreq = gd->cpu_clk;	/* Internal Freq, in Hz */
+	bd->bi_busfreq = gd->bus_clk;	/* Bus Freq,      in Hz */
+#if defined(CONFIG_CPM2)
+	bd->bi_cpmfreq = gd->cpm_clk;
+	bd->bi_brgfreq = gd->brg_clk;
+	bd->bi_sccfreq = gd->scc_clk;
+	bd->bi_vco     = gd->vco_out;
+#endif /* CONFIG_CPM2 */
+#if defined(CONFIG_MPC512X)
+	bd->bi_ipsfreq = gd->ips_clk;
+#endif /* CONFIG_MPC512X */
+#if defined(CONFIG_MPC5xxx)
+	bd->bi_ipbfreq = gd->ipb_clk;
+	bd->bi_pcifreq = gd->pci_clk;
+#endif /* CONFIG_MPC5xxx */
+	bd->bi_baudrate = gd->baudrate;	/* Console Baudrate     */
+
+#ifdef CONFIG_SYS_EXTBDINFO
+	strncpy ((char *)bd->bi_s_version, "1.2", sizeof (bd->bi_s_version));
+	strncpy ((char *)bd->bi_r_version, U_BOOT_VERSION, sizeof (bd->bi_r_version));
+
+	bd->bi_procfreq = gd->cpu_clk;	/* Processor Speed, In Hz */
+	bd->bi_plb_busfreq = gd->bus_clk;
+#if defined(CONFIG_405GP) || defined(CONFIG_405EP) || \
+    defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+	bd->bi_pci_busfreq = get_PCI_freq ();
+	bd->bi_opbfreq = get_OPB_freq ();
+#elif defined(CONFIG_XILINX_405)
+	bd->bi_pci_busfreq = get_PCI_freq ();
+#endif
+#endif
+
+	debug ("New Stack Pointer is: %08lx\n", addr_sp);
+
+	WATCHDOG_RESET ();
+
+#ifdef CONFIG_POST
+	post_bootmode_init();
+	post_run (NULL, POST_ROM | post_bootmode_get(0));
+#endif
+
+	WATCHDOG_RESET();
+
+	gd->relocaddr = addr; /* Record relocation address, useful for debug */
+
+	memcpy (id, (void *)gd, sizeof (gd_t));
+
+	relocate_code (addr_sp, id, addr);
+
+	/* NOTREACHED - relocate_code() does not return */
+}
+
+/************************************************************************
+ *
+ * This is the next part if the initialization sequence: we are now
+ * running from RAM and have a "normal" C environment, i. e. global
+ * data can be written, BSS has been cleared, the stack size in not
+ * that critical any more, etc.
+ *
+ ************************************************************************
+ */
+void board_init_r (gd_t *id, ulong dest_addr)
+{
+	char *s;
+	bd_t *bd;
+	ulong malloc_start;
+
+#ifndef CONFIG_SYS_NO_FLASH
+	ulong flash_size;
+#endif
+
+	gd = id;		/* initialize RAM version of global data */
+	bd = gd->bd;
+
+	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
+
+	/* The Malloc area is immediately below the monitor copy in DRAM */
+	malloc_start = dest_addr - TOTAL_MALLOC_LEN;
+
+#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
+	/*
+	 * The gd->cpu pointer is set to an address in flash before relocation.
+	 * We need to update it to point to the same CPU entry in RAM.
+	 */
+	gd->cpu += dest_addr - CONFIG_SYS_MONITOR_BASE;
+#endif
+
+#ifdef CONFIG_SERIAL_MULTI
+	serial_initialize();
+#endif
+
+	debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
+
+	WATCHDOG_RESET ();
+
+	/*
+	 * Setup trap handlers
+	 */
+	trap_init (dest_addr);
+
+#ifdef CONFIG_ADDR_MAP
+	init_addr_map();
+#endif
+
+#if defined(CONFIG_BOARD_EARLY_INIT_R)
+	board_early_init_r ();
+#endif
+
+	monitor_flash_len = (ulong)&__init_end - dest_addr;
+
+	WATCHDOG_RESET ();
+
+#ifdef CONFIG_LOGBUFFER
+	logbuff_init_ptrs ();
+#endif
+#ifdef CONFIG_POST
+	post_output_backlog ();
+#endif
+
+	WATCHDOG_RESET();
+
+#if defined(CONFIG_SYS_DELAYED_ICACHE) || defined(CONFIG_MPC83xx)
+	icache_enable ();	/* it's time to enable the instruction cache */
+#endif
+
+#if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500)
+	unlock_ram_in_cache();	/* it's time to unlock D-cache in e500 */
+#endif
+
+#if defined(CONFIG_BAB7xx) || defined(CONFIG_CPC45)
+	/*
+	 * Do PCI configuration on BAB7xx and CPC45 _before_ the flash
+	 * gets initialised, because we need the ISA resp. PCI_to_LOCAL bus
+	 * bridge there.
+	 */
+	pci_init ();
+#endif
+#if defined(CONFIG_BAB7xx)
+	/*
+	 * Initialise the ISA bridge
+	 */
+	initialise_w83c553f ();
+#endif
+
+	asm ("sync ; isync");
+
+	mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);
+
+#if !defined(CONFIG_SYS_NO_FLASH)
+	puts ("FLASH: ");
+
+	if ((flash_size = flash_init ()) > 0) {
+# ifdef CONFIG_SYS_FLASH_CHECKSUM
+		print_size (flash_size, "");
+		/*
+		 * Compute and print flash CRC if flashchecksum is set to 'y'
+		 *
+		 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
+		 */
+		s = getenv ("flashchecksum");
+		if (s && (*s == 'y')) {
+			printf ("  CRC: %08X",
+				crc32 (0, (const unsigned char *) CONFIG_SYS_FLASH_BASE, flash_size)
+			);
+		}
+		putc ('\n');
+# else	/* !CONFIG_SYS_FLASH_CHECKSUM */
+		print_size (flash_size, "\n");
+# endif /* CONFIG_SYS_FLASH_CHECKSUM */
+	} else {
+		puts (failed);
+		hang ();
+	}
+
+	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;	/* update start of FLASH memory    */
+	bd->bi_flashsize = flash_size;	/* size of FLASH memory (final value) */
+
+#if defined(CONFIG_SYS_UPDATE_FLASH_SIZE)
+	/* Make a update of the Memctrl. */
+	update_flash_size (flash_size);
+#endif
+
+
+# if defined(CONFIG_PCU_E) || defined(CONFIG_OXC) || defined(CONFIG_RMU)
+	/* flash mapped at end of memory map */
+	bd->bi_flashoffset = TEXT_BASE + flash_size;
+# elif CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
+	bd->bi_flashoffset = monitor_flash_len;	/* reserved area for startup monitor  */
+# else
+	bd->bi_flashoffset = 0;
+# endif
+#else	/* CONFIG_SYS_NO_FLASH */
+
+	bd->bi_flashsize = 0;
+	bd->bi_flashstart = 0;
+	bd->bi_flashoffset = 0;
+#endif /* !CONFIG_SYS_NO_FLASH */
+
+	WATCHDOG_RESET ();
+
+	/* initialize higher level parts of CPU like time base and timers */
+	cpu_init_r ();
+
+	WATCHDOG_RESET ();
+
+#ifdef CONFIG_SPI
+# if !defined(CONFIG_ENV_IS_IN_EEPROM)
+	spi_init_f ();
+# endif
+	spi_init_r ();
+#endif
+
+#if defined(CONFIG_CMD_NAND)
+	WATCHDOG_RESET ();
+	puts ("NAND:  ");
+	nand_init();		/* go init the NAND */
+#endif
+
+	/* relocate environment function pointers etc. */
+	env_relocate ();
+
+	/*
+	 * Fill in missing fields of bd_info.
+	 * We do this here, where we have "normal" access to the
+	 * environment; we used to do this still running from ROM,
+	 * where had to use getenv_r(), which can be pretty slow when
+	 * the environment is in EEPROM.
+	 */
+
+#if defined(CONFIG_SYS_EXTBDINFO)
+#if defined(CONFIG_405GP) || defined(CONFIG_405EP)
+#if defined(CONFIG_I2CFAST)
+	/*
+	 * set bi_iic_fast for linux taking environment variable
+	 * "i2cfast" into account
+	 */
+	{
+		char *s = getenv ("i2cfast");
+		if (s && ((*s == 'y') || (*s == 'Y'))) {
+			bd->bi_iic_fast[0] = 1;
+			bd->bi_iic_fast[1] = 1;
+		} else {
+			bd->bi_iic_fast[0] = 0;
+			bd->bi_iic_fast[1] = 0;
+		}
+	}
+#else
+	bd->bi_iic_fast[0] = 0;
+	bd->bi_iic_fast[1] = 0;
+#endif	/* CONFIG_I2CFAST */
+#endif	/* CONFIG_405GP, CONFIG_405EP */
+#endif	/* CONFIG_SYS_EXTBDINFO */
+
+#if defined(CONFIG_SC3)
+	sc3_read_eeprom();
+#endif
+
+#if defined (CONFIG_ID_EEPROM) || defined (CONFIG_SYS_I2C_MAC_OFFSET)
+	mac_read_from_eeprom();
+#endif
+
+#ifdef	CONFIG_HERMES
+	if ((gd->board_type >> 16) == 2)
+		bd->bi_ethspeed = gd->board_type & 0xFFFF;
+	else
+		bd->bi_ethspeed = 0xFFFF;
+#endif
+
+#ifdef CONFIG_CMD_NET
+	/* kept around for legacy kernels only ... ignore the next section */
+	eth_getenv_enetaddr("ethaddr", bd->bi_enetaddr);
+#ifdef CONFIG_HAS_ETH1
+	eth_getenv_enetaddr("eth1addr", bd->bi_enet1addr);
+#endif
+#ifdef CONFIG_HAS_ETH2
+	eth_getenv_enetaddr("eth2addr", bd->bi_enet2addr);
+#endif
+#ifdef CONFIG_HAS_ETH3
+	eth_getenv_enetaddr("eth3addr", bd->bi_enet3addr);
+#endif
+#ifdef CONFIG_HAS_ETH4
+	eth_getenv_enetaddr("eth4addr", bd->bi_enet4addr);
+#endif
+#ifdef CONFIG_HAS_ETH5
+	eth_getenv_enetaddr("eth5addr", bd->bi_enet5addr);
+#endif
+#endif /* CONFIG_CMD_NET */
+
+	/* IP Address */
+	bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
+
+	WATCHDOG_RESET ();
+
+#if defined(CONFIG_PCI) && !defined(CONFIG_BAB7xx) && !defined(CONFIG_CPC45)
+	/*
+	 * Do pci configuration
+	 */
+	pci_init ();
+#endif
+
+/** leave this here (after malloc(), environment and PCI are working) **/
+	/* Initialize stdio devices */
+	stdio_init ();
+
+	/* Initialize the jump table for applications */
+	jumptable_init ();
+
+#if defined(CONFIG_API)
+	/* Initialize API */
+	api_init ();
+#endif
+
+	/* Initialize the console (after the relocation and devices init) */
+	console_init_r ();
+
+#if defined(CONFIG_MISC_INIT_R)
+	/* miscellaneous platform dependent initialisations */
+	misc_init_r ();
+#endif
+
+#ifdef	CONFIG_HERMES
+	if (bd->bi_ethspeed != 0xFFFF)
+		hermes_start_lxt980 ((int) bd->bi_ethspeed);
+#endif
+
+#if defined(CONFIG_CMD_KGDB)
+	WATCHDOG_RESET ();
+	puts ("KGDB:  ");
+	kgdb_init ();
+#endif
+
+	debug ("U-Boot relocated to %08lx\n", dest_addr);
+
+	/*
+	 * Enable Interrupts
+	 */
+	interrupt_init ();
+
+	/* Must happen after interrupts are initialized since
+	 * an irq handler gets installed
+	 */
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
+	serial_buffered_init();
+#endif
+
+#if defined(CONFIG_STATUS_LED) && defined(STATUS_LED_BOOT)
+	status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING);
+#endif
+
+	udelay (20);
+
+	set_timer (0);
+
+	/* Initialize from environment */
+	if ((s = getenv ("loadaddr")) != NULL) {
+		load_addr = simple_strtoul (s, NULL, 16);
+	}
+#if defined(CONFIG_CMD_NET)
+	if ((s = getenv ("bootfile")) != NULL) {
+		copy_filename (BootFile, s, sizeof (BootFile));
+	}
+#endif
+
+	WATCHDOG_RESET ();
+
+#if defined(CONFIG_DTT)		/* Digital Thermometers and Thermostats */
+	dtt_init ();
+#endif
+#if defined(CONFIG_CMD_SCSI)
+	WATCHDOG_RESET ();
+	puts ("SCSI:  ");
+	scsi_init ();
+#endif
+
+#ifdef CONFIG_GENERIC_MMC
+	WATCHDOG_RESET ();
+	puts ("MMC:  ");
+	mmc_initialize (bd);
+#endif
+
+#if defined(CONFIG_CMD_DOC)
+	WATCHDOG_RESET ();
+	puts ("DOC:   ");
+	doc_init ();
+#endif
+
+#ifdef CONFIG_BITBANGMII
+	bb_miiphy_init();
+#endif
+#if defined(CONFIG_CMD_NET)
+#if defined(CONFIG_NET_MULTI)
+	WATCHDOG_RESET ();
+	puts ("Net:   ");
+#endif
+	eth_initialize (bd);
+#endif
+
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_RESET_PHY_R)
+	WATCHDOG_RESET ();
+	debug ("Reset Ethernet PHY\n");
+	reset_phy ();
+#endif
+
+#ifdef CONFIG_POST
+	post_run (NULL, POST_RAM | post_bootmode_get(0));
+#endif
+
+#if defined(CONFIG_CMD_PCMCIA) \
+    && !defined(CONFIG_CMD_IDE)
+	WATCHDOG_RESET ();
+	puts ("PCMCIA:");
+	pcmcia_init ();
+#endif
+
+#if defined(CONFIG_CMD_IDE)
+	WATCHDOG_RESET ();
+# ifdef	CONFIG_IDE_8xx_PCCARD
+	puts ("PCMCIA:");
+# else
+	puts ("IDE:   ");
+#endif
+#if defined(CONFIG_START_IDE)
+	if (board_start_ide())
+		ide_init ();
+#else
+	ide_init ();
+#endif
+#endif
+
+#ifdef CONFIG_LAST_STAGE_INIT
+	WATCHDOG_RESET ();
+	/*
+	 * Some parts can be only initialized if all others (like
+	 * Interrupts) are up and running (i.e. the PC-style ISA
+	 * keyboard).
+	 */
+	last_stage_init ();
+#endif
+
+#if defined(CONFIG_CMD_BEDBUG)
+	WATCHDOG_RESET ();
+	bedbug_init ();
+#endif
+
+#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER)
+	/*
+	 * Export available size of memory for Linux,
+	 * taking into account the protected RAM at top of memory
+	 */
+	{
+		ulong pram;
+		uchar memsz[32];
+#ifdef CONFIG_PRAM
+		char *s;
+
+		if ((s = getenv ("pram")) != NULL) {
+			pram = simple_strtoul (s, NULL, 10);
+		} else {
+			pram = CONFIG_PRAM;
+		}
+#else
+		pram=0;
+#endif
+#ifdef CONFIG_LOGBUFFER
+#ifndef CONFIG_ALT_LB_ADDR
+		/* Also take the logbuffer into account (pram is in kB) */
+		pram += (LOGBUFF_LEN+LOGBUFF_OVERHEAD)/1024;
+#endif
+#endif
+		sprintf ((char *)memsz, "%ldk", (bd->bi_memsize / 1024) - pram);
+		setenv ("mem", (char *)memsz);
+	}
+#endif
+
+#ifdef CONFIG_PS2KBD
+	puts ("PS/2:  ");
+	kbd_init();
+#endif
+
+#ifdef CONFIG_MODEM_SUPPORT
+ {
+	 extern int do_mdm_init;
+	 do_mdm_init = gd->do_mdm_init;
+ }
+#endif
+
+	/* Initialization complete - start the monitor */
+
+	/* main_loop() can return to retry autoboot, if so just run it again. */
+	for (;;) {
+		WATCHDOG_RESET ();
+		main_loop ();
+	}
+
+	/* NOTREACHED - no way out of command loop except booting */
+}
+
+void hang (void)
+{
+	puts ("### ERROR ### Please RESET the board ###\n");
+	show_boot_progress(-30);
+	for (;;);
+}
+
+
+#if 0 /* We could use plain global data, but the resulting code is bigger */
+/*
+ * Pointer to initial global data area
+ *
+ * Here we initialize it.
+ */
+#undef	XTRN_DECLARE_GLOBAL_DATA_PTR
+#define XTRN_DECLARE_GLOBAL_DATA_PTR	/* empty = allocate here */
+DECLARE_GLOBAL_DATA_PTR = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+#endif  /* 0 */
+
+/************************************************************************/
diff --git a/arch/powerpc/lib/bootm.c b/arch/powerpc/lib/bootm.c
new file mode 100644
index 0000000..0685a93
--- /dev/null
+++ b/arch/powerpc/lib/bootm.c
@@ -0,0 +1,367 @@
+/*
+ * (C) Copyright 2008 Semihalf
+ *
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <image.h>
+#include <malloc.h>
+#include <u-boot/zlib.h>
+#include <bzlib.h>
+#include <environment.h>
+#include <asm/byteorder.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <fdt.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+
+#endif
+
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+#include <asm/cache.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+extern ulong get_effective_memsize(void);
+static ulong get_sp (void);
+static void set_clocks_in_mhz (bd_t *kbd);
+
+#ifndef CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE
+#define CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE	(768*1024*1024)
+#endif
+
+static void boot_jump_linux(bootm_headers_t *images)
+{
+	void	(*kernel)(bd_t *, ulong r4, ulong r5, ulong r6,
+			  ulong r7, ulong r8, ulong r9);
+#ifdef CONFIG_OF_LIBFDT
+	char *of_flat_tree = images->ft_addr;
+#endif
+
+	kernel = (void (*)(bd_t *, ulong, ulong, ulong,
+			   ulong, ulong, ulong))images->ep;
+	debug ("## Transferring control to Linux (at address %08lx) ...\n",
+		(ulong)kernel);
+
+	show_boot_progress (15);
+
+#if defined(CONFIG_SYS_INIT_RAM_LOCK) && !defined(CONFIG_E500)
+	unlock_ram_in_cache();
+#endif
+
+#if defined(CONFIG_OF_LIBFDT)
+	if (of_flat_tree) {	/* device tree; boot new style */
+		/*
+		 * Linux Kernel Parameters (passing device tree):
+		 *   r3: pointer to the fdt
+		 *   r4: 0
+		 *   r5: 0
+		 *   r6: epapr magic
+		 *   r7: size of IMA in bytes
+		 *   r8: 0
+		 *   r9: 0
+		 */
+#if defined(CONFIG_85xx) || defined(CONFIG_440)
+ #define EPAPR_MAGIC	(0x45504150)
+#else
+ #define EPAPR_MAGIC	(0x65504150)
+#endif
+
+		debug ("   Booting using OF flat tree...\n");
+		WATCHDOG_RESET ();
+		(*kernel) ((bd_t *)of_flat_tree, 0, 0, EPAPR_MAGIC,
+			   CONFIG_SYS_BOOTMAPSZ, 0, 0);
+		/* does not return */
+	} else
+#endif
+	{
+		/*
+		 * Linux Kernel Parameters (passing board info data):
+		 *   r3: ptr to board info data
+		 *   r4: initrd_start or 0 if no initrd
+		 *   r5: initrd_end - unused if r4 is 0
+		 *   r6: Start of command line string
+		 *   r7: End   of command line string
+		 *   r8: 0
+		 *   r9: 0
+		 */
+		ulong cmd_start = images->cmdline_start;
+		ulong cmd_end = images->cmdline_end;
+		ulong initrd_start = images->initrd_start;
+		ulong initrd_end = images->initrd_end;
+		bd_t *kbd = images->kbd;
+
+		debug ("   Booting using board info...\n");
+		WATCHDOG_RESET ();
+		(*kernel) (kbd, initrd_start, initrd_end,
+			   cmd_start, cmd_end, 0, 0);
+		/* does not return */
+	}
+	return ;
+}
+
+void arch_lmb_reserve(struct lmb *lmb)
+{
+	phys_size_t bootm_size;
+	ulong size, sp, bootmap_base;
+
+	bootmap_base = getenv_bootm_low();
+	bootm_size = getenv_bootm_size();
+
+#ifdef DEBUG
+	if (((u64)bootmap_base + bootm_size) >
+	    (CONFIG_SYS_SDRAM_BASE + (u64)gd->ram_size))
+		puts("WARNING: bootm_low + bootm_size exceed total memory\n");
+	if ((bootmap_base + bootm_size) > get_effective_memsize())
+		puts("WARNING: bootm_low + bootm_size exceed eff. memory\n");
+#endif
+
+	size = min(bootm_size, get_effective_memsize());
+	size = min(size, CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE);
+
+	if (size < bootm_size) {
+		ulong base = bootmap_base + size;
+		printf("WARNING: adjusting available memory to %lx\n", size);
+		lmb_reserve(lmb, base, bootm_size - size);
+	}
+
+	/*
+	 * Booting a (Linux) kernel image
+	 *
+	 * Allocate space for command line and board info - the
+	 * address should be as high as possible within the reach of
+	 * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
+	 * memory, which means far enough below the current stack
+	 * pointer.
+	 */
+	sp = get_sp();
+	debug ("## Current stack ends at 0x%08lx\n", sp);
+
+	/* adjust sp by 1K to be safe */
+	sp -= 1024;
+	lmb_reserve(lmb, sp, (CONFIG_SYS_SDRAM_BASE + get_effective_memsize() - sp));
+
+	return ;
+}
+
+static void boot_prep_linux(void)
+{
+#ifdef CONFIG_MP
+	/* if we are MP make sure to flush the dcache() to any changes are made
+	 * visibile to all other cores */
+	flush_dcache();
+#endif
+	return ;
+}
+
+static int boot_cmdline_linux(bootm_headers_t *images)
+{
+	ulong bootmap_base = getenv_bootm_low();
+	ulong of_size = images->ft_len;
+	struct lmb *lmb = &images->lmb;
+	ulong *cmd_start = &images->cmdline_start;
+	ulong *cmd_end = &images->cmdline_end;
+
+	int ret = 0;
+
+	if (!of_size) {
+		/* allocate space and init command line */
+		ret = boot_get_cmdline (lmb, cmd_start, cmd_end, bootmap_base);
+		if (ret) {
+			puts("ERROR with allocation of cmdline\n");
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static int boot_bd_t_linux(bootm_headers_t *images)
+{
+	ulong bootmap_base = getenv_bootm_low();
+	ulong of_size = images->ft_len;
+	struct lmb *lmb = &images->lmb;
+	bd_t **kbd = &images->kbd;
+
+	int ret = 0;
+
+	if (!of_size) {
+		/* allocate space for kernel copy of board info */
+		ret = boot_get_kbd (lmb, kbd, bootmap_base);
+		if (ret) {
+			puts("ERROR with allocation of kernel bd\n");
+			return ret;
+		}
+		set_clocks_in_mhz(*kbd);
+	}
+
+	return ret;
+}
+
+static int boot_body_linux(bootm_headers_t *images)
+{
+	ulong rd_len;
+	struct lmb *lmb = &images->lmb;
+	ulong *initrd_start = &images->initrd_start;
+	ulong *initrd_end = &images->initrd_end;
+#if defined(CONFIG_OF_LIBFDT)
+	ulong bootmap_base = getenv_bootm_low();
+	ulong of_size = images->ft_len;
+	char **of_flat_tree = &images->ft_addr;
+#endif
+
+	int ret;
+
+	/* allocate space and init command line */
+	ret = boot_cmdline_linux(images);
+	if (ret)
+		return ret;
+
+	/* allocate space for kernel copy of board info */
+	ret = boot_bd_t_linux(images);
+	if (ret)
+		return ret;
+
+	rd_len = images->rd_end - images->rd_start;
+	ret = boot_ramdisk_high (lmb, images->rd_start, rd_len, initrd_start, initrd_end);
+	if (ret)
+		return ret;
+
+#if defined(CONFIG_OF_LIBFDT)
+	ret = boot_relocate_fdt(lmb, bootmap_base, of_flat_tree, &of_size);
+	if (ret)
+		return ret;
+
+	/*
+	 * Add the chosen node if it doesn't exist, add the env and bd_t
+	 * if the user wants it (the logic is in the subroutines).
+	 */
+	if (of_size) {
+		if (fdt_chosen(*of_flat_tree, 1) < 0) {
+			puts ("ERROR: ");
+			puts ("/chosen node create failed");
+			puts (" - must RESET the board to recover.\n");
+			return -1;
+		}
+#ifdef CONFIG_OF_BOARD_SETUP
+		/* Call the board-specific fixup routine */
+		ft_board_setup(*of_flat_tree, gd->bd);
+#endif
+
+		/* Delete the old LMB reservation */
+		lmb_free(lmb, (phys_addr_t)(u32)*of_flat_tree,
+				(phys_size_t)fdt_totalsize(*of_flat_tree));
+
+		ret = fdt_resize(*of_flat_tree);
+		if (ret < 0)
+			return ret;
+		of_size = ret;
+
+		if (*initrd_start && *initrd_end)
+			of_size += FDT_RAMDISK_OVERHEAD;
+		/* Create a new LMB reservation */
+		lmb_reserve(lmb, (ulong)*of_flat_tree, of_size);
+
+		/* fixup the initrd now that we know where it should be */
+		if (*initrd_start && *initrd_end)
+			fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1);
+	}
+#endif	/* CONFIG_OF_LIBFDT */
+	return 0;
+}
+
+__attribute__((noinline))
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	int	ret;
+
+	if (flag & BOOTM_STATE_OS_CMDLINE) {
+		boot_cmdline_linux(images);
+		return 0;
+	}
+
+	if (flag & BOOTM_STATE_OS_BD_T) {
+		boot_bd_t_linux(images);
+		return 0;
+	}
+
+	if (flag & BOOTM_STATE_OS_PREP) {
+		boot_prep_linux();
+		return 0;
+	}
+
+	if (flag & BOOTM_STATE_OS_GO) {
+		boot_jump_linux(images);
+		return 0;
+	}
+
+	boot_prep_linux();
+	ret = boot_body_linux(images);
+	if (ret)
+		return ret;
+	boot_jump_linux(images);
+
+	return 0;
+}
+
+static ulong get_sp (void)
+{
+	ulong sp;
+
+	asm( "mr %0,1": "=r"(sp) : );
+	return sp;
+}
+
+static void set_clocks_in_mhz (bd_t *kbd)
+{
+	char	*s;
+
+	if ((s = getenv ("clocks_in_mhz")) != NULL) {
+		/* convert all clock information to MHz */
+		kbd->bi_intfreq /= 1000000L;
+		kbd->bi_busfreq /= 1000000L;
+#if defined(CONFIG_MPC8220)
+		kbd->bi_inpfreq /= 1000000L;
+		kbd->bi_pcifreq /= 1000000L;
+		kbd->bi_pevfreq /= 1000000L;
+		kbd->bi_flbfreq /= 1000000L;
+		kbd->bi_vcofreq /= 1000000L;
+#endif
+#if defined(CONFIG_CPM2)
+		kbd->bi_cpmfreq /= 1000000L;
+		kbd->bi_brgfreq /= 1000000L;
+		kbd->bi_sccfreq /= 1000000L;
+		kbd->bi_vco	/= 1000000L;
+#endif
+#if defined(CONFIG_MPC5xxx)
+		kbd->bi_ipbfreq /= 1000000L;
+		kbd->bi_pcifreq /= 1000000L;
+#endif /* CONFIG_MPC5xxx */
+	}
+}
diff --git a/arch/powerpc/lib/cache.c b/arch/powerpc/lib/cache.c
new file mode 100644
index 0000000..338b08b
--- /dev/null
+++ b/arch/powerpc/lib/cache.c
@@ -0,0 +1,53 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/cache.h>
+#include <watchdog.h>
+
+void flush_cache(ulong start_addr, ulong size)
+{
+#ifndef CONFIG_5xx
+	ulong addr, start, end;
+
+	start = start_addr & ~(CONFIG_SYS_CACHELINE_SIZE - 1);
+	end = start_addr + size - 1;
+
+	for (addr = start; (addr <= end) && (addr >= start);
+			addr += CONFIG_SYS_CACHELINE_SIZE) {
+		asm volatile("dcbst 0,%0" : : "r" (addr) : "memory");
+		WATCHDOG_RESET();
+	}
+	/* wait for all dcbst to complete on bus */
+	asm volatile("sync" : : : "memory");
+
+	for (addr = start; (addr <= end) && (addr >= start);
+			addr += CONFIG_SYS_CACHELINE_SIZE) {
+		asm volatile("icbi 0,%0" : : "r" (addr) : "memory");
+		WATCHDOG_RESET();
+	}
+	asm volatile("sync" : : : "memory");
+	/* flush prefetch queue */
+	asm volatile("isync" : : : "memory");
+#endif
+}
diff --git a/arch/powerpc/lib/extable.c b/arch/powerpc/lib/extable.c
new file mode 100644
index 0000000..7408d5c
--- /dev/null
+++ b/arch/powerpc/lib/extable.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue.  No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path.  This means when everything is well,
+ * we don't even have to jump over them.  Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct exception_table_entry
+{
+	unsigned long insn, fixup;
+};
+
+extern const struct exception_table_entry __start___ex_table[];
+extern const struct exception_table_entry __stop___ex_table[];
+
+static inline unsigned long
+search_one_table(const struct exception_table_entry *first,
+		 const struct exception_table_entry *last,
+		 unsigned long value)
+{
+	long diff;
+	while (first <= last) {
+		diff = first->insn - value;
+		if (diff == 0)
+			return first->fixup;
+		first++;
+	}
+
+	return 0;
+}
+
+int	ex_tab_message = 1;
+
+unsigned long
+search_exception_table(unsigned long addr)
+{
+	unsigned long ret;
+
+	/* There is only the kernel to search.  */
+	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
+	/* if the serial port does not hang in exception, printf can be used */
+#if !defined(CONFIG_SYS_SERIAL_HANG_IN_EXCEPTION)
+	if (ex_tab_message)
+		debug("Bus Fault @ 0x%08lx, fixup 0x%08lx\n", addr, ret);
+#endif
+	if (ret) return ret;
+
+	return 0;
+}
diff --git a/arch/powerpc/lib/interrupts.c b/arch/powerpc/lib/interrupts.c
new file mode 100644
index 0000000..f603170
--- /dev/null
+++ b/arch/powerpc/lib/interrupts.c
@@ -0,0 +1,153 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2003
+ * Gleb Natapov <gnatapov@mrv.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <watchdog.h>
+#ifdef CONFIG_STATUS_LED
+#include <status_led.h>
+#endif
+
+#ifdef CONFIG_SHOW_ACTIVITY
+void board_show_activity (ulong) __attribute__((weak, alias("__board_show_activity")));
+
+void __board_show_activity (ulong dummy)
+{
+	return;
+}
+#endif /* CONFIG_SHOW_ACTIVITY */
+
+#ifndef CONFIG_SYS_WATCHDOG_FREQ
+#define CONFIG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
+#endif
+
+extern int interrupt_init_cpu (unsigned *);
+extern void timer_interrupt_cpu (struct pt_regs *);
+
+static unsigned decrementer_count; /* count value for 1e6/HZ microseconds */
+
+static __inline__ unsigned long get_msr (void)
+{
+	unsigned long msr;
+
+	asm volatile ("mfmsr %0":"=r" (msr):);
+
+	return msr;
+}
+
+static __inline__ void set_msr (unsigned long msr)
+{
+	asm volatile ("mtmsr %0"::"r" (msr));
+}
+
+static __inline__ unsigned long get_dec (void)
+{
+	unsigned long val;
+
+	asm volatile ("mfdec %0":"=r" (val):);
+
+	return val;
+}
+
+
+static __inline__ void set_dec (unsigned long val)
+{
+	if (val)
+		asm volatile ("mtdec %0"::"r" (val));
+}
+
+
+void enable_interrupts (void)
+{
+	set_msr (get_msr () | MSR_EE);
+}
+
+/* returns flag if MSR_EE was set before */
+int disable_interrupts (void)
+{
+	ulong msr = get_msr ();
+
+	set_msr (msr & ~MSR_EE);
+	return ((msr & MSR_EE) != 0);
+}
+
+int interrupt_init (void)
+{
+	int ret;
+
+	/* call cpu specific function from $(CPU)/interrupts.c */
+	ret = interrupt_init_cpu (&decrementer_count);
+
+	if (ret)
+		return ret;
+
+	set_dec (decrementer_count);
+
+	set_msr (get_msr () | MSR_EE);
+
+	return (0);
+}
+
+static volatile ulong timestamp = 0;
+
+void timer_interrupt (struct pt_regs *regs)
+{
+	/* call cpu specific function from $(CPU)/interrupts.c */
+	timer_interrupt_cpu (regs);
+
+	/* Restore Decrementer Count */
+	set_dec (decrementer_count);
+
+	timestamp++;
+
+#if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG)
+	if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
+		WATCHDOG_RESET ();
+#endif    /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
+
+#ifdef CONFIG_STATUS_LED
+	status_led_tick (timestamp);
+#endif /* CONFIG_STATUS_LED */
+
+#ifdef CONFIG_SHOW_ACTIVITY
+	board_show_activity (timestamp);
+#endif /* CONFIG_SHOW_ACTIVITY */
+}
+
+void reset_timer (void)
+{
+	timestamp = 0;
+}
+
+ulong get_timer (ulong base)
+{
+	return (timestamp - base);
+}
+
+void set_timer (ulong t)
+{
+	timestamp = t;
+}
diff --git a/arch/powerpc/lib/kgdb.c b/arch/powerpc/lib/kgdb.c
new file mode 100644
index 0000000..d3eb1f3
--- /dev/null
+++ b/arch/powerpc/lib/kgdb.c
@@ -0,0 +1,321 @@
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/signal.h>
+#include <asm/processor.h>
+
+#define PC_REGNUM 64
+#define SP_REGNUM 1
+
+void breakinst(void);
+
+int
+kgdb_setjmp(long *buf)
+{
+	asm ("mflr 0; stw 0,0(%0);"
+	     "stw 1,4(%0); stw 2,8(%0);"
+	     "mfcr 0; stw 0,12(%0);"
+	     "stmw 13,16(%0)"
+	     : : "r" (buf));
+	/* XXX should save fp regs as well */
+	return 0;
+}
+
+void
+kgdb_longjmp(long *buf, int val)
+{
+	if (val == 0)
+		val = 1;
+	asm ("lmw 13,16(%0);"
+	     "lwz 0,12(%0); mtcrf 0x38,0;"
+	     "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
+	     "mtlr 0; mr 3,%1"
+	     : : "r" (buf), "r" (val));
+}
+
+static inline unsigned long
+get_msr(void)
+{
+	unsigned long msr;
+	asm volatile("mfmsr %0" : "=r" (msr):);
+	return msr;
+}
+
+static inline void
+set_msr(unsigned long msr)
+{
+	asm volatile("mtmsr %0" : : "r" (msr));
+}
+
+/* Convert the SPARC hardware trap type code to a unix signal number. */
+/*
+ * This table contains the mapping between PowerPC hardware trap types, and
+ * signals, which are primarily what GDB understands.
+ */
+static struct hard_trap_info
+{
+	unsigned int tt;		/* Trap type code for powerpc */
+	unsigned char signo;		/* Signal that we map this trap into */
+} hard_trap_info[] = {
+	{ 0x200, SIGSEGV },			/* machine check */
+	{ 0x300, SIGSEGV },			/* address error (store) */
+	{ 0x400, SIGBUS },			/* instruction bus error */
+	{ 0x500, SIGINT },			/* interrupt */
+	{ 0x600, SIGBUS },			/* alingment */
+	{ 0x700, SIGTRAP },			/* breakpoint trap */
+	{ 0x800, SIGFPE },			/* fpu unavail */
+	{ 0x900, SIGALRM },			/* decrementer */
+	{ 0xa00, SIGILL },			/* reserved */
+	{ 0xb00, SIGILL },			/* reserved */
+	{ 0xc00, SIGCHLD },			/* syscall */
+	{ 0xd00, SIGTRAP },			/* single-step/watch */
+	{ 0xe00, SIGFPE },			/* fp assist */
+	{ 0, 0}				/* Must be last */
+};
+
+static int
+computeSignal(unsigned int tt)
+{
+	struct hard_trap_info *ht;
+
+	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+		if (ht->tt == tt)
+			return ht->signo;
+
+	return SIGHUP;         /* default for things we don't know about */
+}
+
+void
+kgdb_enter(struct pt_regs *regs, kgdb_data *kdp)
+{
+	unsigned long msr;
+
+	kdp->private[0] = msr = get_msr();
+	set_msr(msr & ~MSR_EE);	/* disable interrupts */
+
+	if (regs->nip == (unsigned long)breakinst) {
+		/* Skip over breakpoint trap insn */
+		regs->nip += 4;
+	}
+	regs->msr &= ~MSR_SE;
+
+	/* reply to host that an exception has occurred */
+	kdp->sigval = computeSignal(regs->trap);
+
+	kdp->nregs = 2;
+
+	kdp->regs[0].num = PC_REGNUM;
+	kdp->regs[0].val = regs->nip;
+
+	kdp->regs[1].num = SP_REGNUM;
+	kdp->regs[1].val = regs->gpr[SP_REGNUM];
+}
+
+void
+kgdb_exit(struct pt_regs *regs, kgdb_data *kdp)
+{
+	unsigned long msr = kdp->private[0];
+
+	if (kdp->extype & KGDBEXIT_WITHADDR)
+		regs->nip = kdp->exaddr;
+
+	switch (kdp->extype & KGDBEXIT_TYPEMASK) {
+
+	case KGDBEXIT_KILL:
+	case KGDBEXIT_CONTINUE:
+		set_msr(msr);
+		break;
+
+	case KGDBEXIT_SINGLE:
+		regs->msr |= MSR_SE;
+#if 0
+		set_msr(msr | MSR_SE);
+#endif
+		break;
+	}
+}
+
+int
+kgdb_trap(struct pt_regs *regs)
+{
+	return (regs->trap);
+}
+
+/* return the value of the CPU registers.
+ * some of them are non-PowerPC names :(
+ * they are stored in gdb like:
+ * struct {
+ *     u32 gpr[32];
+ *     f64 fpr[32];
+ *     u32 pc, ps, cnd, lr; (ps=msr)
+ *     u32 cnt, xer, mq;
+ * }
+ */
+
+#define SPACE_REQUIRED	((32*4)+(32*8)+(6*4))
+
+#ifdef CONFIG_8260
+/* store floating double indexed */
+#define STFDI(n,p)	__asm__ __volatile__ ("stfd " #n ",%0" : "=o"(p[2*n]))
+/* store floating double multiple */
+#define STFDM(p)	{ STFDI( 0,p); STFDI( 1,p); STFDI( 2,p); STFDI( 3,p); \
+			  STFDI( 4,p); STFDI( 5,p); STFDI( 6,p); STFDI( 7,p); \
+			  STFDI( 8,p); STFDI( 9,p); STFDI(10,p); STFDI(11,p); \
+			  STFDI(12,p); STFDI(13,p); STFDI(14,p); STFDI(15,p); \
+			  STFDI(16,p); STFDI(17,p); STFDI(18,p); STFDI(19,p); \
+			  STFDI(20,p); STFDI(21,p); STFDI(22,p); STFDI(23,p); \
+			  STFDI(24,p); STFDI(25,p); STFDI(26,p); STFDI(27,p); \
+			  STFDI(28,p); STFDI(29,p); STFDI(30,p); STFDI(31,p); }
+#endif
+
+int
+kgdb_getregs(struct pt_regs *regs, char *buf, int max)
+{
+	int i;
+	unsigned long *ptr = (unsigned long *)buf;
+
+	if (max < SPACE_REQUIRED)
+		kgdb_error(KGDBERR_NOSPACE);
+
+	if ((unsigned long)ptr & 3)
+		kgdb_error(KGDBERR_ALIGNFAULT);
+
+	/* General Purpose Regs */
+	for (i = 0; i < 32; i++)
+		*ptr++ = regs->gpr[i];
+
+	/* Floating Point Regs */
+#ifdef CONFIG_8260
+	STFDM(ptr);
+	ptr += 32*2;
+#else
+	for (i = 0; i < 32; i++) {
+		*ptr++ = 0;
+		*ptr++ = 0;
+	}
+#endif
+
+	/* pc, msr, cr, lr, ctr, xer, (mq is unused) */
+	*ptr++ = regs->nip;
+	*ptr++ = regs->msr;
+	*ptr++ = regs->ccr;
+	*ptr++ = regs->link;
+	*ptr++ = regs->ctr;
+	*ptr++ = regs->xer;
+
+	return (SPACE_REQUIRED);
+}
+
+/* set the value of the CPU registers */
+
+#ifdef CONFIG_8260
+/* load floating double */
+#define LFD(n,v)	__asm__ __volatile__ ("lfd " #n ",%0" :: "o"(v))
+/* load floating double indexed */
+#define LFDI(n,p)	__asm__ __volatile__ ("lfd " #n ",%0" :: "o"((p)[2*n]))
+/* load floating double multiple */
+#define LFDM(p)		{ LFDI( 0,p); LFDI( 1,p); LFDI( 2,p); LFDI( 3,p); \
+			  LFDI( 4,p); LFDI( 5,p); LFDI( 6,p); LFDI( 7,p); \
+			  LFDI( 8,p); LFDI( 9,p); LFDI(10,p); LFDI(11,p); \
+			  LFDI(12,p); LFDI(13,p); LFDI(14,p); LFDI(15,p); \
+			  LFDI(16,p); LFDI(17,p); LFDI(18,p); LFDI(19,p); \
+			  LFDI(20,p); LFDI(21,p); LFDI(22,p); LFDI(23,p); \
+			  LFDI(24,p); LFDI(25,p); LFDI(26,p); LFDI(27,p); \
+			  LFDI(28,p); LFDI(29,p); LFDI(30,p); LFDI(31,p); }
+#endif
+
+void
+kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length)
+{
+	unsigned long *ptr = (unsigned long *)buf;
+
+	if (regno < 0 || regno >= 70)
+		kgdb_error(KGDBERR_BADPARAMS);
+	else if (regno >= 32 && regno < 64) {
+		if (length < 8)
+			kgdb_error(KGDBERR_NOSPACE);
+	}
+	else {
+		if (length < 4)
+			kgdb_error(KGDBERR_NOSPACE);
+	}
+
+	if ((unsigned long)ptr & 3)
+		kgdb_error(KGDBERR_ALIGNFAULT);
+
+	if (regno >= 0 && regno < 32)
+		regs->gpr[regno] = *ptr;
+	else switch (regno) {
+
+#ifdef CONFIG_8260
+#define caseF(n) \
+	case (n) + 32:	LFD(n, *ptr);		break;
+
+caseF( 0) caseF( 1) caseF( 2) caseF( 3) caseF( 4) caseF( 5) caseF( 6) caseF( 7)
+caseF( 8) caseF( 9) caseF(10) caseF(11) caseF(12) caseF(13) caseF(14) caseF(15)
+caseF(16) caseF(17) caseF(18) caseF(19) caseF(20) caseF(21) caseF(22) caseF(23)
+caseF(24) caseF(25) caseF(26) caseF(27) caseF(28) caseF(29) caseF(30) caseF(31)
+
+#undef caseF
+#endif
+
+	case 64:	regs->nip = *ptr;	break;
+	case 65:	regs->msr = *ptr;	break;
+	case 66:	regs->ccr = *ptr;	break;
+	case 67:	regs->link = *ptr;	break;
+	case 68:	regs->ctr = *ptr;	break;
+	case 69:	regs->ctr = *ptr;	break;
+
+	default:
+		kgdb_error(KGDBERR_BADPARAMS);
+	}
+}
+
+void
+kgdb_putregs(struct pt_regs *regs, char *buf, int length)
+{
+	int i;
+	unsigned long *ptr = (unsigned long *)buf;
+
+	if (length < SPACE_REQUIRED)
+		kgdb_error(KGDBERR_NOSPACE);
+
+	if ((unsigned long)ptr & 3)
+		kgdb_error(KGDBERR_ALIGNFAULT);
+
+	/*
+	 * If the stack pointer has moved, you should pray.
+	 * (cause only god can help you).
+	 */
+
+	/* General Purpose Regs */
+	for (i = 0; i < 32; i++)
+		regs->gpr[i] = *ptr++;
+
+	/* Floating Point Regs */
+#ifdef CONFIG_8260
+	LFDM(ptr);
+#endif
+	ptr += 32*2;
+
+	/* pc, msr, cr, lr, ctr, xer, (mq is unused) */
+	regs->nip = *ptr++;
+	regs->msr = *ptr++;
+	regs->ccr = *ptr++;
+	regs->link = *ptr++;
+	regs->ctr = *ptr++;
+	regs->xer = *ptr++;
+}
+
+/* This function will generate a breakpoint exception.  It is used at the
+   beginning of a program to sync up with a debugger and can be used
+   otherwise as a quick means to stop program execution and "break" into
+   the debugger. */
+
+void
+kgdb_breakpoint(int argc, char *argv[])
+{
+	asm("	.globl breakinst\n\
+	     breakinst: .long 0x7d821008\n\
+	    ");
+}
diff --git a/arch/powerpc/lib/ppccache.S b/arch/powerpc/lib/ppccache.S
new file mode 100644
index 0000000..278a804
--- /dev/null
+++ b/arch/powerpc/lib/ppccache.S
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 1998  Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000, 2001,2002 Wolfgang Denk <wd@denx.de>
+ * Copyright Freescale Semiconductor, Inc. 2004, 2006.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <ppc_asm.tmpl>
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 ppcDcbf */
+/* Description:	 Data Cache block flush */
+/* Input:	 r3 = effective address */
+/* Output:	 none. */
+/*------------------------------------------------------------------------------- */
+	.globl	ppcDcbf
+ppcDcbf:
+	dcbf	r0,r3
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 ppcDcbi */
+/* Description:	 Data Cache block Invalidate */
+/* Input:	 r3 = effective address */
+/* Output:	 none. */
+/*------------------------------------------------------------------------------- */
+	.globl	ppcDcbi
+ppcDcbi:
+	dcbi	r0,r3
+	blr
+
+/*--------------------------------------------------------------------------
+ * Function:	 ppcDcbz
+ * Description:	 Data Cache block zero.
+ * Input:	 r3 = effective address
+ * Output:	 none.
+ *-------------------------------------------------------------------------- */
+
+	.globl	ppcDcbz
+ppcDcbz:
+	dcbz	r0,r3
+	blr
+
+/*------------------------------------------------------------------------------- */
+/* Function:	 ppcSync */
+/* Description:	 Processor Synchronize */
+/* Input:	 none. */
+/* Output:	 none. */
+/*------------------------------------------------------------------------------- */
+	.globl	ppcSync
+ppcSync:
+	sync
+	blr
diff --git a/arch/powerpc/lib/ppcstring.S b/arch/powerpc/lib/ppcstring.S
new file mode 100644
index 0000000..97023a0
--- /dev/null
+++ b/arch/powerpc/lib/ppcstring.S
@@ -0,0 +1,216 @@
+/*
+ * String handling functions for PowerPC.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * 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 <ppc_asm.tmpl>
+#include <asm/errno.h>
+
+	.globl	strcpy
+strcpy:
+	addi	r5,r3,-1
+	addi	r4,r4,-1
+1:	lbzu	r0,1(r4)
+	cmpwi	0,r0,0
+	stbu	r0,1(r5)
+	bne	1b
+	blr
+
+	.globl	strncpy
+strncpy:
+	cmpwi	0,r5,0
+	beqlr
+	mtctr	r5
+	addi	r6,r3,-1
+	addi	r4,r4,-1
+1:	lbzu	r0,1(r4)
+	cmpwi	0,r0,0
+	stbu	r0,1(r6)
+	bdnzf	2,1b		/* dec ctr, branch if ctr != 0 && !cr0.eq */
+	blr
+
+	.globl	strcat
+strcat:
+	addi	r5,r3,-1
+	addi	r4,r4,-1
+1:	lbzu	r0,1(r5)
+	cmpwi	0,r0,0
+	bne	1b
+	addi	r5,r5,-1
+1:	lbzu	r0,1(r4)
+	cmpwi	0,r0,0
+	stbu	r0,1(r5)
+	bne	1b
+	blr
+
+	.globl	strcmp
+strcmp:
+	addi	r5,r3,-1
+	addi	r4,r4,-1
+1:	lbzu	r3,1(r5)
+	cmpwi	1,r3,0
+	lbzu	r0,1(r4)
+	subf.	r3,r0,r3
+	beqlr	1
+	beq	1b
+	blr
+
+	.globl	strlen
+strlen:
+	addi	r4,r3,-1
+1:	lbzu	r0,1(r4)
+	cmpwi	0,r0,0
+	bne	1b
+	subf	r3,r3,r4
+	blr
+
+	.globl	memset
+memset:
+	rlwimi	r4,r4,8,16,23
+	rlwimi	r4,r4,16,0,15
+	addi	r6,r3,-4
+	cmplwi	0,r5,4
+	blt	7f
+	stwu	r4,4(r6)
+	beqlr
+	andi.	r0,r6,3
+	add	r5,r0,r5
+	subf	r6,r0,r6
+	rlwinm	r0,r5,32-2,2,31
+	mtctr	r0
+	bdz	6f
+1:	stwu	r4,4(r6)
+	bdnz	1b
+6:	andi.	r5,r5,3
+7:	cmpwi	0,r5,0
+	beqlr
+	mtctr	r5
+	addi	r6,r6,3
+8:	stbu	r4,1(r6)
+	bdnz	8b
+	blr
+
+	.globl	bcopy
+bcopy:
+	mr	r6,r3
+	mr	r3,r4
+	mr	r4,r6
+	b	memcpy
+
+	.globl	memmove
+memmove:
+	cmplw	0,r3,r4
+	bgt	backwards_memcpy
+	/* fall through */
+
+	.globl	memcpy
+memcpy:
+	rlwinm.	r7,r5,32-3,3,31		/* r0 = r5 >> 3 */
+	addi	r6,r3,-4
+	addi	r4,r4,-4
+	beq	2f			/* if less than 8 bytes to do */
+	andi.	r0,r6,3			/* get dest word aligned */
+	mtctr	r7
+	bne	5f
+1:	lwz	r7,4(r4)
+	lwzu	r8,8(r4)
+	stw	r7,4(r6)
+	stwu	r8,8(r6)
+	bdnz	1b
+	andi.	r5,r5,7
+2:	cmplwi	0,r5,4
+	blt	3f
+	lwzu	r0,4(r4)
+	addi	r5,r5,-4
+	stwu	r0,4(r6)
+3:	cmpwi	0,r5,0
+	beqlr
+	mtctr	r5
+	addi	r4,r4,3
+	addi	r6,r6,3
+4:	lbzu	r0,1(r4)
+	stbu	r0,1(r6)
+	bdnz	4b
+	blr
+5:	subfic	r0,r0,4
+	mtctr	r0
+6:	lbz	r7,4(r4)
+	addi	r4,r4,1
+	stb	r7,4(r6)
+	addi	r6,r6,1
+	bdnz	6b
+	subf	r5,r0,r5
+	rlwinm.	r7,r5,32-3,3,31
+	beq	2b
+	mtctr	r7
+	b	1b
+
+	.globl	backwards_memcpy
+backwards_memcpy:
+	rlwinm.	r7,r5,32-3,3,31		/* r0 = r5 >> 3 */
+	add	r6,r3,r5
+	add	r4,r4,r5
+	beq	2f
+	andi.	r0,r6,3
+	mtctr	r7
+	bne	5f
+1:	lwz	r7,-4(r4)
+	lwzu	r8,-8(r4)
+	stw	r7,-4(r6)
+	stwu	r8,-8(r6)
+	bdnz	1b
+	andi.	r5,r5,7
+2:	cmplwi	0,r5,4
+	blt	3f
+	lwzu	r0,-4(r4)
+	subi	r5,r5,4
+	stwu	r0,-4(r6)
+3:	cmpwi	0,r5,0
+	beqlr
+	mtctr	r5
+4:	lbzu	r0,-1(r4)
+	stbu	r0,-1(r6)
+	bdnz	4b
+	blr
+5:	mtctr	r0
+6:	lbzu	r7,-1(r4)
+	stbu	r7,-1(r6)
+	bdnz	6b
+	subf	r5,r0,r5
+	rlwinm.	r7,r5,32-3,3,31
+	beq	2b
+	mtctr	r7
+	b	1b
+
+	.globl	memcmp
+memcmp:
+	cmpwi	0,r5,0
+	ble-	2f
+	mtctr	r5
+	addi	r6,r3,-1
+	addi	r4,r4,-1
+1:	lbzu	r3,1(r6)
+	lbzu	r0,1(r4)
+	subf.	r3,r0,r3
+	bdnzt	2,1b
+	blr
+2:	li	r3,0
+	blr
+
+	.global	memchr
+memchr:
+	cmpwi	0,r5,0
+	ble-	2f
+	mtctr	r5
+	addi	r3,r3,-1
+1:	lbzu	r0,1(r3)
+	cmpw	0,r0,r4
+	bdnzf	2,1b
+	beqlr
+2:	li	r3,0
+	blr
diff --git a/arch/powerpc/lib/reloc.S b/arch/powerpc/lib/reloc.S
new file mode 100644
index 0000000..50f9a83
--- /dev/null
+++ b/arch/powerpc/lib/reloc.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppc_asm.tmpl>
+
+	.file	"reloc.S"
+
+	.text
+#ifndef CONFIG_NAND_SPL
+	/*
+	 * Function: relocate entries for one exception vector
+	 */
+	.globl trap_reloc
+	.type	trap_reloc, @function
+trap_reloc:
+	lwz	r0, 0(r7)		/* hdlr ...		*/
+	add	r0, r0, r3		/*  ... += dest_addr	*/
+	stw	r0, 0(r7)
+
+	lwz	r0, 4(r7)		/* int_return ...	*/
+	add	r0, r0, r3		/*  ... += dest_addr	*/
+	stw	r0, 4(r7)
+
+	lwz	r0, 8(r7)		/* transfer_to_handler ...*/
+	add	r0, r0, r3		/*  ... += dest_addr	*/
+	stw	r0, 8(r7)
+
+	blr
+	.size	trap_reloc, .-trap_reloc
+#endif
diff --git a/arch/powerpc/lib/ticks.S b/arch/powerpc/lib/ticks.S
new file mode 100644
index 0000000..b8d25b7
--- /dev/null
+++ b/arch/powerpc/lib/ticks.S
@@ -0,0 +1,65 @@
+/*
+ * (C) Copyright 2000, 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
+ *  base on code by
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <config.h>
+#include <watchdog.h>
+
+/*
+ * unsigned long long get_ticks(void);
+ *
+ * read timebase as "long long"
+ */
+	.globl	get_ticks
+get_ticks:
+1:	mftbu	r3
+	mftb	r4
+	mftbu	r5
+	cmp	0,r3,r5
+	bne	1b
+	blr
+
+/*
+ * Delay for a number of ticks
+ */
+	.globl	wait_ticks
+wait_ticks:
+	mflr	r8		/* save link register */
+	mr	r7, r3		/* save tick count */
+	bl	get_ticks	/* Get start time */
+
+	/* Calculate end time */
+	addc    r7, r4, r7	/* Compute end time lower */
+	addze	r6, r3		/*     and end time upper */
+
+	WATCHDOG_RESET		/* Trigger watchdog, if needed */
+1:	bl	get_ticks	/* Get current time */
+	subfc	r4, r4, r7	/* Subtract current time from end time */
+	subfe.	r3, r3, r6
+	bge	1b		/* Loop until time expired */
+
+	mtlr	r8		/* restore link register */
+	blr
diff --git a/arch/powerpc/lib/time.c b/arch/powerpc/lib/time.c
new file mode 100644
index 0000000..2909961
--- /dev/null
+++ b/arch/powerpc/lib/time.c
@@ -0,0 +1,97 @@
+/*
+ * (C) Copyright 2000, 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * This function is intended for SHORT delays only.
+ * It will overflow at around 10 seconds @ 400MHz,
+ * or 20 seconds @ 200MHz.
+ */
+unsigned long usec2ticks(unsigned long usec)
+{
+	ulong ticks;
+
+	if (usec < 1000) {
+		ticks = ((usec * (get_tbclk()/1000)) + 500) / 1000;
+	} else {
+		ticks = ((usec / 10) * (get_tbclk() / 100000));
+	}
+
+	return (ticks);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * We implement the delay by converting the delay (the number of
+ * microseconds to wait) into a number of time base ticks; then we
+ * watch the time base until it has incremented by that amount.
+ */
+void __udelay(unsigned long usec)
+{
+	ulong ticks = usec2ticks (usec);
+	wait_ticks (ticks);
+}
+
+/* ------------------------------------------------------------------------- */
+#ifndef CONFIG_NAND_SPL
+unsigned long ticks2usec(unsigned long ticks)
+{
+	ulong tbclk = get_tbclk();
+
+	/* usec = ticks * 1000000 / tbclk
+	 * Multiplication would overflow at ~4.2e3 ticks,
+	 * so we break it up into
+	 * usec = ( ( ticks * 1000) / tbclk ) * 1000;
+	 */
+	ticks *= 1000L;
+	ticks /= tbclk;
+	ticks *= 1000L;
+
+	return ((ulong)ticks);
+}
+#endif
+/* ------------------------------------------------------------------------- */
+
+int init_timebase (void)
+{
+#if defined(CONFIG_5xx) || defined(CONFIG_8xx)
+	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+
+	/* unlock */
+	immap->im_sitk.sitk_tbk = KAPWR_KEY;
+#endif
+
+	/* reset */
+	asm ("li 3,0 ; mttbu 3 ; mttbl 3 ;");
+
+#if defined(CONFIG_5xx) || defined(CONFIG_8xx)
+	/* enable */
+	immap->im_sit.sit_tbscr |= TBSCR_TBE;
+#endif
+	return (0);
+}
+/* ------------------------------------------------------------------------- */