[PATCH v1 04/12] nand: move nand_erase_opts() to core NAND folder

Michael Nazzareno Trimarchi michael at amarulasolutions.com
Wed Jan 3 09:21:08 CET 2024


Hi Alexey

On Thu, Dec 28, 2023 at 4:39 PM Alexey Romanov
<avromanov at 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 at 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 at amarulasolutions.com>


More information about the U-Boot mailing list