[PATCH v2 04/14] nand: move nand_erase_opts() to core NAND folder

Alexey Romanov avromanov at salutedevices.com
Tue Jan 9 18:32:16 CET 2024


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>
Reviewed-By: Michael Trimarchi <michael at amarulasolutions.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



More information about the U-Boot mailing list