All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 00/12] Support SPI NAND in fastboot protocol
@ 2023-12-28 15:39 Alexey Romanov
  2023-12-28 15:39 ` [PATCH v1 01/12] nand: move NAND initialization API to nand/core.c Alexey Romanov
                   ` (11 more replies)
  0 siblings, 12 replies; 23+ messages in thread
From: Alexey Romanov @ 2023-12-28 15:39 UTC (permalink / raw)
  To: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, michael, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

Currently, fastboot in U-Boot doens't support SPI NAND
devices. This patchset adds support for SPI NAND in fastboot
nand subsystem.

Alexey Romanov (12):
  nand: move NAND initialization API to nand/core.c
  nand: don't overwrite mtd name in nand_register()
  nand: move nand_util.c to NAND core folder
  nand: move nand_erase_opts() to core NAND folder
  spi: add board_nand_init() function
  spi: use nand_register() instead of add_mtd_device()
  mtdparts: use negative error codes
  jffs2: use negative error codes
  cmd: allow to enable CMD_NAND for SPI NAND devices
  fastboot: check device type for SPI NAND too
  fastboot: enable FASTBOOT_FLASH option for SPI NAND devices
  fastboot: fb_nand: add missing newlines in pr_err() macro

 cmd/Kconfig                      |   2 +-
 cmd/jffs2.c                      |  45 +-
 cmd/mtdparts.c                   | 154 +++----
 drivers/fastboot/Kconfig         |   4 +-
 drivers/fastboot/fb_nand.c       |  12 +-
 drivers/mtd/Kconfig              |   2 +-
 drivers/mtd/nand/Kconfig         |  10 +
 drivers/mtd/nand/Makefile        |   2 +-
 drivers/mtd/nand/core.c          | 140 ++++++
 drivers/mtd/nand/raw/Kconfig     |  10 -
 drivers/mtd/nand/raw/nand.c      | 134 ------
 drivers/mtd/nand/raw/nand_util.c | 664 -----------------------------
 drivers/mtd/nand/spi/Kconfig     |   1 +
 drivers/mtd/nand/spi/core.c      |  17 +-
 drivers/mtd/nand/util.c          | 709 +++++++++++++++++++++++++++++++
 include/nand.h                   |   2 +
 16 files changed, 989 insertions(+), 919 deletions(-)
 create mode 100644 drivers/mtd/nand/util.c

-- 
2.30.1


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v1 01/12] nand: move NAND initialization API to nand/core.c
  2023-12-28 15:39 [PATCH v1 00/12] Support SPI NAND in fastboot protocol Alexey Romanov
@ 2023-12-28 15:39 ` Alexey Romanov
  2023-12-28 16:51   ` Sean Anderson
  2023-12-28 15:39 ` [PATCH v1 02/12] nand: don't overwrite mtd name in nand_register() Alexey Romanov
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Alexey Romanov @ 2023-12-28 15:39 UTC (permalink / raw)
  To: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, michael, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

nand_register() and nand_init() is generic API for both
RAW and SPI NAND's. We have to move this functions
from drivers/mtd/nand/raw/nand.c to drivers/mtd/nand/core.c.

Functions designed to work with RAW NAND should remain
in drivers/mtd/nand/raw/nand.c.

Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
---
 drivers/mtd/Kconfig          |   2 +-
 drivers/mtd/nand/Kconfig     |  10 +++
 drivers/mtd/nand/core.c      | 136 +++++++++++++++++++++++++++++++++++
 drivers/mtd/nand/raw/Kconfig |  10 ---
 drivers/mtd/nand/raw/nand.c  | 134 ----------------------------------
 include/nand.h               |   2 +
 6 files changed, 149 insertions(+), 145 deletions(-)

diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index c56840c849..1902351719 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -260,7 +260,7 @@ config SYS_NAND_MAX_ECCPOS
 
 config SYS_NAND_MAX_CHIPS
 	int "NAND max chips"
-	depends on MTD_RAW_NAND || CMD_ONENAND || TARGET_S5PC210_UNIVERSAL || \
+	depends on MTD_RAW_NAND || MTD_SPI_NAND || CMD_ONENAND || TARGET_S5PC210_UNIVERSAL || \
 		SPL_OMAP3_ID_NAND
 	default 1
 	help
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 78ae04bdcb..9a1d4ac0dc 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -1,6 +1,16 @@
 config MTD_NAND_CORE
 	tristate
 
+config SYS_MAX_NAND_DEVICE
+	int "Maximum number of NAND devices to support"
+	default 1
+
+config SYS_NAND_SELF_INIT
+	bool
+	help
+	  This option, if enabled, provides more flexible and linux-like
+	  NAND initialization process.
+
 source "drivers/mtd/nand/raw/Kconfig"
 
 source "drivers/mtd/nand/spi/Kconfig"
diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c
index 4b9dd6a926..ff298e3a0f 100644
--- a/drivers/mtd/nand/core.c
+++ b/drivers/mtd/nand/core.c
@@ -10,6 +10,7 @@
 #define pr_fmt(fmt)	"nand: " fmt
 
 #include <common.h>
+#include <nand.h>
 #include <watchdog.h>
 #ifndef __UBOOT__
 #include <linux/compat.h>
@@ -18,6 +19,12 @@
 #include <linux/bitops.h>
 #include <linux/mtd/nand.h>
 
+int nand_curr_device = -1;
+
+static struct mtd_info *nand_info[CONFIG_SYS_MAX_NAND_DEVICE];
+static char dev_name[CONFIG_SYS_MAX_NAND_DEVICE][8];
+static unsigned long total_nand_size; /* in kiB */
+
 /**
  * nanddev_isbad() - Check if a block is bad
  * @nand: NAND device
@@ -250,6 +257,135 @@ void nanddev_cleanup(struct nand_device *nand)
 }
 EXPORT_SYMBOL_GPL(nanddev_cleanup);
 
+struct mtd_info *get_nand_dev_by_index(int dev)
+{
+	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev] ||
+	    !nand_info[dev]->name)
+		return NULL;
+
+	return nand_info[dev];
+}
+EXPORT_SYMBOL_GPL(get_nand_dev_by_index);
+
+int nand_mtd_to_devnum(struct mtd_info *mtd)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
+		if (mtd && get_nand_dev_by_index(i) == mtd)
+			return i;
+	}
+
+	return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(nand_mtd_to_devnum);
+
+/* Register an initialized NAND mtd device with the U-Boot NAND command. */
+int nand_register(int devnum, struct mtd_info *mtd)
+{
+	if (devnum >= CONFIG_SYS_MAX_NAND_DEVICE)
+		return -EINVAL;
+
+	nand_info[devnum] = mtd;
+
+	sprintf(dev_name[devnum], "nand%d", devnum);
+	mtd->name = dev_name[devnum];
+
+#ifdef CONFIG_MTD
+	/*
+	 * Add MTD device so that we can reference it later
+	 * via the mtdcore infrastructure (e.g. ubi).
+	 */
+	add_mtd_device(mtd);
+#endif
+
+	total_nand_size += mtd->size / 1024;
+
+	if (nand_curr_device == -1)
+		nand_curr_device = devnum;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nand_register);
+
+#ifdef CONFIG_MTD_CONCAT
+static void create_mtd_concat(void)
+{
+	struct mtd_info *nand_info_list[CONFIG_SYS_MAX_NAND_DEVICE];
+	int nand_devices_found = 0;
+	int i;
+
+	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
+		struct mtd_info *mtd = get_nand_dev_by_index(i);
+		if (mtd != NULL) {
+			nand_info_list[nand_devices_found] = mtd;
+			nand_devices_found++;
+		}
+	}
+	if (nand_devices_found > 1) {
+		struct mtd_info *mtd;
+		char c_mtd_name[16];
+
+		/*
+		 * We detected multiple devices. Concatenate them together.
+		 */
+		sprintf(c_mtd_name, "nand%d", nand_devices_found);
+		mtd = mtd_concat_create(nand_info_list, nand_devices_found,
+					c_mtd_name);
+
+		if (mtd == NULL)
+			return;
+
+		nand_register(nand_devices_found, mtd);
+	}
+
+	return;
+}
+#else
+static void create_mtd_concat(void)
+{
+}
+#endif
+
+unsigned long nand_size(void)
+{
+	return total_nand_size;
+}
+EXPORT_SYMBOL_GPL(nand_size);
+
+void nand_init(void)
+{
+	static int initialized;
+
+	/*
+	 * Avoid initializing NAND Flash multiple times,
+	 * otherwise it will calculate a wrong total size.
+	 */
+	if (initialized)
+		return;
+	initialized = 1;
+
+#if CONFIG_IS_ENABLED(SYS_NAND_SELF_INIT)
+	board_nand_init();
+#else
+	int i;
+
+	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
+		nand_init_chip(i);
+#endif
+
+#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
+	/*
+	 * Select the chip in the board/cpu specific driver
+	 */
+	board_nand_select_device(mtd_to_nand(get_nand_dev_by_index(nand_curr_device)),
+				 nand_curr_device);
+#endif
+
+	create_mtd_concat();
+}
+EXPORT_SYMBOL_GPL(nand_init);
+
 MODULE_DESCRIPTION("Generic NAND framework");
 MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index f0100a601d..31949f1dff 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -3,12 +3,6 @@ menuconfig MTD_RAW_NAND
 	bool "Raw NAND Device Support"
 if MTD_RAW_NAND
 
-config SYS_NAND_SELF_INIT
-	bool
-	help
-	  This option, if enabled, provides more flexible and linux-like
-	  NAND initialization process.
-
 config SPL_SYS_NAND_SELF_INIT
 	bool
 	depends on !SPL_NAND_SIMPLE
@@ -29,10 +23,6 @@ config TPL_NAND_INIT
 config SPL_NAND_INIT
 	bool
 
-config SYS_MAX_NAND_DEVICE
-	int "Maximum number of NAND devices to support"
-	default 1
-
 config SYS_NAND_DRIVER_ECC_LAYOUT
 	bool "Omit standard ECC layouts to save space"
 	help
diff --git a/drivers/mtd/nand/raw/nand.c b/drivers/mtd/nand/raw/nand.c
index eacd99c4e2..edca824d77 100644
--- a/drivers/mtd/nand/raw/nand.c
+++ b/drivers/mtd/nand/raw/nand.c
@@ -15,68 +15,10 @@
 #define CFG_SYS_NAND_BASE_LIST { CFG_SYS_NAND_BASE }
 #endif
 
-int nand_curr_device = -1;
-
-static struct mtd_info *nand_info[CONFIG_SYS_MAX_NAND_DEVICE];
-
 #if !CONFIG_IS_ENABLED(SYS_NAND_SELF_INIT)
 static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];
 static ulong base_address[CONFIG_SYS_MAX_NAND_DEVICE] = CFG_SYS_NAND_BASE_LIST;
-#endif
-
-static char dev_name[CONFIG_SYS_MAX_NAND_DEVICE][8];
-
-static unsigned long total_nand_size; /* in kiB */
-
-struct mtd_info *get_nand_dev_by_index(int dev)
-{
-	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev] ||
-	    !nand_info[dev]->name)
-		return NULL;
 
-	return nand_info[dev];
-}
-
-int nand_mtd_to_devnum(struct mtd_info *mtd)
-{
-	int i;
-
-	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
-		if (mtd && get_nand_dev_by_index(i) == mtd)
-			return i;
-	}
-
-	return -ENODEV;
-}
-
-/* Register an initialized NAND mtd device with the U-Boot NAND command. */
-int nand_register(int devnum, struct mtd_info *mtd)
-{
-	if (devnum >= CONFIG_SYS_MAX_NAND_DEVICE)
-		return -EINVAL;
-
-	nand_info[devnum] = mtd;
-
-	sprintf(dev_name[devnum], "nand%d", devnum);
-	mtd->name = dev_name[devnum];
-
-#ifdef CONFIG_MTD
-	/*
-	 * Add MTD device so that we can reference it later
-	 * via the mtdcore infrastructure (e.g. ubi).
-	 */
-	add_mtd_device(mtd);
-#endif
-
-	total_nand_size += mtd->size / 1024;
-
-	if (nand_curr_device == -1)
-		nand_curr_device = devnum;
-
-	return 0;
-}
-
-#if !CONFIG_IS_ENABLED(SYS_NAND_SELF_INIT)
 static void nand_init_chip(int i)
 {
 	struct nand_chip *nand = &nand_chip[i];
@@ -98,79 +40,3 @@ static void nand_init_chip(int i)
 	nand_register(i, mtd);
 }
 #endif
-
-#ifdef CONFIG_MTD_CONCAT
-static void create_mtd_concat(void)
-{
-	struct mtd_info *nand_info_list[CONFIG_SYS_MAX_NAND_DEVICE];
-	int nand_devices_found = 0;
-	int i;
-
-	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
-		struct mtd_info *mtd = get_nand_dev_by_index(i);
-		if (mtd != NULL) {
-			nand_info_list[nand_devices_found] = mtd;
-			nand_devices_found++;
-		}
-	}
-	if (nand_devices_found > 1) {
-		struct mtd_info *mtd;
-		char c_mtd_name[16];
-
-		/*
-		 * We detected multiple devices. Concatenate them together.
-		 */
-		sprintf(c_mtd_name, "nand%d", nand_devices_found);
-		mtd = mtd_concat_create(nand_info_list, nand_devices_found,
-					c_mtd_name);
-
-		if (mtd == NULL)
-			return;
-
-		nand_register(nand_devices_found, mtd);
-	}
-
-	return;
-}
-#else
-static void create_mtd_concat(void)
-{
-}
-#endif
-
-unsigned long nand_size(void)
-{
-	return total_nand_size;
-}
-
-void nand_init(void)
-{
-	static int initialized;
-
-	/*
-	 * Avoid initializing NAND Flash multiple times,
-	 * otherwise it will calculate a wrong total size.
-	 */
-	if (initialized)
-		return;
-	initialized = 1;
-
-#if CONFIG_IS_ENABLED(SYS_NAND_SELF_INIT)
-	board_nand_init();
-#else
-	int i;
-
-	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-		nand_init_chip(i);
-#endif
-
-#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
-	/*
-	 * Select the chip in the board/cpu specific driver
-	 */
-	board_nand_select_device(mtd_to_nand(get_nand_dev_by_index(nand_curr_device)),
-				 nand_curr_device);
-#endif
-
-	create_mtd_concat();
-}
diff --git a/include/nand.h b/include/nand.h
index 70c1286ccb..16cfc2a24a 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -25,6 +25,8 @@ int nand_register(int devnum, struct mtd_info *mtd);
 struct nand_chip;
 
 extern int board_nand_init(struct nand_chip *nand);
+
+void nand_init_chip(int index);
 #endif
 
 extern int nand_curr_device;
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v1 02/12] nand: don't overwrite mtd name in nand_register()
  2023-12-28 15:39 [PATCH v1 00/12] Support SPI NAND in fastboot protocol Alexey Romanov
  2023-12-28 15:39 ` [PATCH v1 01/12] nand: move NAND initialization API to nand/core.c Alexey Romanov
@ 2023-12-28 15:39 ` Alexey Romanov
  2023-12-28 15:39 ` [PATCH v1 03/12] nand: move nand_util.c to NAND core folder Alexey Romanov
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Alexey Romanov @ 2023-12-28 15:39 UTC (permalink / raw)
  To: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, michael, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

We use this function in SPI NAND subsystem, which already
filled mtd->name field with "spi-nand0" string.

Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
---
 drivers/mtd/nand/core.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c
index ff298e3a0f..5a63e74ccb 100644
--- a/drivers/mtd/nand/core.c
+++ b/drivers/mtd/nand/core.c
@@ -22,7 +22,7 @@
 int nand_curr_device = -1;
 
 static struct mtd_info *nand_info[CONFIG_SYS_MAX_NAND_DEVICE];
-static char dev_name[CONFIG_SYS_MAX_NAND_DEVICE][8];
+static char dev_name[CONFIG_SYS_MAX_NAND_DEVICE][16];
 static unsigned long total_nand_size; /* in kiB */
 
 /**
@@ -288,8 +288,12 @@ int nand_register(int devnum, struct mtd_info *mtd)
 
 	nand_info[devnum] = mtd;
 
-	sprintf(dev_name[devnum], "nand%d", devnum);
-	mtd->name = dev_name[devnum];
+	if (!strlen(mtd->name)) {
+		snprintf(dev_name[devnum], ARRAY_SIZE(dev_name[devnum]), "nand%d", devnum);
+		mtd->name = dev_name[devnum];
+	} else {
+		strlcpy(dev_name[devnum], mtd->name, ARRAY_SIZE(dev_name[devnum]));
+	}
 
 #ifdef CONFIG_MTD
 	/*
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v1 03/12] nand: move nand_util.c to NAND core folder
  2023-12-28 15:39 [PATCH v1 00/12] Support SPI NAND in fastboot protocol Alexey Romanov
  2023-12-28 15:39 ` [PATCH v1 01/12] nand: move NAND initialization API to nand/core.c Alexey Romanov
  2023-12-28 15:39 ` [PATCH v1 02/12] nand: don't overwrite mtd name in nand_register() Alexey Romanov
@ 2023-12-28 15:39 ` Alexey Romanov
  2023-12-28 15:39 ` [PATCH v1 04/12] nand: move nand_erase_opts() to core NAND folder Alexey Romanov
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Alexey Romanov @ 2023-12-28 15:39 UTC (permalink / raw)
  To: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, michael, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

This is right place for this API. Now, fastboot code uses this
API: these functions should be available regardless of the
selected NAND type (RAW / SPI).

Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
---
 drivers/mtd/nand/Makefile        |   2 +-
 drivers/mtd/nand/raw/nand_util.c | 511 -----------------------------
 drivers/mtd/nand/util.c          | 543 +++++++++++++++++++++++++++++++
 3 files changed, 544 insertions(+), 512 deletions(-)
 create mode 100644 drivers/mtd/nand/util.c

diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 96e186600a..301b1bceff 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 
 ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),)
-nandcore-objs := core.o bbt.o
+nandcore-objs := core.o bbt.o util.o
 obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
 obj-$(CONFIG_MTD_RAW_NAND) += raw/
 obj-$(CONFIG_MTD_SPI_NAND) += spi/
diff --git a/drivers/mtd/nand/raw/nand_util.c b/drivers/mtd/nand/raw/nand_util.c
index 72cc24f403..9c18ce63b9 100644
--- a/drivers/mtd/nand/raw/nand_util.c
+++ b/drivers/mtd/nand/raw/nand_util.c
@@ -35,7 +35,6 @@
 #include <jffs2/jffs2.h>
 
 typedef struct erase_info	erase_info_t;
-typedef struct mtd_info		mtd_info_t;
 
 /* support only for native endian JFFS2 */
 #define cpu_to_je16(x) (x)
@@ -395,513 +394,3 @@ int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length,
 	return ret;
 }
 #endif
-
-/**
- * check_skip_len
- *
- * Check if there are any bad blocks, and whether length including bad
- * blocks fits into device
- *
- * @param mtd nand mtd instance
- * @param offset offset in flash
- * @param length image length
- * @param used length of flash needed for the requested length
- * Return: 0 if the image fits and there are no bad blocks
- *         1 if the image fits, but there are bad blocks
- *        -1 if the image does not fit
- */
-static int check_skip_len(struct mtd_info *mtd, loff_t offset, size_t length,
-			  size_t *used)
-{
-	size_t len_excl_bad = 0;
-	int ret = 0;
-
-	while (len_excl_bad < length) {
-		size_t block_len, block_off;
-		loff_t block_start;
-
-		if (offset >= mtd->size)
-			return -1;
-
-		block_start = offset & ~(loff_t)(mtd->erasesize - 1);
-		block_off = offset & (mtd->erasesize - 1);
-		block_len = mtd->erasesize - block_off;
-
-		if (!nand_block_isbad(mtd, block_start))
-			len_excl_bad += block_len;
-		else
-			ret = 1;
-
-		offset += block_len;
-		*used += block_len;
-	}
-
-	/* If the length is not a multiple of block_len, adjust. */
-	if (len_excl_bad > length)
-		*used -= (len_excl_bad - length);
-
-	return ret;
-}
-
-#ifdef CONFIG_CMD_NAND_TRIMFFS
-static size_t drop_ffs(const struct mtd_info *mtd, const u_char *buf,
-			const size_t *len)
-{
-	size_t l = *len;
-	ssize_t i;
-
-	for (i = l - 1; i >= 0; i--)
-		if (buf[i] != 0xFF)
-			break;
-
-	/* The resulting length must be aligned to the minimum flash I/O size */
-	l = i + 1;
-	l = (l + mtd->writesize - 1) / mtd->writesize;
-	l *=  mtd->writesize;
-
-	/*
-	 * since the input length may be unaligned, prevent access past the end
-	 * of the buffer
-	 */
-	return min(l, *len);
-}
-#endif
-
-/**
- * nand_verify_page_oob:
- *
- * Verify a page of NAND flash, including the OOB.
- * Reads page of NAND and verifies the contents and OOB against the
- * values in ops.
- *
- * @param mtd		nand mtd instance
- * @param ops		MTD operations, including data to verify
- * @param ofs		offset in flash
- * Return:		0 in case of success
- */
-int nand_verify_page_oob(struct mtd_info *mtd, struct mtd_oob_ops *ops,
-			 loff_t ofs)
-{
-	int rval;
-	struct mtd_oob_ops vops;
-	size_t verlen = mtd->writesize + mtd->oobsize;
-
-	memcpy(&vops, ops, sizeof(vops));
-
-	vops.datbuf = memalign(ARCH_DMA_MINALIGN, verlen);
-
-	if (!vops.datbuf)
-		return -ENOMEM;
-
-	vops.oobbuf = vops.datbuf + mtd->writesize;
-
-	rval = mtd_read_oob(mtd, ofs, &vops);
-	if (!rval)
-		rval = memcmp(ops->datbuf, vops.datbuf, vops.len);
-	if (!rval)
-		rval = memcmp(ops->oobbuf, vops.oobbuf, vops.ooblen);
-
-	free(vops.datbuf);
-
-	return rval ? -EIO : 0;
-}
-
-/**
- * nand_verify:
- *
- * Verify a region of NAND flash.
- * Reads NAND in page-sized chunks and verifies the contents against
- * the contents of a buffer.  The offset into the NAND must be
- * page-aligned, and the function doesn't handle skipping bad blocks.
- *
- * @param mtd		nand mtd instance
- * @param ofs		offset in flash
- * @param len		buffer length
- * @param buf		buffer to read from
- * Return:		0 in case of success
- */
-int nand_verify(struct mtd_info *mtd, loff_t ofs, size_t len, u_char *buf)
-{
-	int rval = 0;
-	size_t verofs;
-	size_t verlen = mtd->writesize;
-	uint8_t *verbuf = memalign(ARCH_DMA_MINALIGN, verlen);
-
-	if (!verbuf)
-		return -ENOMEM;
-
-	/* Read the NAND back in page-size groups to limit malloc size */
-	for (verofs = ofs; verofs < ofs + len;
-	     verofs += verlen, buf += verlen) {
-		verlen = min(mtd->writesize, (uint32_t)(ofs + len - verofs));
-		rval = nand_read(mtd, verofs, &verlen, verbuf);
-		if (!rval || (rval == -EUCLEAN))
-			rval = memcmp(buf, verbuf, verlen);
-
-		if (rval)
-			break;
-	}
-
-	free(verbuf);
-
-	return rval ? -EIO : 0;
-}
-
-/**
- * nand_write_skip_bad:
- *
- * Write image to NAND flash.
- * Blocks that are marked bad are skipped and the is written to the next
- * block instead as long as the image is short enough to fit even after
- * skipping the bad blocks.  Due to bad blocks we may not be able to
- * perform the requested write.  In the case where the write would
- * extend beyond the end of the NAND device, both length and actual (if
- * not NULL) are set to 0.  In the case where the write would extend
- * beyond the limit we are passed, length is set to 0 and actual is set
- * to the required length.
- *
- * @param mtd		nand mtd instance
- * @param offset	offset in flash
- * @param length	buffer length
- * @param actual	set to size required to write length worth of
- *			buffer or 0 on error, if not NULL
- * @param lim		maximum size that actual may be in order to not
- *			exceed the buffer
- * @param buffer        buffer to read from
- * @param flags		flags modifying the behaviour of the write to NAND
- * Return:		0 in case of success
- */
-int nand_write_skip_bad(struct mtd_info *mtd, loff_t offset, size_t *length,
-			size_t *actual, loff_t lim, u_char *buffer, int flags)
-{
-	int rval = 0, blocksize;
-	size_t left_to_write = *length;
-	size_t used_for_write = 0;
-	u_char *p_buffer = buffer;
-	int need_skip;
-
-	if (actual)
-		*actual = 0;
-
-	blocksize = mtd->erasesize;
-
-	/*
-	 * nand_write() handles unaligned, partial page writes.
-	 *
-	 * We allow length to be unaligned, for convenience in
-	 * using the $filesize variable.
-	 *
-	 * However, starting at an unaligned offset makes the
-	 * semantics of bad block skipping ambiguous (really,
-	 * you should only start a block skipping access at a
-	 * partition boundary).  So don't try to handle that.
-	 */
-	if ((offset & (mtd->writesize - 1)) != 0) {
-		printf("Attempt to write non page-aligned data\n");
-		*length = 0;
-		return -EINVAL;
-	}
-
-	need_skip = check_skip_len(mtd, offset, *length, &used_for_write);
-
-	if (actual)
-		*actual = used_for_write;
-
-	if (need_skip < 0) {
-		printf("Attempt to write outside the flash area\n");
-		*length = 0;
-		return -EINVAL;
-	}
-
-	if (used_for_write > lim) {
-		puts("Size of write exceeds partition or device limit\n");
-		*length = 0;
-		return -EFBIG;
-	}
-
-	if (!need_skip && !(flags & WITH_DROP_FFS)) {
-		rval = nand_write(mtd, offset, length, buffer);
-
-		if ((flags & WITH_WR_VERIFY) && !rval)
-			rval = nand_verify(mtd, offset, *length, buffer);
-
-		if (rval == 0)
-			return 0;
-
-		*length = 0;
-		printf("NAND write to offset %llx failed %d\n",
-			offset, rval);
-		return rval;
-	}
-
-	while (left_to_write > 0) {
-		loff_t block_start = offset & ~(loff_t)(mtd->erasesize - 1);
-		size_t block_offset = offset & (mtd->erasesize - 1);
-		size_t write_size, truncated_write_size;
-
-		schedule();
-
-		if (nand_block_isbad(mtd, block_start)) {
-			printf("Skip bad block 0x%08llx\n", block_start);
-			offset += mtd->erasesize - block_offset;
-			continue;
-		}
-
-		if (left_to_write < (blocksize - block_offset))
-			write_size = left_to_write;
-		else
-			write_size = blocksize - block_offset;
-
-		truncated_write_size = write_size;
-#ifdef CONFIG_CMD_NAND_TRIMFFS
-		if (flags & WITH_DROP_FFS)
-			truncated_write_size = drop_ffs(mtd, p_buffer,
-					&write_size);
-#endif
-
-		rval = nand_write(mtd, offset, &truncated_write_size,
-				p_buffer);
-
-		if ((flags & WITH_WR_VERIFY) && !rval)
-			rval = nand_verify(mtd, offset,
-				truncated_write_size, p_buffer);
-
-		offset += write_size;
-		p_buffer += write_size;
-
-		if (rval != 0) {
-			printf("NAND write to offset %llx failed %d\n",
-				offset, rval);
-			*length -= left_to_write;
-			return rval;
-		}
-
-		left_to_write -= write_size;
-	}
-
-	return 0;
-}
-
-/**
- * nand_read_skip_bad:
- *
- * Read image from NAND flash.
- * Blocks that are marked bad are skipped and the next block is read
- * instead as long as the image is short enough to fit even after
- * skipping the bad blocks.  Due to bad blocks we may not be able to
- * perform the requested read.  In the case where the read would extend
- * beyond the end of the NAND device, both length and actual (if not
- * NULL) are set to 0.  In the case where the read would extend beyond
- * the limit we are passed, length is set to 0 and actual is set to the
- * required length.
- *
- * @param mtd nand mtd instance
- * @param offset offset in flash
- * @param length buffer length, on return holds number of read bytes
- * @param actual set to size required to read length worth of buffer or 0
- * on error, if not NULL
- * @param lim maximum size that actual may be in order to not exceed the
- * buffer
- * @param buffer buffer to write to
- * Return: 0 in case of success
- */
-int nand_read_skip_bad(struct mtd_info *mtd, loff_t offset, size_t *length,
-		       size_t *actual, loff_t lim, u_char *buffer)
-{
-	int rval;
-	size_t left_to_read = *length;
-	size_t used_for_read = 0;
-	u_char *p_buffer = buffer;
-	int need_skip;
-
-	if ((offset & (mtd->writesize - 1)) != 0) {
-		printf("Attempt to read non page-aligned data\n");
-		*length = 0;
-		if (actual)
-			*actual = 0;
-		return -EINVAL;
-	}
-
-	need_skip = check_skip_len(mtd, offset, *length, &used_for_read);
-
-	if (actual)
-		*actual = used_for_read;
-
-	if (need_skip < 0) {
-		printf("Attempt to read outside the flash area\n");
-		*length = 0;
-		return -EINVAL;
-	}
-
-	if (used_for_read > lim) {
-		puts("Size of read exceeds partition or device limit\n");
-		*length = 0;
-		return -EFBIG;
-	}
-
-	if (!need_skip) {
-		rval = nand_read(mtd, offset, length, buffer);
-		if (!rval || rval == -EUCLEAN)
-			return 0;
-
-		*length = 0;
-		printf("NAND read from offset %llx failed %d\n",
-			offset, rval);
-		return rval;
-	}
-
-	while (left_to_read > 0) {
-		size_t block_offset = offset & (mtd->erasesize - 1);
-		size_t read_length;
-
-		schedule();
-
-		if (nand_block_isbad(mtd, offset & ~(mtd->erasesize - 1))) {
-			printf("Skipping bad block 0x%08llx\n",
-				offset & ~(mtd->erasesize - 1));
-			offset += mtd->erasesize - block_offset;
-			continue;
-		}
-
-		if (left_to_read < (mtd->erasesize - block_offset))
-			read_length = left_to_read;
-		else
-			read_length = mtd->erasesize - block_offset;
-
-		rval = nand_read(mtd, offset, &read_length, p_buffer);
-		if (rval && rval != -EUCLEAN) {
-			printf("NAND read from offset %llx failed %d\n",
-				offset, rval);
-			*length -= left_to_read;
-			return rval;
-		}
-
-		left_to_read -= read_length;
-		offset       += read_length;
-		p_buffer     += read_length;
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_CMD_NAND_TORTURE
-
-/**
- * check_pattern:
- *
- * Check if buffer contains only a certain byte pattern.
- *
- * @param buf buffer to check
- * @param patt the pattern to check
- * @param size buffer size in bytes
- * Return: 1 if there are only patt bytes in buf
- *         0 if something else was found
- */
-static int check_pattern(const u_char *buf, u_char patt, int size)
-{
-	int i;
-
-	for (i = 0; i < size; i++)
-		if (buf[i] != patt)
-			return 0;
-	return 1;
-}
-
-/**
- * nand_torture:
- *
- * Torture a block of NAND flash.
- * This is useful to determine if a block that caused a write error is still
- * good or should be marked as bad.
- *
- * @param mtd nand mtd instance
- * @param offset offset in flash
- * Return: 0 if the block is still good
- */
-int nand_torture(struct mtd_info *mtd, loff_t offset)
-{
-	u_char patterns[] = {0xa5, 0x5a, 0x00};
-	struct erase_info instr = {
-		.mtd = mtd,
-		.addr = offset,
-		.len = mtd->erasesize,
-	};
-	size_t retlen;
-	int err, ret = -1, i, patt_count;
-	u_char *buf;
-
-	if ((offset & (mtd->erasesize - 1)) != 0) {
-		puts("Attempt to torture a block at a non block-aligned offset\n");
-		return -EINVAL;
-	}
-
-	if (offset + mtd->erasesize > mtd->size) {
-		puts("Attempt to torture a block outside the flash area\n");
-		return -EINVAL;
-	}
-
-	patt_count = ARRAY_SIZE(patterns);
-
-	buf = malloc_cache_aligned(mtd->erasesize);
-	if (buf == NULL) {
-		puts("Out of memory for erase block buffer\n");
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < patt_count; i++) {
-		err = mtd_erase(mtd, &instr);
-		if (err) {
-			printf("%s: erase() failed for block at 0x%llx: %d\n",
-				mtd->name, instr.addr, err);
-			goto out;
-		}
-
-		/* Make sure the block contains only 0xff bytes */
-		err = mtd_read(mtd, offset, mtd->erasesize, &retlen, buf);
-		if ((err && err != -EUCLEAN) || retlen != mtd->erasesize) {
-			printf("%s: read() failed for block at 0x%llx: %d\n",
-				mtd->name, instr.addr, err);
-			goto out;
-		}
-
-		err = check_pattern(buf, 0xff, mtd->erasesize);
-		if (!err) {
-			printf("Erased block at 0x%llx, but a non-0xff byte was found\n",
-				offset);
-			ret = -EIO;
-			goto out;
-		}
-
-		/* Write a pattern and check it */
-		memset(buf, patterns[i], mtd->erasesize);
-		err = mtd_write(mtd, offset, mtd->erasesize, &retlen, buf);
-		if (err || retlen != mtd->erasesize) {
-			printf("%s: write() failed for block at 0x%llx: %d\n",
-				mtd->name, instr.addr, err);
-			goto out;
-		}
-
-		err = mtd_read(mtd, offset, mtd->erasesize, &retlen, buf);
-		if ((err && err != -EUCLEAN) || retlen != mtd->erasesize) {
-			printf("%s: read() failed for block at 0x%llx: %d\n",
-				mtd->name, instr.addr, err);
-			goto out;
-		}
-
-		err = check_pattern(buf, patterns[i], mtd->erasesize);
-		if (!err) {
-			printf("Pattern 0x%.2x checking failed for block at "
-					"0x%llx\n", patterns[i], offset);
-			ret = -EIO;
-			goto out;
-		}
-	}
-
-	ret = 0;
-
-out:
-	free(buf);
-	return ret;
-}
-
-#endif
diff --git a/drivers/mtd/nand/util.c b/drivers/mtd/nand/util.c
new file mode 100644
index 0000000000..4a372bb67d
--- /dev/null
+++ b/drivers/mtd/nand/util.c
@@ -0,0 +1,543 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * drivers/mtd/nand/util.c
+ *
+ * Copyright (C) 2006 by Weiss-Electronic GmbH.
+ * All rights reserved.
+ *
+ * @author:	Guido Classen <clagix@gmail.com>
+ * @descr:	NAND Flash support
+ * @references: borrowed heavily from Linux mtd-utils code:
+ *		flash_eraseall.c by Arcom Control System Ltd
+ *		nandwrite.c by Steven J. Hill (sjhill@realitydiluted.com)
+ *			       and Thomas Gleixner (tglx@linutronix.de)
+ *
+ * Copyright (C) 2008 Nokia Corporation: drop_ffs() function by
+ * Artem Bityutskiy <dedekind1@gmail.com> from mtd-utils
+ *
+ * Copyright 2010 Freescale Semiconductor
+ */
+
+#include <common.h>
+#include <command.h>
+#include <log.h>
+#include <watchdog.h>
+#include <malloc.h>
+#include <memalign.h>
+#include <div64.h>
+#include <asm/cache.h>
+#include <dm/devres.h>
+
+#include <linux/errno.h>
+#include <linux/mtd/mtd.h>
+#include <nand.h>
+
+/**
+ * check_skip_len
+ *
+ * Check if there are any bad blocks, and whether length including bad
+ * blocks fits into device
+ *
+ * @param mtd nand mtd instance
+ * @param offset offset in flash
+ * @param length image length
+ * @param used length of flash needed for the requested length
+ * Return: 0 if the image fits and there are no bad blocks
+ *         1 if the image fits, but there are bad blocks
+ *        -1 if the image does not fit
+ */
+static int check_skip_len(struct mtd_info *mtd, loff_t offset, size_t length,
+			  size_t *used)
+{
+	size_t len_excl_bad = 0;
+	int ret = 0;
+
+	while (len_excl_bad < length) {
+		size_t block_len, block_off;
+		loff_t block_start;
+
+		if (offset >= mtd->size)
+			return -1;
+
+		block_start = offset & ~(loff_t)(mtd->erasesize - 1);
+		block_off = offset & (mtd->erasesize - 1);
+		block_len = mtd->erasesize - block_off;
+
+		if (!nand_block_isbad(mtd, block_start))
+			len_excl_bad += block_len;
+		else
+			ret = 1;
+
+		offset += block_len;
+		*used += block_len;
+	}
+
+	/* If the length is not a multiple of block_len, adjust. */
+	if (len_excl_bad > length)
+		*used -= (len_excl_bad - length);
+
+	return ret;
+}
+
+#ifdef CONFIG_CMD_NAND_TRIMFFS
+static size_t drop_ffs(const struct mtd_info *mtd, const u_char *buf,
+			const size_t *len)
+{
+	size_t l = *len;
+	ssize_t i;
+
+	for (i = l - 1; i >= 0; i--)
+		if (buf[i] != 0xFF)
+			break;
+
+	/* The resulting length must be aligned to the minimum flash I/O size */
+	l = i + 1;
+	l = (l + mtd->writesize - 1) / mtd->writesize;
+	l *=  mtd->writesize;
+
+	/*
+	 * since the input length may be unaligned, prevent access past the end
+	 * of the buffer
+	 */
+	return min(l, *len);
+}
+#endif
+
+/**
+ * nand_verify_page_oob:
+ *
+ * Verify a page of NAND flash, including the OOB.
+ * Reads page of NAND and verifies the contents and OOB against the
+ * values in ops.
+ *
+ * @param mtd		nand mtd instance
+ * @param ops		MTD operations, including data to verify
+ * @param ofs		offset in flash
+ * Return:		0 in case of success
+ */
+int nand_verify_page_oob(struct mtd_info *mtd, struct mtd_oob_ops *ops,
+			 loff_t ofs)
+{
+	int rval;
+	struct mtd_oob_ops vops;
+	size_t verlen = mtd->writesize + mtd->oobsize;
+
+	memcpy(&vops, ops, sizeof(vops));
+
+	vops.datbuf = memalign(ARCH_DMA_MINALIGN, verlen);
+
+	if (!vops.datbuf)
+		return -ENOMEM;
+
+	vops.oobbuf = vops.datbuf + mtd->writesize;
+
+	rval = mtd_read_oob(mtd, ofs, &vops);
+	if (!rval)
+		rval = memcmp(ops->datbuf, vops.datbuf, vops.len);
+	if (!rval)
+		rval = memcmp(ops->oobbuf, vops.oobbuf, vops.ooblen);
+
+	free(vops.datbuf);
+
+	return rval ? -EIO : 0;
+}
+
+/**
+ * nand_verify:
+ *
+ * Verify a region of NAND flash.
+ * Reads NAND in page-sized chunks and verifies the contents against
+ * the contents of a buffer.  The offset into the NAND must be
+ * page-aligned, and the function doesn't handle skipping bad blocks.
+ *
+ * @param mtd		nand mtd instance
+ * @param ofs		offset in flash
+ * @param len		buffer length
+ * @param buf		buffer to read from
+ * Return:		0 in case of success
+ */
+int nand_verify(struct mtd_info *mtd, loff_t ofs, size_t len, u_char *buf)
+{
+	int rval = 0;
+	size_t verofs;
+	size_t verlen = mtd->writesize;
+	uint8_t *verbuf = memalign(ARCH_DMA_MINALIGN, verlen);
+
+	if (!verbuf)
+		return -ENOMEM;
+
+	/* Read the NAND back in page-size groups to limit malloc size */
+	for (verofs = ofs; verofs < ofs + len;
+	     verofs += verlen, buf += verlen) {
+		verlen = min(mtd->writesize, (uint32_t)(ofs + len - verofs));
+		rval = nand_read(mtd, verofs, &verlen, verbuf);
+		if (!rval || (rval == -EUCLEAN))
+			rval = memcmp(buf, verbuf, verlen);
+
+		if (rval)
+			break;
+	}
+
+	free(verbuf);
+
+	return rval ? -EIO : 0;
+}
+
+/**
+ * nand_write_skip_bad:
+ *
+ * Write image to NAND flash.
+ * Blocks that are marked bad are skipped and the is written to the next
+ * block instead as long as the image is short enough to fit even after
+ * skipping the bad blocks.  Due to bad blocks we may not be able to
+ * perform the requested write.  In the case where the write would
+ * extend beyond the end of the NAND device, both length and actual (if
+ * not NULL) are set to 0.  In the case where the write would extend
+ * beyond the limit we are passed, length is set to 0 and actual is set
+ * to the required length.
+ *
+ * @param mtd		nand mtd instance
+ * @param offset	offset in flash
+ * @param length	buffer length
+ * @param actual	set to size required to write length worth of
+ *			buffer or 0 on error, if not NULL
+ * @param lim		maximum size that actual may be in order to not
+ *			exceed the buffer
+ * @param buffer        buffer to read from
+ * @param flags		flags modifying the behaviour of the write to NAND
+ * Return:		0 in case of success
+ */
+int nand_write_skip_bad(struct mtd_info *mtd, loff_t offset, size_t *length,
+			size_t *actual, loff_t lim, u_char *buffer, int flags)
+{
+	int rval = 0, blocksize;
+	size_t left_to_write = *length;
+	size_t used_for_write = 0;
+	u_char *p_buffer = buffer;
+	int need_skip;
+
+	if (actual)
+		*actual = 0;
+
+	blocksize = mtd->erasesize;
+
+	/*
+	 * nand_write() handles unaligned, partial page writes.
+	 *
+	 * We allow length to be unaligned, for convenience in
+	 * using the $filesize variable.
+	 *
+	 * However, starting at an unaligned offset makes the
+	 * semantics of bad block skipping ambiguous (really,
+	 * you should only start a block skipping access at a
+	 * partition boundary).  So don't try to handle that.
+	 */
+	if ((offset & (mtd->writesize - 1)) != 0) {
+		printf("Attempt to write non page-aligned data\n");
+		*length = 0;
+		return -EINVAL;
+	}
+
+	need_skip = check_skip_len(mtd, offset, *length, &used_for_write);
+
+	if (actual)
+		*actual = used_for_write;
+
+	if (need_skip < 0) {
+		printf("Attempt to write outside the flash area\n");
+		*length = 0;
+		return -EINVAL;
+	}
+
+	if (used_for_write > lim) {
+		puts("Size of write exceeds partition or device limit\n");
+		*length = 0;
+		return -EFBIG;
+	}
+
+	if (!need_skip && !(flags & WITH_DROP_FFS)) {
+		rval = nand_write(mtd, offset, length, buffer);
+
+		if ((flags & WITH_WR_VERIFY) && !rval)
+			rval = nand_verify(mtd, offset, *length, buffer);
+
+		if (rval == 0)
+			return 0;
+
+		*length = 0;
+		printf("NAND write to offset %llx failed %d\n",
+			offset, rval);
+		return rval;
+	}
+
+	while (left_to_write > 0) {
+		loff_t block_start = offset & ~(loff_t)(mtd->erasesize - 1);
+		size_t block_offset = offset & (mtd->erasesize - 1);
+		size_t write_size, truncated_write_size;
+
+		schedule();
+
+		if (nand_block_isbad(mtd, block_start)) {
+			printf("Skip bad block 0x%08llx\n", block_start);
+			offset += mtd->erasesize - block_offset;
+			continue;
+		}
+
+		if (left_to_write < (blocksize - block_offset))
+			write_size = left_to_write;
+		else
+			write_size = blocksize - block_offset;
+
+		truncated_write_size = write_size;
+#ifdef CONFIG_CMD_NAND_TRIMFFS
+		if (flags & WITH_DROP_FFS)
+			truncated_write_size = drop_ffs(mtd, p_buffer,
+					&write_size);
+#endif
+
+		rval = nand_write(mtd, offset, &truncated_write_size,
+				p_buffer);
+
+		if ((flags & WITH_WR_VERIFY) && !rval)
+			rval = nand_verify(mtd, offset,
+				truncated_write_size, p_buffer);
+
+		offset += write_size;
+		p_buffer += write_size;
+
+		if (rval != 0) {
+			printf("NAND write to offset %llx failed %d\n",
+				offset, rval);
+			*length -= left_to_write;
+			return rval;
+		}
+
+		left_to_write -= write_size;
+	}
+
+	return 0;
+}
+
+/**
+ * nand_read_skip_bad:
+ *
+ * Read image from NAND flash.
+ * Blocks that are marked bad are skipped and the next block is read
+ * instead as long as the image is short enough to fit even after
+ * skipping the bad blocks.  Due to bad blocks we may not be able to
+ * perform the requested read.  In the case where the read would extend
+ * beyond the end of the NAND device, both length and actual (if not
+ * NULL) are set to 0.  In the case where the read would extend beyond
+ * the limit we are passed, length is set to 0 and actual is set to the
+ * required length.
+ *
+ * @param mtd nand mtd instance
+ * @param offset offset in flash
+ * @param length buffer length, on return holds number of read bytes
+ * @param actual set to size required to read length worth of buffer or 0
+ * on error, if not NULL
+ * @param lim maximum size that actual may be in order to not exceed the
+ * buffer
+ * @param buffer buffer to write to
+ * Return: 0 in case of success
+ */
+int nand_read_skip_bad(struct mtd_info *mtd, loff_t offset, size_t *length,
+		       size_t *actual, loff_t lim, u_char *buffer)
+{
+	int rval;
+	size_t left_to_read = *length;
+	size_t used_for_read = 0;
+	u_char *p_buffer = buffer;
+	int need_skip;
+
+	if ((offset & (mtd->writesize - 1)) != 0) {
+		printf("Attempt to read non page-aligned data\n");
+		*length = 0;
+		if (actual)
+			*actual = 0;
+		return -EINVAL;
+	}
+
+	need_skip = check_skip_len(mtd, offset, *length, &used_for_read);
+
+	if (actual)
+		*actual = used_for_read;
+
+	if (need_skip < 0) {
+		printf("Attempt to read outside the flash area\n");
+		*length = 0;
+		return -EINVAL;
+	}
+
+	if (used_for_read > lim) {
+		puts("Size of read exceeds partition or device limit\n");
+		*length = 0;
+		return -EFBIG;
+	}
+
+	if (!need_skip) {
+		rval = nand_read(mtd, offset, length, buffer);
+		if (!rval || rval == -EUCLEAN)
+			return 0;
+
+		*length = 0;
+		printf("NAND read from offset %llx failed %d\n",
+			offset, rval);
+		return rval;
+	}
+
+	while (left_to_read > 0) {
+		size_t block_offset = offset & (mtd->erasesize - 1);
+		size_t read_length;
+
+		schedule();
+
+		if (nand_block_isbad(mtd, offset & ~(mtd->erasesize - 1))) {
+			printf("Skipping bad block 0x%08llx\n",
+				offset & ~(mtd->erasesize - 1));
+			offset += mtd->erasesize - block_offset;
+			continue;
+		}
+
+		if (left_to_read < (mtd->erasesize - block_offset))
+			read_length = left_to_read;
+		else
+			read_length = mtd->erasesize - block_offset;
+
+		rval = nand_read(mtd, offset, &read_length, p_buffer);
+		if (rval && rval != -EUCLEAN) {
+			printf("NAND read from offset %llx failed %d\n",
+				offset, rval);
+			*length -= left_to_read;
+			return rval;
+		}
+
+		left_to_read -= read_length;
+		offset       += read_length;
+		p_buffer     += read_length;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_CMD_NAND_TORTURE
+
+/**
+ * check_pattern:
+ *
+ * Check if buffer contains only a certain byte pattern.
+ *
+ * @param buf buffer to check
+ * @param patt the pattern to check
+ * @param size buffer size in bytes
+ * Return: 1 if there are only patt bytes in buf
+ *         0 if something else was found
+ */
+static int check_pattern(const u_char *buf, u_char patt, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		if (buf[i] != patt)
+			return 0;
+	return 1;
+}
+
+/**
+ * nand_torture:
+ *
+ * Torture a block of NAND flash.
+ * This is useful to determine if a block that caused a write error is still
+ * good or should be marked as bad.
+ *
+ * @param mtd nand mtd instance
+ * @param offset offset in flash
+ * Return: 0 if the block is still good
+ */
+int nand_torture(struct mtd_info *mtd, loff_t offset)
+{
+	u_char patterns[] = {0xa5, 0x5a, 0x00};
+	struct erase_info instr = {
+		.mtd = mtd,
+		.addr = offset,
+		.len = mtd->erasesize,
+	};
+	size_t retlen;
+	int err, ret = -1, i, patt_count;
+	u_char *buf;
+
+	if ((offset & (mtd->erasesize - 1)) != 0) {
+		puts("Attempt to torture a block at a non block-aligned offset\n");
+		return -EINVAL;
+	}
+
+	if (offset + mtd->erasesize > mtd->size) {
+		puts("Attempt to torture a block outside the flash area\n");
+		return -EINVAL;
+	}
+
+	patt_count = ARRAY_SIZE(patterns);
+
+	buf = malloc_cache_aligned(mtd->erasesize);
+	if (buf == NULL) {
+		puts("Out of memory for erase block buffer\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < patt_count; i++) {
+		err = mtd_erase(mtd, &instr);
+		if (err) {
+			printf("%s: erase() failed for block at 0x%llx: %d\n",
+				mtd->name, instr.addr, err);
+			goto out;
+		}
+
+		/* Make sure the block contains only 0xff bytes */
+		err = mtd_read(mtd, offset, mtd->erasesize, &retlen, buf);
+		if ((err && err != -EUCLEAN) || retlen != mtd->erasesize) {
+			printf("%s: read() failed for block at 0x%llx: %d\n",
+				mtd->name, instr.addr, err);
+			goto out;
+		}
+
+		err = check_pattern(buf, 0xff, mtd->erasesize);
+		if (!err) {
+			printf("Erased block at 0x%llx, but a non-0xff byte was found\n",
+				offset);
+			ret = -EIO;
+			goto out;
+		}
+
+		/* Write a pattern and check it */
+		memset(buf, patterns[i], mtd->erasesize);
+		err = mtd_write(mtd, offset, mtd->erasesize, &retlen, buf);
+		if (err || retlen != mtd->erasesize) {
+			printf("%s: write() failed for block at 0x%llx: %d\n",
+				mtd->name, instr.addr, err);
+			goto out;
+		}
+
+		err = mtd_read(mtd, offset, mtd->erasesize, &retlen, buf);
+		if ((err && err != -EUCLEAN) || retlen != mtd->erasesize) {
+			printf("%s: read() failed for block at 0x%llx: %d\n",
+				mtd->name, instr.addr, err);
+			goto out;
+		}
+
+		err = check_pattern(buf, patterns[i], mtd->erasesize);
+		if (!err) {
+			printf("Pattern 0x%.2x checking failed for block at "
+					"0x%llx\n", patterns[i], offset);
+			ret = -EIO;
+			goto out;
+		}
+	}
+
+	ret = 0;
+
+out:
+	free(buf);
+	return ret;
+}
+
+#endif
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v1 04/12] nand: move nand_erase_opts() to core NAND folder
  2023-12-28 15:39 [PATCH v1 00/12] Support SPI NAND in fastboot protocol Alexey Romanov
                   ` (2 preceding siblings ...)
  2023-12-28 15:39 ` [PATCH v1 03/12] nand: move nand_util.c to NAND core folder Alexey Romanov
@ 2023-12-28 15:39 ` Alexey Romanov
  2024-01-03  8:21   ` Michael Nazzareno Trimarchi
  2023-12-28 15:39 ` [PATCH v1 05/12] spi: add board_nand_init() function Alexey Romanov
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Alexey Romanov @ 2023-12-28 15:39 UTC (permalink / raw)
  To: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, michael, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

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


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v1 05/12] spi: add board_nand_init() function
  2023-12-28 15:39 [PATCH v1 00/12] Support SPI NAND in fastboot protocol Alexey Romanov
                   ` (3 preceding siblings ...)
  2023-12-28 15:39 ` [PATCH v1 04/12] nand: move nand_erase_opts() to core NAND folder Alexey Romanov
@ 2023-12-28 15:39 ` Alexey Romanov
  2023-12-28 15:39 ` [PATCH v1 06/12] spi: use nand_register() instead of add_mtd_device() Alexey Romanov
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Alexey Romanov @ 2023-12-28 15:39 UTC (permalink / raw)
  To: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, michael, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

By analogy with RAW NAND drivers, select SYS_NAND_SELF_INIT
option and implement board_nand_init() function. It will be
called from nand_init().

Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
---
 drivers/mtd/nand/spi/Kconfig |  1 +
 drivers/mtd/nand/spi/core.c  | 14 ++++++++++++++
 2 files changed, 15 insertions(+)

diff --git a/drivers/mtd/nand/spi/Kconfig b/drivers/mtd/nand/spi/Kconfig
index 0777dfdf0a..c9ca76a1c9 100644
--- a/drivers/mtd/nand/spi/Kconfig
+++ b/drivers/mtd/nand/spi/Kconfig
@@ -2,6 +2,7 @@ menuconfig MTD_SPI_NAND
 	bool "SPI NAND device Support"
 	depends on DM_MTD && DM_SPI
 	select MTD_NAND_CORE
+	select SYS_NAND_SELF_INIT
 	select SPI_MEM
 	help
 	  This is the framework for the SPI NAND device drivers.
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 202e3f11ec..27ad6fefdb 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -28,6 +28,7 @@
 #include <spi-mem.h>
 #include <dm/device_compat.h>
 #include <dm/devres.h>
+#include <dm/uclass.h>
 #include <linux/bitops.h>
 #include <linux/bug.h>
 #include <linux/mtd/spinand.h>
@@ -1296,3 +1297,16 @@ U_BOOT_DRIVER(spinand) = {
 	.priv_auto	= sizeof(struct spinand_device),
 	.probe = spinand_probe,
 };
+
+void board_nand_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_get_device_by_driver(UCLASS_SPI,
+					  DM_DRIVER_GET(spinand),
+					  &dev);
+	if (ret && ret != -ENODEV)
+		log_err("Failed to initialize SPI NAND driver. (error %d)\n",
+			ret);
+}
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v1 06/12] spi: use nand_register() instead of add_mtd_device()
  2023-12-28 15:39 [PATCH v1 00/12] Support SPI NAND in fastboot protocol Alexey Romanov
                   ` (4 preceding siblings ...)
  2023-12-28 15:39 ` [PATCH v1 05/12] spi: add board_nand_init() function Alexey Romanov
@ 2023-12-28 15:39 ` Alexey Romanov
  2023-12-28 15:39 ` [PATCH v1 07/12] mtdparts: use negative error codes Alexey Romanov
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Alexey Romanov @ 2023-12-28 15:39 UTC (permalink / raw)
  To: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, michael, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

Most functions that work with NAND device (for example fastboot),
use the get_nand_dev_by_index() function to work with NAND MTD.
In order to use this feature, SPI NAND must be registered via
nand_register().

Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
---
 drivers/mtd/nand/spi/core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 27ad6fefdb..5210332712 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -23,6 +23,7 @@
 #else
 #include <common.h>
 #include <errno.h>
+#include <nand.h>
 #include <watchdog.h>
 #include <spi.h>
 #include <spi-mem.h>
@@ -1222,7 +1223,7 @@ static int spinand_probe(struct udevice *dev)
 #ifndef __UBOOT__
 	ret = mtd_device_register(mtd, NULL, 0);
 #else
-	ret = add_mtd_device(mtd);
+	ret = nand_register(0, mtd);
 #endif
 	if (ret)
 		goto err_spinand_cleanup;
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v1 07/12] mtdparts: use negative error codes
  2023-12-28 15:39 [PATCH v1 00/12] Support SPI NAND in fastboot protocol Alexey Romanov
                   ` (5 preceding siblings ...)
  2023-12-28 15:39 ` [PATCH v1 06/12] spi: use nand_register() instead of add_mtd_device() Alexey Romanov
@ 2023-12-28 15:39 ` Alexey Romanov
  2024-01-03  8:24   ` Michael Nazzareno Trimarchi
  2023-12-28 15:39 ` [PATCH v1 08/12] jffs2: " Alexey Romanov
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Alexey Romanov @ 2023-12-28 15:39 UTC (permalink / raw)
  To: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, michael, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

It is bad practice to use such error codes. Error codes
must be negative.

Also, fastboot code expects that if successful, mtdparts
functions will return a value greater than 0. You can see
fastboot_nand_get_part_info() functions calls inside
getvar_get_part_info().

And use 'return CMD_RET_FAILURE' define instead of 'return 1'.

Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
---
 cmd/mtdparts.c | 154 ++++++++++++++++++++++++-------------------------
 1 file changed, 77 insertions(+), 77 deletions(-)

diff --git a/cmd/mtdparts.c b/cmd/mtdparts.c
index 0984158f41..08e5b794db 100644
--- a/cmd/mtdparts.c
+++ b/cmd/mtdparts.c
@@ -299,7 +299,7 @@ static void current_save(void)
  * @param type mtd type
  * @param num mtd number
  * @param mtd a pointer to an mtd_info instance (output)
- * Return: 0 if device is valid, 1 otherwise
+ * Return: 0 if device is valid, -errno otherwise
  */
 static int get_mtd_info(u8 type, u8 num, struct mtd_info **mtd)
 {
@@ -309,7 +309,7 @@ static int get_mtd_info(u8 type, u8 num, struct mtd_info **mtd)
 	*mtd = get_mtd_device_nm(mtd_dev);
 	if (IS_ERR(*mtd)) {
 		printf("Device %s not found!\n", mtd_dev);
-		return 1;
+		return -ENODEV;
 	}
 	put_mtd_device(*mtd);
 
@@ -323,7 +323,7 @@ static int get_mtd_info(u8 type, u8 num, struct mtd_info **mtd)
  *
  * @param id of the parent device
  * @param part partition to validate
- * Return: 0 if partition is valid, 1 otherwise
+ * Return: 0 if partition is valid, -errno otherwise
  */
 static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
 {
@@ -333,7 +333,7 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
 	u64 offset, size;
 
 	if (get_mtd_info(id->type, id->num, &mtd))
-		return 1;
+		return -EINVAL;
 
 	part->sector_size = mtd->erasesize;
 
@@ -347,14 +347,14 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
 			printf("%s%d: partition (%s) start offset"
 			       "alignment incorrect\n",
 			       MTD_DEV_TYPE(id->type), id->num, part->name);
-			return 1;
+			return -EINVAL;
 		}
 
 		size = part->size;
 		if (do_div(size, mtd->erasesize)) {
 			printf("%s%d: partition (%s) size alignment incorrect\n",
 			       MTD_DEV_TYPE(id->type), id->num, part->name);
-			return 1;
+			return -EINVAL;
 		}
 	} else {
 		/*
@@ -374,7 +374,7 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
 
 		printf("%s%d: partition (%s) start offset alignment incorrect\n",
 		       MTD_DEV_TYPE(id->type), id->num, part->name);
-		return 1;
+		return -EINVAL;
 
 	start_ok:
 
@@ -393,7 +393,7 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
 
 		printf("%s%d: partition (%s) size alignment incorrect\n",
 		       MTD_DEV_TYPE(id->type), id->num, part->name);
-		return 1;
+		return -EINVAL;
 
 	end_ok:
 		return 0;
@@ -410,7 +410,7 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
  *
  * @param id of the parent device
  * @param part partition to validate
- * Return: 0 if partition is valid, 1 otherwise
+ * Return: 0 if partition is valid, -errno otherwise
  */
 static int part_validate(struct mtdids *id, struct part_info *part)
 {
@@ -420,18 +420,18 @@ static int part_validate(struct mtdids *id, struct part_info *part)
 	if (part->offset > id->size) {
 		printf("%s: offset %08llx beyond flash size %08llx\n",
 				id->mtd_id, part->offset, id->size);
-		return 1;
+		return -EINVAL;
 	}
 
 	if ((part->offset + part->size) <= part->offset) {
 		printf("%s%d: partition (%s) size too big\n",
 				MTD_DEV_TYPE(id->type), id->num, part->name);
-		return 1;
+		return -EINVAL;
 	}
 
 	if (part->offset + part->size > id->size) {
 		printf("%s: partitioning exceeds flash size\n", id->mtd_id);
-		return 1;
+		return -EINVAL;
 	}
 
 	/*
@@ -446,7 +446,7 @@ static int part_validate(struct mtdids *id, struct part_info *part)
  *
  * @param dev device to delete partition from
  * @param part partition to delete
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -ernno otherwise
  */
 static int part_del(struct mtd_device *dev, struct part_info *part)
 {
@@ -544,7 +544,7 @@ static int part_sort_add(struct mtd_device *dev, struct part_info *part)
 		/* be compliant with kernel cmdline, allow only one partition at offset zero */
 		if ((new_pi->offset == pi->offset) && (pi->offset == 0)) {
 			printf("cannot add second partition at offset 0\n");
-			return 1;
+			return -EINVAL;
 		}
 
 		if (new_pi->offset <= pi->offset) {
@@ -574,17 +574,17 @@ static int part_sort_add(struct mtd_device *dev, struct part_info *part)
  *
  * @param dev device to which partition is added
  * @param part partition to be added
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 static int part_add(struct mtd_device *dev, struct part_info *part)
 {
 	/* verify alignment and size */
 	if (part_validate(dev->id, part) != 0)
-		return 1;
+		return -EINVAL;
 
 	/* partition is ok, add it to the list */
 	if (part_sort_add(dev, part) != 0)
-		return 1;
+		return -EINVAL;
 
 	return 0;
 }
@@ -596,7 +596,7 @@ static int part_add(struct mtd_device *dev, struct part_info *part)
  * @param partdef pointer to the partition definition string i.e. <part-def>
  * @param ret output pointer to next char after parse completes (output)
  * @param retpart pointer to the allocated partition (output)
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 static int part_parse(const char *const partdef, const char **ret, struct part_info **retpart)
 {
@@ -622,7 +622,7 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
 		size = memsize_parse(p, &p);
 		if (size < MIN_PART_SIZE) {
 			printf("partition size too small (%llx)\n", size);
-			return 1;
+			return -EINVAL;
 		}
 	}
 
@@ -638,12 +638,12 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
 		name = ++p;
 		if ((p = strchr(name, ')')) == NULL) {
 			printf("no closing ) found in partition name\n");
-			return 1;
+			return -EINVAL;
 		}
 		name_len = p - name + 1;
 		if ((name_len - 1) == 0) {
 			printf("empty partition name\n");
-			return 1;
+			return -EINVAL;
 		}
 		p++;
 	} else {
@@ -664,7 +664,7 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
 		if (size == SIZE_REMAINING) {
 			*ret = NULL;
 			printf("no partitions allowed after a fill-up partition\n");
-			return 1;
+			return -EINVAL;
 		}
 		*ret = ++p;
 	} else if ((*p == ';') || (*p == '\0')) {
@@ -672,14 +672,14 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
 	} else {
 		printf("unexpected character '%c' at the end of partition\n", *p);
 		*ret = NULL;
-		return 1;
+		return -EINVAL;
 	}
 
 	/*  allocate memory */
 	part = (struct part_info *)malloc(sizeof(struct part_info) + name_len);
 	if (!part) {
 		printf("out of memory\n");
-		return 1;
+		return -ENOMEM;
 	}
 	memset(part, 0, sizeof(struct part_info) + name_len);
 	part->size = size;
@@ -714,14 +714,14 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
  * @param type mtd type
  * @param num mtd number
  * @param size a pointer to the size of the mtd device (output)
- * Return: 0 if device is valid, 1 otherwise
+ * Return: 0 if device is valid, -errno otherwise
  */
 static int mtd_device_validate(u8 type, u8 num, u64 *size)
 {
 	struct mtd_info *mtd = NULL;
 
 	if (get_mtd_info(type, num, &mtd))
-		return 1;
+		return -EINVAL;
 
 	*size = mtd->size;
 
@@ -732,7 +732,7 @@ static int mtd_device_validate(u8 type, u8 num, u64 *size)
  * Delete all mtd devices from a supplied devices list, free memory allocated for
  * each device and delete all device partitions.
  *
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 static int device_delall(struct list_head *head)
 {
@@ -756,7 +756,7 @@ static int device_delall(struct list_head *head)
  * from device list and device memory is freed.
  *
  * @param dev device to be deleted
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 static int device_del(struct mtd_device *dev)
 {
@@ -835,7 +835,7 @@ static void device_add(struct mtd_device *dev)
  * @param mtd_dev pointer to the device definition string i.e. <mtd-dev>
  * @param ret output pointer to next char after parse completes (output)
  * @param retdev pointer to the allocated device (output)
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_device **retdev)
 {
@@ -864,7 +864,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
 	mtd_id = p = mtd_dev;
 	if (!(p = strchr(mtd_id, ':'))) {
 		printf("no <mtd-id> identifier\n");
-		return 1;
+		return -EINVAL;
 	}
 	mtd_id_len = p - mtd_id + 1;
 	p++;
@@ -872,7 +872,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
 	/* verify if we have a valid device specified */
 	if ((id = id_find_by_mtd_id(mtd_id, mtd_id_len - 1)) == NULL) {
 		printf("invalid mtd device '%.*s'\n", mtd_id_len - 1, mtd_id);
-		return 1;
+		return -ENODEV;
 	}
 
 	pend = strchr(p, ';');
@@ -915,7 +915,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
 	}
 	if (err == 1) {
 		part_delall(&tmp_list);
-		return 1;
+		return -EINVAL;
 	}
 
 	debug("\ntotal partitions: %d\n", num_parts);
@@ -932,14 +932,14 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
 			printf("unexpected character '%c' at the end of device\n", *p);
 			if (ret)
 				*ret = NULL;
-			return 1;
+			return -EINVAL;
 		}
 	}
 
 	/* allocate memory for mtd_device structure */
 	if ((dev = (struct mtd_device *)malloc(sizeof(struct mtd_device))) == NULL) {
 		printf("out of memory\n");
-		return 1;
+		return -ENOMEM;
 	}
 	memset(dev, 0, sizeof(struct mtd_device));
 	dev->id = id;
@@ -953,7 +953,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
 		list_del(entry);
 		if (part_sort_add(dev, part) != 0) {
 			device_del(dev);
-			return 1;
+			return -EINVAL;
 		}
 	}
 
@@ -966,7 +966,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
 /**
  * Initialize global device list.
  *
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 static int mtd_devices_init(void)
 {
@@ -1037,7 +1037,7 @@ static struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_
  * @param ret_id output pointer to next char after parse completes (output)
  * @param dev_type parsed device type (output)
  * @param dev_num parsed device number (output)
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type,
 		 u8 *dev_num)
@@ -1059,12 +1059,12 @@ int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type,
 		p += 8;
 	} else {
 		printf("incorrect device type in %s\n", id);
-		return 1;
+		return -EINVAL;
 	}
 
 	if (!isdigit(*p)) {
 		printf("incorrect device number in %s\n", id);
-		return 1;
+		return -EINVAL;
 	}
 
 	*dev_num = simple_strtoul(p, (char **)&p, 0);
@@ -1079,7 +1079,7 @@ int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type,
  *
  * @param buf output buffer holding generated mtdparts string (output)
  * @param buflen buffer size
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 static int generate_mtdparts(char *buf, u32 buflen)
 {
@@ -1195,7 +1195,7 @@ static int generate_mtdparts(char *buf, u32 buflen)
 
 cleanup:
 	last_parts[0] = '\0';
-	return 1;
+	return -EINVAL;
 }
 
 /**
@@ -1204,7 +1204,7 @@ cleanup:
  *
  * @param buf output buffer holding generated mtdparts string (output)
  * @param buflen buffer size
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 static int generate_mtdparts_save(char *buf, u32 buflen)
 {
@@ -1342,7 +1342,7 @@ static void list_partitions(void)
  * @param dev pointer to the requested device (output)
  * @param part_num verified partition number (output)
  * @param part pointer to requested partition (output)
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 int find_dev_and_part(const char *id, struct mtd_device **dev,
 		u8 *part_num, struct part_info **part)
@@ -1370,27 +1370,27 @@ int find_dev_and_part(const char *id, struct mtd_device **dev,
 	*part_num = 0;
 
 	if (mtd_id_parse(p, &p, &type, &dnum) != 0)
-		return 1;
+		return -EINVAL;
 
 	if ((*p++ != ',') || (*p == '\0')) {
 		printf("no partition number specified\n");
-		return 1;
+		return -EINVAL;
 	}
 	pnum = simple_strtoul(p, (char **)&p, 0);
 	if (*p != '\0') {
 		printf("unexpected trailing character '%c'\n", *p);
-		return 1;
+		return -EINVAL;
 	}
 
 	if ((*dev = device_find(type, dnum)) == NULL) {
 		printf("no such device %s%d\n", MTD_DEV_TYPE(type), dnum);
-		return 1;
+		return -ENODEV;
 	}
 
 	if ((*part = mtd_part_info(*dev, pnum)) == NULL) {
 		printf("no such partition\n");
 		*dev = NULL;
-		return 1;
+		return -EINVAL;
 	}
 
 	*part_num = pnum;
@@ -1402,7 +1402,7 @@ int find_dev_and_part(const char *id, struct mtd_device **dev,
  * Find and delete partition. For partition id format see find_dev_and_part().
  *
  * @param id string describing device and partition
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 static int delete_partition(const char *id)
 {
@@ -1417,17 +1417,17 @@ static int delete_partition(const char *id)
 				part->name, part->size, part->offset);
 
 		if (part_del(dev, part) != 0)
-			return 1;
+			return -EINVAL;
 
 		if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
 			printf("generated mtdparts too long, resetting to null\n");
-			return 1;
+			return -EINVAL;
 		}
 		return 0;
 	}
 
 	printf("partition %s not found\n", id);
-	return 1;
+	return -ENOENT;
 }
 
 #if defined(CONFIG_CMD_MTDPARTS_SPREAD)
@@ -1478,7 +1478,7 @@ static void spread_partition(struct mtd_info *mtd, struct part_info *part,
  * as big as their mtdparts environment variable sizes and they each start
  * on a good block.
  *
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 static int spread_partitions(void)
 {
@@ -1493,7 +1493,7 @@ static int spread_partitions(void)
 		dev = list_entry(dentry, struct mtd_device, link);
 
 		if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
-			return 1;
+			return -EINVAL;
 
 		part_num = 0;
 		cur_offs = 0;
@@ -1519,7 +1519,7 @@ static int spread_partitions(void)
 
 	if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
 		printf("generated mtdparts too long, resetting to null\n");
-		return 1;
+		return -EINVAL;
 	}
 	return 0;
 }
@@ -1547,7 +1547,7 @@ static const char *env_get_mtdparts(char *buf)
  * for each entry. Add created devices to the global devices list.
  *
  * @param mtdparts string specifing mtd partitions
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 static int parse_mtdparts(const char *const mtdparts)
 {
@@ -1605,7 +1605,7 @@ static int parse_mtdparts(const char *const mtdparts)
  * to the global mtdids list.
  *
  * @param ids mapping string
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 static int parse_mtdids(const char *const ids)
 {
@@ -1646,7 +1646,7 @@ static int parse_mtdids(const char *const ids)
 
 		/* check if requested device exists */
 		if (mtd_device_validate(type, num, &size) != 0)
-			return 1;
+			return -EINVAL;
 
 		/* locate <mtd-id> */
 		mtd_id = p;
@@ -1704,7 +1704,7 @@ static int parse_mtdids(const char *const ids)
 			list_del(entry);
 			free(id_tmp);
 		}
-		return 1;
+		return -EINVAL;
 	}
 
 	return 0;
@@ -1715,7 +1715,7 @@ static int parse_mtdids(const char *const ids)
  * Parse and initialize global mtdids mapping and create global
  * device/partition list.
  *
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 int mtdparts_init(void)
 {
@@ -1768,12 +1768,12 @@ int mtdparts_init(void)
 			env_set("mtdids", (char *)ids);
 		} else {
 			printf("mtdids not defined, no default present\n");
-			return 1;
+			return -ENXIO;
 		}
 	}
 	if (strlen(ids) > MTDIDS_MAXLEN - 1) {
 		printf("mtdids too long (> %d)\n", MTDIDS_MAXLEN);
-		return 1;
+		return -EINVAL;
 	}
 
 	/* use defaults when mtdparts variable is not defined
@@ -1789,7 +1789,7 @@ int mtdparts_init(void)
 
 	if (parts && (strlen(parts) > MTDPARTS_MAXLEN - 1)) {
 		printf("mtdparts too long (> %d)\n", MTDPARTS_MAXLEN);
-		return 1;
+		return -EINVAL;
 	}
 
 	/* check if we have already parsed those mtdids */
@@ -1800,7 +1800,7 @@ int mtdparts_init(void)
 
 		if (parse_mtdids(ids) != 0) {
 			mtd_devices_init();
-			return 1;
+			return -EINVAL;
 		}
 
 		/* ok it's good, save new ids */
@@ -1810,11 +1810,11 @@ int mtdparts_init(void)
 	/* parse partitions if either mtdparts or mtdids were updated */
 	if (parts && ((last_parts[0] == '\0') || ((strcmp(last_parts, parts) != 0)) || ids_changed)) {
 		if (parse_mtdparts(parts) != 0)
-			return 1;
+			return -EINVAL;
 
 		if (list_empty(&devices)) {
 			printf("mtdparts_init: no valid partitions\n");
-			return 1;
+			return -ENXIO;
 		}
 
 		/* ok it's good, save new parts */
@@ -1923,15 +1923,15 @@ static int do_chpart(struct cmd_tbl *cmdtp, int flag, int argc,
 	u8 pnum;
 
 	if (mtdparts_init() !=0)
-		return 1;
+		return CMD_RET_FAILURE;
 
 	if (argc < 2) {
 		printf("no partition id specified\n");
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
 	if (find_dev_and_part(argv[1], &dev, &pnum, &part) != 0)
-		return 1;
+		return CMD_RET_FAILURE;
 
 	current_mtd_dev = dev;
 	current_mtd_partnum = pnum;
@@ -1978,7 +1978,7 @@ static int do_mtdparts(struct cmd_tbl *cmdtp, int flag, int argc,
 
 	/* make sure we are in sync with env variables */
 	if (mtdparts_init() != 0)
-		return 1;
+		return CMD_RET_FAILURE;
 
 	if (argc == 1) {
 		list_partitions();
@@ -2000,11 +2000,11 @@ static int do_mtdparts(struct cmd_tbl *cmdtp, int flag, int argc,
 		struct part_info *p;
 
 		if (mtd_id_parse(argv[2], NULL, &type, &num) != 0)
-			return 1;
+			return CMD_RET_FAILURE;
 
 		if ((id = id_find(type, num)) == NULL) {
 			printf("no such device %s defined in mtdids variable\n", argv[2]);
-			return 1;
+			return CMD_RET_FAILURE;
 		}
 
 		len = strlen(id->mtd_id) + 1;	/* 'mtd_id:' */
@@ -2015,14 +2015,14 @@ static int do_mtdparts(struct cmd_tbl *cmdtp, int flag, int argc,
 
 		if (len >= PART_ADD_DESC_MAXLEN) {
 			printf("too long partition description\n");
-			return 1;
+			return CMD_RET_FAILURE;
 		}
 		sprintf(tmpbuf, "%s:%s(%s)%s",
 				id->mtd_id, argv[3], argv[4], argv[5] ? argv[5] : "");
 		debug("add tmpbuf: %s\n", tmpbuf);
 
 		if ((device_parse(tmpbuf, NULL, &dev) != 0) || (!dev))
-			return 1;
+			return -EINVAL;
 
 		debug("+ %s\t%d\t%s\n", MTD_DEV_TYPE(dev->id->type),
 				dev->id->num, dev->id->mtd_id);
@@ -2031,7 +2031,7 @@ static int do_mtdparts(struct cmd_tbl *cmdtp, int flag, int argc,
 
 #if defined(CONFIG_CMD_MTDPARTS_SPREAD)
 		if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
-			return 1;
+			return CMD_RET_FAILURE;
 
 		if (!strcmp(&argv[1][3], ".spread")) {
 			spread_partition(mtd, p, &next_offset);
@@ -2045,12 +2045,12 @@ static int do_mtdparts(struct cmd_tbl *cmdtp, int flag, int argc,
 		} else if (part_add(dev_tmp, p) != 0) {
 			/* merge new partition with existing ones*/
 			device_del(dev);
-			return 1;
+			return CMD_RET_FAILURE;
 		}
 
 		if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
 			printf("generated mtdparts too long, resetting to null\n");
-			return 1;
+			return CMD_RET_FAILURE;
 		}
 
 		return 0;
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v1 08/12] jffs2: use negative error codes
  2023-12-28 15:39 [PATCH v1 00/12] Support SPI NAND in fastboot protocol Alexey Romanov
                   ` (6 preceding siblings ...)
  2023-12-28 15:39 ` [PATCH v1 07/12] mtdparts: use negative error codes Alexey Romanov
@ 2023-12-28 15:39 ` Alexey Romanov
  2023-12-28 15:39 ` [PATCH v1 09/12] cmd: allow to enable CMD_NAND for SPI NAND devices Alexey Romanov
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Alexey Romanov @ 2023-12-28 15:39 UTC (permalink / raw)
  To: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, michael, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

It is bad practice to use such error codes. Error codes
must be negative.

And use CMD_RET_FAILURE and CMD_RET_SUCCESS defines instead
of 1 and 0.

Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
---
 cmd/jffs2.c | 45 +++++++++++++++++++++++----------------------
 1 file changed, 23 insertions(+), 22 deletions(-)

diff --git a/cmd/jffs2.c b/cmd/jffs2.c
index e00fcc2022..068eeedc58 100644
--- a/cmd/jffs2.c
+++ b/cmd/jffs2.c
@@ -151,7 +151,7 @@ extern int cramfs_info (struct part_info *info);
  * Check device number to be within valid range for given device type.
  *
  * @param dev device to validate
- * Return: 0 if device is valid, 1 otherwise
+ * Return: 0 if device is valid, -errno otherwise
  */
 static int mtd_device_validate(u8 type, u8 num, u32 *size)
 {
@@ -191,7 +191,7 @@ static int mtd_device_validate(u8 type, u8 num, u32 *size)
 	} else
 		printf("Unknown defice type %d\n", type);
 
-	return 1;
+	return -EINVAL;
 }
 
 /**
@@ -202,7 +202,7 @@ static int mtd_device_validate(u8 type, u8 num, u32 *size)
  * @param ret_id output pointer to next char after parse completes (output)
  * @param dev_type parsed device type (output)
  * @param dev_num parsed device number (output)
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 static int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num)
 {
@@ -220,12 +220,12 @@ static int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *d
 		p += 7;
 	} else {
 		printf("incorrect device type in %s\n", id);
-		return 1;
+		return -EINVAL;
 	}
 
 	if (!isdigit(*p)) {
 		printf("incorrect device number in %s\n", id);
-		return 1;
+		return -EINVAL;
 	}
 
 	*dev_num = simple_strtoul(p, (char **)&p, 0);
@@ -328,7 +328,7 @@ static inline u32 get_part_sector_size(struct mtdids *id, struct part_info *part
  * 'Static' version of command line mtdparts_init() routine. Single partition on
  * a single device configuration.
  *
- * Return: 0 on success, 1 otherwise
+ * Return: 0 on success, -errno otherwise
  */
 int mtdparts_init(void)
 {
@@ -348,7 +348,7 @@ int mtdparts_init(void)
 					sizeof(struct mtdids));
 		if (!current_mtd_dev) {
 			printf("out of memory\n");
-			return 1;
+			return -ENOMEM;
 		}
 		memset(current_mtd_dev, 0, sizeof(struct mtd_device) +
 		       sizeof(struct part_info) + sizeof(struct mtdids));
@@ -365,7 +365,7 @@ int mtdparts_init(void)
 				(mtd_device_validate(id->type, id->num, &size) != 0)) {
 			printf("incorrect device: %s%d\n", MTD_DEV_TYPE(id->type), id->num);
 			free(current_mtd_dev);
-			return 1;
+			return -EINVAL;
 		}
 		id->size = size;
 		INIT_LIST_HEAD(&id->link);
@@ -485,7 +485,7 @@ int do_jffs2_fsload(struct cmd_tbl *cmdtp, int flag, int argc,
 
 	/* make sure we are in sync with env variables */
 	if (mtdparts_init() !=0)
-		return 1;
+		return CMD_RET_FAILURE;
 
 	if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){
 
@@ -500,17 +500,18 @@ int do_jffs2_fsload(struct cmd_tbl *cmdtp, int flag, int argc,
 			size = jffs2_1pass_load((char *)offset, part, filename);
 		}
 
-		if (size > 0) {
-			printf("### %s load complete: %d bytes loaded to 0x%lx\n",
-				fsname, size, offset);
-			env_set_hex("filesize", size);
-		} else {
+		if (size <= 0) {
 			printf("### %s LOAD ERROR<%x> for %s!\n", fsname, size, filename);
+			return CMD_RET_FAILURE;
 		}
 
-		return !(size > 0);
+		printf("### %s load complete: %d bytes loaded to 0x%lx\n",
+			fsname, size, offset);
+		env_set_hex("filesize", size);
+
+		return 0;
 	}
-	return 1;
+	return CMD_RET_FAILURE;
 }
 
 /**
@@ -534,7 +535,7 @@ int do_jffs2_ls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 
 	/* make sure we are in sync with env variables */
 	if (mtdparts_init() !=0)
-		return 1;
+		return CMD_RET_FAILURE;
 
 	if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){
 
@@ -546,9 +547,9 @@ int do_jffs2_ls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 			ret = jffs2_1pass_ls(part, filename);
 		}
 
-		return ret ? 0 : 1;
+		return ret ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
 	}
-	return 1;
+	return CMD_RET_FAILURE;
 }
 
 /**
@@ -570,7 +571,7 @@ int do_jffs2_fsinfo(struct cmd_tbl *cmdtp, int flag, int argc,
 
 	/* make sure we are in sync with env variables */
 	if (mtdparts_init() !=0)
-		return 1;
+		return CMD_RET_FAILURE;
 
 	if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){
 
@@ -585,9 +586,9 @@ int do_jffs2_fsinfo(struct cmd_tbl *cmdtp, int flag, int argc,
 			ret = jffs2_1pass_info(part);
 		}
 
-		return ret ? 0 : 1;
+		return ret ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
 	}
-	return 1;
+	return CMD_RET_FAILURE;
 }
 
 /***************************************************/
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v1 09/12] cmd: allow to enable CMD_NAND for SPI NAND devices
  2023-12-28 15:39 [PATCH v1 00/12] Support SPI NAND in fastboot protocol Alexey Romanov
                   ` (7 preceding siblings ...)
  2023-12-28 15:39 ` [PATCH v1 08/12] jffs2: " Alexey Romanov
@ 2023-12-28 15:39 ` Alexey Romanov
  2023-12-28 16:55   ` Sean Anderson
  2023-12-28 15:39 ` [PATCH v1 10/12] fastboot: check device type for SPI NAND too Alexey Romanov
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Alexey Romanov @ 2023-12-28 15:39 UTC (permalink / raw)
  To: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, michael, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

Boards with SPI NAND also can use this command.

Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
---
 cmd/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index c47523a03b..c8484576e2 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1367,7 +1367,7 @@ config CMD_MUX
 config CMD_NAND
 	bool "nand"
 	default y if NAND_SUNXI
-	depends on MTD_RAW_NAND
+	depends on MTD_RAW_NAND || MTD_SPI_NAND
 	help
 	  NAND support.
 
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v1 10/12] fastboot: check device type for SPI NAND too
  2023-12-28 15:39 [PATCH v1 00/12] Support SPI NAND in fastboot protocol Alexey Romanov
                   ` (8 preceding siblings ...)
  2023-12-28 15:39 ` [PATCH v1 09/12] cmd: allow to enable CMD_NAND for SPI NAND devices Alexey Romanov
@ 2023-12-28 15:39 ` Alexey Romanov
  2023-12-28 16:54   ` Sean Anderson
  2024-01-02 13:00   ` Mattijs Korpershoek
  2023-12-28 15:39 ` [PATCH v1 11/12] fastboot: enable FASTBOOT_FLASH option for SPI NAND devices Alexey Romanov
  2023-12-28 15:39 ` [PATCH v1 12/12] fastboot: fb_nand: add missing newlines in pr_err() macro Alexey Romanov
  11 siblings, 2 replies; 23+ messages in thread
From: Alexey Romanov @ 2023-12-28 15:39 UTC (permalink / raw)
  To: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, michael, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

SPI NAND devices also supports 'fastboot erase / flash' commands.

Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
---
 drivers/fastboot/fb_nand.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/fastboot/fb_nand.c b/drivers/fastboot/fb_nand.c
index 6d3a900c77..39d888301f 100644
--- a/drivers/fastboot/fb_nand.c
+++ b/drivers/fastboot/fb_nand.c
@@ -53,7 +53,7 @@ static int fb_nand_lookup(const char *partname,
 		return ret;
 	}
 
-	if (dev->id->type != MTD_DEV_TYPE_NAND) {
+	if (dev->id->type != MTD_DEV_TYPE_NAND && dev->id->type != MTD_DEV_TYPE_SPINAND) {
 		pr_err("partition '%s' is not stored on a NAND device",
 		      partname);
 		fastboot_fail("not a NAND device", response);
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v1 11/12] fastboot: enable FASTBOOT_FLASH option for SPI NAND devices
  2023-12-28 15:39 [PATCH v1 00/12] Support SPI NAND in fastboot protocol Alexey Romanov
                   ` (9 preceding siblings ...)
  2023-12-28 15:39 ` [PATCH v1 10/12] fastboot: check device type for SPI NAND too Alexey Romanov
@ 2023-12-28 15:39 ` Alexey Romanov
  2023-12-28 16:55   ` Sean Anderson
  2024-01-02 13:00   ` Mattijs Korpershoek
  2023-12-28 15:39 ` [PATCH v1 12/12] fastboot: fb_nand: add missing newlines in pr_err() macro Alexey Romanov
  11 siblings, 2 replies; 23+ messages in thread
From: Alexey Romanov @ 2023-12-28 15:39 UTC (permalink / raw)
  To: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, michael, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

From now we can use FASTBOOT_FLASH_NAND option for SPI NAND.

Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
---
 drivers/fastboot/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
index a3df9aa3d0..3cfeea4837 100644
--- a/drivers/fastboot/Kconfig
+++ b/drivers/fastboot/Kconfig
@@ -86,7 +86,7 @@ config FASTBOOT_USB_DEV
 config FASTBOOT_FLASH
 	bool "Enable FASTBOOT FLASH command"
 	default y if ARCH_SUNXI || ARCH_ROCKCHIP
-	depends on MMC || (MTD_RAW_NAND && CMD_MTDPARTS)
+	depends on MMC || ((MTD_RAW_NAND || MTD_SPI_NAND) && CMD_MTDPARTS)
 	select IMAGE_SPARSE
 	help
 	  The fastboot protocol includes a "flash" command for writing
@@ -112,7 +112,7 @@ config FASTBOOT_FLASH_MMC
 
 config FASTBOOT_FLASH_NAND
 	bool "FASTBOOT on NAND"
-	depends on MTD_RAW_NAND && CMD_MTDPARTS
+	depends on (MTD_RAW_NAND || MTD_SPI_NAND) && CMD_MTDPARTS
 
 endchoice
 
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v1 12/12] fastboot: fb_nand: add missing newlines in pr_err() macro
  2023-12-28 15:39 [PATCH v1 00/12] Support SPI NAND in fastboot protocol Alexey Romanov
                   ` (10 preceding siblings ...)
  2023-12-28 15:39 ` [PATCH v1 11/12] fastboot: enable FASTBOOT_FLASH option for SPI NAND devices Alexey Romanov
@ 2023-12-28 15:39 ` Alexey Romanov
  2023-12-28 16:54   ` Sean Anderson
  2024-01-02 13:01   ` Mattijs Korpershoek
  11 siblings, 2 replies; 23+ messages in thread
From: Alexey Romanov @ 2023-12-28 15:39 UTC (permalink / raw)
  To: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, michael, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

pr_err() doesn't add an newline symbol when printing.

Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
---
 drivers/fastboot/fb_nand.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/fastboot/fb_nand.c b/drivers/fastboot/fb_nand.c
index 39d888301f..9db1903e41 100644
--- a/drivers/fastboot/fb_nand.c
+++ b/drivers/fastboot/fb_nand.c
@@ -48,13 +48,13 @@ static int fb_nand_lookup(const char *partname,
 
 	ret = find_dev_and_part(partname, &dev, &pnum, part);
 	if (ret) {
-		pr_err("cannot find partition: '%s'", partname);
+		pr_err("cannot find partition: '%s'\n", partname);
 		fastboot_fail("cannot find partition", response);
 		return ret;
 	}
 
 	if (dev->id->type != MTD_DEV_TYPE_NAND && dev->id->type != MTD_DEV_TYPE_SPINAND) {
-		pr_err("partition '%s' is not stored on a NAND device",
+		pr_err("partition '%s' is not stored on a NAND device\n",
 		      partname);
 		fastboot_fail("not a NAND device", response);
 		return -EINVAL;
@@ -178,7 +178,7 @@ void fastboot_nand_flash_write(const char *cmd, void *download_buffer,
 
 	ret = fb_nand_lookup(cmd, &mtd, &part, response);
 	if (ret) {
-		pr_err("invalid NAND device");
+		pr_err("invalid NAND device\n");
 		fastboot_fail("invalid NAND device", response);
 		return;
 	}
@@ -242,7 +242,7 @@ void fastboot_nand_erase(const char *cmd, char *response)
 
 	ret = fb_nand_lookup(cmd, &mtd, &part, response);
 	if (ret) {
-		pr_err("invalid NAND device");
+		pr_err("invalid NAND device\n");
 		fastboot_fail("invalid NAND device", response);
 		return;
 	}
@@ -253,7 +253,7 @@ void fastboot_nand_erase(const char *cmd, char *response)
 
 	ret = _fb_nand_erase(mtd, part);
 	if (ret) {
-		pr_err("failed erasing from device %s", mtd->name);
+		pr_err("failed erasing from device %s\n", mtd->name);
 		fastboot_fail("failed erasing from device", response);
 		return;
 	}
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH v1 01/12] nand: move NAND initialization API to nand/core.c
  2023-12-28 15:39 ` [PATCH v1 01/12] nand: move NAND initialization API to nand/core.c Alexey Romanov
@ 2023-12-28 16:51   ` Sean Anderson
  0 siblings, 0 replies; 23+ messages in thread
From: Sean Anderson @ 2023-12-28 16:51 UTC (permalink / raw)
  To: Alexey Romanov, michal.simek, marex, michael, stcarlso, tobias,
	seanedmond, abdellatif.elkhlifi, neil.armstrong, n-jain1,
	xypron.glpk, dario.binacchi, michael, frieder.schrempf, sjg, hs,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel

On 12/28/23 10:39, Alexey Romanov wrote:
> nand_register() and nand_init() is generic API for both
> RAW and SPI NAND's. We have to move this functions
> from drivers/mtd/nand/raw/nand.c to drivers/mtd/nand/core.c.
> 
> Functions designed to work with RAW NAND should remain
> in drivers/mtd/nand/raw/nand.c.
> 
> Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
> ---
>  drivers/mtd/Kconfig          |   2 +-
>  drivers/mtd/nand/Kconfig     |  10 +++
>  drivers/mtd/nand/core.c      | 136 +++++++++++++++++++++++++++++++++++
>  drivers/mtd/nand/raw/Kconfig |  10 ---
>  drivers/mtd/nand/raw/nand.c  | 134 ----------------------------------
>  include/nand.h               |   2 +
>  6 files changed, 149 insertions(+), 145 deletions(-)
> 
> diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
> index c56840c849..1902351719 100644
> --- a/drivers/mtd/Kconfig
> +++ b/drivers/mtd/Kconfig
> @@ -260,7 +260,7 @@ config SYS_NAND_MAX_ECCPOS
>  
>  config SYS_NAND_MAX_CHIPS
>  	int "NAND max chips"
> -	depends on MTD_RAW_NAND || CMD_ONENAND || TARGET_S5PC210_UNIVERSAL || \
> +	depends on MTD_RAW_NAND || MTD_SPI_NAND || CMD_ONENAND || TARGET_S5PC210_UNIVERSAL || \
>  		SPL_OMAP3_ID_NAND
>  	default 1
>  	help
> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> index 78ae04bdcb..9a1d4ac0dc 100644
> --- a/drivers/mtd/nand/Kconfig
> +++ b/drivers/mtd/nand/Kconfig
> @@ -1,6 +1,16 @@
>  config MTD_NAND_CORE
>  	tristate
>  
> +config SYS_MAX_NAND_DEVICE
> +	int "Maximum number of NAND devices to support"
> +	default 1
> +
> +config SYS_NAND_SELF_INIT
> +	bool
> +	help
> +	  This option, if enabled, provides more flexible and linux-like
> +	  NAND initialization process.
> +
>  source "drivers/mtd/nand/raw/Kconfig"
>  
>  source "drivers/mtd/nand/spi/Kconfig"
> diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c
> index 4b9dd6a926..ff298e3a0f 100644
> --- a/drivers/mtd/nand/core.c
> +++ b/drivers/mtd/nand/core.c
> @@ -10,6 +10,7 @@
>  #define pr_fmt(fmt)	"nand: " fmt
>  
>  #include <common.h>
> +#include <nand.h>
>  #include <watchdog.h>
>  #ifndef __UBOOT__
>  #include <linux/compat.h>
> @@ -18,6 +19,12 @@
>  #include <linux/bitops.h>
>  #include <linux/mtd/nand.h>
>  
> +int nand_curr_device = -1;
> +
> +static struct mtd_info *nand_info[CONFIG_SYS_MAX_NAND_DEVICE];
> +static char dev_name[CONFIG_SYS_MAX_NAND_DEVICE][8];
> +static unsigned long total_nand_size; /* in kiB */
> +
>  /**
>   * nanddev_isbad() - Check if a block is bad
>   * @nand: NAND device
> @@ -250,6 +257,135 @@ void nanddev_cleanup(struct nand_device *nand)
>  }
>  EXPORT_SYMBOL_GPL(nanddev_cleanup);
>  
> +struct mtd_info *get_nand_dev_by_index(int dev)
> +{
> +	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev] ||
> +	    !nand_info[dev]->name)
> +		return NULL;
> +
> +	return nand_info[dev];
> +}
> +EXPORT_SYMBOL_GPL(get_nand_dev_by_index);
> +
> +int nand_mtd_to_devnum(struct mtd_info *mtd)
> +{
> +	int i;
> +
> +	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
> +		if (mtd && get_nand_dev_by_index(i) == mtd)
> +			return i;
> +	}
> +
> +	return -ENODEV;
> +}
> +EXPORT_SYMBOL_GPL(nand_mtd_to_devnum);
> +
> +/* Register an initialized NAND mtd device with the U-Boot NAND command. */
> +int nand_register(int devnum, struct mtd_info *mtd)
> +{
> +	if (devnum >= CONFIG_SYS_MAX_NAND_DEVICE)
> +		return -EINVAL;
> +
> +	nand_info[devnum] = mtd;
> +
> +	sprintf(dev_name[devnum], "nand%d", devnum);
> +	mtd->name = dev_name[devnum];
> +
> +#ifdef CONFIG_MTD
> +	/*
> +	 * Add MTD device so that we can reference it later
> +	 * via the mtdcore infrastructure (e.g. ubi).
> +	 */
> +	add_mtd_device(mtd);
> +#endif
> +
> +	total_nand_size += mtd->size / 1024;
> +
> +	if (nand_curr_device == -1)
> +		nand_curr_device = devnum;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(nand_register);
> +
> +#ifdef CONFIG_MTD_CONCAT
> +static void create_mtd_concat(void)
> +{
> +	struct mtd_info *nand_info_list[CONFIG_SYS_MAX_NAND_DEVICE];
> +	int nand_devices_found = 0;
> +	int i;
> +
> +	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
> +		struct mtd_info *mtd = get_nand_dev_by_index(i);
> +		if (mtd != NULL) {
> +			nand_info_list[nand_devices_found] = mtd;
> +			nand_devices_found++;
> +		}
> +	}
> +	if (nand_devices_found > 1) {
> +		struct mtd_info *mtd;
> +		char c_mtd_name[16];
> +
> +		/*
> +		 * We detected multiple devices. Concatenate them together.
> +		 */
> +		sprintf(c_mtd_name, "nand%d", nand_devices_found);
> +		mtd = mtd_concat_create(nand_info_list, nand_devices_found,
> +					c_mtd_name);
> +
> +		if (mtd == NULL)
> +			return;
> +
> +		nand_register(nand_devices_found, mtd);
> +	}
> +
> +	return;
> +}
> +#else
> +static void create_mtd_concat(void)
> +{
> +}
> +#endif
> +
> +unsigned long nand_size(void)
> +{
> +	return total_nand_size;
> +}
> +EXPORT_SYMBOL_GPL(nand_size);
> +
> +void nand_init(void)
> +{
> +	static int initialized;
> +
> +	/*
> +	 * Avoid initializing NAND Flash multiple times,
> +	 * otherwise it will calculate a wrong total size.
> +	 */
> +	if (initialized)
> +		return;
> +	initialized = 1;
> +
> +#if CONFIG_IS_ENABLED(SYS_NAND_SELF_INIT)
> +	board_nand_init();
> +#else
> +	int i;
> +
> +	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
> +		nand_init_chip(i);
> +#endif
> +
> +#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
> +	/*
> +	 * Select the chip in the board/cpu specific driver
> +	 */
> +	board_nand_select_device(mtd_to_nand(get_nand_dev_by_index(nand_curr_device)),
> +				 nand_curr_device);
> +#endif
> +
> +	create_mtd_concat();
> +}
> +EXPORT_SYMBOL_GPL(nand_init);
> +
>  MODULE_DESCRIPTION("Generic NAND framework");
>  MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");
>  MODULE_LICENSE("GPL v2");
> diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
> index f0100a601d..31949f1dff 100644
> --- a/drivers/mtd/nand/raw/Kconfig
> +++ b/drivers/mtd/nand/raw/Kconfig
> @@ -3,12 +3,6 @@ menuconfig MTD_RAW_NAND
>  	bool "Raw NAND Device Support"
>  if MTD_RAW_NAND
>  
> -config SYS_NAND_SELF_INIT
> -	bool
> -	help
> -	  This option, if enabled, provides more flexible and linux-like
> -	  NAND initialization process.
> -
>  config SPL_SYS_NAND_SELF_INIT
>  	bool
>  	depends on !SPL_NAND_SIMPLE
> @@ -29,10 +23,6 @@ config TPL_NAND_INIT
>  config SPL_NAND_INIT
>  	bool
>  
> -config SYS_MAX_NAND_DEVICE
> -	int "Maximum number of NAND devices to support"
> -	default 1
> -
>  config SYS_NAND_DRIVER_ECC_LAYOUT
>  	bool "Omit standard ECC layouts to save space"
>  	help
> diff --git a/drivers/mtd/nand/raw/nand.c b/drivers/mtd/nand/raw/nand.c
> index eacd99c4e2..edca824d77 100644
> --- a/drivers/mtd/nand/raw/nand.c
> +++ b/drivers/mtd/nand/raw/nand.c
> @@ -15,68 +15,10 @@
>  #define CFG_SYS_NAND_BASE_LIST { CFG_SYS_NAND_BASE }
>  #endif
>  
> -int nand_curr_device = -1;
> -
> -static struct mtd_info *nand_info[CONFIG_SYS_MAX_NAND_DEVICE];
> -
>  #if !CONFIG_IS_ENABLED(SYS_NAND_SELF_INIT)
>  static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];
>  static ulong base_address[CONFIG_SYS_MAX_NAND_DEVICE] = CFG_SYS_NAND_BASE_LIST;
> -#endif
> -
> -static char dev_name[CONFIG_SYS_MAX_NAND_DEVICE][8];
> -
> -static unsigned long total_nand_size; /* in kiB */
> -
> -struct mtd_info *get_nand_dev_by_index(int dev)
> -{
> -	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev] ||
> -	    !nand_info[dev]->name)
> -		return NULL;
>  
> -	return nand_info[dev];
> -}
> -
> -int nand_mtd_to_devnum(struct mtd_info *mtd)
> -{
> -	int i;
> -
> -	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
> -		if (mtd && get_nand_dev_by_index(i) == mtd)
> -			return i;
> -	}
> -
> -	return -ENODEV;
> -}
> -
> -/* Register an initialized NAND mtd device with the U-Boot NAND command. */
> -int nand_register(int devnum, struct mtd_info *mtd)
> -{
> -	if (devnum >= CONFIG_SYS_MAX_NAND_DEVICE)
> -		return -EINVAL;
> -
> -	nand_info[devnum] = mtd;
> -
> -	sprintf(dev_name[devnum], "nand%d", devnum);
> -	mtd->name = dev_name[devnum];
> -
> -#ifdef CONFIG_MTD
> -	/*
> -	 * Add MTD device so that we can reference it later
> -	 * via the mtdcore infrastructure (e.g. ubi).
> -	 */
> -	add_mtd_device(mtd);
> -#endif
> -
> -	total_nand_size += mtd->size / 1024;
> -
> -	if (nand_curr_device == -1)
> -		nand_curr_device = devnum;
> -
> -	return 0;
> -}
> -
> -#if !CONFIG_IS_ENABLED(SYS_NAND_SELF_INIT)

Please rebase on u-boot/next and also move nand_unregister.

--Sean

>  static void nand_init_chip(int i)
>  {
>  	struct nand_chip *nand = &nand_chip[i];
> @@ -98,79 +40,3 @@ static void nand_init_chip(int i)
>  	nand_register(i, mtd);
>  }
>  #endif
> -
> -#ifdef CONFIG_MTD_CONCAT
> -static void create_mtd_concat(void)
> -{
> -	struct mtd_info *nand_info_list[CONFIG_SYS_MAX_NAND_DEVICE];
> -	int nand_devices_found = 0;
> -	int i;
> -
> -	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
> -		struct mtd_info *mtd = get_nand_dev_by_index(i);
> -		if (mtd != NULL) {
> -			nand_info_list[nand_devices_found] = mtd;
> -			nand_devices_found++;
> -		}
> -	}
> -	if (nand_devices_found > 1) {
> -		struct mtd_info *mtd;
> -		char c_mtd_name[16];
> -
> -		/*
> -		 * We detected multiple devices. Concatenate them together.
> -		 */
> -		sprintf(c_mtd_name, "nand%d", nand_devices_found);
> -		mtd = mtd_concat_create(nand_info_list, nand_devices_found,
> -					c_mtd_name);
> -
> -		if (mtd == NULL)
> -			return;
> -
> -		nand_register(nand_devices_found, mtd);
> -	}
> -
> -	return;
> -}
> -#else
> -static void create_mtd_concat(void)
> -{
> -}
> -#endif
> -
> -unsigned long nand_size(void)
> -{
> -	return total_nand_size;
> -}
> -
> -void nand_init(void)
> -{
> -	static int initialized;
> -
> -	/*
> -	 * Avoid initializing NAND Flash multiple times,
> -	 * otherwise it will calculate a wrong total size.
> -	 */
> -	if (initialized)
> -		return;
> -	initialized = 1;
> -
> -#if CONFIG_IS_ENABLED(SYS_NAND_SELF_INIT)
> -	board_nand_init();
> -#else
> -	int i;
> -
> -	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
> -		nand_init_chip(i);
> -#endif
> -
> -#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
> -	/*
> -	 * Select the chip in the board/cpu specific driver
> -	 */
> -	board_nand_select_device(mtd_to_nand(get_nand_dev_by_index(nand_curr_device)),
> -				 nand_curr_device);
> -#endif
> -
> -	create_mtd_concat();
> -}
> diff --git a/include/nand.h b/include/nand.h
> index 70c1286ccb..16cfc2a24a 100644
> --- a/include/nand.h
> +++ b/include/nand.h
> @@ -25,6 +25,8 @@ int nand_register(int devnum, struct mtd_info *mtd);
>  struct nand_chip;
>  
>  extern int board_nand_init(struct nand_chip *nand);
> +
> +void nand_init_chip(int index);
>  #endif
>  
>  extern int nand_curr_device;


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v1 12/12] fastboot: fb_nand: add missing newlines in pr_err() macro
  2023-12-28 15:39 ` [PATCH v1 12/12] fastboot: fb_nand: add missing newlines in pr_err() macro Alexey Romanov
@ 2023-12-28 16:54   ` Sean Anderson
  2024-01-02 13:01   ` Mattijs Korpershoek
  1 sibling, 0 replies; 23+ messages in thread
From: Sean Anderson @ 2023-12-28 16:54 UTC (permalink / raw)
  To: Alexey Romanov, michal.simek, marex, michael, stcarlso, tobias,
	seanedmond, abdellatif.elkhlifi, neil.armstrong, n-jain1,
	xypron.glpk, dario.binacchi, michael, frieder.schrempf, sjg, hs,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel

On 12/28/23 10:39, Alexey Romanov wrote:
> pr_err() doesn't add an newline symbol when printing.
> 
> Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
> ---
>  drivers/fastboot/fb_nand.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/fastboot/fb_nand.c b/drivers/fastboot/fb_nand.c
> index 39d888301f..9db1903e41 100644
> --- a/drivers/fastboot/fb_nand.c
> +++ b/drivers/fastboot/fb_nand.c
> @@ -48,13 +48,13 @@ static int fb_nand_lookup(const char *partname,
>  
>  	ret = find_dev_and_part(partname, &dev, &pnum, part);
>  	if (ret) {
> -		pr_err("cannot find partition: '%s'", partname);
> +		pr_err("cannot find partition: '%s'\n", partname);
>  		fastboot_fail("cannot find partition", response);
>  		return ret;
>  	}
>  
>  	if (dev->id->type != MTD_DEV_TYPE_NAND && dev->id->type != MTD_DEV_TYPE_SPINAND) {
> -		pr_err("partition '%s' is not stored on a NAND device",
> +		pr_err("partition '%s' is not stored on a NAND device\n",
>  		      partname);
>  		fastboot_fail("not a NAND device", response);
>  		return -EINVAL;
> @@ -178,7 +178,7 @@ void fastboot_nand_flash_write(const char *cmd, void *download_buffer,
>  
>  	ret = fb_nand_lookup(cmd, &mtd, &part, response);
>  	if (ret) {
> -		pr_err("invalid NAND device");
> +		pr_err("invalid NAND device\n");
>  		fastboot_fail("invalid NAND device", response);
>  		return;
>  	}
> @@ -242,7 +242,7 @@ void fastboot_nand_erase(const char *cmd, char *response)
>  
>  	ret = fb_nand_lookup(cmd, &mtd, &part, response);
>  	if (ret) {
> -		pr_err("invalid NAND device");
> +		pr_err("invalid NAND device\n");
>  		fastboot_fail("invalid NAND device", response);
>  		return;
>  	}
> @@ -253,7 +253,7 @@ void fastboot_nand_erase(const char *cmd, char *response)
>  
>  	ret = _fb_nand_erase(mtd, part);
>  	if (ret) {
> -		pr_err("failed erasing from device %s", mtd->name);
> +		pr_err("failed erasing from device %s\n", mtd->name);
>  		fastboot_fail("failed erasing from device", response);
>  		return;
>  	}

Reviewed-by: Sean Anderson <sean.anderson@seco.com>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v1 10/12] fastboot: check device type for SPI NAND too
  2023-12-28 15:39 ` [PATCH v1 10/12] fastboot: check device type for SPI NAND too Alexey Romanov
@ 2023-12-28 16:54   ` Sean Anderson
  2024-01-02 13:00   ` Mattijs Korpershoek
  1 sibling, 0 replies; 23+ messages in thread
From: Sean Anderson @ 2023-12-28 16:54 UTC (permalink / raw)
  To: Alexey Romanov, michal.simek, marex, michael, stcarlso, tobias,
	seanedmond, abdellatif.elkhlifi, neil.armstrong, n-jain1,
	xypron.glpk, dario.binacchi, michael, frieder.schrempf, sjg, hs,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel

On 12/28/23 10:39, Alexey Romanov wrote:
> SPI NAND devices also supports 'fastboot erase / flash' commands.
> 
> Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
> ---
>  drivers/fastboot/fb_nand.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/fastboot/fb_nand.c b/drivers/fastboot/fb_nand.c
> index 6d3a900c77..39d888301f 100644
> --- a/drivers/fastboot/fb_nand.c
> +++ b/drivers/fastboot/fb_nand.c
> @@ -53,7 +53,7 @@ static int fb_nand_lookup(const char *partname,
>  		return ret;
>  	}
>  
> -	if (dev->id->type != MTD_DEV_TYPE_NAND) {
> +	if (dev->id->type != MTD_DEV_TYPE_NAND && dev->id->type != MTD_DEV_TYPE_SPINAND) {
>  		pr_err("partition '%s' is not stored on a NAND device",
>  		      partname);
>  		fastboot_fail("not a NAND device", response);

Reviewed-by: Sean Anderson <sean.anderson@seco.com>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v1 11/12] fastboot: enable FASTBOOT_FLASH option for SPI NAND devices
  2023-12-28 15:39 ` [PATCH v1 11/12] fastboot: enable FASTBOOT_FLASH option for SPI NAND devices Alexey Romanov
@ 2023-12-28 16:55   ` Sean Anderson
  2024-01-02 13:00   ` Mattijs Korpershoek
  1 sibling, 0 replies; 23+ messages in thread
From: Sean Anderson @ 2023-12-28 16:55 UTC (permalink / raw)
  To: Alexey Romanov, michal.simek, marex, michael, stcarlso, tobias,
	seanedmond, abdellatif.elkhlifi, neil.armstrong, n-jain1,
	xypron.glpk, dario.binacchi, michael, frieder.schrempf, sjg, hs,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel

On 12/28/23 10:39, Alexey Romanov wrote:
> From now we can use FASTBOOT_FLASH_NAND option for SPI NAND.
> 
> Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
> ---
>  drivers/fastboot/Kconfig | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
> index a3df9aa3d0..3cfeea4837 100644
> --- a/drivers/fastboot/Kconfig
> +++ b/drivers/fastboot/Kconfig
> @@ -86,7 +86,7 @@ config FASTBOOT_USB_DEV
>  config FASTBOOT_FLASH
>  	bool "Enable FASTBOOT FLASH command"
>  	default y if ARCH_SUNXI || ARCH_ROCKCHIP
> -	depends on MMC || (MTD_RAW_NAND && CMD_MTDPARTS)
> +	depends on MMC || ((MTD_RAW_NAND || MTD_SPI_NAND) && CMD_MTDPARTS)
>  	select IMAGE_SPARSE
>  	help
>  	  The fastboot protocol includes a "flash" command for writing
> @@ -112,7 +112,7 @@ config FASTBOOT_FLASH_MMC
>  
>  config FASTBOOT_FLASH_NAND
>  	bool "FASTBOOT on NAND"
> -	depends on MTD_RAW_NAND && CMD_MTDPARTS
> +	depends on (MTD_RAW_NAND || MTD_SPI_NAND) && CMD_MTDPARTS
>  
>  endchoice
>  

Reviewed-by: Sean Anderson <sean.anderson@seco.com>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v1 09/12] cmd: allow to enable CMD_NAND for SPI NAND devices
  2023-12-28 15:39 ` [PATCH v1 09/12] cmd: allow to enable CMD_NAND for SPI NAND devices Alexey Romanov
@ 2023-12-28 16:55   ` Sean Anderson
  0 siblings, 0 replies; 23+ messages in thread
From: Sean Anderson @ 2023-12-28 16:55 UTC (permalink / raw)
  To: Alexey Romanov, michal.simek, marex, michael, stcarlso, tobias,
	seanedmond, abdellatif.elkhlifi, neil.armstrong, n-jain1,
	xypron.glpk, dario.binacchi, michael, frieder.schrempf, sjg, hs,
	dimorinny, mkorpershoek, patrick.delaunay
  Cc: u-boot, kernel

On 12/28/23 10:39, Alexey Romanov wrote:
> Boards with SPI NAND also can use this command.
> 
> Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
> ---
>  cmd/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index c47523a03b..c8484576e2 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -1367,7 +1367,7 @@ config CMD_MUX
>  config CMD_NAND
>  	bool "nand"
>  	default y if NAND_SUNXI
> -	depends on MTD_RAW_NAND
> +	depends on MTD_RAW_NAND || MTD_SPI_NAND
>  	help
>  	  NAND support.
>  

Reviewed-by: Sean Anderson <sean.anderson@seco.com>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v1 10/12] fastboot: check device type for SPI NAND too
  2023-12-28 15:39 ` [PATCH v1 10/12] fastboot: check device type for SPI NAND too Alexey Romanov
  2023-12-28 16:54   ` Sean Anderson
@ 2024-01-02 13:00   ` Mattijs Korpershoek
  1 sibling, 0 replies; 23+ messages in thread
From: Mattijs Korpershoek @ 2024-01-02 13:00 UTC (permalink / raw)
  To: Alexey Romanov, michal.simek, marex, michael, stcarlso, tobias,
	seanedmond, abdellatif.elkhlifi, neil.armstrong, n-jain1,
	xypron.glpk, dario.binacchi, michael, frieder.schrempf, sjg, hs,
	sean.anderson, dimorinny, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

Hi Alexey,

Thank you for the patch.

On Thu, Dec 28, 2023 at 18:39, Alexey Romanov <avromanov@salutedevices.com> wrote:

> SPI NAND devices also supports 'fastboot erase / flash' commands.
>
> Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>

Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>

> ---
>  drivers/fastboot/fb_nand.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/fastboot/fb_nand.c b/drivers/fastboot/fb_nand.c
> index 6d3a900c77..39d888301f 100644
> --- a/drivers/fastboot/fb_nand.c
> +++ b/drivers/fastboot/fb_nand.c
> @@ -53,7 +53,7 @@ static int fb_nand_lookup(const char *partname,
>  		return ret;
>  	}
>  
> -	if (dev->id->type != MTD_DEV_TYPE_NAND) {
> +	if (dev->id->type != MTD_DEV_TYPE_NAND && dev->id->type != MTD_DEV_TYPE_SPINAND) {
>  		pr_err("partition '%s' is not stored on a NAND device",
>  		      partname);
>  		fastboot_fail("not a NAND device", response);
> -- 
> 2.30.1

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v1 11/12] fastboot: enable FASTBOOT_FLASH option for SPI NAND devices
  2023-12-28 15:39 ` [PATCH v1 11/12] fastboot: enable FASTBOOT_FLASH option for SPI NAND devices Alexey Romanov
  2023-12-28 16:55   ` Sean Anderson
@ 2024-01-02 13:00   ` Mattijs Korpershoek
  1 sibling, 0 replies; 23+ messages in thread
From: Mattijs Korpershoek @ 2024-01-02 13:00 UTC (permalink / raw)
  To: Alexey Romanov, michal.simek, marex, michael, stcarlso, tobias,
	seanedmond, abdellatif.elkhlifi, neil.armstrong, n-jain1,
	xypron.glpk, dario.binacchi, michael, frieder.schrempf, sjg, hs,
	sean.anderson, dimorinny, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

Hi Alexey,

Thank you for the patch.

On Thu, Dec 28, 2023 at 18:39, Alexey Romanov <avromanov@salutedevices.com> wrote:

> From now we can use FASTBOOT_FLASH_NAND option for SPI NAND.
>
> Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>

Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>

> ---
>  drivers/fastboot/Kconfig | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
> index a3df9aa3d0..3cfeea4837 100644
> --- a/drivers/fastboot/Kconfig
> +++ b/drivers/fastboot/Kconfig
> @@ -86,7 +86,7 @@ config FASTBOOT_USB_DEV
>  config FASTBOOT_FLASH
>  	bool "Enable FASTBOOT FLASH command"
>  	default y if ARCH_SUNXI || ARCH_ROCKCHIP
> -	depends on MMC || (MTD_RAW_NAND && CMD_MTDPARTS)
> +	depends on MMC || ((MTD_RAW_NAND || MTD_SPI_NAND) && CMD_MTDPARTS)
>  	select IMAGE_SPARSE
>  	help
>  	  The fastboot protocol includes a "flash" command for writing
> @@ -112,7 +112,7 @@ config FASTBOOT_FLASH_MMC
>  
>  config FASTBOOT_FLASH_NAND
>  	bool "FASTBOOT on NAND"
> -	depends on MTD_RAW_NAND && CMD_MTDPARTS
> +	depends on (MTD_RAW_NAND || MTD_SPI_NAND) && CMD_MTDPARTS
>  
>  endchoice
>  
> -- 
> 2.30.1

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v1 12/12] fastboot: fb_nand: add missing newlines in pr_err() macro
  2023-12-28 15:39 ` [PATCH v1 12/12] fastboot: fb_nand: add missing newlines in pr_err() macro Alexey Romanov
  2023-12-28 16:54   ` Sean Anderson
@ 2024-01-02 13:01   ` Mattijs Korpershoek
  1 sibling, 0 replies; 23+ messages in thread
From: Mattijs Korpershoek @ 2024-01-02 13:01 UTC (permalink / raw)
  To: Alexey Romanov, michal.simek, marex, michael, stcarlso, tobias,
	seanedmond, abdellatif.elkhlifi, neil.armstrong, n-jain1,
	xypron.glpk, dario.binacchi, michael, frieder.schrempf, sjg, hs,
	sean.anderson, dimorinny, patrick.delaunay
  Cc: u-boot, kernel, Alexey Romanov

Hi Alexey,

Thank you for the patch.

On Thu, Dec 28, 2023 at 18:39, Alexey Romanov <avromanov@salutedevices.com> wrote:

> pr_err() doesn't add an newline symbol when printing.
>
> Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>

Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>

> ---
>  drivers/fastboot/fb_nand.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/fastboot/fb_nand.c b/drivers/fastboot/fb_nand.c
> index 39d888301f..9db1903e41 100644
> --- a/drivers/fastboot/fb_nand.c
> +++ b/drivers/fastboot/fb_nand.c
> @@ -48,13 +48,13 @@ static int fb_nand_lookup(const char *partname,
>  
>  	ret = find_dev_and_part(partname, &dev, &pnum, part);
>  	if (ret) {
> -		pr_err("cannot find partition: '%s'", partname);
> +		pr_err("cannot find partition: '%s'\n", partname);
>  		fastboot_fail("cannot find partition", response);
>  		return ret;
>  	}
>  
>  	if (dev->id->type != MTD_DEV_TYPE_NAND && dev->id->type != MTD_DEV_TYPE_SPINAND) {
> -		pr_err("partition '%s' is not stored on a NAND device",
> +		pr_err("partition '%s' is not stored on a NAND device\n",
>  		      partname);
>  		fastboot_fail("not a NAND device", response);
>  		return -EINVAL;
> @@ -178,7 +178,7 @@ void fastboot_nand_flash_write(const char *cmd, void *download_buffer,
>  
>  	ret = fb_nand_lookup(cmd, &mtd, &part, response);
>  	if (ret) {
> -		pr_err("invalid NAND device");
> +		pr_err("invalid NAND device\n");
>  		fastboot_fail("invalid NAND device", response);
>  		return;
>  	}
> @@ -242,7 +242,7 @@ void fastboot_nand_erase(const char *cmd, char *response)
>  
>  	ret = fb_nand_lookup(cmd, &mtd, &part, response);
>  	if (ret) {
> -		pr_err("invalid NAND device");
> +		pr_err("invalid NAND device\n");
>  		fastboot_fail("invalid NAND device", response);
>  		return;
>  	}
> @@ -253,7 +253,7 @@ void fastboot_nand_erase(const char *cmd, char *response)
>  
>  	ret = _fb_nand_erase(mtd, part);
>  	if (ret) {
> -		pr_err("failed erasing from device %s", mtd->name);
> +		pr_err("failed erasing from device %s\n", mtd->name);
>  		fastboot_fail("failed erasing from device", response);
>  		return;
>  	}
> -- 
> 2.30.1

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v1 04/12] nand: move nand_erase_opts() to core NAND folder
  2023-12-28 15:39 ` [PATCH v1 04/12] nand: move nand_erase_opts() to core NAND folder Alexey Romanov
@ 2024-01-03  8:21   ` Michael Nazzareno Trimarchi
  0 siblings, 0 replies; 23+ messages in thread
From: Michael Nazzareno Trimarchi @ 2024-01-03  8:21 UTC (permalink / raw)
  To: Alexey Romanov
  Cc: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay, u-boot, kernel

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>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v1 07/12] mtdparts: use negative error codes
  2023-12-28 15:39 ` [PATCH v1 07/12] mtdparts: use negative error codes Alexey Romanov
@ 2024-01-03  8:24   ` Michael Nazzareno Trimarchi
  0 siblings, 0 replies; 23+ messages in thread
From: Michael Nazzareno Trimarchi @ 2024-01-03  8:24 UTC (permalink / raw)
  To: Alexey Romanov
  Cc: michal.simek, marex, michael, stcarlso, tobias, seanedmond,
	abdellatif.elkhlifi, neil.armstrong, n-jain1, xypron.glpk,
	dario.binacchi, frieder.schrempf, sjg, hs, sean.anderson,
	dimorinny, mkorpershoek, patrick.delaunay, u-boot, kernel

Hi

On Thu, Dec 28, 2023 at 4:39 PM Alexey Romanov
<avromanov@salutedevices.com> wrote:
>
> It is bad practice to use such error codes. Error codes
> must be negative.
>
> Also, fastboot code expects that if successful, mtdparts
> functions will return a value greater than 0. You can see
> fastboot_nand_get_part_info() functions calls inside
> getvar_get_part_info().
>
> And use 'return CMD_RET_FAILURE' define instead of 'return 1'.
>

Can you split the CMD_RET_FAILURE in a separate patch?

> Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
> ---
>  cmd/mtdparts.c | 154 ++++++++++++++++++++++++-------------------------
>  1 file changed, 77 insertions(+), 77 deletions(-)
>
> diff --git a/cmd/mtdparts.c b/cmd/mtdparts.c
> index 0984158f41..08e5b794db 100644
> --- a/cmd/mtdparts.c
> +++ b/cmd/mtdparts.c
> @@ -299,7 +299,7 @@ static void current_save(void)
>   * @param type mtd type
>   * @param num mtd number
>   * @param mtd a pointer to an mtd_info instance (output)
> - * Return: 0 if device is valid, 1 otherwise
> + * Return: 0 if device is valid, -errno otherwise
>   */
>  static int get_mtd_info(u8 type, u8 num, struct mtd_info **mtd)
>  {
> @@ -309,7 +309,7 @@ static int get_mtd_info(u8 type, u8 num, struct mtd_info **mtd)
>         *mtd = get_mtd_device_nm(mtd_dev);
>         if (IS_ERR(*mtd)) {
>                 printf("Device %s not found!\n", mtd_dev);
> -               return 1;
> +               return -ENODEV;
>         }
>         put_mtd_device(*mtd);
>
> @@ -323,7 +323,7 @@ static int get_mtd_info(u8 type, u8 num, struct mtd_info **mtd)
>   *
>   * @param id of the parent device
>   * @param part partition to validate
> - * Return: 0 if partition is valid, 1 otherwise
> + * Return: 0 if partition is valid, -errno otherwise
>   */
>  static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
>  {
> @@ -333,7 +333,7 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
>         u64 offset, size;
>
>         if (get_mtd_info(id->type, id->num, &mtd))
> -               return 1;
> +               return -EINVAL;
>
>         part->sector_size = mtd->erasesize;
>
> @@ -347,14 +347,14 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
>                         printf("%s%d: partition (%s) start offset"
>                                "alignment incorrect\n",
>                                MTD_DEV_TYPE(id->type), id->num, part->name);
> -                       return 1;
> +                       return -EINVAL;
>                 }
>
>                 size = part->size;
>                 if (do_div(size, mtd->erasesize)) {
>                         printf("%s%d: partition (%s) size alignment incorrect\n",
>                                MTD_DEV_TYPE(id->type), id->num, part->name);
> -                       return 1;
> +                       return -EINVAL;
>                 }
>         } else {
>                 /*
> @@ -374,7 +374,7 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
>
>                 printf("%s%d: partition (%s) start offset alignment incorrect\n",
>                        MTD_DEV_TYPE(id->type), id->num, part->name);
> -               return 1;
> +               return -EINVAL;
>
>         start_ok:
>
> @@ -393,7 +393,7 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
>
>                 printf("%s%d: partition (%s) size alignment incorrect\n",
>                        MTD_DEV_TYPE(id->type), id->num, part->name);
> -               return 1;
> +               return -EINVAL;
>
>         end_ok:
>                 return 0;
> @@ -410,7 +410,7 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
>   *
>   * @param id of the parent device
>   * @param part partition to validate
> - * Return: 0 if partition is valid, 1 otherwise
> + * Return: 0 if partition is valid, -errno otherwise
>   */
>  static int part_validate(struct mtdids *id, struct part_info *part)
>  {
> @@ -420,18 +420,18 @@ static int part_validate(struct mtdids *id, struct part_info *part)
>         if (part->offset > id->size) {
>                 printf("%s: offset %08llx beyond flash size %08llx\n",
>                                 id->mtd_id, part->offset, id->size);
> -               return 1;
> +               return -EINVAL;
>         }
>
>         if ((part->offset + part->size) <= part->offset) {
>                 printf("%s%d: partition (%s) size too big\n",
>                                 MTD_DEV_TYPE(id->type), id->num, part->name);
> -               return 1;
> +               return -EINVAL;
>         }
>
>         if (part->offset + part->size > id->size) {
>                 printf("%s: partitioning exceeds flash size\n", id->mtd_id);
> -               return 1;
> +               return -EINVAL;
>         }
>
>         /*
> @@ -446,7 +446,7 @@ static int part_validate(struct mtdids *id, struct part_info *part)
>   *
>   * @param dev device to delete partition from
>   * @param part partition to delete
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -ernno otherwise
>   */
>  static int part_del(struct mtd_device *dev, struct part_info *part)
>  {
> @@ -544,7 +544,7 @@ static int part_sort_add(struct mtd_device *dev, struct part_info *part)
>                 /* be compliant with kernel cmdline, allow only one partition at offset zero */
>                 if ((new_pi->offset == pi->offset) && (pi->offset == 0)) {
>                         printf("cannot add second partition at offset 0\n");
> -                       return 1;
> +                       return -EINVAL;
>                 }
>
>                 if (new_pi->offset <= pi->offset) {
> @@ -574,17 +574,17 @@ static int part_sort_add(struct mtd_device *dev, struct part_info *part)
>   *
>   * @param dev device to which partition is added
>   * @param part partition to be added
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  static int part_add(struct mtd_device *dev, struct part_info *part)
>  {
>         /* verify alignment and size */
>         if (part_validate(dev->id, part) != 0)
> -               return 1;
> +               return -EINVAL;
>
>         /* partition is ok, add it to the list */
>         if (part_sort_add(dev, part) != 0)
> -               return 1;
> +               return -EINVAL;
>
>         return 0;
>  }
> @@ -596,7 +596,7 @@ static int part_add(struct mtd_device *dev, struct part_info *part)
>   * @param partdef pointer to the partition definition string i.e. <part-def>
>   * @param ret output pointer to next char after parse completes (output)
>   * @param retpart pointer to the allocated partition (output)
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  static int part_parse(const char *const partdef, const char **ret, struct part_info **retpart)
>  {
> @@ -622,7 +622,7 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
>                 size = memsize_parse(p, &p);
>                 if (size < MIN_PART_SIZE) {
>                         printf("partition size too small (%llx)\n", size);
> -                       return 1;
> +                       return -EINVAL;
>                 }
>         }
>
> @@ -638,12 +638,12 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
>                 name = ++p;
>                 if ((p = strchr(name, ')')) == NULL) {
>                         printf("no closing ) found in partition name\n");
> -                       return 1;
> +                       return -EINVAL;
>                 }
>                 name_len = p - name + 1;
>                 if ((name_len - 1) == 0) {
>                         printf("empty partition name\n");
> -                       return 1;
> +                       return -EINVAL;
>                 }
>                 p++;
>         } else {
> @@ -664,7 +664,7 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
>                 if (size == SIZE_REMAINING) {
>                         *ret = NULL;
>                         printf("no partitions allowed after a fill-up partition\n");
> -                       return 1;
> +                       return -EINVAL;
>                 }
>                 *ret = ++p;
>         } else if ((*p == ';') || (*p == '\0')) {
> @@ -672,14 +672,14 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
>         } else {
>                 printf("unexpected character '%c' at the end of partition\n", *p);
>                 *ret = NULL;
> -               return 1;
> +               return -EINVAL;
>         }
>
>         /*  allocate memory */
>         part = (struct part_info *)malloc(sizeof(struct part_info) + name_len);
>         if (!part) {
>                 printf("out of memory\n");
> -               return 1;
> +               return -ENOMEM;
>         }
>         memset(part, 0, sizeof(struct part_info) + name_len);
>         part->size = size;
> @@ -714,14 +714,14 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
>   * @param type mtd type
>   * @param num mtd number
>   * @param size a pointer to the size of the mtd device (output)
> - * Return: 0 if device is valid, 1 otherwise
> + * Return: 0 if device is valid, -errno otherwise
>   */
>  static int mtd_device_validate(u8 type, u8 num, u64 *size)
>  {
>         struct mtd_info *mtd = NULL;
>
>         if (get_mtd_info(type, num, &mtd))
> -               return 1;
> +               return -EINVAL;
>
>         *size = mtd->size;
>
> @@ -732,7 +732,7 @@ static int mtd_device_validate(u8 type, u8 num, u64 *size)
>   * Delete all mtd devices from a supplied devices list, free memory allocated for
>   * each device and delete all device partitions.
>   *
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  static int device_delall(struct list_head *head)
>  {
> @@ -756,7 +756,7 @@ static int device_delall(struct list_head *head)
>   * from device list and device memory is freed.
>   *
>   * @param dev device to be deleted
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  static int device_del(struct mtd_device *dev)
>  {
> @@ -835,7 +835,7 @@ static void device_add(struct mtd_device *dev)
>   * @param mtd_dev pointer to the device definition string i.e. <mtd-dev>
>   * @param ret output pointer to next char after parse completes (output)
>   * @param retdev pointer to the allocated device (output)
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_device **retdev)
>  {
> @@ -864,7 +864,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
>         mtd_id = p = mtd_dev;
>         if (!(p = strchr(mtd_id, ':'))) {
>                 printf("no <mtd-id> identifier\n");
> -               return 1;
> +               return -EINVAL;
>         }
>         mtd_id_len = p - mtd_id + 1;
>         p++;
> @@ -872,7 +872,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
>         /* verify if we have a valid device specified */
>         if ((id = id_find_by_mtd_id(mtd_id, mtd_id_len - 1)) == NULL) {
>                 printf("invalid mtd device '%.*s'\n", mtd_id_len - 1, mtd_id);
> -               return 1;
> +               return -ENODEV;
>         }
>
>         pend = strchr(p, ';');
> @@ -915,7 +915,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
>         }
>         if (err == 1) {
>                 part_delall(&tmp_list);
> -               return 1;
> +               return -EINVAL;
>         }
>
>         debug("\ntotal partitions: %d\n", num_parts);
> @@ -932,14 +932,14 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
>                         printf("unexpected character '%c' at the end of device\n", *p);
>                         if (ret)
>                                 *ret = NULL;
> -                       return 1;
> +                       return -EINVAL;
>                 }
>         }
>
>         /* allocate memory for mtd_device structure */
>         if ((dev = (struct mtd_device *)malloc(sizeof(struct mtd_device))) == NULL) {
>                 printf("out of memory\n");
> -               return 1;
> +               return -ENOMEM;
>         }
>         memset(dev, 0, sizeof(struct mtd_device));
>         dev->id = id;
> @@ -953,7 +953,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
>                 list_del(entry);
>                 if (part_sort_add(dev, part) != 0) {
>                         device_del(dev);
> -                       return 1;
> +                       return -EINVAL;
>                 }
>         }
>
> @@ -966,7 +966,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
>  /**
>   * Initialize global device list.
>   *
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  static int mtd_devices_init(void)
>  {
> @@ -1037,7 +1037,7 @@ static struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_
>   * @param ret_id output pointer to next char after parse completes (output)
>   * @param dev_type parsed device type (output)
>   * @param dev_num parsed device number (output)
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type,
>                  u8 *dev_num)
> @@ -1059,12 +1059,12 @@ int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type,
>                 p += 8;
>         } else {
>                 printf("incorrect device type in %s\n", id);
> -               return 1;
> +               return -EINVAL;
>         }
>
>         if (!isdigit(*p)) {
>                 printf("incorrect device number in %s\n", id);
> -               return 1;
> +               return -EINVAL;
>         }
>
>         *dev_num = simple_strtoul(p, (char **)&p, 0);
> @@ -1079,7 +1079,7 @@ int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type,
>   *
>   * @param buf output buffer holding generated mtdparts string (output)
>   * @param buflen buffer size
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  static int generate_mtdparts(char *buf, u32 buflen)
>  {
> @@ -1195,7 +1195,7 @@ static int generate_mtdparts(char *buf, u32 buflen)
>
>  cleanup:
>         last_parts[0] = '\0';
> -       return 1;
> +       return -EINVAL;
>  }
>
>  /**
> @@ -1204,7 +1204,7 @@ cleanup:
>   *
>   * @param buf output buffer holding generated mtdparts string (output)
>   * @param buflen buffer size
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  static int generate_mtdparts_save(char *buf, u32 buflen)
>  {
> @@ -1342,7 +1342,7 @@ static void list_partitions(void)
>   * @param dev pointer to the requested device (output)
>   * @param part_num verified partition number (output)
>   * @param part pointer to requested partition (output)
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  int find_dev_and_part(const char *id, struct mtd_device **dev,
>                 u8 *part_num, struct part_info **part)
> @@ -1370,27 +1370,27 @@ int find_dev_and_part(const char *id, struct mtd_device **dev,
>         *part_num = 0;
>
>         if (mtd_id_parse(p, &p, &type, &dnum) != 0)
> -               return 1;
> +               return -EINVAL;
>
>         if ((*p++ != ',') || (*p == '\0')) {
>                 printf("no partition number specified\n");
> -               return 1;
> +               return -EINVAL;
>         }
>         pnum = simple_strtoul(p, (char **)&p, 0);
>         if (*p != '\0') {
>                 printf("unexpected trailing character '%c'\n", *p);
> -               return 1;
> +               return -EINVAL;
>         }
>
>         if ((*dev = device_find(type, dnum)) == NULL) {
>                 printf("no such device %s%d\n", MTD_DEV_TYPE(type), dnum);
> -               return 1;
> +               return -ENODEV;
>         }
>
>         if ((*part = mtd_part_info(*dev, pnum)) == NULL) {
>                 printf("no such partition\n");
>                 *dev = NULL;
> -               return 1;
> +               return -EINVAL;
>         }
>
>         *part_num = pnum;
> @@ -1402,7 +1402,7 @@ int find_dev_and_part(const char *id, struct mtd_device **dev,
>   * Find and delete partition. For partition id format see find_dev_and_part().
>   *
>   * @param id string describing device and partition
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  static int delete_partition(const char *id)
>  {
> @@ -1417,17 +1417,17 @@ static int delete_partition(const char *id)
>                                 part->name, part->size, part->offset);
>
>                 if (part_del(dev, part) != 0)
> -                       return 1;
> +                       return -EINVAL;
>
>                 if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
>                         printf("generated mtdparts too long, resetting to null\n");
> -                       return 1;
> +                       return -EINVAL;
>                 }
>                 return 0;
>         }
>
>         printf("partition %s not found\n", id);
> -       return 1;
> +       return -ENOENT;
>  }
>
>  #if defined(CONFIG_CMD_MTDPARTS_SPREAD)
> @@ -1478,7 +1478,7 @@ static void spread_partition(struct mtd_info *mtd, struct part_info *part,
>   * as big as their mtdparts environment variable sizes and they each start
>   * on a good block.
>   *
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  static int spread_partitions(void)
>  {
> @@ -1493,7 +1493,7 @@ static int spread_partitions(void)
>                 dev = list_entry(dentry, struct mtd_device, link);
>
>                 if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
> -                       return 1;
> +                       return -EINVAL;
>
>                 part_num = 0;
>                 cur_offs = 0;
> @@ -1519,7 +1519,7 @@ static int spread_partitions(void)
>
>         if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
>                 printf("generated mtdparts too long, resetting to null\n");
> -               return 1;
> +               return -EINVAL;
>         }
>         return 0;
>  }
> @@ -1547,7 +1547,7 @@ static const char *env_get_mtdparts(char *buf)
>   * for each entry. Add created devices to the global devices list.
>   *
>   * @param mtdparts string specifing mtd partitions
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  static int parse_mtdparts(const char *const mtdparts)
>  {
> @@ -1605,7 +1605,7 @@ static int parse_mtdparts(const char *const mtdparts)
>   * to the global mtdids list.
>   *
>   * @param ids mapping string
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  static int parse_mtdids(const char *const ids)
>  {
> @@ -1646,7 +1646,7 @@ static int parse_mtdids(const char *const ids)
>
>                 /* check if requested device exists */
>                 if (mtd_device_validate(type, num, &size) != 0)
> -                       return 1;
> +                       return -EINVAL;
>
>                 /* locate <mtd-id> */
>                 mtd_id = p;
> @@ -1704,7 +1704,7 @@ static int parse_mtdids(const char *const ids)
>                         list_del(entry);
>                         free(id_tmp);
>                 }
> -               return 1;
> +               return -EINVAL;
>         }
>
>         return 0;
> @@ -1715,7 +1715,7 @@ static int parse_mtdids(const char *const ids)
>   * Parse and initialize global mtdids mapping and create global
>   * device/partition list.
>   *
> - * Return: 0 on success, 1 otherwise
> + * Return: 0 on success, -errno otherwise
>   */
>  int mtdparts_init(void)
>  {
> @@ -1768,12 +1768,12 @@ int mtdparts_init(void)
>                         env_set("mtdids", (char *)ids);
>                 } else {
>                         printf("mtdids not defined, no default present\n");
> -                       return 1;
> +                       return -ENXIO;
>                 }
>         }
>         if (strlen(ids) > MTDIDS_MAXLEN - 1) {
>                 printf("mtdids too long (> %d)\n", MTDIDS_MAXLEN);
> -               return 1;
> +               return -EINVAL;
>         }
>
>         /* use defaults when mtdparts variable is not defined
> @@ -1789,7 +1789,7 @@ int mtdparts_init(void)
>
>         if (parts && (strlen(parts) > MTDPARTS_MAXLEN - 1)) {
>                 printf("mtdparts too long (> %d)\n", MTDPARTS_MAXLEN);
> -               return 1;
> +               return -EINVAL;
>         }
>
>         /* check if we have already parsed those mtdids */
> @@ -1800,7 +1800,7 @@ int mtdparts_init(void)
>
>                 if (parse_mtdids(ids) != 0) {
>                         mtd_devices_init();
> -                       return 1;
> +                       return -EINVAL;
>                 }
>
>                 /* ok it's good, save new ids */
> @@ -1810,11 +1810,11 @@ int mtdparts_init(void)
>         /* parse partitions if either mtdparts or mtdids were updated */
>         if (parts && ((last_parts[0] == '\0') || ((strcmp(last_parts, parts) != 0)) || ids_changed)) {
>                 if (parse_mtdparts(parts) != 0)
> -                       return 1;
> +                       return -EINVAL;
>
>                 if (list_empty(&devices)) {
>                         printf("mtdparts_init: no valid partitions\n");
> -                       return 1;
> +                       return -ENXIO;
>                 }
>
>                 /* ok it's good, save new parts */
> @@ -1923,15 +1923,15 @@ static int do_chpart(struct cmd_tbl *cmdtp, int flag, int argc,
>         u8 pnum;
>
>         if (mtdparts_init() !=0)
> -               return 1;
> +               return CMD_RET_FAILURE;
>
>         if (argc < 2) {
>                 printf("no partition id specified\n");
> -               return 1;
> +               return CMD_RET_FAILURE;
>         }
>
>         if (find_dev_and_part(argv[1], &dev, &pnum, &part) != 0)
> -               return 1;
> +               return CMD_RET_FAILURE;
>
>         current_mtd_dev = dev;
>         current_mtd_partnum = pnum;
> @@ -1978,7 +1978,7 @@ static int do_mtdparts(struct cmd_tbl *cmdtp, int flag, int argc,
>
>         /* make sure we are in sync with env variables */
>         if (mtdparts_init() != 0)
> -               return 1;
> +               return CMD_RET_FAILURE;
>
>         if (argc == 1) {
>                 list_partitions();
> @@ -2000,11 +2000,11 @@ static int do_mtdparts(struct cmd_tbl *cmdtp, int flag, int argc,
>                 struct part_info *p;
>
>                 if (mtd_id_parse(argv[2], NULL, &type, &num) != 0)
> -                       return 1;
> +                       return CMD_RET_FAILURE;
>
>                 if ((id = id_find(type, num)) == NULL) {
>                         printf("no such device %s defined in mtdids variable\n", argv[2]);
> -                       return 1;
> +                       return CMD_RET_FAILURE;
>                 }
>
>                 len = strlen(id->mtd_id) + 1;   /* 'mtd_id:' */
> @@ -2015,14 +2015,14 @@ static int do_mtdparts(struct cmd_tbl *cmdtp, int flag, int argc,
>
>                 if (len >= PART_ADD_DESC_MAXLEN) {
>                         printf("too long partition description\n");
> -                       return 1;
> +                       return CMD_RET_FAILURE;
>                 }
>                 sprintf(tmpbuf, "%s:%s(%s)%s",
>                                 id->mtd_id, argv[3], argv[4], argv[5] ? argv[5] : "");
>                 debug("add tmpbuf: %s\n", tmpbuf);
>
>                 if ((device_parse(tmpbuf, NULL, &dev) != 0) || (!dev))
> -                       return 1;
> +                       return -EINVAL;
>
>                 debug("+ %s\t%d\t%s\n", MTD_DEV_TYPE(dev->id->type),
>                                 dev->id->num, dev->id->mtd_id);
> @@ -2031,7 +2031,7 @@ static int do_mtdparts(struct cmd_tbl *cmdtp, int flag, int argc,
>
>  #if defined(CONFIG_CMD_MTDPARTS_SPREAD)
>                 if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
> -                       return 1;
> +                       return CMD_RET_FAILURE;
>
>                 if (!strcmp(&argv[1][3], ".spread")) {
>                         spread_partition(mtd, p, &next_offset);
> @@ -2045,12 +2045,12 @@ static int do_mtdparts(struct cmd_tbl *cmdtp, int flag, int argc,
>                 } else if (part_add(dev_tmp, p) != 0) {
>                         /* merge new partition with existing ones*/
>                         device_del(dev);
> -                       return 1;
> +                       return CMD_RET_FAILURE;
>                 }
>
>                 if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
>                         printf("generated mtdparts too long, resetting to null\n");
> -                       return 1;
> +                       return CMD_RET_FAILURE;
>                 }
>
>                 return 0;
> --
> 2.30.1
>

Reviewed-by: Michael Trimarchi <michael@amarulasolutions.com>

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2024-01-03  8:25 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-12-28 15:39 [PATCH v1 00/12] Support SPI NAND in fastboot protocol Alexey Romanov
2023-12-28 15:39 ` [PATCH v1 01/12] nand: move NAND initialization API to nand/core.c Alexey Romanov
2023-12-28 16:51   ` Sean Anderson
2023-12-28 15:39 ` [PATCH v1 02/12] nand: don't overwrite mtd name in nand_register() Alexey Romanov
2023-12-28 15:39 ` [PATCH v1 03/12] nand: move nand_util.c to NAND core folder Alexey Romanov
2023-12-28 15:39 ` [PATCH v1 04/12] nand: move nand_erase_opts() to core NAND folder Alexey Romanov
2024-01-03  8:21   ` Michael Nazzareno Trimarchi
2023-12-28 15:39 ` [PATCH v1 05/12] spi: add board_nand_init() function Alexey Romanov
2023-12-28 15:39 ` [PATCH v1 06/12] spi: use nand_register() instead of add_mtd_device() Alexey Romanov
2023-12-28 15:39 ` [PATCH v1 07/12] mtdparts: use negative error codes Alexey Romanov
2024-01-03  8:24   ` Michael Nazzareno Trimarchi
2023-12-28 15:39 ` [PATCH v1 08/12] jffs2: " Alexey Romanov
2023-12-28 15:39 ` [PATCH v1 09/12] cmd: allow to enable CMD_NAND for SPI NAND devices Alexey Romanov
2023-12-28 16:55   ` Sean Anderson
2023-12-28 15:39 ` [PATCH v1 10/12] fastboot: check device type for SPI NAND too Alexey Romanov
2023-12-28 16:54   ` Sean Anderson
2024-01-02 13:00   ` Mattijs Korpershoek
2023-12-28 15:39 ` [PATCH v1 11/12] fastboot: enable FASTBOOT_FLASH option for SPI NAND devices Alexey Romanov
2023-12-28 16:55   ` Sean Anderson
2024-01-02 13:00   ` Mattijs Korpershoek
2023-12-28 15:39 ` [PATCH v1 12/12] fastboot: fb_nand: add missing newlines in pr_err() macro Alexey Romanov
2023-12-28 16:54   ` Sean Anderson
2024-01-02 13:01   ` Mattijs Korpershoek

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.