[U-Boot] [PATCH] Flex-OneNAND driver
Kyungmin Park
kmpark at infradead.org
Fri Sep 26 03:27:20 CEST 2008
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);
More information about the U-Boot
mailing list