]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - drivers/mtd/nand/nand_util.c
NAND: add the ability to directly write yaffs image
[people/ms/u-boot.git] / drivers / mtd / nand / nand_util.c
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;