All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 1/2] nand: extend .raw accesses to work on multiple pages
@ 2012-03-28 22:26 Scott Wood
  2012-03-28 22:27 ` [U-Boot] [PATCH 2/2] nand: remote biterr command stub Scott Wood
  2012-05-18 22:59 ` [U-Boot] [PATCH 1/2] nand: extend .raw accesses to work on multiple pages Scott Wood
  0 siblings, 2 replies; 5+ messages in thread
From: Scott Wood @ 2012-03-28 22:26 UTC (permalink / raw)
  To: u-boot

A use for this is to read, modify, erase, and write an entire block as a
single unit, as a replacement for the biterr command.  This way gives
more flexibility in that you can also test multiple bit errors, errors
in the ECC, etc.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
 common/cmd_nand.c |   95 +++++++++++++++++++++++++++++++++++++++-------------
 doc/README.nand   |   16 ++++----
 2 files changed, 79 insertions(+), 32 deletions(-)

diff --git a/common/cmd_nand.c b/common/cmd_nand.c
index bae630d..4456706 100644
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -11,7 +11,7 @@
  * Added 16-bit nand support
  * (C) 2004 Texas Instruments
  *
- * Copyright 2010 Freescale Semiconductor
+ * Copyright 2010, 2012 Freescale Semiconductor
  * The portions of this file whose copyright is held by Freescale and which
  * are not considered a derived work of GPL v2-only code may be distributed
  * and/or modified under the terms of the GNU General Public License as
@@ -390,6 +390,41 @@ static void nand_print_and_set_info(int idx)
 	setenv("nand_erasesize", buf);
 }
 
+static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count,
+			int read)
+{
+	int ret = 0;
+	size_t rwsize;
+
+	while (count--) {
+		/* Raw access */
+		mtd_oob_ops_t ops = {
+			.datbuf = (u8 *)addr,
+			.oobbuf = ((u8 *)addr) + nand->writesize,
+			.len = nand->writesize,
+			.ooblen = nand->oobsize,
+			.mode = MTD_OOB_RAW
+		};
+
+		rwsize = nand->writesize + nand->oobsize;
+		if (read)
+			ret = nand->read_oob(nand, off, &ops);
+		else
+			ret = nand->write_oob(nand, off, &ops);
+
+		if (ret) {
+			printf("%s: error at offset %llx, ret %d\n",
+				__func__, (long long)off, ret);
+			break;
+		}
+
+		addr += nand->writesize + nand->oobsize;
+		off += nand->writesize;
+	}
+
+	return ret;
+}
+
 int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
 	int i, ret = 0;
@@ -568,7 +603,9 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 
 	if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
 		size_t rwsize;
+		ulong pagecount = 1;
 		int read;
+		int raw;
 
 		if (argc < 4)
 			goto usage;
@@ -577,13 +614,36 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 
 		read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
 		printf("\nNAND %s: ", read ? "read" : "write");
-		if (arg_off_size(argc - 3, argv + 3, &dev, &off, &size) != 0)
-			return 1;
 
 		nand = &nand_info[dev];
-		rwsize = size;
 
 		s = strchr(cmd, '.');
+
+		if (!strcmp(s, ".raw")) {
+			raw = 1;
+
+			if (arg_off(argv[3], &dev, &off, &size))
+				return 1;
+
+			if (argc > 4 && !str2long(argv[4], &pagecount)) {
+				printf("'%s' is not a number\n", argv[4]);
+				return 1;
+			}
+
+			if (pagecount * nand->writesize > size) {
+				puts("Size exceeds partition or device limit\n");
+				return -1;
+			}
+
+			rwsize = pagecount * (nand->writesize + nand->oobsize);
+		} else {
+			if (arg_off_size(argc - 3, argv + 3, &dev,
+						&off, &size) != 0)
+				return 1;
+
+			rwsize = size;
+		}
+
 		if (!s || !strcmp(s, ".jffs2") ||
 		    !strcmp(s, ".e") || !strcmp(s, ".i")) {
 			if (read)
@@ -609,7 +669,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 				return 1;
 			}
 			ret = nand_write_skip_bad(nand, off, &rwsize,
-						(u_char *)addr, WITH_YAFFS_OOB);
+						(u_char *)addr,
+						WITH_INLINE_OOB);
 #endif
 		} else if (!strcmp(s, ".oob")) {
 			/* out-of-band data */
@@ -623,22 +684,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 				ret = nand->read_oob(nand, off, &ops);
 			else
 				ret = nand->write_oob(nand, off, &ops);
-		} else if (!strcmp(s, ".raw")) {
-			/* Raw access */
-			mtd_oob_ops_t ops = {
-				.datbuf = (u8 *)addr,
-				.oobbuf = ((u8 *)addr) + nand->writesize,
-				.len = nand->writesize,
-				.ooblen = nand->oobsize,
-				.mode = MTD_OOB_RAW
-			};
-
-			rwsize = nand->writesize + nand->oobsize;
-
-			if (read)
-				ret = nand->read_oob(nand, off, &ops);
-			else
-				ret = nand->write_oob(nand, off, &ops);
+		} else if (raw) {
+			ret = raw_access(nand, addr, off, pagecount, read);
 		} else {
 			printf("Unknown nand command suffix '%s'.\n", s);
 			return 1;
@@ -732,9 +779,9 @@ 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"
-	"nand read.raw - addr off|partition\n"
-	"nand write.raw - addr off|partition\n"
-	"    Use read.raw/write.raw to avoid ECC and access the page as-is.\n"
+	"nand read.raw - addr off|partition [count]\n"
+	"nand write.raw - addr off|partition [count]\n"
+	"    Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
 #ifdef CONFIG_CMD_NAND_TRIMFFS
 	"nand write.trimffs - addr off|partition size\n"
 	"    write 'size' bytes starting at offset 'off' from memory address\n"
diff --git a/doc/README.nand b/doc/README.nand
index 04a87c9..1602b5e 100644
--- a/doc/README.nand
+++ b/doc/README.nand
@@ -94,14 +94,14 @@ Commands:
       of data for one 512-byte page or 2 256-byte pages. There is no check
       for bad blocks.
 
-   nand read.raw addr ofs|partition
-      Read page from `ofs' in NAND flash to `addr'. This reads the raw page,
-      so ECC is avoided and the OOB area is read as well.
-
-   nand write.raw addr ofs|partition
-      Write page from `addr' to `ofs' in NAND flash. This writes the raw page,
-      so ECC is avoided and the OOB area is written as well, making the whole
-      page written as-is.
+   nand read.raw addr ofs|partition [count]
+   nand write.raw addr ofs|partition [count]
+      Read or write one or more pages at "ofs" in NAND flash, from or to
+      "addr" in memory.  This is a raw access, so ECC is avoided and the
+      OOB area is transferred as well.  If count is absent, it is assumed
+      to be one page.  As with .yaffs2 accesses, the data is formatted as
+      a packed sequence of "data, oob, data, oob, ..." -- no alignment of
+      individual pages is maintained.
 
 Configuration Options:
 
-- 
1.7.7.rc3.4.g8d714

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-05-18 22:59 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-28 22:26 [U-Boot] [PATCH 1/2] nand: extend .raw accesses to work on multiple pages Scott Wood
2012-03-28 22:27 ` [U-Boot] [PATCH 2/2] nand: remote biterr command stub Scott Wood
2012-03-29  6:15   ` Stefan Roese
2012-03-29  6:23   ` Wolfgang Denk
2012-05-18 22:59 ` [U-Boot] [PATCH 1/2] nand: extend .raw accesses to work on multiple pages Scott Wood

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.