Move lib_$ARCH directories to arch/$ARCH/lib

Also move lib_$ARCH/config.mk to arch/$ARCH/config.mk

This change is intended to clean up the top-level directory structure
and more closely mimic Linux's directory organization.

Signed-off-by: Peter Tyser <ptyser@xes-inc.com>
diff --git a/arch/arm/config.mk b/arch/arm/config.mk
new file mode 100644
index 0000000..e10dafc
--- /dev/null
+++ b/arch/arm/config.mk
@@ -0,0 +1,66 @@
+#
+# (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 ?= arm-linux-
+
+ifeq ($(BOARD),omap2420h4)
+STANDALONE_LOAD_ADDR = 0x80300000
+else
+ifeq ($(SOC),omap3)
+STANDALONE_LOAD_ADDR = 0x80300000
+else
+STANDALONE_LOAD_ADDR = 0xc100000
+endif
+endif
+
+PLATFORM_CPPFLAGS += -DCONFIG_ARM -D__ARM__
+
+# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
+PLATFORM_CPPFLAGS += $(call cc-option,-marm,)
+
+# Try if EABI is supported, else fall back to old API,
+# i. e. for example:
+# - with ELDK 4.2 (EABI supported), use:
+#	-mabi=aapcs-linux -mno-thumb-interwork
+# - with ELDK 4.1 (gcc 4.x, no EABI), use:
+#	-mabi=apcs-gnu -mno-thumb-interwork
+# - with ELDK 3.1 (gcc 3.x), use:
+#	-mapcs-32 -mno-thumb-interwork
+PLATFORM_CPPFLAGS += $(call cc-option,\
+				-mabi=aapcs-linux -mno-thumb-interwork,\
+				$(call cc-option,\
+					-mapcs-32,\
+					$(call cc-option,\
+						-mabi=apcs-gnu,\
+					)\
+				) $(call cc-option,-mno-thumb-interwork,)\
+			)
+
+# For EABI, make sure to provide raise()
+ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS)))
+# This file is parsed several times; make sure to add only once.
+ifeq (,$(findstring arch/arm/lib/eabi_compat.o,$(PLATFORM_LIBS)))
+PLATFORM_LIBS += $(OBJTREE)/arch/arm/lib/eabi_compat.o
+endif
+endif
+LDSCRIPT := $(SRCTREE)/$(CPUDIR)/u-boot.lds
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
new file mode 100644
index 0000000..0293348
--- /dev/null
+++ b/arch/arm/lib/Makefile
@@ -0,0 +1,82 @@
+#
+# (C) Copyright 2002-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
+LIBGCC	= $(obj)libgcc.a
+
+GLSOBJS	+= _ashldi3.o
+GLSOBJS	+= _ashrdi3.o
+GLSOBJS	+= _divsi3.o
+GLSOBJS	+= _lshrdi3.o
+GLSOBJS	+= _modsi3.o
+GLSOBJS	+= _udivsi3.o
+GLSOBJS	+= _umodsi3.o
+
+GLCOBJS	+= div0.o
+
+COBJS-y	+= board.o
+COBJS-y	+= bootm.o
+COBJS-y	+= cache.o
+ifndef CONFIG_SYS_NO_CP15_CACHE
+COBJS-y	+= cache-cp15.o
+endif
+COBJS-y	+= interrupts.o
+COBJS-y	+= reset.o
+
+SRCS	:= $(GLSOBJS:.o=.S) $(GLCOBJS:.o=.c) \
+	   $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+LGOBJS	:= $(addprefix $(obj),$(GLSOBJS)) \
+	   $(addprefix $(obj),$(GLCOBJS))
+
+# Always build libarm.a
+TARGETS	:= $(LIB)
+
+# Build private libgcc only when asked for
+ifdef USE_PRIVATE_LIBGCC
+TARGETS	+= $(LIBGCC)
+endif
+
+# For EABI conformant tool chains, provide eabi_compat()
+ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS)))
+TARGETS	+= $(obj)eabi_compat.o
+endif
+
+all:	$(TARGETS)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+$(LIBGCC): $(obj).depend $(LGOBJS)
+	$(AR) $(ARFLAGS) $@ $(LGOBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/lib/_ashldi3.S b/arch/arm/lib/_ashldi3.S
new file mode 100644
index 0000000..834ddc2
--- /dev/null
+++ b/arch/arm/lib/_ashldi3.S
@@ -0,0 +1,48 @@
+/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
+   Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+This file 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; see the file COPYING.  If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+
+#ifdef __ARMEB__
+#define al r1
+#define ah r0
+#else
+#define al r0
+#define ah r1
+#endif
+
+.globl __ashldi3
+.globl	__aeabi_llsl
+__ashldi3:
+__aeabi_llsl:
+
+	subs	r3, r2, #32
+	rsb	ip, r2, #32
+	movmi	ah, ah, lsl r2
+	movpl	ah, al, lsl r3
+	orrmi	ah, ah, al, lsr ip
+	mov	al, al, lsl r2
+	mov	pc, lr
diff --git a/arch/arm/lib/_ashrdi3.S b/arch/arm/lib/_ashrdi3.S
new file mode 100644
index 0000000..671ac87
--- /dev/null
+++ b/arch/arm/lib/_ashrdi3.S
@@ -0,0 +1,48 @@
+/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
+   Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+This file 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; see the file COPYING.  If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+
+#ifdef __ARMEB__
+#define al r1
+#define ah r0
+#else
+#define al r0
+#define ah r1
+#endif
+
+.globl __ashrdi3
+.globl __aeabi_lasr
+__ashrdi3:
+__aeabi_lasr:
+
+	subs	r3, r2, #32
+	rsb	ip, r2, #32
+	movmi	al, al, lsr r2
+	movpl	al, ah, asr r3
+	orrmi	al, al, ah, lsl ip
+	mov	ah, ah, asr r2
+	mov	pc, lr
diff --git a/arch/arm/lib/_divsi3.S b/arch/arm/lib/_divsi3.S
new file mode 100644
index 0000000..cfbadb2
--- /dev/null
+++ b/arch/arm/lib/_divsi3.S
@@ -0,0 +1,142 @@
+
+.macro ARM_DIV_BODY dividend, divisor, result, curbit
+
+#if __LINUX_ARM_ARCH__ >= 5
+
+	clz	\curbit, \divisor
+	clz	\result, \dividend
+	sub	\result, \curbit, \result
+	mov	\curbit, #1
+	mov	\divisor, \divisor, lsl \result
+	mov	\curbit, \curbit, lsl \result
+	mov	\result, #0
+
+#else
+
+	@ Initially shift the divisor left 3 bits if possible,
+	@ set curbit accordingly.  This allows for curbit to be located
+	@ at the left end of each 4 bit nibbles in the division loop
+	@ to save one loop in most cases.
+	tst	\divisor, #0xe0000000
+	moveq	\divisor, \divisor, lsl #3
+	moveq	\curbit, #8
+	movne	\curbit, #1
+
+	@ Unless the divisor is very big, shift it up in multiples of
+	@ four bits, since this is the amount of unwinding in the main
+	@ division loop.  Continue shifting until the divisor is
+	@ larger than the dividend.
+1:	cmp	\divisor, #0x10000000
+	cmplo	\divisor, \dividend
+	movlo	\divisor, \divisor, lsl #4
+	movlo	\curbit, \curbit, lsl #4
+	blo	1b
+
+	@ For very big divisors, we must shift it a bit at a time, or
+	@ we will be in danger of overflowing.
+1:	cmp	\divisor, #0x80000000
+	cmplo	\divisor, \dividend
+	movlo	\divisor, \divisor, lsl #1
+	movlo	\curbit, \curbit, lsl #1
+	blo	1b
+
+	mov	\result, #0
+
+#endif
+
+	@ Division loop
+1:	cmp	\dividend, \divisor
+	subhs	\dividend, \dividend, \divisor
+	orrhs	\result,   \result,   \curbit
+	cmp	\dividend, \divisor,  lsr #1
+	subhs	\dividend, \dividend, \divisor, lsr #1
+	orrhs	\result,   \result,   \curbit,  lsr #1
+	cmp	\dividend, \divisor,  lsr #2
+	subhs	\dividend, \dividend, \divisor, lsr #2
+	orrhs	\result,   \result,   \curbit,  lsr #2
+	cmp	\dividend, \divisor,  lsr #3
+	subhs	\dividend, \dividend, \divisor, lsr #3
+	orrhs	\result,   \result,   \curbit,  lsr #3
+	cmp	\dividend, #0			@ Early termination?
+	movnes	\curbit,   \curbit,  lsr #4	@ No, any more bits to do?
+	movne	\divisor,  \divisor, lsr #4
+	bne	1b
+
+.endm
+
+.macro ARM_DIV2_ORDER divisor, order
+
+#if __LINUX_ARM_ARCH__ >= 5
+
+	clz	\order, \divisor
+	rsb	\order, \order, #31
+
+#else
+
+	cmp	\divisor, #(1 << 16)
+	movhs	\divisor, \divisor, lsr #16
+	movhs	\order, #16
+	movlo	\order, #0
+
+	cmp	\divisor, #(1 << 8)
+	movhs	\divisor, \divisor, lsr #8
+	addhs	\order, \order, #8
+
+	cmp	\divisor, #(1 << 4)
+	movhs	\divisor, \divisor, lsr #4
+	addhs	\order, \order, #4
+
+	cmp	\divisor, #(1 << 2)
+	addhi	\order, \order, #3
+	addls	\order, \order, \divisor, lsr #1
+
+#endif
+
+.endm
+
+	.align	5
+.globl __divsi3
+.globl __aeabi_idiv
+__divsi3:
+__aeabi_idiv:
+	cmp	r1, #0
+	eor	ip, r0, r1			@ save the sign of the result.
+	beq	Ldiv0
+	rsbmi	r1, r1, #0			@ loops below use unsigned.
+	subs	r2, r1, #1			@ division by 1 or -1 ?
+	beq	10f
+	movs	r3, r0
+	rsbmi	r3, r0, #0			@ positive dividend value
+	cmp	r3, r1
+	bls	11f
+	tst	r1, r2				@ divisor is power of 2 ?
+	beq	12f
+
+	ARM_DIV_BODY r3, r1, r0, r2
+
+	cmp	ip, #0
+	rsbmi	r0, r0, #0
+	mov	pc, lr
+
+10:	teq	ip, r0				@ same sign ?
+	rsbmi	r0, r0, #0
+	mov	pc, lr
+
+11:	movlo	r0, #0
+	moveq	r0, ip, asr #31
+	orreq	r0, r0, #1
+	mov	pc, lr
+
+12:	ARM_DIV2_ORDER r1, r2
+
+	cmp	ip, #0
+	mov	r0, r3, lsr r2
+	rsbmi	r0, r0, #0
+	mov	pc, lr
+
+Ldiv0:
+
+	str	lr, [sp, #-4]!
+	bl	__div0
+	mov	r0, #0			@ About as wrong as it could be.
+	ldr	pc, [sp], #4
diff --git a/arch/arm/lib/_lshrdi3.S b/arch/arm/lib/_lshrdi3.S
new file mode 100644
index 0000000..e7fa799
--- /dev/null
+++ b/arch/arm/lib/_lshrdi3.S
@@ -0,0 +1,48 @@
+/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
+   Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+This file 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; see the file COPYING.  If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+
+#ifdef __ARMEB__
+#define al r1
+#define ah r0
+#else
+#define al r0
+#define ah r1
+#endif
+
+.globl __lshrdi3
+.globl __aeabi_llsr
+__lshrdi3:
+__aeabi_llsr:
+
+	subs	r3, r2, #32
+	rsb	ip, r2, #32
+	movmi	al, al, lsr r2
+	movpl	al, ah, lsr r3
+	orrmi	al, al, ah, lsl ip
+	mov	ah, ah, lsr r2
+	mov	pc, lr
diff --git a/arch/arm/lib/_modsi3.S b/arch/arm/lib/_modsi3.S
new file mode 100644
index 0000000..539c584
--- /dev/null
+++ b/arch/arm/lib/_modsi3.S
@@ -0,0 +1,99 @@
+
+.macro ARM_MOD_BODY dividend, divisor, order, spare
+
+#if __LINUX_ARM_ARCH__ >= 5
+
+	clz	\order, \divisor
+	clz	\spare, \dividend
+	sub	\order, \order, \spare
+	mov	\divisor, \divisor, lsl \order
+
+#else
+
+	mov	\order, #0
+
+	@ Unless the divisor is very big, shift it up in multiples of
+	@ four bits, since this is the amount of unwinding in the main
+	@ division loop.  Continue shifting until the divisor is
+	@ larger than the dividend.
+1:	cmp	\divisor, #0x10000000
+	cmplo	\divisor, \dividend
+	movlo	\divisor, \divisor, lsl #4
+	addlo	\order, \order, #4
+	blo	1b
+
+	@ For very big divisors, we must shift it a bit at a time, or
+	@ we will be in danger of overflowing.
+1:	cmp	\divisor, #0x80000000
+	cmplo	\divisor, \dividend
+	movlo	\divisor, \divisor, lsl #1
+	addlo	\order, \order, #1
+	blo	1b
+
+#endif
+
+	@ Perform all needed substractions to keep only the reminder.
+	@ Do comparisons in batch of 4 first.
+	subs	\order, \order, #3		@ yes, 3 is intended here
+	blt	2f
+
+1:	cmp	\dividend, \divisor
+	subhs	\dividend, \dividend, \divisor
+	cmp	\dividend, \divisor,  lsr #1
+	subhs	\dividend, \dividend, \divisor, lsr #1
+	cmp	\dividend, \divisor,  lsr #2
+	subhs	\dividend, \dividend, \divisor, lsr #2
+	cmp	\dividend, \divisor,  lsr #3
+	subhs	\dividend, \dividend, \divisor, lsr #3
+	cmp	\dividend, #1
+	mov	\divisor, \divisor, lsr #4
+	subges	\order, \order, #4
+	bge	1b
+
+	tst	\order, #3
+	teqne	\dividend, #0
+	beq	5f
+
+	@ Either 1, 2 or 3 comparison/substractions are left.
+2:	cmn	\order, #2
+	blt	4f
+	beq	3f
+	cmp	\dividend, \divisor
+	subhs	\dividend, \dividend, \divisor
+	mov	\divisor,  \divisor,  lsr #1
+3:	cmp	\dividend, \divisor
+	subhs	\dividend, \dividend, \divisor
+	mov	\divisor,  \divisor,  lsr #1
+4:	cmp	\dividend, \divisor
+	subhs	\dividend, \dividend, \divisor
+5:
+.endm
+
+	.align	5
+.globl __modsi3
+__modsi3:
+	cmp	r1, #0
+	beq	Ldiv0
+	rsbmi	r1, r1, #0			@ loops below use unsigned.
+	movs	ip, r0				@ preserve sign of dividend
+	rsbmi	r0, r0, #0			@ if negative make positive
+	subs	r2, r1, #1			@ compare divisor with 1
+	cmpne	r0, r1				@ compare dividend with divisor
+	moveq	r0, #0
+	tsthi	r1, r2				@ see if divisor is power of 2
+	andeq	r0, r0, r2
+	bls	10f
+
+	ARM_MOD_BODY r0, r1, r2, r3
+
+10:	cmp	ip, #0
+	rsbmi	r0, r0, #0
+	mov	pc, lr
+
+
+Ldiv0:
+
+	str	lr, [sp, #-4]!
+	bl	__div0
+	mov	r0, #0			@ About as wrong as it could be.
+	ldr	pc, [sp], #4
diff --git a/arch/arm/lib/_udivsi3.S b/arch/arm/lib/_udivsi3.S
new file mode 100644
index 0000000..1309802
--- /dev/null
+++ b/arch/arm/lib/_udivsi3.S
@@ -0,0 +1,93 @@
+/* # 1 "libgcc1.S" */
+@ libgcc1 routines for ARM cpu.
+@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
+dividend	.req	r0
+divisor		.req	r1
+result		.req	r2
+curbit		.req	r3
+/* ip		.req	r12	*/
+/* sp		.req	r13	*/
+/* lr		.req	r14	*/
+/* pc		.req	r15	*/
+	.text
+	.globl	 __udivsi3
+	.type	__udivsi3 ,function
+	.globl	__aeabi_uidiv
+	.type	__aeabi_uidiv ,function
+	.align	0
+ __udivsi3:
+ __aeabi_uidiv:
+	cmp	divisor, #0
+	beq	Ldiv0
+	mov	curbit, #1
+	mov	result, #0
+	cmp	dividend, divisor
+	bcc	Lgot_result
+Loop1:
+	@ Unless the divisor is very big, shift it up in multiples of
+	@ four bits, since this is the amount of unwinding in the main
+	@ division loop.  Continue shifting until the divisor is
+	@ larger than the dividend.
+	cmp	divisor, #0x10000000
+	cmpcc	divisor, dividend
+	movcc	divisor, divisor, lsl #4
+	movcc	curbit, curbit, lsl #4
+	bcc	Loop1
+Lbignum:
+	@ For very big divisors, we must shift it a bit at a time, or
+	@ we will be in danger of overflowing.
+	cmp	divisor, #0x80000000
+	cmpcc	divisor, dividend
+	movcc	divisor, divisor, lsl #1
+	movcc	curbit, curbit, lsl #1
+	bcc	Lbignum
+Loop3:
+	@ Test for possible subtractions, and note which bits
+	@ are done in the result.  On the final pass, this may subtract
+	@ too much from the dividend, but the result will be ok, since the
+	@ "bit" will have been shifted out at the bottom.
+	cmp	dividend, divisor
+	subcs	dividend, dividend, divisor
+	orrcs	result, result, curbit
+	cmp	dividend, divisor, lsr #1
+	subcs	dividend, dividend, divisor, lsr #1
+	orrcs	result, result, curbit, lsr #1
+	cmp	dividend, divisor, lsr #2
+	subcs	dividend, dividend, divisor, lsr #2
+	orrcs	result, result, curbit, lsr #2
+	cmp	dividend, divisor, lsr #3
+	subcs	dividend, dividend, divisor, lsr #3
+	orrcs	result, result, curbit, lsr #3
+	cmp	dividend, #0			@ Early termination?
+	movnes	curbit, curbit, lsr #4		@ No, any more bits to do?
+	movne	divisor, divisor, lsr #4
+	bne	Loop3
+Lgot_result:
+	mov	r0, result
+	mov	pc, lr
+Ldiv0:
+	str	lr, [sp, #-4]!
+	bl	 __div0       (PLT)
+	mov	r0, #0			@ about as wrong as it could be
+	ldmia	sp!, {pc}
+	.size  __udivsi3       , . -  __udivsi3
+
+.globl __aeabi_uidivmod
+__aeabi_uidivmod:
+
+	stmfd	sp!, {r0, r1, ip, lr}
+	bl	__aeabi_uidiv
+	ldmfd	sp!, {r1, r2, ip, lr}
+	mul	r3, r0, r2
+	sub	r1, r1, r3
+	mov	pc, lr
+
+.globl __aeabi_idivmod
+__aeabi_idivmod:
+
+	stmfd	sp!, {r0, r1, ip, lr}
+	bl	__aeabi_idiv
+	ldmfd	sp!, {r1, r2, ip, lr}
+	mul	r3, r0, r2
+	sub	r1, r1, r3
+	mov	pc, lr
diff --git a/arch/arm/lib/_umodsi3.S b/arch/arm/lib/_umodsi3.S
new file mode 100644
index 0000000..8465ef0
--- /dev/null
+++ b/arch/arm/lib/_umodsi3.S
@@ -0,0 +1,88 @@
+/* # 1 "libgcc1.S" */
+@ libgcc1 routines for ARM cpu.
+@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
+/* # 145 "libgcc1.S" */
+dividend	.req	r0
+divisor		.req	r1
+overdone	.req	r2
+curbit		.req	r3
+/* ip		.req	r12	*/
+/* sp		.req	r13	*/
+/* lr		.req	r14	*/
+/* pc		.req	r15	*/
+	.text
+	.globl	 __umodsi3
+	.type  __umodsi3       ,function
+	.align 0
+ __umodsi3      :
+	cmp	divisor, #0
+	beq	Ldiv0
+	mov	curbit, #1
+	cmp	dividend, divisor
+	movcc	pc, lr
+Loop1:
+	@ Unless the divisor is very big, shift it up in multiples of
+	@ four bits, since this is the amount of unwinding in the main
+	@ division loop.  Continue shifting until the divisor is
+	@ larger than the dividend.
+	cmp	divisor, #0x10000000
+	cmpcc	divisor, dividend
+	movcc	divisor, divisor, lsl #4
+	movcc	curbit, curbit, lsl #4
+	bcc	Loop1
+Lbignum:
+	@ For very big divisors, we must shift it a bit at a time, or
+	@ we will be in danger of overflowing.
+	cmp	divisor, #0x80000000
+	cmpcc	divisor, dividend
+	movcc	divisor, divisor, lsl #1
+	movcc	curbit, curbit, lsl #1
+	bcc	Lbignum
+Loop3:
+	@ Test for possible subtractions.  On the final pass, this may
+	@ subtract too much from the dividend, so keep track of which
+	@ subtractions are done, we can fix them up afterwards...
+	mov	overdone, #0
+	cmp	dividend, divisor
+	subcs	dividend, dividend, divisor
+	cmp	dividend, divisor, lsr #1
+	subcs	dividend, dividend, divisor, lsr #1
+	orrcs	overdone, overdone, curbit, ror #1
+	cmp	dividend, divisor, lsr #2
+	subcs	dividend, dividend, divisor, lsr #2
+	orrcs	overdone, overdone, curbit, ror #2
+	cmp	dividend, divisor, lsr #3
+	subcs	dividend, dividend, divisor, lsr #3
+	orrcs	overdone, overdone, curbit, ror #3
+	mov	ip, curbit
+	cmp	dividend, #0			@ Early termination?
+	movnes	curbit, curbit, lsr #4		@ No, any more bits to do?
+	movne	divisor, divisor, lsr #4
+	bne	Loop3
+	@ Any subtractions that we should not have done will be recorded in
+	@ the top three bits of "overdone".  Exactly which were not needed
+	@ are governed by the position of the bit, stored in ip.
+	@ If we terminated early, because dividend became zero,
+	@ then none of the below will match, since the bit in ip will not be
+	@ in the bottom nibble.
+	ands	overdone, overdone, #0xe0000000
+	moveq	pc, lr				@ No fixups needed
+	tst	overdone, ip, ror #3
+	addne	dividend, dividend, divisor, lsr #3
+	tst	overdone, ip, ror #2
+	addne	dividend, dividend, divisor, lsr #2
+	tst	overdone, ip, ror #1
+	addne	dividend, dividend, divisor, lsr #1
+	mov	pc, lr
+Ldiv0:
+	str	lr, [sp, #-4]!
+	bl	 __div0       (PLT)
+	mov	r0, #0			@ about as wrong as it could be
+	ldmia	sp!, {pc}
+	.size  __umodsi3       , . -  __umodsi3
+/* # 320 "libgcc1.S" */
+/* # 421 "libgcc1.S" */
+/* # 433 "libgcc1.S" */
+/* # 456 "libgcc1.S" */
+/* # 500 "libgcc1.S" */
+/* # 580 "libgcc1.S" */
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
new file mode 100644
index 0000000..f5660a9
--- /dev/null
+++ b/arch/arm/lib/board.c
@@ -0,0 +1,452 @@
+/*
+ * (C) Copyright 2002-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002
+ * 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
+ */
+
+/*
+ * To match the U-Boot user interface on ARM platforms to the U-Boot
+ * standard (as on PPC platforms), some messages with debug character
+ * are removed from the default U-Boot build.
+ *
+ * Define DEBUG here if you want additional info as shown below
+ * printed upon startup:
+ *
+ * U-Boot code: 00F00000 -> 00F3C774  BSS: -> 00FC3274
+ * IRQ Stack: 00ebff7c
+ * FIQ Stack: 00ebef7c
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <stdio_dev.h>
+#include <timestamp.h>
+#include <version.h>
+#include <net.h>
+#include <serial.h>
+#include <nand.h>
+#include <onenand_uboot.h>
+#include <mmc.h>
+
+#ifdef CONFIG_BITBANGMII
+#include <miiphy.h>
+#endif
+
+#ifdef CONFIG_DRIVER_SMC91111
+#include "../drivers/net/smc91111.h"
+#endif
+#ifdef CONFIG_DRIVER_LAN91C96
+#include "../drivers/net/lan91c96.h"
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+ulong monitor_flash_len;
+
+#ifdef CONFIG_HAS_DATAFLASH
+extern int  AT91F_DataflashInit(void);
+extern void dataflash_print_info(void);
+#endif
+
+#ifndef CONFIG_IDENT_STRING
+#define CONFIG_IDENT_STRING ""
+#endif
+
+const char version_string[] =
+	U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")"CONFIG_IDENT_STRING;
+
+#ifdef CONFIG_DRIVER_RTL8019
+extern void rtl8019_get_enetaddr (uchar * addr);
+#endif
+
+#if defined(CONFIG_HARD_I2C) || \
+    defined(CONFIG_SOFT_I2C)
+#include <i2c.h>
+#endif
+
+
+/************************************************************************
+ * Coloured LED functionality
+ ************************************************************************
+ * May be supplied by boards if desired
+ */
+void inline __coloured_LED_init (void) {}
+void coloured_LED_init (void) __attribute__((weak, alias("__coloured_LED_init")));
+void inline __red_LED_on (void) {}
+void red_LED_on (void) __attribute__((weak, alias("__red_LED_on")));
+void inline __red_LED_off(void) {}
+void red_LED_off(void) __attribute__((weak, alias("__red_LED_off")));
+void inline __green_LED_on(void) {}
+void green_LED_on(void) __attribute__((weak, alias("__green_LED_on")));
+void inline __green_LED_off(void) {}
+void green_LED_off(void) __attribute__((weak, alias("__green_LED_off")));
+void inline __yellow_LED_on(void) {}
+void yellow_LED_on(void) __attribute__((weak, alias("__yellow_LED_on")));
+void inline __yellow_LED_off(void) {}
+void yellow_LED_off(void) __attribute__((weak, alias("__yellow_LED_off")));
+void inline __blue_LED_on(void) {}
+void blue_LED_on(void) __attribute__((weak, alias("__blue_LED_on")));
+void inline __blue_LED_off(void) {}
+void blue_LED_off(void) __attribute__((weak, alias("__blue_LED_off")));
+
+/************************************************************************
+ * Init Utilities							*
+ ************************************************************************
+ * Some of this code should be moved into the core functions,
+ * or dropped completely,
+ * but let's get it working (again) first...
+ */
+
+#if defined(CONFIG_ARM_DCC) && !defined(CONFIG_BAUDRATE)
+#define CONFIG_BAUDRATE 115200
+#endif
+static int init_baudrate (void)
+{
+	char tmp[64];	/* long enough for environment variables */
+	int i = getenv_r ("baudrate", tmp, sizeof (tmp));
+	gd->bd->bi_baudrate = gd->baudrate = (i > 0)
+			? (int) simple_strtoul (tmp, NULL, 10)
+			: CONFIG_BAUDRATE;
+
+	return (0);
+}
+
+static int display_banner (void)
+{
+	printf ("\n\n%s\n\n", version_string);
+	debug ("U-Boot code: %08lX -> %08lX  BSS: -> %08lX\n",
+	       _armboot_start, _bss_start, _bss_end);
+#ifdef CONFIG_MODEM_SUPPORT
+	debug ("Modem Support enabled\n");
+#endif
+#ifdef CONFIG_USE_IRQ
+	debug ("IRQ Stack: %08lx\n", IRQ_STACK_START);
+	debug ("FIQ Stack: %08lx\n", FIQ_STACK_START);
+#endif
+
+	return (0);
+}
+
+/*
+ * WARNING: this code looks "cleaner" than the PowerPC version, but
+ * has the disadvantage that you either get nothing, or everything.
+ * On PowerPC, you might see "DRAM: " before the system hangs - which
+ * gives a simple yet clear indication which part of the
+ * initialization if failing.
+ */
+static int display_dram_config (void)
+{
+	int i;
+
+#ifdef DEBUG
+	puts ("RAM Configuration:\n");
+
+	for(i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
+		printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
+		print_size (gd->bd->bi_dram[i].size, "\n");
+	}
+#else
+	ulong size = 0;
+
+	for (i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
+		size += gd->bd->bi_dram[i].size;
+	}
+	puts("DRAM:  ");
+	print_size(size, "\n");
+#endif
+
+	return (0);
+}
+
+#ifndef CONFIG_SYS_NO_FLASH
+static void display_flash_config (ulong size)
+{
+	puts ("Flash: ");
+	print_size (size, "\n");
+}
+#endif /* CONFIG_SYS_NO_FLASH */
+
+#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_CMD_PCI) || defined (CONFIG_PCI)
+#include <pci.h>
+static int arm_pci_init(void)
+{
+	pci_init();
+	return 0;
+}
+#endif /* CONFIG_CMD_PCI || CONFIG_PCI */
+
+/*
+ * Breathe some life into the board...
+ *
+ * Initialize a serial port as console, and carry out some hardware
+ * tests.
+ *
+ * The first part of initialization is running from Flash memory;
+ * its main purpose is to initialize the RAM so that we
+ * can relocate the monitor code to RAM.
+ */
+
+/*
+ * 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 dependent #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);
+
+int print_cpuinfo (void);
+
+init_fnc_t *init_sequence[] = {
+#if defined(CONFIG_ARCH_CPU_INIT)
+	arch_cpu_init,		/* basic arch cpu dependent setup */
+#endif
+	board_init,		/* basic board dependent setup */
+#if defined(CONFIG_USE_IRQ)
+	interrupt_init,		/* set up exceptions */
+#endif
+	timer_init,		/* initialize timer */
+#ifdef CONFIG_FSL_ESDHC
+	get_clocks,
+#endif
+	env_init,		/* initialize environment */
+	init_baudrate,		/* initialze baudrate settings */
+	serial_init,		/* serial communications setup */
+	console_init_f,		/* stage 1 init of console */
+	display_banner,		/* say that we are here */
+#if defined(CONFIG_DISPLAY_CPUINFO)
+	print_cpuinfo,		/* display cpu info (and speed) */
+#endif
+#if defined(CONFIG_DISPLAY_BOARDINFO)
+	checkboard,		/* display board info */
+#endif
+#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
+	init_func_i2c,
+#endif
+	dram_init,		/* configure available RAM banks */
+#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
+	arm_pci_init,
+#endif
+	display_dram_config,
+	NULL,
+};
+
+void start_armboot (void)
+{
+	init_fnc_t **init_fnc_ptr;
+	char *s;
+#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
+	unsigned long addr;
+#endif
+
+	/* Pointer is writable since we allocated a register for it */
+	gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
+	/* compiler optimization barrier needed for GCC >= 3.4 */
+	__asm__ __volatile__("": : :"memory");
+
+	memset ((void*)gd, 0, sizeof (gd_t));
+	gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
+	memset (gd->bd, 0, sizeof (bd_t));
+
+	gd->flags |= GD_FLG_RELOC;
+
+	monitor_flash_len = _bss_start - _armboot_start;
+
+	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
+		if ((*init_fnc_ptr)() != 0) {
+			hang ();
+		}
+	}
+
+	/* armboot_start is defined in the board-specific linker script */
+	mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,
+			CONFIG_SYS_MALLOC_LEN);
+
+#ifndef CONFIG_SYS_NO_FLASH
+	/* configure available FLASH banks */
+	display_flash_config (flash_init ());
+#endif /* CONFIG_SYS_NO_FLASH */
+
+#ifdef CONFIG_VFD
+#	ifndef PAGE_SIZE
+#	  define PAGE_SIZE 4096
+#	endif
+	/*
+	 * reserve memory for VFD display (always full pages)
+	 */
+	/* bss_end is defined in the board-specific linker script */
+	addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+	vfd_setmem (addr);
+	gd->fb_base = addr;
+#endif /* CONFIG_VFD */
+
+#ifdef CONFIG_LCD
+	/* board init may have inited fb_base */
+	if (!gd->fb_base) {
+#		ifndef PAGE_SIZE
+#		  define PAGE_SIZE 4096
+#		endif
+		/*
+		 * reserve memory for LCD display (always full pages)
+		 */
+		/* bss_end is defined in the board-specific linker script */
+		addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+		lcd_setmem (addr);
+		gd->fb_base = addr;
+	}
+#endif /* CONFIG_LCD */
+
+#if defined(CONFIG_CMD_NAND)
+	puts ("NAND:  ");
+	nand_init();		/* go init the NAND */
+#endif
+
+#if defined(CONFIG_CMD_ONENAND)
+	onenand_init();
+#endif
+
+#ifdef CONFIG_HAS_DATAFLASH
+	AT91F_DataflashInit();
+	dataflash_print_info();
+#endif
+
+	/* initialize environment */
+	env_relocate ();
+
+#ifdef CONFIG_VFD
+	/* must do this after the framebuffer is allocated */
+	drv_vfd_init();
+#endif /* CONFIG_VFD */
+
+#ifdef CONFIG_SERIAL_MULTI
+	serial_initialize();
+#endif
+
+	/* IP Address */
+	gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
+
+	stdio_init ();	/* get the devices list going. */
+
+	jumptable_init ();
+
+#if defined(CONFIG_API)
+	/* Initialize API */
+	api_init ();
+#endif
+
+	console_init_r ();	/* fully init console as a device */
+
+#if defined(CONFIG_ARCH_MISC_INIT)
+	/* miscellaneous arch dependent initialisations */
+	arch_misc_init ();
+#endif
+#if defined(CONFIG_MISC_INIT_R)
+	/* miscellaneous platform dependent initialisations */
+	misc_init_r ();
+#endif
+
+	/* enable exceptions */
+	enable_interrupts ();
+
+	/* Perform network card initialisation if necessary */
+#ifdef CONFIG_DRIVER_TI_EMAC
+	/* XXX: this needs to be moved to board init */
+extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
+	if (getenv ("ethaddr")) {
+		uchar enetaddr[6];
+		eth_getenv_enetaddr("ethaddr", enetaddr);
+		davinci_eth_set_mac_addr(enetaddr);
+	}
+#endif
+
+#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
+	/* XXX: this needs to be moved to board init */
+	if (getenv ("ethaddr")) {
+		uchar enetaddr[6];
+		eth_getenv_enetaddr("ethaddr", enetaddr);
+		smc_set_mac_addr(enetaddr);
+	}
+#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
+
+	/* 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
+
+#ifdef BOARD_LATE_INIT
+	board_late_init ();
+#endif
+
+#ifdef CONFIG_GENERIC_MMC
+	puts ("MMC:   ");
+	mmc_initialize (gd->bd);
+#endif
+
+#ifdef CONFIG_BITBANGMII
+	bb_miiphy_init();
+#endif
+#if defined(CONFIG_CMD_NET)
+#if defined(CONFIG_NET_MULTI)
+	puts ("Net:   ");
+#endif
+	eth_initialize(gd->bd);
+#if defined(CONFIG_RESET_PHY_R)
+	debug ("Reset Ethernet PHY\n");
+	reset_phy();
+#endif
+#endif
+	/* main_loop() can return to retry autoboot, if so just run it again. */
+	for (;;) {
+		main_loop ();
+	}
+
+	/* NOTREACHED - no way out of command loop except booting */
+}
+
+void hang (void)
+{
+	puts ("### ERROR ### Please RESET the board ###\n");
+	for (;;);
+}
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
new file mode 100644
index 0000000..128b7e3
--- /dev/null
+++ b/arch/arm/lib/bootm.c
@@ -0,0 +1,279 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * Copyright (C) 2001  Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 <image.h>
+#include <u-boot/zlib.h>
+#include <asm/byteorder.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
+    defined (CONFIG_CMDLINE_TAG) || \
+    defined (CONFIG_INITRD_TAG) || \
+    defined (CONFIG_SERIAL_TAG) || \
+    defined (CONFIG_REVISION_TAG) || \
+    defined (CONFIG_VFD) || \
+    defined (CONFIG_LCD)
+static void setup_start_tag (bd_t *bd);
+
+# ifdef CONFIG_SETUP_MEMORY_TAGS
+static void setup_memory_tags (bd_t *bd);
+# endif
+static void setup_commandline_tag (bd_t *bd, char *commandline);
+
+# ifdef CONFIG_INITRD_TAG
+static void setup_initrd_tag (bd_t *bd, ulong initrd_start,
+			      ulong initrd_end);
+# endif
+static void setup_end_tag (bd_t *bd);
+
+# if defined (CONFIG_VFD) || defined (CONFIG_LCD)
+static void setup_videolfb_tag (gd_t *gd);
+# endif
+
+static struct tag *params;
+#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
+
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	bd_t	*bd = gd->bd;
+	char	*s;
+	int	machid = bd->bi_arch_number;
+	void	(*theKernel)(int zero, int arch, uint params);
+
+#ifdef CONFIG_CMDLINE_TAG
+	char *commandline = getenv ("bootargs");
+#endif
+
+	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+		return 1;
+
+	theKernel = (void (*)(int, int, uint))images->ep;
+
+	s = getenv ("machid");
+	if (s) {
+		machid = simple_strtoul (s, NULL, 16);
+		printf ("Using machid 0x%x from environment\n", machid);
+	}
+
+	show_boot_progress (15);
+
+	debug ("## Transferring control to Linux (at address %08lx) ...\n",
+	       (ulong) theKernel);
+
+#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
+    defined (CONFIG_CMDLINE_TAG) || \
+    defined (CONFIG_INITRD_TAG) || \
+    defined (CONFIG_SERIAL_TAG) || \
+    defined (CONFIG_REVISION_TAG) || \
+    defined (CONFIG_LCD) || \
+    defined (CONFIG_VFD)
+	setup_start_tag (bd);
+#ifdef CONFIG_SERIAL_TAG
+	setup_serial_tag (&params);
+#endif
+#ifdef CONFIG_REVISION_TAG
+	setup_revision_tag (&params);
+#endif
+#ifdef CONFIG_SETUP_MEMORY_TAGS
+	setup_memory_tags (bd);
+#endif
+#ifdef CONFIG_CMDLINE_TAG
+	setup_commandline_tag (bd, commandline);
+#endif
+#ifdef CONFIG_INITRD_TAG
+	if (images->rd_start && images->rd_end)
+		setup_initrd_tag (bd, images->rd_start, images->rd_end);
+#endif
+#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
+	setup_videolfb_tag ((gd_t *) gd);
+#endif
+	setup_end_tag (bd);
+#endif
+
+	/* we assume that the kernel is in place */
+	printf ("\nStarting kernel ...\n\n");
+
+#ifdef CONFIG_USB_DEVICE
+	{
+		extern void udc_disconnect (void);
+		udc_disconnect ();
+	}
+#endif
+
+	cleanup_before_linux ();
+
+	theKernel (0, machid, bd->bi_boot_params);
+	/* does not return */
+
+	return 1;
+}
+
+
+#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
+    defined (CONFIG_CMDLINE_TAG) || \
+    defined (CONFIG_INITRD_TAG) || \
+    defined (CONFIG_SERIAL_TAG) || \
+    defined (CONFIG_REVISION_TAG) || \
+    defined (CONFIG_LCD) || \
+    defined (CONFIG_VFD)
+static void setup_start_tag (bd_t *bd)
+{
+	params = (struct tag *) bd->bi_boot_params;
+
+	params->hdr.tag = ATAG_CORE;
+	params->hdr.size = tag_size (tag_core);
+
+	params->u.core.flags = 0;
+	params->u.core.pagesize = 0;
+	params->u.core.rootdev = 0;
+
+	params = tag_next (params);
+}
+
+
+#ifdef CONFIG_SETUP_MEMORY_TAGS
+static void setup_memory_tags (bd_t *bd)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		params->hdr.tag = ATAG_MEM;
+		params->hdr.size = tag_size (tag_mem32);
+
+		params->u.mem.start = bd->bi_dram[i].start;
+		params->u.mem.size = bd->bi_dram[i].size;
+
+		params = tag_next (params);
+	}
+}
+#endif /* CONFIG_SETUP_MEMORY_TAGS */
+
+
+static void setup_commandline_tag (bd_t *bd, char *commandline)
+{
+	char *p;
+
+	if (!commandline)
+		return;
+
+	/* eat leading white space */
+	for (p = commandline; *p == ' '; p++);
+
+	/* skip non-existent command lines so the kernel will still
+	 * use its default command line.
+	 */
+	if (*p == '\0')
+		return;
+
+	params->hdr.tag = ATAG_CMDLINE;
+	params->hdr.size =
+		(sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
+
+	strcpy (params->u.cmdline.cmdline, p);
+
+	params = tag_next (params);
+}
+
+
+#ifdef CONFIG_INITRD_TAG
+static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end)
+{
+	/* an ATAG_INITRD node tells the kernel where the compressed
+	 * ramdisk can be found. ATAG_RDIMG is a better name, actually.
+	 */
+	params->hdr.tag = ATAG_INITRD2;
+	params->hdr.size = tag_size (tag_initrd);
+
+	params->u.initrd.start = initrd_start;
+	params->u.initrd.size = initrd_end - initrd_start;
+
+	params = tag_next (params);
+}
+#endif /* CONFIG_INITRD_TAG */
+
+
+#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
+extern ulong calc_fbsize (void);
+static void setup_videolfb_tag (gd_t *gd)
+{
+	/* An ATAG_VIDEOLFB node tells the kernel where and how large
+	 * the framebuffer for video was allocated (among other things).
+	 * Note that a _physical_ address is passed !
+	 *
+	 * We only use it to pass the address and size, the other entries
+	 * in the tag_videolfb are not of interest.
+	 */
+	params->hdr.tag = ATAG_VIDEOLFB;
+	params->hdr.size = tag_size (tag_videolfb);
+
+	params->u.videolfb.lfb_base = (u32) gd->fb_base;
+	/* Fb size is calculated according to parameters for our panel
+	 */
+	params->u.videolfb.lfb_size = calc_fbsize();
+
+	params = tag_next (params);
+}
+#endif /* CONFIG_VFD || CONFIG_LCD */
+
+#ifdef CONFIG_SERIAL_TAG
+void setup_serial_tag (struct tag **tmp)
+{
+	struct tag *params = *tmp;
+	struct tag_serialnr serialnr;
+	void get_board_serial(struct tag_serialnr *serialnr);
+
+	get_board_serial(&serialnr);
+	params->hdr.tag = ATAG_SERIAL;
+	params->hdr.size = tag_size (tag_serialnr);
+	params->u.serialnr.low = serialnr.low;
+	params->u.serialnr.high= serialnr.high;
+	params = tag_next (params);
+	*tmp = params;
+}
+#endif
+
+#ifdef CONFIG_REVISION_TAG
+void setup_revision_tag(struct tag **in_params)
+{
+	u32 rev = 0;
+	u32 get_board_rev(void);
+
+	rev = get_board_rev();
+	params->hdr.tag = ATAG_REVISION;
+	params->hdr.size = tag_size (tag_revision);
+	params->u.revision.rev = rev;
+	params = tag_next (params);
+}
+#endif  /* CONFIG_REVISION_TAG */
+
+
+static void setup_end_tag (bd_t *bd)
+{
+	params->hdr.tag = ATAG_NONE;
+	params->hdr.size = 0;
+}
+
+#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c
new file mode 100644
index 0000000..62ed54f
--- /dev/null
+++ b/arch/arm/lib/cache-cp15.c
@@ -0,0 +1,120 @@
+/*
+ * (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/system.h>
+
+#if !(defined(CONFIG_SYS_NO_ICACHE) && defined(CONFIG_SYS_NO_DCACHE))
+static void cp_delay (void)
+{
+	volatile int i;
+
+	/* copro seems to need some delay between reading and writing */
+	for (i = 0; i < 100; i++)
+		nop();
+}
+
+/* cache_bit must be either CR_I or CR_C */
+static void cache_enable(uint32_t cache_bit)
+{
+	uint32_t reg;
+
+	reg = get_cr();	/* get control reg. */
+	cp_delay();
+	set_cr(reg | cache_bit);
+}
+
+/* cache_bit must be either CR_I or CR_C */
+static void cache_disable(uint32_t cache_bit)
+{
+	uint32_t reg;
+
+	reg = get_cr();
+	cp_delay();
+	set_cr(reg & ~cache_bit);
+}
+#endif
+
+#ifdef CONFIG_SYS_NO_ICACHE
+void icache_enable (void)
+{
+	return;
+}
+
+void icache_disable (void)
+{
+	return;
+}
+
+int icache_status (void)
+{
+	return 0;					/* always off */
+}
+#else
+void icache_enable(void)
+{
+	cache_enable(CR_I);
+}
+
+void icache_disable(void)
+{
+	cache_disable(CR_I);
+}
+
+int icache_status(void)
+{
+	return (get_cr() & CR_I) != 0;
+}
+#endif
+
+#ifdef CONFIG_SYS_NO_DCACHE
+void dcache_enable (void)
+{
+	return;
+}
+
+void dcache_disable (void)
+{
+	return;
+}
+
+int dcache_status (void)
+{
+	return 0;					/* always off */
+}
+#else
+void dcache_enable(void)
+{
+	cache_enable(CR_C);
+}
+
+void dcache_disable(void)
+{
+	cache_disable(CR_C);
+}
+
+int dcache_status(void)
+{
+	return (get_cr() & CR_C) != 0;
+}
+#endif
diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c
new file mode 100644
index 0000000..61ee9d3
--- /dev/null
+++ b/arch/arm/lib/cache.c
@@ -0,0 +1,36 @@
+/*
+ * (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
+ */
+
+/* for now: just dummy functions to satisfy the linker */
+
+#include <common.h>
+
+void  flush_cache (unsigned long dummy1, unsigned long dummy2)
+{
+#ifdef CONFIG_OMAP2420
+	void arm1136_cache_flush(void);
+
+	arm1136_cache_flush();
+#endif
+	return;
+}
diff --git a/arch/arm/lib/div0.c b/arch/arm/lib/div0.c
new file mode 100644
index 0000000..6267bf1
--- /dev/null
+++ b/arch/arm/lib/div0.c
@@ -0,0 +1,30 @@
+/*
+ * (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
+ */
+
+/* Replacement (=dummy) for GNU/Linux division-by zero handler */
+void __div0 (void)
+{
+	extern void hang (void);
+
+	hang();
+}
diff --git a/arch/arm/lib/eabi_compat.c b/arch/arm/lib/eabi_compat.c
new file mode 100644
index 0000000..86eacf1
--- /dev/null
+++ b/arch/arm/lib/eabi_compat.c
@@ -0,0 +1,18 @@
+/*
+ * Utility functions needed for (some) EABI conformant tool chains.
+ *
+ * (C) Copyright 2009 Wolfgang Denk <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.
+ */
+
+#include <common.h>
+
+int raise (int signum)
+{
+	printf("raise: Signal # %d caught\n", signum);
+	return 0;
+}
diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c
new file mode 100644
index 0000000..1f2b815
--- /dev/null
+++ b/arch/arm/lib/interrupts.c
@@ -0,0 +1,187 @@
+/*
+ * (C) Copyright 2003
+ * Texas Instruments <www.ti.com>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002-2004
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * (C) Copyright 2004
+ * Philippe Robin, ARM Ltd. <philippe.robin@arm.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/proc-armv/ptrace.h>
+
+#ifdef CONFIG_USE_IRQ
+DECLARE_GLOBAL_DATA_PTR;
+
+int interrupt_init (void)
+{
+	/*
+	 * setup up stacks if necessary
+	 */
+	IRQ_STACK_START = _armboot_start - CONFIG_SYS_MALLOC_LEN - CONFIG_SYS_GBL_DATA_SIZE - 4;
+	FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
+
+	return arch_interrupt_init();
+}
+
+/* enable IRQ interrupts */
+void enable_interrupts (void)
+{
+	unsigned long temp;
+	__asm__ __volatile__("mrs %0, cpsr\n"
+			     "bic %0, %0, #0x80\n"
+			     "msr cpsr_c, %0"
+			     : "=r" (temp)
+			     :
+			     : "memory");
+}
+
+
+/*
+ * disable IRQ/FIQ interrupts
+ * returns true if interrupts had been enabled before we disabled them
+ */
+int disable_interrupts (void)
+{
+	unsigned long old,temp;
+	__asm__ __volatile__("mrs %0, cpsr\n"
+			     "orr %1, %0, #0xc0\n"
+			     "msr cpsr_c, %1"
+			     : "=r" (old), "=r" (temp)
+			     :
+			     : "memory");
+	return (old & 0x80) == 0;
+}
+#else
+void enable_interrupts (void)
+{
+	return;
+}
+int disable_interrupts (void)
+{
+	return 0;
+}
+#endif
+
+
+void bad_mode (void)
+{
+	panic ("Resetting CPU ...\n");
+	reset_cpu (0);
+}
+
+void show_regs (struct pt_regs *regs)
+{
+	unsigned long flags;
+	const char *processor_modes[] = {
+	"USER_26",	"FIQ_26",	"IRQ_26",	"SVC_26",
+	"UK4_26",	"UK5_26",	"UK6_26",	"UK7_26",
+	"UK8_26",	"UK9_26",	"UK10_26",	"UK11_26",
+	"UK12_26",	"UK13_26",	"UK14_26",	"UK15_26",
+	"USER_32",	"FIQ_32",	"IRQ_32",	"SVC_32",
+	"UK4_32",	"UK5_32",	"UK6_32",	"ABT_32",
+	"UK8_32",	"UK9_32",	"UK10_32",	"UND_32",
+	"UK12_32",	"UK13_32",	"UK14_32",	"SYS_32",
+	};
+
+	flags = condition_codes (regs);
+
+	printf ("pc : [<%08lx>]	   lr : [<%08lx>]\n"
+		"sp : %08lx  ip : %08lx	 fp : %08lx\n",
+		instruction_pointer (regs),
+		regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
+	printf ("r10: %08lx  r9 : %08lx	 r8 : %08lx\n",
+		regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
+	printf ("r7 : %08lx  r6 : %08lx	 r5 : %08lx  r4 : %08lx\n",
+		regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4);
+	printf ("r3 : %08lx  r2 : %08lx	 r1 : %08lx  r0 : %08lx\n",
+		regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0);
+	printf ("Flags: %c%c%c%c",
+		flags & CC_N_BIT ? 'N' : 'n',
+		flags & CC_Z_BIT ? 'Z' : 'z',
+		flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v');
+	printf ("  IRQs %s  FIQs %s  Mode %s%s\n",
+		interrupts_enabled (regs) ? "on" : "off",
+		fast_interrupts_enabled (regs) ? "on" : "off",
+		processor_modes[processor_mode (regs)],
+		thumb_mode (regs) ? " (T)" : "");
+}
+
+void do_undefined_instruction (struct pt_regs *pt_regs)
+{
+	printf ("undefined instruction\n");
+	show_regs (pt_regs);
+	bad_mode ();
+}
+
+void do_software_interrupt (struct pt_regs *pt_regs)
+{
+	printf ("software interrupt\n");
+	show_regs (pt_regs);
+	bad_mode ();
+}
+
+void do_prefetch_abort (struct pt_regs *pt_regs)
+{
+	printf ("prefetch abort\n");
+	show_regs (pt_regs);
+	bad_mode ();
+}
+
+void do_data_abort (struct pt_regs *pt_regs)
+{
+	printf ("data abort\n");
+	show_regs (pt_regs);
+	bad_mode ();
+}
+
+void do_not_used (struct pt_regs *pt_regs)
+{
+	printf ("not used\n");
+	show_regs (pt_regs);
+	bad_mode ();
+}
+
+void do_fiq (struct pt_regs *pt_regs)
+{
+	printf ("fast interrupt request\n");
+	show_regs (pt_regs);
+	bad_mode ();
+}
+
+#ifndef CONFIG_USE_IRQ
+void do_irq (struct pt_regs *pt_regs)
+{
+	printf ("interrupt request\n");
+	show_regs (pt_regs);
+	bad_mode ();
+}
+#endif
diff --git a/arch/arm/lib/reset.c b/arch/arm/lib/reset.c
new file mode 100644
index 0000000..4fcedfa
--- /dev/null
+++ b/arch/arm/lib/reset.c
@@ -0,0 +1,53 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * (C) Copyright 2004
+ * DAVE Srl
+ * http://www.dave-tech.it
+ * http://www.wawnet.biz
+ * mailto:info@wawnet.biz
+ *
+ * (C) Copyright 2004 Texas Insturments
+ *
+ * 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>
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	puts ("resetting ...\n");
+
+	udelay (50000);				/* wait 50 ms */
+
+	disable_interrupts();
+	reset_cpu(0);
+
+	/*NOTREACHED*/
+	return 0;
+}
diff --git a/arch/avr32/config.mk b/arch/avr32/config.mk
new file mode 100644
index 0000000..1121ca1
--- /dev/null
+++ b/arch/avr32/config.mk
@@ -0,0 +1,29 @@
+#
+# (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 ?= avr32-linux-
+
+STANDALONE_LOAD_ADDR = 0x00000000
+
+PLATFORM_RELFLAGS	+= -ffixed-r5 -fPIC -mno-init-got -mrelax
+PLATFORM_LDFLAGS	+= --relax
diff --git a/arch/avr32/lib/Makefile b/arch/avr32/lib/Makefile
new file mode 100644
index 0000000..37b8051
--- /dev/null
+++ b/arch/avr32/lib/Makefile
@@ -0,0 +1,49 @@
+#
+# (C) Copyright 2002-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2004-2006 Atmel Corporation
+#
+# 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	+= memset.o
+
+COBJS-y	+= board.o
+COBJS-y	+= bootm.o
+COBJS-y	+= interrupts.o
+
+SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/avr32/lib/board.c b/arch/avr32/lib/board.c
new file mode 100644
index 0000000..917ed6c
--- /dev/null
+++ b/arch/avr32/lib/board.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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 <malloc.h>
+#include <stdio_dev.h>
+#include <timestamp.h>
+#include <version.h>
+#include <net.h>
+
+#ifdef CONFIG_BITBANGMII
+#include <miiphy.h>
+#endif
+
+#include <asm/initcalls.h>
+#include <asm/sections.h>
+
+#ifndef CONFIG_IDENT_STRING
+#define CONFIG_IDENT_STRING ""
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+const char version_string[] =
+	U_BOOT_VERSION " ("U_BOOT_DATE" - "U_BOOT_TIME") " CONFIG_IDENT_STRING;
+
+unsigned long monitor_flash_len;
+
+/* Weak aliases for optional board functions */
+static int __do_nothing(void)
+{
+	return 0;
+}
+int board_postclk_init(void) __attribute__((weak, alias("__do_nothing")));
+int board_early_init_r(void) __attribute__((weak, alias("__do_nothing")));
+
+#ifdef CONFIG_SYS_DMA_ALLOC_LEN
+#include <asm/arch/cacheflush.h>
+#include <asm/io.h>
+
+static unsigned long dma_alloc_start;
+static unsigned long dma_alloc_end;
+static unsigned long dma_alloc_brk;
+
+static void dma_alloc_init(void)
+{
+	unsigned long monitor_addr;
+
+	monitor_addr = CONFIG_SYS_MONITOR_BASE + gd->reloc_off;
+	dma_alloc_end = monitor_addr - CONFIG_SYS_MALLOC_LEN;
+	dma_alloc_start = dma_alloc_end - CONFIG_SYS_DMA_ALLOC_LEN;
+	dma_alloc_brk = dma_alloc_start;
+
+	printf("DMA: Using memory from 0x%08lx to 0x%08lx\n",
+	       dma_alloc_start, dma_alloc_end);
+
+	dcache_invalidate_range(cached(dma_alloc_start),
+				dma_alloc_end - dma_alloc_start);
+}
+
+void *dma_alloc_coherent(size_t len, unsigned long *handle)
+{
+	unsigned long paddr = dma_alloc_brk;
+
+	if (dma_alloc_brk + len > dma_alloc_end)
+		return NULL;
+
+	dma_alloc_brk = ((paddr + len + CONFIG_SYS_DCACHE_LINESZ - 1)
+			 & ~(CONFIG_SYS_DCACHE_LINESZ - 1));
+
+	*handle = paddr;
+	return uncached(paddr);
+}
+#else
+static inline void dma_alloc_init(void)
+{
+
+}
+#endif
+
+static int init_baudrate(void)
+{
+	char tmp[64];
+	int i;
+
+	i = getenv_r("baudrate", tmp, sizeof(tmp));
+	if (i > 0) {
+		gd->baudrate = simple_strtoul(tmp, NULL, 10);
+	} else {
+		gd->baudrate = CONFIG_BAUDRATE;
+	}
+	return 0;
+}
+
+
+static int display_banner (void)
+{
+	printf ("\n\n%s\n\n", version_string);
+	printf ("U-Boot code: %p -> %p  data: %p -> %p\n",
+		_text, _etext, _data, _end);
+	return 0;
+}
+
+void hang(void)
+{
+	for (;;) ;
+}
+
+static int display_dram_config (void)
+{
+	int i;
+
+	puts ("DRAM Configuration:\n");
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
+		print_size (gd->bd->bi_dram[i].size, "\n");
+	}
+
+	return 0;
+}
+
+static void display_flash_config (void)
+{
+	puts ("Flash: ");
+	print_size(gd->bd->bi_flashsize, " ");
+	printf("at address 0x%08lx\n", gd->bd->bi_flashstart);
+}
+
+void board_init_f(ulong board_type)
+{
+	gd_t gd_data;
+	gd_t *new_gd;
+	bd_t *bd;
+	unsigned long *new_sp;
+	unsigned long monitor_len;
+	unsigned long monitor_addr;
+	unsigned long addr;
+	long sdram_size;
+
+	/* Initialize the global data pointer */
+	memset(&gd_data, 0, sizeof(gd_data));
+	gd = &gd_data;
+
+	/* Perform initialization sequence */
+	board_early_init_f();
+	cpu_init();
+	board_postclk_init();
+	env_init();
+	init_baudrate();
+	serial_init();
+	console_init_f();
+	display_banner();
+	sdram_size = initdram(board_type);
+
+	/* If we have no SDRAM, we can't go on */
+	if (sdram_size <= 0)
+		panic("No working SDRAM available\n");
+
+	/*
+	 * 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):
+	 *  - u-boot image
+	 *  - heap for malloc()
+	 *  - board info struct
+	 *  - global data struct
+	 *  - stack
+	 */
+	addr = CONFIG_SYS_SDRAM_BASE + sdram_size;
+	monitor_len = _end - _text;
+
+	/*
+	 * Reserve memory for u-boot code, data and bss.
+	 * Round down to next 4 kB limit.
+	 */
+	addr -= monitor_len;
+	addr &= ~(4096UL - 1);
+	monitor_addr = addr;
+
+	/* Reserve memory for malloc() */
+	addr -= CONFIG_SYS_MALLOC_LEN;
+
+#ifdef CONFIG_SYS_DMA_ALLOC_LEN
+	/* Reserve DMA memory (must be cache aligned) */
+	addr &= ~(CONFIG_SYS_DCACHE_LINESZ - 1);
+	addr -= CONFIG_SYS_DMA_ALLOC_LEN;
+#endif
+
+#ifdef CONFIG_LCD
+#ifdef CONFIG_FB_ADDR
+	printf("LCD: Frame buffer allocated at preset 0x%08x\n",
+	       CONFIG_FB_ADDR);
+	gd->fb_base = (void *)CONFIG_FB_ADDR;
+#else
+	addr = lcd_setmem(addr);
+	printf("LCD: Frame buffer allocated at 0x%08lx\n", addr);
+	gd->fb_base = (void *)addr;
+#endif /* CONFIG_FB_ADDR */
+#endif /* CONFIG_LCD */
+
+	/* Allocate a Board Info struct on a word boundary */
+	addr -= sizeof(bd_t);
+	addr &= ~3UL;
+	gd->bd = bd = (bd_t *)addr;
+
+	/* Allocate a new global data copy on a 8-byte boundary. */
+	addr -= sizeof(gd_t);
+	addr &= ~7UL;
+	new_gd = (gd_t *)addr;
+
+	/* And finally, a new, bigger stack. */
+	new_sp = (unsigned long *)addr;
+	gd->stack_end = addr;
+	*(--new_sp) = 0;
+	*(--new_sp) = 0;
+
+	/*
+	 * Initialize the board information struct with the
+	 * information we have.
+	 */
+	bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+	bd->bi_dram[0].size = sdram_size;
+	bd->bi_baudrate = gd->baudrate;
+
+	memcpy(new_gd, gd, sizeof(gd_t));
+
+	relocate_code((unsigned long)new_sp, new_gd, monitor_addr);
+}
+
+void board_init_r(gd_t *new_gd, ulong dest_addr)
+{
+	extern void malloc_bin_reloc (void);
+#ifndef CONFIG_ENV_IS_NOWHERE
+	extern char * env_name_spec;
+#endif
+	char *s;
+	cmd_tbl_t *cmdtp;
+	bd_t *bd;
+
+	gd = new_gd;
+	bd = gd->bd;
+
+	gd->flags |= GD_FLG_RELOC;
+	gd->reloc_off = dest_addr - CONFIG_SYS_MONITOR_BASE;
+
+	board_early_init_r();
+
+	monitor_flash_len = _edata - _text;
+
+	/*
+	 * We have to relocate the command table manually
+	 */
+	for (cmdtp = &__u_boot_cmd_start;
+	     cmdtp !=  &__u_boot_cmd_end; cmdtp++) {
+		unsigned long addr;
+
+		addr = (unsigned long)cmdtp->cmd + gd->reloc_off;
+		cmdtp->cmd = (typeof(cmdtp->cmd))addr;
+
+		addr = (unsigned long)cmdtp->name + gd->reloc_off;
+		cmdtp->name = (typeof(cmdtp->name))addr;
+
+		if (cmdtp->usage) {
+			addr = (unsigned long)cmdtp->usage + gd->reloc_off;
+			cmdtp->usage = (typeof(cmdtp->usage))addr;
+		}
+#ifdef CONFIG_SYS_LONGHELP
+		if (cmdtp->help) {
+			addr = (unsigned long)cmdtp->help + gd->reloc_off;
+			cmdtp->help = (typeof(cmdtp->help))addr;
+		}
+#endif
+	}
+
+	/* there are some other pointer constants we must deal with */
+#ifndef CONFIG_ENV_IS_NOWHERE
+	env_name_spec += gd->reloc_off;
+#endif
+
+	timer_init();
+
+	/* The malloc area is right below the monitor image in RAM */
+	mem_malloc_init(CONFIG_SYS_MONITOR_BASE + gd->reloc_off -
+			CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN);
+	malloc_bin_reloc();
+	dma_alloc_init();
+
+	enable_interrupts();
+
+	bd->bi_flashstart = 0;
+	bd->bi_flashsize = 0;
+	bd->bi_flashoffset = 0;
+
+#ifndef CONFIG_SYS_NO_FLASH
+	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
+	bd->bi_flashsize = flash_init();
+	bd->bi_flashoffset = (unsigned long)_edata - (unsigned long)_text;
+
+	if (bd->bi_flashsize)
+		display_flash_config();
+#endif
+
+	if (bd->bi_dram[0].size)
+		display_dram_config();
+
+	gd->bd->bi_boot_params = malloc(CONFIG_SYS_BOOTPARAMS_LEN);
+	if (!gd->bd->bi_boot_params)
+		puts("WARNING: Cannot allocate space for boot parameters\n");
+
+	/* initialize environment */
+	env_relocate();
+
+	bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
+
+	stdio_init();
+	jumptable_init();
+	console_init_r();
+
+	s = getenv("loadaddr");
+	if (s)
+		load_addr = simple_strtoul(s, NULL, 16);
+
+#ifdef CONFIG_BITBANGMII
+	bb_miiphy_init();
+#endif
+#if defined(CONFIG_CMD_NET)
+	s = getenv("bootfile");
+	if (s)
+		copy_filename(BootFile, s, sizeof(BootFile));
+#if defined(CONFIG_NET_MULTI)
+	puts("Net:   ");
+#endif
+	eth_initialize(gd->bd);
+#endif
+
+	for (;;) {
+		main_loop();
+	}
+}
diff --git a/arch/avr32/lib/bootm.c b/arch/avr32/lib/bootm.c
new file mode 100644
index 0000000..6a3172a
--- /dev/null
+++ b/arch/avr32/lib/bootm.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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 <image.h>
+#include <u-boot/zlib.h>
+#include <asm/byteorder.h>
+#include <asm/arch/addrspace.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/arch/clk.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* CPU-specific hook to allow flushing of caches, etc. */
+extern void prepare_to_boot(void);
+
+static struct tag *setup_start_tag(struct tag *params)
+{
+	params->hdr.tag = ATAG_CORE;
+	params->hdr.size = tag_size(tag_core);
+
+	params->u.core.flags = 0;
+	params->u.core.pagesize = 4096;
+	params->u.core.rootdev = 0;
+
+	return tag_next(params);
+}
+
+static struct tag *setup_memory_tags(struct tag *params)
+{
+	bd_t *bd = gd->bd;
+	int i;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		params->hdr.tag = ATAG_MEM;
+		params->hdr.size = tag_size(tag_mem_range);
+
+		params->u.mem_range.addr = bd->bi_dram[i].start;
+		params->u.mem_range.size = bd->bi_dram[i].size;
+
+		params = tag_next(params);
+	}
+
+	return params;
+}
+
+static struct tag *setup_commandline_tag(struct tag *params, char *cmdline)
+{
+	if (!cmdline)
+		return params;
+
+	/* eat leading white space */
+	while (*cmdline == ' ') cmdline++;
+
+	/*
+	 * Don't include tags for empty command lines; let the kernel
+	 * use its default command line.
+	 */
+	if (*cmdline == '\0')
+		return params;
+
+	params->hdr.tag = ATAG_CMDLINE;
+	params->hdr.size =
+		(sizeof (struct tag_header) + strlen(cmdline) + 1 + 3) >> 2;
+	strcpy(params->u.cmdline.cmdline, cmdline);
+
+	return tag_next(params);
+}
+
+static struct tag *setup_ramdisk_tag(struct tag *params,
+				     unsigned long rd_start,
+				     unsigned long rd_end)
+{
+	if (rd_start == rd_end)
+		return params;
+
+	params->hdr.tag = ATAG_RDIMG;
+	params->hdr.size = tag_size(tag_mem_range);
+
+	params->u.mem_range.addr = rd_start;
+	params->u.mem_range.size = rd_end - rd_start;
+
+	return tag_next(params);
+}
+
+static struct tag *setup_clock_tags(struct tag *params)
+{
+	params->hdr.tag = ATAG_CLOCK;
+	params->hdr.size = tag_size(tag_clock);
+	params->u.clock.clock_id = ACLOCK_BOOTCPU;
+	params->u.clock.clock_flags = 0;
+	params->u.clock.clock_hz = gd->cpu_hz;
+
+#ifdef CONFIG_AT32AP7000
+	/*
+	 * New kernels don't need this, but we should be backwards
+	 * compatible for a while...
+	 */
+	params = tag_next(params);
+
+	params->hdr.tag = ATAG_CLOCK;
+	params->hdr.size = tag_size(tag_clock);
+	params->u.clock.clock_id = ACLOCK_HSB;
+	params->u.clock.clock_flags = 0;
+	params->u.clock.clock_hz = get_hsb_clk_rate();
+#endif
+
+	return tag_next(params);
+}
+
+static struct tag *setup_ethernet_tag(struct tag *params,
+				      char *addr, int index)
+{
+	char *s, *e;
+	int i;
+
+	params->hdr.tag = ATAG_ETHERNET;
+	params->hdr.size = tag_size(tag_ethernet);
+
+	params->u.ethernet.mac_index = index;
+	params->u.ethernet.mii_phy_addr = gd->bd->bi_phy_id[index];
+
+	s = addr;
+	for (i = 0; i < 6; i++) {
+		params->u.ethernet.hw_address[i] = simple_strtoul(s, &e, 16);
+		s = e + 1;
+	}
+
+	return tag_next(params);
+}
+
+static struct tag *setup_ethernet_tags(struct tag *params)
+{
+	char name[16] = "ethaddr";
+	char *addr;
+	int i = 0;
+
+	do {
+		addr = getenv(name);
+		if (addr)
+			params = setup_ethernet_tag(params, addr, i);
+		sprintf(name, "eth%daddr", ++i);
+	} while (i < 4);
+
+	return params;
+}
+
+static void setup_end_tag(struct tag *params)
+{
+	params->hdr.tag = ATAG_NONE;
+	params->hdr.size = 0;
+}
+
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	void	(*theKernel)(int magic, void *tagtable);
+	struct	tag *params, *params_start;
+	char	*commandline = getenv("bootargs");
+
+	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+		return 1;
+
+	theKernel = (void *)images->ep;
+
+	show_boot_progress (15);
+
+	params = params_start = (struct tag *)gd->bd->bi_boot_params;
+	params = setup_start_tag(params);
+	params = setup_memory_tags(params);
+	if (images->rd_start) {
+		params = setup_ramdisk_tag(params,
+					   PHYSADDR(images->rd_start),
+					   PHYSADDR(images->rd_end));
+	}
+	params = setup_commandline_tag(params, commandline);
+	params = setup_clock_tags(params);
+	params = setup_ethernet_tags(params);
+	setup_end_tag(params);
+
+	printf("\nStarting kernel at %p (params at %p)...\n\n",
+	       theKernel, params_start);
+
+	prepare_to_boot();
+
+	theKernel(ATAG_MAGIC, params_start);
+	/* does not return */
+
+	return 1;
+}
diff --git a/arch/avr32/lib/interrupts.c b/arch/avr32/lib/interrupts.c
new file mode 100644
index 0000000..bbbc490
--- /dev/null
+++ b/arch/avr32/lib/interrupts.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * 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/sysreg.h>
+
+void enable_interrupts(void)
+{
+	asm volatile("csrf	%0" : : "n"(SYSREG_GM_OFFSET));
+}
+
+int disable_interrupts(void)
+{
+	unsigned long sr;
+
+	sr = sysreg_read(SR);
+	asm volatile("ssrf	%0" : : "n"(SYSREG_GM_OFFSET));
+
+#ifdef CONFIG_AT32UC3A0xxx
+	/* Two NOPs are required after masking interrupts on the
+	 * AT32UC3A0512ES. See errata 41.4.5.5. */
+	asm("nop");
+	asm("nop");
+#endif
+
+	return !SYSREG_BFEXT(GM, sr);
+}
diff --git a/arch/avr32/lib/memset.S b/arch/avr32/lib/memset.S
new file mode 100644
index 0000000..79e3c67
--- /dev/null
+++ b/arch/avr32/lib/memset.S
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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
+ */
+
+	/*
+	 * r12:	void *b
+	 * r11:	int c
+	 * r10:	size_t len
+	 *
+	 * Returns b in r12
+	 */
+	.section .text.memset, "ax", @progbits
+
+	.global	memset
+	.type	memset, @function
+	.align	2
+memset:
+	mov	r9, r12
+	mov	r8, r12
+	or	r11, r11, r11 << 8
+	andl	r9, 3, COH
+	brne	1f
+
+2:	or	r11, r11, r11 << 16
+	sub	r10, 4
+	brlt	5f
+
+	/* Let's do some real work */
+4:	st.w	r8++, r11
+	sub	r10, 4
+	brge	4b
+
+	/*
+	 * When we get here, we've got less than 4 bytes to set. r10
+	 * might be negative.
+	 */
+5:	sub	r10, -4
+	reteq	r12
+
+	/* Fastpath ends here, exactly 32 bytes from memset */
+
+	/* Handle unaligned count or pointer */
+	bld	r10, 1
+	brcc	6f
+	st.b	r8++, r11
+	st.b	r8++, r11
+	bld	r10, 0
+	retcc	r12
+6:	st.b	r8++, r11
+	mov	pc, lr
+
+	/* Handle unaligned pointer */
+1:	sub	r10, 4
+	brlt	5b
+	add	r10, r9
+	lsl	r9, 1
+	add	pc, r9
+	st.b	r8++, r11
+	st.b	r8++, r11
+	st.b	r8++, r11
+	rjmp	2b
+
+	.size	memset, . - memset
diff --git a/arch/blackfin/config.mk b/arch/blackfin/config.mk
new file mode 100644
index 0000000..137834e
--- /dev/null
+++ b/arch/blackfin/config.mk
@@ -0,0 +1,72 @@
+#
+# (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 ?= bfin-uclinux-
+
+STANDALONE_LOAD_ADDR = 0x1000 -m elf32bfin
+
+CONFIG_BFIN_CPU := $(strip $(subst ",,$(CONFIG_BFIN_CPU)))
+CONFIG_BFIN_BOOT_MODE := $(strip $(subst ",,$(CONFIG_BFIN_BOOT_MODE)))
+CONFIG_ENV_OFFSET := $(strip $(subst ",,$(CONFIG_ENV_OFFSET)))
+CONFIG_ENV_SIZE := $(strip $(subst ",,$(CONFIG_ENV_SIZE)))
+
+PLATFORM_RELFLAGS += -ffixed-P3 -fomit-frame-pointer -mno-fdpic
+PLATFORM_CPPFLAGS += -DCONFIG_BLACKFIN
+
+LDFLAGS += --gc-sections -m elf32bfin
+PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
+
+ifneq (,$(CONFIG_BFIN_CPU))
+PLATFORM_RELFLAGS += -mcpu=$(CONFIG_BFIN_CPU)
+endif
+
+ifneq ($(CONFIG_BFIN_BOOT_MODE),BFIN_BOOT_BYPASS)
+ALL += $(obj)u-boot.ldr
+endif
+ifeq ($(CONFIG_ENV_IS_EMBEDDED_IN_LDR),y)
+CREATE_LDR_ENV = $(obj)tools/envcrc --binary > $(obj)env-ldr.o
+else
+CREATE_LDR_ENV =
+endif
+
+SYM_PREFIX = _
+
+LDR_FLAGS-y :=
+LDR_FLAGS-$(CONFIG_BFIN_BOOTROM_USES_EVT1) += -J
+
+LDR_FLAGS += --bmode $(subst BFIN_BOOT_,,$(CONFIG_BFIN_BOOT_MODE))
+LDR_FLAGS += --use-vmas
+LDR_FLAGS += --initcode $(obj)$(CPUDIR)/initcode.o
+ifneq ($(CONFIG_BFIN_BOOT_MODE),BFIN_BOOT_UART)
+LDR_FLAGS-$(CONFIG_ENV_IS_EMBEDDED_IN_LDR) += \
+	--punchit $$(($(CONFIG_ENV_OFFSET))):$$(($(CONFIG_ENV_SIZE))):$(obj)env-ldr.o
+endif
+ifneq (,$(findstring s,$(MAKEFLAGS)))
+LDR_FLAGS += --quiet
+endif
+
+LDR_FLAGS += $(LDR_FLAGS-y)
+
+ifeq ($(wildcard $(TOPDIR)/board/$(BOARD)/u-boot.lds*),)
+LDSCRIPT = $(obj)arch/$(ARCH)/lib/u-boot.lds.S
+endif
diff --git a/arch/blackfin/lib/.gitignore b/arch/blackfin/lib/.gitignore
new file mode 100644
index 0000000..09f1be0
--- /dev/null
+++ b/arch/blackfin/lib/.gitignore
@@ -0,0 +1 @@
+u-boot.lds
diff --git a/arch/blackfin/lib/Makefile b/arch/blackfin/lib/Makefile
new file mode 100644
index 0000000..3bdba75
--- /dev/null
+++ b/arch/blackfin/lib/Makefile
@@ -0,0 +1,65 @@
+#
+# U-boot Makefile
+#
+# Copyright (c) 2005-2008 Analog Devices Inc.
+#
+# (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., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301 USA
+#
+
+include $(TOPDIR)/config.mk
+
+CFLAGS += -DBFIN_BOARD_NAME='"$(BOARD)"'
+
+LIB	= $(obj)lib$(ARCH).a
+
+SOBJS-y	+= ins.o
+SOBJS-y	+= memcmp.o
+SOBJS-y	+= memcpy.o
+SOBJS-y	+= memmove.o
+SOBJS-y	+= memset.o
+SOBJS-y	+= outs.o
+SOBJS-$(CONFIG_CMD_KGDB) += __kgdb.o
+
+COBJS-y	+= board.o
+COBJS-y	+= boot.o
+COBJS-y	+= cache.o
+COBJS-y	+= clocks.o
+COBJS-$(CONFIG_CMD_CACHE_DUMP) += cmd_cache_dump.o
+COBJS-$(CONFIG_CMD_KGDB) += kgdb.o
+COBJS-y	+= muldi3.o
+COBJS-$(CONFIG_POST) += post.o tests.o
+COBJS-y	+= string.o
+
+SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/blackfin/lib/__kgdb.S b/arch/blackfin/lib/__kgdb.S
new file mode 100644
index 0000000..cba4179
--- /dev/null
+++ b/arch/blackfin/lib/__kgdb.S
@@ -0,0 +1,155 @@
+
+#include <asm/linkage.h>
+
+/* save stack context for non-local goto
+ * int kgdb_setjmp(long *buf)
+ */
+
+ENTRY(_kgdb_setjmp)
+	[--SP] = p0; 	/* Save P0 */
+	p0 = r0;
+	r0 = [SP++];	/* Load P0 into R0 */
+
+	[p0 + 0x00] = r0;       /* GP address registers */
+	[p0 + 0x04] = p1;
+	[p0 + 0x08] = p2;
+	[p0 + 0x0C] = p3;
+	[p0 + 0x10] = p4;
+	[p0 + 0x14] = p5;
+	[p0 + 0x18] = FP;       /* frame pointer */
+	[p0 + 0x1C] = SP;       /* stack pointer */
+
+	[p0 + 0x20] = p0;       /* data regs */
+	[p0 + 0x24] = r1;
+	[p0 + 0x28] = r2;
+	[p0 + 0x2C] = r3;
+	[p0 + 0x30] = r4;
+	[p0 + 0x34] = r5;
+	[p0 + 0x38] = r6;
+	[p0 + 0x3C] = r7;
+
+	r0 = ASTAT;	[p0 + 0x40] = r0;
+
+	/* loop counters */
+	r0 = LC0;	[p0 + 0x44] = r0;
+	r0 = LC1;	[p0 + 0x48] = r0;
+
+	/* Accumulator */
+	r0 = A0.w;	[p0 + 0x4C] = r0;
+	r0.l = A0.x;	[p0 + 0x50] = r0;
+	r0 = A1.w;	[p0 + 0x54] = r0;
+	r0.l = A1.x;	[p0 + 0x58] = r0;
+
+	/* index registers */
+	r0 = i0;	[p0 + 0x5C] = r0;
+	r0 = i1;	[p0 + 0x60] = r0;
+	r0 = i2;	[p0 + 0x64] = r0;
+	r0 = i3;	[p0 + 0x68] = r0;
+
+	/* modifier registers */
+	r0 = m0;	[p0 + 0x6C] = r0;
+	r0 = m1;	[p0 + 0x70] = r0;
+	r0 = m2;	[p0 + 0x74] = r0;
+	r0 = m3;	[p0 + 0x78] = r0;
+
+	/* length registers */
+	r0 = l0;	[p0 + 0x7C] = r0;
+	r0 = l1;	[p0 + 0x80] = r0;
+	r0 = l2;	[p0 + 0x84] = r0;
+	r0 = l3;	[p0 + 0x88] = r0;
+
+	/* base registers */
+	r0 = b0;	[p0 + 0x8C] = r0;
+	r0 = b1;	[p0 + 0x90] = r0;
+	r0 = b2;	[p0 + 0x94] = r0;
+	r0 = b3;	[p0 + 0x98] = r0;
+
+	/* store return address */
+	r0 = RETS;	[p0 + 0x9C] = r0;
+
+	R0 = 0;
+	RTS;
+ENDPROC(_kgdb_setjmp)
+
+/*
+ * non-local jump to a saved stack context
+ * longjmp(long *buf, int val)
+ */
+
+ENTRY(_kgdb_longjmp)
+	p0 = r0;
+	r0 = [p0 + 0x00];
+	[--sp] = r0;
+
+	/* GP address registers - skip p0 for now*/
+	p1 = [p0 + 0x04];
+	p2 = [p0 + 0x08];
+	p3 = [p0 + 0x0C];
+	p4 = [p0 + 0x10];
+	p5 = [p0 + 0x14];
+	/* frame pointer */
+	fp = [p0 + 0x18];
+	/* stack pointer */
+	r0 = [sp++];
+	sp = [p0 + 0x1C];
+	[--sp] = r0;
+	[--sp] = r1;
+
+	/* data regs */
+	r0 = [p0 + 0x20];
+	r1 = [p0 + 0x24];
+	r2 = [p0 + 0x28];
+	r3 = [p0 + 0x2C];
+	r4 = [p0 + 0x30];
+	r5 = [p0 + 0x34];
+	r6 = [p0 + 0x38];
+	r7 = [p0 + 0x3C];
+
+	r0 = [p0 + 0x40];	ASTAT = r0;
+
+	/* loop counters */
+	r0 = [p0 + 0x44];	LC0 = r0;
+	r0 = [p0 + 0x48];	LC1 = r0;
+
+	/* Accumulator */
+	r0 = [p0 + 0x4C];	A0.w = r0;
+	r0 = [p0 + 0x50];	A0.x = r0;
+	r0 = [p0 + 0x54];	A1.w = r0;
+	r0 = [p0 + 0x58];	A1.x = r0;
+
+	/* index registers */
+	r0 = [p0 + 0x5C];	i0 = r0;
+	r0 = [p0 + 0x60];	i1 = r0;
+	r0 = [p0 + 0x64];	i2 = r0;
+	r0 = [p0 + 0x68];	i3 = r0;
+
+	/* modifier registers */
+	r0 = [p0 + 0x6C];	m0 = r0;
+	r0 = [p0 + 0x70];	m1 = r0;
+	r0 = [p0 + 0x74];	m2 = r0;
+	r0 = [p0 + 0x78];	m3 = r0;
+
+	/* length registers */
+	r0 = [p0 + 0x7C];	l0 = r0;
+	r0 = [p0 + 0x80];	l1 = r0;
+	r0 = [p0 + 0x84];	l2 = r0;
+	r0 = [p0 + 0x88];	l3 = r0;
+
+	/* base registers */
+	r0 = [p0 + 0x8C];	b0 = r0;
+	r0 = [p0 + 0x90];	b1 = r0;
+	r0 = [p0 + 0x94];	b2 = r0;
+	r0 = [p0 + 0x98];	b3 = r0;
+
+	/* store return address */
+	r0 = [p0 + 0x9C];	RETS = r0;
+
+	/* fixup R0 & P0 */
+	r0 = [sp++];
+	p0 = [sp++];
+	CC = R0 == 0;
+	IF !CC JUMP .Lfinished;
+	R0 = 1;
+.Lfinished:
+	RTS;
+ENDPROC(_kgdb_longjmp)
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
new file mode 100644
index 0000000..4e9bb19
--- /dev/null
+++ b/arch/blackfin/lib/board.c
@@ -0,0 +1,419 @@
+/*
+ * U-boot - board.c First C file to be called contains init routines
+ *
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <stdio_dev.h>
+#include <environment.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <net.h>
+#include <timestamp.h>
+#include <status_led.h>
+#include <version.h>
+
+#include <asm/cplb.h>
+#include <asm/mach-common/bits/mpu.h>
+#include <kgdb.h>
+
+#ifdef CONFIG_CMD_NAND
+#include <nand.h>	/* cannot even include nand.h if it isnt configured */
+#endif
+
+#ifdef CONFIG_BITBANGMII
+#include <miiphy.h>
+#endif
+
+#if defined(CONFIG_POST)
+#include <post.h>
+int post_flag;
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+const char version_string[] = U_BOOT_VERSION " ("U_BOOT_DATE" - "U_BOOT_TIME")";
+
+__attribute__((always_inline))
+static inline void serial_early_puts(const char *s)
+{
+#ifdef CONFIG_DEBUG_EARLY_SERIAL
+	serial_puts("Early: ");
+	serial_puts(s);
+#endif
+}
+
+static int display_banner(void)
+{
+	printf("\n\n%s\n\n", version_string);
+	printf("CPU:   ADSP " MK_STR(CONFIG_BFIN_CPU) " "
+		"(Detected Rev: 0.%d) "
+		"(%s boot)\n",
+		bfin_revid(),
+		get_bfin_boot_mode(CONFIG_BFIN_BOOT_MODE));
+	return 0;
+}
+
+static int init_baudrate(void)
+{
+	char baudrate[15];
+	int i = getenv_r("baudrate", baudrate, sizeof(baudrate));
+	gd->bd->bi_baudrate = gd->baudrate = (i > 0)
+	    ? simple_strtoul(baudrate, NULL, 10)
+	    : CONFIG_BAUDRATE;
+	return 0;
+}
+
+static void display_global_data(void)
+{
+	bd_t *bd;
+
+#ifndef CONFIG_DEBUG_EARLY_SERIAL
+	return;
+#endif
+
+	bd = gd->bd;
+	printf(" gd: %p\n", gd);
+	printf(" |-flags: %lx\n", gd->flags);
+	printf(" |-board_type: %lx\n", gd->board_type);
+	printf(" |-baudrate: %lu\n", gd->baudrate);
+	printf(" |-have_console: %lx\n", gd->have_console);
+	printf(" |-ram_size: %lx\n", gd->ram_size);
+	printf(" |-env_addr: %lx\n", gd->env_addr);
+	printf(" |-env_valid: %lx\n", gd->env_valid);
+	printf(" |-jt(%p): %p\n", gd->jt, *(gd->jt));
+	printf(" \\-bd: %p\n", gd->bd);
+	printf("   |-bi_baudrate: %x\n", bd->bi_baudrate);
+	printf("   |-bi_ip_addr: %lx\n", bd->bi_ip_addr);
+	printf("   |-bi_boot_params: %lx\n", bd->bi_boot_params);
+	printf("   |-bi_memstart: %lx\n", bd->bi_memstart);
+	printf("   |-bi_memsize: %lx\n", bd->bi_memsize);
+	printf("   |-bi_flashstart: %lx\n", bd->bi_flashstart);
+	printf("   |-bi_flashsize: %lx\n", bd->bi_flashsize);
+	printf("   \\-bi_flashoffset: %lx\n", bd->bi_flashoffset);
+}
+
+#define CPLB_PAGE_SIZE (4 * 1024 * 1024)
+#define CPLB_PAGE_MASK (~(CPLB_PAGE_SIZE - 1))
+void init_cplbtables(void)
+{
+	volatile uint32_t *ICPLB_ADDR, *ICPLB_DATA;
+	volatile uint32_t *DCPLB_ADDR, *DCPLB_DATA;
+	uint32_t extern_memory;
+	size_t i;
+
+	void icplb_add(uint32_t addr, uint32_t data)
+	{
+		*(ICPLB_ADDR + i) = addr;
+		*(ICPLB_DATA + i) = data;
+	}
+	void dcplb_add(uint32_t addr, uint32_t data)
+	{
+		*(DCPLB_ADDR + i) = addr;
+		*(DCPLB_DATA + i) = data;
+	}
+
+	/* populate a few common entries ... we'll let
+	 * the memory map and cplb exception handler do
+	 * the rest of the work.
+	 */
+	i = 0;
+	ICPLB_ADDR = (uint32_t *)ICPLB_ADDR0;
+	ICPLB_DATA = (uint32_t *)ICPLB_DATA0;
+	DCPLB_ADDR = (uint32_t *)DCPLB_ADDR0;
+	DCPLB_DATA = (uint32_t *)DCPLB_DATA0;
+
+	icplb_add(0xFFA00000, L1_IMEMORY);
+	dcplb_add(0xFF800000, L1_DMEMORY);
+	++i;
+
+	if (CONFIG_MEM_SIZE) {
+		uint32_t mbase = CONFIG_SYS_MONITOR_BASE;
+		uint32_t mend  = mbase + CONFIG_SYS_MONITOR_LEN;
+		mbase &= CPLB_PAGE_MASK;
+		mend &= CPLB_PAGE_MASK;
+
+		icplb_add(mbase, SDRAM_IKERNEL);
+		dcplb_add(mbase, SDRAM_DKERNEL);
+		++i;
+
+		/*
+		 * If the monitor crosses a 4 meg boundary, we'll need
+		 * to lock two entries for it.  We assume it doesn't
+		 * cross two 4 meg boundaries ...
+		 */
+		if (mbase != mend) {
+			icplb_add(mend, SDRAM_IKERNEL);
+			dcplb_add(mend, SDRAM_DKERNEL);
+			++i;
+		}
+	}
+
+	icplb_add(0x20000000, SDRAM_INON_CHBL);
+	dcplb_add(0x20000000, SDRAM_EBIU);
+	++i;
+
+	/* Add entries for the rest of external RAM up to the bootrom */
+	extern_memory = 0;
+
+#ifdef CONFIG_DEBUG_NULL_PTR
+	icplb_add(extern_memory, (SDRAM_IKERNEL & ~PAGE_SIZE_MASK) | PAGE_SIZE_1KB);
+	dcplb_add(extern_memory, (SDRAM_DKERNEL & ~PAGE_SIZE_MASK) | PAGE_SIZE_1KB);
+	++i;
+	icplb_add(extern_memory, SDRAM_IKERNEL);
+	dcplb_add(extern_memory, SDRAM_DKERNEL);
+	extern_memory += CPLB_PAGE_SIZE;
+	++i;
+#endif
+
+	while (i < 16 && extern_memory < (CONFIG_SYS_MONITOR_BASE & CPLB_PAGE_MASK)) {
+		icplb_add(extern_memory, SDRAM_IGENERIC);
+		dcplb_add(extern_memory, SDRAM_DGENERIC);
+		extern_memory += CPLB_PAGE_SIZE;
+		++i;
+	}
+	while (i < 16) {
+		icplb_add(0, 0);
+		dcplb_add(0, 0);
+		++i;
+	}
+}
+
+/*
+ * 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".
+ */
+
+extern int watchdog_init(void);
+extern int exception_init(void);
+extern int irq_init(void);
+extern int timer_init(void);
+
+void board_init_f(ulong bootflag)
+{
+	ulong addr;
+	bd_t *bd;
+	char buf[32];
+
+#ifdef CONFIG_BOARD_EARLY_INIT_F
+	serial_early_puts("Board early init flash\n");
+	board_early_init_f();
+#endif
+
+	serial_early_puts("Init CPLB tables\n");
+	init_cplbtables();
+
+	serial_early_puts("Exceptions setup\n");
+	exception_init();
+
+#ifndef CONFIG_ICACHE_OFF
+	serial_early_puts("Turn on ICACHE\n");
+	icache_enable();
+#endif
+#ifndef CONFIG_DCACHE_OFF
+	serial_early_puts("Turn on DCACHE\n");
+	dcache_enable();
+#endif
+
+#ifdef CONFIG_WATCHDOG
+	serial_early_puts("Setting up external watchdog\n");
+	watchdog_init();
+#endif
+
+#ifdef DEBUG
+	if (CONFIG_SYS_GBL_DATA_SIZE < sizeof(*gd))
+		hang();
+#endif
+	serial_early_puts("Init global data\n");
+	gd = (gd_t *) (CONFIG_SYS_GBL_DATA_ADDR);
+	memset((void *)gd, 0, CONFIG_SYS_GBL_DATA_SIZE);
+
+	/* Board data initialization */
+	addr = (CONFIG_SYS_GBL_DATA_ADDR + sizeof(gd_t));
+
+	/* Align to 4 byte boundary */
+	addr &= ~(4 - 1);
+	bd = (bd_t *) addr;
+	gd->bd = bd;
+	memset((void *)bd, 0, sizeof(bd_t));
+
+	bd->bi_r_version = version_string;
+	bd->bi_cpu = MK_STR(CONFIG_BFIN_CPU);
+	bd->bi_board_name = BFIN_BOARD_NAME;
+	bd->bi_vco = get_vco();
+	bd->bi_cclk = get_cclk();
+	bd->bi_sclk = get_sclk();
+	bd->bi_memstart = CONFIG_SYS_SDRAM_BASE;
+	bd->bi_memsize = CONFIG_SYS_MAX_RAM_SIZE;
+
+	/* Initialize */
+	serial_early_puts("IRQ init\n");
+	irq_init();
+	serial_early_puts("Environment init\n");
+	env_init();
+	serial_early_puts("Baudrate init\n");
+	init_baudrate();
+	serial_early_puts("Serial init\n");
+	serial_init();
+	serial_early_puts("Console init flash\n");
+	console_init_f();
+	serial_early_puts("End of early debugging\n");
+	display_banner();
+
+	checkboard();
+	timer_init();
+
+	printf("Clock: VCO: %s MHz, ", strmhz(buf, get_vco()));
+	printf("Core: %s MHz, ", strmhz(buf, get_cclk()));
+	printf("System: %s MHz\n", strmhz(buf, get_sclk()));
+
+	printf("RAM:   ");
+	print_size(bd->bi_memsize, "\n");
+#if defined(CONFIG_POST)
+	post_init_f();
+	post_bootmode_init();
+	post_run(NULL, POST_ROM | post_bootmode_get(0));
+#endif
+
+	board_init_r((gd_t *) gd, 0x20000010);
+}
+
+static void board_net_init_r(bd_t *bd)
+{
+#ifdef CONFIG_BITBANGMII
+	bb_miiphy_init();
+#endif
+#ifdef CONFIG_CMD_NET
+	char *s;
+
+	if ((s = getenv("bootfile")) != NULL)
+		copy_filename(BootFile, s, sizeof(BootFile));
+
+	bd->bi_ip_addr = getenv_IPaddr("ipaddr");
+
+	printf("Net:   ");
+	eth_initialize(gd->bd);
+#endif
+}
+
+void board_init_r(gd_t * id, ulong dest_addr)
+{
+	char *s;
+	bd_t *bd;
+	gd = id;
+	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
+	bd = gd->bd;
+
+#if defined(CONFIG_POST)
+	post_output_backlog();
+	post_reloc();
+#endif
+
+	/* initialize malloc() area */
+	mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
+
+#if	!defined(CONFIG_SYS_NO_FLASH)
+	/* Initialize the flash and protect u-boot by default */
+	extern flash_info_t flash_info[];
+	puts("Flash: ");
+	ulong size = flash_init();
+	print_size(size, "\n");
+	flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_FLASH_BASE,
+		CONFIG_SYS_FLASH_BASE + CONFIG_SYS_MONITOR_LEN - 1,
+		&flash_info[0]);
+	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
+	bd->bi_flashsize = size;
+	bd->bi_flashoffset = 0;
+#else
+	bd->bi_flashstart = 0;
+	bd->bi_flashsize = 0;
+	bd->bi_flashoffset = 0;
+#endif
+
+#ifdef CONFIG_CMD_NAND
+	puts("NAND:  ");
+	nand_init();		/* go init the NAND */
+#endif
+
+#ifdef CONFIG_GENERIC_MMC
+	puts("MMC:  ");
+	mmc_initialize(bd);
+#endif
+
+	/* relocate environment function pointers etc. */
+	env_relocate();
+
+	/* Initialize stdio devices */
+	stdio_init();
+	jumptable_init();
+
+	/* Initialize the console (after the relocation and devices init) */
+	console_init_r();
+
+#ifdef CONFIG_CMD_KGDB
+	puts("KGDB:  ");
+	kgdb_init();
+#endif
+
+#ifdef CONFIG_STATUS_LED
+	status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING);
+	status_led_set(STATUS_LED_CRASH, STATUS_LED_OFF);
+#endif
+
+	/* Initialize from environment */
+	if ((s = getenv("loadaddr")) != NULL)
+		load_addr = simple_strtoul(s, NULL, 16);
+
+#if defined(CONFIG_MISC_INIT_R)
+	/* miscellaneous platform dependent initialisations */
+	misc_init_r();
+#endif
+
+	board_net_init_r(bd);
+
+	display_global_data();
+
+#if defined(CONFIG_POST)
+	if (post_flag)
+		post_run(NULL, POST_RAM | post_bootmode_get(0));
+#endif
+
+	if (bfin_os_log_check()) {
+		puts("\nLog buffer from operating system:\n");
+		bfin_os_log_dump();
+		puts("\n");
+	}
+
+	/* main_loop() can return to retry autoboot, if so just run it again. */
+	for (;;)
+		main_loop();
+}
+
+void hang(void)
+{
+#ifdef CONFIG_STATUS_LED
+	status_led_set(STATUS_LED_BOOT, STATUS_LED_OFF);
+	status_led_set(STATUS_LED_CRASH, STATUS_LED_BLINKING);
+#endif
+	puts("### ERROR ### Please RESET the board ###\n");
+	while (1)
+		/* If a JTAG emulator is hooked up, we'll automatically trigger
+		 * a breakpoint in it.  If one isn't, this is just a NOP.
+		 */
+		asm("emuexcpt;");
+}
diff --git a/arch/blackfin/lib/boot.c b/arch/blackfin/lib/boot.c
new file mode 100644
index 0000000..951d5b0
--- /dev/null
+++ b/arch/blackfin/lib/boot.c
@@ -0,0 +1,63 @@
+/*
+ * U-boot - boot.c - misc boot helper functions
+ *
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <image.h>
+#include <asm/blackfin.h>
+
+#ifdef SHARED_RESOURCES
+extern void swap_to(int device_id);
+#endif
+
+static char *make_command_line(void)
+{
+	char *dest = (char *)CONFIG_LINUX_CMDLINE_ADDR;
+	char *bootargs = getenv("bootargs");
+
+	if (bootargs == NULL)
+		return NULL;
+
+	strncpy(dest, bootargs, CONFIG_LINUX_CMDLINE_SIZE);
+	dest[CONFIG_LINUX_CMDLINE_SIZE - 1] = 0;
+	return dest;
+}
+
+extern ulong bfin_poweron_retx;
+
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	int	(*appl) (char *cmdline);
+	char	*cmdline;
+
+	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+		return 1;
+
+#ifdef SHARED_RESOURCES
+	swap_to(FLASH);
+#endif
+
+	appl = (int (*)(char *))images->ep;
+
+	printf("Starting Kernel at = %p\n", appl);
+	cmdline = make_command_line();
+	icache_disable();
+	dcache_disable();
+	asm __volatile__(
+		"RETX = %[retx];"
+		"CALL (%0);"
+		:
+		: "p"(appl), "q0"(cmdline), [retx] "d"(bfin_poweron_retx)
+	);
+	/* does not return */
+
+	return 1;
+}
diff --git a/arch/blackfin/lib/cache.c b/arch/blackfin/lib/cache.c
new file mode 100644
index 0000000..0a321a4
--- /dev/null
+++ b/arch/blackfin/lib/cache.c
@@ -0,0 +1,113 @@
+/*
+ * U-boot - cache.c
+ *
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <asm/blackfin.h>
+#include <asm/mach-common/bits/mpu.h>
+
+void flush_cache(unsigned long addr, unsigned long size)
+{
+	void *start_addr, *end_addr;
+	int istatus, dstatus;
+
+	/* no need to flush stuff in on chip memory (L1/L2/etc...) */
+	if (addr >= 0xE0000000)
+		return;
+
+	start_addr = (void *)addr;
+	end_addr = (void *)(addr + size);
+	istatus = icache_status();
+	dstatus = dcache_status();
+
+	if (istatus) {
+		if (dstatus)
+			blackfin_icache_dcache_flush_range(start_addr, end_addr);
+		else
+			blackfin_icache_flush_range(start_addr, end_addr);
+	} else if (dstatus)
+		blackfin_dcache_flush_range(start_addr, end_addr);
+}
+
+#ifdef CONFIG_DCACHE_WB
+static void flushinv_all_dcache(void)
+{
+	u32 way, bank, subbank, set;
+	u32 status, addr;
+	u32 dmem_ctl = bfin_read_DMEM_CONTROL();
+
+	for (bank = 0; bank < 2; ++bank) {
+		if (!(dmem_ctl & (1 << (DMC1_P - bank))))
+			continue;
+
+		for (way = 0; way < 2; ++way)
+			for (subbank = 0; subbank < 4; ++subbank)
+				for (set = 0; set < 64; ++set) {
+
+					bfin_write_DTEST_COMMAND(
+						way << 26 |
+						bank << 23 |
+						subbank << 16 |
+						set << 5
+					);
+					CSYNC();
+					status = bfin_read_DTEST_DATA0();
+
+					/* only worry about valid/dirty entries */
+					if ((status & 0x3) != 0x3)
+						continue;
+
+					/* construct the address using the tag */
+					addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5);
+
+					/* flush it */
+					__asm__ __volatile__("FLUSHINV[%0];" : : "a"(addr));
+				}
+	}
+}
+#endif
+
+void icache_enable(void)
+{
+	bfin_write_IMEM_CONTROL(IMC | ENICPLB);
+	SSYNC();
+}
+
+void icache_disable(void)
+{
+	bfin_write_IMEM_CONTROL(0);
+	SSYNC();
+}
+
+int icache_status(void)
+{
+	return bfin_read_IMEM_CONTROL() & IMC;
+}
+
+void dcache_enable(void)
+{
+	bfin_write_DMEM_CONTROL(ACACHE_BCACHE | ENDCPLB | PORT_PREF0);
+	SSYNC();
+}
+
+void dcache_disable(void)
+{
+#ifdef CONFIG_DCACHE_WB
+	bfin_write_DMEM_CONTROL(bfin_read_DMEM_CONTROL() & ~(ENDCPLB));
+	flushinv_all_dcache();
+#endif
+	bfin_write_DMEM_CONTROL(0);
+	SSYNC();
+}
+
+int dcache_status(void)
+{
+	return bfin_read_DMEM_CONTROL() & ACACHE_BCACHE;
+}
diff --git a/arch/blackfin/lib/clocks.c b/arch/blackfin/lib/clocks.c
new file mode 100644
index 0000000..0be395b
--- /dev/null
+++ b/arch/blackfin/lib/clocks.c
@@ -0,0 +1,77 @@
+/*
+ * clocks.c - figure out sclk/cclk/vco and such
+ *
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <asm/blackfin.h>
+
+/* Get the voltage input multiplier */
+static u_long cached_vco_pll_ctl, cached_vco;
+u_long get_vco(void)
+{
+	u_long msel;
+
+	u_long pll_ctl = bfin_read_PLL_CTL();
+	if (pll_ctl == cached_vco_pll_ctl)
+		return cached_vco;
+	else
+		cached_vco_pll_ctl = pll_ctl;
+
+	msel = (pll_ctl >> 9) & 0x3F;
+	if (0 == msel)
+		msel = 64;
+
+	cached_vco = CONFIG_CLKIN_HZ;
+	cached_vco >>= (1 & pll_ctl);	/* DF bit */
+	cached_vco *= msel;
+	return cached_vco;
+}
+
+/* Get the Core clock */
+static u_long cached_cclk_pll_div, cached_cclk;
+u_long get_cclk(void)
+{
+	u_long csel, ssel;
+
+	if (bfin_read_PLL_STAT() & 0x1)
+		return CONFIG_CLKIN_HZ;
+
+	ssel = bfin_read_PLL_DIV();
+	if (ssel == cached_cclk_pll_div)
+		return cached_cclk;
+	else
+		cached_cclk_pll_div = ssel;
+
+	csel = ((ssel >> 4) & 0x03);
+	ssel &= 0xf;
+	if (ssel && ssel < (1 << csel))	/* SCLK > CCLK */
+		cached_cclk = get_vco() / ssel;
+	else
+		cached_cclk = get_vco() >> csel;
+	return cached_cclk;
+}
+
+/* Get the System clock */
+static u_long cached_sclk_pll_div, cached_sclk;
+u_long get_sclk(void)
+{
+	u_long ssel;
+
+	if (bfin_read_PLL_STAT() & 0x1)
+		return CONFIG_CLKIN_HZ;
+
+	ssel = bfin_read_PLL_DIV();
+	if (ssel == cached_sclk_pll_div)
+		return cached_sclk;
+	else
+		cached_sclk_pll_div = ssel;
+
+	ssel &= 0xf;
+
+	cached_sclk = get_vco() / ssel;
+	return cached_sclk;
+}
diff --git a/arch/blackfin/lib/cmd_cache_dump.c b/arch/blackfin/lib/cmd_cache_dump.c
new file mode 100644
index 0000000..de5840e
--- /dev/null
+++ b/arch/blackfin/lib/cmd_cache_dump.c
@@ -0,0 +1,145 @@
+/*
+ * U-boot - cmd_cache_dump.c
+ *
+ * Copyright (c) 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+
+#include <asm/blackfin.h>
+#include <asm/mach-common/bits/mpu.h>
+
+static int check_limit(const char *type, size_t start_limit, size_t end_limit, size_t start, size_t end)
+{
+	if (start >= start_limit && start <= end_limit && \
+	    end <= end_limit && end >= start_limit && \
+	    start <= end)
+		return 0;
+
+	printf("%s limit violation: %zu <= (user:%zu) <= (user:%zu) <= %zu\n",
+		type, start_limit, start, end, end_limit);
+	return 1;
+}
+
+int do_icache_dump(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	int cache_status = icache_status();
+
+	if (cache_status)
+		icache_disable();
+
+	uint32_t cmd_base, tag, cache_upper, cache_lower;
+
+	size_t way, way_start = 0, way_end = 3;
+	size_t sbnk, sbnk_start = 0, sbnk_end = 3;
+	size_t set, set_start = 0, set_end = 31;
+	size_t dw;
+
+	if (argc > 1) {
+		way_start = way_end = simple_strtoul(argv[1], NULL, 10);
+		if (argc > 2) {
+			sbnk_start = sbnk_end = simple_strtoul(argv[2], NULL, 10);
+			if (argc > 3)
+				set_start = set_end = simple_strtoul(argv[3], NULL, 10);
+		}
+	}
+
+	if (check_limit("way", 0, 3, way_start, way_end) || \
+	    check_limit("subbank", 0, 3, sbnk_start, sbnk_end) || \
+	    check_limit("set", 0, 31, set_start, set_end))
+		return 1;
+
+	puts("Way:Subbank:Set: [valid-tag lower upper] {invalid-tag lower upper}...\n");
+
+	for (way = way_start; way <= way_end; ++way) {
+		for (sbnk = sbnk_start; sbnk <= sbnk_end; ++sbnk) {
+			for (set = set_start; set <= set_end; ++set) {
+				printf("%zu:%zu:%2zu: ", way, sbnk, set);
+				for (dw = 0; dw < 4; ++dw) {
+					if (ctrlc())
+						return 1;
+
+					cmd_base = \
+						(way  << 26) | \
+						(sbnk << 16) | \
+						(set  <<  5) | \
+						(dw   <<  3);
+
+					/* first read the tag */
+					bfin_write_ITEST_COMMAND(cmd_base | 0x0);
+					SSYNC();
+					tag = bfin_read_ITEST_DATA0();
+					printf("%c%08x ", (tag & 0x1 ? ' ' : '{'), tag);
+
+					/* grab the data at this loc */
+					bfin_write_ITEST_COMMAND(cmd_base | 0x4);
+					SSYNC();
+					cache_lower = bfin_read_ITEST_DATA0();
+					cache_upper = bfin_read_ITEST_DATA1();
+					printf("%08x %08x%c ", cache_lower, cache_upper, (tag & 0x1 ? ' ' : '}'));
+				}
+				puts("\n");
+			}
+		}
+	}
+
+	if (cache_status)
+		icache_enable();
+
+	return 0;
+}
+
+U_BOOT_CMD(icache_dump, 4, 0, do_icache_dump,
+	"icache_dump - dump current instruction cache\n",
+	"[way] [subbank] [set]");
+
+int do_dcache_dump(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	u32 way, bank, subbank, set;
+	u32 status, addr;
+	u32 dmem_ctl = bfin_read_DMEM_CONTROL();
+
+	for (bank = 0; bank < 2; ++bank) {
+		if (!(dmem_ctl & (1 << (DMC1_P - bank))))
+			continue;
+
+		for (way = 0; way < 2; ++way)
+			for (subbank = 0; subbank < 4; ++subbank) {
+				printf("%i:%i:%i:\t", bank, way, subbank);
+				for (set = 0; set < 64; ++set) {
+
+					if (ctrlc())
+						return 1;
+
+					/* retrieve a cache tag */
+					bfin_write_DTEST_COMMAND(
+						way << 26 |
+						bank << 23 |
+						subbank << 16 |
+						set << 5
+					);
+					CSYNC();
+					status = bfin_read_DTEST_DATA0();
+
+					/* construct the address using the tag */
+					addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5);
+
+					/* show it */
+					if (set && !(set % 4))
+						puts("\n\t");
+					printf("%c%08x%c%08x%c ", (status & 0x1 ? '[' : '{'), status, (status & 0x2 ? 'd' : ' '), addr, (status & 0x1 ? ']' : '}'));
+				}
+				puts("\n");
+			}
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(dcache_dump, 4, 0, do_dcache_dump,
+	"dcache_dump - dump current data cache\n",
+	"[bank] [way] [subbank] [set]");
diff --git a/arch/blackfin/lib/ins.S b/arch/blackfin/lib/ins.S
new file mode 100644
index 0000000..4519596
--- /dev/null
+++ b/arch/blackfin/lib/ins.S
@@ -0,0 +1,117 @@
+/*
+ * arch/blackfin/lib/ins.S - ins{bwl} using hardware loops
+ *
+ * Copyright 2004-2008 Analog Devices Inc.
+ * Copyright (C) 2005 Bas Vermeulen, BuyWays BV <bas@buyways.nl>
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <asm/blackfin.h>
+
+.align 2
+
+#ifdef CONFIG_IPIPE
+# define DO_CLI \
+	[--sp] = rets; \
+	[--sp] = (P5:0); \
+	sp += -12; \
+	call ___ipipe_disable_root_irqs_hw; \
+	sp += 12; \
+	(P5:0) = [sp++];
+# define CLI_INNER_NOP
+#else
+# define DO_CLI cli R3;
+# define CLI_INNER_NOP nop; nop; nop;
+#endif
+
+#ifdef CONFIG_IPIPE
+# define DO_STI \
+	sp += -12; \
+	call ___ipipe_enable_root_irqs_hw; \
+	sp += 12; \
+2:	rets = [sp++];
+#else
+# define DO_STI 2: sti R3;
+#endif
+
+#ifdef CONFIG_BFIN_INS_LOWOVERHEAD
+# define CLI_OUTER DO_CLI;
+# define STI_OUTER DO_STI;
+# define CLI_INNER 1:
+# if ANOMALY_05000416
+#  define STI_INNER nop; 2: nop;
+# else
+#  define STI_INNER 2:
+# endif
+#else
+# define CLI_OUTER
+# define STI_OUTER
+# define CLI_INNER 1: DO_CLI; CLI_INNER_NOP;
+# define STI_INNER DO_STI;
+#endif
+
+/*
+ * Reads on the Blackfin are speculative. In Blackfin terms, this means they
+ * can be interrupted at any time (even after they have been issued on to the
+ * external bus), and re-issued after the interrupt occurs.
+ *
+ * If a FIFO is sitting on the end of the read, it will see two reads,
+ * when the core only sees one. The FIFO receives the read which is cancelled,
+ * and not delivered to the core.
+ *
+ * To solve this, interrupts are turned off before reads occur to I/O space.
+ * There are 3 versions of all these functions
+ *  - turns interrupts off every read (higher overhead, but lower latency)
+ *  - turns interrupts off every loop (low overhead, but longer latency)
+ *  - DMA version, which do not suffer from this issue. DMA versions have
+ *      different name (prefixed by dma_ ), and are located in
+ *      ../kernel/bfin_dma_5xx.c
+ * Using the dma related functions are recommended for transfering large
+ * buffers in/out of FIFOs.
+ */
+
+#define COMMON_INS(func, ops) \
+ENTRY(_ins##func) \
+	P0 = R0;	/* P0 = port */ \
+	CLI_OUTER;	/* 3 instructions before first read access */ \
+	P1 = R1;	/* P1 = address */ \
+	P2 = R2;	/* P2 = count */ \
+	SSYNC; \
+ \
+	LSETUP(1f, 2f) LC0 = P2; \
+	CLI_INNER; \
+	ops; \
+	STI_INNER; \
+ \
+	STI_OUTER; \
+	RTS; \
+ENDPROC(_ins##func)
+
+COMMON_INS(l, \
+	R0 = [P0]; \
+	[P1++] = R0; \
+)
+
+COMMON_INS(w, \
+	R0 = W[P0]; \
+	W[P1++] = R0; \
+)
+
+COMMON_INS(w_8, \
+	R0 = W[P0]; \
+	B[P1++] = R0; \
+	R0 = R0 >> 8; \
+	B[P1++] = R0; \
+)
+
+COMMON_INS(b, \
+	R0 = B[P0]; \
+	B[P1++] = R0; \
+)
+
+COMMON_INS(l_16, \
+	R0 = [P0]; \
+	W[P1++] = R0; \
+	R0 = R0 >> 16; \
+	W[P1++] = R0; \
+)
diff --git a/arch/blackfin/lib/kgdb.c b/arch/blackfin/lib/kgdb.c
new file mode 100644
index 0000000..bd62d71
--- /dev/null
+++ b/arch/blackfin/lib/kgdb.c
@@ -0,0 +1,423 @@
+/*
+ * U-boot - architecture specific kgdb code
+ *
+ * Copyright 2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <command.h>
+
+#include <kgdb.h>
+#include <asm/processor.h>
+#include <asm/mach-common/bits/core.h>
+#include "kgdb.h"
+#include <asm/deferred.h>
+#include <asm/traps.h>
+#include <asm/signal.h>
+
+void kgdb_enter(struct pt_regs *regs, kgdb_data *kdp)
+{
+	/* disable interrupts */
+	disable_interrupts();
+
+	/* reply to host that an exception has occurred */
+	kdp->sigval = kgdb_trap(regs);
+
+	/* send the PC and the Stack Pointer */
+	kdp->nregs = 2;
+	kdp->regs[0].num = BFIN_PC;
+	kdp->regs[0].val = regs->pc;
+
+	kdp->regs[1].num = BFIN_SP;
+	kdp->regs[1].val = (unsigned long)regs;
+
+}
+
+void kgdb_exit(struct pt_regs *regs, kgdb_data *kdp)
+{
+	if (kdp->extype & KGDBEXIT_WITHADDR)
+		printf("KGDBEXIT_WITHADDR\n");
+
+	switch (kdp->extype & KGDBEXIT_TYPEMASK) {
+	case KGDBEXIT_KILL:
+		printf("KGDBEXIT_KILL:\n");
+		break;
+	case KGDBEXIT_CONTINUE:
+		/* Make sure the supervisor single step bit is clear */
+		regs->syscfg &= ~1;
+		break;
+	case KGDBEXIT_SINGLE:
+		/* set the supervisor single step bit */
+		regs->syscfg |= 1;
+		break;
+	default:
+		printf("KGDBEXIT : %d\n", kdp->extype);
+	}
+
+	/* enable interrupts */
+	enable_interrupts();
+}
+
+int kgdb_trap(struct pt_regs *regs)
+{
+	/* ipend doesn't get filled in properly */
+	switch (regs->seqstat & EXCAUSE) {
+	case VEC_EXCPT01:
+		return SIGTRAP;
+	case VEC_EXCPT03:
+		return SIGSEGV;
+	case VEC_EXCPT02:
+		return SIGTRAP;
+	case VEC_EXCPT04 ... VEC_EXCPT15:
+		return SIGILL;
+	case VEC_STEP:
+		return SIGTRAP;
+	case VEC_OVFLOW:
+		return SIGTRAP;
+	case VEC_UNDEF_I:
+		return SIGILL;
+	case VEC_ILGAL_I:
+		return SIGILL;
+	case VEC_CPLB_VL:
+		return SIGSEGV;
+	case VEC_MISALI_D:
+		return SIGBUS;
+	case VEC_UNCOV:
+		return SIGILL;
+	case VEC_CPLB_MHIT:
+		return SIGSEGV;
+	case VEC_MISALI_I:
+		return SIGBUS;
+	case VEC_CPLB_I_VL:
+		return SIGBUS;
+	case VEC_CPLB_I_MHIT:
+		return SIGSEGV;
+	default:
+		return SIGBUS;
+	}
+}
+
+/*
+ * getregs - gets the pt_regs, and gives them to kgdb's buffer
+ */
+int kgdb_getregs(struct pt_regs *regs, char *buf, int max)
+{
+	unsigned long *gdb_regs = (unsigned long *)buf;
+
+	if (max < NUMREGBYTES)
+		kgdb_error(KGDBERR_NOSPACE);
+
+	if ((unsigned long)gdb_regs & 3)
+		kgdb_error(KGDBERR_ALIGNFAULT);
+
+	gdb_regs[BFIN_R0] = regs->r0;
+	gdb_regs[BFIN_R1] = regs->r1;
+	gdb_regs[BFIN_R2] = regs->r2;
+	gdb_regs[BFIN_R3] = regs->r3;
+	gdb_regs[BFIN_R4] = regs->r4;
+	gdb_regs[BFIN_R5] = regs->r5;
+	gdb_regs[BFIN_R6] = regs->r6;
+	gdb_regs[BFIN_R7] = regs->r7;
+	gdb_regs[BFIN_P0] = regs->p0;
+	gdb_regs[BFIN_P1] = regs->p1;
+	gdb_regs[BFIN_P2] = regs->p2;
+	gdb_regs[BFIN_P3] = regs->p3;
+	gdb_regs[BFIN_P4] = regs->p4;
+	gdb_regs[BFIN_P5] = regs->p5;
+	gdb_regs[BFIN_SP] = (unsigned long)regs;
+	gdb_regs[BFIN_FP] = regs->fp;
+	gdb_regs[BFIN_I0] = regs->i0;
+	gdb_regs[BFIN_I1] = regs->i1;
+	gdb_regs[BFIN_I2] = regs->i2;
+	gdb_regs[BFIN_I3] = regs->i3;
+	gdb_regs[BFIN_M0] = regs->m0;
+	gdb_regs[BFIN_M1] = regs->m1;
+	gdb_regs[BFIN_M2] = regs->m2;
+	gdb_regs[BFIN_M3] = regs->m3;
+	gdb_regs[BFIN_B0] = regs->b0;
+	gdb_regs[BFIN_B1] = regs->b1;
+	gdb_regs[BFIN_B2] = regs->b2;
+	gdb_regs[BFIN_B3] = regs->b3;
+	gdb_regs[BFIN_L0] = regs->l0;
+	gdb_regs[BFIN_L1] = regs->l1;
+	gdb_regs[BFIN_L2] = regs->l2;
+	gdb_regs[BFIN_L3] = regs->l3;
+	gdb_regs[BFIN_A0_DOT_X] = regs->a0x;
+	gdb_regs[BFIN_A0_DOT_W] = regs->a0w;
+	gdb_regs[BFIN_A1_DOT_X] = regs->a1x;
+	gdb_regs[BFIN_A1_DOT_W] = regs->a1w;
+	gdb_regs[BFIN_ASTAT] = regs->astat;
+	gdb_regs[BFIN_RETS] = regs->rets;
+	gdb_regs[BFIN_LC0] = regs->lc0;
+	gdb_regs[BFIN_LT0] = regs->lt0;
+	gdb_regs[BFIN_LB0] = regs->lb0;
+	gdb_regs[BFIN_LC1] = regs->lc1;
+	gdb_regs[BFIN_LT1] = regs->lt1;
+	gdb_regs[BFIN_LB1] = regs->lb1;
+	gdb_regs[BFIN_CYCLES] = 0;
+	gdb_regs[BFIN_CYCLES2] = 0;
+	gdb_regs[BFIN_USP] = regs->usp;
+	gdb_regs[BFIN_SEQSTAT] = regs->seqstat;
+	gdb_regs[BFIN_SYSCFG] = regs->syscfg;
+	gdb_regs[BFIN_RETI] = regs->pc;
+	gdb_regs[BFIN_RETX] = regs->retx;
+	gdb_regs[BFIN_RETN] = regs->retn;
+	gdb_regs[BFIN_RETE] = regs->rete;
+	gdb_regs[BFIN_PC] = regs->pc;
+	gdb_regs[BFIN_CC] = 0;
+	gdb_regs[BFIN_EXTRA1] = 0;
+	gdb_regs[BFIN_EXTRA2] = 0;
+	gdb_regs[BFIN_EXTRA3] = 0;
+	gdb_regs[BFIN_IPEND] = regs->ipend;
+
+	return NUMREGBYTES;
+}
+
+/*
+ * putreg - put kgdb's reg (regno) into the pt_regs
+ */
+void kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length)
+{
+	unsigned long *ptr = (unsigned long *)buf;
+
+	if (regno < 0 || regno > BFIN_NUM_REGS)
+		kgdb_error(KGDBERR_BADPARAMS);
+
+	if (length < 4)
+		kgdb_error(KGDBERR_NOSPACE);
+
+	if ((unsigned long)ptr & 3)
+		kgdb_error(KGDBERR_ALIGNFAULT);
+
+	switch (regno) {
+	case BFIN_R0:
+		regs->r0 = *ptr;
+		break;
+	case BFIN_R1:
+		regs->r1 = *ptr;
+		break;
+	case BFIN_R2:
+		regs->r2 = *ptr;
+		break;
+	case BFIN_R3:
+		regs->r3 = *ptr;
+		break;
+	case BFIN_R4:
+		regs->r4 = *ptr;
+		break;
+	case BFIN_R5:
+		regs->r5 = *ptr;
+		break;
+	case BFIN_R6:
+		regs->r6 = *ptr;
+		break;
+	case BFIN_R7:
+		regs->r7 = *ptr;
+		break;
+	case BFIN_P0:
+		regs->p0 = *ptr;
+		break;
+	case BFIN_P1:
+		regs->p1 = *ptr;
+		break;
+	case BFIN_P2:
+		regs->p2 = *ptr;
+		break;
+	case BFIN_P3:
+		regs->p3 = *ptr;
+		break;
+	case BFIN_P4:
+		regs->p4 = *ptr;
+		break;
+	case BFIN_P5:
+		regs->p5 = *ptr;
+		break;
+	case BFIN_SP:
+		regs->reserved = *ptr;
+		break;
+	case BFIN_FP:
+		regs->fp = *ptr;
+		break;
+	case BFIN_I0:
+		regs->i0 = *ptr;
+		break;
+	case BFIN_I1:
+		regs->i1 = *ptr;
+		break;
+	case BFIN_I2:
+		regs->i2 = *ptr;
+		break;
+	case BFIN_I3:
+		regs->i3 = *ptr;
+		break;
+	case BFIN_M0:
+		regs->m0 = *ptr;
+		break;
+	case BFIN_M1:
+		regs->m1 = *ptr;
+		break;
+	case BFIN_M2:
+		regs->m2 = *ptr;
+		break;
+	case BFIN_M3:
+		regs->m3 = *ptr;
+		break;
+	case BFIN_B0:
+		regs->b0 = *ptr;
+		break;
+	case BFIN_B1:
+		regs->b1 = *ptr;
+		break;
+	case BFIN_B2:
+		regs->b2 = *ptr;
+		break;
+	case BFIN_B3:
+		regs->b3 = *ptr;
+		break;
+	case BFIN_L0:
+		regs->l0 = *ptr;
+		break;
+	case BFIN_L1:
+		regs->l1 = *ptr;
+		break;
+	case BFIN_L2:
+		regs->l2 = *ptr;
+		break;
+	case BFIN_L3:
+		regs->l3 = *ptr;
+		break;
+	case BFIN_A0_DOT_X:
+		regs->a0x = *ptr;
+		break;
+	case BFIN_A0_DOT_W:
+		regs->a0w = *ptr;
+		break;
+	case BFIN_A1_DOT_X:
+		regs->a1x = *ptr;
+		break;
+	case BFIN_A1_DOT_W:
+		regs->a1w = *ptr;
+		break;
+	case BFIN_ASTAT:
+		regs->astat = *ptr;
+		break;
+	case BFIN_RETS:
+		regs->rets = *ptr;
+		break;
+	case BFIN_LC0:
+		regs->lc0 = *ptr;
+		break;
+	case BFIN_LT0:
+		regs->lt0 = *ptr;
+		break;
+	case BFIN_LB0:
+		regs->lb0 = *ptr;
+		break;
+	case BFIN_LC1:
+		regs->lc1 = *ptr;
+		break;
+	case BFIN_LT1:
+		regs->lt1 = *ptr;
+		break;
+	case BFIN_LB1:
+		regs->lb1 = *ptr;
+		break;
+/*
+  BFIN_CYCLES,
+  BFIN_CYCLES2,
+  BFIN_USP,
+  BFIN_SEQSTAT,
+  BFIN_SYSCFG,
+*/
+	case BFIN_RETX:
+		regs->retx = *ptr;
+		break;
+	case BFIN_RETN:
+		regs->retn = *ptr;
+		break;
+	case BFIN_RETE:
+		regs->rete = *ptr;
+		break;
+	case BFIN_PC:
+		regs->pc = *ptr;
+		break;
+
+	default:
+		kgdb_error(KGDBERR_BADPARAMS);
+	}
+}
+
+void kgdb_putregs(struct pt_regs *regs, char *buf, int length)
+{
+	unsigned long *gdb_regs = (unsigned long *)buf;
+
+	if (length != BFIN_NUM_REGS)
+		kgdb_error(KGDBERR_NOSPACE);
+
+	if ((unsigned long)gdb_regs & 3)
+		kgdb_error(KGDBERR_ALIGNFAULT);
+
+	regs->r0 = gdb_regs[BFIN_R0];
+	regs->r1 = gdb_regs[BFIN_R1];
+	regs->r2 = gdb_regs[BFIN_R2];
+	regs->r3 = gdb_regs[BFIN_R3];
+	regs->r4 = gdb_regs[BFIN_R4];
+	regs->r5 = gdb_regs[BFIN_R5];
+	regs->r6 = gdb_regs[BFIN_R6];
+	regs->r7 = gdb_regs[BFIN_R7];
+	regs->p0 = gdb_regs[BFIN_P0];
+	regs->p1 = gdb_regs[BFIN_P1];
+	regs->p2 = gdb_regs[BFIN_P2];
+	regs->p3 = gdb_regs[BFIN_P3];
+	regs->p4 = gdb_regs[BFIN_P4];
+	regs->p5 = gdb_regs[BFIN_P5];
+	regs->fp = gdb_regs[BFIN_FP];
+/*	regs->sp = gdb_regs[BFIN_ ]; */
+	regs->i0 = gdb_regs[BFIN_I0];
+	regs->i1 = gdb_regs[BFIN_I1];
+	regs->i2 = gdb_regs[BFIN_I2];
+	regs->i3 = gdb_regs[BFIN_I3];
+	regs->m0 = gdb_regs[BFIN_M0];
+	regs->m1 = gdb_regs[BFIN_M1];
+	regs->m2 = gdb_regs[BFIN_M2];
+	regs->m3 = gdb_regs[BFIN_M3];
+	regs->b0 = gdb_regs[BFIN_B0];
+	regs->b1 = gdb_regs[BFIN_B1];
+	regs->b2 = gdb_regs[BFIN_B2];
+	regs->b3 = gdb_regs[BFIN_B3];
+	regs->l0 = gdb_regs[BFIN_L0];
+	regs->l1 = gdb_regs[BFIN_L1];
+	regs->l2 = gdb_regs[BFIN_L2];
+	regs->l3 = gdb_regs[BFIN_L3];
+	regs->a0x = gdb_regs[BFIN_A0_DOT_X];
+	regs->a0w = gdb_regs[BFIN_A0_DOT_W];
+	regs->a1x = gdb_regs[BFIN_A1_DOT_X];
+	regs->a1w = gdb_regs[BFIN_A1_DOT_W];
+	regs->rets = gdb_regs[BFIN_RETS];
+	regs->lc0 = gdb_regs[BFIN_LC0];
+	regs->lt0 = gdb_regs[BFIN_LT0];
+	regs->lb0 = gdb_regs[BFIN_LB0];
+	regs->lc1 = gdb_regs[BFIN_LC1];
+	regs->lt1 = gdb_regs[BFIN_LT1];
+	regs->lb1 = gdb_regs[BFIN_LB1];
+	regs->usp = gdb_regs[BFIN_USP];
+	regs->syscfg = gdb_regs[BFIN_SYSCFG];
+	regs->retx = gdb_regs[BFIN_PC];
+	regs->retn = gdb_regs[BFIN_RETN];
+	regs->rete = gdb_regs[BFIN_RETE];
+	regs->pc = gdb_regs[BFIN_PC];
+
+#if 0	/* can't change these */
+	regs->astat = gdb_regs[BFIN_ASTAT];
+	regs->seqstat = gdb_regs[BFIN_SEQSTAT];
+	regs->ipend = gdb_regs[BFIN_IPEND];
+#endif
+
+}
+
+void kgdb_breakpoint(int argc, char *argv[])
+{
+	asm volatile ("excpt 0x1\n");
+}
diff --git a/arch/blackfin/lib/kgdb.h b/arch/blackfin/lib/kgdb.h
new file mode 100644
index 0000000..18f1f49
--- /dev/null
+++ b/arch/blackfin/lib/kgdb.h
@@ -0,0 +1,160 @@
+/* Blackfin KGDB header
+ *
+ * Copyright 2005-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __ASM_BLACKFIN_KGDB_H__
+#define __ASM_BLACKFIN_KGDB_H__
+
+/* gdb locks */
+#define KGDB_MAX_NO_CPUS 8
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers.
+ * At least NUMREGBYTES*2 are needed for register packets.
+ * Longer buffer is needed to list all threads.
+ */
+#define BUFMAX 2048
+
+enum regnames {
+  /* Core Registers */
+  BFIN_R0 = 0,
+  BFIN_R1,
+  BFIN_R2,
+  BFIN_R3,
+  BFIN_R4,
+  BFIN_R5,
+  BFIN_R6,
+  BFIN_R7,
+  BFIN_P0,
+  BFIN_P1,
+  BFIN_P2,
+  BFIN_P3,
+  BFIN_P4,
+  BFIN_P5,
+  BFIN_SP,
+  BFIN_FP,
+  BFIN_I0,
+  BFIN_I1,
+  BFIN_I2,
+  BFIN_I3,
+  BFIN_M0,
+  BFIN_M1,
+  BFIN_M2,
+  BFIN_M3,
+  BFIN_B0,
+  BFIN_B1,
+  BFIN_B2,
+  BFIN_B3,
+  BFIN_L0,
+  BFIN_L1,
+  BFIN_L2,
+  BFIN_L3,
+  BFIN_A0_DOT_X,
+  BFIN_A0_DOT_W,
+  BFIN_A1_DOT_X,
+  BFIN_A1_DOT_W,
+  BFIN_ASTAT,
+  BFIN_RETS,
+  BFIN_LC0,
+  BFIN_LT0,
+  BFIN_LB0,
+  BFIN_LC1,
+  BFIN_LT1,
+  BFIN_LB1,
+  BFIN_CYCLES,
+  BFIN_CYCLES2,
+  BFIN_USP,
+  BFIN_SEQSTAT,
+  BFIN_SYSCFG,
+  BFIN_RETI,
+  BFIN_RETX,
+  BFIN_RETN,
+  BFIN_RETE,
+
+  /* Pseudo Registers */
+  BFIN_PC,
+  BFIN_CC,
+  BFIN_EXTRA1,		/* Address of .text section.  */
+  BFIN_EXTRA2,		/* Address of .data section.  */
+  BFIN_EXTRA3,		/* Address of .bss section.  */
+  BFIN_FDPIC_EXEC,
+  BFIN_FDPIC_INTERP,
+
+  /* MMRs */
+  BFIN_IPEND,
+
+  /* LAST ENTRY SHOULD NOT BE CHANGED.  */
+  BFIN_NUM_REGS		/* The number of all registers.  */
+};
+
+/* Number of bytes of registers.  */
+#define NUMREGBYTES (BFIN_NUM_REGS * 4)
+
+static inline void arch_kgdb_breakpoint(void)
+{
+	asm volatile ("EXCPT 2;");
+}
+#define BREAK_INSTR_SIZE	2
+#define CACHE_FLUSH_IS_SAFE	1
+#define GDB_ADJUSTS_BREAK_OFFSET
+#define GDB_SKIP_HW_WATCH_TEST
+#define HW_INST_WATCHPOINT_NUM	6
+#define HW_WATCHPOINT_NUM	8
+#define TYPE_INST_WATCHPOINT	0
+#define TYPE_DATA_WATCHPOINT	1
+
+/* Instruction watchpoint address control register bits mask */
+#define WPPWR		0x1
+#define WPIREN01	0x2
+#define WPIRINV01	0x4
+#define WPIAEN0		0x8
+#define WPIAEN1		0x10
+#define WPICNTEN0	0x20
+#define WPICNTEN1	0x40
+#define EMUSW0		0x80
+#define EMUSW1		0x100
+#define WPIREN23	0x200
+#define WPIRINV23	0x400
+#define WPIAEN2		0x800
+#define WPIAEN3		0x1000
+#define WPICNTEN2	0x2000
+#define WPICNTEN3	0x4000
+#define EMUSW2		0x8000
+#define EMUSW3		0x10000
+#define WPIREN45	0x20000
+#define WPIRINV45	0x40000
+#define WPIAEN4		0x80000
+#define WPIAEN5		0x100000
+#define WPICNTEN4	0x200000
+#define WPICNTEN5	0x400000
+#define EMUSW4		0x800000
+#define EMUSW5		0x1000000
+#define WPAND		0x2000000
+
+/* Data watchpoint address control register bits mask */
+#define WPDREN01	0x1
+#define WPDRINV01	0x2
+#define WPDAEN0		0x4
+#define WPDAEN1		0x8
+#define WPDCNTEN0	0x10
+#define WPDCNTEN1	0x20
+
+#define WPDSRC0		0xc0
+#define WPDACC0_OFFSET	8
+#define WPDSRC1		0xc00
+#define WPDACC1_OFFSET	12
+
+/* Watchpoint status register bits mask */
+#define STATIA0		0x1
+#define STATIA1		0x2
+#define STATIA2		0x4
+#define STATIA3		0x8
+#define STATIA4		0x10
+#define STATIA5		0x20
+#define STATDA0		0x40
+#define STATDA1		0x80
+
+#endif
diff --git a/arch/blackfin/lib/memcmp.S b/arch/blackfin/lib/memcmp.S
new file mode 100644
index 0000000..6c834a7
--- /dev/null
+++ b/arch/blackfin/lib/memcmp.S
@@ -0,0 +1,103 @@
+/*
+ * File: memcmp.S
+ *
+ * Copyright 2004-2007 Analog Devices Inc.
+ * Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+.align 2
+
+/*
+ * C Library function MEMCMP
+ * R0 = First Address
+ * R1 = Second Address
+ * R2 = count
+ * Favours word aligned data.
+ */
+
+.globl _memcmp;
+.type _memcmp, STT_FUNC;
+_memcmp:
+	I1 = P3;
+	P0 = R0;			/* P0 = s1 address */
+	P3 = R1;			/* P3 = s2 Address  */
+	P2 = R2 ;			/* P2 = count */
+	CC = R2 <= 7(IU);
+	IF CC JUMP  .Ltoo_small;
+	I0 = R1;			/* s2 */
+	R1 = R1 | R0;		/* OR addresses together */
+	R1 <<= 30;		/* check bottom two bits */
+	CC =  AZ;			/* AZ set if zero. */
+	IF !CC JUMP  .Lbytes ;	/* Jump if addrs not aligned. */
+
+	P1 = P2 >> 2;		/* count = n/4 */
+	R3 =  3;
+	R2 = R2 & R3;		/* remainder */
+	P2 = R2;			/* set remainder */
+
+	LSETUP (.Lquad_loop_s , .Lquad_loop_e) LC0=P1;
+.Lquad_loop_s:
+	NOP;
+	R0 = [P0++];
+	R1 = [I0++];
+	CC = R0 == R1;
+	IF !CC JUMP .Lquad_different;
+.Lquad_loop_e:
+	NOP;
+
+	P3 = I0;			/* s2 */
+.Ltoo_small:
+	CC = P2 == 0;		/* Check zero count*/
+	IF CC JUMP .Lfinished;	/* very unlikely*/
+
+.Lbytes:
+	LSETUP (.Lbyte_loop_s , .Lbyte_loop_e) LC0=P2;
+.Lbyte_loop_s:
+	R1 = B[P3++](Z);	/* *s2 */
+	R0 = B[P0++](Z);	/* *s1 */
+	CC = R0 == R1;
+	IF !CC JUMP .Ldifferent;
+.Lbyte_loop_e:
+	NOP;
+
+.Ldifferent:
+	R0 = R0 - R1;
+	P3 = I1;
+	RTS;
+
+.Lquad_different:
+/* We've read two quads which don't match.
+ * Can't just compare them, because we're
+ * a little-endian machine, so the MSBs of
+ * the regs occur at later addresses in the
+ * string.
+ * Arrange to re-read those two quads again,
+ * byte-by-byte.
+ */
+	P0 += -4;		/* back up to the start of the */
+	P3 = I0;		/* quads, and increase the*/
+	P2 += 4;		/* remainder count*/
+	P3 += -4;
+	JUMP .Lbytes;
+
+.Lfinished:
+	R0 = 0;
+	P3 = I1;
+	RTS;
+
+.size _memcmp, .-_memcmp
diff --git a/arch/blackfin/lib/memcpy.S b/arch/blackfin/lib/memcpy.S
new file mode 100644
index 0000000..e6b359a
--- /dev/null
+++ b/arch/blackfin/lib/memcpy.S
@@ -0,0 +1,117 @@
+/*
+ * File: memcpy.S
+ *
+ * Copyright 2004-2007 Analog Devices Inc.
+ * Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+.align 2
+
+.globl _memcpy_ASM;
+.type _memcpy_ASM, STT_FUNC;
+_memcpy_ASM:
+	CC = R2 <=  0;	/* length not positive?*/
+	IF CC JUMP  .L_P1L2147483647;	/* Nothing to do */
+
+	P0 = R0 ;	/* dst*/
+	P1 = R1 ;	/* src*/
+	P2 = R2 ;	/* length */
+
+	/* check for overlapping data */
+	CC = R1 < R0;	/* src < dst */
+	IF !CC JUMP .Lno_overlap;
+	R3 = R1 + R2;
+	CC = R0 < R3;	/* and dst < src+len */
+	IF CC JUMP .Lhas_overlap;
+
+.Lno_overlap:
+	/* Check for aligned data.*/
+
+	R3 = R1 | R0;
+	R0 = 0x3;
+	R3 = R3 & R0;
+	CC = R3;	/* low bits set on either address? */
+	IF CC JUMP .Lnot_aligned;
+
+	/* Both addresses are word-aligned, so we can copy
+	at least part of the data using word copies.*/
+	P2 = P2 >> 2;
+	CC = P2 <= 2;
+	IF !CC JUMP .Lmore_than_seven;
+	/* less than eight bytes... */
+	P2 = R2;
+	LSETUP(.Lthree_start, .Lthree_end) LC0=P2;
+	R0 = R1;	/* setup src address for return */
+.Lthree_start:
+	R3 = B[P1++] (X);
+.Lthree_end:
+	B[P0++] = R3;
+
+	RTS;
+
+.Lmore_than_seven:
+	/* There's at least eight bytes to copy. */
+	P2 += -1;	/* because we unroll one iteration */
+	LSETUP(.Lword_loop, .Lword_loop) LC0=P2;
+	R0 = R1;
+	I1 = P1;
+	R3 = [I1++];
+.Lword_loop:
+	MNOP || [P0++] = R3 || R3 = [I1++];
+
+	[P0++] = R3;
+	/* Any remaining bytes to copy? */
+	R3 = 0x3;
+	R3 = R2 & R3;
+	CC = R3 == 0;
+	P1 = I1;	/* in case there's something left, */
+	IF !CC JUMP .Lbytes_left;
+	RTS;
+.Lbytes_left:	P2 = R3;
+.Lnot_aligned:
+	/* From here, we're copying byte-by-byte. */
+	LSETUP (.Lbyte_start , .Lbyte_end) LC0=P2;
+	R0 = R1;	/* Save src address for return */
+.Lbyte_start:
+	R1 = B[P1++] (X);
+.Lbyte_end:
+	B[P0++] = R1;
+
+.L_P1L2147483647:
+	RTS;
+
+.Lhas_overlap:
+/* Need to reverse the copying, because the
+ * dst would clobber the src.
+ * Don't bother to work out alignment for
+ * the reverse case.
+ */
+	R0 = R1;	/* save src for later. */
+	P0 = P0 + P2;
+	P0 += -1;
+	P1 = P1 + P2;
+	P1 += -1;
+	LSETUP(.Lover_start, .Lover_end) LC0=P2;
+.Lover_start:
+	R1 = B[P1--] (X);
+.Lover_end:
+	B[P0--] = R1;
+
+	RTS;
+
+.size _memcpy_ASM, .-_memcpy_ASM
diff --git a/arch/blackfin/lib/memmove.S b/arch/blackfin/lib/memmove.S
new file mode 100644
index 0000000..e385c4f
--- /dev/null
+++ b/arch/blackfin/lib/memmove.S
@@ -0,0 +1,96 @@
+/*
+ * File: memmove.S
+ *
+ * Copyright 2004-2007 Analog Devices Inc.
+ * Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+.align 2
+
+/*
+ * C Library function MEMMOVE
+ * R0 = To Address (leave unchanged to form result)
+ * R1 = From Address
+ * R2 = count
+ * Data may overlap
+ */
+
+.globl _memmove;
+.type _memmove, STT_FUNC;
+_memmove:
+	I1 = P3;
+	P0 = R0;                  /* P0 = To address */
+	P3 = R1;                  /* P3 = From Address */
+	P2 = R2 ;                 /* P2 = count */
+	CC = P2 == 0;             /* Check zero count*/
+	IF CC JUMP .Lfinished;    /* very unlikely */
+
+	CC = R1 < R0 (IU);        /* From < To */
+	IF !CC JUMP .Lno_overlap;
+	R3 = R1 + R2;
+	CC = R0 <= R3 (IU);       /* (From+len) >= To */
+	IF CC JUMP .Loverlap;
+.Lno_overlap:
+	R3 = 11;
+	CC = R2 <= R3;
+	IF CC JUMP  .Lbytes;
+	R3 = R1 | R0;             /* OR addresses together */
+	R3 <<= 30;                /* check bottom two bits */
+	CC =  AZ;                 /* AZ set if zero.*/
+	IF !CC JUMP  .Lbytes ;    /* Jump if addrs not aligned.*/
+
+	I0 = P3;
+	P1 = P2 >> 2;             /* count = n/4 */
+	P1 += -1;
+	R3 =  3;
+	R2 = R2 & R3;             /* remainder */
+	P2 = R2;                  /* set remainder */
+	R1 = [I0++];
+
+	LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1;
+.Lquad_loop: MNOP || [P0++] = R1 || R1 = [I0++];
+	[P0++] = R1;
+
+	CC = P2 == 0;             /* any remaining bytes? */
+	P3 = I0;                  /* Ammend P3 to updated ptr. */
+	IF !CC JUMP .Lbytes;
+	P3 = I1;
+	RTS;
+
+.Lbytes:     LSETUP (.Lbyte2_s , .Lbyte2_e) LC0=P2;
+.Lbyte2_s:   R1 = B[P3++](Z);
+.Lbyte2_e:   B[P0++] = R1;
+
+.Lfinished:  P3 = I1;
+	RTS;
+
+.Loverlap:
+	P2 += -1;
+	P0 = P0 + P2;
+	P3 = P3 + P2;
+	R1 = B[P3--] (Z);
+	CC = P2 == 0;
+	IF CC JUMP .Lno_loop;
+	LSETUP (.Lol_s, .Lol_e) LC0 = P2;
+.Lol_s:    B[P0--] = R1;
+.Lol_e:    R1 = B[P3--] (Z);
+.Lno_loop: B[P0] = R1;
+	P3 = I1;
+	RTS;
+
+.size _memmove, .-_memmove
diff --git a/arch/blackfin/lib/memset.S b/arch/blackfin/lib/memset.S
new file mode 100644
index 0000000..26f63cd
--- /dev/null
+++ b/arch/blackfin/lib/memset.S
@@ -0,0 +1,96 @@
+/*
+ * File: memset.S
+ *
+ * Copyright 2004-2007 Analog Devices Inc.
+ * Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+.align 2
+
+/*
+ * C Library function MEMSET
+ * R0 = address (leave unchanged to form result)
+ * R1 = filler byte
+ * R2 = count
+ * Favours word aligned data.
+ */
+
+.globl _memset;
+.type _memset, STT_FUNC;
+_memset:
+	P0 = R0 ;              /* P0 = address */
+	P2 = R2 ;              /* P2 = count   */
+	R3 = R0 + R2;          /* end          */
+	CC = R2 <= 7(IU);
+	IF CC JUMP  .Ltoo_small;
+	R1 = R1.B (Z);         /* R1 = fill char */
+	R2 =  3;
+	R2 = R0 & R2;          /* addr bottom two bits */
+	CC =  R2 == 0;             /* AZ set if zero.	*/
+	IF !CC JUMP  .Lforce_align ;  /* Jump if addr not aligned. */
+
+.Laligned:
+	P1 = P2 >> 2;          /* count = n/4        */
+	R2 = R1 <<  8;         /* create quad filler */
+	R2.L = R2.L + R1.L(NS);
+	R2.H = R2.L + R1.H(NS);
+	P2 = R3;
+
+	LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1;
+.Lquad_loop:
+	[P0++] = R2;
+
+	CC = P0 == P2;
+	IF !CC JUMP .Lbytes_left;
+	RTS;
+
+.Lbytes_left:
+	R2 = R3;                /* end point */
+	R3 = P0;                /* current position */
+	R2 = R2 - R3;           /* bytes left */
+	P2 = R2;
+
+.Ltoo_small:
+	CC = P2 == 0;           /* Check zero count */
+	IF CC JUMP .Lfinished;    /* Unusual */
+
+.Lbytes:
+	LSETUP (.Lbyte_loop , .Lbyte_loop) LC0=P2;
+.Lbyte_loop:
+	B[P0++] = R1;
+
+.Lfinished:
+	RTS;
+
+.Lforce_align:
+	CC = BITTST (R0, 0);  /* odd byte */
+	R0 = 4;
+	R0 = R0 - R2;
+	P1 = R0;
+	R0 = P0;		    /* Recover return address */
+	IF !CC JUMP .Lskip1;
+	B[P0++] = R1;
+.Lskip1:
+	CC = R2 <= 2;          /* 2 bytes */
+	P2 -= P1;              /* reduce count */
+	IF !CC JUMP .Laligned;
+	B[P0++] = R1;
+	B[P0++] = R1;
+	JUMP .Laligned;
+
+.size _memset, .-_memset
diff --git a/arch/blackfin/lib/muldi3.c b/arch/blackfin/lib/muldi3.c
new file mode 100644
index 0000000..bf1ca53
--- /dev/null
+++ b/arch/blackfin/lib/muldi3.c
@@ -0,0 +1,92 @@
+/*
+ * U-boot - muldi3.c contains routines for mult and div
+ *
+ * Copyright (c) 2005-2007 Analog Devices 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., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* Generic function got from GNU gcc package, libgcc2.c */
+#ifndef SI_TYPE_SIZE
+#define SI_TYPE_SIZE 32
+#endif
+#define __ll_B (1L << (SI_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
+#define __ll_highpart(t) ((USItype) (t) / __ll_B)
+#define BITS_PER_UNIT 8
+
+#if !defined (umul_ppmm)
+#define umul_ppmm(w1, w0, u, v)						\
+do {									\
+	USItype __x0, __x1, __x2, __x3;					\
+	USItype __ul, __vl, __uh, __vh;					\
+									\
+	__ul = __ll_lowpart (u);					\
+	__uh = __ll_highpart (u);					\
+	__vl = __ll_lowpart (v);					\
+	__vh = __ll_highpart (v);					\
+									\
+	__x0 = (USItype) __ul * __vl;					\
+	__x1 = (USItype) __ul * __vh;					\
+	__x2 = (USItype) __uh * __vl;					\
+	__x3 = (USItype) __uh * __vh;					\
+									\
+	__x1 += __ll_highpart (__x0);/* this can't give carry */	\
+	__x1 += __x2;	/* but this indeed can */			\
+	if (__x1 < __x2)	/* did we get it? */			\
+		__x3 += __ll_B;	/* yes, add it in the proper pos. */	\
+									\
+	(w1) = __x3 + __ll_highpart (__x1);				\
+	(w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0);	\
+} while (0)
+#endif
+
+#if !defined (__umulsidi3)
+#define __umulsidi3(u, v)						\
+	({DIunion __w;							\
+	umul_ppmm (__w.s.high, __w.s.low, u, v);			\
+	__w.ll; })
+#endif
+
+typedef unsigned int USItype __attribute__ ((mode(SI)));
+typedef int SItype __attribute__ ((mode(SI)));
+typedef int DItype __attribute__ ((mode(DI)));
+typedef int word_type __attribute__ ((mode(__word__)));
+
+struct DIstruct {
+	SItype low, high;
+};
+typedef union {
+	struct DIstruct s;
+	DItype ll;
+} DIunion;
+
+DItype __muldi3(DItype u, DItype v)
+{
+	DIunion w;
+	DIunion uu, vv;
+
+	uu.ll = u, vv.ll = v;
+	/*  panic("kernel panic for __muldi3"); */
+	w.ll = __umulsidi3(uu.s.low, vv.s.low);
+	w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
+		     + (USItype) uu.s.high * (USItype) vv.s.low);
+
+	return w.ll;
+}
diff --git a/arch/blackfin/lib/outs.S b/arch/blackfin/lib/outs.S
new file mode 100644
index 0000000..90c6033
--- /dev/null
+++ b/arch/blackfin/lib/outs.S
@@ -0,0 +1,60 @@
+/*
+ * Implementation of outs{bwl} for BlackFin processors using zero overhead loops.
+ *
+ * Copyright 2005-2009 Analog Devices Inc.
+ *                2005 BuyWays BV
+ *                      Bas Vermeulen <bas@buyways.nl>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <asm/linkage.h>
+
+.align 2
+
+ENTRY(_outsl)
+	P0 = R0;	/* P0 = port */
+	P1 = R1;	/* P1 = address */
+	P2 = R2;	/* P2 = count */
+
+	LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
+.Llong_loop_s: R0 = [P1++];
+.Llong_loop_e: [P0] = R0;
+	RTS;
+ENDPROC(_outsl)
+
+ENTRY(_outsw)
+	P0 = R0;	/* P0 = port */
+	P1 = R1;	/* P1 = address */
+	P2 = R2;	/* P2 = count */
+
+	LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
+.Lword_loop_s: R0 = W[P1++];
+.Lword_loop_e: W[P0] = R0;
+	RTS;
+ENDPROC(_outsw)
+
+ENTRY(_outsb)
+	P0 = R0;	/* P0 = port */
+	P1 = R1;	/* P1 = address */
+	P2 = R2;	/* P2 = count */
+
+	LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
+.Lbyte_loop_s: R0 = B[P1++];
+.Lbyte_loop_e: B[P0] = R0;
+	RTS;
+ENDPROC(_outsb)
+
+ENTRY(_outsw_8)
+	P0 = R0;	/* P0 = port */
+	P1 = R1;	/* P1 = address */
+	P2 = R2;	/* P2 = count */
+
+	LSETUP( .Lword8_loop_s, .Lword8_loop_e) LC0 = P2;
+.Lword8_loop_s: R1 = B[P1++];
+		R0 = B[P1++];
+		R0 = R0 << 8;
+		R0 = R0 + R1;
+.Lword8_loop_e: W[P0] = R0;
+	RTS;
+ENDPROC(_outsw_8)
diff --git a/arch/blackfin/lib/post.c b/arch/blackfin/lib/post.c
new file mode 100644
index 0000000..faf6b96
--- /dev/null
+++ b/arch/blackfin/lib/post.c
@@ -0,0 +1,421 @@
+/*
+ * (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 <stdio_dev.h>
+#include <watchdog.h>
+#include <post.h>
+
+#ifdef CONFIG_LOGBUFFER
+#include <logbuff.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define POST_MAX_NUMBER		32
+
+#define BOOTMODE_MAGIC	0xDEAD0000
+
+int post_init_f(void)
+{
+	int res = 0;
+	unsigned int i;
+
+	for (i = 0; i < post_list_size; i++) {
+		struct post_test *test = post_list + i;
+
+		if (test->init_f && test->init_f()) {
+			res = -1;
+		}
+	}
+
+	gd->post_init_f_time = post_time_ms(0);
+	if (!gd->post_init_f_time) {
+		printf
+		    ("post/post.c: post_time_ms seems not to be implemented\n");
+	}
+
+	return res;
+}
+
+void post_bootmode_init(void)
+{
+	int bootmode = post_bootmode_get(0);
+	int newword;
+
+	if (post_hotkeys_pressed() && !(bootmode & POST_POWERTEST)) {
+		newword = BOOTMODE_MAGIC | POST_SLOWTEST;
+	} else if (bootmode == 0) {
+		newword = BOOTMODE_MAGIC | POST_POWERON;
+	} else if (bootmode == POST_POWERON || bootmode == POST_SLOWTEST) {
+		newword = BOOTMODE_MAGIC | POST_NORMAL;
+	} else {
+		/* Use old value */
+		newword = post_word_load() & ~POST_COLDBOOT;
+	}
+
+	if (bootmode == 0) {
+		/* We are booting after power-on */
+		newword |= POST_COLDBOOT;
+	}
+
+	post_word_store(newword);
+
+	/* Reset activity record */
+	gd->post_log_word = 0;
+}
+
+int post_bootmode_get(unsigned int *last_test)
+{
+	unsigned long word = post_word_load();
+	int bootmode;
+
+	if ((word & 0xFFFF0000) != BOOTMODE_MAGIC) {
+		return 0;
+	}
+
+	bootmode = word & 0x7F;
+
+	if (last_test && (bootmode & POST_POWERTEST)) {
+		*last_test = (word >> 8) & 0xFF;
+	}
+
+	return bootmode;
+}
+
+/* POST tests run before relocation only mark status bits .... */
+static void post_log_mark_start(unsigned long testid)
+{
+	gd->post_log_word |= (testid) << 16;
+}
+
+static void post_log_mark_succ(unsigned long testid)
+{
+	gd->post_log_word |= testid;
+}
+
+/* ... and the messages are output once we are relocated */
+void post_output_backlog(void)
+{
+	int j;
+
+	for (j = 0; j < post_list_size; j++) {
+		if (gd->post_log_word & (post_list[j].testid << 16)) {
+			post_log("POST %s ", post_list[j].cmd);
+			if (gd->post_log_word & post_list[j].testid)
+				post_log("PASSED\n");
+			else {
+				post_log("FAILED\n");
+				show_boot_progress (-31);
+			}
+		}
+	}
+}
+
+static void post_bootmode_test_on(unsigned int last_test)
+{
+	unsigned long word = post_word_load();
+
+	word |= POST_POWERTEST;
+
+	word |= (last_test & 0xFF) << 8;
+
+	post_word_store(word);
+}
+
+static void post_bootmode_test_off(void)
+{
+	unsigned long word = post_word_load();
+
+	word &= ~POST_POWERTEST;
+
+	post_word_store(word);
+}
+
+static void post_get_flags(int *test_flags)
+{
+	int flag[] = { POST_POWERON, POST_NORMAL, POST_SLOWTEST };
+	char *var[] = { "post_poweron", "post_normal", "post_slowtest" };
+	int varnum = sizeof(var) / sizeof(var[0]);
+	char list[128];		/* long enough for POST list */
+	char *name;
+	char *s;
+	int last;
+	int i, j;
+
+	for (j = 0; j < post_list_size; j++) {
+		test_flags[j] = post_list[j].flags;
+	}
+
+	for (i = 0; i < varnum; i++) {
+		if (getenv_r(var[i], list, sizeof(list)) <= 0)
+			continue;
+
+		for (j = 0; j < post_list_size; j++) {
+			test_flags[j] &= ~flag[i];
+		}
+
+		last = 0;
+		name = list;
+		while (!last) {
+			while (*name && *name == ' ')
+				name++;
+			if (*name == 0)
+				break;
+			s = name + 1;
+			while (*s && *s != ' ')
+				s++;
+			if (*s == 0)
+				last = 1;
+			else
+				*s = 0;
+
+			for (j = 0; j < post_list_size; j++) {
+				if (strcmp(post_list[j].cmd, name) == 0) {
+					test_flags[j] |= flag[i];
+					break;
+				}
+			}
+
+			if (j == post_list_size) {
+				printf("No such test: %s\n", name);
+			}
+
+			name = s + 1;
+		}
+	}
+
+	for (j = 0; j < post_list_size; j++) {
+		if (test_flags[j] & POST_POWERON) {
+			test_flags[j] |= POST_SLOWTEST;
+		}
+	}
+}
+
+static int post_run_single(struct post_test *test,
+			   int test_flags, int flags, unsigned int i)
+{
+	if ((flags & test_flags & POST_ALWAYS) &&
+	    (flags & test_flags & POST_MEM)) {
+		WATCHDOG_RESET();
+
+		if (!(flags & POST_REBOOT)) {
+			if ((test_flags & POST_REBOOT)
+			    && !(flags & POST_MANUAL)) {
+				post_bootmode_test_on(i);
+			}
+
+			if (test_flags & POST_PREREL)
+				post_log_mark_start(test->testid);
+			else
+				post_log("POST %s ", test->cmd);
+		}
+
+		if (test_flags & POST_PREREL) {
+			if ((*test->test) (flags) == 0)
+				post_log_mark_succ(test->testid);
+		} else {
+			if ((*test->test) (flags) != 0) {
+				post_log("FAILED\n");
+				show_boot_progress (-32);
+			} else
+				post_log("PASSED\n");
+		}
+
+		if ((test_flags & POST_REBOOT) && !(flags & POST_MANUAL)) {
+			post_bootmode_test_off();
+		}
+
+		return 0;
+	} else {
+		return -1;
+	}
+}
+
+int post_run(char *name, int flags)
+{
+	unsigned int i;
+	int test_flags[POST_MAX_NUMBER];
+
+	post_get_flags(test_flags);
+
+	if (name == NULL) {
+		unsigned int last;
+
+		if (post_bootmode_get(&last) & POST_POWERTEST) {
+			if (last < post_list_size &&
+			    (flags & test_flags[last] & POST_ALWAYS) &&
+			    (flags & test_flags[last] & POST_MEM)) {
+
+				post_run_single(post_list + last,
+						test_flags[last],
+						flags | POST_REBOOT, last);
+
+				for (i = last + 1; i < post_list_size; i++) {
+					post_run_single(post_list + i,
+							test_flags[i],
+							flags, i);
+				}
+			}
+		} else {
+			for (i = 0; i < post_list_size; i++) {
+				post_run_single(post_list + i,
+						test_flags[i], flags, i);
+			}
+		}
+
+		return 0;
+	} else {
+		for (i = 0; i < post_list_size; i++) {
+			if (strcmp(post_list[i].cmd, name) == 0)
+				break;
+		}
+
+		if (i < post_list_size) {
+			return post_run_single(post_list + i,
+					       test_flags[i], flags, i);
+		} else {
+			return -1;
+		}
+	}
+}
+
+static int post_info_single(struct post_test *test, int full)
+{
+	if (test->flags & POST_MANUAL) {
+		if (full)
+			printf("%s - %s\n"
+			       "  %s\n", test->cmd, test->name, test->desc);
+		else
+			printf("  %-15s - %s\n", test->cmd, test->name);
+
+		return 0;
+	} else {
+		return -1;
+	}
+}
+
+int post_info(char *name)
+{
+	unsigned int i;
+
+	if (name == NULL) {
+		for (i = 0; i < post_list_size; i++) {
+			post_info_single(post_list + i, 0);
+		}
+
+		return 0;
+	} else {
+		for (i = 0; i < post_list_size; i++) {
+			if (strcmp(post_list[i].cmd, name) == 0)
+				break;
+		}
+
+		if (i < post_list_size) {
+			return post_info_single(post_list + i, 1);
+		} else {
+			return -1;
+		}
+	}
+}
+
+int post_log(char *format, ...)
+{
+	va_list args;
+	uint i;
+	char printbuffer[CONFIG_SYS_PBSIZE];
+
+	va_start(args, format);
+
+	/* For this to work, printbuffer must be larger than
+	 * anything we ever want to print.
+	 */
+	i = vsprintf(printbuffer, format, args);
+	va_end(args);
+
+#ifdef CONFIG_LOGBUFFER
+	/* Send to the logbuffer */
+	logbuff_log(printbuffer);
+#else
+	/* Send to the stdout file */
+	puts(printbuffer);
+#endif
+
+	return 0;
+}
+
+void post_reloc(void)
+{
+	unsigned int i;
+
+	/*
+	 * We have to relocate the test table manually
+	 */
+	for (i = 0; i < post_list_size; i++) {
+		ulong addr;
+		struct post_test *test = post_list + i;
+
+		if (test->name) {
+			addr = (ulong) (test->name) + gd->reloc_off;
+			test->name = (char *)addr;
+		}
+
+		if (test->cmd) {
+			addr = (ulong) (test->cmd) + gd->reloc_off;
+			test->cmd = (char *)addr;
+		}
+
+		if (test->desc) {
+			addr = (ulong) (test->desc) + gd->reloc_off;
+			test->desc = (char *)addr;
+		}
+
+		if (test->test) {
+			addr = (ulong) (test->test) + gd->reloc_off;
+			test->test = (int (*)(int flags))addr;
+		}
+
+		if (test->init_f) {
+			addr = (ulong) (test->init_f) + gd->reloc_off;
+			test->init_f = (int (*)(void))addr;
+		}
+
+		if (test->reloc) {
+			addr = (ulong) (test->reloc) + gd->reloc_off;
+			test->reloc = (void (*)(void))addr;
+
+			test->reloc();
+		}
+	}
+}
+
+/*
+ * Some tests (e.g. SYSMON) need the time when post_init_f started,
+ * but we cannot use get_timer() at this point.
+ *
+ * On PowerPC we implement it using the timebase register.
+ */
+unsigned long post_time_ms(unsigned long base)
+{
+	return (unsigned long)get_ticks() / (get_tbclk() / CONFIG_SYS_HZ) - base;
+}
diff --git a/arch/blackfin/lib/string.c b/arch/blackfin/lib/string.c
new file mode 100644
index 0000000..e344d3b
--- /dev/null
+++ b/arch/blackfin/lib/string.c
@@ -0,0 +1,274 @@
+/*
+ * U-boot - string.c Contains library routines.
+ *
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ *
+ * (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., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/blackfin.h>
+#include <asm/io.h>
+#include <asm/mach-common/bits/dma.h>
+
+char *strcpy(char *dest, const char *src)
+{
+	char *xdest = dest;
+	char temp = 0;
+
+	__asm__ __volatile__ (
+		"1:\t%2 = B [%1++] (Z);\n\t"
+		"B [%0++] = %2;\n\t"
+		"CC = %2;\n\t"
+		"if cc jump 1b (bp);\n"
+		: "=a"(dest), "=a"(src), "=d"(temp)
+		: "0"(dest), "1"(src), "2"(temp)
+		: "memory");
+
+	return xdest;
+}
+
+char *strncpy(char *dest, const char *src, size_t n)
+{
+	char *xdest = dest;
+	char temp = 0;
+
+	if (n == 0)
+		return xdest;
+
+	__asm__ __volatile__ (
+		"1:\t%3 = B [%1++] (Z);\n\t"
+		"B [%0++] = %3;\n\t"
+		"CC = %3;\n\t"
+		"if ! cc jump 2f;\n\t"
+		"%2 += -1;\n\t"
+		"CC = %2 == 0;\n\t"
+		"if ! cc jump 1b (bp);\n"
+		"2:\n"
+		: "=a"(dest), "=a"(src), "=da"(n), "=d"(temp)
+		: "0"(dest), "1"(src), "2"(n), "3"(temp)
+		: "memory");
+
+	return xdest;
+}
+
+int strcmp(const char *cs, const char *ct)
+{
+	char __res1, __res2;
+
+	__asm__ (
+		"1:\t%2 = B[%0++] (Z);\n\t"	/* get *cs */
+		"%3 = B[%1++] (Z);\n\t"	/* get *ct */
+		"CC = %2 == %3;\n\t"	/* compare a byte */
+		"if ! cc jump 2f;\n\t"	/* not equal, break out */
+		"CC = %2;\n\t"	/* at end of cs? */
+		"if cc jump 1b (bp);\n\t"	/* no, keep going */
+		"jump.s 3f;\n"	/* strings are equal */
+		"2:\t%2 = %2 - %3;\n"	/* *cs - *ct */
+		"3:\n"
+		: "=a"(cs), "=a"(ct), "=d"(__res1), "=d"(__res2)
+		: "0"(cs), "1"(ct));
+
+	return __res1;
+}
+
+int strncmp(const char *cs, const char *ct, size_t count)
+{
+	char __res1, __res2;
+
+	if (!count)
+		return 0;
+
+	__asm__(
+		"1:\t%3 = B[%0++] (Z);\n\t"	/* get *cs */
+		"%4 = B[%1++] (Z);\n\t"	/* get *ct */
+		"CC = %3 == %4;\n\t"	/* compare a byte */
+		"if ! cc jump 3f;\n\t"	/* not equal, break out */
+		"CC = %3;\n\t"	/* at end of cs? */
+		"if ! cc jump 4f;\n\t"	/* yes, all done */
+		"%2 += -1;\n\t"	/* no, adjust count */
+		"CC = %2 == 0;\n\t" "if ! cc jump 1b;\n"	/* more to do, keep going */
+		"2:\t%3 = 0;\n\t"	/* strings are equal */
+		"jump.s    4f;\n" "3:\t%3 = %3 - %4;\n"	/* *cs - *ct */
+		"4:"
+		: "=a"(cs), "=a"(ct), "=da"(count), "=d"(__res1), "=d"(__res2)
+		: "0"(cs), "1"(ct), "2"(count));
+
+	return __res1;
+}
+
+#ifdef bfin_write_MDMA1_D0_IRQ_STATUS
+# define bfin_write_MDMA_D0_IRQ_STATUS bfin_write_MDMA1_D0_IRQ_STATUS
+# define bfin_write_MDMA_D0_START_ADDR bfin_write_MDMA1_D0_START_ADDR
+# define bfin_write_MDMA_D0_X_COUNT    bfin_write_MDMA1_D0_X_COUNT
+# define bfin_write_MDMA_D0_X_MODIFY   bfin_write_MDMA1_D0_X_MODIFY
+# define bfin_write_MDMA_D0_CONFIG     bfin_write_MDMA1_D0_CONFIG
+# define bfin_write_MDMA_S0_START_ADDR bfin_write_MDMA1_S0_START_ADDR
+# define bfin_write_MDMA_S0_X_COUNT    bfin_write_MDMA1_S0_X_COUNT
+# define bfin_write_MDMA_S0_X_MODIFY   bfin_write_MDMA1_S0_X_MODIFY
+# define bfin_write_MDMA_S0_CONFIG     bfin_write_MDMA1_S0_CONFIG
+# define bfin_write_MDMA_D0_IRQ_STATUS bfin_write_MDMA1_D0_IRQ_STATUS
+# define bfin_read_MDMA_D0_IRQ_STATUS  bfin_read_MDMA1_D0_IRQ_STATUS
+#endif
+/* This version misbehaves for count values of 0 and 2^16+.
+ * Perhaps we should detect that ?  Nowhere do we actually
+ * use dma memcpy for those types of lengths though ...
+ */
+void dma_memcpy_nocache(void *dst, const void *src, size_t count)
+{
+	uint16_t wdsize, mod;
+
+	/* Disable DMA in case it's still running (older u-boot's did not
+	 * always turn them off).  Do it before the if statement below so
+	 * we can be cheap and not do a SSYNC() due to the forced abort.
+	 */
+	bfin_write_MDMA_D0_CONFIG(0);
+	bfin_write_MDMA_S0_CONFIG(0);
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_RUN | DMA_DONE | DMA_ERR);
+
+	/* Scratchpad cannot be a DMA source or destination */
+	if (((unsigned long)src >= L1_SRAM_SCRATCH &&
+	     (unsigned long)src < L1_SRAM_SCRATCH_END) ||
+	    ((unsigned long)dst >= L1_SRAM_SCRATCH &&
+	     (unsigned long)dst < L1_SRAM_SCRATCH_END))
+		hang();
+
+	if (((unsigned long)dst | (unsigned long)src | count) & 0x1) {
+		wdsize = WDSIZE_8;
+		mod = 1;
+	} else if (((unsigned long)dst | (unsigned long)src | count) & 0x2) {
+		wdsize = WDSIZE_16;
+		count >>= 1;
+		mod = 2;
+	} else {
+		wdsize = WDSIZE_32;
+		count >>= 2;
+		mod = 4;
+	}
+
+	/* Copy sram functions from sdram to sram */
+	/* Setup destination start address */
+	bfin_write_MDMA_D0_START_ADDR(dst);
+	/* Setup destination xcount */
+	bfin_write_MDMA_D0_X_COUNT(count);
+	/* Setup destination xmodify */
+	bfin_write_MDMA_D0_X_MODIFY(mod);
+
+	/* Setup Source start address */
+	bfin_write_MDMA_S0_START_ADDR(src);
+	/* Setup Source xcount */
+	bfin_write_MDMA_S0_X_COUNT(count);
+	/* Setup Source xmodify */
+	bfin_write_MDMA_S0_X_MODIFY(mod);
+
+	/* Enable source DMA */
+	bfin_write_MDMA_S0_CONFIG(wdsize | DMAEN);
+	bfin_write_MDMA_D0_CONFIG(wdsize | DMAEN | WNR | DI_EN);
+	SSYNC();
+
+	while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
+		continue;
+
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_RUN | DMA_DONE | DMA_ERR);
+	bfin_write_MDMA_D0_CONFIG(0);
+	bfin_write_MDMA_S0_CONFIG(0);
+}
+/* We should do a dcache invalidate on the destination after the dma, but since
+ * we lack such hardware capability, we'll flush/invalidate the destination
+ * before the dma and bank on the idea that u-boot is single threaded.
+ */
+void *dma_memcpy(void *dst, const void *src, size_t count)
+{
+	if (dcache_status()) {
+		blackfin_dcache_flush_range(src, src + count);
+		blackfin_dcache_flush_invalidate_range(dst, dst + count);
+	}
+
+	dma_memcpy_nocache(dst, src, count);
+
+	if (icache_status())
+		blackfin_icache_flush_range(dst, dst + count);
+
+	return dst;
+}
+
+/*
+ * memcpy - Copy one area of memory to another
+ * @dest: Where to copy to
+ * @src: Where to copy from
+ * @count: The size of the area.
+ *
+ * We need to have this wrapper in memcpy() as common code may call memcpy()
+ * to load up L1 regions.  Consider loading an ELF which has sections with
+ * LMA's pointing to L1.  The common code ELF loader will simply use memcpy()
+ * to move the ELF's sections into the right place.  We need to catch that
+ * here and redirect to dma_memcpy().
+ */
+extern void *memcpy_ASM(void *dst, const void *src, size_t count);
+void *memcpy(void *dst, const void *src, size_t count)
+{
+	if (!count)
+		return dst;
+
+#ifdef CONFIG_CMD_KGDB
+	if (src >= (void *)SYSMMR_BASE) {
+		if (count == 2 && (unsigned long)src % 2 == 0) {
+			u16 mmr = bfin_read16(src);
+			memcpy(dst, &mmr, sizeof(mmr));
+			return dst;
+		}
+		if (count == 4 && (unsigned long)src % 4 == 0) {
+			u32 mmr = bfin_read32(src);
+			memcpy(dst, &mmr, sizeof(mmr));
+			return dst;
+		}
+		/* Failed for some reason */
+		memset(dst, 0xad, count);
+		return dst;
+	}
+	if (dst >= (void *)SYSMMR_BASE) {
+		if (count == 2 && (unsigned long)dst % 2 == 0) {
+			u16 mmr;
+			memcpy(&mmr, src, sizeof(mmr));
+			bfin_write16(dst, mmr);
+			return dst;
+		}
+		if (count == 4 && (unsigned long)dst % 4 == 0) {
+			u32 mmr;
+			memcpy(&mmr, src, sizeof(mmr));
+			bfin_write32(dst, mmr);
+			return dst;
+		}
+		/* Failed for some reason */
+		memset(dst, 0xad, count);
+		return dst;
+	}
+#endif
+
+	/* if L1 is the source or dst, use DMA */
+	if (addr_bfin_on_chip_mem(dst) || addr_bfin_on_chip_mem(src))
+		return dma_memcpy(dst, src, count);
+	else
+		/* No L1 is involved, so just call regular memcpy */
+		return memcpy_ASM(dst, src, count);
+}
diff --git a/arch/blackfin/lib/tests.c b/arch/blackfin/lib/tests.c
new file mode 100644
index 0000000..bf7fba0
--- /dev/null
+++ b/arch/blackfin/lib/tests.c
@@ -0,0 +1,250 @@
+/*
+ * (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
+ *
+ * Be sure to mark tests to be run before relocation as such with the
+ * CONFIG_SYS_POST_PREREL flag so that logging is done correctly if the
+ * logbuffer support is enabled.
+ */
+
+#include <common.h>
+#include <config.h>
+
+#include <post.h>
+#define CONFIG_SYS_POST_FLASH  0x00004000
+#define CONFIG_SYS_POST_LED    0x00008000
+#define CONFIG_SYS_POST_BUTTON 0x00010000
+
+extern int cache_post_test(int flags);
+extern int watchdog_post_test(int flags);
+extern int i2c_post_test(int flags);
+extern int rtc_post_test(int flags);
+extern int memory_post_test(int flags);
+extern int cpu_post_test(int flags);
+extern int uart_post_test(int flags);
+extern int ether_post_test(int flags);
+extern int spi_post_test(int flags);
+extern int usb_post_test(int flags);
+extern int spr_post_test(int flags);
+extern int sysmon_post_test(int flags);
+extern int dsp_post_test(int flags);
+extern int codec_post_test(int flags);
+
+extern int sysmon_init_f(void);
+
+extern void sysmon_reloc(void);
+
+extern int flash_post_test(int flags);
+extern int led_post_test(int flags);
+extern int button_post_test(int flags);
+
+struct post_test post_list[] = {
+#if CONFIG_POST & CONFIG_SYS_POST_CACHE
+	{
+	 "Cache test",
+	 "cache",
+	 "This test verifies the CPU cache operation.",
+	 POST_RAM | POST_ALWAYS,
+	 &cache_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_CACHE},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_WATCHDOG
+	{
+	 "Watchdog timer test",
+	 "watchdog",
+	 "This test checks the watchdog timer.",
+	 POST_RAM | POST_POWERON | POST_SLOWTEST | POST_MANUAL | POST_REBOOT,
+	 &watchdog_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_WATCHDOG},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_I2C
+	{
+	 "I2C test",
+	 "i2c",
+	 "This test verifies the I2C operation.",
+	 POST_RAM | POST_ALWAYS,
+	 &i2c_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_I2C},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_RTC
+	{
+	 "RTC test",
+	 "rtc",
+	 "This test verifies the RTC operation.",
+	 POST_RAM | POST_SLOWTEST | POST_MANUAL,
+	 &rtc_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_RTC},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_MEMORY
+	{
+	 "Memory test",
+	 "memory",
+	 "This test checks RAM.",
+	 POST_ROM | POST_POWERON | POST_SLOWTEST | POST_PREREL,
+	 &memory_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_MEMORY},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_CPU
+	{
+	 "CPU test",
+	 "cpu",
+	 "This test verifies the arithmetic logic unit of" " CPU.",
+	 POST_RAM | POST_ALWAYS,
+	 &cpu_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_CPU},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_UART
+	{
+	 "UART test",
+	 "uart",
+	 "This test verifies the UART operation.",
+	 POST_RAM | POST_SLOWTEST | POST_MANUAL,
+	 &uart_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_UART},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_ETHER
+	{
+	 "ETHERNET test",
+	 "ethernet",
+	 "This test verifies the ETHERNET operation.",
+	 POST_RAM | POST_ALWAYS | POST_MANUAL,
+	 &ether_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_ETHER},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_SPI
+	{
+	 "SPI test",
+	 "spi",
+	 "This test verifies the SPI operation.",
+	 POST_RAM | POST_ALWAYS | POST_MANUAL,
+	 &spi_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_SPI},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_USB
+	{
+	 "USB test",
+	 "usb",
+	 "This test verifies the USB operation.",
+	 POST_RAM | POST_ALWAYS | POST_MANUAL,
+	 &usb_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_USB},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_SPR
+	{
+	 "SPR test",
+	 "spr",
+	 "This test checks SPR contents.",
+	 POST_ROM | POST_ALWAYS | POST_PREREL,
+	 &spr_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_SPR},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_SYSMON
+	{
+	 "SYSMON test",
+	 "sysmon",
+	 "This test monitors system hardware.",
+	 POST_RAM | POST_ALWAYS,
+	 &sysmon_post_test,
+	 &sysmon_init_f,
+	 &sysmon_reloc,
+	 CONFIG_SYS_POST_SYSMON},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_DSP
+	{
+	 "DSP test",
+	 "dsp",
+	 "This test checks any connected DSP(s).",
+	 POST_RAM | POST_MANUAL,
+	 &dsp_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_DSP},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_CODEC
+	{
+	 "CODEC test",
+	 "codec",
+	 "This test checks any connected codec(s).",
+	 POST_RAM | POST_MANUAL,
+	 &codec_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_CODEC},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_FLASH
+	{
+	 "FLASH test",
+	 "flash",
+	 "This test checks flash.",
+	 POST_RAM | POST_ALWAYS | POST_MANUAL,
+	 &flash_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_FLASH},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_LED
+	{
+	 "LED test",
+	 "LED",
+	 "This test checks LED ",
+	 POST_RAM | POST_ALWAYS | POST_MANUAL,
+	 &led_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_LED},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_BUTTON
+	{
+	 "Button test",
+	 "button",
+	 "This test checks Button ",
+	 POST_RAM | POST_ALWAYS | POST_MANUAL,
+	 &button_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_BUTTON},
+#endif
+
+};
+
+unsigned int post_list_size = sizeof(post_list) / sizeof(struct post_test);
diff --git a/arch/blackfin/lib/u-boot.lds.S b/arch/blackfin/lib/u-boot.lds.S
new file mode 100644
index 0000000..2b23d8b
--- /dev/null
+++ b/arch/blackfin/lib/u-boot.lds.S
@@ -0,0 +1,153 @@
+/*
+ * U-boot - u-boot.lds.S
+ *
+ * Copyright (c) 2005-2010 Analog Device Inc.
+ *
+ * (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 <config.h>
+#include <asm/blackfin.h>
+#undef ALIGN
+#undef ENTRY
+
+#ifndef LDS_BOARD_TEXT
+# define LDS_BOARD_TEXT
+#endif
+
+/* If we don't actually load anything into L1 data, this will avoid
+ * a syntax error.  If we do actually load something into L1 data,
+ * we'll get a linker memory load error (which is what we'd want).
+ * This is here in the first place so we can quickly test building
+ * for different CPU's which may lack non-cache L1 data.
+ */
+#ifndef L1_DATA_B_SRAM
+# define L1_DATA_B_SRAM      CONFIG_SYS_MONITOR_BASE
+# define L1_DATA_B_SRAM_SIZE 0
+#endif
+
+/* The 0xC offset is so we don't clobber the tiny LDR jump block. */
+#ifdef CONFIG_BFIN_BOOTROM_USES_EVT1
+# define L1_CODE_ORIGIN L1_INST_SRAM
+#else
+# define L1_CODE_ORIGIN L1_INST_SRAM + 0xC
+#endif
+
+OUTPUT_ARCH(bfin)
+
+MEMORY
+{
+#if CONFIG_MEM_SIZE
+	ram     : ORIGIN = CONFIG_SYS_MONITOR_BASE, LENGTH = CONFIG_SYS_MONITOR_LEN
+# define ram_code ram
+# define ram_data ram
+#else
+# define ram_code l1_code
+# define ram_data l1_data
+#endif
+	l1_code : ORIGIN = L1_CODE_ORIGIN,          LENGTH = L1_INST_SRAM_SIZE
+	l1_data : ORIGIN = L1_DATA_B_SRAM,          LENGTH = L1_DATA_B_SRAM_SIZE
+}
+
+ENTRY(_start)
+SECTIONS
+{
+	.text.pre :
+	{
+		cpu/blackfin/start.o (.text .text.*)
+
+		LDS_BOARD_TEXT
+	} >ram_code
+
+	.text.init :
+	{
+		cpu/blackfin/initcode.o (.text .text.*)
+	} >ram_code
+	__initcode_lma = LOADADDR(.text.init);
+	__initcode_len = SIZEOF(.text.init);
+
+	.text :
+	{
+		*(.text .text.*)
+	} >ram_code
+
+	.rodata :
+	{
+		. = ALIGN(4);
+		*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+		. = ALIGN(4);
+	} >ram_data
+
+	.data :
+	{
+		. = ALIGN(4);
+		*(.data .data.*)
+		*(.data1)
+		*(.sdata)
+		*(.sdata2)
+		*(.dynamic)
+		CONSTRUCTORS
+	} >ram_data
+
+	.u_boot_cmd :
+	{
+		___u_boot_cmd_start = .;
+		*(.u_boot_cmd)
+		___u_boot_cmd_end = .;
+	} >ram_data
+
+	.text_l1 :
+	{
+		. = ALIGN(4);
+		__stext_l1 = .;
+		*(.l1.text)
+		. = ALIGN(4);
+		__etext_l1 = .;
+	} >l1_code AT>ram_code
+	__text_l1_lma = LOADADDR(.text_l1);
+	__text_l1_len = SIZEOF(.text_l1);
+	ASSERT (__text_l1_len <= L1_INST_SRAM_SIZE, "L1 text overflow!")
+
+	.data_l1 :
+	{
+		. = ALIGN(4);
+		__sdata_l1 = .;
+		*(.l1.data)
+		*(.l1.bss)
+		. = ALIGN(4);
+		__edata_l1 = .;
+	} >l1_data AT>ram_data
+	__data_l1_lma = LOADADDR(.data_l1);
+	__data_l1_len = SIZEOF(.data_l1);
+	ASSERT (__data_l1_len <= L1_DATA_B_SRAM_SIZE, "L1 data B overflow!")
+
+	.bss :
+	{
+		. = ALIGN(4);
+		*(.sbss) *(.scommon)
+		*(.dynbss)
+		*(.bss .bss.*)
+		*(COMMON)
+	} >ram_data
+	__bss_vma = ADDR(.bss);
+	__bss_len = SIZEOF(.bss);
+}
diff --git a/arch/i386/config.mk b/arch/i386/config.mk
new file mode 100644
index 0000000..4b990e0
--- /dev/null
+++ b/arch/i386/config.mk
@@ -0,0 +1,28 @@
+#
+# (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 ?= i386-linux-
+
+STANDALONE_LOAD_ADDR = 0x40000
+
+PLATFORM_CPPFLAGS += -DCONFIG_I386 -D__I386__
diff --git a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile
new file mode 100644
index 0000000..9838506
--- /dev/null
+++ b/arch/i386/lib/Makefile
@@ -0,0 +1,59 @@
+#
+# (C) Copyright 2002-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	+= bios.o
+SOBJS-y	+= bios_pci.o
+SOBJS-y	+= realmode_switch.o
+
+COBJS-y	+= bios_setup.o
+COBJS-y	+= board.o
+COBJS-y	+= bootm.o
+COBJS-y	+= interrupts.o
+COBJS-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o
+COBJS-$(CONFIG_SYS_GENERIC_TIMER) += pcat_timer.o
+COBJS-$(CONFIG_PCI) += pci.o
+COBJS-$(CONFIG_PCI) += pci_type1.o
+COBJS-y	+= realmode.o
+COBJS-y	+= timer.o
+COBJS-y	+= video_bios.o
+COBJS-y	+= video.o
+COBJS-y	+= zimage.o
+
+SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/i386/lib/bios.S b/arch/i386/lib/bios.S
new file mode 100644
index 0000000..48f1b81
--- /dev/null
+++ b/arch/i386/lib/bios.S
@@ -0,0 +1,532 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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 msbios.c from rolo 1.6:
+ *----------------------------------------------------------------------
+ * (C) Copyright 2000
+ * Sysgo Real-Time Solutions GmbH
+ * Klein-Winternheim, Germany
+ *----------------------------------------------------------------------
+ */
+
+#include "bios.h"
+
+/*
+ * During it's initialization phase, before switching to protected
+ * mode, the Linux Kernel makes a few BIOS calls. This won't work
+ * if the board does not have a BIOS.
+ *
+ * This is a very minimalisic BIOS that supplies just enough
+ * functionality to keep the Linux Kernel happy. It is NOT
+ * a general purpose replacement for a real BIOS !!
+ */
+
+
+.section .bios, "ax"
+.code16
+.org 0
+	/* a call to f000:0 should warmboot */
+	jmp	realmode_reset
+
+.globl rm_int00
+.hidden rm_int00
+.type rm_int00, @function
+rm_int00:
+	pushw	$0
+	jmp	any_interrupt16
+.globl rm_int01
+.hidden rm_int01
+.type rm_int01, @function
+rm_int01:
+	pushw	$1
+	jmp	any_interrupt16
+.globl rm_int02
+.hidden rm_int02
+.type rm_int02, @function
+rm_int02:
+	pushw	$2
+	jmp	any_interrupt16
+.globl rm_int03
+.hidden rm_int03
+.type rm_int03, @function
+rm_int03:
+	pushw	$3
+	jmp	any_interrupt16
+.globl rm_int04
+.hidden rm_int04
+.type rm_int04, @function
+rm_int04:
+	pushw	$4
+	jmp	any_interrupt16
+.globl rm_int05
+.hidden rm_int05
+.type rm_int05, @function
+rm_int05:
+	pushw	$5
+	jmp	any_interrupt16
+.globl rm_int06
+.hidden rm_int06
+.type rm_int06, @function
+rm_int06:
+	pushw	$6
+	jmp	any_interrupt16
+.globl rm_int07
+.hidden rm_int07
+.type rm_int07, @function
+rm_int07:
+	pushw	$7
+	jmp	any_interrupt16
+.globl rm_int08
+.hidden rm_int08
+.type rm_int08, @function
+rm_int08:
+	pushw	$8
+	jmp	any_interrupt16
+.globl rm_int09
+.hidden rm_int09
+.type rm_int09, @function
+rm_int09:
+	pushw	$9
+	jmp	any_interrupt16
+.globl rm_int0a
+.hidden rm_int0a
+.type rm_int0a, @function
+rm_int0a:
+	pushw	$10
+	jmp	any_interrupt16
+.globl rm_int0b
+.hidden rm_int0b
+.type rm_int0b, @function
+rm_int0b:
+	pushw	$11
+	jmp	any_interrupt16
+.globl rm_int0c
+.hidden rm_int0c
+.type rm_int0c, @function
+rm_int0c:
+	pushw	$12
+	jmp	any_interrupt16
+.globl rm_int0d
+.hidden rm_int0d
+.type rm_int0d, @function
+rm_int0d:
+	pushw	$13
+	jmp	any_interrupt16
+.globl rm_int0e
+.hidden rm_int0e
+.type rm_int0e, @function
+rm_int0e:
+	pushw	$14
+	jmp	any_interrupt16
+.globl rm_int0f
+.hidden rm_int0f
+.type rm_int0f, @function
+rm_int0f:
+	pushw	$15
+	jmp	any_interrupt16
+.globl rm_int10
+.hidden rm_int10
+.type rm_int10, @function
+rm_int10:
+	pushw	$16
+	jmp	any_interrupt16
+.globl rm_int11
+.hidden rm_int11
+.type rm_int11, @function
+rm_int11:
+	pushw	$17
+	jmp	any_interrupt16
+.globl rm_int12
+.hidden rm_int12
+.type rm_int12, @function
+rm_int12:
+	pushw	$18
+	jmp	any_interrupt16
+.globl rm_int13
+.hidden rm_int13
+.type rm_int13, @function
+rm_int13:
+	pushw	$19
+	jmp	any_interrupt16
+.globl rm_int14
+.hidden rm_int14
+.type rm_int14, @function
+rm_int14:
+	pushw	$20
+	jmp	any_interrupt16
+.globl rm_int15
+.hidden rm_int15
+.type rm_int15, @function
+rm_int15:
+	pushw	$21
+	jmp	any_interrupt16
+.globl rm_int16
+.hidden rm_int16
+.type rm_int16, @function
+rm_int16:
+	pushw	$22
+	jmp	any_interrupt16
+.globl rm_int17
+.hidden rm_int17
+.type rm_int17, @function
+rm_int17:
+	pushw	$23
+	jmp	any_interrupt16
+.globl rm_int18
+.hidden rm_int18
+.type rm_int18, @function
+rm_int18:
+	pushw	$24
+	jmp	any_interrupt16
+.globl rm_int19
+.hidden rm_int19
+.type rm_int19, @function
+rm_int19:
+	pushw	$25
+	jmp	any_interrupt16
+.globl rm_int1a
+.hidden rm_int1a
+.type rm_int1a, @function
+rm_int1a:
+	pushw	$26
+	jmp	any_interrupt16
+.globl rm_int1b
+.hidden rm_int1b
+.type rm_int1b, @function
+rm_int1b:
+	pushw	$27
+	jmp	any_interrupt16
+.globl rm_int1c
+.hidden rm_int1c
+.type rm_int1c, @function
+rm_int1c:
+	pushw	$28
+	jmp	any_interrupt16
+.globl rm_int1d
+.hidden rm_int1d
+.type rm_int1d, @function
+rm_int1d:
+	pushw	$29
+	jmp	any_interrupt16
+.globl rm_int1e
+.hidden rm_int1e
+.type rm_int1e, @function
+rm_int1e:
+	pushw	$30
+	jmp	any_interrupt16
+.globl rm_int1f
+.hidden rm_int1f
+.type rm_int1f, @function
+rm_int1f:
+	pushw	$31
+	jmp	any_interrupt16
+.globl rm_def_int
+.hidden rm_def_int
+.type rm_def_int, @function
+rm_def_int:
+	iret
+
+
+	/*
+	 * All interrupt jumptable entries jump to here
+	 * after pushing the interrupt vector number onto the
+	 * stack.
+	 */
+any_interrupt16:
+	MAKE_BIOS_STACK
+
+gs	movw	OFFS_VECTOR(%bp), %ax
+	cmpw	$0x10, %ax
+	je	Lint_10h
+	cmpw	$0x11, %ax
+	je	Lint_11h
+	cmpw	$0x12, %ax
+	je	Lint_12h
+	cmpw	$0x13, %ax
+	je	Lint_13h
+	cmpw	$0x15, %ax
+	je	Lint_15h
+	cmpw	$0x16, %ax
+	je	Lint_16h
+	cmpw	$0x1a, %ax
+	je	Lint_1ah
+	movw	$0xffff, %ax
+	jmp	Lout
+Lint_10h:					/* VGA BIOS services */
+	call	bios_10h
+	jmp	Lout
+Lint_11h:
+	call	bios_11h
+	jmp	Lout
+Lint_12h:
+	call	bios_12h
+	jmp	Lout
+Lint_13h:					/* BIOS disk services */
+	call	bios_13h
+	jmp	Lout
+Lint_15h:					/* Misc. BIOS services */
+	call	bios_15h
+	jmp	Lout
+Lint_16h:					/* keyboard services */
+	call	bios_16h
+	jmp	Lout
+Lint_1ah:					/* PCI bios */
+	call	bios_1ah
+	jmp	Lout
+Lout:
+	cmpw	$0, %ax
+	je	Lhandeled
+
+	/* Insert code for unhandeled INTs here.
+	 *
+	 * ROLO prints a message to the console
+	 * (we could do that but then we're in 16bit mode
+	 * so we'll have to get back into 32bit mode
+	 * to use the console I/O routines (if we do this
+	 * we shuls make int 0x10 and int 0x16 work as well))
+	 */
+Lhandeled:
+	RESTORE_CALLERS_STACK
+	addw	$2,%sp				/* dump vector number */
+	iret					/* return from interrupt */
+
+
+/*
+ ************************************************************
+ * BIOS	interrupt 10h -- VGA services
+ ************************************************************
+ */
+bios_10h:
+gs	movw	OFFS_AX(%bp), %ax
+	shrw	$8, %ax
+	cmpw	$0x3, %ax
+	je	Lcur_pos
+	cmpw	$0xf, %ax
+	je	Lvid_state
+	cmpw	$0x12, %ax
+	je	Lvid_cfg
+	movw	$0xffff, %ax
+	ret
+Lcur_pos:					/* Read Cursor Position and Size */
+gs	movw	$0, OFFS_CX(%bp)
+gs	movw	$0, OFFS_DX(%bp)
+	xorw	%ax, %ax
+	ret
+Lvid_state:					/* Get Video State */
+gs	movw	$(80 << 8|0x03), OFFS_AX(%bp)	/* 80 columns, 80x25, 16 colors */
+gs	movw	$0, OFFS_BX(%bp)
+	xorw	%ax, %ax
+	ret
+Lvid_cfg:	/* Video Subsystem Configuration (EGA/VGA) */
+gs	movw	$0x10, OFFS_BX(%bp)		/* indicate CGA/MDA/HGA */
+	xorw	%ax, %ax
+	ret
+
+
+/*
+ ************************************************************
+ * BIOS interrupt 11h -- Equipment determination
+ ************************************************************
+ */
+
+bios_11h:
+cs	movw	bios_equipment, %ax
+gs	movw	%ax, OFFS_AX(%bp)
+	xorw	%ax, %ax
+	ret
+
+
+/*
+ ************************************************************
+ * BIOS	interrupt 12h -- Get Memory Size
+ ************************************************************
+ */
+bios_12h:
+cs	movw	ram_in_64kb_chunks, %ax
+	cmpw	$0xa, %ax
+	ja	b12_more_than_640k
+	shlw	$6, %ax
+	jmp	b12_return
+b12_more_than_640k:
+	movw	$0x280, %ax
+b12_return:
+gs	movw	%ax, OFFS_AX(%bp)		/* return number of kilobytes in ax */
+
+gs	movw	OFFS_FLAGS(%bp), %ax
+	andw	$0xfffe, %ax			/* clear carry -- function succeeded */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+
+	xorw	%ax, %ax
+	ret
+
+
+/*
+ ************************************************************
+ * BIOS interrupt 13h -- Disk services
+ ************************************************************
+ */
+bios_13h:
+gs	movw	OFFS_AX(%bp), %ax
+	shrw	$8, %ax
+	cmpw	$0x15, %ax
+	je	Lfunc_15h
+	movw	$0xffff, %ax
+	ret
+Lfunc_15h:
+gs	movw	OFFS_AX(%bp), %ax
+	andw	$0xff, %ax			/* return AH=0->drive not present */
+gs	movw	%ax, OFFS_AX(%bp)
+	xorw	%ax, %ax
+	ret
+
+
+/*
+ ***********************************************************
+ * BIOS interrupt 15h -- Miscellaneous services
+ ***********************************************************
+ */
+bios_15h:
+gs	movw	OFFS_AX(%bp), %ax
+	shrw	$8, %ax
+	cmpw	$0xc0, %ax
+	je	Lfunc_c0h
+	cmpw	$0xe8, %ax
+	je	Lfunc_e8h
+	cmpw	$0x88, %ax
+	je	Lfunc_88h
+	movw	$0xffff, %ax
+	ret
+
+Lfunc_c0h:					/* Return System Configuration Parameters (PS2 only) */
+gs	movw	OFFS_FLAGS(%bp), %ax
+	orw	$1, %ax				/* return carry -- function not supported */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+	xorw	%ax, %ax
+	ret
+
+Lfunc_e8h:
+gs	movw	OFFS_AX(%bp), %ax
+	andw	$0xff, %ax
+	cmpw	$1, %ax
+	je	Lfunc_e801h
+gs	movw	OFFS_FLAGS(%bp), %ax
+	orw	$1, %ax				/* return carry -- function not supported */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+	xorw	%ax, %ax
+	ret
+
+Lfunc_e801h:					/* Get memory size for >64M Configurations */
+cs	movw	ram_in_64kb_chunks, %ax
+	cmpw	$0x100, %ax
+	ja	e801_more_than_16mb
+	shlw	$6, %ax				/* multiply by 64 */
+	subw	$0x400, %ax			/* 1st meg does not count */
+
+gs	movw	%ax, OFFS_AX(%bp)		/* return memory size between 1M and 16M in 1kb chunks in AX and CX */
+gs	movw	%ax, OFFS_CX(%bp)
+gs	movw	$0, OFFS_BX(%bp)		/* set BX and DX to 0*/
+gs	movw	$0, OFFS_DX(%bp)
+gs	movw	OFFS_FLAGS(%bp), %ax
+	andw	$0xfffe, %ax			/* clear carry -- function succeeded */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+	xorw	%ax, %ax
+	ret
+
+e801_more_than_16mb:
+	subw	$0x100, %ax			/* subtract 16MB */
+
+gs	movw	$0x3c00, OFFS_AX(%bp)		/* return 0x3c00 (16MB-1MB) in AX and CX */
+gs	movw	$0x3c00, OFFS_CX(%bp)
+gs	movw	%ax, OFFS_BX(%bp)		/* set BX and DX to number of 64kb chunks above 16MB */
+gs	movw	%ax, OFFS_DX(%bp)
+
+gs	movw	OFFS_FLAGS(%bp), %ax
+	andw	$0xfffe, %ax			/* clear carry -- function succeeded */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+	xorw	%ax, %ax
+	ret
+
+Lfunc_88h:
+cs	movw	ram_in_64kb_chunks, %ax
+	cmpw	$0x100, %ax
+	jna	b88_not_more_than16
+	movw	$0x100, %ax
+b88_not_more_than16:
+	shlw	$6, %ax
+	subw	$0x400, %ax			/* 1st meg does not count */
+
+gs	movw	%ax, OFFS_AX(%bp)		/* return number of kilobytes between 16MB and 16MB in ax */
+
+gs	movw	OFFS_FLAGS(%bp), %ax
+	andw	$0xfffe, %ax			/* clear carry -- function succeeded */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+
+	xorw	%ax, %ax
+	ret
+
+
+/*
+ ************************************************************
+ * BIOS interrupt 16h -- keyboard services
+ ************************************************************
+ */
+bios_16h:
+gs	movw	OFFS_AX(%bp), %ax
+	shrw	$8, %ax
+	cmpw	$0x03, %ax
+	je	Lfunc_03h
+	movw	$0xffff, %ax
+	ret
+Lfunc_03h:
+	xorw	%ax, %ax			/* do nothing -- function not supported */
+	ret
+
+/*
+ ************************************************************
+ * BIOS interrupt 1ah -- PCI bios
+ ************************************************************
+ */
+bios_1ah:
+gs	movw	OFFS_AX(%bp), %ax
+	cmpb	$0xb1, %ah
+	je	Lfunc_b1h
+	movw	$0xffff, %ax
+	ret
+Lfunc_b1h:
+	call	realmode_pci_bios
+	xorw	%ax, %ax			/* do nothing -- function not supported */
+	ret
+
+
+.globl ram_in_64kb_chunks
+.hidden ram_in_64kb_chunks
+.type ram_in_64kb_chunks, @function
+ram_in_64kb_chunks:
+	.word	0
+
+.globl bios_equipment
+.hidden bios_equipment
+.type bios_equipment, @function
+bios_equipment:
+	.word	0
diff --git a/arch/i386/lib/bios.h b/arch/i386/lib/bios.h
new file mode 100644
index 0000000..4901f89
--- /dev/null
+++ b/arch/i386/lib/bios.h
@@ -0,0 +1,94 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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 _BIOS_H_
+#define _BIOS_H_
+
+#define OFFS_ES      0     /* 16bit */
+#define OFFS_GS      2     /* 16bit */
+#define OFFS_DS      4     /* 16bit */
+#define OFFS_EDI     6     /* 32bit */
+#define OFFS_DI      6     /* low 16 bits of EDI */
+#define OFFS_ESI     10    /* 32bit */
+#define OFFS_SI      10    /* low 16 bits of ESI */
+#define OFFS_EBP     14    /* 32bit */
+#define OFFS_BP      14    /* low 16 bits of EBP */
+#define OFFS_ESP     18    /* 32bit */
+#define OFFS_SP      18    /* low 16 bits of ESP */
+#define OFFS_EBX     22    /* 32bit */
+#define OFFS_BX      22    /* low 16 bits of EBX */
+#define OFFS_BL      22    /* low  8 bits of BX */
+#define OFFS_BH      23    /* high 8 bits of BX */
+#define OFFS_EDX     26    /* 32bit */
+#define OFFS_DX      26    /* low 16 bits of EBX */
+#define OFFS_DL      26    /* low  8 bits of BX */
+#define OFFS_DH      27    /* high 8 bits of BX */
+#define OFFS_ECX     30    /* 32bit */
+#define OFFS_CX      30    /* low 16 bits of EBX */
+#define OFFS_CL      30    /* low  8 bits of BX */
+#define OFFS_CH      31    /* high 8 bits of BX */
+#define OFFS_EAX     34    /* 32bit */
+#define OFFS_AX      34    /* low 16 bits of EBX */
+#define OFFS_AL      34    /* low  8 bits of BX */
+#define OFFS_AH      35    /* high 8 bits of BX */
+#define OFFS_VECTOR  38    /* 16bit */
+#define OFFS_IP      40    /* 16bit */
+#define OFFS_CS      42    /* 16bit */
+#define OFFS_FLAGS   44    /* 16bit */
+
+#define SEGMENT      0x40
+#define STACK	     0x800			/* stack at 0x40:0x800 -> 0x800 */
+
+/* save general registers */
+/* save some segments     */
+/* save callers stack segment .. */
+/* ... in gs */
+	/* setup my segments */
+	/* setup BIOS stackpointer */
+
+#define MAKE_BIOS_STACK \
+	pushal		; \
+	pushw	%ds	; \
+	pushw	%gs	; \
+	pushw	%es	; \
+	pushw	%ss	; \
+	popw	%gs	; \
+	movw	$SEGMENT,%ax ; \
+	movw	%ax,%ds	; \
+	movw	%ax,%es	; \
+	movw	%ax,%ss	; \
+	movw	%sp,%bp	; \
+	movw	$STACK,%sp
+
+#define RESTORE_CALLERS_STACK \
+	pushw	%gs     ;			/* restore callers stack segment */ \
+	popw	%ss     ; \
+	movw	%bp,%sp	;			/* restore stackpointer */ \
+		\
+	popw	%es	;			/* restore segment selectors */ \
+	popw	%gs     ; \
+	popw	%ds     ; \
+		\
+	popal					/* restore GP registers */
+
+#endif
diff --git a/arch/i386/lib/bios_pci.S b/arch/i386/lib/bios_pci.S
new file mode 100644
index 0000000..9e412e5
--- /dev/null
+++ b/arch/i386/lib/bios_pci.S
@@ -0,0 +1,413 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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
+ */
+
+/*
+ * x86 realmode assembly implementation of a PCI BIOS
+ * for platforms that use one PCI hose and configuration
+ * access type 1. (The common case for low-end PC's)
+ */
+
+#include "bios.h"
+
+#define PCI_BIOS_DEBUG
+
+.section .bios, "ax"
+.code16
+.globl realmode_pci_bios_call_entry
+.hidden realmode_pci_bios_call_entry
+.type realmode_pci_bios_call_entry, @function
+realmode_pci_bios_call_entry:
+	MAKE_BIOS_STACK
+	call realmode_pci_bios
+	RESTORE_CALLERS_STACK
+	ret
+
+
+.globl realmode_pci_bios
+realmode_pci_bios:
+gs	movw	OFFS_AX(%bp), %ax
+	cmpb	$1, %al
+	je	pci_bios_present
+	cmpb	$2, %al
+	je	pci_bios_find_device
+	cmpb	$3, %al
+	je	pci_bios_find_class
+	cmpb	$6, %al
+	je	pci_bios_generate_special_cycle
+	cmpb	$8, %al
+	je	pci_bios_read_cfg_byte
+	cmpb	$9, %al
+	je	pci_bios_read_cfg_word
+	cmpb	$10, %al
+	je	pci_bios_read_cfg_dword
+	cmpb	$11, %al
+	je	pci_bios_write_cfg_byte
+	cmpb	$12, %al
+	je	pci_bios_write_cfg_word
+	cmpb	$13, %al
+	je	pci_bios_write_cfg_dword
+	cmpb	$14, %al
+	je	pci_bios_get_irq_routing
+	cmpb	$15, %al
+	je	pci_bios_set_irq
+	jmp	unknown_function
+
+/*****************************************************************************/
+
+pci_bios_present:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_present
+#endif
+	movl	$0x20494350, %eax
+gs	movl	%eax, OFFS_EDX(%bp)
+	movb	$0x01, %al
+gs	movb	%al, OFFS_AL(%bp)	/* We support cfg type 1 */
+	movw	$0x0210, %ax            /* version 2.10 */
+gs	movw	%ax, OFFS_BX(%bp)
+cs	movb	pci_last_bus, %al       /* last bus number */
+gs	movb	%al, OFFS_CL(%bp)
+	jmp	clear_carry
+
+/*****************************************************************************/
+
+/* device 0-31, function 0-7 */
+pci_bios_find_device:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_find_device
+#endif
+gs	movw	OFFS_CX(%bp), %di
+	shll	$16, %edi
+gs	movw	OFFS_DX(%bp), %di       /* edi now holds device in upper 16
+					 * bits and vendor in lower 16 bits */
+gs	movw	OFFS_SI(%bp), %si
+	xorw	%bx, %bx                /* start at bus 0 dev 0 function 0 */
+pfd_loop:
+	xorw	%ax, %ax		/* dword 0 is vendor/device */
+	call	__pci_bios_select_register
+	movw	$0xcfc, %dx
+	inl	%dx, %eax
+	cmpl	%edi, %eax		/* our device ? */
+	je	pfd_found_one
+pfd_next_dev:
+	/* check for multi function devices */
+	movw	%bx, %ax
+	andw	$3, %ax
+	jnz	pfd_function_not_zero
+	movw	$0x000c, %ax
+	call	__pci_bios_select_register
+	movw	$0xcfe, %dx
+	inb	%dx, %al
+	andb	$0x80, %al
+	jz	pfd_not_multi_function
+pfd_function_not_zero:
+	incw	%bx			/* next function, overflows in to
+					 * device number, then bus number */
+	jmp	pfd_check_bus
+
+pfd_not_multi_function:
+	andw	$0xfff8, %bx            /* remove function bits */
+	addw	$0x0008, %bx            /* next device, overflows in to bus number */
+pfd_check_bus:
+cs	movb	pci_last_bus, %ah
+	cmpb	%ah, %bh
+	ja	pfd_not_found
+	jmp	pfd_loop
+pfd_found_one:
+	decw	%si
+	js	pfd_done
+	jmp	pfd_next_dev
+
+pfd_done:
+gs	movw	%bx, OFFS_BX(%bp)
+	jmp	clear_carry
+
+pfd_not_found:
+	movb	$0x86, %ah              /* device not found */
+	jmp	set_carry
+
+/*****************************************************************************/
+
+pci_bios_find_class:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_find_class
+#endif
+gs	movl	OFFS_ECX(%bp), %edi
+	andl	$0x00ffffff, %edi       /* edi now holds class-code in lower 24 bits */
+gs	movw	OFFS_SI(%bp), %si
+	xorw	%bx, %bx                /* start at bus 0 dev 0 function 0 */
+pfc_loop:
+	movw	$8, %ax			/* dword 8 is class-code high 24bits */
+	call	__pci_bios_select_register
+	movw	$0xcfc, %dx
+	inl	%dx, %eax
+	shrl	$8, %eax
+	andl	$0x00ffffff, %eax
+	cmpl	%edi, %eax		/* our device ? */
+	je	pfc_found_one
+pfc_next_dev:
+	/* check for multi function devices */
+	andw	$3, %bx
+	jnz	pfc_function_not_zero
+	movw	$0x000c, %ax
+	call	__pci_bios_select_register
+	movw	$0xcfe, %dx
+	inb	%dx, %al
+	andb	$0x80, %al
+	jz	pfc_not_multi_function
+pfc_function_not_zero:
+	incw	%bx			/* next function, overflows in to
+					 * device number, then bus number */
+	jmp	pfc_check_bus
+
+pfc_not_multi_function:
+	andw	$0xfff8, %bx            /* remove function bits */
+	addw	$0x0008, %bx            /* next device, overflows in to bus number */
+pfc_check_bus:
+cs	movb	pci_last_bus, %ah
+	cmpb	%ah, %bh
+	ja	pfc_not_found
+	jmp	pfc_loop
+pfc_found_one:
+	decw	%si
+	js	pfc_done
+	jmp	pfc_next_dev
+
+pfc_done:
+gs	movw	%bx, OFFS_BX(%bp)
+	jmp	clear_carry
+
+pfc_not_found:
+	movb	$0x86, %ah              /* device not found */
+	jmp	set_carry
+
+/*****************************************************************************/
+
+pci_bios_generate_special_cycle:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_generate_special_cycle
+#endif
+	movb	$0x81, %ah              /* function not supported */
+	jmp	set_carry
+
+/*****************************************************************************/
+
+pci_bios_read_cfg_byte:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_read_cfg_byte
+#endif
+	call	pci_bios_select_register
+gs	movw	OFFS_DI(%bp), %dx
+	andw	$3, %dx
+	addw	$0xcfc, %dx
+	inb	%dx, %al
+gs	movb	%al, OFFS_CL(%bp)
+	jmp	clear_carry
+
+/*****************************************************************************/
+
+pci_bios_read_cfg_word:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_read_cfg_word
+#endif
+	call	pci_bios_select_register
+gs	movw	OFFS_DI(%bp), %dx
+	andw	$2, %dx
+	addw	$0xcfc, %dx
+	inw	%dx, %ax
+gs	movw	%ax, OFFS_CX(%bp)
+	jmp	clear_carry
+
+
+/*****************************************************************************/
+
+pci_bios_read_cfg_dword:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_read_cfg_dword
+#endif
+	call	pci_bios_select_register
+	movw	$0xcfc, %dx
+	inl	%dx, %eax
+gs	movl	%eax, OFFS_ECX(%bp)
+	jmp	clear_carry
+
+/*****************************************************************************/
+
+pci_bios_write_cfg_byte:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_write_cfg_byte
+#endif
+	call	pci_bios_select_register
+gs	movw	OFFS_DI(%bp), %dx
+gs	movb	OFFS_CL(%bp), %al
+	andw	$3, %dx
+	addw	$0xcfc, %dx
+	outb	%al, %dx
+	jmp	clear_carry
+
+/*****************************************************************************/
+
+pci_bios_write_cfg_word:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_write_cfg_word
+#endif
+	call	pci_bios_select_register
+gs	movw	OFFS_DI(%bp), %dx
+gs	movw	OFFS_CX(%bp), %ax
+	andw	$2, %dx
+	addw	$0xcfc, %dx
+	outw	%ax, %dx
+	jmp	clear_carry
+
+/*****************************************************************************/
+
+pci_bios_write_cfg_dword:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_write_cfg_dword
+#endif
+	call	pci_bios_select_register
+gs	movl	OFFS_ECX(%bp), %eax
+	movw	$0xcfc, %dx
+	outl	%eax, %dx
+	jmp	clear_carry
+
+/*****************************************************************************/
+
+pci_bios_get_irq_routing:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_get_irq_routing
+#endif
+	movb	$0x81, %ah              /* function not supported */
+	jmp	set_carry
+
+/*****************************************************************************/
+
+pci_bios_set_irq:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_set_irq
+#endif
+	movb	$0x81, %ah              /* function not supported */
+	jmp	set_carry
+
+/*****************************************************************************/
+
+unknown_function:
+#ifdef PCI_BIOS_DEBUG
+cs	incl	num_pci_bios_unknown_function
+#endif
+	movb	$0x81, %ah              /* function not supported */
+	jmp	set_carry
+
+/*****************************************************************************/
+
+pci_bios_select_register:
+gs	movw	OFFS_BX(%bp), %bx
+gs	movw	OFFS_DI(%bp), %ax
+/* destroys eax, dx */
+__pci_bios_select_register:               /* BX holds device id, AX holds register index */
+	pushl	%ebx
+	andl	$0xfc, %eax
+	andl	$0xffff, %ebx
+	shll	$8, %ebx
+	orl	%ebx, %eax
+	orl	$0x80000000, %eax
+	movw	$0xcf8, %dx
+	outl	%eax, %dx
+	popl	%ebx
+	ret
+
+
+clear_carry:
+gs	movw	OFFS_FLAGS(%bp), %ax
+	andw	$0xfffe, %ax			/* clear carry -- function succeeded */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+	xorw	%ax, %ax
+gs	movb	%ah, OFFS_AH(%bp)
+	ret
+
+set_carry:
+gs	movb	%ah, OFFS_AH(%bp)
+gs	movw	OFFS_FLAGS(%bp), %ax
+	orw	$1, %ax				/* return carry -- function not supported */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+	movw	$-1, %ax
+	ret
+
+/*****************************************************************************/
+
+.globl pci_last_bus
+pci_last_bus:
+	.byte	0
+
+#ifdef PCI_BIOS_DEBUG
+.globl num_pci_bios_present
+num_pci_bios_present:
+	.long	0
+
+.globl num_pci_bios_find_device
+num_pci_bios_find_device:
+	.long	0
+
+.globl num_pci_bios_find_class
+num_pci_bios_find_class:
+	.long	0
+
+.globl num_pci_bios_generate_special_cycle
+num_pci_bios_generate_special_cycle:
+	.long 0
+
+.globl num_pci_bios_read_cfg_byte
+num_pci_bios_read_cfg_byte:
+	.long	0
+
+.globl num_pci_bios_read_cfg_word
+num_pci_bios_read_cfg_word:
+	.long	0
+
+.globl num_pci_bios_read_cfg_dword
+num_pci_bios_read_cfg_dword:
+	.long	0
+
+.globl num_pci_bios_write_cfg_byte
+num_pci_bios_write_cfg_byte:
+	.long	0
+
+.globl num_pci_bios_write_cfg_word
+num_pci_bios_write_cfg_word:
+	.long	0
+
+.globl num_pci_bios_write_cfg_dword
+num_pci_bios_write_cfg_dword:
+	.long	0
+
+.globl num_pci_bios_get_irq_routing
+num_pci_bios_get_irq_routing:
+	.long	0
+
+.globl num_pci_bios_set_irq
+num_pci_bios_set_irq:
+	.long	0
+
+.globl num_pci_bios_unknown_function
+num_pci_bios_unknown_function:
+	.long	0
+#endif
diff --git a/arch/i386/lib/bios_setup.c b/arch/i386/lib/bios_setup.c
new file mode 100644
index 0000000..6491e52
--- /dev/null
+++ b/arch/i386/lib/bios_setup.c
@@ -0,0 +1,242 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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
+ */
+
+
+/*
+ * Partly based on msbios.c from rolo 1.6:
+ *----------------------------------------------------------------------
+ * (C) Copyright 2000
+ * Sysgo Real-Time Solutions GmbH
+ * Klein-Winternheim, Germany
+ *----------------------------------------------------------------------
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/realmode.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define NUMVECTS	256
+
+#define BIOS_DATA        ((char*)0x400)
+#define BIOS_DATA_SIZE   256
+#define BIOS_BASE        ((char*)0xf0000)
+#define BIOS_CS          0xf000
+
+extern ulong _i386boot_bios;
+extern ulong _i386boot_bios_size;
+
+/* these are defined in a 16bit segment and needs
+ * to be accessed with the RELOC_16_xxxx() macros below
+ */
+extern u16 ram_in_64kb_chunks;
+extern u16 bios_equipment;
+extern u8  pci_last_bus;
+
+extern void *rm_int00;
+extern void *rm_int01;
+extern void *rm_int02;
+extern void *rm_int03;
+extern void *rm_int04;
+extern void *rm_int05;
+extern void *rm_int06;
+extern void *rm_int07;
+extern void *rm_int08;
+extern void *rm_int09;
+extern void *rm_int0a;
+extern void *rm_int0b;
+extern void *rm_int0c;
+extern void *rm_int0d;
+extern void *rm_int0e;
+extern void *rm_int0f;
+extern void *rm_int10;
+extern void *rm_int11;
+extern void *rm_int12;
+extern void *rm_int13;
+extern void *rm_int14;
+extern void *rm_int15;
+extern void *rm_int16;
+extern void *rm_int17;
+extern void *rm_int18;
+extern void *rm_int19;
+extern void *rm_int1a;
+extern void *rm_int1b;
+extern void *rm_int1c;
+extern void *rm_int1d;
+extern void *rm_int1e;
+extern void *rm_int1f;
+extern void *rm_def_int;
+
+extern void *realmode_reset;
+extern void *realmode_pci_bios_call_entry;
+
+static int set_jmp_vector(int entry_point, void *target)
+{
+	if (entry_point & ~0xffff) {
+		return -1;
+	}
+
+	if (((u32)target-0xf0000) & ~0xffff) {
+		return -1;
+	}
+	printf("set_jmp_vector: 0xf000:%04x -> %p\n",
+	       entry_point, target);
+
+	/* jmp opcode */
+	writeb(0xea, 0xf0000 + entry_point);
+
+	/* offset */
+	writew(((u32)target-0xf0000), 0xf0000 + entry_point + 1);
+
+	/* segment */
+	writew(0xf000, 0xf0000 + entry_point + 3);
+
+	return 0;
+}
+
+
+/*
+ ************************************************************
+ * Install an interrupt vector
+ ************************************************************
+ */
+
+static void setvector(int vector, u16 segment, void *handler)
+{
+	u16 *ptr = (u16*)(vector*4);
+	ptr[0] = ((u32)handler - (segment << 4))&0xffff;
+	ptr[1] = segment;
+
+#if 0
+	printf("setvector: int%02x -> %04x:%04x\n",
+	       vector, ptr[1], ptr[0]);
+#endif
+}
+
+#define RELOC_16_LONG(seg, off) *(u32*)(seg << 4 | (u32)&off)
+#define RELOC_16_WORD(seg, off) *(u16*)(seg << 4 | (u32)&off)
+#define RELOC_16_BYTE(seg, off) *(u8*)(seg << 4 | (u32)&off)
+
+int bios_setup(void)
+{
+	ulong i386boot_bios      = (ulong)&_i386boot_bios;
+	ulong i386boot_bios_size = (ulong)&_i386boot_bios_size;
+
+	static int done=0;
+	int vector;
+#ifdef CONFIG_PCI
+	struct pci_controller *pri_hose;
+#endif
+	if (done) {
+		return 0;
+	}
+	done = 1;
+
+	if (i386boot_bios_size > 65536) {
+		printf("BIOS too large (%ld bytes, max is 65536)\n",
+		       i386boot_bios_size);
+		return -1;
+	}
+
+	memcpy(BIOS_BASE, (void*)i386boot_bios, i386boot_bios_size);
+
+	/* clear bda */
+	memset(BIOS_DATA, 0, BIOS_DATA_SIZE);
+
+	/* enter some values to the bda */
+	writew(0x3f8, BIOS_DATA);   /* com1 addr */
+	writew(0x2f8, BIOS_DATA+2); /* com2 addr */
+	writew(0x3e8, BIOS_DATA+4); /* com3 addr */
+	writew(0x2e8, BIOS_DATA+6); /* com4 addr */
+	writew(0x278, BIOS_DATA+8); /* lpt1 addr */
+	/*
+	 * The kernel wants to read the base memory size
+	 * from 40:13. Put a zero there to avoid an error message
+	 */
+	writew(0, BIOS_DATA+0x13);  /* base memory size */
+
+
+	/* setup realmode interrupt vectors */
+	for (vector = 0; vector < NUMVECTS; vector++) {
+		setvector(vector, BIOS_CS, &rm_def_int);
+	}
+
+	setvector(0x00, BIOS_CS, &rm_int00);
+	setvector(0x01, BIOS_CS, &rm_int01);
+	setvector(0x02, BIOS_CS, &rm_int02);
+	setvector(0x03, BIOS_CS, &rm_int03);
+	setvector(0x04, BIOS_CS, &rm_int04);
+	setvector(0x05, BIOS_CS, &rm_int05);
+	setvector(0x06, BIOS_CS, &rm_int06);
+	setvector(0x07, BIOS_CS, &rm_int07);
+	setvector(0x08, BIOS_CS, &rm_int08);
+	setvector(0x09, BIOS_CS, &rm_int09);
+	setvector(0x0a, BIOS_CS, &rm_int0a);
+	setvector(0x0b, BIOS_CS, &rm_int0b);
+	setvector(0x0c, BIOS_CS, &rm_int0c);
+	setvector(0x0d, BIOS_CS, &rm_int0d);
+	setvector(0x0e, BIOS_CS, &rm_int0e);
+	setvector(0x0f, BIOS_CS, &rm_int0f);
+	setvector(0x10, BIOS_CS, &rm_int10);
+	setvector(0x11, BIOS_CS, &rm_int11);
+	setvector(0x12, BIOS_CS, &rm_int12);
+	setvector(0x13, BIOS_CS, &rm_int13);
+	setvector(0x14, BIOS_CS, &rm_int14);
+	setvector(0x15, BIOS_CS, &rm_int15);
+	setvector(0x16, BIOS_CS, &rm_int16);
+	setvector(0x17, BIOS_CS, &rm_int17);
+	setvector(0x18, BIOS_CS, &rm_int18);
+	setvector(0x19, BIOS_CS, &rm_int19);
+	setvector(0x1a, BIOS_CS, &rm_int1a);
+	setvector(0x1b, BIOS_CS, &rm_int1b);
+	setvector(0x1c, BIOS_CS, &rm_int1c);
+	setvector(0x1d, BIOS_CS, &rm_int1d);
+	setvector(0x1e, BIOS_CS, &rm_int1e);
+	setvector(0x1f, BIOS_CS, &rm_int1f);
+
+	set_jmp_vector(0xfff0, &realmode_reset);
+	set_jmp_vector(0xfe6e, &realmode_pci_bios_call_entry);
+
+	/* fill in data area */
+	RELOC_16_WORD(0xf000, ram_in_64kb_chunks) = gd->ram_size >> 16;
+	RELOC_16_WORD(0xf000, bios_equipment) = 0; /* FixMe */
+
+	/* If we assume only one PCI hose, this PCI hose
+	 * will own PCI bus #0, and the last PCI bus of
+	 * that PCI hose will be the last PCI bus in the
+	 * system.
+	 * (This, ofcause break on multi hose systems,
+	 *  but our PCI BIOS only support one hose anyway)
+	 */
+#ifdef CONFIG_PCI
+	pri_hose = pci_bus_to_hose(0);
+	if (NULL != pri_hose) {
+		/* fill in last pci bus number for use by the realmode
+		 * PCI BIOS */
+		RELOC_16_BYTE(0xf000, pci_last_bus) = pri_hose->last_busno;
+	}
+#endif
+	return 0;
+}
diff --git a/arch/i386/lib/board.c b/arch/i386/lib/board.c
new file mode 100644
index 0000000..f3b6348
--- /dev/null
+++ b/arch/i386/lib/board.c
@@ -0,0 +1,429 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engstr�m, Omicron Ceti AB, daniel@omicron.se
+ *
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002
+ * 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>
+#include <watchdog.h>
+#include <command.h>
+#include <stdio_dev.h>
+#include <timestamp.h>
+#include <version.h>
+#include <malloc.h>
+#include <net.h>
+#include <ide.h>
+#include <asm/u-boot-i386.h>
+#include <elf.h>
+
+#ifdef CONFIG_BITBANGMII
+#include <miiphy.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Exports from the Linker Script */
+extern ulong _i386boot_text_start;
+extern ulong _i386boot_rel_dyn_start;
+extern ulong _i386boot_rel_dyn_end;
+extern ulong _i386boot_bss_start;
+extern ulong _i386boot_bss_size;
+void ram_bootstrap (void *);
+const char version_string[] =
+	U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")";
+
+/************************************************************************
+ * Init Utilities							*
+ ************************************************************************
+ * Some of this code should be moved into the core functions,
+ * or dropped completely,
+ * 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, 64);
+
+	gd->baudrate = (i != 0)
+			? (int) simple_strtoul (tmp, NULL, 10)
+			: CONFIG_BAUDRATE;
+
+	return (0);
+}
+
+static int display_banner (void)
+{
+
+	printf ("\n\n%s\n\n", version_string);
+/*
+	printf ("U-Boot code: %08lX -> %08lX  data: %08lX -> %08lX\n"
+		"        BSS: %08lX -> %08lX stack: %08lX -> %08lX\n",
+		i386boot_start, i386boot_romdata_start-1,
+		i386boot_romdata_dest, i386boot_romdata_dest+i386boot_romdata_size-1,
+		i386boot_bss_start, i386boot_bss_start+i386boot_bss_size-1,
+		i386boot_bss_start+i386boot_bss_size,
+		i386boot_bss_start+i386boot_bss_size+CONFIG_SYS_STACK_SIZE-1);
+
+*/
+
+	return (0);
+}
+
+/*
+ * WARNING: this code looks "cleaner" than the PowerPC version, but
+ * has the disadvantage that you either get nothing, or everything.
+ * On PowerPC, you might see "DRAM: " before the system hangs - which
+ * gives a simple yet clear indication which part of the
+ * initialization if failing.
+ */
+static int display_dram_config (void)
+{
+	int i;
+
+	puts ("DRAM Configuration:\n");
+
+	for (i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
+		printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
+		print_size (gd->bd->bi_dram[i].size, "\n");
+	}
+
+	return (0);
+}
+
+static void display_flash_config (ulong size)
+{
+	puts ("Flash: ");
+	print_size (size, "\n");
+}
+
+/*
+ * Breath some life into the board...
+ *
+ * Initialize an SMC for serial comms, and carry out some hardware
+ * tests.
+ *
+ * The first part of initialization is running from Flash memory;
+ * its main purpose is to initialize the RAM so that we
+ * can relocate the monitor code to RAM.
+ */
+
+
+/*
+ * 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_fnc_t *init_sequence[] = {
+	serial_init,
+	cpu_init_r,		/* basic cpu dependent setup */
+	board_early_init_r,	/* basic board dependent setup */
+	dram_init,		/* configure available RAM banks */
+	interrupt_init,		/* set up exceptions */
+	timer_init,
+	env_init,		/* initialize environment */
+	init_baudrate,		/* initialze baudrate settings */
+	serial_init,		/* serial communications setup */
+	display_banner,
+	display_dram_config,
+
+	NULL,
+};
+
+gd_t *gd;
+
+/*
+ * Load U-Boot into RAM, initialize BSS, perform relocation adjustments
+ */
+void board_init_f (ulong stack_limit)
+{
+	void *text_start = &_i386boot_text_start;
+	void *u_boot_cmd_end = &__u_boot_cmd_end;
+	Elf32_Rel *rel_dyn_start = (Elf32_Rel *)&_i386boot_rel_dyn_start;
+	Elf32_Rel *rel_dyn_end = (Elf32_Rel *)&_i386boot_rel_dyn_end;
+	void *bss_start = &_i386boot_bss_start;
+	void *bss_size = &_i386boot_bss_size;
+
+	size_t uboot_size;
+	void *ram_start;
+	ulong rel_offset;
+	Elf32_Rel *re;
+
+	void (*start_func)(void *);
+
+	/* compiler optimization barrier needed for GCC >= 3.4 */
+	__asm__ __volatile__("": : :"memory");
+
+	uboot_size = (size_t)u_boot_cmd_end - (size_t)text_start;
+	ram_start  = (void *)stack_limit - (uboot_size + (ulong)bss_size);
+	rel_offset = text_start - ram_start;
+	start_func = ram_bootstrap - rel_offset;
+
+	/* First stage CPU initialization */
+	if (cpu_init_f() != 0)
+		hang();
+
+	/* First stage Board initialization */
+	if (board_early_init_f() != 0)
+		hang();
+
+	/* Copy U-Boot into RAM */
+	memcpy(ram_start, text_start, (size_t)uboot_size);
+
+	/* Clear BSS */
+	memset(bss_start - rel_offset,	0, (size_t)bss_size);
+
+	/* Perform relocation adjustments */
+	for (re = rel_dyn_start; re < rel_dyn_end; re++)
+	{
+		if (re->r_offset >= TEXT_BASE)
+			if (*(ulong *)re->r_offset >= TEXT_BASE)
+				*(ulong *)(re->r_offset - rel_offset) -= (Elf32_Addr)rel_offset;
+	}
+
+	start_func(ram_start);
+
+	/* NOTREACHED - relocate_code() does not return */
+	while(1);
+}
+
+/*
+ * All attempts to jump straight from board_init_f() to board_init_r()
+ * have failed, hence this special 'bootstrap' function.
+ */
+void ram_bootstrap (void *ram_start)
+{
+	static gd_t gd_data;
+
+	/* compiler optimization barrier needed for GCC >= 3.4 */
+	__asm__ __volatile__("": : :"memory");
+
+	board_init_r(&gd_data, (ulong)ram_start);
+}
+
+void board_init_r(gd_t *id, ulong ram_start)
+{
+	char *s;
+	int i;
+	ulong size;
+	static bd_t bd_data;
+	init_fnc_t **init_fnc_ptr;
+
+	show_boot_progress(0x21);
+
+	gd = id;
+	/* compiler optimization barrier needed for GCC >= 3.4 */
+	__asm__ __volatile__("": : :"memory");
+
+	memset (gd, 0, sizeof (gd_t));
+	gd->bd = &bd_data;
+	memset (gd->bd, 0, sizeof (bd_t));
+	show_boot_progress(0x22);
+
+	gd->baudrate =  CONFIG_BAUDRATE;
+
+	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
+
+	mem_malloc_init((((ulong)ram_start - CONFIG_SYS_MALLOC_LEN)+3)&~3,
+			CONFIG_SYS_MALLOC_LEN);
+
+	for (init_fnc_ptr = init_sequence, i=0; *init_fnc_ptr; ++init_fnc_ptr, i++) {
+		show_boot_progress(0xa130|i);
+
+		if ((*init_fnc_ptr)() != 0) {
+			hang ();
+		}
+	}
+	show_boot_progress(0x23);
+
+	/* configure available FLASH banks */
+	size = flash_init();
+	display_flash_config(size);
+	show_boot_progress(0x24);
+
+	show_boot_progress(0x25);
+
+	/* initialize environment */
+	env_relocate ();
+	show_boot_progress(0x26);
+
+
+	/* IP Address */
+	bd_data.bi_ip_addr = getenv_IPaddr ("ipaddr");
+
+#if defined(CONFIG_PCI)
+	/*
+	 * Do pci configuration
+	 */
+	pci_init();
+#endif
+
+	show_boot_progress(0x27);
+
+
+	stdio_init ();
+
+	jumptable_init ();
+
+	/* Initialize the console (after the relocation and devices init) */
+	console_init_r();
+
+#ifdef CONFIG_MISC_INIT_R
+	/* miscellaneous platform dependent initialisations */
+	misc_init_r();
+#endif
+
+#if defined(CONFIG_CMD_PCMCIA) && !defined(CONFIG_CMD_IDE)
+	WATCHDOG_RESET();
+	puts ("PCMCIA:");
+	pcmcia_init();
+#endif
+
+#if defined(CONFIG_CMD_KGDB)
+	WATCHDOG_RESET();
+	puts("KGDB:  ");
+	kgdb_init();
+#endif
+
+	/* enable exceptions */
+	enable_interrupts();
+	show_boot_progress(0x28);
+
+	/* Must happen after interrupts are initialized since
+	 * an irq handler gets installed
+	 */
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
+	serial_buffered_init();
+#endif
+
+#ifdef CONFIG_STATUS_LED
+	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_CMD_IDE)
+	WATCHDOG_RESET();
+	puts("IDE:   ");
+	ide_init();
+#endif
+
+#if defined(CONFIG_CMD_SCSI)
+	WATCHDOG_RESET();
+	puts("SCSI:  ");
+	scsi_init();
+#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(gd->bd);
+#endif
+
+#if ( defined(CONFIG_CMD_NET)) && (0)
+	WATCHDOG_RESET();
+# ifdef DEBUG
+	puts ("Reset Ethernet PHY\n");
+# endif
+	reset_phy();
+#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
+
+
+#ifdef CONFIG_POST
+	post_run (NULL, POST_RAM | post_bootmode_get(0));
+#endif
+
+
+	show_boot_progress(0x29);
+
+	/* main_loop() can return to retry autoboot, if so just run it again. */
+	for (;;) {
+		main_loop();
+	}
+
+	/* NOTREACHED - no way out of command loop except booting */
+}
+
+void hang (void)
+{
+	puts ("### ERROR ### Please RESET the board ###\n");
+	for (;;);
+}
+
+unsigned long do_go_exec (ulong (*entry)(int, char *[]), int argc, char *argv[])
+{
+	/*
+	 * TODO: Test this function - changed to fix compiler error.
+	 * Original code was:
+	 *   return (entry >> 1) (argc, argv);
+	 * with a comment about Nios function pointers are address >> 1
+	 */
+	return (entry) (argc, argv);
+}
diff --git a/arch/i386/lib/bootm.c b/arch/i386/lib/bootm.c
new file mode 100644
index 0000000..f96d7bd
--- /dev/null
+++ b/arch/i386/lib/bootm.c
@@ -0,0 +1,94 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * Copyright (C) 2001  Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 <image.h>
+#include <u-boot/zlib.h>
+#include <asm/byteorder.h>
+#include <asm/zimage.h>
+
+/*cmd_boot.c*/
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	void		*base_ptr;
+	ulong		os_data, os_len;
+	image_header_t	*hdr;
+
+#if defined(CONFIG_FIT)
+	const void	*data;
+	size_t		len;
+#endif
+
+	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+		return 1;
+
+	if (images->legacy_hdr_valid) {
+		hdr = images->legacy_hdr_os;
+		if (image_check_type (hdr, IH_TYPE_MULTI)) {
+			/* if multi-part image, we need to get first subimage */
+			image_multi_getimg (hdr, 0, &os_data, &os_len);
+		} else {
+			/* otherwise get image data */
+			os_data = image_get_data (hdr);
+			os_len = image_get_data_size (hdr);
+		}
+#if defined(CONFIG_FIT)
+	} else if (images->fit_uname_os) {
+		ret = fit_image_get_data (images->fit_hdr_os,
+					images->fit_noffset_os, &data, &len);
+		if (ret) {
+			puts ("Can't get image data/size!\n");
+			goto error;
+		}
+		os_data = (ulong)data;
+		os_len = (ulong)len;
+#endif
+	} else {
+		puts ("Could not find kernel image!\n");
+		goto error;
+	}
+
+	base_ptr = load_zimage ((void*)os_data, os_len,
+			images->rd_start, images->rd_end - images->rd_start, 0);
+
+	if (NULL == base_ptr) {
+		printf ("## Kernel loading failed ...\n");
+		goto error;
+
+	}
+
+#ifdef DEBUG
+	printf ("## Transferring control to Linux (at address %08x) ...\n",
+		(u32)base_ptr);
+#endif
+
+	/* we assume that the kernel is in place */
+	printf("\nStarting kernel ...\n\n");
+
+	boot_zimage(base_ptr);
+	/* does not return */
+
+error:
+	return 1;
+}
diff --git a/arch/i386/lib/interrupts.c b/arch/i386/lib/interrupts.c
new file mode 100644
index 0000000..51def59
--- /dev/null
+++ b/arch/i386/lib/interrupts.c
@@ -0,0 +1,161 @@
+/*
+ * (C) Copyright 2009
+ * Graeme Russ, graeme.russ@gmail.com
+ *
+ * (C) Copyright 2007
+ * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com
+ *
+ * (C) Copyright 2006
+ * Detlev Zundel, DENX Software Engineering, dzu@denx.de
+ *
+ * (C) Copyright -2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * (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 file contains the high-level API for the interrupt sub-system
+ * of the i386 port of U-Boot. Most of the functionality has been
+ * shamelessly stolen from the leon2 / leon3 ports of U-Boot.
+ * Daniel Hellstrom, Detlev Zundel, Wolfgang Denk and Josh Huber are
+ * credited for the corresponding work on those ports. The original
+ * interrupt handling routines for the i386 port were written by
+ * Daniel Engström
+ */
+
+#include <common.h>
+#include <asm/interrupt.h>
+
+struct irq_action {
+	interrupt_handler_t *handler;
+	void *arg;
+	unsigned int count;
+};
+
+static struct irq_action irq_handlers[CONFIG_SYS_NUM_IRQS] = { {0} };
+static int spurious_irq_cnt = 0;
+static int spurious_irq = 0;
+
+void irq_install_handler(int irq, interrupt_handler_t *handler, void *arg)
+{
+	int status;
+
+	if (irq < 0 || irq >= CONFIG_SYS_NUM_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);
+
+	status = disable_interrupts ();
+
+	irq_handlers[irq].handler = handler;
+	irq_handlers[irq].arg = arg;
+	irq_handlers[irq].count = 0;
+
+	unmask_irq(irq);
+
+	if (status)
+		enable_interrupts();
+
+	return;
+}
+
+void irq_free_handler(int irq)
+{
+	int status;
+
+	if (irq < 0 || irq >= CONFIG_SYS_NUM_IRQS) {
+		printf("irq_free_handler: bad irq number %d\n", irq);
+		return;
+	}
+
+	status = disable_interrupts ();
+
+	mask_irq(irq);
+
+	irq_handlers[irq].handler = NULL;
+	irq_handlers[irq].arg = NULL;
+
+	if (status)
+		enable_interrupts();
+
+	return;
+}
+
+void do_irq(int hw_irq)
+{
+	int irq = hw_irq - 0x20;
+
+	if (irq < 0 || irq >= CONFIG_SYS_NUM_IRQS) {
+		printf("do_irq: bad irq number %d\n", irq);
+		return;
+	}
+
+	if (irq_handlers[irq].handler) {
+		mask_irq(irq);
+
+		irq_handlers[irq].handler(irq_handlers[irq].arg);
+		irq_handlers[irq].count++;
+
+		unmask_irq(irq);
+		specific_eoi(irq);
+
+	} else {
+		if ((irq & 7) != 7) {
+			spurious_irq_cnt++;
+			spurious_irq = irq;
+		}
+	}
+}
+
+#if defined(CONFIG_CMD_IRQ)
+int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	int irq;
+
+	printf("Spurious IRQ: %u, last unknown IRQ: %d\n",
+	       spurious_irq_cnt, spurious_irq);
+
+	printf ("Interrupt-Information:\n");
+	printf ("Nr  Routine   Arg       Count\n");
+
+	for (irq = 0; irq <= CONFIG_SYS_NUM_IRQS; irq++) {
+		if (irq_handlers[irq].handler != NULL) {
+			printf ("%02d  %08lx  %08lx  %d\n",
+					irq,
+					(ulong)irq_handlers[irq].handler,
+					(ulong)irq_handlers[irq].arg,
+					irq_handlers[irq].count);
+		}
+	}
+
+	return 0;
+}
+#endif
diff --git a/arch/i386/lib/pcat_interrupts.c b/arch/i386/lib/pcat_interrupts.c
new file mode 100644
index 0000000..67e6e97
--- /dev/null
+++ b/arch/i386/lib/pcat_interrupts.c
@@ -0,0 +1,132 @@
+/*
+ * (C) Copyright 2009
+ * Graeme Russ, graeme.russ@gmail.com
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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 provides the interrupt handling functionality for systems
+ * based on the standard PC/AT architecture using two cascaded i8259
+ * Programmable Interrupt Controllers.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/i8259.h>
+#include <asm/ibmpc.h>
+#include <asm/interrupt.h>
+
+#if CONFIG_SYS_NUM_IRQS != 16
+#error "CONFIG_SYS_NUM_IRQS must equal 16 if CONFIG_SYS_NUM_IRQS is defined"
+#endif
+
+int interrupt_init(void)
+{
+	u8 i;
+
+	disable_interrupts();
+
+	/* Mask all interrupts */
+	outb(0xff, MASTER_PIC + IMR);
+	outb(0xff, SLAVE_PIC + IMR);
+
+	/* Master PIC */
+	/* Place master PIC interrupts at INT20 */
+	/* ICW3, One slave PIC is present */
+	outb(ICW1_SEL|ICW1_EICW4, MASTER_PIC + ICW1);
+	outb(0x20, MASTER_PIC + ICW2);
+	outb(IR2, MASTER_PIC + ICW3);
+	outb(ICW4_PM, MASTER_PIC + ICW4);
+
+	for (i = 0; i < 8; i++)
+		outb(OCW2_SEOI | i, MASTER_PIC + OCW2);
+
+	/* Slave PIC */
+	/* Place slave PIC interrupts at INT28 */
+	/* Slave ID */
+	outb(ICW1_SEL|ICW1_EICW4, SLAVE_PIC + ICW1);
+	outb(0x28, SLAVE_PIC + ICW2);
+	outb(0x02, SLAVE_PIC + ICW3);
+	outb(ICW4_PM, SLAVE_PIC + ICW4);
+
+	for (i = 0; i < 8; i++)
+		outb(OCW2_SEOI | i, SLAVE_PIC + OCW2);
+
+	/*
+	 * Enable cascaded interrupts by unmasking the cascade IRQ pin of
+	 * the master PIC
+	 */
+	unmask_irq (2);
+
+	enable_interrupts();
+
+	return 0;
+}
+
+void mask_irq(int irq)
+{
+	int imr_port;
+
+	if (irq >= CONFIG_SYS_NUM_IRQS)
+		return;
+
+	if (irq > 7)
+		imr_port = SLAVE_PIC + IMR;
+	else
+		imr_port = MASTER_PIC + IMR;
+
+	outb(inb(imr_port) | (1 << (irq & 7)), imr_port);
+}
+
+void unmask_irq(int irq)
+{
+	int imr_port;
+
+	if (irq >= CONFIG_SYS_NUM_IRQS)
+		return;
+
+	if (irq > 7)
+		imr_port = SLAVE_PIC + IMR;
+	else
+		imr_port = MASTER_PIC + IMR;
+
+	outb(inb(imr_port) & ~(1 << (irq & 7)), imr_port);
+}
+
+void specific_eoi(int irq)
+{
+	if (irq >= CONFIG_SYS_NUM_IRQS)
+		return;
+
+	if (irq > 7) {
+		/*
+		 *  IRQ is on the slave - Issue a corresponding EOI to the
+		 *  slave PIC and an EOI for IRQ2 (the cascade interrupt)
+		 *  on the master PIC
+		 */
+		outb(OCW2_SEOI | (irq & 7), SLAVE_PIC + OCW2);
+		irq = SEOI_IR2;
+	}
+
+	outb(OCW2_SEOI | irq, MASTER_PIC + OCW2);
+}
diff --git a/arch/i386/lib/pcat_timer.c b/arch/i386/lib/pcat_timer.c
new file mode 100644
index 0000000..1373fd1
--- /dev/null
+++ b/arch/i386/lib/pcat_timer.c
@@ -0,0 +1,107 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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/i8254.h>
+#include <asm/ibmpc.h>
+#include <asm/interrupt.h>
+
+#define TIMER0_VALUE 0x04aa /* 1kHz 1.9318MHz / 1000 */
+#define TIMER2_VALUE 0x0a8e /* 440Hz */
+
+static int timer_init_done = 0;
+
+int timer_init(void)
+{
+	/* initialize timer 0 and 2
+	 *
+	 * Timer 0 is used to increment system_tick 1000 times/sec
+	 * Timer 1 was used for DRAM refresh in early PC's
+	 * Timer 2 is used to drive the speaker
+	 * (to stasrt a beep: write 3 to port 0x61,
+	 * to stop it again: write 0)
+	 */
+	outb (PIT_CMD_CTR0 | PIT_CMD_BOTH | PIT_CMD_MODE2,
+	      PIT_BASE + PIT_COMMAND);
+	outb (TIMER0_VALUE & 0xff, PIT_BASE + PIT_T0);
+	outb (TIMER0_VALUE >> 8, PIT_BASE + PIT_T0);
+
+	outb (PIT_CMD_CTR2 | PIT_CMD_BOTH | PIT_CMD_MODE3,
+	      PIT_BASE + PIT_COMMAND);
+	outb (TIMER2_VALUE & 0xff, PIT_BASE + PIT_T2);
+	outb (TIMER2_VALUE >> 8, PIT_BASE + PIT_T2);
+
+	irq_install_handler (0, timer_isr, NULL);
+	unmask_irq (0);
+
+	timer_init_done = 1;
+
+	return 0;
+}
+
+static u16 read_pit(void)
+{
+	u8 low;
+
+	outb (PIT_CMD_LATCH, PIT_BASE + PIT_COMMAND);
+	low = inb (PIT_BASE + PIT_T0);
+
+	return ((inb (PIT_BASE + PIT_T0) << 8) | low);
+}
+
+/* this is not very exact */
+void __udelay (unsigned long usec)
+{
+	int counter;
+	int wraps;
+
+	if (timer_init_done)
+	{
+		counter = read_pit ();
+		wraps = usec / 1000;
+		usec = usec % 1000;
+
+		usec *= 1194;
+		usec /= 1000;
+		usec += counter;
+
+		while (usec > 1194) {
+			usec -= 1194;
+			wraps++;
+		}
+
+		while (1) {
+			int new_count = read_pit ();
+
+			if (((new_count < usec) && !wraps) || wraps < 0)
+				break;
+
+			if (new_count > counter)
+				wraps--;
+
+			counter = new_count;
+		}
+	}
+
+}
diff --git a/arch/i386/lib/pci.c b/arch/i386/lib/pci.c
new file mode 100644
index 0000000..9020e7c
--- /dev/null
+++ b/arch/i386/lib/pci.c
@@ -0,0 +1,152 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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>
+#include <asm/io.h>
+#include <asm/pci.h>
+
+#undef PCI_ROM_SCAN_VERBOSE
+
+int pci_shadow_rom(pci_dev_t dev, unsigned char *dest)
+{
+	struct pci_controller *hose;
+	int res = -1;
+	int i;
+
+	u32 rom_addr;
+	u32 addr_reg;
+	u32 size;
+
+	u16 vendor;
+	u16 device;
+	u32 class_code;
+
+	hose = pci_bus_to_hose(PCI_BUS(dev));
+#if 0
+	printf("pci_shadow_rom() asked to shadow device %x to %x\n",
+	       dev, (u32)dest);
+#endif
+	pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
+	pci_read_config_word(dev, PCI_DEVICE_ID, &device);
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_code);
+
+	class_code &= 0xffffff00;
+	class_code >>= 8;
+
+#if 0
+	printf("PCI Header Vendor %04x device %04x class %06x\n",
+	       vendor, device, class_code);
+#endif
+	/* Enable the rom addess decoder */
+	pci_write_config_dword(dev, PCI_ROM_ADDRESS, (u32)PCI_ROM_ADDRESS_MASK);
+	pci_read_config_dword(dev, PCI_ROM_ADDRESS, &addr_reg);
+
+	if (!addr_reg) {
+		/* register unimplemented */
+		printf("pci_chadow_rom: device do not seem to have a rom\n");
+		return -1;
+	}
+
+	size = (~(addr_reg&PCI_ROM_ADDRESS_MASK))+1;
+
+#if 0
+	printf("ROM is %d bytes\n", size);
+#endif
+	rom_addr = pci_get_rom_window(hose, size);
+#if 0
+	printf("ROM mapped at %x \n", rom_addr);
+#endif
+	pci_write_config_dword(dev, PCI_ROM_ADDRESS,
+			       pci_phys_to_mem(dev, rom_addr)
+			       |PCI_ROM_ADDRESS_ENABLE);
+
+
+	for (i=rom_addr;i<rom_addr+size; i+=512) {
+
+
+		if (readw(i) == 0xaa55) {
+			u32 pci_data;
+#ifdef PCI_ROM_SCAN_VERBOSE
+			printf("ROM signature found\n");
+#endif
+			pci_data = readw(0x18+i);
+			pci_data += i;
+
+			if (0==memcmp((void*)pci_data, "PCIR", 4)) {
+#ifdef PCI_ROM_SCAN_VERBOSE
+				printf("Fount PCI rom image at offset %d\n", i-rom_addr);
+				printf("Vendor %04x device %04x class %06x\n",
+				       readw(pci_data+4), readw(pci_data+6),
+				       readl(pci_data+0x0d)&0xffffff);
+				printf("%s\n",
+				       (readw(pci_data+0x15) &0x80)?
+				       "Last image":"More images follow");
+				switch	(readb(pci_data+0x14)) {
+				case 0:
+					printf("X86 code\n");
+					break;
+				case 1:
+					printf("Openfirmware code\n");
+					break;
+				case 2:
+					printf("PARISC code\n");
+					break;
+				}
+				printf("Image size %d\n", readw(pci_data+0x10) * 512);
+#endif
+				/* FixMe: I think we should compare the class code
+				 * bytes as well but I have no reference on the
+				 * exact order of these bytes in the PCI ROM header */
+				if (readw(pci_data+4) == vendor &&
+				    readw(pci_data+6) == device &&
+				    /* (readl(pci_data+0x0d)&0xffffff) == class_code && */
+				    readb(pci_data+0x14) == 0 /* x86 code image */ ) {
+#ifdef PCI_ROM_SCAN_VERBOSE
+					printf("Suitable ROM image found, copying\n");
+#endif
+					memmove(dest, (void*)rom_addr, readw(pci_data+0x10) * 512);
+					res = 0;
+					break;
+
+				}
+				if (readw(pci_data+0x15) &0x80) {
+					break;
+				}
+			}
+		}
+
+	}
+
+#ifdef PCI_ROM_SCAN_VERBOSE
+	if (res) {
+		printf("No suitable image found\n");
+	}
+#endif
+	/* disable PAR register and PCI device ROM address devocer */
+	pci_remove_rom_window(hose, rom_addr);
+
+	pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
+
+	return res;
+}
diff --git a/arch/i386/lib/pci_type1.c b/arch/i386/lib/pci_type1.c
new file mode 100644
index 0000000..225ae4a
--- /dev/null
+++ b/arch/i386/lib/pci_type1.c
@@ -0,0 +1,51 @@
+/*
+ * Support for type PCI configuration cycles.
+ * based on pci_indirect.c
+ *
+ * Copyright (C) 2002 Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/io.h>
+#include <pci.h>
+
+#define cfg_read(val, addr, op)	*val = op((int)(addr))
+#define cfg_write(val, addr, op)	op((val), (int)(addr))
+
+#define TYPE1_PCI_OP(rw, size, type, op, mask)				\
+static int								\
+type1_##rw##_config_##size(struct pci_controller *hose,			\
+			      pci_dev_t dev, int offset, type val)	\
+{									\
+	outl(dev | (offset & 0xfc) | 0x80000000, (int)hose->cfg_addr);	\
+	cfg_##rw(val, hose->cfg_data + (offset & mask), op);		\
+	return 0;							\
+}
+
+
+TYPE1_PCI_OP(read, byte, u8 *, inb, 3)
+TYPE1_PCI_OP(read, word, u16 *, inw, 2)
+TYPE1_PCI_OP(read, dword, u32 *, inl, 0)
+
+TYPE1_PCI_OP(write, byte, u8, outb, 3)
+TYPE1_PCI_OP(write, word, u16, outw, 2)
+TYPE1_PCI_OP(write, dword, u32, outl, 0)
+
+void pci_setup_type1(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+{
+	pci_set_ops(hose,
+		    type1_read_config_byte,
+		    type1_read_config_word,
+		    type1_read_config_dword,
+		    type1_write_config_byte,
+		    type1_write_config_word,
+		    type1_write_config_dword);
+
+	hose->cfg_addr = (unsigned int *) cfg_addr;
+	hose->cfg_data = (unsigned char *) cfg_data;
+}
diff --git a/arch/i386/lib/realmode.c b/arch/i386/lib/realmode.c
new file mode 100644
index 0000000..3c3c1fc
--- /dev/null
+++ b/arch/i386/lib/realmode.c
@@ -0,0 +1,100 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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/ptrace.h>
+#include <asm/realmode.h>
+
+
+#define REALMODE_BASE    ((char*)0x7c0)
+#define REALMODE_MAILBOX ((char*)0xe00)
+
+
+extern ulong _i386boot_realmode;
+extern ulong _i386boot_realmode_size;
+extern char realmode_enter;
+
+int realmode_setup(void)
+{
+	ulong i386boot_realmode      = (ulong)&_i386boot_realmode;
+	ulong i386boot_realmode_size = (ulong)&_i386boot_realmode_size;
+
+	/* copy the realmode switch code */
+	if (i386boot_realmode_size > (REALMODE_MAILBOX-REALMODE_BASE)) {
+		printf("realmode switch too large (%ld bytes, max is %d)\n",
+		       i386boot_realmode_size, (REALMODE_MAILBOX-REALMODE_BASE));
+		return -1;
+	}
+
+	memcpy(REALMODE_BASE, (void*)i386boot_realmode, i386boot_realmode_size);
+	asm("wbinvd\n");
+
+	return 0;
+}
+
+int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out)
+{
+
+	/* setup out thin bios emulation */
+	if (bios_setup()) {
+		return -1;
+	}
+
+	if (realmode_setup()) {
+		return -1;
+	}
+
+	in->eip = off;
+	in->xcs = seg;
+	if (3>(in->esp & 0xffff)) {
+		printf("Warning: entering realmode with sp < 4 will fail\n");
+	}
+
+	memcpy(REALMODE_MAILBOX, in, sizeof(struct pt_regs));
+	asm("wbinvd\n");
+
+	__asm__ volatile (
+		 "lcall $0x20,%0\n"  : :  "i" (&realmode_enter) );
+
+	asm("wbinvd\n");
+	memcpy(out, REALMODE_MAILBOX, sizeof(struct pt_regs));
+
+	return out->eax;
+}
+
+
+/* This code is supposed to access a realmode interrupt
+ * it does currently not work for me */
+int enter_realmode_int(u8 lvl, struct pt_regs *in, struct pt_regs *out)
+{
+	/* place two instructions at 0x700 */
+	writeb(0xcd, 0x700);  /* int $lvl */
+	writeb(lvl, 0x701);
+	writeb(0xcb, 0x702);  /* lret */
+	asm("wbinvd\n");
+
+	enter_realmode(0x00, 0x700, in, out);
+
+	return out->eflags&1;
+}
diff --git a/arch/i386/lib/realmode_switch.S b/arch/i386/lib/realmode_switch.S
new file mode 100644
index 0000000..d6c74ec
--- /dev/null
+++ b/arch/i386/lib/realmode_switch.S
@@ -0,0 +1,222 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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
+ */
+
+
+/* 32bit -> 16bit -> 32bit mode switch code */
+
+/*
+ * Stack frame at 0xe00
+ *	e00 ebx;
+ *	e04 ecx;
+ *	e08 edx;
+ *	e0c esi;
+ *	e10 edi;
+ *	e14 ebp;
+ *	e18 eax;
+ *	e1c ds;
+ *	e20 es;
+ *	e24 fs;
+ *	e28 gs;
+ *	e2c orig_eax;
+ *	e30 eip;
+ *	e34 cs;
+ *	e38 eflags;
+ *	e3c esp;
+ *	e40 ss;
+ */
+
+#define a32		.byte 0x67;		/* address size prefix 32 */
+#define o32		.byte 0x66;		/* operand size prefix 32 */
+
+.section .realmode, "ax"
+.code16
+						/* 16bit protected mode code here */
+.globl realmode_enter
+realmode_enter:
+o32	pusha
+o32	pushf
+	cli
+	sidt	saved_idt
+	sgdt	saved_gdt
+	movl	%esp, %eax
+	movl	%eax, saved_protected_mode_esp
+
+	movl	$0x10, %eax
+	movl	%eax, %esp
+	movw	$0x28, %ax
+	movw	%ax, %ds
+	movw	%ax, %es
+	movw	%ax, %fs
+	movw	%ax, %gs
+
+	lidt	realmode_idt_ptr
+	movl	%cr0, %eax			/* Go back into real mode by */
+	andl	$0x7ffffffe, %eax		/* clearing PE to 0 */
+	movl	%eax, %cr0
+	ljmp	$0x0,$do_realmode		/* switch to real mode */
+
+do_realmode:					/* realmode code from here */
+	movw	%cs,%ax
+	movw	%ax,%ds
+	movw	%ax,%es
+	movw	%ax,%fs
+	movw	%ax,%gs
+
+						/* create a temporary stack */
+
+	movw	$0xc0, %ax
+	movw	%ax, %ss
+	movw	$0x200, %ax
+	movw	%ax, %sp
+
+	popl	%ebx
+	popl	%ecx
+	popl	%edx
+	popl	%esi
+	popl	%edi
+	popl	%ebp
+	popl	%eax
+	movl	%eax, temp_eax
+	popl	%eax
+	movw	%ax, %ds
+	popl	%eax
+	movw	%ax, %es
+	popl	%eax
+	movw	%ax, %fs
+	popl	%eax
+	movw	%ax, %gs
+	popl	%eax				/* orig_eax */
+	popl	%eax
+cs	movw	%ax, temp_ip
+	popl	%eax
+cs	movw	%ax, temp_cs
+o32	popf
+	popl	%eax
+	popw	%ss
+	movl	%eax, %esp
+cs	movl	temp_eax, %eax
+	wbinvd					/* self-modifying code,
+						 * better flush the cache */
+
+	.byte	0x9a				/* lcall */
+temp_ip:
+	.word	0				/* new ip */
+temp_cs:
+	.word	0				/* new cs */
+realmode_ret:
+						/* save eax, esp and ss */
+cs	movl	%eax, saved_eax
+	movl	%esp, %eax
+cs	movl	%eax, saved_esp
+	movw	%ss, %ax
+cs	movw	%ax, saved_ss
+
+	/* restore the stack, note that we set sp to 0x244;
+	 * pt_regs is 0x44 bytes long and we push the structure
+	 * backwards on to the stack, bottom first */
+
+	movw	$0xc0, %ax
+	movw	%ax, %ss
+	movw	$0x244, %ax
+	movw	%ax, %sp
+
+	xorl	%eax,%eax
+cs	movw	saved_ss, %ax
+	pushl	%eax
+cs	movl	saved_esp, %eax
+	pushl	%eax
+o32	pushf
+	xorl	%eax,%eax
+cs	movw	temp_cs, %ax
+	pushl	%eax
+cs	movw	temp_ip, %ax
+	pushl	%eax
+	pushl	$0
+	movw	%gs, %ax
+	pushl	%eax
+	movw	%fs, %ax
+	pushl	%eax
+	movw	%es, %ax
+	pushl	%eax
+	movw	%ds, %ax
+	pushl	%eax
+	movl	saved_eax, %eax
+	pushl	%eax
+	pushl	%ebp
+	pushl	%edi
+	pushl	%esi
+	pushl	%edx
+	pushl	%ecx
+	pushl	%ebx
+
+o32 cs	lidt	saved_idt
+o32 cs	lgdt	saved_gdt			/* Set GDTR */
+
+	movl	%cr0, %eax			/* Go back into protected mode */
+	orl	$1,%eax	/* reset PE to 1 */
+	movl	%eax, %cr0
+	jmp	next_line			/* flush prefetch queue */
+next_line:
+	movw	$return_ptr, %ax
+	movw	%ax,%bp
+o32 cs	ljmp	*(%bp)
+
+.code32
+protected_mode:
+	movl	$0x18,%eax			/* reload GDT[3] */
+	movw	%ax,%fs				/* reset FS */
+	movw	%ax,%ds				/* reset DS */
+	movw	%ax,%gs				/* reset GS */
+	movw	%ax,%es				/* reset ES */
+	movw	%ax,%ss				/* reset SS */
+	movl	saved_protected_mode_esp, %eax
+	movl	%eax, %esp
+	popf
+	popa
+	ret
+
+temp_eax:
+	.long	0
+
+saved_ss:
+	.word	0
+saved_esp:
+	.long	0
+saved_eax:
+	.long	0
+
+realmode_idt_ptr:
+	.word	0x400
+	.word	0x0, 0x0
+
+saved_gdt:
+	.word	0, 0, 0, 0
+saved_idt:
+	.word	0, 0, 0, 0
+
+saved_protected_mode_esp:
+	.long	0
+
+return_ptr:
+	.long	protected_mode
+	.word	0x10
diff --git a/arch/i386/lib/timer.c b/arch/i386/lib/timer.c
new file mode 100644
index 0000000..5cb1f54
--- /dev/null
+++ b/arch/i386/lib/timer.c
@@ -0,0 +1,107 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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 <asm/io.h>
+#include <asm/i8254.h>
+#include <asm/ibmpc.h>
+
+struct timer_isr_function {
+	struct timer_isr_function *next;
+	timer_fnc_t *isr_func;
+};
+
+static struct timer_isr_function *first_timer_isr = NULL;
+static volatile unsigned long system_ticks = 0;
+
+/*
+ * register_timer_isr() allows multiple architecture and board specific
+ * functions to be called every millisecond. Keep the execution time of
+ * each function as low as possible
+ */
+int register_timer_isr (timer_fnc_t *isr_func)
+{
+	struct timer_isr_function *new_func;
+	struct timer_isr_function *temp;
+	int flag;
+
+	new_func = malloc(sizeof(struct timer_isr_function));
+
+	if (new_func == NULL)
+		return 1;
+
+	new_func->isr_func = isr_func;
+	new_func->next = NULL;
+
+	/*
+	 *  Don't allow timer interrupts while the
+	 *  linked list is being modified
+	 */
+	flag = disable_interrupts ();
+
+	if (first_timer_isr == NULL) {
+		first_timer_isr = new_func;
+	} else {
+		temp = first_timer_isr;
+		while (temp->next != NULL)
+			temp = temp->next;
+		temp->next = new_func;
+	}
+
+	if (flag)
+		enable_interrupts ();
+
+	return 0;
+}
+
+/*
+ * timer_isr() MUST be the registered interrupt handler for
+ */
+void timer_isr(void *unused)
+{
+	struct timer_isr_function *temp = first_timer_isr;
+
+	system_ticks++;
+
+	/* Execute each registered function */
+	while (temp != NULL) {
+		temp->isr_func ();
+		temp = temp->next;
+	}
+}
+
+void reset_timer (void)
+{
+	system_ticks = 0;
+}
+
+ulong get_timer (ulong base)
+{
+	return (system_ticks - base);
+}
+
+void set_timer (ulong t)
+{
+	system_ticks = t;
+}
diff --git a/arch/i386/lib/video.c b/arch/i386/lib/video.c
new file mode 100644
index 0000000..c58ed10
--- /dev/null
+++ b/arch/i386/lib/video.c
@@ -0,0 +1,237 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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>
+#include <stdio_dev.h>
+#include <i8042.h>
+#include <asm/ptrace.h>
+#include <asm/realmode.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+
+
+/* basic textmode I/O from linux kernel */
+static char *vidmem = (char *)0xb8000;
+static int vidport;
+static int lines, cols;
+static int orig_x, orig_y;
+
+static void beep(int dur)
+{
+	int i;
+
+	outb_p(3, 0x61);
+	for (i=0;i<10*dur;i++) {
+		udelay(1000);
+	}
+	outb_p(0, 0x61);
+}
+
+static void scroll(void)
+{
+	int i;
+
+	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
+	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
+		vidmem[i] = ' ';
+}
+
+static void __video_putc(const char c, int *x, int *y)
+{
+	if (c == '\n') {
+		(*x) = 0;
+		if ( ++(*y) >= lines ) {
+			scroll();
+			(*y)--;
+		}
+	} else if (c == '\b') {
+		if ((*x) != 0) {
+			--(*x);
+			vidmem [ ( (*x) + cols * (*y) ) * 2 ] = ' ';
+		}
+	} else if (c == '\r') {
+		(*x) = 0;
+
+	} else if (c == '\a') {
+		beep(3);
+
+	} else if (c == '\t') {
+		__video_putc(' ', x, y);
+		__video_putc(' ', x, y);
+		__video_putc(' ', x, y);
+		__video_putc(' ', x, y);
+		__video_putc(' ', x, y);
+		__video_putc(' ', x, y);
+		__video_putc(' ', x, y);
+		__video_putc(' ', x, y);
+	} else if (c == '\v') {
+		switch ((*x) % 8) {
+		case 0:
+			__video_putc(' ', x, y);
+		case 7:
+			__video_putc(' ', x, y);
+		case 6:
+			__video_putc(' ', x, y);
+		case 5:
+			__video_putc(' ', x, y);
+		case 4:
+			__video_putc(' ', x, y);
+		case 3:
+			__video_putc(' ', x, y);
+		case 2:
+			__video_putc(' ', x, y);
+		case 1:
+			__video_putc(' ', x, y);
+		}
+	} else if (c == '\f') {
+		int i;
+		for (i=0;i<lines*cols*2;i+=2) {
+			vidmem[i] = 0;
+		}
+		(*x) = 0;
+		(*y) = 0;
+	} else {
+		vidmem [ ( (*x) + cols * (*y) ) * 2 ] = c;
+		if ( ++(*x) >= cols ) {
+			(*x) = 0;
+			if ( ++(*y) >= lines ) {
+				scroll();
+				(*y)--;
+			}
+		}
+	}
+}
+
+static void video_putc(const char c)
+{
+	int x,y,pos;
+
+	x = orig_x;
+	y = orig_y;
+
+	__video_putc(c, &x, &y);
+
+	orig_x = x;
+	orig_y = y;
+
+	pos = (x + cols * y) * 2;	/* Update cursor position */
+	outb_p(14, vidport);
+	outb_p(0xff & (pos >> 9), vidport+1);
+	outb_p(15, vidport);
+	outb_p(0xff & (pos >> 1), vidport+1);
+}
+
+static void video_puts(const char *s)
+{
+	int x,y,pos;
+	char c;
+
+	x = orig_x;
+	y = orig_y;
+
+	while ( ( c = *s++ ) != '\0' ) {
+		__video_putc(c, &x, &y);
+	}
+
+	orig_x = x;
+	orig_y = y;
+
+	pos = (x + cols * y) * 2;	/* Update cursor position */
+	outb_p(14, vidport);
+	outb_p(0xff & (pos >> 9), vidport+1);
+	outb_p(15, vidport);
+	outb_p(0xff & (pos >> 1), vidport+1);
+}
+
+int video_init(void)
+{
+	u16 pos;
+
+	static struct stdio_dev vga_dev;
+	static struct stdio_dev kbd_dev;
+
+	vidmem = (char *) 0xb8000;
+	vidport = 0x3d4;
+
+	lines = 25;
+	cols = 80;
+
+	outb_p(14, vidport);
+	pos = inb_p(vidport+1);
+	pos <<= 8;
+	outb_p(15, vidport);
+	pos |= inb_p(vidport+1);
+
+	orig_x = pos%cols;
+	orig_y = pos/cols;
+
+#if 0
+	printf("pos %x %d %d\n", pos, orig_x, orig_y);
+#endif
+	if (orig_y > lines) {
+		orig_x = orig_y =0;
+	}
+
+
+	memset(&vga_dev, 0, sizeof(vga_dev));
+	strcpy(vga_dev.name, "vga");
+	vga_dev.ext   = 0;
+	vga_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
+	vga_dev.putc  = video_putc;        /* 'putc' function */
+	vga_dev.puts  = video_puts;        /* 'puts' function */
+	vga_dev.tstc  = NULL;              /* 'tstc' function */
+	vga_dev.getc  = NULL;              /* 'getc' function */
+
+	if (stdio_register(&vga_dev) == 0) {
+	    return 1;
+	}
+
+	if (i8042_kbd_init()) {
+		return 1;
+	}
+
+	memset(&kbd_dev, 0, sizeof(kbd_dev));
+	strcpy(kbd_dev.name, "kbd");
+	kbd_dev.ext   = 0;
+	kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
+	kbd_dev.putc  = NULL;        /* 'putc' function */
+	kbd_dev.puts  = NULL;        /* 'puts' function */
+	kbd_dev.tstc  = i8042_tstc;  /* 'tstc' function */
+	kbd_dev.getc  = i8042_getc;  /* 'getc' function */
+
+	if (stdio_register(&kbd_dev) == 0) {
+	    return 1;
+	}
+	return 0;
+}
+
+
+int drv_video_init(void)
+{
+	if (video_bios_init()) {
+		return 1;
+	}
+
+	return video_init();
+}
diff --git a/arch/i386/lib/video_bios.c b/arch/i386/lib/video_bios.c
new file mode 100644
index 0000000..c8060e6
--- /dev/null
+++ b/arch/i386/lib/video_bios.c
@@ -0,0 +1,222 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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>
+#include <malloc.h>
+#include <asm/ptrace.h>
+#include <asm/realmode.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+
+#undef PCI_BIOS_DEBUG
+#undef VGA_BIOS_DEBUG
+
+#ifdef	VGA_BIOS_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+#ifdef CONFIG_PCI
+
+#ifdef PCI_BIOS_DEBUG
+#define RELOC_16(seg, off) *(u32*)(seg << 4 | (u32)&off)
+extern u32 num_pci_bios_present;
+extern u32 num_pci_bios_find_device;
+extern u32 num_pci_bios_find_class;
+extern u32 num_pci_bios_generate_special_cycle;
+extern u32 num_pci_bios_read_cfg_byte;
+extern u32 num_pci_bios_read_cfg_word;
+extern u32 num_pci_bios_read_cfg_dword;
+extern u32 num_pci_bios_write_cfg_byte;
+extern u32 num_pci_bios_write_cfg_word;
+extern u32 num_pci_bios_write_cfg_dword;
+extern u32 num_pci_bios_get_irq_routing;
+extern u32 num_pci_bios_set_irq;
+extern u32 num_pci_bios_unknown_function;
+
+void print_bios_bios_stat(void)
+{
+	printf("16 bit functions:\n");
+	printf("pci_bios_present:                %d\n", RELOC_16(0xf000, num_pci_bios_present));
+	printf("pci_bios_find_device:            %d\n", RELOC_16(0xf000, num_pci_bios_find_device));
+	printf("pci_bios_find_class:             %d\n", RELOC_16(0xf000, num_pci_bios_find_class));
+	printf("pci_bios_generate_special_cycle: %d\n", RELOC_16(0xf000, num_pci_bios_generate_special_cycle));
+	printf("pci_bios_read_cfg_byte:          %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_byte));
+	printf("pci_bios_read_cfg_word:          %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_word));
+	printf("pci_bios_read_cfg_dword:         %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_dword));
+	printf("pci_bios_write_cfg_byte:         %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_byte));
+	printf("pci_bios_write_cfg_word:         %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_word));
+	printf("pci_bios_write_cfg_dword:        %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_dword));
+	printf("pci_bios_get_irq_routing:        %d\n", RELOC_16(0xf000, num_pci_bios_get_irq_routing));
+	printf("pci_bios_set_irq:                %d\n", RELOC_16(0xf000, num_pci_bios_set_irq));
+	printf("pci_bios_unknown_function:       %d\n", RELOC_16(0xf000, num_pci_bios_unknown_function));
+
+}
+#endif
+
+#ifdef CONFIG_VIDEO
+
+#define PCI_CLASS_VIDEO             3
+#define PCI_CLASS_VIDEO_STD         0
+#define PCI_CLASS_VIDEO_PROG_IF_VGA 0
+
+static struct pci_device_id supported[] = {
+	{PCI_VIDEO_VENDOR_ID, PCI_VIDEO_DEVICE_ID},
+	{}
+};
+
+static u32 probe_pci_video(void)
+{
+	pci_dev_t devbusfn;
+
+	if ((devbusfn = pci_find_devices(supported, 0) != -1)) {
+		u32 old;
+		u32 addr;
+
+		/* PCI video device detected */
+		printf("Found PCI VGA device at %02x.%02x.%x\n",
+		       PCI_BUS(devbusfn), PCI_DEV(devbusfn), PCI_FUNC(devbusfn));
+
+		/* Enable I/O decoding as well, PCI viudeo boards
+		 * support I/O accesses, but they provide no
+		 * bar register for this since the ports are fixed.
+		 */
+		pci_write_config_word(devbusfn, PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_MASTER);
+
+		/* Test the ROM decoder, do the device support a rom? */
+		pci_read_config_dword(devbusfn, PCI_ROM_ADDRESS, &old);
+		pci_write_config_dword(devbusfn, PCI_ROM_ADDRESS, (u32)PCI_ROM_ADDRESS_MASK);
+		pci_read_config_dword(devbusfn, PCI_ROM_ADDRESS, &addr);
+		pci_write_config_dword(devbusfn, PCI_ROM_ADDRESS, old);
+
+		if (!addr) {
+			printf("PCI VGA have no ROM?\n");
+			return 0;
+		}
+
+		/* device have a rom */
+		if (pci_shadow_rom(devbusfn, (void*)0xc0000)) {
+			printf("Shadowing of PCI VGA BIOS failed\n");
+			return 0;
+		}
+
+		/* Now enable lagacy VGA port access */
+		if (pci_enable_legacy_video_ports(pci_bus_to_hose(PCI_BUS(devbusfn)))) {
+			printf("PCI VGA enable failed\n");
+			return 0;
+		}
+
+
+		/* return the pci device info, that we'll need later */
+		return PCI_BUS(devbusfn) << 8 |
+			PCI_DEV(devbusfn) << 3 | (PCI_FUNC(devbusfn)&7);
+	}
+
+	return 0;
+}
+
+static int probe_isa_video(void)
+{
+	u32 ptr;
+	char *buf;
+
+	if (0 == (ptr = isa_map_rom(0xc0000, 0x8000))) {
+		return -1;
+	}
+	if (NULL == (buf=malloc(0x8000))) {
+		isa_unmap_rom(ptr);
+		return -1;
+	}
+	if (readw(ptr) != 0xaa55) {
+		free(buf);
+		isa_unmap_rom(ptr);
+		return -1;
+	}
+
+	/* shadow the rom */
+	memcpy(buf, (void*)ptr, 0x8000);
+	isa_unmap_rom(ptr);
+	memcpy((void*)0xc0000, buf, 0x8000);
+
+	free(buf);
+
+	return 0;
+}
+
+int video_bios_init(void)
+{
+	struct pt_regs regs;
+
+	/* clear the video bios area in case we warmbooted */
+	memset((void*)0xc0000, 0, 0x8000);
+	memset(&regs, 0, sizeof(struct pt_regs));
+
+	if (probe_isa_video()) {
+		/* No ISA board found, try the PCI bus */
+		regs.eax = probe_pci_video();
+	}
+
+	/* Did we succeed in mapping any video bios */
+	if (readw(0xc0000) == 0xaa55) {
+	        int size;
+		int i;
+		u8 sum;
+
+		PRINTF("Found video bios signature\n");
+		size = 512*readb(0xc0002);
+		PRINTF("size %d\n", size);
+		sum=0;
+		for (i=0;i<size;i++) {
+			sum += readb(0xc0000 + i);
+		}
+		PRINTF("Checksum is %sOK\n",sum?"NOT ":"");
+		if (sum) {
+			return 1;
+		}
+
+		/* some video bioses (ATI Mach64) seem to think that
+		 * the original int 10 handler is always at
+		 * 0xf000:0xf065 , place an iret instruction there
+		 */
+		writeb(0xcf, 0xff065);
+
+		regs.esp = 0x8000;
+		regs.xss = 0x2000;
+		enter_realmode(0xc000, 3, &regs, &regs);
+		PRINTF("INT 0x10 vector after:  %04x:%04x\n",
+		       readw(0x42), readw(0x40));
+		PRINTF("BIOS returned %scarry\n", regs.eflags & 1?"":"NOT ");
+#ifdef PCI_BIOS_DEBUG
+		print_bios_bios_stat();
+#endif
+		return (regs.eflags & 1);
+
+	}
+
+	return 1;
+
+}
+#endif
+#endif
diff --git a/arch/i386/lib/zimage.c b/arch/i386/lib/zimage.c
new file mode 100644
index 0000000..c3b4e59
--- /dev/null
+++ b/arch/i386/lib/zimage.c
@@ -0,0 +1,225 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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
+ */
+
+/*
+ * Linux i386 zImage and bzImage loading
+ *
+ * based on the procdure described in
+ * linux/Documentation/i386/boot.txt
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/ptrace.h>
+#include <asm/zimage.h>
+#include <asm/realmode.h>
+#include <asm/byteorder.h>
+
+/*
+ * Memory lay-out:
+ *
+ * relative to setup_base (which is 0x90000 currently)
+ *
+ *	0x0000-0x7FFF	Real mode kernel
+ *	0x8000-0x8FFF	Stack and heap
+ *	0x9000-0x90FF	Kernel command line
+ */
+#define DEFAULT_SETUP_BASE  0x90000
+#define COMMAND_LINE_OFFSET 0x9000
+#define HEAP_END_OFFSET     0x8e00
+
+#define COMMAND_LINE_SIZE   2048
+
+static void build_command_line(char *command_line, int auto_boot)
+{
+	char *env_command_line;
+
+	command_line[0] = '\0';
+
+	env_command_line =  getenv("bootargs");
+
+	/* set console= argument if we use a serial console */
+	if (NULL == strstr(env_command_line, "console=")) {
+		if (0==strcmp(getenv("stdout"), "serial")) {
+
+			/* We seem to use serial console */
+			sprintf(command_line, "console=ttyS0,%s ",
+				 getenv("baudrate"));
+		}
+	}
+
+	if (auto_boot) {
+		strcat(command_line, "auto ");
+	}
+
+	if (NULL != env_command_line) {
+		strcat(command_line, env_command_line);
+	}
+
+
+	printf("Kernel command line: \"%s\"\n", command_line);
+}
+
+void *load_zimage(char *image, unsigned long kernel_size,
+		  unsigned long initrd_addr, unsigned long initrd_size,
+		  int auto_boot)
+{
+	void *setup_base;
+	int setup_size;
+	int bootproto;
+	int big_image;
+	void *load_address;
+
+
+	setup_base = (void*)DEFAULT_SETUP_BASE;	/* base address for real-mode segment */
+
+	if (KERNEL_MAGIC != *(u16*)(image + BOOT_FLAG_OFF)) {
+		printf("Error: Invalid kernel magic (found 0x%04x, expected 0xaa55)\n",
+		       *(u16*)(image + BOOT_FLAG_OFF));
+		return 0;
+	}
+
+
+	/* determine boot protocol version */
+	if (KERNEL_V2_MAGIC == *(u32*)(image+HEADER_OFF)) {
+		bootproto = *(u16*)(image+VERSION_OFF);
+	} else {
+		/* Very old kernel */
+		bootproto = 0x0100;
+	}
+
+	/* determine size of setup */
+	if (0 == *(u8*)(image + SETUP_SECTS_OFF)) {
+		setup_size = 5 * 512;
+	} else {
+		setup_size = (*(u8*)(image + SETUP_SECTS_OFF) + 1) * 512;
+	}
+
+	if (setup_size > SETUP_MAX_SIZE) {
+		printf("Error: Setup is too large (%d bytes)\n", setup_size);
+	}
+
+	/* Determine image type */
+	big_image = (bootproto >= 0x0200) && (*(u8*)(image + LOADFLAGS_OFF) & BIG_KERNEL_FLAG);
+
+	/* Derermine load address */
+	load_address = (void*)(big_image ? BZIMAGE_LOAD_ADDR:ZIMAGE_LOAD_ADDR);
+
+	/* load setup */
+	memmove(setup_base, image, setup_size);
+
+	printf("Using boot protocol version %x.%02x\n",
+	       (bootproto & 0xff00) >> 8, bootproto & 0xff);
+
+
+	if (bootproto == 0x0100) {
+
+		*(u16*)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC;
+		*(u16*)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET;
+
+		/* A very old kernel MUST have its real-mode code
+		 * loaded at 0x90000 */
+
+		if ((u32)setup_base != 0x90000) {
+			/* Copy the real-mode kernel */
+			memmove((void*)0x90000, setup_base, setup_size);
+			/* Copy the command line */
+			memmove((void*)0x99000, setup_base+COMMAND_LINE_OFFSET,
+			       COMMAND_LINE_SIZE);
+
+			setup_base = (void*)0x90000;		 /* Relocated */
+		}
+
+		/* It is recommended to clear memory up to the 32K mark */
+		memset((void*)0x90000 + setup_size, 0, SETUP_MAX_SIZE-setup_size);
+	}
+
+	if (bootproto >= 0x0200) {
+		*(u8*)(setup_base + TYPE_OF_LOADER_OFF) = 0xff;
+		printf("Linux kernel version %s\n",
+		       (char*)(setup_base + SETUP_START_OFFSET +
+			       *(u16*)(setup_base + START_SYS_OFF + 2)));
+
+		if (initrd_addr) {
+			printf("Initial RAM disk at linear address 0x%08lx, size %ld bytes\n",
+			       initrd_addr, initrd_size);
+
+			*(u32*)(setup_base + RAMDISK_IMAGE_OFF) = initrd_addr;
+			*(u32*)(setup_base + RAMDISK_SIZE_OFF)=initrd_size;
+		}
+	}
+
+	if (bootproto >= 0x0201) {
+		*(u16*)(setup_base + HEAP_END_PTR_OFF) = HEAP_END_OFFSET;
+
+		/* CAN_USE_HEAP */
+		*(u8*)(setup_base + LOADFLAGS_OFF) =
+			*(u8*)(setup_base + LOADFLAGS_OFF) | HEAP_FLAG;
+	}
+
+	if (bootproto >= 0x0202) {
+		*(u32*)(setup_base + CMD_LINE_PTR_OFF) = (u32)setup_base + COMMAND_LINE_OFFSET;
+	} else if (bootproto >= 0x0200) {
+		*(u16*)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC;
+		*(u16*)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET;
+		*(u16*)(setup_base + SETUP_MOVE_SIZE_OFF) = 0x9100;
+	}
+
+
+	if (big_image) {
+		if ((kernel_size - setup_size) > BZIMAGE_MAX_SIZE) {
+			printf("Error: bzImage kernel too big! (size: %ld, max: %d)\n",
+			       kernel_size - setup_size, BZIMAGE_MAX_SIZE);
+			return 0;
+		}
+
+	} else if ((kernel_size - setup_size) > ZIMAGE_MAX_SIZE) {
+		printf("Error: zImage kernel too big! (size: %ld, max: %d)\n",
+		       kernel_size - setup_size, ZIMAGE_MAX_SIZE);
+		return 0;
+	}
+
+	/* build command line at COMMAND_LINE_OFFSET */
+	build_command_line(setup_base + COMMAND_LINE_OFFSET, auto_boot);
+
+	printf("Loading %czImage at address 0x%08x (%ld bytes)\n", big_image ? 'b' : ' ',
+	       (u32)load_address, kernel_size - setup_size);
+
+
+	memmove(load_address, image + setup_size, kernel_size - setup_size);
+
+	/* ready for booting */
+	return setup_base;
+}
+
+void boot_zimage(void *setup_base)
+{
+	struct pt_regs regs;
+
+	memset(&regs, 0, sizeof(struct pt_regs));
+	regs.xds = (u32)setup_base >> 4;
+	regs.xss = 0x9000;
+	regs.esp = 0x9000;
+	regs.eflags = 0;
+	enter_realmode(((u32)setup_base+SETUP_START_OFFSET)>>4, 0, &regs, &regs);
+}
diff --git a/arch/m68k/config.mk b/arch/m68k/config.mk
new file mode 100644
index 0000000..749c389
--- /dev/null
+++ b/arch/m68k/config.mk
@@ -0,0 +1,30 @@
+#
+# (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 ?= m68k-elf-
+
+clibdir = $(shell dirname `$(CC) $(CFLAGS) -print-file-name=libc.a`)
+STANDALONE_LOAD_ADDR = 0x20000 -L $(clibdir)
+
+PLATFORM_CPPFLAGS += -DCONFIG_M68K -D__M68K__
+PLATFORM_LDFLAGS  += -n
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile
new file mode 100644
index 0000000..6db35ed
--- /dev/null
+++ b/arch/m68k/lib/Makefile
@@ -0,0 +1,50 @@
+#
+# (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	+=
+
+COBJS-y	+= board.o
+COBJS-y	+= bootm.o
+COBJS-y	+= cache.o
+COBJS-y	+= interrupts.o
+COBJS-y	+= time.o
+COBJS-y	+= traps.o
+
+SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/m68k/lib/board.c b/arch/m68k/lib/board.c
new file mode 100644
index 0000000..732023d
--- /dev/null
+++ b/arch/m68k/lib/board.c
@@ -0,0 +1,744 @@
+/*
+ * (C) Copyright 2003
+ * Josef Baumgartner <josef.baumgartner@telex.de>
+ *
+ * (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 <command.h>
+#include <malloc.h>
+#include <stdio_dev.h>
+
+#include <asm/immap.h>
+
+#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>
+#include <serial.h>
+#if defined(CONFIG_CMD_BEDBUG)
+#include <cmd_bedbug.h>
+#endif
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+#include <commproc.h>
+#endif
+#include <version.h>
+
+#if defined(CONFIG_HARD_I2C) || \
+    defined(CONFIG_SOFT_I2C)
+#include <i2c.h>
+#endif
+
+#ifdef CONFIG_CMD_SPI
+#include <spi.h>
+#endif
+
+#ifdef CONFIG_BITBANGMII
+#include <miiphy.h>
+#endif
+
+#include <nand.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static char *failed = "*** failed ***\n";
+
+#ifdef	CONFIG_PCU_E
+extern flash_info_t flash_info[];
+#endif
+
+#include <environment.h>
+
+#if ( ((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
+
+extern ulong __init_end;
+extern ulong _end;
+
+extern	void timer_init(void);
+
+#if defined(CONFIG_WATCHDOG)
+# define INIT_FUNC_WATCHDOG_INIT	watchdog_init,
+# define WATCHDOG_DISABLE		watchdog_disable
+
+extern int watchdog_init(void);
+extern int watchdog_disable(void);
+#else
+# define INIT_FUNC_WATCHDOG_INIT	/* undef */
+# define WATCHDOG_DISABLE		/* undef */
+#endif /* CONFIG_WATCHDOG */
+
+ulong monitor_flash_len;
+
+/************************************************************************
+ * 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);
+}
+
+/***********************************************************************/
+
+static int init_func_ram (void)
+{
+	int board_type = 0;	/* use dummy arg */
+	puts ("DRAM:  ");
+
+	if ((gd->ram_size = initdram (board_type)) > 0) {
+		print_size (gd->ram_size, "\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
+
+/***********************************************************************/
+
+/************************************************************************
+ * Initialization sequence						*
+ ************************************************************************
+ */
+
+init_fnc_t *init_sequence[] = {
+	get_clocks,
+	env_init,
+	init_baudrate,
+	serial_init,
+	console_init_f,
+	display_options,
+	checkcpu,
+	checkboard,
+#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
+	init_func_i2c,
+#endif
+#if defined(CONFIG_HARD_SPI)
+	init_func_spi,
+#endif
+	init_func_ram,
+#if defined(CONFIG_SYS_DRAM_TEST)
+	testdram,
+#endif /* CONFIG_SYS_DRAM_TEST */
+	INIT_FUNC_WATCHDOG_INIT
+	NULL,			/* Terminate this list */
+};
+
+
+/************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************
+ */
+
+void
+board_init_f (ulong bootflag)
+{
+	bd_t *bd;
+	ulong len, addr, addr_sp;
+	ulong *paddr;
+	gd_t *id;
+	init_fnc_t **init_fnc_ptr;
+#ifdef CONFIG_PRAM
+	int i;
+	ulong reg;
+	char 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");
+
+	/* Clear initial global data */
+	memset ((void *) gd, 0, sizeof (gd_t));
+
+	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):
+	 *	- protected RAM
+	 *	- LCD framebuffer
+	 *	- monitor code
+	 *	- board info struct
+	 */
+	len = (ulong)&_end - CONFIG_SYS_MONITOR_BASE;
+
+	addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
+
+#ifdef CONFIG_LOGBUFFER
+	/* reserve kernel log buffer */
+	addr -= (LOGBUFF_RESERVE);
+	debug ("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, addr);
+#endif
+
+#ifdef CONFIG_PRAM
+	/*
+	 * reserve protected RAM
+	 */
+	i = getenv_r ("pram", tmp, sizeof (tmp));
+	reg = (i > 0) ? simple_strtoul (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 */
+
+	/*
+	 * reserve memory for U-Boot code, data & bss
+	 * round down to next 4 kB limit
+	 */
+	addr -= len;
+	addr &= ~(4096 - 1);
+
+	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);
+
+	/* Reserve memory for boot params. */
+	addr_sp -= CONFIG_SYS_BOOTPARAMS_LEN;
+	bd->bi_boot_params = addr_sp;
+	debug ("Reserving %dk for boot parameters at: %08lx\n",
+			CONFIG_SYS_BOOTPARAMS_LEN >> 10, 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;
+
+	paddr = (ulong *)addr_sp;
+	*paddr-- = 0;
+	*paddr-- = 0;
+	addr_sp = (ulong)paddr;
+
+	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_SYS_INIT_RAM_ADDR
+	bd->bi_sramstart = CONFIG_SYS_INIT_RAM_ADDR;	/* start of  SRAM memory	*/
+	bd->bi_sramsize  = CONFIG_SYS_INIT_RAM_END;	/* size  of  SRAM memory	*/
+#endif
+	bd->bi_mbar_base = CONFIG_SYS_MBAR;		/* base of internal registers */
+
+	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 */
+#ifdef CONFIG_PCI
+	bd->bi_pcifreq = gd->pci_clk;		/* PCI Freq in Hz */
+#endif
+#ifdef CONFIG_EXTRA_CLOCK
+	bd->bi_inpfreq = gd->inp_clk;		/* input Freq in Hz */
+	bd->bi_vcofreq = gd->vco_clk;		/* vco Freq in Hz */
+	bd->bi_flbfreq = gd->flb_clk;		/* flexbus Freq in Hz */
+#endif
+	bd->bi_baudrate = gd->baudrate;	/* Console Baudrate     */
+
+#ifdef CONFIG_SYS_EXTBDINFO
+	strncpy (bd->bi_s_version, "1.2", sizeof (bd->bi_s_version));
+	strncpy (bd->bi_r_version, U_BOOT_VERSION, sizeof (bd->bi_r_version));
+#endif
+
+	WATCHDOG_RESET ();
+
+#ifdef CONFIG_POST
+	post_bootmode_init();
+	post_run (NULL, POST_ROM | post_bootmode_get(0));
+#endif
+
+	WATCHDOG_RESET();
+
+	memcpy (id, (void *)gd, sizeof (gd_t));
+
+	debug ("Start relocate of code from %08x to %08lx\n", CONFIG_SYS_MONITOR_BASE, addr);
+	relocate_code (addr_sp, id, addr);
+
+	/* NOTREACHED - jump_to_ram() 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)
+{
+	cmd_tbl_t *cmdtp;
+	char *s;
+	bd_t *bd;
+	extern void malloc_bin_reloc (void);
+
+#ifndef CONFIG_ENV_IS_NOWHERE
+	extern char * env_name_spec;
+#endif
+#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 */
+
+#ifdef CONFIG_SERIAL_MULTI
+	serial_initialize();
+#endif
+
+	debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
+
+	WATCHDOG_RESET ();
+
+	gd->reloc_off =  dest_addr - CONFIG_SYS_MONITOR_BASE;
+
+	monitor_flash_len = (ulong)&__init_end - dest_addr;
+
+	/*
+	 * We have to relocate the command table manually
+	 */
+	for (cmdtp = &__u_boot_cmd_start; cmdtp !=  &__u_boot_cmd_end; cmdtp++) {
+		ulong addr;
+		addr = (ulong) (cmdtp->cmd) + gd->reloc_off;
+#if 0
+		printf ("Command \"%s\": 0x%08lx => 0x%08lx\n",
+				cmdtp->name, (ulong) (cmdtp->cmd), addr);
+#endif
+		cmdtp->cmd =
+			(int (*)(struct cmd_tbl_s *, int, int, char *[]))addr;
+
+		addr = (ulong)(cmdtp->name) + gd->reloc_off;
+		cmdtp->name = (char *)addr;
+
+		if (cmdtp->usage) {
+			addr = (ulong)(cmdtp->usage) + gd->reloc_off;
+			cmdtp->usage = (char *)addr;
+		}
+#ifdef	CONFIG_SYS_LONGHELP
+		if (cmdtp->help) {
+			addr = (ulong)(cmdtp->help) + gd->reloc_off;
+			cmdtp->help = (char *)addr;
+		}
+#endif
+	}
+	/* there are some other pointer constants we must deal with */
+#ifndef CONFIG_ENV_IS_NOWHERE
+	env_name_spec += gd->reloc_off;
+#endif
+
+	WATCHDOG_RESET ();
+
+#ifdef CONFIG_LOGBUFFER
+	logbuff_init_ptrs ();
+#endif
+#ifdef CONFIG_POST
+	post_output_backlog ();
+	post_reloc ();
+#endif
+	WATCHDOG_RESET();
+
+#if 0
+	/* instruction cache enabled in cpu_init_f() for faster relocation */
+	icache_enable ();	/* it's time to enable the instruction cache */
+#endif
+
+	/*
+	 * Setup trap handlers
+	 */
+	trap_init (CONFIG_SYS_SDRAM_BASE);
+
+	/* The Malloc area is immediately below the monitor copy in DRAM */
+	mem_malloc_init (CONFIG_SYS_MONITOR_BASE + gd->reloc_off -
+			TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN);
+	malloc_bin_reloc ();
+
+#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) */
+	bd->bi_flashoffset = 0;
+#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
+
+	/* 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.
+	 */
+	bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
+
+	WATCHDOG_RESET ();
+
+#if defined(CONFIG_PCI)
+	/*
+	 * 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 ();
+
+	/* 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
+
+#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
+	 */
+	timer_init();
+
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
+	serial_buffered_init();
+#endif
+
+#ifdef CONFIG_STATUS_LED
+	status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING);
+#endif
+
+	udelay (20);
+
+	set_timer (0);
+
+	/* Insert function pointers now that we have relocated the code */
+
+	/* 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_CMD_DOC)
+	WATCHDOG_RESET ();
+	puts ("DOC:   ");
+	doc_init ();
+#endif
+
+#if defined(CONFIG_CMD_NAND)
+	WATCHDOG_RESET ();
+	puts ("NAND:  ");
+	nand_init();		/* go init the NAND */
+#endif
+
+#ifdef CONFIG_BITBANGMII
+	bb_miiphy_init();
+#endif
+#if defined(CONFIG_CMD_NET)
+	WATCHDOG_RESET();
+#if defined(FEC_ENET)
+	eth_init(bd);
+#endif
+#if defined(CONFIG_NET_MULTI)
+	puts ("Net:   ");
+	eth_initialize (bd);
+#endif
+#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 ();
+	puts ("IDE:   ");
+	ide_init ();
+#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;
+		char 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
+		/* Also take the logbuffer into account (pram is in kB) */
+		pram += (LOGBUFF_LEN+LOGBUFF_OVERHEAD)/1024;
+#endif
+		sprintf (memsz, "%ldk", (bd->bi_memsize / 1024) - pram);
+		setenv ("mem", memsz);
+	}
+#endif
+
+#ifdef CONFIG_MODEM_SUPPORT
+ {
+	 extern int do_mdm_init;
+	 do_mdm_init = gd->do_mdm_init;
+ }
+#endif
+
+#ifdef CONFIG_WATCHDOG
+	/* disable watchdog if environment is set */
+	if ((s = getenv ("watchdog")) != NULL) {
+		if (strncmp (s, "off", 3) == 0) {
+			WATCHDOG_DISABLE ();
+		}
+	}
+#endif /* CONFIG_WATCHDOG*/
+
+
+	/* 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");
+	for (;;);
+}
diff --git a/arch/m68k/lib/bootm.c b/arch/m68k/lib/bootm.c
new file mode 100644
index 0000000..e5ed6eb
--- /dev/null
+++ b/arch/m68k/lib/bootm.c
@@ -0,0 +1,146 @@
+/*
+ * (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>
+#include <command.h>
+#include <image.h>
+#include <u-boot/zlib.h>
+#include <bzlib.h>
+#include <watchdog.h>
+#include <environment.h>
+#include <asm/byteorder.h>
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+# include <status_led.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define PHYSADDR(x) x
+
+#define LINUX_MAX_ENVS		256
+#define LINUX_MAX_ARGS		256
+
+static ulong get_sp (void);
+static void set_clocks_in_mhz (bd_t *kbd);
+
+void arch_lmb_reserve(struct lmb *lmb)
+{
+	ulong sp;
+
+	/*
+	 * 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 ", sp);
+
+	/* adjust sp by 1K to be safe */
+	sp -= 1024;
+	lmb_reserve(lmb, sp, (CONFIG_SYS_SDRAM_BASE + gd->ram_size - sp));
+}
+
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	ulong rd_len;
+	ulong initrd_start, initrd_end;
+	int ret;
+
+	ulong cmd_start, cmd_end;
+	ulong bootmap_base;
+	bd_t  *kbd;
+	void  (*kernel) (bd_t *, ulong, ulong, ulong, ulong);
+	struct lmb *lmb = &images->lmb;
+
+	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+		return 1;
+
+	bootmap_base = getenv_bootm_low();
+
+	/* 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");
+		goto error;
+	}
+
+	/* 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");
+		goto error;
+	}
+	set_clocks_in_mhz(kbd);
+
+	kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))images->ep;
+
+	rd_len = images->rd_end - images->rd_start;
+	ret = boot_ramdisk_high (lmb, images->rd_start, rd_len,
+			&initrd_start, &initrd_end);
+	if (ret)
+		goto error;
+
+	debug("## Transferring control to Linux (at address %08lx) ...\n",
+	      (ulong) kernel);
+
+	show_boot_progress (15);
+
+	/*
+	 * Linux Kernel Parameters (passing board info data):
+	 *   sp+00: Ignore, side effect of using jsr to jump to kernel
+	 *   sp+04: ptr to board info data
+	 *   sp+08: initrd_start or 0 if no initrd
+	 *   sp+12: initrd_end - unused if initrd_start is 0
+	 *   sp+16: Start of command line string
+	 *   sp+20: End   of command line string
+	 */
+	(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end);
+	/* does not return */
+error:
+	return 1;
+}
+
+static ulong get_sp (void)
+{
+	ulong sp;
+
+	asm("movel %%a7, %%d0\n"
+	    "movel %%d0, %0\n": "=d"(sp): :"%d0");
+
+	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;
+	}
+}
diff --git a/arch/m68k/lib/cache.c b/arch/m68k/lib/cache.c
new file mode 100644
index 0000000..ed88178
--- /dev/null
+++ b/arch/m68k/lib/cache.c
@@ -0,0 +1,150 @@
+/*
+ * (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/immap.h>
+#include <asm/cache.h>
+
+volatile int *cf_icache_status = (int *)ICACHE_STATUS;
+volatile int *cf_dcache_status = (int *)DCACHE_STATUS;
+
+void flush_cache(ulong start_addr, ulong size)
+{
+	/* Must be implemented for all M68k processors with copy-back data cache */
+}
+
+int icache_status(void)
+{
+	return *cf_icache_status;
+}
+
+int dcache_status(void)
+{
+	return *cf_dcache_status;
+}
+
+void icache_enable(void)
+{
+	icache_invalid();
+
+	*cf_icache_status = 1;
+
+#ifdef CONFIG_CF_V4
+	__asm__ __volatile__("movec %0, %%acr2"::"r"(CONFIG_SYS_CACHE_ACR2));
+	__asm__ __volatile__("movec %0, %%acr3"::"r"(CONFIG_SYS_CACHE_ACR3));
+#elif defined(CONFIG_CF_V4e)
+	__asm__ __volatile__("movec %0, %%acr6"::"r"(CONFIG_SYS_CACHE_ACR6));
+	__asm__ __volatile__("movec %0, %%acr7"::"r"(CONFIG_SYS_CACHE_ACR7));
+#else
+	__asm__ __volatile__("movec %0, %%acr0"::"r"(CONFIG_SYS_CACHE_ACR0));
+	__asm__ __volatile__("movec %0, %%acr1"::"r"(CONFIG_SYS_CACHE_ACR1));
+#endif
+
+	__asm__ __volatile__("movec %0, %%cacr"::"r"(CONFIG_SYS_CACHE_ICACR));
+}
+
+void icache_disable(void)
+{
+	u32 temp = 0;
+
+	*cf_icache_status = 0;
+	icache_invalid();
+
+#ifdef CONFIG_CF_V4
+	__asm__ __volatile__("movec %0, %%acr2"::"r"(temp));
+	__asm__ __volatile__("movec %0, %%acr3"::"r"(temp));
+#elif defined(CONFIG_CF_V4e)
+	__asm__ __volatile__("movec %0, %%acr6"::"r"(temp));
+	__asm__ __volatile__("movec %0, %%acr7"::"r"(temp));
+#else
+	__asm__ __volatile__("movec %0, %%acr0"::"r"(temp));
+	__asm__ __volatile__("movec %0, %%acr1"::"r"(temp));
+
+#endif
+}
+
+void icache_invalid(void)
+{
+	u32 temp;
+
+	temp = CONFIG_SYS_ICACHE_INV;
+	if (*cf_icache_status)
+		temp |= CONFIG_SYS_CACHE_ICACR;
+
+	__asm__ __volatile__("movec %0, %%cacr"::"r"(temp));
+}
+
+/*
+ * data cache only for ColdFire V4 such as MCF547x_8x, MCF5445x
+ * the dcache will be dummy in ColdFire V2 and V3
+ */
+void dcache_enable(void)
+{
+	dcache_invalid();
+	*cf_dcache_status = 1;
+
+#ifdef CONFIG_CF_V4
+	__asm__ __volatile__("movec %0, %%acr0"::"r"(CONFIG_SYS_CACHE_ACR0));
+	__asm__ __volatile__("movec %0, %%acr1"::"r"(CONFIG_SYS_CACHE_ACR1));
+#elif defined(CONFIG_CF_V4e)
+	__asm__ __volatile__("movec %0, %%acr4"::"r"(CONFIG_SYS_CACHE_ACR4));
+	__asm__ __volatile__("movec %0, %%acr5"::"r"(CONFIG_SYS_CACHE_ACR5));
+
+#endif
+
+	__asm__ __volatile__("movec %0, %%cacr"::"r"(CONFIG_SYS_CACHE_DCACR));
+}
+
+void dcache_disable(void)
+{
+	u32 temp = 0;
+
+	*cf_dcache_status = 0;
+	dcache_invalid();
+
+	__asm__ __volatile__("movec %0, %%cacr"::"r"(temp));
+
+#ifdef CONFIG_CF_V4
+	__asm__ __volatile__("movec %0, %%acr0"::"r"(temp));
+	__asm__ __volatile__("movec %0, %%acr1"::"r"(temp));
+#elif defined(CONFIG_CF_V4e)
+	__asm__ __volatile__("movec %0, %%acr4"::"r"(temp));
+	__asm__ __volatile__("movec %0, %%acr5"::"r"(temp));
+
+#endif
+}
+
+void dcache_invalid(void)
+{
+#ifdef CONFIG_CF_V4
+	u32 temp;
+
+	temp = CONFIG_SYS_DCACHE_INV;
+	if (*cf_dcache_status)
+		temp |= CONFIG_SYS_CACHE_DCACR;
+	if (*cf_icache_status)
+		temp |= CONFIG_SYS_CACHE_ICACR;
+
+	__asm__ __volatile__("movec %0, %%cacr"::"r"(temp));
+#endif
+}
diff --git a/arch/m68k/lib/interrupts.c b/arch/m68k/lib/interrupts.c
new file mode 100644
index 0000000..133494f
--- /dev/null
+++ b/arch/m68k/lib/interrupts.c
@@ -0,0 +1,115 @@
+/*
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2007 Freescale Semiconductor 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 <watchdog.h>
+#include <asm/processor.h>
+#include <asm/immap.h>
+
+#define	NR_IRQS		(CONFIG_SYS_NUM_IRQS)
+
+/*
+ * Interrupt vector functions.
+ */
+struct interrupt_action {
+	interrupt_handler_t *handler;
+	void *arg;
+};
+
+static struct interrupt_action irq_vecs[NR_IRQS];
+
+static __inline__ unsigned short get_sr (void)
+{
+	unsigned short sr;
+
+	asm volatile ("move.w %%sr,%0":"=r" (sr):);
+
+	return sr;
+}
+
+static __inline__ void set_sr (unsigned short sr)
+{
+	asm volatile ("move.w %0,%%sr"::"r" (sr));
+}
+
+/************************************************************************/
+/*
+ * Install and free an interrupt handler
+ */
+void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
+{
+	if ((vec < 0) || (vec >= NR_IRQS)) {
+		printf ("irq_install_handler: wrong interrupt vector %d\n",
+			vec);
+		return;
+	}
+
+	irq_vecs[vec].handler = handler;
+	irq_vecs[vec].arg = arg;
+}
+
+void irq_free_handler (int vec)
+{
+	if ((vec < 0) || (vec >= NR_IRQS)) {
+		return;
+	}
+
+	irq_vecs[vec].handler = NULL;
+	irq_vecs[vec].arg = NULL;
+}
+
+void enable_interrupts (void)
+{
+	unsigned short sr;
+
+	sr = get_sr ();
+	set_sr (sr & ~0x0700);
+}
+
+int disable_interrupts (void)
+{
+	unsigned short sr;
+
+	sr = get_sr ();
+	set_sr (sr | 0x0700);
+
+	return ((sr & 0x0700) == 0);	/* return TRUE, if interrupts were enabled before */
+}
+
+void int_handler (struct pt_regs *fp)
+{
+	int vec;
+
+	vec = (fp->vector >> 2) & 0xff;
+	if (vec > 0x40)
+		vec -= 0x40;
+
+	if (irq_vecs[vec].handler != NULL) {
+		irq_vecs[vec].handler (irq_vecs[vec].arg);
+	} else {
+		printf ("\nBogus External Interrupt Vector %d\n", vec);
+	}
+}
diff --git a/arch/m68k/lib/time.c b/arch/m68k/lib/time.c
new file mode 100644
index 0000000..7eaea5e
--- /dev/null
+++ b/arch/m68k/lib/time.c
@@ -0,0 +1,227 @@
+/*
+ * (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de>
+ *
+ * (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/timer.h>
+#include <asm/immap.h>
+#include <watchdog.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static volatile ulong timestamp = 0;
+
+#ifndef CONFIG_SYS_WATCHDOG_FREQ
+#define CONFIG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
+#endif
+
+#if defined(CONFIG_MCFTMR)
+#ifndef CONFIG_SYS_UDELAY_BASE
+#	error	"uDelay base not defined!"
+#endif
+
+#if !defined(CONFIG_SYS_TMR_BASE) || !defined(CONFIG_SYS_INTR_BASE) || !defined(CONFIG_SYS_TMRINTR_NO) || !defined(CONFIG_SYS_TMRINTR_MASK)
+#	error	"TMR_BASE, INTR_BASE, TMRINTR_NO or TMRINTR_MASk not defined!"
+#endif
+extern void dtimer_intr_setup(void);
+
+void __udelay(unsigned long usec)
+{
+	volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_UDELAY_BASE);
+	uint start, now, tmp;
+
+	while (usec > 0) {
+		if (usec > 65000)
+			tmp = 65000;
+		else
+			tmp = usec;
+		usec = usec - tmp;
+
+		/* Set up TIMER 3 as timebase clock */
+		timerp->tmr = DTIM_DTMR_RST_RST;
+		timerp->tcn = 0;
+		/* set period to 1 us */
+		timerp->tmr =
+		    CONFIG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 | DTIM_DTMR_FRR |
+		    DTIM_DTMR_RST_EN;
+
+		start = now = timerp->tcn;
+		while (now < start + tmp)
+			now = timerp->tcn;
+	}
+}
+
+void dtimer_interrupt(void *not_used)
+{
+	volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_TMR_BASE);
+
+	/* check for timer interrupt asserted */
+	if ((CONFIG_SYS_TMRPND_REG & CONFIG_SYS_TMRINTR_MASK) == CONFIG_SYS_TMRINTR_PEND) {
+		timerp->ter = (DTIM_DTER_CAP | DTIM_DTER_REF);
+		timestamp++;
+
+		#if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG)
+		if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0) {
+			WATCHDOG_RESET ();
+		}
+		#endif    /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
+		return;
+	}
+}
+
+void timer_init(void)
+{
+	volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_TMR_BASE);
+
+	timestamp = 0;
+
+	timerp->tcn = 0;
+	timerp->trr = 0;
+
+	/* Set up TIMER 4 as clock */
+	timerp->tmr = DTIM_DTMR_RST_RST;
+
+	/* initialize and enable timer interrupt */
+	irq_install_handler(CONFIG_SYS_TMRINTR_NO, dtimer_interrupt, 0);
+
+	timerp->tcn = 0;
+	timerp->trr = 1000;	/* Interrupt every ms */
+
+	dtimer_intr_setup();
+
+	/* set a period of 1us, set timer mode to restart and enable timer and interrupt */
+	timerp->tmr = CONFIG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 |
+	    DTIM_DTMR_FRR | DTIM_DTMR_ORRI | DTIM_DTMR_RST_EN;
+}
+
+void reset_timer(void)
+{
+	timestamp = 0;
+}
+
+ulong get_timer(ulong base)
+{
+	return (timestamp - base);
+}
+
+void set_timer(ulong t)
+{
+	timestamp = t;
+}
+#endif				/* CONFIG_MCFTMR */
+
+#if defined(CONFIG_MCFPIT)
+#if !defined(CONFIG_SYS_PIT_BASE)
+#	error	"CONFIG_SYS_PIT_BASE not defined!"
+#endif
+
+static unsigned short lastinc;
+
+void __udelay(unsigned long usec)
+{
+	volatile pit_t *timerp = (pit_t *) (CONFIG_SYS_UDELAY_BASE);
+	uint tmp;
+
+	while (usec > 0) {
+		if (usec > 65000)
+			tmp = 65000;
+		else
+			tmp = usec;
+		usec = usec - tmp;
+
+		/* Set up TIMER 3 as timebase clock */
+		timerp->pcsr = PIT_PCSR_OVW;
+		timerp->pmr = 0;
+		/* set period to 1 us */
+		timerp->pcsr |= PIT_PCSR_PRE(CONFIG_SYS_PIT_PRESCALE) | PIT_PCSR_EN;
+
+		timerp->pmr = tmp;
+		while (timerp->pcntr > 0) ;
+	}
+}
+
+void timer_init(void)
+{
+	volatile pit_t *timerp = (pit_t *) (CONFIG_SYS_PIT_BASE);
+	timestamp = 0;
+
+	/* Set up TIMER 4 as poll clock */
+	timerp->pcsr = PIT_PCSR_OVW;
+	timerp->pmr = lastinc = 0;
+	timerp->pcsr |= PIT_PCSR_PRE(CONFIG_SYS_PIT_PRESCALE) | PIT_PCSR_EN;
+}
+
+void set_timer(ulong t)
+{
+	volatile pit_t *timerp = (pit_t *) (CONFIG_SYS_PIT_BASE);
+
+	timestamp = 0;
+	timerp->pmr = lastinc = 0;
+}
+
+ulong get_timer(ulong base)
+{
+	unsigned short now, diff;
+	volatile pit_t *timerp = (pit_t *) (CONFIG_SYS_PIT_BASE);
+
+	now = timerp->pcntr;
+	diff = -(now - lastinc);
+
+	timestamp += diff;
+	lastinc = now;
+	return timestamp - base;
+}
+
+void wait_ticks(unsigned long ticks)
+{
+	set_timer(0);
+	while (get_timer(0) < ticks) ;
+}
+#endif				/* CONFIG_MCFPIT */
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On M68K it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+unsigned long usec2ticks(unsigned long usec)
+{
+	return get_timer(usec);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On M68K it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	ulong tbclk;
+	tbclk = CONFIG_SYS_HZ;
+	return tbclk;
+}
diff --git a/arch/m68k/lib/traps.c b/arch/m68k/lib/traps.c
new file mode 100644
index 0000000..1ca94dc
--- /dev/null
+++ b/arch/m68k/lib/traps.c
@@ -0,0 +1,76 @@
+/*
+ * (C) Copyright 2003
+ * Josef Baumgartner <josef.baumgartner@telex.de>
+ *
+ * (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 <command.h>
+#include <asm/processor.h>
+
+
+extern void _exc_handler(void);
+extern void _int_handler(void);
+
+static void show_frame(struct pt_regs *fp)
+{
+	printf ("Vector Number: %d  Format: %02x  Fault Status: %01x\n\n", (fp->vector & 0x3fc) >> 2,
+	        fp->format, (fp->vector & 0x3) | ((fp->vector & 0xc00) >> 8));
+	printf ("PC: %08lx    SR: %08lx    SP: %08lx\n", fp->pc, (long) fp->sr, (long) fp);
+	printf ("D0: %08lx    D1: %08lx    D2: %08lx    D3: %08lx\n",
+		fp->d0, fp->d1, fp->d2, fp->d3);
+	printf ("D4: %08lx    D5: %08lx    D6: %08lx    D7: %08lx\n",
+		fp->d4, fp->d5, fp->d6, fp->d7);
+	printf ("A0: %08lx    A1: %08lx    A2: %08lx    A3: %08lx\n",
+		fp->a0, fp->a1, fp->a2, fp->a3);
+	printf ("A4: %08lx    A5: %08lx    A6: %08lx\n",
+		fp->a4, fp->a5, fp->a6);
+}
+
+void exc_handler(struct pt_regs *fp) {
+	printf("\n\n*** Unexpected exception ***\n");
+	show_frame (fp);
+	printf("\n*** Please Reset Board! ***\n");
+	for(;;);
+}
+
+void trap_init(ulong value) {
+	unsigned long *vec = (ulong *)value;
+	int i;
+
+	for(i = 2; i < 25; i++) {
+		vec[i] = (unsigned long)_exc_handler;
+	}
+	for(i = 25; i < 32; i++) {
+		vec[i] = (unsigned long)_int_handler;
+	}
+	for(i = 32; i < 64; i++) {
+		vec[i] = (unsigned long)_exc_handler;
+	}
+	for(i = 64; i < 256; i++) {
+		vec[i] = (unsigned long)_int_handler;
+	}
+
+	setvbr(value);		/* set vector base register to new table */
+}
diff --git a/arch/microblaze/config.mk b/arch/microblaze/config.mk
new file mode 100644
index 0000000..c3c9f95
--- /dev/null
+++ b/arch/microblaze/config.mk
@@ -0,0 +1,31 @@
+#
+# (C) Copyright 2007-2008 Michal Simek
+# Michal SIMEK <monstr@monstr.eu>
+#
+# (C) Copyright 2004 Atmark Techno, Inc.
+# Yasushi SHOJI <yashi@atmark-techno.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
+#
+
+CROSS_COMPILE ?= mb-
+
+STANDALONE_LOAD_ADDR = 0x80F00000
+
+PLATFORM_CPPFLAGS += -ffixed-r31 -D__microblaze__
diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile
new file mode 100644
index 0000000..9b0f296
--- /dev/null
+++ b/arch/microblaze/lib/Makefile
@@ -0,0 +1,48 @@
+#
+# (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$(ARCH).a
+
+SOBJS-y	+=
+
+COBJS-y	+= board.o
+COBJS-y	+= bootm.o
+COBJS-y	+= cache.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)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c
new file mode 100644
index 0000000..d4baea9
--- /dev/null
+++ b/arch/microblaze/lib/board.c
@@ -0,0 +1,162 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ * (C) Copyright 2004 Atmark Techno, Inc.
+ *
+ * Michal  SIMEK <monstr@monstr.eu>
+ * Yasushi SHOJI <yashi@atmark-techno.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 <command.h>
+#include <malloc.h>
+#include <timestamp.h>
+#include <version.h>
+#include <watchdog.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+const char version_string[] = U_BOOT_VERSION " ("U_BOOT_DATE" - "U_BOOT_TIME")";
+
+#ifdef CONFIG_SYS_GPIO_0
+extern int gpio_init (void);
+#endif
+#ifdef CONFIG_SYS_INTC_0
+extern int interrupts_init (void);
+#endif
+#if defined(CONFIG_CMD_NET)
+extern int eth_init (bd_t * bis);
+#endif
+
+/*
+ * 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_fnc_t *init_sequence[] = {
+	env_init,
+	serial_init,
+#ifdef CONFIG_SYS_GPIO_0
+	gpio_init,
+#endif
+#ifdef CONFIG_SYS_INTC_0
+	interrupts_init,
+#endif
+	NULL,
+};
+
+void board_init (void)
+{
+	bd_t *bd;
+	init_fnc_t **init_fnc_ptr;
+	gd = (gd_t *) CONFIG_SYS_GBL_DATA_OFFSET;
+#if defined(CONFIG_CMD_FLASH)
+	ulong flash_size = 0;
+#endif
+	asm ("nop");	/* FIXME gd is not initialize - wait */
+	memset ((void *)gd, 0, CONFIG_SYS_GBL_DATA_SIZE);
+	gd->bd = (bd_t *) (gd + 1);	/* At end of global data */
+	gd->baudrate = CONFIG_BAUDRATE;
+	bd = gd->bd;
+	bd->bi_baudrate = CONFIG_BAUDRATE;
+	bd->bi_memstart = CONFIG_SYS_SDRAM_BASE;
+	bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE;
+	gd->flags |= GD_FLG_RELOC;      /* tell others: relocation done */
+
+	/*
+	 * The Malloc area is immediately below the monitor copy in DRAM
+	 * aka CONFIG_SYS_MONITOR_BASE - Note there is no need for reloc_off
+	 * as our monitory code is run from SDRAM
+	 */
+	mem_malloc_init (CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
+
+	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
+		WATCHDOG_RESET ();
+		if ((*init_fnc_ptr) () != 0) {
+			hang ();
+		}
+	}
+
+	puts ("SDRAM :\n");
+	printf ("\t\tIcache:%s\n", icache_status() ? "OK" : "FAIL");
+	printf ("\t\tDcache:%s\n", dcache_status() ? "OK" : "FAIL");
+	printf ("\tU-Boot Start:0x%08x\n", TEXT_BASE);
+
+#if defined(CONFIG_CMD_FLASH)
+	puts ("FLASH: ");
+	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
+	if (0 < (flash_size = flash_init ())) {
+		bd->bi_flashsize = flash_size;
+		bd->bi_flashoffset = CONFIG_SYS_FLASH_BASE + flash_size;
+# 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 ("Flash init FAILED");
+		bd->bi_flashstart = 0;
+		bd->bi_flashsize = 0;
+		bd->bi_flashoffset = 0;
+	}
+#endif
+
+#if defined(CONFIG_CMD_NET)
+	/* IP Address */
+	bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
+	eth_init (bd);
+#endif
+
+	/* relocate environment function pointers etc. */
+	env_relocate ();
+
+	/* main_loop */
+	for (;;) {
+		WATCHDOG_RESET ();
+		main_loop ();
+	}
+}
+
+void hang (void)
+{
+	puts ("### ERROR ### Please RESET the board ###\n");
+	for (;;) ;
+}
diff --git a/arch/microblaze/lib/bootm.c b/arch/microblaze/lib/bootm.c
new file mode 100644
index 0000000..bce4774
--- /dev/null
+++ b/arch/microblaze/lib/bootm.c
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ * (C) Copyright 2004 Atmark Techno, Inc.
+ *
+ * Michal  SIMEK <monstr@monstr.eu>
+ * Yasushi SHOJI <yashi@atmark-techno.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 <command.h>
+#include <image.h>
+#include <u-boot/zlib.h>
+#include <asm/byteorder.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	/* First parameter is mapped to $r5 for kernel boot args */
+	void	(*theKernel) (char *);
+	char	*commandline = getenv ("bootargs");
+
+	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+		return 1;
+
+	theKernel = (void (*)(char *))images->ep;
+
+	show_boot_progress (15);
+
+#ifdef DEBUG
+	printf ("## Transferring control to Linux (at address %08lx) ...\n",
+		(ulong) theKernel);
+#endif
+
+	theKernel (commandline);
+	/* does not return */
+
+	return 1;
+}
diff --git a/arch/microblaze/lib/cache.c b/arch/microblaze/lib/cache.c
new file mode 100644
index 0000000..4b2e8e3
--- /dev/null
+++ b/arch/microblaze/lib/cache.c
@@ -0,0 +1,43 @@
+/*
+ * (C) Copyright 2004 Atmark Techno, Inc.
+ *
+ * Yasushi SHOJI <yashi@atmark-techno.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>
+
+void flush_cache (ulong addr, ulong size)
+{
+	int i;
+	for (i = 0; i < size; i += 4)
+		asm volatile (
+#ifdef CONFIG_ICACHE
+				"wic	%0, r0;"
+#endif
+				"nop;"
+#ifdef CONFIG_DCACHE
+				"wdc	%0, r0;"
+#endif
+				"nop;"
+				:
+				: "r" (addr + i)
+				: "memory");
+}
diff --git a/arch/microblaze/lib/time.c b/arch/microblaze/lib/time.c
new file mode 100644
index 0000000..da016a0
--- /dev/null
+++ b/arch/microblaze/lib/time.c
@@ -0,0 +1,42 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ * (C) Copyright 2004 Atmark Techno, Inc.
+ *
+ * Michal  SIMEK <monstr@monstr.eu>
+ * Yasushi SHOJI <yashi@atmark-techno.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>
+
+#ifdef CONFIG_SYS_TIMER_0
+void __udelay (unsigned long usec)
+{
+	int i;
+	i = get_timer (0);
+	while ((get_timer (0) - i) < (usec / 1000)) ;
+}
+#else
+void __udelay (unsigned long usec)
+{
+	unsigned int i;
+	for (i = 0; i < (usec * CONFIG_XILINX_CLOCK_FREQ / 10000000); i++);
+}
+#endif
diff --git a/arch/mips/config.mk b/arch/mips/config.mk
new file mode 100644
index 0000000..aa06761
--- /dev/null
+++ b/arch/mips/config.mk
@@ -0,0 +1,52 @@
+#
+# (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
+#
+
+CROSS_COMPILE ?= mips_4KC-
+
+STANDALONE_LOAD_ADDR = 0x80200000 -T mips.lds
+
+PLATFORM_CPPFLAGS += -DCONFIG_MIPS -D__MIPS__
+
+#
+# From Linux arch/mips/Makefile
+#
+# GCC uses -G 0 -mabicalls -fpic as default.  We don't want PIC in the kernel
+# code since it only slows down the whole thing.  At some point we might make
+# use of global pointer optimizations but their use of $28 conflicts with
+# the current pointer optimization.
+#
+# The DECStation requires an ECOFF kernel for remote booting, other MIPS
+# machines may also.  Since BFD is incredibly buggy with respect to
+# crossformat linking we rely on the elf2ecoff tool for format conversion.
+#
+# cflags-y			+= -G 0 -mno-abicalls -fno-pic -pipe
+# cflags-y			+= -msoft-float
+# LDFLAGS_vmlinux		+= -G 0 -static -n -nostdlib
+# MODFLAGS			+= -mlong-calls
+#
+# On the other hand, we want PIC in the U-Boot code to relocate it from ROM
+# to RAM. $28 is always used as gp.
+#
+PLATFORM_CPPFLAGS		+= -G 0 -mabicalls -fpic
+PLATFORM_CPPFLAGS		+= -msoft-float
+PLATFORM_LDFLAGS		+= -G 0 -static -n -nostdlib
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
new file mode 100644
index 0000000..7967e58
--- /dev/null
+++ b/arch/mips/lib/Makefile
@@ -0,0 +1,51 @@
+#
+# (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$(ARCH).a
+
+SOBJS-y	+=
+
+COBJS-y	+= board.o
+ifeq ($(CONFIG_QEMU_MIPS),y)
+COBJS-y	+= bootm_qemu_mips.o
+else
+COBJS-y	+= bootm.o
+endif
+COBJS-y	+= time.o
+
+SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/mips/lib/board.c b/arch/mips/lib/board.c
new file mode 100644
index 0000000..b2d113e
--- /dev/null
+++ b/arch/mips/lib/board.c
@@ -0,0 +1,436 @@
+/*
+ * (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>
+#include <command.h>
+#include <malloc.h>
+#include <stdio_dev.h>
+#include <timestamp.h>
+#include <version.h>
+#include <net.h>
+#include <environment.h>
+#include <nand.h>
+#include <onenand_uboot.h>
+#include <spi.h>
+
+#ifdef CONFIG_BITBANGMII
+#include <miiphy.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if ( ((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
+
+#undef DEBUG
+
+extern int timer_init(void);
+
+extern int incaip_set_cpuclk(void);
+
+extern ulong uboot_end_data;
+extern ulong uboot_end;
+
+ulong monitor_flash_len;
+
+const char version_string[] =
+	U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")";
+
+static char *failed = "*** failed ***\n";
+
+/*
+ * mips_io_port_base is the begin of the address space to which x86 style
+ * I/O ports are mapped.
+ */
+unsigned long mips_io_port_base = -1;
+
+int __board_early_init_f(void)
+{
+	/*
+	 * Nothing to do in this dummy implementation
+	 */
+	return 0;
+}
+int board_early_init_f(void) __attribute__((weak, alias("__board_early_init_f")));
+
+
+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, "\n");
+		return (0);
+	}
+	puts (failed);
+	return (1);
+}
+
+static int display_banner(void)
+{
+
+	printf ("\n\n%s\n\n", version_string);
+	return (0);
+}
+
+#ifndef CONFIG_SYS_NO_FLASH
+static void display_flash_config(ulong size)
+{
+	puts ("Flash: ");
+	print_size (size, "\n");
+}
+#endif
+
+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);
+}
+
+
+/*
+ * Breath some life into the board...
+ *
+ * The first part of initialization is running from Flash memory;
+ * its main purpose is to initialize the RAM so that we
+ * can relocate the monitor code to RAM.
+ */
+
+/*
+ * 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_fnc_t *init_sequence[] = {
+	board_early_init_f,
+	timer_init,
+	env_init,		/* initialize environment */
+#ifdef CONFIG_INCA_IP
+	incaip_set_cpuclk,	/* set cpu clock according to environment variable */
+#endif
+	init_baudrate,		/* initialze baudrate settings */
+	serial_init,		/* serial communications setup */
+	console_init_f,
+	display_banner,		/* say that we are here */
+	checkboard,
+	init_func_ram,
+	NULL,
+};
+
+
+void board_init_f(ulong bootflag)
+{
+	gd_t gd_data, *id;
+	bd_t *bd;
+	init_fnc_t **init_fnc_ptr;
+	ulong addr, addr_sp, len = (ulong)&uboot_end - CONFIG_SYS_MONITOR_BASE;
+	ulong *s;
+#ifdef CONFIG_PURPLE
+	void copy_code (ulong);
+#endif
+
+	/* Pointer is writable since we allocated a register for it.
+	 */
+	gd = &gd_data;
+	/* compiler optimization barrier needed for GCC >= 3.4 */
+	__asm__ __volatile__("": : :"memory");
+
+	memset ((void *)gd, 0, sizeof (gd_t));
+
+	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.
+	 */
+	addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
+
+	/* We can reserve some RAM "on top" here.
+	 */
+
+	/* round down to next 4 kB limit.
+	 */
+	addr &= ~(4096 - 1);
+	debug ("Top of RAM usable for U-Boot at: %08lx\n", addr);
+
+	/* Reserve memory for U-Boot code, data & bss
+	 * round down to next 16 kB limit
+	 */
+	addr -= len;
+	addr &= ~(16 * 1024 - 1);
+
+	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);
+
+	/* Reserve memory for boot params.
+	 */
+	addr_sp -= CONFIG_SYS_BOOTPARAMS_LEN;
+	bd->bi_boot_params = addr_sp;
+	debug ("Reserving %dk for boot params() at: %08lx\n",
+			CONFIG_SYS_BOOTPARAMS_LEN >> 10, 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 */
+	bd->bi_baudrate	= gd->baudrate;		/* Console Baudrate */
+
+	memcpy (id, (void *)gd, sizeof (gd_t));
+
+	/* On the purple board we copy the code in a special way
+	 * in order to solve flash problems
+	 */
+#ifdef CONFIG_PURPLE
+	copy_code(addr);
+#endif
+
+	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)
+{
+	cmd_tbl_t *cmdtp;
+#ifndef CONFIG_SYS_NO_FLASH
+	ulong size;
+#endif
+	extern void malloc_bin_reloc (void);
+#ifndef CONFIG_ENV_IS_NOWHERE
+	extern char * env_name_spec;
+#endif
+	char *s;
+	bd_t *bd;
+
+	gd = id;
+	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
+
+	debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
+
+	gd->reloc_off = dest_addr - CONFIG_SYS_MONITOR_BASE;
+
+	monitor_flash_len = (ulong)&uboot_end_data - dest_addr;
+
+	/*
+	 * We have to relocate the command table manually
+	 */
+	for (cmdtp = &__u_boot_cmd_start; cmdtp !=  &__u_boot_cmd_end; cmdtp++) {
+		ulong addr;
+
+		addr = (ulong) (cmdtp->cmd) + gd->reloc_off;
+#if 0
+		printf ("Command \"%s\": 0x%08lx => 0x%08lx\n",
+				cmdtp->name, (ulong) (cmdtp->cmd), addr);
+#endif
+		cmdtp->cmd =
+			(int (*)(struct cmd_tbl_s *, int, int, char *[]))addr;
+
+		addr = (ulong)(cmdtp->name) + gd->reloc_off;
+		cmdtp->name = (char *)addr;
+
+		if (cmdtp->usage) {
+			addr = (ulong)(cmdtp->usage) + gd->reloc_off;
+			cmdtp->usage = (char *)addr;
+		}
+#ifdef	CONFIG_SYS_LONGHELP
+		if (cmdtp->help) {
+			addr = (ulong)(cmdtp->help) + gd->reloc_off;
+			cmdtp->help = (char *)addr;
+		}
+#endif
+	}
+	/* there are some other pointer constants we must deal with */
+#ifndef CONFIG_ENV_IS_NOWHERE
+	env_name_spec += gd->reloc_off;
+#endif
+
+	bd = gd->bd;
+
+	/* The Malloc area is immediately below the monitor copy in DRAM */
+	mem_malloc_init(CONFIG_SYS_MONITOR_BASE + gd->reloc_off -
+			TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN);
+	malloc_bin_reloc();
+
+#ifndef CONFIG_SYS_NO_FLASH
+	/* configure available FLASH banks */
+	size = flash_init();
+	display_flash_config (size);
+	bd->bi_flashsize = size;
+#endif
+
+	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
+#if CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
+	bd->bi_flashoffset = monitor_flash_len;	/* reserved area for U-Boot */
+#else
+	bd->bi_flashoffset = 0;
+#endif
+
+#ifdef CONFIG_CMD_NAND
+	puts ("NAND:  ");
+	nand_init ();		/* go init the NAND */
+#endif
+
+#if defined(CONFIG_CMD_ONENAND)
+	onenand_init();
+#endif
+
+	/* relocate environment function pointers etc. */
+	env_relocate();
+
+	/* IP Address */
+	bd->bi_ip_addr = getenv_IPaddr("ipaddr");
+
+#if defined(CONFIG_PCI)
+	/*
+	 * Do pci configuration
+	 */
+	pci_init();
+#endif
+
+/** leave this here (after malloc(), environment and PCI are working) **/
+	/* Initialize stdio devices */
+	stdio_init ();
+
+	jumptable_init ();
+
+	/* Initialize the console (after the relocation and devices init) */
+	console_init_r ();
+/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/
+
+	/* 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
+
+#ifdef CONFIG_CMD_SPI
+	puts ("SPI:   ");
+	spi_init ();		/* go init the SPI */
+	puts ("ready\n");
+#endif
+
+#if defined(CONFIG_MISC_INIT_R)
+	/* miscellaneous platform dependent initialisations */
+	misc_init_r ();
+#endif
+
+#ifdef CONFIG_BITBANGMII
+	bb_miiphy_init();
+#endif
+#if defined(CONFIG_CMD_NET)
+#if defined(CONFIG_NET_MULTI)
+	puts ("Net:   ");
+#endif
+	eth_initialize(gd->bd);
+#endif
+
+	/* main_loop() can return to retry autoboot, if so just run it again. */
+	for (;;) {
+		main_loop ();
+	}
+
+	/* NOTREACHED - no way out of command loop except booting */
+}
+
+void hang (void)
+{
+	puts ("### ERROR ### Please RESET the board ###\n");
+	for (;;);
+}
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
new file mode 100644
index 0000000..54af24c
--- /dev/null
+++ b/arch/mips/lib/bootm.c
@@ -0,0 +1,174 @@
+/*
+ * (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>
+#include <command.h>
+#include <image.h>
+#include <u-boot/zlib.h>
+#include <asm/byteorder.h>
+#include <asm/addrspace.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define	LINUX_MAX_ENVS		256
+#define	LINUX_MAX_ARGS		256
+
+static int	linux_argc;
+static char **	linux_argv;
+
+static char **	linux_env;
+static char *	linux_env_p;
+static int	linux_env_idx;
+
+static void linux_params_init (ulong start, char * commandline);
+static void linux_env_set (char * env_name, char * env_val);
+
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	void	(*theKernel) (int, char **, char **, int *);
+	char	*commandline = getenv ("bootargs");
+	char	env_buf[12];
+	char	*cp;
+
+	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+		return 1;
+
+	/* find kernel entry point */
+	theKernel = (void (*)(int, char **, char **, int *))images->ep;
+
+	show_boot_progress (15);
+
+#ifdef DEBUG
+	printf ("## Transferring control to Linux (at address %08lx) ...\n",
+		(ulong) theKernel);
+#endif
+
+	linux_params_init (UNCACHED_SDRAM (gd->bd->bi_boot_params), commandline);
+
+#ifdef CONFIG_MEMSIZE_IN_BYTES
+	sprintf (env_buf, "%lu", (ulong)gd->ram_size);
+	debug ("## Giving linux memsize in bytes, %lu\n", (ulong)gd->ram_size);
+#else
+	sprintf (env_buf, "%lu", (ulong)(gd->ram_size >> 20));
+	debug ("## Giving linux memsize in MB, %lu\n", (ulong)(gd->ram_size >> 20));
+#endif /* CONFIG_MEMSIZE_IN_BYTES */
+
+	linux_env_set ("memsize", env_buf);
+
+	sprintf (env_buf, "0x%08X", (uint) UNCACHED_SDRAM (images->rd_start));
+	linux_env_set ("initrd_start", env_buf);
+
+	sprintf (env_buf, "0x%X", (uint) (images->rd_end - images->rd_start));
+	linux_env_set ("initrd_size", env_buf);
+
+	sprintf (env_buf, "0x%08X", (uint) (gd->bd->bi_flashstart));
+	linux_env_set ("flash_start", env_buf);
+
+	sprintf (env_buf, "0x%X", (uint) (gd->bd->bi_flashsize));
+	linux_env_set ("flash_size", env_buf);
+
+	cp = getenv("ethaddr");
+	if (cp != NULL) {
+		linux_env_set("ethaddr", cp);
+	}
+
+	cp = getenv("eth1addr");
+	if (cp != NULL) {
+		linux_env_set("eth1addr", cp);
+	}
+
+	/* we assume that the kernel is in place */
+	printf ("\nStarting kernel ...\n\n");
+
+	theKernel (linux_argc, linux_argv, linux_env, 0);
+	/* does not return */
+	return 1;
+}
+
+static void linux_params_init (ulong start, char *line)
+{
+	char *next, *quote, *argp;
+
+	linux_argc = 1;
+	linux_argv = (char **) start;
+	linux_argv[0] = 0;
+	argp = (char *) (linux_argv + LINUX_MAX_ARGS);
+
+	next = line;
+
+	while (line && *line && linux_argc < LINUX_MAX_ARGS) {
+		quote = strchr (line, '"');
+		next = strchr (line, ' ');
+
+		while (next != NULL && quote != NULL && quote < next) {
+			/* we found a left quote before the next blank
+			 * now we have to find the matching right quote
+			 */
+			next = strchr (quote + 1, '"');
+			if (next != NULL) {
+				quote = strchr (next + 1, '"');
+				next = strchr (next + 1, ' ');
+			}
+		}
+
+		if (next == NULL) {
+			next = line + strlen (line);
+		}
+
+		linux_argv[linux_argc] = argp;
+		memcpy (argp, line, next - line);
+		argp[next - line] = 0;
+
+		argp += next - line + 1;
+		linux_argc++;
+
+		if (*next)
+			next++;
+
+		line = next;
+	}
+
+	linux_env = (char **) (((ulong) argp + 15) & ~15);
+	linux_env[0] = 0;
+	linux_env_p = (char *) (linux_env + LINUX_MAX_ENVS);
+	linux_env_idx = 0;
+}
+
+static void linux_env_set (char *env_name, char *env_val)
+{
+	if (linux_env_idx < LINUX_MAX_ENVS - 1) {
+		linux_env[linux_env_idx] = linux_env_p;
+
+		strcpy (linux_env_p, env_name);
+		linux_env_p += strlen (env_name);
+
+		strcpy (linux_env_p, "=");
+		linux_env_p += 1;
+
+		strcpy (linux_env_p, env_val);
+		linux_env_p += strlen (env_val);
+
+		linux_env_p++;
+		linux_env[++linux_env_idx] = 0;
+	}
+}
diff --git a/arch/mips/lib/bootm_qemu_mips.c b/arch/mips/lib/bootm_qemu_mips.c
new file mode 100644
index 0000000..cc70fa9
--- /dev/null
+++ b/arch/mips/lib/bootm_qemu_mips.c
@@ -0,0 +1,76 @@
+/*
+ * (C) Copyright 2008
+ * Jean-Christophe PLAGNIOL-VILLARD <jcplagniol@jcrosoft.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 <command.h>
+#include <image.h>
+#include <asm/byteorder.h>
+#include <asm/addrspace.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	void	(*theKernel) (int, char **, char **, int *);
+	char	*bootargs = getenv ("bootargs");
+	char	*start;
+	uint	len;
+
+	/* find kernel entry point */
+	theKernel = (void (*)(int, char **, char **, int *))images->ep;
+
+	show_boot_progress (15);
+
+	debug ("## Transferring control to Linux (at address %08lx) ...\n",
+		(ulong) theKernel);
+
+	gd->bd->bi_boot_params = gd->bd->bi_memstart + (16 << 20) - 256;
+	debug ("%-12s= 0x%08lX\n", "boot_params", (ulong)gd->bd->bi_boot_params);
+
+	/* set Magic */
+	*(int32_t *)(gd->bd->bi_boot_params - 4) = 0x12345678;
+	/* set ram_size */
+	*(int32_t *)(gd->bd->bi_boot_params - 8) = gd->ram_size;
+
+	start = (char*)gd->bd->bi_boot_params;
+
+	len = strlen(bootargs);
+
+	strncpy(start, bootargs, len + 1);
+
+	start += len;
+
+	len = images->rd_end - images->rd_start;
+	if (len > 0) {
+		start += sprintf(start," rd_start=0x%08X rd_size=0x%0X",
+		(uint) UNCACHED_SDRAM (images->rd_start),
+		(uint) len);
+	}
+
+	/* we assume that the kernel is in place */
+	printf ("\nStarting kernel ...\n\n");
+
+	theKernel (0, NULL, NULL, 0);
+	/* does not return */
+	return 1;
+}
diff --git a/arch/mips/lib/time.c b/arch/mips/lib/time.c
new file mode 100644
index 0000000..0e66441
--- /dev/null
+++ b/arch/mips/lib/time.c
@@ -0,0 +1,98 @@
+/*
+ * (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>
+#include <asm/mipsregs.h>
+
+static unsigned long timestamp;
+
+/* how many counter cycles in a jiffy */
+#define CYCLES_PER_JIFFY	(CONFIG_SYS_MIPS_TIMER_FREQ + CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ
+
+/*
+ * timer without interrupts
+ */
+
+int timer_init(void)
+{
+	/* Set up the timer for the first expiration. */
+	timestamp = 0;
+	write_c0_compare(read_c0_count() + CYCLES_PER_JIFFY);
+
+	return 0;
+}
+
+void reset_timer(void)
+{
+	timestamp = 0;
+	write_c0_compare(read_c0_count() + CYCLES_PER_JIFFY);
+}
+
+ulong get_timer(ulong base)
+{
+	unsigned int count;
+	unsigned int expirelo = read_c0_compare();
+
+	/* Check to see if we have missed any timestamps. */
+	count = read_c0_count();
+	while ((count - expirelo) < 0x7fffffff) {
+		expirelo += CYCLES_PER_JIFFY;
+		timestamp++;
+	}
+	write_c0_compare(expirelo);
+
+	return (timestamp - base);
+}
+
+void set_timer(ulong t)
+{
+	timestamp = t;
+	write_c0_compare(read_c0_count() + CYCLES_PER_JIFFY);
+}
+
+void __udelay(unsigned long usec)
+{
+	unsigned int tmo;
+
+	tmo = read_c0_count() + (usec * (CONFIG_SYS_MIPS_TIMER_FREQ / 1000000));
+	while ((tmo - read_c0_count()) < 0x7fffffff)
+		/*NOP*/;
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On MIPS it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On MIPS it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	return CONFIG_SYS_HZ;
+}
diff --git a/arch/nios/config.mk b/arch/nios/config.mk
new file mode 100644
index 0000000..e1b9f07
--- /dev/null
+++ b/arch/nios/config.mk
@@ -0,0 +1,29 @@
+#
+# (C) Copyright 2003
+# Psyent Corporation <www.psyent.com>
+# Scott McNutt <smcnutt@psyent.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
+#
+
+CROSS_COMPILE ?= nios-elf-
+
+STANDALONE_LOAD_ADDR = 0x00800000 -L $(gcclibdir)/m32
+
+PLATFORM_CPPFLAGS += -m32 -DCONFIG_NIOS -D__NIOS__ -ffixed-g7 -gstabs
diff --git a/arch/nios/lib/Makefile b/arch/nios/lib/Makefile
new file mode 100644
index 0000000..f66e989
--- /dev/null
+++ b/arch/nios/lib/Makefile
@@ -0,0 +1,50 @@
+#
+# (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	+=
+
+COBJS-y	+= board.o
+COBJS-y	+= bootm.o
+COBJS-y	+= cache.o
+COBJS-y	+= divmod.o
+COBJS-y	+= mult.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)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/nios/lib/board.c b/arch/nios/lib/board.c
new file mode 100644
index 0000000..5d2fb2e
--- /dev/null
+++ b/arch/nios/lib/board.c
@@ -0,0 +1,168 @@
+/*
+ * (C) Copyright 2003, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.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 <stdio_dev.h>
+#include <watchdog.h>
+#include <malloc.h>
+#include <net.h>
+#ifdef CONFIG_STATUS_LED
+#include <status_led.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * 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);
+
+
+/************************************************************************
+ * Initialization sequence						*
+ ***********************************************************************/
+
+init_fnc_t *init_sequence[] = {
+
+#if defined(CONFIG_BOARD_EARLY_INIT_F)
+	board_early_init_f,	/* Call board-specific init code early.*/
+#endif
+
+	env_init,
+	serial_init,
+	console_init_f,
+	display_options,
+	checkcpu,
+	checkboard,
+	NULL,			/* Terminate this list */
+};
+
+
+/***********************************************************************/
+void board_init (void)
+{
+	bd_t *bd;
+	init_fnc_t **init_fnc_ptr;
+	char *s, *e;
+	int i;
+
+	/* Pointer is writable since we allocated a register for it.
+	 * Nios treats CONFIG_SYS_GBL_DATA_OFFSET as an address.
+	 */
+	gd = (gd_t *)CONFIG_SYS_GBL_DATA_OFFSET;
+	/* compiler optimization barrier needed for GCC >= 3.4 */
+	__asm__ __volatile__("": : :"memory");
+
+	memset( gd, 0, CONFIG_SYS_GBL_DATA_SIZE );
+
+	gd->bd = (bd_t *)(gd+1);	/* At end of global data */
+	gd->baudrate = CONFIG_BAUDRATE;
+	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
+
+	bd = gd->bd;
+	bd->bi_memstart	= CONFIG_SYS_SDRAM_BASE;
+	bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE;
+	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
+#if	defined(CONFIG_SYS_SRAM_BASE) && defined(CONFIG_SYS_SRAM_SIZE)
+	bd->bi_sramstart= CONFIG_SYS_SRAM_BASE;
+	bd->bi_sramsize	= CONFIG_SYS_SRAM_SIZE;
+#endif
+	bd->bi_baudrate	= CONFIG_BAUDRATE;
+
+	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
+		WATCHDOG_RESET ();
+		if ((*init_fnc_ptr) () != 0) {
+			hang ();
+		}
+	}
+
+	WATCHDOG_RESET ();
+
+	/* The Malloc area is immediately below the monitor copy in RAM */
+	mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
+
+	WATCHDOG_RESET ();
+	bd->bi_flashsize = flash_init();
+
+	WATCHDOG_RESET ();
+	env_relocate();
+
+	bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
+
+	WATCHDOG_RESET ();
+	stdio_init();
+	jumptable_init();
+	console_init_r();
+	/*
+	 */
+
+	WATCHDOG_RESET ();
+	interrupt_init ();
+
+#ifdef CONFIG_STATUS_LED
+	status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING);
+#endif
+
+	/* main_loop */
+	for (;;) {
+		WATCHDOG_RESET ();
+		main_loop ();
+	}
+}
+
+
+/***********************************************************************/
+
+void hang (void)
+{
+#ifdef CONFIG_STATUS_LED
+	status_led_set(STATUS_LED_BOOT, STATUS_LED_OFF);
+	status_led_set(STATUS_LED_RED, STATUS_LED_BLINKING);
+#endif
+	puts("### ERROR ### Please reset board ###\n");
+	for (;;);
+}
+
+unsigned long do_go_exec (ulong (*entry)(int, char *[]), int argc, char *argv[])
+{
+	/*
+	 * x86 does not use a dedicated register to pass the pointer
+	 * to the global_data
+	 */
+	argv[-1] = (char *)gd;
+	return entry (argc, argv);
+}
diff --git a/arch/nios/lib/bootm.c b/arch/nios/lib/bootm.c
new file mode 100644
index 0000000..b0d5b82
--- /dev/null
+++ b/arch/nios/lib/bootm.c
@@ -0,0 +1,34 @@
+/*
+ * (C) Copyright 2003, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.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 <command.h>
+
+/* FIXME: Once we find a stable version of uC-linux for nios
+ * we can get this working. ;-)
+ *
+ */
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	return 1;
+}
diff --git a/arch/nios/lib/cache.c b/arch/nios/lib/cache.c
new file mode 100644
index 0000000..87dbab1
--- /dev/null
+++ b/arch/nios/lib/cache.c
@@ -0,0 +1,32 @@
+/*
+ * (C) Copyright 2003, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.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>
+
+
+void flush_cache (ulong addr, ulong size)
+{
+	/* Nios cache is write-thru -- nothing to do here.
+	 */
+	return;
+}
diff --git a/arch/nios/lib/divmod.c b/arch/nios/lib/divmod.c
new file mode 100644
index 0000000..3c7e71e
--- /dev/null
+++ b/arch/nios/lib/divmod.c
@@ -0,0 +1,101 @@
+/*
+ * This file is part of GNU CC.
+ *
+ * GNU CC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU CC 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 GNU CC; see the file COPYING.  If not, write
+ * to the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include "math.h"
+
+USItype udivmodsi4 (USItype num, USItype den, word_type modwanted)
+{
+	USItype bit = 1;
+	USItype res = 0;
+
+	while (den < num && bit && !(den & (1L << 31))) {
+		den <<= 1;
+		bit <<= 1;
+	}
+	while (bit) {
+		if (num >= den) {
+			num -= den;
+			res |= bit;
+		}
+		bit >>= 1;
+		den >>= 1;
+	}
+	if (modwanted)
+		return num;
+	return res;
+}
+
+
+SItype __divsi3 (SItype a, SItype b)
+{
+	word_type neg = 0;
+	SItype res;
+
+	if (a < 0) {
+		a = -a;
+		neg = !neg;
+	}
+
+	if (b < 0) {
+		b = -b;
+		neg = !neg;
+	}
+
+	res = udivmodsi4 (a, b, 0);
+
+	if (neg)
+		res = -res;
+
+	return res;
+}
+
+
+SItype __modsi3 (SItype a, SItype b)
+{
+	word_type neg = 0;
+	SItype res;
+
+	if (a < 0) {
+		a = -a;
+		neg = 1;
+	}
+
+	if (b < 0)
+		b = -b;
+
+	res = udivmodsi4 (a, b, 1);
+
+	if (neg)
+		res = -res;
+
+	return res;
+}
+
+
+SItype __udivsi3 (SItype a, SItype b)
+{
+	return udivmodsi4 (a, b, 0);
+}
+
+
+SItype __umodsi3 (SItype a, SItype b)
+{
+	return udivmodsi4 (a, b, 1);
+}
diff --git a/arch/nios/lib/math.h b/arch/nios/lib/math.h
new file mode 100644
index 0000000..f0aed8e
--- /dev/null
+++ b/arch/nios/lib/math.h
@@ -0,0 +1,16 @@
+#define BITS_PER_UNIT	8
+
+typedef	 int HItype			__attribute__ ((mode (HI)));
+typedef unsigned int UHItype		__attribute__ ((mode (HI)));
+
+typedef		 int SItype		__attribute__ ((mode (SI)));
+typedef unsigned int USItype		__attribute__ ((mode (SI)));
+
+typedef int word_type			__attribute__ ((mode (__word__)));
+
+struct SIstruct {HItype low, high;};
+
+typedef union {
+	struct SIstruct s;
+	SItype ll;
+} SIunion;
diff --git a/arch/nios/lib/mult.c b/arch/nios/lib/mult.c
new file mode 100644
index 0000000..ec8139e
--- /dev/null
+++ b/arch/nios/lib/mult.c
@@ -0,0 +1,56 @@
+/*
+ * This file is part of GNU CC.
+ *
+ * GNU CC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU CC 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 GNU CC; see the file COPYING.  If not, write
+ * to the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include <common.h>
+
+#if !defined(CONFIG_SYS_NIOS_MULT_HW) && !defined(CONFIG_SYS_NIOS_MULT_MSTEP)
+
+#include "math.h"
+
+USItype __mulsi3 (USItype a, USItype b)
+{
+	USItype c = 0;
+
+	while (a != 0) {
+		if (a & 1)
+			c += b;
+		a >>= 1;
+		b <<= 1;
+	}
+
+	return c;
+}
+
+
+UHItype __mulhi3 (UHItype a, UHItype b)
+{
+	UHItype c = 0;
+
+	while (a != 0) {
+		if (a & 1)
+			c += b;
+		a >>= 1;
+		b <<= 1;
+	}
+
+	return c;
+}
+
+#endif /*!defined(CONFIG_SYS_NIOS_MULT_HW) && !defined(CONFIG_SYS_NIOS_MULT_MSTEP) */
diff --git a/arch/nios/lib/time.c b/arch/nios/lib/time.c
new file mode 100644
index 0000000..d5096ee
--- /dev/null
+++ b/arch/nios/lib/time.c
@@ -0,0 +1,38 @@
+/*
+ * (C) Copyright 2003, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.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>
+
+
+extern void dly_clks( unsigned long ticks );
+
+void __udelay(unsigned long usec)
+{
+	/* The Nios core doesn't have a timebase, so we do our
+	 * best for now and call a low-level loop that counts
+	 * cpu clocks.
+	 */
+	unsigned long cnt = (CONFIG_SYS_CLK_FREQ/1000000) * usec;
+	dly_clks (cnt);
+}
diff --git a/arch/nios2/config.mk b/arch/nios2/config.mk
new file mode 100644
index 0000000..be40639
--- /dev/null
+++ b/arch/nios2/config.mk
@@ -0,0 +1,30 @@
+#
+# (C) Copyright 2004
+# Psyent Corporation <www.psyent.com>
+# Scott McNutt <smcnutt@psyent.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
+#
+
+CROSS_COMPILE ?= nios2-elf-
+
+STANDALONE_LOAD_ADDR = 0x02000000 -L $(gcclibdir)
+
+PLATFORM_CPPFLAGS += -DCONFIG_NIOS2 -D__NIOS2__
+PLATFORM_CPPFLAGS += -ffixed-r15 -G0
diff --git a/arch/nios2/lib/Makefile b/arch/nios2/lib/Makefile
new file mode 100644
index 0000000..b69bc38
--- /dev/null
+++ b/arch/nios2/lib/Makefile
@@ -0,0 +1,49 @@
+#
+# (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	+= cache.o
+
+COBJS-y	+= board.o
+COBJS-y	+= bootm.o
+COBJS-y	+= divmod.o
+COBJS-y	+= mult.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)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c
new file mode 100644
index 0000000..8ec66a3
--- /dev/null
+++ b/arch/nios2/lib/board.c
@@ -0,0 +1,164 @@
+/*
+ * (C) Copyright 2003, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.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 <stdio_dev.h>
+#include <watchdog.h>
+#include <malloc.h>
+#include <net.h>
+#ifdef CONFIG_STATUS_LED
+#include <status_led.h>
+#endif
+#if defined(CONFIG_SYS_NIOS_EPCSBASE)
+#include <nios2-epcs.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * 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);
+
+
+/************************************************************************
+ * Initialization sequence						*
+ ***********************************************************************/
+
+init_fnc_t *init_sequence[] = {
+
+#if defined(CONFIG_BOARD_EARLY_INIT_F)
+	board_early_init_f,	/* Call board-specific init code early.*/
+#endif
+#if defined(CONFIG_SYS_NIOS_EPCSBASE)
+	epcs_reset,
+#endif
+
+	env_init,
+	serial_init,
+	console_init_f,
+	display_options,
+	checkcpu,
+	checkboard,
+	NULL,			/* Terminate this list */
+};
+
+
+/***********************************************************************/
+void board_init (void)
+{
+	bd_t *bd;
+	init_fnc_t **init_fnc_ptr;
+
+	/* Pointer is writable since we allocated a register for it.
+	 * Nios treats CONFIG_SYS_GBL_DATA_OFFSET as an address.
+	 */
+	gd = (gd_t *)CONFIG_SYS_GBL_DATA_OFFSET;
+	/* compiler optimization barrier needed for GCC >= 3.4 */
+	__asm__ __volatile__("": : :"memory");
+
+	memset( gd, 0, CONFIG_SYS_GBL_DATA_SIZE );
+
+	gd->bd = (bd_t *)(gd+1);	/* At end of global data */
+	gd->baudrate = CONFIG_BAUDRATE;
+	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
+
+	bd = gd->bd;
+	bd->bi_memstart	= CONFIG_SYS_SDRAM_BASE;
+	bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE;
+	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
+#if	defined(CONFIG_SYS_SRAM_BASE) && defined(CONFIG_SYS_SRAM_SIZE)
+	bd->bi_sramstart= CONFIG_SYS_SRAM_BASE;
+	bd->bi_sramsize	= CONFIG_SYS_SRAM_SIZE;
+#endif
+	bd->bi_baudrate	= CONFIG_BAUDRATE;
+
+	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
+		WATCHDOG_RESET ();
+		if ((*init_fnc_ptr) () != 0) {
+			hang ();
+		}
+	}
+
+	WATCHDOG_RESET ();
+
+	/* The Malloc area is immediately below the monitor copy in RAM */
+	mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
+
+	WATCHDOG_RESET ();
+	bd->bi_flashsize = flash_init();
+
+	WATCHDOG_RESET ();
+	env_relocate();
+
+	bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
+
+	WATCHDOG_RESET ();
+	stdio_init();
+	jumptable_init();
+	console_init_r();
+
+	WATCHDOG_RESET ();
+	interrupt_init ();
+
+#if defined(CONFIG_BOARD_LATE_INIT)
+	board_late_init ();
+#endif
+
+#if defined(CONFIG_CMD_NET)
+#if defined(CONFIG_NET_MULTI)
+	puts ("Net:   ");
+#endif
+	eth_initialize (bd);
+#endif
+
+	/* main_loop */
+	for (;;) {
+		WATCHDOG_RESET ();
+		main_loop ();
+	}
+}
+
+
+/***********************************************************************/
+
+void hang (void)
+{
+	disable_interrupts ();
+	puts("### ERROR ### Please reset board ###\n");
+	for (;;);
+}
diff --git a/arch/nios2/lib/bootm.c b/arch/nios2/lib/bootm.c
new file mode 100644
index 0000000..5d25edf
--- /dev/null
+++ b/arch/nios2/lib/bootm.c
@@ -0,0 +1,52 @@
+/*
+ * (C) Copyright 2003, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.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 <command.h>
+#include <asm/byteorder.h>
+#include <asm/cache.h>
+
+#define NIOS_MAGIC 0x534f494e /* enable command line and initrd passing */
+
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	void (*kernel)(int, int, int, char *) = (void *)images->ep;
+	char *commandline = getenv("bootargs");
+	ulong initrd_start = images->rd_start;
+	ulong initrd_end = images->rd_end;
+
+	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+		return 1;
+
+	/* flushes data and instruction caches before calling the kernel */
+	disable_interrupts();
+	flush_dcache((ulong)kernel, CONFIG_SYS_DCACHE_SIZE);
+	flush_icache((ulong)kernel, CONFIG_SYS_ICACHE_SIZE);
+
+	debug("bootargs=%s @ 0x%lx\n", commandline, (ulong)&commandline);
+	debug("initrd=0x%lx-0x%lx\n", (ulong)initrd_start, (ulong)initrd_end);
+	kernel(NIOS_MAGIC, initrd_start, initrd_end, commandline);
+	/* does not return */
+
+	return 1;
+}
diff --git a/arch/nios2/lib/cache.S b/arch/nios2/lib/cache.S
new file mode 100644
index 0000000..ee3b4b7
--- /dev/null
+++ b/arch/nios2/lib/cache.S
@@ -0,0 +1,74 @@
+/*
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.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>
+
+	.text
+
+	.global flush_dcache
+
+flush_dcache:
+	add	r5, r5, r4
+	movhi	r8, %hi(CONFIG_SYS_DCACHELINE_SIZE)
+	ori	r8, r8, %lo(CONFIG_SYS_DCACHELINE_SIZE)
+0:	flushd	0(r4)
+	add	r4, r4, r8
+	bltu	r4, r5, 0b
+	ret
+
+
+	.global flush_icache
+
+flush_icache:
+	add	r5, r5, r4
+	movhi	r8, %hi(CONFIG_SYS_ICACHELINE_SIZE)
+	ori	r8, r8, %lo(CONFIG_SYS_ICACHELINE_SIZE)
+1:	flushi	r4
+	add	r4, r4, r8
+	bltu	r4, r5, 1b
+	ret
+
+	.global flush_cache
+
+flush_cache:
+	add	r5, r5, r4
+	mov	r9, r4
+	mov	r10, r5
+
+	movhi	r8, %hi(CONFIG_SYS_DCACHELINE_SIZE)
+	ori	r8, r8, %lo(CONFIG_SYS_DCACHELINE_SIZE)
+0:	flushd	0(r4)
+	add	r4, r4, r8
+	bltu	r4, r5, 0b
+
+	mov	r4, r9
+	mov	r5, r10
+	movhi	r8, %hi(CONFIG_SYS_ICACHELINE_SIZE)
+	ori	r8, r8, %lo(CONFIG_SYS_ICACHELINE_SIZE)
+1:	flushi	r4
+	add	r4, r4, r8
+	bltu	r4, r5, 1b
+
+	sync
+	flushp
+	ret
diff --git a/arch/nios2/lib/divmod.c b/arch/nios2/lib/divmod.c
new file mode 100644
index 0000000..3c7e71e
--- /dev/null
+++ b/arch/nios2/lib/divmod.c
@@ -0,0 +1,101 @@
+/*
+ * This file is part of GNU CC.
+ *
+ * GNU CC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU CC 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 GNU CC; see the file COPYING.  If not, write
+ * to the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include "math.h"
+
+USItype udivmodsi4 (USItype num, USItype den, word_type modwanted)
+{
+	USItype bit = 1;
+	USItype res = 0;
+
+	while (den < num && bit && !(den & (1L << 31))) {
+		den <<= 1;
+		bit <<= 1;
+	}
+	while (bit) {
+		if (num >= den) {
+			num -= den;
+			res |= bit;
+		}
+		bit >>= 1;
+		den >>= 1;
+	}
+	if (modwanted)
+		return num;
+	return res;
+}
+
+
+SItype __divsi3 (SItype a, SItype b)
+{
+	word_type neg = 0;
+	SItype res;
+
+	if (a < 0) {
+		a = -a;
+		neg = !neg;
+	}
+
+	if (b < 0) {
+		b = -b;
+		neg = !neg;
+	}
+
+	res = udivmodsi4 (a, b, 0);
+
+	if (neg)
+		res = -res;
+
+	return res;
+}
+
+
+SItype __modsi3 (SItype a, SItype b)
+{
+	word_type neg = 0;
+	SItype res;
+
+	if (a < 0) {
+		a = -a;
+		neg = 1;
+	}
+
+	if (b < 0)
+		b = -b;
+
+	res = udivmodsi4 (a, b, 1);
+
+	if (neg)
+		res = -res;
+
+	return res;
+}
+
+
+SItype __udivsi3 (SItype a, SItype b)
+{
+	return udivmodsi4 (a, b, 0);
+}
+
+
+SItype __umodsi3 (SItype a, SItype b)
+{
+	return udivmodsi4 (a, b, 1);
+}
diff --git a/arch/nios2/lib/math.h b/arch/nios2/lib/math.h
new file mode 100644
index 0000000..f0aed8e
--- /dev/null
+++ b/arch/nios2/lib/math.h
@@ -0,0 +1,16 @@
+#define BITS_PER_UNIT	8
+
+typedef	 int HItype			__attribute__ ((mode (HI)));
+typedef unsigned int UHItype		__attribute__ ((mode (HI)));
+
+typedef		 int SItype		__attribute__ ((mode (SI)));
+typedef unsigned int USItype		__attribute__ ((mode (SI)));
+
+typedef int word_type			__attribute__ ((mode (__word__)));
+
+struct SIstruct {HItype low, high;};
+
+typedef union {
+	struct SIstruct s;
+	SItype ll;
+} SIunion;
diff --git a/arch/nios2/lib/mult.c b/arch/nios2/lib/mult.c
new file mode 100644
index 0000000..ec8139e
--- /dev/null
+++ b/arch/nios2/lib/mult.c
@@ -0,0 +1,56 @@
+/*
+ * This file is part of GNU CC.
+ *
+ * GNU CC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU CC 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 GNU CC; see the file COPYING.  If not, write
+ * to the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include <common.h>
+
+#if !defined(CONFIG_SYS_NIOS_MULT_HW) && !defined(CONFIG_SYS_NIOS_MULT_MSTEP)
+
+#include "math.h"
+
+USItype __mulsi3 (USItype a, USItype b)
+{
+	USItype c = 0;
+
+	while (a != 0) {
+		if (a & 1)
+			c += b;
+		a >>= 1;
+		b <<= 1;
+	}
+
+	return c;
+}
+
+
+UHItype __mulhi3 (UHItype a, UHItype b)
+{
+	UHItype c = 0;
+
+	while (a != 0) {
+		if (a & 1)
+			c += b;
+		a >>= 1;
+		b <<= 1;
+	}
+
+	return c;
+}
+
+#endif /*!defined(CONFIG_SYS_NIOS_MULT_HW) && !defined(CONFIG_SYS_NIOS_MULT_MSTEP) */
diff --git a/arch/nios2/lib/time.c b/arch/nios2/lib/time.c
new file mode 100644
index 0000000..d5096ee
--- /dev/null
+++ b/arch/nios2/lib/time.c
@@ -0,0 +1,38 @@
+/*
+ * (C) Copyright 2003, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.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>
+
+
+extern void dly_clks( unsigned long ticks );
+
+void __udelay(unsigned long usec)
+{
+	/* The Nios core doesn't have a timebase, so we do our
+	 * best for now and call a low-level loop that counts
+	 * cpu clocks.
+	 */
+	unsigned long cnt = (CONFIG_SYS_CLK_FREQ/1000000) * usec;
+	dly_clks (cnt);
+}
diff --git a/arch/ppc/config.mk b/arch/ppc/config.mk
new file mode 100644
index 0000000..06a3b10
--- /dev/null
+++ b/arch/ppc/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/ppc/lib/Makefile b/arch/ppc/lib/Makefile
new file mode 100644
index 0000000..334e457
--- /dev/null
+++ b/arch/ppc/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/ppc/lib/bat_rw.c b/arch/ppc/lib/bat_rw.c
new file mode 100644
index 0000000..c48c240
--- /dev/null
+++ b/arch/ppc/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/ppc/lib/board.c b/arch/ppc/lib/board.c
new file mode 100644
index 0000000..a30acee
--- /dev/null
+++ b/arch/ppc/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/ppc/lib/bootm.c b/arch/ppc/lib/bootm.c
new file mode 100644
index 0000000..0685a93
--- /dev/null
+++ b/arch/ppc/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/ppc/lib/cache.c b/arch/ppc/lib/cache.c
new file mode 100644
index 0000000..338b08b
--- /dev/null
+++ b/arch/ppc/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/ppc/lib/extable.c b/arch/ppc/lib/extable.c
new file mode 100644
index 0000000..7408d5c
--- /dev/null
+++ b/arch/ppc/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/ppc/lib/interrupts.c b/arch/ppc/lib/interrupts.c
new file mode 100644
index 0000000..f603170
--- /dev/null
+++ b/arch/ppc/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/ppc/lib/kgdb.c b/arch/ppc/lib/kgdb.c
new file mode 100644
index 0000000..d3eb1f3
--- /dev/null
+++ b/arch/ppc/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/ppc/lib/ppccache.S b/arch/ppc/lib/ppccache.S
new file mode 100644
index 0000000..278a804
--- /dev/null
+++ b/arch/ppc/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/ppc/lib/ppcstring.S b/arch/ppc/lib/ppcstring.S
new file mode 100644
index 0000000..97023a0
--- /dev/null
+++ b/arch/ppc/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/ppc/lib/reloc.S b/arch/ppc/lib/reloc.S
new file mode 100644
index 0000000..50f9a83
--- /dev/null
+++ b/arch/ppc/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/ppc/lib/ticks.S b/arch/ppc/lib/ticks.S
new file mode 100644
index 0000000..b8d25b7
--- /dev/null
+++ b/arch/ppc/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/ppc/lib/time.c b/arch/ppc/lib/time.c
new file mode 100644
index 0000000..2909961
--- /dev/null
+++ b/arch/ppc/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);
+}
+/* ------------------------------------------------------------------------- */
diff --git a/arch/sh/config.mk b/arch/sh/config.mk
new file mode 100644
index 0000000..797bf4c
--- /dev/null
+++ b/arch/sh/config.mk
@@ -0,0 +1,34 @@
+#
+# (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 ?= sh4-linux-
+
+STANDALONE_LOAD_ADDR = 0x8C000000
+ifeq ($(CPU),sh2)
+STANDALONE_LOAD_ADDR += -EB
+endif
+
+PLATFORM_CPPFLAGS += -DCONFIG_SH -D__SH__
+PLATFORM_LDFLAGS += -e $(TEXT_BASE) --defsym reloc_dst=$(TEXT_BASE)
+
+LDSCRIPT := $(SRCTREE)/$(CPUDIR)/u-boot.lds
diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile
new file mode 100644
index 0000000..f7c6479
--- /dev/null
+++ b/arch/sh/lib/Makefile
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2007
+# Nobuhiro Iwamatsu <iwamatsu@nigauri.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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(ARCH).a
+
+SOBJS-y	+=
+
+COBJS-y	+= board.o
+COBJS-y	+= bootm.o
+ifeq ($(CONFIG_SH2),y)
+COBJS-y	+= time_sh2.o
+else
+COBJS-y	+= time.o
+endif
+
+SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/sh/lib/board.c b/arch/sh/lib/board.c
new file mode 100644
index 0000000..c97e20c
--- /dev/null
+++ b/arch/sh/lib/board.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2007,2008
+ * Nobuhiro Iwamatsu <iwamatsu@nigauri.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
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <stdio_dev.h>
+#include <timestamp.h>
+#include <version.h>
+#include <watchdog.h>
+#include <net.h>
+#include <environment.h>
+
+#ifdef CONFIG_BITBANGMII
+#include <miiphy.h>
+#endif
+
+extern int cpu_init(void);
+extern int board_init(void);
+extern int dram_init(void);
+extern int timer_init(void);
+
+const char version_string[] = U_BOOT_VERSION" ("U_BOOT_DATE" - "U_BOOT_TIME")";
+
+unsigned long monitor_flash_len = CONFIG_SYS_MONITOR_LEN;
+
+static int sh_flash_init(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	gd->bd->bi_flashsize = flash_init();
+	printf("FLASH: %ldMB\n", gd->bd->bi_flashsize / (1024*1024));
+
+	return 0;
+}
+
+#if defined(CONFIG_CMD_NAND)
+# include <nand.h>
+# define INIT_FUNC_NAND_INIT nand_init,
+#else
+# define INIT_FUNC_NAND_INIT
+#endif /* CONFIG_CMD_NAND */
+
+#if defined(CONFIG_WATCHDOG)
+extern int watchdog_init(void);
+extern int watchdog_disable(void);
+# define INIT_FUNC_WATCHDOG_INIT	watchdog_init,
+# define WATCHDOG_DISABLE       	watchdog_disable
+#else
+# define INIT_FUNC_WATCHDOG_INIT
+# define WATCHDOG_DISABLE
+#endif /* CONFIG_WATCHDOG */
+
+#if defined(CONFIG_CMD_IDE)
+# include <ide.h>
+# define INIT_FUNC_IDE_INIT	ide_init,
+#else
+# define INIT_FUNC_IDE_INIT
+#endif /* CONFIG_CMD_IDE */
+
+#if defined(CONFIG_PCI)
+#include <pci.h>
+static int sh_pci_init(void)
+{
+	pci_init();
+	return 0;
+}
+# define INIT_FUNC_PCI_INIT sh_pci_init,
+#else
+# define INIT_FUNC_PCI_INIT
+#endif /* CONFIG_PCI */
+
+static int sh_mem_env_init(void)
+{
+	mem_malloc_init(TEXT_BASE - CONFIG_SYS_GBL_DATA_SIZE -
+			CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN - 16);
+	env_relocate();
+	jumptable_init();
+	return 0;
+}
+
+#if defined(CONFIG_CMD_NET)
+static int sh_net_init(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	gd->bd->bi_ip_addr = getenv_IPaddr("ipaddr");
+	return 0;
+}
+#endif
+
+typedef int (init_fnc_t) (void);
+
+init_fnc_t *init_sequence[] =
+{
+	cpu_init,		/* basic cpu dependent setup */
+	board_init,		/* basic board dependent setup */
+	interrupt_init,	/* set up exceptions */
+	env_init,		/* event init */
+	serial_init,	/* SCIF init */
+	INIT_FUNC_WATCHDOG_INIT	/* watchdog init */
+	console_init_f,
+	display_options,
+	checkcpu,
+	checkboard,		/* Check support board */
+	dram_init,		/* SDRAM init */
+	timer_init,		/* SuperH Timer (TCNT0 only) init */
+	sh_mem_env_init,
+	sh_flash_init,	/* Flash memory(NOR) init*/
+	INIT_FUNC_NAND_INIT/* Flash memory (NAND) init */
+	INIT_FUNC_PCI_INIT	/* PCI init */
+	stdio_init,
+	console_init_r,
+	interrupt_init,
+#ifdef BOARD_LATE_INIT
+	board_late_init,
+#endif
+#if defined(CONFIG_CMD_NET)
+	sh_net_init,		/* SH specific eth init */
+#endif
+	NULL			/* Terminate this list */
+};
+
+void sh_generic_init(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	bd_t *bd;
+	init_fnc_t **init_fnc_ptr;
+
+	memset(gd, 0, CONFIG_SYS_GBL_DATA_SIZE);
+
+	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
+
+	gd->bd = (bd_t *)(gd + 1);	/* At end of global data */
+	gd->baudrate = CONFIG_BAUDRATE;
+
+	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
+
+	bd = gd->bd;
+	bd->bi_memstart	= CONFIG_SYS_SDRAM_BASE;
+	bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE;
+	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
+#if defined(CONFIG_SYS_SRAM_BASE) && defined(CONFIG_SYS_SRAM_SIZE)
+	bd->bi_sramstart = CONFIG_SYS_SRAM_BASE;
+	bd->bi_sramsize	= CONFIG_SYS_SRAM_SIZE;
+#endif
+	bd->bi_baudrate	= CONFIG_BAUDRATE;
+
+	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
+		WATCHDOG_RESET();
+		if ((*init_fnc_ptr) () != 0)
+			hang();
+	}
+
+#ifdef CONFIG_WATCHDOG
+	/* disable watchdog if environment is set */
+	{
+		char *s = getenv("watchdog");
+		if (s != NULL)
+			if (strncmp(s, "off", 3) == 0)
+				WATCHDOG_DISABLE();
+	}
+#endif /* CONFIG_WATCHDOG*/
+
+
+#ifdef CONFIG_BITBANGMII
+	bb_miiphy_init();
+#endif
+#if defined(CONFIG_CMD_NET)
+	{
+		char *s;
+		puts("Net:   ");
+		eth_initialize(gd->bd);
+
+		s = getenv("bootfile");
+		if (s != NULL)
+			copy_filename(BootFile, s, sizeof(BootFile));
+	}
+#endif /* CONFIG_CMD_NET */
+
+	while (1) {
+		WATCHDOG_RESET();
+		main_loop();
+	}
+}
+
+/***********************************************************************/
+
+void hang(void)
+{
+	puts("Board ERROR\n");
+	for (;;)
+		;
+}
diff --git a/arch/sh/lib/bootm.c b/arch/sh/lib/bootm.c
new file mode 100644
index 0000000..ae1f869
--- /dev/null
+++ b/arch/sh/lib/bootm.c
@@ -0,0 +1,70 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (c) Copyright 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
+ * (c) Copyright 2008 Renesas Solutions Corp.
+ *
+ * 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/byteorder.h>
+
+#ifdef CONFIG_SYS_DEBUG
+static void hexdump(unsigned char *buf, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++) {
+		if ((i % 16) == 0)
+			printf("%s%08x: ", i ? "\n" : "",
+							(unsigned int)&buf[i]);
+		printf("%02x ", buf[i]);
+	}
+	printf("\n");
+}
+#endif
+
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	/* Linux kernel load address */
+	void (*kernel) (void) = (void (*)(void))images->ep;
+	/* empty_zero_page */
+	unsigned char *param
+		= (unsigned char *)image_get_load(images->legacy_hdr_os);
+	/* Linux kernel command line */
+	char *cmdline = (char *)param + 0x100;
+	/* PAGE_SIZE */
+	unsigned long size = images->ep - (unsigned long)param;
+	char *bootargs = getenv("bootargs");
+
+	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+		return 1;
+
+	/* Setup parameters */
+	memset(param, 0, size);	/* Clear zero page */
+	strcpy(cmdline, bootargs);
+
+	kernel();
+	/* does not return */
+
+	return 1;
+}
diff --git a/arch/sh/lib/time.c b/arch/sh/lib/time.c
new file mode 100644
index 0000000..9a8f89a
--- /dev/null
+++ b/arch/sh/lib/time.c
@@ -0,0 +1,141 @@
+/*
+ * (C) Copyright 2009
+ * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * (C) Copyright 2007-2008
+ * Nobobuhiro Iwamatsu <iwamatsu@nigauri.org>
+ *
+ * (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>
+#include <div64.h>
+#include <asm/processor.h>
+#include <asm/clk.h>
+#include <asm/io.h>
+
+#define TMU_MAX_COUNTER (~0UL)
+
+static ulong timer_freq;
+
+static inline unsigned long long tick_to_time(unsigned long long tick)
+{
+	tick *= CONFIG_SYS_HZ;
+	do_div(tick, timer_freq);
+
+	return tick;
+}
+
+static inline unsigned long long usec_to_tick(unsigned long long usec)
+{
+	usec *= timer_freq;
+	do_div(usec, 1000000);
+
+	return usec;
+}
+
+static void tmu_timer_start (unsigned int timer)
+{
+	if (timer > 2)
+		return;
+	writeb(readb(TSTR) | (1 << timer), TSTR);
+}
+
+static void tmu_timer_stop (unsigned int timer)
+{
+	if (timer > 2)
+		return;
+	writeb(readb(TSTR) & ~(1 << timer), TSTR);
+}
+
+int timer_init (void)
+{
+	/* Divide clock by CONFIG_SYS_TMU_CLK_DIV */
+	u16 bit = 0;
+
+	switch (CONFIG_SYS_TMU_CLK_DIV) {
+	case 1024:
+		bit = 4;
+		break;
+	case 256:
+		bit = 3;
+		break;
+	case 64:
+		bit = 2;
+		break;
+	case 16:
+		bit = 1;
+		break;
+	case 4:
+	default:
+		break;
+	}
+	writew(readw(TCR0) | bit, TCR0);
+
+	/* Calc clock rate */
+	timer_freq = get_tmu0_clk_rate() >> ((bit + 1) * 2);
+
+	tmu_timer_stop(0);
+	tmu_timer_start(0);
+
+	return 0;
+}
+
+unsigned long long get_ticks (void)
+{
+	return 0 - readl(TCNT0);
+}
+
+void __udelay (unsigned long usec)
+{
+	unsigned long long tmp;
+	ulong tmo;
+
+	tmo = usec_to_tick(usec);
+	tmp = get_ticks() + tmo;	/* get current timestamp */
+
+	while (get_ticks() < tmp)	/* loop till event */
+		 /*NOP*/;
+}
+
+unsigned long get_timer (unsigned long base)
+{
+	/* return msec */
+	return tick_to_time(get_ticks()) - base;
+}
+
+void set_timer (unsigned long t)
+{
+	writel((0 - t), TCNT0);
+}
+
+void reset_timer (void)
+{
+	tmu_timer_stop(0);
+	set_timer (0);
+	tmu_timer_start(0);
+}
+
+unsigned long get_tbclk (void)
+{
+	return timer_freq;
+}
diff --git a/arch/sh/lib/time_sh2.c b/arch/sh/lib/time_sh2.c
new file mode 100644
index 0000000..789b46f
--- /dev/null
+++ b/arch/sh/lib/time_sh2.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2007,2008 Nobobuhiro Iwamatsu <iwamatsu@nigauri.org>
+ * Copyright (C) 2008 Renesas Solutions Corp.
+ *
+ * (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>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+#define CMT_CMCSR_INIT	0x0001	/* PCLK/32 */
+#define CMT_CMCSR_CALIB 0x0000
+#define CMT_MAX_COUNTER (0xFFFFFFFF)
+#define CMT_TIMER_RESET (0xFFFF)
+
+static vu_long cmt0_timer;
+
+static void cmt_timer_start(unsigned int timer)
+{
+	writew(readw(CMSTR) | 0x01, CMSTR);
+}
+
+static void cmt_timer_stop(unsigned int timer)
+{
+	writew(readw(CMSTR) & ~0x01, CMSTR);
+}
+
+int timer_init(void)
+{
+	cmt0_timer = 0;
+	/* Divide clock by 32 */
+	readw(CMCSR_0);
+	writew(CMT_CMCSR_INIT, CMCSR_0);
+
+	/* User Device 0 only */
+	cmt_timer_stop(0);
+	set_timer(CMT_TIMER_RESET);
+	cmt_timer_start(0);
+
+	return 0;
+}
+
+unsigned long long get_ticks(void)
+{
+	return cmt0_timer;
+}
+
+static vu_long cmcnt = 0;
+static unsigned long get_usec (void)
+{
+	ulong data = readw(CMCNT_0);
+
+	if (data >= cmcnt)
+		cmcnt = data - cmcnt;
+	else
+		cmcnt = (CMT_TIMER_RESET - cmcnt) + data;
+
+	if ((cmt0_timer + cmcnt) > CMT_MAX_COUNTER)
+		cmt0_timer = ((cmt0_timer + cmcnt) - CMT_MAX_COUNTER);
+	else
+		cmt0_timer += cmcnt;
+
+	cmcnt = data;
+	return cmt0_timer;
+}
+
+/* return msec */
+ulong get_timer(ulong base)
+{
+	return (get_usec() / 1000) - base;
+}
+
+void set_timer(ulong t)
+{
+	writew((u16) t, CMCOR_0);
+}
+
+void reset_timer(void)
+{
+	cmt_timer_stop(0);
+	set_timer(CMT_TIMER_RESET);
+	cmt0_timer = 0;
+	cmt_timer_start(0);
+}
+
+void __udelay(unsigned long usec)
+{
+	unsigned long end = get_usec() + usec;
+
+	while (get_usec() < end)
+		continue;
+}
+
+unsigned long get_tbclk(void)
+{
+	return CONFIG_SYS_HZ;
+}
diff --git a/arch/sparc/config.mk b/arch/sparc/config.mk
new file mode 100644
index 0000000..4de6515
--- /dev/null
+++ b/arch/sparc/config.mk
@@ -0,0 +1,28 @@
+#
+# (C) Copyright 2007
+# Daniel Hellstrom, Gaisler Research, daniel@gaisler.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
+#
+
+CROSS_COMPILE ?= sparc-elf-
+
+STANDALONE_LOAD_ADDR = 0x00000000 -L $(gcclibdir) -T sparc.lds
+
+PLATFORM_CPPFLAGS += -DCONFIG_SPARC -D__sparc__
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
new file mode 100644
index 0000000..040ca10
--- /dev/null
+++ b/arch/sparc/lib/Makefile
@@ -0,0 +1,45 @@
+#
+# (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	=
+
+COBJS	= board.o cache.o interrupts.o time.o bootm.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/sparc/lib/board.c b/arch/sparc/lib/board.c
new file mode 100644
index 0000000..11eea60
--- /dev/null
+++ b/arch/sparc/lib/board.c
@@ -0,0 +1,472 @@
+/* SPARC Board initialization
+ *
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2007
+ * Daniel Hellstrom, Gaisler Research, daniel@gaisler.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 <command.h>
+#include <malloc.h>
+#include <stdio_dev.h>
+#include <config.h>
+#if defined(CONFIG_CMD_IDE)
+#include <ide.h>
+#endif
+#ifdef CONFIG_STATUS_LED
+#include <status_led.h>
+#endif
+#include <net.h>
+#include <serial.h>
+#include <version.h>
+#if defined(CONFIG_POST)
+#include <post.h>
+#endif
+#ifdef CONFIG_PS2KBD
+#include <keyboard.h>
+#endif
+#ifdef CONFIG_CMD_AMBAPP
+#include <ambapp.h>
+#endif
+
+#ifdef CONFIG_BITBANGMII
+#include <miiphy.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Debug options
+#define DEBUG_INIT_SEQUENCE
+#define DEBUG_MEM_LAYOUT
+#define DEBUG_COMMANDS
+*/
+
+extern void timer_interrupt_init(void);
+extern void malloc_bin_reloc(void);
+extern int do_ambapp_print(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]);
+extern int prom_init(void);
+
+#if defined(CONFIG__CMD_DOC)
+void doc_init(void);
+#endif
+
+#if !defined(CONFIG_SYS_NO_FLASH)
+static char *failed = "*** failed ***\n";
+#endif
+
+#include <environment.h>
+
+ulong monitor_flash_len;
+
+/************************************************************************
+ * 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);
+}
+
+/***********************************************************************/
+
+/*
+ * 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);
+
+#define WATCHDOG_RESET(x)
+
+/************************************************************************
+ * Initialization sequence						*
+ ************************************************************************
+ */
+
+init_fnc_t *init_sequence[] = {
+
+#if defined(CONFIG_BOARD_EARLY_INIT_F)
+	board_early_init_f,
+#endif
+	serial_init,
+
+	init_timebase,
+
+#if defined(CONFIG_CMD_AMBAPP)
+	ambapp_init_reloc,
+#endif
+
+	env_init,
+
+	init_baudrate,
+
+	console_init_f,
+	display_options,
+
+	checkcpu,
+	checkboard,
+#if defined(CONFIG_MISC_INIT_F)
+	misc_init_f,
+#endif
+
+#ifdef CONFIG_POST
+	post_init_f,
+#endif
+
+	NULL,			/* Terminate this list,
+				 * beware: this list will be relocated
+				 * which means that NULL will become
+				 * NULL+RELOC_OFFSET. We simply make
+				 * NULL be -RELOC_OFFSET instead.
+				 */
+};
+
+/************************************************************************
+ *
+ * This is the SPARC board initialization routine, running from RAM.
+ *
+ ************************************************************************
+ */
+#ifdef DEBUG_INIT_SEQUENCE
+char *str_init_seq = "INIT_SEQ 00\n";
+char *str_init_seq_done = "\n\rInit sequence done...\r\n\r\n";
+#endif
+
+void board_init_f(ulong bootflag)
+{
+	cmd_tbl_t *cmdtp;
+	bd_t *bd;
+	unsigned char *s;
+	init_fnc_t **init_fnc_ptr;
+	int j;
+	int i;
+	char *e;
+
+#ifndef CONFIG_SYS_NO_FLASH
+	ulong flash_size;
+#endif
+
+	gd = (gd_t *) (CONFIG_SYS_GBL_DATA_OFFSET);
+
+	/* Clear initial global data */
+	memset((void *)gd, 0, sizeof(gd_t));
+
+	gd->bd = (bd_t *) (gd + 1);	/* At end of global data */
+	gd->baudrate = CONFIG_BAUDRATE;
+	gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
+
+	bd = gd->bd;
+	bd->bi_memstart = CONFIG_SYS_RAM_BASE;
+	bd->bi_memsize = CONFIG_SYS_RAM_SIZE;
+	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
+#if	defined(CONFIG_SYS_SRAM_BASE) && defined(CONFIG_SYS_SRAM_SIZE)
+	bd->bi_sramstart = CONFIG_SYS_SRAM_BASE;
+	bd->bi_sramsize = CONFIG_SYS_SRAM_SIZE;
+#endif
+	bd->bi_baudrate = CONFIG_BAUDRATE;
+	bd->bi_bootflags = bootflag;	/* boot / reboot flag (for LynxOS)    */
+
+	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
+	gd->reloc_off = CONFIG_SYS_RELOC_MONITOR_BASE - CONFIG_SYS_MONITOR_BASE;
+
+	for (init_fnc_ptr = init_sequence, j = 0; *init_fnc_ptr;
+	     ++init_fnc_ptr, j++) {
+#ifdef DEBUG_INIT_SEQUENCE
+		if (j > 9)
+			str_init_seq[9] = '0' + (j / 10);
+		str_init_seq[10] = '0' + (j - (j / 10) * 10);
+		serial_puts(str_init_seq);
+#endif
+		if ((*init_fnc_ptr + gd->reloc_off) () != 0) {
+			hang();
+		}
+	}
+#ifdef DEBUG_INIT_SEQUENCE
+	serial_puts(str_init_seq_done);
+#endif
+
+	/*
+	 * 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):
+	 *  - kernel log buffer
+	 *  - protected RAM
+	 *  - LCD framebuffer
+	 *  - monitor code
+	 *  - board info struct
+	 */
+#ifdef DEBUG_MEM_LAYOUT
+	printf("CONFIG_SYS_MONITOR_BASE:       0x%lx\n", CONFIG_SYS_MONITOR_BASE);
+	printf("CONFIG_ENV_ADDR:           0x%lx\n", CONFIG_ENV_ADDR);
+	printf("CONFIG_SYS_RELOC_MONITOR_BASE: 0x%lx (%d)\n", CONFIG_SYS_RELOC_MONITOR_BASE,
+	       CONFIG_SYS_MONITOR_LEN);
+	printf("CONFIG_SYS_MALLOC_BASE:        0x%lx (%d)\n", CONFIG_SYS_MALLOC_BASE,
+	       CONFIG_SYS_MALLOC_LEN);
+	printf("CONFIG_SYS_INIT_SP_OFFSET:     0x%lx (%d)\n", CONFIG_SYS_INIT_SP_OFFSET,
+	       CONFIG_SYS_STACK_SIZE);
+	printf("CONFIG_SYS_PROM_OFFSET:        0x%lx (%d)\n", CONFIG_SYS_PROM_OFFSET,
+	       CONFIG_SYS_PROM_SIZE);
+	printf("CONFIG_SYS_GBL_DATA_OFFSET:    0x%lx (%d)\n", CONFIG_SYS_GBL_DATA_OFFSET,
+	       CONFIG_SYS_GBL_DATA_SIZE);
+#endif
+
+#ifdef CONFIG_POST
+	post_bootmode_init();
+	post_run(NULL, POST_ROM | post_bootmode_get(0));
+#endif
+
+	/*
+	 * We have to relocate the command table manually
+	 */
+	for (cmdtp = &__u_boot_cmd_start; cmdtp != &__u_boot_cmd_end; cmdtp++) {
+		ulong addr;
+		addr = (ulong) (cmdtp->cmd) + gd->reloc_off;
+#if DEBUG_COMMANDS
+		printf("Command \"%s\": 0x%08lx => 0x%08lx\n",
+		       cmdtp->name, (ulong) (cmdtp->cmd), addr);
+#endif
+		cmdtp->cmd =
+		    (int (*)(struct cmd_tbl_s *, int, int, char *[]))addr;
+
+		addr = (ulong) (cmdtp->name) + gd->reloc_off;
+		cmdtp->name = (char *)addr;
+
+		if (cmdtp->usage) {
+			addr = (ulong) (cmdtp->usage) + gd->reloc_off;
+			cmdtp->usage = (char *)addr;
+		}
+#ifdef	CONFIG_SYS_LONGHELP
+		if (cmdtp->help) {
+			addr = (ulong) (cmdtp->help) + gd->reloc_off;
+			cmdtp->help = (char *)addr;
+		}
+#endif
+	}
+
+#if defined(CONFIG_CMD_AMBAPP) && defined(CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP)
+	puts("AMBA:\n");
+	do_ambapp_print(NULL, 0, 0, NULL);
+#endif
+
+	/* initialize higher level parts of CPU like time base and timers */
+	cpu_init_r();
+
+	/* start timer */
+	timer_interrupt_init();
+
+	/*
+	 * Enable Interrupts before any calls to udelay,
+	 * the flash driver may use udelay resulting in
+	 * a hang if not timer0 IRQ is enabled.
+	 */
+	interrupt_init();
+
+	/* The Malloc area is immediately below the monitor copy in RAM */
+	mem_malloc_init(CONFIG_SYS_MALLOC_BASE,
+			CONFIG_SYS_MALLOC_END - CONFIG_SYS_MALLOC_BASE);
+	malloc_bin_reloc();
+
+#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: %08lX",
+			       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 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 */
+
+#ifdef CONFIG_SPI
+# if !defined(CONFIG_ENV_IS_IN_EEPROM)
+	spi_init_f();
+# endif
+	spi_init_r();
+#endif
+
+	/* relocate environment function pointers etc. */
+	env_relocate();
+
+#if defined(CONFIG_BOARD_LATE_INIT)
+	board_late_init();
+#endif
+
+#ifdef CONFIG_ID_EEPROM
+	mac_read_from_eeprom();
+#endif
+
+	/* IP Address */
+	bd->bi_ip_addr = getenv_IPaddr("ipaddr");
+#if defined(CONFIG_PCI)
+	/*
+	 * Do pci configuration
+	 */
+	pci_init();
+#endif
+
+	/* Initialize stdio devices */
+	stdio_init();
+
+	/* Initialize the jump table for applications */
+	jumptable_init();
+
+	/* Initialize the console (after the relocation and devices init) */
+	console_init_r();
+
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
+	serial_buffered_init();
+#endif
+
+#ifdef CONFIG_STATUS_LED
+	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 /* CONFIG_CMD_NET */
+
+	WATCHDOG_RESET();
+
+#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_IDE)
+	WATCHDOG_RESET();
+	puts("IDE:   ");
+	ide_init();
+#endif /* CONFIG_CMD_IDE */
+
+#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
+
+#ifdef CONFIG_PS2KBD
+	puts("PS/2:  ");
+	kbd_init();
+#endif
+	prom_init();
+
+	/* main_loop */
+	for (;;) {
+		WATCHDOG_RESET();
+		main_loop();
+	}
+
+}
+
+void hang(void)
+{
+	puts("### ERROR ### Please RESET the board ###\n");
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+	show_boot_progress(-30);
+#endif
+	for (;;) ;
+}
+
+/************************************************************************/
diff --git a/arch/sparc/lib/bootm.c b/arch/sparc/lib/bootm.c
new file mode 100644
index 0000000..c62cf57
--- /dev/null
+++ b/arch/sparc/lib/bootm.c
@@ -0,0 +1,189 @@
+/* SPARC code for booting linux 2.6
+ *
+ * (C) Copyright 2007
+ * Daniel Hellstrom, Gaisler Research, daniel@gaisler.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 <command.h>
+#include <asm/byteorder.h>
+#include <asm/prom.h>
+#include <asm/cache.h>
+#include <image.h>
+
+#define PRINT_KERNEL_HEADER
+
+extern image_header_t header;
+extern void srmmu_init_cpu(unsigned int entry);
+extern void prepare_bootargs(char *bootargs);
+
+#ifdef CONFIG_USB_UHCI
+extern int usb_lowlevel_stop(void);
+#endif
+
+/* sparc kernel argument (the ROM vector) */
+struct linux_romvec *kernel_arg_promvec;
+
+/* page szie is 4k */
+#define PAGE_SIZE 0x1000
+#define RAMDISK_IMAGE_START_MASK	0x07FF
+#define RAMDISK_PROMPT_FLAG		0x8000
+#define RAMDISK_LOAD_FLAG		0x4000
+struct __attribute__ ((packed)) {
+	char traptable[PAGE_SIZE];
+	char swapper_pg_dir[PAGE_SIZE];
+	char pg0[PAGE_SIZE];
+	char pg1[PAGE_SIZE];
+	char pg2[PAGE_SIZE];
+	char pg3[PAGE_SIZE];
+	char empty_bad_page[PAGE_SIZE];
+	char empty_bad_page_table[PAGE_SIZE];
+	char empty_zero_page[PAGE_SIZE];
+	unsigned char hdr[4];	/* ascii "HdrS" */
+	/* 00.02.06.0b is for Linux kernel 2.6.11 */
+	unsigned char linuxver_mega_major;
+	unsigned char linuxver_major;
+	unsigned char linuxver_minor;
+	unsigned char linuxver_revision;
+	/* header version 0x0203 */
+	unsigned short hdr_ver;
+	union __attribute__ ((packed)) {
+		struct __attribute__ ((packed)) {
+			unsigned short root_flags;
+			unsigned short root_dev;
+			unsigned short ram_flags;
+			unsigned int sparc_ramdisk_image;
+			unsigned int sparc_ramdisk_size;
+			unsigned int reboot_command;
+			unsigned int resv[3];
+			unsigned int end;
+		} ver_0203;
+	} hdr_input;
+} *linux_hdr;
+
+/* temporary initrd image holder */
+image_header_t ihdr;
+
+void arch_lmb_reserve(struct lmb *lmb)
+{
+	/* Reserve the space used by PROM and stack. This is done
+	 * to avoid that the RAM image is copied over stack or
+	 * PROM.
+	 */
+	lmb_reserve(lmb, CONFIG_SYS_RELOC_MONITOR_BASE, CONFIG_SYS_RAM_END);
+}
+
+/* boot the linux kernel */
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t * images)
+{
+	char *bootargs;
+	ulong initrd_start, initrd_end;
+	ulong rd_len;
+	unsigned int data, len, checksum;
+	unsigned int initrd_addr, kernend;
+	void (*kernel) (struct linux_romvec *, void *);
+	struct lmb *lmb = &images->lmb;
+	int ret;
+
+	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+		return 1;
+
+	/* Get virtual address of kernel start */
+	linux_hdr = (void *)images->os.load;
+
+	/* */
+	kernel = (void (*)(struct linux_romvec *, void *))images->ep;
+
+	/* check for a SPARC kernel */
+	if ((linux_hdr->hdr[0] != 'H') ||
+	    (linux_hdr->hdr[1] != 'd') ||
+	    (linux_hdr->hdr[2] != 'r') || (linux_hdr->hdr[3] != 'S')) {
+		puts("Error reading header of SPARC Linux kernel, aborting\n");
+		goto error;
+	}
+#ifdef PRINT_KERNEL_HEADER
+	printf("## Found SPARC Linux kernel %d.%d.%d ...\n",
+	       linux_hdr->linuxver_major,
+	       linux_hdr->linuxver_minor, linux_hdr->linuxver_revision);
+#endif
+
+#ifdef CONFIG_USB_UHCI
+	usb_lowlevel_stop();
+#endif
+
+	/* set basic boot params in kernel header now that it has been
+	 * extracted and is writeable.
+	 */
+
+	/* Calc length of RAM disk, if zero no ramdisk available */
+	rd_len = images->rd_end - images->rd_start;
+
+	if (rd_len) {
+		ret = boot_ramdisk_high(lmb, images->rd_start, rd_len,
+					&initrd_start, &initrd_end);
+		if (ret) {
+			puts("### Failed to relocate RAM disk\n");
+			goto error;
+		}
+
+		/* Update SPARC kernel header so that Linux knows
+		 * what is going on and where to find RAM disk.
+		 *
+		 * Set INITRD Image address relative to RAM Start
+		 */
+		linux_hdr->hdr_input.ver_0203.sparc_ramdisk_image =
+		    initrd_start - CONFIG_SYS_RAM_BASE;
+		linux_hdr->hdr_input.ver_0203.sparc_ramdisk_size = rd_len;
+		/* Clear READ ONLY flag if set to non-zero */
+		linux_hdr->hdr_input.ver_0203.root_flags = 1;
+		/* Set root device to: Root_RAM0 */
+		linux_hdr->hdr_input.ver_0203.root_dev = 0x100;
+		linux_hdr->hdr_input.ver_0203.ram_flags = 0;
+	} else {
+		/* NOT using RAMDISK image, overwriting kernel defaults */
+		linux_hdr->hdr_input.ver_0203.sparc_ramdisk_image = 0;
+		linux_hdr->hdr_input.ver_0203.sparc_ramdisk_size = 0;
+		/* Leave to kernel defaults
+		   linux_hdr->hdr_input.ver_0203.root_flags = 1;
+		   linux_hdr->hdr_input.ver_0203.root_dev = 0;
+		   linux_hdr->hdr_input.ver_0203.ram_flags = 0;
+		 */
+	}
+
+	/* Copy bootargs from bootargs variable to kernel readable area */
+	bootargs = getenv("bootargs");
+	prepare_bootargs(bootargs);
+
+	/* turn on mmu & setup context table & page table for process 0 (kernel) */
+	srmmu_init_cpu((unsigned int)kernel);
+
+	/* Enter SPARC Linux kernel
+	 * From now on the only code in u-boot that will be
+	 * executed is the PROM code.
+	 */
+	kernel(kernel_arg_promvec, (void *)images->ep);
+
+	/* It will never come to this... */
+	while (1) ;
+
+      error:
+	return 1;
+}
diff --git a/arch/sparc/lib/cache.c b/arch/sparc/lib/cache.c
new file mode 100644
index 0000000..59d9bbe
--- /dev/null
+++ b/arch/sparc/lib/cache.c
@@ -0,0 +1,33 @@
+/* Sparc cache library
+ *
+ * (C) Copyright 2007
+ * Daniel Hellstrom, Gaisler Research, daniel@gaisler.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>
+
+void flush_cache(ulong start_addr, ulong size)
+{
+	/* Flush All Cache */
+	sparc_dcache_flush_all();
+	sparc_icache_flush_all();
+}
diff --git a/arch/sparc/lib/interrupts.c b/arch/sparc/lib/interrupts.c
new file mode 100644
index 0000000..4c73b82
--- /dev/null
+++ b/arch/sparc/lib/interrupts.c
@@ -0,0 +1,122 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2003
+ * Gleb Natapov <gnatapov@mrv.com>
+ *
+ * (C) Copyright 2007
+ * Daniel Hellstrom, Gaisler Research, daniel@gaisler.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/irq.h>
+
+/* Implemented by SPARC CPUs */
+extern int interrupt_init_cpu(void);
+extern void timer_interrupt_cpu(void *arg);
+extern int timer_interrupt_init_cpu(void);
+
+int intLock(void)
+{
+	unsigned int pil;
+
+	pil = get_pil();
+
+	/* set PIL to 15 ==> no pending interrupts will interrupt CPU */
+	set_pil(15);
+
+	return pil;
+}
+
+void intUnlock(int oldLevel)
+{
+	set_pil(oldLevel);
+}
+
+void enable_interrupts(void)
+{
+	set_pil(0);		/* enable all interrupts */
+}
+
+int disable_interrupts(void)
+{
+	return intLock();
+}
+
+int interrupt_init(void)
+{
+	int ret;
+
+	/* call cpu specific function from $(CPU)/interrupts.c */
+	ret = interrupt_init_cpu();
+
+	/* enable global interrupts */
+	enable_interrupts();
+
+	return ret;
+}
+
+/* timer interrupt/overflow counter */
+static volatile ulong timestamp = 0;
+
+/* regs can not be used here! regs is actually the pointer given in
+ * irq_install_handler
+ */
+void timer_interrupt(struct pt_regs *regs)
+{
+	/* call cpu specific function from $(CPU)/interrupts.c */
+	timer_interrupt_cpu((void *)regs);
+
+	timestamp++;
+}
+
+void reset_timer(void)
+{
+	timestamp = 0;
+}
+
+ulong get_timer(ulong base)
+{
+	return (timestamp - base);
+}
+
+void set_timer(ulong t)
+{
+	timestamp = t;
+}
+
+void timer_interrupt_init(void)
+{
+	int irq;
+
+	reset_timer();
+
+	irq = timer_interrupt_init_cpu();
+
+	if (irq < 0) {
+		/* cpu specific code handled the interrupt registration it self */
+		return;
+	}
+	/* register interrupt handler for timer */
+	irq_install_handler(irq, (void (*)(void *))timer_interrupt, NULL);
+}
diff --git a/arch/sparc/lib/time.c b/arch/sparc/lib/time.c
new file mode 100644
index 0000000..82b2a3a
--- /dev/null
+++ b/arch/sparc/lib/time.c
@@ -0,0 +1,78 @@
+/*
+ * (C) Copyright 2000, 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2007
+ * Daniel Hellstrom, Gaisler Research, daniel@gaisler.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>
+
+/* Implemented by SPARC CPUs */
+extern void cpu_wait_ticks(unsigned long ticks);
+extern unsigned long cpu_usec2ticks(unsigned long usec);
+extern unsigned long cpu_ticks2usec(unsigned long ticks);
+
+/* ------------------------------------------------------------------------- */
+
+void wait_ticks(unsigned long ticks)
+{
+	cpu_wait_ticks(ticks);
+}
+
+/*
+ * This function is intended for SHORT delays only.
+ */
+unsigned long usec2ticks(unsigned long usec)
+{
+	return cpu_usec2ticks(usec);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * 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);
+}
+
+/* ------------------------------------------------------------------------- */
+
+unsigned long ticks2usec(unsigned long ticks)
+{
+	return cpu_ticks2usec(ticks);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int init_timebase(void)
+{
+
+	return (0);
+}
+
+/* ------------------------------------------------------------------------- */