[U-Boot] [PATCH v2 4/4] Flex-OneNAND boundary setting command

Amul Kumar Saha amul.saha at samsung.com
Mon Mar 23 08:06:32 CET 2009


Hi Scott,

>> +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?
> 

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

>> + 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);
>> + }
> 
> What happens if the user runs the setboundary command on non-flex
> onenand?  Does it fail gracefully?
> 

Resolved.

>> +
>>  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.
> 

Resolved


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

Thank You,
Amul Kumar Saha


Signed-off-by: Rohit Hagargundgi <h.rohit at samsung.com>
Signed-off-by: Amul Kumar Saha <amul.saha at samsung.com>
---
 common/cmd_onenand.c      |  103 ++++++++++++++++++++++++++++++++--------------
 include/configs/apollon.h |    2
 2 files changed, 74 insertions(+), 31 deletions(-)

diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c
index 5832ff8..ed6681a 100644
--- a/common/cmd_onenand.c
+++ b/common/cmd_onenand.c
@@ -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 at 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 at offset (UNSAFE)\n"
+ "onenand setboundary DIE BOUNDARY [LOCK] - "
+ "Change SLC boundary of Flex-OneNAND\n"
 );
diff --git a/include/configs/apollon.h b/include/configs/apollon.h
index 0fcb22b..3a096c8 100644
--- a/include/configs/apollon.h
+++ b/include/configs/apollon.h
@@ -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


More information about the U-Boot mailing list