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

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

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

Signed-off-by: Peter Tyser <ptyser@xes-inc.com>
diff --git a/arch/blackfin/config.mk b/arch/blackfin/config.mk
new file mode 100644
index 0000000..137834e
--- /dev/null
+++ b/arch/blackfin/config.mk
@@ -0,0 +1,72 @@
+#
+# (C) Copyright 2000-2002
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+CROSS_COMPILE ?= bfin-uclinux-
+
+STANDALONE_LOAD_ADDR = 0x1000 -m elf32bfin
+
+CONFIG_BFIN_CPU := $(strip $(subst ",,$(CONFIG_BFIN_CPU)))
+CONFIG_BFIN_BOOT_MODE := $(strip $(subst ",,$(CONFIG_BFIN_BOOT_MODE)))
+CONFIG_ENV_OFFSET := $(strip $(subst ",,$(CONFIG_ENV_OFFSET)))
+CONFIG_ENV_SIZE := $(strip $(subst ",,$(CONFIG_ENV_SIZE)))
+
+PLATFORM_RELFLAGS += -ffixed-P3 -fomit-frame-pointer -mno-fdpic
+PLATFORM_CPPFLAGS += -DCONFIG_BLACKFIN
+
+LDFLAGS += --gc-sections -m elf32bfin
+PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
+
+ifneq (,$(CONFIG_BFIN_CPU))
+PLATFORM_RELFLAGS += -mcpu=$(CONFIG_BFIN_CPU)
+endif
+
+ifneq ($(CONFIG_BFIN_BOOT_MODE),BFIN_BOOT_BYPASS)
+ALL += $(obj)u-boot.ldr
+endif
+ifeq ($(CONFIG_ENV_IS_EMBEDDED_IN_LDR),y)
+CREATE_LDR_ENV = $(obj)tools/envcrc --binary > $(obj)env-ldr.o
+else
+CREATE_LDR_ENV =
+endif
+
+SYM_PREFIX = _
+
+LDR_FLAGS-y :=
+LDR_FLAGS-$(CONFIG_BFIN_BOOTROM_USES_EVT1) += -J
+
+LDR_FLAGS += --bmode $(subst BFIN_BOOT_,,$(CONFIG_BFIN_BOOT_MODE))
+LDR_FLAGS += --use-vmas
+LDR_FLAGS += --initcode $(obj)$(CPUDIR)/initcode.o
+ifneq ($(CONFIG_BFIN_BOOT_MODE),BFIN_BOOT_UART)
+LDR_FLAGS-$(CONFIG_ENV_IS_EMBEDDED_IN_LDR) += \
+	--punchit $$(($(CONFIG_ENV_OFFSET))):$$(($(CONFIG_ENV_SIZE))):$(obj)env-ldr.o
+endif
+ifneq (,$(findstring s,$(MAKEFLAGS)))
+LDR_FLAGS += --quiet
+endif
+
+LDR_FLAGS += $(LDR_FLAGS-y)
+
+ifeq ($(wildcard $(TOPDIR)/board/$(BOARD)/u-boot.lds*),)
+LDSCRIPT = $(obj)arch/$(ARCH)/lib/u-boot.lds.S
+endif
diff --git a/arch/blackfin/lib/.gitignore b/arch/blackfin/lib/.gitignore
new file mode 100644
index 0000000..09f1be0
--- /dev/null
+++ b/arch/blackfin/lib/.gitignore
@@ -0,0 +1 @@
+u-boot.lds
diff --git a/arch/blackfin/lib/Makefile b/arch/blackfin/lib/Makefile
new file mode 100644
index 0000000..3bdba75
--- /dev/null
+++ b/arch/blackfin/lib/Makefile
@@ -0,0 +1,65 @@
+#
+# U-boot Makefile
+#
+# Copyright (c) 2005-2008 Analog Devices Inc.
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301 USA
+#
+
+include $(TOPDIR)/config.mk
+
+CFLAGS += -DBFIN_BOARD_NAME='"$(BOARD)"'
+
+LIB	= $(obj)lib$(ARCH).a
+
+SOBJS-y	+= ins.o
+SOBJS-y	+= memcmp.o
+SOBJS-y	+= memcpy.o
+SOBJS-y	+= memmove.o
+SOBJS-y	+= memset.o
+SOBJS-y	+= outs.o
+SOBJS-$(CONFIG_CMD_KGDB) += __kgdb.o
+
+COBJS-y	+= board.o
+COBJS-y	+= boot.o
+COBJS-y	+= cache.o
+COBJS-y	+= clocks.o
+COBJS-$(CONFIG_CMD_CACHE_DUMP) += cmd_cache_dump.o
+COBJS-$(CONFIG_CMD_KGDB) += kgdb.o
+COBJS-y	+= muldi3.o
+COBJS-$(CONFIG_POST) += post.o tests.o
+COBJS-y	+= string.o
+
+SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/blackfin/lib/__kgdb.S b/arch/blackfin/lib/__kgdb.S
new file mode 100644
index 0000000..cba4179
--- /dev/null
+++ b/arch/blackfin/lib/__kgdb.S
@@ -0,0 +1,155 @@
+
+#include <asm/linkage.h>
+
+/* save stack context for non-local goto
+ * int kgdb_setjmp(long *buf)
+ */
+
+ENTRY(_kgdb_setjmp)
+	[--SP] = p0; 	/* Save P0 */
+	p0 = r0;
+	r0 = [SP++];	/* Load P0 into R0 */
+
+	[p0 + 0x00] = r0;       /* GP address registers */
+	[p0 + 0x04] = p1;
+	[p0 + 0x08] = p2;
+	[p0 + 0x0C] = p3;
+	[p0 + 0x10] = p4;
+	[p0 + 0x14] = p5;
+	[p0 + 0x18] = FP;       /* frame pointer */
+	[p0 + 0x1C] = SP;       /* stack pointer */
+
+	[p0 + 0x20] = p0;       /* data regs */
+	[p0 + 0x24] = r1;
+	[p0 + 0x28] = r2;
+	[p0 + 0x2C] = r3;
+	[p0 + 0x30] = r4;
+	[p0 + 0x34] = r5;
+	[p0 + 0x38] = r6;
+	[p0 + 0x3C] = r7;
+
+	r0 = ASTAT;	[p0 + 0x40] = r0;
+
+	/* loop counters */
+	r0 = LC0;	[p0 + 0x44] = r0;
+	r0 = LC1;	[p0 + 0x48] = r0;
+
+	/* Accumulator */
+	r0 = A0.w;	[p0 + 0x4C] = r0;
+	r0.l = A0.x;	[p0 + 0x50] = r0;
+	r0 = A1.w;	[p0 + 0x54] = r0;
+	r0.l = A1.x;	[p0 + 0x58] = r0;
+
+	/* index registers */
+	r0 = i0;	[p0 + 0x5C] = r0;
+	r0 = i1;	[p0 + 0x60] = r0;
+	r0 = i2;	[p0 + 0x64] = r0;
+	r0 = i3;	[p0 + 0x68] = r0;
+
+	/* modifier registers */
+	r0 = m0;	[p0 + 0x6C] = r0;
+	r0 = m1;	[p0 + 0x70] = r0;
+	r0 = m2;	[p0 + 0x74] = r0;
+	r0 = m3;	[p0 + 0x78] = r0;
+
+	/* length registers */
+	r0 = l0;	[p0 + 0x7C] = r0;
+	r0 = l1;	[p0 + 0x80] = r0;
+	r0 = l2;	[p0 + 0x84] = r0;
+	r0 = l3;	[p0 + 0x88] = r0;
+
+	/* base registers */
+	r0 = b0;	[p0 + 0x8C] = r0;
+	r0 = b1;	[p0 + 0x90] = r0;
+	r0 = b2;	[p0 + 0x94] = r0;
+	r0 = b3;	[p0 + 0x98] = r0;
+
+	/* store return address */
+	r0 = RETS;	[p0 + 0x9C] = r0;
+
+	R0 = 0;
+	RTS;
+ENDPROC(_kgdb_setjmp)
+
+/*
+ * non-local jump to a saved stack context
+ * longjmp(long *buf, int val)
+ */
+
+ENTRY(_kgdb_longjmp)
+	p0 = r0;
+	r0 = [p0 + 0x00];
+	[--sp] = r0;
+
+	/* GP address registers - skip p0 for now*/
+	p1 = [p0 + 0x04];
+	p2 = [p0 + 0x08];
+	p3 = [p0 + 0x0C];
+	p4 = [p0 + 0x10];
+	p5 = [p0 + 0x14];
+	/* frame pointer */
+	fp = [p0 + 0x18];
+	/* stack pointer */
+	r0 = [sp++];
+	sp = [p0 + 0x1C];
+	[--sp] = r0;
+	[--sp] = r1;
+
+	/* data regs */
+	r0 = [p0 + 0x20];
+	r1 = [p0 + 0x24];
+	r2 = [p0 + 0x28];
+	r3 = [p0 + 0x2C];
+	r4 = [p0 + 0x30];
+	r5 = [p0 + 0x34];
+	r6 = [p0 + 0x38];
+	r7 = [p0 + 0x3C];
+
+	r0 = [p0 + 0x40];	ASTAT = r0;
+
+	/* loop counters */
+	r0 = [p0 + 0x44];	LC0 = r0;
+	r0 = [p0 + 0x48];	LC1 = r0;
+
+	/* Accumulator */
+	r0 = [p0 + 0x4C];	A0.w = r0;
+	r0 = [p0 + 0x50];	A0.x = r0;
+	r0 = [p0 + 0x54];	A1.w = r0;
+	r0 = [p0 + 0x58];	A1.x = r0;
+
+	/* index registers */
+	r0 = [p0 + 0x5C];	i0 = r0;
+	r0 = [p0 + 0x60];	i1 = r0;
+	r0 = [p0 + 0x64];	i2 = r0;
+	r0 = [p0 + 0x68];	i3 = r0;
+
+	/* modifier registers */
+	r0 = [p0 + 0x6C];	m0 = r0;
+	r0 = [p0 + 0x70];	m1 = r0;
+	r0 = [p0 + 0x74];	m2 = r0;
+	r0 = [p0 + 0x78];	m3 = r0;
+
+	/* length registers */
+	r0 = [p0 + 0x7C];	l0 = r0;
+	r0 = [p0 + 0x80];	l1 = r0;
+	r0 = [p0 + 0x84];	l2 = r0;
+	r0 = [p0 + 0x88];	l3 = r0;
+
+	/* base registers */
+	r0 = [p0 + 0x8C];	b0 = r0;
+	r0 = [p0 + 0x90];	b1 = r0;
+	r0 = [p0 + 0x94];	b2 = r0;
+	r0 = [p0 + 0x98];	b3 = r0;
+
+	/* store return address */
+	r0 = [p0 + 0x9C];	RETS = r0;
+
+	/* fixup R0 & P0 */
+	r0 = [sp++];
+	p0 = [sp++];
+	CC = R0 == 0;
+	IF !CC JUMP .Lfinished;
+	R0 = 1;
+.Lfinished:
+	RTS;
+ENDPROC(_kgdb_longjmp)
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
new file mode 100644
index 0000000..4e9bb19
--- /dev/null
+++ b/arch/blackfin/lib/board.c
@@ -0,0 +1,419 @@
+/*
+ * U-boot - board.c First C file to be called contains init routines
+ *
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <stdio_dev.h>
+#include <environment.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <net.h>
+#include <timestamp.h>
+#include <status_led.h>
+#include <version.h>
+
+#include <asm/cplb.h>
+#include <asm/mach-common/bits/mpu.h>
+#include <kgdb.h>
+
+#ifdef CONFIG_CMD_NAND
+#include <nand.h>	/* cannot even include nand.h if it isnt configured */
+#endif
+
+#ifdef CONFIG_BITBANGMII
+#include <miiphy.h>
+#endif
+
+#if defined(CONFIG_POST)
+#include <post.h>
+int post_flag;
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+const char version_string[] = U_BOOT_VERSION " ("U_BOOT_DATE" - "U_BOOT_TIME")";
+
+__attribute__((always_inline))
+static inline void serial_early_puts(const char *s)
+{
+#ifdef CONFIG_DEBUG_EARLY_SERIAL
+	serial_puts("Early: ");
+	serial_puts(s);
+#endif
+}
+
+static int display_banner(void)
+{
+	printf("\n\n%s\n\n", version_string);
+	printf("CPU:   ADSP " MK_STR(CONFIG_BFIN_CPU) " "
+		"(Detected Rev: 0.%d) "
+		"(%s boot)\n",
+		bfin_revid(),
+		get_bfin_boot_mode(CONFIG_BFIN_BOOT_MODE));
+	return 0;
+}
+
+static int init_baudrate(void)
+{
+	char baudrate[15];
+	int i = getenv_r("baudrate", baudrate, sizeof(baudrate));
+	gd->bd->bi_baudrate = gd->baudrate = (i > 0)
+	    ? simple_strtoul(baudrate, NULL, 10)
+	    : CONFIG_BAUDRATE;
+	return 0;
+}
+
+static void display_global_data(void)
+{
+	bd_t *bd;
+
+#ifndef CONFIG_DEBUG_EARLY_SERIAL
+	return;
+#endif
+
+	bd = gd->bd;
+	printf(" gd: %p\n", gd);
+	printf(" |-flags: %lx\n", gd->flags);
+	printf(" |-board_type: %lx\n", gd->board_type);
+	printf(" |-baudrate: %lu\n", gd->baudrate);
+	printf(" |-have_console: %lx\n", gd->have_console);
+	printf(" |-ram_size: %lx\n", gd->ram_size);
+	printf(" |-env_addr: %lx\n", gd->env_addr);
+	printf(" |-env_valid: %lx\n", gd->env_valid);
+	printf(" |-jt(%p): %p\n", gd->jt, *(gd->jt));
+	printf(" \\-bd: %p\n", gd->bd);
+	printf("   |-bi_baudrate: %x\n", bd->bi_baudrate);
+	printf("   |-bi_ip_addr: %lx\n", bd->bi_ip_addr);
+	printf("   |-bi_boot_params: %lx\n", bd->bi_boot_params);
+	printf("   |-bi_memstart: %lx\n", bd->bi_memstart);
+	printf("   |-bi_memsize: %lx\n", bd->bi_memsize);
+	printf("   |-bi_flashstart: %lx\n", bd->bi_flashstart);
+	printf("   |-bi_flashsize: %lx\n", bd->bi_flashsize);
+	printf("   \\-bi_flashoffset: %lx\n", bd->bi_flashoffset);
+}
+
+#define CPLB_PAGE_SIZE (4 * 1024 * 1024)
+#define CPLB_PAGE_MASK (~(CPLB_PAGE_SIZE - 1))
+void init_cplbtables(void)
+{
+	volatile uint32_t *ICPLB_ADDR, *ICPLB_DATA;
+	volatile uint32_t *DCPLB_ADDR, *DCPLB_DATA;
+	uint32_t extern_memory;
+	size_t i;
+
+	void icplb_add(uint32_t addr, uint32_t data)
+	{
+		*(ICPLB_ADDR + i) = addr;
+		*(ICPLB_DATA + i) = data;
+	}
+	void dcplb_add(uint32_t addr, uint32_t data)
+	{
+		*(DCPLB_ADDR + i) = addr;
+		*(DCPLB_DATA + i) = data;
+	}
+
+	/* populate a few common entries ... we'll let
+	 * the memory map and cplb exception handler do
+	 * the rest of the work.
+	 */
+	i = 0;
+	ICPLB_ADDR = (uint32_t *)ICPLB_ADDR0;
+	ICPLB_DATA = (uint32_t *)ICPLB_DATA0;
+	DCPLB_ADDR = (uint32_t *)DCPLB_ADDR0;
+	DCPLB_DATA = (uint32_t *)DCPLB_DATA0;
+
+	icplb_add(0xFFA00000, L1_IMEMORY);
+	dcplb_add(0xFF800000, L1_DMEMORY);
+	++i;
+
+	if (CONFIG_MEM_SIZE) {
+		uint32_t mbase = CONFIG_SYS_MONITOR_BASE;
+		uint32_t mend  = mbase + CONFIG_SYS_MONITOR_LEN;
+		mbase &= CPLB_PAGE_MASK;
+		mend &= CPLB_PAGE_MASK;
+
+		icplb_add(mbase, SDRAM_IKERNEL);
+		dcplb_add(mbase, SDRAM_DKERNEL);
+		++i;
+
+		/*
+		 * If the monitor crosses a 4 meg boundary, we'll need
+		 * to lock two entries for it.  We assume it doesn't
+		 * cross two 4 meg boundaries ...
+		 */
+		if (mbase != mend) {
+			icplb_add(mend, SDRAM_IKERNEL);
+			dcplb_add(mend, SDRAM_DKERNEL);
+			++i;
+		}
+	}
+
+	icplb_add(0x20000000, SDRAM_INON_CHBL);
+	dcplb_add(0x20000000, SDRAM_EBIU);
+	++i;
+
+	/* Add entries for the rest of external RAM up to the bootrom */
+	extern_memory = 0;
+
+#ifdef CONFIG_DEBUG_NULL_PTR
+	icplb_add(extern_memory, (SDRAM_IKERNEL & ~PAGE_SIZE_MASK) | PAGE_SIZE_1KB);
+	dcplb_add(extern_memory, (SDRAM_DKERNEL & ~PAGE_SIZE_MASK) | PAGE_SIZE_1KB);
+	++i;
+	icplb_add(extern_memory, SDRAM_IKERNEL);
+	dcplb_add(extern_memory, SDRAM_DKERNEL);
+	extern_memory += CPLB_PAGE_SIZE;
+	++i;
+#endif
+
+	while (i < 16 && extern_memory < (CONFIG_SYS_MONITOR_BASE & CPLB_PAGE_MASK)) {
+		icplb_add(extern_memory, SDRAM_IGENERIC);
+		dcplb_add(extern_memory, SDRAM_DGENERIC);
+		extern_memory += CPLB_PAGE_SIZE;
+		++i;
+	}
+	while (i < 16) {
+		icplb_add(0, 0);
+		dcplb_add(0, 0);
+		++i;
+	}
+}
+
+/*
+ * All attempts to come up with a "common" initialization sequence
+ * that works for all boards and architectures failed: some of the
+ * requirements are just _too_ different. To get rid of the resulting
+ * mess of board dependend #ifdef'ed code we now make the whole
+ * initialization sequence configurable to the user.
+ *
+ * The requirements for any new initalization function is simple: it
+ * receives a pointer to the "global data" structure as it's only
+ * argument, and returns an integer return code, where 0 means
+ * "continue" and != 0 means "fatal error, hang the system".
+ */
+
+extern int watchdog_init(void);
+extern int exception_init(void);
+extern int irq_init(void);
+extern int timer_init(void);
+
+void board_init_f(ulong bootflag)
+{
+	ulong addr;
+	bd_t *bd;
+	char buf[32];
+
+#ifdef CONFIG_BOARD_EARLY_INIT_F
+	serial_early_puts("Board early init flash\n");
+	board_early_init_f();
+#endif
+
+	serial_early_puts("Init CPLB tables\n");
+	init_cplbtables();
+
+	serial_early_puts("Exceptions setup\n");
+	exception_init();
+
+#ifndef CONFIG_ICACHE_OFF
+	serial_early_puts("Turn on ICACHE\n");
+	icache_enable();
+#endif
+#ifndef CONFIG_DCACHE_OFF
+	serial_early_puts("Turn on DCACHE\n");
+	dcache_enable();
+#endif
+
+#ifdef CONFIG_WATCHDOG
+	serial_early_puts("Setting up external watchdog\n");
+	watchdog_init();
+#endif
+
+#ifdef DEBUG
+	if (CONFIG_SYS_GBL_DATA_SIZE < sizeof(*gd))
+		hang();
+#endif
+	serial_early_puts("Init global data\n");
+	gd = (gd_t *) (CONFIG_SYS_GBL_DATA_ADDR);
+	memset((void *)gd, 0, CONFIG_SYS_GBL_DATA_SIZE);
+
+	/* Board data initialization */
+	addr = (CONFIG_SYS_GBL_DATA_ADDR + sizeof(gd_t));
+
+	/* Align to 4 byte boundary */
+	addr &= ~(4 - 1);
+	bd = (bd_t *) addr;
+	gd->bd = bd;
+	memset((void *)bd, 0, sizeof(bd_t));
+
+	bd->bi_r_version = version_string;
+	bd->bi_cpu = MK_STR(CONFIG_BFIN_CPU);
+	bd->bi_board_name = BFIN_BOARD_NAME;
+	bd->bi_vco = get_vco();
+	bd->bi_cclk = get_cclk();
+	bd->bi_sclk = get_sclk();
+	bd->bi_memstart = CONFIG_SYS_SDRAM_BASE;
+	bd->bi_memsize = CONFIG_SYS_MAX_RAM_SIZE;
+
+	/* Initialize */
+	serial_early_puts("IRQ init\n");
+	irq_init();
+	serial_early_puts("Environment init\n");
+	env_init();
+	serial_early_puts("Baudrate init\n");
+	init_baudrate();
+	serial_early_puts("Serial init\n");
+	serial_init();
+	serial_early_puts("Console init flash\n");
+	console_init_f();
+	serial_early_puts("End of early debugging\n");
+	display_banner();
+
+	checkboard();
+	timer_init();
+
+	printf("Clock: VCO: %s MHz, ", strmhz(buf, get_vco()));
+	printf("Core: %s MHz, ", strmhz(buf, get_cclk()));
+	printf("System: %s MHz\n", strmhz(buf, get_sclk()));
+
+	printf("RAM:   ");
+	print_size(bd->bi_memsize, "\n");
+#if defined(CONFIG_POST)
+	post_init_f();
+	post_bootmode_init();
+	post_run(NULL, POST_ROM | post_bootmode_get(0));
+#endif
+
+	board_init_r((gd_t *) gd, 0x20000010);
+}
+
+static void board_net_init_r(bd_t *bd)
+{
+#ifdef CONFIG_BITBANGMII
+	bb_miiphy_init();
+#endif
+#ifdef CONFIG_CMD_NET
+	char *s;
+
+	if ((s = getenv("bootfile")) != NULL)
+		copy_filename(BootFile, s, sizeof(BootFile));
+
+	bd->bi_ip_addr = getenv_IPaddr("ipaddr");
+
+	printf("Net:   ");
+	eth_initialize(gd->bd);
+#endif
+}
+
+void board_init_r(gd_t * id, ulong dest_addr)
+{
+	char *s;
+	bd_t *bd;
+	gd = id;
+	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
+	bd = gd->bd;
+
+#if defined(CONFIG_POST)
+	post_output_backlog();
+	post_reloc();
+#endif
+
+	/* initialize malloc() area */
+	mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
+
+#if	!defined(CONFIG_SYS_NO_FLASH)
+	/* Initialize the flash and protect u-boot by default */
+	extern flash_info_t flash_info[];
+	puts("Flash: ");
+	ulong size = flash_init();
+	print_size(size, "\n");
+	flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_FLASH_BASE,
+		CONFIG_SYS_FLASH_BASE + CONFIG_SYS_MONITOR_LEN - 1,
+		&flash_info[0]);
+	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
+	bd->bi_flashsize = size;
+	bd->bi_flashoffset = 0;
+#else
+	bd->bi_flashstart = 0;
+	bd->bi_flashsize = 0;
+	bd->bi_flashoffset = 0;
+#endif
+
+#ifdef CONFIG_CMD_NAND
+	puts("NAND:  ");
+	nand_init();		/* go init the NAND */
+#endif
+
+#ifdef CONFIG_GENERIC_MMC
+	puts("MMC:  ");
+	mmc_initialize(bd);
+#endif
+
+	/* relocate environment function pointers etc. */
+	env_relocate();
+
+	/* Initialize stdio devices */
+	stdio_init();
+	jumptable_init();
+
+	/* Initialize the console (after the relocation and devices init) */
+	console_init_r();
+
+#ifdef CONFIG_CMD_KGDB
+	puts("KGDB:  ");
+	kgdb_init();
+#endif
+
+#ifdef CONFIG_STATUS_LED
+	status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING);
+	status_led_set(STATUS_LED_CRASH, STATUS_LED_OFF);
+#endif
+
+	/* Initialize from environment */
+	if ((s = getenv("loadaddr")) != NULL)
+		load_addr = simple_strtoul(s, NULL, 16);
+
+#if defined(CONFIG_MISC_INIT_R)
+	/* miscellaneous platform dependent initialisations */
+	misc_init_r();
+#endif
+
+	board_net_init_r(bd);
+
+	display_global_data();
+
+#if defined(CONFIG_POST)
+	if (post_flag)
+		post_run(NULL, POST_RAM | post_bootmode_get(0));
+#endif
+
+	if (bfin_os_log_check()) {
+		puts("\nLog buffer from operating system:\n");
+		bfin_os_log_dump();
+		puts("\n");
+	}
+
+	/* main_loop() can return to retry autoboot, if so just run it again. */
+	for (;;)
+		main_loop();
+}
+
+void hang(void)
+{
+#ifdef CONFIG_STATUS_LED
+	status_led_set(STATUS_LED_BOOT, STATUS_LED_OFF);
+	status_led_set(STATUS_LED_CRASH, STATUS_LED_BLINKING);
+#endif
+	puts("### ERROR ### Please RESET the board ###\n");
+	while (1)
+		/* If a JTAG emulator is hooked up, we'll automatically trigger
+		 * a breakpoint in it.  If one isn't, this is just a NOP.
+		 */
+		asm("emuexcpt;");
+}
diff --git a/arch/blackfin/lib/boot.c b/arch/blackfin/lib/boot.c
new file mode 100644
index 0000000..951d5b0
--- /dev/null
+++ b/arch/blackfin/lib/boot.c
@@ -0,0 +1,63 @@
+/*
+ * U-boot - boot.c - misc boot helper functions
+ *
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <image.h>
+#include <asm/blackfin.h>
+
+#ifdef SHARED_RESOURCES
+extern void swap_to(int device_id);
+#endif
+
+static char *make_command_line(void)
+{
+	char *dest = (char *)CONFIG_LINUX_CMDLINE_ADDR;
+	char *bootargs = getenv("bootargs");
+
+	if (bootargs == NULL)
+		return NULL;
+
+	strncpy(dest, bootargs, CONFIG_LINUX_CMDLINE_SIZE);
+	dest[CONFIG_LINUX_CMDLINE_SIZE - 1] = 0;
+	return dest;
+}
+
+extern ulong bfin_poweron_retx;
+
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	int	(*appl) (char *cmdline);
+	char	*cmdline;
+
+	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+		return 1;
+
+#ifdef SHARED_RESOURCES
+	swap_to(FLASH);
+#endif
+
+	appl = (int (*)(char *))images->ep;
+
+	printf("Starting Kernel at = %p\n", appl);
+	cmdline = make_command_line();
+	icache_disable();
+	dcache_disable();
+	asm __volatile__(
+		"RETX = %[retx];"
+		"CALL (%0);"
+		:
+		: "p"(appl), "q0"(cmdline), [retx] "d"(bfin_poweron_retx)
+	);
+	/* does not return */
+
+	return 1;
+}
diff --git a/arch/blackfin/lib/cache.c b/arch/blackfin/lib/cache.c
new file mode 100644
index 0000000..0a321a4
--- /dev/null
+++ b/arch/blackfin/lib/cache.c
@@ -0,0 +1,113 @@
+/*
+ * U-boot - cache.c
+ *
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <asm/blackfin.h>
+#include <asm/mach-common/bits/mpu.h>
+
+void flush_cache(unsigned long addr, unsigned long size)
+{
+	void *start_addr, *end_addr;
+	int istatus, dstatus;
+
+	/* no need to flush stuff in on chip memory (L1/L2/etc...) */
+	if (addr >= 0xE0000000)
+		return;
+
+	start_addr = (void *)addr;
+	end_addr = (void *)(addr + size);
+	istatus = icache_status();
+	dstatus = dcache_status();
+
+	if (istatus) {
+		if (dstatus)
+			blackfin_icache_dcache_flush_range(start_addr, end_addr);
+		else
+			blackfin_icache_flush_range(start_addr, end_addr);
+	} else if (dstatus)
+		blackfin_dcache_flush_range(start_addr, end_addr);
+}
+
+#ifdef CONFIG_DCACHE_WB
+static void flushinv_all_dcache(void)
+{
+	u32 way, bank, subbank, set;
+	u32 status, addr;
+	u32 dmem_ctl = bfin_read_DMEM_CONTROL();
+
+	for (bank = 0; bank < 2; ++bank) {
+		if (!(dmem_ctl & (1 << (DMC1_P - bank))))
+			continue;
+
+		for (way = 0; way < 2; ++way)
+			for (subbank = 0; subbank < 4; ++subbank)
+				for (set = 0; set < 64; ++set) {
+
+					bfin_write_DTEST_COMMAND(
+						way << 26 |
+						bank << 23 |
+						subbank << 16 |
+						set << 5
+					);
+					CSYNC();
+					status = bfin_read_DTEST_DATA0();
+
+					/* only worry about valid/dirty entries */
+					if ((status & 0x3) != 0x3)
+						continue;
+
+					/* construct the address using the tag */
+					addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5);
+
+					/* flush it */
+					__asm__ __volatile__("FLUSHINV[%0];" : : "a"(addr));
+				}
+	}
+}
+#endif
+
+void icache_enable(void)
+{
+	bfin_write_IMEM_CONTROL(IMC | ENICPLB);
+	SSYNC();
+}
+
+void icache_disable(void)
+{
+	bfin_write_IMEM_CONTROL(0);
+	SSYNC();
+}
+
+int icache_status(void)
+{
+	return bfin_read_IMEM_CONTROL() & IMC;
+}
+
+void dcache_enable(void)
+{
+	bfin_write_DMEM_CONTROL(ACACHE_BCACHE | ENDCPLB | PORT_PREF0);
+	SSYNC();
+}
+
+void dcache_disable(void)
+{
+#ifdef CONFIG_DCACHE_WB
+	bfin_write_DMEM_CONTROL(bfin_read_DMEM_CONTROL() & ~(ENDCPLB));
+	flushinv_all_dcache();
+#endif
+	bfin_write_DMEM_CONTROL(0);
+	SSYNC();
+}
+
+int dcache_status(void)
+{
+	return bfin_read_DMEM_CONTROL() & ACACHE_BCACHE;
+}
diff --git a/arch/blackfin/lib/clocks.c b/arch/blackfin/lib/clocks.c
new file mode 100644
index 0000000..0be395b
--- /dev/null
+++ b/arch/blackfin/lib/clocks.c
@@ -0,0 +1,77 @@
+/*
+ * clocks.c - figure out sclk/cclk/vco and such
+ *
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <asm/blackfin.h>
+
+/* Get the voltage input multiplier */
+static u_long cached_vco_pll_ctl, cached_vco;
+u_long get_vco(void)
+{
+	u_long msel;
+
+	u_long pll_ctl = bfin_read_PLL_CTL();
+	if (pll_ctl == cached_vco_pll_ctl)
+		return cached_vco;
+	else
+		cached_vco_pll_ctl = pll_ctl;
+
+	msel = (pll_ctl >> 9) & 0x3F;
+	if (0 == msel)
+		msel = 64;
+
+	cached_vco = CONFIG_CLKIN_HZ;
+	cached_vco >>= (1 & pll_ctl);	/* DF bit */
+	cached_vco *= msel;
+	return cached_vco;
+}
+
+/* Get the Core clock */
+static u_long cached_cclk_pll_div, cached_cclk;
+u_long get_cclk(void)
+{
+	u_long csel, ssel;
+
+	if (bfin_read_PLL_STAT() & 0x1)
+		return CONFIG_CLKIN_HZ;
+
+	ssel = bfin_read_PLL_DIV();
+	if (ssel == cached_cclk_pll_div)
+		return cached_cclk;
+	else
+		cached_cclk_pll_div = ssel;
+
+	csel = ((ssel >> 4) & 0x03);
+	ssel &= 0xf;
+	if (ssel && ssel < (1 << csel))	/* SCLK > CCLK */
+		cached_cclk = get_vco() / ssel;
+	else
+		cached_cclk = get_vco() >> csel;
+	return cached_cclk;
+}
+
+/* Get the System clock */
+static u_long cached_sclk_pll_div, cached_sclk;
+u_long get_sclk(void)
+{
+	u_long ssel;
+
+	if (bfin_read_PLL_STAT() & 0x1)
+		return CONFIG_CLKIN_HZ;
+
+	ssel = bfin_read_PLL_DIV();
+	if (ssel == cached_sclk_pll_div)
+		return cached_sclk;
+	else
+		cached_sclk_pll_div = ssel;
+
+	ssel &= 0xf;
+
+	cached_sclk = get_vco() / ssel;
+	return cached_sclk;
+}
diff --git a/arch/blackfin/lib/cmd_cache_dump.c b/arch/blackfin/lib/cmd_cache_dump.c
new file mode 100644
index 0000000..de5840e
--- /dev/null
+++ b/arch/blackfin/lib/cmd_cache_dump.c
@@ -0,0 +1,145 @@
+/*
+ * U-boot - cmd_cache_dump.c
+ *
+ * Copyright (c) 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+
+#include <asm/blackfin.h>
+#include <asm/mach-common/bits/mpu.h>
+
+static int check_limit(const char *type, size_t start_limit, size_t end_limit, size_t start, size_t end)
+{
+	if (start >= start_limit && start <= end_limit && \
+	    end <= end_limit && end >= start_limit && \
+	    start <= end)
+		return 0;
+
+	printf("%s limit violation: %zu <= (user:%zu) <= (user:%zu) <= %zu\n",
+		type, start_limit, start, end, end_limit);
+	return 1;
+}
+
+int do_icache_dump(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	int cache_status = icache_status();
+
+	if (cache_status)
+		icache_disable();
+
+	uint32_t cmd_base, tag, cache_upper, cache_lower;
+
+	size_t way, way_start = 0, way_end = 3;
+	size_t sbnk, sbnk_start = 0, sbnk_end = 3;
+	size_t set, set_start = 0, set_end = 31;
+	size_t dw;
+
+	if (argc > 1) {
+		way_start = way_end = simple_strtoul(argv[1], NULL, 10);
+		if (argc > 2) {
+			sbnk_start = sbnk_end = simple_strtoul(argv[2], NULL, 10);
+			if (argc > 3)
+				set_start = set_end = simple_strtoul(argv[3], NULL, 10);
+		}
+	}
+
+	if (check_limit("way", 0, 3, way_start, way_end) || \
+	    check_limit("subbank", 0, 3, sbnk_start, sbnk_end) || \
+	    check_limit("set", 0, 31, set_start, set_end))
+		return 1;
+
+	puts("Way:Subbank:Set: [valid-tag lower upper] {invalid-tag lower upper}...\n");
+
+	for (way = way_start; way <= way_end; ++way) {
+		for (sbnk = sbnk_start; sbnk <= sbnk_end; ++sbnk) {
+			for (set = set_start; set <= set_end; ++set) {
+				printf("%zu:%zu:%2zu: ", way, sbnk, set);
+				for (dw = 0; dw < 4; ++dw) {
+					if (ctrlc())
+						return 1;
+
+					cmd_base = \
+						(way  << 26) | \
+						(sbnk << 16) | \
+						(set  <<  5) | \
+						(dw   <<  3);
+
+					/* first read the tag */
+					bfin_write_ITEST_COMMAND(cmd_base | 0x0);
+					SSYNC();
+					tag = bfin_read_ITEST_DATA0();
+					printf("%c%08x ", (tag & 0x1 ? ' ' : '{'), tag);
+
+					/* grab the data at this loc */
+					bfin_write_ITEST_COMMAND(cmd_base | 0x4);
+					SSYNC();
+					cache_lower = bfin_read_ITEST_DATA0();
+					cache_upper = bfin_read_ITEST_DATA1();
+					printf("%08x %08x%c ", cache_lower, cache_upper, (tag & 0x1 ? ' ' : '}'));
+				}
+				puts("\n");
+			}
+		}
+	}
+
+	if (cache_status)
+		icache_enable();
+
+	return 0;
+}
+
+U_BOOT_CMD(icache_dump, 4, 0, do_icache_dump,
+	"icache_dump - dump current instruction cache\n",
+	"[way] [subbank] [set]");
+
+int do_dcache_dump(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	u32 way, bank, subbank, set;
+	u32 status, addr;
+	u32 dmem_ctl = bfin_read_DMEM_CONTROL();
+
+	for (bank = 0; bank < 2; ++bank) {
+		if (!(dmem_ctl & (1 << (DMC1_P - bank))))
+			continue;
+
+		for (way = 0; way < 2; ++way)
+			for (subbank = 0; subbank < 4; ++subbank) {
+				printf("%i:%i:%i:\t", bank, way, subbank);
+				for (set = 0; set < 64; ++set) {
+
+					if (ctrlc())
+						return 1;
+
+					/* retrieve a cache tag */
+					bfin_write_DTEST_COMMAND(
+						way << 26 |
+						bank << 23 |
+						subbank << 16 |
+						set << 5
+					);
+					CSYNC();
+					status = bfin_read_DTEST_DATA0();
+
+					/* construct the address using the tag */
+					addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5);
+
+					/* show it */
+					if (set && !(set % 4))
+						puts("\n\t");
+					printf("%c%08x%c%08x%c ", (status & 0x1 ? '[' : '{'), status, (status & 0x2 ? 'd' : ' '), addr, (status & 0x1 ? ']' : '}'));
+				}
+				puts("\n");
+			}
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(dcache_dump, 4, 0, do_dcache_dump,
+	"dcache_dump - dump current data cache\n",
+	"[bank] [way] [subbank] [set]");
diff --git a/arch/blackfin/lib/ins.S b/arch/blackfin/lib/ins.S
new file mode 100644
index 0000000..4519596
--- /dev/null
+++ b/arch/blackfin/lib/ins.S
@@ -0,0 +1,117 @@
+/*
+ * arch/blackfin/lib/ins.S - ins{bwl} using hardware loops
+ *
+ * Copyright 2004-2008 Analog Devices Inc.
+ * Copyright (C) 2005 Bas Vermeulen, BuyWays BV <bas@buyways.nl>
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <asm/blackfin.h>
+
+.align 2
+
+#ifdef CONFIG_IPIPE
+# define DO_CLI \
+	[--sp] = rets; \
+	[--sp] = (P5:0); \
+	sp += -12; \
+	call ___ipipe_disable_root_irqs_hw; \
+	sp += 12; \
+	(P5:0) = [sp++];
+# define CLI_INNER_NOP
+#else
+# define DO_CLI cli R3;
+# define CLI_INNER_NOP nop; nop; nop;
+#endif
+
+#ifdef CONFIG_IPIPE
+# define DO_STI \
+	sp += -12; \
+	call ___ipipe_enable_root_irqs_hw; \
+	sp += 12; \
+2:	rets = [sp++];
+#else
+# define DO_STI 2: sti R3;
+#endif
+
+#ifdef CONFIG_BFIN_INS_LOWOVERHEAD
+# define CLI_OUTER DO_CLI;
+# define STI_OUTER DO_STI;
+# define CLI_INNER 1:
+# if ANOMALY_05000416
+#  define STI_INNER nop; 2: nop;
+# else
+#  define STI_INNER 2:
+# endif
+#else
+# define CLI_OUTER
+# define STI_OUTER
+# define CLI_INNER 1: DO_CLI; CLI_INNER_NOP;
+# define STI_INNER DO_STI;
+#endif
+
+/*
+ * Reads on the Blackfin are speculative. In Blackfin terms, this means they
+ * can be interrupted at any time (even after they have been issued on to the
+ * external bus), and re-issued after the interrupt occurs.
+ *
+ * If a FIFO is sitting on the end of the read, it will see two reads,
+ * when the core only sees one. The FIFO receives the read which is cancelled,
+ * and not delivered to the core.
+ *
+ * To solve this, interrupts are turned off before reads occur to I/O space.
+ * There are 3 versions of all these functions
+ *  - turns interrupts off every read (higher overhead, but lower latency)
+ *  - turns interrupts off every loop (low overhead, but longer latency)
+ *  - DMA version, which do not suffer from this issue. DMA versions have
+ *      different name (prefixed by dma_ ), and are located in
+ *      ../kernel/bfin_dma_5xx.c
+ * Using the dma related functions are recommended for transfering large
+ * buffers in/out of FIFOs.
+ */
+
+#define COMMON_INS(func, ops) \
+ENTRY(_ins##func) \
+	P0 = R0;	/* P0 = port */ \
+	CLI_OUTER;	/* 3 instructions before first read access */ \
+	P1 = R1;	/* P1 = address */ \
+	P2 = R2;	/* P2 = count */ \
+	SSYNC; \
+ \
+	LSETUP(1f, 2f) LC0 = P2; \
+	CLI_INNER; \
+	ops; \
+	STI_INNER; \
+ \
+	STI_OUTER; \
+	RTS; \
+ENDPROC(_ins##func)
+
+COMMON_INS(l, \
+	R0 = [P0]; \
+	[P1++] = R0; \
+)
+
+COMMON_INS(w, \
+	R0 = W[P0]; \
+	W[P1++] = R0; \
+)
+
+COMMON_INS(w_8, \
+	R0 = W[P0]; \
+	B[P1++] = R0; \
+	R0 = R0 >> 8; \
+	B[P1++] = R0; \
+)
+
+COMMON_INS(b, \
+	R0 = B[P0]; \
+	B[P1++] = R0; \
+)
+
+COMMON_INS(l_16, \
+	R0 = [P0]; \
+	W[P1++] = R0; \
+	R0 = R0 >> 16; \
+	W[P1++] = R0; \
+)
diff --git a/arch/blackfin/lib/kgdb.c b/arch/blackfin/lib/kgdb.c
new file mode 100644
index 0000000..bd62d71
--- /dev/null
+++ b/arch/blackfin/lib/kgdb.c
@@ -0,0 +1,423 @@
+/*
+ * U-boot - architecture specific kgdb code
+ *
+ * Copyright 2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <command.h>
+
+#include <kgdb.h>
+#include <asm/processor.h>
+#include <asm/mach-common/bits/core.h>
+#include "kgdb.h"
+#include <asm/deferred.h>
+#include <asm/traps.h>
+#include <asm/signal.h>
+
+void kgdb_enter(struct pt_regs *regs, kgdb_data *kdp)
+{
+	/* disable interrupts */
+	disable_interrupts();
+
+	/* reply to host that an exception has occurred */
+	kdp->sigval = kgdb_trap(regs);
+
+	/* send the PC and the Stack Pointer */
+	kdp->nregs = 2;
+	kdp->regs[0].num = BFIN_PC;
+	kdp->regs[0].val = regs->pc;
+
+	kdp->regs[1].num = BFIN_SP;
+	kdp->regs[1].val = (unsigned long)regs;
+
+}
+
+void kgdb_exit(struct pt_regs *regs, kgdb_data *kdp)
+{
+	if (kdp->extype & KGDBEXIT_WITHADDR)
+		printf("KGDBEXIT_WITHADDR\n");
+
+	switch (kdp->extype & KGDBEXIT_TYPEMASK) {
+	case KGDBEXIT_KILL:
+		printf("KGDBEXIT_KILL:\n");
+		break;
+	case KGDBEXIT_CONTINUE:
+		/* Make sure the supervisor single step bit is clear */
+		regs->syscfg &= ~1;
+		break;
+	case KGDBEXIT_SINGLE:
+		/* set the supervisor single step bit */
+		regs->syscfg |= 1;
+		break;
+	default:
+		printf("KGDBEXIT : %d\n", kdp->extype);
+	}
+
+	/* enable interrupts */
+	enable_interrupts();
+}
+
+int kgdb_trap(struct pt_regs *regs)
+{
+	/* ipend doesn't get filled in properly */
+	switch (regs->seqstat & EXCAUSE) {
+	case VEC_EXCPT01:
+		return SIGTRAP;
+	case VEC_EXCPT03:
+		return SIGSEGV;
+	case VEC_EXCPT02:
+		return SIGTRAP;
+	case VEC_EXCPT04 ... VEC_EXCPT15:
+		return SIGILL;
+	case VEC_STEP:
+		return SIGTRAP;
+	case VEC_OVFLOW:
+		return SIGTRAP;
+	case VEC_UNDEF_I:
+		return SIGILL;
+	case VEC_ILGAL_I:
+		return SIGILL;
+	case VEC_CPLB_VL:
+		return SIGSEGV;
+	case VEC_MISALI_D:
+		return SIGBUS;
+	case VEC_UNCOV:
+		return SIGILL;
+	case VEC_CPLB_MHIT:
+		return SIGSEGV;
+	case VEC_MISALI_I:
+		return SIGBUS;
+	case VEC_CPLB_I_VL:
+		return SIGBUS;
+	case VEC_CPLB_I_MHIT:
+		return SIGSEGV;
+	default:
+		return SIGBUS;
+	}
+}
+
+/*
+ * getregs - gets the pt_regs, and gives them to kgdb's buffer
+ */
+int kgdb_getregs(struct pt_regs *regs, char *buf, int max)
+{
+	unsigned long *gdb_regs = (unsigned long *)buf;
+
+	if (max < NUMREGBYTES)
+		kgdb_error(KGDBERR_NOSPACE);
+
+	if ((unsigned long)gdb_regs & 3)
+		kgdb_error(KGDBERR_ALIGNFAULT);
+
+	gdb_regs[BFIN_R0] = regs->r0;
+	gdb_regs[BFIN_R1] = regs->r1;
+	gdb_regs[BFIN_R2] = regs->r2;
+	gdb_regs[BFIN_R3] = regs->r3;
+	gdb_regs[BFIN_R4] = regs->r4;
+	gdb_regs[BFIN_R5] = regs->r5;
+	gdb_regs[BFIN_R6] = regs->r6;
+	gdb_regs[BFIN_R7] = regs->r7;
+	gdb_regs[BFIN_P0] = regs->p0;
+	gdb_regs[BFIN_P1] = regs->p1;
+	gdb_regs[BFIN_P2] = regs->p2;
+	gdb_regs[BFIN_P3] = regs->p3;
+	gdb_regs[BFIN_P4] = regs->p4;
+	gdb_regs[BFIN_P5] = regs->p5;
+	gdb_regs[BFIN_SP] = (unsigned long)regs;
+	gdb_regs[BFIN_FP] = regs->fp;
+	gdb_regs[BFIN_I0] = regs->i0;
+	gdb_regs[BFIN_I1] = regs->i1;
+	gdb_regs[BFIN_I2] = regs->i2;
+	gdb_regs[BFIN_I3] = regs->i3;
+	gdb_regs[BFIN_M0] = regs->m0;
+	gdb_regs[BFIN_M1] = regs->m1;
+	gdb_regs[BFIN_M2] = regs->m2;
+	gdb_regs[BFIN_M3] = regs->m3;
+	gdb_regs[BFIN_B0] = regs->b0;
+	gdb_regs[BFIN_B1] = regs->b1;
+	gdb_regs[BFIN_B2] = regs->b2;
+	gdb_regs[BFIN_B3] = regs->b3;
+	gdb_regs[BFIN_L0] = regs->l0;
+	gdb_regs[BFIN_L1] = regs->l1;
+	gdb_regs[BFIN_L2] = regs->l2;
+	gdb_regs[BFIN_L3] = regs->l3;
+	gdb_regs[BFIN_A0_DOT_X] = regs->a0x;
+	gdb_regs[BFIN_A0_DOT_W] = regs->a0w;
+	gdb_regs[BFIN_A1_DOT_X] = regs->a1x;
+	gdb_regs[BFIN_A1_DOT_W] = regs->a1w;
+	gdb_regs[BFIN_ASTAT] = regs->astat;
+	gdb_regs[BFIN_RETS] = regs->rets;
+	gdb_regs[BFIN_LC0] = regs->lc0;
+	gdb_regs[BFIN_LT0] = regs->lt0;
+	gdb_regs[BFIN_LB0] = regs->lb0;
+	gdb_regs[BFIN_LC1] = regs->lc1;
+	gdb_regs[BFIN_LT1] = regs->lt1;
+	gdb_regs[BFIN_LB1] = regs->lb1;
+	gdb_regs[BFIN_CYCLES] = 0;
+	gdb_regs[BFIN_CYCLES2] = 0;
+	gdb_regs[BFIN_USP] = regs->usp;
+	gdb_regs[BFIN_SEQSTAT] = regs->seqstat;
+	gdb_regs[BFIN_SYSCFG] = regs->syscfg;
+	gdb_regs[BFIN_RETI] = regs->pc;
+	gdb_regs[BFIN_RETX] = regs->retx;
+	gdb_regs[BFIN_RETN] = regs->retn;
+	gdb_regs[BFIN_RETE] = regs->rete;
+	gdb_regs[BFIN_PC] = regs->pc;
+	gdb_regs[BFIN_CC] = 0;
+	gdb_regs[BFIN_EXTRA1] = 0;
+	gdb_regs[BFIN_EXTRA2] = 0;
+	gdb_regs[BFIN_EXTRA3] = 0;
+	gdb_regs[BFIN_IPEND] = regs->ipend;
+
+	return NUMREGBYTES;
+}
+
+/*
+ * putreg - put kgdb's reg (regno) into the pt_regs
+ */
+void kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length)
+{
+	unsigned long *ptr = (unsigned long *)buf;
+
+	if (regno < 0 || regno > BFIN_NUM_REGS)
+		kgdb_error(KGDBERR_BADPARAMS);
+
+	if (length < 4)
+		kgdb_error(KGDBERR_NOSPACE);
+
+	if ((unsigned long)ptr & 3)
+		kgdb_error(KGDBERR_ALIGNFAULT);
+
+	switch (regno) {
+	case BFIN_R0:
+		regs->r0 = *ptr;
+		break;
+	case BFIN_R1:
+		regs->r1 = *ptr;
+		break;
+	case BFIN_R2:
+		regs->r2 = *ptr;
+		break;
+	case BFIN_R3:
+		regs->r3 = *ptr;
+		break;
+	case BFIN_R4:
+		regs->r4 = *ptr;
+		break;
+	case BFIN_R5:
+		regs->r5 = *ptr;
+		break;
+	case BFIN_R6:
+		regs->r6 = *ptr;
+		break;
+	case BFIN_R7:
+		regs->r7 = *ptr;
+		break;
+	case BFIN_P0:
+		regs->p0 = *ptr;
+		break;
+	case BFIN_P1:
+		regs->p1 = *ptr;
+		break;
+	case BFIN_P2:
+		regs->p2 = *ptr;
+		break;
+	case BFIN_P3:
+		regs->p3 = *ptr;
+		break;
+	case BFIN_P4:
+		regs->p4 = *ptr;
+		break;
+	case BFIN_P5:
+		regs->p5 = *ptr;
+		break;
+	case BFIN_SP:
+		regs->reserved = *ptr;
+		break;
+	case BFIN_FP:
+		regs->fp = *ptr;
+		break;
+	case BFIN_I0:
+		regs->i0 = *ptr;
+		break;
+	case BFIN_I1:
+		regs->i1 = *ptr;
+		break;
+	case BFIN_I2:
+		regs->i2 = *ptr;
+		break;
+	case BFIN_I3:
+		regs->i3 = *ptr;
+		break;
+	case BFIN_M0:
+		regs->m0 = *ptr;
+		break;
+	case BFIN_M1:
+		regs->m1 = *ptr;
+		break;
+	case BFIN_M2:
+		regs->m2 = *ptr;
+		break;
+	case BFIN_M3:
+		regs->m3 = *ptr;
+		break;
+	case BFIN_B0:
+		regs->b0 = *ptr;
+		break;
+	case BFIN_B1:
+		regs->b1 = *ptr;
+		break;
+	case BFIN_B2:
+		regs->b2 = *ptr;
+		break;
+	case BFIN_B3:
+		regs->b3 = *ptr;
+		break;
+	case BFIN_L0:
+		regs->l0 = *ptr;
+		break;
+	case BFIN_L1:
+		regs->l1 = *ptr;
+		break;
+	case BFIN_L2:
+		regs->l2 = *ptr;
+		break;
+	case BFIN_L3:
+		regs->l3 = *ptr;
+		break;
+	case BFIN_A0_DOT_X:
+		regs->a0x = *ptr;
+		break;
+	case BFIN_A0_DOT_W:
+		regs->a0w = *ptr;
+		break;
+	case BFIN_A1_DOT_X:
+		regs->a1x = *ptr;
+		break;
+	case BFIN_A1_DOT_W:
+		regs->a1w = *ptr;
+		break;
+	case BFIN_ASTAT:
+		regs->astat = *ptr;
+		break;
+	case BFIN_RETS:
+		regs->rets = *ptr;
+		break;
+	case BFIN_LC0:
+		regs->lc0 = *ptr;
+		break;
+	case BFIN_LT0:
+		regs->lt0 = *ptr;
+		break;
+	case BFIN_LB0:
+		regs->lb0 = *ptr;
+		break;
+	case BFIN_LC1:
+		regs->lc1 = *ptr;
+		break;
+	case BFIN_LT1:
+		regs->lt1 = *ptr;
+		break;
+	case BFIN_LB1:
+		regs->lb1 = *ptr;
+		break;
+/*
+  BFIN_CYCLES,
+  BFIN_CYCLES2,
+  BFIN_USP,
+  BFIN_SEQSTAT,
+  BFIN_SYSCFG,
+*/
+	case BFIN_RETX:
+		regs->retx = *ptr;
+		break;
+	case BFIN_RETN:
+		regs->retn = *ptr;
+		break;
+	case BFIN_RETE:
+		regs->rete = *ptr;
+		break;
+	case BFIN_PC:
+		regs->pc = *ptr;
+		break;
+
+	default:
+		kgdb_error(KGDBERR_BADPARAMS);
+	}
+}
+
+void kgdb_putregs(struct pt_regs *regs, char *buf, int length)
+{
+	unsigned long *gdb_regs = (unsigned long *)buf;
+
+	if (length != BFIN_NUM_REGS)
+		kgdb_error(KGDBERR_NOSPACE);
+
+	if ((unsigned long)gdb_regs & 3)
+		kgdb_error(KGDBERR_ALIGNFAULT);
+
+	regs->r0 = gdb_regs[BFIN_R0];
+	regs->r1 = gdb_regs[BFIN_R1];
+	regs->r2 = gdb_regs[BFIN_R2];
+	regs->r3 = gdb_regs[BFIN_R3];
+	regs->r4 = gdb_regs[BFIN_R4];
+	regs->r5 = gdb_regs[BFIN_R5];
+	regs->r6 = gdb_regs[BFIN_R6];
+	regs->r7 = gdb_regs[BFIN_R7];
+	regs->p0 = gdb_regs[BFIN_P0];
+	regs->p1 = gdb_regs[BFIN_P1];
+	regs->p2 = gdb_regs[BFIN_P2];
+	regs->p3 = gdb_regs[BFIN_P3];
+	regs->p4 = gdb_regs[BFIN_P4];
+	regs->p5 = gdb_regs[BFIN_P5];
+	regs->fp = gdb_regs[BFIN_FP];
+/*	regs->sp = gdb_regs[BFIN_ ]; */
+	regs->i0 = gdb_regs[BFIN_I0];
+	regs->i1 = gdb_regs[BFIN_I1];
+	regs->i2 = gdb_regs[BFIN_I2];
+	regs->i3 = gdb_regs[BFIN_I3];
+	regs->m0 = gdb_regs[BFIN_M0];
+	regs->m1 = gdb_regs[BFIN_M1];
+	regs->m2 = gdb_regs[BFIN_M2];
+	regs->m3 = gdb_regs[BFIN_M3];
+	regs->b0 = gdb_regs[BFIN_B0];
+	regs->b1 = gdb_regs[BFIN_B1];
+	regs->b2 = gdb_regs[BFIN_B2];
+	regs->b3 = gdb_regs[BFIN_B3];
+	regs->l0 = gdb_regs[BFIN_L0];
+	regs->l1 = gdb_regs[BFIN_L1];
+	regs->l2 = gdb_regs[BFIN_L2];
+	regs->l3 = gdb_regs[BFIN_L3];
+	regs->a0x = gdb_regs[BFIN_A0_DOT_X];
+	regs->a0w = gdb_regs[BFIN_A0_DOT_W];
+	regs->a1x = gdb_regs[BFIN_A1_DOT_X];
+	regs->a1w = gdb_regs[BFIN_A1_DOT_W];
+	regs->rets = gdb_regs[BFIN_RETS];
+	regs->lc0 = gdb_regs[BFIN_LC0];
+	regs->lt0 = gdb_regs[BFIN_LT0];
+	regs->lb0 = gdb_regs[BFIN_LB0];
+	regs->lc1 = gdb_regs[BFIN_LC1];
+	regs->lt1 = gdb_regs[BFIN_LT1];
+	regs->lb1 = gdb_regs[BFIN_LB1];
+	regs->usp = gdb_regs[BFIN_USP];
+	regs->syscfg = gdb_regs[BFIN_SYSCFG];
+	regs->retx = gdb_regs[BFIN_PC];
+	regs->retn = gdb_regs[BFIN_RETN];
+	regs->rete = gdb_regs[BFIN_RETE];
+	regs->pc = gdb_regs[BFIN_PC];
+
+#if 0	/* can't change these */
+	regs->astat = gdb_regs[BFIN_ASTAT];
+	regs->seqstat = gdb_regs[BFIN_SEQSTAT];
+	regs->ipend = gdb_regs[BFIN_IPEND];
+#endif
+
+}
+
+void kgdb_breakpoint(int argc, char *argv[])
+{
+	asm volatile ("excpt 0x1\n");
+}
diff --git a/arch/blackfin/lib/kgdb.h b/arch/blackfin/lib/kgdb.h
new file mode 100644
index 0000000..18f1f49
--- /dev/null
+++ b/arch/blackfin/lib/kgdb.h
@@ -0,0 +1,160 @@
+/* Blackfin KGDB header
+ *
+ * Copyright 2005-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __ASM_BLACKFIN_KGDB_H__
+#define __ASM_BLACKFIN_KGDB_H__
+
+/* gdb locks */
+#define KGDB_MAX_NO_CPUS 8
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers.
+ * At least NUMREGBYTES*2 are needed for register packets.
+ * Longer buffer is needed to list all threads.
+ */
+#define BUFMAX 2048
+
+enum regnames {
+  /* Core Registers */
+  BFIN_R0 = 0,
+  BFIN_R1,
+  BFIN_R2,
+  BFIN_R3,
+  BFIN_R4,
+  BFIN_R5,
+  BFIN_R6,
+  BFIN_R7,
+  BFIN_P0,
+  BFIN_P1,
+  BFIN_P2,
+  BFIN_P3,
+  BFIN_P4,
+  BFIN_P5,
+  BFIN_SP,
+  BFIN_FP,
+  BFIN_I0,
+  BFIN_I1,
+  BFIN_I2,
+  BFIN_I3,
+  BFIN_M0,
+  BFIN_M1,
+  BFIN_M2,
+  BFIN_M3,
+  BFIN_B0,
+  BFIN_B1,
+  BFIN_B2,
+  BFIN_B3,
+  BFIN_L0,
+  BFIN_L1,
+  BFIN_L2,
+  BFIN_L3,
+  BFIN_A0_DOT_X,
+  BFIN_A0_DOT_W,
+  BFIN_A1_DOT_X,
+  BFIN_A1_DOT_W,
+  BFIN_ASTAT,
+  BFIN_RETS,
+  BFIN_LC0,
+  BFIN_LT0,
+  BFIN_LB0,
+  BFIN_LC1,
+  BFIN_LT1,
+  BFIN_LB1,
+  BFIN_CYCLES,
+  BFIN_CYCLES2,
+  BFIN_USP,
+  BFIN_SEQSTAT,
+  BFIN_SYSCFG,
+  BFIN_RETI,
+  BFIN_RETX,
+  BFIN_RETN,
+  BFIN_RETE,
+
+  /* Pseudo Registers */
+  BFIN_PC,
+  BFIN_CC,
+  BFIN_EXTRA1,		/* Address of .text section.  */
+  BFIN_EXTRA2,		/* Address of .data section.  */
+  BFIN_EXTRA3,		/* Address of .bss section.  */
+  BFIN_FDPIC_EXEC,
+  BFIN_FDPIC_INTERP,
+
+  /* MMRs */
+  BFIN_IPEND,
+
+  /* LAST ENTRY SHOULD NOT BE CHANGED.  */
+  BFIN_NUM_REGS		/* The number of all registers.  */
+};
+
+/* Number of bytes of registers.  */
+#define NUMREGBYTES (BFIN_NUM_REGS * 4)
+
+static inline void arch_kgdb_breakpoint(void)
+{
+	asm volatile ("EXCPT 2;");
+}
+#define BREAK_INSTR_SIZE	2
+#define CACHE_FLUSH_IS_SAFE	1
+#define GDB_ADJUSTS_BREAK_OFFSET
+#define GDB_SKIP_HW_WATCH_TEST
+#define HW_INST_WATCHPOINT_NUM	6
+#define HW_WATCHPOINT_NUM	8
+#define TYPE_INST_WATCHPOINT	0
+#define TYPE_DATA_WATCHPOINT	1
+
+/* Instruction watchpoint address control register bits mask */
+#define WPPWR		0x1
+#define WPIREN01	0x2
+#define WPIRINV01	0x4
+#define WPIAEN0		0x8
+#define WPIAEN1		0x10
+#define WPICNTEN0	0x20
+#define WPICNTEN1	0x40
+#define EMUSW0		0x80
+#define EMUSW1		0x100
+#define WPIREN23	0x200
+#define WPIRINV23	0x400
+#define WPIAEN2		0x800
+#define WPIAEN3		0x1000
+#define WPICNTEN2	0x2000
+#define WPICNTEN3	0x4000
+#define EMUSW2		0x8000
+#define EMUSW3		0x10000
+#define WPIREN45	0x20000
+#define WPIRINV45	0x40000
+#define WPIAEN4		0x80000
+#define WPIAEN5		0x100000
+#define WPICNTEN4	0x200000
+#define WPICNTEN5	0x400000
+#define EMUSW4		0x800000
+#define EMUSW5		0x1000000
+#define WPAND		0x2000000
+
+/* Data watchpoint address control register bits mask */
+#define WPDREN01	0x1
+#define WPDRINV01	0x2
+#define WPDAEN0		0x4
+#define WPDAEN1		0x8
+#define WPDCNTEN0	0x10
+#define WPDCNTEN1	0x20
+
+#define WPDSRC0		0xc0
+#define WPDACC0_OFFSET	8
+#define WPDSRC1		0xc00
+#define WPDACC1_OFFSET	12
+
+/* Watchpoint status register bits mask */
+#define STATIA0		0x1
+#define STATIA1		0x2
+#define STATIA2		0x4
+#define STATIA3		0x8
+#define STATIA4		0x10
+#define STATIA5		0x20
+#define STATDA0		0x40
+#define STATDA1		0x80
+
+#endif
diff --git a/arch/blackfin/lib/memcmp.S b/arch/blackfin/lib/memcmp.S
new file mode 100644
index 0000000..6c834a7
--- /dev/null
+++ b/arch/blackfin/lib/memcmp.S
@@ -0,0 +1,103 @@
+/*
+ * File: memcmp.S
+ *
+ * Copyright 2004-2007 Analog Devices Inc.
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+.align 2
+
+/*
+ * C Library function MEMCMP
+ * R0 = First Address
+ * R1 = Second Address
+ * R2 = count
+ * Favours word aligned data.
+ */
+
+.globl _memcmp;
+.type _memcmp, STT_FUNC;
+_memcmp:
+	I1 = P3;
+	P0 = R0;			/* P0 = s1 address */
+	P3 = R1;			/* P3 = s2 Address  */
+	P2 = R2 ;			/* P2 = count */
+	CC = R2 <= 7(IU);
+	IF CC JUMP  .Ltoo_small;
+	I0 = R1;			/* s2 */
+	R1 = R1 | R0;		/* OR addresses together */
+	R1 <<= 30;		/* check bottom two bits */
+	CC =  AZ;			/* AZ set if zero. */
+	IF !CC JUMP  .Lbytes ;	/* Jump if addrs not aligned. */
+
+	P1 = P2 >> 2;		/* count = n/4 */
+	R3 =  3;
+	R2 = R2 & R3;		/* remainder */
+	P2 = R2;			/* set remainder */
+
+	LSETUP (.Lquad_loop_s , .Lquad_loop_e) LC0=P1;
+.Lquad_loop_s:
+	NOP;
+	R0 = [P0++];
+	R1 = [I0++];
+	CC = R0 == R1;
+	IF !CC JUMP .Lquad_different;
+.Lquad_loop_e:
+	NOP;
+
+	P3 = I0;			/* s2 */
+.Ltoo_small:
+	CC = P2 == 0;		/* Check zero count*/
+	IF CC JUMP .Lfinished;	/* very unlikely*/
+
+.Lbytes:
+	LSETUP (.Lbyte_loop_s , .Lbyte_loop_e) LC0=P2;
+.Lbyte_loop_s:
+	R1 = B[P3++](Z);	/* *s2 */
+	R0 = B[P0++](Z);	/* *s1 */
+	CC = R0 == R1;
+	IF !CC JUMP .Ldifferent;
+.Lbyte_loop_e:
+	NOP;
+
+.Ldifferent:
+	R0 = R0 - R1;
+	P3 = I1;
+	RTS;
+
+.Lquad_different:
+/* We've read two quads which don't match.
+ * Can't just compare them, because we're
+ * a little-endian machine, so the MSBs of
+ * the regs occur at later addresses in the
+ * string.
+ * Arrange to re-read those two quads again,
+ * byte-by-byte.
+ */
+	P0 += -4;		/* back up to the start of the */
+	P3 = I0;		/* quads, and increase the*/
+	P2 += 4;		/* remainder count*/
+	P3 += -4;
+	JUMP .Lbytes;
+
+.Lfinished:
+	R0 = 0;
+	P3 = I1;
+	RTS;
+
+.size _memcmp, .-_memcmp
diff --git a/arch/blackfin/lib/memcpy.S b/arch/blackfin/lib/memcpy.S
new file mode 100644
index 0000000..e6b359a
--- /dev/null
+++ b/arch/blackfin/lib/memcpy.S
@@ -0,0 +1,117 @@
+/*
+ * File: memcpy.S
+ *
+ * Copyright 2004-2007 Analog Devices Inc.
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+.align 2
+
+.globl _memcpy_ASM;
+.type _memcpy_ASM, STT_FUNC;
+_memcpy_ASM:
+	CC = R2 <=  0;	/* length not positive?*/
+	IF CC JUMP  .L_P1L2147483647;	/* Nothing to do */
+
+	P0 = R0 ;	/* dst*/
+	P1 = R1 ;	/* src*/
+	P2 = R2 ;	/* length */
+
+	/* check for overlapping data */
+	CC = R1 < R0;	/* src < dst */
+	IF !CC JUMP .Lno_overlap;
+	R3 = R1 + R2;
+	CC = R0 < R3;	/* and dst < src+len */
+	IF CC JUMP .Lhas_overlap;
+
+.Lno_overlap:
+	/* Check for aligned data.*/
+
+	R3 = R1 | R0;
+	R0 = 0x3;
+	R3 = R3 & R0;
+	CC = R3;	/* low bits set on either address? */
+	IF CC JUMP .Lnot_aligned;
+
+	/* Both addresses are word-aligned, so we can copy
+	at least part of the data using word copies.*/
+	P2 = P2 >> 2;
+	CC = P2 <= 2;
+	IF !CC JUMP .Lmore_than_seven;
+	/* less than eight bytes... */
+	P2 = R2;
+	LSETUP(.Lthree_start, .Lthree_end) LC0=P2;
+	R0 = R1;	/* setup src address for return */
+.Lthree_start:
+	R3 = B[P1++] (X);
+.Lthree_end:
+	B[P0++] = R3;
+
+	RTS;
+
+.Lmore_than_seven:
+	/* There's at least eight bytes to copy. */
+	P2 += -1;	/* because we unroll one iteration */
+	LSETUP(.Lword_loop, .Lword_loop) LC0=P2;
+	R0 = R1;
+	I1 = P1;
+	R3 = [I1++];
+.Lword_loop:
+	MNOP || [P0++] = R3 || R3 = [I1++];
+
+	[P0++] = R3;
+	/* Any remaining bytes to copy? */
+	R3 = 0x3;
+	R3 = R2 & R3;
+	CC = R3 == 0;
+	P1 = I1;	/* in case there's something left, */
+	IF !CC JUMP .Lbytes_left;
+	RTS;
+.Lbytes_left:	P2 = R3;
+.Lnot_aligned:
+	/* From here, we're copying byte-by-byte. */
+	LSETUP (.Lbyte_start , .Lbyte_end) LC0=P2;
+	R0 = R1;	/* Save src address for return */
+.Lbyte_start:
+	R1 = B[P1++] (X);
+.Lbyte_end:
+	B[P0++] = R1;
+
+.L_P1L2147483647:
+	RTS;
+
+.Lhas_overlap:
+/* Need to reverse the copying, because the
+ * dst would clobber the src.
+ * Don't bother to work out alignment for
+ * the reverse case.
+ */
+	R0 = R1;	/* save src for later. */
+	P0 = P0 + P2;
+	P0 += -1;
+	P1 = P1 + P2;
+	P1 += -1;
+	LSETUP(.Lover_start, .Lover_end) LC0=P2;
+.Lover_start:
+	R1 = B[P1--] (X);
+.Lover_end:
+	B[P0--] = R1;
+
+	RTS;
+
+.size _memcpy_ASM, .-_memcpy_ASM
diff --git a/arch/blackfin/lib/memmove.S b/arch/blackfin/lib/memmove.S
new file mode 100644
index 0000000..e385c4f
--- /dev/null
+++ b/arch/blackfin/lib/memmove.S
@@ -0,0 +1,96 @@
+/*
+ * File: memmove.S
+ *
+ * Copyright 2004-2007 Analog Devices Inc.
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+.align 2
+
+/*
+ * C Library function MEMMOVE
+ * R0 = To Address (leave unchanged to form result)
+ * R1 = From Address
+ * R2 = count
+ * Data may overlap
+ */
+
+.globl _memmove;
+.type _memmove, STT_FUNC;
+_memmove:
+	I1 = P3;
+	P0 = R0;                  /* P0 = To address */
+	P3 = R1;                  /* P3 = From Address */
+	P2 = R2 ;                 /* P2 = count */
+	CC = P2 == 0;             /* Check zero count*/
+	IF CC JUMP .Lfinished;    /* very unlikely */
+
+	CC = R1 < R0 (IU);        /* From < To */
+	IF !CC JUMP .Lno_overlap;
+	R3 = R1 + R2;
+	CC = R0 <= R3 (IU);       /* (From+len) >= To */
+	IF CC JUMP .Loverlap;
+.Lno_overlap:
+	R3 = 11;
+	CC = R2 <= R3;
+	IF CC JUMP  .Lbytes;
+	R3 = R1 | R0;             /* OR addresses together */
+	R3 <<= 30;                /* check bottom two bits */
+	CC =  AZ;                 /* AZ set if zero.*/
+	IF !CC JUMP  .Lbytes ;    /* Jump if addrs not aligned.*/
+
+	I0 = P3;
+	P1 = P2 >> 2;             /* count = n/4 */
+	P1 += -1;
+	R3 =  3;
+	R2 = R2 & R3;             /* remainder */
+	P2 = R2;                  /* set remainder */
+	R1 = [I0++];
+
+	LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1;
+.Lquad_loop: MNOP || [P0++] = R1 || R1 = [I0++];
+	[P0++] = R1;
+
+	CC = P2 == 0;             /* any remaining bytes? */
+	P3 = I0;                  /* Ammend P3 to updated ptr. */
+	IF !CC JUMP .Lbytes;
+	P3 = I1;
+	RTS;
+
+.Lbytes:     LSETUP (.Lbyte2_s , .Lbyte2_e) LC0=P2;
+.Lbyte2_s:   R1 = B[P3++](Z);
+.Lbyte2_e:   B[P0++] = R1;
+
+.Lfinished:  P3 = I1;
+	RTS;
+
+.Loverlap:
+	P2 += -1;
+	P0 = P0 + P2;
+	P3 = P3 + P2;
+	R1 = B[P3--] (Z);
+	CC = P2 == 0;
+	IF CC JUMP .Lno_loop;
+	LSETUP (.Lol_s, .Lol_e) LC0 = P2;
+.Lol_s:    B[P0--] = R1;
+.Lol_e:    R1 = B[P3--] (Z);
+.Lno_loop: B[P0] = R1;
+	P3 = I1;
+	RTS;
+
+.size _memmove, .-_memmove
diff --git a/arch/blackfin/lib/memset.S b/arch/blackfin/lib/memset.S
new file mode 100644
index 0000000..26f63cd
--- /dev/null
+++ b/arch/blackfin/lib/memset.S
@@ -0,0 +1,96 @@
+/*
+ * File: memset.S
+ *
+ * Copyright 2004-2007 Analog Devices Inc.
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+.align 2
+
+/*
+ * C Library function MEMSET
+ * R0 = address (leave unchanged to form result)
+ * R1 = filler byte
+ * R2 = count
+ * Favours word aligned data.
+ */
+
+.globl _memset;
+.type _memset, STT_FUNC;
+_memset:
+	P0 = R0 ;              /* P0 = address */
+	P2 = R2 ;              /* P2 = count   */
+	R3 = R0 + R2;          /* end          */
+	CC = R2 <= 7(IU);
+	IF CC JUMP  .Ltoo_small;
+	R1 = R1.B (Z);         /* R1 = fill char */
+	R2 =  3;
+	R2 = R0 & R2;          /* addr bottom two bits */
+	CC =  R2 == 0;             /* AZ set if zero.	*/
+	IF !CC JUMP  .Lforce_align ;  /* Jump if addr not aligned. */
+
+.Laligned:
+	P1 = P2 >> 2;          /* count = n/4        */
+	R2 = R1 <<  8;         /* create quad filler */
+	R2.L = R2.L + R1.L(NS);
+	R2.H = R2.L + R1.H(NS);
+	P2 = R3;
+
+	LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1;
+.Lquad_loop:
+	[P0++] = R2;
+
+	CC = P0 == P2;
+	IF !CC JUMP .Lbytes_left;
+	RTS;
+
+.Lbytes_left:
+	R2 = R3;                /* end point */
+	R3 = P0;                /* current position */
+	R2 = R2 - R3;           /* bytes left */
+	P2 = R2;
+
+.Ltoo_small:
+	CC = P2 == 0;           /* Check zero count */
+	IF CC JUMP .Lfinished;    /* Unusual */
+
+.Lbytes:
+	LSETUP (.Lbyte_loop , .Lbyte_loop) LC0=P2;
+.Lbyte_loop:
+	B[P0++] = R1;
+
+.Lfinished:
+	RTS;
+
+.Lforce_align:
+	CC = BITTST (R0, 0);  /* odd byte */
+	R0 = 4;
+	R0 = R0 - R2;
+	P1 = R0;
+	R0 = P0;		    /* Recover return address */
+	IF !CC JUMP .Lskip1;
+	B[P0++] = R1;
+.Lskip1:
+	CC = R2 <= 2;          /* 2 bytes */
+	P2 -= P1;              /* reduce count */
+	IF !CC JUMP .Laligned;
+	B[P0++] = R1;
+	B[P0++] = R1;
+	JUMP .Laligned;
+
+.size _memset, .-_memset
diff --git a/arch/blackfin/lib/muldi3.c b/arch/blackfin/lib/muldi3.c
new file mode 100644
index 0000000..bf1ca53
--- /dev/null
+++ b/arch/blackfin/lib/muldi3.c
@@ -0,0 +1,92 @@
+/*
+ * U-boot - muldi3.c contains routines for mult and div
+ *
+ * Copyright (c) 2005-2007 Analog Devices Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* Generic function got from GNU gcc package, libgcc2.c */
+#ifndef SI_TYPE_SIZE
+#define SI_TYPE_SIZE 32
+#endif
+#define __ll_B (1L << (SI_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
+#define __ll_highpart(t) ((USItype) (t) / __ll_B)
+#define BITS_PER_UNIT 8
+
+#if !defined (umul_ppmm)
+#define umul_ppmm(w1, w0, u, v)						\
+do {									\
+	USItype __x0, __x1, __x2, __x3;					\
+	USItype __ul, __vl, __uh, __vh;					\
+									\
+	__ul = __ll_lowpart (u);					\
+	__uh = __ll_highpart (u);					\
+	__vl = __ll_lowpart (v);					\
+	__vh = __ll_highpart (v);					\
+									\
+	__x0 = (USItype) __ul * __vl;					\
+	__x1 = (USItype) __ul * __vh;					\
+	__x2 = (USItype) __uh * __vl;					\
+	__x3 = (USItype) __uh * __vh;					\
+									\
+	__x1 += __ll_highpart (__x0);/* this can't give carry */	\
+	__x1 += __x2;	/* but this indeed can */			\
+	if (__x1 < __x2)	/* did we get it? */			\
+		__x3 += __ll_B;	/* yes, add it in the proper pos. */	\
+									\
+	(w1) = __x3 + __ll_highpart (__x1);				\
+	(w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0);	\
+} while (0)
+#endif
+
+#if !defined (__umulsidi3)
+#define __umulsidi3(u, v)						\
+	({DIunion __w;							\
+	umul_ppmm (__w.s.high, __w.s.low, u, v);			\
+	__w.ll; })
+#endif
+
+typedef unsigned int USItype __attribute__ ((mode(SI)));
+typedef int SItype __attribute__ ((mode(SI)));
+typedef int DItype __attribute__ ((mode(DI)));
+typedef int word_type __attribute__ ((mode(__word__)));
+
+struct DIstruct {
+	SItype low, high;
+};
+typedef union {
+	struct DIstruct s;
+	DItype ll;
+} DIunion;
+
+DItype __muldi3(DItype u, DItype v)
+{
+	DIunion w;
+	DIunion uu, vv;
+
+	uu.ll = u, vv.ll = v;
+	/*  panic("kernel panic for __muldi3"); */
+	w.ll = __umulsidi3(uu.s.low, vv.s.low);
+	w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
+		     + (USItype) uu.s.high * (USItype) vv.s.low);
+
+	return w.ll;
+}
diff --git a/arch/blackfin/lib/outs.S b/arch/blackfin/lib/outs.S
new file mode 100644
index 0000000..90c6033
--- /dev/null
+++ b/arch/blackfin/lib/outs.S
@@ -0,0 +1,60 @@
+/*
+ * Implementation of outs{bwl} for BlackFin processors using zero overhead loops.
+ *
+ * Copyright 2005-2009 Analog Devices Inc.
+ *                2005 BuyWays BV
+ *                      Bas Vermeulen <bas@buyways.nl>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <asm/linkage.h>
+
+.align 2
+
+ENTRY(_outsl)
+	P0 = R0;	/* P0 = port */
+	P1 = R1;	/* P1 = address */
+	P2 = R2;	/* P2 = count */
+
+	LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
+.Llong_loop_s: R0 = [P1++];
+.Llong_loop_e: [P0] = R0;
+	RTS;
+ENDPROC(_outsl)
+
+ENTRY(_outsw)
+	P0 = R0;	/* P0 = port */
+	P1 = R1;	/* P1 = address */
+	P2 = R2;	/* P2 = count */
+
+	LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
+.Lword_loop_s: R0 = W[P1++];
+.Lword_loop_e: W[P0] = R0;
+	RTS;
+ENDPROC(_outsw)
+
+ENTRY(_outsb)
+	P0 = R0;	/* P0 = port */
+	P1 = R1;	/* P1 = address */
+	P2 = R2;	/* P2 = count */
+
+	LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
+.Lbyte_loop_s: R0 = B[P1++];
+.Lbyte_loop_e: B[P0] = R0;
+	RTS;
+ENDPROC(_outsb)
+
+ENTRY(_outsw_8)
+	P0 = R0;	/* P0 = port */
+	P1 = R1;	/* P1 = address */
+	P2 = R2;	/* P2 = count */
+
+	LSETUP( .Lword8_loop_s, .Lword8_loop_e) LC0 = P2;
+.Lword8_loop_s: R1 = B[P1++];
+		R0 = B[P1++];
+		R0 = R0 << 8;
+		R0 = R0 + R1;
+.Lword8_loop_e: W[P0] = R0;
+	RTS;
+ENDPROC(_outsw_8)
diff --git a/arch/blackfin/lib/post.c b/arch/blackfin/lib/post.c
new file mode 100644
index 0000000..faf6b96
--- /dev/null
+++ b/arch/blackfin/lib/post.c
@@ -0,0 +1,421 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <stdio_dev.h>
+#include <watchdog.h>
+#include <post.h>
+
+#ifdef CONFIG_LOGBUFFER
+#include <logbuff.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define POST_MAX_NUMBER		32
+
+#define BOOTMODE_MAGIC	0xDEAD0000
+
+int post_init_f(void)
+{
+	int res = 0;
+	unsigned int i;
+
+	for (i = 0; i < post_list_size; i++) {
+		struct post_test *test = post_list + i;
+
+		if (test->init_f && test->init_f()) {
+			res = -1;
+		}
+	}
+
+	gd->post_init_f_time = post_time_ms(0);
+	if (!gd->post_init_f_time) {
+		printf
+		    ("post/post.c: post_time_ms seems not to be implemented\n");
+	}
+
+	return res;
+}
+
+void post_bootmode_init(void)
+{
+	int bootmode = post_bootmode_get(0);
+	int newword;
+
+	if (post_hotkeys_pressed() && !(bootmode & POST_POWERTEST)) {
+		newword = BOOTMODE_MAGIC | POST_SLOWTEST;
+	} else if (bootmode == 0) {
+		newword = BOOTMODE_MAGIC | POST_POWERON;
+	} else if (bootmode == POST_POWERON || bootmode == POST_SLOWTEST) {
+		newword = BOOTMODE_MAGIC | POST_NORMAL;
+	} else {
+		/* Use old value */
+		newword = post_word_load() & ~POST_COLDBOOT;
+	}
+
+	if (bootmode == 0) {
+		/* We are booting after power-on */
+		newword |= POST_COLDBOOT;
+	}
+
+	post_word_store(newword);
+
+	/* Reset activity record */
+	gd->post_log_word = 0;
+}
+
+int post_bootmode_get(unsigned int *last_test)
+{
+	unsigned long word = post_word_load();
+	int bootmode;
+
+	if ((word & 0xFFFF0000) != BOOTMODE_MAGIC) {
+		return 0;
+	}
+
+	bootmode = word & 0x7F;
+
+	if (last_test && (bootmode & POST_POWERTEST)) {
+		*last_test = (word >> 8) & 0xFF;
+	}
+
+	return bootmode;
+}
+
+/* POST tests run before relocation only mark status bits .... */
+static void post_log_mark_start(unsigned long testid)
+{
+	gd->post_log_word |= (testid) << 16;
+}
+
+static void post_log_mark_succ(unsigned long testid)
+{
+	gd->post_log_word |= testid;
+}
+
+/* ... and the messages are output once we are relocated */
+void post_output_backlog(void)
+{
+	int j;
+
+	for (j = 0; j < post_list_size; j++) {
+		if (gd->post_log_word & (post_list[j].testid << 16)) {
+			post_log("POST %s ", post_list[j].cmd);
+			if (gd->post_log_word & post_list[j].testid)
+				post_log("PASSED\n");
+			else {
+				post_log("FAILED\n");
+				show_boot_progress (-31);
+			}
+		}
+	}
+}
+
+static void post_bootmode_test_on(unsigned int last_test)
+{
+	unsigned long word = post_word_load();
+
+	word |= POST_POWERTEST;
+
+	word |= (last_test & 0xFF) << 8;
+
+	post_word_store(word);
+}
+
+static void post_bootmode_test_off(void)
+{
+	unsigned long word = post_word_load();
+
+	word &= ~POST_POWERTEST;
+
+	post_word_store(word);
+}
+
+static void post_get_flags(int *test_flags)
+{
+	int flag[] = { POST_POWERON, POST_NORMAL, POST_SLOWTEST };
+	char *var[] = { "post_poweron", "post_normal", "post_slowtest" };
+	int varnum = sizeof(var) / sizeof(var[0]);
+	char list[128];		/* long enough for POST list */
+	char *name;
+	char *s;
+	int last;
+	int i, j;
+
+	for (j = 0; j < post_list_size; j++) {
+		test_flags[j] = post_list[j].flags;
+	}
+
+	for (i = 0; i < varnum; i++) {
+		if (getenv_r(var[i], list, sizeof(list)) <= 0)
+			continue;
+
+		for (j = 0; j < post_list_size; j++) {
+			test_flags[j] &= ~flag[i];
+		}
+
+		last = 0;
+		name = list;
+		while (!last) {
+			while (*name && *name == ' ')
+				name++;
+			if (*name == 0)
+				break;
+			s = name + 1;
+			while (*s && *s != ' ')
+				s++;
+			if (*s == 0)
+				last = 1;
+			else
+				*s = 0;
+
+			for (j = 0; j < post_list_size; j++) {
+				if (strcmp(post_list[j].cmd, name) == 0) {
+					test_flags[j] |= flag[i];
+					break;
+				}
+			}
+
+			if (j == post_list_size) {
+				printf("No such test: %s\n", name);
+			}
+
+			name = s + 1;
+		}
+	}
+
+	for (j = 0; j < post_list_size; j++) {
+		if (test_flags[j] & POST_POWERON) {
+			test_flags[j] |= POST_SLOWTEST;
+		}
+	}
+}
+
+static int post_run_single(struct post_test *test,
+			   int test_flags, int flags, unsigned int i)
+{
+	if ((flags & test_flags & POST_ALWAYS) &&
+	    (flags & test_flags & POST_MEM)) {
+		WATCHDOG_RESET();
+
+		if (!(flags & POST_REBOOT)) {
+			if ((test_flags & POST_REBOOT)
+			    && !(flags & POST_MANUAL)) {
+				post_bootmode_test_on(i);
+			}
+
+			if (test_flags & POST_PREREL)
+				post_log_mark_start(test->testid);
+			else
+				post_log("POST %s ", test->cmd);
+		}
+
+		if (test_flags & POST_PREREL) {
+			if ((*test->test) (flags) == 0)
+				post_log_mark_succ(test->testid);
+		} else {
+			if ((*test->test) (flags) != 0) {
+				post_log("FAILED\n");
+				show_boot_progress (-32);
+			} else
+				post_log("PASSED\n");
+		}
+
+		if ((test_flags & POST_REBOOT) && !(flags & POST_MANUAL)) {
+			post_bootmode_test_off();
+		}
+
+		return 0;
+	} else {
+		return -1;
+	}
+}
+
+int post_run(char *name, int flags)
+{
+	unsigned int i;
+	int test_flags[POST_MAX_NUMBER];
+
+	post_get_flags(test_flags);
+
+	if (name == NULL) {
+		unsigned int last;
+
+		if (post_bootmode_get(&last) & POST_POWERTEST) {
+			if (last < post_list_size &&
+			    (flags & test_flags[last] & POST_ALWAYS) &&
+			    (flags & test_flags[last] & POST_MEM)) {
+
+				post_run_single(post_list + last,
+						test_flags[last],
+						flags | POST_REBOOT, last);
+
+				for (i = last + 1; i < post_list_size; i++) {
+					post_run_single(post_list + i,
+							test_flags[i],
+							flags, i);
+				}
+			}
+		} else {
+			for (i = 0; i < post_list_size; i++) {
+				post_run_single(post_list + i,
+						test_flags[i], flags, i);
+			}
+		}
+
+		return 0;
+	} else {
+		for (i = 0; i < post_list_size; i++) {
+			if (strcmp(post_list[i].cmd, name) == 0)
+				break;
+		}
+
+		if (i < post_list_size) {
+			return post_run_single(post_list + i,
+					       test_flags[i], flags, i);
+		} else {
+			return -1;
+		}
+	}
+}
+
+static int post_info_single(struct post_test *test, int full)
+{
+	if (test->flags & POST_MANUAL) {
+		if (full)
+			printf("%s - %s\n"
+			       "  %s\n", test->cmd, test->name, test->desc);
+		else
+			printf("  %-15s - %s\n", test->cmd, test->name);
+
+		return 0;
+	} else {
+		return -1;
+	}
+}
+
+int post_info(char *name)
+{
+	unsigned int i;
+
+	if (name == NULL) {
+		for (i = 0; i < post_list_size; i++) {
+			post_info_single(post_list + i, 0);
+		}
+
+		return 0;
+	} else {
+		for (i = 0; i < post_list_size; i++) {
+			if (strcmp(post_list[i].cmd, name) == 0)
+				break;
+		}
+
+		if (i < post_list_size) {
+			return post_info_single(post_list + i, 1);
+		} else {
+			return -1;
+		}
+	}
+}
+
+int post_log(char *format, ...)
+{
+	va_list args;
+	uint i;
+	char printbuffer[CONFIG_SYS_PBSIZE];
+
+	va_start(args, format);
+
+	/* For this to work, printbuffer must be larger than
+	 * anything we ever want to print.
+	 */
+	i = vsprintf(printbuffer, format, args);
+	va_end(args);
+
+#ifdef CONFIG_LOGBUFFER
+	/* Send to the logbuffer */
+	logbuff_log(printbuffer);
+#else
+	/* Send to the stdout file */
+	puts(printbuffer);
+#endif
+
+	return 0;
+}
+
+void post_reloc(void)
+{
+	unsigned int i;
+
+	/*
+	 * We have to relocate the test table manually
+	 */
+	for (i = 0; i < post_list_size; i++) {
+		ulong addr;
+		struct post_test *test = post_list + i;
+
+		if (test->name) {
+			addr = (ulong) (test->name) + gd->reloc_off;
+			test->name = (char *)addr;
+		}
+
+		if (test->cmd) {
+			addr = (ulong) (test->cmd) + gd->reloc_off;
+			test->cmd = (char *)addr;
+		}
+
+		if (test->desc) {
+			addr = (ulong) (test->desc) + gd->reloc_off;
+			test->desc = (char *)addr;
+		}
+
+		if (test->test) {
+			addr = (ulong) (test->test) + gd->reloc_off;
+			test->test = (int (*)(int flags))addr;
+		}
+
+		if (test->init_f) {
+			addr = (ulong) (test->init_f) + gd->reloc_off;
+			test->init_f = (int (*)(void))addr;
+		}
+
+		if (test->reloc) {
+			addr = (ulong) (test->reloc) + gd->reloc_off;
+			test->reloc = (void (*)(void))addr;
+
+			test->reloc();
+		}
+	}
+}
+
+/*
+ * Some tests (e.g. SYSMON) need the time when post_init_f started,
+ * but we cannot use get_timer() at this point.
+ *
+ * On PowerPC we implement it using the timebase register.
+ */
+unsigned long post_time_ms(unsigned long base)
+{
+	return (unsigned long)get_ticks() / (get_tbclk() / CONFIG_SYS_HZ) - base;
+}
diff --git a/arch/blackfin/lib/string.c b/arch/blackfin/lib/string.c
new file mode 100644
index 0000000..e344d3b
--- /dev/null
+++ b/arch/blackfin/lib/string.c
@@ -0,0 +1,274 @@
+/*
+ * U-boot - string.c Contains library routines.
+ *
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/blackfin.h>
+#include <asm/io.h>
+#include <asm/mach-common/bits/dma.h>
+
+char *strcpy(char *dest, const char *src)
+{
+	char *xdest = dest;
+	char temp = 0;
+
+	__asm__ __volatile__ (
+		"1:\t%2 = B [%1++] (Z);\n\t"
+		"B [%0++] = %2;\n\t"
+		"CC = %2;\n\t"
+		"if cc jump 1b (bp);\n"
+		: "=a"(dest), "=a"(src), "=d"(temp)
+		: "0"(dest), "1"(src), "2"(temp)
+		: "memory");
+
+	return xdest;
+}
+
+char *strncpy(char *dest, const char *src, size_t n)
+{
+	char *xdest = dest;
+	char temp = 0;
+
+	if (n == 0)
+		return xdest;
+
+	__asm__ __volatile__ (
+		"1:\t%3 = B [%1++] (Z);\n\t"
+		"B [%0++] = %3;\n\t"
+		"CC = %3;\n\t"
+		"if ! cc jump 2f;\n\t"
+		"%2 += -1;\n\t"
+		"CC = %2 == 0;\n\t"
+		"if ! cc jump 1b (bp);\n"
+		"2:\n"
+		: "=a"(dest), "=a"(src), "=da"(n), "=d"(temp)
+		: "0"(dest), "1"(src), "2"(n), "3"(temp)
+		: "memory");
+
+	return xdest;
+}
+
+int strcmp(const char *cs, const char *ct)
+{
+	char __res1, __res2;
+
+	__asm__ (
+		"1:\t%2 = B[%0++] (Z);\n\t"	/* get *cs */
+		"%3 = B[%1++] (Z);\n\t"	/* get *ct */
+		"CC = %2 == %3;\n\t"	/* compare a byte */
+		"if ! cc jump 2f;\n\t"	/* not equal, break out */
+		"CC = %2;\n\t"	/* at end of cs? */
+		"if cc jump 1b (bp);\n\t"	/* no, keep going */
+		"jump.s 3f;\n"	/* strings are equal */
+		"2:\t%2 = %2 - %3;\n"	/* *cs - *ct */
+		"3:\n"
+		: "=a"(cs), "=a"(ct), "=d"(__res1), "=d"(__res2)
+		: "0"(cs), "1"(ct));
+
+	return __res1;
+}
+
+int strncmp(const char *cs, const char *ct, size_t count)
+{
+	char __res1, __res2;
+
+	if (!count)
+		return 0;
+
+	__asm__(
+		"1:\t%3 = B[%0++] (Z);\n\t"	/* get *cs */
+		"%4 = B[%1++] (Z);\n\t"	/* get *ct */
+		"CC = %3 == %4;\n\t"	/* compare a byte */
+		"if ! cc jump 3f;\n\t"	/* not equal, break out */
+		"CC = %3;\n\t"	/* at end of cs? */
+		"if ! cc jump 4f;\n\t"	/* yes, all done */
+		"%2 += -1;\n\t"	/* no, adjust count */
+		"CC = %2 == 0;\n\t" "if ! cc jump 1b;\n"	/* more to do, keep going */
+		"2:\t%3 = 0;\n\t"	/* strings are equal */
+		"jump.s    4f;\n" "3:\t%3 = %3 - %4;\n"	/* *cs - *ct */
+		"4:"
+		: "=a"(cs), "=a"(ct), "=da"(count), "=d"(__res1), "=d"(__res2)
+		: "0"(cs), "1"(ct), "2"(count));
+
+	return __res1;
+}
+
+#ifdef bfin_write_MDMA1_D0_IRQ_STATUS
+# define bfin_write_MDMA_D0_IRQ_STATUS bfin_write_MDMA1_D0_IRQ_STATUS
+# define bfin_write_MDMA_D0_START_ADDR bfin_write_MDMA1_D0_START_ADDR
+# define bfin_write_MDMA_D0_X_COUNT    bfin_write_MDMA1_D0_X_COUNT
+# define bfin_write_MDMA_D0_X_MODIFY   bfin_write_MDMA1_D0_X_MODIFY
+# define bfin_write_MDMA_D0_CONFIG     bfin_write_MDMA1_D0_CONFIG
+# define bfin_write_MDMA_S0_START_ADDR bfin_write_MDMA1_S0_START_ADDR
+# define bfin_write_MDMA_S0_X_COUNT    bfin_write_MDMA1_S0_X_COUNT
+# define bfin_write_MDMA_S0_X_MODIFY   bfin_write_MDMA1_S0_X_MODIFY
+# define bfin_write_MDMA_S0_CONFIG     bfin_write_MDMA1_S0_CONFIG
+# define bfin_write_MDMA_D0_IRQ_STATUS bfin_write_MDMA1_D0_IRQ_STATUS
+# define bfin_read_MDMA_D0_IRQ_STATUS  bfin_read_MDMA1_D0_IRQ_STATUS
+#endif
+/* This version misbehaves for count values of 0 and 2^16+.
+ * Perhaps we should detect that ?  Nowhere do we actually
+ * use dma memcpy for those types of lengths though ...
+ */
+void dma_memcpy_nocache(void *dst, const void *src, size_t count)
+{
+	uint16_t wdsize, mod;
+
+	/* Disable DMA in case it's still running (older u-boot's did not
+	 * always turn them off).  Do it before the if statement below so
+	 * we can be cheap and not do a SSYNC() due to the forced abort.
+	 */
+	bfin_write_MDMA_D0_CONFIG(0);
+	bfin_write_MDMA_S0_CONFIG(0);
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_RUN | DMA_DONE | DMA_ERR);
+
+	/* Scratchpad cannot be a DMA source or destination */
+	if (((unsigned long)src >= L1_SRAM_SCRATCH &&
+	     (unsigned long)src < L1_SRAM_SCRATCH_END) ||
+	    ((unsigned long)dst >= L1_SRAM_SCRATCH &&
+	     (unsigned long)dst < L1_SRAM_SCRATCH_END))
+		hang();
+
+	if (((unsigned long)dst | (unsigned long)src | count) & 0x1) {
+		wdsize = WDSIZE_8;
+		mod = 1;
+	} else if (((unsigned long)dst | (unsigned long)src | count) & 0x2) {
+		wdsize = WDSIZE_16;
+		count >>= 1;
+		mod = 2;
+	} else {
+		wdsize = WDSIZE_32;
+		count >>= 2;
+		mod = 4;
+	}
+
+	/* Copy sram functions from sdram to sram */
+	/* Setup destination start address */
+	bfin_write_MDMA_D0_START_ADDR(dst);
+	/* Setup destination xcount */
+	bfin_write_MDMA_D0_X_COUNT(count);
+	/* Setup destination xmodify */
+	bfin_write_MDMA_D0_X_MODIFY(mod);
+
+	/* Setup Source start address */
+	bfin_write_MDMA_S0_START_ADDR(src);
+	/* Setup Source xcount */
+	bfin_write_MDMA_S0_X_COUNT(count);
+	/* Setup Source xmodify */
+	bfin_write_MDMA_S0_X_MODIFY(mod);
+
+	/* Enable source DMA */
+	bfin_write_MDMA_S0_CONFIG(wdsize | DMAEN);
+	bfin_write_MDMA_D0_CONFIG(wdsize | DMAEN | WNR | DI_EN);
+	SSYNC();
+
+	while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
+		continue;
+
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_RUN | DMA_DONE | DMA_ERR);
+	bfin_write_MDMA_D0_CONFIG(0);
+	bfin_write_MDMA_S0_CONFIG(0);
+}
+/* We should do a dcache invalidate on the destination after the dma, but since
+ * we lack such hardware capability, we'll flush/invalidate the destination
+ * before the dma and bank on the idea that u-boot is single threaded.
+ */
+void *dma_memcpy(void *dst, const void *src, size_t count)
+{
+	if (dcache_status()) {
+		blackfin_dcache_flush_range(src, src + count);
+		blackfin_dcache_flush_invalidate_range(dst, dst + count);
+	}
+
+	dma_memcpy_nocache(dst, src, count);
+
+	if (icache_status())
+		blackfin_icache_flush_range(dst, dst + count);
+
+	return dst;
+}
+
+/*
+ * memcpy - Copy one area of memory to another
+ * @dest: Where to copy to
+ * @src: Where to copy from
+ * @count: The size of the area.
+ *
+ * We need to have this wrapper in memcpy() as common code may call memcpy()
+ * to load up L1 regions.  Consider loading an ELF which has sections with
+ * LMA's pointing to L1.  The common code ELF loader will simply use memcpy()
+ * to move the ELF's sections into the right place.  We need to catch that
+ * here and redirect to dma_memcpy().
+ */
+extern void *memcpy_ASM(void *dst, const void *src, size_t count);
+void *memcpy(void *dst, const void *src, size_t count)
+{
+	if (!count)
+		return dst;
+
+#ifdef CONFIG_CMD_KGDB
+	if (src >= (void *)SYSMMR_BASE) {
+		if (count == 2 && (unsigned long)src % 2 == 0) {
+			u16 mmr = bfin_read16(src);
+			memcpy(dst, &mmr, sizeof(mmr));
+			return dst;
+		}
+		if (count == 4 && (unsigned long)src % 4 == 0) {
+			u32 mmr = bfin_read32(src);
+			memcpy(dst, &mmr, sizeof(mmr));
+			return dst;
+		}
+		/* Failed for some reason */
+		memset(dst, 0xad, count);
+		return dst;
+	}
+	if (dst >= (void *)SYSMMR_BASE) {
+		if (count == 2 && (unsigned long)dst % 2 == 0) {
+			u16 mmr;
+			memcpy(&mmr, src, sizeof(mmr));
+			bfin_write16(dst, mmr);
+			return dst;
+		}
+		if (count == 4 && (unsigned long)dst % 4 == 0) {
+			u32 mmr;
+			memcpy(&mmr, src, sizeof(mmr));
+			bfin_write32(dst, mmr);
+			return dst;
+		}
+		/* Failed for some reason */
+		memset(dst, 0xad, count);
+		return dst;
+	}
+#endif
+
+	/* if L1 is the source or dst, use DMA */
+	if (addr_bfin_on_chip_mem(dst) || addr_bfin_on_chip_mem(src))
+		return dma_memcpy(dst, src, count);
+	else
+		/* No L1 is involved, so just call regular memcpy */
+		return memcpy_ASM(dst, src, count);
+}
diff --git a/arch/blackfin/lib/tests.c b/arch/blackfin/lib/tests.c
new file mode 100644
index 0000000..bf7fba0
--- /dev/null
+++ b/arch/blackfin/lib/tests.c
@@ -0,0 +1,250 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Be sure to mark tests to be run before relocation as such with the
+ * CONFIG_SYS_POST_PREREL flag so that logging is done correctly if the
+ * logbuffer support is enabled.
+ */
+
+#include <common.h>
+#include <config.h>
+
+#include <post.h>
+#define CONFIG_SYS_POST_FLASH  0x00004000
+#define CONFIG_SYS_POST_LED    0x00008000
+#define CONFIG_SYS_POST_BUTTON 0x00010000
+
+extern int cache_post_test(int flags);
+extern int watchdog_post_test(int flags);
+extern int i2c_post_test(int flags);
+extern int rtc_post_test(int flags);
+extern int memory_post_test(int flags);
+extern int cpu_post_test(int flags);
+extern int uart_post_test(int flags);
+extern int ether_post_test(int flags);
+extern int spi_post_test(int flags);
+extern int usb_post_test(int flags);
+extern int spr_post_test(int flags);
+extern int sysmon_post_test(int flags);
+extern int dsp_post_test(int flags);
+extern int codec_post_test(int flags);
+
+extern int sysmon_init_f(void);
+
+extern void sysmon_reloc(void);
+
+extern int flash_post_test(int flags);
+extern int led_post_test(int flags);
+extern int button_post_test(int flags);
+
+struct post_test post_list[] = {
+#if CONFIG_POST & CONFIG_SYS_POST_CACHE
+	{
+	 "Cache test",
+	 "cache",
+	 "This test verifies the CPU cache operation.",
+	 POST_RAM | POST_ALWAYS,
+	 &cache_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_CACHE},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_WATCHDOG
+	{
+	 "Watchdog timer test",
+	 "watchdog",
+	 "This test checks the watchdog timer.",
+	 POST_RAM | POST_POWERON | POST_SLOWTEST | POST_MANUAL | POST_REBOOT,
+	 &watchdog_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_WATCHDOG},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_I2C
+	{
+	 "I2C test",
+	 "i2c",
+	 "This test verifies the I2C operation.",
+	 POST_RAM | POST_ALWAYS,
+	 &i2c_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_I2C},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_RTC
+	{
+	 "RTC test",
+	 "rtc",
+	 "This test verifies the RTC operation.",
+	 POST_RAM | POST_SLOWTEST | POST_MANUAL,
+	 &rtc_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_RTC},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_MEMORY
+	{
+	 "Memory test",
+	 "memory",
+	 "This test checks RAM.",
+	 POST_ROM | POST_POWERON | POST_SLOWTEST | POST_PREREL,
+	 &memory_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_MEMORY},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_CPU
+	{
+	 "CPU test",
+	 "cpu",
+	 "This test verifies the arithmetic logic unit of" " CPU.",
+	 POST_RAM | POST_ALWAYS,
+	 &cpu_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_CPU},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_UART
+	{
+	 "UART test",
+	 "uart",
+	 "This test verifies the UART operation.",
+	 POST_RAM | POST_SLOWTEST | POST_MANUAL,
+	 &uart_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_UART},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_ETHER
+	{
+	 "ETHERNET test",
+	 "ethernet",
+	 "This test verifies the ETHERNET operation.",
+	 POST_RAM | POST_ALWAYS | POST_MANUAL,
+	 &ether_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_ETHER},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_SPI
+	{
+	 "SPI test",
+	 "spi",
+	 "This test verifies the SPI operation.",
+	 POST_RAM | POST_ALWAYS | POST_MANUAL,
+	 &spi_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_SPI},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_USB
+	{
+	 "USB test",
+	 "usb",
+	 "This test verifies the USB operation.",
+	 POST_RAM | POST_ALWAYS | POST_MANUAL,
+	 &usb_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_USB},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_SPR
+	{
+	 "SPR test",
+	 "spr",
+	 "This test checks SPR contents.",
+	 POST_ROM | POST_ALWAYS | POST_PREREL,
+	 &spr_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_SPR},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_SYSMON
+	{
+	 "SYSMON test",
+	 "sysmon",
+	 "This test monitors system hardware.",
+	 POST_RAM | POST_ALWAYS,
+	 &sysmon_post_test,
+	 &sysmon_init_f,
+	 &sysmon_reloc,
+	 CONFIG_SYS_POST_SYSMON},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_DSP
+	{
+	 "DSP test",
+	 "dsp",
+	 "This test checks any connected DSP(s).",
+	 POST_RAM | POST_MANUAL,
+	 &dsp_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_DSP},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_CODEC
+	{
+	 "CODEC test",
+	 "codec",
+	 "This test checks any connected codec(s).",
+	 POST_RAM | POST_MANUAL,
+	 &codec_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_CODEC},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_FLASH
+	{
+	 "FLASH test",
+	 "flash",
+	 "This test checks flash.",
+	 POST_RAM | POST_ALWAYS | POST_MANUAL,
+	 &flash_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_FLASH},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_LED
+	{
+	 "LED test",
+	 "LED",
+	 "This test checks LED ",
+	 POST_RAM | POST_ALWAYS | POST_MANUAL,
+	 &led_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_LED},
+#endif
+#if CONFIG_POST & CONFIG_SYS_POST_BUTTON
+	{
+	 "Button test",
+	 "button",
+	 "This test checks Button ",
+	 POST_RAM | POST_ALWAYS | POST_MANUAL,
+	 &button_post_test,
+	 NULL,
+	 NULL,
+	 CONFIG_SYS_POST_BUTTON},
+#endif
+
+};
+
+unsigned int post_list_size = sizeof(post_list) / sizeof(struct post_test);
diff --git a/arch/blackfin/lib/u-boot.lds.S b/arch/blackfin/lib/u-boot.lds.S
new file mode 100644
index 0000000..2b23d8b
--- /dev/null
+++ b/arch/blackfin/lib/u-boot.lds.S
@@ -0,0 +1,153 @@
+/*
+ * U-boot - u-boot.lds.S
+ *
+ * Copyright (c) 2005-2010 Analog Device Inc.
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <asm/blackfin.h>
+#undef ALIGN
+#undef ENTRY
+
+#ifndef LDS_BOARD_TEXT
+# define LDS_BOARD_TEXT
+#endif
+
+/* If we don't actually load anything into L1 data, this will avoid
+ * a syntax error.  If we do actually load something into L1 data,
+ * we'll get a linker memory load error (which is what we'd want).
+ * This is here in the first place so we can quickly test building
+ * for different CPU's which may lack non-cache L1 data.
+ */
+#ifndef L1_DATA_B_SRAM
+# define L1_DATA_B_SRAM      CONFIG_SYS_MONITOR_BASE
+# define L1_DATA_B_SRAM_SIZE 0
+#endif
+
+/* The 0xC offset is so we don't clobber the tiny LDR jump block. */
+#ifdef CONFIG_BFIN_BOOTROM_USES_EVT1
+# define L1_CODE_ORIGIN L1_INST_SRAM
+#else
+# define L1_CODE_ORIGIN L1_INST_SRAM + 0xC
+#endif
+
+OUTPUT_ARCH(bfin)
+
+MEMORY
+{
+#if CONFIG_MEM_SIZE
+	ram     : ORIGIN = CONFIG_SYS_MONITOR_BASE, LENGTH = CONFIG_SYS_MONITOR_LEN
+# define ram_code ram
+# define ram_data ram
+#else
+# define ram_code l1_code
+# define ram_data l1_data
+#endif
+	l1_code : ORIGIN = L1_CODE_ORIGIN,          LENGTH = L1_INST_SRAM_SIZE
+	l1_data : ORIGIN = L1_DATA_B_SRAM,          LENGTH = L1_DATA_B_SRAM_SIZE
+}
+
+ENTRY(_start)
+SECTIONS
+{
+	.text.pre :
+	{
+		cpu/blackfin/start.o (.text .text.*)
+
+		LDS_BOARD_TEXT
+	} >ram_code
+
+	.text.init :
+	{
+		cpu/blackfin/initcode.o (.text .text.*)
+	} >ram_code
+	__initcode_lma = LOADADDR(.text.init);
+	__initcode_len = SIZEOF(.text.init);
+
+	.text :
+	{
+		*(.text .text.*)
+	} >ram_code
+
+	.rodata :
+	{
+		. = ALIGN(4);
+		*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+		. = ALIGN(4);
+	} >ram_data
+
+	.data :
+	{
+		. = ALIGN(4);
+		*(.data .data.*)
+		*(.data1)
+		*(.sdata)
+		*(.sdata2)
+		*(.dynamic)
+		CONSTRUCTORS
+	} >ram_data
+
+	.u_boot_cmd :
+	{
+		___u_boot_cmd_start = .;
+		*(.u_boot_cmd)
+		___u_boot_cmd_end = .;
+	} >ram_data
+
+	.text_l1 :
+	{
+		. = ALIGN(4);
+		__stext_l1 = .;
+		*(.l1.text)
+		. = ALIGN(4);
+		__etext_l1 = .;
+	} >l1_code AT>ram_code
+	__text_l1_lma = LOADADDR(.text_l1);
+	__text_l1_len = SIZEOF(.text_l1);
+	ASSERT (__text_l1_len <= L1_INST_SRAM_SIZE, "L1 text overflow!")
+
+	.data_l1 :
+	{
+		. = ALIGN(4);
+		__sdata_l1 = .;
+		*(.l1.data)
+		*(.l1.bss)
+		. = ALIGN(4);
+		__edata_l1 = .;
+	} >l1_data AT>ram_data
+	__data_l1_lma = LOADADDR(.data_l1);
+	__data_l1_len = SIZEOF(.data_l1);
+	ASSERT (__data_l1_len <= L1_DATA_B_SRAM_SIZE, "L1 data B overflow!")
+
+	.bss :
+	{
+		. = ALIGN(4);
+		*(.sbss) *(.scommon)
+		*(.dynbss)
+		*(.bss .bss.*)
+		*(COMMON)
+	} >ram_data
+	__bss_vma = ADDR(.bss);
+	__bss_len = SIZEOF(.bss);
+}