Browse Source

Re-factoring the legacy NAND code (legacy NAND now only in board-specific
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.

Bartlomiej Sieka 19 years ago
parent
commit
addb2e1650
86 changed files with 2881 additions and 2712 deletions
  1. 4 4
      MAKEALL
  2. 1 1
      board/amcc/bamboo/bamboo.c
  3. 4 0
      board/amcc/bamboo/config.mk
  4. 1 0
      board/bmw/config.mk
  5. 5 1
      board/dave/PPChameleonEVB/config.mk
  6. 3 33
      board/dave/PPChameleonEVB/nand.c
  7. 1 1
      board/esd/ash405/ash405.c
  8. 3 0
      board/esd/ash405/config.mk
  9. 1 1
      board/esd/cms700/cms700.c
  10. 3 0
      board/esd/cms700/config.mk
  11. 18 10
      board/esd/common/auto_update.c
  12. 4 0
      board/esd/cpci405/config.mk
  13. 4 0
      board/esd/hh405/config.mk
  14. 1 1
      board/esd/hh405/hh405.c
  15. 4 0
      board/esd/hub405/config.mk
  16. 1 1
      board/esd/hub405/hub405.c
  17. 3 0
      board/esd/plu405/config.mk
  18. 1 1
      board/esd/plu405/plu405.c
  19. 3 0
      board/esd/voh405/config.mk
  20. 1 1
      board/esd/voh405/voh405.c
  21. 3 0
      board/esd/wuh405/config.mk
  22. 1 1
      board/esd/wuh405/wuh405.c
  23. 1 1
      board/g2000/g2000.c
  24. 3 0
      board/netphone/config.mk
  25. 1 1
      board/netphone/netphone.c
  26. 1 1
      board/netstar/config.mk
  27. 2 2
      board/netstar/setup.S
  28. 4 0
      board/netta2/config.mk
  29. 1 1
      board/netta2/netta2.c
  30. 3 0
      board/netvia/config.mk
  31. 1 1
      board/netvia/netvia.c
  32. 1 1
      board/omap2420h4/omap2420h4.c
  33. 3 0
      board/sixnet/config.mk
  34. 1 1
      board/sixnet/sixnet.c
  35. 1 1
      board/stxxtc/stxxtc.c
  36. 1 1
      common/Makefile
  37. 2 1
      common/cmd_doc.c
  38. 10 7
      common/cmd_jffs2.c
  39. 412 1547
      common/cmd_nand.c
  40. 0 364
      common/cmd_nand_new.c
  41. 26 21
      common/env_nand.c
  42. 5 2
      drivers/nand/diskonchip.c
  43. 4 3
      drivers/nand/nand.c
  44. 6 5
      drivers/nand/nand_base.c
  45. 4 3
      drivers/nand/nand_bbt.c
  46. 4 3
      drivers/nand/nand_ecc.c
  47. 4 3
      drivers/nand/nand_ids.c
  48. 16 0
      drivers/nand_legacy/Makefile
  49. 1615 0
      drivers/nand_legacy/nand_legacy.c
  50. 14 10
      fs/jffs2/jffs2_1pass.c
  51. 1 1
      fs/jffs2/jffs2_nand_1pass.c
  52. 3 0
      include/configs/ASH405.h
  53. 4 0
      include/configs/BMW.h
  54. 2 0
      include/configs/CMS700.h
  55. 2 0
      include/configs/CPCI405.h
  56. 2 0
      include/configs/CPCI4052.h
  57. 3 0
      include/configs/CPCI405AB.h
  58. 2 0
      include/configs/CPCI405DT.h
  59. 2 0
      include/configs/CPU86.h
  60. 2 0
      include/configs/CPU87.h
  61. 2 0
      include/configs/GEN860T.h
  62. 2 0
      include/configs/HH405.h
  63. 2 0
      include/configs/HUB405.h
  64. 2 0
      include/configs/MIP405.h
  65. 1 0
      include/configs/NETPHONE.h
  66. 1 0
      include/configs/NETTA2.h
  67. 2 0
      include/configs/NETVIA.h
  68. 1 0
      include/configs/PCIPPC2.h
  69. 1 0
      include/configs/PCIPPC6.h
  70. 2 0
      include/configs/PIP405.h
  71. 2 0
      include/configs/PLU405.h
  72. 2 0
      include/configs/PM520.h
  73. 2 0
      include/configs/PM826.h
  74. 1 0
      include/configs/PM828.h
  75. 17 86
      include/configs/PPChameleonEVB.h
  76. 2 0
      include/configs/RBC823.h
  77. 1 0
      include/configs/SXNI855T.h
  78. 2 0
      include/configs/VOH405.h
  79. 2 0
      include/configs/WUH405.h
  80. 1 0
      include/configs/bamboo.h
  81. 1 1
      include/configs/netstar.h
  82. 1 0
      include/configs/svm_sc8xx.h
  83. 385 119
      include/linux/mtd/nand.h
  84. 4 0
      include/linux/mtd/nand_ids.h
  85. 203 0
      include/linux/mtd/nand_legacy.h
  86. 0 469
      include/linux/mtd/nand_new.h

+ 4 - 4
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
 "
 
 #########################################################################

+ 1 - 1
board/amcc/bamboo/bamboo.c

@@ -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];
 
 /*----------------------------------------------------------------------------+

+ 4 - 0
board/amcc/bamboo/config.mk

@@ -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
+

+ 1 - 0
board/bmw/config.mk

@@ -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)
+

+ 5 - 1
board/dave/PPChameleonEVB/config.mk

@@ -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
+

+ 3 - 33
board/dave/PPChameleonEVB/nand.c

@@ -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) */

+ 1 - 1
board/esd/ash405/ash405.c

@@ -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)

+ 3 - 0
board/esd/ash405/config.mk

@@ -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

+ 1 - 1
board/esd/cms700/cms700.c

@@ -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)

+ 3 - 0
board/esd/cms700/config.mk

@@ -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

+ 18 - 10
board/esd/common/auto_update.c

@@ -23,10 +23,15 @@
  */
 
 #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

+ 4 - 0
board/esd/cpci405/config.mk

@@ -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
+

+ 4 - 0
board/esd/hh405/config.mk

@@ -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
+

+ 1 - 1
board/esd/hh405/hh405.c

@@ -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)

+ 4 - 0
board/esd/hub405/config.mk

@@ -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
+

+ 1 - 1
board/esd/hub405/hub405.c

@@ -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)

+ 3 - 0
board/esd/plu405/config.mk

@@ -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

+ 1 - 1
board/esd/plu405/plu405.c

@@ -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)

+ 3 - 0
board/esd/voh405/config.mk

@@ -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

+ 1 - 1
board/esd/voh405/voh405.c

@@ -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)

+ 3 - 0
board/esd/wuh405/config.mk

@@ -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

+ 1 - 1
board/esd/wuh405/wuh405.c

@@ -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)

+ 1 - 1
board/g2000/g2000.c

@@ -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)

+ 3 - 0
board/netphone/config.mk

@@ -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

+ 1 - 1
board/netphone/netphone.c

@@ -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];

+ 1 - 1
board/netstar/config.mk

@@ -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
 

+ 2 - 2
board/netstar/setup.S

@@ -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

+ 4 - 0
board/netta2/config.mk

@@ -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
+

+ 1 - 1
board/netta2/netta2.c

@@ -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];

+ 3 - 0
board/netvia/config.mk

@@ -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

+ 1 - 1
board/netvia/netvia.c

@@ -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];

+ 1 - 1
board/omap2420h4/omap2420h4.c

@@ -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
 

+ 3 - 0
board/sixnet/config.mk

@@ -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

+ 1 - 1
board/sixnet/sixnet.c

@@ -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
 

+ 1 - 1
board/stxxtc/stxxtc.c

@@ -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];

+ 1 - 1
common/Makefile

@@ -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 \

+ 2 - 1
common/cmd_doc.c

@@ -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>
 

+ 10 - 7
common/cmd_jffs2.c

@@ -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>
 
@@ -99,10 +98,14 @@
 
 #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];

+ 412 - 1547
common/cmd_nand.c

@@ -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>
@@ -21,11 +402,12 @@
 # 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 */

+ 0 - 364
common/cmd_nand_new.c

@@ -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) */

+ 26 - 21
common/env_nand.c

@@ -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
@@ -55,16 +55,12 @@
 #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();
 

+ 5 - 2
drivers/nand/diskonchip.c

@@ -20,7 +20,11 @@
  */
 
 #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 */

+ 4 - 3
drivers/nand/nand.c

@@ -23,7 +23,10 @@
 
 #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 */
-

+ 6 - 5
drivers/nand/nand_base.c

@@ -71,7 +71,10 @@
 #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 */
-

+ 4 - 3
drivers/nand/nand_bbt.c

@@ -54,7 +54,10 @@
 
 #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 */
-

+ 4 - 3
drivers/nand/nand_ecc.c

@@ -37,7 +37,10 @@
 
 #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 */
-

+ 4 - 3
drivers/nand/nand_ids.c

@@ -13,7 +13,10 @@
 
 #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 */
-

+ 16 - 0
drivers/nand_legacy/Makefile

@@ -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

+ 1615 - 0
drivers/nand_legacy/nand_legacy.c

@@ -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) */

+ 14 - 10
fs/jffs2/jffs2_1pass.c

@@ -143,7 +143,8 @@
 /* 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)

+ 1 - 1
fs/jffs2/jffs2_nand_1pass.c

@@ -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>

+ 3 - 0
include/configs/ASH405.h

@@ -132,6 +132,9 @@
  * NAND-FLASH stuff
  *-----------------------------------------------------------------------
  */
+
+#define CFG_NAND_LEGACY
+
 #define CFG_MAX_NAND_DEVICE	1	/* Max number of NAND devices		*/
 #define SECTORSIZE 512
 

+ 4 - 0
include/configs/BMW.h

@@ -69,6 +69,10 @@
 				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)

+ 2 - 0
include/configs/CMS700.h

@@ -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	*/

+ 2 - 0
include/configs/CPCI405.h

@@ -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	*/

+ 2 - 0
include/configs/CPCI4052.h

@@ -100,6 +100,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	*/

+ 3 - 0
include/configs/CPCI405AB.h

@@ -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	*/

+ 2 - 0
include/configs/CPCI405DT.h

@@ -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	*/

+ 2 - 0
include/configs/CPU86.h

@@ -178,6 +178,8 @@
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 /*
  * Miscellaneous configurable options
  */

+ 2 - 0
include/configs/CPU87.h

@@ -189,6 +189,8 @@
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 /*
  * Miscellaneous configurable options
  */

+ 2 - 0
include/configs/GEN860T.h

@@ -284,6 +284,8 @@
  */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 /*
  * Verbose help from command monitor.
  */

+ 2 - 0
include/configs/HH405.h

@@ -122,6 +122,8 @@
 /* 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		*/
 

+ 2 - 0
include/configs/HUB405.h

@@ -135,6 +135,8 @@
  * NAND-FLASH stuff
  *-----------------------------------------------------------------------
  */
+#define CFG_NAND_LEGACY
+
 #define CFG_MAX_NAND_DEVICE	1	/* Max number of NAND devices		*/
 #define SECTORSIZE 512
 

+ 2 - 0
include/configs/MIP405.h

@@ -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 "> "
 /**************************************************************

+ 1 - 0
include/configs/NETPHONE.h

@@ -491,6 +491,7 @@
 /****************************************************************/
 
 /* NAND */
+#define CFG_NAND_LEGACY
 #define CFG_NAND_BASE		NAND_BASE
 #define CONFIG_MTD_NAND_ECC_JFFS2
 #define CONFIG_MTD_NAND_VERIFY_WRITE

+ 1 - 0
include/configs/NETTA2.h

@@ -491,6 +491,7 @@
 /****************************************************************/
 
 /* NAND */
+#define CFG_NAND_LEGACY
 #define CFG_NAND_BASE		NAND_BASE
 #define CONFIG_MTD_NAND_ECC_JFFS2
 #define CONFIG_MTD_NAND_VERIFY_WRITE

+ 2 - 0
include/configs/NETVIA.h

@@ -387,6 +387,8 @@
 
 /*****************************************************************************/
 
+#define CFG_NAND_LEGACY
+
 #if defined(CONFIG_NETVIA_VERSION) && CONFIG_NETVIA_VERSION >= 2
 
 /* NAND */

+ 1 - 0
include/configs/PCIPPC2.h

@@ -77,6 +77,7 @@
  */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
 
 /*
  * Miscellaneous configurable options

+ 1 - 0
include/configs/PCIPPC6.h

@@ -79,6 +79,7 @@
  */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
 
 /*
  * Miscellaneous configurable options

+ 2 - 0
include/configs/PIP405.h

@@ -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 "> "
 /**************************************************************

+ 2 - 0
include/configs/PLU405.h

@@ -160,6 +160,8 @@
  * NAND-FLASH stuff
  *-----------------------------------------------------------------------
  */
+#define CFG_NAND_LEGACY
+
 #define CFG_MAX_NAND_DEVICE	1	/* Max number of NAND devices		*/
 #define SECTORSIZE 512
 

+ 2 - 0
include/configs/PM520.h

@@ -101,6 +101,8 @@
 #define ADD_DOC_CMD             0
 #else
 #define ADD_DOC_CMD             CFG_CMD_DOC
+/* DoC requires legacy NAND for now */
+#define CFG_NAND_LEGACY
 #endif
 
 /*

+ 2 - 0
include/configs/PM826.h

@@ -180,6 +180,8 @@
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
 
+#define CFG_NAND_LEGACY
+
 /*
  * Disk-On-Chip configuration
  */

+ 1 - 0
include/configs/PM828.h

@@ -183,6 +183,7 @@
 /*
  * Disk-On-Chip configuration
  */
+#define CFG_NAND_LEGACY
 
 #define CFG_DOC_SHORT_TIMEOUT
 #define CFG_MAX_DOC_DEVICE	1	/* Max number of DOC devices	*/

+ 17 - 86
include/configs/PPChameleonEVB.h

@@ -188,36 +188,31 @@
  * 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) \
@@ -293,83 +288,19 @@
 		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) */
@@ -385,7 +316,7 @@
 #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
  *-----------------------------------------------------------------------

+ 2 - 0
include/configs/RBC823.h

@@ -326,6 +326,8 @@
 /************************************************************
  * 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

+ 1 - 0
include/configs/SXNI855T.h

@@ -183,6 +183,7 @@
 */
 
 /* 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

+ 2 - 0
include/configs/VOH405.h

@@ -141,6 +141,8 @@
  * NAND-FLASH stuff
  *-----------------------------------------------------------------------
  */
+#define CFG_NAND_LEGACY
+
 #define CFG_MAX_NAND_DEVICE	1	/* Max number of NAND devices		*/
 #define SECTORSIZE 512
 

+ 2 - 0
include/configs/WUH405.h

@@ -133,6 +133,8 @@
  * NAND-FLASH stuff
  *-----------------------------------------------------------------------
  */
+#define CFG_NAND_LEGACY
+
 #define CFG_MAX_NAND_DEVICE	1	/* Max number of NAND devices		*/
 #define SECTORSIZE 512
 

+ 1 - 0
include/configs/bamboo.h

@@ -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

+ 1 - 1
include/configs/netstar.h

@@ -130,8 +130,8 @@
  * 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)

+ 1 - 0
include/configs/svm_sc8xx.h

@@ -141,6 +141,7 @@
 
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
+#define CFG_NAND_LEGACY
 
 /*
  * Miscellaneous configurable options

+ 385 - 119
include/linux/mtd/nand.h

@@ -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
@@ -32,13 +32,66 @@
  *			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
  */
@@ -48,12 +101,104 @@
 #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 */

+ 4 - 0
include/linux/mtd/nand_ids.h

@@ -28,6 +28,10 @@
 #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},

+ 203 - 0
include/linux/mtd/nand_legacy.h

@@ -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 */

+ 0 - 469
include/linux/mtd/nand_new.h

@@ -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 */