[U-Boot-Users] [PATCH 2/7 v2] NAND_CMD_READOOB is not supported by all chips, read OOB with the page instead

Guennadi Liakhovetski lg at denx.de
Mon Aug 4 12:42:57 CEST 2008


I _think_ this should work with all NAND chips. Otherwise we might have to 
introduce a configuration variable.

Signed-off-by: Guennadi Liakhovetski <lg at denx.de>
---
 nand_spl/nand_boot.c |   61 +++++++++++++++++++++++++------------------------
 1 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/nand_spl/nand_boot.c b/nand_spl/nand_boot.c
index 563a80b..78eaf75 100644
--- a/nand_spl/nand_boot.c
+++ b/nand_spl/nand_boot.c
@@ -128,21 +128,6 @@ static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8
 }
 #endif
 
-static int nand_is_bad_block(struct mtd_info *mtd, int block)
-{
-	struct nand_chip *this = mtd->priv;
-
-	nand_command(mtd, block, 0, CFG_NAND_BAD_BLOCK_POS, NAND_CMD_READOOB);
-
-	/*
-	 * Read one byte
-	 */
-	if (this->read_byte(mtd) != 0xff)
-		return 1;
-
-	return 0;
-}
-
 static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst)
 {
 	struct nand_chip *this = mtd->priv;
@@ -150,8 +135,6 @@ static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst)
 	u_char *ecc_code;
 	u_char *oob_data;
 	int i;
-	int eccsize = CFG_NAND_ECCSIZE;
-	int eccbytes = CFG_NAND_ECCBYTES;
 	int eccsteps = CFG_NAND_ECCSTEPS;
 	uint8_t *p = dst;
 	int stat;
@@ -163,11 +146,11 @@ static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst)
 	 */
 	ecc_calc = (u_char *)(CFG_SDRAM_BASE + 0x10000);
 	ecc_code = ecc_calc + 0x100;
-	oob_data = ecc_calc + 0x200;
+	oob_data = p + CFG_NAND_PAGE_SIZE; /* Append OOB to the page data */
 
-	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+	for (i = 0; eccsteps; eccsteps--, i += CFG_NAND_ECCBYTES, p += CFG_NAND_ECCSIZE) {
 		this->enable_hwecc(mtd, NAND_ECC_READ);
-		this->read_buf(mtd, p, eccsize);
+		this->read_buf(mtd, p, CFG_NAND_ECCSIZE);
 		this->calculate_ecc(mtd, p, &ecc_calc[i]);
 	}
 	this->read_buf(mtd, oob_data, CFG_NAND_OOBSIZE);
@@ -179,7 +162,7 @@ static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst)
 	eccsteps = CFG_NAND_ECCSTEPS;
 	p = dst;
 
-	for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+	for (i = 0; eccsteps; eccsteps--, i += CFG_NAND_ECCBYTES, p += CFG_NAND_ECCSIZE) {
 		/* No chance to do something with the possible error message
 		 * from correct_data(). We just hope that all possible errors
 		 * are corrected by this routine.
@@ -195,6 +178,7 @@ static int nand_load(struct mtd_info *mtd, int offs, int uboot_size, uchar *dst)
 	int block;
 	int blockcopy_count;
 	int page;
+	unsigned read = 0;
 
 	/*
 	 * offs has to be aligned to a block address!
@@ -202,18 +186,29 @@ static int nand_load(struct mtd_info *mtd, int offs, int uboot_size, uchar *dst)
 	block = offs / CFG_NAND_BLOCK_SIZE;
 	blockcopy_count = 0;
 
-	while (blockcopy_count < (uboot_size / CFG_NAND_BLOCK_SIZE)) {
-		if (!nand_is_bad_block(mtd, block)) {
-			/*
-			 * Skip bad blocks
-			 */
-			for (page = 0; page < CFG_NAND_PAGE_COUNT; page++) {
-				nand_read_page(mtd, block, page, dst);
-				dst += CFG_NAND_PAGE_SIZE;
+	while (blockcopy_count < ((uboot_size + CFG_NAND_BLOCK_SIZE - 1) / CFG_NAND_BLOCK_SIZE)) {
+		/*
+		 * Skip bad blocks
+		 */
+		int badblock = 0;
+		for (page = 0; page < CFG_NAND_PAGE_COUNT; page++) {
+			nand_read_page(mtd, block, page, dst);
+			if ((!page
+#ifdef CFG_NAND_BBT_2NDPAGE
+			     || page == 1
+#endif
+				    ) && dst[CFG_NAND_PAGE_SIZE] != 0xff) {
+				badblock = 1;
+				break;
 			}
+			/* Overwrite skipped pages */
+			if (read >= offs)
+				dst += CFG_NAND_PAGE_SIZE;
+			read += CFG_NAND_PAGE_SIZE;
+		}
 
+		if (!badblock)
 			blockcopy_count++;
-		}
 
 		block++;
 	}
@@ -241,12 +236,18 @@ void nand_boot(void)
 	nand_chip.dev_ready = NULL;	/* preset to NULL */
 	board_nand_init(&nand_chip);
 
+	if (nand_chip.select_chip)
+		nand_chip.select_chip(&nand_info, 0);
+
 	/*
 	 * Load U-Boot image from NAND into RAM
 	 */
 	ret = nand_load(&nand_info, CFG_NAND_U_BOOT_OFFS, CFG_NAND_U_BOOT_SIZE,
 			(uchar *)CFG_NAND_U_BOOT_DST);
 
+	if (nand_chip.select_chip)
+		nand_chip.select_chip(&nand_info, -1);
+
 	/*
 	 * Jump to U-Boot image
 	 */
-- 
1.5.4





More information about the U-Boot mailing list