--- /data/src/u-boot-1.1.4/common/cmd_nand.c	2005-12-17 00:39:27.000000000 +0800
+++ ./common/cmd_nand.c	2006-07-17 17:34:00.000000000 +0800
@@ -6,6 +6,10 @@
  *
  * Added 16-bit nand support
  * (C) 2004 Texas Instruments
+ *
+ * Added programming in both block and spare column area
+ * Specifically, it is meant for programming binary generated by mkyaffsimage
+ * (C) 2006 Applied Biosystems Instruments <terence.soh@appliedbiosystems.com>
  */
 
 #include <common.h>
@@ -68,6 +72,7 @@ struct nand_oob_config {
 #define NANDRW_WRITE	0x00
 #define NANDRW_JFFS2	0x02
 #define NANDRW_JFFS2_SKIP	0x04
+#define NANDRW_NOECC	0x08
 
 /*
  * Function Prototypes
@@ -91,11 +96,19 @@ static int NanD_WaitReady(struct nand_ch
 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
+static int nand_write_noecc (struct nand_chip* nand, size_t to, size_t len,
+				size_t * retlen, const u_char * buf);
+static int nand_read_noecc(struct nand_chip *nand, size_t start, size_t len,
+				size_t * retlen, u_char *buf);
+int nand_rw_noecc (struct nand_chip* nand, int cmd,
+			size_t start, size_t len,
+			size_t * retlen, u_char * buf);
 
 struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE] = {{0}};
 
 /* Current NAND Device	*/
 static int curr_device = -1;
+static int pages_per_block;
 
 /* ------------------------------------------------------------------------- */
 
@@ -217,6 +230,9 @@ int do_nand (cmd_tbl_t *cmdtp, int flag,
 			if (cmd & NANDRW_READ)
 				cmd |= NANDRW_JFFS2_SKIP;	/* skip bad blocks (on read too) */
 		}
+		else if (cmdtail && !strncmp(cmdtail, ".noecc", 2)) {
+			cmd |= NANDRW_NOECC;	/* read/write to OOB without ECC */
+		}
 #ifdef SXNI855T
 		/* need ".e" same as ".j" for compatibility with older units */
 		else if (cmdtail && !strcmp(cmdtail, ".e"))
@@ -240,8 +256,13 @@ int do_nand (cmd_tbl_t *cmdtp, int flag,
 			(cmd & NANDRW_READ) ? "read" : "write",
 			curr_device, off, size);
 
-		ret = nand_rw(nand_dev_desc + curr_device, cmd, off, size,
-			     (size_t *)&total, (u_char*)addr);
+		if (cmd & NANDRW_NOECC){
+			ret = nand_rw_noecc(nand_dev_desc + curr_device, cmd, off, size,
+					&total, (u_char*)addr);
+		} else {
+			ret = nand_rw(nand_dev_desc + curr_device, cmd, off, size,
+					&total, (u_char*)addr);
+		}
 
 		printf (" %d bytes %s: %s\n", total,
 			(cmd & NANDRW_READ) ? "read" : "written",
@@ -285,6 +306,8 @@ U_BOOT_CMD(
 	"nand bad - show bad blocks\n"
 	"nand read.oob addr off size - read out-of-band data\n"
 	"nand write.oob addr off size - read out-of-band data\n"
+	"nand read.noecc addr off size - read data without ECC"
+	"nand write.noecc addr off size - write data without ECC"
 );
 
 int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
@@ -445,6 +468,61 @@ static void nand_print_bad(struct nand_c
 	puts("\n");
 }
 
+/* Dealing in (nand->oobblock + nand->oobsize) i.e. 528, 2112... bytes per page */
+int nand_rw_noecc (struct nand_chip* nand, int cmd,
+			size_t start, size_t len,
+			size_t * retlen, u_char * buf)
+{
+	int ret = 0, n, total = 0;
+	unsigned long eblk;
+
+	while (len) {
+		if (start%((nand->oobblock + nand->oobsize)*pages_per_block) == 0) {
+			/* have crossed into new erase block, deal with
+			 * it if it is sure marked bad.
+			 */
+			eblk = start/((nand->oobblock + nand->oobsize)*pages_per_block);
+			eblk *= nand->oobblock;
+			if (check_block(nand, eblk)) {
+				if (cmd == (NANDRW_WRITE | NANDRW_NOECC)) {
+					start += ((nand->oobblock + nand->oobsize)*pages_per_block);
+					continue;
+				}
+			}
+		}
+
+		/* Start on 528/2112 bytes boundary */
+		if (start%((nand->oobblock + nand->oobsize))){
+			printf("\nError: Reading/Writing must start from %d byte page boundary, 0x%8X\n",
+				(nand->oobblock + nand->oobsize),start);
+			return -1;
+		} else {
+			/* reading and writing without ECC */
+			if (cmd & NANDRW_READ) {
+				ret = nand_read_noecc(nand, start,
+						min(len, (nand->oobblock + nand->oobsize)*pages_per_block),
+						&n, (u_char*)buf);
+			} else {
+				ret = nand_write_noecc(nand, start,
+						min(len, (nand->oobblock + nand->oobsize)*pages_per_block),
+						&n, (u_char*)buf);
+			}
+		}
+
+		if (ret)
+			break;
+
+		start  += n;
+		buf   += n;
+		total += n;
+		len   -= n;
+	}
+	if (retlen)
+		*retlen = total;
+
+	return ret;
+}
+
 /* 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
@@ -722,6 +800,7 @@ static int NanD_IdentChip(struct nand_ch
 				nand->erasesize  = nand_flash_ids[i].erasesize;
 				nand->chips_name = nand_flash_ids[i].name;
 				nand->bus16	 = nand_flash_ids[i].bus16;
+				pages_per_block = nand->erasesize / nand->oobblock;
  				return 1;
 			}
 			return 0;
@@ -876,6 +955,56 @@ static void NanD_ReadBuf (struct nand_ch
 	}
 }
 
+/* Read entire page (without ECC) */
+static int nand_read_noecc(struct nand_chip *nand, size_t start, size_t len,
+				size_t * retlen, u_char *buf)
+{
+	int col, page;
+
+	/* First we calculate the starting page */
+	/* Address here take spare area into account */
+	page = start / (nand->oobblock + nand->oobsize);
+	/* Get raw starting column */
+	col = start % (nand->oobblock + nand->oobsize);
+
+	/* Initialize return value */
+	*retlen = 0;
+	NAND_ENABLE_CE(nand);		/* set pin low */
+	/* Loop until all data read */
+	while (*retlen < len) {
+		/* Send the read command */
+		NanD_Command(nand, NAND_CMD_READ0);
+
+		/* Address to NAND flash don't take the spare area into account */
+		if (nand->bus16) {
+			NanD_Address(nand, ADDR_COLUMN_PAGE,
+				(page * nand->oobblock) + (col >> 1));
+		} else {
+			NanD_Address(nand, ADDR_COLUMN_PAGE,
+				(page * nand->oobblock) + col);
+		}
+
+		/* Read the data directly into the return buffer */
+		if ((*retlen + (nand->oobblock + nand->oobsize - col)) >= len) {
+			NanD_ReadBuf(nand, buf + *retlen, len - *retlen);
+			*retlen = len;
+			/* We're done */
+			continue;
+		} else {
+			NanD_ReadBuf(nand, buf + *retlen, nand->oobblock + nand->oobsize - col);
+			*retlen += nand->oobblock + nand->oobsize - col;
+		}
+		/* 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 */
+	/* Always successful. No ECC */
+	return 0;
+}
+
 /*
  * NAND read with ECC
  */
@@ -1245,6 +1374,84 @@ static int nand_write_page (struct nand_
 	return 0;
 }
 
+/* Write entire page (including out of bound area) */
+static int nand_write_noecc (struct nand_chip* nand, size_t to, size_t len,
+				size_t * retlen, const u_char * buf)
+{
+	int i, page, col, ret, cnt = 0;
+
+	/* Initialize return length value */
+	*retlen = 0;
+	ret = 0;
+
+	/* Get page */
+	page = ((int) to) / (nand->oobblock + nand->oobsize);
+	/* Get the starting column. Should be zero */
+	col = to % (nand->oobblock + nand->oobsize);
+
+	/* Loop until all data is written */
+	while (*retlen < len) {
+		/* Write data into buffer */
+		if ((col + len - *retlen) >= (nand->oobblock + nand->oobsize)) {
+			/* >= (nand->oobblock + nand->oobsize) bytes to be written */
+			for (i = col, cnt = 0; i < (nand->oobblock + nand->oobsize); i++, cnt++) {
+				nand->data_buf[i] = buf[(*retlen + cnt)];
+			}
+		} else {
+			/* Less than (nand->oobblock + nand->oobsize) bytes to be written */
+			for (i = col, cnt = 0; cnt < (len - *retlen); i++, cnt++) {
+				nand->data_buf[i] = buf[(*retlen + cnt)];
+			}
+		}
+		/* set pin low */
+		NAND_ENABLE_CE(nand);
+		NanD_Command (nand, NAND_CMD_SEQIN);
+
+		if (nand->bus16) {
+			NanD_Address (nand, ADDR_COLUMN_PAGE,
+				(page * nand->oobblock) + (col >> 1));
+		} else {
+			NanD_Address (nand, ADDR_COLUMN_PAGE,
+				(page * nand->oobblock) + col);
+		}
+		/* Write out complete page of data */
+		if (nand->bus16) {
+			for (i = 0; i < cnt; i += 2) {
+				WRITE_NAND (nand->data_buf[i] +
+					(nand->data_buf[i + 1] << 8),
+					nand->IO_ADDR);
+			}
+		} else {
+			/* Send command to begin auto page programming */
+			for (i = 0; i < cnt ; 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);
+
+		NAND_WAIT_READY(nand);
+
+		/* See if device thinks it succeeded */
+		if (READ_NAND (nand->IO_ADDR) & 0x01) {
+			printf ("%s: Failed write, page 0x%08x, ", __FUNCTION__,
+				page);
+			ret = -1;
+		}
+
+		/* De-select the NAND device */
+		NAND_DISABLE_CE(nand);		/* set pin high */
+
+		/* Next data start at page boundary */
+		col = 0;
+		/* Update written bytes count */
+		*retlen += cnt;
+		/* Increment page address */
+		page++;
+	}
+	return ret;
+}
+
 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)
 {
