From 41c86240567307655ad837be17e6f5fa2a06452f Mon Sep 17 00:00:00 2001 From: Lei Wen Date: Thu, 2 Dec 2010 05:17:55 +0000 Subject: [PATCH] onenand: add yaffs write command 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 --- common/cmd_onenand.c | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c index cb2ba70..a27adaa 100644 --- a/common/cmd_onenand.c +++ b/common/cmd_onenand.c @@ -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"