At bootloader, we don't need to read full page. It takes too long time.
Instead it only read pages required for boot.
Of course, this patch reduces the boot time

Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com>
---
diff --git a/drivers/mtd/onenand/onenand_bbt.c 
b/drivers/mtd/onenand/onenand_bbt.c
index c4bdb57..8bc9e8a 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -48,6 +48,43 @@ static int check_short_pattern(uint8_t * buf, int len, int 
paglen,
        return 0;
 }
 
+static int read_page_oob(struct mtd_info *mtd, loff_t from, u_char *buf)
+{
+       struct onenand_chip *this = mtd->priv;
+       struct bbm_info *bbm = this->bbm;
+       struct nand_bbt_descr *bd = bbm->badblock_pattern;
+       struct mtd_oob_ops ops;
+       int ret, scanlen, block, j, res;
+
+       scanlen = 0;
+
+       ops.mode = MTD_OOB_PLACE;
+       ops.ooblen = 16;
+       ops.oobbuf = buf;
+       ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
+
+       /* Get block number * 2 */
+       block = (int)(from >> (bbm->bbt_erase_shift - 1));
+
+       /* Set as normal block */
+       res = 0x00;
+       bbm->bbt[block >> 3] |= 0x00 << (block & 0x6);
+
+       for (j = 0; j < 2; j++) {
+               ret = onenand_bbt_read_oob(mtd, from + j * mtd->writesize + 
bd->offs, &ops);
+               if (ret || check_short_pattern(&buf[j * scanlen], scanlen, 
mtd->writesize, bd)) {
+                       bbm->bbt[block >> 3] |= 0x03 << (block & 0x6);
+                       res = 0x03;
+                       printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
+                                       block >> 1, (unsigned int) from);
+                       mtd->ecc_stats.badblocks++;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
 /**
  * create_bbt - [GENERIC] Create a bad block table by scanning the device
  * @param mtd          MTD device structure
@@ -155,6 +192,11 @@ static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t 
offs, int allowbbt)
        block = (int)(offs >> (bbm->bbt_erase_shift - 1));
        res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
+       if (this->options & ONENAND_RUNTIME_BADBLOCK_CHECK) {
+               if (res == 0x02)
+                       res = read_page_oob(mtd, offs, this->oob_buf);
+       }
+
        MTDDEBUG (MTD_DEBUG_LEVEL2,
                "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 
0x%02x\n",
                (unsigned int)offs, block >> 1, res);
@@ -210,6 +252,12 @@ int onenand_scan_bbt(struct mtd_info *mtd, struct 
nand_bbt_descr *bd)
        if (!bbm->isbad_bbt)
                bbm->isbad_bbt = onenand_isbad_bbt;
 
+       if (this->options & ONENAND_RUNTIME_BADBLOCK_CHECK) {
+               printk(KERN_INFO "Scanning device for bad blocks (skipped)\n");
+               memset(bbm->bbt, 0xaa, len);
+               return 0;
+       }
+
        /* Scan the device to build a memory based bad block table */
        if ((ret = onenand_memory_bbt(mtd, bd))) {
                printk(KERN_ERR
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 4b0c923..76dfce4 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -135,6 +135,7 @@ struct onenand_chip {
 #define ONENAND_HAS_CONT_LOCK          (0x0001)
 #define ONENAND_HAS_UNLOCK_ALL         (0x0002)
 #define ONENAND_HAS_2PLANE             (0x0004)
+#define ONENAND_RUNTIME_BADBLOCK_CHECK (0x0200)
 #define ONENAND_PAGEBUF_ALLOC          (0x1000)
 #define ONENAND_OOBBUF_ALLOC           (0x2000)
 
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to