[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