onenand: add yaffs write command
authorLei Wen <leiwen@marvell.com>
Thu, 2 Dec 2010 05:17:55 +0000 (05:17 +0000)
committerScott Wood <scottwood@freescale.com>
Fri, 17 Dec 2010 20:32:12 +0000 (14:32 -0600)
Yaffs image require to use the oob to store some info, so when we
burn the yaffs image, we need to also write the image's oob part
into flash.

This patch add addition suffix to onenand write to give the uboot
the power to directly burn the yaffs image to onenand.

Signed-off-by: Lei Wen <leiwen@marvell.com>
common/cmd_onenand.c

index cb2ba70517d4608feb0fc8fdf835b13dddc8a896..a27adaa61d44990beca2d7d90a34e8ecfd2e674f 100644 (file)
@@ -112,8 +112,32 @@ static int onenand_block_read(loff_t from, size_t len,
        return 0;
 }
 
+static int onenand_write_oneblock_withoob(loff_t to, const u_char * buf,
+                                         size_t *retlen)
+{
+       struct mtd_oob_ops ops = {
+               .len = mtd->writesize,
+               .ooblen = mtd->oobsize,
+               .mode = MTD_OOB_AUTO,
+       };
+       int page, ret = 0;
+       for (page = 0; page < (mtd->erasesize / mtd->writesize); page ++) {
+               ops.datbuf = (u_char *)buf;
+               buf += mtd->writesize;
+               ops.oobbuf = (u_char *)buf;
+               buf += mtd->oobsize;
+               ret = mtd->write_oob(mtd, to, &ops);
+               if (ret)
+                       break;
+               to += mtd->writesize;
+       }
+
+       *retlen = (ret) ? 0 : mtd->erasesize;
+       return ret;
+}
+
 static int onenand_block_write(loff_t to, size_t len,
-                              size_t *retlen, const u_char * buf)
+                              size_t *retlen, const u_char * buf, int withoob)
 {
        struct onenand_chip *this = mtd->priv;
        int blocks = len >> this->erase_shift;
@@ -140,7 +164,10 @@ static int onenand_block_write(loff_t to, size_t len,
                        goto next;
                }
 
-               ret = mtd->write(mtd, ofs, blocksize, &_retlen, buf);
+               if (!withoob)
+                       ret = mtd->write(mtd, ofs, blocksize, &_retlen, buf);
+               else
+                       ret = onenand_write_oneblock_withoob(ofs, buf, &_retlen);
                if (ret) {
                        printk("Write failed 0x%x, %d", (u32)ofs, ret);
                        skip_ofs += blocksize;
@@ -386,19 +413,22 @@ static int do_onenand_write(cmd_tbl_t * cmdtp, int flag, int argc, char * const
 {
        ulong addr, ofs;
        size_t len;
-       int ret = 0;
+       int ret = 0, withoob = 0;
        size_t retlen = 0;
 
        if (argc < 3)
                return cmd_usage(cmdtp);
 
+       if (strncmp(argv[0] + 6, "yaffs", 5) == 0)
+               withoob = 1;
+
        addr = (ulong)simple_strtoul(argv[1], NULL, 16);
 
        printf("\nOneNAND write: ");
        if (arg_off_size(argc - 2, argv + 2, &ofs, &len) != 0)
                return 1;
 
-       ret = onenand_block_write(ofs, len, &retlen, (u8 *)addr);
+       ret = onenand_block_write(ofs, len, &retlen, (u8 *)addr, withoob);
 
        printf(" %d bytes written: %s\n", retlen, ret ? "ERROR" : "OK");
 
@@ -521,6 +551,7 @@ static cmd_tbl_t cmd_onenand_sub[] = {
        U_BOOT_CMD_MKENT(bad, 1, 0, do_onenand_bad, "", ""),
        U_BOOT_CMD_MKENT(read, 4, 0, do_onenand_read, "", ""),
        U_BOOT_CMD_MKENT(write, 4, 0, do_onenand_write, "", ""),
+       U_BOOT_CMD_MKENT(write.yaffs, 4, 0, do_onenand_write, "", ""),
        U_BOOT_CMD_MKENT(erase, 3, 0, do_onenand_erase, "", ""),
        U_BOOT_CMD_MKENT(test, 3, 0, do_onenand_test, "", ""),
        U_BOOT_CMD_MKENT(dump, 2, 0, do_onenand_dump, "", ""),
@@ -560,7 +591,7 @@ U_BOOT_CMD(
        "info - show available OneNAND devices\n"
        "onenand bad - show bad blocks\n"
        "onenand read[.oob] addr off size\n"
-       "onenand write addr off size\n"
+       "onenand write[.yaffs] addr off size\n"
        "    read/write 'size' bytes starting at offset 'off'\n"
        "    to/from memory address 'addr', skipping bad blocks.\n"
        "onenand erase [force] [off size] - erase 'size' bytes from\n"