--- u-boot-2004-08-18-2000/include/linux/mtd/nand.h	2003-09-11 14:50:28.000000000 -0500
+++ u-boot/include/linux/mtd/nand.h	2004-10-29 15:09:06.000000000 -0500
@@ -122,6 +122,7 @@ struct nand_chip {
 	uint oobblock;  /* Size of OOB blocks (e.g. 512) */
 	uint oobsize;   /* Amount of OOB data per block (e.g. 16) */
 	uint eccsize;
+	int bus16;
 };
 
 /*
@@ -165,6 +166,7 @@ struct nand_flash_dev {
 	char page256;
 	char pageadrlen;
 	unsigned long erasesize;
+	int bus16;
 };
 
 /*
--- u-boot-2004-08-18-2000/include/linux/mtd/nand_ids.h	2003-05-31 13:35:29.000000000 -0500
+++ u-boot/include/linux/mtd/nand_ids.h	2004-10-29 15:08:54.000000000 -0500
@@ -29,24 +29,26 @@
 #define __LINUX_MTD_NAND_IDS_H
 
 static struct nand_flash_dev nand_flash_ids[] = {
-	{"Toshiba TC5816BDC",     NAND_MFR_TOSHIBA, 0x64, 21, 1, 2, 0x1000},
-	{"Toshiba TC5832DC",      NAND_MFR_TOSHIBA, 0x6b, 22, 0, 2, 0x2000},
-	{"Toshiba TH58V128DC",    NAND_MFR_TOSHIBA, 0x73, 24, 0, 2, 0x4000},
-	{"Toshiba TC58256FT/DC",  NAND_MFR_TOSHIBA, 0x75, 25, 0, 2, 0x4000},
-	{"Toshiba TH58512FT",     NAND_MFR_TOSHIBA, 0x76, 26, 0, 3, 0x4000},
-	{"Toshiba TC58V32DC",     NAND_MFR_TOSHIBA, 0xe5, 22, 0, 2, 0x2000},
-	{"Toshiba TC58V64AFT/DC", NAND_MFR_TOSHIBA, 0xe6, 23, 0, 2, 0x2000},
-	{"Toshiba TC58V16BDC",    NAND_MFR_TOSHIBA, 0xea, 21, 1, 2, 0x1000},
-	{"Toshiba TH58100FT",     NAND_MFR_TOSHIBA, 0x79, 27, 0, 3, 0x4000},
-	{"Samsung KM29N16000",    NAND_MFR_SAMSUNG, 0x64, 21, 1, 2, 0x1000},
-	{"Samsung unknown 4Mb",   NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000},
-	{"Samsung KM29U128T",     NAND_MFR_SAMSUNG, 0x73, 24, 0, 2, 0x4000},
-	{"Samsung KM29U256T",     NAND_MFR_SAMSUNG, 0x75, 25, 0, 2, 0x4000},
-	{"Samsung unknown 64Mb",  NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000},
-	{"Samsung KM29W32000",    NAND_MFR_SAMSUNG, 0xe3, 22, 0, 2, 0x2000},
-	{"Samsung unknown 4Mb",   NAND_MFR_SAMSUNG, 0xe5, 22, 0, 2, 0x2000},
-	{"Samsung KM29U64000",    NAND_MFR_SAMSUNG, 0xe6, 23, 0, 2, 0x2000},
-	{"Samsung KM29W16000",    NAND_MFR_SAMSUNG, 0xea, 21, 1, 2, 0x1000},
+	{"Toshiba TC5816BDC",     NAND_MFR_TOSHIBA, 0x64, 21, 1, 2, 0x1000, 0},
+	{"Toshiba TC5832DC",      NAND_MFR_TOSHIBA, 0x6b, 22, 0, 2, 0x2000, 0},
+	{"Toshiba TH58V128DC",    NAND_MFR_TOSHIBA, 0x73, 24, 0, 2, 0x4000, 0},
+	{"Toshiba TC58256FT/DC",  NAND_MFR_TOSHIBA, 0x75, 25, 0, 2, 0x4000, 0},
+	{"Toshiba TH58512FT",     NAND_MFR_TOSHIBA, 0x76, 26, 0, 3, 0x4000, 0},
+	{"Toshiba TC58V32DC",     NAND_MFR_TOSHIBA, 0xe5, 22, 0, 2, 0x2000, 0},
+	{"Toshiba TC58V64AFT/DC", NAND_MFR_TOSHIBA, 0xe6, 23, 0, 2, 0x2000, 0},
+	{"Toshiba TC58V16BDC",    NAND_MFR_TOSHIBA, 0xea, 21, 1, 2, 0x1000, 0},
+	{"Toshiba TH58100FT",     NAND_MFR_TOSHIBA, 0x79, 27, 0, 3, 0x4000, 0},
+	{"Samsung KM29N16000",    NAND_MFR_SAMSUNG, 0x64, 21, 1, 2, 0x1000, 0},
+	{"Samsung unknown 4Mb",   NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000, 0},
+	{"Samsung KM29U128T",     NAND_MFR_SAMSUNG, 0x73, 24, 0, 2, 0x4000, 0},
+	{"Samsung KM29U256T",     NAND_MFR_SAMSUNG, 0x75, 25, 0, 2, 0x4000, 0},
+	{"Samsung unknown 64Mb",  NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000, 0},
+	{"Samsung KM29W32000",    NAND_MFR_SAMSUNG, 0xe3, 22, 0, 2, 0x2000, 0},
+	{"Samsung unknown 4Mb",   NAND_MFR_SAMSUNG, 0xe5, 22, 0, 2, 0x2000, 0},
+	{"Samsung KM29U64000",    NAND_MFR_SAMSUNG, 0xe6, 23, 0, 2, 0x2000, 0},
+	{"Samsung KM29W16000",    NAND_MFR_SAMSUNG, 0xea, 21, 1, 2, 0x1000, 0},
+	{"Samsung K9F5616Q0C",    NAND_MFR_SAMSUNG, 0x45, 25, 0, 2, 0x4000, 1},
+	{"Samsung K9K1216Q0C",    NAND_MFR_SAMSUNG, 0x46, 26, 0, 3, 0x4000, 1},
 	{NULL,}
 };
 
--- u-boot-2004-08-18-2000/common/cmd_nand.c	2004-07-10 16:45:49.000000000 -0500
+++ u-boot/common/cmd_nand.c	2004-11-02 16:05:58.000000000 -0600
@@ -3,6 +3,9 @@
  * 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>
@@ -20,10 +23,6 @@
 
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
 
-#ifdef CONFIG_AT91RM9200DK
-#include <asm/arch/hardware.h>
-#endif
-
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ids.h>
 #include <jffs2/jffs2.h>
@@ -395,6 +394,7 @@ int check_block(struct nand_chip* nand, 
 {
 	int 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;
@@ -405,12 +405,22 @@ int check_block(struct nand_chip* nand, 
 	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, &oob_data) ||
 	    oob_data != 0xff ||
 	    nand_read_oob(nand, page1 + badpos, 1, &retlen, &oob_data) ||
 	    oob_data != 0xff)
 		return 1;
+	}
 
 	return 0;
 }
@@ -704,7 +714,9 @@ static int NanD_IdentChip(struct nand_ch
 				    nand_flash_ids[i].erasesize;
 				nand->chips_name =
 				    nand_flash_ids[i].name;
-				return 1;
+				nand->bus16 =
+				    nand_flash_ids[i].bus16;
+ 				return 1;
 			}
 			return 0;
 		}
@@ -790,7 +802,47 @@ static void NanD_ScanChips(struct nand_c
 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);
@@ -815,6 +867,7 @@ static void NanD_ReadBuf(struct nand_chi
 		*data_buf++ = READ_NAND(nandptr);
 		cntr--;
 	}
+	}
 }
 
 /*
@@ -863,7 +916,11 @@ static int nand_read_ecc(struct nand_chi
 			goto readdata;
 		/* Send the read command */
 		NanD_Command(nand, NAND_CMD_READ0);
-		NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);
+		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);
 
@@ -930,7 +987,11 @@ readdata:
 #else
 		/* Send the read command */
 		NanD_Command(nand, NAND_CMD_READ0);
-		NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);
+		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);
@@ -967,6 +1028,7 @@ static int nand_write_page (struct nand_
 {
 
 	int i;
+	u16 val;
 	unsigned long nandptr = nand->IO_ADDR;
 #ifdef CONFIG_MTD_NAND_ECC
 #ifdef CONFIG_MTD_NAND_VERIFY_WRITE
@@ -985,10 +1047,25 @@ static int nand_write_page (struct nand_
 	/* 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)) {
@@ -1019,11 +1096,21 @@ static int nand_write_page (struct nand_
 	/* Send command to begin auto page programming */
 	NanD_Command(nand, NAND_CMD_READ0);
 	NanD_Command(nand, NAND_CMD_SEQIN);
-	NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);
+	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);
@@ -1061,13 +1148,26 @@ static int nand_write_page (struct nand_
 		NanD_Command(nand, NAND_CMD_READ0);
 	else
 		NanD_Command(nand, NAND_CMD_READ1);
-	NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);
+	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 */
-	for (i = col; i < last; i++) {
-		if (nand->data_buf[i] != readb (nand->IO_ADDR)) {
-			printf ("%s: Failed write verify, page 0x%08x ", __FUNCTION__, page);
-			return -1;
+	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;
+			}
 		}
 	}
 
@@ -1077,9 +1177,19 @@ static int nand_write_page (struct nand_
 	 * correctly for the same reasons stated above.
 	 */
 	NanD_Command(nand, NAND_CMD_READOOB);
-	NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);
-	for (i = 0; i < nand->oobsize; i++)
-		nand->data_buf[i] = readb (nand->IO_ADDR);
+	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) {
+			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 "
@@ -1116,6 +1226,10 @@ static int nand_write_ecc (struct nand_c
 #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 */
@@ -1163,6 +1277,10 @@ out:
 #ifdef CONFIG_OMAP1510
     	archflashwp(0,1);
 #endif
+#ifdef CFG_NAND_WP
+	NAND_WP_ON();
+#endif
+
 	return ret;
 }
 
@@ -1189,7 +1307,11 @@ static int nand_read_oob(struct nand_chi
 
 	NAND_ENABLE_CE(nand);  /* set pin low */
 	NanD_Command(nand, NAND_CMD_READOOB);
-	NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
+	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 */
@@ -1239,8 +1361,12 @@ static int nand_write_oob(struct nand_ch
 
 	/* issue the Read2 command to set the pointer to the Spare Data Area. */
 	NanD_Command(nand, NAND_CMD_READOOB);
-	NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
-
+	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) {
@@ -1252,8 +1378,12 @@ static int nand_write_oob(struct nand_ch
 
 	/* issue the Serial Data In command to initial the Page Program process */
 	NanD_Command(nand, NAND_CMD_SEQIN);
-	NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
-
+	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.      */
@@ -1282,8 +1412,14 @@ static int nand_write_oob(struct nand_ch
 		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);
@@ -1334,6 +1470,9 @@ int nand_erase(struct nand_chip* nand, s
 #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 */
@@ -1418,6 +1557,10 @@ out:
 #ifdef CONFIG_OMAP1510
     	archflashwp(0,1);
 #endif
+#ifdef CFG_NAND_WP
+	NAND_WP_ON();
+#endif
+
 	return ret;
 }
 
