We have to read a whole page on large-page NAND chips, at least the chip
installed on SMDK6400 can only read whole pages with READ0. Also activate
chipselect before using the chip, and deactivate it afterwards.

Signed-off-by: Guennadi Liakhovetski <[EMAIL PROTECTED]>
---
 nand_spl/nand_boot.c |   69 +++++++++++++++++++++++++++----------------------
 1 files changed, 38 insertions(+), 31 deletions(-)

diff --git a/nand_spl/nand_boot.c b/nand_spl/nand_boot.c
index 0f56ba5..8cd0046 100644
--- a/nand_spl/nand_boot.c
+++ b/nand_spl/nand_boot.c
@@ -132,21 +132,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 (in_8(this->IO_ADDR_R) != 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;
@@ -154,8 +139,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;
@@ -167,11 +150,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->ecc.hwctl(mtd, NAND_ECC_READ);
-               this->read_buf(mtd, p, eccsize);
+               this->read_buf(mtd, p, CFG_NAND_ECCSIZE);
                this->ecc.calculate(mtd, p, &ecc_calc[i]);
        }
        this->read_buf(mtd, oob_data, CFG_NAND_OOBSIZE);
@@ -183,7 +167,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.
@@ -199,25 +184,41 @@ static int nand_load(struct mtd_info *mtd, int offs, int 
uboot_size, uchar *dst)
        int block;
        int blockcopy_count;
        int page;
+       unsigned int read = 0;
 
        /*
-        * offs has to be aligned to a block address!
+        * offs has to be aligned to a page address!
         */
        block = offs / CFG_NAND_BLOCK_SIZE;
+       /* Recalculate offs as an offset inside a block */
+       offs -= CFG_NAND_BLOCK_SIZE * block;
        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 == 0
+#ifdef CFG_NAND_BBT_2NDPAGE
+                            || page == 1
+#endif
+                                   ) && dst[CFG_NAND_PAGE_SIZE +
+                                            CFG_NAND_BAD_BLOCK_POS] != 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++;
        }
@@ -245,12 +246,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


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
U-Boot-Users mailing list
U-Boot-Users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/u-boot-users

Reply via email to