aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/config.mk66
-rw-r--r--arch/arm/lib/Makefile82
-rw-r--r--arch/arm/lib/_ashldi3.S48
-rw-r--r--arch/arm/lib/_ashrdi3.S48
-rw-r--r--arch/arm/lib/_divsi3.S142
-rw-r--r--arch/arm/lib/_lshrdi3.S48
-rw-r--r--arch/arm/lib/_modsi3.S99
-rw-r--r--arch/arm/lib/_udivsi3.S93
-rw-r--r--arch/arm/lib/_umodsi3.S88
-rw-r--r--arch/arm/lib/board.c452
-rw-r--r--arch/arm/lib/bootm.c279
-rw-r--r--arch/arm/lib/cache-cp15.c120
-rw-r--r--arch/arm/lib/cache.c36
-rw-r--r--arch/arm/lib/div0.c30
-rw-r--r--arch/arm/lib/eabi_compat.c18
-rw-r--r--arch/arm/lib/interrupts.c187
-rw-r--r--arch/arm/lib/reset.c53
-rw-r--r--arch/avr32/config.mk29
-rw-r--r--arch/avr32/lib/Makefile49
-rw-r--r--arch/avr32/lib/board.c360
-rw-r--r--arch/avr32/lib/bootm.c209
-rw-r--r--arch/avr32/lib/interrupts.c46
-rw-r--r--arch/avr32/lib/memset.S81
-rw-r--r--arch/blackfin/config.mk72
-rw-r--r--arch/blackfin/lib/.gitignore1
-rw-r--r--arch/blackfin/lib/Makefile65
-rw-r--r--arch/blackfin/lib/__kgdb.S155
-rw-r--r--arch/blackfin/lib/board.c419
-rw-r--r--arch/blackfin/lib/boot.c63
-rw-r--r--arch/blackfin/lib/cache.c113
-rw-r--r--arch/blackfin/lib/clocks.c77
-rw-r--r--arch/blackfin/lib/cmd_cache_dump.c145
-rw-r--r--arch/blackfin/lib/ins.S117
-rw-r--r--arch/blackfin/lib/kgdb.c423
-rw-r--r--arch/blackfin/lib/kgdb.h160
-rw-r--r--arch/blackfin/lib/memcmp.S103
-rw-r--r--arch/blackfin/lib/memcpy.S117
-rw-r--r--arch/blackfin/lib/memmove.S96
-rw-r--r--arch/blackfin/lib/memset.S96
-rw-r--r--arch/blackfin/lib/muldi3.c92
-rw-r--r--arch/blackfin/lib/outs.S60
-rw-r--r--arch/blackfin/lib/post.c421
-rw-r--r--arch/blackfin/lib/string.c274
-rw-r--r--arch/blackfin/lib/tests.c250
-rw-r--r--arch/blackfin/lib/u-boot.lds.S153
-rw-r--r--arch/i386/config.mk28
-rw-r--r--arch/i386/lib/Makefile59
-rw-r--r--arch/i386/lib/bios.S532
-rw-r--r--arch/i386/lib/bios.h94
-rw-r--r--arch/i386/lib/bios_pci.S413
-rw-r--r--arch/i386/lib/bios_setup.c242
-rw-r--r--arch/i386/lib/board.c429
-rw-r--r--arch/i386/lib/bootm.c94
-rw-r--r--arch/i386/lib/interrupts.c161
-rw-r--r--arch/i386/lib/pcat_interrupts.c132
-rw-r--r--arch/i386/lib/pcat_timer.c107
-rw-r--r--arch/i386/lib/pci.c152
-rw-r--r--arch/i386/lib/pci_type1.c51
-rw-r--r--arch/i386/lib/realmode.c100
-rw-r--r--arch/i386/lib/realmode_switch.S222
-rw-r--r--arch/i386/lib/timer.c107
-rw-r--r--arch/i386/lib/video.c237
-rw-r--r--arch/i386/lib/video_bios.c222
-rw-r--r--arch/i386/lib/zimage.c225
-rw-r--r--arch/m68k/config.mk30
-rw-r--r--arch/m68k/lib/Makefile50
-rw-r--r--arch/m68k/lib/board.c744
-rw-r--r--arch/m68k/lib/bootm.c146
-rw-r--r--arch/m68k/lib/cache.c150
-rw-r--r--arch/m68k/lib/interrupts.c115
-rw-r--r--arch/m68k/lib/time.c227
-rw-r--r--arch/m68k/lib/traps.c76
-rw-r--r--arch/microblaze/config.mk31
-rw-r--r--arch/microblaze/lib/Makefile48
-rw-r--r--arch/microblaze/lib/board.c162
-rw-r--r--arch/microblaze/lib/bootm.c57
-rw-r--r--arch/microblaze/lib/cache.c43
-rw-r--r--arch/microblaze/lib/time.c42
-rw-r--r--arch/mips/config.mk52
-rw-r--r--arch/mips/lib/Makefile51
-rw-r--r--arch/mips/lib/board.c436
-rw-r--r--arch/mips/lib/bootm.c174
-rw-r--r--arch/mips/lib/bootm_qemu_mips.c76
-rw-r--r--arch/mips/lib/time.c98
-rw-r--r--arch/nios/config.mk29
-rw-r--r--arch/nios/lib/Makefile50
-rw-r--r--arch/nios/lib/board.c168
-rw-r--r--arch/nios/lib/bootm.c34
-rw-r--r--arch/nios/lib/cache.c32
-rw-r--r--arch/nios/lib/divmod.c101
-rw-r--r--arch/nios/lib/math.h16
-rw-r--r--arch/nios/lib/mult.c56
-rw-r--r--arch/nios/lib/time.c38
-rw-r--r--arch/nios2/config.mk30
-rw-r--r--arch/nios2/lib/Makefile49
-rw-r--r--arch/nios2/lib/board.c164
-rw-r--r--arch/nios2/lib/bootm.c52
-rw-r--r--arch/nios2/lib/cache.S74
-rw-r--r--arch/nios2/lib/divmod.c101
-rw-r--r--arch/nios2/lib/math.h16
-rw-r--r--arch/nios2/lib/mult.c56
-rw-r--r--arch/nios2/lib/time.c38
-rw-r--r--arch/ppc/config.mk44
-rw-r--r--arch/ppc/lib/Makefile61
-rw-r--r--arch/ppc/lib/bat_rw.c260
-rw-r--r--arch/ppc/lib/board.c1084
-rw-r--r--arch/ppc/lib/bootm.c367
-rw-r--r--arch/ppc/lib/cache.c53
-rw-r--r--arch/ppc/lib/extable.c83
-rw-r--r--arch/ppc/lib/interrupts.c153
-rw-r--r--arch/ppc/lib/kgdb.c321
-rw-r--r--arch/ppc/lib/ppccache.S72
-rw-r--r--arch/ppc/lib/ppcstring.S216
-rw-r--r--arch/ppc/lib/reloc.S49
-rw-r--r--arch/ppc/lib/ticks.S65
-rw-r--r--arch/ppc/lib/time.c97
-rw-r--r--arch/sh/config.mk34
-rw-r--r--arch/sh/lib/Makefile48
-rw-r--r--arch/sh/lib/board.c211
-rw-r--r--arch/sh/lib/bootm.c70
-rw-r--r--arch/sh/lib/time.c141
-rw-r--r--arch/sh/lib/time_sh2.c117
-rw-r--r--arch/sparc/config.mk28
-rw-r--r--arch/sparc/lib/Makefile45
-rw-r--r--arch/sparc/lib/board.c472
-rw-r--r--arch/sparc/lib/bootm.c189
-rw-r--r--arch/sparc/lib/cache.c33
-rw-r--r--arch/sparc/lib/interrupts.c122
-rw-r--r--arch/sparc/lib/time.c78
129 files changed, 18167 insertions, 0 deletions
diff --git a/arch/arm/config.mk b/arch/arm/config.mk
new file mode 100644
index 000000000..e10dafca5
--- /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 000000000..02933485c
--- /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 000000000..834ddc254
--- /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 000000000..671ac87a2
--- /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 000000000..cfbadb2ab
--- /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 000000000..e7fa79938
--- /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 000000000..539c58499
--- /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 000000000..130980261
--- /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 000000000..8465ef09d
--- /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 000000000..f5660a985
--- /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 000000000..128b7e313
--- /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 000000000..62ed54fb4
--- /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 000000000..61ee9d3b1
--- /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 000000000..6267bf16a
--- /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 000000000..86eacf1b0
--- /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 000000000..1f2b81561
--- /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 000000000..4fcedfa15
--- /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 000000000..1121ca1cc
--- /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 000000000..37b80514f
--- /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 000000000..917ed6ce7
--- /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 000000000..6a3172a9a
--- /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 000000000..bbbc490db
--- /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 000000000..79e3c675a
--- /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 000000000..137834e7e
--- /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 000000000..09f1be04e
--- /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 000000000..3bdba754d
--- /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 000000000..cba4179d3
--- /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 000000000..4e9bb1922
--- /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 000000000..951d5b0d0
--- /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 000000000..0a321a448
--- /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 000000000..0be395bb3
--- /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 000000000..de5840e4c
--- /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 000000000..451959642
--- /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 000000000..bd62d7105
--- /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 000000000..18f1f493c
--- /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 000000000..6c834a7e8
--- /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 000000000..e6b359a34
--- /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 000000000..e385c4f6f
--- /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 000000000..26f63cdc9
--- /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 000000000..bf1ca535f
--- /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 000000000..90c6033c9
--- /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 000000000..faf6b96ba
--- /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 000000000..e344d3b94
--- /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 000000000..bf7fba00c
--- /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 000000000..2b23d8ba6
--- /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 000000000..4b990e04e
--- /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 000000000..983850668
--- /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 000000000..48f1b8112
--- /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 000000000..4901f8917
--- /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 000000000..9e412e5e4
--- /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 000000000..6491e522e
--- /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 000000000..f3b634855
--- /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 000000000..f96d7bd6d
--- /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 000000000..51def5995
--- /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 000000000..67e6e97e3
--- /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 000000000..1373fd125
--- /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 000000000..9020e7ce7
--- /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 000000000..225ae4a99
--- /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 000000000..3c3c1fc96
--- /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 000000000..d6c74ecd7
--- /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 000000000..5cb1f54fb
--- /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 000000000..c58ed104c
--- /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 000000000..c8060e60a
--- /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 000000000..c3b4e597a
--- /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 000000000..749c38968
--- /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 000000000..6db35ed2c
--- /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 000000000..732023d67
--- /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 000000000..e5ed6eb7c
--- /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 000000000..ed881783f
--- /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 000000000..133494f6d
--- /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 000000000..7eaea5e7f
--- /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 000000000..1ca94dc55
--- /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 000000000..c3c9f958c
--- /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 000000000..9b0f296e3
--- /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 000000000..d4baea930
--- /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 000000000..bce4774fe
--- /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 000000000..4b2e8e379
--- /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 000000000..da016a001
--- /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 000000000..aa06761ae
--- /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 000000000..7967e5803
--- /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 000000000..b2d113e87
--- /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 000000000..54af24cba
--- /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 000000000..cc70fa93f
--- /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 000000000..0e6644149
--- /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 000000000..e1b9f07bb
--- /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 000000000..f66e9893a
--- /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 000000000..5d2fb2ec4
--- /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 000000000..b0d5b8257
--- /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 000000000..87dbab173
--- /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 000000000..3c7e71e97
--- /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 000000000..f0aed8edc
--- /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 000000000..ec8139ed5
--- /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 000000000..d5096ee12
--- /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 000000000..be4063928
--- /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 000000000..b69bc3885
--- /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 000000000..8ec66a354
--- /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 000000000..5d25edf80
--- /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 000000000..ee3b4b79b
--- /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 000000000..3c7e71e97
--- /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 000000000..f0aed8edc
--- /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 000000000..ec8139ed5
--- /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 000000000..d5096ee12
--- /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 000000000..06a3b107d
--- /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 000000000..334e45780
--- /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 000000000..c48c24015
--- /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 000000000..a30acee4f
--- /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 000000000..0685a9331
--- /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 000000000..338b08bd7
--- /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 000000000..7408d5c96
--- /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 000000000..f6031707a
--- /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 000000000..d3eb1f35a
--- /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 000000000..278a8048f
--- /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 000000000..97023a055
--- /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 000000000..50f9a83fc
--- /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 000000000..b8d25b7f4
--- /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 000000000..29099612d
--- /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 000000000..797bf4c22
--- /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 000000000..f7c647942
--- /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 000000000..c97e20c3e
--- /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 000000000..ae1f869f1
--- /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 000000000..9a8f89aef
--- /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 000000000..789b46f0e
--- /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 000000000..4de6515ef
--- /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 000000000..040ca10d3
--- /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 000000000..11eea603c
--- /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 000000000..c62cf57d8
--- /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 000000000..59d9bbe67
--- /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 000000000..4c73b82a6
--- /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 000000000..82b2a3abc
--- /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);
+}
+
+/* ------------------------------------------------------------------------- */