diff mbox series

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

Message ID 20231228153922.84323-5-avromanov@salutedevices.com
State Superseded
Delegated to: Dario Binacchi
Headers show
Series Support SPI NAND in fastboot protocol | expand

Commit Message

Alexey Romanov Dec. 28, 2023, 3:39 p.m. UTC
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(-)

Comments

Michael Nazzareno Trimarchi Jan. 3, 2024, 8:21 a.m. UTC | #1
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 mbox series

Patch

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
  *