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

Add command for changing Flex-OneNAND SLC / MLC boundary.
Signed-off-by: Rohit Hagargundgi h.rohit@samsung.com --- common/cmd_onenand.c | 65 +++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 56 insertions(+), 9 deletions(-)
diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c index 8d87b78..2caae45 100644 --- a/common/cmd_onenand.c +++ b/common/cmd_onenand.c @@ -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 at 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" );

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.
Signed-off-by: Rohit Hagargundgi h.rohit@samsung.com --- common/cmd_onenand.c | 88 ++++++++++++++++++++++++++++++++-------------- include/configs/apollon.h | 2 - 2 files changed, 64 insertions(+), 26 deletions(-)
diff --git a/include/configs/apollon.h b/include/configs/apollon.h index dff47fc..6e3e34a 100644 --- a/include/configs/apollon.h +++ b/include/configs/apollon.h @@ -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
diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c index 6a2c924..7779b44 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,21 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return ret == 0 ? 1 : 0; }
+ 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; }
@@ -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" "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 setboundary DIE BOUNDARY [LOCK] - " + "Change SLC boundary of Flex-OneNAND\n" );

On Sun, Mar 08, 2009 at 12:17:36PM +0530, Rohit Hagargundgi wrote:
+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?
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?
- 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

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

On Mon, Mar 23, 2009 at 12:36:32PM +0530, Amul Kumar Saha wrote:
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;
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).
- int blocks = (int) onenand_block(this, from + len)
- onenand_block(this, from);
Why the (int) cast? onenand_block() already returns int.
- 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.
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.
@@ -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.
- die = (int) simple_strtoul(argv[2], NULL, 0);
- bdry = (int) simple_strtoul(argv[3], NULL, 0);
Casts should not be necessary.
- if (argc == 5 && strncmp(argv[4], "LOCK", 4) == 0)
lock = 1;
Please have commands be lower-case, just like all the other ones.
-Scott

Hi Scott,
- int blocks = (int) onenand_block(this, from + len)
- onenand_block(this, from);
Why the (int) cast? onenand_block() already returns int.
Resolved
- 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.
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.
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.
- 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); }
- 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.
- 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

On Wed, Mar 25, 2009 at 08:44:37PM +0530, Amul Kumar Saha wrote:
- 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

Hi Scott,
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.

OneNAND commands now work for Flex-OneNAND. Add command for changing Flex-OneNAND SLC / MLC boundary.
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, 73 insertions(+), 32 deletions(-)
diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c index 5832ff8..8d25238 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 = 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 at 0x%x", (u32)(ofs >> this->erase_shift), (u32)ofs); + while (blocks <= end_block) { + printf("\rTesting block %d at 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 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
participants (3)
-
Amul Kumar Saha
-
Rohit Hagargundgi
-
Scott Wood