All of lore.kernel.org
 help / color / mirror / Atom feed
From: Larisa Ileana Grigore <larisa.grigore@nxp.com>
To: linux-mtd@lists.infradead.org
Subject: [PATCH 1/1] mtd-utils: flash_erase: Add flash erase chip
Date: Fri, 23 Apr 2021 18:07:04 +0300	[thread overview]
Message-ID: <20210423150704.7248-2-larisa.grigore@nxp.com> (raw)
In-Reply-To: <20210423150704.7248-1-larisa.grigore@nxp.com>

Some flash types support full erase chip command which can reduce the
flash erase time. Try first to erase the entire flash and fall back
to the old method if the operation fails.

Signed-off-by: Larisa Ileana Grigore <larisa.grigore@nxp.com>
---
 include/libmtd.h         | 15 +++++++
 lib/libmtd.c             | 26 ++++++++---
 misc-utils/flash_erase.c | 95 ++++++++++++++++++++++++++++++----------
 3 files changed, 106 insertions(+), 30 deletions(-)

diff --git a/include/libmtd.h b/include/libmtd.h
index cc24af8..6ab0de5 100644
--- a/include/libmtd.h
+++ b/include/libmtd.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008, 2009 Nokia Corporation
+ * Copyright 2021 NXP
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -174,6 +175,20 @@ int mtd_lock(const struct mtd_dev_info *mtd, int fd, int eb);
  */
 int mtd_unlock(const struct mtd_dev_info *mtd, int fd, int eb);
 
+/**
+ * mtd_unlock_multi - unlock eraseblocks.
+ * @desc: MTD library descriptor
+ * @mtd: MTD device description object
+ * @fd: MTD device node file descriptor
+ * @eb: index of first eraseblock to unlock
+ * @blocks: the number of eraseblocks to unlock
+ *
+ * This function unlocks @blocks starting at eraseblock @eb.
+ * Returns %0 in case of success and %-1 in case of failure.
+ */
+int mtd_unlock_multi(const struct mtd_dev_info *mtd, int fd, int eb,
+		     int blocks);
+
 /**
  * mtd_erase - erase multiple eraseblocks.
  * @desc: MTD library descriptor
diff --git a/lib/libmtd.c b/lib/libmtd.c
index 9d8d0e8..c1022cf 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) International Business Machines Corp., 2006
  * Copyright (C) 2009 Nokia Corporation
+ * Copyright 2021 NXP
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -831,8 +832,8 @@ static int mtd_valid_erase_block(const struct mtd_dev_info *mtd, int eb)
 	return 0;
 }
 
-static int mtd_xlock(const struct mtd_dev_info *mtd, int fd, int eb, int req,
-		     const char *sreq)
+static int mtd_xlock(const struct mtd_dev_info *mtd, int fd, int eb,
+		     int blocks, int req, const char *sreq)
 {
 	int ret;
 	struct erase_info_user ei;
@@ -841,8 +842,14 @@ static int mtd_xlock(const struct mtd_dev_info *mtd, int fd, int eb, int req,
 	if (ret)
 		return ret;
 
+	if (blocks > 1) {
+		ret = mtd_valid_erase_block(mtd, eb + blocks - 1);
+		if (ret)
+			return ret;
+	}
+
 	ei.start = eb * mtd->eb_size;
-	ei.length = mtd->eb_size;
+	ei.length = mtd->eb_size * blocks;
 
 	ret = ioctl(fd, req, &ei);
 	if (ret < 0)
@@ -850,16 +857,23 @@ static int mtd_xlock(const struct mtd_dev_info *mtd, int fd, int eb, int req,
 
 	return 0;
 }
-#define mtd_xlock(mtd, fd, eb, req) mtd_xlock(mtd, fd, eb, req, #req)
+#define mtd_xlock(mtd, fd, eb, blocks, req) \
+	mtd_xlock(mtd, fd, eb, blocks, req, #req)
 
 int mtd_lock(const struct mtd_dev_info *mtd, int fd, int eb)
 {
-	return mtd_xlock(mtd, fd, eb, MEMLOCK);
+	return mtd_xlock(mtd, fd, eb, 1, MEMLOCK);
 }
 
 int mtd_unlock(const struct mtd_dev_info *mtd, int fd, int eb)
 {
-	return mtd_xlock(mtd, fd, eb, MEMUNLOCK);
+	return mtd_xlock(mtd, fd, eb, 1, MEMUNLOCK);
+}
+
+int mtd_unlock_multi(const struct mtd_dev_info *mtd, int fd, int eb,
+		     int blocks)
+{
+	return mtd_xlock(mtd, fd, eb, blocks, MEMUNLOCK);
 }
 
 int mtd_erase_multi(libmtd_t desc, const struct mtd_dev_info *mtd,
diff --git a/misc-utils/flash_erase.c b/misc-utils/flash_erase.c
index a7fc6a6..49a880f 100644
--- a/misc-utils/flash_erase.c
+++ b/misc-utils/flash_erase.c
@@ -2,6 +2,7 @@
 
    Copyright (C) 2000 Arcom Control System Ltd
    Copyright (C) 2010 Mike Frysinger <vapier@gentoo.org>
+   Copyright 2021 NXP
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -50,11 +51,10 @@ static int unlock;		/* unlock sectors before erasing */
 static struct jffs2_unknown_node cleanmarker;
 int target_endian = __BYTE_ORDER;
 
-static void show_progress(struct mtd_dev_info *mtd, off_t start, int eb,
-			  int eb_start, int eb_cnt)
+static void show_progress(off_t start, int eb, int eb_start, int eb_cnt, int step)
 {
 	bareverbose(!quiet, "\rErasing %d Kibyte @ %llx -- %2i %% complete ",
-		mtd->eb_size / 1024, (unsigned long long)start, ((eb - eb_start) * 100) / eb_cnt);
+		step / 1024, (unsigned long long)start, ((eb - eb_start) * 100) / eb_cnt);
 	fflush(stdout);
 }
 
@@ -88,6 +88,27 @@ static void display_version (void)
 			PROGRAM_NAME);
 }
 
+static void clear_marker(libmtd_t mtd_desc, struct mtd_dev_info *mtd, int fd,
+			 unsigned int eb, int cmlen, bool isNAND)
+{
+	off_t offset = (off_t)eb * mtd->eb_size;
+
+	/* write cleanmarker */
+	if (isNAND) {
+		if (mtd_write(mtd_desc, mtd, fd, eb, 0, NULL, 0, &cleanmarker, cmlen,
+				MTD_OPS_AUTO_OOB) != 0) {
+			sys_errmsg("%s: MTD writeoob failure", mtd_device);
+			return;
+		}
+	} else {
+		if (pwrite(fd, &cleanmarker, sizeof(cleanmarker), (loff_t)offset) != sizeof(cleanmarker)) {
+			sys_errmsg("%s: MTD write failure", mtd_device);
+			return;
+		}
+	}
+	verbose(!quiet, "%llx : Cleanmarker Updated.", (unsigned long long)offset);
+}
+
 int main(int argc, char *argv[])
 {
 	libmtd_t mtd_desc;
@@ -95,7 +116,7 @@ int main(int argc, char *argv[])
 	int fd, cmlen = 8;
 	unsigned long long start;
 	unsigned int eb, eb_start, eb_cnt;
-	bool isNAND;
+	bool isNAND, erase_chip = false;
 	int error = 0;
 	off_t offset = 0;
 
@@ -205,6 +226,47 @@ int main(int argc, char *argv[])
 	if (eb_cnt == 0)
 		eb_cnt = (mtd.size / mtd.eb_size) - eb_start;
 
+	if (eb_start == 0 && mtd.size == eb_cnt * mtd.eb_size)
+		erase_chip = true;
+
+	/* If MTD device may have bad eraseblocks,
+	 * erase one by one each sector
+	 */
+	if (noskipbad && mtd.bb_allowed)
+		erase_chip = false;
+
+	if (erase_chip) {
+		show_progress(0, eb_start, eb_start, eb_cnt, mtd.size);
+
+		if (unlock) {
+			if (mtd_unlock_multi(&mtd, fd, eb_start, eb_cnt) != 0) {
+				sys_errmsg("%s: MTD unlock entire chip failure." \
+					   "Trying one by one each sector.",
+					    mtd_device);
+				goto erase_each_sector;
+			}
+		}
+
+		if (mtd_erase_multi(mtd_desc, &mtd, fd, eb_start, eb_cnt) != 0) {
+			sys_errmsg("%s: MTD Erase entire chip failure" \
+				    "Trying one by one each sector.",
+				    mtd_device);
+			goto erase_each_sector;
+		}
+
+		show_progress(0, eb_start + eb_cnt, eb_start,
+			      eb_cnt, mtd.size);
+
+		if (!jffs2)
+			goto out;
+
+		/* write cleanmarker */
+		for (eb = eb_start; eb < eb_start + eb_cnt; eb++)
+			clear_marker(mtd_desc, &mtd, fd, eb, cmlen, isNAND);
+		goto out;
+	}
+
+erase_each_sector:
 	for (eb = eb_start; eb < eb_start + eb_cnt; eb++) {
 		offset = (off_t)eb * mtd.eb_size;
 
@@ -223,7 +285,7 @@ int main(int argc, char *argv[])
 			}
 		}
 
-		show_progress(&mtd, offset, eb, eb_start, eb_cnt);
+		show_progress(offset, eb, eb_start, eb_cnt, mtd.eb_size);
 
 		if (unlock) {
 			if (mtd_unlock(&mtd, fd, eb) != 0) {
@@ -237,26 +299,11 @@ int main(int argc, char *argv[])
 			continue;
 		}
 
-		/* format for JFFS2 ? */
-		if (!jffs2)
-			continue;
-
-		/* write cleanmarker */
-		if (isNAND) {
-			if (mtd_write(mtd_desc, &mtd, fd, eb, 0, NULL, 0, &cleanmarker, cmlen,
-					MTD_OPS_AUTO_OOB) != 0) {
-				sys_errmsg("%s: MTD writeoob failure", mtd_device);
-				continue;
-			}
-		} else {
-			if (pwrite(fd, &cleanmarker, sizeof(cleanmarker), (loff_t)offset) != sizeof(cleanmarker)) {
-				sys_errmsg("%s: MTD write failure", mtd_device);
-				continue;
-			}
-		}
-		verbose(!quiet, " Cleanmarker Updated.");
+		if (jffs2)
+			clear_marker(mtd_desc, &mtd, fd, eb, cmlen, isNAND);
 	}
-	show_progress(&mtd, offset, eb, eb_start, eb_cnt);
+	show_progress(offset, eb, eb_start, eb_cnt, mtd.eb_size);
+out:
 	bareverbose(!quiet, "\n");
 
 	return 0;
-- 
2.17.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

  reply	other threads:[~2021-04-23 15:08 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-23 15:07 [PATCH] Add full flash erase support in mtd-utils Larisa Ileana Grigore
2021-04-23 15:07 ` Larisa Ileana Grigore [this message]
2021-04-23 16:54   ` [PATCH 1/1] mtd-utils: flash_erase: Add flash erase chip Michael Walle
2021-05-05  6:50   ` David Oberhollenzer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210423150704.7248-2-larisa.grigore@nxp.com \
    --to=larisa.grigore@nxp.com \
    --cc=linux-mtd@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.