All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 00/13] Port manufacturer specific initialization
@ 2022-07-19 20:21 Michael Trimarchi
  2022-07-19 20:21 ` [PATCH V2 01/13] mtd: nand: Get rid of busw parameter Michael Trimarchi
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: Michael Trimarchi @ 2022-07-19 20:21 UTC (permalink / raw)
  To: u-boot
  Cc: Dario Binacchi, Tommaso Merciai, Kory Maincent, Marek Behún,
	Miquel Raynal, Pali Rohár, Patrice Chotard, Priyanka Jain,
	Simon Glass, Wolfgang Denk, Zhengxun Li

In preparation of re-sync of mtd stack, we opt to move the current stack
slowly in order to have a more easy sync and test. We would like to
prepare uboot to support no-jedec and no-onfi compliant nand so we need
to clean up a bit the code we have now and upstream some of the support.
In this series we expect no functional change

Tested on:
        - imx6ull Micron MT29F2G08ABAGAH4

Michael Trimarchi (13):
  mtd: nand: Get rid of busw parameter
  mtd: nand: Store nand ID in struct nand_chip
  mtd: nand: Add manufacturer specific initialization/detection steps
  mtd: nand: Get rid of mtd variable in function calls
  mtd: nand: Export symbol nand_decode_ext_id
  mtd: nand: Move Samsung specific init/detection logic in
    nand_samsung.c
  mtd: nand: Move Hynix specific init/detection logic in nand_hynix.c
  mtd: nand: Move Toshiba specific init/detection logic in
    nand_toshiba.c
  mtd: nand: Move Micron specific init logic in nand_micron.c
  mtd: nand: Move AMD/Spansion specific init/detection logic in
    nand_amd.c
  mtd: nand: Move Macronix specific initialization in nand_macronix.c
  mtd: nand: toshiba: Retrieve ECC requirements from extended ID
  mtd: decommission the NAND museum

 drivers/mtd/nand/raw/Makefile        |  10 +-
 drivers/mtd/nand/raw/nand_amd.c      |  51 ++++
 drivers/mtd/nand/raw/nand_base.c     | 359 ++++++++++-----------------
 drivers/mtd/nand/raw/nand_hynix.c    |  84 +++++++
 drivers/mtd/nand/raw/nand_ids.c      |  24 +-
 drivers/mtd/nand/raw/nand_macronix.c |  30 +++
 drivers/mtd/nand/raw/nand_micron.c   |  86 +++++++
 drivers/mtd/nand/raw/nand_samsung.c  |  89 +++++++
 drivers/mtd/nand/raw/nand_toshiba.c  |  78 ++++++
 include/linux/mtd/rawnand.h          |  78 ++++--
 10 files changed, 615 insertions(+), 274 deletions(-)
 create mode 100644 drivers/mtd/nand/raw/nand_amd.c
 create mode 100644 drivers/mtd/nand/raw/nand_hynix.c
 create mode 100644 drivers/mtd/nand/raw/nand_macronix.c
 create mode 100644 drivers/mtd/nand/raw/nand_micron.c
 create mode 100644 drivers/mtd/nand/raw/nand_samsung.c
 create mode 100644 drivers/mtd/nand/raw/nand_toshiba.c

-- 
2.34.1


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

* [PATCH V2 01/13] mtd: nand: Get rid of busw parameter
  2022-07-19 20:21 [PATCH V2 00/13] Port manufacturer specific initialization Michael Trimarchi
@ 2022-07-19 20:21 ` Michael Trimarchi
  2022-07-19 20:21 ` [PATCH V2 02/13] mtd: nand: Store nand ID in struct nand_chip Michael Trimarchi
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Michael Trimarchi @ 2022-07-19 20:21 UTC (permalink / raw)
  To: u-boot
  Cc: Dario Binacchi, Tommaso Merciai, Patrice Chotard, Wolfgang Denk,
	Marek Behún, Simon Glass, Kory Maincent, Pali Rohár

Upstream linux commit 29a198a159

Auto-detection functions are passed a busw parameter to retrieve the actual
NAND bus width and eventually set the correct value in chip->options.
Rework the nand_get_flash_type() function to get rid of this extra
parameter and let detection code directly set the NAND_BUSWIDTH_16 flag in
chip->options if needed.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- use short-commit form
	- remove linux info. Uboot seems that backport without add this
	  extra information
---
 drivers/mtd/nand/raw/nand_base.c | 59 +++++++++++++++++---------------
 1 file changed, 32 insertions(+), 27 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index e8ece0a4a0..9a2194ebd3 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -3898,8 +3898,7 @@ static void nand_onfi_detect_micron(struct nand_chip *chip,
 /*
  * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
  */
-static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
-					int *busw)
+static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip)
 {
 	struct nand_onfi_params *p = &chip->onfi_params;
 	char id[4];
@@ -3971,9 +3970,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 	chip->bits_per_cell = p->bits_per_cell;
 
 	if (onfi_feature(chip) & ONFI_FEATURE_16_BIT_BUS)
-		*busw = NAND_BUSWIDTH_16;
-	else
-		*busw = 0;
+		chip->options |= NAND_BUSWIDTH_16;
 
 	if (p->ecc_bits != 0xff) {
 		chip->ecc_strength_ds = p->ecc_bits;
@@ -4003,8 +4000,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 	return 1;
 }
 #else
-static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
-					int *busw)
+static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip)
 {
 	return 0;
 }
@@ -4013,8 +4009,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 /*
  * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise.
  */
-static int nand_flash_detect_jedec(struct mtd_info *mtd, struct nand_chip *chip,
-					int *busw)
+static int nand_flash_detect_jedec(struct mtd_info *mtd, struct nand_chip *chip)
 {
 	struct nand_jedec_params *p = &chip->jedec_params;
 	struct jedec_ecc_info *ecc;
@@ -4076,9 +4071,7 @@ static int nand_flash_detect_jedec(struct mtd_info *mtd, struct nand_chip *chip,
 	chip->bits_per_cell = p->bits_per_cell;
 
 	if (jedec_feature(chip) & JEDEC_FEATURE_16_BIT_BUS)
-		*busw = NAND_BUSWIDTH_16;
-	else
-		*busw = 0;
+		chip->options |= NAND_BUSWIDTH_16;
 
 	/* ECC info */
 	ecc = &p->ecc_info[0];
@@ -4168,7 +4161,7 @@ static int nand_get_bits_per_cell(u8 cellinfo)
  * manufacturer-specific "extended ID" decoding patterns.
  */
 static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
-				u8 id_data[8], int *busw)
+				u8 id_data[8])
 {
 	int extid, id_len;
 	/* The 3rd id byte holds MLC / multichip data */
@@ -4221,7 +4214,6 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
 		/* Calc blocksize */
 		mtd->erasesize = (128 * 1024) <<
 			(((extid >> 1) & 0x04) | (extid & 0x03));
-		*busw = 0;
 	} else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX &&
 			!nand_is_slc(chip)) {
 		unsigned int tmp;
@@ -4262,7 +4254,6 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
 			mtd->erasesize = 768 * 1024;
 		else
 			mtd->erasesize = (64 * 1024) << tmp;
-		*busw = 0;
 	} else {
 		/* Calc pagesize */
 		mtd->writesize = 1024 << (extid & 0x03);
@@ -4275,7 +4266,9 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
 		mtd->erasesize = (64 * 1024) << (extid & 0x03);
 		extid >>= 2;
 		/* Get buswidth information */
-		*busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
+		/* Get buswidth information */
+		if (extid & 0x1)
+			chip->options |= NAND_BUSWIDTH_16;
 
 		/*
 		 * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per
@@ -4301,15 +4294,13 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
  * the chip.
  */
 static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip,
-				struct nand_flash_dev *type, u8 id_data[8],
-				int *busw)
+				struct nand_flash_dev *type, u8 id_data[8])
 {
 	int maf_id = id_data[0];
 
 	mtd->erasesize = type->erasesize;
 	mtd->writesize = type->pagesize;
 	mtd->oobsize = mtd->writesize / 32;
-	*busw = type->options & NAND_BUSWIDTH_16;
 
 	/* All legacy ID NAND are small-page, SLC */
 	chip->bits_per_cell = 1;
@@ -4371,7 +4362,7 @@ static inline bool is_full_id_nand(struct nand_flash_dev *type)
 }
 
 static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
-		   struct nand_flash_dev *type, u8 *id_data, int *busw)
+		   struct nand_flash_dev *type, u8 *id_data)
 {
 	if (!strncmp((char *)type->id, (char *)id_data, type->id_len)) {
 		mtd->writesize = type->pagesize;
@@ -4386,8 +4377,6 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
 		chip->onfi_timing_mode_default =
 					type->onfi_timing_mode_default;
 
-		*busw = type->options & NAND_BUSWIDTH_16;
-
 		if (!mtd->name)
 			mtd->name = type->name;
 
@@ -4449,9 +4438,24 @@ struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	if (!type)
 		type = nand_flash_ids;
 
+	/*
+	 * Save the NAND_BUSWIDTH_16 flag before letting auto-detection logic
+	 * override it.
+	 * This is required to make sure initial NAND bus width set by the
+	 * NAND controller driver is coherent with the real NAND bus width
+	 * (extracted by auto-detection code).
+	 */
+	busw = chip->options & NAND_BUSWIDTH_16;
+
+	/*
+	 * The flag is only set (never cleared), reset it to its default value
+	 * before starting auto-detection.
+	 */
+	chip->options &= ~NAND_BUSWIDTH_16;
+
 	for (; type->name != NULL; type++) {
 		if (is_full_id_nand(type)) {
-			if (find_full_id_nand(mtd, chip, type, id_data, &busw))
+			if (find_full_id_nand(mtd, chip, type, id_data))
 				goto ident_done;
 		} else if (*dev_id == type->dev_id) {
 			break;
@@ -4461,11 +4465,11 @@ struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	chip->onfi_version = 0;
 	if (!type->name || !type->pagesize) {
 		/* Check if the chip is ONFI compliant */
-		if (nand_flash_detect_onfi(mtd, chip, &busw))
+		if (nand_flash_detect_onfi(mtd, chip))
 			goto ident_done;
 
 		/* Check if the chip is JEDEC compliant */
-		if (nand_flash_detect_jedec(mtd, chip, &busw))
+		if (nand_flash_detect_jedec(mtd, chip))
 			goto ident_done;
 	}
 
@@ -4479,10 +4483,11 @@ struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 
 	if (!type->pagesize) {
 		/* Decode parameters from extended ID */
-		nand_decode_ext_id(mtd, chip, id_data, &busw);
+		nand_decode_ext_id(mtd, chip, id_data);
 	} else {
-		nand_decode_id(mtd, chip, type, id_data, &busw);
+		nand_decode_id(mtd, chip, type, id_data);
 	}
+
 	/* Get chip options */
 	chip->options |= type->options;
 
-- 
2.34.1


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

* [PATCH V2 02/13] mtd: nand: Store nand ID in struct nand_chip
  2022-07-19 20:21 [PATCH V2 00/13] Port manufacturer specific initialization Michael Trimarchi
  2022-07-19 20:21 ` [PATCH V2 01/13] mtd: nand: Get rid of busw parameter Michael Trimarchi
@ 2022-07-19 20:21 ` Michael Trimarchi
  2022-07-19 20:21 ` [PATCH V2 03/13] mtd: nand: Add manufacturer specific initialization/detection steps Michael Trimarchi
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Michael Trimarchi @ 2022-07-19 20:21 UTC (permalink / raw)
  To: u-boot
  Cc: Dario Binacchi, Tommaso Merciai, Patrice Chotard, Wolfgang Denk,
	Pali Rohár, Priyanka Jain, Kory Maincent, Marek Behún,
	Simon Glass

Upstream linux commit 7f501f0a72

Store the NAND ID in struct nand_chip to avoid passing id_data and id_len
as function parameters.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- use short-commit form
	- remove linux info. Uboot seems that backport without add this
	  extra information
---
 drivers/mtd/nand/raw/nand_base.c | 54 ++++++++++++++++----------------
 include/linux/mtd/rawnand.h      | 15 +++++++++
 2 files changed, 42 insertions(+), 27 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 9a2194ebd3..4a78770a25 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4160,16 +4160,14 @@ static int nand_get_bits_per_cell(u8 cellinfo)
  * chip. The rest of the parameters must be decoded according to generic or
  * manufacturer-specific "extended ID" decoding patterns.
  */
-static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
-				u8 id_data[8])
+static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip)
 {
 	int extid, id_len;
 	/* The 3rd id byte holds MLC / multichip data */
-	chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
+	chip->bits_per_cell = nand_get_bits_per_cell(chip->id.data[2]);
 	/* The 4th id byte is the important one */
-	extid = id_data[3];
-
-	id_len = nand_id_len(id_data, 8);
+	extid = chip->id.data[3];
+	id_len = chip->id.len;
 
 	/*
 	 * Field definitions are in the following datasheets:
@@ -4180,8 +4178,8 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
 	 * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung
 	 * ID to decide what to do.
 	 */
-	if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG &&
-			!nand_is_slc(chip) && id_data[5] != 0x00) {
+	if (id_len == 6 && chip->id.data[0] == NAND_MFR_SAMSUNG &&
+			!nand_is_slc(chip) && chip->id.data[5] != 0x00) {
 		/* Calc pagesize */
 		mtd->writesize = 2048 << (extid & 0x03);
 		extid >>= 2;
@@ -4214,7 +4212,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
 		/* Calc blocksize */
 		mtd->erasesize = (128 * 1024) <<
 			(((extid >> 1) & 0x04) | (extid & 0x03));
-	} else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX &&
+	} else if (id_len == 6 && chip->id.data[0] == NAND_MFR_HYNIX &&
 			!nand_is_slc(chip)) {
 		unsigned int tmp;
 
@@ -4278,10 +4276,10 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
 		 *                         110b -> 24nm
 		 * - ID byte 5, bit[7]:    1 -> BENAND, 0 -> raw SLC
 		 */
-		if (id_len >= 6 && id_data[0] == NAND_MFR_TOSHIBA &&
+		if (id_len >= 6 && chip->id.data[0] == NAND_MFR_TOSHIBA &&
 				nand_is_slc(chip) &&
-				(id_data[5] & 0x7) == 0x6 /* 24nm */ &&
-				!(id_data[4] & 0x80) /* !BENAND */) {
+				(chip->id.data[5] & 0x7) == 0x6 /* 24nm */ &&
+				!(chip->id.data[4] & 0x80) /* !BENAND */) {
 			mtd->oobsize = 32 * mtd->writesize >> 9;
 		}
 
@@ -4294,9 +4292,9 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
  * the chip.
  */
 static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip,
-				struct nand_flash_dev *type, u8 id_data[8])
+				struct nand_flash_dev *type)
 {
-	int maf_id = id_data[0];
+	int maf_id = chip->id.data[0];
 
 	mtd->erasesize = type->erasesize;
 	mtd->writesize = type->pagesize;
@@ -4311,11 +4309,11 @@ static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip,
 	 * listed in nand_ids table.
 	 * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
 	 */
-	if (maf_id == NAND_MFR_AMD && id_data[4] != 0x00 && id_data[5] == 0x00
-			&& id_data[6] == 0x00 && id_data[7] == 0x00
+	if (maf_id == NAND_MFR_AMD && chip->id.data[4] != 0x00 && chip->id.data[5] == 0x00
+			&& chip->id.data[6] == 0x00 && chip->id.data[7] == 0x00
 			&& mtd->writesize == 512) {
 		mtd->erasesize = 128 * 1024;
-		mtd->erasesize <<= ((id_data[3] & 0x03) << 1);
+		mtd->erasesize <<= ((chip->id.data[3] & 0x03) << 1);
 	}
 }
 
@@ -4325,9 +4323,9 @@ static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip,
  * page size, cell-type information).
  */
 static void nand_decode_bbm_options(struct mtd_info *mtd,
-				    struct nand_chip *chip, u8 id_data[8])
+				    struct nand_chip *chip)
 {
-	int maf_id = id_data[0];
+	int maf_id = chip->id.data[0];
 
 	/* Set the bad block position */
 	if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16))
@@ -4362,14 +4360,14 @@ static inline bool is_full_id_nand(struct nand_flash_dev *type)
 }
 
 static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
-		   struct nand_flash_dev *type, u8 *id_data)
+		   struct nand_flash_dev *type)
 {
-	if (!strncmp((char *)type->id, (char *)id_data, type->id_len)) {
+	if (!strncmp((char *)type->id, (char *)chip->id.data, type->id_len)) {
 		mtd->writesize = type->pagesize;
 		mtd->erasesize = type->erasesize;
 		mtd->oobsize = type->oobsize;
 
-		chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
+		chip->bits_per_cell = nand_get_bits_per_cell(chip->id.data[2]);
 		chip->chipsize = (uint64_t)type->chipsize << 20;
 		chip->options |= type->options;
 		chip->ecc_strength_ds = NAND_ECC_STRENGTH(type);
@@ -4395,7 +4393,7 @@ struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 {
 	int busw, ret;
 	int maf_idx;
-	u8 id_data[8];
+	u8 *id_data = chip->id.data;
 
 	/*
 	 * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
@@ -4453,9 +4451,11 @@ struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	 */
 	chip->options &= ~NAND_BUSWIDTH_16;
 
+	chip->id.len = nand_id_len(id_data, ARRAY_SIZE(chip->id.data));
+
 	for (; type->name != NULL; type++) {
 		if (is_full_id_nand(type)) {
-			if (find_full_id_nand(mtd, chip, type, id_data))
+			if (find_full_id_nand(mtd, chip, type))
 				goto ident_done;
 		} else if (*dev_id == type->dev_id) {
 			break;
@@ -4483,9 +4483,9 @@ struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 
 	if (!type->pagesize) {
 		/* Decode parameters from extended ID */
-		nand_decode_ext_id(mtd, chip, id_data);
+		nand_decode_ext_id(mtd, chip);
 	} else {
-		nand_decode_id(mtd, chip, type, id_data);
+		nand_decode_id(mtd, chip, type);
 	}
 
 	/* Get chip options */
@@ -4523,7 +4523,7 @@ ident_done:
 		return ERR_PTR(-EINVAL);
 	}
 
-	nand_decode_bbm_options(mtd, chip, id_data);
+	nand_decode_bbm_options(mtd, chip);
 
 	/* Calculate the address shift from the page size */
 	chip->page_shift = ffs(mtd->writesize) - 1;
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 3417ca2a0d..f2c6a978cb 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -507,6 +507,19 @@ static inline void nand_hw_control_init(struct nand_hw_control *nfc)
 	init_waitqueue_head(&nfc->wq);
 }
 
+/* The maximum expected count of bytes in the NAND ID sequence */
+#define NAND_MAX_ID_LEN 8
+
+/**
+ * struct nand_id - NAND id structure
+ * @data: buffer containing the id bytes.
+ * @len: ID length.
+ */
+struct nand_id {
+	u8 data[NAND_MAX_ID_LEN];
+	int len;
+};
+
 /**
  * struct nand_ecc_step_info - ECC step information of ECC engine
  * @stepsize: data bytes per ECC step
@@ -888,6 +901,8 @@ nand_get_sdr_timings(const struct nand_data_interface *conf)
 
 struct nand_chip {
 	struct mtd_info mtd;
+	struct nand_id id;
+
 	void __iomem *IO_ADDR_R;
 	void __iomem *IO_ADDR_W;
 
-- 
2.34.1


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

* [PATCH V2 03/13] mtd: nand: Add manufacturer specific initialization/detection steps
  2022-07-19 20:21 [PATCH V2 00/13] Port manufacturer specific initialization Michael Trimarchi
  2022-07-19 20:21 ` [PATCH V2 01/13] mtd: nand: Get rid of busw parameter Michael Trimarchi
  2022-07-19 20:21 ` [PATCH V2 02/13] mtd: nand: Store nand ID in struct nand_chip Michael Trimarchi
@ 2022-07-19 20:21 ` Michael Trimarchi
  2022-07-19 20:21 ` [PATCH V2 04/13] mtd: nand: Get rid of mtd variable in function calls Michael Trimarchi
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Michael Trimarchi @ 2022-07-19 20:21 UTC (permalink / raw)
  To: u-boot
  Cc: Dario Binacchi, Tommaso Merciai, Patrice Chotard, Wolfgang Denk,
	Kory Maincent, Simon Glass, Marek Behún

Upstream linux commit abbe26d144

A lot of NANDs are implementing generic features in a non-generic way,
or are providing advanced auto-detection logic where the NAND ID bytes
meaning changes with the NAND generation.

Providing this vendor specific initialization step will allow us to get
rid of full-id entries in the nand_ids table or all the vendor specific
cases added over the time in the generic NAND ID decoding logic.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- use short-commit form
	- remove linux info. Uboot seems that backport without add this
	  extra information
---
 drivers/mtd/nand/raw/nand_base.c | 90 +++++++++++++++++++++++++-------
 include/linux/mtd/rawnand.h      | 30 +++++++++++
 2 files changed, 102 insertions(+), 18 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 4a78770a25..3b9c78cb24 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4286,6 +4286,39 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip)
 	}
 }
 
+/*
+ * Manufacturer detection. Only used when the NAND is not ONFI or JEDEC
+ * compliant and does not have a full-id or legacy-id entry in the nand_ids
+ * table.
+ */
+static void nand_manufacturer_detect(struct mtd_info *mtd, struct nand_chip *chip)
+{
+	/*
+	 * Try manufacturer detection if available and use
+	 * nand_decode_ext_id() otherwise.
+	 */
+	if (chip->manufacturer.desc && chip->manufacturer.desc->ops &&
+	    chip->manufacturer.desc->ops->detect)
+		chip->manufacturer.desc->ops->detect(chip);
+	else
+		nand_decode_ext_id(mtd, chip);
+}
+
+/*
+ * Manufacturer initialization. This function is called for all NANDs including
+ * ONFI and JEDEC compliant ones.
+ * Manufacturer drivers should put all their specific initialization code in
+ * their ->init() hook.
+ */
+static int nand_manufacturer_init(struct nand_chip *chip)
+{
+	if (!chip->manufacturer.desc || !chip->manufacturer.desc->ops ||
+	    !chip->manufacturer.desc->ops->init)
+		return 0;
+
+	return chip->manufacturer.desc->ops->init(chip);
+}
+
 /*
  * Old devices have chip data hardcoded in the device ID table. nand_decode_id
  * decodes a matching ID table entry and assigns the MTD size parameters for
@@ -4383,6 +4416,26 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
 	return false;
 }
 
+/**
+ * nand_get_manufacturer_desc - Get manufacturer information from the
+ *                              manufacturer ID
+ * @id: manufacturer ID
+ *
+ * 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)
+{
+	int i;
+
+	for (i = 0; nand_manuf_ids[i].id != 0x0; i++) {
+		if (nand_manuf_ids[i].id == id)
+			return &nand_manuf_ids[i];
+	}
+
+	return NULL;
+}
+
 /*
  * Get the flash and manufacturer id and lookup if the type is supported.
  */
@@ -4391,8 +4444,8 @@ struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 						  int *maf_id, int *dev_id,
 						  struct nand_flash_dev *type)
 {
+	const struct nand_manufacturers *manufacturer_desc;
 	int busw, ret;
-	int maf_idx;
 	u8 *id_data = chip->id.data;
 
 	/*
@@ -4433,6 +4486,12 @@ struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 		return ERR_PTR(-ENODEV);
 	}
 
+	chip->id.len = nand_id_len(id_data, ARRAY_SIZE(chip->id.data));
+
+	/* Try to identify manufacturer */
+	manufacturer_desc = nand_get_manufacturer_desc(*maf_id);
+	chip->manufacturer.desc = manufacturer_desc;
+
 	if (!type)
 		type = nand_flash_ids;
 
@@ -4451,8 +4510,6 @@ struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	 */
 	chip->options &= ~NAND_BUSWIDTH_16;
 
-	chip->id.len = nand_id_len(id_data, ARRAY_SIZE(chip->id.data));
-
 	for (; type->name != NULL; type++) {
 		if (is_full_id_nand(type)) {
 			if (find_full_id_nand(mtd, chip, type))
@@ -4482,8 +4539,7 @@ struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	chip->chipsize = (uint64_t)type->chipsize << 20;
 
 	if (!type->pagesize) {
-		/* Decode parameters from extended ID */
-		nand_decode_ext_id(mtd, chip);
+		nand_manufacturer_detect(mtd, chip);
 	} else {
 		nand_decode_id(mtd, chip, type);
 	}
@@ -4499,12 +4555,6 @@ struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 		chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
 ident_done:
 
-	/* Try to identify manufacturer */
-	for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) {
-		if (nand_manuf_ids[maf_idx].id == *maf_id)
-			break;
-	}
-
 	if (chip->options & NAND_BUSWIDTH_AUTO) {
 		WARN_ON(chip->options & NAND_BUSWIDTH_16);
 		chip->options |= busw;
@@ -4516,7 +4566,7 @@ ident_done:
 		 */
 		pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
 			*maf_id, *dev_id);
-		pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, mtd->name);
+		pr_info("%s %s\n", manufacturer_desc->name, mtd->name);
 		pr_warn("bus width %d instead %d bit\n",
 			   (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
 			   busw ? 16 : 8);
@@ -4549,28 +4599,32 @@ ident_done:
 	if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
 		chip->cmdfunc = nand_command_lp;
 
+	ret = nand_manufacturer_init(chip);
+	if (ret)
+		return ERR_PTR(ret);
+
 	pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
 		*maf_id, *dev_id);
 
 #ifdef CONFIG_SYS_NAND_ONFI_DETECTION
 	if (chip->onfi_version)
-		pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+		pr_info("%s %s\n", manufacturer_desc->name,
 				chip->onfi_params.model);
 	else if (chip->jedec_version)
-		pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+		pr_info("%s %s\n", manufacturer_desc->name,
 				chip->jedec_params.model);
 	else
-		pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+		pr_info("%s %s\n", manufacturer_desc->name,
 				type->name);
 #else
 	if (chip->jedec_version)
-		pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+		pr_info("%s %s\n", manufacturer_desc->name,
 				chip->jedec_params.model);
 	else
-		pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+		pr_info("%s %s\n", manufacturer_desc->name,
 				type->name);
 
-	pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
+	pr_info("%s %s\n", manufacturer_desc->name,
 		type->name);
 #endif
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index f2c6a978cb..57fe7fb47b 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -796,6 +796,17 @@ nand_get_sdr_timings(const struct nand_data_interface *conf)
 	return &conf->timings.sdr;
 }
 
+/**
+ * struct nand_manufacturer_ops - NAND Manufacturer operations
+ * @detect: detect the NAND memory organization and capabilities
+ * @init: initialize all vendor specific fields (like the ->read_retry()
+ *	  implementation) if any.
+ */
+struct nand_manufacturer_ops {
+	void (*detect)(struct nand_chip *chip);
+	int (*init)(struct nand_chip *chip);
+};
+
 /**
  * struct nand_chip - NAND Private Flash Chip Data
  * @mtd:		MTD device registered to the MTD framework
@@ -897,6 +908,7 @@ nand_get_sdr_timings(const struct nand_data_interface *conf)
  *			devices.
  * @priv:		[OPTIONAL] pointer to private chip data
  * @write_page:		[REPLACEABLE] High-level page write function
+ * @manufacturer:	[INTERN] Contains manufacturer information
  */
 
 struct nand_chip {
@@ -983,6 +995,11 @@ struct nand_chip {
 	struct nand_bbt_descr *badblock_pattern;
 
 	void *priv;
+
+	struct {
+		const struct nand_manufacturers *desc;
+		void *priv;
+	} manufacturer;
 };
 
 static inline void nand_set_flash_node(struct nand_chip *chip,
@@ -1016,6 +1033,17 @@ static inline void nand_set_controller_data(struct nand_chip *chip, void *priv)
 	chip->priv = priv;
 }
 
+static inline void nand_set_manufacturer_data(struct nand_chip *chip,
+					      void *priv)
+{
+	chip->manufacturer.priv = priv;
+}
+
+static inline void *nand_get_manufacturer_data(struct nand_chip *chip)
+{
+	return chip->manufacturer.priv;
+}
+
 /*
  * NAND Flash Manufacturer ID Codes
  */
@@ -1120,10 +1148,12 @@ struct nand_flash_dev {
  * struct nand_manufacturers - NAND Flash Manufacturer ID Structure
  * @name:	Manufacturer name
  * @id:		manufacturer ID code of device.
+ * @ops:	manufacturer operations
 */
 struct nand_manufacturers {
 	int id;
 	char *name;
+	const struct nand_manufacturer_ops *ops;
 };
 
 extern struct nand_flash_dev nand_flash_ids[];
-- 
2.34.1


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

* [PATCH V2 04/13] mtd: nand: Get rid of mtd variable in function calls
  2022-07-19 20:21 [PATCH V2 00/13] Port manufacturer specific initialization Michael Trimarchi
                   ` (2 preceding siblings ...)
  2022-07-19 20:21 ` [PATCH V2 03/13] mtd: nand: Add manufacturer specific initialization/detection steps Michael Trimarchi
@ 2022-07-19 20:21 ` Michael Trimarchi
  2022-07-19 20:21 ` [PATCH V2 05/13] mtd: nand: Export symbol nand_decode_ext_id Michael Trimarchi
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Michael Trimarchi @ 2022-07-19 20:21 UTC (permalink / raw)
  To: u-boot
  Cc: Dario Binacchi, Tommaso Merciai, Patrice Chotard, Wolfgang Denk,
	Marek Behún, Kory Maincent, Pali Rohár, Simon Glass

chip points to mtd. Passing chip is enough to have a reference
to mtd when is necessary

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- no changes
---
 drivers/mtd/nand/raw/nand_base.c | 20 +++++++++++---------
 include/linux/mtd/rawnand.h      |  3 +--
 2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3b9c78cb24..7d52372af5 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4160,8 +4160,9 @@ static int nand_get_bits_per_cell(u8 cellinfo)
  * chip. The rest of the parameters must be decoded according to generic or
  * manufacturer-specific "extended ID" decoding patterns.
  */
-static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip)
+static void nand_decode_ext_id(struct nand_chip *chip)
 {
+	struct mtd_info *mtd = &chip->mtd;
 	int extid, id_len;
 	/* The 3rd id byte holds MLC / multichip data */
 	chip->bits_per_cell = nand_get_bits_per_cell(chip->id.data[2]);
@@ -4291,7 +4292,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip)
  * compliant and does not have a full-id or legacy-id entry in the nand_ids
  * table.
  */
-static void nand_manufacturer_detect(struct mtd_info *mtd, struct nand_chip *chip)
+static void nand_manufacturer_detect(struct nand_chip *chip)
 {
 	/*
 	 * Try manufacturer detection if available and use
@@ -4301,7 +4302,7 @@ static void nand_manufacturer_detect(struct mtd_info *mtd, struct nand_chip *chi
 	    chip->manufacturer.desc->ops->detect)
 		chip->manufacturer.desc->ops->detect(chip);
 	else
-		nand_decode_ext_id(mtd, chip);
+		nand_decode_ext_id(chip);
 }
 
 /*
@@ -4324,9 +4325,10 @@ static int nand_manufacturer_init(struct nand_chip *chip)
  * decodes a matching ID table entry and assigns the MTD size parameters for
  * the chip.
  */
-static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip,
+static void nand_decode_id(struct nand_chip *chip,
 				struct nand_flash_dev *type)
 {
+	struct mtd_info *mtd = &chip->mtd;
 	int maf_id = chip->id.data[0];
 
 	mtd->erasesize = type->erasesize;
@@ -4439,11 +4441,11 @@ static const struct nand_manufacturers *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 mtd_info *mtd,
-						  struct nand_chip *chip,
+struct nand_flash_dev *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_manufacturers *manufacturer_desc;
 	int busw, ret;
 	u8 *id_data = chip->id.data;
@@ -4539,9 +4541,9 @@ struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	chip->chipsize = (uint64_t)type->chipsize << 20;
 
 	if (!type->pagesize) {
-		nand_manufacturer_detect(mtd, chip);
+		nand_manufacturer_detect(chip);
 	} else {
-		nand_decode_id(mtd, chip, type);
+		nand_decode_id(chip, type);
 	}
 
 	/* Get chip options */
@@ -4731,7 +4733,7 @@ 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(mtd, chip, &nand_maf_id,
+	type = nand_get_flash_type(chip, &nand_maf_id,
 				   &nand_dev_id, table);
 
 	if (IS_ERR(type)) {
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 57fe7fb47b..d8141cb4d1 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -29,8 +29,7 @@ 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 mtd_info *mtd,
-					   struct nand_chip *chip,
+struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip,
 					   int *maf_id, int *dev_id,
 					   struct nand_flash_dev *type);
 
-- 
2.34.1


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

* [PATCH V2 05/13] mtd: nand: Export symbol nand_decode_ext_id
  2022-07-19 20:21 [PATCH V2 00/13] Port manufacturer specific initialization Michael Trimarchi
                   ` (3 preceding siblings ...)
  2022-07-19 20:21 ` [PATCH V2 04/13] mtd: nand: Get rid of mtd variable in function calls Michael Trimarchi
@ 2022-07-19 20:21 ` Michael Trimarchi
  2022-07-19 20:21 ` [PATCH V2 06/13] mtd: nand: Move Samsung specific init/detection logic in nand_samsung.c Michael Trimarchi
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Michael Trimarchi @ 2022-07-19 20:21 UTC (permalink / raw)
  To: u-boot
  Cc: Dario Binacchi, Tommaso Merciai, Patrice Chotard, Wolfgang Denk,
	Miquel Raynal, Marek Behún, Pali Rohár, Kory Maincent,
	Simon Glass

In preparation of moving specific nand support that are not jedec
or onfi

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- no changes
---
 drivers/mtd/nand/raw/nand_base.c | 3 ++-
 include/linux/mtd/rawnand.h      | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 7d52372af5..4cb38378f4 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4160,7 +4160,7 @@ static int nand_get_bits_per_cell(u8 cellinfo)
  * chip. The rest of the parameters must be decoded according to generic or
  * manufacturer-specific "extended ID" decoding patterns.
  */
-static void nand_decode_ext_id(struct nand_chip *chip)
+void nand_decode_ext_id(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = &chip->mtd;
 	int extid, id_len;
@@ -4286,6 +4286,7 @@ static void nand_decode_ext_id(struct nand_chip *chip)
 
 	}
 }
+EXPORT_SYMBOL_GPL(nand_decode_ext_id);
 
 /*
  * Manufacturer detection. Only used when the NAND is not ONFI or JEDEC
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index d8141cb4d1..8fb2a43296 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1374,4 +1374,7 @@ int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
 int nand_write_data_op(struct nand_chip *chip, const void *buf,
 		       unsigned int len, bool force_8bit);
 
+/* Default extended ID decoding function */
+void nand_decode_ext_id(struct nand_chip *chip);
+
 #endif /* __LINUX_MTD_RAWNAND_H */
-- 
2.34.1


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

* [PATCH V2 06/13] mtd: nand: Move Samsung specific init/detection logic in nand_samsung.c
  2022-07-19 20:21 [PATCH V2 00/13] Port manufacturer specific initialization Michael Trimarchi
                   ` (4 preceding siblings ...)
  2022-07-19 20:21 ` [PATCH V2 05/13] mtd: nand: Export symbol nand_decode_ext_id Michael Trimarchi
@ 2022-07-19 20:21 ` Michael Trimarchi
  2022-07-19 20:21 ` [PATCH V2 07/13] mtd: nand: Move Hynix specific init/detection logic in nand_hynix.c Michael Trimarchi
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Michael Trimarchi @ 2022-07-19 20:21 UTC (permalink / raw)
  To: u-boot
  Cc: Dario Binacchi, Tommaso Merciai, Zhengxun Li, Patrice Chotard,
	Wolfgang Denk, Kory Maincent, Marek Behún, Simon Glass

Upstream linux commit c51d0ac59f

Move Samsung specific initialization and detection logic into
nand_samsung.c. This is part of the "separate vendor specific code from
core" cleanup process.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- use short-commit form
	- remove linux info. Uboot seems that backport without add this
	  extra information
	- adjust the include file in nand_samsung
---
 drivers/mtd/nand/raw/Makefile       |  3 +-
 drivers/mtd/nand/raw/nand_base.c    | 50 +---------------
 drivers/mtd/nand/raw/nand_ids.c     |  4 +-
 drivers/mtd/nand/raw/nand_samsung.c | 89 +++++++++++++++++++++++++++++
 include/linux/mtd/rawnand.h         |  2 +
 5 files changed, 98 insertions(+), 50 deletions(-)
 create mode 100644 drivers/mtd/nand/raw/nand_samsung.c

diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index e3f6b903f7..0e3f017bf6 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -14,7 +14,7 @@ obj-$(CONFIG_SPL_NAND_DENALI) += denali_spl.o
 obj-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
 obj-$(CONFIG_SPL_NAND_LOAD) += nand_spl_load.o
 obj-$(CONFIG_SPL_NAND_ECC) += nand_ecc.o
-obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o
+obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o nand_samsung.o
 obj-$(CONFIG_SPL_NAND_IDENT) += nand_ids.o nand_timings.o
 obj-$(CONFIG_TPL_NAND_INIT) += nand.o
 ifeq ($(CONFIG_SPL_ENV_SUPPORT),y)
@@ -31,6 +31,7 @@ obj-y += nand_ids.o
 obj-y += nand_util.o
 obj-y += nand_ecc.o
 obj-y += nand_base.o
+obj-y += nand_samsung.o
 obj-y += nand_timings.o
 
 endif # not spl
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 4cb38378f4..7f41395afe 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4173,47 +4173,12 @@ void nand_decode_ext_id(struct nand_chip *chip)
 	/*
 	 * Field definitions are in the following datasheets:
 	 * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
-	 * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44)
 	 * Hynix MLC   (6 byte ID): Hynix H27UBG8T2B (p.22)
 	 *
 	 * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung
 	 * ID to decide what to do.
 	 */
-	if (id_len == 6 && chip->id.data[0] == NAND_MFR_SAMSUNG &&
-			!nand_is_slc(chip) && chip->id.data[5] != 0x00) {
-		/* Calc pagesize */
-		mtd->writesize = 2048 << (extid & 0x03);
-		extid >>= 2;
-		/* Calc oobsize */
-		switch (((extid >> 2) & 0x04) | (extid & 0x03)) {
-		case 1:
-			mtd->oobsize = 128;
-			break;
-		case 2:
-			mtd->oobsize = 218;
-			break;
-		case 3:
-			mtd->oobsize = 400;
-			break;
-		case 4:
-			mtd->oobsize = 436;
-			break;
-		case 5:
-			mtd->oobsize = 512;
-			break;
-		case 6:
-			mtd->oobsize = 640;
-			break;
-		case 7:
-		default: /* Other cases are "reserved" (unknown) */
-			mtd->oobsize = 1024;
-			break;
-		}
-		extid >>= 2;
-		/* Calc blocksize */
-		mtd->erasesize = (128 * 1024) <<
-			(((extid >> 1) & 0x04) | (extid & 0x03));
-	} else if (id_len == 6 && chip->id.data[0] == NAND_MFR_HYNIX &&
+	if (id_len == 6 && chip->id.data[0] == NAND_MFR_HYNIX &&
 			!nand_is_slc(chip)) {
 		unsigned int tmp;
 
@@ -4375,13 +4340,10 @@ static void nand_decode_bbm_options(struct mtd_info *mtd,
 	 * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba,
 	 * AMD/Spansion, and Macronix.  All others scan only the first page.
 	 */
-	if (!nand_is_slc(chip) &&
-			(maf_id == NAND_MFR_SAMSUNG ||
-			 maf_id == NAND_MFR_HYNIX))
+	if (!nand_is_slc(chip) && maf_id == NAND_MFR_HYNIX)
 		chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
 	else if ((nand_is_slc(chip) &&
-				(maf_id == NAND_MFR_SAMSUNG ||
-				 maf_id == NAND_MFR_HYNIX ||
+				(maf_id == NAND_MFR_HYNIX ||
 				 maf_id == NAND_MFR_TOSHIBA ||
 				 maf_id == NAND_MFR_AMD ||
 				 maf_id == NAND_MFR_MACRONIX)) ||
@@ -4550,12 +4512,6 @@ struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip,
 	/* Get chip options */
 	chip->options |= type->options;
 
-	/*
-	 * Check if chip is not a Samsung device. Do not clear the
-	 * options for chips which do not have an extended id.
-	 */
-	if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
-		chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
 ident_done:
 
 	if (chip->options & NAND_BUSWIDTH_AUTO) {
diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
index 2a50f0b214..f4126c3a5a 100644
--- a/drivers/mtd/nand/raw/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
@@ -10,7 +10,7 @@
 #include <linux/mtd/rawnand.h>
 #include <linux/sizes.h>
 
-#define LP_OPTIONS NAND_SAMSUNG_LP_OPTIONS
+#define LP_OPTIONS 0
 #define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
 
 #define SP_OPTIONS NAND_NEED_READRDY
@@ -189,7 +189,7 @@ struct nand_flash_dev nand_flash_ids[] = {
 /* Manufacturer IDs */
 struct nand_manufacturers nand_manuf_ids[] = {
 	{NAND_MFR_TOSHIBA, "Toshiba"},
-	{NAND_MFR_SAMSUNG, "Samsung"},
+	{NAND_MFR_SAMSUNG, "Samsung", &samsung_nand_manuf_ops},
 	{NAND_MFR_FUJITSU, "Fujitsu"},
 	{NAND_MFR_NATIONAL, "National"},
 	{NAND_MFR_RENESAS, "Renesas"},
diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c
new file mode 100644
index 0000000000..ae39805949
--- /dev/null
+++ b/drivers/mtd/nand/raw/nand_samsung.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 Free Electrons
+ * Copyright (C) 2017 NextThing Co
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bug.h>
+#include <linux/mtd/rawnand.h>
+
+static void samsung_nand_decode_id(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	/* New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) */
+	if (chip->id.len == 6 && !nand_is_slc(chip) &&
+	    chip->id.data[5] != 0x00) {
+		u8 extid = chip->id.data[3];
+
+		/* Get pagesize */
+		mtd->writesize = 2048 << (extid & 0x03);
+
+		extid >>= 2;
+
+		/* Get oobsize */
+		switch (((extid >> 2) & 0x4) | (extid & 0x3)) {
+		case 1:
+			mtd->oobsize = 128;
+			break;
+		case 2:
+			mtd->oobsize = 218;
+			break;
+		case 3:
+			mtd->oobsize = 400;
+			break;
+		case 4:
+			mtd->oobsize = 436;
+			break;
+		case 5:
+			mtd->oobsize = 512;
+			break;
+		case 6:
+			mtd->oobsize = 640;
+			break;
+		case 7:
+		default: /* Other cases are "reserved" (unknown) */
+			WARN(1, "Invalid OOB size value");
+			mtd->oobsize = 1024;
+			break;
+		}
+
+		/* Get blocksize */
+		extid >>= 2;
+		mtd->erasesize = (128 * 1024) <<
+				 (((extid >> 1) & 0x04) | (extid & 0x03));
+	} else {
+		nand_decode_ext_id(chip);
+	}
+}
+
+static int samsung_nand_init(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	if (mtd->writesize > 512)
+		chip->options |= NAND_SAMSUNG_LP_OPTIONS;
+
+	if (!nand_is_slc(chip))
+		chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
+	else
+		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+
+	return 0;
+}
+
+const struct nand_manufacturer_ops samsung_nand_manuf_ops = {
+	.detect = samsung_nand_decode_id,
+	.init = samsung_nand_init,
+};
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 8fb2a43296..d0312e924b 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1158,6 +1158,8 @@ struct nand_manufacturers {
 extern struct nand_flash_dev nand_flash_ids[];
 extern struct nand_manufacturers nand_manuf_ids[];
 
+extern const struct nand_manufacturer_ops samsung_nand_manuf_ops;
+
 int nand_default_bbt(struct mtd_info *mtd);
 int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
 int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs);
-- 
2.34.1


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

* [PATCH V2 07/13] mtd: nand: Move Hynix specific init/detection logic in nand_hynix.c
  2022-07-19 20:21 [PATCH V2 00/13] Port manufacturer specific initialization Michael Trimarchi
                   ` (5 preceding siblings ...)
  2022-07-19 20:21 ` [PATCH V2 06/13] mtd: nand: Move Samsung specific init/detection logic in nand_samsung.c Michael Trimarchi
@ 2022-07-19 20:21 ` Michael Trimarchi
  2022-07-19 20:21 ` [PATCH V2 08/13] mtd: nand: Move Toshiba specific init/detection logic in nand_toshiba.c Michael Trimarchi
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Michael Trimarchi @ 2022-07-19 20:21 UTC (permalink / raw)
  To: u-boot
  Cc: Dario Binacchi, Tommaso Merciai, Zhengxun Li, Patrice Chotard,
	Wolfgang Denk, Priyanka Jain, Kory Maincent, Marek Behún,
	Simon Glass

Upstream linux commit 01389b6bd2

Move Hynix specific initialization and detection logic into
nand_hynix.c. This is part of the "separate vendor specific code from
core" cleanup process.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- use short-commit form
	- remove linux info. Uboot seems that backport without add this
	  extra information
	- adjust the include file in nand_hynix
---
 drivers/mtd/nand/raw/Makefile     |   3 +-
 drivers/mtd/nand/raw/nand_base.c  | 117 ++++++++----------------------
 drivers/mtd/nand/raw/nand_hynix.c |  84 +++++++++++++++++++++
 drivers/mtd/nand/raw/nand_ids.c   |   2 +-
 include/linux/mtd/rawnand.h       |   1 +
 5 files changed, 119 insertions(+), 88 deletions(-)
 create mode 100644 drivers/mtd/nand/raw/nand_hynix.c

diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 0e3f017bf6..294d131264 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -14,7 +14,7 @@ obj-$(CONFIG_SPL_NAND_DENALI) += denali_spl.o
 obj-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
 obj-$(CONFIG_SPL_NAND_LOAD) += nand_spl_load.o
 obj-$(CONFIG_SPL_NAND_ECC) += nand_ecc.o
-obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o nand_samsung.o
+obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o nand_hynix.o nand_samsung.o
 obj-$(CONFIG_SPL_NAND_IDENT) += nand_ids.o nand_timings.o
 obj-$(CONFIG_TPL_NAND_INIT) += nand.o
 ifeq ($(CONFIG_SPL_ENV_SUPPORT),y)
@@ -31,6 +31,7 @@ obj-y += nand_ids.o
 obj-y += nand_util.o
 obj-y += nand_ecc.o
 obj-y += nand_base.o
+obj-y += nand_hynix.o
 obj-y += nand_samsung.o
 obj-y += nand_timings.o
 
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 7f41395afe..6ff1a2cb29 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4170,85 +4170,34 @@ void nand_decode_ext_id(struct nand_chip *chip)
 	extid = chip->id.data[3];
 	id_len = chip->id.len;
 
+	/* Calc pagesize */
+	mtd->writesize = 1024 << (extid & 0x03);
+	extid >>= 2;
+	/* Calc oobsize */
+	mtd->oobsize = (8 << (extid & 0x01)) *
+		(mtd->writesize >> 9);
+	extid >>= 2;
+	/* Calc blocksize. Blocksize is multiples of 64KiB */
+	mtd->erasesize = (64 * 1024) << (extid & 0x03);
+	extid >>= 2;
+	/* Get buswidth information */
+	/* Get buswidth information */
+	if (extid & 0x1)
+		chip->options |= NAND_BUSWIDTH_16;
+
 	/*
-	 * Field definitions are in the following datasheets:
-	 * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
-	 * Hynix MLC   (6 byte ID): Hynix H27UBG8T2B (p.22)
-	 *
-	 * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung
-	 * ID to decide what to do.
+	 * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per
+	 * 512B page. For Toshiba SLC, we decode the 5th/6th byte as
+	 * follows:
+	 * - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm,
+	 *                         110b -> 24nm
+	 * - ID byte 5, bit[7]:    1 -> BENAND, 0 -> raw SLC
 	 */
-	if (id_len == 6 && chip->id.data[0] == NAND_MFR_HYNIX &&
-			!nand_is_slc(chip)) {
-		unsigned int tmp;
-
-		/* Calc pagesize */
-		mtd->writesize = 2048 << (extid & 0x03);
-		extid >>= 2;
-		/* Calc oobsize */
-		switch (((extid >> 2) & 0x04) | (extid & 0x03)) {
-		case 0:
-			mtd->oobsize = 128;
-			break;
-		case 1:
-			mtd->oobsize = 224;
-			break;
-		case 2:
-			mtd->oobsize = 448;
-			break;
-		case 3:
-			mtd->oobsize = 64;
-			break;
-		case 4:
-			mtd->oobsize = 32;
-			break;
-		case 5:
-			mtd->oobsize = 16;
-			break;
-		default:
-			mtd->oobsize = 640;
-			break;
-		}
-		extid >>= 2;
-		/* Calc blocksize */
-		tmp = ((extid >> 1) & 0x04) | (extid & 0x03);
-		if (tmp < 0x03)
-			mtd->erasesize = (128 * 1024) << tmp;
-		else if (tmp == 0x03)
-			mtd->erasesize = 768 * 1024;
-		else
-			mtd->erasesize = (64 * 1024) << tmp;
-	} else {
-		/* Calc pagesize */
-		mtd->writesize = 1024 << (extid & 0x03);
-		extid >>= 2;
-		/* Calc oobsize */
-		mtd->oobsize = (8 << (extid & 0x01)) *
-			(mtd->writesize >> 9);
-		extid >>= 2;
-		/* Calc blocksize. Blocksize is multiples of 64KiB */
-		mtd->erasesize = (64 * 1024) << (extid & 0x03);
-		extid >>= 2;
-		/* Get buswidth information */
-		/* Get buswidth information */
-		if (extid & 0x1)
-			chip->options |= NAND_BUSWIDTH_16;
-
-		/*
-		 * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per
-		 * 512B page. For Toshiba SLC, we decode the 5th/6th byte as
-		 * follows:
-		 * - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm,
-		 *                         110b -> 24nm
-		 * - ID byte 5, bit[7]:    1 -> BENAND, 0 -> raw SLC
-		 */
-		if (id_len >= 6 && chip->id.data[0] == NAND_MFR_TOSHIBA &&
-				nand_is_slc(chip) &&
-				(chip->id.data[5] & 0x7) == 0x6 /* 24nm */ &&
-				!(chip->id.data[4] & 0x80) /* !BENAND */) {
-			mtd->oobsize = 32 * mtd->writesize >> 9;
-		}
-
+	if (id_len >= 6 && chip->id.data[0] == NAND_MFR_TOSHIBA &&
+			nand_is_slc(chip) &&
+			(chip->id.data[5] & 0x7) == 0x6 /* 24nm */ &&
+			!(chip->id.data[4] & 0x80) /* !BENAND */) {
+		mtd->oobsize = 32 * mtd->writesize >> 9;
 	}
 }
 EXPORT_SYMBOL_GPL(nand_decode_ext_id);
@@ -4340,15 +4289,11 @@ static void nand_decode_bbm_options(struct mtd_info *mtd,
 	 * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba,
 	 * AMD/Spansion, and Macronix.  All others scan only the first page.
 	 */
-	if (!nand_is_slc(chip) && maf_id == NAND_MFR_HYNIX)
-		chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
-	else if ((nand_is_slc(chip) &&
-				(maf_id == NAND_MFR_HYNIX ||
-				 maf_id == NAND_MFR_TOSHIBA ||
-				 maf_id == NAND_MFR_AMD ||
-				 maf_id == NAND_MFR_MACRONIX)) ||
-			(mtd->writesize == 2048 &&
-			 maf_id == NAND_MFR_MICRON))
+	if ((nand_is_slc(chip) &&
+	     (maf_id == NAND_MFR_TOSHIBA ||
+	      maf_id == NAND_MFR_AMD ||
+	      maf_id == NAND_MFR_MACRONIX)) ||
+	    (mtd->writesize == 2048 && maf_id == NAND_MFR_MICRON))
 		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
 }
 
diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
new file mode 100644
index 0000000000..153e5eccf2
--- /dev/null
+++ b/drivers/mtd/nand/raw/nand_hynix.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 Free Electrons
+ * Copyright (C) 2017 NextThing Co
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mtd/rawnand.h>
+
+static void hynix_nand_decode_id(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	/* Hynix MLC   (6 byte ID): Hynix H27UBG8T2B (p.22) */
+	if (chip->id.len == 6 && !nand_is_slc(chip)) {
+		u8 tmp, extid = chip->id.data[3];
+
+		/* Extract pagesize */
+		mtd->writesize = 2048 << (extid & 0x03);
+		extid >>= 2;
+
+		/* Extract oobsize */
+		switch (((extid >> 2) & 0x4) | (extid & 0x3)) {
+		case 0:
+			mtd->oobsize = 128;
+			break;
+		case 1:
+			mtd->oobsize = 224;
+			break;
+		case 2:
+			mtd->oobsize = 448;
+			break;
+		case 3:
+			mtd->oobsize = 64;
+			break;
+		case 4:
+			mtd->oobsize = 32;
+			break;
+		case 5:
+			mtd->oobsize = 16;
+			break;
+		default:
+			mtd->oobsize = 640;
+			break;
+		}
+
+		/* Extract blocksize */
+		extid >>= 2;
+		tmp = ((extid >> 1) & 0x04) | (extid & 0x03);
+		if (tmp < 0x03)
+			mtd->erasesize = (128 * 1024) << tmp;
+		else if (tmp == 0x03)
+			mtd->erasesize = 768 * 1024;
+		else
+			mtd->erasesize = (64 * 1024) << tmp;
+	} else {
+		nand_decode_ext_id(chip);
+	}
+}
+
+static int hynix_nand_init(struct nand_chip *chip)
+{
+	if (!nand_is_slc(chip))
+		chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
+	else
+		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+
+	return 0;
+}
+
+const struct nand_manufacturer_ops hynix_nand_manuf_ops = {
+	.detect = hynix_nand_decode_id,
+	.init = hynix_nand_init,
+};
diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
index f4126c3a5a..ec263a4327 100644
--- a/drivers/mtd/nand/raw/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
@@ -194,7 +194,7 @@ struct nand_manufacturers nand_manuf_ids[] = {
 	{NAND_MFR_NATIONAL, "National"},
 	{NAND_MFR_RENESAS, "Renesas"},
 	{NAND_MFR_STMICRO, "ST Micro"},
-	{NAND_MFR_HYNIX, "Hynix"},
+	{NAND_MFR_HYNIX, "Hynix", &hynix_nand_manuf_ops},
 	{NAND_MFR_MICRON, "Micron"},
 	{NAND_MFR_AMD, "AMD/Spansion"},
 	{NAND_MFR_MACRONIX, "Macronix"},
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index d0312e924b..d35277d187 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1159,6 +1159,7 @@ extern struct nand_flash_dev nand_flash_ids[];
 extern struct nand_manufacturers nand_manuf_ids[];
 
 extern const struct nand_manufacturer_ops samsung_nand_manuf_ops;
+extern const struct nand_manufacturer_ops hynix_nand_manuf_ops;
 
 int nand_default_bbt(struct mtd_info *mtd);
 int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
-- 
2.34.1


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

* [PATCH V2 08/13] mtd: nand: Move Toshiba specific init/detection logic in nand_toshiba.c
  2022-07-19 20:21 [PATCH V2 00/13] Port manufacturer specific initialization Michael Trimarchi
                   ` (6 preceding siblings ...)
  2022-07-19 20:21 ` [PATCH V2 07/13] mtd: nand: Move Hynix specific init/detection logic in nand_hynix.c Michael Trimarchi
@ 2022-07-19 20:21 ` Michael Trimarchi
  2022-07-19 20:21 ` [PATCH V2 09/13] mtd: nand: Move Micron specific init logic in nand_micron.c Michael Trimarchi
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Michael Trimarchi @ 2022-07-19 20:21 UTC (permalink / raw)
  To: u-boot
  Cc: Dario Binacchi, Tommaso Merciai, Zhengxun Li, Patrice Chotard,
	Wolfgang Denk, Miquel Raynal, Priyanka Jain, Marek Behún,
	Pali Rohár, Kory Maincent, Simon Glass

Upstream linux commit 9b2d61f80b

Move Toshiba specific initialization and detection logic into
nand_toshiba.c. This is part of the "separate vendor specific code from
core" cleanup process.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- use short-commit form
	- remove linux info. Uboot seems that backport without add this
	  extra information
	- adjust the include file in nand_toshiba
---
 drivers/mtd/nand/raw/Makefile       |  3 +-
 drivers/mtd/nand/raw/nand_base.c    | 21 ++----------
 drivers/mtd/nand/raw/nand_ids.c     |  2 +-
 drivers/mtd/nand/raw/nand_toshiba.c | 52 +++++++++++++++++++++++++++++
 include/linux/mtd/rawnand.h         |  1 +
 5 files changed, 58 insertions(+), 21 deletions(-)
 create mode 100644 drivers/mtd/nand/raw/nand_toshiba.c

diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 294d131264..db608a2830 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -14,7 +14,7 @@ obj-$(CONFIG_SPL_NAND_DENALI) += denali_spl.o
 obj-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
 obj-$(CONFIG_SPL_NAND_LOAD) += nand_spl_load.o
 obj-$(CONFIG_SPL_NAND_ECC) += nand_ecc.o
-obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o nand_hynix.o nand_samsung.o
+obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o nand_hynix.o nand_samsung.o nand_toshiba.o
 obj-$(CONFIG_SPL_NAND_IDENT) += nand_ids.o nand_timings.o
 obj-$(CONFIG_TPL_NAND_INIT) += nand.o
 ifeq ($(CONFIG_SPL_ENV_SUPPORT),y)
@@ -33,6 +33,7 @@ obj-y += nand_ecc.o
 obj-y += nand_base.o
 obj-y += nand_hynix.o
 obj-y += nand_samsung.o
+obj-y += nand_toshiba.o
 obj-y += nand_timings.o
 
 endif # not spl
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 6ff1a2cb29..8c06b1c530 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4163,12 +4163,11 @@ static int nand_get_bits_per_cell(u8 cellinfo)
 void nand_decode_ext_id(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = &chip->mtd;
-	int extid, id_len;
+	int extid;
 	/* The 3rd id byte holds MLC / multichip data */
 	chip->bits_per_cell = nand_get_bits_per_cell(chip->id.data[2]);
 	/* The 4th id byte is the important one */
 	extid = chip->id.data[3];
-	id_len = chip->id.len;
 
 	/* Calc pagesize */
 	mtd->writesize = 1024 << (extid & 0x03);
@@ -4184,21 +4183,6 @@ void nand_decode_ext_id(struct nand_chip *chip)
 	/* Get buswidth information */
 	if (extid & 0x1)
 		chip->options |= NAND_BUSWIDTH_16;
-
-	/*
-	 * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per
-	 * 512B page. For Toshiba SLC, we decode the 5th/6th byte as
-	 * follows:
-	 * - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm,
-	 *                         110b -> 24nm
-	 * - ID byte 5, bit[7]:    1 -> BENAND, 0 -> raw SLC
-	 */
-	if (id_len >= 6 && chip->id.data[0] == NAND_MFR_TOSHIBA &&
-			nand_is_slc(chip) &&
-			(chip->id.data[5] & 0x7) == 0x6 /* 24nm */ &&
-			!(chip->id.data[4] & 0x80) /* !BENAND */) {
-		mtd->oobsize = 32 * mtd->writesize >> 9;
-	}
 }
 EXPORT_SYMBOL_GPL(nand_decode_ext_id);
 
@@ -4290,8 +4274,7 @@ static void nand_decode_bbm_options(struct mtd_info *mtd,
 	 * AMD/Spansion, and Macronix.  All others scan only the first page.
 	 */
 	if ((nand_is_slc(chip) &&
-	     (maf_id == NAND_MFR_TOSHIBA ||
-	      maf_id == NAND_MFR_AMD ||
+	     (maf_id == NAND_MFR_AMD ||
 	      maf_id == NAND_MFR_MACRONIX)) ||
 	    (mtd->writesize == 2048 && maf_id == NAND_MFR_MICRON))
 		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
index ec263a4327..509652c8e2 100644
--- a/drivers/mtd/nand/raw/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
@@ -188,7 +188,7 @@ struct nand_flash_dev nand_flash_ids[] = {
 
 /* Manufacturer IDs */
 struct nand_manufacturers nand_manuf_ids[] = {
-	{NAND_MFR_TOSHIBA, "Toshiba"},
+	{NAND_MFR_TOSHIBA, "Toshiba", &toshiba_nand_manuf_ops},
 	{NAND_MFR_SAMSUNG, "Samsung", &samsung_nand_manuf_ops},
 	{NAND_MFR_FUJITSU, "Fujitsu"},
 	{NAND_MFR_NATIONAL, "National"},
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
new file mode 100644
index 0000000000..4328e566b0
--- /dev/null
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 Free Electrons
+ * Copyright (C) 2017 NextThing Co
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bug.h>
+#include <linux/mtd/rawnand.h>
+
+static void toshiba_nand_decode_id(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	nand_decode_ext_id(chip);
+
+	/*
+	 * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per
+	 * 512B page. For Toshiba SLC, we decode the 5th/6th byte as
+	 * follows:
+	 * - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm,
+	 *                         110b -> 24nm
+	 * - ID byte 5, bit[7]:    1 -> BENAND, 0 -> raw SLC
+	 */
+	if (chip->id.len >= 6 && nand_is_slc(chip) &&
+	    (chip->id.data[5] & 0x7) == 0x6 /* 24nm */ &&
+	    !(chip->id.data[4] & 0x80) /* !BENAND */)
+		mtd->oobsize = 32 * mtd->writesize >> 9;
+}
+
+static int toshiba_nand_init(struct nand_chip *chip)
+{
+	if (nand_is_slc(chip))
+		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+
+	return 0;
+}
+
+const struct nand_manufacturer_ops toshiba_nand_manuf_ops = {
+	.detect = toshiba_nand_decode_id,
+	.init = toshiba_nand_init,
+};
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index d35277d187..73abb34016 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1158,6 +1158,7 @@ struct nand_manufacturers {
 extern struct nand_flash_dev nand_flash_ids[];
 extern struct nand_manufacturers nand_manuf_ids[];
 
+extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
 extern const struct nand_manufacturer_ops samsung_nand_manuf_ops;
 extern const struct nand_manufacturer_ops hynix_nand_manuf_ops;
 
-- 
2.34.1


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

* [PATCH V2 09/13] mtd: nand: Move Micron specific init logic in nand_micron.c
  2022-07-19 20:21 [PATCH V2 00/13] Port manufacturer specific initialization Michael Trimarchi
                   ` (7 preceding siblings ...)
  2022-07-19 20:21 ` [PATCH V2 08/13] mtd: nand: Move Toshiba specific init/detection logic in nand_toshiba.c Michael Trimarchi
@ 2022-07-19 20:21 ` Michael Trimarchi
  2022-07-19 20:22 ` [PATCH V2 10/13] mtd: nand: Move AMD/Spansion specific init/detection logic in nand_amd.c Michael Trimarchi
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Michael Trimarchi @ 2022-07-19 20:21 UTC (permalink / raw)
  To: u-boot
  Cc: Dario Binacchi, Tommaso Merciai, Zhengxun Li, Patrice Chotard,
	Wolfgang Denk, Simon Glass, Miquel Raynal, Marek Behún,
	Pali Rohár, Kory Maincent

Upstream linux commit 10d4e75c36

Move Micron specific initialization logic into nand_micron.c. This is
part of the "separate vendor specific code from core" cleanup process.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- use short-commit form
	- remove linux info. Uboot seems that backport without add this
	  extra information
	- adjust the include file in nand_micron
---
 drivers/mtd/nand/raw/Makefile      |  3 +-
 drivers/mtd/nand/raw/nand_base.c   | 33 +-----------
 drivers/mtd/nand/raw/nand_ids.c    |  2 +-
 drivers/mtd/nand/raw/nand_micron.c | 86 ++++++++++++++++++++++++++++++
 include/linux/mtd/rawnand.h        | 21 +-------
 5 files changed, 92 insertions(+), 53 deletions(-)
 create mode 100644 drivers/mtd/nand/raw/nand_micron.c

diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index db608a2830..e8fb451076 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -14,7 +14,7 @@ obj-$(CONFIG_SPL_NAND_DENALI) += denali_spl.o
 obj-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
 obj-$(CONFIG_SPL_NAND_LOAD) += nand_spl_load.o
 obj-$(CONFIG_SPL_NAND_ECC) += nand_ecc.o
-obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o nand_hynix.o nand_samsung.o nand_toshiba.o
+obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o nand_hynix.o nand_micron.o nand_samsung.o nand_toshiba.o
 obj-$(CONFIG_SPL_NAND_IDENT) += nand_ids.o nand_timings.o
 obj-$(CONFIG_TPL_NAND_INIT) += nand.o
 ifeq ($(CONFIG_SPL_ENV_SUPPORT),y)
@@ -32,6 +32,7 @@ obj-y += nand_util.o
 obj-y += nand_ecc.o
 obj-y += nand_base.o
 obj-y += nand_hynix.o
+obj-y += nand_micron.o
 obj-y += nand_samsung.o
 obj-y += nand_toshiba.o
 obj-y += nand_timings.o
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 8c06b1c530..d2079c73fb 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -3871,30 +3871,6 @@ ext_out:
 	return ret;
 }
 
-static int nand_setup_read_retry_micron(struct mtd_info *mtd, int retry_mode)
-{
-	struct nand_chip *chip = mtd_to_nand(mtd);
-	uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
-
-	return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
-			feature);
-}
-
-/*
- * Configure chip properties from Micron vendor-specific ONFI table
- */
-static void nand_onfi_detect_micron(struct nand_chip *chip,
-		struct nand_onfi_params *p)
-{
-	struct nand_onfi_vendor_micron *micron = (void *)p->vendor;
-
-	if (le16_to_cpu(p->vendor_revision) < 1)
-		return;
-
-	chip->read_retries = micron->read_retry_options;
-	chip->setup_read_retry = nand_setup_read_retry_micron;
-}
-
 /*
  * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
  */
@@ -3994,9 +3970,6 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip)
 		pr_warn("Could not retrieve ONFI ECC requirements\n");
 	}
 
-	if (p->jedec_id == NAND_MFR_MICRON)
-		nand_onfi_detect_micron(chip, p);
-
 	return 1;
 }
 #else
@@ -4273,10 +4246,8 @@ static void nand_decode_bbm_options(struct mtd_info *mtd,
 	 * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba,
 	 * AMD/Spansion, and Macronix.  All others scan only the first page.
 	 */
-	if ((nand_is_slc(chip) &&
-	     (maf_id == NAND_MFR_AMD ||
-	      maf_id == NAND_MFR_MACRONIX)) ||
-	    (mtd->writesize == 2048 && maf_id == NAND_MFR_MICRON))
+	if (nand_is_slc(chip) &&
+	    (maf_id == NAND_MFR_AMD || maf_id == NAND_MFR_MACRONIX))
 		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
 }
 
diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
index 509652c8e2..bb5ac8337f 100644
--- a/drivers/mtd/nand/raw/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
@@ -195,7 +195,7 @@ struct nand_manufacturers nand_manuf_ids[] = {
 	{NAND_MFR_RENESAS, "Renesas"},
 	{NAND_MFR_STMICRO, "ST Micro"},
 	{NAND_MFR_HYNIX, "Hynix", &hynix_nand_manuf_ops},
-	{NAND_MFR_MICRON, "Micron"},
+	{NAND_MFR_MICRON, "Micron", &micron_nand_manuf_ops},
 	{NAND_MFR_AMD, "AMD/Spansion"},
 	{NAND_MFR_MACRONIX, "Macronix"},
 	{NAND_MFR_EON, "Eon"},
diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
new file mode 100644
index 0000000000..50426983ba
--- /dev/null
+++ b/drivers/mtd/nand/raw/nand_micron.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 Free Electrons
+ * Copyright (C) 2017 NextThing Co
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mtd/rawnand.h>
+
+struct nand_onfi_vendor_micron {
+	u8 two_plane_read;
+	u8 read_cache;
+	u8 read_unique_id;
+	u8 dq_imped;
+	u8 dq_imped_num_settings;
+	u8 dq_imped_feat_addr;
+	u8 rb_pulldown_strength;
+	u8 rb_pulldown_strength_feat_addr;
+	u8 rb_pulldown_strength_num_settings;
+	u8 otp_mode;
+	u8 otp_page_start;
+	u8 otp_data_prot_addr;
+	u8 otp_num_pages;
+	u8 otp_feat_addr;
+	u8 read_retry_options;
+	u8 reserved[72];
+	u8 param_revision;
+} __packed;
+
+static int micron_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
+
+	return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
+				       feature);
+}
+
+/*
+ * Configure chip properties from Micron vendor-specific ONFI table
+ */
+static int micron_nand_onfi_init(struct nand_chip *chip)
+{
+	struct nand_onfi_params *p = &chip->onfi_params;
+	struct nand_onfi_vendor_micron *micron = (void *)p->vendor;
+
+	if (!chip->onfi_version)
+		return 0;
+
+	if (le16_to_cpu(p->vendor_revision) < 1)
+		return 0;
+
+	chip->read_retries = micron->read_retry_options;
+	chip->setup_read_retry = micron_nand_setup_read_retry;
+
+	return 0;
+}
+
+static int micron_nand_init(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	int ret;
+
+	ret = micron_nand_onfi_init(chip);
+	if (ret)
+		return ret;
+
+	if (mtd->writesize == 2048)
+		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+
+	return 0;
+}
+
+const struct nand_manufacturer_ops micron_nand_manuf_ops = {
+	.init = micron_nand_init,
+};
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 73abb34016..ec0f77b24b 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -388,26 +388,6 @@ struct onfi_ext_param_page {
 	 */
 } __packed;
 
-struct nand_onfi_vendor_micron {
-	u8 two_plane_read;
-	u8 read_cache;
-	u8 read_unique_id;
-	u8 dq_imped;
-	u8 dq_imped_num_settings;
-	u8 dq_imped_feat_addr;
-	u8 rb_pulldown_strength;
-	u8 rb_pulldown_strength_feat_addr;
-	u8 rb_pulldown_strength_num_settings;
-	u8 otp_mode;
-	u8 otp_page_start;
-	u8 otp_data_prot_addr;
-	u8 otp_num_pages;
-	u8 otp_feat_addr;
-	u8 read_retry_options;
-	u8 reserved[72];
-	u8 param_revision;
-} __packed;
-
 struct jedec_ecc_info {
 	u8 ecc_bits;
 	u8 codeword_size;
@@ -1161,6 +1141,7 @@ extern struct nand_manufacturers nand_manuf_ids[];
 extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
 extern const struct nand_manufacturer_ops samsung_nand_manuf_ops;
 extern const struct nand_manufacturer_ops hynix_nand_manuf_ops;
+extern const struct nand_manufacturer_ops micron_nand_manuf_ops;
 
 int nand_default_bbt(struct mtd_info *mtd);
 int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
-- 
2.34.1


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

* [PATCH V2 10/13] mtd: nand: Move AMD/Spansion specific init/detection logic in nand_amd.c
  2022-07-19 20:21 [PATCH V2 00/13] Port manufacturer specific initialization Michael Trimarchi
                   ` (8 preceding siblings ...)
  2022-07-19 20:21 ` [PATCH V2 09/13] mtd: nand: Move Micron specific init logic in nand_micron.c Michael Trimarchi
@ 2022-07-19 20:22 ` Michael Trimarchi
  2022-07-19 20:22 ` [PATCH V2 11/13] mtd: nand: Move Macronix specific initialization in nand_macronix.c Michael Trimarchi
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Michael Trimarchi @ 2022-07-19 20:22 UTC (permalink / raw)
  To: u-boot
  Cc: Dario Binacchi, Tommaso Merciai, Zhengxun Li, Patrice Chotard,
	Wolfgang Denk, Kory Maincent, Simon Glass, Pali Rohár

Upstream linux commit 229204da53

Move AMD/Spansion specific initialization/detection logic into
nand_amd.c. This is part of the "separate vendor specific code from
core" cleanup process.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- use short-commit form
	- remove linux info. Uboot seems that backport without add this
	  extra information
	- adjust the include file in nand_amd
---
 drivers/mtd/nand/raw/Makefile    |  4 ++-
 drivers/mtd/nand/raw/nand_amd.c  | 51 ++++++++++++++++++++++++++++++++
 drivers/mtd/nand/raw/nand_base.c | 17 +----------
 drivers/mtd/nand/raw/nand_ids.c  |  2 +-
 include/linux/mtd/rawnand.h      |  1 +
 5 files changed, 57 insertions(+), 18 deletions(-)
 create mode 100644 drivers/mtd/nand/raw/nand_amd.c

diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index e8fb451076..e1d511c12c 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -14,7 +14,8 @@ obj-$(CONFIG_SPL_NAND_DENALI) += denali_spl.o
 obj-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
 obj-$(CONFIG_SPL_NAND_LOAD) += nand_spl_load.o
 obj-$(CONFIG_SPL_NAND_ECC) += nand_ecc.o
-obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o nand_hynix.o nand_micron.o nand_samsung.o nand_toshiba.o
+obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o nand_amd.o nand_hynix.o nand_micron.o \
+				nand_samsung.o nand_toshiba.o
 obj-$(CONFIG_SPL_NAND_IDENT) += nand_ids.o nand_timings.o
 obj-$(CONFIG_TPL_NAND_INIT) += nand.o
 ifeq ($(CONFIG_SPL_ENV_SUPPORT),y)
@@ -31,6 +32,7 @@ obj-y += nand_ids.o
 obj-y += nand_util.o
 obj-y += nand_ecc.o
 obj-y += nand_base.o
+obj-y += nand_amd.o
 obj-y += nand_hynix.o
 obj-y += nand_micron.o
 obj-y += nand_samsung.o
diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
new file mode 100644
index 0000000000..22f060f381
--- /dev/null
+++ b/drivers/mtd/nand/raw/nand_amd.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 Free Electrons
+ * Copyright (C) 2017 NextThing Co
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mtd/rawnand.h>
+
+static void amd_nand_decode_id(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	nand_decode_ext_id(chip);
+
+	/*
+	 * Check for Spansion/AMD ID + repeating 5th, 6th byte since
+	 * some Spansion chips have erasesize that conflicts with size
+	 * listed in nand_ids table.
+	 * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
+	 */
+	if (chip->id.data[4] != 0x00 && chip->id.data[5] == 0x00 &&
+	    chip->id.data[6] == 0x00 && chip->id.data[7] == 0x00 &&
+	    mtd->writesize == 512) {
+		mtd->erasesize = 128 * 1024;
+		mtd->erasesize <<= ((chip->id.data[3] & 0x03) << 1);
+	}
+}
+
+static int amd_nand_init(struct nand_chip *chip)
+{
+	if (nand_is_slc(chip))
+		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+
+	return 0;
+}
+
+const struct nand_manufacturer_ops amd_nand_manuf_ops = {
+	.detect = amd_nand_decode_id,
+	.init = amd_nand_init,
+};
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index d2079c73fb..f79e57b9fb 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4201,7 +4201,6 @@ static void nand_decode_id(struct nand_chip *chip,
 				struct nand_flash_dev *type)
 {
 	struct mtd_info *mtd = &chip->mtd;
-	int maf_id = chip->id.data[0];
 
 	mtd->erasesize = type->erasesize;
 	mtd->writesize = type->pagesize;
@@ -4209,19 +4208,6 @@ static void nand_decode_id(struct nand_chip *chip,
 
 	/* All legacy ID NAND are small-page, SLC */
 	chip->bits_per_cell = 1;
-
-	/*
-	 * Check for Spansion/AMD ID + repeating 5th, 6th byte since
-	 * some Spansion chips have erasesize that conflicts with size
-	 * listed in nand_ids table.
-	 * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
-	 */
-	if (maf_id == NAND_MFR_AMD && chip->id.data[4] != 0x00 && chip->id.data[5] == 0x00
-			&& chip->id.data[6] == 0x00 && chip->id.data[7] == 0x00
-			&& mtd->writesize == 512) {
-		mtd->erasesize = 128 * 1024;
-		mtd->erasesize <<= ((chip->id.data[3] & 0x03) << 1);
-	}
 }
 
 /*
@@ -4246,8 +4232,7 @@ static void nand_decode_bbm_options(struct mtd_info *mtd,
 	 * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba,
 	 * AMD/Spansion, and Macronix.  All others scan only the first page.
 	 */
-	if (nand_is_slc(chip) &&
-	    (maf_id == NAND_MFR_AMD || maf_id == NAND_MFR_MACRONIX))
+	if (nand_is_slc(chip) && maf_id == NAND_MFR_MACRONIX)
 		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
 }
 
diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
index bb5ac8337f..c78f2e0880 100644
--- a/drivers/mtd/nand/raw/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
@@ -196,7 +196,7 @@ struct nand_manufacturers nand_manuf_ids[] = {
 	{NAND_MFR_STMICRO, "ST Micro"},
 	{NAND_MFR_HYNIX, "Hynix", &hynix_nand_manuf_ops},
 	{NAND_MFR_MICRON, "Micron", &micron_nand_manuf_ops},
-	{NAND_MFR_AMD, "AMD/Spansion"},
+	{NAND_MFR_AMD, "AMD/Spansion", &amd_nand_manuf_ops},
 	{NAND_MFR_MACRONIX, "Macronix"},
 	{NAND_MFR_EON, "Eon"},
 	{NAND_MFR_SANDISK, "SanDisk"},
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index ec0f77b24b..bb1a359a9c 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1142,6 +1142,7 @@ extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
 extern const struct nand_manufacturer_ops samsung_nand_manuf_ops;
 extern const struct nand_manufacturer_ops hynix_nand_manuf_ops;
 extern const struct nand_manufacturer_ops micron_nand_manuf_ops;
+extern const struct nand_manufacturer_ops amd_nand_manuf_ops;
 
 int nand_default_bbt(struct mtd_info *mtd);
 int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
-- 
2.34.1


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

* [PATCH V2 11/13] mtd: nand: Move Macronix specific initialization in nand_macronix.c
  2022-07-19 20:21 [PATCH V2 00/13] Port manufacturer specific initialization Michael Trimarchi
                   ` (9 preceding siblings ...)
  2022-07-19 20:22 ` [PATCH V2 10/13] mtd: nand: Move AMD/Spansion specific init/detection logic in nand_amd.c Michael Trimarchi
@ 2022-07-19 20:22 ` Michael Trimarchi
  2022-07-19 20:22 ` [PATCH V2 12/13] mtd: nand: toshiba: Retrieve ECC requirements from extended ID Michael Trimarchi
  2022-07-19 20:22 ` [PATCH V2 13/13] mtd: decommission the NAND museum Michael Trimarchi
  12 siblings, 0 replies; 14+ messages in thread
From: Michael Trimarchi @ 2022-07-19 20:22 UTC (permalink / raw)
  To: u-boot
  Cc: Dario Binacchi, Tommaso Merciai, Zhengxun Li, Patrice Chotard,
	Wolfgang Denk, Marek Behún, Pali Rohár, Kory Maincent,
	Simon Glass

Upstream linux commit 3b5206f4be

Move Macronix specific initialization logic into nand_macronix.c. This
is part of the "separate vendor specific code from core" cleanup
process.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- use short-commit form
	- remove linux info. Uboot seems that backport without add this
	  extra information
	- adjust the include file in nand_macronix
---
 drivers/mtd/nand/raw/Makefile        |  4 +++-
 drivers/mtd/nand/raw/nand_base.c     | 11 ----------
 drivers/mtd/nand/raw/nand_ids.c      |  2 +-
 drivers/mtd/nand/raw/nand_macronix.c | 30 ++++++++++++++++++++++++++++
 include/linux/mtd/rawnand.h          |  1 +
 5 files changed, 35 insertions(+), 13 deletions(-)
 create mode 100644 drivers/mtd/nand/raw/nand_macronix.c

diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index e1d511c12c..c8317a1078 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -14,7 +14,8 @@ obj-$(CONFIG_SPL_NAND_DENALI) += denali_spl.o
 obj-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
 obj-$(CONFIG_SPL_NAND_LOAD) += nand_spl_load.o
 obj-$(CONFIG_SPL_NAND_ECC) += nand_ecc.o
-obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o nand_amd.o nand_hynix.o nand_micron.o \
+obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o nand_amd.o nand_hynix.o \
+				nand_macronix.o nand_micron.o \
 				nand_samsung.o nand_toshiba.o
 obj-$(CONFIG_SPL_NAND_IDENT) += nand_ids.o nand_timings.o
 obj-$(CONFIG_TPL_NAND_INIT) += nand.o
@@ -34,6 +35,7 @@ obj-y += nand_ecc.o
 obj-y += nand_base.o
 obj-y += nand_amd.o
 obj-y += nand_hynix.o
+obj-y += nand_macronix.o
 obj-y += nand_micron.o
 obj-y += nand_samsung.o
 obj-y += nand_toshiba.o
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index f79e57b9fb..a38cc4d135 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4218,22 +4218,11 @@ static void nand_decode_id(struct nand_chip *chip,
 static void nand_decode_bbm_options(struct mtd_info *mtd,
 				    struct nand_chip *chip)
 {
-	int maf_id = chip->id.data[0];
-
 	/* Set the bad block position */
 	if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16))
 		chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
 	else
 		chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
-
-	/*
-	 * Bad block marker is stored in the last page of each block on Samsung
-	 * and Hynix MLC devices; stored in first two pages of each block on
-	 * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba,
-	 * AMD/Spansion, and Macronix.  All others scan only the first page.
-	 */
-	if (nand_is_slc(chip) && maf_id == NAND_MFR_MACRONIX)
-		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
 }
 
 static inline bool is_full_id_nand(struct nand_flash_dev *type)
diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
index c78f2e0880..7602dd30f1 100644
--- a/drivers/mtd/nand/raw/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
@@ -197,7 +197,7 @@ struct nand_manufacturers nand_manuf_ids[] = {
 	{NAND_MFR_HYNIX, "Hynix", &hynix_nand_manuf_ops},
 	{NAND_MFR_MICRON, "Micron", &micron_nand_manuf_ops},
 	{NAND_MFR_AMD, "AMD/Spansion", &amd_nand_manuf_ops},
-	{NAND_MFR_MACRONIX, "Macronix"},
+	{NAND_MFR_MACRONIX, "Macronix", &macronix_nand_manuf_ops},
 	{NAND_MFR_EON, "Eon"},
 	{NAND_MFR_SANDISK, "SanDisk"},
 	{NAND_MFR_INTEL, "Intel"},
diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c
new file mode 100644
index 0000000000..d290ff2a6d
--- /dev/null
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 Free Electrons
+ * Copyright (C) 2017 NextThing Co
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mtd/rawnand.h>
+
+static int macronix_nand_init(struct nand_chip *chip)
+{
+	if (nand_is_slc(chip))
+		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+
+	return 0;
+}
+
+const struct nand_manufacturer_ops macronix_nand_manuf_ops = {
+	.init = macronix_nand_init,
+};
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index bb1a359a9c..aa45558b3d 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1143,6 +1143,7 @@ extern const struct nand_manufacturer_ops samsung_nand_manuf_ops;
 extern const struct nand_manufacturer_ops hynix_nand_manuf_ops;
 extern const struct nand_manufacturer_ops micron_nand_manuf_ops;
 extern const struct nand_manufacturer_ops amd_nand_manuf_ops;
+extern const struct nand_manufacturer_ops macronix_nand_manuf_ops;
 
 int nand_default_bbt(struct mtd_info *mtd);
 int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
-- 
2.34.1


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

* [PATCH V2 12/13] mtd: nand: toshiba: Retrieve ECC requirements from extended ID
  2022-07-19 20:21 [PATCH V2 00/13] Port manufacturer specific initialization Michael Trimarchi
                   ` (10 preceding siblings ...)
  2022-07-19 20:22 ` [PATCH V2 11/13] mtd: nand: Move Macronix specific initialization in nand_macronix.c Michael Trimarchi
@ 2022-07-19 20:22 ` Michael Trimarchi
  2022-07-19 20:22 ` [PATCH V2 13/13] mtd: decommission the NAND museum Michael Trimarchi
  12 siblings, 0 replies; 14+ messages in thread
From: Michael Trimarchi @ 2022-07-19 20:22 UTC (permalink / raw)
  To: u-boot; +Cc: Dario Binacchi, Tommaso Merciai

Upstream linux commit fb3bff5b40

This patch enables support to read the ECC strength and size from the
NAND flash using Toshiba Memory SLC NAND extended-ID. This patch is
based on the information of the 6th ID byte of the Toshiba Memory SLC
NAND.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- use short-commit form
	- remove linux info. Uboot seems that backport without add this
	  extra information
---
 drivers/mtd/nand/raw/nand_toshiba.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index 4328e566b0..1adce3ebbd 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -36,6 +36,32 @@ static void toshiba_nand_decode_id(struct nand_chip *chip)
 	    (chip->id.data[5] & 0x7) == 0x6 /* 24nm */ &&
 	    !(chip->id.data[4] & 0x80) /* !BENAND */)
 		mtd->oobsize = 32 * mtd->writesize >> 9;
+
+	/*
+	 * Extract ECC requirements from 6th id byte.
+	 * For Toshiba SLC, ecc requrements are as follows:
+	 *  - 43nm: 1 bit ECC for each 512Byte is required.
+	 *  - 32nm: 4 bit ECC for each 512Byte is required.
+	 *  - 24nm: 8 bit ECC for each 512Byte is required.
+	 */
+	if (chip->id.len >= 6 && nand_is_slc(chip)) {
+		chip->ecc_step_ds = 512;
+		switch (chip->id.data[5] & 0x7) {
+		case 0x4:
+			chip->ecc_strength_ds = 1;
+			break;
+		case 0x5:
+			chip->ecc_strength_ds = 4;
+			break;
+		case 0x6:
+			chip->ecc_strength_ds = 8;
+			break;
+		default:
+			WARN(1, "Could not get ECC info");
+			chip->ecc_step_ds = 0;
+			break;
+		}
+	}
 }
 
 static int toshiba_nand_init(struct nand_chip *chip)
-- 
2.34.1


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

* [PATCH V2 13/13] mtd: decommission the NAND museum
  2022-07-19 20:21 [PATCH V2 00/13] Port manufacturer specific initialization Michael Trimarchi
                   ` (11 preceding siblings ...)
  2022-07-19 20:22 ` [PATCH V2 12/13] mtd: nand: toshiba: Retrieve ECC requirements from extended ID Michael Trimarchi
@ 2022-07-19 20:22 ` Michael Trimarchi
  12 siblings, 0 replies; 14+ messages in thread
From: Michael Trimarchi @ 2022-07-19 20:22 UTC (permalink / raw)
  To: u-boot; +Cc: Dario Binacchi, Tommaso Merciai, Wolfgang Denk

Upstream linux commit f7025a43a9

The MTD subsystem has its own small museum of ancient NANDs in a form of the
CONFIG_MTD_NAND_MUSEUM_IDS configuration option. The museum contains stone age
NANDs with 256 bytes pages, as well as iron age NANDs with 512 bytes per page
and up to 8MiB page size.

It is with great sorrow that I inform you that the museum is being
decommissioned. The MTD subsystem is out of budget for Kconfig options and
already has too many of them, and there is a general kernel trend to simplify
the configuration menu.

We remove the stone age exhibits along with closing the museum

REMARK Don't apply this part from upstream:

Some of the iron age ones are transferred to the regular NAND depot. Namely, only those
which have unique device IDs are transferred, and the ones which have
conflicting device IDs are removed.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V1->V2:
	- use short-commit form
	- remove linux info. Uboot seems that backport without add this
	  extra information
	- remove part of the patch because they will be removed anyway
	  later in linux
---
 drivers/mtd/nand/raw/nand_ids.c | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
index 7602dd30f1..4dece1b206 100644
--- a/drivers/mtd/nand/raw/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
@@ -24,16 +24,6 @@
  * extended chip ID.
  */
 struct nand_flash_dev nand_flash_ids[] = {
-#ifdef CONFIG_MTD_NAND_MUSEUM_IDS
-	LEGACY_ID_NAND("NAND 1MiB 5V 8-bit",	0x6e, 1, SZ_4K, SP_OPTIONS),
-	LEGACY_ID_NAND("NAND 2MiB 5V 8-bit",	0x64, 2, SZ_4K, SP_OPTIONS),
-	LEGACY_ID_NAND("NAND 1MiB 3,3V 8-bit",	0xe8, 1, SZ_4K, SP_OPTIONS),
-	LEGACY_ID_NAND("NAND 1MiB 3,3V 8-bit",	0xec, 1, SZ_4K, SP_OPTIONS),
-	LEGACY_ID_NAND("NAND 2MiB 3,3V 8-bit",	0xea, 2, SZ_4K, SP_OPTIONS),
-	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit",	0xd5, 4, SZ_8K, SP_OPTIONS),
-
-	LEGACY_ID_NAND("NAND 8MiB 3,3V 8-bit",	0xe6, 8, SZ_8K, SP_OPTIONS),
-#endif
 	/*
 	 * Some incompatible NAND chips share device ID's and so must be
 	 * listed by full ID. We list them first so that we can easily identify
-- 
2.34.1


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

end of thread, other threads:[~2022-07-19 20:25 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-19 20:21 [PATCH V2 00/13] Port manufacturer specific initialization Michael Trimarchi
2022-07-19 20:21 ` [PATCH V2 01/13] mtd: nand: Get rid of busw parameter Michael Trimarchi
2022-07-19 20:21 ` [PATCH V2 02/13] mtd: nand: Store nand ID in struct nand_chip Michael Trimarchi
2022-07-19 20:21 ` [PATCH V2 03/13] mtd: nand: Add manufacturer specific initialization/detection steps Michael Trimarchi
2022-07-19 20:21 ` [PATCH V2 04/13] mtd: nand: Get rid of mtd variable in function calls Michael Trimarchi
2022-07-19 20:21 ` [PATCH V2 05/13] mtd: nand: Export symbol nand_decode_ext_id Michael Trimarchi
2022-07-19 20:21 ` [PATCH V2 06/13] mtd: nand: Move Samsung specific init/detection logic in nand_samsung.c Michael Trimarchi
2022-07-19 20:21 ` [PATCH V2 07/13] mtd: nand: Move Hynix specific init/detection logic in nand_hynix.c Michael Trimarchi
2022-07-19 20:21 ` [PATCH V2 08/13] mtd: nand: Move Toshiba specific init/detection logic in nand_toshiba.c Michael Trimarchi
2022-07-19 20:21 ` [PATCH V2 09/13] mtd: nand: Move Micron specific init logic in nand_micron.c Michael Trimarchi
2022-07-19 20:22 ` [PATCH V2 10/13] mtd: nand: Move AMD/Spansion specific init/detection logic in nand_amd.c Michael Trimarchi
2022-07-19 20:22 ` [PATCH V2 11/13] mtd: nand: Move Macronix specific initialization in nand_macronix.c Michael Trimarchi
2022-07-19 20:22 ` [PATCH V2 12/13] mtd: nand: toshiba: Retrieve ECC requirements from extended ID Michael Trimarchi
2022-07-19 20:22 ` [PATCH V2 13/13] mtd: decommission the NAND museum Michael Trimarchi

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.