Message ID | 20231228153922.84323-5-avromanov@salutedevices.com |
---|---|
State | Superseded |
Delegated to: | Dario Binacchi |
Headers | show |
Series | Support SPI NAND in fastboot protocol | expand |
Hi Alexey On Thu, Dec 28, 2023 at 4:39 PM Alexey Romanov <avromanov@salutedevices.com> wrote: > > Currently nand_erase_opts() placed in the nand/raw/ folder, > because it uses the RAW NAND specific API (struct nand_chip). > This patch move it to core NAND folder and make function generic, > for both RAW/SPI NAND's usage. > > Also, nand_erase_opts() used in fastboot/fb_nand.c, cmd/nand.c > and env/nand.c code. This is also the reason why we should move > it to core folder and make it more general. > > Signed-off-by: Alexey Romanov <avromanov@salutedevices.com> > --- > drivers/mtd/nand/raw/nand_util.c | 153 ---------------------------- > drivers/mtd/nand/util.c | 166 +++++++++++++++++++++++++++++++ > 2 files changed, 166 insertions(+), 153 deletions(-) > > diff --git a/drivers/mtd/nand/raw/nand_util.c b/drivers/mtd/nand/raw/nand_util.c > index 9c18ce63b9..f7704d4697 100644 > --- a/drivers/mtd/nand/raw/nand_util.c > +++ b/drivers/mtd/nand/raw/nand_util.c > @@ -32,159 +32,6 @@ > #include <linux/mtd/mtd.h> > #include <linux/mtd/rawnand.h> > #include <nand.h> > -#include <jffs2/jffs2.h> > - > -typedef struct erase_info erase_info_t; > - > -/* support only for native endian JFFS2 */ > -#define cpu_to_je16(x) (x) > -#define cpu_to_je32(x) (x) > - > -/** > - * nand_erase_opts: - erase NAND flash with support for various options > - * (jffs2 formatting) > - * > - * @param mtd nand mtd instance to erase > - * @param opts options, @see struct nand_erase_options > - * Return: 0 in case of success > - * > - * This code is ported from flash_eraseall.c from Linux mtd utils by > - * Arcom Control System Ltd. > - */ > -int nand_erase_opts(struct mtd_info *mtd, > - const nand_erase_options_t *opts) > -{ > - struct jffs2_unknown_node cleanmarker; > - erase_info_t erase; > - unsigned long erase_length, erased_length; /* in blocks */ > - int result; > - int percent_complete = -1; > - const char *mtd_device = mtd->name; > - struct mtd_oob_ops oob_opts; > - struct nand_chip *chip = mtd_to_nand(mtd); > - > - if ((opts->offset & (mtd->erasesize - 1)) != 0) { > - printf("Attempt to erase non block-aligned data\n"); > - return -1; > - } > - > - memset(&erase, 0, sizeof(erase)); > - memset(&oob_opts, 0, sizeof(oob_opts)); > - > - erase.mtd = mtd; > - erase.len = mtd->erasesize; > - erase.addr = opts->offset; > - erase_length = lldiv(opts->length + mtd->erasesize - 1, > - mtd->erasesize); > - > - cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); > - cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); > - cleanmarker.totlen = cpu_to_je32(8); > - > - /* scrub option allows to erase badblock. To prevent internal > - * check from erase() method, set block check method to dummy > - * and disable bad block table while erasing. > - */ > - if (opts->scrub) { > - erase.scrub = opts->scrub; > - /* > - * We don't need the bad block table anymore... > - * after scrub, there are no bad blocks left! > - */ > - if (chip->bbt) { > - kfree(chip->bbt); > - } > - chip->bbt = NULL; > - chip->options &= ~NAND_BBT_SCANNED; > - } > - > - for (erased_length = 0; > - erased_length < erase_length; > - erase.addr += mtd->erasesize) { > - > - schedule(); > - > - if (opts->lim && (erase.addr >= (opts->offset + opts->lim))) { > - puts("Size of erase exceeds limit\n"); > - return -EFBIG; > - } > - if (!opts->scrub) { > - int ret = mtd_block_isbad(mtd, erase.addr); > - if (ret > 0) { > - if (!opts->quiet) > - printf("\rSkipping %s at " > - "0x%08llx " > - " \n", > - ret == 1 ? "bad block" : "bbt reserved", > - erase.addr); > - > - if (!opts->spread) > - erased_length++; > - > - continue; > - > - } else if (ret < 0) { > - printf("\n%s: MTD get bad block failed: %d\n", > - mtd_device, > - ret); > - return -1; > - } > - } > - > - erased_length++; > - > - result = mtd_erase(mtd, &erase); > - if (result != 0) { > - printf("\n%s: MTD Erase failure: %d\n", > - mtd_device, result); > - continue; > - } > - > - /* format for JFFS2 ? */ > - if (opts->jffs2 && chip->ecc.layout->oobavail >= 8) { > - struct mtd_oob_ops ops; > - ops.ooblen = 8; > - ops.datbuf = NULL; > - ops.oobbuf = (uint8_t *)&cleanmarker; > - ops.ooboffs = 0; > - ops.mode = MTD_OPS_AUTO_OOB; > - > - result = mtd_write_oob(mtd, erase.addr, &ops); > - if (result != 0) { > - printf("\n%s: MTD writeoob failure: %d\n", > - mtd_device, result); > - continue; > - } > - } > - > - if (!opts->quiet) { > - unsigned long long n = erased_length * 100ULL; > - int percent; > - > - do_div(n, erase_length); > - percent = (int)n; > - > - /* output progress message only at whole percent > - * steps to reduce the number of messages printed > - * on (slow) serial consoles > - */ > - if (percent != percent_complete) { > - percent_complete = percent; > - > - printf("\rErasing at 0x%llx -- %3d%% complete.", > - erase.addr, percent); > - > - if (opts->jffs2 && result == 0) > - printf(" Cleanmarker written at 0x%llx.", > - erase.addr); > - } > - } > - } > - if (!opts->quiet) > - printf("\n"); > - > - return 0; > -} > > #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK > > diff --git a/drivers/mtd/nand/util.c b/drivers/mtd/nand/util.c > index 4a372bb67d..f02c1ef4ca 100644 > --- a/drivers/mtd/nand/util.c > +++ b/drivers/mtd/nand/util.c > @@ -28,10 +28,176 @@ > #include <asm/cache.h> > #include <dm/devres.h> > > +#include <jffs2/jffs2.h> > #include <linux/errno.h> > #include <linux/mtd/mtd.h> > +#include <linux/mtd/nand.h> > +#include <linux/mtd/rawnand.h> > #include <nand.h> > > +typedef struct erase_info erase_info_t; > + > +/* support only for native endian JFFS2 */ > +#define cpu_to_je16(x) (x) > +#define cpu_to_je32(x) (x) > + > +/** > + * nand_erase_opts: - erase NAND flash with support for various options > + * (jffs2 formatting) > + * > + * @param mtd nand mtd instance to erase > + * @param opts options, @see struct nand_erase_options > + * Return: 0 in case of success > + * > + * This code is ported from flash_eraseall.c from Linux mtd utils by > + * Arcom Control System Ltd. > + */ > +int nand_erase_opts(struct mtd_info *mtd, > + const nand_erase_options_t *opts) > +{ > + struct jffs2_unknown_node cleanmarker; > + erase_info_t erase; > + unsigned long erase_length, erased_length; /* in blocks */ > + int result; > + int percent_complete = -1; > + const char *mtd_device = mtd->name; > + struct mtd_oob_ops oob_opts; > + u32 oobavail = mtd->oobavail; > +#if CONFIG_IS_ENABLED(MTD_RAW_NAND) > + struct nand_chip *chip = mtd_to_nand(mtd); > +#elif CONFIG_IS_ENABLED(MTD_SPI_NAND) > + struct nand_device *nand = mtd_to_nanddev(mtd); > +#endif > + > + if ((opts->offset & (mtd->erasesize - 1)) != 0) { > + printf("Attempt to erase non block-aligned data\n"); > + return -1; > + } > + > + memset(&erase, 0, sizeof(erase)); > + memset(&oob_opts, 0, sizeof(oob_opts)); > + > + erase.mtd = mtd; > + erase.len = mtd->erasesize; > + erase.addr = opts->offset; > + erase_length = lldiv(opts->length + mtd->erasesize - 1, > + mtd->erasesize); > + > + cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); > + cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); > + cleanmarker.totlen = cpu_to_je32(8); > + > + /* scrub option allows to erase badblock. To prevent internal > + * check from erase() method, set block check method to dummy > + * and disable bad block table while erasing. > + */ > + if (opts->scrub) { > + erase.scrub = opts->scrub; > + > + /* > + * We don't need the bad block table anymore... > + * after scrub, there are no bad blocks left! > + */ > +#if CONFIG_IS_ENABLED(MTD_RAW_NAND) > + if (chip->bbt) { > + kfree(chip->bbt); > + } > + chip->bbt = NULL; > + chip->options &= ~NAND_BBT_SCANNED; > +#elif CONFIG_IS_ENABLED(MTD_SPI_NAND) > + if (nanddev_bbt_is_initialized(nand)) > + nanddev_bbt_cleanup(nand); > +#endif > + } > + > + for (erased_length = 0; > + erased_length < erase_length; > + erase.addr += mtd->erasesize) { > + > + schedule(); > + > + if (opts->lim && (erase.addr >= (opts->offset + opts->lim))) { > + puts("Size of erase exceeds limit\n"); > + return -EFBIG; > + } > + if (!opts->scrub) { > + int ret = mtd_block_isbad(mtd, erase.addr); > + if (ret > 0) { > + if (!opts->quiet) > + printf("\rSkipping %s at " > + "0x%08llx " > + " \n", > + ret == 1 ? "bad block" : "bbt reserved", > + erase.addr); > + > + if (!opts->spread) > + erased_length++; > + > + continue; > + > + } else if (ret < 0) { > + printf("\n%s: MTD get bad block failed: %d\n", > + mtd_device, > + ret); > + return -1; > + } > + } > + > + erased_length++; > + > + result = mtd_erase(mtd, &erase); > + if (result != 0) { > + printf("\n%s: MTD Erase failure: %d\n", > + mtd_device, result); > + continue; > + } > + > + /* format for JFFS2 ? */ > + if (opts->jffs2 && oobavail >= 8) { > + struct mtd_oob_ops ops; > + ops.ooblen = 8; > + ops.datbuf = NULL; > + ops.oobbuf = (uint8_t *)&cleanmarker; > + ops.ooboffs = 0; > + ops.mode = MTD_OPS_AUTO_OOB; > + > + result = mtd_write_oob(mtd, erase.addr, &ops); > + if (result != 0) { > + printf("\n%s: MTD writeoob failure: %d\n", > + mtd_device, result); > + continue; > + } > + } > + > + if (!opts->quiet) { > + unsigned long long n = erased_length * 100ULL; > + int percent; > + > + do_div(n, erase_length); > + percent = (int)n; > + > + /* output progress message only at whole percent > + * steps to reduce the number of messages printed > + * on (slow) serial consoles > + */ > + if (percent != percent_complete) { > + percent_complete = percent; > + > + printf("\rErasing at 0x%llx -- %3d%% complete.", > + erase.addr, percent); > + > + if (opts->jffs2 && result == 0) > + printf(" Cleanmarker written at 0x%llx.", > + erase.addr); > + } > + } > + } > + if (!opts->quiet) > + printf("\n"); > + > + return 0; > +} > + > /** > * check_skip_len > * > -- > 2.30.1 > Reviewed-By: Michael Trimarchi <michael@amarulasolutions.com>
diff --git a/drivers/mtd/nand/raw/nand_util.c b/drivers/mtd/nand/raw/nand_util.c index 9c18ce63b9..f7704d4697 100644 --- a/drivers/mtd/nand/raw/nand_util.c +++ b/drivers/mtd/nand/raw/nand_util.c @@ -32,159 +32,6 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/rawnand.h> #include <nand.h> -#include <jffs2/jffs2.h> - -typedef struct erase_info erase_info_t; - -/* support only for native endian JFFS2 */ -#define cpu_to_je16(x) (x) -#define cpu_to_je32(x) (x) - -/** - * nand_erase_opts: - erase NAND flash with support for various options - * (jffs2 formatting) - * - * @param mtd nand mtd instance to erase - * @param opts options, @see struct nand_erase_options - * Return: 0 in case of success - * - * This code is ported from flash_eraseall.c from Linux mtd utils by - * Arcom Control System Ltd. - */ -int nand_erase_opts(struct mtd_info *mtd, - const nand_erase_options_t *opts) -{ - struct jffs2_unknown_node cleanmarker; - erase_info_t erase; - unsigned long erase_length, erased_length; /* in blocks */ - int result; - int percent_complete = -1; - const char *mtd_device = mtd->name; - struct mtd_oob_ops oob_opts; - struct nand_chip *chip = mtd_to_nand(mtd); - - if ((opts->offset & (mtd->erasesize - 1)) != 0) { - printf("Attempt to erase non block-aligned data\n"); - return -1; - } - - memset(&erase, 0, sizeof(erase)); - memset(&oob_opts, 0, sizeof(oob_opts)); - - erase.mtd = mtd; - erase.len = mtd->erasesize; - erase.addr = opts->offset; - erase_length = lldiv(opts->length + mtd->erasesize - 1, - mtd->erasesize); - - cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); - cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); - cleanmarker.totlen = cpu_to_je32(8); - - /* scrub option allows to erase badblock. To prevent internal - * check from erase() method, set block check method to dummy - * and disable bad block table while erasing. - */ - if (opts->scrub) { - erase.scrub = opts->scrub; - /* - * We don't need the bad block table anymore... - * after scrub, there are no bad blocks left! - */ - if (chip->bbt) { - kfree(chip->bbt); - } - chip->bbt = NULL; - chip->options &= ~NAND_BBT_SCANNED; - } - - for (erased_length = 0; - erased_length < erase_length; - erase.addr += mtd->erasesize) { - - schedule(); - - if (opts->lim && (erase.addr >= (opts->offset + opts->lim))) { - puts("Size of erase exceeds limit\n"); - return -EFBIG; - } - if (!opts->scrub) { - int ret = mtd_block_isbad(mtd, erase.addr); - if (ret > 0) { - if (!opts->quiet) - printf("\rSkipping %s at " - "0x%08llx " - " \n", - ret == 1 ? "bad block" : "bbt reserved", - erase.addr); - - if (!opts->spread) - erased_length++; - - continue; - - } else if (ret < 0) { - printf("\n%s: MTD get bad block failed: %d\n", - mtd_device, - ret); - return -1; - } - } - - erased_length++; - - result = mtd_erase(mtd, &erase); - if (result != 0) { - printf("\n%s: MTD Erase failure: %d\n", - mtd_device, result); - continue; - } - - /* format for JFFS2 ? */ - if (opts->jffs2 && chip->ecc.layout->oobavail >= 8) { - struct mtd_oob_ops ops; - ops.ooblen = 8; - ops.datbuf = NULL; - ops.oobbuf = (uint8_t *)&cleanmarker; - ops.ooboffs = 0; - ops.mode = MTD_OPS_AUTO_OOB; - - result = mtd_write_oob(mtd, erase.addr, &ops); - if (result != 0) { - printf("\n%s: MTD writeoob failure: %d\n", - mtd_device, result); - continue; - } - } - - if (!opts->quiet) { - unsigned long long n = erased_length * 100ULL; - int percent; - - do_div(n, erase_length); - percent = (int)n; - - /* output progress message only at whole percent - * steps to reduce the number of messages printed - * on (slow) serial consoles - */ - if (percent != percent_complete) { - percent_complete = percent; - - printf("\rErasing at 0x%llx -- %3d%% complete.", - erase.addr, percent); - - if (opts->jffs2 && result == 0) - printf(" Cleanmarker written at 0x%llx.", - erase.addr); - } - } - } - if (!opts->quiet) - printf("\n"); - - return 0; -} #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK diff --git a/drivers/mtd/nand/util.c b/drivers/mtd/nand/util.c index 4a372bb67d..f02c1ef4ca 100644 --- a/drivers/mtd/nand/util.c +++ b/drivers/mtd/nand/util.c @@ -28,10 +28,176 @@ #include <asm/cache.h> #include <dm/devres.h> +#include <jffs2/jffs2.h> #include <linux/errno.h> #include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/rawnand.h> #include <nand.h> +typedef struct erase_info erase_info_t; + +/* support only for native endian JFFS2 */ +#define cpu_to_je16(x) (x) +#define cpu_to_je32(x) (x) + +/** + * nand_erase_opts: - erase NAND flash with support for various options + * (jffs2 formatting) + * + * @param mtd nand mtd instance to erase + * @param opts options, @see struct nand_erase_options + * Return: 0 in case of success + * + * This code is ported from flash_eraseall.c from Linux mtd utils by + * Arcom Control System Ltd. + */ +int nand_erase_opts(struct mtd_info *mtd, + const nand_erase_options_t *opts) +{ + struct jffs2_unknown_node cleanmarker; + erase_info_t erase; + unsigned long erase_length, erased_length; /* in blocks */ + int result; + int percent_complete = -1; + const char *mtd_device = mtd->name; + struct mtd_oob_ops oob_opts; + u32 oobavail = mtd->oobavail; +#if CONFIG_IS_ENABLED(MTD_RAW_NAND) + struct nand_chip *chip = mtd_to_nand(mtd); +#elif CONFIG_IS_ENABLED(MTD_SPI_NAND) + struct nand_device *nand = mtd_to_nanddev(mtd); +#endif + + if ((opts->offset & (mtd->erasesize - 1)) != 0) { + printf("Attempt to erase non block-aligned data\n"); + return -1; + } + + memset(&erase, 0, sizeof(erase)); + memset(&oob_opts, 0, sizeof(oob_opts)); + + erase.mtd = mtd; + erase.len = mtd->erasesize; + erase.addr = opts->offset; + erase_length = lldiv(opts->length + mtd->erasesize - 1, + mtd->erasesize); + + cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); + cleanmarker.totlen = cpu_to_je32(8); + + /* scrub option allows to erase badblock. To prevent internal + * check from erase() method, set block check method to dummy + * and disable bad block table while erasing. + */ + if (opts->scrub) { + erase.scrub = opts->scrub; + + /* + * We don't need the bad block table anymore... + * after scrub, there are no bad blocks left! + */ +#if CONFIG_IS_ENABLED(MTD_RAW_NAND) + if (chip->bbt) { + kfree(chip->bbt); + } + chip->bbt = NULL; + chip->options &= ~NAND_BBT_SCANNED; +#elif CONFIG_IS_ENABLED(MTD_SPI_NAND) + if (nanddev_bbt_is_initialized(nand)) + nanddev_bbt_cleanup(nand); +#endif + } + + for (erased_length = 0; + erased_length < erase_length; + erase.addr += mtd->erasesize) { + + schedule(); + + if (opts->lim && (erase.addr >= (opts->offset + opts->lim))) { + puts("Size of erase exceeds limit\n"); + return -EFBIG; + } + if (!opts->scrub) { + int ret = mtd_block_isbad(mtd, erase.addr); + if (ret > 0) { + if (!opts->quiet) + printf("\rSkipping %s at " + "0x%08llx " + " \n", + ret == 1 ? "bad block" : "bbt reserved", + erase.addr); + + if (!opts->spread) + erased_length++; + + continue; + + } else if (ret < 0) { + printf("\n%s: MTD get bad block failed: %d\n", + mtd_device, + ret); + return -1; + } + } + + erased_length++; + + result = mtd_erase(mtd, &erase); + if (result != 0) { + printf("\n%s: MTD Erase failure: %d\n", + mtd_device, result); + continue; + } + + /* format for JFFS2 ? */ + if (opts->jffs2 && oobavail >= 8) { + struct mtd_oob_ops ops; + ops.ooblen = 8; + ops.datbuf = NULL; + ops.oobbuf = (uint8_t *)&cleanmarker; + ops.ooboffs = 0; + ops.mode = MTD_OPS_AUTO_OOB; + + result = mtd_write_oob(mtd, erase.addr, &ops); + if (result != 0) { + printf("\n%s: MTD writeoob failure: %d\n", + mtd_device, result); + continue; + } + } + + if (!opts->quiet) { + unsigned long long n = erased_length * 100ULL; + int percent; + + do_div(n, erase_length); + percent = (int)n; + + /* output progress message only at whole percent + * steps to reduce the number of messages printed + * on (slow) serial consoles + */ + if (percent != percent_complete) { + percent_complete = percent; + + printf("\rErasing at 0x%llx -- %3d%% complete.", + erase.addr, percent); + + if (opts->jffs2 && result == 0) + printf(" Cleanmarker written at 0x%llx.", + erase.addr); + } + } + } + if (!opts->quiet) + printf("\n"); + + return 0; +} + /** * check_skip_len *
Currently nand_erase_opts() placed in the nand/raw/ folder, because it uses the RAW NAND specific API (struct nand_chip). This patch move it to core NAND folder and make function generic, for both RAW/SPI NAND's usage. Also, nand_erase_opts() used in fastboot/fb_nand.c, cmd/nand.c and env/nand.c code. This is also the reason why we should move it to core folder and make it more general. Signed-off-by: Alexey Romanov <avromanov@salutedevices.com> --- drivers/mtd/nand/raw/nand_util.c | 153 ---------------------------- drivers/mtd/nand/util.c | 166 +++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 153 deletions(-)