diff mbox

[U-Boot,1/2] nand: extend .raw accesses to work on multiple pages

Message ID 20120328222653.GA14861@schlenkerla.am.freescale.net
State Accepted
Commit 418396e212b59bf907dbccad997ff50f7eb61b16
Delegated to: Scott Wood
Headers show

Commit Message

Scott Wood March 28, 2012, 10:26 p.m. UTC
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(-)

Comments

Scott Wood May 18, 2012, 10:59 p.m. UTC | #1
On 03/28/2012 05:26 PM, Scott Wood wrote:
> 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(-)

Applied to u-boot-nand-flash.

-Scott
diff mbox

Patch

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: