All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 00/30] Allow vendor drivers to propose their own timings
@ 2020-05-28 23:15 Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 01/30] mtd: rawnand: Use unsigned types for nand_chip unsigned values Miquel Raynal
                   ` (29 more replies)
  0 siblings, 30 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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. While at it, I did
some cleanup and prepared the introduction of NV-DDR timings.

Cheers,
Miquèl

Changes in v6:
* Collected R-by tags.
* Inserted a patch renaming massively the "data interface" name into
  "interface configuration". Followed this naming for the rest of the
  series, in particular for the new hooks.
* Re-added a comment about the specific tCCS, tR, tBERS and tPROG
  timings.
* Inverted the conditions in onfi_find_closest_sdr_mode() as advised.
* Created a helper to retrieve the reset interface configuration.
* Dropped nand_extract_sdr_timings() and kept nand_get_sdr_timings().
* Created nand_get_interface_config() instead, to retrieve an
  interface configuration provided a nand_chip object.
* Changed the scope of a variable.
* Turned onfi_fill_interface_config() into a void helper.
* Fixed typos.
* Used strncmp() to compare NAND chip model names.
* Prevented applying timing mode 0 twice.
* Created a ->current_interface_config entry in nand_chip, always
  pointing to the right interface configuration.
* Renamed the other entry ->best_interface_config.

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.


Boris Brezillon (1):
  mtd: rawnand: s/data_interface/interface_config/

Miquel Raynal (28):
  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_iface()
  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: timings: Make onfi_fill_interface_config() a void helper
  mtd: rawnand: Define a unique reset interface configuration
  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->interface_config indirection
  mtd: rawnand: Introduce nand_choose_best_sdr_timings()
  mtd: rawnand: Add the ->choose_interface() hook
  mtd: rawnand: toshiba: Implement ->choose_interface() for
    TC58TEG5DCLTA00
  mtd: rawnand: toshiba: Implement ->choose_interface() for TC58NVG0S3E
  mtd: rawnand: hynix: Implement ->choose_interface() for
    H27UCG8T2ATR-BC
  mtd: rawnand: Get rid of the default ONFI timing mode
  mtd: rawnand: Allocate the best interface configuration dynamically

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

 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              |  22 +-
 drivers/mtd/nand/raw/marvell_nand.c           |  20 +-
 drivers/mtd/nand/raw/meson_nand.c             |  14 +-
 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              | 287 ++++++++++--------
 drivers/mtd/nand/raw/nand_hynix.c             |  15 +-
 drivers/mtd/nand/raw/nand_ids.c               |  24 +-
 drivers/mtd/nand/raw/nand_legacy.c            |   7 +-
 drivers/mtd/nand/raw/nand_macronix.c          |  10 +-
 drivers/mtd/nand/raw/nand_micron.c            |   2 +-
 drivers/mtd/nand/raw/nand_timings.c           | 117 +++++--
 drivers/mtd/nand/raw/nand_toshiba.c           |  68 ++++-
 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                   | 270 ++++++++--------
 27 files changed, 587 insertions(+), 401 deletions(-)

-- 
2.20.1


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

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

* [PATCH v6 01/30] mtd: rawnand: Use unsigned types for nand_chip unsigned values
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 02/30] mtd: rawnand: Only use u8 instead of uint8_t in nand_chip structure Miquel Raynal
                   ` (28 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 65b1c1c18b41..830f2d08937f 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] 44+ messages in thread

* [PATCH v6 02/30] mtd: rawnand: Only use u8 instead of uint8_t in nand_chip structure
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 01/30] mtd: rawnand: Use unsigned types for nand_chip unsigned values Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 03/30] mtd: rawnand: Create a nand_chip operations structure Miquel Raynal
                   ` (27 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 830f2d08937f..cea137778224 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] 44+ messages in thread

* [PATCH v6 03/30] mtd: rawnand: Create a nand_chip operations structure
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 01/30] mtd: rawnand: Use unsigned types for nand_chip unsigned values Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 02/30] mtd: rawnand: Only use u8 instead of uint8_t in nand_chip structure Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 04/30] mtd: rawnand: Rename the manufacturer structure Miquel Raynal
                   ` (26 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 45124dbb1835..d9cb71e7c0ed 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -3215,10 +3215,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)
@@ -4462,8 +4462,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);
@@ -4481,8 +4481,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",
@@ -4511,10 +4511,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);
 }
 
 /**
@@ -4527,10 +4527,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 cea137778224..7f9be95ca8dc 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] 44+ messages in thread

* [PATCH v6 04/30] mtd: rawnand: Rename the manufacturer structure
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (2 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 03/30] mtd: rawnand: Create a nand_chip operations structure Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 05/30] mtd: rawnand: Declare the nand_manufacturer structure out of nand_chip Miquel Raynal
                   ` (25 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 d9cb71e7c0ed..534ee75d0f2b 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4810,9 +4810,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";
 }
 
 /*
@@ -4820,7 +4820,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;
@@ -4877,8 +4877,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;
@@ -4957,7 +4957,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);
@@ -4992,7 +4992,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 7f9be95ca8dc..860d3c1020ef 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] 44+ messages in thread

* [PATCH v6 05/30] mtd: rawnand: Declare the nand_manufacturer structure out of nand_chip
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (3 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 04/30] mtd: rawnand: Rename the manufacturer structure Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 06/30] mtd: rawnand: Reorganize the nand_chip structure Miquel Raynal
                   ` (24 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 860d3c1020ef..a3dfa36a9fd5 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] 44+ messages in thread

* [PATCH v6 06/30] mtd: rawnand: Reorganize the nand_chip structure
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (4 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 05/30] mtd: rawnand: Declare the nand_manufacturer structure out of nand_chip Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 07/30] mtd: rawnand: Compare the actual timing values Miquel Raynal
                   ` (23 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 a3dfa36a9fd5..544ec8736793 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] 44+ messages in thread

* [PATCH v6 07/30] mtd: rawnand: Compare the actual timing values
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (5 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 06/30] mtd: rawnand: Reorganize the nand_chip structure Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 08/30] mtd: rawnand: Use the data interface mode entry when relevant Miquel Raynal
                   ` (22 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 534ee75d0f2b..3526c2a50bbe 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] 44+ messages in thread

* [PATCH v6 08/30] mtd: rawnand: Use the data interface mode entry when relevant
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (6 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 07/30] mtd: rawnand: Compare the actual timing values Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 09/30] mtd: rawnand: Rename nand_has_setup_data_iface() Miquel Raynal
                   ` (21 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 3526c2a50bbe..6e06ccf61aeb 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] 44+ messages in thread

* [PATCH v6 09/30] mtd: rawnand: Rename nand_has_setup_data_iface()
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (7 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 08/30] mtd: rawnand: Use the data interface mode entry when relevant Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 10/30] mtd: rawnand: Fix nand_setup_data_interface() description Miquel Raynal
                   ` (20 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, Miquel Raynal

This is really a NAND controller hook so call it
nand_controller_can_setup_data_iface(), 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..a5e2cec7e301 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_can_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 6e06ccf61aeb..2a477ce81165 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_can_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_can_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_can_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..848403dcae03 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_can_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] 44+ messages in thread

* [PATCH v6 10/30] mtd: rawnand: Fix nand_setup_data_interface() description
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (8 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 09/30] mtd: rawnand: Rename nand_has_setup_data_iface() Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 11/30] mtd: rawnand: Rename nand_init_data_interface() Miquel Raynal
                   ` (19 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 2a477ce81165..01e788e0d010 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] 44+ messages in thread

* [PATCH v6 11/30] mtd: rawnand: Rename nand_init_data_interface()
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (9 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 10/30] mtd: rawnand: Fix nand_setup_data_interface() description Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 12/30] mtd: rawnand: timings: Update onfi_fill_data_interface() kernel doc Miquel Raynal
                   ` (18 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 01e788e0d010..1d9cf02d164b 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;
 
@@ -5969,8 +5969,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] 44+ messages in thread

* [PATCH v6 12/30] mtd: rawnand: timings: Update onfi_fill_data_interface() kernel doc
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (10 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 11/30] mtd: rawnand: Rename nand_init_data_interface() Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 13/30] mtd: rawnand: timings: Provide onfi_fill_data_interface() with a data interface Miquel Raynal
                   ` (17 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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] 44+ messages in thread

* [PATCH v6 13/30] mtd: rawnand: timings: Provide onfi_fill_data_interface() with a data interface
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (11 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 12/30] mtd: rawnand: timings: Update onfi_fill_data_interface() kernel doc Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-29  7:16   ` Boris Brezillon
  2020-05-28 23:15 ` [PATCH v6 14/30] mtd: rawnand: timings: Add a helper to find the closest ONFI mode Miquel Raynal
                   ` (16 subsequent siblings)
  29 siblings, 1 reply; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 a5e2cec7e301..0f74509abc4c 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 1d9cf02d164b..b4de85794e07 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;
 
@@ -5182,7 +5183,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] 44+ messages in thread

* [PATCH v6 14/30] mtd: rawnand: timings: Add a helper to find the closest ONFI mode
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (12 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 13/30] mtd: rawnand: timings: Provide onfi_fill_data_interface() with a data interface Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 15/30] mtd: rawnand: timings: Avoid redefining tR_max and tCCS_min Miquel Raynal
                   ` (15 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/raw/internals.h    |  2 ++
 drivers/mtd/nand/raw/nand_timings.c | 47 +++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index 0f74509abc4c..bcc9fff03354 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..71aed21a7fc6 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -273,6 +273,53 @@ 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)
+			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] 44+ messages in thread

* [PATCH v6 15/30] mtd: rawnand: timings: Avoid redefining tR_max and tCCS_min
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (13 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 14/30] mtd: rawnand: timings: Add a helper to find the closest ONFI mode Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-28 23:15 ` [PATCH v6 16/30] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max Miquel Raynal
                   ` (14 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, Miquel Raynal

These two values are already hardcoded in the default ONFI timing
structure, no need to redefine them here. Plus, we want to be able to
reference timing mode 0 easily and reliably, without extra
computation, so we get rid of the extra assignations.

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 71aed21a7fc6..728a2dee1eed 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -369,9 +369,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] 44+ messages in thread

* [PATCH v6 16/30] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (14 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 15/30] mtd: rawnand: timings: Avoid redefining tR_max and tCCS_min Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-29  7:21   ` Boris Brezillon
  2020-05-28 23:15 ` [PATCH v6 17/30] mtd: rawnand: s/data_interface/interface_config/ Miquel Raynal
                   ` (13 subsequent siblings)
  29 siblings, 1 reply; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 | 31 ++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
index 728a2dee1eed..9ff4b121ab1e 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -12,6 +12,13 @@
 
 #define ONFI_DYN_TIMING_MAX U16_MAX
 
+/*
+ * 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.
+ *
+ * These four values are tweaked to be more accurate in the case of ONFI chips.
+ */
 static const struct nand_data_interface onfi_sdr_timings[] = {
 	/* Mode 0 */
 	{
@@ -20,6 +27,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 +72,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 +117,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 +162,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 +207,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 +252,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,
@@ -357,18 +376,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] 44+ messages in thread

* [PATCH v6 17/30] mtd: rawnand: s/data_interface/interface_config/
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (15 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 16/30] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max Miquel Raynal
@ 2020-05-28 23:15 ` Miquel Raynal
  2020-05-29  7:44   ` Boris Brezillon
  2020-05-29  7:47   ` Boris Brezillon
  2020-05-28 23:16 ` [PATCH v6 18/30] mtd: rawnand: timings: Make onfi_fill_interface_config() a void helper Miquel Raynal
                   ` (12 subsequent siblings)
  29 siblings, 2 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:15 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, Miquel Raynal

From: Boris Brezillon <boris.brezillon@collabora.com>

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>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.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              | 12 +--
 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              | 99 ++++++++++---------
 drivers/mtd/nand/raw/nand_legacy.c            |  4 +-
 drivers/mtd/nand/raw/nand_timings.c           | 17 ++--
 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, 159 insertions(+), 159 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 bcc9fff03354..93386bdfbad6 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -84,10 +84,10 @@ 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,
-			     struct nand_data_interface *iface,
-			     enum nand_data_interface_type type,
-			     int timing_mode);
+int onfi_fill_interface_config(struct nand_chip *chip,
+			       struct nand_interface_config *iface,
+			       enum nand_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);
@@ -133,10 +133,10 @@ static inline int nand_exec_op(struct nand_chip *chip,
 	return chip->controller->ops->exec_op(chip, op, false);
 }
 
-static inline bool nand_controller_can_setup_data_iface(struct nand_chip *chip)
+static inline bool nand_controller_can_setup_interface(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 b4de85794e07..de596c06c9c2 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 - Reset data interface and timings
  * @chip: The NAND chip
  * @chipnr: Internal die id
  *
@@ -906,11 +906,12 @@ 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(struct nand_chip *chip, int chipnr)
 {
+	const struct nand_controller_ops *ops = chip->controller->ops;
 	int ret;
 
-	if (!nand_controller_can_setup_data_iface(chip))
+	if (!nand_controller_can_setup_interface(chip))
 		return 0;
 
 	/*
@@ -927,9 +928,9 @@ 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);
+	onfi_fill_interface_config(chip, &chip->interface_config,
+				   NAND_SDR_IFACE, 0);
+	ret = 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 +938,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
  *
@@ -946,13 +947,13 @@ 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 mode = chip->data_interface.timings.mode;
+	u8 mode = chip->interface_config.timings.mode;
 	u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { mode, };
 	int ret;
 
-	if (!nand_controller_can_setup_data_iface(chip))
+	if (!nand_controller_can_setup_interface(chip))
 		return 0;
 
 	/* Change the mode on the chip side (if supported by the NAND chip) */
@@ -966,8 +967,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;
 
@@ -996,7 +997,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(chip, chipnr);
 	nand_select_target(chip, chipnr);
 	nand_reset_op(chip);
 	nand_deselect_target(chip);
@@ -1005,7 +1006,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
 }
 
 /**
- * nand_choose_data_interface - find the best data interface and timings
+ * nand_choose_interface - find the best data interface and timings
  * @chip: The NAND chip
  *
  * Find the best data interface and NAND timings supported by the chip
@@ -1013,16 +1014,16 @@ 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_ 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)
+static int nand_choose_interface(struct nand_chip *chip)
 {
 	int modes, mode, ret;
 
-	if (!nand_controller_can_setup_data_iface(chip))
+	if (!nand_controller_can_setup_interface(chip))
 		return 0;
 
 	/*
@@ -1040,8 +1041,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, &chip->data_interface,
-					       NAND_SDR_IFACE, mode);
+		ret = onfi_fill_interface_config(chip, &chip->interface_config,
+						 NAND_SDR_IFACE, mode);
 		if (ret)
 			continue;
 
@@ -1049,9 +1050,9 @@ static int nand_choose_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;
@@ -1121,7 +1122,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),
@@ -1163,7 +1164,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),
@@ -1260,7 +1261,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)),
@@ -1315,7 +1316,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),
@@ -1391,7 +1392,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[] = {
 		/*
@@ -1514,7 +1515,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)),
@@ -1621,7 +1622,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),
@@ -1676,7 +1677,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)),
@@ -1715,7 +1716,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)),
@@ -1784,7 +1785,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),
@@ -1843,7 +1844,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)),
@@ -1890,7 +1891,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)),
@@ -1947,7 +1948,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),
@@ -2477,17 +2478,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
- * apply back the previous timings.
+ * nand_reset_interface 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_intf_config = chip->interface_config;
 	int ret;
 
-	ret = nand_reset_data_interface(chip, chipnr);
+	ret = nand_reset_interface(chip, chipnr);
 	if (ret)
 		return ret;
 
@@ -2503,18 +2504,18 @@ 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() 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 (!memcmp(&chip->data_interface, &saved_data_intf,
-		    sizeof(saved_data_intf)))
+	if (!memcmp(&chip->interface_config, &saved_intf_config,
+		    sizeof(saved_intf_config)))
 		return 0;
 
-	chip->data_interface = saved_data_intf;
-	ret = nand_setup_data_interface(chip, chipnr);
+	chip->interface_config = saved_intf_config;
+	ret = nand_setup_interface(chip, chipnr);
 	if (ret)
 		return ret;
 
@@ -3226,7 +3227,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));
 }
 
@@ -5183,7 +5184,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, &chip->data_interface, NAND_SDR_IFACE, 0);
+	onfi_fill_interface_config(chip, &chip->interface_config, NAND_SDR_IFACE, 0);
 
 	ret = nand_dt_init(chip);
 	if (ret)
@@ -5971,13 +5972,13 @@ static int nand_scan_tail(struct nand_chip *chip)
 		mtd->bitflip_threshold = DIV_ROUND_UP(mtd->ecc_strength * 3, 4);
 
 	/* Find the fastest data interface for this chip */
-	ret = nand_choose_data_interface(chip);
+	ret = nand_choose_interface(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 848403dcae03..60798eb29ca9 100644
--- a/drivers/mtd/nand/raw/nand_legacy.c
+++ b/drivers/mtd/nand/raw/nand_legacy.c
@@ -365,8 +365,8 @@ 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_controller_can_setup_data_iface(chip))
-		ndelay(chip->data_interface.timings.sdr.tCCS_min / 1000);
+	if (nand_controller_can_setup_interface(chip))
+		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 9ff4b121ab1e..997a1dd929de 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -19,7 +19,7 @@
  *
  * These four values are tweaked to be more accurate in the case of ONFI chips.
  */
-static const struct nand_data_interface onfi_sdr_timings[] = {
+static const struct nand_interface_config onfi_sdr_timings[] = {
 	/* Mode 0 */
 	{
 		.type = NAND_SDR_IFACE,
@@ -340,16 +340,17 @@ onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings)
 }
 
 /**
- * onfi_fill_data_interface - Initialize a data interface from a given ONFI mode
+ * onfi_fill_interface_config - Initialize an interface config from a given
+ *                              ONFI mode
  * @chip: The NAND chip
- * @iface: The data interface to fill
- * @type: The data interface type
+ * @iface: The interface configuration to fill
+ * @type: The 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)
+int onfi_fill_interface_config(struct nand_chip *chip,
+			       struct nand_interface_config *iface,
+			       enum nand_interface_type type,
+			       int timing_mode)
 {
 	struct onfi_params *onfi = chip->parameters.onfi;
 
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 544ec8736793..c2fcac38bcc2 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);
 };
 
 /**
@@ -1070,7 +1069,7 @@ struct nand_manufacturer {
  * @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
+ * @interface_config: 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
@@ -1118,7 +1117,7 @@ struct nand_chip {
 
 	/* Data interface */
 	int onfi_timing_mode_default;
-	struct nand_data_interface data_interface;
+	struct nand_interface_config interface_config;
 
 	/* Bad block information */
 	unsigned int bbt_erase_shift;
-- 
2.20.1


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

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

* [PATCH v6 18/30] mtd: rawnand: timings: Make onfi_fill_interface_config() a void helper
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (16 preceding siblings ...)
  2020-05-28 23:15 ` [PATCH v6 17/30] mtd: rawnand: s/data_interface/interface_config/ Miquel Raynal
@ 2020-05-28 23:16 ` Miquel Raynal
  2020-05-29  7:27   ` Boris Brezillon
  2020-05-28 23:16 ` [PATCH v6 19/30] mtd: rawnand: Define a unique reset interface configuration Miquel Raynal
                   ` (11 subsequent siblings)
  29 siblings, 1 reply; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, Miquel Raynal

Warn the user if the parameters are wrong but basically it would mean
there is a serious issue in the NAND core. So no need to ever check
its output, let's make this helper return void.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/internals.h    |  8 ++++----
 drivers/mtd/nand/raw/nand_base.c    |  6 ++----
 drivers/mtd/nand/raw/nand_timings.c | 19 +++++++++----------
 3 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index 93386bdfbad6..11415b054d2e 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -84,10 +84,10 @@ 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_interface_config(struct nand_chip *chip,
-			       struct nand_interface_config *iface,
-			       enum nand_interface_type type,
-			       int timing_mode);
+void onfi_fill_interface_config(struct nand_chip *chip,
+				struct nand_interface_config *iface,
+				enum nand_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);
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index de596c06c9c2..07a7d918b462 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -1041,10 +1041,8 @@ static int nand_choose_interface(struct nand_chip *chip)
 	}
 
 	for (mode = fls(modes) - 1; mode >= 0; mode--) {
-		ret = onfi_fill_interface_config(chip, &chip->interface_config,
-						 NAND_SDR_IFACE, mode);
-		if (ret)
-			continue;
+		onfi_fill_interface_config(chip, &chip->interface_config,
+					   NAND_SDR_IFACE, mode);
 
 		/*
 		 * Pass NAND_DATA_IFACE_CHECK_ONLY to only check if the
diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
index 997a1dd929de..6c12cd52323d 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -347,18 +347,19 @@ onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings)
  * @type: The interface type
  * @timing_mode: The ONFI timing mode
  */
-int onfi_fill_interface_config(struct nand_chip *chip,
-			       struct nand_interface_config *iface,
-			       enum nand_interface_type type,
-			       int timing_mode)
+void onfi_fill_interface_config(struct nand_chip *chip,
+				struct nand_interface_config *iface,
+				enum nand_interface_type type,
+				int timing_mode)
 {
 	struct onfi_params *onfi = chip->parameters.onfi;
 
-	if (type != NAND_SDR_IFACE)
-		return -EINVAL;
+	if (WARN_ON(type != NAND_SDR_IFACE))
+		return;
 
-	if (timing_mode < 0 || timing_mode >= ARRAY_SIZE(onfi_sdr_timings))
-		return -EINVAL;
+	if (WARN_ON(timing_mode < 0 ||
+		    timing_mode >= ARRAY_SIZE(onfi_sdr_timings)))
+		return;
 
 	*iface = onfi_sdr_timings[timing_mode];
 
@@ -378,6 +379,4 @@ int onfi_fill_interface_config(struct nand_chip *chip,
 		/* nanoseconds -> picoseconds */
 		timings->tCCS_min = 1000UL * onfi->tCCS;
 	}
-
-	return 0;
 }
-- 
2.20.1


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

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

* [PATCH v6 19/30] mtd: rawnand: Define a unique reset interface configuration
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (17 preceding siblings ...)
  2020-05-28 23:16 ` [PATCH v6 18/30] mtd: rawnand: timings: Make onfi_fill_interface_config() a void helper Miquel Raynal
@ 2020-05-28 23:16 ` Miquel Raynal
  2020-05-29  7:32   ` Boris Brezillon
  2020-05-28 23:16 ` [PATCH v6 20/30] mtd: rawnand: marvell: Use a helper to access the timings Miquel Raynal
                   ` (10 subsequent siblings)
  29 siblings, 1 reply; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, Miquel Raynal

All NAND chips will always use the same interface configuration for
reset and at startup: SDR mode 0. Instead of copying around the
interface configuration, let's just define a helper to retrieve the
reset interface configuration object.

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

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 07a7d918b462..4a72ec221262 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -928,9 +928,7 @@ static int nand_reset_interface(struct nand_chip *chip, int chipnr)
 	 * timings to timing mode 0.
 	 */
 
-	onfi_fill_interface_config(chip, &chip->interface_config,
-				   NAND_SDR_IFACE, 0);
-	ret = ops->setup_interface(chip, chipnr, &chip->interface_config);
+	ret = ops->setup_interface(chip, chipnr, nand_get_reset_interface());
 	if (ret)
 		pr_err("Failed to configure data interface to SDR timing mode 0\n");
 
@@ -2483,7 +2481,6 @@ EXPORT_SYMBOL_GPL(nand_subop_get_data_len);
  */
 int nand_reset(struct nand_chip *chip, int chipnr)
 {
-	struct nand_interface_config saved_intf_config = chip->interface_config;
 	int ret;
 
 	ret = nand_reset_interface(chip, chipnr);
@@ -2508,11 +2505,10 @@ int nand_reset(struct nand_chip *chip, int chipnr)
 	 * nand_setup_interface() uses ->set/get_features() which would
 	 * fail anyway as the parameter page is not available yet.
 	 */
-	if (!memcmp(&chip->interface_config, &saved_intf_config,
-		    sizeof(saved_intf_config)))
+	if (!memcmp(&chip->interface_config, nand_get_reset_interface(),
+		    sizeof(chip->interface_config)))
 		return 0;
 
-	chip->interface_config = saved_intf_config;
 	ret = nand_setup_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 6c12cd52323d..0089196b9e36 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -292,6 +292,12 @@ static const struct nand_interface_config onfi_sdr_timings[] = {
 	},
 };
 
+/* All NAND chips share the same reset data interface: SDR mode 0 */
+const struct nand_interface_config *nand_get_reset_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 c2fcac38bcc2..b37eb5ee11c8 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1202,6 +1202,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 */
+const struct nand_interface_config *nand_get_reset_interface(void);
+
 /*
  * 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] 44+ messages in thread

* [PATCH v6 20/30] mtd: rawnand: marvell: Use a helper to access the timings
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (18 preceding siblings ...)
  2020-05-28 23:16 ` [PATCH v6 19/30] mtd: rawnand: Define a unique reset interface configuration Miquel Raynal
@ 2020-05-28 23:16 ` Miquel Raynal
  2020-05-28 23:16 ` [PATCH v6 21/30] mtd: rawnand: legacy: " Miquel Raynal
                   ` (9 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/raw/marvell_nand.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
index 37d451f5e898..59609f680cbf 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->interface_config);
 	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,8 @@ 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->interface_config.timings.sdr.tPROG_max));
+	ret = marvell_nfc_wait_op(chip, PSEC_TO_MSEC(sdr->tPROG_max));
+
 	return ret;
 }
 
@@ -1562,6 +1563,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->interface_config);
 	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 +1600,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->interface_config.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] 44+ messages in thread

* [PATCH v6 21/30] mtd: rawnand: legacy: Use a helper to access the timings
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (19 preceding siblings ...)
  2020-05-28 23:16 ` [PATCH v6 20/30] mtd: rawnand: marvell: Use a helper to access the timings Miquel Raynal
@ 2020-05-28 23:16 ` Miquel Raynal
  2020-05-28 23:16 ` [PATCH v6 22/30] mtd: rawnand: Hide the chip->interface_config indirection Miquel Raynal
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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>
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 60798eb29ca9..8f3644ca2ea0 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->interface_config);
+
 	/*
 	 * 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_can_setup_interface(chip))
-		ndelay(chip->interface_config.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] 44+ messages in thread

* [PATCH v6 22/30] mtd: rawnand: Hide the chip->interface_config indirection
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (20 preceding siblings ...)
  2020-05-28 23:16 ` [PATCH v6 21/30] mtd: rawnand: legacy: " Miquel Raynal
@ 2020-05-28 23:16 ` Miquel Raynal
  2020-05-29  7:37   ` Boris Brezillon
  2020-05-28 23:16 ` [PATCH v6 23/30] mtd: rawnand: Introduce nand_choose_best_sdr_timings() Miquel Raynal
                   ` (7 subsequent siblings)
  29 siblings, 1 reply; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, Miquel Raynal

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

Instead, we introduce a helper, nand_get_interface_config(), and use
it to retrieve the current interface configuration out of a nand_chip
object.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/marvell_nand.c    |  6 ++-
 drivers/mtd/nand/raw/meson_nand.c      |  8 ++--
 drivers/mtd/nand/raw/nand_base.c       | 56 +++++++++++++-------------
 drivers/mtd/nand/raw/nand_legacy.c     |  3 +-
 drivers/mtd/nand/raw/nand_toshiba.c    |  4 +-
 drivers/mtd/nand/raw/stm32_fmc2_nand.c |  2 +-
 include/linux/mtd/rawnand.h            | 11 +++++
 7 files changed, 52 insertions(+), 38 deletions(-)

diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
index 59609f680cbf..46d5c0a71e89 100644
--- a/drivers/mtd/nand/raw/marvell_nand.c
+++ b/drivers/mtd/nand/raw/marvell_nand.c
@@ -1096,7 +1096,8 @@ 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->interface_config);
+	const struct nand_interface_config *config = nand_get_interface_config(chip);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 	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;
@@ -1563,7 +1564,8 @@ 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->interface_config);
+	const struct nand_interface_config *config = nand_get_interface_config(chip);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
 	const u8 *data = buf;
diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
index c9b9594efa4f..42174915d074 100644
--- a/drivers/mtd/nand/raw/meson_nand.c
+++ b/drivers/mtd/nand/raw/meson_nand.c
@@ -573,10 +573,10 @@ static int meson_nfc_write_buf(struct nand_chip *nand, u8 *buf, int len)
 static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand,
 						int page, bool in)
 {
+	const struct nand_interface_config *config = nand_get_interface_config(nand);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 	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->interface_config);
 	u32 *addrs = nfc->cmdfifo.rw.addrs;
 	u32 cs = nfc->param.chip_select;
 	u32 cmd0, cmd_num, row_start;
@@ -626,9 +626,9 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand,
 static int meson_nfc_write_page_sub(struct nand_chip *nand,
 				    int page, int raw)
 {
+	const struct nand_interface_config *config = nand_get_interface_config(nand);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 	struct mtd_info *mtd = nand_to_mtd(nand);
-	const struct nand_sdr_timings *sdr =
-		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;
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 4a72ec221262..14d003062fa6 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->interface_config);
+	timings = nand_get_sdr_timings(nand_get_interface_config(chip));
 	ndelay(PSEC_TO_NSEC(timings->tWB_max));
 
 	ret = nand_status_op(chip, NULL);
@@ -1116,9 +1116,9 @@ static int nand_sp_exec_read_page_op(struct nand_chip *chip, unsigned int page,
 				     unsigned int offset_in_page, void *buf,
 				     unsigned int len)
 {
+	const struct nand_interface_config *config = nand_get_interface_config(chip);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 	struct mtd_info *mtd = nand_to_mtd(chip);
-	const struct nand_sdr_timings *sdr =
-		nand_get_sdr_timings(&chip->interface_config);
 	u8 addrs[4];
 	struct nand_op_instr instrs[] = {
 		NAND_OP_CMD(NAND_CMD_READ0, 0),
@@ -1159,8 +1159,8 @@ 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->interface_config);
+	const struct nand_interface_config *config = nand_get_interface_config(chip);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 	u8 addrs[5];
 	struct nand_op_instr instrs[] = {
 		NAND_OP_CMD(NAND_CMD_READ0, 0),
@@ -1256,8 +1256,8 @@ 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->interface_config);
+		const struct nand_interface_config *config = nand_get_interface_config(chip);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_PARAM, 0),
 			NAND_OP_ADDR(1, &page, PSEC_TO_NSEC(sdr->tWB_max)),
@@ -1311,8 +1311,8 @@ 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->interface_config);
+		const struct nand_interface_config *config = nand_get_interface_config(chip);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 		u8 addrs[2] = {};
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_RNDOUT, 0),
@@ -1386,9 +1386,9 @@ static int nand_exec_prog_page_op(struct nand_chip *chip, unsigned int page,
 				  unsigned int offset_in_page, const void *buf,
 				  unsigned int len, bool prog)
 {
+	const struct nand_interface_config *config = nand_get_interface_config(chip);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 	struct mtd_info *mtd = nand_to_mtd(chip);
-	const struct nand_sdr_timings *sdr =
-		nand_get_sdr_timings(&chip->interface_config);
 	u8 addrs[5] = {};
 	struct nand_op_instr instrs[] = {
 		/*
@@ -1510,8 +1510,8 @@ 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->interface_config);
+		const struct nand_interface_config *config = nand_get_interface_config(chip);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_PAGEPROG,
 				    PSEC_TO_NSEC(sdr->tWB_max)),
@@ -1617,8 +1617,8 @@ 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->interface_config);
+		const struct nand_interface_config *config = nand_get_interface_config(chip);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 		u8 addrs[2];
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_RNDIN, 0),
@@ -1672,8 +1672,8 @@ 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->interface_config);
+		const struct nand_interface_config *config = nand_get_interface_config(chip);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_READID, 0),
 			NAND_OP_ADDR(1, &addr, PSEC_TO_NSEC(sdr->tADL_min)),
@@ -1711,8 +1711,8 @@ 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->interface_config);
+		const struct nand_interface_config *config = nand_get_interface_config(chip);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_STATUS,
 				    PSEC_TO_NSEC(sdr->tADL_min)),
@@ -1780,8 +1780,8 @@ 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->interface_config);
+		const struct nand_interface_config *config = nand_get_interface_config(chip);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 		u8 addrs[3] = {	page, page >> 8, page >> 16 };
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_ERASE1, 0),
@@ -1839,8 +1839,8 @@ 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->interface_config);
+		const struct nand_interface_config *config = nand_get_interface_config(chip);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(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)),
@@ -1886,8 +1886,8 @@ 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->interface_config);
+		const struct nand_interface_config *config = nand_get_interface_config(chip);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(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)),
@@ -1943,8 +1943,8 @@ 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->interface_config);
+		const struct nand_interface_config *config = nand_get_interface_config(chip);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(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),
@@ -3221,7 +3221,7 @@ static void nand_wait_readrdy(struct nand_chip *chip)
 	if (!(chip->options & NAND_NEED_READRDY))
 		return;
 
-	sdr = nand_get_sdr_timings(&chip->interface_config);
+	sdr = nand_get_sdr_timings(nand_get_interface_config(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 8f3644ca2ea0..32601f91d375 100644
--- a/drivers/mtd/nand/raw/nand_legacy.c
+++ b/drivers/mtd/nand/raw/nand_legacy.c
@@ -354,7 +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->interface_config);
+	const struct nand_interface_config *config = nand_get_interface_config(chip);
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
 
 	/*
 	 * 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 f99c9cc5ffa5..2712f4e95798 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -32,8 +32,8 @@ 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->interface_config);
+		const struct nand_interface_config *config = nand_get_interface_config(chip);
+		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(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/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 749ac1044006..a4140af43ed4 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->interface_config);
+	timings = nand_get_sdr_timings(nand_get_interface_config(chip));
 	ndelay(PSEC_TO_NSEC(timings->tWB_max));
 
 	/* R/B# signal is low, clear high level flag */
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index b37eb5ee11c8..03b62f900d20 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1205,6 +1205,17 @@ static inline struct device_node *nand_get_flash_node(struct nand_chip *chip)
 /* Default/reset data interface */
 const struct nand_interface_config *nand_get_reset_interface(void);
 
+/**
+ * nand_get_interface_config - Retrieve the current interface configuration
+ *                             of a NAND chip
+ * @chip: The NAND chip
+ */
+static inline const struct nand_interface_config *
+nand_get_interface_config(struct nand_chip *chip)
+{
+	return &chip->interface_config;
+}
+
 /*
  * 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] 44+ messages in thread

* [PATCH v6 23/30] mtd: rawnand: Introduce nand_choose_best_sdr_timings()
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (21 preceding siblings ...)
  2020-05-28 23:16 ` [PATCH v6 22/30] mtd: rawnand: Hide the chip->interface_config indirection Miquel Raynal
@ 2020-05-28 23:16 ` Miquel Raynal
  2020-05-28 23:16 ` [PATCH v6 24/30] mtd: rawnand: Add the ->choose_interface() hook Miquel Raynal
                   ` (6 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, Miquel Raynal

Extract the logic out of nand_choose_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 | 100 +++++++++++++++++++------------
 2 files changed, 64 insertions(+), 39 deletions(-)

diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index 11415b054d2e..3feff77c7c81 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -90,6 +90,9 @@ void onfi_fill_interface_config(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_interface_config *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 14d003062fa6..28e249beb335 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -1003,59 +1003,81 @@ static int nand_setup_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 interface configuration (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_interface_config *iface,
+				 struct nand_sdr_timings *spec_timings)
+{
+	const struct nand_controller_ops *ops = chip->controller->ops;
+	int best_mode = 0, 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_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) {
+			unsigned int onfi_modes;
+
+			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--) {
+		onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, mode);
+
+		ret = ops->setup_interface(chip, NAND_DATA_IFACE_CHECK_ONLY,
+					   iface);
+		if (!ret)
+			return 0;
+	}
+
+	return 0;
+}
+
 /**
  * nand_choose_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->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_interface(struct nand_chip *chip)
 {
-	int modes, mode, ret;
-
 	if (!nand_controller_can_setup_interface(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--) {
-		onfi_fill_interface_config(chip, &chip->interface_config,
-					   NAND_SDR_IFACE, mode);
-
-		/*
-		 * Pass NAND_DATA_IFACE_CHECK_ONLY to only check if the
-		 * controller supports the requested timings.
-		 */
-		ret = chip->controller->ops->setup_interface(chip,
-						 NAND_DATA_IFACE_CHECK_ONLY,
-						 &chip->interface_config);
-		if (!ret) {
-			chip->onfi_timing_mode_default = mode;
-			break;
-		}
-	}
-
-	return 0;
+	return nand_choose_best_sdr_timings(chip, &chip->interface_config,
+					    NULL);
 }
 
 /**
-- 
2.20.1


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

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

* [PATCH v6 24/30] mtd: rawnand: Add the ->choose_interface() hook
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (22 preceding siblings ...)
  2020-05-28 23:16 ` [PATCH v6 23/30] mtd: rawnand: Introduce nand_choose_best_sdr_timings() Miquel Raynal
@ 2020-05-28 23:16 ` Miquel Raynal
  2020-05-29  7:42   ` Boris Brezillon
  2020-05-28 23:16 ` [PATCH v6 25/30] mtd: rawnand: toshiba: Implement ->choose_interface() for TC58TEG5DCLTA00 Miquel Raynal
                   ` (5 subsequent siblings)
  29 siblings, 1 reply; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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
interface 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 28e249beb335..132feee3ba13 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -1047,7 +1047,6 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
 		}
 	}
 
-
 	for (mode = best_mode; mode >= 0; mode--) {
 		onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, mode);
 
@@ -1065,7 +1064,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.
  *
@@ -1076,6 +1077,10 @@ static int nand_choose_interface(struct nand_chip *chip)
 	if (!nand_controller_can_setup_interface(chip))
 		return 0;
 
+	if (chip->ops.choose_interface)
+		return chip->ops.choose_interface(chip,
+						  &chip->interface_config);
+
 	return nand_choose_best_sdr_timings(chip, &chip->interface_config,
 					    NULL);
 }
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 03b62f900d20..ce4a525517a6 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1033,6 +1033,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);
@@ -1040,6 +1041,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_interface)(struct nand_chip *chip,
+				struct nand_interface_config *iface);
 };
 
 /**
-- 
2.20.1


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

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

* [PATCH v6 25/30] mtd: rawnand: toshiba: Implement ->choose_interface() for TC58TEG5DCLTA00
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (23 preceding siblings ...)
  2020-05-28 23:16 ` [PATCH v6 24/30] mtd: rawnand: Add the ->choose_interface() hook Miquel Raynal
@ 2020-05-28 23:16 ` Miquel Raynal
  2020-05-28 23:16 ` [PATCH v6 26/30] mtd: rawnand: toshiba: Implement ->choose_interface() for TC58NVG0S3E Miquel Raynal
                   ` (4 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/raw/nand_toshiba.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index 2712f4e95798..38f25178c39c 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -194,11 +194,19 @@ static void toshiba_nand_decode_id(struct nand_chip *chip)
 	}
 }
 
+static int tc58teg5dclta00_choose_interface(struct nand_chip *chip,
+					    struct nand_interface_config *iface)
+{
+	onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, 5);
+
+	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_interface = &tc58teg5dclta00_choose_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] 44+ messages in thread

* [PATCH v6 26/30] mtd: rawnand: toshiba: Implement ->choose_interface() for TC58NVG0S3E
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (24 preceding siblings ...)
  2020-05-28 23:16 ` [PATCH v6 25/30] mtd: rawnand: toshiba: Implement ->choose_interface() for TC58TEG5DCLTA00 Miquel Raynal
@ 2020-05-28 23:16 ` Miquel Raynal
  2020-05-28 23:16 ` [PATCH v6 27/30] mtd: rawnand: hynix: Implement ->choose_interface() for H27UCG8T2ATR-BC Miquel Raynal
                   ` (3 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 | 18 ++++++++++++++++++
 2 files changed, 19 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 38f25178c39c..a6888e4d436b 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -202,6 +202,14 @@ static int tc58teg5dclta00_choose_interface(struct nand_chip *chip,
 	return nand_choose_best_sdr_timings(chip, iface, NULL);
 }
 
+static int tc58nvg0s3e_choose_interface(struct nand_chip *chip,
+					struct nand_interface_config *iface)
+{
+	onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, 2);
+
+	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);
@@ -213,6 +221,13 @@ static int tc58teg5dclta00_init(struct nand_chip *chip)
 	return 0;
 }
 
+static int tc58nvg0s3e_init(struct nand_chip *chip)
+{
+	chip->ops.choose_interface = &tc58nvg0s3e_choose_interface;
+
+	return 0;
+}
+
 static int toshiba_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
@@ -225,6 +240,9 @@ static int toshiba_nand_init(struct nand_chip *chip)
 
 	if (!strcmp("TC58TEG5DCLTA00", chip->parameters.model))
 		tc58teg5dclta00_init(chip);
+	if (!strncmp("TC58NVG0S3E", chip->parameters.model,
+		     sizeof("TC58NVG0S3E") - 1))
+		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] 44+ messages in thread

* [PATCH v6 27/30] mtd: rawnand: hynix: Implement ->choose_interface() for H27UCG8T2ATR-BC
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (25 preceding siblings ...)
  2020-05-28 23:16 ` [PATCH v6 26/30] mtd: rawnand: toshiba: Implement ->choose_interface() for TC58NVG0S3E Miquel Raynal
@ 2020-05-28 23:16 ` Miquel Raynal
  2020-05-28 23:16 ` [PATCH v6 28/30] mtd: rawnand: toshiba: Choose the data interface for TH58NVG2S3HBAI4 Miquel Raynal
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 | 13 +++++++++++++
 drivers/mtd/nand/raw/nand_ids.c   |  2 +-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
index 7d1be53f27f3..fa656bc5a918 100644
--- a/drivers/mtd/nand/raw/nand_hynix.c
+++ b/drivers/mtd/nand/raw/nand_hynix.c
@@ -673,6 +673,15 @@ static void hynix_nand_cleanup(struct nand_chip *chip)
 	nand_set_manufacturer_data(chip, NULL);
 }
 
+static int
+h27ucg8t2atrbc_choose_interface(struct nand_chip *chip,
+				struct nand_interface_config *iface)
+{
+	onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, 4);
+
+	return nand_choose_best_sdr_timings(chip, iface, NULL);
+}
+
 static int hynix_nand_init(struct nand_chip *chip)
 {
 	struct hynix_nand *hynix;
@@ -689,6 +698,10 @@ static int hynix_nand_init(struct nand_chip *chip)
 
 	nand_set_manufacturer_data(chip, hynix);
 
+	if (!strncmp("H27UCG8T2ATR-BC", chip->parameters.model,
+		     sizeof("H27UCG8T2ATR-BC") - 1))
+		chip->ops.choose_interface = h27ucg8t2atrbc_choose_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] 44+ messages in thread

* [PATCH v6 28/30] mtd: rawnand: toshiba: Choose the data interface for TH58NVG2S3HBAI4
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (26 preceding siblings ...)
  2020-05-28 23:16 ` [PATCH v6 27/30] mtd: rawnand: hynix: Implement ->choose_interface() for H27UCG8T2ATR-BC Miquel Raynal
@ 2020-05-28 23:16 ` Miquel Raynal
  2020-05-28 23:16 ` [PATCH v6 29/30] mtd: rawnand: Get rid of the default ONFI timing mode Miquel Raynal
  2020-05-28 23:16 ` [PATCH v6 30/30] mtd: rawnand: Allocate the best interface configuration dynamically Miquel Raynal
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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 | 36 +++++++++++++++++++++++++++++
 2 files changed, 39 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 a6888e4d436b..56463c6ef9ae 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -210,6 +210,32 @@ static int tc58nvg0s3e_choose_interface(struct nand_chip *chip,
 	return nand_choose_best_sdr_timings(chip, iface, NULL);
 }
 
+static int th58nvg2s3hbai4_choose_interface(struct nand_chip *chip,
+					    struct nand_interface_config *iface)
+{
+	struct nand_sdr_timings *sdr = &iface->timings.sdr;
+
+	/* Start with timings from the closest timing mode, mode 4. */
+	onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, 4);
+
+	/* 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);
@@ -228,6 +254,13 @@ static int tc58nvg0s3e_init(struct nand_chip *chip)
 	return 0;
 }
 
+static int th58nvg2s3hbai4_init(struct nand_chip *chip)
+{
+	chip->ops.choose_interface = th58nvg2s3hbai4_choose_interface;
+
+	return 0;
+}
+
 static int toshiba_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
@@ -243,6 +276,9 @@ static int toshiba_nand_init(struct nand_chip *chip)
 	if (!strncmp("TC58NVG0S3E", chip->parameters.model,
 		     sizeof("TC58NVG0S3E") - 1))
 		tc58nvg0s3e_init(chip);
+	if (!strncmp("TH58NVG2S3HBAI4", chip->parameters.model,
+		     sizeof("TH58NVG2S3HBAI4") - 1))
+		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] 44+ messages in thread

* [PATCH v6 29/30] mtd: rawnand: Get rid of the default ONFI timing mode
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (27 preceding siblings ...)
  2020-05-28 23:16 ` [PATCH v6 28/30] mtd: rawnand: toshiba: Choose the data interface for TH58NVG2S3HBAI4 Miquel Raynal
@ 2020-05-28 23:16 ` Miquel Raynal
  2020-05-28 23:16 ` [PATCH v6 30/30] mtd: rawnand: Allocate the best interface configuration dynamically Miquel Raynal
  29 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, Miquel Raynal

The ->choose_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, 4 insertions(+), 24 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 132feee3ba13..2f913ce8328f 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -1010,10 +1010,8 @@ static int nand_setup_interface(struct nand_chip *chip, int chipnr)
  * @iface: the interface configuration (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_interface_config *iface,
@@ -1036,15 +1034,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) {
-			unsigned int onfi_modes;
-
-			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--) {
@@ -4763,8 +4754,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 ce4a525517a6..7b7db2d91a9a 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1069,9 +1069,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
  * @interface_config: 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
@@ -1119,7 +1116,6 @@ struct nand_chip {
 	unsigned int options;
 
 	/* Data interface */
-	int onfi_timing_mode_default;
 	struct nand_interface_config interface_config;
 
 	/* Bad block information */
@@ -1271,10 +1267,6 @@ nand_get_interface_config(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] 44+ messages in thread

* [PATCH v6 30/30] mtd: rawnand: Allocate the best interface configuration dynamically
  2020-05-28 23:15 [PATCH v6 00/30] Allow vendor drivers to propose their own timings Miquel Raynal
                   ` (28 preceding siblings ...)
  2020-05-28 23:16 ` [PATCH v6 29/30] mtd: rawnand: Get rid of the default ONFI timing mode Miquel Raynal
@ 2020-05-28 23:16 ` Miquel Raynal
  2020-05-29  8:54   ` Boris Brezillon
  29 siblings, 1 reply; 44+ messages in thread
From: Miquel Raynal @ 2020-05-28 23:16 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Rickard Andersson, Michal Simek, Boris Brezillon,
	Naga Sureshkumar Relli, Thomas Petazzoni, 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.

Use a second pointer to always have a reference on the currently
applied interface configuration.

This way, either there is a "best interface configuration" and the
requested timings will be these, or there is none and the default set
will be used, 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 | 56 +++++++++++++++++++++++---------
 include/linux/mtd/rawnand.h      | 11 +++++--
 2 files changed, 48 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 2f913ce8328f..13fee17cd411 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -928,7 +928,9 @@ static int nand_reset_interface(struct nand_chip *chip, int chipnr)
 	 * timings to timing mode 0.
 	 */
 
-	ret = ops->setup_interface(chip, chipnr, nand_get_reset_interface());
+	chip->current_interface_config = nand_get_reset_interface();
+	ret = ops->setup_interface(chip, chipnr,
+				   chip->current_interface_config);
 	if (ret)
 		pr_err("Failed to configure data interface to SDR timing mode 0\n");
 
@@ -947,7 +949,8 @@ static int nand_reset_interface(struct nand_chip *chip, int chipnr)
  */
 static int nand_setup_interface(struct nand_chip *chip, int chipnr)
 {
-	u8 mode = chip->interface_config.timings.mode;
+	const struct nand_controller_ops *ops = chip->controller->ops;
+	u8 mode = chip->best_interface_config->timings.mode;
 	u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { mode, };
 	int ret;
 
@@ -965,14 +968,13 @@ static int nand_setup_interface(struct nand_chip *chip, int chipnr)
 	}
 
 	/* Change the mode on the controller side */
-	ret = chip->controller->ops->setup_interface(chip, chipnr,
-						     &chip->interface_config);
+	ret = ops->setup_interface(chip, chipnr, chip->best_interface_config);
 	if (ret)
 		return ret;
 
 	/* Check the mode has been accepted by the chip, if supported */
 	if (!nand_supports_get_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE))
-		return 0;
+		goto update_interface_config;
 
 	memset(tmode_param, 0, ONFI_SUBFEATURE_PARAM_LEN);
 	nand_select_target(chip, chipnr);
@@ -988,6 +990,9 @@ static int nand_setup_interface(struct nand_chip *chip, int chipnr)
 		goto err_reset_chip;
 	}
 
+update_interface_config:
+	chip->current_interface_config = chip->best_interface_config;
+
 	return 0;
 
 err_reset_chip:
@@ -1029,8 +1034,10 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
 		/* Verify the controller supports the requested interface */
 		ret = ops->setup_interface(chip, NAND_DATA_IFACE_CHECK_ONLY,
 					   iface);
-		if (!ret)
+		if (!ret) {
+			chip->best_interface_config = iface;
 			return ret;
+		}
 
 		/* Fallback to slower modes */
 		best_mode = iface->timings.mode;
@@ -1044,9 +1051,11 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
 		ret = ops->setup_interface(chip, NAND_DATA_IFACE_CHECK_ONLY,
 					   iface);
 		if (!ret)
-			return 0;
+			break;
 	}
 
+	chip->best_interface_config = iface;
+
 	return 0;
 }
 
@@ -1065,15 +1074,25 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
  */
 static int nand_choose_interface(struct nand_chip *chip)
 {
+	struct nand_interface_config *iface;
+	int ret;
+
 	if (!nand_controller_can_setup_interface(chip))
 		return 0;
 
+	iface = kzalloc(sizeof(*iface), GFP_KERNEL);
+	if (!iface)
+		return -ENOMEM;
+
 	if (chip->ops.choose_interface)
-		return chip->ops.choose_interface(chip,
-						  &chip->interface_config);
+		ret = chip->ops.choose_interface(chip, iface);
+	else
+		ret = nand_choose_best_sdr_timings(chip, iface, NULL);
 
-	return nand_choose_best_sdr_timings(chip, &chip->interface_config,
-					    NULL);
+	if (ret)
+		kfree(iface);
+
+	return ret;
 }
 
 /**
@@ -2523,8 +2542,8 @@ int nand_reset(struct nand_chip *chip, int chipnr)
 	 * nand_setup_interface() uses ->set/get_features() which would
 	 * fail anyway as the parameter page is not available yet.
 	 */
-	if (!memcmp(&chip->interface_config, nand_get_reset_interface(),
-		    sizeof(chip->interface_config)))
+	if (!chip->best_interface_config ||
+	    chip->best_interface_config == nand_get_reset_interface())
 		return 0;
 
 	ret = nand_setup_interface(chip, chipnr);
@@ -5194,7 +5213,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_interface_config(chip, &chip->interface_config, NAND_SDR_IFACE, 0);
+	chip->current_interface_config = nand_get_reset_interface();
 
 	ret = nand_dt_init(chip);
 	if (ret)
@@ -5990,7 +6009,7 @@ static int nand_scan_tail(struct nand_chip *chip)
 	for (i = 0; i < nanddev_ntargets(&chip->base); i++) {
 		ret = nand_setup_interface(chip, i);
 		if (ret)
-			goto err_nanddev_cleanup;
+			goto err_free_interface_config;
 	}
 
 	/* Check, if we should skip the bad block table scan */
@@ -6000,10 +6019,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_interface_config;
 
 	return 0;
 
+err_free_interface_config:
+	kfree(chip->best_interface_config);
 
 err_nanddev_cleanup:
 	nanddev_cleanup(&chip->base);
@@ -6097,6 +6118,9 @@ void nand_cleanup(struct nand_chip *chip)
 			& NAND_BBT_DYNAMICSTRUCT)
 		kfree(chip->badblock_pattern);
 
+	/* Free the data interface */
+	kfree(chip->best_interface_config);
+
 	/* Free manufacturer priv data. */
 	nand_manufacturer_cleanup(chip);
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 7b7db2d91a9a..50ea4b825324 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1069,7 +1069,11 @@ 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.
- * @interface_config: NAND interface timing information
+ * @current_interface_config: The currently used NAND interface configuration
+ * @best_interface_config: The best NAND interface configuration which fits both
+ *                         the NAND chip and NAND controller constraints. If
+ *                         unset, the default reset interface configuration 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
@@ -1116,7 +1120,8 @@ struct nand_chip {
 	unsigned int options;
 
 	/* Data interface */
-	struct nand_interface_config interface_config;
+	const struct nand_interface_config *current_interface_config;
+	struct nand_interface_config *best_interface_config;
 
 	/* Bad block information */
 	unsigned int bbt_erase_shift;
@@ -1212,7 +1217,7 @@ const struct nand_interface_config *nand_get_reset_interface(void);
 static inline const struct nand_interface_config *
 nand_get_interface_config(struct nand_chip *chip)
 {
-	return &chip->interface_config;
+	return chip->current_interface_config;
 }
 
 /*
-- 
2.20.1


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

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

* Re: [PATCH v6 13/30] mtd: rawnand: timings: Provide onfi_fill_data_interface() with a data interface
  2020-05-28 23:15 ` [PATCH v6 13/30] mtd: rawnand: timings: Provide onfi_fill_data_interface() with a data interface Miquel Raynal
@ 2020-05-29  7:16   ` Boris Brezillon
  0 siblings, 0 replies; 44+ messages in thread
From: Boris Brezillon @ 2020-05-29  7:16 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Michal Simek, Vignesh Raghavendra,
	Tudor Ambarus, Richard Weinberger, linux-mtd, Thomas Petazzoni,
	Naga Sureshkumar Relli

On Fri, 29 May 2020 01:15:55 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> We rely be default on the data interface which is in the nand_chip

          ^by

> structure but it should be possible to fill any other data interface.

But even then it sounds weird. How about:

"
Right now the core uses onfi_fill_data_interface() to initialize the
nand_data_interface object embedded in nand_chip, but we are about to
allocate this object dynamically and let manufacturer drivers provide
their own interface config. Let's patch the onfi_fill_data_interface()
so it can initialize an interface config that's not the one
currently attached to the nand_chip.
"

> 
> 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 a5e2cec7e301..0f74509abc4c 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 1d9cf02d164b..b4de85794e07 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;
>  
> @@ -5182,7 +5183,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)


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

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

* Re: [PATCH v6 16/30] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max
  2020-05-28 23:15 ` [PATCH v6 16/30] mtd: rawnand: timings: Use default values for tPROG_max and tBERS_max Miquel Raynal
@ 2020-05-29  7:21   ` Boris Brezillon
  0 siblings, 0 replies; 44+ messages in thread
From: Boris Brezillon @ 2020-05-29  7:21 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Michal Simek, Vignesh Raghavendra,
	Tudor Ambarus, Richard Weinberger, linux-mtd, Thomas Petazzoni,
	Naga Sureshkumar Relli

On Fri, 29 May 2020 01:15:58 +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.

And most importantly you want to do that to return a pointer to mode 0
directly :P.

> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

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

> ---
>  drivers/mtd/nand/raw/nand_timings.c | 31 ++++++++++++++++++-----------
>  1 file changed, 19 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
> index 728a2dee1eed..9ff4b121ab1e 100644
> --- a/drivers/mtd/nand/raw/nand_timings.c
> +++ b/drivers/mtd/nand/raw/nand_timings.c
> @@ -12,6 +12,13 @@
>  
>  #define ONFI_DYN_TIMING_MAX U16_MAX
>  
> +/*
> + * 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.
> + *
> + * These four values are tweaked to be more accurate in the case of ONFI chips.
> + */
>  static const struct nand_data_interface onfi_sdr_timings[] = {
>  	/* Mode 0 */
>  	{
> @@ -20,6 +27,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 +72,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 +117,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 +162,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 +207,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 +252,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,
> @@ -357,18 +376,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] 44+ messages in thread

* Re: [PATCH v6 18/30] mtd: rawnand: timings: Make onfi_fill_interface_config() a void helper
  2020-05-28 23:16 ` [PATCH v6 18/30] mtd: rawnand: timings: Make onfi_fill_interface_config() a void helper Miquel Raynal
@ 2020-05-29  7:27   ` Boris Brezillon
  0 siblings, 0 replies; 44+ messages in thread
From: Boris Brezillon @ 2020-05-29  7:27 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Michal Simek, Vignesh Raghavendra,
	Tudor Ambarus, Richard Weinberger, linux-mtd, Thomas Petazzoni,
	Naga Sureshkumar Relli

On Fri, 29 May 2020 01:16:00 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Warn the user if the parameters are wrong but basically it would mean
> there is a serious issue in the NAND core. So no need to ever check
> its output, let's make this helper return void.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

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

One comment below.

> ---
>  drivers/mtd/nand/raw/internals.h    |  8 ++++----
>  drivers/mtd/nand/raw/nand_base.c    |  6 ++----
>  drivers/mtd/nand/raw/nand_timings.c | 19 +++++++++----------
>  3 files changed, 15 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
> index 93386bdfbad6..11415b054d2e 100644
> --- a/drivers/mtd/nand/raw/internals.h
> +++ b/drivers/mtd/nand/raw/internals.h
> @@ -84,10 +84,10 @@ 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_interface_config(struct nand_chip *chip,
> -			       struct nand_interface_config *iface,
> -			       enum nand_interface_type type,
> -			       int timing_mode);
> +void onfi_fill_interface_config(struct nand_chip *chip,
> +				struct nand_interface_config *iface,
> +				enum nand_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);
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index de596c06c9c2..07a7d918b462 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -1041,10 +1041,8 @@ static int nand_choose_interface(struct nand_chip *chip)
>  	}
>  
>  	for (mode = fls(modes) - 1; mode >= 0; mode--) {
> -		ret = onfi_fill_interface_config(chip, &chip->interface_config,
> -						 NAND_SDR_IFACE, mode);
> -		if (ret)
> -			continue;
> +		onfi_fill_interface_config(chip, &chip->interface_config,
> +					   NAND_SDR_IFACE, mode);
>  
>  		/*
>  		 * Pass NAND_DATA_IFACE_CHECK_ONLY to only check if the
> diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
> index 997a1dd929de..6c12cd52323d 100644
> --- a/drivers/mtd/nand/raw/nand_timings.c
> +++ b/drivers/mtd/nand/raw/nand_timings.c
> @@ -347,18 +347,19 @@ onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings)
>   * @type: The interface type
>   * @timing_mode: The ONFI timing mode
>   */
> -int onfi_fill_interface_config(struct nand_chip *chip,
> -			       struct nand_interface_config *iface,
> -			       enum nand_interface_type type,
> -			       int timing_mode)
> +void onfi_fill_interface_config(struct nand_chip *chip,
> +				struct nand_interface_config *iface,
> +				enum nand_interface_type type,
> +				int timing_mode)
>  {
>  	struct onfi_params *onfi = chip->parameters.onfi;
>  
> -	if (type != NAND_SDR_IFACE)
> -		return -EINVAL;
> +	if (WARN_ON(type != NAND_SDR_IFACE))
> +		return;
>  
> -	if (timing_mode < 0 || timing_mode >= ARRAY_SIZE(onfi_sdr_timings))
> -		return -EINVAL;
> +	if (WARN_ON(timing_mode < 0 ||

timing_mode should probably be unsigned, that would allow us to get rid
of this test.

> +		    timing_mode >= ARRAY_SIZE(onfi_sdr_timings)))
> +		return;
>  
>  	*iface = onfi_sdr_timings[timing_mode];
>  
> @@ -378,6 +379,4 @@ int onfi_fill_interface_config(struct nand_chip *chip,
>  		/* nanoseconds -> picoseconds */
>  		timings->tCCS_min = 1000UL * onfi->tCCS;
>  	}
> -
> -	return 0;
>  }


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

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

* Re: [PATCH v6 19/30] mtd: rawnand: Define a unique reset interface configuration
  2020-05-28 23:16 ` [PATCH v6 19/30] mtd: rawnand: Define a unique reset interface configuration Miquel Raynal
@ 2020-05-29  7:32   ` Boris Brezillon
  2020-05-29  9:27     ` Miquel Raynal
  0 siblings, 1 reply; 44+ messages in thread
From: Boris Brezillon @ 2020-05-29  7:32 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Michal Simek, Vignesh Raghavendra,
	Tudor Ambarus, Richard Weinberger, linux-mtd, Thomas Petazzoni,
	Naga Sureshkumar Relli

On Fri, 29 May 2020 01:16:01 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> All NAND chips will always use the same interface configuration for
> reset and at startup: SDR mode 0. Instead of copying around the
> interface configuration, let's just define a helper to retrieve the
> reset interface configuration object.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/nand_base.c    | 10 +++-------
>  drivers/mtd/nand/raw/nand_timings.c |  6 ++++++
>  include/linux/mtd/rawnand.h         |  3 +++
>  3 files changed, 12 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 07a7d918b462..4a72ec221262 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -928,9 +928,7 @@ static int nand_reset_interface(struct nand_chip *chip, int chipnr)
>  	 * timings to timing mode 0.
>  	 */
>  
> -	onfi_fill_interface_config(chip, &chip->interface_config,
> -				   NAND_SDR_IFACE, 0);
> -	ret = ops->setup_interface(chip, chipnr, &chip->interface_config);
> +	ret = ops->setup_interface(chip, chipnr, nand_get_reset_interface());
>  	if (ret)
>  		pr_err("Failed to configure data interface to SDR timing mode 0\n");
>  
> @@ -2483,7 +2481,6 @@ EXPORT_SYMBOL_GPL(nand_subop_get_data_len);
>   */
>  int nand_reset(struct nand_chip *chip, int chipnr)
>  {
> -	struct nand_interface_config saved_intf_config = chip->interface_config;
>  	int ret;
>  
>  	ret = nand_reset_interface(chip, chipnr);
> @@ -2508,11 +2505,10 @@ int nand_reset(struct nand_chip *chip, int chipnr)
>  	 * nand_setup_interface() uses ->set/get_features() which would
>  	 * fail anyway as the parameter page is not available yet.
>  	 */
> -	if (!memcmp(&chip->interface_config, &saved_intf_config,
> -		    sizeof(saved_intf_config)))
> +	if (!memcmp(&chip->interface_config, nand_get_reset_interface(),
> +		    sizeof(chip->interface_config)))
>  		return 0;
>  
> -	chip->interface_config = saved_intf_config;

Are you sure you can do that now? Looks like the current interface
config is not preserved, and you end up with mode 0 after a reset.

>  	ret = nand_setup_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 6c12cd52323d..0089196b9e36 100644
> --- a/drivers/mtd/nand/raw/nand_timings.c
> +++ b/drivers/mtd/nand/raw/nand_timings.c
> @@ -292,6 +292,12 @@ static const struct nand_interface_config onfi_sdr_timings[] = {
>  	},
>  };
>  
> +/* All NAND chips share the same reset data interface: SDR mode 0 */
> +const struct nand_interface_config *nand_get_reset_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 c2fcac38bcc2..b37eb5ee11c8 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -1202,6 +1202,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 */
> +const struct nand_interface_config *nand_get_reset_interface(void);
> +
>  /*
>   * 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] 44+ messages in thread

* Re: [PATCH v6 22/30] mtd: rawnand: Hide the chip->interface_config indirection
  2020-05-28 23:16 ` [PATCH v6 22/30] mtd: rawnand: Hide the chip->interface_config indirection Miquel Raynal
@ 2020-05-29  7:37   ` Boris Brezillon
  0 siblings, 0 replies; 44+ messages in thread
From: Boris Brezillon @ 2020-05-29  7:37 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Michal Simek, Vignesh Raghavendra,
	Tudor Ambarus, Richard Weinberger, linux-mtd, Thomas Petazzoni,
	Naga Sureshkumar Relli

On Fri, 29 May 2020 01:16:04 +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.

					    ^accessing the
					    chip->interface_config
					    directly.

> 
> Instead, we introduce a helper, nand_get_interface_config(), and use
> it to retrieve the current interface configuration out of a nand_chip
> object.


Would have been much better to have that patch before patch 19 so you
can modify drivers only once.

> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/marvell_nand.c    |  6 ++-
>  drivers/mtd/nand/raw/meson_nand.c      |  8 ++--
>  drivers/mtd/nand/raw/nand_base.c       | 56 +++++++++++++-------------
>  drivers/mtd/nand/raw/nand_legacy.c     |  3 +-
>  drivers/mtd/nand/raw/nand_toshiba.c    |  4 +-
>  drivers/mtd/nand/raw/stm32_fmc2_nand.c |  2 +-
>  include/linux/mtd/rawnand.h            | 11 +++++
>  7 files changed, 52 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
> index 59609f680cbf..46d5c0a71e89 100644
> --- a/drivers/mtd/nand/raw/marvell_nand.c
> +++ b/drivers/mtd/nand/raw/marvell_nand.c
> @@ -1096,7 +1096,8 @@ 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->interface_config);
> +	const struct nand_interface_config *config = nand_get_interface_config(chip);
> +	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  	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;
> @@ -1563,7 +1564,8 @@ 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->interface_config);
> +	const struct nand_interface_config *config = nand_get_interface_config(chip);
> +	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  	struct mtd_info *mtd = nand_to_mtd(chip);
>  	const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
>  	const u8 *data = buf;
> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
> index c9b9594efa4f..42174915d074 100644
> --- a/drivers/mtd/nand/raw/meson_nand.c
> +++ b/drivers/mtd/nand/raw/meson_nand.c
> @@ -573,10 +573,10 @@ static int meson_nfc_write_buf(struct nand_chip *nand, u8 *buf, int len)
>  static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand,
>  						int page, bool in)
>  {
> +	const struct nand_interface_config *config = nand_get_interface_config(nand);
> +	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  	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->interface_config);
>  	u32 *addrs = nfc->cmdfifo.rw.addrs;
>  	u32 cs = nfc->param.chip_select;
>  	u32 cmd0, cmd_num, row_start;
> @@ -626,9 +626,9 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand,
>  static int meson_nfc_write_page_sub(struct nand_chip *nand,
>  				    int page, int raw)
>  {
> +	const struct nand_interface_config *config = nand_get_interface_config(nand);
> +	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  	struct mtd_info *mtd = nand_to_mtd(nand);
> -	const struct nand_sdr_timings *sdr =
> -		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;
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 4a72ec221262..14d003062fa6 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->interface_config);
> +	timings = nand_get_sdr_timings(nand_get_interface_config(chip));
>  	ndelay(PSEC_TO_NSEC(timings->tWB_max));
>  
>  	ret = nand_status_op(chip, NULL);
> @@ -1116,9 +1116,9 @@ static int nand_sp_exec_read_page_op(struct nand_chip *chip, unsigned int page,
>  				     unsigned int offset_in_page, void *buf,
>  				     unsigned int len)
>  {
> +	const struct nand_interface_config *config = nand_get_interface_config(chip);
> +	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  	struct mtd_info *mtd = nand_to_mtd(chip);
> -	const struct nand_sdr_timings *sdr =
> -		nand_get_sdr_timings(&chip->interface_config);
>  	u8 addrs[4];
>  	struct nand_op_instr instrs[] = {
>  		NAND_OP_CMD(NAND_CMD_READ0, 0),
> @@ -1159,8 +1159,8 @@ 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->interface_config);
> +	const struct nand_interface_config *config = nand_get_interface_config(chip);
> +	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  	u8 addrs[5];
>  	struct nand_op_instr instrs[] = {
>  		NAND_OP_CMD(NAND_CMD_READ0, 0),
> @@ -1256,8 +1256,8 @@ 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->interface_config);
> +		const struct nand_interface_config *config = nand_get_interface_config(chip);
> +		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  		struct nand_op_instr instrs[] = {
>  			NAND_OP_CMD(NAND_CMD_PARAM, 0),
>  			NAND_OP_ADDR(1, &page, PSEC_TO_NSEC(sdr->tWB_max)),
> @@ -1311,8 +1311,8 @@ 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->interface_config);
> +		const struct nand_interface_config *config = nand_get_interface_config(chip);
> +		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  		u8 addrs[2] = {};
>  		struct nand_op_instr instrs[] = {
>  			NAND_OP_CMD(NAND_CMD_RNDOUT, 0),
> @@ -1386,9 +1386,9 @@ static int nand_exec_prog_page_op(struct nand_chip *chip, unsigned int page,
>  				  unsigned int offset_in_page, const void *buf,
>  				  unsigned int len, bool prog)
>  {
> +	const struct nand_interface_config *config = nand_get_interface_config(chip);
> +	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  	struct mtd_info *mtd = nand_to_mtd(chip);
> -	const struct nand_sdr_timings *sdr =
> -		nand_get_sdr_timings(&chip->interface_config);
>  	u8 addrs[5] = {};
>  	struct nand_op_instr instrs[] = {
>  		/*
> @@ -1510,8 +1510,8 @@ 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->interface_config);
> +		const struct nand_interface_config *config = nand_get_interface_config(chip);
> +		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  		struct nand_op_instr instrs[] = {
>  			NAND_OP_CMD(NAND_CMD_PAGEPROG,
>  				    PSEC_TO_NSEC(sdr->tWB_max)),
> @@ -1617,8 +1617,8 @@ 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->interface_config);
> +		const struct nand_interface_config *config = nand_get_interface_config(chip);
> +		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  		u8 addrs[2];
>  		struct nand_op_instr instrs[] = {
>  			NAND_OP_CMD(NAND_CMD_RNDIN, 0),
> @@ -1672,8 +1672,8 @@ 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->interface_config);
> +		const struct nand_interface_config *config = nand_get_interface_config(chip);
> +		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  		struct nand_op_instr instrs[] = {
>  			NAND_OP_CMD(NAND_CMD_READID, 0),
>  			NAND_OP_ADDR(1, &addr, PSEC_TO_NSEC(sdr->tADL_min)),
> @@ -1711,8 +1711,8 @@ 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->interface_config);
> +		const struct nand_interface_config *config = nand_get_interface_config(chip);
> +		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  		struct nand_op_instr instrs[] = {
>  			NAND_OP_CMD(NAND_CMD_STATUS,
>  				    PSEC_TO_NSEC(sdr->tADL_min)),
> @@ -1780,8 +1780,8 @@ 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->interface_config);
> +		const struct nand_interface_config *config = nand_get_interface_config(chip);
> +		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  		u8 addrs[3] = {	page, page >> 8, page >> 16 };
>  		struct nand_op_instr instrs[] = {
>  			NAND_OP_CMD(NAND_CMD_ERASE1, 0),
> @@ -1839,8 +1839,8 @@ 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->interface_config);
> +		const struct nand_interface_config *config = nand_get_interface_config(chip);
> +		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(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)),
> @@ -1886,8 +1886,8 @@ 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->interface_config);
> +		const struct nand_interface_config *config = nand_get_interface_config(chip);
> +		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(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)),
> @@ -1943,8 +1943,8 @@ 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->interface_config);
> +		const struct nand_interface_config *config = nand_get_interface_config(chip);
> +		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(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),
> @@ -3221,7 +3221,7 @@ static void nand_wait_readrdy(struct nand_chip *chip)
>  	if (!(chip->options & NAND_NEED_READRDY))
>  		return;
>  
> -	sdr = nand_get_sdr_timings(&chip->interface_config);
> +	sdr = nand_get_sdr_timings(nand_get_interface_config(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 8f3644ca2ea0..32601f91d375 100644
> --- a/drivers/mtd/nand/raw/nand_legacy.c
> +++ b/drivers/mtd/nand/raw/nand_legacy.c
> @@ -354,7 +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->interface_config);
> +	const struct nand_interface_config *config = nand_get_interface_config(chip);
> +	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(config);
>  
>  	/*
>  	 * 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 f99c9cc5ffa5..2712f4e95798 100644
> --- a/drivers/mtd/nand/raw/nand_toshiba.c
> +++ b/drivers/mtd/nand/raw/nand_toshiba.c
> @@ -32,8 +32,8 @@ 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->interface_config);
> +		const struct nand_interface_config *config = nand_get_interface_config(chip);
> +		const struct nand_sdr_timings *sdr = nand_get_sdr_timings(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/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index 749ac1044006..a4140af43ed4 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->interface_config);
> +	timings = nand_get_sdr_timings(nand_get_interface_config(chip));
>  	ndelay(PSEC_TO_NSEC(timings->tWB_max));
>  
>  	/* R/B# signal is low, clear high level flag */
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index b37eb5ee11c8..03b62f900d20 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -1205,6 +1205,17 @@ static inline struct device_node *nand_get_flash_node(struct nand_chip *chip)
>  /* Default/reset data interface */
>  const struct nand_interface_config *nand_get_reset_interface(void);
>  
> +/**
> + * nand_get_interface_config - Retrieve the current interface configuration
> + *                             of a NAND chip
> + * @chip: The NAND chip
> + */
> +static inline const struct nand_interface_config *
> +nand_get_interface_config(struct nand_chip *chip)
> +{
> +	return &chip->interface_config;
> +}
> +
>  /*
>   * 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] 44+ messages in thread

* Re: [PATCH v6 24/30] mtd: rawnand: Add the ->choose_interface() hook
  2020-05-28 23:16 ` [PATCH v6 24/30] mtd: rawnand: Add the ->choose_interface() hook Miquel Raynal
@ 2020-05-29  7:42   ` Boris Brezillon
  0 siblings, 0 replies; 44+ messages in thread
From: Boris Brezillon @ 2020-05-29  7:42 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Michal Simek, Vignesh Raghavendra,
	Tudor Ambarus, Richard Weinberger, linux-mtd, Thomas Petazzoni,
	Naga Sureshkumar Relli

On Fri, 29 May 2020 01:16:06 +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
> interface 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 28e249beb335..132feee3ba13 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -1047,7 +1047,6 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
>  		}
>  	}
>  
> -
>  	for (mode = best_mode; mode >= 0; mode--) {
>  		onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, mode);
>  
> @@ -1065,7 +1064,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.
>   *
> @@ -1076,6 +1077,10 @@ static int nand_choose_interface(struct nand_chip *chip)
>  	if (!nand_controller_can_setup_interface(chip))
>  		return 0;
>  
> +	if (chip->ops.choose_interface)
> +		return chip->ops.choose_interface(chip,
> +						  &chip->interface_config);
> +
>  	return nand_choose_best_sdr_timings(chip, &chip->interface_config,
>  					    NULL);
>  }
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index 03b62f900d20..ce4a525517a6 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -1033,6 +1033,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);
> @@ -1040,6 +1041,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_interface)(struct nand_chip *chip,

s/choose_interface/choose_interface_config/

> +				struct nand_interface_config *iface);
>  };
>  
>  /**


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

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

* Re: [PATCH v6 17/30] mtd: rawnand: s/data_interface/interface_config/
  2020-05-28 23:15 ` [PATCH v6 17/30] mtd: rawnand: s/data_interface/interface_config/ Miquel Raynal
@ 2020-05-29  7:44   ` Boris Brezillon
  2020-05-29  7:47   ` Boris Brezillon
  1 sibling, 0 replies; 44+ messages in thread
From: Boris Brezillon @ 2020-05-29  7:44 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Michal Simek, Vignesh Raghavendra,
	Tudor Ambarus, Richard Weinberger, linux-mtd, Thomas Petazzoni,
	Naga Sureshkumar Relli

On Fri, 29 May 2020 01:15:59 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

>   */
> -static int nand_choose_data_interface(struct nand_chip *chip)
> +static int nand_choose_interface(struct nand_chip *chip)

nand_choose_interface_config().

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

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

* Re: [PATCH v6 17/30] mtd: rawnand: s/data_interface/interface_config/
  2020-05-28 23:15 ` [PATCH v6 17/30] mtd: rawnand: s/data_interface/interface_config/ Miquel Raynal
  2020-05-29  7:44   ` Boris Brezillon
@ 2020-05-29  7:47   ` Boris Brezillon
  2020-05-29  8:11     ` Boris Brezillon
  1 sibling, 1 reply; 44+ messages in thread
From: Boris Brezillon @ 2020-05-29  7:47 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Michal Simek, Vignesh Raghavendra,
	Tudor Ambarus, Richard Weinberger, linux-mtd, Thomas Petazzoni,
	Naga Sureshkumar Relli

On Fri, 29 May 2020 01:15:59 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> From: Boris Brezillon <boris.brezillon@collabora.com>
> 
> 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>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

I know it's painful to move that one, but I think it should be at the
beginning of the series so the functions/fields you introduce have the
right name from the start.

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

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

* Re: [PATCH v6 17/30] mtd: rawnand: s/data_interface/interface_config/
  2020-05-29  7:47   ` Boris Brezillon
@ 2020-05-29  8:11     ` Boris Brezillon
  2020-05-29  8:19       ` Miquel Raynal
  0 siblings, 1 reply; 44+ messages in thread
From: Boris Brezillon @ 2020-05-29  8:11 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Michal Simek, Vignesh Raghavendra,
	Tudor Ambarus, Richard Weinberger, linux-mtd, Thomas Petazzoni,
	Naga Sureshkumar Relli

On Fri, 29 May 2020 09:47:55 +0200
Boris Brezillon <boris.brezillon@collabora.com> wrote:

> On Fri, 29 May 2020 01:15:59 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > From: Boris Brezillon <boris.brezillon@collabora.com>
> > 
> > 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>
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>  
> 
> I know it's painful to move that one, but I think it should be at the
> beginning of the series so the functions/fields you introduce have the
> right name from the start.

Hm, maybe I'm wrong and you don't introduce any new interface-related
functions/fields before that one.

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

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

* Re: [PATCH v6 17/30] mtd: rawnand: s/data_interface/interface_config/
  2020-05-29  8:11     ` Boris Brezillon
@ 2020-05-29  8:19       ` Miquel Raynal
  0 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-29  8:19 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Michal Simek, Vignesh Raghavendra,
	Tudor Ambarus, Richard Weinberger, linux-mtd, Thomas Petazzoni,
	Naga Sureshkumar Relli

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Fri, 29 May
2020 10:11:07 +0200:

> On Fri, 29 May 2020 09:47:55 +0200
> Boris Brezillon <boris.brezillon@collabora.com> wrote:
> 
> > On Fri, 29 May 2020 01:15:59 +0200
> > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >   
> > > From: Boris Brezillon <boris.brezillon@collabora.com>
> > > 
> > > 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>
> > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>    
> > 
> > I know it's painful to move that one, but I think it should be at the
> > beginning of the series so the functions/fields you introduce have the
> > right name from the start.  
> 
> Hm, maybe I'm wrong and you don't introduce any new interface-related
> functions/fields before that one.


Indeed, I don't introduce new hooks before this patch. What I do is
renaming a few fields, but honestly, before of after, the
s/data_interface/interface_config/ applies anyway.

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

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

* Re: [PATCH v6 30/30] mtd: rawnand: Allocate the best interface configuration dynamically
  2020-05-28 23:16 ` [PATCH v6 30/30] mtd: rawnand: Allocate the best interface configuration dynamically Miquel Raynal
@ 2020-05-29  8:54   ` Boris Brezillon
  2020-05-29  9:16     ` Miquel Raynal
  0 siblings, 1 reply; 44+ messages in thread
From: Boris Brezillon @ 2020-05-29  8:54 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Rickard Andersson, Michal Simek, Vignesh Raghavendra,
	Tudor Ambarus, Richard Weinberger, linux-mtd, Thomas Petazzoni,
	Naga Sureshkumar Relli

On Fri, 29 May 2020 01:16:12 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

>  
> @@ -947,7 +949,8 @@ static int nand_reset_interface(struct nand_chip *chip, int chipnr)
>   */
>  static int nand_setup_interface(struct nand_chip *chip, int chipnr)
>  {
> -	u8 mode = chip->interface_config.timings.mode;
> +	const struct nand_controller_ops *ops = chip->controller->ops;
> +	u8 mode = chip->best_interface_config->timings.mode;

I didn't check, but I assume it's safe to dereference
->best_interface_config here (IOW, ->best_interface_config is
guaranteed to be != NULL).

>  	u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { mode, };
>  	int ret;
>  

>  
>  /**
> @@ -2523,8 +2542,8 @@ int nand_reset(struct nand_chip *chip, int chipnr)
>  	 * nand_setup_interface() uses ->set/get_features() which would
>  	 * fail anyway as the parameter page is not available yet.
>  	 */
> -	if (!memcmp(&chip->interface_config, nand_get_reset_interface(),
> -		    sizeof(chip->interface_config)))
> +	if (!chip->best_interface_config ||
> +	    chip->best_interface_config == nand_get_reset_interface())

I think 'chip->best_interface_config == nand_get_reset_interface()' is
never true.

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

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

* Re: [PATCH v6 30/30] mtd: rawnand: Allocate the best interface configuration dynamically
  2020-05-29  8:54   ` Boris Brezillon
@ 2020-05-29  9:16     ` Miquel Raynal
  0 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-29  9:16 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Michal Simek, Vignesh Raghavendra,
	Tudor Ambarus, Richard Weinberger, linux-mtd, Thomas Petazzoni,
	Naga Sureshkumar Relli


Boris Brezillon <boris.brezillon@collabora.com> wrote on Fri, 29 May
2020 10:54:31 +0200:

> On Fri, 29 May 2020 01:16:12 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> >  
> > @@ -947,7 +949,8 @@ static int nand_reset_interface(struct nand_chip *chip, int chipnr)
> >   */
> >  static int nand_setup_interface(struct nand_chip *chip, int chipnr)
> >  {
> > -	u8 mode = chip->interface_config.timings.mode;
> > +	const struct nand_controller_ops *ops = chip->controller->ops;
> > +	u8 mode = chip->best_interface_config->timings.mode;  
> 
> I didn't check, but I assume it's safe to dereference
> ->best_interface_config here (IOW, ->best_interface_config is  
> guaranteed to be != NULL).

Yes it's safe. ->best_interface_config is always set, even with mode 0
configuration.

> 
> >  	u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { mode, };
> >  	int ret;
> >    
> 
> >  
> >  /**
> > @@ -2523,8 +2542,8 @@ int nand_reset(struct nand_chip *chip, int chipnr)
> >  	 * nand_setup_interface() uses ->set/get_features() which would
> >  	 * fail anyway as the parameter page is not available yet.
> >  	 */
> > -	if (!memcmp(&chip->interface_config, nand_get_reset_interface(),
> > -		    sizeof(chip->interface_config)))
> > +	if (!chip->best_interface_config ||
> > +	    chip->best_interface_config == nand_get_reset_interface())  
> 
> I think 'chip->best_interface_config == nand_get_reset_interface()' is
> never true.

Oh right. I'll drop this, and we'll accept to sometimes call
nand_setup_interface() to apply timings mode 0 while they are already
applied. I don't think it's a big deal.


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

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

* Re: [PATCH v6 19/30] mtd: rawnand: Define a unique reset interface configuration
  2020-05-29  7:32   ` Boris Brezillon
@ 2020-05-29  9:27     ` Miquel Raynal
  0 siblings, 0 replies; 44+ messages in thread
From: Miquel Raynal @ 2020-05-29  9:27 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Rickard Andersson, Michal Simek, Vignesh Raghavendra,
	Tudor Ambarus, Richard Weinberger, linux-mtd, Thomas Petazzoni,
	Naga Sureshkumar Relli


Boris Brezillon <boris.brezillon@collabora.com> wrote on Fri, 29 May
2020 09:32:05 +0200:

> On Fri, 29 May 2020 01:16:01 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > All NAND chips will always use the same interface configuration for
> > reset and at startup: SDR mode 0. Instead of copying around the
> > interface configuration, let's just define a helper to retrieve the
> > reset interface configuration object.
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/mtd/nand/raw/nand_base.c    | 10 +++-------
> >  drivers/mtd/nand/raw/nand_timings.c |  6 ++++++
> >  include/linux/mtd/rawnand.h         |  3 +++
> >  3 files changed, 12 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > index 07a7d918b462..4a72ec221262 100644
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> > @@ -928,9 +928,7 @@ static int nand_reset_interface(struct nand_chip *chip, int chipnr)
> >  	 * timings to timing mode 0.
> >  	 */
> >  
> > -	onfi_fill_interface_config(chip, &chip->interface_config,
> > -				   NAND_SDR_IFACE, 0);
> > -	ret = ops->setup_interface(chip, chipnr, &chip->interface_config);
> > +	ret = ops->setup_interface(chip, chipnr, nand_get_reset_interface());
> >  	if (ret)
> >  		pr_err("Failed to configure data interface to SDR timing mode 0\n");
> >  
> > @@ -2483,7 +2481,6 @@ EXPORT_SYMBOL_GPL(nand_subop_get_data_len);
> >   */
> >  int nand_reset(struct nand_chip *chip, int chipnr)
> >  {
> > -	struct nand_interface_config saved_intf_config = chip->interface_config;
> >  	int ret;
> >  
> >  	ret = nand_reset_interface(chip, chipnr);
> > @@ -2508,11 +2505,10 @@ int nand_reset(struct nand_chip *chip, int chipnr)
> >  	 * nand_setup_interface() uses ->set/get_features() which would
> >  	 * fail anyway as the parameter page is not available yet.
> >  	 */
> > -	if (!memcmp(&chip->interface_config, &saved_intf_config,
> > -		    sizeof(saved_intf_config)))
> > +	if (!memcmp(&chip->interface_config, nand_get_reset_interface(),
> > +		    sizeof(chip->interface_config)))
> >  		return 0;
> >  
> > -	chip->interface_config = saved_intf_config;  
> 
> Are you sure you can do that now? Looks like the current interface
> config is not preserved, and you end up with mode 0 after a reset.

You're probably right, I'll move that to the patch handling
interface_config pointers.

> 
> >  	ret = nand_setup_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 6c12cd52323d..0089196b9e36 100644
> > --- a/drivers/mtd/nand/raw/nand_timings.c
> > +++ b/drivers/mtd/nand/raw/nand_timings.c
> > @@ -292,6 +292,12 @@ static const struct nand_interface_config onfi_sdr_timings[] = {
> >  	},
> >  };
> >  
> > +/* All NAND chips share the same reset data interface: SDR mode 0 */
> > +const struct nand_interface_config *nand_get_reset_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 c2fcac38bcc2..b37eb5ee11c8 100644
> > --- a/include/linux/mtd/rawnand.h
> > +++ b/include/linux/mtd/rawnand.h
> > @@ -1202,6 +1202,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 */
> > +const struct nand_interface_config *nand_get_reset_interface(void);
> > +
> >  /*
> >   * 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] 44+ messages in thread

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

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.