
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