Merge branch 'merge' of git://www.denx.de/git/u-boot-microblaze
diff --git a/CHANGELOG b/CHANGELOG
index 82b3145..66fa2e1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,98 @@
+commit e1893815b0999410d7a327589611c7b38e95299e
+Author: Wolfgang Denk <wd@denx.de>
+Date:	Fri Oct 12 15:49:39 2007 +0200
+
+    GP3 SSA: enable RTC
+
+    Signed-off-by: Wolfgang Denk <wd@denx.de>
+
+commit 8002012041f1ff9f997a5727abe5015f70cd2e46
+Author: Grzegorz Bernacki <gjb@semihalf.com>
+Date:	Tue Oct 9 13:58:24 2007 +0200
+
+    [ads5121] EEPROM support added.
+
+    Signed-off-by: Grzegorz Bernacki <gjb@semihalf.com>
+
+commit 2b2a587d6d3076387d22ac740f44044bf46e2cb8
+Author: Marian Balakowicz <m8@semihalf.com>
+Date:	Fri Oct 5 10:40:54 2007 +0200
+
+    tqm5200: Fix CONFIG_CMD_PCI typo in board config file.
+
+    Signed-off-by: Marian Balakowicz <m8@semihalf.com>
+
+commit 92869195ef8210758d2176230c0a36897afd50ed
+Author: Bartlomiej Sieka <tur@semihalf.com>
+Date:	Fri Oct 5 09:46:06 2007 +0200
+
+    CM5200: Fix missing null-termination in hostname manipulation code
+
+    Signed-off-by: Bartlomiej Sieka <tur@semihalf.com>
+
+commit 738815c0cc44aa329097f868dc1efc49ede9c5ba
+Author: Stefan Roese <sr@denx.de>
+Date:	Tue Oct 2 11:44:46 2007 +0200
+
+    ppc4xx: Coding style cleanup
+
+    Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 87c1833a39e944db66385286fd5e28f9b3fcdd50
+Author: Stefan Roese <sr@denx.de>
+Date:	Tue Oct 2 11:44:19 2007 +0200
+
+    ppc4xx: lwmon5: Remove watchdog for now, since not fully tested yet
+
+    Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 2db64784061bfc34f4ba70ef1d2fbe7133b55670
+Author: Grzegorz Bernacki <gjb@semihalf.com>
+Date:	Mon Oct 1 09:51:50 2007 +0200
+
+    Program EPLD to force full duplex mode for PHY.
+
+    EPLD forces modes of PHY operation. By default full duplex is turned off.
+    This fix turns it on.
+
+    Signed-off-by: Grzegorz Bernacki <gjb@semihalf.com>
+
+commit 86ec86c04326c3913178a7679aa910de071da75d
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date:	Thu Sep 27 23:27:47 2007 +0200
+
+    Fix missing DECLARE_GLOBAL_DATA_PTR on CONFIG_LPC2292 in serial
+
+    Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 3e954beb614b5b190d7f4f4c3b641437a0132e35
+Author: Stefan Roese <sr@denx.de>
+Date:	Tue Sep 11 14:12:55 2007 +0200
+
+    ppc4xx: lwmon5: Change GPIO 58 to default to low (watchdog test)
+
+    Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 0d38effc6e359e6b1b0c78d66e8bc1a4dc15a2ae
+Author: Grant Likely <grant.likely@secretlab.ca>
+Date:	Tue Sep 25 15:48:05 2007 -0600
+
+    Fpga: fix incorrect test of CFG_FPGA_XILINX macro
+
+    CFG_FPGA_XILINX is a bit value used to test against the value in
+    CONFIG_FPGA.  Testing for a value will always return TRUE.	I don't
+    think that is the intention in this code.
+
+    Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+
+commit 66dcad3a9a53e0766d90e0084123bd8529522fb0
+Author: Wolfgang Denk <wd@denx.de>
+Date:	Thu Sep 20 00:04:14 2007 +0200
+
+    v1.3.0-rc2
+
+    Signed-off-by: Wolfgang Denk <wd@denx.de>
+
 commit 135e19bc2773ebca487e9a8371f67e1ba202313a
 Author: Wolfgang Denk <wd@denx.de>
 Date:	Tue Sep 18 21:36:35 2007 +0200
@@ -38,6 +133,21 @@
 
     Signed-off-by: Wolfgang Denk <wd@denx.de>
 
+commit bd86220f58b99d6896198c385fda132f0c980915
+Author: Peter Pearse <peter.pearse@arm.com>
+Date:	Tue Sep 18 13:07:54 2007 +0100
+
+    Move coloured led API to status_led.h
+    Improve indentation in drivers/at45.c
+
+commit 97213f32416ead885deafea86774e912ffd60ad0
+Author: David Saada <David.Saada@ecitele.com>
+Date:	Mon Sep 17 17:04:47 2007 +0200
+
+    Description: Add NEC's PCI OHCI module ID to the USB OHCI driver
+
+    Signed-off-by: David Saada <david.saada@ecitele.com>
+
 commit 67c31036acaaaa992fc346cc89db0909a7e733c4
 Author: Wolfgang Denk <wd@denx.de>
 Date:	Sun Sep 16 17:10:04 2007 +0200
@@ -193,6 +303,18 @@
 
     Signed-off-by: Marian Balakowicz <m8@semihalf.com>
 
+commit e1f601b572db5de9aa81a0b77c68a86994fe24c4
+Author: Bartlomiej Sieka <tur@semihalf.com>
+Date:	Thu Sep 13 16:33:59 2007 +0200
+
+    tqm5200: Restore customary env. variable boot commands for powerpc kernels
+
+    - update default definitions of kernel_addr and fdt_addr env. variables
+    - make arch/powerpc booting the default scenario
+    - update MTD partition layout to match the above
+
+    Signed-off-by: Bartlomiej Sieka <tur@semihalf.com>
+
 commit f34024d4a328e6edd906456da98d2c537155c4f7
 Author: Wolfgang Denk <wd@denx.de>
 Date:	Wed Sep 12 00:48:57 2007 +0200
@@ -201,6 +323,12 @@
 
     Signed-off-by: Wolfgang Denk <wd@denx.de>
 
+commit d94c79e47011af5e8dd10ed6163c09b4cfc743cc
+Author: Peter Pearse <peter.pearse@arm.com>
+Date:	Tue Sep 11 15:35:01 2007 +0100
+
+    Final tidy
+
 commit 38ad82da0c1180ecdeb212a8f4245e945bcc546e
 Author: Grzegorz Bernacki <gjb@semihalf.com>
 Date:	Tue Sep 11 15:42:11 2007 +0200
@@ -507,6 +635,14 @@
 
     Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
 
+commit 80767a6cead9990d9e77e62be947843c2c72f469
+Author: Peter Pearse <peter.pearse@arm.com>
+Date:	Wed Sep 5 16:04:41 2007 +0100
+
+    Changed API name to coloured_led.h
+    Removed code using deprecated ifdef CONFIG_BOOTBINFUNC
+    Tidied other cpu/arm920t/start.S code
+
 commit 56a9270521baaa00e12639a978302a67f61ef060
 Author: Kumar Gala <galak@kernel.crashing.org>
 Date:	Thu Aug 30 16:18:18 2007 -0500
@@ -532,6 +668,31 @@
 
     Signed-off-by: Ed Swarthout <Ed.Swarthout@freescale.com>
 
+commit 9f5c3d3720e777a572dcdc8af2008b44c7243885
+Author: Peter Pearse <peter.pearse@arm.com>
+Date:	Tue Sep 4 16:18:38 2007 +0100
+
+    Add coloured led interface for ARM boards.
+    Use it in cpu/arm920t/start.S to indicate U-Boot code has been entered.
+
+commit 7462fe0d5a9d40cde083fb1a3cd73911996b5ecb
+Author: Peter Pearse <peter.pearse@arm.com>
+Date:	Tue Sep 4 14:49:28 2007 +0100
+
+    Move include/led.h to board/at91rm9200dk
+
+commit 6e4bf9b24e57c15abc6542e685d06380bc64af27
+Author: Peter Pearse <peter.pearse@arm.com>
+Date:	Tue Sep 4 14:25:51 2007 +0100
+
+    Ran Lindent on drivers/at45.c
+
+commit 557ab89d294f08dd532f21d19861b40093200a33
+Author: Peter Pearse <peter.pearse@arm.com>
+Date:	Tue Sep 4 14:23:50 2007 +0100
+
+    Rename CONFIG_CMD_MUX to CONFIG_CMD_AT91_SPIMUX
+
 commit 81b73dec16fd1227369a191e725e10044a9d56b8
 Author: Gary Jennejohn <garyj@denx.de>
 Date:	Fri Aug 31 15:21:46 2007 +0200
@@ -607,6 +768,20 @@
 
     Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
 
+commit 04625764cc93ce8a61625ac19d7fe2a2ceee8143
+Author: Stefan Roese <sr@denx.de>
+Date:	Wed Aug 29 16:31:18 2007 +0200
+
+    ppc4xx: Change lwmon5 default environment to support Linux RTC
+
+    The Linux PCF8563 RTC driver doesn't do autoprobing, so we need
+    to supply the RTC I2C address as bootline parameter. This patch
+    adds support for this rtc probing parameter to the bootargs:
+
+    "rtc-pcf8563.probe=0,0x51"
+
+    Signed-off-by: Stefan Roese <sr@denx.de>
+
 commit 2602a5c40ae37ab965a4e240854fdaffb51328a4
 Author: Kim Phillips <kim.phillips@freescale.com>
 Date:	Wed Aug 29 09:06:05 2007 -0500
diff --git a/Makefile b/Makefile
index 8d500f5..5fe67fc 100644
--- a/Makefile
+++ b/Makefile
@@ -211,6 +211,7 @@
 LIBS += drivers/bios_emulator/libatibiosemu.a
 LIBS += drivers/nand/libnand.a
 LIBS += drivers/nand_legacy/libnand_legacy.a
+LIBS += drivers/onenand/libonenand.a
 LIBS += drivers/net/libnet.a
 ifeq ($(CPU),mpc83xx)
 LIBS += drivers/qe/qe.a
diff --git a/board/amcc/luan/luan.c b/board/amcc/luan/luan.c
index 7b16f8a..0067ce0 100644
--- a/board/amcc/luan/luan.c
+++ b/board/amcc/luan/luan.c
@@ -39,8 +39,6 @@
  ************************************************************************/
 int board_early_init_f(void)
 {
-	volatile epld_t *x = (epld_t *) CFG_EPLD_BASE;
-
 	mtebc( pb0ap,  0x03800000 );	/* set chip selects */
 	mtebc( pb0cr,  0xffc58000 );	/* ebc0_b0cr, 4MB at 0xffc00000 CS0 */
 	mtebc( pb1ap,  0x03800000 );
@@ -66,8 +64,6 @@
 	mtdcr( uic0sr, 0x00000000 );	/* clear all interrupts */
 	mtdcr( uic0sr, 0xffffffff );
 
-	x->ethuart &= ~EPLD2_RESET_ETH_N; /* put Ethernet+PHY in reset */
-
 	return  0;
 }
 
@@ -79,7 +75,18 @@
 int misc_init_r(void)
 {
 	volatile epld_t *x = (epld_t *) CFG_EPLD_BASE;
-	x->ethuart |= EPLD2_RESET_ETH_N; /* take Ethernet+PHY out of reset */
+
+	/* set modes of operation */
+	x->ethuart |= EPLD2_ETH_MODE_10 | EPLD2_ETH_MODE_100 |
+		EPLD2_ETH_MODE_1000 | EPLD2_ETH_DUPLEX_MODE;
+	/* clear ETHERNET_AUTO_NEGO bit to turn on autonegotiation */
+	x->ethuart &= ~EPLD2_ETH_AUTO_NEGO;
+
+	/* put Ethernet+PHY in reset */
+	x->ethuart &= ~EPLD2_RESET_ETH_N;
+	udelay(10000);
+	/* take Ethernet+PHY out of reset */
+	x->ethuart |= EPLD2_RESET_ETH_N;
 
 	return  0;
 }
diff --git a/board/at91rm9200dk/led.c b/board/at91rm9200dk/led.c
index 0518918..47a3bfc 100644
--- a/board/at91rm9200dk/led.c
+++ b/board/at91rm9200dk/led.c
@@ -66,7 +66,7 @@
 }
 
 
-void LED_init (void)
+void coloured_LED_init (void)
 {
 	AT91PS_PIO	PIOB	= AT91C_BASE_PIOB;
 	AT91PS_PMC	PMC	= AT91C_BASE_PMC;
diff --git a/board/cm5200/cm5200.c b/board/cm5200/cm5200.c
index b74ac08..e2ab5b8 100644
--- a/board/cm5200/cm5200.c
+++ b/board/cm5200/cm5200.c
@@ -397,6 +397,7 @@
 					"operational\n");
 
 	/* set the hostname appropriate to the module we're running on */
+	hostname[0] = 0x00;
 	compose_hostname(hw_id, hostname);
 	setenv("hostname", hostname);
 
diff --git a/common/Makefile b/common/Makefile
index ef7d097..fde5ad9 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -37,13 +37,14 @@
 	  cmd_load.o cmd_log.o \
 	  cmd_mem.o cmd_mii.o cmd_misc.o cmd_mmc.o \
 	  cmd_nand.o cmd_net.o cmd_nvedit.o \
+	  cmd_onenand.o \
 	  cmd_pci.o cmd_pcmcia.o cmd_portio.o \
 	  cmd_reginfo.o cmd_reiser.o cmd_sata.o cmd_scsi.o cmd_spi.o \
 	  cmd_universe.o cmd_usb.o cmd_vfd.o \
 	  command.o console.o cyclon2.o devices.o dlmalloc.o docecc.o \
 	  environment.o env_common.o \
 	  env_nand.o env_dataflash.o env_flash.o env_eeprom.o \
-	  env_nvram.o env_nowhere.o \
+	  env_onenand.o env_nvram.o env_nowhere.o \
 	  exports.o \
 	  fdt_support.o flash.o fpga.o ft_build.o \
 	  hush.o kgdb.o lcd.o lists.o lynxkdi.o \
diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c
index 3fc4fca..cce23ad 100644
--- a/common/cmd_fpga.c
+++ b/common/cmd_fpga.c
@@ -60,6 +60,7 @@
 /* Convert bitstream data and load into the fpga */
 int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size)
 {
+#if (CONFIG_FPGA & CFG_FPGA_XILINX)
 	unsigned int length;
 	unsigned char* swapdata;
 	unsigned int swapsize;
@@ -72,7 +73,6 @@
 
 	dataptr = (unsigned char *)fpgadata;
 
-#if CFG_FPGA_XILINX
 	/* skip the first bytes of the bitsteam, their meaning is unknown */
 	length = (*dataptr << 8) + *(dataptr+1);
 	dataptr+=2;
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 1db0fc3..6770408 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -57,8 +57,9 @@
     !defined(CFG_ENV_IS_IN_FLASH)	&& \
     !defined(CFG_ENV_IS_IN_DATAFLASH)	&& \
     !defined(CFG_ENV_IS_IN_NAND)	&& \
+    !defined(CFG_ENV_IS_IN_ONENAND)	&& \
     !defined(CFG_ENV_IS_NOWHERE)
-# error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|NOWHERE}
+# error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|ONENAND|NOWHERE}
 #endif
 
 #define XMK_STR(x)	#x
@@ -553,7 +554,8 @@
 
 #if defined(CFG_ENV_IS_IN_NVRAM) || defined(CFG_ENV_IS_IN_EEPROM) \
     || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_FLASH)) \
-    || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND))
+    || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND)) \
+    || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_ONENAND))
 int do_saveenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
 	extern char * env_name_spec;
@@ -608,7 +610,8 @@
 
 #if defined(CFG_ENV_IS_IN_NVRAM) || defined(CFG_ENV_IS_IN_EEPROM) \
     || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_FLASH)) \
-    || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND))
+    || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND)) \
+    || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_ONENAND))
 U_BOOT_CMD(
 	saveenv, 1, 0,	do_saveenv,
 	"saveenv - save environment variables to persistent storage\n",
diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c
new file mode 100644
index 0000000..dcda099
--- /dev/null
+++ b/common/cmd_onenand.c
@@ -0,0 +1,155 @@
+/*
+ *  U-Boot command for OneNAND support
+ *
+ *  Copyright (C) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <command.h>
+
+#ifdef CONFIG_CMD_ONENAND
+
+#include <linux/mtd/compat.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+
+#include <asm/io.h>
+
+extern struct mtd_info onenand_mtd;
+extern struct onenand_chip onenand_chip;
+
+int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	int ret = 0;
+
+	switch (argc) {
+	case 0:
+	case 1:
+		printf("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+
+	case 2:
+		if (strncmp(argv[1], "open", 4) == 0) {
+			onenand_init();
+			return 0;
+		}
+		onenand_print_device_info(onenand_chip.device_id, 1);
+		return 0;
+
+	default:
+		/* At least 4 args */
+		if (strncmp(argv[1], "erase", 5) == 0) {
+			struct erase_info instr;
+			ulong start, end;
+			ulong block;
+
+			start = simple_strtoul(argv[2], NULL, 10);
+			end = simple_strtoul(argv[3], NULL, 10);
+			start -= (unsigned long)onenand_chip.base;
+			end -= (unsigned long)onenand_chip.base;
+
+			if (!end || end < 0)
+				end = start;
+
+			printf("Erase block from %d to %d\n", start, end);
+
+			for (block = start; block <= end; block++) {
+				instr.addr = block << onenand_chip.erase_shift;
+				instr.len = 1 << onenand_chip.erase_shift;
+				ret = onenand_erase(&onenand_mtd, &instr);
+				if (ret) {
+					printf("erase failed %d\n", block);
+					break;
+				}
+			}
+
+			return 0;
+		}
+
+		if (strncmp(argv[1], "read", 4) == 0) {
+			ulong addr = simple_strtoul(argv[2], NULL, 16);
+			ulong ofs = simple_strtoul(argv[3], NULL, 16);
+			size_t len = simple_strtoul(argv[4], NULL, 16);
+			size_t retlen = 0;
+			int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1;
+
+			ofs -= (unsigned long)onenand_chip.base;
+
+			if (oob)
+				onenand_read_oob(&onenand_mtd, ofs, len,
+						 &retlen, (u_char *) addr);
+			else
+				onenand_read(&onenand_mtd, ofs, len, &retlen,
+					     (u_char *) addr);
+			printf("Done\n");
+
+			return 0;
+		}
+
+		if (strncmp(argv[1], "write", 5) == 0) {
+			ulong addr = simple_strtoul(argv[2], NULL, 16);
+			ulong ofs = simple_strtoul(argv[3], NULL, 16);
+			size_t len = simple_strtoul(argv[4], NULL, 16);
+			size_t retlen = 0;
+
+			ofs -= (unsigned long)onenand_chip.base;
+
+			onenand_write(&onenand_mtd, ofs, len, &retlen,
+				      (u_char *) addr);
+			printf("Done\n");
+
+			return 0;
+		}
+
+		if (strncmp(argv[1], "block", 5) == 0) {
+			ulong addr = simple_strtoul(argv[2], NULL, 16);
+			ulong block = simple_strtoul(argv[3], NULL, 10);
+			ulong page = simple_strtoul(argv[4], NULL, 10);
+			size_t len = simple_strtol(argv[5], NULL, 10);
+			size_t retlen = 0;
+			ulong ofs;
+			int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1;
+
+			ofs = block << onenand_chip.erase_shift;
+			if (page)
+				ofs += page << onenand_chip.page_shift;
+
+			if (!len) {
+				if (oob)
+					len = 64;
+				else
+					len = 512;
+			}
+
+			if (oob)
+				onenand_read_oob(&onenand_mtd, ofs, len,
+						 &retlen, (u_char *) addr);
+			else
+				onenand_read(&onenand_mtd, ofs, len, &retlen,
+					     (u_char *) addr);
+			return 0;
+		}
+
+		break;
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	onenand,	6,	1,	do_onenand,
+	"onenand - OneNAND sub-system\n",
+	"info   - show available OneNAND devices\n"
+	"onenand read[.oob] addr ofs len - read data at ofs with len to addr\n"
+	"onenand write addr ofs len - write data at ofs with len from addr\n"
+	"onenand erase saddr eaddr - erase block start addr to end addr\n"
+	"onenand block[.oob] addr block [page] [len] - "
+		"read data with (block [, page]) to addr"
+);
+
+#endif /* CONFIG_CMD_ONENAND */
diff --git a/common/env_onenand.c b/common/env_onenand.c
new file mode 100644
index 0000000..66107f9
--- /dev/null
+++ b/common/env_onenand.c
@@ -0,0 +1,134 @@
+/*
+ * (C) Copyright 2005-2007 Samsung Electronics
+ * Kyungmin Park <kyungmin.park@samsung.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>
+
+#if defined(CFG_ENV_IS_IN_ONENAND)	/* Environment is in OneNAND */
+
+#include <command.h>
+#include <environment.h>
+#include <linux/stddef.h>
+#include <malloc.h>
+
+#include <linux/mtd/compat.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+
+extern struct mtd_info onenand_mtd;
+extern struct onenand_chip onenand_chip;
+
+/* References to names in env_common.c */
+extern uchar default_environment[];
+
+#define ONENAND_ENV_SIZE(mtd)	(mtd.oobblock - ENV_HEADER_SIZE)
+
+char *env_name_spec = "OneNAND";
+
+#ifdef ENV_IS_EMBEDDED
+extern uchar environment[];
+env_t *env_ptr = (env_t *) (&environment[0]);
+#else /* ! ENV_IS_EMBEDDED */
+static unsigned char onenand_env[MAX_ONENAND_PAGESIZE];
+env_t *env_ptr = (env_t *) onenand_env;
+#endif /* ENV_IS_EMBEDDED */
+
+uchar env_get_char_spec(int index)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	return (*((uchar *) (gd->env_addr + index)));
+}
+
+void env_relocate_spec(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	unsigned long env_addr;
+	int use_default = 0;
+	int retlen;
+
+	env_addr = CFG_ENV_ADDR;
+	env_addr -= (unsigned long)onenand_chip.base;
+
+	/* Check OneNAND exist */
+	if (onenand_mtd.oobblock)
+		/* Ignore read fail */
+		onenand_read(&onenand_mtd, env_addr, onenand_mtd.oobblock,
+			     &retlen, (u_char *) env_ptr);
+	else
+		onenand_mtd.oobblock = MAX_ONENAND_PAGESIZE;
+
+	if (crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd)) !=
+	    env_ptr->crc)
+		use_default = 1;
+
+	if (use_default) {
+		memcpy(env_ptr->data, default_environment,
+		       ONENAND_ENV_SIZE(onenand_mtd));
+		env_ptr->crc =
+		    crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd));
+	}
+
+	gd->env_addr = (ulong) & env_ptr->data;
+	gd->env_valid = 1;
+}
+
+int saveenv(void)
+{
+	unsigned long env_addr = CFG_ENV_ADDR;
+	struct erase_info instr;
+	int retlen;
+
+	instr.len = CFG_ENV_SIZE;
+	instr.addr = env_addr;
+	instr.addr -= (unsigned long)onenand_chip.base;
+	if (onenand_erase(&onenand_mtd, &instr)) {
+		printf("OneNAND: erase failed at 0x%08x\n", env_addr);
+		return 1;
+	}
+
+	/* update crc */
+	env_ptr->crc =
+	    crc32(0, env_ptr->data, onenand_mtd.oobblock - ENV_HEADER_SIZE);
+
+	env_addr -= (unsigned long)onenand_chip.base;
+	if (onenand_write(&onenand_mtd, env_addr, onenand_mtd.oobblock, &retlen,
+	     (u_char *) env_ptr)) {
+		printf("OneNAND: write failed at 0x%08x\n", instr.addr);
+		return 2;
+	}
+
+	return 0;
+}
+
+int env_init(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	/* use default */
+	gd->env_addr = (ulong) & default_environment[0];
+	gd->env_valid = 1;
+
+	return 0;
+}
+
+#endif /* CFG_ENV_IS_IN_ONENAND */
diff --git a/cpu/arm720t/serial.c b/cpu/arm720t/serial.c
index 27eb73a..1b0e147 100644
--- a/cpu/arm720t/serial.c
+++ b/cpu/arm720t/serial.c
@@ -125,6 +125,8 @@
 
 #elif defined(CONFIG_LPC2292)
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #include <asm/arch/hardware.h>
 
 void serial_setbrg (void)
diff --git a/cpu/arm920t/start.S b/cpu/arm920t/start.S
index b9c364b..aefcdd1 100644
--- a/cpu/arm920t/start.S
+++ b/cpu/arm920t/start.S
@@ -27,9 +27,7 @@
 
 #include <config.h>
 #include <version.h>
-#if	defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
-#include	<led.h>
-#endif
+#include <status_led.h>
 
 /*
  *************************************************************************
@@ -41,7 +39,7 @@
 
 
 .globl _start
-_start:	b       reset
+_start:	b       start_code
 	ldr	pc, _undefined_instruction
 	ldr	pc, _software_interrupt
 	ldr	pc, _prefetch_abort
@@ -64,7 +62,7 @@
 /*
  *************************************************************************
  *
- * Startup Code (reset vector)
+ * Startup Code (called from the ARM reset exception vector)
  *
  * do important init only if we don't start from memory!
  * relocate armboot to ram
@@ -106,10 +104,10 @@
 
 
 /*
- * the actual reset code
+ * the actual start code
  */
 
-reset:
+start_code:
 	/*
 	 * set the cpu to SVC32 mode
 	 */
@@ -118,58 +116,12 @@
 	orr	r0,r0,#0xd3
 	msr	cpsr,r0
 
-#if	CONFIG_AT91RM9200
-#if	defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
-	bl LED_init
+	bl coloured_LED_init
 	bl red_LED_on
-#endif
-
-#ifdef CONFIG_BOOTBINFUNC
-/* code based on entry.S from ATMEL */
-#define AT91C_BASE_CKGR 0xFFFFFC20
-#define CKGR_MOR 0
-	/* Get the CKGR Base Address */
-	ldr     r1, =AT91C_BASE_CKGR
 
-/* Main oscillator Enable register	APMC_MOR : Enable main oscillator , OSCOUNT = 0xFF */
-/*	ldr 	r0, = AT91C_CKGR_MOSCEN:OR:AT91C_CKGR_OSCOUNT */
-	ldr 	r0, =0x0000FF01
-	str     r0, [r1, #CKGR_MOR]
-	/* Add loop to compensate Main Oscillator startup time */
-	ldr 	r0, =0x00000010
-LoopOsc:
-	subs    r0, r0, #1
-	bhi     LoopOsc
-	/* scratch stack */
-	ldr 	r1, =0x00204000
-	/* Insure word alignment */
-	bic     r1, r1, #3
-	/* Init stack SYS	 */
-	mov     sp, r1
-	/*
-	 * This does a lot more than just set up the memory, which
-	 * is why it's called lowlevelinit
-	 */
-	bl	lowlevelinit /* in memsetup.S */
-	bl	icache_enable;
-	/* ------------------------------------
-	 * Read/modify/write CP15 control register
-	 * -------------------------------------
-	 * read cp15 control register (cp15 r1) in r0
-	 * ------------------------------------
-	 */
-	mrc     p15, 0, r0, c1, c0, 0
-	/* Reset bit :Little Endian end fast bus mode */
-	ldr     r3, =0xC0000080
-	/* Set bit :Asynchronous clock mode, Not Fast Bus */
-	ldr     r4, =0xC0000000
-	bic     r0, r0, r3
-	orr     r0, r0, r4
-	/* write r0 in cp15 control register (cp15 r1) */
-	mcr     p15, 0, r0, c1, c0, 0
-#endif /* CONFIG_BOOTBINFUNC */
+#if	defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
 	/*
-	 * relocate exeception table
+	 * relocate exception table
 	 */
 	ldr	r0, =_start
 	ldr	r1, =0x0
@@ -181,19 +133,20 @@
 	bne	copyex
 #endif
 
-/* turn off the watchdog */
-#if defined(CONFIG_S3C2400)
-# define pWTCON		0x15300000
-# define INTMSK		0x14400008	/* Interupt-Controller base addresses */
-# define CLKDIVN	0x14800014	/* clock divisor register */
-#elif defined(CONFIG_S3C2410)
-# define pWTCON		0x53000000
-# define INTMSK		0x4A000008	/* Interupt-Controller base addresses */
-# define INTSUBMSK	0x4A00001C
-# define CLKDIVN	0x4C000014	/* clock divisor register */
-#endif
-
 #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
+	/* turn off the watchdog */
+
+# if defined(CONFIG_S3C2400)
+#  define pWTCON		0x15300000
+#  define INTMSK		0x14400008	/* Interupt-Controller base addresses */
+#  define CLKDIVN	0x14800014	/* clock divisor register */
+#else
+#  define pWTCON		0x53000000
+#  define INTMSK		0x4A000008	/* Interupt-Controller base addresses */
+#  define INTSUBMSK	0x4A00001C
+#  define CLKDIVN	0x4C000014	/* clock divisor register */
+# endif
+
 	ldr     r0, =pWTCON
 	mov     r1, #0x0
 	str     r1, [r0]
@@ -226,25 +179,7 @@
 #endif
 
 #ifdef	CONFIG_AT91RM9200
-#ifdef CONFIG_BOOTBINFUNC
-relocate:				/* relocate U-Boot to RAM	    */
-	adr	r0, _start		/* r0 <- current position of code   */
-	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */
-	cmp     r0, r1                  /* don't reloc during debug         */
-	beq     stack_setup
-
-	ldr	r2, _armboot_start
-	ldr	r3, _bss_start
-	sub	r2, r3, r2		/* r2 <- size of armboot            */
-	add	r2, r0, r2		/* r2 <- source end address         */
 
-copy_loop:
-	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */
-	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */
-	cmp	r0, r2			/* until source end addreee [r2]    */
-	ble	copy_loop
-#endif /* CONFIG_BOOTBINFUNC */
-#else
 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
 relocate:				/* relocate U-Boot to RAM	    */
 	adr	r0, _start		/* r0 <- current position of code   */
@@ -284,27 +219,6 @@
 	cmp	r0, r1
 	ble	clbss_l
 
-#if 0
-	/* try doing this stuff after the relocation */
-	ldr     r0, =pWTCON
-	mov     r1, #0x0
-	str     r1, [r0]
-
-	/*
-	 * mask all IRQs by setting all bits in the INTMR - default
-	 */
-	mov	r1, #0xffffffff
-	ldr	r0, =INTMR
-	str	r1, [r0]
-
-	/* FCLK:HCLK:PCLK = 1:2:4 */
-	/* default FCLK is 120 MHz ! */
-	ldr	r0, =CLKDIVN
-	mov	r1, #3
-	str	r1, [r0]
-	/* END stuff after relocation */
-#endif
-
 	ldr	pc, _start_armboot
 
 _start_armboot:	.word start_armboot
diff --git a/cpu/ppc4xx/440spe_pcie.c b/cpu/ppc4xx/440spe_pcie.c
index 158f1c5..3eac0ae 100644
--- a/cpu/ppc4xx/440spe_pcie.c
+++ b/cpu/ppc4xx/440spe_pcie.c
@@ -104,7 +104,7 @@
 	if ((!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 0))) &&
 		((PCI_BUS(devfn) == 0) || (PCI_BUS(devfn) == 1)))
 		return 0;
-		
+
 	address = pcie_get_base(hose, devfn);
 	offset += devfn << 4;
 
@@ -136,12 +136,12 @@
 	int offset, int len, u32 val) {
 
 	u8 *address;
-	
+
 	/*
 	 * Bus numbers are relative to hose->first_busno
 	 */
 	devfn -= PCI_BDF(hose->first_busno, 0, 0);
-	
+
 	/*
 	 * Same constraints as in pcie_read_config().
 	 */
@@ -151,7 +151,7 @@
 	if ((!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 0))) &&
 		((PCI_BUS(devfn) == 0) || (PCI_BUS(devfn) == 1)))
 		return 0;
-	
+
 	address = pcie_get_base(hose, devfn);
 	offset += devfn << 4;
 
@@ -926,7 +926,7 @@
 		 in_le16((u16 *)(mbase + PCI_COMMAND)) |
 		 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
 	printf("PCIE:%d successfully set as rootpoint\n",port);
-	
+
 	/* Set Device and Vendor Id */
 	switch (port) {
 	case 0:
diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c
index cc8e734..71a9e37 100644
--- a/cpu/ppc4xx/4xx_enet.c
+++ b/cpu/ppc4xx/4xx_enet.c
@@ -138,7 +138,8 @@
 #define BI_PHYMODE_MII   7
 #endif
 
-#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || \
+	defined(CONFIG_440GRX) || defined(CONFIG_440SP)
 #define SDR0_MFR_ETH_CLK_SEL_V(n)	((0x01<<27) / (n+1))
 #endif
 
@@ -408,7 +409,8 @@
 	int ethgroup = -1;
 #endif
 #endif
-#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || defined(CONFIG_440SPE)
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_440SP) || defined(CONFIG_440SPE)
 	unsigned long mfr;
 #endif
 
@@ -500,7 +502,8 @@
 	__asm__ volatile ("eieio");
 
 	/* reset emac so we have access to the phy */
-#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_440SP) || defined(CONFIG_440SPE)
 	/* provide clocks for EMAC internal loopback  */
 	mfsdr (sdr_mfr, mfr);
 	mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum);
@@ -518,7 +521,8 @@
 	if (failsafe <= 0)
 		printf("\nProblem resetting EMAC!\n");
 
-#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_440SP) || defined(CONFIG_440SPE)
 	/* remove clocks for EMAC internal loopback  */
 	mfsdr (sdr_mfr, mfr);
 	mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum);
@@ -920,8 +924,8 @@
 
 	/* set speed */
 	if (speed == _1000BASET) {
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
-    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_440SP) || defined(CONFIG_440SPE)
 		unsigned long pfc1;
 
 		mfsdr (sdr_pfc1, pfc1);
diff --git a/drivers/at45.c b/drivers/at45.c
old mode 100755
new mode 100644
index 507ff36..dac987a
--- a/drivers/at45.c
+++ b/drivers/at45.c
@@ -27,33 +27,31 @@
 /*
  * spi.c API
  */
-extern unsigned int	AT91F_SpiWrite (AT91PS_DataflashDesc pDesc);
-extern void 		AT91F_SpiEnable(int cs);
+extern unsigned int AT91F_SpiWrite(AT91PS_DataflashDesc pDesc);
+extern void AT91F_SpiEnable(int cs);
 
 #define AT91C_TIMEOUT_WRDY			200000
 
-
 /*----------------------------------------------------------------------*/
 /* \fn    AT91F_DataFlashSendCommand					*/
 /* \brief Generic function to send a command to the dataflash		*/
 /*----------------------------------------------------------------------*/
-AT91S_DataFlashStatus AT91F_DataFlashSendCommand(
-	AT91PS_DataFlash pDataFlash,
-	unsigned char OpCode,
-	unsigned int CmdSize,
-	unsigned int DataflashAddress)
+AT91S_DataFlashStatus AT91F_DataFlashSendCommand(AT91PS_DataFlash pDataFlash,
+						 unsigned char OpCode,
+						 unsigned int CmdSize,
+						 unsigned int DataflashAddress)
 {
 	unsigned int adr;
 
-	if ( (pDataFlash->pDataFlashDesc->state) != IDLE)
+	if ((pDataFlash->pDataFlashDesc->state) != IDLE)
 		return DATAFLASH_BUSY;
 
 	/* process the address to obtain page address and byte address */
 	adr = ((DataflashAddress / (pDataFlash->pDevice->pages_size)) <<
-		pDataFlash->pDevice->page_offset) + (DataflashAddress %
-		(pDataFlash->pDevice->pages_size));
+		pDataFlash->pDevice->page_offset) +
+			(DataflashAddress % (pDataFlash->pDevice->pages_size));
 
-	/* fill the  command  buffer */
+	/* fill the command buffer */
 	pDataFlash->pDataFlashDesc->command[0] = OpCode;
 	if (pDataFlash->pDevice->pages_number >= 16384) {
 		pDataFlash->pDataFlashDesc->command[1] =
@@ -78,16 +76,16 @@
 	pDataFlash->pDataFlashDesc->command[7] = 0;
 
 	/* Initialize the SpiData structure for the spi write fuction */
-	pDataFlash->pDataFlashDesc->tx_cmd_pt   =
+	pDataFlash->pDataFlashDesc->tx_cmd_pt =
 		pDataFlash->pDataFlashDesc->command;
-	pDataFlash->pDataFlashDesc->tx_cmd_size =  CmdSize;
-	pDataFlash->pDataFlashDesc->rx_cmd_pt   =
+	pDataFlash->pDataFlashDesc->tx_cmd_size = CmdSize;
+	pDataFlash->pDataFlashDesc->rx_cmd_pt =
 		pDataFlash->pDataFlashDesc->command;
-	pDataFlash->pDataFlashDesc->rx_cmd_size =  CmdSize;
+	pDataFlash->pDataFlashDesc->rx_cmd_size = CmdSize;
 
 	/* send the command and read the data */
-	return AT91F_SpiWrite (pDataFlash->pDataFlashDesc); }
-
+	return AT91F_SpiWrite(pDataFlash->pDataFlashDesc);
+}
 
 /*----------------------------------------------------------------------*/
 /* \fn    AT91F_DataFlashGetStatus					*/
@@ -98,50 +96,49 @@
 	AT91S_DataFlashStatus status;
 
 	/* if a transfert is in progress ==> return 0 */
-	if( (pDesc->state) != IDLE)
+	if ((pDesc->state) != IDLE)
 		return DATAFLASH_BUSY;
 
 	/* first send the read status command (D7H) */
 	pDesc->command[0] = DB_STATUS;
 	pDesc->command[1] = 0;
 
-	pDesc->DataFlash_state  = GET_STATUS;
-	pDesc->tx_data_size 	= 0;	/* Transmit the command */
-					/* and receive response */
-	pDesc->tx_cmd_pt 		= pDesc->command;
-	pDesc->rx_cmd_pt 		= pDesc->command;
-	pDesc->rx_cmd_size 		= 2;
-	pDesc->tx_cmd_size 		= 2;
-	status = AT91F_SpiWrite (pDesc);
+	pDesc->DataFlash_state = GET_STATUS;
+	pDesc->tx_data_size = 0;	/* Transmit the command */
+	/* and receive response */
+	pDesc->tx_cmd_pt = pDesc->command;
+	pDesc->rx_cmd_pt = pDesc->command;
+	pDesc->rx_cmd_size = 2;
+	pDesc->tx_cmd_size = 2;
+	status = AT91F_SpiWrite(pDesc);
 
-	pDesc->DataFlash_state = *( (unsigned char *) (pDesc->rx_cmd_pt) +1);
+	pDesc->DataFlash_state = *((unsigned char *)(pDesc->rx_cmd_pt) + 1);
 
 	return status;
 }
 
-
 /*----------------------------------------------------------------------*/
 /* \fn    AT91F_DataFlashWaitReady					*/
 /* \brief wait for dataflash ready (bit7 of the status register == 1)	*/
 /*----------------------------------------------------------------------*/
 AT91S_DataFlashStatus AT91F_DataFlashWaitReady(AT91PS_DataflashDesc
-pDataFlashDesc, unsigned int timeout)
+						pDataFlashDesc,
+						unsigned int timeout)
 {
 	pDataFlashDesc->DataFlash_state = IDLE;
 
 	do {
 		AT91F_DataFlashGetStatus(pDataFlashDesc);
 		timeout--;
-	} while( ((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) &&
-			(timeout > 0) );
+	} while (((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) &&
+		 (timeout > 0));
 
-	if((pDataFlashDesc->DataFlash_state & 0x80) != 0x80)
+	if ((pDataFlashDesc->DataFlash_state & 0x80) != 0x80)
 		return DATAFLASH_ERROR;
 
 	return DATAFLASH_OK;
 }
 
-
 /*--------------------------------------------------------------------------*/
 /* Function Name       : AT91F_DataFlashContinuousRead 			    */
 /* Object              : Continuous stream Read 			    */
@@ -151,17 +148,17 @@
 /*                     : <sizeToRead> = data buffer size		    */
 /* Return value		: State of the dataflash			    */
 /*--------------------------------------------------------------------------*/
-AT91S_DataFlashStatus AT91F_DataFlashContinuousRead (
-	AT91PS_DataFlash pDataFlash,
-	int src,
-	unsigned char *dataBuffer,
-	int sizeToRead )
+AT91S_DataFlashStatus AT91F_DataFlashContinuousRead(
+				AT91PS_DataFlash pDataFlash,
+				int src,
+				unsigned char *dataBuffer,
+				int sizeToRead)
 {
 	AT91S_DataFlashStatus status;
 	/* Test the size to read in the device */
-	if ( (src + sizeToRead) >
-		(pDataFlash->pDevice->pages_size *
-		(pDataFlash->pDevice->pages_number)))
+	if ((src + sizeToRead) >
+			(pDataFlash->pDevice->pages_size *
+				(pDataFlash->pDevice->pages_number)))
 		return DATAFLASH_MEMORY_OVERFLOW;
 
 	pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer;
@@ -169,13 +166,12 @@
 	pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer;
 	pDataFlash->pDataFlashDesc->tx_data_size = sizeToRead;
 
-	status = AT91F_DataFlashSendCommand
-			(pDataFlash, DB_CONTINUOUS_ARRAY_READ, 8, src);
+	status = AT91F_DataFlashSendCommand(
+			pDataFlash, DB_CONTINUOUS_ARRAY_READ, 8, src);
 	/* Send the command to the dataflash */
-	return(status);
+	return (status);
 }
 
-
 /*---------------------------------------------------------------------------*/
 /* Function Name       : AT91F_DataFlashPagePgmBuf			     */
 /* Object              : Main memory page program thru buffer 1 or buffer 2  */
@@ -185,11 +181,10 @@
 /*                     : <SizeToWrite> = data buffer size		     */
 /* Return value		: State of the dataflash			     */
 /*---------------------------------------------------------------------------*/
-AT91S_DataFlashStatus AT91F_DataFlashPagePgmBuf(
-	AT91PS_DataFlash pDataFlash,
-	unsigned char *src,
-	unsigned int dest,
-	unsigned int SizeToWrite)
+AT91S_DataFlashStatus AT91F_DataFlashPagePgmBuf(AT91PS_DataFlash pDataFlash,
+						unsigned char *src,
+						unsigned int dest,
+						unsigned int SizeToWrite)
 {
 	int cmdsize;
 	pDataFlash->pDataFlashDesc->tx_data_pt = src;
@@ -201,9 +196,9 @@
 	/* Send the command to the dataflash */
 	if (pDataFlash->pDevice->pages_number >= 16384)
 		cmdsize = 5;
-	return(AT91F_DataFlashSendCommand (pDataFlash, DB_PAGE_PGM_BUF1,
-cmdsize, dest)); }
-
+	return (AT91F_DataFlashSendCommand(
+			pDataFlash, DB_PAGE_PGM_BUF1, cmdsize, dest));
+}
 
 /*---------------------------------------------------------------------------*/
 /* Function Name       : AT91F_MainMemoryToBufferTransfert		     */
@@ -214,26 +209,29 @@
 /* Return value		: State of the dataflash			     */
 /*---------------------------------------------------------------------------*/
 AT91S_DataFlashStatus AT91F_MainMemoryToBufferTransfert(
-	AT91PS_DataFlash pDataFlash,
-	unsigned char BufferCommand,
-	unsigned int page)
+					AT91PS_DataFlash
+					pDataFlash,
+					unsigned char
+					BufferCommand,
+					unsigned int page)
 {
 	int cmdsize;
 	/* Test if the buffer command is legal */
-	if ((BufferCommand != DB_PAGE_2_BUF1_TRF)
-		&& (BufferCommand != DB_PAGE_2_BUF2_TRF))
+	if ((BufferCommand != DB_PAGE_2_BUF1_TRF) &&
+			(BufferCommand != DB_PAGE_2_BUF2_TRF)) {
 		return DATAFLASH_BAD_COMMAND;
+	}
 
 	/* no data to transmit or receive */
 	pDataFlash->pDataFlashDesc->tx_data_size = 0;
 	cmdsize = 4;
 	if (pDataFlash->pDevice->pages_number >= 16384)
 		cmdsize = 5;
-	return(AT91F_DataFlashSendCommand (pDataFlash, BufferCommand, cmdsize,
-page*pDataFlash->pDevice->pages_size));
+	return (AT91F_DataFlashSendCommand(
+			pDataFlash, BufferCommand, cmdsize,
+			page * pDataFlash->pDevice->pages_size));
 }
 
-
 /*-------------------------------------------------------------------------- */
 /* Function Name       : AT91F_DataFlashWriteBuffer			     */
 /* Object              : Write data to the internal sram buffer 1 or 2	     */
@@ -244,58 +242,61 @@
 /*                     : <SizeToWrite> = data buffer size		     */
 /* Return value		: State of the dataflash			     */
 /*---------------------------------------------------------------------------*/
-AT91S_DataFlashStatus AT91F_DataFlashWriteBuffer (
-	AT91PS_DataFlash pDataFlash,
-	unsigned char BufferCommand,
-	unsigned char *dataBuffer,
-	unsigned int bufferAddress,
-	int SizeToWrite )
+AT91S_DataFlashStatus AT91F_DataFlashWriteBuffer(
+					AT91PS_DataFlash pDataFlash,
+					unsigned char BufferCommand,
+					unsigned char *dataBuffer,
+					unsigned int bufferAddress,
+					int SizeToWrite)
 {
 	int cmdsize;
 	/* Test if the buffer command is legal */
-	if ((BufferCommand != DB_BUF1_WRITE)
-		&& (BufferCommand != DB_BUF2_WRITE))
+	if ((BufferCommand != DB_BUF1_WRITE) &&
+			(BufferCommand != DB_BUF2_WRITE)) {
 		return DATAFLASH_BAD_COMMAND;
+	}
 
 	/* buffer address must be lower than page size */
 	if (bufferAddress > pDataFlash->pDevice->pages_size)
 		return DATAFLASH_BAD_ADDRESS;
 
-	if ( (pDataFlash->pDataFlashDesc->state)  != IDLE)
+	if ((pDataFlash->pDataFlashDesc->state) != IDLE)
 		return DATAFLASH_BUSY;
 
 	/* Send first Write Command */
 	pDataFlash->pDataFlashDesc->command[0] = BufferCommand;
 	pDataFlash->pDataFlashDesc->command[1] = 0;
 	if (pDataFlash->pDevice->pages_number >= 16384) {
-	    	pDataFlash->pDataFlashDesc->command[2] = 0;
-	    	pDataFlash->pDataFlashDesc->command[3] =
+		pDataFlash->pDataFlashDesc->command[2] = 0;
+		pDataFlash->pDataFlashDesc->command[3] =
 			(unsigned char)(((unsigned int)(bufferAddress &
-				pDataFlash->pDevice->byte_mask)) >> 8);
-	    	pDataFlash->pDataFlashDesc->command[4] =
-			(unsigned char)((unsigned int)bufferAddress  & 0x00FF);
+							pDataFlash->pDevice->
+							byte_mask)) >> 8);
+		pDataFlash->pDataFlashDesc->command[4] =
+			(unsigned char)((unsigned int)bufferAddress & 0x00FF);
 		cmdsize = 5;
 	} else {
-	    	pDataFlash->pDataFlashDesc->command[2] =
+		pDataFlash->pDataFlashDesc->command[2] =
 			(unsigned char)(((unsigned int)(bufferAddress &
-				pDataFlash->pDevice->byte_mask)) >> 8);
-	    	pDataFlash->pDataFlashDesc->command[3] =
-			(unsigned char)((unsigned int)bufferAddress  & 0x00FF);
-	    	pDataFlash->pDataFlashDesc->command[4] = 0;
+							pDataFlash->pDevice->
+							byte_mask)) >> 8);
+		pDataFlash->pDataFlashDesc->command[3] =
+			(unsigned char)((unsigned int)bufferAddress & 0x00FF);
+		pDataFlash->pDataFlashDesc->command[4] = 0;
 		cmdsize = 4;
 	}
 
-	pDataFlash->pDataFlashDesc->tx_cmd_pt 	 =
+	pDataFlash->pDataFlashDesc->tx_cmd_pt =
 		pDataFlash->pDataFlashDesc->command;
 	pDataFlash->pDataFlashDesc->tx_cmd_size = cmdsize;
-	pDataFlash->pDataFlashDesc->rx_cmd_pt 	 =
+	pDataFlash->pDataFlashDesc->rx_cmd_pt =
 		pDataFlash->pDataFlashDesc->command;
 	pDataFlash->pDataFlashDesc->rx_cmd_size = cmdsize;
 
-	pDataFlash->pDataFlashDesc->rx_data_pt 	= dataBuffer;
-	pDataFlash->pDataFlashDesc->tx_data_pt 	= dataBuffer;
-	pDataFlash->pDataFlashDesc->rx_data_size 	= SizeToWrite;
-	pDataFlash->pDataFlashDesc->tx_data_size 	= SizeToWrite;
+	pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer;
+	pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer;
+	pDataFlash->pDataFlashDesc->rx_data_size = SizeToWrite;
+	pDataFlash->pDataFlashDesc->tx_data_size = SizeToWrite;
 
 	return AT91F_SpiWrite(pDataFlash->pDataFlashDesc);
 }
@@ -309,22 +310,22 @@
 /* Return value		: State of the dataflash			     */
 /*---------------------------------------------------------------------------*/
 AT91S_DataFlashStatus AT91F_PageErase(
-	AT91PS_DataFlash pDataFlash,
-	unsigned int page)
+					AT91PS_DataFlash pDataFlash,
+					unsigned int page)
 {
 	int cmdsize;
 	/* Test if the buffer command is legal */
 	/* no data to transmit or receive */
-    	pDataFlash->pDataFlashDesc->tx_data_size = 0;
+	pDataFlash->pDataFlashDesc->tx_data_size = 0;
 
 	cmdsize = 4;
 	if (pDataFlash->pDevice->pages_number >= 16384)
 		cmdsize = 5;
-	return(AT91F_DataFlashSendCommand (pDataFlash, DB_PAGE_ERASE, cmdsize,
-page*pDataFlash->pDevice->pages_size));
+	return (AT91F_DataFlashSendCommand(pDataFlash,
+				DB_PAGE_ERASE, cmdsize,
+				page * pDataFlash->pDevice->pages_size));
 }
 
-
 /*---------------------------------------------------------------------------*/
 /* Function Name       : AT91F_BlockErase                                    */
 /* Object              : Erase a Block 					     */
@@ -334,18 +335,19 @@
 /* Return value		: State of the dataflash			     */
 /*---------------------------------------------------------------------------*/
 AT91S_DataFlashStatus AT91F_BlockErase(
-	AT91PS_DataFlash pDataFlash,
-	unsigned int block)
+				AT91PS_DataFlash pDataFlash,
+				unsigned int block)
 {
 	int cmdsize;
 	/* Test if the buffer command is legal */
 	/* no data to transmit or receive */
-    	pDataFlash->pDataFlashDesc->tx_data_size = 0;
+	pDataFlash->pDataFlashDesc->tx_data_size = 0;
 	cmdsize = 4;
 	if (pDataFlash->pDevice->pages_number >= 16384)
 		cmdsize = 5;
-	return(AT91F_DataFlashSendCommand (pDataFlash, DB_BLOCK_ERASE,cmdsize,
-block*8*pDataFlash->pDevice->pages_size));
+	return (AT91F_DataFlashSendCommand(pDataFlash, DB_BLOCK_ERASE, cmdsize,
+					block * 8 *
+					pDataFlash->pDevice->pages_size));
 }
 
 /*---------------------------------------------------------------------------*/
@@ -356,17 +358,16 @@
 /*                     : <dest> = main memory address			     */
 /* Return value		: State of the dataflash			     */
 /*---------------------------------------------------------------------------*/
-AT91S_DataFlashStatus AT91F_WriteBufferToMain (
-	AT91PS_DataFlash pDataFlash,
-	unsigned char BufferCommand,
-	unsigned int dest )
+AT91S_DataFlashStatus AT91F_WriteBufferToMain(AT91PS_DataFlash pDataFlash,
+					unsigned char BufferCommand,
+					unsigned int dest)
 {
 	int cmdsize;
 	/* Test if the buffer command is correct */
 	if ((BufferCommand != DB_BUF1_PAGE_PGM) &&
-	    (BufferCommand != DB_BUF1_PAGE_ERASE_PGM) &&
-	    (BufferCommand != DB_BUF2_PAGE_PGM) &&
-	    (BufferCommand != DB_BUF2_PAGE_ERASE_PGM) )
+			(BufferCommand != DB_BUF1_PAGE_ERASE_PGM) &&
+			(BufferCommand != DB_BUF2_PAGE_PGM) &&
+			(BufferCommand != DB_BUF2_PAGE_ERASE_PGM))
 		return DATAFLASH_BAD_COMMAND;
 
 	/* no data to transmit or receive */
@@ -376,9 +377,9 @@
 	if (pDataFlash->pDevice->pages_number >= 16384)
 		cmdsize = 5;
 	/* Send the command to the dataflash */
-	return(AT91F_DataFlashSendCommand (pDataFlash, BufferCommand, cmdsize,
-						dest)); }
-
+	return (AT91F_DataFlashSendCommand(pDataFlash, BufferCommand,
+						cmdsize, dest));
+}
 
 /*---------------------------------------------------------------------------*/
 /* Function Name       : AT91F_PartialPageWrite				     */
@@ -387,11 +388,10 @@
 /*			: <AdrInpage> = adr to begin the fading		     */
 /*                     : <length> = Number of bytes to erase		     */
 /*---------------------------------------------------------------------------*/
-AT91S_DataFlashStatus AT91F_PartialPageWrite (
-	AT91PS_DataFlash pDataFlash,
-	unsigned char *src,
-	unsigned int dest,
-	unsigned int size)
+AT91S_DataFlashStatus AT91F_PartialPageWrite(AT91PS_DataFlash pDataFlash,
+					unsigned char *src,
+					unsigned int dest,
+					unsigned int size)
 {
 	unsigned int page;
 	unsigned int AdrInPage;
@@ -400,10 +400,9 @@
 	AdrInPage = dest % (pDataFlash->pDevice->pages_size);
 
 	/* Read the contents of the page in the Sram Buffer */
-	AT91F_MainMemoryToBufferTransfert(pDataFlash,
-						DB_PAGE_2_BUF1_TRF, page);
+	AT91F_MainMemoryToBufferTransfert(pDataFlash, DB_PAGE_2_BUF1_TRF, page);
 	AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
-						AT91C_TIMEOUT_WRDY);
+				 AT91C_TIMEOUT_WRDY);
 	/*Update the SRAM buffer */
 	AT91F_DataFlashWriteBuffer(pDataFlash, DB_BUF1_WRITE, src,
 					AdrInPage, size);
@@ -416,12 +415,13 @@
 		AT91F_PageErase(pDataFlash, page);
 		/* Rewrite the modified Sram Buffer in the main memory */
 		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
-						AT91C_TIMEOUT_WRDY);
+					 AT91C_TIMEOUT_WRDY);
 	}
 
 	/* Rewrite the modified Sram Buffer in the main memory */
-	return(AT91F_WriteBufferToMain(pDataFlash, DB_BUF1_PAGE_ERASE_PGM,
-				(page*pDataFlash->pDevice->pages_size)));
+	return (AT91F_WriteBufferToMain(pDataFlash, DB_BUF1_PAGE_ERASE_PGM,
+					(page *
+					 pDataFlash->pDevice->pages_size)));
 }
 
 /*---------------------------------------------------------------------------*/
@@ -431,11 +431,9 @@
 /*                     : <dest> = dataflash adress			     */
 /*                     : <size> = data buffer size			     */
 /*---------------------------------------------------------------------------*/
-AT91S_DataFlashStatus AT91F_DataFlashWrite(
-	AT91PS_DataFlash pDataFlash,
-	unsigned char *src,
-	int dest,
-	int size )
+AT91S_DataFlashStatus AT91F_DataFlashWrite(AT91PS_DataFlash pDataFlash,
+						unsigned char *src,
+						int dest, int size)
 {
 	unsigned int length;
 	unsigned int page;
@@ -443,26 +441,24 @@
 
 	AT91F_SpiEnable(pDataFlash->pDevice->cs);
 
-	if ( (dest + size) > (pDataFlash->pDevice->pages_size *
-					(pDataFlash->pDevice->pages_number)))
+	if ((dest + size) > (pDataFlash->pDevice->pages_size *
+			(pDataFlash->pDevice->pages_number)))
 		return DATAFLASH_MEMORY_OVERFLOW;
 
 	/* If destination does not fit a page start address */
-	if ((dest % ((unsigned int)(pDataFlash->pDevice->pages_size)))  != 0 )
-	{
-		length = pDataFlash->pDevice->pages_size -
-				(dest %
-				((unsigned int)
-				(pDataFlash->pDevice->pages_size)));
+	if ((dest % ((unsigned int)(pDataFlash->pDevice->pages_size))) != 0) {
+		length =
+			pDataFlash->pDevice->pages_size -
+			(dest % ((unsigned int)(pDataFlash->pDevice->pages_size)));
 
 		if (size < length)
 			length = size;
 
-		if(!AT91F_PartialPageWrite(pDataFlash,src, dest, length))
+		if (!AT91F_PartialPageWrite(pDataFlash, src, dest, length))
 			return DATAFLASH_ERROR;
 
 		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
-			AT91C_TIMEOUT_WRDY);
+					 AT91C_TIMEOUT_WRDY);
 
 		/* Update size, source and destination pointers */
 		size -= length;
@@ -470,78 +466,77 @@
 		src += length;
 	}
 
-	while (( size - pDataFlash->pDevice->pages_size ) >= 0 ) {
+	while ((size - pDataFlash->pDevice->pages_size) >= 0) {
 		/* program dataflash page */
 		page = (unsigned int)dest / (pDataFlash->pDevice->pages_size);
 
 		status = AT91F_DataFlashWriteBuffer(pDataFlash,
-				DB_BUF1_WRITE, src, 0,
-				pDataFlash->pDevice->pages_size);
+					DB_BUF1_WRITE, src, 0,
+					pDataFlash->pDevice->
+					pages_size);
 		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
-						AT91C_TIMEOUT_WRDY);
+					 AT91C_TIMEOUT_WRDY);
 
 		status = AT91F_PageErase(pDataFlash, page);
 		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
-						AT91C_TIMEOUT_WRDY);
+					 AT91C_TIMEOUT_WRDY);
 		if (!status)
 			return DATAFLASH_ERROR;
 
-		status = AT91F_WriteBufferToMain (pDataFlash,
-						DB_BUF1_PAGE_PGM, dest);
-		if(!status)
+		status = AT91F_WriteBufferToMain(pDataFlash,
+					 DB_BUF1_PAGE_PGM, dest);
+		if (!status)
 			return DATAFLASH_ERROR;
 
 		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
-						AT91C_TIMEOUT_WRDY);
+					 AT91C_TIMEOUT_WRDY);
 
 		/* Update size, source and destination pointers */
 		size -= pDataFlash->pDevice->pages_size;
 		dest += pDataFlash->pDevice->pages_size;
-		src  += pDataFlash->pDevice->pages_size;
+		src += pDataFlash->pDevice->pages_size;
 	}
 
 	/* If still some bytes to read */
-	if ( size > 0 ) {
+	if (size > 0) {
 		/* program dataflash page */
-		if(!AT91F_PartialPageWrite(pDataFlash, src, dest, size) )
+		if (!AT91F_PartialPageWrite(pDataFlash, src, dest, size))
 			return DATAFLASH_ERROR;
 
 		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
-						AT91C_TIMEOUT_WRDY);
+					 AT91C_TIMEOUT_WRDY);
 	}
 	return DATAFLASH_OK;
 }
 
-
 /*---------------------------------------------------------------------------*/
 /* Function Name       : AT91F_DataFlashRead 				     */
 /* Object              : Read a block in dataflash			     */
 /* Input Parameters    : 						     */
 /* Return value		: 						     */
 /*---------------------------------------------------------------------------*/
-int AT91F_DataFlashRead(
-	AT91PS_DataFlash pDataFlash,
-	unsigned long addr,
-	unsigned long size,
-	char *buffer)
+int AT91F_DataFlashRead(AT91PS_DataFlash pDataFlash,
+			unsigned long addr, unsigned long size, char *buffer)
 {
 	unsigned long SizeToRead;
 
 	AT91F_SpiEnable(pDataFlash->pDevice->cs);
 
-	if(AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
+	if (AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
 					AT91C_TIMEOUT_WRDY) != DATAFLASH_OK)
 		return -1;
 
 	while (size) {
-		SizeToRead = (size < 0x8000)? size:0x8000;
+		SizeToRead = (size < 0x8000) ? size : 0x8000;
 
 		if (AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
-					AT91C_TIMEOUT_WRDY) != DATAFLASH_OK)
+					AT91C_TIMEOUT_WRDY) !=
+						DATAFLASH_OK)
 			return -1;
 
-		if (AT91F_DataFlashContinuousRead (pDataFlash, addr,
-				(uchar *) buffer, SizeToRead) != DATAFLASH_OK)
+		if (AT91F_DataFlashContinuousRead(pDataFlash, addr,
+						(uchar *) buffer,
+						SizeToRead) != DATAFLASH_OK)
 			return -1;
 
 		size -= SizeToRead;
@@ -558,9 +553,10 @@
 /* Input Parameters    : 						     */
 /* Return value	       : Dataflash status register			     */
 /*---------------------------------------------------------------------------*/
-int AT91F_DataflashProbe(int cs, AT91PS_DataflashDesc pDesc) {
+int AT91F_DataflashProbe(int cs, AT91PS_DataflashDesc pDesc)
+{
 	AT91F_SpiEnable(cs);
 	AT91F_DataFlashGetStatus(pDesc);
-	return((pDesc->command[1] == 0xFF)? 0: pDesc->command[1] & 0x3C);
+	return ((pDesc->command[1] == 0xFF) ? 0 : pDesc->command[1] & 0x3C);
 }
 #endif
diff --git a/drivers/onenand/Makefile b/drivers/onenand/Makefile
new file mode 100644
index 0000000..2049413
--- /dev/null
+++ b/drivers/onenand/Makefile
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2005-2007 Samsung Electronics.
+# Kyungmin Park <kyungmin.park@samsung.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	:= $(obj)libonenand.a
+
+COBJS	:= onenand_base.o onenand_bbt.o
+
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/onenand/onenand_base.c b/drivers/onenand/onenand_base.c
new file mode 100644
index 0000000..7983a4a
--- /dev/null
+++ b/drivers/onenand/onenand_base.c
@@ -0,0 +1,1294 @@
+/*
+ *  linux/drivers/mtd/onenand/onenand_base.c
+ *
+ *  Copyright (C) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_CMD_ONENAND
+
+#include <linux/mtd/compat.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+
+#include <asm/io.h>
+#include <asm/errno.h>
+
+static const unsigned char ffchars[] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	/* 16 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	/* 32 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	/* 48 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	/* 64 */
+};
+
+/**
+ * onenand_readw - [OneNAND Interface] Read OneNAND register
+ * @param addr		address to read
+ *
+ * Read OneNAND register
+ */
+static unsigned short onenand_readw(void __iomem * addr)
+{
+	return readw(addr);
+}
+
+/**
+ * onenand_writew - [OneNAND Interface] Write OneNAND register with value
+ * @param value		value to write
+ * @param addr		address to write
+ *
+ * Write OneNAND register with value
+ */
+static void onenand_writew(unsigned short value, void __iomem * addr)
+{
+	writew(value, addr);
+}
+
+/**
+ * onenand_block_address - [DEFAULT] Get block address
+ * @param device	the device id
+ * @param block		the block
+ * @return		translated block address if DDP, otherwise same
+ *
+ * Setup Start Address 1 Register (F100h)
+ */
+static int onenand_block_address(int device, int block)
+{
+	if (device & ONENAND_DEVICE_IS_DDP) {
+		/* Device Flash Core select, NAND Flash Block Address */
+		int dfs = 0, density, mask;
+
+		density = device >> ONENAND_DEVICE_DENSITY_SHIFT;
+		mask = (1 << (density + 6));
+
+		if (block & mask)
+			dfs = 1;
+
+		return (dfs << ONENAND_DDP_SHIFT) | (block & (mask - 1));
+	}
+
+	return block;
+}
+
+/**
+ * onenand_bufferram_address - [DEFAULT] Get bufferram address
+ * @param device	the device id
+ * @param block		the block
+ * @return		set DBS value if DDP, otherwise 0
+ *
+ * Setup Start Address 2 Register (F101h) for DDP
+ */
+static int onenand_bufferram_address(int device, int block)
+{
+	if (device & ONENAND_DEVICE_IS_DDP) {
+		/* Device BufferRAM Select */
+		int dbs = 0, density, mask;
+
+		density = device >> ONENAND_DEVICE_DENSITY_SHIFT;
+		mask = (1 << (density + 6));
+
+		if (block & mask)
+			dbs = 1;
+
+		return (dbs << ONENAND_DDP_SHIFT);
+	}
+
+	return 0;
+}
+
+/**
+ * onenand_page_address - [DEFAULT] Get page address
+ * @param page		the page address
+ * @param sector	the sector address
+ * @return		combined page and sector address
+ *
+ * Setup Start Address 8 Register (F107h)
+ */
+static int onenand_page_address(int page, int sector)
+{
+	/* Flash Page Address, Flash Sector Address */
+	int fpa, fsa;
+
+	fpa = page & ONENAND_FPA_MASK;
+	fsa = sector & ONENAND_FSA_MASK;
+
+	return ((fpa << ONENAND_FPA_SHIFT) | fsa);
+}
+
+/**
+ * onenand_buffer_address - [DEFAULT] Get buffer address
+ * @param dataram1	DataRAM index
+ * @param sectors	the sector address
+ * @param count		the number of sectors
+ * @return		the start buffer value
+ *
+ * Setup Start Buffer Register (F200h)
+ */
+static int onenand_buffer_address(int dataram1, int sectors, int count)
+{
+	int bsa, bsc;
+
+	/* BufferRAM Sector Address */
+	bsa = sectors & ONENAND_BSA_MASK;
+
+	if (dataram1)
+		bsa |= ONENAND_BSA_DATARAM1;	/* DataRAM1 */
+	else
+		bsa |= ONENAND_BSA_DATARAM0;	/* DataRAM0 */
+
+	/* BufferRAM Sector Count */
+	bsc = count & ONENAND_BSC_MASK;
+
+	return ((bsa << ONENAND_BSA_SHIFT) | bsc);
+}
+
+/**
+ * onenand_command - [DEFAULT] Send command to OneNAND device
+ * @param mtd		MTD device structure
+ * @param cmd		the command to be sent
+ * @param addr		offset to read from or write to
+ * @param len		number of bytes to read or write
+ *
+ * Send command to OneNAND device. This function is used for middle/large page
+ * devices (1KB/2KB Bytes per page)
+ */
+static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr,
+			   size_t len)
+{
+	struct onenand_chip *this = mtd->priv;
+	int value, readcmd = 0;
+	int block, page;
+	/* Now we use page size operation */
+	int sectors = 4, count = 4;
+
+	/* Address translation */
+	switch (cmd) {
+	case ONENAND_CMD_UNLOCK:
+	case ONENAND_CMD_LOCK:
+	case ONENAND_CMD_LOCK_TIGHT:
+		block = -1;
+		page = -1;
+		break;
+
+	case ONENAND_CMD_ERASE:
+	case ONENAND_CMD_BUFFERRAM:
+		block = (int)(addr >> this->erase_shift);
+		page = -1;
+		break;
+
+	default:
+		block = (int)(addr >> this->erase_shift);
+		page = (int)(addr >> this->page_shift);
+		page &= this->page_mask;
+		break;
+	}
+
+	/* NOTE: The setting order of the registers is very important! */
+	if (cmd == ONENAND_CMD_BUFFERRAM) {
+		/* Select DataRAM for DDP */
+		value = onenand_bufferram_address(this->device_id, block);
+		this->write_word(value,
+				 this->base + ONENAND_REG_START_ADDRESS2);
+
+		/* Switch to the next data buffer */
+		ONENAND_SET_NEXT_BUFFERRAM(this);
+
+		return 0;
+	}
+
+	if (block != -1) {
+		/* Write 'DFS, FBA' of Flash */
+		value = onenand_block_address(this->device_id, block);
+		this->write_word(value,
+				 this->base + ONENAND_REG_START_ADDRESS1);
+	}
+
+	if (page != -1) {
+		int dataram;
+
+		switch (cmd) {
+		case ONENAND_CMD_READ:
+		case ONENAND_CMD_READOOB:
+			dataram = ONENAND_SET_NEXT_BUFFERRAM(this);
+			readcmd = 1;
+			break;
+
+		default:
+			dataram = ONENAND_CURRENT_BUFFERRAM(this);
+			break;
+		}
+
+		/* Write 'FPA, FSA' of Flash */
+		value = onenand_page_address(page, sectors);
+		this->write_word(value,
+				 this->base + ONENAND_REG_START_ADDRESS8);
+
+		/* Write 'BSA, BSC' of DataRAM */
+		value = onenand_buffer_address(dataram, sectors, count);
+		this->write_word(value, this->base + ONENAND_REG_START_BUFFER);
+
+		if (readcmd) {
+			/* Select DataRAM for DDP */
+			value =
+			    onenand_bufferram_address(this->device_id, block);
+			this->write_word(value,
+					 this->base +
+					 ONENAND_REG_START_ADDRESS2);
+		}
+	}
+
+	/* Interrupt clear */
+	this->write_word(ONENAND_INT_CLEAR, this->base + ONENAND_REG_INTERRUPT);
+	/* Write command */
+	this->write_word(cmd, this->base + ONENAND_REG_COMMAND);
+
+	return 0;
+}
+
+/**
+ * onenand_wait - [DEFAULT] wait until the command is done
+ * @param mtd		MTD device structure
+ * @param state		state to select the max. timeout value
+ *
+ * Wait for command done. This applies to all OneNAND command
+ * Read can take up to 30us, erase up to 2ms and program up to 350us
+ * according to general OneNAND specs
+ */
+static int onenand_wait(struct mtd_info *mtd, int state)
+{
+	struct onenand_chip *this = mtd->priv;
+	unsigned int flags = ONENAND_INT_MASTER;
+	unsigned int interrupt = 0;
+	unsigned int ctrl, ecc;
+
+	while (1) {
+		interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
+		if (interrupt & flags)
+			break;
+	}
+
+	ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
+
+	if (ctrl & ONENAND_CTRL_ERROR) {
+		DEBUG(MTD_DEBUG_LEVEL0,
+		      "onenand_wait: controller error = 0x%04x\n", ctrl);
+		return -EAGAIN;
+	}
+
+	if (ctrl & ONENAND_CTRL_LOCK) {
+		DEBUG(MTD_DEBUG_LEVEL0,
+		      "onenand_wait: it's locked error = 0x%04x\n", ctrl);
+		return -EIO;
+	}
+
+	if (interrupt & ONENAND_INT_READ) {
+		ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
+		if (ecc & ONENAND_ECC_2BIT_ALL) {
+			DEBUG(MTD_DEBUG_LEVEL0,
+			      "onenand_wait: ECC error = 0x%04x\n", ecc);
+			return -EBADMSG;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * onenand_bufferram_offset - [DEFAULT] BufferRAM offset
+ * @param mtd		MTD data structure
+ * @param area		BufferRAM area
+ * @return		offset given area
+ *
+ * Return BufferRAM offset given area
+ */
+static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area)
+{
+	struct onenand_chip *this = mtd->priv;
+
+	if (ONENAND_CURRENT_BUFFERRAM(this)) {
+		if (area == ONENAND_DATARAM)
+			return mtd->oobblock;
+		if (area == ONENAND_SPARERAM)
+			return mtd->oobsize;
+	}
+
+	return 0;
+}
+
+/**
+ * onenand_read_bufferram - [OneNAND Interface] Read the bufferram area
+ * @param mtd		MTD data structure
+ * @param area		BufferRAM area
+ * @param buffer	the databuffer to put/get data
+ * @param offset	offset to read from or write to
+ * @param count		number of bytes to read/write
+ *
+ * Read the BufferRAM area
+ */
+static int onenand_read_bufferram(struct mtd_info *mtd, int area,
+				  unsigned char *buffer, int offset,
+				  size_t count)
+{
+	struct onenand_chip *this = mtd->priv;
+	void __iomem *bufferram;
+
+	bufferram = this->base + area;
+	bufferram += onenand_bufferram_offset(mtd, area);
+
+	memcpy(buffer, bufferram + offset, count);
+
+	return 0;
+}
+
+/**
+ * onenand_sync_read_bufferram - [OneNAND Interface] Read the bufferram area with Sync. Burst mode
+ * @param mtd		MTD data structure
+ * @param area		BufferRAM area
+ * @param buffer	the databuffer to put/get data
+ * @param offset	offset to read from or write to
+ * @param count		number of bytes to read/write
+ *
+ * Read the BufferRAM area with Sync. Burst Mode
+ */
+static int onenand_sync_read_bufferram(struct mtd_info *mtd, int area,
+				       unsigned char *buffer, int offset,
+				       size_t count)
+{
+	struct onenand_chip *this = mtd->priv;
+	void __iomem *bufferram;
+
+	bufferram = this->base + area;
+	bufferram += onenand_bufferram_offset(mtd, area);
+
+	this->mmcontrol(mtd, ONENAND_SYS_CFG1_SYNC_READ);
+
+	memcpy(buffer, bufferram + offset, count);
+
+	this->mmcontrol(mtd, 0);
+
+	return 0;
+}
+
+/**
+ * onenand_write_bufferram - [OneNAND Interface] Write the bufferram area
+ * @param mtd		MTD data structure
+ * @param area		BufferRAM area
+ * @param buffer	the databuffer to put/get data
+ * @param offset	offset to read from or write to
+ * @param count		number of bytes to read/write
+ *
+ * Write the BufferRAM area
+ */
+static int onenand_write_bufferram(struct mtd_info *mtd, int area,
+				   const unsigned char *buffer, int offset,
+				   size_t count)
+{
+	struct onenand_chip *this = mtd->priv;
+	void __iomem *bufferram;
+
+	bufferram = this->base + area;
+	bufferram += onenand_bufferram_offset(mtd, area);
+
+	memcpy(bufferram + offset, buffer, count);
+
+	return 0;
+}
+
+/**
+ * onenand_check_bufferram - [GENERIC] Check BufferRAM information
+ * @param mtd		MTD data structure
+ * @param addr		address to check
+ * @return		1 if there are valid data, otherwise 0
+ *
+ * Check bufferram if there is data we required
+ */
+static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr)
+{
+	struct onenand_chip *this = mtd->priv;
+	int block, page;
+	int i;
+
+	block = (int)(addr >> this->erase_shift);
+	page = (int)(addr >> this->page_shift);
+	page &= this->page_mask;
+
+	i = ONENAND_CURRENT_BUFFERRAM(this);
+
+	/* Is there valid data? */
+	if (this->bufferram[i].block == block &&
+	    this->bufferram[i].page == page && this->bufferram[i].valid)
+		return 1;
+
+	return 0;
+}
+
+/**
+ * onenand_update_bufferram - [GENERIC] Update BufferRAM information
+ * @param mtd		MTD data structure
+ * @param addr		address to update
+ * @param valid		valid flag
+ *
+ * Update BufferRAM information
+ */
+static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr,
+				    int valid)
+{
+	struct onenand_chip *this = mtd->priv;
+	int block, page;
+	int i;
+
+	block = (int)(addr >> this->erase_shift);
+	page = (int)(addr >> this->page_shift);
+	page &= this->page_mask;
+
+	/* Invalidate BufferRAM */
+	for (i = 0; i < MAX_BUFFERRAM; i++) {
+		if (this->bufferram[i].block == block &&
+		    this->bufferram[i].page == page)
+			this->bufferram[i].valid = 0;
+	}
+
+	/* Update BufferRAM */
+	i = ONENAND_CURRENT_BUFFERRAM(this);
+	this->bufferram[i].block = block;
+	this->bufferram[i].page = page;
+	this->bufferram[i].valid = valid;
+
+	return 0;
+}
+
+/**
+ * onenand_get_device - [GENERIC] Get chip for selected access
+ * @param mtd		MTD device structure
+ * @param new_state	the state which is requested
+ *
+ * Get the device and lock it for exclusive access
+ */
+static void onenand_get_device(struct mtd_info *mtd, int new_state)
+{
+	/* Do nothing */
+}
+
+/**
+ * onenand_release_device - [GENERIC] release chip
+ * @param mtd		MTD device structure
+ *
+ * Deselect, release chip lock and wake up anyone waiting on the device
+ */
+static void onenand_release_device(struct mtd_info *mtd)
+{
+	/* Do nothing */
+}
+
+/**
+ * onenand_read_ecc - [MTD Interface] Read data with ECC
+ * @param mtd		MTD device structure
+ * @param from		offset to read from
+ * @param len		number of bytes to read
+ * @param retlen	pointer to variable to store the number of read bytes
+ * @param buf		the databuffer to put data
+ * @param oob_buf	filesystem supplied oob data buffer
+ * @param oobsel	oob selection structure
+ *
+ * OneNAND read with ECC
+ */
+static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
+			    size_t * retlen, u_char * buf,
+			    u_char * oob_buf, struct nand_oobinfo *oobsel)
+{
+	struct onenand_chip *this = mtd->priv;
+	int read = 0, column;
+	int thislen;
+	int ret = 0;
+
+	DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ecc: from = 0x%08x, len = %i\n",
+	      (unsigned int)from, (int)len);
+
+	/* Do not allow reads past end of device */
+	if ((from + len) > mtd->size) {
+		DEBUG(MTD_DEBUG_LEVEL0,
+		      "onenand_read_ecc: Attempt read beyond end of device\n");
+		*retlen = 0;
+		return -EINVAL;
+	}
+
+	/* Grab the lock and see if the device is available */
+	onenand_get_device(mtd, FL_READING);
+
+	while (read < len) {
+		thislen = min_t(int, mtd->oobblock, len - read);
+
+		column = from & (mtd->oobblock - 1);
+		if (column + thislen > mtd->oobblock)
+			thislen = mtd->oobblock - column;
+
+		if (!onenand_check_bufferram(mtd, from)) {
+			this->command(mtd, ONENAND_CMD_READ, from,
+				      mtd->oobblock);
+			ret = this->wait(mtd, FL_READING);
+			/* First copy data and check return value for ECC handling */
+			onenand_update_bufferram(mtd, from, 1);
+		}
+
+		this->read_bufferram(mtd, ONENAND_DATARAM, buf, column,
+				     thislen);
+
+		read += thislen;
+		if (read == len)
+			break;
+
+		if (ret) {
+			DEBUG(MTD_DEBUG_LEVEL0,
+			      "onenand_read_ecc: read failed = %d\n", ret);
+			break;
+		}
+
+		from += thislen;
+		buf += thislen;
+	}
+
+	/* Deselect and wake up anyone waiting on the device */
+	onenand_release_device(mtd);
+
+	/*
+	 * Return success, if no ECC failures, else -EBADMSG
+	 * fs driver will take care of that, because
+	 * retlen == desired len and result == -EBADMSG
+	 */
+	*retlen = read;
+	return ret;
+}
+
+/**
+ * onenand_read - [MTD Interface] MTD compability function for onenand_read_ecc
+ * @param mtd		MTD device structure
+ * @param from		offset to read from
+ * @param len		number of bytes to read
+ * @param retlen	pointer to variable to store the number of read bytes
+ * @param buf		the databuffer to put data
+ *
+ * This function simply calls onenand_read_ecc with oob buffer and oobsel = NULL
+*/
+int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
+		 size_t * retlen, u_char * buf)
+{
+	return onenand_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
+}
+
+/**
+ * onenand_read_oob - [MTD Interface] OneNAND read out-of-band
+ * @param mtd		MTD device structure
+ * @param from		offset to read from
+ * @param len		number of bytes to read
+ * @param retlen	pointer to variable to store the number of read bytes
+ * @param buf		the databuffer to put data
+ *
+ * OneNAND read out-of-band data from the spare area
+ */
+int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
+		     size_t * retlen, u_char * buf)
+{
+	struct onenand_chip *this = mtd->priv;
+	int read = 0, thislen, column;
+	int ret = 0;
+
+	DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob: from = 0x%08x, len = %i\n",
+	      (unsigned int)from, (int)len);
+
+	/* Initialize return length value */
+	*retlen = 0;
+
+	/* Do not allow reads past end of device */
+	if (unlikely((from + len) > mtd->size)) {
+		DEBUG(MTD_DEBUG_LEVEL0,
+		      "onenand_read_oob: Attempt read beyond end of device\n");
+		return -EINVAL;
+	}
+
+	/* Grab the lock and see if the device is available */
+	onenand_get_device(mtd, FL_READING);
+
+	column = from & (mtd->oobsize - 1);
+
+	while (read < len) {
+		thislen = mtd->oobsize - column;
+		thislen = min_t(int, thislen, len);
+
+		this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);
+
+		onenand_update_bufferram(mtd, from, 0);
+
+		ret = this->wait(mtd, FL_READING);
+		/* First copy data and check return value for ECC handling */
+
+		this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column,
+				     thislen);
+
+		read += thislen;
+		if (read == len)
+			break;
+
+		if (ret) {
+			DEBUG(MTD_DEBUG_LEVEL0,
+			      "onenand_read_oob: read failed = %d\n", ret);
+			break;
+		}
+
+		buf += thislen;
+		/* Read more? */
+		if (read < len) {
+			/* Page size */
+			from += mtd->oobblock;
+			column = 0;
+		}
+	}
+
+	/* Deselect and wake up anyone waiting on the device */
+	onenand_release_device(mtd);
+
+	*retlen = read;
+	return ret;
+}
+
+#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
+/**
+ * onenand_verify_page - [GENERIC] verify the chip contents after a write
+ * @param mtd		MTD device structure
+ * @param buf		the databuffer to verify
+ * @param block		block address
+ * @param page		page address
+ *
+ * Check DataRAM area directly
+ */
+static int onenand_verify_page(struct mtd_info *mtd, u_char * buf,
+			       loff_t addr, int block, int page)
+{
+	struct onenand_chip *this = mtd->priv;
+	void __iomem *dataram0, *dataram1;
+	int ret = 0;
+
+	this->command(mtd, ONENAND_CMD_READ, addr, mtd->oobblock);
+
+	ret = this->wait(mtd, FL_READING);
+	if (ret)
+		return ret;
+
+	onenand_update_bufferram(mtd, addr, 1);
+
+	/* Check, if the two dataram areas are same */
+	dataram0 = this->base + ONENAND_DATARAM;
+	dataram1 = dataram0 + mtd->oobblock;
+
+	if (memcmp(dataram0, dataram1, mtd->oobblock))
+		return -EBADMSG;
+
+	return 0;
+}
+#else
+#define onenand_verify_page(...)	(0)
+#endif
+
+#define NOTALIGNED(x)	((x & (mtd->oobblock - 1)) != 0)
+
+/**
+ * onenand_write_ecc - [MTD Interface] OneNAND write with ECC
+ * @param mtd		MTD device structure
+ * @param to		offset to write to
+ * @param len		number of bytes to write
+ * @param retlen	pointer to variable to store the number of written bytes
+ * @param buf		the data to write
+ * @param eccbuf	filesystem supplied oob data buffer
+ * @param oobsel	oob selection structure
+ *
+ * OneNAND write with ECC
+ */
+static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
+			     size_t * retlen, const u_char * buf,
+			     u_char * eccbuf, struct nand_oobinfo *oobsel)
+{
+	struct onenand_chip *this = mtd->priv;
+	int written = 0;
+	int ret = 0;
+
+	DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ecc: to = 0x%08x, len = %i\n",
+	      (unsigned int)to, (int)len);
+
+	/* Initialize retlen, in case of early exit */
+	*retlen = 0;
+
+	/* Do not allow writes past end of device */
+	if (unlikely((to + len) > mtd->size)) {
+		DEBUG(MTD_DEBUG_LEVEL0,
+		      "onenand_write_ecc: Attempt write to past end of device\n");
+		return -EINVAL;
+	}
+
+	/* Reject writes, which are not page aligned */
+	if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
+		DEBUG(MTD_DEBUG_LEVEL0,
+		      "onenand_write_ecc: Attempt to write not page aligned data\n");
+		return -EINVAL;
+	}
+
+	/* Grab the lock and see if the device is available */
+	onenand_get_device(mtd, FL_WRITING);
+
+	/* Loop until all data write */
+	while (written < len) {
+		int thislen = min_t(int, mtd->oobblock, len - written);
+
+		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock);
+
+		this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen);
+		this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0,
+				      mtd->oobsize);
+
+		this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock);
+
+		onenand_update_bufferram(mtd, to, 1);
+
+		ret = this->wait(mtd, FL_WRITING);
+		if (ret) {
+			DEBUG(MTD_DEBUG_LEVEL0,
+			      "onenand_write_ecc: write filaed %d\n", ret);
+			break;
+		}
+
+		written += thislen;
+
+		/* Only check verify write turn on */
+		ret = onenand_verify_page(mtd, (u_char *) buf, to, block, page);
+		if (ret) {
+			DEBUG(MTD_DEBUG_LEVEL0,
+			      "onenand_write_ecc: verify failed %d\n", ret);
+			break;
+		}
+
+		if (written == len)
+			break;
+
+		to += thislen;
+		buf += thislen;
+	}
+
+	/* Deselect and wake up anyone waiting on the device */
+	onenand_release_device(mtd);
+
+	*retlen = written;
+
+	return ret;
+}
+
+/**
+ * onenand_write - [MTD Interface] compability function for onenand_write_ecc
+ * @param mtd		MTD device structure
+ * @param to		offset to write to
+ * @param len		number of bytes to write
+ * @param retlen	pointer to variable to store the number of written bytes
+ * @param buf		the data to write
+ *
+ * This function simply calls onenand_write_ecc
+ * with oob buffer and oobsel = NULL
+ */
+int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
+		  size_t * retlen, const u_char * buf)
+{
+	return onenand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL);
+}
+
+/**
+ * onenand_write_oob - [MTD Interface] OneNAND write out-of-band
+ * @param mtd		MTD device structure
+ * @param to		offset to write to
+ * @param len		number of bytes to write
+ * @param retlen	pointer to variable to store the number of written bytes
+ * @param buf		the data to write
+ *
+ * OneNAND write out-of-band
+ */
+int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
+		      size_t * retlen, const u_char * buf)
+{
+	struct onenand_chip *this = mtd->priv;
+	int column, status;
+	int written = 0;
+
+	DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n",
+	      (unsigned int)to, (int)len);
+
+	/* Initialize retlen, in case of early exit */
+	*retlen = 0;
+
+	/* Do not allow writes past end of device */
+	if (unlikely((to + len) > mtd->size)) {
+		DEBUG(MTD_DEBUG_LEVEL0,
+		      "onenand_write_oob: Attempt write to past end of device\n");
+		return -EINVAL;
+	}
+
+	/* Grab the lock and see if the device is available */
+	onenand_get_device(mtd, FL_WRITING);
+
+	/* Loop until all data write */
+	while (written < len) {
+		int thislen = min_t(int, mtd->oobsize, len - written);
+
+		column = to & (mtd->oobsize - 1);
+
+		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize);
+
+		this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0,
+				      mtd->oobsize);
+		this->write_bufferram(mtd, ONENAND_SPARERAM, buf, column,
+				      thislen);
+
+		this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
+
+		onenand_update_bufferram(mtd, to, 0);
+
+		status = this->wait(mtd, FL_WRITING);
+		if (status)
+			break;
+
+		written += thislen;
+		if (written == len)
+			break;
+
+		to += thislen;
+		buf += thislen;
+	}
+
+	/* Deselect and wake up anyone waiting on the device */
+	onenand_release_device(mtd);
+
+	*retlen = written;
+
+	return 0;
+}
+
+/**
+ * onenand_erase - [MTD Interface] erase block(s)
+ * @param mtd		MTD device structure
+ * @param instr		erase instruction
+ *
+ * Erase one ore more blocks
+ */
+int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct onenand_chip *this = mtd->priv;
+	unsigned int block_size;
+	loff_t addr;
+	int len;
+	int ret = 0;
+
+	DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len = %i\n",
+	      (unsigned int)instr->addr, (unsigned int)instr->len);
+
+	block_size = (1 << this->erase_shift);
+
+	/* Start address must align on block boundary */
+	if (unlikely(instr->addr & (block_size - 1))) {
+		DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Unaligned address\n");
+		return -EINVAL;
+	}
+
+	/* Length must align on block boundary */
+	if (unlikely(instr->len & (block_size - 1))) {
+		DEBUG(MTD_DEBUG_LEVEL0,
+		      "onenand_erase: Length not block aligned\n");
+		return -EINVAL;
+	}
+
+	/* Do not allow erase past end of device */
+	if (unlikely((instr->len + instr->addr) > mtd->size)) {
+		DEBUG(MTD_DEBUG_LEVEL0,
+		      "onenand_erase: Erase past end of device\n");
+		return -EINVAL;
+	}
+
+	instr->fail_addr = 0xffffffff;
+
+	/* Grab the lock and see if the device is available */
+	onenand_get_device(mtd, FL_ERASING);
+
+	/* Loop throught the pages */
+	len = instr->len;
+	addr = instr->addr;
+
+	instr->state = MTD_ERASING;
+
+	while (len) {
+
+		/* TODO Check badblock */
+
+		this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
+
+		ret = this->wait(mtd, FL_ERASING);
+		/* Check, if it is write protected */
+		if (ret) {
+			if (ret == -EPERM)
+				DEBUG(MTD_DEBUG_LEVEL0,
+				      "onenand_erase: Device is write protected!!!\n");
+			else
+				DEBUG(MTD_DEBUG_LEVEL0,
+				      "onenand_erase: Failed erase, block %d\n",
+				      (unsigned)(addr >> this->erase_shift));
+			instr->state = MTD_ERASE_FAILED;
+			instr->fail_addr = addr;
+			goto erase_exit;
+		}
+
+		len -= block_size;
+		addr += block_size;
+	}
+
+	instr->state = MTD_ERASE_DONE;
+
+      erase_exit:
+
+	ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
+	/* Do call back function */
+	if (!ret)
+		mtd_erase_callback(instr);
+
+	/* Deselect and wake up anyone waiting on the device */
+	onenand_release_device(mtd);
+
+	return ret;
+}
+
+/**
+ * onenand_sync - [MTD Interface] sync
+ * @param mtd		MTD device structure
+ *
+ * Sync is actually a wait for chip ready function
+ */
+void onenand_sync(struct mtd_info *mtd)
+{
+	DEBUG(MTD_DEBUG_LEVEL3, "onenand_sync: called\n");
+
+	/* Grab the lock and see if the device is available */
+	onenand_get_device(mtd, FL_SYNCING);
+
+	/* Release it and go back */
+	onenand_release_device(mtd);
+}
+
+/**
+ * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
+ * @param mtd		MTD device structure
+ * @param ofs		offset relative to mtd start
+ */
+int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs)
+{
+	/*
+	 * TODO
+	 * 1. Bad block table (BBT)
+	 *   -> using NAND BBT to support JFFS2
+	 * 2. Bad block management (BBM)
+	 *   -> bad block replace scheme
+	 *
+	 * Currently we do nothing
+	 */
+	return 0;
+}
+
+/**
+ * onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
+ * @param mtd		MTD device structure
+ * @param ofs		offset relative to mtd start
+ */
+int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+	/* see above */
+	return 0;
+}
+
+/**
+ * onenand_unlock - [MTD Interface] Unlock block(s)
+ * @param mtd		MTD device structure
+ * @param ofs		offset relative to mtd start
+ * @param len		number of bytes to unlock
+ *
+ * Unlock one or more blocks
+ */
+int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+	struct onenand_chip *this = mtd->priv;
+	int start, end, block, value, status;
+
+	start = ofs >> this->erase_shift;
+	end = len >> this->erase_shift;
+
+	/* Continuous lock scheme */
+	if (this->options & ONENAND_CONT_LOCK) {
+		/* Set start block address */
+		this->write_word(start,
+				 this->base + ONENAND_REG_START_BLOCK_ADDRESS);
+		/* Set end block address */
+		this->write_word(end - 1,
+				 this->base + ONENAND_REG_END_BLOCK_ADDRESS);
+		/* Write unlock command */
+		this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0);
+
+		/* There's no return value */
+		this->wait(mtd, FL_UNLOCKING);
+
+		/* Sanity check */
+		while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
+		       & ONENAND_CTRL_ONGO)
+			continue;
+
+		/* Check lock status */
+		status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
+		if (!(status & ONENAND_WP_US))
+			printk(KERN_ERR "wp status = 0x%x\n", status);
+
+		return 0;
+	}
+
+	/* Block lock scheme */
+	for (block = start; block < end; block++) {
+		/* Set start block address */
+		this->write_word(block,
+				 this->base + ONENAND_REG_START_BLOCK_ADDRESS);
+		/* Write unlock command */
+		this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0);
+
+		/* There's no return value */
+		this->wait(mtd, FL_UNLOCKING);
+
+		/* Sanity check */
+		while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
+		       & ONENAND_CTRL_ONGO)
+			continue;
+
+		/* Set block address for read block status */
+		value = onenand_block_address(this->device_id, block);
+		this->write_word(value,
+				 this->base + ONENAND_REG_START_ADDRESS1);
+
+		/* Check lock status */
+		status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
+		if (!(status & ONENAND_WP_US))
+			printk(KERN_ERR "block = %d, wp status = 0x%x\n",
+			       block, status);
+	}
+
+	return 0;
+}
+
+/**
+ * onenand_print_device_info - Print device ID
+ * @param device        device ID
+ *
+ * Print device ID
+ */
+void onenand_print_device_info(int device, int verbose)
+{
+	int vcc, demuxed, ddp, density;
+
+	if (!verbose)
+		return;
+
+	vcc = device & ONENAND_DEVICE_VCC_MASK;
+	demuxed = device & ONENAND_DEVICE_IS_DEMUX;
+	ddp = device & ONENAND_DEVICE_IS_DDP;
+	density = device >> ONENAND_DEVICE_DENSITY_SHIFT;
+	printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n",
+	       demuxed ? "" : "Muxed ",
+	       ddp ? "(DDP)" : "",
+	       (16 << density), vcc ? "2.65/3.3" : "1.8", device);
+}
+
+static const struct onenand_manufacturers onenand_manuf_ids[] = {
+	{ONENAND_MFR_SAMSUNG, "Samsung"},
+	{ONENAND_MFR_UNKNOWN, "Unknown"}
+};
+
+/**
+ * onenand_check_maf - Check manufacturer ID
+ * @param manuf         manufacturer ID
+ *
+ * Check manufacturer ID
+ */
+static int onenand_check_maf(int manuf)
+{
+	int i;
+
+	for (i = 0; onenand_manuf_ids[i].id; i++) {
+		if (manuf == onenand_manuf_ids[i].id)
+			break;
+	}
+
+#ifdef ONENAND_DEBUG
+	printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n",
+	       onenand_manuf_ids[i].name, manuf);
+#endif
+
+	return (i != ONENAND_MFR_UNKNOWN);
+}
+
+/**
+ * onenand_probe - [OneNAND Interface] Probe the OneNAND device
+ * @param mtd		MTD device structure
+ *
+ * OneNAND detection method:
+ *   Compare the the values from command with ones from register
+ */
+static int onenand_probe(struct mtd_info *mtd)
+{
+	struct onenand_chip *this = mtd->priv;
+	int bram_maf_id, bram_dev_id, maf_id, dev_id;
+	int version_id;
+	int density;
+
+	/* Send the command for reading device ID from BootRAM */
+	this->write_word(ONENAND_CMD_READID, this->base + ONENAND_BOOTRAM);
+
+	/* Read manufacturer and device IDs from BootRAM */
+	bram_maf_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x0);
+	bram_dev_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x2);
+
+	/* Check manufacturer ID */
+	if (onenand_check_maf(bram_maf_id))
+		return -ENXIO;
+
+	/* Reset OneNAND to read default register values */
+	this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
+
+	{
+		int i;
+		for (i = 0; i < 10000; i++) ;
+	}
+
+	/* Read manufacturer and device IDs from Register */
+	maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
+	dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
+
+	/* Check OneNAND device */
+	if (maf_id != bram_maf_id || dev_id != bram_dev_id)
+		return -ENXIO;
+
+	/* Flash device information */
+	onenand_print_device_info(dev_id, 0);
+	this->device_id = dev_id;
+
+	density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
+	this->chipsize = (16 << density) << 20;
+
+	/* OneNAND page size & block size */
+	/* The data buffer size is equal to page size */
+	mtd->oobblock =
+	    this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
+	mtd->oobsize = mtd->oobblock >> 5;
+	/* Pagers per block is always 64 in OneNAND */
+	mtd->erasesize = mtd->oobblock << 6;
+
+	this->erase_shift = ffs(mtd->erasesize) - 1;
+	this->page_shift = ffs(mtd->oobblock) - 1;
+	this->ppb_shift = (this->erase_shift - this->page_shift);
+	this->page_mask = (mtd->erasesize / mtd->oobblock) - 1;
+
+	/* REVIST: Multichip handling */
+
+	mtd->size = this->chipsize;
+
+	/* Version ID */
+	version_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
+#ifdef ONENAND_DEBUG
+	printk(KERN_DEBUG "OneNAND version = 0x%04x\n", version_id);
+#endif
+
+	/* Lock scheme */
+	if (density <= ONENAND_DEVICE_DENSITY_512Mb &&
+	    !(version_id >> ONENAND_VERSION_PROCESS_SHIFT)) {
+		printk(KERN_INFO "Lock scheme is Continues Lock\n");
+		this->options |= ONENAND_CONT_LOCK;
+	}
+
+	return 0;
+}
+
+/**
+ * onenand_scan - [OneNAND Interface] Scan for the OneNAND device
+ * @param mtd		MTD device structure
+ * @param maxchips	Number of chips to scan for
+ *
+ * This fills out all the not initialized function pointers
+ * with the defaults.
+ * The flash ID is read and the mtd/chip structures are
+ * filled with the appropriate values.
+ */
+int onenand_scan(struct mtd_info *mtd, int maxchips)
+{
+	struct onenand_chip *this = mtd->priv;
+
+	if (!this->read_word)
+		this->read_word = onenand_readw;
+	if (!this->write_word)
+		this->write_word = onenand_writew;
+
+	if (!this->command)
+		this->command = onenand_command;
+	if (!this->wait)
+		this->wait = onenand_wait;
+
+	if (!this->read_bufferram)
+		this->read_bufferram = onenand_read_bufferram;
+	if (!this->write_bufferram)
+		this->write_bufferram = onenand_write_bufferram;
+
+	if (onenand_probe(mtd))
+		return -ENXIO;
+
+	/* Set Sync. Burst Read after probing */
+	if (this->mmcontrol) {
+		printk(KERN_INFO "OneNAND Sync. Burst Read support\n");
+		this->read_bufferram = onenand_sync_read_bufferram;
+	}
+
+	onenand_unlock(mtd, 0, mtd->size);
+
+	return onenand_default_bbt(mtd);
+}
+
+/**
+ * onenand_release - [OneNAND Interface] Free resources held by the OneNAND device
+ * @param mtd		MTD device structure
+ */
+void onenand_release(struct mtd_info *mtd)
+{
+}
+
+/*
+ * OneNAND initialization at U-Boot
+ */
+struct mtd_info onenand_mtd;
+struct onenand_chip onenand_chip;
+
+void onenand_init(void)
+{
+	memset(&onenand_mtd, 0, sizeof(struct mtd_info));
+	memset(&onenand_chip, 0, sizeof(struct onenand_chip));
+
+	onenand_chip.base = (void *)CFG_ONENAND_BASE;
+	onenand_mtd.priv = &onenand_chip;
+
+	onenand_scan(&onenand_mtd, 1);
+
+	puts("OneNAND: ");
+	print_size(onenand_mtd.size, "\n");
+}
+
+#endif /* CONFIG_CMD_ONENAND */
diff --git a/drivers/onenand/onenand_bbt.c b/drivers/onenand/onenand_bbt.c
new file mode 100644
index 0000000..5a610ee
--- /dev/null
+++ b/drivers/onenand/onenand_bbt.c
@@ -0,0 +1,265 @@
+/*
+ *  linux/drivers/mtd/onenand/onenand_bbt.c
+ *
+ *  Bad Block Table support for the OneNAND driver
+ *
+ *  Copyright(c) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ *  TODO:
+ *    Split BBT core and chip specific BBT.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_CMD_ONENAND
+
+#include <linux/mtd/compat.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+#include <malloc.h>
+
+#include <asm/errno.h>
+
+/**
+ * check_short_pattern - [GENERIC] check if a pattern is in the buffer
+ * @param buf		the buffer to search
+ * @param len		the length of buffer to search
+ * @param paglen	the pagelength
+ * @param td		search pattern descriptor
+ *
+ * Check for a pattern at the given place. Used to search bad block
+ * tables and good / bad block identifiers. Same as check_pattern, but
+ * no optional empty check and the pattern is expected to start
+ * at offset 0.
+ */
+static int check_short_pattern(uint8_t * buf, int len, int paglen,
+			       struct nand_bbt_descr *td)
+{
+	int i;
+	uint8_t *p = buf;
+
+	/* Compare the pattern */
+	for (i = 0; i < td->len; i++) {
+		if (p[i] != td->pattern[i])
+			return -1;
+	}
+	return 0;
+}
+
+/**
+ * create_bbt - [GENERIC] Create a bad block table by scanning the device
+ * @param mtd		MTD device structure
+ * @param buf		temporary buffer
+ * @param bd		descriptor for the good/bad block search pattern
+ * @param chip		create the table for a specific chip, -1 read all chips.
+ *              Applies only if NAND_BBT_PERCHIP option is set
+ *
+ * Create a bad block table by scanning the device
+ * for the given good/bad block identify pattern
+ */
+static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
+		      struct nand_bbt_descr *bd, int chip)
+{
+	struct onenand_chip *this = mtd->priv;
+	struct bbm_info *bbm = this->bbm;
+	int i, j, numblocks, len, scanlen;
+	int startblock;
+	loff_t from;
+	size_t readlen, ooblen;
+
+	printk(KERN_INFO "Scanning device for bad blocks\n");
+
+	len = 1;
+
+	/* We need only read few bytes from the OOB area */
+	scanlen = ooblen = 0;
+	readlen = bd->len;
+
+	/* chip == -1 case only */
+	/* Note that numblocks is 2 * (real numblocks) here;
+	 * see i += 2 below as it makses shifting and masking less painful
+	 */
+	numblocks = mtd->size >> (bbm->bbt_erase_shift - 1);
+	startblock = 0;
+	from = 0;
+
+	for (i = startblock; i < numblocks;) {
+		int ret;
+
+		for (j = 0; j < len; j++) {
+			size_t retlen;
+
+			/* No need to read pages fully,
+			 * just read required OOB bytes */
+			ret = onenand_read_oob(mtd,
+					     from + j * mtd->oobblock +
+					     bd->offs, readlen, &retlen,
+					     &buf[0]);
+
+			if (ret && ret != -EAGAIN) {
+				printk("ret = %d\n", ret);
+				return ret;
+			}
+
+			if (check_short_pattern
+			    (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
+				bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
+				printk(KERN_WARNING
+				       "Bad eraseblock %d at 0x%08x\n", i >> 1,
+				       (unsigned int)from);
+				break;
+			}
+		}
+		i += 2;
+		from += (1 << bbm->bbt_erase_shift);
+	}
+
+	return 0;
+}
+
+/**
+ * onenand_memory_bbt - [GENERIC] create a memory based bad block table
+ * @param mtd		MTD device structure
+ * @param bd		descriptor for the good/bad block search pattern
+ *
+ * The function creates a memory based bbt by scanning the device
+ * for manufacturer / software marked good / bad blocks
+ */
+static inline int onenand_memory_bbt(struct mtd_info *mtd,
+				     struct nand_bbt_descr *bd)
+{
+	unsigned char data_buf[MAX_ONENAND_PAGESIZE];
+
+	bd->options &= ~NAND_BBT_SCANEMPTY;
+	return create_bbt(mtd, data_buf, bd, -1);
+}
+
+/**
+ * onenand_isbad_bbt - [OneNAND Interface] Check if a block is bad
+ * @param mtd		MTD device structure
+ * @param offs		offset in the device
+ * @param allowbbt	allow access to bad block table region
+ */
+static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
+{
+	struct onenand_chip *this = mtd->priv;
+	struct bbm_info *bbm = this->bbm;
+	int block;
+	uint8_t res;
+
+	/* Get block number * 2 */
+	block = (int)(offs >> (bbm->bbt_erase_shift - 1));
+	res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
+
+	DEBUG(MTD_DEBUG_LEVEL2,
+	      "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
+	      (unsigned int)offs, block >> 1, res);
+
+	switch ((int)res) {
+	case 0x00:
+		return 0;
+	case 0x01:
+		return 1;
+	case 0x02:
+		return allowbbt ? 0 : 1;
+	}
+
+	return 1;
+}
+
+/**
+ * onenand_scan_bbt - [OneNAND Interface] scan, find, read and maybe create bad block table(s)
+ * @param mtd		MTD device structure
+ * @param bd		descriptor for the good/bad block search pattern
+ *
+ * The function checks, if a bad block table(s) is/are already
+ * available. If not it scans the device for manufacturer
+ * marked good / bad blocks and writes the bad block table(s) to
+ * the selected place.
+ *
+ * The bad block table memory is allocated here. It must be freed
+ * by calling the onenand_free_bbt function.
+ *
+ */
+int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
+{
+	struct onenand_chip *this = mtd->priv;
+	struct bbm_info *bbm = this->bbm;
+	int len, ret = 0;
+
+	len = mtd->size >> (this->erase_shift + 2);
+	/* Allocate memory (2bit per block) */
+	bbm->bbt = malloc(len);
+	if (!bbm->bbt) {
+		printk(KERN_ERR "onenand_scan_bbt: Out of memory\n");
+		return -ENOMEM;
+	}
+	/* Clear the memory bad block table */
+	memset(bbm->bbt, 0x00, len);
+
+	/* Set the bad block position */
+	bbm->badblockpos = ONENAND_BADBLOCK_POS;
+
+	/* Set erase shift */
+	bbm->bbt_erase_shift = this->erase_shift;
+
+	if (!bbm->isbad_bbt)
+		bbm->isbad_bbt = onenand_isbad_bbt;
+
+	/* Scan the device to build a memory based bad block table */
+	if ((ret = onenand_memory_bbt(mtd, bd))) {
+		printk(KERN_ERR
+		       "onenand_scan_bbt: Can't scan flash and build the RAM-based BBT\n");
+		free(bbm->bbt);
+		bbm->bbt = NULL;
+	}
+
+	return ret;
+}
+
+/*
+ * Define some generic bad / good block scan pattern which are used
+ * while scanning a device for factory marked good / bad blocks.
+ */
+static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+
+static struct nand_bbt_descr largepage_memorybased = {
+	.options = 0,
+	.offs = 0,
+	.len = 2,
+	.pattern = scan_ff_pattern,
+};
+
+/**
+ * onenand_default_bbt - [OneNAND Interface] Select a default bad block table for the device
+ * @param mtd		MTD device structure
+ *
+ * This function selects the default bad block table
+ * support for the device and calls the onenand_scan_bbt function
+ */
+int onenand_default_bbt(struct mtd_info *mtd)
+{
+	struct onenand_chip *this = mtd->priv;
+	struct bbm_info *bbm;
+
+	this->bbm = malloc(sizeof(struct bbm_info));
+	if (!this->bbm)
+		return -ENOMEM;
+
+	bbm = this->bbm;
+
+	memset(bbm, 0, sizeof(struct bbm_info));
+
+	/* 1KB page has same configuration as 2KB page */
+	if (!bbm->badblock_pattern)
+		bbm->badblock_pattern = &largepage_memorybased;
+
+	return onenand_scan_bbt(mtd, bbm->badblock_pattern);
+}
+
+#endif /* CFG_CMD_ONENAND */
diff --git a/drivers/usb_ohci.c b/drivers/usb_ohci.c
index 14984a5..7ddcab6 100644
--- a/drivers/usb_ohci.c
+++ b/drivers/usb_ohci.c
@@ -93,6 +93,7 @@
 #ifdef CONFIG_PCI_OHCI
 static struct pci_device_id ohci_pci_ids[] = {
 	{0x10b9, 0x5237},	/* ULI1575 PCI OHCI module ids */
+	{0x1033, 0x0035},	/* NEC PCI OHCI module ids */
 	/* Please add supported PCI OHCI controller ids here */
 	{0, 0}
 };
diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h
index 3d91e99..d7ef65d 100644
--- a/include/config_cmd_all.h
+++ b/include/config_cmd_all.h
@@ -59,6 +59,7 @@
 #define CONFIG_CMD_NAND		/* NAND support			*/
 #define CONFIG_CMD_NET		/* bootp, tftpboot, rarpboot	*/
 #define CONFIG_CMD_NFS		/* NFS support			*/
+#define CONFIG_CMD_ONENAND	/* OneNAND support		*/
 #define CONFIG_CMD_PCI		/* pciinfo			*/
 #define CONFIG_CMD_PCMCIA	/* PCMCIA support		*/
 #define CONFIG_CMD_PING		/* ping support			*/
@@ -76,6 +77,6 @@
 #define CONFIG_CMD_USB		/* USB Support			*/
 #define CONFIG_CMD_VFD		/* VFD support (TRAB)		*/
 #define CONFIG_CMD_XIMG		/* Load part of Multi Image	*/
-#define CONFIG_CMD_MUX		/* AT91 MMC/SPI Mux Support     */
+#define CONFIG_CMD_AT91_SPIMUX	/* AT91 MMC/SPI Mux Support     */
 
 #endif	/* _CONFIG_CMD_ALL_H */
diff --git a/include/configs/TQM5200.h b/include/configs/TQM5200.h
index e0c9d81..d553404 100644
--- a/include/configs/TQM5200.h
+++ b/include/configs/TQM5200.h
@@ -188,7 +188,7 @@
 #endif
 
 #ifdef CONFIG_PCI
-#define CONFIG_CMD_CMD_PCI
+#define CONFIG_CMD_PCI
 #endif
 
 #if defined(CONFIG_MINIFAP) || defined(CONFIG_STK52XX) || defined(CONFIG_FO300)
@@ -238,13 +238,13 @@
 		"protect on FC000000 +${filesize}\0"
 #endif
 
-#ifndef CONFIG_CAM5200
+#if defined(CONFIG_TQM5200)
 #define CUSTOM_ENV_SETTINGS						\
+	"hostname=tqm5200\0"						\
 	"bootfile=/tftpboot/tqm5200/uImage\0"				\
-	"bootfile_fdt=/tftpboot/tqm5200/uImage_fdt\0"			\
 	"fdt_file=/tftpboot/tqm5200/tqm5200.dtb\0"			\
 	"u-boot=/tftpboot/tqm5200/u-boot.bin\0"
-#else
+#elif defined(CONFIG_CAM5200)
 #define CUSTOM_ENV_SETTINGS						\
 	"bootfile=cam5200/uImage\0"					\
 	"u-boot=cam5200/u-boot.bin\0"					\
@@ -252,11 +252,13 @@
 #endif
 
 #define CONFIG_EXTRA_ENV_SETTINGS					\
-	"console=ttyS0\0"						\
-	"kernel_addr=200000\0"						\
-	"fdt_addr=400000\0"						\
-	"hostname=tqm5200\0"						\
 	"netdev=eth0\0"							\
+	"console=ttyPSC0\0"						\
+	"fdt_addr=FC0A0000\0"						\
+	"kernel_addr=FC0C0000\0"					\
+	"ramdisk_addr=FC300000\0"					\
+	"kernel_addr_r=200000\0"					\
+	"fdt_addr_r=400000\0"						\
 	"rootpath=/opt/eldk/ppc_6xx\0"					\
 	"ramargs=setenv bootargs root=/dev/ram rw\0"			\
 	"nfsargs=setenv bootargs root=/dev/nfs rw "			\
@@ -266,16 +268,20 @@
 		":${hostname}:${netdev}:off panic=1\0"			\
 	"addcons=setenv bootargs ${bootargs} "				\
 		"console=${console},${baudrate}\0"			\
-	"flash_self=run ramargs addip addcons;"				\
+	"flash_self_old=sete console ttyS0; run ramargs addip addcons;"	\
 		"bootm ${kernel_addr} ${ramdisk_addr}\0"		\
-	"flash_nfs=run nfsargs addip addcons;"				\
+	"flash_self=run ramargs addip addcons;"				\
+		"bootm ${kernel_addr} ${ramdisk_addr} ${fdt_addr}\0"	\
+	"flash_nfs_old=sete console ttyS0; run nfsargs addip addcons;"	\
 		"bootm ${kernel_addr}\0"				\
-	"net_nfs=tftp ${kernel_addr} ${bootfile};"			\
-		"run nfsargs addip addcons;bootm\0"			\
-	"net_nfs_fdt=tftp ${kernel_addr} ${bootfile_fdt};"		\
-		"tftp ${fdt_addr} ${fdt_file};setenv console ttyPSC0;"	\
-		"run nfsargs addip addcons;"				\
+	"flash_nfs=run nfsargs addip addcons;"				\
 		"bootm ${kernel_addr} - ${fdt_addr}\0"			\
+	"net_nfs_old=tftp ${kernel_addr_r} ${bootfile};"		\
+		"sete console ttyS0; run nfsargs addip addcons;bootm\0"	\
+	"net_nfs=tftp ${kernel_addr_r} ${bootfile}; "			\
+		"tftp ${fdt_addr_r} ${fdt_file}; "			\
+		"run nfsargs addip addcons; "				\
+		"bootm ${kernel_addr_r} - ${fdt_addr_r}\0"		\
 	CUSTOM_ENV_SETTINGS						\
 	"load=tftp 200000 ${u-boot}\0"					\
 	ENV_UPDT							\
@@ -408,11 +414,12 @@
 #  endif /* CFG_LOWBOOT */
 # else	/* !CONFIG_TQM5200_B */
 #   define MTDPARTS_DEFAULT	"mtdparts=TQM5200-0:640k(firmware),"	\
-						"1408k(kernel),"	\
+						"128k(dtb),"		\
+						"2304k(kernel),"	\
 						"2m(initrd),"		\
 						"4m(small-fs),"		\
 						"8m(misc),"		\
-						"16m(big-fs)"
+						"15m(big-fs)"
 # endif /* CONFIG_TQM5200_B */
 #elif defined (CONFIG_CAM5200)
 #   define MTDPARTS_DEFAULT	"mtdparts=TQM5200-0:768k(firmware),"	\
diff --git a/include/configs/ads5121.h b/include/configs/ads5121.h
index 22eac1b..bb1efdf 100644
--- a/include/configs/ads5121.h
+++ b/include/configs/ads5121.h
@@ -235,6 +235,14 @@
 #endif
 
 /*
+ * EEPROM configuration
+ */
+#define CFG_I2C_EEPROM_ADDR_LEN		2	/* 16-bit EEPROM address */
+#define CFG_I2C_EEPROM_ADDR		0x50	/* Atmel: AT24C32A-10TQ-2.7 */
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS	10	/* 10ms of delay */
+#define CFG_EEPROM_PAGE_WRITE_BITS	5	/* 32-Byte Page Write Mode */
+
+/*
  * Ethernet configuration
  */
 #define CONFIG_MPC512x_FEC	1
@@ -275,6 +283,7 @@
 #define CONFIG_CMD_NFS
 #define CONFIG_CMD_PING
 #define CONFIG_CMD_REGINFO
+#define CONFIG_CMD_EEPROM
 
 #if defined(CONFIG_PCI)
 #define CONFIG_CMD_PCI
diff --git a/include/configs/lwmon5.h b/include/configs/lwmon5.h
index be48324..00c34d5d 100644
--- a/include/configs/lwmon5.h
+++ b/include/configs/lwmon5.h
@@ -200,12 +200,13 @@
 		"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}"	\
 		":${hostname}:${netdev}:off panic=1\0"			\
 	"addtty=setenv bootargs ${bootargs} console=ttyS1,${baudrate}\0"\
-	"flash_nfs=run nfsargs addip addtty;"				\
+	"addmisc=setenv bootargs ${bootargs} rtc-pcf8563.probe=0,0x51\0"\
+	"flash_nfs=run nfsargs addip addtty addmisc;"			\
 		"bootm ${kernel_addr}\0"				\
-	"flash_self=run ramargs addip addtty;"				\
+	"flash_self=run ramargs addip addtty addmisc;"			\
 		"bootm ${kernel_addr} ${ramdisk_addr}\0"		\
-	"net_nfs=tftp 200000 ${bootfile};run nfsargs addip addtty;"     \
-	        "bootm\0"						\
+	"net_nfs=tftp 200000 ${bootfile};"				\
+		"run nfsargs addip addtty addmisc;bootm\0"		\
 	"rootpath=/opt/eldk/ppc_4xxFP\0"				\
 	"bootfile=/tftpboot/lwmon5/uImage\0"				\
 	"kernel_addr=FC000000\0"					\
@@ -338,7 +339,12 @@
 #define CFG_PCI_SUBSYS_VENDORID 0x10e8	/* AMCC				*/
 #define CFG_PCI_SUBSYS_ID       0xcafe	/* Whatever			*/
 
+#if 0
+/*
+ * ToDo: Watchdog is not test fully, so exclude it for now
+ */
 #define CONFIG_HW_WATCHDOG	1	/* Use external HW-Watchdog	*/
+#endif
 
 /*
  * For booting Linux, the board info and command line data
@@ -472,7 +478,7 @@
 {GPIO1_BASE, GPIO_OUT, GPIO_SEL , GPIO_OUT_1}, /* GPIO55  Unselect via TraceSelect Bit	*/	\
 {GPIO1_BASE, GPIO_OUT, GPIO_SEL , GPIO_OUT_0}, /* GPIO56  Unselect via TraceSelect Bit	*/	\
 {GPIO1_BASE, GPIO_OUT, GPIO_SEL , GPIO_OUT_1}, /* GPIO57  Unselect via TraceSelect Bit	*/	\
-{GPIO1_BASE, GPIO_OUT, GPIO_SEL , GPIO_OUT_1}, /* GPIO58  Unselect via TraceSelect Bit	*/	\
+{GPIO1_BASE, GPIO_OUT, GPIO_SEL , GPIO_OUT_0}, /* GPIO58  Unselect via TraceSelect Bit	*/	\
 {GPIO1_BASE, GPIO_OUT, GPIO_SEL , GPIO_OUT_0}, /* GPIO59  Unselect via TraceSelect Bit	*/	\
 {GPIO1_BASE, GPIO_OUT, GPIO_SEL , GPIO_OUT_0}, /* GPIO60  Unselect via TraceSelect Bit	*/	\
 {GPIO1_BASE, GPIO_IN , GPIO_SEL , GPIO_OUT_0}, /* GPIO61  Unselect via TraceSelect Bit	*/	\
diff --git a/include/configs/stxssa.h b/include/configs/stxssa.h
index b41dafa..c6e7953 100644
--- a/include/configs/stxssa.h
+++ b/include/configs/stxssa.h
@@ -189,20 +189,21 @@
 #define CFG_PROMPT_HUSH_PS2 "> "
 #endif
 
-/* I2C */
+/*
+ * I2C
+ */
 #define CONFIG_FSL_I2C			/* Use FSL common I2C driver */
 #define  CONFIG_HARD_I2C		/* I2C with hardware support*/
 #undef	CONFIG_SOFT_I2C			/* I2C bit-banged */
 #define CFG_I2C_SPEED		400000	/* I2C speed and slave address	*/
 #define CFG_I2C_SLAVE		0x7F
-#if 0
-#define CFG_I2C_NOPROBES	{0x00}	/* Don't probe these addrs */
-#else
-/* I did the 'if 0' so we could keep the syntax above if ever needed. */
 #undef CFG_I2C_NOPROBES
-#endif
 #define CFG_I2C_OFFSET		0x3000
 
+/* I2C RTC */
+#define CONFIG_RTC_DS1337		/* This is really a DS1339 RTC	*/
+#define CFG_I2C_RTC_ADDR	0x68	/* at address 0x68		*/
+
 /* I2C EEPROM.	AT24C32, we keep our environment in here.
 */
 #define CFG_I2C_EEPROM_ADDR		0x51	/* 1010001x		*/
@@ -341,8 +342,13 @@
  */
 #include <config_cmd_default.h>
 
-#define CONFIG_CMD_PING
+#define CONFIG_CMD_DATE
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_EEPROM
 #define CONFIG_CMD_I2C
+#define CONFIG_CMD_NFS
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_SNTP
 
 #if defined(CONFIG_PCI)
     #define CONFIG_CMD_PCI
diff --git a/include/led.h b/include/led.h
deleted file mode 100644
index 57c2b4a..0000000
--- a/include/led.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * (C) Copyright 2006
- * Atmel Nordic AB <www.atmel.com>
- * Ulf Samuelsson <ulf@atmel.com>
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#ifndef __LED_H
-#define __LED_H
-
-#ifndef	__ASSEMBLY__
-extern void	LED_init (void);
-extern void	red_LED_on(void);
-extern void	red_LED_off(void);
-extern void	green_LED_on(void);
-extern void	green_LED_off(void);
-extern void	yellow_LED_on(void);
-extern void	yellow_LED_off(void);
-#else
-	.extern LED_init
-	.extern red_LED_on
-	.extern red_LED_off
-	.extern yellow_LED_on
-	.extern yellow_LED_off
-	.extern green_LED_on
-	.extern green_LED_off
-#endif
-#endif
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
new file mode 100644
index 0000000..f194cf1
--- /dev/null
+++ b/include/linux/mtd/bbm.h
@@ -0,0 +1,127 @@
+/*
+ *  linux/include/linux/mtd/bbm.h
+ *
+ *  NAND family Bad Block Management (BBM) header file
+ *    - Bad Block Table (BBT) implementation
+ *
+ *  Copyright (c) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ *  Copyright (c) 2000-2005
+ *  Thomas Gleixner <tglx@linuxtronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __LINUX_MTD_BBM_H
+#define __LINUX_MTD_BBM_H
+
+/* The maximum number of NAND chips in an array */
+#ifndef NAND_MAX_CHIPS
+#define NAND_MAX_CHIPS		8
+#endif
+
+/**
+ * struct nand_bbt_descr - bad block table descriptor
+ * @param options	options for this descriptor
+ * @param pages		the page(s) where we find the bbt, used with
+ * 			option BBT_ABSPAGE when bbt is searched,
+ * 			then we store the found bbts pages here.
+ *			Its an array and supports up to 8 chips now
+ * @param offs		offset of the pattern in the oob area of the page
+ * @param veroffs	offset of the bbt version counter in the oob are of the page
+ * @param version	version read from the bbt page during scan
+ * @param len		length of the pattern, if 0 no pattern check is performed
+ * @param maxblocks	maximum number of blocks to search for a bbt. This number of
+ *			blocks is reserved at the end of the device
+ *			where the tables are written.
+ * @param reserved_block_code	if non-0, this pattern denotes a reserved
+ *			(rather than bad) block in the stored bbt
+ * @param pattern	pattern to identify bad block table or factory marked
+ *			good / bad blocks, can be NULL, if len = 0
+ *
+ * Descriptor for the bad block table marker and the descriptor for the
+ * pattern which identifies good and bad blocks. The assumption is made
+ * that the pattern and the version count are always located in the oob area
+ * of the first block.
+ */
+struct nand_bbt_descr {
+	int options;
+	int pages[NAND_MAX_CHIPS];
+	int offs;
+	int veroffs;
+	uint8_t version[NAND_MAX_CHIPS];
+	int len;
+	int maxblocks;
+	int reserved_block_code;
+	uint8_t *pattern;
+};
+
+/* Options for the bad block table descriptors */
+
+/* The number of bits used per block in the bbt on the device */
+#define NAND_BBT_NRBITS_MSK	0x0000000F
+#define NAND_BBT_1BIT		0x00000001
+#define NAND_BBT_2BIT		0x00000002
+#define NAND_BBT_4BIT		0x00000004
+#define NAND_BBT_8BIT		0x00000008
+/* The bad block table is in the last good block of the device */
+#define NAND_BBT_LASTBLOCK	0x00000010
+/* The bbt is at the given page, else we must scan for the bbt */
+#define NAND_BBT_ABSPAGE	0x00000020
+/* The bbt is at the given page, else we must scan for the bbt */
+#define NAND_BBT_SEARCH		0x00000040
+/* bbt is stored per chip on multichip devices */
+#define NAND_BBT_PERCHIP	0x00000080
+/* bbt has a version counter at offset veroffs */
+#define NAND_BBT_VERSION	0x00000100
+/* Create a bbt if none axists */
+#define NAND_BBT_CREATE		0x00000200
+/* Search good / bad pattern through all pages of a block */
+#define NAND_BBT_SCANALLPAGES	0x00000400
+/* Scan block empty during good / bad block scan */
+#define NAND_BBT_SCANEMPTY	0x00000800
+/* Write bbt if neccecary */
+#define NAND_BBT_WRITE		0x00001000
+/* Read and write back block contents when writing bbt */
+#define NAND_BBT_SAVECONTENT	0x00002000
+/* Search good / bad pattern on the first and the second page */
+#define NAND_BBT_SCAN2NDPAGE	0x00004000
+
+/* The maximum number of blocks to scan for a bbt */
+#define NAND_BBT_SCAN_MAXBLOCKS	4
+
+/*
+ * Constants for oob configuration
+ */
+#define ONENAND_BADBLOCK_POS	0
+
+/**
+ * struct bbt_info - [GENERIC] Bad Block Table data structure
+ * @param bbt_erase_shift	[INTERN] number of address bits in a bbt entry
+ * @param badblockpos		[INTERN] position of the bad block marker in the oob area
+ * @param bbt			[INTERN] bad block table pointer
+ * @param badblock_pattern	[REPLACEABLE] bad block scan pattern used for initial bad block scan
+ * @param priv			[OPTIONAL] pointer to private bbm date
+ */
+struct bbm_info {
+	int bbt_erase_shift;
+	int badblockpos;
+	int options;
+
+	uint8_t *bbt;
+
+	int (*isbad_bbt) (struct mtd_info * mtd, loff_t ofs, int allowbbt);
+
+	/* TODO Add more NAND specific fileds */
+	struct nand_bbt_descr *badblock_pattern;
+
+	void *priv;
+};
+
+/* OneNAND BBT interface */
+extern int onenand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd);
+extern int onenand_default_bbt (struct mtd_info *mtd);
+
+#endif				/* __LINUX_MTD_BBM_H */
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
new file mode 100644
index 0000000..4b0c2df
--- /dev/null
+++ b/include/linux/mtd/onenand.h
@@ -0,0 +1,143 @@
+/*
+ *  linux/include/linux/mtd/onenand.h
+ *
+ *  Copyright (C) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_MTD_ONENAND_H
+#define __LINUX_MTD_ONENAND_H
+
+#include <linux/mtd/onenand_regs.h>
+
+/* Note: The header order is impoertant */
+#include <onenand_uboot.h>
+
+#include <linux/mtd/bbm.h>
+
+#define MAX_BUFFERRAM		2
+#define MAX_ONENAND_PAGESIZE	(2048 + 64)
+
+/* Scan and identify a OneNAND device */
+extern int onenand_scan (struct mtd_info *mtd, int max_chips);
+/* Free resources held by the OneNAND device */
+extern void onenand_release (struct mtd_info *mtd);
+
+/**
+ * onenand_state_t - chip states
+ * Enumeration for OneNAND flash chip state
+ */
+typedef enum {
+	FL_READY,
+	FL_READING,
+	FL_WRITING,
+	FL_ERASING,
+	FL_SYNCING,
+	FL_UNLOCKING,
+	FL_LOCKING,
+} onenand_state_t;
+
+/**
+ * struct onenand_bufferram - OneNAND BufferRAM Data
+ * @param block		block address in BufferRAM
+ * @param page		page address in BufferRAM
+ * @param valid		valid flag
+ */
+struct onenand_bufferram {
+	int block;
+	int page;
+	int valid;
+};
+
+/**
+ * struct onenand_chip - OneNAND Private Flash Chip Data
+ * @param base		[BOARDSPECIFIC] address to access OneNAND
+ * @param chipsize	[INTERN] the size of one chip for multichip arrays
+ * @param device_id	[INTERN] device ID
+ * @param verstion_id	[INTERN] version ID
+ * @param options	[BOARDSPECIFIC] various chip options. They can partly be set to inform onenand_scan about
+ * @param erase_shift	[INTERN] number of address bits in a block
+ * @param page_shift	[INTERN] number of address bits in a page
+ * @param ppb_shift	[INTERN] number of address bits in a pages per block
+ * @param page_mask	[INTERN] a page per block mask
+ * @param bufferam_index	[INTERN] BufferRAM index
+ * @param bufferam	[INTERN] BufferRAM info
+ * @param readw		[REPLACEABLE] hardware specific function for read short
+ * @param writew	[REPLACEABLE] hardware specific function for write short
+ * @param command	[REPLACEABLE] hardware specific function for writing commands to the chip
+ * @param wait		[REPLACEABLE] hardware specific function for wait on ready
+ * @param read_bufferram	[REPLACEABLE] hardware specific function for BufferRAM Area
+ * @param write_bufferram	[REPLACEABLE] hardware specific function for BufferRAM Area
+ * @param chip_lock	[INTERN] spinlock used to protect access to this structure and the chip
+ * @param wq		[INTERN] wait queue to sleep on if a OneNAND operation is in progress
+ * @param state		[INTERN] the current state of the OneNAND device
+ * @param autooob	[REPLACEABLE] the default (auto)placement scheme
+ * @param priv		[OPTIONAL] pointer to private chip date
+ */
+struct onenand_chip {
+	void __iomem *base;
+	unsigned int chipsize;
+	unsigned int device_id;
+	unsigned int options;
+
+	unsigned int erase_shift;
+	unsigned int page_shift;
+	unsigned int ppb_shift;	/* Pages per block shift */
+	unsigned int page_mask;
+
+	unsigned int bufferram_index;
+	struct onenand_bufferram bufferram[MAX_BUFFERRAM];
+
+	int (*command) (struct mtd_info * mtd, int cmd, loff_t address,
+			size_t len);
+	int (*wait) (struct mtd_info * mtd, int state);
+	int (*read_bufferram) (struct mtd_info * mtd, int area,
+			       unsigned char *buffer, int offset, size_t count);
+	int (*write_bufferram) (struct mtd_info * mtd, int area,
+				const unsigned char *buffer, int offset,
+				size_t count);
+	unsigned short (*read_word) (void __iomem * addr);
+	void (*write_word) (unsigned short value, void __iomem * addr);
+	void (*mmcontrol) (struct mtd_info * mtd, int sync_read);
+
+	spinlock_t chip_lock;
+	wait_queue_head_t wq;
+	onenand_state_t state;
+
+	struct nand_oobinfo *autooob;
+
+	void *bbm;
+
+	void *priv;
+};
+
+#define ONENAND_CURRENT_BUFFERRAM(this)		(this->bufferram_index)
+#define ONENAND_NEXT_BUFFERRAM(this)		(this->bufferram_index ^ 1)
+#define ONENAND_SET_NEXT_BUFFERRAM(this)	(this->bufferram_index ^= 1)
+
+/*
+ * Options bits
+ */
+#define ONENAND_CONT_LOCK		(0x0001)
+
+/*
+ * OneNAND Flash Manufacturer ID Codes
+ */
+#define ONENAND_MFR_SAMSUNG	0xec
+#define ONENAND_MFR_UNKNOWN	0x00
+
+/**
+ * struct nand_manufacturers - NAND Flash Manufacturer ID Structure
+ * @param name:		Manufacturer name
+ * @param id:		manufacturer ID code of device.
+*/
+struct onenand_manufacturers {
+	int id;
+	char *name;
+};
+
+#endif				/* __LINUX_MTD_ONENAND_H */
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
new file mode 100644
index 0000000..c8a9f3e
--- /dev/null
+++ b/include/linux/mtd/onenand_regs.h
@@ -0,0 +1,181 @@
+/*
+ *  linux/include/linux/mtd/onenand_regs.h
+ *
+ *  OneNAND Register header file
+ *
+ *  Copyright (C) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ONENAND_REG_H
+#define __ONENAND_REG_H
+
+/* Memory Address Map Translation (Word order) */
+#define ONENAND_MEMORY_MAP(x)		((x) << 1)
+
+/*
+ * External BufferRAM area
+ */
+#define	ONENAND_BOOTRAM			ONENAND_MEMORY_MAP(0x0000)
+#define	ONENAND_DATARAM			ONENAND_MEMORY_MAP(0x0200)
+#define	ONENAND_SPARERAM		ONENAND_MEMORY_MAP(0x8010)
+
+/*
+ * OneNAND Registers
+ */
+#define ONENAND_REG_MANUFACTURER_ID	ONENAND_MEMORY_MAP(0xF000)
+#define ONENAND_REG_DEVICE_ID		ONENAND_MEMORY_MAP(0xF001)
+#define ONENAND_REG_VERSION_ID		ONENAND_MEMORY_MAP(0xF002)
+#define ONENAND_REG_DATA_BUFFER_SIZE	ONENAND_MEMORY_MAP(0xF003)
+#define ONENAND_REG_BOOT_BUFFER_SIZE	ONENAND_MEMORY_MAP(0xF004)
+#define ONENAND_REG_NUM_BUFFERS		ONENAND_MEMORY_MAP(0xF005)
+#define ONENAND_REG_TECHNOLOGY		ONENAND_MEMORY_MAP(0xF006)
+
+#define ONENAND_REG_START_ADDRESS1	ONENAND_MEMORY_MAP(0xF100)
+#define ONENAND_REG_START_ADDRESS2	ONENAND_MEMORY_MAP(0xF101)
+#define ONENAND_REG_START_ADDRESS3	ONENAND_MEMORY_MAP(0xF102)
+#define ONENAND_REG_START_ADDRESS4	ONENAND_MEMORY_MAP(0xF103)
+#define ONENAND_REG_START_ADDRESS5	ONENAND_MEMORY_MAP(0xF104)
+#define ONENAND_REG_START_ADDRESS6	ONENAND_MEMORY_MAP(0xF105)
+#define ONENAND_REG_START_ADDRESS7	ONENAND_MEMORY_MAP(0xF106)
+#define ONENAND_REG_START_ADDRESS8	ONENAND_MEMORY_MAP(0xF107)
+
+#define ONENAND_REG_START_BUFFER	ONENAND_MEMORY_MAP(0xF200)
+#define ONENAND_REG_COMMAND		ONENAND_MEMORY_MAP(0xF220)
+#define ONENAND_REG_SYS_CFG1		ONENAND_MEMORY_MAP(0xF221)
+#define ONENAND_REG_SYS_CFG2		ONENAND_MEMORY_MAP(0xF222)
+#define ONENAND_REG_CTRL_STATUS		ONENAND_MEMORY_MAP(0xF240)
+#define ONENAND_REG_INTERRUPT		ONENAND_MEMORY_MAP(0xF241)
+#define ONENAND_REG_START_BLOCK_ADDRESS	ONENAND_MEMORY_MAP(0xF24C)
+#define ONENAND_REG_END_BLOCK_ADDRESS	ONENAND_MEMORY_MAP(0xF24D)
+#define ONENAND_REG_WP_STATUS		ONENAND_MEMORY_MAP(0xF24E)
+
+#define ONENAND_REG_ECC_STATUS		ONENAND_MEMORY_MAP(0xFF00)
+#define ONENAND_REG_ECC_M0		ONENAND_MEMORY_MAP(0xFF01)
+#define ONENAND_REG_ECC_S0		ONENAND_MEMORY_MAP(0xFF02)
+#define ONENAND_REG_ECC_M1		ONENAND_MEMORY_MAP(0xFF03)
+#define ONENAND_REG_ECC_S1		ONENAND_MEMORY_MAP(0xFF04)
+#define ONENAND_REG_ECC_M2		ONENAND_MEMORY_MAP(0xFF05)
+#define ONENAND_REG_ECC_S2		ONENAND_MEMORY_MAP(0xFF06)
+#define ONENAND_REG_ECC_M3		ONENAND_MEMORY_MAP(0xFF07)
+#define ONENAND_REG_ECC_S3		ONENAND_MEMORY_MAP(0xFF08)
+
+/*
+ * Device ID Register F001h (R)
+ */
+#define ONENAND_DEVICE_DENSITY_SHIFT	(4)
+#define ONENAND_DEVICE_IS_DDP		(1 << 3)
+#define ONENAND_DEVICE_IS_DEMUX		(1 << 2)
+#define ONENAND_DEVICE_VCC_MASK		(0x3)
+
+#define ONENAND_DEVICE_DENSITY_512Mb	(0x002)
+
+/*
+ * Version ID Register F002h (R)
+ */
+#define ONENAND_VERSION_PROCESS_SHIFT	(8)
+
+/*
+ * Start Address 1 F100h (R/W)
+ */
+#define ONENAND_DDP_SHIFT		(15)
+
+/*
+ * Start Address 8 F107h (R/W)
+ */
+#define ONENAND_FPA_MASK		(0x3f)
+#define ONENAND_FPA_SHIFT		(2)
+#define ONENAND_FSA_MASK		(0x03)
+
+/*
+ * Start Buffer Register F200h (R/W)
+ */
+#define ONENAND_BSA_MASK		(0x03)
+#define ONENAND_BSA_SHIFT		(8)
+#define ONENAND_BSA_BOOTRAM		(0 << 2)
+#define ONENAND_BSA_DATARAM0		(2 << 2)
+#define ONENAND_BSA_DATARAM1		(3 << 2)
+#define ONENAND_BSC_MASK		(0x03)
+
+/*
+ * Command Register F220h (R/W)
+ */
+#define ONENAND_CMD_READ		(0x00)
+#define ONENAND_CMD_READOOB		(0x13)
+#define ONENAND_CMD_PROG		(0x80)
+#define ONENAND_CMD_PROGOOB		(0x1A)
+#define ONENAND_CMD_UNLOCK		(0x23)
+#define ONENAND_CMD_LOCK		(0x2A)
+#define ONENAND_CMD_LOCK_TIGHT		(0x2C)
+#define ONENAND_CMD_ERASE		(0x94)
+#define ONENAND_CMD_RESET		(0xF0)
+#define ONENAND_CMD_READID		(0x90)
+
+/* NOTE: Those are not *REAL* commands */
+#define ONENAND_CMD_BUFFERRAM		(0x1978)
+
+/*
+ * System Configuration 1 Register F221h (R, R/W)
+ */
+#define ONENAND_SYS_CFG1_SYNC_READ	(1 << 15)
+#define ONENAND_SYS_CFG1_BRL_7		(7 << 12)
+#define ONENAND_SYS_CFG1_BRL_6		(6 << 12)
+#define ONENAND_SYS_CFG1_BRL_5		(5 << 12)
+#define ONENAND_SYS_CFG1_BRL_4		(4 << 12)
+#define ONENAND_SYS_CFG1_BRL_3		(3 << 12)
+#define ONENAND_SYS_CFG1_BRL_10		(2 << 12)
+#define ONENAND_SYS_CFG1_BRL_9		(1 << 12)
+#define ONENAND_SYS_CFG1_BRL_8		(0 << 12)
+#define ONENAND_SYS_CFG1_BRL_SHIFT	(12)
+#define ONENAND_SYS_CFG1_BL_32		(4 << 9)
+#define ONENAND_SYS_CFG1_BL_16		(3 << 9)
+#define ONENAND_SYS_CFG1_BL_8		(2 << 9)
+#define ONENAND_SYS_CFG1_BL_4		(1 << 9)
+#define ONENAND_SYS_CFG1_BL_CONT	(0 << 9)
+#define ONENAND_SYS_CFG1_BL_SHIFT	(9)
+#define ONENAND_SYS_CFG1_NO_ECC		(1 << 8)
+#define ONENAND_SYS_CFG1_RDY		(1 << 7)
+#define ONENAND_SYS_CFG1_INT		(1 << 6)
+#define ONENAND_SYS_CFG1_IOBE		(1 << 5)
+#define ONENAND_SYS_CFG1_RDY_CONF	(1 << 4)
+
+/*
+ * Controller Status Register F240h (R)
+ */
+#define ONENAND_CTRL_ONGO		(1 << 15)
+#define ONENAND_CTRL_LOCK		(1 << 14)
+#define ONENAND_CTRL_LOAD		(1 << 13)
+#define ONENAND_CTRL_PROGRAM		(1 << 12)
+#define ONENAND_CTRL_ERASE		(1 << 11)
+#define ONENAND_CTRL_ERROR		(1 << 10)
+#define ONENAND_CTRL_RSTB		(1 << 7)
+
+/*
+ * Interrupt Status Register F241h (R)
+ */
+#define ONENAND_INT_MASTER		(1 << 15)
+#define ONENAND_INT_READ		(1 << 7)
+#define ONENAND_INT_WRITE		(1 << 6)
+#define ONENAND_INT_ERASE		(1 << 5)
+#define ONENAND_INT_RESET		(1 << 4)
+#define ONENAND_INT_CLEAR		(0 << 0)
+
+/*
+ * NAND Flash Write Protection Status Register F24Eh (R)
+ */
+#define ONENAND_WP_US			(1 << 2)
+#define ONENAND_WP_LS			(1 << 1)
+#define ONENAND_WP_LTS			(1 << 0)
+
+/*
+ * ECC Status Reigser FF00h (R)
+ */
+#define ONENAND_ECC_1BIT		(1 << 0)
+#define ONENAND_ECC_2BIT		(1 << 1)
+#define ONENAND_ECC_2BIT_ALL		(0xAAAA)
+
+#endif				/* __ONENAND_REG_H */
diff --git a/include/onenand_uboot.h b/include/onenand_uboot.h
new file mode 100644
index 0000000..bd1831e
--- /dev/null
+++ b/include/onenand_uboot.h
@@ -0,0 +1,39 @@
+/*
+ *  Header file for OneNAND support for U-Boot
+ *
+ *  Adaptation from kernel to U-Boot
+ *
+ *  Copyright (C) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __UBOOT_ONENAND_H
+#define __UBOOT_ONENAND_H
+
+struct kvec {
+	void *iov_base;
+	size_t iov_len;
+};
+
+typedef int spinlock_t;
+typedef int wait_queue_head_t;
+
+/* Functions */
+extern void onenand_init(void);
+extern int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
+			size_t * retlen, u_char * buf);
+extern int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
+			    size_t * retlen, u_char * buf);
+extern int onenand_write(struct mtd_info *mtd, loff_t from, size_t len,
+			 size_t * retlen, const u_char * buf);
+extern int onenand_erase(struct mtd_info *mtd, struct erase_info *instr);
+
+extern int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
+
+extern void onenand_print_device_info(int device, int verbose);
+
+#endif /* __UBOOT_ONENAND_H */
diff --git a/include/status_led.h b/include/status_led.h
index a646814..d12bb67 100644
--- a/include/status_led.h
+++ b/include/status_led.h
@@ -383,6 +383,27 @@
 # include <asm/status_led.h>
 #endif
 
+/*
+ * Coloured LEDs API
+ */
+#ifndef	__ASSEMBLY__
+extern void	coloured_LED_init (void);
+extern void	red_LED_on(void);
+extern void	red_LED_off(void);
+extern void	green_LED_on(void);
+extern void	green_LED_off(void);
+extern void	yellow_LED_on(void);
+extern void	yellow_LED_off(void);
+#else
+	.extern LED_init
+	.extern red_LED_on
+	.extern red_LED_off
+	.extern yellow_LED_on
+	.extern yellow_LED_off
+	.extern green_LED_on
+	.extern green_LED_off
+#endif
+
 #endif	/* CONFIG_STATUS_LED	*/
 
 #endif	/* _STATUS_LED_H_	*/
diff --git a/lib_arm/board.c b/lib_arm/board.c
index d28afc5..7e97f13 100644
--- a/lib_arm/board.c
+++ b/lib_arm/board.c
@@ -58,6 +58,10 @@
 void nand_init (void);
 #endif
 
+#if defined(CONFIG_CMD_ONENAND)
+void onenand_init(void);
+#endif
+
 ulong monitor_flash_len;
 
 #ifdef CONFIG_HAS_DATAFLASH
@@ -112,6 +116,26 @@
 }
 
 /************************************************************************
+ * Coloured LED functionality
+ ************************************************************************
+ * May be supplied by boards if desired
+ */
+void inline __coloured_LED_init (void) {}
+void inline coloured_LED_init (void) __attribute__((weak, alias("__coloured_LED_init")));
+void inline __red_LED_on (void) {}
+void inline red_LED_on (void) __attribute__((weak, alias("__red_LED_on")));
+void inline __red_LED_off(void) {}
+void inline red_LED_off(void)	     __attribute__((weak, alias("__red_LED_off")));
+void inline __green_LED_on(void) {}
+void inline green_LED_on(void) __attribute__((weak, alias("__green_LED_on")));
+void inline __green_LED_off(void) {}
+void inline green_LED_off(void)__attribute__((weak, alias("__green_LED_off")));
+void inline __yellow_LED_on(void) {}
+void inline yellow_LED_on(void)__attribute__((weak, alias("__yellow_LED_on")));
+void inline __yellow_LED_off(void) {}
+void inline yellow_LED_off(void)__attribute__((weak, alias("__yellow_LED_off")));
+
+/************************************************************************
  * Init Utilities							*
  ************************************************************************
  * Some of this code should be moved into the core functions,
@@ -185,7 +209,6 @@
 }
 #endif /* CFG_NO_FLASH */
 
-
 /*
  * Breathe some life into the board...
  *
@@ -301,6 +324,10 @@
 	nand_init();		/* go init the NAND */
 #endif
 
+#if defined(CONFIG_CMD_ONENAND)
+	onenand_init();
+#endif
+
 #ifdef CONFIG_HAS_DATAFLASH
 	AT91F_DataflashInit();
 	dataflash_print_info();