فهرست منبع

NAND: add the ability to directly write yaffs image

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>
Lei Wen 14 سال پیش
والد
کامیت
47fc18f1e7
3فایلهای تغییر یافته به همراه70 افزوده شده و 10 حذف شده
  1. 14 1
      common/cmd_nand.c
  2. 55 8
      drivers/mtd/nand/nand_util.c
  3. 1 1
      include/nand.h

+ 14 - 1
common/cmd_nand.c

@@ -574,7 +574,15 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 							 (u_char *)addr);
 							 (u_char *)addr);
 			else
 			else
 				ret = nand_write_skip_bad(nand, off, &rwsize,
 				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")) {
 		} else if (!strcmp(s, ".oob")) {
 			/* out-of-band data */
 			/* out-of-band data */
 			mtd_oob_ops_t ops = {
 			mtd_oob_ops_t ops = {
@@ -680,6 +688,11 @@ U_BOOT_CMD(
 	"nand write - addr off|partition size\n"
 	"nand write - addr off|partition size\n"
 	"    read/write 'size' bytes starting at offset 'off'\n"
 	"    read/write 'size' bytes starting at offset 'off'\n"
 	"    to/from memory address 'addr', skipping bad blocks.\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 "
 	"nand erase[.spread] [clean] [off [size]] - erase 'size' bytes "
 	"from offset 'off'\n"
 	"from offset 'off'\n"
 	"    With '.spread', erase enough for given file size, otherwise,\n"
 	"    With '.spread', erase enough for given file size, otherwise,\n"

+ 55 - 8
drivers/mtd/nand/nand_util.c

@@ -447,17 +447,34 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length)
  * @param nand  	NAND device
  * @param nand  	NAND device
  * @param offset	offset in flash
  * @param offset	offset in flash
  * @param length	buffer length
  * @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
  * @return		0 in case of success
  */
  */
 int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 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;
 	size_t left_to_write = *length;
 	u_char *p_buffer = buffer;
 	u_char *p_buffer = buffer;
 	int need_skip;
 	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.
 	 * 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;
 			continue;
 		}
 		}
 
 
-		if (left_to_write < (nand->erasesize - block_offset))
+		if (left_to_write < (blocksize - block_offset))
 			write_size = left_to_write;
 			write_size = left_to_write;
 		else
 		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) {
 		if (rval != 0) {
 			printf ("NAND write to offset %llx failed %d\n",
 			printf ("NAND write to offset %llx failed %d\n",
 				offset, rval);
 				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;
 		left_to_write -= write_size;
-		offset        += write_size;
-		p_buffer      += write_size;
 	}
 	}
 
 
 	return 0;
 	return 0;

+ 1 - 1
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,
 int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 		       u_char *buffer);
 		       u_char *buffer);
 int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 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);
 int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts);
 
 
 #define NAND_LOCK_STATUS_TIGHT	0x01
 #define NAND_LOCK_STATUS_TIGHT	0x01