linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 00/28] Allow vendor drivers to propose their own timings
@ 2020-05-26 19:16 Miquel Raynal
  2020-05-26 19:16 ` [PATCH v5 01/28] mtd: rawnand: Use unsigned types for nand_chip unsigned values Miquel Raynal
                   ` (27 more replies)
  0 siblings, 28 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

As raised by Rickard, certain chips like Toshiba/Kioxia
TH58NVG2S3HBAI4 are not ONFI compliant and because of that, work at a
very slow pace. This chip in particular supports running at a pace
"close" to ONFI mode 4.

This series provides a way to manufacturer drivers to propose a data
interface to the core with a very simple interface and also improves
the core by allocating the data interface dynamically and use a static
default reset interface.

Cheers,
Miquèl

Changes in v5:
* Collected R-by tags.
* Dropped the rename of onfi_timing_mode_default, got rid of it instead.
* Converted Hynix and Toshiba drivers to ->choose_data_interface().
* Created a static default reset data interface object.
* Allocated dynamically the timings.
* Renamed onfi_find_closest_sdr_mode() and its parameter.
* Dropped the comparison with maximum values in
  onfi_find_closest_sdr_mode().
* Use "best_timings" instead of "best_iface" as DDR is not supported
  yet.
* Dropped choose_best_vendor_sdr_timings() and unifed its content with
  choose_best_sdr_timings().
* If the specific timing set close to ONFI mode X is not supported,
  fallback to ONFI mode X first, not X - 1.

Changes in v4:
* Took Rickard patch based on my previous proposals over Github and
  tweaked a few more things:
  - Added a "generic" helper to fallback on slower ONFI modes when the
    proposed interface is not supported by the controller.
  - Fixed more kdoc.
  - Simplified the vendor driver side by providing additional helpers.
* Tweaked a little bit Rickard patch to fit the latest changes.

Miquel Raynal (27):
  mtd: rawnand: Use unsigned types for nand_chip unsigned values
  mtd: rawnand: Only use u8 instead of uint8_t in nand_chip structure
  mtd: rawnand: Create a nand_chip operations structure
  mtd: rawnand: Rename the manufacturer structure
  mtd: rawnand: Declare the nand_manufacturer structure out of nand_chip
  mtd: rawnand: Reorganize the nand_chip structure
  mtd: rawnand: Compare the actual timing values
  mtd: rawnand: Use the data interface mode entry when relevant
  mtd: rawnand: Rename nand_has_setup_data_interface()
  mtd: rawnand: Fix nand_setup_data_interface() description
  mtd: rawnand: Rename nand_init_data_interface()
  mtd: rawnand: timings: Update onfi_fill_data_interface() kernel doc
  mtd: rawnand: timings: Provide onfi_fill_data_interface() with a data
    interface
  mtd: rawnand: timings: Add a helper to find the closest ONFI mode
  mtd: rawnand: timings: Avoid redefining tR_max and tCCS_min
  mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max
  mtd: rawnand: Define a unique reset data interface
  mtd: rawnand: marvell: Use a helper to access the timings
  mtd: rawnand: legacy: Use a helper to access the timings
  mtd: rawnand: Hide the chip->data_interface indirection
  mtd: rawnand: Introduce nand_choose_best_sdr_timings()
  mtd: rawnand: Add the ->choose_data_interface() hook
  mtd: rawnand: toshiba: Implement ->choose_data_interface() for
    TC58TEG5DCLTA00
  mtd: rawnand: toshiba: Implement ->choose_data_interface() for
    TC58NVG0S3E
  mtd: rawnand: hynix: Implement ->choose_data_interface() for
    H27UCG8T2ATR-BC
  mtd: rawnand: Get rid of the default ONFI timing mode
  mtd: rawnand: Allocate the best data interface structure dynamically

Rickard x Andersson (1):
  mtd: rawnand: toshiba: Choose the data interface for TH58NVG2S3HBAI4

 drivers/mtd/nand/raw/ams-delta.c              |   2 +-
 .../mtd/nand/raw/cadence-nand-controller.c    |   2 +-
 drivers/mtd/nand/raw/denali.c                 |   2 +-
 drivers/mtd/nand/raw/fsmc_nand.c              |   2 +-
 drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c    |   2 +-
 drivers/mtd/nand/raw/internals.h              |  14 +-
 drivers/mtd/nand/raw/marvell_nand.c           |  10 +-
 drivers/mtd/nand/raw/meson_nand.c             |   8 +-
 drivers/mtd/nand/raw/mtk_nand.c               |   2 +-
 drivers/mtd/nand/raw/mxc_nand.c               |   2 +-
 drivers/mtd/nand/raw/mxic_nand.c              |   2 +-
 drivers/mtd/nand/raw/nand_base.c              | 244 +++++++++--------
 drivers/mtd/nand/raw/nand_hynix.c             |  18 +-
 drivers/mtd/nand/raw/nand_ids.c               |  24 +-
 drivers/mtd/nand/raw/nand_legacy.c            |   6 +-
 drivers/mtd/nand/raw/nand_macronix.c          |  10 +-
 drivers/mtd/nand/raw/nand_micron.c            |   2 +-
 drivers/mtd/nand/raw/nand_timings.c           |  89 +++++--
 drivers/mtd/nand/raw/nand_toshiba.c           |  78 +++++-
 drivers/mtd/nand/raw/s3c2410.c                |   2 +-
 drivers/mtd/nand/raw/stm32_fmc2_nand.c        |   4 +-
 drivers/mtd/nand/raw/sunxi_nand.c             |   2 +-
 drivers/mtd/nand/raw/tango_nand.c             |   2 +-
 drivers/mtd/nand/raw/tegra_nand.c             |   2 +-
 include/linux/mtd/rawnand.h                   | 250 +++++++++---------
 25 files changed, 476 insertions(+), 305 deletions(-)

-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 01/28] mtd: rawnand: Use unsigned types for nand_chip unsigned values
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
@ 2020-05-26 19:16 ` Miquel Raynal
  2020-05-26 19:16 ` [PATCH v5 02/28] mtd: rawnand: Only use u8 instead of uint8_t in nand_chip structure Miquel Raynal
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

page_shift, phys_erase_shift, bbt_erase_shift, chip_shift, pagemask,
subpagesize and badblockbits are all positive values, so declare
them as unsigned.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 include/linux/mtd/rawnand.h | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 2804c13e5662..8a1e0192f78e 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1110,11 +1110,11 @@ struct nand_chip {
 	unsigned int options;
 	unsigned int bbt_options;
 
-	int page_shift;
-	int phys_erase_shift;
-	int bbt_erase_shift;
-	int chip_shift;
-	int pagemask;
+	unsigned int page_shift;
+	unsigned int phys_erase_shift;
+	unsigned int bbt_erase_shift;
+	unsigned int chip_shift;
+	unsigned int pagemask;
 	u8 *data_buf;
 
 	struct {
@@ -1122,10 +1122,10 @@ struct nand_chip {
 		int page;
 	} pagecache;
 
-	int subpagesize;
+	unsigned int subpagesize;
 	int onfi_timing_mode_default;
 	unsigned int badblockpos;
-	int badblockbits;
+	unsigned int badblockbits;
 
 	struct nand_id id;
 	struct nand_parameters parameters;
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 02/28] mtd: rawnand: Only use u8 instead of uint8_t in nand_chip structure
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
  2020-05-26 19:16 ` [PATCH v5 01/28] mtd: rawnand: Use unsigned types for nand_chip unsigned values Miquel Raynal
@ 2020-05-26 19:16 ` Miquel Raynal
  2020-05-26 19:17 ` [PATCH v5 03/28] mtd: rawnand: Create a nand_chip operations structure Miquel Raynal
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

Mechanical change to avoid using old types.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 include/linux/mtd/rawnand.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 8a1e0192f78e..7d62e0e719ac 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1141,13 +1141,13 @@ struct nand_chip {
 	int (*suspend)(struct nand_chip *chip);
 	void (*resume)(struct nand_chip *chip);
 
-	uint8_t *oob_poi;
+	u8 *oob_poi;
 	struct nand_controller *controller;
 
 	struct nand_ecc_ctrl ecc;
 	unsigned long buf_align;
 
-	uint8_t *bbt;
+	u8 *bbt;
 	struct nand_bbt_descr *bbt_td;
 	struct nand_bbt_descr *bbt_md;
 
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 03/28] mtd: rawnand: Create a nand_chip operations structure
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
  2020-05-26 19:16 ` [PATCH v5 01/28] mtd: rawnand: Use unsigned types for nand_chip unsigned values Miquel Raynal
  2020-05-26 19:16 ` [PATCH v5 02/28] mtd: rawnand: Only use u8 instead of uint8_t in nand_chip structure Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 19:17 ` [PATCH v5 04/28] mtd: rawnand: Rename the manufacturer structure Miquel Raynal
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

And move nand_chip hooks there.

While moving entries from one structure to the other, adapt the
documentation style.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/raw/nand_base.c     | 20 ++++++++---------
 drivers/mtd/nand/raw/nand_hynix.c    |  2 +-
 drivers/mtd/nand/raw/nand_macronix.c | 10 ++++-----
 drivers/mtd/nand/raw/nand_micron.c   |  2 +-
 include/linux/mtd/rawnand.h          | 32 ++++++++++++++++------------
 5 files changed, 35 insertions(+), 31 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 6a6a0a36b3fd..b86f641f6d74 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -3285,10 +3285,10 @@ static int nand_setup_read_retry(struct nand_chip *chip, int retry_mode)
 	if (retry_mode >= chip->read_retries)
 		return -EINVAL;
 
-	if (!chip->setup_read_retry)
+	if (!chip->ops.setup_read_retry)
 		return -EOPNOTSUPP;
 
-	return chip->setup_read_retry(chip, retry_mode);
+	return chip->ops.setup_read_retry(chip, retry_mode);
 }
 
 static void nand_wait_readrdy(struct nand_chip *chip)
@@ -4532,8 +4532,8 @@ static int nand_suspend(struct mtd_info *mtd)
 	int ret = 0;
 
 	mutex_lock(&chip->lock);
-	if (chip->suspend)
-		ret = chip->suspend(chip);
+	if (chip->ops.suspend)
+		ret = chip->ops.suspend(chip);
 	if (!ret)
 		chip->suspended = 1;
 	mutex_unlock(&chip->lock);
@@ -4551,8 +4551,8 @@ static void nand_resume(struct mtd_info *mtd)
 
 	mutex_lock(&chip->lock);
 	if (chip->suspended) {
-		if (chip->resume)
-			chip->resume(chip);
+		if (chip->ops.resume)
+			chip->ops.resume(chip);
 		chip->suspended = 0;
 	} else {
 		pr_err("%s called for a chip which is not in suspended state\n",
@@ -4581,10 +4581,10 @@ static int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 
-	if (!chip->lock_area)
+	if (!chip->ops.lock_area)
 		return -ENOTSUPP;
 
-	return chip->lock_area(chip, ofs, len);
+	return chip->ops.lock_area(chip, ofs, len);
 }
 
 /**
@@ -4597,10 +4597,10 @@ static int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 
-	if (!chip->unlock_area)
+	if (!chip->ops.unlock_area)
 		return -ENOTSUPP;
 
-	return chip->unlock_area(chip, ofs, len);
+	return chip->ops.unlock_area(chip, ofs, len);
 }
 
 /* Set default functions */
diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
index 7caedaa5b9e5..7d1be53f27f3 100644
--- a/drivers/mtd/nand/raw/nand_hynix.c
+++ b/drivers/mtd/nand/raw/nand_hynix.c
@@ -337,7 +337,7 @@ static int hynix_mlc_1xnm_rr_init(struct nand_chip *chip,
 	rr->nregs = nregs;
 	rr->regs = hynix_1xnm_mlc_read_retry_regs;
 	hynix->read_retry = rr;
-	chip->setup_read_retry = hynix_nand_setup_read_retry;
+	chip->ops.setup_read_retry = hynix_nand_setup_read_retry;
 	chip->read_retries = nmodes;
 
 out:
diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c
index 09c254c97b5c..1472f925f386 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -130,7 +130,7 @@ static void macronix_nand_onfi_init(struct nand_chip *chip)
 		return;
 
 	chip->read_retries = MACRONIX_NUM_READ_RETRY_MODES;
-	chip->setup_read_retry = macronix_nand_setup_read_retry;
+	chip->ops.setup_read_retry = macronix_nand_setup_read_retry;
 
 	if (p->supports_set_get_features) {
 		bitmap_set(p->set_feature_list,
@@ -242,8 +242,8 @@ static void macronix_nand_block_protection_support(struct nand_chip *chip)
 	bitmap_set(chip->parameters.set_feature_list,
 		   ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1);
 
-	chip->lock_area = mxic_nand_lock;
-	chip->unlock_area = mxic_nand_unlock;
+	chip->ops.lock_area = mxic_nand_lock;
+	chip->ops.unlock_area = mxic_nand_unlock;
 }
 
 static int nand_power_down_op(struct nand_chip *chip)
@@ -312,8 +312,8 @@ static void macronix_nand_deep_power_down_support(struct nand_chip *chip)
 	if (i < 0)
 		return;
 
-	chip->suspend = mxic_nand_suspend;
-	chip->resume = mxic_nand_resume;
+	chip->ops.suspend = mxic_nand_suspend;
+	chip->ops.resume = mxic_nand_resume;
 }
 
 static int macronix_nand_init(struct nand_chip *chip)
diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
index 3589b4fce0d4..4385092a9325 100644
--- a/drivers/mtd/nand/raw/nand_micron.c
+++ b/drivers/mtd/nand/raw/nand_micron.c
@@ -84,7 +84,7 @@ static int micron_nand_onfi_init(struct nand_chip *chip)
 		struct nand_onfi_vendor_micron *micron = (void *)p->onfi->vendor;
 
 		chip->read_retries = micron->read_retry_options;
-		chip->setup_read_retry = micron_nand_setup_read_retry;
+		chip->ops.setup_read_retry = micron_nand_setup_read_retry;
 	}
 
 	if (p->supports_set_get_features) {
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 7d62e0e719ac..b33cd68852c4 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1027,16 +1027,31 @@ struct nand_legacy {
 	struct nand_controller dummy_controller;
 };
 
+/**
+ * struct nand_chip_ops - NAND chip operations
+ * @suspend: Suspend operation
+ * @resume: Resume operation
+ * @lock_area: Lock operation
+ * @unlock_area: Unlock operation
+ * @setup_read_retry: Set the read-retry mode (mostly needed for MLC NANDs)
+ */
+struct nand_chip_ops {
+	int (*suspend)(struct nand_chip *chip);
+	void (*resume)(struct nand_chip *chip);
+	int (*lock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
+	int (*unlock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
+	int (*setup_read_retry)(struct nand_chip *chip, int retry_mode);
+};
+
 /**
  * struct nand_chip - NAND Private Flash Chip Data
  * @base:		Inherit from the generic NAND device
+ * @ops:		NAND chip operations
  * @legacy:		All legacy fields/hooks. If you develop a new driver,
  *			don't even try to use any of these fields/hooks, and if
  *			you're modifying an existing driver that is using those
  *			fields/hooks, you should consider reworking the driver
  *			avoid using them.
- * @setup_read_retry:	[FLASHSPECIFIC] flash (vendor) specific function for
- *			setting the read-retry mode. Mostly needed for MLC NAND.
  * @ecc:		[BOARDSPECIFIC] ECC control structure
  * @buf_align:		minimum buffer alignment required by a platform
  * @oob_poi:		"poison value buffer," used for laying out OOB data
@@ -1081,8 +1096,6 @@ struct nand_legacy {
  * @lock:		lock protecting the suspended field. Also used to
  *			serialize accesses to the NAND device.
  * @suspended:		set to 1 when the device is suspended, 0 when it's not.
- * @suspend:		[REPLACEABLE] specific NAND device suspend operation
- * @resume:		[REPLACEABLE] specific NAND device resume operation
  * @bbt:		[INTERN] bad block table pointer
  * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash
  *			lookup.
@@ -1096,17 +1109,13 @@ struct nand_legacy {
  * @manufacturer:	[INTERN] Contains manufacturer information
  * @manufacturer.desc:	[INTERN] Contains manufacturer's description
  * @manufacturer.priv:	[INTERN] Contains manufacturer private information
- * @lock_area:		[REPLACEABLE] specific NAND chip lock operation
- * @unlock_area:	[REPLACEABLE] specific NAND chip unlock operation
  */
 
 struct nand_chip {
 	struct nand_device base;
-
+	struct nand_chip_ops ops;
 	struct nand_legacy legacy;
 
-	int (*setup_read_retry)(struct nand_chip *chip, int retry_mode);
-
 	unsigned int options;
 	unsigned int bbt_options;
 
@@ -1138,8 +1147,6 @@ struct nand_chip {
 
 	struct mutex lock;
 	unsigned int suspended : 1;
-	int (*suspend)(struct nand_chip *chip);
-	void (*resume)(struct nand_chip *chip);
 
 	u8 *oob_poi;
 	struct nand_controller *controller;
@@ -1159,9 +1166,6 @@ struct nand_chip {
 		const struct nand_manufacturer *desc;
 		void *priv;
 	} manufacturer;
-
-	int (*lock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
-	int (*unlock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
 };
 
 extern const struct mtd_ooblayout_ops nand_ooblayout_sp_ops;
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 04/28] mtd: rawnand: Rename the manufacturer structure
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (2 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 03/28] mtd: rawnand: Create a nand_chip operations structure Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 19:17 ` [PATCH v5 05/28] mtd: rawnand: Declare the nand_manufacturer structure out of nand_chip Miquel Raynal
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

It is currently called nand_manufacturer but could actually be called
nand_manufacturer_desc, like its instances, so that the former name is
left unused for now.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/raw/internals.h |  6 +++---
 drivers/mtd/nand/raw/nand_base.c | 14 +++++++-------
 drivers/mtd/nand/raw/nand_ids.c  | 16 ++++++++--------
 include/linux/mtd/rawnand.h      |  2 +-
 4 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index 03866b0aadea..a518acfd9b3f 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -53,12 +53,12 @@ struct nand_manufacturer_ops {
 };
 
 /**
- * struct nand_manufacturer - NAND Flash Manufacturer structure
+ * struct nand_manufacturer_desc - NAND Flash Manufacturer descriptor
  * @name: Manufacturer name
  * @id: manufacturer ID code of device.
  * @ops: manufacturer operations
  */
-struct nand_manufacturer {
+struct nand_manufacturer_desc {
 	int id;
 	char *name;
 	const struct nand_manufacturer_ops *ops;
@@ -79,7 +79,7 @@ extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
 extern const struct mtd_pairing_scheme dist3_pairing_scheme;
 
 /* Core functions */
-const struct nand_manufacturer *nand_get_manufacturer(u8 id);
+const struct nand_manufacturer_desc *nand_get_manufacturer_desc(u8 id);
 int nand_bbm_get_next_page(struct nand_chip *chip, int page);
 int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs);
 int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index b86f641f6d74..14f1359a60b8 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4880,9 +4880,9 @@ static void nand_manufacturer_cleanup(struct nand_chip *chip)
 }
 
 static const char *
-nand_manufacturer_name(const struct nand_manufacturer *manufacturer)
+nand_manufacturer_name(const struct nand_manufacturer_desc *manufacturer_desc)
 {
-	return manufacturer ? manufacturer->name : "Unknown";
+	return manufacturer_desc ? manufacturer_desc->name : "Unknown";
 }
 
 /*
@@ -4890,7 +4890,7 @@ nand_manufacturer_name(const struct nand_manufacturer *manufacturer)
  */
 static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
 {
-	const struct nand_manufacturer *manufacturer;
+	const struct nand_manufacturer_desc *manufacturer_desc;
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct nand_memory_organization *memorg;
 	int busw, ret;
@@ -4947,8 +4947,8 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
 	chip->id.len = nand_id_len(id_data, ARRAY_SIZE(chip->id.data));
 
 	/* Try to identify manufacturer */
-	manufacturer = nand_get_manufacturer(maf_id);
-	chip->manufacturer.desc = manufacturer;
+	manufacturer_desc = nand_get_manufacturer_desc(maf_id);
+	chip->manufacturer.desc = manufacturer_desc;
 
 	if (!type)
 		type = nand_flash_ids;
@@ -5027,7 +5027,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
 		 */
 		pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
 			maf_id, dev_id);
-		pr_info("%s %s\n", nand_manufacturer_name(manufacturer),
+		pr_info("%s %s\n", nand_manufacturer_name(manufacturer_desc),
 			mtd->name);
 		pr_warn("bus width %d instead of %d bits\n", busw ? 16 : 8,
 			(chip->options & NAND_BUSWIDTH_16) ? 16 : 8);
@@ -5062,7 +5062,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
 
 	pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
 		maf_id, dev_id);
-	pr_info("%s %s\n", nand_manufacturer_name(manufacturer),
+	pr_info("%s %s\n", nand_manufacturer_name(manufacturer_desc),
 		chip->parameters.model);
 	pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n",
 		(int)(targetsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
index ba27902fc54b..e0dbc2e316c7 100644
--- a/drivers/mtd/nand/raw/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
@@ -166,7 +166,7 @@ struct nand_flash_dev nand_flash_ids[] = {
 };
 
 /* Manufacturer IDs */
-static const struct nand_manufacturer nand_manufacturers[] = {
+static const struct nand_manufacturer_desc nand_manufacturer_descs[] = {
 	{NAND_MFR_AMD, "AMD/Spansion", &amd_nand_manuf_ops},
 	{NAND_MFR_ATO, "ATO"},
 	{NAND_MFR_EON, "Eon"},
@@ -186,20 +186,20 @@ static const struct nand_manufacturer nand_manufacturers[] = {
 };
 
 /**
- * nand_get_manufacturer - Get manufacturer information from the manufacturer
- *			   ID
+ * nand_get_manufacturer_desc - Get manufacturer information from the
+ *                              manufacturer ID
  * @id: manufacturer ID
  *
- * Returns a pointer a nand_manufacturer object if the manufacturer is defined
+ * Returns a nand_manufacturer_desc object if the manufacturer is defined
  * in the NAND manufacturers database, NULL otherwise.
  */
-const struct nand_manufacturer *nand_get_manufacturer(u8 id)
+const struct nand_manufacturer_desc *nand_get_manufacturer_desc(u8 id)
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(nand_manufacturers); i++)
-		if (nand_manufacturers[i].id == id)
-			return &nand_manufacturers[i];
+	for (i = 0; i < ARRAY_SIZE(nand_manufacturer_descs); i++)
+		if (nand_manufacturer_descs[i].id == id)
+			return &nand_manufacturer_descs[i];
 
 	return NULL;
 }
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index b33cd68852c4..d8492d966b40 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1163,7 +1163,7 @@ struct nand_chip {
 	void *priv;
 
 	struct {
-		const struct nand_manufacturer *desc;
+		const struct nand_manufacturer_desc *desc;
 		void *priv;
 	} manufacturer;
 };
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 05/28] mtd: rawnand: Declare the nand_manufacturer structure out of nand_chip
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (3 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 04/28] mtd: rawnand: Rename the manufacturer structure Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 19:17 ` [PATCH v5 06/28] mtd: rawnand: Reorganize the nand_chip structure Miquel Raynal
                   ` (22 subsequent siblings)
  27 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

Now that struct nand_manufacturer type is free, use it to store the
nand_manufacturer_desc and the manufacturer's private data.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 include/linux/mtd/rawnand.h | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index d8492d966b40..2a9b5d5b315b 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1043,10 +1043,21 @@ struct nand_chip_ops {
 	int (*setup_read_retry)(struct nand_chip *chip, int retry_mode);
 };
 
+/**
+ * struct nand_manufacturer - NAND manufacturer structure
+ * @desc: The manufacturer description
+ * @priv: Private information for the manufacturer driver
+ */
+struct nand_manufacturer {
+	const struct nand_manufacturer_desc *desc;
+	void *priv;
+};
+
 /**
  * struct nand_chip - NAND Private Flash Chip Data
  * @base:		Inherit from the generic NAND device
  * @ops:		NAND chip operations
+ * @manufacturer:	Manufacturer information
  * @legacy:		All legacy fields/hooks. If you develop a new driver,
  *			don't even try to use any of these fields/hooks, and if
  *			you're modifying an existing driver that is using those
@@ -1106,13 +1117,11 @@ struct nand_chip_ops {
  *			structure which is shared among multiple independent
  *			devices.
  * @priv:		[OPTIONAL] pointer to private chip data
- * @manufacturer:	[INTERN] Contains manufacturer information
- * @manufacturer.desc:	[INTERN] Contains manufacturer's description
- * @manufacturer.priv:	[INTERN] Contains manufacturer private information
  */
 
 struct nand_chip {
 	struct nand_device base;
+	struct nand_manufacturer manufacturer;
 	struct nand_chip_ops ops;
 	struct nand_legacy legacy;
 
@@ -1161,11 +1170,6 @@ struct nand_chip {
 	struct nand_bbt_descr *badblock_pattern;
 
 	void *priv;
-
-	struct {
-		const struct nand_manufacturer_desc *desc;
-		void *priv;
-	} manufacturer;
 };
 
 extern const struct mtd_ooblayout_ops nand_ooblayout_sp_ops;
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 06/28] mtd: rawnand: Reorganize the nand_chip structure
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (4 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 05/28] mtd: rawnand: Declare the nand_manufacturer structure out of nand_chip Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 19:17 ` [PATCH v5 07/28] mtd: rawnand: Compare the actual timing values Miquel Raynal
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

Reorder fields in this structure and pack entries by theme:
* The main descriptive structures
* The data interface details
* Bad block information
* The device layout
* Extra buffers matching the device layout
* Internal values
* External objects like the ECC controller, the ECC engine and a
  private data pointer.

While at it, adapt the documentation style.

I changed on purpose the description of @oob_poi which was weird.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 include/linux/mtd/rawnand.h | 166 +++++++++++++++++-------------------
 1 file changed, 76 insertions(+), 90 deletions(-)

diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 2a9b5d5b315b..622da6527a36 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1055,120 +1055,106 @@ struct nand_manufacturer {
 
 /**
  * struct nand_chip - NAND Private Flash Chip Data
- * @base:		Inherit from the generic NAND device
- * @ops:		NAND chip operations
- * @manufacturer:	Manufacturer information
- * @legacy:		All legacy fields/hooks. If you develop a new driver,
- *			don't even try to use any of these fields/hooks, and if
- *			you're modifying an existing driver that is using those
- *			fields/hooks, you should consider reworking the driver
- *			avoid using them.
- * @ecc:		[BOARDSPECIFIC] ECC control structure
- * @buf_align:		minimum buffer alignment required by a platform
- * @oob_poi:		"poison value buffer," used for laying out OOB data
- *			before writing
- * @page_shift:		[INTERN] number of address bits in a page (column
- *			address bits).
- * @phys_erase_shift:	[INTERN] number of address bits in a physical eraseblock
- * @bbt_erase_shift:	[INTERN] number of address bits in a bbt entry
- * @chip_shift:		[INTERN] number of address bits in one chip
- * @options:		[BOARDSPECIFIC] various chip options. They can partly
- *			be set to inform nand_scan about special functionality.
- *			See the defines for further explanation.
- * @bbt_options:	[INTERN] bad block specific options. All options used
- *			here must come from bbm.h. By default, these options
- *			will be copied to the appropriate nand_bbt_descr's.
- * @badblockpos:	[INTERN] position of the bad block marker in the oob
- *			area.
- * @badblockbits:	[INTERN] minimum number of set bits in a good block's
- *			bad block marker position; i.e., BBM == 11110111b is
- *			not bad when badblockbits == 7
- * @onfi_timing_mode_default: [INTERN] default ONFI timing mode. This field is
- *			      set to the actually used ONFI mode if the chip is
- *			      ONFI compliant or deduced from the datasheet if
- *			      the NAND chip is not ONFI compliant.
- * @pagemask:		[INTERN] page number mask = number of (pages / chip) - 1
- * @data_buf:		[INTERN] buffer for data, size is (page size + oobsize).
- * @pagecache:		Structure containing page cache related fields
- * @pagecache.bitflips:	Number of bitflips of the cached page
- * @pagecache.page:	Page number currently in the cache. -1 means no page is
- *			currently cached
- * @subpagesize:	[INTERN] holds the subpagesize
- * @id:			[INTERN] holds NAND ID
- * @parameters:		[INTERN] holds generic parameters under an easily
- *			readable form.
- * @data_interface:	[INTERN] NAND interface timing information
- * @cur_cs:		currently selected target. -1 means no target selected,
- *			otherwise we should always have cur_cs >= 0 &&
- *			cur_cs < nanddev_ntargets(). NAND Controller drivers
- *			should not modify this value, but they're allowed to
- *			read it.
- * @read_retries:	[INTERN] the number of read retry modes supported
- * @lock:		lock protecting the suspended field. Also used to
- *			serialize accesses to the NAND device.
- * @suspended:		set to 1 when the device is suspended, 0 when it's not.
- * @bbt:		[INTERN] bad block table pointer
- * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash
- *			lookup.
- * @bbt_md:		[REPLACEABLE] bad block table mirror descriptor
- * @badblock_pattern:	[REPLACEABLE] bad block scan pattern used for initial
- *			bad block scan.
- * @controller:		[REPLACEABLE] a pointer to a hardware controller
- *			structure which is shared among multiple independent
- *			devices.
- * @priv:		[OPTIONAL] pointer to private chip data
+ * @base: Inherit from the generic NAND device
+ * @id: Holds NAND ID
+ * @parameters: Holds generic parameters under an easily readable form
+ * @manufacturer: Manufacturer information
+ * @ops: NAND chip operations
+ * @legacy: All legacy fields/hooks. If you develop a new driver, don't even try
+ *          to use any of these fields/hooks, and if you're modifying an
+ *          existing driver that is using those fields/hooks, you should
+ *          consider reworking the driver and avoid using them.
+ * @options: Various chip options. They can partly be set to inform nand_scan
+ *           about special functionality. See the defines for further
+ *           explanation.
+ * @onfi_timing_mode_default: Default ONFI timing mode. This field is set to the
+ *			      actually used ONFI mode if the chip is ONFI
+ *			      compliant or deduced from the datasheet otherwise
+ * @data_interface: NAND interface timing information
+ * @bbt_erase_shift: Number of address bits in a bbt entry
+ * @bbt_options: Bad block table specific options. All options used here must
+ *               come from bbm.h. By default, these options will be copied to
+ *               the appropriate nand_bbt_descr's.
+ * @badblockpos: Bad block marker position in the oob area
+ * @badblockbits: Minimum number of set bits in a good block's bad block marker
+ *                position; i.e., BBM = 11110111b is good when badblockbits = 7
+ * @bbt_td: Bad block table descriptor for flash lookup
+ * @bbt_md: Bad block table mirror descriptor
+ * @badblock_pattern: Bad block scan pattern used for initial bad block scan
+ * @bbt: Bad block table pointer
+ * @page_shift: Number of address bits in a page (column address bits)
+ * @phys_erase_shift: Number of address bits in a physical eraseblock
+ * @chip_shift: Number of address bits in one chip
+ * @pagemask: Page number mask = number of (pages / chip) - 1
+ * @subpagesize: Holds the subpagesize
+ * @data_buf: Buffer for data, size is (page size + oobsize)
+ * @oob_poi: pointer on the OOB area covered by data_buf
+ * @pagecache: Structure containing page cache related fields
+ * @pagecache.bitflips: Number of bitflips of the cached page
+ * @pagecache.page: Page number currently in the cache. -1 means no page is
+ *                  currently cached
+ * @buf_align: Minimum buffer alignment required by a platform
+ * @lock: Lock protecting the suspended field. Also used to serialize accesses
+ *        to the NAND device
+ * @suspended: Set to 1 when the device is suspended, 0 when it's not
+ * @cur_cs: Currently selected target. -1 means no target selected, otherwise we
+ *          should always have cur_cs >= 0 && cur_cs < nanddev_ntargets().
+ *          NAND Controller drivers should not modify this value, but they're
+ *          allowed to read it.
+ * @read_retries: The number of read retry modes supported
+ * @controller: The hardware controller	structure which is shared among multiple
+ *              independent devices
+ * @ecc: The ECC controller structure
+ * @priv: Chip private data
  */
-
 struct nand_chip {
 	struct nand_device base;
+	struct nand_id id;
+	struct nand_parameters parameters;
 	struct nand_manufacturer manufacturer;
 	struct nand_chip_ops ops;
 	struct nand_legacy legacy;
-
 	unsigned int options;
+
+	/* Data interface */
+	int onfi_timing_mode_default;
+	struct nand_data_interface data_interface;
+
+	/* Bad block information */
+	unsigned int bbt_erase_shift;
 	unsigned int bbt_options;
+	unsigned int badblockpos;
+	unsigned int badblockbits;
+	struct nand_bbt_descr *bbt_td;
+	struct nand_bbt_descr *bbt_md;
+	struct nand_bbt_descr *badblock_pattern;
+	u8 *bbt;
 
+	/* Device internal layout */
 	unsigned int page_shift;
 	unsigned int phys_erase_shift;
-	unsigned int bbt_erase_shift;
 	unsigned int chip_shift;
 	unsigned int pagemask;
+	unsigned int subpagesize;
+
+	/* Buffers */
 	u8 *data_buf;
-
+	u8 *oob_poi;
 	struct {
 		unsigned int bitflips;
 		int page;
 	} pagecache;
+	unsigned long buf_align;
 
-	unsigned int subpagesize;
-	int onfi_timing_mode_default;
-	unsigned int badblockpos;
-	unsigned int badblockbits;
-
-	struct nand_id id;
-	struct nand_parameters parameters;
-
-	struct nand_data_interface data_interface;
-
+	/* Internals */
+	struct mutex lock;
+	unsigned int suspended : 1;
 	int cur_cs;
-
 	int read_retries;
 
-	struct mutex lock;
-	unsigned int suspended : 1;
-
-	u8 *oob_poi;
+	/* Externals */
 	struct nand_controller *controller;
-
 	struct nand_ecc_ctrl ecc;
-	unsigned long buf_align;
-
-	u8 *bbt;
-	struct nand_bbt_descr *bbt_td;
-	struct nand_bbt_descr *bbt_md;
-
-	struct nand_bbt_descr *badblock_pattern;
-
 	void *priv;
 };
 
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 07/28] mtd: rawnand: Compare the actual timing values
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (5 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 06/28] mtd: rawnand: Reorganize the nand_chip structure Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 19:17 ` [PATCH v5 08/28] mtd: rawnand: Use the data interface mode entry when relevant Miquel Raynal
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

Avoid relying just on the default timing mode to discriminate if the
data interface must be restored. This field should only be used
at initialization time by legacy chips statically defined. Do a
memcmp() instead.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/raw/nand_base.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 14f1359a60b8..7567c973964b 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -2512,7 +2512,8 @@ int nand_reset(struct nand_chip *chip, int chipnr)
 	 * nand_setup_data_interface() uses ->set/get_features() which would
 	 * fail anyway as the parameter page is not available yet.
 	 */
-	if (!chip->onfi_timing_mode_default)
+	if (!memcmp(&chip->data_interface, &saved_data_intf,
+		    sizeof(saved_data_intf)))
 		return 0;
 
 	chip->data_interface = saved_data_intf;
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 08/28] mtd: rawnand: Use the data interface mode entry when relevant
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (6 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 07/28] mtd: rawnand: Compare the actual timing values Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 19:17 ` [PATCH v5 09/28] mtd: rawnand: Rename nand_has_setup_data_interface() Miquel Raynal
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

The data interface setup does not care about the default timing mode
but cares about the actual timing mode at the time of the call of this
helper.

Use this entry instead and let chip->default_timing_mode only be used
at initialization time.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/raw/nand_base.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 7567c973964b..6a6af0b19fec 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -951,9 +951,8 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
  */
 static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
 {
-	u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = {
-		chip->onfi_timing_mode_default,
-	};
+	u8 mode = chip->data_interface.timings.mode;
+	u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { mode, };
 	int ret;
 
 	if (!nand_has_setup_data_iface(chip))
@@ -987,9 +986,9 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
 	if (ret)
 		goto err_reset_chip;
 
-	if (tmode_param[0] != chip->onfi_timing_mode_default) {
+	if (tmode_param[0] != mode) {
 		pr_warn("timing mode %d not acknowledged by the NAND chip\n",
-			chip->onfi_timing_mode_default);
+			mode);
 		goto err_reset_chip;
 	}
 
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 09/28] mtd: rawnand: Rename nand_has_setup_data_interface()
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (7 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 08/28] mtd: rawnand: Use the data interface mode entry when relevant Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 19:17 ` [PATCH v5 10/28] mtd: rawnand: Fix nand_setup_data_interface() description Miquel Raynal
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

This is really a NAND controller hook so call it
nand_controller_has_setup_data_interface(), which makes much more
sense.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/raw/internals.h   | 2 +-
 drivers/mtd/nand/raw/nand_base.c   | 6 +++---
 drivers/mtd/nand/raw/nand_legacy.c | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index a518acfd9b3f..347d42c55353 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -130,7 +130,7 @@ static inline int nand_exec_op(struct nand_chip *chip,
 	return chip->controller->ops->exec_op(chip, op, false);
 }
 
-static inline bool nand_has_setup_data_iface(struct nand_chip *chip)
+static inline bool nand_controller_has_setup_data_iface(struct nand_chip *chip)
 {
 	if (!chip->controller || !chip->controller->ops ||
 	    !chip->controller->ops->setup_data_interface)
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 6a6af0b19fec..8e2c5f52ae6b 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -910,7 +910,7 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
 {
 	int ret;
 
-	if (!nand_has_setup_data_iface(chip))
+	if (!nand_controller_has_setup_data_iface(chip))
 		return 0;
 
 	/*
@@ -955,7 +955,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
 	u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { mode, };
 	int ret;
 
-	if (!nand_has_setup_data_iface(chip))
+	if (!nand_controller_has_setup_data_iface(chip))
 		return 0;
 
 	/* Change the mode on the chip side (if supported by the NAND chip) */
@@ -1025,7 +1025,7 @@ static int nand_init_data_interface(struct nand_chip *chip)
 {
 	int modes, mode, ret;
 
-	if (!nand_has_setup_data_iface(chip))
+	if (!nand_controller_has_setup_data_iface(chip))
 		return 0;
 
 	/*
diff --git a/drivers/mtd/nand/raw/nand_legacy.c b/drivers/mtd/nand/raw/nand_legacy.c
index d64791c06a97..8b91aa7773d8 100644
--- a/drivers/mtd/nand/raw/nand_legacy.c
+++ b/drivers/mtd/nand/raw/nand_legacy.c
@@ -365,7 +365,7 @@ static void nand_ccs_delay(struct nand_chip *chip)
 	 * Wait tCCS_min if it is correctly defined, otherwise wait 500ns
 	 * (which should be safe for all NANDs).
 	 */
-	if (nand_has_setup_data_iface(chip))
+	if (nand_controller_has_setup_data_iface(chip))
 		ndelay(chip->data_interface.timings.sdr.tCCS_min / 1000);
 	else
 		ndelay(500);
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 10/28] mtd: rawnand: Fix nand_setup_data_interface() description
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (8 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 09/28] mtd: rawnand: Rename nand_has_setup_data_interface() Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 19:17 ` [PATCH v5 11/28] mtd: rawnand: Rename nand_init_data_interface() Miquel Raynal
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

This is a copy/paste error and belongs to nand_init_data_interface()
description.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/raw/nand_base.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 8e2c5f52ae6b..d2313ea49768 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -941,11 +941,8 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
  * @chip: The NAND chip
  * @chipnr: Internal die id
  *
- * Find and configure the best data interface and NAND timings supported by
- * the chip and the driver.
- * First tries to retrieve supported timing modes from ONFI information,
- * and if the NAND chip does not support ONFI, relies on the
- * ->onfi_timing_mode_default specified in the nand_ids table.
+ * Configure what has been reported to be the best data interface and NAND
+ * timings supported by the chip and the driver.
  *
  * Returns 0 for success or negative error code otherwise.
  */
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 11/28] mtd: rawnand: Rename nand_init_data_interface()
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (9 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 10/28] mtd: rawnand: Fix nand_setup_data_interface() description Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 19:17 ` [PATCH v5 12/28] mtd: rawnand: timings: Update onfi_fill_data_interface() kernel doc Miquel Raynal
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

This name is a bit misleading, what we do in this helper is trying to
find the best SDR timings supported by the controller and the chip.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/raw/nand_base.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index d2313ea49768..9b94552fb177 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -1005,7 +1005,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
 }
 
 /**
- * nand_init_data_interface - find the best data interface and timings
+ * nand_choose_data_interface - find the best data interface and timings
  * @chip: The NAND chip
  *
  * Find the best data interface and NAND timings supported by the chip
@@ -1018,7 +1018,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
  *
  * Returns 0 for success or negative error code otherwise.
  */
-static int nand_init_data_interface(struct nand_chip *chip)
+static int nand_choose_data_interface(struct nand_chip *chip)
 {
 	int modes, mode, ret;
 
@@ -6047,8 +6047,8 @@ static int nand_scan_tail(struct nand_chip *chip)
 	if (!mtd->bitflip_threshold)
 		mtd->bitflip_threshold = DIV_ROUND_UP(mtd->ecc_strength * 3, 4);
 
-	/* Initialize the ->data_interface field. */
-	ret = nand_init_data_interface(chip);
+	/* Find the fastest data interface for this chip */
+	ret = nand_choose_data_interface(chip);
 	if (ret)
 		goto err_nanddev_cleanup;
 
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 12/28] mtd: rawnand: timings: Update onfi_fill_data_interface() kernel doc
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (10 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 11/28] mtd: rawnand: Rename nand_init_data_interface() Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 19:17 ` [PATCH v5 13/28] mtd: rawnand: timings: Provide onfi_fill_data_interface() with a data interface Miquel Raynal
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

Describe all parameters and drop the legacy [NAND Interface] prefix.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/raw/nand_timings.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
index 36d21be3dfe5..a73d934e86f9 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -274,9 +274,10 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
 };
 
 /**
- * onfi_fill_data_interface - [NAND Interface] Initialize a data interface from
- * given ONFI mode
- * @mode: The ONFI timing mode
+ * onfi_fill_data_interface - Initialize a data interface from a given ONFI mode
+ * @chip: The NAND chip
+ * @type: The data interface type
+ * @timing_mode: The ONFI timing mode
  */
 int onfi_fill_data_interface(struct nand_chip *chip,
 			     enum nand_data_interface_type type,
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 13/28] mtd: rawnand: timings: Provide onfi_fill_data_interface() with a data interface
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (11 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 12/28] mtd: rawnand: timings: Update onfi_fill_data_interface() kernel doc Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 19:17 ` [PATCH v5 14/28] mtd: rawnand: timings: Add a helper to find the closest ONFI mode Miquel Raynal
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

We rely be default on the data interface which is in the nand_chip
structure but it should be possible to fill any other data interface.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/raw/internals.h    | 1 +
 drivers/mtd/nand/raw/nand_base.c    | 7 ++++---
 drivers/mtd/nand/raw/nand_timings.c | 3 ++-
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index 347d42c55353..dc84e3b55d48 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -85,6 +85,7 @@ int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs);
 int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
 		    int allowbbt);
 int onfi_fill_data_interface(struct nand_chip *chip,
+			     struct nand_data_interface *iface,
 			     enum nand_data_interface_type type,
 			     int timing_mode);
 int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 9b94552fb177..89f10a8c1d62 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -927,7 +927,7 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
 	 * timings to timing mode 0.
 	 */
 
-	onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0);
+	onfi_fill_data_interface(chip, &chip->data_interface, NAND_SDR_IFACE, 0);
 	ret = chip->controller->ops->setup_data_interface(chip, chipnr,
 							&chip->data_interface);
 	if (ret)
@@ -1040,7 +1040,8 @@ static int nand_choose_data_interface(struct nand_chip *chip)
 	}
 
 	for (mode = fls(modes) - 1; mode >= 0; mode--) {
-		ret = onfi_fill_data_interface(chip, NAND_SDR_IFACE, mode);
+		ret = onfi_fill_data_interface(chip, &chip->data_interface,
+					       NAND_SDR_IFACE, mode);
 		if (ret)
 			continue;
 
@@ -5250,7 +5251,7 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
 	mutex_init(&chip->lock);
 
 	/* Enforce the right timings for reset/detection */
-	onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0);
+	onfi_fill_data_interface(chip, &chip->data_interface, NAND_SDR_IFACE, 0);
 
 	ret = nand_dt_init(chip);
 	if (ret)
diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
index a73d934e86f9..ce6bb87db2e8 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -276,14 +276,15 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
 /**
  * onfi_fill_data_interface - Initialize a data interface from a given ONFI mode
  * @chip: The NAND chip
+ * @iface: The data interface to fill
  * @type: The data interface type
  * @timing_mode: The ONFI timing mode
  */
 int onfi_fill_data_interface(struct nand_chip *chip,
+			     struct nand_data_interface *iface,
 			     enum nand_data_interface_type type,
 			     int timing_mode)
 {
-	struct nand_data_interface *iface = &chip->data_interface;
 	struct onfi_params *onfi = chip->parameters.onfi;
 
 	if (type != NAND_SDR_IFACE)
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 14/28] mtd: rawnand: timings: Add a helper to find the closest ONFI mode
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (12 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 13/28] mtd: rawnand: timings: Provide onfi_fill_data_interface() with a data interface Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 21:42   ` Boris Brezillon
  2020-05-26 19:17 ` [PATCH v5 15/28] mtd: rawnand: timings: Avoid redefining tR_max and tCCS_min Miquel Raynal
                   ` (13 subsequent siblings)
  27 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

Vendors are allowed to provide their own set of timings. In this case,
we provide a way to derive the "closest" timing mode so that, if the
NAND controller does not support tweaking these parameters, it will be
able to configure itself anyway.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/internals.h    |  2 ++
 drivers/mtd/nand/raw/nand_timings.c | 49 +++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+)

diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index dc84e3b55d48..c7357ae86eeb 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -88,6 +88,8 @@ int onfi_fill_data_interface(struct nand_chip *chip,
 			     struct nand_data_interface *iface,
 			     enum nand_data_interface_type type,
 			     int timing_mode);
+unsigned int
+onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings);
 int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
 int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
 int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf,
diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
index ce6bb87db2e8..3c44c4b90536 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -273,6 +273,55 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
 	},
 };
 
+/**
+ * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a
+ *                              set of timings
+ * @spec_timings: the timings to challenge
+ */
+unsigned int
+onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings)
+{
+	const struct nand_sdr_timings *onfi_timings;
+	int mode;
+
+	for (mode = ARRAY_SIZE(onfi_sdr_timings) - 1; mode > 0; mode--) {
+		onfi_timings = &onfi_sdr_timings[mode].timings.sdr;
+
+		if (spec_timings->tCCS_min > onfi_timings->tCCS_min ||
+		    spec_timings->tADL_min > onfi_timings->tADL_min ||
+		    spec_timings->tALH_min > onfi_timings->tALH_min ||
+		    spec_timings->tALS_min > onfi_timings->tALS_min ||
+		    spec_timings->tAR_min > onfi_timings->tAR_min ||
+		    spec_timings->tCEH_min > onfi_timings->tCEH_min ||
+		    spec_timings->tCH_min > onfi_timings->tCH_min ||
+		    spec_timings->tCLH_min > onfi_timings->tCLH_min ||
+		    spec_timings->tCLR_min > onfi_timings->tCLR_min ||
+		    spec_timings->tCLS_min > onfi_timings->tCLS_min ||
+		    spec_timings->tCOH_min > onfi_timings->tCOH_min ||
+		    spec_timings->tCS_min > onfi_timings->tCS_min ||
+		    spec_timings->tDH_min > onfi_timings->tDH_min ||
+		    spec_timings->tDS_min > onfi_timings->tDS_min ||
+		    spec_timings->tIR_min > onfi_timings->tIR_min ||
+		    spec_timings->tRC_min > onfi_timings->tRC_min ||
+		    spec_timings->tREH_min > onfi_timings->tREH_min ||
+		    spec_timings->tRHOH_min > onfi_timings->tRHOH_min ||
+		    spec_timings->tRHW_min > onfi_timings->tRHW_min ||
+		    spec_timings->tRLOH_min > onfi_timings->tRLOH_min ||
+		    spec_timings->tRP_min > onfi_timings->tRP_min ||
+		    spec_timings->tRR_min > onfi_timings->tRR_min ||
+		    spec_timings->tWC_min > onfi_timings->tWC_min ||
+		    spec_timings->tWH_min > onfi_timings->tWH_min ||
+		    spec_timings->tWHR_min > onfi_timings->tWHR_min ||
+		    spec_timings->tWP_min > onfi_timings->tWP_min ||
+		    spec_timings->tWW_min > onfi_timings->tWW_min)
+			continue;
+
+		return mode;
+	}
+
+	return 0;
+}
+
 /**
  * onfi_fill_data_interface - Initialize a data interface from a given ONFI mode
  * @chip: The NAND chip
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 15/28] mtd: rawnand: timings: Avoid redefining tR_max and tCCS_min
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (13 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 14/28] mtd: rawnand: timings: Add a helper to find the closest ONFI mode Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 20:33   ` Boris Brezillon
  2020-05-26 19:17 ` [PATCH v5 16/28] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max Miquel Raynal
                   ` (12 subsequent siblings)
  27 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

These two values are already hardcoded in the default ONFI timing
structure, no need to redefine them here.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_timings.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
index 3c44c4b90536..c2286a75d134 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -371,9 +371,6 @@ int onfi_fill_data_interface(struct nand_chip *chip,
 		/* microseconds -> picoseconds */
 		timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
 		timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
-
-		timings->tR_max = 200000000;
-		timings->tCCS_min = 500000;
 	}
 
 	return 0;
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 16/28] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (14 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 15/28] mtd: rawnand: timings: Avoid redefining tR_max and tCCS_min Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 20:32   ` Boris Brezillon
  2020-05-26 21:25   ` Boris Brezillon
  2020-05-26 19:17 ` [PATCH v5 17/28] mtd: rawnand: Define a unique reset data interface Miquel Raynal
                   ` (11 subsequent siblings)
  27 siblings, 2 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

The ONFI parameter page of a chip might define more fine grained
tPROG_max and tBERS_max. When we do not have this information, we
default to the highest possible values (they are maxima anyway).

There is no point setting these fields at runtime, so explicitly move
these defaults to the main ONFI SDR timings structure.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_timings.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
index c2286a75d134..52ee83e75646 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -20,6 +20,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
 		.timings.sdr = {
 			.tCCS_min = 500000,
 			.tR_max = 200000000,
+			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
+			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
 			.tADL_min = 400000,
 			.tALH_min = 20000,
 			.tALS_min = 50000,
@@ -63,6 +65,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
 		.timings.sdr = {
 			.tCCS_min = 500000,
 			.tR_max = 200000000,
+			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
+			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
 			.tADL_min = 400000,
 			.tALH_min = 10000,
 			.tALS_min = 25000,
@@ -106,6 +110,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
 		.timings.sdr = {
 			.tCCS_min = 500000,
 			.tR_max = 200000000,
+			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
+			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
 			.tADL_min = 400000,
 			.tALH_min = 10000,
 			.tALS_min = 15000,
@@ -149,6 +155,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
 		.timings.sdr = {
 			.tCCS_min = 500000,
 			.tR_max = 200000000,
+			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
+			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
 			.tADL_min = 400000,
 			.tALH_min = 5000,
 			.tALS_min = 10000,
@@ -192,6 +200,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
 		.timings.sdr = {
 			.tCCS_min = 500000,
 			.tR_max = 200000000,
+			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
+			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
 			.tADL_min = 400000,
 			.tALH_min = 5000,
 			.tALS_min = 10000,
@@ -235,6 +245,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
 		.timings.sdr = {
 			.tCCS_min = 500000,
 			.tR_max = 200000000,
+			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
+			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
 			.tADL_min = 400000,
 			.tALH_min = 5000,
 			.tALS_min = 10000,
@@ -359,18 +371,6 @@ int onfi_fill_data_interface(struct nand_chip *chip,
 
 		/* nanoseconds -> picoseconds */
 		timings->tCCS_min = 1000UL * onfi->tCCS;
-	} else {
-		struct nand_sdr_timings *timings = &iface->timings.sdr;
-		/*
-		 * For non-ONFI chips we use the highest possible value for
-		 * tPROG and tBERS. tR and tCCS will take the default values
-		 * precised in the ONFI specification for timing mode 0,
-		 * respectively 200us and 500ns.
-		 */
-
-		/* microseconds -> picoseconds */
-		timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
-		timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
 	}
 
 	return 0;
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 17/28] mtd: rawnand: Define a unique reset data interface
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (15 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 16/28] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 21:23   ` Boris Brezillon
  2020-05-26 19:17 ` [PATCH v5 18/28] mtd: rawnand: marvell: Use a helper to access the timings Miquel Raynal
                   ` (10 subsequent siblings)
  27 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

All NAND chips will always use the same data interface for reset and
at startup: SDR mode 0. Instead of copying around the data interface
timings, let's just have a default reset data interface for that.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_base.c    | 9 +++------
 drivers/mtd/nand/raw/nand_timings.c | 3 +++
 include/linux/mtd/rawnand.h         | 3 +++
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 89f10a8c1d62..1005035c233a 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -927,9 +927,8 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
 	 * timings to timing mode 0.
 	 */
 
-	onfi_fill_data_interface(chip, &chip->data_interface, NAND_SDR_IFACE, 0);
 	ret = chip->controller->ops->setup_data_interface(chip, chipnr,
-							&chip->data_interface);
+							  nand_reset_data_iface);
 	if (ret)
 		pr_err("Failed to configure data interface to SDR timing mode 0\n");
 
@@ -2484,7 +2483,6 @@ EXPORT_SYMBOL_GPL(nand_subop_get_data_len);
  */
 int nand_reset(struct nand_chip *chip, int chipnr)
 {
-	struct nand_data_interface saved_data_intf = chip->data_interface;
 	int ret;
 
 	ret = nand_reset_data_interface(chip, chipnr);
@@ -2509,11 +2507,10 @@ int nand_reset(struct nand_chip *chip, int chipnr)
 	 * nand_setup_data_interface() uses ->set/get_features() which would
 	 * fail anyway as the parameter page is not available yet.
 	 */
-	if (!memcmp(&chip->data_interface, &saved_data_intf,
-		    sizeof(saved_data_intf)))
+	if (!memcmp(&chip->data_interface, nand_reset_data_iface,
+		    sizeof(*nand_reset_data_iface)))
 		return 0;
 
-	chip->data_interface = saved_data_intf;
 	ret = nand_setup_data_interface(chip, chipnr);
 	if (ret)
 		return ret;
diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
index 52ee83e75646..343284c43e81 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -285,6 +285,9 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
 	},
 };
 
+/* All NAND chips share the same reset data interface: SDR mode 0 */
+const struct nand_data_interface *nand_reset_data_iface = &onfi_sdr_timings[0];
+
 /**
  * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a
  *                              set of timings
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 622da6527a36..6c334cca3977 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1203,6 +1203,9 @@ static inline struct device_node *nand_get_flash_node(struct nand_chip *chip)
 	return mtd_get_of_node(nand_to_mtd(chip));
 }
 
+/* Default/reset data interface */
+extern const struct nand_data_interface *nand_reset_data_iface;
+
 /*
  * A helper for defining older NAND chips where the second ID byte fully
  * defined the chip, including the geometry (chip size, eraseblock size, page
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 18/28] mtd: rawnand: marvell: Use a helper to access the timings
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (16 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 17/28] mtd: rawnand: Define a unique reset data interface Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 21:26   ` Boris Brezillon
  2020-05-26 19:17 ` [PATCH v5 19/28] mtd: rawnand: legacy: " Miquel Raynal
                   ` (9 subsequent siblings)
  27 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

Do not access the SDR timings directly but use nand_get_sdr_timings()
instead. This way, future patching over this helper will be easier.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/marvell_nand.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
index 260a0430313e..ebf45a2754f1 100644
--- a/drivers/mtd/nand/raw/marvell_nand.c
+++ b/drivers/mtd/nand/raw/marvell_nand.c
@@ -1096,6 +1096,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip,
 						const u8 *oob_buf, bool raw,
 						int page)
 {
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface);
 	struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
 	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
 	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
@@ -1140,8 +1141,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip,
 	if (ret)
 		return ret;
 
-	ret = marvell_nfc_wait_op(chip,
-				  PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max));
+	ret = marvell_nfc_wait_op(chip, PSEC_TO_MSEC(sdr->tPROG_max));
 	return ret;
 }
 
@@ -1562,6 +1562,7 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip,
 					     const u8 *buf,
 					     int oob_required, int page)
 {
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface);
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
 	const u8 *data = buf;
@@ -1598,8 +1599,7 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip,
 		marvell_nfc_wait_ndrun(chip);
 	}
 
-	ret = marvell_nfc_wait_op(chip,
-				  PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max));
+	ret = marvell_nfc_wait_op(chip, PSEC_TO_MSEC(sdr->tPROG_max));
 
 	marvell_nfc_disable_hw_ecc(chip);
 
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 19/28] mtd: rawnand: legacy: Use a helper to access the timings
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (17 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 18/28] mtd: rawnand: marvell: Use a helper to access the timings Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 21:28   ` Boris Brezillon
  2020-05-26 19:17 ` [PATCH v5 20/28] mtd: rawnand: Hide the chip->data_interface indirection Miquel Raynal
                   ` (8 subsequent siblings)
  27 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

Do not access the SDR timings directly but use nand_get_sdr_timings()
instead. This way, future patching over this helper will be easier.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_legacy.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_legacy.c b/drivers/mtd/nand/raw/nand_legacy.c
index 8b91aa7773d8..34b4c944f6a6 100644
--- a/drivers/mtd/nand/raw/nand_legacy.c
+++ b/drivers/mtd/nand/raw/nand_legacy.c
@@ -354,6 +354,8 @@ static void nand_command(struct nand_chip *chip, unsigned int command,
 
 static void nand_ccs_delay(struct nand_chip *chip)
 {
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface);
+
 	/*
 	 * The controller already takes care of waiting for tCCS when the RNDIN
 	 * or RNDOUT command is sent, return directly.
@@ -366,7 +368,7 @@ static void nand_ccs_delay(struct nand_chip *chip)
 	 * (which should be safe for all NANDs).
 	 */
 	if (nand_controller_has_setup_data_iface(chip))
-		ndelay(chip->data_interface.timings.sdr.tCCS_min / 1000);
+		ndelay(sdr->tCCS_min / 1000);
 	else
 		ndelay(500);
 }
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 20/28] mtd: rawnand: Hide the chip->data_interface indirection
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (18 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 19/28] mtd: rawnand: legacy: " Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 21:36   ` Boris Brezillon
  2020-05-26 19:17 ` [PATCH v5 21/28] mtd: rawnand: Introduce nand_choose_best_sdr_timings() Miquel Raynal
                   ` (7 subsequent siblings)
  27 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

As a preparation for allocating the data interface structure
dynamically (and rename it), let's avoid calling it directly.

Instead, we operate a rename on an existing helper to reuse that name
for another helper:
* s/nand_get_sdr_timings/nand_extract_sdr_timings/
  -> this helper just extracts timings from a given data interface
* nand_get_sdr_timings()
  -> this helper retrieves the in use timings from a nand_chip structure

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/ams-delta.c              |  2 +-
 .../mtd/nand/raw/cadence-nand-controller.c    |  2 +-
 drivers/mtd/nand/raw/denali.c                 |  2 +-
 drivers/mtd/nand/raw/fsmc_nand.c              |  2 +-
 drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c    |  2 +-
 drivers/mtd/nand/raw/marvell_nand.c           |  6 +--
 drivers/mtd/nand/raw/meson_nand.c             |  8 ++--
 drivers/mtd/nand/raw/mtk_nand.c               |  2 +-
 drivers/mtd/nand/raw/mxc_nand.c               |  2 +-
 drivers/mtd/nand/raw/mxic_nand.c              |  2 +-
 drivers/mtd/nand/raw/nand_base.c              | 43 +++++++------------
 drivers/mtd/nand/raw/nand_legacy.c            |  2 +-
 drivers/mtd/nand/raw/nand_toshiba.c           |  3 +-
 drivers/mtd/nand/raw/s3c2410.c                |  2 +-
 drivers/mtd/nand/raw/stm32_fmc2_nand.c        |  4 +-
 drivers/mtd/nand/raw/sunxi_nand.c             |  2 +-
 drivers/mtd/nand/raw/tango_nand.c             |  2 +-
 drivers/mtd/nand/raw/tegra_nand.c             |  2 +-
 include/linux/mtd/rawnand.h                   | 14 +++++-
 19 files changed, 49 insertions(+), 55 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 3711e7a0436c..c541f78f9e1d 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -195,7 +195,7 @@ static int gpio_nand_setup_data_interface(struct nand_chip *this, int csline,
 					  const struct nand_data_interface *cf)
 {
 	struct gpio_nand *priv = nand_get_controller_data(this);
-	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(cf);
+	const struct nand_sdr_timings *sdr = nand_extract_sdr_timings(cf);
 	struct device *dev = &nand_to_mtd(this)->dev;
 
 	if (IS_ERR(sdr))
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c
index c405722adfe1..847aaa3d7508 100644
--- a/drivers/mtd/nand/raw/cadence-nand-controller.c
+++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
@@ -2327,7 +2327,7 @@ cadence_nand_setup_data_interface(struct nand_chip *chip, int chipnr,
 	u32 dll_phy_dqs_timing = 0, phony_dqs_timing = 0, rd_del_sel = 0;
 	u32 sampling_point;
 
-	sdr = nand_get_sdr_timings(conf);
+	sdr = nand_extract_sdr_timings(conf);
 	if (IS_ERR(sdr))
 		return PTR_ERR(sdr);
 
diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
index 4e6e1578aa2d..b45998e6ecc5 100644
--- a/drivers/mtd/nand/raw/denali.c
+++ b/drivers/mtd/nand/raw/denali.c
@@ -774,7 +774,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr,
 	int addr_2_data_mask;
 	u32 tmp;
 
-	timings = nand_get_sdr_timings(conf);
+	timings = nand_extract_sdr_timings(conf);
 	if (IS_ERR(timings))
 		return PTR_ERR(timings);
 
diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
index 3909752b14c5..c7cacc77b7c8 100644
--- a/drivers/mtd/nand/raw/fsmc_nand.c
+++ b/drivers/mtd/nand/raw/fsmc_nand.c
@@ -335,7 +335,7 @@ static int fsmc_setup_data_interface(struct nand_chip *nand, int csline,
 	const struct nand_sdr_timings *sdrt;
 	int ret;
 
-	sdrt = nand_get_sdr_timings(conf);
+	sdrt = nand_extract_sdr_timings(conf);
 	if (IS_ERR(sdrt))
 		return PTR_ERR(sdrt);
 
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 061a8ddda275..341248e69d18 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -743,7 +743,7 @@ static int gpmi_setup_data_interface(struct nand_chip *chip, int chipnr,
 	const struct nand_sdr_timings *sdr;
 
 	/* Retrieve required NAND timings */
-	sdr = nand_get_sdr_timings(conf);
+	sdr = nand_extract_sdr_timings(conf);
 	if (IS_ERR(sdr))
 		return PTR_ERR(sdr);
 
diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
index ebf45a2754f1..acd45bbe1782 100644
--- a/drivers/mtd/nand/raw/marvell_nand.c
+++ b/drivers/mtd/nand/raw/marvell_nand.c
@@ -1096,7 +1096,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip,
 						const u8 *oob_buf, bool raw,
 						int page)
 {
-	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 	struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
 	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
 	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
@@ -1562,7 +1562,7 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip,
 					     const u8 *buf,
 					     int oob_required, int page)
 {
-	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
 	const u8 *data = buf;
@@ -2316,7 +2316,7 @@ static int marvell_nfc_setup_data_interface(struct nand_chip *chip, int chipnr,
 	struct marvell_nfc_timings nfc_tmg;
 	int read_delay;
 
-	sdr = nand_get_sdr_timings(conf);
+	sdr = nand_extract_sdr_timings(conf);
 	if (IS_ERR(sdr))
 		return PTR_ERR(sdr);
 
diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
index 3f376471f3f7..95b5f3d7c714 100644
--- a/drivers/mtd/nand/raw/meson_nand.c
+++ b/drivers/mtd/nand/raw/meson_nand.c
@@ -575,8 +575,7 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand,
 {
 	struct mtd_info *mtd = nand_to_mtd(nand);
 	struct meson_nfc *nfc = nand_get_controller_data(nand);
-	const struct nand_sdr_timings *sdr =
-		nand_get_sdr_timings(&nand->data_interface);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(nand);
 	u32 *addrs = nfc->cmdfifo.rw.addrs;
 	u32 cs = nfc->param.chip_select;
 	u32 cmd0, cmd_num, row_start;
@@ -627,8 +626,7 @@ static int meson_nfc_write_page_sub(struct nand_chip *nand,
 				    int page, int raw)
 {
 	struct mtd_info *mtd = nand_to_mtd(nand);
-	const struct nand_sdr_timings *sdr =
-		nand_get_sdr_timings(&nand->data_interface);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(nand);
 	struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
 	struct meson_nfc *nfc = nand_get_controller_data(nand);
 	int data_len, info_len;
@@ -1104,7 +1102,7 @@ int meson_nfc_setup_data_interface(struct nand_chip *nand, int csline,
 	const struct nand_sdr_timings *timings;
 	u32 div, bt_min, bt_max, tbers_clocks;
 
-	timings = nand_get_sdr_timings(conf);
+	timings = nand_extract_sdr_timings(conf);
 	if (IS_ERR(timings))
 		return -ENOTSUPP;
 
diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
index c1a6e31aabb8..e64abb77ed12 100644
--- a/drivers/mtd/nand/raw/mtk_nand.c
+++ b/drivers/mtd/nand/raw/mtk_nand.c
@@ -509,7 +509,7 @@ static int mtk_nfc_setup_data_interface(struct nand_chip *chip, int csline,
 	u32 rate, tpoecs, tprecs, tc2r, tw2r, twh, twst = 0, trlt = 0;
 	u32 temp, tsel = 0;
 
-	timings = nand_get_sdr_timings(conf);
+	timings = nand_extract_sdr_timings(conf);
 	if (IS_ERR(timings))
 		return -ENOTSUPP;
 
diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c
index 09dacb83cb5a..0613e22f180c 100644
--- a/drivers/mtd/nand/raw/mxc_nand.c
+++ b/drivers/mtd/nand/raw/mxc_nand.c
@@ -1148,7 +1148,7 @@ static int mxc_nand_v2_setup_data_interface(struct nand_chip *chip, int csline,
 	const struct nand_sdr_timings *timings;
 	u16 config1;
 
-	timings = nand_get_sdr_timings(conf);
+	timings = nand_extract_sdr_timings(conf);
 	if (IS_ERR(timings))
 		return -ENOTSUPP;
 
diff --git a/drivers/mtd/nand/raw/mxic_nand.c b/drivers/mtd/nand/raw/mxic_nand.c
index 57f36721f4c6..277c168e0af7 100644
--- a/drivers/mtd/nand/raw/mxic_nand.c
+++ b/drivers/mtd/nand/raw/mxic_nand.c
@@ -459,7 +459,7 @@ static int mxic_nfc_setup_data_interface(struct nand_chip *chip, int chipnr,
 	unsigned long freq;
 	int ret;
 
-	sdr = nand_get_sdr_timings(conf);
+	sdr = nand_extract_sdr_timings(conf);
 	if (IS_ERR(sdr))
 		return PTR_ERR(sdr);
 
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 1005035c233a..6a7edd2e1357 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -773,7 +773,7 @@ int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
 		return -ENOTSUPP;
 
 	/* Wait tWB before polling the STATUS reg. */
-	timings = nand_get_sdr_timings(&chip->data_interface);
+	timings = nand_get_sdr_timings(chip);
 	ndelay(PSEC_TO_NSEC(timings->tWB_max));
 
 	ret = nand_status_op(chip, NULL);
@@ -1119,8 +1119,7 @@ static int nand_sp_exec_read_page_op(struct nand_chip *chip, unsigned int page,
 				     unsigned int len)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
-	const struct nand_sdr_timings *sdr =
-		nand_get_sdr_timings(&chip->data_interface);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 	u8 addrs[4];
 	struct nand_op_instr instrs[] = {
 		NAND_OP_CMD(NAND_CMD_READ0, 0),
@@ -1161,8 +1160,7 @@ static int nand_lp_exec_read_page_op(struct nand_chip *chip, unsigned int page,
 				     unsigned int offset_in_page, void *buf,
 				     unsigned int len)
 {
-	const struct nand_sdr_timings *sdr =
-		nand_get_sdr_timings(&chip->data_interface);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 	u8 addrs[5];
 	struct nand_op_instr instrs[] = {
 		NAND_OP_CMD(NAND_CMD_READ0, 0),
@@ -1258,8 +1256,7 @@ int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf,
 		return -EINVAL;
 
 	if (nand_has_exec_op(chip)) {
-		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_PARAM, 0),
 			NAND_OP_ADDR(1, &page, PSEC_TO_NSEC(sdr->tWB_max)),
@@ -1313,8 +1310,7 @@ int nand_change_read_column_op(struct nand_chip *chip,
 		return -ENOTSUPP;
 
 	if (nand_has_exec_op(chip)) {
-		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 		u8 addrs[2] = {};
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_RNDOUT, 0),
@@ -1389,8 +1385,7 @@ static int nand_exec_prog_page_op(struct nand_chip *chip, unsigned int page,
 				  unsigned int len, bool prog)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
-	const struct nand_sdr_timings *sdr =
-		nand_get_sdr_timings(&chip->data_interface);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 	u8 addrs[5] = {};
 	struct nand_op_instr instrs[] = {
 		/*
@@ -1512,8 +1507,7 @@ int nand_prog_page_end_op(struct nand_chip *chip)
 	u8 status;
 
 	if (nand_has_exec_op(chip)) {
-		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_PAGEPROG,
 				    PSEC_TO_NSEC(sdr->tWB_max)),
@@ -1619,8 +1613,7 @@ int nand_change_write_column_op(struct nand_chip *chip,
 		return -ENOTSUPP;
 
 	if (nand_has_exec_op(chip)) {
-		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 		u8 addrs[2];
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_RNDIN, 0),
@@ -1674,8 +1667,7 @@ int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf,
 		return -EINVAL;
 
 	if (nand_has_exec_op(chip)) {
-		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_READID, 0),
 			NAND_OP_ADDR(1, &addr, PSEC_TO_NSEC(sdr->tADL_min)),
@@ -1713,8 +1705,7 @@ EXPORT_SYMBOL_GPL(nand_readid_op);
 int nand_status_op(struct nand_chip *chip, u8 *status)
 {
 	if (nand_has_exec_op(chip)) {
-		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_STATUS,
 				    PSEC_TO_NSEC(sdr->tADL_min)),
@@ -1782,8 +1773,7 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock)
 	u8 status;
 
 	if (nand_has_exec_op(chip)) {
-		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 		u8 addrs[3] = {	page, page >> 8, page >> 16 };
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_ERASE1, 0),
@@ -1841,8 +1831,7 @@ static int nand_set_features_op(struct nand_chip *chip, u8 feature,
 	int i, ret;
 
 	if (nand_has_exec_op(chip)) {
-		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_SET_FEATURES, 0),
 			NAND_OP_ADDR(1, &feature, PSEC_TO_NSEC(sdr->tADL_min)),
@@ -1888,8 +1877,7 @@ static int nand_get_features_op(struct nand_chip *chip, u8 feature,
 	int i;
 
 	if (nand_has_exec_op(chip)) {
-		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_GET_FEATURES, 0),
 			NAND_OP_ADDR(1, &feature, PSEC_TO_NSEC(sdr->tWB_max)),
@@ -1945,8 +1933,7 @@ static int nand_wait_rdy_op(struct nand_chip *chip, unsigned int timeout_ms,
 int nand_reset_op(struct nand_chip *chip)
 {
 	if (nand_has_exec_op(chip)) {
-		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_RESET, PSEC_TO_NSEC(sdr->tWB_max)),
 			NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tRST_max), 0),
@@ -3293,7 +3280,7 @@ static void nand_wait_readrdy(struct nand_chip *chip)
 	if (!(chip->options & NAND_NEED_READRDY))
 		return;
 
-	sdr = nand_get_sdr_timings(&chip->data_interface);
+	sdr = nand_get_sdr_timings(chip);
 	WARN_ON(nand_wait_rdy_op(chip, PSEC_TO_MSEC(sdr->tR_max), 0));
 }
 
diff --git a/drivers/mtd/nand/raw/nand_legacy.c b/drivers/mtd/nand/raw/nand_legacy.c
index 34b4c944f6a6..fc0443bb45cf 100644
--- a/drivers/mtd/nand/raw/nand_legacy.c
+++ b/drivers/mtd/nand/raw/nand_legacy.c
@@ -354,7 +354,7 @@ static void nand_command(struct nand_chip *chip, unsigned int command,
 
 static void nand_ccs_delay(struct nand_chip *chip)
 {
-	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 
 	/*
 	 * The controller already takes care of waiting for tCCS when the RNDIN
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index ae069905d7e4..302d4a6e175b 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -32,8 +32,7 @@ static int toshiba_nand_benand_read_eccstatus_op(struct nand_chip *chip,
 	u8 *ecc_status = buf;
 
 	if (nand_has_exec_op(chip)) {
-		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(chip);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(TOSHIBA_NAND_CMD_ECC_STATUS_READ,
 				    PSEC_TO_NSEC(sdr->tADL_min)),
diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c
index f86dff311464..be95d9fbd33a 100644
--- a/drivers/mtd/nand/raw/s3c2410.c
+++ b/drivers/mtd/nand/raw/s3c2410.c
@@ -817,7 +817,7 @@ static int s3c2410_nand_setup_data_interface(struct nand_chip *chip, int csline,
 	const struct nand_sdr_timings *timings;
 	int tacls;
 
-	timings = nand_get_sdr_timings(conf);
+	timings = nand_extract_sdr_timings(conf);
 	if (IS_ERR(timings))
 		return -ENOTSUPP;
 
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 65c9d17b25a3..e0969ecc910d 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -1308,7 +1308,7 @@ static int stm32_fmc2_nfc_waitrdy(struct nand_chip *chip,
 		dev_warn(nfc->dev, "Waitrdy timeout\n");
 
 	/* Wait tWB before R/B# signal is low */
-	timings = nand_get_sdr_timings(&chip->data_interface);
+	timings = nand_get_sdr_timings(chip);
 	ndelay(PSEC_TO_NSEC(timings->tWB_max));
 
 	/* R/B# signal is low, clear high level flag */
@@ -1550,7 +1550,7 @@ static int stm32_fmc2_nfc_setup_interface(struct nand_chip *chip, int chipnr,
 {
 	const struct nand_sdr_timings *sdrt;
 
-	sdrt = nand_get_sdr_timings(conf);
+	sdrt = nand_extract_sdr_timings(conf);
 	if (IS_ERR(sdrt))
 		return PTR_ERR(sdrt);
 
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index ffbc1651fadc..eb99b23629b8 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -1386,7 +1386,7 @@ static int sunxi_nfc_setup_data_interface(struct nand_chip *nand, int csline,
 	s32 tWB, tADL, tWHR, tRHW, tCAD;
 	long real_clk_rate;
 
-	timings = nand_get_sdr_timings(conf);
+	timings = nand_extract_sdr_timings(conf);
 	if (IS_ERR(timings))
 		return -ENOTSUPP;
 
diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c
index 246871e01027..0c98b95704fe 100644
--- a/drivers/mtd/nand/raw/tango_nand.c
+++ b/drivers/mtd/nand/raw/tango_nand.c
@@ -479,7 +479,7 @@ static u32 to_ticks(int kHz, int ps)
 static int tango_set_timings(struct nand_chip *chip, int csline,
 			     const struct nand_data_interface *conf)
 {
-	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(conf);
+	const struct nand_sdr_timings *sdr = nand_extract_sdr_timings(conf);
 	struct tango_nfc *nfc = to_tango_nfc(chip->controller);
 	struct tango_chip *tchip = to_tango_chip(chip);
 	u32 Trdy, Textw, Twc, Twpw, Tacc, Thold, Trpw, Textr;
diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c
index f9d046b2cd3b..2aaba9e15614 100644
--- a/drivers/mtd/nand/raw/tegra_nand.c
+++ b/drivers/mtd/nand/raw/tegra_nand.c
@@ -819,7 +819,7 @@ static int tegra_nand_setup_data_interface(struct nand_chip *chip, int csline,
 	struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller);
 	const struct nand_sdr_timings *timings;
 
-	timings = nand_get_sdr_timings(conf);
+	timings = nand_extract_sdr_timings(conf);
 	if (IS_ERR(timings))
 		return PTR_ERR(timings);
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 6c334cca3977..2995d29587c3 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -517,11 +517,11 @@ struct nand_data_interface {
 };
 
 /**
- * nand_get_sdr_timings - get SDR timing from data interface
+ * nand_extract_sdr_timings - Retrieve SDR timing from a data interface
  * @conf:	The data interface
  */
 static inline const struct nand_sdr_timings *
-nand_get_sdr_timings(const struct nand_data_interface *conf)
+nand_extract_sdr_timings(const struct nand_data_interface *conf)
 {
 	if (conf->type != NAND_SDR_IFACE)
 		return ERR_PTR(-EINVAL);
@@ -1206,6 +1206,16 @@ static inline struct device_node *nand_get_flash_node(struct nand_chip *chip)
 /* Default/reset data interface */
 extern const struct nand_data_interface *nand_reset_data_iface;
 
+/**
+ * nand_get_sdr_timings - Retrieve the current SDR timings of a NAND chip
+ * @chip: The NAND chip
+ */
+static inline const struct nand_sdr_timings *
+nand_get_sdr_timings(struct nand_chip *chip)
+{
+	return nand_extract_sdr_timings(&chip->data_interface);
+}
+
 /*
  * A helper for defining older NAND chips where the second ID byte fully
  * defined the chip, including the geometry (chip size, eraseblock size, page
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 21/28] mtd: rawnand: Introduce nand_choose_best_sdr_timings()
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (19 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 20/28] mtd: rawnand: Hide the chip->data_interface indirection Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 21:50   ` Boris Brezillon
  2020-05-26 19:17 ` [PATCH v5 22/28] mtd: rawnand: Add the ->choose_data_interface() hook Miquel Raynal
                   ` (6 subsequent siblings)
  27 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

Extract the logic out of nand_choose_data_interface() to create a
public helper that can be reused by manufacturer drivers. Add the
possibility to provide a specific set of timings.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/internals.h |   3 +
 drivers/mtd/nand/raw/nand_base.c | 104 +++++++++++++++++++------------
 2 files changed, 66 insertions(+), 41 deletions(-)

diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index c7357ae86eeb..5c49c4d1e231 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -90,6 +90,9 @@ int onfi_fill_data_interface(struct nand_chip *chip,
 			     int timing_mode);
 unsigned int
 onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings);
+int nand_choose_best_sdr_timings(struct nand_chip *chip,
+				 struct nand_data_interface *iface,
+				 struct nand_sdr_timings *spec_timings);
 int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
 int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
 int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf,
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 6a7edd2e1357..b2e833a8ab9d 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -1003,61 +1003,83 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
 	return ret;
 }
 
+/**
+ * nand_choose_best_sdr_timings - Pick up the best SDR timings that both the
+ *                                NAND controller and the NAND chip support
+ * @chip: the NAND chip
+ * @iface: the data interface (can eventually be updated)
+ * @spec_timings: specific timings, when not fitting the ONFI specification
+ *
+ * If specific timings are provided, use them. Otherwise, try to retrieve
+ * supported timing modes from ONFI information. Finally, if the NAND chip does
+ * not follow the ONFI specification, rely on the ->default_timing_mode
+ * specified in the nand_ids table.
+ */
+int nand_choose_best_sdr_timings(struct nand_chip *chip,
+				 struct nand_data_interface *iface,
+				 struct nand_sdr_timings *spec_timings)
+{
+	const struct nand_controller_ops *ops = chip->controller->ops;
+	int best_mode = 0, onfi_modes, mode, ret;
+
+	iface->type = NAND_SDR_IFACE;
+
+	if (spec_timings) {
+		iface->timings.sdr = *spec_timings;
+		iface->timings.mode = onfi_find_closest_sdr_mode(spec_timings);
+
+		/* Verify the controller supports the requested interface */
+		ret = ops->setup_data_interface(chip,
+						NAND_DATA_IFACE_CHECK_ONLY,
+						iface);
+		if (!ret)
+			return ret;
+
+		/* Fallback to slower modes */
+		best_mode = iface->timings.mode;
+	} else {
+		if (chip->parameters.onfi) {
+			onfi_modes = chip->parameters.onfi->async_timing_mode;
+			best_mode = fls(onfi_modes) - 1;
+		} else {
+			best_mode = chip->onfi_timing_mode_default;
+		}
+	}
+
+
+	for (mode = best_mode; mode >= 0; mode--) {
+		ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE,
+					       mode);
+		if (ret)
+			continue;
+
+		ret = ops->setup_data_interface(chip,
+						NAND_DATA_IFACE_CHECK_ONLY,
+						iface);
+		if (!ret)
+			break;
+	}
+
+	return 0;
+}
+
 /**
  * nand_choose_data_interface - find the best data interface and timings
  * @chip: The NAND chip
  *
  * Find the best data interface and NAND timings supported by the chip
  * and the driver.
- * First tries to retrieve supported timing modes from ONFI information,
- * and if the NAND chip does not support ONFI, relies on the
- * ->onfi_timing_mode_default specified in the nand_ids table. After this
- * function nand_chip->data_interface is initialized with the best timing mode
- * available.
+ * After this function nand_chip->data_interface is initialized with the best
+ * timing mode available.
  *
  * Returns 0 for success or negative error code otherwise.
  */
 static int nand_choose_data_interface(struct nand_chip *chip)
 {
-	int modes, mode, ret;
-
 	if (!nand_controller_has_setup_data_iface(chip))
 		return 0;
 
-	/*
-	 * First try to identify the best timings from ONFI parameters and
-	 * if the NAND does not support ONFI, fallback to the default ONFI
-	 * timing mode.
-	 */
-	if (chip->parameters.onfi) {
-		modes = chip->parameters.onfi->async_timing_mode;
-	} else {
-		if (!chip->onfi_timing_mode_default)
-			return 0;
-
-		modes = GENMASK(chip->onfi_timing_mode_default, 0);
-	}
-
-	for (mode = fls(modes) - 1; mode >= 0; mode--) {
-		ret = onfi_fill_data_interface(chip, &chip->data_interface,
-					       NAND_SDR_IFACE, mode);
-		if (ret)
-			continue;
-
-		/*
-		 * Pass NAND_DATA_IFACE_CHECK_ONLY to only check if the
-		 * controller supports the requested timings.
-		 */
-		ret = chip->controller->ops->setup_data_interface(chip,
-						 NAND_DATA_IFACE_CHECK_ONLY,
-						 &chip->data_interface);
-		if (!ret) {
-			chip->onfi_timing_mode_default = mode;
-			break;
-		}
-	}
-
-	return 0;
+	return nand_choose_best_sdr_timings(chip, &chip->data_interface, NULL);
 }
 
 /**
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 22/28] mtd: rawnand: Add the ->choose_data_interface() hook
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (20 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 21/28] mtd: rawnand: Introduce nand_choose_best_sdr_timings() Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 21:52   ` Boris Brezillon
  2020-05-26 19:17 ` [PATCH v5 23/28] mtd: rawnand: toshiba: Implement ->choose_data_interface() for TC58TEG5DCLTA00 Miquel Raynal
                   ` (5 subsequent siblings)
  27 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

This hook can be overloaded by NAND manufacturer drivers to propose
alternative timings when not following the main standards. In this
case, the manufacturer drivers is responsible for choosing the best
data interface and configuration that fits both the controller and
chip capabilities.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_base.c | 9 +++++++--
 include/linux/mtd/rawnand.h      | 3 +++
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index b2e833a8ab9d..f14d297c50f4 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -1046,7 +1046,6 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
 		}
 	}
 
-
 	for (mode = best_mode; mode >= 0; mode--) {
 		ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE,
 					       mode);
@@ -1068,7 +1067,9 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
  * @chip: The NAND chip
  *
  * Find the best data interface and NAND timings supported by the chip
- * and the driver.
+ * and the driver. Eventually let the NAND manufacturer driver propose his own
+ * set of timings.
+ *
  * After this function nand_chip->data_interface is initialized with the best
  * timing mode available.
  *
@@ -1079,6 +1080,10 @@ static int nand_choose_data_interface(struct nand_chip *chip)
 	if (!nand_controller_has_setup_data_iface(chip))
 		return 0;
 
+	if (chip->ops.choose_data_interface)
+		return chip->ops.choose_data_interface(chip,
+						       &chip->data_interface);
+
 	return nand_choose_best_sdr_timings(chip, &chip->data_interface, NULL);
 }
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 2995d29587c3..5bd79e853140 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1034,6 +1034,7 @@ struct nand_legacy {
  * @lock_area: Lock operation
  * @unlock_area: Unlock operation
  * @setup_read_retry: Set the read-retry mode (mostly needed for MLC NANDs)
+ * @choose_data_interface: Choose the best data interface
  */
 struct nand_chip_ops {
 	int (*suspend)(struct nand_chip *chip);
@@ -1041,6 +1042,8 @@ struct nand_chip_ops {
 	int (*lock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
 	int (*unlock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
 	int (*setup_read_retry)(struct nand_chip *chip, int retry_mode);
+	int (*choose_data_interface)(struct nand_chip *chip,
+				     struct nand_data_interface *iface);
 };
 
 /**
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 23/28] mtd: rawnand: toshiba: Implement ->choose_data_interface() for TC58TEG5DCLTA00
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (21 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 22/28] mtd: rawnand: Add the ->choose_data_interface() hook Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 21:54   ` Boris Brezillon
  2020-05-26 19:17 ` [PATCH v5 24/28] mtd: rawnand: toshiba: Implement ->choose_data_interface() for TC58NVG0S3E Miquel Raynal
                   ` (4 subsequent siblings)
  27 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

Implement this hook for the tc58teg5dclta00 NAND chip and stop setting
->default_timing_mode.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_toshiba.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index 302d4a6e175b..fe2bc20972a9 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -193,11 +193,24 @@ static void toshiba_nand_decode_id(struct nand_chip *chip)
 	}
 }
 
+static int
+tc58teg5dclta00_choose_data_interface(struct nand_chip *chip,
+				      struct nand_data_interface *iface)
+{
+	int ret;
+
+	ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE, 5);
+	if (ret)
+		return ret;
+
+	return nand_choose_best_sdr_timings(chip, iface, NULL);
+}
+
 static int tc58teg5dclta00_init(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 
-	chip->onfi_timing_mode_default = 5;
+	chip->ops.choose_data_interface = &tc58teg5dclta00_choose_data_interface;
 	chip->options |= NAND_NEED_SCRAMBLING;
 	mtd_set_pairing_scheme(mtd, &dist3_pairing_scheme);
 
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 24/28] mtd: rawnand: toshiba: Implement ->choose_data_interface() for TC58NVG0S3E
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (22 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 23/28] mtd: rawnand: toshiba: Implement ->choose_data_interface() for TC58TEG5DCLTA00 Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 22:02   ` Boris Brezillon
  2020-05-26 19:17 ` [PATCH v5 25/28] mtd: rawnand: hynix: Implement ->choose_data_interface() for H27UCG8T2ATR-BC Miquel Raynal
                   ` (3 subsequent siblings)
  27 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

This chip supports ONFI SDR timing mode 2, implement the new hook to
advertize it.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_ids.c     |  3 +--
 drivers/mtd/nand/raw/nand_toshiba.c | 21 +++++++++++++++++++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
index e0dbc2e316c7..c729a8bc895d 100644
--- a/drivers/mtd/nand/raw/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
@@ -28,8 +28,7 @@ struct nand_flash_dev nand_flash_ids[] = {
 	 */
 	{"TC58NVG0S3E 1G 3.3V 8-bit",
 		{ .id = {0x98, 0xd1, 0x90, 0x15, 0x76, 0x14, 0x01, 0x00} },
-		  SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512),
-		  2 },
+		  SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512), },
 	{"TC58NVG2S0F 4G 3.3V 8-bit",
 		{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} },
 		  SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) },
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index fe2bc20972a9..860ae0c13063 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -206,6 +206,18 @@ tc58teg5dclta00_choose_data_interface(struct nand_chip *chip,
 	return nand_choose_best_sdr_timings(chip, iface, NULL);
 }
 
+static int tc58nvg0s3e_choose_data_interface(struct nand_chip *chip,
+					     struct nand_data_interface *iface)
+{
+	int ret;
+
+	ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE, 2);
+	if (ret)
+		return ret;
+
+	return nand_choose_best_sdr_timings(chip, iface, NULL);
+}
+
 static int tc58teg5dclta00_init(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
@@ -217,6 +229,13 @@ static int tc58teg5dclta00_init(struct nand_chip *chip)
 	return 0;
 }
 
+static int tc58nvg0s3e_init(struct nand_chip *chip)
+{
+	chip->ops.choose_data_interface = &tc58nvg0s3e_choose_data_interface;
+
+	return 0;
+}
+
 static int toshiba_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
@@ -229,6 +248,8 @@ static int toshiba_nand_init(struct nand_chip *chip)
 
 	if (!strcmp("TC58TEG5DCLTA00", chip->parameters.model))
 		tc58teg5dclta00_init(chip);
+	if (!strcmp("TC58NVG0S3E", chip->parameters.model))
+		tc58nvg0s3e_init(chip);
 
 	return 0;
 }
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 25/28] mtd: rawnand: hynix: Implement ->choose_data_interface() for H27UCG8T2ATR-BC
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (23 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 24/28] mtd: rawnand: toshiba: Implement ->choose_data_interface() for TC58NVG0S3E Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 22:06   ` Boris Brezillon
  2020-05-26 19:17 ` [PATCH v5 26/28] mtd: rawnand: toshiba: Choose the data interface for TH58NVG2S3HBAI4 Miquel Raynal
                   ` (2 subsequent siblings)
  27 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

This chip supports ONFI SDR timing mode 4, implement the new hook to
advertize it.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_hynix.c | 16 ++++++++++++++++
 drivers/mtd/nand/raw/nand_ids.c   |  2 +-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
index 7d1be53f27f3..d61a55121962 100644
--- a/drivers/mtd/nand/raw/nand_hynix.c
+++ b/drivers/mtd/nand/raw/nand_hynix.c
@@ -673,6 +673,19 @@ static void hynix_nand_cleanup(struct nand_chip *chip)
 	nand_set_manufacturer_data(chip, NULL);
 }
 
+static int
+h27ucg8t2atrbc_choose_data_interface(struct nand_chip *chip,
+				     struct nand_data_interface *iface)
+{
+	int ret;
+
+	ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE, 4);
+	if (ret)
+		return ret;
+
+	return nand_choose_best_sdr_timings(chip, iface, NULL);
+}
+
 static int hynix_nand_init(struct nand_chip *chip)
 {
 	struct hynix_nand *hynix;
@@ -689,6 +702,9 @@ static int hynix_nand_init(struct nand_chip *chip)
 
 	nand_set_manufacturer_data(chip, hynix);
 
+	if (!strcmp("H27UCG8T2ATR-BC", chip->parameters.model))
+		chip->ops.choose_data_interface = h27ucg8t2atrbc_choose_data_interface;
+
 	ret = hynix_nand_rr_init(chip);
 	if (ret)
 		hynix_nand_cleanup(chip);
diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
index c729a8bc895d..3b890d55703d 100644
--- a/drivers/mtd/nand/raw/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
@@ -50,7 +50,7 @@ struct nand_flash_dev nand_flash_ids[] = {
 	{"H27UCG8T2ATR-BC 64G 3.3V 8-bit",
 		{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
 		  SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640,
-		  NAND_ECC_INFO(40, SZ_1K), 4 },
+		  NAND_ECC_INFO(40, SZ_1K) },
 
 	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
 	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 26/28] mtd: rawnand: toshiba: Choose the data interface for TH58NVG2S3HBAI4
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (24 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 25/28] mtd: rawnand: hynix: Implement ->choose_data_interface() for H27UCG8T2ATR-BC Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 22:10   ` Boris Brezillon
  2020-05-26 19:17 ` [PATCH v5 27/28] mtd: rawnand: Get rid of the default ONFI timing mode Miquel Raynal
  2020-05-26 19:17 ` [PATCH v5 28/28] mtd: rawnand: Allocate the best data interface structure dynamically Miquel Raynal
  27 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

From: Rickard x Andersson <rickaran@axis.com>

The Kioxia/Toshiba TH58NVG2S3HBAI4 NAND memory is not ONFI compliant.
The timings of the NAND chip memory are quite close to ONFI mode 4 but
is breaking that spec.

By providing our own set of timings, erase block read speed is increased
from 6910 kiB/s to 13490 kiB/s and erase block write speed is increased
from 3350 kiB/s to 4410 kiB/s.

Tested on IMX6SX which has a NAND controller supporting EDO mode.

Signed-off-by: Rickard x Andersson <rickaran@axis.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_ids.c     |  3 +++
 drivers/mtd/nand/raw/nand_toshiba.c | 39 +++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
index 3b890d55703d..b9945791a9d7 100644
--- a/drivers/mtd/nand/raw/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
@@ -51,6 +51,9 @@ struct nand_flash_dev nand_flash_ids[] = {
 		{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
 		  SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640,
 		  NAND_ECC_INFO(40, SZ_1K) },
+	{"TH58NVG2S3HBAI4 4G 3.3V 8-bit",
+		{ .id = {0x98, 0xdc, 0x91, 0x15, 0x76} },
+		  SZ_2K, SZ_512, SZ_128K, 0, 5, 128, NAND_ECC_INFO(8, SZ_512) },
 
 	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
 	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index 860ae0c13063..fc044b3424a7 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -218,6 +218,36 @@ static int tc58nvg0s3e_choose_data_interface(struct nand_chip *chip,
 	return nand_choose_best_sdr_timings(chip, iface, NULL);
 }
 
+static int
+th58nvg2s3hbai4_choose_data_interface(struct nand_chip *chip,
+				      struct nand_data_interface *iface)
+{
+	struct nand_sdr_timings *sdr = &iface->timings.sdr;
+	int ret;
+
+	/* Start with timings from the closest timing mode, mode 4. */
+	ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE, 4);
+	if (ret)
+		return ret;
+
+	/* Patch timings that differ from mode 4. */
+	sdr->tALS_min = 12000;
+	sdr->tCHZ_max = 20000;
+	sdr->tCLS_min = 12000;
+	sdr->tCOH_min = 0;
+	sdr->tDS_min = 12000;
+	sdr->tRHOH_min = 25000;
+	sdr->tRHW_min = 30000;
+	sdr->tRHZ_max = 60000;
+	sdr->tWHR_min = 60000;
+
+	/* Patch timings not part of onfi timing mode. */
+	sdr->tPROG_max = 700000000;
+	sdr->tBERS_max = 5000000000;
+
+	return nand_choose_best_sdr_timings(chip, iface, sdr);
+}
+
 static int tc58teg5dclta00_init(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
@@ -236,6 +266,13 @@ static int tc58nvg0s3e_init(struct nand_chip *chip)
 	return 0;
 }
 
+static int th58nvg2s3hbai4_init(struct nand_chip *chip)
+{
+	chip->ops.choose_data_interface = th58nvg2s3hbai4_choose_data_interface;
+
+	return 0;
+}
+
 static int toshiba_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
@@ -250,6 +287,8 @@ static int toshiba_nand_init(struct nand_chip *chip)
 		tc58teg5dclta00_init(chip);
 	if (!strcmp("TC58NVG0S3E", chip->parameters.model))
 		tc58nvg0s3e_init(chip);
+	if (!strncmp("TH58NVG2S3HBAI4", chip->parameters.model, 15))
+		th58nvg2s3hbai4_init(chip);
 
 	return 0;
 }
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 27/28] mtd: rawnand: Get rid of the default ONFI timing mode
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (25 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 26/28] mtd: rawnand: toshiba: Choose the data interface for TH58NVG2S3HBAI4 Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 22:13   ` Boris Brezillon
  2020-05-26 19:17 ` [PATCH v5 28/28] mtd: rawnand: Allocate the best data interface structure dynamically Miquel Raynal
  27 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

The ->choose_data_interface() hook is here for manufacturer drivers to
provide a better timing interface than the default one, this field is
not needed anymore.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_base.c | 19 +++++--------------
 include/linux/mtd/rawnand.h      |  9 ---------
 2 files changed, 5 insertions(+), 23 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index f14d297c50f4..2547136a9cd7 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -1010,17 +1010,15 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
  * @iface: the data interface (can eventually be updated)
  * @spec_timings: specific timings, when not fitting the ONFI specification
  *
- * If specific timings are provided, use them. Otherwise, try to retrieve
- * supported timing modes from ONFI information. Finally, if the NAND chip does
- * not follow the ONFI specification, rely on the ->default_timing_mode
- * specified in the nand_ids table.
+ * If specific timings are provided, use them. Otherwise, retrieve supported
+ * timing modes from ONFI information.
  */
 int nand_choose_best_sdr_timings(struct nand_chip *chip,
 				 struct nand_data_interface *iface,
 				 struct nand_sdr_timings *spec_timings)
 {
 	const struct nand_controller_ops *ops = chip->controller->ops;
-	int best_mode = 0, onfi_modes, mode, ret;
+	int best_mode = 0, mode, ret;
 
 	iface->type = NAND_SDR_IFACE;
 
@@ -1037,13 +1035,8 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
 
 		/* Fallback to slower modes */
 		best_mode = iface->timings.mode;
-	} else {
-		if (chip->parameters.onfi) {
-			onfi_modes = chip->parameters.onfi->async_timing_mode;
-			best_mode = fls(onfi_modes) - 1;
-		} else {
-			best_mode = chip->onfi_timing_mode_default;
-		}
+	} else if (chip->parameters.onfi) {
+		best_mode = fls(chip->parameters.onfi->async_timing_mode) - 1;
 	}
 
 	for (mode = best_mode; mode >= 0; mode--) {
@@ -4822,8 +4815,6 @@ static bool find_full_id_nand(struct nand_chip *chip,
 		chip->options |= type->options;
 		chip->base.eccreq.strength = NAND_ECC_STRENGTH(type);
 		chip->base.eccreq.step_size = NAND_ECC_STEP(type);
-		chip->onfi_timing_mode_default =
-					type->onfi_timing_mode_default;
 
 		chip->parameters.model = kstrdup(type->name, GFP_KERNEL);
 		if (!chip->parameters.model)
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 5bd79e853140..00557e553827 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1070,9 +1070,6 @@ struct nand_manufacturer {
  * @options: Various chip options. They can partly be set to inform nand_scan
  *           about special functionality. See the defines for further
  *           explanation.
- * @onfi_timing_mode_default: Default ONFI timing mode. This field is set to the
- *			      actually used ONFI mode if the chip is ONFI
- *			      compliant or deduced from the datasheet otherwise
  * @data_interface: NAND interface timing information
  * @bbt_erase_shift: Number of address bits in a bbt entry
  * @bbt_options: Bad block table specific options. All options used here must
@@ -1120,7 +1117,6 @@ struct nand_chip {
 	unsigned int options;
 
 	/* Data interface */
-	int onfi_timing_mode_default;
 	struct nand_data_interface data_interface;
 
 	/* Bad block information */
@@ -1271,10 +1267,6 @@ nand_get_sdr_timings(struct nand_chip *chip)
  *               @ecc_step_ds in nand_chip{}, also from the datasheet.
  *               For example, the "4bit ECC for each 512Byte" can be set with
  *               NAND_ECC_INFO(4, 512).
- * @onfi_timing_mode_default: the default ONFI timing mode entered after a NAND
- *			      reset. Should be deduced from timings described
- *			      in the datasheet.
- *
  */
 struct nand_flash_dev {
 	char *name;
@@ -1295,7 +1287,6 @@ struct nand_flash_dev {
 		uint16_t strength_ds;
 		uint16_t step_ds;
 	} ecc;
-	int onfi_timing_mode_default;
 };
 
 int nand_create_bbt(struct nand_chip *chip);
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH v5 28/28] mtd: rawnand: Allocate the best data interface structure dynamically
  2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (26 preceding siblings ...)
  2020-05-26 19:17 ` [PATCH v5 27/28] mtd: rawnand: Get rid of the default ONFI timing mode Miquel Raynal
@ 2020-05-26 19:17 ` Miquel Raynal
  2020-05-26 22:28   ` Boris Brezillon
  27 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-26 19:17 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Boris Brezillon, Miquel Raynal

Instead of manipulating the statically allocated structure and copy
timings around, allocate one at identification time and save it in the
nand_chip structure once it has been initialized.

This way, either there is a "best data interface" and the requested
timings will be these, or there is none, forcing the core to use the
default set, statically defined in the core, shared across all NAND
chips.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_base.c | 42 ++++++++++++++++++++++----------
 include/linux/mtd/rawnand.h      | 13 +++++++---
 2 files changed, 39 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 2547136a9cd7..247bf5faaf55 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -947,7 +947,7 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
  */
 static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
 {
-	u8 mode = chip->data_interface.timings.mode;
+	u8 mode = chip->best_iface->timings.mode;
 	u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { mode, };
 	int ret;
 
@@ -966,7 +966,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
 
 	/* Change the mode on the controller side */
 	ret = chip->controller->ops->setup_data_interface(chip, chipnr,
-							&chip->data_interface);
+							  chip->best_iface);
 	if (ret)
 		return ret;
 
@@ -1030,8 +1030,10 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
 		ret = ops->setup_data_interface(chip,
 						NAND_DATA_IFACE_CHECK_ONLY,
 						iface);
-		if (!ret)
+		if (!ret) {
+			chip->best_iface = iface;
 			return ret;
+		}
 
 		/* Fallback to slower modes */
 		best_mode = iface->timings.mode;
@@ -1052,6 +1054,8 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
 			break;
 	}
 
+	chip->best_iface = iface;
+
 	return 0;
 }
 
@@ -1070,14 +1074,25 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
  */
 static int nand_choose_data_interface(struct nand_chip *chip)
 {
+	struct nand_data_interface *iface;
+	int ret;
+
 	if (!nand_controller_has_setup_data_iface(chip))
 		return 0;
 
+	iface = kzalloc(sizeof(*iface), GFP_KERNEL);
+	if (!iface)
+		return -ENOMEM;
+
 	if (chip->ops.choose_data_interface)
-		return chip->ops.choose_data_interface(chip,
-						       &chip->data_interface);
+		ret = chip->ops.choose_data_interface(chip, iface);
+	else
+		ret = nand_choose_best_sdr_timings(chip, iface, NULL);
 
-	return nand_choose_best_sdr_timings(chip, &chip->data_interface, NULL);
+	if (ret)
+		kfree(iface);
+
+	return ret;
 }
 
 /**
@@ -2514,8 +2529,7 @@ int nand_reset(struct nand_chip *chip, int chipnr)
 	 * nand_setup_data_interface() uses ->set/get_features() which would
 	 * fail anyway as the parameter page is not available yet.
 	 */
-	if (!memcmp(&chip->data_interface, nand_reset_data_iface,
-		    sizeof(*nand_reset_data_iface)))
+	if (!chip->best_iface)
 		return 0;
 
 	ret = nand_setup_data_interface(chip, chipnr);
@@ -5252,9 +5266,6 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
 
 	mutex_init(&chip->lock);
 
-	/* Enforce the right timings for reset/detection */
-	onfi_fill_data_interface(chip, &chip->data_interface, NAND_SDR_IFACE, 0);
-
 	ret = nand_dt_init(chip);
 	if (ret)
 		return ret;
@@ -6059,7 +6070,7 @@ static int nand_scan_tail(struct nand_chip *chip)
 	for (i = 0; i < nanddev_ntargets(&chip->base); i++) {
 		ret = nand_setup_data_interface(chip, i);
 		if (ret)
-			goto err_nanddev_cleanup;
+			goto err_free_data_iface;
 	}
 
 	/* Check, if we should skip the bad block table scan */
@@ -6069,10 +6080,12 @@ static int nand_scan_tail(struct nand_chip *chip)
 	/* Build bad block table */
 	ret = nand_create_bbt(chip);
 	if (ret)
-		goto err_nanddev_cleanup;
+		goto err_free_data_iface;
 
 	return 0;
 
+err_free_data_iface:
+	kfree(chip->best_iface);
 
 err_nanddev_cleanup:
 	nanddev_cleanup(&chip->base);
@@ -6166,6 +6179,9 @@ void nand_cleanup(struct nand_chip *chip)
 			& NAND_BBT_DYNAMICSTRUCT)
 		kfree(chip->badblock_pattern);
 
+	/* Free the data interface */
+	kfree(chip->best_iface);
+
 	/* Free manufacturer priv data. */
 	nand_manufacturer_cleanup(chip);
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 00557e553827..0f215faa3072 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1070,7 +1070,9 @@ struct nand_manufacturer {
  * @options: Various chip options. They can partly be set to inform nand_scan
  *           about special functionality. See the defines for further
  *           explanation.
- * @data_interface: NAND interface timing information
+ * @best_iface: The best NAND data interface which fits both the NAND chip and
+ *              NAND controller constraints. If unset, the default reset data
+ *              interface must be used.
  * @bbt_erase_shift: Number of address bits in a bbt entry
  * @bbt_options: Bad block table specific options. All options used here must
  *               come from bbm.h. By default, these options will be copied to
@@ -1117,7 +1119,7 @@ struct nand_chip {
 	unsigned int options;
 
 	/* Data interface */
-	struct nand_data_interface data_interface;
+	struct nand_data_interface *best_iface;
 
 	/* Bad block information */
 	unsigned int bbt_erase_shift;
@@ -1212,7 +1214,12 @@ extern const struct nand_data_interface *nand_reset_data_iface;
 static inline const struct nand_sdr_timings *
 nand_get_sdr_timings(struct nand_chip *chip)
 {
-	return nand_extract_sdr_timings(&chip->data_interface);
+	const struct nand_data_interface *iface = chip->best_iface;
+
+	if (!iface)
+		iface = nand_reset_data_iface;
+
+	return nand_extract_sdr_timings(iface);
 }
 
 /*
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 16/28] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max
  2020-05-26 19:17 ` [PATCH v5 16/28] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max Miquel Raynal
@ 2020-05-26 20:32   ` Boris Brezillon
  2020-05-26 21:25   ` Boris Brezillon
  1 sibling, 0 replies; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 20:32 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:13 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> The ONFI parameter page of a chip might define more fine grained
> tPROG_max and tBERS_max. When we do not have this information, we
> default to the highest possible values (they are maxima anyway).
> 
> There is no point setting these fields at runtime, so explicitly move
> these defaults to the main ONFI SDR timings structure.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/nand_timings.c | 24 ++++++++++++------------
>  1 file changed, 12 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
> index c2286a75d134..52ee83e75646 100644
> --- a/drivers/mtd/nand/raw/nand_timings.c
> +++ b/drivers/mtd/nand/raw/nand_timings.c
> @@ -20,6 +20,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
>  		.timings.sdr = {
>  			.tCCS_min = 500000,
>  			.tR_max = 200000000,
> +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
>  			.tADL_min = 400000,
>  			.tALH_min = 20000,
>  			.tALS_min = 50000,
> @@ -63,6 +65,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
>  		.timings.sdr = {
>  			.tCCS_min = 500000,
>  			.tR_max = 200000000,
> +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
>  			.tADL_min = 400000,
>  			.tALH_min = 10000,
>  			.tALS_min = 25000,
> @@ -106,6 +110,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
>  		.timings.sdr = {
>  			.tCCS_min = 500000,
>  			.tR_max = 200000000,
> +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
>  			.tADL_min = 400000,
>  			.tALH_min = 10000,
>  			.tALS_min = 15000,
> @@ -149,6 +155,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
>  		.timings.sdr = {
>  			.tCCS_min = 500000,
>  			.tR_max = 200000000,
> +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
>  			.tADL_min = 400000,
>  			.tALH_min = 5000,
>  			.tALS_min = 10000,
> @@ -192,6 +200,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
>  		.timings.sdr = {
>  			.tCCS_min = 500000,
>  			.tR_max = 200000000,
> +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
>  			.tADL_min = 400000,
>  			.tALH_min = 5000,
>  			.tALS_min = 10000,
> @@ -235,6 +245,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
>  		.timings.sdr = {
>  			.tCCS_min = 500000,
>  			.tR_max = 200000000,
> +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
>  			.tADL_min = 400000,
>  			.tALH_min = 5000,
>  			.tALS_min = 10000,
> @@ -359,18 +371,6 @@ int onfi_fill_data_interface(struct nand_chip *chip,
>  
>  		/* nanoseconds -> picoseconds */
>  		timings->tCCS_min = 1000UL * onfi->tCCS;
> -	} else {
> -		struct nand_sdr_timings *timings = &iface->timings.sdr;
> -		/*
> -		 * For non-ONFI chips we use the highest possible value for
> -		 * tPROG and tBERS. tR and tCCS will take the default values
> -		 * precised in the ONFI specification for timing mode 0,
> -		 * respectively 200us and 500ns.
> -		 */
> -

I'm not entirely sure that's an improvement. You actually duplicate the
assignment and get rid of a comment that's useful IMHO. 

> -		/* microseconds -> picoseconds */
> -		timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
> -		timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
>  	}
>  
>  	return 0;


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 15/28] mtd: rawnand: timings: Avoid redefining tR_max and tCCS_min
  2020-05-26 19:17 ` [PATCH v5 15/28] mtd: rawnand: timings: Avoid redefining tR_max and tCCS_min Miquel Raynal
@ 2020-05-26 20:33   ` Boris Brezillon
  0 siblings, 0 replies; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 20:33 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:12 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> These two values are already hardcoded in the default ONFI timing
> structure, no need to redefine them here.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/nand_timings.c | 3 ---
>  1 file changed, 3 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
> index 3c44c4b90536..c2286a75d134 100644
> --- a/drivers/mtd/nand/raw/nand_timings.c
> +++ b/drivers/mtd/nand/raw/nand_timings.c
> @@ -371,9 +371,6 @@ int onfi_fill_data_interface(struct nand_chip *chip,
>  		/* microseconds -> picoseconds */
>  		timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
>  		timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
> -
> -		timings->tR_max = 200000000;
> -		timings->tCCS_min = 500000;

I'd rather drop the definitions in the ONFI timings and keep that one.

>  	}
>  
>  	return 0;


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 17/28] mtd: rawnand: Define a unique reset data interface
  2020-05-26 19:17 ` [PATCH v5 17/28] mtd: rawnand: Define a unique reset data interface Miquel Raynal
@ 2020-05-26 21:23   ` Boris Brezillon
  2020-05-27  7:20     ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 21:23 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:14 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> All NAND chips will always use the same data interface for reset and
> at startup: SDR mode 0. Instead of copying around the data interface
> timings, let's just have a default reset data interface for that.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/nand_base.c    | 9 +++------
>  drivers/mtd/nand/raw/nand_timings.c | 3 +++
>  include/linux/mtd/rawnand.h         | 3 +++
>  3 files changed, 9 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 89f10a8c1d62..1005035c233a 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -927,9 +927,8 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
>  	 * timings to timing mode 0.
>  	 */
>  
> -	onfi_fill_data_interface(chip, &chip->data_interface, NAND_SDR_IFACE, 0);
>  	ret = chip->controller->ops->setup_data_interface(chip, chipnr,
> -							&chip->data_interface);
> +							  nand_reset_data_iface);
>  	if (ret)
>  		pr_err("Failed to configure data interface to SDR timing mode 0\n");
>  
> @@ -2484,7 +2483,6 @@ EXPORT_SYMBOL_GPL(nand_subop_get_data_len);
>   */
>  int nand_reset(struct nand_chip *chip, int chipnr)
>  {
> -	struct nand_data_interface saved_data_intf = chip->data_interface;
>  	int ret;
>  
>  	ret = nand_reset_data_interface(chip, chipnr);
> @@ -2509,11 +2507,10 @@ int nand_reset(struct nand_chip *chip, int chipnr)
>  	 * nand_setup_data_interface() uses ->set/get_features() which would
>  	 * fail anyway as the parameter page is not available yet.
>  	 */
> -	if (!memcmp(&chip->data_interface, &saved_data_intf,
> -		    sizeof(saved_data_intf)))
> +	if (!memcmp(&chip->data_interface, nand_reset_data_iface,
> +		    sizeof(*nand_reset_data_iface)))
>  		return 0;
>  
> -	chip->data_interface = saved_data_intf;
>  	ret = nand_setup_data_interface(chip, chipnr);
>  	if (ret)
>  		return ret;
> diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
> index 52ee83e75646..343284c43e81 100644
> --- a/drivers/mtd/nand/raw/nand_timings.c
> +++ b/drivers/mtd/nand/raw/nand_timings.c
> @@ -285,6 +285,9 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
>  	},
>  };
>  
> +/* All NAND chips share the same reset data interface: SDR mode 0 */
> +const struct nand_data_interface *nand_reset_data_iface = &onfi_sdr_timings[0];

Can we make that one a function?

const struct nand_data_interface *nand_get_reset_data_interface(void)
{
	return &onfi_sdr_timings[0];
}

> +
>  /**
>   * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a
>   *                              set of timings
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index 622da6527a36..6c334cca3977 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -1203,6 +1203,9 @@ static inline struct device_node *nand_get_flash_node(struct nand_chip *chip)
>  	return mtd_get_of_node(nand_to_mtd(chip));
>  }
>  
> +/* Default/reset data interface */
> +extern const struct nand_data_interface *nand_reset_data_iface;
> +
>  /*
>   * A helper for defining older NAND chips where the second ID byte fully
>   * defined the chip, including the geometry (chip size, eraseblock size, page


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 16/28] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max
  2020-05-26 19:17 ` [PATCH v5 16/28] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max Miquel Raynal
  2020-05-26 20:32   ` Boris Brezillon
@ 2020-05-26 21:25   ` Boris Brezillon
  2020-05-27  7:17     ` Miquel Raynal
  1 sibling, 1 reply; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 21:25 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:13 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> The ONFI parameter page of a chip might define more fine grained
> tPROG_max and tBERS_max. When we do not have this information, we
> default to the highest possible values (they are maxima anyway).
> 
> There is no point setting these fields at runtime, so explicitly move
> these defaults to the main ONFI SDR timings structure.

Okay, now I see why you're doing that: you want to return the mode 0
entry directly, and it makes sense, but it should be explained in the
commit message.

> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/nand_timings.c | 24 ++++++++++++------------
>  1 file changed, 12 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
> index c2286a75d134..52ee83e75646 100644
> --- a/drivers/mtd/nand/raw/nand_timings.c
> +++ b/drivers/mtd/nand/raw/nand_timings.c
> @@ -20,6 +20,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
>  		.timings.sdr = {
>  			.tCCS_min = 500000,
>  			.tR_max = 200000000,
> +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
>  			.tADL_min = 400000,
>  			.tALH_min = 20000,
>  			.tALS_min = 50000,
> @@ -63,6 +65,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
>  		.timings.sdr = {
>  			.tCCS_min = 500000,
>  			.tR_max = 200000000,
> +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
>  			.tADL_min = 400000,
>  			.tALH_min = 10000,
>  			.tALS_min = 25000,
> @@ -106,6 +110,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
>  		.timings.sdr = {
>  			.tCCS_min = 500000,
>  			.tR_max = 200000000,
> +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
>  			.tADL_min = 400000,
>  			.tALH_min = 10000,
>  			.tALS_min = 15000,
> @@ -149,6 +155,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
>  		.timings.sdr = {
>  			.tCCS_min = 500000,
>  			.tR_max = 200000000,
> +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
>  			.tADL_min = 400000,
>  			.tALH_min = 5000,
>  			.tALS_min = 10000,
> @@ -192,6 +200,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
>  		.timings.sdr = {
>  			.tCCS_min = 500000,
>  			.tR_max = 200000000,
> +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
>  			.tADL_min = 400000,
>  			.tALH_min = 5000,
>  			.tALS_min = 10000,
> @@ -235,6 +245,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
>  		.timings.sdr = {
>  			.tCCS_min = 500000,
>  			.tR_max = 200000000,
> +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
>  			.tADL_min = 400000,
>  			.tALH_min = 5000,
>  			.tALS_min = 10000,
> @@ -359,18 +371,6 @@ int onfi_fill_data_interface(struct nand_chip *chip,
>  
>  		/* nanoseconds -> picoseconds */
>  		timings->tCCS_min = 1000UL * onfi->tCCS;
> -	} else {
> -		struct nand_sdr_timings *timings = &iface->timings.sdr;
> -		/*
> -		 * For non-ONFI chips we use the highest possible value for
> -		 * tPROG and tBERS. tR and tCCS will take the default values
> -		 * precised in the ONFI specification for timing mode 0,
> -		 * respectively 200us and 500ns.
> -		 */
> -
> -		/* microseconds -> picoseconds */
> -		timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
> -		timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
>  	}
>  
>  	return 0;


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 18/28] mtd: rawnand: marvell: Use a helper to access the timings
  2020-05-26 19:17 ` [PATCH v5 18/28] mtd: rawnand: marvell: Use a helper to access the timings Miquel Raynal
@ 2020-05-26 21:26   ` Boris Brezillon
  0 siblings, 0 replies; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 21:26 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:15 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Do not access the SDR timings directly but use nand_get_sdr_timings()
> instead. This way, future patching over this helper will be easier.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
>  drivers/mtd/nand/raw/marvell_nand.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
> index 260a0430313e..ebf45a2754f1 100644
> --- a/drivers/mtd/nand/raw/marvell_nand.c
> +++ b/drivers/mtd/nand/raw/marvell_nand.c
> @@ -1096,6 +1096,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip,
>  						const u8 *oob_buf, bool raw,
>  						int page)
>  {
> +	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface);
>  	struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
>  	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
>  	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
> @@ -1140,8 +1141,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip,
>  	if (ret)
>  		return ret;
>  
> -	ret = marvell_nfc_wait_op(chip,
> -				  PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max));
> +	ret = marvell_nfc_wait_op(chip, PSEC_TO_MSEC(sdr->tPROG_max));
>  	return ret;
>  }
>  
> @@ -1562,6 +1562,7 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip,
>  					     const u8 *buf,
>  					     int oob_required, int page)
>  {
> +	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface);
>  	struct mtd_info *mtd = nand_to_mtd(chip);
>  	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
>  	const u8 *data = buf;
> @@ -1598,8 +1599,7 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip,
>  		marvell_nfc_wait_ndrun(chip);
>  	}
>  
> -	ret = marvell_nfc_wait_op(chip,
> -				  PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max));
> +	ret = marvell_nfc_wait_op(chip, PSEC_TO_MSEC(sdr->tPROG_max));
>  
>  	marvell_nfc_disable_hw_ecc(chip);
>  


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 19/28] mtd: rawnand: legacy: Use a helper to access the timings
  2020-05-26 19:17 ` [PATCH v5 19/28] mtd: rawnand: legacy: " Miquel Raynal
@ 2020-05-26 21:28   ` Boris Brezillon
  0 siblings, 0 replies; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 21:28 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:16 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Do not access the SDR timings directly but use nand_get_sdr_timings()
> instead. This way, future patching over this helper will be easier.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
>  drivers/mtd/nand/raw/nand_legacy.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_legacy.c b/drivers/mtd/nand/raw/nand_legacy.c
> index 8b91aa7773d8..34b4c944f6a6 100644
> --- a/drivers/mtd/nand/raw/nand_legacy.c
> +++ b/drivers/mtd/nand/raw/nand_legacy.c
> @@ -354,6 +354,8 @@ static void nand_command(struct nand_chip *chip, unsigned int command,
>  
>  static void nand_ccs_delay(struct nand_chip *chip)
>  {
> +	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface);
> +
>  	/*
>  	 * The controller already takes care of waiting for tCCS when the RNDIN
>  	 * or RNDOUT command is sent, return directly.
> @@ -366,7 +368,7 @@ static void nand_ccs_delay(struct nand_chip *chip)
>  	 * (which should be safe for all NANDs).
>  	 */
>  	if (nand_controller_has_setup_data_iface(chip))
> -		ndelay(chip->data_interface.timings.sdr.tCCS_min / 1000);
> +		ndelay(sdr->tCCS_min / 1000);
>  	else
>  		ndelay(500);
>  }


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 20/28] mtd: rawnand: Hide the chip->data_interface indirection
  2020-05-26 19:17 ` [PATCH v5 20/28] mtd: rawnand: Hide the chip->data_interface indirection Miquel Raynal
@ 2020-05-26 21:36   ` Boris Brezillon
  2020-05-27  7:36     ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 21:36 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:17 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> As a preparation for allocating the data interface structure
> dynamically (and rename it), let's avoid calling it directly.
> 
> Instead, we operate a rename on an existing helper to reuse that name
> for another helper:
> * s/nand_get_sdr_timings/nand_extract_sdr_timings/
>   -> this helper just extracts timings from a given data interface

Hm, I'm not entirely happy with that name. In my mind extract means
that you had to do some transformation to get the data, which is not
the case here. How about nand_data_interface_get_sdr_timings()? 

> * nand_get_sdr_timings()
>   -> this helper retrieves the in use timings from a nand_chip structure

Do we really need that one? Can we do that in 2 steps instead?

conf = nand_get_data_interface_config(chip);
sdr = nand_data_interface_get_sdr_timings(conf);
  
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 14/28] mtd: rawnand: timings: Add a helper to find the closest ONFI mode
  2020-05-26 19:17 ` [PATCH v5 14/28] mtd: rawnand: timings: Add a helper to find the closest ONFI mode Miquel Raynal
@ 2020-05-26 21:42   ` Boris Brezillon
  2020-05-27  7:42     ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 21:42 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:11 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Vendors are allowed to provide their own set of timings. In this case,
> we provide a way to derive the "closest" timing mode so that, if the
> NAND controller does not support tweaking these parameters, it will be
> able to configure itself anyway.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/internals.h    |  2 ++
>  drivers/mtd/nand/raw/nand_timings.c | 49 +++++++++++++++++++++++++++++
>  2 files changed, 51 insertions(+)
> 
> diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
> index dc84e3b55d48..c7357ae86eeb 100644
> --- a/drivers/mtd/nand/raw/internals.h
> +++ b/drivers/mtd/nand/raw/internals.h
> @@ -88,6 +88,8 @@ int onfi_fill_data_interface(struct nand_chip *chip,
>  			     struct nand_data_interface *iface,
>  			     enum nand_data_interface_type type,
>  			     int timing_mode);
> +unsigned int
> +onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings);
>  int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
>  int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
>  int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf,
> diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
> index ce6bb87db2e8..3c44c4b90536 100644
> --- a/drivers/mtd/nand/raw/nand_timings.c
> +++ b/drivers/mtd/nand/raw/nand_timings.c
> @@ -273,6 +273,55 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
>  	},
>  };
>  
> +/**
> + * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a
> + *                              set of timings
> + * @spec_timings: the timings to challenge
> + */
> +unsigned int
> +onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings)
> +{
> +	const struct nand_sdr_timings *onfi_timings;
> +	int mode;
> +
> +	for (mode = ARRAY_SIZE(onfi_sdr_timings) - 1; mode > 0; mode--) {
> +		onfi_timings = &onfi_sdr_timings[mode].timings.sdr;
> +
> +		if (spec_timings->tCCS_min > onfi_timings->tCCS_min ||
> +		    spec_timings->tADL_min > onfi_timings->tADL_min ||
> +		    spec_timings->tALH_min > onfi_timings->tALH_min ||
> +		    spec_timings->tALS_min > onfi_timings->tALS_min ||
> +		    spec_timings->tAR_min > onfi_timings->tAR_min ||
> +		    spec_timings->tCEH_min > onfi_timings->tCEH_min ||
> +		    spec_timings->tCH_min > onfi_timings->tCH_min ||
> +		    spec_timings->tCLH_min > onfi_timings->tCLH_min ||
> +		    spec_timings->tCLR_min > onfi_timings->tCLR_min ||
> +		    spec_timings->tCLS_min > onfi_timings->tCLS_min ||
> +		    spec_timings->tCOH_min > onfi_timings->tCOH_min ||
> +		    spec_timings->tCS_min > onfi_timings->tCS_min ||
> +		    spec_timings->tDH_min > onfi_timings->tDH_min ||
> +		    spec_timings->tDS_min > onfi_timings->tDS_min ||
> +		    spec_timings->tIR_min > onfi_timings->tIR_min ||
> +		    spec_timings->tRC_min > onfi_timings->tRC_min ||
> +		    spec_timings->tREH_min > onfi_timings->tREH_min ||
> +		    spec_timings->tRHOH_min > onfi_timings->tRHOH_min ||
> +		    spec_timings->tRHW_min > onfi_timings->tRHW_min ||
> +		    spec_timings->tRLOH_min > onfi_timings->tRLOH_min ||
> +		    spec_timings->tRP_min > onfi_timings->tRP_min ||
> +		    spec_timings->tRR_min > onfi_timings->tRR_min ||
> +		    spec_timings->tWC_min > onfi_timings->tWC_min ||
> +		    spec_timings->tWH_min > onfi_timings->tWH_min ||
> +		    spec_timings->tWHR_min > onfi_timings->tWHR_min ||
> +		    spec_timings->tWP_min > onfi_timings->tWP_min ||
> +		    spec_timings->tWW_min > onfi_timings->tWW_min)

Just nitpicking but you could just do the opposite test ('<=' instead of
'>' and '&&' instead of '||') and return mode directly, so you don't
need this continue.

I didn't check if all the _min timings were tested, but assuming that's
the case, you can add

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> +			continue;
> +
> +		return mode;
> +	}
> +
> +	return 0;
> +}
> +
>  /**
>   * onfi_fill_data_interface - Initialize a data interface from a given ONFI mode
>   * @chip: The NAND chip


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 21/28] mtd: rawnand: Introduce nand_choose_best_sdr_timings()
  2020-05-26 19:17 ` [PATCH v5 21/28] mtd: rawnand: Introduce nand_choose_best_sdr_timings() Miquel Raynal
@ 2020-05-26 21:50   ` Boris Brezillon
  2020-05-27  7:45     ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 21:50 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:18 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Extract the logic out of nand_choose_data_interface() to create a
> public helper that can be reused by manufacturer drivers. Add the
> possibility to provide a specific set of timings.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/internals.h |   3 +
>  drivers/mtd/nand/raw/nand_base.c | 104 +++++++++++++++++++------------
>  2 files changed, 66 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
> index c7357ae86eeb..5c49c4d1e231 100644
> --- a/drivers/mtd/nand/raw/internals.h
> +++ b/drivers/mtd/nand/raw/internals.h
> @@ -90,6 +90,9 @@ int onfi_fill_data_interface(struct nand_chip *chip,
>  			     int timing_mode);
>  unsigned int
>  onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings);
> +int nand_choose_best_sdr_timings(struct nand_chip *chip,
> +				 struct nand_data_interface *iface,
> +				 struct nand_sdr_timings *spec_timings);
>  int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
>  int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
>  int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf,
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 6a7edd2e1357..b2e833a8ab9d 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -1003,61 +1003,83 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
>  	return ret;
>  }
>  
> +/**
> + * nand_choose_best_sdr_timings - Pick up the best SDR timings that both the
> + *                                NAND controller and the NAND chip support
> + * @chip: the NAND chip
> + * @iface: the data interface (can eventually be updated)
> + * @spec_timings: specific timings, when not fitting the ONFI specification
> + *
> + * If specific timings are provided, use them. Otherwise, try to retrieve
> + * supported timing modes from ONFI information. Finally, if the NAND chip does
> + * not follow the ONFI specification, rely on the ->default_timing_mode
> + * specified in the nand_ids table.
> + */
> +int nand_choose_best_sdr_timings(struct nand_chip *chip,
> +				 struct nand_data_interface *iface,
> +				 struct nand_sdr_timings *spec_timings)
> +{
> +	const struct nand_controller_ops *ops = chip->controller->ops;
> +	int best_mode = 0, onfi_modes, mode, ret;
> +
> +	iface->type = NAND_SDR_IFACE;
> +
> +	if (spec_timings) {
> +		iface->timings.sdr = *spec_timings;
> +		iface->timings.mode = onfi_find_closest_sdr_mode(spec_timings);
> +
> +		/* Verify the controller supports the requested interface */
> +		ret = ops->setup_data_interface(chip,
> +						NAND_DATA_IFACE_CHECK_ONLY,
> +						iface);
> +		if (!ret)
> +			return ret;
> +
> +		/* Fallback to slower modes */
> +		best_mode = iface->timings.mode;
> +	} else {
> +		if (chip->parameters.onfi) {

onfi_modes var should be declared here.

> +			onfi_modes = chip->parameters.onfi->async_timing_mode;
> +			best_mode = fls(onfi_modes) - 1;
> +		} else {
> +			best_mode = chip->onfi_timing_mode_default;
> +		}
> +	}
> +
> +
> +	for (mode = best_mode; mode >= 0; mode--) {
> +		ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE,
> +					       mode);
> +		if (ret)
> +			continue;

In practice onfi_fill_data_interface() will only return an error if you
pass a type that's not SDR (not the case here, or a mode that's outside
the SDR mode bounds). Maybe we should just clamp the value/warn when
that happens and make onfi_fill_data_interface() a void function.

> +
> +		ret = ops->setup_data_interface(chip,
> +						NAND_DATA_IFACE_CHECK_ONLY,
> +						iface);
> +		if (!ret)
> +			break;

			return 0;

> +	}
> +
> +	return 0;
> +}
> +
>  /**
>   * nand_choose_data_interface - find the best data interface and timings
>   * @chip: The NAND chip
>   *
>   * Find the best data interface and NAND timings supported by the chip
>   * and the driver.
> - * First tries to retrieve supported timing modes from ONFI information,
> - * and if the NAND chip does not support ONFI, relies on the
> - * ->onfi_timing_mode_default specified in the nand_ids table. After this
> - * function nand_chip->data_interface is initialized with the best timing mode
> - * available.
> + * After this function nand_chip->data_interface is initialized with the best
> + * timing mode available.
>   *
>   * Returns 0 for success or negative error code otherwise.
>   */
>  static int nand_choose_data_interface(struct nand_chip *chip)
>  {
> -	int modes, mode, ret;
> -
>  	if (!nand_controller_has_setup_data_iface(chip))
>  		return 0;
>  
> -	/*
> -	 * First try to identify the best timings from ONFI parameters and
> -	 * if the NAND does not support ONFI, fallback to the default ONFI
> -	 * timing mode.
> -	 */
> -	if (chip->parameters.onfi) {
> -		modes = chip->parameters.onfi->async_timing_mode;
> -	} else {
> -		if (!chip->onfi_timing_mode_default)
> -			return 0;
> -
> -		modes = GENMASK(chip->onfi_timing_mode_default, 0);
> -	}
> -
> -	for (mode = fls(modes) - 1; mode >= 0; mode--) {
> -		ret = onfi_fill_data_interface(chip, &chip->data_interface,
> -					       NAND_SDR_IFACE, mode);
> -		if (ret)
> -			continue;
> -
> -		/*
> -		 * Pass NAND_DATA_IFACE_CHECK_ONLY to only check if the
> -		 * controller supports the requested timings.
> -		 */
> -		ret = chip->controller->ops->setup_data_interface(chip,
> -						 NAND_DATA_IFACE_CHECK_ONLY,
> -						 &chip->data_interface);
> -		if (!ret) {
> -			chip->onfi_timing_mode_default = mode;
> -			break;
> -		}
> -	}
> -
> -	return 0;
> +	return nand_choose_best_sdr_timings(chip, &chip->data_interface, NULL);
>  }
>  
>  /**


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 22/28] mtd: rawnand: Add the ->choose_data_interface() hook
  2020-05-26 19:17 ` [PATCH v5 22/28] mtd: rawnand: Add the ->choose_data_interface() hook Miquel Raynal
@ 2020-05-26 21:52   ` Boris Brezillon
  2020-05-27  7:46     ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 21:52 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:19 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> This hook can be overloaded by NAND manufacturer drivers to propose
> alternative timings when not following the main standards. In this
> case, the manufacturer drivers is responsible for choosing the best
> data interface and configuration that fits both the controller and

		  ^ s/and//

> chip capabilities.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/nand_base.c | 9 +++++++--
>  include/linux/mtd/rawnand.h      | 3 +++
>  2 files changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index b2e833a8ab9d..f14d297c50f4 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -1046,7 +1046,6 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
>  		}
>  	}
>  
> -

Should this line removal be part of another patch?

>  	for (mode = best_mode; mode >= 0; mode--) {
>  		ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE,
>  					       mode);
> @@ -1068,7 +1067,9 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
>   * @chip: The NAND chip
>   *
>   * Find the best data interface and NAND timings supported by the chip
> - * and the driver.
> + * and the driver. Eventually let the NAND manufacturer driver propose his own
> + * set of timings.
> + *
>   * After this function nand_chip->data_interface is initialized with the best
>   * timing mode available.
>   *
> @@ -1079,6 +1080,10 @@ static int nand_choose_data_interface(struct nand_chip *chip)
>  	if (!nand_controller_has_setup_data_iface(chip))
>  		return 0;
>  
> +	if (chip->ops.choose_data_interface)
> +		return chip->ops.choose_data_interface(chip,
> +						       &chip->data_interface);
> +
>  	return nand_choose_best_sdr_timings(chip, &chip->data_interface, NULL);
>  }
>  
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index 2995d29587c3..5bd79e853140 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -1034,6 +1034,7 @@ struct nand_legacy {
>   * @lock_area: Lock operation
>   * @unlock_area: Unlock operation
>   * @setup_read_retry: Set the read-retry mode (mostly needed for MLC NANDs)
> + * @choose_data_interface: Choose the best data interface
>   */
>  struct nand_chip_ops {
>  	int (*suspend)(struct nand_chip *chip);
> @@ -1041,6 +1042,8 @@ struct nand_chip_ops {
>  	int (*lock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
>  	int (*unlock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
>  	int (*setup_read_retry)(struct nand_chip *chip, int retry_mode);
> +	int (*choose_data_interface)(struct nand_chip *chip,
> +				     struct nand_data_interface *iface);
>  };
>  
>  /**


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 23/28] mtd: rawnand: toshiba: Implement ->choose_data_interface() for TC58TEG5DCLTA00
  2020-05-26 19:17 ` [PATCH v5 23/28] mtd: rawnand: toshiba: Implement ->choose_data_interface() for TC58TEG5DCLTA00 Miquel Raynal
@ 2020-05-26 21:54   ` Boris Brezillon
  0 siblings, 0 replies; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 21:54 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:20 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Implement this hook for the tc58teg5dclta00 NAND chip and stop setting
> ->default_timing_mode.  
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
>  drivers/mtd/nand/raw/nand_toshiba.c | 15 ++++++++++++++-
>  1 file changed, 14 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
> index 302d4a6e175b..fe2bc20972a9 100644
> --- a/drivers/mtd/nand/raw/nand_toshiba.c
> +++ b/drivers/mtd/nand/raw/nand_toshiba.c
> @@ -193,11 +193,24 @@ static void toshiba_nand_decode_id(struct nand_chip *chip)
>  	}
>  }
>  
> +static int
> +tc58teg5dclta00_choose_data_interface(struct nand_chip *chip,
> +				      struct nand_data_interface *iface)
> +{
> +	int ret;
> +
> +	ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE, 5);
> +	if (ret)
> +		return ret;
> +
> +	return nand_choose_best_sdr_timings(chip, iface, NULL);
> +}
> +
>  static int tc58teg5dclta00_init(struct nand_chip *chip)
>  {
>  	struct mtd_info *mtd = nand_to_mtd(chip);
>  
> -	chip->onfi_timing_mode_default = 5;
> +	chip->ops.choose_data_interface = &tc58teg5dclta00_choose_data_interface;
>  	chip->options |= NAND_NEED_SCRAMBLING;
>  	mtd_set_pairing_scheme(mtd, &dist3_pairing_scheme);
>  


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 24/28] mtd: rawnand: toshiba: Implement ->choose_data_interface() for TC58NVG0S3E
  2020-05-26 19:17 ` [PATCH v5 24/28] mtd: rawnand: toshiba: Implement ->choose_data_interface() for TC58NVG0S3E Miquel Raynal
@ 2020-05-26 22:02   ` Boris Brezillon
  2020-05-27  7:47     ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 22:02 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:21 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> This chip supports ONFI SDR timing mode 2, implement the new hook to
> advertize it.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/nand_ids.c     |  3 +--
>  drivers/mtd/nand/raw/nand_toshiba.c | 21 +++++++++++++++++++++
>  2 files changed, 22 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
> index e0dbc2e316c7..c729a8bc895d 100644
> --- a/drivers/mtd/nand/raw/nand_ids.c
> +++ b/drivers/mtd/nand/raw/nand_ids.c
> @@ -28,8 +28,7 @@ struct nand_flash_dev nand_flash_ids[] = {
>  	 */
>  	{"TC58NVG0S3E 1G 3.3V 8-bit",
>  		{ .id = {0x98, 0xd1, 0x90, 0x15, 0x76, 0x14, 0x01, 0x00} },
> -		  SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512),
> -		  2 },
> +		  SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512), },
>  	{"TC58NVG2S0F 4G 3.3V 8-bit",
>  		{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} },
>  		  SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) },
> diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
> index fe2bc20972a9..860ae0c13063 100644
> --- a/drivers/mtd/nand/raw/nand_toshiba.c
> +++ b/drivers/mtd/nand/raw/nand_toshiba.c
> @@ -206,6 +206,18 @@ tc58teg5dclta00_choose_data_interface(struct nand_chip *chip,
>  	return nand_choose_best_sdr_timings(chip, iface, NULL);
>  }
>  
> +static int tc58nvg0s3e_choose_data_interface(struct nand_chip *chip,
> +					     struct nand_data_interface *iface)
> +{
> +	int ret;
> +
> +	ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE, 2);
> +	if (ret)
> +		return ret;
> +
> +	return nand_choose_best_sdr_timings(chip, iface, NULL);
> +}
> +
>  static int tc58teg5dclta00_init(struct nand_chip *chip)
>  {
>  	struct mtd_info *mtd = nand_to_mtd(chip);
> @@ -217,6 +229,13 @@ static int tc58teg5dclta00_init(struct nand_chip *chip)
>  	return 0;
>  }
>  
> +static int tc58nvg0s3e_init(struct nand_chip *chip)
> +{
> +	chip->ops.choose_data_interface = &tc58nvg0s3e_choose_data_interface;
> +
> +	return 0;
> +}
> +
>  static int toshiba_nand_init(struct nand_chip *chip)
>  {
>  	if (nand_is_slc(chip))
> @@ -229,6 +248,8 @@ static int toshiba_nand_init(struct nand_chip *chip)
>  
>  	if (!strcmp("TC58TEG5DCLTA00", chip->parameters.model))
>  		tc58teg5dclta00_init(chip);
> +	if (!strcmp("TC58NVG0S3E", chip->parameters.model))

The model won't match "TC58NVG0S3E", unless you use strncmp().

> +		tc58nvg0s3e_init(chip);
>  
>  	return 0;
>  }


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 25/28] mtd: rawnand: hynix: Implement ->choose_data_interface() for H27UCG8T2ATR-BC
  2020-05-26 19:17 ` [PATCH v5 25/28] mtd: rawnand: hynix: Implement ->choose_data_interface() for H27UCG8T2ATR-BC Miquel Raynal
@ 2020-05-26 22:06   ` Boris Brezillon
  2020-05-27  7:50     ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 22:06 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:22 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> This chip supports ONFI SDR timing mode 4, implement the new hook to
> advertize it.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/nand_hynix.c | 16 ++++++++++++++++
>  drivers/mtd/nand/raw/nand_ids.c   |  2 +-
>  2 files changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
> index 7d1be53f27f3..d61a55121962 100644
> --- a/drivers/mtd/nand/raw/nand_hynix.c
> +++ b/drivers/mtd/nand/raw/nand_hynix.c
> @@ -673,6 +673,19 @@ static void hynix_nand_cleanup(struct nand_chip *chip)
>  	nand_set_manufacturer_data(chip, NULL);
>  }
>  
> +static int
> +h27ucg8t2atrbc_choose_data_interface(struct nand_chip *chip,
> +				     struct nand_data_interface *iface)
> +{
> +	int ret;
> +
> +	ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE, 4);
> +	if (ret)
> +		return ret;
> +
> +	return nand_choose_best_sdr_timings(chip, iface, NULL);
> +}
> +
>  static int hynix_nand_init(struct nand_chip *chip)
>  {
>  	struct hynix_nand *hynix;
> @@ -689,6 +702,9 @@ static int hynix_nand_init(struct nand_chip *chip)
>  
>  	nand_set_manufacturer_data(chip, hynix);
>  
> +	if (!strcmp("H27UCG8T2ATR-BC", chip->parameters.model))
> +		chip->ops.choose_data_interface = h27ucg8t2atrbc_choose_data_interface;

Same here. You either have to compare against "H27UCG8T2ATR-BC 64G 3.3V
8-bit" or use strncmp. This being said, I wonder if comparing the ID is
not simpler.

> +
>  	ret = hynix_nand_rr_init(chip);
>  	if (ret)
>  		hynix_nand_cleanup(chip);
> diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
> index c729a8bc895d..3b890d55703d 100644
> --- a/drivers/mtd/nand/raw/nand_ids.c
> +++ b/drivers/mtd/nand/raw/nand_ids.c
> @@ -50,7 +50,7 @@ struct nand_flash_dev nand_flash_ids[] = {
>  	{"H27UCG8T2ATR-BC 64G 3.3V 8-bit",
>  		{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
>  		  SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640,
> -		  NAND_ECC_INFO(40, SZ_1K), 4 },
> +		  NAND_ECC_INFO(40, SZ_1K) },
>  

Ultimately we should have those vendor specific entries defined in each
vendor driver rather than declared here (not asking that for this
series though).

>  	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
>  	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 26/28] mtd: rawnand: toshiba: Choose the data interface for TH58NVG2S3HBAI4
  2020-05-26 19:17 ` [PATCH v5 26/28] mtd: rawnand: toshiba: Choose the data interface for TH58NVG2S3HBAI4 Miquel Raynal
@ 2020-05-26 22:10   ` Boris Brezillon
  0 siblings, 0 replies; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 22:10 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:23 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> From: Rickard x Andersson <rickaran@axis.com>
> 
> The Kioxia/Toshiba TH58NVG2S3HBAI4 NAND memory is not ONFI compliant.
> The timings of the NAND chip memory are quite close to ONFI mode 4 but
> is breaking that spec.
> 
> By providing our own set of timings, erase block read speed is increased
> from 6910 kiB/s to 13490 kiB/s and erase block write speed is increased
> from 3350 kiB/s to 4410 kiB/s.
> 
> Tested on IMX6SX which has a NAND controller supporting EDO mode.
> 
> Signed-off-by: Rickard x Andersson <rickaran@axis.com>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/nand_ids.c     |  3 +++
>  drivers/mtd/nand/raw/nand_toshiba.c | 39 +++++++++++++++++++++++++++++
>  2 files changed, 42 insertions(+)
> 
> diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
> index 3b890d55703d..b9945791a9d7 100644
> --- a/drivers/mtd/nand/raw/nand_ids.c
> +++ b/drivers/mtd/nand/raw/nand_ids.c
> @@ -51,6 +51,9 @@ struct nand_flash_dev nand_flash_ids[] = {
>  		{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
>  		  SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640,
>  		  NAND_ECC_INFO(40, SZ_1K) },
> +	{"TH58NVG2S3HBAI4 4G 3.3V 8-bit",
> +		{ .id = {0x98, 0xdc, 0x91, 0x15, 0x76} },
> +		  SZ_2K, SZ_512, SZ_128K, 0, 5, 128, NAND_ECC_INFO(8, SZ_512) },
>  
>  	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
>  	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
> diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
> index 860ae0c13063..fc044b3424a7 100644
> --- a/drivers/mtd/nand/raw/nand_toshiba.c
> +++ b/drivers/mtd/nand/raw/nand_toshiba.c
> @@ -218,6 +218,36 @@ static int tc58nvg0s3e_choose_data_interface(struct nand_chip *chip,
>  	return nand_choose_best_sdr_timings(chip, iface, NULL);
>  }
>  
> +static int
> +th58nvg2s3hbai4_choose_data_interface(struct nand_chip *chip,
> +				      struct nand_data_interface *iface)
> +{
> +	struct nand_sdr_timings *sdr = &iface->timings.sdr;
> +	int ret;
> +
> +	/* Start with timings from the closest timing mode, mode 4. */
> +	ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE, 4);
> +	if (ret)
> +		return ret;
> +
> +	/* Patch timings that differ from mode 4. */
> +	sdr->tALS_min = 12000;
> +	sdr->tCHZ_max = 20000;
> +	sdr->tCLS_min = 12000;
> +	sdr->tCOH_min = 0;
> +	sdr->tDS_min = 12000;
> +	sdr->tRHOH_min = 25000;
> +	sdr->tRHW_min = 30000;
> +	sdr->tRHZ_max = 60000;
> +	sdr->tWHR_min = 60000;
> +
> +	/* Patch timings not part of onfi timing mode. */
> +	sdr->tPROG_max = 700000000;
> +	sdr->tBERS_max = 5000000000;
> +
> +	return nand_choose_best_sdr_timings(chip, iface, sdr);
> +}
> +
>  static int tc58teg5dclta00_init(struct nand_chip *chip)
>  {
>  	struct mtd_info *mtd = nand_to_mtd(chip);
> @@ -236,6 +266,13 @@ static int tc58nvg0s3e_init(struct nand_chip *chip)
>  	return 0;
>  }
>  
> +static int th58nvg2s3hbai4_init(struct nand_chip *chip)
> +{
> +	chip->ops.choose_data_interface = th58nvg2s3hbai4_choose_data_interface;
> +
> +	return 0;
> +}
> +
>  static int toshiba_nand_init(struct nand_chip *chip)
>  {
>  	if (nand_is_slc(chip))
> @@ -250,6 +287,8 @@ static int toshiba_nand_init(struct nand_chip *chip)
>  		tc58teg5dclta00_init(chip);
>  	if (!strcmp("TC58NVG0S3E", chip->parameters.model))
>  		tc58nvg0s3e_init(chip);
> +	if (!strncmp("TH58NVG2S3HBAI4", chip->parameters.model, 15))

								^sizeof("TH58NVG2S3HBAI4" - 1)

> +		th58nvg2s3hbai4_init(chip);
>  
>  	return 0;
>  }


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 27/28] mtd: rawnand: Get rid of the default ONFI timing mode
  2020-05-26 19:17 ` [PATCH v5 27/28] mtd: rawnand: Get rid of the default ONFI timing mode Miquel Raynal
@ 2020-05-26 22:13   ` Boris Brezillon
  0 siblings, 0 replies; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 22:13 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:24 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> The ->choose_data_interface() hook is here for manufacturer drivers to
> provide a better timing interface than the default one, this field is
> not needed anymore.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
>  drivers/mtd/nand/raw/nand_base.c | 19 +++++--------------
>  include/linux/mtd/rawnand.h      |  9 ---------
>  2 files changed, 5 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index f14d297c50f4..2547136a9cd7 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -1010,17 +1010,15 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
>   * @iface: the data interface (can eventually be updated)
>   * @spec_timings: specific timings, when not fitting the ONFI specification
>   *
> - * If specific timings are provided, use them. Otherwise, try to retrieve
> - * supported timing modes from ONFI information. Finally, if the NAND chip does
> - * not follow the ONFI specification, rely on the ->default_timing_mode
> - * specified in the nand_ids table.
> + * If specific timings are provided, use them. Otherwise, retrieve supported
> + * timing modes from ONFI information.
>   */
>  int nand_choose_best_sdr_timings(struct nand_chip *chip,
>  				 struct nand_data_interface *iface,
>  				 struct nand_sdr_timings *spec_timings)
>  {
>  	const struct nand_controller_ops *ops = chip->controller->ops;
> -	int best_mode = 0, onfi_modes, mode, ret;
> +	int best_mode = 0, mode, ret;
>  
>  	iface->type = NAND_SDR_IFACE;
>  
> @@ -1037,13 +1035,8 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
>  
>  		/* Fallback to slower modes */
>  		best_mode = iface->timings.mode;
> -	} else {
> -		if (chip->parameters.onfi) {
> -			onfi_modes = chip->parameters.onfi->async_timing_mode;
> -			best_mode = fls(onfi_modes) - 1;
> -		} else {
> -			best_mode = chip->onfi_timing_mode_default;
> -		}
> +	} else if (chip->parameters.onfi) {
> +		best_mode = fls(chip->parameters.onfi->async_timing_mode) - 1;
>  	}
>  
>  	for (mode = best_mode; mode >= 0; mode--) {
> @@ -4822,8 +4815,6 @@ static bool find_full_id_nand(struct nand_chip *chip,
>  		chip->options |= type->options;
>  		chip->base.eccreq.strength = NAND_ECC_STRENGTH(type);
>  		chip->base.eccreq.step_size = NAND_ECC_STEP(type);
> -		chip->onfi_timing_mode_default =
> -					type->onfi_timing_mode_default;
>  
>  		chip->parameters.model = kstrdup(type->name, GFP_KERNEL);
>  		if (!chip->parameters.model)
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index 5bd79e853140..00557e553827 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -1070,9 +1070,6 @@ struct nand_manufacturer {
>   * @options: Various chip options. They can partly be set to inform nand_scan
>   *           about special functionality. See the defines for further
>   *           explanation.
> - * @onfi_timing_mode_default: Default ONFI timing mode. This field is set to the
> - *			      actually used ONFI mode if the chip is ONFI
> - *			      compliant or deduced from the datasheet otherwise
>   * @data_interface: NAND interface timing information
>   * @bbt_erase_shift: Number of address bits in a bbt entry
>   * @bbt_options: Bad block table specific options. All options used here must
> @@ -1120,7 +1117,6 @@ struct nand_chip {
>  	unsigned int options;
>  
>  	/* Data interface */
> -	int onfi_timing_mode_default;
>  	struct nand_data_interface data_interface;
>  
>  	/* Bad block information */
> @@ -1271,10 +1267,6 @@ nand_get_sdr_timings(struct nand_chip *chip)
>   *               @ecc_step_ds in nand_chip{}, also from the datasheet.
>   *               For example, the "4bit ECC for each 512Byte" can be set with
>   *               NAND_ECC_INFO(4, 512).
> - * @onfi_timing_mode_default: the default ONFI timing mode entered after a NAND
> - *			      reset. Should be deduced from timings described
> - *			      in the datasheet.
> - *
>   */
>  struct nand_flash_dev {
>  	char *name;
> @@ -1295,7 +1287,6 @@ struct nand_flash_dev {
>  		uint16_t strength_ds;
>  		uint16_t step_ds;
>  	} ecc;
> -	int onfi_timing_mode_default;
>  };
>  
>  int nand_create_bbt(struct nand_chip *chip);


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 28/28] mtd: rawnand: Allocate the best data interface structure dynamically
  2020-05-26 19:17 ` [PATCH v5 28/28] mtd: rawnand: Allocate the best data interface structure dynamically Miquel Raynal
@ 2020-05-26 22:28   ` Boris Brezillon
  2020-05-27  7:57     ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Boris Brezillon @ 2020-05-26 22:28 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Tue, 26 May 2020 21:17:25 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Instead of manipulating the statically allocated structure and copy
> timings around, allocate one at identification time and save it in the
> nand_chip structure once it has been initialized.
> 
> This way, either there is a "best data interface" and the requested
> timings will be these, or there is none, forcing the core to use the
> default set, statically defined in the core, shared across all NAND
> chips.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/nand_base.c | 42 ++++++++++++++++++++++----------
>  include/linux/mtd/rawnand.h      | 13 +++++++---
>  2 files changed, 39 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 2547136a9cd7..247bf5faaf55 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -947,7 +947,7 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
>   */
>  static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
>  {
> -	u8 mode = chip->data_interface.timings.mode;
> +	u8 mode = chip->best_iface->timings.mode;
>  	u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { mode, };
>  	int ret;
>  
> @@ -966,7 +966,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
>  
>  	/* Change the mode on the controller side */
>  	ret = chip->controller->ops->setup_data_interface(chip, chipnr,
> -							&chip->data_interface);
> +							  chip->best_iface);
>  	if (ret)
>  		return ret;
>  
> @@ -1030,8 +1030,10 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
>  		ret = ops->setup_data_interface(chip,
>  						NAND_DATA_IFACE_CHECK_ONLY,
>  						iface);
> -		if (!ret)
> +		if (!ret) {
> +			chip->best_iface = iface;
>  			return ret;
> +		}
>  
>  		/* Fallback to slower modes */
>  		best_mode = iface->timings.mode;
> @@ -1052,6 +1054,8 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
>  			break;
>  	}
>  
> +	chip->best_iface = iface;
> +
>  	return 0;
>  }
>  
> @@ -1070,14 +1074,25 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
>   */
>  static int nand_choose_data_interface(struct nand_chip *chip)
>  {
> +	struct nand_data_interface *iface;
> +	int ret;
> +
>  	if (!nand_controller_has_setup_data_iface(chip))
>  		return 0;
>  
> +	iface = kzalloc(sizeof(*iface), GFP_KERNEL);
> +	if (!iface)
> +		return -ENOMEM;
> +
>  	if (chip->ops.choose_data_interface)
> -		return chip->ops.choose_data_interface(chip,
> -						       &chip->data_interface);
> +		ret = chip->ops.choose_data_interface(chip, iface);
> +	else
> +		ret = nand_choose_best_sdr_timings(chip, iface, NULL);
>  
> -	return nand_choose_best_sdr_timings(chip, &chip->data_interface, NULL);
> +	if (ret)
> +		kfree(iface);
> +
> +	return ret;
>  }
>  
>  /**
> @@ -2514,8 +2529,7 @@ int nand_reset(struct nand_chip *chip, int chipnr)
>  	 * nand_setup_data_interface() uses ->set/get_features() which would
>  	 * fail anyway as the parameter page is not available yet.
>  	 */
> -	if (!memcmp(&chip->data_interface, nand_reset_data_iface,
> -		    sizeof(*nand_reset_data_iface)))
> +	if (!chip->best_iface)
>  		return 0;
>  

If you assign ->best_iface for mode 0 (as done above) and keep the
!chip->best_iface test that means you apply timing mode 0 twice. Not
a big deal but I wanted to point it out.

>  	ret = nand_setup_data_interface(chip, chipnr);
> @@ -5252,9 +5266,6 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
>  
>  	mutex_init(&chip->lock);
>  
> -	/* Enforce the right timings for reset/detection */
> -	onfi_fill_data_interface(chip, &chip->data_interface, NAND_SDR_IFACE, 0);
> -
>  	ret = nand_dt_init(chip);
>  	if (ret)
>  		return ret;
> @@ -6059,7 +6070,7 @@ static int nand_scan_tail(struct nand_chip *chip)
>  	for (i = 0; i < nanddev_ntargets(&chip->base); i++) {
>  		ret = nand_setup_data_interface(chip, i);
>  		if (ret)
> -			goto err_nanddev_cleanup;
> +			goto err_free_data_iface;
>  	}
>  
>  	/* Check, if we should skip the bad block table scan */
> @@ -6069,10 +6080,12 @@ static int nand_scan_tail(struct nand_chip *chip)
>  	/* Build bad block table */
>  	ret = nand_create_bbt(chip);
>  	if (ret)
> -		goto err_nanddev_cleanup;
> +		goto err_free_data_iface;
>  
>  	return 0;
>  
> +err_free_data_iface:
> +	kfree(chip->best_iface);
>  
>  err_nanddev_cleanup:
>  	nanddev_cleanup(&chip->base);
> @@ -6166,6 +6179,9 @@ void nand_cleanup(struct nand_chip *chip)
>  			& NAND_BBT_DYNAMICSTRUCT)
>  		kfree(chip->badblock_pattern);
>  
> +	/* Free the data interface */
> +	kfree(chip->best_iface);
> +
>  	/* Free manufacturer priv data. */
>  	nand_manufacturer_cleanup(chip);
>  
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index 00557e553827..0f215faa3072 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -1070,7 +1070,9 @@ struct nand_manufacturer {
>   * @options: Various chip options. They can partly be set to inform nand_scan
>   *           about special functionality. See the defines for further
>   *           explanation.
> - * @data_interface: NAND interface timing information
> + * @best_iface: The best NAND data interface which fits both the NAND chip and

						^ configuration

> + *              NAND controller constraints. If unset, the default reset data
> + *              interface must be used.
>   * @bbt_erase_shift: Number of address bits in a bbt entry
>   * @bbt_options: Bad block table specific options. All options used here must
>   *               come from bbm.h. By default, these options will be copied to
> @@ -1117,7 +1119,7 @@ struct nand_chip {
>  	unsigned int options;
>  
>  	/* Data interface */
> -	struct nand_data_interface data_interface;
> +	struct nand_data_interface *best_iface;

Not sure why you rename this field, but if we go for a name update, I'd
vote for best_iface_cfg (or something that clarifies the fact that this
is the data interface configuration).

>  
>  	/* Bad block information */
>  	unsigned int bbt_erase_shift;
> @@ -1212,7 +1214,12 @@ extern const struct nand_data_interface *nand_reset_data_iface;
>  static inline const struct nand_sdr_timings *
>  nand_get_sdr_timings(struct nand_chip *chip)
>  {
> -	return nand_extract_sdr_timings(&chip->data_interface);
> +	const struct nand_data_interface *iface = chip->best_iface;
> +
> +	if (!iface)
> +		iface = nand_reset_data_iface;
> +
> +	return nand_extract_sdr_timings(iface);
>  }
>  
>  /*


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 16/28] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max
  2020-05-26 21:25   ` Boris Brezillon
@ 2020-05-27  7:17     ` Miquel Raynal
  2020-05-27  7:22       ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-27  7:17 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Tue, 26 May
2020 23:25:30 +0200:

> On Tue, 26 May 2020 21:17:13 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > The ONFI parameter page of a chip might define more fine grained
> > tPROG_max and tBERS_max. When we do not have this information, we
> > default to the highest possible values (they are maxima anyway).
> > 
> > There is no point setting these fields at runtime, so explicitly move
> > these defaults to the main ONFI SDR timings structure.  
> 
> Okay, now I see why you're doing that: you want to return the mode 0
> entry directly, and it makes sense, but it should be explained in the
> commit message.

Okay I will mention it in the other commit message, and perhaps move
the comment about them as well so that it does not get lost.

I can also assign these timings manually for mode 0 in the helper you
requested.

What do you prefer?

> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/mtd/nand/raw/nand_timings.c | 24 ++++++++++++------------
> >  1 file changed, 12 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
> > index c2286a75d134..52ee83e75646 100644
> > --- a/drivers/mtd/nand/raw/nand_timings.c
> > +++ b/drivers/mtd/nand/raw/nand_timings.c
> > @@ -20,6 +20,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> >  		.timings.sdr = {
> >  			.tCCS_min = 500000,
> >  			.tR_max = 200000000,
> > +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> >  			.tADL_min = 400000,
> >  			.tALH_min = 20000,
> >  			.tALS_min = 50000,
> > @@ -63,6 +65,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> >  		.timings.sdr = {
> >  			.tCCS_min = 500000,
> >  			.tR_max = 200000000,
> > +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> >  			.tADL_min = 400000,
> >  			.tALH_min = 10000,
> >  			.tALS_min = 25000,
> > @@ -106,6 +110,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> >  		.timings.sdr = {
> >  			.tCCS_min = 500000,
> >  			.tR_max = 200000000,
> > +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> >  			.tADL_min = 400000,
> >  			.tALH_min = 10000,
> >  			.tALS_min = 15000,
> > @@ -149,6 +155,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> >  		.timings.sdr = {
> >  			.tCCS_min = 500000,
> >  			.tR_max = 200000000,
> > +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> >  			.tADL_min = 400000,
> >  			.tALH_min = 5000,
> >  			.tALS_min = 10000,
> > @@ -192,6 +200,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> >  		.timings.sdr = {
> >  			.tCCS_min = 500000,
> >  			.tR_max = 200000000,
> > +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> >  			.tADL_min = 400000,
> >  			.tALH_min = 5000,
> >  			.tALS_min = 10000,
> > @@ -235,6 +245,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> >  		.timings.sdr = {
> >  			.tCCS_min = 500000,
> >  			.tR_max = 200000000,
> > +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> >  			.tADL_min = 400000,
> >  			.tALH_min = 5000,
> >  			.tALS_min = 10000,
> > @@ -359,18 +371,6 @@ int onfi_fill_data_interface(struct nand_chip *chip,
> >  
> >  		/* nanoseconds -> picoseconds */
> >  		timings->tCCS_min = 1000UL * onfi->tCCS;
> > -	} else {
> > -		struct nand_sdr_timings *timings = &iface->timings.sdr;
> > -		/*
> > -		 * For non-ONFI chips we use the highest possible value for
> > -		 * tPROG and tBERS. tR and tCCS will take the default values
> > -		 * precised in the ONFI specification for timing mode 0,
> > -		 * respectively 200us and 500ns.
> > -		 */
> > -
> > -		/* microseconds -> picoseconds */
> > -		timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
> > -		timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
> >  	}
> >  
> >  	return 0;  
> 

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 17/28] mtd: rawnand: Define a unique reset data interface
  2020-05-26 21:23   ` Boris Brezillon
@ 2020-05-27  7:20     ` Miquel Raynal
  2020-05-27  8:10       ` Boris Brezillon
  0 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-27  7:20 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Tue, 26 May
2020 23:23:38 +0200:

> On Tue, 26 May 2020 21:17:14 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > All NAND chips will always use the same data interface for reset and
> > at startup: SDR mode 0. Instead of copying around the data interface
> > timings, let's just have a default reset data interface for that.
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/mtd/nand/raw/nand_base.c    | 9 +++------
> >  drivers/mtd/nand/raw/nand_timings.c | 3 +++
> >  include/linux/mtd/rawnand.h         | 3 +++
> >  3 files changed, 9 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > index 89f10a8c1d62..1005035c233a 100644
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> > @@ -927,9 +927,8 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
> >  	 * timings to timing mode 0.
> >  	 */
> >  
> > -	onfi_fill_data_interface(chip, &chip->data_interface, NAND_SDR_IFACE, 0);
> >  	ret = chip->controller->ops->setup_data_interface(chip, chipnr,
> > -							&chip->data_interface);
> > +							  nand_reset_data_iface);
> >  	if (ret)
> >  		pr_err("Failed to configure data interface to SDR timing mode 0\n");
> >  
> > @@ -2484,7 +2483,6 @@ EXPORT_SYMBOL_GPL(nand_subop_get_data_len);
> >   */
> >  int nand_reset(struct nand_chip *chip, int chipnr)
> >  {
> > -	struct nand_data_interface saved_data_intf = chip->data_interface;
> >  	int ret;
> >  
> >  	ret = nand_reset_data_interface(chip, chipnr);
> > @@ -2509,11 +2507,10 @@ int nand_reset(struct nand_chip *chip, int chipnr)
> >  	 * nand_setup_data_interface() uses ->set/get_features() which would
> >  	 * fail anyway as the parameter page is not available yet.
> >  	 */
> > -	if (!memcmp(&chip->data_interface, &saved_data_intf,
> > -		    sizeof(saved_data_intf)))
> > +	if (!memcmp(&chip->data_interface, nand_reset_data_iface,
> > +		    sizeof(*nand_reset_data_iface)))
> >  		return 0;
> >  
> > -	chip->data_interface = saved_data_intf;
> >  	ret = nand_setup_data_interface(chip, chipnr);
> >  	if (ret)
> >  		return ret;
> > diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
> > index 52ee83e75646..343284c43e81 100644
> > --- a/drivers/mtd/nand/raw/nand_timings.c
> > +++ b/drivers/mtd/nand/raw/nand_timings.c
> > @@ -285,6 +285,9 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> >  	},
> >  };
> >  
> > +/* All NAND chips share the same reset data interface: SDR mode 0 */
> > +const struct nand_data_interface *nand_reset_data_iface = &onfi_sdr_timings[0];  
> 
> Can we make that one a function?
> 
> const struct nand_data_interface *nand_get_reset_data_interface(void)
> {
> 	return &onfi_sdr_timings[0];
> }

Sure!

> 
> > +
> >  /**
> >   * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a
> >   *                              set of timings
> > diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> > index 622da6527a36..6c334cca3977 100644
> > --- a/include/linux/mtd/rawnand.h
> > +++ b/include/linux/mtd/rawnand.h
> > @@ -1203,6 +1203,9 @@ static inline struct device_node *nand_get_flash_node(struct nand_chip *chip)
> >  	return mtd_get_of_node(nand_to_mtd(chip));
> >  }
> >  
> > +/* Default/reset data interface */
> > +extern const struct nand_data_interface *nand_reset_data_iface;
> > +
> >  /*
> >   * A helper for defining older NAND chips where the second ID byte fully
> >   * defined the chip, including the geometry (chip size, eraseblock size, page  
> 

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 16/28] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max
  2020-05-27  7:17     ` Miquel Raynal
@ 2020-05-27  7:22       ` Miquel Raynal
  2020-05-27  7:28         ` Boris Brezillon
  0 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-27  7:22 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

Hi Miquel,

Miquel Raynal <miquel.raynal@bootlin.com> wrote on Wed, 27 May 2020
09:17:58 +0200:

> Hi Boris,
> 
> Boris Brezillon <boris.brezillon@collabora.com> wrote on Tue, 26 May
> 2020 23:25:30 +0200:
> 
> > On Tue, 26 May 2020 21:17:13 +0200
> > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >   
> > > The ONFI parameter page of a chip might define more fine grained
> > > tPROG_max and tBERS_max. When we do not have this information, we
> > > default to the highest possible values (they are maxima anyway).
> > > 
> > > There is no point setting these fields at runtime, so explicitly move
> > > these defaults to the main ONFI SDR timings structure.    
> > 
> > Okay, now I see why you're doing that: you want to return the mode 0
> > entry directly, and it makes sense, but it should be explained in the
> > commit message.  
> 
> Okay I will mention it in the other commit message, and perhaps move
> the comment about them as well so that it does not get lost.
> 
> I can also assign these timings manually for mode 0 in the helper you
> requested.

Actually I don't like this idea which would mean changing the content
of the timings structure itself...

I would prefer to move these 4 values to the structure (as I already
do) plus moving the comment explaining the derivations.

> 
> What do you prefer?
> 
> > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > ---
> > >  drivers/mtd/nand/raw/nand_timings.c | 24 ++++++++++++------------
> > >  1 file changed, 12 insertions(+), 12 deletions(-)
> > > 
> > > diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
> > > index c2286a75d134..52ee83e75646 100644
> > > --- a/drivers/mtd/nand/raw/nand_timings.c
> > > +++ b/drivers/mtd/nand/raw/nand_timings.c
> > > @@ -20,6 +20,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> > >  		.timings.sdr = {
> > >  			.tCCS_min = 500000,
> > >  			.tR_max = 200000000,
> > > +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > > +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > >  			.tADL_min = 400000,
> > >  			.tALH_min = 20000,
> > >  			.tALS_min = 50000,
> > > @@ -63,6 +65,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> > >  		.timings.sdr = {
> > >  			.tCCS_min = 500000,
> > >  			.tR_max = 200000000,
> > > +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > > +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > >  			.tADL_min = 400000,
> > >  			.tALH_min = 10000,
> > >  			.tALS_min = 25000,
> > > @@ -106,6 +110,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> > >  		.timings.sdr = {
> > >  			.tCCS_min = 500000,
> > >  			.tR_max = 200000000,
> > > +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > > +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > >  			.tADL_min = 400000,
> > >  			.tALH_min = 10000,
> > >  			.tALS_min = 15000,
> > > @@ -149,6 +155,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> > >  		.timings.sdr = {
> > >  			.tCCS_min = 500000,
> > >  			.tR_max = 200000000,
> > > +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > > +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > >  			.tADL_min = 400000,
> > >  			.tALH_min = 5000,
> > >  			.tALS_min = 10000,
> > > @@ -192,6 +200,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> > >  		.timings.sdr = {
> > >  			.tCCS_min = 500000,
> > >  			.tR_max = 200000000,
> > > +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > > +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > >  			.tADL_min = 400000,
> > >  			.tALH_min = 5000,
> > >  			.tALS_min = 10000,
> > > @@ -235,6 +245,8 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> > >  		.timings.sdr = {
> > >  			.tCCS_min = 500000,
> > >  			.tR_max = 200000000,
> > > +			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > > +			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
> > >  			.tADL_min = 400000,
> > >  			.tALH_min = 5000,
> > >  			.tALS_min = 10000,
> > > @@ -359,18 +371,6 @@ int onfi_fill_data_interface(struct nand_chip *chip,
> > >  
> > >  		/* nanoseconds -> picoseconds */
> > >  		timings->tCCS_min = 1000UL * onfi->tCCS;
> > > -	} else {
> > > -		struct nand_sdr_timings *timings = &iface->timings.sdr;
> > > -		/*
> > > -		 * For non-ONFI chips we use the highest possible value for
> > > -		 * tPROG and tBERS. tR and tCCS will take the default values
> > > -		 * precised in the ONFI specification for timing mode 0,
> > > -		 * respectively 200us and 500ns.
> > > -		 */
> > > -
> > > -		/* microseconds -> picoseconds */
> > > -		timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
> > > -		timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
> > >  	}
> > >  
> > >  	return 0;    
> >   


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 16/28] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max
  2020-05-27  7:22       ` Miquel Raynal
@ 2020-05-27  7:28         ` Boris Brezillon
  0 siblings, 0 replies; 62+ messages in thread
From: Boris Brezillon @ 2020-05-27  7:28 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Wed, 27 May 2020 09:22:49 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Hi Miquel,
> 
> Miquel Raynal <miquel.raynal@bootlin.com> wrote on Wed, 27 May 2020
> 09:17:58 +0200:
> 
> > Hi Boris,
> > 
> > Boris Brezillon <boris.brezillon@collabora.com> wrote on Tue, 26 May
> > 2020 23:25:30 +0200:
> >   
> > > On Tue, 26 May 2020 21:17:13 +0200
> > > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> > >     
> > > > The ONFI parameter page of a chip might define more fine grained
> > > > tPROG_max and tBERS_max. When we do not have this information, we
> > > > default to the highest possible values (they are maxima anyway).
> > > > 
> > > > There is no point setting these fields at runtime, so explicitly move
> > > > these defaults to the main ONFI SDR timings structure.      
> > > 
> > > Okay, now I see why you're doing that: you want to return the mode 0
> > > entry directly, and it makes sense, but it should be explained in the
> > > commit message.    
> > 
> > Okay I will mention it in the other commit message, and perhaps move
> > the comment about them as well so that it does not get lost.
> > 
> > I can also assign these timings manually for mode 0 in the helper you
> > requested.  
> 
> Actually I don't like this idea which would mean changing the content
> of the timings structure itself...

Me neither, they should stay const.

> 
> I would prefer to move these 4 values to the structure (as I already
> do) plus moving the comment explaining the derivations.
> 

Agreed.

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 20/28] mtd: rawnand: Hide the chip->data_interface indirection
  2020-05-26 21:36   ` Boris Brezillon
@ 2020-05-27  7:36     ` Miquel Raynal
  2020-05-27  8:14       ` Boris Brezillon
  0 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-27  7:36 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Tue, 26 May
2020 23:36:20 +0200:

> On Tue, 26 May 2020 21:17:17 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > As a preparation for allocating the data interface structure
> > dynamically (and rename it), let's avoid calling it directly.
> > 
> > Instead, we operate a rename on an existing helper to reuse that name
> > for another helper:
> > * s/nand_get_sdr_timings/nand_extract_sdr_timings/  
> >   -> this helper just extracts timings from a given data interface  
> 
> Hm, I'm not entirely happy with that name. In my mind extract means
> that you had to do some transformation to get the data, which is not
> the case here. How about nand_data_interface_get_sdr_timings()? 
> 
> > * nand_get_sdr_timings()  
> >   -> this helper retrieves the in use timings from a nand_chip structure  
> 
> Do we really need that one? Can we do that in 2 steps instead?

Yes I can do that in two steps, I didn't think it was needed but no pb.

> 
> conf = nand_get_data_interface_config(chip);
> sdr = nand_data_interface_get_sdr_timings(conf);

I find the names too long. Do you think I can stick to
nand_get_sdr_timings(conf) and nand_get_data_interface(chip)? These
helpers are very often used at the start of a function and would
definitely break systematically the 80 chars limit otherwise...

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 14/28] mtd: rawnand: timings: Add a helper to find the closest ONFI mode
  2020-05-26 21:42   ` Boris Brezillon
@ 2020-05-27  7:42     ` Miquel Raynal
  0 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-27  7:42 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Tue, 26 May
2020 23:42:05 +0200:

> On Tue, 26 May 2020 21:17:11 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > Vendors are allowed to provide their own set of timings. In this case,
> > we provide a way to derive the "closest" timing mode so that, if the
> > NAND controller does not support tweaking these parameters, it will be
> > able to configure itself anyway.
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/mtd/nand/raw/internals.h    |  2 ++
> >  drivers/mtd/nand/raw/nand_timings.c | 49 +++++++++++++++++++++++++++++
> >  2 files changed, 51 insertions(+)
> > 
> > diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
> > index dc84e3b55d48..c7357ae86eeb 100644
> > --- a/drivers/mtd/nand/raw/internals.h
> > +++ b/drivers/mtd/nand/raw/internals.h
> > @@ -88,6 +88,8 @@ int onfi_fill_data_interface(struct nand_chip *chip,
> >  			     struct nand_data_interface *iface,
> >  			     enum nand_data_interface_type type,
> >  			     int timing_mode);
> > +unsigned int
> > +onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings);
> >  int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
> >  int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
> >  int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf,
> > diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
> > index ce6bb87db2e8..3c44c4b90536 100644
> > --- a/drivers/mtd/nand/raw/nand_timings.c
> > +++ b/drivers/mtd/nand/raw/nand_timings.c
> > @@ -273,6 +273,55 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> >  	},
> >  };
> >  
> > +/**
> > + * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a
> > + *                              set of timings
> > + * @spec_timings: the timings to challenge
> > + */
> > +unsigned int
> > +onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings)
> > +{
> > +	const struct nand_sdr_timings *onfi_timings;
> > +	int mode;
> > +
> > +	for (mode = ARRAY_SIZE(onfi_sdr_timings) - 1; mode > 0; mode--) {
> > +		onfi_timings = &onfi_sdr_timings[mode].timings.sdr;
> > +
> > +		if (spec_timings->tCCS_min > onfi_timings->tCCS_min ||
> > +		    spec_timings->tADL_min > onfi_timings->tADL_min ||
> > +		    spec_timings->tALH_min > onfi_timings->tALH_min ||
> > +		    spec_timings->tALS_min > onfi_timings->tALS_min ||
> > +		    spec_timings->tAR_min > onfi_timings->tAR_min ||
> > +		    spec_timings->tCEH_min > onfi_timings->tCEH_min ||
> > +		    spec_timings->tCH_min > onfi_timings->tCH_min ||
> > +		    spec_timings->tCLH_min > onfi_timings->tCLH_min ||
> > +		    spec_timings->tCLR_min > onfi_timings->tCLR_min ||
> > +		    spec_timings->tCLS_min > onfi_timings->tCLS_min ||
> > +		    spec_timings->tCOH_min > onfi_timings->tCOH_min ||
> > +		    spec_timings->tCS_min > onfi_timings->tCS_min ||
> > +		    spec_timings->tDH_min > onfi_timings->tDH_min ||
> > +		    spec_timings->tDS_min > onfi_timings->tDS_min ||
> > +		    spec_timings->tIR_min > onfi_timings->tIR_min ||
> > +		    spec_timings->tRC_min > onfi_timings->tRC_min ||
> > +		    spec_timings->tREH_min > onfi_timings->tREH_min ||
> > +		    spec_timings->tRHOH_min > onfi_timings->tRHOH_min ||
> > +		    spec_timings->tRHW_min > onfi_timings->tRHW_min ||
> > +		    spec_timings->tRLOH_min > onfi_timings->tRLOH_min ||
> > +		    spec_timings->tRP_min > onfi_timings->tRP_min ||
> > +		    spec_timings->tRR_min > onfi_timings->tRR_min ||
> > +		    spec_timings->tWC_min > onfi_timings->tWC_min ||
> > +		    spec_timings->tWH_min > onfi_timings->tWH_min ||
> > +		    spec_timings->tWHR_min > onfi_timings->tWHR_min ||
> > +		    spec_timings->tWP_min > onfi_timings->tWP_min ||
> > +		    spec_timings->tWW_min > onfi_timings->tWW_min)  
> 
> Just nitpicking but you could just do the opposite test ('<=' instead of
> '>' and '&&' instead of '||') and return mode directly, so you don't  
> need this continue.

I did it because I wanted the continue; statement to be called as soon
as one test was "true" (ie. wrong in this case) but actually it would
work the same with a <= and a &&, so I'll switch.

> I didn't check if all the _min timings were tested, but assuming that's
> the case, you can add

I copy/pasted the entire structure definition so unless I messed with
it, it should be fine.

> 
> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
> 
> > +			continue;
> > +
> > +		return mode;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  /**
> >   * onfi_fill_data_interface - Initialize a data interface from a given ONFI mode
> >   * @chip: The NAND chip  
> 


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 21/28] mtd: rawnand: Introduce nand_choose_best_sdr_timings()
  2020-05-26 21:50   ` Boris Brezillon
@ 2020-05-27  7:45     ` Miquel Raynal
  0 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-27  7:45 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Tue, 26 May
2020 23:50:03 +0200:

> On Tue, 26 May 2020 21:17:18 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > Extract the logic out of nand_choose_data_interface() to create a
> > public helper that can be reused by manufacturer drivers. Add the
> > possibility to provide a specific set of timings.
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/mtd/nand/raw/internals.h |   3 +
> >  drivers/mtd/nand/raw/nand_base.c | 104 +++++++++++++++++++------------
> >  2 files changed, 66 insertions(+), 41 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
> > index c7357ae86eeb..5c49c4d1e231 100644
> > --- a/drivers/mtd/nand/raw/internals.h
> > +++ b/drivers/mtd/nand/raw/internals.h
> > @@ -90,6 +90,9 @@ int onfi_fill_data_interface(struct nand_chip *chip,
> >  			     int timing_mode);
> >  unsigned int
> >  onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings);
> > +int nand_choose_best_sdr_timings(struct nand_chip *chip,
> > +				 struct nand_data_interface *iface,
> > +				 struct nand_sdr_timings *spec_timings);
> >  int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
> >  int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
> >  int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf,
> > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > index 6a7edd2e1357..b2e833a8ab9d 100644
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> > @@ -1003,61 +1003,83 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
> >  	return ret;
> >  }
> >  
> > +/**
> > + * nand_choose_best_sdr_timings - Pick up the best SDR timings that both the
> > + *                                NAND controller and the NAND chip support
> > + * @chip: the NAND chip
> > + * @iface: the data interface (can eventually be updated)
> > + * @spec_timings: specific timings, when not fitting the ONFI specification
> > + *
> > + * If specific timings are provided, use them. Otherwise, try to retrieve
> > + * supported timing modes from ONFI information. Finally, if the NAND chip does
> > + * not follow the ONFI specification, rely on the ->default_timing_mode
> > + * specified in the nand_ids table.
> > + */
> > +int nand_choose_best_sdr_timings(struct nand_chip *chip,
> > +				 struct nand_data_interface *iface,
> > +				 struct nand_sdr_timings *spec_timings)
> > +{
> > +	const struct nand_controller_ops *ops = chip->controller->ops;
> > +	int best_mode = 0, onfi_modes, mode, ret;
> > +
> > +	iface->type = NAND_SDR_IFACE;
> > +
> > +	if (spec_timings) {
> > +		iface->timings.sdr = *spec_timings;
> > +		iface->timings.mode = onfi_find_closest_sdr_mode(spec_timings);
> > +
> > +		/* Verify the controller supports the requested interface */
> > +		ret = ops->setup_data_interface(chip,
> > +						NAND_DATA_IFACE_CHECK_ONLY,
> > +						iface);
> > +		if (!ret)
> > +			return ret;
> > +
> > +		/* Fallback to slower modes */
> > +		best_mode = iface->timings.mode;
> > +	} else {
> > +		if (chip->parameters.onfi) {  
> 
> onfi_modes var should be declared here.

Ok

> 
> > +			onfi_modes = chip->parameters.onfi->async_timing_mode;
> > +			best_mode = fls(onfi_modes) - 1;
> > +		} else {
> > +			best_mode = chip->onfi_timing_mode_default;
> > +		}
> > +	}
> > +
> > +
> > +	for (mode = best_mode; mode >= 0; mode--) {
> > +		ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE,
> > +					       mode);
> > +		if (ret)
> > +			continue;  
> 
> In practice onfi_fill_data_interface() will only return an error if you
> pass a type that's not SDR (not the case here, or a mode that's outside
> the SDR mode bounds). Maybe we should just clamp the value/warn when
> that happens and make onfi_fill_data_interface() a void function.

Agreed, I'll call WARN_ON() in it and return void. This function should
"never" fail.

> 
> > +
> > +		ret = ops->setup_data_interface(chip,
> > +						NAND_DATA_IFACE_CHECK_ONLY,
> > +						iface);
> > +		if (!ret)
> > +			break;  
> 
> 			return 0;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  /**
> >   * nand_choose_data_interface - find the best data interface and timings
> >   * @chip: The NAND chip
> >   *
> >   * Find the best data interface and NAND timings supported by the chip
> >   * and the driver.
> > - * First tries to retrieve supported timing modes from ONFI information,
> > - * and if the NAND chip does not support ONFI, relies on the
> > - * ->onfi_timing_mode_default specified in the nand_ids table. After this
> > - * function nand_chip->data_interface is initialized with the best timing mode
> > - * available.
> > + * After this function nand_chip->data_interface is initialized with the best
> > + * timing mode available.
> >   *
> >   * Returns 0 for success or negative error code otherwise.
> >   */
> >  static int nand_choose_data_interface(struct nand_chip *chip)
> >  {
> > -	int modes, mode, ret;
> > -
> >  	if (!nand_controller_has_setup_data_iface(chip))
> >  		return 0;
> >  
> > -	/*
> > -	 * First try to identify the best timings from ONFI parameters and
> > -	 * if the NAND does not support ONFI, fallback to the default ONFI
> > -	 * timing mode.
> > -	 */
> > -	if (chip->parameters.onfi) {
> > -		modes = chip->parameters.onfi->async_timing_mode;
> > -	} else {
> > -		if (!chip->onfi_timing_mode_default)
> > -			return 0;
> > -
> > -		modes = GENMASK(chip->onfi_timing_mode_default, 0);
> > -	}
> > -
> > -	for (mode = fls(modes) - 1; mode >= 0; mode--) {
> > -		ret = onfi_fill_data_interface(chip, &chip->data_interface,
> > -					       NAND_SDR_IFACE, mode);
> > -		if (ret)
> > -			continue;
> > -
> > -		/*
> > -		 * Pass NAND_DATA_IFACE_CHECK_ONLY to only check if the
> > -		 * controller supports the requested timings.
> > -		 */
> > -		ret = chip->controller->ops->setup_data_interface(chip,
> > -						 NAND_DATA_IFACE_CHECK_ONLY,
> > -						 &chip->data_interface);
> > -		if (!ret) {
> > -			chip->onfi_timing_mode_default = mode;
> > -			break;
> > -		}
> > -	}
> > -
> > -	return 0;
> > +	return nand_choose_best_sdr_timings(chip, &chip->data_interface, NULL);
> >  }
> >  
> >  /**  
> 

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 22/28] mtd: rawnand: Add the ->choose_data_interface() hook
  2020-05-26 21:52   ` Boris Brezillon
@ 2020-05-27  7:46     ` Miquel Raynal
  0 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-27  7:46 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus


Boris Brezillon <boris.brezillon@collabora.com> wrote on Tue, 26 May
2020 23:52:25 +0200:

> On Tue, 26 May 2020 21:17:19 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > This hook can be overloaded by NAND manufacturer drivers to propose
> > alternative timings when not following the main standards. In this
> > case, the manufacturer drivers is responsible for choosing the best
> > data interface and configuration that fits both the controller and  
> 
> 		  ^ s/and//
> 
> > chip capabilities.
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/mtd/nand/raw/nand_base.c | 9 +++++++--
> >  include/linux/mtd/rawnand.h      | 3 +++
> >  2 files changed, 10 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > index b2e833a8ab9d..f14d297c50f4 100644
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> > @@ -1046,7 +1046,6 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
> >  		}
> >  	}
> >  
> > -  
> 
> Should this line removal be part of another patch?

Absoluely.

> 
> >  	for (mode = best_mode; mode >= 0; mode--) {
> >  		ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE,
> >  					       mode);
> > @@ -1068,7 +1067,9 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
> >   * @chip: The NAND chip
> >   *
> >   * Find the best data interface and NAND timings supported by the chip
> > - * and the driver.
> > + * and the driver. Eventually let the NAND manufacturer driver propose his own
> > + * set of timings.
> > + *
> >   * After this function nand_chip->data_interface is initialized with the best
> >   * timing mode available.
> >   *
> > @@ -1079,6 +1080,10 @@ static int nand_choose_data_interface(struct nand_chip *chip)
> >  	if (!nand_controller_has_setup_data_iface(chip))
> >  		return 0;
> >  
> > +	if (chip->ops.choose_data_interface)
> > +		return chip->ops.choose_data_interface(chip,
> > +						       &chip->data_interface);
> > +
> >  	return nand_choose_best_sdr_timings(chip, &chip->data_interface, NULL);
> >  }
> >  
> > diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> > index 2995d29587c3..5bd79e853140 100644
> > --- a/include/linux/mtd/rawnand.h
> > +++ b/include/linux/mtd/rawnand.h
> > @@ -1034,6 +1034,7 @@ struct nand_legacy {
> >   * @lock_area: Lock operation
> >   * @unlock_area: Unlock operation
> >   * @setup_read_retry: Set the read-retry mode (mostly needed for MLC NANDs)
> > + * @choose_data_interface: Choose the best data interface
> >   */
> >  struct nand_chip_ops {
> >  	int (*suspend)(struct nand_chip *chip);
> > @@ -1041,6 +1042,8 @@ struct nand_chip_ops {
> >  	int (*lock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
> >  	int (*unlock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
> >  	int (*setup_read_retry)(struct nand_chip *chip, int retry_mode);
> > +	int (*choose_data_interface)(struct nand_chip *chip,
> > +				     struct nand_data_interface *iface);
> >  };
> >  
> >  /**  
> 

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 24/28] mtd: rawnand: toshiba: Implement ->choose_data_interface() for TC58NVG0S3E
  2020-05-26 22:02   ` Boris Brezillon
@ 2020-05-27  7:47     ` Miquel Raynal
  0 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-27  7:47 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus


Boris Brezillon <boris.brezillon@collabora.com> wrote on Wed, 27 May
2020 00:02:03 +0200:

> On Tue, 26 May 2020 21:17:21 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > This chip supports ONFI SDR timing mode 2, implement the new hook to
> > advertize it.
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/mtd/nand/raw/nand_ids.c     |  3 +--
> >  drivers/mtd/nand/raw/nand_toshiba.c | 21 +++++++++++++++++++++
> >  2 files changed, 22 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
> > index e0dbc2e316c7..c729a8bc895d 100644
> > --- a/drivers/mtd/nand/raw/nand_ids.c
> > +++ b/drivers/mtd/nand/raw/nand_ids.c
> > @@ -28,8 +28,7 @@ struct nand_flash_dev nand_flash_ids[] = {
> >  	 */
> >  	{"TC58NVG0S3E 1G 3.3V 8-bit",
> >  		{ .id = {0x98, 0xd1, 0x90, 0x15, 0x76, 0x14, 0x01, 0x00} },
> > -		  SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512),
> > -		  2 },
> > +		  SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512), },
> >  	{"TC58NVG2S0F 4G 3.3V 8-bit",
> >  		{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} },
> >  		  SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) },
> > diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
> > index fe2bc20972a9..860ae0c13063 100644
> > --- a/drivers/mtd/nand/raw/nand_toshiba.c
> > +++ b/drivers/mtd/nand/raw/nand_toshiba.c
> > @@ -206,6 +206,18 @@ tc58teg5dclta00_choose_data_interface(struct nand_chip *chip,
> >  	return nand_choose_best_sdr_timings(chip, iface, NULL);
> >  }
> >  
> > +static int tc58nvg0s3e_choose_data_interface(struct nand_chip *chip,
> > +					     struct nand_data_interface *iface)
> > +{
> > +	int ret;
> > +
> > +	ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE, 2);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return nand_choose_best_sdr_timings(chip, iface, NULL);
> > +}
> > +
> >  static int tc58teg5dclta00_init(struct nand_chip *chip)
> >  {
> >  	struct mtd_info *mtd = nand_to_mtd(chip);
> > @@ -217,6 +229,13 @@ static int tc58teg5dclta00_init(struct nand_chip *chip)
> >  	return 0;
> >  }
> >  
> > +static int tc58nvg0s3e_init(struct nand_chip *chip)
> > +{
> > +	chip->ops.choose_data_interface = &tc58nvg0s3e_choose_data_interface;
> > +
> > +	return 0;
> > +}
> > +
> >  static int toshiba_nand_init(struct nand_chip *chip)
> >  {
> >  	if (nand_is_slc(chip))
> > @@ -229,6 +248,8 @@ static int toshiba_nand_init(struct nand_chip *chip)
> >  
> >  	if (!strcmp("TC58TEG5DCLTA00", chip->parameters.model))
> >  		tc58teg5dclta00_init(chip);
> > +	if (!strcmp("TC58NVG0S3E", chip->parameters.model))  
> 
> The model won't match "TC58NVG0S3E", unless you use strncmp().

I definitely will.

> 
> > +		tc58nvg0s3e_init(chip);
> >  
> >  	return 0;
> >  }  
> 


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 25/28] mtd: rawnand: hynix: Implement ->choose_data_interface() for H27UCG8T2ATR-BC
  2020-05-26 22:06   ` Boris Brezillon
@ 2020-05-27  7:50     ` Miquel Raynal
  0 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-27  7:50 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus


Boris Brezillon <boris.brezillon@collabora.com> wrote on Wed, 27 May
2020 00:06:06 +0200:

> On Tue, 26 May 2020 21:17:22 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > This chip supports ONFI SDR timing mode 4, implement the new hook to
> > advertize it.
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/mtd/nand/raw/nand_hynix.c | 16 ++++++++++++++++
> >  drivers/mtd/nand/raw/nand_ids.c   |  2 +-
> >  2 files changed, 17 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
> > index 7d1be53f27f3..d61a55121962 100644
> > --- a/drivers/mtd/nand/raw/nand_hynix.c
> > +++ b/drivers/mtd/nand/raw/nand_hynix.c
> > @@ -673,6 +673,19 @@ static void hynix_nand_cleanup(struct nand_chip *chip)
> >  	nand_set_manufacturer_data(chip, NULL);
> >  }
> >  
> > +static int
> > +h27ucg8t2atrbc_choose_data_interface(struct nand_chip *chip,
> > +				     struct nand_data_interface *iface)
> > +{
> > +	int ret;
> > +
> > +	ret = onfi_fill_data_interface(chip, iface, NAND_SDR_IFACE, 4);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return nand_choose_best_sdr_timings(chip, iface, NULL);
> > +}
> > +
> >  static int hynix_nand_init(struct nand_chip *chip)
> >  {
> >  	struct hynix_nand *hynix;
> > @@ -689,6 +702,9 @@ static int hynix_nand_init(struct nand_chip *chip)
> >  
> >  	nand_set_manufacturer_data(chip, hynix);
> >  
> > +	if (!strcmp("H27UCG8T2ATR-BC", chip->parameters.model))
> > +		chip->ops.choose_data_interface = h27ucg8t2atrbc_choose_data_interface;  
> 
> Same here. You either have to compare against "H27UCG8T2ATR-BC 64G 3.3V
> 8-bit" or use strncmp. This being said, I wonder if comparing the ID is
> not simpler.

I prefer to stick to strncmp so that the name of the part is clearly
identified for now. Maybe if we have too much exceptions coming in
we'll have to switch to ID bytes to "share" conditions between similar
parts.

> 
> > +
> >  	ret = hynix_nand_rr_init(chip);
> >  	if (ret)
> >  		hynix_nand_cleanup(chip);
> > diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
> > index c729a8bc895d..3b890d55703d 100644
> > --- a/drivers/mtd/nand/raw/nand_ids.c
> > +++ b/drivers/mtd/nand/raw/nand_ids.c
> > @@ -50,7 +50,7 @@ struct nand_flash_dev nand_flash_ids[] = {
> >  	{"H27UCG8T2ATR-BC 64G 3.3V 8-bit",
> >  		{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
> >  		  SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640,
> > -		  NAND_ECC_INFO(40, SZ_1K), 4 },
> > +		  NAND_ECC_INFO(40, SZ_1K) },
> >    
> 
> Ultimately we should have those vendor specific entries defined in each
> vendor driver rather than declared here (not asking that for this
> series though).
> 
> >  	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
> >  	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),  
> 

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 28/28] mtd: rawnand: Allocate the best data interface structure dynamically
  2020-05-26 22:28   ` Boris Brezillon
@ 2020-05-27  7:57     ` Miquel Raynal
  2020-05-27  8:35       ` Boris Brezillon
  0 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-27  7:57 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus


Boris Brezillon <boris.brezillon@collabora.com> wrote on Wed, 27 May
2020 00:28:44 +0200:

> On Tue, 26 May 2020 21:17:25 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > Instead of manipulating the statically allocated structure and copy
> > timings around, allocate one at identification time and save it in the
> > nand_chip structure once it has been initialized.
> > 
> > This way, either there is a "best data interface" and the requested
> > timings will be these, or there is none, forcing the core to use the
> > default set, statically defined in the core, shared across all NAND
> > chips.
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/mtd/nand/raw/nand_base.c | 42 ++++++++++++++++++++++----------
> >  include/linux/mtd/rawnand.h      | 13 +++++++---
> >  2 files changed, 39 insertions(+), 16 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > index 2547136a9cd7..247bf5faaf55 100644
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> > @@ -947,7 +947,7 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
> >   */
> >  static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
> >  {
> > -	u8 mode = chip->data_interface.timings.mode;
> > +	u8 mode = chip->best_iface->timings.mode;
> >  	u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { mode, };
> >  	int ret;
> >  
> > @@ -966,7 +966,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
> >  
> >  	/* Change the mode on the controller side */
> >  	ret = chip->controller->ops->setup_data_interface(chip, chipnr,
> > -							&chip->data_interface);
> > +							  chip->best_iface);
> >  	if (ret)
> >  		return ret;
> >  
> > @@ -1030,8 +1030,10 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
> >  		ret = ops->setup_data_interface(chip,
> >  						NAND_DATA_IFACE_CHECK_ONLY,
> >  						iface);
> > -		if (!ret)
> > +		if (!ret) {
> > +			chip->best_iface = iface;
> >  			return ret;
> > +		}
> >  
> >  		/* Fallback to slower modes */
> >  		best_mode = iface->timings.mode;
> > @@ -1052,6 +1054,8 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
> >  			break;
> >  	}
> >  
> > +	chip->best_iface = iface;
> > +
> >  	return 0;
> >  }
> >  
> > @@ -1070,14 +1074,25 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
> >   */
> >  static int nand_choose_data_interface(struct nand_chip *chip)
> >  {
> > +	struct nand_data_interface *iface;
> > +	int ret;
> > +
> >  	if (!nand_controller_has_setup_data_iface(chip))
> >  		return 0;
> >  
> > +	iface = kzalloc(sizeof(*iface), GFP_KERNEL);
> > +	if (!iface)
> > +		return -ENOMEM;
> > +
> >  	if (chip->ops.choose_data_interface)
> > -		return chip->ops.choose_data_interface(chip,
> > -						       &chip->data_interface);
> > +		ret = chip->ops.choose_data_interface(chip, iface);
> > +	else
> > +		ret = nand_choose_best_sdr_timings(chip, iface, NULL);
> >  
> > -	return nand_choose_best_sdr_timings(chip, &chip->data_interface, NULL);
> > +	if (ret)
> > +		kfree(iface);
> > +
> > +	return ret;
> >  }
> >  
> >  /**
> > @@ -2514,8 +2529,7 @@ int nand_reset(struct nand_chip *chip, int chipnr)
> >  	 * nand_setup_data_interface() uses ->set/get_features() which would
> >  	 * fail anyway as the parameter page is not available yet.
> >  	 */
> > -	if (!memcmp(&chip->data_interface, nand_reset_data_iface,
> > -		    sizeof(*nand_reset_data_iface)))
> > +	if (!chip->best_iface)
> >  		return 0;
> >    
> 
> If you assign ->best_iface for mode 0 (as done above) and keep the
> !chip->best_iface test that means you apply timing mode 0 twice. Not
> a big deal but I wanted to point it out.

That's partially true, because what is your way to discriminate between
a virgin mode 0 and a mode 1 but not totally 1 so it is reported as 0?
We should do a memcmp(). So IMHO it's worth the extra call to
nand_setup_data_interface() to have a clear and quick condition here.

> 
> >  	ret = nand_setup_data_interface(chip, chipnr);
> > @@ -5252,9 +5266,6 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
> >  
> >  	mutex_init(&chip->lock);
> >  
> > -	/* Enforce the right timings for reset/detection */
> > -	onfi_fill_data_interface(chip, &chip->data_interface, NAND_SDR_IFACE, 0);
> > -
> >  	ret = nand_dt_init(chip);
> >  	if (ret)
> >  		return ret;
> > @@ -6059,7 +6070,7 @@ static int nand_scan_tail(struct nand_chip *chip)
> >  	for (i = 0; i < nanddev_ntargets(&chip->base); i++) {
> >  		ret = nand_setup_data_interface(chip, i);
> >  		if (ret)
> > -			goto err_nanddev_cleanup;
> > +			goto err_free_data_iface;
> >  	}
> >  
> >  	/* Check, if we should skip the bad block table scan */
> > @@ -6069,10 +6080,12 @@ static int nand_scan_tail(struct nand_chip *chip)
> >  	/* Build bad block table */
> >  	ret = nand_create_bbt(chip);
> >  	if (ret)
> > -		goto err_nanddev_cleanup;
> > +		goto err_free_data_iface;
> >  
> >  	return 0;
> >  
> > +err_free_data_iface:
> > +	kfree(chip->best_iface);
> >  
> >  err_nanddev_cleanup:
> >  	nanddev_cleanup(&chip->base);
> > @@ -6166,6 +6179,9 @@ void nand_cleanup(struct nand_chip *chip)
> >  			& NAND_BBT_DYNAMICSTRUCT)
> >  		kfree(chip->badblock_pattern);
> >  
> > +	/* Free the data interface */
> > +	kfree(chip->best_iface);
> > +
> >  	/* Free manufacturer priv data. */
> >  	nand_manufacturer_cleanup(chip);
> >  
> > diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> > index 00557e553827..0f215faa3072 100644
> > --- a/include/linux/mtd/rawnand.h
> > +++ b/include/linux/mtd/rawnand.h
> > @@ -1070,7 +1070,9 @@ struct nand_manufacturer {
> >   * @options: Various chip options. They can partly be set to inform nand_scan
> >   *           about special functionality. See the defines for further
> >   *           explanation.
> > - * @data_interface: NAND interface timing information
> > + * @best_iface: The best NAND data interface which fits both the NAND chip and  
> 
> 						^ configuration
> 
> > + *              NAND controller constraints. If unset, the default reset data
> > + *              interface must be used.
> >   * @bbt_erase_shift: Number of address bits in a bbt entry
> >   * @bbt_options: Bad block table specific options. All options used here must
> >   *               come from bbm.h. By default, these options will be copied to
> > @@ -1117,7 +1119,7 @@ struct nand_chip {
> >  	unsigned int options;
> >  
> >  	/* Data interface */
> > -	struct nand_data_interface data_interface;
> > +	struct nand_data_interface *best_iface;  
> 
> Not sure why you rename this field, but if we go for a name update, I'd
> vote for best_iface_cfg (or something that clarifies the fact that this
> is the data interface configuration).

Maybe I misunderstood your request, you were saying that allocating a
"best data interface object" would be good, so I interpreted it as:
rename it, and allocated it dynamically. I'm fine keeping
data_interface and just declaring it as a pointer.

Anyway, I like talking about the "interface" rather than the "interface
configuration" which is implied in my mind, I saw you were asking to
add "configuration" sometimes, do you have something in mind that I
don't?

> 
> >  
> >  	/* Bad block information */
> >  	unsigned int bbt_erase_shift;
> > @@ -1212,7 +1214,12 @@ extern const struct nand_data_interface *nand_reset_data_iface;
> >  static inline const struct nand_sdr_timings *
> >  nand_get_sdr_timings(struct nand_chip *chip)
> >  {
> > -	return nand_extract_sdr_timings(&chip->data_interface);
> > +	const struct nand_data_interface *iface = chip->best_iface;
> > +
> > +	if (!iface)
> > +		iface = nand_reset_data_iface;
> > +
> > +	return nand_extract_sdr_timings(iface);
> >  }
> >  
> >  /*  
> 


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 17/28] mtd: rawnand: Define a unique reset data interface
  2020-05-27  7:20     ` Miquel Raynal
@ 2020-05-27  8:10       ` Boris Brezillon
  0 siblings, 0 replies; 62+ messages in thread
From: Boris Brezillon @ 2020-05-27  8:10 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Wed, 27 May 2020 09:20:46 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Hi Boris,
> 
> Boris Brezillon <boris.brezillon@collabora.com> wrote on Tue, 26 May
> 2020 23:23:38 +0200:
> 
> > On Tue, 26 May 2020 21:17:14 +0200
> > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >   
> > > All NAND chips will always use the same data interface for reset and
> > > at startup: SDR mode 0. Instead of copying around the data interface
> > > timings, let's just have a default reset data interface for that.
> > > 
> > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > ---
> > >  drivers/mtd/nand/raw/nand_base.c    | 9 +++------
> > >  drivers/mtd/nand/raw/nand_timings.c | 3 +++
> > >  include/linux/mtd/rawnand.h         | 3 +++
> > >  3 files changed, 9 insertions(+), 6 deletions(-)
> > > 
> > > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > > index 89f10a8c1d62..1005035c233a 100644
> > > --- a/drivers/mtd/nand/raw/nand_base.c
> > > +++ b/drivers/mtd/nand/raw/nand_base.c
> > > @@ -927,9 +927,8 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
> > >  	 * timings to timing mode 0.
> > >  	 */
> > >  
> > > -	onfi_fill_data_interface(chip, &chip->data_interface, NAND_SDR_IFACE, 0);
> > >  	ret = chip->controller->ops->setup_data_interface(chip, chipnr,
> > > -							&chip->data_interface);
> > > +							  nand_reset_data_iface);
> > >  	if (ret)
> > >  		pr_err("Failed to configure data interface to SDR timing mode 0\n");
> > >  
> > > @@ -2484,7 +2483,6 @@ EXPORT_SYMBOL_GPL(nand_subop_get_data_len);
> > >   */
> > >  int nand_reset(struct nand_chip *chip, int chipnr)
> > >  {
> > > -	struct nand_data_interface saved_data_intf = chip->data_interface;
> > >  	int ret;
> > >  
> > >  	ret = nand_reset_data_interface(chip, chipnr);
> > > @@ -2509,11 +2507,10 @@ int nand_reset(struct nand_chip *chip, int chipnr)
> > >  	 * nand_setup_data_interface() uses ->set/get_features() which would
> > >  	 * fail anyway as the parameter page is not available yet.
> > >  	 */
> > > -	if (!memcmp(&chip->data_interface, &saved_data_intf,
> > > -		    sizeof(saved_data_intf)))
> > > +	if (!memcmp(&chip->data_interface, nand_reset_data_iface,
> > > +		    sizeof(*nand_reset_data_iface)))
> > >  		return 0;
> > >  
> > > -	chip->data_interface = saved_data_intf;
> > >  	ret = nand_setup_data_interface(chip, chipnr);
> > >  	if (ret)
> > >  		return ret;
> > > diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
> > > index 52ee83e75646..343284c43e81 100644
> > > --- a/drivers/mtd/nand/raw/nand_timings.c
> > > +++ b/drivers/mtd/nand/raw/nand_timings.c
> > > @@ -285,6 +285,9 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
> > >  	},
> > >  };
> > >  
> > > +/* All NAND chips share the same reset data interface: SDR mode 0 */
> > > +const struct nand_data_interface *nand_reset_data_iface = &onfi_sdr_timings[0];    
> > 
> > Can we make that one a function?
> > 
> > const struct nand_data_interface *nand_get_reset_data_interface(void)

On a second thought, I think adding _config() would be better. And
since we are at refactoring/renaming things, I'd suggest a transversal
s/data_interface/interface_config/ rename.

--->8---
From 1a67f7f1883777b91997c2a9ec46e738689bfd8d Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon@collabora.com>
Date: Wed, 27 May 2020 10:08:22 +0200
Subject: [PATCH] mtd: rawnand: s/data_interface/interface_config/

The name/suffix data_interface is a bit misleading in that the field
or functions actually represent a configuration that can be applied by
the controller/chip. Let's rename all fields/functions/hooks that are
worth renaming.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/raw/ams-delta.c              |  6 +-
 drivers/mtd/nand/raw/arasan-nand-controller.c |  6 +-
 drivers/mtd/nand/raw/atmel/nand-controller.c  | 34 ++++----
 .../mtd/nand/raw/cadence-nand-controller.c    |  6 +-
 drivers/mtd/nand/raw/denali.c                 |  8 +-
 drivers/mtd/nand/raw/fsmc_nand.c              |  6 +-
 drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c    |  6 +-
 drivers/mtd/nand/raw/internals.h              |  8 +-
 drivers/mtd/nand/raw/marvell_nand.c           | 13 ++-
 drivers/mtd/nand/raw/meson_nand.c             | 10 +--
 drivers/mtd/nand/raw/mtk_nand.c               |  6 +-
 drivers/mtd/nand/raw/mxc_nand.c               | 20 ++---
 drivers/mtd/nand/raw/mxic_nand.c              |  6 +-
 drivers/mtd/nand/raw/nand_base.c              | 84 +++++++++----------
 drivers/mtd/nand/raw/nand_legacy.c            |  2 +-
 drivers/mtd/nand/raw/nand_timings.c           | 12 +--
 drivers/mtd/nand/raw/nand_toshiba.c           |  2 +-
 drivers/mtd/nand/raw/s3c2410.c                |  6 +-
 drivers/mtd/nand/raw/stm32_fmc2_nand.c        |  6 +-
 drivers/mtd/nand/raw/sunxi_nand.c             |  6 +-
 drivers/mtd/nand/raw/tango_nand.c             |  4 +-
 drivers/mtd/nand/raw/tegra_nand.c             |  6 +-
 include/linux/mtd/rawnand.h                   | 29 ++++---
 23 files changed, 145 insertions(+), 147 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 3711e7a0436c..fdba155416d2 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -191,8 +191,8 @@ static int gpio_nand_exec_op(struct nand_chip *this,
 	return ret;
 }
 
-static int gpio_nand_setup_data_interface(struct nand_chip *this, int csline,
-					  const struct nand_data_interface *cf)
+static int gpio_nand_setup_interface(struct nand_chip *this, int csline,
+				     const struct nand_interface_config *cf)
 {
 	struct gpio_nand *priv = nand_get_controller_data(this);
 	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(cf);
@@ -217,7 +217,7 @@ static int gpio_nand_setup_data_interface(struct nand_chip *this, int csline,
 
 static const struct nand_controller_ops gpio_nand_ops = {
 	.exec_op = gpio_nand_exec_op,
-	.setup_data_interface = gpio_nand_setup_data_interface,
+	.setup_interface = gpio_nand_setup_interface,
 };
 
 /*
diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c
index 7141dcccba3c..12c643e97c85 100644
--- a/drivers/mtd/nand/raw/arasan-nand-controller.c
+++ b/drivers/mtd/nand/raw/arasan-nand-controller.c
@@ -854,8 +854,8 @@ static int anfc_exec_op(struct nand_chip *chip,
 	return nand_op_parser_exec_op(chip, &anfc_op_parser, op, check_only);
 }
 
-static int anfc_setup_data_interface(struct nand_chip *chip, int target,
-				     const struct nand_data_interface *conf)
+static int anfc_setup_interface(struct nand_chip *chip, int target,
+				const struct nand_interface_config *conf)
 {
 	struct anand *anand = to_anand(chip);
 	struct arasan_nfc *nfc = to_anfc(chip->controller);
@@ -1083,7 +1083,7 @@ static void anfc_detach_chip(struct nand_chip *chip)
 
 static const struct nand_controller_ops anfc_ops = {
 	.exec_op = anfc_exec_op,
-	.setup_data_interface = anfc_setup_data_interface,
+	.setup_interface = anfc_setup_interface,
 	.attach_chip = anfc_attach_chip,
 	.detach_chip = anfc_detach_chip,
 };
diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
index 46a3724a788e..c9818f548d07 100644
--- a/drivers/mtd/nand/raw/atmel/nand-controller.c
+++ b/drivers/mtd/nand/raw/atmel/nand-controller.c
@@ -200,8 +200,8 @@ struct atmel_nand_controller_ops {
 	void (*nand_init)(struct atmel_nand_controller *nc,
 			  struct atmel_nand *nand);
 	int (*ecc_init)(struct nand_chip *chip);
-	int (*setup_data_interface)(struct atmel_nand *nand, int csline,
-				    const struct nand_data_interface *conf);
+	int (*setup_interface)(struct atmel_nand *nand, int csline,
+			       const struct nand_interface_config *conf);
 };
 
 struct atmel_nand_controller_caps {
@@ -1168,7 +1168,7 @@ static int atmel_hsmc_nand_ecc_init(struct nand_chip *chip)
 }
 
 static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand,
-					const struct nand_data_interface *conf,
+					const struct nand_interface_config *conf,
 					struct atmel_smc_cs_conf *smcconf)
 {
 	u32 ncycles, totalcycles, timeps, mckperiodps;
@@ -1397,9 +1397,9 @@ static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand,
 	return 0;
 }
 
-static int atmel_smc_nand_setup_data_interface(struct atmel_nand *nand,
+static int atmel_smc_nand_setup_interface(struct atmel_nand *nand,
 					int csline,
-					const struct nand_data_interface *conf)
+					const struct nand_interface_config *conf)
 {
 	struct atmel_nand_controller *nc;
 	struct atmel_smc_cs_conf smcconf;
@@ -1422,9 +1422,9 @@ static int atmel_smc_nand_setup_data_interface(struct atmel_nand *nand,
 	return 0;
 }
 
-static int atmel_hsmc_nand_setup_data_interface(struct atmel_nand *nand,
+static int atmel_hsmc_nand_setup_interface(struct atmel_nand *nand,
 					int csline,
-					const struct nand_data_interface *conf)
+					const struct nand_interface_config *conf)
 {
 	struct atmel_hsmc_nand_controller *nc;
 	struct atmel_smc_cs_conf smcconf;
@@ -1452,8 +1452,8 @@ static int atmel_hsmc_nand_setup_data_interface(struct atmel_nand *nand,
 	return 0;
 }
 
-static int atmel_nand_setup_data_interface(struct nand_chip *chip, int csline,
-					const struct nand_data_interface *conf)
+static int atmel_nand_setup_interface(struct nand_chip *chip, int csline,
+				      const struct nand_interface_config *conf)
 {
 	struct atmel_nand *nand = to_atmel_nand(chip);
 	struct atmel_nand_controller *nc;
@@ -1464,7 +1464,7 @@ static int atmel_nand_setup_data_interface(struct nand_chip *chip, int csline,
 	    (csline < 0 && csline != NAND_DATA_IFACE_CHECK_ONLY))
 		return -EINVAL;
 
-	return nc->caps->ops->setup_data_interface(nand, csline, conf);
+	return nc->caps->ops->setup_interface(nand, csline, conf);
 }
 
 static void atmel_nand_init(struct atmel_nand_controller *nc,
@@ -1483,7 +1483,7 @@ static void atmel_nand_init(struct atmel_nand_controller *nc,
 	chip->legacy.write_buf = atmel_nand_write_buf;
 	chip->legacy.select_chip = atmel_nand_select_chip;
 
-	if (!nc->mck || !nc->caps->ops->setup_data_interface)
+	if (!nc->mck || !nc->caps->ops->setup_interface)
 		chip->options |= NAND_KEEP_TIMINGS;
 
 	/* Some NANDs require a longer delay than the default one (20us). */
@@ -1956,7 +1956,7 @@ static int atmel_nand_attach_chip(struct nand_chip *chip)
 
 static const struct nand_controller_ops atmel_nand_controller_ops = {
 	.attach_chip = atmel_nand_attach_chip,
-	.setup_data_interface = atmel_nand_setup_data_interface,
+	.setup_interface = atmel_nand_setup_interface,
 };
 
 static int atmel_nand_controller_init(struct atmel_nand_controller *nc,
@@ -2318,7 +2318,7 @@ static const struct atmel_nand_controller_ops atmel_hsmc_nc_ops = {
 	.remove = atmel_hsmc_nand_controller_remove,
 	.ecc_init = atmel_hsmc_nand_ecc_init,
 	.nand_init = atmel_hsmc_nand_init,
-	.setup_data_interface = atmel_hsmc_nand_setup_data_interface,
+	.setup_interface = atmel_hsmc_nand_setup_interface,
 };
 
 static const struct atmel_nand_controller_caps atmel_sama5_nc_caps = {
@@ -2375,10 +2375,10 @@ atmel_smc_nand_controller_remove(struct atmel_nand_controller *nc)
 
 /*
  * The SMC reg layout of at91rm9200 is completely different which prevents us
- * from re-using atmel_smc_nand_setup_data_interface() for the
- * ->setup_data_interface() hook.
+ * from re-using atmel_smc_nand_setup_interface() for the
+ * ->setup_interface() hook.
  * At this point, there's no support for the at91rm9200 SMC IP, so we leave
- * ->setup_data_interface() unassigned.
+ * ->setup_interface() unassigned.
  */
 static const struct atmel_nand_controller_ops at91rm9200_nc_ops = {
 	.probe = atmel_smc_nand_controller_probe,
@@ -2399,7 +2399,7 @@ static const struct atmel_nand_controller_ops atmel_smc_nc_ops = {
 	.remove = atmel_smc_nand_controller_remove,
 	.ecc_init = atmel_nand_ecc_init,
 	.nand_init = atmel_smc_nand_init,
-	.setup_data_interface = atmel_smc_nand_setup_data_interface,
+	.setup_interface = atmel_smc_nand_setup_interface,
 };
 
 static const struct atmel_nand_controller_caps atmel_sam9260_nc_caps = {
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c
index c405722adfe1..574cbd3446e5 100644
--- a/drivers/mtd/nand/raw/cadence-nand-controller.c
+++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
@@ -2303,8 +2303,8 @@ static inline u32 calc_tdvw(u32 trp_cnt, u32 clk_period, u32 trhoh_min,
 }
 
 static int
-cadence_nand_setup_data_interface(struct nand_chip *chip, int chipnr,
-				  const struct nand_data_interface *conf)
+cadence_nand_setup_interface(struct nand_chip *chip, int chipnr,
+			     const struct nand_interface_config *conf)
 {
 	const struct nand_sdr_timings *sdr;
 	struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller);
@@ -2690,7 +2690,7 @@ static int cadence_nand_attach_chip(struct nand_chip *chip)
 static const struct nand_controller_ops cadence_nand_controller_ops = {
 	.attach_chip = cadence_nand_attach_chip,
 	.exec_op = cadence_nand_exec_op,
-	.setup_data_interface = cadence_nand_setup_data_interface,
+	.setup_interface = cadence_nand_setup_interface,
 };
 
 static int cadence_nand_chip_init(struct cdns_nand_ctrl *cdns_ctrl,
diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
index 4e6e1578aa2d..9d99dade95ce 100644
--- a/drivers/mtd/nand/raw/denali.c
+++ b/drivers/mtd/nand/raw/denali.c
@@ -761,8 +761,8 @@ static int denali_write_page(struct nand_chip *chip, const u8 *buf,
 	return denali_page_xfer(chip, (void *)buf, mtd->writesize, page, true);
 }
 
-static int denali_setup_data_interface(struct nand_chip *chip, int chipnr,
-				       const struct nand_data_interface *conf)
+static int denali_setup_interface(struct nand_chip *chip, int chipnr,
+				  const struct nand_interface_config *conf)
 {
 	static const unsigned int data_setup_on_host = 10000;
 	struct denali_controller *denali = to_denali_controller(chip);
@@ -1173,7 +1173,7 @@ static int denali_exec_op(struct nand_chip *chip,
 static const struct nand_controller_ops denali_controller_ops = {
 	.attach_chip = denali_attach_chip,
 	.exec_op = denali_exec_op,
-	.setup_data_interface = denali_setup_data_interface,
+	.setup_interface = denali_setup_interface,
 };
 
 int denali_chip_init(struct denali_controller *denali,
@@ -1230,7 +1230,7 @@ int denali_chip_init(struct denali_controller *denali,
 		chip->buf_align = 16;
 	}
 
-	/* clk rate info is needed for setup_data_interface */
+	/* clk rate info is needed for setup_interface */
 	if (!denali->clk_rate || !denali->clk_x_rate)
 		chip->options |= NAND_KEEP_TIMINGS;
 
diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
index 3909752b14c5..92ddc41d0ff0 100644
--- a/drivers/mtd/nand/raw/fsmc_nand.c
+++ b/drivers/mtd/nand/raw/fsmc_nand.c
@@ -327,8 +327,8 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host,
 	return 0;
 }
 
-static int fsmc_setup_data_interface(struct nand_chip *nand, int csline,
-				     const struct nand_data_interface *conf)
+static int fsmc_setup_interface(struct nand_chip *nand, int csline,
+				const struct nand_interface_config *conf)
 {
 	struct fsmc_nand_data *host = nand_to_fsmc(nand);
 	struct fsmc_nand_timings tims;
@@ -951,7 +951,7 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand)
 static const struct nand_controller_ops fsmc_nand_controller_ops = {
 	.attach_chip = fsmc_nand_attach_chip,
 	.exec_op = fsmc_exec_op,
-	.setup_data_interface = fsmc_setup_data_interface,
+	.setup_interface = fsmc_setup_interface,
 };
 
 /**
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 061a8ddda275..5d4aee46cc55 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -736,8 +736,8 @@ static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
 	udelay(dll_wait_time_us);
 }
 
-static int gpmi_setup_data_interface(struct nand_chip *chip, int chipnr,
-				     const struct nand_data_interface *conf)
+static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
+				const struct nand_interface_config *conf)
 {
 	struct gpmi_nand_data *this = nand_get_controller_data(chip);
 	const struct nand_sdr_timings *sdr;
@@ -2400,7 +2400,7 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
 
 static const struct nand_controller_ops gpmi_nand_controller_ops = {
 	.attach_chip = gpmi_nand_attach_chip,
-	.setup_data_interface = gpmi_setup_data_interface,
+	.setup_interface = gpmi_setup_interface,
 	.exec_op = gpmi_nfc_exec_op,
 };
 
diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index 03866b0aadea..1e85e046625b 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -84,9 +84,9 @@ int nand_bbm_get_next_page(struct nand_chip *chip, int page);
 int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs);
 int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
 		    int allowbbt);
-int onfi_fill_data_interface(struct nand_chip *chip,
-			     enum nand_data_interface_type type,
-			     int timing_mode);
+int onfi_fill_interface_config(struct nand_chip *chip,
+			      enum nand_interface_type type,
+			      int timing_mode);
 int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
 int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
 int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf,
@@ -133,7 +133,7 @@ static inline int nand_exec_op(struct nand_chip *chip,
 static inline bool nand_has_setup_data_iface(struct nand_chip *chip)
 {
 	if (!chip->controller || !chip->controller->ops ||
-	    !chip->controller->ops->setup_data_interface)
+	    !chip->controller->ops->setup_interface)
 		return false;
 
 	if (chip->options & NAND_KEEP_TIMINGS)
diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
index 260a0430313e..37d451f5e898 100644
--- a/drivers/mtd/nand/raw/marvell_nand.c
+++ b/drivers/mtd/nand/raw/marvell_nand.c
@@ -1141,7 +1141,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip,
 		return ret;
 
 	ret = marvell_nfc_wait_op(chip,
-				  PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max));
+				  PSEC_TO_MSEC(chip->interface_config.timings.sdr.tPROG_max));
 	return ret;
 }
 
@@ -1599,7 +1599,7 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip,
 	}
 
 	ret = marvell_nfc_wait_op(chip,
-				  PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max));
+				  PSEC_TO_MSEC(chip->interface_config.timings.sdr.tPROG_max));
 
 	marvell_nfc_disable_hw_ecc(chip);
 
@@ -2305,9 +2305,8 @@ static struct nand_bbt_descr bbt_mirror_descr = {
 	.pattern = bbt_mirror_pattern
 };
 
-static int marvell_nfc_setup_data_interface(struct nand_chip *chip, int chipnr,
-					    const struct nand_data_interface
-					    *conf)
+static int marvell_nfc_setup_interface(struct nand_chip *chip, int chipnr,
+				       const struct nand_interface_config *conf)
 {
 	struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
 	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
@@ -2508,7 +2507,7 @@ static int marvell_nand_attach_chip(struct nand_chip *chip)
 static const struct nand_controller_ops marvell_nand_controller_ops = {
 	.attach_chip = marvell_nand_attach_chip,
 	.exec_op = marvell_nfc_exec_op,
-	.setup_data_interface = marvell_nfc_setup_data_interface,
+	.setup_interface = marvell_nfc_setup_interface,
 };
 
 static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
@@ -2644,7 +2643,7 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
 
 	/*
 	 * Save a reference value for timing registers before
-	 * ->setup_data_interface() is called.
+	 * ->setup_interface() is called.
 	 */
 	marvell_nand->ndtr0 = readl_relaxed(nfc->regs + NDTR0);
 	marvell_nand->ndtr1 = readl_relaxed(nfc->regs + NDTR1);
diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
index 3f376471f3f7..c9b9594efa4f 100644
--- a/drivers/mtd/nand/raw/meson_nand.c
+++ b/drivers/mtd/nand/raw/meson_nand.c
@@ -576,7 +576,7 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand,
 	struct mtd_info *mtd = nand_to_mtd(nand);
 	struct meson_nfc *nfc = nand_get_controller_data(nand);
 	const struct nand_sdr_timings *sdr =
-		nand_get_sdr_timings(&nand->data_interface);
+		nand_get_sdr_timings(&nand->interface_config);
 	u32 *addrs = nfc->cmdfifo.rw.addrs;
 	u32 cs = nfc->param.chip_select;
 	u32 cmd0, cmd_num, row_start;
@@ -628,7 +628,7 @@ static int meson_nfc_write_page_sub(struct nand_chip *nand,
 {
 	struct mtd_info *mtd = nand_to_mtd(nand);
 	const struct nand_sdr_timings *sdr =
-		nand_get_sdr_timings(&nand->data_interface);
+		nand_get_sdr_timings(&nand->interface_config);
 	struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
 	struct meson_nfc *nfc = nand_get_controller_data(nand);
 	int data_len, info_len;
@@ -1097,8 +1097,8 @@ static int meson_chip_buffer_init(struct nand_chip *nand)
 }
 
 static
-int meson_nfc_setup_data_interface(struct nand_chip *nand, int csline,
-				   const struct nand_data_interface *conf)
+int meson_nfc_setup_interface(struct nand_chip *nand, int csline,
+			      const struct nand_interface_config *conf)
 {
 	struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
 	const struct nand_sdr_timings *timings;
@@ -1222,7 +1222,7 @@ static int meson_nand_attach_chip(struct nand_chip *nand)
 static const struct nand_controller_ops meson_nand_controller_ops = {
 	.attach_chip = meson_nand_attach_chip,
 	.detach_chip = meson_nand_detach_chip,
-	.setup_data_interface = meson_nfc_setup_data_interface,
+	.setup_interface = meson_nfc_setup_interface,
 	.exec_op = meson_nfc_exec_op,
 };
 
diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
index c1a6e31aabb8..a3bc1b2d6bbd 100644
--- a/drivers/mtd/nand/raw/mtk_nand.c
+++ b/drivers/mtd/nand/raw/mtk_nand.c
@@ -501,8 +501,8 @@ static void mtk_nfc_write_buf(struct nand_chip *chip, const u8 *buf, int len)
 		mtk_nfc_write_byte(chip, buf[i]);
 }
 
-static int mtk_nfc_setup_data_interface(struct nand_chip *chip, int csline,
-					const struct nand_data_interface *conf)
+static int mtk_nfc_setup_interface(struct nand_chip *chip, int csline,
+				   const struct nand_interface_config *conf)
 {
 	struct mtk_nfc *nfc = nand_get_controller_data(chip);
 	const struct nand_sdr_timings *timings;
@@ -1325,7 +1325,7 @@ static int mtk_nfc_attach_chip(struct nand_chip *chip)
 
 static const struct nand_controller_ops mtk_nfc_controller_ops = {
 	.attach_chip = mtk_nfc_attach_chip,
-	.setup_data_interface = mtk_nfc_setup_data_interface,
+	.setup_interface = mtk_nfc_setup_interface,
 };
 
 static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c
index 09dacb83cb5a..07c41e8bae2d 100644
--- a/drivers/mtd/nand/raw/mxc_nand.c
+++ b/drivers/mtd/nand/raw/mxc_nand.c
@@ -137,8 +137,8 @@ struct mxc_nand_devtype_data {
 	u32 (*get_ecc_status)(struct mxc_nand_host *);
 	const struct mtd_ooblayout_ops *ooblayout;
 	void (*select_chip)(struct nand_chip *chip, int cs);
-	int (*setup_data_interface)(struct nand_chip *chip, int csline,
-				    const struct nand_data_interface *conf);
+	int (*setup_interface)(struct nand_chip *chip, int csline,
+			       const struct nand_interface_config *conf);
 	void (*enable_hwecc)(struct nand_chip *chip, bool enable);
 
 	/*
@@ -1139,8 +1139,8 @@ static void preset_v1(struct mtd_info *mtd)
 	writew(0x4, NFC_V1_V2_WRPROT);
 }
 
-static int mxc_nand_v2_setup_data_interface(struct nand_chip *chip, int csline,
-					const struct nand_data_interface *conf)
+static int mxc_nand_v2_setup_interface(struct nand_chip *chip, int csline,
+				       const struct nand_interface_config *conf)
 {
 	struct mxc_nand_host *host = nand_get_controller_data(chip);
 	int tRC_min_ns, tRC_ps, ret;
@@ -1521,7 +1521,7 @@ static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
 	.get_ecc_status = get_ecc_status_v2,
 	.ooblayout = &mxc_v2_ooblayout_ops,
 	.select_chip = mxc_nand_select_chip_v2,
-	.setup_data_interface = mxc_nand_v2_setup_data_interface,
+	.setup_interface = mxc_nand_v2_setup_interface,
 	.enable_hwecc = mxc_nand_enable_hwecc_v1_v2,
 	.irqpending_quirk = 0,
 	.needs_ip = 0,
@@ -1738,17 +1738,17 @@ static int mxcnd_attach_chip(struct nand_chip *chip)
 	return 0;
 }
 
-static int mxcnd_setup_data_interface(struct nand_chip *chip, int chipnr,
-				      const struct nand_data_interface *conf)
+static int mxcnd_setup_interface(struct nand_chip *chip, int chipnr,
+				 const struct nand_interface_config *conf)
 {
 	struct mxc_nand_host *host = nand_get_controller_data(chip);
 
-	return host->devtype_data->setup_data_interface(chip, chipnr, conf);
+	return host->devtype_data->setup_interface(chip, chipnr, conf);
 }
 
 static const struct nand_controller_ops mxcnd_controller_ops = {
 	.attach_chip = mxcnd_attach_chip,
-	.setup_data_interface = mxcnd_setup_data_interface,
+	.setup_interface = mxcnd_setup_interface,
 };
 
 static int mxcnd_probe(struct platform_device *pdev)
@@ -1809,7 +1809,7 @@ static int mxcnd_probe(struct platform_device *pdev)
 	if (err < 0)
 		return err;
 
-	if (!host->devtype_data->setup_data_interface)
+	if (!host->devtype_data->setup_interface)
 		this->options |= NAND_KEEP_TIMINGS;
 
 	if (host->devtype_data->needs_ip) {
diff --git a/drivers/mtd/nand/raw/mxic_nand.c b/drivers/mtd/nand/raw/mxic_nand.c
index 57f36721f4c6..d66b5b0971fa 100644
--- a/drivers/mtd/nand/raw/mxic_nand.c
+++ b/drivers/mtd/nand/raw/mxic_nand.c
@@ -451,8 +451,8 @@ static int mxic_nfc_exec_op(struct nand_chip *chip,
 	return ret;
 }
 
-static int mxic_nfc_setup_data_interface(struct nand_chip *chip, int chipnr,
-					 const struct nand_data_interface *conf)
+static int mxic_nfc_setup_interface(struct nand_chip *chip, int chipnr,
+				    const struct nand_interface_config *conf)
 {
 	struct mxic_nand_ctlr *nfc = nand_get_controller_data(chip);
 	const struct nand_sdr_timings *sdr;
@@ -480,7 +480,7 @@ static int mxic_nfc_setup_data_interface(struct nand_chip *chip, int chipnr,
 
 static const struct nand_controller_ops mxic_nand_controller_ops = {
 	.exec_op = mxic_nfc_exec_op,
-	.setup_data_interface = mxic_nfc_setup_data_interface,
+	.setup_interface = mxic_nfc_setup_interface,
 };
 
 static int mxic_nfc_probe(struct platform_device *pdev)
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 6a6a0a36b3fd..32ee84f50cf6 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -773,7 +773,7 @@ int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
 		return -ENOTSUPP;
 
 	/* Wait tWB before polling the STATUS reg. */
-	timings = nand_get_sdr_timings(&chip->data_interface);
+	timings = nand_get_sdr_timings(&chip->interface_config);
 	ndelay(PSEC_TO_NSEC(timings->tWB_max));
 
 	ret = nand_status_op(chip, NULL);
@@ -898,7 +898,7 @@ static bool nand_supports_set_features(struct nand_chip *chip, int addr)
 }
 
 /**
- * nand_reset_data_interface - Reset data interface and timings
+ * nand_reset_interface_config - Reset data interface and timings
  * @chip: The NAND chip
  * @chipnr: Internal die id
  *
@@ -906,7 +906,7 @@ static bool nand_supports_set_features(struct nand_chip *chip, int addr)
  *
  * Returns 0 for success or negative error code otherwise.
  */
-static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
+static int nand_reset_interface_config(struct nand_chip *chip, int chipnr)
 {
 	int ret;
 
@@ -927,9 +927,9 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
 	 * timings to timing mode 0.
 	 */
 
-	onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0);
-	ret = chip->controller->ops->setup_data_interface(chip, chipnr,
-							&chip->data_interface);
+	onfi_fill_interface_config(chip, NAND_SDR_IFACE, 0);
+	ret = chip->controller->ops->setup_interface(chip, chipnr,
+						     &chip->interface_config);
 	if (ret)
 		pr_err("Failed to configure data interface to SDR timing mode 0\n");
 
@@ -937,7 +937,7 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
 }
 
 /**
- * nand_setup_data_interface - Setup the best data interface and timings
+ * nand_setup_interface - Setup the best data interface and timings
  * @chip: The NAND chip
  * @chipnr: Internal die id
  *
@@ -949,7 +949,7 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
  *
  * Returns 0 for success or negative error code otherwise.
  */
-static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
+static int nand_setup_interface(struct nand_chip *chip, int chipnr)
 {
 	u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = {
 		chip->onfi_timing_mode_default,
@@ -970,8 +970,8 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
 	}
 
 	/* Change the mode on the controller side */
-	ret = chip->controller->ops->setup_data_interface(chip, chipnr,
-							&chip->data_interface);
+	ret = chip->controller->ops->setup_interface(chip, chipnr,
+						     &chip->interface_config);
 	if (ret)
 		return ret;
 
@@ -1000,7 +1000,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
 	 * Fallback to mode 0 if the chip explicitly did not ack the chosen
 	 * timing mode.
 	 */
-	nand_reset_data_interface(chip, chipnr);
+	nand_reset_interface_config(chip, chipnr);
 	nand_select_target(chip, chipnr);
 	nand_reset_op(chip);
 	nand_deselect_target(chip);
@@ -1009,7 +1009,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
 }
 
 /**
- * nand_init_data_interface - find the best data interface and timings
+ * nand_init_interface_config - find the best data interface and timings
  * @chip: The NAND chip
  *
  * Find the best data interface and NAND timings supported by the chip
@@ -1017,12 +1017,12 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
  * First tries to retrieve supported timing modes from ONFI information,
  * and if the NAND chip does not support ONFI, relies on the
  * ->onfi_timing_mode_default specified in the nand_ids table. After this
- * function nand_chip->data_interface is initialized with the best timing mode
+ * function nand_chip->interface_config is initialized with the best timing mode
  * available.
  *
  * Returns 0 for success or negative error code otherwise.
  */
-static int nand_init_data_interface(struct nand_chip *chip)
+static int nand_init_interface_config(struct nand_chip *chip)
 {
 	int modes, mode, ret;
 
@@ -1044,7 +1044,7 @@ static int nand_init_data_interface(struct nand_chip *chip)
 	}
 
 	for (mode = fls(modes) - 1; mode >= 0; mode--) {
-		ret = onfi_fill_data_interface(chip, NAND_SDR_IFACE, mode);
+		ret = onfi_fill_interface_config(chip, NAND_SDR_IFACE, mode);
 		if (ret)
 			continue;
 
@@ -1052,9 +1052,9 @@ static int nand_init_data_interface(struct nand_chip *chip)
 		 * Pass NAND_DATA_IFACE_CHECK_ONLY to only check if the
 		 * controller supports the requested timings.
 		 */
-		ret = chip->controller->ops->setup_data_interface(chip,
+		ret = chip->controller->ops->setup_interface(chip,
 						 NAND_DATA_IFACE_CHECK_ONLY,
-						 &chip->data_interface);
+						 &chip->interface_config);
 		if (!ret) {
 			chip->onfi_timing_mode_default = mode;
 			break;
@@ -1124,7 +1124,7 @@ static int nand_sp_exec_read_page_op(struct nand_chip *chip, unsigned int page,
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	const struct nand_sdr_timings *sdr =
-		nand_get_sdr_timings(&chip->data_interface);
+		nand_get_sdr_timings(&chip->interface_config);
 	u8 addrs[4];
 	struct nand_op_instr instrs[] = {
 		NAND_OP_CMD(NAND_CMD_READ0, 0),
@@ -1166,7 +1166,7 @@ static int nand_lp_exec_read_page_op(struct nand_chip *chip, unsigned int page,
 				     unsigned int len)
 {
 	const struct nand_sdr_timings *sdr =
-		nand_get_sdr_timings(&chip->data_interface);
+		nand_get_sdr_timings(&chip->interface_config);
 	u8 addrs[5];
 	struct nand_op_instr instrs[] = {
 		NAND_OP_CMD(NAND_CMD_READ0, 0),
@@ -1263,7 +1263,7 @@ int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf,
 
 	if (nand_has_exec_op(chip)) {
 		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+			nand_get_sdr_timings(&chip->interface_config);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_PARAM, 0),
 			NAND_OP_ADDR(1, &page, PSEC_TO_NSEC(sdr->tWB_max)),
@@ -1318,7 +1318,7 @@ int nand_change_read_column_op(struct nand_chip *chip,
 
 	if (nand_has_exec_op(chip)) {
 		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+			nand_get_sdr_timings(&chip->interface_config);
 		u8 addrs[2] = {};
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_RNDOUT, 0),
@@ -1394,7 +1394,7 @@ static int nand_exec_prog_page_op(struct nand_chip *chip, unsigned int page,
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	const struct nand_sdr_timings *sdr =
-		nand_get_sdr_timings(&chip->data_interface);
+		nand_get_sdr_timings(&chip->interface_config);
 	u8 addrs[5] = {};
 	struct nand_op_instr instrs[] = {
 		/*
@@ -1517,7 +1517,7 @@ int nand_prog_page_end_op(struct nand_chip *chip)
 
 	if (nand_has_exec_op(chip)) {
 		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+			nand_get_sdr_timings(&chip->interface_config);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_PAGEPROG,
 				    PSEC_TO_NSEC(sdr->tWB_max)),
@@ -1624,7 +1624,7 @@ int nand_change_write_column_op(struct nand_chip *chip,
 
 	if (nand_has_exec_op(chip)) {
 		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+			nand_get_sdr_timings(&chip->interface_config);
 		u8 addrs[2];
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_RNDIN, 0),
@@ -1679,7 +1679,7 @@ int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf,
 
 	if (nand_has_exec_op(chip)) {
 		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+			nand_get_sdr_timings(&chip->interface_config);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_READID, 0),
 			NAND_OP_ADDR(1, &addr, PSEC_TO_NSEC(sdr->tADL_min)),
@@ -1718,7 +1718,7 @@ int nand_status_op(struct nand_chip *chip, u8 *status)
 {
 	if (nand_has_exec_op(chip)) {
 		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+			nand_get_sdr_timings(&chip->interface_config);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_STATUS,
 				    PSEC_TO_NSEC(sdr->tADL_min)),
@@ -1787,7 +1787,7 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock)
 
 	if (nand_has_exec_op(chip)) {
 		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+			nand_get_sdr_timings(&chip->interface_config);
 		u8 addrs[3] = {	page, page >> 8, page >> 16 };
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_ERASE1, 0),
@@ -1846,7 +1846,7 @@ static int nand_set_features_op(struct nand_chip *chip, u8 feature,
 
 	if (nand_has_exec_op(chip)) {
 		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+			nand_get_sdr_timings(&chip->interface_config);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_SET_FEATURES, 0),
 			NAND_OP_ADDR(1, &feature, PSEC_TO_NSEC(sdr->tADL_min)),
@@ -1893,7 +1893,7 @@ static int nand_get_features_op(struct nand_chip *chip, u8 feature,
 
 	if (nand_has_exec_op(chip)) {
 		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+			nand_get_sdr_timings(&chip->interface_config);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_GET_FEATURES, 0),
 			NAND_OP_ADDR(1, &feature, PSEC_TO_NSEC(sdr->tWB_max)),
@@ -1950,7 +1950,7 @@ int nand_reset_op(struct nand_chip *chip)
 {
 	if (nand_has_exec_op(chip)) {
 		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+			nand_get_sdr_timings(&chip->interface_config);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_RESET, PSEC_TO_NSEC(sdr->tWB_max)),
 			NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tRST_max), 0),
@@ -2480,17 +2480,17 @@ EXPORT_SYMBOL_GPL(nand_subop_get_data_len);
  * @chipnr: Internal die id
  *
  * Save the timings data structure, then apply SDR timings mode 0 (see
- * nand_reset_data_interface for details), do the reset operation, and
+ * nand_reset_interface_config for details), do the reset operation, and
  * apply back the previous timings.
  *
  * Returns 0 on success, a negative error code otherwise.
  */
 int nand_reset(struct nand_chip *chip, int chipnr)
 {
-	struct nand_data_interface saved_data_intf = chip->data_interface;
+	struct nand_interface_config saved_data_intf = chip->interface_config;
 	int ret;
 
-	ret = nand_reset_data_interface(chip, chipnr);
+	ret = nand_reset_interface_config(chip, chipnr);
 	if (ret)
 		return ret;
 
@@ -2506,17 +2506,17 @@ int nand_reset(struct nand_chip *chip, int chipnr)
 		return ret;
 
 	/*
-	 * A nand_reset_data_interface() put both the NAND chip and the NAND
+	 * A nand_reset_interface_config() put both the NAND chip and the NAND
 	 * controller in timings mode 0. If the default mode for this chip is
 	 * also 0, no need to proceed to the change again. Plus, at probe time,
-	 * nand_setup_data_interface() uses ->set/get_features() which would
+	 * nand_setup_interface() uses ->set/get_features() which would
 	 * fail anyway as the parameter page is not available yet.
 	 */
 	if (!chip->onfi_timing_mode_default)
 		return 0;
 
-	chip->data_interface = saved_data_intf;
-	ret = nand_setup_data_interface(chip, chipnr);
+	chip->interface_config = saved_data_intf;
+	ret = nand_setup_interface(chip, chipnr);
 	if (ret)
 		return ret;
 
@@ -3298,7 +3298,7 @@ static void nand_wait_readrdy(struct nand_chip *chip)
 	if (!(chip->options & NAND_NEED_READRDY))
 		return;
 
-	sdr = nand_get_sdr_timings(&chip->data_interface);
+	sdr = nand_get_sdr_timings(&chip->interface_config);
 	WARN_ON(nand_wait_rdy_op(chip, PSEC_TO_MSEC(sdr->tR_max), 0));
 }
 
@@ -5253,7 +5253,7 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
 	mutex_init(&chip->lock);
 
 	/* Enforce the right timings for reset/detection */
-	onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0);
+	onfi_fill_interface_config(chip, NAND_SDR_IFACE, 0);
 
 	ret = nand_dt_init(chip);
 	if (ret)
@@ -6050,14 +6050,14 @@ static int nand_scan_tail(struct nand_chip *chip)
 	if (!mtd->bitflip_threshold)
 		mtd->bitflip_threshold = DIV_ROUND_UP(mtd->ecc_strength * 3, 4);
 
-	/* Initialize the ->data_interface field. */
-	ret = nand_init_data_interface(chip);
+	/* Initialize the ->interface_config field. */
+	ret = nand_init_interface_config(chip);
 	if (ret)
 		goto err_nanddev_cleanup;
 
 	/* Enter fastest possible mode on all dies. */
 	for (i = 0; i < nanddev_ntargets(&chip->base); i++) {
-		ret = nand_setup_data_interface(chip, i);
+		ret = nand_setup_interface(chip, i);
 		if (ret)
 			goto err_nanddev_cleanup;
 	}
diff --git a/drivers/mtd/nand/raw/nand_legacy.c b/drivers/mtd/nand/raw/nand_legacy.c
index d64791c06a97..a4fa9e2a74e2 100644
--- a/drivers/mtd/nand/raw/nand_legacy.c
+++ b/drivers/mtd/nand/raw/nand_legacy.c
@@ -366,7 +366,7 @@ static void nand_ccs_delay(struct nand_chip *chip)
 	 * (which should be safe for all NANDs).
 	 */
 	if (nand_has_setup_data_iface(chip))
-		ndelay(chip->data_interface.timings.sdr.tCCS_min / 1000);
+		ndelay(chip->interface_config.timings.sdr.tCCS_min / 1000);
 	else
 		ndelay(500);
 }
diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
index 36d21be3dfe5..070bf6989b88 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -12,7 +12,7 @@
 
 #define ONFI_DYN_TIMING_MAX U16_MAX
 
-static const struct nand_data_interface onfi_sdr_timings[] = {
+static const struct nand_interface_config onfi_sdr_timings[] = {
 	/* Mode 0 */
 	{
 		.type = NAND_SDR_IFACE,
@@ -274,15 +274,15 @@ static const struct nand_data_interface onfi_sdr_timings[] = {
 };
 
 /**
- * onfi_fill_data_interface - [NAND Interface] Initialize a data interface from
- * given ONFI mode
+ * onfi_fill_interface_config - Initialize an interface config from the given
+ *				ONFI mode
  * @mode: The ONFI timing mode
  */
-int onfi_fill_data_interface(struct nand_chip *chip,
-			     enum nand_data_interface_type type,
+int onfi_fill_interface_config(struct nand_chip *chip,
+			     enum nand_interface_type type,
 			     int timing_mode)
 {
-	struct nand_data_interface *iface = &chip->data_interface;
+	struct nand_interface_config *iface = &chip->interface_config;
 	struct onfi_params *onfi = chip->parameters.onfi;
 
 	if (type != NAND_SDR_IFACE)
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index ae069905d7e4..f99c9cc5ffa5 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -33,7 +33,7 @@ static int toshiba_nand_benand_read_eccstatus_op(struct nand_chip *chip,
 
 	if (nand_has_exec_op(chip)) {
 		const struct nand_sdr_timings *sdr =
-			nand_get_sdr_timings(&chip->data_interface);
+			nand_get_sdr_timings(&chip->interface_config);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(TOSHIBA_NAND_CMD_ECC_STATUS_READ,
 				    PSEC_TO_NSEC(sdr->tADL_min)),
diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c
index f86dff311464..f121a3ae294c 100644
--- a/drivers/mtd/nand/raw/s3c2410.c
+++ b/drivers/mtd/nand/raw/s3c2410.c
@@ -808,8 +808,8 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
 	return -ENODEV;
 }
 
-static int s3c2410_nand_setup_data_interface(struct nand_chip *chip, int csline,
-					const struct nand_data_interface *conf)
+static int s3c2410_nand_setup_interface(struct nand_chip *chip, int csline,
+					const struct nand_interface_config *conf)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
@@ -999,7 +999,7 @@ static int s3c2410_nand_attach_chip(struct nand_chip *chip)
 
 static const struct nand_controller_ops s3c24xx_nand_controller_ops = {
 	.attach_chip = s3c2410_nand_attach_chip,
-	.setup_data_interface = s3c2410_nand_setup_data_interface,
+	.setup_interface = s3c2410_nand_setup_interface,
 };
 
 static const struct of_device_id s3c24xx_nand_dt_ids[] = {
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 65c9d17b25a3..749ac1044006 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -1308,7 +1308,7 @@ static int stm32_fmc2_nfc_waitrdy(struct nand_chip *chip,
 		dev_warn(nfc->dev, "Waitrdy timeout\n");
 
 	/* Wait tWB before R/B# signal is low */
-	timings = nand_get_sdr_timings(&chip->data_interface);
+	timings = nand_get_sdr_timings(&chip->interface_config);
 	ndelay(PSEC_TO_NSEC(timings->tWB_max));
 
 	/* R/B# signal is low, clear high level flag */
@@ -1546,7 +1546,7 @@ static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
 }
 
 static int stm32_fmc2_nfc_setup_interface(struct nand_chip *chip, int chipnr,
-					  const struct nand_data_interface *conf)
+					  const struct nand_interface_config *conf)
 {
 	const struct nand_sdr_timings *sdrt;
 
@@ -1764,7 +1764,7 @@ static int stm32_fmc2_nfc_attach_chip(struct nand_chip *chip)
 static const struct nand_controller_ops stm32_fmc2_nfc_controller_ops = {
 	.attach_chip = stm32_fmc2_nfc_attach_chip,
 	.exec_op = stm32_fmc2_nfc_exec_op,
-	.setup_data_interface = stm32_fmc2_nfc_setup_interface,
+	.setup_interface = stm32_fmc2_nfc_setup_interface,
 };
 
 static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc,
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index ffbc1651fadc..9c50c2b965e1 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -1376,8 +1376,8 @@ static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration,
 #define sunxi_nand_lookup_timing(l, p, c) \
 			_sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c)
 
-static int sunxi_nfc_setup_data_interface(struct nand_chip *nand, int csline,
-					const struct nand_data_interface *conf)
+static int sunxi_nfc_setup_interface(struct nand_chip *nand, int csline,
+				     const struct nand_interface_config *conf)
 {
 	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
@@ -1920,7 +1920,7 @@ static int sunxi_nfc_exec_op(struct nand_chip *nand,
 
 static const struct nand_controller_ops sunxi_nand_controller_ops = {
 	.attach_chip = sunxi_nand_attach_chip,
-	.setup_data_interface = sunxi_nfc_setup_data_interface,
+	.setup_interface = sunxi_nfc_setup_interface,
 	.exec_op = sunxi_nfc_exec_op,
 };
 
diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c
index 246871e01027..b7a487a4c3b3 100644
--- a/drivers/mtd/nand/raw/tango_nand.c
+++ b/drivers/mtd/nand/raw/tango_nand.c
@@ -477,7 +477,7 @@ static u32 to_ticks(int kHz, int ps)
 }
 
 static int tango_set_timings(struct nand_chip *chip, int csline,
-			     const struct nand_data_interface *conf)
+			     const struct nand_interface_config *conf)
 {
 	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(conf);
 	struct tango_nfc *nfc = to_tango_nfc(chip->controller);
@@ -527,7 +527,7 @@ static int tango_attach_chip(struct nand_chip *chip)
 
 static const struct nand_controller_ops tango_controller_ops = {
 	.attach_chip = tango_attach_chip,
-	.setup_data_interface = tango_set_timings,
+	.setup_interface = tango_set_timings,
 };
 
 static int chip_init(struct device *dev, struct device_node *np)
diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c
index f9d046b2cd3b..6b6212ffa01c 100644
--- a/drivers/mtd/nand/raw/tegra_nand.c
+++ b/drivers/mtd/nand/raw/tegra_nand.c
@@ -813,8 +813,8 @@ static void tegra_nand_setup_timing(struct tegra_nand_controller *ctrl,
 	writel_relaxed(reg, ctrl->regs + TIMING_2);
 }
 
-static int tegra_nand_setup_data_interface(struct nand_chip *chip, int csline,
-					const struct nand_data_interface *conf)
+static int tegra_nand_setup_interface(struct nand_chip *chip, int csline,
+				      const struct nand_interface_config *conf)
 {
 	struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller);
 	const struct nand_sdr_timings *timings;
@@ -1053,7 +1053,7 @@ static int tegra_nand_attach_chip(struct nand_chip *chip)
 static const struct nand_controller_ops tegra_nand_controller_ops = {
 	.attach_chip = &tegra_nand_attach_chip,
 	.exec_op = tegra_nand_exec_op,
-	.setup_data_interface = tegra_nand_setup_data_interface,
+	.setup_interface = tegra_nand_setup_interface,
 };
 
 static int tegra_nand_chips_init(struct device *dev,
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 2804c13e5662..58fcc882a8df 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -492,22 +492,22 @@ struct nand_sdr_timings {
 };
 
 /**
- * enum nand_data_interface_type - NAND interface timing type
+ * enum nand_interface_type - NAND interface type
  * @NAND_SDR_IFACE:	Single Data Rate interface
  */
-enum nand_data_interface_type {
+enum nand_interface_type {
 	NAND_SDR_IFACE,
 };
 
 /**
- * struct nand_data_interface - NAND interface timing
+ * struct nand_interface_config - NAND interface timing
  * @type:	 type of the timing
  * @timings:	 The timing information
  * @timings.mode: Timing mode as defined in the specification
  * @timings.sdr: Use it when @type is %NAND_SDR_IFACE.
  */
-struct nand_data_interface {
-	enum nand_data_interface_type type;
+struct nand_interface_config {
+	enum nand_interface_type type;
 	struct nand_timings {
 		unsigned int mode;
 		union {
@@ -521,7 +521,7 @@ struct nand_data_interface {
  * @conf:	The data interface
  */
 static inline const struct nand_sdr_timings *
-nand_get_sdr_timings(const struct nand_data_interface *conf)
+nand_get_sdr_timings(const struct nand_interface_config *conf)
 {
 	if (conf->type != NAND_SDR_IFACE)
 		return ERR_PTR(-EINVAL);
@@ -944,11 +944,10 @@ static inline void nand_op_trace(const char *prefix,
  *		 This method replaces chip->legacy.cmdfunc(),
  *		 chip->legacy.{read,write}_{buf,byte,word}(),
  *		 chip->legacy.dev_ready() and chip->legacy.waifunc().
- * @setup_data_interface: setup the data interface and timing. If
- *			  chipnr is set to %NAND_DATA_IFACE_CHECK_ONLY this
- *			  means the configuration should not be applied but
- *			  only checked.
- *			  This hook is optional.
+ * @setup_interface: setup the data interface and timing. If chipnr is set to
+ *		     %NAND_DATA_IFACE_CHECK_ONLY this means the configuration
+ *		     should not be applied but only checked.
+ *		     This hook is optional.
  */
 struct nand_controller_ops {
 	int (*attach_chip)(struct nand_chip *chip);
@@ -956,8 +955,8 @@ struct nand_controller_ops {
 	int (*exec_op)(struct nand_chip *chip,
 		       const struct nand_operation *op,
 		       bool check_only);
-	int (*setup_data_interface)(struct nand_chip *chip, int chipnr,
-				    const struct nand_data_interface *conf);
+	int (*setup_interface)(struct nand_chip *chip, int chipnr,
+			       const struct nand_interface_config *conf);
 };
 
 /**
@@ -1071,7 +1070,7 @@ struct nand_legacy {
  * @id:			[INTERN] holds NAND ID
  * @parameters:		[INTERN] holds generic parameters under an easily
  *			readable form.
- * @data_interface:	[INTERN] NAND interface timing information
+ * @interface_config:	NAND interface configuration
  * @cur_cs:		currently selected target. -1 means no target selected,
  *			otherwise we should always have cur_cs >= 0 &&
  *			cur_cs < nanddev_ntargets(). NAND Controller drivers
@@ -1130,7 +1129,7 @@ struct nand_chip {
 	struct nand_id id;
 	struct nand_parameters parameters;
 
-	struct nand_data_interface data_interface;
+	struct nand_interface_config interface_config;
 
 	int cur_cs;
 

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 20/28] mtd: rawnand: Hide the chip->data_interface indirection
  2020-05-27  7:36     ` Miquel Raynal
@ 2020-05-27  8:14       ` Boris Brezillon
  0 siblings, 0 replies; 62+ messages in thread
From: Boris Brezillon @ 2020-05-27  8:14 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, Vignesh Raghavendra,
	Tudor Ambarus

On Wed, 27 May 2020 09:36:03 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Hi Boris,
> 
> Boris Brezillon <boris.brezillon@collabora.com> wrote on Tue, 26 May
> 2020 23:36:20 +0200:
> 
> > On Tue, 26 May 2020 21:17:17 +0200
> > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >   
> > > As a preparation for allocating the data interface structure
> > > dynamically (and rename it), let's avoid calling it directly.
> > > 
> > > Instead, we operate a rename on an existing helper to reuse that name
> > > for another helper:
> > > * s/nand_get_sdr_timings/nand_extract_sdr_timings/    
> > >   -> this helper just extracts timings from a given data interface    
> > 
> > Hm, I'm not entirely happy with that name. In my mind extract means
> > that you had to do some transformation to get the data, which is not
> > the case here. How about nand_data_interface_get_sdr_timings()? 
> >   
> > > * nand_get_sdr_timings()    
> > >   -> this helper retrieves the in use timings from a nand_chip structure    
> > 
> > Do we really need that one? Can we do that in 2 steps instead?  
> 
> Yes I can do that in two steps, I didn't think it was needed but no pb.
> 
> > 
> > conf = nand_get_data_interface_config(chip);
> > sdr = nand_data_interface_get_sdr_timings(conf);  
> 
> I find the names too long. Do you think I can stick to
> nand_get_sdr_timings(conf) and nand_get_data_interface(chip)? These
> helpers are very often used at the start of a function and would
> definitely break systematically the 80 chars limit otherwise...

Could be nand_get_interface_config() (see my rename patch) and
nand_get_sdr_timings(), yes.

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 28/28] mtd: rawnand: Allocate the best data interface structure dynamically
  2020-05-27  7:57     ` Miquel Raynal
@ 2020-05-27  8:35       ` Boris Brezillon
  2020-05-27  8:49         ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Boris Brezillon @ 2020-05-27  8:35 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Wed, 27 May 2020 09:57:32 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Maybe I misunderstood your request, you were saying that allocating a
> "best data interface object" would be good, so I interpreted it as:
> rename it, and allocated it dynamically. I'm fine keeping
> data_interface and just declaring it as a pointer.

Correct, renaming it into best_iface_cfg is probably good, but then,
maybe we should have a current_iface_cfg, so the core/drivers always
have a pointer to the currently applied config (which after a reset
can be the reset config for a short period of time).

> 
> Anyway, I like talking about the "interface" rather than the "interface
> configuration" which is implied in my mind, I saw you were asking to
> add "configuration" sometimes, do you have something in mind that I
> don't?

Well, to me a configuration is something that you can manipulate without
necessarily implying it's the current state the HW operates in. For a
configuration to be active, you have to apply it. And that's pretty
much what the nand_data_interface describes, a configuration, that can
be retrieved, tweaked, and finally applied. Hence the renaming I
suggest.

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 28/28] mtd: rawnand: Allocate the best data interface structure dynamically
  2020-05-27  8:35       ` Boris Brezillon
@ 2020-05-27  8:49         ` Miquel Raynal
  2020-05-27  8:57           ` Boris Brezillon
  0 siblings, 1 reply; 62+ messages in thread
From: Miquel Raynal @ 2020-05-27  8:49 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus


Boris Brezillon <boris.brezillon@collabora.com> wrote on Wed, 27 May
2020 10:35:19 +0200:

> On Wed, 27 May 2020 09:57:32 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > Maybe I misunderstood your request, you were saying that allocating a
> > "best data interface object" would be good, so I interpreted it as:
> > rename it, and allocated it dynamically. I'm fine keeping
> > data_interface and just declaring it as a pointer.  
> 
> Correct, renaming it into best_iface_cfg is probably good, but then,
> maybe we should have a current_iface_cfg, so the core/drivers always
> have a pointer to the currently applied config (which after a reset
> can be the reset config for a short period of time).

That's why I created an indirection on chip->data_interface.
nand_get_interface_cfg() is here for that -> the drivers do not care
about which one is applied. I don't think we need more than I already
proposed:
-> there is one default reset configuration object that can be used by
   anyone
-> there is a best configuration

If the best configuration has been derived, then it will be used.
Otherwise, the helper will fallback to the default slower one, and this
covers all the cases :)

> 
> > 
> > Anyway, I like talking about the "interface" rather than the "interface
> > configuration" which is implied in my mind, I saw you were asking to
> > add "configuration" sometimes, do you have something in mind that I
> > don't?  
> 
> Well, to me a configuration is something that you can manipulate without
> necessarily implying it's the current state the HW operates in. For a
> configuration to be active, you have to apply it. And that's pretty
> much what the nand_data_interface describes, a configuration, that can
> be retrieved, tweaked, and finally applied. Hence the renaming I
> suggest.

Fine.

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 28/28] mtd: rawnand: Allocate the best data interface structure dynamically
  2020-05-27  8:49         ` Miquel Raynal
@ 2020-05-27  8:57           ` Boris Brezillon
  2020-05-27  9:34             ` Miquel Raynal
  0 siblings, 1 reply; 62+ messages in thread
From: Boris Brezillon @ 2020-05-27  8:57 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus

On Wed, 27 May 2020 10:49:11 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Boris Brezillon <boris.brezillon@collabora.com> wrote on Wed, 27 May
> 2020 10:35:19 +0200:
> 
> > On Wed, 27 May 2020 09:57:32 +0200
> > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >   
> > > Maybe I misunderstood your request, you were saying that allocating a
> > > "best data interface object" would be good, so I interpreted it as:
> > > rename it, and allocated it dynamically. I'm fine keeping
> > > data_interface and just declaring it as a pointer.    
> > 
> > Correct, renaming it into best_iface_cfg is probably good, but then,
> > maybe we should have a current_iface_cfg, so the core/drivers always
> > have a pointer to the currently applied config (which after a reset
> > can be the reset config for a short period of time).  
> 
> That's why I created an indirection on chip->data_interface.
> nand_get_interface_cfg() is here for that -> the drivers do not care
> about which one is applied. I don't think we need more than I already
> proposed:
> -> there is one default reset configuration object that can be used by  
>    anyone
> -> there is a best configuration  
> 
> If the best configuration has been derived, then it will be used.
> Otherwise, the helper will fallback to the default slower one, and this
> covers all the cases :)

My point is, during a reset, you want to use the reset config, but
nand_get_interface_cfg() will always return the best config, which is
not the one currently applied until you actually return back to the
best interface config. That means that any driver using
nand_get_interface_cfg() in the exec_op() path will get a wrong config.
So I'd suggest either not exposing nand_get_interface_cfg() to
controller drivers (which would be a valid approach) or making sure it
always return the currently applied timings.

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH v5 28/28] mtd: rawnand: Allocate the best data interface structure dynamically
  2020-05-27  8:57           ` Boris Brezillon
@ 2020-05-27  9:34             ` Miquel Raynal
  0 siblings, 0 replies; 62+ messages in thread
From: Miquel Raynal @ 2020-05-27  9:34 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Richard Weinberger, linux-mtd,
	Vignesh Raghavendra, Tudor Ambarus


Boris Brezillon <boris.brezillon@collabora.com> wrote on Wed, 27 May
2020 10:57:49 +0200:

> On Wed, 27 May 2020 10:49:11 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > Boris Brezillon <boris.brezillon@collabora.com> wrote on Wed, 27 May
> > 2020 10:35:19 +0200:
> >   
> > > On Wed, 27 May 2020 09:57:32 +0200
> > > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> > >     
> > > > Maybe I misunderstood your request, you were saying that allocating a
> > > > "best data interface object" would be good, so I interpreted it as:
> > > > rename it, and allocated it dynamically. I'm fine keeping
> > > > data_interface and just declaring it as a pointer.      
> > > 
> > > Correct, renaming it into best_iface_cfg is probably good, but then,
> > > maybe we should have a current_iface_cfg, so the core/drivers always
> > > have a pointer to the currently applied config (which after a reset
> > > can be the reset config for a short period of time).    
> > 
> > That's why I created an indirection on chip->data_interface.
> > nand_get_interface_cfg() is here for that -> the drivers do not care
> > about which one is applied. I don't think we need more than I already
> > proposed:  
> > -> there is one default reset configuration object that can be used by    
> >    anyone  
> > -> there is a best configuration    
> > 
> > If the best configuration has been derived, then it will be used.
> > Otherwise, the helper will fallback to the default slower one, and this
> > covers all the cases :)  
> 
> My point is, during a reset, you want to use the reset config, but
> nand_get_interface_cfg() will always return the best config, which is
> not the one currently applied until you actually return back to the
> best interface config. That means that any driver using
> nand_get_interface_cfg() in the exec_op() path will get a wrong config.
> So I'd suggest either not exposing nand_get_interface_cfg() to
> controller drivers (which would be a valid approach) or making sure it
> always return the currently applied timings.

You are right.

STM32_FMC and Marvell controllers access these timings.

I can have a "interface_cfg" and a "best_interface_cfg". Both being
just pointers. nand_get_interface_cfg would return the interface_cfg
pointer which would always be set (either to the default basic
configuration or the quick one). 

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

end of thread, other threads:[~2020-05-27  9:35 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-26 19:16 [PATCH v5 00/28] Allow vendor drivers to propose their own timings Miquel Raynal
2020-05-26 19:16 ` [PATCH v5 01/28] mtd: rawnand: Use unsigned types for nand_chip unsigned values Miquel Raynal
2020-05-26 19:16 ` [PATCH v5 02/28] mtd: rawnand: Only use u8 instead of uint8_t in nand_chip structure Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 03/28] mtd: rawnand: Create a nand_chip operations structure Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 04/28] mtd: rawnand: Rename the manufacturer structure Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 05/28] mtd: rawnand: Declare the nand_manufacturer structure out of nand_chip Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 06/28] mtd: rawnand: Reorganize the nand_chip structure Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 07/28] mtd: rawnand: Compare the actual timing values Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 08/28] mtd: rawnand: Use the data interface mode entry when relevant Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 09/28] mtd: rawnand: Rename nand_has_setup_data_interface() Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 10/28] mtd: rawnand: Fix nand_setup_data_interface() description Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 11/28] mtd: rawnand: Rename nand_init_data_interface() Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 12/28] mtd: rawnand: timings: Update onfi_fill_data_interface() kernel doc Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 13/28] mtd: rawnand: timings: Provide onfi_fill_data_interface() with a data interface Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 14/28] mtd: rawnand: timings: Add a helper to find the closest ONFI mode Miquel Raynal
2020-05-26 21:42   ` Boris Brezillon
2020-05-27  7:42     ` Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 15/28] mtd: rawnand: timings: Avoid redefining tR_max and tCCS_min Miquel Raynal
2020-05-26 20:33   ` Boris Brezillon
2020-05-26 19:17 ` [PATCH v5 16/28] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max Miquel Raynal
2020-05-26 20:32   ` Boris Brezillon
2020-05-26 21:25   ` Boris Brezillon
2020-05-27  7:17     ` Miquel Raynal
2020-05-27  7:22       ` Miquel Raynal
2020-05-27  7:28         ` Boris Brezillon
2020-05-26 19:17 ` [PATCH v5 17/28] mtd: rawnand: Define a unique reset data interface Miquel Raynal
2020-05-26 21:23   ` Boris Brezillon
2020-05-27  7:20     ` Miquel Raynal
2020-05-27  8:10       ` Boris Brezillon
2020-05-26 19:17 ` [PATCH v5 18/28] mtd: rawnand: marvell: Use a helper to access the timings Miquel Raynal
2020-05-26 21:26   ` Boris Brezillon
2020-05-26 19:17 ` [PATCH v5 19/28] mtd: rawnand: legacy: " Miquel Raynal
2020-05-26 21:28   ` Boris Brezillon
2020-05-26 19:17 ` [PATCH v5 20/28] mtd: rawnand: Hide the chip->data_interface indirection Miquel Raynal
2020-05-26 21:36   ` Boris Brezillon
2020-05-27  7:36     ` Miquel Raynal
2020-05-27  8:14       ` Boris Brezillon
2020-05-26 19:17 ` [PATCH v5 21/28] mtd: rawnand: Introduce nand_choose_best_sdr_timings() Miquel Raynal
2020-05-26 21:50   ` Boris Brezillon
2020-05-27  7:45     ` Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 22/28] mtd: rawnand: Add the ->choose_data_interface() hook Miquel Raynal
2020-05-26 21:52   ` Boris Brezillon
2020-05-27  7:46     ` Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 23/28] mtd: rawnand: toshiba: Implement ->choose_data_interface() for TC58TEG5DCLTA00 Miquel Raynal
2020-05-26 21:54   ` Boris Brezillon
2020-05-26 19:17 ` [PATCH v5 24/28] mtd: rawnand: toshiba: Implement ->choose_data_interface() for TC58NVG0S3E Miquel Raynal
2020-05-26 22:02   ` Boris Brezillon
2020-05-27  7:47     ` Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 25/28] mtd: rawnand: hynix: Implement ->choose_data_interface() for H27UCG8T2ATR-BC Miquel Raynal
2020-05-26 22:06   ` Boris Brezillon
2020-05-27  7:50     ` Miquel Raynal
2020-05-26 19:17 ` [PATCH v5 26/28] mtd: rawnand: toshiba: Choose the data interface for TH58NVG2S3HBAI4 Miquel Raynal
2020-05-26 22:10   ` Boris Brezillon
2020-05-26 19:17 ` [PATCH v5 27/28] mtd: rawnand: Get rid of the default ONFI timing mode Miquel Raynal
2020-05-26 22:13   ` Boris Brezillon
2020-05-26 19:17 ` [PATCH v5 28/28] mtd: rawnand: Allocate the best data interface structure dynamically Miquel Raynal
2020-05-26 22:28   ` Boris Brezillon
2020-05-27  7:57     ` Miquel Raynal
2020-05-27  8:35       ` Boris Brezillon
2020-05-27  8:49         ` Miquel Raynal
2020-05-27  8:57           ` Boris Brezillon
2020-05-27  9:34             ` Miquel Raynal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).