
I _think_ this should work with all NAND chips. Otherwise we might have to introduce a configuration variable.
Signed-off-by: Guennadi Liakhovetski lg@denx.de --- nand_spl/nand_boot.c | 64 ++++++++++++++++++++++++++----------------------- 1 files changed, 34 insertions(+), 30 deletions(-)
diff --git a/nand_spl/nand_boot.c b/nand_spl/nand_boot.c index 563a80b..0de4c4b 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,12 @@ 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 +163,8 @@ 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 +180,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 +188,30 @@ 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 +239,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 */