]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
Re-factoring the legacy NAND code (legacy NAND now only in board-specific
authorBartlomiej Sieka <tur@semihalf.com>
Sun, 5 Mar 2006 17:57:33 +0000 (18:57 +0100)
committerBartlomiej Sieka <tur@semihalf.com>
Sun, 5 Mar 2006 17:57:33 +0000 (18:57 +0100)
code and in SoC code). Boards using the old way have CFG_NAND_LEGACY and
BOARDLIBS = drivers/nand_legacy/libnand_legacy.a added. Build breakage for
NETTA.ERR and NETTA_ISDN - will go away when the new NAND support is
implemented for these boards.

86 files changed:
MAKEALL
board/amcc/bamboo/bamboo.c
board/amcc/bamboo/config.mk
board/bmw/config.mk
board/dave/PPChameleonEVB/config.mk
board/dave/PPChameleonEVB/nand.c
board/esd/ash405/ash405.c
board/esd/ash405/config.mk
board/esd/cms700/cms700.c
board/esd/cms700/config.mk
board/esd/common/auto_update.c
board/esd/cpci405/config.mk
board/esd/hh405/config.mk
board/esd/hh405/hh405.c
board/esd/hub405/config.mk
board/esd/hub405/hub405.c
board/esd/plu405/config.mk
board/esd/plu405/plu405.c
board/esd/voh405/config.mk
board/esd/voh405/voh405.c
board/esd/wuh405/config.mk
board/esd/wuh405/wuh405.c
board/g2000/g2000.c
board/netphone/config.mk
board/netphone/netphone.c
board/netstar/config.mk
board/netstar/setup.S
board/netta2/config.mk
board/netta2/netta2.c
board/netvia/config.mk
board/netvia/netvia.c
board/omap2420h4/omap2420h4.c
board/sixnet/config.mk
board/sixnet/sixnet.c
board/stxxtc/stxxtc.c
common/Makefile
common/cmd_doc.c
common/cmd_jffs2.c
common/cmd_nand.c
common/cmd_nand_new.c [deleted file]
common/env_nand.c
drivers/nand/diskonchip.c
drivers/nand/nand.c
drivers/nand/nand_base.c
drivers/nand/nand_bbt.c
drivers/nand/nand_ecc.c
drivers/nand/nand_ids.c
drivers/nand_legacy/Makefile [new file with mode: 0644]
drivers/nand_legacy/nand_legacy.c [new file with mode: 0644]
fs/jffs2/jffs2_1pass.c
fs/jffs2/jffs2_nand_1pass.c
include/configs/ASH405.h
include/configs/BMW.h
include/configs/CMS700.h
include/configs/CPCI405.h
include/configs/CPCI4052.h
include/configs/CPCI405AB.h
include/configs/CPCI405DT.h
include/configs/CPU86.h
include/configs/CPU87.h
include/configs/GEN860T.h
include/configs/HH405.h
include/configs/HUB405.h
include/configs/MIP405.h
include/configs/NETPHONE.h
include/configs/NETTA2.h
include/configs/NETVIA.h
include/configs/PCIPPC2.h
include/configs/PCIPPC6.h
include/configs/PIP405.h
include/configs/PLU405.h
include/configs/PM520.h
include/configs/PM826.h
include/configs/PM828.h
include/configs/PPChameleonEVB.h
include/configs/RBC823.h
include/configs/SXNI855T.h
include/configs/VOH405.h
include/configs/WUH405.h
include/configs/bamboo.h
include/configs/netstar.h
include/configs/svm_sc8xx.h
include/linux/mtd/nand.h
include/linux/mtd/nand_ids.h
include/linux/mtd/nand_legacy.h [new file with mode: 0644]
include/linux/mtd/nand_new.h [deleted file]

diff --git a/MAKEALL b/MAKEALL
index fcbab47cab7c8aee706799f50c94d1676170e6c3..d563227d893d6feaebdb71bd7d621638761e8447 100755 (executable)
--- a/MAKEALL
+++ b/MAKEALL
@@ -177,10 +177,10 @@ LIST_ARM9="       \
        ap920t          ap922_XA10      ap926ejs        ap946es         \
        ap966           cp920t          cp922_XA10      cp926ejs        \
        cp946es         cp966           lpd7a400        mp2usb          \
-       mx1ads          mx1fs2          omap1510inn     omap1610h2      \
-       omap1610inn     omap730p2       scb9328         smdk2400        \
-       smdk2410        trab            VCMA9           versatile       \
-       versatileab     versatilepb     voiceblue
+       mx1ads          mx1fs2          netstar         omap1510inn     \
+       omap1610h2      omap1610inn     omap730p2       scb9328         \
+       smdk2400        smdk2410        trab            VCMA9           \
+       versatile       versatileab     versatilepb     voiceblue
 "
 
 #########################################################################
index 803995ae5d0645d24d38b91296e8a5556d5c1b85..7c989200fe18f0a5500ec79989eee6fc0103ccdf 100644 (file)
@@ -277,7 +277,7 @@ int board_early_init_f(void)
 }
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 
 /*----------------------------------------------------------------------------+
index 35cb65584a1f5d4b6c33c2cfd56a0cd9fe90f0b9..b6495de692cc4e16eb884f6e82cb3ccd788f2668 100644 (file)
@@ -32,3 +32,7 @@ endif
 ifeq ($(dbcr),1)
 PLATFORM_CPPFLAGS += -DCFG_INIT_DBCR=0x8cff0000
 endif
+
+# legacy nand support
+BOARDLIBS = drivers/nand_legacy/libnand_legacy.a
+
index f9915496adaf3d419d7afcad38a2636370077ba4..10b7a9f5ea3369bcd13251035561931999f6b82b 100644 (file)
@@ -30,3 +30,4 @@ TEXT_BASE = 0xFFF00000
 PLATFORM_CPPFLAGS += -DEMBEDDED -DBIG_ENDIAN_HOST -DINCLUDE_5701_AX_FIX=1\
                     -DDBG=0 -DT3_JUMBO_RCV_RCB_ENTRY_COUNT=256\
                     -DTEXT_BASE=$(TEXT_BASE)
+
index 6e03b72b66fa8c5a1a48b6d54185739589b6bd5b..5d3df0c8582f533798622fe70b77f4d8a5aebea7 100644 (file)
@@ -27,5 +27,9 @@
 # Reserve 320 kB for Monitor
 TEXT_BASE = 0xFFFB0000
 
-# Compile the new NAND code (needed iff #ifdef CONFIG_NEW_NAND_CODE)
+# Compile the new NAND code (CFG_NAND_LEGACY mustn't be defined)
 BOARDLIBS = drivers/nand/libnand.a
+
+# Compile the legacy NAND code (CFG_NAND_LEGACY must be defined)
+#BOARDLIBS = drivers/nand_legacy/libnand_legacy.a
+
index 16c67cd9727bf9fe904eb2a8c4991a967505be9e..61edc787faaad8ffc179db1b44b3ea13affe1321 100644 (file)
@@ -22,9 +22,8 @@
 
 #include <common.h>
 
+
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
-#ifdef CONFIG_NEW_NAND_CODE
-/* new NAND handling */
 
 #include <nand.h>
 
@@ -90,7 +89,7 @@ static int ppchameleonevb_device_ready(struct mtd_info *mtdinfo)
 
 /*
  * Board-specific NAND initialization. The following members of the
- * argument are board-specific (per include/linux/mtd/nand_new.h):
+ * argument are board-specific (per include/linux/mtd/nand.h):
  * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
  * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
  * - hwcontrol: hardwarespecific function for accesing control-lines
@@ -115,33 +114,4 @@ void board_nand_init(struct nand_chip *nand)
        nand->chip_delay = NAND_BIG_DELAY_US;
        nand->options = NAND_SAMSUNG_LP_OPTIONS;
 }
-
-#else
-
-/* old NAND handling */
-extern ulong
-nand_probe(ulong physadr);
-
-void
-nand_init(void)
-{
-       ulong totlen = 0;
-
-/*
-       The HI model is equipped with a large block NAND chip not supported yet
-       by U-Boot
-    (CONFIG_PPCHAMELEON_MODULE_MODEL == CONFIG_PPCHAMELEON_MODULE_HI)
-*/
-
-#if (CONFIG_PPCHAMELEON_MODULE_MODEL == CONFIG_PPCHAMELEON_MODULE_ME)
-       debug ("Probing at 0x%.8x\n", CFG_NAND0_BASE);
-       totlen += nand_probe (CFG_NAND0_BASE);
-#endif /* CONFIG_PPCHAMELEON_MODULE_ME, CONFIG_PPCHAMELEON_MODULE_HI */
-
-       debug ("Probing at 0x%.8x\n", CFG_NAND1_BASE);
-       totlen += nand_probe (CFG_NAND1_BASE);
-
-       printf ("%3lu MB\n", totlen >>20);
-}
-#endif
-#endif
+#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
index 03ae7fda4bfd3bd0dddb49dd316159c26a0029c5..84fc3a01dc21e6e684b04c02b34ac5ea1c68c2b6 100644 (file)
@@ -239,7 +239,7 @@ int testdram (void)
 /* ------------------------------------------------------------------------- */
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 
 void nand_init(void)
index 1d743a9f8733e3936035489c4faf9338e17d0477..3cf5dd85bf2dd7e468fbb39513445f9806e26498 100644 (file)
@@ -26,3 +26,6 @@
 #
 
 TEXT_BASE = 0xFFFC0000
+
+# Compile the legacy NAND code (CFG_NAND_LEGACY must be defined)
+BOARDLIBS = drivers/nand_legacy/libnand_legacy.a
index e4cfe1466b36a21be27e3b95b89dd4f7a9467b69..e283a92764bd743904676814477b23ff1e457fd6 100644 (file)
@@ -238,7 +238,7 @@ U_BOOT_CMD(eepwren, 2,      0,      do_eep_wren,
 /* ------------------------------------------------------------------------- */
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 
 void nand_init(void)
index 5c3c01cf8745c7b7f0415dfcbc2db75f4116aa98..0c56c40b9f175a9d1db13795f4cc8496536a702a 100644 (file)
@@ -26,3 +26,6 @@
 #
 
 TEXT_BASE = 0xFFFC0000
+
+# Compile the legacy NAND code (CFG_NAND_LEGACY must be defined)
+BOARDLIBS = drivers/nand_legacy/libnand_legacy.a
index 1decc0ec0cd63b875862ae3297bb8ccdb32966b9..5a70176fade91f0c2352f46463a6b4cac6610534 100644 (file)
  */
 
 #include <common.h>
+
+#ifndef CFG_NAND_LEGACY
+#error CFG_NAND_LEGACY not defined in a file using the legacy NAND support!
+#endif
+
 #include <command.h>
 #include <image.h>
 #include <asm/byteorder.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 #include <fat.h>
 
 #include "auto_update.h"
@@ -37,6 +42,9 @@
 #error "must define CFG_CMD_FAT"
 #endif
 
+
+
+
 extern au_image_t au_image[];
 extern int N_AU_IMAGES;
 
@@ -76,9 +84,9 @@ extern block_dev_desc_t *get_dev (char*, int);
 #define NANDRW_JFFS2   0x02
 #define NANDRW_JFFS2_SKIP      0x04
 extern struct nand_chip nand_dev_desc[];
-extern int nand_rw(struct nand_chip* nand, int cmd, size_t start, size_t len,
+extern int nand_legacy_rw(struct nand_chip* nand, int cmd, size_t start, size_t len,
                   size_t * retlen, u_char * buf);
-extern int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean);
+extern int nand_legacy_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean);
 #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
 
 extern block_dev_desc_t ide_dev_desc[CFG_IDE_MAXDEVICE];
@@ -259,9 +267,9 @@ int au_do_update(int i, long sz)
                } else {
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
                        printf("Updating NAND FLASH with image %s\n", au_image[i].name);
-                       debug ("nand_erase(%lx, %lx);\n", start, end);
-                       rc = nand_erase (nand_dev_desc, start, end - start + 1, 0);
-                       debug ("nand_erase returned %x\n", rc);
+                       debug ("nand_legacy_erase(%lx, %lx);\n", start, end);
+                       rc = nand_legacy_erase (nand_dev_desc, start, end - start + 1, 0);
+                       debug ("nand_legacy_erase returned %x\n", rc);
 #endif
                }
 
@@ -286,10 +294,10 @@ int au_do_update(int i, long sz)
                        rc = flash_write((char *)addr, start, nbytes);
                } else {
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
-                       debug ("nand_rw(%p, %lx %x)\n", addr, start, nbytes);
-                       rc = nand_rw(nand_dev_desc, NANDRW_WRITE | NANDRW_JFFS2,
+                       debug ("nand_legacy_rw(%p, %lx %x)\n", addr, start, nbytes);
+                       rc = nand_legacy_rw(nand_dev_desc, NANDRW_WRITE | NANDRW_JFFS2,
                                     start, nbytes, (size_t *)&total, (uchar *)addr);
-                       debug ("nand_rw: ret=%x total=%d nbytes=%d\n", rc, total, nbytes);
+                       debug ("nand_legacy_rw: ret=%x total=%d nbytes=%d\n", rc, total, nbytes);
 #endif
                }
                if (rc != 0) {
@@ -304,7 +312,7 @@ int au_do_update(int i, long sz)
                        rc = crc32 (0, (uchar *)(start + off), ntohl(hdr->ih_size));
                } else {
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
-                       rc = nand_rw(nand_dev_desc, NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP,
+                       rc = nand_legacy_rw(nand_dev_desc, NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP,
                                     start, nbytes, (size_t *)&total, (uchar *)addr);
                        rc = crc32 (0, (uchar *)(addr + off), ntohl(hdr->ih_size));
 #endif
index 0be45c70d7ab13e5d4fd6828589777b1272f976e..320346f08945765b1fbb844d669d32ab4674a5b0 100644 (file)
@@ -38,3 +38,7 @@ TEXT_BASE = 0xFFFD0000
 endif
 endif
 endif
+
+# Compile the legacy NAND code (CFG_NAND_LEGACY must be defined)
+BOARDLIBS = drivers/nand_legacy/libnand_legacy.a
+
index 7129ad568bc20de690c3727afa1a853959ece63f..ca1f57572b680d82158ed3b65bc60d40ce022f77 100644 (file)
@@ -29,3 +29,7 @@
 TEXT_BASE = 0xFFF80000
 #TEXT_BASE = 0xFFFC0000
 #TEXT_BASE = 0x00FC0000
+
+# Compile the legacy NAND code (CFG_NAND_LEGACY must be defined)
+BOARDLIBS = drivers/nand_legacy/libnand_legacy.a
+
index 9c582b121c6e439da88f6c73a1c3e394a2f01299..a3e935a87a9647ada4771e209ea0e71253455dbc 100644 (file)
@@ -665,7 +665,7 @@ void ide_set_reset(int on)
 
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 
 void nand_init(void)
index a6d31aad2ba881a766c9aced0eba15e633cb3a18..22ff1226bcfbfeba2671631033644f654e25d5a3 100644 (file)
@@ -26,3 +26,7 @@
 #
 
 TEXT_BASE = 0xFFFC0000
+
+# Compile the legacy NAND code (CFG_NAND_LEGACY must be defined)
+BOARDLIBS = drivers/nand_legacy/libnand_legacy.a
+
index e77dba8a869c1ac9d4961fcafec20fe8f6c1e696..0c6771fb120e4baf39c73496f3236b01cc62ebc6 100644 (file)
@@ -265,7 +265,7 @@ int testdram (void)
 
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 
 void nand_init(void)
index 25b210579986548b36679ca2c807722a77e971b2..916b285261ec88148aa8e61898ece3518badb5cc 100644 (file)
@@ -27,3 +27,6 @@
 
 TEXT_BASE = 0xFFFC0000
 #TEXT_BASE = 0x00FC0000
+
+# Compile the legacy NAND code (CFG_NAND_LEGACY must be defined)
+BOARDLIBS = drivers/nand_legacy/libnand_legacy.a
index 5b9d0631f8e782140e4fd0a9e5f0c5d68f0a0cb5..37b92fb65a8dd482a433e0a592c9e5ba33a4ed6a 100644 (file)
@@ -269,7 +269,7 @@ void ide_set_reset(int on)
 
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 
 void nand_init(void)
index 219a4eba15cc0db0851f5cecffc0a714b7649572..72e81030abd69166578a2edfeac1724ffb604847 100644 (file)
@@ -26,3 +26,6 @@
 #
 
 TEXT_BASE = 0xFFF80000
+
+# Compile the legacy NAND code (CFG_NAND_LEGACY must be defined)
+BOARDLIBS = drivers/nand_legacy/libnand_legacy.a
index eda3fd9d9d8639d503a332281a1801d98a8e8c4b..22995b50209db6bb4d7fa1ae3e480bc599030311 100644 (file)
@@ -343,7 +343,7 @@ void ide_set_reset(int on)
 
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 
 void nand_init(void)
index 1d743a9f8733e3936035489c4faf9338e17d0477..3cf5dd85bf2dd7e468fbb39513445f9806e26498 100644 (file)
@@ -26,3 +26,6 @@
 #
 
 TEXT_BASE = 0xFFFC0000
+
+# Compile the legacy NAND code (CFG_NAND_LEGACY must be defined)
+BOARDLIBS = drivers/nand_legacy/libnand_legacy.a
index db24122c5ea7efb2860e4f35002cc55906226322..5a1a3f3e8ee68fe38e07384fb72ba2f9b45a8b76 100644 (file)
@@ -239,7 +239,7 @@ int testdram (void)
 /* ------------------------------------------------------------------------- */
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 
 void nand_init(void)
index 3f7875334defc0b6a7ec69eb13ab241ad63e3f36..39b5c701e02c34f3ed12f0ac94961fa33570aa72 100644 (file)
@@ -185,7 +185,7 @@ int testdram (void)
 
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 
 void nand_init(void)
index 8497ebc812bb2b35cb83716f5f9af5c4a9b2399f..de179c2d657f7d380af320d99a896e69dd84db76 100644 (file)
@@ -26,3 +26,6 @@
 #
 
 TEXT_BASE = 0x40000000
+
+# Compile the legacy NAND code (CFG_NAND_LEGACY must be defined)
+BOARDLIBS = drivers/nand_legacy/libnand_legacy.a
index dd03e4bd5bdd490a8b0c5e8af9d669d418c5e90b..297de97a554ed25eae725acb6566f2ddcb3a6e71 100644 (file)
@@ -599,7 +599,7 @@ int board_early_init_f(void)
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 
 extern ulong nand_probe(ulong physadr);
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
index 57a34c49576441ecf2e31b236c38809d6aa273aa..2e3921b101808d56eed82b1be544e3dc1e1e58a2 100644 (file)
@@ -10,6 +10,6 @@
 # XXX TEXT_BASE = 0x20012000
 TEXT_BASE = 0x13FC0000
 
-# Compile the new NAND code (needed iff #ifdef CONFIG_NEW_NAND_CODE)
+# Compile the new NAND code
 BOARDLIBS = drivers/nand/libnand.a
 
index 82c0342357d5cfe3dd29e1a13b1a774cb040b183..f67786d182e2bb9aa3f5ed4bcad7c77cebca6cd1 100644 (file)
@@ -129,8 +129,8 @@ MUX_CONFIG_OFFSETS:
        .byte 0x0c              @ COMP_MODE_CTRL_0
        .byte 0xff
 
-.globl platformsetup
-platformsetup:
+.globl lowlevel_init
+lowlevel_init:
        /* Improve performance a bit... */
        mrc     p15, 0, r1, c0, c0, 0           @ read C15 ID register
        mrc     p15, 0, r1, c0, c0, 1           @ read C15 Cache information register
index 8497ebc812bb2b35cb83716f5f9af5c4a9b2399f..4b636ed88da102ee291da1bc8f34210c88a4c36c 100644 (file)
@@ -26,3 +26,7 @@
 #
 
 TEXT_BASE = 0x40000000
+
+# Compile the legacy NAND code (CFG_NAND_LEGACY must be defined)
+BOARDLIBS = drivers/nand_legacy/libnand_legacy.a
+
index c9b405145e5918d919a3f2f62d2680a68c7be76b..3ca7bd3c8677e86321d68a417a2e56ea2b17ee02 100644 (file)
@@ -597,7 +597,7 @@ int board_early_init_f(void)
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 
 extern ulong nand_probe(ulong physadr);
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
index 9dddaad54b4fd4013a24164467bfde74e976b1ac..583174a4895ac32d54b51856714c05011cd9a69b 100644 (file)
@@ -26,3 +26,6 @@
 #
 
 TEXT_BASE = 0x40000000
+
+# Compile the legacy NAND code (CFG_NAND_LEGACY must be defined)
+BOARDLIBS = drivers/nand_legacy/libnand_legacy.a
index fb7f7700cffc98ce9e75d4e16f0e8c80179120d3..3e6c61663f202deb232cb831a32f56cd6f51c0d5 100644 (file)
@@ -418,7 +418,7 @@ int board_early_init_f(void)
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 
 extern ulong nand_probe(ulong physadr);
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
index 6ae1a490a500424ba1d198104028b3cdc91c612f..2387176ebce54b1edbf38f44d81bfa49976ed192 100644 (file)
@@ -32,7 +32,7 @@
 #include <i2c.h>
 #include <asm/mach-types.h>
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 #endif
 
index 0cd8f4414802c91be7a479919e6f3f69d14e5a9d..8e73d2f3693940ae4e47d4d1a1dd88c91d8df8dc 100644 (file)
@@ -26,3 +26,6 @@
 #
 
 TEXT_BASE = 0xF8000000
+
+# Compile the legacy NAND code (CFG_NAND_LEGACY must be defined)
+BOARDLIBS = drivers/nand_legacy/libnand_legacy.a
index 867589f918e36da26cd8bd7b81ac89d1689e744c..a25dffdad527d7dc13950513bd035be012464767 100644 (file)
@@ -34,7 +34,7 @@
 #endif
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 #endif
 
index aa3d129f9c930cd34b5b85040a2c85e909c362cc..7caf06a0862d5af851b570464b6a8d3b5fc0b131 100644 (file)
@@ -576,7 +576,7 @@ int board_early_init_f(void)
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 
 extern ulong nand_probe(ulong physadr);
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
index 7e45a7c7168df55320d8a015afae5c6f10780ec0..7dbf84a555ea9d3b54742f96785e8cf900056a83 100644 (file)
@@ -37,7 +37,7 @@ COBJS = main.o ACEX1K.o altera.o bedbug.o circbuf.o \
          cmd_i2c.o cmd_ide.o cmd_immap.o cmd_itest.o cmd_jffs2.o \
          cmd_load.o cmd_log.o \
          cmd_mem.o cmd_mii.o cmd_misc.o cmd_mmc.o \
-         cmd_nand.o cmd_nand_new.o cmd_net.o cmd_nvedit.o \
+         cmd_nand.o cmd_net.o cmd_nvedit.o \
          cmd_pci.o cmd_pcmcia.o cmd_portio.o \
          cmd_reginfo.o cmd_reiser.o cmd_scsi.o cmd_spi.o cmd_universe.o \
          cmd_usb.o cmd_vfd.o \
index 5e9bea30450683eea1d22c91d920676c3e5fe4e6..c726957cace50e6f6628ee8be18209469bdec793 100644 (file)
@@ -22,8 +22,9 @@
 #if (CONFIG_COMMANDS & CFG_CMD_DOC)
 
 #include <linux/mtd/nftl.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_legacy.h>
 #include <linux/mtd/nand_ids.h>
+
 #include <linux/mtd/doc2000.h>
 #include <linux/mtd/nftl.h>
 
index ecadb796347fc5a7ce100cfd7c11269ba804a4ca..201c3c1553c3451c7f4402c7ad3a0127ad38bf9b 100644 (file)
@@ -91,7 +91,6 @@
 #include <command.h>
 #include <malloc.h>
 #include <jffs2/jffs2.h>
-#include <linux/mtd/nand.h>
 #include <linux/list.h>
 #include <linux/ctype.h>
 
 
 #include <cramfs/cramfs_fs.h>
 
-#ifdef CONFIG_NEW_NAND_CODE
+#if (CONFIG_COMMANDS & CFG_CMD_NAND)
+#ifdef CFG_NAND_LEGACY
+#include <linux/mtd/nand_legacy.h>
+#else /* !CFG_NAND_LEGACY */
+#include <linux/mtd/nand.h>
 #include <nand.h>
-#endif
-
+#endif /* !CFG_NAND_LEGACY */
+#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
 /* enable/disable debugging messages */
 #define        DEBUG_JFFS
 #undef DEBUG_JFFS
@@ -467,7 +470,7 @@ static int part_del(struct mtd_device *dev, struct part_info *part)
                }
        }
 
-#ifndef CONFIG_NEW_NAND_CODE
+#ifdef CFG_NAND_LEGACY
        jffs2_free_cache(part);
 #endif
        list_del(&part->link);
@@ -496,7 +499,7 @@ static void part_delall(struct list_head *head)
        list_for_each_safe(entry, n, head) {
                part_tmp = list_entry(entry, struct part_info, link);
 
-#ifndef CONFIG_NEW_NAND_CODE
+#ifdef CFG_NAND_LEGACY
                jffs2_free_cache(part_tmp);
 #endif
                list_del(entry);
@@ -732,7 +735,7 @@ static int device_validate(u8 type, u8 num, u32 *size)
        } else if (type == MTD_DEV_TYPE_NAND) {
 #if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)
                if (num < CFG_MAX_NAND_DEVICE) {
-#ifdef CONFIG_NEW_NAND_CODE
+#ifndef CFG_NAND_LEGACY
                        *size = nand_info[num].size;
 #else
                        extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
index 152873f1ae1069c2057c1cd6d05abcfa02c3e6c6..e46ed1d3c4a0b7599a11536dbf79236d5c38a6b7 100644 (file)
@@ -9,6 +9,387 @@
  */
 
 #include <common.h>
+
+
+#ifndef CFG_NAND_LEGACY
+/*
+ *
+ * New NAND support
+ *
+ */
+#include <common.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_NAND)
+
+#include <command.h>
+#include <watchdog.h>
+#include <malloc.h>
+#include <asm/byteorder.h>
+
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+# include <status_led.h>
+# define SHOW_BOOT_PROGRESS(arg)       show_boot_progress(arg)
+#else
+# define SHOW_BOOT_PROGRESS(arg)
+#endif
+
+#include <jffs2/jffs2.h>
+#include <nand.h>
+
+extern nand_info_t nand_info[];       /* info for NAND chips */
+
+static int nand_dump_oob(nand_info_t *nand, ulong off)
+{
+       return 0;
+}
+
+static int nand_dump(nand_info_t *nand, ulong off)
+{
+       int i;
+       u_char *buf, *p;
+
+       buf = malloc(nand->oobblock + nand->oobsize);
+       if (!buf) {
+               puts("No memory for page buffer\n");
+               return 1;
+       }
+       off &= ~(nand->oobblock - 1);
+       i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);
+       if (i < 0) {
+               printf("Error (%d) reading page %08x\n", i, off);
+               free(buf);
+               return 1;
+       }
+       printf("Page %08x dump:\n", off);
+       i = nand->oobblock >> 4; p = buf;
+       while (i--) {
+               printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"
+                       "  %02x %02x %02x %02x %02x %02x %02x %02x\n",
+                       p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
+                       p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
+               p += 16;
+       }
+       puts("OOB:\n");
+       i = nand->oobsize >> 3;
+       while (i--) {
+               printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
+                       p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+               p += 8;
+       }
+       free(buf);
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void
+arg_off_size(int argc, char *argv[], ulong *off, ulong *size, ulong totsize)
+{
+       *off = 0;
+       *size = 0;
+
+#if defined(CONFIG_JFFS2_NAND) && defined(CFG_JFFS_CUSTOM_PART)
+       if (argc >= 1 && strcmp(argv[0], "partition") == 0) {
+               int part_num;
+               struct part_info *part;
+               const char *partstr;
+
+               if (argc >= 2)
+                       partstr = argv[1];
+               else
+                       partstr = getenv("partition");
+
+               if (partstr)
+                       part_num = (int)simple_strtoul(partstr, NULL, 10);
+               else
+                       part_num = 0;
+
+               part = jffs2_part_info(part_num);
+               if (part == NULL) {
+                       printf("\nInvalid partition %d\n", part_num);
+                       return;
+               }
+               *size = part->size;
+               *off = (ulong)part->offset;
+       } else
+#endif
+       {
+               if (argc >= 1)
+                       *off = (ulong)simple_strtoul(argv[0], NULL, 16);
+               else
+                       *off = 0;
+
+               if (argc >= 2)
+                       *size = (ulong)simple_strtoul(argv[1], NULL, 16);
+               else
+                       *size = totsize - *off;
+
+       }
+
+}
+
+int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+       int i, dev, ret;
+       ulong addr, off, size;
+       char *cmd, *s;
+       nand_info_t *nand;
+
+       /* at least two arguments please */
+       if (argc < 2)
+               goto usage;
+
+       cmd = argv[1];
+
+       if (strcmp(cmd, "info") == 0) {
+
+               putc('\n');
+               for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
+                       if (nand_info[i].name)
+                               printf("Device %d: %s, sector size %lu KiB\n",
+                                       i, nand_info[i].name,
+                                       nand_info[i].erasesize >> 10);
+               }
+               return 0;
+       }
+
+       if (strcmp(cmd, "device") == 0) {
+
+               if (argc < 3) {
+                       if ((nand_curr_device < 0) ||
+                           (nand_curr_device >= CFG_MAX_NAND_DEVICE))
+                               puts("\nno devices available\n");
+                       else
+                               printf("\nDevice %d: %s\n", nand_curr_device,
+                                       nand_info[nand_curr_device].name);
+                       return 0;
+               }
+               dev = (int)simple_strtoul(argv[2], NULL, 10);
+               if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
+                       puts("No such device\n");
+                       return 1;
+               }
+               printf("Device %d: %s", dev, nand_info[dev].name);
+               puts("... is now current device\n");
+               nand_curr_device = dev;
+               return 0;
+       }
+
+       if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
+           strncmp(cmd, "dump", 4) != 0 &&
+           strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0)
+               goto usage;
+
+       /* the following commands operate on the current device */
+       if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||
+           !nand_info[nand_curr_device].name) {
+               puts("\nno devices available\n");
+               return 1;
+       }
+       nand = &nand_info[nand_curr_device];
+
+       if (strcmp(cmd, "bad") == 0) {
+               printf("\nDevice %d bad blocks:\n", nand_curr_device);
+               for (off = 0; off < nand->size; off += nand->erasesize)
+                       if (nand_block_isbad(nand, off))
+                               printf("  %08x\n", off);
+               return 0;
+       }
+
+       if (strcmp(cmd, "erase") == 0) {
+               arg_off_size(argc - 2, argv + 2, &off, &size, nand->size);
+               if (off == 0 && size == 0)
+                       return 1;
+
+               printf("\nNAND erase: device %d offset 0x%x, size 0x%x ",
+                      nand_curr_device, off, size);
+               ret = nand_erase(nand, off, size);
+               printf("%s\n", ret ? "ERROR" : "OK");
+
+               return ret == 0 ? 0 : 1;
+       }
+
+       if (strncmp(cmd, "dump", 4) == 0) {
+               if (argc < 3)
+                       goto usage;
+
+               s = strchr(cmd, '.');
+               off = (int)simple_strtoul(argv[2], NULL, 16);
+
+               if (s != NULL && strcmp(s, ".oob") == 0)
+                       ret = nand_dump_oob(nand, off);
+               else
+                       ret = nand_dump(nand, off);
+
+               return ret == 0 ? 1 : 0;
+
+       }
+
+       /* read write */
+       if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
+               if (argc < 4)
+                       goto usage;
+/*
+               s = strchr(cmd, '.');
+               clean = CLEAN_NONE;
+               if (s != NULL) {
+                       if (strcmp(s, ".jffs2") == 0 || strcmp(s, ".e") == 0
+                           || strcmp(s, ".i"))
+                               clean = CLEAN_JFFS2;
+               }
+*/
+               addr = (ulong)simple_strtoul(argv[2], NULL, 16);
+
+               arg_off_size(argc - 3, argv + 3, &off, &size, nand->size);
+               if (off == 0 && size == 0)
+                       return 1;
+
+               i = strncmp(cmd, "read", 4) == 0;       /* 1 = read, 0 = write */
+               printf("\nNAND %s: device %d offset %u, size %u ... ",
+                      i ? "read" : "write", nand_curr_device, off, size);
+
+               if (i)
+                       ret = nand_read(nand, off, &size, (u_char *)addr);
+               else
+                       ret = nand_write(nand, off, &size, (u_char *)addr);
+
+               printf(" %d bytes %s: %s\n", size,
+                      i ? "read" : "written", ret ? "ERROR" : "OK");
+
+               return ret == 0 ? 0 : 1;
+       }
+usage:
+       printf("Usage:\n%s\n", cmdtp->usage);
+       return 1;
+}
+
+U_BOOT_CMD(nand, 5, 1, do_nand,
+       "nand    - NAND sub-system\n",
+       "info                  - show available NAND devices\n"
+       "nand device [dev]     - show or set current device\n"
+       "nand read[.jffs2]     - addr off size\n"
+       "nand write[.jffs2]    - addr off size - read/write `size' bytes starting\n"
+       "    at offset `off' to/from memory address `addr'\n"
+       "nand erase [clean] [off size] - erase `size' bytes from\n"
+       "    offset `off' (entire device if not specified)\n"
+       "nand bad - show bad blocks\n"
+       "nand dump[.oob] off - dump page\n"
+       "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
+       "nand markbad off - mark bad block at offset (UNSAFE)\n"
+       "nand biterr off - make a bit error at offset (UNSAFE)\n");
+
+int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+       char *boot_device = NULL;
+       char *ep;
+       int dev;
+       int r;
+       ulong addr, cnt, offset = 0;
+       image_header_t *hdr;
+       nand_info_t *nand;
+
+       switch (argc) {
+       case 1:
+               addr = CFG_LOAD_ADDR;
+               boot_device = getenv("bootdevice");
+               break;
+       case 2:
+               addr = simple_strtoul(argv[1], NULL, 16);
+               boot_device = getenv("bootdevice");
+               break;
+       case 3:
+               addr = simple_strtoul(argv[1], NULL, 16);
+               boot_device = argv[2];
+               break;
+       case 4:
+               addr = simple_strtoul(argv[1], NULL, 16);
+               boot_device = argv[2];
+               offset = simple_strtoul(argv[3], NULL, 16);
+               break;
+       default:
+               printf("Usage:\n%s\n", cmdtp->usage);
+               SHOW_BOOT_PROGRESS(-1);
+               return 1;
+       }
+
+       if (!boot_device) {
+               puts("\n** No boot device **\n");
+               SHOW_BOOT_PROGRESS(-1);
+               return 1;
+       }
+
+       dev = simple_strtoul(boot_device, &ep, 16);
+
+       if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
+               printf("\n** Device %d not available\n", dev);
+               SHOW_BOOT_PROGRESS(-1);
+               return 1;
+       }
+
+       nand = &nand_info[dev];
+       printf("\nLoading from device %d: %s (offset 0x%lx)\n",
+              dev, nand->name, offset);
+
+       cnt = nand->oobblock;
+       r = nand_read(nand, offset, &cnt, (u_char *) addr);
+       if (r) {
+               printf("** Read error on %d\n", dev);
+               SHOW_BOOT_PROGRESS(-1);
+               return 1;
+       }
+
+       hdr = (image_header_t *) addr;
+
+       if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+               printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
+               SHOW_BOOT_PROGRESS(-1);
+               return 1;
+       }
+
+       print_image_hdr(hdr);
+
+       cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t));
+
+       r = nand_read(nand, offset, &cnt, (u_char *) addr);
+       if (r) {
+               printf("** Read error on %d\n", dev);
+               SHOW_BOOT_PROGRESS(-1);
+               return 1;
+       }
+
+       /* Loading ok, update default load address */
+
+       load_addr = addr;
+
+       /* Check if we should attempt an auto-start */
+       if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
+               char *local_args[2];
+               extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
+
+               local_args[0] = argv[0];
+               local_args[1] = NULL;
+
+               printf("Automatic boot of image at addr 0x%08lx ...\n", addr);
+
+               do_bootm(cmdtp, 0, 1, local_args);
+               return 1;
+       }
+       return 0;
+}
+
+U_BOOT_CMD(nboot, 4, 1, do_nandboot,
+       "nboot   - boot from NAND device\n", "loadAddr dev\n");
+
+
+#endif                         /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
+
+#else /* CFG_NAND_LEGACY */
+/*
+ *
+ * Legacy NAND support - to be phased out
+ *
+ */
 #include <command.h>
 #include <malloc.h>
 #include <asm/io.h>
 # define SHOW_BOOT_PROGRESS(arg)
 #endif
 
-#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CONFIG_NEW_NAND_CODE)
-
-#include <linux/mtd/nand.h>
+#if (CONFIG_COMMANDS & CFG_CMD_NAND)
+#include <linux/mtd/nand_legacy.h>
+#if 0
 #include <linux/mtd/nand_ids.h>
 #include <jffs2/jffs2.h>
+#endif
 
 #ifdef CONFIG_OMAP1510
 void archflashwp(void *archdata, int wp);
@@ -33,15 +415,6 @@ void archflashwp(void *archdata, int wp);
 
 #define ROUND_DOWN(value,boundary)      ((value) & (~((boundary)-1)))
 
-/*
- * Definition of the out of band configuration structure
- */
-struct nand_oob_config {
-       int ecc_pos[6];         /* position of ECC bytes inside oob */
-       int badblock_pos;       /* position of bad block flag inside oob -1 = inactive */
-       int eccvalid_pos;       /* position of ECC valid flag inside oob -1 = inactive */
-} oob_config = { {0}, 0, 0};
-
 #undef NAND_DEBUG
 #undef PSYCHO_DEBUG
 
@@ -63,41 +436,30 @@ struct nand_oob_config {
 #define CONFIG_MTD_NAND_ECC  /* enable ECC */
 #define CONFIG_MTD_NAND_ECC_JFFS2
 
-/* bits for nand_rw() `cmd'; or together as needed */
+/* bits for nand_legacy_rw() `cmd'; or together as needed */
 #define NANDRW_READ    0x01
 #define NANDRW_WRITE   0x00
 #define NANDRW_JFFS2   0x02
 #define NANDRW_JFFS2_SKIP      0x04
 
-/*
- * Function Prototypes
- */
-static void nand_print(struct nand_chip *nand);
-int nand_rw (struct nand_chip* nand, int cmd,
-           size_t start, size_t len,
-           size_t * retlen, u_char * buf);
-int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean);
-static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
-                size_t * retlen, u_char *buf, u_char *ecc_code);
-static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len,
-                          size_t * retlen, const u_char * buf, u_char * ecc_code);
-static void nand_print_bad(struct nand_chip *nand);
-static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len,
-                size_t * retlen, u_char * buf);
-static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
-                size_t * retlen, const u_char * buf);
-static int NanD_WaitReady(struct nand_chip *nand, int ale_wait);
-#ifdef CONFIG_MTD_NAND_ECC
-static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc);
-static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code);
-#endif
 
-struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE] = {{0}};
 
-/* Current NAND Device */
-static int curr_device = -1;
+/*
+ * Imports from nand_legacy.c
+ */
+extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
+extern int curr_device;
+extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs,
+                           size_t len, int clean);
+extern int nand_legacy_rw(struct nand_chip *nand, int cmd, size_t start,
+                        size_t len, size_t *retlen, u_char *buf);
+extern void nand_print(struct nand_chip *nand);
+extern void nand_print_bad(struct nand_chip *nand);
+extern int nand_read_oob(struct nand_chip *nand, size_t ofs,
+                              size_t len, size_t *retlen, u_char *buf);
+extern int nand_write_oob(struct nand_chip *nand, size_t ofs,
+                               size_t len, size_t *retlen, const u_char *buf);
 
-/* ------------------------------------------------------------------------- */
 
 int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
@@ -174,7 +536,7 @@ int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
                        curr_device, off, size);
 
-               ret = nand_erase (nand, off, size, 1);
+               ret = nand_legacy_erase (nand, off, size, 1);
 
                printf("%s\n", ret ? "ERROR" : "OK");
 
@@ -240,7 +602,7 @@ int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                        (cmd & NANDRW_READ) ? "read" : "write",
                        curr_device, off, size);
 
-               ret = nand_rw(nand_dev_desc + curr_device, cmd, off, size,
+               ret = nand_legacy_rw(nand_dev_desc + curr_device, cmd, off, size,
                             (size_t *)&total, (u_char*)addr);
 
                printf (" %d bytes %s: %s\n", total,
@@ -258,7 +620,8 @@ int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
                        curr_device, off, size);
 
-               ret = nand_erase (nand_dev_desc + curr_device, off, size, clean);
+               ret = nand_legacy_erase (nand_dev_desc + curr_device,
+                                       off, size, clean);
 
                printf("%s\n", ret ? "ERROR" : "OK");
 
@@ -340,8 +703,8 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
                offset);
 
-       if (nand_rw (nand_dev_desc + dev, NANDRW_READ, offset,
-                   SECTORSIZE, NULL, (u_char *)addr)) {
+       if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset,
+                       SECTORSIZE, NULL, (u_char *)addr)) {
                printf ("** Read error on %d\n", dev);
                SHOW_BOOT_PROGRESS (-1);
                return 1;
@@ -361,8 +724,9 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                return 1;
        }
 
-       if (nand_rw (nand_dev_desc + dev, NANDRW_READ, offset + SECTORSIZE, cnt,
-                   NULL, (u_char *)(addr+SECTORSIZE))) {
+       if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ,
+                       offset + SECTORSIZE, cnt, NULL,
+                       (u_char *)(addr+SECTORSIZE))) {
                printf ("** Read error on %d\n", dev);
                SHOW_BOOT_PROGRESS (-1);
                return 1;
@@ -394,1505 +758,6 @@ U_BOOT_CMD(
        "loadAddr dev\n"
 );
 
-/* returns 0 if block containing pos is OK:
- *             valid erase block and
- *             not marked bad, or no bad mark position is specified
- * returns 1 if marked bad or otherwise invalid
- */
-int check_block (struct nand_chip *nand, unsigned long pos)
-{
-       size_t retlen;
-       uint8_t oob_data;
-       uint16_t oob_data16[6];
-       int page0 = pos & (-nand->erasesize);
-       int page1 = page0 + nand->oobblock;
-       int badpos = oob_config.badblock_pos;
-
-       if (pos >= nand->totlen)
-               return 1;
-
-       if (badpos < 0)
-               return 0;       /* no way to check, assume OK */
-
-       if (nand->bus16) {
-               if (nand_read_oob(nand, (page0 + 0), 12, &retlen, (uint8_t *)oob_data16)
-                   || (oob_data16[2] & 0xff00) != 0xff00)
-                       return 1;
-               if (nand_read_oob(nand, (page1 + 0), 12, &retlen, (uint8_t *)oob_data16)
-                   || (oob_data16[2] & 0xff00) != 0xff00)
-                       return 1;
-       } else {
-               /* Note - bad block marker can be on first or second page */
-               if (nand_read_oob(nand, page0 + badpos, 1, &retlen, (unsigned char *)&oob_data)
-                   || oob_data != 0xff
-                   || nand_read_oob (nand, page1 + badpos, 1, &retlen, (unsigned char *)&oob_data)
-                   || oob_data != 0xff)
-                       return 1;
-       }
-
-       return 0;
-}
-
-/* print bad blocks in NAND flash */
-static void nand_print_bad(struct nand_chip* nand)
-{
-       unsigned long pos;
-
-       for (pos = 0; pos < nand->totlen; pos += nand->erasesize) {
-               if (check_block(nand, pos))
-                       printf(" 0x%8.8lx\n", pos);
-       }
-       puts("\n");
-}
-
-/* cmd: 0: NANDRW_WRITE                        write, fail on bad block
- *     1: NANDRW_READ                  read, fail on bad block
- *     2: NANDRW_WRITE | NANDRW_JFFS2  write, skip bad blocks
- *     3: NANDRW_READ | NANDRW_JFFS2   read, data all 0xff for bad blocks
- *      7: NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP read, skip bad blocks
- */
-int nand_rw (struct nand_chip* nand, int cmd,
-           size_t start, size_t len,
-           size_t * retlen, u_char * buf)
-{
-       int ret = 0, n, total = 0;
-       char eccbuf[6];
-       /* eblk (once set) is the start of the erase block containing the
-        * data being processed.
-        */
-       unsigned long eblk = ~0;        /* force mismatch on first pass */
-       unsigned long erasesize = nand->erasesize;
-
-       while (len) {
-               if ((start & (-erasesize)) != eblk) {
-                       /* have crossed into new erase block, deal with
-                        * it if it is sure marked bad.
-                        */
-                       eblk = start & (-erasesize); /* start of block */
-                       if (check_block(nand, eblk)) {
-                               if (cmd == (NANDRW_READ | NANDRW_JFFS2)) {
-                                       while (len > 0 &&
-                                              start - eblk < erasesize) {
-                                               *(buf++) = 0xff;
-                                               ++start;
-                                               ++total;
-                                               --len;
-                                       }
-                                       continue;
-                               } else if (cmd == (NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP)) {
-                                       start += erasesize;
-                                       continue;
-                               } else if (cmd == (NANDRW_WRITE | NANDRW_JFFS2)) {
-                                       /* skip bad block */
-                                       start += erasesize;
-                                       continue;
-                               } else {
-                                       ret = 1;
-                                       break;
-                               }
-                       }
-               }
-               /* The ECC will not be calculated correctly if
-                  less than 512 is written or read */
-               /* Is request at least 512 bytes AND it starts on a proper boundry */
-               if((start != ROUND_DOWN(start, 0x200)) || (len < 0x200))
-                       printf("Warning block writes should be at least 512 bytes and start on a 512 byte boundry\n");
-
-               if (cmd & NANDRW_READ) {
-                       ret = nand_read_ecc(nand, start,
-                                          min(len, eblk + erasesize - start),
-                                          (size_t *)&n, (u_char*)buf, (u_char *)eccbuf);
-               } else {
-                       ret = nand_write_ecc(nand, start,
-                                           min(len, eblk + erasesize - start),
-                                           (size_t *)&n, (u_char*)buf, (u_char *)eccbuf);
-               }
-
-               if (ret)
-                       break;
-
-               start  += n;
-               buf   += n;
-               total += n;
-               len   -= n;
-       }
-       if (retlen)
-               *retlen = total;
-
-       return ret;
-}
-
-static void nand_print(struct nand_chip *nand)
-{
-       if (nand->numchips > 1) {
-               printf("%s at 0x%lx,\n"
-                      "\t  %d chips %s, size %d MB, \n"
-                      "\t  total size %ld MB, sector size %ld kB\n",
-                      nand->name, nand->IO_ADDR, nand->numchips,
-                      nand->chips_name, 1 << (nand->chipshift - 20),
-                      nand->totlen >> 20, nand->erasesize >> 10);
-       }
-       else {
-               printf("%s at 0x%lx (", nand->chips_name, nand->IO_ADDR);
-               print_size(nand->totlen, ", ");
-               print_size(nand->erasesize, " sector)\n");
-       }
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int NanD_WaitReady(struct nand_chip *nand, int ale_wait)
-{
-       /* This is inline, to optimise the common case, where it's ready instantly */
-       int ret = 0;
-
-#ifdef NAND_NO_RB      /* in config file, shorter delays currently wrap accesses */
-       if(ale_wait)
-               NAND_WAIT_READY(nand);  /* do the worst case 25us wait */
-       else
-               udelay(10);
-#else  /* has functional r/b signal */
-       NAND_WAIT_READY(nand);
-#endif
-       return ret;
-}
-
-/* NanD_Command: Send a flash command to the flash chip */
-
-static inline int NanD_Command(struct nand_chip *nand, unsigned char command)
-{
-       unsigned long nandptr = nand->IO_ADDR;
-
-       /* Assert the CLE (Command Latch Enable) line to the flash chip */
-       NAND_CTL_SETCLE(nandptr);
-
-       /* Send the command */
-       WRITE_NAND_COMMAND(command, nandptr);
-
-       /* Lower the CLE line */
-       NAND_CTL_CLRCLE(nandptr);
-
-#ifdef NAND_NO_RB
-       if(command == NAND_CMD_RESET){
-               u_char ret_val;
-               NanD_Command(nand, NAND_CMD_STATUS);
-               do {
-                       ret_val = READ_NAND(nandptr);/* wait till ready */
-               } while((ret_val & 0x40) != 0x40);
-       }
-#endif
-       return NanD_WaitReady(nand, 0);
-}
-
-/* NanD_Address: Set the current address for the flash chip */
-
-static int NanD_Address(struct nand_chip *nand, int numbytes, unsigned long ofs)
-{
-       unsigned long nandptr;
-       int i;
-
-       nandptr = nand->IO_ADDR;
-
-       /* Assert the ALE (Address Latch Enable) line to the flash chip */
-       NAND_CTL_SETALE(nandptr);
-
-       /* Send the address */
-       /* Devices with 256-byte page are addressed as:
-        * Column (bits 0-7), Page (bits 8-15, 16-23, 24-31)
-        * there is no device on the market with page256
-        * and more than 24 bits.
-        * Devices with 512-byte page are addressed as:
-        * Column (bits 0-7), Page (bits 9-16, 17-24, 25-31)
-        * 25-31 is sent only if the chip support it.
-        * bit 8 changes the read command to be sent
-        * (NAND_CMD_READ0 or NAND_CMD_READ1).
-        */
-
-       if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE)
-               WRITE_NAND_ADDRESS(ofs, nandptr);
-
-       ofs = ofs >> nand->page_shift;
+#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
 
-       if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE) {
-               for (i = 0; i < nand->pageadrlen; i++, ofs = ofs >> 8) {
-                       WRITE_NAND_ADDRESS(ofs, nandptr);
-               }
-       }
-
-       /* Lower the ALE line */
-       NAND_CTL_CLRALE(nandptr);
-
-       /* Wait for the chip to respond */
-       return NanD_WaitReady(nand, 1);
-}
-
-/* NanD_SelectChip: Select a given flash chip within the current floor */
-
-static inline int NanD_SelectChip(struct nand_chip *nand, int chip)
-{
-       /* Wait for it to be ready */
-       return NanD_WaitReady(nand, 0);
-}
-
-/* NanD_IdentChip: Identify a given NAND chip given {floor,chip} */
-
-static int NanD_IdentChip(struct nand_chip *nand, int floor, int chip)
-{
-       int mfr, id, i;
-
-       NAND_ENABLE_CE(nand);  /* set pin low */
-       /* Reset the chip */
-       if (NanD_Command(nand, NAND_CMD_RESET)) {
-#ifdef NAND_DEBUG
-               printf("NanD_Command (reset) for %d,%d returned true\n",
-                      floor, chip);
-#endif
-               NAND_DISABLE_CE(nand);  /* set pin high */
-               return 0;
-       }
-
-       /* Read the NAND chip ID: 1. Send ReadID command */
-       if (NanD_Command(nand, NAND_CMD_READID)) {
-#ifdef NAND_DEBUG
-               printf("NanD_Command (ReadID) for %d,%d returned true\n",
-                      floor, chip);
-#endif
-               NAND_DISABLE_CE(nand);  /* set pin high */
-               return 0;
-       }
-
-       /* Read the NAND chip ID: 2. Send address byte zero */
-       NanD_Address(nand, ADDR_COLUMN, 0);
-
-       /* Read the manufacturer and device id codes from the device */
-
-       mfr = READ_NAND(nand->IO_ADDR);
-
-       id = READ_NAND(nand->IO_ADDR);
-
-       NAND_DISABLE_CE(nand);  /* set pin high */
-
-#ifdef NAND_DEBUG
-       printf("NanD_Command (ReadID) got %x %x\n", mfr, id);
-#endif
-       if (mfr == 0xff || mfr == 0) {
-               /* No response - return failure */
-               return 0;
-       }
-
-       /* Check it's the same as the first chip we identified.
-        * M-Systems say that any given nand_chip device should only
-        * contain _one_ type of flash part, although that's not a
-        * hardware restriction. */
-       if (nand->mfr) {
-               if (nand->mfr == mfr && nand->id == id) {
-                       return 1;       /* This is another the same the first */
-               } else {
-                       printf("Flash chip at floor %d, chip %d is different:\n",
-                              floor, chip);
-               }
-       }
-
-       /* Print and store the manufacturer and ID codes. */
-       for (i = 0; nand_flash_ids[i].name != NULL; i++) {
-               if (mfr == nand_flash_ids[i].manufacture_id &&
-                   id == nand_flash_ids[i].model_id) {
-#ifdef NAND_DEBUG
-                       printf("Flash chip found:\n\t Manufacturer ID: 0x%2.2X, "
-                              "Chip ID: 0x%2.2X (%s)\n", mfr, id,
-                              nand_flash_ids[i].name);
-#endif
-                       if (!nand->mfr) {
-                               nand->mfr = mfr;
-                               nand->id = id;
-                               nand->chipshift =
-                                   nand_flash_ids[i].chipshift;
-                               nand->page256 = nand_flash_ids[i].page256;
-                               nand->eccsize = 256;
-                               if (nand->page256) {
-                                       nand->oobblock = 256;
-                                       nand->oobsize = 8;
-                                       nand->page_shift = 8;
-                               } else {
-                                       nand->oobblock = 512;
-                                       nand->oobsize = 16;
-                                       nand->page_shift = 9;
-                               }
-                               nand->pageadrlen = nand_flash_ids[i].pageadrlen;
-                               nand->erasesize  = nand_flash_ids[i].erasesize;
-                               nand->chips_name = nand_flash_ids[i].name;
-                               nand->bus16      = nand_flash_ids[i].bus16;
-                               return 1;
-                       }
-                       return 0;
-               }
-       }
-
-
-#ifdef NAND_DEBUG
-       /* We haven't fully identified the chip. Print as much as we know. */
-       printf("Unknown flash chip found: %2.2X %2.2X\n",
-              id, mfr);
-#endif
-
-       return 0;
-}
-
-/* NanD_ScanChips: Find all NAND chips present in a nand_chip, and identify them */
-
-static void NanD_ScanChips(struct nand_chip *nand)
-{
-       int floor, chip;
-       int numchips[NAND_MAX_FLOORS];
-       int maxchips = NAND_MAX_CHIPS;
-       int ret = 1;
-
-       nand->numchips = 0;
-       nand->mfr = 0;
-       nand->id = 0;
-
-
-       /* For each floor, find the number of valid chips it contains */
-       for (floor = 0; floor < NAND_MAX_FLOORS; floor++) {
-               ret = 1;
-               numchips[floor] = 0;
-               for (chip = 0; chip < maxchips && ret != 0; chip++) {
-
-                       ret = NanD_IdentChip(nand, floor, chip);
-                       if (ret) {
-                               numchips[floor]++;
-                               nand->numchips++;
-                       }
-               }
-       }
-
-       /* If there are none at all that we recognise, bail */
-       if (!nand->numchips) {
-#ifdef NAND_DEBUG
-               puts ("No NAND flash chips recognised.\n");
-#endif
-               return;
-       }
-
-       /* Allocate an array to hold the information for each chip */
-       nand->chips = malloc(sizeof(struct Nand) * nand->numchips);
-       if (!nand->chips) {
-               puts ("No memory for allocating chip info structures\n");
-               return;
-       }
-
-       ret = 0;
-
-       /* Fill out the chip array with {floor, chipno} for each
-        * detected chip in the device. */
-       for (floor = 0; floor < NAND_MAX_FLOORS; floor++) {
-               for (chip = 0; chip < numchips[floor]; chip++) {
-                       nand->chips[ret].floor = floor;
-                       nand->chips[ret].chip = chip;
-                       nand->chips[ret].curadr = 0;
-                       nand->chips[ret].curmode = 0x50;
-                       ret++;
-               }
-       }
-
-       /* Calculate and print the total size of the device */
-       nand->totlen = nand->numchips * (1 << nand->chipshift);
-
-#ifdef NAND_DEBUG
-       printf("%d flash chips found. Total nand_chip size: %ld MB\n",
-              nand->numchips, nand->totlen >> 20);
-#endif
-}
-
-/* we need to be fast here, 1 us per read translates to 1 second per meg */
-static void NanD_ReadBuf (struct nand_chip *nand, u_char * data_buf, int cntr)
-{
-       unsigned long nandptr = nand->IO_ADDR;
-
-       NanD_Command (nand, NAND_CMD_READ0);
-
-       if (nand->bus16) {
-               u16 val;
-
-               while (cntr >= 16) {
-                       val = READ_NAND (nandptr);
-                       *data_buf++ = val & 0xff;
-                       *data_buf++ = val >> 8;
-                       val = READ_NAND (nandptr);
-                       *data_buf++ = val & 0xff;
-                       *data_buf++ = val >> 8;
-                       val = READ_NAND (nandptr);
-                       *data_buf++ = val & 0xff;
-                       *data_buf++ = val >> 8;
-                       val = READ_NAND (nandptr);
-                       *data_buf++ = val & 0xff;
-                       *data_buf++ = val >> 8;
-                       val = READ_NAND (nandptr);
-                       *data_buf++ = val & 0xff;
-                       *data_buf++ = val >> 8;
-                       val = READ_NAND (nandptr);
-                       *data_buf++ = val & 0xff;
-                       *data_buf++ = val >> 8;
-                       val = READ_NAND (nandptr);
-                       *data_buf++ = val & 0xff;
-                       *data_buf++ = val >> 8;
-                       val = READ_NAND (nandptr);
-                       *data_buf++ = val & 0xff;
-                       *data_buf++ = val >> 8;
-                       cntr -= 16;
-               }
-
-               while (cntr > 0) {
-                       val = READ_NAND (nandptr);
-                       *data_buf++ = val & 0xff;
-                       *data_buf++ = val >> 8;
-                       cntr -= 2;
-               }
-       } else {
-               while (cntr >= 16) {
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       *data_buf++ = READ_NAND (nandptr);
-                       cntr -= 16;
-               }
-
-               while (cntr > 0) {
-                       *data_buf++ = READ_NAND (nandptr);
-                       cntr--;
-               }
-       }
-}
-
-/*
- * NAND read with ECC
- */
-static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
-                size_t * retlen, u_char *buf, u_char *ecc_code)
-{
-       int col, page;
-       int ecc_status = 0;
-#ifdef CONFIG_MTD_NAND_ECC
-       int j;
-       int ecc_failed = 0;
-       u_char *data_poi;
-       u_char ecc_calc[6];
-#endif
-
-       /* Do not allow reads past end of device */
-       if ((start + len) > nand->totlen) {
-               printf ("%s: Attempt read beyond end of device %x %x %x\n",
-                       __FUNCTION__, (uint) start, (uint) len, (uint) nand->totlen);
-               *retlen = 0;
-               return -1;
-       }
-
-       /* First we calculate the starting page */
-       /*page = shr(start, nand->page_shift);*/
-       page = start >> nand->page_shift;
-
-       /* Get raw starting column */
-       col = start & (nand->oobblock - 1);
-
-       /* Initialize return value */
-       *retlen = 0;
-
-       /* Select the NAND device */
-       NAND_ENABLE_CE(nand);  /* set pin low */
-
-       /* Loop until all data read */
-       while (*retlen < len) {
-
-#ifdef CONFIG_MTD_NAND_ECC
-               /* Do we have this page in cache ? */
-               if (nand->cache_page == page)
-                       goto readdata;
-               /* Send the read command */
-               NanD_Command(nand, NAND_CMD_READ0);
-               if (nand->bus16) {
-                       NanD_Address(nand, ADDR_COLUMN_PAGE,
-                                    (page << nand->page_shift) + (col >> 1));
-               } else {
-                       NanD_Address(nand, ADDR_COLUMN_PAGE,
-                                    (page << nand->page_shift) + col);
-               }
-
-               /* Read in a page + oob data */
-               NanD_ReadBuf(nand, nand->data_buf, nand->oobblock + nand->oobsize);
-
-               /* copy data into cache, for read out of cache and if ecc fails */
-               if (nand->data_cache) {
-                       memcpy (nand->data_cache, nand->data_buf,
-                               nand->oobblock + nand->oobsize);
-               }
-
-               /* Pick the ECC bytes out of the oob data */
-               for (j = 0; j < 6; j++) {
-                       ecc_code[j] = nand->data_buf[(nand->oobblock + oob_config.ecc_pos[j])];
-               }
-
-               /* Calculate the ECC and verify it */
-               /* If block was not written with ECC, skip ECC */
-               if (oob_config.eccvalid_pos != -1 &&
-                   (nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] & 0x0f) != 0x0f) {
-
-                       nand_calculate_ecc (&nand->data_buf[0], &ecc_calc[0]);
-                       switch (nand_correct_data (&nand->data_buf[0], &ecc_code[0], &ecc_calc[0])) {
-                       case -1:
-                               printf ("%s: Failed ECC read, page 0x%08x\n", __FUNCTION__, page);
-                               ecc_failed++;
-                               break;
-                       case 1:
-                       case 2: /* transfer ECC corrected data to cache */
-                               if (nand->data_cache)
-                                       memcpy (nand->data_cache, nand->data_buf, 256);
-                               break;
-                       }
-               }
-
-               if (oob_config.eccvalid_pos != -1 &&
-                   nand->oobblock == 512 && (nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] & 0xf0) != 0xf0) {
-
-                       nand_calculate_ecc (&nand->data_buf[256], &ecc_calc[3]);
-                       switch (nand_correct_data (&nand->data_buf[256], &ecc_code[3], &ecc_calc[3])) {
-                       case -1:
-                               printf ("%s: Failed ECC read, page 0x%08x\n", __FUNCTION__, page);
-                               ecc_failed++;
-                               break;
-                       case 1:
-                       case 2: /* transfer ECC corrected data to cache */
-                               if (nand->data_cache)
-                                       memcpy (&nand->data_cache[256], &nand->data_buf[256], 256);
-                               break;
-                       }
-               }
-readdata:
-               /* Read the data from ECC data buffer into return buffer */
-               data_poi = (nand->data_cache) ? nand->data_cache : nand->data_buf;
-               data_poi += col;
-               if ((*retlen + (nand->oobblock - col)) >= len) {
-                       memcpy (buf + *retlen, data_poi, len - *retlen);
-                       *retlen = len;
-               } else {
-                       memcpy (buf + *retlen, data_poi,  nand->oobblock - col);
-                       *retlen += nand->oobblock - col;
-               }
-               /* Set cache page address, invalidate, if ecc_failed */
-               nand->cache_page = (nand->data_cache && !ecc_failed) ? page : -1;
-
-               ecc_status += ecc_failed;
-               ecc_failed = 0;
-
-#else
-               /* Send the read command */
-               NanD_Command(nand, NAND_CMD_READ0);
-               if (nand->bus16) {
-                       NanD_Address(nand, ADDR_COLUMN_PAGE,
-                                    (page << nand->page_shift) + (col >> 1));
-               } else {
-                       NanD_Address(nand, ADDR_COLUMN_PAGE,
-                                    (page << nand->page_shift) + col);
-               }
-
-               /* Read the data directly into the return buffer */
-               if ((*retlen + (nand->oobblock - col)) >= len) {
-                       NanD_ReadBuf(nand, buf + *retlen, len - *retlen);
-                       *retlen = len;
-                       /* We're done */
-                       continue;
-               } else {
-                       NanD_ReadBuf(nand, buf + *retlen, nand->oobblock - col);
-                       *retlen += nand->oobblock - col;
-                       }
-#endif
-               /* For subsequent reads align to page boundary. */
-               col = 0;
-               /* Increment page address */
-               page++;
-       }
-
-       /* De-select the NAND device */
-       NAND_DISABLE_CE(nand);  /* set pin high */
-
-       /*
-        * Return success, if no ECC failures, else -EIO
-        * fs driver will take care of that, because
-        * retlen == desired len and result == -EIO
-        */
-       return ecc_status ? -1 : 0;
-}
-
-/*
- *     Nand_page_program function is used for write and writev !
- */
-static int nand_write_page (struct nand_chip *nand,
-                           int page, int col, int last, u_char * ecc_code)
-{
-
-       int i;
-       unsigned long nandptr = nand->IO_ADDR;
-
-#ifdef CONFIG_MTD_NAND_ECC
-#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
-       int ecc_bytes = (nand->oobblock == 512) ? 6 : 3;
-#endif
-#endif
-       /* pad oob area */
-       for (i = nand->oobblock; i < nand->oobblock + nand->oobsize; i++)
-               nand->data_buf[i] = 0xff;
-
-#ifdef CONFIG_MTD_NAND_ECC
-       /* Zero out the ECC array */
-       for (i = 0; i < 6; i++)
-               ecc_code[i] = 0x00;
-
-       /* Read back previous written data, if col > 0 */
-       if (col) {
-               NanD_Command (nand, NAND_CMD_READ0);
-               if (nand->bus16) {
-                       NanD_Address (nand, ADDR_COLUMN_PAGE,
-                                     (page << nand->page_shift) + (col >> 1));
-               } else {
-                       NanD_Address (nand, ADDR_COLUMN_PAGE,
-                                     (page << nand->page_shift) + col);
-               }
-
-               if (nand->bus16) {
-                       u16 val;
-
-                       for (i = 0; i < col; i += 2) {
-                               val = READ_NAND (nandptr);
-                               nand->data_buf[i] = val & 0xff;
-                               nand->data_buf[i + 1] = val >> 8;
-                       }
-               } else {
-                       for (i = 0; i < col; i++)
-                               nand->data_buf[i] = READ_NAND (nandptr);
-               }
-       }
-
-       /* Calculate and write the ECC if we have enough data */
-       if ((col < nand->eccsize) && (last >= nand->eccsize)) {
-               nand_calculate_ecc (&nand->data_buf[0], &(ecc_code[0]));
-               for (i = 0; i < 3; i++) {
-                       nand->data_buf[(nand->oobblock +
-                                       oob_config.ecc_pos[i])] = ecc_code[i];
-               }
-               if (oob_config.eccvalid_pos != -1) {
-                       nand->data_buf[nand->oobblock +
-                                      oob_config.eccvalid_pos] = 0xf0;
-               }
-       }
-
-       /* Calculate and write the second ECC if we have enough data */
-       if ((nand->oobblock == 512) && (last == nand->oobblock)) {
-               nand_calculate_ecc (&nand->data_buf[256], &(ecc_code[3]));
-               for (i = 3; i < 6; i++) {
-                       nand->data_buf[(nand->oobblock +
-                                       oob_config.ecc_pos[i])] = ecc_code[i];
-               }
-               if (oob_config.eccvalid_pos != -1) {
-                       nand->data_buf[nand->oobblock +
-                                      oob_config.eccvalid_pos] &= 0x0f;
-               }
-       }
-#endif
-       /* Prepad for partial page programming !!! */
-       for (i = 0; i < col; i++)
-               nand->data_buf[i] = 0xff;
-
-       /* Postpad for partial page programming !!! oob is already padded */
-       for (i = last; i < nand->oobblock; i++)
-               nand->data_buf[i] = 0xff;
-
-       /* Send command to begin auto page programming */
-       NanD_Command (nand, NAND_CMD_READ0);
-       NanD_Command (nand, NAND_CMD_SEQIN);
-       if (nand->bus16) {
-               NanD_Address (nand, ADDR_COLUMN_PAGE,
-                             (page << nand->page_shift) + (col >> 1));
-       } else {
-               NanD_Address (nand, ADDR_COLUMN_PAGE,
-                             (page << nand->page_shift) + col);
-       }
-
-       /* Write out complete page of data */
-       if (nand->bus16) {
-               for (i = 0; i < (nand->oobblock + nand->oobsize); i += 2) {
-                       WRITE_NAND (nand->data_buf[i] +
-                                   (nand->data_buf[i + 1] << 8),
-                                   nand->IO_ADDR);
-               }
-       } else {
-               for (i = 0; i < (nand->oobblock + nand->oobsize); i++)
-                       WRITE_NAND (nand->data_buf[i], nand->IO_ADDR);
-       }
-
-       /* Send command to actually program the data */
-       NanD_Command (nand, NAND_CMD_PAGEPROG);
-       NanD_Command (nand, NAND_CMD_STATUS);
-#ifdef NAND_NO_RB
-       {
-               u_char ret_val;
-
-               do {
-                       ret_val = READ_NAND (nandptr);  /* wait till ready */
-               } while ((ret_val & 0x40) != 0x40);
-       }
-#endif
-       /* See if device thinks it succeeded */
-       if (READ_NAND (nand->IO_ADDR) & 0x01) {
-               printf ("%s: Failed write, page 0x%08x, ", __FUNCTION__,
-                       page);
-               return -1;
-       }
-#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
-       /*
-        * The NAND device assumes that it is always writing to
-        * a cleanly erased page. Hence, it performs its internal
-        * write verification only on bits that transitioned from
-        * 1 to 0. The device does NOT verify the whole page on a
-        * byte by byte basis. It is possible that the page was
-        * not completely erased or the page is becoming unusable
-        * due to wear. The read with ECC would catch the error
-        * later when the ECC page check fails, but we would rather
-        * catch it early in the page write stage. Better to write
-        * no data than invalid data.
-        */
-
-       /* Send command to read back the page */
-       if (col < nand->eccsize)
-               NanD_Command (nand, NAND_CMD_READ0);
-       else
-               NanD_Command (nand, NAND_CMD_READ1);
-       if (nand->bus16) {
-               NanD_Address (nand, ADDR_COLUMN_PAGE,
-                             (page << nand->page_shift) + (col >> 1));
-       } else {
-               NanD_Address (nand, ADDR_COLUMN_PAGE,
-                             (page << nand->page_shift) + col);
-       }
-
-       /* Loop through and verify the data */
-       if (nand->bus16) {
-               for (i = col; i < last; i = +2) {
-                       if ((nand->data_buf[i] +
-                            (nand->data_buf[i + 1] << 8)) != READ_NAND (nand->IO_ADDR)) {
-                               printf ("%s: Failed write verify, page 0x%08x ",
-                                       __FUNCTION__, page);
-                               return -1;
-                       }
-               }
-       } else {
-               for (i = col; i < last; i++) {
-                       if (nand->data_buf[i] != READ_NAND (nand->IO_ADDR)) {
-                               printf ("%s: Failed write verify, page 0x%08x ",
-                                       __FUNCTION__, page);
-                               return -1;
-                       }
-               }
-       }
-
-#ifdef CONFIG_MTD_NAND_ECC
-       /*
-        * We also want to check that the ECC bytes wrote
-        * correctly for the same reasons stated above.
-        */
-       NanD_Command (nand, NAND_CMD_READOOB);
-       if (nand->bus16) {
-               NanD_Address (nand, ADDR_COLUMN_PAGE,
-                             (page << nand->page_shift) + (col >> 1));
-       } else {
-               NanD_Address (nand, ADDR_COLUMN_PAGE,
-                             (page << nand->page_shift) + col);
-       }
-       if (nand->bus16) {
-               for (i = 0; i < nand->oobsize; i += 2) {
-                       u16 val;
-
-                       val = READ_NAND (nand->IO_ADDR);
-                       nand->data_buf[i] = val & 0xff;
-                       nand->data_buf[i + 1] = val >> 8;
-               }
-       } else {
-               for (i = 0; i < nand->oobsize; i++) {
-                       nand->data_buf[i] = READ_NAND (nand->IO_ADDR);
-               }
-       }
-       for (i = 0; i < ecc_bytes; i++) {
-               if ((nand->data_buf[(oob_config.ecc_pos[i])] != ecc_code[i]) && ecc_code[i]) {
-                       printf ("%s: Failed ECC write "
-                               "verify, page 0x%08x, "
-                               "%6i bytes were succesful\n",
-                               __FUNCTION__, page, i);
-                       return -1;
-               }
-       }
-#endif /* CONFIG_MTD_NAND_ECC */
-#endif /* CONFIG_MTD_NAND_VERIFY_WRITE */
-       return 0;
-}
-
-static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len,
-                          size_t * retlen, const u_char * buf, u_char * ecc_code)
-{
-       int i, page, col, cnt, ret = 0;
-
-       /* Do not allow write past end of device */
-       if ((to + len) > nand->totlen) {
-               printf ("%s: Attempt to write past end of page\n", __FUNCTION__);
-               return -1;
-       }
-
-       /* Shift to get page */
-       page = ((int) to) >> nand->page_shift;
-
-       /* Get the starting column */
-       col = to & (nand->oobblock - 1);
-
-       /* Initialize return length value */
-       *retlen = 0;
-
-       /* Select the NAND device */
-#ifdef CONFIG_OMAP1510
-       archflashwp(0,0);
-#endif
-#ifdef CFG_NAND_WP
-       NAND_WP_OFF();
-#endif
-
-       NAND_ENABLE_CE(nand);  /* set pin low */
-
-       /* Check the WP bit */
-       NanD_Command(nand, NAND_CMD_STATUS);
-       if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
-               printf ("%s: Device is write protected!!!\n", __FUNCTION__);
-               ret = -1;
-               goto out;
-       }
-
-       /* Loop until all data is written */
-       while (*retlen < len) {
-               /* Invalidate cache, if we write to this page */
-               if (nand->cache_page == page)
-                       nand->cache_page = -1;
-
-               /* Write data into buffer */
-               if ((col + len) >= nand->oobblock) {
-                       for (i = col, cnt = 0; i < nand->oobblock; i++, cnt++) {
-                               nand->data_buf[i] = buf[(*retlen + cnt)];
-                       }
-               } else {
-                       for (i = col, cnt = 0; cnt < (len - *retlen); i++, cnt++) {
-                               nand->data_buf[i] = buf[(*retlen + cnt)];
-                       }
-               }
-               /* We use the same function for write and writev !) */
-               ret = nand_write_page (nand, page, col, i, ecc_code);
-               if (ret)
-                       goto out;
-
-               /* Next data start at page boundary */
-               col = 0;
-
-               /* Update written bytes count */
-               *retlen += cnt;
-
-               /* Increment page address */
-               page++;
-       }
-
-       /* Return happy */
-       *retlen = len;
-
-out:
-       /* De-select the NAND device */
-       NAND_DISABLE_CE(nand);  /* set pin high */
-#ifdef CONFIG_OMAP1510
-       archflashwp(0,1);
-#endif
-#ifdef CFG_NAND_WP
-       NAND_WP_ON();
-#endif
-
-       return ret;
-}
-
-/* read from the 16 bytes of oob data that correspond to a 512 byte
- * page or 2 256-byte pages.
- */
-static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len,
-                        size_t * retlen, u_char * buf)
-{
-       int len256 = 0;
-       struct Nand *mychip;
-       int ret = 0;
-
-       mychip = &nand->chips[ofs >> nand->chipshift];
-
-       /* update address for 2M x 8bit devices. OOB starts on the second */
-       /* page to maintain compatibility with nand_read_ecc. */
-       if (nand->page256) {
-               if (!(ofs & 0x8))
-                       ofs += 0x100;
-               else
-                       ofs -= 0x8;
-       }
-
-       NAND_ENABLE_CE(nand);  /* set pin low */
-       NanD_Command(nand, NAND_CMD_READOOB);
-       if (nand->bus16) {
-               NanD_Address(nand, ADDR_COLUMN_PAGE,
-                            ((ofs >> nand->page_shift) << nand->page_shift) +
-                               ((ofs & (nand->oobblock - 1)) >> 1));
-       } else {
-               NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
-       }
-
-       /* treat crossing 8-byte OOB data for 2M x 8bit devices */
-       /* Note: datasheet says it should automaticaly wrap to the */
-       /*       next OOB block, but it didn't work here. mf.      */
-       if (nand->page256 && ofs + len > (ofs | 0x7) + 1) {
-               len256 = (ofs | 0x7) + 1 - ofs;
-               NanD_ReadBuf(nand, buf, len256);
-
-               NanD_Command(nand, NAND_CMD_READOOB);
-               NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff));
-       }
-
-       NanD_ReadBuf(nand, &buf[len256], len - len256);
-
-       *retlen = len;
-       /* Reading the full OOB data drops us off of the end of the page,
-        * causing the flash device to go into busy mode, so we need
-        * to wait until ready 11.4.1 and Toshiba TC58256FT nands */
-
-       ret = NanD_WaitReady(nand, 1);
-       NAND_DISABLE_CE(nand);  /* set pin high */
-
-       return ret;
-
-}
-
-/* write to the 16 bytes of oob data that correspond to a 512 byte
- * page or 2 256-byte pages.
- */
-static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
-                 size_t * retlen, const u_char * buf)
-{
-       int len256 = 0;
-       int i;
-       unsigned long nandptr = nand->IO_ADDR;
-
-#ifdef PSYCHO_DEBUG
-       printf("nand_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",
-              (long)ofs, len, buf[0], buf[1], buf[2], buf[3],
-              buf[8], buf[9], buf[14],buf[15]);
-#endif
-
-       NAND_ENABLE_CE(nand);  /* set pin low to enable chip */
-
-       /* Reset the chip */
-       NanD_Command(nand, NAND_CMD_RESET);
-
-       /* issue the Read2 command to set the pointer to the Spare Data Area. */
-       NanD_Command(nand, NAND_CMD_READOOB);
-       if (nand->bus16) {
-               NanD_Address(nand, ADDR_COLUMN_PAGE,
-                            ((ofs >> nand->page_shift) << nand->page_shift) +
-                               ((ofs & (nand->oobblock - 1)) >> 1));
-       } else {
-               NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
-       }
-
-       /* update address for 2M x 8bit devices. OOB starts on the second */
-       /* page to maintain compatibility with nand_read_ecc. */
-       if (nand->page256) {
-               if (!(ofs & 0x8))
-                       ofs += 0x100;
-               else
-                       ofs -= 0x8;
-       }
-
-       /* issue the Serial Data In command to initial the Page Program process */
-       NanD_Command(nand, NAND_CMD_SEQIN);
-       if (nand->bus16) {
-               NanD_Address(nand, ADDR_COLUMN_PAGE,
-                            ((ofs >> nand->page_shift) << nand->page_shift) +
-                               ((ofs & (nand->oobblock - 1)) >> 1));
-       } else {
-               NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
-       }
-
-       /* treat crossing 8-byte OOB data for 2M x 8bit devices */
-       /* Note: datasheet says it should automaticaly wrap to the */
-       /*       next OOB block, but it didn't work here. mf.      */
-       if (nand->page256 && ofs + len > (ofs | 0x7) + 1) {
-               len256 = (ofs | 0x7) + 1 - ofs;
-               for (i = 0; i < len256; i++)
-                       WRITE_NAND(buf[i], nandptr);
-
-               NanD_Command(nand, NAND_CMD_PAGEPROG);
-               NanD_Command(nand, NAND_CMD_STATUS);
-#ifdef NAND_NO_RB
-               { u_char ret_val;
-                       do {
-                               ret_val = READ_NAND(nandptr); /* wait till ready */
-                       } while ((ret_val & 0x40) != 0x40);
-               }
-#endif
-               if (READ_NAND(nandptr) & 1) {
-                       puts ("Error programming oob data\n");
-                       /* There was an error */
-                       NAND_DISABLE_CE(nand);  /* set pin high */
-                       *retlen = 0;
-                       return -1;
-               }
-               NanD_Command(nand, NAND_CMD_SEQIN);
-               NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff));
-       }
-
-       if (nand->bus16) {
-               for (i = len256; i < len; i += 2) {
-                       WRITE_NAND(buf[i] + (buf[i+1] << 8), nandptr);
-               }
-       } else {
-               for (i = len256; i < len; i++)
-                       WRITE_NAND(buf[i], nandptr);
-       }
-
-       NanD_Command(nand, NAND_CMD_PAGEPROG);
-       NanD_Command(nand, NAND_CMD_STATUS);
-#ifdef NAND_NO_RB
-       {       u_char ret_val;
-               do {
-                       ret_val = READ_NAND(nandptr); /* wait till ready */
-               } while ((ret_val & 0x40) != 0x40);
-       }
-#endif
-       if (READ_NAND(nandptr) & 1) {
-               puts ("Error programming oob data\n");
-               /* There was an error */
-               NAND_DISABLE_CE(nand);  /* set pin high */
-               *retlen = 0;
-               return -1;
-       }
-
-       NAND_DISABLE_CE(nand);  /* set pin high */
-       *retlen = len;
-       return 0;
-
-}
-
-int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean)
-{
-       /* This is defined as a structure so it will work on any system
-        * using native endian jffs2 (the default).
-        */
-       static struct jffs2_unknown_node clean_marker = {
-               JFFS2_MAGIC_BITMASK,
-               JFFS2_NODETYPE_CLEANMARKER,
-               8               /* 8 bytes in this node */
-       };
-       unsigned long nandptr;
-       struct Nand *mychip;
-       int ret = 0;
-
-       if (ofs & (nand->erasesize-1) || len & (nand->erasesize-1)) {
-               printf ("Offset and size must be sector aligned, erasesize = %d\n",
-                       (int) nand->erasesize);
-               return -1;
-       }
-
-       nandptr = nand->IO_ADDR;
-
-       /* Select the NAND device */
-#ifdef CONFIG_OMAP1510
-       archflashwp(0,0);
-#endif
-#ifdef CFG_NAND_WP
-       NAND_WP_OFF();
-#endif
-    NAND_ENABLE_CE(nand);  /* set pin low */
-
-       /* Check the WP bit */
-       NanD_Command(nand, NAND_CMD_STATUS);
-       if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
-               printf ("nand_write_ecc: Device is write protected!!!\n");
-               ret = -1;
-               goto out;
-       }
-
-       /* Check the WP bit */
-       NanD_Command(nand, NAND_CMD_STATUS);
-       if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
-               printf ("%s: Device is write protected!!!\n", __FUNCTION__);
-               ret = -1;
-               goto out;
-       }
-
-       /* FIXME: Do nand in the background. Use timers or schedule_task() */
-       while(len) {
-               /*mychip = &nand->chips[shr(ofs, nand->chipshift)];*/
-               mychip = &nand->chips[ofs >> nand->chipshift];
-
-               /* always check for bad block first, genuine bad blocks
-                * should _never_  be erased.
-                */
-               if (ALLOW_ERASE_BAD_DEBUG || !check_block(nand, ofs)) {
-                       /* Select the NAND device */
-                       NAND_ENABLE_CE(nand);  /* set pin low */
-
-                       NanD_Command(nand, NAND_CMD_ERASE1);
-                       NanD_Address(nand, ADDR_PAGE, ofs);
-                       NanD_Command(nand, NAND_CMD_ERASE2);
-
-                       NanD_Command(nand, NAND_CMD_STATUS);
-
-#ifdef NAND_NO_RB
-                       {       u_char ret_val;
-                               do {
-                                       ret_val = READ_NAND(nandptr); /* wait till ready */
-                               } while ((ret_val & 0x40) != 0x40);
-                       }
-#endif
-                       if (READ_NAND(nandptr) & 1) {
-                               printf ("%s: Error erasing at 0x%lx\n",
-                                       __FUNCTION__, (long)ofs);
-                               /* There was an error */
-                               ret = -1;
-                               goto out;
-                       }
-                       if (clean) {
-                               int n;  /* return value not used */
-                               int p, l;
-
-                               /* clean marker position and size depend
-                                * on the page size, since 256 byte pages
-                                * only have 8 bytes of oob data
-                                */
-                               if (nand->page256) {
-                                       p = NAND_JFFS2_OOB8_FSDAPOS;
-                                       l = NAND_JFFS2_OOB8_FSDALEN;
-                               } else {
-                                       p = NAND_JFFS2_OOB16_FSDAPOS;
-                                       l = NAND_JFFS2_OOB16_FSDALEN;
-                               }
-
-                               ret = nand_write_oob(nand, ofs + p, l, (size_t *)&n,
-                                                    (u_char *)&clean_marker);
-                               /* quit here if write failed */
-                               if (ret)
-                                       goto out;
-                       }
-               }
-               ofs += nand->erasesize;
-               len -= nand->erasesize;
-       }
-
-out:
-       /* De-select the NAND device */
-       NAND_DISABLE_CE(nand);  /* set pin high */
-#ifdef CONFIG_OMAP1510
-       archflashwp(0,1);
-#endif
-#ifdef CFG_NAND_WP
-       NAND_WP_ON();
-#endif
-
-       return ret;
-}
-
-static inline int nandcheck(unsigned long potential, unsigned long physadr)
-{
-       return 0;
-}
-
-unsigned long nand_probe(unsigned long physadr)
-{
-       struct nand_chip *nand = NULL;
-       int i = 0, ChipID = 1;
-
-#ifdef CONFIG_MTD_NAND_ECC_JFFS2
-       oob_config.ecc_pos[0] = NAND_JFFS2_OOB_ECCPOS0;
-       oob_config.ecc_pos[1] = NAND_JFFS2_OOB_ECCPOS1;
-       oob_config.ecc_pos[2] = NAND_JFFS2_OOB_ECCPOS2;
-       oob_config.ecc_pos[3] = NAND_JFFS2_OOB_ECCPOS3;
-       oob_config.ecc_pos[4] = NAND_JFFS2_OOB_ECCPOS4;
-       oob_config.ecc_pos[5] = NAND_JFFS2_OOB_ECCPOS5;
-       oob_config.eccvalid_pos = 4;
-#else
-       oob_config.ecc_pos[0] = NAND_NOOB_ECCPOS0;
-       oob_config.ecc_pos[1] = NAND_NOOB_ECCPOS1;
-       oob_config.ecc_pos[2] = NAND_NOOB_ECCPOS2;
-       oob_config.ecc_pos[3] = NAND_NOOB_ECCPOS3;
-       oob_config.ecc_pos[4] = NAND_NOOB_ECCPOS4;
-       oob_config.ecc_pos[5] = NAND_NOOB_ECCPOS5;
-       oob_config.eccvalid_pos = NAND_NOOB_ECCVPOS;
-#endif
-       oob_config.badblock_pos = 5;
-
-       for (i=0; i<CFG_MAX_NAND_DEVICE; i++) {
-               if (nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN) {
-                       nand = &nand_dev_desc[i];
-                       break;
-               }
-       }
-       if (!nand)
-               return (0);
-
-       memset((char *)nand, 0, sizeof(struct nand_chip));
-
-       nand->IO_ADDR = physadr;
-       nand->cache_page = -1;  /* init the cache page */
-       NanD_ScanChips(nand);
-
-       if (nand->totlen == 0) {
-               /* no chips found, clean up and quit */
-               memset((char *)nand, 0, sizeof(struct nand_chip));
-               nand->ChipID = NAND_ChipID_UNKNOWN;
-               return (0);
-       }
-
-       nand->ChipID = ChipID;
-       if (curr_device == -1)
-               curr_device = i;
-
-       nand->data_buf = malloc (nand->oobblock + nand->oobsize);
-       if (!nand->data_buf) {
-               puts ("Cannot allocate memory for data structures.\n");
-               return (0);
-       }
-
-       return (nand->totlen);
-}
-
-#ifdef CONFIG_MTD_NAND_ECC
-/*
- * Pre-calculated 256-way 1 byte column parity
- */
-static const u_char nand_ecc_precalc_table[] = {
-       0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
-       0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
-       0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
-       0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
-       0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
-       0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
-       0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
-       0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
-       0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
-       0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
-       0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
-       0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
-       0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
-       0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
-       0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
-       0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
-       0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
-       0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
-       0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
-       0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
-       0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
-       0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
-       0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
-       0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
-       0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
-       0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
-       0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
-       0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
-       0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
-       0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
-       0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
-       0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
-};
-
-
-/*
- * Creates non-inverted ECC code from line parity
- */
-static void nand_trans_result(u_char reg2, u_char reg3,
-       u_char *ecc_code)
-{
-       u_char a, b, i, tmp1, tmp2;
-
-       /* Initialize variables */
-       a = b = 0x80;
-       tmp1 = tmp2 = 0;
-
-       /* Calculate first ECC byte */
-       for (i = 0; i < 4; i++) {
-               if (reg3 & a)           /* LP15,13,11,9 --> ecc_code[0] */
-                       tmp1 |= b;
-               b >>= 1;
-               if (reg2 & a)           /* LP14,12,10,8 --> ecc_code[0] */
-                       tmp1 |= b;
-               b >>= 1;
-               a >>= 1;
-       }
-
-       /* Calculate second ECC byte */
-       b = 0x80;
-       for (i = 0; i < 4; i++) {
-               if (reg3 & a)           /* LP7,5,3,1 --> ecc_code[1] */
-                       tmp2 |= b;
-               b >>= 1;
-               if (reg2 & a)           /* LP6,4,2,0 --> ecc_code[1] */
-                       tmp2 |= b;
-               b >>= 1;
-               a >>= 1;
-       }
-
-       /* Store two of the ECC bytes */
-       ecc_code[0] = tmp1;
-       ecc_code[1] = tmp2;
-}
-
-/*
- * Calculate 3 byte ECC code for 256 byte block
- */
-static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code)
-{
-       u_char idx, reg1, reg3;
-       int j;
-
-       /* Initialize variables */
-       reg1 = reg3 = 0;
-       ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
-
-       /* Build up column parity */
-       for(j = 0; j < 256; j++) {
-
-               /* Get CP0 - CP5 from table */
-               idx = nand_ecc_precalc_table[dat[j]];
-               reg1 ^= idx;
-
-               /* All bit XOR = 1 ? */
-               if (idx & 0x40) {
-                       reg3 ^= (u_char) j;
-               }
-       }
-
-       /* Create non-inverted ECC code from line parity */
-       nand_trans_result((reg1 & 0x40) ? ~reg3 : reg3, reg3, ecc_code);
-
-       /* Calculate final ECC code */
-       ecc_code[0] = ~ecc_code[0];
-       ecc_code[1] = ~ecc_code[1];
-       ecc_code[2] = ((~reg1) << 2) | 0x03;
-}
-
-/*
- * Detect and correct a 1 bit error for 256 byte block
- */
-static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc)
-{
-       u_char a, b, c, d1, d2, d3, add, bit, i;
-
-       /* Do error detection */
-       d1 = calc_ecc[0] ^ read_ecc[0];
-       d2 = calc_ecc[1] ^ read_ecc[1];
-       d3 = calc_ecc[2] ^ read_ecc[2];
-
-       if ((d1 | d2 | d3) == 0) {
-               /* No errors */
-               return 0;
-       } else {
-               a = (d1 ^ (d1 >> 1)) & 0x55;
-               b = (d2 ^ (d2 >> 1)) & 0x55;
-               c = (d3 ^ (d3 >> 1)) & 0x54;
-
-               /* Found and will correct single bit error in the data */
-               if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {
-                       c = 0x80;
-                       add = 0;
-                       a = 0x80;
-                       for (i=0; i<4; i++) {
-                               if (d1 & c)
-                                       add |= a;
-                               c >>= 2;
-                               a >>= 1;
-                       }
-                       c = 0x80;
-                       for (i=0; i<4; i++) {
-                               if (d2 & c)
-                                       add |= a;
-                               c >>= 2;
-                               a >>= 1;
-                       }
-                       bit = 0;
-                       b = 0x04;
-                       c = 0x80;
-                       for (i=0; i<3; i++) {
-                               if (d3 & c)
-                                       bit |= b;
-                               c >>= 2;
-                               b >>= 1;
-                       }
-                       b = 0x01;
-                       a = dat[add];
-                       a ^= (b << bit);
-                       dat[add] = a;
-                       return 1;
-               }
-               else {
-                       i = 0;
-                       while (d1) {
-                               if (d1 & 0x01)
-                                       ++i;
-                               d1 >>= 1;
-                       }
-                       while (d2) {
-                               if (d2 & 0x01)
-                                       ++i;
-                               d2 >>= 1;
-                       }
-                       while (d3) {
-                               if (d3 & 0x01)
-                                       ++i;
-                               d3 >>= 1;
-                       }
-                       if (i == 1) {
-                               /* ECC Code Error Correction */
-                               read_ecc[0] = calc_ecc[0];
-                               read_ecc[1] = calc_ecc[1];
-                               read_ecc[2] = calc_ecc[2];
-                               return 2;
-                       }
-                       else {
-                               /* Uncorrectable Error */
-                               return -1;
-                       }
-               }
-       }
-
-       /* Should never happen */
-       return -1;
-}
-
-#endif
-
-#ifdef CONFIG_JFFS2_NAND
-
-int read_jffs2_nand(size_t start, size_t len,
-                   size_t * retlen, u_char * buf, int nanddev)
-{
-       return nand_rw(nand_dev_desc + nanddev, NANDRW_READ | NANDRW_JFFS2,
-                      start, len, retlen, buf);
-}
-
-#endif /* CONFIG_JFFS2_NAND */
-
-
-#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
+#endif /* CFG_NAND_LEGACY */
diff --git a/common/cmd_nand_new.c b/common/cmd_nand_new.c
deleted file mode 100644 (file)
index 3ff2eba..0000000
+++ /dev/null
@@ -1,364 +0,0 @@
-#include <common.h>
-
-#if (CONFIG_COMMANDS & CFG_CMD_NAND) && defined CONFIG_NEW_NAND_CODE
-
-#include <command.h>
-#include <watchdog.h>
-#include <malloc.h>
-#include <asm/byteorder.h>
-
-#ifdef CONFIG_SHOW_BOOT_PROGRESS
-# include <status_led.h>
-# define SHOW_BOOT_PROGRESS(arg)       show_boot_progress(arg)
-#else
-# define SHOW_BOOT_PROGRESS(arg)
-#endif
-
-#include <jffs2/jffs2.h>
-#include <nand.h>
-
-extern nand_info_t nand_info[];       /* info for NAND chips */
-
-static int nand_dump_oob(nand_info_t *nand, ulong off)
-{
-       return 0;
-}
-
-static int nand_dump(nand_info_t *nand, ulong off)
-{
-       int i;
-       u_char *buf, *p;
-
-       buf = malloc(nand->oobblock + nand->oobsize);
-       if (!buf) {
-               puts("No memory for page buffer\n");
-               return 1;
-       }
-       off &= ~(nand->oobblock - 1);
-       i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);
-       if (i < 0) {
-               printf("Error (%d) reading page %08x\n", i, off);
-               free(buf);
-               return 1;
-       }
-       printf("Page %08x dump:\n", off);
-       i = nand->oobblock >> 4; p = buf;
-       while (i--) {
-               printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"
-                       "  %02x %02x %02x %02x %02x %02x %02x %02x\n",
-                       p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
-                       p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
-               p += 16;
-       }
-       puts("OOB:\n");
-       i = nand->oobsize >> 3;
-       while (i--) {
-               printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
-                       p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
-               p += 8;
-       }
-       free(buf);
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static void
-arg_off_size(int argc, char *argv[], ulong *off, ulong *size, ulong totsize)
-{
-       *off = 0;
-       *size = 0;
-
-#if defined(CONFIG_JFFS2_NAND) && defined(CFG_JFFS_CUSTOM_PART)
-       if (argc >= 1 && strcmp(argv[0], "partition") == 0) {
-               int part_num;
-               struct part_info *part;
-               const char *partstr;
-
-               if (argc >= 2)
-                       partstr = argv[1];
-               else
-                       partstr = getenv("partition");
-
-               if (partstr)
-                       part_num = (int)simple_strtoul(partstr, NULL, 10);
-               else
-                       part_num = 0;
-
-               part = jffs2_part_info(part_num);
-               if (part == NULL) {
-                       printf("\nInvalid partition %d\n", part_num);
-                       return;
-               }
-               *size = part->size;
-               *off = (ulong)part->offset;
-       } else
-#endif
-       {
-               if (argc >= 1)
-                       *off = (ulong)simple_strtoul(argv[0], NULL, 16);
-               else
-                       *off = 0;
-
-               if (argc >= 2)
-                       *size = (ulong)simple_strtoul(argv[1], NULL, 16);
-               else
-                       *size = totsize - *off;
-
-       }
-
-}
-
-int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
-{
-       int i, dev, ret;
-       ulong addr, off, size;
-       char *cmd, *s;
-       nand_info_t *nand;
-
-       /* at least two arguments please */
-       if (argc < 2)
-               goto usage;
-
-       cmd = argv[1];
-
-       if (strcmp(cmd, "info") == 0) {
-
-               putc('\n');
-               for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
-                       if (nand_info[i].name)
-                               printf("Device %d: %s\n", i, nand_info[i].name);
-               }
-               return 0;
-       }
-
-       if (strcmp(cmd, "device") == 0) {
-
-               if (argc < 3) {
-                       if ((nand_curr_device < 0) ||
-                           (nand_curr_device >= CFG_MAX_NAND_DEVICE))
-                               puts("\nno devices available\n");
-                       else
-                               printf("\nDevice %d: %s\n", nand_curr_device,
-                                       nand_info[nand_curr_device].name);
-                       return 0;
-               }
-               dev = (int)simple_strtoul(argv[2], NULL, 10);
-               if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
-                       puts("No such device\n");
-                       return 1;
-               }
-               printf("Device %d: %s", dev, nand_info[dev].name);
-               puts("... is now current device\n");
-               nand_curr_device = dev;
-               return 0;
-       }
-
-       if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
-           strncmp(cmd, "dump", 4) != 0 &&
-           strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0)
-               goto usage;
-
-       /* the following commands operate on the current device */
-       if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||
-           !nand_info[nand_curr_device].name) {
-               puts("\nno devices available\n");
-               return 1;
-       }
-       nand = &nand_info[nand_curr_device];
-
-       if (strcmp(cmd, "bad") == 0) {
-               printf("\nDevice %d bad blocks:\n", nand_curr_device);
-               for (off = 0; off < nand->size; off += nand->erasesize)
-                       if (nand_block_isbad(nand, off))
-                               printf("  %08x\n", off);
-               return 0;
-       }
-
-       if (strcmp(cmd, "erase") == 0) {
-               arg_off_size(argc - 2, argv + 2, &off, &size, nand->size);
-               if (off == 0 && size == 0)
-                       return 1;
-
-               printf("\nNAND erase: device %d offset 0x%x, size 0x%x ",
-                      nand_curr_device, off, size);
-               ret = nand_erase(nand, off, size);
-               printf("%s\n", ret ? "ERROR" : "OK");
-
-               return ret == 0 ? 0 : 1;
-       }
-
-       if (strncmp(cmd, "dump", 4) == 0) {
-               if (argc < 3)
-                       goto usage;
-
-               s = strchr(cmd, '.');
-               off = (int)simple_strtoul(argv[2], NULL, 16);
-
-               if (s != NULL && strcmp(s, ".oob") == 0)
-                       ret = nand_dump_oob(nand, off);
-               else
-                       ret = nand_dump(nand, off);
-
-               return ret == 0 ? 1 : 0;
-
-       }
-
-       /* read write */
-       if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
-               if (argc < 4)
-                       goto usage;
-/*
-               s = strchr(cmd, '.');
-               clean = CLEAN_NONE;
-               if (s != NULL) {
-                       if (strcmp(s, ".jffs2") == 0 || strcmp(s, ".e") == 0
-                           || strcmp(s, ".i"))
-                               clean = CLEAN_JFFS2;
-               }
-*/
-               addr = (ulong)simple_strtoul(argv[2], NULL, 16);
-
-               arg_off_size(argc - 3, argv + 3, &off, &size, nand->size);
-               if (off == 0 && size == 0)
-                       return 1;
-
-               i = strncmp(cmd, "read", 4) == 0;       /* 1 = read, 0 = write */
-               printf("\nNAND %s: device %d offset %u, size %u ... ",
-                      i ? "read" : "write", nand_curr_device, off, size);
-
-               if (i)
-                       ret = nand_read(nand, off, &size, (u_char *)addr);
-               else
-                       ret = nand_write(nand, off, &size, (u_char *)addr);
-
-               printf(" %d bytes %s: %s\n", size,
-                      i ? "read" : "written", ret ? "ERROR" : "OK");
-
-               return ret == 0 ? 0 : 1;
-       }
-usage:
-       printf("Usage:\n%s\n", cmdtp->usage);
-       return 1;
-}
-
-U_BOOT_CMD(nand, 5, 1, do_nand,
-       "nand    - NAND sub-system\n",
-       "info                  - show available NAND devices\n"
-       "nand device [dev]     - show or set current device\n"
-       "nand read[.jffs2]     - addr off size\n"
-       "nand write[.jffs2]    - addr off size - read/write `size' bytes starting\n"
-       "    at offset `off' to/from memory address `addr'\n"
-       "nand erase [clean] [off size] - erase `size' bytes from\n"
-       "    offset `off' (entire device if not specified)\n"
-       "nand bad - show bad blocks\n"
-       "nand dump[.oob] off - dump page\n"
-       "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
-       "nand markbad off - mark bad block at offset (UNSAFE)\n"
-       "nand biterr off - make a bit error at offset (UNSAFE)\n");
-
-int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
-{
-       char *boot_device = NULL;
-       char *ep;
-       int dev;
-       int r;
-       ulong addr, cnt, offset = 0;
-       image_header_t *hdr;
-       nand_info_t *nand;
-
-       switch (argc) {
-       case 1:
-               addr = CFG_LOAD_ADDR;
-               boot_device = getenv("bootdevice");
-               break;
-       case 2:
-               addr = simple_strtoul(argv[1], NULL, 16);
-               boot_device = getenv("bootdevice");
-               break;
-       case 3:
-               addr = simple_strtoul(argv[1], NULL, 16);
-               boot_device = argv[2];
-               break;
-       case 4:
-               addr = simple_strtoul(argv[1], NULL, 16);
-               boot_device = argv[2];
-               offset = simple_strtoul(argv[3], NULL, 16);
-               break;
-       default:
-               printf("Usage:\n%s\n", cmdtp->usage);
-               SHOW_BOOT_PROGRESS(-1);
-               return 1;
-       }
-
-       if (!boot_device) {
-               puts("\n** No boot device **\n");
-               SHOW_BOOT_PROGRESS(-1);
-               return 1;
-       }
-
-       dev = simple_strtoul(boot_device, &ep, 16);
-
-       if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
-               printf("\n** Device %d not available\n", dev);
-               SHOW_BOOT_PROGRESS(-1);
-               return 1;
-       }
-
-       nand = &nand_info[dev];
-       printf("\nLoading from device %d: %s (offset 0x%lx)\n",
-              dev, nand->name, offset);
-
-       cnt = nand->oobblock;
-       r = nand_read(nand, offset, &cnt, (u_char *) addr);
-       if (r) {
-               printf("** Read error on %d\n", dev);
-               SHOW_BOOT_PROGRESS(-1);
-               return 1;
-       }
-
-       hdr = (image_header_t *) addr;
-
-       if (ntohl(hdr->ih_magic) != IH_MAGIC) {
-               printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
-               SHOW_BOOT_PROGRESS(-1);
-               return 1;
-       }
-
-       print_image_hdr(hdr);
-
-       cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t));
-
-       r = nand_read(nand, offset, &cnt, (u_char *) addr);
-       if (r) {
-               printf("** Read error on %d\n", dev);
-               SHOW_BOOT_PROGRESS(-1);
-               return 1;
-       }
-
-       /* Loading ok, update default load address */
-
-       load_addr = addr;
-
-       /* Check if we should attempt an auto-start */
-       if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
-               char *local_args[2];
-               extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
-
-               local_args[0] = argv[0];
-               local_args[1] = NULL;
-
-               printf("Automatic boot of image at addr 0x%08lx ...\n", addr);
-
-               do_bootm(cmdtp, 0, 1, local_args);
-               return 1;
-       }
-       return 0;
-}
-
-U_BOOT_CMD(nboot, 4, 1, do_nandboot,
-       "nboot   - boot from NAND device\n", "loadAddr dev\n");
-
-
-#endif                         /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
index 60aba1e7e667ee8137b2ce61611c2e038fd92c8e..4896853530194ca0292ea83bf2bf139297b51275 100644 (file)
@@ -36,7 +36,7 @@
 #include <command.h>
 #include <environment.h>
 #include <linux/stddef.h>
-#include <linux/mtd/nand.h>
+#include <nand.h>
 
 #if ((CONFIG_COMMANDS&(CFG_CMD_ENV|CFG_CMD_NAND)) == (CFG_CMD_ENV|CFG_CMD_NAND))
 #define CMD_SAVEENV
 #error CONFIG_INFERNO not supported yet
 #endif
 
-/* references to names in cmd_nand.c */
-#define NANDRW_READ            0x01
-#define NANDRW_WRITE   0x00
-#define NANDRW_JFFS2   0x02
-extern struct nand_chip nand_dev_desc[];
-int nand_rw (struct nand_chip* nand, int cmd,
+int nand_legacy_rw (struct nand_chip* nand, int cmd,
            size_t start, size_t len,
            size_t * retlen, u_char * buf);
-int nand_erase(struct nand_chip* nand, size_t ofs,
-                               size_t len, int clean);
+
+/* info for NAND chips, defined in drivers/nand/nand.c */
+extern nand_info_t nand_info[];
 
 /* references to names in env_common.c */
 extern uchar default_environment[];
@@ -110,34 +106,43 @@ int env_init(void)
 }
 
 #ifdef CMD_SAVEENV
+/*
+ * The legacy NAND code saved the environment in the first NAND device i.e.,
+ * nand_dev_desc + 0. This is also the behaviour using the new NAND code.
+ */
 int saveenv(void)
 {
        int     total, ret = 0;
-       puts ("Erasing Nand...");
-       if (nand_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SIZE, 0))
-               return 1;
+
+       puts ("Erasing Nand...");
+       if (nand_erase(&nand_info[0], CFG_NEW_OFFSET, CFG_ENV_SIZE))
+               return 1;
 
        puts ("Writing to Nand... ");
-       ret = nand_rw(nand_dev_desc + 0,
-                                 NANDRW_WRITE | NANDRW_JFFS2, CFG_ENV_OFFSET, CFG_ENV_SIZE,
-                             &total, (u_char*)env_ptr);
-       if (ret || total != CFG_ENV_SIZE)
+       total = CFG_ENV_SIZE;
+       ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total,
+                       (u_char*) env_ptr);
+       if (ret || total != CFG_ENV_SIZE)
                return 1;
 
-       puts ("done\n");
-       return ret;
+       puts ("done\n");
+       return ret;
 }
 #endif /* CMD_SAVEENV */
 
 
+/*
+ * The legacy NAND code saved the environment in the first NAND device i.e.,
+ * nand_dev_desc + 0. This is also the behaviour using the new NAND code.
+ */
 void env_relocate_spec (void)
 {
 #if !defined(ENV_IS_EMBEDDED)
        int ret, total;
 
-       ret = nand_rw(nand_dev_desc + 0,
-                                 NANDRW_READ | NANDRW_JFFS2, CFG_ENV_OFFSET, CFG_ENV_SIZE,
-                             &total, (u_char*)env_ptr);
+       total = CFG_ENV_SIZE;
+       ret = nand_read(&nand_info[0], CFG_ENV_OFFSET, &total,
+                       (u_char*) env_ptr);
        if (ret || total != CFG_ENV_SIZE)
                return use_default();
 
index 07e2549352c72e61fa8ed760692eeea585938903..afaae834f1c106297f673ba064178561b2214342 100644 (file)
  */
 
 #include <common.h>
-#ifdef CONFIG_NEW_NAND_CODE
+
+#ifdef CFG_NAND_LEGACY
+#error CFG_NAND_LEGACY defined in a file not using the legacy NAND support!
+#endif
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sched.h>
@@ -1782,4 +1786,3 @@ module_exit(cleanup_nanddoc);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
 MODULE_DESCRIPTION("M-Systems DiskOnChip 2000, Millennium and Millennium Plus device driver\n");
-#endif /* CONFIG_NEW_NAND_CODE */
index bc85005b2af28429898691143ca2a13ee4e2da0b..dd80026fe02ec63850248bd0a8ac8bfa18a0c578 100644 (file)
 
 #include <common.h>
 
-#ifdef CONFIG_NEW_NAND_CODE
+#ifdef CFG_NAND_LEGACY
+#error CFG_NAND_LEGACY defined in a file not using the legacy NAND support!
+#endif
+
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
 
 #include <nand.h>
@@ -72,5 +75,3 @@ void nand_init(void)
 }
 
 #endif
-#endif /* CONFIG_NEW_NAND_CODE */
-
index b039c3cd8c1b4ac1c8bdb2535c56b9963f3183dd..b2cd62e37e8d0ba961b6cdc73a5a31fef6c6c17a 100644 (file)
 #endif
 
 #include <common.h>
-#ifdef CONFIG_NEW_NAND_CODE
+
+#ifdef CFG_NAND_LEGACY
+#error CFG_NAND_LEGACY defined in a file not using the legacy NAND support!
+#endif
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
 
@@ -864,10 +867,10 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
                                break;
                }
        }
-
-       /* XXX nand device 1 on dave (PPChameleonEVB) needs more time */
+#ifdef PPCHAMELON_NAND_TIMER_HACK
        reset_timer();
        while (get_timer(0) < 10);
+#endif /*  PPCHAMELON_NAND_TIMER_HACK */
 
        return this->read_byte(mtd);
 }
@@ -2660,5 +2663,3 @@ void nand_release (struct mtd_info *mtd)
 }
 
 #endif
-#endif /* CONFIG_NEW_NAND_CODE */
-
index f4813088b5e3ed45a61ee3571458704f30f0cb6c..ac168723e22c2cd532059c9bc5ee586ea3ace4bd 100644 (file)
 
 #include <common.h>
 
-#ifdef CONFIG_NEW_NAND_CODE
+#ifdef CFG_NAND_LEGACY
+#error CFG_NAND_LEGACY defined in a file not using the legacy NAND support!
+#endif
+
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
 
 #include <malloc.h>
@@ -1051,5 +1054,3 @@ int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)
 }
 
 #endif
-#endif /* CONFIG_NEW_NAND_CODE */
-
index 4e610c1123e5f5b458805c15a7d230699b5645c9..e0d0e8bcc40705b6a42d47c3526fc5441a16fd1c 100644 (file)
 
 #include <common.h>
 
-#ifdef CONFIG_NEW_NAND_CODE
+#ifdef CFG_NAND_LEGACY
+#error CFG_NAND_LEGACY defined in a file not using the legacy NAND support!
+#endif
+
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
 
 #include<linux/mtd/mtd.h>
@@ -243,5 +246,3 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha
 }
 
 #endif /* CONFIG_COMMANDS & CFG_CMD_NAND */
-#endif /* CONFIG_NEW_NAND_CODE */
-
index d3553261073759edd943f6cc30f96f6ef6e62768..3d4d372f17f1855f604a87a8eba3973d579c5606 100644 (file)
 
 #include <common.h>
 
-#ifdef CONFIG_NEW_NAND_CODE
+#ifdef CFG_NAND_LEGACY
+#error CFG_NAND_LEGACY defined in a file not using the legacy NAND support!
+#endif
+
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
 
 #include <linux/mtd/nand.h>
@@ -127,5 +130,3 @@ struct nand_manufacturers nand_manuf_ids[] = {
        {0x0, "Unknown"}
 };
 #endif
-#endif /* CONFIG_NEW_NAND_CODE */
-
diff --git a/drivers/nand_legacy/Makefile b/drivers/nand_legacy/Makefile
new file mode 100644 (file)
index 0000000..7e2cf66
--- /dev/null
@@ -0,0 +1,16 @@
+include $(TOPDIR)/config.mk
+
+LIB := libnand_legacy.a
+
+OBJS := nand_legacy.o
+all:   $(LIB)
+
+$(LIB):        $(OBJS)
+       $(AR) crv $@ $(OBJS)
+
+#########################################################################
+
+.depend:       Makefile $(OBJS:.o=.c)
+               $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@
+
+sinclude .depend
diff --git a/drivers/nand_legacy/nand_legacy.c b/drivers/nand_legacy/nand_legacy.c
new file mode 100644 (file)
index 0000000..3989ca2
--- /dev/null
@@ -0,0 +1,1615 @@
+/*
+ * (C) 2006 Denx
+ * Driver for NAND support, Rick Bronson
+ * borrowed heavily from:
+ * (c) 1999 Machine Vision Holdings, Inc.
+ * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
+ *
+ * Added 16-bit nand support
+ * (C) 2004 Texas Instruments
+ */
+
+#include <common.h>
+
+#ifndef CFG_NAND_LEGACY
+#error CFG_NAND_LEGACY not defined in a file using the legacy NAND support!
+#endif
+
+#include <command.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <watchdog.h>
+
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+# include <status_led.h>
+# define SHOW_BOOT_PROGRESS(arg)       show_boot_progress(arg)
+#else
+# define SHOW_BOOT_PROGRESS(arg)
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_NAND)
+
+#include <linux/mtd/nand_legacy.h>
+#include <linux/mtd/nand_ids.h>
+#include <jffs2/jffs2.h>
+
+#ifdef CONFIG_OMAP1510
+void archflashwp(void *archdata, int wp);
+#endif
+
+#define ROUND_DOWN(value,boundary)      ((value) & (~((boundary)-1)))
+
+#undef PSYCHO_DEBUG
+#undef NAND_DEBUG
+
+/* ****************** WARNING *********************
+ * When ALLOW_ERASE_BAD_DEBUG is non-zero the erase command will
+ * erase (or at least attempt to erase) blocks that are marked
+ * bad. This can be very handy if you are _sure_ that the block
+ * is OK, say because you marked a good block bad to test bad
+ * block handling and you are done testing, or if you have
+ * accidentally marked blocks bad.
+ *
+ * Erasing factory marked bad blocks is a _bad_ idea. If the
+ * erase succeeds there is no reliable way to find them again,
+ * and attempting to program or erase bad blocks can affect
+ * the data in _other_ (good) blocks.
+ */
+#define         ALLOW_ERASE_BAD_DEBUG 0
+
+#define CONFIG_MTD_NAND_ECC  /* enable ECC */
+#define CONFIG_MTD_NAND_ECC_JFFS2
+
+/* bits for nand_legacy_rw() `cmd'; or together as needed */
+#define NANDRW_READ    0x01
+#define NANDRW_WRITE   0x00
+#define NANDRW_JFFS2   0x02
+#define NANDRW_JFFS2_SKIP      0x04
+
+
+/*
+ * Exported variables etc.
+ */
+
+/* Definition of the out of band configuration structure */
+struct nand_oob_config {
+       /* position of ECC bytes inside oob */
+       int ecc_pos[6];
+       /* position of  bad blk flag inside oob -1 = inactive */
+       int badblock_pos;
+       /* position of ECC valid flag inside oob -1 = inactive */
+       int eccvalid_pos;
+} oob_config = { {0}, 0, 0};
+
+struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE] = {{0}};
+
+int curr_device = -1; /* Current NAND Device */
+
+
+/*
+ * Exported functionss
+ */
+int nand_legacy_erase(struct nand_chip* nand, size_t ofs,
+                    size_t len, int clean);
+int nand_legacy_rw(struct nand_chip* nand, int cmd,
+                 size_t start, size_t len,
+                 size_t * retlen, u_char * buf);
+void nand_print(struct nand_chip *nand);
+void nand_print_bad(struct nand_chip *nand);
+int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len,
+                size_t * retlen, u_char * buf);
+int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
+                size_t * retlen, const u_char * buf);
+
+/*
+ * Internals
+ */
+static int NanD_WaitReady(struct nand_chip *nand, int ale_wait);
+static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
+                size_t * retlen, u_char *buf, u_char *ecc_code);
+static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len,
+                          size_t * retlen, const u_char * buf,
+                          u_char * ecc_code);
+#ifdef CONFIG_MTD_NAND_ECC
+static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc);
+static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code);
+#endif
+
+
+/*
+ *
+ * Function definitions
+ *
+ */
+
+/* returns 0 if block containing pos is OK:
+ *             valid erase block and
+ *             not marked bad, or no bad mark position is specified
+ * returns 1 if marked bad or otherwise invalid
+ */
+static int check_block (struct nand_chip *nand, unsigned long pos)
+{
+       size_t retlen;
+       uint8_t oob_data;
+       uint16_t oob_data16[6];
+       int page0 = pos & (-nand->erasesize);
+       int page1 = page0 + nand->oobblock;
+       int badpos = oob_config.badblock_pos;
+
+       if (pos >= nand->totlen)
+               return 1;
+
+       if (badpos < 0)
+               return 0;       /* no way to check, assume OK */
+
+       if (nand->bus16) {
+               if (nand_read_oob(nand, (page0 + 0), 12, &retlen, (uint8_t *)oob_data16)
+                   || (oob_data16[2] & 0xff00) != 0xff00)
+                       return 1;
+               if (nand_read_oob(nand, (page1 + 0), 12, &retlen, (uint8_t *)oob_data16)
+                   || (oob_data16[2] & 0xff00) != 0xff00)
+                       return 1;
+       } else {
+               /* Note - bad block marker can be on first or second page */
+               if (nand_read_oob(nand, page0 + badpos, 1, &retlen, (unsigned char *)&oob_data)
+                   || oob_data != 0xff
+                   || nand_read_oob (nand, page1 + badpos, 1, &retlen, (unsigned char *)&oob_data)
+                   || oob_data != 0xff)
+                       return 1;
+       }
+
+       return 0;
+}
+
+/* print bad blocks in NAND flash */
+void nand_print_bad(struct nand_chip* nand)
+{
+       unsigned long pos;
+
+       for (pos = 0; pos < nand->totlen; pos += nand->erasesize) {
+               if (check_block(nand, pos))
+                       printf(" 0x%8.8lx\n", pos);
+       }
+       puts("\n");
+}
+
+/* cmd: 0: NANDRW_WRITE                        write, fail on bad block
+ *     1: NANDRW_READ                  read, fail on bad block
+ *     2: NANDRW_WRITE | NANDRW_JFFS2  write, skip bad blocks
+ *     3: NANDRW_READ | NANDRW_JFFS2   read, data all 0xff for bad blocks
+ *      7: NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP read, skip bad blocks
+ */
+int nand_legacy_rw (struct nand_chip* nand, int cmd,
+                  size_t start, size_t len,
+                  size_t * retlen, u_char * buf)
+{
+       int ret = 0, n, total = 0;
+       char eccbuf[6];
+       /* eblk (once set) is the start of the erase block containing the
+        * data being processed.
+        */
+       unsigned long eblk = ~0;        /* force mismatch on first pass */
+       unsigned long erasesize = nand->erasesize;
+
+       while (len) {
+               if ((start & (-erasesize)) != eblk) {
+                       /* have crossed into new erase block, deal with
+                        * it if it is sure marked bad.
+                        */
+                       eblk = start & (-erasesize); /* start of block */
+                       if (check_block(nand, eblk)) {
+                               if (cmd == (NANDRW_READ | NANDRW_JFFS2)) {
+                                       while (len > 0 &&
+                                              start - eblk < erasesize) {
+                                               *(buf++) = 0xff;
+                                               ++start;
+                                               ++total;
+                                               --len;
+                                       }
+                                       continue;
+                               } else if (cmd == (NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP)) {
+                                       start += erasesize;
+                                       continue;
+                               } else if (cmd == (NANDRW_WRITE | NANDRW_JFFS2)) {
+                                       /* skip bad block */
+                                       start += erasesize;
+                                       continue;
+                               } else {
+                                       ret = 1;
+                                       break;
+                               }
+                       }
+               }
+               /* The ECC will not be calculated correctly if
+                  less than 512 is written or read */
+               /* Is request at least 512 bytes AND it starts on a proper boundry */
+               if((start != ROUND_DOWN(start, 0x200)) || (len < 0x200))
+                       printf("Warning block writes should be at least 512 bytes and start on a 512 byte boundry\n");
+
+               if (cmd & NANDRW_READ) {
+                       ret = nand_read_ecc(nand, start,
+                                          min(len, eblk + erasesize - start),
+                                          (size_t *)&n, (u_char*)buf, (u_char *)eccbuf);
+               } else {
+                       ret = nand_write_ecc(nand, start,
+                                           min(len, eblk + erasesize - start),
+                                           (size_t *)&n, (u_char*)buf, (u_char *)eccbuf);
+               }
+
+               if (ret)
+                       break;
+
+               start  += n;
+               buf   += n;
+               total += n;
+               len   -= n;
+       }
+       if (retlen)
+               *retlen = total;
+
+       return ret;
+}
+
+void nand_print(struct nand_chip *nand)
+{
+       if (nand->numchips > 1) {
+               printf("%s at 0x%lx,\n"
+                      "\t  %d chips %s, size %d MB, \n"
+                      "\t  total size %ld MB, sector size %ld kB\n",
+                      nand->name, nand->IO_ADDR, nand->numchips,
+                      nand->chips_name, 1 << (nand->chipshift - 20),
+                      nand->totlen >> 20, nand->erasesize >> 10);
+       }
+       else {
+               printf("%s at 0x%lx (", nand->chips_name, nand->IO_ADDR);
+               print_size(nand->totlen, ", ");
+               print_size(nand->erasesize, " sector)\n");
+       }
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int NanD_WaitReady(struct nand_chip *nand, int ale_wait)
+{
+       /* This is inline, to optimise the common case, where it's ready instantly */
+       int ret = 0;
+
+#ifdef NAND_NO_RB      /* in config file, shorter delays currently wrap accesses */
+       if(ale_wait)
+               NAND_WAIT_READY(nand);  /* do the worst case 25us wait */
+       else
+               udelay(10);
+#else  /* has functional r/b signal */
+       NAND_WAIT_READY(nand);
+#endif
+       return ret;
+}
+
+/* NanD_Command: Send a flash command to the flash chip */
+
+static inline int NanD_Command(struct nand_chip *nand, unsigned char command)
+{
+       unsigned long nandptr = nand->IO_ADDR;
+
+       /* Assert the CLE (Command Latch Enable) line to the flash chip */
+       NAND_CTL_SETCLE(nandptr);
+
+       /* Send the command */
+       WRITE_NAND_COMMAND(command, nandptr);
+
+       /* Lower the CLE line */
+       NAND_CTL_CLRCLE(nandptr);
+
+#ifdef NAND_NO_RB
+       if(command == NAND_CMD_RESET){
+               u_char ret_val;
+               NanD_Command(nand, NAND_CMD_STATUS);
+               do {
+                       ret_val = READ_NAND(nandptr);/* wait till ready */
+               } while((ret_val & 0x40) != 0x40);
+       }
+#endif
+       return NanD_WaitReady(nand, 0);
+}
+
+/* NanD_Address: Set the current address for the flash chip */
+
+static int NanD_Address(struct nand_chip *nand, int numbytes, unsigned long ofs)
+{
+       unsigned long nandptr;
+       int i;
+
+       nandptr = nand->IO_ADDR;
+
+       /* Assert the ALE (Address Latch Enable) line to the flash chip */
+       NAND_CTL_SETALE(nandptr);
+
+       /* Send the address */
+       /* Devices with 256-byte page are addressed as:
+        * Column (bits 0-7), Page (bits 8-15, 16-23, 24-31)
+        * there is no device on the market with page256
+        * and more than 24 bits.
+        * Devices with 512-byte page are addressed as:
+        * Column (bits 0-7), Page (bits 9-16, 17-24, 25-31)
+        * 25-31 is sent only if the chip support it.
+        * bit 8 changes the read command to be sent
+        * (NAND_CMD_READ0 or NAND_CMD_READ1).
+        */
+
+       if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE)
+               WRITE_NAND_ADDRESS(ofs, nandptr);
+
+       ofs = ofs >> nand->page_shift;
+
+       if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE) {
+               for (i = 0; i < nand->pageadrlen; i++, ofs = ofs >> 8) {
+                       WRITE_NAND_ADDRESS(ofs, nandptr);
+               }
+       }
+
+       /* Lower the ALE line */
+       NAND_CTL_CLRALE(nandptr);
+
+       /* Wait for the chip to respond */
+       return NanD_WaitReady(nand, 1);
+}
+
+/* NanD_SelectChip: Select a given flash chip within the current floor */
+
+static inline int NanD_SelectChip(struct nand_chip *nand, int chip)
+{
+       /* Wait for it to be ready */
+       return NanD_WaitReady(nand, 0);
+}
+
+/* NanD_IdentChip: Identify a given NAND chip given {floor,chip} */
+
+static int NanD_IdentChip(struct nand_chip *nand, int floor, int chip)
+{
+       int mfr, id, i;
+
+       NAND_ENABLE_CE(nand);  /* set pin low */
+       /* Reset the chip */
+       if (NanD_Command(nand, NAND_CMD_RESET)) {
+#ifdef NAND_DEBUG
+               printf("NanD_Command (reset) for %d,%d returned true\n",
+                      floor, chip);
+#endif
+               NAND_DISABLE_CE(nand);  /* set pin high */
+               return 0;
+       }
+
+       /* Read the NAND chip ID: 1. Send ReadID command */
+       if (NanD_Command(nand, NAND_CMD_READID)) {
+#ifdef NAND_DEBUG
+               printf("NanD_Command (ReadID) for %d,%d returned true\n",
+                      floor, chip);
+#endif
+               NAND_DISABLE_CE(nand);  /* set pin high */
+               return 0;
+       }
+
+       /* Read the NAND chip ID: 2. Send address byte zero */
+       NanD_Address(nand, ADDR_COLUMN, 0);
+
+       /* Read the manufacturer and device id codes from the device */
+
+       mfr = READ_NAND(nand->IO_ADDR);
+
+       id = READ_NAND(nand->IO_ADDR);
+
+       NAND_DISABLE_CE(nand);  /* set pin high */
+
+#ifdef NAND_DEBUG
+       printf("NanD_Command (ReadID) got %x %x\n", mfr, id);
+#endif
+       if (mfr == 0xff || mfr == 0) {
+               /* No response - return failure */
+               return 0;
+       }
+
+       /* Check it's the same as the first chip we identified.
+        * M-Systems say that any given nand_chip device should only
+        * contain _one_ type of flash part, although that's not a
+        * hardware restriction. */
+       if (nand->mfr) {
+               if (nand->mfr == mfr && nand->id == id) {
+                       return 1;       /* This is another the same the first */
+               } else {
+                       printf("Flash chip at floor %d, chip %d is different:\n",
+                              floor, chip);
+               }
+       }
+
+       /* Print and store the manufacturer and ID codes. */
+       for (i = 0; nand_flash_ids[i].name != NULL; i++) {
+               if (mfr == nand_flash_ids[i].manufacture_id &&
+                   id == nand_flash_ids[i].model_id) {
+#ifdef NAND_DEBUG
+                       printf("Flash chip found:\n\t Manufacturer ID: 0x%2.2X, "
+                              "Chip ID: 0x%2.2X (%s)\n", mfr, id,
+                              nand_flash_ids[i].name);
+#endif
+                       if (!nand->mfr) {
+                               nand->mfr = mfr;
+                               nand->id = id;
+                               nand->chipshift =
+                                   nand_flash_ids[i].chipshift;
+                               nand->page256 = nand_flash_ids[i].page256;
+                               nand->eccsize = 256;
+                               if (nand->page256) {
+                                       nand->oobblock = 256;
+                                       nand->oobsize = 8;
+                                       nand->page_shift = 8;
+                               } else {
+                                       nand->oobblock = 512;
+                                       nand->oobsize = 16;
+                                       nand->page_shift = 9;
+                               }
+                               nand->pageadrlen = nand_flash_ids[i].pageadrlen;
+                               nand->erasesize  = nand_flash_ids[i].erasesize;
+                               nand->chips_name = nand_flash_ids[i].name;
+                               nand->bus16      = nand_flash_ids[i].bus16;
+                               return 1;
+                       }
+                       return 0;
+               }
+       }
+
+
+#ifdef NAND_DEBUG
+       /* We haven't fully identified the chip. Print as much as we know. */
+       printf("Unknown flash chip found: %2.2X %2.2X\n",
+              id, mfr);
+#endif
+
+       return 0;
+}
+
+/* NanD_ScanChips: Find all NAND chips present in a nand_chip, and identify them */
+
+static void NanD_ScanChips(struct nand_chip *nand)
+{
+       int floor, chip;
+       int numchips[NAND_MAX_FLOORS];
+       int maxchips = NAND_MAX_CHIPS;
+       int ret = 1;
+
+       nand->numchips = 0;
+       nand->mfr = 0;
+       nand->id = 0;
+
+
+       /* For each floor, find the number of valid chips it contains */
+       for (floor = 0; floor < NAND_MAX_FLOORS; floor++) {
+               ret = 1;
+               numchips[floor] = 0;
+               for (chip = 0; chip < maxchips && ret != 0; chip++) {
+
+                       ret = NanD_IdentChip(nand, floor, chip);
+                       if (ret) {
+                               numchips[floor]++;
+                               nand->numchips++;
+                       }
+               }
+       }
+
+       /* If there are none at all that we recognise, bail */
+       if (!nand->numchips) {
+#ifdef NAND_DEBUG
+               puts ("No NAND flash chips recognised.\n");
+#endif
+               return;
+       }
+
+       /* Allocate an array to hold the information for each chip */
+       nand->chips = malloc(sizeof(struct Nand) * nand->numchips);
+       if (!nand->chips) {
+               puts ("No memory for allocating chip info structures\n");
+               return;
+       }
+
+       ret = 0;
+
+       /* Fill out the chip array with {floor, chipno} for each
+        * detected chip in the device. */
+       for (floor = 0; floor < NAND_MAX_FLOORS; floor++) {
+               for (chip = 0; chip < numchips[floor]; chip++) {
+                       nand->chips[ret].floor = floor;
+                       nand->chips[ret].chip = chip;
+                       nand->chips[ret].curadr = 0;
+                       nand->chips[ret].curmode = 0x50;
+                       ret++;
+               }
+       }
+
+       /* Calculate and print the total size of the device */
+       nand->totlen = nand->numchips * (1 << nand->chipshift);
+
+#ifdef NAND_DEBUG
+       printf("%d flash chips found. Total nand_chip size: %ld MB\n",
+              nand->numchips, nand->totlen >> 20);
+#endif
+}
+
+/* we need to be fast here, 1 us per read translates to 1 second per meg */
+static void NanD_ReadBuf (struct nand_chip *nand, u_char * data_buf, int cntr)
+{
+       unsigned long nandptr = nand->IO_ADDR;
+
+       NanD_Command (nand, NAND_CMD_READ0);
+
+       if (nand->bus16) {
+               u16 val;
+
+               while (cntr >= 16) {
+                       val = READ_NAND (nandptr);
+                       *data_buf++ = val & 0xff;
+                       *data_buf++ = val >> 8;
+                       val = READ_NAND (nandptr);
+                       *data_buf++ = val & 0xff;
+                       *data_buf++ = val >> 8;
+                       val = READ_NAND (nandptr);
+                       *data_buf++ = val & 0xff;
+                       *data_buf++ = val >> 8;
+                       val = READ_NAND (nandptr);
+                       *data_buf++ = val & 0xff;
+                       *data_buf++ = val >> 8;
+                       val = READ_NAND (nandptr);
+                       *data_buf++ = val & 0xff;
+                       *data_buf++ = val >> 8;
+                       val = READ_NAND (nandptr);
+                       *data_buf++ = val & 0xff;
+                       *data_buf++ = val >> 8;
+                       val = READ_NAND (nandptr);
+                       *data_buf++ = val & 0xff;
+                       *data_buf++ = val >> 8;
+                       val = READ_NAND (nandptr);
+                       *data_buf++ = val & 0xff;
+                       *data_buf++ = val >> 8;
+                       cntr -= 16;
+               }
+
+               while (cntr > 0) {
+                       val = READ_NAND (nandptr);
+                       *data_buf++ = val & 0xff;
+                       *data_buf++ = val >> 8;
+                       cntr -= 2;
+               }
+       } else {
+               while (cntr >= 16) {
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       *data_buf++ = READ_NAND (nandptr);
+                       cntr -= 16;
+               }
+
+               while (cntr > 0) {
+                       *data_buf++ = READ_NAND (nandptr);
+                       cntr--;
+               }
+       }
+}
+
+/*
+ * NAND read with ECC
+ */
+static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
+                size_t * retlen, u_char *buf, u_char *ecc_code)
+{
+       int col, page;
+       int ecc_status = 0;
+#ifdef CONFIG_MTD_NAND_ECC
+       int j;
+       int ecc_failed = 0;
+       u_char *data_poi;
+       u_char ecc_calc[6];
+#endif
+
+       /* Do not allow reads past end of device */
+       if ((start + len) > nand->totlen) {
+               printf ("%s: Attempt read beyond end of device %x %x %x\n",
+                       __FUNCTION__, (uint) start, (uint) len, (uint) nand->totlen);
+               *retlen = 0;
+               return -1;
+       }
+
+       /* First we calculate the starting page */
+       /*page = shr(start, nand->page_shift);*/
+       page = start >> nand->page_shift;
+
+       /* Get raw starting column */
+       col = start & (nand->oobblock - 1);
+
+       /* Initialize return value */
+       *retlen = 0;
+
+       /* Select the NAND device */
+       NAND_ENABLE_CE(nand);  /* set pin low */
+
+       /* Loop until all data read */
+       while (*retlen < len) {
+
+#ifdef CONFIG_MTD_NAND_ECC
+               /* Do we have this page in cache ? */
+               if (nand->cache_page == page)
+                       goto readdata;
+               /* Send the read command */
+               NanD_Command(nand, NAND_CMD_READ0);
+               if (nand->bus16) {
+                       NanD_Address(nand, ADDR_COLUMN_PAGE,
+                                    (page << nand->page_shift) + (col >> 1));
+               } else {
+                       NanD_Address(nand, ADDR_COLUMN_PAGE,
+                                    (page << nand->page_shift) + col);
+               }
+
+               /* Read in a page + oob data */
+               NanD_ReadBuf(nand, nand->data_buf, nand->oobblock + nand->oobsize);
+
+               /* copy data into cache, for read out of cache and if ecc fails */
+               if (nand->data_cache) {
+                       memcpy (nand->data_cache, nand->data_buf,
+                               nand->oobblock + nand->oobsize);
+               }
+
+               /* Pick the ECC bytes out of the oob data */
+               for (j = 0; j < 6; j++) {
+                       ecc_code[j] = nand->data_buf[(nand->oobblock + oob_config.ecc_pos[j])];
+               }
+
+               /* Calculate the ECC and verify it */
+               /* If block was not written with ECC, skip ECC */
+               if (oob_config.eccvalid_pos != -1 &&
+                   (nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] & 0x0f) != 0x0f) {
+
+                       nand_calculate_ecc (&nand->data_buf[0], &ecc_calc[0]);
+                       switch (nand_correct_data (&nand->data_buf[0], &ecc_code[0], &ecc_calc[0])) {
+                       case -1:
+                               printf ("%s: Failed ECC read, page 0x%08x\n", __FUNCTION__, page);
+                               ecc_failed++;
+                               break;
+                       case 1:
+                       case 2: /* transfer ECC corrected data to cache */
+                               if (nand->data_cache)
+                                       memcpy (nand->data_cache, nand->data_buf, 256);
+                               break;
+                       }
+               }
+
+               if (oob_config.eccvalid_pos != -1 &&
+                   nand->oobblock == 512 && (nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] & 0xf0) != 0xf0) {
+
+                       nand_calculate_ecc (&nand->data_buf[256], &ecc_calc[3]);
+                       switch (nand_correct_data (&nand->data_buf[256], &ecc_code[3], &ecc_calc[3])) {
+                       case -1:
+                               printf ("%s: Failed ECC read, page 0x%08x\n", __FUNCTION__, page);
+                               ecc_failed++;
+                               break;
+                       case 1:
+                       case 2: /* transfer ECC corrected data to cache */
+                               if (nand->data_cache)
+                                       memcpy (&nand->data_cache[256], &nand->data_buf[256], 256);
+                               break;
+                       }
+               }
+readdata:
+               /* Read the data from ECC data buffer into return buffer */
+               data_poi = (nand->data_cache) ? nand->data_cache : nand->data_buf;
+               data_poi += col;
+               if ((*retlen + (nand->oobblock - col)) >= len) {
+                       memcpy (buf + *retlen, data_poi, len - *retlen);
+                       *retlen = len;
+               } else {
+                       memcpy (buf + *retlen, data_poi,  nand->oobblock - col);
+                       *retlen += nand->oobblock - col;
+               }
+               /* Set cache page address, invalidate, if ecc_failed */
+               nand->cache_page = (nand->data_cache && !ecc_failed) ? page : -1;
+
+               ecc_status += ecc_failed;
+               ecc_failed = 0;
+
+#else
+               /* Send the read command */
+               NanD_Command(nand, NAND_CMD_READ0);
+               if (nand->bus16) {
+                       NanD_Address(nand, ADDR_COLUMN_PAGE,
+                                    (page << nand->page_shift) + (col >> 1));
+               } else {
+                       NanD_Address(nand, ADDR_COLUMN_PAGE,
+                                    (page << nand->page_shift) + col);
+               }
+
+               /* Read the data directly into the return buffer */
+               if ((*retlen + (nand->oobblock - col)) >= len) {
+                       NanD_ReadBuf(nand, buf + *retlen, len - *retlen);
+                       *retlen = len;
+                       /* We're done */
+                       continue;
+               } else {
+                       NanD_ReadBuf(nand, buf + *retlen, nand->oobblock - col);
+                       *retlen += nand->oobblock - col;
+                       }
+#endif
+               /* For subsequent reads align to page boundary. */
+               col = 0;
+               /* Increment page address */
+               page++;
+       }
+
+       /* De-select the NAND device */
+       NAND_DISABLE_CE(nand);  /* set pin high */
+
+       /*
+        * Return success, if no ECC failures, else -EIO
+        * fs driver will take care of that, because
+        * retlen == desired len and result == -EIO
+        */
+       return ecc_status ? -1 : 0;
+}
+
+/*
+ *     Nand_page_program function is used for write and writev !
+ */
+static int nand_write_page (struct nand_chip *nand,
+                           int page, int col, int last, u_char * ecc_code)
+{
+
+       int i;
+       unsigned long nandptr = nand->IO_ADDR;
+
+#ifdef CONFIG_MTD_NAND_ECC
+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
+       int ecc_bytes = (nand->oobblock == 512) ? 6 : 3;
+#endif
+#endif
+       /* pad oob area */
+       for (i = nand->oobblock; i < nand->oobblock + nand->oobsize; i++)
+               nand->data_buf[i] = 0xff;
+
+#ifdef CONFIG_MTD_NAND_ECC
+       /* Zero out the ECC array */
+       for (i = 0; i < 6; i++)
+               ecc_code[i] = 0x00;
+
+       /* Read back previous written data, if col > 0 */
+       if (col) {
+               NanD_Command (nand, NAND_CMD_READ0);
+               if (nand->bus16) {
+                       NanD_Address (nand, ADDR_COLUMN_PAGE,
+                                     (page << nand->page_shift) + (col >> 1));
+               } else {
+                       NanD_Address (nand, ADDR_COLUMN_PAGE,
+                                     (page << nand->page_shift) + col);
+               }
+
+               if (nand->bus16) {
+                       u16 val;
+
+                       for (i = 0; i < col; i += 2) {
+                               val = READ_NAND (nandptr);
+                               nand->data_buf[i] = val & 0xff;
+                               nand->data_buf[i + 1] = val >> 8;
+                       }
+               } else {
+                       for (i = 0; i < col; i++)
+                               nand->data_buf[i] = READ_NAND (nandptr);
+               }
+       }
+
+       /* Calculate and write the ECC if we have enough data */
+       if ((col < nand->eccsize) && (last >= nand->eccsize)) {
+               nand_calculate_ecc (&nand->data_buf[0], &(ecc_code[0]));
+               for (i = 0; i < 3; i++) {
+                       nand->data_buf[(nand->oobblock +
+                                       oob_config.ecc_pos[i])] = ecc_code[i];
+               }
+               if (oob_config.eccvalid_pos != -1) {
+                       nand->data_buf[nand->oobblock +
+                                      oob_config.eccvalid_pos] = 0xf0;
+               }
+       }
+
+       /* Calculate and write the second ECC if we have enough data */
+       if ((nand->oobblock == 512) && (last == nand->oobblock)) {
+               nand_calculate_ecc (&nand->data_buf[256], &(ecc_code[3]));
+               for (i = 3; i < 6; i++) {
+                       nand->data_buf[(nand->oobblock +
+                                       oob_config.ecc_pos[i])] = ecc_code[i];
+               }
+               if (oob_config.eccvalid_pos != -1) {
+                       nand->data_buf[nand->oobblock +
+                                      oob_config.eccvalid_pos] &= 0x0f;
+               }
+       }
+#endif
+       /* Prepad for partial page programming !!! */
+       for (i = 0; i < col; i++)
+               nand->data_buf[i] = 0xff;
+
+       /* Postpad for partial page programming !!! oob is already padded */
+       for (i = last; i < nand->oobblock; i++)
+               nand->data_buf[i] = 0xff;
+
+       /* Send command to begin auto page programming */
+       NanD_Command (nand, NAND_CMD_READ0);
+       NanD_Command (nand, NAND_CMD_SEQIN);
+       if (nand->bus16) {
+               NanD_Address (nand, ADDR_COLUMN_PAGE,
+                             (page << nand->page_shift) + (col >> 1));
+       } else {
+               NanD_Address (nand, ADDR_COLUMN_PAGE,
+                             (page << nand->page_shift) + col);
+       }
+
+       /* Write out complete page of data */
+       if (nand->bus16) {
+               for (i = 0; i < (nand->oobblock + nand->oobsize); i += 2) {
+                       WRITE_NAND (nand->data_buf[i] +
+                                   (nand->data_buf[i + 1] << 8),
+                                   nand->IO_ADDR);
+               }
+       } else {
+               for (i = 0; i < (nand->oobblock + nand->oobsize); i++)
+                       WRITE_NAND (nand->data_buf[i], nand->IO_ADDR);
+       }
+
+       /* Send command to actually program the data */
+       NanD_Command (nand, NAND_CMD_PAGEPROG);
+       NanD_Command (nand, NAND_CMD_STATUS);
+#ifdef NAND_NO_RB
+       {
+               u_char ret_val;
+
+               do {
+                       ret_val = READ_NAND (nandptr);  /* wait till ready */
+               } while ((ret_val & 0x40) != 0x40);
+       }
+#endif
+       /* See if device thinks it succeeded */
+       if (READ_NAND (nand->IO_ADDR) & 0x01) {
+               printf ("%s: Failed write, page 0x%08x, ", __FUNCTION__,
+                       page);
+               return -1;
+       }
+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
+       /*
+        * The NAND device assumes that it is always writing to
+        * a cleanly erased page. Hence, it performs its internal
+        * write verification only on bits that transitioned from
+        * 1 to 0. The device does NOT verify the whole page on a
+        * byte by byte basis. It is possible that the page was
+        * not completely erased or the page is becoming unusable
+        * due to wear. The read with ECC would catch the error
+        * later when the ECC page check fails, but we would rather
+        * catch it early in the page write stage. Better to write
+        * no data than invalid data.
+        */
+
+       /* Send command to read back the page */
+       if (col < nand->eccsize)
+               NanD_Command (nand, NAND_CMD_READ0);
+       else
+               NanD_Command (nand, NAND_CMD_READ1);
+       if (nand->bus16) {
+               NanD_Address (nand, ADDR_COLUMN_PAGE,
+                             (page << nand->page_shift) + (col >> 1));
+       } else {
+               NanD_Address (nand, ADDR_COLUMN_PAGE,
+                             (page << nand->page_shift) + col);
+       }
+
+       /* Loop through and verify the data */
+       if (nand->bus16) {
+               for (i = col; i < last; i = +2) {
+                       if ((nand->data_buf[i] +
+                            (nand->data_buf[i + 1] << 8)) != READ_NAND (nand->IO_ADDR)) {
+                               printf ("%s: Failed write verify, page 0x%08x ",
+                                       __FUNCTION__, page);
+                               return -1;
+                       }
+               }
+       } else {
+               for (i = col; i < last; i++) {
+                       if (nand->data_buf[i] != READ_NAND (nand->IO_ADDR)) {
+                               printf ("%s: Failed write verify, page 0x%08x ",
+                                       __FUNCTION__, page);
+                               return -1;
+                       }
+               }
+       }
+
+#ifdef CONFIG_MTD_NAND_ECC
+       /*
+        * We also want to check that the ECC bytes wrote
+        * correctly for the same reasons stated above.
+        */
+       NanD_Command (nand, NAND_CMD_READOOB);
+       if (nand->bus16) {
+               NanD_Address (nand, ADDR_COLUMN_PAGE,
+                             (page << nand->page_shift) + (col >> 1));
+       } else {
+               NanD_Address (nand, ADDR_COLUMN_PAGE,
+                             (page << nand->page_shift) + col);
+       }
+       if (nand->bus16) {
+               for (i = 0; i < nand->oobsize; i += 2) {
+                       u16 val;
+
+                       val = READ_NAND (nand->IO_ADDR);
+                       nand->data_buf[i] = val & 0xff;
+                       nand->data_buf[i + 1] = val >> 8;
+               }
+       } else {
+               for (i = 0; i < nand->oobsize; i++) {
+                       nand->data_buf[i] = READ_NAND (nand->IO_ADDR);
+               }
+       }
+       for (i = 0; i < ecc_bytes; i++) {
+               if ((nand->data_buf[(oob_config.ecc_pos[i])] != ecc_code[i]) && ecc_code[i]) {
+                       printf ("%s: Failed ECC write "
+                               "verify, page 0x%08x, "
+                               "%6i bytes were succesful\n",
+                               __FUNCTION__, page, i);
+                       return -1;
+               }
+       }
+#endif /* CONFIG_MTD_NAND_ECC */
+#endif /* CONFIG_MTD_NAND_VERIFY_WRITE */
+       return 0;
+}
+
+static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len,
+                          size_t * retlen, const u_char * buf, u_char * ecc_code)
+{
+       int i, page, col, cnt, ret = 0;
+
+       /* Do not allow write past end of device */
+       if ((to + len) > nand->totlen) {
+               printf ("%s: Attempt to write past end of page\n", __FUNCTION__);
+               return -1;
+       }
+
+       /* Shift to get page */
+       page = ((int) to) >> nand->page_shift;
+
+       /* Get the starting column */
+       col = to & (nand->oobblock - 1);
+
+       /* Initialize return length value */
+       *retlen = 0;
+
+       /* Select the NAND device */
+#ifdef CONFIG_OMAP1510
+       archflashwp(0,0);
+#endif
+#ifdef CFG_NAND_WP
+       NAND_WP_OFF();
+#endif
+
+       NAND_ENABLE_CE(nand);  /* set pin low */
+
+       /* Check the WP bit */
+       NanD_Command(nand, NAND_CMD_STATUS);
+       if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
+               printf ("%s: Device is write protected!!!\n", __FUNCTION__);
+               ret = -1;
+               goto out;
+       }
+
+       /* Loop until all data is written */
+       while (*retlen < len) {
+               /* Invalidate cache, if we write to this page */
+               if (nand->cache_page == page)
+                       nand->cache_page = -1;
+
+               /* Write data into buffer */
+               if ((col + len) >= nand->oobblock) {
+                       for (i = col, cnt = 0; i < nand->oobblock; i++, cnt++) {
+                               nand->data_buf[i] = buf[(*retlen + cnt)];
+                       }
+               } else {
+                       for (i = col, cnt = 0; cnt < (len - *retlen); i++, cnt++) {
+                               nand->data_buf[i] = buf[(*retlen + cnt)];
+                       }
+               }
+               /* We use the same function for write and writev !) */
+               ret = nand_write_page (nand, page, col, i, ecc_code);
+               if (ret)
+                       goto out;
+
+               /* Next data start at page boundary */
+               col = 0;
+
+               /* Update written bytes count */
+               *retlen += cnt;
+
+               /* Increment page address */
+               page++;
+       }
+
+       /* Return happy */
+       *retlen = len;
+
+out:
+       /* De-select the NAND device */
+       NAND_DISABLE_CE(nand);  /* set pin high */
+#ifdef CONFIG_OMAP1510
+       archflashwp(0,1);
+#endif
+#ifdef CFG_NAND_WP
+       NAND_WP_ON();
+#endif
+
+       return ret;
+}
+
+/* read from the 16 bytes of oob data that correspond to a 512 byte
+ * page or 2 256-byte pages.
+ */
+int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len,
+                        size_t * retlen, u_char * buf)
+{
+       int len256 = 0;
+       struct Nand *mychip;
+       int ret = 0;
+
+       mychip = &nand->chips[ofs >> nand->chipshift];
+
+       /* update address for 2M x 8bit devices. OOB starts on the second */
+       /* page to maintain compatibility with nand_read_ecc. */
+       if (nand->page256) {
+               if (!(ofs & 0x8))
+                       ofs += 0x100;
+               else
+                       ofs -= 0x8;
+       }
+
+       NAND_ENABLE_CE(nand);  /* set pin low */
+       NanD_Command(nand, NAND_CMD_READOOB);
+       if (nand->bus16) {
+               NanD_Address(nand, ADDR_COLUMN_PAGE,
+                            ((ofs >> nand->page_shift) << nand->page_shift) +
+                               ((ofs & (nand->oobblock - 1)) >> 1));
+       } else {
+               NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
+       }
+
+       /* treat crossing 8-byte OOB data for 2M x 8bit devices */
+       /* Note: datasheet says it should automaticaly wrap to the */
+       /*       next OOB block, but it didn't work here. mf.      */
+       if (nand->page256 && ofs + len > (ofs | 0x7) + 1) {
+               len256 = (ofs | 0x7) + 1 - ofs;
+               NanD_ReadBuf(nand, buf, len256);
+
+               NanD_Command(nand, NAND_CMD_READOOB);
+               NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff));
+       }
+
+       NanD_ReadBuf(nand, &buf[len256], len - len256);
+
+       *retlen = len;
+       /* Reading the full OOB data drops us off of the end of the page,
+        * causing the flash device to go into busy mode, so we need
+        * to wait until ready 11.4.1 and Toshiba TC58256FT nands */
+
+       ret = NanD_WaitReady(nand, 1);
+       NAND_DISABLE_CE(nand);  /* set pin high */
+
+       return ret;
+
+}
+
+/* write to the 16 bytes of oob data that correspond to a 512 byte
+ * page or 2 256-byte pages.
+ */
+int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
+                 size_t * retlen, const u_char * buf)
+{
+       int len256 = 0;
+       int i;
+       unsigned long nandptr = nand->IO_ADDR;
+
+#ifdef PSYCHO_DEBUG
+       printf("nand_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",
+              (long)ofs, len, buf[0], buf[1], buf[2], buf[3],
+              buf[8], buf[9], buf[14],buf[15]);
+#endif
+
+       NAND_ENABLE_CE(nand);  /* set pin low to enable chip */
+
+       /* Reset the chip */
+       NanD_Command(nand, NAND_CMD_RESET);
+
+       /* issue the Read2 command to set the pointer to the Spare Data Area. */
+       NanD_Command(nand, NAND_CMD_READOOB);
+       if (nand->bus16) {
+               NanD_Address(nand, ADDR_COLUMN_PAGE,
+                            ((ofs >> nand->page_shift) << nand->page_shift) +
+                               ((ofs & (nand->oobblock - 1)) >> 1));
+       } else {
+               NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
+       }
+
+       /* update address for 2M x 8bit devices. OOB starts on the second */
+       /* page to maintain compatibility with nand_read_ecc. */
+       if (nand->page256) {
+               if (!(ofs & 0x8))
+                       ofs += 0x100;
+               else
+                       ofs -= 0x8;
+       }
+
+       /* issue the Serial Data In command to initial the Page Program process */
+       NanD_Command(nand, NAND_CMD_SEQIN);
+       if (nand->bus16) {
+               NanD_Address(nand, ADDR_COLUMN_PAGE,
+                            ((ofs >> nand->page_shift) << nand->page_shift) +
+                               ((ofs & (nand->oobblock - 1)) >> 1));
+       } else {
+               NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
+       }
+
+       /* treat crossing 8-byte OOB data for 2M x 8bit devices */
+       /* Note: datasheet says it should automaticaly wrap to the */
+       /*       next OOB block, but it didn't work here. mf.      */
+       if (nand->page256 && ofs + len > (ofs | 0x7) + 1) {
+               len256 = (ofs | 0x7) + 1 - ofs;
+               for (i = 0; i < len256; i++)
+                       WRITE_NAND(buf[i], nandptr);
+
+               NanD_Command(nand, NAND_CMD_PAGEPROG);
+               NanD_Command(nand, NAND_CMD_STATUS);
+#ifdef NAND_NO_RB
+               { u_char ret_val;
+                       do {
+                               ret_val = READ_NAND(nandptr); /* wait till ready */
+                       } while ((ret_val & 0x40) != 0x40);
+               }
+#endif
+               if (READ_NAND(nandptr) & 1) {
+                       puts ("Error programming oob data\n");
+                       /* There was an error */
+                       NAND_DISABLE_CE(nand);  /* set pin high */
+                       *retlen = 0;
+                       return -1;
+               }
+               NanD_Command(nand, NAND_CMD_SEQIN);
+               NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff));
+       }
+
+       if (nand->bus16) {
+               for (i = len256; i < len; i += 2) {
+                       WRITE_NAND(buf[i] + (buf[i+1] << 8), nandptr);
+               }
+       } else {
+               for (i = len256; i < len; i++)
+                       WRITE_NAND(buf[i], nandptr);
+       }
+
+       NanD_Command(nand, NAND_CMD_PAGEPROG);
+       NanD_Command(nand, NAND_CMD_STATUS);
+#ifdef NAND_NO_RB
+       {       u_char ret_val;
+               do {
+                       ret_val = READ_NAND(nandptr); /* wait till ready */
+               } while ((ret_val & 0x40) != 0x40);
+       }
+#endif
+       if (READ_NAND(nandptr) & 1) {
+               puts ("Error programming oob data\n");
+               /* There was an error */
+               NAND_DISABLE_CE(nand);  /* set pin high */
+               *retlen = 0;
+               return -1;
+       }
+
+       NAND_DISABLE_CE(nand);  /* set pin high */
+       *retlen = len;
+       return 0;
+
+}
+
+int nand_legacy_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean)
+{
+       /* This is defined as a structure so it will work on any system
+        * using native endian jffs2 (the default).
+        */
+       static struct jffs2_unknown_node clean_marker = {
+               JFFS2_MAGIC_BITMASK,
+               JFFS2_NODETYPE_CLEANMARKER,
+               8               /* 8 bytes in this node */
+       };
+       unsigned long nandptr;
+       struct Nand *mychip;
+       int ret = 0;
+
+       if (ofs & (nand->erasesize-1) || len & (nand->erasesize-1)) {
+               printf ("Offset and size must be sector aligned, erasesize = %d\n",
+                       (int) nand->erasesize);
+               return -1;
+       }
+
+       nandptr = nand->IO_ADDR;
+
+       /* Select the NAND device */
+#ifdef CONFIG_OMAP1510
+       archflashwp(0,0);
+#endif
+#ifdef CFG_NAND_WP
+       NAND_WP_OFF();
+#endif
+    NAND_ENABLE_CE(nand);  /* set pin low */
+
+       /* Check the WP bit */
+       NanD_Command(nand, NAND_CMD_STATUS);
+       if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
+               printf ("nand_write_ecc: Device is write protected!!!\n");
+               ret = -1;
+               goto out;
+       }
+
+       /* Check the WP bit */
+       NanD_Command(nand, NAND_CMD_STATUS);
+       if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
+               printf ("%s: Device is write protected!!!\n", __FUNCTION__);
+               ret = -1;
+               goto out;
+       }
+
+       /* FIXME: Do nand in the background. Use timers or schedule_task() */
+       while(len) {
+               /*mychip = &nand->chips[shr(ofs, nand->chipshift)];*/
+               mychip = &nand->chips[ofs >> nand->chipshift];
+
+               /* always check for bad block first, genuine bad blocks
+                * should _never_  be erased.
+                */
+               if (ALLOW_ERASE_BAD_DEBUG || !check_block(nand, ofs)) {
+                       /* Select the NAND device */
+                       NAND_ENABLE_CE(nand);  /* set pin low */
+
+                       NanD_Command(nand, NAND_CMD_ERASE1);
+                       NanD_Address(nand, ADDR_PAGE, ofs);
+                       NanD_Command(nand, NAND_CMD_ERASE2);
+
+                       NanD_Command(nand, NAND_CMD_STATUS);
+
+#ifdef NAND_NO_RB
+                       {       u_char ret_val;
+                               do {
+                                       ret_val = READ_NAND(nandptr); /* wait till ready */
+                               } while ((ret_val & 0x40) != 0x40);
+                       }
+#endif
+                       if (READ_NAND(nandptr) & 1) {
+                               printf ("%s: Error erasing at 0x%lx\n",
+                                       __FUNCTION__, (long)ofs);
+                               /* There was an error */
+                               ret = -1;
+                               goto out;
+                       }
+                       if (clean) {
+                               int n;  /* return value not used */
+                               int p, l;
+
+                               /* clean marker position and size depend
+                                * on the page size, since 256 byte pages
+                                * only have 8 bytes of oob data
+                                */
+                               if (nand->page256) {
+                                       p = NAND_JFFS2_OOB8_FSDAPOS;
+                                       l = NAND_JFFS2_OOB8_FSDALEN;
+                               } else {
+                                       p = NAND_JFFS2_OOB16_FSDAPOS;
+                                       l = NAND_JFFS2_OOB16_FSDALEN;
+                               }
+
+                               ret = nand_write_oob(nand, ofs + p, l, (size_t *)&n,
+                                                    (u_char *)&clean_marker);
+                               /* quit here if write failed */
+                               if (ret)
+                                       goto out;
+                       }
+               }
+               ofs += nand->erasesize;
+               len -= nand->erasesize;
+       }
+
+out:
+       /* De-select the NAND device */
+       NAND_DISABLE_CE(nand);  /* set pin high */
+#ifdef CONFIG_OMAP1510
+       archflashwp(0,1);
+#endif
+#ifdef CFG_NAND_WP
+       NAND_WP_ON();
+#endif
+
+       return ret;
+}
+
+
+static inline int nandcheck(unsigned long potential, unsigned long physadr)
+{
+       return 0;
+}
+
+unsigned long nand_probe(unsigned long physadr)
+{
+       struct nand_chip *nand = NULL;
+       int i = 0, ChipID = 1;
+
+#ifdef CONFIG_MTD_NAND_ECC_JFFS2
+       oob_config.ecc_pos[0] = NAND_JFFS2_OOB_ECCPOS0;
+       oob_config.ecc_pos[1] = NAND_JFFS2_OOB_ECCPOS1;
+       oob_config.ecc_pos[2] = NAND_JFFS2_OOB_ECCPOS2;
+       oob_config.ecc_pos[3] = NAND_JFFS2_OOB_ECCPOS3;
+       oob_config.ecc_pos[4] = NAND_JFFS2_OOB_ECCPOS4;
+       oob_config.ecc_pos[5] = NAND_JFFS2_OOB_ECCPOS5;
+       oob_config.eccvalid_pos = 4;
+#else
+       oob_config.ecc_pos[0] = NAND_NOOB_ECCPOS0;
+       oob_config.ecc_pos[1] = NAND_NOOB_ECCPOS1;
+       oob_config.ecc_pos[2] = NAND_NOOB_ECCPOS2;
+       oob_config.ecc_pos[3] = NAND_NOOB_ECCPOS3;
+       oob_config.ecc_pos[4] = NAND_NOOB_ECCPOS4;
+       oob_config.ecc_pos[5] = NAND_NOOB_ECCPOS5;
+       oob_config.eccvalid_pos = NAND_NOOB_ECCVPOS;
+#endif
+       oob_config.badblock_pos = 5;
+
+       for (i=0; i<CFG_MAX_NAND_DEVICE; i++) {
+               if (nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN) {
+                       nand = &nand_dev_desc[i];
+                       break;
+               }
+       }
+       if (!nand)
+               return (0);
+
+       memset((char *)nand, 0, sizeof(struct nand_chip));
+
+       nand->IO_ADDR = physadr;
+       nand->cache_page = -1;  /* init the cache page */
+       NanD_ScanChips(nand);
+
+       if (nand->totlen == 0) {
+               /* no chips found, clean up and quit */
+               memset((char *)nand, 0, sizeof(struct nand_chip));
+               nand->ChipID = NAND_ChipID_UNKNOWN;
+               return (0);
+       }
+
+       nand->ChipID = ChipID;
+       if (curr_device == -1)
+               curr_device = i;
+
+       nand->data_buf = malloc (nand->oobblock + nand->oobsize);
+       if (!nand->data_buf) {
+               puts ("Cannot allocate memory for data structures.\n");
+               return (0);
+       }
+
+       return (nand->totlen);
+}
+
+#ifdef CONFIG_MTD_NAND_ECC
+/*
+ * Pre-calculated 256-way 1 byte column parity
+ */
+static const u_char nand_ecc_precalc_table[] = {
+       0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
+       0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
+       0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
+       0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+       0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
+       0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+       0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
+       0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+       0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
+       0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+       0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
+       0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+       0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
+       0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+       0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
+       0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+       0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
+       0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+       0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
+       0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+       0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
+       0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+       0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
+       0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+       0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
+       0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+       0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
+       0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+       0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
+       0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+       0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
+       0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
+};
+
+
+/*
+ * Creates non-inverted ECC code from line parity
+ */
+static void nand_trans_result(u_char reg2, u_char reg3,
+       u_char *ecc_code)
+{
+       u_char a, b, i, tmp1, tmp2;
+
+       /* Initialize variables */
+       a = b = 0x80;
+       tmp1 = tmp2 = 0;
+
+       /* Calculate first ECC byte */
+       for (i = 0; i < 4; i++) {
+               if (reg3 & a)           /* LP15,13,11,9 --> ecc_code[0] */
+                       tmp1 |= b;
+               b >>= 1;
+               if (reg2 & a)           /* LP14,12,10,8 --> ecc_code[0] */
+                       tmp1 |= b;
+               b >>= 1;
+               a >>= 1;
+       }
+
+       /* Calculate second ECC byte */
+       b = 0x80;
+       for (i = 0; i < 4; i++) {
+               if (reg3 & a)           /* LP7,5,3,1 --> ecc_code[1] */
+                       tmp2 |= b;
+               b >>= 1;
+               if (reg2 & a)           /* LP6,4,2,0 --> ecc_code[1] */
+                       tmp2 |= b;
+               b >>= 1;
+               a >>= 1;
+       }
+
+       /* Store two of the ECC bytes */
+       ecc_code[0] = tmp1;
+       ecc_code[1] = tmp2;
+}
+
+/*
+ * Calculate 3 byte ECC code for 256 byte block
+ */
+static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code)
+{
+       u_char idx, reg1, reg3;
+       int j;
+
+       /* Initialize variables */
+       reg1 = reg3 = 0;
+       ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
+
+       /* Build up column parity */
+       for(j = 0; j < 256; j++) {
+
+               /* Get CP0 - CP5 from table */
+               idx = nand_ecc_precalc_table[dat[j]];
+               reg1 ^= idx;
+
+               /* All bit XOR = 1 ? */
+               if (idx & 0x40) {
+                       reg3 ^= (u_char) j;
+               }
+       }
+
+       /* Create non-inverted ECC code from line parity */
+       nand_trans_result((reg1 & 0x40) ? ~reg3 : reg3, reg3, ecc_code);
+
+       /* Calculate final ECC code */
+       ecc_code[0] = ~ecc_code[0];
+       ecc_code[1] = ~ecc_code[1];
+       ecc_code[2] = ((~reg1) << 2) | 0x03;
+}
+
+/*
+ * Detect and correct a 1 bit error for 256 byte block
+ */
+static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc)
+{
+       u_char a, b, c, d1, d2, d3, add, bit, i;
+
+       /* Do error detection */
+       d1 = calc_ecc[0] ^ read_ecc[0];
+       d2 = calc_ecc[1] ^ read_ecc[1];
+       d3 = calc_ecc[2] ^ read_ecc[2];
+
+       if ((d1 | d2 | d3) == 0) {
+               /* No errors */
+               return 0;
+       } else {
+               a = (d1 ^ (d1 >> 1)) & 0x55;
+               b = (d2 ^ (d2 >> 1)) & 0x55;
+               c = (d3 ^ (d3 >> 1)) & 0x54;
+
+               /* Found and will correct single bit error in the data */
+               if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {
+                       c = 0x80;
+                       add = 0;
+                       a = 0x80;
+                       for (i=0; i<4; i++) {
+                               if (d1 & c)
+                                       add |= a;
+                               c >>= 2;
+                               a >>= 1;
+                       }
+                       c = 0x80;
+                       for (i=0; i<4; i++) {
+                               if (d2 & c)
+                                       add |= a;
+                               c >>= 2;
+                               a >>= 1;
+                       }
+                       bit = 0;
+                       b = 0x04;
+                       c = 0x80;
+                       for (i=0; i<3; i++) {
+                               if (d3 & c)
+                                       bit |= b;
+                               c >>= 2;
+                               b >>= 1;
+                       }
+                       b = 0x01;
+                       a = dat[add];
+                       a ^= (b << bit);
+                       dat[add] = a;
+                       return 1;
+               }
+               else {
+                       i = 0;
+                       while (d1) {
+                               if (d1 & 0x01)
+                                       ++i;
+                               d1 >>= 1;
+                       }
+                       while (d2) {
+                               if (d2 & 0x01)
+                                       ++i;
+                               d2 >>= 1;
+                       }
+                       while (d3) {
+                               if (d3 & 0x01)
+                                       ++i;
+                               d3 >>= 1;
+                       }
+                       if (i == 1) {
+                               /* ECC Code Error Correction */
+                               read_ecc[0] = calc_ecc[0];
+                               read_ecc[1] = calc_ecc[1];
+                               read_ecc[2] = calc_ecc[2];
+                               return 2;
+                       }
+                       else {
+                               /* Uncorrectable Error */
+                               return -1;
+                       }
+               }
+       }
+
+       /* Should never happen */
+       return -1;
+}
+
+#endif
+
+#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
index f1156481d4c6ea02183942b14a1841b43d7f6092..6361d06d200a77ed293be63eede3d76e351fe233 100644 (file)
 /* keeps pointer to currentlu processed partition */
 static struct part_info *current_part;
 
-#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CONFIG_NEW_NAND_CODE)
+#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)
+#include <nand.h>
 /*
  * Support for jffs2 on top of NAND-flash
  *
@@ -154,9 +155,8 @@ static struct part_info *current_part;
  *
  */
 
-/* this one defined in cmd_nand.c */
-int read_jffs2_nand(size_t start, size_t len,
-                   size_t * retlen, u_char * buf, int nanddev);
+/* info for NAND chips, defined in drivers/nand/nand.c */
+extern nand_info_t nand_info[];
 
 #define NAND_PAGE_SIZE 512
 #define NAND_PAGE_SHIFT 9
@@ -167,6 +167,7 @@ int read_jffs2_nand(size_t start, size_t len,
 #endif
 #define NAND_CACHE_SIZE (NAND_CACHE_PAGES*NAND_PAGE_SIZE)
 
+#ifdef CFG_NAND_LEGACY
 static u8* nand_cache = NULL;
 static u32 nand_cache_off = (u32)-1;
 
@@ -174,7 +175,7 @@ static int read_nand_cached(u32 off, u32 size, u_char *buf)
 {
        struct mtdids *id = current_part->dev->id;
        u32 bytes_read = 0;
-       size_t retlen;
+       ulong retlen;
        int cpy_bytes;
 
        while (bytes_read < size) {
@@ -191,8 +192,10 @@ static int read_nand_cached(u32 off, u32 size, u_char *buf)
                                        return -1;
                                }
                        }
-                       if (read_jffs2_nand(nand_cache_off, NAND_CACHE_SIZE,
-                                               &retlen, nand_cache, id->num) < 0 ||
+
+                       retlen = NAND_CACHE_SIZE;
+                       if (nand_read(&nand_info[id->num], nand_cache_off,
+                                       &retlen, nand_cache) != 0 ||
                                        retlen != NAND_CACHE_SIZE) {
                                printf("read_nand_cached: error reading nand off %#x size %d bytes\n",
                                                nand_cache_off, NAND_CACHE_SIZE);
@@ -248,6 +251,7 @@ static void put_fl_mem_nand(void *buf)
 {
        free(buf);
 }
+#endif /* CFG_NAND_LEGACY */
 #endif /* #if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) */
 
 
@@ -290,7 +294,7 @@ static inline void *get_fl_mem(u32 off, u32 size, void *ext_buf)
                return get_fl_mem_nor(off);
 #endif
 
-#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CONFIG_NEW_NAND_CODE)
+#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) && defined(CFG_NAND_LEGACY)
        if (id->type == MTD_DEV_TYPE_NAND)
                return get_fl_mem_nand(off, size, ext_buf);
 #endif
@@ -308,7 +312,7 @@ static inline void *get_node_mem(u32 off)
                return get_node_mem_nor(off);
 #endif
 
-#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CONFIG_NEW_NAND_CODE)
+#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) && defined(CFG_NAND_LEGACY)
        if (id->type == MTD_DEV_TYPE_NAND)
                return get_node_mem_nand(off);
 #endif
@@ -319,7 +323,7 @@ static inline void *get_node_mem(u32 off)
 
 static inline void put_fl_mem(void *buf)
 {
-#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CONFIG_NEW_NAND_CODE)
+#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) && defined(CFG_NAND_LEGACY)
        struct mtdids *id = current_part->dev->id;
 
        if (id->type == MTD_DEV_TYPE_NAND)
index e5c2a7dd4129bd1310309c78a9eb74287311c666..e78af7578b6a7d712d5f962e0999aa1c6de6e08f 100644 (file)
@@ -1,6 +1,6 @@
 #include <common.h>
 
-#if defined(CONFIG_NEW_NAND_CODE) && (CONFIG_COMMANDS & CFG_CMD_JFFS2)
+#if !defined(CFG_NAND_LEGACY) && (CONFIG_COMMANDS & CFG_CMD_JFFS2)
 
 #include <malloc.h>
 #include <linux/stat.h>
index 9841893899adc1d5fa426a65f1d49c44de64c70b..d03c05bf349fd141f95d5711aa82a50ac57e62ff 100644 (file)
  * NAND-FLASH stuff
  *-----------------------------------------------------------------------
  */
+
+#define CFG_NAND_LEGACY
+
 #define CFG_MAX_NAND_DEVICE    1       /* Max number of NAND devices           */
 #define SECTORSIZE 512
 
index 050054d274c7ee3dd2b22fceb8b7dfe0a3dcdd6d..3bd43d836930aaaee01924ea3bc3d367b663cec6 100644 (file)
                                CFG_CMD_DOC     | \
                                CFG_CMD_ELF     | \
                                0 )
+
+/* CFG_CMD_DOC required legacy NAND support */
+#define CFG_NAND_LEGACY
+
 #if 0
 #define CONFIG_COMMANDS                (CONFIG_CMD_DFL | CFG_CMD_DHCP | \
                                 CFG_CMD_PCI | CFG_CMD_DOC | CFG_CMD_DATE)
index 6025886e3eaf63eee1a03871e402862e31dc11d8..1cca2859f4ba8dc4f2d45a10244619490825c0cc 100644 (file)
@@ -81,6 +81,8 @@
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 #undef CONFIG_WATCHDOG                 /* watchdog disabled            */
 
 #define CONFIG_SDRAM_BANK0     1       /* init onboard SDRAM bank 0    */
index efc3adaece2121d0a71fbf557b75b5597ee2e81d..047e2f1eef9cc57f7a5ba6517de8cf828d2f358b 100644 (file)
@@ -79,6 +79,8 @@
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 #undef CONFIG_WATCHDOG                 /* watchdog disabled            */
 
 #define CONFIG_SDRAM_BANK0     1       /* init onboard SDRAM bank 0    */
index 1347f2afcaee28369df823bf805c2fc13f663837..d756f447f7faed06880c80c343de219f93b836de 100644 (file)
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 #undef CONFIG_WATCHDOG                 /* watchdog disabled            */
 
 #define CONFIG_SDRAM_BANK0     1       /* init onboard SDRAM bank 0    */
index 9d52815092fa5b7cd2cdbb6faa210fde80f5d74d..852d94a410ac8a45de3b0a8daaf110fa0de9559d 100644 (file)
@@ -87,6 +87,9 @@
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
+
 #undef CONFIG_WATCHDOG                 /* watchdog disabled            */
 
 #define CONFIG_SDRAM_BANK0     1       /* init onboard SDRAM bank 0    */
index 946a0fd194583b396c78c841b71b4bc505b2d003..2260327c3f855ba88a3429695bae0b7c875abe20 100644 (file)
@@ -98,6 +98,8 @@
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 #undef CONFIG_WATCHDOG                 /* watchdog disabled            */
 
 #define CONFIG_SDRAM_BANK0     1       /* init onboard SDRAM bank 0    */
index 16a9ea5dd710db9aae16ea1bf2ceeff1d0f26866..1e9a99eed33e9e50640fa76e29e5ca0c730cf16d 100644 (file)
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 /*
  * Miscellaneous configurable options
  */
index a23d7e50b7bda3f2b64523ac223a08ec8a522291..9a98e5c191e183b5323731a4f9761d9eb12773e4 100644 (file)
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 /*
  * Miscellaneous configurable options
  */
index de8f7ae7112d6f02c19b202fcf83990324ce408d..6613f90a770075547700e0cfd12c08d5fc0023b6 100644 (file)
  */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 /*
  * Verbose help from command monitor.
  */
index 131c21555d3e674fefddb0ccf6556611e56e9555..41a35d2c53cc07650054643da20d10fdb031d639 100644 (file)
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 #undef  CONFIG_BZIP2    /* include support for bzip2 compressed images */
 #undef  CONFIG_WATCHDOG                        /* watchdog disabled            */
 
index eb627e881dd50883e826c5e78bebf3da1dfcb8f9..f84e356216bd9a0e941872f9739a01a7e29d9099 100644 (file)
  * NAND-FLASH stuff
  *-----------------------------------------------------------------------
  */
+#define CFG_NAND_LEGACY
+
 #define CFG_MAX_NAND_DEVICE    1       /* Max number of NAND devices           */
 #define SECTORSIZE 512
 
index db2147b481a4467a2559847804c37703482dbfc8..1f01e7be0b0a3711450b2e824e27df4ff23fbde2 100644 (file)
@@ -87,6 +87,8 @@
 /* this must be included AFTER the definition of CONFIG_COMMANDS  (if any) */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 #define         CFG_HUSH_PARSER
 #define         CFG_PROMPT_HUSH_PS2 "> "
 /**************************************************************
index bf4c899592fed76a4f9000b9a37d0d6ce2ac5479..444f721cc85a847bfdf704002a49ebae75043b80 100644 (file)
 /****************************************************************/
 
 /* NAND */
+#define CFG_NAND_LEGACY
 #define CFG_NAND_BASE          NAND_BASE
 #define CONFIG_MTD_NAND_ECC_JFFS2
 #define CONFIG_MTD_NAND_VERIFY_WRITE
index 529cb4cbae2e2b34af3a5681028113f3882bd311..e20e72495ccbc8dce1602f8817690d9ae9684601 100644 (file)
 /****************************************************************/
 
 /* NAND */
+#define CFG_NAND_LEGACY
 #define CFG_NAND_BASE          NAND_BASE
 #define CONFIG_MTD_NAND_ECC_JFFS2
 #define CONFIG_MTD_NAND_VERIFY_WRITE
index dc6b15fcdc492c0aec9efe55c54811370cd77525..e30be0987aa47619863424afe90229304ad54c25 100644 (file)
 
 /*****************************************************************************/
 
+#define CFG_NAND_LEGACY
+
 #if defined(CONFIG_NETVIA_VERSION) && CONFIG_NETVIA_VERSION >= 2
 
 /* NAND */
index d03706e19365c667b59e4dea8f10e024ff589a60..3a97fbcbde84056918ad52d625c72fe2a966b2a5 100644 (file)
@@ -77,6 +77,7 @@
  */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
 
 /*
  * Miscellaneous configurable options
index 92b2f7cf839753744ad936ea9b7ce1b951be41b7..130beb78e637682ed35a69ba5dcd9150e9fcf779 100644 (file)
@@ -79,6 +79,7 @@
  */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
 
 /*
  * Miscellaneous configurable options
index 9668fb0ce2fc919372e0e03ff948eef9ac33a805..091b768a99203d5e23fc73ed315d8a3ea6a362bb 100644 (file)
@@ -69,6 +69,8 @@
 /* this must be included AFTER the definition of CONFIG_COMMANDS  (if any) */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 #define         CFG_HUSH_PARSER
 #define         CFG_PROMPT_HUSH_PS2 "> "
 /**************************************************************
index 54ecfa4c5e31e32c04b91d48c99a0b3930242e51..dd5d83168042f121c85a6c7938e2234bfabcb2d9 100644 (file)
  * NAND-FLASH stuff
  *-----------------------------------------------------------------------
  */
+#define CFG_NAND_LEGACY
+
 #define CFG_MAX_NAND_DEVICE    1       /* Max number of NAND devices           */
 #define SECTORSIZE 512
 
index e73ad5100c2ea5a7c20b60afc62bfdfe3ce7f20a..9c241e67e732359d1f2568f3a1d6006f0b03d53e 100644 (file)
 #define ADD_DOC_CMD             0
 #else
 #define ADD_DOC_CMD             CFG_CMD_DOC
+/* DoC requires legacy NAND for now */
+#define CFG_NAND_LEGACY
 #endif
 
 /*
index 6e5e3bbe18cf29334fced893fe9c6db6e10b5ae0..88fdb51adef553924a89c326cd81454170ab6c8b 100644 (file)
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 /*
  * Disk-On-Chip configuration
  */
index 982a1f814301a57cbbb27b2937137cb390758e81..37ee9771b52fa5c3b57ef27c2d7b98a765734b64 100644 (file)
 /*
  * Disk-On-Chip configuration
  */
+#define CFG_NAND_LEGACY
 
 #define CFG_DOC_SHORT_TIMEOUT
 #define CFG_MAX_DOC_DEVICE     1       /* Max number of DOC devices    */
index c406c8f4bc17d5f1593caa82267c639e41005ccd..88e6db491bfd3720f23daf8765d97f49626510fa 100644 (file)
  * NAND-FLASH stuff
  *-----------------------------------------------------------------------
  */
+/*
+ * nand device 1 on dave (PPChameleonEVB) needs more time,
+ * so we just introduce additional wait in nand_wait(),
+ * effectively for both devices.
+ */
+#define PPCHAMELON_NAND_TIMER_HACK
 
-/* Use the new NAND code. (BOARDLIBS = drivers/nand/libnand.a required) */
-#define CONFIG_NEW_NAND_CODE
 #define CFG_NAND0_BASE 0xFF400000
 #define CFG_NAND1_BASE 0xFF000000
 #define CFG_NAND_BASE_LIST     { CFG_NAND0_BASE, CFG_NAND1_BASE }
 #define NAND_BIG_DELAY_US      25
 #define CFG_MAX_NAND_DEVICE    2       /* Max number of NAND devices */
-#define SECTORSIZE 512
-#define NAND_NO_RB
 
-#define ADDR_COLUMN 1
-#define ADDR_PAGE 2
-#define ADDR_COLUMN_PAGE 3
-
-#define NAND_ChipID_UNKNOWN    0x00
-#define NAND_MAX_FLOORS 1
 #define NAND_MAX_CHIPS 1
 
 #define CFG_NAND0_CE  (0x80000000 >> 1)         /* our CE is GPIO1 */
+#define CFG_NAND0_RDY (0x80000000 >> 4)         /* our RDY is GPIO4 */
 #define CFG_NAND0_CLE (0x80000000 >> 2)         /* our CLE is GPIO2 */
 #define CFG_NAND0_ALE (0x80000000 >> 3)         /* our ALE is GPIO3 */
-#define CFG_NAND0_RDY (0x80000000 >> 4)         /* our RDY is GPIO4 */
 
 #define CFG_NAND1_CE  (0x80000000 >> 14)  /* our CE is GPIO14 */
+#define CFG_NAND1_RDY (0x80000000 >> 31)  /* our RDY is GPIO31 */
 #define CFG_NAND1_CLE (0x80000000 >> 15)  /* our CLE is GPIO15 */
 #define CFG_NAND1_ALE (0x80000000 >> 16)  /* our ALE is GPIO16 */
-#define CFG_NAND1_RDY (0x80000000 >> 31)  /* our RDY is GPIO31 */
 
-#ifdef CONFIG_NEW_NAND_CODE
 #define MACRO_NAND_DISABLE_CE(nandptr) do \
 { \
        switch((unsigned long)nandptr) \
                break; \
        } \
 } while(0)
-#else
-#define NAND_DISABLE_CE(nand) do \
-{ \
-       switch((unsigned long)(((struct nand_chip *)nand)->IO_ADDR)) \
-       { \
-           case CFG_NAND0_BASE: \
-               out32(GPIO0_OR, in32(GPIO0_OR) | CFG_NAND0_CE); \
-               break; \
-           case CFG_NAND1_BASE: \
-               out32(GPIO0_OR, in32(GPIO0_OR) | CFG_NAND1_CE); \
-               break; \
-       } \
-} while(0)
 
-#define NAND_ENABLE_CE(nand) do \
-{ \
-       switch((unsigned long)(((struct nand_chip *)nand)->IO_ADDR)) \
-       { \
-           case CFG_NAND0_BASE: \
-               out32(GPIO0_OR, in32(GPIO0_OR) & ~CFG_NAND0_CE); \
-               break; \
-           case CFG_NAND1_BASE: \
-               out32(GPIO0_OR, in32(GPIO0_OR) & ~CFG_NAND1_CE); \
-               break; \
-       } \
-} while(0)
+#if 0
+#define SECTORSIZE 512
+#define NAND_NO_RB
 
-#define NAND_CTL_CLRALE(nandptr) do \
-{ \
-       switch((unsigned long)nandptr) \
-       { \
-           case CFG_NAND0_BASE: \
-               out32(GPIO0_OR, in32(GPIO0_OR) & ~CFG_NAND0_ALE); \
-               break; \
-           case CFG_NAND1_BASE: \
-               out32(GPIO0_OR, in32(GPIO0_OR) & ~CFG_NAND1_ALE); \
-               break; \
-       } \
-} while(0)
+#define ADDR_COLUMN 1
+#define ADDR_PAGE 2
+#define ADDR_COLUMN_PAGE 3
 
-#define NAND_CTL_SETALE(nandptr) do \
-{ \
-       switch((unsigned long)nandptr) \
-       { \
-           case CFG_NAND0_BASE: \
-               out32(GPIO0_OR, in32(GPIO0_OR) | CFG_NAND0_ALE); \
-               break; \
-           case CFG_NAND1_BASE: \
-               out32(GPIO0_OR, in32(GPIO0_OR) | CFG_NAND1_ALE); \
-               break; \
-       } \
-} while(0)
+#define NAND_ChipID_UNKNOWN    0x00
+#define NAND_MAX_FLOORS 1
 
-#define NAND_CTL_CLRCLE(nandptr) do \
-{ \
-       switch((unsigned long)nandptr) \
-       { \
-           case CFG_NAND0_BASE: \
-               out32(GPIO0_OR, in32(GPIO0_OR) & ~CFG_NAND0_CLE); \
-               break; \
-           case CFG_NAND1_BASE: \
-               out32(GPIO0_OR, in32(GPIO0_OR) & ~CFG_NAND1_CLE); \
-               break; \
-       } \
-} while(0)
 
-#define NAND_CTL_SETCLE(nandptr) do { \
-       switch((unsigned long)nandptr) { \
-       case CFG_NAND0_BASE: \
-               out32(GPIO0_OR, in32(GPIO0_OR) | CFG_NAND0_CLE); \
-               break; \
-       case CFG_NAND1_BASE: \
-               out32(GPIO0_OR, in32(GPIO0_OR) | CFG_NAND1_CLE); \
-               break; \
-       } \
-} while(0)
-#endif /* !CONFIG_NEW_NAND_CODE */
 
 #ifdef NAND_NO_RB
 /* constant delay (see also tR in the datasheet) */
 #define WRITE_NAND_ADDRESS(d, adr) do{ *(volatile __u8 *)((unsigned long)adr) = (__u8)(d); } while(0)
 #define WRITE_NAND(d, adr) do{ *(volatile __u8 *)((unsigned long)adr) = (__u8)d; } while(0)
 #define READ_NAND(adr) ((volatile unsigned char)(*(volatile __u8 *)(unsigned long)adr))
-
+#endif
 /*-----------------------------------------------------------------------
  * PCI stuff
  *-----------------------------------------------------------------------
index 242c837a3b86ab5be554761fa7cd130a18c9be8c..21945a343cd807436095812c71129ce2881fb5e2 100644 (file)
 /************************************************************
  * Disk-On-Chip configuration
  ************************************************************/
+#define CFG_NAND_LEGACY
+
 #define CFG_MAX_DOC_DEVICE     1       /* Max number of DOC devices            */
 #define CFG_DOC_SHORT_TIMEOUT
 #define CFG_DOC_SUPPORT_2000
index c1c765f39d000e11054924bc8ec58a460af5a475..a8454d99fc0a8fc450048d71cfdc044584aba679 100644 (file)
 */
 
 /* NAND flash support */
+#define CFG_NAND_LEGACY
 #define CONFIG_MTD_NAND_ECC_JFFS2
 #define CFG_MAX_NAND_DEVICE    1       /* Max number of NAND devices   */
 #define SECTORSIZE 512
index 3ca137e53aca281879073e572b2fc476986ee83e..96f3d26cc5eea997c1406a525222030180ac36ba 100644 (file)
  * NAND-FLASH stuff
  *-----------------------------------------------------------------------
  */
+#define CFG_NAND_LEGACY
+
 #define CFG_MAX_NAND_DEVICE    1       /* Max number of NAND devices           */
 #define SECTORSIZE 512
 
index d92f81f78ee4f6784ef14f678174a0422ebbc6e1..faf855d2492c072fe238a4e978ac7fc7de7204e8 100644 (file)
  * NAND-FLASH stuff
  *-----------------------------------------------------------------------
  */
+#define CFG_NAND_LEGACY
+
 #define CFG_MAX_NAND_DEVICE    1       /* Max number of NAND devices           */
 #define SECTORSIZE 512
 
index eacc74446cebc27bb9a6e20b6c2769838252b731..6d3282150d7686dccebc503fb8b72a0dd8203a85 100644 (file)
@@ -43,6 +43,7 @@
  * 2nd ethernet port you have to "undef" the following define.
  */
 #define CONFIG_BAMBOO_NAND      1       /* enable nand flash support    */
+#define CFG_NAND_LEGACY
 
 /*-----------------------------------------------------------------------
  * Base addresses -- Note these are effective addresses where the
index 30d2654732213b85896d49da880732c5b3f8dd1c..697796a11432c0709e80ccea1250054ca8a108aa 100644 (file)
  * NAND flash
  */
 #define CFG_MAX_NAND_DEVICE    1
+#define NAND_MAX_CHIPS         1
 #define CFG_NAND_BASE  0x04000000 + (2 << 23)
-#define CONFIG_NEW_NAND_CODE
 
 /*
  * JFFS2 partitions (mtdparts command line support)
index 7118f3f74be7380d94fa2ab527e82d7e5bab5f52..92ee8cb3331f961cdceb467ae582928292ec7f3e 100644 (file)
 
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
+#define CFG_NAND_LEGACY
 
 /*
  * Miscellaneous configurable options
index b0894c5e83d474dc29133474dbe7c89cd5afb863..c105ecc3acb26c30e9389de49f9b611df5a2b647 100644 (file)
@@ -2,10 +2,10 @@
  *  linux/include/linux/mtd/nand.h
  *
  *  Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com>
- *                     Steven J. Hill <sjhill@cotw.com>
- *                    Thomas Gleixner <gleixner@autronix.de>
+ *                     Steven J. Hill <sjhill@realitydiluted.com>
+ *                    Thomas Gleixner <tglx@linutronix.de>
  *
- * $Id: nand.h,v 1.7 2003/07/24 23:30:46 a0384864 Exp $
+ * $Id: nand.h,v 1.68 2004/11/12 10:40:37 gleixner Exp $
  *
  * 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
  *                     command delay times for different chips
  *   04-28-2002 TG     OOB config defines moved from nand.c to avoid duplicate
  *                     defines in jffs2/wbuf.c
+ *   08-07-2002 TG     forced bad block location to byte 5 of OOB, even if
+ *                     CONFIG_MTD_NAND_ECC_JFFS2 is not set
+ *   08-10-2002 TG     extensions to nand_chip structure to support HW-ECC
+ *
+ *   08-29-2002 tglx   nand_chip structure: data_poi for selecting
+ *                     internal / fs-driver buffer
+ *                     support for 6byte/512byte hardware ECC
+ *                     read_ecc, write_ecc extended for different oob-layout
+ *                     oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB,
+ *                     NAND_YAFFS_OOB
+ *  11-25-2002 tglx    Added Manufacturer code FUJITSU, NATIONAL
+ *                     Split manufacturer and device ID structures
+ *
+ *  02-08-2004 tglx    added option field to nand structure for chip anomalities
+ *  05-25-2004 tglx    added bad block table support, ST-MICRO manufacturer id
+ *                     update of nand_chip structure description
  */
 #ifndef __LINUX_MTD_NAND_H
 #define __LINUX_MTD_NAND_H
 
-#ifdef CONFIG_NEW_NAND_CODE
-#include "nand_new.h"
-#else
+#include <linux/mtd/compat.h>
+#include <linux/mtd/mtd.h>
+
+struct mtd_info;
+/* Scan and identify a NAND device */
+extern int nand_scan (struct mtd_info *mtd, int max_chips);
+/* Free resources held by the NAND device */
+extern void nand_release (struct mtd_info *mtd);
+
+/* Read raw data from the device without ECC */
+extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen);
+
+
+
+/* This constant declares the max. oobsize / page, which
+ * is supported now. If you add a chip with bigger oobsize/page
+ * adjust this accordingly.
+ */
+#define NAND_MAX_OOBSIZE       64
+
+/*
+ * Constants for hardware specific CLE/ALE/NCE function
+*/
+/* Select the chip by setting nCE to low */
+#define NAND_CTL_SETNCE        1
+/* Deselect the chip by setting nCE to high */
+#define NAND_CTL_CLRNCE                2
+/* Select the command latch by setting CLE to high */
+#define NAND_CTL_SETCLE                3
+/* Deselect the command latch by setting CLE to low */
+#define NAND_CTL_CLRCLE                4
+/* Select the address latch by setting ALE to high */
+#define NAND_CTL_SETALE                5
+/* Deselect the address latch by setting ALE to low */
+#define NAND_CTL_CLRALE                6
+/* Set write protection by setting WP to high. Not used! */
+#define NAND_CTL_SETWP         7
+/* Clear write protection by setting WP to low. Not used! */
+#define NAND_CTL_CLRWP         8
+
 /*
  * Standard NAND flash commands
  */
 #define NAND_CMD_READOOB       0x50
 #define NAND_CMD_ERASE1                0x60
 #define NAND_CMD_STATUS                0x70
+#define NAND_CMD_STATUS_MULTI  0x71
 #define NAND_CMD_SEQIN         0x80
 #define NAND_CMD_READID                0x90
 #define NAND_CMD_ERASE2                0xd0
 #define NAND_CMD_RESET         0xff
 
+/* Extended commands for large page devices */
+#define NAND_CMD_READSTART     0x30
+#define NAND_CMD_CACHEDPROG    0x15
+
+/* Status bits */
+#define NAND_STATUS_FAIL       0x01
+#define NAND_STATUS_FAIL_N1    0x02
+#define NAND_STATUS_TRUE_READY 0x20
+#define NAND_STATUS_READY      0x40
+#define NAND_STATUS_WP         0x80
+
+/*
+ * Constants for ECC_MODES
+ */
+
+/* No ECC. Usage is not recommended ! */
+#define NAND_ECC_NONE          0
+/* Software ECC 3 byte ECC per 256 Byte data */
+#define NAND_ECC_SOFT          1
+/* Hardware ECC 3 byte ECC per 256 Byte data */
+#define NAND_ECC_HW3_256       2
+/* Hardware ECC 3 byte ECC per 512 Byte data */
+#define NAND_ECC_HW3_512       3
+/* Hardware ECC 3 byte ECC per 512 Byte data */
+#define NAND_ECC_HW6_512       4
+/* Hardware ECC 8 byte ECC per 512 Byte data */
+#define NAND_ECC_HW8_512       6
+/* Hardware ECC 12 byte ECC per 2048 Byte data */
+#define NAND_ECC_HW12_2048     7
+
 /*
+ * Constants for Hardware ECC
+*/
+/* Reset Hardware ECC for read */
+#define NAND_ECC_READ          0
+/* Reset Hardware ECC for write */
+#define NAND_ECC_WRITE         1
+/* Enable Hardware ECC before syndrom is read back from flash */
+#define NAND_ECC_READSYN       2
+
+/* Option constants for bizarre disfunctionality and real
+*  features
+*/
+/* Chip can not auto increment pages */
+#define NAND_NO_AUTOINCR       0x00000001
+/* Buswitdh is 16 bit */
+#define NAND_BUSWIDTH_16       0x00000002
+/* Device supports partial programming without padding */
+#define NAND_NO_PADDING                0x00000004
+/* Chip has cache program function */
+#define NAND_CACHEPRG          0x00000008
+/* Chip has copy back function */
+#define NAND_COPYBACK          0x00000010
+/* AND Chip which has 4 banks and a confusing page / block
+ * assignment. See Renesas datasheet for further information */
+#define NAND_IS_AND            0x00000020
+/* Chip has a array of 4 pages which can be read without
+ * additional ready /busy waits */
+#define NAND_4PAGE_ARRAY       0x00000040
+
+/* Options valid for Samsung large page devices */
+#define NAND_SAMSUNG_LP_OPTIONS \
+       (NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
+
+/* Macros to identify the above */
+#define NAND_CANAUTOINCR(chip) (!(chip->options & NAND_NO_AUTOINCR))
+#define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING))
+#define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG))
+#define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK))
+
+/* Mask to zero out the chip options, which come from the id table */
+#define NAND_CHIPOPTIONS_MSK   (0x0000ffff & ~NAND_NO_AUTOINCR)
+
+/* Non chip related options */
+/* Use a flash based bad block table. This option is passed to the
+ * default bad block table function. */
+#define NAND_USE_FLASH_BBT     0x00010000
+/* The hw ecc generator provides a syndrome instead a ecc value on read
+ * This can only work if we have the ecc bytes directly behind the
+ * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
+#define NAND_HWECC_SYNDROME    0x00020000
+
+
+/* Options set by nand scan */
+/* Nand scan has allocated oob_buf */
+#define NAND_OOBBUF_ALLOC      0x40000000
+/* Nand scan has allocated data_buf */
+#define NAND_DATABUF_ALLOC     0x80000000
+
+
+/*
+ * nand_state_t - chip states
  * Enumeration for NAND flash chip state
  */
 typedef enum {
@@ -61,71 +206,138 @@ typedef enum {
        FL_READING,
        FL_WRITING,
        FL_ERASING,
-       FL_SYNCING
+       FL_SYNCING,
+       FL_CACHEDPRG,
 } nand_state_t;
 
+/* Keep gcc happy */
+struct nand_chip;
 
-/*
- * NAND Private Flash Chip Data
- *
- * Structure overview:
- *
- *  IO_ADDR - address to access the 8 I/O lines of the flash device
- *
- *  hwcontrol - hardwarespecific function for accesing control-lines
- *
- *  dev_ready - hardwarespecific function for accesing device ready/busy line
- *
- *  chip_lock - spinlock used to protect access to this structure
- *
- *  wq - wait queue to sleep on if a NAND operation is in progress
- *
- *  state - give the current state of the NAND device
- *
- *  page_shift - number of address bits in a page (column address bits)
- *
- *  data_buf - data buffer passed to/from MTD user modules
- *
- *  data_cache - data cache for redundant page access and shadow for
- *              ECC failure
- *
- *  ecc_code_buf - used only for holding calculated or read ECCs for
- *                 a page read or written when ECC is in use
- *
- *  reserved - padding to make structure fall on word boundary if
- *             when ECC is in use
+#if 0
+/**
+ * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices
+ * @lock:               protection lock
+ * @active:            the mtd device which holds the controller currently
  */
-struct Nand {
-       char floor, chip;
-       unsigned long curadr;
-       unsigned char curmode;
-       /* Also some erase/write/pipeline info when we get that far */
+struct nand_hw_control {
+       spinlock_t       lock;
+       struct nand_chip *active;
 };
+#endif
+
+/**
+ * struct nand_chip - NAND Private Flash Chip Data
+ * @IO_ADDR_R:         [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
+ * @IO_ADDR_W:         [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
+ * @read_byte:         [REPLACEABLE] read one byte from the chip
+ * @write_byte:                [REPLACEABLE] write one byte to the chip
+ * @read_word:         [REPLACEABLE] read one word from the chip
+ * @write_word:                [REPLACEABLE] write one word to the chip
+ * @write_buf:         [REPLACEABLE] write data from the buffer to the chip
+ * @read_buf:          [REPLACEABLE] read data from the chip into the buffer
+ * @verify_buf:                [REPLACEABLE] verify buffer contents against the chip data
+ * @select_chip:       [REPLACEABLE] select chip nr
+ * @block_bad:         [REPLACEABLE] check, if the block is bad
+ * @block_markbad:     [REPLACEABLE] mark the block bad
+ * @hwcontrol:         [BOARDSPECIFIC] hardwarespecific function for accesing control-lines
+ * @dev_ready:         [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
+ *                     If set to NULL no access to ready/busy is available and the ready/busy information
+ *                     is read from the chip status register
+ * @cmdfunc:           [REPLACEABLE] hardwarespecific function for writing commands to the chip
+ * @waitfunc:          [REPLACEABLE] hardwarespecific function for wait on ready
+ * @calculate_ecc:     [REPLACEABLE] function for ecc calculation or readback from ecc hardware
+ * @correct_data:      [REPLACEABLE] function for ecc correction, matching to ecc generator (sw/hw)
+ * @enable_hwecc:      [BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
+ *                     be provided if a hardware ECC is available
+ * @erase_cmd:         [INTERN] erase command write function, selectable due to AND support
+ * @scan_bbt:          [REPLACEABLE] function to scan bad block table
+ * @eccmode:           [BOARDSPECIFIC] mode of ecc, see defines
+ * @eccsize:           [INTERN] databytes used per ecc-calculation
+ * @eccbytes:          [INTERN] number of ecc bytes per ecc-calculation step
+ * @eccsteps:          [INTERN] number of ecc calculation steps per page
+ * @chip_delay:                [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
+ * @chip_lock:         [INTERN] spinlock used to protect access to this structure and the chip
+ * @wq:                        [INTERN] wait queue to sleep on if a NAND operation is in progress
+ * @state:             [INTERN] the current state of the NAND device
+ * @page_shift:                [INTERN] number of address bits in a page (column address bits)
+ * @phys_erase_shift:  [INTERN] number of address bits in a physical eraseblock
+ * @bbt_erase_shift:   [INTERN] number of address bits in a bbt entry
+ * @chip_shift:                [INTERN] number of address bits in one chip
+ * @data_buf:          [INTERN] internal buffer for one page + oob
+ * @oob_buf:           [INTERN] oob buffer for one eraseblock
+ * @oobdirty:          [INTERN] indicates that oob_buf must be reinitialized
+ * @data_poi:          [INTERN] pointer to a data buffer
+ * @options:           [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
+ *                     special functionality. See the defines for further explanation
+ * @badblockpos:       [INTERN] position of the bad block marker in the oob area
+ * @numchips:          [INTERN] number of physical chips
+ * @chipsize:          [INTERN] the size of one chip for multichip arrays
+ * @pagemask:          [INTERN] page number mask = number of (pages / chip) - 1
+ * @pagebuf:           [INTERN] holds the pagenumber which is currently in data_buf
+ * @autooob:           [REPLACEABLE] the default (auto)placement scheme
+ * @bbt:               [INTERN] bad block table pointer
+ * @bbt_td:            [REPLACEABLE] bad block table descriptor for flash lookup
+ * @bbt_md:            [REPLACEABLE] bad block table mirror descriptor
+ * @badblock_pattern:  [REPLACEABLE] bad block scan pattern used for initial bad block scan
+ * @controller:                [OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices
+ * @priv:              [OPTIONAL] pointer to private chip date
+ */
 
 struct nand_chip {
+       void  __iomem   *IO_ADDR_R;
+       void  __iomem   *IO_ADDR_W;
+
+       u_char          (*read_byte)(struct mtd_info *mtd);
+       void            (*write_byte)(struct mtd_info *mtd, u_char byte);
+       u16             (*read_word)(struct mtd_info *mtd);
+       void            (*write_word)(struct mtd_info *mtd, u16 word);
+
+       void            (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
+       void            (*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
+       int             (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);
+       void            (*select_chip)(struct mtd_info *mtd, int chip);
+       int             (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
+       int             (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
+       void            (*hwcontrol)(struct mtd_info *mtd, int cmd);
+       int             (*dev_ready)(struct mtd_info *mtd);
+       void            (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
+       int             (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
+       int             (*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
+       int             (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
+       void            (*enable_hwecc)(struct mtd_info *mtd, int mode);
+       void            (*erase_cmd)(struct mtd_info *mtd, int page);
+       int             (*scan_bbt)(struct mtd_info *mtd);
+       int             eccmode;
+       int             eccsize;
+       int             eccbytes;
+       int             eccsteps;
+       int             chip_delay;
+#if 0
+       spinlock_t      chip_lock;
+       wait_queue_head_t wq;
+       nand_state_t    state;
+#endif
        int             page_shift;
+       int             phys_erase_shift;
+       int             bbt_erase_shift;
+       int             chip_shift;
        u_char          *data_buf;
-       u_char          *data_cache;
-       int             cache_page;
-       u_char          ecc_code_buf[6];
-       u_char          reserved[2];
-       char ChipID; /* Type of DiskOnChip */
-       struct Nand *chips;
-       int chipshift;
-       char* chips_name;
-       unsigned long erasesize;
-       unsigned long mfr; /* Flash IDs - only one type of flash per device */
-       unsigned long id;
-       char* name;
-       int numchips;
-       char page256;
-       char pageadrlen;
-       unsigned long IO_ADDR;  /* address to access the 8 I/O lines to the flash device */
-       unsigned long totlen;
-       uint oobblock;  /* Size of OOB blocks (e.g. 512) */
-       uint oobsize;   /* Amount of OOB data per block (e.g. 16) */
-       uint eccsize;
-       int bus16;
+       u_char          *oob_buf;
+       int             oobdirty;
+       u_char          *data_poi;
+       unsigned int    options;
+       int             badblockpos;
+       int             numchips;
+       unsigned long   chipsize;
+       int             pagemask;
+       int             pagebuf;
+       struct nand_oobinfo     *autooob;
+       uint8_t         *bbt;
+       struct nand_bbt_descr   *bbt_td;
+       struct nand_bbt_descr   *bbt_md;
+       struct nand_bbt_descr   *badblock_pattern;
+       struct nand_hw_control  *controller;
+       void            *priv;
 };
 
 /*
@@ -133,71 +345,125 @@ struct nand_chip {
  */
 #define NAND_MFR_TOSHIBA       0x98
 #define NAND_MFR_SAMSUNG       0xec
+#define NAND_MFR_FUJITSU       0x04
+#define NAND_MFR_NATIONAL      0x8f
+#define NAND_MFR_RENESAS       0x07
+#define NAND_MFR_STMICRO       0x20
 
-/*
- * NAND Flash Device ID Structure
- *
- * Structure overview:
- *
- *  name - Complete name of device
- *
- *  manufacture_id - manufacturer ID code of device.
- *
- *  model_id - model ID code of device.
- *
- *  chipshift - total number of address bits for the device which
- *              is used to calculate address offsets and the total
- *              number of bytes the device is capable of.
+/**
+ * struct nand_flash_dev - NAND Flash Device ID Structure
  *
- *  page256 - denotes if flash device has 256 byte pages or not.
- *
- *  pageadrlen - number of bytes minus one needed to hold the
- *               complete address into the flash array. Keep in
- *               mind that when a read or write is done to a
- *               specific address, the address is input serially
- *               8 bits at a time. This structure member is used
- *               by the read/write routines as a loop index for
- *               shifting the address out 8 bits at a time.
- *
- *  erasesize - size of an erase block in the flash device.
+ * @name:      Identify the device type
+ * @id:        device ID code
+ * @pagesize:          Pagesize in bytes. Either 256 or 512 or 0
+ *             If the pagesize is 0, then the real pagesize
+ *             and the eraseize are determined from the
+ *             extended id bytes in the chip
+ * @erasesize:         Size of an erase block in the flash device.
+ * @chipsize:          Total chipsize in Mega Bytes
+ * @options:   Bitfield to store chip relevant options
  */
 struct nand_flash_dev {
-       char * name;
-       int manufacture_id;
-       int model_id;
-       int chipshift;
-       char page256;
-       char pageadrlen;
+       char *name;
+       int id;
+       unsigned long pagesize;
+       unsigned long chipsize;
        unsigned long erasesize;
-       int bus16;
+       unsigned long options;
 };
 
+/**
+ * struct nand_manufacturers - NAND Flash Manufacturer ID Structure
+ * @name:      Manufacturer name
+ * @id:        manufacturer ID code of device.
+*/
+struct nand_manufacturers {
+       int id;
+       char * name;
+};
+
+extern struct nand_flash_dev nand_flash_ids[];
+extern struct nand_manufacturers nand_manuf_ids[];
+
+/**
+ * struct nand_bbt_descr - bad block table descriptor
+ * @options:   options for this descriptor
+ * @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
+ * @offs:      offset of the pattern in the oob area of the page
+ * @veroffs:   offset of the bbt version counter in the oob are of the page
+ * @version:   version read from the bbt page during scan
+ * @len:       length of the pattern, if 0 no pattern check is performed
+ * @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.
+ * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than
+ *              bad) block in the stored bbt
+ * @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
+
+extern int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd);
+extern int nand_update_bbt (struct mtd_info *mtd, loff_t offs);
+extern int nand_default_bbt (struct mtd_info *mtd);
+extern int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt);
+extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt);
+
 /*
 * Constants for oob configuration
 */
-#define NAND_NOOB_ECCPOS0              0
-#define NAND_NOOB_ECCPOS1              1
-#define NAND_NOOB_ECCPOS2              2
-#define NAND_NOOB_ECCPOS3              3
-#define NAND_NOOB_ECCPOS4              6
-#define NAND_NOOB_ECCPOS5              7
-#define NAND_NOOB_BADBPOS              -1
-#define NAND_NOOB_ECCVPOS              -1
-
-#define NAND_JFFS2_OOB_ECCPOS0         0
-#define NAND_JFFS2_OOB_ECCPOS1         1
-#define NAND_JFFS2_OOB_ECCPOS2         2
-#define NAND_JFFS2_OOB_ECCPOS3         3
-#define NAND_JFFS2_OOB_ECCPOS4         6
-#define NAND_JFFS2_OOB_ECCPOS5         7
-#define NAND_JFFS2_OOB_BADBPOS         5
-#define NAND_JFFS2_OOB_ECCVPOS         4
-
-#define NAND_JFFS2_OOB8_FSDAPOS                6
-#define NAND_JFFS2_OOB16_FSDAPOS       8
-#define NAND_JFFS2_OOB8_FSDALEN                2
-#define NAND_JFFS2_OOB16_FSDALEN       8
-
-unsigned long nand_probe(unsigned long physadr);
-#endif /* !CONFIG_NEW_NAND_CODE */
+#define NAND_SMALL_BADBLOCK_POS                5
+#define NAND_LARGE_BADBLOCK_POS                0
+
 #endif /* __LINUX_MTD_NAND_H */
index 75c305b569fdc57e6edccd2e469ddf8631a8af5d..d9eb9118280753ad6b93d3c6740f163b30665119 100644 (file)
 #ifndef __LINUX_MTD_NAND_IDS_H
 #define __LINUX_MTD_NAND_IDS_H
 
+#ifndef CFG_NAND_LEGACY
+#error This module is for the legacy NAND support
+#endif
+
 static struct nand_flash_dev nand_flash_ids[] = {
        {"Toshiba TC5816BDC",     NAND_MFR_TOSHIBA, 0x64, 21, 1, 2, 0x1000, 0},
        {"Toshiba TC5832DC",      NAND_MFR_TOSHIBA, 0x6b, 22, 0, 2, 0x2000, 0},
diff --git a/include/linux/mtd/nand_legacy.h b/include/linux/mtd/nand_legacy.h
new file mode 100644 (file)
index 0000000..a8769e7
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ *  linux/include/linux/mtd/nand.h
+ *
+ *  Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com>
+ *                     Steven J. Hill <sjhill@cotw.com>
+ *                    Thomas Gleixner <gleixner@autronix.de>
+ *
+ * $Id: nand.h,v 1.7 2003/07/24 23:30:46 a0384864 Exp $
+ *
+ * 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.
+ *
+ *  Info:
+ *   Contains standard defines and IDs for NAND flash devices
+ *
+ *  Changelog:
+ *   01-31-2000 DMW     Created
+ *   09-18-2000 SJH     Moved structure out of the Disk-On-Chip drivers
+ *                     so it can be used by other NAND flash device
+ *                     drivers. I also changed the copyright since none
+ *                     of the original contents of this file are specific
+ *                     to DoC devices. David can whack me with a baseball
+ *                     bat later if I did something naughty.
+ *   10-11-2000 SJH     Added private NAND flash structure for driver
+ *   10-24-2000 SJH     Added prototype for 'nand_scan' function
+ *   10-29-2001 TG     changed nand_chip structure to support
+ *                     hardwarespecific function for accessing control lines
+ *   02-21-2002 TG     added support for different read/write adress and
+ *                     ready/busy line access function
+ *   02-26-2002 TG     added chip_delay to nand_chip structure to optimize
+ *                     command delay times for different chips
+ *   04-28-2002 TG     OOB config defines moved from nand.c to avoid duplicate
+ *                     defines in jffs2/wbuf.c
+ */
+#ifndef __LINUX_MTD_NAND_LEGACY_H
+#define __LINUX_MTD_NAND_LEGACY_H
+
+#ifndef CFG_NAND_LEGACY
+#error This module is for the legacy NAND support
+#endif
+
+/*
+ * Standard NAND flash commands
+ */
+#define NAND_CMD_READ0         0
+#define NAND_CMD_READ1         1
+#define NAND_CMD_PAGEPROG      0x10
+#define NAND_CMD_READOOB       0x50
+#define NAND_CMD_ERASE1                0x60
+#define NAND_CMD_STATUS                0x70
+#define NAND_CMD_SEQIN         0x80
+#define NAND_CMD_READID                0x90
+#define NAND_CMD_ERASE2                0xd0
+#define NAND_CMD_RESET         0xff
+
+/*
+ * Enumeration for NAND flash chip state
+ */
+typedef enum {
+       FL_READY,
+       FL_READING,
+       FL_WRITING,
+       FL_ERASING,
+       FL_SYNCING
+} nand_state_t;
+
+
+/*
+ * NAND Private Flash Chip Data
+ *
+ * Structure overview:
+ *
+ *  IO_ADDR - address to access the 8 I/O lines of the flash device
+ *
+ *  hwcontrol - hardwarespecific function for accesing control-lines
+ *
+ *  dev_ready - hardwarespecific function for accesing device ready/busy line
+ *
+ *  chip_lock - spinlock used to protect access to this structure
+ *
+ *  wq - wait queue to sleep on if a NAND operation is in progress
+ *
+ *  state - give the current state of the NAND device
+ *
+ *  page_shift - number of address bits in a page (column address bits)
+ *
+ *  data_buf - data buffer passed to/from MTD user modules
+ *
+ *  data_cache - data cache for redundant page access and shadow for
+ *              ECC failure
+ *
+ *  ecc_code_buf - used only for holding calculated or read ECCs for
+ *                 a page read or written when ECC is in use
+ *
+ *  reserved - padding to make structure fall on word boundary if
+ *             when ECC is in use
+ */
+struct Nand {
+       char floor, chip;
+       unsigned long curadr;
+       unsigned char curmode;
+       /* Also some erase/write/pipeline info when we get that far */
+};
+
+struct nand_chip {
+       int             page_shift;
+       u_char          *data_buf;
+       u_char          *data_cache;
+       int             cache_page;
+       u_char          ecc_code_buf[6];
+       u_char          reserved[2];
+       char ChipID; /* Type of DiskOnChip */
+       struct Nand *chips;
+       int chipshift;
+       char* chips_name;
+       unsigned long erasesize;
+       unsigned long mfr; /* Flash IDs - only one type of flash per device */
+       unsigned long id;
+       char* name;
+       int numchips;
+       char page256;
+       char pageadrlen;
+       unsigned long IO_ADDR;  /* address to access the 8 I/O lines to the flash device */
+       unsigned long totlen;
+       uint oobblock;  /* Size of OOB blocks (e.g. 512) */
+       uint oobsize;   /* Amount of OOB data per block (e.g. 16) */
+       uint eccsize;
+       int bus16;
+};
+
+/*
+ * NAND Flash Manufacturer ID Codes
+ */
+#define NAND_MFR_TOSHIBA       0x98
+#define NAND_MFR_SAMSUNG       0xec
+
+/*
+ * NAND Flash Device ID Structure
+ *
+ * Structure overview:
+ *
+ *  name - Complete name of device
+ *
+ *  manufacture_id - manufacturer ID code of device.
+ *
+ *  model_id - model ID code of device.
+ *
+ *  chipshift - total number of address bits for the device which
+ *              is used to calculate address offsets and the total
+ *              number of bytes the device is capable of.
+ *
+ *  page256 - denotes if flash device has 256 byte pages or not.
+ *
+ *  pageadrlen - number of bytes minus one needed to hold the
+ *               complete address into the flash array. Keep in
+ *               mind that when a read or write is done to a
+ *               specific address, the address is input serially
+ *               8 bits at a time. This structure member is used
+ *               by the read/write routines as a loop index for
+ *               shifting the address out 8 bits at a time.
+ *
+ *  erasesize - size of an erase block in the flash device.
+ */
+struct nand_flash_dev {
+       char * name;
+       int manufacture_id;
+       int model_id;
+       int chipshift;
+       char page256;
+       char pageadrlen;
+       unsigned long erasesize;
+       int bus16;
+};
+
+/*
+* Constants for oob configuration
+*/
+#define NAND_NOOB_ECCPOS0              0
+#define NAND_NOOB_ECCPOS1              1
+#define NAND_NOOB_ECCPOS2              2
+#define NAND_NOOB_ECCPOS3              3
+#define NAND_NOOB_ECCPOS4              6
+#define NAND_NOOB_ECCPOS5              7
+#define NAND_NOOB_BADBPOS              -1
+#define NAND_NOOB_ECCVPOS              -1
+
+#define NAND_JFFS2_OOB_ECCPOS0         0
+#define NAND_JFFS2_OOB_ECCPOS1         1
+#define NAND_JFFS2_OOB_ECCPOS2         2
+#define NAND_JFFS2_OOB_ECCPOS3         3
+#define NAND_JFFS2_OOB_ECCPOS4         6
+#define NAND_JFFS2_OOB_ECCPOS5         7
+#define NAND_JFFS2_OOB_BADBPOS         5
+#define NAND_JFFS2_OOB_ECCVPOS         4
+
+#define NAND_JFFS2_OOB8_FSDAPOS                6
+#define NAND_JFFS2_OOB16_FSDAPOS       8
+#define NAND_JFFS2_OOB8_FSDALEN                2
+#define NAND_JFFS2_OOB16_FSDALEN       8
+
+unsigned long nand_probe(unsigned long physadr);
+#endif /* __LINUX_MTD_NAND_LEGACY_H */
diff --git a/include/linux/mtd/nand_new.h b/include/linux/mtd/nand_new.h
deleted file mode 100644 (file)
index 7d4b805..0000000
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- *  linux/include/linux/mtd/nand.h
- *
- *  Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com>
- *                     Steven J. Hill <sjhill@realitydiluted.com>
- *                    Thomas Gleixner <tglx@linutronix.de>
- *
- * $Id: nand.h,v 1.68 2004/11/12 10:40:37 gleixner Exp $
- *
- * 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.
- *
- *  Info:
- *   Contains standard defines and IDs for NAND flash devices
- *
- *  Changelog:
- *   01-31-2000 DMW     Created
- *   09-18-2000 SJH     Moved structure out of the Disk-On-Chip drivers
- *                     so it can be used by other NAND flash device
- *                     drivers. I also changed the copyright since none
- *                     of the original contents of this file are specific
- *                     to DoC devices. David can whack me with a baseball
- *                     bat later if I did something naughty.
- *   10-11-2000 SJH     Added private NAND flash structure for driver
- *   10-24-2000 SJH     Added prototype for 'nand_scan' function
- *   10-29-2001 TG     changed nand_chip structure to support
- *                     hardwarespecific function for accessing control lines
- *   02-21-2002 TG     added support for different read/write adress and
- *                     ready/busy line access function
- *   02-26-2002 TG     added chip_delay to nand_chip structure to optimize
- *                     command delay times for different chips
- *   04-28-2002 TG     OOB config defines moved from nand.c to avoid duplicate
- *                     defines in jffs2/wbuf.c
- *   08-07-2002 TG     forced bad block location to byte 5 of OOB, even if
- *                     CONFIG_MTD_NAND_ECC_JFFS2 is not set
- *   08-10-2002 TG     extensions to nand_chip structure to support HW-ECC
- *
- *   08-29-2002 tglx   nand_chip structure: data_poi for selecting
- *                     internal / fs-driver buffer
- *                     support for 6byte/512byte hardware ECC
- *                     read_ecc, write_ecc extended for different oob-layout
- *                     oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB,
- *                     NAND_YAFFS_OOB
- *  11-25-2002 tglx    Added Manufacturer code FUJITSU, NATIONAL
- *                     Split manufacturer and device ID structures
- *
- *  02-08-2004 tglx    added option field to nand structure for chip anomalities
- *  05-25-2004 tglx    added bad block table support, ST-MICRO manufacturer id
- *                     update of nand_chip structure description
- */
-#ifndef __LINUX_MTD_NAND_NEW_H
-#define __LINUX_MTD_NAND_NEW_H
-
-#include <linux/mtd/compat.h>
-#include <linux/mtd/mtd.h>
-
-struct mtd_info;
-/* Scan and identify a NAND device */
-extern int nand_scan (struct mtd_info *mtd, int max_chips);
-/* Free resources held by the NAND device */
-extern void nand_release (struct mtd_info *mtd);
-
-/* Read raw data from the device without ECC */
-extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen);
-
-
-
-/* This constant declares the max. oobsize / page, which
- * is supported now. If you add a chip with bigger oobsize/page
- * adjust this accordingly.
- */
-#define NAND_MAX_OOBSIZE       64
-
-/*
- * Constants for hardware specific CLE/ALE/NCE function
-*/
-/* Select the chip by setting nCE to low */
-#define NAND_CTL_SETNCE        1
-/* Deselect the chip by setting nCE to high */
-#define NAND_CTL_CLRNCE                2
-/* Select the command latch by setting CLE to high */
-#define NAND_CTL_SETCLE                3
-/* Deselect the command latch by setting CLE to low */
-#define NAND_CTL_CLRCLE                4
-/* Select the address latch by setting ALE to high */
-#define NAND_CTL_SETALE                5
-/* Deselect the address latch by setting ALE to low */
-#define NAND_CTL_CLRALE                6
-/* Set write protection by setting WP to high. Not used! */
-#define NAND_CTL_SETWP         7
-/* Clear write protection by setting WP to low. Not used! */
-#define NAND_CTL_CLRWP         8
-
-/*
- * Standard NAND flash commands
- */
-#define NAND_CMD_READ0         0
-#define NAND_CMD_READ1         1
-#define NAND_CMD_PAGEPROG      0x10
-#define NAND_CMD_READOOB       0x50
-#define NAND_CMD_ERASE1                0x60
-#define NAND_CMD_STATUS                0x70
-#define NAND_CMD_STATUS_MULTI  0x71
-#define NAND_CMD_SEQIN         0x80
-#define NAND_CMD_READID                0x90
-#define NAND_CMD_ERASE2                0xd0
-#define NAND_CMD_RESET         0xff
-
-/* Extended commands for large page devices */
-#define NAND_CMD_READSTART     0x30
-#define NAND_CMD_CACHEDPROG    0x15
-
-/* Status bits */
-#define NAND_STATUS_FAIL       0x01
-#define NAND_STATUS_FAIL_N1    0x02
-#define NAND_STATUS_TRUE_READY 0x20
-#define NAND_STATUS_READY      0x40
-#define NAND_STATUS_WP         0x80
-
-/*
- * Constants for ECC_MODES
- */
-
-/* No ECC. Usage is not recommended ! */
-#define NAND_ECC_NONE          0
-/* Software ECC 3 byte ECC per 256 Byte data */
-#define NAND_ECC_SOFT          1
-/* Hardware ECC 3 byte ECC per 256 Byte data */
-#define NAND_ECC_HW3_256       2
-/* Hardware ECC 3 byte ECC per 512 Byte data */
-#define NAND_ECC_HW3_512       3
-/* Hardware ECC 3 byte ECC per 512 Byte data */
-#define NAND_ECC_HW6_512       4
-/* Hardware ECC 8 byte ECC per 512 Byte data */
-#define NAND_ECC_HW8_512       6
-/* Hardware ECC 12 byte ECC per 2048 Byte data */
-#define NAND_ECC_HW12_2048     7
-
-/*
- * Constants for Hardware ECC
-*/
-/* Reset Hardware ECC for read */
-#define NAND_ECC_READ          0
-/* Reset Hardware ECC for write */
-#define NAND_ECC_WRITE         1
-/* Enable Hardware ECC before syndrom is read back from flash */
-#define NAND_ECC_READSYN       2
-
-/* Option constants for bizarre disfunctionality and real
-*  features
-*/
-/* Chip can not auto increment pages */
-#define NAND_NO_AUTOINCR       0x00000001
-/* Buswitdh is 16 bit */
-#define NAND_BUSWIDTH_16       0x00000002
-/* Device supports partial programming without padding */
-#define NAND_NO_PADDING                0x00000004
-/* Chip has cache program function */
-#define NAND_CACHEPRG          0x00000008
-/* Chip has copy back function */
-#define NAND_COPYBACK          0x00000010
-/* AND Chip which has 4 banks and a confusing page / block
- * assignment. See Renesas datasheet for further information */
-#define NAND_IS_AND            0x00000020
-/* Chip has a array of 4 pages which can be read without
- * additional ready /busy waits */
-#define NAND_4PAGE_ARRAY       0x00000040
-
-/* Options valid for Samsung large page devices */
-#define NAND_SAMSUNG_LP_OPTIONS \
-       (NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
-
-/* Macros to identify the above */
-#define NAND_CANAUTOINCR(chip) (!(chip->options & NAND_NO_AUTOINCR))
-#define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING))
-#define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG))
-#define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK))
-
-/* Mask to zero out the chip options, which come from the id table */
-#define NAND_CHIPOPTIONS_MSK   (0x0000ffff & ~NAND_NO_AUTOINCR)
-
-/* Non chip related options */
-/* Use a flash based bad block table. This option is passed to the
- * default bad block table function. */
-#define NAND_USE_FLASH_BBT     0x00010000
-/* The hw ecc generator provides a syndrome instead a ecc value on read
- * This can only work if we have the ecc bytes directly behind the
- * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
-#define NAND_HWECC_SYNDROME    0x00020000
-
-
-/* Options set by nand scan */
-/* Nand scan has allocated oob_buf */
-#define NAND_OOBBUF_ALLOC      0x40000000
-/* Nand scan has allocated data_buf */
-#define NAND_DATABUF_ALLOC     0x80000000
-
-
-/*
- * nand_state_t - chip states
- * Enumeration for NAND flash chip state
- */
-typedef enum {
-       FL_READY,
-       FL_READING,
-       FL_WRITING,
-       FL_ERASING,
-       FL_SYNCING,
-       FL_CACHEDPRG,
-} nand_state_t;
-
-/* Keep gcc happy */
-struct nand_chip;
-
-#if 0
-/**
- * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices
- * @lock:               protection lock
- * @active:            the mtd device which holds the controller currently
- */
-struct nand_hw_control {
-       spinlock_t       lock;
-       struct nand_chip *active;
-};
-#endif
-
-/**
- * struct nand_chip - NAND Private Flash Chip Data
- * @IO_ADDR_R:         [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
- * @IO_ADDR_W:         [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
- * @read_byte:         [REPLACEABLE] read one byte from the chip
- * @write_byte:                [REPLACEABLE] write one byte to the chip
- * @read_word:         [REPLACEABLE] read one word from the chip
- * @write_word:                [REPLACEABLE] write one word to the chip
- * @write_buf:         [REPLACEABLE] write data from the buffer to the chip
- * @read_buf:          [REPLACEABLE] read data from the chip into the buffer
- * @verify_buf:                [REPLACEABLE] verify buffer contents against the chip data
- * @select_chip:       [REPLACEABLE] select chip nr
- * @block_bad:         [REPLACEABLE] check, if the block is bad
- * @block_markbad:     [REPLACEABLE] mark the block bad
- * @hwcontrol:         [BOARDSPECIFIC] hardwarespecific function for accesing control-lines
- * @dev_ready:         [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
- *                     If set to NULL no access to ready/busy is available and the ready/busy information
- *                     is read from the chip status register
- * @cmdfunc:           [REPLACEABLE] hardwarespecific function for writing commands to the chip
- * @waitfunc:          [REPLACEABLE] hardwarespecific function for wait on ready
- * @calculate_ecc:     [REPLACEABLE] function for ecc calculation or readback from ecc hardware
- * @correct_data:      [REPLACEABLE] function for ecc correction, matching to ecc generator (sw/hw)
- * @enable_hwecc:      [BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
- *                     be provided if a hardware ECC is available
- * @erase_cmd:         [INTERN] erase command write function, selectable due to AND support
- * @scan_bbt:          [REPLACEABLE] function to scan bad block table
- * @eccmode:           [BOARDSPECIFIC] mode of ecc, see defines
- * @eccsize:           [INTERN] databytes used per ecc-calculation
- * @eccbytes:          [INTERN] number of ecc bytes per ecc-calculation step
- * @eccsteps:          [INTERN] number of ecc calculation steps per page
- * @chip_delay:                [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
- * @chip_lock:         [INTERN] spinlock used to protect access to this structure and the chip
- * @wq:                        [INTERN] wait queue to sleep on if a NAND operation is in progress
- * @state:             [INTERN] the current state of the NAND device
- * @page_shift:                [INTERN] number of address bits in a page (column address bits)
- * @phys_erase_shift:  [INTERN] number of address bits in a physical eraseblock
- * @bbt_erase_shift:   [INTERN] number of address bits in a bbt entry
- * @chip_shift:                [INTERN] number of address bits in one chip
- * @data_buf:          [INTERN] internal buffer for one page + oob
- * @oob_buf:           [INTERN] oob buffer for one eraseblock
- * @oobdirty:          [INTERN] indicates that oob_buf must be reinitialized
- * @data_poi:          [INTERN] pointer to a data buffer
- * @options:           [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
- *                     special functionality. See the defines for further explanation
- * @badblockpos:       [INTERN] position of the bad block marker in the oob area
- * @numchips:          [INTERN] number of physical chips
- * @chipsize:          [INTERN] the size of one chip for multichip arrays
- * @pagemask:          [INTERN] page number mask = number of (pages / chip) - 1
- * @pagebuf:           [INTERN] holds the pagenumber which is currently in data_buf
- * @autooob:           [REPLACEABLE] the default (auto)placement scheme
- * @bbt:               [INTERN] bad block table pointer
- * @bbt_td:            [REPLACEABLE] bad block table descriptor for flash lookup
- * @bbt_md:            [REPLACEABLE] bad block table mirror descriptor
- * @badblock_pattern:  [REPLACEABLE] bad block scan pattern used for initial bad block scan
- * @controller:                [OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices
- * @priv:              [OPTIONAL] pointer to private chip date
- */
-
-struct nand_chip {
-       void  __iomem   *IO_ADDR_R;
-       void  __iomem   *IO_ADDR_W;
-
-       u_char          (*read_byte)(struct mtd_info *mtd);
-       void            (*write_byte)(struct mtd_info *mtd, u_char byte);
-       u16             (*read_word)(struct mtd_info *mtd);
-       void            (*write_word)(struct mtd_info *mtd, u16 word);
-
-       void            (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
-       void            (*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
-       int             (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);
-       void            (*select_chip)(struct mtd_info *mtd, int chip);
-       int             (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
-       int             (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
-       void            (*hwcontrol)(struct mtd_info *mtd, int cmd);
-       int             (*dev_ready)(struct mtd_info *mtd);
-       void            (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
-       int             (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
-       int             (*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
-       int             (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
-       void            (*enable_hwecc)(struct mtd_info *mtd, int mode);
-       void            (*erase_cmd)(struct mtd_info *mtd, int page);
-       int             (*scan_bbt)(struct mtd_info *mtd);
-       int             eccmode;
-       int             eccsize;
-       int             eccbytes;
-       int             eccsteps;
-       int             chip_delay;
-#if 0
-       spinlock_t      chip_lock;
-       wait_queue_head_t wq;
-       nand_state_t    state;
-#endif
-       int             page_shift;
-       int             phys_erase_shift;
-       int             bbt_erase_shift;
-       int             chip_shift;
-       u_char          *data_buf;
-       u_char          *oob_buf;
-       int             oobdirty;
-       u_char          *data_poi;
-       unsigned int    options;
-       int             badblockpos;
-       int             numchips;
-       unsigned long   chipsize;
-       int             pagemask;
-       int             pagebuf;
-       struct nand_oobinfo     *autooob;
-       uint8_t         *bbt;
-       struct nand_bbt_descr   *bbt_td;
-       struct nand_bbt_descr   *bbt_md;
-       struct nand_bbt_descr   *badblock_pattern;
-       struct nand_hw_control  *controller;
-       void            *priv;
-};
-
-/*
- * NAND Flash Manufacturer ID Codes
- */
-#define NAND_MFR_TOSHIBA       0x98
-#define NAND_MFR_SAMSUNG       0xec
-#define NAND_MFR_FUJITSU       0x04
-#define NAND_MFR_NATIONAL      0x8f
-#define NAND_MFR_RENESAS       0x07
-#define NAND_MFR_STMICRO       0x20
-
-/**
- * struct nand_flash_dev - NAND Flash Device ID Structure
- *
- * @name:      Identify the device type
- * @id:        device ID code
- * @pagesize:          Pagesize in bytes. Either 256 or 512 or 0
- *             If the pagesize is 0, then the real pagesize
- *             and the eraseize are determined from the
- *             extended id bytes in the chip
- * @erasesize:         Size of an erase block in the flash device.
- * @chipsize:          Total chipsize in Mega Bytes
- * @options:   Bitfield to store chip relevant options
- */
-struct nand_flash_dev {
-       char *name;
-       int id;
-       unsigned long pagesize;
-       unsigned long chipsize;
-       unsigned long erasesize;
-       unsigned long options;
-};
-
-/**
- * struct nand_manufacturers - NAND Flash Manufacturer ID Structure
- * @name:      Manufacturer name
- * @id:        manufacturer ID code of device.
-*/
-struct nand_manufacturers {
-       int id;
-       char * name;
-};
-
-extern struct nand_flash_dev nand_flash_ids[];
-extern struct nand_manufacturers nand_manuf_ids[];
-
-/**
- * struct nand_bbt_descr - bad block table descriptor
- * @options:   options for this descriptor
- * @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
- * @offs:      offset of the pattern in the oob area of the page
- * @veroffs:   offset of the bbt version counter in the oob are of the page
- * @version:   version read from the bbt page during scan
- * @len:       length of the pattern, if 0 no pattern check is performed
- * @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.
- * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than
- *              bad) block in the stored bbt
- * @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
-
-extern int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd);
-extern int nand_update_bbt (struct mtd_info *mtd, loff_t offs);
-extern int nand_default_bbt (struct mtd_info *mtd);
-extern int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt);
-extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt);
-
-/*
-* Constants for oob configuration
-*/
-#define NAND_SMALL_BADBLOCK_POS                5
-#define NAND_LARGE_BADBLOCK_POS                0
-
-#endif /* __LINUX_MTD_NAND_NEW_H */