
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 *