[PATCH 0/5] Another smaller update to the nand stack

Update the stack to move it slowly to linux with some improvements. We want to support more samsung variant and clean up a bit the code. This will be the last upstream changes for now until a quick review of spl code will be done to reduce duplication. I decided to move the imx8mn_bsh_smm_s2 board to use the full nand detect because onfi can easily fail on no-onfi, no-jedec nand. I take care to move the mt7621 to use nand_detect and ask gently to test it again
Series successfully tested on imx8mn bsh smm s2 with NAND: - Macronix MX30LF4G18AC 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
Michael Trimarchi (5): mtd: nand: Rename the nand_manufacturers struct mtd: nand: change return type of nand_get_flash_type() to int mtd: nand: Rename nand_get_flash_type() into nand_detect() mtd: nand: samsung: Retrieve ECC requirements from extended configs: imx8mn_bsh_smm_s2: Use nand_base ident for nand identification
configs/imx8mn_bsh_smm_s2_defconfig | 2 ++ drivers/mtd/nand/raw/mt7621_nand.c | 9 ++++--- drivers/mtd/nand/raw/mxs_nand_spl.c | 8 +++---- drivers/mtd/nand/raw/nand_base.c | 37 +++++++++++++---------------- drivers/mtd/nand/raw/nand_ids.c | 2 +- drivers/mtd/nand/raw/nand_samsung.c | 20 ++++++++++++++++ include/linux/mtd/rawnand.h | 13 +++++----- 7 files changed, 54 insertions(+), 37 deletions(-)

Upstream linux commit 8cfb9ab68f9070.
Drop the 's' at the end of nand_manufacturers since the struct is actually describing a single manufacturer, not a manufacturer table.
Signed-off-by: Michael Trimarchi michael@amarulasolutions.com --- drivers/mtd/nand/raw/nand_base.c | 4 ++-- drivers/mtd/nand/raw/nand_ids.c | 2 +- include/linux/mtd/rawnand.h | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 4b09a11288..9d8ccfda53 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -4261,7 +4261,7 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip, * Returns a nand_manufacturer_desc object if the manufacturer is defined * in the NAND manufacturers database, NULL otherwise. */ -static const struct nand_manufacturers *nand_get_manufacturer_desc(u8 id) +static const struct nand_manufacturer *nand_get_manufacturer_desc(u8 id) { int i;
@@ -4281,7 +4281,7 @@ struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip, int *maf_id, struct nand_flash_dev *type) { struct mtd_info *mtd = &chip->mtd; - const struct nand_manufacturers *manufacturer_desc; + const struct nand_manufacturer *manufacturer_desc; int busw, ret; u8 *id_data = chip->id.data;
diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c index 4dece1b206..d0cfacc69b 100644 --- a/drivers/mtd/nand/raw/nand_ids.c +++ b/drivers/mtd/nand/raw/nand_ids.c @@ -177,7 +177,7 @@ struct nand_flash_dev nand_flash_ids[] = { };
/* Manufacturer IDs */ -struct nand_manufacturers nand_manuf_ids[] = { +struct nand_manufacturer nand_manuf_ids[] = { {NAND_MFR_TOSHIBA, "Toshiba", &toshiba_nand_manuf_ops}, {NAND_MFR_SAMSUNG, "Samsung", &samsung_nand_manuf_ops}, {NAND_MFR_FUJITSU, "Fujitsu"}, diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index aa45558b3d..8dc2d81dba 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -976,7 +976,7 @@ struct nand_chip { void *priv;
struct { - const struct nand_manufacturers *desc; + const struct nand_manufacturer *desc; void *priv; } manufacturer; }; @@ -1124,19 +1124,19 @@ struct nand_flash_dev { };
/** - * struct nand_manufacturers - NAND Flash Manufacturer ID Structure + * struct nand_manufacturer - NAND Flash Manufacturer ID Structure * @name: Manufacturer name * @id: manufacturer ID code of device. * @ops: manufacturer operations */ -struct nand_manufacturers { +struct nand_manufacturer { int id; char *name; const struct nand_manufacturer_ops *ops; };
extern struct nand_flash_dev nand_flash_ids[]; -extern struct nand_manufacturers nand_manuf_ids[]; +extern struct nand_manufacturer nand_manuf_ids[];
extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops; extern const struct nand_manufacturer_ops samsung_nand_manuf_ops;

Upstream linux commit 4722c0e958e636.
The returned "type" is never used in nand_scan_ident() and spl code
Make nand_get_flash_type() simply return an integer value in order to avoid unnecessary ERR_PTR/PTR_ERR dance.
Signed-off-by: Michael Trimarchi michael@amarulasolutions.com --- drivers/mtd/nand/raw/mt7621_nand.c | 10 +++++----- drivers/mtd/nand/raw/mxs_nand_spl.c | 8 ++++---- drivers/mtd/nand/raw/nand_base.c | 28 +++++++++++++--------------- include/linux/mtd/rawnand.h | 5 ++--- 4 files changed, 24 insertions(+), 27 deletions(-)
diff --git a/drivers/mtd/nand/raw/mt7621_nand.c b/drivers/mtd/nand/raw/mt7621_nand.c index 9763ae6dc5..a4a0bce35d 100644 --- a/drivers/mtd/nand/raw/mt7621_nand.c +++ b/drivers/mtd/nand/raw/mt7621_nand.c @@ -1184,13 +1184,13 @@ int mt7621_nfc_spl_post_init(struct mt7621_nfc *nfc) { struct nand_chip *nand = &nfc->nand; int nand_maf_id, nand_dev_id; - struct nand_flash_dev *type; + int ret;
- type = nand_get_flash_type(nand, &nand_maf_id, - &nand_dev_id, NULL); + ret = nand_get_flash_type(nand, &nand_maf_id, + &nand_dev_id, NULL);
- if (IS_ERR(type)) - return PTR_ERR(type); + if (ret) + return ret;
nand->numchips = 1; nand->mtd.size = nand->chipsize; diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c b/drivers/mtd/nand/raw/mxs_nand_spl.c index 3daacbb330..773d375fc2 100644 --- a/drivers/mtd/nand/raw/mxs_nand_spl.c +++ b/drivers/mtd/nand/raw/mxs_nand_spl.c @@ -81,13 +81,13 @@ static int mxs_flash_full_ident(struct mtd_info *mtd) { int nand_maf_id, nand_dev_id; struct nand_chip *chip = mtd_to_nand(mtd); - struct nand_flash_dev *type; + int ret;
- type = nand_get_flash_type(mtd, chip, &nand_maf_id, &nand_dev_id, NULL); + ret = nand_get_flash_type(mtd, chip, &nand_maf_id, &nand_dev_id, NULL);
- if (IS_ERR(type)) { + if (ret) { chip->select_chip(mtd, -1); - return PTR_ERR(type); + return ret; }
return 0; diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 9d8ccfda53..b4fa618dc4 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -4276,9 +4276,8 @@ static const struct nand_manufacturer *nand_get_manufacturer_desc(u8 id) /* * Get the flash and manufacturer id and lookup if the type is supported. */ -struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip, int *maf_id, - int *dev_id, - struct nand_flash_dev *type) +int nand_get_flash_type(struct nand_chip *chip, int *maf_id, + int *dev_id, struct nand_flash_dev *type) { struct mtd_info *mtd = &chip->mtd; const struct nand_manufacturer *manufacturer_desc; @@ -4291,7 +4290,7 @@ struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip, int *maf_id, */ ret = nand_reset(chip, 0); if (ret) - return ERR_PTR(ret); + return ret;
/* Select the device */ chip->select_chip(mtd, 0); @@ -4299,7 +4298,7 @@ struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip, int *maf_id, /* Send the command for reading device ID */ ret = nand_readid_op(chip, 0, id_data, 2); if (ret) - return ERR_PTR(ret); + return ret;
/* Read manufacturer and device IDs */ *maf_id = id_data[0]; @@ -4315,12 +4314,12 @@ struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip, int *maf_id, /* Read entire ID string */ ret = nand_readid_op(chip, 0, id_data, 8); if (ret) - return ERR_PTR(ret); + return ret;
if (id_data[0] != *maf_id || id_data[1] != *dev_id) { pr_info("second ID read did not match %02x,%02x against %02x,%02x\n", *maf_id, *dev_id, id_data[0], id_data[1]); - return ERR_PTR(-ENODEV); + return -ENODEV; }
chip->id.len = nand_id_len(id_data, ARRAY_SIZE(chip->id.data)); @@ -4368,7 +4367,7 @@ struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip, int *maf_id, }
if (!type->name) - return ERR_PTR(-ENODEV); + return -ENODEV;
if (!mtd->name) mtd->name = type->name; @@ -4401,7 +4400,7 @@ ident_done: pr_warn("bus width %d instead %d bit\n", (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, busw ? 16 : 8); - return ERR_PTR(-EINVAL); + return -EINVAL; }
nand_decode_bbm_options(mtd, chip); @@ -4432,7 +4431,7 @@ ident_done:
ret = nand_manufacturer_init(chip); if (ret) - return ERR_PTR(ret); + return ret;
pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", *maf_id, *dev_id); @@ -4460,7 +4459,7 @@ ident_done: pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n", (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", mtd->erasesize >> 10, mtd->writesize, mtd->oobsize); - return type; + return 0; } EXPORT_SYMBOL(nand_get_flash_type);
@@ -4547,7 +4546,6 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, { int i, nand_maf_id, nand_dev_id; struct nand_chip *chip = mtd_to_nand(mtd); - struct nand_flash_dev *type; int ret;
if (ofnode_valid(chip->flash_node)) { @@ -4560,14 +4558,14 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);
/* Read the flash type */ - type = nand_get_flash_type(chip, &nand_maf_id, + ret = nand_get_flash_type(chip, &nand_maf_id, &nand_dev_id, table);
- if (IS_ERR(type)) { + if (ret) { if (!(chip->options & NAND_SCAN_SILENT_NODEV)) pr_warn("No NAND device found\n"); chip->select_chip(mtd, -1); - return PTR_ERR(type); + return ret; }
/* Initialize the ->data_interface field. */ diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 8dc2d81dba..8178f36b49 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -29,9 +29,8 @@ struct nand_flash_dev; struct device_node;
/* Get the flash and manufacturer id and lookup if the type is supported. */ -struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip, - int *maf_id, int *dev_id, - struct nand_flash_dev *type); +int nand_get_flash_type(struct nand_chip *chip, int *maf_id, int *dev_id, + struct nand_flash_dev *type);
/* Scan and identify a NAND device */ int nand_scan(struct mtd_info *mtd, int max_chips);

Upstream linux commit 7bb427990ee364.
Rename the function to match this new behavior.
NOTE: fix nand_detect/nand_get_flash_type parameters in mxs_nand_spl. This code seems never executed by any board as alternative for nand detect
Signed-off-by: Michael Trimarchi michael@amarulasolutions.com --- drivers/mtd/nand/raw/mt7621_nand.c | 3 +-- drivers/mtd/nand/raw/mxs_nand_spl.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 11 +++++------ include/linux/mtd/rawnand.h | 4 ++-- 4 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/drivers/mtd/nand/raw/mt7621_nand.c b/drivers/mtd/nand/raw/mt7621_nand.c index a4a0bce35d..f6eddb84a9 100644 --- a/drivers/mtd/nand/raw/mt7621_nand.c +++ b/drivers/mtd/nand/raw/mt7621_nand.c @@ -1186,8 +1186,7 @@ int mt7621_nfc_spl_post_init(struct mt7621_nfc *nfc) int nand_maf_id, nand_dev_id; int ret;
- ret = nand_get_flash_type(nand, &nand_maf_id, - &nand_dev_id, NULL); + ret = nand_detect(nand, &nand_maf_id, &nand_dev_id, NULL);
if (ret) return ret; diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c b/drivers/mtd/nand/raw/mxs_nand_spl.c index 773d375fc2..ef03b7789d 100644 --- a/drivers/mtd/nand/raw/mxs_nand_spl.c +++ b/drivers/mtd/nand/raw/mxs_nand_spl.c @@ -83,7 +83,7 @@ static int mxs_flash_full_ident(struct mtd_info *mtd) struct nand_chip *chip = mtd_to_nand(mtd); int ret;
- ret = nand_get_flash_type(mtd, chip, &nand_maf_id, &nand_dev_id, NULL); + ret = nand_detect(chip, &nand_maf_id, &nand_dev_id, NULL);
if (ret) { chip->select_chip(mtd, -1); diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index b4fa618dc4..1a1a757932 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -4276,8 +4276,8 @@ static const struct nand_manufacturer *nand_get_manufacturer_desc(u8 id) /* * Get the flash and manufacturer id and lookup if the type is supported. */ -int nand_get_flash_type(struct nand_chip *chip, int *maf_id, - int *dev_id, struct nand_flash_dev *type) +int nand_detect(struct nand_chip *chip, int *maf_id, + int *dev_id, struct nand_flash_dev *type) { struct mtd_info *mtd = &chip->mtd; const struct nand_manufacturer *manufacturer_desc; @@ -4461,7 +4461,7 @@ ident_done: mtd->erasesize >> 10, mtd->writesize, mtd->oobsize); return 0; } -EXPORT_SYMBOL(nand_get_flash_type); +EXPORT_SYMBOL(nand_detect);
#if CONFIG_IS_ENABLED(OF_CONTROL)
@@ -4558,8 +4558,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);
/* Read the flash type */ - ret = nand_get_flash_type(chip, &nand_maf_id, - &nand_dev_id, table); + ret = nand_detect(chip, &nand_maf_id, &nand_dev_id, table);
if (ret) { if (!(chip->options & NAND_SCAN_SILENT_NODEV)) @@ -4591,7 +4590,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, for (i = 1; i < maxchips; i++) { u8 id[2];
- /* See comment in nand_get_flash_type for reset */ + /* See comment in nand_detect for reset */ nand_reset(chip, i);
chip->select_chip(mtd, i); diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 8178f36b49..fb002ae641 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -29,8 +29,8 @@ struct nand_flash_dev; struct device_node;
/* Get the flash and manufacturer id and lookup if the type is supported. */ -int nand_get_flash_type(struct nand_chip *chip, int *maf_id, int *dev_id, - struct nand_flash_dev *type); +int nand_detect(struct nand_chip *chip, int *maf_id, int *dev_id, + struct nand_flash_dev *type);
/* Scan and identify a NAND device */ int nand_scan(struct mtd_info *mtd, int max_chips);

Upstream linux commit 8fc82d456e40a0.
On some nand controllers with hw-ecc the controller code wants to know the ecc strength and size and having these as 0, 0 is not accepted.
Specifying these in devicetree is possible but undesirable as the nand may be different in different production runs of the same board, so it is better to get this info from the nand id where possible.
This commit adds code to read the ecc strength and size from the nand for Samsung extended-id nands. This code is based on the info for the 5th id byte in the datasheets for the following Samsung nands: K9GAG08U0E, K9GAG08U0F, K9GAG08X0D, K9GBG08U0A, K9GBG08U0B. These all use these bits in the exact same way.
Signed-off-by: Michael Trimarchi michael@amarulasolutions.com --- drivers/mtd/nand/raw/nand_samsung.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c index 0ab8062193..36ef48e5ec 100644 --- a/drivers/mtd/nand/raw/nand_samsung.c +++ b/drivers/mtd/nand/raw/nand_samsung.c @@ -64,6 +64,26 @@ static void samsung_nand_decode_id(struct nand_chip *chip) extid >>= 2; mtd->erasesize = (128 * 1024) << (((extid >> 1) & 0x04) | (extid & 0x03)); + + /* Extract ECC requirements from 5th id byte*/ + extid = (chip->id.data[4] >> 4) & 0x07; + if (extid < 5) { + chip->ecc_step_ds = 512; + chip->ecc_strength_ds = 1 << extid; + } else { + chip->ecc_step_ds = 1024; + switch (extid) { + case 5: + chip->ecc_strength_ds = 24; + break; + case 6: + chip->ecc_strength_ds = 40; + break; + case 7: + chip->ecc_strength_ds = 60; + break; + } + } } else { nand_decode_ext_id(chip); }

The board can mount different nand brand type. Try to use the full scan detection and not the onfi one
Signed-off-by: Michael Trimarchi michael@amarulasolutions.com --- configs/imx8mn_bsh_smm_s2_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/imx8mn_bsh_smm_s2_defconfig b/configs/imx8mn_bsh_smm_s2_defconfig index 79995591f2..139cf0392b 100644 --- a/configs/imx8mn_bsh_smm_s2_defconfig +++ b/configs/imx8mn_bsh_smm_s2_defconfig @@ -44,6 +44,8 @@ CONFIG_SPL_DMA=y CONFIG_SPL_I2C=y CONFIG_SPL_MTD_SUPPORT=y CONFIG_SPL_NAND_SUPPORT=y +CONFIG_SPL_NAND_BASE=y +CONFIG_SPL_NAND_IDENT=y CONFIG_SPL_POWER=y CONFIG_SPL_WATCHDOG=y CONFIG_SYS_PROMPT="> "

On Thu, Jul 28, 2022 at 7:17 PM Michael Trimarchi michael@amarulasolutions.com wrote:
Update the stack to move it slowly to linux with some improvements. We want to support more samsung variant and clean up a bit the code. This will be the last upstream changes for now until a quick review of spl code will be done to reduce duplication. I decided to move the imx8mn_bsh_smm_s2 board to use the full nand detect because onfi can easily fail on no-onfi, no-jedec nand. I take care to move the mt7621 to use nand_detect and ask gently to test it again
Series successfully tested on imx8mn bsh smm s2 with NAND: - Macronix MX30LF4G18AC 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
Michael Trimarchi (5): mtd: nand: Rename the nand_manufacturers struct mtd: nand: change return type of nand_get_flash_type() to int mtd: nand: Rename nand_get_flash_type() into nand_detect() mtd: nand: samsung: Retrieve ECC requirements from extended configs: imx8mn_bsh_smm_s2: Use nand_base ident for nand identification
configs/imx8mn_bsh_smm_s2_defconfig | 2 ++ drivers/mtd/nand/raw/mt7621_nand.c | 9 ++++--- drivers/mtd/nand/raw/mxs_nand_spl.c | 8 +++---- drivers/mtd/nand/raw/nand_base.c | 37 +++++++++++++---------------- drivers/mtd/nand/raw/nand_ids.c | 2 +- drivers/mtd/nand/raw/nand_samsung.c | 20 ++++++++++++++++ include/linux/mtd/rawnand.h | 13 +++++----- 7 files changed, 54 insertions(+), 37 deletions(-)
-- 2.34.1
Applied thanks
participants (2)
-
Michael Nazzareno Trimarchi
-
Michael Trimarchi