]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
NAND: add the ability to directly write yaffs image
authorLei Wen <leiwen@marvell.com>
Thu, 6 Jan 2011 03:11:58 +0000 (11:11 +0800)
committerScott Wood <scottwood@freescale.com>
Wed, 12 Jan 2011 23:13:10 +0000 (17:13 -0600)
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 <leiwen@marvell.com>
common/cmd_nand.c
drivers/mtd/nand/nand_util.c
include/nand.h

index 6783645356fefd35c6a21a7418be5454e806a058..7bd37de78dee9e717f4c521c2eeaa51fe2825de3 100644 (file)
@@ -574,7 +574,15 @@ 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);
+#ifdef CONFIG_CMD_NAND_YAFFS
+               } else if (!strcmp(s, ".yaffs")) {
+                       if (read) {
+                               printf("Unknown nand command suffix '%s'.\n", s);
+                               return 1;
+                       }
+                       ret = nand_write_skip_bad(nand, off, &rwsize, (u_char *)addr, 1);
+#endif
                } else if (!strcmp(s, ".oob")) {
                        /* out-of-band data */
                        mtd_oob_ops_t ops = {
@@ -680,6 +688,11 @@ U_BOOT_CMD(
        "nand write - addr off|partition size\n"
        "    read/write 'size' bytes starting at offset 'off'\n"
        "    to/from memory address 'addr', skipping bad blocks.\n"
+#ifdef CONFIG_CMD_NAND_YAFFS
+       "nand write.yaffs - addr off|partition size\n"
+       "    write 'size' bytes starting at offset 'off' with yaffs format\n"
+       "    from memory address 'addr', skipping bad blocks.\n"
+#endif
        "nand erase[.spread] [clean] [off [size]] - erase 'size' bytes "
        "from offset 'off'\n"
        "    With '.spread', erase enough for given file size, otherwise,\n"
index 22c741169476269d167d42b8207da08f500768ae..8b4f7388152c70e209d2f8f8193d3ea0a35306e3 100644 (file)
@@ -447,17 +447,34 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length)
  * @param nand         NAND device
  * @param offset       offset in flash
  * @param length       buffer length
- * @param buf           buffer to read from
+ * @param buffer        buffer to read from
+ * @param withoob      whether write with yaffs format
  * @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;
        size_t left_to_write = *length;
        u_char *p_buffer = buffer;
        int need_skip;
 
+#ifdef CONFIG_CMD_NAND_YAFFS
+       if (withoob) {
+               int pages;
+               pages = nand->erasesize / nand->writesize;
+               blocksize = (pages * nand->oobsize) + nand->erasesize;
+               if (*length % (nand->writesize + nand->oobsize)) {
+                       printf ("Attempt to write incomplete page"
+                               " in yaffs mode\n");
+                       return -EINVAL;
+               }
+       } else
+#endif
+       {
+               blocksize = nand->erasesize;
+       }
+
        /*
         * nand_write() handles unaligned, partial page writes.
         *
@@ -506,12 +523,44 @@ 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;
+                       write_size = blocksize - block_offset;
+
+#ifdef CONFIG_CMD_NAND_YAFFS
+               if (withoob) {
+                       int page, pages;
+                       size_t pagesize = nand->writesize;
+                       size_t pagesize_oob = pagesize + nand->oobsize;
+                       struct mtd_oob_ops ops;
+
+                       ops.len = pagesize;
+                       ops.ooblen = nand->oobsize;
+                       ops.mode = MTD_OOB_AUTO;
+                       ops.ooboffs = 0;
+
+                       pages = write_size / pagesize_oob;
+                       for (page = 0; page < pages; page++) {
+                               ops.datbuf = p_buffer;
+                               ops.oobbuf = ops.datbuf + pagesize;
+
+                               rval = nand->write_oob(nand, offset, &ops);
+                               if (!rval)
+                                       break;
+
+                               offset += pagesize;
+                               p_buffer += pagesize_oob;
+                       }
+               }
+               else
+#endif
+               {
+                       rval = nand_write (nand, offset, &write_size, p_buffer);
+                       offset += write_size;
+                       p_buffer += write_size;
+               }
 
-               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 +569,6 @@ 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;
        }
 
        return 0;
index a4524113d00e60f7f6b30acc4c4fff263fc39e62..7459bd0330a1b16f9153b8e1ee3dc2134739bf63 100644 (file)
@@ -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