Skip to contentSkip to conversation

Flex-OneNAND boundary setting command

PATCH New Rohit Hagargundgi 3 participants 9 messages Dec 11, 2008 – Mar 26, 2009

lore
Share & tools
lore
#0 lore raw

PATCH v2 4/4 Flex-OneNAND boundary setting command

Add command for changing Flex-OneNAND SLC / MLC boundary.

---
 common/cmd_onenand.c |   65 +++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 56 insertions(+), 9 deletions(-)
common/cmd_onenand.c +56 -9
index 8d87b78..2caae45 100644
@@ -21,8 +21,35 @@
 extern struct mtd_info onenand_mtd;
 extern struct onenand_chip onenand_chip;
 
+/**
+ * do_set_boundary - [Flex-OneNAND] Set boundary of Flex-OneNAND
+ * @param mtd		mtd information structure
+ * @param die		die of device for which boundary will be set
+ * @param bdry		new boundary value ie last SLC block of die
+ *
+ * Set boundary of Flex-OneNAND
+ */
+int do_set_boundary(struct mtd_info *mtd, unsigned die, unsigned bdry, int lock)
+{
+	struct onenand_chip *this = mtd->priv;
+
+	if (!FLEXONENAND(this)) {
+		printf("Flex-OneNAND not found.\n");
+		return -1;
+	}
+
+	if (die >= this->dies) {
+		printf("Invalid die index\n");
+		return -1;
+	}
+
+	return flexonenand_set_boundary(mtd, die, bdry, lock);
+}
+
 int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 {
+	struct mtd_info *mtd = &onenand_mtd;
+	struct onenand_chip *this = mtd->priv;
 	int ret = 0;
 
 	switch (argc) {
@@ -57,10 +84,11 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 				start = simple_strtoul(argv[2], NULL, 10);
 				end = simple_strtoul(argv[3], NULL, 10);
 
-				start >>= onenand_chip.erase_shift;
-				end >>= onenand_chip.erase_shift;
+				start = onenand_get_block(this,	start, NULL);
+				end = onenand_get_block(this, end, NULL);
 				/* Don't include the end block */
-				end--;
+				if (end > 0)
+					end--;
 			}
 
 			if (!end || end < 0)
@@ -69,8 +97,13 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 			printf("Erase block from %lu to %lu\n", start, end);
 
 			for (block = start; block <= end; block++) {
-				instr.addr = block << onenand_chip.erase_shift;
-				instr.len = 1 << onenand_chip.erase_shift;
+				instr.addr = onenand_get_addr(this, block);
+				if (mtd->numeraseregions > 1) {
+					int i = flexonenand_region(mtd, instr.addr);
+					instr.len = mtd->eraseregions[i].erasesize;
+				} else
+					instr.len = mtd->erasesize;
+
 				ret = onenand_erase(&onenand_mtd, &instr);
 				if (ret) {
 					printf("erase failed %lu\n", block);
@@ -134,15 +167,15 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 			ops.mode = MTD_OOB_PLACE;
 
 
-			ofs = block << onenand_chip.erase_shift;
+			ofs = onenand_get_addr(this, block);
 			if (page)
 				ofs += page << onenand_chip.page_shift;
 
 			if (!len) {
 				if (oob)
-					ops.ooblen = 64;
+					ops.ooblen = FLEXONENAND(this) ? 128 : 64;
 				else
-					ops.len = 512;
+					ops.len = FLEXONENAND(this) ? 4096 : 512;
 			}
 
 			if (oob) {
@@ -158,6 +191,18 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 			return 0;
 		}
 
+		if (strncmp(argv[1], "setboundary", 11) == 0) {
+			unsigned die = simple_strtoul(argv[2], NULL, 0);
+			unsigned bdry = simple_strtoul(argv[3], NULL, 0);
+			int lock = 0;
+
+			if (argc == 5 && strncmp(argv[4], "LOCK", 4) == 0)
+				lock = 1;
+
+			do_set_boundary(mtd, die, bdry, lock);
+			return 0;
+		}
+
 		break;
 	}
 
@@ -172,5 +217,7 @@ U_BOOT_CMD(
 	"onenand write addr ofs len - write data@ofs with len from addr\n"
 	"onenand erase saddr eaddr - erase block start addr to end addr\n"
 	"onenand block[.oob] addr block [page] [len] - "
-		"read data with (block [, page]) to addr"
+		"read data with (block [, page]) to addr\n"
+	"onenand setboundary DIE BOUNDARY [LOCK] - "
+	"Change SLC boundary of Flex-OneNAND\n"
 );
Signature · 1 line
1.5.4.3
#1 lore raw

PATCH v2 4/4 Flex-OneNAND boundary setting command

Quoted 2 lines · On Thursday 11 December 2008 19:57:53 Rohit Hagargundgi wrote:

Add command for changing Flex-OneNAND SLC / MLC boundary.

Also onenand commands work for Flex-OneNAND.

---
 common/cmd_onenand.c      |   88 ++++++++++++++++++++++++++++++++--------------
 include/configs/apollon.h |    2 -
 2 files changed, 64 insertions(+), 26 deletions(-)
include/configs/apollon.h +1 -1
index dff47fc..6e3e34a 100644
@@ -76,7 +76,7 @@
  */
 #define	CONFIG_ENV_SIZE SZ_128K	/* Total Size of Environment Sector */
 #define CONFIG_ENV_SIZE_FLEX SZ_256K
-#define	CONFIG_SYS_MALLOC_LEN	(CONFIG_ENV_SIZE + SZ_1M)
+#define	CONFIG_SYS_MALLOC_LEN	(CONFIG_ENV_SIZE + SZ_2M)
 /* bytes reserved for initial data */
 #define	CONFIG_SYS_GBL_DATA_SIZE	128
 
common/cmd_onenand.c +63 -25

194 lines not on this page · raw message

#2 lore raw

PATCH v2 4/4 Flex-OneNAND boundary setting command

common/cmd_onenand.c static int arg_off_size(int argc, char *argv[], ulong *off, size_t *size) · line 77

Quoted 10 lines · Rohit Hagargundgi
common/cmd_onenand.c +10 -0
+static inline int onenand_blocksize(loff_t ofs)
+{
+	struct onenand_chip *this = mtd->priv;
+	int i;
+
+	if (!FLEXONENAND(this))
+		return mtd->erasesize;
+
+	i = flexonenand_region(mtd, ofs);
+	return mtd->eraseregions[i].erasesize;

Can we define the interface to the onenand code such that the caller doesn't need to care what type of onenand it is, and non-flex will simply appear to have one region?

Quoted 4 lines
common/cmd_onenand.c +4 -0
+		if (strncmp(cmd, "setboundary", 11) == 0) {
+			int die, bdry, lock = 0;
+
+			if (argc < 4)

common/cmd_onenand.c int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) · line 496

Quoted 10 lines
common/cmd_onenand.c +10 -0
+				goto usage;
+
+			die = (int) simple_strtoul(argv[2], NULL, 0);
+			bdry = (int) simple_strtoul(argv[3], NULL, 0);
+
+			if (argc == 5 && strncmp(argv[4], "LOCK", 4) == 0)
+				lock = 1;
+
+			return flexonenand_set_boundary(mtd, die, bdry, lock);
+		}

What happens if the user runs the setboundary command on non-flex onenand? Does it fail gracefully?

common/cmd_onenand.c U_BOOT_CMD( · line 517

Quoted 10 lines
common/cmd_onenand.c +2 -1
+
 		break;
 	}
@@ -478,9 +514,11 @@ U_BOOT_CMD(
 	"onenand write[.oob] addr off size\n"
 	"    read/write 'size' bytes starting at offset 'off'\n"
 	"    to/from memory address 'addr', skipping bad blocks.\n"
-	"onenand erase [force] [off size] - erase 'size' bytes from\n"
+	"onenand erase [force] [off size] - erase 'size' bytes from off\n"

Quotes around 'off', as is done elsewhere in the help text.

-Scott

#3 lore raw

PATCH v2 4/4 Flex-OneNAND boundary setting command

Hi Scott,

Quoted 6 lines
Quoted 6 lines
(quoted diff) +6 -0
+static inline int onenand_blocksize(loff_t ofs)
+{
+ struct onenand_chip *this = mtd->priv;
+ int i;
+
+ if (!FLEXONENAND(this))
Quoted 9 lines
Quoted 4 lines

+ return mtd->erasesize;
+
+ i = flexonenand_region(mtd, ofs);
+ return mtd->eraseregions[i].erasesize;

Can we define the interface to the onenand code such that the caller doesn't need to care what type of onenand it is, and non-flex will simply appear to have one region?

Right. We shall take this on moving ahead. Guess this is fine for now.

Quoted 9 lines
Quoted 9 lines

+ if (strncmp(cmd, "setboundary", 11) == 0) {
+ int die, bdry, lock = 0;

(quoted diff) +7 -0
+
+ if (argc < 4)
+ goto usage;
+
+ die = (int) simple_strtoul(argv[2], NULL, 0);
+ bdry = (int) simple_strtoul(argv[3], NULL, 0);
+
Quoted 9 lines
Quoted 5 lines

+ if (argc == 5 && strncmp(argv[4], "LOCK", 4) == 0)
+ lock = 1;
+
+ return flexonenand_set_boundary(mtd, die, bdry, lock);
+ }

What happens if the user runs the setboundary command on non-flex onenand? Does it fail gracefully?

Resolved.

Quoted 4 lines
Quoted 4 lines

+
break;
}

Quoted 9 lines

Review U_BOOT_CMD( · line 517

Quoted 6 lines
(quoted diff) +1 -1
@@ -478,9 +514,11 @@ U_BOOT_CMD(
 "onenand write[.oob] addr off size\n"
 "    read/write 'size' bytes starting at offset 'off'\n"
 "    to/from memory address 'addr', skipping bad blocks.\n"
- "onenand erase [force] [off size] - erase 'size' bytes from\n"
+ "onenand erase [force] [off size] - erase 'size' bytes from off\n"

Quotes around 'off', as is done elsewhere in the help text.

Resolved

OneNAND commands now work for Flex-OneNAND.
Add command for changing Flex-OneNAND SLC / MLC boundary.

Thank You,
Amul Kumar Saha

---
 common/cmd_onenand.c      |  103 ++++++++++++++++++++++++++++++++--------------
 include/configs/apollon.h |    2
 2 files changed, 74 insertions(+), 31 deletions(-)
common/cmd_onenand.c +73 -30
index 5832ff8..ed6681a 100644
@@ -65,36 +65,49 @@ static int arg_off_size(int argc, char *argv[], ulong *off, size_t *size)
  return 0;
 }
 
+static inline int onenand_blocksize(loff_t ofs)
+{
+ struct onenand_chip *this = mtd->priv;
+ int i;
+
+ if (!FLEXONENAND(this))
+  return mtd->erasesize;
+
+ i = flexonenand_region(mtd, ofs);
+ return mtd->eraseregions[i].erasesize;
+}
+
 static int onenand_block_read(loff_t from, size_t len,
          size_t *retlen, u_char *buf, int oob)
 {
  struct onenand_chip *this = mtd->priv;
- int blocks = (int) len >> this->erase_shift;
- int blocksize = (1 << this->erase_shift);
+ int blocks = (int) onenand_block(this, from + len)
+    - onenand_block(this, from);
+ int blocksize;
  loff_t ofs = from;
  struct mtd_oob_ops ops = {
   .retlen  = 0,
  };
  int ret;
 
- if (oob)
-  ops.ooblen = blocksize;
- else
-  ops.len = blocksize;
-
  while (blocks) {
+  blocksize = onenand_blocksize(ofs);
+
   ret = mtd->block_isbad(mtd, ofs);
   if (ret) {
    printk("Bad blocks %d at 0x%x\n",
-          (u32)(ofs >> this->erase_shift), (u32)ofs);
+          (u32)onenand_block(this, ofs), (u32)ofs);
    ofs += blocksize;
    continue;
   }
 
-  if (oob)
+  if (oob) {
    ops.oobbuf = buf;
-  else
+   ops.ooblen = blocksize;
+  } else {
    ops.datbuf = buf;
+   ops.len = blocksize;
+  }
 
   ops.retlen = 0;
   ret = mtd->read_oob(mtd, ofs, &ops);
@@ -116,8 +129,7 @@ static int onenand_block_write(loff_t to, size_t len,
           size_t *retlen, const u_char * buf)
 {
  struct onenand_chip *this = mtd->priv;
- int blocks = len >> this->erase_shift;
- int blocksize = (1 << this->erase_shift);
+ int blocks, blocksize;
  loff_t ofs;
  size_t _retlen = 0;
  int ret;
@@ -131,11 +143,15 @@ static int onenand_block_write(loff_t to, size_t len,
  }
  ofs = to;
 
+ blocks = (int) onenand_block(this, ofs + len) - onenand_block(this, ofs);
+
  while (blocks) {
+  blocksize = onenand_blocksize(ofs);
+
   ret = mtd->block_isbad(mtd, ofs);
   if (ret) {
    printk("Bad blocks %d at 0x%x\n",
-          (u32)(ofs >> this->erase_shift), (u32)ofs);
+          (u32)onenand_block(this, ofs), (u32)ofs);
    skip_ofs += blocksize;
    goto next;
   }
@@ -165,13 +181,15 @@ static int onenand_block_erase(u32 start, u32 size, int force)
  };
  loff_t ofs;
  int ret;
- int blocksize = 1 << this->erase_shift;
+ int blocksize;
 
  for (ofs = start; ofs < (start + size); ofs += blocksize) {
+  blocksize = onenand_blocksize(ofs);
+
   ret = mtd->block_isbad(mtd, ofs);
   if (ret && !force) {
    printf("Skip erase bad block %d at 0x%x\n",
-          (u32)(ofs >> this->erase_shift), (u32)ofs);
+          (u32)onenand_block(this, ofs), (u32)ofs);
    continue;
   }
 
@@ -182,7 +200,7 @@ static int onenand_block_erase(u32 start, u32 size, int force)
   ret = mtd->erase(mtd, &instr);
   if (ret) {
    printf("erase failed block %d at 0x%x\n",
-          (u32)(ofs >> this->erase_shift), (u32)ofs);
+          (u32)onenand_block(this, ofs), (u32)ofs);
    continue;
   }
  }
@@ -219,25 +237,27 @@ static int onenand_block_test(u32 start, u32 size)
   return -1;
  }
 
- start_block = start >> this->erase_shift;
- end_block = (start + size) >> this->erase_shift;
+ start_block = onenand_block(this, start);
+ end_block = onenand_block(this, start + size);
 
  /* Protect boot-loader from badblock testing */
  if (start_block < 2)
   start_block = 2;
 
- if (end_block > (mtd->size >> this->erase_shift))
-  end_block = mtd->size >> this->erase_shift;
+ if (end_block > onenand_block(this, mtd->size))
+  end_block = onenand_block(this, mtd->size);
 
  blocks = start_block;
  ofs = start;
  while (blocks < end_block) {
-  printf("\rTesting block %d@0x%x", (u32)(ofs >> this->erase_shift), (u32)ofs);
+  printf("\rTesting block %d at 0x%x", (u32) onenand_block(this, ofs), (u32)ofs);
+
+  blocksize = onenand_blocksize(ofs);
 
   ret = mtd->block_isbad(mtd, ofs);
   if (ret) {
    printf("Skip erase bad block %d at 0x%x\n",
-          (u32)(ofs >> this->erase_shift), (u32)ofs);
+          (u32)onenand_block(this, ofs), (u32)ofs);
    goto next;
   }
 
@@ -341,7 +361,6 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 
  mtd = &onenand_mtd;
  this = mtd->priv;
- blocksize = (1 << this->erase_shift);
 
  cmd = argv[1];
 
@@ -359,9 +378,11 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
   if (strcmp(cmd, "bad") == 0) {
    /* Currently only one OneNAND device is supported */
    printf("\nDevice %d bad blocks:\n", 0);
-   for (ofs = 0; ofs < mtd->size; ofs += mtd->erasesize) {
+   for (ofs = 0; ofs < mtd->size; ofs += blocksize) {
     if (mtd->block_isbad(mtd, ofs))
      printf("  %08x\n", (u32)ofs);
+
+    blocksize = onenand_blocksize(ofs);
    }
 
    return 0;
@@ -459,6 +480,26 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
    return ret == 0 ? 1 : 0;
   }
 
+  /*
+   * The following cmd holds true only for a Flex-OneNAND
+   */
+  if (FLEXONENAND(this)) {
+   if (strncmp(cmd, "setboundary", 11) == 0) {
+    int die, bdry, lock = 0;
+
+    if (argc < 4)
+     goto usage;
+
+    die = (int) simple_strtoul(argv[2], NULL, 0);
+    bdry = (int) simple_strtoul(argv[3], NULL, 0);
+
+    if (argc == 5 && strncmp(argv[4], "LOCK", 4) == 0)
+     lock = 1;
+
+    return flexonenand_set_boundary(mtd, die, bdry, lock);
+   }
+  }
+
   break;
  }
 
@@ -474,13 +515,15 @@ U_BOOT_CMD(
  "OneNAND sub-system",
  "info - show available OneNAND devices\n"
  "onenand bad - show bad blocks\n"
- "onenand read[.oob] addr off size\n"
- "onenand write[.oob] addr off size\n"
+ "onenand read[.oob] addr 'off' size\n"
+ "onenand write[.oob] addr 'off' size\n"
  "    read/write 'size' bytes starting at offset 'off'\n"
  "    to/from memory address 'addr', skipping bad blocks.\n"
- "onenand erase [force] [off size] - erase 'size' bytes from\n"
- "onenand test [off size] - test 'size' bytes from\n"
+ "onenand erase [force] ['off' size] - erase 'size' bytes from 'off'\n"
+ "onenand test ['off' size] - test 'size' bytes from\n"
  "    offset 'off' (entire device if not specified)\n"
- "onenand dump[.oob] off - dump page\n"
- "onenand markbad off - mark bad block at offset (UNSAFE)\n"
+ "onenand dump[.oob] 'off' - dump page\n"
+ "onenand markbad 'off' - mark bad block@offset (UNSAFE)\n"
+ "onenand setboundary DIE BOUNDARY [LOCK] - "
+ "Change SLC boundary of Flex-OneNAND\n"
 );
include/configs/apollon.h +1 -1
index 0fcb22b..3a096c8 100644
@@ -77,7 +77,7 @@
  */
 #define CONFIG_ENV_SIZE SZ_128K /* Total Size of Environment Sector */
 #define CONFIG_ENV_SIZE_FLEX SZ_256K
-#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + SZ_1M)
+#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + SZ_2M)
 /* bytes reserved for initial data */
 #define CONFIG_SYS_GBL_DATA_SIZE 128
#4 lore raw

PATCH v2 4/4 Flex-OneNAND boundary setting command

common/cmd_onenand.c static int arg_off_size(int argc, char *argv[], ulong · line 72

Quoted 13 lines · Amul Kumar Saha
common/cmd_onenand.c +4 -0
index 5832ff8..ed6681a 100644
@@ -65,36 +65,49 @@ static int arg_off_size(int argc, char *argv[], ulong 
 *off, size_t *size)
 return 0;
 }
 
+static inline int onenand_blocksize(loff_t ofs)
+{
+ struct onenand_chip *this = mtd->priv;
+ int i;

Patch is whitespace-damaged. Please send the patch separately (not as a reply; it's easy to miss patches at the end of a reply, and I have to manually strip the discussion from the changelog) using something that will preserve the patch text intact (not Outlook Express).

common/cmd_onenand.c static int arg_off_size(int argc, char *argv[], ulong *off, size_t *size) · line 85

Quoted 2 lines
common/cmd_onenand.c +2 -0
+ int blocks = (int) onenand_block(this, from + len)
+    - onenand_block(this, from);

Why the (int) cast? onenand_block() already returns int.

common/cmd_onenand.c static int onenand_block_test(u32 start, u32 size) · line 248

Quoted 4 lines
common/cmd_onenand.c +2 -2
- if (end_block > (mtd->size >> this->erase_shift))
-  end_block = mtd->size >> this->erase_shift;
+ if (end_block > onenand_block(this, mtd->size))
+  end_block = onenand_block(this, mtd->size);

This should probably be:

if (end_block >= onenand_block(this, mtd->size - 1))

...to avoid asking for a block that doesn't exist.

common/cmd_onenand.c static int arg_off_size(int argc, char *argv[], ulong · line 82

Quoted 7 lines
common/cmd_onenand.c +1 -1
 blocks = start_block;
 ofs = start;
 while (blocks < end_block) {
-  printf("\rTesting block %d at 0x%x", (u32)(ofs >> this->erase_shift), 
 (u32)ofs);
+  printf("\rTesting block %d at 0x%x", (u32) onenand_block(this, ofs), 
 (u32)ofs);

No (u32) cast on return from onenand_block(). Likewise elsewhere.

common/cmd_onenand.c int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, · line 387

Quoted 12 lines
common/cmd_onenand.c +3 -1
@@ -359,9 +378,11 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, 
 char *argv[])
  if (strcmp(cmd, "bad") == 0) {
   /* Currently only one OneNAND device is supported */
   printf("\nDevice %d bad blocks:\n", 0);
-   for (ofs = 0; ofs < mtd->size; ofs += mtd->erasesize) {
+   for (ofs = 0; ofs < mtd->size; ofs += blocksize) {
    if (mtd->block_isbad(mtd, ofs))
     printf("  %08x\n", (u32)ofs);
+
+    blocksize = onenand_blocksize(ofs);
   }

Hmm, not sure I like blocksize being used in the for loop when it's first initialized in the body of the loop. It's valid code, but it might be more readable as a while loop.

common/cmd_onenand.c int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) · line 494

Quoted 2 lines
common/cmd_onenand.c +2 -0
+    die = (int) simple_strtoul(argv[2], NULL, 0);
+    bdry = (int) simple_strtoul(argv[3], NULL, 0);

Casts should not be necessary.

common/cmd_onenand.c int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) · line 497

Quoted 2 lines
common/cmd_onenand.c +2 -0
+    if (argc == 5 && strncmp(argv[4], "LOCK", 4) == 0)
+     lock = 1;

Please have commands be lower-case, just like all the other ones.

-Scott

#5 lore raw

PATCH v2 4/4 Flex-OneNAND boundary setting command

In reply to Scott Wood

Hi Scott,

Quoted 6 lines
Quoted 3 lines

+ int blocks = (int) onenand_block(this, from + len)
+ - onenand_block(this, from);

Why the (int) cast? onenand_block() already returns int.

Resolved

Quoted 11 lines

common/cmd_onenand.c static int onenand_block_test(u32 start, u32 size) · line 248

Quoted 4 lines

- if (end_block > (mtd->size >> this->erase_shift))

common/cmd_onenand.c +2 -1
-  end_block = mtd->size >> this->erase_shift;
+ if (end_block > onenand_block(this, mtd->size))
+  end_block = onenand_block(this, mtd->size);

This should probably be:

if (end_block >= onenand_block(this, mtd->size - 1))

...to avoid asking for a block that doesn't exist.

Changed from mtd->size to (mtd->size) - 1,
In the OP, end_block was understood to accomodate (last_block_no + 1). But, as you have pointed it may be more conventional to have the exact last_block_no

made necessary changes in some other places as well.

Quoted 10 lines
Quoted 7 lines

blocks = start_block;
ofs = start;
while (blocks < end_block) {
- printf("\rTesting block %d at 0x%x", (u32)(ofs >> this->erase_shift), (u32)ofs);
+ printf("\rTesting block %d at 0x%x", (u32) onenand_block(this, ofs), (u32)ofs);

No (u32) cast on return from onenand_block(). Likewise elsewhere.

Accepted and changed.

Quoted 11 lines

common/cmd_onenand.c int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) · line 386

Quoted 6 lines
common/cmd_onenand.c +3 -0
+   for (ofs = 0; ofs < mtd->size; ofs += blocksize) {
    if (mtd->block_isbad(mtd, ofs))
     printf("  %08x\n", (u32)ofs);
+
+    blocksize = onenand_blocksize(ofs);
   }

Hmm, not sure I like blocksize being used in the for loop when it's first initialized in the body of the loop. It's valid code, but it might be more readable as a while loop.

Modified it to a while loop. Thanks :)

ofs = 0;
while (ofs < mtd->size) {
if (mtd->block_isbad(mtd, ofs))

     printf("  %08x\n", (u32)ofs);

ofs += onenand_blocksize(ofs);
}

Quoted 5 lines

common/cmd_onenand.c int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) · line 490

Quoted 2 lines
common/cmd_onenand.c +2 -0
+    die = (int) simple_strtoul(argv[2], NULL, 0);
+    bdry = (int) simple_strtoul(argv[3], NULL, 0);

Casts should not be necessary.

I believe that typecasting a UL to an int, is OK.
Do let me know.

Quoted 5 lines

common/cmd_onenand.c int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) · line 493

Quoted 2 lines
common/cmd_onenand.c +2 -0
+    if (argc == 5 && strncmp(argv[4], "LOCK", 4) == 0)
+     lock = 1;

Please have commands be lower-case, just like all the other ones.

Changed

Do let me know, your feedback on the changes made. I'll send the updated patch, in the next post.

With regards,
Amul

#6 lore raw

PATCH v2 4/4 Flex-OneNAND boundary setting command

Quoted 8 lines · Amul Kumar Saha
Quoted 5 lines

common/cmd_onenand.c int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) · line 490

Quoted 2 lines
common/cmd_onenand.c +2 -0
+    die = (int) simple_strtoul(argv[2], NULL, 0);
+    bdry = (int) simple_strtoul(argv[3], NULL, 0);

Casts should not be necessary.

I believe that typecasting a UL to an int, is OK.
Do let me know.

The compiler will implicitly cast unsigned long to int. The explicit cast is unnecessary clutter which makes it harder to find casts that aren't OK.

-Scott

#7 lore raw

PATCH v2 4/4 Flex-OneNAND boundary setting command

Hi Scott,

Quoted 5 lines
Quoted 2 lines

I believe that typecasting a UL to an int, is OK.
Do let me know.

The compiler will implicitly cast unsigned long to int. The explicit cast is unnecessary clutter which makes it harder to find casts that aren't OK.

Accepted and changed.

Thank You
Amul.

#8 lore raw

PATCH v2 4/4 Flex-OneNAND boundary setting command

In reply to Scott Wood

OneNAND commands now work for Flex-OneNAND.
Add command for changing Flex-OneNAND SLC / MLC boundary.

---
common/cmd_onenand.c | 103 ++++++++++++++++++++++++++++++++--------------
include/configs/apollon.h | 2

2 files changed, 73 insertions(+), 32 deletions(-)
common/cmd_onenand.c +72 -31
index 5832ff8..8d25238 100644
@@ -65,36 +65,49 @@ static int arg_off_size(int argc, char *argv[], ulong *off, size_t *size)
 	return 0;
 }
 
+static inline int onenand_blocksize(loff_t ofs)
+{
+	struct onenand_chip *this = mtd->priv;
+	int i;
+
+	if (!FLEXONENAND(this))
+		return mtd->erasesize;
+
+	i = flexonenand_region(mtd, ofs);
+	return mtd->eraseregions[i].erasesize;
+}
+
 static int onenand_block_read(loff_t from, size_t len,
 			      size_t *retlen, u_char *buf, int oob)
 {
 	struct onenand_chip *this = mtd->priv;
-	int blocks = (int) len >> this->erase_shift;
-	int blocksize = (1 << this->erase_shift);
+	int blocks = onenand_block(this, from + len)
+			 - onenand_block(this, from);
+	int blocksize;
 	loff_t ofs = from;
 	struct mtd_oob_ops ops = {
 		.retlen		= 0,
 	};
 	int ret;
 
-	if (oob)
-		ops.ooblen = blocksize;
-	else
-		ops.len = blocksize;
-
 	while (blocks) {
+		blocksize = onenand_blocksize(ofs);
+
 		ret = mtd->block_isbad(mtd, ofs);
 		if (ret) {
 			printk("Bad blocks %d at 0x%x\n",
-			       (u32)(ofs >> this->erase_shift), (u32)ofs);
+			       onenand_block(this, ofs), (u32)ofs);
 			ofs += blocksize;
 			continue;
 		}
 
-		if (oob)
+		if (oob) {
 			ops.oobbuf = buf;
-		else
+			ops.ooblen = blocksize;
+		} else {
 			ops.datbuf = buf;
+			ops.len = blocksize;
+		}
 
 		ops.retlen = 0;
 		ret = mtd->read_oob(mtd, ofs, &ops);
@@ -116,8 +129,7 @@ static int onenand_block_write(loff_t to, size_t len,
 			       size_t *retlen, const u_char * buf)
 {
 	struct onenand_chip *this = mtd->priv;
-	int blocks = len >> this->erase_shift;
-	int blocksize = (1 << this->erase_shift);
+	int blocks, blocksize;
 	loff_t ofs;
 	size_t _retlen = 0;
 	int ret;
@@ -131,11 +143,15 @@ static int onenand_block_write(loff_t to, size_t len,
 	}
 	ofs = to;
 
+	blocks = onenand_block(this, ofs + len) - onenand_block(this, ofs);
+
 	while (blocks) {
+		blocksize = onenand_blocksize(ofs);
+
 		ret = mtd->block_isbad(mtd, ofs);
 		if (ret) {
 			printk("Bad blocks %d at 0x%x\n",
-			       (u32)(ofs >> this->erase_shift), (u32)ofs);
+			       onenand_block(this, ofs), (u32)ofs);
 			skip_ofs += blocksize;
 			goto next;
 		}
@@ -165,13 +181,15 @@ static int onenand_block_erase(u32 start, u32 size, int force)
 	};
 	loff_t ofs;
 	int ret;
-	int blocksize = 1 << this->erase_shift;
+	int blocksize;
 
 	for (ofs = start; ofs < (start + size); ofs += blocksize) {
+		blocksize = onenand_blocksize(ofs);
+
 		ret = mtd->block_isbad(mtd, ofs);
 		if (ret && !force) {
 			printf("Skip erase bad block %d at 0x%x\n",
-			       (u32)(ofs >> this->erase_shift), (u32)ofs);
+			       onenand_block(this, ofs), (u32)ofs);
 			continue;
 		}
 
@@ -182,7 +200,7 @@ static int onenand_block_erase(u32 start, u32 size, int force)
 		ret = mtd->erase(mtd, &instr);
 		if (ret) {
 			printf("erase failed block %d at 0x%x\n",
-			       (u32)(ofs >> this->erase_shift), (u32)ofs);
+			       onenand_block(this, ofs), (u32)ofs);
 			continue;
 		}
 	}
@@ -219,25 +237,27 @@ static int onenand_block_test(u32 start, u32 size)
 		return -1;
 	}
 
-	start_block = start >> this->erase_shift;
-	end_block = (start + size) >> this->erase_shift;
+	start_block = onenand_block(this, start);
+	end_block = onenand_block(this, start + size - 1);
 
 	/* Protect boot-loader from badblock testing */
 	if (start_block < 2)
 		start_block = 2;
 
-	if (end_block > (mtd->size >> this->erase_shift))
-		end_block = mtd->size >> this->erase_shift;
+	if (end_block > onenand_block(this, mtd->size - 1))
+		end_block = onenand_block(this, mtd->size - 1);
 
 	blocks = start_block;
 	ofs = start;
-	while (blocks < end_block) {
-		printf("\rTesting block %d@0x%x", (u32)(ofs >> this->erase_shift), (u32)ofs);
+	while (blocks <= end_block) {
+		printf("\rTesting block %d@0x%x", onenand_block(this, ofs), (u32)ofs);
+
+		blocksize = onenand_blocksize(ofs);
 
 		ret = mtd->block_isbad(mtd, ofs);
 		if (ret) {
 			printf("Skip erase bad block %d at 0x%x\n",
-			       (u32)(ofs >> this->erase_shift), (u32)ofs);
+			       onenand_block(this, ofs), (u32)ofs);
 			goto next;
 		}
 
@@ -341,7 +361,6 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 
 	mtd = &onenand_mtd;
 	this = mtd->priv;
-	blocksize = (1 << this->erase_shift);
 
 	cmd = argv[1];
 
@@ -359,9 +378,12 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 		if (strcmp(cmd, "bad") == 0) {
 			/* Currently only one OneNAND device is supported */
 			printf("\nDevice %d bad blocks:\n", 0);
-			for (ofs = 0; ofs < mtd->size; ofs += mtd->erasesize) {
+			ofs = 0;
+			while (ofs < mtd->size) {
 				if (mtd->block_isbad(mtd, ofs))
 					printf("  %08x\n", (u32)ofs);
+
+				ofs += onenand_blocksize(ofs);
 			}
 
 			return 0;
@@ -459,6 +481,23 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 			return ret == 0 ? 1 : 0;
 		}
 
+		if (FLEXONENAND(this)) {
+			if (strncmp(cmd, "setboundary", 11) == 0) {
+				int die, bdry, lock = 0;
+
+				if (argc < 4)
+					goto usage;
+
+				die = (int) simple_strtoul(argv[2], NULL, 0);
+				bdry = (int) simple_strtoul(argv[3], NULL, 0);
+
+				if (argc == 5 && strncmp(argv[4], "lock", 4) == 0)
+					lock = 1;
+
+				return flexonenand_set_boundary(mtd, die, bdry, lock);
+			}
+		}
+
 		break;
 	}
 
@@ -474,13 +513,15 @@ U_BOOT_CMD(
 	"OneNAND sub-system",
 	"info - show available OneNAND devices\n"
 	"onenand bad - show bad blocks\n"
-	"onenand read[.oob] addr off size\n"
-	"onenand write[.oob] addr off size\n"
+	"onenand read[.oob] addr 'off' size\n"
+	"onenand write[.oob] addr 'off' size\n"
 	"    read/write 'size' bytes starting at offset 'off'\n"
 	"    to/from memory address 'addr', skipping bad blocks.\n"
-	"onenand erase [force] [off size] - erase 'size' bytes from\n"
-	"onenand test [off size] - test 'size' bytes from\n"
+	"onenand erase [force] ['off' size] - erase 'size' bytes from 'off'\n"
+	"onenand test ['off' size] - test 'size' bytes from\n"
 	"    offset 'off' (entire device if not specified)\n"
-	"onenand dump[.oob] off - dump page\n"
-	"onenand markbad off - mark bad block at offset (UNSAFE)\n"
+	"onenand dump[.oob] 'off' - dump page\n"
+	"onenand markbad 'off' - mark bad block@offset (UNSAFE)\n"
+	"onenand setboundary DIE BOUNDARY [LOCK] - "
+	"Change SLC boundary of Flex-OneNAND\n"
 );
include/configs/apollon.h +1 -1
index 0fcb22b..3a096c8 100644
@@ -77,7 +77,7 @@
  */
 #define	CONFIG_ENV_SIZE SZ_128K	/* Total Size of Environment Sector */
 #define CONFIG_ENV_SIZE_FLEX SZ_256K
-#define	CONFIG_SYS_MALLOC_LEN	(CONFIG_ENV_SIZE + SZ_1M)
+#define	CONFIG_SYS_MALLOC_LEN	(CONFIG_ENV_SIZE + SZ_2M)
 /* bytes reserved for initial data */
 #define	CONFIG_SYS_GBL_DATA_SIZE	128