]> www.infradead.org Git - mtd-utils.git/commitdiff
mtd-utils: flash_erase: Add flash erase chip
authorLarisa Ileana Grigore <larisa.grigore@nxp.com>
Fri, 23 Apr 2021 15:07:04 +0000 (18:07 +0300)
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>
Wed, 5 May 2021 06:29:50 +0000 (08:29 +0200)
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>
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
include/libmtd.h
lib/libmtd.c
misc-utils/flash_erase.c

index cc24af81bd17264fbb89c6168db5851d1864cbb7..6ab0de55ff12d83ded883b3159a44545584964a0 100644 (file)
@@ -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
index b581d80092cb1b4a25ad5f289db0828bb1f130f5..a363e56eaa2769ff50dd0726732874a7fe725966 100644 (file)
@@ -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
@@ -834,8 +835,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;
@@ -844,8 +845,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)
@@ -853,16 +860,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,
index a7fc6a6d0fa6561f793ac8abac12668db92c7880..49a880fc28bd390ac18fb4751c3491462e15a493 100644 (file)
@@ -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;