Skip to contentSkip to conversation

nand: extend .raw accesses to work on multiple pages

PATCH New Scott Wood 3 participants 5 messages Mar 28, 2012 – May 18, 2012

lore
Share & tools
lore

Scott Wood

author
#0 lore raw

PATCH 1/2 nand: extend .raw accesses to work on multiple pages

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.

---
 common/cmd_nand.c |   95 +++++++++++++++++++++++++++++++++++++++-------------
 doc/README.nand   |   16 ++++----
 2 files changed, 79 insertions(+), 32 deletions(-)
common/cmd_nand.c +71 -24
index bae630d..4456706 100644
@@ -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"
doc/README.nand +8 -8
index 04a87c9..1602b5e 100644
@@ -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:
 
Signature · 1 line
1.7.7.rc3.4.g8d714
author
#1 lore raw

PATCH 1/2 nand: extend .raw accesses to work on multiple pages

Quoted 10 lines · Scott Wood

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.

---
 common/cmd_nand.c |   95 +++++++++++++++++++++++++++++++++++++++-------------
 doc/README.nand   |   16 ++++----
 2 files changed, 79 insertions(+), 32 deletions(-)

Applied to u-boot-nand-flash.

-Scott

author
#2 lore raw

PATCH 2/2 nand: remote biterr command stub

In reply to Scott Wood

It can be scripted instead with .raw accesses.

---
 common/cmd_nand.c |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)
common/cmd_nand.c +0 -6
index 4456706..368c9f2 100644
@@ -723,11 +723,6 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 		return ret;
 	}
 
-	if (strcmp(cmd, "biterr") == 0) {
-		/* todo */
-		return 1;
-	}
-
 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
 	if (strcmp(cmd, "lock") == 0) {
 		int tight = 0;
@@ -804,7 +799,6 @@ U_BOOT_CMD(
 	"nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
 	"    really clean NAND erasing bad blocks (UNSAFE)\n"
 	"nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
-	"nand biterr off - make a bit error at offset (UNSAFE)"
 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
 	"\n"
 	"nand lock [tight] [status]\n"
Signature · 1 line
1.7.7.rc3.4.g8d714
#3 lore raw

PATCH 2/2 nand: remote biterr command stub

Quoted 1 line · On Thursday 29 March 2012 00:27:43 Scott Wood wrote:

It can be scripted instead with .raw accesses.

Typo in the subject: s/remote/remove

Thanks,
Stefan

#4 lore raw

PATCH 2/2 nand: remote biterr command stub

In reply to Scott Wood

Dear Scott Wood,

Quoted 3 lines · In message <[email protected]> you wrote:

It can be scripted instead with .raw accesses.

Can you please add an example how to do that to the commit message? Thanks.

Best regards,

Wolfgang Denk

Signature · 6 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
You Earth people glorified organized violence  for  forty  centuries.
But you imprison those who employ it privately.
	-- Spock, "Dagger of the Mind", stardate 2715.1