
Hi,
In u-boot, I only comment the u-boot part only. others are same at mtd mailing list.
generally looks good to me. except minor ones.
Thank you, Kyungmin Park
--- a/common/cmd_onenand.c +++ b/common/cmd_onenand.c @@ -20,9 +20,64 @@
extern struct mtd_info onenand_mtd; extern struct onenand_chip onenand_chip; +loff_t flexonenand_get_addr(int block)
Should be static. maybe you use this one for drviers/mtd/onenand. but it's not good idea. I want to separate onenand command and driver codes.
+{
struct mtd_info *mtd = &onenand_mtd;
struct onenand_chip *this = mtd->priv;
loff_t ofs;
int die = 0, boundary;
ofs = 0;
if (this->dies == 2 && block >= this->density_mask) {
block -= this->density_mask;
die = 1;
ofs = this->diesize[0];
}
boundary = this->boundary[die];
ofs += block << (this->erase_shift - 1);
if (block > (boundary + 1))
ofs += (block - boundary - 1) << (this->erase_shift - 1);
return ofs;
+}
+static int do_erase(ulong start, ulong end) +{
struct mtd_info *mtd = &onenand_mtd;
struct onenand_chip *this = mtd->priv;
struct erase_info instr = {
.callback = NULL,
};
int i, ret;
ulong block;
printf("Erase block from %lu to %lu\n", start, end);
for (block = start; block <= end; block++) {
if (FLEXONENAND(this))
instr.addr = flexonenand_get_addr(block);
else
instr.addr = block << onenand_chip.erase_shift;
if (FLEXONENAND(this) && (mtd->numeraseregions > 1)) {
for (i = 0; i < mtd->numeraseregions &&
mtd->eraseregions[i].offset <= instr.addr;
i++)
;
i--;
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);
}
return 0;
+}
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) {
@@ -42,11 +97,7 @@ default: /* At least 4 args */ if (strncmp(argv[1], "erase", 5) == 0) {
struct erase_info instr = {
.callback = NULL,
}; ulong start, end;
ulong block; char *endtail; if (strncmp(argv[2], "block", 5) == 0) {
@@ -57,28 +108,18 @@ 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(&onenand_mtd,
start, NULL);
end = onenand_get_block(&onenand_mtd,
end, NULL); /* Don't include the end block */
end--;
if (end > 0)
end--; } if (!end || end < 0) end = start;
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;
ret = onenand_erase(&onenand_mtd, &instr);
if (ret) {
printf("erase failed %lu\n", block);
break;
}
}
return 0;
return do_erase(start, end); } if (strncmp(argv[1], "read", 4) == 0) {
@@ -134,15 +175,18 @@ ops.mode = MTD_OOB_PLACE;
ofs = block << onenand_chip.erase_shift;
if (FLEXONENAND(this))
ofs = flexonenand_get_addr(block);
else
ofs = block << onenand_chip.erase_shift; 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 +202,39 @@ 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, old;
if (!FLEXONENAND(this)) {
printf("Flex-OneNAND not found.\n");
return -1;
}
if (argc == 5 && strncmp(argv[4], "LOCK", 4) == 0)
lock = 1;
if (die >= this->dies) {
printf("Invalid die index\n");
return -1;
}
if (!(bdry % 2)) {
printf("Attempt to set even boundary
value.\n");
Typo, 'even' should be 'odd'.
bdry += 1;
printf("Setting boundary to %d\n", bdry);
}
old = this->boundary[die] + (die *
this->density_mask);
ret = flexonenand_set_boundary(mtd, die, bdry,
lock);
if (!ret) {
int new = this->boundary[die] +
(die * this->density_mask);
do_erase(min(old, new) + 1, max(old, new));
}
return 0;
} break; }
@@ -172,5 +249,7 @@ "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"
); diff --git a/common/env_onenand.c b/common/env_onenand.c --- a/common/env_onenand.c +++ b/common/env_onenand.c @@ -58,11 +58,14 @@
void env_relocate_spec(void) {
struct onenand_chip *this = &onenand_chip; unsigned long env_addr; int use_default = 0; size_t retlen; env_addr = CONFIG_ENV_ADDR;
if (FLEXONENAND(this))
env_addr = CONFIG_ENV_ADDR_FLEX;
Umm do you have more fancy method to determine the environment address whatever it's OneNAND or not.
/* Check OneNAND exist */ if (onenand_mtd.writesize)
@@ -89,6 +92,7 @@
int saveenv(void) {
struct onenand_chip *this = &onenand_chip; unsigned long env_addr = CONFIG_ENV_ADDR; struct erase_info instr = { .callback = NULL,
@@ -96,6 +100,12 @@ size_t retlen;
instr.len = CONFIG_ENV_SIZE;
if (FLEXONENAND(this)) {
env_addr = CONFIG_ENV_ADDR_FLEX;
instr.len = CONFIG_ENV_SIZE_FLEX;
instr.len <<= onenand_mtd.eraseregions[0].numblocks == 1 ?
1 : 0;
}
Ditto.
instr.addr = env_addr; if (onenand_erase(&onenand_mtd, &instr)) { printf("OneNAND: erase failed at 0x%08lx\n", env_addr);