From patchwork Mon Jan 3 13:09:20 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [U-Boot] NAND: add the ability to directly write yaffs image Date: Mon, 03 Jan 2011 03:09:20 -0000 From: Lei Wen X-Patchwork-Id: 77248 Message-Id: <1294060160-16848-1-git-send-email-leiwen@marvell.com> To: Scott Wood , u-boot@lists.denx.de, adrian.wenl@gmail.com This patch add addition suffix to nand write to give the uboot the power to directly burn the yaffs image to nand. Signed-off-by: Lei Wen --- common/cmd_nand.c | 12 ++++++++-- drivers/mtd/nand/nand_util.c | 43 +++++++++++++++++++++++++++++++++++------ include/nand.h | 2 +- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/common/cmd_nand.c b/common/cmd_nand.c index c547a68..e113971 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -574,7 +574,13 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) (u_char *)addr); else ret = nand_write_skip_bad(nand, off, &rwsize, - (u_char *)addr); + (u_char *)addr, 0); + } else if (!strcmp(s, ".yaffs")) { + if (read) { + printf("Unknown nand command suffix '%s'.\n", s); + return 1; + } + ret = nand_write_skip_bad(nand, off, &size, (u_char *)addr, 1); } else if (!strcmp(s, ".oob")) { /* out-of-band data */ mtd_oob_ops_t ops = { @@ -677,7 +683,7 @@ U_BOOT_CMD( "info - show available NAND devices\n" "nand device [dev] - show or set current device\n" "nand read - addr off|partition size\n" - "nand write - addr off|partition size\n" + "nand write[.yaffs] - addr off|partition size\n" " read/write 'size' bytes starting at offset 'off'\n" " to/from memory address 'addr', skipping bad blocks.\n" "nand erase[.spread] [clean] [off [size]] - erase 'size' bytes " @@ -720,7 +726,7 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, s = strchr(cmd, '.'); if (s != NULL && - (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) { + (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i") && strcmp(s, ".yaffs"))) { printf("Unknown nand load suffix '%s'\n", s); show_boot_progress(-53); return 1; diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 22c7411..e7a314a 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -451,12 +451,24 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length) * @return 0 in case of success */ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, - u_char *buffer) + u_char *buffer, int withoob) { - int rval; + int rval = 0, blocksize, pages, page; size_t left_to_write = *length; u_char *p_buffer = buffer; int need_skip; + struct mtd_oob_ops ops; + + if (withoob) { + pages = nand->erasesize / nand->writesize; + blocksize = (pages * nand->oobsize) + nand->erasesize; + if (*length % (nand->writesize + nand->oobsize)) { + printf ("Attempt to write non yaffs page aligned data\n"); + return -EINVAL; + } + } + else + blocksize = nand->erasesize; /* * nand_write() handles unaligned, partial page writes. @@ -506,12 +518,26 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, continue; } - if (left_to_write < (nand->erasesize - block_offset)) + if (left_to_write < (blocksize - block_offset)) write_size = left_to_write; else - write_size = nand->erasesize - block_offset; - - rval = nand_write (nand, offset, &write_size, p_buffer); + write_size = blocksize - block_offset; + + if (withoob) { + ops.len = nand->writesize; + ops.ooblen = nand->oobsize; + ops.mode = MTD_OOB_AUTO; + ops.ooboffs = 0; + pages = write_size / (nand->writesize + nand->oobsize); + for (page = 0; page < pages && !rval; page ++) { + ops.datbuf = (page * (nand->writesize + nand->oobsize)) + + p_buffer; + ops.oobbuf = ops.datbuf + nand->writesize; + rval = nand->write_oob(nand, offset + page *nand->writesize, &ops); + } + } + else + rval = nand_write (nand, offset, &write_size, p_buffer); if (rval != 0) { printf ("NAND write to offset %llx failed %d\n", offset, rval); @@ -520,8 +546,11 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, } left_to_write -= write_size; - offset += write_size; p_buffer += write_size; + if (withoob) + offset += (write_size + nand->erasesize - blocksize); + else + offset += write_size; } return 0; diff --git a/include/nand.h b/include/nand.h index a452411..7459bd0 100644 --- a/include/nand.h +++ b/include/nand.h @@ -115,7 +115,7 @@ typedef struct nand_erase_options nand_erase_options_t; int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, u_char *buffer); int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, - u_char *buffer); + u_char *buffer, int withoob); int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts); #define NAND_LOCK_STATUS_TIGHT 0x01