
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