summaryrefslogtreecommitdiffstats
path: root/common/cmd_onenand.c
diff options
context:
space:
mode:
authorLei Wen <leiwen@marvell.com>2010-12-02 05:17:55 +0000
committerScott Wood <scottwood@freescale.com>2010-12-17 14:32:12 -0600
commit41c86240567307655ad837be17e6f5fa2a06452f (patch)
treef576a8f8f9c699c6cdb33b79842d65433ec4aeb6 /common/cmd_onenand.c
parent7a8fc36e6c3430784c877b6799833059b1ef4d33 (diff)
downloadblackbird-obmc-uboot-41c86240567307655ad837be17e6f5fa2a06452f.tar.gz
blackbird-obmc-uboot-41c86240567307655ad837be17e6f5fa2a06452f.zip
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 <leiwen@marvell.com>
Diffstat (limited to 'common/cmd_onenand.c')
-rw-r--r--common/cmd_onenand.c41
1 files changed, 36 insertions, 5 deletions
diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c
index cb2ba70517..a27adaa61d 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"
OpenPOWER on IntegriCloud